LCOV - code coverage report
Current view: top level - src/backend/executor - nodeAgg.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 1092 1134 96.3 %
Date: 2019-09-19 02:07:14 Functions: 36 38 94.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * nodeAgg.c
       4             :  *    Routines to handle aggregate nodes.
       5             :  *
       6             :  *    ExecAgg normally evaluates each aggregate in the following steps:
       7             :  *
       8             :  *       transvalue = initcond
       9             :  *       foreach input_tuple do
      10             :  *          transvalue = transfunc(transvalue, input_value(s))
      11             :  *       result = finalfunc(transvalue, direct_argument(s))
      12             :  *
      13             :  *    If a finalfunc is not supplied then the result is just the ending
      14             :  *    value of transvalue.
      15             :  *
      16             :  *    Other behaviors can be selected by the "aggsplit" mode, which exists
      17             :  *    to support partial aggregation.  It is possible to:
      18             :  *    * Skip running the finalfunc, so that the output is always the
      19             :  *    final transvalue state.
      20             :  *    * Substitute the combinefunc for the transfunc, so that transvalue
      21             :  *    states (propagated up from a child partial-aggregation step) are merged
      22             :  *    rather than processing raw input rows.  (The statements below about
      23             :  *    the transfunc apply equally to the combinefunc, when it's selected.)
      24             :  *    * Apply the serializefunc to the output values (this only makes sense
      25             :  *    when skipping the finalfunc, since the serializefunc works on the
      26             :  *    transvalue data type).
      27             :  *    * Apply the deserializefunc to the input values (this only makes sense
      28             :  *    when using the combinefunc, for similar reasons).
      29             :  *    It is the planner's responsibility to connect up Agg nodes using these
      30             :  *    alternate behaviors in a way that makes sense, with partial aggregation
      31             :  *    results being fed to nodes that expect them.
      32             :  *
      33             :  *    If a normal aggregate call specifies DISTINCT or ORDER BY, we sort the
      34             :  *    input tuples and eliminate duplicates (if required) before performing
      35             :  *    the above-depicted process.  (However, we don't do that for ordered-set
      36             :  *    aggregates; their "ORDER BY" inputs are ordinary aggregate arguments
      37             :  *    so far as this module is concerned.)  Note that partial aggregation
      38             :  *    is not supported in these cases, since we couldn't ensure global
      39             :  *    ordering or distinctness of the inputs.
      40             :  *
      41             :  *    If transfunc is marked "strict" in pg_proc and initcond is NULL,
      42             :  *    then the first non-NULL input_value is assigned directly to transvalue,
      43             :  *    and transfunc isn't applied until the second non-NULL input_value.
      44             :  *    The agg's first input type and transtype must be the same in this case!
      45             :  *
      46             :  *    If transfunc is marked "strict" then NULL input_values are skipped,
      47             :  *    keeping the previous transvalue.  If transfunc is not strict then it
      48             :  *    is called for every input tuple and must deal with NULL initcond
      49             :  *    or NULL input_values for itself.
      50             :  *
      51             :  *    If finalfunc is marked "strict" then it is not called when the
      52             :  *    ending transvalue is NULL, instead a NULL result is created
      53             :  *    automatically (this is just the usual handling of strict functions,
      54             :  *    of course).  A non-strict finalfunc can make its own choice of
      55             :  *    what to return for a NULL ending transvalue.
      56             :  *
      57             :  *    Ordered-set aggregates are treated specially in one other way: we
      58             :  *    evaluate any "direct" arguments and pass them to the finalfunc along
      59             :  *    with the transition value.
      60             :  *
      61             :  *    A finalfunc can have additional arguments beyond the transvalue and
      62             :  *    any "direct" arguments, corresponding to the input arguments of the
      63             :  *    aggregate.  These are always just passed as NULL.  Such arguments may be
      64             :  *    needed to allow resolution of a polymorphic aggregate's result type.
      65             :  *
      66             :  *    We compute aggregate input expressions and run the transition functions
      67             :  *    in a temporary econtext (aggstate->tmpcontext).  This is reset at least
      68             :  *    once per input tuple, so when the transvalue datatype is
      69             :  *    pass-by-reference, we have to be careful to copy it into a longer-lived
      70             :  *    memory context, and free the prior value to avoid memory leakage.  We
      71             :  *    store transvalues in another set of econtexts, aggstate->aggcontexts
      72             :  *    (one per grouping set, see below), which are also used for the hashtable
      73             :  *    structures in AGG_HASHED mode.  These econtexts are rescanned, not just
      74             :  *    reset, at group boundaries so that aggregate transition functions can
      75             :  *    register shutdown callbacks via AggRegisterCallback.
      76             :  *
      77             :  *    The node's regular econtext (aggstate->ss.ps.ps_ExprContext) is used to
      78             :  *    run finalize functions and compute the output tuple; this context can be
      79             :  *    reset once per output tuple.
      80             :  *
      81             :  *    The executor's AggState node is passed as the fmgr "context" value in
      82             :  *    all transfunc and finalfunc calls.  It is not recommended that the
      83             :  *    transition functions look at the AggState node directly, but they can
      84             :  *    use AggCheckCallContext() to verify that they are being called by
      85             :  *    nodeAgg.c (and not as ordinary SQL functions).  The main reason a
      86             :  *    transition function might want to know this is so that it can avoid
      87             :  *    palloc'ing a fixed-size pass-by-ref transition value on every call:
      88             :  *    it can instead just scribble on and return its left input.  Ordinarily
      89             :  *    it is completely forbidden for functions to modify pass-by-ref inputs,
      90             :  *    but in the aggregate case we know the left input is either the initial
      91             :  *    transition value or a previous function result, and in either case its
      92             :  *    value need not be preserved.  See int8inc() for an example.  Notice that
      93             :  *    the EEOP_AGG_PLAIN_TRANS step is coded to avoid a data copy step when
      94             :  *    the previous transition value pointer is returned.  It is also possible
      95             :  *    to avoid repeated data copying when the transition value is an expanded
      96             :  *    object: to do that, the transition function must take care to return
      97             :  *    an expanded object that is in a child context of the memory context
      98             :  *    returned by AggCheckCallContext().  Also, some transition functions want
      99             :  *    to store working state in addition to the nominal transition value; they
     100             :  *    can use the memory context returned by AggCheckCallContext() to do that.
     101             :  *
     102             :  *    Note: AggCheckCallContext() is available as of PostgreSQL 9.0.  The
     103             :  *    AggState is available as context in earlier releases (back to 8.1),
     104             :  *    but direct examination of the node is needed to use it before 9.0.
     105             :  *
     106             :  *    As of 9.4, aggregate transition functions can also use AggGetAggref()
     107             :  *    to get hold of the Aggref expression node for their aggregate call.
     108             :  *    This is mainly intended for ordered-set aggregates, which are not
     109             :  *    supported as window functions.  (A regular aggregate function would
     110             :  *    need some fallback logic to use this, since there's no Aggref node
     111             :  *    for a window function.)
     112             :  *
     113             :  *    Grouping sets:
     114             :  *
     115             :  *    A list of grouping sets which is structurally equivalent to a ROLLUP
     116             :  *    clause (e.g. (a,b,c), (a,b), (a)) can be processed in a single pass over
     117             :  *    ordered data.  We do this by keeping a separate set of transition values
     118             :  *    for each grouping set being concurrently processed; for each input tuple
     119             :  *    we update them all, and on group boundaries we reset those states
     120             :  *    (starting at the front of the list) whose grouping values have changed
     121             :  *    (the list of grouping sets is ordered from most specific to least
     122             :  *    specific).
     123             :  *
     124             :  *    Where more complex grouping sets are used, we break them down into
     125             :  *    "phases", where each phase has a different sort order (except phase 0
     126             :  *    which is reserved for hashing).  During each phase but the last, the
     127             :  *    input tuples are additionally stored in a tuplesort which is keyed to the
     128             :  *    next phase's sort order; during each phase but the first, the input
     129             :  *    tuples are drawn from the previously sorted data.  (The sorting of the
     130             :  *    data for the first phase is handled by the planner, as it might be
     131             :  *    satisfied by underlying nodes.)
     132             :  *
     133             :  *    Hashing can be mixed with sorted grouping.  To do this, we have an
     134             :  *    AGG_MIXED strategy that populates the hashtables during the first sorted
     135             :  *    phase, and switches to reading them out after completing all sort phases.
     136             :  *    We can also support AGG_HASHED with multiple hash tables and no sorting
     137             :  *    at all.
     138             :  *
     139             :  *    From the perspective of aggregate transition and final functions, the
     140             :  *    only issue regarding grouping sets is this: a single call site (flinfo)
     141             :  *    of an aggregate function may be used for updating several different
     142             :  *    transition values in turn. So the function must not cache in the flinfo
     143             :  *    anything which logically belongs as part of the transition value (most
     144             :  *    importantly, the memory context in which the transition value exists).
     145             :  *    The support API functions (AggCheckCallContext, AggRegisterCallback) are
     146             :  *    sensitive to the grouping set for which the aggregate function is
     147             :  *    currently being called.
     148             :  *
     149             :  *    Plan structure:
     150             :  *
     151             :  *    What we get from the planner is actually one "real" Agg node which is
     152             :  *    part of the plan tree proper, but which optionally has an additional list
     153             :  *    of Agg nodes hung off the side via the "chain" field.  This is because an
     154             :  *    Agg node happens to be a convenient representation of all the data we
     155             :  *    need for grouping sets.
     156             :  *
     157             :  *    For many purposes, we treat the "real" node as if it were just the first
     158             :  *    node in the chain.  The chain must be ordered such that hashed entries
     159             :  *    come before sorted/plain entries; the real node is marked AGG_MIXED if
     160             :  *    there are both types present (in which case the real node describes one
     161             :  *    of the hashed groupings, other AGG_HASHED nodes may optionally follow in
     162             :  *    the chain, followed in turn by AGG_SORTED or (one) AGG_PLAIN node).  If
     163             :  *    the real node is marked AGG_HASHED or AGG_SORTED, then all the chained
     164             :  *    nodes must be of the same type; if it is AGG_PLAIN, there can be no
     165             :  *    chained nodes.
     166             :  *
     167             :  *    We collect all hashed nodes into a single "phase", numbered 0, and create
     168             :  *    a sorted phase (numbered 1..n) for each AGG_SORTED or AGG_PLAIN node.
     169             :  *    Phase 0 is allocated even if there are no hashes, but remains unused in
     170             :  *    that case.
     171             :  *
     172             :  *    AGG_HASHED nodes actually refer to only a single grouping set each,
     173             :  *    because for each hashed grouping we need a separate grpColIdx and
     174             :  *    numGroups estimate.  AGG_SORTED nodes represent a "rollup", a list of
     175             :  *    grouping sets that share a sort order.  Each AGG_SORTED node other than
     176             :  *    the first one has an associated Sort node which describes the sort order
     177             :  *    to be used; the first sorted node takes its input from the outer subtree,
     178             :  *    which the planner has already arranged to provide ordered data.
     179             :  *
     180             :  *    Memory and ExprContext usage:
     181             :  *
     182             :  *    Because we're accumulating aggregate values across input rows, we need to
     183             :  *    use more memory contexts than just simple input/output tuple contexts.
     184             :  *    In fact, for a rollup, we need a separate context for each grouping set
     185             :  *    so that we can reset the inner (finer-grained) aggregates on their group
     186             :  *    boundaries while continuing to accumulate values for outer
     187             :  *    (coarser-grained) groupings.  On top of this, we might be simultaneously
     188             :  *    populating hashtables; however, we only need one context for all the
     189             :  *    hashtables.
     190             :  *
     191             :  *    So we create an array, aggcontexts, with an ExprContext for each grouping
     192             :  *    set in the largest rollup that we're going to process, and use the
     193             :  *    per-tuple memory context of those ExprContexts to store the aggregate
     194             :  *    transition values.  hashcontext is the single context created to support
     195             :  *    all hash tables.
     196             :  *
     197             :  *    Transition / Combine function invocation:
     198             :  *
     199             :  *    For performance reasons transition functions, including combine
     200             :  *    functions, aren't invoked one-by-one from nodeAgg.c after computing
     201             :  *    arguments using the expression evaluation engine. Instead
     202             :  *    ExecBuildAggTrans() builds one large expression that does both argument
     203             :  *    evaluation and transition function invocation. That avoids performance
     204             :  *    issues due to repeated uses of expression evaluation, complications due
     205             :  *    to filter expressions having to be evaluated early, and allows to JIT
     206             :  *    the entire expression into one native function.
     207             :  *
     208             :  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
     209             :  * Portions Copyright (c) 1994, Regents of the University of California
     210             :  *
     211             :  * IDENTIFICATION
     212             :  *    src/backend/executor/nodeAgg.c
     213             :  *
     214             :  *-------------------------------------------------------------------------
     215             :  */
     216             : 
     217             : #include "postgres.h"
     218             : 
     219             : #include "access/htup_details.h"
     220             : #include "catalog/objectaccess.h"
     221             : #include "catalog/pg_aggregate.h"
     222             : #include "catalog/pg_proc.h"
     223             : #include "catalog/pg_type.h"
     224             : #include "executor/executor.h"
     225             : #include "executor/nodeAgg.h"
     226             : #include "miscadmin.h"
     227             : #include "nodes/makefuncs.h"
     228             : #include "nodes/nodeFuncs.h"
     229             : #include "optimizer/optimizer.h"
     230             : #include "parser/parse_agg.h"
     231             : #include "parser/parse_coerce.h"
     232             : #include "utils/acl.h"
     233             : #include "utils/builtins.h"
     234             : #include "utils/expandeddatum.h"
     235             : #include "utils/lsyscache.h"
     236             : #include "utils/memutils.h"
     237             : #include "utils/syscache.h"
     238             : #include "utils/tuplesort.h"
     239             : #include "utils/datum.h"
     240             : 
     241             : 
     242             : static void select_current_set(AggState *aggstate, int setno, bool is_hash);
     243             : static void initialize_phase(AggState *aggstate, int newphase);
     244             : static TupleTableSlot *fetch_input_tuple(AggState *aggstate);
     245             : static void initialize_aggregates(AggState *aggstate,
     246             :                                   AggStatePerGroup *pergroups,
     247             :                                   int numReset);
     248             : static void advance_transition_function(AggState *aggstate,
     249             :                                         AggStatePerTrans pertrans,
     250             :                                         AggStatePerGroup pergroupstate);
     251             : static void advance_aggregates(AggState *aggstate);
     252             : static void process_ordered_aggregate_single(AggState *aggstate,
     253             :                                              AggStatePerTrans pertrans,
     254             :                                              AggStatePerGroup pergroupstate);
     255             : static void process_ordered_aggregate_multi(AggState *aggstate,
     256             :                                             AggStatePerTrans pertrans,
     257             :                                             AggStatePerGroup pergroupstate);
     258             : static void finalize_aggregate(AggState *aggstate,
     259             :                                AggStatePerAgg peragg,
     260             :                                AggStatePerGroup pergroupstate,
     261             :                                Datum *resultVal, bool *resultIsNull);
     262             : static void finalize_partialaggregate(AggState *aggstate,
     263             :                                       AggStatePerAgg peragg,
     264             :                                       AggStatePerGroup pergroupstate,
     265             :                                       Datum *resultVal, bool *resultIsNull);
     266             : static void prepare_projection_slot(AggState *aggstate,
     267             :                                     TupleTableSlot *slot,
     268             :                                     int currentSet);
     269             : static void finalize_aggregates(AggState *aggstate,
     270             :                                 AggStatePerAgg peragg,
     271             :                                 AggStatePerGroup pergroup);
     272             : static TupleTableSlot *project_aggregates(AggState *aggstate);
     273             : static Bitmapset *find_unaggregated_cols(AggState *aggstate);
     274             : static bool find_unaggregated_cols_walker(Node *node, Bitmapset **colnos);
     275             : static void build_hash_table(AggState *aggstate);
     276             : static TupleHashEntryData *lookup_hash_entry(AggState *aggstate);
     277             : static void lookup_hash_entries(AggState *aggstate);
     278             : static TupleTableSlot *agg_retrieve_direct(AggState *aggstate);
     279             : static void agg_fill_hash_table(AggState *aggstate);
     280             : static TupleTableSlot *agg_retrieve_hash_table(AggState *aggstate);
     281             : static Datum GetAggInitVal(Datum textInitVal, Oid transtype);
     282             : static void build_pertrans_for_aggref(AggStatePerTrans pertrans,
     283             :                                       AggState *aggstate, EState *estate,
     284             :                                       Aggref *aggref, Oid aggtransfn, Oid aggtranstype,
     285             :                                       Oid aggserialfn, Oid aggdeserialfn,
     286             :                                       Datum initValue, bool initValueIsNull,
     287             :                                       Oid *inputTypes, int numArguments);
     288             : static int  find_compatible_peragg(Aggref *newagg, AggState *aggstate,
     289             :                                    int lastaggno, List **same_input_transnos);
     290             : static int  find_compatible_pertrans(AggState *aggstate, Aggref *newagg,
     291             :                                      bool shareable,
     292             :                                      Oid aggtransfn, Oid aggtranstype,
     293             :                                      Oid aggserialfn, Oid aggdeserialfn,
     294             :                                      Datum initValue, bool initValueIsNull,
     295             :                                      List *transnos);
     296             : 
     297             : 
     298             : /*
     299             :  * Select the current grouping set; affects current_set and
     300             :  * curaggcontext.
     301             :  */
     302             : static void
     303     5357412 : select_current_set(AggState *aggstate, int setno, bool is_hash)
     304             : {
     305             :     /* when changing this, also adapt ExecInterpExpr() and friends */
     306     5357412 :     if (is_hash)
     307     2967162 :         aggstate->curaggcontext = aggstate->hashcontext;
     308             :     else
     309     2390250 :         aggstate->curaggcontext = aggstate->aggcontexts[setno];
     310             : 
     311     5357412 :     aggstate->current_set = setno;
     312     5357412 : }
     313             : 
     314             : /*
     315             :  * Switch to phase "newphase", which must either be 0 or 1 (to reset) or
     316             :  * current_phase + 1. Juggle the tuplesorts accordingly.
     317             :  *
     318             :  * Phase 0 is for hashing, which we currently handle last in the AGG_MIXED
     319             :  * case, so when entering phase 0, all we need to do is drop open sorts.
     320             :  */
     321             : static void
     322     1135834 : initialize_phase(AggState *aggstate, int newphase)
     323             : {
     324             :     Assert(newphase <= 1 || newphase == aggstate->current_phase + 1);
     325             : 
     326             :     /*
     327             :      * Whatever the previous state, we're now done with whatever input
     328             :      * tuplesort was in use.
     329             :      */
     330     1135834 :     if (aggstate->sort_in)
     331             :     {
     332          24 :         tuplesort_end(aggstate->sort_in);
     333          24 :         aggstate->sort_in = NULL;
     334             :     }
     335             : 
     336     1135834 :     if (newphase <= 1)
     337             :     {
     338             :         /*
     339             :          * Discard any existing output tuplesort.
     340             :          */
     341     1135722 :         if (aggstate->sort_out)
     342             :         {
     343           4 :             tuplesort_end(aggstate->sort_out);
     344           4 :             aggstate->sort_out = NULL;
     345             :         }
     346             :     }
     347             :     else
     348             :     {
     349             :         /*
     350             :          * The old output tuplesort becomes the new input one, and this is the
     351             :          * right time to actually sort it.
     352             :          */
     353         112 :         aggstate->sort_in = aggstate->sort_out;
     354         112 :         aggstate->sort_out = NULL;
     355             :         Assert(aggstate->sort_in);
     356         112 :         tuplesort_performsort(aggstate->sort_in);
     357             :     }
     358             : 
     359             :     /*
     360             :      * If this isn't the last phase, we need to sort appropriately for the
     361             :      * next phase in sequence.
     362             :      */
     363     1135834 :     if (newphase > 0 && newphase < aggstate->numphases - 1)
     364             :     {
     365         136 :         Sort       *sortnode = aggstate->phases[newphase + 1].sortnode;
     366         136 :         PlanState  *outerNode = outerPlanState(aggstate);
     367         136 :         TupleDesc   tupDesc = ExecGetResultType(outerNode);
     368             : 
     369         136 :         aggstate->sort_out = tuplesort_begin_heap(tupDesc,
     370             :                                                   sortnode->numCols,
     371             :                                                   sortnode->sortColIdx,
     372             :                                                   sortnode->sortOperators,
     373             :                                                   sortnode->collations,
     374             :                                                   sortnode->nullsFirst,
     375             :                                                   work_mem,
     376             :                                                   NULL, false);
     377             :     }
     378             : 
     379     1135834 :     aggstate->current_phase = newphase;
     380     1135834 :     aggstate->phase = &aggstate->phases[newphase];
     381     1135834 : }
     382             : 
     383             : /*
     384             :  * Fetch a tuple from either the outer plan (for phase 1) or from the sorter
     385             :  * populated by the previous phase.  Copy it to the sorter for the next phase
     386             :  * if any.
     387             :  *
     388             :  * Callers cannot rely on memory for tuple in returned slot remaining valid
     389             :  * past any subsequently fetched tuple.
     390             :  */
     391             : static TupleTableSlot *
     392    14746706 : fetch_input_tuple(AggState *aggstate)
     393             : {
     394             :     TupleTableSlot *slot;
     395             : 
     396    14746706 :     if (aggstate->sort_in)
     397             :     {
     398             :         /* make sure we check for interrupts in either path through here */
     399      100556 :         CHECK_FOR_INTERRUPTS();
     400      100556 :         if (!tuplesort_gettupleslot(aggstate->sort_in, true, false,
     401             :                                     aggstate->sort_slot, NULL))
     402         112 :             return NULL;
     403      100444 :         slot = aggstate->sort_slot;
     404             :     }
     405             :     else
     406    14646150 :         slot = ExecProcNode(outerPlanState(aggstate));
     407             : 
     408    14746580 :     if (!TupIsNull(slot) && aggstate->sort_out)
     409      100444 :         tuplesort_puttupleslot(aggstate->sort_out, slot);
     410             : 
     411    14746580 :     return slot;
     412             : }
     413             : 
     414             : /*
     415             :  * (Re)Initialize an individual aggregate.
     416             :  *
     417             :  * This function handles only one grouping set, already set in
     418             :  * aggstate->current_set.
     419             :  *
     420             :  * When called, CurrentMemoryContext should be the per-query context.
     421             :  */
     422             : static void
     423     1328094 : initialize_aggregate(AggState *aggstate, AggStatePerTrans pertrans,
     424             :                      AggStatePerGroup pergroupstate)
     425             : {
     426             :     /*
     427             :      * Start a fresh sort operation for each DISTINCT/ORDER BY aggregate.
     428             :      */
     429     1328094 :     if (pertrans->numSortCols > 0)
     430             :     {
     431             :         /*
     432             :          * In case of rescan, maybe there could be an uncompleted sort
     433             :          * operation?  Clean it up if so.
     434             :          */
     435     1069026 :         if (pertrans->sortstates[aggstate->current_set])
     436           0 :             tuplesort_end(pertrans->sortstates[aggstate->current_set]);
     437             : 
     438             : 
     439             :         /*
     440             :          * We use a plain Datum sorter when there's a single input column;
     441             :          * otherwise sort the full tuple.  (See comments for
     442             :          * process_ordered_aggregate_single.)
     443             :          */
     444     1069026 :         if (pertrans->numInputs == 1)
     445             :         {
     446        2448 :             Form_pg_attribute attr = TupleDescAttr(pertrans->sortdesc, 0);
     447             : 
     448        4896 :             pertrans->sortstates[aggstate->current_set] =
     449        9792 :                 tuplesort_begin_datum(attr->atttypid,
     450        2448 :                                       pertrans->sortOperators[0],
     451        2448 :                                       pertrans->sortCollations[0],
     452        2448 :                                       pertrans->sortNullsFirst[0],
     453             :                                       work_mem, NULL, false);
     454             :         }
     455             :         else
     456     2133156 :             pertrans->sortstates[aggstate->current_set] =
     457     1066578 :                 tuplesort_begin_heap(pertrans->sortdesc,
     458             :                                      pertrans->numSortCols,
     459             :                                      pertrans->sortColIdx,
     460             :                                      pertrans->sortOperators,
     461             :                                      pertrans->sortCollations,
     462             :                                      pertrans->sortNullsFirst,
     463             :                                      work_mem, NULL, false);
     464             :     }
     465             : 
     466             :     /*
     467             :      * (Re)set transValue to the initial value.
     468             :      *
     469             :      * Note that when the initial value is pass-by-ref, we must copy it (into
     470             :      * the aggcontext) since we will pfree the transValue later.
     471             :      */
     472     1328094 :     if (pertrans->initValueIsNull)
     473     1184472 :         pergroupstate->transValue = pertrans->initValue;
     474             :     else
     475             :     {
     476             :         MemoryContext oldContext;
     477             : 
     478      143622 :         oldContext = MemoryContextSwitchTo(
     479      143622 :                                            aggstate->curaggcontext->ecxt_per_tuple_memory);
     480      287244 :         pergroupstate->transValue = datumCopy(pertrans->initValue,
     481      143622 :                                               pertrans->transtypeByVal,
     482      143622 :                                               pertrans->transtypeLen);
     483      143622 :         MemoryContextSwitchTo(oldContext);
     484             :     }
     485     1328094 :     pergroupstate->transValueIsNull = pertrans->initValueIsNull;
     486             : 
     487             :     /*
     488             :      * If the initial value for the transition state doesn't exist in the
     489             :      * pg_aggregate table then we will let the first non-NULL value returned
     490             :      * from the outer procNode become the initial value. (This is useful for
     491             :      * aggregates like max() and min().) The noTransValue flag signals that we
     492             :      * still need to do this.
     493             :      */
     494     1328094 :     pergroupstate->noTransValue = pertrans->initValueIsNull;
     495     1328094 : }
     496             : 
     497             : /*
     498             :  * Initialize all aggregate transition states for a new group of input values.
     499             :  *
     500             :  * If there are multiple grouping sets, we initialize only the first numReset
     501             :  * of them (the grouping sets are ordered so that the most specific one, which
     502             :  * is reset most often, is first). As a convenience, if numReset is 0, we
     503             :  * reinitialize all sets.
     504             :  *
     505             :  * NB: This cannot be used for hash aggregates, as for those the grouping set
     506             :  * number has to be specified from further up.
     507             :  *
     508             :  * When called, CurrentMemoryContext should be the per-query context.
     509             :  */
     510             : static void
     511     1181346 : initialize_aggregates(AggState *aggstate,
     512             :                       AggStatePerGroup *pergroups,
     513             :                       int numReset)
     514             : {
     515             :     int         transno;
     516     1181346 :     int         numGroupingSets = Max(aggstate->phase->numsets, 1);
     517     1181346 :     int         setno = 0;
     518     1181346 :     int         numTrans = aggstate->numtrans;
     519     1181346 :     AggStatePerTrans transstates = aggstate->pertrans;
     520             : 
     521     1181346 :     if (numReset == 0)
     522           0 :         numReset = numGroupingSets;
     523             : 
     524     2363472 :     for (setno = 0; setno < numReset; setno++)
     525             :     {
     526     1182126 :         AggStatePerGroup pergroup = pergroups[setno];
     527             : 
     528     1182126 :         select_current_set(aggstate, setno, false);
     529             : 
     530     2368856 :         for (transno = 0; transno < numTrans; transno++)
     531             :         {
     532     1186730 :             AggStatePerTrans pertrans = &transstates[transno];
     533     1186730 :             AggStatePerGroup pergroupstate = &pergroup[transno];
     534             : 
     535     1186730 :             initialize_aggregate(aggstate, pertrans, pergroupstate);
     536             :         }
     537             :     }
     538     1181346 : }
     539             : 
     540             : /*
     541             :  * Given new input value(s), advance the transition function of one aggregate
     542             :  * state within one grouping set only (already set in aggstate->current_set)
     543             :  *
     544             :  * The new values (and null flags) have been preloaded into argument positions
     545             :  * 1 and up in pertrans->transfn_fcinfo, so that we needn't copy them again to
     546             :  * pass to the transition function.  We also expect that the static fields of
     547             :  * the fcinfo are already initialized; that was done by ExecInitAgg().
     548             :  *
     549             :  * It doesn't matter which memory context this is called in.
     550             :  */
     551             : static void
     552       22692 : advance_transition_function(AggState *aggstate,
     553             :                             AggStatePerTrans pertrans,
     554             :                             AggStatePerGroup pergroupstate)
     555             : {
     556       22692 :     FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
     557             :     MemoryContext oldContext;
     558             :     Datum       newVal;
     559             : 
     560       22692 :     if (pertrans->transfn.fn_strict)
     561             :     {
     562             :         /*
     563             :          * For a strict transfn, nothing happens when there's a NULL input; we
     564             :          * just keep the prior transValue.
     565             :          */
     566        6098 :         int         numTransInputs = pertrans->numTransInputs;
     567             :         int         i;
     568             : 
     569       12244 :         for (i = 1; i <= numTransInputs; i++)
     570             :         {
     571        6146 :             if (fcinfo->args[i].isnull)
     572           0 :                 return;
     573             :         }
     574        6098 :         if (pergroupstate->noTransValue)
     575             :         {
     576             :             /*
     577             :              * transValue has not been initialized. This is the first non-NULL
     578             :              * input value. We use it as the initial value for transValue. (We
     579             :              * already checked that the agg's input type is binary-compatible
     580             :              * with its transtype, so straight copy here is OK.)
     581             :              *
     582             :              * We must copy the datum into aggcontext if it is pass-by-ref. We
     583             :              * do not need to pfree the old transValue, since it's NULL.
     584             :              */
     585           8 :             oldContext = MemoryContextSwitchTo(
     586           8 :                                                aggstate->curaggcontext->ecxt_per_tuple_memory);
     587          16 :             pergroupstate->transValue = datumCopy(fcinfo->args[1].value,
     588           8 :                                                   pertrans->transtypeByVal,
     589           8 :                                                   pertrans->transtypeLen);
     590           8 :             pergroupstate->transValueIsNull = false;
     591           8 :             pergroupstate->noTransValue = false;
     592           8 :             MemoryContextSwitchTo(oldContext);
     593           8 :             return;
     594             :         }
     595        6090 :         if (pergroupstate->transValueIsNull)
     596             :         {
     597             :             /*
     598             :              * Don't call a strict function with NULL inputs.  Note it is
     599             :              * possible to get here despite the above tests, if the transfn is
     600             :              * strict *and* returned a NULL on a prior cycle. If that happens
     601             :              * we will propagate the NULL all the way to the end.
     602             :              */
     603           0 :             return;
     604             :         }
     605             :     }
     606             : 
     607             :     /* We run the transition functions in per-input-tuple memory context */
     608       22684 :     oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
     609             : 
     610             :     /* set up aggstate->curpertrans for AggGetAggref() */
     611       22684 :     aggstate->curpertrans = pertrans;
     612             : 
     613             :     /*
     614             :      * OK to call the transition function
     615             :      */
     616       22684 :     fcinfo->args[0].value = pergroupstate->transValue;
     617       22684 :     fcinfo->args[0].isnull = pergroupstate->transValueIsNull;
     618       22684 :     fcinfo->isnull = false;      /* just in case transfn doesn't set it */
     619             : 
     620       22684 :     newVal = FunctionCallInvoke(fcinfo);
     621             : 
     622       22684 :     aggstate->curpertrans = NULL;
     623             : 
     624             :     /*
     625             :      * If pass-by-ref datatype, must copy the new value into aggcontext and
     626             :      * free the prior transValue.  But if transfn returned a pointer to its
     627             :      * first input, we don't need to do anything.  Also, if transfn returned a
     628             :      * pointer to a R/W expanded object that is already a child of the
     629             :      * aggcontext, assume we can adopt that value without copying it.
     630             :      */
     631       22924 :     if (!pertrans->transtypeByVal &&
     632         240 :         DatumGetPointer(newVal) != DatumGetPointer(pergroupstate->transValue))
     633             :     {
     634         240 :         if (!fcinfo->isnull)
     635             :         {
     636         240 :             MemoryContextSwitchTo(aggstate->curaggcontext->ecxt_per_tuple_memory);
     637         256 :             if (DatumIsReadWriteExpandedObject(newVal,
     638             :                                                false,
     639         256 :                                                pertrans->transtypeLen) &&
     640          16 :                 MemoryContextGetParent(DatumGetEOHP(newVal)->eoh_context) == CurrentMemoryContext)
     641             :                  /* do nothing */ ;
     642             :             else
     643         480 :                 newVal = datumCopy(newVal,
     644         240 :                                    pertrans->transtypeByVal,
     645         240 :                                    pertrans->transtypeLen);
     646             :         }
     647         240 :         if (!pergroupstate->transValueIsNull)
     648             :         {
     649         232 :             if (DatumIsReadWriteExpandedObject(pergroupstate->transValue,
     650             :                                                false,
     651             :                                                pertrans->transtypeLen))
     652           0 :                 DeleteExpandedObject(pergroupstate->transValue);
     653             :             else
     654         232 :                 pfree(DatumGetPointer(pergroupstate->transValue));
     655             :         }
     656             :     }
     657             : 
     658       22684 :     pergroupstate->transValue = newVal;
     659       22684 :     pergroupstate->transValueIsNull = fcinfo->isnull;
     660             : 
     661       22684 :     MemoryContextSwitchTo(oldContext);
     662             : }
     663             : 
     664             : /*
     665             :  * Advance each aggregate transition state for one input tuple.  The input
     666             :  * tuple has been stored in tmpcontext->ecxt_outertuple, so that it is
     667             :  * accessible to ExecEvalExpr.
     668             :  *
     669             :  * We have two sets of transition states to handle: one for sorted aggregation
     670             :  * and one for hashed; we do them both here, to avoid multiple evaluation of
     671             :  * the inputs.
     672             :  *
     673             :  * When called, CurrentMemoryContext should be the per-query context.
     674             :  */
     675             : static void
     676    13588608 : advance_aggregates(AggState *aggstate)
     677             : {
     678             :     bool        dummynull;
     679             : 
     680    13588608 :     ExecEvalExprSwitchContext(aggstate->phase->evaltrans,
     681             :                               aggstate->tmpcontext,
     682             :                               &dummynull);
     683    13588580 : }
     684             : 
     685             : /*
     686             :  * Run the transition function for a DISTINCT or ORDER BY aggregate
     687             :  * with only one input.  This is called after we have completed
     688             :  * entering all the input values into the sort object.  We complete the
     689             :  * sort, read out the values in sorted order, and run the transition
     690             :  * function on each value (applying DISTINCT if appropriate).
     691             :  *
     692             :  * Note that the strictness of the transition function was checked when
     693             :  * entering the values into the sort, so we don't check it again here;
     694             :  * we just apply standard SQL DISTINCT logic.
     695             :  *
     696             :  * The one-input case is handled separately from the multi-input case
     697             :  * for performance reasons: for single by-value inputs, such as the
     698             :  * common case of count(distinct id), the tuplesort_getdatum code path
     699             :  * is around 300% faster.  (The speedup for by-reference types is less
     700             :  * but still noticeable.)
     701             :  *
     702             :  * This function handles only one grouping set (already set in
     703             :  * aggstate->current_set).
     704             :  *
     705             :  * When called, CurrentMemoryContext should be the per-query context.
     706             :  */
     707             : static void
     708        2448 : process_ordered_aggregate_single(AggState *aggstate,
     709             :                                  AggStatePerTrans pertrans,
     710             :                                  AggStatePerGroup pergroupstate)
     711             : {
     712        2448 :     Datum       oldVal = (Datum) 0;
     713        2448 :     bool        oldIsNull = true;
     714        2448 :     bool        haveOldVal = false;
     715        2448 :     MemoryContext workcontext = aggstate->tmpcontext->ecxt_per_tuple_memory;
     716             :     MemoryContext oldContext;
     717        2448 :     bool        isDistinct = (pertrans->numDistinctCols > 0);
     718        2448 :     Datum       newAbbrevVal = (Datum) 0;
     719        2448 :     Datum       oldAbbrevVal = (Datum) 0;
     720        2448 :     FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
     721             :     Datum      *newVal;
     722             :     bool       *isNull;
     723             : 
     724             :     Assert(pertrans->numDistinctCols < 2);
     725             : 
     726        2448 :     tuplesort_performsort(pertrans->sortstates[aggstate->current_set]);
     727             : 
     728             :     /* Load the column into argument 1 (arg 0 will be transition value) */
     729        2448 :     newVal = &fcinfo->args[1].value;
     730        2448 :     isNull = &fcinfo->args[1].isnull;
     731             : 
     732             :     /*
     733             :      * Note: if input type is pass-by-ref, the datums returned by the sort are
     734             :      * freshly palloc'd in the per-query context, so we must be careful to
     735             :      * pfree them when they are no longer needed.
     736             :      */
     737             : 
     738      161370 :     while (tuplesort_getdatum(pertrans->sortstates[aggstate->current_set],
     739             :                               true, newVal, isNull, &newAbbrevVal))
     740             :     {
     741             :         /*
     742             :          * Clear and select the working context for evaluation of the equality
     743             :          * function and transition function.
     744             :          */
     745      156474 :         MemoryContextReset(workcontext);
     746      156474 :         oldContext = MemoryContextSwitchTo(workcontext);
     747             : 
     748             :         /*
     749             :          * If DISTINCT mode, and not distinct from prior, skip it.
     750             :          */
     751      156474 :         if (isDistinct &&
     752      155504 :             haveOldVal &&
     753      155508 :             ((oldIsNull && *isNull) ||
     754      466486 :              (!oldIsNull && !*isNull &&
     755      310960 :               oldAbbrevVal == newAbbrevVal &&
     756      155478 :               DatumGetBool(FunctionCall2Coll(&pertrans->equalfnOne,
     757             :                                              pertrans->aggCollation,
     758             :                                              oldVal, *newVal)))))
     759             :         {
     760             :             /* equal to prior, so forget this one */
     761      298152 :             if (!pertrans->inputtypeByVal && !*isNull)
     762      124600 :                 pfree(DatumGetPointer(*newVal));
     763             :         }
     764             :         else
     765             :         {
     766        7398 :             advance_transition_function(aggstate, pertrans, pergroupstate);
     767             :             /* forget the old value, if any */
     768        7398 :             if (!oldIsNull && !pertrans->inputtypeByVal)
     769        6132 :                 pfree(DatumGetPointer(oldVal));
     770             :             /* and remember the new one for subsequent equality checks */
     771        7398 :             oldVal = *newVal;
     772        7398 :             oldAbbrevVal = newAbbrevVal;
     773        7398 :             oldIsNull = *isNull;
     774        7398 :             haveOldVal = true;
     775             :         }
     776             : 
     777      156474 :         MemoryContextSwitchTo(oldContext);
     778             :     }
     779             : 
     780        2448 :     if (!oldIsNull && !pertrans->inputtypeByVal)
     781         166 :         pfree(DatumGetPointer(oldVal));
     782             : 
     783        2448 :     tuplesort_end(pertrans->sortstates[aggstate->current_set]);
     784        2448 :     pertrans->sortstates[aggstate->current_set] = NULL;
     785        2448 : }
     786             : 
     787             : /*
     788             :  * Run the transition function for a DISTINCT or ORDER BY aggregate
     789             :  * with more than one input.  This is called after we have completed
     790             :  * entering all the input values into the sort object.  We complete the
     791             :  * sort, read out the values in sorted order, and run the transition
     792             :  * function on each value (applying DISTINCT if appropriate).
     793             :  *
     794             :  * This function handles only one grouping set (already set in
     795             :  * aggstate->current_set).
     796             :  *
     797             :  * When called, CurrentMemoryContext should be the per-query context.
     798             :  */
     799             : static void
     800     1066578 : process_ordered_aggregate_multi(AggState *aggstate,
     801             :                                 AggStatePerTrans pertrans,
     802             :                                 AggStatePerGroup pergroupstate)
     803             : {
     804     1066578 :     ExprContext *tmpcontext = aggstate->tmpcontext;
     805     1066578 :     FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
     806     1066578 :     TupleTableSlot *slot1 = pertrans->sortslot;
     807     1066578 :     TupleTableSlot *slot2 = pertrans->uniqslot;
     808     1066578 :     int         numTransInputs = pertrans->numTransInputs;
     809     1066578 :     int         numDistinctCols = pertrans->numDistinctCols;
     810     1066578 :     Datum       newAbbrevVal = (Datum) 0;
     811     1066578 :     Datum       oldAbbrevVal = (Datum) 0;
     812     1066578 :     bool        haveOldValue = false;
     813     1066578 :     TupleTableSlot *save = aggstate->tmpcontext->ecxt_outertuple;
     814             :     int         i;
     815             : 
     816     1066578 :     tuplesort_performsort(pertrans->sortstates[aggstate->current_set]);
     817             : 
     818     1066578 :     ExecClearTuple(slot1);
     819     1066578 :     if (slot2)
     820          56 :         ExecClearTuple(slot2);
     821             : 
     822     2148722 :     while (tuplesort_gettupleslot(pertrans->sortstates[aggstate->current_set],
     823             :                                   true, true, slot1, &newAbbrevVal))
     824             :     {
     825       15566 :         CHECK_FOR_INTERRUPTS();
     826             : 
     827       15566 :         tmpcontext->ecxt_outertuple = slot1;
     828       15566 :         tmpcontext->ecxt_innertuple = slot2;
     829             : 
     830       16038 :         if (numDistinctCols == 0 ||
     831         888 :             !haveOldValue ||
     832         808 :             newAbbrevVal != oldAbbrevVal ||
     833         392 :             !ExecQual(pertrans->equalfnMulti, tmpcontext))
     834             :         {
     835             :             /*
     836             :              * Extract the first numTransInputs columns as datums to pass to
     837             :              * the transfn.
     838             :              */
     839       15294 :             slot_getsomeattrs(slot1, numTransInputs);
     840             : 
     841             :             /* Load values into fcinfo */
     842             :             /* Start from 1, since the 0th arg will be the transition value */
     843       31768 :             for (i = 0; i < numTransInputs; i++)
     844             :             {
     845       16474 :                 fcinfo->args[i + 1].value = slot1->tts_values[i];
     846       16474 :                 fcinfo->args[i + 1].isnull = slot1->tts_isnull[i];
     847             :             }
     848             : 
     849       15294 :             advance_transition_function(aggstate, pertrans, pergroupstate);
     850             : 
     851       15294 :             if (numDistinctCols > 0)
     852             :             {
     853             :                 /* swap the slot pointers to retain the current tuple */
     854         200 :                 TupleTableSlot *tmpslot = slot2;
     855             : 
     856         200 :                 slot2 = slot1;
     857         200 :                 slot1 = tmpslot;
     858             :                 /* avoid ExecQual() calls by reusing abbreviated keys */
     859         200 :                 oldAbbrevVal = newAbbrevVal;
     860         200 :                 haveOldValue = true;
     861             :             }
     862             :         }
     863             : 
     864             :         /* Reset context each time */
     865       15566 :         ResetExprContext(tmpcontext);
     866             : 
     867       15566 :         ExecClearTuple(slot1);
     868             :     }
     869             : 
     870     1066578 :     if (slot2)
     871          56 :         ExecClearTuple(slot2);
     872             : 
     873     1066578 :     tuplesort_end(pertrans->sortstates[aggstate->current_set]);
     874     1066578 :     pertrans->sortstates[aggstate->current_set] = NULL;
     875             : 
     876             :     /* restore previous slot, potentially in use for grouping sets */
     877     1066578 :     tmpcontext->ecxt_outertuple = save;
     878     1066578 : }
     879             : 
     880             : /*
     881             :  * Compute the final value of one aggregate.
     882             :  *
     883             :  * This function handles only one grouping set (already set in
     884             :  * aggstate->current_set).
     885             :  *
     886             :  * The finalfn will be run, and the result delivered, in the
     887             :  * output-tuple context; caller's CurrentMemoryContext does not matter.
     888             :  *
     889             :  * The finalfn uses the state as set in the transno. This also might be
     890             :  * being used by another aggregate function, so it's important that we do
     891             :  * nothing destructive here.
     892             :  */
     893             : static void
     894     1322324 : finalize_aggregate(AggState *aggstate,
     895             :                    AggStatePerAgg peragg,
     896             :                    AggStatePerGroup pergroupstate,
     897             :                    Datum *resultVal, bool *resultIsNull)
     898             : {
     899     1322324 :     LOCAL_FCINFO(fcinfo, FUNC_MAX_ARGS);
     900     1322324 :     bool        anynull = false;
     901             :     MemoryContext oldContext;
     902             :     int         i;
     903             :     ListCell   *lc;
     904     1322324 :     AggStatePerTrans pertrans = &aggstate->pertrans[peragg->transno];
     905             : 
     906     1322324 :     oldContext = MemoryContextSwitchTo(aggstate->ss.ps.ps_ExprContext->ecxt_per_tuple_memory);
     907             : 
     908             :     /*
     909             :      * Evaluate any direct arguments.  We do this even if there's no finalfn
     910             :      * (which is unlikely anyway), so that side-effects happen as expected.
     911             :      * The direct arguments go into arg positions 1 and up, leaving position 0
     912             :      * for the transition state value.
     913             :      */
     914     1322324 :     i = 1;
     915     1322932 :     foreach(lc, peragg->aggdirectargs)
     916             :     {
     917         608 :         ExprState  *expr = (ExprState *) lfirst(lc);
     918             : 
     919         608 :         fcinfo->args[i].value = ExecEvalExpr(expr,
     920             :                                              aggstate->ss.ps.ps_ExprContext,
     921             :                                              &fcinfo->args[i].isnull);
     922         608 :         anynull |= fcinfo->args[i].isnull;
     923         608 :         i++;
     924             :     }
     925             : 
     926             :     /*
     927             :      * Apply the agg's finalfn if one is provided, else return transValue.
     928             :      */
     929     1322324 :     if (OidIsValid(peragg->finalfn_oid))
     930             :     {
     931     1117534 :         int         numFinalArgs = peragg->numFinalArgs;
     932             : 
     933             :         /* set up aggstate->curperagg for AggGetAggref() */
     934     1117534 :         aggstate->curperagg = peragg;
     935             : 
     936     1117534 :         InitFunctionCallInfoData(*fcinfo, &peragg->finalfn,
     937             :                                  numFinalArgs,
     938             :                                  pertrans->aggCollation,
     939             :                                  (void *) aggstate, NULL);
     940             : 
     941             :         /* Fill in the transition state value */
     942     1117534 :         fcinfo->args[0].value =
     943     1117534 :             MakeExpandedObjectReadOnly(pergroupstate->transValue,
     944             :                                        pergroupstate->transValueIsNull,
     945             :                                        pertrans->transtypeLen);
     946     1117534 :         fcinfo->args[0].isnull = pergroupstate->transValueIsNull;
     947     1117534 :         anynull |= pergroupstate->transValueIsNull;
     948             : 
     949             :         /* Fill any remaining argument positions with nulls */
     950     2225800 :         for (; i < numFinalArgs; i++)
     951             :         {
     952     1108266 :             fcinfo->args[i].value = (Datum) 0;
     953     1108266 :             fcinfo->args[i].isnull = true;
     954     1108266 :             anynull = true;
     955             :         }
     956             : 
     957     1117534 :         if (fcinfo->flinfo->fn_strict && anynull)
     958             :         {
     959             :             /* don't call a strict function with NULL inputs */
     960           0 :             *resultVal = (Datum) 0;
     961           0 :             *resultIsNull = true;
     962             :         }
     963             :         else
     964             :         {
     965     1117534 :             *resultVal = FunctionCallInvoke(fcinfo);
     966     1117534 :             *resultIsNull = fcinfo->isnull;
     967             :         }
     968     1117534 :         aggstate->curperagg = NULL;
     969             :     }
     970             :     else
     971             :     {
     972             :         /* Don't need MakeExpandedObjectReadOnly; datumCopy will copy it */
     973      204790 :         *resultVal = pergroupstate->transValue;
     974      204790 :         *resultIsNull = pergroupstate->transValueIsNull;
     975             :     }
     976             : 
     977             :     /*
     978             :      * If result is pass-by-ref, make sure it is in the right context.
     979             :      */
     980     1385718 :     if (!peragg->resulttypeByVal && !*resultIsNull &&
     981       63394 :         !MemoryContextContains(CurrentMemoryContext,
     982       63394 :                                DatumGetPointer(*resultVal)))
     983         828 :         *resultVal = datumCopy(*resultVal,
     984         414 :                                peragg->resulttypeByVal,
     985         414 :                                peragg->resulttypeLen);
     986             : 
     987     1322324 :     MemoryContextSwitchTo(oldContext);
     988     1322324 : }
     989             : 
     990             : /*
     991             :  * Compute the output value of one partial aggregate.
     992             :  *
     993             :  * The serialization function will be run, and the result delivered, in the
     994             :  * output-tuple context; caller's CurrentMemoryContext does not matter.
     995             :  */
     996             : static void
     997        7982 : finalize_partialaggregate(AggState *aggstate,
     998             :                           AggStatePerAgg peragg,
     999             :                           AggStatePerGroup pergroupstate,
    1000             :                           Datum *resultVal, bool *resultIsNull)
    1001             : {
    1002        7982 :     AggStatePerTrans pertrans = &aggstate->pertrans[peragg->transno];
    1003             :     MemoryContext oldContext;
    1004             : 
    1005        7982 :     oldContext = MemoryContextSwitchTo(aggstate->ss.ps.ps_ExprContext->ecxt_per_tuple_memory);
    1006             : 
    1007             :     /*
    1008             :      * serialfn_oid will be set if we must serialize the transvalue before
    1009             :      * returning it
    1010             :      */
    1011        7982 :     if (OidIsValid(pertrans->serialfn_oid))
    1012             :     {
    1013             :         /* Don't call a strict serialization function with NULL input. */
    1014          60 :         if (pertrans->serialfn.fn_strict && pergroupstate->transValueIsNull)
    1015             :         {
    1016          48 :             *resultVal = (Datum) 0;
    1017          48 :             *resultIsNull = true;
    1018             :         }
    1019             :         else
    1020             :         {
    1021          12 :             FunctionCallInfo fcinfo = pertrans->serialfn_fcinfo;
    1022             : 
    1023          12 :             fcinfo->args[0].value =
    1024          12 :                 MakeExpandedObjectReadOnly(pergroupstate->transValue,
    1025             :                                            pergroupstate->transValueIsNull,
    1026             :                                            pertrans->transtypeLen);
    1027          12 :             fcinfo->args[0].isnull = pergroupstate->transValueIsNull;
    1028             : 
    1029          12 :             *resultVal = FunctionCallInvoke(fcinfo);
    1030          12 :             *resultIsNull = fcinfo->isnull;
    1031             :         }
    1032             :     }
    1033             :     else
    1034             :     {
    1035             :         /* Don't need MakeExpandedObjectReadOnly; datumCopy will copy it */
    1036        7922 :         *resultVal = pergroupstate->transValue;
    1037        7922 :         *resultIsNull = pergroupstate->transValueIsNull;
    1038             :     }
    1039             : 
    1040             :     /* If result is pass-by-ref, make sure it is in the right context. */
    1041       10654 :     if (!peragg->resulttypeByVal && !*resultIsNull &&
    1042        2672 :         !MemoryContextContains(CurrentMemoryContext,
    1043        2672 :                                DatumGetPointer(*resultVal)))
    1044        5320 :         *resultVal = datumCopy(*resultVal,
    1045        2660 :                                peragg->resulttypeByVal,
    1046        2660 :                                peragg->resulttypeLen);
    1047             : 
    1048        7982 :     MemoryContextSwitchTo(oldContext);
    1049        7982 : }
    1050             : 
    1051             : /*
    1052             :  * Prepare to finalize and project based on the specified representative tuple
    1053             :  * slot and grouping set.
    1054             :  *
    1055             :  * In the specified tuple slot, force to null all attributes that should be
    1056             :  * read as null in the context of the current grouping set.  Also stash the
    1057             :  * current group bitmap where GroupingExpr can get at it.
    1058             :  *
    1059             :  * This relies on three conditions:
    1060             :  *
    1061             :  * 1) Nothing is ever going to try and extract the whole tuple from this slot,
    1062             :  * only reference it in evaluations, which will only access individual
    1063             :  * attributes.
    1064             :  *
    1065             :  * 2) No system columns are going to need to be nulled. (If a system column is
    1066             :  * referenced in a group clause, it is actually projected in the outer plan
    1067             :  * tlist.)
    1068             :  *
    1069             :  * 3) Within a given phase, we never need to recover the value of an attribute
    1070             :  * once it has been set to null.
    1071             :  *
    1072             :  * Poking into the slot this way is a bit ugly, but the consensus is that the
    1073             :  * alternative was worse.
    1074             :  */
    1075             : static void
    1076     1404292 : prepare_projection_slot(AggState *aggstate, TupleTableSlot *slot, int currentSet)
    1077             : {
    1078     1404292 :     if (aggstate->phase->grouped_cols)
    1079             :     {
    1080      224602 :         Bitmapset  *grouped_cols = aggstate->phase->grouped_cols[currentSet];
    1081             : 
    1082      224602 :         aggstate->grouped_cols = grouped_cols;
    1083             : 
    1084      224602 :         if (TTS_EMPTY(slot))
    1085             :         {
    1086             :             /*
    1087             :              * Force all values to be NULL if working on an empty input tuple
    1088             :              * (i.e. an empty grouping set for which no input rows were
    1089             :              * supplied).
    1090             :              */
    1091          32 :             ExecStoreAllNullTuple(slot);
    1092             :         }
    1093      224570 :         else if (aggstate->all_grouped_cols)
    1094             :         {
    1095             :             ListCell   *lc;
    1096             : 
    1097             :             /* all_grouped_cols is arranged in desc order */
    1098      224534 :             slot_getsomeattrs(slot, linitial_int(aggstate->all_grouped_cols));
    1099             : 
    1100      713096 :             foreach(lc, aggstate->all_grouped_cols)
    1101             :             {
    1102      488562 :                 int         attnum = lfirst_int(lc);
    1103             : 
    1104      488562 :                 if (!bms_is_member(attnum, grouped_cols))
    1105        2732 :                     slot->tts_isnull[attnum - 1] = true;
    1106             :             }
    1107             :         }
    1108             :     }
    1109     1404292 : }
    1110             : 
    1111             : /*
    1112             :  * Compute the final value of all aggregates for one group.
    1113             :  *
    1114             :  * This function handles only one grouping set at a time, which the caller must
    1115             :  * have selected.  It's also the caller's responsibility to adjust the supplied
    1116             :  * pergroup parameter to point to the current set's transvalues.
    1117             :  *
    1118             :  * Results are stored in the output econtext aggvalues/aggnulls.
    1119             :  */
    1120             : static void
    1121     1404292 : finalize_aggregates(AggState *aggstate,
    1122             :                     AggStatePerAgg peraggs,
    1123             :                     AggStatePerGroup pergroup)
    1124             : {
    1125     1404292 :     ExprContext *econtext = aggstate->ss.ps.ps_ExprContext;
    1126     1404292 :     Datum      *aggvalues = econtext->ecxt_aggvalues;
    1127     1404292 :     bool       *aggnulls = econtext->ecxt_aggnulls;
    1128             :     int         aggno;
    1129             :     int         transno;
    1130             : 
    1131             :     /*
    1132             :      * If there were any DISTINCT and/or ORDER BY aggregates, sort their
    1133             :      * inputs and run the transition functions.
    1134             :      */
    1135     2734506 :     for (transno = 0; transno < aggstate->numtrans; transno++)
    1136             :     {
    1137     1330214 :         AggStatePerTrans pertrans = &aggstate->pertrans[transno];
    1138             :         AggStatePerGroup pergroupstate;
    1139             : 
    1140     1330214 :         pergroupstate = &pergroup[transno];
    1141             : 
    1142     1330214 :         if (pertrans->numSortCols > 0)
    1143             :         {
    1144             :             Assert(aggstate->aggstrategy != AGG_HASHED &&
    1145             :                    aggstate->aggstrategy != AGG_MIXED);
    1146             : 
    1147     1069026 :             if (pertrans->numInputs == 1)
    1148        2448 :                 process_ordered_aggregate_single(aggstate,
    1149             :                                                  pertrans,
    1150             :                                                  pergroupstate);
    1151             :             else
    1152     1066578 :                 process_ordered_aggregate_multi(aggstate,
    1153             :                                                 pertrans,
    1154             :                                                 pergroupstate);
    1155             :         }
    1156             :     }
    1157             : 
    1158             :     /*
    1159             :      * Run the final functions.
    1160             :      */
    1161     2734598 :     for (aggno = 0; aggno < aggstate->numaggs; aggno++)
    1162             :     {
    1163     1330306 :         AggStatePerAgg peragg = &peraggs[aggno];
    1164     1330306 :         int         transno = peragg->transno;
    1165             :         AggStatePerGroup pergroupstate;
    1166             : 
    1167     1330306 :         pergroupstate = &pergroup[transno];
    1168             : 
    1169     1330306 :         if (DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit))
    1170       15964 :             finalize_partialaggregate(aggstate, peragg, pergroupstate,
    1171        7982 :                                       &aggvalues[aggno], &aggnulls[aggno]);
    1172             :         else
    1173     2644648 :             finalize_aggregate(aggstate, peragg, pergroupstate,
    1174     1322324 :                                &aggvalues[aggno], &aggnulls[aggno]);
    1175             :     }
    1176     1404292 : }
    1177             : 
    1178             : /*
    1179             :  * Project the result of a group (whose aggs have already been calculated by
    1180             :  * finalize_aggregates). Returns the result slot, or NULL if no row is
    1181             :  * projected (suppressed by qual).
    1182             :  */
    1183             : static TupleTableSlot *
    1184     1404292 : project_aggregates(AggState *aggstate)
    1185             : {
    1186     1404292 :     ExprContext *econtext = aggstate->ss.ps.ps_ExprContext;
    1187             : 
    1188             :     /*
    1189             :      * Check the qual (HAVING clause); if the group does not match, ignore it.
    1190             :      */
    1191     1404292 :     if (ExecQual(aggstate->ss.ps.qual, econtext))
    1192             :     {
    1193             :         /*
    1194             :          * Form and return projection tuple using the aggregate results and
    1195             :          * the representative input tuple.
    1196             :          */
    1197     1399532 :         return ExecProject(aggstate->ss.ps.ps_ProjInfo);
    1198             :     }
    1199             :     else
    1200        4760 :         InstrCountFiltered1(aggstate, 1);
    1201             : 
    1202        4760 :     return NULL;
    1203             : }
    1204             : 
    1205             : /*
    1206             :  * find_unaggregated_cols
    1207             :  *    Construct a bitmapset of the column numbers of un-aggregated Vars
    1208             :  *    appearing in our targetlist and qual (HAVING clause)
    1209             :  */
    1210             : static Bitmapset *
    1211        2824 : find_unaggregated_cols(AggState *aggstate)
    1212             : {
    1213        2824 :     Agg        *node = (Agg *) aggstate->ss.ps.plan;
    1214             :     Bitmapset  *colnos;
    1215             : 
    1216        2824 :     colnos = NULL;
    1217        2824 :     (void) find_unaggregated_cols_walker((Node *) node->plan.targetlist,
    1218             :                                          &colnos);
    1219        2824 :     (void) find_unaggregated_cols_walker((Node *) node->plan.qual,
    1220             :                                          &colnos);
    1221        2824 :     return colnos;
    1222             : }
    1223             : 
    1224             : static bool
    1225       23252 : find_unaggregated_cols_walker(Node *node, Bitmapset **colnos)
    1226             : {
    1227       23252 :     if (node == NULL)
    1228        2526 :         return false;
    1229       20726 :     if (IsA(node, Var))
    1230             :     {
    1231        4326 :         Var        *var = (Var *) node;
    1232             : 
    1233             :         /* setrefs.c should have set the varno to OUTER_VAR */
    1234             :         Assert(var->varno == OUTER_VAR);
    1235             :         Assert(var->varlevelsup == 0);
    1236        4326 :         *colnos = bms_add_member(*colnos, var->varattno);
    1237        4326 :         return false;
    1238             :     }
    1239       16400 :     if (IsA(node, Aggref) ||IsA(node, GroupingFunc))
    1240             :     {
    1241             :         /* do not descend into aggregate exprs */
    1242        3928 :         return false;
    1243             :     }
    1244       12472 :     return expression_tree_walker(node, find_unaggregated_cols_walker,
    1245             :                                   (void *) colnos);
    1246             : }
    1247             : 
    1248             : /*
    1249             :  * (Re-)initialize the hash table(s) to empty.
    1250             :  *
    1251             :  * To implement hashed aggregation, we need a hashtable that stores a
    1252             :  * representative tuple and an array of AggStatePerGroup structs for each
    1253             :  * distinct set of GROUP BY column values.  We compute the hash key from the
    1254             :  * GROUP BY columns.  The per-group data is allocated in lookup_hash_entry(),
    1255             :  * for each entry.
    1256             :  *
    1257             :  * We have a separate hashtable and associated perhash data structure for each
    1258             :  * grouping set for which we're doing hashing.
    1259             :  *
    1260             :  * The contents of the hash tables always live in the hashcontext's per-tuple
    1261             :  * memory context (there is only one of these for all tables together, since
    1262             :  * they are all reset at the same time).
    1263             :  */
    1264             : static void
    1265       39336 : build_hash_table(AggState *aggstate)
    1266             : {
    1267       39336 :     MemoryContext tmpmem = aggstate->tmpcontext->ecxt_per_tuple_memory;
    1268             :     Size        additionalsize;
    1269             :     int         i;
    1270             : 
    1271             :     Assert(aggstate->aggstrategy == AGG_HASHED || aggstate->aggstrategy == AGG_MIXED);
    1272             : 
    1273       39336 :     additionalsize = aggstate->numtrans * sizeof(AggStatePerGroupData);
    1274             : 
    1275       78872 :     for (i = 0; i < aggstate->num_hashes; ++i)
    1276             :     {
    1277       39536 :         AggStatePerHash perhash = &aggstate->perhash[i];
    1278             : 
    1279             :         Assert(perhash->aggnode->numGroups > 0);
    1280             : 
    1281       39536 :         if (perhash->hashtable)
    1282       36536 :             ResetTupleHashTable(perhash->hashtable);
    1283             :         else
    1284       21000 :             perhash->hashtable = BuildTupleHashTableExt(&aggstate->ss.ps,
    1285        3000 :                                                         perhash->hashslot->tts_tupleDescriptor,
    1286             :                                                         perhash->numCols,
    1287             :                                                         perhash->hashGrpColIdxHash,
    1288        3000 :                                                         perhash->eqfuncoids,
    1289             :                                                         perhash->hashfunctions,
    1290        3000 :                                                         perhash->aggnode->grpCollations,
    1291        3000 :                                                         perhash->aggnode->numGroups,
    1292             :                                                         additionalsize,
    1293        3000 :                                                         aggstate->ss.ps.state->es_query_cxt,
    1294        3000 :                                                         aggstate->hashcontext->ecxt_per_tuple_memory,
    1295             :                                                         tmpmem,
    1296        3000 :                                                         DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit));
    1297             :     }
    1298       39336 : }
    1299             : 
    1300             : /*
    1301             :  * Compute columns that actually need to be stored in hashtable entries.  The
    1302             :  * incoming tuples from the child plan node will contain grouping columns,
    1303             :  * other columns referenced in our targetlist and qual, columns used to
    1304             :  * compute the aggregate functions, and perhaps just junk columns we don't use
    1305             :  * at all.  Only columns of the first two types need to be stored in the
    1306             :  * hashtable, and getting rid of the others can make the table entries
    1307             :  * significantly smaller.  The hashtable only contains the relevant columns,
    1308             :  * and is packed/unpacked in lookup_hash_entry() / agg_retrieve_hash_table()
    1309             :  * into the format of the normal input descriptor.
    1310             :  *
    1311             :  * Additional columns, in addition to the columns grouped by, come from two
    1312             :  * sources: Firstly functionally dependent columns that we don't need to group
    1313             :  * by themselves, and secondly ctids for row-marks.
    1314             :  *
    1315             :  * To eliminate duplicates, we build a bitmapset of the needed columns, and
    1316             :  * then build an array of the columns included in the hashtable. We might
    1317             :  * still have duplicates if the passed-in grpColIdx has them, which can happen
    1318             :  * in edge cases from semijoins/distinct; these can't always be removed,
    1319             :  * because it's not certain that the duplicate cols will be using the same
    1320             :  * hash function.
    1321             :  *
    1322             :  * Note that the array is preserved over ExecReScanAgg, so we allocate it in
    1323             :  * the per-query context (unlike the hash table itself).
    1324             :  */
    1325             : static void
    1326        2824 : find_hash_columns(AggState *aggstate)
    1327             : {
    1328             :     Bitmapset  *base_colnos;
    1329        2824 :     List       *outerTlist = outerPlanState(aggstate)->plan->targetlist;
    1330        2824 :     int         numHashes = aggstate->num_hashes;
    1331        2824 :     EState     *estate = aggstate->ss.ps.state;
    1332             :     int         j;
    1333             : 
    1334             :     /* Find Vars that will be needed in tlist and qual */
    1335        2824 :     base_colnos = find_unaggregated_cols(aggstate);
    1336             : 
    1337        5824 :     for (j = 0; j < numHashes; ++j)
    1338             :     {
    1339        3000 :         AggStatePerHash perhash = &aggstate->perhash[j];
    1340        3000 :         Bitmapset  *colnos = bms_copy(base_colnos);
    1341        3000 :         AttrNumber *grpColIdx = perhash->aggnode->grpColIdx;
    1342        3000 :         List       *hashTlist = NIL;
    1343             :         TupleDesc   hashDesc;
    1344             :         int         maxCols;
    1345             :         int         i;
    1346             : 
    1347        3000 :         perhash->largestGrpColIdx = 0;
    1348             : 
    1349             :         /*
    1350             :          * If we're doing grouping sets, then some Vars might be referenced in
    1351             :          * tlist/qual for the benefit of other grouping sets, but not needed
    1352             :          * when hashing; i.e. prepare_projection_slot will null them out, so
    1353             :          * there'd be no point storing them.  Use prepare_projection_slot's
    1354             :          * logic to determine which.
    1355             :          */
    1356        3000 :         if (aggstate->phases[0].grouped_cols)
    1357             :         {
    1358        3000 :             Bitmapset  *grouped_cols = aggstate->phases[0].grouped_cols[j];
    1359             :             ListCell   *lc;
    1360             : 
    1361        7504 :             foreach(lc, aggstate->all_grouped_cols)
    1362             :             {
    1363        4504 :                 int         attnum = lfirst_int(lc);
    1364             : 
    1365        4504 :                 if (!bms_is_member(attnum, grouped_cols))
    1366         544 :                     colnos = bms_del_member(colnos, attnum);
    1367             :             }
    1368             :         }
    1369             : 
    1370             :         /*
    1371             :          * Compute maximum number of input columns accounting for possible
    1372             :          * duplications in the grpColIdx array, which can happen in some edge
    1373             :          * cases where HashAggregate was generated as part of a semijoin or a
    1374             :          * DISTINCT.
    1375             :          */
    1376        3000 :         maxCols = bms_num_members(colnos) + perhash->numCols;
    1377             : 
    1378        3000 :         perhash->hashGrpColIdxInput =
    1379        3000 :             palloc(maxCols * sizeof(AttrNumber));
    1380        3000 :         perhash->hashGrpColIdxHash =
    1381        3000 :             palloc(perhash->numCols * sizeof(AttrNumber));
    1382             : 
    1383             :         /* Add all the grouping columns to colnos */
    1384        6964 :         for (i = 0; i < perhash->numCols; i++)
    1385        3964 :             colnos = bms_add_member(colnos, grpColIdx[i]);
    1386             : 
    1387             :         /*
    1388             :          * First build mapping for columns directly hashed. These are the
    1389             :          * first, because they'll be accessed when computing hash values and
    1390             :          * comparing tuples for exact matches. We also build simple mapping
    1391             :          * for execGrouping, so it knows where to find the to-be-hashed /
    1392             :          * compared columns in the input.
    1393             :          */
    1394        6964 :         for (i = 0; i < perhash->numCols; i++)
    1395             :         {
    1396        3964 :             perhash->hashGrpColIdxInput[i] = grpColIdx[i];
    1397        3964 :             perhash->hashGrpColIdxHash[i] = i + 1;
    1398        3964 :             perhash->numhashGrpCols++;
    1399             :             /* delete already mapped columns */
    1400        3964 :             bms_del_member(colnos, grpColIdx[i]);
    1401             :         }
    1402             : 
    1403             :         /* and add the remaining columns */
    1404        6372 :         while ((i = bms_first_member(colnos)) >= 0)
    1405             :         {
    1406         372 :             perhash->hashGrpColIdxInput[perhash->numhashGrpCols] = i;
    1407         372 :             perhash->numhashGrpCols++;
    1408             :         }
    1409             : 
    1410             :         /* and build a tuple descriptor for the hashtable */
    1411        7336 :         for (i = 0; i < perhash->numhashGrpCols; i++)
    1412             :         {
    1413        4336 :             int         varNumber = perhash->hashGrpColIdxInput[i] - 1;
    1414             : 
    1415        4336 :             hashTlist = lappend(hashTlist, list_nth(outerTlist, varNumber));
    1416        4336 :             perhash->largestGrpColIdx =
    1417        4336 :                 Max(varNumber + 1, perhash->largestGrpColIdx);
    1418             :         }
    1419             : 
    1420        3000 :         hashDesc = ExecTypeFromTL(hashTlist);
    1421             : 
    1422        6000 :         execTuplesHashPrepare(perhash->numCols,
    1423        3000 :                               perhash->aggnode->grpOperators,
    1424             :                               &perhash->eqfuncoids,
    1425             :                               &perhash->hashfunctions);
    1426        3000 :         perhash->hashslot =
    1427        3000 :             ExecAllocTableSlot(&estate->es_tupleTable, hashDesc,
    1428             :                                &TTSOpsMinimalTuple);
    1429             : 
    1430        3000 :         list_free(hashTlist);
    1431        3000 :         bms_free(colnos);
    1432             :     }
    1433             : 
    1434        2824 :     bms_free(base_colnos);
    1435        2824 : }
    1436             : 
    1437             : /*
    1438             :  * Estimate per-hash-table-entry overhead for the planner.
    1439             :  *
    1440             :  * Note that the estimate does not include space for pass-by-reference
    1441             :  * transition data values, nor for the representative tuple of each group.
    1442             :  * Nor does this account of the target fill-factor and growth policy of the
    1443             :  * hash table.
    1444             :  */
    1445             : Size
    1446        4952 : hash_agg_entry_size(int numAggs)
    1447             : {
    1448             :     Size        entrysize;
    1449             : 
    1450             :     /* This must match build_hash_table */
    1451        4952 :     entrysize = sizeof(TupleHashEntryData) +
    1452        4952 :         numAggs * sizeof(AggStatePerGroupData);
    1453        4952 :     entrysize = MAXALIGN(entrysize);
    1454             : 
    1455        4952 :     return entrysize;
    1456             : }
    1457             : 
    1458             : /*
    1459             :  * Find or create a hashtable entry for the tuple group containing the current
    1460             :  * tuple (already set in tmpcontext's outertuple slot), in the current grouping
    1461             :  * set (which the caller must have selected - note that initialize_aggregate
    1462             :  * depends on this).
    1463             :  *
    1464             :  * When called, CurrentMemoryContext should be the per-query context.
    1465             :  */
    1466             : static TupleHashEntryData *
    1467     2925290 : lookup_hash_entry(AggState *aggstate)
    1468             : {
    1469     2925290 :     TupleTableSlot *inputslot = aggstate->tmpcontext->ecxt_outertuple;
    1470     2925290 :     AggStatePerHash perhash = &aggstate->perhash[aggstate->current_set];
    1471     2925290 :     TupleTableSlot *hashslot = perhash->hashslot;
    1472             :     TupleHashEntryData *entry;
    1473             :     bool        isnew;
    1474             :     int         i;
    1475             : 
    1476             :     /* transfer just the needed columns into hashslot */
    1477     2925290 :     slot_getsomeattrs(inputslot, perhash->largestGrpColIdx);
    1478     2925290 :     ExecClearTuple(hashslot);
    1479             : 
    1480     7245290 :     for (i = 0; i < perhash->numhashGrpCols; i++)
    1481             :     {
    1482     4320000 :         int         varNumber = perhash->hashGrpColIdxInput[i] - 1;
    1483             : 
    1484     4320000 :         hashslot->tts_values[i] = inputslot->tts_values[varNumber];
    1485     4320000 :         hashslot->tts_isnull[i] = inputslot->tts_isnull[varNumber];
    1486             :     }
    1487     2925290 :     ExecStoreVirtualTuple(hashslot);
    1488             : 
    1489             :     /* find or create the hashtable entry using the filtered tuple */
    1490     2925290 :     entry = LookupTupleHashEntry(perhash->hashtable, hashslot, &isnew);
    1491             : 
    1492     2925290 :     if (isnew)
    1493             :     {
    1494             :         AggStatePerGroup pergroup;
    1495             :         int         transno;
    1496             : 
    1497      221146 :         pergroup = (AggStatePerGroup)
    1498      221146 :             MemoryContextAlloc(perhash->hashtable->tablecxt,
    1499      221146 :                                sizeof(AggStatePerGroupData) * aggstate->numtrans);
    1500      221146 :         entry->additional = pergroup;
    1501             : 
    1502             :         /*
    1503             :          * Initialize aggregates for new tuple group, lookup_hash_entries()
    1504             :          * already has selected the relevant grouping set.
    1505             :          */
    1506      362510 :         for (transno = 0; transno < aggstate->numtrans; transno++)
    1507             :         {
    1508      141364 :             AggStatePerTrans pertrans = &aggstate->pertrans[transno];
    1509      141364 :             AggStatePerGroup pergroupstate = &pergroup[transno];
    1510             : 
    1511      141364 :             initialize_aggregate(aggstate, pertrans, pergroupstate);
    1512             :         }
    1513             :     }
    1514             : 
    1515     2925290 :     return entry;
    1516             : }
    1517             : 
    1518             : /*
    1519             :  * Look up hash entries for the current tuple in all hashed grouping sets,
    1520             :  * returning an array of pergroup pointers suitable for advance_aggregates.
    1521             :  *
    1522             :  * Be aware that lookup_hash_entry can reset the tmpcontext.
    1523             :  */
    1524             : static void
    1525     2884290 : lookup_hash_entries(AggState *aggstate)
    1526             : {
    1527     2884290 :     int         numHashes = aggstate->num_hashes;
    1528     2884290 :     AggStatePerGroup *pergroup = aggstate->hash_pergroup;
    1529             :     int         setno;
    1530             : 
    1531     5809580 :     for (setno = 0; setno < numHashes; setno++)
    1532             :     {
    1533     2925290 :         select_current_set(aggstate, setno, true);
    1534     2925290 :         pergroup[setno] = lookup_hash_entry(aggstate)->additional;
    1535             :     }
    1536     2884290 : }
    1537             : 
    1538             : /*
    1539             :  * ExecAgg -
    1540             :  *
    1541             :  *    ExecAgg receives tuples from its outer subplan and aggregates over
    1542             :  *    the appropriate attribute for each aggregate function use (Aggref
    1543             :  *    node) appearing in the targetlist or qual of the node.  The number
    1544             :  *    of tuples to aggregate over depends on whether grouped or plain
    1545             :  *    aggregation is selected.  In grouped aggregation, we produce a result
    1546             :  *    row for each group; in plain aggregation there's a single result row
    1547             :  *    for the whole query.  In either case, the value of each aggregate is
    1548             :  *    stored in the expression context to be used when ExecProject evaluates
    1549             :  *    the result tuple.
    1550             :  */
    1551             : static TupleTableSlot *
    1552     2555766 : ExecAgg(PlanState *pstate)
    1553             : {
    1554     2555766 :     AggState   *node = castNode(AggState, pstate);
    1555     2555766 :     TupleTableSlot *result = NULL;
    1556             : 
    1557     2555766 :     CHECK_FOR_INTERRUPTS();
    1558             : 
    1559     2555766 :     if (!node->agg_done)
    1560             :     {
    1561             :         /* Dispatch based on strategy */
    1562     1438996 :         switch (node->phase->aggstrategy)
    1563             :         {
    1564             :             case AGG_HASHED:
    1565      256724 :                 if (!node->table_filled)
    1566       38426 :                     agg_fill_hash_table(node);
    1567             :                 /* FALLTHROUGH */
    1568             :             case AGG_MIXED:
    1569      257284 :                 result = agg_retrieve_hash_table(node);
    1570      257284 :                 break;
    1571             :             case AGG_PLAIN:
    1572             :             case AGG_SORTED:
    1573     1181712 :                 result = agg_retrieve_direct(node);
    1574     1181670 :                 break;
    1575             :         }
    1576             : 
    1577     1438954 :         if (!TupIsNull(result))
    1578     1399532 :             return result;
    1579             :     }
    1580             : 
    1581     1156192 :     return NULL;
    1582             : }
    1583             : 
    1584             : /*
    1585             :  * ExecAgg for non-hashed case
    1586             :  */
    1587             : static TupleTableSlot *
    1588     1181712 : agg_retrieve_direct(AggState *aggstate)
    1589             : {
    1590     1181712 :     Agg        *node = aggstate->phase->aggnode;
    1591             :     ExprContext *econtext;
    1592             :     ExprContext *tmpcontext;
    1593             :     AggStatePerAgg peragg;
    1594             :     AggStatePerGroup *pergroups;
    1595             :     TupleTableSlot *outerslot;
    1596             :     TupleTableSlot *firstSlot;
    1597             :     TupleTableSlot *result;
    1598     1181712 :     bool        hasGroupingSets = aggstate->phase->numsets > 0;
    1599     1181712 :     int         numGroupingSets = Max(aggstate->phase->numsets, 1);
    1600             :     int         currentSet;
    1601             :     int         nextSetSize;
    1602             :     int         numReset;
    1603             :     int         i;
    1604             : 
    1605             :     /*
    1606             :      * get state info from node
    1607             :      *
    1608             :      * econtext is the per-output-tuple expression context
    1609             :      *
    1610             :      * tmpcontext is the per-input-tuple expression context
    1611             :      */
    1612     1181712 :     econtext = aggstate->ss.ps.ps_ExprContext;
    1613     1181712 :     tmpcontext = aggstate->tmpcontext;
    1614             : 
    1615     1181712 :     peragg = aggstate->peragg;
    1616     1181712 :     pergroups = aggstate->pergroups;
    1617     1181712 :     firstSlot = aggstate->ss.ss_ScanTupleSlot;
    1618             : 
    1619             :     /*
    1620             :      * We loop retrieving groups until we find one matching
    1621             :      * aggstate->ss.ps.qual
    1622             :      *
    1623             :      * For grouping sets, we have the invariant that aggstate->projected_set
    1624             :      * is either -1 (initial call) or the index (starting from 0) in
    1625             :      * gset_lengths for the group we just completed (either by projecting a
    1626             :      * row or by discarding it in the qual).
    1627             :      */
    1628     2364346 :     while (!aggstate->agg_done)
    1629             :     {
    1630             :         /*
    1631             :          * Clear the per-output-tuple context for each group, as well as
    1632             :          * aggcontext (which contains any pass-by-ref transvalues of the old
    1633             :          * group).  Some aggregate functions store working state in child
    1634             :          * contexts; those now get reset automatically without us needing to
    1635             :          * do anything special.
    1636             :          *
    1637             :          * We use ReScanExprContext not just ResetExprContext because we want
    1638             :          * any registered shutdown callbacks to be called.  That allows
    1639             :          * aggregate functions to ensure they've cleaned up any non-memory
    1640             :          * resources.
    1641             :          */
    1642     1182548 :         ReScanExprContext(econtext);
    1643             : 
    1644             :         /*
    1645             :          * Determine how many grouping sets need to be reset at this boundary.
    1646             :          */
    1647     1245508 :         if (aggstate->projected_set >= 0 &&
    1648       62960 :             aggstate->projected_set < numGroupingSets)
    1649       62956 :             numReset = aggstate->projected_set + 1;
    1650             :         else
    1651     1119592 :             numReset = numGroupingSets;
    1652             : 
    1653             :         /*
    1654             :          * numReset can change on a phase boundary, but that's OK; we want to
    1655             :          * reset the contexts used in _this_ phase, and later, after possibly
    1656             :          * changing phase, initialize the right number of aggregates for the
    1657             :          * _new_ phase.
    1658             :          */
    1659             : 
    1660     2366700 :         for (i = 0; i < numReset; i++)
    1661             :         {
    1662     1184152 :             ReScanExprContext(aggstate->aggcontexts[i]);
    1663             :         }
    1664             : 
    1665             :         /*
    1666             :          * Check if input is complete and there are no more groups to project
    1667             :          * in this phase; move to next phase or mark as done.
    1668             :          */
    1669     1183408 :         if (aggstate->input_done == true &&
    1670         860 :             aggstate->projected_set >= (numGroupingSets - 1))
    1671             :         {
    1672         424 :             if (aggstate->current_phase < aggstate->numphases - 1)
    1673             :             {
    1674         112 :                 initialize_phase(aggstate, aggstate->current_phase + 1);
    1675         112 :                 aggstate->input_done = false;
    1676         112 :                 aggstate->projected_set = -1;
    1677         112 :                 numGroupingSets = Max(aggstate->phase->numsets, 1);
    1678         112 :                 node = aggstate->phase->aggnode;
    1679         112 :                 numReset = numGroupingSets;
    1680             :             }
    1681         312 :             else if (aggstate->aggstrategy == AGG_MIXED)
    1682             :             {
    1683             :                 /*
    1684             :                  * Mixed mode; we've output all the grouped stuff and have
    1685             :                  * full hashtables, so switch to outputting those.
    1686             :                  */
    1687          56 :                 initialize_phase(aggstate, 0);
    1688          56 :                 aggstate->table_filled = true;
    1689          56 :                 ResetTupleHashIterator(aggstate->perhash[0].hashtable,
    1690             :                                        &aggstate->perhash[0].hashiter);
    1691          56 :                 select_current_set(aggstate, 0, true);
    1692          56 :                 return agg_retrieve_hash_table(aggstate);
    1693             :             }
    1694             :             else
    1695             :             {
    1696         256 :                 aggstate->agg_done = true;
    1697         256 :                 break;
    1698             :             }
    1699             :         }
    1700             : 
    1701             :         /*
    1702             :          * Get the number of columns in the next grouping set after the last
    1703             :          * projected one (if any). This is the number of columns to compare to
    1704             :          * see if we reached the boundary of that set too.
    1705             :          */
    1706     1244772 :         if (aggstate->projected_set >= 0 &&
    1707       62536 :             aggstate->projected_set < (numGroupingSets - 1))
    1708        1544 :             nextSetSize = aggstate->phase->gset_lengths[aggstate->projected_set + 1];
    1709             :         else
    1710     1180692 :             nextSetSize = 0;
    1711             : 
    1712             :         /*----------
    1713             :          * If a subgroup for the current grouping set is present, project it.
    1714             :          *
    1715             :          * We have a new group if:
    1716             :          *  - we're out of input but haven't projected all grouping sets
    1717             :          *    (checked above)
    1718             :          * OR
    1719             :          *    - we already projected a row that wasn't from the last grouping
    1720             :          *      set
    1721             :          *    AND
    1722             :          *    - the next grouping set has at least one grouping column (since
    1723             :          *      empty grouping sets project only once input is exhausted)
    1724             :          *    AND
    1725             :          *    - the previous and pending rows differ on the grouping columns
    1726             :          *      of the next grouping set
    1727             :          *----------
    1728             :          */
    1729     1182236 :         tmpcontext->ecxt_innertuple = econtext->ecxt_outertuple;
    1730     2364036 :         if (aggstate->input_done ||
    1731     1244938 :             (node->aggstrategy != AGG_PLAIN &&
    1732      125238 :              aggstate->projected_set != -1 &&
    1733       63208 :              aggstate->projected_set < (numGroupingSets - 1) &&
    1734         776 :              nextSetSize > 0 &&
    1735         776 :              !ExecQualAndReset(aggstate->phase->eqfunctions[nextSetSize - 1],
    1736             :                                tmpcontext)))
    1737             :         {
    1738         768 :             aggstate->projected_set += 1;
    1739             : 
    1740             :             Assert(aggstate->projected_set < numGroupingSets);
    1741         768 :             Assert(nextSetSize > 0 || aggstate->input_done);
    1742             :         }
    1743             :         else
    1744             :         {
    1745             :             /*
    1746             :              * We no longer care what group we just projected, the next
    1747             :              * projection will always be the first (or only) grouping set
    1748             :              * (unless the input proves to be empty).
    1749             :              */
    1750     1181468 :             aggstate->projected_set = 0;
    1751             : 
    1752             :             /*
    1753             :              * If we don't already have the first tuple of the new group,
    1754             :              * fetch it from the outer plan.
    1755             :              */
    1756     1181468 :             if (aggstate->grp_firstTuple == NULL)
    1757             :             {
    1758     1119700 :                 outerslot = fetch_input_tuple(aggstate);
    1759     1119686 :                 if (!TupIsNull(outerslot))
    1760             :                 {
    1761             :                     /*
    1762             :                      * Make a copy of the first input tuple; we will use this
    1763             :                      * for comparisons (in group mode) and for projection.
    1764             :                      */
    1765       64528 :                     aggstate->grp_firstTuple = ExecCopySlotHeapTuple(outerslot);
    1766             :                 }
    1767             :                 else
    1768             :                 {
    1769             :                     /* outer plan produced no tuples at all */
    1770     1055158 :                     if (hasGroupingSets)
    1771             :                     {
    1772             :                         /*
    1773             :                          * If there was no input at all, we need to project
    1774             :                          * rows only if there are grouping sets of size 0.
    1775             :                          * Note that this implies that there can't be any
    1776             :                          * references to ungrouped Vars, which would otherwise
    1777             :                          * cause issues with the empty output slot.
    1778             :                          *
    1779             :                          * XXX: This is no longer true, we currently deal with
    1780             :                          * this in finalize_aggregates().
    1781             :                          */
    1782          36 :                         aggstate->input_done = true;
    1783             : 
    1784          88 :                         while (aggstate->phase->gset_lengths[aggstate->projected_set] > 0)
    1785             :                         {
    1786          20 :                             aggstate->projected_set += 1;
    1787          20 :                             if (aggstate->projected_set >= numGroupingSets)
    1788             :                             {
    1789             :                                 /*
    1790             :                                  * We can't set agg_done here because we might
    1791             :                                  * have more phases to do, even though the
    1792             :                                  * input is empty. So we need to restart the
    1793             :                                  * whole outer loop.
    1794             :                                  */
    1795           4 :                                 break;
    1796             :                             }
    1797             :                         }
    1798             : 
    1799          36 :                         if (aggstate->projected_set >= numGroupingSets)
    1800           4 :                             continue;
    1801             :                     }
    1802             :                     else
    1803             :                     {
    1804     1055122 :                         aggstate->agg_done = true;
    1805             :                         /* If we are grouping, we should produce no tuples too */
    1806     1055122 :                         if (node->aggstrategy != AGG_PLAIN)
    1807         104 :                             return NULL;
    1808             :                     }
    1809             :                 }
    1810             :             }
    1811             : 
    1812             :             /*
    1813             :              * Initialize working state for a new input tuple group.
    1814             :              */
    1815     1181346 :             initialize_aggregates(aggstate, pergroups, numReset);
    1816             : 
    1817     1181346 :             if (aggstate->grp_firstTuple != NULL)
    1818             :             {
    1819             :                 /*
    1820             :                  * Store the copied first input tuple in the tuple table slot
    1821             :                  * reserved for it.  The tuple will be deleted when it is
    1822             :                  * cleared from the slot.
    1823             :                  */
    1824      126296 :                 ExecForceStoreHeapTuple(aggstate->grp_firstTuple,
    1825             :                                         firstSlot, true);
    1826      126296 :                 aggstate->grp_firstTuple = NULL; /* don't keep two pointers */
    1827             : 
    1828             :                 /* set up for first advance_aggregates call */
    1829      126296 :                 tmpcontext->ecxt_outertuple = firstSlot;
    1830             : 
    1831             :                 /*
    1832             :                  * Process each outer-plan tuple, and then fetch the next one,
    1833             :                  * until we exhaust the outer plan or cross a group boundary.
    1834             :                  */
    1835             :                 for (;;)
    1836             :                 {
    1837             :                     /*
    1838             :                      * During phase 1 only of a mixed agg, we need to update
    1839             :                      * hashtables as well in advance_aggregates.
    1840             :                      */
    1841    21334480 :                     if (aggstate->aggstrategy == AGG_MIXED &&
    1842       17380 :                         aggstate->current_phase == 1)
    1843             :                     {
    1844       17380 :                         lookup_hash_entries(aggstate);
    1845             :                     }
    1846             : 
    1847             :                     /* Advance the aggregates (or combine functions) */
    1848    10721698 :                     advance_aggregates(aggstate);
    1849             : 
    1850             :                     /* Reset per-input-tuple context after each tuple */
    1851    10721670 :                     ResetExprContext(tmpcontext);
    1852             : 
    1853    10721670 :                     outerslot = fetch_input_tuple(aggstate);
    1854    10721670 :                     if (TupIsNull(outerslot))
    1855             :                     {
    1856             :                         /* no more outer-plan tuples available */
    1857       64496 :                         if (hasGroupingSets)
    1858             :                         {
    1859         388 :                             aggstate->input_done = true;
    1860         388 :                             break;
    1861             :                         }
    1862             :                         else
    1863             :                         {
    1864       64108 :                             aggstate->agg_done = true;
    1865       64108 :                             break;
    1866             :                         }
    1867             :                     }
    1868             :                     /* set up for next advance_aggregates call */
    1869    10657174 :                     tmpcontext->ecxt_outertuple = outerslot;
    1870             : 
    1871             :                     /*
    1872             :                      * If we are grouping, check whether we've crossed a group
    1873             :                      * boundary.
    1874             :                      */
    1875    10657174 :                     if (node->aggstrategy != AGG_PLAIN)
    1876             :                     {
    1877     1007734 :                         tmpcontext->ecxt_innertuple = firstSlot;
    1878     1007734 :                         if (!ExecQual(aggstate->phase->eqfunctions[node->numCols - 1],
    1879             :                                       tmpcontext))
    1880             :                         {
    1881       61772 :                             aggstate->grp_firstTuple = ExecCopySlotHeapTuple(outerslot);
    1882       61772 :                             break;
    1883             :                         }
    1884             :                     }
    1885             :                 }
    1886             :             }
    1887             : 
    1888             :             /*
    1889             :              * Use the representative input tuple for any references to
    1890             :              * non-aggregated input columns in aggregate direct args, the node
    1891             :              * qual, and the tlist.  (If we are not grouping, and there are no
    1892             :              * input rows at all, we will come here with an empty firstSlot
    1893             :              * ... but if not grouping, there can't be any references to
    1894             :              * non-aggregated input columns, so no problem.)
    1895             :              */
    1896     1181318 :             econtext->ecxt_outertuple = firstSlot;
    1897             :         }
    1898             : 
    1899             :         Assert(aggstate->projected_set >= 0);
    1900             : 
    1901     1182086 :         currentSet = aggstate->projected_set;
    1902             : 
    1903     1182086 :         prepare_projection_slot(aggstate, econtext->ecxt_outertuple, currentSet);
    1904             : 
    1905     1182086 :         select_current_set(aggstate, currentSet, false);
    1906             : 
    1907     1182086 :         finalize_aggregates(aggstate,
    1908             :                             peragg,
    1909     1182086 :                             pergroups[currentSet]);
    1910             : 
    1911             :         /*
    1912             :          * If there's no row to project right now, we must continue rather
    1913             :          * than returning a null since there might be more groups.
    1914             :          */
    1915     1182086 :         result = project_aggregates(aggstate);
    1916     1182086 :         if (result)
    1917     1181168 :             return result;
    1918             :     }
    1919             : 
    1920             :     /* No more groups */
    1921         342 :     return NULL;
    1922             : }
    1923             : 
    1924             : /*
    1925             :  * ExecAgg for hashed case: read input and build hash table
    1926             :  */
    1927             : static void
    1928       38426 : agg_fill_hash_table(AggState *aggstate)
    1929             : {
    1930             :     TupleTableSlot *outerslot;
    1931       38426 :     ExprContext *tmpcontext = aggstate->tmpcontext;
    1932             : 
    1933             :     /*
    1934             :      * Process each outer-plan tuple, and then fetch the next one, until we
    1935             :      * exhaust the outer plan.
    1936             :      */
    1937             :     for (;;)
    1938             :     {
    1939     5772246 :         outerslot = fetch_input_tuple(aggstate);
    1940     2905336 :         if (TupIsNull(outerslot))
    1941             :             break;
    1942             : 
    1943             :         /* set up for lookup_hash_entries and advance_aggregates */
    1944     2866910 :         tmpcontext->ecxt_outertuple = outerslot;
    1945             : 
    1946             :         /* Find or build hashtable entries */
    1947     2866910 :         lookup_hash_entries(aggstate);
    1948             : 
    1949             :         /* Advance the aggregates (or combine functions) */
    1950     2866910 :         advance_aggregates(aggstate);
    1951             : 
    1952             :         /*
    1953             :          * Reset per-input-tuple context after each tuple, but note that the
    1954             :          * hash lookups do this too
    1955             :          */
    1956     2866910 :         ResetExprContext(aggstate->tmpcontext);
    1957             :     }
    1958             : 
    1959       38426 :     aggstate->table_filled = true;
    1960             :     /* Initialize to walk the first hash table */
    1961       38426 :     select_current_set(aggstate, 0, true);
    1962       38426 :     ResetTupleHashIterator(aggstate->perhash[0].hashtable,
    1963             :                            &aggstate->perhash[0].hashiter);
    1964       38426 : }
    1965             : 
    1966             : /*
    1967             :  * ExecAgg for hashed case: retrieving groups from hash table
    1968             :  */
    1969             : static TupleTableSlot *
    1970      257340 : agg_retrieve_hash_table(AggState *aggstate)
    1971             : {
    1972             :     ExprContext *econtext;
    1973             :     AggStatePerAgg peragg;
    1974             :     AggStatePerGroup pergroup;
    1975             :     TupleHashEntryData *entry;
    1976             :     TupleTableSlot *firstSlot;
    1977             :     TupleTableSlot *result;
    1978             :     AggStatePerHash perhash;
    1979             : 
    1980             :     /*
    1981             :      * get state info from node.
    1982             :      *
    1983             :      * econtext is the per-output-tuple expression context.
    1984             :      */
    1985      257340 :     econtext = aggstate->ss.ps.ps_ExprContext;
    1986      257340 :     peragg = aggstate->peragg;
    1987      257340 :     firstSlot = aggstate->ss.ss_ScanTupleSlot;
    1988             : 
    1989             :     /*
    1990             :      * Note that perhash (and therefore anything accessed through it) can
    1991             :      * change inside the loop, as we change between grouping sets.
    1992             :      */
    1993      257340 :     perhash = &aggstate->perhash[aggstate->current_set];
    1994             : 
    1995             :     /*
    1996             :      * We loop retrieving groups until we find one satisfying
    1997             :      * aggstate->ss.ps.qual
    1998             :      */
    1999      518632 :     while (!aggstate->agg_done)
    2000             :     {
    2001      261292 :         TupleTableSlot *hashslot = perhash->hashslot;
    2002             :         int         i;
    2003             : 
    2004      261292 :         CHECK_FOR_INTERRUPTS();
    2005             : 
    2006             :         /*
    2007             :          * Find the next entry in the hash table
    2008             :          */
    2009      261292 :         entry = ScanTupleHashTable(perhash->hashtable, &perhash->hashiter);
    2010      261292 :         if (entry == NULL)
    2011             :         {
    2012       39086 :             int         nextset = aggstate->current_set + 1;
    2013             : 
    2014       39086 :             if (nextset < aggstate->num_hashes)
    2015             :             {
    2016             :                 /*
    2017             :                  * Switch to next grouping set, reinitialize, and restart the
    2018             :                  * loop.
    2019             :                  */
    2020         110 :                 select_current_set(aggstate, nextset, true);
    2021             : 
    2022         110 :                 perhash = &aggstate->perhash[aggstate->current_set];
    2023             : 
    2024         110 :                 ResetTupleHashIterator(perhash->hashtable, &perhash->hashiter);
    2025             : 
    2026         110 :                 continue;
    2027             :             }
    2028             :             else
    2029             :             {
    2030             :                 /* No more hashtables, so done */
    2031       38976 :                 aggstate->agg_done = true;
    2032       38976 :                 return NULL;
    2033             :             }
    2034             :         }
    2035             : 
    2036             :         /*
    2037             :          * Clear the per-output-tuple context for each group
    2038             :          *
    2039             :          * We intentionally don't use ReScanExprContext here; if any aggs have
    2040             :          * registered shutdown callbacks, they mustn't be called yet, since we
    2041             :          * might not be done with that agg.
    2042             :          */
    2043      222206 :         ResetExprContext(econtext);
    2044             : 
    2045             :         /*
    2046             :          * Transform representative tuple back into one with the right
    2047             :          * columns.
    2048             :          */
    2049      222206 :         ExecStoreMinimalTuple(entry->firstTuple, hashslot, false);
    2050      222206 :         slot_getallattrs(hashslot);
    2051             : 
    2052      222206 :         ExecClearTuple(firstSlot);
    2053      222206 :         memset(firstSlot->tts_isnull, true,
    2054      222206 :                firstSlot->tts_tupleDescriptor->natts * sizeof(bool));
    2055             : 
    2056      705128 :         for (i = 0; i < perhash->numhashGrpCols; i++)
    2057             :         {
    2058      482922 :             int         varNumber = perhash->hashGrpColIdxInput[i] - 1;
    2059             : 
    2060      482922 :             firstSlot->tts_values[varNumber] = hashslot->tts_values[i];
    2061      482922 :             firstSlot->tts_isnull[varNumber] = hashslot->tts_isnull[i];
    2062             :         }
    2063      222206 :         ExecStoreVirtualTuple(firstSlot);
    2064             : 
    2065      222206 :         pergroup = (AggStatePerGroup) entry->additional;
    2066             : 
    2067             :         /*
    2068             :          * Use the representative input tuple for any references to
    2069             :          * non-aggregated input columns in the qual and tlist.
    2070             :          */
    2071      222206 :         econtext->ecxt_outertuple = firstSlot;
    2072             : 
    2073      222206 :         prepare_projection_slot(aggstate,
    2074             :                                 econtext->ecxt_outertuple,
    2075             :                                 aggstate->current_set);
    2076             : 
    2077      222206 :         finalize_aggregates(aggstate, peragg, pergroup);
    2078             : 
    2079      222206 :         result = project_aggregates(aggstate);
    2080      222206 :         if (result)
    2081      218364 :             return result;
    2082             :     }
    2083             : 
    2084             :     /* No more groups */
    2085           0 :     return NULL;
    2086             : }
    2087             : 
    2088             : /* -----------------
    2089             :  * ExecInitAgg
    2090             :  *
    2091             :  *  Creates the run-time information for the agg node produced by the
    2092             :  *  planner and initializes its outer subtree.
    2093             :  *
    2094             :  * -----------------
    2095             :  */
    2096             : AggState *
    2097       28770 : ExecInitAgg(Agg *node, EState *estate, int eflags)
    2098             : {
    2099             :     AggState   *aggstate;
    2100             :     AggStatePerAgg peraggs;
    2101             :     AggStatePerTrans pertransstates;
    2102             :     AggStatePerGroup *pergroups;
    2103             :     Plan       *outerPlan;
    2104             :     ExprContext *econtext;
    2105             :     TupleDesc   scanDesc;
    2106             :     int         numaggs,
    2107             :                 transno,
    2108             :                 aggno;
    2109             :     int         phase;
    2110             :     int         phaseidx;
    2111             :     ListCell   *l;
    2112       28770 :     Bitmapset  *all_grouped_cols = NULL;
    2113       28770 :     int         numGroupingSets = 1;
    2114             :     int         numPhases;
    2115             :     int         numHashes;
    2116       28770 :     int         i = 0;
    2117       28770 :     int         j = 0;
    2118       54808 :     bool        use_hashing = (node->aggstrategy == AGG_HASHED ||
    2119       26038 :                                node->aggstrategy == AGG_MIXED);
    2120             : 
    2121             :     /* check for unsupported flags */
    2122             :     Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
    2123             : 
    2124             :     /*
    2125             :      * create state structure
    2126             :      */
    2127       28770 :     aggstate = makeNode(AggState);
    2128       28770 :     aggstate->ss.ps.plan = (Plan *) node;
    2129       28770 :     aggstate->ss.ps.state = estate;
    2130       28770 :     aggstate->ss.ps.ExecProcNode = ExecAgg;
    2131             : 
    2132       28770 :     aggstate->aggs = NIL;
    2133       28770 :     aggstate->numaggs = 0;
    2134       28770 :     aggstate->numtrans = 0;
    2135       28770 :     aggstate->aggstrategy = node->aggstrategy;
    2136       28770 :     aggstate->aggsplit = node->aggsplit;
    2137       28770 :     aggstate->maxsets = 0;
    2138       28770 :     aggstate->projected_set = -1;
    2139       28770 :     aggstate->current_set = 0;
    2140       28770 :     aggstate->peragg = NULL;
    2141       28770 :     aggstate->pertrans = NULL;
    2142       28770 :     aggstate->curperagg = NULL;
    2143       28770 :     aggstate->curpertrans = NULL;
    2144       28770 :     aggstate->input_done = false;
    2145       28770 :     aggstate->agg_done = false;
    2146       28770 :     aggstate->pergroups = NULL;
    2147       28770 :     aggstate->grp_firstTuple = NULL;
    2148       28770 :     aggstate->sort_in = NULL;
    2149       28770 :     aggstate->sort_out = NULL;
    2150             : 
    2151             :     /*
    2152             :      * phases[0] always exists, but is dummy in sorted/plain mode
    2153             :      */
    2154       28770 :     numPhases = (use_hashing ? 1 : 2);
    2155       28770 :     numHashes = (use_hashing ? 1 : 0);
    2156             : 
    2157             :     /*
    2158             :      * Calculate the maximum number of grouping sets in any phase; this
    2159             :      * determines the size of some allocations.  Also calculate the number of
    2160             :      * phases, since all hashed/mixed nodes contribute to only a single phase.
    2161             :      */
    2162       28770 :     if (node->groupingSets)
    2163             :     {
    2164         424 :         numGroupingSets = list_length(node->groupingSets);
    2165             : 
    2166         820 :         foreach(l, node->chain)
    2167             :         {
    2168         396 :             Agg        *agg = lfirst(l);
    2169             : 
    2170         396 :             numGroupingSets = Max(numGroupingSets,
    2171             :                                   list_length(agg->groupingSets));
    2172             : 
    2173             :             /*
    2174             :              * additional AGG_HASHED aggs become part of phase 0, but all
    2175             :              * others add an extra phase.
    2176             :              */
    2177         396 :             if (agg->aggstrategy != AGG_HASHED)
    2178         220 :                 ++numPhases;
    2179             :             else
    2180         176 :                 ++numHashes;
    2181             :         }
    2182             :     }
    2183             : 
    2184       28770 :     aggstate->maxsets = numGroupingSets;
    2185       28770 :     aggstate->numphases = numPhases;
    2186             : 
    2187       28770 :     aggstate->aggcontexts = (ExprContext **)
    2188       28770 :         palloc0(sizeof(ExprContext *) * numGroupingSets);
    2189             : 
    2190             :     /*
    2191             :      * Create expression contexts.  We need three or more, one for
    2192             :      * per-input-tuple processing, one for per-output-tuple processing, one
    2193             :      * for all the hashtables, and one for each grouping set.  The per-tuple
    2194             :      * memory context of the per-grouping-set ExprContexts (aggcontexts)
    2195             :      * replaces the standalone memory context formerly used to hold transition
    2196             :      * values.  We cheat a little by using ExecAssignExprContext() to build
    2197             :      * all of them.
    2198             :      *
    2199             :      * NOTE: the details of what is stored in aggcontexts and what is stored
    2200             :      * in the regular per-query memory context are driven by a simple
    2201             :      * decision: we want to reset the aggcontext at group boundaries (if not
    2202             :      * hashing) and in ExecReScanAgg to recover no-longer-wanted space.
    2203             :      */
    2204       28770 :     ExecAssignExprContext(estate, &aggstate->ss.ps);
    2205       28770 :     aggstate->tmpcontext = aggstate->ss.ps.ps_ExprContext;
    2206             : 
    2207       57988 :     for (i = 0; i < numGroupingSets; ++i)
    2208             :     {
    2209       29218 :         ExecAssignExprContext(estate, &aggstate->ss.ps);
    2210       29218 :         aggstate->aggcontexts[i] = aggstate->ss.ps.ps_ExprContext;
    2211             :     }
    2212             : 
    2213       28770 :     if (use_hashing)
    2214             :     {
    2215        2824 :         ExecAssignExprContext(estate, &aggstate->ss.ps);
    2216        2824 :         aggstate->hashcontext = aggstate->ss.ps.ps_ExprContext;
    2217             :     }
    2218             : 
    2219       28770 :     ExecAssignExprContext(estate, &aggstate->ss.ps);
    2220             : 
    2221             :     /*
    2222             :      * Initialize child nodes.
    2223             :      *
    2224             :      * If we are doing a hashed aggregation then the child plan does not need
    2225             :      * to handle REWIND efficiently; see ExecReScanAgg.
    2226             :      */
    2227       28770 :     if (node->aggstrategy == AGG_HASHED)
    2228        2732 :         eflags &= ~EXEC_FLAG_REWIND;
    2229       28770 :     outerPlan = outerPlan(node);
    2230       28770 :     outerPlanState(aggstate) = ExecInitNode(outerPlan, estate, eflags);
    2231             : 
    2232             :     /*
    2233             :      * initialize source tuple type.
    2234             :      */
    2235       28770 :     aggstate->ss.ps.outerops =
    2236       28770 :         ExecGetResultSlotOps(outerPlanState(&aggstate->ss),
    2237             :                              &aggstate->ss.ps.outeropsfixed);
    2238       28770 :     aggstate->ss.ps.outeropsset = true;
    2239             : 
    2240       28770 :     ExecCreateScanSlotFromOuterPlan(estate, &aggstate->ss,
    2241             :                                     aggstate->ss.ps.outerops);
    2242       28770 :     scanDesc = aggstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
    2243             : 
    2244             :     /*
    2245             :      * If there are more than two phases (including a potential dummy phase
    2246             :      * 0), input will be resorted using tuplesort. Need a slot for that.
    2247             :      */
    2248       28770 :     if (numPhases > 2)
    2249             :     {
    2250         108 :         aggstate->sort_slot = ExecInitExtraTupleSlot(estate, scanDesc,
    2251             :                                                      &TTSOpsMinimalTuple);
    2252             : 
    2253             :         /*
    2254             :          * The output of the tuplesort, and the output from the outer child
    2255             :          * might not use the same type of slot. In most cases the child will
    2256             :          * be a Sort, and thus return a TTSOpsMinimalTuple type slot - but the
    2257             :          * input can also be be presorted due an index, in which case it could
    2258             :          * be a different type of slot.
    2259             :          *
    2260             :          * XXX: For efficiency it would be good to instead/additionally
    2261             :          * generate expressions with corresponding settings of outerops* for
    2262             :          * the individual phases - deforming is often a bottleneck for
    2263             :          * aggregations with lots of rows per group. If there's multiple
    2264             :          * sorts, we know that all but the first use TTSOpsMinimalTuple (via
    2265             :          * the nodeAgg.c internal tuplesort).
    2266             :          */
    2267         216 :         if (aggstate->ss.ps.outeropsfixed &&
    2268         108 :             aggstate->ss.ps.outerops != &TTSOpsMinimalTuple)
    2269           8 :             aggstate->ss.ps.outeropsfixed = false;
    2270             :     }
    2271             : 
    2272             :     /*
    2273             :      * Initialize result type, slot and projection.
    2274             :      */
    2275       28770 :     ExecInitResultTupleSlotTL(&aggstate->ss.ps, &TTSOpsVirtual);
    2276       28770 :     ExecAssignProjectionInfo(&aggstate->ss.ps, NULL);
    2277             : 
    2278             :     /*
    2279             :      * initialize child expressions
    2280             :      *
    2281             :      * We expect the parser to have checked that no aggs contain other agg
    2282             :      * calls in their arguments (and just to be sure, we verify it again while
    2283             :      * initializing the plan node).  This would make no sense under SQL
    2284             :      * semantics, and it's forbidden by the spec.  Because it is true, we
    2285             :      * don't need to worry about evaluating the aggs in any particular order.
    2286             :      *
    2287             :      * Note: execExpr.c finds Aggrefs for us, and adds their AggrefExprState
    2288             :      * nodes to aggstate->aggs.  Aggrefs in the qual are found here; Aggrefs
    2289             :      * in the targetlist are found during ExecAssignProjectionInfo, below.
    2290             :      */
    2291       28770 :     aggstate->ss.ps.qual =
    2292       28770 :         ExecInitQual(node->plan.qual, (PlanState *) aggstate);
    2293             : 
    2294             :     /*
    2295             :      * We should now have found all Aggrefs in the targetlist and quals.
    2296             :      */
    2297       28770 :     numaggs = aggstate->numaggs;
    2298             :     Assert(numaggs == list_length(aggstate->aggs));
    2299             : 
    2300             :     /*
    2301             :      * For each phase, prepare grouping set data and fmgr lookup data for
    2302             :      * compare functions.  Accumulate all_grouped_cols in passing.
    2303             :      */
    2304       28770 :     aggstate->phases = palloc0(numPhases * sizeof(AggStatePerPhaseData));
    2305             : 
    2306       28770 :     aggstate->num_hashes = numHashes;
    2307       28770 :     if (numHashes)
    2308             :     {
    2309        2824 :         aggstate->perhash = palloc0(sizeof(AggStatePerHashData) * numHashes);
    2310        2824 :         aggstate->phases[0].numsets = 0;
    2311        2824 :         aggstate->phases[0].gset_lengths = palloc(numHashes * sizeof(int));
    2312        2824 :         aggstate->phases[0].grouped_cols = palloc(numHashes * sizeof(Bitmapset *));
    2313             :     }
    2314             : 
    2315       28770 :     phase = 0;
    2316       57936 :     for (phaseidx = 0; phaseidx <= list_length(node->chain); ++phaseidx)
    2317             :     {
    2318             :         Agg        *aggnode;
    2319             :         Sort       *sortnode;
    2320             : 
    2321       29166 :         if (phaseidx > 0)
    2322             :         {
    2323         396 :             aggnode = list_nth_node(Agg, node->chain, phaseidx - 1);
    2324         396 :             sortnode = castNode(Sort, aggnode->plan.lefttree);
    2325             :         }
    2326             :         else
    2327             :         {
    2328       28770 :             aggnode = node;
    2329       28770 :             sortnode = NULL;
    2330             :         }
    2331             : 
    2332             :         Assert(phase <= 1 || sortnode);
    2333             : 
    2334       29166 :         if (aggnode->aggstrategy == AGG_HASHED
    2335       26258 :             || aggnode->aggstrategy == AGG_MIXED)
    2336             :         {
    2337        3000 :             AggStatePerPhase phasedata = &aggstate->phases[0];
    2338             :             AggStatePerHash perhash;
    2339        3000 :             Bitmapset  *cols = NULL;
    2340             : 
    2341             :             Assert(phase == 0);
    2342        3000 :             i = phasedata->numsets++;
    2343        3000 :             perhash = &aggstate->perhash[i];
    2344             : 
    2345             :             /* phase 0 always points to the "real" Agg in the hash case */
    2346        3000 :             phasedata->aggnode = node;
    2347        3000 :             phasedata->aggstrategy = node->aggstrategy;
    2348             : 
    2349             :             /* but the actual Agg node representing this hash is saved here */
    2350        3000 :             perhash->aggnode = aggnode;
    2351             : 
    2352        3000 :             phasedata->gset_lengths[i] = perhash->numCols = aggnode->numCols;
    2353             : 
    2354        6964 :             for (j = 0; j < aggnode->numCols; ++j)
    2355        3964 :                 cols = bms_add_member(cols, aggnode->grpColIdx[j]);
    2356             : 
    2357        3000 :             phasedata->grouped_cols[i] = cols;
    2358             : 
    2359        3000 :             all_grouped_cols = bms_add_members(all_grouped_cols, cols);
    2360        3000 :             continue;
    2361             :         }
    2362             :         else
    2363             :         {
    2364       26166 :             AggStatePerPhase phasedata = &aggstate->phases[++phase];
    2365             :             int         num_sets;
    2366             : 
    2367       26166 :             phasedata->numsets = num_sets = list_length(aggnode->groupingSets);
    2368             : 
    2369       26166 :             if (num_sets)
    2370             :             {
    2371         496 :                 phasedata->gset_lengths = palloc(num_sets * sizeof(int));
    2372         496 :                 phasedata->grouped_cols = palloc(num_sets * sizeof(Bitmapset *));
    2373             : 
    2374         496 :                 i = 0;
    2375        1472 :                 foreach(l, aggnode->groupingSets)
    2376             :                 {
    2377         976 :                     int         current_length = list_length(lfirst(l));
    2378         976 :                     Bitmapset  *cols = NULL;
    2379             : 
    2380             :                     /* planner forces this to be correct */
    2381        1888 :                     for (j = 0; j < current_length; ++j)
    2382         912 :                         cols = bms_add_member(cols, aggnode->grpColIdx[j]);
    2383             : 
    2384         976 :                     phasedata->grouped_cols[i] = cols;
    2385         976 :                     phasedata->gset_lengths[i] = current_length;
    2386             : 
    2387         976 :                     ++i;
    2388             :                 }
    2389             : 
    2390         496 :                 all_grouped_cols = bms_add_members(all_grouped_cols,
    2391         496 :                                                    phasedata->grouped_cols[0]);
    2392             :             }
    2393             :             else
    2394             :             {
    2395             :                 Assert(phaseidx == 0);
    2396             : 
    2397       25670 :                 phasedata->gset_lengths = NULL;
    2398       25670 :                 phasedata->grouped_cols = NULL;
    2399             :             }
    2400             : 
    2401             :             /*
    2402             :              * If we are grouping, precompute fmgr lookup data for inner loop.
    2403             :              */
    2404       26166 :             if (aggnode->aggstrategy == AGG_SORTED)
    2405             :             {
    2406        1304 :                 int         i = 0;
    2407             : 
    2408             :                 Assert(aggnode->numCols > 0);
    2409             : 
    2410             :                 /*
    2411             :                  * Build a separate function for each subset of columns that
    2412             :                  * need to be compared.
    2413             :                  */
    2414        1304 :                 phasedata->eqfunctions =
    2415        1304 :                     (ExprState **) palloc0(aggnode->numCols * sizeof(ExprState *));
    2416             : 
    2417             :                 /* for each grouping set */
    2418        2144 :                 for (i = 0; i < phasedata->numsets; i++)
    2419             :                 {
    2420         840 :                     int         length = phasedata->gset_lengths[i];
    2421             : 
    2422         840 :                     if (phasedata->eqfunctions[length - 1] != NULL)
    2423         248 :                         continue;
    2424             : 
    2425        1184 :                     phasedata->eqfunctions[length - 1] =
    2426         592 :                         execTuplesMatchPrepare(scanDesc,
    2427             :                                                length,
    2428         592 :                                                aggnode->grpColIdx,
    2429         592 :                                                aggnode->grpOperators,
    2430         592 :                                                aggnode->grpCollations,
    2431             :                                                (PlanState *) aggstate);
    2432             :                 }
    2433             : 
    2434             :                 /* and for all grouped columns, unless already computed */
    2435        1304 :                 if (phasedata->eqfunctions[aggnode->numCols - 1] == NULL)
    2436             :                 {
    2437        1792 :                     phasedata->eqfunctions[aggnode->numCols - 1] =
    2438         896 :                         execTuplesMatchPrepare(scanDesc,
    2439             :                                                aggnode->numCols,
    2440         896 :                                                aggnode->grpColIdx,
    2441         896 :                                                aggnode->grpOperators,
    2442         896 :                                                aggnode->grpCollations,
    2443             :                                                (PlanState *) aggstate);
    2444             :                 }
    2445             :             }
    2446             : 
    2447       26166 :             phasedata->aggnode = aggnode;
    2448       26166 :             phasedata->aggstrategy = aggnode->aggstrategy;
    2449       26166 :             phasedata->sortnode = sortnode;
    2450             :         }
    2451             :     }
    2452             : 
    2453             :     /*
    2454             :      * Convert all_grouped_cols to a descending-order list.
    2455             :      */
    2456       28770 :     i = -1;
    2457       61956 :     while ((i = bms_next_member(all_grouped_cols, i)) >= 0)
    2458        4416 :         aggstate->all_grouped_cols = lcons_int(i, aggstate->all_grouped_cols);
    2459             : 
    2460             :     /*
    2461             :      * Set up aggregate-result storage in the output expr context, and also
    2462             :      * allocate my private per-agg working storage
    2463             :      */
    2464       28770 :     econtext = aggstate->ss.ps.ps_ExprContext;
    2465       28770 :     econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs);
    2466       28770 :     econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs);
    2467             : 
    2468       28770 :     peraggs = (AggStatePerAgg) palloc0(sizeof(AggStatePerAggData) * numaggs);
    2469       28770 :     pertransstates = (AggStatePerTrans) palloc0(sizeof(AggStatePerTransData) * numaggs);
    2470             : 
    2471       28770 :     aggstate->peragg = peraggs;
    2472       28770 :     aggstate->pertrans = pertransstates;
    2473             : 
    2474             : 
    2475       28770 :     aggstate->all_pergroups =
    2476       28770 :         (AggStatePerGroup *) palloc0(sizeof(AggStatePerGroup)
    2477       28770 :                                      * (numGroupingSets + numHashes));
    2478       28770 :     pergroups = aggstate->all_pergroups;
    2479             : 
    2480       28770 :     if (node->aggstrategy != AGG_HASHED)
    2481             :     {
    2482       52524 :         for (i = 0; i < numGroupingSets; i++)
    2483             :         {
    2484       26486 :             pergroups[i] = (AggStatePerGroup) palloc0(sizeof(AggStatePerGroupData)
    2485             :                                                       * numaggs);
    2486             :         }
    2487             : 
    2488       26038 :         aggstate->pergroups = pergroups;
    2489       26038 :         pergroups += numGroupingSets;
    2490             :     }
    2491             : 
    2492             :     /*
    2493             :      * Hashing can only appear in the initial phase.
    2494             :      */
    2495       28770 :     if (use_hashing)
    2496             :     {
    2497             :         /* this is an array of pointers, not structures */
    2498        2824 :         aggstate->hash_pergroup = pergroups;
    2499             : 
    2500        2824 :         find_hash_columns(aggstate);
    2501        2824 :         build_hash_table(aggstate);
    2502        2824 :         aggstate->table_filled = false;
    2503             :     }
    2504             : 
    2505             :     /*
    2506             :      * Initialize current phase-dependent values to initial phase. The initial
    2507             :      * phase is 1 (first sort pass) for all strategies that use sorting (if
    2508             :      * hashing is being done too, then phase 0 is processed last); but if only
    2509             :      * hashing is being done, then phase 0 is all there is.
    2510             :      */
    2511       28770 :     if (node->aggstrategy == AGG_HASHED)
    2512             :     {
    2513        2732 :         aggstate->current_phase = 0;
    2514        2732 :         initialize_phase(aggstate, 0);
    2515        2732 :         select_current_set(aggstate, 0, true);
    2516             :     }
    2517             :     else
    2518             :     {
    2519       26038 :         aggstate->current_phase = 1;
    2520       26038 :         initialize_phase(aggstate, 1);
    2521       26038 :         select_current_set(aggstate, 0, false);
    2522             :     }
    2523             : 
    2524             :     /* -----------------
    2525             :      * Perform lookups of aggregate function info, and initialize the
    2526             :      * unchanging fields of the per-agg and per-trans data.
    2527             :      *
    2528             :      * We try to optimize by detecting duplicate aggregate functions so that
    2529             :      * their state and final values are re-used, rather than needlessly being
    2530             :      * re-calculated independently. We also detect aggregates that are not
    2531             :      * the same, but which can share the same transition state.
    2532             :      *
    2533             :      * Scenarios:
    2534             :      *
    2535             :      * 1. Identical aggregate function calls appear in the query:
    2536             :      *
    2537             :      *    SELECT SUM(x) FROM ... HAVING SUM(x) > 0
    2538             :      *
    2539             :      *    Since these aggregates are identical, we only need to calculate
    2540             :      *    the value once. Both aggregates will share the same 'aggno' value.
    2541             :      *
    2542             :      * 2. Two different aggregate functions appear in the query, but the
    2543             :      *    aggregates have the same arguments, transition functions and
    2544             :      *    initial values (and, presumably, different final functions):
    2545             :      *
    2546             :      *    SELECT AVG(x), STDDEV(x) FROM ...
    2547             :      *
    2548             :      *    In this case we must create a new peragg for the varying aggregate,
    2549             :      *    and we need to call the final functions separately, but we need
    2550             :      *    only run the transition function once.  (This requires that the
    2551             :      *    final functions be nondestructive of the transition state, but
    2552             :      *    that's required anyway for other reasons.)
    2553             :      *
    2554             :      * For either of these optimizations to be valid, all aggregate properties
    2555             :      * used in the transition phase must be the same, including any modifiers
    2556             :      * such as ORDER BY, DISTINCT and FILTER, and the arguments mustn't
    2557             :      * contain any volatile functions.
    2558             :      * -----------------
    2559             :      */
    2560       28770 :     aggno = -1;
    2561       28770 :     transno = -1;
    2562       60188 :     foreach(l, aggstate->aggs)
    2563             :     {
    2564       31422 :         AggrefExprState *aggrefstate = (AggrefExprState *) lfirst(l);
    2565       31422 :         Aggref     *aggref = aggrefstate->aggref;
    2566             :         AggStatePerAgg peragg;
    2567             :         AggStatePerTrans pertrans;
    2568             :         int         existing_aggno;
    2569             :         int         existing_transno;
    2570             :         List       *same_input_transnos;
    2571             :         Oid         inputTypes[FUNC_MAX_ARGS];
    2572             :         int         numArguments;
    2573             :         int         numDirectArgs;
    2574             :         HeapTuple   aggTuple;
    2575             :         Form_pg_aggregate aggform;
    2576             :         AclResult   aclresult;
    2577             :         Oid         transfn_oid,
    2578             :                     finalfn_oid;
    2579             :         bool        shareable;
    2580             :         Oid         serialfn_oid,
    2581             :                     deserialfn_oid;
    2582             :         Expr       *finalfnexpr;
    2583             :         Oid         aggtranstype;
    2584             :         Datum       textInitVal;
    2585             :         Datum       initValue;
    2586             :         bool        initValueIsNull;
    2587             : 
    2588             :         /* Planner should have assigned aggregate to correct level */
    2589             :         Assert(aggref->agglevelsup == 0);
    2590             :         /* ... and the split mode should match */
    2591             :         Assert(aggref->aggsplit == aggstate->aggsplit);
    2592             : 
    2593             :         /* 1. Check for already processed aggs which can be re-used */
    2594       31422 :         existing_aggno = find_compatible_peragg(aggref, aggstate, aggno,
    2595             :                                                 &same_input_transnos);
    2596       31422 :         if (existing_aggno != -1)
    2597             :         {
    2598             :             /*
    2599             :              * Existing compatible agg found. so just point the Aggref to the
    2600             :              * same per-agg struct.
    2601             :              */
    2602         300 :             aggrefstate->aggno = existing_aggno;
    2603         300 :             continue;
    2604             :         }
    2605             : 
    2606             :         /* Mark Aggref state node with assigned index in the result array */
    2607       31122 :         peragg = &peraggs[++aggno];
    2608       31122 :         peragg->aggref = aggref;
    2609       31122 :         aggrefstate->aggno = aggno;
    2610             : 
    2611             :         /* Fetch the pg_aggregate row */
    2612       31122 :         aggTuple = SearchSysCache1(AGGFNOID,
    2613       31122 :                                    ObjectIdGetDatum(aggref->aggfnoid));
    2614       31122 :         if (!HeapTupleIsValid(aggTuple))
    2615           0 :             elog(ERROR, "cache lookup failed for aggregate %u",
    2616             :                  aggref->aggfnoid);
    2617       31122 :         aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);
    2618             : 
    2619             :         /* Check permission to call aggregate function */
    2620       31122 :         aclresult = pg_proc_aclcheck(aggref->aggfnoid, GetUserId(),
    2621             :                                      ACL_EXECUTE);
    2622       31122 :         if (aclresult != ACLCHECK_OK)
    2623           4 :             aclcheck_error(aclresult, OBJECT_AGGREGATE,
    2624           4 :                            get_func_name(aggref->aggfnoid));
    2625       31118 :         InvokeFunctionExecuteHook(aggref->aggfnoid);
    2626             : 
    2627             :         /* planner recorded transition state type in the Aggref itself */
    2628       31118 :         aggtranstype = aggref->aggtranstype;
    2629             :         Assert(OidIsValid(aggtranstype));
    2630             : 
    2631             :         /*
    2632             :          * If this aggregation is performing state combines, then instead of
    2633             :          * using the transition function, we'll use the combine function
    2634             :          */
    2635       31118 :         if (DO_AGGSPLIT_COMBINE(aggstate->aggsplit))
    2636             :         {
    2637         816 :             transfn_oid = aggform->aggcombinefn;
    2638             : 
    2639             :             /* If not set then the planner messed up */
    2640         816 :             if (!OidIsValid(transfn_oid))
    2641           0 :                 elog(ERROR, "combinefn not set for aggregate function");
    2642             :         }
    2643             :         else
    2644       30302 :             transfn_oid = aggform->aggtransfn;
    2645             : 
    2646             :         /* Final function only required if we're finalizing the aggregates */
    2647       31118 :         if (DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit))
    2648        2654 :             peragg->finalfn_oid = finalfn_oid = InvalidOid;
    2649             :         else
    2650       28464 :             peragg->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
    2651             : 
    2652             :         /*
    2653             :          * If finalfn is marked read-write, we can't share transition states;
    2654             :          * but it is okay to share states for AGGMODIFY_SHAREABLE aggs.  Also,
    2655             :          * if we're not executing the finalfn here, we can share regardless.
    2656             :          */
    2657       31118 :         shareable = (aggform->aggfinalmodify != AGGMODIFY_READ_WRITE) ||
    2658             :             (finalfn_oid == InvalidOid);
    2659       31118 :         peragg->shareable = shareable;
    2660             : 
    2661       31118 :         serialfn_oid = InvalidOid;
    2662       31118 :         deserialfn_oid = InvalidOid;
    2663             : 
    2664             :         /*
    2665             :          * Check if serialization/deserialization is required.  We only do it
    2666             :          * for aggregates that have transtype INTERNAL.
    2667             :          */
    2668       31118 :         if (aggtranstype == INTERNALOID)
    2669             :         {
    2670             :             /*
    2671             :              * The planner should only have generated a serialize agg node if
    2672             :              * every aggregate with an INTERNAL state has a serialization
    2673             :              * function.  Verify that.
    2674             :              */
    2675       15656 :             if (DO_AGGSPLIT_SERIALIZE(aggstate->aggsplit))
    2676             :             {
    2677             :                 /* serialization only valid when not running finalfn */
    2678             :                 Assert(DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit));
    2679             : 
    2680          72 :                 if (!OidIsValid(aggform->aggserialfn))
    2681           0 :                     elog(ERROR, "serialfunc not provided for serialization aggregation");
    2682          72 :                 serialfn_oid = aggform->aggserialfn;
    2683             :             }
    2684             : 
    2685             :             /* Likewise for deserialization functions */
    2686       15656 :             if (DO_AGGSPLIT_DESERIALIZE(aggstate->aggsplit))
    2687             :             {
    2688             :                 /* deserialization only valid when combining states */
    2689             :                 Assert(DO_AGGSPLIT_COMBINE(aggstate->aggsplit));
    2690             : 
    2691          24 :                 if (!OidIsValid(aggform->aggdeserialfn))
    2692           0 :                     elog(ERROR, "deserialfunc not provided for deserialization aggregation");
    2693          24 :                 deserialfn_oid = aggform->aggdeserialfn;
    2694             :             }
    2695             :         }
    2696             : 
    2697             :         /* Check that aggregate owner has permission to call component fns */
    2698             :         {
    2699             :             HeapTuple   procTuple;
    2700             :             Oid         aggOwner;
    2701             : 
    2702       31118 :             procTuple = SearchSysCache1(PROCOID,
    2703       31118 :                                         ObjectIdGetDatum(aggref->aggfnoid));
    2704       31118 :             if (!HeapTupleIsValid(procTuple))
    2705           0 :                 elog(ERROR, "cache lookup failed for function %u",
    2706             :                      aggref->aggfnoid);
    2707       31118 :             aggOwner = ((Form_pg_proc) GETSTRUCT(procTuple))->proowner;
    2708       31118 :             ReleaseSysCache(procTuple);
    2709             : 
    2710       31118 :             aclresult = pg_proc_aclcheck(transfn_oid, aggOwner,
    2711             :                                          ACL_EXECUTE);
    2712       31118 :             if (aclresult != ACLCHECK_OK)
    2713           0 :                 aclcheck_error(aclresult, OBJECT_FUNCTION,
    2714           0 :                                get_func_name(transfn_oid));
    2715       31118 :             InvokeFunctionExecuteHook(transfn_oid);
    2716       31118 :             if (OidIsValid(finalfn_oid))
    2717             :             {
    2718       16642 :                 aclresult = pg_proc_aclcheck(finalfn_oid, aggOwner,
    2719             :                                              ACL_EXECUTE);
    2720       16642 :                 if (aclresult != ACLCHECK_OK)
    2721           0 :                     aclcheck_error(aclresult, OBJECT_FUNCTION,
    2722           0 :                                    get_func_name(finalfn_oid));
    2723       16642 :                 InvokeFunctionExecuteHook(finalfn_oid);
    2724             :             }
    2725       31118 :             if (OidIsValid(serialfn_oid))
    2726             :             {
    2727          72 :                 aclresult = pg_proc_aclcheck(serialfn_oid, aggOwner,
    2728             :                                              ACL_EXECUTE);
    2729          72 :                 if (aclresult != ACLCHECK_OK)
    2730           0 :                     aclcheck_error(aclresult, OBJECT_FUNCTION,
    2731           0 :                                    get_func_name(serialfn_oid));
    2732          72 :                 InvokeFunctionExecuteHook(serialfn_oid);
    2733             :             }
    2734       31118 :             if (OidIsValid(deserialfn_oid))
    2735             :             {
    2736          24 :                 aclresult = pg_proc_aclcheck(deserialfn_oid, aggOwner,
    2737             :                                              ACL_EXECUTE);
    2738          24 :                 if (aclresult != ACLCHECK_OK)
    2739           0 :                     aclcheck_error(aclresult, OBJECT_FUNCTION,
    2740           0 :                                    get_func_name(deserialfn_oid));
    2741          24 :                 InvokeFunctionExecuteHook(deserialfn_oid);
    2742             :             }
    2743             :         }
    2744             : 
    2745             :         /*
    2746             :          * Get actual datatypes of the (nominal) aggregate inputs.  These
    2747             :          * could be different from the agg's declared input types, when the
    2748             :          * agg accepts ANY or a polymorphic type.
    2749             :          */
    2750       31118 :         numArguments = get_aggregate_argtypes(aggref, inputTypes);
    2751             : 
    2752             :         /* Count the "direct" arguments, if any */
    2753       31118 :         numDirectArgs = list_length(aggref->aggdirectargs);
    2754             : 
    2755             :         /* Detect how many arguments to pass to the finalfn */
    2756       31118 :         if (aggform->aggfinalextra)
    2757       13698 :             peragg->numFinalArgs = numArguments + 1;
    2758             :         else
    2759       17420 :             peragg->numFinalArgs = numDirectArgs + 1;
    2760             : 
    2761             :         /* Initialize any direct-argument expressions */
    2762       31118 :         peragg->aggdirectargs = ExecInitExprList(aggref->aggdirectargs,
    2763             :                                                  (PlanState *) aggstate);
    2764             : 
    2765             :         /*
    2766             :          * build expression trees using actual argument & result types for the
    2767             :          * finalfn, if it exists and is required.
    2768             :          */
    2769       31118 :         if (OidIsValid(finalfn_oid))
    2770             :         {
    2771       16642 :             build_aggregate_finalfn_expr(inputTypes,
    2772             :                                          peragg->numFinalArgs,
    2773             :                                          aggtranstype,
    2774             :                                          aggref->aggtype,
    2775             :                                          aggref->inputcollid,
    2776             :                                          finalfn_oid,
    2777             :                                          &finalfnexpr);
    2778       16642 :             fmgr_info(finalfn_oid, &peragg->finalfn);
    2779       16642 :             fmgr_info_set_expr((Node *) finalfnexpr, &peragg->finalfn);
    2780             :         }
    2781             : 
    2782             :         /* get info about the output value's datatype */
    2783       31118 :         get_typlenbyval(aggref->aggtype,
    2784             :                         &peragg->resulttypeLen,
    2785             :                         &peragg->resulttypeByVal);
    2786             : 
    2787             :         /*
    2788             :          * initval is potentially null, so don't try to access it as a struct
    2789             :          * field. Must do it the hard way with SysCacheGetAttr.
    2790             :          */
    2791       31118 :         textInitVal = SysCacheGetAttr(AGGFNOID, aggTuple,
    2792             :                                       Anum_pg_aggregate_agginitval,
    2793             :                                       &initValueIsNull);
    2794       31118 :         if (initValueIsNull)
    2795       21144 :             initValue = (Datum) 0;
    2796             :         else
    2797        9974 :             initValue = GetAggInitVal(textInitVal, aggtranstype);
    2798             : 
    2799             :         /*
    2800             :          * 2. Build working state for invoking the transition function, or
    2801             :          * look up previously initialized working state, if we can share it.
    2802             :          *
    2803             :          * find_compatible_peragg() already collected a list of shareable
    2804             :          * per-Trans's with the same inputs. Check if any of them have the
    2805             :          * same transition function and initial value.
    2806             :          */
    2807       31118 :         existing_transno = find_compatible_pertrans(aggstate, aggref,
    2808             :                                                     shareable,
    2809             :                                                     transfn_oid, aggtranstype,
    2810             :                                                     serialfn_oid, deserialfn_oid,
    2811             :                                                     initValue, initValueIsNull,
    2812             :                                                     same_input_transnos);
    2813       31118 :         if (existing_transno != -1)
    2814             :         {
    2815             :             /*
    2816             :              * Existing compatible trans found, so just point the 'peragg' to
    2817             :              * the same per-trans struct, and mark the trans state as shared.
    2818             :              */
    2819          92 :             pertrans = &pertransstates[existing_transno];
    2820          92 :             pertrans->aggshared = true;
    2821          92 :             peragg->transno = existing_transno;
    2822             :         }
    2823             :         else
    2824             :         {
    2825       31026 :             pertrans = &pertransstates[++transno];
    2826       31026 :             build_pertrans_for_aggref(pertrans, aggstate, estate,
    2827             :                                       aggref, transfn_oid, aggtranstype,
    2828             :                                       serialfn_oid, deserialfn_oid,
    2829             :                                       initValue, initValueIsNull,
    2830             :                                       inputTypes, numArguments);
    2831       31026 :             peragg->transno = transno;
    2832             :         }
    2833       31118 :         ReleaseSysCache(aggTuple);
    2834             :     }
    2835             : 
    2836             :     /*
    2837             :      * Update aggstate->numaggs to be the number of unique aggregates found.
    2838             :      * Also set numstates to the number of unique transition states found.
    2839             :      */
    2840       28766 :     aggstate->numaggs = aggno + 1;
    2841       28766 :     aggstate->numtrans = transno + 1;
    2842             : 
    2843             :     /*
    2844             :      * Last, check whether any more aggregates got added onto the node while
    2845             :      * we processed the expressions for the aggregate arguments (including not
    2846             :      * only the regular arguments and FILTER expressions handled immediately
    2847             :      * above, but any direct arguments we might've handled earlier).  If so,
    2848             :      * we have nested aggregate functions, which is semantically nonsensical,
    2849             :      * so complain.  (This should have been caught by the parser, so we don't
    2850             :      * need to work hard on a helpful error message; but we defend against it
    2851             :      * here anyway, just to be sure.)
    2852             :      */
    2853       28766 :     if (numaggs != list_length(aggstate->aggs))
    2854           0 :         ereport(ERROR,
    2855             :                 (errcode(ERRCODE_GROUPING_ERROR),
    2856             :                  errmsg("aggregate function calls cannot be nested")));
    2857             : 
    2858             :     /*
    2859             :      * Build expressions doing all the transition work at once. We build a
    2860             :      * different one for each phase, as the number of transition function
    2861             :      * invocation can differ between phases. Note this'll work both for
    2862             :      * transition and combination functions (although there'll only be one
    2863             :      * phase in the latter case).
    2864             :      */
    2865       83694 :     for (phaseidx = 0; phaseidx < aggstate->numphases; phaseidx++)
    2866             :     {
    2867       54928 :         AggStatePerPhase phase = &aggstate->phases[phaseidx];
    2868       54928 :         bool        dohash = false;
    2869       54928 :         bool        dosort = false;
    2870             : 
    2871             :         /* phase 0 doesn't necessarily exist */
    2872       54928 :         if (!phase->aggnode)
    2873       25942 :             continue;
    2874             : 
    2875       28986 :         if (aggstate->aggstrategy == AGG_MIXED && phaseidx == 1)
    2876             :         {
    2877             :             /*
    2878             :              * Phase one, and only phase one, in a mixed agg performs both
    2879             :              * sorting and aggregation.
    2880             :              */
    2881          92 :             dohash = true;
    2882          92 :             dosort = true;
    2883             :         }
    2884       28894 :         else if (aggstate->aggstrategy == AGG_MIXED && phaseidx == 0)
    2885             :         {
    2886             :             /*
    2887             :              * No need to compute a transition function for an AGG_MIXED phase
    2888             :              * 0 - the contents of the hashtables will have been computed
    2889             :              * during phase 1.
    2890             :              */
    2891          92 :             continue;
    2892             :         }
    2893       32810 :         else if (phase->aggstrategy == AGG_PLAIN ||
    2894        4008 :                  phase->aggstrategy == AGG_SORTED)
    2895             :         {
    2896       26070 :             dohash = false;
    2897       26070 :             dosort = true;
    2898             :         }
    2899        2732 :         else if (phase->aggstrategy == AGG_HASHED)
    2900             :         {
    2901        2732 :             dohash = true;
    2902        2732 :             dosort = false;
    2903             :         }
    2904             :         else
    2905             :             Assert(false);
    2906             : 
    2907       28894 :         phase->evaltrans = ExecBuildAggTrans(aggstate, phase, dosort, dohash);
    2908             : 
    2909             :     }
    2910             : 
    2911       28766 :     return aggstate;
    2912             : }
    2913             : 
    2914             : /*
    2915             :  * Build the state needed to calculate a state value for an aggregate.
    2916             :  *
    2917             :  * This initializes all the fields in 'pertrans'. 'aggref' is the aggregate
    2918             :  * to initialize the state for. 'aggtransfn', 'aggtranstype', and the rest
    2919             :  * of the arguments could be calculated from 'aggref', but the caller has
    2920             :  * calculated them already, so might as well pass them.
    2921             :  */
    2922             : static void
    2923       31026 : build_pertrans_for_aggref(AggStatePerTrans pertrans,
    2924             :                           AggState *aggstate, EState *estate,
    2925             :                           Aggref *aggref,
    2926             :                           Oid aggtransfn, Oid aggtranstype,
    2927             :                           Oid aggserialfn, Oid aggdeserialfn,
    2928             :                           Datum initValue, bool initValueIsNull,
    2929             :                           Oid *inputTypes, int numArguments)
    2930             : {
    2931       31026 :     int         numGroupingSets = Max(aggstate->maxsets, 1);
    2932       31026 :     Expr       *serialfnexpr = NULL;
    2933       31026 :     Expr       *deserialfnexpr = NULL;
    2934             :     ListCell   *lc;
    2935             :     int         numInputs;
    2936             :     int         numDirectArgs;
    2937             :     List       *sortlist;
    2938             :     int         numSortCols;
    2939             :     int         numDistinctCols;
    2940             :     int         i;
    2941             : 
    2942             :     /* Begin filling in the pertrans data */
    2943       31026 :     pertrans->aggref = aggref;
    2944       31026 :     pertrans->aggshared = false;
    2945       31026 :     pertrans->aggCollation = aggref->inputcollid;
    2946       31026 :     pertrans->transfn_oid = aggtransfn;
    2947       31026 :     pertrans->serialfn_oid = aggserialfn;
    2948       31026 :     pertrans->deserialfn_oid = aggdeserialfn;
    2949       31026 :     pertrans->initValue = initValue;
    2950       31026 :     pertrans->initValueIsNull = initValueIsNull;
    2951             : 
    2952             :     /* Count the "direct" arguments, if any */
    2953       31026 :     numDirectArgs = list_length(aggref->aggdirectargs);
    2954             : 
    2955             :     /* Count the number of aggregated input columns */
    2956       31026 :     pertrans->numInputs = numInputs = list_length(aggref->args);
    2957             : 
    2958       31026 :     pertrans->aggtranstype = aggtranstype;
    2959             : 
    2960             :     /*
    2961             :      * When combining states, we have no use at all for the aggregate
    2962             :      * function's transfn. Instead we use the combinefn.  In this case, the
    2963             :      * transfn and transfn_oid fields of pertrans refer to the combine
    2964             :      * function rather than the transition function.
    2965             :      */
    2966       31026 :     if (DO_AGGSPLIT_COMBINE(aggstate->aggsplit))
    2967             :     {
    2968             :         Expr       *combinefnexpr;
    2969             :         size_t      numTransArgs;
    2970             : 
    2971             :         /*
    2972             :          * When combining there's only one input, the to-be-combined added
    2973             :          * transition value from below (this node's transition value is
    2974             :          * counted separately).
    2975             :          */
    2976         816 :         pertrans->numTransInputs = 1;
    2977             : 
    2978             :         /* account for the current transition state */
    2979         816 :         numTransArgs = pertrans->numTransInputs + 1;
    2980             : 
    2981         816 :         build_aggregate_combinefn_expr(aggtranstype,
    2982             :                                        aggref->inputcollid,
    2983             :                                        aggtransfn,
    2984             :                                        &combinefnexpr);
    2985         816 :         fmgr_info(aggtransfn, &pertrans->transfn);
    2986         816 :         fmgr_info_set_expr((Node *) combinefnexpr, &pertrans->transfn);
    2987             : 
    2988         816 :         pertrans->transfn_fcinfo =
    2989         816 :             (FunctionCallInfo) palloc(SizeForFunctionCallInfo(2));
    2990         816 :         InitFunctionCallInfoData(*pertrans->transfn_fcinfo,
    2991             :                                  &pertrans->transfn,
    2992             :                                  numTransArgs,
    2993             :                                  pertrans->aggCollation,
    2994             :                                  (void *) aggstate, NULL);
    2995             : 
    2996             :         /*
    2997             :          * Ensure that a combine function to combine INTERNAL states is not
    2998             :          * strict. This should have been checked during CREATE AGGREGATE, but
    2999             :          * the strict property could have been changed since then.
    3000             :          */
    3001         816 :         if (pertrans->transfn.fn_strict && aggtranstype == INTERNALOID)
    3002           0 :             ereport(ERROR,
    3003             :                     (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
    3004             :                      errmsg("combine function with transition type %s must not be declared STRICT",
    3005             :                             format_type_be(aggtranstype))));
    3006             :     }
    3007             :     else
    3008             :     {
    3009             :         Expr       *transfnexpr;
    3010             :         size_t      numTransArgs;
    3011             : 
    3012             :         /* Detect how many arguments to pass to the transfn */
    3013       30210 :         if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
    3014         138 :             pertrans->numTransInputs = numInputs;
    3015             :         else
    3016       30072 :             pertrans->numTransInputs = numArguments;
    3017             : 
    3018             :         /* account for the current transition state */
    3019       30210 :         numTransArgs = pertrans->numTransInputs + 1;
    3020             : 
    3021             :         /*
    3022             :          * Set up infrastructure for calling the transfn.  Note that
    3023             :          * invtransfn is not needed here.
    3024             :          */
    3025       60420 :         build_aggregate_transfn_expr(inputTypes,
    3026             :                                      numArguments,
    3027             :                                      numDirectArgs,
    3028       30210 :                                      aggref->aggvariadic,
    3029             :                                      aggtranstype,
    3030             :                                      aggref->inputcollid,
    3031             :                                      aggtransfn,
    3032             :                                      InvalidOid,
    3033             :                                      &transfnexpr,
    3034             :                                      NULL);
    3035       30210 :         fmgr_info(aggtransfn, &pertrans->transfn);
    3036       30210 :         fmgr_info_set_expr((Node *) transfnexpr, &pertrans->transfn);
    3037             : 
    3038       30210 :         pertrans->transfn_fcinfo =
    3039       30210 :             (FunctionCallInfo) palloc(SizeForFunctionCallInfo(numTransArgs));
    3040       30210 :         InitFunctionCallInfoData(*pertrans->transfn_fcinfo,
    3041             :                                  &pertrans->transfn,
    3042             :                                  numTransArgs,
    3043             :                                  pertrans->aggCollation,
    3044             :                                  (void *) aggstate, NULL);
    3045             : 
    3046             :         /*
    3047             :          * If the transfn is strict and the initval is NULL, make sure input
    3048             :          * type and transtype are the same (or at least binary-compatible), so
    3049             :          * that it's OK to use the first aggregated input value as the initial
    3050             :          * transValue.  This should have been checked at agg definition time,
    3051             :          * but we must check again in case the transfn's strictness property
    3052             :          * has been changed.
    3053             :          */
    3054       30210 :         if (pertrans->transfn.fn_strict && pertrans->initValueIsNull)
    3055             :         {
    3056        6736 :             if (numArguments <= numDirectArgs ||
    3057        3368 :                 !IsBinaryCoercible(inputTypes[numDirectArgs],
    3058             :                                    aggtranstype))
    3059           0 :                 ereport(ERROR,
    3060             :                         (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
    3061             :                          errmsg("aggregate %u needs to have compatible input type and transition type",
    3062             :                                 aggref->aggfnoid)));
    3063             :         }
    3064             :     }
    3065             : 
    3066             :     /* get info about the state value's datatype */
    3067       31026 :     get_typlenbyval(aggtranstype,
    3068             :                     &pertrans->transtypeLen,
    3069             :                     &pertrans->transtypeByVal);
    3070             : 
    3071       31026 :     if (OidIsValid(aggserialfn))
    3072             :     {
    3073          72 :         build_aggregate_serialfn_expr(aggserialfn,
    3074             :                                       &serialfnexpr);
    3075          72 :         fmgr_info(aggserialfn, &pertrans->serialfn);
    3076          72 :         fmgr_info_set_expr((Node *) serialfnexpr, &pertrans->serialfn);
    3077             : 
    3078          72 :         pertrans->serialfn_fcinfo =
    3079          72 :             (FunctionCallInfo) palloc(SizeForFunctionCallInfo(1));
    3080          72 :         InitFunctionCallInfoData(*pertrans->serialfn_fcinfo,
    3081             :                                  &pertrans->serialfn,
    3082             :                                  1,
    3083             :                                  InvalidOid,
    3084             :                                  (void *) aggstate, NULL);
    3085             :     }
    3086             : 
    3087       31026 :     if (OidIsValid(aggdeserialfn))
    3088             :     {
    3089          24 :         build_aggregate_deserialfn_expr(aggdeserialfn,
    3090             :                                         &deserialfnexpr);
    3091          24 :         fmgr_info(aggdeserialfn, &pertrans->deserialfn);
    3092          24 :         fmgr_info_set_expr((Node *) deserialfnexpr, &pertrans->deserialfn);
    3093             : 
    3094          24 :         pertrans->deserialfn_fcinfo =
    3095          24 :             (FunctionCallInfo) palloc(SizeForFunctionCallInfo(2));
    3096          24 :         InitFunctionCallInfoData(*pertrans->deserialfn_fcinfo,
    3097             :                                  &pertrans->deserialfn,
    3098             :                                  2,
    3099             :                                  InvalidOid,
    3100             :                                  (void *) aggstate, NULL);
    3101             : 
    3102             :     }
    3103             : 
    3104             :     /*
    3105             :      * If we're doing either DISTINCT or ORDER BY for a plain agg, then we
    3106             :      * have a list of SortGroupClause nodes; fish out the data in them and
    3107             :      * stick them into arrays.  We ignore ORDER BY for an ordered-set agg,
    3108             :      * however; the agg's transfn and finalfn are responsible for that.
    3109             :      *
    3110             :      * Note that by construction, if there is a DISTINCT clause then the ORDER
    3111             :      * BY clause is a prefix of it (see transformDistinctClause).
    3112             :      */
    3113       31026 :     if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
    3114             :     {
    3115         138 :         sortlist = NIL;
    3116         138 :         numSortCols = numDistinctCols = 0;
    3117             :     }
    3118       30888 :     else if (aggref->aggdistinct)
    3119             :     {
    3120         218 :         sortlist = aggref->aggdistinct;
    3121         218 :         numSortCols = numDistinctCols = list_length(sortlist);
    3122             :         Assert(numSortCols >= list_length(aggref->aggorder));
    3123             :     }
    3124             :     else
    3125             :     {
    3126       30670 :         sortlist = aggref->aggorder;
    3127       30670 :         numSortCols = list_length(sortlist);
    3128       30670 :         numDistinctCols = 0;
    3129             :     }
    3130             : 
    3131       31026 :     pertrans->numSortCols = numSortCols;
    3132       31026 :     pertrans->numDistinctCols = numDistinctCols;
    3133             : 
    3134             :     /*
    3135             :      * If we have either sorting or filtering to do, create a tupledesc and
    3136             :      * slot corresponding to the aggregated inputs (including sort
    3137             :      * expressions) of the agg.
    3138             :      */
    3139       31026 :     if (numSortCols > 0 || aggref->aggfilter)
    3140             :     {
    3141        9560 :         pertrans->sortdesc = ExecTypeFromTL(aggref->args);
    3142        9560 :         pertrans->sortslot =
    3143        9560 :             ExecInitExtraTupleSlot(estate, pertrans->sortdesc,
    3144             :                                    &TTSOpsMinimalTuple);
    3145             :     }
    3146             : 
    3147       31026 :     if (numSortCols > 0)
    3148             :     {
    3149             :         /*
    3150             :          * We don't implement DISTINCT or ORDER BY aggs in the HASHED case
    3151             :          * (yet)
    3152             :          */
    3153             :         Assert(aggstate->aggstrategy != AGG_HASHED && aggstate->aggstrategy != AGG_MIXED);
    3154             : 
    3155             :         /* If we have only one input, we need its len/byval info. */
    3156        9108 :         if (numInputs == 1)
    3157             :         {
    3158        1616 :             get_typlenbyval(inputTypes[numDirectArgs],
    3159             :                             &pertrans->inputtypeLen,
    3160             :                             &pertrans->inputtypeByVal);
    3161             :         }
    3162        7492 :         else if (numDistinctCols > 0)
    3163             :         {
    3164             :             /* we will need an extra slot to store prior values */
    3165          56 :             pertrans->uniqslot =
    3166          56 :                 ExecInitExtraTupleSlot(estate, pertrans->sortdesc,
    3167             :                                        &TTSOpsMinimalTuple);
    3168             :         }
    3169             : 
    3170             :         /* Extract the sort information for use later */
    3171        9108 :         pertrans->sortColIdx =
    3172        9108 :             (AttrNumber *) palloc(numSortCols * sizeof(AttrNumber));
    3173        9108 :         pertrans->sortOperators =
    3174        9108 :             (Oid *) palloc(numSortCols * sizeof(Oid));
    3175        9108 :         pertrans->sortCollations =
    3176        9108 :             (Oid *) palloc(numSortCols * sizeof(Oid));
    3177        9108 :         pertrans->sortNullsFirst =
    3178        9108 :             (bool *) palloc(numSortCols * sizeof(bool));
    3179             : 
    3180        9108 :         i = 0;
    3181       18340 :         foreach(lc, sortlist)
    3182             :         {
    3183        9232 :             SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc);
    3184        9232 :             TargetEntry *tle = get_sortgroupclause_tle(sortcl, aggref->args);
    3185             : 
    3186             :             /* the parser should have made sure of this */
    3187             :             Assert(OidIsValid(sortcl->sortop));
    3188             : 
    3189        9232 :             pertrans->sortColIdx[i] = tle->resno;
    3190        9232 :             pertrans->sortOperators[i] = sortcl->sortop;
    3191        9232 :             pertrans->sortCollations[i] = exprCollation((Node *) tle->expr);
    3192        9232 :             pertrans->sortNullsFirst[i] = sortcl->nulls_first;
    3193        9232 :             i++;
    3194             :         }
    3195             :         Assert(i == numSortCols);
    3196             :     }
    3197             : 
    3198       31026 :     if (aggref->aggdistinct)
    3199             :     {
    3200             :         Oid        *ops;
    3201             : 
    3202             :         Assert(numArguments > 0);
    3203             :         Assert(list_length(aggref->aggdistinct) == numDistinctCols);
    3204             : 
    3205         218 :         ops = palloc(numDistinctCols * sizeof(Oid));
    3206             : 
    3207         218 :         i = 0;
    3208         540 :         foreach(lc, aggref->aggdistinct)
    3209         322 :             ops[i++] = ((SortGroupClause *) lfirst(lc))->eqop;
    3210             : 
    3211             :         /* lookup / build the necessary comparators */
    3212         218 :         if (numDistinctCols == 1)
    3213         162 :             fmgr_info(get_opcode(ops[0]), &pertrans->equalfnOne);
    3214             :         else
    3215          56 :             pertrans->equalfnMulti =
    3216         112 :                 execTuplesMatchPrepare(pertrans->sortdesc,
    3217             :                                        numDistinctCols,
    3218          56 :                                        pertrans->sortColIdx,
    3219             :                                        ops,
    3220          56 :                                        pertrans->sortCollations,
    3221             :                                        &aggstate->ss.ps);
    3222         218 :         pfree(ops);
    3223             :     }
    3224             : 
    3225       31026 :     pertrans->sortstates = (Tuplesortstate **)
    3226       31026 :         palloc0(sizeof(Tuplesortstate *) * numGroupingSets);
    3227       31026 : }
    3228             : 
    3229             : 
    3230             : static Datum
    3231        9974 : GetAggInitVal(Datum textInitVal, Oid transtype)
    3232             : {
    3233             :     Oid         typinput,
    3234             :                 typioparam;
    3235             :     char       *strInitVal;
    3236             :     Datum       initVal;
    3237             : 
    3238        9974 :     getTypeInputInfo(transtype, &typinput, &typioparam);
    3239        9974 :     strInitVal = TextDatumGetCString(textInitVal);
    3240        9974 :     initVal = OidInputFunctionCall(typinput, strInitVal,
    3241             :                                    typioparam, -1);
    3242        9974 :     pfree(strInitVal);
    3243        9974 :     return initVal;
    3244             : }
    3245             : 
    3246             : /*
    3247             :  * find_compatible_peragg - search for a previously initialized per-Agg struct
    3248             :  *
    3249             :  * Searches the previously looked at aggregates to find one which is compatible
    3250             :  * with this one, with the same input parameters. If no compatible aggregate
    3251             :  * can be found, returns -1.
    3252             :  *
    3253             :  * As a side-effect, this also collects a list of existing, shareable per-Trans
    3254             :  * structs with matching inputs. If no identical Aggref is found, the list is
    3255             :  * passed later to find_compatible_pertrans, to see if we can at least reuse
    3256             :  * the state value of another aggregate.
    3257             :  */
    3258             : static int
    3259       31422 : find_compatible_peragg(Aggref *newagg, AggState *aggstate,
    3260             :                        int lastaggno, List **same_input_transnos)
    3261             : {
    3262             :     int         aggno;
    3263             :     AggStatePerAgg peraggs;
    3264             : 
    3265       31422 :     *same_input_transnos = NIL;
    3266             : 
    3267             :     /* we mustn't reuse the aggref if it contains volatile function calls */
    3268       31422 :     if (contain_volatile_functions((Node *) newagg))
    3269          32 :         return -1;
    3270             : 
    3271       31390 :     peraggs = aggstate->peragg;
    3272             : 
    3273             :     /*
    3274             :      * Search through the list of already seen aggregates. If we find an
    3275             :      * existing identical aggregate call, then we can re-use that one. While
    3276             :      * searching, we'll also collect a list of Aggrefs with the same input
    3277             :      * parameters. If no matching Aggref is found, the caller can potentially
    3278             :      * still re-use the transition state of one of them.  (At this stage we
    3279             :      * just compare the parsetrees; whether different aggregates share the
    3280             :      * same transition function will be checked later.)
    3281             :      */
    3282       37862 :     for (aggno = 0; aggno <= lastaggno; aggno++)
    3283             :     {
    3284             :         AggStatePerAgg peragg;
    3285             :         Aggref     *existingRef;
    3286             : 
    3287        6772 :         peragg = &peraggs[aggno];
    3288        6772 :         existingRef = peragg->aggref;
    3289             : 
    3290             :         /* all of the following must be the same or it's no match */
    3291       13088 :         if (newagg->inputcollid != existingRef->inputcollid ||
    3292        9100 :             newagg->aggtranstype != existingRef->aggtranstype ||
    3293        4410 :             newagg->aggstar != existingRef->aggstar ||
    3294        3252 :             newagg->aggvariadic != existingRef->aggvariadic ||
    3295        3220 :             newagg->aggkind != existingRef->aggkind ||
    3296        2254 :             !equal(newagg->args, existingRef->args) ||
    3297        1316 :             !equal(newagg->aggorder, existingRef->aggorder) ||
    3298        1312 :             !equal(newagg->aggdistinct, existingRef->aggdistinct) ||
    3299         656 :             !equal(newagg->aggfilter, existingRef->aggfilter))
    3300        6140 :             continue;
    3301             : 
    3302             :         /* if it's the same aggregate function then report exact match */
    3303         932 :         if (newagg->aggfnoid == existingRef->aggfnoid &&
    3304         600 :             newagg->aggtype == existingRef->aggtype &&
    3305         600 :             newagg->aggcollid == existingRef->aggcollid &&
    3306         300 :             equal(newagg->aggdirectargs, existingRef->aggdirectargs))
    3307             :         {
    3308         300 :             list_free(*same_input_transnos);
    3309         300 :             *same_input_transnos = NIL;
    3310         300 :             return aggno;
    3311             :         }
    3312             : 
    3313             :         /*
    3314             :          * Not identical, but it had the same inputs.  If the final function
    3315             :          * permits sharing, return its transno to the caller, in case we can
    3316             :          * re-use its per-trans state.  (If there's already sharing going on,
    3317             :          * we might report a transno more than once.  find_compatible_pertrans
    3318             :          * is cheap enough that it's not worth spending cycles to avoid that.)
    3319             :          */
    3320         332 :         if (peragg->shareable)
    3321         328 :             *same_input_transnos = lappend_int(*same_input_transnos,
    3322             :                                                peragg->transno);
    3323             :     }
    3324             : 
    3325       31090 :     return -1;
    3326             : }
    3327             : 
    3328             : /*
    3329             :  * find_compatible_pertrans - search for a previously initialized per-Trans
    3330             :  * struct
    3331             :  *
    3332             :  * Searches the list of transnos for a per-Trans struct with the same
    3333             :  * transition function and initial condition. (The inputs have already been
    3334             :  * verified to match.)
    3335             :  */
    3336             : static int
    3337       31118 : find_compatible_pertrans(AggState *aggstate, Aggref *newagg, bool shareable,
    3338             :                          Oid aggtransfn, Oid aggtranstype,
    3339             :                          Oid aggserialfn, Oid aggdeserialfn,
    3340             :                          Datum initValue, bool initValueIsNull,
    3341             :                          List *transnos)
    3342             : {
    3343             :     ListCell   *lc;
    3344             : 
    3345             :     /* If this aggregate can't share transition states, give up */
    3346       31118 :     if (!shareable)
    3347          68 :         return -1;
    3348             : 
    3349       31262 :     foreach(lc, transnos)
    3350             :     {
    3351         304 :         int         transno = lfirst_int(lc);
    3352         304 :         AggStatePerTrans pertrans = &aggstate->pertrans[transno];
    3353             : 
    3354             :         /*
    3355             :          * if the transfns or transition state types are not the same then the
    3356             :          * state can't be shared.
    3357             :          */
    3358         400 :         if (aggtransfn != pertrans->transfn_oid ||
    3359          96 :             aggtranstype != pertrans->aggtranstype)
    3360         208 :             continue;
    3361             : 
    3362             :         /*
    3363             :          * The serialization and deserialization functions must match, if
    3364             :          * present, as we're unable to share the trans state for aggregates
    3365             :          * which will serialize or deserialize into different formats.
    3366             :          * Remember that these will be InvalidOid if they're not required for
    3367             :          * this agg node.
    3368             :          */
    3369         192 :         if (aggserialfn != pertrans->serialfn_oid ||
    3370          96 :             aggdeserialfn != pertrans->deserialfn_oid)
    3371           0 :             continue;
    3372             : 
    3373             :         /*
    3374             :          * Check that the initial condition matches, too.
    3375             :          */
    3376          96 :         if (initValueIsNull && pertrans->initValueIsNull)
    3377         112 :             return transno;
    3378             : 
    3379         152 :         if (!initValueIsNull && !pertrans->initValueIsNull &&
    3380         152 :             datumIsEqual(initValue, pertrans->initValue,
    3381         152 :                          pertrans->transtypeByVal, pertrans->transtypeLen))
    3382          72 :             return transno;
    3383             :     }
    3384       30958 :     return -1;
    3385             : }
    3386             : 
    3387             : void
    3388       28718 : ExecEndAgg(AggState *node)
    3389             : {
    3390             :     PlanState  *outerPlan;
    3391             :     int         transno;
    3392       28718 :     int         numGroupingSets = Max(node->maxsets, 1);
    3393             :     int         setno;
    3394             : 
    3395             :     /* Make sure we have closed any open tuplesorts */
    3396             : 
    3397       28718 :     if (node->sort_in)
    3398          88 :         tuplesort_end(node->sort_in);
    3399       28718 :     if (node->sort_out)
    3400          20 :         tuplesort_end(node->sort_out);
    3401             : 
    3402       59694 :     for (transno = 0; transno < node->numtrans; transno++)
    3403             :     {
    3404       30976 :         AggStatePerTrans pertrans = &node->pertrans[transno];
    3405             : 
    3406       62548 :         for (setno = 0; setno < numGroupingSets; setno++)
    3407             :         {
    3408       31572 :             if (pertrans->sortstates[setno])
    3409           0 :                 tuplesort_end(pertrans->sortstates[setno]);
    3410             :         }
    3411             :     }
    3412             : 
    3413             :     /* And ensure any agg shutdown callbacks have been called */
    3414       57884 :     for (setno = 0; setno < numGroupingSets; setno++)
    3415       29166 :         ReScanExprContext(node->aggcontexts[setno]);
    3416       28718 :     if (node->hashcontext)
    3417        2818 :         ReScanExprContext(node->hashcontext);
    3418             : 
    3419             :     /*
    3420             :      * We don't actually free any ExprContexts here (see comment in
    3421             :      * ExecFreeExprContext), just unlinking the output one from the plan node
    3422             :      * suffices.
    3423             :      */
    3424       28718 :     ExecFreeExprContext(&node->ss.ps);
    3425             : 
    3426             :     /* clean up tuple table */
    3427       28718 :     ExecClearTuple(node->ss.ss_ScanTupleSlot);
    3428             : 
    3429       28718 :     outerPlan = outerPlanState(node);
    3430       28718 :     ExecEndNode(outerPlan);
    3431       28718 : }
    3432             : 
    3433             : void
    3434     1144282 : ExecReScanAgg(AggState *node)
    3435             : {
    3436     1144282 :     ExprContext *econtext = node->ss.ps.ps_ExprContext;
    3437     1144282 :     PlanState  *outerPlan = outerPlanState(node);
    3438     1144282 :     Agg        *aggnode = (Agg *) node->ss.ps.plan;
    3439             :     int         transno;
    3440     1144282 :     int         numGroupingSets = Max(node->maxsets, 1);
    3441             :     int         setno;
    3442             : 
    3443     1144282 :     node->agg_done = false;
    3444             : 
    3445     1144282 :     if (node->aggstrategy == AGG_HASHED)
    3446             :     {
    3447             :         /*
    3448             :          * In the hashed case, if we haven't yet built the hash table then we
    3449             :          * can just return; nothing done yet, so nothing to undo. If subnode's
    3450             :          * chgParam is not NULL then it will be re-scanned by ExecProcNode,
    3451             :          * else no reason to re-scan it at all.
    3452             :          */
    3453       37386 :         if (!node->table_filled)
    3454         338 :             return;
    3455             : 
    3456             :         /*
    3457             :          * If we do have the hash table, and the subplan does not have any
    3458             :          * parameter changes, and none of our own parameter changes affect
    3459             :          * input expressions of the aggregated functions, then we can just
    3460             :          * rescan the existing hash table; no need to build it again.
    3461             :          */
    3462       37612 :         if (outerPlan->chgParam == NULL &&
    3463         564 :             !bms_overlap(node->ss.ps.chgParam, aggnode->aggParams))
    3464             :         {
    3465         548 :             ResetTupleHashIterator(node->perhash[0].hashtable,
    3466             :                                    &node->perhash[0].hashiter);
    3467         548 :             select_current_set(node, 0, true);
    3468         548 :             return;
    3469             :         }
    3470             :     }
    3471             : 
    3472             :     /* Make sure we have closed any open tuplesorts */
    3473     2250312 :     for (transno = 0; transno < node->numtrans; transno++)
    3474             :     {
    3475     2213856 :         for (setno = 0; setno < numGroupingSets; setno++)
    3476             :         {
    3477     1106940 :             AggStatePerTrans pertrans = &node->pertrans[transno];
    3478             : 
    3479     1106940 :             if (pertrans->sortstates[setno])
    3480             :             {
    3481           0 :                 tuplesort_end(pertrans->sortstates[setno]);
    3482           0 :                 pertrans->sortstates[setno] = NULL;
    3483             :             }
    3484             :         }
    3485             :     }
    3486             : 
    3487             :     /*
    3488             :      * We don't need to ReScanExprContext the output tuple context here;
    3489             :      * ExecReScan already did it. But we do need to reset our per-grouping-set
    3490             :      * contexts, which may have transvalues stored in them. (We use rescan
    3491             :      * rather than just reset because transfns may have registered callbacks
    3492             :      * that need to be run now.) For the AGG_HASHED case, see below.
    3493             :      */
    3494             : 
    3495     2286816 :     for (setno = 0; setno < numGroupingSets; setno++)
    3496             :     {
    3497     1143420 :         ReScanExprContext(node->aggcontexts[setno]);
    3498             :     }
    3499             : 
    3500             :     /* Release first tuple of group, if we have made a copy */
    3501     1143396 :     if (node->grp_firstTuple != NULL)
    3502             :     {
    3503           0 :         heap_freetuple(node->grp_firstTuple);
    3504           0 :         node->grp_firstTuple = NULL;
    3505             :     }
    3506     1143396 :     ExecClearTuple(node->ss.ss_ScanTupleSlot);
    3507             : 
    3508             :     /* Forget current agg values */
    3509     1143396 :     MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numaggs);
    3510     1143396 :     MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numaggs);
    3511             : 
    3512             :     /*
    3513             :      * With AGG_HASHED/MIXED, the hash table is allocated in a sub-context of
    3514             :      * the hashcontext. This used to be an issue, but now, resetting a context
    3515             :      * automatically deletes sub-contexts too.
    3516             :      */
    3517     1143396 :     if (node->aggstrategy == AGG_HASHED || node->aggstrategy == AGG_MIXED)
    3518             :     {
    3519       36512 :         ReScanExprContext(node->hashcontext);
    3520             :         /* Rebuild an empty hash table */
    3521       36512 :         build_hash_table(node);
    3522       36512 :         node->table_filled = false;
    3523             :         /* iterator will be reset when the table is filled */
    3524             :     }
    3525             : 
    3526     1143396 :     if (node->aggstrategy != AGG_HASHED)
    3527             :     {
    3528             :         /*
    3529             :          * Reset the per-group state (in particular, mark transvalues null)
    3530             :          */
    3531     2213816 :         for (setno = 0; setno < numGroupingSets; setno++)
    3532             :         {
    3533     1106920 :             MemSet(node->pergroups[setno], 0,
    3534             :                    sizeof(AggStatePerGroupData) * node->numaggs);
    3535             :         }
    3536             : 
    3537             :         /* reset to phase 1 */
    3538     1106896 :         initialize_phase(node, 1);
    3539             : 
    3540     1106896 :         node->input_done = false;
    3541     1106896 :         node->projected_set = -1;
    3542             :     }
    3543             : 
    3544     1143396 :     if (outerPlan->chgParam == NULL)
    3545          96 :         ExecReScan(outerPlan);
    3546             : }
    3547             : 
    3548             : 
    3549             : /***********************************************************************
    3550             :  * API exposed to aggregate functions
    3551             :  ***********************************************************************/
    3552             : 
    3553             : 
    3554             : /*
    3555             :  * AggCheckCallContext - test if a SQL function is being called as an aggregate
    3556             :  *
    3557             :  * The transition and/or final functions of an aggregate may want to verify
    3558             :  * that they are being called as aggregates, rather than as plain SQL
    3559             :  * functions.  They should use this function to do so.  The return value
    3560             :  * is nonzero if being called as an aggregate, or zero if not.  (Specific
    3561             :  * nonzero values are AGG_CONTEXT_AGGREGATE or AGG_CONTEXT_WINDOW, but more
    3562             :  * values could conceivably appear in future.)
    3563             :  *
    3564             :  * If aggcontext isn't NULL, the function also stores at *aggcontext the
    3565             :  * identity of the memory context that aggregate transition values are being
    3566             :  * stored in.  Note that the same aggregate call site (flinfo) may be called
    3567             :  * interleaved on different transition values in different contexts, so it's
    3568             :  * not kosher to cache aggcontext under fn_extra.  It is, however, kosher to
    3569             :  * cache it in the transvalue itself (for internal-type transvalues).
    3570             :  */
    3571             : int
    3572     2213740 : AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
    3573             : {
    3574     2213740 :     if (fcinfo->context && IsA(fcinfo->context, AggState))
    3575             :     {
    3576     2164988 :         if (aggcontext)
    3577             :         {
    3578      450624 :             AggState   *aggstate = ((AggState *) fcinfo->context);
    3579      450624 :             ExprContext *cxt = aggstate->curaggcontext;
    3580             : 
    3581      450624 :             *aggcontext = cxt->ecxt_per_tuple_memory;
    3582             :         }
    3583     2164988 :         return AGG_CONTEXT_AGGREGATE;
    3584             :     }
    3585       48752 :     if (fcinfo->context && IsA(fcinfo->context, WindowAggState))
    3586             :     {
    3587       47696 :         if (aggcontext)
    3588         360 :             *aggcontext = ((WindowAggState *) fcinfo->context)->curaggcontext;
    3589       47696 :         return AGG_CONTEXT_WINDOW;
    3590             :     }
    3591             : 
    3592             :     /* this is just to prevent "uninitialized variable" warnings */
    3593        1056 :     if (aggcontext)
    3594        1024 :         *aggcontext = NULL;
    3595        1056 :     return 0;
    3596             : }
    3597             : 
    3598             : /*
    3599             :  * AggGetAggref - allow an aggregate support function to get its Aggref
    3600             :  *
    3601             :  * If the function is being called as an aggregate support function,
    3602             :  * return the Aggref node for the aggregate call.  Otherwise, return NULL.
    3603             :  *
    3604             :  * Aggregates sharing the same inputs and transition functions can get
    3605             :  * merged into a single transition calculation.  If the transition function
    3606             :  * calls AggGetAggref, it will get some one of the Aggrefs for which it is
    3607             :  * executing.  It must therefore not pay attention to the Aggref fields that
    3608             :  * relate to the final function, as those are indeterminate.  But if a final
    3609             :  * function calls AggGetAggref, it will get a precise result.
    3610             :  *
    3611             :  * Note that if an aggregate is being used as a window function, this will
    3612             :  * return NULL.  We could provide a similar function to return the relevant
    3613             :  * WindowFunc node in such cases, but it's not needed yet.
    3614             :  */
    3615             : Aggref *
    3616         134 : AggGetAggref(FunctionCallInfo fcinfo)
    3617             : {
    3618         134 :     if (fcinfo->context && IsA(fcinfo->context, AggState))
    3619             :     {
    3620         134 :         AggState   *aggstate = (AggState *) fcinfo->context;
    3621             :         AggStatePerAgg curperagg;
    3622             :         AggStatePerTrans curpertrans;
    3623             : 
    3624             :         /* check curperagg (valid when in a final function) */
    3625         134 :         curperagg = aggstate->curperagg;
    3626             : 
    3627         134 :         if (curperagg)
    3628           0 :             return curperagg->aggref;
    3629             : 
    3630             :         /* check curpertrans (valid when in a transition function) */
    3631         134 :         curpertrans = aggstate->curpertrans;
    3632             : 
    3633         134 :         if (curpertrans)
    3634         134 :             return curpertrans->aggref;
    3635             :     }
    3636           0 :     return NULL;
    3637             : }
    3638             : 
    3639             : /*
    3640             :  * AggGetTempMemoryContext - fetch short-term memory context for aggregates
    3641             :  *
    3642             :  * This is useful in agg final functions; the context returned is one that
    3643             :  * the final function can safely reset as desired.  This isn't useful for
    3644             :  * transition functions, since the context returned MAY (we don't promise)
    3645             :  * be the same as the context those are called in.
    3646             :  *
    3647             :  * As above, this is currently not useful for aggs called as window functions.
    3648             :  */
    3649             : MemoryContext
    3650           0 : AggGetTempMemoryContext(FunctionCallInfo fcinfo)
    3651             : {
    3652           0 :     if (fcinfo->context && IsA(fcinfo->context, AggState))
    3653             :     {
    3654           0 :         AggState   *aggstate = (AggState *) fcinfo->context;
    3655             : 
    3656           0 :         return aggstate->tmpcontext->ecxt_per_tuple_memory;
    3657             :     }
    3658           0 :     return NULL;
    3659             : }
    3660             : 
    3661             : /*
    3662             :  * AggStateIsShared - find out whether transition state is shared
    3663             :  *
    3664             :  * If the function is being called as an aggregate support function,
    3665             :  * return true if the aggregate's transition state is shared across
    3666             :  * multiple aggregates, false if it is not.
    3667             :  *
    3668             :  * Returns true if not called as an aggregate support function.
    3669             :  * This is intended as a conservative answer, ie "no you'd better not
    3670             :  * scribble on your input".  In particular, will return true if the
    3671             :  * aggregate is being used as a window function, which is a scenario
    3672             :  * in which changing the transition state is a bad idea.  We might
    3673             :  * want to refine the behavior for the window case in future.
    3674             :  */
    3675             : bool
    3676         134 : AggStateIsShared(FunctionCallInfo fcinfo)
    3677             : {
    3678         134 :     if (fcinfo->context && IsA(fcinfo->context, AggState))
    3679             :     {
    3680         134 :         AggState   *aggstate = (AggState *) fcinfo->context;
    3681             :         AggStatePerAgg curperagg;
    3682             :         AggStatePerTrans curpertrans;
    3683             : 
    3684             :         /* check curperagg (valid when in a final function) */
    3685         134 :         curperagg = aggstate->curperagg;
    3686             : 
    3687         134 :         if (curperagg)
    3688           0 :             return aggstate->pertrans[curperagg->transno].aggshared;
    3689             : 
    3690             :         /* check curpertrans (valid when in a transition function) */
    3691         134 :         curpertrans = aggstate->curpertrans;
    3692             : 
    3693         134 :         if (curpertrans)
    3694         134 :             return curpertrans->aggshared;
    3695             :     }
    3696           0 :     return true;
    3697             : }
    3698             : 
    3699             : /*
    3700             :  * AggRegisterCallback - register a cleanup callback for an aggregate
    3701             :  *
    3702             :  * This is useful for aggs to register shutdown callbacks, which will ensure
    3703             :  * that non-memory resources are freed.  The callback will occur just before
    3704             :  * the associated aggcontext (as returned by AggCheckCallContext) is reset,
    3705             :  * either between groups or as a result of rescanning the query.  The callback
    3706             :  * will NOT be called on error paths.  The typical use-case is for freeing of
    3707             :  * tuplestores or tuplesorts maintained in aggcontext, or pins held by slots
    3708             :  * created by the agg functions.  (The callback will not be called until after
    3709             :  * the result of the finalfn is no longer needed, so it's safe for the finalfn
    3710             :  * to return data that will be freed by the callback.)
    3711             :  *
    3712             :  * As above, this is currently not useful for aggs called as window functions.
    3713             :  */
    3714             : void
    3715         422 : AggRegisterCallback(FunctionCallInfo fcinfo,
    3716             :                     ExprContextCallbackFunction func,
    3717             :                     Datum arg)
    3718             : {
    3719         422 :     if (fcinfo->context && IsA(fcinfo->context, AggState))
    3720             :     {
    3721         422 :         AggState   *aggstate = (AggState *) fcinfo->context;
    3722         422 :         ExprContext *cxt = aggstate->curaggcontext;
    3723             : 
    3724         422 :         RegisterExprContextCallback(cxt, func, arg);
    3725             : 
    3726         422 :         return;
    3727             :     }
    3728           0 :     elog(ERROR, "aggregate function cannot register a callback in this context");
    3729             : }
    3730             : 
    3731             : 
    3732             : /*
    3733             :  * aggregate_dummy - dummy execution routine for aggregate functions
    3734             :  *
    3735             :  * This function is listed as the implementation (prosrc field) of pg_proc
    3736             :  * entries for aggregate functions.  Its only purpose is to throw an error
    3737             :  * if someone mistakenly executes such a function in the normal way.
    3738             :  *
    3739             :  * Perhaps someday we could assign real meaning to the prosrc field of
    3740             :  * an aggregate?
    3741             :  */
    3742             : Datum
    3743           0 : aggregate_dummy(PG_FUNCTION_ARGS)
    3744             : {
    3745           0 :     elog(ERROR, "aggregate function %u called as normal function",
    3746             :          fcinfo->flinfo->fn_oid);
    3747             :     return (Datum) 0;           /* keep compiler quiet */
    3748             : }

Generated by: LCOV version 1.13