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-2008, PostgreSQL Global Development Group
61 * Portions Copyright (c) 1994, Regents of the University of California
66 *-------------------------------------------------------------------------
71 #include "catalog/pg_aggregate.h"
72 #include "catalog/pg_proc.h"
73 #include "catalog/pg_type.h"
74 #include "executor/executor.h"
75 #include "executor/nodeAgg.h"
76 #include "miscadmin.h"
77 #include "nodes/nodeFuncs.h"
78 #include "optimizer/clauses.h"
79 #include "parser/parse_agg.h"
80 #include "parser/parse_coerce.h"
81 #include "parser/parse_oper.h"
82 #include "utils/acl.h"
83 #include "utils/builtins.h"
84 #include "utils/lsyscache.h"
85 #include "utils/memutils.h"
86 #include "utils/syscache.h"
87 #include "utils/tuplesort.h"
88 #include "utils/datum.h"
92 * AggStatePerAggData - per-aggregate working state for the Agg scan
94 typedef struct AggStatePerAggData
97 * These values are set up during ExecInitAgg() and do not change
101 /* Links to Aggref expr and state nodes this working state is for */
102 AggrefExprState
*aggrefstate
;
105 /* number of input arguments for aggregate */
108 /* Oids of transfer functions */
110 Oid finalfn_oid
; /* may be InvalidOid */
113 * fmgr lookup data for transfer functions --- only valid when
114 * corresponding oid is not InvalidOid. Note in particular that fn_strict
115 * flags are kept here.
121 * Type of input data and Oid of sort operator to use for it; only
122 * set/used when aggregate has DISTINCT flag. (These are not used
123 * directly by nodeAgg, but must be passed to the Tuplesort object.)
129 * fmgr lookup data for input type's equality operator --- only set/used
130 * when aggregate has DISTINCT flag.
135 * initial value from pg_aggregate entry
138 bool initValueIsNull
;
141 * We need the len and byval info for the agg's input, result, and
142 * transition data types in order to know how to copy/delete values.
152 * These values are working state that is initialized at the start of an
153 * input tuple group and updated for each input tuple.
155 * For a simple (non DISTINCT) aggregate, we just feed the input values
156 * straight to the transition function. If it's DISTINCT, we pass the
157 * input values into a Tuplesort object; then at completion of the input
158 * tuple group, we scan the sorted values, eliminate duplicates, and run
159 * the transition function on the rest.
162 Tuplesortstate
*sortstate
; /* sort object, if a DISTINCT agg */
163 } AggStatePerAggData
;
166 * AggStatePerGroupData - per-aggregate-per-group working state
168 * These values are working state that is initialized at the start of
169 * an input tuple group and updated for each input tuple.
171 * In AGG_PLAIN and AGG_SORTED modes, we have a single array of these
172 * structs (pointed to by aggstate->pergroup); we re-use the array for
173 * each input group, if it's AGG_SORTED mode. In AGG_HASHED mode, the
174 * hash table contains an array of these structs for each tuple group.
176 * Logically, the sortstate field belongs in this struct, but we do not
177 * keep it here for space reasons: we don't support DISTINCT aggregates
178 * in AGG_HASHED mode, so there's no reason to use up a pointer field
179 * in every entry of the hashtable.
181 typedef struct AggStatePerGroupData
183 Datum transValue
; /* current transition value */
184 bool transValueIsNull
;
186 bool noTransValue
; /* true if transValue not set yet */
189 * Note: noTransValue initially has the same value as transValueIsNull,
190 * and if true both are cleared to false at the same time. They are not
191 * the same though: if transfn later returns a NULL, we want to keep that
192 * NULL and not auto-replace it with a later input value. Only the first
193 * non-NULL input will be auto-substituted.
195 } AggStatePerGroupData
;
198 * To implement hashed aggregation, we need a hashtable that stores a
199 * representative tuple and an array of AggStatePerGroup structs for each
200 * distinct set of GROUP BY column values. We compute the hash key from
201 * the GROUP BY columns.
203 typedef struct AggHashEntryData
*AggHashEntry
;
205 typedef struct AggHashEntryData
207 TupleHashEntryData shared
; /* common header for hash table entries */
208 /* per-aggregate transition status array - must be last! */
209 AggStatePerGroupData pergroup
[1]; /* VARIABLE LENGTH ARRAY */
210 } AggHashEntryData
; /* VARIABLE LENGTH STRUCT */
213 static void initialize_aggregates(AggState
*aggstate
,
214 AggStatePerAgg peragg
,
215 AggStatePerGroup pergroup
);
216 static void advance_transition_function(AggState
*aggstate
,
217 AggStatePerAgg peraggstate
,
218 AggStatePerGroup pergroupstate
,
219 FunctionCallInfoData
*fcinfo
);
220 static void advance_aggregates(AggState
*aggstate
, AggStatePerGroup pergroup
);
221 static void process_sorted_aggregate(AggState
*aggstate
,
222 AggStatePerAgg peraggstate
,
223 AggStatePerGroup pergroupstate
);
224 static void finalize_aggregate(AggState
*aggstate
,
225 AggStatePerAgg peraggstate
,
226 AggStatePerGroup pergroupstate
,
227 Datum
*resultVal
, bool *resultIsNull
);
228 static Bitmapset
*find_unaggregated_cols(AggState
*aggstate
);
229 static bool find_unaggregated_cols_walker(Node
*node
, Bitmapset
**colnos
);
230 static void build_hash_table(AggState
*aggstate
);
231 static AggHashEntry
lookup_hash_entry(AggState
*aggstate
,
232 TupleTableSlot
*inputslot
);
233 static TupleTableSlot
*agg_retrieve_direct(AggState
*aggstate
);
234 static void agg_fill_hash_table(AggState
*aggstate
);
235 static TupleTableSlot
*agg_retrieve_hash_table(AggState
*aggstate
);
236 static Datum
GetAggInitVal(Datum textInitVal
, Oid transtype
);
240 * Initialize all aggregates for a new group of input values.
242 * When called, CurrentMemoryContext should be the per-query context.
245 initialize_aggregates(AggState
*aggstate
,
246 AggStatePerAgg peragg
,
247 AggStatePerGroup pergroup
)
251 for (aggno
= 0; aggno
< aggstate
->numaggs
; aggno
++)
253 AggStatePerAgg peraggstate
= &peragg
[aggno
];
254 AggStatePerGroup pergroupstate
= &pergroup
[aggno
];
255 Aggref
*aggref
= peraggstate
->aggref
;
258 * Start a fresh sort operation for each DISTINCT aggregate.
260 if (aggref
->aggdistinct
)
263 * In case of rescan, maybe there could be an uncompleted sort
264 * operation? Clean it up if so.
266 if (peraggstate
->sortstate
)
267 tuplesort_end(peraggstate
->sortstate
);
269 peraggstate
->sortstate
=
270 tuplesort_begin_datum(peraggstate
->inputType
,
271 peraggstate
->sortOperator
, false,
276 * If we are reinitializing after a group boundary, we have to free
277 * any prior transValue to avoid memory leakage. We must check not
278 * only the isnull flag but whether the pointer is NULL; since
279 * pergroupstate is initialized with palloc0, the initial condition
280 * has isnull = 0 and null pointer.
282 if (!peraggstate
->transtypeByVal
&&
283 !pergroupstate
->transValueIsNull
&&
284 DatumGetPointer(pergroupstate
->transValue
) != NULL
)
285 pfree(DatumGetPointer(pergroupstate
->transValue
));
288 * (Re)set transValue to the initial value.
290 * Note that when the initial value is pass-by-ref, we must copy it
291 * (into the aggcontext) since we will pfree the transValue later.
293 if (peraggstate
->initValueIsNull
)
294 pergroupstate
->transValue
= peraggstate
->initValue
;
297 MemoryContext oldContext
;
299 oldContext
= MemoryContextSwitchTo(aggstate
->aggcontext
);
300 pergroupstate
->transValue
= datumCopy(peraggstate
->initValue
,
301 peraggstate
->transtypeByVal
,
302 peraggstate
->transtypeLen
);
303 MemoryContextSwitchTo(oldContext
);
305 pergroupstate
->transValueIsNull
= peraggstate
->initValueIsNull
;
308 * If the initial value for the transition state doesn't exist in the
309 * pg_aggregate table then we will let the first non-NULL value
310 * returned from the outer procNode become the initial value. (This is
311 * useful for aggregates like max() and min().) The noTransValue flag
312 * signals that we still need to do this.
314 pergroupstate
->noTransValue
= peraggstate
->initValueIsNull
;
319 * Given new input value(s), advance the transition function of an aggregate.
321 * The new values (and null flags) have been preloaded into argument positions
322 * 1 and up in fcinfo, so that we needn't copy them again to pass to the
323 * transition function. No other fields of fcinfo are assumed valid.
325 * It doesn't matter which memory context this is called in.
328 advance_transition_function(AggState
*aggstate
,
329 AggStatePerAgg peraggstate
,
330 AggStatePerGroup pergroupstate
,
331 FunctionCallInfoData
*fcinfo
)
333 int numArguments
= peraggstate
->numArguments
;
334 MemoryContext oldContext
;
338 if (peraggstate
->transfn
.fn_strict
)
341 * For a strict transfn, nothing happens when there's a NULL input; we
342 * just keep the prior transValue.
344 for (i
= 1; i
<= numArguments
; i
++)
346 if (fcinfo
->argnull
[i
])
349 if (pergroupstate
->noTransValue
)
352 * transValue has not been initialized. This is the first non-NULL
353 * input value. We use it as the initial value for transValue. (We
354 * already checked that the agg's input type is binary-compatible
355 * with its transtype, so straight copy here is OK.)
357 * We must copy the datum into aggcontext if it is pass-by-ref. We
358 * do not need to pfree the old transValue, since it's NULL.
360 oldContext
= MemoryContextSwitchTo(aggstate
->aggcontext
);
361 pergroupstate
->transValue
= datumCopy(fcinfo
->arg
[1],
362 peraggstate
->transtypeByVal
,
363 peraggstate
->transtypeLen
);
364 pergroupstate
->transValueIsNull
= false;
365 pergroupstate
->noTransValue
= false;
366 MemoryContextSwitchTo(oldContext
);
369 if (pergroupstate
->transValueIsNull
)
372 * Don't call a strict function with NULL inputs. Note it is
373 * possible to get here despite the above tests, if the transfn is
374 * strict *and* returned a NULL on a prior cycle. If that happens
375 * we will propagate the NULL all the way to the end.
381 /* We run the transition functions in per-input-tuple memory context */
382 oldContext
= MemoryContextSwitchTo(aggstate
->tmpcontext
->ecxt_per_tuple_memory
);
385 * OK to call the transition function
387 InitFunctionCallInfoData(*fcinfo
, &(peraggstate
->transfn
),
389 (void *) aggstate
, NULL
);
390 fcinfo
->arg
[0] = pergroupstate
->transValue
;
391 fcinfo
->argnull
[0] = pergroupstate
->transValueIsNull
;
393 newVal
= FunctionCallInvoke(fcinfo
);
396 * If pass-by-ref datatype, must copy the new value into aggcontext and
397 * pfree the prior transValue. But if transfn returned a pointer to its
398 * first input, we don't need to do anything.
400 if (!peraggstate
->transtypeByVal
&&
401 DatumGetPointer(newVal
) != DatumGetPointer(pergroupstate
->transValue
))
405 MemoryContextSwitchTo(aggstate
->aggcontext
);
406 newVal
= datumCopy(newVal
,
407 peraggstate
->transtypeByVal
,
408 peraggstate
->transtypeLen
);
410 if (!pergroupstate
->transValueIsNull
)
411 pfree(DatumGetPointer(pergroupstate
->transValue
));
414 pergroupstate
->transValue
= newVal
;
415 pergroupstate
->transValueIsNull
= fcinfo
->isnull
;
417 MemoryContextSwitchTo(oldContext
);
421 * Advance all the aggregates for one input tuple. The input tuple
422 * has been stored in tmpcontext->ecxt_outertuple, so that it is accessible
423 * to ExecEvalExpr. pergroup is the array of per-group structs to use
424 * (this might be in a hashtable entry).
426 * When called, CurrentMemoryContext should be the per-query context.
429 advance_aggregates(AggState
*aggstate
, AggStatePerGroup pergroup
)
431 ExprContext
*econtext
= aggstate
->tmpcontext
;
434 for (aggno
= 0; aggno
< aggstate
->numaggs
; aggno
++)
436 AggStatePerAgg peraggstate
= &aggstate
->peragg
[aggno
];
437 AggStatePerGroup pergroupstate
= &pergroup
[aggno
];
438 AggrefExprState
*aggrefstate
= peraggstate
->aggrefstate
;
439 Aggref
*aggref
= peraggstate
->aggref
;
440 FunctionCallInfoData fcinfo
;
443 MemoryContext oldContext
;
445 /* Switch memory context just once for all args */
446 oldContext
= MemoryContextSwitchTo(econtext
->ecxt_per_tuple_memory
);
448 /* Evaluate inputs and save in fcinfo */
449 /* We start from 1, since the 0th arg will be the transition value */
451 foreach(arg
, aggrefstate
->args
)
453 ExprState
*argstate
= (ExprState
*) lfirst(arg
);
455 fcinfo
.arg
[i
] = ExecEvalExpr(argstate
, econtext
,
456 fcinfo
.argnull
+ i
, NULL
);
461 MemoryContextSwitchTo(oldContext
);
463 if (aggref
->aggdistinct
)
465 /* in DISTINCT mode, we may ignore nulls */
466 /* XXX we assume there is only one input column */
467 if (fcinfo
.argnull
[1])
469 tuplesort_putdatum(peraggstate
->sortstate
, fcinfo
.arg
[1],
474 advance_transition_function(aggstate
, peraggstate
, pergroupstate
,
481 * Run the transition function for a DISTINCT aggregate. This is called
482 * after we have completed entering all the input values into the sort
483 * object. We complete the sort, read out the values in sorted order,
484 * and run the transition function on each non-duplicate value.
486 * When called, CurrentMemoryContext should be the per-query context.
489 process_sorted_aggregate(AggState
*aggstate
,
490 AggStatePerAgg peraggstate
,
491 AggStatePerGroup pergroupstate
)
493 Datum oldVal
= (Datum
) 0;
494 bool haveOldVal
= false;
495 MemoryContext workcontext
= aggstate
->tmpcontext
->ecxt_per_tuple_memory
;
496 MemoryContext oldContext
;
499 FunctionCallInfoData fcinfo
;
501 tuplesort_performsort(peraggstate
->sortstate
);
503 newVal
= fcinfo
.arg
+ 1;
504 isNull
= fcinfo
.argnull
+ 1;
507 * Note: if input type is pass-by-ref, the datums returned by the sort are
508 * freshly palloc'd in the per-query context, so we must be careful to
509 * pfree them when they are no longer needed.
512 while (tuplesort_getdatum(peraggstate
->sortstate
, true,
516 * DISTINCT always suppresses nulls, per SQL spec, regardless of the
517 * transition function's strictness.
523 * Clear and select the working context for evaluation of the equality
524 * function and transition function.
526 MemoryContextReset(workcontext
);
527 oldContext
= MemoryContextSwitchTo(workcontext
);
530 DatumGetBool(FunctionCall2(&peraggstate
->equalfn
,
533 /* equal to prior, so forget this one */
534 if (!peraggstate
->inputtypeByVal
)
535 pfree(DatumGetPointer(*newVal
));
539 advance_transition_function(aggstate
, peraggstate
, pergroupstate
,
541 /* forget the old value, if any */
542 if (haveOldVal
&& !peraggstate
->inputtypeByVal
)
543 pfree(DatumGetPointer(oldVal
));
544 /* and remember the new one for subsequent equality checks */
549 MemoryContextSwitchTo(oldContext
);
552 if (haveOldVal
&& !peraggstate
->inputtypeByVal
)
553 pfree(DatumGetPointer(oldVal
));
555 tuplesort_end(peraggstate
->sortstate
);
556 peraggstate
->sortstate
= NULL
;
560 * Compute the final value of one aggregate.
562 * The finalfunction will be run, and the result delivered, in the
563 * output-tuple context; caller's CurrentMemoryContext does not matter.
566 finalize_aggregate(AggState
*aggstate
,
567 AggStatePerAgg peraggstate
,
568 AggStatePerGroup pergroupstate
,
569 Datum
*resultVal
, bool *resultIsNull
)
571 MemoryContext oldContext
;
573 oldContext
= MemoryContextSwitchTo(aggstate
->ss
.ps
.ps_ExprContext
->ecxt_per_tuple_memory
);
576 * Apply the agg's finalfn if one is provided, else return transValue.
578 if (OidIsValid(peraggstate
->finalfn_oid
))
580 FunctionCallInfoData fcinfo
;
582 InitFunctionCallInfoData(fcinfo
, &(peraggstate
->finalfn
), 1,
583 (void *) aggstate
, NULL
);
584 fcinfo
.arg
[0] = pergroupstate
->transValue
;
585 fcinfo
.argnull
[0] = pergroupstate
->transValueIsNull
;
586 if (fcinfo
.flinfo
->fn_strict
&& pergroupstate
->transValueIsNull
)
588 /* don't call a strict function with NULL inputs */
589 *resultVal
= (Datum
) 0;
590 *resultIsNull
= true;
594 *resultVal
= FunctionCallInvoke(&fcinfo
);
595 *resultIsNull
= fcinfo
.isnull
;
600 *resultVal
= pergroupstate
->transValue
;
601 *resultIsNull
= pergroupstate
->transValueIsNull
;
605 * If result is pass-by-ref, make sure it is in the right context.
607 if (!peraggstate
->resulttypeByVal
&& !*resultIsNull
&&
608 !MemoryContextContains(CurrentMemoryContext
,
609 DatumGetPointer(*resultVal
)))
610 *resultVal
= datumCopy(*resultVal
,
611 peraggstate
->resulttypeByVal
,
612 peraggstate
->resulttypeLen
);
614 MemoryContextSwitchTo(oldContext
);
618 * find_unaggregated_cols
619 * Construct a bitmapset of the column numbers of un-aggregated Vars
620 * appearing in our targetlist and qual (HAVING clause)
623 find_unaggregated_cols(AggState
*aggstate
)
625 Agg
*node
= (Agg
*) aggstate
->ss
.ps
.plan
;
629 (void) find_unaggregated_cols_walker((Node
*) node
->plan
.targetlist
,
631 (void) find_unaggregated_cols_walker((Node
*) node
->plan
.qual
,
637 find_unaggregated_cols_walker(Node
*node
, Bitmapset
**colnos
)
643 Var
*var
= (Var
*) node
;
645 /* setrefs.c should have set the varno to OUTER */
646 Assert(var
->varno
== OUTER
);
647 Assert(var
->varlevelsup
== 0);
648 *colnos
= bms_add_member(*colnos
, var
->varattno
);
651 if (IsA(node
, Aggref
)) /* do not descend into aggregate exprs */
653 return expression_tree_walker(node
, find_unaggregated_cols_walker
,
658 * Initialize the hash table to empty.
660 * The hash table always lives in the aggcontext memory context.
663 build_hash_table(AggState
*aggstate
)
665 Agg
*node
= (Agg
*) aggstate
->ss
.ps
.plan
;
666 MemoryContext tmpmem
= aggstate
->tmpcontext
->ecxt_per_tuple_memory
;
669 Assert(node
->aggstrategy
== AGG_HASHED
);
670 Assert(node
->numGroups
> 0);
672 entrysize
= sizeof(AggHashEntryData
) +
673 (aggstate
->numaggs
- 1) *sizeof(AggStatePerGroupData
);
675 aggstate
->hashtable
= BuildTupleHashTable(node
->numCols
,
677 aggstate
->eqfunctions
,
678 aggstate
->hashfunctions
,
681 aggstate
->aggcontext
,
686 * Create a list of the tuple columns that actually need to be stored in
687 * hashtable entries. The incoming tuples from the child plan node will
688 * contain grouping columns, other columns referenced in our targetlist and
689 * qual, columns used to compute the aggregate functions, and perhaps just
690 * junk columns we don't use at all. Only columns of the first two types
691 * need to be stored in the hashtable, and getting rid of the others can
692 * make the table entries significantly smaller. To avoid messing up Var
693 * numbering, we keep the same tuple descriptor for hashtable entries as the
694 * incoming tuples have, but set unwanted columns to NULL in the tuples that
697 * To eliminate duplicates, we build a bitmapset of the needed columns, then
698 * convert it to an integer list (cheaper to scan at runtime). The list is
699 * in decreasing order so that the first entry is the largest;
700 * lookup_hash_entry depends on this to use slot_getsomeattrs correctly.
701 * Note that the list is preserved over ExecReScanAgg, so we allocate it in
702 * the per-query context (unlike the hash table itself).
704 * Note: at present, searching the tlist/qual is not really necessary since
705 * the parser should disallow any unaggregated references to ungrouped
706 * columns. However, the search will be needed when we add support for
707 * SQL99 semantics that allow use of "functionally dependent" columns that
708 * haven't been explicitly grouped by.
711 find_hash_columns(AggState
*aggstate
)
713 Agg
*node
= (Agg
*) aggstate
->ss
.ps
.plan
;
718 /* Find Vars that will be needed in tlist and qual */
719 colnos
= find_unaggregated_cols(aggstate
);
720 /* Add in all the grouping columns */
721 for (i
= 0; i
< node
->numCols
; i
++)
722 colnos
= bms_add_member(colnos
, node
->grpColIdx
[i
]);
723 /* Convert to list, using lcons so largest element ends up first */
725 while ((i
= bms_first_member(colnos
)) >= 0)
726 collist
= lcons_int(i
, collist
);
733 * Estimate per-hash-table-entry overhead for the planner.
735 * Note that the estimate does not include space for pass-by-reference
736 * transition data values, nor for the representative tuple of each group.
739 hash_agg_entry_size(int numAggs
)
743 /* This must match build_hash_table */
744 entrysize
= sizeof(AggHashEntryData
) +
745 (numAggs
- 1) *sizeof(AggStatePerGroupData
);
746 entrysize
= MAXALIGN(entrysize
);
747 /* Account for hashtable overhead (assuming fill factor = 1) */
748 entrysize
+= 3 * sizeof(void *);
753 * Find or create a hashtable entry for the tuple group containing the
756 * When called, CurrentMemoryContext should be the per-query context.
759 lookup_hash_entry(AggState
*aggstate
, TupleTableSlot
*inputslot
)
761 TupleTableSlot
*hashslot
= aggstate
->hashslot
;
766 /* if first time through, initialize hashslot by cloning input slot */
767 if (hashslot
->tts_tupleDescriptor
== NULL
)
769 ExecSetSlotDescriptor(hashslot
, inputslot
->tts_tupleDescriptor
);
770 /* Make sure all unused columns are NULLs */
771 ExecStoreAllNullTuple(hashslot
);
774 /* transfer just the needed columns into hashslot */
775 slot_getsomeattrs(inputslot
, linitial_int(aggstate
->hash_needed
));
776 foreach(l
, aggstate
->hash_needed
)
778 int varNumber
= lfirst_int(l
) - 1;
780 hashslot
->tts_values
[varNumber
] = inputslot
->tts_values
[varNumber
];
781 hashslot
->tts_isnull
[varNumber
] = inputslot
->tts_isnull
[varNumber
];
784 /* find or create the hashtable entry using the filtered tuple */
785 entry
= (AggHashEntry
) LookupTupleHashEntry(aggstate
->hashtable
,
791 /* initialize aggregates for new tuple group */
792 initialize_aggregates(aggstate
, aggstate
->peragg
, entry
->pergroup
);
801 * ExecAgg receives tuples from its outer subplan and aggregates over
802 * the appropriate attribute for each aggregate function use (Aggref
803 * node) appearing in the targetlist or qual of the node. The number
804 * of tuples to aggregate over depends on whether grouped or plain
805 * aggregation is selected. In grouped aggregation, we produce a result
806 * row for each group; in plain aggregation there's a single result row
807 * for the whole query. In either case, the value of each aggregate is
808 * stored in the expression context to be used when ExecProject evaluates
812 ExecAgg(AggState
*node
)
818 * Check to see if we're still projecting out tuples from a previous agg
819 * tuple (because there is a function-returning-set in the projection
820 * expressions). If so, try to project another one.
822 if (node
->ss
.ps
.ps_TupFromTlist
)
824 TupleTableSlot
*result
;
827 result
= ExecProject(node
->ss
.ps
.ps_ProjInfo
, &isDone
);
828 if (isDone
== ExprMultipleResult
)
830 /* Done with that source tuple... */
831 node
->ss
.ps
.ps_TupFromTlist
= false;
834 if (((Agg
*) node
->ss
.ps
.plan
)->aggstrategy
== AGG_HASHED
)
836 if (!node
->table_filled
)
837 agg_fill_hash_table(node
);
838 return agg_retrieve_hash_table(node
);
841 return agg_retrieve_direct(node
);
845 * ExecAgg for non-hashed case
847 static TupleTableSlot
*
848 agg_retrieve_direct(AggState
*aggstate
)
850 Agg
*node
= (Agg
*) aggstate
->ss
.ps
.plan
;
851 PlanState
*outerPlan
;
852 ExprContext
*econtext
;
853 ExprContext
*tmpcontext
;
856 AggStatePerAgg peragg
;
857 AggStatePerGroup pergroup
;
858 TupleTableSlot
*outerslot
;
859 TupleTableSlot
*firstSlot
;
863 * get state info from node
865 outerPlan
= outerPlanState(aggstate
);
866 /* econtext is the per-output-tuple expression context */
867 econtext
= aggstate
->ss
.ps
.ps_ExprContext
;
868 aggvalues
= econtext
->ecxt_aggvalues
;
869 aggnulls
= econtext
->ecxt_aggnulls
;
870 /* tmpcontext is the per-input-tuple expression context */
871 tmpcontext
= aggstate
->tmpcontext
;
872 peragg
= aggstate
->peragg
;
873 pergroup
= aggstate
->pergroup
;
874 firstSlot
= aggstate
->ss
.ss_ScanTupleSlot
;
877 * We loop retrieving groups until we find one matching
878 * aggstate->ss.ps.qual
880 while (!aggstate
->agg_done
)
883 * If we don't already have the first tuple of the new group, fetch it
884 * from the outer plan.
886 if (aggstate
->grp_firstTuple
== NULL
)
888 outerslot
= ExecProcNode(outerPlan
);
889 if (!TupIsNull(outerslot
))
892 * Make a copy of the first input tuple; we will use this for
893 * comparisons (in group mode) and for projection.
895 aggstate
->grp_firstTuple
= ExecCopySlotTuple(outerslot
);
899 /* outer plan produced no tuples at all */
900 aggstate
->agg_done
= true;
901 /* If we are grouping, we should produce no tuples too */
902 if (node
->aggstrategy
!= AGG_PLAIN
)
908 * Clear the per-output-tuple context for each group
910 ResetExprContext(econtext
);
913 * Initialize working state for a new input tuple group
915 initialize_aggregates(aggstate
, peragg
, pergroup
);
917 if (aggstate
->grp_firstTuple
!= NULL
)
920 * Store the copied first input tuple in the tuple table slot
921 * reserved for it. The tuple will be deleted when it is cleared
924 ExecStoreTuple(aggstate
->grp_firstTuple
,
928 aggstate
->grp_firstTuple
= NULL
; /* don't keep two pointers */
930 /* set up for first advance_aggregates call */
931 tmpcontext
->ecxt_outertuple
= firstSlot
;
934 * Process each outer-plan tuple, and then fetch the next one,
935 * until we exhaust the outer plan or cross a group boundary.
939 advance_aggregates(aggstate
, pergroup
);
941 /* Reset per-input-tuple context after each tuple */
942 ResetExprContext(tmpcontext
);
944 outerslot
= ExecProcNode(outerPlan
);
945 if (TupIsNull(outerslot
))
947 /* no more outer-plan tuples available */
948 aggstate
->agg_done
= true;
951 /* set up for next advance_aggregates call */
952 tmpcontext
->ecxt_outertuple
= outerslot
;
955 * If we are grouping, check whether we've crossed a group
958 if (node
->aggstrategy
== AGG_SORTED
)
960 if (!execTuplesMatch(firstSlot
,
962 node
->numCols
, node
->grpColIdx
,
963 aggstate
->eqfunctions
,
964 tmpcontext
->ecxt_per_tuple_memory
))
967 * Save the first input tuple of the next group.
969 aggstate
->grp_firstTuple
= ExecCopySlotTuple(outerslot
);
977 * Done scanning input tuple group. Finalize each aggregate
978 * calculation, and stash results in the per-output-tuple context.
980 for (aggno
= 0; aggno
< aggstate
->numaggs
; aggno
++)
982 AggStatePerAgg peraggstate
= &peragg
[aggno
];
983 AggStatePerGroup pergroupstate
= &pergroup
[aggno
];
985 if (peraggstate
->aggref
->aggdistinct
)
986 process_sorted_aggregate(aggstate
, peraggstate
, pergroupstate
);
988 finalize_aggregate(aggstate
, peraggstate
, pergroupstate
,
989 &aggvalues
[aggno
], &aggnulls
[aggno
]);
993 * Use the representative input tuple for any references to
994 * non-aggregated input columns in the qual and tlist. (If we are not
995 * grouping, and there are no input rows at all, we will come here
996 * with an empty firstSlot ... but if not grouping, there can't be any
997 * references to non-aggregated input columns, so no problem.)
999 econtext
->ecxt_outertuple
= firstSlot
;
1002 * Check the qual (HAVING clause); if the group does not match, ignore
1003 * it and loop back to try to process another group.
1005 if (ExecQual(aggstate
->ss
.ps
.qual
, econtext
, false))
1008 * Form and return a projection tuple using the aggregate results
1009 * and the representative input tuple.
1011 TupleTableSlot
*result
;
1012 ExprDoneCond isDone
;
1014 result
= ExecProject(aggstate
->ss
.ps
.ps_ProjInfo
, &isDone
);
1016 if (isDone
!= ExprEndResult
)
1018 aggstate
->ss
.ps
.ps_TupFromTlist
=
1019 (isDone
== ExprMultipleResult
);
1025 /* No more groups */
1030 * ExecAgg for hashed case: phase 1, read input and build hash table
1033 agg_fill_hash_table(AggState
*aggstate
)
1035 PlanState
*outerPlan
;
1036 ExprContext
*tmpcontext
;
1038 TupleTableSlot
*outerslot
;
1041 * get state info from node
1043 outerPlan
= outerPlanState(aggstate
);
1044 /* tmpcontext is the per-input-tuple expression context */
1045 tmpcontext
= aggstate
->tmpcontext
;
1048 * Process each outer-plan tuple, and then fetch the next one, until we
1049 * exhaust the outer plan.
1053 outerslot
= ExecProcNode(outerPlan
);
1054 if (TupIsNull(outerslot
))
1056 /* set up for advance_aggregates call */
1057 tmpcontext
->ecxt_outertuple
= outerslot
;
1059 /* Find or build hashtable entry for this tuple's group */
1060 entry
= lookup_hash_entry(aggstate
, outerslot
);
1062 /* Advance the aggregates */
1063 advance_aggregates(aggstate
, entry
->pergroup
);
1065 /* Reset per-input-tuple context after each tuple */
1066 ResetExprContext(tmpcontext
);
1069 aggstate
->table_filled
= true;
1070 /* Initialize to walk the hash table */
1071 ResetTupleHashIterator(aggstate
->hashtable
, &aggstate
->hashiter
);
1075 * ExecAgg for hashed case: phase 2, retrieving groups from hash table
1077 static TupleTableSlot
*
1078 agg_retrieve_hash_table(AggState
*aggstate
)
1080 ExprContext
*econtext
;
1083 AggStatePerAgg peragg
;
1084 AggStatePerGroup pergroup
;
1086 TupleTableSlot
*firstSlot
;
1090 * get state info from node
1092 /* econtext is the per-output-tuple expression context */
1093 econtext
= aggstate
->ss
.ps
.ps_ExprContext
;
1094 aggvalues
= econtext
->ecxt_aggvalues
;
1095 aggnulls
= econtext
->ecxt_aggnulls
;
1096 peragg
= aggstate
->peragg
;
1097 firstSlot
= aggstate
->ss
.ss_ScanTupleSlot
;
1100 * We loop retrieving groups until we find one satisfying
1101 * aggstate->ss.ps.qual
1103 while (!aggstate
->agg_done
)
1106 * Find the next entry in the hash table
1108 entry
= (AggHashEntry
) ScanTupleHashTable(&aggstate
->hashiter
);
1111 /* No more entries in hashtable, so done */
1112 aggstate
->agg_done
= TRUE
;
1117 * Clear the per-output-tuple context for each group
1119 ResetExprContext(econtext
);
1122 * Store the copied first input tuple in the tuple table slot reserved
1123 * for it, so that it can be used in ExecProject.
1125 ExecStoreMinimalTuple(entry
->shared
.firstTuple
,
1129 pergroup
= entry
->pergroup
;
1132 * Finalize each aggregate calculation, and stash results in the
1133 * per-output-tuple context.
1135 for (aggno
= 0; aggno
< aggstate
->numaggs
; aggno
++)
1137 AggStatePerAgg peraggstate
= &peragg
[aggno
];
1138 AggStatePerGroup pergroupstate
= &pergroup
[aggno
];
1140 Assert(!peraggstate
->aggref
->aggdistinct
);
1141 finalize_aggregate(aggstate
, peraggstate
, pergroupstate
,
1142 &aggvalues
[aggno
], &aggnulls
[aggno
]);
1146 * Use the representative input tuple for any references to
1147 * non-aggregated input columns in the qual and tlist.
1149 econtext
->ecxt_outertuple
= firstSlot
;
1152 * Check the qual (HAVING clause); if the group does not match, ignore
1153 * it and loop back to try to process another group.
1155 if (ExecQual(aggstate
->ss
.ps
.qual
, econtext
, false))
1158 * Form and return a projection tuple using the aggregate results
1159 * and the representative input tuple.
1161 TupleTableSlot
*result
;
1162 ExprDoneCond isDone
;
1164 result
= ExecProject(aggstate
->ss
.ps
.ps_ProjInfo
, &isDone
);
1166 if (isDone
!= ExprEndResult
)
1168 aggstate
->ss
.ps
.ps_TupFromTlist
=
1169 (isDone
== ExprMultipleResult
);
1175 /* No more groups */
1179 /* -----------------
1182 * Creates the run-time information for the agg node produced by the
1183 * planner and initializes its outer subtree
1187 ExecInitAgg(Agg
*node
, EState
*estate
, int eflags
)
1190 AggStatePerAgg peragg
;
1192 ExprContext
*econtext
;
1197 /* check for unsupported flags */
1198 Assert(!(eflags
& (EXEC_FLAG_BACKWARD
| EXEC_FLAG_MARK
)));
1201 * create state structure
1203 aggstate
= makeNode(AggState
);
1204 aggstate
->ss
.ps
.plan
= (Plan
*) node
;
1205 aggstate
->ss
.ps
.state
= estate
;
1207 aggstate
->aggs
= NIL
;
1208 aggstate
->numaggs
= 0;
1209 aggstate
->eqfunctions
= NULL
;
1210 aggstate
->hashfunctions
= NULL
;
1211 aggstate
->peragg
= NULL
;
1212 aggstate
->agg_done
= false;
1213 aggstate
->pergroup
= NULL
;
1214 aggstate
->grp_firstTuple
= NULL
;
1215 aggstate
->hashtable
= NULL
;
1218 * Create expression contexts. We need two, one for per-input-tuple
1219 * processing and one for per-output-tuple processing. We cheat a little
1220 * by using ExecAssignExprContext() to build both.
1222 ExecAssignExprContext(estate
, &aggstate
->ss
.ps
);
1223 aggstate
->tmpcontext
= aggstate
->ss
.ps
.ps_ExprContext
;
1224 ExecAssignExprContext(estate
, &aggstate
->ss
.ps
);
1227 * We also need a long-lived memory context for holding hashtable data
1228 * structures and transition values. NOTE: the details of what is stored
1229 * in aggcontext and what is stored in the regular per-query memory
1230 * context are driven by a simple decision: we want to reset the
1231 * aggcontext in ExecReScanAgg to recover no-longer-wanted space.
1233 aggstate
->aggcontext
=
1234 AllocSetContextCreate(CurrentMemoryContext
,
1236 ALLOCSET_DEFAULT_MINSIZE
,
1237 ALLOCSET_DEFAULT_INITSIZE
,
1238 ALLOCSET_DEFAULT_MAXSIZE
);
1240 #define AGG_NSLOTS 3
1243 * tuple table initialization
1245 ExecInitScanTupleSlot(estate
, &aggstate
->ss
);
1246 ExecInitResultTupleSlot(estate
, &aggstate
->ss
.ps
);
1247 aggstate
->hashslot
= ExecInitExtraTupleSlot(estate
);
1250 * initialize child expressions
1252 * Note: ExecInitExpr finds Aggrefs for us, and also checks that no aggs
1253 * contain other agg calls in their arguments. This would make no sense
1254 * under SQL semantics anyway (and it's forbidden by the spec). Because
1255 * that is true, we don't need to worry about evaluating the aggs in any
1258 aggstate
->ss
.ps
.targetlist
= (List
*)
1259 ExecInitExpr((Expr
*) node
->plan
.targetlist
,
1260 (PlanState
*) aggstate
);
1261 aggstate
->ss
.ps
.qual
= (List
*)
1262 ExecInitExpr((Expr
*) node
->plan
.qual
,
1263 (PlanState
*) aggstate
);
1266 * initialize child nodes
1268 * If we are doing a hashed aggregation then the child plan does not need
1269 * to handle REWIND efficiently; see ExecReScanAgg.
1271 if (node
->aggstrategy
== AGG_HASHED
)
1272 eflags
&= ~EXEC_FLAG_REWIND
;
1273 outerPlan
= outerPlan(node
);
1274 outerPlanState(aggstate
) = ExecInitNode(outerPlan
, estate
, eflags
);
1277 * initialize source tuple type.
1279 ExecAssignScanTypeFromOuterPlan(&aggstate
->ss
);
1282 * Initialize result tuple type and projection info.
1284 ExecAssignResultTypeFromTL(&aggstate
->ss
.ps
);
1285 ExecAssignProjectionInfo(&aggstate
->ss
.ps
, NULL
);
1287 aggstate
->ss
.ps
.ps_TupFromTlist
= false;
1290 * get the count of aggregates in targetlist and quals
1292 numaggs
= aggstate
->numaggs
;
1293 Assert(numaggs
== list_length(aggstate
->aggs
));
1297 * This is not an error condition: we might be using the Agg node just
1298 * to do hash-based grouping. Even in the regular case,
1299 * constant-expression simplification could optimize away all of the
1300 * Aggrefs in the targetlist and qual. So keep going, but force local
1301 * copy of numaggs positive so that palloc()s below don't choke.
1307 * If we are grouping, precompute fmgr lookup data for inner loop. We need
1308 * both equality and hashing functions to do it by hashing, but only
1309 * equality if not hashing.
1311 if (node
->numCols
> 0)
1313 if (node
->aggstrategy
== AGG_HASHED
)
1314 execTuplesHashPrepare(node
->numCols
,
1316 &aggstate
->eqfunctions
,
1317 &aggstate
->hashfunctions
);
1319 aggstate
->eqfunctions
=
1320 execTuplesMatchPrepare(node
->numCols
,
1321 node
->grpOperators
);
1325 * Set up aggregate-result storage in the output expr context, and also
1326 * allocate my private per-agg working storage
1328 econtext
= aggstate
->ss
.ps
.ps_ExprContext
;
1329 econtext
->ecxt_aggvalues
= (Datum
*) palloc0(sizeof(Datum
) * numaggs
);
1330 econtext
->ecxt_aggnulls
= (bool *) palloc0(sizeof(bool) * numaggs
);
1332 peragg
= (AggStatePerAgg
) palloc0(sizeof(AggStatePerAggData
) * numaggs
);
1333 aggstate
->peragg
= peragg
;
1335 if (node
->aggstrategy
== AGG_HASHED
)
1337 build_hash_table(aggstate
);
1338 aggstate
->table_filled
= false;
1339 /* Compute the columns we actually need to hash on */
1340 aggstate
->hash_needed
= find_hash_columns(aggstate
);
1344 AggStatePerGroup pergroup
;
1346 pergroup
= (AggStatePerGroup
) palloc0(sizeof(AggStatePerGroupData
) * numaggs
);
1347 aggstate
->pergroup
= pergroup
;
1351 * Perform lookups of aggregate function info, and initialize the
1352 * unchanging fields of the per-agg data. We also detect duplicate
1353 * aggregates (for example, "SELECT sum(x) ... HAVING sum(x) > 0"). When
1354 * duplicates are detected, we only make an AggStatePerAgg struct for the
1355 * first one. The clones are simply pointed at the same result entry by
1356 * giving them duplicate aggno values.
1359 foreach(l
, aggstate
->aggs
)
1361 AggrefExprState
*aggrefstate
= (AggrefExprState
*) lfirst(l
);
1362 Aggref
*aggref
= (Aggref
*) aggrefstate
->xprstate
.expr
;
1363 AggStatePerAgg peraggstate
;
1364 Oid inputTypes
[FUNC_MAX_ARGS
];
1367 Form_pg_aggregate aggform
;
1369 AclResult aclresult
;
1378 /* Planner should have assigned aggregate to correct level */
1379 Assert(aggref
->agglevelsup
== 0);
1381 /* Look for a previous duplicate aggregate */
1382 for (i
= 0; i
<= aggno
; i
++)
1384 if (equal(aggref
, peragg
[i
].aggref
) &&
1385 !contain_volatile_functions((Node
*) aggref
))
1390 /* Found a match to an existing entry, so just mark it */
1391 aggrefstate
->aggno
= i
;
1395 /* Nope, so assign a new PerAgg record */
1396 peraggstate
= &peragg
[++aggno
];
1398 /* Mark Aggref state node with assigned index in the result array */
1399 aggrefstate
->aggno
= aggno
;
1401 /* Fill in the peraggstate data */
1402 peraggstate
->aggrefstate
= aggrefstate
;
1403 peraggstate
->aggref
= aggref
;
1404 numArguments
= list_length(aggref
->args
);
1405 peraggstate
->numArguments
= numArguments
;
1408 * Get actual datatypes of the inputs. These could be different from
1409 * the agg's declared input types, when the agg accepts ANY or a
1413 foreach(lc
, aggref
->args
)
1415 inputTypes
[i
++] = exprType((Node
*) lfirst(lc
));
1418 aggTuple
= SearchSysCache(AGGFNOID
,
1419 ObjectIdGetDatum(aggref
->aggfnoid
),
1421 if (!HeapTupleIsValid(aggTuple
))
1422 elog(ERROR
, "cache lookup failed for aggregate %u",
1424 aggform
= (Form_pg_aggregate
) GETSTRUCT(aggTuple
);
1426 /* Check permission to call aggregate function */
1427 aclresult
= pg_proc_aclcheck(aggref
->aggfnoid
, GetUserId(),
1429 if (aclresult
!= ACLCHECK_OK
)
1430 aclcheck_error(aclresult
, ACL_KIND_PROC
,
1431 get_func_name(aggref
->aggfnoid
));
1433 peraggstate
->transfn_oid
= transfn_oid
= aggform
->aggtransfn
;
1434 peraggstate
->finalfn_oid
= finalfn_oid
= aggform
->aggfinalfn
;
1436 /* Check that aggregate owner has permission to call component fns */
1438 HeapTuple procTuple
;
1441 procTuple
= SearchSysCache(PROCOID
,
1442 ObjectIdGetDatum(aggref
->aggfnoid
),
1444 if (!HeapTupleIsValid(procTuple
))
1445 elog(ERROR
, "cache lookup failed for function %u",
1447 aggOwner
= ((Form_pg_proc
) GETSTRUCT(procTuple
))->proowner
;
1448 ReleaseSysCache(procTuple
);
1450 aclresult
= pg_proc_aclcheck(transfn_oid
, aggOwner
,
1452 if (aclresult
!= ACLCHECK_OK
)
1453 aclcheck_error(aclresult
, ACL_KIND_PROC
,
1454 get_func_name(transfn_oid
));
1455 if (OidIsValid(finalfn_oid
))
1457 aclresult
= pg_proc_aclcheck(finalfn_oid
, aggOwner
,
1459 if (aclresult
!= ACLCHECK_OK
)
1460 aclcheck_error(aclresult
, ACL_KIND_PROC
,
1461 get_func_name(finalfn_oid
));
1465 /* resolve actual type of transition state, if polymorphic */
1466 aggtranstype
= aggform
->aggtranstype
;
1467 if (IsPolymorphicType(aggtranstype
))
1469 /* have to fetch the agg's declared input types... */
1470 Oid
*declaredArgTypes
;
1473 (void) get_func_signature(aggref
->aggfnoid
,
1474 &declaredArgTypes
, &agg_nargs
);
1475 Assert(agg_nargs
== numArguments
);
1476 aggtranstype
= enforce_generic_type_consistency(inputTypes
,
1481 pfree(declaredArgTypes
);
1484 /* build expression trees using actual argument & result types */
1485 build_aggregate_fnexprs(inputTypes
,
1494 fmgr_info(transfn_oid
, &peraggstate
->transfn
);
1495 peraggstate
->transfn
.fn_expr
= (Node
*) transfnexpr
;
1497 if (OidIsValid(finalfn_oid
))
1499 fmgr_info(finalfn_oid
, &peraggstate
->finalfn
);
1500 peraggstate
->finalfn
.fn_expr
= (Node
*) finalfnexpr
;
1503 get_typlenbyval(aggref
->aggtype
,
1504 &peraggstate
->resulttypeLen
,
1505 &peraggstate
->resulttypeByVal
);
1506 get_typlenbyval(aggtranstype
,
1507 &peraggstate
->transtypeLen
,
1508 &peraggstate
->transtypeByVal
);
1511 * initval is potentially null, so don't try to access it as a struct
1512 * field. Must do it the hard way with SysCacheGetAttr.
1514 textInitVal
= SysCacheGetAttr(AGGFNOID
, aggTuple
,
1515 Anum_pg_aggregate_agginitval
,
1516 &peraggstate
->initValueIsNull
);
1518 if (peraggstate
->initValueIsNull
)
1519 peraggstate
->initValue
= (Datum
) 0;
1521 peraggstate
->initValue
= GetAggInitVal(textInitVal
,
1525 * If the transfn is strict and the initval is NULL, make sure input
1526 * type and transtype are the same (or at least binary-compatible), so
1527 * that it's OK to use the first input value as the initial
1528 * transValue. This should have been checked at agg definition time,
1529 * but just in case...
1531 if (peraggstate
->transfn
.fn_strict
&& peraggstate
->initValueIsNull
)
1533 if (numArguments
< 1 ||
1534 !IsBinaryCoercible(inputTypes
[0], aggtranstype
))
1536 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION
),
1537 errmsg("aggregate %u needs to have compatible input type and transition type",
1538 aggref
->aggfnoid
)));
1541 if (aggref
->aggdistinct
)
1546 /* We don't implement DISTINCT aggs in the HASHED case */
1547 Assert(node
->aggstrategy
!= AGG_HASHED
);
1550 * We don't currently implement DISTINCT aggs for aggs having more
1551 * than one argument. This isn't required for anything in the SQL
1552 * spec, but really it ought to be implemented for
1553 * feature-completeness. FIXME someday.
1555 if (numArguments
!= 1)
1557 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
1558 errmsg("DISTINCT is supported only for single-argument aggregates")));
1560 peraggstate
->inputType
= inputTypes
[0];
1561 get_typlenbyval(inputTypes
[0],
1562 &peraggstate
->inputtypeLen
,
1563 &peraggstate
->inputtypeByVal
);
1566 * Look up the sorting and comparison operators to use. XXX it's
1567 * pretty bletcherous to be making this sort of semantic decision
1568 * in the executor. Probably the parser should decide this and
1569 * record it in the Aggref node ... or at latest, do it in the
1572 get_sort_group_operators(inputTypes
[0],
1574 <_opr
, &eq_opr
, NULL
);
1575 fmgr_info(get_opcode(eq_opr
), &(peraggstate
->equalfn
));
1576 peraggstate
->sortOperator
= lt_opr
;
1577 peraggstate
->sortstate
= NULL
;
1580 ReleaseSysCache(aggTuple
);
1583 /* Update numaggs to match number of unique aggregates found */
1584 aggstate
->numaggs
= aggno
+ 1;
1590 GetAggInitVal(Datum textInitVal
, Oid transtype
)
1597 getTypeInputInfo(transtype
, &typinput
, &typioparam
);
1598 strInitVal
= TextDatumGetCString(textInitVal
);
1599 initVal
= OidInputFunctionCall(typinput
, strInitVal
,
1606 ExecCountSlotsAgg(Agg
*node
)
1608 return ExecCountSlotsNode(outerPlan(node
)) +
1609 ExecCountSlotsNode(innerPlan(node
)) +
1614 ExecEndAgg(AggState
*node
)
1616 PlanState
*outerPlan
;
1619 /* Make sure we have closed any open tuplesorts */
1620 for (aggno
= 0; aggno
< node
->numaggs
; aggno
++)
1622 AggStatePerAgg peraggstate
= &node
->peragg
[aggno
];
1624 if (peraggstate
->sortstate
)
1625 tuplesort_end(peraggstate
->sortstate
);
1629 * Free both the expr contexts.
1631 ExecFreeExprContext(&node
->ss
.ps
);
1632 node
->ss
.ps
.ps_ExprContext
= node
->tmpcontext
;
1633 ExecFreeExprContext(&node
->ss
.ps
);
1635 /* clean up tuple table */
1636 ExecClearTuple(node
->ss
.ss_ScanTupleSlot
);
1638 MemoryContextDelete(node
->aggcontext
);
1640 outerPlan
= outerPlanState(node
);
1641 ExecEndNode(outerPlan
);
1645 ExecReScanAgg(AggState
*node
, ExprContext
*exprCtxt
)
1647 ExprContext
*econtext
= node
->ss
.ps
.ps_ExprContext
;
1650 node
->agg_done
= false;
1652 node
->ss
.ps
.ps_TupFromTlist
= false;
1654 if (((Agg
*) node
->ss
.ps
.plan
)->aggstrategy
== AGG_HASHED
)
1657 * In the hashed case, if we haven't yet built the hash table then we
1658 * can just return; nothing done yet, so nothing to undo. If subnode's
1659 * chgParam is not NULL then it will be re-scanned by ExecProcNode,
1660 * else no reason to re-scan it at all.
1662 if (!node
->table_filled
)
1666 * If we do have the hash table and the subplan does not have any
1667 * parameter changes, then we can just rescan the existing hash table;
1668 * no need to build it again.
1670 if (((PlanState
*) node
)->lefttree
->chgParam
== NULL
)
1672 ResetTupleHashIterator(node
->hashtable
, &node
->hashiter
);
1677 /* Make sure we have closed any open tuplesorts */
1678 for (aggno
= 0; aggno
< node
->numaggs
; aggno
++)
1680 AggStatePerAgg peraggstate
= &node
->peragg
[aggno
];
1682 if (peraggstate
->sortstate
)
1683 tuplesort_end(peraggstate
->sortstate
);
1684 peraggstate
->sortstate
= NULL
;
1687 /* Release first tuple of group, if we have made a copy */
1688 if (node
->grp_firstTuple
!= NULL
)
1690 heap_freetuple(node
->grp_firstTuple
);
1691 node
->grp_firstTuple
= NULL
;
1694 /* Forget current agg values */
1695 MemSet(econtext
->ecxt_aggvalues
, 0, sizeof(Datum
) * node
->numaggs
);
1696 MemSet(econtext
->ecxt_aggnulls
, 0, sizeof(bool) * node
->numaggs
);
1699 * Release all temp storage. Note that with AGG_HASHED, the hash table is
1700 * allocated in a sub-context of the aggcontext. We're going to rebuild
1701 * the hash table from scratch, so we need to use
1702 * MemoryContextResetAndDeleteChildren() to avoid leaking the old hash
1703 * table's memory context header.
1705 MemoryContextResetAndDeleteChildren(node
->aggcontext
);
1707 if (((Agg
*) node
->ss
.ps
.plan
)->aggstrategy
== AGG_HASHED
)
1709 /* Rebuild an empty hash table */
1710 build_hash_table(node
);
1711 node
->table_filled
= false;
1716 * Reset the per-group state (in particular, mark transvalues null)
1718 MemSet(node
->pergroup
, 0,
1719 sizeof(AggStatePerGroupData
) * node
->numaggs
);
1723 * if chgParam of subnode is not null then plan will be re-scanned by
1724 * first ExecProcNode.
1726 if (((PlanState
*) node
)->lefttree
->chgParam
== NULL
)
1727 ExecReScan(((PlanState
*) node
)->lefttree
, exprCtxt
);
1731 * aggregate_dummy - dummy execution routine for aggregate functions
1733 * This function is listed as the implementation (prosrc field) of pg_proc
1734 * entries for aggregate functions. Its only purpose is to throw an error
1735 * if someone mistakenly executes such a function in the normal way.
1737 * Perhaps someday we could assign real meaning to the prosrc field of
1741 aggregate_dummy(PG_FUNCTION_ARGS
)
1743 elog(ERROR
, "aggregate function %u called as normal function",
1744 fcinfo
->flinfo
->fn_oid
);
1745 return (Datum
) 0; /* keep compiler quiet */