STET

agent_patch

runs/2026-02-28__18-27-22__gpt-5-3-codex/flux-pr-1839/flux-pr-1839.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/agent-logs/agent.patch

13247 bytes

Back to adjudication
diff --git a/tmp/agent-patch-flux-pr-1839.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/ast/ddl.rs b/app/src/ast/ddl.rs
index a8a1fdb..1c1b427 100644
--- a/tmp/agent-patch-flux-pr-1839.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/ast/ddl.rs
+++ b/app/src/ast/ddl.rs
@@ -2258,6 +2258,13 @@ pub struct CreateFunction {
     pub if_not_exists: bool,
     pub name: ObjectName,
     pub args: Option<Vec<OperateFunctionArg>>,
+    /// Named table variable in SQL Server table-valued functions.
+    ///
+    /// Example:
+    /// ```sql
+    /// RETURNS @result TABLE(id INT)
+    /// ```
+    pub return_table: Option<Ident>,
     pub return_type: Option<DataType>,
     /// The expression that defines the function.
     ///
@@ -2330,7 +2337,11 @@ impl fmt::Display for CreateFunction {
             write!(f, "({})", display_comma_separated(args))?;
         }
         if let Some(return_type) = &self.return_type {
-            write!(f, " RETURNS {return_type}")?;
+            if let Some(return_table) = &self.return_table {
+                write!(f, " RETURNS {return_table} {return_type}")?;
+            } else {
+                write!(f, " RETURNS {return_type}")?;
+            }
         }
         if let Some(determinism_specifier) = &self.determinism_specifier {
             write!(f, " {determinism_specifier}")?;
@@ -2356,6 +2367,9 @@ impl fmt::Display for CreateFunction {
         if let Some(CreateFunctionBody::Return(function_body)) = &self.function_body {
             write!(f, " RETURN {function_body}")?;
         }
+        if let Some(CreateFunctionBody::ReturnQuery(function_body)) = &self.function_body {
+            write!(f, " RETURN {function_body}")?;
+        }
         if let Some(using) = &self.using {
             write!(f, " {using}")?;
         }
diff --git a/tmp/agent-patch-flux-pr-1839.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/ast/mod.rs b/app/src/ast/mod.rs
index e18251e..f8d528f 100644
--- a/tmp/agent-patch-flux-pr-1839.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/ast/mod.rs
+++ b/app/src/ast/mod.rs
@@ -8780,6 +8780,17 @@ pub enum CreateFunctionBody {
     ///
     /// [PostgreSQL]: https://www.postgresql.org/docs/current/sql-createfunction.html
     Return(Expr),
+    /// Function body query using the `RETURN` keyword.
+    ///
+    /// Example:
+    /// ```sql
+    /// CREATE FUNCTION my_tvf()
+    /// RETURNS TABLE
+    /// RETURN SELECT 1 AS id;
+    /// ```
+    ///
+    /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql
+    ReturnQuery(Box<Query>),
 }
 
 #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
diff --git a/tmp/agent-patch-flux-pr-1839.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/parser/mod.rs b/app/src/parser/mod.rs
index 47b321d..70ba582 100644
--- a/tmp/agent-patch-flux-pr-1839.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/parser/mod.rs
+++ b/app/src/parser/mod.rs
@@ -5069,6 +5069,7 @@ impl<'a> Parser<'a> {
             temporary,
             name,
             args: Some(args),
+            return_table: None,
             return_type,
             behavior: body.behavior,
             called_on_null: body.called_on_null,
@@ -5106,6 +5107,7 @@ impl<'a> Parser<'a> {
             using,
             if_not_exists: false,
             args: None,
+            return_table: None,
             return_type: None,
             behavior: None,
             called_on_null: None,
@@ -5179,6 +5181,7 @@ impl<'a> Parser<'a> {
             if_not_exists,
             name,
             args: Some(args),
+            return_table: None,
             return_type,
             function_body,
             language,
@@ -5204,19 +5207,36 @@ impl<'a> Parser<'a> {
         let (name, args) = self.parse_create_function_name_and_params()?;
 
         self.expect_keyword(Keyword::RETURNS)?;
+        let mut return_table = None;
+        if self.peek_token().token == Token::Word(_) {
+            let table_name = self.parse_identifier()?;
+            if self.peek_keyword(Keyword::TABLE) {
+                return_table = Some(table_name);
+            } else {
+                self.prev_token();
+            }
+        }
         let return_type = Some(self.parse_data_type()?);
 
-        self.expect_keyword_is(Keyword::AS)?;
-
-        let begin_token = self.expect_keyword(Keyword::BEGIN)?;
-        let statements = self.parse_statement_list(&[Keyword::END])?;
-        let end_token = self.expect_keyword(Keyword::END)?;
+        let _ = self.parse_keyword(Keyword::AS);
 
-        let function_body = Some(CreateFunctionBody::AsBeginEnd(BeginEndStatements {
-            begin_token: AttachedToken(begin_token),
-            statements,
-            end_token: AttachedToken(end_token),
-        }));
+        let function_body = if self.peek_keyword(Keyword::BEGIN) {
+            let begin_token = self.expect_keyword(Keyword::BEGIN)?;
+            let statements = self.parse_statement_list(&[Keyword::END])?;
+            let end_token = self.expect_keyword(Keyword::END)?;
+            Some(CreateFunctionBody::AsBeginEnd(BeginEndStatements {
+                begin_token: AttachedToken(begin_token),
+                statements,
+                end_token: AttachedToken(end_token),
+            }))
+        } else {
+            self.expect_keyword(Keyword::RETURN)?;
+            if self.peek_sub_query() {
+                Some(CreateFunctionBody::ReturnQuery(Box::new(self.parse_query()?)))
+            } else {
+                Some(CreateFunctionBody::Return(self.parse_expr()?))
+            }
+        };
 
         Ok(Statement::CreateFunction(CreateFunction {
             or_alter,
@@ -5225,6 +5245,7 @@ impl<'a> Parser<'a> {
             if_not_exists: false,
             name,
             args: Some(args),
+            return_table,
             return_type,
             function_body,
             language: None,
@@ -9839,20 +9860,19 @@ impl<'a> Parser<'a> {
     }
 
     fn parse_returns_table_column(&mut self) -> Result<ColumnDef, ParserError> {
-        let name = self.parse_identifier()?;
-        let data_type = self.parse_data_type()?;
-        Ok(ColumnDef {
-            name,
-            data_type,
-            options: Vec::new(), // No constraints expected here
-        })
+        self.parse_column_def()
     }
 
     fn parse_returns_table_columns(&mut self) -> Result<Vec<ColumnDef>, ParserError> {
-        self.expect_token(&Token::LParen)?;
-        let columns = self.parse_comma_separated(Parser::parse_returns_table_column)?;
-        self.expect_token(&Token::RParen)?;
-        Ok(columns)
+        if self.consume_token(&Token::LParen) {
+            let columns = self.parse_comma_separated(Parser::parse_returns_table_column)?;
+            self.expect_token(&Token::RParen)?;
+            Ok(columns)
+        } else if dialect_of!(self is MsSqlDialect) {
+            Ok(vec![])
+        } else {
+            self.expected("a list of columns in parentheses", self.peek_token())
+        }
     }
 
     pub fn parse_string_values(&mut self) -> Result<Vec<String>, ParserError> {
diff --git a/tmp/agent-patch-flux-pr-1839.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_bigquery.rs b/app/tests/sqlparser_bigquery.rs
index 8f54f3c..a408821 100644
--- a/tmp/agent-patch-flux-pr-1839.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_bigquery.rs
+++ b/app/tests/sqlparser_bigquery.rs
@@ -2144,6 +2144,7 @@ fn test_bigquery_create_function() {
                 Ident::new("myfunction"),
             ]),
             args: Some(vec![OperateFunctionArg::with_name("x", DataType::Float64),]),
+            return_table: None,
             return_type: Some(DataType::Float64),
             function_body: Some(CreateFunctionBody::AsAfterOptions(Expr::Value(
                 number("42").with_empty_span()
diff --git a/tmp/agent-patch-flux-pr-1839.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_mssql.rs b/app/tests/sqlparser_mssql.rs
index 7b3769e..ffefd14 100644
--- a/tmp/agent-patch-flux-pr-1839.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_mssql.rs
+++ b/app/tests/sqlparser_mssql.rs
@@ -222,6 +222,7 @@ fn parse_create_function() {
                     default_expr: None,
                 },
             ]),
+            return_table: None,
             return_type: Some(DataType::Int(None)),
             function_body: Some(CreateFunctionBody::AsBeginEnd(BeginEndStatements {
                 begin_token: AttachedToken::empty(),
@@ -288,6 +289,68 @@ fn parse_create_function() {
         END\
     ";
     let _ = ms().verified_stmt(create_function_with_return_expression);
+
+    let inline_table_valued_function = "\
+        CREATE FUNCTION some_tvf(@foo INT) \
+        RETURNS TABLE \
+        AS \
+        RETURN SELECT @foo AS foo\
+    ";
+    let stmt = ms().verified_stmt(inline_table_valued_function);
+    match stmt {
+        Statement::CreateFunction(CreateFunction {
+            return_table,
+            return_type,
+            function_body,
+            ..
+        }) => {
+            assert_eq!(return_table, None);
+            assert_eq!(return_type, Some(DataType::Table(vec![])));
+            assert!(matches!(function_body, Some(CreateFunctionBody::ReturnQuery(_))));
+        }
+        _ => unreachable!(),
+    }
+
+    let inline_table_valued_function_without_as = "\
+        CREATE FUNCTION some_tvf(@foo INT) \
+        RETURNS TABLE \
+        RETURN SELECT @foo AS foo\
+    ";
+    let _ = ms().verified_stmt(inline_table_valued_function_without_as);
+
+    let multi_statement_table_valued_function = "\
+        CREATE FUNCTION some_tvf(@foo INT) \
+        RETURNS @result TABLE(id INT NOT NULL, name VARCHAR(20) NULL) \
+        BEGIN \
+            INSERT INTO @result \
+            SELECT @foo, 'x'; \
+            RETURN; \
+        END\
+    ";
+    let stmt = ms().verified_stmt(multi_statement_table_valued_function);
+    match stmt {
+        Statement::CreateFunction(CreateFunction {
+            return_table,
+            return_type,
+            function_body,
+            ..
+        }) => {
+            assert_eq!(return_table, Some(Ident::new("@result")));
+            match return_type {
+                Some(DataType::Table(columns)) => {
+                    assert_eq!(columns.len(), 2);
+                    assert!(!columns[0].options.is_empty());
+                    assert!(!columns[1].options.is_empty());
+                }
+                _ => unreachable!(),
+            }
+            assert!(matches!(
+                function_body,
+                Some(CreateFunctionBody::AsBeginEnd(_))
+            ));
+        }
+        _ => unreachable!(),
+    }
 }
 
 #[test]
diff --git a/tmp/agent-patch-flux-pr-1839.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_postgres.rs b/app/tests/sqlparser_postgres.rs
index 682c0d6..9ef5109 100644
--- a/tmp/agent-patch-flux-pr-1839.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_postgres.rs
+++ b/app/tests/sqlparser_postgres.rs
@@ -4135,6 +4135,7 @@ $$"#;
                     DataType::Varchar(None),
                 ),
             ]),
+            return_table: None,
             return_type: Some(DataType::Boolean),
             language: Some("plpgsql".into()),
             behavior: None,
@@ -4173,6 +4174,7 @@ $$"#;
                     DataType::Int(None)
                 )
             ]),
+            return_table: None,
             return_type: Some(DataType::Boolean),
             language: Some("plpgsql".into()),
             behavior: None,
@@ -4215,6 +4217,7 @@ $$"#;
                     DataType::Int(None)
                 ),
             ]),
+            return_table: None,
             return_type: Some(DataType::Boolean),
             language: Some("plpgsql".into()),
             behavior: None,
@@ -4257,6 +4260,7 @@ $$"#;
                     DataType::Int(None)
                 ),
             ]),
+            return_table: None,
             return_type: Some(DataType::Boolean),
             language: Some("plpgsql".into()),
             behavior: None,
@@ -4292,6 +4296,7 @@ $$"#;
                 ),
                 OperateFunctionArg::with_name("b", DataType::Varchar(None)),
             ]),
+            return_table: None,
             return_type: Some(DataType::Boolean),
             language: Some("plpgsql".into()),
             behavior: None,
@@ -4330,6 +4335,7 @@ fn parse_create_function() {
                 OperateFunctionArg::unnamed(DataType::Integer(None)),
                 OperateFunctionArg::unnamed(DataType::Integer(None)),
             ]),
+            return_table: None,
             return_type: Some(DataType::Integer(None)),
             language: Some("SQL".into()),
             behavior: Some(FunctionBehavior::Immutable),
@@ -5873,6 +5879,7 @@ fn parse_trigger_related_functions() {
             if_not_exists: false,
             name: ObjectName::from(vec![Ident::new("emp_stamp")]),
             args: Some(vec![]),
+            return_table: None,
             return_type: Some(DataType::Trigger),
             function_body: Some(
                 CreateFunctionBody::AsBeforeOptions(