diff --git a/src/dialect/snowflake.rs b/src/dialect/snowflake.rs index f756c4159..6c160a9dd 100644 --- a/src/dialect/snowflake.rs +++ b/src/dialect/snowflake.rs @@ -247,6 +247,17 @@ impl Dialect for SnowflakeDialect { fn parse_statement(&self, parser: &mut Parser) -> Option> { if parser.parse_keyword(Keyword::BEGIN) { + // Snowflake supports both `BEGIN TRANSACTION` and `BEGIN ... END` blocks. + // If the next keyword indicates a transaction statement, let the + // standard parse_begin() handle it. + if parser + .peek_one_of_keywords(&[Keyword::TRANSACTION, Keyword::WORK, Keyword::NAME]) + .is_some() + || matches!(parser.peek_token_ref().token, Token::SemiColon | Token::EOF) + { + parser.prev_token(); + return None; + } return Some(parser.parse_begin_exception_end()); } diff --git a/tests/sqlparser_snowflake.rs b/tests/sqlparser_snowflake.rs index c51cf3bdf..022c644a4 100644 --- a/tests/sqlparser_snowflake.rs +++ b/tests/sqlparser_snowflake.rs @@ -4610,6 +4610,27 @@ END assert_eq!(2, exception[1].statements.len()); } +#[test] +fn test_begin_transaction() { + snowflake().verified_stmt("BEGIN TRANSACTION"); + snowflake().verified_stmt("BEGIN WORK"); + + // BEGIN TRANSACTION with statements + let stmts = snowflake() + .parse_sql_statements("BEGIN TRANSACTION; DROP TABLE IF EXISTS bla; COMMIT") + .unwrap(); + assert_eq!(3, stmts.len()); + + // Bare BEGIN (no TRANSACTION keyword) with statements + let stmts = snowflake() + .parse_sql_statements("BEGIN; DROP TABLE IF EXISTS bla; COMMIT") + .unwrap(); + assert_eq!(3, stmts.len()); + + // Bare BEGIN at EOF (no semicolon, no TRANSACTION keyword) + snowflake().verified_stmt("BEGIN"); +} + #[test] fn test_snowflake_fetch_clause_syntax() { let canonical = "SELECT c1 FROM fetch_test FETCH FIRST 2 ROWS ONLY";