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

Go to the source code of this file.

Data Structures

struct  AggStatePerTransData
 
struct  AggStatePerAggData
 
struct  AggStatePerGroupData
 
struct  AggStatePerPhaseData
 
struct  AggStatePerHashData
 

Macros

#define FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE   0
 
#define FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL   1
 
#define FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE   2
 

Typedefs

typedef struct AggStatePerTransData AggStatePerTransData
 
typedef struct AggStatePerAggData AggStatePerAggData
 
typedef struct AggStatePerGroupData AggStatePerGroupData
 
typedef struct AggStatePerPhaseData AggStatePerPhaseData
 
typedef struct AggStatePerHashData AggStatePerHashData
 

Functions

AggStateExecInitAgg (Agg *node, EState *estate, int eflags)
 
void ExecEndAgg (AggState *node)
 
void ExecReScanAgg (AggState *node)
 
Size hash_agg_entry_size (int numTrans, Size tupleWidth, Size transitionSpace)
 
void hash_agg_set_limits (double hashentrysize, uint64 input_groups, int used_bits, Size *mem_limit, uint64 *ngroups_limit, int *num_partitions)
 

Macro Definition Documentation

◆ FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE

#define FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE   2

Definition at line 248 of file nodeAgg.h.

Referenced by llvm_compile_expr().

◆ FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE

#define FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE   0

Definition at line 243 of file nodeAgg.h.

Referenced by llvm_compile_expr().

◆ FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL

#define FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL   1

Definition at line 245 of file nodeAgg.h.

Referenced by llvm_compile_expr().

Typedef Documentation

◆ AggStatePerAggData

◆ AggStatePerGroupData

◆ AggStatePerHashData

◆ AggStatePerPhaseData

◆ AggStatePerTransData

Function Documentation

◆ ExecEndAgg()

void ExecEndAgg ( AggState node)

Definition at line 4483 of file nodeAgg.c.

References AggState::aggcontexts, ExecClearTuple(), ExecEndNode(), ExecFreeExprContext(), AggState::hash_metacxt, hashagg_reset_spill_state(), AggState::hashcontext, Max, AggState::maxsets, MemoryContextDelete(), 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().

4484 {
4486  int transno;
4487  int numGroupingSets = Max(node->maxsets, 1);
4488  int setno;
4489 
4490  /* Make sure we have closed any open tuplesorts */
4491 
4492  if (node->sort_in)
4493  tuplesort_end(node->sort_in);
4494  if (node->sort_out)
4495  tuplesort_end(node->sort_out);
4496 
4498 
4499  if (node->hash_metacxt != NULL)
4500  {
4502  node->hash_metacxt = NULL;
4503  }
4504 
4505  for (transno = 0; transno < node->numtrans; transno++)
4506  {
4507  AggStatePerTrans pertrans = &node->pertrans[transno];
4508 
4509  for (setno = 0; setno < numGroupingSets; setno++)
4510  {
4511  if (pertrans->sortstates[setno])
4512  tuplesort_end(pertrans->sortstates[setno]);
4513  }
4514  }
4515 
4516  /* And ensure any agg shutdown callbacks have been called */
4517  for (setno = 0; setno < numGroupingSets; setno++)
4518  ReScanExprContext(node->aggcontexts[setno]);
4519  if (node->hashcontext)
4521 
4522  /*
4523  * We don't actually free any ExprContexts here (see comment in
4524  * ExecFreeExprContext), just unlinking the output one from the plan node
4525  * suffices.
4526  */
4527  ExecFreeExprContext(&node->ss.ps);
4528 
4529  /* clean up tuple table */
4531 
4532  outerPlan = outerPlanState(node);
4533  ExecEndNode(outerPlan);
4534 }
static void hashagg_reset_spill_state(AggState *aggstate)
Definition: nodeAgg.c:3113
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:543
Tuplesortstate * sort_out
Definition: execnodes.h:2155
ScanState ss
Definition: execnodes.h:2125
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1335
AggStatePerTrans pertrans
Definition: execnodes.h:2135
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:655
int numtrans
Definition: execnodes.h:2128
PlanState ps
Definition: execnodes.h:1332
int maxsets
Definition: execnodes.h:2152
MemoryContext hash_metacxt
Definition: execnodes.h:2164
Tuplesortstate * sort_in
Definition: execnodes.h:2154
#define outerPlanState(node)
Definition: execnodes.h:1039
Tuplesortstate ** sortstates
Definition: nodeAgg.h:153
#define outerPlan(node)
Definition: plannodes.h:172
ExprContext * hashcontext
Definition: execnodes.h:2136
#define Max(x, y)
Definition: c.h:914
ExprContext ** aggcontexts
Definition: execnodes.h:2137
void ReScanExprContext(ExprContext *econtext)
Definition: execUtils.c:443
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1388

◆ ExecInitAgg()

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

Definition at line 3165 of file nodeAgg.c.

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, AggState::agg_done, AGG_HASHED, AGG_MIXED, AGG_PLAIN, AGG_SORTED, AggState::aggcontexts, AggStatePerAggData::aggdirectargs, Aggref::aggdirectargs, AGGFNOID, Aggref::aggfnoid, Aggref::agglevelsup, AggrefExprState::aggno, AggStatePerPhaseData::aggnode, AggStatePerHashData::aggnode, AggStatePerAggData::aggref, AggrefExprState::aggref, AggState::aggs, AggStatePerTransData::aggshared, Aggref::aggsplit, Agg::aggsplit, AggState::aggsplit, AggStatePerPhaseData::aggstrategy, Agg::aggstrategy, AggState::aggstrategy, Aggref::aggtranstype, Aggref::aggtype, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, bms_add_member(), bms_add_members(), bms_next_member(), build_aggregate_finalfn_expr(), build_hash_tables(), build_pertrans_for_aggref(), castNode, Agg::chain, CreateWorkExprContext(), AggState::curperagg, AggState::curpertrans, AggState::current_set, DO_AGGSPLIT_COMBINE, DO_AGGSPLIT_DESERIALIZE, DO_AGGSPLIT_SERIALIZE, DO_AGGSPLIT_SKIPFINAL, ExprContext::ecxt_aggnulls, ExprContext::ecxt_aggvalues, elog, AggStatePerPhaseData::eqfunctions, ereport, errcode(), errmsg(), ERROR, EState::es_query_cxt, AggStatePerPhaseData::evaltrans, AggStatePerPhaseData::evaltrans_cache, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, EXEC_FLAG_REWIND, ExecAgg(), ExecAssignExprContext(), ExecAssignProjectionInfo(), ExecBuildAggTrans(), ExecCreateScanSlotFromOuterPlan(), ExecGetResultSlotOps(), ExecInitExprList(), ExecInitExtraTupleSlot(), ExecInitNode(), ExecInitQual(), ExecInitResultTupleSlotTL(), PlanState::ExecProcNode, execTuplesMatchPrepare(), AggStatePerAggData::finalfn, AggStatePerAggData::finalfn_oid, find_compatible_peragg(), find_compatible_pertrans(), find_hash_columns(), 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::grpCollations, Agg::grpOperators, AggStatePerPhaseData::gset_lengths, hash_agg_entry_size(), hash_agg_set_limits(), AggState::hashcontext, HeapTupleIsValid, i, initialize_phase(), initValue(), AggState::input_done, Aggref::inputcollid, InvalidOid, InvokeFunctionExecuteHook, lcons_int(), Plan::lefttree, lfirst, list_length(), list_nth_node, makeNode, Max, AggState::maxsets, NIL, AggState::numaggs, AggStatePerHashData::numCols, Agg::numCols, AggStatePerAggData::numFinalArgs, AggState::numphases, AggStatePerPhaseData::numsets, AggState::numtrans, OBJECT_AGGREGATE, OBJECT_FUNCTION, ObjectIdGetDatum, OidIsValid, PlanState::outerops, PlanState::outeropsfixed, PlanState::outeropsset, outerPlan, outerPlanState, palloc(), palloc0(), AggState::peragg, AggState::pergroups, AggState::pertrans, pg_proc_aclcheck(), Agg::plan, PlanState::plan, Plan::plan_width, PROCOID, AggState::projected_set, ScanState::ps, PlanState::ps_ExprContext, Plan::qual, PlanState::qual, ReleaseSysCache(), AggStatePerAggData::resulttypeByVal, AggStatePerAggData::resulttypeLen, SearchSysCache1(), select_current_set(), AggStatePerAggData::shareable, AggState::sort_in, AggState::sort_out, AggState::sort_slot, AggStatePerPhaseData::sortnode, AggState::ss, ScanState::ss_ScanTupleSlot, PlanState::state, SysCacheGetAttr(), AggState::tmpcontext, Agg::transitionSpace, AggStatePerAggData::transno, TupleTableSlot::tts_tupleDescriptor, TTSOpsMinimalTuple, and TTSOpsVirtual.

