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.

Referenced by llvm_compile_expr().

◆ FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE

#define FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE   0

Definition at line 244 of file nodeAgg.h.

Referenced by llvm_compile_expr().

◆ FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL

#define FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL   1

Definition at line 246 of file nodeAgg.h.

Referenced by llvm_compile_expr().

Typedef Documentation

◆ AggStatePerAggData

◆ AggStatePerGroupData

◆ AggStatePerHashData

◆ AggStatePerPhaseData

◆ AggStatePerTransData

Function Documentation

◆ ExecAggEstimate()

void ExecAggEstimate ( AggState node,
ParallelContext pcxt 
)

Definition at line 4759 of file nodeAgg.c.

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

4760 {
4761  Size size;
4762 
4763  /* don't need this if not instrumenting or no workers */
4764  if (!node->ss.ps.instrument || pcxt->nworkers == 0)
4765  return;
4766 
4767  size = mul_size(pcxt->nworkers, sizeof(AggregateInstrumentation));
4768  size = add_size(size, offsetof(SharedAggInfo, sinstrument));
4769  shm_toc_estimate_chunk(&pcxt->estimator, size);
4770  shm_toc_estimate_keys(&pcxt->estimator, 1);
4771 }
Instrumentation * instrument
Definition: execnodes.h:951
ScanState ss
Definition: execnodes.h:2163
shm_toc_estimator estimator
Definition: parallel.h:42
#define shm_toc_estimate_chunk(e, sz)
Definition: shm_toc.h:51
PlanState ps
Definition: execnodes.h:1330
Size mul_size(Size s1, Size s2)
Definition: shmem.c:519
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
size_t Size
Definition: c.h:540
#define shm_toc_estimate_keys(e, cnt)
Definition: shm_toc.h:53
#define offsetof(type, field)
Definition: c.h:727

◆ ExecAggInitializeDSM()

void ExecAggInitializeDSM ( AggState node,
ParallelContext pcxt 
)

Definition at line 4780 of file nodeAgg.c.

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

4781 {
4782  Size size;
4783 
4784  /* don't need this if not instrumenting or no workers */
4785  if (!node->ss.ps.instrument || pcxt->nworkers == 0)
4786  return;
4787 
4788  size = offsetof(SharedAggInfo, sinstrument)
4789  + pcxt->nworkers * sizeof(AggregateInstrumentation);
4790  node->shared_info = shm_toc_allocate(pcxt->toc, size);
4791  /* ensure any unfilled slots will contain zeroes */
4792  memset(node->shared_info, 0, size);
4793  node->shared_info->num_workers = pcxt->nworkers;
4794  shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id,
4795  node->shared_info);
4796 }
Instrumentation * instrument
Definition: execnodes.h:951
ScanState ss
Definition: execnodes.h:2163
int plan_node_id
Definition: plannodes.h:135
PlanState ps
Definition: execnodes.h:1330
struct AggregateInstrumentation AggregateInstrumentation
Plan * plan
Definition: execnodes.h:941
size_t Size
Definition: c.h:540
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition: shm_toc.c:88
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition: shm_toc.c:171
SharedAggInfo * shared_info
Definition: execnodes.h:2235
#define offsetof(type, field)
Definition: c.h:727
shm_toc * toc
Definition: parallel.h:45

◆ ExecAggInitializeWorker()

void ExecAggInitializeWorker ( AggState node,
ParallelWorkerContext pwcxt 
)

Definition at line 4805 of file nodeAgg.c.

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

Referenced by ExecParallelInitializeWorker().

4806 {
4807  node->shared_info =
4808  shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, true);
4809 }
ScanState ss
Definition: execnodes.h:2163
int plan_node_id
Definition: plannodes.h:135
PlanState ps
Definition: execnodes.h:1330
Plan * plan
Definition: execnodes.h:941
SharedAggInfo * shared_info
Definition: execnodes.h:2235
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
Definition: shm_toc.c:232

◆ ExecAggRetrieveInstrumentation()

void ExecAggRetrieveInstrumentation ( AggState node)

Definition at line 4818 of file nodeAgg.c.

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

Referenced by ExecParallelRetrieveInstrumentation().

4819 {
4820  Size size;
4821  SharedAggInfo *si;
4822 
4823  if (node->shared_info == NULL)
4824  return;
4825 
4826  size = offsetof(SharedAggInfo, sinstrument)
4828  si = palloc(size);
4829  memcpy(si, node->shared_info, size);
4830  node->shared_info = si;
4831 }
struct AggregateInstrumentation AggregateInstrumentation
size_t Size
Definition: c.h:540
void * palloc(Size size)
Definition: mcxt.c:950
SharedAggInfo * shared_info
Definition: execnodes.h:2235
#define offsetof(type, field)
Definition: c.h:727

◆ ExecEndAgg()

void ExecEndAgg ( AggState node)

Definition at line 4370 of file nodeAgg.c.

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

4371 {
4373  int transno;
4374  int numGroupingSets = Max(node->maxsets, 1);
4375  int setno;
4376 
4377  /*
4378  * When ending a parallel worker, copy the statistics gathered by the
4379  * worker back into shared memory so that it can be picked up by the main
4380  * process to report in EXPLAIN ANALYZE.
4381  */
4382  if (node->shared_info && IsParallelWorker())
4383  {
4385 
4386  Assert(ParallelWorkerNumber <= node->shared_info->num_workers);
4389  si->hash_disk_used = node->hash_disk_used;
4390  si->hash_mem_peak = node->hash_mem_peak;
4391  }
4392 
4393  /* Make sure we have closed any open tuplesorts */
4394 
4395  if (node->sort_in)
4396  tuplesort_end(node->sort_in);
4397  if (node->sort_out)
4398  tuplesort_end(node->sort_out);
4399 
4401 
4402  if (node->hash_metacxt != NULL)
4403  {
4405  node->hash_metacxt = NULL;
4406  }
4407 
4408  for (transno = 0; transno < node->numtrans; transno++)
4409  {
4410  AggStatePerTrans pertrans = &node->pertrans[transno];
4411 
4412  for (setno = 0; setno < numGroupingSets; setno++)
4413  {
4414  if (pertrans->sortstates[setno])
4415  tuplesort_end(pertrans->sortstates[setno]);
4416  }
4417  }
4418 
4419  /* And ensure any agg shutdown callbacks have been called */
4420  for (setno = 0; setno < numGroupingSets; setno++)
4421  ReScanExprContext(node->aggcontexts[setno]);
4422  if (node->hashcontext)
4424 
4425  /*
4426  * We don't actually free any ExprContexts here (see comment in
4427  * ExecFreeExprContext), just unlinking the output one from the plan node
4428  * suffices.
4429  */
4430  ExecFreeExprContext(&node->ss.ps);
4431 
4432  /* clean up tuple table */
4434 
4435  outerPlan = outerPlanState(node);
4436  ExecEndNode(outerPlan);
4437 }
static void hashagg_reset_spill_state(AggState *aggstate)
Definition: nodeAgg.c:3193
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:212
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:549
Tuplesortstate * sort_out
Definition: execnodes.h:2196
ScanState ss
Definition: execnodes.h:2163
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1333
AggregateInstrumentation sinstrument[FLEXIBLE_ARRAY_MEMBER]
Definition: execnodes.h:2139
AggStatePerTrans pertrans
Definition: execnodes.h:2173
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:650
int numtrans
Definition: execnodes.h:2166
PlanState ps
Definition: execnodes.h:1330
int maxsets
Definition: execnodes.h:2193
MemoryContext hash_metacxt
Definition: execnodes.h:2205
Tuplesortstate * sort_in
Definition: execnodes.h:2195
#define outerPlanState(node)
Definition: execnodes.h:1035
Tuplesortstate ** sortstates
Definition: nodeAgg.h:154
int ParallelWorkerNumber
Definition: parallel.c:112
#define IsParallelWorker()
Definition: parallel.h:61
int hash_batches_used
Definition: execnodes.h:2224
#define outerPlan(node)
Definition: plannodes.h:166
ExprContext * hashcontext
Definition: execnodes.h:2174
uint64 hash_disk_used
Definition: execnodes.h:2223
#define Max(x, y)
Definition: c.h:980
ExprContext ** aggcontexts
Definition: execnodes.h:2175
#define Assert(condition)
Definition: c.h:804
void ReScanExprContext(ExprContext *econtext)
Definition: execUtils.c:438
Size hash_mem_peak
Definition: execnodes.h:2220
SharedAggInfo * shared_info
Definition: execnodes.h:2235
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1464

