|
125 | 125 | hsql::DatetimeField datetime_field; |
126 | 126 | hsql::DropColumnAction* drop_action_t; |
127 | 127 | hsql::Expr* expr; |
| 128 | + hsql::FrameBound* frame_bound; |
| 129 | + hsql::FrameDescription* frame_description; |
| 130 | + hsql::FrameType frame_type; |
128 | 131 | hsql::GroupByDescription* group_t; |
129 | 132 | hsql::ImportType import_type_t; |
130 | 133 | hsql::JoinType join_type; |
131 | 134 | hsql::LimitDescription* limit; |
| 135 | + hsql::LockingClause* locking_t; |
132 | 136 | hsql::OrderDescription* order; |
133 | 137 | hsql::OrderType order_type; |
134 | 138 | hsql::SetOperation* set_operator_t; |
|
137 | 141 | hsql::TableName table_name; |
138 | 142 | hsql::TableRef* table; |
139 | 143 | hsql::UpdateClause* update_t; |
| 144 | + hsql::WindowDescription* window_description; |
140 | 145 | hsql::WithDescription* with_description_t; |
141 | | - hsql::LockingClause* locking_t; |
142 | 146 |
|
143 | 147 | std::vector<char*>* str_vec; |
144 | 148 | std::unordered_set<hsql::ConstraintType>* column_constraint_set; |
|
161 | 165 | ** Destructor symbols |
162 | 166 | *********************************/ |
163 | 167 | // clang-format off |
164 | | - %destructor { } <fval> <ival> <bval> <join_type> <order_type> <datetime_field> <column_type_t> <column_constraint_t> <import_type_t> <column_constraint_set> <lock_mode_t> <lock_wait_policy_t> |
| 168 | + %destructor { } <fval> <ival> <bval> <join_type> <order_type> <datetime_field> <column_type_t> <column_constraint_t> <import_type_t> <column_constraint_set> <lock_mode_t> <lock_wait_policy_t> <frame_type> |
165 | 169 | %destructor { |
166 | 170 | free( ($$.name) ); |
167 | 171 | free( ($$.schema) ); |
|
202 | 206 | %token DOUBLE ESCAPE EXCEPT EXISTS EXTRACT CAST FORMAT GLOBAL HAVING IMPORT |
203 | 207 | %token INSERT ISNULL OFFSET RENAME SCHEMA SELECT SORTED |
204 | 208 | %token TABLES UNIQUE UNLOAD UPDATE VALUES AFTER ALTER CROSS |
205 | | - %token DELTA FLOAT GROUP INDEX INNER LIMIT LOCAL MERGE MINUS ORDER |
| 209 | + %token DELTA FLOAT GROUP INDEX INNER LIMIT LOCAL MERGE MINUS ORDER OVER |
206 | 210 | %token OUTER RIGHT TABLE UNION USING WHERE CALL CASE CHAR COPY DATE DATETIME |
207 | 211 | %token DESC DROP ELSE FILE FROM FULL HASH HINT INTO JOIN |
208 | | - %token LEFT LIKE LOAD LONG NULL PLAN SHOW TEXT THEN TIME |
| 212 | + %token LEFT LIKE LOAD LONG NULL PARTITION PLAN SHOW TEXT THEN TIME |
209 | 213 | %token VIEW WHEN WITH ADD ALL AND ASC END FOR INT KEY |
210 | 214 | %token NOT OFF SET TOP AS BY IF IN IS OF ON OR TO NO |
211 | 215 | %token ARRAY CONCAT ILIKE SECOND MINUTE HOUR DAY MONTH YEAR |
212 | 216 | %token SECONDS MINUTES HOURS DAYS MONTHS YEARS INTERVAL |
213 | 217 | %token TRUE FALSE BOOLEAN |
214 | 218 | %token TRANSACTION BEGIN COMMIT ROLLBACK |
215 | 219 | %token NOWAIT SKIP LOCKED SHARE |
| 220 | + %token RANGE ROWS GROUPS UNBOUNDED FOLLOWING PRECEDING CURRENT_ROW |
216 | 221 |
|
217 | 222 | /********************************* |
218 | 223 | ** Non-Terminal types (http://www.gnu.org/software/bison/manual/html_node/Type-Decl.html) |
|
235 | 240 | %type <table_name> table_name |
236 | 241 | %type <sval> opt_index_name |
237 | 242 | %type <sval> file_path prepare_target_query |
| 243 | + %type <frame_description> opt_frame_clause |
| 244 | + %type <frame_bound> frame_bound |
| 245 | + %type <frame_type> frame_type |
| 246 | + %type <window_description> opt_window |
238 | 247 | %type <bval> opt_not_exists opt_exists opt_distinct opt_all |
239 | 248 | %type <ival_pair> opt_decimal_specification |
240 | 249 | %type <ival> opt_time_precision |
|
272 | 281 | %type <import_type_t> opt_file_type file_type |
273 | 282 |
|
274 | 283 | %type <str_vec> ident_commalist opt_column_list |
275 | | - %type <expr_vec> expr_list select_list opt_literal_list literal_list hint_list opt_hints |
| 284 | + %type <expr_vec> expr_list select_list opt_literal_list literal_list hint_list opt_hints opt_partition |
276 | 285 | %type <table_vec> table_ref_commalist |
277 | 286 | %type <order_vec> opt_order order_list |
278 | 287 | %type <with_description_vec> opt_with_clause with_clause with_description_list |
@@ -978,8 +987,37 @@ comp_expr : operand '=' operand { $$ = Expr::makeOpBinary($1, kOpEquals, $3); } |
978 | 987 | | operand LESSEQ operand { $$ = Expr::makeOpBinary($1, kOpLessEq, $3); } |
979 | 988 | | operand GREATEREQ operand { $$ = Expr::makeOpBinary($1, kOpGreaterEq, $3); }; |
980 | 989 |
|
981 | | -function_expr : IDENTIFIER '(' ')' { $$ = Expr::makeFunctionRef($1, new std::vector<Expr*>(), false); } |
982 | | -| IDENTIFIER '(' opt_distinct expr_list ')' { $$ = Expr::makeFunctionRef($1, $4, $3); }; |
| 990 | +// `function_expr is used for window functions, aggregate expressions, and functions calls because we run into shift/ |
| 991 | +// reduce conflicts when splitting them. |
| 992 | +function_expr : IDENTIFIER '(' ')' opt_window { $$ = Expr::makeFunctionRef($1, new std::vector<Expr*>(), false, $4); } |
| 993 | +| IDENTIFIER '(' opt_distinct expr_list ')' opt_window { $$ = Expr::makeFunctionRef($1, $4, $3, $6); }; |
| 994 | + |
| 995 | +// Window function expressions, based on https://www.postgresql.org/docs/15/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS |
| 996 | +// We do not support named windows, collations and exclusions (for simplicity) and filters (not part of the SQL standard). |
| 997 | +opt_window : OVER '(' opt_partition opt_order opt_frame_clause ')' { $$ = new WindowDescription($3, $4, $5); } |
| 998 | +| /* empty */ { $$ = nullptr; }; |
| 999 | + |
| 1000 | +opt_partition : PARTITION BY expr_list { $$ = $3; } |
| 1001 | +| /* empty */ { $$ = nullptr; }; |
| 1002 | + |
| 1003 | +// We use the Postgres default if the frame end or the whole frame clause is omitted. "If `frame_end` is omitted, the |
| 1004 | +// end defaults to `CURRENT ROW`. [...] The default framing option is `RANGE UNBOUNDED PRECEDING`, which is the same as |
| 1005 | +// `RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW`." |
| 1006 | +opt_frame_clause : frame_type frame_bound { $$ = new FrameDescription{$1, $2, new FrameBound{0, kCurrentRow, false}}; } |
| 1007 | +| frame_type BETWEEN frame_bound AND frame_bound { $$ = new FrameDescription{$1, $3, $5}; } |
| 1008 | +| /* empty */ { |
| 1009 | + $$ = new FrameDescription{kRange, new FrameBound{0, kPreceding, true}, new FrameBound{0, kCurrentRow, false}}; |
| 1010 | +}; |
| 1011 | + |
| 1012 | +frame_type : RANGE { $$ = kRange; } |
| 1013 | +| ROWS { $$ = kRows; } |
| 1014 | +| GROUPS { $$ = kGroups; }; |
| 1015 | + |
| 1016 | +frame_bound : UNBOUNDED PRECEDING { $$ = new FrameBound{0, kPreceding, true}; } |
| 1017 | +| INTVAL PRECEDING { $$ = new FrameBound{$1, kPreceding, false}; } |
| 1018 | +| UNBOUNDED FOLLOWING { $$ = new FrameBound{0, kFollowing, true}; } |
| 1019 | +| INTVAL FOLLOWING { $$ = new FrameBound{$1, kFollowing, false}; } |
| 1020 | +| CURRENT_ROW { $$ = new FrameBound{0, kCurrentRow, false}; }; |
983 | 1021 |
|
984 | 1022 | extract_expr : EXTRACT '(' datetime_field FROM expr ')' { $$ = Expr::makeExtract($3, $5); }; |
985 | 1023 |
|
|
0 commit comments