This is an automated email from the ASF dual-hosted git repository.

github-bot pushed a commit to branch 
gh-readonly-queue/main/pr-2212-6a48f44f99d015a4f7a86275e2521ea2cc45fdae
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git

commit 798fbe4b934bd6409839f75e88efb5ca98e5abb9
Author: Guan-Ming (Wesley) Chiu <[email protected]>
AuthorDate: Sat Feb 14 15:00:24 2026 +0800

    MSSQL: Add support for TRAN shorthand (#2212)
    
    Signed-off-by: Guan-Ming (Wesley) Chiu 
<[email protected]>
---
 src/ast/mod.rs           |  6 +++++-
 src/dialect/mssql.rs     |  8 ++++++--
 src/keywords.rs          |  1 +
 src/parser/mod.rs        | 15 +++++++++------
 tests/sqlparser_mssql.rs | 28 ++++++++++++++++++++++++++++
 5 files changed, 49 insertions(+), 9 deletions(-)

diff --git a/src/ast/mod.rs b/src/ast/mod.rs
index 4d8c536a..eda28226 100644
--- a/src/ast/mod.rs
+++ b/src/ast/mod.rs
@@ -6390,7 +6390,7 @@ impl Display for CascadeOption {
     }
 }
 
-/// Transaction started with [ TRANSACTION | WORK ]
+/// Transaction started with [ TRANSACTION | WORK | TRAN ]
 #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
@@ -6399,6 +6399,9 @@ pub enum BeginTransactionKind {
     Transaction,
     /// Alternate `WORK` keyword.
     Work,
+    /// MSSQL shorthand `TRAN` keyword.
+    /// See 
<https://learn.microsoft.com/en-us/sql/t-sql/language-elements/begin-transaction-transact-sql>
+    Tran,
 }
 
 impl Display for BeginTransactionKind {
@@ -6406,6 +6409,7 @@ impl Display for BeginTransactionKind {
         match self {
             BeginTransactionKind::Transaction => write!(f, "TRANSACTION"),
             BeginTransactionKind::Work => write!(f, "WORK"),
+            BeginTransactionKind::Tran => write!(f, "TRAN"),
         }
     }
 }
diff --git a/src/dialect/mssql.rs b/src/dialect/mssql.rs
index e763165d..a2127f0d 100644
--- a/src/dialect/mssql.rs
+++ b/src/dialect/mssql.rs
@@ -151,8 +151,12 @@ impl Dialect for MsSqlDialect {
             let is_block = parser
                 .maybe_parse(|p| {
                     if p.parse_transaction_modifier().is_some()
-                        || p.parse_one_of_keywords(&[Keyword::TRANSACTION, 
Keyword::WORK])
-                            .is_some()
+                        || p.parse_one_of_keywords(&[
+                            Keyword::TRANSACTION,
+                            Keyword::WORK,
+                            Keyword::TRAN,
+                        ])
+                        .is_some()
                         || matches!(p.peek_token_ref().token, Token::SemiColon 
| Token::EOF)
                     {
                         p.expected("statement", p.peek_token())
diff --git a/src/keywords.rs b/src/keywords.rs
index 7950b191..f1dbcd93 100644
--- a/src/keywords.rs
+++ b/src/keywords.rs
@@ -1051,6 +1051,7 @@ define_keywords!(
     TOTP,
     TRACE,
     TRAILING,
+    TRAN,
     TRANSACTION,
     TRANSIENT,
     TRANSLATE,
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 7dc75815..1c20014d 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -18142,11 +18142,14 @@ impl<'a> Parser<'a> {
     /// Parse a 'BEGIN' statement
     pub fn parse_begin(&mut self) -> Result<Statement, ParserError> {
         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),
-            _ => None,
-        };
+        let transaction =
+            match self.parse_one_of_keywords(&[Keyword::TRANSACTION, 
Keyword::WORK, Keyword::TRAN])
+            {
+                Some(Keyword::TRANSACTION) => 
Some(BeginTransactionKind::Transaction),
+                Some(Keyword::WORK) => Some(BeginTransactionKind::Work),
+                Some(Keyword::TRAN) => Some(BeginTransactionKind::Tran),
+                _ => None,
+            };
         Ok(Statement::StartTransaction {
             modes: self.parse_transaction_modes()?,
             begin: true,
@@ -18280,7 +18283,7 @@ impl<'a> Parser<'a> {
 
     /// Parse an optional `AND [NO] CHAIN` clause for `COMMIT` and `ROLLBACK` 
statements
     pub fn parse_commit_rollback_chain(&mut self) -> Result<bool, ParserError> 
{
-        let _ = self.parse_one_of_keywords(&[Keyword::TRANSACTION, 
Keyword::WORK]);
+        let _ = self.parse_one_of_keywords(&[Keyword::TRANSACTION, 
Keyword::WORK, Keyword::TRAN]);
         if self.parse_keyword(Keyword::AND) {
             let chain = !self.parse_keyword(Keyword::NO);
             self.expect_keyword_is(Keyword::CHAIN)?;
diff --git a/tests/sqlparser_mssql.rs b/tests/sqlparser_mssql.rs
index 82e6f462..cf9ae898 100644
--- a/tests/sqlparser_mssql.rs
+++ b/tests/sqlparser_mssql.rs
@@ -2665,3 +2665,31 @@ fn parse_mssql_begin_end_block() {
         _ => panic!("Expected StartTransaction, got: {stmt:?}"),
     }
 }
+
+/// MSSQL supports `TRAN` as shorthand for `TRANSACTION`.
+/// See 
<https://learn.microsoft.com/en-us/sql/t-sql/language-elements/begin-transaction-transact-sql>
+#[test]
+fn parse_mssql_tran_shorthand() {
+    // BEGIN TRAN
+    let sql = "BEGIN TRAN";
+    let stmt = ms().verified_stmt(sql);
+    match &stmt {
+        Statement::StartTransaction {
+            begin,
+            transaction,
+            has_end_keyword,
+            ..
+        } => {
+            assert!(begin);
+            assert_eq!(*transaction, Some(BeginTransactionKind::Tran));
+            assert!(!has_end_keyword);
+        }
+        _ => panic!("Expected StartTransaction, got: {stmt:?}"),
+    }
+
+    // COMMIT TRAN normalizes to COMMIT (same as COMMIT TRANSACTION)
+    ms().one_statement_parses_to("COMMIT TRAN", "COMMIT");
+
+    // ROLLBACK TRAN normalizes to ROLLBACK (same as ROLLBACK TRANSACTION)
+    ms().one_statement_parses_to("ROLLBACK TRAN", "ROLLBACK");
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to