◆ ExecInitAgg()

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

Definition at line 3245 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, Aggref::aggno, AggStatePerPhaseData::aggnode, AggStatePerHashData::aggnode, AggStatePerTransData::aggref, AggStatePerAggData::aggref, AggState::aggs, AggStatePerTransData::aggshared, Aggref::aggsplit, Agg::aggsplit, AggState::aggsplit, AggStatePerPhaseData::aggstrategy, Agg::aggstrategy, AggState::aggstrategy, Aggref::aggtransno, 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_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, 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(), 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().

3246 {
3247  AggState *aggstate;
3248  AggStatePerAgg peraggs;
3249  AggStatePerTrans pertransstates;
3250  AggStatePerGroup *pergroups;
3251  Plan *outerPlan;
3252  ExprContext *econtext;
3253  TupleDesc scanDesc;
3254  int max_aggno;
3255  int max_transno;
3256  int numaggrefs;
3257  int numaggs;
3258  int numtrans;
3259  int phase;
3260  int phaseidx;
3261  ListCell *l;
3262  Bitmapset *all_grouped_cols = NULL;
3263  int numGroupingSets = 1;
3264  int numPhases;
3265  int numHashes;
3266  int i = 0;
3267  int j = 0;
3268  bool use_hashing = (node->aggstrategy == AGG_HASHED ||
3269  node->aggstrategy == AGG_MIXED);
3270 
3271  /* check for unsupported flags */
3272  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
3273 
3274  /*
3275  * create state structure
3276  */
3277  aggstate = makeNode(AggState);
3278  aggstate->ss.ps.plan = (Plan *) node;
3279  aggstate->ss.ps.state = estate;
3280  aggstate->ss.ps.ExecProcNode = ExecAgg;
3281 
3282  aggstate->aggs = NIL;
3283  aggstate->numaggs = 0;
3284  aggstate->numtrans = 0;
3285  aggstate->aggstrategy = node->aggstrategy;
3286  aggstate->aggsplit = node->aggsplit;
3287  aggstate->maxsets = 0;
3288  aggstate->projected_set = -1;
3289  aggstate->current_set = 0;
3290  aggstate->peragg = NULL;
3291  aggstate->pertrans = NULL;
3292  aggstate->curperagg = NULL;
3293  aggstate->curpertrans = NULL;
3294  aggstate->input_done = false;
3295  aggstate->agg_done = false;
3296  aggstate->pergroups = NULL;
3297  aggstate->grp_firstTuple = NULL;
3298  aggstate->sort_in = NULL;
3299  aggstate->sort_out = NULL;
3300 
3301  /*
3302  * phases[0] always exists, but is dummy in sorted/plain mode
3303  */
3304  numPhases = (use_hashing ? 1 : 2);
3305  numHashes = (use_hashing ? 1 : 0);
3306 
3307  /*
3308  * Calculate the maximum number of grouping sets in any phase; this
3309  * determines the size of some allocations. Also calculate the number of
3310  * phases, since all hashed/mixed nodes contribute to only a single phase.
3311  */
3312  if (node->groupingSets)
3313  {
3314  numGroupingSets = list_length(node->groupingSets);
3315 
3316  foreach(l, node->chain)
3317  {
3318  Agg *agg = lfirst(l);
3319 
3320  numGroupingSets = Max(numGroupingSets,
3321  list_length(agg->groupingSets));
3322 
3323  /*
3324  * additional AGG_HASHED aggs become part of phase 0, but all
3325  * others add an extra phase.
3326  */
3327  if (agg->aggstrategy != AGG_HASHED)
3328  ++numPhases;
3329  else
3330  ++numHashes;
3331  }
3332  }
3333 
3334  aggstate->maxsets = numGroupingSets;
3335  aggstate->numphases = numPhases;
3336 
3337  aggstate->aggcontexts = (ExprContext **)
3338  palloc0(sizeof(ExprContext *) * numGroupingSets);
3339 
3340  /*
3341  * Create expression contexts. We need three or more, one for
3342  * per-input-tuple processing, one for per-output-tuple processing, one
3343  * for all the hashtables, and one for each grouping set. The per-tuple
3344  * memory context of the per-grouping-set ExprContexts (aggcontexts)
3345  * replaces the standalone memory context formerly used to hold transition
3346  * values. We cheat a little by using ExecAssignExprContext() to build
3347  * all of them.
3348  *
3349  * NOTE: the details of what is stored in aggcontexts and what is stored
3350  * in the regular per-query memory context are driven by a simple
3351  * decision: we want to reset the aggcontext at group boundaries (if not
3352  * hashing) and in ExecReScanAgg to recover no-longer-wanted space.
3353  */
3354  ExecAssignExprContext(estate, &aggstate->ss.ps);
3355  aggstate->tmpcontext = aggstate->ss.ps.ps_ExprContext;
3356 
3357  for (i = 0; i < numGroupingSets; ++i)
3358  {
3359  ExecAssignExprContext(estate, &aggstate->ss.ps);
3360  aggstate->aggcontexts[i] = aggstate->ss.ps.ps_ExprContext;
3361  }
3362 
3363  if (use_hashing)
3364  aggstate->hashcontext = CreateWorkExprContext(estate);
3365 
3366  ExecAssignExprContext(estate, &aggstate->ss.ps);
3367 
3368  /*
3369  * Initialize child nodes.
3370  *
3371  * If we are doing a hashed aggregation then the child plan does not need
3372  * to handle REWIND efficiently; see ExecReScanAgg.
3373  */
3374  if (node->aggstrategy == AGG_HASHED)
3375  eflags &= ~EXEC_FLAG_REWIND;
3376  outerPlan = outerPlan(node);
3377  outerPlanState(aggstate) = ExecInitNode(outerPlan, estate, eflags);
3378 
3379  /*
3380  * initialize source tuple type.
3381  */
3382  aggstate->ss.ps.outerops =
3384  &aggstate->ss.ps.outeropsfixed);
3385  aggstate->ss.ps.outeropsset = true;
3386 
3387  ExecCreateScanSlotFromOuterPlan(estate, &aggstate->ss,
3388  aggstate->ss.ps.outerops);
3389  scanDesc = aggstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
3390 
3391  /*
3392  * If there are more than two phases (including a potential dummy phase
3393  * 0), input will be resorted using tuplesort. Need a slot for that.
3394  */
3395  if (numPhases > 2)
3396  {
3397  aggstate->sort_slot = ExecInitExtraTupleSlot(estate, scanDesc,
3399 
3400  /*
3401  * The output of the tuplesort, and the output from the outer child
3402  * might not use the same type of slot. In most cases the child will
3403  * be a Sort, and thus return a TTSOpsMinimalTuple type slot - but the
3404  * input can also be presorted due an index, in which case it could be
3405  * a different type of slot.
3406  *
3407  * XXX: For efficiency it would be good to instead/additionally
3408  * generate expressions with corresponding settings of outerops* for
3409  * the individual phases - deforming is often a bottleneck for
3410  * aggregations with lots of rows per group. If there's multiple
3411  * sorts, we know that all but the first use TTSOpsMinimalTuple (via
3412  * the nodeAgg.c internal tuplesort).
3413  */
3414  if (aggstate->ss.ps.outeropsfixed &&
3415  aggstate->ss.ps.outerops != &TTSOpsMinimalTuple)
3416  aggstate->ss.ps.outeropsfixed = false;
3417  }
3418 
3419  /*
3420  * Initialize result type, slot and projection.
3421  */
3423  ExecAssignProjectionInfo(&aggstate->ss.ps, NULL);
3424 
3425  /*
3426  * initialize child expressions
3427  *
3428  * We expect the parser to have checked that no aggs contain other agg
3429  * calls in their arguments (and just to be sure, we verify it again while
3430  * initializing the plan node). This would make no sense under SQL
3431  * semantics, and it's forbidden by the spec. Because it is true, we
3432  * don't need to worry about evaluating the aggs in any particular order.
3433  *
3434  * Note: execExpr.c finds Aggrefs for us, and adds them to aggstate->aggs.
3435  * Aggrefs in the qual are found here; Aggrefs in the targetlist are found
3436  * during ExecAssignProjectionInfo, above.
3437  */
3438  aggstate->ss.ps.qual =
3439  ExecInitQual(node->plan.qual, (PlanState *) aggstate);
3440 
3441  /*
3442  * We should now have found all Aggrefs in the targetlist and quals.
3443  */
3444  numaggrefs = list_length(aggstate->aggs);
3445  max_aggno = -1;
3446  max_transno = -1;
3447  foreach(l, aggstate->aggs)
3448  {
3449  Aggref *aggref = (Aggref *) lfirst(l);
3450 
3451  max_aggno = Max(max_aggno, aggref->aggno);
3452  max_transno = Max(max_transno, aggref->aggtransno);
3453  }
3454  numaggs = max_aggno + 1;
3455  numtrans = max_transno + 1;
3456 
3457  /*
3458  * For each phase, prepare grouping set data and fmgr lookup data for
3459  * compare functions. Accumulate all_grouped_cols in passing.
3460  */
3461  aggstate->phases = palloc0(numPhases * sizeof(AggStatePerPhaseData));
3462 
3463  aggstate->num_hashes = numHashes;
3464  if (numHashes)
3465  {
3466  aggstate->perhash = palloc0(sizeof(AggStatePerHashData) * numHashes);
3467  aggstate->phases[0].numsets = 0;
3468  aggstate->phases[0].gset_lengths = palloc(numHashes * sizeof(int));
3469  aggstate->phases[0].grouped_cols = palloc(numHashes * sizeof(Bitmapset *));
3470  }
3471 
3472  phase = 0;
3473  for (phaseidx = 0; phaseidx <= list_length(node->chain); ++phaseidx)
3474  {
3475  Agg *aggnode;
3476  Sort *sortnode;
3477 
3478  if (phaseidx > 0)
3479  {
3480  aggnode = list_nth_node(Agg, node->chain, phaseidx - 1);
3481  sortnode = castNode(Sort, aggnode->plan.lefttree);
3482  }
3483  else
3484  {
3485  aggnode = node;
3486  sortnode = NULL;
3487  }
3488 
3489  Assert(phase <= 1 || sortnode);
3490 
3491  if (aggnode->aggstrategy == AGG_HASHED
3492  || aggnode->aggstrategy == AGG_MIXED)
3493  {
3494  AggStatePerPhase phasedata = &aggstate->phases[0];
3495  AggStatePerHash perhash;
3496  Bitmapset *cols = NULL;
3497 
3498  Assert(phase == 0);
3499  i = phasedata->numsets++;
3500  perhash = &aggstate->perhash[i];
3501 
3502  /* phase 0 always points to the "real" Agg in the hash case */
3503  phasedata->aggnode = node;
3504  phasedata->aggstrategy = node->aggstrategy;
3505 
3506  /* but the actual Agg node representing this hash is saved here */
3507  perhash->aggnode = aggnode;
3508 
3509  phasedata->gset_lengths[i] = perhash->numCols = aggnode->numCols;
3510 
3511  for (j = 0; j < aggnode->numCols; ++j)
3512  cols = bms_add_member(cols, aggnode->grpColIdx[j]);
3513 
3514  phasedata->grouped_cols[i] = cols;
3515 
3516  all_grouped_cols = bms_add_members(all_grouped_cols, cols);
3517  continue;
3518  }
3519  else
3520  {
3521  AggStatePerPhase phasedata = &aggstate->phases[++phase];
3522  int num_sets;
3523 
3524  phasedata->numsets = num_sets = list_length(aggnode->groupingSets);
3525 
3526  if (num_sets)
3527  {
3528  phasedata->gset_lengths = palloc(num_sets * sizeof(int));
3529  phasedata->grouped_cols = palloc(num_sets * sizeof(Bitmapset *));
3530 
3531  i = 0;
3532  foreach(l, aggnode->groupingSets)
3533  {
3534  int current_length = list_length(lfirst(l));
3535  Bitmapset *cols = NULL;
3536 
3537  /* planner forces this to be correct */
3538  for (j = 0; j < current_length; ++j)
3539  cols = bms_add_member(cols, aggnode->grpColIdx[j]);
3540 
3541  phasedata->grouped_cols[i] = cols;
3542  phasedata->gset_lengths[i] = current_length;
3543 
3544  ++i;
3545  }
3546 
3547  all_grouped_cols = bms_add_members(all_grouped_cols,
3548  phasedata->grouped_cols[0]);
3549  }
3550  else
3551  {
3552  Assert(phaseidx == 0);
3553 
3554  phasedata->gset_lengths = NULL;
3555  phasedata->grouped_cols = NULL;
3556  }
3557 
3558  /*
3559  * If we are grouping, precompute fmgr lookup data for inner loop.
3560  */
3561  if (aggnode->aggstrategy == AGG_SORTED)
3562  {
3563  int i = 0;
3564 
3565  Assert(aggnode->numCols > 0);
3566 
3567  /*
3568  * Build a separate function for each subset of columns that
3569  * need to be compared.
3570  */
3571  phasedata->eqfunctions =
3572  (ExprState **) palloc0(aggnode->numCols * sizeof(ExprState *));
3573 
3574  /* for each grouping set */
3575  for (i = 0; i < phasedata->numsets; i++)
3576  {
3577  int length = phasedata->gset_lengths[i];
3578 
3579  if (phasedata->eqfunctions[length - 1] != NULL)
3580  continue;
3581 
3582  phasedata->eqfunctions[length - 1] =
3583  execTuplesMatchPrepare(scanDesc,
3584  length,
3585  aggnode->grpColIdx,
3586  aggnode->grpOperators,
3587  aggnode->grpCollations,
3588  (PlanState *) aggstate);
3589  }
3590 
3591  /* and for all grouped columns, unless already computed */
3592  if (phasedata->eqfunctions[aggnode->numCols - 1] == NULL)
3593  {
3594  phasedata->eqfunctions[aggnode->numCols - 1] =
3595  execTuplesMatchPrepare(scanDesc,
3596  aggnode->numCols,
3597  aggnode->grpColIdx,
3598  aggnode->grpOperators,
3599  aggnode->grpCollations,
3600  (PlanState *) aggstate);
3601  }
3602  }
3603 
3604  phasedata->aggnode = aggnode;
3605  phasedata->aggstrategy = aggnode->aggstrategy;
3606  phasedata->sortnode = sortnode;
3607  }
3608  }
3609 
3610  /*
3611  * Convert all_grouped_cols to a descending-order list.
3612  */
3613  i = -1;
3614  while ((i = bms_next_member(all_grouped_cols, i)) >= 0)
3615  aggstate->all_grouped_cols = lcons_int(i, aggstate->all_grouped_cols);
3616 
3617  /*
3618  * Set up aggregate-result storage in the output expr context, and also
3619  * allocate my private per-agg working storage
3620  */
3621  econtext = aggstate->ss.ps.ps_ExprContext;
3622  econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs);
3623  econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs);
3624 
3625  peraggs = (AggStatePerAgg) palloc0(sizeof(AggStatePerAggData) * numaggs);
3626  pertransstates = (AggStatePerTrans) palloc0(sizeof(AggStatePerTransData) * numtrans);
3627 
3628  aggstate->peragg = peraggs;
3629  aggstate->pertrans = pertransstates;
3630 
3631 
3632  aggstate->all_pergroups =
3634  * (numGroupingSets + numHashes));
3635  pergroups = aggstate->all_pergroups;
3636 
3637  if (node->aggstrategy != AGG_HASHED)
3638  {
3639  for (i = 0; i < numGroupingSets; i++)
3640  {
3641  pergroups[i] = (AggStatePerGroup) palloc0(sizeof(AggStatePerGroupData)
3642  * numaggs);
3643  }
3644 
3645  aggstate->pergroups = pergroups;
3646  pergroups += numGroupingSets;
3647  }
3648 
3649  /*
3650  * Hashing can only appear in the initial phase.
3651  */
3652  if (use_hashing)
3653  {
3654  Plan *outerplan = outerPlan(node);
3655  uint64 totalGroups = 0;
3656  int i;
3657 
3658  aggstate->hash_metacxt = AllocSetContextCreate(aggstate->ss.ps.state->es_query_cxt,
3659  "HashAgg meta context",
3661  aggstate->hash_spill_rslot = ExecInitExtraTupleSlot(estate, scanDesc,
3663  aggstate->hash_spill_wslot = ExecInitExtraTupleSlot(estate, scanDesc,
3664  &TTSOpsVirtual);
3665 
3666  /* this is an array of pointers, not structures */
3667  aggstate->hash_pergroup = pergroups;
3668 
3669  aggstate->hashentrysize = hash_agg_entry_size(aggstate->numtrans,
3670  outerplan->plan_width,
3671  node->transitionSpace);
3672 
3673  /*
3674  * Consider all of the grouping sets together when setting the limits
3675  * and estimating the number of partitions. This can be inaccurate
3676  * when there is more than one grouping set, but should still be
3677  * reasonable.
3678  */
3679  for (i = 0; i < aggstate->num_hashes; i++)
3680  totalGroups += aggstate->perhash[i].aggnode->numGroups;
3681 
3682  hash_agg_set_limits(aggstate->hashentrysize, totalGroups, 0,
3683  &aggstate->hash_mem_limit,
3684  &aggstate->hash_ngroups_limit,
3685  &aggstate->hash_planned_partitions);
3686  find_hash_columns(aggstate);
3687 
3688  /* Skip massive memory allocation if we are just doing EXPLAIN */
3689  if (!(eflags & EXEC_FLAG_EXPLAIN_ONLY))
3690  build_hash_tables(aggstate);
3691 
3692  aggstate->table_filled = false;
3693 
3694  /* Initialize this to 1, meaning nothing spilled, yet */
3695  aggstate->hash_batches_used = 1;
3696  }
3697 
3698  /*
3699  * Initialize current phase-dependent values to initial phase. The initial
3700  * phase is 1 (first sort pass) for all strategies that use sorting (if
3701  * hashing is being done too, then phase 0 is processed last); but if only
3702  * hashing is being done, then phase 0 is all there is.
3703  */
3704  if (node->aggstrategy == AGG_HASHED)
3705  {
3706  aggstate->current_phase = 0;
3707  initialize_phase(aggstate, 0);
3708  select_current_set(aggstate, 0, true);
3709  }
3710  else
3711  {
3712  aggstate->current_phase = 1;
3713  initialize_phase(aggstate, 1);
3714  select_current_set(aggstate, 0, false);
3715  }
3716 
3717  /*
3718  * Perform lookups of aggregate function info, and initialize the
3719  * unchanging fields of the per-agg and per-trans data.
3720  */
3721  foreach(l, aggstate->aggs)
3722  {
3723  Aggref *aggref = lfirst(l);
3724  AggStatePerAgg peragg;
3725  AggStatePerTrans pertrans;
3726  Oid inputTypes[FUNC_MAX_ARGS];
3727  int numArguments;
3728  int numDirectArgs;
3729  HeapTuple aggTuple;
3730  Form_pg_aggregate aggform;
3731  AclResult aclresult;
3732  Oid finalfn_oid;
3733  Oid serialfn_oid,
3734  deserialfn_oid;
3735  Oid aggOwner;
3736  Expr *finalfnexpr;
3737  Oid aggtranstype;
3738 
3739  /* Planner should have assigned aggregate to correct level */
3740  Assert(aggref->agglevelsup == 0);
3741  /* ... and the split mode should match */
3742  Assert(aggref->aggsplit == aggstate->aggsplit);
3743 
3744  peragg = &peraggs[aggref->aggno];
3745 
3746  /* Check if we initialized the state for this aggregate already. */
3747  if (peragg->aggref != NULL)
3748  continue;
3749 
3750  peragg->aggref = aggref;
3751  peragg->transno = aggref->aggtransno;
3752 
3753  /* Fetch the pg_aggregate row */
3754  aggTuple = SearchSysCache1(AGGFNOID,
3755  ObjectIdGetDatum(aggref->aggfnoid));
3756  if (!HeapTupleIsValid(aggTuple))
3757  elog(ERROR, "cache lookup failed for aggregate %u",
3758  aggref->aggfnoid);
3759  aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);
3760 
3761  /* Check permission to call aggregate function */
3762  aclresult = pg_proc_aclcheck(aggref->aggfnoid, GetUserId(),
3763  ACL_EXECUTE);
3764  if (aclresult != ACLCHECK_OK)
3765  aclcheck_error(aclresult, OBJECT_AGGREGATE,
3766  get_func_name(aggref->aggfnoid));
3768 
3769  /* planner recorded transition state type in the Aggref itself */
3770  aggtranstype = aggref->aggtranstype;
3771  Assert(OidIsValid(aggtranstype));
3772 
3773  /* Final function only required if we're finalizing the aggregates */
3774  if (DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit))
3775  peragg->finalfn_oid = finalfn_oid = InvalidOid;
3776  else
3777  peragg->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
3778 
3779  serialfn_oid = InvalidOid;
3780  deserialfn_oid = InvalidOid;
3781 
3782  /*
3783  * Check if serialization/deserialization is required. We only do it
3784  * for aggregates that have transtype INTERNAL.
3785  */
3786  if (aggtranstype == INTERNALOID)
3787  {
3788  /*
3789  * The planner should only have generated a serialize agg node if
3790  * every aggregate with an INTERNAL state has a serialization
3791  * function. Verify that.
3792  */
3793  if (DO_AGGSPLIT_SERIALIZE(aggstate->aggsplit))
3794  {
3795  /* serialization only valid when not running finalfn */
3797 
3798  if (!OidIsValid(aggform->aggserialfn))
3799  elog(ERROR, "serialfunc not provided for serialization aggregation");
3800  serialfn_oid = aggform->aggserialfn;
3801  }
3802 
3803  /* Likewise for deserialization functions */
3804  if (DO_AGGSPLIT_DESERIALIZE(aggstate->aggsplit))
3805  {
3806  /* deserialization only valid when combining states */
3807  Assert(DO_AGGSPLIT_COMBINE(aggstate->aggsplit));
3808 
3809  if (!OidIsValid(aggform->aggdeserialfn))
3810  elog(ERROR, "deserialfunc not provided for deserialization aggregation");
3811  deserialfn_oid = aggform->aggdeserialfn;
3812  }
3813  }
3814 
3815  /* Check that aggregate owner has permission to call component fns */
3816  {
3817  HeapTuple procTuple;
3818 
3819  procTuple = SearchSysCache1(PROCOID,
3820  ObjectIdGetDatum(aggref->aggfnoid));
3821  if (!HeapTupleIsValid(procTuple))
3822  elog(ERROR, "cache lookup failed for function %u",
3823  aggref->aggfnoid);
3824  aggOwner = ((Form_pg_proc) GETSTRUCT(procTuple))->proowner;
3825  ReleaseSysCache(procTuple);
3826 
3827  if (OidIsValid(finalfn_oid))
3828  {
3829  aclresult = pg_proc_aclcheck(finalfn_oid, aggOwner,
3830  ACL_EXECUTE);
3831  if (aclresult != ACLCHECK_OK)
3832  aclcheck_error(aclresult, OBJECT_FUNCTION,
3833  get_func_name(finalfn_oid));
3834  InvokeFunctionExecuteHook(finalfn_oid);
3835  }
3836  if (OidIsValid(serialfn_oid))
3837  {
3838  aclresult = pg_proc_aclcheck(serialfn_oid, aggOwner,
3839  ACL_EXECUTE);
3840  if (aclresult != ACLCHECK_OK)
3841  aclcheck_error(aclresult, OBJECT_FUNCTION,
3842  get_func_name(serialfn_oid));
3843  InvokeFunctionExecuteHook(serialfn_oid);
3844  }
3845  if (OidIsValid(deserialfn_oid))
3846  {
3847  aclresult = pg_proc_aclcheck(deserialfn_oid, aggOwner,
3848  ACL_EXECUTE);
3849  if (aclresult != ACLCHECK_OK)
3850  aclcheck_error(aclresult, OBJECT_FUNCTION,
3851  get_func_name(deserialfn_oid));
3852  InvokeFunctionExecuteHook(deserialfn_oid);
3853  }
3854  }
3855 
3856  /*
3857  * Get actual datatypes of the (nominal) aggregate inputs. These
3858  * could be different from the agg's declared input types, when the
3859  * agg accepts ANY or a polymorphic type.
3860  */
3861  numArguments = get_aggregate_argtypes(aggref, inputTypes);
3862 
3863  /* Count the "direct" arguments, if any */
3864  numDirectArgs = list_length(aggref->aggdirectargs);
3865 
3866  /* Detect how many arguments to pass to the finalfn */
3867  if (aggform->aggfinalextra)
3868  peragg->numFinalArgs = numArguments + 1;
3869  else
3870  peragg->numFinalArgs = numDirectArgs + 1;
3871 
3872  /* Initialize any direct-argument expressions */
3873  peragg->aggdirectargs = ExecInitExprList(aggref->aggdirectargs,
3874  (PlanState *) aggstate);
3875 
3876  /*
3877  * build expression trees using actual argument & result types for the
3878  * finalfn, if it exists and is required.
3879  */
3880  if (OidIsValid(finalfn_oid))
3881  {
3882  build_aggregate_finalfn_expr(inputTypes,
3883  peragg->numFinalArgs,
3884  aggtranstype,
3885  aggref->aggtype,
3886  aggref->inputcollid,
3887  finalfn_oid,
3888  &finalfnexpr);
3889  fmgr_info(finalfn_oid, &peragg->finalfn);
3890  fmgr_info_set_expr((Node *) finalfnexpr, &peragg->finalfn);
3891  }
3892 
3893  /* get info about the output value's datatype */
3894  get_typlenbyval(aggref->aggtype,
3895  &peragg->resulttypeLen,
3896  &peragg->resulttypeByVal);
3897 
3898  /*
3899  * Build working state for invoking the transition function, if we
3900  * haven't done it already.
3901  */
3902  pertrans = &pertransstates[aggref->aggtransno];
3903  if (pertrans->aggref == NULL)
3904  {
3905  Datum textInitVal;
3906  Datum initValue;
3907  bool initValueIsNull;
3908  Oid transfn_oid;
3909 
3910  /*
3911  * If this aggregation is performing state combines, then instead
3912  * of using the transition function, we'll use the combine
3913  * function
3914  */
3915  if (DO_AGGSPLIT_COMBINE(aggstate->aggsplit))
3916  {
3917  transfn_oid = aggform->aggcombinefn;
3918 
3919  /* If not set then the planner messed up */
3920  if (!OidIsValid(transfn_oid))
3921  elog(ERROR, "combinefn not set for aggregate function");
3922  }
3923  else
3924  transfn_oid = aggform->aggtransfn;
3925 
3926  aclresult = pg_proc_aclcheck(transfn_oid, aggOwner,
3927  ACL_EXECUTE);
3928  if (aclresult != ACLCHECK_OK)
3929  aclcheck_error(aclresult, OBJECT_FUNCTION,
3930  get_func_name(transfn_oid));
3931  InvokeFunctionExecuteHook(transfn_oid);
3932 
3933  /*
3934  * initval is potentially null, so don't try to access it as a
3935  * struct field. Must do it the hard way with SysCacheGetAttr.
3936  */
3937  textInitVal = SysCacheGetAttr(AGGFNOID, aggTuple,
3938  Anum_pg_aggregate_agginitval,
3939  &initValueIsNull);
3940  if (initValueIsNull)
3941  initValue = (Datum) 0;
3942  else
3943  initValue = GetAggInitVal(textInitVal, aggtranstype);
3944 
3945  build_pertrans_for_aggref(pertrans, aggstate, estate,
3946  aggref, transfn_oid, aggtranstype,
3947  serialfn_oid, deserialfn_oid,
3948  initValue, initValueIsNull,
3949  inputTypes, numArguments);
3950  }
3951  else
3952  pertrans->aggshared = true;
3953  ReleaseSysCache(aggTuple);
3954  }
3955 
3956  /*
3957  * Update aggstate->numaggs to be the number of unique aggregates found.
3958  * Also set numstates to the number of unique transition states found.
3959  */
3960  aggstate->numaggs = numaggs;
3961  aggstate->numtrans = numtrans;
3962 
3963  /*
3964  * Last, check whether any more aggregates got added onto the node while
3965  * we processed the expressions for the aggregate arguments (including not
3966  * only the regular arguments and FILTER expressions handled immediately
3967  * above, but any direct arguments we might've handled earlier). If so,
3968  * we have nested aggregate functions, which is semantically nonsensical,
3969  * so complain. (This should have been caught by the parser, so we don't
3970  * need to work hard on a helpful error message; but we defend against it
3971  * here anyway, just to be sure.)
3972  */
3973  if (numaggrefs != list_length(aggstate->aggs))
3974  ereport(ERROR,
3975  (errcode(ERRCODE_GROUPING_ERROR),
3976  errmsg("aggregate function calls cannot be nested")));
3977 
3978  /*
3979  * Build expressions doing all the transition work at once. We build a
3980  * different one for each phase, as the number of transition function
3981  * invocation can differ between phases. Note this'll work both for
3982  * transition and combination functions (although there'll only be one
3983  * phase in the latter case).
3984  */
3985  for (phaseidx = 0; phaseidx < aggstate->numphases; phaseidx++)
3986  {
3987  AggStatePerPhase phase = &aggstate->phases[phaseidx];
3988  bool dohash = false;
3989  bool dosort = false;
3990 
3991  /* phase 0 doesn't necessarily exist */
3992  if (!phase->aggnode)
3993  continue;
3994 
3995  if (aggstate->aggstrategy == AGG_MIXED && phaseidx == 1)
3996  {
3997  /*
3998  * Phase one, and only phase one, in a mixed agg performs both
3999  * sorting and aggregation.
4000  */
4001  dohash = true;
4002  dosort = true;
4003  }
4004  else if (aggstate->aggstrategy == AGG_MIXED && phaseidx == 0)
4005  {
4006  /*
4007  * No need to compute a transition function for an AGG_MIXED phase
4008  * 0 - the contents of the hashtables will have been computed
4009  * during phase 1.
4010  */
4011  continue;
4012  }
4013  else if (phase->aggstrategy == AGG_PLAIN ||
4014  phase->aggstrategy == AGG_SORTED)
4015  {
4016  dohash = false;
4017  dosort = true;
4018  }
4019  else if (phase->aggstrategy == AGG_HASHED)
4020  {
4021  dohash = true;
4022  dosort = false;
4023  }
4024  else
4025  Assert(false);
4026 
4027  phase->evaltrans = ExecBuildAggTrans(aggstate, phase, dosort, dohash,
4028  false);
4029 
4030  /* cache compiled expression for outer slot without NULL check */
4031  phase->evaltrans_cache[0][0] = phase->evaltrans;
4032  }
4033 
4034  return aggstate;
4035 }
struct AggStatePerTransData * AggStatePerTrans
Definition: execnodes.h:2156
ExprState ** eqfunctions
Definition: nodeAgg.h:278
AggStatePerGroup * hash_pergroup
Definition: execnodes.h:2227
#define NIL
Definition: pg_list.h:65
struct AggStatePerGroupData * AggStatePerGroup
Definition: execnodes.h:2157
static void select_current_set(AggState *aggstate, int setno, bool is_hash)
Definition: nodeAgg.c:475
int numCols
Definition: plannodes.h:834
List * qual
Definition: plannodes.h:137
AggStatePerPhase phases
Definition: execnodes.h:2194
double hashentrysize
Definition: execnodes.h:2219
#define AllocSetContextCreate
Definition: memutils.h:170
Datum * ecxt_aggvalues
Definition: execnodes.h:244
uint64 hash_ngroups_limit
Definition: execnodes.h:2216
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:835
uint64 transitionSpace
Definition: plannodes.h:839
int aggtransno
Definition: primnodes.h:336
const TupleTableSlotOps * ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
Definition: execUtils.c:499
List * lcons_int(int datum, List *list)
Definition: list.c:486
int numaggs
Definition: execnodes.h:2165
Oid GetUserId(void)
Definition: miscinit.c:478
bool agg_done
Definition: execnodes.h:2183
#define castNode(_type_, nodeptr)
Definition: nodes.h:602
Oid * grpCollations
Definition: plannodes.h:837
TupleTableSlot * sort_slot
Definition: execnodes.h:2197
List * all_grouped_cols
Definition: execnodes.h:2188
Tuplesortstate * sort_out
Definition: execnodes.h:2196
ScanState ss
Definition: execnodes.h:2163
ExprContext * ps_ExprContext
Definition: execnodes.h:980
ExprState * evaltrans
Definition: nodeAgg.h:283
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:321
int current_phase
Definition: execnodes.h:2171
Definition: nodes.h:533
AggSplit aggsplit
Definition: execnodes.h:2168
static TupleTableSlot * ExecAgg(PlanState *pstate)
Definition: nodeAgg.c:2153
int errcode(int sqlerrcode)
Definition: elog.c:694
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1333
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:2044
TupleTableSlot * hash_spill_rslot
Definition: execnodes.h:2209
AggStatePerTrans pertrans
Definition: execnodes.h:2173
EState * state
Definition: execnodes.h:943
int projected_set
Definition: execnodes.h:2184
unsigned int Oid
Definition: postgres_ext.h:31
HeapTuple grp_firstTuple
Definition: execnodes.h:2201
Aggref * aggref
Definition: nodeAgg.h:187
int current_set
Definition: execnodes.h:2186
#define OidIsValid(objectId)
Definition: c.h:710
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:795
int numtrans
Definition: execnodes.h:2166
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:209
ExprContext * tmpcontext
Definition: execnodes.h:2176
#define FUNC_MAX_ARGS
Aggref * aggref
Definition: nodeAgg.h:44
Bitmapset ** grouped_cols
Definition: nodeAgg.h:277
PlanState ps
Definition: execnodes.h:1330
int maxsets
Definition: execnodes.h:2193
Size hash_agg_entry_size(int numTrans, Size tupleWidth, Size transitionSpace)
Definition: nodeAgg.c:1693
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3313
#define DO_AGGSPLIT_SERIALIZE(as)
Definition: nodes.h:797
MemoryContext es_query_cxt
Definition: execnodes.h:572
AggStrategy aggstrategy
Definition: plannodes.h:832
bool table_filled
Definition: execnodes.h:2203
AggStrategy aggstrategy
Definition: execnodes.h:2167
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:45
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1579
MemoryContext hash_metacxt
Definition: execnodes.h:2205
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:126
static void find_hash_columns(AggState *aggstate)
Definition: nodeAgg.c:1564
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
Tuplesortstate * sort_in
Definition: execnodes.h:2195
#define EXEC_FLAG_BACKWARD
Definition: executor.h:58
#define outerPlanState(node)
Definition: execnodes.h:1035
#define list_nth_node(type, list, n)
Definition: pg_list.h:306
static int initValue(long lng_val)
Definition: informix.c:677
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:535
#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:333
int hash_planned_partitions
Definition: execnodes.h:2217
List * aggdirectargs
Definition: primnodes.h:324
static Datum GetAggInitVal(Datum textInitVal, Oid transtype)
Definition: nodeAgg.c:4354
AggStatePerAgg curperagg
Definition: execnodes.h:2179
AggStatePerHash perhash
Definition: execnodes.h:2226
bool outeropsset
Definition: execnodes.h:1022
AggStrategy aggstrategy
Definition: nodeAgg.h:274
ExprState * evaltrans_cache[2][2]
Definition: nodeAgg.h:291
#define EXEC_FLAG_REWIND
Definition: executor.h:57
int hash_batches_used
Definition: execnodes.h:2224
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:191
#define outerPlan(node)
Definition: plannodes.h:166
int num_hashes
Definition: execnodes.h:2204
Plan plan
Definition: plannodes.h:831
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
bool input_done
Definition: execnodes.h:2182
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:124
ExprContext * hashcontext
Definition: execnodes.h:2174
bool * ecxt_aggnulls
Definition: execnodes.h:246
void * palloc0(Size size)
Definition: mcxt.c:981
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:947
AclResult
Definition: acl.h:177
uintptr_t Datum
Definition: postgres.h:367
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
List * groupingSets
Definition: plannodes.h:842
int16 resulttypeLen
Definition: nodeAgg.h:216
static void initialize_phase(AggState *aggstate, int newphase)
Definition: nodeAgg.c:497
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:133
Plan * plan
Definition: execnodes.h:941
#define InvalidOid
Definition: postgres_ext.h:36
Oid aggfnoid
Definition: primnodes.h:318
#define ereport(elevel,...)
Definition: elog.h:155
int aggno
Definition: primnodes.h:335
#define Max(x, y)
Definition: c.h:980
ExprContext ** aggcontexts
Definition: execnodes.h:2175
#define makeNode(_type_)
Definition: nodes.h:581
int plan_width
Definition: plannodes.h:124
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
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:833
struct AggStatePerAggData * AggStatePerAgg
Definition: execnodes.h:2155
FormData_pg_aggregate * Form_pg_aggregate
Definition: pg_aggregate.h:109
AggSplit aggsplit
Definition: primnodes.h:334
AggStatePerGroup * pergroups
Definition: execnodes.h:2199
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:480
static int list_length(const List *l)
Definition: pg_list.h:149
long numGroups
Definition: plannodes.h:838
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:796
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:2198
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1769
bool outeropsfixed
Definition: execnodes.h:1018
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
#define DO_AGGSPLIT_DESERIALIZE(as)
Definition: nodes.h:798
Size hash_mem_limit
Definition: execnodes.h:2215
struct Plan * lefttree
Definition: plannodes.h:138
int numphases
Definition: execnodes.h:2170
ExprState * qual
Definition: execnodes.h:962
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:1797
Oid * grpOperators
Definition: plannodes.h:836
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:905
List * chain
Definition: plannodes.h:843
AggStatePerAgg peragg
Definition: execnodes.h:2172
#define ACL_EXECUTE
Definition: parsenodes.h:81
#define elog(elevel,...)
Definition: elog.h:227
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4606
int i
List * aggdirectargs
Definition: nodeAgg.h:210
Oid aggtranstype
Definition: primnodes.h:322
AggStatePerTrans curpertrans
Definition: execnodes.h:2181
Oid aggtype
Definition: primnodes.h:319
bool resulttypeByVal
Definition: nodeAgg.h:217
Definition: plannodes.h:829
ExprContext * CreateWorkExprContext(EState *estate)
Definition: execUtils.c:316
List * aggs
Definition: execnodes.h:2164
void ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate, const TupleTableSlotOps *tts_ops)
Definition: execUtils.c:682
int get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
Definition: parse_agg.c:1826
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:4046
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:140
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:56
const TupleTableSlotOps TTSOpsMinimalTuple
Definition: execTuples.c:85
FmgrInfo finalfn
Definition: nodeAgg.h:199
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:793
TupleTableSlot * hash_spill_wslot
Definition: execnodes.h:2210
static void build_hash_tables(AggState *aggstate)
Definition: nodeAgg.c:1469
const TupleTableSlotOps * outerops
Definition: execnodes.h:1014
ExprState * ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase, bool doSort, bool doHash, bool nullcheck)
Definition: execExpr.c:2941
AggStatePerGroup * all_pergroups
Definition: execnodes.h:2232

