Skip to content

Commit e16b246

Browse files
Encapsulate CreateFunction (#1573)
1 parent bd750df commit e16b246

File tree

6 files changed

+149
-148
lines changed

6 files changed

+149
-148
lines changed

src/ast/ddl.rs

+127-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ use sqlparser_derive::{Visit, VisitMut};
3030

3131
use crate::ast::value::escape_single_quote_string;
3232
use crate::ast::{
33-
display_comma_separated, display_separated, DataType, Expr, Ident, MySQLColumnPosition,
34-
ObjectName, OrderByExpr, ProjectionSelect, SequenceOptions, SqlOption, Tag, Value,
33+
display_comma_separated, display_separated, CreateFunctionBody, CreateFunctionUsing, DataType,
34+
Expr, FunctionBehavior, FunctionCalledOnNull, FunctionDeterminismSpecifier, FunctionParallel,
35+
Ident, MySQLColumnPosition, ObjectName, OperateFunctionArg, OrderByExpr, ProjectionSelect,
36+
SequenceOptions, SqlOption, Tag, Value,
3537
};
3638
use crate::keywords::Keyword;
3739
use crate::tokenizer::Token;
@@ -1819,3 +1821,126 @@ impl fmt::Display for ClusteredBy {
18191821
write!(f, " INTO {} BUCKETS", self.num_buckets)
18201822
}
18211823
}
1824+
1825+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1826+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1827+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1828+
pub struct CreateFunction {
1829+
pub or_replace: bool,
1830+
pub temporary: bool,
1831+
pub if_not_exists: bool,
1832+
pub name: ObjectName,
1833+
pub args: Option<Vec<OperateFunctionArg>>,
1834+
pub return_type: Option<DataType>,
1835+
/// The expression that defines the function.
1836+
///
1837+
/// Examples:
1838+
/// ```sql
1839+
/// AS ((SELECT 1))
1840+
/// AS "console.log();"
1841+
/// ```
1842+
pub function_body: Option<CreateFunctionBody>,
1843+
/// Behavior attribute for the function
1844+
///
1845+
/// IMMUTABLE | STABLE | VOLATILE
1846+
///
1847+
/// [Postgres](https://www.postgresql.org/docs/current/sql-createfunction.html)
1848+
pub behavior: Option<FunctionBehavior>,
1849+
/// CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
1850+
///
1851+
/// [Postgres](https://www.postgresql.org/docs/current/sql-createfunction.html)
1852+
pub called_on_null: Option<FunctionCalledOnNull>,
1853+
/// PARALLEL { UNSAFE | RESTRICTED | SAFE }
1854+
///
1855+
/// [Postgres](https://www.postgresql.org/docs/current/sql-createfunction.html)
1856+
pub parallel: Option<FunctionParallel>,
1857+
/// USING ... (Hive only)
1858+
pub using: Option<CreateFunctionUsing>,
1859+
/// Language used in a UDF definition.
1860+
///
1861+
/// Example:
1862+
/// ```sql
1863+
/// CREATE FUNCTION foo() LANGUAGE js AS "console.log();"
1864+
/// ```
1865+
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_a_javascript_udf)
1866+
pub language: Option<Ident>,
1867+
/// Determinism keyword used for non-sql UDF definitions.
1868+
///
1869+
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11)
1870+
pub determinism_specifier: Option<FunctionDeterminismSpecifier>,
1871+
/// List of options for creating the function.
1872+
///
1873+
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11)
1874+
pub options: Option<Vec<SqlOption>>,
1875+
/// Connection resource for a remote function.
1876+
///
1877+
/// Example:
1878+
/// ```sql
1879+
/// CREATE FUNCTION foo()
1880+
/// RETURNS FLOAT64
1881+
/// REMOTE WITH CONNECTION us.myconnection
1882+
/// ```
1883+
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_a_remote_function)
1884+
pub remote_connection: Option<ObjectName>,
1885+
}
1886+
1887+
impl fmt::Display for CreateFunction {
1888+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1889+
write!(
1890+
f,
1891+
"CREATE {or_replace}{temp}FUNCTION {if_not_exists}{name}",
1892+
name = self.name,
1893+
temp = if self.temporary { "TEMPORARY " } else { "" },
1894+
or_replace = if self.or_replace { "OR REPLACE " } else { "" },
1895+
if_not_exists = if self.if_not_exists {
1896+
"IF NOT EXISTS "
1897+
} else {
1898+
""
1899+
},
1900+
)?;
1901+
if let Some(args) = &self.args {
1902+
write!(f, "({})", display_comma_separated(args))?;
1903+
}
1904+
if let Some(return_type) = &self.return_type {
1905+
write!(f, " RETURNS {return_type}")?;
1906+
}
1907+
if let Some(determinism_specifier) = &self.determinism_specifier {
1908+
write!(f, " {determinism_specifier}")?;
1909+
}
1910+
if let Some(language) = &self.language {
1911+
write!(f, " LANGUAGE {language}")?;
1912+
}
1913+
if let Some(behavior) = &self.behavior {
1914+
write!(f, " {behavior}")?;
1915+
}
1916+
if let Some(called_on_null) = &self.called_on_null {
1917+
write!(f, " {called_on_null}")?;
1918+
}
1919+
if let Some(parallel) = &self.parallel {
1920+
write!(f, " {parallel}")?;
1921+
}
1922+
if let Some(remote_connection) = &self.remote_connection {
1923+
write!(f, " REMOTE WITH CONNECTION {remote_connection}")?;
1924+
}
1925+
if let Some(CreateFunctionBody::AsBeforeOptions(function_body)) = &self.function_body {
1926+
write!(f, " AS {function_body}")?;
1927+
}
1928+
if let Some(CreateFunctionBody::Return(function_body)) = &self.function_body {
1929+
write!(f, " RETURN {function_body}")?;
1930+
}
1931+
if let Some(using) = &self.using {
1932+
write!(f, " {using}")?;
1933+
}
1934+
if let Some(options) = &self.options {
1935+
write!(
1936+
f,
1937+
" OPTIONS({})",
1938+
display_comma_separated(options.as_slice())
1939+
)?;
1940+
}
1941+
if let Some(CreateFunctionBody::AsAfterOptions(function_body)) = &self.function_body {
1942+
write!(f, " AS {function_body}")?;
1943+
}
1944+
Ok(())
1945+
}
1946+
}

