PostgreSQL Source Code  git master
nodeAgg.h File Reference
#include "access/parallel.h"
#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, double input_groups, int used_bits, Size *mem_limit, uint64 *ngroups_limit, int *num_partitions)
 
void ExecAggEstimate (AggState *node, ParallelContext *pcxt)
 
void ExecAggInitializeDSM (AggState *node, ParallelContext *pcxt)
 
void ExecAggInitializeWorker (AggState *node, ParallelWorkerContext *pwcxt)
 
void ExecAggRetrieveInstrumentation (AggState *node)
 

Macro Definition Documentation

◆ FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE

#define FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE   2

Definition at line 249 of file nodeAgg.h.

◆ FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE

#define FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE   0

Definition at line 244 of file nodeAgg.h.

◆ FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL

#define FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL   1

Definition at line 246 of file nodeAgg.h.

Typedef Documentation

◆ AggStatePerAggData

◆ AggStatePerGroupData

◆ AggStatePerHashData

◆ AggStatePerPhaseData

◆ AggStatePerTransData

Function Documentation

◆ ExecAggEstimate()

void ExecAggEstimate ( AggState node,
ParallelContext pcxt 
)

Definition at line 4659 of file nodeAgg.c.

4660 {
4661  Size size;
4662 
4663  /* don't need this if not instrumenting or no workers */
4664  if (!node->ss.ps.instrument || pcxt->nworkers == 0)
4665  return;
4666 
4667  size = mul_size(pcxt->nworkers, sizeof(AggregateInstrumentation));
4668  size = add_size(size, offsetof(SharedAggInfo, sinstrument));
4669  shm_toc_estimate_chunk(&pcxt->estimator, size);
4670  shm_toc_estimate_keys(&pcxt->estimator, 1);
4671 }
#define offsetof(type, field)
Definition: c.h:727
size_t Size
Definition: c.h:540
#define shm_toc_estimate_chunk(e, sz)
Definition: shm_toc.h:51
#define shm_toc_estimate_keys(e, cnt)
Definition: shm_toc.h:53
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
Size mul_size(Size s1, Size s2)
Definition: shmem.c:519
ScanState ss
Definition: execnodes.h:2326
shm_toc_estimator estimator
Definition: parallel.h:42
Instrumentation * instrument
Definition: execnodes.h:1008
PlanState ps
Definition: execnodes.h:1423

References add_size(), ParallelContext::estimator, PlanState::instrument, mul_size(), ParallelContext::nworkers, offsetof, ScanState::ps, shm_toc_estimate_chunk, shm_toc_estimate_keys, and AggState::ss.

Referenced by ExecParallelEstimate().

◆ ExecAggInitializeDSM()

void ExecAggInitializeDSM ( AggState node,
ParallelContext pcxt 
)

Definition at line 4680 of file nodeAgg.c.

4681 {
4682  Size size;
4683 
4684  /* don't need this if not instrumenting or no workers */
4685  if (!node->ss.ps.instrument || pcxt->nworkers == 0)
4686  return;
4687 
4688  size = offsetof(SharedAggInfo, sinstrument)
4689  + pcxt->nworkers * sizeof(AggregateInstrumentation);
4690  node->shared_info = shm_toc_allocate(pcxt->toc, size);
4691  /* ensure any unfilled slots will contain zeroes */
4692  memset(node->shared_info, 0, size);
4693  node->shared_info->num_workers = pcxt->nworkers;
4694  shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id,
4695  node->shared_info);
4696 }
struct AggregateInstrumentation AggregateInstrumentation
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition: shm_toc.c:171
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition: shm_toc.c:88
SharedAggInfo * shared_info
Definition: execnodes.h:2398
shm_toc * toc
Definition: parallel.h:45
Plan * plan
Definition: execnodes.h:998
int plan_node_id
Definition: plannodes.h:141

References PlanState::instrument, SharedAggInfo::num_workers, ParallelContext::nworkers, offsetof, PlanState::plan, Plan::plan_node_id, ScanState::ps, AggState::shared_info, shm_toc_allocate(), shm_toc_insert(), AggState::ss, and ParallelContext::toc.

Referenced by ExecParallelInitializeDSM().

◆ ExecAggInitializeWorker()

void ExecAggInitializeWorker ( AggState node,
ParallelWorkerContext pwcxt 
)

Definition at line 4705 of file nodeAgg.c.

4706 {
4707  node->shared_info =
4708  shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, true);
4709 }
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
Definition: shm_toc.c:232

References PlanState::plan, Plan::plan_node_id, ScanState::ps, AggState::shared_info, shm_toc_lookup(), AggState::ss, and ParallelWorkerContext::toc.

Referenced by ExecParallelInitializeWorker().

◆ ExecAggRetrieveInstrumentation()

void ExecAggRetrieveInstrumentation ( AggState node)

Definition at line 4718 of file nodeAgg.c.

4719 {
4720  Size size;
4721  SharedAggInfo *si;
4722 
4723  if (node->shared_info == NULL)
4724  return;
4725 
4726  size = offsetof(SharedAggInfo, sinstrument)
4728  si = palloc(size);
4729  memcpy(si, node->shared_info, size);
4730  node->shared_info = si;
4731 }
void * palloc(Size size)
Definition: mcxt.c:1068

References SharedAggInfo::num_workers, offsetof, palloc(), and AggState::shared_info.

Referenced by ExecParallelRetrieveInstrumentation().

◆ ExecEndAgg()

void ExecEndAgg ( AggState node)

Definition at line 4270 of file nodeAgg.c.

4271 {
4273  int transno;
4274  int numGroupingSets = Max(node->maxsets, 1);
4275  int setno;
4276 
4277  /*
4278  * When ending a parallel worker, copy the statistics gathered by the
4279  * worker back into shared memory so that it can be picked up by the main
4280  * process to report in EXPLAIN ANALYZE.
4281  */
4282  if (node->shared_info && IsParallelWorker())
4283  {
4285 
4286  Assert(ParallelWorkerNumber <= node->shared_info->num_workers);
4289  si->hash_disk_used = node->hash_disk_used;
4290  si->hash_mem_peak = node->hash_mem_peak;
4291  }
4292 
4293  /* Make sure we have closed any open tuplesorts */
4294 
4295  if (node->sort_in)
4296  tuplesort_end(node->sort_in);
4297  if (node->sort_out)
4298  tuplesort_end(node->sort_out);
4299 
4301 
4302  if (node->hash_metacxt != NULL)
4303  {
4305  node->hash_metacxt = NULL;
4306  }
4307 
4308  for (transno = 0; transno < node->numtrans; transno++)
4309  {
4310  AggStatePerTrans pertrans = &node->pertrans[transno];
4311 
4312  for (setno = 0; setno < numGroupingSets; setno++)
4313  {
4314  if (pertrans->sortstates[setno])
4315  tuplesort_end(pertrans->sortstates[setno]);
4316  }
4317  }
4318 
4319  /* And ensure any agg shutdown callbacks have been called */
4320  for (setno = 0; setno < numGroupingSets; setno++)
4321  ReScanExprContext(node->aggcontexts[setno]);
4322  if (node->hashcontext)
4324 
4325  /*
4326  * We don't actually free any ExprContexts here (see comment in
4327  * ExecFreeExprContext), just unlinking the output one from the plan node
4328  * suffices.
4329  */
4330  ExecFreeExprContext(&node->ss.ps);
4331 
4332  /* clean up tuple table */
4334 
4335  outerPlan = outerPlanState(node);
4337 }
int ParallelWorkerNumber
Definition: parallel.c:112
#define Max(x, y)
Definition: c.h:980
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:556
void ReScanExprContext(ExprContext *econtext)
Definition: execUtils.c:438
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:650
#define outerPlanState(node)
Definition: execnodes.h:1094
#define IsParallelWorker()
Definition: parallel.h:61
Assert(fmt[strlen(fmt) - 1] !='\n')
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
static void hashagg_reset_spill_state(AggState *aggstate)
Definition: nodeAgg.c:3115
#define outerPlan(node)
Definition: plannodes.h:172
Tuplesortstate ** sortstates
Definition: nodeAgg.h:154
MemoryContext hash_metacxt
Definition: execnodes.h:2368
Tuplesortstate * sort_out
Definition: execnodes.h:2359
uint64 hash_disk_used
Definition: execnodes.h:2386
AggStatePerTrans pertrans
Definition: execnodes.h:2336
int numtrans
Definition: execnodes.h:2329
ExprContext * hashcontext
Definition: execnodes.h:2337
Size hash_mem_peak
Definition: execnodes.h:2383
int hash_batches_used
Definition: execnodes.h:2387
Tuplesortstate * sort_in
Definition: execnodes.h:2358
int maxsets
Definition: execnodes.h:2356
ExprContext ** aggcontexts
Definition: execnodes.h:2338
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1426
AggregateInstrumentation sinstrument[FLEXIBLE_ARRAY_MEMBER]
Definition: execnodes.h:2302
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1620
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425

