From cc34ab3e01cd2dcafed76da2879677085d5f8083 Mon Sep 17 00:00:00 2001 From: Eric Kidd Date: Thu, 9 Nov 2023 09:33:58 -0500 Subject: [PATCH] Figure out FIRST_VALUE & LAST_VALUE --- src/ast.rs | 20 +++++++++++++++++++ .../functions/windows/first_last_value.sql | 6 ++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index 32679e1..1c542fe 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1416,6 +1416,10 @@ pub enum WindowFrameStart { unbounded_token: Keyword, preceding_token: Keyword, }, + CurrentRow { + current_token: Keyword, + row_token: PseudoKeyword, + }, } /// A window frame end. Keep this simple for now. @@ -1425,6 +1429,10 @@ pub enum WindowFrameEnd { current_token: Keyword, row_token: PseudoKeyword, }, + UnboundedFollowing { + unbounded_token: Keyword, + following_token: Keyword, + }, } /// Data types. @@ -2544,6 +2552,12 @@ peg::parser! { preceding_token, } } + / current_token:k("CURRENT") row_token:pk("ROW") { + WindowFrameStart::CurrentRow { + current_token, + row_token, + } + } rule window_frame_end() -> WindowFrameEnd = current_token:k("CURRENT") row_token:pk("ROW") { @@ -2552,6 +2566,12 @@ peg::parser! { row_token, } } + / unbounded_token:k("UNBOUNDED") following_token:k("FOLLOWING") { + WindowFrameEnd::UnboundedFollowing { + unbounded_token, + following_token, + } + } rule cast() -> Cast = cast_type:cast_type() paren1:p("(") expression:expression() as_token:k("AS") data_type:data_type() paren2:p(")") { diff --git a/tests/sql/functions/windows/first_last_value.sql b/tests/sql/functions/windows/first_last_value.sql index 8ab72e0..9681b76 100644 --- a/tests/sql/functions/windows/first_last_value.sql +++ b/tests/sql/functions/windows/first_last_value.sql @@ -1,6 +1,3 @@ --- pending: sqlite3 FIRST_VALUE, LAST_VALUE seem to require frames to work? --- pending: trino FIRST_VALUE, LAST_VALUE seem to require frames to work? - -- FIRST_VALUE, LAST_VALUE -- A fixture table for testing window functions. @@ -22,7 +19,8 @@ CREATE OR REPLACE TABLE __result1 AS SELECT item, FIRST_VALUE(item) OVER (PARTITION BY category ORDER BY price) AS cheapest_alternative, - LAST_VALUE(item) OVER (PARTITION BY category ORDER BY price) AS most_expensive_alternative, + -- We need the RANGE frame here. + LAST_VALUE(item) OVER (PARTITION BY category ORDER BY price RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS most_expensive_alternative, FROM groceries; CREATE OR REPLACE TABLE __expected1 (