diff --git a/crates/squawk_parser/src/grammar.rs b/crates/squawk_parser/src/grammar.rs index 73416f11..a5773d08 100644 --- a/crates/squawk_parser/src/grammar.rs +++ b/crates/squawk_parser/src/grammar.rs @@ -3421,7 +3421,7 @@ fn on_clause(p: &mut Parser<'_>) { assert!(p.at(ON_KW)); let m = p.start(); p.bump(ON_KW); - expr(p); + clause_expr(p); m.complete(p, ON_CLAUSE); } @@ -4476,17 +4476,20 @@ fn opt_repeatable_clause(p: &mut Parser<'_>) -> Option { Some(m.complete(p, REPEATABLE_CLAUSE)) } +fn clause_expr(p: &mut Parser<'_>) { + if p.at(AND_KW) || p.at(OR_KW) { + p.err_and_bump(&format!("expected expression but got {:?}", p.current())); + } + expr(p); +} + fn opt_where_clause(p: &mut Parser<'_>) -> Option { if !p.at(WHERE_KW) { return None; } let m = p.start(); p.bump(WHERE_KW); - // TODO: we might want to be fancier, maybe all binary only operators? - if p.at(AND_KW) || p.at(OR_KW) { - p.err_and_bump(&format!("expected expression but got {:?}", p.current())); - } - expr(p); + clause_expr(p); Some(m.complete(p, WHERE_CLAUSE)) } @@ -4580,7 +4583,7 @@ fn opt_having_clause(p: &mut Parser<'_>) -> Option { } let m = p.start(); p.bump(HAVING_KW); - expr(p); + clause_expr(p); Some(m.complete(p, HAVING_CLAUSE)) } diff --git a/crates/squawk_parser/tests/data/err/select.sql b/crates/squawk_parser/tests/data/err/select.sql index a39154b6..a8cda298 100644 --- a/crates/squawk_parser/tests/data/err/select.sql +++ b/crates/squawk_parser/tests/data/err/select.sql @@ -81,6 +81,12 @@ grant select on t to u; select from t where and c > 10; select from t where or c != 'b'; +select having and c > 10; +select having or c != 'b'; + +select from t join u on and true; +select from t join u on or true; + -- select end select end; diff --git a/crates/squawk_parser/tests/snapshots/tests__select_err.snap b/crates/squawk_parser/tests/snapshots/tests__select_err.snap index 95b84baa..b5cb4f97 100644 --- a/crates/squawk_parser/tests/snapshots/tests__select_err.snap +++ b/crates/squawk_parser/tests/snapshots/tests__select_err.snap @@ -803,6 +803,106 @@ SOURCE_FILE STRING "'b'" SEMICOLON ";" WHITESPACE "\n\n" + SELECT + SELECT_CLAUSE + SELECT_KW "select" + WHITESPACE " " + HAVING_CLAUSE + HAVING_KW "having" + WHITESPACE " " + ERROR + AND_KW "and" + WHITESPACE " " + BIN_EXPR + NAME_REF + IDENT "c" + WHITESPACE " " + R_ANGLE ">" + WHITESPACE " " + LITERAL + INT_NUMBER "10" + SEMICOLON ";" + WHITESPACE "\n" + SELECT + SELECT_CLAUSE + SELECT_KW "select" + WHITESPACE " " + HAVING_CLAUSE + HAVING_KW "having" + WHITESPACE " " + ERROR + OR_KW "or" + WHITESPACE " " + BIN_EXPR + NAME_REF + IDENT "c" + WHITESPACE " " + NEQ "!=" + WHITESPACE " " + LITERAL + STRING "'b'" + SEMICOLON ";" + WHITESPACE "\n\n" + SELECT + SELECT_CLAUSE + SELECT_KW "select" + WHITESPACE " " + FROM_CLAUSE + FROM_KW "from" + WHITESPACE " " + JOIN_EXPR + FROM_ITEM + NAME_REF + IDENT "t" + WHITESPACE " " + JOIN + JOIN_INNER + JOIN_KW "join" + WHITESPACE " " + FROM_ITEM + NAME_REF + IDENT "u" + WHITESPACE " " + ON_CLAUSE + ON_KW "on" + WHITESPACE " " + ERROR + AND_KW "and" + WHITESPACE " " + LITERAL + TRUE_KW "true" + SEMICOLON ";" + WHITESPACE "\n" + SELECT + SELECT_CLAUSE + SELECT_KW "select" + WHITESPACE " " + FROM_CLAUSE + FROM_KW "from" + WHITESPACE " " + JOIN_EXPR + FROM_ITEM + NAME_REF + IDENT "t" + WHITESPACE " " + JOIN + JOIN_INNER + JOIN_KW "join" + WHITESPACE " " + FROM_ITEM + NAME_REF + IDENT "u" + WHITESPACE " " + ON_CLAUSE + ON_KW "on" + WHITESPACE " " + ERROR + OR_KW "or" + WHITESPACE " " + LITERAL + TRUE_KW "true" + SEMICOLON ";" + WHITESPACE "\n\n" COMMENT "-- select end" WHITESPACE "\n" SELECT @@ -1021,31 +1121,47 @@ error[syntax-error]: expected expression but got OR_KW ╭▸ 82 │ select from t where or c != 'b'; ╰╴ ━ -error[syntax-error]: expected SEMICOLON +error[syntax-error]: expected expression but got AND_KW ╭▸ -85 │ select - │ ┏━━━━━━━┛ -86 │ ┃ end; - ╰╴┗━┛ +84 │ select having and c > 10; + ╰╴ ━ +error[syntax-error]: expected expression but got OR_KW + ╭▸ +85 │ select having or c != 'b'; + ╰╴ ━ +error[syntax-error]: expected expression but got AND_KW + ╭▸ +87 │ select from t join u on and true; + ╰╴ ━ +error[syntax-error]: expected expression but got OR_KW + ╭▸ +88 │ select from t join u on or true; + ╰╴ ━ error[syntax-error]: expected SEMICOLON ╭▸ -89 │ select +91 │ select │ ┏━━━━━━━┛ -90 │ ┃ analyze; +92 │ ┃ end; ╰╴┗━┛ error[syntax-error]: expected SEMICOLON ╭▸ -92 │ select +95 │ select │ ┏━━━━━━━┛ -93 │ ┃ analyse; +96 │ ┃ analyze; ╰╴┗━┛ error[syntax-error]: expected SEMICOLON ╭▸ -97 │ select +98 │ select │ ┏━━━━━━━┛ -98 │ ┃ with t as (select 1) +99 │ ┃ analyse; ╰╴┗━┛ +error[syntax-error]: expected SEMICOLON + ╭▸ +103 │ select + │ ┏━━━━━━━┛ +104 │ ┃ with t as (select 1) + ╰╴┗━┛ error[syntax-error]: unexpected trailing comma ╭▸ -102 │ select 1, +108 │ select 1, ╰╴ ━