PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
nodeAgg.h File Reference
#include "nodes/execnodes.h"
Include dependency graph for nodeAgg.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

AggStateExecInitAgg (Agg *node, EState *estate, int eflags)
 
TupleTableSlotExecAgg (AggState *node)
 
void ExecEndAgg (AggState *node)
 
void ExecReScanAgg (AggState *node)
 
Size hash_agg_entry_size (int numAggs)
 
Datum aggregate_dummy (PG_FUNCTION_ARGS)
 

Function Documentation

Datum aggregate_dummy ( PG_FUNCTION_ARGS  )

Definition at line 3777 of file nodeAgg.c.

References elog, and ERROR.

3778 {
3779  elog(ERROR, "aggregate function %u called as normal function",
3780  fcinfo->flinfo->fn_oid);
3781  return (Datum) 0; /* keep compiler quiet */
3782 }
#define ERROR
Definition: elog.h:43
uintptr_t Datum
Definition: postgres.h:374
#define elog
Definition: elog.h:219
TupleTableSlot* ExecAgg ( AggState node)

Definition at line 1899 of file nodeAgg.c.

References AggState::agg_done, agg_fill_hash_table(), AGG_HASHED, agg_retrieve_direct(), agg_retrieve_hash_table(), AggStatePerPhaseData::aggnode, Agg::aggstrategy, NULL, AggState::phase, AggState::table_filled, and TupIsNull.

Referenced by ExecProcNode().

1900 {
1901  TupleTableSlot *result;
1902 
1903  if (!node->agg_done)
1904  {
1905  /* Dispatch based on strategy */
1906  switch (node->phase->aggnode->aggstrategy)
1907  {
1908  case AGG_HASHED:
1909  if (!node->table_filled)
1910  agg_fill_hash_table(node);
1911  result = agg_retrieve_hash_table(node);
1912  break;
1913  default:
1914  result = agg_retrieve_direct(node);
1915  break;
1916  }
1917 
1918  if (!TupIsNull(result))
1919  return result;
1920  }
1921 
1922  return NULL;
1923 }
static void agg_fill_hash_table(AggState *aggstate)
Definition: nodeAgg.c:2253
bool agg_done
Definition: execnodes.h:1882
AggStrategy aggstrategy
Definition: plannodes.h:733
bool table_filled
Definition: execnodes.h:1904
static TupleTableSlot * agg_retrieve_hash_table(AggState *aggstate)
Definition: nodeAgg.c:2300
static TupleTableSlot * agg_retrieve_direct(AggState *aggstate)
Definition: nodeAgg.c:1929
#define TupIsNull(slot)
Definition: tuptable.h:138
AggStatePerPhase phase
Definition: execnodes.h:1872
#define NULL
Definition: c.h:226
void ExecEndAgg ( AggState node)

Definition at line 3487 of file nodeAgg.c.

References AggState::aggcontexts, ExecClearTuple(), ExecEndNode(), ExecFreeExprContext(), Max, AggState::maxsets, AggState::numtrans, outerPlan, outerPlanState, AggState::pertrans, ScanState::ps, ReScanExprContext(), AggState::sort_in, AggState::sort_out, AggStatePerTransData::sortstates, AggState::ss, ScanState::ss_ScanTupleSlot, and tuplesort_end().

Referenced by ExecEndNode().