src/ast/mod.rs

+4-129
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub use self::dcl::{AlterRoleOperation, ResetConfig, RoleOption, SetConfigValue,
4747
pub use self::ddl::{
4848
AlterColumnOperation, AlterIndexOperation, AlterPolicyOperation, AlterTableOperation,
4949
ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnPolicy, ColumnPolicyProperty,
50-
ConstraintCharacteristics, Deduplicate, DeferrableInitial, GeneratedAs,
50+
ConstraintCharacteristics, CreateFunction, Deduplicate, DeferrableInitial, GeneratedAs,
5151
GeneratedExpressionMode, IdentityParameters, IdentityProperty, IdentityPropertyFormatKind,
5252
IdentityPropertyKind, IdentityPropertyOrder, IndexOption, IndexType, KeyOrIndexDisplay, Owner,
5353
Partition, ProcedureParam, ReferentialAction, TableConstraint, TagsColumnOption,
@@ -897,7 +897,7 @@ pub enum Expr {
897897
/// Example:
898898
///
899899
/// ```sql
900-
/// SELECT (SELECT ',' + name FROM sys.objects FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)')
900+
/// SELECT (SELECT ',' + name FROM sys.objects FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)')
901901
/// SELECT CONVERT(XML,'<Book>abc</Book>').value('.','NVARCHAR(MAX)').value('.','NVARCHAR(MAX)')
902902
/// ```
903903
///
@@ -3003,64 +3003,7 @@ pub enum Statement {
30033003
/// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
30043004
/// 2. [Postgres](https://www.postgresql.org/docs/15/sql-createfunction.html)
30053005
/// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
3006-
CreateFunction {
3007-
or_replace: bool,
3008-
temporary: bool,
3009-
if_not_exists: bool,
3010-
name: ObjectName,
3011-
args: Option<Vec<OperateFunctionArg>>,
3012-
return_type: Option<DataType>,
3013-
/// The expression that defines the function.
3014-
///
3015-
/// Examples:
3016-
/// ```sql
3017-
/// AS ((SELECT 1))
3018-
/// AS "console.log();"
3019-
/// ```
3020-
function_body: Option<CreateFunctionBody>,
3021-
/// Behavior attribute for the function
3022-
///
3023-
/// IMMUTABLE | STABLE | VOLATILE
3024-
///
3025-
/// [Postgres](https://www.postgresql.org/docs/current/sql-createfunction.html)
3026-
behavior: Option<FunctionBehavior>,
3027-
/// CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
3028-
///
3029-
/// [Postgres](https://www.postgresql.org/docs/current/sql-createfunction.html)
3030-
called_on_null: Option<FunctionCalledOnNull>,
3031-
/// PARALLEL { UNSAFE | RESTRICTED | SAFE }
3032-
///
3033-
/// [Postgres](https://www.postgresql.org/docs/current/sql-createfunction.html)
3034-
parallel: Option<FunctionParallel>,
3035-
/// USING ... (Hive only)
3036-
using: Option<CreateFunctionUsing>,
3037-
/// Language used in a UDF definition.
3038-
///
3039-
/// Example:
3040-
/// ```sql
3041-
/// CREATE FUNCTION foo() LANGUAGE js AS "console.log();"
3042-
/// ```
3043-
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_a_javascript_udf)
3044-
language: Option<Ident>,
3045-
/// Determinism keyword used for non-sql UDF definitions.
3046-
///
3047-
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11)
3048-
determinism_specifier: Option<FunctionDeterminismSpecifier>,
3049-
/// List of options for creating the function.
3050-
///
3051-
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11)
3052-
options: Option<Vec<SqlOption>>,
3053-
/// Connection resource for a remote function.
3054-
///
3055-
/// Example:
3056-
/// ```sql
3057-
/// CREATE FUNCTION foo()
3058-
/// RETURNS FLOAT64
3059-
/// REMOTE WITH CONNECTION us.myconnection
3060-
/// ```
3061-
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_a_remote_function)
3062-
remote_connection: Option<ObjectName>,
3063-
},
3006+
CreateFunction(CreateFunction),
30643007
/// CREATE TRIGGER
30653008
///
30663009
/// Examples:
@@ -3826,75 +3769,7 @@ impl fmt::Display for Statement {
38263769
}
38273770
Ok(())
38283771
}
3829-
Statement::CreateFunction {
3830-
or_replace,
3831-
temporary,
3832-
if_not_exists,
3833-
name,
3834-
args,
3835-
return_type,
3836-
function_body,
3837-
language,
3838-
behavior,
3839-
called_on_null,
3840-
parallel,
3841-
using,
3842-
determinism_specifier,
3843-
options,
3844-
remote_connection,
3845-
} => {
3846-
write!(
3847-
f,
3848-
"CREATE {or_replace}{temp}FUNCTION {if_not_exists}{name}",
3849-
temp = if *temporary { "TEMPORARY " } else { "" },
3850-
or_replace = if *or_replace { "OR REPLACE " } else { "" },
3851-
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
3852-
)?;
3853-
if let Some(args) = args {
3854-
write!(f, "({})", display_comma_separated(args))?;
3855-
}
3856-
if let Some(return_type) = return_type {
3857-
write!(f, " RETURNS {return_type}")?;
3858-
}
3859-
if let Some(determinism_specifier) = determinism_specifier {
3860-
write!(f, " {determinism_specifier}")?;
3861-
}
3862-
if let Some(language) = language {
3863-
write!(f, " LANGUAGE {language}")?;
3864-
}
3865-
if let Some(behavior) = behavior {
3866-
write!(f, " {behavior}")?;
3867-
}
3868-
if let Some(called_on_null) = called_on_null {
3869-
write!(f, " {called_on_null}")?;
3870-
}
3871-
if let Some(parallel) = parallel {
3872-
write!(f, " {parallel}")?;
3873-
}
3874-
if let Some(remote_connection) = remote_connection {
3875-
write!(f, " REMOTE WITH CONNECTION {remote_connection}")?;
3876-
}
3877-
if let Some(CreateFunctionBody::AsBeforeOptions(function_body)) = function_body {
3878-
write!(f, " AS {function_body}")?;
3879-
}
3880-
if let Some(CreateFunctionBody::Return(function_body)) = function_body {
3881-
write!(f, " RETURN {function_body}")?;
3882-
}
3883-
if let Some(using) = using {
3884-
write!(f, " {using}")?;
3885-
}
3886-
if let Some(options) = options {
3887-
write!(
3888-
f,
3889-
" OPTIONS({})",
3890-
display_comma_separated(options.as_slice())
3891-
)?;
3892-
}
3893-
if let Some(CreateFunctionBody::AsAfterOptions(function_body)) = function_body {
3894-
write!(f, " AS {function_body}")?;
3895-
}
3896-
Ok(())
3897-
}
3772+
Statement::CreateFunction(create_function) => create_function.fmt(f),
38983773
Statement::CreateTrigger {
38993774
or_replace,
39003775
is_constraint,

src/parser/mod.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -4240,7 +4240,7 @@ impl<'a> Parser<'a> {
42404240
}
42414241
}
42424242

