PostgreSQL Source Code  git master
nodeAgg.h File Reference
#include "nodes/execnodes.h"
Include dependency graph for nodeAgg.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

AggStateExecInitAgg (Agg *node, EState *estate, int eflags)
 
void ExecEndAgg (AggState *node)
 
void ExecReScanAgg (AggState *node)
 
Size hash_agg_entry_size (int numAggs)
 
Datum aggregate_dummy (PG_FUNCTION_ARGS)
 

Function Documentation

◆ aggregate_dummy()

Datum aggregate_dummy ( PG_FUNCTION_ARGS  )

Definition at line 4298 of file nodeAgg.c.

References elog, and ERROR.

4299 {
4300  elog(ERROR, "aggregate function %u called as normal function",
4301  fcinfo->flinfo->fn_oid);
4302  return (Datum) 0; /* keep compiler quiet */
4303 }
#define ERROR
Definition: elog.h:43
uintptr_t Datum
Definition: postgres.h:372
#define elog
Definition: elog.h:219

◆ ExecEndAgg()

void ExecEndAgg ( AggState node)

Definition at line 3946 of file nodeAgg.c.

References AggState::aggcontexts, ExecClearTuple(), ExecEndNode(), ExecFreeExprContext(), AggState::hashcontext, Max, AggState::maxsets, AggState::numtrans, outerPlan, outerPlanState, AggState::pertrans, ScanState::ps, ReScanExprContext(), AggState::sort_in, AggState::sort_out, AggStatePerTransData::sortstates, AggState::ss, ScanState::ss_ScanTupleSlot, and tuplesort_end().

Referenced by ExecEndNode().

