diff --git a/crates/squawk_parser/src/grammar.rs b/crates/squawk_parser/src/grammar.rs index ff6d449a..6b255afb 100644 --- a/crates/squawk_parser/src/grammar.rs +++ b/crates/squawk_parser/src/grammar.rs @@ -1696,16 +1696,6 @@ fn arg_list(p: &mut Parser<'_>) { m.complete(p, ARG_LIST); return; } - if p.nth_at(1, DISTINCT_KW) || p.nth_at(1, ALL_KW) { - p.bump(L_PAREN); - p.bump_any(); - if arg_expr(p).is_none() { - p.error("expected expression"); - } - p.expect(R_PAREN); - m.complete(p, ARG_LIST); - return; - } delimited( p, L_PAREN, @@ -1713,7 +1703,12 @@ fn arg_list(p: &mut Parser<'_>) { COMMA, || "expected expression".into(), EXPR_FIRST.union(ATTRIBUTE_FIRST), - |p| arg_expr(p).is_some(), + |p| { + if p.at(DISTINCT_KW) || p.at(ALL_KW) { + p.bump_any(); // consume DISTINCT or ALL + } + arg_expr(p).is_some() + }, ); m.complete(p, ARG_LIST); } diff --git a/crates/squawk_parser/tests/data/ok/select.sql b/crates/squawk_parser/tests/data/ok/select.sql index f77c9021..1cd363d7 100644 --- a/crates/squawk_parser/tests/data/ok/select.sql +++ b/crates/squawk_parser/tests/data/ok/select.sql @@ -500,3 +500,9 @@ ORDER BY sensor_id, day; -- select_from_user_table select * from user; + +-- select with aggregates +explain (costs off) +select string_agg(distinct f1, ',') filter (where length(f1) > 1) +from varchar_tbl; + diff --git a/crates/squawk_parser/tests/snapshots/tests__select_ok.snap b/crates/squawk_parser/tests/snapshots/tests__select_ok.snap index 7be1834e..73476551 100644 --- a/crates/squawk_parser/tests/snapshots/tests__select_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__select_ok.snap @@ -1,6 +1,7 @@ --- source: crates/squawk_parser/tests/tests.rs input_file: crates/squawk_parser/tests/data/ok/select.sql +snapshot_kind: text --- SOURCE_FILE COMMENT "-- parens_and_unions" @@ -5864,4 +5865,66 @@ SOURCE_FILE NAME_REF USER_KW "user" SEMICOLON ";" + WHITESPACE "\n\n" + COMMENT "-- select with aggregates" WHITESPACE "\n" + EXPLAIN + EXPLAIN_KW "explain" + WHITESPACE " " + L_PAREN "(" + IDENT "costs" + WHITESPACE " " + LITERAL + OFF_KW "off" + R_PAREN ")" + WHITESPACE "\n" + SELECT + SELECT_CLAUSE + SELECT_KW "select" + WHITESPACE " " + TARGET_LIST + TARGET + CALL_EXPR + NAME_REF + IDENT "string_agg" + ARG_LIST + L_PAREN "(" + DISTINCT_KW "distinct" + WHITESPACE " " + NAME_REF + IDENT "f1" + COMMA "," + WHITESPACE " " + LITERAL + STRING "','" + R_PAREN ")" + WHITESPACE " " + FILTER_CLAUSE + FILTER_KW "filter" + WHITESPACE " " + L_PAREN "(" + WHERE_KW "where" + WHITESPACE " " + BIN_EXPR + CALL_EXPR + NAME_REF + IDENT "length" + ARG_LIST + L_PAREN "(" + NAME_REF + IDENT "f1" + R_PAREN ")" + WHITESPACE " " + R_ANGLE ">" + WHITESPACE " " + LITERAL + INT_NUMBER "1" + R_PAREN ")" + WHITESPACE "\n" + FROM_CLAUSE + FROM_KW "from" + WHITESPACE " " + NAME_REF + IDENT "varchar_tbl" + SEMICOLON ";" + WHITESPACE "\n\n"