Skip to content

Commit 1bea379

Browse files
am357jpschorr
andauthored
Fix parsing for dot following arr and [*] path and add TABLE keyword (#152)
* Add `TABLE` keyword This is to ensure the following syntax conformance test passes: ``` fn invalid_path_component_keyword_in_path_test() { let statement = r#"SELECT foo.id, foo.table FROM `[{id: 1, table: "foos"}]` AS foo"#; let res = partiql_parser::Parser::default().parse(statement); assert!( res.is_err(), "For `{}`, expected `Err(_)`, but was `{:#?}`", statement, res ); } ``` * Fix parsing for path whildcard and array with a dot This change fixes parsing of expressions like the following: `foo(x, y)[*].*.b[5]` In the above expression a `.` follows a path whildcard * Add identation * Table -> TABLE Co-authored-by: Josh Pschorr <[email protected]>
1 parent c676134 commit 1bea379

File tree

3 files changed

+55
-44
lines changed

3 files changed

+55
-44
lines changed

partiql-parser/src/lexer.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,8 @@ pub enum Token<'input> {
606606
Right,
607607
#[regex("(?i:Select)")]
608608
Select,
609+
#[regex("(?i:Table)")]
610+
Table,
609611
#[regex("(?i:Time)")]
610612
Time,
611613
#[regex("(?i:Timestamp)")]
@@ -680,6 +682,7 @@ impl<'input> Token<'input> {
680682
| Token::Preserve
681683
| Token::Right
682684
| Token::Select
685+
| Token::Table
683686
| Token::Time
684687
| Token::Timestamp
685688
| Token::Then
@@ -789,6 +792,7 @@ impl<'input> fmt::Display for Token<'input> {
789792
| Token::Preserve
790793
| Token::Right
791794
| Token::Select
795+
| Token::Table
792796
| Token::Time
793797
| Token::Timestamp
794798
| Token::Then
@@ -826,7 +830,7 @@ mod tests {
826830
"WiTH Where Value uSiNg Unpivot UNION True Select right Preserve pivoT Outer Order Or \
827831
On Offset Nulls Null Not Natural Missing Limit Like Left Lateral Last Join \
828832
Intersect Is Inner In Having Group From For Full First False Except Escape Desc \
829-
Cross Time Timestamp Date By Between At As And Asc All Values Case When Then Else End";
833+
Cross Table Time Timestamp Date By Between At As And Asc All Values Case When Then Else End";
830834
let symbols = symbols.split(' ').chain(primitives.split(' '));
831835
let keywords = keywords.split(' ');
832836

@@ -846,9 +850,9 @@ mod tests {
846850
"LATERAL", ".", "LAST", "||", "JOIN", ":", "INTERSECT", "--", "IS", "/**/", "INNER",
847851
"<unquoted_ident:UNQUOTED_IDENT>", "IN", "<quoted_ident:QUOTED_IDENT>", "HAVING",
848852
"<unquoted_atident:UNQUOTED_ATIDENT>", "GROUP", "<quoted_atident:QUOTED_ATIDENT>",
849-
"FROM", "FOR", "FULL", "FIRST", "FALSE", "EXCEPT", "ESCAPE", "DESC", "CROSS", "TIME",
850-
"TIMESTAMP", "DATE", "BY", "BETWEEN", "AT", "AS", "AND", "ASC", "ALL", "VALUES", "CASE",
851-
"WHEN", "THEN", "ELSE", "END"
853+
"FROM", "FOR", "FULL", "FIRST", "FALSE", "EXCEPT", "ESCAPE", "DESC", "CROSS", "TABLE",
854+
"TIME", "TIMESTAMP", "DATE", "BY", "BETWEEN", "AT", "AS", "AND", "ASC", "ALL", "VALUES",
855+
"CASE", "WHEN", "THEN", "ELSE", "END"
852856
];
853857
let displayed = toks
854858
.into_iter()

partiql-parser/src/parse/mod.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -302,12 +302,12 @@ mod tests {
302302

303303
#[test]
304304
fn query() {
305-
parse!(r#"(SELECT a FROM table).a"#);
306-
parse!(r#"(SELECT a FROM table).'a'"#);
307-
parse!(r#"(SELECT a FROM table)."a""#);
308-
parse!(r#"(SELECT a FROM table)['a']"#);
309-
parse!(r#"(SELECT a FROM table).*"#);
310-
parse!(r#"(SELECT a FROM table)[*]"#);
305+
parse!(r#"(SELECT a FROM t).a"#);
306+
parse!(r#"(SELECT a FROM t).'a'"#);
307+
parse!(r#"(SELECT a FROM t)."a""#);
308+
parse!(r#"(SELECT a FROM t)['a']"#);
309+
parse!(r#"(SELECT a FROM t).*"#);
310+
parse!(r#"(SELECT a FROM t)[*]"#);
311311
}
312312

313313
#[test]
@@ -317,6 +317,7 @@ mod tests {
317317
parse!(r#"foo(x, y)[*]"#);
318318
parse!(r#"foo(x, y)[5]"#);
319319
parse!(r#"foo(x, y).a.*"#);
320+
parse!(r#"foo(x, y)[*].*.b[5]"#);
320321
}
321322

322323
#[test]

partiql-parser/src/parse/partiql.lalrpop

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -750,11 +750,34 @@ ExprPrecedence03: ast::Expr = {
750750
<ExprPrecedence02>,
751751
}
752752

753+
ExprPrecedence02: ast::Expr = {
754+
<lo:@L> <expr:PathExpr> <hi:@R> => ast::Expr {
755+
kind: ast::ExprKind::Path( expr.ast(lo..hi) )
756+
},
757+
<ExprPrecedence01>,
758+
}
759+
753760
PathExpr: ast::Path = {
754761
<l:ExprPrecedence01> "." <steps:PathSteps> => ast::Path { root:Box::new(l), steps },
755-
<l:ExprPrecedence01> "." "*" => ast::Path {
756-
root:Box::new(l), steps:vec![ast::PathStep::PathUnpivot]
757-
},
762+
<l:ExprPrecedence01> "[" "*" "]" "." <s:PathSteps> => {
763+
let step = ast::PathStep::PathWildCard;
764+
ast::Path {
765+
root: Box::new(l),
766+
steps: std::iter::once(step).chain(s.into_iter()).collect()
767+
}
768+
},
769+
<l:ExprPrecedence01> "[" <expr:ExprQuery> "]" "." <s:PathSteps> => {
770+
let step = ast::PathStep::PathExpr(
771+
ast::PathExpr{
772+
index: Box::new(*expr),
773+
}
774+
);
775+
776+
ast::Path {
777+
root: Box::new(l),
778+
steps: std::iter::once(step).chain(s.into_iter()).collect()
779+
}
780+
},
758781
<l:ExprPrecedence01> "[" "*" "]" => ast::Path {
759782
root:Box::new(l), steps:vec![ast::PathStep::PathWildCard]
760783
},
@@ -770,13 +793,6 @@ PathExpr: ast::Path = {
770793
},
771794
};
772795

773-
ExprPrecedence02: ast::Expr = {
774-
<lo:@L> <expr:PathExpr> <hi:@R> => ast::Expr {
775-
kind: ast::ExprKind::Path( expr.ast(lo..hi) )
776-
},
777-
<ExprPrecedence01>,
778-
}
779-
780796
#[inline]
781797
ExprPrecedence01: ast::Expr = {
782798
<lo:@L> <call:FunctionCall> <hi:@R> => ast::Expr{ kind: ast::ExprKind::Call( call.ast(lo..hi) ) },
@@ -946,23 +962,10 @@ FunctionArgName: ast::SymbolPrimitive = {
946962
// See the path expression conformance tests under `partiql-tests` or parser unit-tests for more examples.
947963
PathSteps: Vec<ast::PathStep> = {
948964
<path:PathSteps> "." <v:PathExprVarRef> => {
949-
let step = ast::PathStep::PathExpr(
950-
ast::PathExpr{
951-
index: Box::new(v),
952-
});
953-
954-
let mut steps = path;
955-
steps.push(step);
956-
steps
957-
// ast::Path{ root:path.root, steps }
965+
vec![ast::PathStep::PathExpr( ast::PathExpr{ index: Box::new(v) })]
958966
},
959-
<lo:@L> <path:PathSteps> "[" "*" "]" <hi:@R> => {
960-
let step = ast::PathStep::PathWildCard;
961-
962-
let mut steps = path;
963-
steps.push(step);
964-
steps
965-
// ast::Path{ root:path.root, steps }
967+
<lo:@L> <path:PathSteps> "[" "*" "]" <hi:@R> => {
968+
vec![ast::PathStep::PathWildCard]
966969
},
967970
<lo:@L> <path:PathSteps> "." "*" <hi:@R> => {
968971
let step = ast::PathStep::PathUnpivot;
@@ -983,16 +986,18 @@ PathSteps: Vec<ast::PathStep> = {
983986
let mut steps = path;
984987
steps.push(step);
985988
steps
986-
// ast::Path{ root:path.root, steps }
989+
},
990+
"[" "*" "]" => {
991+
vec![ast::PathStep::PathWildCard]
992+
},
993+
"[" <expr:ExprQuery> "]" => {
994+
vec![ast::PathStep::PathExpr( ast::PathExpr{ index: Box::new(*expr) })]
995+
},
996+
"*" => {
997+
vec![ast::PathStep::PathUnpivot]
987998
},
988999
<v:PathExprVarRef> => {
989-
let step = ast::PathStep::PathExpr(
990-
ast::PathExpr{
991-
index: Box::new(v),
992-
});
993-
let steps = vec![step];
994-
steps
995-
// ast::Path{ root: Box::new(v), steps: vec![] }
1000+
vec![ast::PathStep::PathExpr( ast::PathExpr{ index: Box::new(v) })]
9961001
},
9971002
}
9981003

@@ -1294,6 +1299,7 @@ extern {
12941299
"PRESERVE" => lexer::Token::Preserve,
12951300
"RIGHT" => lexer::Token::Right,
12961301
"SELECT" => lexer::Token::Select,
1302+
"TABLE" => lexer::Token::Table,
12971303
"TIME" => lexer::Token::Time,
12981304
"TIMESTAMP" => lexer::Token::Timestamp,
12991305
"THEN" => lexer::Token::Then,

0 commit comments

Comments
 (0)