4243-
Ok(Statement::CreateFunction {
4243+
Ok(Statement::CreateFunction(CreateFunction {
42444244
or_replace,
42454245
temporary,
42464246
name,
@@ -4256,7 +4256,7 @@ impl<'a> Parser<'a> {
42564256
determinism_specifier: None,
42574257
options: None,
42584258
remote_connection: None,
4259-
})
4259+
}))
42604260
}
42614261

42624262
/// Parse `CREATE FUNCTION` for [Hive]
@@ -4273,7 +4273,7 @@ impl<'a> Parser<'a> {
42734273
let as_ = self.parse_create_function_body_string()?;
42744274
let using = self.parse_optional_create_function_using()?;
42754275

4276-
Ok(Statement::CreateFunction {
4276+
Ok(Statement::CreateFunction(CreateFunction {
42774277
or_replace,
42784278
temporary,
42794279
name,
@@ -4289,7 +4289,7 @@ impl<'a> Parser<'a> {
42894289
determinism_specifier: None,
42904290
options: None,
42914291
remote_connection: None,
4292-
})
4292+
}))
42934293
}
42944294

42954295
/// Parse `CREATE FUNCTION` for [BigQuery]
@@ -4362,7 +4362,7 @@ impl<'a> Parser<'a> {
43624362
None
43634363
};
43644364

4365-
Ok(Statement::CreateFunction {
4365+
Ok(Statement::CreateFunction(CreateFunction {
43664366
or_replace,
43674367
temporary,
43684368
if_not_exists,
@@ -4378,7 +4378,7 @@ impl<'a> Parser<'a> {
43784378
behavior: None,
43794379
called_on_null: None,
43804380
parallel: None,
4381-
})
4381+
}))
43824382
}
43834383

43844384
fn parse_function_arg(&mut self) -> Result<OperateFunctionArg, ParserError> {

tests/sqlparser_bigquery.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2011,7 +2011,7 @@ fn test_bigquery_create_function() {
20112011
let stmt = bigquery().verified_stmt(sql);
20122012
assert_eq!(
20132013
stmt,
2014-
Statement::CreateFunction {
2014+
Statement::CreateFunction(CreateFunction {
20152015
or_replace: true,
20162016
temporary: true,
20172017
if_not_exists: false,
@@ -2036,7 +2036,7 @@ fn test_bigquery_create_function() {
20362036
remote_connection: None,
20372037
called_on_null: None,
20382038
parallel: None,
2039-
}
2039+
})
20402040
);
20412041

20422042
let sqls = [

0 commit comments

Comments
 (0)