agent_patch
runs/2026-02-21__03-36-16__gpt-5-1-codex-mini/flux-pr-1649/flux-pr-1649.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/agent-logs/agent.patch
10253 bytes
diff --git a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/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-21__03-36-16__gpt-5-1-codex-mini/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-21__03-36-16__gpt-5-1-codex-mini/app/src/ast/mod.rs b/app/src/ast/mod.rs
index 6d0ef42..5746695 100644
--- a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/ast/mod.rs
+++ b/app/src/ast/mod.rs
@@ -2985,7 +2985,11 @@ pub enum Statement {
/// ```sql
/// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
/// ```
- Commit { chain: bool },
+ /// or `END [ TRY | CATCH ]`
+ Commit {
+ chain: bool,
+ modifier: Option<TransactionModifier>,
+ },
/// ```sql
/// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
/// ```
@@ -4614,8 +4618,12 @@ impl fmt::Display for Statement {
}
Ok(())
}
- Statement::Commit { chain } => {
- write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" },)
+ Statement::Commit { chain, modifier } => {
+ if let Some(modifier) = *modifier {
+ write!(f, "END {modifier}")
+ } else {
+ write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" },)
+ }
}
Statement::Rollback { chain, savepoint } => {
write!(f, "ROLLBACK")?;
@@ -6388,9 +6396,10 @@ impl fmt::Display for TransactionIsolationLevel {
}
}
-/// SQLite specific syntax
+/// Optional keywords that can follow `BEGIN` or `END`.
///
-/// <https://sqlite.org/lang_transaction.html>
+/// SQLite supports `DEFERRED`, `IMMEDIATE`, and `EXCLUSIVE`.
+/// MSSQL supports `TRY` and `CATCH`.
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
@@ -6398,6 +6407,8 @@ pub enum TransactionModifier {
Deferred,
Immediate,
Exclusive,
+ Try,
+ Catch,
}
impl fmt::Display for TransactionModifier {
@@ -6407,6 +6418,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-21__03-36-16__gpt-5-1-codex-mini/app/src/dialect/mssql.rs b/app/src/dialect/mssql.rs
index 2d0ef02..d6668d1 100644
--- a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/dialect/mssql.rs
+++ b/app/src/dialect/mssql.rs
@@ -50,6 +50,10 @@ impl Dialect for MsSqlDialect {
true
}
+ fn supports_start_transaction_modifier(&self) -> bool {
+ true
+ }
+
fn supports_eq_alias_assignment(&self) -> bool {
true
}
diff --git a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/keywords.rs b/app/src/keywords.rs
index c8f3cba..c50c2bd 100644
--- a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/keywords.rs
+++ b/app/src/keywords.rs
@@ -151,6 +151,7 @@ define_keywords!(
CASE,
CAST,
CATALOG,
+ CATCH,
CEIL,
CEILING,
CENTURY,
@@ -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-21__03-36-16__gpt-5-1-codex-mini/app/src/parser/mod.rs b/app/src/parser/mod.rs
index 95413a8..78d4a88 100644
--- a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/src/parser/mod.rs
+++ b/app/src/parser/mod.rs
@@ -12792,17 +12792,7 @@ 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_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),
@@ -12817,9 +12807,13 @@ impl<'a> Parser<'a> {
}
pub fn parse_end(&mut self) -> Result<Statement, ParserError> {
- Ok(Statement::Commit {
- chain: self.parse_commit_rollback_chain()?,
- })
+ let modifier = self.parse_transaction_modifier();
+ let chain = if modifier.is_some() {
+ false
+ } else {
+ self.parse_commit_rollback_chain()?
+ };
+ Ok(Statement::Commit { chain, modifier })
}
pub fn parse_transaction_modes(&mut self) -> Result<Vec<TransactionMode>, ParserError> {
@@ -12861,6 +12855,7 @@ impl<'a> Parser<'a> {
pub fn parse_commit(&mut self) -> Result<Statement, ParserError> {
Ok(Statement::Commit {
chain: self.parse_commit_rollback_chain()?,
+ modifier: None,
})
}
@@ -12893,6 +12888,34 @@ impl<'a> Parser<'a> {
}
}
+ fn parse_transaction_modifier(&mut self) -> Option<TransactionModifier> {
+ if !self.dialect.supports_start_transaction_modifier() {
+ return None;
+ }
+
+ if self.parse_keyword(Keyword::TRY) {
+ return Some(TransactionModifier::Try);
+ }
+
+ if self.parse_keyword(Keyword::CATCH) {
+ return Some(TransactionModifier::Catch);
+ }
+
+ if self.parse_keyword(Keyword::DEFERRED) {
+ return Some(TransactionModifier::Deferred);
+ }
+
+ if self.parse_keyword(Keyword::IMMEDIATE) {
+ return Some(TransactionModifier::Immediate);
+ }
+
+ if self.parse_keyword(Keyword::EXCLUSIVE) {
+ return Some(TransactionModifier::Exclusive);
+ }
+
+ None
+ }
+
pub fn parse_deallocate(&mut self) -> Result<Statement, ParserError> {
let prepare = self.parse_keyword(Keyword::PREPARE);
let name = self.parse_identifier()?;
diff --git a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/tests/sqlparser_common.rs b/app/tests/sqlparser_common.rs
index b47159d..2a979d0 100644
--- a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/tests/sqlparser_common.rs
+++ b/app/tests/sqlparser_common.rs
@@ -8102,12 +8102,12 @@ fn parse_set_time_zone_alias() {
#[test]
fn parse_commit() {
match verified_stmt("COMMIT") {
- Statement::Commit { chain: false } => (),
+ Statement::Commit { chain: false, .. } => (),
_ => unreachable!(),
}
match verified_stmt("COMMIT AND CHAIN") {
- Statement::Commit { chain: true } => (),
+ Statement::Commit { chain: true, .. } => (),
_ => unreachable!(),
}
diff --git a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/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-21__03-36-16__gpt-5-1-codex-mini/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-21__03-36-16__gpt-5-1-codex-mini/app/tests/sqlparser_mssql.rs b/app/tests/sqlparser_mssql.rs
index ecc874a..99eac6d 100644
--- a/tmp/agent-patch-flux-pr-1649.1-of-1.2026-02-21__03-36-16__gpt-5-1-codex-mini/app/tests/sqlparser_mssql.rs
+++ b/app/tests/sqlparser_mssql.rs
@@ -1679,6 +1679,43 @@ fn parse_true_false_as_identifiers() {
);
}
+#[test]
+fn parse_mssql_try_catch_blocks() {
+ match ms().verified_stmt("BEGIN TRY") {
+ Statement::StartTransaction {
+ begin: true,
+ modifier: Some(TransactionModifier::Try),
+ ..
+ } => {}
+ _ => unreachable!(),
+ }
+
+ match ms().verified_stmt("BEGIN CATCH") {
+ Statement::StartTransaction {
+ begin: true,
+ modifier: Some(TransactionModifier::Catch),
+ ..
+ } => {}
+ _ => unreachable!(),
+ }
+
+ match ms().verified_stmt("END TRY") {
+ Statement::Commit {
+ chain: false,
+ modifier: Some(TransactionModifier::Try),
+ } => {}
+ _ => unreachable!(),
+ }
+
+ match ms().verified_stmt("END CATCH") {
+ Statement::Commit {
+ chain: false,
+ modifier: Some(TransactionModifier::Catch),
+ } => {}
+ _ => unreachable!(),
+ }
+}
+
fn ms() -> TestedDialects {
TestedDialects::new(vec![Box::new(MsSqlDialect {})])
}