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)
 
TupleTableSlotExecAgg (AggState *node)
 
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 4135 of file nodeAgg.c.

References elog, and ERROR.

4136 {
4137  elog(ERROR, "aggregate function %u called as normal function",
4138  fcinfo->flinfo->fn_oid);
4139  return (Datum) 0; /* keep compiler quiet */
4140 }
#define ERROR
Definition: elog.h:43
uintptr_t Datum
Definition: postgres.h:372
#define elog
Definition: elog.h:219
TupleTableSlot* ExecAgg ( AggState node)

Definition at line 2099 of file nodeAgg.c.

References AggState::agg_done, agg_fill_hash_table(), AGG_HASHED, AGG_MIXED, AGG_PLAIN, agg_retrieve_direct(), agg_retrieve_hash_table(), AGG_SORTED, AggStatePerPhaseData::aggstrategy, NULL, AggState::phase, result, AggState::table_filled, and TupIsNull.

Referenced by ExecProcNode().

2100 {
2102 
2103  if (!node->agg_done)
2104  {
2105  /* Dispatch based on strategy */
2106  switch (node->phase->aggstrategy)
2107  {
2108  case AGG_HASHED:
2109  if (!node->table_filled)
2110  agg_fill_hash_table(node);
2111  /* FALLTHROUGH */
2112  case AGG_MIXED:
2113  result = agg_retrieve_hash_table(node);
2114  break;
2115  case AGG_PLAIN:
2116  case AGG_SORTED:
2117  result = agg_retrieve_direct(node);
2118  break;
2119  }
2120 
2121  if (!TupIsNull(result))
2122  return result;
2123  }
2124 
2125  return NULL;
2126 }
static void agg_fill_hash_table(AggState *aggstate)
Definition: nodeAgg.c:2486
bool agg_done
Definition: execnodes.h:1748
return result
Definition: formatting.c:1618
bool table_filled
Definition: execnodes.h:1764
static TupleTableSlot * agg_retrieve_hash_table(AggState *aggstate)
Definition: nodeAgg.c:2533
static TupleTableSlot * agg_retrieve_direct(AggState *aggstate)
Definition: nodeAgg.c:2132
#define TupIsNull(slot)
Definition: tuptable.h:138
AggStrategy aggstrategy
Definition: nodeAgg.c:489
AggStatePerPhase phase
Definition: execnodes.h:1737
#define NULL
Definition: c.h:229
void ExecEndAgg ( AggState node)

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

