Skip to content

Commit 36dd588

Browse files
committed
Code review comments
1 parent 13cb58e commit 36dd588

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
@@ -675,7 +675,7 @@ pub trait Dialect: Debug + Any {
675675
fn supports_create_table_select(&self) -> bool {
676676
false
677677
}
678-
678+
679679
/// Returns true if the specified keyword is reserved and cannot be
680680
/// used as an identifier without special handling like quoting.
681681
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
}
@@ -1029,45 +1025,48 @@ impl<'a> Parser<'a> {
10291025
Ok(Statement::NOTIFY { channel, payload })
10301026
}
10311027

1032-
fn parse_expr_by_keyword(&mut self, w: &Word) -> Result<Expr, ParserError> {
1028+
fn parse_expr_prefix_by_reserved_word(
1029+
&mut self,
1030+
w: &Word,
1031+
) -> Result<Option<Expr>, ParserError> {
10331032
match w.keyword {
10341033
Keyword::TRUE | Keyword::FALSE if self.dialect.supports_boolean_literals() => {
10351034
self.prev_token();
1036-
Ok(Expr::Value(self.parse_value()?))
1035+
Ok(Some(Expr::Value(self.parse_value()?)))
10371036
}
10381037
Keyword::NULL => {
10391038
self.prev_token();
1040-
Ok(Expr::Value(self.parse_value()?))
1039+
Ok(Some(Expr::Value(self.parse_value()?)))
10411040
}
10421041
Keyword::CURRENT_CATALOG
10431042
| Keyword::CURRENT_USER
10441043
| Keyword::SESSION_USER
10451044
| Keyword::USER
10461045
if dialect_of!(self is PostgreSqlDialect | GenericDialect) =>
10471046
{
1048-
Ok(Expr::Function(Function {
1047+
Ok(Some(Expr::Function(Function {
10491048
name: ObjectName(vec![w.to_ident()]),
10501049
parameters: FunctionArguments::None,
10511050
args: FunctionArguments::None,
10521051
null_treatment: None,
10531052
filter: None,
10541053
over: None,
10551054
within_group: vec![],
1056-
}))
1055+
})))
10571056
}
10581057
Keyword::CURRENT_TIMESTAMP
10591058
| Keyword::CURRENT_TIME
10601059
| Keyword::CURRENT_DATE
10611060
| Keyword::LOCALTIME
10621061
| Keyword::LOCALTIMESTAMP => {
1063-
self.parse_time_functions(ObjectName(vec![w.to_ident()]))
1064-
}
1065-
Keyword::CASE => self.parse_case_expr(),
1066-
Keyword::CONVERT => self.parse_convert_expr(false),
1067-
Keyword::TRY_CONVERT if self.dialect.supports_try_convert() => self.parse_convert_expr(true),
1068-
Keyword::CAST => self.parse_cast_expr(CastKind::Cast),
1069-
Keyword::TRY_CAST => self.parse_cast_expr(CastKind::TryCast),
1070-
Keyword::SAFE_CAST => self.parse_cast_expr(CastKind::SafeCast),
1062+
Ok(Some(self.parse_time_functions(ObjectName(vec![w.to_ident()]))?))
1063+
}
1064+
Keyword::CASE => Ok(Some(self.parse_case_expr()?)),
1065+
Keyword::CONVERT => Ok(Some(self.parse_convert_expr(false)?)),
1066+
Keyword::TRY_CONVERT if self.dialect.supports_try_convert() => Ok(Some(self.parse_convert_expr(true)?)),
1067+
Keyword::CAST => Ok(Some(self.parse_cast_expr(CastKind::Cast)?)),
1068+
Keyword::TRY_CAST => Ok(Some(self.parse_cast_expr(CastKind::TryCast)?)),
1069+
Keyword::SAFE_CAST => Ok(Some(self.parse_cast_expr(CastKind::SafeCast)?)),
10711070
Keyword::EXISTS
10721071
// Support parsing Databricks has a function named `exists`.
10731072
if !dialect_of!(self is DatabricksDialect)
@@ -1079,22 +1078,22 @@ impl<'a> Parser<'a> {
10791078
})
10801079
) =>
10811080
{
1082-
self.parse_exists_expr(false)
1081+
Ok(Some(self.parse_exists_expr(false)?))
10831082
}
1084-
Keyword::EXTRACT => self.parse_extract_expr(),
1085-
Keyword::CEIL => self.parse_ceil_floor_expr(true),
1086-
Keyword::FLOOR => self.parse_ceil_floor_expr(false),
1083+
Keyword::EXTRACT => Ok(Some(self.parse_extract_expr()?)),
1084+
Keyword::CEIL => Ok(Some(self.parse_ceil_floor_expr(true)?)),
1085+
Keyword::FLOOR => Ok(Some(self.parse_ceil_floor_expr(false)?)),
10871086
Keyword::POSITION if self.peek_token().token == Token::LParen => {
1088-
self.parse_position_expr(w.to_ident())
1087+
Ok(Some(self.parse_position_expr(w.to_ident())?))
10891088
}
1090-
Keyword::SUBSTRING => self.parse_substring_expr(),
1091-
Keyword::OVERLAY => self.parse_overlay_expr(),
1092-
Keyword::TRIM => self.parse_trim_expr(),
1093-
Keyword::INTERVAL => self.parse_interval(),
1089+
Keyword::SUBSTRING => Ok(Some(self.parse_substring_expr()?)),
1090+
Keyword::OVERLAY => Ok(Some(self.parse_overlay_expr()?)),
1091+
Keyword::TRIM => Ok(Some(self.parse_trim_expr()?)),
1092+
Keyword::INTERVAL => Ok(Some(self.parse_interval()?)),
10941093
// Treat ARRAY[1,2,3] as an array [1,2,3], otherwise try as subquery or a function call
10951094
Keyword::ARRAY if self.peek_token() == Token::LBracket => {
10961095
self.expect_token(&Token::LBracket)?;
1097-
self.parse_array_expr(true)
1096+
Ok(Some(self.parse_array_expr(true)?))
10981097
}
10991098
Keyword::ARRAY
11001099
if self.peek_token() == Token::LParen
@@ -1103,37 +1102,36 @@ impl<'a> Parser<'a> {
11031102
self.expect_token(&Token::LParen)?;
11041103
let query = self.parse_query()?;
11051104
self.expect_token(&Token::RParen)?;
1106-
Ok(Expr::Function(Function {
1105+
Ok(Some(Expr::Function(Function {
11071106
name: ObjectName(vec![w.to_ident()]),
11081107
parameters: FunctionArguments::None,
11091108
args: FunctionArguments::Subquery(query),
11101109
filter: None,
11111110
null_treatment: None,
11121111
over: None,
11131112
within_group: vec![],
1114-
}))
1113+
})))
11151114
}
1116-
Keyword::NOT => self.parse_not(),
1115+
Keyword::NOT => Ok(Some(self.parse_not()?)),
11171116
Keyword::MATCH if dialect_of!(self is MySqlDialect | GenericDialect) => {
1118-
self.parse_match_against()
1117+
Ok(Some(self.parse_match_against()?))
11191118
}
11201119
Keyword::STRUCT if dialect_of!(self is BigQueryDialect | GenericDialect) => {
11211120
self.prev_token();
1122-
self.parse_bigquery_struct_literal()
1121+
Ok(Some(self.parse_bigquery_struct_literal()?))
11231122
}
11241123
Keyword::PRIOR if matches!(self.state, ParserState::ConnectBy) => {
11251124
let expr = self.parse_subexpr(self.dialect.prec_value(Precedence::PlusMinus))?;
1126-
Ok(Expr::Prior(Box::new(expr)))
1125+
Ok(Some(Expr::Prior(Box::new(expr))))
11271126
}
11281127
Keyword::MAP if self.peek_token() == Token::LBrace && self.dialect.support_map_literal_syntax() => {
1129-
self.parse_duckdb_map_literal()
1128+
Ok(Some(self.parse_duckdb_map_literal()?))
11301129
}
1131-
Keyword::DEFAULT => Ok(Expr::Default),
1132-
_ => Err(ParserError::BranchAbandoned)
1130+
_ => Ok(None)
11331131
}
11341132
}
11351133