References AggState::aggcontexts, Assert(), ExecClearTuple(), ExecEndNode(), ExecFreeExprContext(), AggregateInstrumentation::hash_batches_used, AggState::hash_batches_used, AggregateInstrumentation::hash_disk_used, AggState::hash_disk_used, AggregateInstrumentation::hash_mem_peak, AggState::hash_mem_peak, AggState::hash_metacxt, hashagg_reset_spill_state(), AggState::hashcontext, IsParallelWorker, Max, AggState::maxsets, MemoryContextDelete(), AggState::numtrans, outerPlan, outerPlanState, ParallelWorkerNumber, AggState::pertrans, ScanState::ps, ReScanExprContext(), AggState::shared_info, SharedAggInfo::sinstrument, AggState::sort_in, AggState::sort_out, AggStatePerTransData::sortstates, AggState::ss, ScanState::ss_ScanTupleSlot, and tuplesort_end().

Referenced by ExecEndNode().

◆ ExecInitAgg()

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

Definition at line 3155 of file nodeAgg.c.

3156 {
3157  AggState *aggstate;
3158  AggStatePerAgg peraggs;
3159  AggStatePerTrans pertransstates;
3160  AggStatePerGroup *pergroups;
3161  Plan *outerPlan;
3162  ExprContext *econtext;
3163  TupleDesc scanDesc;
3164  int max_aggno;
3165  int max_transno;
3166  int numaggrefs;
3167  int numaggs;
3168  int numtrans;
3169  int phase;
3170  int phaseidx;
3171  ListCell *l;
3172  Bitmapset *all_grouped_cols = NULL;
3173  int numGroupingSets = 1;
3174  int numPhases;
3175  int numHashes;
3176  int i = 0;
3177  int j = 0;
3178  bool use_hashing = (node->aggstrategy == AGG_HASHED ||
3179  node->aggstrategy == AGG_MIXED);
3180 
3181  /* check for unsupported flags */
3182  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
3183 
3184  /*
3185  * create state structure
3186  */
3187  aggstate = makeNode(AggState);
3188  aggstate->ss.ps.plan = (Plan *) node;
3189  aggstate->ss.ps.state = estate;
3190  aggstate->ss.ps.ExecProcNode = ExecAgg;
3191 
3192  aggstate->aggs = NIL;
3193  aggstate->numaggs = 0;
3194  aggstate->numtrans = 0;
3195  aggstate->aggstrategy = node->aggstrategy;
3196  aggstate->aggsplit = node->aggsplit;
3197  aggstate->maxsets = 0;
3198  aggstate->projected_set = -1;
3199  aggstate->current_set = 0;
3200  aggstate->peragg = NULL;
3201  aggstate->pertrans = NULL;
3202  aggstate->curperagg = NULL;
3203  aggstate->curpertrans = NULL;
3204  aggstate->input_done = false;
3205  aggstate->agg_done = false;
3206  aggstate->pergroups = NULL;
3207  aggstate->grp_firstTuple = NULL;
3208  aggstate->sort_in = NULL;
3209  aggstate->sort_out = NULL;
3210 
3211  /*
3212  * phases[0] always exists, but is dummy in sorted/plain mode
3213  */
3214  numPhases = (use_hashing ? 1 : 2);
3215  numHashes = (use_hashing ? 1 : 0);
3216 
3217  /*
3218  * Calculate the maximum number of grouping sets in any phase; this
3219  * determines the size of some allocations. Also calculate the number of
3220  * phases, since all hashed/mixed nodes contribute to only a single phase.
3221  */
3222  if (node->groupingSets)
3223  {
3224  numGroupingSets = list_length(node->groupingSets);
3225 
3226  foreach(l, node->chain)
3227  {
3228  Agg *agg = lfirst(l);
3229 
3230  numGroupingSets = Max(numGroupingSets,
3231  list_length(agg->groupingSets));
3232 
3233  /*
3234  * additional AGG_HASHED aggs become part of phase 0, but all
3235  * others add an extra phase.
3236  */
3237  if (agg->aggstrategy != AGG_HASHED)
3238  ++numPhases;
3239  else
3240  ++numHashes;
3241  }
3242  }
3243 
3244  aggstate->maxsets = numGroupingSets;
3245  aggstate->numphases = numPhases;
3246 
3247  aggstate->aggcontexts = (ExprContext **)
3248  palloc0(sizeof(ExprContext *) * numGroupingSets);
3249 
3250  /*
3251  * Create expression contexts. We need three or more, one for
3252  * per-input-tuple processing, one for per-output-tuple processing, one
3253  * for all the hashtables, and one for each grouping set. The per-tuple
3254  * memory context of the per-grouping-set ExprContexts (aggcontexts)
3255  * replaces the standalone memory context formerly used to hold transition
3256  * values. We cheat a little by using ExecAssignExprContext() to build
3257  * all of them.
3258  *
3259  * NOTE: the details of what is stored in aggcontexts and what is stored
3260  * in the regular per-query memory context are driven by a simple
3261  * decision: we want to reset the aggcontext at group boundaries (if not
3262  * hashing) and in ExecReScanAgg to recover no-longer-wanted space.
3263  */
3264  ExecAssignExprContext(estate, &aggstate->ss.ps);
3265  aggstate->tmpcontext = aggstate->ss.ps.ps_ExprContext;
3266 
3267  for (i = 0; i < numGroupingSets; ++i)
3268  {
3269  ExecAssignExprContext(estate, &aggstate->ss.ps);
3270  aggstate->aggcontexts[i] = aggstate->ss.ps.ps_ExprContext;
3271  }
3272 
3273  if (use_hashing)
3274  aggstate->hashcontext = CreateWorkExprContext(estate);
3275 
3276  ExecAssignExprContext(estate, &aggstate->ss.ps);
3277 
3278  /*
3279  * Initialize child nodes.
3280  *
3281  * If we are doing a hashed aggregation then the child plan does not need
3282  * to handle REWIND efficiently; see ExecReScanAgg.
3283  */
3284  if (node->aggstrategy == AGG_HASHED)
3285  eflags &= ~EXEC_FLAG_REWIND;
3286  outerPlan = outerPlan(node);
3287  outerPlanState(aggstate) = ExecInitNode(outerPlan, estate, eflags);
3288 
3289  /*
3290  * initialize source tuple type.
3291  */
3292  aggstate->ss.ps.outerops =
3294  &aggstate->ss.ps.outeropsfixed);
3295  aggstate->ss.ps.outeropsset = true;
3296 
3297  ExecCreateScanSlotFromOuterPlan(estate, &aggstate->ss,
3298  aggstate->ss.ps.outerops);
3299  scanDesc = aggstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
3300 
3301  /*
3302  * If there are more than two phases (including a potential dummy phase
3303  * 0), input will be resorted using tuplesort. Need a slot for that.
3304  */
3305  if (numPhases > 2)
3306  {
3307  aggstate->sort_slot = ExecInitExtraTupleSlot(estate, scanDesc,
3309 
3310  /*
3311  * The output of the tuplesort, and the output from the outer child
3312  * might not use the same type of slot. In most cases the child will
3313  * be a Sort, and thus return a TTSOpsMinimalTuple type slot - but the
3314  * input can also be presorted due an index, in which case it could be
3315  * a different type of slot.
3316  *
3317  * XXX: For efficiency it would be good to instead/additionally
3318  * generate expressions with corresponding settings of outerops* for
3319  * the individual phases - deforming is often a bottleneck for
3320  * aggregations with lots of rows per group. If there's multiple
3321  * sorts, we know that all but the first use TTSOpsMinimalTuple (via
3322  * the nodeAgg.c internal tuplesort).
3323  */
3324  if (aggstate->ss.ps.outeropsfixed &&
3325  aggstate->ss.ps.outerops != &TTSOpsMinimalTuple)
3326  aggstate->ss.ps.outeropsfixed = false;
3327  }
3328 
3329  /*
3330  * Initialize result type, slot and projection.
3331  */
3333  ExecAssignProjectionInfo(&aggstate->ss.ps, NULL);
3334 
3335  /*
3336  * initialize child expressions
3337  *
3338  * We expect the parser to have checked that no aggs contain other agg
3339  * calls in their arguments (and just to be sure, we verify it again while
3340  * initializing the plan node). This would make no sense under SQL
3341  * semantics, and it's forbidden by the spec. Because it is true, we
3342  * don't need to worry about evaluating the aggs in any particular order.
3343  *
3344  * Note: execExpr.c finds Aggrefs for us, and adds them to aggstate->aggs.
3345  * Aggrefs in the qual are found here; Aggrefs in the targetlist are found
3346  * during ExecAssignProjectionInfo, above.
3347  */
3348  aggstate->ss.ps.qual =
3349  ExecInitQual(node->plan.qual, (PlanState *) aggstate);
3350 
3351  /*
3352  * We should now have found all Aggrefs in the targetlist and quals.
3353  */
3354  numaggrefs = list_length(aggstate->aggs);
3355  max_aggno = -1;
3356  max_transno = -1;
3357  foreach(l, aggstate->aggs)
3358  {
3359  Aggref *aggref = (Aggref *) lfirst(l);
3360 
3361  max_aggno = Max(max_aggno, aggref->aggno);
3362  max_transno = Max(max_transno, aggref->aggtransno);
3363  }
3364  numaggs = max_aggno + 1;
3365  numtrans = max_transno + 1;
3366 
3367  /*
3368  * For each phase, prepare grouping set data and fmgr lookup data for
3369  * compare functions. Accumulate all_grouped_cols in passing.
3370  */
3371  aggstate->phases = palloc0(numPhases * sizeof(AggStatePerPhaseData));
3372 
3373  aggstate->num_hashes = numHashes;
3374  if (numHashes)
3375  {
3376  aggstate->perhash = palloc0(sizeof(AggStatePerHashData) * numHashes);
3377  aggstate->phases[0].numsets = 0;
3378  aggstate->phases[0].gset_lengths = palloc(numHashes * sizeof(int));
3379  aggstate->phases[0].grouped_cols = palloc(numHashes * sizeof(Bitmapset *));
3380  }
3381 
3382  phase = 0;
3383  for (phaseidx = 0; phaseidx <= list_length(node->chain); ++phaseidx)
3384  {
3385  Agg *aggnode;
3386  Sort *sortnode;
3387 
3388  if (phaseidx > 0)
3389  {
3390  aggnode = list_nth_node(Agg, node->chain, phaseidx - 1);
3391  sortnode = castNode(Sort, aggnode->plan.lefttree);
3392  }
3393  else
3394  {
3395  aggnode = node;
3396  sortnode = NULL;
3397  }
3398 
3399  Assert(phase <= 1 || sortnode);
3400 
3401  if (aggnode->aggstrategy == AGG_HASHED
3402  || aggnode->aggstrategy == AGG_MIXED)
3403  {
3404  AggStatePerPhase phasedata = &aggstate->phases[0];
3405  AggStatePerHash perhash;
3406  Bitmapset *cols = NULL;
3407 
3408  Assert(phase == 0);
3409  i = phasedata->numsets++;
3410  perhash = &aggstate->perhash[i];
3411 
3412  /* phase 0 always points to the "real" Agg in the hash case */
3413  phasedata->aggnode = node;
3414  phasedata->aggstrategy = node->aggstrategy;
3415 
3416  /* but the actual Agg node representing this hash is saved here */
3417  perhash->aggnode = aggnode;
3418 
3419  phasedata->gset_lengths[i] = perhash->numCols = aggnode->numCols;
3420 
3421  for (j = 0; j < aggnode->numCols; ++j)
3422  cols = bms_add_member(cols, aggnode->grpColIdx[j]);
3423 
3424  phasedata->grouped_cols[i] = cols;
3425 
3426  all_grouped_cols = bms_add_members(all_grouped_cols, cols);
3427  continue;
3428  }
3429  else
3430  {
3431  AggStatePerPhase phasedata = &aggstate->phases[++phase];
3432  int num_sets;
3433 
3434  phasedata->numsets = num_sets = list_length(aggnode->groupingSets);
3435 
3436  if (num_sets)
3437  {
3438  phasedata->gset_lengths = palloc(num_sets * sizeof(int));
3439  phasedata->grouped_cols = palloc(num_sets * sizeof(Bitmapset *));
3440 
3441  i = 0;
3442  foreach(l, aggnode->groupingSets)
3443  {
3444  int current_length = list_length(lfirst(l));
3445  Bitmapset *cols = NULL;
3446 
3447  /* planner forces this to be correct */
3448  for (j = 0; j < current_length; ++j)
3449  cols = bms_add_member(cols, aggnode->grpColIdx[j]);
3450 
3451  phasedata->grouped_cols[i] = cols;
3452  phasedata->gset_lengths[i] = current_length;
3453 
3454  ++i;
3455  }
3456 
3457  all_grouped_cols = bms_add_members(all_grouped_cols,
3458  phasedata->grouped_cols[0]);
3459  }
3460  else
3461  {
3462  Assert(phaseidx == 0);
3463 
3464  phasedata->gset_lengths = NULL;
3465  phasedata->grouped_cols = NULL;
3466  }
3467 
3468  /*
3469  * If we are grouping, precompute fmgr lookup data for inner loop.
3470  */
3471  if (aggnode->aggstrategy == AGG_SORTED)
3472  {
3473  int i = 0;
3474 
3475  Assert(aggnode->numCols > 0);
3476 
3477  /*
3478  * Build a separate function for each subset of columns that
3479  * need to be compared.
3480  */
3481  phasedata->eqfunctions =
3482  (ExprState **) palloc0(aggnode->numCols * sizeof(ExprState *));
3483 
3484  /* for each grouping set */
3485  for (i = 0; i < phasedata->numsets; i++)
3486  {
3487  int length = phasedata->gset_lengths[i];
3488 
3489  if (phasedata->eqfunctions[length - 1] != NULL)
3490  continue;
3491 
3492  phasedata->eqfunctions[length - 1] =
3493  execTuplesMatchPrepare(scanDesc,
3494  length,
3495  aggnode->grpColIdx,
3496  aggnode->grpOperators,
3497  aggnode->grpCollations,
3498  (PlanState *) aggstate);
3499  }
3500 
3501  /* and for all grouped columns, unless already computed */
3502  if (phasedata->eqfunctions[aggnode->numCols - 1] == NULL)
3503  {
3504  phasedata->eqfunctions[aggnode->numCols - 1] =
3505  execTuplesMatchPrepare(scanDesc,
3506  aggnode->numCols,
3507  aggnode->grpColIdx,
3508  aggnode->grpOperators,
3509  aggnode->grpCollations,
3510  (PlanState *) aggstate);
3511  }
3512  }
3513 
3514  phasedata->aggnode = aggnode;
3515  phasedata->aggstrategy = aggnode->aggstrategy;
3516  phasedata->sortnode = sortnode;
3517  }
3518  }
3519 
3520  /*
3521  * Convert all_grouped_cols to a descending-order list.
3522  */
3523  i = -1;
3524  while ((i = bms_next_member(all_grouped_cols, i)) >= 0)
3525  aggstate->all_grouped_cols = lcons_int(i, aggstate->all_grouped_cols);
3526 
3527  /*
3528  * Set up aggregate-result storage in the output expr context, and also
3529  * allocate my private per-agg working storage
3530  */
3531  econtext = aggstate->ss.ps.ps_ExprContext;
3532  econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs);
3533  econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs);
3534 
3535  peraggs = (AggStatePerAgg) palloc0(sizeof(AggStatePerAggData) * numaggs);
3536  pertransstates = (AggStatePerTrans) palloc0(sizeof(AggStatePerTransData) * numtrans);
3537 
3538  aggstate->peragg = peraggs;
3539  aggstate->pertrans = pertransstates;
3540 
3541 
3542  aggstate->all_pergroups =
3544  * (numGroupingSets + numHashes));
3545  pergroups = aggstate->all_pergroups;
3546 
3547  if (node->aggstrategy != AGG_HASHED)
3548  {
3549  for (i = 0; i < numGroupingSets; i++)
3550  {
3551  pergroups[i] = (AggStatePerGroup) palloc0(sizeof(AggStatePerGroupData)
3552  * numaggs);
3553  }
3554 
3555  aggstate->pergroups = pergroups;
3556  pergroups += numGroupingSets;
3557  }
3558 
3559  /*
3560  * Hashing can only appear in the initial phase.
3561  */
3562  if (use_hashing)
3563  {
3564  Plan *outerplan = outerPlan(node);
3565  uint64 totalGroups = 0;
3566  int i;
3567 
3568  aggstate->hash_metacxt = AllocSetContextCreate(aggstate->ss.ps.state->es_query_cxt,
3569  "HashAgg meta context",
3571  aggstate->hash_spill_rslot = ExecInitExtraTupleSlot(estate, scanDesc,
3573  aggstate->hash_spill_wslot = ExecInitExtraTupleSlot(estate, scanDesc,
3574  &TTSOpsVirtual);
3575 
3576  /* this is an array of pointers, not structures */
3577  aggstate->hash_pergroup = pergroups;
3578 
3579  aggstate->hashentrysize = hash_agg_entry_size(aggstate->numtrans,
3580  outerplan->plan_width,
3581  node->transitionSpace);
3582 
3583  /*
3584  * Consider all of the grouping sets together when setting the limits
3585  * and estimating the number of partitions. This can be inaccurate
3586  * when there is more than one grouping set, but should still be
3587  * reasonable.
3588  */
3589  for (i = 0; i < aggstate->num_hashes; i++)
3590  totalGroups += aggstate->perhash[i].aggnode->numGroups;
3591 
3592  hash_agg_set_limits(aggstate->hashentrysize, totalGroups, 0,
3593  &aggstate->hash_mem_limit,
3594  &aggstate->hash_ngroups_limit,
3595  &aggstate->hash_planned_partitions);
3596  find_hash_columns(aggstate);
3597 
3598  /* Skip massive memory allocation if we are just doing EXPLAIN */
3599  if (!(eflags & EXEC_FLAG_EXPLAIN_ONLY))
3600  build_hash_tables(aggstate);
3601 
3602  aggstate->table_filled = false;
3603 
3604  /* Initialize this to 1, meaning nothing spilled, yet */
3605  aggstate->hash_batches_used = 1;
3606  }
3607 
3608  /*
3609  * Initialize current phase-dependent values to initial phase. The initial
3610  * phase is 1 (first sort pass) for all strategies that use sorting (if
3611  * hashing is being done too, then phase 0 is processed last); but if only
3612  * hashing is being done, then phase 0 is all there is.
3613  */
3614  if (node->aggstrategy == AGG_HASHED)
3615  {
3616  aggstate->current_phase = 0;
3617  initialize_phase(aggstate, 0);
3618  select_current_set(aggstate, 0, true);
3619  }
3620  else
3621  {
3622  aggstate->current_phase = 1;
3623  initialize_phase(aggstate, 1);
3624  select_current_set(aggstate, 0, false);
3625  }
3626 
3627  /*
3628  * Perform lookups of aggregate function info, and initialize the
3629  * unchanging fields of the per-agg and per-trans data.
3630  */
3631  foreach(l, aggstate->aggs)
3632  {
3633  Aggref *aggref = lfirst(l);
3634  AggStatePerAgg peragg;
3635  AggStatePerTrans pertrans;
3636  Oid aggTransFnInputTypes[FUNC_MAX_ARGS];
3637  int numAggTransFnArgs;
3638  int numDirectArgs;
3639  HeapTuple aggTuple;
3640  Form_pg_aggregate aggform;
3641  AclResult aclresult;
3642  Oid finalfn_oid;
3643  Oid serialfn_oid,
3644  deserialfn_oid;
3645  Oid aggOwner;
3646  Expr *finalfnexpr;
3647  Oid aggtranstype;
3648 
3649  /* Planner should have assigned aggregate to correct level */
3650  Assert(aggref->agglevelsup == 0);
3651  /* ... and the split mode should match */
3652  Assert(aggref->aggsplit == aggstate->aggsplit);
3653 
3654  peragg = &peraggs[aggref->aggno];
3655 
3656  /* Check if we initialized the state for this aggregate already. */
3657  if (peragg->aggref != NULL)
3658  continue;
3659 
3660  peragg->aggref = aggref;
3661  peragg->transno = aggref->aggtransno;
3662 
3663  /* Fetch the pg_aggregate row */
3664  aggTuple = SearchSysCache1(AGGFNOID,
3665  ObjectIdGetDatum(aggref->aggfnoid));
3666  if (!HeapTupleIsValid(aggTuple))
3667  elog(ERROR, "cache lookup failed for aggregate %u",
3668  aggref->aggfnoid);
3669  aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);
3670 
3671  /* Check permission to call aggregate function */
3672  aclresult = pg_proc_aclcheck(aggref->aggfnoid, GetUserId(),
3673  ACL_EXECUTE);
3674  if (aclresult != ACLCHECK_OK)
3675  aclcheck_error(aclresult, OBJECT_AGGREGATE,
3676  get_func_name(aggref->aggfnoid));
3678 
3679  /* planner recorded transition state type in the Aggref itself */
3680  aggtranstype = aggref->aggtranstype;
3681  Assert(OidIsValid(aggtranstype));
3682 
3683  /* Final function only required if we're finalizing the aggregates */
3684  if (DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit))
3685  peragg->finalfn_oid = finalfn_oid = InvalidOid;
3686  else
3687  peragg->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
3688 
3689  serialfn_oid = InvalidOid;
3690  deserialfn_oid = InvalidOid;
3691 
3692  /*
3693  * Check if serialization/deserialization is required. We only do it
3694  * for aggregates that have transtype INTERNAL.
3695  */
3696  if (aggtranstype == INTERNALOID)
3697  {
3698  /*
3699  * The planner should only have generated a serialize agg node if
3700  * every aggregate with an INTERNAL state has a serialization
3701  * function. Verify that.
3702  */
3703  if (DO_AGGSPLIT_SERIALIZE(aggstate->aggsplit))
3704  {
3705  /* serialization only valid when not running finalfn */
3707 
3708  if (!OidIsValid(aggform->aggserialfn))
3709  elog(ERROR, "serialfunc not provided for serialization aggregation");
3710  serialfn_oid = aggform->aggserialfn;
3711  }
3712 
3713  /* Likewise for deserialization functions */
3714  if (DO_AGGSPLIT_DESERIALIZE(aggstate->aggsplit))
3715  {
3716  /* deserialization only valid when combining states */
3717  Assert(DO_AGGSPLIT_COMBINE(aggstate->aggsplit));
3718 
3719  if (!OidIsValid(aggform->aggdeserialfn))
3720  elog(ERROR, "deserialfunc not provided for deserialization aggregation");
3721  deserialfn_oid = aggform->aggdeserialfn;
3722  }
3723  }
3724 
3725  /* Check that aggregate owner has permission to call component fns */
3726  {
3727  HeapTuple procTuple;
3728 
3729  procTuple = SearchSysCache1(PROCOID,
3730  ObjectIdGetDatum(aggref->aggfnoid));
3731  if (!HeapTupleIsValid(procTuple))
3732  elog(ERROR, "cache lookup failed for function %u",
3733  aggref->aggfnoid);
3734  aggOwner = ((Form_pg_proc) GETSTRUCT(procTuple))->proowner;
3735  ReleaseSysCache(procTuple);
3736 
3737  if (OidIsValid(finalfn_oid))
3738  {
3739  aclresult = pg_proc_aclcheck(finalfn_oid, aggOwner,
3740  ACL_EXECUTE);
3741  if (aclresult != ACLCHECK_OK)
3742  aclcheck_error(aclresult, OBJECT_FUNCTION,
3743  get_func_name(finalfn_oid));
3744  InvokeFunctionExecuteHook(finalfn_oid);
3745  }
3746  if (OidIsValid(serialfn_oid))
3747  {
3748  aclresult = pg_proc_aclcheck(serialfn_oid, aggOwner,
3749  ACL_EXECUTE);
3750  if (aclresult != ACLCHECK_OK)
3751  aclcheck_error(aclresult, OBJECT_FUNCTION,
3752  get_func_name(serialfn_oid));
3753  InvokeFunctionExecuteHook(serialfn_oid);
3754  }
3755  if (OidIsValid(deserialfn_oid))
3756  {
3757  aclresult = pg_proc_aclcheck(deserialfn_oid, aggOwner,
3758  ACL_EXECUTE);
3759  if (aclresult != ACLCHECK_OK)
3760  aclcheck_error(aclresult, OBJECT_FUNCTION,
3761  get_func_name(deserialfn_oid));
3762  InvokeFunctionExecuteHook(deserialfn_oid);
3763  }
3764  }
3765 
3766  /*
3767  * Get actual datatypes of the (nominal) aggregate inputs. These
3768  * could be different from the agg's declared input types, when the
3769  * agg accepts ANY or a polymorphic type.
3770  */
3771  numAggTransFnArgs = get_aggregate_argtypes(aggref,
3772  aggTransFnInputTypes);
3773 
3774  /* Count the "direct" arguments, if any */
3775  numDirectArgs = list_length(aggref->aggdirectargs);
3776 
3777  /* Detect how many arguments to pass to the finalfn */
3778  if (aggform->aggfinalextra)
3779  peragg->numFinalArgs = numAggTransFnArgs + 1;
3780  else
3781  peragg->numFinalArgs = numDirectArgs + 1;
3782 
3783  /* Initialize any direct-argument expressions */
3784  peragg->aggdirectargs = ExecInitExprList(aggref->aggdirectargs,
3785  (PlanState *) aggstate);
3786 
3787  /*
3788  * build expression trees using actual argument & result types for the
3789  * finalfn, if it exists and is required.
3790  */
3791  if (OidIsValid(finalfn_oid))
3792  {
3793  build_aggregate_finalfn_expr(aggTransFnInputTypes,
3794  peragg->numFinalArgs,
3795  aggtranstype,
3796  aggref->aggtype,
3797  aggref->inputcollid,
3798  finalfn_oid,
3799  &finalfnexpr);
3800  fmgr_info(finalfn_oid, &peragg->finalfn);
3801  fmgr_info_set_expr((Node *) finalfnexpr, &peragg->finalfn);
3802  }
3803 
3804  /* get info about the output value's datatype */
3805  get_typlenbyval(aggref->aggtype,
3806  &peragg->resulttypeLen,
3807  &peragg->resulttypeByVal);
3808 
3809  /*
3810  * Build working state for invoking the transition function, if we
3811  * haven't done it already.
3812  */
3813  pertrans = &pertransstates[aggref->aggtransno];
3814  if (pertrans->aggref == NULL)
3815  {
3816  Datum textInitVal;
3817  Datum initValue;
3818  bool initValueIsNull;
3819  Oid transfn_oid;
3820 
3821  /*
3822  * If this aggregation is performing state combines, then instead
3823  * of using the transition function, we'll use the combine
3824  * function.
3825  */
3826  if (DO_AGGSPLIT_COMBINE(aggstate->aggsplit))
3827  {
3828  transfn_oid = aggform->aggcombinefn;
3829 
3830  /* If not set then the planner messed up */
3831  if (!OidIsValid(transfn_oid))
3832  elog(ERROR, "combinefn not set for aggregate function");
3833  }
3834  else
3835  transfn_oid = aggform->aggtransfn;
3836 
3837  aclresult = pg_proc_aclcheck(transfn_oid, aggOwner, ACL_EXECUTE);
3838  if (aclresult != ACLCHECK_OK)
3839  aclcheck_error(aclresult, OBJECT_FUNCTION,
3840  get_func_name(transfn_oid));
3841  InvokeFunctionExecuteHook(transfn_oid);
3842 
3843  /*
3844  * initval is potentially null, so don't try to access it as a
3845  * struct field. Must do it the hard way with SysCacheGetAttr.
3846  */
3847  textInitVal = SysCacheGetAttr(AGGFNOID, aggTuple,
3848  Anum_pg_aggregate_agginitval,
3849  &initValueIsNull);
3850  if (initValueIsNull)
3851  initValue = (Datum) 0;
3852  else
3853  initValue = GetAggInitVal(textInitVal, aggtranstype);
3854 
3855  if (DO_AGGSPLIT_COMBINE(aggstate->aggsplit))
3856  {
3857  Oid combineFnInputTypes[] = {aggtranstype,
3858  aggtranstype};
3859 
3860  /*
3861  * When combining there's only one input, the to-be-combined
3862  * transition value. The transition value is not counted
3863  * here.
3864  */
3865  pertrans->numTransInputs = 1;
3866 
3867  /* aggcombinefn always has two arguments of aggtranstype */
3868  build_pertrans_for_aggref(pertrans, aggstate, estate,
3869  aggref, transfn_oid, aggtranstype,
3870  serialfn_oid, deserialfn_oid,
3871  initValue, initValueIsNull,
3872  combineFnInputTypes, 2);
3873 
3874  /*
3875  * Ensure that a combine function to combine INTERNAL states
3876  * is not strict. This should have been checked during CREATE
3877  * AGGREGATE, but the strict property could have been changed
3878  * since then.
3879  */
3880  if (pertrans->transfn.fn_strict && aggtranstype == INTERNALOID)
3881  ereport(ERROR,
3882  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
3883  errmsg("combine function with transition type %s must not be declared STRICT",
3884  format_type_be(aggtranstype))));
3885  }
3886  else
3887  {
3888  /* Detect how many arguments to pass to the transfn */
3889  if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
3890  pertrans->numTransInputs = list_length(aggref->args);
3891  else
3892  pertrans->numTransInputs = numAggTransFnArgs;
3893 
3894  build_pertrans_for_aggref(pertrans, aggstate, estate,
3895  aggref, transfn_oid, aggtranstype,
3896  serialfn_oid, deserialfn_oid,
3897  initValue, initValueIsNull,
3898  aggTransFnInputTypes,
3899  numAggTransFnArgs);
3900 
3901  /*
3902  * If the transfn is strict and the initval is NULL, make sure
3903  * input type and transtype are the same (or at least
3904  * binary-compatible), so that it's OK to use the first
3905  * aggregated input value as the initial transValue. This
3906  * should have been checked at agg definition time, but we
3907  * must check again in case the transfn's strictness property
3908  * has been changed.
3909  */
3910  if (pertrans->transfn.fn_strict && pertrans->initValueIsNull)
3911  {
3912  if (numAggTransFnArgs <= numDirectArgs ||
3913  !IsBinaryCoercible(aggTransFnInputTypes[numDirectArgs],
3914  aggtranstype))
3915  ereport(ERROR,
3916  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
3917  errmsg("aggregate %u needs to have compatible input type and transition type",
3918  aggref->aggfnoid)));
3919  }
3920  }
3921  }
3922  else
3923  pertrans->aggshared = true;
3924  ReleaseSysCache(aggTuple);
3925  }
3926 
3927  /*
3928  * Update aggstate->numaggs to be the number of unique aggregates found.
3929  * Also set numstates to the number of unique transition states found.
3930  */
3931  aggstate->numaggs = numaggs;
3932  aggstate->numtrans = numtrans;
3933 
3934  /*
3935  * Last, check whether any more aggregates got added onto the node while
3936  * we processed the expressions for the aggregate arguments (including not
3937  * only the regular arguments and FILTER expressions handled immediately
3938  * above, but any direct arguments we might've handled earlier). If so,
3939  * we have nested aggregate functions, which is semantically nonsensical,
3940  * so complain. (This should have been caught by the parser, so we don't
3941  * need to work hard on a helpful error message; but we defend against it
3942  * here anyway, just to be sure.)
3943  */
3944  if (numaggrefs != list_length(aggstate->aggs))
3945  ereport(ERROR,
3946  (errcode(ERRCODE_GROUPING_ERROR),
3947  errmsg("aggregate function calls cannot be nested")));
3948 
3949  /*
3950  * Build expressions doing all the transition work at once. We build a
3951  * different one for each phase, as the number of transition function
3952  * invocation can differ between phases. Note this'll work both for
3953  * transition and combination functions (although there'll only be one
3954  * phase in the latter case).
3955  */
3956  for (phaseidx = 0; phaseidx < aggstate->numphases; phaseidx++)
3957  {
3958  AggStatePerPhase phase = &aggstate->phases[phaseidx];
3959  bool dohash = false;
3960  bool dosort = false;
3961 
3962  /* phase 0 doesn't necessarily exist */
3963  if (!phase->aggnode)
3964  continue;
3965 
3966  if (aggstate->aggstrategy == AGG_MIXED && phaseidx == 1)
3967  {
3968  /*
3969  * Phase one, and only phase one, in a mixed agg performs both
3970  * sorting and aggregation.
3971  */
3972  dohash = true;
3973  dosort = true;
3974  }
3975  else if (aggstate->aggstrategy == AGG_MIXED && phaseidx == 0)
3976  {
3977  /*
3978  * No need to compute a transition function for an AGG_MIXED phase
3979  * 0 - the contents of the hashtables will have been computed
3980  * during phase 1.
3981  */
3982  continue;
3983  }
3984  else if (phase->aggstrategy == AGG_PLAIN ||
3985  phase->aggstrategy == AGG_SORTED)
3986  {
3987  dohash = false;
3988  dosort = true;
3989  }
3990  else if (phase->aggstrategy == AGG_HASHED)
3991  {
3992  dohash = true;
3993  dosort = false;
3994  }
3995  else
3996  Assert(false);
3997 
3998  phase->evaltrans = ExecBuildAggTrans(aggstate, phase, dosort, dohash,
3999  false);
4000 
4001  /* cache compiled expression for outer slot without NULL check */
4002  phase->evaltrans_cache[0][0] = phase->evaltrans;
4003  }
4004 
4005  return aggstate;
4006 }
AclResult
Definition: acl.h:181
@ ACLCHECK_OK
Definition: acl.h:182
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3512
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:5071
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1045
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:738
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:795
#define OidIsValid(objectId)
Definition: c.h:710
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
#define ereport(elevel,...)
Definition: elog.h:143
List * ExecInitExprList(List *nodes, PlanState *parent)
Definition: execExpr.c:318
ExprState * ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, bool doSort, bool doHash, bool nullcheck)
Definition: execExpr.c:3538
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:209
ExprState * execTuplesMatchPrepare(TupleDesc desc, int numCols, const AttrNumber *keyColIdx, const Oid *eqOperators, const Oid *collations, PlanState *parent)
Definition: execGrouping.c:59
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:141
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1831
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1799
const TupleTableSlotOps TTSOpsMinimalTuple
Definition: execTuples.c:85
ExprContext * CreateWorkExprContext(EState *estate)
Definition: execUtils.c:316
const TupleTableSlotOps * ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
Definition: execUtils.c:499
void ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate, const TupleTableSlotOps *tts_ops)
Definition: execUtils.c:682
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:480
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:535
struct AggStatePerGroupData * AggStatePerGroup
Definition: execnodes.h:2320
struct AggStatePerTransData * AggStatePerTrans
Definition: execnodes.h:2319
struct AggStatePerAggData * AggStatePerAgg
Definition: execnodes.h:2318
#define EXEC_FLAG_BACKWARD
Definition: executor.h:58
#define EXEC_FLAG_REWIND
Definition: executor.h:57
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:56
#define EXEC_FLAG_MARK
Definition: executor.h:59
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:126
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:135
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:649
static int initValue(long lng_val)
Definition: informix.c:677
int j
Definition: isn.c:74
int i
Definition: isn.c:73
List * lcons_int(int datum, List *list)
Definition: list.c:492
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:2208
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1589
void * palloc0(Size size)
Definition: mcxt.c:1099
#define AllocSetContextCreate
Definition: memutils.h:173
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
Oid GetUserId(void)
Definition: miscinit.c:492
static void find_hash_columns(AggState *aggstate)
Definition: nodeAgg.c:1546
static Datum GetAggInitVal(Datum textInitVal, Oid transtype)
Definition: nodeAgg.c:4254
static TupleTableSlot * ExecAgg(PlanState *pstate)
Definition: nodeAgg.c:2140
static void initialize_phase(AggState *aggstate, int newphase)
Definition: nodeAgg.c:479
Size hash_agg_entry_size(int numTrans, Size tupleWidth, Size transitionSpace)
Definition: nodeAgg.c:1676
static void build_pertrans_for_aggref(AggStatePerTrans pertrans, AggState *aggstate, EState *estate, Aggref *aggref, Oid transfn_oid, Oid aggtranstype, Oid aggserialfn, Oid aggdeserialfn, Datum initValue, bool initValueIsNull, Oid *inputTypes, int numArguments)
Definition: nodeAgg.c:4019
static void build_hash_tables(AggState *aggstate)
Definition: nodeAgg.c:1451
static void select_current_set(AggState *aggstate, int setno, bool is_hash)
Definition: nodeAgg.c:457
void hash_agg_set_limits(double hashentrysize, double input_groups, int used_bits, Size *mem_limit, uint64 *ngroups_limit, int *num_partitions)
Definition: nodeAgg.c:1780
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:839
#define DO_AGGSPLIT_DESERIALIZE(as)
Definition: nodes.h:841
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:838
@ AGG_SORTED
Definition: nodes.h:808
@ AGG_HASHED
Definition: nodes.h:809
@ AGG_MIXED
Definition: nodes.h:810
@ AGG_PLAIN
Definition: nodes.h:807
#define DO_AGGSPLIT_SERIALIZE(as)
Definition: nodes.h:840
#define makeNode(_type_)
Definition: nodes.h:621
#define castNode(_type_, nodeptr)
Definition: nodes.h:642
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:211
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:2084
int get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
Definition: parse_agg.c:1890
bool IsBinaryCoercible(Oid srctype, Oid targettype)
@ OBJECT_AGGREGATE
Definition: parsenodes.h:2135
@ OBJECT_FUNCTION
Definition: parsenodes.h:2153
#define ACL_EXECUTE
Definition: parsenodes.h:89
FormData_pg_aggregate * Form_pg_aggregate
Definition: pg_aggregate.h:109
#define FUNC_MAX_ARGS
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
#define NIL
Definition: pg_list.h:65
#define list_nth_node(type, list, n)
Definition: pg_list.h:306
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:136
uintptr_t Datum
Definition: postgres.h:411
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
FmgrInfo finalfn
Definition: nodeAgg.h:199
bool resulttypeByVal
Definition: nodeAgg.h:217
List * aggdirectargs
Definition: nodeAgg.h:210
Aggref * aggref
Definition: nodeAgg.h:187
int16 resulttypeLen
Definition: nodeAgg.h:216
Bitmapset ** grouped_cols
Definition: nodeAgg.h:277
ExprState * evaltrans
Definition: nodeAgg.h:283
ExprState * evaltrans_cache[2][2]
Definition: nodeAgg.h:291
ExprState ** eqfunctions
Definition: nodeAgg.h:278
AggStrategy aggstrategy
Definition: nodeAgg.h:274
FmgrInfo transfn
Definition: nodeAgg.h:81
Aggref * aggref
Definition: nodeAgg.h:44
AggStatePerGroup * all_pergroups
Definition: execnodes.h:2395
AggStatePerGroup * hash_pergroup
Definition: execnodes.h:2390
List * aggs
Definition: execnodes.h:2327
ExprContext * tmpcontext
Definition: execnodes.h:2339
int hash_planned_partitions
Definition: execnodes.h:2380
HeapTuple grp_firstTuple
Definition: execnodes.h:2364
Size hash_mem_limit
Definition: execnodes.h:2378
AggStatePerTrans curpertrans
Definition: execnodes.h:2344
bool table_filled
Definition: execnodes.h:2366
int current_set
Definition: execnodes.h:2349
AggStrategy aggstrategy
Definition: execnodes.h:2330
AggSplit aggsplit
Definition: execnodes.h:2331
int projected_set
Definition: execnodes.h:2347
uint64 hash_ngroups_limit
Definition: execnodes.h:2379
bool input_done
Definition: execnodes.h:2345
AggStatePerPhase phases
Definition: execnodes.h:2357
List * all_grouped_cols
Definition: execnodes.h:2351
AggStatePerGroup * pergroups
Definition: execnodes.h:2362
AggStatePerHash perhash
Definition: execnodes.h:2389
double hashentrysize
Definition: execnodes.h:2382
int numphases
Definition: execnodes.h:2333
TupleTableSlot * hash_spill_wslot
Definition: execnodes.h:2373
AggStatePerAgg curperagg
Definition: execnodes.h:2342
TupleTableSlot * sort_slot
Definition: execnodes.h:2360
int numaggs
Definition: execnodes.h:2328
int num_hashes
Definition: execnodes.h:2367
AggStatePerAgg peragg
Definition: execnodes.h:2335
TupleTableSlot * hash_spill_rslot
Definition: execnodes.h:2372
int current_phase
Definition: execnodes.h:2334
bool agg_done
Definition: execnodes.h:2346
Definition: plannodes.h:895
AggSplit aggsplit
Definition: plannodes.h:898
List * chain
Definition: plannodes.h:908
long numGroups
Definition: plannodes.h:903
List * groupingSets
Definition: plannodes.h:907
AttrNumber * grpColIdx
Definition: plannodes.h:900
Plan plan
Definition: plannodes.h:896
int numCols
Definition: plannodes.h:899
uint64 transitionSpace
Definition: plannodes.h:904
Oid * grpOperators
Definition: plannodes.h:901
AggStrategy aggstrategy
Definition: plannodes.h:897
Oid * grpCollations
Definition: plannodes.h:902
Oid aggfnoid
Definition: primnodes.h:332
List * aggdirectargs
Definition: primnodes.h:338
char aggkind
Definition: primnodes.h:346
Oid aggtranstype
Definition: primnodes.h:336
int aggtransno
Definition: primnodes.h:350
Index agglevelsup
Definition: primnodes.h:347
List * args
Definition: primnodes.h:339
Oid inputcollid
Definition: primnodes.h:335
Oid aggtype
Definition: primnodes.h:333
AggSplit aggsplit
Definition: primnodes.h:348
int aggno
Definition: primnodes.h:349
MemoryContext es_query_cxt
Definition: execnodes.h:632
Datum * ecxt_aggvalues
Definition: execnodes.h:251
bool * ecxt_aggnulls
Definition: execnodes.h:253
bool fn_strict
Definition: fmgr.h:61
Definition: nodes.h:574
bool outeropsset
Definition: execnodes.h:1081
const TupleTableSlotOps * outerops
Definition: execnodes.h:1073
ExprState * qual
Definition: execnodes.h:1019
bool outeropsfixed
Definition: execnodes.h:1077
EState * state
Definition: execnodes.h:1000
ExprContext * ps_ExprContext
Definition: execnodes.h:1037
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1004
struct Plan * lefttree
Definition: plannodes.h:144
List * qual
Definition: plannodes.h:143
int plan_width
Definition: plannodes.h:125
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:124
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1221
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1173
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1434
@ AGGFNOID
Definition: syscache.h:34
@ PROCOID
Definition: syscache.h:79