◆ ExecReScanAgg()

void ExecReScanAgg ( AggState node)

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

4441 {
4442  ExprContext *econtext = node->ss.ps.ps_ExprContext;
4444  Agg *aggnode = (Agg *) node->ss.ps.plan;
4445  int transno;
4446  int numGroupingSets = Max(node->maxsets, 1);
4447  int setno;
4448 
4449  node->agg_done = false;
4450 
4451  if (node->aggstrategy == AGG_HASHED)
4452  {
4453  /*
4454  * In the hashed case, if we haven't yet built the hash table then we
4455  * can just return; nothing done yet, so nothing to undo. If subnode's
4456  * chgParam is not NULL then it will be re-scanned by ExecProcNode,
4457  * else no reason to re-scan it at all.
4458  */
4459  if (!node->table_filled)
4460  return;
4461 
4462  /*
4463  * If we do have the hash table, and it never spilled, and the subplan
4464  * does not have any parameter changes, and none of our own parameter
4465  * changes affect input expressions of the aggregated functions, then
4466  * we can just rescan the existing hash table; no need to build it
4467  * again.
4468  */
4469  if (outerPlan->chgParam == NULL && !node->hash_ever_spilled &&
4470  !bms_overlap(node->ss.ps.chgParam, aggnode->aggParams))
4471  {
4473  &node->perhash[0].hashiter);
4474  select_current_set(node, 0, true);
4475  return;
4476  }
4477  }
4478 
4479  /* Make sure we have closed any open tuplesorts */
4480  for (transno = 0; transno < node->numtrans; transno++)
4481  {
4482  for (setno = 0; setno < numGroupingSets; setno++)
4483  {
4484  AggStatePerTrans pertrans = &node->pertrans[transno];
4485 
4486  if (pertrans->sortstates[setno])
4487  {
4488  tuplesort_end(pertrans->sortstates[setno]);
4489  pertrans->sortstates[setno] = NULL;
4490  }
4491  }
4492  }
4493 
4494  /*
4495  * We don't need to ReScanExprContext the output tuple context here;
4496  * ExecReScan already did it. But we do need to reset our per-grouping-set
4497  * contexts, which may have transvalues stored in them. (We use rescan
4498  * rather than just reset because transfns may have registered callbacks
4499  * that need to be run now.) For the AGG_HASHED case, see below.
4500  */
4501 
4502  for (setno = 0; setno < numGroupingSets; setno++)
4503  {
4504  ReScanExprContext(node->aggcontexts[setno]);
4505  }
4506 
4507  /* Release first tuple of group, if we have made a copy */
4508  if (node->grp_firstTuple != NULL)
4509  {
4511  node->grp_firstTuple = NULL;
4512  }
4514 
4515  /* Forget current agg values */
4516  MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numaggs);
4517  MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numaggs);
4518 
4519  /*
4520  * With AGG_HASHED/MIXED, the hash table is allocated in a sub-context of
4521  * the hashcontext. This used to be an issue, but now, resetting a context
4522  * automatically deletes sub-contexts too.
4523  */
4524  if (node->aggstrategy == AGG_HASHED || node->aggstrategy == AGG_MIXED)
4525  {
4527 
4528  node->hash_ever_spilled = false;
4529  node->hash_spill_mode = false;
4530  node->hash_ngroups_current = 0;
4531 
4533  /* Rebuild an empty hash table */
4534  build_hash_tables(node);
4535  node->table_filled = false;
4536  /* iterator will be reset when the table is filled */
4537 
4538  hashagg_recompile_expressions(node, false, false);
4539  }
4540 
4541  if (node->aggstrategy != AGG_HASHED)
4542  {
4543  /*
4544  * Reset the per-group state (in particular, mark transvalues null)
4545  */
4546  for (setno = 0; setno < numGroupingSets; setno++)
4547  {
4548  MemSet(node->pergroups[setno], 0,
4549  sizeof(AggStatePerGroupData) * node->numaggs);
4550  }
4551 
4552  /* reset to phase 1 */
4553  initialize_phase(node, 1);
4554 
4555  node->input_done = false;
4556  node->projected_set = -1;
4557  }
4558 
4559  if (outerPlan->chgParam == NULL)
4560  ExecReScan(outerPlan);
4561 }
static void hashagg_reset_spill_state(AggState *aggstate)
Definition: nodeAgg.c:3193
static void select_current_set(AggState *aggstate, int setno, bool is_hash)
Definition: nodeAgg.c:475
Datum * ecxt_aggvalues
Definition: execnodes.h:244
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
int numaggs
Definition: execnodes.h:2165
bool agg_done
Definition: execnodes.h:2183
ScanState ss
Definition: execnodes.h:2163
ExprContext * ps_ExprContext
Definition: execnodes.h:980
void ExecReScan(PlanState *node)
Definition: execAmi.c:77
#define MemSet(start, val, len)
Definition: c.h:1008
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1333
AggStatePerTrans pertrans
Definition: execnodes.h:2173
int projected_set
Definition: execnodes.h:2184
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
HeapTuple grp_firstTuple
Definition: execnodes.h:2201
int numtrans
Definition: execnodes.h:2166
bool hash_spill_mode
Definition: execnodes.h:2213
PlanState ps
Definition: execnodes.h:1330
int maxsets
Definition: execnodes.h:2193
bool table_filled
Definition: execnodes.h:2203
AggStrategy aggstrategy
Definition: execnodes.h:2167
#define outerPlanState(node)
Definition: execnodes.h:1035
Tuplesortstate ** sortstates
Definition: nodeAgg.h:154
Bitmapset * aggParams
Definition: plannodes.h:840
AggStatePerHash perhash
Definition: execnodes.h:2226
Bitmapset * chgParam
Definition: execnodes.h:973
#define outerPlan(node)
Definition: plannodes.h:166
TupleHashIterator hashiter
Definition: nodeAgg.h:304
bool input_done
Definition: execnodes.h:2182
ExprContext * hashcontext
Definition: execnodes.h:2174
bool * ecxt_aggnulls
Definition: execnodes.h:246
uintptr_t Datum
Definition: postgres.h:367
static void initialize_phase(AggState *aggstate, int newphase)
Definition: nodeAgg.c:497
Plan * plan
Definition: execnodes.h:941
#define ResetTupleHashIterator(htable, iter)
Definition: execnodes.h:744
static void hashagg_recompile_expressions(AggState *aggstate, bool minslot, bool nullcheck)
Definition: nodeAgg.c:1740
#define Max(x, y)
Definition: c.h:980
ExprContext ** aggcontexts
Definition: execnodes.h:2175
bool hash_ever_spilled
Definition: execnodes.h:2212
AggStatePerGroup * pergroups
Definition: execnodes.h:2199
void ReScanExprContext(ExprContext *econtext)
Definition: execUtils.c:438
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:494
uint64 hash_ngroups_current
Definition: execnodes.h:2221
Definition: plannodes.h:829
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1464
TupleHashTable hashtable
Definition: nodeAgg.h:303
static void build_hash_tables(AggState *aggstate)
Definition: nodeAgg.c:1469

