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-2011, PostgreSQL Global Development Group
71 * Portions Copyright (c) 1994, Regents of the University of California
74 * src/backend/executor/nodeAgg.c
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 /* Input collation derived for aggregate */
136 /* number of sorting columns */
139 /* number of sorting columns to consider in DISTINCT comparisons */
140 /* (this is either zero or the same as numSortCols) */
143 /* deconstructed sorting information (arrays of length numSortCols) */
144 AttrNumber *sortColIdx;
147 bool *sortNullsFirst;
150 * fmgr lookup data for input columns' equality operators --- only
151 * set/used when aggregate has DISTINCT flag. Note that these are in
152 * order of sort column index, not parameter index.
154 FmgrInfo *equalfns; /* array of length numDistinctCols */
157 * initial value from pg_aggregate entry
160 bool initValueIsNull;
163 * We need the len and byval info for the agg's input, result, and
164 * transition data types in order to know how to copy/delete values.
166 * Note that the info for the input type is used only when handling
167 * DISTINCT aggs with just one argument, so there is only one input type.
177 * Stuff for evaluation of inputs. We used to just use ExecEvalExpr, but
178 * with the addition of ORDER BY we now need at least a slot for passing
179 * data to the sort object, which requires a tupledesc, so we might as
180 * well go whole hog and use ExecProject too.
182 TupleDesc evaldesc; /* descriptor of input tuples */
183 ProjectionInfo *evalproj; /* projection machinery */
186 * Slots for holding the evaluated input arguments. These are set up
187 * during ExecInitAgg() and then used for each input row.
189 TupleTableSlot *evalslot; /* current input tuple */
190 TupleTableSlot *uniqslot; /* used for multi-column DISTINCT */
193 * These values are working state that is initialized at the start of an
194 * input tuple group and updated for each input tuple.
196 * For a simple (non DISTINCT/ORDER BY) aggregate, we just feed the input
197 * values straight to the transition function. If it's DISTINCT or
198 * requires ORDER BY, we pass the input values into a Tuplesort object;
199 * then at completion of the input tuple group, we scan the sorted values,
200 * eliminate duplicates if needed, and run the transition function on the
204 Tuplesortstate *sortstate; /* sort object, if DISTINCT or ORDER BY */
205 } AggStatePerAggData;
208 * AggStatePerGroupData - per-aggregate-per-group working state
210 * These values are working state that is initialized at the start of
211 * an input tuple group and updated for each input tuple.
213 * In AGG_PLAIN and AGG_SORTED modes, we have a single array of these
214 * structs (pointed to by aggstate->pergroup); we re-use the array for
215 * each input group, if it's AGG_SORTED mode. In AGG_HASHED mode, the
216 * hash table contains an array of these structs for each tuple group.
218 * Logically, the sortstate field belongs in this struct, but we do not
219 * keep it here for space reasons: we don't support DISTINCT aggregates
220 * in AGG_HASHED mode, so there's no reason to use up a pointer field
221 * in every entry of the hashtable.
223 typedef struct AggStatePerGroupData
225 Datum transValue; /* current transition value */
226 bool transValueIsNull;
228 bool noTransValue; /* true if transValue not set yet */
231 * Note: noTransValue initially has the same value as transValueIsNull,
232 * and if true both are cleared to false at the same time. They are not
233 * the same though: if transfn later returns a NULL, we want to keep that
234 * NULL and not auto-replace it with a later input value. Only the first
235 * non-NULL input will be auto-substituted.
237 } AggStatePerGroupData;
240 * To implement hashed aggregation, we need a hashtable that stores a
241 * representative tuple and an array of AggStatePerGroup structs for each
242 * distinct set of GROUP BY column values. We compute the hash key from
243 * the GROUP BY columns.
245 typedef struct AggHashEntryData *AggHashEntry;
247 typedef struct AggHashEntryData
249 TupleHashEntryData shared; /* common header for hash table entries */
250 /* per-aggregate transition status array - must be last! */
251 AggStatePerGroupData pergroup[1]; /* VARIABLE LENGTH ARRAY */
252 } AggHashEntryData; /* VARIABLE LENGTH STRUCT */
255 static void initialize_aggregates(AggState *aggstate,
256 AggStatePerAgg peragg,
257 AggStatePerGroup pergroup);
258 static void advance_transition_function(AggState *aggstate,
259 AggStatePerAgg peraggstate,
260 AggStatePerGroup pergroupstate,
261 FunctionCallInfoData *fcinfo);
262 static void advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup);
263 static void process_ordered_aggregate_single(AggState *aggstate,
264 AggStatePerAgg peraggstate,
265 AggStatePerGroup pergroupstate);
266 static void process_ordered_aggregate_multi(AggState *aggstate,
267 AggStatePerAgg peraggstate,
268 AggStatePerGroup pergroupstate);
269 static void finalize_aggregate(AggState *aggstate,
270 AggStatePerAgg peraggstate,
271 AggStatePerGroup pergroupstate,
272 Datum *resultVal, bool *resultIsNull);
273 static Bitmapset *find_unaggregated_cols(AggState *aggstate);
274 static bool find_unaggregated_cols_walker(Node *node, Bitmapset **colnos);
275 static void build_hash_table(AggState *aggstate);
276 static AggHashEntry lookup_hash_entry(AggState *aggstate,
277 TupleTableSlot *inputslot);
278 static TupleTableSlot *agg_retrieve_direct(AggState *aggstate);
279 static void agg_fill_hash_table(AggState *aggstate);
280 static TupleTableSlot *agg_retrieve_hash_table(AggState *aggstate);
281 static Datum GetAggInitVal(Datum textInitVal, Oid transtype);
285 * Initialize all aggregates for a new group of input values.
287 * When called, CurrentMemoryContext should be the per-query context.
290 initialize_aggregates(AggState *aggstate,
291 AggStatePerAgg peragg,
292 AggStatePerGroup pergroup)
296 for (aggno = 0; aggno < aggstate->numaggs; aggno++)
298 AggStatePerAgg peraggstate = &peragg[aggno];
299 AggStatePerGroup pergroupstate = &pergroup[aggno];
302 * Start a fresh sort operation for each DISTINCT/ORDER BY aggregate.
304 if (peraggstate->numSortCols > 0)
307 * In case of rescan, maybe there could be an uncompleted sort
308 * operation? Clean it up if so.
310 if (peraggstate->sortstate)
311 tuplesort_end(peraggstate->sortstate);
314 * We use a plain Datum sorter when there's a single input column;
315 * otherwise sort the full tuple. (See comments for
316 * process_ordered_aggregate_single.)
318 peraggstate->sortstate =
319 (peraggstate->numInputs == 1) ?
320 tuplesort_begin_datum(peraggstate->evaldesc->attrs[0]->atttypid,
321 peraggstate->sortOperators[0],
322 peraggstate->sortCollations[0],
323 peraggstate->sortNullsFirst[0],
325 tuplesort_begin_heap(peraggstate->evaldesc,
326 peraggstate->numSortCols,
327 peraggstate->sortColIdx,
328 peraggstate->sortOperators,
329 peraggstate->sortCollations,
330 peraggstate->sortNullsFirst,
335 * (Re)set transValue to the initial value.
337 * Note that when the initial value is pass-by-ref, we must copy it
338 * (into the aggcontext) since we will pfree the transValue later.
340 if (peraggstate->initValueIsNull)
341 pergroupstate->transValue = peraggstate->initValue;
344 MemoryContext oldContext;
346 oldContext = MemoryContextSwitchTo(aggstate->aggcontext);
347 pergroupstate->transValue = datumCopy(peraggstate->initValue,
348 peraggstate->transtypeByVal,
349 peraggstate->transtypeLen);
350 MemoryContextSwitchTo(oldContext);
352 pergroupstate->transValueIsNull = peraggstate->initValueIsNull;
355 * If the initial value for the transition state doesn't exist in the
356 * pg_aggregate table then we will let the first non-NULL value
357 * returned from the outer procNode become the initial value. (This is
358 * useful for aggregates like max() and min().) The noTransValue flag
359 * signals that we still need to do this.
361 pergroupstate->noTransValue = peraggstate->initValueIsNull;
366 * Given new input value(s), advance the transition function of an aggregate.
368 * The new values (and null flags) have been preloaded into argument positions
369 * 1 and up in fcinfo, so that we needn't copy them again to pass to the
370 * transition function. No other fields of fcinfo are assumed valid.
372 * It doesn't matter which memory context this is called in.
375 advance_transition_function(AggState *aggstate,
376 AggStatePerAgg peraggstate,
377 AggStatePerGroup pergroupstate,
378 FunctionCallInfoData *fcinfo)
380 int numArguments = peraggstate->numArguments;
381 MemoryContext oldContext;
385 if (peraggstate->transfn.fn_strict)
388 * For a strict transfn, nothing happens when there's a NULL input; we
389 * just keep the prior transValue.
391 for (i = 1; i <= numArguments; i++)
393 if (fcinfo->argnull[i])
396 if (pergroupstate->noTransValue)
399 * transValue has not been initialized. This is the first non-NULL
400 * input value. We use it as the initial value for transValue. (We
401 * already checked that the agg's input type is binary-compatible
402 * with its transtype, so straight copy here is OK.)
404 * We must copy the datum into aggcontext if it is pass-by-ref. We
405 * do not need to pfree the old transValue, since it's NULL.
407 oldContext = MemoryContextSwitchTo(aggstate->aggcontext);
408 pergroupstate->transValue = datumCopy(fcinfo->arg[1],
409 peraggstate->transtypeByVal,
410 peraggstate->transtypeLen);
411 pergroupstate->transValueIsNull = false;
412 pergroupstate->noTransValue = false;
413 MemoryContextSwitchTo(oldContext);
416 if (pergroupstate->transValueIsNull)
419 * Don't call a strict function with NULL inputs. Note it is
420 * possible to get here despite the above tests, if the transfn is
421 * strict *and* returned a NULL on a prior cycle. If that happens
422 * we will propagate the NULL all the way to the end.
428 /* We run the transition functions in per-input-tuple memory context */
429 oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
432 * OK to call the transition function
434 InitFunctionCallInfoData(*fcinfo, &(peraggstate->transfn),
436 peraggstate->aggCollation,
437 (void *) aggstate, NULL);
438 fcinfo->arg[0] = pergroupstate->transValue;
439 fcinfo->argnull[0] = pergroupstate->transValueIsNull;
441 newVal = FunctionCallInvoke(fcinfo);
444 * If pass-by-ref datatype, must copy the new value into aggcontext and
445 * pfree the prior transValue. But if transfn returned a pointer to its
446 * first input, we don't need to do anything.
448 if (!peraggstate->transtypeByVal &&
449 DatumGetPointer(newVal) != DatumGetPointer(pergroupstate->transValue))
453 MemoryContextSwitchTo(aggstate->aggcontext);
454 newVal = datumCopy(newVal,
455 peraggstate->transtypeByVal,
456 peraggstate->transtypeLen);
458 if (!pergroupstate->transValueIsNull)
459 pfree(DatumGetPointer(pergroupstate->transValue));
462 pergroupstate->transValue = newVal;
463 pergroupstate->transValueIsNull = fcinfo->isnull;
465 MemoryContextSwitchTo(oldContext);
469 * Advance all the aggregates for one input tuple. The input tuple
470 * has been stored in tmpcontext->ecxt_outertuple, so that it is accessible
471 * to ExecEvalExpr. pergroup is the array of per-group structs to use
472 * (this might be in a hashtable entry).
474 * When called, CurrentMemoryContext should be the per-query context.
477 advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
481 for (aggno = 0; aggno < aggstate->numaggs; aggno++)
483 AggStatePerAgg peraggstate = &aggstate->peragg[aggno];
484 AggStatePerGroup pergroupstate = &pergroup[aggno];
485 int nargs = peraggstate->numArguments;
487 TupleTableSlot *slot;
489 /* Evaluate the current input expressions for this aggregate */
490 slot = ExecProject(peraggstate->evalproj, NULL);
492 if (peraggstate->numSortCols > 0)
494 /* DISTINCT and/or ORDER BY case */
495 Assert(slot->tts_nvalid == peraggstate->numInputs);
498 * If the transfn is strict, we want to check for nullity before
499 * storing the row in the sorter, to save space if there are a lot
500 * of nulls. Note that we must only check numArguments columns,
501 * not numInputs, since nullity in columns used only for sorting
502 * is not relevant here.
504 if (peraggstate->transfn.fn_strict)
506 for (i = 0; i < nargs; i++)
508 if (slot->tts_isnull[i])
515 /* OK, put the tuple into the tuplesort object */
516 if (peraggstate->numInputs == 1)
517 tuplesort_putdatum(peraggstate->sortstate,
519 slot->tts_isnull[0]);
521 tuplesort_puttupleslot(peraggstate->sortstate, slot);
525 /* We can apply the transition function immediately */
526 FunctionCallInfoData fcinfo;
528 /* Load values into fcinfo */
529 /* Start from 1, since the 0th arg will be the transition value */
530 Assert(slot->tts_nvalid >= nargs);
531 for (i = 0; i < nargs; i++)
533 fcinfo.arg[i + 1] = slot->tts_values[i];
534 fcinfo.argnull[i + 1] = slot->tts_isnull[i];
537 advance_transition_function(aggstate, peraggstate, pergroupstate,
545 * Run the transition function for a DISTINCT or ORDER BY aggregate
546 * with only one input. This is called after we have completed
547 * entering all the input values into the sort object. We complete the
548 * sort, read out the values in sorted order, and run the transition
549 * function on each value (applying DISTINCT if appropriate).
551 * Note that the strictness of the transition function was checked when
552 * entering the values into the sort, so we don't check it again here;
553 * we just apply standard SQL DISTINCT logic.
555 * The one-input case is handled separately from the multi-input case
556 * for performance reasons: for single by-value inputs, such as the
557 * common case of count(distinct id), the tuplesort_getdatum code path
558 * is around 300% faster. (The speedup for by-reference types is less
559 * but still noticeable.)
561 * When called, CurrentMemoryContext should be the per-query context.
564 process_ordered_aggregate_single(AggState *aggstate,
565 AggStatePerAgg peraggstate,
566 AggStatePerGroup pergroupstate)
568 Datum oldVal = (Datum) 0;
569 bool oldIsNull = true;
570 bool haveOldVal = false;
571 MemoryContext workcontext = aggstate->tmpcontext->ecxt_per_tuple_memory;
572 MemoryContext oldContext;
573 bool isDistinct = (peraggstate->numDistinctCols > 0);
576 FunctionCallInfoData fcinfo;
578 Assert(peraggstate->numDistinctCols < 2);
580 tuplesort_performsort(peraggstate->sortstate);
582 /* Load the column into argument 1 (arg 0 will be transition value) */
583 newVal = fcinfo.arg + 1;
584 isNull = fcinfo.argnull + 1;
587 * Note: if input type is pass-by-ref, the datums returned by the sort are
588 * freshly palloc'd in the per-query context, so we must be careful to
589 * pfree them when they are no longer needed.
592 while (tuplesort_getdatum(peraggstate->sortstate, true,
596 * Clear and select the working context for evaluation of the equality
597 * function and transition function.
599 MemoryContextReset(workcontext);
600 oldContext = MemoryContextSwitchTo(workcontext);
603 * If DISTINCT mode, and not distinct from prior, skip it.
605 * Note: we assume equality functions don't care about collation.
609 ((oldIsNull && *isNull) ||
610 (!oldIsNull && !*isNull &&
611 DatumGetBool(FunctionCall2(&peraggstate->equalfns[0],
614 /* equal to prior, so forget this one */
615 if (!peraggstate->inputtypeByVal && !*isNull)
616 pfree(DatumGetPointer(*newVal));
620 advance_transition_function(aggstate, peraggstate, pergroupstate,
622 /* forget the old value, if any */
623 if (!oldIsNull && !peraggstate->inputtypeByVal)
624 pfree(DatumGetPointer(oldVal));
625 /* and remember the new one for subsequent equality checks */
631 MemoryContextSwitchTo(oldContext);
634 if (!oldIsNull && !peraggstate->inputtypeByVal)
635 pfree(DatumGetPointer(oldVal));
637 tuplesort_end(peraggstate->sortstate);
638 peraggstate->sortstate = NULL;
642 * Run the transition function for a DISTINCT or ORDER BY aggregate
643 * with more than one input. This is called after we have completed
644 * entering all the input values into the sort object. We complete the
645 * sort, read out the values in sorted order, and run the transition
646 * function on each value (applying DISTINCT if appropriate).
648 * When called, CurrentMemoryContext should be the per-query context.
651 process_ordered_aggregate_multi(AggState *aggstate,
652 AggStatePerAgg peraggstate,
653 AggStatePerGroup pergroupstate)
655 MemoryContext workcontext = aggstate->tmpcontext->ecxt_per_tuple_memory;
656 FunctionCallInfoData fcinfo;
657 TupleTableSlot *slot1 = peraggstate->evalslot;
658 TupleTableSlot *slot2 = peraggstate->uniqslot;
659 int numArguments = peraggstate->numArguments;
660 int numDistinctCols = peraggstate->numDistinctCols;
661 bool haveOldValue = false;
664 tuplesort_performsort(peraggstate->sortstate);
666 ExecClearTuple(slot1);
668 ExecClearTuple(slot2);
670 while (tuplesort_gettupleslot(peraggstate->sortstate, true, slot1))
673 * Extract the first numArguments as datums to pass to the transfn.
674 * (This will help execTuplesMatch too, so do it immediately.)
676 slot_getsomeattrs(slot1, numArguments);
678 if (numDistinctCols == 0 ||
680 !execTuplesMatch(slot1, slot2,
682 peraggstate->sortColIdx,
683 peraggstate->equalfns,
686 /* Load values into fcinfo */
687 /* Start from 1, since the 0th arg will be the transition value */
688 for (i = 0; i < numArguments; i++)
690 fcinfo.arg[i + 1] = slot1->tts_values[i];
691 fcinfo.argnull[i + 1] = slot1->tts_isnull[i];
694 advance_transition_function(aggstate, peraggstate, pergroupstate,
697 if (numDistinctCols > 0)
699 /* swap the slot pointers to retain the current tuple */
700 TupleTableSlot *tmpslot = slot2;
708 /* Reset context each time, unless execTuplesMatch did it for us */
709 if (numDistinctCols == 0)
710 MemoryContextReset(workcontext);
712 ExecClearTuple(slot1);
716 ExecClearTuple(slot2);
718 tuplesort_end(peraggstate->sortstate);
719 peraggstate->sortstate = NULL;
723 * Compute the final value of one aggregate.
725 * The finalfunction will be run, and the result delivered, in the
726 * output-tuple context; caller's CurrentMemoryContext does not matter.
729 finalize_aggregate(AggState *aggstate,
730 AggStatePerAgg peraggstate,
731 AggStatePerGroup pergroupstate,
732 Datum *resultVal, bool *resultIsNull)
734 MemoryContext oldContext;
736 oldContext = MemoryContextSwitchTo(aggstate->ss.ps.ps_ExprContext->ecxt_per_tuple_memory);
739 * Apply the agg's finalfn if one is provided, else return transValue.
741 if (OidIsValid(peraggstate->finalfn_oid))
743 FunctionCallInfoData fcinfo;
745 InitFunctionCallInfoData(fcinfo, &(peraggstate->finalfn), 1,
746 peraggstate->aggCollation,
747 (void *) aggstate, NULL);
748 fcinfo.arg[0] = pergroupstate->transValue;
749 fcinfo.argnull[0] = pergroupstate->transValueIsNull;
750 if (fcinfo.flinfo->fn_strict && pergroupstate->transValueIsNull)
752 /* don't call a strict function with NULL inputs */
753 *resultVal = (Datum) 0;
754 *resultIsNull = true;
758 *resultVal = FunctionCallInvoke(&fcinfo);
759 *resultIsNull = fcinfo.isnull;
764 *resultVal = pergroupstate->transValue;
765 *resultIsNull = pergroupstate->transValueIsNull;
769 * If result is pass-by-ref, make sure it is in the right context.
771 if (!peraggstate->resulttypeByVal && !*resultIsNull &&
772 !MemoryContextContains(CurrentMemoryContext,
773 DatumGetPointer(*resultVal)))
774 *resultVal = datumCopy(*resultVal,
775 peraggstate->resulttypeByVal,
776 peraggstate->resulttypeLen);
778 MemoryContextSwitchTo(oldContext);
782 * find_unaggregated_cols
783 * Construct a bitmapset of the column numbers of un-aggregated Vars
784 * appearing in our targetlist and qual (HAVING clause)
787 find_unaggregated_cols(AggState *aggstate)
789 Agg *node = (Agg *) aggstate->ss.ps.plan;
793 (void) find_unaggregated_cols_walker((Node *) node->plan.targetlist,
795 (void) find_unaggregated_cols_walker((Node *) node->plan.qual,
801 find_unaggregated_cols_walker(Node *node, Bitmapset **colnos)
807 Var *var = (Var *) node;
809 /* setrefs.c should have set the varno to OUTER */
810 Assert(var->varno == OUTER);
811 Assert(var->varlevelsup == 0);
812 *colnos = bms_add_member(*colnos, var->varattno);
815 if (IsA(node, Aggref)) /* do not descend into aggregate exprs */
817 return expression_tree_walker(node, find_unaggregated_cols_walker,
822 * Initialize the hash table to empty.
824 * The hash table always lives in the aggcontext memory context.
827 build_hash_table(AggState *aggstate)
829 Agg *node = (Agg *) aggstate->ss.ps.plan;
830 MemoryContext tmpmem = aggstate->tmpcontext->ecxt_per_tuple_memory;
833 Assert(node->aggstrategy == AGG_HASHED);
834 Assert(node->numGroups > 0);
836 entrysize = sizeof(AggHashEntryData) +
837 (aggstate->numaggs - 1) * sizeof(AggStatePerGroupData);
839 aggstate->hashtable = BuildTupleHashTable(node->numCols,
841 aggstate->eqfunctions,
842 aggstate->hashfunctions,
845 aggstate->aggcontext,
850 * Create a list of the tuple columns that actually need to be stored in
851 * hashtable entries. The incoming tuples from the child plan node will
852 * contain grouping columns, other columns referenced in our targetlist and
853 * qual, columns used to compute the aggregate functions, and perhaps just
854 * junk columns we don't use at all. Only columns of the first two types
855 * need to be stored in the hashtable, and getting rid of the others can
856 * make the table entries significantly smaller. To avoid messing up Var
857 * numbering, we keep the same tuple descriptor for hashtable entries as the
858 * incoming tuples have, but set unwanted columns to NULL in the tuples that
861 * To eliminate duplicates, we build a bitmapset of the needed columns, then
862 * convert it to an integer list (cheaper to scan at runtime). The list is
863 * in decreasing order so that the first entry is the largest;
864 * lookup_hash_entry depends on this to use slot_getsomeattrs correctly.
865 * Note that the list is preserved over ExecReScanAgg, so we allocate it in
866 * the per-query context (unlike the hash table itself).
868 * Note: at present, searching the tlist/qual is not really necessary since
869 * the parser should disallow any unaggregated references to ungrouped
870 * columns. However, the search will be needed when we add support for
871 * SQL99 semantics that allow use of "functionally dependent" columns that
872 * haven't been explicitly grouped by.
875 find_hash_columns(AggState *aggstate)
877 Agg *node = (Agg *) aggstate->ss.ps.plan;
882 /* Find Vars that will be needed in tlist and qual */
883 colnos = find_unaggregated_cols(aggstate);
884 /* Add in all the grouping columns */
885 for (i = 0; i < node->numCols; i++)
886 colnos = bms_add_member(colnos, node->grpColIdx[i]);
887 /* Convert to list, using lcons so largest element ends up first */
889 while ((i = bms_first_member(colnos)) >= 0)
890 collist = lcons_int(i, collist);
897 * Estimate per-hash-table-entry overhead for the planner.
899 * Note that the estimate does not include space for pass-by-reference
900 * transition data values, nor for the representative tuple of each group.
903 hash_agg_entry_size(int numAggs)
907 /* This must match build_hash_table */
908 entrysize = sizeof(AggHashEntryData) +
909 (numAggs - 1) * sizeof(AggStatePerGroupData);
910 entrysize = MAXALIGN(entrysize);
911 /* Account for hashtable overhead (assuming fill factor = 1) */
912 entrysize += 3 * sizeof(void *);
917 * Find or create a hashtable entry for the tuple group containing the
920 * When called, CurrentMemoryContext should be the per-query context.
923 lookup_hash_entry(AggState *aggstate, TupleTableSlot *inputslot)
925 TupleTableSlot *hashslot = aggstate->hashslot;
930 /* if first time through, initialize hashslot by cloning input slot */
931 if (hashslot->tts_tupleDescriptor == NULL)
933 ExecSetSlotDescriptor(hashslot, inputslot->tts_tupleDescriptor);
934 /* Make sure all unused columns are NULLs */
935 ExecStoreAllNullTuple(hashslot);
938 /* transfer just the needed columns into hashslot */
939 slot_getsomeattrs(inputslot, linitial_int(aggstate->hash_needed));
940 foreach(l, aggstate->hash_needed)
942 int varNumber = lfirst_int(l) - 1;
944 hashslot->tts_values[varNumber] = inputslot->tts_values[varNumber];
945 hashslot->tts_isnull[varNumber] = inputslot->tts_isnull[varNumber];
948 /* find or create the hashtable entry using the filtered tuple */
949 entry = (AggHashEntry) LookupTupleHashEntry(aggstate->hashtable,
955 /* initialize aggregates for new tuple group */
956 initialize_aggregates(aggstate, aggstate->peragg, entry->pergroup);
965 * ExecAgg receives tuples from its outer subplan and aggregates over
966 * the appropriate attribute for each aggregate function use (Aggref
967 * node) appearing in the targetlist or qual of the node. The number
968 * of tuples to aggregate over depends on whether grouped or plain
969 * aggregation is selected. In grouped aggregation, we produce a result
970 * row for each group; in plain aggregation there's a single result row
971 * for the whole query. In either case, the value of each aggregate is
972 * stored in the expression context to be used when ExecProject evaluates
976 ExecAgg(AggState *node)
979 * Check to see if we're still projecting out tuples from a previous agg
980 * tuple (because there is a function-returning-set in the projection
981 * expressions). If so, try to project another one.
983 if (node->ss.ps.ps_TupFromTlist)
985 TupleTableSlot *result;
988 result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
989 if (isDone == ExprMultipleResult)
991 /* Done with that source tuple... */
992 node->ss.ps.ps_TupFromTlist = false;
996 * Exit if nothing left to do. (We must do the ps_TupFromTlist check
997 * first, because in some cases agg_done gets set before we emit the final
998 * aggregate tuple, and we have to finish running SRFs for it.)
1003 /* Dispatch based on strategy */
1004 if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
1006 if (!node->table_filled)
1007 agg_fill_hash_table(node);
1008 return agg_retrieve_hash_table(node);
1011 return agg_retrieve_direct(node);
1015 * ExecAgg for non-hashed case
1017 static TupleTableSlot *
1018 agg_retrieve_direct(AggState *aggstate)
1020 Agg *node = (Agg *) aggstate->ss.ps.plan;
1021 PlanState *outerPlan;
1022 ExprContext *econtext;
1023 ExprContext *tmpcontext;
1026 AggStatePerAgg peragg;
1027 AggStatePerGroup pergroup;
1028 TupleTableSlot *outerslot;
1029 TupleTableSlot *firstSlot;
1033 * get state info from node
1035 outerPlan = outerPlanState(aggstate);
1036 /* econtext is the per-output-tuple expression context */
1037 econtext = aggstate->ss.ps.ps_ExprContext;
1038 aggvalues = econtext->ecxt_aggvalues;
1039 aggnulls = econtext->ecxt_aggnulls;
1040 /* tmpcontext is the per-input-tuple expression context */
1041 tmpcontext = aggstate->tmpcontext;
1042 peragg = aggstate->peragg;
1043 pergroup = aggstate->pergroup;
1044 firstSlot = aggstate->ss.ss_ScanTupleSlot;
1047 * We loop retrieving groups until we find one matching
1048 * aggstate->ss.ps.qual
1050 while (!aggstate->agg_done)
1053 * If we don't already have the first tuple of the new group, fetch it
1054 * from the outer plan.
1056 if (aggstate->grp_firstTuple == NULL)
1058 outerslot = ExecProcNode(outerPlan);
1059 if (!TupIsNull(outerslot))
1062 * Make a copy of the first input tuple; we will use this for
1063 * comparisons (in group mode) and for projection.
1065 aggstate->grp_firstTuple = ExecCopySlotTuple(outerslot);
1069 /* outer plan produced no tuples at all */
1070 aggstate->agg_done = true;
1071 /* If we are grouping, we should produce no tuples too */
1072 if (node->aggstrategy != AGG_PLAIN)
1078 * Clear the per-output-tuple context for each group, as well as
1079 * aggcontext (which contains any pass-by-ref transvalues of the old
1080 * group). We also clear any child contexts of the aggcontext; some
1081 * aggregate functions store working state in such contexts.
1083 ResetExprContext(econtext);
1085 MemoryContextResetAndDeleteChildren(aggstate->aggcontext);
1088 * Initialize working state for a new input tuple group
1090 initialize_aggregates(aggstate, peragg, pergroup);
1092 if (aggstate->grp_firstTuple != NULL)
1095 * Store the copied first input tuple in the tuple table slot
1096 * reserved for it. The tuple will be deleted when it is cleared
1099 ExecStoreTuple(aggstate->grp_firstTuple,
1103 aggstate->grp_firstTuple = NULL; /* don't keep two pointers */
1105 /* set up for first advance_aggregates call */
1106 tmpcontext->ecxt_outertuple = firstSlot;
1109 * Process each outer-plan tuple, and then fetch the next one,
1110 * until we exhaust the outer plan or cross a group boundary.
1114 advance_aggregates(aggstate, pergroup);
1116 /* Reset per-input-tuple context after each tuple */
1117 ResetExprContext(tmpcontext);
1119 outerslot = ExecProcNode(outerPlan);
1120 if (TupIsNull(outerslot))
1122 /* no more outer-plan tuples available */
1123 aggstate->agg_done = true;
1126 /* set up for next advance_aggregates call */
1127 tmpcontext->ecxt_outertuple = outerslot;
1130 * If we are grouping, check whether we've crossed a group
1133 if (node->aggstrategy == AGG_SORTED)
1135 if (!execTuplesMatch(firstSlot,
1137 node->numCols, node->grpColIdx,
1138 aggstate->eqfunctions,
1139 tmpcontext->ecxt_per_tuple_memory))
1142 * Save the first input tuple of the next group.
1144 aggstate->grp_firstTuple = ExecCopySlotTuple(outerslot);
1152 * Done scanning input tuple group. Finalize each aggregate
1153 * calculation, and stash results in the per-output-tuple context.
1155 for (aggno = 0; aggno < aggstate->numaggs; aggno++)
1157 AggStatePerAgg peraggstate = &peragg[aggno];
1158 AggStatePerGroup pergroupstate = &pergroup[aggno];
1160 if (peraggstate->numSortCols > 0)
1162 if (peraggstate->numInputs == 1)
1163 process_ordered_aggregate_single(aggstate,
1167 process_ordered_aggregate_multi(aggstate,
1172 finalize_aggregate(aggstate, peraggstate, pergroupstate,
1173 &aggvalues[aggno], &aggnulls[aggno]);
1177 * Use the representative input tuple for any references to
1178 * non-aggregated input columns in the qual and tlist. (If we are not
1179 * grouping, and there are no input rows at all, we will come here
1180 * with an empty firstSlot ... but if not grouping, there can't be any
1181 * references to non-aggregated input columns, so no problem.)
1183 econtext->ecxt_outertuple = firstSlot;
1186 * Check the qual (HAVING clause); if the group does not match, ignore
1187 * it and loop back to try to process another group.
1189 if (ExecQual(aggstate->ss.ps.qual, econtext, false))
1192 * Form and return a projection tuple using the aggregate results
1193 * and the representative input tuple.
1195 TupleTableSlot *result;
1196 ExprDoneCond isDone;
1198 result = ExecProject(aggstate->ss.ps.ps_ProjInfo, &isDone);
1200 if (isDone != ExprEndResult)
1202 aggstate->ss.ps.ps_TupFromTlist =
1203 (isDone == ExprMultipleResult);
1209 /* No more groups */
1214 * ExecAgg for hashed case: phase 1, read input and build hash table
1217 agg_fill_hash_table(AggState *aggstate)
1219 PlanState *outerPlan;
1220 ExprContext *tmpcontext;
1222 TupleTableSlot *outerslot;
1225 * get state info from node
1227 outerPlan = outerPlanState(aggstate);
1228 /* tmpcontext is the per-input-tuple expression context */
1229 tmpcontext = aggstate->tmpcontext;
1232 * Process each outer-plan tuple, and then fetch the next one, until we
1233 * exhaust the outer plan.
1237 outerslot = ExecProcNode(outerPlan);
1238 if (TupIsNull(outerslot))
1240 /* set up for advance_aggregates call */
1241 tmpcontext->ecxt_outertuple = outerslot;
1243 /* Find or build hashtable entry for this tuple's group */
1244 entry = lookup_hash_entry(aggstate, outerslot);
1246 /* Advance the aggregates */
1247 advance_aggregates(aggstate, entry->pergroup);
1249 /* Reset per-input-tuple context after each tuple */
1250 ResetExprContext(tmpcontext);
1253 aggstate->table_filled = true;
1254 /* Initialize to walk the hash table */
1255 ResetTupleHashIterator(aggstate->hashtable, &aggstate->hashiter);
1259 * ExecAgg for hashed case: phase 2, retrieving groups from hash table
1261 static TupleTableSlot *
1262 agg_retrieve_hash_table(AggState *aggstate)
1264 ExprContext *econtext;
1267 AggStatePerAgg peragg;
1268 AggStatePerGroup pergroup;
1270 TupleTableSlot *firstSlot;
1274 * get state info from node
1276 /* econtext is the per-output-tuple expression context */
1277 econtext = aggstate->ss.ps.ps_ExprContext;
1278 aggvalues = econtext->ecxt_aggvalues;
1279 aggnulls = econtext->ecxt_aggnulls;
1280 peragg = aggstate->peragg;
1281 firstSlot = aggstate->ss.ss_ScanTupleSlot;
1284 * We loop retrieving groups until we find one satisfying
1285 * aggstate->ss.ps.qual
1287 while (!aggstate->agg_done)
1290 * Find the next entry in the hash table
1292 entry = (AggHashEntry) ScanTupleHashTable(&aggstate->hashiter);
1295 /* No more entries in hashtable, so done */
1296 aggstate->agg_done = TRUE;
1301 * Clear the per-output-tuple context for each group
1303 ResetExprContext(econtext);
1306 * Store the copied first input tuple in the tuple table slot reserved
1307 * for it, so that it can be used in ExecProject.
1309 ExecStoreMinimalTuple(entry->shared.firstTuple,
1313 pergroup = entry->pergroup;
1316 * Finalize each aggregate calculation, and stash results in the
1317 * per-output-tuple context.
1319 for (aggno = 0; aggno < aggstate->numaggs; aggno++)
1321 AggStatePerAgg peraggstate = &peragg[aggno];
1322 AggStatePerGroup pergroupstate = &pergroup[aggno];
1324 Assert(peraggstate->numSortCols == 0);
1325 finalize_aggregate(aggstate, peraggstate, pergroupstate,
1326 &aggvalues[aggno], &aggnulls[aggno]);
1330 * Use the representative input tuple for any references to
1331 * non-aggregated input columns in the qual and tlist.
1333 econtext->ecxt_outertuple = firstSlot;
1336 * Check the qual (HAVING clause); if the group does not match, ignore
1337 * it and loop back to try to process another group.
1339 if (ExecQual(aggstate->ss.ps.qual, econtext, false))
1342 * Form and return a projection tuple using the aggregate results
1343 * and the representative input tuple.
1345 TupleTableSlot *result;
1346 ExprDoneCond isDone;
1348 result = ExecProject(aggstate->ss.ps.ps_ProjInfo, &isDone);
1350 if (isDone != ExprEndResult)
1352 aggstate->ss.ps.ps_TupFromTlist =
1353 (isDone == ExprMultipleResult);
1359 /* No more groups */
1363 /* -----------------
1366 * Creates the run-time information for the agg node produced by the
1367 * planner and initializes its outer subtree
1371 ExecInitAgg(Agg *node, EState *estate, int eflags)
1374 AggStatePerAgg peragg;
1376 ExprContext *econtext;
1381 /* check for unsupported flags */
1382 Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
1385 * create state structure
1387 aggstate = makeNode(AggState);
1388 aggstate->ss.ps.plan = (Plan *) node;
1389 aggstate->ss.ps.state = estate;
1391 aggstate->aggs = NIL;
1392 aggstate->numaggs = 0;
1393 aggstate->eqfunctions = NULL;
1394 aggstate->hashfunctions = NULL;
1395 aggstate->peragg = NULL;
1396 aggstate->agg_done = false;
1397 aggstate->pergroup = NULL;
1398 aggstate->grp_firstTuple = NULL;
1399 aggstate->hashtable = NULL;
1402 * Create expression contexts. We need two, one for per-input-tuple
1403 * processing and one for per-output-tuple processing. We cheat a little
1404 * by using ExecAssignExprContext() to build both.
1406 ExecAssignExprContext(estate, &aggstate->ss.ps);
1407 aggstate->tmpcontext = aggstate->ss.ps.ps_ExprContext;
1408 ExecAssignExprContext(estate, &aggstate->ss.ps);
1411 * We also need a long-lived memory context for holding hashtable data
1412 * structures and transition values. NOTE: the details of what is stored
1413 * in aggcontext and what is stored in the regular per-query memory
1414 * context are driven by a simple decision: we want to reset the
1415 * aggcontext at group boundaries (if not hashing) and in ExecReScanAgg to
1416 * recover no-longer-wanted space.
1418 aggstate->aggcontext =
1419 AllocSetContextCreate(CurrentMemoryContext,
1421 ALLOCSET_DEFAULT_MINSIZE,
1422 ALLOCSET_DEFAULT_INITSIZE,
1423 ALLOCSET_DEFAULT_MAXSIZE);
1426 * tuple table initialization
1428 ExecInitScanTupleSlot(estate, &aggstate->ss);
1429 ExecInitResultTupleSlot(estate, &aggstate->ss.ps);
1430 aggstate->hashslot = ExecInitExtraTupleSlot(estate);
1433 * initialize child expressions
1435 * Note: ExecInitExpr finds Aggrefs for us, and also checks that no aggs
1436 * contain other agg calls in their arguments. This would make no sense
1437 * under SQL semantics anyway (and it's forbidden by the spec). Because
1438 * that is true, we don't need to worry about evaluating the aggs in any
1441 aggstate->ss.ps.targetlist = (List *)
1442 ExecInitExpr((Expr *) node->plan.targetlist,
1443 (PlanState *) aggstate);
1444 aggstate->ss.ps.qual = (List *)
1445 ExecInitExpr((Expr *) node->plan.qual,
1446 (PlanState *) aggstate);
1449 * initialize child nodes
1451 * If we are doing a hashed aggregation then the child plan does not need
1452 * to handle REWIND efficiently; see ExecReScanAgg.
1454 if (node->aggstrategy == AGG_HASHED)
1455 eflags &= ~EXEC_FLAG_REWIND;
1456 outerPlan = outerPlan(node);
1457 outerPlanState(aggstate) = ExecInitNode(outerPlan, estate, eflags);
1460 * initialize source tuple type.
1462 ExecAssignScanTypeFromOuterPlan(&aggstate->ss);
1465 * Initialize result tuple type and projection info.
1467 ExecAssignResultTypeFromTL(&aggstate->ss.ps);
1468 ExecAssignProjectionInfo(&aggstate->ss.ps, NULL);
1470 aggstate->ss.ps.ps_TupFromTlist = false;
1473 * get the count of aggregates in targetlist and quals
1475 numaggs = aggstate->numaggs;
1476 Assert(numaggs == list_length(aggstate->aggs));
1480 * This is not an error condition: we might be using the Agg node just
1481 * to do hash-based grouping. Even in the regular case,
1482 * constant-expression simplification could optimize away all of the
1483 * Aggrefs in the targetlist and qual. So keep going, but force local
1484 * copy of numaggs positive so that palloc()s below don't choke.
1490 * If we are grouping, precompute fmgr lookup data for inner loop. We need
1491 * both equality and hashing functions to do it by hashing, but only
1492 * equality if not hashing.
1494 if (node->numCols > 0)
1496 if (node->aggstrategy == AGG_HASHED)
1497 execTuplesHashPrepare(node->numCols,
1499 &aggstate->eqfunctions,
1500 &aggstate->hashfunctions);
1502 aggstate->eqfunctions =
1503 execTuplesMatchPrepare(node->numCols,
1504 node->grpOperators);
1508 * Set up aggregate-result storage in the output expr context, and also
1509 * allocate my private per-agg working storage
1511 econtext = aggstate->ss.ps.ps_ExprContext;
1512 econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs);
1513 econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs);
1515 peragg = (AggStatePerAgg) palloc0(sizeof(AggStatePerAggData) * numaggs);
1516 aggstate->peragg = peragg;
1518 if (node->aggstrategy == AGG_HASHED)
1520 build_hash_table(aggstate);
1521 aggstate->table_filled = false;
1522 /* Compute the columns we actually need to hash on */
1523 aggstate->hash_needed = find_hash_columns(aggstate);
1527 AggStatePerGroup pergroup;
1529 pergroup = (AggStatePerGroup) palloc0(sizeof(AggStatePerGroupData) * numaggs);
1530 aggstate->pergroup = pergroup;
1534 * Perform lookups of aggregate function info, and initialize the
1535 * unchanging fields of the per-agg data. We also detect duplicate
1536 * aggregates (for example, "SELECT sum(x) ... HAVING sum(x) > 0"). When
1537 * duplicates are detected, we only make an AggStatePerAgg struct for the
1538 * first one. The clones are simply pointed at the same result entry by
1539 * giving them duplicate aggno values.
1542 foreach(l, aggstate->aggs)
1544 AggrefExprState *aggrefstate = (AggrefExprState *) lfirst(l);
1545 Aggref *aggref = (Aggref *) aggrefstate->xprstate.expr;
1546 AggStatePerAgg peraggstate;
1547 Oid inputTypes[FUNC_MAX_ARGS];
1551 int numDistinctCols;
1554 Form_pg_aggregate aggform;
1556 AclResult aclresult;
1565 /* Planner should have assigned aggregate to correct level */
1566 Assert(aggref->agglevelsup == 0);
1568 /* Look for a previous duplicate aggregate */
1569 for (i = 0; i <= aggno; i++)
1571 if (equal(aggref, peragg[i].aggref) &&
1572 !contain_volatile_functions((Node *) aggref))
1577 /* Found a match to an existing entry, so just mark it */
1578 aggrefstate->aggno = i;
1582 /* Nope, so assign a new PerAgg record */
1583 peraggstate = &peragg[++aggno];
1585 /* Mark Aggref state node with assigned index in the result array */
1586 aggrefstate->aggno = aggno;
1588 /* Fill in the peraggstate data */
1589 peraggstate->aggrefstate = aggrefstate;
1590 peraggstate->aggref = aggref;
1591 numInputs = list_length(aggref->args);
1592 peraggstate->numInputs = numInputs;
1593 peraggstate->sortstate = NULL;
1596 * Get actual datatypes of the inputs. These could be different from
1597 * the agg's declared input types, when the agg accepts ANY or a
1601 foreach(lc, aggref->args)
1603 TargetEntry *tle = (TargetEntry *) lfirst(lc);
1606 inputTypes[numArguments++] = exprType((Node *) tle->expr);
1608 peraggstate->numArguments = numArguments;
1610 aggTuple = SearchSysCache1(AGGFNOID,
1611 ObjectIdGetDatum(aggref->aggfnoid));
1612 if (!HeapTupleIsValid(aggTuple))
1613 elog(ERROR, "cache lookup failed for aggregate %u",
1615 aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);
1617 /* Check permission to call aggregate function */
1618 aclresult = pg_proc_aclcheck(aggref->aggfnoid, GetUserId(),
1620 if (aclresult != ACLCHECK_OK)
1621 aclcheck_error(aclresult, ACL_KIND_PROC,
1622 get_func_name(aggref->aggfnoid));
1624 peraggstate->transfn_oid = transfn_oid = aggform->aggtransfn;
1625 peraggstate->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
1627 /* Check that aggregate owner has permission to call component fns */
1629 HeapTuple procTuple;
1632 procTuple = SearchSysCache1(PROCOID,
1633 ObjectIdGetDatum(aggref->aggfnoid));
1634 if (!HeapTupleIsValid(procTuple))
1635 elog(ERROR, "cache lookup failed for function %u",
1637 aggOwner = ((Form_pg_proc) GETSTRUCT(procTuple))->proowner;
1638 ReleaseSysCache(procTuple);
1640 aclresult = pg_proc_aclcheck(transfn_oid, aggOwner,
1642 if (aclresult != ACLCHECK_OK)
1643 aclcheck_error(aclresult, ACL_KIND_PROC,
1644 get_func_name(transfn_oid));
1645 if (OidIsValid(finalfn_oid))
1647 aclresult = pg_proc_aclcheck(finalfn_oid, aggOwner,
1649 if (aclresult != ACLCHECK_OK)
1650 aclcheck_error(aclresult, ACL_KIND_PROC,
1651 get_func_name(finalfn_oid));
1655 /* resolve actual type of transition state, if polymorphic */
1656 aggtranstype = aggform->aggtranstype;
1657 if (IsPolymorphicType(aggtranstype))
1659 /* have to fetch the agg's declared input types... */
1660 Oid *declaredArgTypes;
1663 (void) get_func_signature(aggref->aggfnoid,
1664 &declaredArgTypes, &agg_nargs);
1665 Assert(agg_nargs == numArguments);
1666 aggtranstype = enforce_generic_type_consistency(inputTypes,
1671 pfree(declaredArgTypes);
1674 /* build expression trees using actual argument & result types */
1675 build_aggregate_fnexprs(inputTypes,
1679 aggref->inputcollid,
1685 fmgr_info(transfn_oid, &peraggstate->transfn);
1686 fmgr_info_set_expr((Node *) transfnexpr, &peraggstate->transfn);
1688 if (OidIsValid(finalfn_oid))
1690 fmgr_info(finalfn_oid, &peraggstate->finalfn);
1691 fmgr_info_set_expr((Node *) finalfnexpr, &peraggstate->finalfn);
1694 peraggstate->aggCollation = aggref->inputcollid;
1696 get_typlenbyval(aggref->aggtype,
1697 &peraggstate->resulttypeLen,
1698 &peraggstate->resulttypeByVal);
1699 get_typlenbyval(aggtranstype,
1700 &peraggstate->transtypeLen,
1701 &peraggstate->transtypeByVal);
1704 * initval is potentially null, so don't try to access it as a struct
1705 * field. Must do it the hard way with SysCacheGetAttr.
1707 textInitVal = SysCacheGetAttr(AGGFNOID, aggTuple,
1708 Anum_pg_aggregate_agginitval,
1709 &peraggstate->initValueIsNull);
1711 if (peraggstate->initValueIsNull)
1712 peraggstate->initValue = (Datum) 0;
1714 peraggstate->initValue = GetAggInitVal(textInitVal,
1718 * If the transfn is strict and the initval is NULL, make sure input
1719 * type and transtype are the same (or at least binary-compatible), so
1720 * that it's OK to use the first input value as the initial
1721 * transValue. This should have been checked at agg definition time,
1722 * but just in case...
1724 if (peraggstate->transfn.fn_strict && peraggstate->initValueIsNull)
1726 if (numArguments < 1 ||
1727 !IsBinaryCoercible(inputTypes[0], aggtranstype))
1729 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1730 errmsg("aggregate %u needs to have compatible input type and transition type",
1731 aggref->aggfnoid)));
1735 * Get a tupledesc corresponding to the inputs (including sort
1736 * expressions) of the agg.
1738 peraggstate->evaldesc = ExecTypeFromTL(aggref->args, false);
1740 /* Create slot we're going to do argument evaluation in */
1741 peraggstate->evalslot = ExecInitExtraTupleSlot(estate);
1742 ExecSetSlotDescriptor(peraggstate->evalslot, peraggstate->evaldesc);
1744 /* Set up projection info for evaluation */
1745 peraggstate->evalproj = ExecBuildProjectionInfo(aggrefstate->args,
1746 aggstate->tmpcontext,
1747 peraggstate->evalslot,
1751 * If we're doing either DISTINCT or ORDER BY, then we have a list of
1752 * SortGroupClause nodes; fish out the data in them and stick them
1755 * Note that by construction, if there is a DISTINCT clause then the
1756 * ORDER BY clause is a prefix of it (see transformDistinctClause).
1758 if (aggref->aggdistinct)
1760 sortlist = aggref->aggdistinct;
1761 numSortCols = numDistinctCols = list_length(sortlist);
1762 Assert(numSortCols >= list_length(aggref->aggorder));
1766 sortlist = aggref->aggorder;
1767 numSortCols = list_length(sortlist);
1768 numDistinctCols = 0;
1771 peraggstate->numSortCols = numSortCols;
1772 peraggstate->numDistinctCols = numDistinctCols;
1774 if (numSortCols > 0)
1777 * We don't implement DISTINCT or ORDER BY aggs in the HASHED case
1780 Assert(node->aggstrategy != AGG_HASHED);
1782 /* If we have only one input, we need its len/byval info. */
1785 get_typlenbyval(inputTypes[0],
1786 &peraggstate->inputtypeLen,
1787 &peraggstate->inputtypeByVal);
1789 else if (numDistinctCols > 0)
1791 /* we will need an extra slot to store prior values */
1792 peraggstate->uniqslot = ExecInitExtraTupleSlot(estate);
1793 ExecSetSlotDescriptor(peraggstate->uniqslot,
1794 peraggstate->evaldesc);
1797 /* Extract the sort information for use later */
1798 peraggstate->sortColIdx =
1799 (AttrNumber *) palloc(numSortCols * sizeof(AttrNumber));
1800 peraggstate->sortOperators =
1801 (Oid *) palloc(numSortCols * sizeof(Oid));
1802 peraggstate->sortCollations =
1803 (Oid *) palloc(numSortCols * sizeof(Oid));
1804 peraggstate->sortNullsFirst =
1805 (bool *) palloc(numSortCols * sizeof(bool));
1808 foreach(lc, sortlist)
1810 SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc);
1811 TargetEntry *tle = get_sortgroupclause_tle(sortcl,
1814 /* the parser should have made sure of this */
1815 Assert(OidIsValid(sortcl->sortop));
1817 peraggstate->sortColIdx[i] = tle->resno;
1818 peraggstate->sortOperators[i] = sortcl->sortop;
1819 peraggstate->sortCollations[i] = exprCollation((Node *) tle->expr);
1820 peraggstate->sortNullsFirst[i] = sortcl->nulls_first;
1823 Assert(i == numSortCols);
1826 if (aggref->aggdistinct)
1828 Assert(numArguments > 0);
1831 * We need the equal function for each DISTINCT comparison we will
1834 peraggstate->equalfns =
1835 (FmgrInfo *) palloc(numDistinctCols * sizeof(FmgrInfo));
1838 foreach(lc, aggref->aggdistinct)
1840 SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc);
1842 fmgr_info(get_opcode(sortcl->eqop), &peraggstate->equalfns[i]);
1845 Assert(i == numDistinctCols);
1848 ReleaseSysCache(aggTuple);
1851 /* Update numaggs to match number of unique aggregates found */
1852 aggstate->numaggs = aggno + 1;
1858 GetAggInitVal(Datum textInitVal, Oid transtype)
1865 getTypeInputInfo(transtype, &typinput, &typioparam);
1866 strInitVal = TextDatumGetCString(textInitVal);
1867 initVal = OidInputFunctionCall(typinput, strInitVal,
1874 ExecEndAgg(AggState *node)
1876 PlanState *outerPlan;
1879 /* Make sure we have closed any open tuplesorts */
1880 for (aggno = 0; aggno < node->numaggs; aggno++)
1882 AggStatePerAgg peraggstate = &node->peragg[aggno];
1884 if (peraggstate->sortstate)
1885 tuplesort_end(peraggstate->sortstate);
1889 * Free both the expr contexts.
1891 ExecFreeExprContext(&node->ss.ps);
1892 node->ss.ps.ps_ExprContext = node->tmpcontext;
1893 ExecFreeExprContext(&node->ss.ps);
1895 /* clean up tuple table */
1896 ExecClearTuple(node->ss.ss_ScanTupleSlot);
1898 MemoryContextDelete(node->aggcontext);
1900 outerPlan = outerPlanState(node);
1901 ExecEndNode(outerPlan);
1905 ExecReScanAgg(AggState *node)
1907 ExprContext *econtext = node->ss.ps.ps_ExprContext;
1910 node->agg_done = false;
1912 node->ss.ps.ps_TupFromTlist = false;
1914 if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
1917 * In the hashed case, if we haven't yet built the hash table then we
1918 * can just return; nothing done yet, so nothing to undo. If subnode's
1919 * chgParam is not NULL then it will be re-scanned by ExecProcNode,
1920 * else no reason to re-scan it at all.
1922 if (!node->table_filled)
1926 * If we do have the hash table and the subplan does not have any
1927 * parameter changes, then we can just rescan the existing hash table;
1928 * no need to build it again.
1930 if (node->ss.ps.lefttree->chgParam == NULL)
1932 ResetTupleHashIterator(node->hashtable, &node->hashiter);
1937 /* Make sure we have closed any open tuplesorts */
1938 for (aggno = 0; aggno < node->numaggs; aggno++)
1940 AggStatePerAgg peraggstate = &node->peragg[aggno];
1942 if (peraggstate->sortstate)
1943 tuplesort_end(peraggstate->sortstate);
1944 peraggstate->sortstate = NULL;
1947 /* Release first tuple of group, if we have made a copy */
1948 if (node->grp_firstTuple != NULL)
1950 heap_freetuple(node->grp_firstTuple);
1951 node->grp_firstTuple = NULL;
1954 /* Forget current agg values */
1955 MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numaggs);
1956 MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numaggs);
1959 * Release all temp storage. Note that with AGG_HASHED, the hash table is
1960 * allocated in a sub-context of the aggcontext. We're going to rebuild
1961 * the hash table from scratch, so we need to use
1962 * MemoryContextResetAndDeleteChildren() to avoid leaking the old hash
1963 * table's memory context header.
1965 MemoryContextResetAndDeleteChildren(node->aggcontext);
1967 if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
1969 /* Rebuild an empty hash table */
1970 build_hash_table(node);
1971 node->table_filled = false;
1976 * Reset the per-group state (in particular, mark transvalues null)
1978 MemSet(node->pergroup, 0,
1979 sizeof(AggStatePerGroupData) * node->numaggs);
1983 * if chgParam of subnode is not null then plan will be re-scanned by
1984 * first ExecProcNode.
1986 if (node->ss.ps.lefttree->chgParam == NULL)
1987 ExecReScan(node->ss.ps.lefttree);
1991 * AggCheckCallContext - test if a SQL function is being called as an aggregate
1993 * The transition and/or final functions of an aggregate may want to verify
1994 * that they are being called as aggregates, rather than as plain SQL
1995 * functions. They should use this function to do so. The return value
1996 * is nonzero if being called as an aggregate, or zero if not. (Specific
1997 * nonzero values are AGG_CONTEXT_AGGREGATE or AGG_CONTEXT_WINDOW, but more
1998 * values could conceivably appear in future.)
2000 * If aggcontext isn't NULL, the function also stores at *aggcontext the
2001 * identity of the memory context that aggregate transition values are
2005 AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
2007 if (fcinfo->context && IsA(fcinfo->context, AggState))
2010 *aggcontext = ((AggState *) fcinfo->context)->aggcontext;
2011 return AGG_CONTEXT_AGGREGATE;
2013 if (fcinfo->context && IsA(fcinfo->context, WindowAggState))
2016 *aggcontext = ((WindowAggState *) fcinfo->context)->aggcontext;
2017 return AGG_CONTEXT_WINDOW;
2020 /* this is just to prevent "uninitialized variable" warnings */
2027 * aggregate_dummy - dummy execution routine for aggregate functions
2029 * This function is listed as the implementation (prosrc field) of pg_proc
2030 * entries for aggregate functions. Its only purpose is to throw an error
2031 * if someone mistakenly executes such a function in the normal way.
2033 * Perhaps someday we could assign real meaning to the prosrc field of
2037 aggregate_dummy(PG_FUNCTION_ARGS)
2039 elog(ERROR, "aggregate function %u called as normal function",
2040 fcinfo->flinfo->fn_oid);
2041 return (Datum) 0; /* keep compiler quiet */