Skip to content

Commit 685a7a0

Browse files
committed
Add the option for the parser to try and parse an expression as identifier if the expression parsing fails
1 parent 3a8369a commit 685a7a0

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>,
@@ -1432,6 +1434,7 @@ impl fmt::Display for Expr {
14321434
write!(f, "{expr}::{data_type}")
14331435
}
14341436
},
1437+
Expr::Default => write!(f, "DEFAULT"),
14351438
Expr::Extract {
14361439
field,
14371440
syntax,

src/dialect/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,12 @@ pub trait Dialect: Debug + Any {
622622
fn supports_boolean_literals(&self) -> bool {
623623
true
624624
}
625+
626+
/// Returns true if the specified keyword is reserved and cannot be
627+
/// used as an identifier without special handling like quoting.
628+
fn is_reserved_for_identifier(&self, kw: Keyword) -> bool {
629+
keywords::RESERVED_FOR_IDENTIFIER.contains(&kw)
630+
}
625631
}
626632

627633
/// 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;
@@ -203,6 +205,16 @@ impl Dialect for SnowflakeDialect {
203205
fn allow_extract_single_quotes(&self) -> bool {
204206
true
205207
}
208+
209+
fn is_reserved_for_identifier(&self, kw: Keyword) -> bool {
210+
// Unreserve some keywords that Snowflake accepts as identifiers
211+
// See: https://docs.snowflake.com/en/sql-reference/reserved-keywords
212+
if matches!(kw, Keyword::INTERVAL) {
213+
false
214+
} else {
215+
RESERVED_FOR_IDENTIFIER.contains(&kw)
216+
}
217+
}
206218
}
207219

208220
/// Parse snowflake create table statement.

src/keywords.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -939,3 +939,13 @@ pub const RESERVED_FOR_COLUMN_ALIAS: &[Keyword] = &[
939939
Keyword::INTO,
940940
Keyword::END,
941941
];
942+
943+
/// Global list of reserved keywords that cannot be parsed as identifiers
944+
/// without special handling like quoting. Parser should call `Dialect::is_reserved_for_identifier`
945+
/// to allow for each dialect to customize the list.
946+
pub const RESERVED_FOR_IDENTIFIER: &[Keyword] = &[
947+
Keyword::EXISTS,
948+
Keyword::INTERVAL,
949+
Keyword::STRUCT,
950+
Keyword::TRIM,
951+
];

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
@@ -1744,10 +1744,7 @@ fn parse_merge() {
17441744
columns: vec![Ident::new("a"), Ident::new("b"),],
17451745
kind: MergeInsertKind::Values(Values {
17461746
explicit_row: false,
1747-
rows: vec![vec![
1748-
Expr::Value(number("1")),
1749-
Expr::Identifier(Ident::new("DEFAULT")),
1750-
]]
1747+
rows: vec![vec![Expr::Value(number("1")), Expr::Default,]]
17511748
})
17521749
})
17531750
},
@@ -1758,10 +1755,7 @@ fn parse_merge() {
17581755
columns: vec![],
17591756
kind: MergeInsertKind::Values(Values {
17601757
explicit_row: false,
1761-
rows: vec![vec![
1762-
Expr::Value(number("1")),
1763-
Expr::Identifier(Ident::new("DEFAULT")),
1764-
]]
1758+
rows: vec![vec![Expr::Value(number("1")), Expr::Default,]]
17651759
})
17661760
})
17671761
},

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::{
@@ -5071,7 +5071,9 @@ fn parse_interval_dont_require_unit() {
50715071

50725072
#[test]
50735073
fn parse_interval_require_unit() {
5074-
let dialects = all_dialects_where(|d| d.require_interval_qualifier());
5074+
let dialects = all_dialects_where(|d| {
5075+
d.require_interval_qualifier() && d.is_reserved_for_identifier(Keyword::INTERVAL)
5076+
});
50755077

50765078
let sql = "SELECT INTERVAL '1 DAY'";
50775079
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

@@ -4290,10 +4287,7 @@ fn test_simple_postgres_insert_with_alias() {
42904287
body: Box::new(SetExpr::Values(Values {
42914288
explicit_row: false,
42924289
rows: vec![vec![
4293-
Expr::Identifier(Ident {
4294-
value: "DEFAULT".to_string(),
4295-
quote_style: None
4296-
}),
4290+
Expr::Default,
42974291
Expr::Value(Value::Number("123".to_string(), false))
42984292
]]
42994293
})),
@@ -4424,10 +4418,7 @@ fn test_simple_insert_with_quoted_alias() {
44244418
body: Box::new(SetExpr::Values(Values {
44254419
explicit_row: false,
44264420
rows: vec![vec![
4427-
Expr::Identifier(Ident {
4428-
value: "DEFAULT".to_string(),
4429-
quote_style: None
4430-
}),
4421+
Expr::Default,
44314422
Expr::Value(Value::SingleQuotedString("0123".to_string()))
44324423
]]
44334424
})),

0 commit comments

Comments
 (0)