PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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

Datum aggregate_dummy ( PG_FUNCTION_ARGS  )

Definition at line 4287 of file nodeAgg.c.

References elog, and ERROR.

4288 {
4289  elog(ERROR, "aggregate function %u called as normal function",
4290  fcinfo->flinfo->fn_oid);
4291  return (Datum) 0; /* keep compiler quiet */
4292 }
#define ERROR
Definition: elog.h:43
uintptr_t Datum
Definition: postgres.h:372
#define elog
Definition: elog.h:219
void ExecEndAgg ( AggState node)

Definition at line 3935 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().

3936 {
3938  int transno;
3939  int numGroupingSets = Max(node->maxsets, 1);
3940  int setno;
3941 
3942  /* Make sure we have closed any open tuplesorts */
3943 
3944  if (node->sort_in)
3945  tuplesort_end(node->sort_in);
3946  if (node->sort_out)
3947  tuplesort_end(node->sort_out);
3948 
3949  for (transno = 0; transno < node->numtrans; transno++)
3950  {
3951  AggStatePerTrans pertrans = &node->pertrans[transno];
3952 
3953  for (setno = 0; setno < numGroupingSets; setno++)
3954  {
3955  if (pertrans->sortstates[setno])
3956  tuplesort_end(pertrans->sortstates[setno]);
3957  }
3958  }
3959 
3960  /* And ensure any agg shutdown callbacks have been called */
3961  for (setno = 0; setno < numGroupingSets; setno++)
3962  ReScanExprContext(node->aggcontexts[setno]);
3963  if (node->hashcontext)
3965 
3966  /*
3967  * We don't actually free any ExprContexts here (see comment in
3968  * ExecFreeExprContext), just unlinking the output one from the plan node
3969  * suffices.
3970  */
3971  ExecFreeExprContext(&node->ss.ps);
3972 
3973  /* clean up tuple table */
3975 
3976  outerPlan = outerPlanState(node);
3977  ExecEndNode(outerPlan);
3978 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:523
Tuplesortstate * sort_out
Definition: execnodes.h:1823
ScanState ss
Definition: execnodes.h:1796
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1104
AggStatePerTrans pertrans
Definition: execnodes.h:1806
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:521
int numtrans
Definition: execnodes.h:1799
PlanState ps
Definition: execnodes.h:1101
int maxsets
Definition: execnodes.h:1820
Tuplesortstate * sort_in
Definition: execnodes.h:1822
#define outerPlanState(node)
Definition: execnodes.h:893
Tuplesortstate ** sortstates
Definition: nodeAgg.c:382
#define outerPlan(node)
Definition: plannodes.h:174
ExprContext * hashcontext
Definition: execnodes.h:1807
#define Max(x, y)
Definition: c.h:806
ExprContext ** aggcontexts
Definition: execnodes.h:1808
void ReScanExprContext(ExprContext *econtext)
Definition: execUtils.c:381
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1104
AggState* ExecInitAgg ( Agg node,
EState estate,
int  eflags 
)

Definition at line 2697 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, Aggref::aggtranstype, Aggref::aggtype, AggState::all_grouped_cols, 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::combinedproj, AggState::curperagg, AggState::curpertrans, AggState::current_phase, AggState::current_set, DO_AGGSPLIT_COMBINE, DO_AGGSPLIT_DESERIALIZE, DO_AGGSPLIT_SERIALIZE, DO_AGGSPLIT_SKIPFINAL, ExprContext::ecxt_aggnulls, ExprContext::ecxt_aggvalues, elog, AggStatePerPhaseData::eqfunctions, AggStatePerHashData::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::hash_pergroup, AggState::hashcontext, AggStatePerHashData::hashfunctions, AggStatePerHashData::hashslot, HeapTupleIsValid, i, initialize_phase(), initValue(), 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::num_hashes, 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::perhash, AggState::pertrans, pg_proc_aclcheck(), AggState::phases, 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(), AggStatePerAggData::sharable, AggState::sort_in, AggState::sort_out, AggState::sort_slot, AggStatePerPhaseData::sortnode, AggStatePerTransData::sortslot, AggState::ss, ScanState::ss_ScanTupleSlot, PlanState::state, SysCacheGetAttr(), AggState::table_filled, AggState::tmpcontext, AggStatePerAggData::transno, and TupleTableSlot::tts_tupleDescriptor.

Referenced by ExecInitNode().

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

Definition at line 3981 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().

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

Definition at line 2039 of file nodeAgg.c.

References MAXALIGN.

Referenced by create_distinct_paths(), and estimate_hashagg_tablesize().

2040 {
2041  Size entrysize;
2042 
2043  /* This must match build_hash_table */
2044  entrysize = sizeof(TupleHashEntryData) +
2045  numAggs * sizeof(AggStatePerGroupData);
2046  entrysize = MAXALIGN(entrysize);
2047 
2048  return entrysize;
2049 }
struct TupleHashEntryData TupleHashEntryData
size_t Size
Definition: c.h:350
#define MAXALIGN(LEN)
Definition: c.h:576