Skip to content

Commit f82bb83

Browse files
committed
refactor(ast): move SETOF from DataType into FunctionReturnType enum
SETOF is a PostgreSQL-specific modifier for function return types, not a standalone data type. Introduce FunctionReturnType enum with DataType and SetOf variants, replacing DataType::SetOf. Addresses review feedback on #2217.
1 parent 6f0f20a commit f82bb83

File tree

7 files changed

+65
-38
lines changed

7 files changed

+65
-38
lines changed

src/ast/data_type.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,6 @@ pub enum DataType {
6161
/// Table columns.
6262
columns: Vec<ColumnDef>,
6363
},
64-
/// SETOF type modifier for [PostgreSQL] function return types,
65-
/// e.g. `CREATE FUNCTION ... RETURNS SETOF text`.
66-
///
67-
/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
68-
SetOf(Box<DataType>),
6964
/// Fixed-length character type, e.g. CHARACTER(10).
7065
Character(Option<CharacterLength>),
7166
/// Fixed-length char type, e.g. CHAR(10).
@@ -813,7 +808,6 @@ impl fmt::Display for DataType {
813808
DataType::NamedTable { name, columns } => {
814809
write!(f, "{} TABLE ({})", name, display_comma_separated(columns))
815810
}
816-
DataType::SetOf(inner) => write!(f, "SETOF {inner}"),
817811
DataType::GeometricType(kind) => write!(f, "{kind}"),
818812
DataType::TsVector => write!(f, "TSVECTOR"),
819813
DataType::TsQuery => write!(f, "TSQUERY"),

src/ast/ddl.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3466,6 +3466,31 @@ impl fmt::Display for CreateDomain {
34663466
}
34673467
}
34683468

3469+
/// The return type of a `CREATE FUNCTION` statement.
3470+
///
3471+
/// Separates `SETOF` from plain data types because `SETOF` is a
3472+
/// [PostgreSQL]-specific modifier, not a standalone data type.
3473+
///
3474+
/// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
3475+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3476+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3477+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3478+
pub enum FunctionReturnType {
3479+
/// A normal data type, e.g. `RETURNS TEXT`.
3480+
DataType(DataType),
3481+
/// `RETURNS SETOF <type>`, e.g. `RETURNS SETOF TEXT`.
3482+
SetOf(DataType),
3483+
}
3484+
3485+
impl fmt::Display for FunctionReturnType {
3486+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3487+
match self {
3488+
FunctionReturnType::DataType(data_type) => write!(f, "{data_type}"),
3489+
FunctionReturnType::SetOf(data_type) => write!(f, "SETOF {data_type}"),
3490+
}
3491+
}
3492+
}
3493+
34693494
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
34703495
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
34713496
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
@@ -3486,7 +3511,7 @@ pub struct CreateFunction {
34863511
/// List of arguments for the function.
34873512
pub args: Option<Vec<OperateFunctionArg>>,
34883513
/// The return type of the function.
3489-
pub return_type: Option<DataType>,
3514+
pub return_type: Option<FunctionReturnType>,
34903515
/// The expression that defines the function.
34913516
///
34923517
/// Examples:

src/ast/mod.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,16 @@ pub use self::ddl::{
7171
CreateIndex, CreateOperator, CreateOperatorClass, CreateOperatorFamily, CreatePolicy,
7272
CreatePolicyCommand, CreatePolicyType, CreateTable, CreateTrigger, CreateView, Deduplicate,
7373
DeferrableInitial, DropBehavior, DropExtension, DropFunction, DropOperator, DropOperatorClass,
74-
DropOperatorFamily, DropOperatorSignature, DropPolicy, DropTrigger, ForValues, GeneratedAs,
75-
GeneratedExpressionMode, IdentityParameters, IdentityProperty, IdentityPropertyFormatKind,
76-
IdentityPropertyKind, IdentityPropertyOrder, IndexColumn, IndexOption, IndexType,
77-
KeyOrIndexDisplay, Msck, NullsDistinctOption, OperatorArgTypes, OperatorClassItem,
78-
OperatorFamilyDropItem, OperatorFamilyItem, OperatorOption, OperatorPurpose, Owner, Partition,
79-
PartitionBoundValue, ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity,
80-
TagsColumnOption, TriggerObjectKind, Truncate, UserDefinedTypeCompositeAttributeDef,
81-
UserDefinedTypeInternalLength, UserDefinedTypeRangeOption, UserDefinedTypeRepresentation,
82-
UserDefinedTypeSqlDefinitionOption, UserDefinedTypeStorage, ViewColumnDef,
74+
DropOperatorFamily, DropOperatorSignature, DropPolicy, DropTrigger, ForValues,
75+
FunctionReturnType, GeneratedAs, GeneratedExpressionMode, IdentityParameters, IdentityProperty,
76+
IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, IndexColumn,
77+
IndexOption, IndexType, KeyOrIndexDisplay, Msck, NullsDistinctOption, OperatorArgTypes,
78+
OperatorClassItem, OperatorFamilyDropItem, OperatorFamilyItem, OperatorOption, OperatorPurpose,
79+
Owner, Partition, PartitionBoundValue, ProcedureParam, ReferentialAction, RenameTableNameKind,
80+
ReplicaIdentity, TagsColumnOption, TriggerObjectKind, Truncate,
81+
UserDefinedTypeCompositeAttributeDef, UserDefinedTypeInternalLength,
82+
UserDefinedTypeRangeOption, UserDefinedTypeRepresentation, UserDefinedTypeSqlDefinitionOption,
83+
UserDefinedTypeStorage, ViewColumnDef,
8384
};
8485
pub use self::dml::{
8586
Delete, Insert, Merge, MergeAction, MergeClause, MergeClauseKind, MergeInsertExpr,

src/parser/mod.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5488,7 +5488,7 @@ impl<'a> Parser<'a> {
54885488
self.expect_token(&Token::RParen)?;
54895489

54905490
let return_type = if self.parse_keyword(Keyword::RETURNS) {
5491-
Some(self.parse_data_type()?)
5491+
Some(self.parse_function_return_type()?)
54925492
} else {
54935493
None
54945494
};
@@ -5667,7 +5667,7 @@ impl<'a> Parser<'a> {
56675667
let (name, args) = self.parse_create_function_name_and_params()?;
56685668

56695669
let return_type = if self.parse_keyword(Keyword::RETURNS) {
5670-
Some(self.parse_data_type()?)
5670+
Some(self.parse_function_return_type()?)
56715671
} else {
56725672
None
56735673
};
@@ -5770,10 +5770,10 @@ impl<'a> Parser<'a> {
57705770
})
57715771
})?;
57725772

5773-
let return_type = if return_table.is_some() {
5774-
return_table
5773+
let return_type = if let Some(table_type) = return_table {
5774+
Some(FunctionReturnType::DataType(table_type))
57755775
} else {
5776-
Some(self.parse_data_type()?)
5776+
Some(FunctionReturnType::DataType(self.parse_data_type()?))
57775777
};
57785778

57795779
let _ = self.parse_keyword(Keyword::AS);
@@ -5826,6 +5826,17 @@ impl<'a> Parser<'a> {
58265826
})
58275827
}
58285828