3947 {
3949  int transno;
3950  int numGroupingSets = Max(node->maxsets, 1);
3951  int setno;
3952 
3953  /* Make sure we have closed any open tuplesorts */
3954 
3955  if (node->sort_in)
3956  tuplesort_end(node->sort_in);
3957  if (node->sort_out)
3958  tuplesort_end(node->sort_out);
3959 
3960  for (transno = 0; transno < node->numtrans; transno++)
3961  {
3962  AggStatePerTrans pertrans = &node->pertrans[transno];
3963 
3964  for (setno = 0; setno < numGroupingSets; setno++)
3965  {
3966  if (pertrans->sortstates[setno])
3967  tuplesort_end(pertrans->sortstates[setno]);
3968  }
3969  }
3970 
3971  /* And ensure any agg shutdown callbacks have been called */
3972  for (setno = 0; setno < numGroupingSets; setno++)
3973  ReScanExprContext(node->aggcontexts[setno]);
3974  if (node->hashcontext)
3976 
3977  /*
3978  * We don't actually free any ExprContexts here (see comment in
3979  * ExecFreeExprContext), just unlinking the output one from the plan node
3980  * suffices.
3981  */
3982  ExecFreeExprContext(&node->ss.ps);
3983 
3984  /* clean up tuple table */
3986 
3987  outerPlan = outerPlanState(node);
3988  ExecEndNode(outerPlan);
3989 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:523
Tuplesortstate * sort_out
Definition: execnodes.h:1843
ScanState ss
Definition: execnodes.h:1816
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1116
AggStatePerTrans pertrans
Definition: execnodes.h:1826
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:603
int numtrans
Definition: execnodes.h:1819
PlanState ps
Definition: execnodes.h:1113
int maxsets
Definition: execnodes.h:1840
Tuplesortstate * sort_in
Definition: execnodes.h:1842
#define outerPlanState(node)
Definition: execnodes.h:896
Tuplesortstate ** sortstates
Definition: nodeAgg.c:382
#define outerPlan(node)
Definition: plannodes.h:174
ExprContext * hashcontext
Definition: execnodes.h:1827
#define Max(x, y)
Definition: c.h:796
ExprContext ** aggcontexts
Definition: execnodes.h:1828
void ReScanExprContext(ExprContext *econtext)
Definition: execUtils.c:384
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1104

◆ ExecInitAgg()

AggState* ExecInitAgg ( Agg node,
EState estate,
int  eflags 
)

Definition at line 2708 of file nodeAgg.c.

References ACL_EXECUTE, ACL_KIND_PROC, aclcheck_error(), ACLCHECK_OK, AggState::agg_done, AGG_HASHED, AGG_MIXED, AGG_SORTED, AggState::aggcontexts, Aggref::aggdirectargs, AggStatePerAggData::aggdirectargs, Aggref::aggfilter, AGGFNOID, Aggref::aggfnoid, Aggref::agglevelsup, AGGMODIFY_READ_WRITE, AggrefExprState::aggno, AggStatePerPhaseData::aggnode, AggStatePerHashData::aggnode, AggStatePerTransData::aggref, AggStatePerAggData::aggref, AggrefExprState::aggref, AggState::aggs, AggStatePerTransData::aggshared, Aggref::aggsplit, Agg::aggsplit, AggState::aggsplit, AggStatePerPhaseData::aggstrategy, Agg::aggstrategy, AggState::aggstrategy, AggStatePerTransData::aggtranstype, Aggref::aggtranstype, Aggref::aggtype, Anum_pg_aggregate_agginitval, arg, Aggref::args, Assert, bms_add_member(), bms_add_members(), bms_next_member(), build_aggregate_finalfn_expr(), build_hash_table(), build_pertrans_for_aggref(), castNode, Agg::chain, AggState::curperagg, AggState::curpertrans, AggState::current_set, AggStatePerTransData::deserialfn_oid, DO_AGGSPLIT_COMBINE, DO_AGGSPLIT_DESERIALIZE, DO_AGGSPLIT_SERIALIZE, DO_AGGSPLIT_SKIPFINAL, ExprContext::ecxt_aggnulls, ExprContext::ecxt_aggvalues, elog, AggStatePerPhaseData::eqfunctions, ereport, errcode(), errmsg(), ERROR, AggStatePerTransData::evalproj, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, EXEC_FLAG_REWIND, ExecAgg(), ExecAssignExprContext(), ExecAssignProjectionInfo(), ExecAssignResultTypeFromTL(), ExecAssignScanTypeFromOuterPlan(), ExecBuildProjectionInfo(), ExecInitExprList(), ExecInitExtraTupleSlot(), ExecInitNode(), ExecInitQual(), ExecInitResultTupleSlot(), ExecInitScanTupleSlot(), PlanState::ExecProcNode, ExecSetSlotDescriptor(), execTuplesHashPrepare(), execTuplesMatchPrepare(), ExecTypeFromTL(), AggStatePerAggData::finalfn, AggStatePerAggData::finalfn_oid, find_compatible_peragg(), find_compatible_pertrans(), find_hash_columns(), flatCopyTargetEntry(), fmgr_info(), fmgr_info_set_expr, FUNC_MAX_ARGS, get_aggregate_argtypes(), get_func_name(), get_typlenbyval(), GetAggInitVal(), GETSTRUCT, GetUserId(), AggStatePerPhaseData::grouped_cols, Agg::groupingSets, AggState::grp_firstTuple, Agg::grpColIdx, Agg::grpOperators, AggStatePerPhaseData::gset_lengths, AggState::hashcontext, HeapTupleIsValid, i, initialize_phase(), AggStatePerTransData::initValue, AggStatePerTransData::initValueIsNull, AggState::input_done, Aggref::inputcollid, AggStatePerTransData::inputoff, INTERNALOID, InvalidOid, InvokeFunctionExecuteHook, lappend(), lcons_int(), Plan::lefttree, lfirst, lfirst_node, list_length(), list_nth_node, makeNode, makeTargetEntry(), Max, AggState::maxsets, NIL, AggState::numaggs, AggStatePerHashData::numCols, Agg::numCols, AggStatePerAggData::numFinalArgs, AggState::numphases, AggStatePerPhaseData::numsets, AggState::numtrans, ObjectIdGetDatum, OidIsValid, outerPlan, outerPlanState, palloc(), palloc0(), AggState::peragg, AggState::pergroup, AggState::pertrans, pg_proc_aclcheck(), Agg::plan, PlanState::plan, PROCOID, AggState::projected_set, ScanState::ps, PlanState::ps_ExprContext, Plan::qual, PlanState::qual, ReleaseSysCache(), TargetEntry::resno, AggStatePerAggData::resulttypeByVal, AggStatePerAggData::resulttypeLen, SearchSysCache1(), select_current_set(), AggStatePerTransData::serialfn_oid, AggStatePerAggData::sharable, AggState::sort_in, AggState::sort_out, AggState::sort_slot, AggStatePerPhaseData::sortnode, AggStatePerTransData::sortslot, AggState::ss, PlanState::state, SysCacheGetAttr(), AggState::tmpcontext, AggStatePerTransData::transfn_oid, and AggStatePerAggData::transno.

Referenced by ExecInitNode().

2709 {
2710  AggState *aggstate;
2711  AggStatePerAgg peraggs;
2712  AggStatePerTrans pertransstates;
2713  Plan *outerPlan;
2714  ExprContext *econtext;
2715  int numaggs,
2716  transno,
2717  aggno;
2718  int phase;
2719  int phaseidx;
2720  List *combined_inputeval;
2721  TupleDesc combineddesc;
2722  TupleTableSlot *combinedslot;
2723  ListCell *l;
2724  Bitmapset *all_grouped_cols = NULL;
2725  int numGroupingSets = 1;
2726  int numPhases;
2727  int numHashes;
2728  int column_offset;
2729  int i = 0;
2730  int j = 0;
2731  bool use_hashing = (node->aggstrategy == AGG_HASHED ||
2732  node->aggstrategy == AGG_MIXED);
2733 
2734  /* check for unsupported flags */
2735  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
2736 
2737  /*
2738  * create state structure
2739  */
2740  aggstate = makeNode(AggState);
2741  aggstate->ss.ps.plan = (Plan *) node;
2742  aggstate->ss.ps.state = estate;
2743  aggstate->ss.ps.ExecProcNode = ExecAgg;
2744 
2745  aggstate->aggs = NIL;
2746  aggstate->numaggs = 0;
2747  aggstate->numtrans = 0;
2748  aggstate->aggstrategy = node->aggstrategy;
2749  aggstate->aggsplit = node->aggsplit;
2750  aggstate->maxsets = 0;
2751  aggstate->projected_set = -1;
2752  aggstate->current_set = 0;
2753  aggstate->peragg = NULL;
2754  aggstate->pertrans = NULL;
2755  aggstate->curperagg = NULL;
2756  aggstate->curpertrans = NULL;
2757  aggstate->input_done = false;
2758  aggstate->agg_done = false;
2759  aggstate->pergroup = NULL;
2760  aggstate->grp_firstTuple = NULL;
2761  aggstate->sort_in = NULL;
2762  aggstate->sort_out = NULL;
2763 
2764  /*
2765  * phases[0] always exists, but is dummy in sorted/plain mode
2766  */
2767  numPhases = (use_hashing ? 1 : 2);
2768  numHashes = (use_hashing ? 1 : 0);
2769 
2770  /*
2771  * Calculate the maximum number of grouping sets in any phase; this
2772  * determines the size of some allocations. Also calculate the number of
2773  * phases, since all hashed/mixed nodes contribute to only a single phase.
2774  */
2775  if (node->groupingSets)
2776  {
2777  numGroupingSets = list_length(node->groupingSets);
2778 
2779  foreach(l, node->chain)
2780  {
2781  Agg *agg = lfirst(l);
2782 
2783  numGroupingSets = Max(numGroupingSets,
2784  list_length(agg->groupingSets));
2785 
2786  /*
2787  * additional AGG_HASHED aggs become part of phase 0, but all
2788  * others add an extra phase.
2789  */
2790  if (agg->aggstrategy != AGG_HASHED)
2791  ++numPhases;
2792  else
2793  ++numHashes;
2794  }
2795  }
2796 
2797  aggstate->maxsets = numGroupingSets;
2798  aggstate->numphases = numPhases;
2799 
2800  aggstate->aggcontexts = (ExprContext **)
2801  palloc0(sizeof(ExprContext *) * numGroupingSets);
2802 
2803  /*
2804  * Create expression contexts. We need three or more, one for
2805  * per-input-tuple processing, one for per-output-tuple processing, one
2806  * for all the hashtables, and one for each grouping set. The per-tuple
2807  * memory context of the per-grouping-set ExprContexts (aggcontexts)
2808  * replaces the standalone memory context formerly used to hold transition
2809  * values. We cheat a little by using ExecAssignExprContext() to build
2810  * all of them.
2811  *
2812  * NOTE: the details of what is stored in aggcontexts and what is stored
2813  * in the regular per-query memory context are driven by a simple
2814  * decision: we want to reset the aggcontext at group boundaries (if not
2815  * hashing) and in ExecReScanAgg to recover no-longer-wanted space.
2816  */
2817  ExecAssignExprContext(estate, &aggstate->ss.ps);
2818  aggstate->tmpcontext = aggstate->ss.ps.ps_ExprContext;
2819 
2820  for (i = 0; i < numGroupingSets; ++i)
2821  {
2822  ExecAssignExprContext(estate, &aggstate->ss.ps);
2823  aggstate->aggcontexts[i] = aggstate->ss.ps.ps_ExprContext;
2824  }
2825 
2826  if (use_hashing)
2827  {
2828  ExecAssignExprContext(estate, &aggstate->ss.ps);
2829  aggstate->hashcontext = aggstate->ss.ps.ps_ExprContext;
2830  }
2831 
2832  ExecAssignExprContext(estate, &aggstate->ss.ps);
2833 
2834  /*
2835  * tuple table initialization.
2836  *
2837  * For hashtables, we create some additional slots below.
2838  */
2839  ExecInitScanTupleSlot(estate, &aggstate->ss);
2840  ExecInitResultTupleSlot(estate, &aggstate->ss.ps);
2841  aggstate->sort_slot = ExecInitExtraTupleSlot(estate);
2842 
2843  /*
2844  * initialize child expressions
2845  *
2846  * We expect the parser to have checked that no aggs contain other agg
2847  * calls in their arguments (and just to be sure, we verify it again while
2848  * initializing the plan node). This would make no sense under SQL
2849  * semantics, and it's forbidden by the spec. Because it is true, we
2850  * don't need to worry about evaluating the aggs in any particular order.
2851  *
2852  * Note: execExpr.c finds Aggrefs for us, and adds their AggrefExprState
2853  * nodes to aggstate->aggs. Aggrefs in the qual are found here; Aggrefs
2854  * in the targetlist are found during ExecAssignProjectionInfo, below.
2855  */
2856  aggstate->ss.ps.qual =
2857  ExecInitQual(node->plan.qual, (PlanState *) aggstate);
2858 
2859  /*
2860  * Initialize child nodes.
2861  *
2862  * If we are doing a hashed aggregation then the child plan does not need
2863  * to handle REWIND efficiently; see ExecReScanAgg.
2864  */
2865  if (node->aggstrategy == AGG_HASHED)
2866  eflags &= ~EXEC_FLAG_REWIND;
2867  outerPlan = outerPlan(node);
2868  outerPlanState(aggstate) = ExecInitNode(outerPlan, estate, eflags);
2869 
2870  /*
2871  * initialize source tuple type.
2872  */
2873  ExecAssignScanTypeFromOuterPlan(&aggstate->ss);
2874  if (node->chain)
2875  ExecSetSlotDescriptor(aggstate->sort_slot,
2877 
2878  /*
2879  * Initialize result tuple type and projection info.
2880  */
2881  ExecAssignResultTypeFromTL(&aggstate->ss.ps);
2882  ExecAssignProjectionInfo(&aggstate->ss.ps, NULL);
2883 
2884  /*
2885  * We should now have found all Aggrefs in the targetlist and quals.
2886  */
2887  numaggs = aggstate->numaggs;
2888  Assert(numaggs == list_length(aggstate->aggs));
2889 
2890  /*
2891  * For each phase, prepare grouping set data and fmgr lookup data for
2892  * compare functions. Accumulate all_grouped_cols in passing.
2893  */
2894  aggstate->phases = palloc0(numPhases * sizeof(AggStatePerPhaseData));
2895 
2896  aggstate->num_hashes = numHashes;
2897  if (numHashes)
2898  {
2899  aggstate->perhash = palloc0(sizeof(AggStatePerHashData) * numHashes);
2900  aggstate->phases[0].numsets = 0;
2901  aggstate->phases[0].gset_lengths = palloc(numHashes * sizeof(int));
2902  aggstate->phases[0].grouped_cols = palloc(numHashes * sizeof(Bitmapset *));
2903  }
2904 
2905  phase = 0;
2906  for (phaseidx = 0; phaseidx <= list_length(node->chain); ++phaseidx)
2907  {
2908  Agg *aggnode;
2909  Sort *sortnode;
2910 
2911  if (phaseidx > 0)
2912  {
2913  aggnode = list_nth_node(Agg, node->chain, phaseidx - 1);
2914  sortnode = castNode(Sort, aggnode->plan.lefttree);
2915  }
2916  else
2917  {
2918  aggnode = node;
2919  sortnode = NULL;
2920  }
2921 
2922  Assert(phase <= 1 || sortnode);
2923 
2924  if (aggnode->aggstrategy == AGG_HASHED
2925  || aggnode->aggstrategy == AGG_MIXED)
2926  {
2927  AggStatePerPhase phasedata = &aggstate->phases[0];
2928  AggStatePerHash perhash;
2929  Bitmapset *cols = NULL;
2930 
2931  Assert(phase == 0);
2932  i = phasedata->numsets++;
2933  perhash = &aggstate->perhash[i];
2934 
2935  /* phase 0 always points to the "real" Agg in the hash case */
2936  phasedata->aggnode = node;
2937  phasedata->aggstrategy = node->aggstrategy;
2938 
2939  /* but the actual Agg node representing this hash is saved here */
2940  perhash->aggnode = aggnode;
2941 
2942  phasedata->gset_lengths[i] = perhash->numCols = aggnode->numCols;
2943 
2944  for (j = 0; j < aggnode->numCols; ++j)
2945  cols = bms_add_member(cols, aggnode->grpColIdx[j]);
2946 
2947  phasedata->grouped_cols[i] = cols;
2948 
2949  all_grouped_cols = bms_add_members(all_grouped_cols, cols);
2950  continue;
2951  }
2952  else
2953  {
2954  AggStatePerPhase phasedata = &aggstate->phases[++phase];
2955  int num_sets;
2956 
2957  phasedata->numsets = num_sets = list_length(aggnode->groupingSets);
2958 
2959  if (num_sets)
2960  {
2961  phasedata->gset_lengths = palloc(num_sets * sizeof(int));
2962  phasedata->grouped_cols = palloc(num_sets * sizeof(Bitmapset *));
2963 
2964  i = 0;
2965  foreach(l, aggnode->groupingSets)
2966  {
2967  int current_length = list_length(lfirst(l));
2968  Bitmapset *cols = NULL;
2969 
2970  /* planner forces this to be correct */
2971  for (j = 0; j < current_length; ++j)
2972  cols = bms_add_member(cols, aggnode->grpColIdx[j]);
2973 
2974  phasedata->grouped_cols[i] = cols;
2975  phasedata->gset_lengths[i] = current_length;
2976 
2977  ++i;
2978  }
2979 
2980  all_grouped_cols = bms_add_members(all_grouped_cols,
2981  phasedata->grouped_cols[0]);
2982  }
2983  else
2984  {
2985  Assert(phaseidx == 0);
2986 
2987  phasedata->gset_lengths = NULL;
2988  phasedata->grouped_cols = NULL;
2989  }
2990 
2991  /*
2992  * If we are grouping, precompute fmgr lookup data for inner loop.
2993  */
2994  if (aggnode->aggstrategy == AGG_SORTED)
2995  {
2996  Assert(aggnode->numCols > 0);
2997 
2998  phasedata->eqfunctions =
3000  aggnode->grpOperators);
3001  }
3002 
3003  phasedata->aggnode = aggnode;
3004  phasedata->aggstrategy = aggnode->aggstrategy;
3005  phasedata->sortnode = sortnode;
3006  }
3007  }
3008 
3009  /*
3010  * Convert all_grouped_cols to a descending-order list.
3011  */
3012  i = -1;
3013  while ((i = bms_next_member(all_grouped_cols, i)) >= 0)
3014  aggstate->all_grouped_cols = lcons_int(i, aggstate->all_grouped_cols);
3015 
3016  /*
3017  * Set up aggregate-result storage in the output expr context, and also
3018  * allocate my private per-agg working storage
3019  */
3020  econtext = aggstate->ss.ps.ps_ExprContext;
3021  econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs);
3022  econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs);
3023 
3024  peraggs = (AggStatePerAgg) palloc0(sizeof(AggStatePerAggData) * numaggs);
3025  pertransstates = (AggStatePerTrans) palloc0(sizeof(AggStatePerTransData) * numaggs);
3026 
3027  aggstate->peragg = peraggs;
3028  aggstate->pertrans = pertransstates;
3029 
3030  /*
3031  * Hashing can only appear in the initial phase.
3032  */
3033  if (use_hashing)
3034  {
3035  for (i = 0; i < numHashes; ++i)
3036  {
3037  aggstate->perhash[i].hashslot = ExecInitExtraTupleSlot(estate);
3038 
3039  execTuplesHashPrepare(aggstate->perhash[i].numCols,
3040  aggstate->perhash[i].aggnode->grpOperators,
3041  &aggstate->perhash[i].eqfunctions,
3042  &aggstate->perhash[i].hashfunctions);
3043  }
3044 
3045  /* this is an array of pointers, not structures */
3046  aggstate->hash_pergroup = palloc0(sizeof(AggStatePerGroup) * numHashes);
3047 
3048  find_hash_columns(aggstate);
3049  build_hash_table(aggstate);
3050  aggstate->table_filled = false;
3051  }
3052 
3053  if (node->aggstrategy != AGG_HASHED)
3054  {
3055  AggStatePerGroup pergroup;
3056 
3057  pergroup = (AggStatePerGroup) palloc0(sizeof(AggStatePerGroupData)
3058  * numaggs
3059  * numGroupingSets);
3060 
3061  aggstate->pergroup = pergroup;
3062  }
3063 
3064  /*
3065  * Initialize current phase-dependent values to initial phase. The initial
3066  * phase is 1 (first sort pass) for all strategies that use sorting (if
3067  * hashing is being done too, then phase 0 is processed last); but if only
3068  * hashing is being done, then phase 0 is all there is.
3069  */
3070  if (node->aggstrategy == AGG_HASHED)
3071  {
3072  aggstate->current_phase = 0;
3073  initialize_phase(aggstate, 0);
3074  select_current_set(aggstate, 0, true);
3075  }
3076  else
3077  {
3078  aggstate->current_phase = 1;
3079  initialize_phase(aggstate, 1);
3080  select_current_set(aggstate, 0, false);
3081  }
3082 
3083  /* -----------------
3084  * Perform lookups of aggregate function info, and initialize the
3085  * unchanging fields of the per-agg and per-trans data.
3086  *
3087  * We try to optimize by detecting duplicate aggregate functions so that
3088  * their state and final values are re-used, rather than needlessly being
3089  * re-calculated independently. We also detect aggregates that are not
3090  * the same, but which can share the same transition state.
3091  *
3092  * Scenarios:
3093  *
3094  * 1. Identical aggregate function calls appear in the query:
3095  *
3096  * SELECT SUM(x) FROM ... HAVING SUM(x) > 0
3097  *
3098  * Since these aggregates are identical, we only need to calculate
3099  * the value once. Both aggregates will share the same 'aggno' value.
3100  *
3101  * 2. Two different aggregate functions appear in the query, but the
3102  * aggregates have the same arguments, transition functions and
3103  * initial values (and, presumably, different final functions):
3104  *
3105  * SELECT AVG(x), STDDEV(x) FROM ...
3106  *
3107  * In this case we must create a new peragg for the varying aggregate,
3108  * and we need to call the final functions separately, but we need
3109  * only run the transition function once. (This requires that the
3110  * final functions be nondestructive of the transition state, but
3111  * that's required anyway for other reasons.)
3112  *
3113  * For either of these optimizations to be valid, all aggregate properties
3114  * used in the transition phase must be the same, including any modifiers
3115  * such as ORDER BY, DISTINCT and FILTER, and the arguments mustn't
3116  * contain any volatile functions.
3117  * -----------------
3118  */
3119  aggno = -1;
3120  transno = -1;
3121  foreach(l, aggstate->aggs)
3122  {
3123  AggrefExprState *aggrefstate = (AggrefExprState *) lfirst(l);
3124  Aggref *aggref = aggrefstate->aggref;
3125  AggStatePerAgg peragg;
3126  AggStatePerTrans pertrans;
3127  int existing_aggno;
3128  int existing_transno;
3129  List *same_input_transnos;
3130  Oid inputTypes[FUNC_MAX_ARGS];
3131  int numArguments;
3132  int numDirectArgs;
3133  HeapTuple aggTuple;
3134  Form_pg_aggregate aggform;
3135  AclResult aclresult;
3136  Oid transfn_oid,
3137  finalfn_oid;
3138  bool sharable;
3139  Oid serialfn_oid,
3140  deserialfn_oid;
3141  Expr *finalfnexpr;
3142  Oid aggtranstype;
3143  Datum textInitVal;
3144  Datum initValue;
3145  bool initValueIsNull;
3146 
3147  /* Planner should have assigned aggregate to correct level */
3148  Assert(aggref->agglevelsup == 0);
3149  /* ... and the split mode should match */
3150  Assert(aggref->aggsplit == aggstate->aggsplit);
3151 
3152  /* 1. Check for already processed aggs which can be re-used */
3153  existing_aggno = find_compatible_peragg(aggref, aggstate, aggno,
3154  &same_input_transnos);
3155  if (existing_aggno != -1)
3156  {
3157  /*
3158  * Existing compatible agg found. so just point the Aggref to the
3159  * same per-agg struct.
3160  */
3161  aggrefstate->aggno = existing_aggno;
3162  continue;
3163  }
3164 
3165  /* Mark Aggref state node with assigned index in the result array */
3166  peragg = &peraggs[++aggno];
3167  peragg->aggref = aggref;
3168  aggrefstate->aggno = aggno;
3169 
3170  /* Fetch the pg_aggregate row */
3171  aggTuple = SearchSysCache1(AGGFNOID,
3172  ObjectIdGetDatum(aggref->aggfnoid));
3173  if (!HeapTupleIsValid(aggTuple))
3174  elog(ERROR, "cache lookup failed for aggregate %u",
3175  aggref->aggfnoid);
3176  aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);
3177 
3178  /* Check permission to call aggregate function */
3179  aclresult = pg_proc_aclcheck(aggref->aggfnoid, GetUserId(),
3180  ACL_EXECUTE);
3181  if (aclresult != ACLCHECK_OK)
3182  aclcheck_error(aclresult, ACL_KIND_PROC,
3183  get_func_name(aggref->aggfnoid));
3185 
3186  /* planner recorded transition state type in the Aggref itself */
3187  aggtranstype = aggref->aggtranstype;
3188  Assert(OidIsValid(aggtranstype));
3189 
3190  /*
3191  * If this aggregation is performing state combines, then instead of
3192  * using the transition function, we'll use the combine function
3193  */
3194  if (DO_AGGSPLIT_COMBINE(aggstate->aggsplit))
3195  {
3196  transfn_oid = aggform->aggcombinefn;
3197 
3198  /* If not set then the planner messed up */
3199  if (!OidIsValid(transfn_oid))
3200  elog(ERROR, "combinefn not set for aggregate function");
3201  }
3202  else
3203  transfn_oid = aggform->aggtransfn;
3204 
3205  /* Final function only required if we're finalizing the aggregates */
3206  if (DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit))
3207  peragg->finalfn_oid = finalfn_oid = InvalidOid;
3208  else
3209  peragg->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
3210 
3211  /*
3212  * If finalfn is marked read-write, we can't share transition states;
3213  * but it is okay to share states for AGGMODIFY_SHARABLE aggs. Also,
3214  * if we're not executing the finalfn here, we can share regardless.
3215  */
3216  sharable = (aggform->aggfinalmodify != AGGMODIFY_READ_WRITE) ||
3217  (finalfn_oid == InvalidOid);
3218  peragg->sharable = sharable;
3219 
3220  serialfn_oid = InvalidOid;
3221  deserialfn_oid = InvalidOid;
3222 
3223  /*
3224  * Check if serialization/deserialization is required. We only do it
3225  * for aggregates that have transtype INTERNAL.
3226  */
3227  if (aggtranstype == INTERNALOID)
3228  {
3229  /*
3230  * The planner should only have generated a serialize agg node if
3231  * every aggregate with an INTERNAL state has a serialization
3232  * function. Verify that.
3233  */
3234  if (DO_AGGSPLIT_SERIALIZE(aggstate->aggsplit))
3235  {
3236  /* serialization only valid when not running finalfn */
3238 
3239  if (!OidIsValid(aggform->aggserialfn))
3240  elog(ERROR, "serialfunc not provided for serialization aggregation");
3241  serialfn_oid = aggform->aggserialfn;
3242  }
3243 
3244  /* Likewise for deserialization functions */
3245  if (DO_AGGSPLIT_DESERIALIZE(aggstate->aggsplit))
3246  {
3247  /* deserialization only valid when combining states */
3248  Assert(DO_AGGSPLIT_COMBINE(aggstate->aggsplit));
3249 
3250  if (!OidIsValid(aggform->aggdeserialfn))
3251  elog(ERROR, "deserialfunc not provided for deserialization aggregation");
3252  deserialfn_oid = aggform->aggdeserialfn;
3253  }
3254  }
3255 
3256  /* Check that aggregate owner has permission to call component fns */
3257  {
3258  HeapTuple procTuple;
3259  Oid aggOwner;
3260 
3261  procTuple = SearchSysCache1(PROCOID,
3262  ObjectIdGetDatum(aggref->aggfnoid));
3263  if (!HeapTupleIsValid(procTuple))
3264  elog(ERROR, "cache lookup failed for function %u",
3265  aggref->aggfnoid);
3266  aggOwner = ((Form_pg_proc) GETSTRUCT(procTuple))->proowner;
3267  ReleaseSysCache(procTuple);
3268 
3269  aclresult = pg_proc_aclcheck(transfn_oid, aggOwner,
3270  ACL_EXECUTE);
3271  if (aclresult != ACLCHECK_OK)
3272  aclcheck_error(aclresult, ACL_KIND_PROC,
3273  get_func_name(transfn_oid));
3274  InvokeFunctionExecuteHook(transfn_oid);
3275  if (OidIsValid(finalfn_oid))
3276  {
3277  aclresult = pg_proc_aclcheck(finalfn_oid, aggOwner,
3278  ACL_EXECUTE);
3279  if (aclresult != ACLCHECK_OK)
3280  aclcheck_error(aclresult, ACL_KIND_PROC,
3281  get_func_name(finalfn_oid));
3282  InvokeFunctionExecuteHook(finalfn_oid);
3283  }
3284  if (OidIsValid(serialfn_oid))
3285  {
3286  aclresult = pg_proc_aclcheck(serialfn_oid, aggOwner,
3287  ACL_EXECUTE);
3288  if (aclresult != ACLCHECK_OK)
3289  aclcheck_error(aclresult, ACL_KIND_PROC,
3290  get_func_name(serialfn_oid));
3291  InvokeFunctionExecuteHook(serialfn_oid);
3292  }
3293  if (OidIsValid(deserialfn_oid))
3294  {
3295  aclresult = pg_proc_aclcheck(deserialfn_oid, aggOwner,
3296  ACL_EXECUTE);
3297  if (aclresult != ACLCHECK_OK)
3298  aclcheck_error(aclresult, ACL_KIND_PROC,
3299  get_func_name(deserialfn_oid));
3300  InvokeFunctionExecuteHook(deserialfn_oid);
3301  }
3302  }
3303 
3304  /*
3305  * Get actual datatypes of the (nominal) aggregate inputs. These
3306  * could be different from the agg's declared input types, when the
3307  * agg accepts ANY or a polymorphic type.
3308  */
3309  numArguments = get_aggregate_argtypes(aggref, inputTypes);
3310 
3311  /* Count the "direct" arguments, if any */
3312  numDirectArgs = list_length(aggref->aggdirectargs);
3313 
3314  /* Detect how many arguments to pass to the finalfn */
3315  if (aggform->aggfinalextra)
3316  peragg->numFinalArgs = numArguments + 1;
3317  else
3318  peragg->numFinalArgs = numDirectArgs + 1;
3319 
3320  /* Initialize any direct-argument expressions */
3321  peragg->aggdirectargs = ExecInitExprList(aggref->aggdirectargs,
3322  (PlanState *) aggstate);
3323 
3324  /*
3325  * build expression trees using actual argument & result types for the
3326  * finalfn, if it exists and is required.
3327  */
3328  if (OidIsValid(finalfn_oid))
3329  {
3330  build_aggregate_finalfn_expr(inputTypes,
3331  peragg->numFinalArgs,
3332  aggtranstype,
3333  aggref->aggtype,
3334  aggref->inputcollid,
3335  finalfn_oid,
3336  &finalfnexpr);
3337  fmgr_info(finalfn_oid, &peragg->finalfn);
3338  fmgr_info_set_expr((Node *) finalfnexpr, &peragg->finalfn);
3339  }
3340 
3341  /* get info about the output value's datatype */
3342  get_typlenbyval(aggref->aggtype,
3343  &peragg->resulttypeLen,
3344  &peragg->resulttypeByVal);
3345 
3346  /*
3347  * initval is potentially null, so don't try to access it as a struct
3348  * field. Must do it the hard way with SysCacheGetAttr.
3349  */
3350  textInitVal = SysCacheGetAttr(AGGFNOID, aggTuple,
3352  &initValueIsNull);
3353  if (initValueIsNull)
3354  initValue = (Datum) 0;
3355  else
3356  initValue = GetAggInitVal(textInitVal, aggtranstype);
3357 
3358  /*
3359  * 2. Build working state for invoking the transition function, or
3360  * look up previously initialized working state, if we can share it.
3361  *
3362  * find_compatible_peragg() already collected a list of sharable
3363  * per-Trans's with the same inputs. Check if any of them have the
3364  * same transition function and initial value.
3365  */
3366  existing_transno = find_compatible_pertrans(aggstate, aggref,
3367  sharable,
3368  transfn_oid, aggtranstype,
3369  serialfn_oid, deserialfn_oid,
3370  initValue, initValueIsNull,
3371  same_input_transnos);
3372  if (existing_transno != -1)
3373  {
3374  /*
3375  * Existing compatible trans found, so just point the 'peragg' to
3376  * the same per-trans struct, and mark the trans state as shared.
3377  */
3378  pertrans = &pertransstates[existing_transno];
3379  pertrans->aggshared = true;
3380  peragg->transno = existing_transno;
3381  }
3382  else
3383  {
3384  pertrans = &pertransstates[++transno];
3385  build_pertrans_for_aggref(pertrans, aggstate, estate,
3386  aggref, transfn_oid, aggtranstype,
3387  serialfn_oid, deserialfn_oid,
3388  initValue, initValueIsNull,
3389  inputTypes, numArguments);
3390  peragg->transno = transno;
3391  }
3392  ReleaseSysCache(aggTuple);
3393  }
3394 
3395  /*
3396  * Update aggstate->numaggs to be the number of unique aggregates found.
3397  * Also set numstates to the number of unique transition states found.
3398  */
3399  aggstate->numaggs = aggno + 1;
3400  aggstate->numtrans = transno + 1;
3401 
3402  /*
3403  * Build a single projection computing the required arguments for all
3404  * aggregates at once; if there's more than one, that's considerably
3405  * faster than doing it separately for each.
3406  *
3407  * First create a targetlist representing the values to compute.
3408  */
3409  combined_inputeval = NIL;
3410  column_offset = 0;
3411  for (transno = 0; transno < aggstate->numtrans; transno++)
3412  {
3413  AggStatePerTrans pertrans = &pertransstates[transno];
3414 
3415  /*
3416  * Mark this per-trans state with its starting column in the combined
3417  * slot.
3418  */
3419  pertrans->inputoff = column_offset;
3420 
3421  /*
3422  * If the aggregate has a FILTER, we can only evaluate the filter
3423  * expression, not the actual input expressions, during the combined
3424  * eval step --- unless we're ignoring the filter because this node is
3425  * running combinefns not transfns.
3426  */
3427  if (pertrans->aggref->aggfilter &&
3428  !DO_AGGSPLIT_COMBINE(aggstate->aggsplit))
3429  {
3430  TargetEntry *tle;
3431 
3432  tle = makeTargetEntry(pertrans->aggref->aggfilter,
3433  column_offset + 1, NULL, false);
3434  combined_inputeval = lappend(combined_inputeval, tle);
3435  column_offset++;
3436 
3437  /*
3438  * We'll need separate projection machinery for the real args.
3439  * Arrange to evaluate them into the sortslot previously created.
3440  */
3441  Assert(pertrans->sortslot);
3442  pertrans->evalproj = ExecBuildProjectionInfo(pertrans->aggref->args,
3443  aggstate->tmpcontext,
3444  pertrans->sortslot,
3445  &aggstate->ss.ps,
3446  NULL);
3447  }
3448  else
3449  {
3450  /*
3451  * Add agg's input expressions to combined_inputeval, adjusting
3452  * resnos in the copied target entries to match the combined slot.
3453  */
3454  ListCell *arg;
3455 
3456  foreach(arg, pertrans->aggref->args)
3457  {
3458  TargetEntry *source_tle = lfirst_node(TargetEntry, arg);
3459  TargetEntry *tle;
3460 
3461  tle = flatCopyTargetEntry(source_tle);
3462  tle->resno += column_offset;
3463 
3464  combined_inputeval = lappend(combined_inputeval, tle);
3465  }
3466 
3467  column_offset += list_length(pertrans->aggref->args);
3468  }
3469  }
3470 
3471  /* Now create a projection for the combined targetlist */
3472  combineddesc = ExecTypeFromTL(combined_inputeval, false);
3473  combinedslot = ExecInitExtraTupleSlot(estate);
3474  ExecSetSlotDescriptor(combinedslot, combineddesc);
3475  aggstate->combinedproj = ExecBuildProjectionInfo(combined_inputeval,
3476  aggstate->tmpcontext,
3477  combinedslot,
3478  &aggstate->ss.ps,
3479  NULL);
3480 
3481  /*
3482  * Last, check whether any more aggregates got added onto the node while
3483  * we processed the expressions for the aggregate arguments (including not
3484  * only the regular arguments and FILTER expressions handled immediately
3485  * above, but any direct arguments we might've handled earlier). If so,
3486  * we have nested aggregate functions, which is semantically nonsensical,
3487  * so complain. (This should have been caught by the parser, so we don't
3488  * need to work hard on a helpful error message; but we defend against it
3489  * here anyway, just to be sure.)
3490  */
3491  if (numaggs != list_length(aggstate->aggs))
3492  ereport(ERROR,
3493  (errcode(ERRCODE_GROUPING_ERROR),
3494  errmsg("aggregate function calls cannot be nested")));
3495 
3496  return aggstate;
3497 }
FmgrInfo * eqfunctions
Definition: nodeAgg.c:521
struct AggStatePerTransData * AggStatePerTrans
Definition: execnodes.h:1809
AggStatePerGroup * hash_pergroup
Definition: execnodes.h:1852
#define NIL
Definition: pg_list.h:69
struct AggStatePerGroupData * AggStatePerGroup
Definition: execnodes.h:1810
static void select_current_set(AggState *aggstate, int setno, bool is_hash)
Definition: nodeAgg.c:597
int numCols
Definition: plannodes.h:786
List * qual
Definition: plannodes.h:145
AggStatePerPhase phases
Definition: execnodes.h:1841
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate)
Definition: execTuples.c:852
Datum * ecxt_aggvalues
Definition: execnodes.h:214
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate)
Definition: execTuples.c:842
#define AGGMODIFY_READ_WRITE
Definition: pg_aggregate.h:145
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
AttrNumber * grpColIdx
Definition: plannodes.h:787
#define Anum_pg_aggregate_agginitval
Definition: pg_aggregate.h:117
List * lcons_int(int datum, List *list)
Definition: list.c:277
int numaggs
Definition: execnodes.h:1818
Oid GetUserId(void)
Definition: miscinit.c:284
bool agg_done
Definition: execnodes.h:1834
#define castNode(_type_, nodeptr)
Definition: nodes.h:581
TupleTableSlot * sort_slot
Definition: execnodes.h:1844
List * all_grouped_cols
Definition: execnodes.h:1838
Tuplesortstate * sort_out
Definition: execnodes.h:1843
ScanState ss
Definition: execnodes.h:1816
ExprContext * ps_ExprContext
Definition: execnodes.h:884
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1009
FmgrInfo * eqfunctions
Definition: nodeAgg.c:503
Oid inputcollid
Definition: primnodes.h:297
int current_phase
Definition: execnodes.h:1824
Definition: nodes.h:512
AggSplit aggsplit
Definition: execnodes.h:1821
static TupleTableSlot * ExecAgg(PlanState *pstate)
Definition: nodeAgg.c:2145
int errcode(int sqlerrcode)
Definition: elog.c:575
List * args
Definition: primnodes.h:301
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1116
void build_aggregate_finalfn_expr(Oid *agg_input_types, int num_finalfn_inputs, Oid agg_state_type, Oid agg_result_type, Oid agg_input_collation, Oid finalfn_oid, Expr **finalfnexpr)
Definition: parse_agg.c:2030
AggStatePerTrans pertrans
Definition: execnodes.h:1826
EState * state
Definition: execnodes.h:852
int projected_set
Definition: execnodes.h:1835
unsigned int Oid
Definition: postgres_ext.h:31
HeapTuple grp_firstTuple
Definition: execnodes.h:1847
Aggref * aggref
Definition: nodeAgg.c:415
int current_set
Definition: execnodes.h:1836
#define OidIsValid(objectId)
Definition: c.h:576
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:771
int numtrans
Definition: execnodes.h:1819
void execTuplesHashPrepare(int numCols, Oid *eqOperators, FmgrInfo **eqFunctions, FmgrInfo **hashFunctions)
Definition: execGrouping.c:233
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:160
void ExecAssignResultTypeFromTL(PlanState *planstate)
Definition: execUtils.c:448
ExprContext * tmpcontext
Definition: execnodes.h:1829
#define FUNC_MAX_ARGS
Bitmapset ** grouped_cols
Definition: nodeAgg.c:502
PlanState ps
Definition: execnodes.h:1113
int maxsets
Definition: execnodes.h:1840
#define DO_AGGSPLIT_SERIALIZE(as)
Definition: nodes.h:773
AggStrategy aggstrategy
Definition: plannodes.h:784
bool table_filled
Definition: execnodes.h:1849
AggStrategy aggstrategy
Definition: execnodes.h:1820
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1412
void ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
Definition: execTuples.c:832
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:122
static void find_hash_columns(AggState *aggstate)
Definition: nodeAgg.c:1948
Tuplesortstate * sort_in
Definition: execnodes.h:1842
#define EXEC_FLAG_BACKWARD
Definition: executor.h:60
#define lfirst_node(type, lc)
Definition: pg_list.h:109
#define outerPlanState(node)
Definition: execnodes.h:896
Aggref * aggref
Definition: execnodes.h:660
#define list_nth_node(type, list, n)
Definition: pg_list.h:227
static int initValue(long lng_val)
Definition: informix.c:702
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:495
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3457
static void build_hash_table(AggState *aggstate)
Definition: nodeAgg.c:1899
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:104
AttrNumber resno
Definition: primnodes.h:1376
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:266
Index agglevelsup
Definition: primnodes.h:309
List * aggdirectargs
Definition: primnodes.h:300
static Datum GetAggInitVal(Datum textInitVal, Oid transtype)
Definition: nodeAgg.c:3789
AggStatePerAgg curperagg
Definition: execnodes.h:1831
AggStatePerHash perhash
Definition: execnodes.h:1851
TargetEntry * flatCopyTargetEntry(TargetEntry *src_tle)
Definition: makefuncs.c:270
AggStrategy aggstrategy
Definition: nodeAgg.c:499
#define EXEC_FLAG_REWIND
Definition: executor.h:59
#define ereport(elevel, rest)
Definition: elog.h:122
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:237
TupleDesc ExecTypeFromTL(List *targetList, bool hasoid)
Definition: execTuples.c:888
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:179
#define outerPlan(node)
Definition: plannodes.h:174
List * lappend(List *list, void *datum)
Definition: list.c:128
int num_hashes
Definition: execnodes.h:1850
Plan plan
Definition: plannodes.h:783
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
bool input_done
Definition: execnodes.h:1833
ProjectionInfo * combinedproj
Definition: execnodes.h:1854
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:121
ExprContext * hashcontext
Definition: execnodes.h:1827
bool * ecxt_aggnulls
Definition: execnodes.h:215
static int find_compatible_peragg(Aggref *newagg, AggState *aggstate, int lastaggno, List **same_input_transnos)
Definition: nodeAgg.c:3817
void * palloc0(Size size)
Definition: mcxt.c:877
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:856
AclResult
Definition: acl.h:178
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:247
AggStatePerGroup pergroup
Definition: execnodes.h:1846
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1368
List * groupingSets
Definition: plannodes.h:792
int16 resulttypeLen
Definition: nodeAgg.c:444
static void initialize_phase(AggState *aggstate, int newphase)
Definition: nodeAgg.c:615
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
Plan * plan
Definition: execnodes.h:850
#define InvalidOid
Definition: postgres_ext.h:36
Oid aggfnoid
Definition: primnodes.h:294
#define INTERNALOID
Definition: pg_type.h:698
#define Max(x, y)
Definition: c.h:796
ExprContext ** aggcontexts
Definition: execnodes.h:1828
#define makeNode(_type_)
Definition: nodes.h:560
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
FmgrInfo * hashfunctions
Definition: nodeAgg.c:520
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
#define EXEC_FLAG_MARK
Definition: executor.h:61
AggSplit aggsplit
Definition: plannodes.h:785
struct AggStatePerAggData * AggStatePerAgg
Definition: execnodes.h:1808
FormData_pg_aggregate * Form_pg_aggregate
Definition: pg_aggregate.h:89
AggSplit aggsplit
Definition: primnodes.h:310
ProjectionInfo * evalproj
Definition: nodeAgg.c:357
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:426
static int list_length(const List *l)
Definition: pg_list.h:89
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:772
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:2020
Expr * aggfilter
Definition: primnodes.h:304
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:698
#define DO_AGGSPLIT_DESERIALIZE(as)
Definition: nodes.h:774
struct Plan * lefttree
Definition: plannodes.h:146
int numphases
Definition: execnodes.h:1823
ExprState * qual
Definition: execnodes.h:868
void ExecAssignScanTypeFromOuterPlan(ScanState *scanstate)
Definition: execUtils.c:639
Oid * grpOperators
Definition: plannodes.h:788
void * palloc(Size size)
Definition: mcxt.c:848
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
Definition: execExpr.c:301
int errmsg(const char *fmt,...)
Definition: elog.c:797
List * chain
Definition: plannodes.h:793
AggStatePerAgg peragg
Definition: execnodes.h:1825
#define ACL_EXECUTE
Definition: parsenodes.h:79
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4504
int i
List * aggdirectargs
Definition: nodeAgg.c:438
Oid aggtranstype
Definition: primnodes.h:298
static int find_compatible_pertrans(AggState *aggstate, Aggref *newagg, bool sharable, Oid aggtransfn, Oid aggtranstype, Oid aggserialfn, Oid aggdeserialfn, Datum initValue, bool initValueIsNull, List *transnos)
Definition: nodeAgg.c:3895
void * arg
AggStatePerTrans curpertrans
Definition: execnodes.h:1832
Oid aggtype
Definition: primnodes.h:295
bool resulttypeByVal
Definition: nodeAgg.c:445
Definition: plannodes.h:781
#define elog
Definition: elog.h:219
List * aggs
Definition: execnodes.h:1817
TupleTableSlot * sortslot
Definition: nodeAgg.c:364
FmgrInfo * execTuplesMatchPrepare(int numCols, Oid *eqOperators)
Definition: execGrouping.c:204
TupleTableSlot * hashslot
Definition: nodeAgg.c:519
int get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
Definition: parse_agg.c:1812
static void build_pertrans_for_aggref(AggStatePerTrans pertrans, AggState *aggstate, EState *estate, Aggref *aggref, Oid aggtransfn, Oid aggtranstype, Oid aggserialfn, Oid aggdeserialfn, Datum initValue, bool initValueIsNull, Oid *inputTypes, int numArguments)
Definition: nodeAgg.c:3508
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:139
Definition: pg_list.h:45
FmgrInfo finalfn
Definition: nodeAgg.c:427
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:755

