Skip to content

Commit 62385ea

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 b31d30c commit 62385ea

File tree

8 files changed

+90
-38
lines changed

8 files changed

+90
-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/ast/spans.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,31 @@ impl Spanned for CreateTable {
597597
}
598598
}
599599

600+
impl Spanned for PartitionBoundValue {
601+
fn span(&self) -> Span {
602+
match self {
603+
PartitionBoundValue::Expr(expr) => expr.span(),
604+
PartitionBoundValue::MinValue => Span::empty(),
605+
PartitionBoundValue::MaxValue => Span::empty(),
606+
}
607+
}
608+
}
609+
610+
impl Spanned for ForValues {
611+
fn span(&self) -> Span {
612+
match self {
613+
ForValues::In(exprs) => union_spans(exprs.iter().map(|e| e.span())),
614+
ForValues::From { from, to } => union_spans(
615+
from.iter()
616+
.map(|v| v.span())
617+
.chain(to.iter().map(|v| v.span())),
618+
),
619+
ForValues::With { .. } => Span::empty(),
620+
ForValues::Default => Span::empty(),
621+
}
622+
}
623+
}
624+
600625
impl Spanned for ColumnDef {
601626
fn span(&self) -> Span {
602627
let ColumnDef {

src/parser/mod.rs

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

55475547
let return_type = if self.parse_keyword(Keyword::RETURNS) {
5548-
Some(self.parse_data_type()?)
5548+
Some(self.parse_function_return_type()?)
55495549
} else {
55505550
None
55515551
};
@@ -5724,7 +5724,7 @@ impl<'a> Parser<'a> {
57245724
let (name, args) = self.parse_create_function_name_and_params()?;
57255725

57265726
let return_type = if self.parse_keyword(Keyword::RETURNS) {
5727-
Some(self.parse_data_type()?)
5727+
Some(self.parse_function_return_type()?)
57285728
} else {
57295729
None
57305730
};
@@ -5827,10 +5827,10 @@ impl<'a> Parser<'a> {
58275827
})
58285828
})?;
58295829

5830-
let return_type = if return_table.is_some() {
5831-
return_table
5830+
let return_type = if let Some(table_type) = return_table {
5831+
Some(FunctionReturnType::DataType(table_type))
58325832
} else {
5833-
Some(self.parse_data_type()?)
5833+
Some(FunctionReturnType::DataType(self.parse_data_type()?))
58345834
};
58355835

58365836
let _ = self.parse_keyword(Keyword::AS);
@@ -5883,6 +5883,17 @@ impl<'a> Parser<'a> {
58835883
})
58845884
}
58855885

