]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeAgg.c
Add an at-least-marginally-plausible method of estimating the number
[postgresql] / src / backend / executor / nodeAgg.c
1 /*-------------------------------------------------------------------------
2  *
3  * nodeAgg.c
4  *        Routines to handle aggregate nodes.
5  *
6  *        ExecAgg evaluates each aggregate in the following steps:
7  *
8  *               transvalue = initcond
9  *               foreach input_value do
10  *                      transvalue = transfunc(transvalue, input_value)
11  *               result = finalfunc(transvalue)
12  *
13  *        If a finalfunc is not supplied then the result is just the ending
14  *        value of transvalue.
15  *
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 input type and transtype must be the same in this case!
20  *
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_value for itself.
25  *
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.
31  *
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.
42  *
43  *
44  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
45  * Portions Copyright (c) 1994, Regents of the University of California
46  *
47  * IDENTIFICATION
48  *        $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.96 2002/11/19 23:21:57 tgl Exp $
49  *
50  *-------------------------------------------------------------------------
51  */
52
53 #include "postgres.h"
54
55 #include "access/heapam.h"
56 #include "catalog/pg_aggregate.h"
57 #include "catalog/pg_operator.h"
58 #include "executor/executor.h"
59 #include "executor/nodeAgg.h"
60 #include "executor/nodeGroup.h"
61 #include "executor/nodeHash.h"
62 #include "miscadmin.h"
63 #include "optimizer/clauses.h"
64 #include "parser/parse_coerce.h"
65 #include "parser/parse_expr.h"
66 #include "parser/parse_oper.h"
67 #include "utils/acl.h"
68 #include "utils/builtins.h"
69 #include "utils/lsyscache.h"
70 #include "utils/syscache.h"
71 #include "utils/tuplesort.h"
72 #include "utils/datum.h"
73
74
75 /*
76  * AggStatePerAggData - per-aggregate working state for the Agg scan
77  */
78 typedef struct AggStatePerAggData
79 {
80         /*
81          * These values are set up during ExecInitAgg() and do not change
82          * thereafter:
83          */
84
85         /* Link to Aggref node this working state is for */
86         Aggref     *aggref;
87
88         /* Oids of transfer functions */
89         Oid                     transfn_oid;
90         Oid                     finalfn_oid;    /* may be InvalidOid */
91
92         /*
93          * fmgr lookup data for transfer functions --- only valid when
94          * corresponding oid is not InvalidOid.  Note in particular that
95          * fn_strict flags are kept here.
96          */
97         FmgrInfo        transfn;
98         FmgrInfo        finalfn;
99
100         /*
101          * Type of input data and Oid of sort operator to use for it; only
102          * set/used when aggregate has DISTINCT flag.  (These are not used
103          * directly by nodeAgg, but must be passed to the Tuplesort object.)
104          */
105         Oid                     inputType;
106         Oid                     sortOperator;
107
108         /*
109          * fmgr lookup data for input type's equality operator --- only
110          * set/used when aggregate has DISTINCT flag.
111          */
112         FmgrInfo        equalfn;
113
114         /*
115          * initial value from pg_aggregate entry
116          */
117         Datum           initValue;
118         bool            initValueIsNull;
119
120         /*
121          * We need the len and byval info for the agg's input, result, and
122          * transition data types in order to know how to copy/delete values.
123          */
124         int16           inputtypeLen,
125                                 resulttypeLen,
126                                 transtypeLen;
127         bool            inputtypeByVal,
128                                 resulttypeByVal,
129                                 transtypeByVal;
130
131         /*
132          * These values are working state that is initialized at the start of
133          * an input tuple group and updated for each input tuple.
134          *
135          * For a simple (non DISTINCT) aggregate, we just feed the input values
136          * straight to the transition function.  If it's DISTINCT, we pass the
137          * input values into a Tuplesort object; then at completion of the
138          * input tuple group, we scan the sorted values, eliminate duplicates,
139          * and run the transition function on the rest.
140          */
141
142         Tuplesortstate *sortstate;      /* sort object, if a DISTINCT agg */
143 } AggStatePerAggData;
144
145 /*
146  * AggStatePerGroupData - per-aggregate-per-group working state
147  *
148  * These values are working state that is initialized at the start of
149  * an input tuple group and updated for each input tuple.
150  *
151  * In AGG_PLAIN and AGG_SORTED modes, we have a single array of these
152  * structs (pointed to by aggstate->pergroup); we re-use the array for
153  * each input group, if it's AGG_SORTED mode.  In AGG_HASHED mode, the
154  * hash table contains an array of these structs for each tuple group.
155  *
156  * Logically, the sortstate field belongs in this struct, but we do not
157  * keep it here for space reasons: we don't support DISTINCT aggregates
158  * in AGG_HASHED mode, so there's no reason to use up a pointer field
159  * in every entry of the hashtable.
160  */
161 typedef struct AggStatePerGroupData
162 {
163         Datum           transValue;             /* current transition value */
164         bool            transValueIsNull;
165
166         bool            noTransValue;   /* true if transValue not set yet */
167
168         /*
169          * Note: noTransValue initially has the same value as
170          * transValueIsNull, and if true both are cleared to false at the same
171          * time.  They are not the same though: if transfn later returns a
172          * NULL, we want to keep that NULL and not auto-replace it with a
173          * later input value. Only the first non-NULL input will be
174          * auto-substituted.
175          */
176 } AggStatePerGroupData;
177
178 /*
179  * To implement hashed aggregation, we need a hashtable that stores a
180  * representative tuple and an array of AggStatePerGroup structs for each
181  * distinct set of GROUP BY column values.  We compute the hash key from
182  * the GROUP BY columns.
183  */
184 typedef struct AggHashEntryData
185 {
186         AggHashEntry    next;           /* next entry in same hash bucket */
187         uint32          hashkey;                /* exact hash key of this entry */
188         HeapTuple       firstTuple;             /* copy of first tuple in this group */
189         /* per-aggregate transition status array - must be last! */
190         AggStatePerGroupData pergroup[1];       /* VARIABLE LENGTH ARRAY */
191 } AggHashEntryData;                             /* VARIABLE LENGTH STRUCT */
192
193 typedef struct AggHashTableData
194 {
195         int                     nbuckets;               /* number of buckets in hash table */
196         AggHashEntry buckets[1];        /* VARIABLE LENGTH ARRAY */
197 } AggHashTableData;                             /* VARIABLE LENGTH STRUCT */
198
199
200 static void initialize_aggregates(AggState *aggstate,
201                                                                   AggStatePerAgg peragg,
202                                                                   AggStatePerGroup pergroup);
203 static void advance_transition_function(AggState *aggstate,
204                                                                                 AggStatePerAgg peraggstate,
205                                                                                 AggStatePerGroup pergroupstate,
206                                                                                 Datum newVal, bool isNull);
207 static void advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup);
208 static void process_sorted_aggregate(AggState *aggstate,
209                                                                          AggStatePerAgg peraggstate,
210                                                                          AggStatePerGroup pergroupstate);
211 static void finalize_aggregate(AggState *aggstate,
212                                                            AggStatePerAgg peraggstate,
213                                                            AggStatePerGroup pergroupstate,
214                                                            Datum *resultVal, bool *resultIsNull);
215 static void build_hash_table(Agg *node);
216 static AggHashEntry lookup_hash_entry(Agg *node, TupleTableSlot *slot);
217 static TupleTableSlot *agg_retrieve_direct(Agg *node);
218 static void agg_fill_hash_table(Agg *node);
219 static TupleTableSlot *agg_retrieve_hash_table(Agg *node);
220 static Datum GetAggInitVal(Datum textInitVal, Oid transtype);
221
222
223 /*
224  * Initialize all aggregates for a new group of input values.
225  *
226  * When called, CurrentMemoryContext should be the per-query context.
227  */
228 static void
229 initialize_aggregates(AggState *aggstate,
230                                           AggStatePerAgg peragg,
231                                           AggStatePerGroup pergroup)
232 {
233         int                     aggno;
234
235         for (aggno = 0; aggno < aggstate->numaggs; aggno++)
236         {
237                 AggStatePerAgg peraggstate = &peragg[aggno];
238                 AggStatePerGroup pergroupstate = &pergroup[aggno];
239                 Aggref     *aggref = peraggstate->aggref;
240
241                 /*
242                  * Start a fresh sort operation for each DISTINCT aggregate.
243                  */
244                 if (aggref->aggdistinct)
245                 {
246                         /*
247                          * In case of rescan, maybe there could be an uncompleted sort
248                          * operation?  Clean it up if so.
249                          */
250                         if (peraggstate->sortstate)
251                                 tuplesort_end(peraggstate->sortstate);
252
253                         peraggstate->sortstate =
254                                 tuplesort_begin_datum(peraggstate->inputType,
255                                                                           peraggstate->sortOperator,
256                                                                           false);
257                 }
258
259                 /*
260                  * (Re)set transValue to the initial value.
261                  *
262                  * Note that when the initial value is pass-by-ref, we must copy it
263                  * (into the aggcontext) since we will pfree the transValue later.
264                  */
265                 if (peraggstate->initValueIsNull)
266                         pergroupstate->transValue = peraggstate->initValue;
267                 else
268                 {
269                         MemoryContext oldContext;
270
271                         oldContext = MemoryContextSwitchTo(aggstate->aggcontext);
272                         pergroupstate->transValue = datumCopy(peraggstate->initValue,
273                                                                                                   peraggstate->transtypeByVal,
274                                                                                                   peraggstate->transtypeLen);
275                         MemoryContextSwitchTo(oldContext);
276                 }
277                 pergroupstate->transValueIsNull = peraggstate->initValueIsNull;
278
279                 /*
280                  * If the initial value for the transition state doesn't exist in the
281                  * pg_aggregate table then we will let the first non-NULL value
282                  * returned from the outer procNode become the initial value. (This is
283                  * useful for aggregates like max() and min().)  The noTransValue flag
284                  * signals that we still need to do this.
285                  */
286                 pergroupstate->noTransValue = peraggstate->initValueIsNull;
287         }
288 }
289
290 /*
291  * Given a new input value, advance the transition function of an aggregate.
292  *
293  * It doesn't matter which memory context this is called in.
294  */
295 static void
296 advance_transition_function(AggState *aggstate,
297                                                         AggStatePerAgg peraggstate,
298                                                         AggStatePerGroup pergroupstate,
299                                                         Datum newVal, bool isNull)
300 {
301         FunctionCallInfoData fcinfo;
302         MemoryContext oldContext;
303
304         if (peraggstate->transfn.fn_strict)
305         {
306                 /*
307                  * For a strict transfn, nothing happens at a NULL input
308                  * tuple; we just keep the prior transValue.
309                  */
310                 if (isNull)
311                         return;
312                 if (pergroupstate->noTransValue)
313                 {
314                         /*
315                          * transValue has not been initialized. This is the first
316                          * non-NULL input value. We use it as the initial value for
317                          * transValue. (We already checked that the agg's input type
318                          * is binary-compatible with its transtype, so straight copy
319                          * here is OK.)
320                          *
321                          * We must copy the datum into aggcontext if it is pass-by-ref.
322                          * We do not need to pfree the old transValue, since it's NULL.
323                          */
324                         oldContext = MemoryContextSwitchTo(aggstate->aggcontext);
325                         pergroupstate->transValue = datumCopy(newVal,
326                                                                                                   peraggstate->transtypeByVal,
327                                                                                                   peraggstate->transtypeLen);
328                         pergroupstate->transValueIsNull = false;
329                         pergroupstate->noTransValue = false;
330                         MemoryContextSwitchTo(oldContext);
331                         return;
332                 }
333                 if (pergroupstate->transValueIsNull)
334                 {
335                         /*
336                          * Don't call a strict function with NULL inputs.  Note it is
337                          * possible to get here despite the above tests, if the
338                          * transfn is strict *and* returned a NULL on a prior cycle.
339                          * If that happens we will propagate the NULL all the way to
340                          * the end.
341                          */
342                         return;
343                 }
344         }
345
346         /* We run the transition functions in per-input-tuple memory context */
347         oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
348
349         /*
350          * OK to call the transition function
351          *
352          * This is heavily-used code, so manually zero just the necessary fields
353          * instead of using MemSet().  Compare FunctionCall2().
354          */
355
356         /* MemSet(&fcinfo, 0, sizeof(fcinfo)); */
357         fcinfo.context = NULL;
358         fcinfo.resultinfo = NULL;
359         fcinfo.isnull = false;
360
361         fcinfo.flinfo = &peraggstate->transfn;
362         fcinfo.nargs = 2;
363         fcinfo.arg[0] = pergroupstate->transValue;
364         fcinfo.argnull[0] = pergroupstate->transValueIsNull;
365         fcinfo.arg[1] = newVal;
366         fcinfo.argnull[1] = isNull;
367
368         newVal = FunctionCallInvoke(&fcinfo);
369
370         /*
371          * If pass-by-ref datatype, must copy the new value into aggcontext and
372          * pfree the prior transValue.  But if transfn returned a pointer to its
373          * first input, we don't need to do anything.
374          */
375         if (!peraggstate->transtypeByVal &&
376                 DatumGetPointer(newVal) != DatumGetPointer(pergroupstate->transValue))
377         {
378                 if (!fcinfo.isnull)
379                 {
380                         MemoryContextSwitchTo(aggstate->aggcontext);
381                         newVal = datumCopy(newVal,
382                                                            peraggstate->transtypeByVal,
383                                                            peraggstate->transtypeLen);
384                 }
385                 if (!pergroupstate->transValueIsNull)
386                         pfree(DatumGetPointer(pergroupstate->transValue));
387         }
388
389         pergroupstate->transValue = newVal;
390         pergroupstate->transValueIsNull = fcinfo.isnull;
391
392         MemoryContextSwitchTo(oldContext);
393 }
394
395 /*
396  * Advance all the aggregates for one input tuple.  The input tuple
397  * has been stored in tmpcontext->ecxt_scantuple, so that it is accessible
398  * to ExecEvalExpr.  pergroup is the array of per-group structs to use
399  * (this might be in a hashtable entry).
400  *
401  * When called, CurrentMemoryContext should be the per-query context.
402  */
403 static void
404 advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
405 {
406         ExprContext *econtext = aggstate->tmpcontext;
407         int                     aggno;
408
409         for (aggno = 0; aggno < aggstate->numaggs; aggno++)
410         {
411                 AggStatePerAgg peraggstate = &aggstate->peragg[aggno];
412                 AggStatePerGroup pergroupstate = &pergroup[aggno];
413                 Aggref     *aggref = peraggstate->aggref;
414                 Datum           newVal;
415                 bool            isNull;
416
417                 newVal = ExecEvalExprSwitchContext(aggref->target, econtext,
418                                                                                    &isNull, NULL);
419
420                 if (aggref->aggdistinct)
421                 {
422                         /* in DISTINCT mode, we may ignore nulls */
423                         if (isNull)
424                                 continue;
425                         tuplesort_putdatum(peraggstate->sortstate, newVal, isNull);
426                 }
427                 else
428                 {
429                         advance_transition_function(aggstate, peraggstate, pergroupstate,
430                                                                                 newVal, isNull);
431                 }
432         }
433 }
434
435 /*
436  * Run the transition function for a DISTINCT aggregate.  This is called
437  * after we have completed entering all the input values into the sort
438  * object.      We complete the sort, read out the values in sorted order,
439  * and run the transition function on each non-duplicate value.
440  *
441  * When called, CurrentMemoryContext should be the per-query context.
442  */
443 static void
444 process_sorted_aggregate(AggState *aggstate,
445                                                  AggStatePerAgg peraggstate,
446                                                  AggStatePerGroup pergroupstate)
447 {
448         Datum           oldVal = (Datum) 0;
449         bool            haveOldVal = false;
450         MemoryContext workcontext = aggstate->tmpcontext->ecxt_per_tuple_memory;
451         MemoryContext oldContext;
452         Datum           newVal;
453         bool            isNull;
454
455         tuplesort_performsort(peraggstate->sortstate);
456
457         /*
458          * Note: if input type is pass-by-ref, the datums returned by the sort
459          * are freshly palloc'd in the per-query context, so we must be
460          * careful to pfree them when they are no longer needed.
461          */
462
463         while (tuplesort_getdatum(peraggstate->sortstate, true,
464                                                           &newVal, &isNull))
465         {
466                 /*
467                  * DISTINCT always suppresses nulls, per SQL spec, regardless of
468                  * the transition function's strictness.
469                  */
470                 if (isNull)
471                         continue;
472
473                 /*
474                  * Clear and select the working context for evaluation of
475                  * the equality function and transition function.
476                  */
477                 MemoryContextReset(workcontext);
478                 oldContext = MemoryContextSwitchTo(workcontext);
479
480                 if (haveOldVal &&
481                         DatumGetBool(FunctionCall2(&peraggstate->equalfn,
482                                                                            oldVal, newVal)))
483                 {
484                         /* equal to prior, so forget this one */
485                         if (!peraggstate->inputtypeByVal)
486                                 pfree(DatumGetPointer(newVal));
487                 }
488                 else
489                 {
490                         advance_transition_function(aggstate, peraggstate, pergroupstate,
491                                                                                 newVal, false);
492                         /* forget the old value, if any */
493                         if (haveOldVal && !peraggstate->inputtypeByVal)
494                                 pfree(DatumGetPointer(oldVal));
495                         /* and remember the new one for subsequent equality checks */
496                         oldVal = newVal;
497                         haveOldVal = true;
498                 }
499
500                 MemoryContextSwitchTo(oldContext);
501         }
502
503         if (haveOldVal && !peraggstate->inputtypeByVal)
504                 pfree(DatumGetPointer(oldVal));
505
506         tuplesort_end(peraggstate->sortstate);
507         peraggstate->sortstate = NULL;
508 }
509
510 /*
511  * Compute the final value of one aggregate.
512  *
513  * The finalfunction will be run, and the result delivered, in the
514  * output-tuple context; caller's CurrentMemoryContext does not matter.
515  */
516 static void
517 finalize_aggregate(AggState *aggstate,
518                                    AggStatePerAgg peraggstate,
519                                    AggStatePerGroup pergroupstate,
520                                    Datum *resultVal, bool *resultIsNull)
521 {
522         MemoryContext oldContext;
523
524         oldContext = MemoryContextSwitchTo(aggstate->csstate.cstate.cs_ExprContext->ecxt_per_tuple_memory);
525
526         /*
527          * Apply the agg's finalfn if one is provided, else return transValue.
528          */
529         if (OidIsValid(peraggstate->finalfn_oid))
530         {
531                 FunctionCallInfoData fcinfo;
532
533                 MemSet(&fcinfo, 0, sizeof(fcinfo));
534                 fcinfo.flinfo = &peraggstate->finalfn;
535                 fcinfo.nargs = 1;
536                 fcinfo.arg[0] = pergroupstate->transValue;
537                 fcinfo.argnull[0] = pergroupstate->transValueIsNull;
538                 if (fcinfo.flinfo->fn_strict && pergroupstate->transValueIsNull)
539                 {
540                         /* don't call a strict function with NULL inputs */
541                         *resultVal = (Datum) 0;
542                         *resultIsNull = true;
543                 }
544                 else
545                 {
546                         *resultVal = FunctionCallInvoke(&fcinfo);
547                         *resultIsNull = fcinfo.isnull;
548                 }
549         }
550         else
551         {
552                 *resultVal = pergroupstate->transValue;
553                 *resultIsNull = pergroupstate->transValueIsNull;
554         }
555
556         /*
557          * If result is pass-by-ref, make sure it is in the right context.
558          */
559         if (!peraggstate->resulttypeByVal && !*resultIsNull &&
560                 !MemoryContextContains(CurrentMemoryContext,
561                                                            DatumGetPointer(*resultVal)))
562                 *resultVal = datumCopy(*resultVal,
563                                                            peraggstate->resulttypeByVal,
564                                                            peraggstate->resulttypeLen);
565
566         MemoryContextSwitchTo(oldContext);
567 }
568
569 /*
570  * Initialize the hash table to empty.
571  *
572  * The hash table always lives in the aggcontext memory context.
573  */
574 static void
575 build_hash_table(Agg *node)
576 {
577         AggState   *aggstate = node->aggstate;
578         AggHashTable    hashtable;
579         Size                    tabsize;
580
581         Assert(node->aggstrategy == AGG_HASHED);
582         Assert(node->numGroups > 0);
583         tabsize = sizeof(AggHashTableData) +
584                 (node->numGroups - 1) * sizeof(AggHashEntry);
585         hashtable = (AggHashTable) MemoryContextAlloc(aggstate->aggcontext,
586                                                                                                   tabsize);
587         MemSet(hashtable, 0, tabsize);
588         hashtable->nbuckets = node->numGroups;
589         aggstate->hashtable = hashtable;
590 }
591
592 /*
593  * Find or create a hashtable entry for the tuple group containing the
594  * given tuple.
595  *
596  * When called, CurrentMemoryContext should be the per-query context.
597  */
598 static AggHashEntry
599 lookup_hash_entry(Agg *node, TupleTableSlot *slot)
600 {
601         AggState   *aggstate = node->aggstate;
602         AggHashTable hashtable = aggstate->hashtable;
603         MemoryContext   tmpmem = aggstate->tmpcontext->ecxt_per_tuple_memory;
604         HeapTuple       tuple = slot->val;
605         TupleDesc       tupdesc = slot->ttc_tupleDescriptor;
606         uint32          hashkey = 0;
607         int                     i;
608         int                     bucketno;
609         AggHashEntry    entry;
610         MemoryContext oldContext;
611         Size            entrysize;
612
613         /* Need to run the hash function in short-lived context */
614         oldContext = MemoryContextSwitchTo(tmpmem);
615
616         for (i = 0; i < node->numCols; i++)
617         {
618                 AttrNumber      att = node->grpColIdx[i];
619                 Datum           attr;
620                 bool            isNull;
621
622                 /* rotate hashkey left 1 bit at each step */
623                 hashkey = (hashkey << 1) | ((hashkey & 0x80000000) ? 1 : 0);
624
625                 attr = heap_getattr(tuple, att, tupdesc, &isNull);
626                 if (isNull)
627                         continue;                       /* treat nulls as having hash key 0 */
628                 hashkey ^= ComputeHashFunc(attr,
629                                                                    (int) tupdesc->attrs[att - 1]->attlen,
630                                                                    tupdesc->attrs[att - 1]->attbyval);
631         }
632         bucketno = hashkey % (uint32) hashtable->nbuckets;
633
634         for (entry = hashtable->buckets[bucketno];
635                  entry != NULL;
636                  entry = entry->next)
637         {
638                 /* Quick check using hashkey */
639                 if (entry->hashkey != hashkey)
640                         continue;
641                 if (execTuplesMatch(entry->firstTuple,
642                                                         tuple,
643                                                         tupdesc,
644                                                         node->numCols, node->grpColIdx,
645                                                         aggstate->eqfunctions,
646                                                         tmpmem))
647                 {
648                         MemoryContextSwitchTo(oldContext);
649                         return entry;
650                 }
651         }
652
653         /* Not there, so build a new one */
654         MemoryContextSwitchTo(aggstate->aggcontext);
655         entrysize = sizeof(AggHashEntryData) +
656                 (aggstate->numaggs - 1) * sizeof(AggStatePerGroupData);
657         entry = (AggHashEntry) palloc0(entrysize);
658
659         entry->hashkey = hashkey;
660         entry->firstTuple = heap_copytuple(tuple);
661
662         entry->next = hashtable->buckets[bucketno];
663         hashtable->buckets[bucketno] = entry;
664
665         MemoryContextSwitchTo(oldContext);
666
667         /* initialize aggregates for new tuple group */
668         initialize_aggregates(aggstate, aggstate->peragg, entry->pergroup);
669
670         return entry;
671 }
672
673 /*
674  * ExecAgg -
675  *
676  *        ExecAgg receives tuples from its outer subplan and aggregates over
677  *        the appropriate attribute for each aggregate function use (Aggref
678  *        node) appearing in the targetlist or qual of the node.  The number
679  *        of tuples to aggregate over depends on whether grouped or plain
680  *        aggregation is selected.  In grouped aggregation, we produce a result
681  *        row for each group; in plain aggregation there's a single result row
682  *        for the whole query.  In either case, the value of each aggregate is
683  *        stored in the expression context to be used when ExecProject evaluates
684  *        the result tuple.
685  */
686 TupleTableSlot *
687 ExecAgg(Agg *node)
688 {
689         AggState   *aggstate = node->aggstate;
690
691         if (aggstate->agg_done)
692                 return NULL;
693
694         if (node->aggstrategy == AGG_HASHED)
695         {
696                 if (!aggstate->table_filled)
697                         agg_fill_hash_table(node);
698                 return agg_retrieve_hash_table(node);
699         }
700         else
701         {
702                 return agg_retrieve_direct(node);
703         }
704 }
705
706 /*
707  * ExecAgg for non-hashed case
708  */
709 static TupleTableSlot *
710 agg_retrieve_direct(Agg *node)
711 {
712         AggState   *aggstate;
713         Plan       *outerPlan;
714         ExprContext *econtext;
715         ExprContext *tmpcontext;
716         ProjectionInfo *projInfo;
717         Datum      *aggvalues;
718         bool       *aggnulls;
719         AggStatePerAgg peragg;
720         AggStatePerGroup pergroup;
721         TupleTableSlot *outerslot;
722         TupleTableSlot *firstSlot;
723         TupleTableSlot *resultSlot;
724         int                     aggno;
725
726         /*
727          * get state info from node
728          */
729         aggstate = node->aggstate;
730         outerPlan = outerPlan(node);
731         /* econtext is the per-output-tuple expression context */
732         econtext = aggstate->csstate.cstate.cs_ExprContext;
733         aggvalues = econtext->ecxt_aggvalues;
734         aggnulls = econtext->ecxt_aggnulls;
735         /* tmpcontext is the per-input-tuple expression context */
736         tmpcontext = aggstate->tmpcontext;
737         projInfo = aggstate->csstate.cstate.cs_ProjInfo;
738         peragg = aggstate->peragg;
739         pergroup = aggstate->pergroup;
740         firstSlot = aggstate->csstate.css_ScanTupleSlot;
741
742         /*
743          * We loop retrieving groups until we find one matching
744          * node->plan.qual
745          */
746         do
747         {
748                 if (aggstate->agg_done)
749                         return NULL;
750
751                 /*
752                  * If we don't already have the first tuple of the new group,
753                  * fetch it from the outer plan.
754                  */
755                 if (aggstate->grp_firstTuple == NULL)
756                 {
757                         outerslot = ExecProcNode(outerPlan, (Plan *) node);
758                         if (!TupIsNull(outerslot))
759                         {
760                                 /*
761                                  * Make a copy of the first input tuple; we will use this
762                                  * for comparisons (in group mode) and for projection.
763                                  */
764                                 aggstate->grp_firstTuple = heap_copytuple(outerslot->val);
765                         }
766                         else
767                         {
768                                 /* outer plan produced no tuples at all */
769                                 aggstate->agg_done = true;
770                                 /* If we are grouping, we should produce no tuples too */
771                                 if (node->aggstrategy != AGG_PLAIN)
772                                         return NULL;
773                         }
774                 }
775
776                 /*
777                  * Clear the per-output-tuple context for each group
778                  */
779                 ResetExprContext(econtext);
780
781                 /*
782                  * Initialize working state for a new input tuple group
783                  */
784                 initialize_aggregates(aggstate, peragg, pergroup);
785
786                 if (aggstate->grp_firstTuple != NULL)
787                 {
788                         /*
789                          * Store the copied first input tuple in the tuple table slot
790                          * reserved for it.  The tuple will be deleted when it is
791                          * cleared from the slot.
792                          */
793                         ExecStoreTuple(aggstate->grp_firstTuple,
794                                                    firstSlot,
795                                                    InvalidBuffer,
796                                                    true);
797                         aggstate->grp_firstTuple = NULL; /* don't keep two pointers */
798
799                         /* set up for first advance_aggregates call */
800                         tmpcontext->ecxt_scantuple = firstSlot;
801
802                         /*
803                          * Process each outer-plan tuple, and then fetch the next one,
804                          * until we exhaust the outer plan or cross a group boundary.
805                          */
806                         for (;;)
807                         {
808                                 advance_aggregates(aggstate, pergroup);
809
810                                 /* Reset per-input-tuple context after each tuple */
811                                 ResetExprContext(tmpcontext);
812
813                                 outerslot = ExecProcNode(outerPlan, (Plan *) node);
814                                 if (TupIsNull(outerslot))
815                                 {
816                                         /* no more outer-plan tuples available */
817                                         aggstate->agg_done = true;
818                                         break;
819                                 }
820                                 /* set up for next advance_aggregates call */
821                                 tmpcontext->ecxt_scantuple = outerslot;
822
823                                 /*
824                                  * If we are grouping, check whether we've crossed a group
825                                  * boundary.
826                                  */
827                                 if (node->aggstrategy == AGG_SORTED)
828                                 {
829                                         if (!execTuplesMatch(firstSlot->val,
830                                                                                  outerslot->val,
831                                                                                  firstSlot->ttc_tupleDescriptor,
832                                                                                  node->numCols, node->grpColIdx,
833                                                                                  aggstate->eqfunctions,
834                                                                                  tmpcontext->ecxt_per_tuple_memory))
835                                         {
836                                                 /*
837                                                  * Save the first input tuple of the next group.
838                                                  */
839                                                 aggstate->grp_firstTuple = heap_copytuple(outerslot->val);
840                                                 break;
841                                         }
842                                 }
843                         }
844                 }
845
846                 /*
847                  * Done scanning input tuple group. Finalize each aggregate
848                  * calculation, and stash results in the per-output-tuple context.
849                  */
850                 for (aggno = 0; aggno < aggstate->numaggs; aggno++)
851                 {
852                         AggStatePerAgg peraggstate = &peragg[aggno];
853                         AggStatePerGroup pergroupstate = &pergroup[aggno];
854
855                         if (peraggstate->aggref->aggdistinct)
856                                 process_sorted_aggregate(aggstate, peraggstate, pergroupstate);
857
858                         finalize_aggregate(aggstate, peraggstate, pergroupstate,
859                                                            &aggvalues[aggno], &aggnulls[aggno]);
860                 }
861
862                 /*
863                  * If we have no first tuple (ie, the outerPlan didn't return
864                  * anything), create a dummy all-nulls input tuple for use by
865                  * ExecProject. 99.44% of the time this is a waste of cycles,
866                  * because ordinarily the projected output tuple's targetlist
867                  * cannot contain any direct (non-aggregated) references to
868                  * input columns, so the dummy tuple will not be referenced.
869                  * However there are special cases where this isn't so --- in
870                  * particular an UPDATE involving an aggregate will have a
871                  * targetlist reference to ctid.  We need to return a null for
872                  * ctid in that situation, not coredump.
873                  *
874                  * The values returned for the aggregates will be the initial
875                  * values of the transition functions.
876                  */
877                 if (TupIsNull(firstSlot))
878                 {
879                         TupleDesc       tupType;
880
881                         /* Should only happen in non-grouped mode */
882                         Assert(node->aggstrategy == AGG_PLAIN);
883                         Assert(aggstate->agg_done);
884
885                         tupType = firstSlot->ttc_tupleDescriptor;
886                         /* watch out for zero-column input tuples, though... */
887                         if (tupType && tupType->natts > 0)
888                         {
889                                 HeapTuple       nullsTuple;
890                                 Datum      *dvalues;
891                                 char       *dnulls;
892
893                                 dvalues = (Datum *) palloc0(sizeof(Datum) * tupType->natts);
894                                 dnulls = (char *) palloc(sizeof(char) * tupType->natts);
895                                 MemSet(dnulls, 'n', sizeof(char) * tupType->natts);
896                                 nullsTuple = heap_formtuple(tupType, dvalues, dnulls);
897                                 ExecStoreTuple(nullsTuple,
898                                                            firstSlot,
899                                                            InvalidBuffer,
900                                                            true);
901                                 pfree(dvalues);
902                                 pfree(dnulls);
903                         }
904                 }
905
906                 /*
907                  * Form a projection tuple using the aggregate results and the
908                  * representative input tuple.  Store it in the result tuple slot.
909                  * Note we do not support aggregates returning sets ...
910                  */
911                 econtext->ecxt_scantuple = firstSlot;
912                 resultSlot = ExecProject(projInfo, NULL);
913
914                 /*
915                  * If the completed tuple does not match the qualifications, it is
916                  * ignored and we loop back to try to process another group.
917                  * Otherwise, return the tuple.
918                  */
919         }
920         while (!ExecQual(node->plan.qual, econtext, false));
921
922         return resultSlot;
923 }
924
925 /*
926  * ExecAgg for hashed case: phase 1, read input and build hash table
927  */
928 static void
929 agg_fill_hash_table(Agg *node)
930 {
931         AggState   *aggstate;
932         Plan       *outerPlan;
933         ExprContext *tmpcontext;
934         AggHashEntry    entry;
935         TupleTableSlot *outerslot;
936
937         /*
938          * get state info from node
939          */
940         aggstate = node->aggstate;
941         outerPlan = outerPlan(node);
942         /* tmpcontext is the per-input-tuple expression context */
943         tmpcontext = aggstate->tmpcontext;
944
945         /*
946          * Process each outer-plan tuple, and then fetch the next one,
947          * until we exhaust the outer plan.
948          */
949         for (;;)
950         {
951                 outerslot = ExecProcNode(outerPlan, (Plan *) node);
952                 if (TupIsNull(outerslot))
953                         break;
954                 /* set up for advance_aggregates call */
955                 tmpcontext->ecxt_scantuple = outerslot;
956
957                 /* Find or build hashtable entry for this tuple's group */
958                 entry = lookup_hash_entry(node, outerslot);
959
960                 /* Advance the aggregates */
961                 advance_aggregates(aggstate, entry->pergroup);
962
963                 /* Reset per-input-tuple context after each tuple */
964                 ResetExprContext(tmpcontext);
965         }
966
967         aggstate->table_filled = true;
968         /* Initialize to walk the hash table */
969         aggstate->next_hash_entry = NULL;
970         aggstate->next_hash_bucket = 0;
971 }
972
973 /*
974  * ExecAgg for hashed case: phase 2, retrieving groups from hash table
975  */
976 static TupleTableSlot *
977 agg_retrieve_hash_table(Agg *node)
978 {
979         AggState   *aggstate;
980         ExprContext *econtext;
981         ProjectionInfo *projInfo;
982         Datum      *aggvalues;
983         bool       *aggnulls;
984         AggStatePerAgg peragg;
985         AggStatePerGroup pergroup;
986         AggHashTable    hashtable;
987         AggHashEntry    entry;
988         TupleTableSlot *firstSlot;
989         TupleTableSlot *resultSlot;
990         int                     aggno;
991
992         /*
993          * get state info from node
994          */
995         aggstate = node->aggstate;
996         /* econtext is the per-output-tuple expression context */
997         econtext = aggstate->csstate.cstate.cs_ExprContext;
998         aggvalues = econtext->ecxt_aggvalues;
999         aggnulls = econtext->ecxt_aggnulls;
1000         projInfo = aggstate->csstate.cstate.cs_ProjInfo;
1001         peragg = aggstate->peragg;
1002         hashtable = aggstate->hashtable;
1003         firstSlot = aggstate->csstate.css_ScanTupleSlot;
1004
1005         /*
1006          * We loop retrieving groups until we find one matching
1007          * node->plan.qual
1008          */
1009         do
1010         {
1011                 if (aggstate->agg_done)
1012                         return NULL;
1013
1014                 /*
1015                  * Find the next entry in the hash table
1016                  */
1017                 entry = aggstate->next_hash_entry;
1018                 while (entry == NULL)
1019                 {
1020                         if (aggstate->next_hash_bucket >= hashtable->nbuckets)
1021                         {
1022                                 /* No more entries in hashtable, so done */
1023                                 aggstate->agg_done = TRUE;
1024                                 return NULL;
1025                         }
1026                         entry = hashtable->buckets[aggstate->next_hash_bucket++];
1027                 }
1028                 aggstate->next_hash_entry = entry->next;
1029
1030                 /*
1031                  * Clear the per-output-tuple context for each group
1032                  */
1033                 ResetExprContext(econtext);
1034
1035                 /*
1036                  * Store the copied first input tuple in the tuple table slot
1037                  * reserved for it, so that it can be used in ExecProject.
1038                  */
1039                 ExecStoreTuple(entry->firstTuple,
1040                                            firstSlot,
1041                                            InvalidBuffer,
1042                                            false);
1043
1044                 pergroup = entry->pergroup;
1045
1046                 /*
1047                  * Finalize each aggregate calculation, and stash results in the
1048                  * per-output-tuple context.
1049                  */
1050                 for (aggno = 0; aggno < aggstate->numaggs; aggno++)
1051                 {
1052                         AggStatePerAgg peraggstate = &peragg[aggno];
1053                         AggStatePerGroup pergroupstate = &pergroup[aggno];
1054
1055                         Assert(!peraggstate->aggref->aggdistinct);
1056                         finalize_aggregate(aggstate, peraggstate, pergroupstate,
1057                                                            &aggvalues[aggno], &aggnulls[aggno]);
1058                 }
1059
1060                 /*
1061                  * Form a projection tuple using the aggregate results and the
1062                  * representative input tuple.  Store it in the result tuple slot.
1063                  * Note we do not support aggregates returning sets ...
1064                  */
1065                 econtext->ecxt_scantuple = firstSlot;
1066                 resultSlot = ExecProject(projInfo, NULL);
1067
1068                 /*
1069                  * If the completed tuple does not match the qualifications, it is
1070                  * ignored and we loop back to try to process another group.
1071                  * Otherwise, return the tuple.
1072                  */
1073         }
1074         while (!ExecQual(node->plan.qual, econtext, false));
1075
1076         return resultSlot;
1077 }
1078
1079 /* -----------------
1080  * ExecInitAgg
1081  *
1082  *      Creates the run-time information for the agg node produced by the
1083  *      planner and initializes its outer subtree
1084  * -----------------
1085  */
1086 bool
1087 ExecInitAgg(Agg *node, EState *estate, Plan *parent)
1088 {
1089         AggState   *aggstate;
1090         AggStatePerAgg peragg;
1091         Plan       *outerPlan;
1092         ExprContext *econtext;
1093         int                     numaggs,
1094                                 aggno;
1095         List       *alist;
1096
1097         /*
1098          * assign the node's execution state
1099          */
1100         node->plan.state = estate;
1101
1102         /*
1103          * create state structure
1104          */
1105         aggstate = makeNode(AggState);
1106         node->aggstate = aggstate;
1107         aggstate->eqfunctions = NULL;
1108         aggstate->peragg = NULL;
1109         aggstate->agg_done = false;
1110         aggstate->pergroup = NULL;
1111         aggstate->grp_firstTuple = NULL;
1112         aggstate->hashtable = NULL;
1113
1114         /*
1115          * find aggregates in targetlist and quals
1116          *
1117          * Note: pull_agg_clauses also checks that no aggs contain other agg
1118          * calls in their arguments.  This would make no sense under SQL
1119          * semantics anyway (and it's forbidden by the spec).  Because that is
1120          * true, we don't need to worry about evaluating the aggs in any
1121          * particular order.
1122          */
1123         aggstate->aggs = nconc(pull_agg_clause((Node *) node->plan.targetlist),
1124                                                    pull_agg_clause((Node *) node->plan.qual));
1125         aggstate->numaggs = numaggs = length(aggstate->aggs);
1126         if (numaggs <= 0)
1127         {
1128                 /*
1129                  * This is not an error condition: we might be using the Agg node just
1130                  * to do hash-based grouping.  Even in the regular case,
1131                  * constant-expression simplification could optimize away all of the
1132                  * Aggrefs in the targetlist and qual.  So keep going, but force local
1133                  * copy of numaggs positive so that palloc()s below don't choke.
1134                  */
1135                 numaggs = 1;
1136         }
1137
1138         /*
1139          * Create expression contexts.  We need two, one for per-input-tuple
1140          * processing and one for per-output-tuple processing.  We cheat a little
1141          * by using ExecAssignExprContext() to build both.
1142          */
1143         ExecAssignExprContext(estate, &aggstate->csstate.cstate);
1144         aggstate->tmpcontext = aggstate->csstate.cstate.cs_ExprContext;
1145         ExecAssignExprContext(estate, &aggstate->csstate.cstate);
1146
1147         /*
1148          * We also need a long-lived memory context for holding hashtable
1149          * data structures and transition values.  NOTE: the details of what
1150          * is stored in aggcontext and what is stored in the regular per-query
1151          * memory context are driven by a simple decision: we want to reset the
1152          * aggcontext in ExecReScanAgg to recover no-longer-wanted space.
1153          */
1154         aggstate->aggcontext =
1155                 AllocSetContextCreate(CurrentMemoryContext,
1156                                                           "AggContext",
1157                                                           ALLOCSET_DEFAULT_MINSIZE,
1158                                                           ALLOCSET_DEFAULT_INITSIZE,
1159                                                           ALLOCSET_DEFAULT_MAXSIZE);
1160
1161 #define AGG_NSLOTS 2
1162
1163         /*
1164          * tuple table initialization
1165          */
1166         ExecInitScanTupleSlot(estate, &aggstate->csstate);
1167         ExecInitResultTupleSlot(estate, &aggstate->csstate.cstate);
1168
1169         /*
1170          * Set up aggregate-result storage in the output expr context, and also
1171          * allocate my private per-agg working storage
1172          */
1173         econtext = aggstate->csstate.cstate.cs_ExprContext;
1174         econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs);
1175         econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs);
1176
1177         peragg = (AggStatePerAgg) palloc0(sizeof(AggStatePerAggData) * numaggs);
1178         aggstate->peragg = peragg;
1179
1180         if (node->aggstrategy == AGG_HASHED)
1181         {
1182                 build_hash_table(node);
1183                 aggstate->table_filled = false;
1184         }
1185         else
1186         {
1187                 AggStatePerGroup pergroup;
1188
1189                 pergroup = (AggStatePerGroup) palloc0(sizeof(AggStatePerGroupData) * numaggs);
1190                 aggstate->pergroup = pergroup;
1191         }
1192
1193         /*
1194          * initialize child nodes
1195          */
1196         outerPlan = outerPlan(node);
1197         ExecInitNode(outerPlan, estate, (Plan *) node);
1198
1199         /*
1200          * initialize source tuple type.
1201          */
1202         ExecAssignScanTypeFromOuterPlan((Plan *) node, &aggstate->csstate);
1203
1204         /*
1205          * Initialize result tuple type and projection info.
1206          */
1207         ExecAssignResultTypeFromTL((Plan *) node, &aggstate->csstate.cstate);
1208         ExecAssignProjectionInfo((Plan *) node, &aggstate->csstate.cstate);
1209
1210         /*
1211          * If we are grouping, precompute fmgr lookup data for inner loop
1212          */
1213         if (node->numCols > 0)
1214         {
1215                 aggstate->eqfunctions =
1216                         execTuplesMatchPrepare(ExecGetScanType(&aggstate->csstate),
1217                                                                    node->numCols,
1218                                                                    node->grpColIdx);
1219         }
1220
1221         /*
1222          * Perform lookups of aggregate function info, and initialize the
1223          * unchanging fields of the per-agg data
1224          */
1225         aggno = -1;
1226         foreach(alist, aggstate->aggs)
1227         {
1228                 Aggref     *aggref = (Aggref *) lfirst(alist);
1229                 AggStatePerAgg peraggstate = &peragg[++aggno];
1230                 HeapTuple       aggTuple;
1231                 Form_pg_aggregate aggform;
1232                 AclResult       aclresult;
1233                 Oid                     transfn_oid,
1234                                         finalfn_oid;
1235                 Datum           textInitVal;
1236
1237                 /* Mark Aggref node with its associated index in the result array */
1238                 aggref->aggno = aggno;
1239
1240                 /* Fill in the peraggstate data */
1241                 peraggstate->aggref = aggref;
1242
1243                 aggTuple = SearchSysCache(AGGFNOID,
1244                                                                   ObjectIdGetDatum(aggref->aggfnoid),
1245                                                                   0, 0, 0);
1246                 if (!HeapTupleIsValid(aggTuple))
1247                         elog(ERROR, "ExecAgg: cache lookup failed for aggregate %u",
1248                                  aggref->aggfnoid);
1249                 aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);
1250
1251                 /* Check permission to call aggregate function */
1252                 aclresult = pg_proc_aclcheck(aggref->aggfnoid, GetUserId(),
1253                                                                          ACL_EXECUTE);
1254                 if (aclresult != ACLCHECK_OK)
1255                         aclcheck_error(aclresult, get_func_name(aggref->aggfnoid));
1256
1257                 get_typlenbyval(aggref->aggtype,
1258                                                 &peraggstate->resulttypeLen,
1259                                                 &peraggstate->resulttypeByVal);
1260                 get_typlenbyval(aggform->aggtranstype,
1261                                                 &peraggstate->transtypeLen,
1262                                                 &peraggstate->transtypeByVal);
1263
1264                 /*
1265                  * initval is potentially null, so don't try to access it as a
1266                  * struct field. Must do it the hard way with SysCacheGetAttr.
1267                  */
1268                 textInitVal = SysCacheGetAttr(AGGFNOID, aggTuple,
1269                                                                           Anum_pg_aggregate_agginitval,
1270                                                                           &peraggstate->initValueIsNull);
1271
1272                 if (peraggstate->initValueIsNull)
1273                         peraggstate->initValue = (Datum) 0;
1274                 else
1275                         peraggstate->initValue = GetAggInitVal(textInitVal,
1276                                                                                                    aggform->aggtranstype);
1277
1278                 peraggstate->transfn_oid = transfn_oid = aggform->aggtransfn;
1279                 peraggstate->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
1280
1281                 fmgr_info(transfn_oid, &peraggstate->transfn);
1282                 if (OidIsValid(finalfn_oid))
1283                         fmgr_info(finalfn_oid, &peraggstate->finalfn);
1284
1285                 /*
1286                  * If the transfn is strict and the initval is NULL, make sure
1287                  * input type and transtype are the same (or at least binary-
1288                  * compatible), so that it's OK to use the first input value as
1289                  * the initial transValue.      This should have been checked at agg
1290                  * definition time, but just in case...
1291                  */
1292                 if (peraggstate->transfn.fn_strict && peraggstate->initValueIsNull)
1293                 {
1294                         /*
1295                          * Note: use the type from the input expression here, not from
1296                          * pg_proc.proargtypes, because the latter might be 0.
1297                          * (Consider COUNT(*).)
1298                          */
1299                         Oid                     inputType = exprType(aggref->target);
1300
1301                         if (!IsBinaryCoercible(inputType, aggform->aggtranstype))
1302                                 elog(ERROR, "Aggregate %u needs to have compatible input type and transition type",
1303                                          aggref->aggfnoid);
1304                 }
1305
1306                 if (aggref->aggdistinct)
1307                 {
1308                         /*
1309                          * Note: use the type from the input expression here, not from
1310                          * pg_proc.proargtypes, because the latter might be a pseudotype.
1311                          * (Consider COUNT(*).)
1312                          */
1313                         Oid                     inputType = exprType(aggref->target);
1314                         Oid                     eq_function;
1315
1316                         /* We don't implement DISTINCT aggs in the HASHED case */
1317                         Assert(node->aggstrategy != AGG_HASHED);
1318
1319                         peraggstate->inputType = inputType;
1320                         get_typlenbyval(inputType,
1321                                                         &peraggstate->inputtypeLen,
1322                                                         &peraggstate->inputtypeByVal);
1323
1324                         eq_function = compatible_oper_funcid(makeList1(makeString("=")),
1325                                                                                                  inputType, inputType,
1326                                                                                                  true);
1327                         if (!OidIsValid(eq_function))
1328                                 elog(ERROR, "Unable to identify an equality operator for type %s",
1329                                          format_type_be(inputType));
1330                         fmgr_info(eq_function, &(peraggstate->equalfn));
1331                         peraggstate->sortOperator = any_ordering_op(inputType);
1332                         peraggstate->sortstate = NULL;
1333                 }
1334
1335                 ReleaseSysCache(aggTuple);
1336         }
1337
1338         return TRUE;
1339 }
1340
1341 static Datum
1342 GetAggInitVal(Datum textInitVal, Oid transtype)
1343 {
1344         char       *strInitVal;
1345         HeapTuple       tup;
1346         Oid                     typinput,
1347                                 typelem;
1348         Datum           initVal;
1349
1350         strInitVal = DatumGetCString(DirectFunctionCall1(textout, textInitVal));
1351
1352         tup = SearchSysCache(TYPEOID,
1353                                                  ObjectIdGetDatum(transtype),
1354                                                  0, 0, 0);
1355         if (!HeapTupleIsValid(tup))
1356                 elog(ERROR, "GetAggInitVal: cache lookup failed on aggregate transition function return type %u", transtype);
1357
1358         typinput = ((Form_pg_type) GETSTRUCT(tup))->typinput;
1359         typelem = ((Form_pg_type) GETSTRUCT(tup))->typelem;
1360         ReleaseSysCache(tup);
1361
1362         initVal = OidFunctionCall3(typinput,
1363                                                            CStringGetDatum(strInitVal),
1364                                                            ObjectIdGetDatum(typelem),
1365                                                            Int32GetDatum(-1));
1366
1367         pfree(strInitVal);
1368         return initVal;
1369 }
1370
1371 int
1372 ExecCountSlotsAgg(Agg *node)
1373 {
1374         return ExecCountSlotsNode(outerPlan(node)) +
1375                 ExecCountSlotsNode(innerPlan(node)) +
1376                 AGG_NSLOTS;
1377 }
1378
1379 void
1380 ExecEndAgg(Agg *node)
1381 {
1382         AggState   *aggstate = node->aggstate;
1383         Plan       *outerPlan;
1384         int                     aggno;
1385
1386         /* Make sure we have closed any open tuplesorts */
1387         for (aggno = 0; aggno < aggstate->numaggs; aggno++)
1388         {
1389                 AggStatePerAgg peraggstate = &aggstate->peragg[aggno];
1390
1391                 if (peraggstate->sortstate)
1392                         tuplesort_end(peraggstate->sortstate);
1393         }
1394
1395         ExecFreeProjectionInfo(&aggstate->csstate.cstate);
1396
1397         /*
1398          * Free both the expr contexts.
1399          */
1400         ExecFreeExprContext(&aggstate->csstate.cstate);
1401         aggstate->csstate.cstate.cs_ExprContext = aggstate->tmpcontext;
1402         ExecFreeExprContext(&aggstate->csstate.cstate);
1403
1404         MemoryContextDelete(aggstate->aggcontext);
1405
1406         outerPlan = outerPlan(node);
1407         ExecEndNode(outerPlan, (Plan *) node);
1408
1409         /* clean up tuple table */
1410         ExecClearTuple(aggstate->csstate.css_ScanTupleSlot);
1411         if (aggstate->grp_firstTuple != NULL)
1412         {
1413                 heap_freetuple(aggstate->grp_firstTuple);
1414                 aggstate->grp_firstTuple = NULL;
1415         }
1416 }
1417
1418 void
1419 ExecReScanAgg(Agg *node, ExprContext *exprCtxt, Plan *parent)
1420 {
1421         AggState   *aggstate = node->aggstate;
1422         ExprContext *econtext = aggstate->csstate.cstate.cs_ExprContext;
1423         int                     aggno;
1424
1425         /* Make sure we have closed any open tuplesorts */
1426         for (aggno = 0; aggno < aggstate->numaggs; aggno++)
1427         {
1428                 AggStatePerAgg peraggstate = &aggstate->peragg[aggno];
1429
1430                 if (peraggstate->sortstate)
1431                         tuplesort_end(peraggstate->sortstate);
1432                 peraggstate->sortstate = NULL;
1433         }
1434
1435         aggstate->agg_done = false;
1436         if (aggstate->grp_firstTuple != NULL)
1437         {
1438                 heap_freetuple(aggstate->grp_firstTuple);
1439                 aggstate->grp_firstTuple = NULL;
1440         }
1441         MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * aggstate->numaggs);
1442         MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * aggstate->numaggs);
1443
1444         MemoryContextReset(aggstate->aggcontext);
1445
1446         if (node->aggstrategy == AGG_HASHED)
1447         {
1448                 build_hash_table(node);
1449                 aggstate->table_filled = false;
1450         }
1451
1452         /*
1453          * if chgParam of subnode is not null then plan will be re-scanned by
1454          * first ExecProcNode.
1455          */
1456         if (((Plan *) node)->lefttree->chgParam == NULL)
1457                 ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);
1458 }
1459
1460 /*
1461  * aggregate_dummy - dummy execution routine for aggregate functions
1462  *
1463  * This function is listed as the implementation (prosrc field) of pg_proc
1464  * entries for aggregate functions.  Its only purpose is to throw an error
1465  * if someone mistakenly executes such a function in the normal way.
1466  *
1467  * Perhaps someday we could assign real meaning to the prosrc field of
1468  * an aggregate?
1469  */
1470 Datum
1471 aggregate_dummy(PG_FUNCTION_ARGS)
1472 {
1473         elog(ERROR, "Aggregate function %u called as normal function",
1474                  fcinfo->flinfo->fn_oid);
1475         return (Datum) 0;                       /* keep compiler quiet */
1476 }