STET

agent_patch

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

10262 bytes

Back to adjudication
diff --git a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/ast/helpers/stmt_create_table.rs b/app/src/ast/helpers/stmt_create_table.rs
index 364969c..2a0663b 100644
--- a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/ast/helpers/stmt_create_table.rs
+++ b/app/src/ast/helpers/stmt_create_table.rs
@@ -548,7 +548,10 @@ mod tests {
 
     #[test]
     pub fn test_from_invalid_statement() {
-        let stmt = Statement::Commit { chain: false };
+        let stmt = Statement::Commit {
+            chain: false,
+            modifier: None,
+        };
 
         assert_eq!(
             CreateTableBuilder::try_from(stmt).unwrap_err(),
diff --git a/tmp/agent-patch-flux-pr-1649.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 6d0ef42..2f7f540 100644
--- a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/ast/mod.rs
+++ b/app/src/ast/mod.rs
@@ -2983,9 +2983,12 @@ pub enum Statement {
         if_exists: bool,
     },
     /// ```sql
-    /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
+    /// COMMIT [ TRY | CATCH ] [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
     /// ```
-    Commit { chain: bool },
+    Commit {
+        chain: bool,
+        modifier: Option<TransactionModifier>,
+    },
     /// ```sql
     /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
     /// ```
@@ -4614,8 +4617,12 @@ impl fmt::Display for Statement {
                 }
                 Ok(())
             }
-            Statement::Commit { chain } => {
-                write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" },)
+            Statement::Commit { chain, modifier } => {
+                write!(f, "COMMIT")?;
+                if let Some(modifier) = modifier {
+                    write!(f, " {modifier}")?;
+                }
+                write!(f, "{}", if *chain { " AND CHAIN" } else { "" },)
             }
             Statement::Rollback { chain, savepoint } => {
                 write!(f, "ROLLBACK")?;
@@ -6388,16 +6395,21 @@ impl fmt::Display for TransactionIsolationLevel {
     }
 }
 
-/// SQLite specific syntax
-///
-/// <https://sqlite.org/lang_transaction.html>
+/// Modifiers for transaction statements.
 #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
 pub enum TransactionModifier {
+    /// SQLite specific syntax: <https://sqlite.org/lang_transaction.html>
     Deferred,
+    /// SQLite specific syntax: <https://sqlite.org/lang_transaction.html>
     Immediate,
+    /// SQLite specific syntax: <https://sqlite.org/lang_transaction.html>
     Exclusive,
+    /// MS SQL specific syntax: `BEGIN TRY` / `END TRY`
+    Try,
+    /// MS SQL specific syntax: `BEGIN CATCH` / `END CATCH`
+    Catch,
 }
 
 impl fmt::Display for TransactionModifier {
@@ -6407,6 +6419,8 @@ impl fmt::Display for TransactionModifier {
             Deferred => "DEFERRED",
             Immediate => "IMMEDIATE",
             Exclusive => "EXCLUSIVE",
+            Try => "TRY",
+            Catch => "CATCH",
         })
     }
 }
diff --git a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/keywords.rs b/app/src/keywords.rs
index c8f3cba..8b4f2b7 100644
--- a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/keywords.rs
+++ b/app/src/keywords.rs
@@ -149,6 +149,7 @@ define_keywords!(
     CASCADE,
     CASCADED,
     CASE,
+    CATCH,
     CAST,
     CATALOG,
     CEIL,
@@ -812,6 +813,7 @@ define_keywords!(
     TRIM_ARRAY,
     TRUE,
     TRUNCATE,
+    TRY,
     TRY_CAST,
     TRY_CONVERT,
     TUPLE,
diff --git a/tmp/agent-patch-flux-pr-1649.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 95413a8..b640a35 100644
--- a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/src/parser/mod.rs
+++ b/app/src/parser/mod.rs
@@ -12792,17 +12792,9 @@ impl<'a> Parser<'a> {
     }
 
     pub fn parse_begin(&mut self) -> Result<Statement, ParserError> {
-        let modifier = if !self.dialect.supports_start_transaction_modifier() {
-            None
-        } else if self.parse_keyword(Keyword::DEFERRED) {
-            Some(TransactionModifier::Deferred)
-        } else if self.parse_keyword(Keyword::IMMEDIATE) {
-            Some(TransactionModifier::Immediate)
-        } else if self.parse_keyword(Keyword::EXCLUSIVE) {
-            Some(TransactionModifier::Exclusive)
-        } else {
-            None
-        };
+        let modifier = self
+            .parse_mssql_try_catch_transaction_modifier()
+            .or_else(|| self.parse_sqlite_start_transaction_modifier());
         let transaction = match self.parse_one_of_keywords(&[Keyword::TRANSACTION, Keyword::WORK]) {
             Some(Keyword::TRANSACTION) => Some(BeginTransactionKind::Transaction),
             Some(Keyword::WORK) => Some(BeginTransactionKind::Work),
@@ -12818,6 +12810,7 @@ impl<'a> Parser<'a> {
 
     pub fn parse_end(&mut self) -> Result<Statement, ParserError> {
         Ok(Statement::Commit {
+            modifier: self.parse_mssql_try_catch_transaction_modifier(),
             chain: self.parse_commit_rollback_chain()?,
         })
     }
@@ -12860,10 +12853,37 @@ impl<'a> Parser<'a> {
 
     pub fn parse_commit(&mut self) -> Result<Statement, ParserError> {
         Ok(Statement::Commit {
+            modifier: self.parse_mssql_try_catch_transaction_modifier(),
             chain: self.parse_commit_rollback_chain()?,
         })
     }
 
+    fn parse_sqlite_start_transaction_modifier(&mut self) -> Option<TransactionModifier> {
+        if !self.dialect.supports_start_transaction_modifier() {
+            None
+        } else if self.parse_keyword(Keyword::DEFERRED) {
+            Some(TransactionModifier::Deferred)
+        } else if self.parse_keyword(Keyword::IMMEDIATE) {
+            Some(TransactionModifier::Immediate)
+        } else if self.parse_keyword(Keyword::EXCLUSIVE) {
+            Some(TransactionModifier::Exclusive)
+        } else {
+            None
+        }
+    }
+
+    fn parse_mssql_try_catch_transaction_modifier(&mut self) -> Option<TransactionModifier> {
+        if !dialect_of!(self is MsSqlDialect | GenericDialect) {
+            None
+        } else if self.parse_keyword(Keyword::TRY) {
+            Some(TransactionModifier::Try)
+        } else if self.parse_keyword(Keyword::CATCH) {
+            Some(TransactionModifier::Catch)
+        } else {
+            None
+        }
+    }
+
     pub fn parse_rollback(&mut self) -> Result<Statement, ParserError> {
         let chain = self.parse_commit_rollback_chain()?;
         let savepoint = self.parse_rollback_savepoint()?;
diff --git a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_common.rs b/app/tests/sqlparser_common.rs
index b47159d..ca08a8e 100644
--- a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_common.rs
+++ b/app/tests/sqlparser_common.rs
@@ -8102,12 +8102,18 @@ fn parse_set_time_zone_alias() {
 #[test]
 fn parse_commit() {
     match verified_stmt("COMMIT") {
-        Statement::Commit { chain: false } => (),
+        Statement::Commit {
+            chain: false,
+            modifier: None,
+        } => (),
         _ => unreachable!(),
     }
 
     match verified_stmt("COMMIT AND CHAIN") {
-        Statement::Commit { chain: true } => (),
+        Statement::Commit {
+            chain: true,
+            modifier: None,
+        } => (),
         _ => unreachable!(),
     }
 
diff --git a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_custom_dialect.rs b/app/tests/sqlparser_custom_dialect.rs
index e9ca82a..5ee6282 100644
--- a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_custom_dialect.rs
+++ b/app/tests/sqlparser_custom_dialect.rs
@@ -115,7 +115,10 @@ fn custom_statement_parser() -> Result<(), ParserError> {
                 for _ in 0..3 {
                     let _ = parser.next_token();
                 }
-                Some(Ok(Statement::Commit { chain: false }))
+                Some(Ok(Statement::Commit {
+                    chain: false,
+                    modifier: None,
+                }))
             } else {
                 None
             }
diff --git a/tmp/agent-patch-flux-pr-1649.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 ecc874a..dd43ed6 100644
--- a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-28__18-27-22__gpt-5-3-codex/app/tests/sqlparser_mssql.rs
+++ b/app/tests/sqlparser_mssql.rs
@@ -185,6 +185,43 @@ fn parse_mssql_create_procedure() {
     let _ = ms().verified_stmt("CREATE PROCEDURE [foo] AS BEGIN UPDATE bar SET col = 'test'; SELECT [foo] FROM BAR WHERE [FOO] > 10 END");
 }
 
+#[test]
+fn parse_mssql_try_catch_transaction_blocks() {
+    assert_eq!(
+        ms_and_generic().verified_stmt("BEGIN TRY"),
+        Statement::StartTransaction {
+            modes: vec![],
+            begin: true,
+            transaction: None,
+            modifier: Some(TransactionModifier::Try),
+        }
+    );
+    assert_eq!(
+        ms_and_generic().verified_stmt("BEGIN CATCH"),
+        Statement::StartTransaction {
+            modes: vec![],
+            begin: true,
+            transaction: None,
+            modifier: Some(TransactionModifier::Catch),
+        }
+    );
+
+    assert_eq!(
+        ms_and_generic().one_statement_parses_to("END TRY", "COMMIT TRY"),
+        Statement::Commit {
+            chain: false,
+            modifier: Some(TransactionModifier::Try),
+        }
+    );
+    assert_eq!(
+        ms_and_generic().one_statement_parses_to("END CATCH", "COMMIT CATCH"),
+        Statement::Commit {
+            chain: false,
+            modifier: Some(TransactionModifier::Catch),
+        }
+    );
+}
+
 #[test]
 fn parse_mssql_apply_join() {
     let _ = ms_and_generic().verified_only_select(