3488 {
3490  int transno;
3491  int numGroupingSets = Max(node->maxsets, 1);
3492  int setno;
3493 
3494  /* Make sure we have closed any open tuplesorts */
3495 
3496  if (node->sort_in)
3497  tuplesort_end(node->sort_in);
3498  if (node->sort_out)
3499  tuplesort_end(node->sort_out);
3500 
3501  for (transno = 0; transno < node->numtrans; transno++)
3502  {
3503  AggStatePerTrans pertrans = &node->pertrans[transno];
3504 
3505  for (setno = 0; setno < numGroupingSets; setno++)
3506  {
3507  if (pertrans->sortstates[setno])
3508  tuplesort_end(pertrans->sortstates[setno]);
3509  }
3510  }
3511 
3512  /* And ensure any agg shutdown callbacks have been called */
3513  for (setno = 0; setno < numGroupingSets; setno++)
3514  ReScanExprContext(node->aggcontexts[setno]);
3515 
3516  /*
3517  * We don't actually free any ExprContexts here (see comment in
3518  * ExecFreeExprContext), just unlinking the output one from the plan node
3519  * suffices.
3520  */
3521  ExecFreeExprContext(&node->ss.ps);
3522 
3523  /* clean up tuple table */
3525 
3526  outerPlan = outerPlanState(node);
3527  ExecEndNode(outerPlan);
3528 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:624
Tuplesortstate * sort_out
Definition: execnodes.h:1892
ScanState ss
Definition: execnodes.h:1867
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1291
AggStatePerTrans pertrans
Definition: execnodes.h:1877
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:685
int numtrans
Definition: execnodes.h:1870
PlanState ps
Definition: execnodes.h:1288
int maxsets
Definition: execnodes.h:1889
Tuplesortstate * sort_in
Definition: execnodes.h:1891
#define outerPlanState(node)
Definition: execnodes.h:1090
Tuplesortstate ** sortstates
Definition: nodeAgg.c:326
#define outerPlan(node)
Definition: plannodes.h:159
#define Max(x, y)
Definition: c.h:796
ExprContext ** aggcontexts
Definition: execnodes.h:1878
void ReScanExprContext(ExprContext *econtext)
Definition: execUtils.c:366
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1157
AggState* ExecInitAgg ( Agg node,
EState estate,
int  eflags 
)

Definition at line 2395 of file nodeAgg.c.

References ACL_EXECUTE, ACL_KIND_PROC, aclcheck_error(), ACLCHECK_OK, AggState::agg_done, AGG_HASHED, AGG_SORTED, AggState::aggcontexts, Aggref::aggdirectargs, AGGFNOID, Aggref::aggfnoid, Aggref::agglevelsup, AggrefExprState::aggno, AggStatePerPhaseData::aggnode, AggStatePerTransData::aggref, AggStatePerAggData::aggref, AggState::aggs, Aggref::aggsplit, Agg::aggsplit, AggState::aggsplit, Agg::aggstrategy, Aggref::aggtranstype, Aggref::aggtype, AggState::all_grouped_cols, Anum_pg_aggregate_agginitval, arg, Aggref::args, Assert, bms_add_member(), bms_add_members(), bms_next_member(), build_aggregate_finalfn_expr(), build_hash_table(), build_pertrans_for_aggref(), castNode, Agg::chain, AggState::curpertrans, AggState::current_phase, AggState::current_set, DO_AGGSPLIT_COMBINE, DO_AGGSPLIT_DESERIALIZE, DO_AGGSPLIT_SERIALIZE, DO_AGGSPLIT_SKIPFINAL, ExprContext::ecxt_aggnulls, ExprContext::ecxt_aggvalues, elog, AggStatePerPhaseData::eqfunctions, ERROR, AggState::evaldesc, AggState::evalslot, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, EXEC_FLAG_REWIND, ExecAssignExprContext(), ExecAssignProjectionInfo(), ExecAssignResultTypeFromTL(), ExecAssignScanTypeFromOuterPlan(), ExecBuildProjectionInfo(), ExecInitExpr(), ExecInitExtraTupleSlot(), ExecInitNode(), ExecInitResultTupleSlot(), ExecInitScanTupleSlot(), ExecSetSlotDescriptor(), execTuplesHashPrepare(), execTuplesMatchPrepare(), ExecTypeFromTL(), ExprState::expr, find_compatible_peragg(), find_compatible_pertrans(), find_hash_columns(), flatCopyTargetEntry(), fmgr_info(), fmgr_info_set_expr, FUNC_MAX_ARGS, get_aggregate_argtypes(), get_func_name(), get_typlenbyval(), GetAggInitVal(), GETSTRUCT, GetUserId(), AggStatePerPhaseData::grouped_cols, Agg::groupingSets, AggState::grp_firstTuple, Agg::grpColIdx, Agg::grpOperators, AggStatePerPhaseData::gset_lengths, AggState::hashfunctions, AggState::hashslot, AggState::hashtable, HeapTupleIsValid, i, initialize_phase(), initValue(), AggState::input_done, Aggref::inputcollid, AggStatePerTransData::inputoff, INTERNALOID, InvalidOid, InvokeFunctionExecuteHook, lappend(), lcons_int(), Plan::lefttree, lfirst, list_length(), list_nth(), makeNode, Max, AggState::maxsets, NIL, NULL, AggState::numaggs, Agg::numCols, AggState::numphases, AggStatePerPhaseData::numsets, AggState::numtrans, ObjectIdGetDatum, OidIsValid, outerPlan, outerPlanState, palloc(), palloc0(), AggState::peragg, AggState::pergroup, AggState::pertrans, pg_proc_aclcheck(), AggState::phases, Agg::plan, PlanState::plan, PROCOID, AggState::projected_set, ScanState::ps, PlanState::ps_ExprContext, Plan::qual, PlanState::qual, ReleaseSysCache(), TargetEntry::resno, SearchSysCache1, AggState::sort_in, AggState::sort_out, AggState::sort_slot, AggStatePerPhaseData::sortnode, AggState::ss, ScanState::ss_ScanTupleSlot, PlanState::state, SysCacheGetAttr(), AggState::table_filled, Plan::targetlist, PlanState::targetlist, AggState::tmpcontext, TupleTableSlot::tts_tupleDescriptor, and AggrefExprState::xprstate.

Referenced by ExecInitNode().

2396 {
2397  AggState *aggstate;
2398  AggStatePerAgg peraggs;
2399  AggStatePerTrans pertransstates;
2400  Plan *outerPlan;
2401  ExprContext *econtext;
2402  int numaggs,
2403  transno,
2404  aggno;
2405  int phase;
2406  List *combined_inputeval;
2407  ListCell *l;
2408  Bitmapset *all_grouped_cols = NULL;
2409  int numGroupingSets = 1;
2410  int numPhases;
2411  int column_offset;
2412  int i = 0;
2413  int j = 0;
2414 
2415  /* check for unsupported flags */
2416  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
2417 
2418  /*
2419  * create state structure
2420  */
2421  aggstate = makeNode(AggState);
2422  aggstate->ss.ps.plan = (Plan *) node;
2423  aggstate->ss.ps.state = estate;
2424 
2425  aggstate->aggs = NIL;
2426  aggstate->numaggs = 0;
2427  aggstate->numtrans = 0;
2428  aggstate->aggsplit = node->aggsplit;
2429  aggstate->maxsets = 0;
2430  aggstate->hashfunctions = NULL;
2431  aggstate->projected_set = -1;
2432  aggstate->current_set = 0;
2433  aggstate->peragg = NULL;
2434  aggstate->pertrans = NULL;
2435  aggstate->curpertrans = NULL;
2436  aggstate->input_done = false;
2437  aggstate->agg_done = false;
2438  aggstate->pergroup = NULL;
2439  aggstate->grp_firstTuple = NULL;
2440  aggstate->hashtable = NULL;
2441  aggstate->sort_in = NULL;
2442  aggstate->sort_out = NULL;
2443 
2444  /*
2445  * Calculate the maximum number of grouping sets in any phase; this
2446  * determines the size of some allocations.
2447  */
2448  if (node->groupingSets)
2449  {
2450  Assert(node->aggstrategy != AGG_HASHED);
2451 
2452  numGroupingSets = list_length(node->groupingSets);
2453 
2454  foreach(l, node->chain)
2455  {
2456  Agg *agg = lfirst(l);
2457 
2458  numGroupingSets = Max(numGroupingSets,
2459  list_length(agg->groupingSets));
2460  }
2461  }
2462 
2463  aggstate->maxsets = numGroupingSets;
2464  aggstate->numphases = numPhases = 1 + list_length(node->chain);
2465 
2466  aggstate->aggcontexts = (ExprContext **)
2467  palloc0(sizeof(ExprContext *) * numGroupingSets);
2468 
2469  /*
2470  * Create expression contexts. We need three or more, one for
2471  * per-input-tuple processing, one for per-output-tuple processing, and
2472  * one for each grouping set. The per-tuple memory context of the
2473  * per-grouping-set ExprContexts (aggcontexts) replaces the standalone
2474  * memory context formerly used to hold transition values. We cheat a
2475  * little by using ExecAssignExprContext() to build all of them.
2476  *
2477  * NOTE: the details of what is stored in aggcontexts and what is stored
2478  * in the regular per-query memory context are driven by a simple
2479  * decision: we want to reset the aggcontext at group boundaries (if not
2480  * hashing) and in ExecReScanAgg to recover no-longer-wanted space.
2481  */
2482  ExecAssignExprContext(estate, &aggstate->ss.ps);
2483  aggstate->tmpcontext = aggstate->ss.ps.ps_ExprContext;
2484 
2485  for (i = 0; i < numGroupingSets; ++i)
2486  {
2487  ExecAssignExprContext(estate, &aggstate->ss.ps);
2488  aggstate->aggcontexts[i] = aggstate->ss.ps.ps_ExprContext;
2489  }
2490 
2491  ExecAssignExprContext(estate, &aggstate->ss.ps);
2492 
2493  /*
2494  * tuple table initialization
2495  */
2496  ExecInitScanTupleSlot(estate, &aggstate->ss);
2497  ExecInitResultTupleSlot(estate, &aggstate->ss.ps);
2498  aggstate->hashslot = ExecInitExtraTupleSlot(estate);
2499  aggstate->sort_slot = ExecInitExtraTupleSlot(estate);
2500 
2501  /*
2502  * initialize child expressions
2503  *
2504  * Note: ExecInitExpr finds Aggrefs for us, and also checks that no aggs
2505  * contain other agg calls in their arguments. This would make no sense
2506  * under SQL semantics anyway (and it's forbidden by the spec). Because
2507  * that is true, we don't need to worry about evaluating the aggs in any
2508  * particular order.
2509  */
2510  aggstate->ss.ps.targetlist = (List *)
2511  ExecInitExpr((Expr *) node->plan.targetlist,
2512  (PlanState *) aggstate);
2513  aggstate->ss.ps.qual = (List *)
2514  ExecInitExpr((Expr *) node->plan.qual,
2515  (PlanState *) aggstate);
2516 
2517  /*
2518  * Initialize child nodes.
2519  *
2520  * If we are doing a hashed aggregation then the child plan does not need
2521  * to handle REWIND efficiently; see ExecReScanAgg.
2522  */
2523  if (node->aggstrategy == AGG_HASHED)
2524  eflags &= ~EXEC_FLAG_REWIND;
2525  outerPlan = outerPlan(node);
2526  outerPlanState(aggstate) = ExecInitNode(outerPlan, estate, eflags);
2527 
2528  /*
2529  * initialize source tuple type.
2530  */
2531  ExecAssignScanTypeFromOuterPlan(&aggstate->ss);
2532  if (node->chain)
2533  ExecSetSlotDescriptor(aggstate->sort_slot,
2535 
2536  /*
2537  * Initialize result tuple type and projection info.
2538  */
2539  ExecAssignResultTypeFromTL(&aggstate->ss.ps);
2540  ExecAssignProjectionInfo(&aggstate->ss.ps, NULL);
2541 
2542  /*
2543  * get the count of aggregates in targetlist and quals
2544  */
2545  numaggs = aggstate->numaggs;
2546  Assert(numaggs == list_length(aggstate->aggs));
2547  if (numaggs <= 0)
2548  {
2549  /*
2550  * This is not an error condition: we might be using the Agg node just
2551  * to do hash-based grouping. Even in the regular case,
2552  * constant-expression simplification could optimize away all of the
2553  * Aggrefs in the targetlist and qual. So keep going, but force local
2554  * copy of numaggs positive so that palloc()s below don't choke.
2555  */
2556  numaggs = 1;
2557  }
2558 
2559  /*
2560  * For each phase, prepare grouping set data and fmgr lookup data for
2561  * compare functions. Accumulate all_grouped_cols in passing.
2562  */
2563 
2564  aggstate->phases = palloc0(numPhases * sizeof(AggStatePerPhaseData));
2565 
2566  for (phase = 0; phase < numPhases; ++phase)
2567  {
2568  AggStatePerPhase phasedata = &aggstate->phases[phase];
2569  Agg *aggnode;
2570  Sort *sortnode;
2571  int num_sets;
2572 
2573  if (phase > 0)
2574  {
2575  aggnode = castNode(Agg, list_nth(node->chain, phase - 1));
2576  sortnode = castNode(Sort, aggnode->plan.lefttree);
2577  }
2578  else
2579  {
2580  aggnode = node;
2581  sortnode = NULL;
2582  }
2583 
2584  phasedata->numsets = num_sets = list_length(aggnode->groupingSets);
2585 
2586  if (num_sets)
2587  {
2588  phasedata->gset_lengths = palloc(num_sets * sizeof(int));
2589  phasedata->grouped_cols = palloc(num_sets * sizeof(Bitmapset *));
2590 
2591  i = 0;
2592  foreach(l, aggnode->groupingSets)
2593  {
2594  int current_length = list_length(lfirst(l));
2595  Bitmapset *cols = NULL;
2596 
2597  /* planner forces this to be correct */
2598  for (j = 0; j < current_length; ++j)
2599  cols = bms_add_member(cols, aggnode->grpColIdx[j]);
2600 
2601  phasedata->grouped_cols[i] = cols;
2602  phasedata->gset_lengths[i] = current_length;
2603  ++i;
2604  }
2605 
2606  all_grouped_cols = bms_add_members(all_grouped_cols,
2607  phasedata->grouped_cols[0]);
2608  }
2609  else
2610  {
2611  Assert(phase == 0);
2612 
2613  phasedata->gset_lengths = NULL;
2614  phasedata->grouped_cols = NULL;
2615  }
2616 
2617  /*
2618  * If we are grouping, precompute fmgr lookup data for inner loop.
2619  */
2620  if (aggnode->aggstrategy == AGG_SORTED)
2621  {
2622  Assert(aggnode->numCols > 0);
2623 
2624  phasedata->eqfunctions =
2626  aggnode->grpOperators);
2627  }
2628 
2629  phasedata->aggnode = aggnode;
2630  phasedata->sortnode = sortnode;
2631  }
2632 
2633  /*
2634  * Convert all_grouped_cols to a descending-order list.
2635  */
2636  i = -1;
2637  while ((i = bms_next_member(all_grouped_cols, i)) >= 0)
2638  aggstate->all_grouped_cols = lcons_int(i, aggstate->all_grouped_cols);
2639 
2640  /*
2641  * Initialize current phase-dependent values to initial phase
2642  */
2643 
2644  aggstate->current_phase = 0;
2645  initialize_phase(aggstate, 0);
2646 
2647  /*
2648  * Set up aggregate-result storage in the output expr context, and also
2649  * allocate my private per-agg working storage
2650  */
2651  econtext = aggstate->ss.ps.ps_ExprContext;
2652  econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs);
2653  econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs);
2654 
2655  peraggs = (AggStatePerAgg) palloc0(sizeof(AggStatePerAggData) * numaggs);
2656  pertransstates = (AggStatePerTrans) palloc0(sizeof(AggStatePerTransData) * numaggs);
2657 
2658  aggstate->peragg = peraggs;
2659  aggstate->pertrans = pertransstates;
2660 
2661 
2662  /*
2663  * Hashing can only appear in the initial phase.
2664  */
2665  if (node->aggstrategy == AGG_HASHED)
2666  {
2667  find_hash_columns(aggstate);
2668 
2670  node->grpOperators,
2671  &aggstate->phases[0].eqfunctions,
2672  &aggstate->hashfunctions);
2673 
2674  build_hash_table(aggstate);
2675  aggstate->table_filled = false;
2676  }
2677  else
2678  {
2679  AggStatePerGroup pergroup;
2680 
2681  pergroup = (AggStatePerGroup) palloc0(sizeof(AggStatePerGroupData)
2682  * numaggs
2683  * numGroupingSets);
2684 
2685  aggstate->pergroup = pergroup;
2686  }
2687 
2688  /* -----------------
2689  * Perform lookups of aggregate function info, and initialize the
2690  * unchanging fields of the per-agg and per-trans data.
2691  *
2692  * We try to optimize by detecting duplicate aggregate functions so that
2693  * their state and final values are re-used, rather than needlessly being
2694  * re-calculated independently. We also detect aggregates that are not
2695  * the same, but which can share the same transition state.
2696  *
2697  * Scenarios:
2698  *
2699  * 1. An aggregate function appears more than once in query:
2700  *
2701  * SELECT SUM(x) FROM ... HAVING SUM(x) > 0
2702  *
2703  * Since the aggregates are the identical, we only need to calculate
2704  * the calculate it once. Both aggregates will share the same 'aggno'
2705  * value.
2706  *
2707  * 2. Two different aggregate functions appear in the query, but the
2708  * aggregates have the same transition function and initial value, but
2709  * different final function:
2710  *
2711  * SELECT SUM(x), AVG(x) FROM ...
2712  *
2713  * In this case we must create a new peragg for the varying aggregate,
2714  * and need to call the final functions separately, but can share the
2715  * same transition state.
2716  *
2717  * For either of these optimizations to be valid, the aggregate's
2718  * arguments must be the same, including any modifiers such as ORDER BY,
2719  * DISTINCT and FILTER, and they mustn't contain any volatile functions.
2720  * -----------------
2721  */
2722  aggno = -1;
2723  transno = -1;
2724  foreach(l, aggstate->aggs)
2725  {
2726  AggrefExprState *aggrefstate = (AggrefExprState *) lfirst(l);
2727  Aggref *aggref = (Aggref *) aggrefstate->xprstate.expr;
2728  AggStatePerAgg peragg;
2729  AggStatePerTrans pertrans;
2730  int existing_aggno;
2731  int existing_transno;
2732  List *same_input_transnos;
2733  Oid inputTypes[FUNC_MAX_ARGS];
2734  int numArguments;
2735  int numDirectArgs;
2736  HeapTuple aggTuple;
2737  Form_pg_aggregate aggform;
2738  AclResult aclresult;
2739  Oid transfn_oid,
2740  finalfn_oid;
2741  Oid serialfn_oid,
2742  deserialfn_oid;
2743  Expr *finalfnexpr;
2744  Oid aggtranstype;
2745  Datum textInitVal;
2746  Datum initValue;
2747  bool initValueIsNull;
2748 
2749  /* Planner should have assigned aggregate to correct level */
2750  Assert(aggref->agglevelsup == 0);
2751  /* ... and the split mode should match */
2752  Assert(aggref->aggsplit == aggstate->aggsplit);
2753 
2754  /* 1. Check for already processed aggs which can be re-used */
2755  existing_aggno = find_compatible_peragg(aggref, aggstate, aggno,
2756  &same_input_transnos);
2757  if (existing_aggno != -1)
2758  {
2759  /*
2760  * Existing compatible agg found. so just point the Aggref to the
2761  * same per-agg struct.
2762  */
2763  aggrefstate->aggno = existing_aggno;
2764  continue;
2765  }
2766 
2767  /* Mark Aggref state node with assigned index in the result array */
2768  peragg = &peraggs[++aggno];
2769  peragg->aggref = aggref;
2770  aggrefstate->aggno = aggno;
2771 
2772  /* Fetch the pg_aggregate row */
2773  aggTuple = SearchSysCache1(AGGFNOID,
2774  ObjectIdGetDatum(aggref->aggfnoid));
2775  if (!HeapTupleIsValid(aggTuple))
2776  elog(ERROR, "cache lookup failed for aggregate %u",
2777  aggref->aggfnoid);
2778  aggform = (Form_pg_aggregate) GETSTRUCT(aggTuple);
2779 
2780  /* Check permission to call aggregate function */
2781  aclresult = pg_proc_aclcheck(aggref->aggfnoid, GetUserId(),
2782  ACL_EXECUTE);
2783  if (aclresult != ACLCHECK_OK)
2784  aclcheck_error(aclresult, ACL_KIND_PROC,
2785  get_func_name(aggref->aggfnoid));
2787 
2788  /* planner recorded transition state type in the Aggref itself */
2789  aggtranstype = aggref->aggtranstype;
2790  Assert(OidIsValid(aggtranstype));
2791 
2792  /*
2793  * If this aggregation is performing state combines, then instead of
2794  * using the transition function, we'll use the combine function
2795  */
2796  if (DO_AGGSPLIT_COMBINE(aggstate->aggsplit))
2797  {
2798  transfn_oid = aggform->aggcombinefn;
2799 
2800  /* If not set then the planner messed up */
2801  if (!OidIsValid(transfn_oid))
2802  elog(ERROR, "combinefn not set for aggregate function");
2803  }
2804  else
2805  transfn_oid = aggform->aggtransfn;
2806 
2807  /* Final function only required if we're finalizing the aggregates */
2808  if (DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit))
2809  peragg->finalfn_oid = finalfn_oid = InvalidOid;
2810  else
2811  peragg->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
2812 
2813  serialfn_oid = InvalidOid;
2814  deserialfn_oid = InvalidOid;
2815 
2816  /*
2817  * Check if serialization/deserialization is required. We only do it
2818  * for aggregates that have transtype INTERNAL.
2819  */
2820  if (aggtranstype == INTERNALOID)
2821  {
2822  /*
2823  * The planner should only have generated a serialize agg node if
2824  * every aggregate with an INTERNAL state has a serialization
2825  * function. Verify that.
2826  */
2827  if (DO_AGGSPLIT_SERIALIZE(aggstate->aggsplit))
2828  {
2829  /* serialization only valid when not running finalfn */
2831 
2832  if (!OidIsValid(aggform->aggserialfn))
2833  elog(ERROR, "serialfunc not provided for serialization aggregation");
2834  serialfn_oid = aggform->aggserialfn;
2835  }
2836 
2837  /* Likewise for deserialization functions */
2838  if (DO_AGGSPLIT_DESERIALIZE(aggstate->aggsplit))
2839  {
2840  /* deserialization only valid when combining states */
2841  Assert(DO_AGGSPLIT_COMBINE(aggstate->aggsplit));
2842 
2843  if (!OidIsValid(aggform->aggdeserialfn))
2844  elog(ERROR, "deserialfunc not provided for deserialization aggregation");
2845  deserialfn_oid = aggform->aggdeserialfn;
2846  }
2847  }
2848 
2849  /* Check that aggregate owner has permission to call component fns */
2850  {
2851  HeapTuple procTuple;
2852  Oid aggOwner;
2853 
2854  procTuple = SearchSysCache1(PROCOID,
2855  ObjectIdGetDatum(aggref->aggfnoid));
2856  if (!HeapTupleIsValid(procTuple))
2857  elog(ERROR, "cache lookup failed for function %u",
2858  aggref->aggfnoid);
2859  aggOwner = ((Form_pg_proc) GETSTRUCT(procTuple))->proowner;
2860  ReleaseSysCache(procTuple);
2861 
2862  aclresult = pg_proc_aclcheck(transfn_oid, aggOwner,
2863  ACL_EXECUTE);
2864  if (aclresult != ACLCHECK_OK)
2865  aclcheck_error(aclresult, ACL_KIND_PROC,
2866  get_func_name(transfn_oid));
2867  InvokeFunctionExecuteHook(transfn_oid);
2868  if (OidIsValid(finalfn_oid))
2869  {
2870  aclresult = pg_proc_aclcheck(finalfn_oid, aggOwner,
2871  ACL_EXECUTE);
2872  if (aclresult != ACLCHECK_OK)
2873  aclcheck_error(aclresult, ACL_KIND_PROC,
2874  get_func_name(finalfn_oid));
2875  InvokeFunctionExecuteHook(finalfn_oid);
2876  }
2877  if (OidIsValid(serialfn_oid))
2878  {
2879  aclresult = pg_proc_aclcheck(serialfn_oid, aggOwner,
2880  ACL_EXECUTE);
2881  if (aclresult != ACLCHECK_OK)
2882  aclcheck_error(aclresult, ACL_KIND_PROC,
2883  get_func_name(serialfn_oid));
2884  InvokeFunctionExecuteHook(serialfn_oid);
2885  }
2886  if (OidIsValid(deserialfn_oid))
2887  {
2888  aclresult = pg_proc_aclcheck(deserialfn_oid, aggOwner,
2889  ACL_EXECUTE);
2890  if (aclresult != ACLCHECK_OK)
2891  aclcheck_error(aclresult, ACL_KIND_PROC,
2892  get_func_name(deserialfn_oid));
2893  InvokeFunctionExecuteHook(deserialfn_oid);
2894  }
2895  }
2896 
2897  /*
2898  * Get actual datatypes of the (nominal) aggregate inputs. These
2899  * could be different from the agg's declared input types, when the
2900  * agg accepts ANY or a polymorphic type.
2901  */
2902  numArguments = get_aggregate_argtypes(aggref, inputTypes);
2903 
2904  /* Count the "direct" arguments, if any */
2905  numDirectArgs = list_length(aggref->aggdirectargs);
2906 
2907  /* Detect how many arguments to pass to the finalfn */
2908  if (aggform->aggfinalextra)
2909  peragg->numFinalArgs = numArguments + 1;
2910  else
2911  peragg->numFinalArgs = numDirectArgs + 1;
2912 
2913  /*
2914  * build expression trees using actual argument & result types for the
2915  * finalfn, if it exists and is required.
2916  */
2917  if (OidIsValid(finalfn_oid))
2918  {
2919  build_aggregate_finalfn_expr(inputTypes,
2920  peragg->numFinalArgs,
2921  aggtranstype,
2922  aggref->aggtype,
2923  aggref->inputcollid,
2924  finalfn_oid,
2925  &finalfnexpr);
2926  fmgr_info(finalfn_oid, &peragg->finalfn);
2927  fmgr_info_set_expr((Node *) finalfnexpr, &peragg->finalfn);
2928  }
2929 
2930  /* get info about the output value's datatype */
2931  get_typlenbyval(aggref->aggtype,
2932  &peragg->resulttypeLen,
2933  &peragg->resulttypeByVal);
2934 
2935  /*
2936  * initval is potentially null, so don't try to access it as a struct
2937  * field. Must do it the hard way with SysCacheGetAttr.
2938  */
2939  textInitVal = SysCacheGetAttr(AGGFNOID, aggTuple,
2941  &initValueIsNull);
2942  if (initValueIsNull)
2943  initValue = (Datum) 0;
2944  else
2945  initValue = GetAggInitVal(textInitVal, aggtranstype);
2946 
2947  /*
2948  * 2. Build working state for invoking the transition function, or
2949  * look up previously initialized working state, if we can share it.
2950  *
2951  * find_compatible_peragg() already collected a list of per-Trans's
2952  * with the same inputs. Check if any of them have the same transition
2953  * function and initial value.
2954  */
2955  existing_transno = find_compatible_pertrans(aggstate, aggref,
2956  transfn_oid, aggtranstype,
2957  serialfn_oid, deserialfn_oid,
2958  initValue, initValueIsNull,
2959  same_input_transnos);
2960  if (existing_transno != -1)
2961  {
2962  /*
2963  * Existing compatible trans found, so just point the 'peragg' to
2964  * the same per-trans struct.
2965  */
2966  pertrans = &pertransstates[existing_transno];
2967  peragg->transno = existing_transno;
2968  }
2969  else
2970  {
2971  pertrans = &pertransstates[++transno];
2972  build_pertrans_for_aggref(pertrans, aggstate, estate,
2973  aggref, transfn_oid, aggtranstype,
2974  serialfn_oid, deserialfn_oid,
2975  initValue, initValueIsNull,
2976  inputTypes, numArguments);
2977  peragg->transno = transno;
2978  }
2979  ReleaseSysCache(aggTuple);
2980  }
2981 
2982  /*
2983  * Update numaggs to match the number of unique aggregates found. Also set
2984  * numstates to the number of unique aggregate states found.
2985  */
2986  aggstate->numaggs = aggno + 1;
2987  aggstate->numtrans = transno + 1;
2988 
2989  /*
2990  * Build a single projection computing the aggregate arguments for all
2991  * aggregates at once, that's considerably faster than doing it separately
2992  * for each.
2993  *
2994  * First create a targetlist combining the targetlist of all the
2995  * transitions.
2996  */
2997  combined_inputeval = NIL;
2998  column_offset = 0;
2999  for (transno = 0; transno < aggstate->numtrans; transno++)
3000  {
3001  AggStatePerTrans pertrans = &pertransstates[transno];
3002  ListCell *arg;
3003 
3004  pertrans->inputoff = column_offset;
3005 
3006  /*
3007  * Adjust resno in a copied target entries, to point into the combined
3008  * slot.
3009  */
3010  foreach(arg, pertrans->aggref->args)
3011  {
3012  TargetEntry *source_tle = castNode(TargetEntry, lfirst(arg));
3013  TargetEntry *tle;
3014 
3015  tle = flatCopyTargetEntry(source_tle);
3016  tle->resno += column_offset;
3017 
3018  combined_inputeval = lappend(combined_inputeval, tle);
3019  }
3020 
3021  column_offset += list_length(pertrans->aggref->args);
3022  }
3023 
3024  /* and then create a projection for that targetlist */
3025  aggstate->evaldesc = ExecTypeFromTL(combined_inputeval, false);
3026  aggstate->evalslot = ExecInitExtraTupleSlot(estate);
3027  combined_inputeval = (List *) ExecInitExpr((Expr *) combined_inputeval,
3028  (PlanState *) aggstate);
3029  aggstate->evalproj = ExecBuildProjectionInfo(combined_inputeval,
3030  aggstate->tmpcontext,
3031  aggstate->evalslot,
3032  NULL);
3033  ExecSetSlotDescriptor(aggstate->evalslot, aggstate->evaldesc);
3034 
3035  return aggstate;
3036 }
struct AggStatePerTransData * AggStatePerTrans
Definition: execnodes.h:1861
#define NIL
Definition: pg_list.h:69
struct AggStatePerGroupData * AggStatePerGroup
Definition: execnodes.h:1862
ExprState xprstate
Definition: execnodes.h:633
int numCols
Definition: plannodes.h:735
List * qual
Definition: plannodes.h:130
AggStatePerPhase phases
Definition: execnodes.h:1890
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate)
Definition: execTuples.c:852
Datum * ecxt_aggvalues
Definition: execnodes.h:144
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate)
Definition: execTuples.c:842
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
AttrNumber * grpColIdx
Definition: plannodes.h:736
#define Anum_pg_aggregate_agginitval
Definition: pg_aggregate.h:113
List * lcons_int(int datum, List *list)
Definition: list.c:277
int numaggs
Definition: execnodes.h:1869
Oid GetUserId(void)
Definition: miscinit.c:282
bool agg_done
Definition: execnodes.h:1882
#define castNode(_type_, nodeptr)
Definition: nodes.h:578
TupleTableSlot * sort_slot
Definition: execnodes.h:1893
List * all_grouped_cols
Definition: execnodes.h:1886
Tuplesortstate * sort_out
Definition: execnodes.h:1892
ScanState ss
Definition: execnodes.h:1867
ExprContext * ps_ExprContext
Definition: execnodes.h:1078
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:907
FmgrInfo * eqfunctions
Definition: nodeAgg.c:438
Oid inputcollid
Definition: primnodes.h:275
List * qual
Definition: execnodes.h:1062
int current_phase
Definition: execnodes.h:1874
static List * find_hash_columns(AggState *aggstate)
Definition: nodeAgg.c:1754
Definition: nodes.h:509
AggSplit aggsplit
Definition: execnodes.h:1871
List * args
Definition: primnodes.h:279
FmgrInfo * hashfunctions
Definition: execnodes.h:1875
List * targetlist
Definition: execnodes.h:1061
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1291
void build_aggregate_finalfn_expr(Oid *agg_input_types, int num_finalfn_inputs, Oid agg_state_type, Oid agg_result_type, Oid agg_input_collation, Oid finalfn_oid, Expr **finalfnexpr)
Definition: parse_agg.c:2004
AggStatePerTrans pertrans
Definition: execnodes.h:1877
EState * state
Definition: execnodes.h:1049
int projected_set
Definition: execnodes.h:1883
unsigned int Oid
Definition: postgres_ext.h:31
HeapTuple grp_firstTuple
Definition: execnodes.h:1896
Aggref * aggref
Definition: nodeAgg.c:359
int current_set
Definition: execnodes.h:1884
#define OidIsValid(objectId)
Definition: c.h:534
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:760
TupleDesc evaldesc
Definition: execnodes.h:1909
int numtrans
Definition: execnodes.h:1870
void execTuplesHashPrepare(int numCols, Oid *eqOperators, FmgrInfo **eqFunctions, FmgrInfo **hashFunctions)
Definition: execGrouping.c:233
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
void ExecAssignResultTypeFromTL(PlanState *planstate)
Definition: execUtils.c:430
ExprContext * tmpcontext
Definition: execnodes.h:1879
#define FUNC_MAX_ARGS
Bitmapset ** grouped_cols
Definition: nodeAgg.c:437
PlanState ps
Definition: execnodes.h:1288
int maxsets
Definition: execnodes.h:1889
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execQual.c:4266
#define DO_AGGSPLIT_SERIALIZE(as)
Definition: nodes.h:762
AggStrategy aggstrategy
Definition: plannodes.h:733
bool table_filled
Definition: execnodes.h:1904
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
Expr * expr
Definition: execnodes.h:598
char * get_func_name(Oid funcid)
Definition: lsyscache.c:1380
void ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
Definition: execTuples.c:832
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:159
Tuplesortstate * sort_in
Definition: execnodes.h:1891
#define EXEC_FLAG_BACKWARD
Definition: executor.h:60
#define outerPlanState(node)
Definition: execnodes.h:1090
void * list_nth(const List *list, int n)
Definition: list.c:410
static int find_compatible_pertrans(AggState *aggstate, Aggref *newagg, Oid aggtransfn, Oid aggtranstype, Oid aggserialfn, Oid aggdeserialfn, Datum initValue, bool initValueIsNull, List *transnos)
Definition: nodeAgg.c:3440
static int initValue(long lng_val)
Definition: informix.c:702
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:657
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3378
static void build_hash_table(AggState *aggstate)
Definition: nodeAgg.c:1711
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:96
AttrNumber resno
Definition: primnodes.h:1331
ProjectionInfo * ExecBuildProjectionInfo(List *targetList, ExprContext *econtext, TupleTableSlot *slot, TupleDesc inputDesc)
Definition: execUtils.c:482
Index agglevelsup
Definition: primnodes.h:287
List * aggdirectargs
Definition: primnodes.h:278
static Datum GetAggInitVal(Datum textInitVal, Oid transtype)
Definition: nodeAgg.c:3339
TargetEntry * flatCopyTargetEntry(TargetEntry *src_tle)
Definition: makefuncs.c:268
#define EXEC_FLAG_REWIND
Definition: executor.h:59
TupleDesc ExecTypeFromTL(List *targetList, bool hasoid)
Definition: execTuples.c:888
#define InvokeFunctionExecuteHook(objectId)
Definition: objectaccess.h:179
#define outerPlan(node)
Definition: plannodes.h:159
List * lappend(List *list, void *datum)
Definition: list.c:128
static void build_pertrans_for_aggref(AggStatePerTrans pertrans, AggState *aggsate, EState *estate, Aggref *aggref, Oid aggtransfn, Oid aggtranstype, Oid aggserialfn, Oid aggdeserialfn, Datum initValue, bool initValueIsNull, Oid *inputTypes, int numArguments)
Definition: nodeAgg.c:3047
Plan plan
Definition: plannodes.h:732
bool input_done
Definition: execnodes.h:1881
TupleHashTable hashtable
Definition: execnodes.h:1898
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:121
TupleTableSlot * evalslot
Definition: execnodes.h:1907
bool * ecxt_aggnulls
Definition: execnodes.h:145
static int find_compatible_peragg(Aggref *newagg, AggState *aggstate, int lastaggno, List **same_input_transnos)
Definition: nodeAgg.c:3367
void * palloc0(Size size)
Definition: mcxt.c:920
AclResult
Definition: acl.h:170
uintptr_t Datum
Definition: postgres.h:374
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:247
AggStatePerGroup pergroup
Definition: execnodes.h:1895
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1245
List * groupingSets
Definition: plannodes.h:741
static void initialize_phase(AggState *aggstate, int newphase)
Definition: nodeAgg.c:508
FormData_pg_proc * Form_pg_proc
Definition: pg_proc.h:83
Plan * plan
Definition: execnodes.h:1047
#define InvalidOid
Definition: postgres_ext.h:36
Oid aggfnoid
Definition: primnodes.h:272
#define INTERNALOID
Definition: pg_type.h:686
#define Max(x, y)
Definition: c.h:796
ExprContext ** aggcontexts
Definition: execnodes.h:1878
#define makeNode(_type_)
Definition: nodes.h:557
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
#define EXEC_FLAG_MARK
Definition: executor.h:61
AggSplit aggsplit
Definition: plannodes.h:734
struct AggStatePerAggData * AggStatePerAgg
Definition: execnodes.h:1860
FormData_pg_aggregate * Form_pg_aggregate
Definition: pg_aggregate.h:87
AggSplit aggsplit
Definition: primnodes.h:288
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:408
static int list_length(const List *l)
Definition: pg_list.h:89
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:761
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:1969
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:668
#define DO_AGGSPLIT_DESERIALIZE(as)
Definition: nodes.h:763
struct Plan * lefttree
Definition: plannodes.h:131
int numphases
Definition: execnodes.h:1873
List * targetlist
Definition: plannodes.h:129
TupleTableSlot * hashslot
Definition: execnodes.h:1899
void ExecAssignScanTypeFromOuterPlan(ScanState *scanstate)
Definition: execUtils.c:721
Oid * grpOperators
Definition: plannodes.h:737
void * palloc(Size size)
Definition: mcxt.c:891
List * chain
Definition: plannodes.h:742
AggStatePerAgg peragg
Definition: execnodes.h:1876
#define ACL_EXECUTE
Definition: parsenodes.h:72
AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4421
int i
Oid aggtranstype
Definition: primnodes.h:276
void * arg
AggStatePerTrans curpertrans
Definition: execnodes.h:1880
Oid aggtype
Definition: primnodes.h:273
Definition: plannodes.h:730
#define elog
Definition: elog.h:219
List * aggs
Definition: execnodes.h:1868
FmgrInfo * execTuplesMatchPrepare(int numCols, Oid *eqOperators)
Definition: execGrouping.c:204
int get_aggregate_argtypes(Aggref *aggref, Oid *inputTypes)
Definition: parse_agg.c:1786
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:137
Definition: pg_list.h:45
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:725
void ExecReScanAgg ( AggState node)