References ACL_EXECUTE, aclcheck_error(), ACLCHECK_OK, AggState::agg_done, AGG_HASHED, AGG_MIXED, AGG_PLAIN, AGG_SORTED, AggState::aggcontexts, AggStatePerAggData::aggdirectargs, Aggref::aggdirectargs, Aggref::aggfnoid, AGGFNOID, Aggref::aggkind, Aggref::agglevelsup, Aggref::aggno, AggStatePerPhaseData::aggnode, AggStatePerHashData::aggnode, AggStatePerTransData::aggref, AggStatePerAggData::aggref, AggState::aggs, AggStatePerTransData::aggshared, AggState::aggsplit, Agg::aggsplit, Aggref::aggsplit, AggStatePerPhaseData::aggstrategy, AggState::aggstrategy, Agg::aggstrategy, Aggref::aggtransno, Aggref::aggtranstype, Aggref::aggtype, AggState::all_grouped_cols, AggState::all_pergroups, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Aggref::args, 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_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, ereport, errcode(), errmsg(), ERROR, EState::es_query_cxt, AggStatePerPhaseData::evaltrans, AggStatePerPhaseData::evaltrans_cache, EXEC_FLAG_BACKWARD, EXEC_FLAG_EXPLAIN_ONLY, 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_hash_columns(), fmgr_info(), fmgr_info_set_expr, FmgrInfo::fn_strict, format_type_be(), 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::hash_batches_used, AggState::hash_mem_limit, AggState::hash_metacxt, AggState::hash_ngroups_limit, AggState::hash_pergroup, AggState::hash_planned_partitions, AggState::hash_spill_rslot, AggState::hash_spill_wslot, AggState::hashcontext, AggState::hashentrysize, HeapTupleIsValid, i, initialize_phase(), initValue(), AggStatePerTransData::initValueIsNull, AggState::input_done, Aggref::inputcollid, InvalidOid, InvokeFunctionExecuteHook, IsBinaryCoercible(), j, lcons_int(), Plan::lefttree, lfirst, list_length(), list_nth_node, makeNode, Max, AggState::maxsets, NIL, AggState::num_hashes, AggState::numaggs, AggStatePerHashData::numCols, Agg::numCols, AggStatePerAggData::numFinalArgs, Agg::numGroups, AggState::numphases, AggStatePerPhaseData::numsets, AggState::numtrans, AggStatePerTransData::numTransInputs, OBJECT_AGGREGATE, OBJECT_FUNCTION, ObjectIdGetDatum, OidIsValid, PlanState::outerops, PlanState::outeropsfixed, PlanState::outeropsset, outerPlan, outerPlanState, palloc(), palloc0(), AggState::peragg, AggState::pergroups, AggState::perhash, AggState::pertrans, pg_proc_aclcheck(), AggState::phases, PlanState::plan, Agg::plan, Plan::plan_width, PROCOID, AggState::projected_set, ScanState::ps, PlanState::ps_ExprContext, PlanState::qual, Plan::qual, ReleaseSysCache(), 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, AggStatePerTransData::transfn, Agg::transitionSpace, AggStatePerAggData::transno, TupleTableSlot::tts_tupleDescriptor, TTSOpsMinimalTuple, and TTSOpsVirtual.