Referenced by ExecInitNode().

3166 {
3167  AggState *aggstate;
3168  AggStatePerAgg peraggs;
3169  AggStatePerTrans pertransstates;
3170  AggStatePerGroup *pergroups;
3171  Plan *outerPlan;
3172  ExprContext *econtext;
3173  TupleDesc scanDesc;
3174  int numaggs,
3175  transno,
3176  aggno;
3177  int phase;
3178  int phaseidx;
3179  ListCell *l;
3180  Bitmapset *all_grouped_cols = NULL;
3181  int numGroupingSets = 1;
3182  int numPhases;
3183  int numHashes;
3184  int i = 0;
3185  int j = 0;
3186  bool use_hashing = (node->aggstrategy == AGG_HASHED ||
3187  node->aggstrategy == AGG_MIXED);
3188 
3189  /* check for unsupported flags */
3190  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
3191 
3192  /*
3193  * create state structure
3194  */
3195  aggstate = makeNode(AggState);
3196  aggstate->ss.ps.plan = (Plan *) node;
3197  aggstate->ss.ps.state = estate;
3198  aggstate->ss.ps.ExecProcNode = ExecAgg;
3199 
3200  aggstate->aggs = NIL;
3201  aggstate->numaggs = 0;
3202  aggstate->numtrans = 0;
3203  aggstate->aggstrategy = node->aggstrategy;
3204  aggstate->aggsplit = node->aggsplit;
3205  aggstate->maxsets = 0;
3206  aggstate->projected_set = -1;
3207  aggstate->current_set = 0;
3208  aggstate->peragg = NULL;
3209  aggstate->pertrans = NULL;
3210  aggstate->curperagg = NULL;
3211  aggstate->curpertrans = NULL;
3212  aggstate->input_done = false;
3213  aggstate->agg_done = false;
3214  aggstate->pergroups = NULL;
3215  aggstate->grp_firstTuple = NULL;
3216  aggstate->sort_in = NULL;
3217  aggstate->sort_out = NULL;
3218 
3219  /*
3220  * phases[0] always exists, but is dummy in sorted/plain mode
3221  */
3222  numPhases = (use_hashing ? 1 : 2);
3223  numHashes = (use_hashing ? 1 : 0);
3224 
3225  /*
3226  * Calculate the maximum number of grouping sets in any phase; this
3227  * determines the size of some allocations. Also calculate the number of
3228  * phases, since all hashed/mixed nodes contribute to only a single phase.
3229  */
3230  if (node->groupingSets)
3231  {
3232  numGroupingSets = list_length(node->groupingSets);
3233 
3234  foreach(l, node->chain)
3235  {
3236  Agg *agg = lfirst(l);
3237 
3238  numGroupingSets = Max(numGroupingSets,
3239  list_length(agg->groupingSets));
3240 
3241  /*
3242  * additional AGG_HASHED aggs become part of phase 0, but all
3243  * others add an extra phase.
3244  */
3245  if (agg->aggstrategy != AGG_HASHED)
3246  ++numPhases;
3247  else
3248  ++numHashes;
3249  }
3250  }
3251 
3252  aggstate->maxsets = numGroupingSets;
3253  aggstate->numphases = numPhases;
3254 
3255  aggstate->aggcontexts = (ExprContext **)
3256  palloc0(sizeof(ExprContext *) * numGroupingSets);
3257 
3258  /*
3259  * Create expression contexts. We need three or more, one for
3260  * per-input-tuple processing, one for per-output-tuple processing, one
3261  * for all the hashtables, and one for each grouping set. The per-tuple
3262  * memory context of the per-grouping-set ExprContexts (aggcontexts)
3263  * replaces the standalone memory context formerly used to hold transition
3264  * values. We cheat a little by using ExecAssignExprContext() to build
3265  * all of them.
3266  *
3267  * NOTE: the details of what is stored in aggcontexts and what is stored
3268  * in the regular per-query memory context are driven by a simple
3269  * decision: we want to reset the aggcontext at group boundaries (if not
3270  * hashing) and in ExecReScanAgg to recover no-longer-wanted space.
3271  */
3272  ExecAssignExprContext(estate, &aggstate->ss.ps);
3273  aggstate->tmpcontext = aggstate->ss.ps.ps_ExprContext;
3274 
3275  for (i = 0; i < numGroupingSets; ++i)
3276  {
3277  ExecAssignExprContext(estate, &aggstate->ss.ps);
3278  aggstate->aggcontexts[i] = aggstate->ss.ps.ps_ExprContext;
3279  }
3280 
3281  if (use_hashing)
3282  aggstate->hashcontext = CreateWorkExprContext(estate);
3283 
3284  ExecAssignExprContext(estate, &aggstate->ss.ps);
3285 
3286  /*
3287  * Initialize child nodes.
3288  *
3289  * If we are doing a hashed aggregation then the child plan does not need
3290  * to handle REWIND efficiently; see ExecReScanAgg.
3291  */
3292  if (node->aggstrategy == AGG_HASHED)
3293  eflags &= ~EXEC_FLAG_REWIND;
3294  outerPlan = outerPlan(node);
3295  outerPlanState(aggstate) = ExecInitNode(outerPlan, estate, eflags);
3296 
3297  /*
3298  * initialize source tuple type.
3299  */
3300  aggstate->ss.ps.outerops =
3302  &aggstate->ss.ps.outeropsfixed);
3303  aggstate->ss.ps.outeropsset = true;
3304 
3305  ExecCreateScanSlotFromOuterPlan(estate, &aggstate->ss,
3306  aggstate->ss.ps.outerops);
3307  scanDesc = aggstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
3308 
3309  /*
3310  * If there are more than two phases (including a potential dummy phase
3311  * 0), input will be resorted using tuplesort. Need a slot for that.
3312  */
3313  if (numPhases > 2)
3314  {
3315  aggstate->sort_slot = ExecInitExtraTupleSlot(estate, scanDesc,
3317 
3318  /*
3319  * The output of the tuplesort, and the output from the outer child
3320  * might not use the same type of slot. In most cases the child will
3321  * be a Sort, and thus return a TTSOpsMinimalTuple type slot - but the
3322  * input can also be presorted due an index, in which case it could be
3323  * a different type of slot.
3324  *
3325  * XXX: For efficiency it would be good to instead/additionally
3326  * generate expressions with corresponding settings of outerops* for
3327  * the individual phases - deforming is often a bottleneck for
3328  * aggregations with lots of rows per group. If there's multiple
3329  * sorts, we know that all but the first use TTSOpsMinimalTuple (via
3330  * the nodeAgg.c internal tuplesort).
3331  */
3332  if (aggstate->ss.ps.outeropsfixed &&
3333  aggstate->ss.ps.outerops != &TTSOpsMinimalTuple)
3334  aggstate->ss.ps.outeropsfixed = false;
3335  }
3336 
3337  /*
3338  * Initialize result type, slot and projection.
3339  */
3341  ExecAssignProjectionInfo(&aggstate->ss.ps, NULL);
3342 
3343  /*
3344  * initialize child expressions
3345  *
3346  * We expect the parser to have checked that no aggs contain other agg
3347  * calls in their arguments (and just to be sure, we verify it again while
3348  * initializing the plan node). This would make no sense under SQL
3349  * semantics, and it's forbidden by the spec. Because it is true, we
3350  * don't need to worry about evaluating the aggs in any particular order.
3351  *
3352  * Note: execExpr.c finds Aggrefs for us, and adds their AggrefExprState
3353  * nodes to aggstate->aggs. Aggrefs in the qual are found here; Aggrefs
3354  * in the targetlist are found during ExecAssignProjectionInfo, below.
3355  */
3356  aggstate->ss.ps.qual =
3357  ExecInitQual(node->plan.qual, (PlanState *) aggstate);
3358 
3359  /*
3360  * We should now have found all Aggrefs in the targetlist and quals.
3361  */
3362  numaggs = aggstate->numaggs;
3363  Assert(numaggs == list_length(aggstate->aggs));
3364 
3365  /*
3366  * For each phase, prepare grouping set data and fmgr lookup data for
3367  * compare functions. Accumulate all_grouped_cols in passing.
3368  */
3369  aggstate->phases = palloc0(numPhases * sizeof(AggStatePerPhaseData));
3370 
3371  aggstate->num_hashes = numHashes;
3372  if (numHashes)
3373  {
3374  aggstate->perhash = palloc0(sizeof(AggStatePerHashData) * numHashes);
3375  aggstate->phases[0].numsets = 0;
3376  aggstate->phases[0].gset_lengths = palloc(numHashes * sizeof(int));
3377  aggstate->phases[0].grouped_cols = palloc(numHashes * sizeof(Bitmapset *));
3378  }
3379 
3380  phase = 0;
3381  for (phaseidx = 0; phaseidx <= list_length(node->chain); ++phaseidx)
3382  {
3383  Agg *aggnode;
3384  Sort *sortnode;
3385 
3386  if (phaseidx > 0)
3387  {
3388  aggnode = list_nth_node(Agg, node->chain, phaseidx - 1);
3389  sortnode = castNode(Sort, aggnode->plan.lefttree);
3390  }
3391  else
3392  {
3393  aggnode = node;
3394  sortnode = NULL;
3395  }
3396 
3397  Assert(phase <= 1 || sortnode);
3398 
3399  if (aggnode->aggstrategy == AGG_HASHED
3400  || aggnode->aggstrategy == AGG_MIXED)
3401  {
3402  AggStatePerPhase phasedata = &aggstate->phases[0];
3403  AggStatePerHash perhash;
3404  Bitmapset *cols = NULL;
3405 
3406  Assert(phase == 0);
3407  i = phasedata->numsets++;
3408  perhash = &aggstate->perhash[i];
3409 
3410  /* phase 0 always points to the "real" Agg in the hash case */
3411  phasedata->aggnode = node;
3412  phasedata->aggstrategy = node->aggstrategy;
3413 
3414  /* but the actual Agg node representing this hash is saved here */
3415  perhash->aggnode = aggnode;
3416 
3417  phasedata->gset_lengths[i] = perhash->numCols = aggnode->numCols;
3418 
3419  for (j = 0; j < aggnode->numCols; ++j)
3420  cols = bms_add_member(cols, aggnode->grpColIdx[j]);
3421 
3422  phasedata->grouped_cols[i] = cols;
3423 
3424  all_grouped_cols = bms_add_members(all_grouped_cols, cols);
3425  continue;
3426  }
3427  else
3428  {
3429  AggStatePerPhase phasedata = &aggstate->phases[++phase];
3430  int num_sets;
3431 
3432  phasedata->numsets = num_sets = list_length(aggnode->groupingSets);
3433 
3434  if (num_sets)
3435  {
3436  phasedata->gset_lengths = palloc(num_sets * sizeof(int));
3437  phasedata->grouped_cols = palloc(num_sets * sizeof(Bitmapset *));
3438 
3439  i = 0;
3440  foreach(l, aggnode->groupingSets)
3441  {
3442  int current_length = list_length(lfirst(l));
3443  Bitmapset *cols = NULL;
3444 
3445  /* planner forces this to be correct */
3446  for (j = 0; j < current_length; ++j)
3447  cols = bms_add_member(cols, aggnode->grpColIdx[j]);
3448 
3449  phasedata->grouped_cols[i] = cols;
3450  phasedata->gset_lengths[i] = current_length;
3451 
3452  ++i;
3453  }
3454 
3455  all_grouped_cols = bms_add_members(all_grouped_cols,
3456  phasedata->grouped_cols[0]);
3457  }
3458  else
3459  {
3460  Assert(phaseidx == 0);
3461 
3462  phasedata->gset_lengths = NULL;
3463  phasedata->grouped_cols = NULL;
3464  }
3465 
3466  /*
3467  * If we are grouping, precompute fmgr lookup data for inner loop.
3468  */
3469  if (aggnode->aggstrategy == AGG_SORTED)
3470  {
3471  int i = 0;
3472 
3473  Assert(aggnode->numCols > 0);
3474 
3475  /*
3476  * Build a separate function for each subset of columns that
3477  * need to be compared.
3478  */
3479  phasedata->eqfunctions =
3480  (ExprState **) palloc0(aggnode->numCols * sizeof(ExprState *));
3481 
3482  /* for each grouping set */
3483  for (i = 0; i < phasedata->numsets; i++)
3484  {
3485  int length = phasedata->gset_lengths[i];
3486 
3487  if (phasedata->eqfunctions[length - 1] != NULL)
3488  continue;
3489 
3490  phasedata->eqfunctions[length - 1] =
3491  execTuplesMatchPrepare(scanDesc,
3492  length,
3493  aggnode->grpColIdx,
3494  aggnode->grpOperators,
3495  aggnode->grpCollations,
3496  (PlanState *) aggstate);
3497  }
3498 
3499  /* and for all grouped columns, unless already computed */
3500  if (phasedata->eqfunctions[aggnode->numCols - 1] == NULL)
3501  {
3502  phasedata->eqfunctions[aggnode->numCols - 1] =
3503  execTuplesMatchPrepare(scanDesc,
3504  aggnode->numCols,
3505  aggnode->grpColIdx,
3506  aggnode->grpOperators,
3507  aggnode->grpCollations,
3508  (PlanState *) aggstate);
3509  }
3510  }
3511 
3512  phasedata->aggnode = aggnode;
3513  phasedata->aggstrategy = aggnode->aggstrategy;
3514  phasedata->sortnode = sortnode;
3515  }
3516  }
3517 
3518  /*
3519  * Convert all_grouped_cols to a descending-order list.
3520  */
3521  i = -1;
3522  while ((i = bms_next_member(all_grouped_cols, i)) >= 0)
3523  aggstate->all_grouped_cols = lcons_int(i, aggstate->all_grouped_cols);
3524 
3525  /*
3526  * Set up aggregate-result storage in the output expr context, and also
3527  * allocate my private per-agg working storage
3528  */
3529  econtext = aggstate->ss.ps.ps_ExprContext;
3530  econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs);
3531  econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs);
3532 
3533  peraggs = (AggStatePerAgg) palloc0(sizeof(AggStatePerAggData) * numaggs);
3534  pertransstates = (AggStatePerTrans) palloc0(sizeof(AggStatePerTransData) * numaggs);
3535 
3536  aggstate->peragg = peraggs;
3537  aggstate->pertrans = pertransstates;
3538 
3539 
3540  aggstate->all_pergroups =
3542  * (numGroupingSets + numHashes));
3543  pergroups = aggstate->all_pergroups;
3544 
3545  if (node->aggstrategy != AGG_HASHED)
3546  {
3547  for (i = 0; i < numGroupingSets; i++)
3548  {
3549  pergroups[i] = (AggStatePerGroup) palloc0(sizeof(AggStatePerGroupData)
3550  * numaggs);
3551  }
3552 
3553  aggstate->pergroups = pergroups;
3554  pergroups += numGroupingSets;
3555  }
3556 
3557  /*
3558  * Hashing can only appear in the initial phase.
3559  */
3560  if (use_hashing)
3561  {
3562  Plan *outerplan = outerPlan(node);
3563  uint64 totalGroups = 0;
3564  int i;
3565 
3566  aggstate->hash_metacxt = AllocSetContextCreate(aggstate->ss.ps.state->es_query_cxt,
3567  "HashAgg meta context",
3569  aggstate->hash_spill_slot = ExecInitExtraTupleSlot(estate, scanDesc,
3571 
3572  /* this is an array of pointers, not structures */
3573  aggstate->hash_pergroup = pergroups;
3574 
3575  aggstate->hashentrysize = hash_agg_entry_size(aggstate->numtrans,
3576  outerplan->plan_width,
3577  node->transitionSpace);
3578 
3579  /*
3580  * Consider all of the grouping sets together when setting the limits
3581  * and estimating the number of partitions. This can be inaccurate
3582  * when there is more than one grouping set, but should still be
3583  * reasonable.
3584  */
3585  for (i = 0; i < aggstate->num_hashes; i++)
3586  totalGroups += aggstate->perhash[i].aggnode->numGroups;
3587 
3588  hash_agg_set_limits(aggstate->hashentrysize, totalGroups, 0,
3589  &aggstate->hash_mem_limit,
3590  &aggstate->hash_ngroups_limit,
3591  &aggstate->hash_planned_partitions);
3592  find_hash_columns(aggstate);
3593  build_hash_tables(aggstate);
3594  aggstate->table_filled = false;
3595  }
3596 
3597  /*
3598  * Initialize current phase-dependent values to initial phase. The initial
3599  * phase is 1 (first sort pass) for all strategies that use sorting (if
3600  * hashing is being done too, then phase 0 is processed last); but if only
3601  * hashing is being done, then phase 0 is all there is.
3602  */
3603  if (node->aggstrategy == AGG_HASHED)
3604  {
3605  aggstate->current_phase = 0;
3606  initialize_phase(aggstate, 0);
3607  select_current_set(aggstate, 0, true);
3608  }
3609  else
3610  {
3611  aggstate->current_phase = 1;
3612  initialize_phase(aggstate, 1);
3613  select_current_set(aggstate, 0, false);
3614  }
3615 
3616  /* -----------------
3617  * Perform lookups of aggregate function info, and initialize the
3618  * unchanging fields of the per-agg and per-trans data.
3619  *
3620  * We try to optimize by detecting duplicate aggregate functions so that
3621  * their state and final values are re-used, rather than needlessly being
3622  * re-calculated independently. We also detect aggregates that are not
3623  * the same, but which can share the same transition state.
3624  *
3625  * Scenarios:
3626  *
3627  * 1. Identical aggregate function calls appear in the query:
3628  *
3629  * SELECT SUM(x) FROM ... HAVING SUM(x) > 0
3630  *
3631  * Since these aggregates are identical, we only need to calculate
3632  * the value once. Both aggregates will share the same 'aggno' value.
3633  *
3634  * 2. Two different aggregate functions appear in the query, but the
3635  * aggregates have the same arguments, transition functions and
3636  * initial values (and, presumably, different final functions):
3637  *
3638  * SELECT AVG(x), STDDEV(x) FROM ...
3639  *
3640  * In this case we must create a new peragg for the varying aggregate,
3641  * and we need to call the final functions separately, but we need
3642  * only run the transition function once. (This requires that the
3643  * final functions be nondestructive of the transition state, but
3644  * that's required anyway for other reasons.)
3645  *
3646  * For either of these optimizations to be valid, all aggregate properties
3647  * used in the transition phase must be the same, including any modifiers
3648  * such as ORDER BY, DISTINCT and FILTER, and the arguments mustn't
3649  * contain any volatile functions.
3650  * -----------------
3651  */
3652  aggno = -1;
3653  transno = -1;
3654  foreach(l, aggstate->aggs)
3655  {
3656  AggrefExprState *aggrefstate = (AggrefExprState *) lfirst(l);
3657  Aggref *aggref = aggrefstate->aggref;
3658  AggStatePerAgg peragg;
3659  AggStatePerTrans pertrans;
3660  int existing_aggno;
3661  int existing_transno;
3662  List *same_input_transnos;
3663  Oid inputTypes[FUNC_MAX_ARGS];
3664  int numArguments;
3665  int numDirectArgs;
3666  HeapTuple aggTuple;
3667  Form_pg_aggregate aggform;
3668  AclResult aclresult;
3669  Oid transfn_oid,
3670  finalfn_oid;
3671  bool shareable;
3672  Oid serialfn_oid,
3673  deserialfn_oid;
3674  Expr *finalfnexpr;
3675  Oid aggtranstype;
3676  Datum textInitVal;
3677  Datum initValue;
3678  bool initValueIsNull;
3679 
3680  /* Planner should have assigned aggregate to correct level */
3681  Assert(aggref->agglevelsup == 0);
3682  /* ... and the split mode should match */
3683  Assert(aggref->aggsplit == aggstate->aggsplit);
3684 
3685  /* 1. Check for already processed aggs which can be re-used */
3686  existing_aggno = find_compatible_peragg(aggref, aggstate, aggno,
3687  &same_input_transnos);
3688  if (existing_aggno != -1)
3689  {
3690  /*
3691  * Existing compatible agg found. so just point the Aggref to the
3692  * same per-agg struct.
3693  */
3694  aggrefstate->aggno = existing_aggno;
3695  continue;
3696  }
3697 
3698  /* Mark Aggref state node with assigned index in the result array */
3699  peragg = &peraggs[++aggno];
3700  peragg->aggref = aggref;
3701  aggrefstate->aggno = aggno;
3702 
3703  /* Fetch the pg_aggregate row */
3704  aggTuple = SearchSysCache1(AGGFNOID,
3705  ObjectIdGetDatum(aggref->aggfnoid));
3706  if (!HeapTupleIsValid(aggTuple))
3707  elog(ERROR, "cache lookup failed for aggregate %u",
3708  aggref->aggfnoid);
3709  aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);
3710 
3711  /* Check permission to call aggregate function */
3712  aclresult = pg_proc_aclcheck(aggref->aggfnoid, GetUserId(),
3713  ACL_EXECUTE);
3714  if (aclresult != ACLCHECK_OK)
3715  aclcheck_error(aclresult, OBJECT_AGGREGATE,
3716  get_func_name(aggref->aggfnoid));
3718 
3719  /* planner recorded transition state type in the Aggref itself */
3720  aggtranstype = aggref->aggtranstype;
3721  Assert(OidIsValid(aggtranstype));
3722 
3723  /*
3724  * If this aggregation is performing state combines, then instead of
3725  * using the transition function, we'll use the combine function
3726  */
3727  if (DO_AGGSPLIT_COMBINE(aggstate->aggsplit))
3728  {
3729  transfn_oid = aggform->aggcombinefn;
3730 
3731  /* If not set then the planner messed up */
3732  if (!OidIsValid(transfn_oid))
3733  elog(ERROR, "combinefn not set for aggregate function");
3734  }
3735  else
3736  transfn_oid = aggform->aggtransfn;
3737 
3738  /* Final function only required if we're finalizing the aggregates */
3739  if (DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit))
3740  peragg->finalfn_oid = finalfn_oid = InvalidOid;
3741  else
3742  peragg->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
3743 
3744  /*
3745  * If finalfn is marked read-write, we can't share transition states;
3746  * but it is okay to share states for AGGMODIFY_SHAREABLE aggs. Also,
3747  * if we're not executing the finalfn here, we can share regardless.
3748  */
3749  shareable = (aggform->aggfinalmodify != AGGMODIFY_READ_WRITE) ||
3750  (finalfn_oid == InvalidOid);
3751  peragg->shareable = shareable;
3752 
3753  serialfn_oid = InvalidOid;
3754  deserialfn_oid = InvalidOid;
3755 
3756  /*
3757  * Check if serialization/deserialization is required. We only do it
3758  * for aggregates that have transtype INTERNAL.
3759  */
3760  if (aggtranstype == INTERNALOID)
3761  {
3762  /*
3763  * The planner should only have generated a serialize agg node if
3764  * every aggregate with an INTERNAL state has a serialization
3765  * function. Verify that.
3766  */
3767  if (DO_AGGSPLIT_SERIALIZE(aggstate->aggsplit))
3768  {
3769  /* serialization only valid when not running finalfn */
3771 
3772  if (!OidIsValid(aggform->aggserialfn))
3773  elog(ERROR, "serialfunc not provided for serialization aggregation");
3774  serialfn_oid = aggform->aggserialfn;
3775  }
3776 
3777  /* Likewise for deserialization functions */
3778  if (DO_AGGSPLIT_DESERIALIZE(aggstate->aggsplit))
3779  {
3780  /* deserialization only valid when combining states */
3781  Assert(DO_AGGSPLIT_COMBINE(aggstate->aggsplit));
3782 
3783  if (!OidIsValid(aggform->aggdeserialfn))
3784  elog(ERROR, "deserialfunc not provided for deserialization aggregation");
3785  deserialfn_oid = aggform->aggdeserialfn;
3786  }
3787  }
3788 
3789  /* Check that aggregate owner has permission to call component fns */
3790  {
3791  HeapTuple procTuple;
3792  Oid aggOwner;
3793 
3794  procTuple = SearchSysCache1(PROCOID,
3795  ObjectIdGetDatum(aggref->aggfnoid));
3796  if (!HeapTupleIsValid(procTuple))
3797  elog(ERROR, "cache lookup failed for function %u",
3798  aggref->aggfnoid);
3799  aggOwner = ((Form_pg_proc) GETSTRUCT(procTuple))->proowner;
3800  ReleaseSysCache(procTuple);
3801 
3802  aclresult = pg_proc_aclcheck(transfn_oid, aggOwner,
3803  ACL_EXECUTE);
3804  if (aclresult != ACLCHECK_OK)
3805  aclcheck_error(aclresult, OBJECT_FUNCTION,
3806  get_func_name(transfn_oid));
3807  InvokeFunctionExecuteHook(transfn_oid);
3808  if (OidIsValid(finalfn_oid))
3809  {
3810  aclresult = pg_proc_aclcheck(finalfn_oid, aggOwner,
3811  ACL_EXECUTE);
3812  if (aclresult != ACLCHECK_OK)
3813  aclcheck_error(aclresult, OBJECT_FUNCTION,
3814  get_func_name(finalfn_oid));
3815  InvokeFunctionExecuteHook(finalfn_oid);
3816  }
3817  if (OidIsValid(serialfn_oid))
3818  {
3819  aclresult = pg_proc_aclcheck(serialfn_oid, aggOwner,
3820  ACL_EXECUTE);
3821  if (aclresult != ACLCHECK_OK)
3822  aclcheck_error(aclresult, OBJECT_FUNCTION,
3823  get_func_name(serialfn_oid));
3824  InvokeFunctionExecuteHook(serialfn_oid);
3825  }
3826  if (OidIsValid(deserialfn_oid))
3827  {
3828  aclresult = pg_proc_aclcheck(deserialfn_oid, aggOwner,
3829  ACL_EXECUTE);
3830  if (aclresult != ACLCHECK_OK)
3831  aclcheck_error(aclresult, OBJECT_FUNCTION,
3832  get_func_name(deserialfn_oid));
3833  InvokeFunctionExecuteHook(deserialfn_oid);
3834  }
3835  }
3836 
3837  /*
3838  * Get actual datatypes of the (nominal) aggregate inputs. These
3839  * could be different from the agg's declared input types, when the
3840  * agg accepts ANY or a polymorphic type.
3841  */
3842  numArguments = get_aggregate_argtypes(aggref, inputTypes);
3843 
3844  /* Count the "direct" arguments, if any */
3845  numDirectArgs = list_length(aggref->aggdirectargs);
3846 
3847  /* Detect how many arguments to pass to the finalfn */
3848  if (aggform->aggfinalextra)
3849  peragg->numFinalArgs = numArguments + 1;
3850  else
3851  peragg->numFinalArgs = numDirectArgs + 1;
3852 
3853  /* Initialize any direct-argument expressions */
3854  peragg->aggdirectargs = ExecInitExprList(aggref->aggdirectargs,
3855  (PlanState *) aggstate);
3856 
3857  /*
3858  * build expression trees using actual argument & result types for the
3859  * finalfn, if it exists and is required.
3860  */
3861  if (OidIsValid(finalfn_oid))
3862  {
3863  build_aggregate_finalfn_expr(inputTypes,
3864  peragg->numFinalArgs,
3865  aggtranstype,
3866  aggref->aggtype,
3867  aggref->inputcollid,
3868  finalfn_oid,
3869  &finalfnexpr);
3870  fmgr_info(finalfn_oid, &peragg->finalfn);
3871  fmgr_info_set_expr((Node *) finalfnexpr, &peragg->finalfn);
3872  }
3873 
3874  /* get info about the output value's datatype */
3875  get_typlenbyval(aggref->aggtype,
3876  &peragg->resulttypeLen,
3877  &peragg->resulttypeByVal);
3878 
3879  /*
3880  * initval is potentially null, so don't try to access it as a struct
3881  * field. Must do it the hard way with SysCacheGetAttr.
3882  */
3883  textInitVal = SysCacheGetAttr(AGGFNOID, aggTuple,
3884  Anum_pg_aggregate_agginitval,
3885  &initValueIsNull);
3886  if (initValueIsNull)
3887  initValue = (Datum) 0;
3888  else
3889  initValue = GetAggInitVal(textInitVal, aggtranstype);
3890 
3891  /*
3892  * 2. Build working state for invoking the transition function, or
3893  * look up previously initialized working state, if we can share it.
3894  *
3895  * find_compatible_peragg() already collected a list of shareable
3896  * per-Trans's with the same inputs. Check if any of them have the
3897  * same transition function and initial value.
3898  */
3899  existing_transno = find_compatible_pertrans(aggstate, aggref,
3900  shareable,
3901  transfn_oid, aggtranstype,
3902  serialfn_oid, deserialfn_oid,
3903  initValue, initValueIsNull,
3904  same_input_transnos);
3905  if (existing_transno != -1)
3906  {
3907  /*
3908  * Existing compatible trans found, so just point the 'peragg' to
3909  * the same per-trans struct, and mark the trans state as shared.
3910  */
3911  pertrans = &pertransstates[existing_transno];
3912  pertrans->aggshared = true;
3913  peragg->transno = existing_transno;
3914  }
3915  else
3916  {
3917  pertrans = &pertransstates[++transno];
3918  build_pertrans_for_aggref(pertrans, aggstate, estate,
3919  aggref, transfn_oid, aggtranstype,
3920  serialfn_oid, deserialfn_oid,
3921  initValue, initValueIsNull,
3922  inputTypes, numArguments);
3923  peragg->transno = transno;
3924  }
3925  ReleaseSysCache(aggTuple);
3926  }
3927 
3928  /*
3929  * Update aggstate->numaggs to be the number of unique aggregates found.
3930  * Also set numstates to the number of unique transition states found.
3931  */
3932  aggstate->numaggs = aggno + 1;
3933  aggstate->numtrans = transno + 1;
3934 
3935  /*
3936  * Last, check whether any more aggregates got added onto the node while
3937  * we processed the expressions for the aggregate arguments (including not
3938  * only the regular arguments and FILTER expressions handled immediately
3939  * above, but any direct arguments we might've handled earlier). If so,
3940  * we have nested aggregate functions, which is semantically nonsensical,
3941  * so complain. (This should have been caught by the parser, so we don't
3942  * need to work hard on a helpful error message; but we defend against it
3943  * here anyway, just to be sure.)
3944  */
3945  if (numaggs != list_length(aggstate->aggs))
3946  ereport(ERROR,
3947  (errcode(ERRCODE_GROUPING_ERROR),
3948  errmsg("aggregate function calls cannot be nested")));
3949 
3950  /*
3951  * Build expressions doing all the transition work at once. We build a
3952  * different one for each phase, as the number of transition function
3953  * invocation can differ between phases. Note this'll work both for
3954  * transition and combination functions (although there'll only be one
3955  * phase in the latter case).
3956  */
3957  for (phaseidx = 0; phaseidx < aggstate->numphases; phaseidx++)
3958  {
3959  AggStatePerPhase phase = &aggstate->phases[phaseidx];
3960  bool dohash = false;
3961  bool dosort = false;
3962 
3963  /* phase 0 doesn't necessarily exist */
3964  if (!phase->aggnode)
3965  continue;
3966 
3967  if (aggstate->aggstrategy == AGG_MIXED && phaseidx == 1)
3968  {
3969  /*
3970  * Phase one, and only phase one, in a mixed agg performs both
3971  * sorting and aggregation.
3972  */
3973  dohash = true;
3974  dosort = true;
3975  }
3976  else if (aggstate->aggstrategy == AGG_MIXED && phaseidx == 0)
3977  {
3978  /*
3979  * No need to compute a transition function for an AGG_MIXED phase
3980  * 0 - the contents of the hashtables will have been computed
3981  * during phase 1.
3982  */
3983  continue;
3984  }
3985  else if (phase->aggstrategy == AGG_PLAIN ||
3986  phase->aggstrategy == AGG_SORTED)
3987  {
3988  dohash = false;
3989  dosort = true;
3990  }
3991  else if (phase->aggstrategy == AGG_HASHED)
3992  {
3993  dohash = true;
3994  dosort = false;
3995  }
3996  else
3997  Assert(false);
3998 
3999  phase->evaltrans = ExecBuildAggTrans(aggstate, phase, dosort, dohash,
4000  false);
4001 
4002  /* cache compiled expression for outer slot without NULL check */
4003  phase->evaltrans_cache[0][0] = phase->evaltrans;
4004  }
4005 
4006  return aggstate;
4007 }
struct AggStatePerTransData * AggStatePerTrans
Definition: execnodes.h:2118
ExprState ** eqfunctions
Definition: nodeAgg.h:277
AggStatePerGroup * hash_pergroup
Definition: execnodes.h:2185
#define NIL
Definition: pg_list.h:65
struct AggStatePerGroupData * AggStatePerGroup
Definition: execnodes.h:2119
static void select_current_set(AggState *aggstate, int setno, bool is_hash)
Definition: nodeAgg.c:460
int numCols
Definition: plannodes.h:821
List * qual
Definition: plannodes.h:143
AggStatePerPhase phases
Definition: execnodes.h:2153
double hashentrysize
Definition: execnodes.h:2177
#define AllocSetContextCreate
Definition: memutils.h:170
Datum * ecxt_aggvalues
Definition: execnodes.h:245
uint64 hash_ngroups_limit
Definition: execnodes.h:2174
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1801
#define GETSTRUCT(TUP)
Definition: htup_details.h:655
AttrNumber * grpColIdx
Definition: plannodes.h:822
uint64 transitionSpace
Definition: plannodes.h:826
const TupleTableSlotOps * ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
Definition: execUtils.c:504
List * lcons_int(int datum, List *list)
Definition: list.c:471
int numaggs
Definition: execnodes.h:2127
Oid GetUserId(void)
Definition: miscinit.c:448
bool agg_done
Definition: execnodes.h:2145
#define castNode(_type_, nodeptr)
Definition: nodes.h:598
Oid * grpCollations
Definition: plannodes.h:824
TupleTableSlot * sort_slot
Definition: execnodes.h:2156
List * all_grouped_cols
Definition: execnodes.h:2150
Tuplesortstate * sort_out
Definition: execnodes.h:2155
ScanState ss
Definition: execnodes.h:2125
ExprContext * ps_ExprContext
Definition: execnodes.h:984
ExprState * evaltrans
Definition: nodeAgg.h:282
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1043
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
Oid inputcollid
Definition: primnodes.h:315
int current_phase
Definition: execnodes.h:2133
Definition: nodes.h:529
AggSplit aggsplit
Definition: execnodes.h:2130
static TupleTableSlot * ExecAgg(PlanState *pstate)
Definition: nodeAgg.c:2122
int errcode(int sqlerrcode)
Definition: elog.c:610
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1335
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:2037
static int find_compatible_pertrans(AggState *aggstate, Aggref *newagg, bool shareable, Oid aggtransfn, Oid aggtranstype, Oid aggserialfn, Oid aggdeserialfn, Datum initValue, bool initValueIsNull, List *transnos)
Definition: nodeAgg.c:4432
AggStatePerTrans pertrans
Definition: execnodes.h:2135
EState * state
Definition: execnodes.h:947
int projected_set
Definition: execnodes.h:2146
unsigned int Oid
Definition: postgres_ext.h:31
HeapTuple grp_firstTuple
Definition: execnodes.h:2160
Aggref * aggref
Definition: nodeAgg.h:186
int current_set
Definition: execnodes.h:2148
#define OidIsValid(objectId)
Definition: c.h:644
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:791
int numtrans
Definition: execnodes.h:2128
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:209
ExprContext * tmpcontext
Definition: execnodes.h:2138
#define FUNC_MAX_ARGS
Bitmapset ** grouped_cols
Definition: nodeAgg.h:276
PlanState ps
Definition: execnodes.h:1332
int maxsets
Definition: execnodes.h:2152
TupleTableSlot * hash_spill_slot
Definition: execnodes.h:2168
Size hash_agg_entry_size(int numTrans, Size tupleWidth, Size transitionSpace)
Definition: nodeAgg.c:1649
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3327
#define DO_AGGSPLIT_SERIALIZE(as)
Definition: nodes.h:793
MemoryContext es_query_cxt
Definition: execnodes.h:555
AggStrategy aggstrategy
Definition: plannodes.h:819
bool table_filled
Definition: execnodes.h:2162
AggStrategy aggstrategy
Definition: execnodes.h:2129
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1471
MemoryContext hash_metacxt
Definition: execnodes.h:2164
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:126
static void find_hash_columns(AggState *aggstate)
Definition: nodeAgg.c:1534
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
Tuplesortstate * sort_in
Definition: execnodes.h:2154
#define EXEC_FLAG_BACKWARD
Definition: executor.h:58
#define outerPlanState(node)
Definition: execnodes.h:1039
Aggref * aggref
Definition: execnodes.h:752
#define list_nth_node(type, list, n)
Definition: pg_list.h:305
static int initValue(long lng_val)
Definition: informix.c:677
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:540
void hash_agg_set_limits(double hashentrysize, uint64 input_groups, int used_bits, Size *mem_limit, uint64 *ngroups_limit, int *num_partitions)
Definition: nodeAgg.c:1747
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:135
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:318
Index agglevelsup
Definition: primnodes.h:327
int hash_planned_partitions
Definition: execnodes.h:2175
List * aggdirectargs
Definition: primnodes.h:318
static Datum GetAggInitVal(Datum textInitVal, Oid transtype)
Definition: nodeAgg.c:4326
AggStatePerAgg curperagg
Definition: execnodes.h:2141
AggStatePerHash perhash
Definition: execnodes.h:2184
bool outeropsset
Definition: execnodes.h:1026
AggStrategy aggstrategy
Definition: nodeAgg.h:273
ExprState * evaltrans_cache[2][2]
Definition: nodeAgg.h:290
#define EXEC_FLAG_REWIND
Definition: executor.h:57
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:191
#define outerPlan(node)
Definition: plannodes.h:172
int num_hashes
Definition: execnodes.h:2163
Plan plan
Definition: plannodes.h:818
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1116
bool input_done
Definition: execnodes.h:2144
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:124
ExprContext * hashcontext
Definition: execnodes.h:2136
bool * ecxt_aggnulls
Definition: execnodes.h:247
static int find_compatible_peragg(Aggref *newagg, AggState *aggstate, int lastaggno, List **same_input_transnos)
Definition: nodeAgg.c:4354
void * palloc0(Size size)
Definition: mcxt.c:980
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:951
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1164
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1377
List * groupingSets
Definition: plannodes.h:829
int16 resulttypeLen
Definition: nodeAgg.h:215
static void initialize_phase(AggState *aggstate, int newphase)
Definition: nodeAgg.c:482
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:133
Plan * plan
Definition: execnodes.h:945
#define InvalidOid
Definition: postgres_ext.h:36
Oid aggfnoid
Definition: primnodes.h:312
#define ereport(elevel,...)
Definition: elog.h:144
#define Max(x, y)
Definition: c.h:914
ExprContext ** aggcontexts
Definition: execnodes.h:2137
#define makeNode(_type_)
Definition: nodes.h:577
int plan_width
Definition: plannodes.h:130
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:738
#define lfirst(lc)
Definition: pg_list.h:190
ExprState * execTuplesMatchPrepare(TupleDesc desc, int numCols, const AttrNumber *keyColIdx, const Oid *eqOperators, const Oid *collations, PlanState *parent)
Definition: execGrouping.c:59
#define EXEC_FLAG_MARK
Definition: executor.h:59
AggSplit aggsplit
Definition: plannodes.h:820
struct AggStatePerAggData * AggStatePerAgg
Definition: execnodes.h:2117
FormData_pg_aggregate * Form_pg_aggregate
Definition: pg_aggregate.h:109
AggSplit aggsplit
Definition: primnodes.h:328
AggStatePerGroup * pergroups
Definition: execnodes.h:2158
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:485
static int list_length(const List *l)
Definition: pg_list.h:169
long numGroups
Definition: plannodes.h:825
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:792
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:2090
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1769
bool outeropsfixed
Definition: execnodes.h:1022
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
#define DO_AGGSPLIT_DESERIALIZE(as)
Definition: nodes.h:794
Size hash_mem_limit
Definition: execnodes.h:2173
struct Plan * lefttree
Definition: plannodes.h:144
int numphases
Definition: execnodes.h:2132
ExprState * qual
Definition: execnodes.h:966
Oid * grpOperators
Definition: plannodes.h:823
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:824
List * chain
Definition: plannodes.h:830
AggStatePerAgg peragg
Definition: execnodes.h:2134
#define ACL_EXECUTE
Definition: parsenodes.h:81
#define elog(elevel,...)
Definition: elog.h:214
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4620
int i
List * aggdirectargs
Definition: nodeAgg.h:209
Oid aggtranstype
Definition: primnodes.h:316
AggStatePerTrans curpertrans
Definition: execnodes.h:2143
Oid aggtype
Definition: primnodes.h:313
bool resulttypeByVal
Definition: nodeAgg.h:216
Definition: plannodes.h:816
ExprContext * CreateWorkExprContext(EState *estate)
Definition: execUtils.c:321
List * aggs
Definition: execnodes.h:2126
void ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate, const TupleTableSlotOps *tts_ops)
Definition: execUtils.c:687
int get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
Definition: parse_agg.c:1819
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:4018
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:139
Definition: pg_list.h:50
const TupleTableSlotOps TTSOpsMinimalTuple
Definition: execTuples.c:85
FmgrInfo finalfn
Definition: nodeAgg.h:198
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:793
static void build_hash_tables(AggState *aggstate)
Definition: nodeAgg.c:1439
const TupleTableSlotOps * outerops
Definition: execnodes.h:1018
ExprState * ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, bool doSort, bool doHash, bool nullcheck)
Definition: execExpr.c:2934
AggStatePerGroup * all_pergroups
Definition: execnodes.h:2190