Definition at line 3531 of file nodeAgg.c.

References AggState::agg_done, AGG_HASHED, AggState::aggcontexts, Agg::aggParams, Agg::aggstrategy, bms_overlap(), build_hash_table(), PlanState::chgParam, ExprContext::ecxt_aggnulls, ExprContext::ecxt_aggvalues, ExecClearTuple(), ExecReScan(), AggState::grp_firstTuple, AggState::hashiter, AggState::hashtable, heap_freetuple(), initialize_phase(), AggState::input_done, Max, AggState::maxsets, MemSet, NULL, AggState::numaggs, AggState::numtrans, outerPlan, outerPlanState, AggState::pergroup, AggState::pertrans, PlanState::plan, AggState::projected_set, ScanState::ps, PlanState::ps_ExprContext, ReScanExprContext(), ResetTupleHashIterator, AggStatePerTransData::sortstates, AggState::ss, ScanState::ss_ScanTupleSlot, AggState::table_filled, and tuplesort_end().

Referenced by ExecReScan().

3532 {
3533  ExprContext *econtext = node->ss.ps.ps_ExprContext;
3535  Agg *aggnode = (Agg *) node->ss.ps.plan;
3536  int transno;
3537  int numGroupingSets = Max(node->maxsets, 1);
3538  int setno;
3539 
3540  node->agg_done = false;
3541 
3542  if (aggnode->aggstrategy == AGG_HASHED)
3543  {
3544  /*
3545  * In the hashed case, if we haven't yet built the hash table then we
3546  * can just return; nothing done yet, so nothing to undo. If subnode's
3547  * chgParam is not NULL then it will be re-scanned by ExecProcNode,
3548  * else no reason to re-scan it at all.
3549  */
3550  if (!node->table_filled)
3551  return;
3552 
3553  /*
3554  * If we do have the hash table, and the subplan does not have any
3555  * parameter changes, and none of our own parameter changes affect
3556  * input expressions of the aggregated functions, then we can just
3557  * rescan the existing hash table; no need to build it again.
3558  */
3559  if (outerPlan->chgParam == NULL &&
3560  !bms_overlap(node->ss.ps.chgParam, aggnode->aggParams))
3561  {
3562  ResetTupleHashIterator(node->hashtable, &node->hashiter);
3563  return;
3564  }
3565  }
3566 
3567  /* Make sure we have closed any open tuplesorts */
3568  for (transno = 0; transno < node->numtrans; transno++)
3569  {
3570  for (setno = 0; setno < numGroupingSets; setno++)
3571  {
3572  AggStatePerTrans pertrans = &node->pertrans[transno];
3573 
3574  if (pertrans->sortstates[setno])
3575  {
3576  tuplesort_end(pertrans->sortstates[setno]);
3577  pertrans->sortstates[setno] = NULL;
3578  }
3579  }
3580  }
3581 
3582  /*
3583  * We don't need to ReScanExprContext the output tuple context here;
3584  * ExecReScan already did it. But we do need to reset our per-grouping-set
3585  * contexts, which may have transvalues stored in them. (We use rescan
3586  * rather than just reset because transfns may have registered callbacks
3587  * that need to be run now.)
3588  *
3589  * Note that with AGG_HASHED, the hash table is allocated in a sub-context
3590  * of the aggcontext. This used to be an issue, but now, resetting a
3591  * context automatically deletes sub-contexts too.
3592  */
3593 
3594  for (setno = 0; setno < numGroupingSets; setno++)
3595  {
3596  ReScanExprContext(node->aggcontexts[setno]);
3597  }
3598 
3599  /* Release first tuple of group, if we have made a copy */
3600  if (node->grp_firstTuple != NULL)
3601  {
3603  node->grp_firstTuple = NULL;
3604  }
3606 
3607  /* Forget current agg values */
3608  MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numaggs);
3609  MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numaggs);
3610 
3611  if (aggnode->aggstrategy == AGG_HASHED)
3612  {
3613  /* Rebuild an empty hash table */
3614  build_hash_table(node);
3615  node->table_filled = false;
3616  }
3617  else
3618  {
3619  /*
3620  * Reset the per-group state (in particular, mark transvalues null)
3621  */
3622  MemSet(node->pergroup, 0,
3623  sizeof(AggStatePerGroupData) * node->numaggs * numGroupingSets);
3624 
3625  /* reset to phase 0 */
3626  initialize_phase(node, 0);
3627 
3628  node->input_done = false;
3629  node->projected_set = -1;
3630  }
3631 
3632  if (outerPlan->chgParam == NULL)
3633  ExecReScan(outerPlan);
3634 }
Datum * ecxt_aggvalues
Definition: execnodes.h:144
int numaggs
Definition: execnodes.h:1869
bool agg_done
Definition: execnodes.h:1882
ScanState ss
Definition: execnodes.h:1867
ExprContext * ps_ExprContext
Definition: execnodes.h:1078
void ExecReScan(PlanState *node)
Definition: execAmi.c:73
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
#define MemSet(start, val, len)
Definition: c.h:853
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1291
AggStatePerTrans pertrans
Definition: execnodes.h:1877
int projected_set
Definition: execnodes.h:1883
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
HeapTuple grp_firstTuple
Definition: execnodes.h:1896
int numtrans
Definition: execnodes.h:1870
PlanState ps
Definition: execnodes.h:1288
int maxsets
Definition: execnodes.h:1889
AggStrategy aggstrategy
Definition: plannodes.h:733
bool table_filled
Definition: execnodes.h:1904
TupleHashIterator hashiter
Definition: execnodes.h:1905
#define outerPlanState(node)
Definition: execnodes.h:1090
Tuplesortstate ** sortstates
Definition: nodeAgg.c:326
Bitmapset * aggParams
Definition: plannodes.h:739
static void build_hash_table(AggState *aggstate)
Definition: nodeAgg.c:1711
Bitmapset * chgParam
Definition: execnodes.h:1072
#define outerPlan(node)
Definition: plannodes.h:159
bool input_done
Definition: execnodes.h:1881
TupleHashTable hashtable
Definition: execnodes.h:1898
bool * ecxt_aggnulls
Definition: execnodes.h:145
uintptr_t Datum
Definition: postgres.h:374
AggStatePerGroup pergroup
Definition: execnodes.h:1895
static void initialize_phase(AggState *aggstate, int newphase)
Definition: nodeAgg.c:508
Plan * plan
Definition: execnodes.h:1047
#define ResetTupleHashIterator(htable, iter)
Definition: execnodes.h:558
#define Max(x, y)
Definition: c.h:796
ExprContext ** aggcontexts
Definition: execnodes.h:1878
#define NULL
Definition: c.h:226
void ReScanExprContext(ExprContext *econtext)
Definition: execUtils.c:366
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:442
Definition: plannodes.h:730
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1157
Size hash_agg_entry_size ( int  numAggs)

Definition at line 1830 of file nodeAgg.c.

References MAXALIGN.

Referenced by create_distinct_paths(), and estimate_hashagg_tablesize().

1831 {
1832  Size entrysize;
1833 
1834  /* This must match build_hash_table */
1835  entrysize = sizeof(TupleHashEntryData) +
1836  numAggs * sizeof(AggStatePerGroupData);
1837  entrysize = MAXALIGN(entrysize);
1838 
1839  return entrysize;
1840 }
struct TupleHashEntryData TupleHashEntryData
size_t Size
Definition: c.h:353
#define MAXALIGN(LEN)
Definition: c.h:584