◆ hash_agg_entry_size()

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

Definition at line 1693 of file nodeAgg.c.

References CHUNKHDRSZ, MAXALIGN, and SizeofMinimalTupleHeader.

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

1694 {
1695  Size tupleChunkSize;
1696  Size pergroupChunkSize;
1697  Size transitionChunkSize;
1698  Size tupleSize = (MAXALIGN(SizeofMinimalTupleHeader) +
1699  tupleWidth);
1700  Size pergroupSize = numTrans * sizeof(AggStatePerGroupData);
1701 
1702  tupleChunkSize = CHUNKHDRSZ + tupleSize;
1703 
1704  if (pergroupSize > 0)
1705  pergroupChunkSize = CHUNKHDRSZ + pergroupSize;
1706  else
1707  pergroupChunkSize = 0;
1708 
1709  if (transitionSpace > 0)
1710  transitionChunkSize = CHUNKHDRSZ + transitionSpace;
1711  else
1712  transitionChunkSize = 0;
1713 
1714  return
1715  sizeof(TupleHashEntryData) +
1716  tupleChunkSize +
1717  pergroupChunkSize +
1718  transitionChunkSize;
1719 }
struct TupleHashEntryData TupleHashEntryData
struct AggStatePerGroupData AggStatePerGroupData
#define SizeofMinimalTupleHeader
Definition: htup_details.h:649
size_t Size
Definition: c.h:540
#define MAXALIGN(LEN)
Definition: c.h:757
#define CHUNKHDRSZ
Definition: nodeAgg.c:312

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

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

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

