From 46e396a7450af0c4b0fce2cf173b6b353373b166 Mon Sep 17 00:00:00 2001 From: Steve Dignam Date: Tue, 27 May 2025 18:59:59 -0400 Subject: [PATCH] parser: fix parsing window definition with multiple expressions --- crates/squawk_parser/src/grammar.rs | 5 + .../tests/data/ok/select_cte.sql | 16 ++ .../tests/snapshots/tests__select_cte_ok.snap | 152 +++++++++++++++++- 3 files changed, 172 insertions(+), 1 deletion(-) diff --git a/crates/squawk_parser/src/grammar.rs b/crates/squawk_parser/src/grammar.rs index 8687b212..708d2701 100644 --- a/crates/squawk_parser/src/grammar.rs +++ b/crates/squawk_parser/src/grammar.rs @@ -3954,6 +3954,11 @@ fn window_definition(p: &mut Parser<'_>) -> bool { if expr(p).is_none() { p.error("expected an expression"); } + while p.eat(COMMA) && !p.at(EOF) { + if expr(p).is_none() { + p.error("expected an expression"); + } + } } opt_order_by_clause(p); if p.at(RANGE_KW) || p.at(ROWS_KW) || p.at(GROUPS_KW) { diff --git a/crates/squawk_parser/tests/data/ok/select_cte.sql b/crates/squawk_parser/tests/data/ok/select_cte.sql index 5cf01a6f..70a4348d 100644 --- a/crates/squawk_parser/tests/data/ok/select_cte.sql +++ b/crates/squawk_parser/tests/data/ok/select_cte.sql @@ -117,3 +117,19 @@ select timestamp from t; with t(time) as (select 1) select time from t; + +-- regression gh issue #509 +WITH ranked_notifications AS ( + SELECT + notification_id, + ROW_NUMBER() OVER ( + PARTITION BY user_id, board_id ORDER BY created_at DESC + ) + FROM public.notification + WHERE android_channel_id = 'watchlist' +) +UPDATE public.notification +SET dismissed_at = current_timestamp +WHERE notification_id IN ( + SELECT notification_id FROM ranked_notifications WHERE rn > 1 +); diff --git a/crates/squawk_parser/tests/snapshots/tests__select_cte_ok.snap b/crates/squawk_parser/tests/snapshots/tests__select_cte_ok.snap index 584f12b6..c745ec0f 100644 --- a/crates/squawk_parser/tests/snapshots/tests__select_cte_ok.snap +++ b/crates/squawk_parser/tests/snapshots/tests__select_cte_ok.snap @@ -1276,4 +1276,154 @@ SOURCE_FILE NAME_REF IDENT "t" SEMICOLON ";" - WHITESPACE "\n\n" + WHITESPACE "\n\n\n" + COMMENT "-- regression gh issue #509" + WHITESPACE "\n" + UPDATE + WITH_CLAUSE + WITH_KW "WITH" + WHITESPACE " " + WITH_TABLE + NAME + IDENT "ranked_notifications" + WHITESPACE " " + AS_KW "AS" + WHITESPACE " " + L_PAREN "(" + WHITESPACE "\n " + SELECT + SELECT_CLAUSE + SELECT_KW "SELECT" + WHITESPACE " \n " + TARGET_LIST + TARGET + NAME_REF + IDENT "notification_id" + COMMA "," + WHITESPACE "\n " + TARGET + CALL_EXPR + NAME_REF + IDENT "ROW_NUMBER" + ARG_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + OVER_CLAUSE + OVER_KW "OVER" + WHITESPACE " " + L_PAREN "(" + WHITESPACE "\n " + WINDOW_DEF + PARTITION_KW "PARTITION" + WHITESPACE " " + BY_KW "BY" + WHITESPACE " " + NAME_REF + IDENT "user_id" + COMMA "," + WHITESPACE " " + NAME_REF + IDENT "board_id" + WHITESPACE " " + ORDER_BY_CLAUSE + ORDER_KW "ORDER" + WHITESPACE " " + BY_KW "BY" + WHITESPACE " " + NAME_REF + IDENT "created_at" + WHITESPACE " " + DESC_KW "DESC" + WHITESPACE "\n " + R_PAREN ")" + WHITESPACE "\n " + FROM_CLAUSE + FROM_KW "FROM" + WHITESPACE " " + FIELD_EXPR + NAME_REF + IDENT "public" + DOT "." + NAME_REF + IDENT "notification" + WHITESPACE "\n " + WHERE_CLAUSE + WHERE_KW "WHERE" + WHITESPACE " " + BIN_EXPR + NAME_REF + IDENT "android_channel_id" + WHITESPACE " " + EQ "=" + WHITESPACE " " + LITERAL + STRING "'watchlist'" + WHITESPACE "\n" + R_PAREN ")" + WHITESPACE "\n" + UPDATE_KW "UPDATE" + WHITESPACE " " + RELATION_NAME + PATH + PATH + PATH_SEGMENT + NAME_REF + IDENT "public" + DOT "." + PATH_SEGMENT + NAME_REF + IDENT "notification" + WHITESPACE "\n" + SET_KW "SET" + WHITESPACE " " + NAME_REF + IDENT "dismissed_at" + WHITESPACE " " + EQ "=" + WHITESPACE " " + NAME_REF + CURRENT_TIMESTAMP_KW "current_timestamp" + WHITESPACE "\n" + WHERE_CLAUSE + WHERE_KW "WHERE" + WHITESPACE " " + BIN_EXPR + NAME_REF + IDENT "notification_id" + WHITESPACE " " + IN_KW "IN" + WHITESPACE " " + PAREN_EXPR + L_PAREN "(" + WHITESPACE "\n " + SELECT + SELECT_CLAUSE + SELECT_KW "SELECT" + WHITESPACE " " + TARGET_LIST + TARGET + NAME_REF + IDENT "notification_id" + WHITESPACE " " + FROM_CLAUSE + FROM_KW "FROM" + WHITESPACE " " + NAME_REF + IDENT "ranked_notifications" + WHITESPACE " " + WHERE_CLAUSE + WHERE_KW "WHERE" + WHITESPACE " " + BIN_EXPR + NAME_REF + IDENT "rn" + WHITESPACE " " + R_ANGLE ">" + WHITESPACE " " + LITERAL + INT_NUMBER "1" + WHITESPACE "\n" + R_PAREN ")" + SEMICOLON ";" + WHITESPACE "\n"