Referenced by ExecInitNode().

◆ ExecReScanAgg()

void ExecReScanAgg ( AggState node)

Definition at line 4340 of file nodeAgg.c.

4341 {
4342  ExprContext *econtext = node->ss.ps.ps_ExprContext;
4344  Agg *aggnode = (Agg *) node->ss.ps.plan;
4345  int transno;
4346  int numGroupingSets = Max(node->maxsets, 1);
4347  int setno;
4348 
4349  node->agg_done = false;
4350 
4351  if (node->aggstrategy == AGG_HASHED)
4352  {
4353  /*
4354  * In the hashed case, if we haven't yet built the hash table then we
4355  * can just return; nothing done yet, so nothing to undo. If subnode's
4356  * chgParam is not NULL then it will be re-scanned by ExecProcNode,
4357  * else no reason to re-scan it at all.
4358  */
4359  if (!node->table_filled)
4360  return;
4361 
4362  /*
4363  * If we do have the hash table, and it never spilled, and the subplan
4364  * does not have any parameter changes, and none of our own parameter
4365  * changes affect input expressions of the aggregated functions, then
4366  * we can just rescan the existing hash table; no need to build it
4367  * again.
4368  */
4369  if (outerPlan->chgParam == NULL && !node->hash_ever_spilled &&
4370  !bms_overlap(node->ss.ps.chgParam, aggnode->aggParams))
4371  {
4373  &node->perhash[0].hashiter);
4374  select_current_set(node, 0, true);
4375  return;
4376  }
4377  }
4378 
4379  /* Make sure we have closed any open tuplesorts */
4380  for (transno = 0; transno < node->numtrans; transno++)
4381  {
4382  for (setno = 0; setno < numGroupingSets; setno++)
4383  {
4384  AggStatePerTrans pertrans = &node->pertrans[transno];
4385 
4386  if (pertrans->sortstates[setno])
4387  {
4388  tuplesort_end(pertrans->sortstates[setno]);
4389  pertrans->sortstates[setno] = NULL;
4390  }
4391  }
4392  }
4393 
4394  /*
4395  * We don't need to ReScanExprContext the output tuple context here;
4396  * ExecReScan already did it. But we do need to reset our per-grouping-set
4397  * contexts, which may have transvalues stored in them. (We use rescan
4398  * rather than just reset because transfns may have registered callbacks
4399  * that need to be run now.) For the AGG_HASHED case, see below.
4400  */
4401 
4402  for (setno = 0; setno < numGroupingSets; setno++)
4403  {
4404  ReScanExprContext(node->aggcontexts[setno]);
4405  }
4406 
4407  /* Release first tuple of group, if we have made a copy */
4408  if (node->grp_firstTuple != NULL)
4409  {
4411  node->grp_firstTuple = NULL;
4412  }
4414 
4415  /* Forget current agg values */
4416  MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numaggs);
4417  MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numaggs);
4418 
4419  /*
4420  * With AGG_HASHED/MIXED, the hash table is allocated in a sub-context of
4421  * the hashcontext. This used to be an issue, but now, resetting a context
4422  * automatically deletes sub-contexts too.
4423  */
4424  if (node->aggstrategy == AGG_HASHED || node->aggstrategy == AGG_MIXED)
4425  {
4427 
4428  node->hash_ever_spilled = false;
4429  node->hash_spill_mode = false;
4430  node->hash_ngroups_current = 0;
4431 
4433  /* Rebuild an empty hash table */
4434  build_hash_tables(node);
4435  node->table_filled = false;
4436  /* iterator will be reset when the table is filled */
4437 
4438  hashagg_recompile_expressions(node, false, false);
4439  }
4440 
4441  if (node->aggstrategy != AGG_HASHED)
4442  {
4443  /*
4444  * Reset the per-group state (in particular, mark transvalues null)
4445  */
4446  for (setno = 0; setno < numGroupingSets; setno++)
4447  {
4448  MemSet(node->pergroups[setno], 0,
4449  sizeof(AggStatePerGroupData) * node->numaggs);
4450  }
4451 
4452  /* reset to phase 1 */
4453  initialize_phase(node, 1);
4454 
4455  node->input_done = false;
4456  node->projected_set = -1;
4457  }
4458 
4459  if (outerPlan->chgParam == NULL)
4461 }
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:494
#define MemSet(start, val, len)
Definition: c.h:1008
void ExecReScan(PlanState *node)
Definition: execAmi.c:78
#define ResetTupleHashIterator(htable, iter)
Definition: execnodes.h:801
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
static void hashagg_recompile_expressions(AggState *aggstate, bool minslot, bool nullcheck)
Definition: nodeAgg.c:1723
TupleHashTable hashtable
Definition: nodeAgg.h:303
TupleHashIterator hashiter
Definition: nodeAgg.h:304
bool hash_spill_mode
Definition: execnodes.h:2376
uint64 hash_ngroups_current
Definition: execnodes.h:2384
bool hash_ever_spilled
Definition: execnodes.h:2375
Bitmapset * aggParams
Definition: plannodes.h:905
Bitmapset * chgParam
Definition: execnodes.h:1030

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().