◆ ExecReScanAgg()

void ExecReScanAgg ( AggState node)

Definition at line 4537 of file nodeAgg.c.

References AggState::agg_done, AGG_HASHED, AGG_MIXED, AggState::aggcontexts, Agg::aggParams, AggState::aggstrategy, bms_overlap(), build_hash_tables(), PlanState::chgParam, ExprContext::ecxt_aggnulls, ExprContext::ecxt_aggvalues, ExecClearTuple(), ExecReScan(), AggState::grp_firstTuple, AggState::hash_ever_spilled, AggState::hash_ngroups_current, AggState::hash_spill_mode, hashagg_recompile_expressions(), hashagg_reset_spill_state(), AggState::hashcontext, AggStatePerHashData::hashiter, AggStatePerHashData::hashtable, heap_freetuple(), initialize_phase(), AggState::input_done, Max, AggState::maxsets, MemSet, AggState::numaggs, AggState::numtrans, outerPlan, outerPlanState, AggState::pergroups, 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().

4538 {
4539  ExprContext *econtext = node->ss.ps.ps_ExprContext;
4541  Agg *aggnode = (Agg *) node->ss.ps.plan;
4542  int transno;
4543  int numGroupingSets = Max(node->maxsets, 1);
4544  int setno;
4545 
4546  node->agg_done = false;
4547 
4548  if (node->aggstrategy == AGG_HASHED)
4549  {
4550  /*
4551  * In the hashed case, if we haven't yet built the hash table then we
4552  * can just return; nothing done yet, so nothing to undo. If subnode's
4553  * chgParam is not NULL then it will be re-scanned by ExecProcNode,
4554  * else no reason to re-scan it at all.
4555  */
4556  if (!node->table_filled)
4557  return;
4558 
4559  /*
4560  * If we do have the hash table, and it never spilled, and the subplan
4561  * does not have any parameter changes, and none of our own parameter
4562  * changes affect input expressions of the aggregated functions, then
4563  * we can just rescan the existing hash table; no need to build it
4564  * again.
4565  */
4566  if (outerPlan->chgParam == NULL && !node->hash_ever_spilled &&
4567  !bms_overlap(node->ss.ps.chgParam, aggnode->aggParams))
4568  {
4570  &node->perhash[0].hashiter);
4571  select_current_set(node, 0, true);
4572  return;
4573  }
4574  }
4575 
4576  /* Make sure we have closed any open tuplesorts */
4577  for (transno = 0; transno < node->numtrans; transno++)
4578  {
4579  for (setno = 0; setno < numGroupingSets; setno++)
4580  {
4581  AggStatePerTrans pertrans = &node->pertrans[transno];
4582 
4583  if (pertrans->sortstates[setno])
4584  {
4585  tuplesort_end(pertrans->sortstates[setno]);
4586  pertrans->sortstates[setno] = NULL;
4587  }
4588  }
4589  }
4590 
4591  /*
4592  * We don't need to ReScanExprContext the output tuple context here;
4593  * ExecReScan already did it. But we do need to reset our per-grouping-set
4594  * contexts, which may have transvalues stored in them. (We use rescan
4595  * rather than just reset because transfns may have registered callbacks
4596  * that need to be run now.) For the AGG_HASHED case, see below.
4597  */
4598 
4599  for (setno = 0; setno < numGroupingSets; setno++)
4600  {
4601  ReScanExprContext(node->aggcontexts[setno]);
4602  }
4603 
4604  /* Release first tuple of group, if we have made a copy */
4605  if (node->grp_firstTuple != NULL)
4606  {
4608  node->grp_firstTuple = NULL;
4609  }
4611 
4612  /* Forget current agg values */
4613  MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numaggs);
4614  MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numaggs);
4615 
4616  /*
4617  * With AGG_HASHED/MIXED, the hash table is allocated in a sub-context of
4618  * the hashcontext. This used to be an issue, but now, resetting a context
4619  * automatically deletes sub-contexts too.
4620  */
4621  if (node->aggstrategy == AGG_HASHED || node->aggstrategy == AGG_MIXED)
4622  {
4624 
4625  node->hash_ever_spilled = false;
4626  node->hash_spill_mode = false;
4627  node->hash_ngroups_current = 0;
4628 
4630  /* Rebuild an empty hash table */
4631  build_hash_tables(node);
4632  node->table_filled = false;
4633  /* iterator will be reset when the table is filled */
4634 
4635  hashagg_recompile_expressions(node, false, false);
4636  }
4637 
4638  if (node->aggstrategy != AGG_HASHED)
4639  {
4640  /*
4641  * Reset the per-group state (in particular, mark transvalues null)
4642  */
4643  for (setno = 0; setno < numGroupingSets; setno++)
4644  {
4645  MemSet(node->pergroups[setno], 0,
4646  sizeof(AggStatePerGroupData) * node->numaggs);
4647  }
4648 
4649  /* reset to phase 1 */
4650  initialize_phase(node, 1);
4651 
4652  node->input_done = false;
4653  node->projected_set = -1;
4654  }
4655 
4656  if (outerPlan->chgParam == NULL)
4657  ExecReScan(outerPlan);
4658 }
static void hashagg_reset_spill_state(AggState *aggstate)
Definition: nodeAgg.c:3113
static void select_current_set(AggState *aggstate, int setno, bool is_hash)
Definition: nodeAgg.c:460
Datum * ecxt_aggvalues
Definition: execnodes.h:245
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
int numaggs
Definition: execnodes.h:2127
bool agg_done
Definition: execnodes.h:2145
ScanState ss
Definition: execnodes.h:2125
ExprContext * ps_ExprContext
Definition: execnodes.h:984
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
#define MemSet(start, val, len)
Definition: c.h:971
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1335
AggStatePerTrans pertrans
Definition: execnodes.h:2135
int projected_set
Definition: execnodes.h:2146
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
HeapTuple grp_firstTuple
Definition: execnodes.h:2160
int numtrans
Definition: execnodes.h:2128
bool hash_spill_mode
Definition: execnodes.h:2171
PlanState ps
Definition: execnodes.h:1332
int maxsets
Definition: execnodes.h:2152
bool table_filled
Definition: execnodes.h:2162
AggStrategy aggstrategy
Definition: execnodes.h:2129
#define outerPlanState(node)
Definition: execnodes.h:1039
Tuplesortstate ** sortstates
Definition: nodeAgg.h:153
Bitmapset * aggParams
Definition: plannodes.h:827
AggStatePerHash perhash
Definition: execnodes.h:2184
Bitmapset * chgParam
Definition: execnodes.h:977
#define outerPlan(node)
Definition: plannodes.h:172
TupleHashIterator hashiter
Definition: nodeAgg.h:303
bool input_done
Definition: execnodes.h:2144
ExprContext * hashcontext
Definition: execnodes.h:2136
bool * ecxt_aggnulls
Definition: execnodes.h:247
uintptr_t Datum
Definition: postgres.h:367
static void initialize_phase(AggState *aggstate, int newphase)
Definition: nodeAgg.c:482
Plan * plan
Definition: execnodes.h:945
#define ResetTupleHashIterator(htable, iter)
Definition: execnodes.h:727
static void hashagg_recompile_expressions(AggState *aggstate, bool minslot, bool nullcheck)
Definition: nodeAgg.c:1696
#define Max(x, y)
Definition: c.h:914
ExprContext ** aggcontexts
Definition: execnodes.h:2137
bool hash_ever_spilled
Definition: execnodes.h:2170
AggStatePerGroup * pergroups
Definition: execnodes.h:2158
void ReScanExprContext(ExprContext *econtext)
Definition: execUtils.c:443
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:494
uint64 hash_ngroups_current
Definition: execnodes.h:2179
Definition: plannodes.h:816
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1388
TupleHashTable hashtable
Definition: nodeAgg.h:302
static void build_hash_tables(AggState *aggstate)
Definition: nodeAgg.c:1439

