Skip to content

Commit f184eff

Browse files
committed
Wrap Throw in named ThrowStatement struct
Signed-off-by: Guan-Ming (Wesley) Chiu <105915352+guan404ming@users.noreply.github.com>
1 parent 379434a commit f184eff

4 files changed

Lines changed: 74 additions & 54 deletions

File tree

src/ast/mod.rs

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2816,6 +2816,41 @@ impl fmt::Display for RaiseStatementValue {
28162816
}
28172817
}
28182818

2819+
/// A MSSQL `THROW` statement.
2820+
///
2821+
/// ```sql
2822+
/// THROW [ error_number, message, state ]
2823+
/// ```
2824+
///
2825+
/// [MSSQL](https://learn.microsoft.com/en-us/sql/t-sql/language-elements/throw-transact-sql)
2826+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2827+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2828+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
2829+
pub struct ThrowStatement {
2830+
/// Error number expression.
2831+
pub error_number: Option<Box<Expr>>,
2832+
/// Error message expression.
2833+
pub message: Option<Box<Expr>>,
2834+
/// State expression.
2835+
pub state: Option<Box<Expr>>,
2836+
}
2837+
2838+
impl fmt::Display for ThrowStatement {
2839+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2840+
let ThrowStatement {
2841+
error_number,
2842+
message,
2843+
state,
2844+
} = self;
2845+
2846+
write!(f, "THROW")?;
2847+
if let (Some(error_number), Some(message), Some(state)) = (error_number, message, state) {
2848+
write!(f, " {error_number}, {message}, {state}")?;
2849+
}
2850+
Ok(())
2851+
}
2852+
}
2853+
28192854
/// Represents an expression assignment within a variable `DECLARE` statement.
28202855
///
28212856
/// Examples:
@@ -4676,19 +4711,8 @@ pub enum Statement {
46764711
/// Additional `WITH` options for RAISERROR.
46774712
options: Vec<RaisErrorOption>,
46784713
},
4679-
/// Throw (MSSQL)
4680-
/// ```sql
4681-
/// THROW [ error_number, message, state ]
4682-
/// ```
4683-
/// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/throw-transact-sql>
4684-
Throw {
4685-
/// Error number expression.
4686-
error_number: Option<Box<Expr>>,
4687-
/// Error message expression.
4688-
message: Option<Box<Expr>>,
4689-
/// State expression.
4690-
state: Option<Box<Expr>>,
4691-
},
4714+
/// A MSSQL `THROW` statement.
4715+
Throw(ThrowStatement),
46924716
/// ```sql
46934717
/// PRINT msg_str | @local_variable | string_expr
46944718
/// ```
@@ -6133,19 +6157,7 @@ impl fmt::Display for Statement {
61336157
}
61346158
Ok(())
61356159
}
6136-
Statement::Throw {
6137-
error_number,
6138-
message,
6139-
state,
6140-
} => {
6141-
write!(f, "THROW")?;
6142-
if let (Some(error_number), Some(message), Some(state)) =
6143-
(error_number, message, state)
6144-
{
6145-
write!(f, " {error_number}, {message}, {state}")?;
6146-
}
6147-
Ok(())
6148-
}
6160+
Statement::Throw(s) => write!(f, "{s}"),
61496161
Statement::Print(s) => write!(f, "{s}"),
61506162
Statement::Return(r) => write!(f, "{r}"),
61516163
Statement::List(command) => write!(f, "LIST {command}"),
@@ -11676,6 +11688,12 @@ impl From<RaiseStatement> for Statement {
1167611688
}
1167711689
}
1167811690

