Header And Logo

PostgreSQL
| The world's most advanced open source database.

nodeAgg.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * nodeAgg.c
00004  *    Routines to handle aggregate nodes.
00005  *
00006  *    ExecAgg evaluates each aggregate in the following steps:
00007  *
00008  *       transvalue = initcond
00009  *       foreach input_tuple do
00010  *          transvalue = transfunc(transvalue, input_value(s))
00011  *       result = finalfunc(transvalue)
00012  *
00013  *    If a finalfunc is not supplied then the result is just the ending
00014  *    value of transvalue.
00015  *
00016  *    If an aggregate call specifies DISTINCT or ORDER BY, we sort the input
00017  *    tuples and eliminate duplicates (if required) before performing the
00018  *    above-depicted process.
00019  *
00020  *    If transfunc is marked "strict" in pg_proc and initcond is NULL,
00021  *    then the first non-NULL input_value is assigned directly to transvalue,
00022  *    and transfunc isn't applied until the second non-NULL input_value.
00023  *    The agg's first input type and transtype must be the same in this case!
00024  *
00025  *    If transfunc is marked "strict" then NULL input_values are skipped,
00026  *    keeping the previous transvalue.  If transfunc is not strict then it
00027  *    is called for every input tuple and must deal with NULL initcond
00028  *    or NULL input_values for itself.
00029  *
00030  *    If finalfunc is marked "strict" then it is not called when the
00031  *    ending transvalue is NULL, instead a NULL result is created
00032  *    automatically (this is just the usual handling of strict functions,
00033  *    of course).  A non-strict finalfunc can make its own choice of
00034  *    what to return for a NULL ending transvalue.
00035  *
00036  *    We compute aggregate input expressions and run the transition functions
00037  *    in a temporary econtext (aggstate->tmpcontext).  This is reset at
00038  *    least once per input tuple, so when the transvalue datatype is
00039  *    pass-by-reference, we have to be careful to copy it into a longer-lived
00040  *    memory context, and free the prior value to avoid memory leakage.
00041  *    We store transvalues in the memory context aggstate->aggcontext,
00042  *    which is also used for the hashtable structures in AGG_HASHED mode.
00043  *    The node's regular econtext (aggstate->csstate.cstate.cs_ExprContext)
00044  *    is used to run finalize functions and compute the output tuple;
00045  *    this context can be reset once per output tuple.
00046  *
00047  *    The executor's AggState node is passed as the fmgr "context" value in
00048  *    all transfunc and finalfunc calls.  It is not recommended that the
00049  *    transition functions look at the AggState node directly, but they can
00050  *    use AggCheckCallContext() to verify that they are being called by
00051  *    nodeAgg.c (and not as ordinary SQL functions).  The main reason a
00052  *    transition function might want to know this is so that it can avoid
00053  *    palloc'ing a fixed-size pass-by-ref transition value on every call:
00054  *    it can instead just scribble on and return its left input.  Ordinarily
00055  *    it is completely forbidden for functions to modify pass-by-ref inputs,
00056  *    but in the aggregate case we know the left input is either the initial
00057  *    transition value or a previous function result, and in either case its
00058  *    value need not be preserved.  See int8inc() for an example.  Notice that
00059  *    advance_transition_function() is coded to avoid a data copy step when
00060  *    the previous transition value pointer is returned.  Also, some
00061  *    transition functions want to store working state in addition to the
00062  *    nominal transition value; they can use the memory context returned by
00063  *    AggCheckCallContext() to do that.
00064  *
00065  *    Note: AggCheckCallContext() is available as of PostgreSQL 9.0.  The
00066  *    AggState is available as context in earlier releases (back to 8.1),
00067  *    but direct examination of the node is needed to use it before 9.0.
00068  *
00069  *
00070  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00071  * Portions Copyright (c) 1994, Regents of the University of California
00072  *
00073  * IDENTIFICATION
00074  *    src/backend/executor/nodeAgg.c
00075  *
00076  *-------------------------------------------------------------------------
00077  */
00078 
00079 #include "postgres.h"
00080 
00081 #include "access/htup_details.h"
00082 #include "catalog/objectaccess.h"
00083 #include "catalog/pg_aggregate.h"
00084 #include "catalog/pg_proc.h"
00085 #include "catalog/pg_type.h"
00086 #include "executor/executor.h"
00087 #include "executor/nodeAgg.h"
00088 #include "miscadmin.h"
00089 #include "nodes/nodeFuncs.h"
00090 #include "optimizer/clauses.h"
00091 #include "optimizer/tlist.h"
00092 #include "parser/parse_agg.h"
00093 #include "parser/parse_coerce.h"
00094 #include "utils/acl.h"
00095 #include "utils/builtins.h"
00096 #include "utils/lsyscache.h"
00097 #include "utils/memutils.h"
00098 #include "utils/syscache.h"
00099 #include "utils/tuplesort.h"
00100 #include "utils/datum.h"
00101 
00102 
00103 /*
00104  * AggStatePerAggData - per-aggregate working state for the Agg scan
00105  */
00106 typedef struct AggStatePerAggData
00107 {
00108     /*
00109      * These values are set up during ExecInitAgg() and do not change
00110      * thereafter:
00111      */
00112 
00113     /* Links to Aggref expr and state nodes this working state is for */
00114     AggrefExprState *aggrefstate;
00115     Aggref     *aggref;
00116 
00117     /* number of input arguments for aggregate function proper */
00118     int         numArguments;
00119 
00120     /* number of inputs including ORDER BY expressions */
00121     int         numInputs;
00122 
00123     /* Oids of transfer functions */
00124     Oid         transfn_oid;
00125     Oid         finalfn_oid;    /* may be InvalidOid */
00126 
00127     /*
00128      * fmgr lookup data for transfer functions --- only valid when
00129      * corresponding oid is not InvalidOid.  Note in particular that fn_strict
00130      * flags are kept here.
00131      */
00132     FmgrInfo    transfn;
00133     FmgrInfo    finalfn;
00134 
00135     /* Input collation derived for aggregate */
00136     Oid         aggCollation;
00137 
00138     /* number of sorting columns */
00139     int         numSortCols;
00140 
00141     /* number of sorting columns to consider in DISTINCT comparisons */
00142     /* (this is either zero or the same as numSortCols) */
00143     int         numDistinctCols;
00144 
00145     /* deconstructed sorting information (arrays of length numSortCols) */
00146     AttrNumber *sortColIdx;
00147     Oid        *sortOperators;
00148     Oid        *sortCollations;
00149     bool       *sortNullsFirst;
00150 
00151     /*
00152      * fmgr lookup data for input columns' equality operators --- only
00153      * set/used when aggregate has DISTINCT flag.  Note that these are in
00154      * order of sort column index, not parameter index.
00155      */
00156     FmgrInfo   *equalfns;       /* array of length numDistinctCols */
00157 
00158     /*
00159      * initial value from pg_aggregate entry
00160      */
00161     Datum       initValue;
00162     bool        initValueIsNull;
00163 
00164     /*
00165      * We need the len and byval info for the agg's input, result, and
00166      * transition data types in order to know how to copy/delete values.
00167      *
00168      * Note that the info for the input type is used only when handling
00169      * DISTINCT aggs with just one argument, so there is only one input type.
00170      */
00171     int16       inputtypeLen,
00172                 resulttypeLen,
00173                 transtypeLen;
00174     bool        inputtypeByVal,
00175                 resulttypeByVal,
00176                 transtypeByVal;
00177 
00178     /*
00179      * Stuff for evaluation of inputs.  We used to just use ExecEvalExpr, but
00180      * with the addition of ORDER BY we now need at least a slot for passing
00181      * data to the sort object, which requires a tupledesc, so we might as
00182      * well go whole hog and use ExecProject too.
00183      */
00184     TupleDesc   evaldesc;       /* descriptor of input tuples */
00185     ProjectionInfo *evalproj;   /* projection machinery */
00186 
00187     /*
00188      * Slots for holding the evaluated input arguments.  These are set up
00189      * during ExecInitAgg() and then used for each input row.
00190      */
00191     TupleTableSlot *evalslot;   /* current input tuple */
00192     TupleTableSlot *uniqslot;   /* used for multi-column DISTINCT */
00193 
00194     /*
00195      * These values are working state that is initialized at the start of an
00196      * input tuple group and updated for each input tuple.
00197      *
00198      * For a simple (non DISTINCT/ORDER BY) aggregate, we just feed the input
00199      * values straight to the transition function.  If it's DISTINCT or
00200      * requires ORDER BY, we pass the input values into a Tuplesort object;
00201      * then at completion of the input tuple group, we scan the sorted values,
00202      * eliminate duplicates if needed, and run the transition function on the
00203      * rest.
00204      */
00205 
00206     Tuplesortstate *sortstate;  /* sort object, if DISTINCT or ORDER BY */
00207 }   AggStatePerAggData;
00208 
00209 /*
00210  * AggStatePerGroupData - per-aggregate-per-group working state
00211  *
00212  * These values are working state that is initialized at the start of
00213  * an input tuple group and updated for each input tuple.
00214  *
00215  * In AGG_PLAIN and AGG_SORTED modes, we have a single array of these
00216  * structs (pointed to by aggstate->pergroup); we re-use the array for
00217  * each input group, if it's AGG_SORTED mode.  In AGG_HASHED mode, the
00218  * hash table contains an array of these structs for each tuple group.
00219  *
00220  * Logically, the sortstate field belongs in this struct, but we do not
00221  * keep it here for space reasons: we don't support DISTINCT aggregates
00222  * in AGG_HASHED mode, so there's no reason to use up a pointer field
00223  * in every entry of the hashtable.
00224  */
00225 typedef struct AggStatePerGroupData
00226 {
00227     Datum       transValue;     /* current transition value */
00228     bool        transValueIsNull;
00229 
00230     bool        noTransValue;   /* true if transValue not set yet */
00231 
00232     /*
00233      * Note: noTransValue initially has the same value as transValueIsNull,
00234      * and if true both are cleared to false at the same time.  They are not
00235      * the same though: if transfn later returns a NULL, we want to keep that
00236      * NULL and not auto-replace it with a later input value. Only the first
00237      * non-NULL input will be auto-substituted.
00238      */
00239 } AggStatePerGroupData;
00240 
00241 /*
00242  * To implement hashed aggregation, we need a hashtable that stores a
00243  * representative tuple and an array of AggStatePerGroup structs for each
00244  * distinct set of GROUP BY column values.  We compute the hash key from
00245  * the GROUP BY columns.
00246  */
00247 typedef struct AggHashEntryData *AggHashEntry;
00248 
00249 typedef struct AggHashEntryData
00250 {
00251     TupleHashEntryData shared;  /* common header for hash table entries */
00252     /* per-aggregate transition status array - must be last! */
00253     AggStatePerGroupData pergroup[1];   /* VARIABLE LENGTH ARRAY */
00254 }   AggHashEntryData;   /* VARIABLE LENGTH STRUCT */
00255 
00256 
00257 static void initialize_aggregates(AggState *aggstate,
00258                       AggStatePerAgg peragg,
00259                       AggStatePerGroup pergroup);
00260 static void advance_transition_function(AggState *aggstate,
00261                             AggStatePerAgg peraggstate,
00262                             AggStatePerGroup pergroupstate,
00263                             FunctionCallInfoData *fcinfo);
00264 static void advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup);
00265 static void process_ordered_aggregate_single(AggState *aggstate,
00266                                  AggStatePerAgg peraggstate,
00267                                  AggStatePerGroup pergroupstate);
00268 static void process_ordered_aggregate_multi(AggState *aggstate,
00269                                 AggStatePerAgg peraggstate,
00270                                 AggStatePerGroup pergroupstate);
00271 static void finalize_aggregate(AggState *aggstate,
00272                    AggStatePerAgg peraggstate,
00273                    AggStatePerGroup pergroupstate,
00274                    Datum *resultVal, bool *resultIsNull);
00275 static Bitmapset *find_unaggregated_cols(AggState *aggstate);
00276 static bool find_unaggregated_cols_walker(Node *node, Bitmapset **colnos);
00277 static void build_hash_table(AggState *aggstate);
00278 static AggHashEntry lookup_hash_entry(AggState *aggstate,
00279                   TupleTableSlot *inputslot);
00280 static TupleTableSlot *agg_retrieve_direct(AggState *aggstate);
00281 static void agg_fill_hash_table(AggState *aggstate);
00282 static TupleTableSlot *agg_retrieve_hash_table(AggState *aggstate);
00283 static Datum GetAggInitVal(Datum textInitVal, Oid transtype);
00284 
00285 
00286 /*
00287  * Initialize all aggregates for a new group of input values.
00288  *
00289  * When called, CurrentMemoryContext should be the per-query context.
00290  */
00291 static void
00292 initialize_aggregates(AggState *aggstate,
00293                       AggStatePerAgg peragg,
00294                       AggStatePerGroup pergroup)
00295 {
00296     int         aggno;
00297 
00298     for (aggno = 0; aggno < aggstate->numaggs; aggno++)
00299     {
00300         AggStatePerAgg peraggstate = &peragg[aggno];
00301         AggStatePerGroup pergroupstate = &pergroup[aggno];
00302 
00303         /*
00304          * Start a fresh sort operation for each DISTINCT/ORDER BY aggregate.
00305          */
00306         if (peraggstate->numSortCols > 0)
00307         {
00308             /*
00309              * In case of rescan, maybe there could be an uncompleted sort
00310              * operation?  Clean it up if so.
00311              */
00312             if (peraggstate->sortstate)
00313                 tuplesort_end(peraggstate->sortstate);
00314 
00315             /*
00316              * We use a plain Datum sorter when there's a single input column;
00317              * otherwise sort the full tuple.  (See comments for
00318              * process_ordered_aggregate_single.)
00319              */
00320             peraggstate->sortstate =
00321                 (peraggstate->numInputs == 1) ?
00322                 tuplesort_begin_datum(peraggstate->evaldesc->attrs[0]->atttypid,
00323                                       peraggstate->sortOperators[0],
00324                                       peraggstate->sortCollations[0],
00325                                       peraggstate->sortNullsFirst[0],
00326                                       work_mem, false) :
00327                 tuplesort_begin_heap(peraggstate->evaldesc,
00328                                      peraggstate->numSortCols,
00329                                      peraggstate->sortColIdx,
00330                                      peraggstate->sortOperators,
00331                                      peraggstate->sortCollations,
00332                                      peraggstate->sortNullsFirst,
00333                                      work_mem, false);
00334         }
00335 
00336         /*
00337          * (Re)set transValue to the initial value.
00338          *
00339          * Note that when the initial value is pass-by-ref, we must copy it
00340          * (into the aggcontext) since we will pfree the transValue later.
00341          */
00342         if (peraggstate->initValueIsNull)
00343             pergroupstate->transValue = peraggstate->initValue;
00344         else
00345         {
00346             MemoryContext oldContext;
00347 
00348             oldContext = MemoryContextSwitchTo(aggstate->aggcontext);
00349             pergroupstate->transValue = datumCopy(peraggstate->initValue,
00350                                                   peraggstate->transtypeByVal,
00351                                                   peraggstate->transtypeLen);
00352             MemoryContextSwitchTo(oldContext);
00353         }
00354         pergroupstate->transValueIsNull = peraggstate->initValueIsNull;
00355 
00356         /*
00357          * If the initial value for the transition state doesn't exist in the
00358          * pg_aggregate table then we will let the first non-NULL value
00359          * returned from the outer procNode become the initial value. (This is
00360          * useful for aggregates like max() and min().) The noTransValue flag
00361          * signals that we still need to do this.
00362          */
00363         pergroupstate->noTransValue = peraggstate->initValueIsNull;
00364     }
00365 }
00366 
00367 /*
00368  * Given new input value(s), advance the transition function of an aggregate.
00369  *
00370  * The new values (and null flags) have been preloaded into argument positions
00371  * 1 and up in fcinfo, so that we needn't copy them again to pass to the
00372  * transition function.  No other fields of fcinfo are assumed valid.
00373  *
00374  * It doesn't matter which memory context this is called in.
00375  */
00376 static void
00377 advance_transition_function(AggState *aggstate,
00378                             AggStatePerAgg peraggstate,
00379                             AggStatePerGroup pergroupstate,
00380                             FunctionCallInfoData *fcinfo)
00381 {
00382     int         numArguments = peraggstate->numArguments;
00383     MemoryContext oldContext;
00384     Datum       newVal;
00385     int         i;
00386 
00387     if (peraggstate->transfn.fn_strict)
00388     {
00389         /*
00390          * For a strict transfn, nothing happens when there's a NULL input; we
00391          * just keep the prior transValue.
00392          */
00393         for (i = 1; i <= numArguments; i++)
00394         {
00395             if (fcinfo->argnull[i])
00396                 return;
00397         }
00398         if (pergroupstate->noTransValue)
00399         {
00400             /*
00401              * transValue has not been initialized. This is the first non-NULL
00402              * input value. We use it as the initial value for transValue. (We
00403              * already checked that the agg's input type is binary-compatible
00404              * with its transtype, so straight copy here is OK.)
00405              *
00406              * We must copy the datum into aggcontext if it is pass-by-ref. We
00407              * do not need to pfree the old transValue, since it's NULL.
00408              */
00409             oldContext = MemoryContextSwitchTo(aggstate->aggcontext);
00410             pergroupstate->transValue = datumCopy(fcinfo->arg[1],
00411                                                   peraggstate->transtypeByVal,
00412                                                   peraggstate->transtypeLen);
00413             pergroupstate->transValueIsNull = false;
00414             pergroupstate->noTransValue = false;
00415             MemoryContextSwitchTo(oldContext);
00416             return;
00417         }
00418         if (pergroupstate->transValueIsNull)
00419         {
00420             /*
00421              * Don't call a strict function with NULL inputs.  Note it is
00422              * possible to get here despite the above tests, if the transfn is
00423              * strict *and* returned a NULL on a prior cycle. If that happens
00424              * we will propagate the NULL all the way to the end.
00425              */
00426             return;
00427         }
00428     }
00429 
00430     /* We run the transition functions in per-input-tuple memory context */
00431     oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
00432 
00433     /*
00434      * OK to call the transition function
00435      */
00436     InitFunctionCallInfoData(*fcinfo, &(peraggstate->transfn),
00437                              numArguments + 1,
00438                              peraggstate->aggCollation,
00439                              (void *) aggstate, NULL);
00440     fcinfo->arg[0] = pergroupstate->transValue;
00441     fcinfo->argnull[0] = pergroupstate->transValueIsNull;
00442 
00443     newVal = FunctionCallInvoke(fcinfo);
00444 
00445     /*
00446      * If pass-by-ref datatype, must copy the new value into aggcontext and
00447      * pfree the prior transValue.  But if transfn returned a pointer to its
00448      * first input, we don't need to do anything.
00449      */
00450     if (!peraggstate->transtypeByVal &&
00451         DatumGetPointer(newVal) != DatumGetPointer(pergroupstate->transValue))
00452     {
00453         if (!fcinfo->isnull)
00454         {
00455             MemoryContextSwitchTo(aggstate->aggcontext);
00456             newVal = datumCopy(newVal,
00457                                peraggstate->transtypeByVal,
00458                                peraggstate->transtypeLen);
00459         }
00460         if (!pergroupstate->transValueIsNull)
00461             pfree(DatumGetPointer(pergroupstate->transValue));
00462     }
00463 
00464     pergroupstate->transValue = newVal;
00465     pergroupstate->transValueIsNull = fcinfo->isnull;
00466 
00467     MemoryContextSwitchTo(oldContext);
00468 }
00469 
00470 /*
00471  * Advance all the aggregates for one input tuple.  The input tuple
00472  * has been stored in tmpcontext->ecxt_outertuple, so that it is accessible
00473  * to ExecEvalExpr.  pergroup is the array of per-group structs to use
00474  * (this might be in a hashtable entry).
00475  *
00476  * When called, CurrentMemoryContext should be the per-query context.
00477  */
00478 static void
00479 advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
00480 {
00481     int         aggno;
00482 
00483     for (aggno = 0; aggno < aggstate->numaggs; aggno++)
00484     {
00485         AggStatePerAgg peraggstate = &aggstate->peragg[aggno];
00486         AggStatePerGroup pergroupstate = &pergroup[aggno];
00487         int         nargs = peraggstate->numArguments;
00488         int         i;
00489         TupleTableSlot *slot;
00490 
00491         /* Evaluate the current input expressions for this aggregate */
00492         slot = ExecProject(peraggstate->evalproj, NULL);
00493 
00494         if (peraggstate->numSortCols > 0)
00495         {
00496             /* DISTINCT and/or ORDER BY case */
00497             Assert(slot->tts_nvalid == peraggstate->numInputs);
00498 
00499             /*
00500              * If the transfn is strict, we want to check for nullity before
00501              * storing the row in the sorter, to save space if there are a lot
00502              * of nulls.  Note that we must only check numArguments columns,
00503              * not numInputs, since nullity in columns used only for sorting
00504              * is not relevant here.
00505              */
00506             if (peraggstate->transfn.fn_strict)
00507             {
00508                 for (i = 0; i < nargs; i++)
00509                 {
00510                     if (slot->tts_isnull[i])
00511                         break;
00512                 }
00513                 if (i < nargs)
00514                     continue;
00515             }
00516 
00517             /* OK, put the tuple into the tuplesort object */
00518             if (peraggstate->numInputs == 1)
00519                 tuplesort_putdatum(peraggstate->sortstate,
00520                                    slot->tts_values[0],
00521                                    slot->tts_isnull[0]);
00522             else
00523                 tuplesort_puttupleslot(peraggstate->sortstate, slot);
00524         }
00525         else
00526         {
00527             /* We can apply the transition function immediately */
00528             FunctionCallInfoData fcinfo;
00529 
00530             /* Load values into fcinfo */
00531             /* Start from 1, since the 0th arg will be the transition value */
00532             Assert(slot->tts_nvalid >= nargs);
00533             for (i = 0; i < nargs; i++)
00534             {
00535                 fcinfo.arg[i + 1] = slot->tts_values[i];
00536                 fcinfo.argnull[i + 1] = slot->tts_isnull[i];
00537             }
00538 
00539             advance_transition_function(aggstate, peraggstate, pergroupstate,
00540                                         &fcinfo);
00541         }
00542     }
00543 }
00544 
00545 
00546 /*
00547  * Run the transition function for a DISTINCT or ORDER BY aggregate
00548  * with only one input.  This is called after we have completed
00549  * entering all the input values into the sort object.  We complete the
00550  * sort, read out the values in sorted order, and run the transition
00551  * function on each value (applying DISTINCT if appropriate).
00552  *
00553  * Note that the strictness of the transition function was checked when
00554  * entering the values into the sort, so we don't check it again here;
00555  * we just apply standard SQL DISTINCT logic.
00556  *
00557  * The one-input case is handled separately from the multi-input case
00558  * for performance reasons: for single by-value inputs, such as the
00559  * common case of count(distinct id), the tuplesort_getdatum code path
00560  * is around 300% faster.  (The speedup for by-reference types is less
00561  * but still noticeable.)
00562  *
00563  * When called, CurrentMemoryContext should be the per-query context.
00564  */
00565 static void
00566 process_ordered_aggregate_single(AggState *aggstate,
00567                                  AggStatePerAgg peraggstate,
00568                                  AggStatePerGroup pergroupstate)
00569 {
00570     Datum       oldVal = (Datum) 0;
00571     bool        oldIsNull = true;
00572     bool        haveOldVal = false;
00573     MemoryContext workcontext = aggstate->tmpcontext->ecxt_per_tuple_memory;
00574     MemoryContext oldContext;
00575     bool        isDistinct = (peraggstate->numDistinctCols > 0);
00576     Datum      *newVal;
00577     bool       *isNull;
00578     FunctionCallInfoData fcinfo;
00579 
00580     Assert(peraggstate->numDistinctCols < 2);
00581 
00582     tuplesort_performsort(peraggstate->sortstate);
00583 
00584     /* Load the column into argument 1 (arg 0 will be transition value) */
00585     newVal = fcinfo.arg + 1;
00586     isNull = fcinfo.argnull + 1;
00587 
00588     /*
00589      * Note: if input type is pass-by-ref, the datums returned by the sort are
00590      * freshly palloc'd in the per-query context, so we must be careful to
00591      * pfree them when they are no longer needed.
00592      */
00593 
00594     while (tuplesort_getdatum(peraggstate->sortstate, true,
00595                               newVal, isNull))
00596     {
00597         /*
00598          * Clear and select the working context for evaluation of the equality
00599          * function and transition function.
00600          */
00601         MemoryContextReset(workcontext);
00602         oldContext = MemoryContextSwitchTo(workcontext);
00603 
00604         /*
00605          * If DISTINCT mode, and not distinct from prior, skip it.
00606          *
00607          * Note: we assume equality functions don't care about collation.
00608          */
00609         if (isDistinct &&
00610             haveOldVal &&
00611             ((oldIsNull && *isNull) ||
00612              (!oldIsNull && !*isNull &&
00613               DatumGetBool(FunctionCall2(&peraggstate->equalfns[0],
00614                                          oldVal, *newVal)))))
00615         {
00616             /* equal to prior, so forget this one */
00617             if (!peraggstate->inputtypeByVal && !*isNull)
00618                 pfree(DatumGetPointer(*newVal));
00619         }
00620         else
00621         {
00622             advance_transition_function(aggstate, peraggstate, pergroupstate,
00623                                         &fcinfo);
00624             /* forget the old value, if any */
00625             if (!oldIsNull && !peraggstate->inputtypeByVal)
00626                 pfree(DatumGetPointer(oldVal));
00627             /* and remember the new one for subsequent equality checks */
00628             oldVal = *newVal;
00629             oldIsNull = *isNull;
00630             haveOldVal = true;
00631         }
00632 
00633         MemoryContextSwitchTo(oldContext);
00634     }
00635 
00636     if (!oldIsNull && !peraggstate->inputtypeByVal)
00637         pfree(DatumGetPointer(oldVal));
00638 
00639     tuplesort_end(peraggstate->sortstate);
00640     peraggstate->sortstate = NULL;
00641 }
00642 
00643 /*
00644  * Run the transition function for a DISTINCT or ORDER BY aggregate
00645  * with more than one input.  This is called after we have completed
00646  * entering all the input values into the sort object.  We complete the
00647  * sort, read out the values in sorted order, and run the transition
00648  * function on each value (applying DISTINCT if appropriate).
00649  *
00650  * When called, CurrentMemoryContext should be the per-query context.
00651  */
00652 static void
00653 process_ordered_aggregate_multi(AggState *aggstate,
00654                                 AggStatePerAgg peraggstate,
00655                                 AggStatePerGroup pergroupstate)
00656 {
00657     MemoryContext workcontext = aggstate->tmpcontext->ecxt_per_tuple_memory;
00658     FunctionCallInfoData fcinfo;
00659     TupleTableSlot *slot1 = peraggstate->evalslot;
00660     TupleTableSlot *slot2 = peraggstate->uniqslot;
00661     int         numArguments = peraggstate->numArguments;
00662     int         numDistinctCols = peraggstate->numDistinctCols;
00663     bool        haveOldValue = false;
00664     int         i;
00665 
00666     tuplesort_performsort(peraggstate->sortstate);
00667 
00668     ExecClearTuple(slot1);
00669     if (slot2)
00670         ExecClearTuple(slot2);
00671 
00672     while (tuplesort_gettupleslot(peraggstate->sortstate, true, slot1))
00673     {
00674         /*
00675          * Extract the first numArguments as datums to pass to the transfn.
00676          * (This will help execTuplesMatch too, so do it immediately.)
00677          */
00678         slot_getsomeattrs(slot1, numArguments);
00679 
00680         if (numDistinctCols == 0 ||
00681             !haveOldValue ||
00682             !execTuplesMatch(slot1, slot2,
00683                              numDistinctCols,
00684                              peraggstate->sortColIdx,
00685                              peraggstate->equalfns,
00686                              workcontext))
00687         {
00688             /* Load values into fcinfo */
00689             /* Start from 1, since the 0th arg will be the transition value */
00690             for (i = 0; i < numArguments; i++)
00691             {
00692                 fcinfo.arg[i + 1] = slot1->tts_values[i];
00693                 fcinfo.argnull[i + 1] = slot1->tts_isnull[i];
00694             }
00695 
00696             advance_transition_function(aggstate, peraggstate, pergroupstate,
00697                                         &fcinfo);
00698 
00699             if (numDistinctCols > 0)
00700             {
00701                 /* swap the slot pointers to retain the current tuple */
00702                 TupleTableSlot *tmpslot = slot2;
00703 
00704                 slot2 = slot1;
00705                 slot1 = tmpslot;
00706                 haveOldValue = true;
00707             }
00708         }
00709 
00710         /* Reset context each time, unless execTuplesMatch did it for us */
00711         if (numDistinctCols == 0)
00712             MemoryContextReset(workcontext);
00713 
00714         ExecClearTuple(slot1);
00715     }
00716 
00717     if (slot2)
00718         ExecClearTuple(slot2);
00719 
00720     tuplesort_end(peraggstate->sortstate);
00721     peraggstate->sortstate = NULL;
00722 }
00723 
00724 /*
00725  * Compute the final value of one aggregate.
00726  *
00727  * The finalfunction will be run, and the result delivered, in the
00728  * output-tuple context; caller's CurrentMemoryContext does not matter.
00729  */
00730 static void
00731 finalize_aggregate(AggState *aggstate,
00732                    AggStatePerAgg peraggstate,
00733                    AggStatePerGroup pergroupstate,
00734                    Datum *resultVal, bool *resultIsNull)
00735 {
00736     MemoryContext oldContext;
00737 
00738     oldContext = MemoryContextSwitchTo(aggstate->ss.ps.ps_ExprContext->ecxt_per_tuple_memory);
00739 
00740     /*
00741      * Apply the agg's finalfn if one is provided, else return transValue.
00742      */
00743     if (OidIsValid(peraggstate->finalfn_oid))
00744     {
00745         FunctionCallInfoData fcinfo;
00746 
00747         InitFunctionCallInfoData(fcinfo, &(peraggstate->finalfn), 1,
00748                                  peraggstate->aggCollation,
00749                                  (void *) aggstate, NULL);
00750         fcinfo.arg[0] = pergroupstate->transValue;
00751         fcinfo.argnull[0] = pergroupstate->transValueIsNull;
00752         if (fcinfo.flinfo->fn_strict && pergroupstate->transValueIsNull)
00753         {
00754             /* don't call a strict function with NULL inputs */
00755             *resultVal = (Datum) 0;
00756             *resultIsNull = true;
00757         }
00758         else
00759         {
00760             *resultVal = FunctionCallInvoke(&fcinfo);
00761             *resultIsNull = fcinfo.isnull;
00762         }
00763     }
00764     else
00765     {
00766         *resultVal = pergroupstate->transValue;
00767         *resultIsNull = pergroupstate->transValueIsNull;
00768     }
00769 
00770     /*
00771      * If result is pass-by-ref, make sure it is in the right context.
00772      */
00773     if (!peraggstate->resulttypeByVal && !*resultIsNull &&
00774         !MemoryContextContains(CurrentMemoryContext,
00775                                DatumGetPointer(*resultVal)))
00776         *resultVal = datumCopy(*resultVal,
00777                                peraggstate->resulttypeByVal,
00778                                peraggstate->resulttypeLen);
00779 
00780     MemoryContextSwitchTo(oldContext);
00781 }
00782 
00783 /*
00784  * find_unaggregated_cols
00785  *    Construct a bitmapset of the column numbers of un-aggregated Vars
00786  *    appearing in our targetlist and qual (HAVING clause)
00787  */
00788 static Bitmapset *
00789 find_unaggregated_cols(AggState *aggstate)
00790 {
00791     Agg        *node = (Agg *) aggstate->ss.ps.plan;
00792     Bitmapset  *colnos;
00793 
00794     colnos = NULL;
00795     (void) find_unaggregated_cols_walker((Node *) node->plan.targetlist,
00796                                          &colnos);
00797     (void) find_unaggregated_cols_walker((Node *) node->plan.qual,
00798                                          &colnos);
00799     return colnos;
00800 }
00801 
00802 static bool
00803 find_unaggregated_cols_walker(Node *node, Bitmapset **colnos)
00804 {
00805     if (node == NULL)
00806         return false;
00807     if (IsA(node, Var))
00808     {
00809         Var        *var = (Var *) node;
00810 
00811         /* setrefs.c should have set the varno to OUTER_VAR */
00812         Assert(var->varno == OUTER_VAR);
00813         Assert(var->varlevelsup == 0);
00814         *colnos = bms_add_member(*colnos, var->varattno);
00815         return false;
00816     }
00817     if (IsA(node, Aggref))      /* do not descend into aggregate exprs */
00818         return false;
00819     return expression_tree_walker(node, find_unaggregated_cols_walker,
00820                                   (void *) colnos);
00821 }
00822 
00823 /*
00824  * Initialize the hash table to empty.
00825  *
00826  * The hash table always lives in the aggcontext memory context.
00827  */
00828 static void
00829 build_hash_table(AggState *aggstate)
00830 {
00831     Agg        *node = (Agg *) aggstate->ss.ps.plan;
00832     MemoryContext tmpmem = aggstate->tmpcontext->ecxt_per_tuple_memory;
00833     Size        entrysize;
00834 
00835     Assert(node->aggstrategy == AGG_HASHED);
00836     Assert(node->numGroups > 0);
00837 
00838     entrysize = sizeof(AggHashEntryData) +
00839         (aggstate->numaggs - 1) * sizeof(AggStatePerGroupData);
00840 
00841     aggstate->hashtable = BuildTupleHashTable(node->numCols,
00842                                               node->grpColIdx,
00843                                               aggstate->eqfunctions,
00844                                               aggstate->hashfunctions,
00845                                               node->numGroups,
00846                                               entrysize,
00847                                               aggstate->aggcontext,
00848                                               tmpmem);
00849 }
00850 
00851 /*
00852  * Create a list of the tuple columns that actually need to be stored in
00853  * hashtable entries.  The incoming tuples from the child plan node will
00854  * contain grouping columns, other columns referenced in our targetlist and
00855  * qual, columns used to compute the aggregate functions, and perhaps just
00856  * junk columns we don't use at all.  Only columns of the first two types
00857  * need to be stored in the hashtable, and getting rid of the others can
00858  * make the table entries significantly smaller.  To avoid messing up Var
00859  * numbering, we keep the same tuple descriptor for hashtable entries as the
00860  * incoming tuples have, but set unwanted columns to NULL in the tuples that
00861  * go into the table.
00862  *
00863  * To eliminate duplicates, we build a bitmapset of the needed columns, then
00864  * convert it to an integer list (cheaper to scan at runtime). The list is
00865  * in decreasing order so that the first entry is the largest;
00866  * lookup_hash_entry depends on this to use slot_getsomeattrs correctly.
00867  * Note that the list is preserved over ExecReScanAgg, so we allocate it in
00868  * the per-query context (unlike the hash table itself).
00869  *
00870  * Note: at present, searching the tlist/qual is not really necessary since
00871  * the parser should disallow any unaggregated references to ungrouped
00872  * columns.  However, the search will be needed when we add support for
00873  * SQL99 semantics that allow use of "functionally dependent" columns that
00874  * haven't been explicitly grouped by.
00875  */
00876 static List *
00877 find_hash_columns(AggState *aggstate)
00878 {
00879     Agg        *node = (Agg *) aggstate->ss.ps.plan;
00880     Bitmapset  *colnos;
00881     List       *collist;
00882     int         i;
00883 
00884     /* Find Vars that will be needed in tlist and qual */
00885     colnos = find_unaggregated_cols(aggstate);
00886     /* Add in all the grouping columns */
00887     for (i = 0; i < node->numCols; i++)
00888         colnos = bms_add_member(colnos, node->grpColIdx[i]);
00889     /* Convert to list, using lcons so largest element ends up first */
00890     collist = NIL;
00891     while ((i = bms_first_member(colnos)) >= 0)
00892         collist = lcons_int(i, collist);
00893     bms_free(colnos);
00894 
00895     return collist;
00896 }
00897 
00898 /*
00899  * Estimate per-hash-table-entry overhead for the planner.
00900  *
00901  * Note that the estimate does not include space for pass-by-reference
00902  * transition data values, nor for the representative tuple of each group.
00903  */
00904 Size
00905 hash_agg_entry_size(int numAggs)
00906 {
00907     Size        entrysize;
00908 
00909     /* This must match build_hash_table */
00910     entrysize = sizeof(AggHashEntryData) +
00911         (numAggs - 1) * sizeof(AggStatePerGroupData);
00912     entrysize = MAXALIGN(entrysize);
00913     /* Account for hashtable overhead (assuming fill factor = 1) */
00914     entrysize += 3 * sizeof(void *);
00915     return entrysize;
00916 }
00917 
00918 /*
00919  * Find or create a hashtable entry for the tuple group containing the
00920  * given tuple.
00921  *
00922  * When called, CurrentMemoryContext should be the per-query context.
00923  */
00924 static AggHashEntry
00925 lookup_hash_entry(AggState *aggstate, TupleTableSlot *inputslot)
00926 {
00927     TupleTableSlot *hashslot = aggstate->hashslot;
00928     ListCell   *l;
00929     AggHashEntry entry;
00930     bool        isnew;
00931 
00932     /* if first time through, initialize hashslot by cloning input slot */
00933     if (hashslot->tts_tupleDescriptor == NULL)
00934     {
00935         ExecSetSlotDescriptor(hashslot, inputslot->tts_tupleDescriptor);
00936         /* Make sure all unused columns are NULLs */
00937         ExecStoreAllNullTuple(hashslot);
00938     }
00939 
00940     /* transfer just the needed columns into hashslot */
00941     slot_getsomeattrs(inputslot, linitial_int(aggstate->hash_needed));
00942     foreach(l, aggstate->hash_needed)
00943     {
00944         int         varNumber = lfirst_int(l) - 1;
00945 
00946         hashslot->tts_values[varNumber] = inputslot->tts_values[varNumber];
00947         hashslot->tts_isnull[varNumber] = inputslot->tts_isnull[varNumber];
00948     }
00949 
00950     /* find or create the hashtable entry using the filtered tuple */
00951     entry = (AggHashEntry) LookupTupleHashEntry(aggstate->hashtable,
00952                                                 hashslot,
00953                                                 &isnew);
00954 
00955     if (isnew)
00956     {
00957         /* initialize aggregates for new tuple group */
00958         initialize_aggregates(aggstate, aggstate->peragg, entry->pergroup);
00959     }
00960 
00961     return entry;
00962 }
00963 
00964 /*
00965  * ExecAgg -
00966  *
00967  *    ExecAgg receives tuples from its outer subplan and aggregates over
00968  *    the appropriate attribute for each aggregate function use (Aggref
00969  *    node) appearing in the targetlist or qual of the node.  The number
00970  *    of tuples to aggregate over depends on whether grouped or plain
00971  *    aggregation is selected.  In grouped aggregation, we produce a result
00972  *    row for each group; in plain aggregation there's a single result row
00973  *    for the whole query.  In either case, the value of each aggregate is
00974  *    stored in the expression context to be used when ExecProject evaluates
00975  *    the result tuple.
00976  */
00977 TupleTableSlot *
00978 ExecAgg(AggState *node)
00979 {
00980     /*
00981      * Check to see if we're still projecting out tuples from a previous agg
00982      * tuple (because there is a function-returning-set in the projection
00983      * expressions).  If so, try to project another one.
00984      */
00985     if (node->ss.ps.ps_TupFromTlist)
00986     {
00987         TupleTableSlot *result;
00988         ExprDoneCond isDone;
00989 
00990         result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
00991         if (isDone == ExprMultipleResult)
00992             return result;
00993         /* Done with that source tuple... */
00994         node->ss.ps.ps_TupFromTlist = false;
00995     }
00996 
00997     /*
00998      * Exit if nothing left to do.  (We must do the ps_TupFromTlist check
00999      * first, because in some cases agg_done gets set before we emit the final
01000      * aggregate tuple, and we have to finish running SRFs for it.)
01001      */
01002     if (node->agg_done)
01003         return NULL;
01004 
01005     /* Dispatch based on strategy */
01006     if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
01007     {
01008         if (!node->table_filled)
01009             agg_fill_hash_table(node);
01010         return agg_retrieve_hash_table(node);
01011     }
01012     else
01013         return agg_retrieve_direct(node);
01014 }
01015 
01016 /*
01017  * ExecAgg for non-hashed case
01018  */
01019 static TupleTableSlot *
01020 agg_retrieve_direct(AggState *aggstate)
01021 {
01022     Agg        *node = (Agg *) aggstate->ss.ps.plan;
01023     PlanState  *outerPlan;
01024     ExprContext *econtext;
01025     ExprContext *tmpcontext;
01026     Datum      *aggvalues;
01027     bool       *aggnulls;
01028     AggStatePerAgg peragg;
01029     AggStatePerGroup pergroup;
01030     TupleTableSlot *outerslot;
01031     TupleTableSlot *firstSlot;
01032     int         aggno;
01033 
01034     /*
01035      * get state info from node
01036      */
01037     outerPlan = outerPlanState(aggstate);
01038     /* econtext is the per-output-tuple expression context */
01039     econtext = aggstate->ss.ps.ps_ExprContext;
01040     aggvalues = econtext->ecxt_aggvalues;
01041     aggnulls = econtext->ecxt_aggnulls;
01042     /* tmpcontext is the per-input-tuple expression context */
01043     tmpcontext = aggstate->tmpcontext;
01044     peragg = aggstate->peragg;
01045     pergroup = aggstate->pergroup;
01046     firstSlot = aggstate->ss.ss_ScanTupleSlot;
01047 
01048     /*
01049      * We loop retrieving groups until we find one matching
01050      * aggstate->ss.ps.qual
01051      */
01052     while (!aggstate->agg_done)
01053     {
01054         /*
01055          * If we don't already have the first tuple of the new group, fetch it
01056          * from the outer plan.
01057          */
01058         if (aggstate->grp_firstTuple == NULL)
01059         {
01060             outerslot = ExecProcNode(outerPlan);
01061             if (!TupIsNull(outerslot))
01062             {
01063                 /*
01064                  * Make a copy of the first input tuple; we will use this for
01065                  * comparisons (in group mode) and for projection.
01066                  */
01067                 aggstate->grp_firstTuple = ExecCopySlotTuple(outerslot);
01068             }
01069             else
01070             {
01071                 /* outer plan produced no tuples at all */
01072                 aggstate->agg_done = true;
01073                 /* If we are grouping, we should produce no tuples too */
01074                 if (node->aggstrategy != AGG_PLAIN)
01075                     return NULL;
01076             }
01077         }
01078 
01079         /*
01080          * Clear the per-output-tuple context for each group, as well as
01081          * aggcontext (which contains any pass-by-ref transvalues of the old
01082          * group).  We also clear any child contexts of the aggcontext; some
01083          * aggregate functions store working state in such contexts.
01084          */
01085         ResetExprContext(econtext);
01086 
01087         MemoryContextResetAndDeleteChildren(aggstate->aggcontext);
01088 
01089         /*
01090          * Initialize working state for a new input tuple group
01091          */
01092         initialize_aggregates(aggstate, peragg, pergroup);
01093 
01094         if (aggstate->grp_firstTuple != NULL)
01095         {
01096             /*
01097              * Store the copied first input tuple in the tuple table slot
01098              * reserved for it.  The tuple will be deleted when it is cleared
01099              * from the slot.
01100              */
01101             ExecStoreTuple(aggstate->grp_firstTuple,
01102                            firstSlot,
01103                            InvalidBuffer,
01104                            true);
01105             aggstate->grp_firstTuple = NULL;    /* don't keep two pointers */
01106 
01107             /* set up for first advance_aggregates call */
01108             tmpcontext->ecxt_outertuple = firstSlot;
01109 
01110             /*
01111              * Process each outer-plan tuple, and then fetch the next one,
01112              * until we exhaust the outer plan or cross a group boundary.
01113              */
01114             for (;;)
01115             {
01116                 advance_aggregates(aggstate, pergroup);
01117 
01118                 /* Reset per-input-tuple context after each tuple */
01119                 ResetExprContext(tmpcontext);
01120 
01121                 outerslot = ExecProcNode(outerPlan);
01122                 if (TupIsNull(outerslot))
01123                 {
01124                     /* no more outer-plan tuples available */
01125                     aggstate->agg_done = true;
01126                     break;
01127                 }
01128                 /* set up for next advance_aggregates call */
01129                 tmpcontext->ecxt_outertuple = outerslot;
01130 
01131                 /*
01132                  * If we are grouping, check whether we've crossed a group
01133                  * boundary.
01134                  */
01135                 if (node->aggstrategy == AGG_SORTED)
01136                 {
01137                     if (!execTuplesMatch(firstSlot,
01138                                          outerslot,
01139                                          node->numCols, node->grpColIdx,
01140                                          aggstate->eqfunctions,
01141                                          tmpcontext->ecxt_per_tuple_memory))
01142                     {
01143                         /*
01144                          * Save the first input tuple of the next group.
01145                          */
01146                         aggstate->grp_firstTuple = ExecCopySlotTuple(outerslot);
01147                         break;
01148                     }
01149                 }
01150             }
01151         }
01152 
01153         /*
01154          * Done scanning input tuple group. Finalize each aggregate
01155          * calculation, and stash results in the per-output-tuple context.
01156          */
01157         for (aggno = 0; aggno < aggstate->numaggs; aggno++)
01158         {
01159             AggStatePerAgg peraggstate = &peragg[aggno];
01160             AggStatePerGroup pergroupstate = &pergroup[aggno];
01161 
01162             if (peraggstate->numSortCols > 0)
01163             {
01164                 if (peraggstate->numInputs == 1)
01165                     process_ordered_aggregate_single(aggstate,
01166                                                      peraggstate,
01167                                                      pergroupstate);
01168                 else
01169                     process_ordered_aggregate_multi(aggstate,
01170                                                     peraggstate,
01171                                                     pergroupstate);
01172             }
01173 
01174             finalize_aggregate(aggstate, peraggstate, pergroupstate,
01175                                &aggvalues[aggno], &aggnulls[aggno]);
01176         }
01177 
01178         /*
01179          * Use the representative input tuple for any references to
01180          * non-aggregated input columns in the qual and tlist.  (If we are not
01181          * grouping, and there are no input rows at all, we will come here
01182          * with an empty firstSlot ... but if not grouping, there can't be any
01183          * references to non-aggregated input columns, so no problem.)
01184          */
01185         econtext->ecxt_outertuple = firstSlot;
01186 
01187         /*
01188          * Check the qual (HAVING clause); if the group does not match, ignore
01189          * it and loop back to try to process another group.
01190          */
01191         if (ExecQual(aggstate->ss.ps.qual, econtext, false))
01192         {
01193             /*
01194              * Form and return a projection tuple using the aggregate results
01195              * and the representative input tuple.
01196              */
01197             TupleTableSlot *result;
01198             ExprDoneCond isDone;
01199 
01200             result = ExecProject(aggstate->ss.ps.ps_ProjInfo, &isDone);
01201 
01202             if (isDone != ExprEndResult)
01203             {
01204                 aggstate->ss.ps.ps_TupFromTlist =
01205                     (isDone == ExprMultipleResult);
01206                 return result;
01207             }
01208         }
01209         else
01210             InstrCountFiltered1(aggstate, 1);
01211     }
01212 
01213     /* No more groups */
01214     return NULL;
01215 }
01216 
01217 /*
01218  * ExecAgg for hashed case: phase 1, read input and build hash table
01219  */
01220 static void
01221 agg_fill_hash_table(AggState *aggstate)
01222 {
01223     PlanState  *outerPlan;
01224     ExprContext *tmpcontext;
01225     AggHashEntry entry;
01226     TupleTableSlot *outerslot;
01227 
01228     /*
01229      * get state info from node
01230      */
01231     outerPlan = outerPlanState(aggstate);
01232     /* tmpcontext is the per-input-tuple expression context */
01233     tmpcontext = aggstate->tmpcontext;
01234 
01235     /*
01236      * Process each outer-plan tuple, and then fetch the next one, until we
01237      * exhaust the outer plan.
01238      */
01239     for (;;)
01240     {
01241         outerslot = ExecProcNode(outerPlan);
01242         if (TupIsNull(outerslot))
01243             break;
01244         /* set up for advance_aggregates call */
01245         tmpcontext->ecxt_outertuple = outerslot;
01246 
01247         /* Find or build hashtable entry for this tuple's group */
01248         entry = lookup_hash_entry(aggstate, outerslot);
01249 
01250         /* Advance the aggregates */
01251         advance_aggregates(aggstate, entry->pergroup);
01252 
01253         /* Reset per-input-tuple context after each tuple */
01254         ResetExprContext(tmpcontext);
01255     }
01256 
01257     aggstate->table_filled = true;
01258     /* Initialize to walk the hash table */
01259     ResetTupleHashIterator(aggstate->hashtable, &aggstate->hashiter);
01260 }
01261 
01262 /*
01263  * ExecAgg for hashed case: phase 2, retrieving groups from hash table
01264  */
01265 static TupleTableSlot *
01266 agg_retrieve_hash_table(AggState *aggstate)
01267 {
01268     ExprContext *econtext;
01269     Datum      *aggvalues;
01270     bool       *aggnulls;
01271     AggStatePerAgg peragg;
01272     AggStatePerGroup pergroup;
01273     AggHashEntry entry;
01274     TupleTableSlot *firstSlot;
01275     int         aggno;
01276 
01277     /*
01278      * get state info from node
01279      */
01280     /* econtext is the per-output-tuple expression context */
01281     econtext = aggstate->ss.ps.ps_ExprContext;
01282     aggvalues = econtext->ecxt_aggvalues;
01283     aggnulls = econtext->ecxt_aggnulls;
01284     peragg = aggstate->peragg;
01285     firstSlot = aggstate->ss.ss_ScanTupleSlot;
01286 
01287     /*
01288      * We loop retrieving groups until we find one satisfying
01289      * aggstate->ss.ps.qual
01290      */
01291     while (!aggstate->agg_done)
01292     {
01293         /*
01294          * Find the next entry in the hash table
01295          */
01296         entry = (AggHashEntry) ScanTupleHashTable(&aggstate->hashiter);
01297         if (entry == NULL)
01298         {
01299             /* No more entries in hashtable, so done */
01300             aggstate->agg_done = TRUE;
01301             return NULL;
01302         }
01303 
01304         /*
01305          * Clear the per-output-tuple context for each group
01306          */
01307         ResetExprContext(econtext);
01308 
01309         /*
01310          * Store the copied first input tuple in the tuple table slot reserved
01311          * for it, so that it can be used in ExecProject.
01312          */
01313         ExecStoreMinimalTuple(entry->shared.firstTuple,
01314                               firstSlot,
01315                               false);
01316 
01317         pergroup = entry->pergroup;
01318 
01319         /*
01320          * Finalize each aggregate calculation, and stash results in the
01321          * per-output-tuple context.
01322          */
01323         for (aggno = 0; aggno < aggstate->numaggs; aggno++)
01324         {
01325             AggStatePerAgg peraggstate = &peragg[aggno];
01326             AggStatePerGroup pergroupstate = &pergroup[aggno];
01327 
01328             Assert(peraggstate->numSortCols == 0);
01329             finalize_aggregate(aggstate, peraggstate, pergroupstate,
01330                                &aggvalues[aggno], &aggnulls[aggno]);
01331         }
01332 
01333         /*
01334          * Use the representative input tuple for any references to
01335          * non-aggregated input columns in the qual and tlist.
01336          */
01337         econtext->ecxt_outertuple = firstSlot;
01338 
01339         /*
01340          * Check the qual (HAVING clause); if the group does not match, ignore
01341          * it and loop back to try to process another group.
01342          */
01343         if (ExecQual(aggstate->ss.ps.qual, econtext, false))
01344         {
01345             /*
01346              * Form and return a projection tuple using the aggregate results
01347              * and the representative input tuple.
01348              */
01349             TupleTableSlot *result;
01350             ExprDoneCond isDone;
01351 
01352             result = ExecProject(aggstate->ss.ps.ps_ProjInfo, &isDone);
01353 
01354             if (isDone != ExprEndResult)
01355             {
01356                 aggstate->ss.ps.ps_TupFromTlist =
01357                     (isDone == ExprMultipleResult);
01358                 return result;
01359             }
01360         }
01361         else
01362             InstrCountFiltered1(aggstate, 1);
01363     }
01364 
01365     /* No more groups */
01366     return NULL;
01367 }
01368 
01369 /* -----------------
01370  * ExecInitAgg
01371  *
01372  *  Creates the run-time information for the agg node produced by the
01373  *  planner and initializes its outer subtree
01374  * -----------------
01375  */
01376 AggState *
01377 ExecInitAgg(Agg *node, EState *estate, int eflags)
01378 {
01379     AggState   *aggstate;
01380     AggStatePerAgg peragg;
01381     Plan       *outerPlan;
01382     ExprContext *econtext;
01383     int         numaggs,
01384                 aggno;
01385     ListCell   *l;
01386 
01387     /* check for unsupported flags */
01388     Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
01389 
01390     /*
01391      * create state structure
01392      */
01393     aggstate = makeNode(AggState);
01394     aggstate->ss.ps.plan = (Plan *) node;
01395     aggstate->ss.ps.state = estate;
01396 
01397     aggstate->aggs = NIL;
01398     aggstate->numaggs = 0;
01399     aggstate->eqfunctions = NULL;
01400     aggstate->hashfunctions = NULL;
01401     aggstate->peragg = NULL;
01402     aggstate->agg_done = false;
01403     aggstate->pergroup = NULL;
01404     aggstate->grp_firstTuple = NULL;
01405     aggstate->hashtable = NULL;
01406 
01407     /*
01408      * Create expression contexts.  We need two, one for per-input-tuple
01409      * processing and one for per-output-tuple processing.  We cheat a little
01410      * by using ExecAssignExprContext() to build both.
01411      */
01412     ExecAssignExprContext(estate, &aggstate->ss.ps);
01413     aggstate->tmpcontext = aggstate->ss.ps.ps_ExprContext;
01414     ExecAssignExprContext(estate, &aggstate->ss.ps);
01415 
01416     /*
01417      * We also need a long-lived memory context for holding hashtable data
01418      * structures and transition values.  NOTE: the details of what is stored
01419      * in aggcontext and what is stored in the regular per-query memory
01420      * context are driven by a simple decision: we want to reset the
01421      * aggcontext at group boundaries (if not hashing) and in ExecReScanAgg to
01422      * recover no-longer-wanted space.
01423      */
01424     aggstate->aggcontext =
01425         AllocSetContextCreate(CurrentMemoryContext,
01426                               "AggContext",
01427                               ALLOCSET_DEFAULT_MINSIZE,
01428                               ALLOCSET_DEFAULT_INITSIZE,
01429                               ALLOCSET_DEFAULT_MAXSIZE);
01430 
01431     /*
01432      * tuple table initialization
01433      */
01434     ExecInitScanTupleSlot(estate, &aggstate->ss);
01435     ExecInitResultTupleSlot(estate, &aggstate->ss.ps);
01436     aggstate->hashslot = ExecInitExtraTupleSlot(estate);
01437 
01438     /*
01439      * initialize child expressions
01440      *
01441      * Note: ExecInitExpr finds Aggrefs for us, and also checks that no aggs
01442      * contain other agg calls in their arguments.  This would make no sense
01443      * under SQL semantics anyway (and it's forbidden by the spec). Because
01444      * that is true, we don't need to worry about evaluating the aggs in any
01445      * particular order.
01446      */
01447     aggstate->ss.ps.targetlist = (List *)
01448         ExecInitExpr((Expr *) node->plan.targetlist,
01449                      (PlanState *) aggstate);
01450     aggstate->ss.ps.qual = (List *)
01451         ExecInitExpr((Expr *) node->plan.qual,
01452                      (PlanState *) aggstate);
01453 
01454     /*
01455      * initialize child nodes
01456      *
01457      * If we are doing a hashed aggregation then the child plan does not need
01458      * to handle REWIND efficiently; see ExecReScanAgg.
01459      */
01460     if (node->aggstrategy == AGG_HASHED)
01461         eflags &= ~EXEC_FLAG_REWIND;
01462     outerPlan = outerPlan(node);
01463     outerPlanState(aggstate) = ExecInitNode(outerPlan, estate, eflags);
01464 
01465     /*
01466      * initialize source tuple type.
01467      */
01468     ExecAssignScanTypeFromOuterPlan(&aggstate->ss);
01469 
01470     /*
01471      * Initialize result tuple type and projection info.
01472      */
01473     ExecAssignResultTypeFromTL(&aggstate->ss.ps);
01474     ExecAssignProjectionInfo(&aggstate->ss.ps, NULL);
01475 
01476     aggstate->ss.ps.ps_TupFromTlist = false;
01477 
01478     /*
01479      * get the count of aggregates in targetlist and quals
01480      */
01481     numaggs = aggstate->numaggs;
01482     Assert(numaggs == list_length(aggstate->aggs));
01483     if (numaggs <= 0)
01484     {
01485         /*
01486          * This is not an error condition: we might be using the Agg node just
01487          * to do hash-based grouping.  Even in the regular case,
01488          * constant-expression simplification could optimize away all of the
01489          * Aggrefs in the targetlist and qual.  So keep going, but force local
01490          * copy of numaggs positive so that palloc()s below don't choke.
01491          */
01492         numaggs = 1;
01493     }
01494 
01495     /*
01496      * If we are grouping, precompute fmgr lookup data for inner loop. We need
01497      * both equality and hashing functions to do it by hashing, but only
01498      * equality if not hashing.
01499      */
01500     if (node->numCols > 0)
01501     {
01502         if (node->aggstrategy == AGG_HASHED)
01503             execTuplesHashPrepare(node->numCols,
01504                                   node->grpOperators,
01505                                   &aggstate->eqfunctions,
01506                                   &aggstate->hashfunctions);
01507         else
01508             aggstate->eqfunctions =
01509                 execTuplesMatchPrepare(node->numCols,
01510                                        node->grpOperators);
01511     }
01512 
01513     /*
01514      * Set up aggregate-result storage in the output expr context, and also
01515      * allocate my private per-agg working storage
01516      */
01517     econtext = aggstate->ss.ps.ps_ExprContext;
01518     econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs);
01519     econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs);
01520 
01521     peragg = (AggStatePerAgg) palloc0(sizeof(AggStatePerAggData) * numaggs);
01522     aggstate->peragg = peragg;
01523 
01524     if (node->aggstrategy == AGG_HASHED)
01525     {
01526         build_hash_table(aggstate);
01527         aggstate->table_filled = false;
01528         /* Compute the columns we actually need to hash on */
01529         aggstate->hash_needed = find_hash_columns(aggstate);
01530     }
01531     else
01532     {
01533         AggStatePerGroup pergroup;
01534 
01535         pergroup = (AggStatePerGroup) palloc0(sizeof(AggStatePerGroupData) * numaggs);
01536         aggstate->pergroup = pergroup;
01537     }
01538 
01539     /*
01540      * Perform lookups of aggregate function info, and initialize the
01541      * unchanging fields of the per-agg data.  We also detect duplicate
01542      * aggregates (for example, "SELECT sum(x) ... HAVING sum(x) > 0"). When
01543      * duplicates are detected, we only make an AggStatePerAgg struct for the
01544      * first one.  The clones are simply pointed at the same result entry by
01545      * giving them duplicate aggno values.
01546      */
01547     aggno = -1;
01548     foreach(l, aggstate->aggs)
01549     {
01550         AggrefExprState *aggrefstate = (AggrefExprState *) lfirst(l);
01551         Aggref     *aggref = (Aggref *) aggrefstate->xprstate.expr;
01552         AggStatePerAgg peraggstate;
01553         Oid         inputTypes[FUNC_MAX_ARGS];
01554         int         numArguments;
01555         int         numInputs;
01556         int         numSortCols;
01557         int         numDistinctCols;
01558         List       *sortlist;
01559         HeapTuple   aggTuple;
01560         Form_pg_aggregate aggform;
01561         Oid         aggtranstype;
01562         AclResult   aclresult;
01563         Oid         transfn_oid,
01564                     finalfn_oid;
01565         Expr       *transfnexpr,
01566                    *finalfnexpr;
01567         Datum       textInitVal;
01568         int         i;
01569         ListCell   *lc;
01570 
01571         /* Planner should have assigned aggregate to correct level */
01572         Assert(aggref->agglevelsup == 0);
01573 
01574         /* Look for a previous duplicate aggregate */
01575         for (i = 0; i <= aggno; i++)
01576         {
01577             if (equal(aggref, peragg[i].aggref) &&
01578                 !contain_volatile_functions((Node *) aggref))
01579                 break;
01580         }
01581         if (i <= aggno)
01582         {
01583             /* Found a match to an existing entry, so just mark it */
01584             aggrefstate->aggno = i;
01585             continue;
01586         }
01587 
01588         /* Nope, so assign a new PerAgg record */
01589         peraggstate = &peragg[++aggno];
01590 
01591         /* Mark Aggref state node with assigned index in the result array */
01592         aggrefstate->aggno = aggno;
01593 
01594         /* Fill in the peraggstate data */
01595         peraggstate->aggrefstate = aggrefstate;
01596         peraggstate->aggref = aggref;
01597         numInputs = list_length(aggref->args);
01598         peraggstate->numInputs = numInputs;
01599         peraggstate->sortstate = NULL;
01600 
01601         /*
01602          * Get actual datatypes of the inputs.  These could be different from
01603          * the agg's declared input types, when the agg accepts ANY or a
01604          * polymorphic type.
01605          */
01606         numArguments = 0;
01607         foreach(lc, aggref->args)
01608         {
01609             TargetEntry *tle = (TargetEntry *) lfirst(lc);
01610 
01611             if (!tle->resjunk)
01612                 inputTypes[numArguments++] = exprType((Node *) tle->expr);
01613         }
01614         peraggstate->numArguments = numArguments;
01615 
01616         aggTuple = SearchSysCache1(AGGFNOID,
01617                                    ObjectIdGetDatum(aggref->aggfnoid));
01618         if (!HeapTupleIsValid(aggTuple))
01619             elog(ERROR, "cache lookup failed for aggregate %u",
01620                  aggref->aggfnoid);
01621         aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);
01622 
01623         /* Check permission to call aggregate function */
01624         aclresult = pg_proc_aclcheck(aggref->aggfnoid, GetUserId(),
01625                                      ACL_EXECUTE);
01626         if (aclresult != ACLCHECK_OK)
01627             aclcheck_error(aclresult, ACL_KIND_PROC,
01628                            get_func_name(aggref->aggfnoid));
01629         InvokeFunctionExecuteHook(aggref->aggfnoid);
01630 
01631         peraggstate->transfn_oid = transfn_oid = aggform->aggtransfn;
01632         peraggstate->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
01633 
01634         /* Check that aggregate owner has permission to call component fns */
01635         {
01636             HeapTuple   procTuple;
01637             Oid         aggOwner;
01638 
01639             procTuple = SearchSysCache1(PROCOID,
01640                                         ObjectIdGetDatum(aggref->aggfnoid));
01641             if (!HeapTupleIsValid(procTuple))
01642                 elog(ERROR, "cache lookup failed for function %u",
01643                      aggref->aggfnoid);
01644             aggOwner = ((Form_pg_proc) GETSTRUCT(procTuple))->proowner;
01645             ReleaseSysCache(procTuple);
01646 
01647             aclresult = pg_proc_aclcheck(transfn_oid, aggOwner,
01648                                          ACL_EXECUTE);
01649             if (aclresult != ACLCHECK_OK)
01650                 aclcheck_error(aclresult, ACL_KIND_PROC,
01651                                get_func_name(transfn_oid));
01652             InvokeFunctionExecuteHook(transfn_oid);
01653             if (OidIsValid(finalfn_oid))
01654             {
01655                 aclresult = pg_proc_aclcheck(finalfn_oid, aggOwner,
01656                                              ACL_EXECUTE);
01657                 if (aclresult != ACLCHECK_OK)
01658                     aclcheck_error(aclresult, ACL_KIND_PROC,
01659                                    get_func_name(finalfn_oid));
01660                 InvokeFunctionExecuteHook(finalfn_oid);
01661             }
01662         }
01663 
01664         /* resolve actual type of transition state, if polymorphic */
01665         aggtranstype = aggform->aggtranstype;
01666         if (IsPolymorphicType(aggtranstype))
01667         {
01668             /* have to fetch the agg's declared input types... */
01669             Oid        *declaredArgTypes;
01670             int         agg_nargs;
01671 
01672             (void) get_func_signature(aggref->aggfnoid,
01673                                       &declaredArgTypes, &agg_nargs);
01674             Assert(agg_nargs == numArguments);
01675             aggtranstype = enforce_generic_type_consistency(inputTypes,
01676                                                             declaredArgTypes,
01677                                                             agg_nargs,
01678                                                             aggtranstype,
01679                                                             false);
01680             pfree(declaredArgTypes);
01681         }
01682 
01683         /* build expression trees using actual argument & result types */
01684         build_aggregate_fnexprs(inputTypes,
01685                                 numArguments,
01686                                 aggtranstype,
01687                                 aggref->aggtype,
01688                                 aggref->inputcollid,
01689                                 transfn_oid,
01690                                 finalfn_oid,
01691                                 &transfnexpr,
01692                                 &finalfnexpr);
01693 
01694         fmgr_info(transfn_oid, &peraggstate->transfn);
01695         fmgr_info_set_expr((Node *) transfnexpr, &peraggstate->transfn);
01696 
01697         if (OidIsValid(finalfn_oid))
01698         {
01699             fmgr_info(finalfn_oid, &peraggstate->finalfn);
01700             fmgr_info_set_expr((Node *) finalfnexpr, &peraggstate->finalfn);
01701         }
01702 
01703         peraggstate->aggCollation = aggref->inputcollid;
01704 
01705         get_typlenbyval(aggref->aggtype,
01706                         &peraggstate->resulttypeLen,
01707                         &peraggstate->resulttypeByVal);
01708         get_typlenbyval(aggtranstype,
01709                         &peraggstate->transtypeLen,
01710                         &peraggstate->transtypeByVal);
01711 
01712         /*
01713          * initval is potentially null, so don't try to access it as a struct
01714          * field. Must do it the hard way with SysCacheGetAttr.
01715          */
01716         textInitVal = SysCacheGetAttr(AGGFNOID, aggTuple,
01717                                       Anum_pg_aggregate_agginitval,
01718                                       &peraggstate->initValueIsNull);
01719 
01720         if (peraggstate->initValueIsNull)
01721             peraggstate->initValue = (Datum) 0;
01722         else
01723             peraggstate->initValue = GetAggInitVal(textInitVal,
01724                                                    aggtranstype);
01725 
01726         /*
01727          * If the transfn is strict and the initval is NULL, make sure input
01728          * type and transtype are the same (or at least binary-compatible), so
01729          * that it's OK to use the first input value as the initial
01730          * transValue.  This should have been checked at agg definition time,
01731          * but just in case...
01732          */
01733         if (peraggstate->transfn.fn_strict && peraggstate->initValueIsNull)
01734         {
01735             if (numArguments < 1 ||
01736                 !IsBinaryCoercible(inputTypes[0], aggtranstype))
01737                 ereport(ERROR,
01738                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
01739                          errmsg("aggregate %u needs to have compatible input type and transition type",
01740                                 aggref->aggfnoid)));
01741         }
01742 
01743         /*
01744          * Get a tupledesc corresponding to the inputs (including sort
01745          * expressions) of the agg.
01746          */
01747         peraggstate->evaldesc = ExecTypeFromTL(aggref->args, false);
01748 
01749         /* Create slot we're going to do argument evaluation in */
01750         peraggstate->evalslot = ExecInitExtraTupleSlot(estate);
01751         ExecSetSlotDescriptor(peraggstate->evalslot, peraggstate->evaldesc);
01752 
01753         /* Set up projection info for evaluation */
01754         peraggstate->evalproj = ExecBuildProjectionInfo(aggrefstate->args,
01755                                                         aggstate->tmpcontext,
01756                                                         peraggstate->evalslot,
01757                                                         NULL);
01758 
01759         /*
01760          * If we're doing either DISTINCT or ORDER BY, then we have a list of
01761          * SortGroupClause nodes; fish out the data in them and stick them
01762          * into arrays.
01763          *
01764          * Note that by construction, if there is a DISTINCT clause then the
01765          * ORDER BY clause is a prefix of it (see transformDistinctClause).
01766          */
01767         if (aggref->aggdistinct)
01768         {
01769             sortlist = aggref->aggdistinct;
01770             numSortCols = numDistinctCols = list_length(sortlist);
01771             Assert(numSortCols >= list_length(aggref->aggorder));
01772         }
01773         else
01774         {
01775             sortlist = aggref->aggorder;
01776             numSortCols = list_length(sortlist);
01777             numDistinctCols = 0;
01778         }
01779 
01780         peraggstate->numSortCols = numSortCols;
01781         peraggstate->numDistinctCols = numDistinctCols;
01782 
01783         if (numSortCols > 0)
01784         {
01785             /*
01786              * We don't implement DISTINCT or ORDER BY aggs in the HASHED case
01787              * (yet)
01788              */
01789             Assert(node->aggstrategy != AGG_HASHED);
01790 
01791             /* If we have only one input, we need its len/byval info. */
01792             if (numInputs == 1)
01793             {
01794                 get_typlenbyval(inputTypes[0],
01795                                 &peraggstate->inputtypeLen,
01796                                 &peraggstate->inputtypeByVal);
01797             }
01798             else if (numDistinctCols > 0)
01799             {
01800                 /* we will need an extra slot to store prior values */
01801                 peraggstate->uniqslot = ExecInitExtraTupleSlot(estate);
01802                 ExecSetSlotDescriptor(peraggstate->uniqslot,
01803                                       peraggstate->evaldesc);
01804             }
01805 
01806             /* Extract the sort information for use later */
01807             peraggstate->sortColIdx =
01808                 (AttrNumber *) palloc(numSortCols * sizeof(AttrNumber));
01809             peraggstate->sortOperators =
01810                 (Oid *) palloc(numSortCols * sizeof(Oid));
01811             peraggstate->sortCollations =
01812                 (Oid *) palloc(numSortCols * sizeof(Oid));
01813             peraggstate->sortNullsFirst =
01814                 (bool *) palloc(numSortCols * sizeof(bool));
01815 
01816             i = 0;
01817             foreach(lc, sortlist)
01818             {
01819                 SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc);
01820                 TargetEntry *tle = get_sortgroupclause_tle(sortcl,
01821                                                            aggref->args);
01822 
01823                 /* the parser should have made sure of this */
01824                 Assert(OidIsValid(sortcl->sortop));
01825 
01826                 peraggstate->sortColIdx[i] = tle->resno;
01827                 peraggstate->sortOperators[i] = sortcl->sortop;
01828                 peraggstate->sortCollations[i] = exprCollation((Node *) tle->expr);
01829                 peraggstate->sortNullsFirst[i] = sortcl->nulls_first;
01830                 i++;
01831             }
01832             Assert(i == numSortCols);
01833         }
01834 
01835         if (aggref->aggdistinct)
01836         {
01837             Assert(numArguments > 0);
01838 
01839             /*
01840              * We need the equal function for each DISTINCT comparison we will
01841              * make.
01842              */
01843             peraggstate->equalfns =
01844                 (FmgrInfo *) palloc(numDistinctCols * sizeof(FmgrInfo));
01845 
01846             i = 0;
01847             foreach(lc, aggref->aggdistinct)
01848             {
01849                 SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc);
01850 
01851                 fmgr_info(get_opcode(sortcl->eqop), &peraggstate->equalfns[i]);
01852                 i++;
01853             }
01854             Assert(i == numDistinctCols);
01855         }
01856 
01857         ReleaseSysCache(aggTuple);
01858     }
01859 
01860     /* Update numaggs to match number of unique aggregates found */
01861     aggstate->numaggs = aggno + 1;
01862 
01863     return aggstate;
01864 }
01865 
01866 static Datum
01867 GetAggInitVal(Datum textInitVal, Oid transtype)
01868 {
01869     Oid         typinput,
01870                 typioparam;
01871     char       *strInitVal;
01872     Datum       initVal;
01873 
01874     getTypeInputInfo(transtype, &typinput, &typioparam);
01875     strInitVal = TextDatumGetCString(textInitVal);
01876     initVal = OidInputFunctionCall(typinput, strInitVal,
01877                                    typioparam, -1);
01878     pfree(strInitVal);
01879     return initVal;
01880 }
01881 
01882 void
01883 ExecEndAgg(AggState *node)
01884 {
01885     PlanState  *outerPlan;
01886     int         aggno;
01887 
01888     /* Make sure we have closed any open tuplesorts */
01889     for (aggno = 0; aggno < node->numaggs; aggno++)
01890     {
01891         AggStatePerAgg peraggstate = &node->peragg[aggno];
01892 
01893         if (peraggstate->sortstate)
01894             tuplesort_end(peraggstate->sortstate);
01895     }
01896 
01897     /*
01898      * Free both the expr contexts.
01899      */
01900     ExecFreeExprContext(&node->ss.ps);
01901     node->ss.ps.ps_ExprContext = node->tmpcontext;
01902     ExecFreeExprContext(&node->ss.ps);
01903 
01904     /* clean up tuple table */
01905     ExecClearTuple(node->ss.ss_ScanTupleSlot);
01906 
01907     MemoryContextDelete(node->aggcontext);
01908 
01909     outerPlan = outerPlanState(node);
01910     ExecEndNode(outerPlan);
01911 }
01912 
01913 void
01914 ExecReScanAgg(AggState *node)
01915 {
01916     ExprContext *econtext = node->ss.ps.ps_ExprContext;
01917     int         aggno;
01918 
01919     node->agg_done = false;
01920 
01921     node->ss.ps.ps_TupFromTlist = false;
01922 
01923     if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
01924     {
01925         /*
01926          * In the hashed case, if we haven't yet built the hash table then we
01927          * can just return; nothing done yet, so nothing to undo. If subnode's
01928          * chgParam is not NULL then it will be re-scanned by ExecProcNode,
01929          * else no reason to re-scan it at all.
01930          */
01931         if (!node->table_filled)
01932             return;
01933 
01934         /*
01935          * If we do have the hash table and the subplan does not have any
01936          * parameter changes, then we can just rescan the existing hash table;
01937          * no need to build it again.
01938          */
01939         if (node->ss.ps.lefttree->chgParam == NULL)
01940         {
01941             ResetTupleHashIterator(node->hashtable, &node->hashiter);
01942             return;
01943         }
01944     }
01945 
01946     /* Make sure we have closed any open tuplesorts */
01947     for (aggno = 0; aggno < node->numaggs; aggno++)
01948     {
01949         AggStatePerAgg peraggstate = &node->peragg[aggno];
01950 
01951         if (peraggstate->sortstate)
01952             tuplesort_end(peraggstate->sortstate);
01953         peraggstate->sortstate = NULL;
01954     }
01955 
01956     /* Release first tuple of group, if we have made a copy */
01957     if (node->grp_firstTuple != NULL)
01958     {
01959         heap_freetuple(node->grp_firstTuple);
01960         node->grp_firstTuple = NULL;
01961     }
01962 
01963     /* Forget current agg values */
01964     MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numaggs);
01965     MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numaggs);
01966 
01967     /*
01968      * Release all temp storage. Note that with AGG_HASHED, the hash table is
01969      * allocated in a sub-context of the aggcontext. We're going to rebuild
01970      * the hash table from scratch, so we need to use
01971      * MemoryContextResetAndDeleteChildren() to avoid leaking the old hash
01972      * table's memory context header.
01973      */
01974     MemoryContextResetAndDeleteChildren(node->aggcontext);
01975 
01976     if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
01977     {
01978         /* Rebuild an empty hash table */
01979         build_hash_table(node);
01980         node->table_filled = false;
01981     }
01982     else
01983     {
01984         /*
01985          * Reset the per-group state (in particular, mark transvalues null)
01986          */
01987         MemSet(node->pergroup, 0,
01988                sizeof(AggStatePerGroupData) * node->numaggs);
01989     }
01990 
01991     /*
01992      * if chgParam of subnode is not null then plan will be re-scanned by
01993      * first ExecProcNode.
01994      */
01995     if (node->ss.ps.lefttree->chgParam == NULL)
01996         ExecReScan(node->ss.ps.lefttree);
01997 }
01998 
01999 /*
02000  * AggCheckCallContext - test if a SQL function is being called as an aggregate
02001  *
02002  * The transition and/or final functions of an aggregate may want to verify
02003  * that they are being called as aggregates, rather than as plain SQL
02004  * functions.  They should use this function to do so.  The return value
02005  * is nonzero if being called as an aggregate, or zero if not.  (Specific
02006  * nonzero values are AGG_CONTEXT_AGGREGATE or AGG_CONTEXT_WINDOW, but more
02007  * values could conceivably appear in future.)
02008  *
02009  * If aggcontext isn't NULL, the function also stores at *aggcontext the
02010  * identity of the memory context that aggregate transition values are
02011  * being stored in.
02012  */
02013 int
02014 AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
02015 {
02016     if (fcinfo->context && IsA(fcinfo->context, AggState))
02017     {
02018         if (aggcontext)
02019             *aggcontext = ((AggState *) fcinfo->context)->aggcontext;
02020         return AGG_CONTEXT_AGGREGATE;
02021     }
02022     if (fcinfo->context && IsA(fcinfo->context, WindowAggState))
02023     {
02024         if (aggcontext)
02025             *aggcontext = ((WindowAggState *) fcinfo->context)->aggcontext;
02026         return AGG_CONTEXT_WINDOW;
02027     }
02028 
02029     /* this is just to prevent "uninitialized variable" warnings */
02030     if (aggcontext)
02031         *aggcontext = NULL;
02032     return 0;
02033 }
02034 
02035 /*
02036  * aggregate_dummy - dummy execution routine for aggregate functions
02037  *
02038  * This function is listed as the implementation (prosrc field) of pg_proc
02039  * entries for aggregate functions.  Its only purpose is to throw an error
02040  * if someone mistakenly executes such a function in the normal way.
02041  *
02042  * Perhaps someday we could assign real meaning to the prosrc field of
02043  * an aggregate?
02044  */
02045 Datum
02046 aggregate_dummy(PG_FUNCTION_ARGS)
02047 {
02048     elog(ERROR, "aggregate function %u called as normal function",
02049          fcinfo->flinfo->fn_oid);
02050     return (Datum) 0;           /* keep compiler quiet */
02051 }