1 /*-------------------------------------------------------------------------
4 * Routines to handle aggregate nodes.
6 * ExecAgg evaluates each aggregate in the following steps:
8 * transvalue = initcond
9 * foreach input_tuple do
10 * transvalue = transfunc(transvalue, input_value(s))
11 * result = finalfunc(transvalue)
13 * If a finalfunc is not supplied then the result is just the ending
14 * value of transvalue.
16 * If an aggregate call specifies DISTINCT or ORDER BY, we sort the input
17 * tuples and eliminate duplicates (if required) before performing the
18 * above-depicted process.
20 * If transfunc is marked "strict" in pg_proc and initcond is NULL,
21 * then the first non-NULL input_value is assigned directly to transvalue,
22 * and transfunc isn't applied until the second non-NULL input_value.
23 * The agg's first input type and transtype must be the same in this case!
25 * If transfunc is marked "strict" then NULL input_values are skipped,
26 * keeping the previous transvalue. If transfunc is not strict then it
27 * is called for every input tuple and must deal with NULL initcond
28 * or NULL input_values for itself.
30 * If finalfunc is marked "strict" then it is not called when the
31 * ending transvalue is NULL, instead a NULL result is created
32 * automatically (this is just the usual handling of strict functions,
33 * of course). A non-strict finalfunc can make its own choice of
34 * what to return for a NULL ending transvalue.
36 * We compute aggregate input expressions and run the transition functions
37 * in a temporary econtext (aggstate->tmpcontext). This is reset at
38 * least once per input tuple, so when the transvalue datatype is
39 * pass-by-reference, we have to be careful to copy it into a longer-lived
40 * memory context, and free the prior value to avoid memory leakage.
41 * We store transvalues in the memory context aggstate->aggcontext,
42 * which is also used for the hashtable structures in AGG_HASHED mode.
43 * The node's regular econtext (aggstate->csstate.cstate.cs_ExprContext)
44 * is used to run finalize functions and compute the output tuple;
45 * this context can be reset once per output tuple.
47 * The executor's AggState node is passed as the fmgr "context" value in
48 * all transfunc and finalfunc calls. It is not recommended that the
49 * transition functions look at the AggState node directly, but they can
50 * use AggCheckCallContext() to verify that they are being called by
51 * nodeAgg.c (and not as ordinary SQL functions). The main reason a
52 * transition function might want to know this is so that it can avoid
53 * palloc'ing a fixed-size pass-by-ref transition value on every call:
54 * it can instead just scribble on and return its left input. Ordinarily
55 * it is completely forbidden for functions to modify pass-by-ref inputs,
56 * but in the aggregate case we know the left input is either the initial
57 * transition value or a previous function result, and in either case its
58 * value need not be preserved. See int8inc() for an example. Notice that
59 * advance_transition_function() is coded to avoid a data copy step when
60 * the previous transition value pointer is returned. Also, some
61 * transition functions want to store working state in addition to the
62 * nominal transition value; they can use the memory context returned by
63 * AggCheckCallContext() to do that.
65 * Note: AggCheckCallContext() is available as of PostgreSQL 9.0. The
66 * AggState is available as context in earlier releases (back to 8.1),
67 * but direct examination of the node is needed to use it before 9.0.
70 * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
71 * Portions Copyright (c) 1994, Regents of the University of California
74 * $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.172 2010/02/08 20:39:51 tgl Exp $
76 *-------------------------------------------------------------------------
81 #include "catalog/pg_aggregate.h"
82 #include "catalog/pg_proc.h"
83 #include "catalog/pg_type.h"
84 #include "executor/executor.h"
85 #include "executor/nodeAgg.h"
86 #include "miscadmin.h"
87 #include "nodes/nodeFuncs.h"
88 #include "optimizer/clauses.h"
89 #include "optimizer/tlist.h"
90 #include "parser/parse_agg.h"
91 #include "parser/parse_coerce.h"
92 #include "utils/acl.h"
93 #include "utils/builtins.h"
94 #include "utils/lsyscache.h"
95 #include "utils/memutils.h"
96 #include "utils/syscache.h"
97 #include "utils/tuplesort.h"
98 #include "utils/datum.h"
102 * AggStatePerAggData - per-aggregate working state for the Agg scan
104 typedef struct AggStatePerAggData
107 * These values are set up during ExecInitAgg() and do not change
111 /* Links to Aggref expr and state nodes this working state is for */
112 AggrefExprState *aggrefstate;
115 /* number of input arguments for aggregate function proper */
118 /* number of inputs including ORDER BY expressions */
121 /* Oids of transfer functions */
123 Oid finalfn_oid; /* may be InvalidOid */
126 * fmgr lookup data for transfer functions --- only valid when
127 * corresponding oid is not InvalidOid. Note in particular that fn_strict
128 * flags are kept here.
133 /* number of sorting columns */
136 /* number of sorting columns to consider in DISTINCT comparisons */
137 /* (this is either zero or the same as numSortCols) */
140 /* deconstructed sorting information (arrays of length numSortCols) */
141 AttrNumber *sortColIdx;
143 bool *sortNullsFirst;
146 * fmgr lookup data for input columns' equality operators --- only
147 * set/used when aggregate has DISTINCT flag. Note that these are in
148 * order of sort column index, not parameter index.
150 FmgrInfo *equalfns; /* array of length numDistinctCols */
153 * initial value from pg_aggregate entry
156 bool initValueIsNull;
159 * We need the len and byval info for the agg's input, result, and
160 * transition data types in order to know how to copy/delete values.
162 * Note that the info for the input type is used only when handling
163 * DISTINCT aggs with just one argument, so there is only one input type.
173 * Stuff for evaluation of inputs. We used to just use ExecEvalExpr, but
174 * with the addition of ORDER BY we now need at least a slot for passing
175 * data to the sort object, which requires a tupledesc, so we might as
176 * well go whole hog and use ExecProject too.
178 TupleDesc evaldesc; /* descriptor of input tuples */
179 ProjectionInfo *evalproj; /* projection machinery */
182 * Slots for holding the evaluated input arguments. These are set up
183 * during ExecInitAgg() and then used for each input row.
185 TupleTableSlot *evalslot; /* current input tuple */
186 TupleTableSlot *uniqslot; /* used for multi-column DISTINCT */
189 * These values are working state that is initialized at the start of an
190 * input tuple group and updated for each input tuple.
192 * For a simple (non DISTINCT/ORDER BY) aggregate, we just feed the input
193 * values straight to the transition function. If it's DISTINCT or
194 * requires ORDER BY, we pass the input values into a Tuplesort object;
195 * then at completion of the input tuple group, we scan the sorted values,
196 * eliminate duplicates if needed, and run the transition function on the
200 Tuplesortstate *sortstate; /* sort object, if DISTINCT or ORDER BY */
201 } AggStatePerAggData;
204 * AggStatePerGroupData - per-aggregate-per-group working state
206 * These values are working state that is initialized at the start of
207 * an input tuple group and updated for each input tuple.
209 * In AGG_PLAIN and AGG_SORTED modes, we have a single array of these
210 * structs (pointed to by aggstate->pergroup); we re-use the array for
211 * each input group, if it's AGG_SORTED mode. In AGG_HASHED mode, the
212 * hash table contains an array of these structs for each tuple group.
214 * Logically, the sortstate field belongs in this struct, but we do not
215 * keep it here for space reasons: we don't support DISTINCT aggregates
216 * in AGG_HASHED mode, so there's no reason to use up a pointer field
217 * in every entry of the hashtable.
219 typedef struct AggStatePerGroupData
221 Datum transValue; /* current transition value */
222 bool transValueIsNull;
224 bool noTransValue; /* true if transValue not set yet */
227 * Note: noTransValue initially has the same value as transValueIsNull,
228 * and if true both are cleared to false at the same time. They are not
229 * the same though: if transfn later returns a NULL, we want to keep that
230 * NULL and not auto-replace it with a later input value. Only the first
231 * non-NULL input will be auto-substituted.
233 } AggStatePerGroupData;
236 * To implement hashed aggregation, we need a hashtable that stores a
237 * representative tuple and an array of AggStatePerGroup structs for each
238 * distinct set of GROUP BY column values. We compute the hash key from
239 * the GROUP BY columns.
241 typedef struct AggHashEntryData *AggHashEntry;
243 typedef struct AggHashEntryData
245 TupleHashEntryData shared; /* common header for hash table entries */
246 /* per-aggregate transition status array - must be last! */
247 AggStatePerGroupData pergroup[1]; /* VARIABLE LENGTH ARRAY */
248 } AggHashEntryData; /* VARIABLE LENGTH STRUCT */
251 static void initialize_aggregates(AggState *aggstate,
252 AggStatePerAgg peragg,
253 AggStatePerGroup pergroup);
254 static void advance_transition_function(AggState *aggstate,
255 AggStatePerAgg peraggstate,
256 AggStatePerGroup pergroupstate,
257 FunctionCallInfoData *fcinfo);
258 static void advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup);
259 static void process_ordered_aggregate_single(AggState *aggstate,
260 AggStatePerAgg peraggstate,
261 AggStatePerGroup pergroupstate);
262 static void process_ordered_aggregate_multi(AggState *aggstate,
263 AggStatePerAgg peraggstate,
264 AggStatePerGroup pergroupstate);
265 static void finalize_aggregate(AggState *aggstate,
266 AggStatePerAgg peraggstate,
267 AggStatePerGroup pergroupstate,
268 Datum *resultVal, bool *resultIsNull);
269 static Bitmapset *find_unaggregated_cols(AggState *aggstate);
270 static bool find_unaggregated_cols_walker(Node *node, Bitmapset **colnos);
271 static void build_hash_table(AggState *aggstate);
272 static AggHashEntry lookup_hash_entry(AggState *aggstate,
273 TupleTableSlot *inputslot);
274 static TupleTableSlot *agg_retrieve_direct(AggState *aggstate);
275 static void agg_fill_hash_table(AggState *aggstate);
276 static TupleTableSlot *agg_retrieve_hash_table(AggState *aggstate);
277 static Datum GetAggInitVal(Datum textInitVal, Oid transtype);
281 * Initialize all aggregates for a new group of input values.
283 * When called, CurrentMemoryContext should be the per-query context.
286 initialize_aggregates(AggState *aggstate,
287 AggStatePerAgg peragg,
288 AggStatePerGroup pergroup)
292 for (aggno = 0; aggno < aggstate->numaggs; aggno++)
294 AggStatePerAgg peraggstate = &peragg[aggno];
295 AggStatePerGroup pergroupstate = &pergroup[aggno];
298 * Start a fresh sort operation for each DISTINCT/ORDER BY aggregate.
300 if (peraggstate->numSortCols > 0)
303 * In case of rescan, maybe there could be an uncompleted sort
304 * operation? Clean it up if so.
306 if (peraggstate->sortstate)
307 tuplesort_end(peraggstate->sortstate);
310 * We use a plain Datum sorter when there's a single input
311 * column; otherwise sort the full tuple. (See comments for
312 * process_ordered_aggregate_single.)
314 peraggstate->sortstate =
315 (peraggstate->numInputs == 1) ?
316 tuplesort_begin_datum(peraggstate->evaldesc->attrs[0]->atttypid,
317 peraggstate->sortOperators[0],
318 peraggstate->sortNullsFirst[0],
320 tuplesort_begin_heap(peraggstate->evaldesc,
321 peraggstate->numSortCols,
322 peraggstate->sortColIdx,
323 peraggstate->sortOperators,
324 peraggstate->sortNullsFirst,
329 * (Re)set transValue to the initial value.
331 * Note that when the initial value is pass-by-ref, we must copy it
332 * (into the aggcontext) since we will pfree the transValue later.
334 if (peraggstate->initValueIsNull)
335 pergroupstate->transValue = peraggstate->initValue;
338 MemoryContext oldContext;
340 oldContext = MemoryContextSwitchTo(aggstate->aggcontext);
341 pergroupstate->transValue = datumCopy(peraggstate->initValue,
342 peraggstate->transtypeByVal,
343 peraggstate->transtypeLen);
344 MemoryContextSwitchTo(oldContext);
346 pergroupstate->transValueIsNull = peraggstate->initValueIsNull;
349 * If the initial value for the transition state doesn't exist in the
350 * pg_aggregate table then we will let the first non-NULL value
351 * returned from the outer procNode become the initial value. (This is
352 * useful for aggregates like max() and min().) The noTransValue flag
353 * signals that we still need to do this.
355 pergroupstate->noTransValue = peraggstate->initValueIsNull;
360 * Given new input value(s), advance the transition function of an aggregate.
362 * The new values (and null flags) have been preloaded into argument positions
363 * 1 and up in fcinfo, so that we needn't copy them again to pass to the
364 * transition function. No other fields of fcinfo are assumed valid.
366 * It doesn't matter which memory context this is called in.
369 advance_transition_function(AggState *aggstate,
370 AggStatePerAgg peraggstate,
371 AggStatePerGroup pergroupstate,
372 FunctionCallInfoData *fcinfo)
374 int numArguments = peraggstate->numArguments;
375 MemoryContext oldContext;
379 if (peraggstate->transfn.fn_strict)
382 * For a strict transfn, nothing happens when there's a NULL input; we
383 * just keep the prior transValue.
385 for (i = 1; i <= numArguments; i++)
387 if (fcinfo->argnull[i])
390 if (pergroupstate->noTransValue)
393 * transValue has not been initialized. This is the first non-NULL
394 * input value. We use it as the initial value for transValue. (We
395 * already checked that the agg's input type is binary-compatible
396 * with its transtype, so straight copy here is OK.)
398 * We must copy the datum into aggcontext if it is pass-by-ref. We
399 * do not need to pfree the old transValue, since it's NULL.
401 oldContext = MemoryContextSwitchTo(aggstate->aggcontext);
402 pergroupstate->transValue = datumCopy(fcinfo->arg[1],
403 peraggstate->transtypeByVal,
404 peraggstate->transtypeLen);
405 pergroupstate->transValueIsNull = false;
406 pergroupstate->noTransValue = false;
407 MemoryContextSwitchTo(oldContext);
410 if (pergroupstate->transValueIsNull)
413 * Don't call a strict function with NULL inputs. Note it is
414 * possible to get here despite the above tests, if the transfn is
415 * strict *and* returned a NULL on a prior cycle. If that happens
416 * we will propagate the NULL all the way to the end.
422 /* We run the transition functions in per-input-tuple memory context */
423 oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
426 * OK to call the transition function
428 InitFunctionCallInfoData(*fcinfo, &(peraggstate->transfn),
430 (void *) aggstate, NULL);
431 fcinfo->arg[0] = pergroupstate->transValue;
432 fcinfo->argnull[0] = pergroupstate->transValueIsNull;
434 newVal = FunctionCallInvoke(fcinfo);
437 * If pass-by-ref datatype, must copy the new value into aggcontext and
438 * pfree the prior transValue. But if transfn returned a pointer to its
439 * first input, we don't need to do anything.
441 if (!peraggstate->transtypeByVal &&
442 DatumGetPointer(newVal) != DatumGetPointer(pergroupstate->transValue))
446 MemoryContextSwitchTo(aggstate->aggcontext);
447 newVal = datumCopy(newVal,
448 peraggstate->transtypeByVal,
449 peraggstate->transtypeLen);
451 if (!pergroupstate->transValueIsNull)
452 pfree(DatumGetPointer(pergroupstate->transValue));
455 pergroupstate->transValue = newVal;
456 pergroupstate->transValueIsNull = fcinfo->isnull;
458 MemoryContextSwitchTo(oldContext);
462 * Advance all the aggregates for one input tuple. The input tuple
463 * has been stored in tmpcontext->ecxt_outertuple, so that it is accessible
464 * to ExecEvalExpr. pergroup is the array of per-group structs to use
465 * (this might be in a hashtable entry).
467 * When called, CurrentMemoryContext should be the per-query context.
470 advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
474 for (aggno = 0; aggno < aggstate->numaggs; aggno++)
476 AggStatePerAgg peraggstate = &aggstate->peragg[aggno];
477 AggStatePerGroup pergroupstate = &pergroup[aggno];
478 int nargs = peraggstate->numArguments;
480 TupleTableSlot *slot;
482 /* Evaluate the current input expressions for this aggregate */
483 slot = ExecProject(peraggstate->evalproj, NULL);
485 if (peraggstate->numSortCols > 0)
487 /* DISTINCT and/or ORDER BY case */
488 Assert(slot->tts_nvalid == peraggstate->numInputs);
491 * If the transfn is strict, we want to check for nullity
492 * before storing the row in the sorter, to save space if
493 * there are a lot of nulls. Note that we must only check
494 * numArguments columns, not numInputs, since nullity in
495 * columns used only for sorting is not relevant here.
497 if (peraggstate->transfn.fn_strict)
499 for (i = 0; i < nargs; i++)
501 if (slot->tts_isnull[i])
508 /* OK, put the tuple into the tuplesort object */
509 if (peraggstate->numInputs == 1)
510 tuplesort_putdatum(peraggstate->sortstate,
512 slot->tts_isnull[0]);
514 tuplesort_puttupleslot(peraggstate->sortstate, slot);
518 /* We can apply the transition function immediately */
519 FunctionCallInfoData fcinfo;
521 /* Load values into fcinfo */
522 /* Start from 1, since the 0th arg will be the transition value */
523 Assert(slot->tts_nvalid >= nargs);
524 for (i = 0; i < nargs; i++)
526 fcinfo.arg[i + 1] = slot->tts_values[i];
527 fcinfo.argnull[i + 1] = slot->tts_isnull[i];
530 advance_transition_function(aggstate, peraggstate, pergroupstate,
538 * Run the transition function for a DISTINCT or ORDER BY aggregate
539 * with only one input. This is called after we have completed
540 * entering all the input values into the sort object. We complete the
541 * sort, read out the values in sorted order, and run the transition
542 * function on each value (applying DISTINCT if appropriate).
544 * Note that the strictness of the transition function was checked when
545 * entering the values into the sort, so we don't check it again here;
546 * we just apply standard SQL DISTINCT logic.
548 * The one-input case is handled separately from the multi-input case
549 * for performance reasons: for single by-value inputs, such as the
550 * common case of count(distinct id), the tuplesort_getdatum code path
551 * is around 300% faster. (The speedup for by-reference types is less
552 * but still noticeable.)
554 * When called, CurrentMemoryContext should be the per-query context.
557 process_ordered_aggregate_single(AggState *aggstate,
558 AggStatePerAgg peraggstate,
559 AggStatePerGroup pergroupstate)
561 Datum oldVal = (Datum) 0;
562 bool oldIsNull = true;
563 bool haveOldVal = false;
564 MemoryContext workcontext = aggstate->tmpcontext->ecxt_per_tuple_memory;
565 MemoryContext oldContext;
566 bool isDistinct = (peraggstate->numDistinctCols > 0);
569 FunctionCallInfoData fcinfo;
571 Assert(peraggstate->numDistinctCols < 2);
573 tuplesort_performsort(peraggstate->sortstate);
575 /* Load the column into argument 1 (arg 0 will be transition value) */
576 newVal = fcinfo.arg + 1;
577 isNull = fcinfo.argnull + 1;
580 * Note: if input type is pass-by-ref, the datums returned by the sort are
581 * freshly palloc'd in the per-query context, so we must be careful to
582 * pfree them when they are no longer needed.
585 while (tuplesort_getdatum(peraggstate->sortstate, true,
589 * Clear and select the working context for evaluation of the equality
590 * function and transition function.
592 MemoryContextReset(workcontext);
593 oldContext = MemoryContextSwitchTo(workcontext);
596 * If DISTINCT mode, and not distinct from prior, skip it.
600 ((oldIsNull && *isNull) ||
601 (!oldIsNull && !*isNull &&
602 DatumGetBool(FunctionCall2(&peraggstate->equalfns[0],
605 /* equal to prior, so forget this one */
606 if (!peraggstate->inputtypeByVal && !*isNull)
607 pfree(DatumGetPointer(*newVal));
611 advance_transition_function(aggstate, peraggstate, pergroupstate,
613 /* forget the old value, if any */
614 if (!oldIsNull && !peraggstate->inputtypeByVal)
615 pfree(DatumGetPointer(oldVal));
616 /* and remember the new one for subsequent equality checks */
622 MemoryContextSwitchTo(oldContext);
625 if (!oldIsNull && !peraggstate->inputtypeByVal)
626 pfree(DatumGetPointer(oldVal));
628 tuplesort_end(peraggstate->sortstate);
629 peraggstate->sortstate = NULL;
633 * Run the transition function for a DISTINCT or ORDER BY aggregate
634 * with more than one input. This is called after we have completed
635 * entering all the input values into the sort object. We complete the
636 * sort, read out the values in sorted order, and run the transition
637 * function on each value (applying DISTINCT if appropriate).
639 * When called, CurrentMemoryContext should be the per-query context.
642 process_ordered_aggregate_multi(AggState *aggstate,
643 AggStatePerAgg peraggstate,
644 AggStatePerGroup pergroupstate)
646 MemoryContext workcontext = aggstate->tmpcontext->ecxt_per_tuple_memory;
647 FunctionCallInfoData fcinfo;
648 TupleTableSlot *slot1 = peraggstate->evalslot;
649 TupleTableSlot *slot2 = peraggstate->uniqslot;
650 int numArguments = peraggstate->numArguments;
651 int numDistinctCols = peraggstate->numDistinctCols;
652 bool haveOldValue = false;
655 tuplesort_performsort(peraggstate->sortstate);
657 ExecClearTuple(slot1);
659 ExecClearTuple(slot2);
661 while (tuplesort_gettupleslot(peraggstate->sortstate, true, slot1))
664 * Extract the first numArguments as datums to pass to the transfn.
665 * (This will help execTuplesMatch too, so do it immediately.)
667 slot_getsomeattrs(slot1, numArguments);
669 if (numDistinctCols == 0 ||
671 !execTuplesMatch(slot1, slot2,
673 peraggstate->sortColIdx,
674 peraggstate->equalfns,
677 /* Load values into fcinfo */
678 /* Start from 1, since the 0th arg will be the transition value */
679 for (i = 0; i < numArguments; i++)
681 fcinfo.arg[i + 1] = slot1->tts_values[i];
682 fcinfo.argnull[i + 1] = slot1->tts_isnull[i];
685 advance_transition_function(aggstate, peraggstate, pergroupstate,
688 if (numDistinctCols > 0)
690 /* swap the slot pointers to retain the current tuple */
691 TupleTableSlot *tmpslot = slot2;
699 /* Reset context each time, unless execTuplesMatch did it for us */
700 if (numDistinctCols == 0)
701 MemoryContextReset(workcontext);
703 ExecClearTuple(slot1);
707 ExecClearTuple(slot2);
709 tuplesort_end(peraggstate->sortstate);
710 peraggstate->sortstate = NULL;
714 * Compute the final value of one aggregate.
716 * The finalfunction will be run, and the result delivered, in the
717 * output-tuple context; caller's CurrentMemoryContext does not matter.
720 finalize_aggregate(AggState *aggstate,
721 AggStatePerAgg peraggstate,
722 AggStatePerGroup pergroupstate,
723 Datum *resultVal, bool *resultIsNull)
725 MemoryContext oldContext;
727 oldContext = MemoryContextSwitchTo(aggstate->ss.ps.ps_ExprContext->ecxt_per_tuple_memory);
730 * Apply the agg's finalfn if one is provided, else return transValue.
732 if (OidIsValid(peraggstate->finalfn_oid))
734 FunctionCallInfoData fcinfo;
736 InitFunctionCallInfoData(fcinfo, &(peraggstate->finalfn), 1,
737 (void *) aggstate, NULL);
738 fcinfo.arg[0] = pergroupstate->transValue;
739 fcinfo.argnull[0] = pergroupstate->transValueIsNull;
740 if (fcinfo.flinfo->fn_strict && pergroupstate->transValueIsNull)
742 /* don't call a strict function with NULL inputs */
743 *resultVal = (Datum) 0;
744 *resultIsNull = true;
748 *resultVal = FunctionCallInvoke(&fcinfo);
749 *resultIsNull = fcinfo.isnull;
754 *resultVal = pergroupstate->transValue;
755 *resultIsNull = pergroupstate->transValueIsNull;
759 * If result is pass-by-ref, make sure it is in the right context.
761 if (!peraggstate->resulttypeByVal && !*resultIsNull &&
762 !MemoryContextContains(CurrentMemoryContext,
763 DatumGetPointer(*resultVal)))
764 *resultVal = datumCopy(*resultVal,
765 peraggstate->resulttypeByVal,
766 peraggstate->resulttypeLen);
768 MemoryContextSwitchTo(oldContext);
772 * find_unaggregated_cols
773 * Construct a bitmapset of the column numbers of un-aggregated Vars
774 * appearing in our targetlist and qual (HAVING clause)
777 find_unaggregated_cols(AggState *aggstate)
779 Agg *node = (Agg *) aggstate->ss.ps.plan;
783 (void) find_unaggregated_cols_walker((Node *) node->plan.targetlist,
785 (void) find_unaggregated_cols_walker((Node *) node->plan.qual,
791 find_unaggregated_cols_walker(Node *node, Bitmapset **colnos)
797 Var *var = (Var *) node;
799 /* setrefs.c should have set the varno to OUTER */
800 Assert(var->varno == OUTER);
801 Assert(var->varlevelsup == 0);
802 *colnos = bms_add_member(*colnos, var->varattno);
805 if (IsA(node, Aggref)) /* do not descend into aggregate exprs */
807 return expression_tree_walker(node, find_unaggregated_cols_walker,
812 * Initialize the hash table to empty.
814 * The hash table always lives in the aggcontext memory context.
817 build_hash_table(AggState *aggstate)
819 Agg *node = (Agg *) aggstate->ss.ps.plan;
820 MemoryContext tmpmem = aggstate->tmpcontext->ecxt_per_tuple_memory;
823 Assert(node->aggstrategy == AGG_HASHED);
824 Assert(node->numGroups > 0);
826 entrysize = sizeof(AggHashEntryData) +
827 (aggstate->numaggs - 1) *sizeof(AggStatePerGroupData);
829 aggstate->hashtable = BuildTupleHashTable(node->numCols,
831 aggstate->eqfunctions,
832 aggstate->hashfunctions,
835 aggstate->aggcontext,
840 * Create a list of the tuple columns that actually need to be stored in
841 * hashtable entries. The incoming tuples from the child plan node will
842 * contain grouping columns, other columns referenced in our targetlist and
843 * qual, columns used to compute the aggregate functions, and perhaps just
844 * junk columns we don't use at all. Only columns of the first two types
845 * need to be stored in the hashtable, and getting rid of the others can
846 * make the table entries significantly smaller. To avoid messing up Var
847 * numbering, we keep the same tuple descriptor for hashtable entries as the
848 * incoming tuples have, but set unwanted columns to NULL in the tuples that
851 * To eliminate duplicates, we build a bitmapset of the needed columns, then
852 * convert it to an integer list (cheaper to scan at runtime). The list is
853 * in decreasing order so that the first entry is the largest;
854 * lookup_hash_entry depends on this to use slot_getsomeattrs correctly.
855 * Note that the list is preserved over ExecReScanAgg, so we allocate it in
856 * the per-query context (unlike the hash table itself).
858 * Note: at present, searching the tlist/qual is not really necessary since
859 * the parser should disallow any unaggregated references to ungrouped
860 * columns. However, the search will be needed when we add support for
861 * SQL99 semantics that allow use of "functionally dependent" columns that
862 * haven't been explicitly grouped by.
865 find_hash_columns(AggState *aggstate)
867 Agg *node = (Agg *) aggstate->ss.ps.plan;
872 /* Find Vars that will be needed in tlist and qual */
873 colnos = find_unaggregated_cols(aggstate);
874 /* Add in all the grouping columns */
875 for (i = 0; i < node->numCols; i++)
876 colnos = bms_add_member(colnos, node->grpColIdx[i]);
877 /* Convert to list, using lcons so largest element ends up first */
879 while ((i = bms_first_member(colnos)) >= 0)
880 collist = lcons_int(i, collist);
887 * Estimate per-hash-table-entry overhead for the planner.
889 * Note that the estimate does not include space for pass-by-reference
890 * transition data values, nor for the representative tuple of each group.
893 hash_agg_entry_size(int numAggs)
897 /* This must match build_hash_table */
898 entrysize = sizeof(AggHashEntryData) +
899 (numAggs - 1) *sizeof(AggStatePerGroupData);
900 entrysize = MAXALIGN(entrysize);
901 /* Account for hashtable overhead (assuming fill factor = 1) */
902 entrysize += 3 * sizeof(void *);
907 * Find or create a hashtable entry for the tuple group containing the
910 * When called, CurrentMemoryContext should be the per-query context.
913 lookup_hash_entry(AggState *aggstate, TupleTableSlot *inputslot)
915 TupleTableSlot *hashslot = aggstate->hashslot;
920 /* if first time through, initialize hashslot by cloning input slot */
921 if (hashslot->tts_tupleDescriptor == NULL)
923 ExecSetSlotDescriptor(hashslot, inputslot->tts_tupleDescriptor);
924 /* Make sure all unused columns are NULLs */
925 ExecStoreAllNullTuple(hashslot);
928 /* transfer just the needed columns into hashslot */
929 slot_getsomeattrs(inputslot, linitial_int(aggstate->hash_needed));
930 foreach(l, aggstate->hash_needed)
932 int varNumber = lfirst_int(l) - 1;
934 hashslot->tts_values[varNumber] = inputslot->tts_values[varNumber];
935 hashslot->tts_isnull[varNumber] = inputslot->tts_isnull[varNumber];
938 /* find or create the hashtable entry using the filtered tuple */
939 entry = (AggHashEntry) LookupTupleHashEntry(aggstate->hashtable,
945 /* initialize aggregates for new tuple group */
946 initialize_aggregates(aggstate, aggstate->peragg, entry->pergroup);
955 * ExecAgg receives tuples from its outer subplan and aggregates over
956 * the appropriate attribute for each aggregate function use (Aggref
957 * node) appearing in the targetlist or qual of the node. The number
958 * of tuples to aggregate over depends on whether grouped or plain
959 * aggregation is selected. In grouped aggregation, we produce a result
960 * row for each group; in plain aggregation there's a single result row
961 * for the whole query. In either case, the value of each aggregate is
962 * stored in the expression context to be used when ExecProject evaluates
966 ExecAgg(AggState *node)
969 * Check to see if we're still projecting out tuples from a previous agg
970 * tuple (because there is a function-returning-set in the projection
971 * expressions). If so, try to project another one.
973 if (node->ss.ps.ps_TupFromTlist)
975 TupleTableSlot *result;
978 result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
979 if (isDone == ExprMultipleResult)
981 /* Done with that source tuple... */
982 node->ss.ps.ps_TupFromTlist = false;
986 * Exit if nothing left to do. (We must do the ps_TupFromTlist check
987 * first, because in some cases agg_done gets set before we emit the
988 * final aggregate tuple, and we have to finish running SRFs for it.)
993 /* Dispatch based on strategy */
994 if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
996 if (!node->table_filled)
997 agg_fill_hash_table(node);
998 return agg_retrieve_hash_table(node);
1001 return agg_retrieve_direct(node);
1005 * ExecAgg for non-hashed case
1007 static TupleTableSlot *
1008 agg_retrieve_direct(AggState *aggstate)
1010 Agg *node = (Agg *) aggstate->ss.ps.plan;
1011 PlanState *outerPlan;
1012 ExprContext *econtext;
1013 ExprContext *tmpcontext;
1016 AggStatePerAgg peragg;
1017 AggStatePerGroup pergroup;
1018 TupleTableSlot *outerslot;
1019 TupleTableSlot *firstSlot;
1023 * get state info from node
1025 outerPlan = outerPlanState(aggstate);
1026 /* econtext is the per-output-tuple expression context */
1027 econtext = aggstate->ss.ps.ps_ExprContext;
1028 aggvalues = econtext->ecxt_aggvalues;
1029 aggnulls = econtext->ecxt_aggnulls;
1030 /* tmpcontext is the per-input-tuple expression context */
1031 tmpcontext = aggstate->tmpcontext;
1032 peragg = aggstate->peragg;
1033 pergroup = aggstate->pergroup;
1034 firstSlot = aggstate->ss.ss_ScanTupleSlot;
1037 * We loop retrieving groups until we find one matching
1038 * aggstate->ss.ps.qual
1040 while (!aggstate->agg_done)
1043 * If we don't already have the first tuple of the new group, fetch it
1044 * from the outer plan.
1046 if (aggstate->grp_firstTuple == NULL)
1048 outerslot = ExecProcNode(outerPlan);
1049 if (!TupIsNull(outerslot))
1052 * Make a copy of the first input tuple; we will use this for
1053 * comparisons (in group mode) and for projection.
1055 aggstate->grp_firstTuple = ExecCopySlotTuple(outerslot);
1059 /* outer plan produced no tuples at all */
1060 aggstate->agg_done = true;
1061 /* If we are grouping, we should produce no tuples too */
1062 if (node->aggstrategy != AGG_PLAIN)
1068 * Clear the per-output-tuple context for each group, as well as
1069 * aggcontext (which contains any pass-by-ref transvalues of the
1070 * old group). We also clear any child contexts of the aggcontext;
1071 * some aggregate functions store working state in such contexts.
1073 ResetExprContext(econtext);
1075 MemoryContextResetAndDeleteChildren(aggstate->aggcontext);
1078 * Initialize working state for a new input tuple group
1080 initialize_aggregates(aggstate, peragg, pergroup);
1082 if (aggstate->grp_firstTuple != NULL)
1085 * Store the copied first input tuple in the tuple table slot
1086 * reserved for it. The tuple will be deleted when it is cleared
1089 ExecStoreTuple(aggstate->grp_firstTuple,
1093 aggstate->grp_firstTuple = NULL; /* don't keep two pointers */
1095 /* set up for first advance_aggregates call */
1096 tmpcontext->ecxt_outertuple = firstSlot;
1099 * Process each outer-plan tuple, and then fetch the next one,
1100 * until we exhaust the outer plan or cross a group boundary.
1104 advance_aggregates(aggstate, pergroup);
1106 /* Reset per-input-tuple context after each tuple */
1107 ResetExprContext(tmpcontext);
1109 outerslot = ExecProcNode(outerPlan);
1110 if (TupIsNull(outerslot))
1112 /* no more outer-plan tuples available */
1113 aggstate->agg_done = true;
1116 /* set up for next advance_aggregates call */
1117 tmpcontext->ecxt_outertuple = outerslot;
1120 * If we are grouping, check whether we've crossed a group
1123 if (node->aggstrategy == AGG_SORTED)
1125 if (!execTuplesMatch(firstSlot,
1127 node->numCols, node->grpColIdx,
1128 aggstate->eqfunctions,
1129 tmpcontext->ecxt_per_tuple_memory))
1132 * Save the first input tuple of the next group.
1134 aggstate->grp_firstTuple = ExecCopySlotTuple(outerslot);
1142 * Done scanning input tuple group. Finalize each aggregate
1143 * calculation, and stash results in the per-output-tuple context.
1145 for (aggno = 0; aggno < aggstate->numaggs; aggno++)
1147 AggStatePerAgg peraggstate = &peragg[aggno];
1148 AggStatePerGroup pergroupstate = &pergroup[aggno];
1150 if (peraggstate->numSortCols > 0)
1152 if (peraggstate->numInputs == 1)
1153 process_ordered_aggregate_single(aggstate,
1157 process_ordered_aggregate_multi(aggstate,
1162 finalize_aggregate(aggstate, peraggstate, pergroupstate,
1163 &aggvalues[aggno], &aggnulls[aggno]);
1167 * Use the representative input tuple for any references to
1168 * non-aggregated input columns in the qual and tlist. (If we are not
1169 * grouping, and there are no input rows at all, we will come here
1170 * with an empty firstSlot ... but if not grouping, there can't be any
1171 * references to non-aggregated input columns, so no problem.)
1173 econtext->ecxt_outertuple = firstSlot;
1176 * Check the qual (HAVING clause); if the group does not match, ignore
1177 * it and loop back to try to process another group.
1179 if (ExecQual(aggstate->ss.ps.qual, econtext, false))
1182 * Form and return a projection tuple using the aggregate results
1183 * and the representative input tuple.
1185 TupleTableSlot *result;
1186 ExprDoneCond isDone;
1188 result = ExecProject(aggstate->ss.ps.ps_ProjInfo, &isDone);
1190 if (isDone != ExprEndResult)
1192 aggstate->ss.ps.ps_TupFromTlist =
1193 (isDone == ExprMultipleResult);
1199 /* No more groups */
1204 * ExecAgg for hashed case: phase 1, read input and build hash table
1207 agg_fill_hash_table(AggState *aggstate)
1209 PlanState *outerPlan;
1210 ExprContext *tmpcontext;
1212 TupleTableSlot *outerslot;
1215 * get state info from node
1217 outerPlan = outerPlanState(aggstate);
1218 /* tmpcontext is the per-input-tuple expression context */
1219 tmpcontext = aggstate->tmpcontext;
1222 * Process each outer-plan tuple, and then fetch the next one, until we
1223 * exhaust the outer plan.
1227 outerslot = ExecProcNode(outerPlan);
1228 if (TupIsNull(outerslot))
1230 /* set up for advance_aggregates call */
1231 tmpcontext->ecxt_outertuple = outerslot;
1233 /* Find or build hashtable entry for this tuple's group */
1234 entry = lookup_hash_entry(aggstate, outerslot);
1236 /* Advance the aggregates */
1237 advance_aggregates(aggstate, entry->pergroup);
1239 /* Reset per-input-tuple context after each tuple */
1240 ResetExprContext(tmpcontext);
1243 aggstate->table_filled = true;
1244 /* Initialize to walk the hash table */
1245 ResetTupleHashIterator(aggstate->hashtable, &aggstate->hashiter);
1249 * ExecAgg for hashed case: phase 2, retrieving groups from hash table
1251 static TupleTableSlot *
1252 agg_retrieve_hash_table(AggState *aggstate)
1254 ExprContext *econtext;
1257 AggStatePerAgg peragg;
1258 AggStatePerGroup pergroup;
1260 TupleTableSlot *firstSlot;
1264 * get state info from node
1266 /* econtext is the per-output-tuple expression context */
1267 econtext = aggstate->ss.ps.ps_ExprContext;
1268 aggvalues = econtext->ecxt_aggvalues;
1269 aggnulls = econtext->ecxt_aggnulls;
1270 peragg = aggstate->peragg;
1271 firstSlot = aggstate->ss.ss_ScanTupleSlot;
1274 * We loop retrieving groups until we find one satisfying
1275 * aggstate->ss.ps.qual
1277 while (!aggstate->agg_done)
1280 * Find the next entry in the hash table
1282 entry = (AggHashEntry) ScanTupleHashTable(&aggstate->hashiter);
1285 /* No more entries in hashtable, so done */
1286 aggstate->agg_done = TRUE;
1291 * Clear the per-output-tuple context for each group
1293 ResetExprContext(econtext);
1296 * Store the copied first input tuple in the tuple table slot reserved
1297 * for it, so that it can be used in ExecProject.
1299 ExecStoreMinimalTuple(entry->shared.firstTuple,
1303 pergroup = entry->pergroup;
1306 * Finalize each aggregate calculation, and stash results in the
1307 * per-output-tuple context.
1309 for (aggno = 0; aggno < aggstate->numaggs; aggno++)
1311 AggStatePerAgg peraggstate = &peragg[aggno];
1312 AggStatePerGroup pergroupstate = &pergroup[aggno];
1314 Assert(peraggstate->numSortCols == 0);
1315 finalize_aggregate(aggstate, peraggstate, pergroupstate,
1316 &aggvalues[aggno], &aggnulls[aggno]);
1320 * Use the representative input tuple for any references to
1321 * non-aggregated input columns in the qual and tlist.
1323 econtext->ecxt_outertuple = firstSlot;
1326 * Check the qual (HAVING clause); if the group does not match, ignore
1327 * it and loop back to try to process another group.
1329 if (ExecQual(aggstate->ss.ps.qual, econtext, false))
1332 * Form and return a projection tuple using the aggregate results
1333 * and the representative input tuple.
1335 TupleTableSlot *result;
1336 ExprDoneCond isDone;
1338 result = ExecProject(aggstate->ss.ps.ps_ProjInfo, &isDone);
1340 if (isDone != ExprEndResult)
1342 aggstate->ss.ps.ps_TupFromTlist =
1343 (isDone == ExprMultipleResult);
1349 /* No more groups */
1353 /* -----------------
1356 * Creates the run-time information for the agg node produced by the
1357 * planner and initializes its outer subtree
1361 ExecInitAgg(Agg *node, EState *estate, int eflags)
1364 AggStatePerAgg peragg;
1366 ExprContext *econtext;
1371 /* check for unsupported flags */
1372 Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
1375 * create state structure
1377 aggstate = makeNode(AggState);
1378 aggstate->ss.ps.plan = (Plan *) node;
1379 aggstate->ss.ps.state = estate;
1381 aggstate->aggs = NIL;
1382 aggstate->numaggs = 0;
1383 aggstate->eqfunctions = NULL;
1384 aggstate->hashfunctions = NULL;
1385 aggstate->peragg = NULL;
1386 aggstate->agg_done = false;
1387 aggstate->pergroup = NULL;
1388 aggstate->grp_firstTuple = NULL;
1389 aggstate->hashtable = NULL;
1392 * Create expression contexts. We need two, one for per-input-tuple
1393 * processing and one for per-output-tuple processing. We cheat a little
1394 * by using ExecAssignExprContext() to build both.
1396 ExecAssignExprContext(estate, &aggstate->ss.ps);
1397 aggstate->tmpcontext = aggstate->ss.ps.ps_ExprContext;
1398 ExecAssignExprContext(estate, &aggstate->ss.ps);
1401 * We also need a long-lived memory context for holding hashtable data
1402 * structures and transition values. NOTE: the details of what is stored
1403 * in aggcontext and what is stored in the regular per-query memory
1404 * context are driven by a simple decision: we want to reset the
1405 * aggcontext at group boundaries (if not hashing) and in ExecReScanAgg
1406 * to recover no-longer-wanted space.
1408 aggstate->aggcontext =
1409 AllocSetContextCreate(CurrentMemoryContext,
1411 ALLOCSET_DEFAULT_MINSIZE,
1412 ALLOCSET_DEFAULT_INITSIZE,
1413 ALLOCSET_DEFAULT_MAXSIZE);
1416 * tuple table initialization
1418 ExecInitScanTupleSlot(estate, &aggstate->ss);
1419 ExecInitResultTupleSlot(estate, &aggstate->ss.ps);
1420 aggstate->hashslot = ExecInitExtraTupleSlot(estate);
1423 * initialize child expressions
1425 * Note: ExecInitExpr finds Aggrefs for us, and also checks that no aggs
1426 * contain other agg calls in their arguments. This would make no sense
1427 * under SQL semantics anyway (and it's forbidden by the spec). Because
1428 * that is true, we don't need to worry about evaluating the aggs in any
1431 aggstate->ss.ps.targetlist = (List *)
1432 ExecInitExpr((Expr *) node->plan.targetlist,
1433 (PlanState *) aggstate);
1434 aggstate->ss.ps.qual = (List *)
1435 ExecInitExpr((Expr *) node->plan.qual,
1436 (PlanState *) aggstate);
1439 * initialize child nodes
1441 * If we are doing a hashed aggregation then the child plan does not need
1442 * to handle REWIND efficiently; see ExecReScanAgg.
1444 if (node->aggstrategy == AGG_HASHED)
1445 eflags &= ~EXEC_FLAG_REWIND;
1446 outerPlan = outerPlan(node);
1447 outerPlanState(aggstate) = ExecInitNode(outerPlan, estate, eflags);
1450 * initialize source tuple type.
1452 ExecAssignScanTypeFromOuterPlan(&aggstate->ss);
1455 * Initialize result tuple type and projection info.
1457 ExecAssignResultTypeFromTL(&aggstate->ss.ps);
1458 ExecAssignProjectionInfo(&aggstate->ss.ps, NULL);
1460 aggstate->ss.ps.ps_TupFromTlist = false;
1463 * get the count of aggregates in targetlist and quals
1465 numaggs = aggstate->numaggs;
1466 Assert(numaggs == list_length(aggstate->aggs));
1470 * This is not an error condition: we might be using the Agg node just
1471 * to do hash-based grouping. Even in the regular case,
1472 * constant-expression simplification could optimize away all of the
1473 * Aggrefs in the targetlist and qual. So keep going, but force local
1474 * copy of numaggs positive so that palloc()s below don't choke.
1480 * If we are grouping, precompute fmgr lookup data for inner loop. We need
1481 * both equality and hashing functions to do it by hashing, but only
1482 * equality if not hashing.
1484 if (node->numCols > 0)
1486 if (node->aggstrategy == AGG_HASHED)
1487 execTuplesHashPrepare(node->numCols,
1489 &aggstate->eqfunctions,
1490 &aggstate->hashfunctions);
1492 aggstate->eqfunctions =
1493 execTuplesMatchPrepare(node->numCols,
1494 node->grpOperators);
1498 * Set up aggregate-result storage in the output expr context, and also
1499 * allocate my private per-agg working storage
1501 econtext = aggstate->ss.ps.ps_ExprContext;
1502 econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs);
1503 econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs);
1505 peragg = (AggStatePerAgg) palloc0(sizeof(AggStatePerAggData) * numaggs);
1506 aggstate->peragg = peragg;
1508 if (node->aggstrategy == AGG_HASHED)
1510 build_hash_table(aggstate);
1511 aggstate->table_filled = false;
1512 /* Compute the columns we actually need to hash on */
1513 aggstate->hash_needed = find_hash_columns(aggstate);
1517 AggStatePerGroup pergroup;
1519 pergroup = (AggStatePerGroup) palloc0(sizeof(AggStatePerGroupData) * numaggs);
1520 aggstate->pergroup = pergroup;
1524 * Perform lookups of aggregate function info, and initialize the
1525 * unchanging fields of the per-agg data. We also detect duplicate
1526 * aggregates (for example, "SELECT sum(x) ... HAVING sum(x) > 0"). When
1527 * duplicates are detected, we only make an AggStatePerAgg struct for the
1528 * first one. The clones are simply pointed at the same result entry by
1529 * giving them duplicate aggno values.
1532 foreach(l, aggstate->aggs)
1534 AggrefExprState *aggrefstate = (AggrefExprState *) lfirst(l);
1535 Aggref *aggref = (Aggref *) aggrefstate->xprstate.expr;
1536 AggStatePerAgg peraggstate;
1537 Oid inputTypes[FUNC_MAX_ARGS];
1541 int numDistinctCols;
1544 Form_pg_aggregate aggform;
1546 AclResult aclresult;
1555 /* Planner should have assigned aggregate to correct level */
1556 Assert(aggref->agglevelsup == 0);
1558 /* Look for a previous duplicate aggregate */
1559 for (i = 0; i <= aggno; i++)
1561 if (equal(aggref, peragg[i].aggref) &&
1562 !contain_volatile_functions((Node *) aggref))
1567 /* Found a match to an existing entry, so just mark it */
1568 aggrefstate->aggno = i;
1572 /* Nope, so assign a new PerAgg record */
1573 peraggstate = &peragg[++aggno];
1575 /* Mark Aggref state node with assigned index in the result array */
1576 aggrefstate->aggno = aggno;
1578 /* Fill in the peraggstate data */
1579 peraggstate->aggrefstate = aggrefstate;
1580 peraggstate->aggref = aggref;
1581 numInputs = list_length(aggref->args);
1582 peraggstate->numInputs = numInputs;
1583 peraggstate->sortstate = NULL;
1586 * Get actual datatypes of the inputs. These could be different from
1587 * the agg's declared input types, when the agg accepts ANY or a
1591 foreach(lc, aggref->args)
1593 TargetEntry *tle = (TargetEntry *) lfirst(lc);
1596 inputTypes[numArguments++] = exprType((Node *) tle->expr);
1598 peraggstate->numArguments = numArguments;
1600 aggTuple = SearchSysCache(AGGFNOID,
1601 ObjectIdGetDatum(aggref->aggfnoid),
1603 if (!HeapTupleIsValid(aggTuple))
1604 elog(ERROR, "cache lookup failed for aggregate %u",
1606 aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);
1608 /* Check permission to call aggregate function */
1609 aclresult = pg_proc_aclcheck(aggref->aggfnoid, GetUserId(),
1611 if (aclresult != ACLCHECK_OK)
1612 aclcheck_error(aclresult, ACL_KIND_PROC,
1613 get_func_name(aggref->aggfnoid));
1615 peraggstate->transfn_oid = transfn_oid = aggform->aggtransfn;
1616 peraggstate->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
1618 /* Check that aggregate owner has permission to call component fns */
1620 HeapTuple procTuple;
1623 procTuple = SearchSysCache(PROCOID,
1624 ObjectIdGetDatum(aggref->aggfnoid),
1626 if (!HeapTupleIsValid(procTuple))
1627 elog(ERROR, "cache lookup failed for function %u",
1629 aggOwner = ((Form_pg_proc) GETSTRUCT(procTuple))->proowner;
1630 ReleaseSysCache(procTuple);
1632 aclresult = pg_proc_aclcheck(transfn_oid, aggOwner,
1634 if (aclresult != ACLCHECK_OK)
1635 aclcheck_error(aclresult, ACL_KIND_PROC,
1636 get_func_name(transfn_oid));
1637 if (OidIsValid(finalfn_oid))
1639 aclresult = pg_proc_aclcheck(finalfn_oid, aggOwner,
1641 if (aclresult != ACLCHECK_OK)
1642 aclcheck_error(aclresult, ACL_KIND_PROC,
1643 get_func_name(finalfn_oid));
1647 /* resolve actual type of transition state, if polymorphic */
1648 aggtranstype = aggform->aggtranstype;
1649 if (IsPolymorphicType(aggtranstype))
1651 /* have to fetch the agg's declared input types... */
1652 Oid *declaredArgTypes;
1655 (void) get_func_signature(aggref->aggfnoid,
1656 &declaredArgTypes, &agg_nargs);
1657 Assert(agg_nargs == numArguments);
1658 aggtranstype = enforce_generic_type_consistency(inputTypes,
1663 pfree(declaredArgTypes);
1666 /* build expression trees using actual argument & result types */
1667 build_aggregate_fnexprs(inputTypes,
1676 fmgr_info(transfn_oid, &peraggstate->transfn);
1677 peraggstate->transfn.fn_expr = (Node *) transfnexpr;
1679 if (OidIsValid(finalfn_oid))
1681 fmgr_info(finalfn_oid, &peraggstate->finalfn);
1682 peraggstate->finalfn.fn_expr = (Node *) finalfnexpr;
1685 get_typlenbyval(aggref->aggtype,
1686 &peraggstate->resulttypeLen,
1687 &peraggstate->resulttypeByVal);
1688 get_typlenbyval(aggtranstype,
1689 &peraggstate->transtypeLen,
1690 &peraggstate->transtypeByVal);
1693 * initval is potentially null, so don't try to access it as a struct
1694 * field. Must do it the hard way with SysCacheGetAttr.
1696 textInitVal = SysCacheGetAttr(AGGFNOID, aggTuple,
1697 Anum_pg_aggregate_agginitval,
1698 &peraggstate->initValueIsNull);
1700 if (peraggstate->initValueIsNull)
1701 peraggstate->initValue = (Datum) 0;
1703 peraggstate->initValue = GetAggInitVal(textInitVal,
1707 * If the transfn is strict and the initval is NULL, make sure input
1708 * type and transtype are the same (or at least binary-compatible), so
1709 * that it's OK to use the first input value as the initial
1710 * transValue. This should have been checked at agg definition time,
1711 * but just in case...
1713 if (peraggstate->transfn.fn_strict && peraggstate->initValueIsNull)
1715 if (numArguments < 1 ||
1716 !IsBinaryCoercible(inputTypes[0], aggtranstype))
1718 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1719 errmsg("aggregate %u needs to have compatible input type and transition type",
1720 aggref->aggfnoid)));
1724 * Get a tupledesc corresponding to the inputs (including sort
1725 * expressions) of the agg.
1727 peraggstate->evaldesc = ExecTypeFromTL(aggref->args, false);
1729 /* Create slot we're going to do argument evaluation in */
1730 peraggstate->evalslot = ExecInitExtraTupleSlot(estate);
1731 ExecSetSlotDescriptor(peraggstate->evalslot, peraggstate->evaldesc);
1733 /* Set up projection info for evaluation */
1734 peraggstate->evalproj = ExecBuildProjectionInfo(aggrefstate->args,
1735 aggstate->tmpcontext,
1736 peraggstate->evalslot,
1740 * If we're doing either DISTINCT or ORDER BY, then we have a list
1741 * of SortGroupClause nodes; fish out the data in them and
1742 * stick them into arrays.
1744 * Note that by construction, if there is a DISTINCT clause then the
1745 * ORDER BY clause is a prefix of it (see transformDistinctClause).
1747 if (aggref->aggdistinct)
1749 sortlist = aggref->aggdistinct;
1750 numSortCols = numDistinctCols = list_length(sortlist);
1751 Assert(numSortCols >= list_length(aggref->aggorder));
1755 sortlist = aggref->aggorder;
1756 numSortCols = list_length(sortlist);
1757 numDistinctCols = 0;
1760 peraggstate->numSortCols = numSortCols;
1761 peraggstate->numDistinctCols = numDistinctCols;
1763 if (numSortCols > 0)
1766 * We don't implement DISTINCT or ORDER BY aggs in the HASHED case
1769 Assert(node->aggstrategy != AGG_HASHED);
1771 /* If we have only one input, we need its len/byval info. */
1774 get_typlenbyval(inputTypes[0],
1775 &peraggstate->inputtypeLen,
1776 &peraggstate->inputtypeByVal);
1778 else if (numDistinctCols > 0)
1780 /* we will need an extra slot to store prior values */
1781 peraggstate->uniqslot = ExecInitExtraTupleSlot(estate);
1782 ExecSetSlotDescriptor(peraggstate->uniqslot,
1783 peraggstate->evaldesc);
1786 /* Extract the sort information for use later */
1787 peraggstate->sortColIdx =
1788 (AttrNumber *) palloc(numSortCols * sizeof(AttrNumber));
1789 peraggstate->sortOperators =
1790 (Oid *) palloc(numSortCols * sizeof(Oid));
1791 peraggstate->sortNullsFirst =
1792 (bool *) palloc(numSortCols * sizeof(bool));
1795 foreach(lc, sortlist)
1797 SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc);
1798 TargetEntry *tle = get_sortgroupclause_tle(sortcl,
1801 /* the parser should have made sure of this */
1802 Assert(OidIsValid(sortcl->sortop));
1804 peraggstate->sortColIdx[i] = tle->resno;
1805 peraggstate->sortOperators[i] = sortcl->sortop;
1806 peraggstate->sortNullsFirst[i] = sortcl->nulls_first;
1809 Assert(i == numSortCols);
1812 if (aggref->aggdistinct)
1814 Assert(numArguments > 0);
1817 * We need the equal function for each DISTINCT comparison we will
1820 peraggstate->equalfns =
1821 (FmgrInfo *) palloc(numDistinctCols * sizeof(FmgrInfo));
1824 foreach(lc, aggref->aggdistinct)
1826 SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc);
1828 fmgr_info(get_opcode(sortcl->eqop), &peraggstate->equalfns[i]);
1831 Assert(i == numDistinctCols);
1834 ReleaseSysCache(aggTuple);
1837 /* Update numaggs to match number of unique aggregates found */
1838 aggstate->numaggs = aggno + 1;
1844 GetAggInitVal(Datum textInitVal, Oid transtype)
1851 getTypeInputInfo(transtype, &typinput, &typioparam);
1852 strInitVal = TextDatumGetCString(textInitVal);
1853 initVal = OidInputFunctionCall(typinput, strInitVal,
1860 ExecEndAgg(AggState *node)
1862 PlanState *outerPlan;
1865 /* Make sure we have closed any open tuplesorts */
1866 for (aggno = 0; aggno < node->numaggs; aggno++)
1868 AggStatePerAgg peraggstate = &node->peragg[aggno];
1870 if (peraggstate->sortstate)
1871 tuplesort_end(peraggstate->sortstate);
1875 * Free both the expr contexts.
1877 ExecFreeExprContext(&node->ss.ps);
1878 node->ss.ps.ps_ExprContext = node->tmpcontext;
1879 ExecFreeExprContext(&node->ss.ps);
1881 /* clean up tuple table */
1882 ExecClearTuple(node->ss.ss_ScanTupleSlot);
1884 MemoryContextDelete(node->aggcontext);
1886 outerPlan = outerPlanState(node);
1887 ExecEndNode(outerPlan);
1891 ExecReScanAgg(AggState *node, ExprContext *exprCtxt)
1893 ExprContext *econtext = node->ss.ps.ps_ExprContext;
1896 node->agg_done = false;
1898 node->ss.ps.ps_TupFromTlist = false;
1900 if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
1903 * In the hashed case, if we haven't yet built the hash table then we
1904 * can just return; nothing done yet, so nothing to undo. If subnode's
1905 * chgParam is not NULL then it will be re-scanned by ExecProcNode,
1906 * else no reason to re-scan it at all.
1908 if (!node->table_filled)
1912 * If we do have the hash table and the subplan does not have any
1913 * parameter changes, then we can just rescan the existing hash table;
1914 * no need to build it again.
1916 if (((PlanState *) node)->lefttree->chgParam == NULL)
1918 ResetTupleHashIterator(node->hashtable, &node->hashiter);
1923 /* Make sure we have closed any open tuplesorts */
1924 for (aggno = 0; aggno < node->numaggs; aggno++)
1926 AggStatePerAgg peraggstate = &node->peragg[aggno];
1928 if (peraggstate->sortstate)
1929 tuplesort_end(peraggstate->sortstate);
1930 peraggstate->sortstate = NULL;
1933 /* Release first tuple of group, if we have made a copy */
1934 if (node->grp_firstTuple != NULL)
1936 heap_freetuple(node->grp_firstTuple);
1937 node->grp_firstTuple = NULL;
1940 /* Forget current agg values */
1941 MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numaggs);
1942 MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numaggs);
1945 * Release all temp storage. Note that with AGG_HASHED, the hash table is
1946 * allocated in a sub-context of the aggcontext. We're going to rebuild
1947 * the hash table from scratch, so we need to use
1948 * MemoryContextResetAndDeleteChildren() to avoid leaking the old hash
1949 * table's memory context header.
1951 MemoryContextResetAndDeleteChildren(node->aggcontext);
1953 if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
1955 /* Rebuild an empty hash table */
1956 build_hash_table(node);
1957 node->table_filled = false;
1962 * Reset the per-group state (in particular, mark transvalues null)
1964 MemSet(node->pergroup, 0,
1965 sizeof(AggStatePerGroupData) * node->numaggs);
1969 * if chgParam of subnode is not null then plan will be re-scanned by
1970 * first ExecProcNode.
1972 if (((PlanState *) node)->lefttree->chgParam == NULL)
1973 ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
1977 * AggCheckCallContext - test if a SQL function is being called as an aggregate
1979 * The transition and/or final functions of an aggregate may want to verify
1980 * that they are being called as aggregates, rather than as plain SQL
1981 * functions. They should use this function to do so. The return value
1982 * is nonzero if being called as an aggregate, or zero if not. (Specific
1983 * nonzero values are AGG_CONTEXT_AGGREGATE or AGG_CONTEXT_WINDOW, but more
1984 * values could conceivably appear in future.)
1986 * If aggcontext isn't NULL, the function also stores at *aggcontext the
1987 * identity of the memory context that aggregate transition values are
1991 AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
1993 if (fcinfo->context && IsA(fcinfo->context, AggState))
1996 *aggcontext = ((AggState *) fcinfo->context)->aggcontext;
1997 return AGG_CONTEXT_AGGREGATE;
1999 if (fcinfo->context && IsA(fcinfo->context, WindowAggState))
2002 *aggcontext = ((WindowAggState *) fcinfo->context)->wincontext;
2003 return AGG_CONTEXT_WINDOW;
2006 /* this is just to prevent "uninitialized variable" warnings */
2013 * aggregate_dummy - dummy execution routine for aggregate functions
2015 * This function is listed as the implementation (prosrc field) of pg_proc
2016 * entries for aggregate functions. Its only purpose is to throw an error
2017 * if someone mistakenly executes such a function in the normal way.
2019 * Perhaps someday we could assign real meaning to the prosrc field of
2023 aggregate_dummy(PG_FUNCTION_ARGS)
2025 elog(ERROR, "aggregate function %u called as normal function",
2026 fcinfo->flinfo->fn_oid);
2027 return (Datum) 0; /* keep compiler quiet */