3838 {
3840  int transno;
3841  int numGroupingSets = Max(node->maxsets, 1);
3842  int setno;
3843 
3844  /* Make sure we have closed any open tuplesorts */
3845 
3846  if (node->sort_in)
3847  tuplesort_end(node->sort_in);
3848  if (node->sort_out)
3849  tuplesort_end(node->sort_out);
3850 
3851  for (transno = 0; transno < node->numtrans; transno++)
3852  {
3853  AggStatePerTrans pertrans = &node->pertrans[transno];
3854 
3855  for (setno = 0; setno < numGroupingSets; setno++)
3856  {
3857  if (pertrans->sortstates[setno])
3858  tuplesort_end(pertrans->sortstates[setno]);
3859  }
3860  }
3861 
3862  /* And ensure any agg shutdown callbacks have been called */
3863  for (setno = 0; setno < numGroupingSets; setno++)
3864  ReScanExprContext(node->aggcontexts[setno]);
3865  if (node->hashcontext)
3867 
3868  /*
3869  * We don't actually free any ExprContexts here (see comment in
3870  * ExecFreeExprContext), just unlinking the output one from the plan node
3871  * suffices.
3872  */
3873  ExecFreeExprContext(&node->ss.ps);
3874 
3875  /* clean up tuple table */
3877 
3878  outerPlan = outerPlanState(node);
3879  ExecEndNode(outerPlan);
3880 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:654
Tuplesortstate * sort_out
Definition: execnodes.h:1758
ScanState ss
Definition: execnodes.h:1731
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1050
AggStatePerTrans pertrans
Definition: execnodes.h:1741
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:516
int numtrans
Definition: execnodes.h:1734
PlanState ps
Definition: execnodes.h:1047
int maxsets
Definition: execnodes.h:1755
Tuplesortstate * sort_in
Definition: execnodes.h:1757
#define outerPlanState(node)
Definition: execnodes.h:845
Tuplesortstate ** sortstates
Definition: nodeAgg.c:380
#define outerPlan(node)
Definition: plannodes.h:164
ExprContext * hashcontext
Definition: execnodes.h:1742
#define Max(x, y)
Definition: c.h:800
ExprContext ** aggcontexts
Definition: execnodes.h:1743
void ReScanExprContext(ExprContext *econtext)
Definition: execUtils.c:376
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1167
AggState* ExecInitAgg ( Agg node,
EState estate,
int  eflags 
)

Definition at line 2658 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, AGGFNOID, Aggref::aggfnoid, Aggref::agglevelsup, AggrefExprState::aggno, AggStatePerPhaseData::aggnode, AggStatePerHashData::aggnode, AggStatePerTransData::aggref, AggStatePerAggData::aggref, AggrefExprState::aggref, AggState::aggs, 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::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, ERROR, AggState::evaldesc, AggState::evalproj, AggState::evalslot, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, EXEC_FLAG_REWIND, ExecAssignExprContext(), ExecAssignProjectionInfo(), ExecAssignResultTypeFromTL(), ExecAssignScanTypeFromOuterPlan(), ExecBuildProjectionInfo(), ExecInitExtraTupleSlot(), ExecInitNode(), ExecInitQual(), ExecInitResultTupleSlot(), ExecInitScanTupleSlot(), 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, Max, AggState::maxsets, NIL, NULL, 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(), AggState::sort_in, AggState::sort_out, AggState::sort_slot, AggStatePerPhaseData::sortnode, AggState::ss, ScanState::ss_ScanTupleSlot, PlanState::state, SysCacheGetAttr(), AggState::table_filled, AggState::tmpcontext, AggStatePerAggData::transno, and TupleTableSlot::tts_tupleDescriptor.

Referenced by ExecInitNode().

2659 {
2660  AggState *aggstate;
2661  AggStatePerAgg peraggs;
2662  AggStatePerTrans pertransstates;
2663  Plan *outerPlan;
2664  ExprContext *econtext;
2665  int numaggs,
2666  transno,
2667  aggno;
2668  int phase;
2669  int phaseidx;
2670  List *combined_inputeval;
2671  ListCell *l;
2672  Bitmapset *all_grouped_cols = NULL;
2673  int numGroupingSets = 1;
2674  int numPhases;
2675  int numHashes;
2676  int column_offset;
2677  int i = 0;
2678  int j = 0;
2679  bool use_hashing = (node->aggstrategy == AGG_HASHED ||
2680  node->aggstrategy == AGG_MIXED);
2681 
2682  /* check for unsupported flags */
2683  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
2684 
2685  /*
2686  * create state structure
2687  */
2688  aggstate = makeNode(AggState);
2689  aggstate->ss.ps.plan = (Plan *) node;
2690  aggstate->ss.ps.state = estate;
2691 
2692  aggstate->aggs = NIL;
2693  aggstate->numaggs = 0;
2694  aggstate->numtrans = 0;
2695  aggstate->aggstrategy = node->aggstrategy;
2696  aggstate->aggsplit = node->aggsplit;
2697  aggstate->maxsets = 0;
2698  aggstate->projected_set = -1;
2699  aggstate->current_set = 0;
2700  aggstate->peragg = NULL;
2701  aggstate->pertrans = NULL;
2702  aggstate->curpertrans = NULL;
2703  aggstate->input_done = false;
2704  aggstate->agg_done = false;
2705  aggstate->pergroup = NULL;
2706  aggstate->grp_firstTuple = NULL;
2707  aggstate->sort_in = NULL;
2708  aggstate->sort_out = NULL;
2709 
2710  /*
2711  * phases[0] always exists, but is dummy in sorted/plain mode
2712  */
2713  numPhases = (use_hashing ? 1 : 2);
2714  numHashes = (use_hashing ? 1 : 0);
2715 
2716  /*
2717  * Calculate the maximum number of grouping sets in any phase; this
2718  * determines the size of some allocations. Also calculate the number of
2719  * phases, since all hashed/mixed nodes contribute to only a single phase.
2720  */
2721  if (node->groupingSets)
2722  {
2723  numGroupingSets = list_length(node->groupingSets);
2724 
2725  foreach(l, node->chain)
2726  {
2727  Agg *agg = lfirst(l);
2728 
2729  numGroupingSets = Max(numGroupingSets,
2730  list_length(agg->groupingSets));
2731 
2732  /*
2733  * additional AGG_HASHED aggs become part of phase 0, but all
2734  * others add an extra phase.
2735  */
2736  if (agg->aggstrategy != AGG_HASHED)
2737  ++numPhases;
2738  else
2739  ++numHashes;
2740  }
2741  }
2742 
2743  aggstate->maxsets = numGroupingSets;
2744  aggstate->numphases = numPhases;
2745 
2746  aggstate->aggcontexts = (ExprContext **)
2747  palloc0(sizeof(ExprContext *) * numGroupingSets);
2748 
2749  /*
2750  * Create expression contexts. We need three or more, one for
2751  * per-input-tuple processing, one for per-output-tuple processing, one
2752  * for all the hashtables, and one for each grouping set. The per-tuple
2753  * memory context of the per-grouping-set ExprContexts (aggcontexts)
2754  * replaces the standalone memory context formerly used to hold transition
2755  * values. We cheat a little by using ExecAssignExprContext() to build
2756  * all of them.
2757  *
2758  * NOTE: the details of what is stored in aggcontexts and what is stored
2759  * in the regular per-query memory context are driven by a simple
2760  * decision: we want to reset the aggcontext at group boundaries (if not
2761  * hashing) and in ExecReScanAgg to recover no-longer-wanted space.
2762  */
2763  ExecAssignExprContext(estate, &aggstate->ss.ps);
2764  aggstate->tmpcontext = aggstate->ss.ps.ps_ExprContext;
2765 
2766  for (i = 0; i < numGroupingSets; ++i)
2767  {
2768  ExecAssignExprContext(estate, &aggstate->ss.ps);
2769  aggstate->aggcontexts[i] = aggstate->ss.ps.ps_ExprContext;
2770  }
2771 
2772  if (use_hashing)
2773  {
2774  ExecAssignExprContext(estate, &aggstate->ss.ps);
2775  aggstate->hashcontext = aggstate->ss.ps.ps_ExprContext;
2776  }
2777 
2778  ExecAssignExprContext(estate, &aggstate->ss.ps);
2779 
2780  /*
2781  * tuple table initialization.
2782  *
2783  * For hashtables, we create some additional slots below.
2784  */
2785  ExecInitScanTupleSlot(estate, &aggstate->ss);
2786  ExecInitResultTupleSlot(estate, &aggstate->ss.ps);
2787  aggstate->sort_slot = ExecInitExtraTupleSlot(estate);
2788 
2789  /*
2790  * initialize child expressions
2791  *
2792  * We rely on the parser to have checked that no aggs contain other agg
2793  * calls in their arguments. This would make no sense under SQL semantics
2794  * (and it's forbidden by the spec). Because it is true, we don't need to
2795  * worry about evaluating the aggs in any particular order.
2796  *
2797  * Note: execExpr.c finds Aggrefs for us, and adds their AggrefExprState
2798  * nodes to aggstate->aggs. Aggrefs in the qual are found here; Aggrefs
2799  * in the targetlist are found during ExecAssignProjectionInfo, below.
2800  */
2801  aggstate->ss.ps.qual =
2802  ExecInitQual(node->plan.qual, (PlanState *) aggstate);
2803 
2804  /*
2805  * Initialize child nodes.
2806  *
2807  * If we are doing a hashed aggregation then the child plan does not need
2808  * to handle REWIND efficiently; see ExecReScanAgg.
2809  */
2810  if (node->aggstrategy == AGG_HASHED)
2811  eflags &= ~EXEC_FLAG_REWIND;
2812  outerPlan = outerPlan(node);
2813  outerPlanState(aggstate) = ExecInitNode(outerPlan, estate, eflags);
2814 
2815  /*
2816  * initialize source tuple type.
2817  */
2818  ExecAssignScanTypeFromOuterPlan(&aggstate->ss);
2819  if (node->chain)
2820  ExecSetSlotDescriptor(aggstate->sort_slot,
2822 
2823  /*
2824  * Initialize result tuple type and projection info.
2825  */
2826  ExecAssignResultTypeFromTL(&aggstate->ss.ps);
2827  ExecAssignProjectionInfo(&aggstate->ss.ps, NULL);
2828 
2829  /*
2830  * We should now have found all Aggrefs in the targetlist and quals.
2831  */
2832  numaggs = aggstate->numaggs;
2833  Assert(numaggs == list_length(aggstate->aggs));
2834  if (numaggs <= 0)
2835  {
2836  /*
2837  * This is not an error condition: we might be using the Agg node just
2838  * to do hash-based grouping. Even in the regular case,
2839  * constant-expression simplification could optimize away all of the
2840  * Aggrefs in the targetlist and qual. So keep going, but force local
2841  * copy of numaggs positive so that palloc()s below don't choke.
2842  */
2843  numaggs = 1;
2844  }
2845 
2846  /*
2847  * For each phase, prepare grouping set data and fmgr lookup data for
2848  * compare functions. Accumulate all_grouped_cols in passing.
2849  */
2850  aggstate->phases = palloc0(numPhases * sizeof(AggStatePerPhaseData));
2851 
2852  aggstate->num_hashes = numHashes;
2853  if (numHashes)
2854  {
2855  aggstate->perhash = palloc0(sizeof(AggStatePerHashData) * numHashes);
2856  aggstate->phases[0].numsets = 0;
2857  aggstate->phases[0].gset_lengths = palloc(numHashes * sizeof(int));
2858  aggstate->phases[0].grouped_cols = palloc(numHashes * sizeof(Bitmapset *));
2859  }
2860 
2861  phase = 0;
2862  for (phaseidx = 0; phaseidx <= list_length(node->chain); ++phaseidx)
2863  {
2864  Agg *aggnode;
2865  Sort *sortnode;
2866 
2867  if (phaseidx > 0)
2868  {
2869  aggnode = list_nth_node(Agg, node->chain, phaseidx - 1);
2870  sortnode = castNode(Sort, aggnode->plan.lefttree);
2871  }
2872  else
2873  {
2874  aggnode = node;
2875  sortnode = NULL;
2876  }
2877 
2878  Assert(phase <= 1 || sortnode);
2879 
2880  if (aggnode->aggstrategy == AGG_HASHED
2881  || aggnode->aggstrategy == AGG_MIXED)
2882  {
2883  AggStatePerPhase phasedata = &aggstate->phases[0];
2884  AggStatePerHash perhash;
2885  Bitmapset *cols = NULL;
2886 
2887  Assert(phase == 0);
2888  i = phasedata->numsets++;
2889  perhash = &aggstate->perhash[i];
2890 
2891  /* phase 0 always points to the "real" Agg in the hash case */
2892  phasedata->aggnode = node;
2893  phasedata->aggstrategy = node->aggstrategy;
2894 
2895  /* but the actual Agg node representing this hash is saved here */
2896  perhash->aggnode = aggnode;
2897 
2898  phasedata->gset_lengths[i] = perhash->numCols = aggnode->numCols;
2899 
2900  for (j = 0; j < aggnode->numCols; ++j)
2901  cols = bms_add_member(cols, aggnode->grpColIdx[j]);
2902 
2903  phasedata->grouped_cols[i] = cols;
2904 
2905  all_grouped_cols = bms_add_members(all_grouped_cols, cols);
2906  continue;
2907  }
2908  else
2909  {
2910  AggStatePerPhase phasedata = &aggstate->phases[++phase];
2911  int num_sets;
2912 
2913  phasedata->numsets = num_sets = list_length(aggnode->groupingSets);
2914 
2915  if (num_sets)
2916  {
2917  phasedata->gset_lengths = palloc(num_sets * sizeof(int));
2918  phasedata->grouped_cols = palloc(num_sets * sizeof(Bitmapset *));
2919 
2920  i = 0;
2921  foreach(l, aggnode->groupingSets)
2922  {
2923  int current_length = list_length(lfirst(l));
2924  Bitmapset *cols = NULL;
2925 
2926  /* planner forces this to be correct */
2927  for (j = 0; j < current_length; ++j)
2928  cols = bms_add_member(cols, aggnode->grpColIdx[j]);
2929 
2930  phasedata->grouped_cols[i] = cols;
2931  phasedata->gset_lengths[i] = current_length;
2932 
2933  ++i;
2934  }
2935 
2936  all_grouped_cols = bms_add_members(all_grouped_cols,
2937  phasedata->grouped_cols[0]);
2938  }
2939  else
2940  {
2941  Assert(phaseidx == 0);
2942 
2943  phasedata->gset_lengths = NULL;
2944  phasedata->grouped_cols = NULL;
2945  }
2946 
2947  /*
2948  * If we are grouping, precompute fmgr lookup data for inner loop.
2949  */
2950  if (aggnode->aggstrategy == AGG_SORTED)
2951  {
2952  Assert(aggnode->numCols > 0);
2953 
2954  phasedata->eqfunctions =
2956  aggnode->grpOperators);
2957  }
2958 
2959  phasedata->aggnode = aggnode;
2960  phasedata->aggstrategy = aggnode->aggstrategy;
2961  phasedata->sortnode = sortnode;
2962  }
2963  }
2964 
2965  /*
2966  * Convert all_grouped_cols to a descending-order list.
2967  */
2968  i = -1;
2969  while ((i = bms_next_member(all_grouped_cols, i)) >= 0)
2970  aggstate->all_grouped_cols = lcons_int(i, aggstate->all_grouped_cols);
2971 
2972  /*
2973  * Set up aggregate-result storage in the output expr context, and also
2974  * allocate my private per-agg working storage
2975  */
2976  econtext = aggstate->ss.ps.ps_ExprContext;
2977  econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs);
2978  econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs);
2979 
2980  peraggs = (AggStatePerAgg) palloc0(sizeof(AggStatePerAggData) * numaggs);
2981  pertransstates = (AggStatePerTrans) palloc0(sizeof(AggStatePerTransData) * numaggs);
2982 
2983  aggstate->peragg = peraggs;
2984  aggstate->pertrans = pertransstates;
2985 
2986  /*
2987  * Hashing can only appear in the initial phase.
2988  */
2989  if (use_hashing)
2990  {
2991  for (i = 0; i < numHashes; ++i)
2992  {
2993  aggstate->perhash[i].hashslot = ExecInitExtraTupleSlot(estate);
2994 
2995  execTuplesHashPrepare(aggstate->perhash[i].numCols,
2996  aggstate->perhash[i].aggnode->grpOperators,
2997  &aggstate->perhash[i].eqfunctions,
2998  &aggstate->perhash[i].hashfunctions);
2999  }
3000 
3001  /* this is an array of pointers, not structures */
3002  aggstate->hash_pergroup = palloc0(sizeof(AggStatePerGroup) * numHashes);
3003 
3004  find_hash_columns(aggstate);
3005  build_hash_table(aggstate);
3006  aggstate->table_filled = false;
3007  }
3008 
3009  if (node->aggstrategy != AGG_HASHED)
3010  {
3011  AggStatePerGroup pergroup;
3012 
3013  pergroup = (AggStatePerGroup) palloc0(sizeof(AggStatePerGroupData)
3014  * numaggs
3015  * numGroupingSets);
3016 
3017  aggstate->pergroup = pergroup;
3018  }
3019 
3020  /*
3021  * Initialize current phase-dependent values to initial phase. The initial
3022  * phase is 1 (first sort pass) for all strategies that use sorting (if
3023  * hashing is being done too, then phase 0 is processed last); but if only
3024  * hashing is being done, then phase 0 is all there is.
3025  */
3026  if (node->aggstrategy == AGG_HASHED)
3027  {
3028  aggstate->current_phase = 0;
3029  initialize_phase(aggstate, 0);
3030  select_current_set(aggstate, 0, true);
3031  }
3032  else
3033  {
3034  aggstate->current_phase = 1;
3035  initialize_phase(aggstate, 1);
3036  select_current_set(aggstate, 0, false);
3037  }
3038 
3039  /* -----------------
3040  * Perform lookups of aggregate function info, and initialize the
3041  * unchanging fields of the per-agg and per-trans data.
3042  *
3043  * We try to optimize by detecting duplicate aggregate functions so that
3044  * their state and final values are re-used, rather than needlessly being
3045  * re-calculated independently. We also detect aggregates that are not
3046  * the same, but which can share the same transition state.
3047  *
3048  * Scenarios:
3049  *
3050  * 1. An aggregate function appears more than once in query:
3051  *
3052  * SELECT SUM(x) FROM ... HAVING SUM(x) > 0
3053  *
3054  * Since the aggregates are the identical, we only need to calculate
3055  * the calculate it once. Both aggregates will share the same 'aggno'
3056  * value.
3057  *
3058  * 2. Two different aggregate functions appear in the query, but the
3059  * aggregates have the same transition function and initial value, but
3060  * different final function:
3061  *
3062  * SELECT SUM(x), AVG(x) FROM ...
3063  *
3064  * In this case we must create a new peragg for the varying aggregate,
3065  * and need to call the final functions separately, but can share the
3066  * same transition state.
3067  *
3068  * For either of these optimizations to be valid, the aggregate's
3069  * arguments must be the same, including any modifiers such as ORDER BY,
3070  * DISTINCT and FILTER, and they mustn't contain any volatile functions.
3071  * -----------------
3072  */
3073  aggno = -1;
3074  transno = -1;
3075  foreach(l, aggstate->aggs)
3076  {
3077  AggrefExprState *aggrefstate = (AggrefExprState *) lfirst(l);
3078  Aggref *aggref = aggrefstate->aggref;
3079  AggStatePerAgg peragg;
3080  AggStatePerTrans pertrans;
3081  int existing_aggno;
3082  int existing_transno;
3083  List *same_input_transnos;
3084  Oid inputTypes[FUNC_MAX_ARGS];
3085  int numArguments;
3086  int numDirectArgs;
3087  HeapTuple aggTuple;
3088  Form_pg_aggregate aggform;
3089  AclResult aclresult;
3090  Oid transfn_oid,
3091  finalfn_oid;
3092  Oid serialfn_oid,
3093  deserialfn_oid;
3094  Expr *finalfnexpr;
3095  Oid aggtranstype;
3096  Datum textInitVal;
3097  Datum initValue;
3098  bool initValueIsNull;
3099 
3100  /* Planner should have assigned aggregate to correct level */
3101  Assert(aggref->agglevelsup == 0);
3102  /* ... and the split mode should match */
3103  Assert(aggref->aggsplit == aggstate->aggsplit);
3104 
3105  /* 1. Check for already processed aggs which can be re-used */
3106  existing_aggno = find_compatible_peragg(aggref, aggstate, aggno,
3107  &same_input_transnos);
3108  if (existing_aggno != -1)
3109  {
3110  /*
3111  * Existing compatible agg found. so just point the Aggref to the
3112  * same per-agg struct.
3113  */
3114  aggrefstate->aggno = existing_aggno;
3115  continue;
3116  }
3117 
3118  /* Mark Aggref state node with assigned index in the result array */
3119  peragg = &peraggs[++aggno];
3120  peragg->aggref = aggref;
3121  aggrefstate->aggno = aggno;
3122 
3123  /* Fetch the pg_aggregate row */
3124  aggTuple = SearchSysCache1(AGGFNOID,
3125  ObjectIdGetDatum(aggref->aggfnoid));
3126  if (!HeapTupleIsValid(aggTuple))
3127  elog(ERROR, "cache lookup failed for aggregate %u",
3128  aggref->aggfnoid);
3129  aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);
3130 
3131  /* Check permission to call aggregate function */
3132  aclresult = pg_proc_aclcheck(aggref->aggfnoid, GetUserId(),
3133  ACL_EXECUTE);
3134  if (aclresult != ACLCHECK_OK)
3135  aclcheck_error(aclresult, ACL_KIND_PROC,
3136  get_func_name(aggref->aggfnoid));
3138 
3139  /* planner recorded transition state type in the Aggref itself */
3140  aggtranstype = aggref->aggtranstype;
3141  Assert(OidIsValid(aggtranstype));
3142 
3143  /*
3144  * If this aggregation is performing state combines, then instead of
3145  * using the transition function, we'll use the combine function
3146  */
3147  if (DO_AGGSPLIT_COMBINE(aggstate->aggsplit))
3148  {
3149  transfn_oid = aggform->aggcombinefn;
3150 
3151  /* If not set then the planner messed up */
3152  if (!OidIsValid(transfn_oid))
3153  elog(ERROR, "combinefn not set for aggregate function");
3154  }
3155  else
3156  transfn_oid = aggform->aggtransfn;
3157 
3158  /* Final function only required if we're finalizing the aggregates */
3159  if (DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit))
3160  peragg->finalfn_oid = finalfn_oid = InvalidOid;
3161  else
3162  peragg->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
3163 
3164  serialfn_oid = InvalidOid;
3165  deserialfn_oid = InvalidOid;
3166 
3167  /*
3168  * Check if serialization/deserialization is required. We only do it
3169  * for aggregates that have transtype INTERNAL.
3170  */
3171  if (aggtranstype == INTERNALOID)
3172  {
3173  /*
3174  * The planner should only have generated a serialize agg node if
3175  * every aggregate with an INTERNAL state has a serialization
3176  * function. Verify that.
3177  */
3178  if (DO_AGGSPLIT_SERIALIZE(aggstate->aggsplit))
3179  {
3180  /* serialization only valid when not running finalfn */
3182 
3183  if (!OidIsValid(aggform->aggserialfn))
3184  elog(ERROR, "serialfunc not provided for serialization aggregation");
3185  serialfn_oid = aggform->aggserialfn;
3186  }
3187 
3188  /* Likewise for deserialization functions */
3189  if (DO_AGGSPLIT_DESERIALIZE(aggstate->aggsplit))
3190  {
3191  /* deserialization only valid when combining states */
3192  Assert(DO_AGGSPLIT_COMBINE(aggstate->aggsplit));
3193 
3194  if (!OidIsValid(aggform->aggdeserialfn))
3195  elog(ERROR, "deserialfunc not provided for deserialization aggregation");
3196  deserialfn_oid = aggform->aggdeserialfn;
3197  }
3198  }
3199 
3200  /* Check that aggregate owner has permission to call component fns */
3201  {
3202  HeapTuple procTuple;
3203  Oid aggOwner;
3204 
3205  procTuple = SearchSysCache1(PROCOID,
3206  ObjectIdGetDatum(aggref->aggfnoid));
3207  if (!HeapTupleIsValid(procTuple))
3208  elog(ERROR, "cache lookup failed for function %u",
3209  aggref->aggfnoid);
3210  aggOwner = ((Form_pg_proc) GETSTRUCT(procTuple))->proowner;
3211  ReleaseSysCache(procTuple);
3212 
3213  aclresult = pg_proc_aclcheck(transfn_oid, aggOwner,
3214  ACL_EXECUTE);
3215  if (aclresult != ACLCHECK_OK)
3216  aclcheck_error(aclresult, ACL_KIND_PROC,
3217  get_func_name(transfn_oid));
3218  InvokeFunctionExecuteHook(transfn_oid);
3219  if (OidIsValid(finalfn_oid))
3220  {
3221  aclresult = pg_proc_aclcheck(finalfn_oid, aggOwner,
3222  ACL_EXECUTE);
3223  if (aclresult != ACLCHECK_OK)
3224  aclcheck_error(aclresult, ACL_KIND_PROC,
3225  get_func_name(finalfn_oid));
3226  InvokeFunctionExecuteHook(finalfn_oid);
3227  }
3228  if (OidIsValid(serialfn_oid))
3229  {
3230  aclresult = pg_proc_aclcheck(serialfn_oid, aggOwner,
3231  ACL_EXECUTE);
3232  if (aclresult != ACLCHECK_OK)
3233  aclcheck_error(aclresult, ACL_KIND_PROC,
3234  get_func_name(serialfn_oid));
3235  InvokeFunctionExecuteHook(serialfn_oid);
3236  }
3237  if (OidIsValid(deserialfn_oid))
3238  {
3239  aclresult = pg_proc_aclcheck(deserialfn_oid, aggOwner,
3240  ACL_EXECUTE);
3241  if (aclresult != ACLCHECK_OK)
3242  aclcheck_error(aclresult, ACL_KIND_PROC,
3243  get_func_name(deserialfn_oid));
3244  InvokeFunctionExecuteHook(deserialfn_oid);
3245  }
3246  }
3247 
3248  /*
3249  * Get actual datatypes of the (nominal) aggregate inputs. These
3250  * could be different from the agg's declared input types, when the
3251  * agg accepts ANY or a polymorphic type.
3252  */
3253  numArguments = get_aggregate_argtypes(aggref, inputTypes);
3254 
3255  /* Count the "direct" arguments, if any */
3256  numDirectArgs = list_length(aggref->aggdirectargs);
3257 
3258  /* Detect how many arguments to pass to the finalfn */
3259  if (aggform->aggfinalextra)
3260  peragg->numFinalArgs = numArguments + 1;
3261  else
3262  peragg->numFinalArgs = numDirectArgs + 1;
3263 
3264  /*
3265  * build expression trees using actual argument & result types for the
3266  * finalfn, if it exists and is required.
3267  */
3268  if (OidIsValid(finalfn_oid))
3269  {
3270  build_aggregate_finalfn_expr(inputTypes,
3271  peragg->numFinalArgs,
3272  aggtranstype,
3273  aggref->aggtype,
3274  aggref->inputcollid,
3275  finalfn_oid,
3276  &finalfnexpr);
3277  fmgr_info(finalfn_oid, &peragg->finalfn);
3278  fmgr_info_set_expr((Node *) finalfnexpr, &peragg->finalfn);
3279  }
3280 
3281  /* get info about the output value's datatype */
3282  get_typlenbyval(aggref->aggtype,
3283  &peragg->resulttypeLen,
3284  &peragg->resulttypeByVal);
3285 
3286  /*
3287  * initval is potentially null, so don't try to access it as a struct
3288  * field. Must do it the hard way with SysCacheGetAttr.
3289  */
3290  textInitVal = SysCacheGetAttr(AGGFNOID, aggTuple,
3292  &initValueIsNull);
3293  if (initValueIsNull)
3294  initValue = (Datum) 0;
3295  else
3296  initValue = GetAggInitVal(textInitVal, aggtranstype);
3297 
3298  /*
3299  * 2. Build working state for invoking the transition function, or
3300  * look up previously initialized working state, if we can share it.
3301  *
3302  * find_compatible_peragg() already collected a list of per-Trans's
3303  * with the same inputs. Check if any of them have the same transition
3304  * function and initial value.
3305  */
3306  existing_transno = find_compatible_pertrans(aggstate, aggref,
3307  transfn_oid, aggtranstype,
3308  serialfn_oid, deserialfn_oid,
3309  initValue, initValueIsNull,
3310  same_input_transnos);
3311  if (existing_transno != -1)
3312  {
3313  /*
3314  * Existing compatible trans found, so just point the 'peragg' to
3315  * the same per-trans struct.
3316  */
3317  pertrans = &pertransstates[existing_transno];
3318  peragg->transno = existing_transno;
3319  }
3320  else
3321  {
3322  pertrans = &pertransstates[++transno];
3323  build_pertrans_for_aggref(pertrans, aggstate, estate,
3324  aggref, transfn_oid, aggtranstype,
3325  serialfn_oid, deserialfn_oid,
3326  initValue, initValueIsNull,
3327  inputTypes, numArguments);
3328  peragg->transno = transno;
3329  }
3330  ReleaseSysCache(aggTuple);
3331  }
3332 
3333  /*
3334  * Update numaggs to match the number of unique aggregates found. Also set
3335  * numstates to the number of unique aggregate states found.
3336  */
3337  aggstate->numaggs = aggno + 1;
3338  aggstate->numtrans = transno + 1;
3339 
3340  /*
3341  * Build a single projection computing the aggregate arguments for all
3342  * aggregates at once, that's considerably faster than doing it separately
3343  * for each.
3344  *
3345  * First create a targetlist combining the targetlist of all the
3346  * transitions.
3347  */
3348  combined_inputeval = NIL;
3349  column_offset = 0;
3350  for (transno = 0; transno < aggstate->numtrans; transno++)
3351  {
3352  AggStatePerTrans pertrans = &pertransstates[transno];
3353  ListCell *arg;
3354 
3355  pertrans->inputoff = column_offset;
3356 
3357  /*
3358  * Adjust resno in a copied target entries, to point into the combined
3359  * slot.
3360  */
3361  foreach(arg, pertrans->aggref->args)
3362  {
3363  TargetEntry *source_tle = lfirst_node(TargetEntry, arg);
3364  TargetEntry *tle;
3365 
3366  tle = flatCopyTargetEntry(source_tle);
3367  tle->resno += column_offset;
3368 
3369  combined_inputeval = lappend(combined_inputeval, tle);
3370  }
3371 
3372  column_offset += list_length(pertrans->aggref->args);
3373  }
3374 
3375  /* and then create a projection for that targetlist */
3376  aggstate->evaldesc = ExecTypeFromTL(combined_inputeval, false);
3377  aggstate->evalslot = ExecInitExtraTupleSlot(estate);
3378  aggstate->evalproj = ExecBuildProjectionInfo(combined_inputeval,
3379  aggstate->tmpcontext,
3380  aggstate->evalslot,
3381  &aggstate->ss.ps,
3382  NULL);
3383  ExecSetSlotDescriptor(aggstate->evalslot, aggstate->evaldesc);
3384 
3385  return aggstate;
3386 }
FmgrInfo * eqfunctions
Definition: nodeAgg.c:511
struct AggStatePerTransData * AggStatePerTrans
Definition: execnodes.h:1724
AggStatePerGroup * hash_pergroup
Definition: execnodes.h:1767
#define NIL
Definition: pg_list.h:69
struct AggStatePerGroupData * AggStatePerGroup
Definition: execnodes.h:1725
static void select_current_set(AggState *aggstate, int setno, bool is_hash)
Definition: nodeAgg.c:586
int numCols
Definition: plannodes.h:776
List * qual
Definition: plannodes.h:135
AggStatePerPhase phases
Definition: execnodes.h:1756
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 GETSTRUCT(TUP)
Definition: htup_details.h:656
AttrNumber * grpColIdx
Definition: plannodes.h:777
#define Anum_pg_aggregate_agginitval
Definition: pg_aggregate.h:113
List * lcons_int(int datum, List *list)
Definition: list.c:277
int numaggs
Definition: execnodes.h:1733
Oid GetUserId(void)
Definition: miscinit.c:283
bool agg_done
Definition: execnodes.h:1748
#define castNode(_type_, nodeptr)
Definition: nodes.h:578
TupleTableSlot * sort_slot
Definition: execnodes.h:1759
List * all_grouped_cols
Definition: execnodes.h:1752
Tuplesortstate * sort_out
Definition: execnodes.h:1758
ProjectionInfo * evalproj
Definition: execnodes.h:1770
ScanState ss
Definition: execnodes.h:1731
ExprContext * ps_ExprContext
Definition: execnodes.h:833
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:937
FmgrInfo * eqfunctions
Definition: nodeAgg.c:493
Oid inputcollid
Definition: primnodes.h:297
int current_phase
Definition: execnodes.h:1739
Definition: nodes.h:509
AggSplit aggsplit
Definition: execnodes.h:1736
List * args
Definition: primnodes.h:301
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1050
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:2004
AggStatePerTrans pertrans
Definition: execnodes.h:1741
EState * state
Definition: execnodes.h:805
int projected_set
Definition: execnodes.h:1749
unsigned int Oid
Definition: postgres_ext.h:31
HeapTuple grp_firstTuple
Definition: execnodes.h:1762
Aggref * aggref
Definition: nodeAgg.c:413
int current_set
Definition: execnodes.h:1750
#define OidIsValid(objectId)
Definition: c.h:538
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:767
TupleDesc evaldesc
Definition: execnodes.h:1771
int numtrans
Definition: execnodes.h:1734
void execTuplesHashPrepare(int numCols, Oid *eqOperators, FmgrInfo **eqFunctions, FmgrInfo **hashFunctions)
Definition: execGrouping.c:233
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:160
void ExecAssignResultTypeFromTL(PlanState *planstate)
Definition: execUtils.c:440
ExprContext * tmpcontext
Definition: execnodes.h:1744
#define FUNC_MAX_ARGS
Bitmapset ** grouped_cols
Definition: nodeAgg.c:492
PlanState ps
Definition: execnodes.h:1047
int maxsets
Definition: execnodes.h:1755
#define DO_AGGSPLIT_SERIALIZE(as)
Definition: nodes.h:769
AggStrategy aggstrategy
Definition: plannodes.h:774
bool table_filled
Definition: execnodes.h:1764
AggStrategy aggstrategy
Definition: execnodes.h:1735
#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:127
static void find_hash_columns(AggState *aggstate)
Definition: nodeAgg.c:1902
Tuplesortstate * sort_in
Definition: execnodes.h:1757
#define EXEC_FLAG_BACKWARD
Definition: executor.h:60
#define lfirst_node(type, lc)
Definition: pg_list.h:109
#define outerPlanState(node)
Definition: execnodes.h:845
Aggref * aggref
Definition: execnodes.h:624
#define list_nth_node(type, list, n)
Definition: pg_list.h:213
static int find_compatible_pertrans(AggState *aggstate, Aggref *newagg, Oid aggtransfn, Oid aggtranstype, Oid aggserialfn, Oid aggdeserialfn, Datum initValue, bool initValueIsNull, List *transnos)
Definition: nodeAgg.c:3790
static int initValue(long lng_val)
Definition: informix.c:702
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:487
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
static void build_hash_table(AggState *aggstate)
Definition: nodeAgg.c:1853
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:104
AttrNumber resno
Definition: primnodes.h:1368
Index agglevelsup
Definition: primnodes.h:309
List * aggdirectargs
Definition: primnodes.h:300
static Datum GetAggInitVal(Datum textInitVal, Oid transtype)
Definition: nodeAgg.c:3689
AggStatePerHash perhash
Definition: execnodes.h:1766
TargetEntry * flatCopyTargetEntry(TargetEntry *src_tle)
Definition: makefuncs.c:268
AggStrategy aggstrategy
Definition: nodeAgg.c:489
#define EXEC_FLAG_REWIND
Definition: executor.h:59
TupleDesc ExecTypeFromTL(List *targetList, bool hasoid)
Definition: execTuples.c:888
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:179
#define outerPlan(node)
Definition: plannodes.h:164
List * lappend(List *list, void *datum)
Definition: list.c:128
int num_hashes
Definition: execnodes.h:1765
Plan plan
Definition: plannodes.h:773
bool input_done
Definition: execnodes.h:1747
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:121
TupleTableSlot * evalslot
Definition: execnodes.h:1769
ExprContext * hashcontext
Definition: execnodes.h:1742
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:3717
void * palloc0(Size size)
Definition: mcxt.c:878
AclResult
Definition: acl.h:170
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:247
AggStatePerGroup pergroup
Definition: execnodes.h:1761
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1278
List * groupingSets
Definition: plannodes.h:782
int16 resulttypeLen
Definition: nodeAgg.c:439
static void initialize_phase(AggState *aggstate, int newphase)
Definition: nodeAgg.c:604
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
Plan * plan
Definition: execnodes.h:803
#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:800
ExprContext ** aggcontexts
Definition: execnodes.h:1743
#define makeNode(_type_)
Definition: nodes.h:557
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
FmgrInfo * hashfunctions
Definition: nodeAgg.c:510
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
#define EXEC_FLAG_MARK
Definition: executor.h:61
AggSplit aggsplit
Definition: plannodes.h:775
struct AggStatePerAggData * AggStatePerAgg
Definition: execnodes.h:1723
FormData_pg_aggregate * Form_pg_aggregate
Definition: pg_aggregate.h:87
AggSplit aggsplit
Definition: primnodes.h:310
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:418
static int list_length(const List *l)
Definition: pg_list.h:89
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:768
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:2001
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:698
#define DO_AGGSPLIT_DESERIALIZE(as)
Definition: nodes.h:770
struct Plan * lefttree
Definition: plannodes.h:136
int numphases
Definition: execnodes.h:1738
ExprState * qual
Definition: execnodes.h:817
void ExecAssignScanTypeFromOuterPlan(ScanState *scanstate)
Definition: execUtils.c:552
Oid * grpOperators
Definition: plannodes.h:778
void * palloc(Size size)
Definition: mcxt.c:849
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, PlanState *parent, TupleDesc inputDesc)
Definition: execExpr.c:301
List * chain
Definition: plannodes.h:783
AggStatePerAgg peragg
Definition: execnodes.h:1740
#define ACL_EXECUTE
Definition: parsenodes.h:79
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4446
int i
Oid aggtranstype
Definition: primnodes.h:298
void * arg
AggStatePerTrans curpertrans
Definition: execnodes.h:1746
Oid aggtype
Definition: primnodes.h:295
bool resulttypeByVal
Definition: nodeAgg.c:440
Definition: plannodes.h:771
#define elog
Definition: elog.h:219
List * aggs
Definition: execnodes.h:1732
FmgrInfo * execTuplesMatchPrepare(int numCols, Oid *eqOperators)
Definition: execGrouping.c:204
TupleTableSlot * hashslot
Definition: nodeAgg.c:509
int get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
Definition: parse_agg.c:1786
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:3397
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:140
Definition: pg_list.h:45
FmgrInfo finalfn
Definition: nodeAgg.c:425
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:755
void ExecReScanAgg ( AggState node)

