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
5652 tgl@sss.pgh.pa.us 109 :CBC 20980 : transformAggregateCall(ParseState *pstate, Aggref *agg,
110 : : List *args, List *aggorder, bool agg_distinct)
111 : : {
3368 112 : 20980 : List *argtypes = NIL;
4275 113 : 20980 : List *tlist = NIL;
114 : 20980 : List *torder = NIL;
5671 bruce@momjian.us 115 : 20980 : List *tdistinct = NIL;
4275 tgl@sss.pgh.pa.us 116 : 20980 : AttrNumber attno = 1;
117 : : int save_next_resno;
118 : : ListCell *lc;
119 : :
120 [ + + ]: 20980 : 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 : 20821 : agg->aggdirectargs = NIL;
162 : :
163 : : /*
164 : : * Transform the plain list of Exprs into a targetlist.
165 : : */
166 [ + + + + : 37890 : foreach(lc, args)
+ + ]
167 : : {
168 : 17069 : Expr *arg = (Expr *) lfirst(lc);
169 : : TargetEntry *tle;
170 : :
171 : : /* We don't bother to assign column names to the entries */
172 : 17069 : tle = makeTargetEntry(arg, attno++, NULL, false);
173 : 17069 : 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 : 20821 : save_next_resno = pstate->p_next_resno;
186 : 20821 : pstate->p_next_resno = attno;
187 : :
188 : 20821 : 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 [ + + ]: 20821 : 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 : : {
4275 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 : :
4275 tgl@sss.pgh.pa.us 223 :CBC 20803 : pstate->p_next_resno = save_next_resno;
224 : : }
225 : :
226 : : /* Update the Aggref with the transformation results */
5744 227 : 20962 : agg->args = tlist;
228 : 20962 : agg->aggorder = torder;
229 : 20962 : 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 : : */
670 238 [ + + + + : 21145 : foreach(lc, agg->aggdirectargs)
+ + ]
239 : : {
240 : 183 : Expr *arg = (Expr *) lfirst(lc);
241 : :
242 : 183 : argtypes = lappend_oid(argtypes, exprType((Node *) arg));
243 : : }
244 [ + + + + : 38961 : foreach(lc, tlist)
+ + ]
245 : : {
246 : 17999 : TargetEntry *tle = (TargetEntry *) lfirst(lc);
247 : :
248 [ + + ]: 17999 : if (tle->resjunk)
249 : 792 : continue; /* ignore junk */
250 : 17207 : argtypes = lappend_oid(argtypes, exprType((Node *) tle->expr));
251 : : }
252 : 20962 : agg->aggargtypes = argtypes;
253 : :
3766 andres@anarazel.de 254 : 20962 : check_agglevels_and_constraints(pstate, (Node *) agg);
255 : 20890 : }
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)
3766 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 : :
3766 andres@anarazel.de 278 [ + - + + :CBC 460 : foreach(lc, args)
+ + ]
279 : : {
280 : : Node *current_result;
281 : :
3759 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 : :
3766 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 : 21143 : check_agglevels_and_constraints(ParseState *pstate, Node *expr)
305 : : {
306 : 21143 : List *directargs = NIL;
307 : 21143 : List *args = NIL;
308 : 21143 : Expr *filter = NULL;
309 : : int min_varlevel;
310 : 21143 : int location = -1;
311 : : Index *p_levelsup;
312 : : const char *err;
313 : : bool errkind;
314 : 21143 : bool isAgg = IsA(expr, Aggref);
315 : :
316 [ + + ]: 21143 : if (isAgg)
317 : : {
3759 bruce@momjian.us 318 : 20962 : Aggref *agg = (Aggref *) expr;
319 : :
3766 andres@anarazel.de 320 : 20962 : directargs = agg->aggdirectargs;
321 : 20962 : args = agg->args;
322 : 20962 : filter = agg->aggfilter;
323 : 20962 : location = agg->location;
324 : 20962 : 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 : : */
4275 tgl@sss.pgh.pa.us 339 : 21143 : min_varlevel = check_agg_arguments(pstate,
340 : : directargs,
341 : : args,
342 : : filter);
343 : :
3766 andres@anarazel.de 344 : 21119 : *p_levelsup = min_varlevel;
345 : :
346 : : /* Mark the correct pstate level as having aggregates */
4775 tgl@sss.pgh.pa.us 347 [ + + ]: 21208 : while (min_varlevel-- > 0)
348 : 89 : pstate = pstate->parentParseState;
349 : 21119 : 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 : 21119 : err = NULL;
362 : 21119 : errkind = false;
363 [ - - - + : 21119 : switch (pstate->p_expr_kind)
- + + + +
- + - - -
+ - - - +
- - - - -
+ - - - -
- - + + +
- + - - ]
364 : : {
4775 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:
3766 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 : :
4775 tgl@sss.pgh.pa.us 382 : 0 : break;
4775 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 : : */
3766 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
3766 andres@anarazel.de 392 :UBC 0 : err = _("grouping operations are not allowed in FROM clause of their own query level");
393 : :
4775 tgl@sss.pgh.pa.us 394 :CBC 12 : break;
4775 tgl@sss.pgh.pa.us 395 :UBC 0 : case EXPR_KIND_FROM_FUNCTION:
3766 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 : :
4775 tgl@sss.pgh.pa.us 401 : 0 : break;
4775 tgl@sss.pgh.pa.us 402 :CBC 6 : case EXPR_KIND_WHERE:
403 : 6 : errkind = true;
3692 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
3692 mail@joeconway.com 409 :UBC 0 : err = _("grouping operations are not allowed in policy expressions");
410 : :
4775 tgl@sss.pgh.pa.us 411 :CBC 3 : break;
412 : 314 : case EXPR_KIND_HAVING:
413 : : /* okay */
414 : 314 : break;
4435 noah@leadboat.com 415 : 6 : case EXPR_KIND_FILTER:
416 : 6 : errkind = true;
417 : 6 : break;
4775 tgl@sss.pgh.pa.us 418 :UBC 0 : case EXPR_KIND_WINDOW_PARTITION:
419 : : /* okay */
420 : 0 : break;
4775 tgl@sss.pgh.pa.us 421 :CBC 6 : case EXPR_KIND_WINDOW_ORDER:
422 : : /* okay */
423 : 6 : break;
4775 tgl@sss.pgh.pa.us 424 :UBC 0 : case EXPR_KIND_WINDOW_FRAME_RANGE:
3766 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 : :
4775 tgl@sss.pgh.pa.us 430 : 0 : break;
431 : 0 : case EXPR_KIND_WINDOW_FRAME_ROWS:
3766 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 : :
2768 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 : :
4775 444 : 0 : break;
4775 tgl@sss.pgh.pa.us 445 :CBC 20711 : case EXPR_KIND_SELECT_TARGET:
446 : : /* okay */
447 : 20711 : break;
4775 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;
1258 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 : :
4775 tgl@sss.pgh.pa.us 459 : 0 : break;
460 : 0 : case EXPR_KIND_GROUP_BY:
461 : 0 : errkind = true;
462 : 0 : break;
4775 tgl@sss.pgh.pa.us 463 :CBC 40 : case EXPR_KIND_ORDER_BY:
464 : : /* okay */
465 : 40 : break;
4775 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:
3766 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 : :
4775 tgl@sss.pgh.pa.us 488 : 0 : break;
4775 tgl@sss.pgh.pa.us 489 :CBC 3 : case EXPR_KIND_COLUMN_DEFAULT:
490 : : case EXPR_KIND_FUNCTION_DEFAULT:
491 : :
3766 andres@anarazel.de 492 [ + - ]: 3 : if (isAgg)
493 : 3 : err = _("aggregate functions are not allowed in DEFAULT expressions");
494 : : else
3766 andres@anarazel.de 495 :UBC 0 : err = _("grouping operations are not allowed in DEFAULT expressions");
496 : :
4775 tgl@sss.pgh.pa.us 497 :CBC 3 : break;
4775 tgl@sss.pgh.pa.us 498 :UBC 0 : case EXPR_KIND_INDEX_EXPRESSION:
3766 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 : :
4775 tgl@sss.pgh.pa.us 504 : 0 : break;
505 : 0 : case EXPR_KIND_INDEX_PREDICATE:
3766 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 : :
1625 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 : :
4775 tgl@sss.pgh.pa.us 518 : 0 : break;
519 : 0 : case EXPR_KIND_ALTER_COL_TRANSFORM:
3766 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 : :
4775 tgl@sss.pgh.pa.us 525 : 0 : break;
526 : 0 : case EXPR_KIND_EXECUTE_PARAMETER:
3766 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 : :
4775 tgl@sss.pgh.pa.us 532 : 0 : break;
533 : 0 : case EXPR_KIND_TRIGGER_WHEN:
3766 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 : :
2416 peter@eisentraut.org 539 : 0 : break;
2416 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
2416 peter@eisentraut.org 544 :UBC 0 : err = _("grouping operations are not allowed in partition bound");
545 : :
4775 tgl@sss.pgh.pa.us 546 :CBC 6 : break;
3195 rhaas@postgresql.org 547 : 3 : case EXPR_KIND_PARTITION_EXPRESSION:
548 [ + - ]: 3 : if (isAgg)
2765 tgl@sss.pgh.pa.us 549 : 3 : err = _("aggregate functions are not allowed in partition key expressions");
550 : : else
2765 tgl@sss.pgh.pa.us 551 :UBC 0 : err = _("grouping operations are not allowed in partition key expressions");
552 : :
3195 rhaas@postgresql.org 553 :CBC 3 : break;
2352 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
2352 peter@eisentraut.org 559 :UBC 0 : err = _("grouping operations are not allowed in column generation expressions");
560 : :
2352 peter@eisentraut.org 561 :CBC 6 : break;
562 : :
2765 tgl@sss.pgh.pa.us 563 :UBC 0 : case EXPR_KIND_CALL_ARGUMENT:
2837 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 : :
2422 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
2422 tomas.vondra@postgre 575 :UBC 0 : err = _("grouping operations are not allowed in COPY FROM WHERE conditions");
576 : :
2422 tomas.vondra@postgre 577 :CBC 3 : break;
578 : :
1678 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 : :
4775 tgl@sss.pgh.pa.us 592 [ + + ]:CBC 21119 : if (err)
6096 593 [ + - ]: 36 : ereport(ERROR,
594 : : (errcode(ERRCODE_GROUPING_ERROR),
595 : : errmsg_internal("%s", err),
596 : : parser_errposition(pstate, location)));
597 : :
4775 598 [ + + ]: 21083 : if (errkind)
599 : : {
3766 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 */
3766 andres@anarazel.de 605 :UBC 0 : err = _("grouping operations are not allowed in %s");
606 : :
4775 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 : 21071 : }
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
4275 641 : 21143 : 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 : :
4775 649 : 21143 : context.pstate = pstate;
650 : 21143 : context.min_varlevel = -1; /* signifies nothing found yet */
651 : 21143 : context.min_agglevel = -1;
652 : 21143 : context.sublevels_up = 0;
653 : :
1480 654 : 21143 : (void) check_agg_arguments_walker((Node *) args, &context);
655 : 21140 : (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 : : */
4775 661 [ + + ]: 21140 : if (context.min_varlevel < 0)
662 : : {
663 [ + - ]: 6695 : if (context.min_agglevel < 0)
4275 664 : 6695 : agglevel = 0;
665 : : else
4275 tgl@sss.pgh.pa.us 666 :UBC 0 : agglevel = context.min_agglevel;
667 : : }
4775 tgl@sss.pgh.pa.us 668 [ + + ]:CBC 14445 : else if (context.min_agglevel < 0)
669 : 14427 : 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 [ + + ]: 21140 : if (agglevel == context.min_agglevel)
677 : : {
678 : : int aggloc;
679 : :
4275 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);
4778 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 : : */
4275 698 [ + + ]: 21125 : if (directargs)
699 : : {
700 : 156 : context.min_varlevel = -1;
701 : 156 : context.min_agglevel = -1;
1480 702 : 156 : (void) check_agg_arguments_walker((Node *) directargs, &context);
4275 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 : : }
4775 718 : 21119 : return agglevel;
719 : : }
720 : :
721 : : static bool
722 : 88562 : check_agg_arguments_walker(Node *node,
723 : : check_agg_arguments_context *context)
724 : : {
725 [ + + ]: 88562 : if (node == NULL)
726 : 27883 : return false;
727 [ + + ]: 60679 : if (IsA(node, Var))
728 : : {
729 : 16271 : int varlevelsup = ((Var *) node)->varlevelsup;
730 : :
731 : : /* convert levelsup to frame of reference of original query */
732 : 16271 : varlevelsup -= context->sublevels_up;
733 : : /* ignore local vars of subqueries */
734 [ + + ]: 16271 : if (varlevelsup >= 0)
735 : : {
736 [ + + ]: 16206 : if (context->min_varlevel < 0 ||
737 [ + + ]: 1731 : context->min_varlevel > varlevelsup)
738 : 14526 : context->min_varlevel = varlevelsup;
739 : : }
740 : 16271 : return false;
741 : : }
742 [ + + ]: 44408 : 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 ||
4775 tgl@sss.pgh.pa.us 752 [ # # ]:UBC 0 : context->min_agglevel > agglevelsup)
4775 tgl@sss.pgh.pa.us 753 :CBC 21 : context->min_agglevel = agglevelsup;
754 : : }
755 : : /* Continue and descend into subtree */
756 : : }
3766 andres@anarazel.de 757 [ - + ]: 44408 : if (IsA(node, GroupingFunc))
758 : : {
3766 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 : : */
2993 tgl@sss.pgh.pa.us 778 [ + + ]:CBC 44408 : if (context->sublevels_up == 0)
779 : : {
1939 780 [ + + + + ]: 44046 : if ((IsA(node, FuncExpr) && ((FuncExpr *) node)->funcretset) ||
781 [ + + - + ]: 44043 : (IsA(node, OpExpr) && ((OpExpr *) node)->opretset))
2993 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 [ - + ]: 44043 : if (IsA(node, WindowFunc))
2993 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 : : }
4775 tgl@sss.pgh.pa.us 794 [ + + ]:CBC 44405 : if (IsA(node, Query))
795 : : {
796 : : /* Recurse into subselects */
797 : : bool result;
798 : :
799 : 60 : context->sublevels_up++;
800 : 60 : result = query_tree_walker((Query *) node,
801 : : check_agg_arguments_walker,
802 : : context,
803 : : 0);
804 : 60 : context->sublevels_up--;
805 : 60 : return result;
806 : : }
807 : :
808 : 44345 : return expression_tree_walker(node,
809 : : check_agg_arguments_walker,
810 : : context);
811 : : }
812 : :
813 : : /*
814 : : * transformWindowFuncCall -
815 : : * Finish initial transformation of a window function call
816 : : *
817 : : * parse_func.c has recognized the function as a window function, and has set
818 : : * up all the fields of the WindowFunc except winref. Here we must (1) add
819 : : * the WindowDef to the pstate (if not a duplicate of one already present) and
820 : : * set winref to link to it; and (2) mark p_hasWindowFuncs true in the pstate.
821 : : * Unlike aggregates, only the most closely nested pstate level need be
822 : : * considered --- there are no "outer window functions" per SQL spec.
823 : : */
824 : : void
6096 825 : 1761 : transformWindowFuncCall(ParseState *pstate, WindowFunc *wfunc,
826 : : WindowDef *windef)
827 : : {
828 : : const char *err;
829 : : bool errkind;
830 : :
831 : : /*
832 : : * A window function call can't contain another one (but aggs are OK). XXX
833 : : * is this required by spec, or just an unimplemented feature?
834 : : *
835 : : * Note: we don't need to check the filter expression here, because the
836 : : * context checks done below and in transformAggregateCall would have
837 : : * already rejected any window funcs or aggs within the filter.
838 : : */
839 [ + + - + ]: 2211 : if (pstate->p_hasWindowFuncs &&
4775 840 : 450 : contain_windowfuncs((Node *) wfunc->args))
6096 tgl@sss.pgh.pa.us 841 [ # # ]:UBC 0 : ereport(ERROR,
842 : : (errcode(ERRCODE_WINDOWING_ERROR),
843 : : errmsg("window function calls cannot be nested"),
844 : : parser_errposition(pstate,
845 : : locate_windowfunc((Node *) wfunc->args))));
846 : :
847 : : /*
848 : : * Check to see if the window function is in an invalid place within the
849 : : * query.
850 : : *
851 : : * For brevity we support two schemes for reporting an error here: set
852 : : * "err" to a custom message, or set "errkind" true if the error context
853 : : * is sufficiently identified by what ParseExprKindName will return, *and*
854 : : * what it will return is just a SQL keyword. (Otherwise, use a custom
855 : : * message to avoid creating translation problems.)
856 : : */
4775 tgl@sss.pgh.pa.us 857 :CBC 1761 : err = NULL;
858 : 1761 : errkind = false;
859 [ - - + - : 1761 : switch (pstate->p_expr_kind)
- + - - -
+ + - - -
+ - - + -
- - - - -
- - - - +
- + + -
- ]
860 : : {
4775 tgl@sss.pgh.pa.us 861 :UBC 0 : case EXPR_KIND_NONE:
862 : 0 : Assert(false); /* can't happen */
863 : : break;
864 : 0 : case EXPR_KIND_OTHER:
865 : : /* Accept window func here; caller must throw error if wanted */
866 : 0 : break;
4775 tgl@sss.pgh.pa.us 867 :CBC 3 : case EXPR_KIND_JOIN_ON:
868 : : case EXPR_KIND_JOIN_USING:
869 : 3 : err = _("window functions are not allowed in JOIN conditions");
870 : 3 : break;
4775 tgl@sss.pgh.pa.us 871 :UBC 0 : case EXPR_KIND_FROM_SUBSELECT:
872 : : /* can't get here, but just in case, throw an error */
873 : 0 : errkind = true;
874 : 0 : break;
875 : 0 : case EXPR_KIND_FROM_FUNCTION:
876 : 0 : err = _("window functions are not allowed in functions in FROM");
877 : 0 : break;
4775 tgl@sss.pgh.pa.us 878 :CBC 6 : case EXPR_KIND_WHERE:
879 : 6 : errkind = true;
880 : 6 : break;
3692 mail@joeconway.com 881 :UBC 0 : case EXPR_KIND_POLICY:
882 : 0 : err = _("window functions are not allowed in policy expressions");
883 : 0 : break;
4775 tgl@sss.pgh.pa.us 884 : 0 : case EXPR_KIND_HAVING:
885 : 0 : errkind = true;
886 : 0 : break;
4435 noah@leadboat.com 887 : 0 : case EXPR_KIND_FILTER:
888 : 0 : errkind = true;
889 : 0 : break;
4775 tgl@sss.pgh.pa.us 890 :CBC 3 : case EXPR_KIND_WINDOW_PARTITION:
891 : : case EXPR_KIND_WINDOW_ORDER:
892 : : case EXPR_KIND_WINDOW_FRAME_RANGE:
893 : : case EXPR_KIND_WINDOW_FRAME_ROWS:
894 : : case EXPR_KIND_WINDOW_FRAME_GROUPS:
895 : 3 : err = _("window functions are not allowed in window definitions");
896 : 3 : break;
897 : 1730 : case EXPR_KIND_SELECT_TARGET:
898 : : /* okay */
899 : 1730 : break;
4775 tgl@sss.pgh.pa.us 900 :UBC 0 : case EXPR_KIND_INSERT_TARGET:
901 : : case EXPR_KIND_UPDATE_SOURCE:
902 : : case EXPR_KIND_UPDATE_TARGET:
903 : 0 : errkind = true;
904 : 0 : break;
1258 alvherre@alvh.no-ip. 905 : 0 : case EXPR_KIND_MERGE_WHEN:
906 : 0 : err = _("window functions are not allowed in MERGE WHEN conditions");
907 : 0 : break;
4775 tgl@sss.pgh.pa.us 908 : 0 : case EXPR_KIND_GROUP_BY:
909 : 0 : errkind = true;
910 : 0 : break;
4775 tgl@sss.pgh.pa.us 911 :CBC 4 : case EXPR_KIND_ORDER_BY:
912 : : /* okay */
913 : 4 : break;
4775 tgl@sss.pgh.pa.us 914 :UBC 0 : case EXPR_KIND_DISTINCT_ON:
915 : : /* okay */
916 : 0 : break;
917 : 0 : case EXPR_KIND_LIMIT:
918 : : case EXPR_KIND_OFFSET:
919 : 0 : errkind = true;
920 : 0 : break;
4775 tgl@sss.pgh.pa.us 921 :CBC 3 : case EXPR_KIND_RETURNING:
922 : : case EXPR_KIND_MERGE_RETURNING:
923 : 3 : errkind = true;
924 : 3 : break;
4775 tgl@sss.pgh.pa.us 925 :UBC 0 : case EXPR_KIND_VALUES:
926 : : case EXPR_KIND_VALUES_SINGLE:
927 : 0 : errkind = true;
928 : 0 : break;
929 : 0 : case EXPR_KIND_CHECK_CONSTRAINT:
930 : : case EXPR_KIND_DOMAIN_CHECK:
4627 peter_e@gmx.net 931 : 0 : err = _("window functions are not allowed in check constraints");
4775 tgl@sss.pgh.pa.us 932 : 0 : break;
933 : 0 : case EXPR_KIND_COLUMN_DEFAULT:
934 : : case EXPR_KIND_FUNCTION_DEFAULT:
935 : 0 : err = _("window functions are not allowed in DEFAULT expressions");
936 : 0 : break;
937 : 0 : case EXPR_KIND_INDEX_EXPRESSION:
938 : 0 : err = _("window functions are not allowed in index expressions");
939 : 0 : break;
1625 tomas.vondra@postgre 940 : 0 : case EXPR_KIND_STATS_EXPRESSION:
941 : 0 : err = _("window functions are not allowed in statistics expressions");
942 : 0 : break;
4775 tgl@sss.pgh.pa.us 943 : 0 : case EXPR_KIND_INDEX_PREDICATE:
944 : 0 : err = _("window functions are not allowed in index predicates");
945 : 0 : break;
946 : 0 : case EXPR_KIND_ALTER_COL_TRANSFORM:
947 : 0 : err = _("window functions are not allowed in transform expressions");
948 : 0 : break;
949 : 0 : case EXPR_KIND_EXECUTE_PARAMETER:
950 : 0 : err = _("window functions are not allowed in EXECUTE parameters");
951 : 0 : break;
952 : 0 : case EXPR_KIND_TRIGGER_WHEN:
953 : 0 : err = _("window functions are not allowed in trigger WHEN conditions");
954 : 0 : break;
2416 peter@eisentraut.org 955 : 0 : case EXPR_KIND_PARTITION_BOUND:
956 : 0 : err = _("window functions are not allowed in partition bound");
957 : 0 : break;
3195 rhaas@postgresql.org 958 :CBC 3 : case EXPR_KIND_PARTITION_EXPRESSION:
2765 tgl@sss.pgh.pa.us 959 : 3 : err = _("window functions are not allowed in partition key expressions");
3195 rhaas@postgresql.org 960 : 3 : break;
2765 tgl@sss.pgh.pa.us 961 :UBC 0 : case EXPR_KIND_CALL_ARGUMENT:
2837 peter_e@gmx.net 962 : 0 : err = _("window functions are not allowed in CALL arguments");
963 : 0 : break;
2422 tomas.vondra@postgre 964 :CBC 3 : case EXPR_KIND_COPY_WHERE:
965 : 3 : err = _("window functions are not allowed in COPY FROM WHERE conditions");
966 : 3 : break;
2352 peter@eisentraut.org 967 : 6 : case EXPR_KIND_GENERATED_COLUMN:
968 : 6 : err = _("window functions are not allowed in column generation expressions");
969 : 6 : break;
1678 peter@eisentraut.org 970 :UBC 0 : case EXPR_KIND_CYCLE_MARK:
971 : 0 : errkind = true;
972 : 0 : break;
973 : :
974 : : /*
975 : : * There is intentionally no default: case here, so that the
976 : : * compiler will warn if we add a new ParseExprKind without
977 : : * extending this switch. If we do see an unrecognized value at
978 : : * runtime, the behavior will be the same as for EXPR_KIND_OTHER,
979 : : * which is sane anyway.
980 : : */
981 : : }
4775 tgl@sss.pgh.pa.us 982 [ + + ]:CBC 1761 : if (err)
983 [ + - ]: 18 : ereport(ERROR,
984 : : (errcode(ERRCODE_WINDOWING_ERROR),
985 : : errmsg_internal("%s", err),
986 : : parser_errposition(pstate, wfunc->location)));
987 [ + + ]: 1743 : if (errkind)
988 [ + - ]: 9 : ereport(ERROR,
989 : : (errcode(ERRCODE_WINDOWING_ERROR),
990 : : /* translator: %s is name of a SQL construct, eg GROUP BY */
991 : : errmsg("window functions are not allowed in %s",
992 : : ParseExprKindName(pstate->p_expr_kind)),
993 : : parser_errposition(pstate, wfunc->location)));
994 : :
995 : : /*
996 : : * If the OVER clause just specifies a window name, find that WINDOW
997 : : * clause (which had better be present). Otherwise, try to match all the
998 : : * properties of the OVER clause, and make a new entry in the p_windowdefs
999 : : * list if no luck.
1000 : : */
6093 1001 [ + + ]: 1734 : if (windef->name)
1002 : : {
6096 1003 : 477 : Index winref = 0;
1004 : : ListCell *lc;
1005 : :
6093 1006 [ + - + - : 477 : Assert(windef->refname == NULL &&
+ - - + ]
1007 : : windef->partitionClause == NIL &&
1008 : : windef->orderClause == NIL &&
1009 : : windef->frameOptions == FRAMEOPTION_DEFAULTS);
1010 : :
6096 1011 [ + - + - : 480 : foreach(lc, pstate->p_windowdefs)
+ - ]
1012 : : {
5931 bruce@momjian.us 1013 : 480 : WindowDef *refwin = (WindowDef *) lfirst(lc);
1014 : :
6096 tgl@sss.pgh.pa.us 1015 : 480 : winref++;
6093 1016 [ + - + + ]: 480 : if (refwin->name && strcmp(refwin->name, windef->name) == 0)
1017 : : {
6096 1018 : 477 : wfunc->winref = winref;
1019 : 477 : break;
1020 : : }
1021 : : }
1022 [ - + ]: 477 : if (lc == NULL) /* didn't find it? */
6096 tgl@sss.pgh.pa.us 1023 [ # # ]:UBC 0 : ereport(ERROR,
1024 : : (errcode(ERRCODE_UNDEFINED_OBJECT),
1025 : : errmsg("window \"%s\" does not exist", windef->name),
1026 : : parser_errposition(pstate, windef->location)));
1027 : : }
1028 : : else
1029 : : {
6096 tgl@sss.pgh.pa.us 1030 :CBC 1257 : Index winref = 0;
1031 : : ListCell *lc;
1032 : :
1033 [ + + + + : 1437 : foreach(lc, pstate->p_windowdefs)
+ + ]
1034 : : {
5931 bruce@momjian.us 1035 : 306 : WindowDef *refwin = (WindowDef *) lfirst(lc);
1036 : :
6096 tgl@sss.pgh.pa.us 1037 : 306 : winref++;
1038 [ + + + - ]: 312 : if (refwin->refname && windef->refname &&
6093 1039 [ + - ]: 6 : strcmp(refwin->refname, windef->refname) == 0)
1040 : : /* matched on refname */ ;
6096 1041 [ + - + + ]: 300 : else if (!refwin->refname && !windef->refname)
1042 : : /* matched, no refname */ ;
1043 : : else
1044 : 24 : continue;
1045 : :
1046 : : /*
1047 : : * Also see similar de-duplication code in optimize_window_clauses
1048 : : */
1049 [ + + + + ]: 519 : if (equal(refwin->partitionClause, windef->partitionClause) &&
6093 1050 : 237 : equal(refwin->orderClause, windef->orderClause) &&
5685 1051 [ + + + - ]: 333 : refwin->frameOptions == windef->frameOptions &&
1052 [ + - ]: 252 : equal(refwin->startOffset, windef->startOffset) &&
1053 : 126 : equal(refwin->endOffset, windef->endOffset))
1054 : : {
1055 : : /* found a duplicate window specification */
6096 1056 : 126 : wfunc->winref = winref;
1057 : 126 : break;
1058 : : }
1059 : : }
1060 [ + + ]: 1257 : if (lc == NULL) /* didn't find it? */
1061 : : {
1062 : 1131 : pstate->p_windowdefs = lappend(pstate->p_windowdefs, windef);
1063 : 1131 : wfunc->winref = list_length(pstate->p_windowdefs);
1064 : : }
1065 : : }
1066 : :
1067 : 1734 : pstate->p_hasWindowFuncs = true;
1068 : 1734 : }
1069 : :
1070 : : /*
1071 : : * parseCheckAggregates
1072 : : * Check for aggregates where they shouldn't be and improper grouping, and
1073 : : * replace grouped variables in the targetlist and HAVING clause with Vars
1074 : : * that reference the RTE_GROUP RTE.
1075 : : * This function should be called after the target list and qualifications
1076 : : * are finalized.
1077 : : *
1078 : : * Misplaced aggregates are now mostly detected in transformAggregateCall,
1079 : : * but it seems more robust to check for aggregates in recursive queries
1080 : : * only after everything is finalized. In any case it's hard to detect
1081 : : * improper grouping on-the-fly, so we have to make another pass over the
1082 : : * query for that.
1083 : : */
1084 : : void
8128 1085 : 18469 : parseCheckAggregates(ParseState *pstate, Query *qry)
1086 : : {
3759 bruce@momjian.us 1087 : 18469 : List *gset_common = NIL;
8128 tgl@sss.pgh.pa.us 1088 : 18469 : List *groupClauses = NIL;
3766 andres@anarazel.de 1089 : 18469 : List *groupClauseCommonVars = NIL;
1090 : : bool have_non_var_grouping;
5509 tgl@sss.pgh.pa.us 1091 : 18469 : List *func_grouped_rels = NIL;
1092 : : ListCell *l;
1093 : : bool hasJoinRTEs;
1094 : : bool hasSelfRefRTEs;
1095 : : Node *clause;
1096 : :
1097 : : /* This should only be called if we found aggregates or grouping */
3766 andres@anarazel.de 1098 [ + + + + : 18469 : Assert(pstate->p_hasAggs || qry->groupClause || qry->havingQual || qry->groupingSets);
- + - - ]
1099 : :
1100 : : /*
1101 : : * If we have grouping sets, expand them and find the intersection of all
1102 : : * sets.
1103 : : */
1104 [ + + ]: 18469 : if (qry->groupingSets)
1105 : : {
1106 : : /*
1107 : : * The limit of 4096 is arbitrary and exists simply to avoid resource
1108 : : * issues from pathological constructs.
1109 : : */
1633 tomas.vondra@postgre 1110 : 454 : List *gsets = expand_grouping_sets(qry->groupingSets, qry->groupDistinct, 4096);
1111 : :
3766 andres@anarazel.de 1112 [ - + ]: 454 : if (!gsets)
3766 andres@anarazel.de 1113 [ # # # # ]:UBC 0 : ereport(ERROR,
1114 : : (errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
1115 : : errmsg("too many grouping sets present (maximum 4096)"),
1116 : : parser_errposition(pstate,
1117 : : qry->groupClause
1118 : : ? exprLocation((Node *) qry->groupClause)
1119 : : : exprLocation((Node *) qry->groupingSets))));
1120 : :
1121 : : /*
1122 : : * The intersection will often be empty, so help things along by
1123 : : * seeding the intersect with the smallest set.
1124 : : */
3766 andres@anarazel.de 1125 :CBC 454 : gset_common = linitial(gsets);
1126 : :
1127 [ + + ]: 454 : if (gset_common)
1128 : : {
1804 tgl@sss.pgh.pa.us 1129 [ + - + + : 302 : for_each_from(l, gsets, 1)
+ + ]
1130 : : {
3766 andres@anarazel.de 1131 : 203 : gset_common = list_intersection_int(gset_common, lfirst(l));
1132 [ + + ]: 203 : if (!gset_common)
1133 : 92 : break;
1134 : : }
1135 : : }
1136 : :
1137 : : /*
1138 : : * If there was only one grouping set in the expansion, AND if the
1139 : : * groupClause is non-empty (meaning that the grouping set is not
1140 : : * empty either), then we can ditch the grouping set and pretend we
1141 : : * just had a normal GROUP BY.
1142 : : */
1143 [ + + + + ]: 454 : if (list_length(gsets) == 1 && qry->groupClause)
1144 : 12 : qry->groupingSets = NIL;
1145 : : }
1146 : :
1147 : : /*
1148 : : * Scan the range table to see if there are JOIN or self-reference CTE
1149 : : * entries. We'll need this info below.
1150 : : */
6181 tgl@sss.pgh.pa.us 1151 : 18469 : hasJoinRTEs = hasSelfRefRTEs = false;
1152 [ + + + + : 40729 : foreach(l, pstate->p_rtable)
+ + ]
1153 : : {
1154 : 22260 : RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
1155 : :
1156 [ + + ]: 22260 : if (rte->rtekind == RTE_JOIN)
1157 : 975 : hasJoinRTEs = true;
1158 [ + + + + ]: 21285 : else if (rte->rtekind == RTE_CTE && rte->self_reference)
1159 : 6 : hasSelfRefRTEs = true;
1160 : : }
1161 : :
1162 : : /*
1163 : : * Build a list of the acceptable GROUP BY expressions for use by
1164 : : * substitute_grouped_columns().
1165 : : *
1166 : : * We get the TLE, not just the expr, because GROUPING wants to know the
1167 : : * sortgroupref.
1168 : : */
7773 neilc@samurai.com 1169 [ + + + + : 22348 : foreach(l, qry->groupClause)
+ + ]
1170 : : {
6244 tgl@sss.pgh.pa.us 1171 : 3879 : SortGroupClause *grpcl = (SortGroupClause *) lfirst(l);
1172 : : TargetEntry *expr;
1173 : :
3766 andres@anarazel.de 1174 : 3879 : expr = get_sortgroupclause_tle(grpcl, qry->targetList);
8128 tgl@sss.pgh.pa.us 1175 [ - + ]: 3879 : if (expr == NULL)
8128 tgl@sss.pgh.pa.us 1176 :UBC 0 : continue; /* probably cannot happen */
1177 : :
2243 tgl@sss.pgh.pa.us 1178 :CBC 3879 : groupClauses = lappend(groupClauses, expr);
1179 : : }
1180 : :
1181 : : /*
1182 : : * If there are join alias vars involved, we have to flatten them to the
1183 : : * underlying vars, so that aliased and unaliased vars will be correctly
1184 : : * taken as equal. We can skip the expense of doing this if no rangetable
1185 : : * entries are RTE_JOIN kind.
1186 : : */
8128 1187 [ + + ]: 18469 : if (hasJoinRTEs)
950 1188 : 810 : groupClauses = (List *) flatten_join_alias_vars(NULL, qry,
1189 : : (Node *) groupClauses);
1190 : :
1191 : : /*
1192 : : * Detect whether any of the grouping expressions aren't simple Vars; if
1193 : : * they're all Vars then we don't have to work so hard in the recursive
1194 : : * scans. (Note we have to flatten aliases before this.)
1195 : : *
1196 : : * Track Vars that are included in all grouping sets separately in
1197 : : * groupClauseCommonVars, since these are the only ones we can use to
1198 : : * check for functional dependencies.
1199 : : */
7892 1200 : 18469 : have_non_var_grouping = false;
7773 neilc@samurai.com 1201 [ + + + + : 22348 : foreach(l, groupClauses)
+ + ]
1202 : : {
3766 andres@anarazel.de 1203 : 3879 : TargetEntry *tle = lfirst(l);
1204 : :
1205 [ + + ]: 3879 : if (!IsA(tle->expr, Var))
1206 : : {
7892 tgl@sss.pgh.pa.us 1207 : 697 : have_non_var_grouping = true;
1208 : : }
3766 andres@anarazel.de 1209 [ + + + + ]: 4004 : else if (!qry->groupingSets ||
1210 : 822 : list_member_int(gset_common, tle->ressortgroupref))
1211 : : {
1212 : 2447 : groupClauseCommonVars = lappend(groupClauseCommonVars, tle->expr);
1213 : : }
1214 : : }
1215 : :
1216 : : /*
1217 : : * If there are any acceptable GROUP BY expressions, build an RTE and
1218 : : * nsitem for the result of the grouping step.
1219 : : */
361 rguo@postgresql.org 1220 [ + + ]: 18469 : if (groupClauses)
1221 : : {
1222 : 2237 : pstate->p_grouping_nsitem =
1223 : 2237 : addRangeTableEntryForGroup(pstate, groupClauses);
1224 : :
1225 : : /* Set qry->rtable again in case it was previously NIL */
1226 : 2237 : qry->rtable = pstate->p_rtable;
1227 : : /* Mark the Query as having RTE_GROUP RTE */
1228 : 2237 : qry->hasGroupRTE = true;
1229 : : }
1230 : :
1231 : : /*
1232 : : * Replace grouped variables in the targetlist and HAVING clause with Vars
1233 : : * that reference the RTE_GROUP RTE. Emit an error message if we find any
1234 : : * ungrouped variables.
1235 : : *
1236 : : * Note: because we check resjunk tlist elements as well as regular ones,
1237 : : * this will also find ungrouped variables that came from ORDER BY and
1238 : : * WINDOW clauses. For that matter, it's also going to examine the
1239 : : * grouping expressions themselves --- but they'll all pass the test ...
1240 : : *
1241 : : * We also finalize GROUPING expressions, but for that we need to traverse
1242 : : * the original (unflattened) clause in order to modify nodes.
1243 : : */
8128 tgl@sss.pgh.pa.us 1244 : 18469 : clause = (Node *) qry->targetList;
3766 andres@anarazel.de 1245 : 18469 : finalize_grouping_exprs(clause, pstate, qry,
1246 : : groupClauses, hasJoinRTEs,
1247 : : have_non_var_grouping);
8128 tgl@sss.pgh.pa.us 1248 [ + + ]: 18466 : if (hasJoinRTEs)
950 1249 : 810 : clause = flatten_join_alias_vars(NULL, qry, clause);
361 rguo@postgresql.org 1250 : 18424 : qry->targetList = (List *)
1251 : 18466 : substitute_grouped_columns(clause, pstate, qry,
1252 : : groupClauses, groupClauseCommonVars,
1253 : : gset_common,
1254 : : have_non_var_grouping,
1255 : : &func_grouped_rels);
1256 : :
8128 tgl@sss.pgh.pa.us 1257 : 18424 : clause = (Node *) qry->havingQual;
3766 andres@anarazel.de 1258 : 18424 : finalize_grouping_exprs(clause, pstate, qry,
1259 : : groupClauses, hasJoinRTEs,
1260 : : have_non_var_grouping);
8128 tgl@sss.pgh.pa.us 1261 [ + + ]: 18424 : if (hasJoinRTEs)
950 1262 : 798 : clause = flatten_join_alias_vars(NULL, qry, clause);
361 rguo@postgresql.org 1263 : 18421 : qry->havingQual =
1264 : 18424 : substitute_grouped_columns(clause, pstate, qry,
1265 : : groupClauses, groupClauseCommonVars,
1266 : : gset_common,
1267 : : have_non_var_grouping,
1268 : : &func_grouped_rels);
1269 : :
1270 : : /*
1271 : : * Per spec, aggregates can't appear in a recursive term.
1272 : : */
6181 tgl@sss.pgh.pa.us 1273 [ + + + + ]: 18421 : if (pstate->p_hasAggs && hasSelfRefRTEs)
1274 [ + - ]: 6 : ereport(ERROR,
1275 : : (errcode(ERRCODE_INVALID_RECURSION),
1276 : : errmsg("aggregate functions are not allowed in a recursive query's recursive term"),
1277 : : parser_errposition(pstate,
1278 : : locate_agg_of_level((Node *) qry, 0))));
8128 1279 : 18415 : }
1280 : :
1281 : : /*
1282 : : * substitute_grouped_columns -
1283 : : * Scan the given expression tree for grouped variables (variables that
1284 : : * are listed in the groupClauses list) and replace them with Vars that
1285 : : * reference the RTE_GROUP RTE. Emit a suitable error message if any
1286 : : * ungrouped variables (variables that are not listed in the groupClauses
1287 : : * list and are not within the arguments of aggregate functions) are
1288 : : * found.
1289 : : *
1290 : : * NOTE: we assume that the given clause has been transformed suitably for
1291 : : * parser output. This means we can use expression_tree_mutator.
1292 : : *
1293 : : * NOTE: we recognize grouping expressions in the main query, but only
1294 : : * grouping Vars in subqueries. For example, this will be rejected,
1295 : : * although it could be allowed:
1296 : : * SELECT
1297 : : * (SELECT x FROM bar where y = (foo.a + foo.b))
1298 : : * FROM foo
1299 : : * GROUP BY a + b;
1300 : : * The difficulty is the need to account for different sublevels_up.
1301 : : * This appears to require a whole custom version of equal(), which is
1302 : : * way more pain than the feature seems worth.
1303 : : */
1304 : : static Node *
361 rguo@postgresql.org 1305 : 36890 : substitute_grouped_columns(Node *node, ParseState *pstate, Query *qry,
1306 : : List *groupClauses, List *groupClauseCommonVars,
1307 : : List *gset_common,
1308 : : bool have_non_var_grouping,
1309 : : List **func_grouped_rels)
1310 : : {
1311 : : substitute_grouped_columns_context context;
1312 : :
9403 tgl@sss.pgh.pa.us 1313 : 36890 : context.pstate = pstate;
5509 1314 : 36890 : context.qry = qry;
2412 1315 : 36890 : context.hasJoinRTEs = false; /* assume caller flattened join Vars */
9403 1316 : 36890 : context.groupClauses = groupClauses;
3766 andres@anarazel.de 1317 : 36890 : context.groupClauseCommonVars = groupClauseCommonVars;
361 rguo@postgresql.org 1318 : 36890 : context.gset_common = gset_common;
8268 tgl@sss.pgh.pa.us 1319 : 36890 : context.have_non_var_grouping = have_non_var_grouping;
5509 1320 : 36890 : context.func_grouped_rels = func_grouped_rels;
8268 1321 : 36890 : context.sublevels_up = 0;
4275 1322 : 36890 : context.in_agg_direct_args = false;
361 rguo@postgresql.org 1323 : 36890 : return substitute_grouped_columns_mutator(node, &context);
1324 : : }
1325 : :
1326 : : static Node *
1327 : 130422 : substitute_grouped_columns_mutator(Node *node,
1328 : : substitute_grouped_columns_context *context)
1329 : : {
1330 : : ListCell *gl;
1331 : :
9576 tgl@sss.pgh.pa.us 1332 [ + + ]: 130422 : if (node == NULL)
361 rguo@postgresql.org 1333 : 41962 : return NULL;
1334 : :
4275 tgl@sss.pgh.pa.us 1335 [ + + ]: 88460 : if (IsA(node, Aggref))
1336 : : {
1337 : 21273 : Aggref *agg = (Aggref *) node;
1338 : :
1339 [ + + ]: 21273 : if ((int) agg->agglevelsup == context->sublevels_up)
1340 : : {
1341 : : /*
1342 : : * If we find an aggregate call of the original level, do not
1343 : : * recurse into its normal arguments, ORDER BY arguments, or
1344 : : * filter; grouped vars there do not need to be replaced and
1345 : : * ungrouped vars there are not an error. But we should check
1346 : : * direct arguments as though they weren't in an aggregate. We
1347 : : * set a special flag in the context to help produce a useful
1348 : : * error message for ungrouped vars in direct arguments.
1349 : : */
361 rguo@postgresql.org 1350 : 21270 : agg = copyObject(agg);
1351 : :
4275 tgl@sss.pgh.pa.us 1352 [ - + ]: 21270 : Assert(!context->in_agg_direct_args);
1353 : 21270 : context->in_agg_direct_args = true;
361 rguo@postgresql.org 1354 : 21267 : agg->aggdirectargs = (List *)
1355 : 21270 : substitute_grouped_columns_mutator((Node *) agg->aggdirectargs,
1356 : : context);
4275 tgl@sss.pgh.pa.us 1357 : 21267 : context->in_agg_direct_args = false;
361 rguo@postgresql.org 1358 : 21267 : return (Node *) agg;
1359 : : }
1360 : :
1361 : : /*
1362 : : * We can skip recursing into aggregates of higher levels altogether,
1363 : : * since they could not possibly contain Vars of concern to us (see
1364 : : * transformAggregateCall). We do need to look at aggregates of lower
1365 : : * levels, however.
1366 : : */
4275 tgl@sss.pgh.pa.us 1367 [ - + ]: 3 : if ((int) agg->agglevelsup > context->sublevels_up)
361 rguo@postgresql.org 1368 :UBC 0 : return node;
1369 : : }
1370 : :
3766 andres@anarazel.de 1371 [ + + ]:CBC 67190 : if (IsA(node, GroupingFunc))
1372 : : {
1373 : 198 : GroupingFunc *grp = (GroupingFunc *) node;
1374 : :
1375 : : /* handled GroupingFunc separately, no need to recheck at this level */
1376 : :
1377 [ + + ]: 198 : if ((int) grp->agglevelsup >= context->sublevels_up)
361 rguo@postgresql.org 1378 : 182 : return node;
1379 : : }
1380 : :
1381 : : /*
1382 : : * If we have any GROUP BY items that are not simple Vars, check to see if
1383 : : * subexpression as a whole matches any GROUP BY item. We need to do this
1384 : : * at every recursion level so that we recognize GROUPed-BY expressions
1385 : : * before reaching variables within them. But this only works at the outer
1386 : : * query level, as noted above.
1387 : : */
8268 tgl@sss.pgh.pa.us 1388 [ + + + + ]: 67008 : if (context->have_non_var_grouping && context->sublevels_up == 0)
1389 : : {
361 rguo@postgresql.org 1390 : 3838 : int attnum = 0;
1391 : :
8268 tgl@sss.pgh.pa.us 1392 [ + - + + : 10456 : foreach(gl, context->groupClauses)
+ + ]
1393 : : {
361 rguo@postgresql.org 1394 : 7702 : TargetEntry *tle = (TargetEntry *) lfirst(gl);
1395 : :
1396 : 7702 : attnum++;
3766 andres@anarazel.de 1397 [ + + ]: 7702 : if (equal(node, tle->expr))
1398 : : {
1399 : : /* acceptable, replace it with a GROUP Var */
361 rguo@postgresql.org 1400 : 1084 : return (Node *) buildGroupedVar(attnum,
1401 : : tle->ressortgroupref,
1402 : : context);
1403 : : }
1404 : : }
1405 : : }
1406 : :
1407 : : /*
1408 : : * Constants are always acceptable. We have to do this after we checked
1409 : : * the subexpression as a whole for a match, because it is possible that
1410 : : * we have GROUP BY items that are constants, and the constants would
1411 : : * become not so constant after the grouping step.
1412 : : */
1413 [ + + ]: 65924 : if (IsA(node, Const) ||
1414 [ + + ]: 63778 : IsA(node, Param))
1415 : 2238 : return node;
1416 : :
1417 : : /*
1418 : : * If we have an ungrouped Var of the original query level, we have a
1419 : : * failure. Vars below the original query level are not a problem, and
1420 : : * neither are Vars from above it. (If such Vars are ungrouped as far as
1421 : : * their own query level is concerned, that's someone else's problem...)
1422 : : */
9576 tgl@sss.pgh.pa.us 1423 [ + + ]: 63686 : if (IsA(node, Var))
1424 : : {
9278 bruce@momjian.us 1425 : 4991 : Var *var = (Var *) node;
1426 : : RangeTblEntry *rte;
1427 : : char *attname;
1428 : :
8268 tgl@sss.pgh.pa.us 1429 [ + + ]: 4991 : if (var->varlevelsup != context->sublevels_up)
361 rguo@postgresql.org 1430 : 216 : return node; /* it's not local to my query, ignore */
1431 : :
1432 : : /*
1433 : : * Check for a match, if we didn't do it above.
1434 : : */
8268 tgl@sss.pgh.pa.us 1435 [ + + - + ]: 4775 : if (!context->have_non_var_grouping || context->sublevels_up != 0)
1436 : : {
361 rguo@postgresql.org 1437 : 4772 : int attnum = 0;
1438 : :
8268 tgl@sss.pgh.pa.us 1439 [ + + + + : 6724 : foreach(gl, context->groupClauses)
+ + ]
1440 : : {
361 rguo@postgresql.org 1441 : 6552 : TargetEntry *tle = (TargetEntry *) lfirst(gl);
1442 : 6552 : Var *gvar = (Var *) tle->expr;
1443 : :
1444 : 6552 : attnum++;
8268 tgl@sss.pgh.pa.us 1445 [ + - ]: 6552 : if (IsA(gvar, Var) &&
1446 [ + + ]: 6552 : gvar->varno == var->varno &&
1447 [ + + ]: 6189 : gvar->varattno == var->varattno &&
1448 [ + - ]: 4600 : gvar->varlevelsup == 0)
1449 : : {
1450 : : /* acceptable, replace it with a GROUP Var */
361 rguo@postgresql.org 1451 : 4600 : return (Node *) buildGroupedVar(attnum,
1452 : : tle->ressortgroupref,
1453 : : context);
1454 : : }
1455 : : }
1456 : : }
1457 : :
1458 : : /*
1459 : : * Check whether the Var is known functionally dependent on the GROUP
1460 : : * BY columns. If so, we can allow the Var to be used, because the
1461 : : * grouping is really a no-op for this table. However, this deduction
1462 : : * depends on one or more constraints of the table, so we have to add
1463 : : * those constraints to the query's constraintDeps list, because it's
1464 : : * not semantically valid anymore if the constraint(s) get dropped.
1465 : : * (Therefore, this check must be the last-ditch effort before raising
1466 : : * error: we don't want to add dependencies unnecessarily.)
1467 : : *
1468 : : * Because this is a pretty expensive check, and will have the same
1469 : : * outcome for all columns of a table, we remember which RTEs we've
1470 : : * already proven functional dependency for in the func_grouped_rels
1471 : : * list. This test also prevents us from adding duplicate entries to
1472 : : * the constraintDeps list.
1473 : : */
5509 tgl@sss.pgh.pa.us 1474 [ + + ]: 175 : if (list_member_int(*context->func_grouped_rels, var->varno))
361 rguo@postgresql.org 1475 : 69 : return node; /* previously proven acceptable */
1476 : :
9403 tgl@sss.pgh.pa.us 1477 [ + - - + ]: 106 : Assert(var->varno > 0 &&
1478 : : (int) var->varno <= list_length(context->pstate->p_rtable));
1479 : 106 : rte = rt_fetch(var->varno, context->pstate->p_rtable);
5509 1480 [ + + ]: 106 : if (rte->rtekind == RTE_RELATION)
1481 : : {
1482 [ + + ]: 103 : if (check_functional_grouping(rte->relid,
1483 : 103 : var->varno,
1484 : : 0,
1485 : : context->groupClauseCommonVars,
1486 : 103 : &context->qry->constraintDeps))
1487 : : {
1488 : 122 : *context->func_grouped_rels =
1489 : 61 : lappend_int(*context->func_grouped_rels, var->varno);
361 rguo@postgresql.org 1490 : 61 : return node; /* acceptable */
1491 : : }
1492 : : }
1493 : :
1494 : : /* Found an ungrouped local variable; generate error message */
9112 tgl@sss.pgh.pa.us 1495 : 45 : attname = get_rte_attribute_name(rte, var->varattno);
8268 1496 [ + - ]: 45 : if (context->sublevels_up == 0)
8085 1497 [ + - + + ]: 45 : ereport(ERROR,
1498 : : (errcode(ERRCODE_GROUPING_ERROR),
1499 : : errmsg("column \"%s.%s\" must appear in the GROUP BY clause or be used in an aggregate function",
1500 : : rte->eref->aliasname, attname),
1501 : : context->in_agg_direct_args ?
1502 : : errdetail("Direct arguments of an ordered-set aggregate must use only grouped columns.") : 0,
1503 : : parser_errposition(context->pstate, var->location)));
1504 : : else
8085 tgl@sss.pgh.pa.us 1505 [ # # ]:UBC 0 : ereport(ERROR,
1506 : : (errcode(ERRCODE_GROUPING_ERROR),
1507 : : errmsg("subquery uses ungrouped column \"%s.%s\" from outer query",
1508 : : rte->eref->aliasname, attname),
1509 : : parser_errposition(context->pstate, var->location)));
1510 : : }
1511 : :
8268 tgl@sss.pgh.pa.us 1512 [ + + ]:CBC 58695 : if (IsA(node, Query))
1513 : : {
1514 : : /* Recurse into subselects */
1515 : : Query *newnode;
1516 : :
1517 : 167 : context->sublevels_up++;
361 rguo@postgresql.org 1518 : 167 : newnode = query_tree_mutator((Query *) node,
1519 : : substitute_grouped_columns_mutator,
1520 : : context,
1521 : : 0);
8268 tgl@sss.pgh.pa.us 1522 : 167 : context->sublevels_up--;
361 rguo@postgresql.org 1523 : 167 : return (Node *) newnode;
1524 : : }
1525 : 58528 : return expression_tree_mutator(node, substitute_grouped_columns_mutator,
1526 : : context);
1527 : : }
1528 : :
1529 : : /*
1530 : : * finalize_grouping_exprs -
1531 : : * Scan the given expression tree for GROUPING() and related calls,
1532 : : * and validate and process their arguments.
1533 : : *
1534 : : * This is split out from substitute_grouped_columns above because it needs
1535 : : * to modify the nodes (which it does in-place, not via a mutator) while
1536 : : * substitute_grouped_columns may see only a copy of the original thanks to
1537 : : * flattening of join alias vars. So here, we flatten each individual
1538 : : * GROUPING argument as we see it before comparing it.
1539 : : */
1540 : : static void
3766 andres@anarazel.de 1541 : 36893 : finalize_grouping_exprs(Node *node, ParseState *pstate, Query *qry,
1542 : : List *groupClauses, bool hasJoinRTEs,
1543 : : bool have_non_var_grouping)
1544 : : {
1545 : : substitute_grouped_columns_context context;
1546 : :
1547 : 36893 : context.pstate = pstate;
1548 : 36893 : context.qry = qry;
2412 tgl@sss.pgh.pa.us 1549 : 36893 : context.hasJoinRTEs = hasJoinRTEs;
3766 andres@anarazel.de 1550 : 36893 : context.groupClauses = groupClauses;
1551 : 36893 : context.groupClauseCommonVars = NIL;
361 rguo@postgresql.org 1552 : 36893 : context.gset_common = NIL;
3766 andres@anarazel.de 1553 : 36893 : context.have_non_var_grouping = have_non_var_grouping;
1554 : 36893 : context.func_grouped_rels = NULL;
1555 : 36893 : context.sublevels_up = 0;
1556 : 36893 : context.in_agg_direct_args = false;
1557 : 36893 : finalize_grouping_exprs_walker(node, &context);
1558 : 36890 : }
1559 : :
1560 : : static bool
1561 : 127775 : finalize_grouping_exprs_walker(Node *node,
1562 : : substitute_grouped_columns_context *context)
1563 : : {
1564 : : ListCell *gl;
1565 : :
1566 [ + + ]: 127775 : if (node == NULL)
1567 : 42569 : return false;
1568 [ + + ]: 85206 : if (IsA(node, Const) ||
1569 [ + + ]: 82422 : IsA(node, Param))
1570 : 2882 : return false; /* constants are always acceptable */
1571 : :
1572 [ + + ]: 82324 : if (IsA(node, Aggref))
1573 : : {
1574 : 21276 : Aggref *agg = (Aggref *) node;
1575 : :
1576 [ + + ]: 21276 : if ((int) agg->agglevelsup == context->sublevels_up)
1577 : : {
1578 : : /*
1579 : : * If we find an aggregate call of the original level, do not
1580 : : * recurse into its normal arguments, ORDER BY arguments, or
1581 : : * filter; GROUPING exprs of this level are not allowed there. But
1582 : : * check direct arguments as though they weren't in an aggregate.
1583 : : */
1584 : : bool result;
1585 : :
1586 [ - + ]: 21273 : Assert(!context->in_agg_direct_args);
1587 : 21273 : context->in_agg_direct_args = true;
1588 : 21273 : result = finalize_grouping_exprs_walker((Node *) agg->aggdirectargs,
1589 : : context);
1590 : 21273 : context->in_agg_direct_args = false;
1591 : 21273 : return result;
1592 : : }
1593 : :
1594 : : /*
1595 : : * We can skip recursing into aggregates of higher levels altogether,
1596 : : * since they could not possibly contain exprs of concern to us (see
1597 : : * transformAggregateCall). We do need to look at aggregates of lower
1598 : : * levels, however.
1599 : : */
1600 [ - + ]: 3 : if ((int) agg->agglevelsup > context->sublevels_up)
3766 andres@anarazel.de 1601 :UBC 0 : return false;
1602 : : }
1603 : :
3766 andres@anarazel.de 1604 [ + + ]:CBC 61051 : if (IsA(node, GroupingFunc))
1605 : : {
1606 : 201 : GroupingFunc *grp = (GroupingFunc *) node;
1607 : :
1608 : : /*
1609 : : * We only need to check GroupingFunc nodes at the exact level to
1610 : : * which they belong, since they cannot mix levels in arguments.
1611 : : */
1612 : :
1613 [ + + ]: 201 : if ((int) grp->agglevelsup == context->sublevels_up)
1614 : : {
1615 : : ListCell *lc;
3759 bruce@momjian.us 1616 : 181 : List *ref_list = NIL;
1617 : :
3766 andres@anarazel.de 1618 [ + - + + : 454 : foreach(lc, grp->args)
+ + ]
1619 : : {
3759 bruce@momjian.us 1620 : 276 : Node *expr = lfirst(lc);
1621 : 276 : Index ref = 0;
1622 : :
2412 tgl@sss.pgh.pa.us 1623 [ + + ]: 276 : if (context->hasJoinRTEs)
950 1624 : 24 : expr = flatten_join_alias_vars(NULL, context->qry, expr);
1625 : :
1626 : : /*
1627 : : * Each expression must match a grouping entry at the current
1628 : : * query level. Unlike the general expression case, we don't
1629 : : * allow functional dependencies or outer references.
1630 : : */
1631 : :
3766 andres@anarazel.de 1632 [ + + ]: 276 : if (IsA(expr, Var))
1633 : : {
3759 bruce@momjian.us 1634 : 246 : Var *var = (Var *) expr;
1635 : :
3766 andres@anarazel.de 1636 [ + - ]: 246 : if (var->varlevelsup == context->sublevels_up)
1637 : : {
1638 [ + + + - : 362 : foreach(gl, context->groupClauses)
+ + ]
1639 : : {
1640 : 359 : TargetEntry *tle = lfirst(gl);
1641 : 359 : Var *gvar = (Var *) tle->expr;
1642 : :
1643 [ + - ]: 359 : if (IsA(gvar, Var) &&
1644 [ + + ]: 359 : gvar->varno == var->varno &&
1645 [ + + ]: 353 : gvar->varattno == var->varattno &&
1646 [ + - ]: 243 : gvar->varlevelsup == 0)
1647 : : {
1648 : 243 : ref = tle->ressortgroupref;
1649 : 243 : break;
1650 : : }
1651 : : }
1652 : : }
1653 : : }
1654 [ + - ]: 30 : else if (context->have_non_var_grouping &&
1655 [ + - ]: 30 : context->sublevels_up == 0)
1656 : : {
1657 [ + - + - : 60 : foreach(gl, context->groupClauses)
+ - ]
1658 : : {
1659 : 60 : TargetEntry *tle = lfirst(gl);
1660 : :
1661 [ + + ]: 60 : if (equal(expr, tle->expr))
1662 : : {
1663 : 30 : ref = tle->ressortgroupref;
1664 : 30 : break;
1665 : : }
1666 : : }
1667 : : }
1668 : :
1669 [ + + ]: 276 : if (ref == 0)
1670 [ + - ]: 3 : ereport(ERROR,
1671 : : (errcode(ERRCODE_GROUPING_ERROR),
1672 : : errmsg("arguments to GROUPING must be grouping expressions of the associated query level"),
1673 : : parser_errposition(context->pstate,
1674 : : exprLocation(expr))));
1675 : :
1676 : 273 : ref_list = lappend_int(ref_list, ref);
1677 : : }
1678 : :
1679 : 178 : grp->refs = ref_list;
1680 : : }
1681 : :
1682 [ + + ]: 198 : if ((int) grp->agglevelsup > context->sublevels_up)
1683 : 4 : return false;
1684 : : }
1685 : :
1686 [ + + ]: 61044 : if (IsA(node, Query))
1687 : : {
1688 : : /* Recurse into subselects */
1689 : : bool result;
1690 : :
1691 : 217 : context->sublevels_up++;
1692 : 217 : result = query_tree_walker((Query *) node,
1693 : : finalize_grouping_exprs_walker,
1694 : : context,
1695 : : 0);
1696 : 217 : context->sublevels_up--;
1697 : 217 : return result;
1698 : : }
1699 : 60827 : return expression_tree_walker(node, finalize_grouping_exprs_walker,
1700 : : context);
1701 : : }
1702 : :
1703 : : /*
1704 : : * buildGroupedVar -
1705 : : * build a Var node that references the RTE_GROUP RTE
1706 : : */
1707 : : static Var *
361 rguo@postgresql.org 1708 : 5684 : buildGroupedVar(int attnum, Index ressortgroupref,
1709 : : substitute_grouped_columns_context *context)
1710 : : {
1711 : : Var *var;
1712 : 5684 : ParseNamespaceItem *grouping_nsitem = context->pstate->p_grouping_nsitem;
1713 : 5684 : ParseNamespaceColumn *nscol = grouping_nsitem->p_nscolumns + attnum - 1;
1714 : :
1715 [ - + ]: 5684 : Assert(nscol->p_varno == grouping_nsitem->p_rtindex);
1716 [ - + ]: 5684 : Assert(nscol->p_varattno == attnum);
1717 : 5684 : var = makeVar(nscol->p_varno,
1718 : 5684 : nscol->p_varattno,
1719 : : nscol->p_vartype,
1720 : : nscol->p_vartypmod,
1721 : : nscol->p_varcollid,
1722 : 5684 : context->sublevels_up);
1723 : : /* makeVar doesn't offer parameters for these, so set by hand: */
1724 : 5684 : var->varnosyn = nscol->p_varnosyn;
1725 : 5684 : var->varattnosyn = nscol->p_varattnosyn;
1726 : :
1727 [ + + ]: 5684 : if (context->qry->groupingSets &&
1728 [ + + ]: 1017 : !list_member_int(context->gset_common, ressortgroupref))
1729 : 915 : var->varnullingrels =
1730 : 915 : bms_add_member(var->varnullingrels, grouping_nsitem->p_rtindex);
1731 : :
1732 : 5684 : return var;
1733 : : }
1734 : :
1735 : :
1736 : : /*
1737 : : * Given a GroupingSet node, expand it and return a list of lists.
1738 : : *
1739 : : * For EMPTY nodes, return a list of one empty list.
1740 : : *
1741 : : * For SIMPLE nodes, return a list of one list, which is the node content.
1742 : : *
1743 : : * For CUBE and ROLLUP nodes, return a list of the expansions.
1744 : : *
1745 : : * For SET nodes, recursively expand contained CUBE and ROLLUP.
1746 : : */
1747 : : static List *
3766 andres@anarazel.de 1748 : 2165 : expand_groupingset_node(GroupingSet *gs)
1749 : : {
3759 bruce@momjian.us 1750 : 2165 : List *result = NIL;
1751 : :
3766 andres@anarazel.de 1752 [ + + + + : 2165 : switch (gs->kind)
+ - ]
1753 : : {
1754 : 216 : case GROUPING_SET_EMPTY:
1755 : 216 : result = list_make1(NIL);
1756 : 216 : break;
1757 : :
1758 : 1016 : case GROUPING_SET_SIMPLE:
1759 : 1016 : result = list_make1(gs->content);
1760 : 1016 : break;
1761 : :
1762 : 277 : case GROUPING_SET_ROLLUP:
1763 : : {
1764 : 277 : List *rollup_val = gs->content;
1765 : : ListCell *lc;
1766 : 277 : int curgroup_size = list_length(gs->content);
1767 : :
1768 [ + + ]: 719 : while (curgroup_size > 0)
1769 : : {
3759 bruce@momjian.us 1770 : 442 : List *current_result = NIL;
1771 : 442 : int i = curgroup_size;
1772 : :
3766 andres@anarazel.de 1773 [ + - + - : 607 : foreach(lc, rollup_val)
+ - ]
1774 : : {
1775 : 607 : GroupingSet *gs_current = (GroupingSet *) lfirst(lc);
1776 : :
1777 [ - + ]: 607 : Assert(gs_current->kind == GROUPING_SET_SIMPLE);
1778 : :
2217 tgl@sss.pgh.pa.us 1779 : 607 : current_result = list_concat(current_result,
1780 : 607 : gs_current->content);
1781 : :
1782 : : /* If we are done with making the current group, break */
3766 andres@anarazel.de 1783 [ + + ]: 607 : if (--i == 0)
1784 : 442 : break;
1785 : : }
1786 : :
1787 : 442 : result = lappend(result, current_result);
1788 : 442 : --curgroup_size;
1789 : : }
1790 : :
1791 : 277 : result = lappend(result, NIL);
1792 : : }
1793 : 277 : break;
1794 : :
1795 : 184 : case GROUPING_SET_CUBE:
1796 : : {
3759 bruce@momjian.us 1797 : 184 : List *cube_list = gs->content;
1798 : 184 : int number_bits = list_length(cube_list);
1799 : : uint32 num_sets;
1800 : : uint32 i;
1801 : :
1802 : : /* parser should cap this much lower */
3766 andres@anarazel.de 1803 [ - + ]: 184 : Assert(number_bits < 31);
1804 : :
1805 : 184 : num_sets = (1U << number_bits);
1806 : :
1807 [ + + ]: 1020 : for (i = 0; i < num_sets; i++)
1808 : : {
3759 bruce@momjian.us 1809 : 836 : List *current_result = NIL;
1810 : : ListCell *lc;
1811 : 836 : uint32 mask = 1U;
1812 : :
3766 andres@anarazel.de 1813 [ + - + + : 2776 : foreach(lc, cube_list)
+ + ]
1814 : : {
1815 : 1940 : GroupingSet *gs_current = (GroupingSet *) lfirst(lc);
1816 : :
1817 [ - + ]: 1940 : Assert(gs_current->kind == GROUPING_SET_SIMPLE);
1818 : :
1819 [ + + ]: 1940 : if (mask & i)
2217 tgl@sss.pgh.pa.us 1820 : 970 : current_result = list_concat(current_result,
1821 : 970 : gs_current->content);
1822 : :
3766 andres@anarazel.de 1823 : 1940 : mask <<= 1;
1824 : : }
1825 : :
1826 : 836 : result = lappend(result, current_result);
1827 : : }
1828 : : }
1829 : 184 : break;
1830 : :
1831 : 472 : case GROUPING_SET_SETS:
1832 : : {
1833 : : ListCell *lc;
1834 : :
1835 [ + - + + : 1680 : foreach(lc, gs->content)
+ + ]
1836 : : {
3759 bruce@momjian.us 1837 : 1208 : List *current_result = expand_groupingset_node(lfirst(lc));
1838 : :
3766 andres@anarazel.de 1839 : 1208 : result = list_concat(result, current_result);
1840 : : }
1841 : : }
1842 : 472 : break;
1843 : : }
1844 : :
1845 : 2165 : return result;
1846 : : }
1847 : :
1848 : : /* list_sort comparator to sort sub-lists by length */
1849 : : static int
2244 tgl@sss.pgh.pa.us 1850 : 2895 : cmp_list_len_asc(const ListCell *a, const ListCell *b)
1851 : : {
1852 : 2895 : int la = list_length((const List *) lfirst(a));
1853 : 2895 : int lb = list_length((const List *) lfirst(b));
1854 : :
568 nathan@postgresql.or 1855 : 2895 : return pg_cmp_s32(la, lb);
1856 : : }
1857 : :
1858 : : /* list_sort comparator to sort sub-lists by length and contents */
1859 : : static int
1633 tomas.vondra@postgre 1860 : 160 : cmp_list_len_contents_asc(const ListCell *a, const ListCell *b)
1861 : : {
1578 tgl@sss.pgh.pa.us 1862 : 160 : int res = cmp_list_len_asc(a, b);
1863 : :
1633 tomas.vondra@postgre 1864 [ + + ]: 160 : if (res == 0)
1865 : : {
1578 tgl@sss.pgh.pa.us 1866 : 48 : List *la = (List *) lfirst(a);
1867 : 48 : List *lb = (List *) lfirst(b);
1868 : : ListCell *lca;
1869 : : ListCell *lcb;
1870 : :
1633 tomas.vondra@postgre 1871 [ + - + + : 112 : forboth(lca, la, lcb, lb)
+ - + + +
+ + - +
+ ]
1872 : : {
1578 tgl@sss.pgh.pa.us 1873 : 80 : int va = lfirst_int(lca);
1874 : 80 : int vb = lfirst_int(lcb);
1875 : :
1633 tomas.vondra@postgre 1876 [ + + ]: 80 : if (va > vb)
1877 : 16 : return 1;
1878 [ + + ]: 72 : if (va < vb)
1879 : 8 : return -1;
1880 : : }
1881 : : }
1882 : :
1883 : 144 : return res;
1884 : : }
1885 : :
1886 : : /*
1887 : : * Expand a groupingSets clause to a flat list of grouping sets.
1888 : : * The returned list is sorted by length, shortest sets first.
1889 : : *
1890 : : * This is mainly for the planner, but we use it here too to do
1891 : : * some consistency checks.
1892 : : */
1893 : : List *
1894 : 893 : expand_grouping_sets(List *groupingSets, bool groupDistinct, int limit)
1895 : : {
3766 andres@anarazel.de 1896 : 893 : List *expanded_groups = NIL;
3759 bruce@momjian.us 1897 : 893 : List *result = NIL;
3766 andres@anarazel.de 1898 : 893 : double numsets = 1;
1899 : : ListCell *lc;
1900 : :
1901 [ - + ]: 893 : if (groupingSets == NIL)
3766 andres@anarazel.de 1902 :UBC 0 : return NIL;
1903 : :
3766 andres@anarazel.de 1904 [ + - + + :CBC 1850 : foreach(lc, groupingSets)
+ + ]
1905 : : {
3759 bruce@momjian.us 1906 : 957 : List *current_result = NIL;
3766 andres@anarazel.de 1907 : 957 : GroupingSet *gs = lfirst(lc);
1908 : :
1909 : 957 : current_result = expand_groupingset_node(gs);
1910 : :
1911 [ - + ]: 957 : Assert(current_result != NIL);
1912 : :
1913 : 957 : numsets *= list_length(current_result);
1914 : :
1915 [ + + - + ]: 957 : if (limit >= 0 && numsets > limit)
3766 andres@anarazel.de 1916 :UBC 0 : return NIL;
1917 : :
3766 andres@anarazel.de 1918 :CBC 957 : expanded_groups = lappend(expanded_groups, current_result);
1919 : : }
1920 : :
1921 : : /*
1922 : : * Do cartesian product between sublists of expanded_groups. While at it,
1923 : : * remove any duplicate elements from individual grouping sets (we must
1924 : : * NOT change the number of sets though)
1925 : : */
1926 : :
1927 [ + - + + : 3536 : foreach(lc, (List *) linitial(expanded_groups))
+ + ]
1928 : : {
1929 : 2643 : result = lappend(result, list_union_int(NIL, (List *) lfirst(lc)));
1930 : : }
1931 : :
1804 tgl@sss.pgh.pa.us 1932 [ + - + + : 957 : for_each_from(lc, expanded_groups, 1)
+ + ]
1933 : : {
3766 andres@anarazel.de 1934 : 64 : List *p = lfirst(lc);
1935 : 64 : List *new_result = NIL;
1936 : : ListCell *lc2;
1937 : :
1938 [ + - + + : 202 : foreach(lc2, result)
+ + ]
1939 : : {
1940 : 138 : List *q = lfirst(lc2);
1941 : : ListCell *lc3;
1942 : :
1943 [ + - + + : 480 : foreach(lc3, p)
+ + ]
1944 : : {
1945 : 342 : new_result = lappend(new_result,
1946 : 342 : list_union_int(q, (List *) lfirst(lc3)));
1947 : : }
1948 : : }
1949 : 64 : result = new_result;
1950 : : }
1951 : :
1952 : : /* Now sort the lists by length and deduplicate if necessary */
1633 tomas.vondra@postgre 1953 [ + + - + ]: 893 : if (!groupDistinct || list_length(result) < 2)
1954 : 885 : list_sort(result, cmp_list_len_asc);
1955 : : else
1956 : : {
1957 : : ListCell *cell;
1958 : : List *prev;
1959 : :
1960 : : /* Sort each groupset individually */
1961 [ + - + + : 80 : foreach(cell, result)
+ + ]
1962 : 72 : list_sort(lfirst(cell), list_int_cmp);
1963 : :
1964 : : /* Now sort the list of groupsets by length and contents */
1965 : 8 : list_sort(result, cmp_list_len_contents_asc);
1966 : :
1967 : : /* Finally, remove duplicates */
1538 drowley@postgresql.o 1968 : 8 : prev = linitial(result);
1633 tomas.vondra@postgre 1969 [ + - + + : 72 : for_each_from(cell, result, 1)
+ + ]
1970 : : {
1971 [ + + ]: 64 : if (equal(lfirst(cell), prev))
tgl@sss.pgh.pa.us 1972 : 32 : result = foreach_delete_current(result, cell);
1973 : : else
tomas.vondra@postgre 1974 : 32 : prev = lfirst(cell);
1975 : : }
1976 : : }
1977 : :
3766 andres@anarazel.de 1978 : 893 : return result;
1979 : : }
1980 : :
1981 : : /*
1982 : : * get_aggregate_argtypes
1983 : : * Identify the specific datatypes passed to an aggregate call.
1984 : : *
1985 : : * Given an Aggref, extract the actual datatypes of the input arguments.
1986 : : * The input datatypes are reported in a way that matches up with the
1987 : : * aggregate's declaration, ie, any ORDER BY columns attached to a plain
1988 : : * aggregate are ignored, but we report both direct and aggregated args of
1989 : : * an ordered-set aggregate.
1990 : : *
1991 : : * Datatypes are returned into inputTypes[], which must reference an array
1992 : : * of length FUNC_MAX_ARGS.
1993 : : *
1994 : : * The function result is the number of actual arguments.
1995 : : */
1996 : : int
4275 tgl@sss.pgh.pa.us 1997 : 46526 : get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
1998 : : {
1999 : 46526 : int numArguments = 0;
2000 : : ListCell *lc;
2001 : :
3368 2002 [ - + ]: 46526 : Assert(list_length(aggref->aggargtypes) <= FUNC_MAX_ARGS);
2003 : :
2004 [ + + + + : 84813 : foreach(lc, aggref->aggargtypes)
+ + ]
2005 : : {
2006 : 38287 : inputTypes[numArguments++] = lfirst_oid(lc);
2007 : : }
2008 : :
4275 2009 : 46526 : return numArguments;
2010 : : }
2011 : :
2012 : : /*
2013 : : * resolve_aggregate_transtype
2014 : : * Identify the transition state value's datatype for an aggregate call.
2015 : : *
2016 : : * This function resolves a polymorphic aggregate's state datatype.
2017 : : * It must be passed the aggtranstype from the aggregate's catalog entry,
2018 : : * as well as the actual argument types extracted by get_aggregate_argtypes.
2019 : : * (We could fetch pg_aggregate.aggtranstype internally, but all existing
2020 : : * callers already have the value at hand, so we make them pass it.)
2021 : : */
2022 : : Oid
2023 : 21781 : resolve_aggregate_transtype(Oid aggfuncid,
2024 : : Oid aggtranstype,
2025 : : Oid *inputTypes,
2026 : : int numArguments)
2027 : : {
2028 : : /* resolve actual type of transition state, if polymorphic */
2029 [ + + + + : 21781 : if (IsPolymorphicType(aggtranstype))
+ - + + +
+ + + + +
+ - + - +
- - + ]
2030 : : {
2031 : : /* have to fetch the agg's declared input types... */
2032 : : Oid *declaredArgTypes;
2033 : : int agg_nargs;
2034 : :
2035 : 272 : (void) get_func_signature(aggfuncid, &declaredArgTypes, &agg_nargs);
2036 : :
2037 : : /*
2038 : : * VARIADIC ANY aggs could have more actual than declared args, but
2039 : : * such extra args can't affect polymorphic type resolution.
2040 : : */
2041 [ - + ]: 272 : Assert(agg_nargs <= numArguments);
2042 : :
2043 : 272 : aggtranstype = enforce_generic_type_consistency(inputTypes,
2044 : : declaredArgTypes,
2045 : : agg_nargs,
2046 : : aggtranstype,
2047 : : false);
2048 : 272 : pfree(declaredArgTypes);
2049 : : }
2050 : 21781 : return aggtranstype;
2051 : : }
2052 : :
2053 : : /*
2054 : : * agg_args_support_sendreceive
2055 : : * Returns true if all non-byval types of aggref's args have send and
2056 : : * receive functions.
2057 : : */
2058 : : bool
957 drowley@postgresql.o 2059 : 5655 : agg_args_support_sendreceive(Aggref *aggref)
2060 : : {
2061 : : ListCell *lc;
2062 : :
2063 [ + - + + : 11241 : foreach(lc, aggref->args)
+ + ]
2064 : : {
2065 : : HeapTuple typeTuple;
2066 : : Form_pg_type pt;
2067 : 5655 : TargetEntry *tle = (TargetEntry *) lfirst(lc);
2068 : 5655 : Oid type = exprType((Node *) tle->expr);
2069 : :
2070 : : /*
2071 : : * RECORD is a special case: it has typsend/typreceive functions, but
2072 : : * record_recv only works if passed the correct typmod to identify the
2073 : : * specific anonymous record type. array_agg_deserialize cannot do
2074 : : * that, so we have to disclaim support for the case.
2075 : : */
181 tgl@sss.pgh.pa.us 2076 [ + + ]: 5655 : if (type == RECORDOID)
2077 : 69 : return false;
2078 : :
957 drowley@postgresql.o 2079 : 5634 : typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(type));
2080 [ - + ]: 5634 : if (!HeapTupleIsValid(typeTuple))
957 drowley@postgresql.o 2081 [ # # ]:UBC 0 : elog(ERROR, "cache lookup failed for type %u", type);
2082 : :
957 drowley@postgresql.o 2083 :CBC 5634 : pt = (Form_pg_type) GETSTRUCT(typeTuple);
2084 : :
2085 [ + + ]: 5634 : if (!pt->typbyval &&
2086 [ + + - + ]: 5560 : (!OidIsValid(pt->typsend) || !OidIsValid(pt->typreceive)))
2087 : : {
2088 : 48 : ReleaseSysCache(typeTuple);
2089 : 48 : return false;
2090 : : }
2091 : 5586 : ReleaseSysCache(typeTuple);
2092 : : }
2093 : 5586 : return true;
2094 : : }
2095 : :
2096 : : /*
2097 : : * Create an expression tree for the transition function of an aggregate.
2098 : : * This is needed so that polymorphic functions can be used within an
2099 : : * aggregate --- without the expression tree, such functions would not know
2100 : : * the datatypes they are supposed to use. (The trees will never actually
2101 : : * be executed, however, so we can skimp a bit on correctness.)
2102 : : *
2103 : : * agg_input_types and agg_state_type identifies the input types of the
2104 : : * aggregate. These should be resolved to actual types (ie, none should
2105 : : * ever be ANYELEMENT etc).
2106 : : * agg_input_collation is the aggregate function's input collation.
2107 : : *
2108 : : * For an ordered-set aggregate, remember that agg_input_types describes
2109 : : * the direct arguments followed by the aggregated arguments.
2110 : : *
2111 : : * transfn_oid and invtransfn_oid identify the funcs to be called; the
2112 : : * latter may be InvalidOid, however if invtransfn_oid is set then
2113 : : * transfn_oid must also be set.
2114 : : *
2115 : : * transfn_oid may also be passed as the aggcombinefn when the *transfnexpr is
2116 : : * to be used for a combine aggregate phase. We expect invtransfn_oid to be
2117 : : * InvalidOid in this case since there is no such thing as an inverse
2118 : : * combinefn.
2119 : : *
2120 : : * Pointers to the constructed trees are returned into *transfnexpr,
2121 : : * *invtransfnexpr. If there is no invtransfn, the respective pointer is set
2122 : : * to NULL. Since use of the invtransfn is optional, NULL may be passed for
2123 : : * invtransfnexpr.
2124 : : */
2125 : : void
3686 heikki.linnakangas@i 2126 : 25260 : build_aggregate_transfn_expr(Oid *agg_input_types,
2127 : : int agg_num_inputs,
2128 : : int agg_num_direct_inputs,
2129 : : bool agg_variadic,
2130 : : Oid agg_state_type,
2131 : : Oid agg_input_collation,
2132 : : Oid transfn_oid,
2133 : : Oid invtransfn_oid,
2134 : : Expr **transfnexpr,
2135 : : Expr **invtransfnexpr)
2136 : : {
2137 : : List *args;
2138 : : FuncExpr *fexpr;
2139 : : int i;
2140 : :
2141 : : /*
2142 : : * Build arg list to use in the transfn FuncExpr node.
2143 : : */
3363 tgl@sss.pgh.pa.us 2144 : 25260 : args = list_make1(make_agg_arg(agg_state_type, agg_input_collation));
2145 : :
4275 2146 [ + + ]: 46519 : for (i = agg_num_direct_inputs; i < agg_num_inputs; i++)
2147 : : {
3363 2148 : 21259 : args = lappend(args,
2149 : 21259 : make_agg_arg(agg_input_types[i], agg_input_collation));
2150 : : }
2151 : :
4386 2152 : 25260 : fexpr = makeFuncExpr(transfn_oid,
2153 : : agg_state_type,
2154 : : args,
2155 : : InvalidOid,
2156 : : agg_input_collation,
2157 : : COERCE_EXPLICIT_CALL);
2158 : 25260 : fexpr->funcvariadic = agg_variadic;
2159 : 25260 : *transfnexpr = (Expr *) fexpr;
2160 : :
2161 : : /*
2162 : : * Build invtransfn expression if requested, with same args as transfn
2163 : : */
4165 2164 [ + + ]: 25260 : if (invtransfnexpr != NULL)
2165 : : {
2166 [ + + ]: 766 : if (OidIsValid(invtransfn_oid))
2167 : : {
2168 : 399 : fexpr = makeFuncExpr(invtransfn_oid,
2169 : : agg_state_type,
2170 : : args,
2171 : : InvalidOid,
2172 : : agg_input_collation,
2173 : : COERCE_EXPLICIT_CALL);
2174 : 399 : fexpr->funcvariadic = agg_variadic;
2175 : 399 : *invtransfnexpr = (Expr *) fexpr;
2176 : : }
2177 : : else
2178 : 367 : *invtransfnexpr = NULL;
2179 : : }
3686 heikki.linnakangas@i 2180 : 25260 : }
2181 : :
2182 : : /*
2183 : : * Like build_aggregate_transfn_expr, but creates an expression tree for the
2184 : : * serialization function of an aggregate.
2185 : : */
2186 : : void
3363 tgl@sss.pgh.pa.us 2187 : 168 : build_aggregate_serialfn_expr(Oid serialfn_oid,
2188 : : Expr **serialfnexpr)
2189 : : {
2190 : : List *args;
2191 : : FuncExpr *fexpr;
2192 : :
2193 : : /* serialfn always takes INTERNAL and returns BYTEA */
2194 : 168 : args = list_make1(make_agg_arg(INTERNALOID, InvalidOid));
2195 : :
3448 rhaas@postgresql.org 2196 : 168 : fexpr = makeFuncExpr(serialfn_oid,
2197 : : BYTEAOID,
2198 : : args,
2199 : : InvalidOid,
2200 : : InvalidOid,
2201 : : COERCE_EXPLICIT_CALL);
2202 : 168 : *serialfnexpr = (Expr *) fexpr;
2203 : 168 : }
2204 : :
2205 : : /*
2206 : : * Like build_aggregate_transfn_expr, but creates an expression tree for the
2207 : : * deserialization function of an aggregate.
2208 : : */
2209 : : void
3363 tgl@sss.pgh.pa.us 2210 : 60 : build_aggregate_deserialfn_expr(Oid deserialfn_oid,
2211 : : Expr **deserialfnexpr)
2212 : : {
2213 : : List *args;
2214 : : FuncExpr *fexpr;
2215 : :
2216 : : /* deserialfn always takes BYTEA, INTERNAL and returns INTERNAL */
2217 : 60 : args = list_make2(make_agg_arg(BYTEAOID, InvalidOid),
2218 : : make_agg_arg(INTERNALOID, InvalidOid));
2219 : :
2220 : 60 : fexpr = makeFuncExpr(deserialfn_oid,
2221 : : INTERNALOID,
2222 : : args,
2223 : : InvalidOid,
2224 : : InvalidOid,
2225 : : COERCE_EXPLICIT_CALL);
2226 : 60 : *deserialfnexpr = (Expr *) fexpr;
2227 : 60 : }
2228 : :
2229 : : /*
2230 : : * Like build_aggregate_transfn_expr, but creates an expression tree for the
2231 : : * final function of an aggregate, rather than the transition function.
2232 : : */
2233 : : void
3686 heikki.linnakangas@i 2234 : 11492 : build_aggregate_finalfn_expr(Oid *agg_input_types,
2235 : : int num_finalfn_inputs,
2236 : : Oid agg_state_type,
2237 : : Oid agg_result_type,
2238 : : Oid agg_input_collation,
2239 : : Oid finalfn_oid,
2240 : : Expr **finalfnexpr)
2241 : : {
2242 : : List *args;
2243 : : int i;
2244 : :
2245 : : /*
2246 : : * Build expr tree for final function
2247 : : */
3363 tgl@sss.pgh.pa.us 2248 : 11492 : args = list_make1(make_agg_arg(agg_state_type, agg_input_collation));
2249 : :
2250 : : /* finalfn may take additional args, which match agg's input types */
4154 2251 [ + + ]: 18815 : for (i = 0; i < num_finalfn_inputs - 1; i++)
2252 : : {
3363 2253 : 7323 : args = lappend(args,
2254 : 7323 : make_agg_arg(agg_input_types[i], agg_input_collation));
2255 : : }
2256 : :
8069 bruce@momjian.us 2257 : 11492 : *finalfnexpr = (Expr *) makeFuncExpr(finalfn_oid,
2258 : : agg_result_type,
2259 : : args,
2260 : : InvalidOid,
2261 : : agg_input_collation,
2262 : : COERCE_EXPLICIT_CALL);
2263 : : /* finalfn is currently never treated as variadic */
8103 tgl@sss.pgh.pa.us 2264 : 11492 : }
2265 : :
2266 : : /*
2267 : : * Convenience function to build dummy argument expressions for aggregates.
2268 : : *
2269 : : * We really only care that an aggregate support function can discover its
2270 : : * actual argument types at runtime using get_fn_expr_argtype(), so it's okay
2271 : : * to use Param nodes that don't correspond to any real Param.
2272 : : */
2273 : : static Node *
3363 2274 : 65622 : make_agg_arg(Oid argtype, Oid argcollation)
2275 : : {
2276 : 65622 : Param *argp = makeNode(Param);
2277 : :
2278 : 65622 : argp->paramkind = PARAM_EXEC;
2279 : 65622 : argp->paramid = -1;
2280 : 65622 : argp->paramtype = argtype;
2281 : 65622 : argp->paramtypmod = -1;
2282 : 65622 : argp->paramcollid = argcollation;
2283 : 65622 : argp->location = -1;
2284 : 65622 : return (Node *) argp;
2285 : : }
|