You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datafusion.apache.org by al...@apache.org on 2024/12/02 17:45:19 UTC
(datafusion-sqlparser-rs) branch main updated: Encapsulate CreateFunction (#1573)
This is an automated email from the ASF dual-hosted git repository.
alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git
The following commit(s) were added to refs/heads/main by this push:
new e16b2467 Encapsulate CreateFunction (#1573)
e16b2467 is described below
commit e16b24679a1e87dd54ce9565e87e818dce4d4a0a
Author: Philip Cristiano <ph...@users.noreply.github.com>
AuthorDate: Mon Dec 2 12:45:14 2024 -0500
Encapsulate CreateFunction (#1573)
---
src/ast/ddl.rs | 129 +++++++++++++++++++++++++++++++++++++++++-
src/ast/mod.rs | 133 ++------------------------------------------
src/parser/mod.rs | 12 ++--
tests/sqlparser_bigquery.rs | 4 +-
tests/sqlparser_hive.rs | 11 ++--
tests/sqlparser_postgres.rs | 8 +--
6 files changed, 149 insertions(+), 148 deletions(-)
diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs
index 3ced478c..9a7d297b 100644
--- a/src/ast/ddl.rs
+++ b/src/ast/ddl.rs
@@ -30,8 +30,10 @@ use sqlparser_derive::{Visit, VisitMut};
use crate::ast::value::escape_single_quote_string;
use crate::ast::{
- display_comma_separated, display_separated, DataType, Expr, Ident, MySQLColumnPosition,
- ObjectName, OrderByExpr, ProjectionSelect, SequenceOptions, SqlOption, Tag, Value,
+ display_comma_separated, display_separated, CreateFunctionBody, CreateFunctionUsing, DataType,
+ Expr, FunctionBehavior, FunctionCalledOnNull, FunctionDeterminismSpecifier, FunctionParallel,
+ Ident, MySQLColumnPosition, ObjectName, OperateFunctionArg, OrderByExpr, ProjectionSelect,
+ SequenceOptions, SqlOption, Tag, Value,
};
use crate::keywords::Keyword;
use crate::tokenizer::Token;
@@ -1819,3 +1821,126 @@ impl fmt::Display for ClusteredBy {
write!(f, " INTO {} BUCKETS", self.num_buckets)
}
}
+
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CreateFunction {
+ pub or_replace: bool,
+ pub temporary: bool,
+ pub if_not_exists: bool,
+ pub name: ObjectName,
+ pub args: Option<Vec<OperateFunctionArg>>,
+ pub return_type: Option<DataType>,
+ /// The expression that defines the function.
+ ///
+ /// Examples:
+ /// ```sql
+ /// AS ((SELECT 1))
+ /// AS "console.log();"
+ /// ```
+ pub function_body: Option<CreateFunctionBody>,
+ /// Behavior attribute for the function
+ ///
+ /// IMMUTABLE | STABLE | VOLATILE
+ ///
+ /// [Postgres](https://www.postgresql.org/docs/current/sql-createfunction.html)
+ pub behavior: Option<FunctionBehavior>,
+ /// CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
+ ///
+ /// [Postgres](https://www.postgresql.org/docs/current/sql-createfunction.html)
+ pub called_on_null: Option<FunctionCalledOnNull>,
+ /// PARALLEL { UNSAFE | RESTRICTED | SAFE }
+ ///
+ /// [Postgres](https://www.postgresql.org/docs/current/sql-createfunction.html)
+ pub parallel: Option<FunctionParallel>,
+ /// USING ... (Hive only)
+ pub using: Option<CreateFunctionUsing>,
+ /// Language used in a UDF definition.
+ ///
+ /// Example:
+ /// ```sql
+ /// CREATE FUNCTION foo() LANGUAGE js AS "console.log();"
+ /// ```
+ /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_a_javascript_udf)
+ pub language: Option<Ident>,
+ /// Determinism keyword used for non-sql UDF definitions.
+ ///
+ /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11)
+ pub determinism_specifier: Option<FunctionDeterminismSpecifier>,
+ /// List of options for creating the function.
+ ///
+ /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11)
+ pub options: Option<Vec<SqlOption>>,
+ /// Connection resource for a remote function.
+ ///
+ /// Example:
+ /// ```sql
+ /// CREATE FUNCTION foo()
+ /// RETURNS FLOAT64
+ /// REMOTE WITH CONNECTION us.myconnection
+ /// ```
+ /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_a_remote_function)
+ pub remote_connection: Option<ObjectName>,
+}
+
+impl fmt::Display for CreateFunction {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(
+ f,
+ "CREATE {or_replace}{temp}FUNCTION {if_not_exists}{name}",
+ name = self.name,
+ temp = if self.temporary { "TEMPORARY " } else { "" },
+ or_replace = if self.or_replace { "OR REPLACE " } else { "" },
+ if_not_exists = if self.if_not_exists {
+ "IF NOT EXISTS "
+ } else {
+ ""
+ },
+ )?;
+ if let Some(args) = &self.args {
+ write!(f, "({})", display_comma_separated(args))?;
+ }
+ if let Some(return_type) = &self.return_type {
+ write!(f, " RETURNS {return_type}")?;
+ }
+ if let Some(determinism_specifier) = &self.determinism_specifier {
+ write!(f, " {determinism_specifier}")?;
+ }
+ if let Some(language) = &self.language {
+ write!(f, " LANGUAGE {language}")?;
+ }
+ if let Some(behavior) = &self.behavior {
+ write!(f, " {behavior}")?;
+ }
+ if let Some(called_on_null) = &self.called_on_null {
+ write!(f, " {called_on_null}")?;
+ }
+ if let Some(parallel) = &self.parallel {
+ write!(f, " {parallel}")?;
+ }
+ if let Some(remote_connection) = &self.remote_connection {
+ write!(f, " REMOTE WITH CONNECTION {remote_connection}")?;
+ }
+ if let Some(CreateFunctionBody::AsBeforeOptions(function_body)) = &self.function_body {
+ write!(f, " AS {function_body}")?;
+ }
+ if let Some(CreateFunctionBody::Return(function_body)) = &self.function_body {
+ write!(f, " RETURN {function_body}")?;
+ }
+ if let Some(using) = &self.using {
+ write!(f, " {using}")?;
+ }
+ if let Some(options) = &self.options {
+ write!(
+ f,
+ " OPTIONS({})",
+ display_comma_separated(options.as_slice())
+ )?;
+ }
+ if let Some(CreateFunctionBody::AsAfterOptions(function_body)) = &self.function_body {
+ write!(f, " AS {function_body}")?;
+ }
+ Ok(())
+ }
+}
diff --git a/src/ast/mod.rs b/src/ast/mod.rs
index d928370a..ef4ccff4 100644
--- a/src/ast/mod.rs
+++ b/src/ast/mod.rs
@@ -47,7 +47,7 @@ pub use self::dcl::{AlterRoleOperation, ResetConfig, RoleOption, SetConfigValue,
pub use self::ddl::{
AlterColumnOperation, AlterIndexOperation, AlterPolicyOperation, AlterTableOperation,
ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnPolicy, ColumnPolicyProperty,
- ConstraintCharacteristics, Deduplicate, DeferrableInitial, GeneratedAs,
+ ConstraintCharacteristics, CreateFunction, Deduplicate, DeferrableInitial, GeneratedAs,
GeneratedExpressionMode, IdentityParameters, IdentityProperty, IdentityPropertyFormatKind,
IdentityPropertyKind, IdentityPropertyOrder, IndexOption, IndexType, KeyOrIndexDisplay, Owner,
Partition, ProcedureParam, ReferentialAction, TableConstraint, TagsColumnOption,
@@ -897,7 +897,7 @@ pub enum Expr {
/// Example:
///
/// ```sql
- /// SELECT (SELECT ',' + name FROM sys.objects FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)')
+ /// SELECT (SELECT ',' + name FROM sys.objects FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)')
/// SELECT CONVERT(XML,'<Book>abc</Book>').value('.','NVARCHAR(MAX)').value('.','NVARCHAR(MAX)')
/// ```
///
@@ -3003,64 +3003,7 @@ pub enum Statement {
/// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
/// 2. [Postgres](https://www.postgresql.org/docs/15/sql-createfunction.html)
/// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
- CreateFunction {
- or_replace: bool,
- temporary: bool,
- if_not_exists: bool,
- name: ObjectName,
- args: Option<Vec<OperateFunctionArg>>,
- return_type: Option<DataType>,
- /// The expression that defines the function.
- ///
- /// Examples:
- /// ```sql
- /// AS ((SELECT 1))
- /// AS "console.log();"
- /// ```
- function_body: Option<CreateFunctionBody>,
- /// Behavior attribute for the function
- ///
- /// IMMUTABLE | STABLE | VOLATILE
- ///
- /// [Postgres](https://www.postgresql.org/docs/current/sql-createfunction.html)
- behavior: Option<FunctionBehavior>,
- /// CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
- ///
- /// [Postgres](https://www.postgresql.org/docs/current/sql-createfunction.html)
- called_on_null: Option<FunctionCalledOnNull>,
- /// PARALLEL { UNSAFE | RESTRICTED | SAFE }
- ///
- /// [Postgres](https://www.postgresql.org/docs/current/sql-createfunction.html)
- parallel: Option<FunctionParallel>,
- /// USING ... (Hive only)
- using: Option<CreateFunctionUsing>,
- /// Language used in a UDF definition.
- ///
- /// Example:
- /// ```sql
- /// CREATE FUNCTION foo() LANGUAGE js AS "console.log();"
- /// ```
- /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_a_javascript_udf)
- language: Option<Ident>,
- /// Determinism keyword used for non-sql UDF definitions.
- ///
- /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11)
- determinism_specifier: Option<FunctionDeterminismSpecifier>,
- /// List of options for creating the function.
- ///
- /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11)
- options: Option<Vec<SqlOption>>,
- /// Connection resource for a remote function.
- ///
- /// Example:
- /// ```sql
- /// CREATE FUNCTION foo()
- /// RETURNS FLOAT64
- /// REMOTE WITH CONNECTION us.myconnection
- /// ```
- /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_a_remote_function)
- remote_connection: Option<ObjectName>,
- },
+ CreateFunction(CreateFunction),
/// CREATE TRIGGER
///
/// Examples:
@@ -3826,75 +3769,7 @@ impl fmt::Display for Statement {
}
Ok(())
}
- Statement::CreateFunction {
- or_replace,
- temporary,
- if_not_exists,
- name,
- args,
- return_type,
- function_body,
- language,
- behavior,
- called_on_null,
- parallel,
- using,
- determinism_specifier,
- options,
- remote_connection,
- } => {
- write!(
- f,
- "CREATE {or_replace}{temp}FUNCTION {if_not_exists}{name}",
- temp = if *temporary { "TEMPORARY " } else { "" },
- or_replace = if *or_replace { "OR REPLACE " } else { "" },
- if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
- )?;
- if let Some(args) = args {
- write!(f, "({})", display_comma_separated(args))?;
- }
- if let Some(return_type) = return_type {
- write!(f, " RETURNS {return_type}")?;
- }
- if let Some(determinism_specifier) = determinism_specifier {
- write!(f, " {determinism_specifier}")?;
- }
- if let Some(language) = language {
- write!(f, " LANGUAGE {language}")?;
- }
- if let Some(behavior) = behavior {
- write!(f, " {behavior}")?;
- }
- if let Some(called_on_null) = called_on_null {
- write!(f, " {called_on_null}")?;
- }
- if let Some(parallel) = parallel {
- write!(f, " {parallel}")?;
- }
- if let Some(remote_connection) = remote_connection {
- write!(f, " REMOTE WITH CONNECTION {remote_connection}")?;
- }
- if let Some(CreateFunctionBody::AsBeforeOptions(function_body)) = function_body {
- write!(f, " AS {function_body}")?;
- }
- if let Some(CreateFunctionBody::Return(function_body)) = function_body {
- write!(f, " RETURN {function_body}")?;
- }
- if let Some(using) = using {
- write!(f, " {using}")?;
- }
- if let Some(options) = options {
- write!(
- f,
- " OPTIONS({})",
- display_comma_separated(options.as_slice())
- )?;
- }
- if let Some(CreateFunctionBody::AsAfterOptions(function_body)) = function_body {
- write!(f, " AS {function_body}")?;
- }
- Ok(())
- }
+ Statement::CreateFunction(create_function) => create_function.fmt(f),
Statement::CreateTrigger {
or_replace,
is_constraint,
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 831098ba..90665e9f 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -4240,7 +4240,7 @@ impl<'a> Parser<'a> {
}
}
- Ok(Statement::CreateFunction {
+ Ok(Statement::CreateFunction(CreateFunction {
or_replace,
temporary,
name,
@@ -4256,7 +4256,7 @@ impl<'a> Parser<'a> {
determinism_specifier: None,
options: None,
remote_connection: None,
- })
+ }))
}
/// Parse `CREATE FUNCTION` for [Hive]
@@ -4273,7 +4273,7 @@ impl<'a> Parser<'a> {
let as_ = self.parse_create_function_body_string()?;
let using = self.parse_optional_create_function_using()?;
- Ok(Statement::CreateFunction {
+ Ok(Statement::CreateFunction(CreateFunction {
or_replace,
temporary,
name,
@@ -4289,7 +4289,7 @@ impl<'a> Parser<'a> {
determinism_specifier: None,
options: None,
remote_connection: None,
- })
+ }))
}
/// Parse `CREATE FUNCTION` for [BigQuery]
@@ -4362,7 +4362,7 @@ impl<'a> Parser<'a> {
None
};
- Ok(Statement::CreateFunction {
+ Ok(Statement::CreateFunction(CreateFunction {
or_replace,
temporary,
if_not_exists,
@@ -4378,7 +4378,7 @@ impl<'a> Parser<'a> {
behavior: None,
called_on_null: None,
parallel: None,
- })
+ }))
}
fn parse_function_arg(&mut self) -> Result<OperateFunctionArg, ParserError> {
diff --git a/tests/sqlparser_bigquery.rs b/tests/sqlparser_bigquery.rs
index 00d12ed8..2be128a8 100644
--- a/tests/sqlparser_bigquery.rs
+++ b/tests/sqlparser_bigquery.rs
@@ -2011,7 +2011,7 @@ fn test_bigquery_create_function() {
let stmt = bigquery().verified_stmt(sql);
assert_eq!(
stmt,
- Statement::CreateFunction {
+ Statement::CreateFunction(CreateFunction {
or_replace: true,
temporary: true,
if_not_exists: false,
@@ -2036,7 +2036,7 @@ fn test_bigquery_create_function() {
remote_connection: None,
called_on_null: None,
parallel: None,
- }
+ })
);
let sqls = [
diff --git a/tests/sqlparser_hive.rs b/tests/sqlparser_hive.rs
index 8d4f7a68..546b289a 100644
--- a/tests/sqlparser_hive.rs
+++ b/tests/sqlparser_hive.rs
@@ -21,9 +21,10 @@
//! is also tested (on the inputs it can handle).
use sqlparser::ast::{
- ClusteredBy, CommentDef, CreateFunctionBody, CreateFunctionUsing, CreateTable, Expr, Function,
- FunctionArgumentList, FunctionArguments, Ident, ObjectName, OneOrManyWithParens, OrderByExpr,
- SelectItem, Statement, TableFactor, UnaryOperator, Use, Value,
+ ClusteredBy, CommentDef, CreateFunction, CreateFunctionBody, CreateFunctionUsing, CreateTable,
+ Expr, Function, FunctionArgumentList, FunctionArguments, Ident, ObjectName,
+ OneOrManyWithParens, OrderByExpr, SelectItem, Statement, TableFactor, UnaryOperator, Use,
+ Value,
};
use sqlparser::dialect::{GenericDialect, HiveDialect, MsSqlDialect};
use sqlparser::parser::ParserError;
@@ -392,13 +393,13 @@ fn set_statement_with_minus() {
fn parse_create_function() {
let sql = "CREATE TEMPORARY FUNCTION mydb.myfunc AS 'org.random.class.Name' USING JAR 'hdfs://somewhere.com:8020/very/far'";
match hive().verified_stmt(sql) {
- Statement::CreateFunction {
+ Statement::CreateFunction(CreateFunction {
temporary,
name,
function_body,
using,
..
- } => {
+ }) => {
assert!(temporary);
assert_eq!(name.to_string(), "mydb.myfunc");
assert_eq!(
diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs
index f94e2f54..52fe6c40 100644
--- a/tests/sqlparser_postgres.rs
+++ b/tests/sqlparser_postgres.rs
@@ -3631,7 +3631,7 @@ fn parse_create_function() {
let sql = "CREATE FUNCTION add(INTEGER, INTEGER) RETURNS INTEGER LANGUAGE SQL IMMUTABLE STRICT PARALLEL SAFE AS 'select $1 + $2;'";
assert_eq!(
pg_and_generic().verified_stmt(sql),
- Statement::CreateFunction {
+ Statement::CreateFunction(CreateFunction {
or_replace: false,
temporary: false,
name: ObjectName(vec![Ident::new("add")]),
@@ -3652,7 +3652,7 @@ fn parse_create_function() {
determinism_specifier: None,
options: None,
remote_connection: None,
- }
+ })
);
}
@@ -4987,7 +4987,7 @@ fn parse_trigger_related_functions() {
assert_eq!(
create_function,
- Statement::CreateFunction {
+ Statement::CreateFunction(CreateFunction {
or_replace: false,
temporary: false,
if_not_exists: false,
@@ -5017,7 +5017,7 @@ fn parse_trigger_related_functions() {
options: None,
remote_connection: None
}
- );
+ ));
// Check the third statement
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org