Skip to content

Commit 787e396

Browse files
committed
Add the option for the parser to try and parse an expression as identifier if the expression parsing fails
1 parent e2197ee commit 787e396

File tree

8 files changed

+250
-185
lines changed

8 files changed

+250
-185
lines changed

src/ast/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,8 @@ pub enum Expr {
694694
// https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements#formatting_syntax
695695
format: Option<CastFormat>,
696696
},
697+
/// `DEFAULT` value of a column e.g. INSERT INTO tbl (a, b) VALUES ('foo', DEFAULT)
698+
Default,
697699
/// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
698700
AtTimeZone {
699701
timestamp: Box<Expr>,
@@ -1431,6 +1433,7 @@ impl fmt::Display for Expr {
14311433
write!(f, "{expr}::{data_type}")
14321434
}
14331435
},
1436+
Expr::Default => write!(f, "DEFAULT"),
14341437
Expr::Extract {
14351438
field,
14361439
syntax,

src/dialect/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,12 @@ pub trait Dialect: Debug + Any {
590590
fn supports_try_convert(&self) -> bool {
591591
false
592592
}
593+
594+
/// Returns true if the specified keyword is reserved and cannot be
595+
/// used as an identifier without special handling like quoting.
596+
fn is_reserved_for_identifier(&self, kw: Keyword) -> bool {
597+
keywords::RESERVED_FOR_IDENTIFIER.contains(&kw)
598+
}
593599
}
594600

595601
/// 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
@@ -936,3 +936,13 @@ pub const RESERVED_FOR_COLUMN_ALIAS: &[Keyword] = &[
936936
Keyword::INTO,
937937
Keyword::END,
938938
];
939+
940+
/// Global list of reserved keywords that cannot be parsed as identifiers
941+
/// without special handling like quoting. Parser should call `Dialect::is_reserved_for_identifier`
942+
/// to allow for each dialect to customize the list.
943+
pub const RESERVED_FOR_IDENTIFIER: &[Keyword] = &[
944+
Keyword::EXISTS,
945+
Keyword::INTERVAL,
946+
Keyword::STRUCT,
947+
Keyword::TRIM,
948+
];

src/parser/mod.rs

Lines changed: 204 additions & 163 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: 10 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::{
@@ -5103,7 +5103,9 @@ fn parse_interval_dont_require_unit() {
51035103

51045104
#[test]
51055105
fn parse_interval_require_unit() {
5106-
let dialects = all_dialects_where(|d| d.require_interval_qualifier());
5106+
let dialects = all_dialects_where(|d| {
5107+
d.require_interval_qualifier() && d.is_reserved_for_identifier(Keyword::INTERVAL)
5108+
});
51075109

51085110
let sql = "SELECT INTERVAL '1 DAY'";
51095111
let err = dialects.parse_sql_statements(sql).unwrap_err();
@@ -11399,3 +11401,9 @@ fn test_show_dbs_schemas_tables_views() {
1139911401
verified_stmt("SHOW MATERIALIZED VIEWS FROM db1");
1140011402
verified_stmt("SHOW MATERIALIZED VIEWS FROM db1 'abc'");
1140111403
}
11404+
11405+
#[test]
11406+
fn test_expr_prefix_ambiguity() {
11407+
all_dialects_where(|d| !d.is_reserved_for_identifier(Keyword::INTERVAL))
11408+
.verified_stmt("SELECT MAX(interval) FROM tbl");
11409+
}

tests/sqlparser_postgres.rs

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

@@ -4284,10 +4281,7 @@ fn test_simple_postgres_insert_with_alias() {
42844281
body: Box::new(SetExpr::Values(Values {
42854282
explicit_row: false,
42864283
rows: vec![vec![
4287-
Expr::Identifier(Ident {
4288-
value: "DEFAULT".to_string(),
4289-
quote_style: None
4290-
}),
4284+
Expr::Default,
42914285
Expr::Value(Value::Number("123".to_string(), false))
42924286
]]
42934287
})),
@@ -4418,10 +4412,7 @@ fn test_simple_insert_with_quoted_alias() {
44184412
body: Box::new(SetExpr::Values(Values {
44194413
explicit_row: false,
44204414
rows: vec![vec![
4421-
Expr::Identifier(Ident {
4422-
value: "DEFAULT".to_string(),
4423-
quote_style: None
4424-
}),
4415+
Expr::Default,
44254416
Expr::Value(Value::SingleQuotedString("0123".to_string()))
44264417
]]
44274418
})),

0 commit comments

Comments
 (0)