Definition at line 3883 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, NULL, 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().

3884 {
3885  ExprContext *econtext = node->ss.ps.ps_ExprContext;
3887  Agg *aggnode = (Agg *) node->ss.ps.plan;
3888  int transno;
3889  int numGroupingSets = Max(node->maxsets, 1);
3890  int setno;
3891 
3892  node->agg_done = false;
3893 
3894  if (node->aggstrategy == AGG_HASHED)
3895  {
3896  /*
3897  * In the hashed case, if we haven't yet built the hash table then we
3898  * can just return; nothing done yet, so nothing to undo. If subnode's
3899  * chgParam is not NULL then it will be re-scanned by ExecProcNode,
3900  * else no reason to re-scan it at all.
3901  */
3902  if (!node->table_filled)
3903  return;
3904 
3905  /*
3906  * If we do have the hash table, and the subplan does not have any
3907  * parameter changes, and none of our own parameter changes affect
3908  * input expressions of the aggregated functions, then we can just
3909  * rescan the existing hash table; no need to build it again.
3910  */
3911  if (outerPlan->chgParam == NULL &&
3912  !bms_overlap(node->ss.ps.chgParam, aggnode->aggParams))
3913  {
3915  &node->perhash[0].hashiter);
3916  select_current_set(node, 0, true);
3917  return;
3918  }
3919  }
3920 
3921  /* Make sure we have closed any open tuplesorts */
3922  for (transno = 0; transno < node->numtrans; transno++)
3923  {
3924  for (setno = 0; setno < numGroupingSets; setno++)
3925  {
3926  AggStatePerTrans pertrans = &node->pertrans[transno];
3927 
3928  if (pertrans->sortstates[setno])
3929  {
3930  tuplesort_end(pertrans->sortstates[setno]);
3931  pertrans->sortstates[setno] = NULL;
3932  }
3933  }
3934  }
3935 
3936  /*
3937  * We don't need to ReScanExprContext the output tuple context here;
3938  * ExecReScan already did it. But we do need to reset our per-grouping-set
3939  * contexts, which may have transvalues stored in them. (We use rescan
3940  * rather than just reset because transfns may have registered callbacks
3941  * that need to be run now.) For the AGG_HASHED case, see below.
3942  */
3943 
3944  for (setno = 0; setno < numGroupingSets; setno++)
3945  {
3946  ReScanExprContext(node->aggcontexts[setno]);
3947  }
3948 
3949  /* Release first tuple of group, if we have made a copy */
3950  if (node->grp_firstTuple != NULL)
3951  {
3953  node->grp_firstTuple = NULL;
3954  }
3956 
3957  /* Forget current agg values */
3958  MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numaggs);
3959  MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numaggs);
3960 
3961  /*
3962  * With AGG_HASHED/MIXED, the hash table is allocated in a sub-context of
3963  * the hashcontext. This used to be an issue, but now, resetting a context
3964  * automatically deletes sub-contexts too.
3965  */
3966  if (node->aggstrategy == AGG_HASHED || node->aggstrategy == AGG_MIXED)
3967  {
3969  /* Rebuild an empty hash table */
3970  build_hash_table(node);
3971  node->table_filled = false;
3972  /* iterator will be reset when the table is filled */
3973  }
3974 
3975  if (node->aggstrategy != AGG_HASHED)
3976  {
3977  /*
3978  * Reset the per-group state (in particular, mark transvalues null)
3979  */
3980  MemSet(node->pergroup, 0,
3981  sizeof(AggStatePerGroupData) * node->numaggs * numGroupingSets);
3982 
3983  /* reset to phase 1 */
3984  initialize_phase(node, 1);
3985 
3986  node->input_done = false;
3987  node->projected_set = -1;
3988  }
3989 
3990  if (outerPlan->chgParam == NULL)
3991  ExecReScan(outerPlan);
3992 }
static void select_current_set(AggState *aggstate, int setno, bool is_hash)
Definition: nodeAgg.c:586
Datum * ecxt_aggvalues
Definition: execnodes.h:213
int numaggs
Definition: execnodes.h:1733
bool agg_done
Definition: execnodes.h:1748
ScanState ss
Definition: execnodes.h:1731
ExprContext * ps_ExprContext
Definition: execnodes.h:833
void ExecReScan(PlanState *node)
Definition: execAmi.c:75
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
#define MemSet(start, val, len)
Definition: c.h:857
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1050
AggStatePerTrans pertrans
Definition: execnodes.h:1741
int projected_set
Definition: execnodes.h:1749
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
HeapTuple grp_firstTuple
Definition: execnodes.h:1762
int numtrans
Definition: execnodes.h:1734
PlanState ps
Definition: execnodes.h:1047
int maxsets
Definition: execnodes.h:1755
bool table_filled
Definition: execnodes.h:1764
AggStrategy aggstrategy
Definition: execnodes.h:1735
#define outerPlanState(node)
Definition: execnodes.h:845
Tuplesortstate ** sortstates
Definition: nodeAgg.c:380
Bitmapset * aggParams
Definition: plannodes.h:780
static void build_hash_table(AggState *aggstate)
Definition: nodeAgg.c:1853
AggStatePerHash perhash
Definition: execnodes.h:1766
Bitmapset * chgParam
Definition: execnodes.h:827
#define outerPlan(node)
Definition: plannodes.h:164
TupleHashIterator hashiter
Definition: nodeAgg.c:508
bool input_done
Definition: execnodes.h:1747
ExprContext * hashcontext
Definition: execnodes.h:1742
bool * ecxt_aggnulls
Definition: execnodes.h:214
uintptr_t Datum
Definition: postgres.h:372
AggStatePerGroup pergroup
Definition: execnodes.h:1761
static void initialize_phase(AggState *aggstate, int newphase)
Definition: nodeAgg.c:604
Plan * plan
Definition: execnodes.h:803
#define ResetTupleHashIterator(htable, iter)
Definition: execnodes.h:599
#define Max(x, y)
Definition: c.h:800
ExprContext ** aggcontexts
Definition: execnodes.h:1743
#define NULL
Definition: c.h:229
void ReScanExprContext(ExprContext *econtext)
Definition: execUtils.c:376
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:443
Definition: plannodes.h:771
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1167
TupleHashTable hashtable
Definition: nodeAgg.c:507
Size hash_agg_entry_size ( int  numAggs)

Definition at line 2004 of file nodeAgg.c.

References MAXALIGN.

Referenced by create_distinct_paths(), and estimate_hashagg_tablesize().

2005 {
2006  Size entrysize;
2007 
2008  /* This must match build_hash_table */
2009  entrysize = sizeof(TupleHashEntryData) +
2010  numAggs * sizeof(AggStatePerGroupData);
2011  entrysize = MAXALIGN(entrysize);
2012 
2013  return entrysize;
2014 }
struct TupleHashEntryData TupleHashEntryData
size_t Size
Definition: c.h:356
#define MAXALIGN(LEN)
Definition: c.h:588