mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-07-07 17:04:59 +00:00
Encapsulate CreateFunction (#1573)
This commit is contained in:
parent
bd750dfada
commit
e16b24679a
6 changed files with 149 additions and 148 deletions
129
src/ast/ddl.rs
129
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(())
|
||||
}
|
||||
}
|
||||
|
|
133
src/ast/mod.rs
133
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,
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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 = [
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue