OSDN Git Service

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