Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * parse_agg.c
4 : : * handle aggregates and window functions in parser
5 : : *
6 : : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 : : * Portions Copyright (c) 1994, Regents of the University of California
8 : : *
9 : : *
10 : : * IDENTIFICATION
11 : : * src/backend/parser/parse_agg.c
12 : : *
13 : : *-------------------------------------------------------------------------
14 : : */
15 : : #include "postgres.h"
16 : :
17 : : #include "access/htup_details.h"
18 : : #include "catalog/pg_aggregate.h"
19 : : #include "catalog/pg_constraint.h"
20 : : #include "catalog/pg_type.h"
21 : : #include "common/int.h"
22 : : #include "nodes/makefuncs.h"
23 : : #include "nodes/nodeFuncs.h"
24 : : #include "optimizer/optimizer.h"
25 : : #include "parser/parse_agg.h"
26 : : #include "parser/parse_clause.h"
27 : : #include "parser/parse_coerce.h"
28 : : #include "parser/parse_expr.h"
29 : : #include "parser/parse_relation.h"
30 : : #include "parser/parsetree.h"
31 : : #include "rewrite/rewriteManip.h"
32 : : #include "utils/builtins.h"
33 : : #include "utils/lsyscache.h"
34 : : #include "utils/syscache.h"
35 : :
36 : : typedef struct
37 : : {
38 : : ParseState *pstate;
39 : : int min_varlevel;
40 : : int min_agglevel;
41 : : int sublevels_up;
42 : : } check_agg_arguments_context;
43 : :
44 : : typedef struct
45 : : {
46 : : ParseState *pstate;
47 : : Query *qry;
48 : : bool hasJoinRTEs;
49 : : List *groupClauses;
50 : : List *groupClauseCommonVars;
51 : : List *gset_common;
52 : : bool have_non_var_grouping;
53 : : List **func_grouped_rels;
54 : : int sublevels_up;
55 : : bool in_agg_direct_args;
56 : : } substitute_grouped_columns_context;
57 : :
58 : : static int check_agg_arguments(ParseState *pstate,
59 : : List *directargs,
60 : : List *args,
61 : : Expr *filter);
62 : : static bool check_agg_arguments_walker(Node *node,
63 : : check_agg_arguments_context *context);
64 : : static Node *substitute_grouped_columns(Node *node, ParseState *pstate, Query *qry,
65 : : List *groupClauses, List *groupClauseCommonVars,
66 : : List *gset_common,
67 : : bool have_non_var_grouping,
68 : : List **func_grouped_rels);
69 : : static Node *substitute_grouped_columns_mutator(Node *node,
70 : : substitute_grouped_columns_context *context);
71 : : static void finalize_grouping_exprs(Node *node, ParseState *pstate, Query *qry,
72 : : List *groupClauses, bool hasJoinRTEs,
73 : : bool have_non_var_grouping);
74 : : static bool finalize_grouping_exprs_walker(Node *node,
75 : : substitute_grouped_columns_context *context);
76 : : static Var *buildGroupedVar(int attnum, Index ressortgroupref,
77 : : substitute_grouped_columns_context *context);
78 : : static void check_agglevels_and_constraints(ParseState *pstate, Node *expr);
79 : : static List *expand_groupingset_node(GroupingSet *gs);
80 : : static Node *make_agg_arg(Oid argtype, Oid argcollation);
81 : :
82 : :
83 : : /*
84 : : * transformAggregateCall -
85 : : * Finish initial transformation of an aggregate call
86 : : *
87 : : * parse_func.c has recognized the function as an aggregate, and has set up
88 : : * all the fields of the Aggref except aggargtypes, aggdirectargs, args,
89 : : * aggorder, aggdistinct and agglevelsup. The passed-in args list has been
90 : : * through standard expression transformation and type coercion to match the
91 : : * agg's declared arg types, while the passed-in aggorder list hasn't been
92 : : * transformed at all.
93 : : *
94 : : * Here we separate the args list into direct and aggregated args, storing the
95 : : * former in agg->aggdirectargs and the latter in agg->args. The regular
96 : : * args, but not the direct args, are converted into a targetlist by inserting
97 : : * TargetEntry nodes. We then transform the aggorder and agg_distinct
98 : : * specifications to produce lists of SortGroupClause nodes for agg->aggorder
99 : : * and agg->aggdistinct. (For a regular aggregate, this might result in
100 : : * adding resjunk expressions to the targetlist; but for ordered-set
101 : : * aggregates the aggorder list will always be one-to-one with the aggregated
102 : : * args.)
103 : : *
104 : : * We must also determine which query level the aggregate actually belongs to,
105 : : * set agglevelsup accordingly, and mark p_hasAggs true in the corresponding
106 : : * pstate level.
107 : : */
108 : : void
5703 tgl@sss.pgh.pa.us 109 :CBC 21289 : transformAggregateCall(ParseState *pstate, Aggref *agg,
110 : : List *args, List *aggorder, bool agg_distinct)
111 : : {
3419 112 : 21289 : List *argtypes = NIL;
4326 113 : 21289 : List *tlist = NIL;
114 : 21289 : List *torder = NIL;
5722 bruce@momjian.us 115 : 21289 : List *tdistinct = NIL;
4326 tgl@sss.pgh.pa.us 116 : 21289 : AttrNumber attno = 1;
117 : : int save_next_resno;
118 : : ListCell *lc;
119 : :
120 [ + + ]: 21289 : if (AGGKIND_IS_ORDERED_SET(agg->aggkind))
121 : : {
122 : : /*
123 : : * For an ordered-set agg, the args list includes direct args and
124 : : * aggregated args; we must split them apart.
125 : : */
126 : 159 : int numDirectArgs = list_length(args) - list_length(aggorder);
127 : : List *aargs;
128 : : ListCell *lc2;
129 : :
130 [ - + ]: 159 : Assert(numDirectArgs >= 0);
131 : :
132 : 159 : aargs = list_copy_tail(args, numDirectArgs);
133 : 159 : agg->aggdirectargs = list_truncate(args, numDirectArgs);
134 : :
135 : : /*
136 : : * Build a tlist from the aggregated args, and make a sortlist entry
137 : : * for each one. Note that the expressions in the SortBy nodes are
138 : : * ignored (they are the raw versions of the transformed args); we are
139 : : * just looking at the sort information in the SortBy nodes.
140 : : */
141 [ + - + + : 345 : forboth(lc, aargs, lc2, aggorder)
+ - + + +
+ + - +
+ ]
142 : : {
143 : 186 : Expr *arg = (Expr *) lfirst(lc);
144 : 186 : SortBy *sortby = (SortBy *) lfirst(lc2);
145 : : TargetEntry *tle;
146 : :
147 : : /* We don't bother to assign column names to the entries */
148 : 186 : tle = makeTargetEntry(arg, attno++, NULL, false);
149 : 186 : tlist = lappend(tlist, tle);
150 : :
151 : 186 : torder = addTargetToSortList(pstate, tle,
152 : : torder, tlist, sortby);
153 : : }
154 : :
155 : : /* Never any DISTINCT in an ordered-set agg */
156 [ - + ]: 159 : Assert(!agg_distinct);
157 : : }
158 : : else
159 : : {
160 : : /* Regular aggregate, so it has no direct args */
161 : 21130 : agg->aggdirectargs = NIL;
162 : :
163 : : /*
164 : : * Transform the plain list of Exprs into a targetlist.
165 : : */
166 [ + + + + : 38404 : foreach(lc, args)
+ + ]
167 : : {
168 : 17274 : Expr *arg = (Expr *) lfirst(lc);
169 : : TargetEntry *tle;
170 : :
171 : : /* We don't bother to assign column names to the entries */
172 : 17274 : tle = makeTargetEntry(arg, attno++, NULL, false);
173 : 17274 : tlist = lappend(tlist, tle);
174 : : }
175 : :
176 : : /*
177 : : * If we have an ORDER BY, transform it. This will add columns to the
178 : : * tlist if they appear in ORDER BY but weren't already in the arg
179 : : * list. They will be marked resjunk = true so we can tell them apart
180 : : * from regular aggregate arguments later.
181 : : *
182 : : * We need to mess with p_next_resno since it will be used to number
183 : : * any new targetlist entries.
184 : : */
185 : 21130 : save_next_resno = pstate->p_next_resno;
186 : 21130 : pstate->p_next_resno = attno;
187 : :
188 : 21130 : torder = transformSortClause(pstate,
189 : : aggorder,
190 : : &tlist,
191 : : EXPR_KIND_ORDER_BY,
192 : : true /* force SQL99 rules */ );
193 : :
194 : : /*
195 : : * If we have DISTINCT, transform that to produce a distinctList.
196 : : */
197 [ + + ]: 21130 : if (agg_distinct)
198 : : {
199 : 275 : tdistinct = transformDistinctClause(pstate, &tlist, torder, true);
200 : :
201 : : /*
202 : : * Remove this check if executor support for hashed distinct for
203 : : * aggregates is ever added.
204 : : */
205 [ + - + + : 604 : foreach(lc, tdistinct)
+ + ]
206 : : {
207 : 347 : SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc);
208 : :
209 [ - + ]: 347 : if (!OidIsValid(sortcl->sortop))
210 : : {
4326 tgl@sss.pgh.pa.us 211 :UBC 0 : Node *expr = get_sortgroupclause_expr(sortcl, tlist);
212 : :
213 [ # # ]: 0 : ereport(ERROR,
214 : : (errcode(ERRCODE_UNDEFINED_FUNCTION),
215 : : errmsg("could not identify an ordering operator for type %s",
216 : : format_type_be(exprType(expr))),
217 : : errdetail("Aggregates with DISTINCT must be able to sort their inputs."),
218 : : parser_errposition(pstate, exprLocation(expr))));
219 : : }
220 : : }
221 : : }
222 : :
4326 tgl@sss.pgh.pa.us 223 :CBC 21112 : pstate->p_next_resno = save_next_resno;
224 : : }
225 : :
226 : : /* Update the Aggref with the transformation results */
5795 227 : 21271 : agg->args = tlist;
228 : 21271 : agg->aggorder = torder;
229 : 21271 : agg->aggdistinct = tdistinct;
230 : :
231 : : /*
232 : : * Now build the aggargtypes list with the type OIDs of the direct and
233 : : * aggregated args, ignoring any resjunk entries that might have been
234 : : * added by ORDER BY/DISTINCT processing. We can't do this earlier
235 : : * because said processing can modify some args' data types, in particular
236 : : * by resolving previously-unresolved "unknown" literals.
237 : : */
721 238 [ + + + + : 21454 : foreach(lc, agg->aggdirectargs)
+ + ]
239 : : {
240 : 183 : Expr *arg = (Expr *) lfirst(lc);
241 : :
242 : 183 : argtypes = lappend_oid(argtypes, exprType((Node *) arg));
243 : : }
244 [ + + + + : 39484 : foreach(lc, tlist)
+ + ]
245 : : {
246 : 18213 : TargetEntry *tle = (TargetEntry *) lfirst(lc);
247 : :
248 [ + + ]: 18213 : if (tle->resjunk)
249 : 801 : continue; /* ignore junk */
250 : 17412 : argtypes = lappend_oid(argtypes, exprType((Node *) tle->expr));
251 : : }
252 : 21271 : agg->aggargtypes = argtypes;
253 : :
3817 andres@anarazel.de 254 : 21271 : check_agglevels_and_constraints(pstate, (Node *) agg);
255 : 21199 : }
256 : :
257 : : /*
258 : : * transformGroupingFunc
259 : : * Transform a GROUPING expression
260 : : *
261 : : * GROUPING() behaves very like an aggregate. Processing of levels and nesting
262 : : * is done as for aggregates. We set p_hasAggs for these expressions too.
263 : : */
264 : : Node *
265 : 181 : transformGroupingFunc(ParseState *pstate, GroupingFunc *p)
266 : : {
267 : : ListCell *lc;
268 : 181 : List *args = p->args;
269 : 181 : List *result_list = NIL;
270 : 181 : GroupingFunc *result = makeNode(GroupingFunc);
271 : :
272 [ - + ]: 181 : if (list_length(args) > 31)
3817 andres@anarazel.de 273 [ # # ]:UBC 0 : ereport(ERROR,
274 : : (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
275 : : errmsg("GROUPING must have fewer than 32 arguments"),
276 : : parser_errposition(pstate, p->location)));
277 : :
3817 andres@anarazel.de 278 [ + - + + :CBC 460 : foreach(lc, args)
+ + ]
279 : : {
280 : : Node *current_result;
281 : :
3810 bruce@momjian.us 282 : 279 : current_result = transformExpr(pstate, (Node *) lfirst(lc), pstate->p_expr_kind);
283 : :
284 : : /* acceptability of expressions is checked later */
285 : :
3817 andres@anarazel.de 286 : 279 : result_list = lappend(result_list, current_result);
287 : : }
288 : :
289 : 181 : result->args = result_list;
290 : 181 : result->location = p->location;
291 : :
292 : 181 : check_agglevels_and_constraints(pstate, (Node *) result);
293 : :
294 : 181 : return (Node *) result;
295 : : }
296 : :
297 : : /*
298 : : * Aggregate functions and grouping operations (which are combined in the spec
299 : : * as <set function specification>) are very similar with regard to level and
300 : : * nesting restrictions (though we allow a lot more things than the spec does).
301 : : * Centralise those restrictions here.
302 : : */
303 : : static void
304 : 21452 : check_agglevels_and_constraints(ParseState *pstate, Node *expr)
305 : : {
306 : 21452 : List *directargs = NIL;
307 : 21452 : List *args = NIL;
308 : 21452 : Expr *filter = NULL;
309 : : int min_varlevel;
310 : 21452 : int location = -1;
311 : : Index *p_levelsup;
312 : : const char *err;
313 : : bool errkind;
314 : 21452 : bool isAgg = IsA(expr, Aggref);
315 : :
316 [ + + ]: 21452 : if (isAgg)
317 : : {
3810 bruce@momjian.us 318 : 21271 : Aggref *agg = (Aggref *) expr;
319 : :
3817 andres@anarazel.de 320 : 21271 : directargs = agg->aggdirectargs;
321 : 21271 : args = agg->args;
322 : 21271 : filter = agg->aggfilter;
323 : 21271 : location = agg->location;
324 : 21271 : p_levelsup = &agg->agglevelsup;
325 : : }
326 : : else
327 : : {
328 : 181 : GroupingFunc *grp = (GroupingFunc *) expr;
329 : :
330 : 181 : args = grp->args;
331 : 181 : location = grp->location;
332 : 181 : p_levelsup = &grp->agglevelsup;
333 : : }
334 : :
335 : : /*
336 : : * Check the arguments to compute the aggregate's level and detect
337 : : * improper nesting.
338 : : */
4326 tgl@sss.pgh.pa.us 339 : 21452 : min_varlevel = check_agg_arguments(pstate,
340 : : directargs,
341 : : args,
342 : : filter);
343 : :
3817 andres@anarazel.de 344 : 21428 : *p_levelsup = min_varlevel;
345 : :
346 : : /* Mark the correct pstate level as having aggregates */
4826 tgl@sss.pgh.pa.us 347 [ + + ]: 21517 : while (min_varlevel-- > 0)
348 : 89 : pstate = pstate->parentParseState;
349 : 21428 : pstate->p_hasAggs = true;
350 : :
351 : : /*
352 : : * Check to see if the aggregate function is in an invalid place within
353 : : * its aggregation query.
354 : : *
355 : : * For brevity we support two schemes for reporting an error here: set
356 : : * "err" to a custom message, or set "errkind" true if the error context
357 : : * is sufficiently identified by what ParseExprKindName will return, *and*
358 : : * what it will return is just a SQL keyword. (Otherwise, use a custom
359 : : * message to avoid creating translation problems.)
360 : : */
361 : 21428 : err = NULL;
362 : 21428 : errkind = false;
363 [ - - - + : 21428 : switch (pstate->p_expr_kind)
- + + + +
- + - - -
+ - - - +
- - - - -
+ - - - -
- - + + +
- + - - ]
364 : : {
4826 tgl@sss.pgh.pa.us 365 :UBC 0 : case EXPR_KIND_NONE:
366 : 0 : Assert(false); /* can't happen */
367 : : break;
368 : 0 : case EXPR_KIND_OTHER:
369 : :
370 : : /*
371 : : * Accept aggregate/grouping here; caller must throw error if
372 : : * wanted
373 : : */
374 : 0 : break;
375 : 0 : case EXPR_KIND_JOIN_ON:
376 : : case EXPR_KIND_JOIN_USING:
3817 andres@anarazel.de 377 [ # # ]: 0 : if (isAgg)
378 : 0 : err = _("aggregate functions are not allowed in JOIN conditions");
379 : : else
380 : 0 : err = _("grouping operations are not allowed in JOIN conditions");
381 : :
4826 tgl@sss.pgh.pa.us 382 : 0 : break;
4826 tgl@sss.pgh.pa.us 383 :CBC 12 : case EXPR_KIND_FROM_SUBSELECT:
384 : :
385 : : /*
386 : : * Aggregate/grouping scope rules make it worth being explicit
387 : : * here
388 : : */
3817 andres@anarazel.de 389 [ + - ]: 12 : if (isAgg)
390 : 12 : err = _("aggregate functions are not allowed in FROM clause of their own query level");
391 : : else
3817 andres@anarazel.de 392 :UBC 0 : err = _("grouping operations are not allowed in FROM clause of their own query level");
393 : :
4826 tgl@sss.pgh.pa.us 394 :CBC 12 : break;
4826 tgl@sss.pgh.pa.us 395 :UBC 0 : case EXPR_KIND_FROM_FUNCTION:
3817 andres@anarazel.de 396 [ # # ]: 0 : if (isAgg)
397 : 0 : err = _("aggregate functions are not allowed in functions in FROM");
398 : : else
399 : 0 : err = _("grouping operations are not allowed in functions in FROM");
400 : :
4826 tgl@sss.pgh.pa.us 401 : 0 : break;
4826 tgl@sss.pgh.pa.us 402 :CBC 6 : case EXPR_KIND_WHERE:
403 : 6 : errkind = true;
3743 mail@joeconway.com 404 : 6 : break;
405 : 3 : case EXPR_KIND_POLICY:
406 [ + - ]: 3 : if (isAgg)
407 : 3 : err = _("aggregate functions are not allowed in policy expressions");
408 : : else
3743 mail@joeconway.com 409 :UBC 0 : err = _("grouping operations are not allowed in policy expressions");
410 : :
4826 tgl@sss.pgh.pa.us 411 :CBC 3 : break;
412 : 338 : case EXPR_KIND_HAVING:
413 : : /* okay */
414 : 338 : break;
4486 noah@leadboat.com 415 : 6 : case EXPR_KIND_FILTER:
416 : 6 : errkind = true;
417 : 6 : break;
4826 tgl@sss.pgh.pa.us 418 :UBC 0 : case EXPR_KIND_WINDOW_PARTITION:
419 : : /* okay */
420 : 0 : break;
4826 tgl@sss.pgh.pa.us 421 :CBC 6 : case EXPR_KIND_WINDOW_ORDER:
422 : : /* okay */
423 : 6 : break;
4826 tgl@sss.pgh.pa.us 424 :UBC 0 : case EXPR_KIND_WINDOW_FRAME_RANGE:
3817 andres@anarazel.de 425 [ # # ]: 0 : if (isAgg)
426 : 0 : err = _("aggregate functions are not allowed in window RANGE");
427 : : else
428 : 0 : err = _("grouping operations are not allowed in window RANGE");
429 : :
4826 tgl@sss.pgh.pa.us 430 : 0 : break;
431 : 0 : case EXPR_KIND_WINDOW_FRAME_ROWS:
3817 andres@anarazel.de 432 [ # # ]: 0 : if (isAgg)
433 : 0 : err = _("aggregate functions are not allowed in window ROWS");
434 : : else
435 : 0 : err = _("grouping operations are not allowed in window ROWS");
436 : :
2819 tgl@sss.pgh.pa.us 437 : 0 : break;
438 : 0 : case EXPR_KIND_WINDOW_FRAME_GROUPS:
439 [ # # ]: 0 : if (isAgg)
440 : 0 : err = _("aggregate functions are not allowed in window GROUPS");
441 : : else
442 : 0 : err = _("grouping operations are not allowed in window GROUPS");
443 : :
4826 444 : 0 : break;
4826 tgl@sss.pgh.pa.us 445 :CBC 20996 : case EXPR_KIND_SELECT_TARGET:
446 : : /* okay */
447 : 20996 : break;
4826 tgl@sss.pgh.pa.us 448 :UBC 0 : case EXPR_KIND_INSERT_TARGET:
449 : : case EXPR_KIND_UPDATE_SOURCE:
450 : : case EXPR_KIND_UPDATE_TARGET:
451 : 0 : errkind = true;
1309 alvherre@alvh.no-ip. 452 : 0 : break;
453 : 0 : case EXPR_KIND_MERGE_WHEN:
454 [ # # ]: 0 : if (isAgg)
455 : 0 : err = _("aggregate functions are not allowed in MERGE WHEN conditions");
456 : : else
457 : 0 : err = _("grouping operations are not allowed in MERGE WHEN conditions");
458 : :
4826 tgl@sss.pgh.pa.us 459 : 0 : break;
460 : 0 : case EXPR_KIND_GROUP_BY:
461 : 0 : errkind = true;
462 : 0 : break;
4826 tgl@sss.pgh.pa.us 463 :CBC 40 : case EXPR_KIND_ORDER_BY:
464 : : /* okay */
465 : 40 : break;
4826 tgl@sss.pgh.pa.us 466 :UBC 0 : case EXPR_KIND_DISTINCT_ON:
467 : : /* okay */
468 : 0 : break;
469 : 0 : case EXPR_KIND_LIMIT:
470 : : case EXPR_KIND_OFFSET:
471 : 0 : errkind = true;
472 : 0 : break;
473 : 0 : case EXPR_KIND_RETURNING:
474 : : case EXPR_KIND_MERGE_RETURNING:
475 : 0 : errkind = true;
476 : 0 : break;
477 : 0 : case EXPR_KIND_VALUES:
478 : : case EXPR_KIND_VALUES_SINGLE:
479 : 0 : errkind = true;
480 : 0 : break;
481 : 0 : case EXPR_KIND_CHECK_CONSTRAINT:
482 : : case EXPR_KIND_DOMAIN_CHECK:
3817 andres@anarazel.de 483 [ # # ]: 0 : if (isAgg)
484 : 0 : err = _("aggregate functions are not allowed in check constraints");
485 : : else
486 : 0 : err = _("grouping operations are not allowed in check constraints");
487 : :
4826 tgl@sss.pgh.pa.us 488 : 0 : break;
4826 tgl@sss.pgh.pa.us 489 :CBC 3 : case EXPR_KIND_COLUMN_DEFAULT:
490 : : case EXPR_KIND_FUNCTION_DEFAULT:
491 : :
3817 andres@anarazel.de 492 [ + - ]: 3 : if (isAgg)
493 : 3 : err = _("aggregate functions are not allowed in DEFAULT expressions");
494 : : else
3817 andres@anarazel.de 495 :UBC 0 : err = _("grouping operations are not allowed in DEFAULT expressions");
496 : :
4826 tgl@sss.pgh.pa.us 497 :CBC 3 : break;
4826 tgl@sss.pgh.pa.us 498 :UBC 0 : case EXPR_KIND_INDEX_EXPRESSION:
3817 andres@anarazel.de 499 [ # # ]: 0 : if (isAgg)
500 : 0 : err = _("aggregate functions are not allowed in index expressions");
501 : : else
502 : 0 : err = _("grouping operations are not allowed in index expressions");
503 : :
4826 tgl@sss.pgh.pa.us 504 : 0 : break;
505 : 0 : case EXPR_KIND_INDEX_PREDICATE:
3817 andres@anarazel.de 506 [ # # ]: 0 : if (isAgg)
507 : 0 : err = _("aggregate functions are not allowed in index predicates");
508 : : else
509 : 0 : err = _("grouping operations are not allowed in index predicates");
510 : :
1676 tomas.vondra@postgre 511 : 0 : break;
512 : 0 : case EXPR_KIND_STATS_EXPRESSION:
513 [ # # ]: 0 : if (isAgg)
514 : 0 : err = _("aggregate functions are not allowed in statistics expressions");
515 : : else
516 : 0 : err = _("grouping operations are not allowed in statistics expressions");
517 : :
4826 tgl@sss.pgh.pa.us 518 : 0 : break;
519 : 0 : case EXPR_KIND_ALTER_COL_TRANSFORM:
3817 andres@anarazel.de 520 [ # # ]: 0 : if (isAgg)
521 : 0 : err = _("aggregate functions are not allowed in transform expressions");
522 : : else
523 : 0 : err = _("grouping operations are not allowed in transform expressions");
524 : :
4826 tgl@sss.pgh.pa.us 525 : 0 : break;
526 : 0 : case EXPR_KIND_EXECUTE_PARAMETER:
3817 andres@anarazel.de 527 [ # # ]: 0 : if (isAgg)
528 : 0 : err = _("aggregate functions are not allowed in EXECUTE parameters");
529 : : else
530 : 0 : err = _("grouping operations are not allowed in EXECUTE parameters");
531 : :
4826 tgl@sss.pgh.pa.us 532 : 0 : break;
533 : 0 : case EXPR_KIND_TRIGGER_WHEN:
3817 andres@anarazel.de 534 [ # # ]: 0 : if (isAgg)
535 : 0 : err = _("aggregate functions are not allowed in trigger WHEN conditions");
536 : : else
537 : 0 : err = _("grouping operations are not allowed in trigger WHEN conditions");
538 : :
2467 peter@eisentraut.org 539 : 0 : break;
2467 peter@eisentraut.org 540 :CBC 6 : case EXPR_KIND_PARTITION_BOUND:
541 [ + - ]: 6 : if (isAgg)
542 : 6 : err = _("aggregate functions are not allowed in partition bound");
543 : : else
2467 peter@eisentraut.org 544 :UBC 0 : err = _("grouping operations are not allowed in partition bound");
545 : :
4826 tgl@sss.pgh.pa.us 546 :CBC 6 : break;
3246 rhaas@postgresql.org 547 : 3 : case EXPR_KIND_PARTITION_EXPRESSION:
548 [ + - ]: 3 : if (isAgg)
2816 tgl@sss.pgh.pa.us 549 : 3 : err = _("aggregate functions are not allowed in partition key expressions");
550 : : else
2816 tgl@sss.pgh.pa.us 551 :UBC 0 : err = _("grouping operations are not allowed in partition key expressions");
552 : :
3246 rhaas@postgresql.org 553 :CBC 3 : break;
2403 peter@eisentraut.org 554 : 6 : case EXPR_KIND_GENERATED_COLUMN:
555 : :
556 [ + - ]: 6 : if (isAgg)
557 : 6 : err = _("aggregate functions are not allowed in column generation expressions");
558 : : else
2403 peter@eisentraut.org 559 :UBC 0 : err = _("grouping operations are not allowed in column generation expressions");
560 : :
2403 peter@eisentraut.org 561 :CBC 6 : break;
562 : :
2816 tgl@sss.pgh.pa.us 563 :UBC 0 : case EXPR_KIND_CALL_ARGUMENT:
2888 peter_e@gmx.net 564 [ # # ]: 0 : if (isAgg)
565 : 0 : err = _("aggregate functions are not allowed in CALL arguments");
566 : : else
567 : 0 : err = _("grouping operations are not allowed in CALL arguments");
568 : :
569 : 0 : break;
570 : :
2473 tomas.vondra@postgre 571 :CBC 3 : case EXPR_KIND_COPY_WHERE:
572 [ + - ]: 3 : if (isAgg)
573 : 3 : err = _("aggregate functions are not allowed in COPY FROM WHERE conditions");
574 : : else
2473 tomas.vondra@postgre 575 :UBC 0 : err = _("grouping operations are not allowed in COPY FROM WHERE conditions");
576 : :
2473 tomas.vondra@postgre 577 :CBC 3 : break;
578 : :
1729 peter@eisentraut.org 579 :UBC 0 : case EXPR_KIND_CYCLE_MARK:
580 : 0 : errkind = true;
581 : 0 : break;
582 : :
583 : : /*
584 : : * There is intentionally no default: case here, so that the
585 : : * compiler will warn if we add a new ParseExprKind without
586 : : * extending this switch. If we do see an unrecognized value at
587 : : * runtime, the behavior will be the same as for EXPR_KIND_OTHER,
588 : : * which is sane anyway.
589 : : */
590 : : }
591 : :
4826 tgl@sss.pgh.pa.us 592 [ + + ]:CBC 21428 : if (err)
6147 593 [ + - ]: 36 : ereport(ERROR,
594 : : (errcode(ERRCODE_GROUPING_ERROR),
595 : : errmsg_internal("%s", err),
596 : : parser_errposition(pstate, location)));
597 : :
4826 598 [ + + ]: 21392 : if (errkind)
599 : : {
3817 andres@anarazel.de 600 [ + - ]: 12 : if (isAgg)
601 : : /* translator: %s is name of a SQL construct, eg GROUP BY */
602 : 12 : err = _("aggregate functions are not allowed in %s");
603 : : else
604 : : /* translator: %s is name of a SQL construct, eg GROUP BY */
3817 andres@anarazel.de 605 :UBC 0 : err = _("grouping operations are not allowed in %s");
606 : :
4826 tgl@sss.pgh.pa.us 607 [ + - ]:CBC 12 : ereport(ERROR,
608 : : (errcode(ERRCODE_GROUPING_ERROR),
609 : : errmsg_internal(err,
610 : : ParseExprKindName(pstate->p_expr_kind)),
611 : : parser_errposition(pstate, location)));
612 : : }
613 : 21380 : }
614 : :
615 : : /*
616 : : * check_agg_arguments
617 : : * Scan the arguments of an aggregate function to determine the
618 : : * aggregate's semantic level (zero is the current select's level,
619 : : * one is its parent, etc).
620 : : *
621 : : * The aggregate's level is the same as the level of the lowest-level variable
622 : : * or aggregate in its aggregated arguments (including any ORDER BY columns)
623 : : * or filter expression; or if it contains no variables at all, we presume it
624 : : * to be local.
625 : : *
626 : : * Vars/Aggs in direct arguments are *not* counted towards determining the
627 : : * agg's level, as those arguments aren't evaluated per-row but only
628 : : * per-group, and so in some sense aren't really agg arguments. However,
629 : : * this can mean that we decide an agg is upper-level even when its direct
630 : : * args contain lower-level Vars/Aggs, and that case has to be disallowed.
631 : : * (This is a little strange, but the SQL standard seems pretty definite that
632 : : * direct args are not to be considered when setting the agg's level.)
633 : : *
634 : : * We also take this opportunity to detect any aggregates or window functions
635 : : * nested within the arguments. We can throw error immediately if we find
636 : : * a window function. Aggregates are a bit trickier because it's only an
637 : : * error if the inner aggregate is of the same semantic level as the outer,
638 : : * which we can't know until we finish scanning the arguments.
639 : : */
640 : : static int
4326 641 : 21452 : check_agg_arguments(ParseState *pstate,
642 : : List *directargs,
643 : : List *args,
644 : : Expr *filter)
645 : : {
646 : : int agglevel;
647 : : check_agg_arguments_context context;
648 : :
4826 649 : 21452 : context.pstate = pstate;
650 : 21452 : context.min_varlevel = -1; /* signifies nothing found yet */
651 : 21452 : context.min_agglevel = -1;
652 : 21452 : context.sublevels_up = 0;
653 : :
1531 654 : 21452 : (void) check_agg_arguments_walker((Node *) args, &context);
655 : 21449 : (void) check_agg_arguments_walker((Node *) filter, &context);
656 : :
657 : : /*
658 : : * If we found no vars nor aggs at all, it's a level-zero aggregate;
659 : : * otherwise, its level is the minimum of vars or aggs.
660 : : */
4826 661 [ + + ]: 21449 : if (context.min_varlevel < 0)
662 : : {
663 [ + - ]: 6791 : if (context.min_agglevel < 0)
4326 664 : 6791 : agglevel = 0;
665 : : else
4326 tgl@sss.pgh.pa.us 666 :UBC 0 : agglevel = context.min_agglevel;
667 : : }
4826 tgl@sss.pgh.pa.us 668 [ + + ]:CBC 14658 : else if (context.min_agglevel < 0)
669 : 14640 : agglevel = context.min_varlevel;
670 : : else
671 : 18 : agglevel = Min(context.min_varlevel, context.min_agglevel);
672 : :
673 : : /*
674 : : * If there's a nested aggregate of the same semantic level, complain.
675 : : */
676 [ + + ]: 21449 : if (agglevel == context.min_agglevel)
677 : : {
678 : : int aggloc;
679 : :
4326 680 : 15 : aggloc = locate_agg_of_level((Node *) args, agglevel);
681 [ + + ]: 15 : if (aggloc < 0)
682 : 6 : aggloc = locate_agg_of_level((Node *) filter, agglevel);
4829 683 [ + - ]: 15 : ereport(ERROR,
684 : : (errcode(ERRCODE_GROUPING_ERROR),
685 : : errmsg("aggregate function calls cannot be nested"),
686 : : parser_errposition(pstate, aggloc)));
687 : : }
688 : :
689 : : /*
690 : : * Now check for vars/aggs in the direct arguments, and throw error if
691 : : * needed. Note that we allow a Var of the agg's semantic level, but not
692 : : * an Agg of that level. In principle such Aggs could probably be
693 : : * supported, but it would create an ordering dependency among the
694 : : * aggregates at execution time. Since the case appears neither to be
695 : : * required by spec nor particularly useful, we just treat it as a
696 : : * nested-aggregate situation.
697 : : */
4326 698 [ + + ]: 21434 : if (directargs)
699 : : {
700 : 156 : context.min_varlevel = -1;
701 : 156 : context.min_agglevel = -1;
1531 702 : 156 : (void) check_agg_arguments_walker((Node *) directargs, &context);
4326 703 [ + + + + ]: 156 : if (context.min_varlevel >= 0 && context.min_varlevel < agglevel)
704 [ + - ]: 3 : ereport(ERROR,
705 : : (errcode(ERRCODE_GROUPING_ERROR),
706 : : errmsg("outer-level aggregate cannot contain a lower-level variable in its direct arguments"),
707 : : parser_errposition(pstate,
708 : : locate_var_of_level((Node *) directargs,
709 : : context.min_varlevel))));
710 [ + + + - ]: 153 : if (context.min_agglevel >= 0 && context.min_agglevel <= agglevel)
711 [ + - ]: 3 : ereport(ERROR,
712 : : (errcode(ERRCODE_GROUPING_ERROR),
713 : : errmsg("aggregate function calls cannot be nested"),
714 : : parser_errposition(pstate,
715 : : locate_agg_of_level((Node *) directargs,
716 : : context.min_agglevel))));
717 : : }
4826 718 : 21428 : return agglevel;
719 : : }
720 : :
721 : : static bool
722 : 89899 : check_agg_arguments_walker(Node *node,
723 : : check_agg_arguments_context *context)
724 : : {
725 [ + + ]: 89899 : if (node == NULL)
726 : 28381 : return false;
727 [ + + ]: 61518 : if (IsA(node, Var))
728 : : {
729 : 16529 : int varlevelsup = ((Var *) node)->varlevelsup;
730 : :
731 : : /* convert levelsup to frame of reference of original query */
732 : 16529 : varlevelsup -= context->sublevels_up;
733 : : /* ignore local vars of subqueries */
734 [ + + ]: 16529 : if (varlevelsup >= 0)
735 : : {
736 [ + + ]: 16464 : if (context->min_varlevel < 0 ||
737 [ + + ]: 1776 : context->min_varlevel > varlevelsup)
738 : 14739 : context->min_varlevel = varlevelsup;
739 : : }
740 : 16529 : return false;
741 : : }
742 [ + + ]: 44989 : if (IsA(node, Aggref))
743 : : {
744 : 27 : int agglevelsup = ((Aggref *) node)->agglevelsup;
745 : :
746 : : /* convert levelsup to frame of reference of original query */
747 : 27 : agglevelsup -= context->sublevels_up;
748 : : /* ignore local aggs of subqueries */
749 [ + + ]: 27 : if (agglevelsup >= 0)
750 : : {
751 [ - + ]: 21 : if (context->min_agglevel < 0 ||
4826 tgl@sss.pgh.pa.us 752 [ # # ]:UBC 0 : context->min_agglevel > agglevelsup)
4826 tgl@sss.pgh.pa.us 753 :CBC 21 : context->min_agglevel = agglevelsup;
754 : : }
755 : : /* Continue and descend into subtree */
756 : : }
3817 andres@anarazel.de 757 [ - + ]: 44989 : if (IsA(node, GroupingFunc))
758 : : {
3817 andres@anarazel.de 759 :UBC 0 : int agglevelsup = ((GroupingFunc *) node)->agglevelsup;
760 : :
761 : : /* convert levelsup to frame of reference of original query */
762 : 0 : agglevelsup -= context->sublevels_up;
763 : : /* ignore local aggs of subqueries */
764 [ # # ]: 0 : if (agglevelsup >= 0)
765 : : {
766 [ # # ]: 0 : if (context->min_agglevel < 0 ||
767 [ # # ]: 0 : context->min_agglevel > agglevelsup)
768 : 0 : context->min_agglevel = agglevelsup;
769 : : }
770 : : /* Continue and descend into subtree */
771 : : }
772 : :
773 : : /*
774 : : * SRFs and window functions can be rejected immediately, unless we are
775 : : * within a sub-select within the aggregate's arguments; in that case
776 : : * they're OK.
777 : : */
3044 tgl@sss.pgh.pa.us 778 [ + + ]:CBC 44989 : if (context->sublevels_up == 0)
779 : : {
1990 780 [ + + + + ]: 44542 : if ((IsA(node, FuncExpr) && ((FuncExpr *) node)->funcretset) ||
781 [ + + - + ]: 44539 : (IsA(node, OpExpr) && ((OpExpr *) node)->opretset))
3044 782 [ + - ]: 3 : ereport(ERROR,
783 : : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
784 : : errmsg("aggregate function calls cannot contain set-returning function calls"),
785 : : errhint("You might be able to move the set-returning function into a LATERAL FROM item."),
786 : : parser_errposition(context->pstate, exprLocation(node))));
787 [ - + ]: 44539 : if (IsA(node, WindowFunc))
3044 tgl@sss.pgh.pa.us 788 [ # # ]:UBC 0 : ereport(ERROR,
789 : : (errcode(ERRCODE_GROUPING_ERROR),
790 : : errmsg("aggregate function calls cannot contain window function calls"),
791 : : parser_errposition(context->pstate,
792 : : ((WindowFunc *) node)->location)));
793 : : }
794 : :
40 tgl@sss.pgh.pa.us 795 [ + + ]:CBC 44986 : if (IsA(node, RangeTblEntry))
796 : : {
797 : : /*
798 : : * CTE references act similarly to Vars of the CTE's level. Without
799 : : * this we might conclude that the Agg can be evaluated above the CTE,
800 : : * leading to trouble.
801 : : */
802 : 61 : RangeTblEntry *rte = (RangeTblEntry *) node;
803 : :
804 [ + + ]: 61 : if (rte->rtekind == RTE_CTE)
805 : : {
806 : 6 : int ctelevelsup = rte->ctelevelsup;
807 : :
808 : : /* convert levelsup to frame of reference of original query */
809 : 6 : ctelevelsup -= context->sublevels_up;
810 : : /* ignore local CTEs of subqueries */
811 [ + - ]: 6 : if (ctelevelsup >= 0)
812 : : {
813 [ + - ]: 6 : if (context->min_varlevel < 0 ||
814 [ + - ]: 6 : context->min_varlevel > ctelevelsup)
815 : 6 : context->min_varlevel = ctelevelsup;
816 : : }
817 : : }
818 : 61 : return false; /* allow range_table_walker to continue */
819 : : }
4826 820 [ + + ]: 44925 : if (IsA(node, Query))
821 : : {
822 : : /* Recurse into subselects */
823 : : bool result;
824 : :
825 : 66 : context->sublevels_up++;
826 : 66 : result = query_tree_walker((Query *) node,
827 : : check_agg_arguments_walker,
828 : : context,
829 : : QTW_EXAMINE_RTES_BEFORE);
830 : 66 : context->sublevels_up--;
831 : 66 : return result;
832 : : }
833 : :
834 : 44859 : return expression_tree_walker(node,
835 : : check_agg_arguments_walker,
836 : : context);
837 : : }
838 : :
839 : : /*
840 : : * transformWindowFuncCall -
841 : : * Finish initial transformation of a window function call
842 : : *
843 : : * parse_func.c has recognized the function as a window function, and has set
844 : : * up all the fields of the WindowFunc except winref. Here we must (1) add
845 : : * the WindowDef to the pstate (if not a duplicate of one already present) and
846 : : * set winref to link to it; and (2) mark p_hasWindowFuncs true in the pstate.
847 : : * Unlike aggregates, only the most closely nested pstate level need be
848 : : * considered --- there are no "outer window functions" per SQL spec.
849 : : */
850 : : void
6147 851 : 1938 : transformWindowFuncCall(ParseState *pstate, WindowFunc *wfunc,
852 : : WindowDef *windef)
853 : : {
854 : : const char *err;
855 : : bool errkind;
856 : :
857 : : /*
858 : : * A window function call can't contain another one (but aggs are OK). XXX
859 : : * is this required by spec, or just an unimplemented feature?
860 : : *
861 : : * Note: we don't need to check the filter expression here, because the
862 : : * context checks done below and in transformAggregateCall would have
863 : : * already rejected any window funcs or aggs within the filter.
864 : : */
865 [ + + - + ]: 2469 : if (pstate->p_hasWindowFuncs &&
4826 866 : 531 : contain_windowfuncs((Node *) wfunc->args))
6147 tgl@sss.pgh.pa.us 867 [ # # ]:UBC 0 : ereport(ERROR,
868 : : (errcode(ERRCODE_WINDOWING_ERROR),
869 : : errmsg("window function calls cannot be nested"),
870 : : parser_errposition(pstate,
871 : : locate_windowfunc((Node *) wfunc->args))));
872 : :
873 : : /*
874 : : * Check to see if the window function is in an invalid place within the
875 : : * query.
876 : : *
877 : : * For brevity we support two schemes for reporting an error here: set
878 : : * "err" to a custom message, or set "errkind" true if the error context
879 : : * is sufficiently identified by what ParseExprKindName will return, *and*
880 : : * what it will return is just a SQL keyword. (Otherwise, use a custom
881 : : * message to avoid creating translation problems.)
882 : : */
4826 tgl@sss.pgh.pa.us 883 :CBC 1938 : err = NULL;
884 : 1938 : errkind = false;
885 [ - - + - : 1938 : switch (pstate->p_expr_kind)
- + - - -
+ + - - -
+ - - + -
- - - - -
- - - - +
- + + -
- ]
886 : : {
4826 tgl@sss.pgh.pa.us 887 :UBC 0 : case EXPR_KIND_NONE:
888 : 0 : Assert(false); /* can't happen */
889 : : break;
890 : 0 : case EXPR_KIND_OTHER:
891 : : /* Accept window func here; caller must throw error if wanted */
892 : 0 : break;
4826 tgl@sss.pgh.pa.us 893 :CBC 3 : case EXPR_KIND_JOIN_ON:
894 : : case EXPR_KIND_JOIN_USING:
895 : 3 : err = _("window functions are not allowed in JOIN conditions");
896 : 3 : break;
4826 tgl@sss.pgh.pa.us 897 :UBC 0 : case EXPR_KIND_FROM_SUBSELECT:
898 : : /* can't get here, but just in case, throw an error */
899 : 0 : errkind = true;
900 : 0 : break;
901 : 0 : case EXPR_KIND_FROM_FUNCTION:
902 : 0 : err = _("window functions are not allowed in functions in FROM");
903 : 0 : break;
4826 tgl@sss.pgh.pa.us 904 :CBC 6 : case EXPR_KIND_WHERE:
905 : 6 : errkind = true;
906 : 6 : break;
3743 mail@joeconway.com 907 :UBC 0 : case EXPR_KIND_POLICY:
908 : 0 : err = _("window functions are not allowed in policy expressions");
909 : 0 : break;
4826 tgl@sss.pgh.pa.us 910 : 0 : case EXPR_KIND_HAVING:
911 : 0 : errkind = true;
912 : 0 : break;
4486 noah@leadboat.com 913 : 0 : case EXPR_KIND_FILTER:
914 : 0 : errkind = true;
915 : 0 : break;
4826 tgl@sss.pgh.pa.us 916 :CBC 3 : case EXPR_KIND_WINDOW_PARTITION:
917 : : case EXPR_KIND_WINDOW_ORDER:
918 : : case EXPR_KIND_WINDOW_FRAME_RANGE:
919 : : case EXPR_KIND_WINDOW_FRAME_ROWS:
920 : : case EXPR_KIND_WINDOW_FRAME_GROUPS:
921 : 3 : err = _("window functions are not allowed in window definitions");
922 : 3 : break;
923 : 1907 : case EXPR_KIND_SELECT_TARGET:
924 : : /* okay */
925 : 1907 : break;
4826 tgl@sss.pgh.pa.us 926 :UBC 0 : case EXPR_KIND_INSERT_TARGET:
927 : : case EXPR_KIND_UPDATE_SOURCE:
928 : : case EXPR_KIND_UPDATE_TARGET:
929 : 0 : errkind = true;
930 : 0 : break;
1309 alvherre@alvh.no-ip. 931 : 0 : case EXPR_KIND_MERGE_WHEN:
932 : 0 : err = _("window functions are not allowed in MERGE WHEN conditions");
933 : 0 : break;
4826 tgl@sss.pgh.pa.us 934 : 0 : case EXPR_KIND_GROUP_BY:
935 : 0 : errkind = true;
936 : 0 : break;
4826 tgl@sss.pgh.pa.us 937 :CBC 4 : case EXPR_KIND_ORDER_BY:
938 : : /* okay */
939 : 4 : break;
4826 tgl@sss.pgh.pa.us 940 :UBC 0 : case EXPR_KIND_DISTINCT_ON:
941 : : /* okay */
942 : 0 : break;
943 : 0 : case EXPR_KIND_LIMIT:
944 : : case EXPR_KIND_OFFSET:
945 : 0 : errkind = true;
946 : 0 : break;
4826 tgl@sss.pgh.pa.us 947 :CBC 3 : case EXPR_KIND_RETURNING:
948 : : case EXPR_KIND_MERGE_RETURNING:
949 : 3 : errkind = true;
950 : 3 : break;
4826 tgl@sss.pgh.pa.us 951 :UBC 0 : case EXPR_KIND_VALUES:
952 : : case EXPR_KIND_VALUES_SINGLE:
953 : 0 : errkind = true;
954 : 0 : break;
955 : 0 : case EXPR_KIND_CHECK_CONSTRAINT:
956 : : case EXPR_KIND_DOMAIN_CHECK:
4678 peter_e@gmx.net 957 : 0 : err = _("window functions are not allowed in check constraints");
4826 tgl@sss.pgh.pa.us 958 : 0 : break;
959 : 0 : case EXPR_KIND_COLUMN_DEFAULT:
960 : : case EXPR_KIND_FUNCTION_DEFAULT:
961 : 0 : err = _("window functions are not allowed in DEFAULT expressions");
962 : 0 : break;
963 : 0 : case EXPR_KIND_INDEX_EXPRESSION:
964 : 0 : err = _("window functions are not allowed in index expressions");
965 : 0 : break;
1676 tomas.vondra@postgre 966 : 0 : case EXPR_KIND_STATS_EXPRESSION:
967 : 0 : err = _("window functions are not allowed in statistics expressions");
968 : 0 : break;
4826 tgl@sss.pgh.pa.us 969 : 0 : case EXPR_KIND_INDEX_PREDICATE:
970 : 0 : err = _("window functions are not allowed in index predicates");
971 : 0 : break;
972 : 0 : case EXPR_KIND_ALTER_COL_TRANSFORM:
973 : 0 : err = _("window functions are not allowed in transform expressions");
974 : 0 : break;
975 : 0 : case EXPR_KIND_EXECUTE_PARAMETER:
976 : 0 : err = _("window functions are not allowed in EXECUTE parameters");
977 : 0 : break;
978 : 0 : case EXPR_KIND_TRIGGER_WHEN:
979 : 0 : err = _("window functions are not allowed in trigger WHEN conditions");
980 : 0 : break;
2467 peter@eisentraut.org 981 : 0 : case EXPR_KIND_PARTITION_BOUND:
982 : 0 : err = _("window functions are not allowed in partition bound");
983 : 0 : break;
3246 rhaas@postgresql.org 984 :CBC 3 : case EXPR_KIND_PARTITION_EXPRESSION:
2816 tgl@sss.pgh.pa.us 985 : 3 : err = _("window functions are not allowed in partition key expressions");
3246 rhaas@postgresql.org 986 : 3 : break;
2816 tgl@sss.pgh.pa.us 987 :UBC 0 : case EXPR_KIND_CALL_ARGUMENT:
2888 peter_e@gmx.net 988 : 0 : err = _("window functions are not allowed in CALL arguments");
989 : 0 : break;
2473 tomas.vondra@postgre 990 :CBC 3 : case EXPR_KIND_COPY_WHERE:
991 : 3 : err = _("window functions are not allowed in COPY FROM WHERE conditions");
992 : 3 : break;
2403 peter@eisentraut.org 993 : 6 : case EXPR_KIND_GENERATED_COLUMN:
994 : 6 : err = _("window functions are not allowed in column generation expressions");
995 : 6 : break;
1729 peter@eisentraut.org 996 :UBC 0 : case EXPR_KIND_CYCLE_MARK:
997 : 0 : errkind = true;
998 : 0 : break;
999 : :
1000 : : /*
1001 : : * There is intentionally no default: case here, so that the
1002 : : * compiler will warn if we add a new ParseExprKind without
1003 : : * extending this switch. If we do see an unrecognized value at
1004 : : * runtime, the behavior will be the same as for EXPR_KIND_OTHER,
1005 : : * which is sane anyway.
1006 : : */
1007 : : }
4826 tgl@sss.pgh.pa.us 1008 [ + + ]:CBC 1938 : if (err)
1009 [ + - ]: 18 : ereport(ERROR,
1010 : : (errcode(ERRCODE_WINDOWING_ERROR),
1011 : : errmsg_internal("%s", err),
1012 : : parser_errposition(pstate, wfunc->location)));
1013 [ + + ]: 1920 : if (errkind)
1014 [ + - ]: 9 : ereport(ERROR,
1015 : : (errcode(ERRCODE_WINDOWING_ERROR),
1016 : : /* translator: %s is name of a SQL construct, eg GROUP BY */
1017 : : errmsg("window functions are not allowed in %s",
1018 : : ParseExprKindName(pstate->p_expr_kind)),
1019 : : parser_errposition(pstate, wfunc->location)));
1020 : :
1021 : : /*
1022 : : * If the OVER clause just specifies a window name, find that WINDOW
1023 : : * clause (which had better be present). Otherwise, try to match all the
1024 : : * properties of the OVER clause, and make a new entry in the p_windowdefs
1025 : : * list if no luck.
1026 : : */
6144 1027 [ + + ]: 1911 : if (windef->name)
1028 : : {
6147 1029 : 591 : Index winref = 0;
1030 : : ListCell *lc;
1031 : :
6144 1032 [ + - + - : 591 : Assert(windef->refname == NULL &&
+ - - + ]
1033 : : windef->partitionClause == NIL &&
1034 : : windef->orderClause == NIL &&
1035 : : windef->frameOptions == FRAMEOPTION_DEFAULTS);
1036 : :
6147 1037 [ + - + - : 612 : foreach(lc, pstate->p_windowdefs)
+ - ]
1038 : : {
5982 bruce@momjian.us 1039 : 612 : WindowDef *refwin = (WindowDef *) lfirst(lc);
1040 : :
6147 tgl@sss.pgh.pa.us 1041 : 612 : winref++;
6144 1042 [ + - + + ]: 612 : if (refwin->name && strcmp(refwin->name, windef->name) == 0)
1043 : : {
6147 1044 : 591 : wfunc->winref = winref;
1045 : 591 : break;
1046 : : }
1047 : : }
1048 [ - + ]: 591 : if (lc == NULL) /* didn't find it? */
6147 tgl@sss.pgh.pa.us 1049 [ # # ]:UBC 0 : ereport(ERROR,
1050 : : (errcode(ERRCODE_UNDEFINED_OBJECT),
1051 : : errmsg("window \"%s\" does not exist", windef->name),
1052 : : parser_errposition(pstate, windef->location)));
1053 : : }
1054 : : else
1055 : : {
6147 tgl@sss.pgh.pa.us 1056 :CBC 1320 : Index winref = 0;
1057 : : ListCell *lc;
1058 : :
1059 [ + + + + : 1500 : foreach(lc, pstate->p_windowdefs)
+ + ]
1060 : : {
5982 bruce@momjian.us 1061 : 306 : WindowDef *refwin = (WindowDef *) lfirst(lc);
1062 : :
6147 tgl@sss.pgh.pa.us 1063 : 306 : winref++;
1064 [ + + + - ]: 312 : if (refwin->refname && windef->refname &&
6144 1065 [ + - ]: 6 : strcmp(refwin->refname, windef->refname) == 0)
1066 : : /* matched on refname */ ;
6147 1067 [ + - + + ]: 300 : else if (!refwin->refname && !windef->refname)
1068 : : /* matched, no refname */ ;
1069 : : else
1070 : 24 : continue;
1071 : :
1072 : : /*
1073 : : * Also see similar de-duplication code in optimize_window_clauses
1074 : : */
1075 [ + + + + ]: 519 : if (equal(refwin->partitionClause, windef->partitionClause) &&
6144 1076 : 237 : equal(refwin->orderClause, windef->orderClause) &&
5736 1077 [ + + + - ]: 333 : refwin->frameOptions == windef->frameOptions &&
1078 [ + - ]: 252 : equal(refwin->startOffset, windef->startOffset) &&
1079 : 126 : equal(refwin->endOffset, windef->endOffset))
1080 : : {
1081 : : /* found a duplicate window specification */
6147 1082 : 126 : wfunc->winref = winref;
1083 : 126 : break;
1084 : : }
1085 : : }
1086 [ + + ]: 1320 : if (lc == NULL) /* didn't find it? */
1087 : : {
1088 : 1194 : pstate->p_windowdefs = lappend(pstate->p_windowdefs, windef);
1089 : 1194 : wfunc->winref = list_length(pstate->p_windowdefs);
1090 : : }
1091 : : }
1092 : :
1093 : 1911 : pstate->p_hasWindowFuncs = true;
1094 : 1911 : }
1095 : :
1096 : : /*
1097 : : * parseCheckAggregates
1098 : : * Check for aggregates where they shouldn't be and improper grouping, and
1099 : : * replace grouped variables in the targetlist and HAVING clause with Vars
1100 : : * that reference the RTE_GROUP RTE.
1101 : : * This function should be called after the target list and qualifications
1102 : : * are finalized.
1103 : : *
1104 : : * Misplaced aggregates are now mostly detected in transformAggregateCall,
1105 : : * but it seems more robust to check for aggregates in recursive queries
1106 : : * only after everything is finalized. In any case it's hard to detect
1107 : : * improper grouping on-the-fly, so we have to make another pass over the
1108 : : * query for that.
1109 : : */
1110 : : void
8179 1111 : 18723 : parseCheckAggregates(ParseState *pstate, Query *qry)
1112 : : {
3810 bruce@momjian.us 1113 : 18723 : List *gset_common = NIL;
8179 tgl@sss.pgh.pa.us 1114 : 18723 : List *groupClauses = NIL;
3817 andres@anarazel.de 1115 : 18723 : List *groupClauseCommonVars = NIL;
1116 : : bool have_non_var_grouping;
5560 tgl@sss.pgh.pa.us 1117 : 18723 : List *func_grouped_rels = NIL;
1118 : : ListCell *l;
1119 : : bool hasJoinRTEs;
1120 : : bool hasSelfRefRTEs;
1121 : : Node *clause;
1122 : :
1123 : : /* This should only be called if we found aggregates or grouping */
3817 andres@anarazel.de 1124 [ + + + + : 18723 : Assert(pstate->p_hasAggs || qry->groupClause || qry->havingQual || qry->groupingSets);
+ + - + ]
1125 : :
1126 : : /*
1127 : : * If we have grouping sets, expand them and find the intersection of all
1128 : : * sets.
1129 : : */
1130 [ + + ]: 18723 : if (qry->groupingSets)
1131 : : {
1132 : : /*
1133 : : * The limit of 4096 is arbitrary and exists simply to avoid resource
1134 : : * issues from pathological constructs.
1135 : : */
1684 tomas.vondra@postgre 1136 : 484 : List *gsets = expand_grouping_sets(qry->groupingSets, qry->groupDistinct, 4096);
1137 : :
3817 andres@anarazel.de 1138 [ - + ]: 484 : if (!gsets)
3817 andres@anarazel.de 1139 [ # # # # ]:UBC 0 : ereport(ERROR,
1140 : : (errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
1141 : : errmsg("too many grouping sets present (maximum 4096)"),
1142 : : parser_errposition(pstate,
1143 : : qry->groupClause
1144 : : ? exprLocation((Node *) qry->groupClause)
1145 : : : exprLocation((Node *) qry->groupingSets))));
1146 : :
1147 : : /*
1148 : : * The intersection will often be empty, so help things along by
1149 : : * seeding the intersect with the smallest set.
1150 : : */
3817 andres@anarazel.de 1151 :CBC 484 : gset_common = linitial(gsets);
1152 : :
1153 [ + + ]: 484 : if (gset_common)
1154 : : {
1855 tgl@sss.pgh.pa.us 1155 [ + - + + : 320 : for_each_from(l, gsets, 1)
+ + ]
1156 : : {
3817 andres@anarazel.de 1157 : 215 : gset_common = list_intersection_int(gset_common, lfirst(l));
1158 [ + + ]: 215 : if (!gset_common)
1159 : 98 : break;
1160 : : }
1161 : : }
1162 : :
1163 : : /*
1164 : : * If there was only one grouping set in the expansion, AND if the
1165 : : * groupClause is non-empty (meaning that the grouping set is not
1166 : : * empty either), then we can ditch the grouping set and pretend we
1167 : : * just had a normal GROUP BY.
1168 : : */
1169 [ + + + + ]: 484 : if (list_length(gsets) == 1 && qry->groupClause)
1170 : 12 : qry->groupingSets = NIL;
1171 : : }
1172 : :
1173 : : /*
1174 : : * Scan the range table to see if there are JOIN or self-reference CTE
1175 : : * entries. We'll need this info below.
1176 : : */
6232 tgl@sss.pgh.pa.us 1177 : 18723 : hasJoinRTEs = hasSelfRefRTEs = false;
1178 [ + + + + : 41526 : foreach(l, pstate->p_rtable)
+ + ]
1179 : : {
1180 : 22803 : RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
1181 : :
1182 [ + + ]: 22803 : if (rte->rtekind == RTE_JOIN)
1183 : 1125 : hasJoinRTEs = true;
1184 [ + + + + ]: 21678 : else if (rte->rtekind == RTE_CTE && rte->self_reference)
1185 : 6 : hasSelfRefRTEs = true;
1186 : : }
1187 : :
1188 : : /*
1189 : : * Build a list of the acceptable GROUP BY expressions for use by
1190 : : * substitute_grouped_columns().
1191 : : *
1192 : : * We get the TLE, not just the expr, because GROUPING wants to know the
1193 : : * sortgroupref.
1194 : : */
7824 neilc@samurai.com 1195 [ + + + + : 22788 : foreach(l, qry->groupClause)
+ + ]
1196 : : {
6295 tgl@sss.pgh.pa.us 1197 : 4065 : SortGroupClause *grpcl = (SortGroupClause *) lfirst(l);
1198 : : TargetEntry *expr;
1199 : :
3817 andres@anarazel.de 1200 : 4065 : expr = get_sortgroupclause_tle(grpcl, qry->targetList);
8179 tgl@sss.pgh.pa.us 1201 [ - + ]: 4065 : if (expr == NULL)
8179 tgl@sss.pgh.pa.us 1202 :UBC 0 : continue; /* probably cannot happen */
1203 : :
2294 tgl@sss.pgh.pa.us 1204 :CBC 4065 : groupClauses = lappend(groupClauses, expr);
1205 : : }
1206 : :
1207 : : /*
1208 : : * If there are join alias vars involved, we have to flatten them to the
1209 : : * underlying vars, so that aliased and unaliased vars will be correctly
1210 : : * taken as equal. We can skip the expense of doing this if no rangetable
1211 : : * entries are RTE_JOIN kind.
1212 : : */
8179 1213 [ + + ]: 18723 : if (hasJoinRTEs)
1001 1214 : 924 : groupClauses = (List *) flatten_join_alias_vars(NULL, qry,
1215 : : (Node *) groupClauses);
1216 : :
1217 : : /*
1218 : : * Detect whether any of the grouping expressions aren't simple Vars; if
1219 : : * they're all Vars then we don't have to work so hard in the recursive
1220 : : * scans. (Note we have to flatten aliases before this.)
1221 : : *
1222 : : * Track Vars that are included in all grouping sets separately in
1223 : : * groupClauseCommonVars, since these are the only ones we can use to
1224 : : * check for functional dependencies.
1225 : : */
7943 1226 : 18723 : have_non_var_grouping = false;
7824 neilc@samurai.com 1227 [ + + + + : 22788 : foreach(l, groupClauses)
+ + ]
1228 : : {
3817 andres@anarazel.de 1229 : 4065 : TargetEntry *tle = lfirst(l);
1230 : :
1231 [ + + ]: 4065 : if (!IsA(tle->expr, Var))
1232 : : {
7943 tgl@sss.pgh.pa.us 1233 : 701 : have_non_var_grouping = true;
1234 : : }
3817 andres@anarazel.de 1235 [ + + + + ]: 4216 : else if (!qry->groupingSets ||
1236 : 852 : list_member_int(gset_common, tle->ressortgroupref))
1237 : : {
1238 : 2605 : groupClauseCommonVars = lappend(groupClauseCommonVars, tle->expr);
1239 : : }
1240 : : }
1241 : :
1242 : : /*
1243 : : * If there are any acceptable GROUP BY expressions, build an RTE and
1244 : : * nsitem for the result of the grouping step.
1245 : : */
412 rguo@postgresql.org 1246 [ + + ]: 18723 : if (groupClauses)
1247 : : {
1248 : 2401 : pstate->p_grouping_nsitem =
1249 : 2401 : addRangeTableEntryForGroup(pstate, groupClauses);
1250 : :
1251 : : /* Set qry->rtable again in case it was previously NIL */
1252 : 2401 : qry->rtable = pstate->p_rtable;
1253 : : /* Mark the Query as having RTE_GROUP RTE */
1254 : 2401 : qry->hasGroupRTE = true;
1255 : : }
1256 : :
1257 : : /*
1258 : : * Replace grouped variables in the targetlist and HAVING clause with Vars
1259 : : * that reference the RTE_GROUP RTE. Emit an error message if we find any
1260 : : * ungrouped variables.
1261 : : *
1262 : : * Note: because we check resjunk tlist elements as well as regular ones,
1263 : : * this will also find ungrouped variables that came from ORDER BY and
1264 : : * WINDOW clauses. For that matter, it's also going to examine the
1265 : : * grouping expressions themselves --- but they'll all pass the test ...
1266 : : *
1267 : : * We also finalize GROUPING expressions, but for that we need to traverse
1268 : : * the original (unflattened) clause in order to modify nodes.
1269 : : */
8179 tgl@sss.pgh.pa.us 1270 : 18723 : clause = (Node *) qry->targetList;
3817 andres@anarazel.de 1271 : 18723 : finalize_grouping_exprs(clause, pstate, qry,
1272 : : groupClauses, hasJoinRTEs,
1273 : : have_non_var_grouping);
8179 tgl@sss.pgh.pa.us 1274 [ + + ]: 18720 : if (hasJoinRTEs)
1001 1275 : 924 : clause = flatten_join_alias_vars(NULL, qry, clause);
412 rguo@postgresql.org 1276 : 18675 : qry->targetList = (List *)
1277 : 18720 : substitute_grouped_columns(clause, pstate, qry,
1278 : : groupClauses, groupClauseCommonVars,
1279 : : gset_common,
1280 : : have_non_var_grouping,
1281 : : &func_grouped_rels);
1282 : :
8179 tgl@sss.pgh.pa.us 1283 : 18675 : clause = (Node *) qry->havingQual;
3817 andres@anarazel.de 1284 : 18675 : finalize_grouping_exprs(clause, pstate, qry,
1285 : : groupClauses, hasJoinRTEs,
1286 : : have_non_var_grouping);
8179 tgl@sss.pgh.pa.us 1287 [ + + ]: 18675 : if (hasJoinRTEs)
1001 1288 : 912 : clause = flatten_join_alias_vars(NULL, qry, clause);
412 rguo@postgresql.org 1289 : 18672 : qry->havingQual =
1290 : 18675 : substitute_grouped_columns(clause, pstate, qry,
1291 : : groupClauses, groupClauseCommonVars,
1292 : : gset_common,
1293 : : have_non_var_grouping,
1294 : : &func_grouped_rels);
1295 : :
1296 : : /*
1297 : : * Per spec, aggregates can't appear in a recursive term.
1298 : : */
6232 tgl@sss.pgh.pa.us 1299 [ + + + + ]: 18672 : if (pstate->p_hasAggs && hasSelfRefRTEs)
1300 [ + - ]: 6 : ereport(ERROR,
1301 : : (errcode(ERRCODE_INVALID_RECURSION),
1302 : : errmsg("aggregate functions are not allowed in a recursive query's recursive term"),
1303 : : parser_errposition(pstate,
1304 : : locate_agg_of_level((Node *) qry, 0))));
8179 1305 : 18666 : }
1306 : :
1307 : : /*
1308 : : * substitute_grouped_columns -
1309 : : * Scan the given expression tree for grouped variables (variables that
1310 : : * are listed in the groupClauses list) and replace them with Vars that
1311 : : * reference the RTE_GROUP RTE. Emit a suitable error message if any
1312 : : * ungrouped variables (variables that are not listed in the groupClauses
1313 : : * list and are not within the arguments of aggregate functions) are
1314 : : * found.
1315 : : *
1316 : : * NOTE: we assume that the given clause has been transformed suitably for
1317 : : * parser output. This means we can use expression_tree_mutator.
1318 : : *
1319 : : * NOTE: we recognize grouping expressions in the main query, but only
1320 : : * grouping Vars in subqueries. For example, this will be rejected,
1321 : : * although it could be allowed:
1322 : : * SELECT
1323 : : * (SELECT x FROM bar where y = (foo.a + foo.b))
1324 : : * FROM foo
1325 : : * GROUP BY a + b;
1326 : : * The difficulty is the need to account for different sublevels_up.
1327 : : * This appears to require a whole custom version of equal(), which is
1328 : : * way more pain than the feature seems worth.
1329 : : */
1330 : : static Node *
412 rguo@postgresql.org 1331 : 37395 : substitute_grouped_columns(Node *node, ParseState *pstate, Query *qry,
1332 : : List *groupClauses, List *groupClauseCommonVars,
1333 : : List *gset_common,
1334 : : bool have_non_var_grouping,
1335 : : List **func_grouped_rels)
1336 : : {
1337 : : substitute_grouped_columns_context context;
1338 : :
9454 tgl@sss.pgh.pa.us 1339 : 37395 : context.pstate = pstate;
5560 1340 : 37395 : context.qry = qry;
2463 1341 : 37395 : context.hasJoinRTEs = false; /* assume caller flattened join Vars */
9454 1342 : 37395 : context.groupClauses = groupClauses;
3817 andres@anarazel.de 1343 : 37395 : context.groupClauseCommonVars = groupClauseCommonVars;
412 rguo@postgresql.org 1344 : 37395 : context.gset_common = gset_common;
8319 tgl@sss.pgh.pa.us 1345 : 37395 : context.have_non_var_grouping = have_non_var_grouping;
5560 1346 : 37395 : context.func_grouped_rels = func_grouped_rels;
8319 1347 : 37395 : context.sublevels_up = 0;
4326 1348 : 37395 : context.in_agg_direct_args = false;
412 rguo@postgresql.org 1349 : 37395 : return substitute_grouped_columns_mutator(node, &context);
1350 : : }
1351 : :
1352 : : static Node *
1353 : 132673 : substitute_grouped_columns_mutator(Node *node,
1354 : : substitute_grouped_columns_context *context)
1355 : : {
1356 : : ListCell *gl;
1357 : :
9627 tgl@sss.pgh.pa.us 1358 [ + + ]: 132673 : if (node == NULL)
412 rguo@postgresql.org 1359 : 42486 : return NULL;
1360 : :
4326 tgl@sss.pgh.pa.us 1361 [ + + ]: 90187 : if (IsA(node, Aggref))
1362 : : {
1363 : 21591 : Aggref *agg = (Aggref *) node;
1364 : :
1365 [ + + ]: 21591 : if ((int) agg->agglevelsup == context->sublevels_up)
1366 : : {
1367 : : /*
1368 : : * If we find an aggregate call of the original level, do not
1369 : : * recurse into its normal arguments, ORDER BY arguments, or
1370 : : * filter; grouped vars there do not need to be replaced and
1371 : : * ungrouped vars there are not an error. But we should check
1372 : : * direct arguments as though they weren't in an aggregate. We
1373 : : * set a special flag in the context to help produce a useful
1374 : : * error message for ungrouped vars in direct arguments.
1375 : : */
412 rguo@postgresql.org 1376 : 21588 : agg = copyObject(agg);
1377 : :
4326 tgl@sss.pgh.pa.us 1378 [ - + ]: 21588 : Assert(!context->in_agg_direct_args);
1379 : 21588 : context->in_agg_direct_args = true;
412 rguo@postgresql.org 1380 : 21585 : agg->aggdirectargs = (List *)
1381 : 21588 : substitute_grouped_columns_mutator((Node *) agg->aggdirectargs,
1382 : : context);
4326 tgl@sss.pgh.pa.us 1383 : 21585 : context->in_agg_direct_args = false;
412 rguo@postgresql.org 1384 : 21585 : return (Node *) agg;
1385 : : }
1386 : :
1387 : : /*
1388 : : * We can skip recursing into aggregates of higher levels altogether,
1389 : : * since they could not possibly contain Vars of concern to us (see
1390 : : * transformAggregateCall). We do need to look at aggregates of lower
1391 : : * levels, however.
1392 : : */
4326 tgl@sss.pgh.pa.us 1393 [ - + ]: 3 : if ((int) agg->agglevelsup > context->sublevels_up)
412 rguo@postgresql.org 1394 :UBC 0 : return node;
1395 : : }
1396 : :
3817 andres@anarazel.de 1397 [ + + ]:CBC 68599 : if (IsA(node, GroupingFunc))
1398 : : {
1399 : 198 : GroupingFunc *grp = (GroupingFunc *) node;
1400 : :
1401 : : /* handled GroupingFunc separately, no need to recheck at this level */
1402 : :
1403 [ + + ]: 198 : if ((int) grp->agglevelsup >= context->sublevels_up)
412 rguo@postgresql.org 1404 : 182 : return node;
1405 : : }
1406 : :
1407 : : /*
1408 : : * If we have any GROUP BY items that are not simple Vars, check to see if
1409 : : * subexpression as a whole matches any GROUP BY item. We need to do this
1410 : : * at every recursion level so that we recognize GROUPed-BY expressions
1411 : : * before reaching variables within them. But this only works at the outer
1412 : : * query level, as noted above.
1413 : : */
8319 tgl@sss.pgh.pa.us 1414 [ + + + + ]: 68417 : if (context->have_non_var_grouping && context->sublevels_up == 0)
1415 : : {
412 rguo@postgresql.org 1416 : 3858 : int attnum = 0;
1417 : :
8319 tgl@sss.pgh.pa.us 1418 [ + - + + : 10492 : foreach(gl, context->groupClauses)
+ + ]
1419 : : {
412 rguo@postgresql.org 1420 : 7722 : TargetEntry *tle = (TargetEntry *) lfirst(gl);
1421 : :
1422 : 7722 : attnum++;
3817 andres@anarazel.de 1423 [ + + ]: 7722 : if (equal(node, tle->expr))
1424 : : {
1425 : : /* acceptable, replace it with a GROUP Var */
412 rguo@postgresql.org 1426 : 1088 : return (Node *) buildGroupedVar(attnum,
1427 : : tle->ressortgroupref,
1428 : : context);
1429 : : }
1430 : : }
1431 : : }
1432 : :
1433 : : /*
1434 : : * Constants are always acceptable. We have to do this after we checked
1435 : : * the subexpression as a whole for a match, because it is possible that
1436 : : * we have GROUP BY items that are constants, and the constants would
1437 : : * become not so constant after the grouping step.
1438 : : */
1439 [ + + ]: 67329 : if (IsA(node, Const) ||
1440 [ + + ]: 65119 : IsA(node, Param))
1441 : 2332 : return node;
1442 : :
1443 : : /*
1444 : : * If we have an ungrouped Var of the original query level, we have a
1445 : : * failure. Vars below the original query level are not a problem, and
1446 : : * neither are Vars from above it. (If such Vars are ungrouped as far as
1447 : : * their own query level is concerned, that's someone else's problem...)
1448 : : */
9627 tgl@sss.pgh.pa.us 1449 [ + + ]: 64997 : if (IsA(node, Var))
1450 : : {
9329 bruce@momjian.us 1451 : 5236 : Var *var = (Var *) node;
1452 : : RangeTblEntry *rte;
1453 : : char *attname;
1454 : :
8319 tgl@sss.pgh.pa.us 1455 [ + + ]: 5236 : if (var->varlevelsup != context->sublevels_up)
412 rguo@postgresql.org 1456 : 216 : return node; /* it's not local to my query, ignore */
1457 : :
1458 : : /*
1459 : : * Check for a match, if we didn't do it above.
1460 : : */
8319 tgl@sss.pgh.pa.us 1461 [ + + - + ]: 5020 : if (!context->have_non_var_grouping || context->sublevels_up != 0)
1462 : : {
412 rguo@postgresql.org 1463 : 5017 : int attnum = 0;
1464 : :
8319 tgl@sss.pgh.pa.us 1465 [ + + + + : 7003 : foreach(gl, context->groupClauses)
+ + ]
1466 : : {
412 rguo@postgresql.org 1467 : 6828 : TargetEntry *tle = (TargetEntry *) lfirst(gl);
1468 : 6828 : Var *gvar = (Var *) tle->expr;
1469 : :
1470 : 6828 : attnum++;
8319 tgl@sss.pgh.pa.us 1471 [ + - ]: 6828 : if (IsA(gvar, Var) &&
1472 [ + + ]: 6828 : gvar->varno == var->varno &&
1473 [ + + ]: 6465 : gvar->varattno == var->varattno &&
1474 [ + - ]: 4842 : gvar->varlevelsup == 0)
1475 : : {
1476 : : /* acceptable, replace it with a GROUP Var */
412 rguo@postgresql.org 1477 : 4842 : return (Node *) buildGroupedVar(attnum,
1478 : : tle->ressortgroupref,
1479 : : context);
1480 : : }
1481 : : }
1482 : : }
1483 : :
1484 : : /*
1485 : : * Check whether the Var is known functionally dependent on the GROUP
1486 : : * BY columns. If so, we can allow the Var to be used, because the
1487 : : * grouping is really a no-op for this table. However, this deduction
1488 : : * depends on one or more constraints of the table, so we have to add
1489 : : * those constraints to the query's constraintDeps list, because it's
1490 : : * not semantically valid anymore if the constraint(s) get dropped.
1491 : : * (Therefore, this check must be the last-ditch effort before raising
1492 : : * error: we don't want to add dependencies unnecessarily.)
1493 : : *
1494 : : * Because this is a pretty expensive check, and will have the same
1495 : : * outcome for all columns of a table, we remember which RTEs we've
1496 : : * already proven functional dependency for in the func_grouped_rels
1497 : : * list. This test also prevents us from adding duplicate entries to
1498 : : * the constraintDeps list.
1499 : : */
5560 tgl@sss.pgh.pa.us 1500 [ + + ]: 178 : if (list_member_int(*context->func_grouped_rels, var->varno))
412 rguo@postgresql.org 1501 : 69 : return node; /* previously proven acceptable */
1502 : :
9454 tgl@sss.pgh.pa.us 1503 [ + - - + ]: 109 : Assert(var->varno > 0 &&
1504 : : (int) var->varno <= list_length(context->pstate->p_rtable));
1505 : 109 : rte = rt_fetch(var->varno, context->pstate->p_rtable);
5560 1506 [ + + ]: 109 : if (rte->rtekind == RTE_RELATION)
1507 : : {
1508 [ + + ]: 106 : if (check_functional_grouping(rte->relid,
1509 : 106 : var->varno,
1510 : : 0,
1511 : : context->groupClauseCommonVars,
1512 : 106 : &context->qry->constraintDeps))
1513 : : {
1514 : 122 : *context->func_grouped_rels =
1515 : 61 : lappend_int(*context->func_grouped_rels, var->varno);
412 rguo@postgresql.org 1516 : 61 : return node; /* acceptable */
1517 : : }
1518 : : }
1519 : :
1520 : : /* Found an ungrouped local variable; generate error message */
9163 tgl@sss.pgh.pa.us 1521 : 48 : attname = get_rte_attribute_name(rte, var->varattno);
8319 1522 [ + - ]: 48 : if (context->sublevels_up == 0)
8136 1523 [ + - + + ]: 48 : ereport(ERROR,
1524 : : (errcode(ERRCODE_GROUPING_ERROR),
1525 : : errmsg("column \"%s.%s\" must appear in the GROUP BY clause or be used in an aggregate function",
1526 : : rte->eref->aliasname, attname),
1527 : : context->in_agg_direct_args ?
1528 : : errdetail("Direct arguments of an ordered-set aggregate must use only grouped columns.") : 0,
1529 : : parser_errposition(context->pstate, var->location)));
1530 : : else
8136 tgl@sss.pgh.pa.us 1531 [ # # ]:UBC 0 : ereport(ERROR,
1532 : : (errcode(ERRCODE_GROUPING_ERROR),
1533 : : errmsg("subquery uses ungrouped column \"%s.%s\" from outer query",
1534 : : rte->eref->aliasname, attname),
1535 : : parser_errposition(context->pstate, var->location)));
1536 : : }
1537 : :
8319 tgl@sss.pgh.pa.us 1538 [ + + ]:CBC 59761 : if (IsA(node, Query))
1539 : : {
1540 : : /* Recurse into subselects */
1541 : : Query *newnode;
1542 : :
1543 : 167 : context->sublevels_up++;
412 rguo@postgresql.org 1544 : 167 : newnode = query_tree_mutator((Query *) node,
1545 : : substitute_grouped_columns_mutator,
1546 : : context,
1547 : : 0);
8319 tgl@sss.pgh.pa.us 1548 : 167 : context->sublevels_up--;
412 rguo@postgresql.org 1549 : 167 : return (Node *) newnode;
1550 : : }
1551 : 59594 : return expression_tree_mutator(node, substitute_grouped_columns_mutator,
1552 : : context);
1553 : : }
1554 : :
1555 : : /*
1556 : : * finalize_grouping_exprs -
1557 : : * Scan the given expression tree for GROUPING() and related calls,
1558 : : * and validate and process their arguments.
1559 : : *
1560 : : * This is split out from substitute_grouped_columns above because it needs
1561 : : * to modify the nodes (which it does in-place, not via a mutator) while
1562 : : * substitute_grouped_columns may see only a copy of the original thanks to
1563 : : * flattening of join alias vars. So here, we flatten each individual
1564 : : * GROUPING argument as we see it before comparing it.
1565 : : */
1566 : : static void
3817 andres@anarazel.de 1567 : 37398 : finalize_grouping_exprs(Node *node, ParseState *pstate, Query *qry,
1568 : : List *groupClauses, bool hasJoinRTEs,
1569 : : bool have_non_var_grouping)
1570 : : {
1571 : : substitute_grouped_columns_context context;
1572 : :
1573 : 37398 : context.pstate = pstate;
1574 : 37398 : context.qry = qry;
2463 tgl@sss.pgh.pa.us 1575 : 37398 : context.hasJoinRTEs = hasJoinRTEs;
3817 andres@anarazel.de 1576 : 37398 : context.groupClauses = groupClauses;
1577 : 37398 : context.groupClauseCommonVars = NIL;
412 rguo@postgresql.org 1578 : 37398 : context.gset_common = NIL;
3817 andres@anarazel.de 1579 : 37398 : context.have_non_var_grouping = have_non_var_grouping;
1580 : 37398 : context.func_grouped_rels = NULL;
1581 : 37398 : context.sublevels_up = 0;
1582 : 37398 : context.in_agg_direct_args = false;
1583 : 37398 : finalize_grouping_exprs_walker(node, &context);
1584 : 37395 : }
1585 : :
1586 : : static bool
1587 : 129925 : finalize_grouping_exprs_walker(Node *node,
1588 : : substitute_grouped_columns_context *context)
1589 : : {
1590 : : ListCell *gl;
1591 : :
1592 [ + + ]: 129925 : if (node == NULL)
1593 : 43096 : return false;
1594 [ + + ]: 86829 : if (IsA(node, Const) ||
1595 [ + + ]: 83980 : IsA(node, Param))
1596 : 2977 : return false; /* constants are always acceptable */
1597 : :
1598 [ + + ]: 83852 : if (IsA(node, Aggref))
1599 : : {
1600 : 21594 : Aggref *agg = (Aggref *) node;
1601 : :
1602 [ + + ]: 21594 : if ((int) agg->agglevelsup == context->sublevels_up)
1603 : : {
1604 : : /*
1605 : : * If we find an aggregate call of the original level, do not
1606 : : * recurse into its normal arguments, ORDER BY arguments, or
1607 : : * filter; GROUPING exprs of this level are not allowed there. But
1608 : : * check direct arguments as though they weren't in an aggregate.
1609 : : */
1610 : : bool result;
1611 : :
1612 [ - + ]: 21591 : Assert(!context->in_agg_direct_args);
1613 : 21591 : context->in_agg_direct_args = true;
1614 : 21591 : result = finalize_grouping_exprs_walker((Node *) agg->aggdirectargs,
1615 : : context);
1616 : 21591 : context->in_agg_direct_args = false;
1617 : 21591 : return result;
1618 : : }
1619 : :
1620 : : /*
1621 : : * We can skip recursing into aggregates of higher levels altogether,
1622 : : * since they could not possibly contain exprs of concern to us (see
1623 : : * transformAggregateCall). We do need to look at aggregates of lower
1624 : : * levels, however.
1625 : : */
1626 [ - + ]: 3 : if ((int) agg->agglevelsup > context->sublevels_up)
3817 andres@anarazel.de 1627 :UBC 0 : return false;
1628 : : }
1629 : :
3817 andres@anarazel.de 1630 [ + + ]:CBC 62261 : if (IsA(node, GroupingFunc))
1631 : : {
1632 : 201 : GroupingFunc *grp = (GroupingFunc *) node;
1633 : :
1634 : : /*
1635 : : * We only need to check GroupingFunc nodes at the exact level to
1636 : : * which they belong, since they cannot mix levels in arguments.
1637 : : */
1638 : :
1639 [ + + ]: 201 : if ((int) grp->agglevelsup == context->sublevels_up)
1640 : : {
1641 : : ListCell *lc;
3810 bruce@momjian.us 1642 : 181 : List *ref_list = NIL;
1643 : :
3817 andres@anarazel.de 1644 [ + - + + : 454 : foreach(lc, grp->args)
+ + ]
1645 : : {
3810 bruce@momjian.us 1646 : 276 : Node *expr = lfirst(lc);
1647 : 276 : Index ref = 0;
1648 : :
2463 tgl@sss.pgh.pa.us 1649 [ + + ]: 276 : if (context->hasJoinRTEs)
1001 1650 : 24 : expr = flatten_join_alias_vars(NULL, context->qry, expr);
1651 : :
1652 : : /*
1653 : : * Each expression must match a grouping entry at the current
1654 : : * query level. Unlike the general expression case, we don't
1655 : : * allow functional dependencies or outer references.
1656 : : */
1657 : :
3817 andres@anarazel.de 1658 [ + + ]: 276 : if (IsA(expr, Var))
1659 : : {
3810 bruce@momjian.us 1660 : 246 : Var *var = (Var *) expr;
1661 : :
3817 andres@anarazel.de 1662 [ + - ]: 246 : if (var->varlevelsup == context->sublevels_up)
1663 : : {
1664 [ + + + - : 362 : foreach(gl, context->groupClauses)
+ + ]
1665 : : {
1666 : 359 : TargetEntry *tle = lfirst(gl);
1667 : 359 : Var *gvar = (Var *) tle->expr;
1668 : :
1669 [ + - ]: 359 : if (IsA(gvar, Var) &&
1670 [ + + ]: 359 : gvar->varno == var->varno &&
1671 [ + + ]: 353 : gvar->varattno == var->varattno &&
1672 [ + - ]: 243 : gvar->varlevelsup == 0)
1673 : : {
1674 : 243 : ref = tle->ressortgroupref;
1675 : 243 : break;
1676 : : }
1677 : : }
1678 : : }
1679 : : }
1680 [ + - ]: 30 : else if (context->have_non_var_grouping &&
1681 [ + - ]: 30 : context->sublevels_up == 0)
1682 : : {
1683 [ + - + - : 60 : foreach(gl, context->groupClauses)
+ - ]
1684 : : {
1685 : 60 : TargetEntry *tle = lfirst(gl);
1686 : :
1687 [ + + ]: 60 : if (equal(expr, tle->expr))
1688 : : {
1689 : 30 : ref = tle->ressortgroupref;
1690 : 30 : break;
1691 : : }
1692 : : }
1693 : : }
1694 : :
1695 [ + + ]: 276 : if (ref == 0)
1696 [ + - ]: 3 : ereport(ERROR,
1697 : : (errcode(ERRCODE_GROUPING_ERROR),
1698 : : errmsg("arguments to GROUPING must be grouping expressions of the associated query level"),
1699 : : parser_errposition(context->pstate,
1700 : : exprLocation(expr))));
1701 : :
1702 : 273 : ref_list = lappend_int(ref_list, ref);
1703 : : }
1704 : :
1705 : 178 : grp->refs = ref_list;
1706 : : }
1707 : :
1708 [ + + ]: 198 : if ((int) grp->agglevelsup > context->sublevels_up)
1709 : 4 : return false;
1710 : : }
1711 : :
1712 [ + + ]: 62254 : if (IsA(node, Query))
1713 : : {
1714 : : /* Recurse into subselects */
1715 : : bool result;
1716 : :
1717 : 217 : context->sublevels_up++;
1718 : 217 : result = query_tree_walker((Query *) node,
1719 : : finalize_grouping_exprs_walker,
1720 : : context,
1721 : : 0);
1722 : 217 : context->sublevels_up--;
1723 : 217 : return result;
1724 : : }
1725 : 62037 : return expression_tree_walker(node, finalize_grouping_exprs_walker,
1726 : : context);
1727 : : }
1728 : :
1729 : : /*
1730 : : * buildGroupedVar -
1731 : : * build a Var node that references the RTE_GROUP RTE
1732 : : */
1733 : : static Var *
412 rguo@postgresql.org 1734 : 5930 : buildGroupedVar(int attnum, Index ressortgroupref,
1735 : : substitute_grouped_columns_context *context)
1736 : : {
1737 : : Var *var;
1738 : 5930 : ParseNamespaceItem *grouping_nsitem = context->pstate->p_grouping_nsitem;
1739 : 5930 : ParseNamespaceColumn *nscol = grouping_nsitem->p_nscolumns + attnum - 1;
1740 : :
1741 [ - + ]: 5930 : Assert(nscol->p_varno == grouping_nsitem->p_rtindex);
1742 [ - + ]: 5930 : Assert(nscol->p_varattno == attnum);
1743 : 5930 : var = makeVar(nscol->p_varno,
1744 : 5930 : nscol->p_varattno,
1745 : : nscol->p_vartype,
1746 : : nscol->p_vartypmod,
1747 : : nscol->p_varcollid,
1748 : 5930 : context->sublevels_up);
1749 : : /* makeVar doesn't offer parameters for these, so set by hand: */
1750 : 5930 : var->varnosyn = nscol->p_varnosyn;
1751 : 5930 : var->varattnosyn = nscol->p_varattnosyn;
1752 : :
1753 [ + + ]: 5930 : if (context->qry->groupingSets &&
1754 [ + + ]: 1053 : !list_member_int(context->gset_common, ressortgroupref))
1755 : 939 : var->varnullingrels =
1756 : 939 : bms_add_member(var->varnullingrels, grouping_nsitem->p_rtindex);
1757 : :
1758 : 5930 : return var;
1759 : : }
1760 : :
1761 : :
1762 : : /*
1763 : : * Given a GroupingSet node, expand it and return a list of lists.
1764 : : *
1765 : : * For EMPTY nodes, return a list of one empty list.
1766 : : *
1767 : : * For SIMPLE nodes, return a list of one list, which is the node content.
1768 : : *
1769 : : * For CUBE and ROLLUP nodes, return a list of the expansions.
1770 : : *
1771 : : * For SET nodes, recursively expand contained CUBE and ROLLUP.
1772 : : */
1773 : : static List *
3817 andres@anarazel.de 1774 : 2297 : expand_groupingset_node(GroupingSet *gs)
1775 : : {
3810 bruce@momjian.us 1776 : 2297 : List *result = NIL;
1777 : :
3817 andres@anarazel.de 1778 [ + + + + : 2297 : switch (gs->kind)
+ - ]
1779 : : {
1780 : 252 : case GROUPING_SET_EMPTY:
1781 : 252 : result = list_make1(NIL);
1782 : 252 : break;
1783 : :
1784 : 1064 : case GROUPING_SET_SIMPLE:
1785 : 1064 : result = list_make1(gs->content);
1786 : 1064 : break;
1787 : :
1788 : 289 : case GROUPING_SET_ROLLUP:
1789 : : {
1790 : 289 : List *rollup_val = gs->content;
1791 : : ListCell *lc;
1792 : 289 : int curgroup_size = list_length(gs->content);
1793 : :
1794 [ + + ]: 743 : while (curgroup_size > 0)
1795 : : {
3810 bruce@momjian.us 1796 : 454 : List *current_result = NIL;
1797 : 454 : int i = curgroup_size;
1798 : :
3817 andres@anarazel.de 1799 [ + - + - : 619 : foreach(lc, rollup_val)
+ - ]
1800 : : {
1801 : 619 : GroupingSet *gs_current = (GroupingSet *) lfirst(lc);
1802 : :
1803 [ - + ]: 619 : Assert(gs_current->kind == GROUPING_SET_SIMPLE);
1804 : :
2268 tgl@sss.pgh.pa.us 1805 : 619 : current_result = list_concat(current_result,
1806 : 619 : gs_current->content);
1807 : :
1808 : : /* If we are done with making the current group, break */
3817 andres@anarazel.de 1809 [ + + ]: 619 : if (--i == 0)
1810 : 454 : break;
1811 : : }
1812 : :
1813 : 454 : result = lappend(result, current_result);
1814 : 454 : --curgroup_size;
1815 : : }
1816 : :
1817 : 289 : result = lappend(result, NIL);
1818 : : }
1819 : 289 : break;
1820 : :
1821 : 184 : case GROUPING_SET_CUBE:
1822 : : {
3810 bruce@momjian.us 1823 : 184 : List *cube_list = gs->content;
1824 : 184 : int number_bits = list_length(cube_list);
1825 : : uint32 num_sets;
1826 : : uint32 i;
1827 : :
1828 : : /* parser should cap this much lower */
3817 andres@anarazel.de 1829 [ - + ]: 184 : Assert(number_bits < 31);
1830 : :
1831 : 184 : num_sets = (1U << number_bits);
1832 : :
1833 [ + + ]: 1020 : for (i = 0; i < num_sets; i++)
1834 : : {
3810 bruce@momjian.us 1835 : 836 : List *current_result = NIL;
1836 : : ListCell *lc;
1837 : 836 : uint32 mask = 1U;
1838 : :
3817 andres@anarazel.de 1839 [ + - + + : 2776 : foreach(lc, cube_list)
+ + ]
1840 : : {
1841 : 1940 : GroupingSet *gs_current = (GroupingSet *) lfirst(lc);
1842 : :
1843 [ - + ]: 1940 : Assert(gs_current->kind == GROUPING_SET_SIMPLE);
1844 : :
1845 [ + + ]: 1940 : if (mask & i)
2268 tgl@sss.pgh.pa.us 1846 : 970 : current_result = list_concat(current_result,
1847 : 970 : gs_current->content);
1848 : :
3817 andres@anarazel.de 1849 : 1940 : mask <<= 1;
1850 : : }
1851 : :
1852 : 836 : result = lappend(result, current_result);
1853 : : }
1854 : : }
1855 : 184 : break;
1856 : :
1857 : 508 : case GROUPING_SET_SETS:
1858 : : {
1859 : : ListCell *lc;
1860 : :
1861 [ + - + + : 1776 : foreach(lc, gs->content)
+ + ]
1862 : : {
3810 bruce@momjian.us 1863 : 1268 : List *current_result = expand_groupingset_node(lfirst(lc));
1864 : :
3817 andres@anarazel.de 1865 : 1268 : result = list_concat(result, current_result);
1866 : : }
1867 : : }
1868 : 508 : break;
1869 : : }
1870 : :
1871 : 2297 : return result;
1872 : : }
1873 : :
1874 : : /* list_sort comparator to sort sub-lists by length */
1875 : : static int
2295 tgl@sss.pgh.pa.us 1876 : 2931 : cmp_list_len_asc(const ListCell *a, const ListCell *b)
1877 : : {
1878 : 2931 : int la = list_length((const List *) lfirst(a));
1879 : 2931 : int lb = list_length((const List *) lfirst(b));
1880 : :
619 nathan@postgresql.or 1881 : 2931 : return pg_cmp_s32(la, lb);
1882 : : }
1883 : :
1884 : : /* list_sort comparator to sort sub-lists by length and contents */
1885 : : static int
1684 tomas.vondra@postgre 1886 : 160 : cmp_list_len_contents_asc(const ListCell *a, const ListCell *b)
1887 : : {
1629 tgl@sss.pgh.pa.us 1888 : 160 : int res = cmp_list_len_asc(a, b);
1889 : :
1684 tomas.vondra@postgre 1890 [ + + ]: 160 : if (res == 0)
1891 : : {
1629 tgl@sss.pgh.pa.us 1892 : 48 : List *la = (List *) lfirst(a);
1893 : 48 : List *lb = (List *) lfirst(b);
1894 : : ListCell *lca;
1895 : : ListCell *lcb;
1896 : :
1684 tomas.vondra@postgre 1897 [ + - + + : 112 : forboth(lca, la, lcb, lb)
+ - + + +
+ + - +
+ ]
1898 : : {
1629 tgl@sss.pgh.pa.us 1899 : 80 : int va = lfirst_int(lca);
1900 : 80 : int vb = lfirst_int(lcb);
1901 : :
1684 tomas.vondra@postgre 1902 [ + + ]: 80 : if (va > vb)
1903 : 16 : return 1;
1904 [ + + ]: 72 : if (va < vb)
1905 : 8 : return -1;
1906 : : }
1907 : : }
1908 : :
1909 : 144 : return res;
1910 : : }
1911 : :
1912 : : /*
1913 : : * Expand a groupingSets clause to a flat list of grouping sets.
1914 : : * The returned list is sorted by length, shortest sets first.
1915 : : *
1916 : : * This is mainly for the planner, but we use it here too to do
1917 : : * some consistency checks.
1918 : : */
1919 : : List *
1920 : 953 : expand_grouping_sets(List *groupingSets, bool groupDistinct, int limit)
1921 : : {
3817 andres@anarazel.de 1922 : 953 : List *expanded_groups = NIL;
3810 bruce@momjian.us 1923 : 953 : List *result = NIL;
3817 andres@anarazel.de 1924 : 953 : double numsets = 1;
1925 : : ListCell *lc;
1926 : :
1927 [ - + ]: 953 : if (groupingSets == NIL)
3817 andres@anarazel.de 1928 :UBC 0 : return NIL;
1929 : :
3817 andres@anarazel.de 1930 [ + - + + :CBC 1982 : foreach(lc, groupingSets)
+ + ]
1931 : : {
3810 bruce@momjian.us 1932 : 1029 : List *current_result = NIL;
3817 andres@anarazel.de 1933 : 1029 : GroupingSet *gs = lfirst(lc);
1934 : :
1935 : 1029 : current_result = expand_groupingset_node(gs);
1936 : :
1937 [ - + ]: 1029 : Assert(current_result != NIL);
1938 : :
1939 : 1029 : numsets *= list_length(current_result);
1940 : :
1941 [ + + - + ]: 1029 : if (limit >= 0 && numsets > limit)
3817 andres@anarazel.de 1942 :UBC 0 : return NIL;
1943 : :
3817 andres@anarazel.de 1944 :CBC 1029 : expanded_groups = lappend(expanded_groups, current_result);
1945 : : }
1946 : :
1947 : : /*
1948 : : * Do cartesian product between sublists of expanded_groups. While at it,
1949 : : * remove any duplicate elements from individual grouping sets (we must
1950 : : * NOT change the number of sets though)
1951 : : */
1952 : :
1953 [ + - + + : 3692 : foreach(lc, (List *) linitial(expanded_groups))
+ + ]
1954 : : {
1955 : 2739 : result = lappend(result, list_union_int(NIL, (List *) lfirst(lc)));
1956 : : }
1957 : :
1855 tgl@sss.pgh.pa.us 1958 [ + - + + : 1029 : for_each_from(lc, expanded_groups, 1)
+ + ]
1959 : : {
3817 andres@anarazel.de 1960 : 76 : List *p = lfirst(lc);
1961 : 76 : List *new_result = NIL;
1962 : : ListCell *lc2;
1963 : :
1964 [ + - + + : 238 : foreach(lc2, result)
+ + ]
1965 : : {
1966 : 162 : List *q = lfirst(lc2);
1967 : : ListCell *lc3;
1968 : :
1969 [ + - + + : 528 : foreach(lc3, p)
+ + ]
1970 : : {
1971 : 366 : new_result = lappend(new_result,
1972 : 366 : list_union_int(q, (List *) lfirst(lc3)));
1973 : : }
1974 : : }
1975 : 76 : result = new_result;
1976 : : }
1977 : :
1978 : : /* Now sort the lists by length and deduplicate if necessary */
1684 tomas.vondra@postgre 1979 [ + + - + ]: 953 : if (!groupDistinct || list_length(result) < 2)
1980 : 945 : list_sort(result, cmp_list_len_asc);
1981 : : else
1982 : : {
1983 : : ListCell *cell;
1984 : : List *prev;
1985 : :
1986 : : /* Sort each groupset individually */
1987 [ + - + + : 80 : foreach(cell, result)
+ + ]
1988 : 72 : list_sort(lfirst(cell), list_int_cmp);
1989 : :
1990 : : /* Now sort the list of groupsets by length and contents */
1991 : 8 : list_sort(result, cmp_list_len_contents_asc);
1992 : :
1993 : : /* Finally, remove duplicates */
1589 drowley@postgresql.o 1994 : 8 : prev = linitial(result);
1684 tomas.vondra@postgre 1995 [ + - + + : 72 : for_each_from(cell, result, 1)
+ + ]
1996 : : {
1997 [ + + ]: 64 : if (equal(lfirst(cell), prev))
tgl@sss.pgh.pa.us 1998 : 32 : result = foreach_delete_current(result, cell);
1999 : : else
tomas.vondra@postgre 2000 : 32 : prev = lfirst(cell);
2001 : : }
2002 : : }
2003 : :
3817 andres@anarazel.de 2004 : 953 : return result;
2005 : : }
2006 : :
2007 : : /*
2008 : : * get_aggregate_argtypes
2009 : : * Identify the specific datatypes passed to an aggregate call.
2010 : : *
2011 : : * Given an Aggref, extract the actual datatypes of the input arguments.
2012 : : * The input datatypes are reported in a way that matches up with the
2013 : : * aggregate's declaration, ie, any ORDER BY columns attached to a plain
2014 : : * aggregate are ignored, but we report both direct and aggregated args of
2015 : : * an ordered-set aggregate.
2016 : : *
2017 : : * Datatypes are returned into inputTypes[], which must reference an array
2018 : : * of length FUNC_MAX_ARGS.
2019 : : *
2020 : : * The function result is the number of actual arguments.
2021 : : */
2022 : : int
4326 tgl@sss.pgh.pa.us 2023 : 49014 : get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
2024 : : {
2025 : 49014 : int numArguments = 0;
2026 : : ListCell *lc;
2027 : :
3419 2028 [ - + ]: 49014 : Assert(list_length(aggref->aggargtypes) <= FUNC_MAX_ARGS);
2029 : :
2030 [ + + + + : 88815 : foreach(lc, aggref->aggargtypes)
+ + ]
2031 : : {
2032 : 39801 : inputTypes[numArguments++] = lfirst_oid(lc);
2033 : : }
2034 : :
4326 2035 : 49014 : return numArguments;
2036 : : }
2037 : :
2038 : : /*
2039 : : * resolve_aggregate_transtype
2040 : : * Identify the transition state value's datatype for an aggregate call.
2041 : : *
2042 : : * This function resolves a polymorphic aggregate's state datatype.
2043 : : * It must be passed the aggtranstype from the aggregate's catalog entry,
2044 : : * as well as the actual argument types extracted by get_aggregate_argtypes.
2045 : : * (We could fetch pg_aggregate.aggtranstype internally, but all existing
2046 : : * callers already have the value at hand, so we make them pass it.)
2047 : : */
2048 : : Oid
2049 : 22091 : resolve_aggregate_transtype(Oid aggfuncid,
2050 : : Oid aggtranstype,
2051 : : Oid *inputTypes,
2052 : : int numArguments)
2053 : : {
2054 : : /* resolve actual type of transition state, if polymorphic */
2055 [ + + + + : 22091 : if (IsPolymorphicType(aggtranstype))
+ - + + +
+ + + + +
+ - + - +
- - + ]
2056 : : {
2057 : : /* have to fetch the agg's declared input types... */
2058 : : Oid *declaredArgTypes;
2059 : : int agg_nargs;
2060 : :
2061 : 272 : (void) get_func_signature(aggfuncid, &declaredArgTypes, &agg_nargs);
2062 : :
2063 : : /*
2064 : : * VARIADIC ANY aggs could have more actual than declared args, but
2065 : : * such extra args can't affect polymorphic type resolution.
2066 : : */
2067 [ - + ]: 272 : Assert(agg_nargs <= numArguments);
2068 : :
2069 : 272 : aggtranstype = enforce_generic_type_consistency(inputTypes,
2070 : : declaredArgTypes,
2071 : : agg_nargs,
2072 : : aggtranstype,
2073 : : false);
2074 : 272 : pfree(declaredArgTypes);
2075 : : }
2076 : 22091 : return aggtranstype;
2077 : : }
2078 : :
2079 : : /*
2080 : : * agg_args_support_sendreceive
2081 : : * Returns true if all non-byval types of aggref's args have send and
2082 : : * receive functions.
2083 : : */
2084 : : bool
1008 drowley@postgresql.o 2085 : 5662 : agg_args_support_sendreceive(Aggref *aggref)
2086 : : {
2087 : : ListCell *lc;
2088 : :
2089 [ + - + + : 11255 : foreach(lc, aggref->args)
+ + ]
2090 : : {
2091 : : HeapTuple typeTuple;
2092 : : Form_pg_type pt;
2093 : 5662 : TargetEntry *tle = (TargetEntry *) lfirst(lc);
2094 : 5662 : Oid type = exprType((Node *) tle->expr);
2095 : :
2096 : : /*
2097 : : * RECORD is a special case: it has typsend/typreceive functions, but
2098 : : * record_recv only works if passed the correct typmod to identify the
2099 : : * specific anonymous record type. array_agg_deserialize cannot do
2100 : : * that, so we have to disclaim support for the case.
2101 : : */
232 tgl@sss.pgh.pa.us 2102 [ + + ]: 5662 : if (type == RECORDOID)
2103 : 69 : return false;
2104 : :
1008 drowley@postgresql.o 2105 : 5641 : typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2106 [ - + ]: 5641 : if (!HeapTupleIsValid(typeTuple))
1008 drowley@postgresql.o 2107 [ # # ]:UBC 0 : elog(ERROR, "cache lookup failed for type %u", type);
2108 : :
1008 drowley@postgresql.o 2109 :CBC 5641 : pt = (Form_pg_type) GETSTRUCT(typeTuple);
2110 : :
2111 [ + + ]: 5641 : if (!pt->typbyval &&
2112 [ + + - + ]: 5567 : (!OidIsValid(pt->typsend) || !OidIsValid(pt->typreceive)))
2113 : : {
2114 : 48 : ReleaseSysCache(typeTuple);
2115 : 48 : return false;
2116 : : }
2117 : 5593 : ReleaseSysCache(typeTuple);
2118 : : }
2119 : 5593 : return true;
2120 : : }
2121 : :
2122 : : /*
2123 : : * Create an expression tree for the transition function of an aggregate.
2124 : : * This is needed so that polymorphic functions can be used within an
2125 : : * aggregate --- without the expression tree, such functions would not know
2126 : : * the datatypes they are supposed to use. (The trees will never actually
2127 : : * be executed, however, so we can skimp a bit on correctness.)
2128 : : *
2129 : : * agg_input_types and agg_state_type identifies the input types of the
2130 : : * aggregate. These should be resolved to actual types (ie, none should
2131 : : * ever be ANYELEMENT etc).
2132 : : * agg_input_collation is the aggregate function's input collation.
2133 : : *
2134 : : * For an ordered-set aggregate, remember that agg_input_types describes
2135 : : * the direct arguments followed by the aggregated arguments.
2136 : : *
2137 : : * transfn_oid and invtransfn_oid identify the funcs to be called; the
2138 : : * latter may be InvalidOid, however if invtransfn_oid is set then
2139 : : * transfn_oid must also be set.
2140 : : *
2141 : : * transfn_oid may also be passed as the aggcombinefn when the *transfnexpr is
2142 : : * to be used for a combine aggregate phase. We expect invtransfn_oid to be
2143 : : * InvalidOid in this case since there is no such thing as an inverse
2144 : : * combinefn.
2145 : : *
2146 : : * Pointers to the constructed trees are returned into *transfnexpr,
2147 : : * *invtransfnexpr. If there is no invtransfn, the respective pointer is set
2148 : : * to NULL. Since use of the invtransfn is optional, NULL may be passed for
2149 : : * invtransfnexpr.
2150 : : */
2151 : : void
3737 heikki.linnakangas@i 2152 : 26350 : build_aggregate_transfn_expr(Oid *agg_input_types,
2153 : : int agg_num_inputs,
2154 : : int agg_num_direct_inputs,
2155 : : bool agg_variadic,
2156 : : Oid agg_state_type,
2157 : : Oid agg_input_collation,
2158 : : Oid transfn_oid,
2159 : : Oid invtransfn_oid,
2160 : : Expr **transfnexpr,
2161 : : Expr **invtransfnexpr)
2162 : : {
2163 : : List *args;
2164 : : FuncExpr *fexpr;
2165 : : int i;
2166 : :
2167 : : /*
2168 : : * Build arg list to use in the transfn FuncExpr node.
2169 : : */
3414 tgl@sss.pgh.pa.us 2170 : 26350 : args = list_make1(make_agg_arg(agg_state_type, agg_input_collation));
2171 : :
4326 2172 [ + + ]: 48854 : for (i = agg_num_direct_inputs; i < agg_num_inputs; i++)
2173 : : {
3414 2174 : 22504 : args = lappend(args,
2175 : 22504 : make_agg_arg(agg_input_types[i], agg_input_collation));
2176 : : }
2177 : :
4437 2178 : 26350 : fexpr = makeFuncExpr(transfn_oid,
2179 : : agg_state_type,
2180 : : args,
2181 : : InvalidOid,
2182 : : agg_input_collation,
2183 : : COERCE_EXPLICIT_CALL);
2184 : 26350 : fexpr->funcvariadic = agg_variadic;
2185 : 26350 : *transfnexpr = (Expr *) fexpr;
2186 : :
2187 : : /*
2188 : : * Build invtransfn expression if requested, with same args as transfn
2189 : : */
4216 2190 [ + + ]: 26350 : if (invtransfnexpr != NULL)
2191 : : {
2192 [ + + ]: 772 : if (OidIsValid(invtransfn_oid))
2193 : : {
2194 : 399 : fexpr = makeFuncExpr(invtransfn_oid,
2195 : : agg_state_type,
2196 : : args,
2197 : : InvalidOid,
2198 : : agg_input_collation,
2199 : : COERCE_EXPLICIT_CALL);
2200 : 399 : fexpr->funcvariadic = agg_variadic;
2201 : 399 : *invtransfnexpr = (Expr *) fexpr;
2202 : : }
2203 : : else
2204 : 373 : *invtransfnexpr = NULL;
2205 : : }
3737 heikki.linnakangas@i 2206 : 26350 : }
2207 : :
2208 : : /*
2209 : : * Like build_aggregate_transfn_expr, but creates an expression tree for the
2210 : : * serialization function of an aggregate.
2211 : : */
2212 : : void
3414 tgl@sss.pgh.pa.us 2213 : 168 : build_aggregate_serialfn_expr(Oid serialfn_oid,
2214 : : Expr **serialfnexpr)
2215 : : {
2216 : : List *args;
2217 : : FuncExpr *fexpr;
2218 : :
2219 : : /* serialfn always takes INTERNAL and returns BYTEA */
2220 : 168 : args = list_make1(make_agg_arg(INTERNALOID, InvalidOid));
2221 : :
3499 rhaas@postgresql.org 2222 : 168 : fexpr = makeFuncExpr(serialfn_oid,
2223 : : BYTEAOID,
2224 : : args,
2225 : : InvalidOid,
2226 : : InvalidOid,
2227 : : COERCE_EXPLICIT_CALL);
2228 : 168 : *serialfnexpr = (Expr *) fexpr;
2229 : 168 : }
2230 : :
2231 : : /*
2232 : : * Like build_aggregate_transfn_expr, but creates an expression tree for the
2233 : : * deserialization function of an aggregate.
2234 : : */
2235 : : void
3414 tgl@sss.pgh.pa.us 2236 : 60 : build_aggregate_deserialfn_expr(Oid deserialfn_oid,
2237 : : Expr **deserialfnexpr)
2238 : : {
2239 : : List *args;
2240 : : FuncExpr *fexpr;
2241 : :
2242 : : /* deserialfn always takes BYTEA, INTERNAL and returns INTERNAL */
2243 : 60 : args = list_make2(make_agg_arg(BYTEAOID, InvalidOid),
2244 : : make_agg_arg(INTERNALOID, InvalidOid));
2245 : :
2246 : 60 : fexpr = makeFuncExpr(deserialfn_oid,
2247 : : INTERNALOID,
2248 : : args,
2249 : : InvalidOid,
2250 : : InvalidOid,
2251 : : COERCE_EXPLICIT_CALL);
2252 : 60 : *deserialfnexpr = (Expr *) fexpr;
2253 : 60 : }
2254 : :
2255 : : /*
2256 : : * Like build_aggregate_transfn_expr, but creates an expression tree for the
2257 : : * final function of an aggregate, rather than the transition function.
2258 : : */
2259 : : void
3737 heikki.linnakangas@i 2260 : 11595 : build_aggregate_finalfn_expr(Oid *agg_input_types,
2261 : : int num_finalfn_inputs,
2262 : : Oid agg_state_type,
2263 : : Oid agg_result_type,
2264 : : Oid agg_input_collation,
2265 : : Oid finalfn_oid,
2266 : : Expr **finalfnexpr)
2267 : : {
2268 : : List *args;
2269 : : int i;
2270 : :
2271 : : /*
2272 : : * Build expr tree for final function
2273 : : */
3414 tgl@sss.pgh.pa.us 2274 : 11595 : args = list_make1(make_agg_arg(agg_state_type, agg_input_collation));
2275 : :
2276 : : /* finalfn may take additional args, which match agg's input types */
4205 2277 [ + + ]: 18973 : for (i = 0; i < num_finalfn_inputs - 1; i++)
2278 : : {
3414 2279 : 7378 : args = lappend(args,
2280 : 7378 : make_agg_arg(agg_input_types[i], agg_input_collation));
2281 : : }
2282 : :
8120 bruce@momjian.us 2283 : 11595 : *finalfnexpr = (Expr *) makeFuncExpr(finalfn_oid,
2284 : : agg_result_type,
2285 : : args,
2286 : : InvalidOid,
2287 : : agg_input_collation,
2288 : : COERCE_EXPLICIT_CALL);
2289 : : /* finalfn is currently never treated as variadic */
8154 tgl@sss.pgh.pa.us 2290 : 11595 : }
2291 : :
2292 : : /*
2293 : : * Convenience function to build dummy argument expressions for aggregates.
2294 : : *
2295 : : * We really only care that an aggregate support function can discover its
2296 : : * actual argument types at runtime using get_fn_expr_argtype(), so it's okay
2297 : : * to use Param nodes that don't correspond to any real Param.
2298 : : */
2299 : : static Node *
3414 2300 : 68115 : make_agg_arg(Oid argtype, Oid argcollation)
2301 : : {
2302 : 68115 : Param *argp = makeNode(Param);
2303 : :
2304 : 68115 : argp->paramkind = PARAM_EXEC;
2305 : 68115 : argp->paramid = -1;
2306 : 68115 : argp->paramtype = argtype;
2307 : 68115 : argp->paramtypmod = -1;
2308 : 68115 : argp->paramcollid = argcollation;
2309 : 68115 : argp->location = -1;
2310 : 68115 : return (Node *) argp;
2311 : : }
|