Skip to content

Commit dc0d8bf

Browse files
committed
Add the option for the parser to try and parse an expression as identifier if the expression parsing fails
1 parent 62fa860 commit dc0d8bf

File tree

8 files changed

+248
-189
lines changed

8 files changed

+248
-189
lines changed

src/ast/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,8 @@ pub enum Expr {
695695
// https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
696696
format: Option<CastFormat>,
697697
},
698+
/// `DEFAULT` value of a column e.g. INSERT INTO tbl (a, b) VALUES ('foo', DEFAULT)
699+
Default,
698700
/// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
699701
AtTimeZone {
700702
timestamp: Box<Expr>,
@@ -1449,6 +1451,7 @@ impl fmt::Display for Expr {
14491451
write!(f, "{expr}::{data_type}")
14501452
}
14511453
},
1454+
Expr::Default => write!(f, "DEFAULT"),
14521455
Expr::Extract {
14531456
field,
14541457
syntax,

src/dialect/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,12 @@ pub trait Dialect: Debug + Any {
681681
fn supports_partiql(&self) -> bool {
682682
false
683683
}
684+
685+
/// Returns true if the specified keyword is reserved and cannot be
686+
/// used as an identifier without special handling like quoting.
687+
fn is_reserved_for_identifier(&self, kw: Keyword) -> bool {
688+
keywords::RESERVED_FOR_IDENTIFIER.contains(&kw)
689+
}
684690
}
685691

686692
/// This represents the operators for which precedence must be defined

src/dialect/snowflake.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ use alloc::vec::Vec;
3838
#[cfg(not(feature = "std"))]
3939
use alloc::{format, vec};
4040

41+
use super::keywords::RESERVED_FOR_IDENTIFIER;
42+
4143
/// A [`Dialect`] for [Snowflake](https://www.snowflake.com/)
4244
#[derive(Debug, Default)]
4345
pub struct SnowflakeDialect;
@@ -214,6 +216,16 @@ impl Dialect for SnowflakeDialect {
214216
fn supports_show_like_before_in(&self) -> bool {
215217
true
216218
}
219+
220+
fn is_reserved_for_identifier(&self, kw: Keyword) -> bool {
221+
// Unreserve some keywords that Snowflake accepts as identifiers
222+
// See: https://docs.snowflake.com/en/sql-reference/reserved-keywords
223+
if matches!(kw, Keyword::INTERVAL) {
224+
false
225+
} else {
226+
RESERVED_FOR_IDENTIFIER.contains(&kw)
227+
}
228+
}
217229
}
218230

219231
/// Parse snowflake create table statement.

src/keywords.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,3 +948,13 @@ pub const RESERVED_FOR_COLUMN_ALIAS: &[Keyword] = &[
948948
Keyword::INTO,
949949
Keyword::END,
950950
];
951+
952+
/// Global list of reserved keywords that cannot be parsed as identifiers
953+
/// without special handling like quoting. Parser should call `Dialect::is_reserved_for_identifier`
954+
/// to allow for each dialect to customize the list.
955+
pub const RESERVED_FOR_IDENTIFIER: &[Keyword] = &[
956+
Keyword::EXISTS,
957+
Keyword::INTERVAL,
958+
Keyword::STRUCT,
959+
Keyword::TRIM,
960+
];

src/parser/mod.rs

Lines changed: 208 additions & 167 deletions
Large diffs are not rendered by default.

tests/sqlparser_bigquery.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1749,10 +1749,7 @@ fn parse_merge() {
17491749
columns: vec![Ident::new("a"), Ident::new("b"),],
17501750
kind: MergeInsertKind::Values(Values {
17511751
explicit_row: false,
1752-
rows: vec![vec![
1753-
Expr::Value(number("1")),
1754-
Expr::Identifier(Ident::new("DEFAULT")),
1755-
]]
1752+
rows: vec![vec![Expr::Value(number("1")), Expr::Default,]]
17561753
})
17571754
})
17581755
},
@@ -1763,10 +1760,7 @@ fn parse_merge() {
17631760
columns: vec![],
17641761
kind: MergeInsertKind::Values(Values {
17651762
explicit_row: false,
1766-
rows: vec![vec![
1767-
Expr::Value(number("1")),
1768-
Expr::Identifier(Ident::new("DEFAULT")),
1769-
]]
1763+
rows: vec![vec![Expr::Value(number("1")), Expr::Default,]]
17701764
})
17711765
})
17721766
},

tests/sqlparser_common.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use sqlparser::dialect::{
3434
GenericDialect, HiveDialect, MsSqlDialect, MySqlDialect, PostgreSqlDialect, RedshiftSqlDialect,
3535
SQLiteDialect, SnowflakeDialect,
3636
};
37-
use sqlparser::keywords::ALL_KEYWORDS;
37+
use sqlparser::keywords::{Keyword, ALL_KEYWORDS};
3838
use sqlparser::parser::{Parser, ParserError, ParserOptions};
3939
use sqlparser::tokenizer::Tokenizer;
4040
use test_utils::{
@@ -5112,7 +5112,9 @@ fn parse_interval_dont_require_unit() {
51125112

51135113
#[test]
51145114
fn parse_interval_require_unit() {
5115-
let dialects = all_dialects_where(|d| d.require_interval_qualifier());
5115+
let dialects = all_dialects_where(|d| {
5116+
d.require_interval_qualifier() && d.is_reserved_for_identifier(Keyword::INTERVAL)
5117+
});
51165118

51175119
let sql = "SELECT INTERVAL '1 DAY'";
51185120
let err = dialects.parse_sql_statements(sql).unwrap_err();

tests/sqlparser_postgres.rs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,10 +1352,7 @@ fn parse_set() {
13521352
local: false,
13531353
hivevar: false,
13541354
variables: OneOrManyWithParens::One(ObjectName(vec![Ident::new("a")])),
1355-
value: vec![Expr::Identifier(Ident {
1356-
value: "DEFAULT".into(),
1357-
quote_style: None
1358-
})],
1355+
value: vec![Expr::Default],
13591356
}
13601357
);
13611358

@@ -4229,10 +4226,7 @@ fn test_simple_postgres_insert_with_alias() {
42294226
body: Box::new(SetExpr::Values(Values {
42304227
explicit_row: false,
42314228
rows: vec![vec![
4232-
Expr::Identifier(Ident {
4233-
value: "DEFAULT".to_string(),
4234-
quote_style: None
4235-
}),
4229+
Expr::Default,
42364230
Expr::Value(Value::Number("123".to_string(), false))
42374231
]]
42384232
})),
@@ -4363,10 +4357,7 @@ fn test_simple_insert_with_quoted_alias() {
43634357
body: Box::new(SetExpr::Values(Values {
43644358
explicit_row: false,
43654359
rows: vec![vec![
4366-
Expr::Identifier(Ident {
4367-
value: "DEFAULT".to_string(),
4368-
quote_style: None
4369-
}),
4360+
Expr::Default,
43704361
Expr::Value(Value::SingleQuotedString("0123".to_string()))
43714362
]]
43724363
})),

0 commit comments

Comments
 (0)