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

References elog, and ERROR.

4135 {
4136  elog(ERROR, "aggregate function %u called as normal function",
4137  fcinfo->flinfo->fn_oid);
4138  return (Datum) 0; /* keep compiler quiet */
4139 }
#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:2485
bool agg_done
Definition: execnodes.h:1775
return result
Definition: formatting.c:1633
bool table_filled
Definition: execnodes.h:1790
static TupleTableSlot * agg_retrieve_hash_table(AggState *aggstate)
Definition: nodeAgg.c:2532
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:1764
#define NULL
Definition: c.h:229
void ExecEndAgg ( AggState node)

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

3837 {
3839  int transno;
3840  int numGroupingSets = Max(node->maxsets, 1);
3841  int setno;
3842 
3843  /* Make sure we have closed any open tuplesorts */
3844 
3845  if (node->sort_in)
3846  tuplesort_end(node->sort_in);
3847  if (node->sort_out)
3848  tuplesort_end(node->sort_out);
3849 
3850  for (transno = 0; transno < node->numtrans; transno++)
3851  {
3852  AggStatePerTrans pertrans = &node->pertrans[transno];
3853 
3854  for (setno = 0; setno < numGroupingSets; setno++)
3855  {
3856  if (pertrans->sortstates[setno])
3857  tuplesort_end(pertrans->sortstates[setno]);
3858  }
3859  }
3860 
3861  /* And ensure any agg shutdown callbacks have been called */
3862  for (setno = 0; setno < numGroupingSets; setno++)
3863  ReScanExprContext(node->aggcontexts[setno]);
3864  if (node->hashcontext)
3866 
3867  /*
3868  * We don't actually free any ExprContexts here (see comment in
3869  * ExecFreeExprContext), just unlinking the output one from the plan node
3870  * suffices.
3871  */
3872  ExecFreeExprContext(&node->ss.ps);
3873 
3874  /* clean up tuple table */
3876 
3877  outerPlan = outerPlanState(node);
3878  ExecEndNode(outerPlan);
3879 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:654
Tuplesortstate * sort_out
Definition: execnodes.h:1784
ScanState ss
Definition: execnodes.h:1758
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1078
AggStatePerTrans pertrans
Definition: execnodes.h:1768
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:516
int numtrans
Definition: execnodes.h:1761
PlanState ps
Definition: execnodes.h:1075
int maxsets
Definition: execnodes.h:1781
Tuplesortstate * sort_in
Definition: execnodes.h:1783
#define outerPlanState(node)
Definition: execnodes.h:874
Tuplesortstate ** sortstates
Definition: nodeAgg.c:380
#define outerPlan(node)
Definition: plannodes.h:174
ExprContext * hashcontext
Definition: execnodes.h:1769
#define Max(x, y)
Definition: c.h:800
ExprContext ** aggcontexts
Definition: execnodes.h:1770
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 2657 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().

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

3883 {
3884  ExprContext *econtext = node->ss.ps.ps_ExprContext;
3886  Agg *aggnode = (Agg *) node->ss.ps.plan;
3887  int transno;
3888  int numGroupingSets = Max(node->maxsets, 1);
3889  int setno;
3890 
3891  node->agg_done = false;
3892 
3893  if (node->aggstrategy == AGG_HASHED)
3894  {
3895  /*
3896  * In the hashed case, if we haven't yet built the hash table then we
3897  * can just return; nothing done yet, so nothing to undo. If subnode's
3898  * chgParam is not NULL then it will be re-scanned by ExecProcNode,
3899  * else no reason to re-scan it at all.
3900  */
3901  if (!node->table_filled)
3902  return;
3903 
3904  /*
3905  * If we do have the hash table, and the subplan does not have any
3906  * parameter changes, and none of our own parameter changes affect
3907  * input expressions of the aggregated functions, then we can just
3908  * rescan the existing hash table; no need to build it again.
3909  */
3910  if (outerPlan->chgParam == NULL &&
3911  !bms_overlap(node->ss.ps.chgParam, aggnode->aggParams))
3912  {
3914  &node->perhash[0].hashiter);
3915  select_current_set(node, 0, true);
3916  return;
3917  }
3918  }
3919 
3920  /* Make sure we have closed any open tuplesorts */
3921  for (transno = 0; transno < node->numtrans; transno++)
3922  {
3923  for (setno = 0; setno < numGroupingSets; setno++)
3924  {
3925  AggStatePerTrans pertrans = &node->pertrans[transno];
3926 
3927  if (pertrans->sortstates[setno])
3928  {
3929  tuplesort_end(pertrans->sortstates[setno]);
3930  pertrans->sortstates[setno] = NULL;
3931  }
3932  }
3933  }
3934 
3935  /*
3936  * We don't need to ReScanExprContext the output tuple context here;
3937  * ExecReScan already did it. But we do need to reset our per-grouping-set
3938  * contexts, which may have transvalues stored in them. (We use rescan
3939  * rather than just reset because transfns may have registered callbacks
3940  * that need to be run now.) For the AGG_HASHED case, see below.
3941  */
3942 
3943  for (setno = 0; setno < numGroupingSets; setno++)
3944  {
3945  ReScanExprContext(node->aggcontexts[setno]);
3946  }
3947 
3948  /* Release first tuple of group, if we have made a copy */
3949  if (node->grp_firstTuple != NULL)
3950  {
3952  node->grp_firstTuple = NULL;
3953  }
3955 
3956  /* Forget current agg values */
3957  MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numaggs);
3958  MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numaggs);
3959 
3960  /*
3961  * With AGG_HASHED/MIXED, the hash table is allocated in a sub-context of
3962  * the hashcontext. This used to be an issue, but now, resetting a context
3963  * automatically deletes sub-contexts too.
3964  */
3965  if (node->aggstrategy == AGG_HASHED || node->aggstrategy == AGG_MIXED)
3966  {
3968  /* Rebuild an empty hash table */
3969  build_hash_table(node);
3970  node->table_filled = false;
3971  /* iterator will be reset when the table is filled */
3972  }
3973 
3974  if (node->aggstrategy != AGG_HASHED)
3975  {
3976  /*
3977  * Reset the per-group state (in particular, mark transvalues null)
3978  */
3979  MemSet(node->pergroup, 0,
3980  sizeof(AggStatePerGroupData) * node->numaggs * numGroupingSets);
3981 
3982  /* reset to phase 1 */
3983  initialize_phase(node, 1);
3984 
3985  node->input_done = false;
3986  node->projected_set = -1;
3987  }
3988 
3989  if (outerPlan->chgParam == NULL)
3990  ExecReScan(outerPlan);
3991 }
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:1760
bool agg_done
Definition: execnodes.h:1775
ScanState ss
Definition: execnodes.h:1758
ExprContext * ps_ExprContext
Definition: execnodes.h:862
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:1078
AggStatePerTrans pertrans
Definition: execnodes.h:1768
int projected_set
Definition: execnodes.h:1776
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1372
HeapTuple grp_firstTuple
Definition: execnodes.h:1788
int numtrans
Definition: execnodes.h:1761
PlanState ps
Definition: execnodes.h:1075
int maxsets
Definition: execnodes.h:1781
bool table_filled
Definition: execnodes.h:1790
AggStrategy aggstrategy
Definition: execnodes.h:1762
#define outerPlanState(node)
Definition: execnodes.h:874
Tuplesortstate ** sortstates
Definition: nodeAgg.c:380
Bitmapset * aggParams
Definition: plannodes.h:789
static void build_hash_table(AggState *aggstate)
Definition: nodeAgg.c:1853
AggStatePerHash perhash
Definition: execnodes.h:1792
Bitmapset * chgParam
Definition: execnodes.h:856
#define outerPlan(node)
Definition: plannodes.h:174
TupleHashIterator hashiter
Definition: nodeAgg.c:508
bool input_done
Definition: execnodes.h:1774
ExprContext * hashcontext
Definition: execnodes.h:1769
bool * ecxt_aggnulls
Definition: execnodes.h:214
uintptr_t Datum
Definition: postgres.h:372
AggStatePerGroup pergroup
Definition: execnodes.h:1787
static void initialize_phase(AggState *aggstate, int newphase)
Definition: nodeAgg.c:604
Plan * plan
Definition: execnodes.h:832
#define ResetTupleHashIterator(htable, iter)
Definition: execnodes.h:629
#define Max(x, y)
Definition: c.h:800
ExprContext ** aggcontexts
Definition: execnodes.h:1770
#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:780
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