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 transfunc is marked "strict" in pg_proc and initcond is NULL,
17 * then the first non-NULL input_value is assigned directly to transvalue,
18 * and transfunc isn't applied until the second non-NULL input_value.
19 * The agg's first input type and transtype must be the same in this case!
21 * If transfunc is marked "strict" then NULL input_values are skipped,
22 * keeping the previous transvalue. If transfunc is not strict then it
23 * is called for every input tuple and must deal with NULL initcond
24 * or NULL input_values for itself.
26 * If finalfunc is marked "strict" then it is not called when the
27 * ending transvalue is NULL, instead a NULL result is created
28 * automatically (this is just the usual handling of strict functions,
29 * of course). A non-strict finalfunc can make its own choice of
30 * what to return for a NULL ending transvalue.
32 * We compute aggregate input expressions and run the transition functions
33 * in a temporary econtext (aggstate->tmpcontext). This is reset at
34 * least once per input tuple, so when the transvalue datatype is
35 * pass-by-reference, we have to be careful to copy it into a longer-lived
36 * memory context, and free the prior value to avoid memory leakage.
37 * We store transvalues in the memory context aggstate->aggcontext,
38 * which is also used for the hashtable structures in AGG_HASHED mode.
39 * The node's regular econtext (aggstate->csstate.cstate.cs_ExprContext)
40 * is used to run finalize functions and compute the output tuple;
41 * this context can be reset once per output tuple.
43 * Beginning in PostgreSQL 8.1, the executor's AggState node is passed as
44 * the fmgr "context" value in all transfunc and finalfunc calls. It is
45 * not really intended that the transition functions will look into the
46 * AggState node, but they can use code like
47 * if (fcinfo->context && IsA(fcinfo->context, AggState))
48 * to verify that they are being called by nodeAgg.c and not as ordinary
49 * SQL functions. The main reason a transition function might want to know
50 * that is that it can avoid palloc'ing a fixed-size pass-by-ref transition
51 * value on every call: it can instead just scribble on and return its left
52 * input. Ordinarily it is completely forbidden for functions to modify
53 * pass-by-ref inputs, but in the aggregate case we know the left input is
54 * either the initial transition value or a previous function result, and
55 * in either case its value need not be preserved. See int8inc() for an
56 * example. Notice that advance_transition_function() is coded to avoid a
57 * data copy step when the previous transition value pointer is returned.
60 * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
61 * Portions Copyright (c) 1994, Regents of the University of California
64 * $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.153 2007/08/08 18:07:05 neilc Exp $
66 *-------------------------------------------------------------------------
71 #include "access/heapam.h"
72 #include "catalog/pg_aggregate.h"
73 #include "catalog/pg_proc.h"
74 #include "catalog/pg_type.h"
75 #include "executor/executor.h"
76 #include "executor/nodeAgg.h"
77 #include "miscadmin.h"
78 #include "optimizer/clauses.h"
79 #include "parser/parse_agg.h"
80 #include "parser/parse_coerce.h"
81 #include "parser/parse_expr.h"
82 #include "parser/parse_oper.h"
83 #include "utils/acl.h"
84 #include "utils/builtins.h"
85 #include "utils/lsyscache.h"
86 #include "utils/memutils.h"
87 #include "utils/syscache.h"
88 #include "utils/tuplesort.h"
89 #include "utils/datum.h"
93 * AggStatePerAggData - per-aggregate working state for the Agg scan
95 typedef struct AggStatePerAggData
98 * These values are set up during ExecInitAgg() and do not change
102 /* Links to Aggref expr and state nodes this working state is for */
103 AggrefExprState *aggrefstate;
106 /* number of input arguments for aggregate */
109 /* Oids of transfer functions */
111 Oid finalfn_oid; /* may be InvalidOid */
114 * fmgr lookup data for transfer functions --- only valid when
115 * corresponding oid is not InvalidOid. Note in particular that fn_strict
116 * flags are kept here.
122 * Type of input data and Oid of sort operator to use for it; only
123 * set/used when aggregate has DISTINCT flag. (These are not used
124 * directly by nodeAgg, but must be passed to the Tuplesort object.)
130 * fmgr lookup data for input type's equality operator --- only set/used
131 * when aggregate has DISTINCT flag.
136 * initial value from pg_aggregate entry
139 bool initValueIsNull;
142 * We need the len and byval info for the agg's input, result, and
143 * transition data types in order to know how to copy/delete values.
153 * These values are working state that is initialized at the start of an
154 * input tuple group and updated for each input tuple.
156 * For a simple (non DISTINCT) aggregate, we just feed the input values
157 * straight to the transition function. If it's DISTINCT, we pass the
158 * input values into a Tuplesort object; then at completion of the input
159 * tuple group, we scan the sorted values, eliminate duplicates, and run
160 * the transition function on the rest.
163 Tuplesortstate *sortstate; /* sort object, if a DISTINCT agg */
164 } AggStatePerAggData;
167 * AggStatePerGroupData - per-aggregate-per-group working state
169 * These values are working state that is initialized at the start of
170 * an input tuple group and updated for each input tuple.
172 * In AGG_PLAIN and AGG_SORTED modes, we have a single array of these
173 * structs (pointed to by aggstate->pergroup); we re-use the array for
174 * each input group, if it's AGG_SORTED mode. In AGG_HASHED mode, the
175 * hash table contains an array of these structs for each tuple group.
177 * Logically, the sortstate field belongs in this struct, but we do not
178 * keep it here for space reasons: we don't support DISTINCT aggregates
179 * in AGG_HASHED mode, so there's no reason to use up a pointer field
180 * in every entry of the hashtable.
182 typedef struct AggStatePerGroupData
184 Datum transValue; /* current transition value */
185 bool transValueIsNull;
187 bool noTransValue; /* true if transValue not set yet */
190 * Note: noTransValue initially has the same value as transValueIsNull,
191 * and if true both are cleared to false at the same time. They are not
192 * the same though: if transfn later returns a NULL, we want to keep that
193 * NULL and not auto-replace it with a later input value. Only the first
194 * non-NULL input will be auto-substituted.
196 } AggStatePerGroupData;
199 * To implement hashed aggregation, we need a hashtable that stores a
200 * representative tuple and an array of AggStatePerGroup structs for each
201 * distinct set of GROUP BY column values. We compute the hash key from
202 * the GROUP BY columns.
204 typedef struct AggHashEntryData *AggHashEntry;
206 typedef struct AggHashEntryData
208 TupleHashEntryData shared; /* common header for hash table entries */
209 /* per-aggregate transition status array - must be last! */
210 AggStatePerGroupData pergroup[1]; /* VARIABLE LENGTH ARRAY */
211 } AggHashEntryData; /* VARIABLE LENGTH STRUCT */
214 static void initialize_aggregates(AggState *aggstate,
215 AggStatePerAgg peragg,
216 AggStatePerGroup pergroup);
217 static void advance_transition_function(AggState *aggstate,
218 AggStatePerAgg peraggstate,
219 AggStatePerGroup pergroupstate,
220 FunctionCallInfoData *fcinfo);
221 static void advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup);
222 static void process_sorted_aggregate(AggState *aggstate,
223 AggStatePerAgg peraggstate,
224 AggStatePerGroup pergroupstate);
225 static void finalize_aggregate(AggState *aggstate,
226 AggStatePerAgg peraggstate,
227 AggStatePerGroup pergroupstate,
228 Datum *resultVal, bool *resultIsNull);
229 static Bitmapset *find_unaggregated_cols(AggState *aggstate);
230 static bool find_unaggregated_cols_walker(Node *node, Bitmapset **colnos);
231 static void build_hash_table(AggState *aggstate);
232 static AggHashEntry lookup_hash_entry(AggState *aggstate,
233 TupleTableSlot *inputslot);
234 static TupleTableSlot *agg_retrieve_direct(AggState *aggstate);
235 static void agg_fill_hash_table(AggState *aggstate);
236 static TupleTableSlot *agg_retrieve_hash_table(AggState *aggstate);
237 static Datum GetAggInitVal(Datum textInitVal, Oid transtype);
241 * Initialize all aggregates for a new group of input values.
243 * When called, CurrentMemoryContext should be the per-query context.
246 initialize_aggregates(AggState *aggstate,
247 AggStatePerAgg peragg,
248 AggStatePerGroup pergroup)
252 for (aggno = 0; aggno < aggstate->numaggs; aggno++)
254 AggStatePerAgg peraggstate = &peragg[aggno];
255 AggStatePerGroup pergroupstate = &pergroup[aggno];
256 Aggref *aggref = peraggstate->aggref;
259 * Start a fresh sort operation for each DISTINCT aggregate.
261 if (aggref->aggdistinct)
264 * In case of rescan, maybe there could be an uncompleted sort
265 * operation? Clean it up if so.
267 if (peraggstate->sortstate)
268 tuplesort_end(peraggstate->sortstate);
270 peraggstate->sortstate =
271 tuplesort_begin_datum(peraggstate->inputType,
272 peraggstate->sortOperator, false,
277 * If we are reinitializing after a group boundary, we have to free
278 * any prior transValue to avoid memory leakage. We must check not
279 * only the isnull flag but whether the pointer is NULL; since
280 * pergroupstate is initialized with palloc0, the initial condition
281 * has isnull = 0 and null pointer.
283 if (!peraggstate->transtypeByVal &&
284 !pergroupstate->transValueIsNull &&
285 DatumGetPointer(pergroupstate->transValue) != NULL)
286 pfree(DatumGetPointer(pergroupstate->transValue));
289 * (Re)set transValue to the initial value.
291 * Note that when the initial value is pass-by-ref, we must copy it
292 * (into the aggcontext) since we will pfree the transValue later.
294 if (peraggstate->initValueIsNull)
295 pergroupstate->transValue = peraggstate->initValue;
298 MemoryContext oldContext;
300 oldContext = MemoryContextSwitchTo(aggstate->aggcontext);
301 pergroupstate->transValue = datumCopy(peraggstate->initValue,
302 peraggstate->transtypeByVal,
303 peraggstate->transtypeLen);
304 MemoryContextSwitchTo(oldContext);
306 pergroupstate->transValueIsNull = peraggstate->initValueIsNull;
309 * If the initial value for the transition state doesn't exist in the
310 * pg_aggregate table then we will let the first non-NULL value
311 * returned from the outer procNode become the initial value. (This is
312 * useful for aggregates like max() and min().) The noTransValue flag
313 * signals that we still need to do this.
315 pergroupstate->noTransValue = peraggstate->initValueIsNull;
320 * Given new input value(s), advance the transition function of an aggregate.
322 * The new values (and null flags) have been preloaded into argument positions
323 * 1 and up in fcinfo, so that we needn't copy them again to pass to the
324 * transition function. No other fields of fcinfo are assumed valid.
326 * It doesn't matter which memory context this is called in.
329 advance_transition_function(AggState *aggstate,
330 AggStatePerAgg peraggstate,
331 AggStatePerGroup pergroupstate,
332 FunctionCallInfoData *fcinfo)
334 int numArguments = peraggstate->numArguments;
335 MemoryContext oldContext;
339 if (peraggstate->transfn.fn_strict)
342 * For a strict transfn, nothing happens when there's a NULL input; we
343 * just keep the prior transValue.
345 for (i = 1; i <= numArguments; i++)
347 if (fcinfo->argnull[i])
350 if (pergroupstate->noTransValue)
353 * transValue has not been initialized. This is the first non-NULL
354 * input value. We use it as the initial value for transValue. (We
355 * already checked that the agg's input type is binary-compatible
356 * with its transtype, so straight copy here is OK.)
358 * We must copy the datum into aggcontext if it is pass-by-ref. We
359 * do not need to pfree the old transValue, since it's NULL.
361 oldContext = MemoryContextSwitchTo(aggstate->aggcontext);
362 pergroupstate->transValue = datumCopy(fcinfo->arg[1],
363 peraggstate->transtypeByVal,
364 peraggstate->transtypeLen);
365 pergroupstate->transValueIsNull = false;
366 pergroupstate->noTransValue = false;
367 MemoryContextSwitchTo(oldContext);
370 if (pergroupstate->transValueIsNull)
373 * Don't call a strict function with NULL inputs. Note it is
374 * possible to get here despite the above tests, if the transfn is
375 * strict *and* returned a NULL on a prior cycle. If that happens
376 * we will propagate the NULL all the way to the end.
382 /* We run the transition functions in per-input-tuple memory context */
383 oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
386 * OK to call the transition function
388 InitFunctionCallInfoData(*fcinfo, &(peraggstate->transfn),
390 (void *) aggstate, NULL);
391 fcinfo->arg[0] = pergroupstate->transValue;
392 fcinfo->argnull[0] = pergroupstate->transValueIsNull;
394 newVal = FunctionCallInvoke(fcinfo);
397 * If pass-by-ref datatype, must copy the new value into aggcontext and
398 * pfree the prior transValue. But if transfn returned a pointer to its
399 * first input, we don't need to do anything.
401 if (!peraggstate->transtypeByVal &&
402 DatumGetPointer(newVal) != DatumGetPointer(pergroupstate->transValue))
406 MemoryContextSwitchTo(aggstate->aggcontext);
407 newVal = datumCopy(newVal,
408 peraggstate->transtypeByVal,
409 peraggstate->transtypeLen);
411 if (!pergroupstate->transValueIsNull)
412 pfree(DatumGetPointer(pergroupstate->transValue));
415 pergroupstate->transValue = newVal;
416 pergroupstate->transValueIsNull = fcinfo->isnull;
418 MemoryContextSwitchTo(oldContext);
422 * Advance all the aggregates for one input tuple. The input tuple
423 * has been stored in tmpcontext->ecxt_outertuple, so that it is accessible
424 * to ExecEvalExpr. pergroup is the array of per-group structs to use
425 * (this might be in a hashtable entry).
427 * When called, CurrentMemoryContext should be the per-query context.
430 advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
432 ExprContext *econtext = aggstate->tmpcontext;
435 for (aggno = 0; aggno < aggstate->numaggs; aggno++)
437 AggStatePerAgg peraggstate = &aggstate->peragg[aggno];
438 AggStatePerGroup pergroupstate = &pergroup[aggno];
439 AggrefExprState *aggrefstate = peraggstate->aggrefstate;
440 Aggref *aggref = peraggstate->aggref;
441 FunctionCallInfoData fcinfo;
444 MemoryContext oldContext;
446 /* Switch memory context just once for all args */
447 oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
449 /* Evaluate inputs and save in fcinfo */
450 /* We start from 1, since the 0th arg will be the transition value */
452 foreach(arg, aggrefstate->args)
454 ExprState *argstate = (ExprState *) lfirst(arg);
456 fcinfo.arg[i] = ExecEvalExpr(argstate, econtext,
457 fcinfo.argnull + i, NULL);
462 MemoryContextSwitchTo(oldContext);
464 if (aggref->aggdistinct)
466 /* in DISTINCT mode, we may ignore nulls */
467 /* XXX we assume there is only one input column */
468 if (fcinfo.argnull[1])
470 tuplesort_putdatum(peraggstate->sortstate, fcinfo.arg[1],
475 advance_transition_function(aggstate, peraggstate, pergroupstate,
482 * Run the transition function for a DISTINCT aggregate. This is called
483 * after we have completed entering all the input values into the sort
484 * object. We complete the sort, read out the values in sorted order,
485 * and run the transition function on each non-duplicate value.
487 * When called, CurrentMemoryContext should be the per-query context.
490 process_sorted_aggregate(AggState *aggstate,
491 AggStatePerAgg peraggstate,
492 AggStatePerGroup pergroupstate)
494 Datum oldVal = (Datum) 0;
495 bool haveOldVal = false;
496 MemoryContext workcontext = aggstate->tmpcontext->ecxt_per_tuple_memory;
497 MemoryContext oldContext;
500 FunctionCallInfoData fcinfo;
502 tuplesort_performsort(peraggstate->sortstate);
504 newVal = fcinfo.arg + 1;
505 isNull = fcinfo.argnull + 1;
508 * Note: if input type is pass-by-ref, the datums returned by the sort are
509 * freshly palloc'd in the per-query context, so we must be careful to
510 * pfree them when they are no longer needed.
513 while (tuplesort_getdatum(peraggstate->sortstate, true,
517 * DISTINCT always suppresses nulls, per SQL spec, regardless of the
518 * transition function's strictness.
524 * Clear and select the working context for evaluation of the equality
525 * function and transition function.
527 MemoryContextReset(workcontext);
528 oldContext = MemoryContextSwitchTo(workcontext);
531 DatumGetBool(FunctionCall2(&peraggstate->equalfn,
534 /* equal to prior, so forget this one */
535 if (!peraggstate->inputtypeByVal)
536 pfree(DatumGetPointer(*newVal));
540 advance_transition_function(aggstate, peraggstate, pergroupstate,
542 /* forget the old value, if any */
543 if (haveOldVal && !peraggstate->inputtypeByVal)
544 pfree(DatumGetPointer(oldVal));
545 /* and remember the new one for subsequent equality checks */
550 MemoryContextSwitchTo(oldContext);
553 if (haveOldVal && !peraggstate->inputtypeByVal)
554 pfree(DatumGetPointer(oldVal));
556 tuplesort_end(peraggstate->sortstate);
557 peraggstate->sortstate = NULL;
561 * Compute the final value of one aggregate.
563 * The finalfunction will be run, and the result delivered, in the
564 * output-tuple context; caller's CurrentMemoryContext does not matter.
567 finalize_aggregate(AggState *aggstate,
568 AggStatePerAgg peraggstate,
569 AggStatePerGroup pergroupstate,
570 Datum *resultVal, bool *resultIsNull)
572 MemoryContext oldContext;
574 oldContext = MemoryContextSwitchTo(aggstate->ss.ps.ps_ExprContext->ecxt_per_tuple_memory);
577 * Apply the agg's finalfn if one is provided, else return transValue.
579 if (OidIsValid(peraggstate->finalfn_oid))
581 FunctionCallInfoData fcinfo;
583 InitFunctionCallInfoData(fcinfo, &(peraggstate->finalfn), 1,
584 (void *) aggstate, NULL);
585 fcinfo.arg[0] = pergroupstate->transValue;
586 fcinfo.argnull[0] = pergroupstate->transValueIsNull;
587 if (fcinfo.flinfo->fn_strict && pergroupstate->transValueIsNull)
589 /* don't call a strict function with NULL inputs */
590 *resultVal = (Datum) 0;
591 *resultIsNull = true;
595 *resultVal = FunctionCallInvoke(&fcinfo);
596 *resultIsNull = fcinfo.isnull;
601 *resultVal = pergroupstate->transValue;
602 *resultIsNull = pergroupstate->transValueIsNull;
606 * If result is pass-by-ref, make sure it is in the right context.
608 if (!peraggstate->resulttypeByVal && !*resultIsNull &&
609 !MemoryContextContains(CurrentMemoryContext,
610 DatumGetPointer(*resultVal)))
611 *resultVal = datumCopy(*resultVal,
612 peraggstate->resulttypeByVal,
613 peraggstate->resulttypeLen);
615 MemoryContextSwitchTo(oldContext);
619 * find_unaggregated_cols
620 * Construct a bitmapset of the column numbers of un-aggregated Vars
621 * appearing in our targetlist and qual (HAVING clause)
624 find_unaggregated_cols(AggState *aggstate)
626 Agg *node = (Agg *) aggstate->ss.ps.plan;
630 (void) find_unaggregated_cols_walker((Node *) node->plan.targetlist,
632 (void) find_unaggregated_cols_walker((Node *) node->plan.qual,
638 find_unaggregated_cols_walker(Node *node, Bitmapset **colnos)
644 Var *var = (Var *) node;
646 /* setrefs.c should have set the varno to OUTER */
647 Assert(var->varno == OUTER);
648 Assert(var->varlevelsup == 0);
649 *colnos = bms_add_member(*colnos, var->varattno);
652 if (IsA(node, Aggref)) /* do not descend into aggregate exprs */
654 return expression_tree_walker(node, find_unaggregated_cols_walker,
659 * Initialize the hash table to empty.
661 * The hash table always lives in the aggcontext memory context.
664 build_hash_table(AggState *aggstate)
666 Agg *node = (Agg *) aggstate->ss.ps.plan;
667 MemoryContext tmpmem = aggstate->tmpcontext->ecxt_per_tuple_memory;
673 Assert(node->aggstrategy == AGG_HASHED);
674 Assert(node->numGroups > 0);
676 entrysize = sizeof(AggHashEntryData) +
677 (aggstate->numaggs - 1) *sizeof(AggStatePerGroupData);
679 aggstate->hashtable = BuildTupleHashTable(node->numCols,
681 aggstate->eqfunctions,
682 aggstate->hashfunctions,
685 aggstate->aggcontext,
689 * Create a list of the tuple columns that actually need to be stored in
690 * hashtable entries. The incoming tuples from the child plan node will
691 * contain grouping columns, other columns referenced in our targetlist
692 * and qual, columns used to compute the aggregate functions, and perhaps
693 * just junk columns we don't use at all. Only columns of the first two
694 * types need to be stored in the hashtable, and getting rid of the others
695 * can make the table entries significantly smaller. To avoid messing up
696 * Var numbering, we keep the same tuple descriptor for hashtable entries
697 * as the incoming tuples have, but set unwanted columns to NULL in the
698 * tuples that go into the table.
700 * To eliminate duplicates, we build a bitmapset of the needed columns,
701 * then convert it to an integer list (cheaper to scan at runtime). The
702 * list is in decreasing order so that the first entry is the largest;
703 * lookup_hash_entry depends on this to use slot_getsomeattrs correctly.
705 * Note: at present, searching the tlist/qual is not really necessary
706 * since the parser should disallow any unaggregated references to
707 * ungrouped columns. However, the search will be needed when we add
708 * support for SQL99 semantics that allow use of "functionally dependent"
709 * columns that haven't been explicitly grouped by.
712 /* Find Vars that will be needed in tlist and qual */
713 colnos = find_unaggregated_cols(aggstate);
714 /* Add in all the grouping columns */
715 for (i = 0; i < node->numCols; i++)
716 colnos = bms_add_member(colnos, node->grpColIdx[i]);
717 /* Convert to list, using lcons so largest element ends up first */
719 while ((i = bms_first_member(colnos)) >= 0)
720 collist = lcons_int(i, collist);
721 aggstate->hash_needed = collist;
725 * Estimate per-hash-table-entry overhead for the planner.
727 * Note that the estimate does not include space for pass-by-reference
728 * transition data values, nor for the representative tuple of each group.
731 hash_agg_entry_size(int numAggs)
735 /* This must match build_hash_table */
736 entrysize = sizeof(AggHashEntryData) +
737 (numAggs - 1) *sizeof(AggStatePerGroupData);
738 entrysize = MAXALIGN(entrysize);
739 /* Account for hashtable overhead (assuming fill factor = 1) */
740 entrysize += 3 * sizeof(void *);
745 * Find or create a hashtable entry for the tuple group containing the
748 * When called, CurrentMemoryContext should be the per-query context.
751 lookup_hash_entry(AggState *aggstate, TupleTableSlot *inputslot)
753 TupleTableSlot *hashslot = aggstate->hashslot;
758 /* if first time through, initialize hashslot by cloning input slot */
759 if (hashslot->tts_tupleDescriptor == NULL)
761 ExecSetSlotDescriptor(hashslot, inputslot->tts_tupleDescriptor);
762 /* Make sure all unused columns are NULLs */
763 ExecStoreAllNullTuple(hashslot);
766 /* transfer just the needed columns into hashslot */
767 slot_getsomeattrs(inputslot, linitial_int(aggstate->hash_needed));
768 foreach(l, aggstate->hash_needed)
770 int varNumber = lfirst_int(l) - 1;
772 hashslot->tts_values[varNumber] = inputslot->tts_values[varNumber];
773 hashslot->tts_isnull[varNumber] = inputslot->tts_isnull[varNumber];
776 /* find or create the hashtable entry using the filtered tuple */
777 entry = (AggHashEntry) LookupTupleHashEntry(aggstate->hashtable,
783 /* initialize aggregates for new tuple group */
784 initialize_aggregates(aggstate, aggstate->peragg, entry->pergroup);
793 * ExecAgg receives tuples from its outer subplan and aggregates over
794 * the appropriate attribute for each aggregate function use (Aggref
795 * node) appearing in the targetlist or qual of the node. The number
796 * of tuples to aggregate over depends on whether grouped or plain
797 * aggregation is selected. In grouped aggregation, we produce a result
798 * row for each group; in plain aggregation there's a single result row
799 * for the whole query. In either case, the value of each aggregate is
800 * stored in the expression context to be used when ExecProject evaluates
804 ExecAgg(AggState *node)
809 if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
811 if (!node->table_filled)
812 agg_fill_hash_table(node);
813 return agg_retrieve_hash_table(node);
816 return agg_retrieve_direct(node);
820 * ExecAgg for non-hashed case
822 static TupleTableSlot *
823 agg_retrieve_direct(AggState *aggstate)
825 Agg *node = (Agg *) aggstate->ss.ps.plan;
826 PlanState *outerPlan;
827 ExprContext *econtext;
828 ExprContext *tmpcontext;
829 ProjectionInfo *projInfo;
832 AggStatePerAgg peragg;
833 AggStatePerGroup pergroup;
834 TupleTableSlot *outerslot;
835 TupleTableSlot *firstSlot;
839 * get state info from node
841 outerPlan = outerPlanState(aggstate);
842 /* econtext is the per-output-tuple expression context */
843 econtext = aggstate->ss.ps.ps_ExprContext;
844 aggvalues = econtext->ecxt_aggvalues;
845 aggnulls = econtext->ecxt_aggnulls;
846 /* tmpcontext is the per-input-tuple expression context */
847 tmpcontext = aggstate->tmpcontext;
848 projInfo = aggstate->ss.ps.ps_ProjInfo;
849 peragg = aggstate->peragg;
850 pergroup = aggstate->pergroup;
851 firstSlot = aggstate->ss.ss_ScanTupleSlot;
854 * We loop retrieving groups until we find one matching
855 * aggstate->ss.ps.qual
857 while (!aggstate->agg_done)
860 * If we don't already have the first tuple of the new group, fetch it
861 * from the outer plan.
863 if (aggstate->grp_firstTuple == NULL)
865 outerslot = ExecProcNode(outerPlan);
866 if (!TupIsNull(outerslot))
869 * Make a copy of the first input tuple; we will use this for
870 * comparisons (in group mode) and for projection.
872 aggstate->grp_firstTuple = ExecCopySlotTuple(outerslot);
876 /* outer plan produced no tuples at all */
877 aggstate->agg_done = true;
878 /* If we are grouping, we should produce no tuples too */
879 if (node->aggstrategy != AGG_PLAIN)
885 * Clear the per-output-tuple context for each group
887 ResetExprContext(econtext);
890 * Initialize working state for a new input tuple group
892 initialize_aggregates(aggstate, peragg, pergroup);
894 if (aggstate->grp_firstTuple != NULL)
897 * Store the copied first input tuple in the tuple table slot
898 * reserved for it. The tuple will be deleted when it is cleared
901 ExecStoreTuple(aggstate->grp_firstTuple,
905 aggstate->grp_firstTuple = NULL; /* don't keep two pointers */
907 /* set up for first advance_aggregates call */
908 tmpcontext->ecxt_outertuple = firstSlot;
911 * Process each outer-plan tuple, and then fetch the next one,
912 * until we exhaust the outer plan or cross a group boundary.
916 advance_aggregates(aggstate, pergroup);
918 /* Reset per-input-tuple context after each tuple */
919 ResetExprContext(tmpcontext);
921 outerslot = ExecProcNode(outerPlan);
922 if (TupIsNull(outerslot))
924 /* no more outer-plan tuples available */
925 aggstate->agg_done = true;
928 /* set up for next advance_aggregates call */
929 tmpcontext->ecxt_outertuple = outerslot;
932 * If we are grouping, check whether we've crossed a group
935 if (node->aggstrategy == AGG_SORTED)
937 if (!execTuplesMatch(firstSlot,
939 node->numCols, node->grpColIdx,
940 aggstate->eqfunctions,
941 tmpcontext->ecxt_per_tuple_memory))
944 * Save the first input tuple of the next group.
946 aggstate->grp_firstTuple = ExecCopySlotTuple(outerslot);
954 * Done scanning input tuple group. Finalize each aggregate
955 * calculation, and stash results in the per-output-tuple context.
957 for (aggno = 0; aggno < aggstate->numaggs; aggno++)
959 AggStatePerAgg peraggstate = &peragg[aggno];
960 AggStatePerGroup pergroupstate = &pergroup[aggno];
962 if (peraggstate->aggref->aggdistinct)
963 process_sorted_aggregate(aggstate, peraggstate, pergroupstate);
965 finalize_aggregate(aggstate, peraggstate, pergroupstate,
966 &aggvalues[aggno], &aggnulls[aggno]);
970 * Use the representative input tuple for any references to
971 * non-aggregated input columns in the qual and tlist. (If we are not
972 * grouping, and there are no input rows at all, we will come here
973 * with an empty firstSlot ... but if not grouping, there can't be any
974 * references to non-aggregated input columns, so no problem.)
976 econtext->ecxt_outertuple = firstSlot;
979 * Check the qual (HAVING clause); if the group does not match, ignore
980 * it and loop back to try to process another group.
982 if (ExecQual(aggstate->ss.ps.qual, econtext, false))
985 * Form and return a projection tuple using the aggregate results
986 * and the representative input tuple. Note we do not support
987 * aggregates returning sets ...
989 return ExecProject(projInfo, NULL);
998 * ExecAgg for hashed case: phase 1, read input and build hash table
1001 agg_fill_hash_table(AggState *aggstate)
1003 PlanState *outerPlan;
1004 ExprContext *tmpcontext;
1006 TupleTableSlot *outerslot;
1009 * get state info from node
1011 outerPlan = outerPlanState(aggstate);
1012 /* tmpcontext is the per-input-tuple expression context */
1013 tmpcontext = aggstate->tmpcontext;
1016 * Process each outer-plan tuple, and then fetch the next one, until we
1017 * exhaust the outer plan.
1021 outerslot = ExecProcNode(outerPlan);
1022 if (TupIsNull(outerslot))
1024 /* set up for advance_aggregates call */
1025 tmpcontext->ecxt_outertuple = outerslot;
1027 /* Find or build hashtable entry for this tuple's group */
1028 entry = lookup_hash_entry(aggstate, outerslot);
1030 /* Advance the aggregates */
1031 advance_aggregates(aggstate, entry->pergroup);
1033 /* Reset per-input-tuple context after each tuple */
1034 ResetExprContext(tmpcontext);
1037 aggstate->table_filled = true;
1038 /* Initialize to walk the hash table */
1039 ResetTupleHashIterator(aggstate->hashtable, &aggstate->hashiter);
1043 * ExecAgg for hashed case: phase 2, retrieving groups from hash table
1045 static TupleTableSlot *
1046 agg_retrieve_hash_table(AggState *aggstate)
1048 ExprContext *econtext;
1049 ProjectionInfo *projInfo;
1052 AggStatePerAgg peragg;
1053 AggStatePerGroup pergroup;
1055 TupleTableSlot *firstSlot;
1059 * get state info from node
1061 /* econtext is the per-output-tuple expression context */
1062 econtext = aggstate->ss.ps.ps_ExprContext;
1063 aggvalues = econtext->ecxt_aggvalues;
1064 aggnulls = econtext->ecxt_aggnulls;
1065 projInfo = aggstate->ss.ps.ps_ProjInfo;
1066 peragg = aggstate->peragg;
1067 firstSlot = aggstate->ss.ss_ScanTupleSlot;
1070 * We loop retrieving groups until we find one satisfying
1071 * aggstate->ss.ps.qual
1073 while (!aggstate->agg_done)
1076 * Find the next entry in the hash table
1078 entry = (AggHashEntry) ScanTupleHashTable(&aggstate->hashiter);
1081 /* No more entries in hashtable, so done */
1082 aggstate->agg_done = TRUE;
1087 * Clear the per-output-tuple context for each group
1089 ResetExprContext(econtext);
1092 * Store the copied first input tuple in the tuple table slot reserved
1093 * for it, so that it can be used in ExecProject.
1095 ExecStoreMinimalTuple(entry->shared.firstTuple,
1099 pergroup = entry->pergroup;
1102 * Finalize each aggregate calculation, and stash results in the
1103 * per-output-tuple context.
1105 for (aggno = 0; aggno < aggstate->numaggs; aggno++)
1107 AggStatePerAgg peraggstate = &peragg[aggno];
1108 AggStatePerGroup pergroupstate = &pergroup[aggno];
1110 Assert(!peraggstate->aggref->aggdistinct);
1111 finalize_aggregate(aggstate, peraggstate, pergroupstate,
1112 &aggvalues[aggno], &aggnulls[aggno]);
1116 * Use the representative input tuple for any references to
1117 * non-aggregated input columns in the qual and tlist.
1119 econtext->ecxt_outertuple = firstSlot;
1122 * Check the qual (HAVING clause); if the group does not match, ignore
1123 * it and loop back to try to process another group.
1125 if (ExecQual(aggstate->ss.ps.qual, econtext, false))
1128 * Form and return a projection tuple using the aggregate results
1129 * and the representative input tuple. Note we do not support
1130 * aggregates returning sets ...
1132 return ExecProject(projInfo, NULL);
1136 /* No more groups */
1140 /* -----------------
1143 * Creates the run-time information for the agg node produced by the
1144 * planner and initializes its outer subtree
1148 ExecInitAgg(Agg *node, EState *estate, int eflags)
1151 AggStatePerAgg peragg;
1153 ExprContext *econtext;
1158 /* check for unsupported flags */
1159 Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
1162 * create state structure
1164 aggstate = makeNode(AggState);
1165 aggstate->ss.ps.plan = (Plan *) node;
1166 aggstate->ss.ps.state = estate;
1168 aggstate->aggs = NIL;
1169 aggstate->numaggs = 0;
1170 aggstate->eqfunctions = NULL;
1171 aggstate->hashfunctions = NULL;
1172 aggstate->peragg = NULL;
1173 aggstate->agg_done = false;
1174 aggstate->pergroup = NULL;
1175 aggstate->grp_firstTuple = NULL;
1176 aggstate->hashtable = NULL;
1179 * Create expression contexts. We need two, one for per-input-tuple
1180 * processing and one for per-output-tuple processing. We cheat a little
1181 * by using ExecAssignExprContext() to build both.
1183 ExecAssignExprContext(estate, &aggstate->ss.ps);
1184 aggstate->tmpcontext = aggstate->ss.ps.ps_ExprContext;
1185 ExecAssignExprContext(estate, &aggstate->ss.ps);
1188 * We also need a long-lived memory context for holding hashtable data
1189 * structures and transition values. NOTE: the details of what is stored
1190 * in aggcontext and what is stored in the regular per-query memory
1191 * context are driven by a simple decision: we want to reset the
1192 * aggcontext in ExecReScanAgg to recover no-longer-wanted space.
1194 aggstate->aggcontext =
1195 AllocSetContextCreate(CurrentMemoryContext,
1197 ALLOCSET_DEFAULT_MINSIZE,
1198 ALLOCSET_DEFAULT_INITSIZE,
1199 ALLOCSET_DEFAULT_MAXSIZE);
1201 #define AGG_NSLOTS 3
1204 * tuple table initialization
1206 ExecInitScanTupleSlot(estate, &aggstate->ss);
1207 ExecInitResultTupleSlot(estate, &aggstate->ss.ps);
1208 aggstate->hashslot = ExecInitExtraTupleSlot(estate);
1211 * initialize child expressions
1213 * Note: ExecInitExpr finds Aggrefs for us, and also checks that no aggs
1214 * contain other agg calls in their arguments. This would make no sense
1215 * under SQL semantics anyway (and it's forbidden by the spec). Because
1216 * that is true, we don't need to worry about evaluating the aggs in any
1219 aggstate->ss.ps.targetlist = (List *)
1220 ExecInitExpr((Expr *) node->plan.targetlist,
1221 (PlanState *) aggstate);
1222 aggstate->ss.ps.qual = (List *)
1223 ExecInitExpr((Expr *) node->plan.qual,
1224 (PlanState *) aggstate);
1227 * initialize child nodes
1229 * If we are doing a hashed aggregation then the child plan does not need
1230 * to handle REWIND efficiently; see ExecReScanAgg.
1232 if (node->aggstrategy == AGG_HASHED)
1233 eflags &= ~EXEC_FLAG_REWIND;
1234 outerPlan = outerPlan(node);
1235 outerPlanState(aggstate) = ExecInitNode(outerPlan, estate, eflags);
1238 * initialize source tuple type.
1240 ExecAssignScanTypeFromOuterPlan(&aggstate->ss);
1243 * Initialize result tuple type and projection info.
1245 ExecAssignResultTypeFromTL(&aggstate->ss.ps);
1246 ExecAssignProjectionInfo(&aggstate->ss.ps, NULL);
1249 * get the count of aggregates in targetlist and quals
1251 numaggs = aggstate->numaggs;
1252 Assert(numaggs == list_length(aggstate->aggs));
1256 * This is not an error condition: we might be using the Agg node just
1257 * to do hash-based grouping. Even in the regular case,
1258 * constant-expression simplification could optimize away all of the
1259 * Aggrefs in the targetlist and qual. So keep going, but force local
1260 * copy of numaggs positive so that palloc()s below don't choke.
1266 * If we are grouping, precompute fmgr lookup data for inner loop. We need
1267 * both equality and hashing functions to do it by hashing, but only
1268 * equality if not hashing.
1270 if (node->numCols > 0)
1272 if (node->aggstrategy == AGG_HASHED)
1273 execTuplesHashPrepare(node->numCols,
1275 &aggstate->eqfunctions,
1276 &aggstate->hashfunctions);
1278 aggstate->eqfunctions =
1279 execTuplesMatchPrepare(node->numCols,
1280 node->grpOperators);
1284 * Set up aggregate-result storage in the output expr context, and also
1285 * allocate my private per-agg working storage
1287 econtext = aggstate->ss.ps.ps_ExprContext;
1288 econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs);
1289 econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs);
1291 peragg = (AggStatePerAgg) palloc0(sizeof(AggStatePerAggData) * numaggs);
1292 aggstate->peragg = peragg;
1294 if (node->aggstrategy == AGG_HASHED)
1296 build_hash_table(aggstate);
1297 aggstate->table_filled = false;
1301 AggStatePerGroup pergroup;
1303 pergroup = (AggStatePerGroup) palloc0(sizeof(AggStatePerGroupData) * numaggs);
1304 aggstate->pergroup = pergroup;
1308 * Perform lookups of aggregate function info, and initialize the
1309 * unchanging fields of the per-agg data. We also detect duplicate
1310 * aggregates (for example, "SELECT sum(x) ... HAVING sum(x) > 0"). When
1311 * duplicates are detected, we only make an AggStatePerAgg struct for the
1312 * first one. The clones are simply pointed at the same result entry by
1313 * giving them duplicate aggno values.
1316 foreach(l, aggstate->aggs)
1318 AggrefExprState *aggrefstate = (AggrefExprState *) lfirst(l);
1319 Aggref *aggref = (Aggref *) aggrefstate->xprstate.expr;
1320 AggStatePerAgg peraggstate;
1321 Oid inputTypes[FUNC_MAX_ARGS];
1324 Form_pg_aggregate aggform;
1326 AclResult aclresult;
1335 /* Planner should have assigned aggregate to correct level */
1336 Assert(aggref->agglevelsup == 0);
1338 /* Look for a previous duplicate aggregate */
1339 for (i = 0; i <= aggno; i++)
1341 if (equal(aggref, peragg[i].aggref) &&
1342 !contain_volatile_functions((Node *) aggref))
1347 /* Found a match to an existing entry, so just mark it */
1348 aggrefstate->aggno = i;
1352 /* Nope, so assign a new PerAgg record */
1353 peraggstate = &peragg[++aggno];
1355 /* Mark Aggref state node with assigned index in the result array */
1356 aggrefstate->aggno = aggno;
1358 /* Fill in the peraggstate data */
1359 peraggstate->aggrefstate = aggrefstate;
1360 peraggstate->aggref = aggref;
1361 numArguments = list_length(aggref->args);
1362 peraggstate->numArguments = numArguments;
1365 * Get actual datatypes of the inputs. These could be different from
1366 * the agg's declared input types, when the agg accepts ANY or
1367 * a polymorphic type.
1370 foreach(lc, aggref->args)
1372 inputTypes[i++] = exprType((Node *) lfirst(lc));
1375 aggTuple = SearchSysCache(AGGFNOID,
1376 ObjectIdGetDatum(aggref->aggfnoid),
1378 if (!HeapTupleIsValid(aggTuple))
1379 elog(ERROR, "cache lookup failed for aggregate %u",
1381 aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);
1383 /* Check permission to call aggregate function */
1384 aclresult = pg_proc_aclcheck(aggref->aggfnoid, GetUserId(),
1386 if (aclresult != ACLCHECK_OK)
1387 aclcheck_error(aclresult, ACL_KIND_PROC,
1388 get_func_name(aggref->aggfnoid));
1390 peraggstate->transfn_oid = transfn_oid = aggform->aggtransfn;
1391 peraggstate->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
1393 /* Check that aggregate owner has permission to call component fns */
1395 HeapTuple procTuple;
1398 procTuple = SearchSysCache(PROCOID,
1399 ObjectIdGetDatum(aggref->aggfnoid),
1401 if (!HeapTupleIsValid(procTuple))
1402 elog(ERROR, "cache lookup failed for function %u",
1404 aggOwner = ((Form_pg_proc) GETSTRUCT(procTuple))->proowner;
1405 ReleaseSysCache(procTuple);
1407 aclresult = pg_proc_aclcheck(transfn_oid, aggOwner,
1409 if (aclresult != ACLCHECK_OK)
1410 aclcheck_error(aclresult, ACL_KIND_PROC,
1411 get_func_name(transfn_oid));
1412 if (OidIsValid(finalfn_oid))
1414 aclresult = pg_proc_aclcheck(finalfn_oid, aggOwner,
1416 if (aclresult != ACLCHECK_OK)
1417 aclcheck_error(aclresult, ACL_KIND_PROC,
1418 get_func_name(finalfn_oid));
1422 /* resolve actual type of transition state, if polymorphic */
1423 aggtranstype = aggform->aggtranstype;
1424 if (IsPolymorphicType(aggtranstype))
1426 /* have to fetch the agg's declared input types... */
1427 Oid *declaredArgTypes;
1430 (void) get_func_signature(aggref->aggfnoid,
1431 &declaredArgTypes, &agg_nargs);
1432 Assert(agg_nargs == numArguments);
1433 aggtranstype = enforce_generic_type_consistency(inputTypes,
1437 pfree(declaredArgTypes);
1440 /* build expression trees using actual argument & result types */
1441 build_aggregate_fnexprs(inputTypes,
1450 fmgr_info(transfn_oid, &peraggstate->transfn);
1451 peraggstate->transfn.fn_expr = (Node *) transfnexpr;
1453 if (OidIsValid(finalfn_oid))
1455 fmgr_info(finalfn_oid, &peraggstate->finalfn);
1456 peraggstate->finalfn.fn_expr = (Node *) finalfnexpr;
1459 get_typlenbyval(aggref->aggtype,
1460 &peraggstate->resulttypeLen,
1461 &peraggstate->resulttypeByVal);
1462 get_typlenbyval(aggtranstype,
1463 &peraggstate->transtypeLen,
1464 &peraggstate->transtypeByVal);
1467 * initval is potentially null, so don't try to access it as a struct
1468 * field. Must do it the hard way with SysCacheGetAttr.
1470 textInitVal = SysCacheGetAttr(AGGFNOID, aggTuple,
1471 Anum_pg_aggregate_agginitval,
1472 &peraggstate->initValueIsNull);
1474 if (peraggstate->initValueIsNull)
1475 peraggstate->initValue = (Datum) 0;
1477 peraggstate->initValue = GetAggInitVal(textInitVal,
1481 * If the transfn is strict and the initval is NULL, make sure input
1482 * type and transtype are the same (or at least binary-compatible), so
1483 * that it's OK to use the first input value as the initial
1484 * transValue. This should have been checked at agg definition time,
1485 * but just in case...
1487 if (peraggstate->transfn.fn_strict && peraggstate->initValueIsNull)
1489 if (numArguments < 1 ||
1490 !IsBinaryCoercible(inputTypes[0], aggtranstype))
1492 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
1493 errmsg("aggregate %u needs to have compatible input type and transition type",
1494 aggref->aggfnoid)));
1497 if (aggref->aggdistinct)
1501 /* We don't implement DISTINCT aggs in the HASHED case */
1502 Assert(node->aggstrategy != AGG_HASHED);
1505 * We don't currently implement DISTINCT aggs for aggs having more
1506 * than one argument. This isn't required for anything in the SQL
1507 * spec, but really it ought to be implemented for
1508 * feature-completeness. FIXME someday.
1510 if (numArguments != 1)
1512 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1513 errmsg("DISTINCT is supported only for single-argument aggregates")));
1515 peraggstate->inputType = inputTypes[0];
1516 get_typlenbyval(inputTypes[0],
1517 &peraggstate->inputtypeLen,
1518 &peraggstate->inputtypeByVal);
1521 * Look up the sorting and comparison operators to use. XXX it's
1522 * pretty bletcherous to be making this sort of semantic decision
1523 * in the executor. Probably the parser should decide this and
1524 * record it in the Aggref node ... or at latest, do it in the
1527 eq_function = equality_oper_funcid(inputTypes[0]);
1528 fmgr_info(eq_function, &(peraggstate->equalfn));
1529 peraggstate->sortOperator = ordering_oper_opid(inputTypes[0]);
1530 peraggstate->sortstate = NULL;
1533 ReleaseSysCache(aggTuple);
1536 /* Update numaggs to match number of unique aggregates found */
1537 aggstate->numaggs = aggno + 1;
1543 GetAggInitVal(Datum textInitVal, Oid transtype)
1550 getTypeInputInfo(transtype, &typinput, &typioparam);
1551 strInitVal = DatumGetCString(DirectFunctionCall1(textout, textInitVal));
1552 initVal = OidInputFunctionCall(typinput, strInitVal,
1559 ExecCountSlotsAgg(Agg *node)
1561 return ExecCountSlotsNode(outerPlan(node)) +
1562 ExecCountSlotsNode(innerPlan(node)) +
1567 ExecEndAgg(AggState *node)
1569 PlanState *outerPlan;
1572 /* Make sure we have closed any open tuplesorts */
1573 for (aggno = 0; aggno < node->numaggs; aggno++)
1575 AggStatePerAgg peraggstate = &node->peragg[aggno];
1577 if (peraggstate->sortstate)
1578 tuplesort_end(peraggstate->sortstate);
1582 * Free both the expr contexts.
1584 ExecFreeExprContext(&node->ss.ps);
1585 node->ss.ps.ps_ExprContext = node->tmpcontext;
1586 ExecFreeExprContext(&node->ss.ps);
1588 /* clean up tuple table */
1589 ExecClearTuple(node->ss.ss_ScanTupleSlot);
1591 MemoryContextDelete(node->aggcontext);
1593 outerPlan = outerPlanState(node);
1594 ExecEndNode(outerPlan);
1598 ExecReScanAgg(AggState *node, ExprContext *exprCtxt)
1600 ExprContext *econtext = node->ss.ps.ps_ExprContext;
1603 node->agg_done = false;
1605 if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
1608 * In the hashed case, if we haven't yet built the hash table then we
1609 * can just return; nothing done yet, so nothing to undo. If subnode's
1610 * chgParam is not NULL then it will be re-scanned by ExecProcNode,
1611 * else no reason to re-scan it at all.
1613 if (!node->table_filled)
1617 * If we do have the hash table and the subplan does not have any
1618 * parameter changes, then we can just rescan the existing hash table;
1619 * no need to build it again.
1621 if (((PlanState *) node)->lefttree->chgParam == NULL)
1623 ResetTupleHashIterator(node->hashtable, &node->hashiter);
1628 /* Make sure we have closed any open tuplesorts */
1629 for (aggno = 0; aggno < node->numaggs; aggno++)
1631 AggStatePerAgg peraggstate = &node->peragg[aggno];
1633 if (peraggstate->sortstate)
1634 tuplesort_end(peraggstate->sortstate);
1635 peraggstate->sortstate = NULL;
1638 /* Release first tuple of group, if we have made a copy */
1639 if (node->grp_firstTuple != NULL)
1641 heap_freetuple(node->grp_firstTuple);
1642 node->grp_firstTuple = NULL;
1645 /* Forget current agg values */
1646 MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numaggs);
1647 MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numaggs);
1650 * Release all temp storage. Note that with AGG_HASHED, the hash table
1651 * is allocated in a sub-context of the aggcontext. We're going to
1652 * rebuild the hash table from scratch, so we need to use
1653 * MemoryContextResetAndDeleteChildren() to avoid leaking the old hash
1654 * table's memory context header.
1656 MemoryContextResetAndDeleteChildren(node->aggcontext);
1658 if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
1660 /* Rebuild an empty hash table */
1661 build_hash_table(node);
1662 node->table_filled = false;
1667 * Reset the per-group state (in particular, mark transvalues null)
1669 MemSet(node->pergroup, 0,
1670 sizeof(AggStatePerGroupData) * node->numaggs);
1674 * if chgParam of subnode is not null then plan will be re-scanned by
1675 * first ExecProcNode.
1677 if (((PlanState *) node)->lefttree->chgParam == NULL)
1678 ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
1682 * aggregate_dummy - dummy execution routine for aggregate functions
1684 * This function is listed as the implementation (prosrc field) of pg_proc
1685 * entries for aggregate functions. Its only purpose is to throw an error
1686 * if someone mistakenly executes such a function in the normal way.
1688 * Perhaps someday we could assign real meaning to the prosrc field of
1692 aggregate_dummy(PG_FUNCTION_ARGS)
1694 elog(ERROR, "aggregate function %u called as normal function",
1695 fcinfo->flinfo->fn_oid);
1696 return (Datum) 0; /* keep compiler quiet */