1136-
fn parse_ident_expr(&mut self, w: &Word) -> Result<Expr, ParserError> {
1134+
fn parse_expr_prefix_by_nonreserved_word(&mut self, w: &Word) -> Result<Expr, ParserError> {
11371135
match self.peek_token().token {
11381136
Token::LParen | Token::Period => {
11391137
let mut id_parts: Vec<Ident> = vec![w.to_ident()];
@@ -1249,23 +1247,33 @@ impl<'a> Parser<'a> {
12491247

12501248
let next_token = self.next_token();
12511249
let expr = match next_token.token {
1252-
// We first try to parse the word as the prefix of an expression.
1253-
// For example, the word INTERVAL in: SELECT INTERVAL '7' DAY
1254-
Token::Word(w) => match self.try_parse(|parser| parser.parse_expr_by_keyword(&w)) {
1255-
Ok(expr) => Ok(expr),
1256-
// Word does not indicate the start of a complex expression, try to parse as identifier
1257-
Err(ParserError::BranchAbandoned) => Ok(self.parse_ident_expr(&w)?),
1258-
// Word indicates the start of a complex expression, try to parse as identifier if the
1259-
// dialect does not reserve it, otherwise return the original error
1260-
Err(e) => {
1261-
if !self.dialect.is_reserved_for_identifier(w.keyword) {
1262-
if let Ok(expr) = self.try_parse(|parser| parser.parse_ident_expr(&w)) {
1263-
return Ok(expr);
1250+
Token::Word(w) => {
1251+
// Save the parser index so we can rollback
1252+
let index_before = self.index;
1253+
// We first try to parse the word as the prefix of an expression.
1254+
// For example, the word INTERVAL in: SELECT INTERVAL '7' DAY
1255+
match self.parse_expr_prefix_by_reserved_word(&w) {
1256+
// No expression prefix associated with this word
1257+
Ok(None) => Ok(self.parse_expr_prefix_by_nonreserved_word(&w)?),
1258+
// This word indicated an expression prefix and parsing was successful
1259+
Ok(Some(expr)) => Ok(expr),
1260+
// This word indicated an expression prefix but parsing failed. Two options:
1261+
// 1. Malformed statement
1262+
// 2. The dialect may allow this word as identifier as well as indicating an expression
1263+
Err(e) => {
1264+
let index_after_error = self.index;
1265+
if !self.dialect.is_reserved_for_identifier(w.keyword) {
1266+
// Rollback before trying to parse using a different approach
1267+
self.index = index_before;
1268+
if let Ok(expr) = self.parse_expr_prefix_by_nonreserved_word(&w) {
1269+
return Ok(expr);
1270+
}
12641271
}
1272+
self.index = index_after_error;
1273+
return Err(e);
12651274
}
1266-
return Err(e);
12671275
}
1268-
}, // End of Token::Word
1276+
} // End of Token::Word
12691277
// array `[1, 2, 3]`
12701278
Token::LBracket => self.parse_array_expr(false),
12711279
tok @ Token::Minus | tok @ Token::Plus => {
@@ -3696,24 +3704,6 @@ impl<'a> Parser<'a> {
36963704
}
36973705
}
36983706

3699-
/// Run a parser method `f`, reverting back to the current position if unsuccessful
3700-
/// but retaining the error message if such was raised by `f`
3701-
pub fn try_parse<T, F>(&mut self, mut f: F) -> Result<T, ParserError>
3702-
where
3703-
F: FnMut(&mut Parser) -> Result<T, ParserError>,
3704-
{
3705-
let index = self.index;
3706-
match f(self) {
3707-
Ok(t) => Ok(t),
3708-
// Unwind stack if limit exceeded
3709-
Err(ParserError::RecursionLimitExceeded) => Err(ParserError::RecursionLimitExceeded),
3710-
Err(e) => {
3711-
self.index = index;
3712-
Err(e)
3713-
}
3714-
}
3715-
}
3716-
37173707
/// Parse either `ALL`, `DISTINCT` or `DISTINCT ON (...)`. Returns [`None`] if `ALL` is parsed
37183708
/// and results in a [`ParserError`] if both `ALL` and `DISTINCT` are found.
37193709
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)