Skip to content

Commit 73120f7

Browse files
committed
Code review comments
1 parent eb9fe84 commit 73120f7

File tree

6 files changed

+74
-84
lines changed

6 files changed

+74
-84
lines changed

src/ast/mod.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -695,8 +695,6 @@ 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,
700698
/// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'`
701699
AtTimeZone {
702700
timestamp: Box<Expr>,
@@ -1451,7 +1449,6 @@ impl fmt::Display for Expr {
14511449
write!(f, "{expr}::{data_type}")
14521450
}
14531451
},
1454-
Expr::Default => write!(f, "DEFAULT"),
14551452
Expr::Extract {
14561453
field,
14571454
syntax,

src/dialect/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ pub trait Dialect: Debug + Any {
680680
fn supports_create_table_select(&self) -> bool {
681681
false
682682
}
683-
683+
684684
/// Returns true if the specified keyword is reserved and cannot be
685685
/// used as an identifier without special handling like quoting.
686686
fn is_reserved_for_identifier(&self, kw: Keyword) -> bool {

src/parser/mod.rs

Lines changed: 59 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,6 @@ pub enum ParserError {
4545
TokenizerError(String),
4646
ParserError(String),
4747
RecursionLimitExceeded,
48-
/// Error indicating that the parsing branch taken
49-
/// did not yield a meaningful result
50-
BranchAbandoned,
5148
}
5249

5350
// avoid clippy type_complexity warnings
@@ -177,7 +174,6 @@ impl fmt::Display for ParserError {
177174
ParserError::TokenizerError(s) => s,
178175
ParserError::ParserError(s) => s,
179176
ParserError::RecursionLimitExceeded => "recursion limit exceeded",
180-
ParserError::BranchAbandoned => "branch abandoned",
181177
}
182178
)
183179
}
@@ -1013,45 +1009,48 @@ impl<'a> Parser<'a> {
10131009
Ok(Statement::NOTIFY { channel, payload })
10141010
}
10151011

1016-
fn parse_expr_by_keyword(&mut self, w: &Word) -> Result<Expr, ParserError> {
1012+
fn parse_expr_prefix_by_reserved_word(
1013+
&mut self,
1014+
w: &Word,
1015+
) -> Result<Option<Expr>, ParserError> {
10171016
match w.keyword {
10181017
Keyword::TRUE | Keyword::FALSE if self.dialect.supports_boolean_literals() => {
10191018
self.prev_token();
1020-
Ok(Expr::Value(self.parse_value()?))
1019+
Ok(Some(Expr::Value(self.parse_value()?)))
10211020
}
10221021
Keyword::NULL => {
10231022
self.prev_token();
1024-
Ok(Expr::Value(self.parse_value()?))
1023+
Ok(Some(Expr::Value(self.parse_value()?)))
10251024
}
10261025
Keyword::CURRENT_CATALOG
10271026
| Keyword::CURRENT_USER
10281027
| Keyword::SESSION_USER
10291028
| Keyword::USER
10301029
if dialect_of!(self is PostgreSqlDialect | GenericDialect) =>
10311030
{
1032-
Ok(Expr::Function(Function {
1031+
Ok(Some(Expr::Function(Function {
10331032
name: ObjectName(vec![w.to_ident()]),
10341033
parameters: FunctionArguments::None,
10351034
args: FunctionArguments::None,
10361035
null_treatment: None,
10371036
filter: None,
10381037
over: None,
10391038
within_group: vec![],
1040-
}))
1039+
})))
10411040
}
10421041
Keyword::CURRENT_TIMESTAMP
10431042
| Keyword::CURRENT_TIME
10441043
| Keyword::CURRENT_DATE
10451044
| Keyword::LOCALTIME
10461045
| Keyword::LOCALTIMESTAMP => {
1047-
self.parse_time_functions(ObjectName(vec![w.to_ident()]))
1048-
}
1049-
Keyword::CASE => self.parse_case_expr(),
1050-
Keyword::CONVERT => self.parse_convert_expr(false),
1051-
Keyword::TRY_CONVERT if self.dialect.supports_try_convert() => self.parse_convert_expr(true),
1052-
Keyword::CAST => self.parse_cast_expr(CastKind::Cast),
1053-
Keyword::TRY_CAST => self.parse_cast_expr(CastKind::TryCast),
1054-
Keyword::SAFE_CAST => self.parse_cast_expr(CastKind::SafeCast),
1046+
Ok(Some(self.parse_time_functions(ObjectName(vec![w.to_ident()]))?))
1047+
}
1048+
Keyword::CASE => Ok(Some(self.parse_case_expr()?)),
1049+
Keyword::CONVERT => Ok(Some(self.parse_convert_expr(false)?)),
1050+
Keyword::TRY_CONVERT if self.dialect.supports_try_convert() => Ok(Some(self.parse_convert_expr(true)?)),
1051+
Keyword::CAST => Ok(Some(self.parse_cast_expr(CastKind::Cast)?)),
1052+
Keyword::TRY_CAST => Ok(Some(self.parse_cast_expr(CastKind::TryCast)?)),
1053+
Keyword::SAFE_CAST => Ok(Some(self.parse_cast_expr(CastKind::SafeCast)?)),
10551054
Keyword::EXISTS
10561055
// Support parsing Databricks has a function named `exists`.
10571056
if !dialect_of!(self is DatabricksDialect)
@@ -1063,22 +1062,22 @@ impl<'a> Parser<'a> {
10631062
})
10641063
) =>
10651064
{
1066-
self.parse_exists_expr(false)
1065+
Ok(Some(self.parse_exists_expr(false)?))
10671066
}
1068-
Keyword::EXTRACT => self.parse_extract_expr(),
1069-
Keyword::CEIL => self.parse_ceil_floor_expr(true),
1070-
Keyword::FLOOR => self.parse_ceil_floor_expr(false),
1067+
Keyword::EXTRACT => Ok(Some(self.parse_extract_expr()?)),
1068+
Keyword::CEIL => Ok(Some(self.parse_ceil_floor_expr(true)?)),
1069+
Keyword::FLOOR => Ok(Some(self.parse_ceil_floor_expr(false)?)),
10711070
Keyword::POSITION if self.peek_token().token == Token::LParen => {
1072-
self.parse_position_expr(w.to_ident())
1071+
Ok(Some(self.parse_position_expr(w.to_ident())?))
10731072
}
1074-
Keyword::SUBSTRING => self.parse_substring_expr(),
1075-
Keyword::OVERLAY => self.parse_overlay_expr(),
1076-
Keyword::TRIM => self.parse_trim_expr(),
1077-
Keyword::INTERVAL => self.parse_interval(),
1073+
Keyword::SUBSTRING => Ok(Some(self.parse_substring_expr()?)),
1074+
Keyword::OVERLAY => Ok(Some(self.parse_overlay_expr()?)),
1075+
Keyword::TRIM => Ok(Some(self.parse_trim_expr()?)),
1076+
Keyword::INTERVAL => Ok(Some(self.parse_interval()?)),
10781077
// Treat ARRAY[1,2,3] as an array [1,2,3], otherwise try as subquery or a function call
10791078
Keyword::ARRAY if self.peek_token() == Token::LBracket => {
10801079
self.expect_token(&Token::LBracket)?;
1081-
self.parse_array_expr(true)
1080+
Ok(Some(self.parse_array_expr(true)?))
10821081
}
10831082
Keyword::ARRAY
10841083
if self.peek_token() == Token::LParen
@@ -1087,37 +1086,36 @@ impl<'a> Parser<'a> {
10871086
self.expect_token(&Token::LParen)?;
10881087
let query = self.parse_query()?;
10891088
self.expect_token(&Token::RParen)?;
1090-
Ok(Expr::Function(Function {
1089+
Ok(Some(Expr::Function(Function {
10911090
name: ObjectName(vec![w.to_ident()]),
10921091
parameters: FunctionArguments::None,
10931092
args: FunctionArguments::Subquery(query),
10941093
filter: None,
10951094
null_treatment: None,
10961095
over: None,
10971096
within_group: vec![],
1098-
}))
1097+
})))
10991098
}
1100-
Keyword::NOT => self.parse_not(),
1099+
Keyword::NOT => Ok(Some(self.parse_not()?)),
11011100
Keyword::MATCH if dialect_of!(self is MySqlDialect | GenericDialect) => {
1102-
self.parse_match_against()
1101+
Ok(Some(self.parse_match_against()?))
11031102
}
11041103
Keyword::STRUCT if dialect_of!(self is BigQueryDialect | GenericDialect) => {
11051104
self.prev_token();
1106-
self.parse_bigquery_struct_literal()
1105+
Ok(Some(self.parse_bigquery_struct_literal()?))
11071106
}
11081107
Keyword::PRIOR if matches!(self.state, ParserState::ConnectBy) => {
11091108
let expr = self.parse_subexpr(self.dialect.prec_value(Precedence::PlusMinus))?;
1110-
Ok(Expr::Prior(Box::new(expr)))
1109+
Ok(Some(Expr::Prior(Box::new(expr))))
11111110
}
11121111
Keyword::MAP if self.peek_token() == Token::LBrace && self.dialect.support_map_literal_syntax() => {
1113-
self.parse_duckdb_map_literal()
1112+
Ok(Some(self.parse_duckdb_map_literal()?))
11141113
}
1115-
Keyword::DEFAULT => Ok(Expr::Default),
1116-
_ => Err(ParserError::BranchAbandoned)
1114+
_ => Ok(None)
11171115
}
11181116
}
11191117