◆ ExecReScanAgg()

void ExecReScanAgg ( AggState node)

Definition at line 3992 of file nodeAgg.c.

References AggState::agg_done, AGG_HASHED, AGG_MIXED, AggState::aggcontexts, Agg::aggParams, AggState::aggstrategy, bms_overlap(), build_hash_table(), PlanState::chgParam, ExprContext::ecxt_aggnulls, ExprContext::ecxt_aggvalues, ExecClearTuple(), ExecReScan(), AggState::grp_firstTuple, AggState::hashcontext, AggStatePerHashData::hashiter, AggStatePerHashData::hashtable, heap_freetuple(), initialize_phase(), AggState::input_done, Max, AggState::maxsets, MemSet, AggState::numaggs, AggState::numtrans, outerPlan, outerPlanState, AggState::pergroup, AggState::perhash, AggState::pertrans, PlanState::plan, AggState::projected_set, ScanState::ps, PlanState::ps_ExprContext, ReScanExprContext(), ResetTupleHashIterator, select_current_set(), AggStatePerTransData::sortstates, AggState::ss, ScanState::ss_ScanTupleSlot, AggState::table_filled, and tuplesort_end().

Referenced by ExecReScan().

3993 {
3994  ExprContext *econtext = node->ss.ps.ps_ExprContext;
3996  Agg *aggnode = (Agg *) node->ss.ps.plan;
3997  int transno;
3998  int numGroupingSets = Max(node->maxsets, 1);
3999  int setno;
4000 
4001  node->agg_done = false;
4002 
4003  if (node->aggstrategy == AGG_HASHED)
4004  {
4005  /*
4006  * In the hashed case, if we haven't yet built the hash table then we
4007  * can just return; nothing done yet, so nothing to undo. If subnode's
4008  * chgParam is not NULL then it will be re-scanned by ExecProcNode,
4009  * else no reason to re-scan it at all.
4010  */
4011  if (!node->table_filled)
4012  return;
4013 
4014  /*
4015  * If we do have the hash table, and the subplan does not have any
4016  * parameter changes, and none of our own parameter changes affect
4017  * input expressions of the aggregated functions, then we can just
4018  * rescan the existing hash table; no need to build it again.
4019  */
4020  if (outerPlan->chgParam == NULL &&
4021  !bms_overlap(node->ss.ps.chgParam, aggnode->aggParams))
4022  {
4024  &node->perhash[0].hashiter);
4025  select_current_set(node, 0, true);
4026  return;
4027  }
4028  }
4029 
4030  /* Make sure we have closed any open tuplesorts */
4031  for (transno = 0; transno < node->numtrans; transno++)
4032  {
4033  for (setno = 0; setno < numGroupingSets; setno++)
4034  {
4035  AggStatePerTrans pertrans = &node->pertrans[transno];
4036 
4037  if (pertrans->sortstates[setno])
4038  {
4039  tuplesort_end(pertrans->sortstates[setno]);
4040  pertrans->sortstates[setno] = NULL;
4041  }
4042  }
4043  }
4044 
4045  /*
4046  * We don't need to ReScanExprContext the output tuple context here;
4047  * ExecReScan already did it. But we do need to reset our per-grouping-set
4048  * contexts, which may have transvalues stored in them. (We use rescan
4049  * rather than just reset because transfns may have registered callbacks
4050  * that need to be run now.) For the AGG_HASHED case, see below.
4051  */
4052 
4053  for (setno = 0; setno < numGroupingSets; setno++)
4054  {
4055  ReScanExprContext(node->aggcontexts[setno]);
4056  }
4057 
4058  /* Release first tuple of group, if we have made a copy */
4059  if (node->grp_firstTuple != NULL)
4060  {
4062  node->grp_firstTuple = NULL;
4063  }
4065 
4066  /* Forget current agg values */
4067  MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numaggs);
4068  MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numaggs);
4069 
4070  /*
4071  * With AGG_HASHED/MIXED, the hash table is allocated in a sub-context of
4072  * the hashcontext. This used to be an issue, but now, resetting a context
4073  * automatically deletes sub-contexts too.
4074  */
4075  if (node->aggstrategy == AGG_HASHED || node->aggstrategy == AGG_MIXED)
4076  {
4078  /* Rebuild an empty hash table */
4079  build_hash_table(node);
4080  node->table_filled = false;
4081  /* iterator will be reset when the table is filled */
4082  }
4083 
4084  if (node->aggstrategy != AGG_HASHED)
4085  {
4086  /*
4087  * Reset the per-group state (in particular, mark transvalues null)
4088  */
4089  MemSet(node->pergroup, 0,
4090  sizeof(AggStatePerGroupData) * node->numaggs * numGroupingSets);
4091 
4092  /* reset to phase 1 */
4093  initialize_phase(node, 1);
4094 
4095  node->input_done = false;
4096  node->projected_set = -1;
4097  }
4098 
4099  if (outerPlan->chgParam == NULL)
4100  ExecReScan(outerPlan);
4101 }
static void select_current_set(AggState *aggstate, int setno, bool is_hash)
Definition: nodeAgg.c:597
Datum * ecxt_aggvalues
Definition: execnodes.h:214
int numaggs
Definition: execnodes.h:1818
bool agg_done
Definition: execnodes.h:1834
ScanState ss
Definition: execnodes.h:1816
ExprContext * ps_ExprContext
Definition: execnodes.h:884
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
#define MemSet(start, val, len)
Definition: c.h:853
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1116
AggStatePerTrans pertrans
Definition: execnodes.h:1826
int projected_set
Definition: execnodes.h:1835
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373
HeapTuple grp_firstTuple
Definition: execnodes.h:1847
int numtrans
Definition: execnodes.h:1819
PlanState ps
Definition: execnodes.h:1113
int maxsets
Definition: execnodes.h:1840
bool table_filled
Definition: execnodes.h:1849
AggStrategy aggstrategy
Definition: execnodes.h:1820
#define outerPlanState(node)
Definition: execnodes.h:896
Tuplesortstate ** sortstates
Definition: nodeAgg.c:382
Bitmapset * aggParams
Definition: plannodes.h:790
static void build_hash_table(AggState *aggstate)
Definition: nodeAgg.c:1899
AggStatePerHash perhash
Definition: execnodes.h:1851
Bitmapset * chgParam
Definition: execnodes.h:878
#define outerPlan(node)
Definition: plannodes.h:174
TupleHashIterator hashiter
Definition: nodeAgg.c:518
bool input_done
Definition: execnodes.h:1833
ExprContext * hashcontext
Definition: execnodes.h:1827
bool * ecxt_aggnulls
Definition: execnodes.h:215
uintptr_t Datum
Definition: postgres.h:372
AggStatePerGroup pergroup
Definition: execnodes.h:1846
static void initialize_phase(AggState *aggstate, int newphase)
Definition: nodeAgg.c:615
Plan * plan
Definition: execnodes.h:850
#define ResetTupleHashIterator(htable, iter)
Definition: execnodes.h:635
#define Max(x, y)
Definition: c.h:796
ExprContext ** aggcontexts
Definition: execnodes.h:1828
void ReScanExprContext(ExprContext *econtext)
Definition: execUtils.c:384
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:443
Definition: plannodes.h:781
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1104
TupleHashTable hashtable
Definition: nodeAgg.c:517

◆ hash_agg_entry_size()

Size hash_agg_entry_size ( int  numAggs)

Definition at line 2050 of file nodeAgg.c.

References MAXALIGN.

Referenced by create_distinct_paths(), and estimate_hashagg_tablesize().

2051 {
2052  Size entrysize;
2053 
2054  /* This must match build_hash_table */
2055  entrysize = sizeof(TupleHashEntryData) +
2056  numAggs * sizeof(AggStatePerGroupData);
2057  entrysize = MAXALIGN(entrysize);
2058 
2059  return entrysize;
2060 }
struct TupleHashEntryData TupleHashEntryData
size_t Size
Definition: c.h:404
#define MAXALIGN(LEN)
Definition: c.h:623