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