◆ hash_agg_entry_size()

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

Definition at line 1676 of file nodeAgg.c.

1677 {
1678  Size tupleChunkSize;
1679  Size pergroupChunkSize;
1680  Size transitionChunkSize;
1681  Size tupleSize = (MAXALIGN(SizeofMinimalTupleHeader) +
1682  tupleWidth);
1683  Size pergroupSize = numTrans * sizeof(AggStatePerGroupData);
1684 
1685  tupleChunkSize = CHUNKHDRSZ + tupleSize;
1686 
1687  if (pergroupSize > 0)
1688  pergroupChunkSize = CHUNKHDRSZ + pergroupSize;
1689  else
1690  pergroupChunkSize = 0;
1691 
1692  if (transitionSpace > 0)
1693  transitionChunkSize = CHUNKHDRSZ + transitionSpace;
1694  else
1695  transitionChunkSize = 0;
1696 
1697  return
1698  sizeof(TupleHashEntryData) +
1699  tupleChunkSize +
1700  pergroupChunkSize +
1701  transitionChunkSize;
1702 }
#define MAXALIGN(LEN)
Definition: c.h:757
struct TupleHashEntryData TupleHashEntryData
#define SizeofMinimalTupleHeader
Definition: htup_details.h:643
#define CHUNKHDRSZ
Definition: nodeAgg.c:321
struct AggStatePerGroupData AggStatePerGroupData