◆ hash_agg_entry_size()

Size hash_agg_entry_size ( int  numTrans,
Size  tupleWidth,
Size  transitionSpace 
)

Definition at line 1649 of file nodeAgg.c.

References CHUNKHDRSZ, MAXALIGN, and SizeofMinimalTupleHeader.

Referenced by cost_agg(), create_distinct_paths(), estimate_hashagg_tablesize(), and ExecInitAgg().

1650 {
1651  Size tupleChunkSize;
1652  Size pergroupChunkSize;
1653  Size transitionChunkSize;
1654  Size tupleSize = (MAXALIGN(SizeofMinimalTupleHeader) +
1655  tupleWidth);
1656  Size pergroupSize = numTrans * sizeof(AggStatePerGroupData);
1657 
1658  tupleChunkSize = CHUNKHDRSZ + tupleSize;
1659 
1660  if (pergroupSize > 0)
1661  pergroupChunkSize = CHUNKHDRSZ + pergroupSize;
1662  else
1663  pergroupChunkSize = 0;
1664 
1665  if (transitionSpace > 0)
1666  transitionChunkSize = CHUNKHDRSZ + transitionSpace;
1667  else
1668  transitionChunkSize = 0;
1669 
1670  return
1671  sizeof(TupleHashEntryData) +
1672  tupleChunkSize +
1673  pergroupChunkSize +
1674  transitionChunkSize;
1675 }
struct TupleHashEntryData TupleHashEntryData
struct AggStatePerGroupData AggStatePerGroupData
#define SizeofMinimalTupleHeader
Definition: htup_details.h:649
size_t Size
Definition: c.h:466
#define MAXALIGN(LEN)
Definition: c.h:691
#define CHUNKHDRSZ
Definition: nodeAgg.c:304

