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
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(