5829+
/// Parse a [FunctionReturnType] after the `RETURNS` keyword.
5830+
///
5831+
/// Handles `RETURNS SETOF <type>` (PostgreSQL) and plain `RETURNS <type>`.
5832+
fn parse_function_return_type(&mut self) -> Result<FunctionReturnType, ParserError> {
5833+
if self.parse_keyword(Keyword::SETOF) {
5834+
Ok(FunctionReturnType::SetOf(self.parse_data_type()?))
5835+
} else {
5836+
Ok(FunctionReturnType::DataType(self.parse_data_type()?))
5837+
}
5838+
}
5839+
58295840
fn parse_create_function_name_and_params(
58305841
&mut self,
58315842
) -> Result<(ObjectName, Vec<OperateFunctionArg>), ParserError> {
@@ -11976,10 +11987,6 @@ impl<'a> Parser<'a> {
1197611987
let field_defs = self.parse_click_house_tuple_def()?;
1197711988
Ok(DataType::Tuple(field_defs))
1197811989
}
11979-
Keyword::SETOF => {
11980-
let inner = self.parse_data_type()?;
11981-
Ok(DataType::SetOf(Box::new(inner)))
11982-
}
1198311990
Keyword::TRIGGER => Ok(DataType::Trigger),
1198411991
Keyword::ANY if self.peek_keyword(Keyword::TYPE) => {
1198511992
let _ = self.parse_keyword(Keyword::TYPE);

tests/sqlparser_bigquery.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2279,7 +2279,7 @@ fn test_bigquery_create_function() {
22792279
Ident::new("myfunction"),
22802280
]),
22812281
args: Some(vec![OperateFunctionArg::with_name("x", DataType::Float64),]),
2282-
return_type: Some(DataType::Float64),
2282+
return_type: Some(FunctionReturnType::DataType(DataType::Float64)),
22832283
function_body: Some(CreateFunctionBody::AsAfterOptions(Expr::Value(
22842284
number("42").with_empty_span()
22852285
))),

tests/sqlparser_mssql.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ fn parse_create_function() {
255255
default_expr: None,
256256
},
257257
]),
258-
return_type: Some(DataType::Int(None)),
258+
return_type: Some(FunctionReturnType::DataType(DataType::Int(None))),
259259
function_body: Some(CreateFunctionBody::AsBeginEnd(BeginEndStatements {
260260
begin_token: AttachedToken::empty(),
261261
statements: vec![Statement::Return(ReturnStatement {
@@ -430,7 +430,7 @@ fn parse_create_function_parameter_default_values() {
430430
data_type: DataType::Int(None),
431431
default_expr: Some(Expr::Value((number("42")).with_empty_span())),
432432
},]),
433-
return_type: Some(DataType::Int(None)),
433+
return_type: Some(FunctionReturnType::DataType(DataType::Int(None))),
434434
function_body: Some(CreateFunctionBody::AsBeginEnd(BeginEndStatements {
435435
begin_token: AttachedToken::empty(),
436436
statements: vec![Statement::Return(ReturnStatement {

tests/sqlparser_postgres.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4307,7 +4307,7 @@ $$"#;
43074307
DataType::Varchar(None),
43084308
),
43094309
]),
4310-
return_type: Some(DataType::Boolean),
4310+
return_type: Some(FunctionReturnType::DataType(DataType::Boolean)),
43114311
language: Some("plpgsql".into()),
43124312
behavior: None,
43134313
called_on_null: None,
@@ -4350,7 +4350,7 @@ $$"#;
43504350
DataType::Int(None)
43514351
)
43524352
]),
4353-
return_type: Some(DataType::Boolean),
4353+
return_type: Some(FunctionReturnType::DataType(DataType::Boolean)),
43544354
language: Some("plpgsql".into()),
43554355
behavior: None,
43564356
called_on_null: None,
@@ -4397,7 +4397,7 @@ $$"#;
43974397
DataType::Int(None)
43984398
),
43994399
]),
4400-
return_type: Some(DataType::Boolean),
4400+
return_type: Some(FunctionReturnType::DataType(DataType::Boolean)),
44014401
language: Some("plpgsql".into()),
44024402
behavior: None,
44034403
called_on_null: None,
@@ -4444,7 +4444,7 @@ $$"#;
44444444
DataType::Int(None)
44454445
),
44464446
]),
4447-
return_type: Some(DataType::Boolean),
4447+
return_type: Some(FunctionReturnType::DataType(DataType::Boolean)),
44484448
language: Some("plpgsql".into()),
44494449
behavior: None,
44504450
called_on_null: None,
@@ -4484,7 +4484,7 @@ $$"#;
44844484
),
44854485
OperateFunctionArg::with_name("b", DataType::Varchar(None)),
44864486
]),
4487-
return_type: Some(DataType::Boolean),
4487+
return_type: Some(FunctionReturnType::DataType(DataType::Boolean)),
44884488
language: Some("plpgsql".into()),
44894489
behavior: None,
44904490
called_on_null: None,
@@ -4527,7 +4527,7 @@ fn parse_create_function() {
45274527
OperateFunctionArg::unnamed(DataType::Integer(None)),
45284528
OperateFunctionArg::unnamed(DataType::Integer(None)),
45294529
]),
4530-
return_type: Some(DataType::Integer(None)),
4530+
return_type: Some(FunctionReturnType::DataType(DataType::Integer(None))),
45314531
language: Some("SQL".into()),
45324532
behavior: Some(FunctionBehavior::Immutable),
45334533
called_on_null: Some(FunctionCalledOnNull::Strict),
@@ -4582,7 +4582,7 @@ fn parse_create_function_returns_setof() {
45824582
let sql = "CREATE FUNCTION get_names() RETURNS SETOF TEXT LANGUAGE sql AS 'SELECT name FROM t'";
45834583
match pg_and_generic().verified_stmt(sql) {
45844584
Statement::CreateFunction(CreateFunction { return_type, .. }) => {
4585-
assert_eq!(return_type, Some(DataType::SetOf(Box::new(DataType::Text))));
4585+
assert_eq!(return_type, Some(FunctionReturnType::SetOf(DataType::Text)));
45864586
}
45874587
_ => panic!("Expected CreateFunction"),
45884588
}
@@ -4663,10 +4663,10 @@ fn parse_create_function_c_with_module_pathname() {
46634663
"input",
46644664
DataType::Custom(ObjectName::from(vec![Ident::new("cstring")]), vec![]),
46654665
),]),
4666-
return_type: Some(DataType::Custom(
4666+
return_type: Some(FunctionReturnType::DataType(DataType::Custom(
46674667
ObjectName::from(vec![Ident::new("cas")]),
46684668
vec![]
4669-
)),
4669+
))),
46704670
language: Some("c".into()),
46714671
behavior: Some(FunctionBehavior::Immutable),
46724672
called_on_null: None,
@@ -6360,7 +6360,7 @@ fn parse_trigger_related_functions() {
63606360
if_not_exists: false,
63616361
name: ObjectName::from(vec![Ident::new("emp_stamp")]),
63626362
args: Some(vec![]),
6363-
return_type: Some(DataType::Trigger),
6363+
return_type: Some(FunctionReturnType::DataType(DataType::Trigger)),
63646364
function_body: Some(
63656365
CreateFunctionBody::AsBeforeOptions {
63666366
body: Expr::Value((

0 commit comments

Comments
 (0)