mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-23 23:44:07 +00:00
Add support for RAISE
statement (#1766)
This commit is contained in:
parent
da5892802f
commit
e3e88290cd
5 changed files with 124 additions and 5 deletions
|
@ -2256,6 +2256,57 @@ impl fmt::Display for ConditionalStatements {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A `RAISE` statement.
|
||||||
|
///
|
||||||
|
/// Examples:
|
||||||
|
/// ```sql
|
||||||
|
/// RAISE USING MESSAGE = 'error';
|
||||||
|
///
|
||||||
|
/// RAISE myerror;
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#raise)
|
||||||
|
/// [Snowflake](https://docs.snowflake.com/en/sql-reference/snowflake-scripting/raise)
|
||||||
|
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||||
|
pub struct RaiseStatement {
|
||||||
|
pub value: Option<RaiseStatementValue>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for RaiseStatement {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let RaiseStatement { value } = self;
|
||||||
|
|
||||||
|
write!(f, "RAISE")?;
|
||||||
|
if let Some(value) = value {
|
||||||
|
write!(f, " {value}")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents the error value of a [RaiseStatement].
|
||||||
|
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
|
||||||
|
pub enum RaiseStatementValue {
|
||||||
|
/// `RAISE USING MESSAGE = 'error'`
|
||||||
|
UsingMessage(Expr),
|
||||||
|
/// `RAISE myerror`
|
||||||
|
Expr(Expr),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for RaiseStatementValue {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
RaiseStatementValue::Expr(expr) => write!(f, "{expr}"),
|
||||||
|
RaiseStatementValue::UsingMessage(expr) => write!(f, "USING MESSAGE = {expr}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents an expression assignment within a variable `DECLARE` statement.
|
/// Represents an expression assignment within a variable `DECLARE` statement.
|
||||||
///
|
///
|
||||||
/// Examples:
|
/// Examples:
|
||||||
|
@ -2827,6 +2878,8 @@ pub enum Statement {
|
||||||
Case(CaseStatement),
|
Case(CaseStatement),
|
||||||
/// An `IF` statement.
|
/// An `IF` statement.
|
||||||
If(IfStatement),
|
If(IfStatement),
|
||||||
|
/// A `RAISE` statement.
|
||||||
|
Raise(RaiseStatement),
|
||||||
/// ```sql
|
/// ```sql
|
||||||
/// CALL <function>
|
/// CALL <function>
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -4142,6 +4195,9 @@ impl fmt::Display for Statement {
|
||||||
Statement::If(stmt) => {
|
Statement::If(stmt) => {
|
||||||
write!(f, "{stmt}")
|
write!(f, "{stmt}")
|
||||||
}
|
}
|
||||||
|
Statement::Raise(stmt) => {
|
||||||
|
write!(f, "{stmt}")
|
||||||
|
}
|
||||||
Statement::AttachDatabase {
|
Statement::AttachDatabase {
|
||||||
schema_name,
|
schema_name,
|
||||||
database_file_name,
|
database_file_name,
|
||||||
|
|
|
@ -32,11 +32,11 @@ use super::{
|
||||||
JoinOperator, JsonPath, JsonPathElem, LateralView, LimitClause, MatchRecognizePattern, Measure,
|
JoinOperator, JsonPath, JsonPathElem, LateralView, LimitClause, MatchRecognizePattern, Measure,
|
||||||
NamedWindowDefinition, ObjectName, ObjectNamePart, Offset, OnConflict, OnConflictAction,
|
NamedWindowDefinition, ObjectName, ObjectNamePart, Offset, OnConflict, OnConflictAction,
|
||||||
OnInsert, OrderBy, OrderByExpr, OrderByKind, Partition, PivotValueSource, ProjectionSelect,
|
OnInsert, OrderBy, OrderByExpr, OrderByKind, Partition, PivotValueSource, ProjectionSelect,
|
||||||
Query, ReferentialAction, RenameSelectItem, ReplaceSelectElement, ReplaceSelectItem, Select,
|
Query, RaiseStatement, RaiseStatementValue, ReferentialAction, RenameSelectItem,
|
||||||
SelectInto, SelectItem, SetExpr, SqlOption, Statement, Subscript, SymbolDefinition, TableAlias,
|
ReplaceSelectElement, ReplaceSelectItem, Select, SelectInto, SelectItem, SetExpr, SqlOption,
|
||||||
TableAliasColumnDef, TableConstraint, TableFactor, TableObject, TableOptionsClustered,
|
Statement, Subscript, SymbolDefinition, TableAlias, TableAliasColumnDef, TableConstraint,
|
||||||
TableWithJoins, UpdateTableFromKind, Use, Value, Values, ViewColumnDef,
|
TableFactor, TableObject, TableOptionsClustered, TableWithJoins, UpdateTableFromKind, Use,
|
||||||
WildcardAdditionalOptions, With, WithFill,
|
Value, Values, ViewColumnDef, WildcardAdditionalOptions, With, WithFill,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Given an iterator of spans, return the [Span::union] of all spans.
|
/// Given an iterator of spans, return the [Span::union] of all spans.
|
||||||
|
@ -337,6 +337,7 @@ impl Spanned for Statement {
|
||||||
} => source.span(),
|
} => source.span(),
|
||||||
Statement::Case(stmt) => stmt.span(),
|
Statement::Case(stmt) => stmt.span(),
|
||||||
Statement::If(stmt) => stmt.span(),
|
Statement::If(stmt) => stmt.span(),
|
||||||
|
Statement::Raise(stmt) => stmt.span(),
|
||||||
Statement::Call(function) => function.span(),
|
Statement::Call(function) => function.span(),
|
||||||
Statement::Copy {
|
Statement::Copy {
|
||||||
source,
|
source,
|
||||||
|
@ -782,6 +783,23 @@ impl Spanned for ConditionalStatements {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Spanned for RaiseStatement {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
let RaiseStatement { value } = self;
|
||||||
|
|
||||||
|
union_spans(value.iter().map(|value| value.span()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Spanned for RaiseStatementValue {
|
||||||
|
fn span(&self) -> Span {
|
||||||
|
match self {
|
||||||
|
RaiseStatementValue::UsingMessage(expr) => expr.span(),
|
||||||
|
RaiseStatementValue::Expr(expr) => expr.span(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// # partial span
|
/// # partial span
|
||||||
///
|
///
|
||||||
/// Missing spans:
|
/// Missing spans:
|
||||||
|
|
|
@ -533,6 +533,7 @@ define_keywords!(
|
||||||
MEDIUMTEXT,
|
MEDIUMTEXT,
|
||||||
MEMBER,
|
MEMBER,
|
||||||
MERGE,
|
MERGE,
|
||||||
|
MESSAGE,
|
||||||
METADATA,
|
METADATA,
|
||||||
METHOD,
|
METHOD,
|
||||||
METRIC,
|
METRIC,
|
||||||
|
@ -695,6 +696,7 @@ define_keywords!(
|
||||||
QUARTER,
|
QUARTER,
|
||||||
QUERY,
|
QUERY,
|
||||||
QUOTE,
|
QUOTE,
|
||||||
|
RAISE,
|
||||||
RAISERROR,
|
RAISERROR,
|
||||||
RANGE,
|
RANGE,
|
||||||
RANK,
|
RANK,
|
||||||
|
|
|
@ -536,6 +536,10 @@ impl<'a> Parser<'a> {
|
||||||
self.prev_token();
|
self.prev_token();
|
||||||
self.parse_if_stmt()
|
self.parse_if_stmt()
|
||||||
}
|
}
|
||||||
|
Keyword::RAISE => {
|
||||||
|
self.prev_token();
|
||||||
|
self.parse_raise_stmt()
|
||||||
|
}
|
||||||
Keyword::SELECT | Keyword::WITH | Keyword::VALUES | Keyword::FROM => {
|
Keyword::SELECT | Keyword::WITH | Keyword::VALUES | Keyword::FROM => {
|
||||||
self.prev_token();
|
self.prev_token();
|
||||||
self.parse_query().map(Statement::Query)
|
self.parse_query().map(Statement::Query)
|
||||||
|
@ -719,6 +723,22 @@ impl<'a> Parser<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a `RAISE` statement.
|
||||||
|
///
|
||||||
|
/// See [Statement::Raise]
|
||||||
|
pub fn parse_raise_stmt(&mut self) -> Result<Statement, ParserError> {
|
||||||
|
self.expect_keyword_is(Keyword::RAISE)?;
|
||||||
|
|
||||||
|
let value = if self.parse_keywords(&[Keyword::USING, Keyword::MESSAGE]) {
|
||||||
|
self.expect_token(&Token::Eq)?;
|
||||||
|
Some(RaiseStatementValue::UsingMessage(self.parse_expr()?))
|
||||||
|
} else {
|
||||||
|
self.maybe_parse(|parser| parser.parse_expr().map(RaiseStatementValue::Expr))?
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Statement::Raise(RaiseStatement { value }))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_comment(&mut self) -> Result<Statement, ParserError> {
|
pub fn parse_comment(&mut self) -> Result<Statement, ParserError> {
|
||||||
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
||||||
|
|
||||||
|
|
|
@ -14298,6 +14298,29 @@ fn parse_if_statement() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_raise_statement() {
|
||||||
|
let sql = "RAISE USING MESSAGE = 42";
|
||||||
|
let Statement::Raise(stmt) = verified_stmt(sql) else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
Some(RaiseStatementValue::UsingMessage(Expr::value(number("42")))),
|
||||||
|
stmt.value
|
||||||
|
);
|
||||||
|
|
||||||
|
verified_stmt("RAISE USING MESSAGE = 'error'");
|
||||||
|
verified_stmt("RAISE myerror");
|
||||||
|
verified_stmt("RAISE 42");
|
||||||
|
verified_stmt("RAISE using");
|
||||||
|
verified_stmt("RAISE");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
ParserError::ParserError("Expected: =, found: error".to_string()),
|
||||||
|
parse_sql_statements("RAISE USING MESSAGE error").unwrap_err()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_lambdas() {
|
fn test_lambdas() {
|
||||||
let dialects = all_dialects_where(|d| d.supports_lambda_functions());
|
let dialects = all_dialects_where(|d| d.supports_lambda_functions());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue