Skip to content

Commit c75f35b

Browse files
committed
Add multi-statement table valued function support for SQL Server
1 parent 6b1d5d6 commit c75f35b

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed

src/ast/data_type.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ pub enum DataType {
5050
/// [PostgreSQL]: https://www.postgresql.org/docs/15/sql-createfunction.html
5151
/// [MsSQL]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#c-create-a-multi-statement-table-valued-function
5252
Table(Vec<ColumnDef>),
53+
/// Table type with a name, e.g. CREATE FUNCTION RETURNS @result TABLE(...).
54+
NamedTable(
55+
/// Table name.
56+
ObjectName,
57+
/// Table columns.
58+
Vec<ColumnDef>,
59+
),
5360
/// Fixed-length character type, e.g. CHARACTER(10).
5461
Character(Option<CharacterLength>),
5562
/// Fixed-length char type, e.g. CHAR(10).
@@ -723,6 +730,9 @@ impl fmt::Display for DataType {
723730
}
724731
write!(f, "TABLE({})", display_comma_separated(fields))
725732
}
733+
DataType::NamedTable(name, fields) => {
734+
write!(f, "{} TABLE ({})", name, display_comma_separated(fields))
735+
}
726736
DataType::GeometricType(kind) => write!(f, "{}", kind),
727737
}
728738
}

src/parser/mod.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5203,7 +5203,36 @@ impl<'a> Parser<'a> {
52035203
let (name, args) = self.parse_create_function_name_and_params()?;
52045204

52055205
self.expect_keyword(Keyword::RETURNS)?;
5206-
let return_type = Some(self.parse_data_type()?);
5206+
5207+
let return_table = self.maybe_parse(|p| {
5208+
let return_table_name = p.parse_identifier()?;
5209+
let table_column_defs = if p.peek_keyword(Keyword::TABLE) {
5210+
match p.parse_data_type()? {
5211+
DataType::Table(t) => t,
5212+
_ => {
5213+
return parser_err!(
5214+
"Expected table data type after TABLE keyword, got {:?}",
5215+
p.peek_token()
5216+
)?
5217+
}
5218+
}
5219+
} else {
5220+
return parser_err!(
5221+
"Expected TABLE keyword after return type, got {:?}",
5222+
p.peek_token()
5223+
);
5224+
};
5225+
Ok(DataType::NamedTable(
5226+
ObjectName(vec![ObjectNamePart::Identifier(return_table_name)]),
5227+
table_column_defs.clone(),
5228+
))
5229+
})?;
5230+
5231+
let return_type = if return_table.is_some() {
5232+
return_table
5233+
} else {
5234+
Some(self.parse_data_type()?)
5235+
};
52075236

52085237
self.expect_keyword_is(Keyword::AS)?;
52095238

tests/sqlparser_mssql.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,17 @@ fn parse_create_function() {
296296
RETURN (SELECT 1 AS col_1)\
297297
";
298298
let _ = ms().verified_stmt(create_inline_table_value_function);
299+
300+
let create_multi_statement_table_value_function = "\
301+
CREATE FUNCTION some_multi_statement_tvf(@foo INT, @bar VARCHAR(256)) \
302+
RETURNS @t TABLE (col_1 INT) \
303+
AS \
304+
BEGIN \
305+
INSERT INTO @t SELECT 1; \
306+
RETURN; \
307+
END\
308+
";
309+
let _ = ms().verified_stmt(create_multi_statement_table_value_function);
299310
}
300311

301312
#[test]

0 commit comments

Comments
 (0)