Skip to content

Commit 6fbaee4

Browse files
Encapsulate CreateFunction
Extract CreateFunction from Statement enum into it's own struct.
1 parent 92c6e7f commit 6fbaee4

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,
@@ -885,7 +885,7 @@ pub enum Expr {
885885
/// Example:
886886
///
887887
/// ```sql
888-
/// SELECT (SELECT ',' + name FROM sys.objects FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)')
888+
/// SELECT (SELECT ',' + name FROM sys.objects FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)')
889889
/// SELECT CONVERT(XML,'<Book>abc</Book>').value('.','NVARCHAR(MAX)').value('.','NVARCHAR(MAX)')
890890
/// ```
891891
///
@@ -2989,64 +2989,7 @@ pub enum Statement {
29892989
/// 1. [Hive](https://cwiki.apache.org/confluence/display/hive/languagemanual+ddl#LanguageManualDDL-Create/Drop/ReloadFunction)
29902990
/// 2. [Postgres](https://www.postgresql.org/docs/15/sql-createfunction.html)
29912991
/// 3. [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_function_statement)
2992-
CreateFunction {
2993-
or_replace: bool,
2994-
temporary: bool,
2995-
if_not_exists: bool,
2996-
name: ObjectName,
2997-
args: Option<Vec<OperateFunctionArg>>,
2998-
return_type: Option<DataType>,
2999-
/// The expression that defines the function.
3000-
///
3001-
/// Examples:
3002-
/// ```sql
3003-
/// AS ((SELECT 1))
3004-
/// AS "console.log();"
3005-
/// ```
3006-
function_body: Option<CreateFunctionBody>,
3007-
/// Behavior attribute for the function
3008-
///
3009-
/// IMMUTABLE | STABLE | VOLATILE
3010-
///
3011-
/// [Postgres](https://www.postgresql.org/docs/current/sql-createfunction.html)
3012-
behavior: Option<FunctionBehavior>,
3013-
/// CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
3014-
///
3015-
/// [Postgres](https://www.postgresql.org/docs/current/sql-createfunction.html)
3016-
called_on_null: Option<FunctionCalledOnNull>,
3017-
/// PARALLEL { UNSAFE | RESTRICTED | SAFE }
3018-
///
3019-
/// [Postgres](https://www.postgresql.org/docs/current/sql-createfunction.html)
3020-
parallel: Option<FunctionParallel>,
3021-
/// USING ... (Hive only)
3022-
using: Option<CreateFunctionUsing>,
3023-
/// Language used in a UDF definition.
3024-
///
3025-
/// Example:
3026-
/// ```sql
3027-
/// CREATE FUNCTION foo() LANGUAGE js AS "console.log();"
3028-
/// ```
3029-
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_a_javascript_udf)
3030-
language: Option<Ident>,
3031-
/// Determinism keyword used for non-sql UDF definitions.
3032-
///
3033-
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11)
3034-
determinism_specifier: Option<FunctionDeterminismSpecifier>,
3035-
/// List of options for creating the function.
3036-
///
3037-
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11)
3038-
options: Option<Vec<SqlOption>>,
3039-
/// Connection resource for a remote function.
3040-
///
3041-
/// Example:
3042-
/// ```sql
3043-
/// CREATE FUNCTION foo()
3044-
/// RETURNS FLOAT64
3045-
/// REMOTE WITH CONNECTION us.myconnection
3046-
/// ```
3047-
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_a_remote_function)
3048-
remote_connection: Option<ObjectName>,
3049-
},
2992+
CreateFunction(CreateFunction),
30502993
/// CREATE TRIGGER
30512994
///
30522995
/// Examples:
@@ -3812,75 +3755,7 @@ impl fmt::Display for Statement {
38123755
}
38133756
Ok(())
38143757
}
3815-
Statement::CreateFunction {
3816-
or_replace,
3817-
temporary,
3818-
if_not_exists,
3819-
name,
3820-
args,
3821-
return_type,
3822-
function_body,
3823-
language,
3824-
behavior,
3825-
called_on_null,
3826-
parallel,
3827-
using,
3828-
determinism_specifier,
3829-
options,
3830-
remote_connection,
3831-
} => {
3832-
write!(
3833-
f,
3834-
"CREATE {or_replace}{temp}FUNCTION {if_not_exists}{name}",
3835-
temp = if *temporary { "TEMPORARY " } else { "" },
3836-
or_replace = if *or_replace { "OR REPLACE " } else { "" },
3837-
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
3838-
)?;
3839-
if let Some(args) = args {
3840-
write!(f, "({})", display_comma_separated(args))?;
3841-
}
3842-
if let Some(return_type) = return_type {
3843-
write!(f, " RETURNS {return_type}")?;
3844-
}
3845-
if let Some(determinism_specifier) = determinism_specifier {
3846-
write!(f, " {determinism_specifier}")?;
3847-
}
3848-
if let Some(language) = language {
3849-
write!(f, " LANGUAGE {language}")?;
3850-
}
3851-
if let Some(behavior) = behavior {
3852-
write!(f, " {behavior}")?;
3853-
}
3854-
if let Some(called_on_null) = called_on_null {
3855-
write!(f, " {called_on_null}")?;
3856-
}
3857-
if let Some(parallel) = parallel {
3858-
write!(f, " {parallel}")?;
3859-
}
3860-
if let Some(remote_connection) = remote_connection {
3861-
write!(f, " REMOTE WITH CONNECTION {remote_connection}")?;
3862-
}
3863-
if let Some(CreateFunctionBody::AsBeforeOptions(function_body)) = function_body {
3864-
write!(f, " AS {function_body}")?;
3865-
}
3866-
if let Some(CreateFunctionBody::Return(function_body)) = function_body {
3867-
write!(f, " RETURN {function_body}")?;
3868-
}
3869-
if let Some(using) = using {
3870-
write!(f, " {using}")?;
3871-
}
3872-
if let Some(options) = options {
3873-
write!(
3874-
f,
3875-
" OPTIONS({})",
3876-
display_comma_separated(options.as_slice())
3877-
)?;
3878-
}
3879-
if let Some(CreateFunctionBody::AsAfterOptions(function_body)) = function_body {
3880-
write!(f, " AS {function_body}")?;
3881-
}
3882-
Ok(())
3883-
}
3758+
Statement::CreateFunction(create_function) => create_function.fmt(f),
38843759
Statement::CreateTrigger {
38853760
or_replace,
38863761
is_constraint,

src/parser/mod.rs

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

4242-
Ok(Statement::CreateFunction {
4242+
Ok(Statement::CreateFunction(CreateFunction {
42434243
or_replace,
42444244
temporary,
42454245
name,
@@ -4255,7 +4255,7 @@ impl<'a> Parser<'a> {
42554255
determinism_specifier: None,
42564256
options: None,
42574257
remote_connection: None,
4258-
})
4258+
}))
42594259
}
42604260

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

4275-
Ok(Statement::CreateFunction {
4275+
Ok(Statement::CreateFunction(CreateFunction {
42764276
or_replace,
42774277
temporary,
42784278
name,
@@ -4288,7 +4288,7 @@ impl<'a> Parser<'a> {
42884288
determinism_specifier: None,
42894289
options: None,
42904290
remote_connection: None,
4291-
})
4291+
}))
42924292
}
42934293

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

4364-
Ok(Statement::CreateFunction {
4364+
Ok(Statement::CreateFunction(CreateFunction {
43654365
or_replace,
43664366
temporary,
43674367
if_not_exists,
@@ -4377,7 +4377,7 @@ impl<'a> Parser<'a> {
43774377
behavior: None,
43784378
called_on_null: None,
43794379
parallel: None,
4380-
})
4380+
}))
43814381
}
43824382

43834383
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)