Skip to content

Commit b6f225d

Browse files
committed
MSSQL: Support standalone BEGIN...END blocks
Signed-off-by: Guan-Ming (Wesley) Chiu <105915352+guan404ming@users.noreply.github.com>
1 parent c8b7f7c commit b6f225d

2 files changed

Lines changed: 87 additions & 1 deletion

File tree

src/dialect/mssql.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,22 @@ impl Dialect for MsSqlDialect {
145145
}
146146

147147
fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
148-
if parser.peek_keyword(Keyword::IF) {
148+
if parser.parse_keyword(Keyword::BEGIN) {
149+
if parser.peek_keyword(Keyword::TRANSACTION)
150+
|| parser.peek_keyword(Keyword::WORK)
151+
|| parser.peek_keyword(Keyword::TRY)
152+
|| parser.peek_keyword(Keyword::CATCH)
153+
|| parser.peek_keyword(Keyword::DEFERRED)
154+
|| parser.peek_keyword(Keyword::IMMEDIATE)
155+
|| parser.peek_keyword(Keyword::EXCLUSIVE)
156+
|| parser.peek_token_ref().token == Token::SemiColon
157+
|| parser.peek_token_ref().token == Token::EOF
158+
{
159+
parser.prev_token();
160+
return None;
161+
}
162+
return Some(parser.parse_begin_exception_end());
163+
} else if parser.peek_keyword(Keyword::IF) {
149164
Some(self.parse_if_stmt(parser))
150165
} else if parser.parse_keywords(&[Keyword::CREATE, Keyword::TRIGGER]) {
151166
Some(self.parse_create_trigger(parser, false))

tests/sqlparser_mssql.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2554,3 +2554,74 @@ fn test_sql_keywords_as_column_aliases() {
25542554
}
25552555
}
25562556
}
2557+
2558+
#[test]
2559+
fn parse_mssql_begin_end_block() {
2560+
// Single statement
2561+
let sql = "BEGIN SELECT 1; END";
2562+
let stmt = ms().verified_stmt(sql);
2563+
match &stmt {
2564+
Statement::StartTransaction {
2565+
begin,
2566+
has_end_keyword,
2567+
statements,
2568+
transaction,
2569+
modifier,
2570+
..
2571+
} => {
2572+
assert!(begin);
2573+
assert!(has_end_keyword);
2574+
assert!(transaction.is_none());
2575+
assert!(modifier.is_none());
2576+
assert_eq!(statements.len(), 1);
2577+
}
2578+
_ => panic!("Expected StartTransaction, got: {stmt:?}"),
2579+
}
2580+
2581+
// Multiple statements
2582+
let sql = "BEGIN SELECT 1; SELECT 2; END";
2583+
let stmt = ms().verified_stmt(sql);
2584+
match &stmt {
2585+
Statement::StartTransaction {
2586+
statements,
2587+
has_end_keyword,
2588+
..
2589+
} => {
2590+
assert!(has_end_keyword);
2591+
assert_eq!(statements.len(), 2);
2592+
}
2593+
_ => panic!("Expected StartTransaction, got: {stmt:?}"),
2594+
}
2595+
2596+
// DML inside BEGIN/END
2597+
let sql = "BEGIN INSERT INTO t VALUES (1); UPDATE t SET x = 2; END";
2598+
let stmt = ms().verified_stmt(sql);
2599+
match &stmt {
2600+
Statement::StartTransaction {
2601+
statements,
2602+
has_end_keyword,
2603+
..
2604+
} => {
2605+
assert!(has_end_keyword);
2606+
assert_eq!(statements.len(), 2);
2607+
}
2608+
_ => panic!("Expected StartTransaction, got: {stmt:?}"),
2609+
}
2610+
2611+
// BEGIN TRANSACTION still works
2612+
let sql = "BEGIN TRANSACTION";
2613+
let stmt = ms().verified_stmt(sql);
2614+
match &stmt {
2615+
Statement::StartTransaction {
2616+
begin,
2617+
has_end_keyword,
2618+
transaction,
2619+
..
2620+
} => {
2621+
assert!(begin);
2622+
assert!(!has_end_keyword);
2623+
assert!(transaction.is_some());
2624+
}
2625+
_ => panic!("Expected StartTransaction, got: {stmt:?}"),
2626+
}
2627+
}

0 commit comments

Comments
 (0)