Re: [PR] Extend exception handling [datafusion-sqlparser-rs]

2025-06-21 Thread via GitHub


alamb commented on PR #1884:
URL: 
https://github.com/apache/datafusion-sqlparser-rs/pull/1884#issuecomment-2993508239

   🚀 


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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



Re: [PR] Extend exception handling [datafusion-sqlparser-rs]

2025-06-20 Thread via GitHub


iffyio merged PR #1884:
URL: https://github.com/apache/datafusion-sqlparser-rs/pull/1884


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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



Re: [PR] Extend exception handling [datafusion-sqlparser-rs]

2025-06-17 Thread via GitHub


bombsimon commented on code in PR #1884:
URL: 
https://github.com/apache/datafusion-sqlparser-rs/pull/1884#discussion_r2152230149


##
src/ast/mod.rs:
##
@@ -3670,17 +3727,24 @@ pub enum Statement {
 /// END;
 /// ```
 statements: Vec,
-/// Statements of an exception clause.
+/// Exception handling with exception clauses and raises.
 /// Example:
 /// ```sql
 /// BEGIN
 /// SELECT 1;
-/// EXCEPTION WHEN ERROR THEN
-/// SELECT 2;
-/// SELECT 3;
+/// EXCEPTION
+/// WHEN EXCEPTION_1 THEN
+/// SELECT 2;
+/// WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
+/// SELECT 3;
+/// WHEN OTHER THEN
+/// SELECT 4;
+/// RAISE;

Review Comment:
   I went ahead and dropped the new `ExceptionClasue` which then also includes 
the custom handling of `RAISE`. `RAISE` will now be a regular statement in the 
block which I actually THINK is correct given something like this:
   
   ```sql
   BEGIN
   SELECT 1;
   EXCEPTION
   WHEN EXCEPTION_1 THEN
   SELECT 1;
   RAISE SOME_OTHER_EX;
   RAISE;
   END;
   ```
   
   With this I moved all the `ExceptionWhen` directly under the 
`StartTransaction` similar to previous statement list.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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



Re: [PR] Extend exception handling [datafusion-sqlparser-rs]

2025-06-17 Thread via GitHub


bombsimon commented on code in PR #1884:
URL: 
https://github.com/apache/datafusion-sqlparser-rs/pull/1884#discussion_r2152166881


##
src/ast/mod.rs:
##
@@ -3670,17 +3727,24 @@ pub enum Statement {
 /// END;
 /// ```
 statements: Vec,
-/// Statements of an exception clause.
+/// Exception handling with exception clauses and raises.
 /// Example:
 /// ```sql
 /// BEGIN
 /// SELECT 1;
-/// EXCEPTION WHEN ERROR THEN
-/// SELECT 2;
-/// SELECT 3;
+/// EXCEPTION
+/// WHEN EXCEPTION_1 THEN
+/// SELECT 2;
+/// WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
+/// SELECT 3;
+/// WHEN OTHER THEN
+/// SELECT 4;
+/// RAISE;

Review Comment:
   So what's your conclusion around the quote I pasted from [the BigQuery 
docs](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
   
   > The RAISE statement must only be used within an EXCEPTION clause. The 
RAISE statement will re-raise the exception that was caught, and preserve the 
original stack trace.
   
   We just treat that as semantics and put the raise directly on the 
`StartTransaction` struct together with a `Vec`?
   
   > So that it seems to me that we should be able to leave as is in the 
previous behavior of treating RAISE as a regular statement. 
   
   You mean the `RAISE` should be a regular statement in the last 
`ExceptionWhen`?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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



Re: [PR] Extend exception handling [datafusion-sqlparser-rs]

2025-06-17 Thread via GitHub


iffyio commented on code in PR #1884:
URL: 
https://github.com/apache/datafusion-sqlparser-rs/pull/1884#discussion_r2151944587


##
src/ast/mod.rs:
##
@@ -2982,6 +2982,74 @@ impl From for Statement {
 }
 }
 
+/// An exception representing exception handling with the `EXCEPTION` keyword.
+///
+/// Snowflake: 

+/// BigQuery: 

+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ExceptionClause {
+/// When represents each `WHEN` case
+pub when: Vec,
+/// The exception that is being raised or the current exception being 
handled if `None`.
+///
+/// Example
+/// RAISE;
+/// RAISE MY_EXCEPTION;
+/// RAISE USING MESSAGE = "Some error";

Review Comment:
   Can we wrap this in a sql codeblock? Also I think it would be useful to show 
the example in the context of the exception when (i.e. illustrating the part of 
the statement does this property map to) vs a standalone statement (which is 
already documented elsewhere)



##
src/ast/mod.rs:
##
@@ -2982,6 +2982,74 @@ impl From for Statement {
 }
 }
 
+/// An exception representing exception handling with the `EXCEPTION` keyword.
+///
+/// Snowflake: 

+/// BigQuery: 

+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ExceptionClause {
+/// When represents each `WHEN` case
+pub when: Vec,
+/// The exception that is being raised or the current exception being 
handled if `None`.
+///
+/// Example
+/// RAISE;
+/// RAISE MY_EXCEPTION;
+/// RAISE USING MESSAGE = "Some error";
+///
+/// BigQuery: 

+/// Snowflake: 

+// pub raises: Option>,
+pub raises: Option>,
+}
+
+impl Display for ExceptionClause {
+fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+write!(f, " EXCEPTION")?;
+for w in &self.when {
+write!(f, "{w}")?;
+}
+
+if let Some(raises) = &self.raises {
+write!(f, " {raises};")?;
+}
+
+Ok(())
+}
+}
+
+/// A representation of a `WHEN` arm with all the identifiers catched and the 
statements to execute
+/// for the arm.
+///
+/// Snowflake: 