11691+
impl From<ThrowStatement> for Statement {
11692+
fn from(t: ThrowStatement) -> Self {
11693+
Self::Throw(t)
11694+
}
11695+
}
11696+
1167911697
impl From<Function> for Statement {
1168011698
fn from(f: Function) -> Self {
1168111699
Self::Call(f)

src/ast/spans.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ impl Spanned for Statement {
481481
Statement::UNLISTEN { .. } => Span::empty(),
482482
Statement::RenameTable { .. } => Span::empty(),
483483
Statement::RaisError { .. } => Span::empty(),
484-
Statement::Throw { .. } => Span::empty(),
484+
Statement::Throw(_) => Span::empty(),
485485
Statement::Print { .. } => Span::empty(),
486486
Statement::Return { .. } => Span::empty(),
487487
Statement::List(..) | Statement::Remove(..) => Span::empty(),

src/parser/mod.rs

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,10 @@ impl<'a> Parser<'a> {
670670
Keyword::RELEASE => self.parse_release(),
671671
Keyword::COMMIT => self.parse_commit(),
672672
Keyword::RAISERROR => Ok(self.parse_raiserror()?),
673-
Keyword::THROW => Ok(self.parse_throw()?),
673+
Keyword::THROW => {
674+
self.prev_token();
675+
self.parse_throw().map(Into::into)
676+
}
674677
Keyword::ROLLBACK => self.parse_rollback(),
675678
Keyword::ASSERT => self.parse_assert(),
676679
// `PREPARE`, `EXECUTE` and `DEALLOCATE` are Postgres-specific
@@ -18261,28 +18264,27 @@ impl<'a> Parser<'a> {
1826118264
}
1826218265
}
1826318266

18264-
/// Parse a MSSQL `THROW` statement
18265-
/// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/throw-transact-sql>
18266-
pub fn parse_throw(&mut self) -> Result<Statement, ParserError> {
18267-
// THROW with no arguments is a re-throw inside a CATCH block
18268-
if self.peek_token_ref().token == Token::SemiColon
18269-
|| self.peek_token_ref().token == Token::EOF
18270-
{
18271-
return Ok(Statement::Throw {
18272-
error_number: None,
18273-
message: None,
18274-
state: None,
18275-
});
18276-
}
18277-
let error_number = Box::new(self.parse_expr()?);
18278-
self.expect_token(&Token::Comma)?;
18279-
let message = Box::new(self.parse_expr()?);
18280-
self.expect_token(&Token::Comma)?;
18281-
let state = Box::new(self.parse_expr()?);
18282-
Ok(Statement::Throw {
18283-
error_number: Some(error_number),
18284-
message: Some(message),
18285-
state: Some(state),
18267+
/// Parse a MSSQL `THROW` statement.
18268+
///
18269+
/// See [Statement::Throw]
18270+
pub fn parse_throw(&mut self) -> Result<ThrowStatement, ParserError> {
18271+
self.expect_keyword_is(Keyword::THROW)?;
18272+
18273+
let error_number = self.maybe_parse(|p| p.parse_expr().map(Box::new))?;
18274+
let (message, state) = if error_number.is_some() {
18275+
self.expect_token(&Token::Comma)?;
18276+
let message = Box::new(self.parse_expr()?);
18277+
self.expect_token(&Token::Comma)?;
18278+
let state = Box::new(self.parse_expr()?);
18279+
(Some(message), Some(state))
18280+
} else {
18281+
(None, None)
18282+
};
18283+
18284+
Ok(ThrowStatement {
18285+
error_number,
18286+
message,
18287+
state,
1828618288
})
1828718289
}
1828818290

tests/sqlparser_mssql.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1672,7 +1672,7 @@ fn test_parse_throw() {
16721672
let s = ms().verified_stmt(sql);
16731673
assert_eq!(
16741674
s,
1675-
Statement::Throw {
1675+
Statement::Throw(ThrowStatement {
16761676
error_number: Some(Box::new(Expr::Value(
16771677
(Value::Number("51000".parse().unwrap(), false)).with_empty_span()
16781678
))),
@@ -1682,7 +1682,7 @@ fn test_parse_throw() {
16821682
state: Some(Box::new(Expr::Value(
16831683
(Value::Number("1".parse().unwrap(), false)).with_empty_span()
16841684
))),
1685-
}
1685+
})
16861686
);
16871687

16881688
// THROW with variable references
@@ -1694,11 +1694,11 @@ fn test_parse_throw() {
16941694
let s = ms().verified_stmt(sql);
16951695
assert_eq!(
16961696
s,
1697-
Statement::Throw {
1697+
Statement::Throw(ThrowStatement {
16981698
error_number: None,
16991699
message: None,
17001700
state: None,
1701-
}
1701+
})
17021702
);
17031703
}
17041704

0 commit comments

Comments
 (0)