OSDN Git Service

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