1800 {
1801  int npartitions;
1802  Size partition_mem;
1803  int hash_mem = get_hash_mem();
1804 
1805  /* if not expected to spill, use all of hash_mem */
1806  if (input_groups * hashentrysize < hash_mem * 1024L)
1807  {
1808  if (num_partitions != NULL)
1809  *num_partitions = 0;
1810  *mem_limit = hash_mem * 1024L;
1811  *ngroups_limit = *mem_limit / hashentrysize;
1812  return;
1813  }
1814 
1815  /*
1816  * Calculate expected memory requirements for spilling, which is the size
1817  * of the buffers needed for all the tapes that need to be open at once.
1818  * Then, subtract that from the memory available for holding hash tables.
1819  */
1820  npartitions = hash_choose_num_partitions(input_groups,
1821  hashentrysize,
1822  used_bits,
1823  NULL);
1824  if (num_partitions != NULL)
1825  *num_partitions = npartitions;
1826 
1827  partition_mem =
1829  HASHAGG_WRITE_BUFFER_SIZE * npartitions;
1830 
1831  /*
1832  * Don't set the limit below 3/4 of hash_mem. In that case, we are at the
1833  * minimum number of partitions, so we aren't going to dramatically exceed
1834  * work mem anyway.
1835  */
1836  if (hash_mem * 1024L > 4 * partition_mem)
1837  *mem_limit = hash_mem * 1024L - partition_mem;
1838  else
1839  *mem_limit = hash_mem * 1024L * 0.75;
1840 
1841  if (*mem_limit > hashentrysize)
1842  *ngroups_limit = *mem_limit / hashentrysize;
1843  else
1844  *ngroups_limit = 1;
1845 }
static int hash_choose_num_partitions(double input_groups, double hashentrysize, int used_bits, int *log2_npartittions)
Definition: nodeAgg.c:1990
#define HASHAGG_READ_BUFFER_SIZE
Definition: nodeAgg.c:297
size_t Size
Definition: c.h:540
#define HASHAGG_WRITE_BUFFER_SIZE
Definition: nodeAgg.c:298
int get_hash_mem(void)
Definition: nodeHash.c:3389