+/// BigQuery: 

+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ExceptionWhen {
+pub idents: Vec,
+pub statements: Vec,
+}
+
+impl Display for ExceptionWhen {
+fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+write!(
+f,
+" WHEN {idents} THEN",

Review Comment:
   ```suggestion
   "WHEN {idents} THEN",
   ```
   display wise its better to have the display impl self contained (the caller 
should write the leading space when needed), that makes it easier to display 
the same struct in other contexts



##
src/ast/mod.rs:
##
@@ -3670,17 +3727,24 @@ pub enum Statement {
 /// END;
 /// ```
 statements: Vec,
-/// Statements of an exception clause.
+/// Exception handling with exception clauses and raises.
 /// Example:
 /// ```sql
 /// BEGIN
 /// SELECT 1;
-/// EXCEPTION WHEN ERROR THEN
-/// SELECT 2;
-/// SELECT 3;
+/// EXCEPTION
+/// WHEN EXCEPTION_1 THEN
+/// SELECT 2;
+/// WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
+/// SELECT 3;
+/// WHEN OTHER THEN
+/// SELECT 4;
+/// RAISE;

Review Comment:
   looking at snowflake and bigquery docs there doest seem to be a need for 
treat raise specially from what i can tell.
   
   snowflake: their example 
[here](https://docs.snowflake.com/en/developer-guide/snowflake-scripting/exceptions#raising-the-same-exception-again-in-an-exception-handler)
 shows raise as a regular statement in the statement list.
   
   bigquery: their 
[spec](https://cloud.google.com/bigquery/docs/reference/standard-sql

Re: [PR] Extend exception handling [datafusion-sqlparser-rs]

2025-06-16 Thread via GitHub


bombsimon commented on code in PR #1884:
URL: 
https://github.com/apache/datafusion-sqlparser-rs/pull/1884#discussion_r2150350430


##
src/ast/mod.rs:
##
@@ -2982,6 +2982,63 @@ impl From for Statement {
 }
 }
 
+/// An exception representing exception handling with the `EXCEPTION` keyword.
+///
+/// Snowflake: 

+/// BigQuery: 

+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct Exception {
+pub when: Vec,
+pub raises: Option>,

Review Comment:
   Added a description.
   
   Initially I used `Option>` because you can either do bare 
`RAISE` which re-reases the exception currently handled _or_ you can do `RASIE 
SOME_EXCEPTION` which reaises `SOME_EXCEPTION`.
   
   For BigQuery however this is a bit more complex, there you can something 
like this which was solved by using the already existing 
[`parse_raise_stmt`](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise).
   
   ```sql
   RAISE USING MESSAGE = FORMAT('Some issue: %s', i)
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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



Re: [PR] Extend exception handling [datafusion-sqlparser-rs]

2025-06-16 Thread via GitHub


bombsimon commented on code in PR #1884:
URL: 
https://github.com/apache/datafusion-sqlparser-rs/pull/1884#discussion_r2150374474


##
tests/sqlparser_common.rs:
##
@@ -8593,7 +8593,7 @@ fn lateral_function() {
 fn parse_start_transaction() {
 let dialects = all_dialects_except(|d|
 // BigQuery does not support this syntax
-d.is::());
+d.is::() || d.is::());

Review Comment:
   Updated comment with Snowflake and added links to respective docs.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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



Re: [PR] Extend exception handling [datafusion-sqlparser-rs]

2025-06-16 Thread via GitHub


bombsimon commented on code in PR #1884:
URL: 
https://github.com/apache/datafusion-sqlparser-rs/pull/1884#discussion_r2150373947


##
src/parser/mod.rs:
##
@@ -15096,12 +15096,16 @@ impl<'a> Parser<'a> {
 transaction: Some(BeginTransactionKind::Transaction),
 modifier: None,
 statements: vec![],
-exception_statements: None,
+exception: None,
 has_end_keyword: false,
 })
 }
 
 pub fn parse_begin(&mut self) -> Result {
+if dialect_of!(self is SnowflakeDialect | BigQueryDialect) {

Review Comment:
   I removed the use of `dialect_of!` macro and added it back to 
`parse_statement` for Snowflake and BigQuery. This means that it will still not 
work on `GenericDialect` but I assume that is correct?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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



Re: [PR] Extend exception handling [datafusion-sqlparser-rs]

2025-06-16 Thread via GitHub


bombsimon commented on code in PR #1884:
URL: 
https://github.com/apache/datafusion-sqlparser-rs/pull/1884#discussion_r2150371186


##
src/ast/mod.rs:
##
@@ -3670,17 +3727,24 @@ pub enum Statement {
 /// END;
 /// ```
 statements: Vec,
-/// Statements of an exception clause.
+/// Exception handling with exception clauses and raises.
 /// Example:
 /// ```sql
 /// BEGIN
 /// SELECT 1;
-/// EXCEPTION WHEN ERROR THEN
-/// SELECT 2;
-/// SELECT 3;
+/// EXCEPTION
+/// WHEN EXCEPTION_1 THEN
+/// SELECT 2;
+/// WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
+/// SELECT 3;
+/// WHEN OTHER THEN
+/// SELECT 4;
+/// RAISE;

Review Comment:
   An exception is represented by an `ExceptionClause` which consists of a 
`Vec` of `ExceptionWhen` (each `WHEN` arm and its statements) and a potential 
`RAISE` statement.
   
   For BigQuery, [the 
docs](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
 says this which I interpreted as it can't be used without `EXCEPTION`:
   
   > **When USING MESSAGE isn't supplied**
   > The RAISE statement must only be used within an EXCEPTION clause. The 
RAISE statement will re-raise the exception that was caught, and preserve the 
original stack trace.
   
   For Snowflake we could likely do this, but there are other concerns. I know 
the parser isn't requiring _valid_ syntax, but since this specific `RAISE` is 
within error handling where you can omit the exception and re-raise what's 
being handled, I think it makes more sense to put it here. I would thing that 
if the `RAISE` was on the `StartTransaction` we would always have an exception 
as described in the [Snowflake 
docs](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise). 
It's mentioned 
[here](https://docs.snowflake.com/en/developer-guide/snowflake-scripting/exceptions#raising-the-same-exception-again-in-an-exception-handler).
   
   If I move the `RAISE` to the `StartTransaction`, should I allow it both with 
and without re-raising and should I move the `Vec` directly 
under `StartTransaction` as well?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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



Re: [PR] Extend exception handling [datafusion-sqlparser-rs]

2025-06-16 Thread via GitHub


bombsimon commented on code in PR #1884:
URL: 
https://github.com/apache/datafusion-sqlparser-rs/pull/1884#discussion_r2150372100


##
src/ast/mod.rs:
##
@@ -2982,6 +2982,63 @@ impl From for Statement {
 }
 }
 
+/// An exception representing exception handling with the `EXCEPTION` keyword.
+///
+/// Snowflake: 

+/// BigQuery: 

+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct Exception {
+pub when: Vec,
+pub raises: Option>,
+}
+
+impl Display for Exception {
+fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+write!(f, " EXCEPTION")?;
+for w in &self.when {
+write!(f, "{w}")?;
+}
+
+if let Some(raises) = &self.raises {
+write!(f, " {raises};")?;
+}
+
+Ok(())
+}
+}
+
+/// A representation of a `WHEN` arm with all the identifiers catched and the 
statements to execute
+/// for the arm.
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ExceptionWhen {
+pub idents: Vec,
+pub statements: Vec,
+}
+
+impl Display for ExceptionWhen {
+fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+let idents = self
+.idents
+.iter()
+.map(ToString::to_string)
+.collect::>()
+.join(" OR ");

Review Comment:
   Oh of course, only knew about `display_comma_separated` and didn't know this 
was a trait. Sorry for not looking further through the code! 🙈 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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



Re: [PR] Extend exception handling [datafusion-sqlparser-rs]

2025-06-16 Thread via GitHub


bombsimon commented on code in PR #1884:
URL: 
https://github.com/apache/datafusion-sqlparser-rs/pull/1884#discussion_r2150350430


##
src/ast/mod.rs:
##
@@ -2982,6 +2982,63 @@ impl From for Statement {
 }
 }
 
+/// An exception representing exception handling with the `EXCEPTION` keyword.
+///
+/// Snowflake: 

+/// BigQuery: 

+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct Exception {
+pub when: Vec,
+pub raises: Option>,

Review Comment:
   Added a description.
   
   Initially I used `Option>` because you can either do bare 
`RAISE` which re-reases the exception currently handled _or_ you can do `RASIE 
SOME_EXCEPTION` which reaises `SOME_EXCEPTION`.
   
   For BigQuery however this is a bit more complex, there you can something 
like this which was solved by using the already existing 
[`parse_raise_stmt`](https://github.com/apache/datafusion-sqlparser-rs/blob/23350bd8d8ee1ff87e2cacb6c9654a9ba1ab76a4/src/parser/mod.rs?plain=1#L786-L800).
   
   ```sql
   RAISE USING MESSAGE = FORMAT('Some issue: %s', i)
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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



Re: [PR] Extend exception handling [datafusion-sqlparser-rs]

2025-06-16 Thread via GitHub


bombsimon commented on code in PR #1884:
URL: 
https://github.com/apache/datafusion-sqlparser-rs/pull/1884#discussion_r2150344133


##
src/ast/mod.rs:
##
@@ -2982,6 +2982,63 @@ impl From for Statement {
 }
 }
 
+/// An exception representing exception handling with the `EXCEPTION` keyword.
+///
+/// Snowflake: 

+/// BigQuery: 

+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct Exception {
+pub when: Vec,
+pub raises: Option>,
+}
+
+impl Display for Exception {
+fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+write!(f, " EXCEPTION")?;
+for w in &self.when {
+write!(f, "{w}")?;
+}
+
+if let Some(raises) = &self.raises {
+write!(f, " {raises};")?;
+}
+
+Ok(())
+}
+}
+
+/// A representation of a `WHEN` arm with all the identifiers catched and the 
statements to execute
+/// for the arm.

Review Comment:
   Added same references!



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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



Re: [PR] Extend exception handling [datafusion-sqlparser-rs]

2025-06-16 Thread via GitHub


iffyio commented on code in PR #1884:
URL: 
https://github.com/apache/datafusion-sqlparser-rs/pull/1884#discussion_r2149643500


##
src/ast/mod.rs:
##
@@ -2982,6 +2982,63 @@ impl From for Statement {
 }
 }
 
+/// An exception representing exception handling with the `EXCEPTION` keyword.
+///
+/// Snowflake: 

+/// BigQuery: 

+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct Exception {

Review Comment:
   ```suggestion
   pub struct ExceptionClause {
   ```



##
src/ast/mod.rs:
##
@@ -2982,6 +2982,63 @@ impl From for Statement {
 }
 }
 
+/// An exception representing exception handling with the `EXCEPTION` keyword.
+///
+/// Snowflake: 

+/// BigQuery: 

+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct Exception {
+pub when: Vec,
+pub raises: Option>,

Review Comment:
   Can we add a description what raises refers to here? thinking since its 
being represetned as a box statement it won't be obvious



##
src/ast/mod.rs:
##
@@ -2982,6 +2982,63 @@ impl From for Statement {
 }
 }
 
+/// An exception representing exception handling with the `EXCEPTION` keyword.
+///
+/// Snowflake: 

+/// BigQuery: 

+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct Exception {
+pub when: Vec,
+pub raises: Option>,
+}
+
+impl Display for Exception {
+fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+write!(f, " EXCEPTION")?;
+for w in &self.when {
+write!(f, "{w}")?;
+}
+
+if let Some(raises) = &self.raises {
+write!(f, " {raises};")?;
+}
+
+Ok(())
+}
+}
+
+/// A representation of a `WHEN` arm with all the identifiers catched and the 
statements to execute
+/// for the arm.
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ExceptionWhen {
+pub idents: Vec,
+pub statements: Vec,
+}
+
+impl Display for ExceptionWhen {
+fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+let idents = self
+.idents
+.iter()
+.map(ToString::to_string)
+.collect::>()
+.join(" OR ");
+
+write!(f, " WHEN {idents} THEN", idents = idents)?;

Review Comment:
   ```suggestion
   write!(f, " WHEN {idents} THEN")?;
   ```



##
src/parser/mod.rs:
##
@@ -15096,12 +15096,16 @@ impl<'a> Parser<'a> {
 transaction: Some(BeginTransactionKind::Transaction),
 modifier: None,
 statements: vec![],
-exception_statements: None,
+exception: None,
 has_end_keyword: false,
 })
 }
 
 pub fn parse_begin(&mut self) -> Result {
+if dialect_of!(self is SnowflakeDialect | BigQueryDialect) {

Review Comment:
   the `dialect_of` macro is discouraged for new code, for dialect-specific 
functionality we would use a method on the Dialect trait - but I don't think 
that would work too well in this case, I think we can use the previous pattern 
of having the dialect call the method instead (i.e the parse_statement approach)



##
src/ast/mod.rs:
##
@@ -3670,17 +3727,24 @@ pub enum Statement {
 /// END;
 /// ```
 statements: Vec,
-/// Statements of an exception clause.
+/// Exception handling with exception clauses and raises.
 /// Example:
 /// ```sql
 /// BEGIN
 /// SELECT 1;
-/// EXCEPTION WHEN ERROR THEN
-/// SELECT 2;
-/// SELECT 3;
+/// EXCEPTION
+/// WHEN EXCEPTION_1 THEN
+/// SELECT 2;
+/// WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
+/// SELECT 3;
+/// WHEN OTHER THEN
+/// SELECT 4;
+/// RAISE;

Review Comment:
   given the syntax example, Im not sure I see the requirement for the 
introduced `