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