◆ hash_agg_set_limits()

void hash_agg_set_limits ( double  hashentrysize,
uint64  input_groups,
int  used_bits,
Size mem_limit,
uint64 *  ngroups_limit,
int *  num_partitions 
)

Definition at line 1747 of file nodeAgg.c.

References hash_choose_num_partitions(), HASHAGG_READ_BUFFER_SIZE, HASHAGG_WRITE_BUFFER_SIZE, and work_mem.

Referenced by agg_refill_hash_table(), cost_agg(), and ExecInitAgg().

1750 {
1751  int npartitions;
1752  Size partition_mem;
1753 
1754  /* if not expected to spill, use all of work_mem */
1755  if (input_groups * hashentrysize < work_mem * 1024L)
1756  {
1757  if (num_partitions != NULL)
1758  *num_partitions = 0;
1759  *mem_limit = work_mem * 1024L;
1760  *ngroups_limit = *mem_limit / hashentrysize;
1761  return;
1762  }
1763 
1764  /*
1765  * Calculate expected memory requirements for spilling, which is the size
1766  * of the buffers needed for all the tapes that need to be open at once.
1767  * Then, subtract that from the memory available for holding hash tables.
1768  */
1769  npartitions = hash_choose_num_partitions(input_groups,
1770  hashentrysize,
1771  used_bits,
1772  NULL);
1773  if (num_partitions != NULL)
1774  *num_partitions = npartitions;
1775 
1776  partition_mem =
1778  HASHAGG_WRITE_BUFFER_SIZE * npartitions;
1779 
1780  /*
1781  * Don't set the limit below 3/4 of work_mem. In that case, we are at the
1782  * minimum number of partitions, so we aren't going to dramatically exceed
1783  * work mem anyway.
1784  */
1785  if (work_mem * 1024L > 4 * partition_mem)
1786  *mem_limit = work_mem * 1024L - partition_mem;
1787  else
1788  *mem_limit = work_mem * 1024L * 0.75;
1789 
1790  if (*mem_limit > hashentrysize)
1791  *ngroups_limit = *mem_limit / hashentrysize;
1792  else
1793  *ngroups_limit = 1;
1794 }
static int hash_choose_num_partitions(uint64 input_groups, double hashentrysize, int used_bits, int *log2_npartittions)
Definition: nodeAgg.c:1940
#define HASHAGG_READ_BUFFER_SIZE
Definition: nodeAgg.c:294
int work_mem
Definition: globals.c:121
size_t Size
Definition: c.h:466
#define HASHAGG_WRITE_BUFFER_SIZE
Definition: nodeAgg.c:295