5886+
/// Parse a [FunctionReturnType] after the `RETURNS` keyword.
5887+
///
5888+
/// Handles `RETURNS SETOF <type>` (PostgreSQL) and plain `RETURNS <type>`.
5889+
fn parse_function_return_type(&mut self) -> Result<FunctionReturnType, ParserError> {
5890+
if self.parse_keyword(Keyword::SETOF) {
5891+
Ok(FunctionReturnType::SetOf(self.parse_data_type()?))
5892+
} else {
5893+
Ok(FunctionReturnType::DataType(self.parse_data_type()?))
5894+
}
5895+
}
5896+
58865897
fn parse_create_function_name_and_params(
58875898
&mut self,
58885899
) -> Result<(ObjectName, Vec<OperateFunctionArg>), ParserError> {
@@ -12064,10 +12075,6 @@ impl<'a> Parser<'a> {
1206412075
let field_defs = self.parse_click_house_tuple_def()?;
1206512076
Ok(DataType::Tuple(field_defs))
1206612077
}
12067-
Keyword::SETOF => {
12068-
let inner = self.parse_data_type()?;
12069-
Ok(DataType::SetOf(Box::new(inner)))
12070-
}
1207112078
Keyword::TRIGGER => Ok(DataType::Trigger),
1207212079
Keyword::ANY if self.peek_keyword(Keyword::TYPE) => {
1207312080
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
@@ -4346,7 +4346,7 @@ $$"#;
43464346
DataType::Varchar(None),
43474347
),
43484348
]),
4349-
return_type: Some(DataType::Boolean),
4349+
return_type: Some(FunctionReturnType::DataType(DataType::Boolean)),
43504350
language: Some("plpgsql".into()),
43514351
behavior: None,
43524352
called_on_null: None,
@@ -4389,7 +4389,7 @@ $$"#;
43894389
DataType::Int(None)
43904390
)
43914391
]),
4392-
return_type: Some(DataType::Boolean),
4392+
return_type: Some(FunctionReturnType::DataType(DataType::Boolean)),
43934393
language: Some("plpgsql".into()),
43944394
behavior: None,
43954395
called_on_null: None,
@@ -4436,7 +4436,7 @@ $$"#;
44364436
DataType::Int(None)
44374437
),
44384438
]),
4439-
return_type: Some(DataType::Boolean),
4439+
return_type: Some(FunctionReturnType::DataType(DataType::Boolean)),
44404440
language: Some("plpgsql".into()),
44414441
behavior: None,
44424442
called_on_null: None,
@@ -4483,7 +4483,7 @@ $$"#;
44834483
DataType::Int(None)
44844484
),
44854485
]),
4486-
return_type: Some(DataType::Boolean),
4486+
return_type: Some(FunctionReturnType::DataType(DataType::Boolean)),
44874487
language: Some("plpgsql".into()),
44884488
behavior: None,
44894489
called_on_null: None,
@@ -4523,7 +4523,7 @@ $$"#;
45234523
),
45244524
OperateFunctionArg::with_name("b", DataType::Varchar(None)),
45254525
]),
4526-
return_type: Some(DataType::Boolean),
4526+
return_type: Some(FunctionReturnType::DataType(DataType::Boolean)),
45274527
language: Some("plpgsql".into()),
45284528
behavior: None,
45294529
called_on_null: None,
@@ -4566,7 +4566,7 @@ fn parse_create_function() {
45664566
OperateFunctionArg::unnamed(DataType::Integer(None)),
45674567
OperateFunctionArg::unnamed(DataType::Integer(None)),
45684568
]),
4569-
return_type: Some(DataType::Integer(None)),
4569+
return_type: Some(FunctionReturnType::DataType(DataType::Integer(None))),
45704570
language: Some("SQL".into()),
45714571
behavior: Some(FunctionBehavior::Immutable),
45724572
called_on_null: Some(FunctionCalledOnNull::Strict),
@@ -4621,7 +4621,7 @@ fn parse_create_function_returns_setof() {
46214621
let sql = "CREATE FUNCTION get_names() RETURNS SETOF TEXT LANGUAGE sql AS 'SELECT name FROM t'";
46224622
match pg_and_generic().verified_stmt(sql) {
46234623
Statement::CreateFunction(CreateFunction { return_type, .. }) => {
4624-
assert_eq!(return_type, Some(DataType::SetOf(Box::new(DataType::Text))));
4624+
assert_eq!(return_type, Some(FunctionReturnType::SetOf(DataType::Text)));
46254625
}
46264626
_ => panic!("Expected CreateFunction"),
46274627
}
@@ -4702,10 +4702,10 @@ fn parse_create_function_c_with_module_pathname() {
47024702
"input",
47034703
DataType::Custom(ObjectName::from(vec![Ident::new("cstring")]), vec![]),
47044704
),]),
4705-
return_type: Some(DataType::Custom(
4705+
return_type: Some(FunctionReturnType::DataType(DataType::Custom(
47064706
ObjectName::from(vec![Ident::new("cas")]),
47074707
vec![]
4708-
)),
4708+
))),
47094709
language: Some("c".into()),
47104710
behavior: Some(FunctionBehavior::Immutable),
47114711
called_on_null: None,
@@ -6399,7 +6399,7 @@ fn parse_trigger_related_functions() {
63996399
if_not_exists: false,
64006400
name: ObjectName::from(vec![Ident::new("emp_stamp")]),
64016401
args: Some(vec![]),
6402-
return_type: Some(DataType::Trigger),
6402+
return_type: Some(FunctionReturnType::DataType(DataType::Trigger)),
64036403
function_body: Some(
64046404
CreateFunctionBody::AsBeforeOptions {
64056405
body: Expr::Value((

0 commit comments

Comments
 (0)