1120-
fn parse_ident_expr(&mut self, w: &Word) -> Result<Expr, ParserError> {
1118+
fn parse_expr_prefix_by_nonreserved_word(&mut self, w: &Word) -> Result<Expr, ParserError> {
11211119
match self.peek_token().token {
11221120
Token::LParen | Token::Period => {
11231121
let mut id_parts: Vec<Ident> = vec![w.to_ident()];
@@ -1233,23 +1231,33 @@ impl<'a> Parser<'a> {
12331231

12341232
let next_token = self.next_token();
12351233
let expr = match next_token.token {
1236-
// We first try to parse the word as the prefix of an expression.
1237-
// For example, the word INTERVAL in: SELECT INTERVAL '7' DAY
1238-
Token::Word(w) => match self.try_parse(|parser| parser.parse_expr_by_keyword(&w)) {
1239-
Ok(expr) => Ok(expr),
1240-
// Word does not indicate the start of a complex expression, try to parse as identifier
1241-
Err(ParserError::BranchAbandoned) => Ok(self.parse_ident_expr(&w)?),
1242-
// Word indicates the start of a complex expression, try to parse as identifier if the
1243-
// dialect does not reserve it, otherwise return the original error
1244-
Err(e) => {
1245-
if !self.dialect.is_reserved_for_identifier(w.keyword) {
1246-
if let Ok(expr) = self.try_parse(|parser| parser.parse_ident_expr(&w)) {
1247-
return Ok(expr);
1234+
Token::Word(w) => {
1235+
// Save the parser index so we can rollback
1236+
let index_before = self.index;
1237+
// We first try to parse the word as the prefix of an expression.
1238+
// For example, the word INTERVAL in: SELECT INTERVAL '7' DAY
1239+
match self.parse_expr_prefix_by_reserved_word(&w) {
1240+
// No expression prefix associated with this word
1241+
Ok(None) => Ok(self.parse_expr_prefix_by_nonreserved_word(&w)?),
1242+
// This word indicated an expression prefix and parsing was successful
1243+
Ok(Some(expr)) => Ok(expr),
1244+
// This word indicated an expression prefix but parsing failed. Two options:
1245+
// 1. Malformed statement
1246+
// 2. The dialect may allow this word as identifier as well as indicating an expression
1247+
Err(e) => {
1248+
let index_after_error = self.index;
1249+
if !self.dialect.is_reserved_for_identifier(w.keyword) {
1250+
// Rollback before trying to parse using a different approach
1251+
self.index = index_before;
1252+
if let Ok(expr) = self.parse_expr_prefix_by_nonreserved_word(&w) {
1253+
return Ok(expr);
1254+
}
12481255
}
1256+
self.index = index_after_error;
1257+
return Err(e);
12491258
}
1250-
return Err(e);
12511259
}
1252-
}, // End of Token::Word
1260+
} // End of Token::Word
12531261
// array `[1, 2, 3]`
12541262
Token::LBracket => self.parse_array_expr(false),
12551263
tok @ Token::Minus | tok @ Token::Plus => {
@@ -3680,24 +3688,6 @@ impl<'a> Parser<'a> {
36803688
}
36813689
}
36823690

3683-
/// Run a parser method `f`, reverting back to the current position if unsuccessful
3684-
/// but retaining the error message if such was raised by `f`
3685-
pub fn try_parse<T, F>(&mut self, mut f: F) -> Result<T, ParserError>
3686-
where
3687-
F: FnMut(&mut Parser) -> Result<T, ParserError>,
3688-
{
3689-
let index = self.index;
3690-
match f(self) {
3691-
Ok(t) => Ok(t),
3692-
// Unwind stack if limit exceeded
3693-
Err(ParserError::RecursionLimitExceeded) => Err(ParserError::RecursionLimitExceeded),
3694-
Err(e) => {
3695-
self.index = index;
3696-
Err(e)
3697-
}
3698-
}
3699-
}
3700-
37013691
/// Parse either `ALL`, `DISTINCT` or `DISTINCT ON (...)`. Returns [`None`] if `ALL` is parsed
37023692
/// and results in a [`ParserError`] if both `ALL` and `DISTINCT` are found.
37033693
pub fn parse_all_or_distinct(&mut self) -> Result<Option<Distinct>, ParserError> {

tests/sqlparser_bigquery.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,7 +1744,10 @@ 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![Expr::Value(number("1")), Expr::Default,]]
1747+
rows: vec![vec![
1748+
Expr::Value(number("1")),
1749+
Expr::Identifier(Ident::new("DEFAULT")),
1750+
]]
17481751
})
17491752
})
17501753
},
@@ -1755,7 +1758,10 @@ fn parse_merge() {
17551758
columns: vec![],
17561759
kind: MergeInsertKind::Values(Values {
17571760
explicit_row: false,
1758-
rows: vec![vec![Expr::Value(number("1")), Expr::Default,]]
1761+
rows: vec![vec![
1762+
Expr::Value(number("1")),
1763+
Expr::Identifier(Ident::new("DEFAULT")),
1764+
]]
17591765
})
17601766
})
17611767
},

tests/sqlparser_common.rs

Lines changed: 2 additions & 5 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::{Keyword, ALL_KEYWORDS};
37+
use sqlparser::keywords::ALL_KEYWORDS;
3838
use sqlparser::parser::{Parser, ParserError, ParserOptions};
3939
use sqlparser::tokenizer::Tokenizer;
4040
use test_utils::{
@@ -5097,10 +5097,7 @@ fn parse_interval_dont_require_unit() {
50975097

50985098
#[test]
50995099
fn parse_interval_require_unit() {
5100-
let dialects = all_dialects_where(|d| {
5101-
d.require_interval_qualifier() && d.is_reserved_for_identifier(Keyword::INTERVAL)
5102-
});
5103-
5100+
let dialects = all_dialects_where(|d| d.require_interval_qualifier());
51045101
let sql = "SELECT INTERVAL '1 DAY'";
51055102
let err = dialects.parse_sql_statements(sql).unwrap_err();
51065103
assert_eq!(

tests/sqlparser_postgres.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,7 +1352,7 @@ fn parse_set() {
13521352
local: false,
13531353
hivevar: false,
13541354
variables: OneOrManyWithParens::One(ObjectName(vec![Ident::new("a")])),
1355-
value: vec![Expr::Default],
1355+
value: vec![Expr::Identifier(Ident::new("DEFAULT"))],
13561356
}
13571357
);
13581358

@@ -4225,7 +4225,7 @@ fn test_simple_postgres_insert_with_alias() {
42254225
body: Box::new(SetExpr::Values(Values {
42264226
explicit_row: false,
42274227
rows: vec![vec![
4228-
Expr::Default,
4228+
Expr::Identifier(Ident::new("DEFAULT")),
42294229
Expr::Value(Value::Number("123".to_string(), false))
42304230
]]
42314231
})),
@@ -4288,7 +4288,7 @@ fn test_simple_postgres_insert_with_alias() {
42884288
body: Box::new(SetExpr::Values(Values {
42894289
explicit_row: false,
42904290
rows: vec![vec![
4291-
Expr::Default,
4291+
Expr::Identifier(Ident::new("DEFAULT")),
42924292
Expr::Value(Value::Number(
42934293
bigdecimal::BigDecimal::new(123.into(), 0),
42944294
false
@@ -4353,7 +4353,7 @@ fn test_simple_insert_with_quoted_alias() {
43534353
body: Box::new(SetExpr::Values(Values {
43544354
explicit_row: false,
43554355
rows: vec![vec![
4356-
Expr::Default,
4356+
Expr::Identifier(Ident::new("DEFAULT")),
43574357
Expr::Value(Value::SingleQuotedString("0123".to_string()))
43584358
]]
43594359
})),

0 commit comments

Comments
 (0)