References CHUNKHDRSZ, MAXALIGN, and SizeofMinimalTupleHeader.

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

◆ hash_agg_set_limits()

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

Definition at line 1780 of file nodeAgg.c.

1783 {
1784  int npartitions;
1785  Size partition_mem;
1786  Size hash_mem_limit = get_hash_memory_limit();
1787 
1788  /* if not expected to spill, use all of hash_mem */
1789  if (input_groups * hashentrysize <= hash_mem_limit)
1790  {
1791  if (num_partitions != NULL)
1792  *num_partitions = 0;
1793  *mem_limit = hash_mem_limit;
1794  *ngroups_limit = hash_mem_limit / hashentrysize;
1795  return;
1796  }
1797 
1798  /*
1799  * Calculate expected memory requirements for spilling, which is the size
1800  * of the buffers needed for all the tapes that need to be open at once.
1801  * Then, subtract that from the memory available for holding hash tables.
1802  */
1803  npartitions = hash_choose_num_partitions(input_groups,
1804  hashentrysize,
1805  used_bits,
1806  NULL);
1807  if (num_partitions != NULL)
1808  *num_partitions = npartitions;
1809 
1810  partition_mem =
1812  HASHAGG_WRITE_BUFFER_SIZE * npartitions;
1813 
1814  /*
1815  * Don't set the limit below 3/4 of hash_mem. In that case, we are at the
1816  * minimum number of partitions, so we aren't going to dramatically exceed
1817  * work mem anyway.
1818  */
1819  if (hash_mem_limit > 4 * partition_mem)
1820  *mem_limit = hash_mem_limit - partition_mem;
1821  else
1822  *mem_limit = hash_mem_limit * 0.75;
1823 
1824  if (*mem_limit > hashentrysize)
1825  *ngroups_limit = *mem_limit / hashentrysize;
1826  else
1827  *ngroups_limit = 1;
1828 }
static int hash_choose_num_partitions(double input_groups, double hashentrysize, int used_bits, int *log2_npartittions)
Definition: nodeAgg.c:1973
#define HASHAGG_READ_BUFFER_SIZE
Definition: nodeAgg.c:306
#define HASHAGG_WRITE_BUFFER_SIZE
Definition: nodeAgg.c:307
size_t get_hash_memory_limit(void)
Definition: nodeHash.c:3401

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

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