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 4132 of file nodeAgg.c.

References elog, and ERROR.

4133 {
4134  elog(ERROR, "aggregate function %u called as normal function",
4135  fcinfo->flinfo->fn_oid);
4136  return (Datum) 0; /* keep compiler quiet */
4137 }
#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 2096 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().

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

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

3835 {
3837  int transno;
3838  int numGroupingSets = Max(node->maxsets, 1);
3839  int setno;
3840 
3841  /* Make sure we have closed any open tuplesorts */
3842 
3843  if (node->sort_in)
3844  tuplesort_end(node->sort_in);
3845  if (node->sort_out)
3846  tuplesort_end(node->sort_out);
3847 
3848  for (transno = 0; transno < node->numtrans; transno++)
3849  {
3850  AggStatePerTrans pertrans = &node->pertrans[transno];
3851 
3852  for (setno = 0; setno < numGroupingSets; setno++)
3853  {
3854  if (pertrans->sortstates[setno])
3855  tuplesort_end(pertrans->sortstates[setno]);
3856  }
3857  }
3858 
3859  /* And ensure any agg shutdown callbacks have been called */
3860  for (setno = 0; setno < numGroupingSets; setno++)
3861  ReScanExprContext(node->aggcontexts[setno]);
3862  if (node->hashcontext)
3864 
3865  /*
3866  * We don't actually free any ExprContexts here (see comment in
3867  * ExecFreeExprContext), just unlinking the output one from the plan node
3868  * suffices.
3869  */
3870  ExecFreeExprContext(&node->ss.ps);
3871 
3872  /* clean up tuple table */
3874 
3875  outerPlan = outerPlanState(node);
3876  ExecEndNode(outerPlan);
3877 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:644
Tuplesortstate * sort_out
Definition: execnodes.h:1733
ScanState ss
Definition: execnodes.h:1706
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1047
AggStatePerTrans pertrans
Definition: execnodes.h:1716
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:511
int numtrans
Definition: execnodes.h:1709
PlanState ps
Definition: execnodes.h:1044
int maxsets
Definition: execnodes.h:1730
Tuplesortstate * sort_in
Definition: execnodes.h:1732
#define outerPlanState(node)
Definition: execnodes.h:842
Tuplesortstate ** sortstates
Definition: nodeAgg.c:380
#define outerPlan(node)
Definition: plannodes.h:162
ExprContext * hashcontext
Definition: execnodes.h:1717
#define Max(x, y)
Definition: c.h:800
ExprContext ** aggcontexts
Definition: execnodes.h:1718
void ReScanExprContext(ExprContext *econtext)
Definition: execUtils.c:371
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1157
AggState* ExecInitAgg ( Agg node,
EState estate,
int  eflags 
)

Definition at line 2655 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, list_length(), list_nth(), 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().

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

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

Definition at line 2001 of file nodeAgg.c.

References MAXALIGN.

Referenced by create_distinct_paths(), and estimate_hashagg_tablesize().

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