PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
nodeAgg.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "executor/executor.h"
#include "executor/nodeAgg.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/tlist.h"
#include "parser/parse_agg.h"
#include "parser/parse_coerce.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/syscache.h"
#include "utils/tuplesort.h"
#include "utils/datum.h"
Include dependency graph for nodeAgg.c:

Go to the source code of this file.

Data Structures

struct  AggStatePerTransData
 
struct  AggStatePerAggData
 
struct  AggStatePerGroupData
 
struct  AggStatePerPhaseData
 

Typedefs

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

Functions

static void initialize_phase (AggState *aggstate, int newphase)
 
static TupleTableSlotfetch_input_tuple (AggState *aggstate)
 
static void initialize_aggregates (AggState *aggstate, AggStatePerGroup pergroup, int numReset)
 
static void advance_transition_function (AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroupstate)
 
static void advance_aggregates (AggState *aggstate, AggStatePerGroup pergroup)
 
static void advance_combine_function (AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroupstate)
 
static void combine_aggregates (AggState *aggstate, AggStatePerGroup pergroup)
 
static void process_ordered_aggregate_single (AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroupstate)
 
static void process_ordered_aggregate_multi (AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroupstate)
 
static void finalize_aggregate (AggState *aggstate, AggStatePerAgg peragg, AggStatePerGroup pergroupstate, Datum *resultVal, bool *resultIsNull)
 
static void finalize_partialaggregate (AggState *aggstate, AggStatePerAgg peragg, AggStatePerGroup pergroupstate, Datum *resultVal, bool *resultIsNull)
 
static void prepare_projection_slot (AggState *aggstate, TupleTableSlot *slot, int currentSet)
 
static void finalize_aggregates (AggState *aggstate, AggStatePerAgg peragg, AggStatePerGroup pergroup, int currentSet)
 
static TupleTableSlotproject_aggregates (AggState *aggstate)
 
static Bitmapsetfind_unaggregated_cols (AggState *aggstate)
 
static bool find_unaggregated_cols_walker (Node *node, Bitmapset **colnos)
 
static void build_hash_table (AggState *aggstate)
 
static TupleHashEntryDatalookup_hash_entry (AggState *aggstate, TupleTableSlot *inputslot)
 
static TupleTableSlotagg_retrieve_direct (AggState *aggstate)
 
static void agg_fill_hash_table (AggState *aggstate)
 
static TupleTableSlotagg_retrieve_hash_table (AggState *aggstate)
 
static Datum GetAggInitVal (Datum textInitVal, Oid transtype)
 
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)
 
static int find_compatible_peragg (Aggref *newagg, AggState *aggstate, int lastaggno, List **same_input_transnos)
 
static int find_compatible_pertrans (AggState *aggstate, Aggref *newagg, Oid aggtransfn, Oid aggtranstype, Oid aggserialfn, Oid aggdeserialfn, Datum initValue, bool initValueIsNull, List *transnos)
 
static void initialize_aggregate (AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroupstate)
 
static Listfind_hash_columns (AggState *aggstate)
 
Size hash_agg_entry_size (int numAggs)
 
TupleTableSlotExecAgg (AggState *node)
 
AggStateExecInitAgg (Agg *node, EState *estate, int eflags)
 
void ExecEndAgg (AggState *node)
 
void ExecReScanAgg (AggState *node)
 
int AggCheckCallContext (FunctionCallInfo fcinfo, MemoryContext *aggcontext)
 
AggrefAggGetAggref (FunctionCallInfo fcinfo)
 
MemoryContext AggGetTempMemoryContext (FunctionCallInfo fcinfo)
 
void AggRegisterCallback (FunctionCallInfo fcinfo, ExprContextCallbackFunction func, Datum arg)
 
Datum aggregate_dummy (PG_FUNCTION_ARGS)
 

Typedef Documentation

Function Documentation

static void advance_aggregates ( AggState aggstate,
AggStatePerGroup  pergroup 
)
static

Definition at line 847 of file nodeAgg.c.

References advance_transition_function(), AggStatePerTransData::aggfilter, FunctionCallInfoData::arg, FunctionCallInfoData::argnull, Assert, AggState::current_set, DatumGetBool, AggState::evalproj, AggState::evalslot, ExecClearTuple(), ExecEvalExprSwitchContext(), ExecProject(), ExecStoreVirtualTuple(), FmgrInfo::fn_strict, i, AggStatePerTransData::inputoff, Max, AggStatePerTransData::numInputs, AggStatePerPhaseData::numsets, AggStatePerTransData::numSortCols, AggState::numtrans, AggStatePerTransData::numTransInputs, AggState::pertrans, AggState::phase, AggStatePerTransData::sortslot, AggStatePerTransData::sortstates, AggState::tmpcontext, AggStatePerTransData::transfn, AggStatePerTransData::transfn_fcinfo, TupleTableSlot::tts_isnull, TupleTableSlot::tts_nvalid, TupleTableSlot::tts_values, tuplesort_putdatum(), and tuplesort_puttupleslot().

Referenced by agg_fill_hash_table(), and agg_retrieve_direct().

848 {
849  int transno;
850  int setno = 0;
851  int numGroupingSets = Max(aggstate->phase->numsets, 1);
852  int numTrans = aggstate->numtrans;
853  TupleTableSlot *slot = aggstate->evalslot;
854 
855  /* compute input for all aggregates */
856  if (aggstate->evalproj)
857  aggstate->evalslot = ExecProject(aggstate->evalproj);
858 
859  for (transno = 0; transno < numTrans; transno++)
860  {
861  AggStatePerTrans pertrans = &aggstate->pertrans[transno];
862  ExprState *filter = pertrans->aggfilter;
863  int numTransInputs = pertrans->numTransInputs;
864  int i;
865  int inputoff = pertrans->inputoff;
866 
867  /* Skip anything FILTERed out */
868  if (filter)
869  {
870  Datum res;
871  bool isnull;
872 
873  res = ExecEvalExprSwitchContext(filter, aggstate->tmpcontext,
874  &isnull);
875  if (isnull || !DatumGetBool(res))
876  continue;
877  }
878 
879  if (pertrans->numSortCols > 0)
880  {
881  /* DISTINCT and/or ORDER BY case */
882  Assert(slot->tts_nvalid >= (pertrans->numInputs + inputoff));
883 
884  /*
885  * If the transfn is strict, we want to check for nullity before
886  * storing the row in the sorter, to save space if there are a lot
887  * of nulls. Note that we must only check numTransInputs columns,
888  * not numInputs, since nullity in columns used only for sorting
889  * is not relevant here.
890  */
891  if (pertrans->transfn.fn_strict)
892  {
893  for (i = 0; i < numTransInputs; i++)
894  {
895  if (slot->tts_isnull[i + inputoff])
896  break;
897  }
898  if (i < numTransInputs)
899  continue;
900  }
901 
902  for (setno = 0; setno < numGroupingSets; setno++)
903  {
904  /* OK, put the tuple into the tuplesort object */
905  if (pertrans->numInputs == 1)
906  tuplesort_putdatum(pertrans->sortstates[setno],
907  slot->tts_values[inputoff],
908  slot->tts_isnull[inputoff]);
909  else
910  {
911  /*
912  * Copy slot contents, starting from inputoff, into sort
913  * slot.
914  */
915  ExecClearTuple(pertrans->sortslot);
916  memcpy(pertrans->sortslot->tts_values,
917  &slot->tts_values[inputoff],
918  pertrans->numInputs * sizeof(Datum));
919  memcpy(pertrans->sortslot->tts_isnull,
920  &slot->tts_isnull[inputoff],
921  pertrans->numInputs * sizeof(bool));
922  pertrans->sortslot->tts_nvalid = pertrans->numInputs;
923  ExecStoreVirtualTuple(pertrans->sortslot);
924  tuplesort_puttupleslot(pertrans->sortstates[setno], pertrans->sortslot);
925  }
926  }
927  }
928  else
929  {
930  /* We can apply the transition function immediately */
931  FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
932 
933  /* Load values into fcinfo */
934  /* Start from 1, since the 0th arg will be the transition value */
935  Assert(slot->tts_nvalid >= (numTransInputs + inputoff));
936 
937  for (i = 0; i < numTransInputs; i++)
938  {
939  fcinfo->arg[i + 1] = slot->tts_values[i + inputoff];
940  fcinfo->argnull[i + 1] = slot->tts_isnull[i + inputoff];
941  }
942 
943  for (setno = 0; setno < numGroupingSets; setno++)
944  {
945  AggStatePerGroup pergroupstate = &pergroup[transno + (setno * numTrans)];
946 
947  aggstate->current_set = setno;
948 
949  advance_transition_function(aggstate, pertrans, pergroupstate);
950  }
951  }
952  }
953 }
TupleTableSlot * ExecProject(ProjectionInfo *projInfo)
Definition: execQual.c:5214
void tuplesort_putdatum(Tuplesortstate *state, Datum val, bool isNull)
Definition: tuplesort.c:1475
ProjectionInfo * evalproj
Definition: execnodes.h:1908
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
Datum * tts_values
Definition: tuptable.h:125
AggStatePerTrans pertrans
Definition: execnodes.h:1877
int current_set
Definition: execnodes.h:1884
int numtrans
Definition: execnodes.h:1870
Datum ExecEvalExprSwitchContext(ExprState *expression, ExprContext *econtext, bool *isNull)
Definition: execQual.c:4219
ExprContext * tmpcontext
Definition: execnodes.h:1879
FmgrInfo transfn
Definition: nodeAgg.c:247
FunctionCallInfoData transfn_fcinfo
Definition: nodeAgg.c:334
bool fn_strict
Definition: fmgr.h:58
Tuplesortstate ** sortstates
Definition: nodeAgg.c:326
bool * tts_isnull
Definition: tuptable.h:126
#define DatumGetBool(X)
Definition: postgres.h:401
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:78
TupleTableSlot * evalslot
Definition: execnodes.h:1907
AggStatePerPhase phase
Definition: execnodes.h:1872
uintptr_t Datum
Definition: postgres.h:374
static void advance_transition_function(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroupstate)
Definition: nodeAgg.c:726
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
#define Max(x, y)
Definition: c.h:796
#define Assert(condition)
Definition: c.h:671
ExprState * aggfilter
Definition: nodeAgg.c:240
int i
TupleTableSlot * sortslot
Definition: nodeAgg.c:309
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:488
void tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
Definition: tuplesort.c:1354
static void advance_combine_function ( AggState aggstate,
AggStatePerTrans  pertrans,
AggStatePerGroup  pergroupstate 
)
static

Definition at line 1039 of file nodeAgg.c.

References AggState::aggcontexts, FunctionCallInfoData::arg, FunctionCallInfoData::argnull, AggState::curpertrans, AggState::current_set, CurrentMemoryContext, datumCopy(), DatumGetEOHP(), DatumGetPointer, DatumIsReadWriteExpandedObject, DeleteExpandedObject(), ExprContext::ecxt_per_tuple_memory, FmgrInfo::fn_strict, FunctionCallInvoke, FunctionCallInfoData::isnull, MemoryContextGetParent(), MemoryContextSwitchTo(), AggStatePerGroupData::noTransValue, NULL, pfree(), AggState::tmpcontext, AggStatePerTransData::transfn, AggStatePerTransData::transfn_fcinfo, AggStatePerTransData::transtypeByVal, AggStatePerTransData::transtypeLen, AggStatePerGroupData::transValue, and AggStatePerGroupData::transValueIsNull.

Referenced by combine_aggregates().

1042 {
1043  FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
1044  MemoryContext oldContext;
1045  Datum newVal;
1046 
1047  if (pertrans->transfn.fn_strict)
1048  {
1049  /* if we're asked to merge to a NULL state, then do nothing */
1050  if (fcinfo->argnull[1])
1051  return;
1052 
1053  if (pergroupstate->noTransValue)
1054  {
1055  /*
1056  * transValue has not yet been initialized. If pass-by-ref
1057  * datatype we must copy the combining state value into
1058  * aggcontext.
1059  */
1060  if (!pertrans->transtypeByVal)
1061  {
1062  oldContext = MemoryContextSwitchTo(
1063  aggstate->aggcontexts[aggstate->current_set]->ecxt_per_tuple_memory);
1064  pergroupstate->transValue = datumCopy(fcinfo->arg[1],
1065  pertrans->transtypeByVal,
1066  pertrans->transtypeLen);
1067  MemoryContextSwitchTo(oldContext);
1068  }
1069  else
1070  pergroupstate->transValue = fcinfo->arg[1];
1071 
1072  pergroupstate->transValueIsNull = false;
1073  pergroupstate->noTransValue = false;
1074  return;
1075  }
1076  }
1077 
1078  /* We run the combine functions in per-input-tuple memory context */
1079  oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
1080 
1081  /* set up aggstate->curpertrans for AggGetAggref() */
1082  aggstate->curpertrans = pertrans;
1083 
1084  /*
1085  * OK to call the combine function
1086  */
1087  fcinfo->arg[0] = pergroupstate->transValue;
1088  fcinfo->argnull[0] = pergroupstate->transValueIsNull;
1089  fcinfo->isnull = false; /* just in case combine func doesn't set it */
1090 
1091  newVal = FunctionCallInvoke(fcinfo);
1092 
1093  aggstate->curpertrans = NULL;
1094 
1095  /*
1096  * If pass-by-ref datatype, must copy the new value into aggcontext and
1097  * free the prior transValue. But if the combine function returned a
1098  * pointer to its first input, we don't need to do anything. Also, if the
1099  * combine function returned a pointer to a R/W expanded object that is
1100  * already a child of the aggcontext, assume we can adopt that value
1101  * without copying it.
1102  */
1103  if (!pertrans->transtypeByVal &&
1104  DatumGetPointer(newVal) != DatumGetPointer(pergroupstate->transValue))
1105  {
1106  if (!fcinfo->isnull)
1107  {
1109  if (DatumIsReadWriteExpandedObject(newVal,
1110  false,
1111  pertrans->transtypeLen) &&
1112  MemoryContextGetParent(DatumGetEOHP(newVal)->eoh_context) == CurrentMemoryContext)
1113  /* do nothing */ ;
1114  else
1115  newVal = datumCopy(newVal,
1116  pertrans->transtypeByVal,
1117  pertrans->transtypeLen);
1118  }
1119  if (!pergroupstate->transValueIsNull)
1120  {
1121  if (DatumIsReadWriteExpandedObject(pergroupstate->transValue,
1122  false,
1123  pertrans->transtypeLen))
1124  DeleteExpandedObject(pergroupstate->transValue);
1125  else
1126  pfree(DatumGetPointer(pergroupstate->transValue));
1127  }
1128  }
1129 
1130  pergroupstate->transValue = newVal;
1131  pergroupstate->transValueIsNull = fcinfo->isnull;
1132 
1133  MemoryContextSwitchTo(oldContext);
1134 }
MemoryContext MemoryContextGetParent(MemoryContext context)
Definition: mcxt.c:448
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:134
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int current_set
Definition: execnodes.h:1884
ExprContext * tmpcontext
Definition: execnodes.h:1879
FmgrInfo transfn
Definition: nodeAgg.c:247
FunctionCallInfoData transfn_fcinfo
Definition: nodeAgg.c:334
void pfree(void *pointer)
Definition: mcxt.c:992
bool fn_strict
Definition: fmgr.h:58
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:129
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:78
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
uintptr_t Datum
Definition: postgres.h:374
void DeleteExpandedObject(Datum d)
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
ExprContext ** aggcontexts
Definition: execnodes.h:1878
#define NULL
Definition: c.h:226
#define DatumIsReadWriteExpandedObject(d, isnull, typlen)
#define DatumGetPointer(X)
Definition: postgres.h:557
AggStatePerTrans curpertrans
Definition: execnodes.h:1880
static void advance_transition_function ( AggState aggstate,
AggStatePerTrans  pertrans,
AggStatePerGroup  pergroupstate 
)
static

Definition at line 726 of file nodeAgg.c.

References AggState::aggcontexts, FunctionCallInfoData::arg, FunctionCallInfoData::argnull, AggState::curpertrans, AggState::current_set, CurrentMemoryContext, datumCopy(), DatumGetEOHP(), DatumGetPointer, DatumIsReadWriteExpandedObject, DeleteExpandedObject(), ExprContext::ecxt_per_tuple_memory, FmgrInfo::fn_strict, FunctionCallInvoke, i, FunctionCallInfoData::isnull, MemoryContextGetParent(), MemoryContextSwitchTo(), AggStatePerGroupData::noTransValue, NULL, AggStatePerTransData::numTransInputs, pfree(), AggState::tmpcontext, AggStatePerTransData::transfn, AggStatePerTransData::transfn_fcinfo, AggStatePerTransData::transtypeByVal, AggStatePerTransData::transtypeLen, AggStatePerGroupData::transValue, and AggStatePerGroupData::transValueIsNull.

Referenced by advance_aggregates(), process_ordered_aggregate_multi(), and process_ordered_aggregate_single().

729 {
730  FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
731  MemoryContext oldContext;
732  Datum newVal;
733 
734  if (pertrans->transfn.fn_strict)
735  {
736  /*
737  * For a strict transfn, nothing happens when there's a NULL input; we
738  * just keep the prior transValue.
739  */
740  int numTransInputs = pertrans->numTransInputs;
741  int i;
742 
743  for (i = 1; i <= numTransInputs; i++)
744  {
745  if (fcinfo->argnull[i])
746  return;
747  }
748  if (pergroupstate->noTransValue)
749  {
750  /*
751  * transValue has not been initialized. This is the first non-NULL
752  * input value. We use it as the initial value for transValue. (We
753  * already checked that the agg's input type is binary-compatible
754  * with its transtype, so straight copy here is OK.)
755  *
756  * We must copy the datum into aggcontext if it is pass-by-ref. We
757  * do not need to pfree the old transValue, since it's NULL.
758  */
759  oldContext = MemoryContextSwitchTo(
760  aggstate->aggcontexts[aggstate->current_set]->ecxt_per_tuple_memory);
761  pergroupstate->transValue = datumCopy(fcinfo->arg[1],
762  pertrans->transtypeByVal,
763  pertrans->transtypeLen);
764  pergroupstate->transValueIsNull = false;
765  pergroupstate->noTransValue = false;
766  MemoryContextSwitchTo(oldContext);
767  return;
768  }
769  if (pergroupstate->transValueIsNull)
770  {
771  /*
772  * Don't call a strict function with NULL inputs. Note it is
773  * possible to get here despite the above tests, if the transfn is
774  * strict *and* returned a NULL on a prior cycle. If that happens
775  * we will propagate the NULL all the way to the end.
776  */
777  return;
778  }
779  }
780 
781  /* We run the transition functions in per-input-tuple memory context */
782  oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
783 
784  /* set up aggstate->curpertrans for AggGetAggref() */
785  aggstate->curpertrans = pertrans;
786 
787  /*
788  * OK to call the transition function
789  */
790  fcinfo->arg[0] = pergroupstate->transValue;
791  fcinfo->argnull[0] = pergroupstate->transValueIsNull;
792  fcinfo->isnull = false; /* just in case transfn doesn't set it */
793 
794  newVal = FunctionCallInvoke(fcinfo);
795 
796  aggstate->curpertrans = NULL;
797 
798  /*
799  * If pass-by-ref datatype, must copy the new value into aggcontext and
800  * free the prior transValue. But if transfn returned a pointer to its
801  * first input, we don't need to do anything. Also, if transfn returned a
802  * pointer to a R/W expanded object that is already a child of the
803  * aggcontext, assume we can adopt that value without copying it.
804  */
805  if (!pertrans->transtypeByVal &&
806  DatumGetPointer(newVal) != DatumGetPointer(pergroupstate->transValue))
807  {
808  if (!fcinfo->isnull)
809  {
812  false,
813  pertrans->transtypeLen) &&
815  /* do nothing */ ;
816  else
817  newVal = datumCopy(newVal,
818  pertrans->transtypeByVal,
819  pertrans->transtypeLen);
820  }
821  if (!pergroupstate->transValueIsNull)
822  {
823  if (DatumIsReadWriteExpandedObject(pergroupstate->transValue,
824  false,
825  pertrans->transtypeLen))
826  DeleteExpandedObject(pergroupstate->transValue);
827  else
828  pfree(DatumGetPointer(pergroupstate->transValue));
829  }
830  }
831 
832  pergroupstate->transValue = newVal;
833  pergroupstate->transValueIsNull = fcinfo->isnull;
834 
835  MemoryContextSwitchTo(oldContext);
836 }
MemoryContext MemoryContextGetParent(MemoryContext context)
Definition: mcxt.c:448
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:134
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int current_set
Definition: execnodes.h:1884
ExprContext * tmpcontext
Definition: execnodes.h:1879
FmgrInfo transfn
Definition: nodeAgg.c:247
FunctionCallInfoData transfn_fcinfo
Definition: nodeAgg.c:334
void pfree(void *pointer)
Definition: mcxt.c:992
bool fn_strict
Definition: fmgr.h:58
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:129
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:78
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
ExpandedObjectHeader * DatumGetEOHP(Datum d)
Definition: expandeddatum.c:29
uintptr_t Datum
Definition: postgres.h:374
void DeleteExpandedObject(Datum d)
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
ExprContext ** aggcontexts
Definition: execnodes.h:1878
#define NULL
Definition: c.h:226
#define DatumIsReadWriteExpandedObject(d, isnull, typlen)
#define DatumGetPointer(X)
Definition: postgres.h:557
int i
AggStatePerTrans curpertrans
Definition: execnodes.h:1880
static void agg_fill_hash_table ( AggState aggstate)
static

Definition at line 2253 of file nodeAgg.c.

References TupleHashEntryData::additional, advance_aggregates(), AggState::aggsplit, combine_aggregates(), DO_AGGSPLIT_COMBINE, ExprContext::ecxt_outertuple, fetch_input_tuple(), AggState::hashiter, AggState::hashtable, lookup_hash_entry(), ResetExprContext, ResetTupleHashIterator, AggState::table_filled, AggState::tmpcontext, and TupIsNull.

Referenced by ExecAgg().

2254 {
2255  ExprContext *tmpcontext;
2256  TupleHashEntryData *entry;
2257  TupleTableSlot *outerslot;
2258 
2259  /*
2260  * get state info from node
2261  *
2262  * tmpcontext is the per-input-tuple expression context
2263  */
2264  tmpcontext = aggstate->tmpcontext;
2265 
2266  /*
2267  * Process each outer-plan tuple, and then fetch the next one, until we
2268  * exhaust the outer plan.
2269  */
2270  for (;;)
2271  {
2272  outerslot = fetch_input_tuple(aggstate);
2273  if (TupIsNull(outerslot))
2274  break;
2275  /* set up for advance_aggregates call */
2276  tmpcontext->ecxt_outertuple = outerslot;
2277 
2278  /* Find or build hashtable entry for this tuple's group */
2279  entry = lookup_hash_entry(aggstate, outerslot);
2280 
2281  /* Advance the aggregates */
2282  if (DO_AGGSPLIT_COMBINE(aggstate->aggsplit))
2283  combine_aggregates(aggstate, (AggStatePerGroup) entry->additional);
2284  else
2285  advance_aggregates(aggstate, (AggStatePerGroup) entry->additional);
2286 
2287  /* Reset per-input-tuple context after each tuple */
2288  ResetExprContext(tmpcontext);
2289  }
2290 
2291  aggstate->table_filled = true;
2292  /* Initialize to walk the hash table */
2293  ResetTupleHashIterator(aggstate->hashtable, &aggstate->hashiter);
2294 }
static TupleTableSlot * fetch_input_tuple(AggState *aggstate)
Definition: nodeAgg.c:575
AggSplit aggsplit
Definition: execnodes.h:1871
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:760
ExprContext * tmpcontext
Definition: execnodes.h:1879
bool table_filled
Definition: execnodes.h:1904
TupleHashIterator hashiter
Definition: execnodes.h:1905
#define TupIsNull(slot)
Definition: tuptable.h:138
static void advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
Definition: nodeAgg.c:847
TupleHashTable hashtable
Definition: execnodes.h:1898
#define ResetTupleHashIterator(htable, iter)
Definition: execnodes.h:558
static TupleHashEntryData * lookup_hash_entry(AggState *aggstate, TupleTableSlot *inputslot)
Definition: nodeAgg.c:1849
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:130
static void combine_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
Definition: nodeAgg.c:963
#define ResetExprContext(econtext)
Definition: executor.h:332
static TupleTableSlot * agg_retrieve_direct ( AggState aggstate)
static

Definition at line 1929 of file nodeAgg.c.

References advance_aggregates(), AggState::agg_done, AGG_PLAIN, AGG_SORTED, AggState::aggcontexts, AggStatePerPhaseData::aggnode, AggState::aggsplit, Agg::aggstrategy, Assert, combine_aggregates(), AggState::current_phase, DO_AGGSPLIT_COMBINE, ExprContext::ecxt_outertuple, ExprContext::ecxt_per_tuple_memory, AggStatePerPhaseData::eqfunctions, ExecCopySlotTuple(), ExecStoreTuple(), execTuplesMatch(), fetch_input_tuple(), finalize_aggregates(), AggState::grp_firstTuple, Agg::grpColIdx, AggStatePerPhaseData::gset_lengths, i, initialize_aggregates(), initialize_phase(), AggState::input_done, InvalidBuffer, Max, NULL, Agg::numCols, AggState::numphases, AggStatePerPhaseData::numsets, AggState::peragg, AggState::pergroup, AggState::phase, prepare_projection_slot(), project_aggregates(), AggState::projected_set, ScanState::ps, PlanState::ps_ExprContext, ReScanExprContext(), ResetExprContext, AggState::ss, ScanState::ss_ScanTupleSlot, AggState::tmpcontext, and TupIsNull.

Referenced by ExecAgg().

1930 {
1931  Agg *node = aggstate->phase->aggnode;
1932  ExprContext *econtext;
1933  ExprContext *tmpcontext;
1934  AggStatePerAgg peragg;
1935  AggStatePerGroup pergroup;
1936  TupleTableSlot *outerslot;
1937  TupleTableSlot *firstSlot;
1938  TupleTableSlot *result;
1939  bool hasGroupingSets = aggstate->phase->numsets > 0;
1940  int numGroupingSets = Max(aggstate->phase->numsets, 1);
1941  int currentSet;
1942  int nextSetSize;
1943  int numReset;
1944  int i;
1945 
1946  /*
1947  * get state info from node
1948  *
1949  * econtext is the per-output-tuple expression context
1950  *
1951  * tmpcontext is the per-input-tuple expression context
1952  */
1953  econtext = aggstate->ss.ps.ps_ExprContext;
1954  tmpcontext = aggstate->tmpcontext;
1955 
1956  peragg = aggstate->peragg;
1957  pergroup = aggstate->pergroup;
1958  firstSlot = aggstate->ss.ss_ScanTupleSlot;
1959 
1960  /*
1961  * We loop retrieving groups until we find one matching
1962  * aggstate->ss.ps.qual
1963  *
1964  * For grouping sets, we have the invariant that aggstate->projected_set
1965  * is either -1 (initial call) or the index (starting from 0) in
1966  * gset_lengths for the group we just completed (either by projecting a
1967  * row or by discarding it in the qual).
1968  */
1969  while (!aggstate->agg_done)
1970  {
1971  /*
1972  * Clear the per-output-tuple context for each group, as well as
1973  * aggcontext (which contains any pass-by-ref transvalues of the old
1974  * group). Some aggregate functions store working state in child
1975  * contexts; those now get reset automatically without us needing to
1976  * do anything special.
1977  *
1978  * We use ReScanExprContext not just ResetExprContext because we want
1979  * any registered shutdown callbacks to be called. That allows
1980  * aggregate functions to ensure they've cleaned up any non-memory
1981  * resources.
1982  */
1983  ReScanExprContext(econtext);
1984 
1985  /*
1986  * Determine how many grouping sets need to be reset at this boundary.
1987  */
1988  if (aggstate->projected_set >= 0 &&
1989  aggstate->projected_set < numGroupingSets)
1990  numReset = aggstate->projected_set + 1;
1991  else
1992  numReset = numGroupingSets;
1993 
1994  /*
1995  * numReset can change on a phase boundary, but that's OK; we want to
1996  * reset the contexts used in _this_ phase, and later, after possibly
1997  * changing phase, initialize the right number of aggregates for the
1998  * _new_ phase.
1999  */
2000 
2001  for (i = 0; i < numReset; i++)
2002  {
2003  ReScanExprContext(aggstate->aggcontexts[i]);
2004  }
2005 
2006  /*
2007  * Check if input is complete and there are no more groups to project
2008  * in this phase; move to next phase or mark as done.
2009  */
2010  if (aggstate->input_done == true &&
2011  aggstate->projected_set >= (numGroupingSets - 1))
2012  {
2013  if (aggstate->current_phase < aggstate->numphases - 1)
2014  {
2015  initialize_phase(aggstate, aggstate->current_phase + 1);
2016  aggstate->input_done = false;
2017  aggstate->projected_set = -1;
2018  numGroupingSets = Max(aggstate->phase->numsets, 1);
2019  node = aggstate->phase->aggnode;
2020  numReset = numGroupingSets;
2021  }
2022  else
2023  {
2024  aggstate->agg_done = true;
2025  break;
2026  }
2027  }
2028 
2029  /*
2030  * Get the number of columns in the next grouping set after the last
2031  * projected one (if any). This is the number of columns to compare to
2032  * see if we reached the boundary of that set too.
2033  */
2034  if (aggstate->projected_set >= 0 &&
2035  aggstate->projected_set < (numGroupingSets - 1))
2036  nextSetSize = aggstate->phase->gset_lengths[aggstate->projected_set + 1];
2037  else
2038  nextSetSize = 0;
2039 
2040  /*----------
2041  * If a subgroup for the current grouping set is present, project it.
2042  *
2043  * We have a new group if:
2044  * - we're out of input but haven't projected all grouping sets
2045  * (checked above)
2046  * OR
2047  * - we already projected a row that wasn't from the last grouping
2048  * set
2049  * AND
2050  * - the next grouping set has at least one grouping column (since
2051  * empty grouping sets project only once input is exhausted)
2052  * AND
2053  * - the previous and pending rows differ on the grouping columns
2054  * of the next grouping set
2055  *----------
2056  */
2057  if (aggstate->input_done ||
2058  (node->aggstrategy == AGG_SORTED &&
2059  aggstate->projected_set != -1 &&
2060  aggstate->projected_set < (numGroupingSets - 1) &&
2061  nextSetSize > 0 &&
2062  !execTuplesMatch(econtext->ecxt_outertuple,
2063  tmpcontext->ecxt_outertuple,
2064  nextSetSize,
2065  node->grpColIdx,
2066  aggstate->phase->eqfunctions,
2067  tmpcontext->ecxt_per_tuple_memory)))
2068  {
2069  aggstate->projected_set += 1;
2070 
2071  Assert(aggstate->projected_set < numGroupingSets);
2072  Assert(nextSetSize > 0 || aggstate->input_done);
2073  }
2074  else
2075  {
2076  /*
2077  * We no longer care what group we just projected, the next
2078  * projection will always be the first (or only) grouping set
2079  * (unless the input proves to be empty).
2080  */
2081  aggstate->projected_set = 0;
2082 
2083  /*
2084  * If we don't already have the first tuple of the new group,
2085  * fetch it from the outer plan.
2086  */
2087  if (aggstate->grp_firstTuple == NULL)
2088  {
2089  outerslot = fetch_input_tuple(aggstate);
2090  if (!TupIsNull(outerslot))
2091  {
2092  /*
2093  * Make a copy of the first input tuple; we will use this
2094  * for comparisons (in group mode) and for projection.
2095  */
2096  aggstate->grp_firstTuple = ExecCopySlotTuple(outerslot);
2097  }
2098  else
2099  {
2100  /* outer plan produced no tuples at all */
2101  if (hasGroupingSets)
2102  {
2103  /*
2104  * If there was no input at all, we need to project
2105  * rows only if there are grouping sets of size 0.
2106  * Note that this implies that there can't be any
2107  * references to ungrouped Vars, which would otherwise
2108  * cause issues with the empty output slot.
2109  *
2110  * XXX: This is no longer true, we currently deal with
2111  * this in finalize_aggregates().
2112  */
2113  aggstate->input_done = true;
2114 
2115  while (aggstate->phase->gset_lengths[aggstate->projected_set] > 0)
2116  {
2117  aggstate->projected_set += 1;
2118  if (aggstate->projected_set >= numGroupingSets)
2119  {
2120  /*
2121  * We can't set agg_done here because we might
2122  * have more phases to do, even though the
2123  * input is empty. So we need to restart the
2124  * whole outer loop.
2125  */
2126  break;
2127  }
2128  }
2129 
2130  if (aggstate->projected_set >= numGroupingSets)
2131  continue;
2132  }
2133  else
2134  {
2135  aggstate->agg_done = true;
2136  /* If we are grouping, we should produce no tuples too */
2137  if (node->aggstrategy != AGG_PLAIN)
2138  return NULL;
2139  }
2140  }
2141  }
2142 
2143  /*
2144  * Initialize working state for a new input tuple group.
2145  */
2146  initialize_aggregates(aggstate, pergroup, numReset);
2147 
2148  if (aggstate->grp_firstTuple != NULL)
2149  {
2150  /*
2151  * Store the copied first input tuple in the tuple table slot
2152  * reserved for it. The tuple will be deleted when it is
2153  * cleared from the slot.
2154  */
2155  ExecStoreTuple(aggstate->grp_firstTuple,
2156  firstSlot,
2157  InvalidBuffer,
2158  true);
2159  aggstate->grp_firstTuple = NULL; /* don't keep two
2160  * pointers */
2161 
2162  /* set up for first advance_aggregates call */
2163  tmpcontext->ecxt_outertuple = firstSlot;
2164 
2165  /*
2166  * Process each outer-plan tuple, and then fetch the next one,
2167  * until we exhaust the outer plan or cross a group boundary.
2168  */
2169  for (;;)
2170  {
2171  if (DO_AGGSPLIT_COMBINE(aggstate->aggsplit))
2172  combine_aggregates(aggstate, pergroup);
2173  else
2174  advance_aggregates(aggstate, pergroup);
2175 
2176  /* Reset per-input-tuple context after each tuple */
2177  ResetExprContext(tmpcontext);
2178 
2179  outerslot = fetch_input_tuple(aggstate);
2180  if (TupIsNull(outerslot))
2181  {
2182  /* no more outer-plan tuples available */
2183  if (hasGroupingSets)
2184  {
2185  aggstate->input_done = true;
2186  break;
2187  }
2188  else
2189  {
2190  aggstate->agg_done = true;
2191  break;
2192  }
2193  }
2194  /* set up for next advance_aggregates call */
2195  tmpcontext->ecxt_outertuple = outerslot;
2196 
2197  /*
2198  * If we are grouping, check whether we've crossed a group
2199  * boundary.
2200  */
2201  if (node->aggstrategy == AGG_SORTED)
2202  {
2203  if (!execTuplesMatch(firstSlot,
2204  outerslot,
2205  node->numCols,
2206  node->grpColIdx,
2207  aggstate->phase->eqfunctions,
2208  tmpcontext->ecxt_per_tuple_memory))
2209  {
2210  aggstate->grp_firstTuple = ExecCopySlotTuple(outerslot);
2211  break;
2212  }
2213  }
2214  }
2215  }
2216 
2217  /*
2218  * Use the representative input tuple for any references to
2219  * non-aggregated input columns in aggregate direct args, the node
2220  * qual, and the tlist. (If we are not grouping, and there are no
2221  * input rows at all, we will come here with an empty firstSlot
2222  * ... but if not grouping, there can't be any references to
2223  * non-aggregated input columns, so no problem.)
2224  */
2225  econtext->ecxt_outertuple = firstSlot;
2226  }
2227 
2228  Assert(aggstate->projected_set >= 0);
2229 
2230  currentSet = aggstate->projected_set;
2231 
2232  prepare_projection_slot(aggstate, econtext->ecxt_outertuple, currentSet);
2233 
2234  finalize_aggregates(aggstate, peragg, pergroup, currentSet);
2235 
2236  /*
2237  * If there's no row to project right now, we must continue rather
2238  * than returning a null since there might be more groups.
2239  */
2240  result = project_aggregates(aggstate);
2241  if (result)
2242  return result;
2243  }
2244 
2245  /* No more groups */
2246  return NULL;
2247 }
static TupleTableSlot * fetch_input_tuple(AggState *aggstate)
Definition: nodeAgg.c:575
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:320
int numCols
Definition: plannodes.h:735
AttrNumber * grpColIdx
Definition: plannodes.h:736
bool agg_done
Definition: execnodes.h:1882
ScanState ss
Definition: execnodes.h:1867
ExprContext * ps_ExprContext
Definition: execnodes.h:1078
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:134
FmgrInfo * eqfunctions
Definition: nodeAgg.c:438
#define InvalidBuffer
Definition: buf.h:25
int current_phase
Definition: execnodes.h:1874
bool execTuplesMatch(TupleTableSlot *slot1, TupleTableSlot *slot2, int numCols, AttrNumber *matchColIdx, FmgrInfo *eqfunctions, MemoryContext evalContext)
Definition: execGrouping.c:69
AggSplit aggsplit
Definition: execnodes.h:1871
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1291
int projected_set
Definition: execnodes.h:1883
HeapTuple grp_firstTuple
Definition: execnodes.h:1896
static TupleTableSlot * project_aggregates(AggState *aggstate)
Definition: nodeAgg.c:1635
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:760
ExprContext * tmpcontext
Definition: execnodes.h:1879
static void prepare_projection_slot(AggState *aggstate, TupleTableSlot *slot, int currentSet)
Definition: nodeAgg.c:1524
PlanState ps
Definition: execnodes.h:1288
static void initialize_aggregates(AggState *aggstate, AggStatePerGroup pergroup, int numReset)
Definition: nodeAgg.c:685
AggStrategy aggstrategy
Definition: plannodes.h:733
#define TupIsNull(slot)
Definition: tuptable.h:138
HeapTuple ExecCopySlotTuple(TupleTableSlot *slot)
Definition: execTuples.c:545
static void advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
Definition: nodeAgg.c:847
bool input_done
Definition: execnodes.h:1881
AggStatePerPhase phase
Definition: execnodes.h:1872
AggStatePerGroup pergroup
Definition: execnodes.h:1895
static void initialize_phase(AggState *aggstate, int newphase)
Definition: nodeAgg.c:508
#define Max(x, y)
Definition: c.h:796
ExprContext ** aggcontexts
Definition: execnodes.h:1878
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:130
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
void ReScanExprContext(ExprContext *econtext)
Definition: execUtils.c:366
int numphases
Definition: execnodes.h:1873
AggStatePerAgg peragg
Definition: execnodes.h:1876
int i
static void finalize_aggregates(AggState *aggstate, AggStatePerAgg peragg, AggStatePerGroup pergroup, int currentSet)
Definition: nodeAgg.c:1567
static void combine_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
Definition: nodeAgg.c:963
Definition: plannodes.h:730
#define ResetExprContext(econtext)
Definition: executor.h:332
static TupleTableSlot * agg_retrieve_hash_table ( AggState aggstate)
static

Definition at line 2300 of file nodeAgg.c.

References TupleHashEntryData::additional, AggState::agg_done, ExprContext::ecxt_outertuple, ExecClearTuple(), ExecStoreMinimalTuple(), ExecStoreVirtualTuple(), finalize_aggregates(), TupleHashEntryData::firstTuple, AggState::hashGrpColIdxInput, AggState::hashiter, AggState::hashslot, AggState::hashtable, i, tupleDesc::natts, NULL, AggState::numhashGrpCols, AggState::peragg, project_aggregates(), ScanState::ps, PlanState::ps_ExprContext, ResetExprContext, ScanTupleHashTable, slot_getallattrs(), AggState::ss, ScanState::ss_ScanTupleSlot, TRUE, TupleTableSlot::tts_isnull, TupleTableSlot::tts_tupleDescriptor, and TupleTableSlot::tts_values.

Referenced by ExecAgg().

2301 {
2302  ExprContext *econtext;
2303  AggStatePerAgg peragg;
2304  AggStatePerGroup pergroup;
2305  TupleHashEntryData *entry;
2306  TupleTableSlot *firstSlot;
2307  TupleTableSlot *result;
2308  TupleTableSlot *hashslot;
2309 
2310  /*
2311  * get state info from node
2312  */
2313  /* econtext is the per-output-tuple expression context */
2314  econtext = aggstate->ss.ps.ps_ExprContext;
2315  peragg = aggstate->peragg;
2316  firstSlot = aggstate->ss.ss_ScanTupleSlot;
2317  hashslot = aggstate->hashslot;
2318 
2319 
2320  /*
2321  * We loop retrieving groups until we find one satisfying
2322  * aggstate->ss.ps.qual
2323  */
2324  while (!aggstate->agg_done)
2325  {
2326  int i;
2327 
2328  /*
2329  * Find the next entry in the hash table
2330  */
2331  entry = ScanTupleHashTable(aggstate->hashtable, &aggstate->hashiter);
2332  if (entry == NULL)
2333  {
2334  /* No more entries in hashtable, so done */
2335  aggstate->agg_done = TRUE;
2336  return NULL;
2337  }
2338 
2339  /*
2340  * Clear the per-output-tuple context for each group
2341  *
2342  * We intentionally don't use ReScanExprContext here; if any aggs have
2343  * registered shutdown callbacks, they mustn't be called yet, since we
2344  * might not be done with that agg.
2345  */
2346  ResetExprContext(econtext);
2347 
2348  /*
2349  * Transform representative tuple back into one with the right
2350  * columns.
2351  */
2352  ExecStoreMinimalTuple(entry->firstTuple, hashslot, false);
2353  slot_getallattrs(hashslot);
2354 
2355  ExecClearTuple(firstSlot);
2356  memset(firstSlot->tts_isnull, true,
2357  firstSlot->tts_tupleDescriptor->natts * sizeof(bool));
2358 
2359  for (i = 0; i < aggstate->numhashGrpCols; i++)
2360  {
2361  int varNumber = aggstate->hashGrpColIdxInput[i] - 1;
2362 
2363  firstSlot->tts_values[varNumber] = hashslot->tts_values[i];
2364  firstSlot->tts_isnull[varNumber] = hashslot->tts_isnull[i];
2365  }
2366  ExecStoreVirtualTuple(firstSlot);
2367 
2368  pergroup = (AggStatePerGroup) entry->additional;
2369 
2370  finalize_aggregates(aggstate, peragg, pergroup, 0);
2371 
2372  /*
2373  * Use the representative input tuple for any references to
2374  * non-aggregated input columns in the qual and tlist.
2375  */
2376  econtext->ecxt_outertuple = firstSlot;
2377 
2378  result = project_aggregates(aggstate);
2379  if (result)
2380  return result;
2381  }
2382 
2383  /* No more groups */
2384  return NULL;
2385 }
struct AggStatePerGroupData * AggStatePerGroup
Definition: execnodes.h:1862
#define ScanTupleHashTable(htable, iter)
Definition: execnodes.h:560
TupleTableSlot * ExecStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot, bool shouldFree)
Definition: execTuples.c:384
bool agg_done
Definition: execnodes.h:1882
ScanState ss
Definition: execnodes.h:1867
ExprContext * ps_ExprContext
Definition: execnodes.h:1078
MinimalTuple firstTuple
Definition: execnodes.h:515
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
AttrNumber * hashGrpColIdxInput
Definition: execnodes.h:1902
Datum * tts_values
Definition: tuptable.h:125
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1291
static TupleTableSlot * project_aggregates(AggState *aggstate)
Definition: nodeAgg.c:1635
int natts
Definition: tupdesc.h:73
PlanState ps
Definition: execnodes.h:1288
TupleHashIterator hashiter
Definition: execnodes.h:1905
bool * tts_isnull
Definition: tuptable.h:126
void slot_getallattrs(TupleTableSlot *slot)
Definition: heaptuple.c:1239
TupleHashTable hashtable
Definition: execnodes.h:1898
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:121
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:130
#define NULL
Definition: c.h:226
TupleTableSlot * hashslot
Definition: execnodes.h:1899
int numhashGrpCols
Definition: execnodes.h:1900
AggStatePerAgg peragg
Definition: execnodes.h:1876
int i
static void finalize_aggregates(AggState *aggstate, AggStatePerAgg peragg, AggStatePerGroup pergroup, int currentSet)
Definition: nodeAgg.c:1567
#define TRUE
Definition: c.h:214
#define ResetExprContext(econtext)
Definition: executor.h:332
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:488
int AggCheckCallContext ( FunctionCallInfo  fcinfo,
MemoryContext aggcontext 
)

Definition at line 3660 of file nodeAgg.c.

References AGG_CONTEXT_AGGREGATE, AGG_CONTEXT_WINDOW, AggState::aggcontexts, FunctionCallInfoData::context, AggState::current_set, ExprContext::ecxt_per_tuple_memory, IsA, and NULL.

Referenced by array_agg_array_finalfn(), array_agg_array_transfn(), array_agg_finalfn(), array_agg_transfn(), bytea_string_agg_finalfn(), fetch_array_arg_replace_nulls(), float4_accum(), float8_accum(), float8_combine(), float8_regr_accum(), float8_regr_combine(), hypothetical_dense_rank_final(), hypothetical_rank_common(), int2_avg_accum(), int2_avg_accum_inv(), int2_sum(), int4_avg_accum(), int4_avg_accum_inv(), int4_avg_combine(), int4_sum(), int8_avg_combine(), int8_avg_deserialize(), int8_avg_serialize(), int8dec(), int8inc(), json_agg_finalfn(), json_agg_transfn(), json_object_agg_finalfn(), json_object_agg_transfn(), jsonb_agg_finalfn(), jsonb_agg_transfn(), jsonb_object_agg_finalfn(), jsonb_object_agg_transfn(), makeBoolAggState(), makeNumericAggState(), makeStringAggState(), mode_final(), numeric_avg_combine(), numeric_avg_deserialize(), numeric_avg_serialize(), numeric_combine(), numeric_deserialize(), numeric_poly_combine(), numeric_poly_deserialize(), numeric_poly_serialize(), numeric_serialize(), ordered_set_startup(), percentile_cont_final_common(), percentile_cont_multi_final_common(), percentile_disc_final(), percentile_disc_multi_final(), and string_agg_finalfn().

3661 {
3662  if (fcinfo->context && IsA(fcinfo->context, AggState))
3663  {
3664  if (aggcontext)
3665  {
3666  AggState *aggstate = ((AggState *) fcinfo->context);
3667  ExprContext *cxt = aggstate->aggcontexts[aggstate->current_set];
3668 
3669  *aggcontext = cxt->ecxt_per_tuple_memory;
3670  }
3671  return AGG_CONTEXT_AGGREGATE;
3672  }
3673  if (fcinfo->context && IsA(fcinfo->context, WindowAggState))
3674  {
3675  if (aggcontext)
3676  *aggcontext = ((WindowAggState *) fcinfo->context)->curaggcontext;
3677  return AGG_CONTEXT_WINDOW;
3678  }
3679 
3680  /* this is just to prevent "uninitialized variable" warnings */
3681  if (aggcontext)
3682  *aggcontext = NULL;
3683  return 0;
3684 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
fmNodePtr context
Definition: fmgr.h:72
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:134
int current_set
Definition: execnodes.h:1884
#define AGG_CONTEXT_AGGREGATE
Definition: fmgr.h:664
ExprContext ** aggcontexts
Definition: execnodes.h:1878
#define NULL
Definition: c.h:226
#define AGG_CONTEXT_WINDOW
Definition: fmgr.h:665
Aggref* AggGetAggref ( FunctionCallInfo  fcinfo)

Definition at line 3697 of file nodeAgg.c.

References AggStatePerTransData::aggref, FunctionCallInfoData::context, IsA, and NULL.

Referenced by ordered_set_startup().

3698 {
3699  if (fcinfo->context && IsA(fcinfo->context, AggState))
3700  {
3701  AggStatePerTrans curpertrans;
3702 
3703  curpertrans = ((AggState *) fcinfo->context)->curpertrans;
3704 
3705  if (curpertrans)
3706  return curpertrans->aggref;
3707  }
3708  return NULL;
3709 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
fmNodePtr context
Definition: fmgr.h:72
#define NULL
Definition: c.h:226
MemoryContext AggGetTempMemoryContext ( FunctionCallInfo  fcinfo)

Definition at line 3722 of file nodeAgg.c.

References FunctionCallInfoData::context, ExprContext::ecxt_per_tuple_memory, IsA, NULL, and AggState::tmpcontext.

Referenced by hypothetical_dense_rank_final().

3723 {
3724  if (fcinfo->context && IsA(fcinfo->context, AggState))
3725  {
3726  AggState *aggstate = (AggState *) fcinfo->context;
3727 
3728  return aggstate->tmpcontext->ecxt_per_tuple_memory;
3729  }
3730  return NULL;
3731 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
fmNodePtr context
Definition: fmgr.h:72
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:134
ExprContext * tmpcontext
Definition: execnodes.h:1879
#define NULL
Definition: c.h:226
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
void AggRegisterCallback ( FunctionCallInfo  fcinfo,
ExprContextCallbackFunction  func,
Datum  arg 
)

Definition at line 3749 of file nodeAgg.c.

References AggState::aggcontexts, FunctionCallInfoData::context, AggState::current_set, elog, ERROR, IsA, and RegisterExprContextCallback().

Referenced by ordered_set_startup().

3752 {
3753  if (fcinfo->context && IsA(fcinfo->context, AggState))
3754  {
3755  AggState *aggstate = (AggState *) fcinfo->context;
3756  ExprContext *cxt = aggstate->aggcontexts[aggstate->current_set];
3757 
3758  RegisterExprContextCallback(cxt, func, arg);
3759 
3760  return;
3761  }
3762  elog(ERROR, "aggregate function cannot register a callback in this context");
3763 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
fmNodePtr context
Definition: fmgr.h:72
int current_set
Definition: execnodes.h:1884
#define ERROR
Definition: elog.h:43
ExprContext ** aggcontexts
Definition: execnodes.h:1878
void RegisterExprContextCallback(ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
Definition: execUtils.c:871
void * arg
#define elog
Definition: elog.h:219
static void build_hash_table ( AggState aggstate)
static

Definition at line 1711 of file nodeAgg.c.

References AGG_HASHED, AggState::aggcontexts, AggState::aggsplit, Agg::aggstrategy, Assert, BuildTupleHashTable(), DO_AGGSPLIT_SKIPFINAL, ExprContext::ecxt_per_tuple_memory, AggStatePerPhaseData::eqfunctions, AggState::hashfunctions, AggState::hashGrpColIdxHash, AggState::hashtable, AggState::numaggs, Agg::numCols, Agg::numGroups, AggState::phase, PlanState::plan, ScanState::ps, AggState::ss, and AggState::tmpcontext.

Referenced by ExecInitAgg(), and ExecReScanAgg().

1712 {
1713  Agg *node = (Agg *) aggstate->ss.ps.plan;
1714  MemoryContext tmpmem = aggstate->tmpcontext->ecxt_per_tuple_memory;
1715  Size additionalsize;
1716 
1717  Assert(node->aggstrategy == AGG_HASHED);
1718  Assert(node->numGroups > 0);
1719 
1720  additionalsize = aggstate->numaggs * sizeof(AggStatePerGroupData);
1721 
1722  aggstate->hashtable = BuildTupleHashTable(node->numCols,
1723  aggstate->hashGrpColIdxHash,
1724  aggstate->phase->eqfunctions,
1725  aggstate->hashfunctions,
1726  node->numGroups,
1727  additionalsize,
1728  aggstate->aggcontexts[0]->ecxt_per_tuple_memory,
1729  tmpmem,
1730  DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit));
1731 }
int numCols
Definition: plannodes.h:735
int numaggs
Definition: execnodes.h:1869
ScanState ss
Definition: execnodes.h:1867
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:134
FmgrInfo * eqfunctions
Definition: nodeAgg.c:438
AggSplit aggsplit
Definition: execnodes.h:1871
FmgrInfo * hashfunctions
Definition: execnodes.h:1875
struct AggStatePerGroupData AggStatePerGroupData
ExprContext * tmpcontext
Definition: execnodes.h:1879
PlanState ps
Definition: execnodes.h:1288
AggStrategy aggstrategy
Definition: plannodes.h:733
TupleHashTable hashtable
Definition: execnodes.h:1898
AttrNumber * hashGrpColIdxHash
Definition: execnodes.h:1903
AggStatePerPhase phase
Definition: execnodes.h:1872
Plan * plan
Definition: execnodes.h:1047
ExprContext ** aggcontexts
Definition: execnodes.h:1878
#define Assert(condition)
Definition: c.h:671
size_t Size
Definition: c.h:353
long numGroups
Definition: plannodes.h:738
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:761
TupleHashTable BuildTupleHashTable(int numCols, AttrNumber *keyColIdx, FmgrInfo *eqfunctions, FmgrInfo *hashfunctions, long nbuckets, Size additionalsize, MemoryContext tablecxt, MemoryContext tempcxt, bool use_variable_hash_iv)
Definition: execGrouping.c:290
Definition: plannodes.h:730
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 
)
static

Definition at line 3047 of file nodeAgg.c.

References AGG_HASHED, AggStatePerTransData::aggCollation, AggStatePerTransData::aggdirectargs, Aggref::aggdirectargs, Aggref::aggdistinct, AggStatePerTransData::aggfilter, Aggref::aggfilter, Aggref::aggfnoid, Aggref::aggkind, AGGKIND_IS_ORDERED_SET, Aggref::aggorder, AggStatePerTransData::aggref, AggState::aggsplit, AggStatePerTransData::aggtranstype, Aggref::aggvariadic, Aggref::args, Assert, build_aggregate_combinefn_expr(), build_aggregate_deserialfn_expr(), build_aggregate_serialfn_expr(), build_aggregate_transfn_expr(), AggStatePerTransData::deserialfn, AggStatePerTransData::deserialfn_fcinfo, AggStatePerTransData::deserialfn_oid, DO_AGGSPLIT_COMBINE, SortGroupClause::eqop, AggStatePerTransData::equalfns, ereport, errcode(), errmsg(), ERROR, ExecInitExpr(), ExecInitExtraTupleSlot(), ExecSetSlotDescriptor(), ExecTypeFromTL(), TargetEntry::expr, exprCollation(), fmgr_info(), fmgr_info_set_expr, FmgrInfo::fn_strict, get_opcode(), get_sortgroupclause_tle(), get_typlenbyval(), i, InitFunctionCallInfoData, AggStatePerTransData::initValue, initValue(), AggStatePerTransData::initValueIsNull, Aggref::inputcollid, AggStatePerTransData::inputtypeByVal, AggStatePerTransData::inputtypeLen, INTERNALOID, InvalidOid, IsBinaryCoercible(), lfirst, list_length(), Max, AggState::maxsets, NIL, NULL, SortGroupClause::nulls_first, AggState::numaggs, AggStatePerTransData::numDistinctCols, AggStatePerTransData::numInputs, AggStatePerTransData::numSortCols, AggStatePerTransData::numTransInputs, OidIsValid, palloc(), palloc0(), PlanState::plan, ScanState::ps, TargetEntry::resno, AggStatePerTransData::serialfn, AggStatePerTransData::serialfn_fcinfo, AggStatePerTransData::serialfn_oid, AggStatePerTransData::sortColIdx, AggStatePerTransData::sortCollations, AggStatePerTransData::sortdesc, AggStatePerTransData::sortNullsFirst, SortGroupClause::sortop, AggStatePerTransData::sortOperators, AggStatePerTransData::sortslot, AggStatePerTransData::sortstates, AggState::ss, AggStatePerTransData::transfn, AggStatePerTransData::transfn_fcinfo, AggStatePerTransData::transfn_oid, AggStatePerTransData::transtypeByVal, AggStatePerTransData::transtypeLen, and AggStatePerTransData::uniqslot.

Referenced by ExecInitAgg().

3054 {
3055  int numGroupingSets = Max(aggstate->maxsets, 1);
3056  Expr *serialfnexpr = NULL;
3057  Expr *deserialfnexpr = NULL;
3058  ListCell *lc;
3059  int numInputs;
3060  int numDirectArgs;
3061  List *sortlist;
3062  int numSortCols;
3063  int numDistinctCols;
3064  int naggs;
3065  int i;
3066 
3067  /* Begin filling in the pertrans data */
3068  pertrans->aggref = aggref;
3069  pertrans->aggCollation = aggref->inputcollid;
3070  pertrans->transfn_oid = aggtransfn;
3071  pertrans->serialfn_oid = aggserialfn;
3072  pertrans->deserialfn_oid = aggdeserialfn;
3073  pertrans->initValue = initValue;
3074  pertrans->initValueIsNull = initValueIsNull;
3075 
3076  /* Count the "direct" arguments, if any */
3077  numDirectArgs = list_length(aggref->aggdirectargs);
3078 
3079  /* Count the number of aggregated input columns */
3080  pertrans->numInputs = numInputs = list_length(aggref->args);
3081 
3082  pertrans->aggtranstype = aggtranstype;
3083 
3084  /* Detect how many arguments to pass to the transfn */
3085  if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
3086  pertrans->numTransInputs = numInputs;
3087  else
3088  pertrans->numTransInputs = numArguments;
3089 
3090  /*
3091  * When combining states, we have no use at all for the aggregate
3092  * function's transfn. Instead we use the combinefn. In this case, the
3093  * transfn and transfn_oid fields of pertrans refer to the combine
3094  * function rather than the transition function.
3095  */
3096  if (DO_AGGSPLIT_COMBINE(aggstate->aggsplit))
3097  {
3098  Expr *combinefnexpr;
3099 
3100  build_aggregate_combinefn_expr(aggtranstype,
3101  aggref->inputcollid,
3102  aggtransfn,
3103  &combinefnexpr);
3104  fmgr_info(aggtransfn, &pertrans->transfn);
3105  fmgr_info_set_expr((Node *) combinefnexpr, &pertrans->transfn);
3106 
3108  &pertrans->transfn,
3109  2,
3110  pertrans->aggCollation,
3111  (void *) aggstate, NULL);
3112 
3113  /*
3114  * Ensure that a combine function to combine INTERNAL states is not
3115  * strict. This should have been checked during CREATE AGGREGATE, but
3116  * the strict property could have been changed since then.
3117  */
3118  if (pertrans->transfn.fn_strict && aggtranstype == INTERNALOID)
3119  ereport(ERROR,
3120  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
3121  errmsg("combine function for aggregate %u must be declared as STRICT",
3122  aggref->aggfnoid)));
3123  }
3124  else
3125  {
3126  Expr *transfnexpr;
3127 
3128  /*
3129  * Set up infrastructure for calling the transfn. Note that invtrans
3130  * is not needed here.
3131  */
3132  build_aggregate_transfn_expr(inputTypes,
3133  numArguments,
3134  numDirectArgs,
3135  aggref->aggvariadic,
3136  aggtranstype,
3137  aggref->inputcollid,
3138  aggtransfn,
3139  InvalidOid,
3140  &transfnexpr,
3141  NULL);
3142  fmgr_info(aggtransfn, &pertrans->transfn);
3143  fmgr_info_set_expr((Node *) transfnexpr, &pertrans->transfn);
3144 
3146  &pertrans->transfn,
3147  pertrans->numTransInputs + 1,
3148  pertrans->aggCollation,
3149  (void *) aggstate, NULL);
3150 
3151  /*
3152  * If the transfn is strict and the initval is NULL, make sure input
3153  * type and transtype are the same (or at least binary-compatible), so
3154  * that it's OK to use the first aggregated input value as the initial
3155  * transValue. This should have been checked at agg definition time,
3156  * but we must check again in case the transfn's strictness property
3157  * has been changed.
3158  */
3159  if (pertrans->transfn.fn_strict && pertrans->initValueIsNull)
3160  {
3161  if (numArguments <= numDirectArgs ||
3162  !IsBinaryCoercible(inputTypes[numDirectArgs],
3163  aggtranstype))
3164  ereport(ERROR,
3165  (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
3166  errmsg("aggregate %u needs to have compatible input type and transition type",
3167  aggref->aggfnoid)));
3168  }
3169  }
3170 
3171  /* get info about the state value's datatype */
3172  get_typlenbyval(aggtranstype,
3173  &pertrans->transtypeLen,
3174  &pertrans->transtypeByVal);
3175 
3176  if (OidIsValid(aggserialfn))
3177  {
3178  build_aggregate_serialfn_expr(aggserialfn,
3179  &serialfnexpr);
3180  fmgr_info(aggserialfn, &pertrans->serialfn);
3181  fmgr_info_set_expr((Node *) serialfnexpr, &pertrans->serialfn);
3182 
3184  &pertrans->serialfn,
3185  1,
3186  InvalidOid,
3187  (void *) aggstate, NULL);
3188  }
3189 
3190  if (OidIsValid(aggdeserialfn))
3191  {
3192  build_aggregate_deserialfn_expr(aggdeserialfn,
3193  &deserialfnexpr);
3194  fmgr_info(aggdeserialfn, &pertrans->deserialfn);
3195  fmgr_info_set_expr((Node *) deserialfnexpr, &pertrans->deserialfn);
3196 
3198  &pertrans->deserialfn,
3199  2,
3200  InvalidOid,
3201  (void *) aggstate, NULL);
3202 
3203  }
3204 
3205  /* Initialize the input and FILTER expressions */
3206  naggs = aggstate->numaggs;
3207  pertrans->aggfilter = ExecInitExpr(aggref->aggfilter,
3208  (PlanState *) aggstate);
3209  pertrans->aggdirectargs = (List *) ExecInitExpr((Expr *) aggref->aggdirectargs,
3210  (PlanState *) aggstate);
3211 
3212  /*
3213  * Complain if the aggregate's arguments contain any aggregates; nested
3214  * agg functions are semantically nonsensical. (This should have been
3215  * caught earlier, but we defend against it here anyway.)
3216  */
3217  if (naggs != aggstate->numaggs)
3218  ereport(ERROR,
3219  (errcode(ERRCODE_GROUPING_ERROR),
3220  errmsg("aggregate function calls cannot be nested")));
3221 
3222  /*
3223  * If we're doing either DISTINCT or ORDER BY for a plain agg, then we
3224  * have a list of SortGroupClause nodes; fish out the data in them and
3225  * stick them into arrays. We ignore ORDER BY for an ordered-set agg,
3226  * however; the agg's transfn and finalfn are responsible for that.
3227  *
3228  * Note that by construction, if there is a DISTINCT clause then the ORDER
3229  * BY clause is a prefix of it (see transformDistinctClause).
3230  */
3231  if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
3232  {
3233  sortlist = NIL;
3234  numSortCols = numDistinctCols = 0;
3235  }
3236  else if (aggref->aggdistinct)
3237  {
3238  sortlist = aggref->aggdistinct;
3239  numSortCols = numDistinctCols = list_length(sortlist);
3240  Assert(numSortCols >= list_length(aggref->aggorder));
3241  }
3242  else
3243  {
3244  sortlist = aggref->aggorder;
3245  numSortCols = list_length(sortlist);
3246  numDistinctCols = 0;
3247  }
3248 
3249  pertrans->numSortCols = numSortCols;
3250  pertrans->numDistinctCols = numDistinctCols;
3251 
3252  if (numSortCols > 0)
3253  {
3254  /*
3255  * Get a tupledesc and slot corresponding to the aggregated inputs
3256  * (including sort expressions) of the agg.
3257  */
3258  pertrans->sortdesc = ExecTypeFromTL(aggref->args, false);
3259  pertrans->sortslot = ExecInitExtraTupleSlot(estate);
3260  ExecSetSlotDescriptor(pertrans->sortslot, pertrans->sortdesc);
3261 
3262  /*
3263  * We don't implement DISTINCT or ORDER BY aggs in the HASHED case
3264  * (yet)
3265  */
3266  Assert(((Agg *) aggstate->ss.ps.plan)->aggstrategy != AGG_HASHED);
3267 
3268  /* If we have only one input, we need its len/byval info. */
3269  if (numInputs == 1)
3270  {
3271  get_typlenbyval(inputTypes[numDirectArgs],
3272  &pertrans->inputtypeLen,
3273  &pertrans->inputtypeByVal);
3274  }
3275  else if (numDistinctCols > 0)
3276  {
3277  /* we will need an extra slot to store prior values */
3278  pertrans->uniqslot = ExecInitExtraTupleSlot(estate);
3279  ExecSetSlotDescriptor(pertrans->uniqslot,
3280  pertrans->sortdesc);
3281  }
3282 
3283  /* Extract the sort information for use later */
3284  pertrans->sortColIdx =
3285  (AttrNumber *) palloc(numSortCols * sizeof(AttrNumber));
3286  pertrans->sortOperators =
3287  (Oid *) palloc(numSortCols * sizeof(Oid));
3288  pertrans->sortCollations =
3289  (Oid *) palloc(numSortCols * sizeof(Oid));
3290  pertrans->sortNullsFirst =
3291  (bool *) palloc(numSortCols * sizeof(bool));
3292 
3293  i = 0;
3294  foreach(lc, sortlist)
3295  {
3296  SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc);
3297  TargetEntry *tle = get_sortgroupclause_tle(sortcl, aggref->args);
3298 
3299  /* the parser should have made sure of this */
3300  Assert(OidIsValid(sortcl->sortop));
3301 
3302  pertrans->sortColIdx[i] = tle->resno;
3303  pertrans->sortOperators[i] = sortcl->sortop;
3304  pertrans->sortCollations[i] = exprCollation((Node *) tle->expr);
3305  pertrans->sortNullsFirst[i] = sortcl->nulls_first;
3306  i++;
3307  }
3308  Assert(i == numSortCols);
3309  }
3310 
3311  if (aggref->aggdistinct)
3312  {
3313  Assert(numArguments > 0);
3314 
3315  /*
3316  * We need the equal function for each DISTINCT comparison we will
3317  * make.
3318  */
3319  pertrans->equalfns =
3320  (FmgrInfo *) palloc(numDistinctCols * sizeof(FmgrInfo));
3321 
3322  i = 0;
3323  foreach(lc, aggref->aggdistinct)
3324  {
3325  SortGroupClause *sortcl = (SortGroupClause *) lfirst(lc);
3326 
3327  fmgr_info(get_opcode(sortcl->eqop), &pertrans->equalfns[i]);
3328  i++;
3329  }
3330  Assert(i == numDistinctCols);
3331  }
3332 
3333  pertrans->sortstates = (Tuplesortstate **)
3334  palloc0(sizeof(Tuplesortstate *) * numGroupingSets);
3335 }
List * aggdistinct
Definition: primnodes.h:281
#define NIL
Definition: pg_list.h:69
Definition: fmgr.h:53
bool aggvariadic
Definition: primnodes.h:284
TupleTableSlot * ExecInitExtraTupleSlot(EState *estate)
Definition: execTuples.c:852
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
Definition: tlist.c:370
Oid inputcollid
Definition: primnodes.h:275
Definition: nodes.h:509
int errcode(int sqlerrcode)
Definition: elog.c:575
List * args
Definition: primnodes.h:279
void build_aggregate_deserialfn_expr(Oid deserialfn_oid, Expr **deserialfnexpr)
Definition: parse_agg.c:1980
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:534
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:760
TupleDesc sortdesc
Definition: nodeAgg.c:302
FmgrInfo transfn
Definition: nodeAgg.c:247
FunctionCallInfoData transfn_fcinfo
Definition: nodeAgg.c:334
#define AGGKIND_IS_ORDERED_SET(kind)
Definition: pg_aggregate.h:129
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execQual.c:4266
#define ERROR
Definition: elog.h:43
bool fn_strict
Definition: fmgr.h:58
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:159
Tuplesortstate ** sortstates
Definition: nodeAgg.c:326
static int initValue(long lng_val)
Definition: informix.c:702
List * aggorder
Definition: primnodes.h:280
#define fmgr_info_set_expr(expr, finfo)
Definition: fmgr.h:96
AttrNumber resno
Definition: primnodes.h:1331
List * aggdirectargs
Definition: primnodes.h:278
AttrNumber * sortColIdx
Definition: nodeAgg.c:266
#define ereport(elevel, rest)
Definition: elog.h:122
void build_aggregate_combinefn_expr(Oid agg_state_type, Oid agg_input_collation, Oid combinefn_oid, Expr **combinefnexpr)
Definition: parse_agg.c:1928
TupleDesc ExecTypeFromTL(List *targetList, bool hasoid)
Definition: execTuples.c:888
bool IsBinaryCoercible(Oid srctype, Oid targettype)
void * palloc0(Size size)
Definition: mcxt.c:920
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:247
FunctionCallInfoData serialfn_fcinfo
Definition: nodeAgg.c:337
FmgrInfo deserialfn
Definition: nodeAgg.c:253
#define InvalidOid
Definition: postgres_ext.h:36
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1062
Oid aggfnoid
Definition: primnodes.h:272
#define INTERNALOID
Definition: pg_type.h:686
#define Max(x, y)
Definition: c.h:796
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
FmgrInfo serialfn
Definition: nodeAgg.c:250
void build_aggregate_serialfn_expr(Oid serialfn_oid, Expr **serialfnexpr)
Definition: parse_agg.c:1957
Expr * expr
Definition: primnodes.h:1330
void build_aggregate_transfn_expr(Oid *agg_input_types, int agg_num_inputs, int agg_num_direct_inputs, bool agg_variadic, Oid agg_state_type, Oid agg_input_collation, Oid transfn_oid, Oid invtransfn_oid, Expr **transfnexpr, Expr **invtransfnexpr)
Definition: parse_agg.c:1867
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:112
static int list_length(const List *l)
Definition: pg_list.h:89
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:745
void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)
Definition: lsyscache.c:1969
Expr * aggfilter
Definition: primnodes.h:282
TupleTableSlot * uniqslot
Definition: nodeAgg.c:310
ExprState * aggfilter
Definition: nodeAgg.c:240
void * palloc(Size size)
Definition: mcxt.c:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
FmgrInfo * equalfns
Definition: nodeAgg.c:276
char aggkind
Definition: primnodes.h:286
Definition: plannodes.h:730
TupleTableSlot * sortslot
Definition: nodeAgg.c:309
List * aggdirectargs
Definition: nodeAgg.c:241
FunctionCallInfoData deserialfn_fcinfo
Definition: nodeAgg.c:339
Definition: pg_list.h:45
int16 AttrNumber
Definition: attnum.h:21
bool * sortNullsFirst
Definition: nodeAgg.c:269
static void combine_aggregates ( AggState aggstate,
AggStatePerGroup  pergroup 
)
static

Definition at line 963 of file nodeAgg.c.

References advance_combine_function(), FunctionCallInfoData::arg, FunctionCallInfoData::argnull, Assert, AggStatePerTransData::deserialfn, AggStatePerTransData::deserialfn_fcinfo, AggStatePerTransData::deserialfn_oid, ExprContext::ecxt_per_tuple_memory, AggState::evalproj, ExecProject(), FmgrInfo::fn_strict, FunctionCallInvoke, AggStatePerTransData::inputoff, FunctionCallInfoData::isnull, MemoryContextSwitchTo(), NULL, AggStatePerPhaseData::numsets, AggState::numtrans, OidIsValid, AggState::pertrans, AggState::phase, PointerGetDatum, AggState::tmpcontext, AggStatePerTransData::transfn_fcinfo, TupleTableSlot::tts_isnull, TupleTableSlot::tts_nvalid, and TupleTableSlot::tts_values.

Referenced by agg_fill_hash_table(), and agg_retrieve_direct().

964 {
965  int transno;
966  int numTrans = aggstate->numtrans;
967  TupleTableSlot *slot;
968 
969  /* combine not supported with grouping sets */
970  Assert(aggstate->phase->numsets == 0);
971 
972  /* compute input for all aggregates */
973  slot = ExecProject(aggstate->evalproj);
974 
975  for (transno = 0; transno < numTrans; transno++)
976  {
977  AggStatePerTrans pertrans = &aggstate->pertrans[transno];
978  AggStatePerGroup pergroupstate = &pergroup[transno];
979  FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
980  int inputoff = pertrans->inputoff;
981 
982  Assert(slot->tts_nvalid > inputoff);
983 
984  /*
985  * deserialfn_oid will be set if we must deserialize the input state
986  * before calling the combine function
987  */
988  if (OidIsValid(pertrans->deserialfn_oid))
989  {
990  /* Don't call a strict deserialization function with NULL input */
991  if (pertrans->deserialfn.fn_strict && slot->tts_isnull[inputoff])
992  {
993  fcinfo->arg[1] = slot->tts_values[inputoff];
994  fcinfo->argnull[1] = slot->tts_isnull[inputoff];
995  }
996  else
997  {
998  FunctionCallInfo dsinfo = &pertrans->deserialfn_fcinfo;
999  MemoryContext oldContext;
1000 
1001  dsinfo->arg[0] = slot->tts_values[inputoff];
1002  dsinfo->argnull[0] = slot->tts_isnull[inputoff];
1003  /* Dummy second argument for type-safety reasons */
1004  dsinfo->arg[1] = PointerGetDatum(NULL);
1005  dsinfo->argnull[1] = false;
1006 
1007  /*
1008  * We run the deserialization functions in per-input-tuple
1009  * memory context.
1010  */
1011  oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
1012 
1013  fcinfo->arg[1] = FunctionCallInvoke(dsinfo);
1014  fcinfo->argnull[1] = dsinfo->isnull;
1015 
1016  MemoryContextSwitchTo(oldContext);
1017  }
1018  }
1019  else
1020  {
1021  fcinfo->arg[1] = slot->tts_values[inputoff];
1022  fcinfo->argnull[1] = slot->tts_isnull[inputoff];
1023  }
1024 
1025  advance_combine_function(aggstate, pertrans, pergroupstate);
1026  }
1027 }
TupleTableSlot * ExecProject(ProjectionInfo *projInfo)
Definition: execQual.c:5214
#define PointerGetDatum(X)
Definition: postgres.h:564
ProjectionInfo * evalproj
Definition: execnodes.h:1908
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:134
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Datum * tts_values
Definition: tuptable.h:125
AggStatePerTrans pertrans
Definition: execnodes.h:1877
#define OidIsValid(objectId)
Definition: c.h:534
int numtrans
Definition: execnodes.h:1870
ExprContext * tmpcontext
Definition: execnodes.h:1879
FunctionCallInfoData transfn_fcinfo
Definition: nodeAgg.c:334
bool fn_strict
Definition: fmgr.h:58
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:129
bool * tts_isnull
Definition: tuptable.h:126
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:78
static void advance_combine_function(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroupstate)
Definition: nodeAgg.c:1039
AggStatePerPhase phase
Definition: execnodes.h:1872
FmgrInfo deserialfn
Definition: nodeAgg.c:253
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
FunctionCallInfoData deserialfn_fcinfo
Definition: nodeAgg.c:339
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
static TupleTableSlot * fetch_input_tuple ( AggState aggstate)
static

Definition at line 575 of file nodeAgg.c.

References ExecProcNode(), NULL, outerPlanState, AggState::sort_in, AggState::sort_out, AggState::sort_slot, TupIsNull, tuplesort_gettupleslot(), and tuplesort_puttupleslot().

Referenced by agg_fill_hash_table(), and agg_retrieve_direct().

576 {
577  TupleTableSlot *slot;
578 
579  if (aggstate->sort_in)
580  {
581  if (!tuplesort_gettupleslot(aggstate->sort_in, true, aggstate->sort_slot,
582  NULL))
583  return NULL;
584  slot = aggstate->sort_slot;
585  }
586  else
587  slot = ExecProcNode(outerPlanState(aggstate));
588 
589  if (!TupIsNull(slot) && aggstate->sort_out)
590  tuplesort_puttupleslot(aggstate->sort_out, slot);
591 
592  return slot;
593 }
TupleTableSlot * ExecProcNode(PlanState *node)
Definition: execProcnode.c:380
TupleTableSlot * sort_slot
Definition: execnodes.h:1893
Tuplesortstate * sort_out
Definition: execnodes.h:1892
Tuplesortstate * sort_in
Definition: execnodes.h:1891
#define outerPlanState(node)
Definition: execnodes.h:1090
#define TupIsNull(slot)
Definition: tuptable.h:138
#define NULL
Definition: c.h:226
void tuplesort_puttupleslot(Tuplesortstate *state, TupleTableSlot *slot)
Definition: tuplesort.c:1354
bool tuplesort_gettupleslot(Tuplesortstate *state, bool forward, TupleTableSlot *slot, Datum *abbrev)
Definition: tuplesort.c:2099
static void finalize_aggregate ( AggState aggstate,
AggStatePerAgg  peragg,
AggStatePerGroup  pergroupstate,
Datum resultVal,
bool resultIsNull 
)
static

Definition at line 1344 of file nodeAgg.c.

References AggStatePerTransData::aggCollation, AggStatePerTransData::aggdirectargs, FunctionCallInfoData::arg, FunctionCallInfoData::argnull, AggState::curpertrans, CurrentMemoryContext, datumCopy(), DatumGetPointer, ExprContext::ecxt_per_tuple_memory, ExecEvalExpr, AggStatePerAggData::finalfn, AggStatePerAggData::finalfn_oid, FunctionCallInfoData::flinfo, FmgrInfo::fn_strict, FunctionCallInvoke, i, InitFunctionCallInfoData, FunctionCallInfoData::isnull, lfirst, MakeExpandedObjectReadOnly, MemoryContextContains(), MemoryContextSwitchTo(), NULL, AggStatePerAggData::numFinalArgs, OidIsValid, AggState::pertrans, ScanState::ps, PlanState::ps_ExprContext, AggStatePerAggData::resulttypeByVal, AggStatePerAggData::resulttypeLen, AggState::ss, AggStatePerAggData::transno, AggStatePerTransData::transtypeLen, AggStatePerGroupData::transValue, and AggStatePerGroupData::transValueIsNull.

Referenced by finalize_aggregates().

1348 {
1349  FunctionCallInfoData fcinfo;
1350  bool anynull = false;
1351  MemoryContext oldContext;
1352  int i;
1353  ListCell *lc;
1354  AggStatePerTrans pertrans = &aggstate->pertrans[peragg->transno];
1355 
1357 
1358  /*
1359  * Evaluate any direct arguments. We do this even if there's no finalfn
1360  * (which is unlikely anyway), so that side-effects happen as expected.
1361  * The direct arguments go into arg positions 1 and up, leaving position 0
1362  * for the transition state value.
1363  */
1364  i = 1;
1365  foreach(lc, pertrans->aggdirectargs)
1366  {
1367  ExprState *expr = (ExprState *) lfirst(lc);
1368 
1369  fcinfo.arg[i] = ExecEvalExpr(expr,
1370  aggstate->ss.ps.ps_ExprContext,
1371  &fcinfo.argnull[i]);
1372  anynull |= fcinfo.argnull[i];
1373  i++;
1374  }
1375 
1376  /*
1377  * Apply the agg's finalfn if one is provided, else return transValue.
1378  */
1379  if (OidIsValid(peragg->finalfn_oid))
1380  {
1381  int numFinalArgs = peragg->numFinalArgs;
1382 
1383  /* set up aggstate->curpertrans for AggGetAggref() */
1384  aggstate->curpertrans = pertrans;
1385 
1386  InitFunctionCallInfoData(fcinfo, &peragg->finalfn,
1387  numFinalArgs,
1388  pertrans->aggCollation,
1389  (void *) aggstate, NULL);
1390 
1391  /* Fill in the transition state value */
1392  fcinfo.arg[0] = MakeExpandedObjectReadOnly(pergroupstate->transValue,
1393  pergroupstate->transValueIsNull,
1394  pertrans->transtypeLen);
1395  fcinfo.argnull[0] = pergroupstate->transValueIsNull;
1396  anynull |= pergroupstate->transValueIsNull;
1397 
1398  /* Fill any remaining argument positions with nulls */
1399  for (; i < numFinalArgs; i++)
1400  {
1401  fcinfo.arg[i] = (Datum) 0;
1402  fcinfo.argnull[i] = true;
1403  anynull = true;
1404  }
1405 
1406  if (fcinfo.flinfo->fn_strict && anynull)
1407  {
1408  /* don't call a strict function with NULL inputs */
1409  *resultVal = (Datum) 0;
1410  *resultIsNull = true;
1411  }
1412  else
1413  {
1414  *resultVal = FunctionCallInvoke(&fcinfo);
1415  *resultIsNull = fcinfo.isnull;
1416  }
1417  aggstate->curpertrans = NULL;
1418  }
1419  else
1420  {
1421  /* Don't need MakeExpandedObjectReadOnly; datumCopy will copy it */
1422  *resultVal = pergroupstate->transValue;
1423  *resultIsNull = pergroupstate->transValueIsNull;
1424  }
1425 
1426  /*
1427  * If result is pass-by-ref, make sure it is in the right context.
1428  */
1429  if (!peragg->resulttypeByVal && !*resultIsNull &&
1431  DatumGetPointer(*resultVal)))
1432  *resultVal = datumCopy(*resultVal,
1433  peragg->resulttypeByVal,
1434  peragg->resulttypeLen);
1435 
1436  MemoryContextSwitchTo(oldContext);
1437 }
ScanState ss
Definition: execnodes.h:1867
ExprContext * ps_ExprContext
Definition: execnodes.h:1078
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:134
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
AggStatePerTrans pertrans
Definition: execnodes.h:1877
#define OidIsValid(objectId)
Definition: c.h:534
PlanState ps
Definition: execnodes.h:1288
FmgrInfo * flinfo
Definition: fmgr.h:71
#define ExecEvalExpr(expr, econtext, isNull)
Definition: executor.h:73
bool fn_strict
Definition: fmgr.h:58
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:129
#define MakeExpandedObjectReadOnly(d, isnull, typlen)
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:78
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
uintptr_t Datum
Definition: postgres.h:374
int16 resulttypeLen
Definition: nodeAgg.c:385
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
bool MemoryContextContains(MemoryContext context, void *pointer)
Definition: mcxt.c:612
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:112
#define DatumGetPointer(X)
Definition: postgres.h:557
int i
AggStatePerTrans curpertrans
Definition: execnodes.h:1880
bool resulttypeByVal
Definition: nodeAgg.c:386
List * aggdirectargs
Definition: nodeAgg.c:241
FmgrInfo finalfn
Definition: nodeAgg.c:371
static void finalize_aggregates ( AggState aggstate,
AggStatePerAgg  peragg,
AggStatePerGroup  pergroup,
int  currentSet 
)
static

Definition at line 1567 of file nodeAgg.c.

References AGG_HASHED, AggState::aggsplit, Assert, AggState::current_set, DO_AGGSPLIT_SKIPFINAL, ExprContext::ecxt_aggnulls, ExprContext::ecxt_aggvalues, finalize_aggregate(), finalize_partialaggregate(), AggState::numaggs, AggStatePerTransData::numInputs, AggStatePerTransData::numSortCols, AggState::numtrans, AggState::pertrans, PlanState::plan, process_ordered_aggregate_multi(), process_ordered_aggregate_single(), ScanState::ps, PlanState::ps_ExprContext, AggState::ss, and AggStatePerAggData::transno.

Referenced by agg_retrieve_direct(), and agg_retrieve_hash_table().

1571 {
1572  ExprContext *econtext = aggstate->ss.ps.ps_ExprContext;
1573  Datum *aggvalues = econtext->ecxt_aggvalues;
1574  bool *aggnulls = econtext->ecxt_aggnulls;
1575  int aggno;
1576  int transno;
1577 
1578  Assert(currentSet == 0 ||
1579  ((Agg *) aggstate->ss.ps.plan)->aggstrategy != AGG_HASHED);
1580 
1581  aggstate->current_set = currentSet;
1582 
1583  /*
1584  * If there were any DISTINCT and/or ORDER BY aggregates, sort their
1585  * inputs and run the transition functions.
1586  */
1587  for (transno = 0; transno < aggstate->numtrans; transno++)
1588  {
1589  AggStatePerTrans pertrans = &aggstate->pertrans[transno];
1590  AggStatePerGroup pergroupstate;
1591 
1592  pergroupstate = &pergroup[transno + (currentSet * (aggstate->numtrans))];
1593 
1594  if (pertrans->numSortCols > 0)
1595  {
1596  Assert(((Agg *) aggstate->ss.ps.plan)->aggstrategy != AGG_HASHED);
1597 
1598  if (pertrans->numInputs == 1)
1600  pertrans,
1601  pergroupstate);
1602  else
1604  pertrans,
1605  pergroupstate);
1606  }
1607  }
1608 
1609  /*
1610  * Run the final functions.
1611  */
1612  for (aggno = 0; aggno < aggstate->numaggs; aggno++)
1613  {
1614  AggStatePerAgg peragg = &peraggs[aggno];
1615  int transno = peragg->transno;
1616  AggStatePerGroup pergroupstate;
1617 
1618  pergroupstate = &pergroup[transno + (currentSet * (aggstate->numtrans))];
1619 
1620  if (DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit))
1621  finalize_partialaggregate(aggstate, peragg, pergroupstate,
1622  &aggvalues[aggno], &aggnulls[aggno]);
1623  else
1624  finalize_aggregate(aggstate, peragg, pergroupstate,
1625  &aggvalues[aggno], &aggnulls[aggno]);
1626  }
1627 }
Datum * ecxt_aggvalues
Definition: execnodes.h:144
int numaggs
Definition: execnodes.h:1869
static void finalize_partialaggregate(AggState *aggstate, AggStatePerAgg peragg, AggStatePerGroup pergroupstate, Datum *resultVal, bool *resultIsNull)
Definition: nodeAgg.c:1446
ScanState ss
Definition: execnodes.h:1867
ExprContext * ps_ExprContext
Definition: execnodes.h:1078
AggSplit aggsplit
Definition: execnodes.h:1871
static void finalize_aggregate(AggState *aggstate, AggStatePerAgg peragg, AggStatePerGroup pergroupstate, Datum *resultVal, bool *resultIsNull)
Definition: nodeAgg.c:1344
AggStatePerTrans pertrans
Definition: execnodes.h:1877
int current_set
Definition: execnodes.h:1884
int numtrans
Definition: execnodes.h:1870
PlanState ps
Definition: execnodes.h:1288
static void process_ordered_aggregate_multi(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroupstate)
Definition: nodeAgg.c:1253
bool * ecxt_aggnulls
Definition: execnodes.h:145
uintptr_t Datum
Definition: postgres.h:374
Plan * plan
Definition: execnodes.h:1047
#define Assert(condition)
Definition: c.h:671
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:761
static void process_ordered_aggregate_single(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroupstate)
Definition: nodeAgg.c:1160
Definition: plannodes.h:730
static void finalize_partialaggregate ( AggState aggstate,
AggStatePerAgg  peragg,
AggStatePerGroup  pergroupstate,
Datum resultVal,
bool resultIsNull 
)
static

Definition at line 1446 of file nodeAgg.c.

References FunctionCallInfoData::arg, FunctionCallInfoData::argnull, CurrentMemoryContext, datumCopy(), DatumGetPointer, ExprContext::ecxt_per_tuple_memory, FmgrInfo::fn_strict, FunctionCallInvoke, FunctionCallInfoData::isnull, MakeExpandedObjectReadOnly, MemoryContextContains(), MemoryContextSwitchTo(), OidIsValid, AggState::pertrans, ScanState::ps, PlanState::ps_ExprContext, AggStatePerAggData::resulttypeByVal, AggStatePerAggData::resulttypeLen, AggStatePerTransData::serialfn, AggStatePerTransData::serialfn_fcinfo, AggStatePerTransData::serialfn_oid, AggState::ss, AggStatePerAggData::transno, AggStatePerTransData::transtypeLen, AggStatePerGroupData::transValue, and AggStatePerGroupData::transValueIsNull.

Referenced by finalize_aggregates().

1450 {
1451  AggStatePerTrans pertrans = &aggstate->pertrans[peragg->transno];
1452  MemoryContext oldContext;
1453 
1455 
1456  /*
1457  * serialfn_oid will be set if we must serialize the transvalue before
1458  * returning it
1459  */
1460  if (OidIsValid(pertrans->serialfn_oid))
1461  {
1462  /* Don't call a strict serialization function with NULL input. */
1463  if (pertrans->serialfn.fn_strict && pergroupstate->transValueIsNull)
1464  {
1465  *resultVal = (Datum) 0;
1466  *resultIsNull = true;
1467  }
1468  else
1469  {
1470  FunctionCallInfo fcinfo = &pertrans->serialfn_fcinfo;
1471 
1472  fcinfo->arg[0] = MakeExpandedObjectReadOnly(pergroupstate->transValue,
1473  pergroupstate->transValueIsNull,
1474  pertrans->transtypeLen);
1475  fcinfo->argnull[0] = pergroupstate->transValueIsNull;
1476 
1477  *resultVal = FunctionCallInvoke(fcinfo);
1478  *resultIsNull = fcinfo->isnull;
1479  }
1480  }
1481  else
1482  {
1483  /* Don't need MakeExpandedObjectReadOnly; datumCopy will copy it */
1484  *resultVal = pergroupstate->transValue;
1485  *resultIsNull = pergroupstate->transValueIsNull;
1486  }
1487 
1488  /* If result is pass-by-ref, make sure it is in the right context. */
1489  if (!peragg->resulttypeByVal && !*resultIsNull &&
1491  DatumGetPointer(*resultVal)))
1492  *resultVal = datumCopy(*resultVal,
1493  peragg->resulttypeByVal,
1494  peragg->resulttypeLen);
1495 
1496  MemoryContextSwitchTo(oldContext);
1497 }
ScanState ss
Definition: execnodes.h:1867
ExprContext * ps_ExprContext
Definition: execnodes.h:1078
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:134
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
AggStatePerTrans pertrans
Definition: execnodes.h:1877
#define OidIsValid(objectId)
Definition: c.h:534
PlanState ps
Definition: execnodes.h:1288
bool fn_strict
Definition: fmgr.h:58
#define FunctionCallInvoke(fcinfo)
Definition: fmgr.h:129
#define MakeExpandedObjectReadOnly(d, isnull, typlen)
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:78
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
uintptr_t Datum
Definition: postgres.h:374
FunctionCallInfoData serialfn_fcinfo
Definition: nodeAgg.c:337
int16 resulttypeLen
Definition: nodeAgg.c:385
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
FmgrInfo serialfn
Definition: nodeAgg.c:250
bool MemoryContextContains(MemoryContext context, void *pointer)
Definition: mcxt.c:612
#define DatumGetPointer(X)
Definition: postgres.h:557
bool resulttypeByVal
Definition: nodeAgg.c:386
static int find_compatible_peragg ( Aggref newagg,
AggState aggstate,
int  lastaggno,
List **  same_input_transnos 
)
static

Definition at line 3367 of file nodeAgg.c.

References Aggref::aggcollid, Aggref::aggdirectargs, Aggref::aggdistinct, Aggref::aggfilter, Aggref::aggfnoid, Aggref::aggkind, Aggref::aggorder, AggStatePerAggData::aggref, Aggref::aggstar, Aggref::aggtranstype, Aggref::aggtype, Aggref::aggvariadic, Aggref::args, contain_volatile_functions(), equal(), Aggref::inputcollid, lappend_int(), list_free(), NIL, AggState::peragg, and AggStatePerAggData::transno.

Referenced by ExecInitAgg().

3369 {
3370  int aggno;
3371  AggStatePerAgg peraggs;
3372 
3373  *same_input_transnos = NIL;
3374 
3375  /* we mustn't reuse the aggref if it contains volatile function calls */
3376  if (contain_volatile_functions((Node *) newagg))
3377  return -1;
3378 
3379  peraggs = aggstate->peragg;
3380 
3381  /*
3382  * Search through the list of already seen aggregates. If we find an
3383  * existing aggregate with the same aggregate function and input
3384  * parameters as an existing one, then we can re-use that one. While
3385  * searching, we'll also collect a list of Aggrefs with the same input
3386  * parameters. If no matching Aggref is found, the caller can potentially
3387  * still re-use the transition state of one of them.
3388  */
3389  for (aggno = 0; aggno <= lastaggno; aggno++)
3390  {
3391  AggStatePerAgg peragg;
3392  Aggref *existingRef;
3393 
3394  peragg = &peraggs[aggno];
3395  existingRef = peragg->aggref;
3396 
3397  /* all of the following must be the same or it's no match */
3398  if (newagg->inputcollid != existingRef->inputcollid ||
3399  newagg->aggtranstype != existingRef->aggtranstype ||
3400  newagg->aggstar != existingRef->aggstar ||
3401  newagg->aggvariadic != existingRef->aggvariadic ||
3402  newagg->aggkind != existingRef->aggkind ||
3403  !equal(newagg->aggdirectargs, existingRef->aggdirectargs) ||
3404  !equal(newagg->args, existingRef->args) ||
3405  !equal(newagg->aggorder, existingRef->aggorder) ||
3406  !equal(newagg->aggdistinct, existingRef->aggdistinct) ||
3407  !equal(newagg->aggfilter, existingRef->aggfilter))
3408  continue;
3409 
3410  /* if it's the same aggregate function then report exact match */
3411  if (newagg->aggfnoid == existingRef->aggfnoid &&
3412  newagg->aggtype == existingRef->aggtype &&
3413  newagg->aggcollid == existingRef->aggcollid)
3414  {
3415  list_free(*same_input_transnos);
3416  *same_input_transnos = NIL;
3417  return aggno;
3418  }
3419 
3420  /*
3421  * Not identical, but it had the same inputs. Return it to the caller,
3422  * in case we can re-use its per-trans state.
3423  */
3424  *same_input_transnos = lappend_int(*same_input_transnos,
3425  peragg->transno);
3426  }
3427 
3428  return -1;
3429 }
List * aggdistinct
Definition: primnodes.h:281
#define NIL
Definition: pg_list.h:69
bool aggvariadic
Definition: primnodes.h:284
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2870
Oid inputcollid
Definition: primnodes.h:275
Definition: nodes.h:509
List * args
Definition: primnodes.h:279
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:950
bool aggstar
Definition: primnodes.h:283
Aggref * aggref
Definition: nodeAgg.c:359
List * aggorder
Definition: primnodes.h:280
List * aggdirectargs
Definition: primnodes.h:278
List * lappend_int(List *list, int datum)
Definition: list.c:146
Oid aggfnoid
Definition: primnodes.h:272
Expr * aggfilter
Definition: primnodes.h:282
Oid aggcollid
Definition: primnodes.h:274
AggStatePerAgg peragg
Definition: execnodes.h:1876
void list_free(List *list)
Definition: list.c:1133
Oid aggtranstype
Definition: primnodes.h:276
Oid aggtype
Definition: primnodes.h:273
char aggkind
Definition: primnodes.h:286
static int find_compatible_pertrans ( AggState aggstate,
Aggref newagg,
Oid  aggtransfn,
Oid  aggtranstype,
Oid  aggserialfn,
Oid  aggdeserialfn,
Datum  initValue,
bool  initValueIsNull,
List transnos 
)
static

Definition at line 3440 of file nodeAgg.c.

References AggStatePerTransData::aggtranstype, datumIsEqual(), AggStatePerTransData::deserialfn_oid, AggStatePerTransData::initValue, AggStatePerTransData::initValueIsNull, lfirst_int, AggState::pertrans, AggStatePerTransData::serialfn_oid, AggStatePerTransData::transfn_oid, AggStatePerTransData::transtypeByVal, and AggStatePerTransData::transtypeLen.

Referenced by ExecInitAgg().

3445 {
3446  ListCell *lc;
3447 
3448  foreach(lc, transnos)
3449  {
3450  int transno = lfirst_int(lc);
3451  AggStatePerTrans pertrans = &aggstate->pertrans[transno];
3452 
3453  /*
3454  * if the transfns or transition state types are not the same then the
3455  * state can't be shared.
3456  */
3457  if (aggtransfn != pertrans->transfn_oid ||
3458  aggtranstype != pertrans->aggtranstype)
3459  continue;
3460 
3461  /*
3462  * The serialization and deserialization functions must match, if
3463  * present, as we're unable to share the trans state for aggregates
3464  * which will serialize or deserialize into different formats.
3465  * Remember that these will be InvalidOid if they're not required for
3466  * this agg node.
3467  */
3468  if (aggserialfn != pertrans->serialfn_oid ||
3469  aggdeserialfn != pertrans->deserialfn_oid)
3470  continue;
3471 
3472  /* Check that the initial condition matches, too. */
3473  if (initValueIsNull && pertrans->initValueIsNull)
3474  return transno;
3475 
3476  if (!initValueIsNull && !pertrans->initValueIsNull &&
3477  datumIsEqual(initValue, pertrans->initValue,
3478  pertrans->transtypeByVal, pertrans->transtypeLen))
3479  {
3480  return transno;
3481  }
3482  }
3483  return -1;
3484 }
bool datumIsEqual(Datum value1, Datum value2, bool typByVal, int typLen)
Definition: datum.c:219
AggStatePerTrans pertrans
Definition: execnodes.h:1877
#define lfirst_int(lc)
Definition: pg_list.h:107
static int initValue(long lng_val)
Definition: informix.c:702
static List* find_hash_columns ( AggState aggstate)
static

Definition at line 1754 of file nodeAgg.c.

References bms_add_member(), bms_del_member(), bms_first_member(), bms_free(), bms_num_members(), ExecSetSlotDescriptor(), ExecTypeFromTL(), find_unaggregated_cols(), Agg::grpColIdx, AggState::hashGrpColIdxHash, AggState::hashGrpColIdxInput, AggState::hashslot, i, lappend(), AggState::largestGrpColIdx, list_free(), list_nth(), Max, NIL, Agg::numCols, AggState::numhashGrpCols, outerPlanState, palloc(), PlanState::plan, ScanState::ps, and AggState::ss.

Referenced by ExecInitAgg().

1755 {
1756  Agg *node = (Agg *) aggstate->ss.ps.plan;
1757  Bitmapset *colnos;
1758  List *collist;
1759  TupleDesc hashDesc;
1760  List *outerTlist = outerPlanState(aggstate)->plan->targetlist;
1761  List *hashTlist = NIL;
1762  int i;
1763 
1764  aggstate->largestGrpColIdx = 0;
1765 
1766  /* Find Vars that will be needed in tlist and qual */
1767  colnos = find_unaggregated_cols(aggstate);
1768  /* Add in all the grouping columns */
1769  for (i = 0; i < node->numCols; i++)
1770  colnos = bms_add_member(colnos, node->grpColIdx[i]);
1771  /* Convert to list, using lcons so largest element ends up first */
1772  collist = NIL;
1773 
1774  aggstate->hashGrpColIdxInput =
1775  palloc(bms_num_members(colnos) * sizeof(AttrNumber));
1776  aggstate->hashGrpColIdxHash =
1777  palloc(node->numCols * sizeof(AttrNumber));
1778 
1779  /*
1780  * First build mapping for columns directly hashed. These are the first,
1781  * because they'll be accessed when computing hash values and comparing
1782  * tuples for exact matches. We also build simple mapping for
1783  * execGrouping, so it knows where to find the to-be-hashed / compared
1784  * columns in the input.
1785  */
1786  for (i = 0; i < node->numCols; i++)
1787  {
1788  aggstate->hashGrpColIdxInput[i] = node->grpColIdx[i];
1789  aggstate->hashGrpColIdxHash[i] = i + 1;
1790  aggstate->numhashGrpCols++;
1791  /* delete already mapped columns */
1792  bms_del_member(colnos, node->grpColIdx[i]);
1793  }
1794 
1795  /* and add the remaining columns */
1796  while ((i = bms_first_member(colnos)) >= 0)
1797  {
1798  aggstate->hashGrpColIdxInput[aggstate->numhashGrpCols] = i;
1799  aggstate->numhashGrpCols++;
1800  }
1801 
1802  /* and build a tuple descriptor for the hashtable */
1803  for (i = 0; i < aggstate->numhashGrpCols; i++)
1804  {
1805  int varNumber = aggstate->hashGrpColIdxInput[i] - 1;
1806 
1807  hashTlist = lappend(hashTlist, list_nth(outerTlist, varNumber));
1808  aggstate->largestGrpColIdx =
1809  Max(varNumber + 1, aggstate->largestGrpColIdx);
1810  }
1811 
1812  hashDesc = ExecTypeFromTL(hashTlist, false);
1813  ExecSetSlotDescriptor(aggstate->hashslot, hashDesc);
1814 
1815  list_free(hashTlist);
1816  bms_free(colnos);
1817 
1818  return collist;
1819 }
#define NIL
Definition: pg_list.h:69
int numCols
Definition: plannodes.h:735
int bms_first_member(Bitmapset *a)
Definition: bitmapset.c:855
AttrNumber * grpColIdx
Definition: plannodes.h:736
ScanState ss
Definition: execnodes.h:1867
AttrNumber * hashGrpColIdxInput
Definition: execnodes.h:1902
PlanState ps
Definition: execnodes.h:1288
#define outerPlanState(node)
Definition: execnodes.h:1090
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:575
void * list_nth(const List *list, int n)
Definition: list.c:410
TupleDesc ExecTypeFromTL(List *targetList, bool hasoid)
Definition: execTuples.c:888
List * lappend(List *list, void *datum)
Definition: list.c:128
AttrNumber * hashGrpColIdxHash
Definition: execnodes.h:1903
void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc)
Definition: execTuples.c:247
Plan * plan
Definition: execnodes.h:1047
void bms_free(Bitmapset *a)
Definition: bitmapset.c:200
#define Max(x, y)
Definition: c.h:796
int largestGrpColIdx
Definition: execnodes.h:1901
static Bitmapset * find_unaggregated_cols(AggState *aggstate)
Definition: nodeAgg.c:1662
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:668
TupleTableSlot * hashslot
Definition: execnodes.h:1899
int numhashGrpCols
Definition: execnodes.h:1900
void * palloc(Size size)
Definition: mcxt.c:891
void list_free(List *list)
Definition: list.c:1133
int i
Definition: plannodes.h:730
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition: bitmapset.c:705
Definition: pg_list.h:45
int16 AttrNumber
Definition: attnum.h:21
static Bitmapset * find_unaggregated_cols ( AggState aggstate)
static

Definition at line 1662 of file nodeAgg.c.

References find_unaggregated_cols_walker(), NULL, Agg::plan, PlanState::plan, ScanState::ps, Plan::qual, AggState::ss, and Plan::targetlist.

Referenced by find_hash_columns().

1663 {
1664  Agg *node = (Agg *) aggstate->ss.ps.plan;
1665  Bitmapset *colnos;
1666 
1667  colnos = NULL;
1669  &colnos);
1670  (void) find_unaggregated_cols_walker((Node *) node->plan.qual,
1671  &colnos);
1672  return colnos;
1673 }
List * qual
Definition: plannodes.h:130
ScanState ss
Definition: execnodes.h:1867
Definition: nodes.h:509
PlanState ps
Definition: execnodes.h:1288
static bool find_unaggregated_cols_walker(Node *node, Bitmapset **colnos)
Definition: nodeAgg.c:1676
Plan plan
Definition: plannodes.h:732
Plan * plan
Definition: execnodes.h:1047
#define NULL
Definition: c.h:226
List * targetlist
Definition: plannodes.h:129
Definition: plannodes.h:730
static bool find_unaggregated_cols_walker ( Node node,
Bitmapset **  colnos 
)
static

Definition at line 1676 of file nodeAgg.c.

References Assert, bms_add_member(), expression_tree_walker(), IsA, NULL, OUTER_VAR, Var::varattno, Var::varlevelsup, and Var::varno.

Referenced by find_unaggregated_cols().

1677 {
1678  if (node == NULL)
1679  return false;
1680  if (IsA(node, Var))
1681  {
1682  Var *var = (Var *) node;
1683 
1684  /* setrefs.c should have set the varno to OUTER_VAR */
1685  Assert(var->varno == OUTER_VAR);
1686  Assert(var->varlevelsup == 0);
1687  *colnos = bms_add_member(*colnos, var->varattno);
1688  return false;
1689  }
1690  if (IsA(node, Aggref) ||IsA(node, GroupingFunc))
1691  {
1692  /* do not descend into aggregate exprs */
1693  return false;
1694  }
1696  (void *) colnos);
1697 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
Index varlevelsup
Definition: primnodes.h:151
AttrNumber varattno
Definition: primnodes.h:146
Definition: primnodes.h:141
static bool find_unaggregated_cols_walker(Node *node, Bitmapset **colnos)
Definition: nodeAgg.c:1676
Index varno
Definition: primnodes.h:144
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1852
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:668
#define OUTER_VAR
Definition: primnodes.h:132
static Datum GetAggInitVal ( Datum  textInitVal,
Oid  transtype 
)
static

Definition at line 3339 of file nodeAgg.c.

References getTypeInputInfo(), OidInputFunctionCall(), pfree(), and TextDatumGetCString.

Referenced by ExecInitAgg().

3340 {
3341  Oid typinput,
3342  typioparam;
3343  char *strInitVal;
3344  Datum initVal;
3345 
3346  getTypeInputInfo(transtype, &typinput, &typioparam);
3347  strInitVal = TextDatumGetCString(textInitVal);
3348  initVal = OidInputFunctionCall(typinput, strInitVal,
3349  typioparam, -1);
3350  pfree(strInitVal);
3351  return initVal;
3352 }
unsigned int Oid
Definition: postgres_ext.h:31
void pfree(void *pointer)
Definition: mcxt.c:992
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2567
#define TextDatumGetCString(d)
Definition: builtins.h:91
uintptr_t Datum
Definition: postgres.h:374
Datum OidInputFunctionCall(Oid functionId, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1997
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
static void initialize_aggregate ( AggState aggstate,
AggStatePerTrans  pertrans,
AggStatePerGroup  pergroupstate 
)
static

Definition at line 604 of file nodeAgg.c.

References AggState::aggcontexts, tupleDesc::attrs, AggState::current_set, datumCopy(), ExprContext::ecxt_per_tuple_memory, AggStatePerTransData::initValue, AggStatePerTransData::initValueIsNull, MemoryContextSwitchTo(), AggStatePerGroupData::noTransValue, AggStatePerTransData::numInputs, AggStatePerTransData::numSortCols, AggStatePerTransData::sortColIdx, AggStatePerTransData::sortCollations, AggStatePerTransData::sortdesc, AggStatePerTransData::sortNullsFirst, AggStatePerTransData::sortOperators, AggStatePerTransData::sortstates, AggStatePerTransData::transtypeByVal, AggStatePerTransData::transtypeLen, AggStatePerGroupData::transValue, AggStatePerGroupData::transValueIsNull, tuplesort_begin_datum(), tuplesort_begin_heap(), tuplesort_end(), and work_mem.

Referenced by initialize_aggregates().

606 {
607  /*
608  * Start a fresh sort operation for each DISTINCT/ORDER BY aggregate.
609  */
610  if (pertrans->numSortCols > 0)
611  {
612  /*
613  * In case of rescan, maybe there could be an uncompleted sort
614  * operation? Clean it up if so.
615  */
616  if (pertrans->sortstates[aggstate->current_set])
617  tuplesort_end(pertrans->sortstates[aggstate->current_set]);
618 
619 
620  /*
621  * We use a plain Datum sorter when there's a single input column;
622  * otherwise sort the full tuple. (See comments for
623  * process_ordered_aggregate_single.)
624  */
625  if (pertrans->numInputs == 1)
626  pertrans->sortstates[aggstate->current_set] =
627  tuplesort_begin_datum(pertrans->sortdesc->attrs[0]->atttypid,
628  pertrans->sortOperators[0],
629  pertrans->sortCollations[0],
630  pertrans->sortNullsFirst[0],
631  work_mem, false);
632  else
633  pertrans->sortstates[aggstate->current_set] =
634  tuplesort_begin_heap(pertrans->sortdesc,
635  pertrans->numSortCols,
636  pertrans->sortColIdx,
637  pertrans->sortOperators,
638  pertrans->sortCollations,
639  pertrans->sortNullsFirst,
640  work_mem, false);
641  }
642 
643  /*
644  * (Re)set transValue to the initial value.
645  *
646  * Note that when the initial value is pass-by-ref, we must copy it (into
647  * the aggcontext) since we will pfree the transValue later.
648  */
649  if (pertrans->initValueIsNull)
650  pergroupstate->transValue = pertrans->initValue;
651  else
652  {
653  MemoryContext oldContext;
654 
655  oldContext = MemoryContextSwitchTo(
656  aggstate->aggcontexts[aggstate->current_set]->ecxt_per_tuple_memory);
657  pergroupstate->transValue = datumCopy(pertrans->initValue,
658  pertrans->transtypeByVal,
659  pertrans->transtypeLen);
660  MemoryContextSwitchTo(oldContext);
661  }
662  pergroupstate->transValueIsNull = pertrans->initValueIsNull;
663 
664  /*
665  * If the initial value for the transition state doesn't exist in the
666  * pg_aggregate table then we will let the first non-NULL value returned
667  * from the outer procNode become the initial value. (This is useful for
668  * aggregates like max() and min().) The noTransValue flag signals that we
669  * still need to do this.
670  */
671  pergroupstate->noTransValue = pertrans->initValueIsNull;
672 }
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:134
Form_pg_attribute * attrs
Definition: tupdesc.h:74
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int current_set
Definition: execnodes.h:1884
TupleDesc sortdesc
Definition: nodeAgg.c:302
Tuplesortstate * tuplesort_begin_datum(Oid datumType, Oid sortOperator, Oid sortCollation, bool nullsFirstFlag, int workMem, bool randomAccess)
Definition: tuplesort.c:1028
Tuplesortstate ** sortstates
Definition: nodeAgg.c:326
AttrNumber * sortColIdx
Definition: nodeAgg.c:266
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:128
int work_mem
Definition: globals.c:112
ExprContext ** aggcontexts
Definition: execnodes.h:1878
Tuplesortstate * tuplesort_begin_heap(TupleDesc tupDesc, int nkeys, AttrNumber *attNums, Oid *sortOperators, Oid *sortCollations, bool *nullsFirstFlags, int workMem, bool randomAccess)
Definition: tuplesort.c:753
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1157
bool * sortNullsFirst
Definition: nodeAgg.c:269
static void initialize_aggregates ( AggState aggstate,
AggStatePerGroup  pergroup,
int  numReset 
)
static

Definition at line 685 of file nodeAgg.c.

References AggState::current_set, initialize_aggregate(), Max, AggStatePerPhaseData::numsets, AggState::numtrans, AggState::pertrans, and AggState::phase.

Referenced by agg_retrieve_direct(), and lookup_hash_entry().

688 {
689  int transno;
690  int numGroupingSets = Max(aggstate->phase->numsets, 1);
691  int setno = 0;
692  AggStatePerTrans transstates = aggstate->pertrans;
693 
694  if (numReset < 1)
695  numReset = numGroupingSets;
696 
697  for (transno = 0; transno < aggstate->numtrans; transno++)
698  {
699  AggStatePerTrans pertrans = &transstates[transno];
700 
701  for (setno = 0; setno < numReset; setno++)
702  {
703  AggStatePerGroup pergroupstate;
704 
705  pergroupstate = &pergroup[transno + (setno * (aggstate->numtrans))];
706 
707  aggstate->current_set = setno;
708 
709  initialize_aggregate(aggstate, pertrans, pergroupstate);
710  }
711  }
712 }
AggStatePerTrans pertrans
Definition: execnodes.h:1877
int current_set
Definition: execnodes.h:1884
int numtrans
Definition: execnodes.h:1870
static void initialize_aggregate(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroupstate)
Definition: nodeAgg.c:604
AggStatePerPhase phase
Definition: execnodes.h:1872
#define Max(x, y)
Definition: c.h:796
static void initialize_phase ( AggState aggstate,
int  newphase 
)
static

Definition at line 508 of file nodeAgg.c.

References Assert, Sort::collations, AggState::current_phase, ExecGetResultType(), NULL, Sort::nullsFirst, Sort::numCols, outerPlanState, AggState::phase, AggState::phases, AggState::sort_in, AggState::sort_out, Sort::sortColIdx, AggStatePerPhaseData::sortnode, Sort::sortOperators, tuplesort_begin_heap(), tuplesort_end(), tuplesort_performsort(), and work_mem.

Referenced by agg_retrieve_direct(), ExecInitAgg(), and ExecReScanAgg().

509 {
510  Assert(newphase == 0 || newphase == aggstate->current_phase + 1);
511 
512  /*
513  * Whatever the previous state, we're now done with whatever input
514  * tuplesort was in use.
515  */
516  if (aggstate->sort_in)
517  {
518  tuplesort_end(aggstate->sort_in);
519  aggstate->sort_in = NULL;
520  }
521 
522  if (newphase == 0)
523  {
524  /*
525  * Discard any existing output tuplesort.
526  */
527  if (aggstate->sort_out)
528  {
529  tuplesort_end(aggstate->sort_out);
530  aggstate->sort_out = NULL;
531  }
532  }
533  else
534  {
535  /*
536  * The old output tuplesort becomes the new input one, and this is the
537  * right time to actually sort it.
538  */
539  aggstate->sort_in = aggstate->sort_out;
540  aggstate->sort_out = NULL;
541  Assert(aggstate->sort_in);
542  tuplesort_performsort(aggstate->sort_in);
543  }
544 
545  /*
546  * If this isn't the last phase, we need to sort appropriately for the
547  * next phase in sequence.
548  */
549  if (newphase < aggstate->numphases - 1)
550  {
551  Sort *sortnode = aggstate->phases[newphase + 1].sortnode;
552  PlanState *outerNode = outerPlanState(aggstate);
553  TupleDesc tupDesc = ExecGetResultType(outerNode);
554 
555  aggstate->sort_out = tuplesort_begin_heap(tupDesc,
556  sortnode->numCols,
557  sortnode->sortColIdx,
558  sortnode->sortOperators,
559  sortnode->collations,
560  sortnode->nullsFirst,
561  work_mem,
562  false);
563  }
564 
565  aggstate->current_phase = newphase;
566  aggstate->phase = &aggstate->phases[newphase];
567 }
AggStatePerPhase phases
Definition: execnodes.h:1890
void tuplesort_performsort(Tuplesortstate *state)
Definition: tuplesort.c:1763
Tuplesortstate * sort_out
Definition: execnodes.h:1892
int current_phase
Definition: execnodes.h:1874
bool * nullsFirst
Definition: plannodes.h:699
Oid * sortOperators
Definition: plannodes.h:697
Tuplesortstate * sort_in
Definition: execnodes.h:1891
#define outerPlanState(node)
Definition: execnodes.h:1090
int numCols
Definition: plannodes.h:695
AggStatePerPhase phase
Definition: execnodes.h:1872
int work_mem
Definition: globals.c:112
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:459
AttrNumber * sortColIdx
Definition: plannodes.h:696
Tuplesortstate * tuplesort_begin_heap(TupleDesc tupDesc, int nkeys, AttrNumber *attNums, Oid *sortOperators, Oid *sortCollations, bool *nullsFirstFlags, int workMem, bool randomAccess)
Definition: tuplesort.c:753
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1157
Oid * collations
Definition: plannodes.h:698
static TupleHashEntryData * lookup_hash_entry ( AggState aggstate,
TupleTableSlot inputslot 
)
static

Definition at line 1849 of file nodeAgg.c.

References TupleHashEntryData::additional, ExecClearTuple(), ExecStoreVirtualTuple(), AggState::hashGrpColIdxInput, AggState::hashslot, AggState::hashtable, i, initialize_aggregates(), AggState::largestGrpColIdx, LookupTupleHashEntry(), MemoryContextAlloc(), AggState::numhashGrpCols, AggState::numtrans, slot_getsomeattrs(), TupleHashTableData::tablecxt, TupleTableSlot::tts_isnull, and TupleTableSlot::tts_values.

Referenced by agg_fill_hash_table().

1850 {
1851  TupleTableSlot *hashslot = aggstate->hashslot;
1852  TupleHashEntryData *entry;
1853  bool isnew;
1854  int i;
1855 
1856  /* transfer just the needed columns into hashslot */
1857  slot_getsomeattrs(inputslot, aggstate->largestGrpColIdx);
1858  ExecClearTuple(hashslot);
1859 
1860  for (i = 0; i < aggstate->numhashGrpCols; i++)
1861  {
1862  int varNumber = aggstate->hashGrpColIdxInput[i] - 1;
1863 
1864  hashslot->tts_values[i] = inputslot->tts_values[varNumber];
1865  hashslot->tts_isnull[i] = inputslot->tts_isnull[varNumber];
1866  }
1867  ExecStoreVirtualTuple(hashslot);
1868 
1869  /* find or create the hashtable entry using the filtered tuple */
1870  entry = LookupTupleHashEntry(aggstate->hashtable, hashslot, &isnew);
1871 
1872  if (isnew)
1873  {
1874  entry->additional = (AggStatePerGroup)
1876  sizeof(AggStatePerGroupData) * aggstate->numtrans);
1877  /* initialize aggregates for new tuple group */
1879  0);
1880  }
1881 
1882  return entry;
1883 }
struct AggStatePerGroupData * AggStatePerGroup
Definition: execnodes.h:1862
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
AttrNumber * hashGrpColIdxInput
Definition: execnodes.h:1902
Datum * tts_values
Definition: tuptable.h:125
int numtrans
Definition: execnodes.h:1870
void slot_getsomeattrs(TupleTableSlot *slot, int attnum)
Definition: heaptuple.c:1283
static void initialize_aggregates(AggState *aggstate, AggStatePerGroup pergroup, int numReset)
Definition: nodeAgg.c:685
MemoryContext tablecxt
Definition: execnodes.h:536
bool * tts_isnull
Definition: tuptable.h:126
TupleHashEntry LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew)
Definition: execGrouping.c:351
TupleHashTable hashtable
Definition: execnodes.h:1898
int largestGrpColIdx
Definition: execnodes.h:1901
TupleTableSlot * hashslot
Definition: execnodes.h:1899
int numhashGrpCols
Definition: execnodes.h:1900
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:749
int i
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:488
static void prepare_projection_slot ( AggState aggstate,
TupleTableSlot slot,
int  currentSet 
)
static

Definition at line 1524 of file nodeAgg.c.

References AggState::all_grouped_cols, bms_is_member(), ExecStoreAllNullTuple(), AggStatePerPhaseData::grouped_cols, AggState::grouped_cols, lfirst_int, linitial_int, AggState::phase, slot_getsomeattrs(), TupleTableSlot::tts_isempty, and TupleTableSlot::tts_isnull.

Referenced by agg_retrieve_direct().

1525 {
1526  if (aggstate->phase->grouped_cols)
1527  {
1528  Bitmapset *grouped_cols = aggstate->phase->grouped_cols[currentSet];
1529 
1530  aggstate->grouped_cols = grouped_cols;
1531 
1532  if (slot->tts_isempty)
1533  {
1534  /*
1535  * Force all values to be NULL if working on an empty input tuple
1536  * (i.e. an empty grouping set for which no input rows were
1537  * supplied).
1538  */
1539  ExecStoreAllNullTuple(slot);
1540  }
1541  else if (aggstate->all_grouped_cols)
1542  {
1543  ListCell *lc;
1544 
1545  /* all_grouped_cols is arranged in desc order */
1547 
1548  foreach(lc, aggstate->all_grouped_cols)
1549  {
1550  int attnum = lfirst_int(lc);
1551 
1552  if (!bms_is_member(attnum, grouped_cols))
1553  slot->tts_isnull[attnum - 1] = true;
1554  }
1555  }
1556  }
1557 }
bool tts_isempty
Definition: tuptable.h:116
TupleTableSlot * ExecStoreAllNullTuple(TupleTableSlot *slot)
Definition: execTuples.c:512
List * all_grouped_cols
Definition: execnodes.h:1886
void slot_getsomeattrs(TupleTableSlot *slot, int attnum)
Definition: heaptuple.c:1283
#define linitial_int(l)
Definition: pg_list.h:111
Bitmapset ** grouped_cols
Definition: nodeAgg.c:437
#define lfirst_int(lc)
Definition: pg_list.h:107
bool * tts_isnull
Definition: tuptable.h:126
Bitmapset * grouped_cols
Definition: execnodes.h:1885
AggStatePerPhase phase
Definition: execnodes.h:1872
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:419
static void process_ordered_aggregate_multi ( AggState aggstate,
AggStatePerTrans  pertrans,
AggStatePerGroup  pergroupstate 
)
static

Definition at line 1253 of file nodeAgg.c.

References advance_transition_function(), FunctionCallInfoData::arg, FunctionCallInfoData::argnull, AggState::current_set, ExprContext::ecxt_per_tuple_memory, AggStatePerTransData::equalfns, ExecClearTuple(), execTuplesMatch(), i, MemoryContextReset(), NULL, AggStatePerTransData::numDistinctCols, AggStatePerTransData::numTransInputs, slot_getsomeattrs(), AggStatePerTransData::sortColIdx, AggStatePerTransData::sortslot, AggStatePerTransData::sortstates, AggState::tmpcontext, AggStatePerTransData::transfn_fcinfo, TupleTableSlot::tts_isnull, TupleTableSlot::tts_values, tuplesort_end(), tuplesort_gettupleslot(), tuplesort_performsort(), and AggStatePerTransData::uniqslot.

Referenced by finalize_aggregates().

1256 {
1257  MemoryContext workcontext = aggstate->tmpcontext->ecxt_per_tuple_memory;
1258  FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
1259  TupleTableSlot *slot1 = pertrans->sortslot;
1260  TupleTableSlot *slot2 = pertrans->uniqslot;
1261  int numTransInputs = pertrans->numTransInputs;
1262  int numDistinctCols = pertrans->numDistinctCols;
1263  Datum newAbbrevVal = (Datum) 0;
1264  Datum oldAbbrevVal = (Datum) 0;
1265  bool haveOldValue = false;
1266  int i;
1267 
1268  tuplesort_performsort(pertrans->sortstates[aggstate->current_set]);
1269 
1270  ExecClearTuple(slot1);
1271  if (slot2)
1272  ExecClearTuple(slot2);
1273 
1274  while (tuplesort_gettupleslot(pertrans->sortstates[aggstate->current_set],
1275  true, slot1, &newAbbrevVal))
1276  {
1277  /*
1278  * Extract the first numTransInputs columns as datums to pass to the
1279  * transfn. (This will help execTuplesMatch too, so we do it
1280  * immediately.)
1281  */
1282  slot_getsomeattrs(slot1, numTransInputs);
1283 
1284  if (numDistinctCols == 0 ||
1285  !haveOldValue ||
1286  newAbbrevVal != oldAbbrevVal ||
1287  !execTuplesMatch(slot1, slot2,
1288  numDistinctCols,
1289  pertrans->sortColIdx,
1290  pertrans->equalfns,
1291  workcontext))
1292  {
1293  /* Load values into fcinfo */
1294  /* Start from 1, since the 0th arg will be the transition value */
1295  for (i = 0; i < numTransInputs; i++)
1296  {
1297  fcinfo->arg[i + 1] = slot1->tts_values[i];
1298  fcinfo->argnull[i + 1] = slot1->tts_isnull[i];
1299  }
1300 
1301  advance_transition_function(aggstate, pertrans, pergroupstate);
1302 
1303  if (numDistinctCols > 0)
1304  {
1305  /* swap the slot pointers to retain the current tuple */
1306  TupleTableSlot *tmpslot = slot2;
1307 
1308  slot2 = slot1;
1309  slot1 = tmpslot;
1310  /* avoid execTuplesMatch() calls by reusing abbreviated keys */
1311  oldAbbrevVal = newAbbrevVal;
1312  haveOldValue = true;
1313  }
1314  }
1315 
1316  /* Reset context each time, unless execTuplesMatch did it for us */
1317  if (numDistinctCols == 0)
1318  MemoryContextReset(workcontext);
1319 
1320  ExecClearTuple(slot1);
1321  }
1322 
1323  if (slot2)
1324  ExecClearTuple(slot2);
1325 
1326  tuplesort_end(pertrans->sortstates[aggstate->current_set]);
1327  pertrans->sortstates[aggstate->current_set] = NULL;
1328 }
void tuplesort_performsort(Tuplesortstate *state)
Definition: tuplesort.c:1763
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:134
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
bool execTuplesMatch(TupleTableSlot *slot1, TupleTableSlot *slot2, int numCols, AttrNumber *matchColIdx, FmgrInfo *eqfunctions, MemoryContext evalContext)
Definition: execGrouping.c:69
Datum * tts_values
Definition: tuptable.h:125
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
int current_set
Definition: execnodes.h:1884
ExprContext * tmpcontext
Definition: execnodes.h:1879
FunctionCallInfoData transfn_fcinfo
Definition: nodeAgg.c:334
void slot_getsomeattrs(TupleTableSlot *slot, int attnum)
Definition: heaptuple.c:1283
Tuplesortstate ** sortstates
Definition: nodeAgg.c:326
bool * tts_isnull
Definition: tuptable.h:126
AttrNumber * sortColIdx
Definition: nodeAgg.c:266
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:78
uintptr_t Datum
Definition: postgres.h:374
static void advance_transition_function(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroupstate)
Definition: nodeAgg.c:726
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
#define NULL
Definition: c.h:226
TupleTableSlot * uniqslot
Definition: nodeAgg.c:310
int i
FmgrInfo * equalfns
Definition: nodeAgg.c:276
TupleTableSlot * sortslot
Definition: nodeAgg.c:309
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1157
bool tuplesort_gettupleslot(Tuplesortstate *state, bool forward, TupleTableSlot *slot, Datum *abbrev)
Definition: tuplesort.c:2099
static void process_ordered_aggregate_single ( AggState aggstate,
AggStatePerTrans  pertrans,
AggStatePerGroup  pergroupstate 
)
static

Definition at line 1160 of file nodeAgg.c.

References advance_transition_function(), FunctionCallInfoData::arg, FunctionCallInfoData::argnull, Assert, AggState::current_set, DatumGetBool, DatumGetPointer, ExprContext::ecxt_per_tuple_memory, AggStatePerTransData::equalfns, FunctionCall2, AggStatePerTransData::inputtypeByVal, MemoryContextReset(), MemoryContextSwitchTo(), NULL, AggStatePerTransData::numDistinctCols, pfree(), AggStatePerTransData::sortstates, AggState::tmpcontext, AggStatePerTransData::transfn_fcinfo, tuplesort_end(), tuplesort_getdatum(), and tuplesort_performsort().

Referenced by finalize_aggregates().

1163 {
1164  Datum oldVal = (Datum) 0;
1165  bool oldIsNull = true;
1166  bool haveOldVal = false;
1167  MemoryContext workcontext = aggstate->tmpcontext->ecxt_per_tuple_memory;
1168  MemoryContext oldContext;
1169  bool isDistinct = (pertrans->numDistinctCols > 0);
1170  Datum newAbbrevVal = (Datum) 0;
1171  Datum oldAbbrevVal = (Datum) 0;
1172  FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
1173  Datum *newVal;
1174  bool *isNull;
1175 
1176  Assert(pertrans->numDistinctCols < 2);
1177 
1178  tuplesort_performsort(pertrans->sortstates[aggstate->current_set]);
1179 
1180  /* Load the column into argument 1 (arg 0 will be transition value) */
1181  newVal = fcinfo->arg + 1;
1182  isNull = fcinfo->argnull + 1;
1183 
1184  /*
1185  * Note: if input type is pass-by-ref, the datums returned by the sort are
1186  * freshly palloc'd in the per-query context, so we must be careful to
1187  * pfree them when they are no longer needed.
1188  */
1189 
1190  while (tuplesort_getdatum(pertrans->sortstates[aggstate->current_set],
1191  true, newVal, isNull, &newAbbrevVal))
1192  {
1193  /*
1194  * Clear and select the working context for evaluation of the equality
1195  * function and transition function.
1196  */
1197  MemoryContextReset(workcontext);
1198  oldContext = MemoryContextSwitchTo(workcontext);
1199 
1200  /*
1201  * If DISTINCT mode, and not distinct from prior, skip it.
1202  *
1203  * Note: we assume equality functions don't care about collation.
1204  */
1205  if (isDistinct &&
1206  haveOldVal &&
1207  ((oldIsNull && *isNull) ||
1208  (!oldIsNull && !*isNull &&
1209  oldAbbrevVal == newAbbrevVal &&
1210  DatumGetBool(FunctionCall2(&pertrans->equalfns[0],
1211  oldVal, *newVal)))))
1212  {
1213  /* equal to prior, so forget this one */
1214  if (!pertrans->inputtypeByVal && !*isNull)
1215  pfree(DatumGetPointer(*newVal));
1216  }
1217  else
1218  {
1219  advance_transition_function(aggstate, pertrans, pergroupstate);
1220  /* forget the old value, if any */
1221  if (!oldIsNull && !pertrans->inputtypeByVal)
1222  pfree(DatumGetPointer(oldVal));
1223  /* and remember the new one for subsequent equality checks */
1224  oldVal = *newVal;
1225  oldAbbrevVal = newAbbrevVal;
1226  oldIsNull = *isNull;
1227  haveOldVal = true;
1228  }
1229 
1230  MemoryContextSwitchTo(oldContext);
1231  }
1232 
1233  if (!oldIsNull && !pertrans->inputtypeByVal)
1234  pfree(DatumGetPointer(oldVal));
1235 
1236  tuplesort_end(pertrans->sortstates[aggstate->current_set]);
1237  pertrans->sortstates[aggstate->current_set] = NULL;
1238 }
bool tuplesort_getdatum(Tuplesortstate *state, bool forward, Datum *val, bool *isNull, Datum *abbrev)
Definition: tuplesort.c:2183
void tuplesort_performsort(Tuplesortstate *state)
Definition: tuplesort.c:1763
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:134
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define FunctionCall2(flinfo, arg1, arg2)
Definition: fmgr.h:575
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
int current_set
Definition: execnodes.h:1884
ExprContext * tmpcontext
Definition: execnodes.h:1879
FunctionCallInfoData transfn_fcinfo
Definition: nodeAgg.c:334
void pfree(void *pointer)
Definition: mcxt.c:992
Tuplesortstate ** sortstates
Definition: nodeAgg.c:326
#define DatumGetBool(X)
Definition: postgres.h:401
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:78
uintptr_t Datum
Definition: postgres.h:374
static void advance_transition_function(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroupstate)
Definition: nodeAgg.c:726
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:77
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define DatumGetPointer(X)
Definition: postgres.h:557
FmgrInfo * equalfns
Definition: nodeAgg.c:276
void tuplesort_end(Tuplesortstate *state)
Definition: tuplesort.c:1157
static TupleTableSlot * project_aggregates ( AggState aggstate)
static

Definition at line 1635 of file nodeAgg.c.

References ExecProject(), ExecQual(), InstrCountFiltered1, NULL, ScanState::ps, PlanState::ps_ExprContext, PlanState::ps_ProjInfo, PlanState::qual, and AggState::ss.

Referenced by agg_retrieve_direct(), and agg_retrieve_hash_table().

1636 {
1637  ExprContext *econtext = aggstate->ss.ps.ps_ExprContext;
1638 
1639  /*
1640  * Check the qual (HAVING clause); if the group does not match, ignore it.
1641  */
1642  if (ExecQual(aggstate->ss.ps.qual, econtext, false))
1643  {
1644  /*
1645  * Form and return projection tuple using the aggregate results and
1646  * the representative input tuple.
1647  */
1648  return ExecProject(aggstate->ss.ps.ps_ProjInfo);
1649  }
1650  else
1651  InstrCountFiltered1(aggstate, 1);
1652 
1653  return NULL;
1654 }
TupleTableSlot * ExecProject(ProjectionInfo *projInfo)
Definition: execQual.c:5214
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1079
ScanState ss
Definition: execnodes.h:1867
ExprContext * ps_ExprContext
Definition: execnodes.h:1078
List * qual
Definition: execnodes.h:1062
PlanState ps
Definition: execnodes.h:1288
bool ExecQual(List *qual, ExprContext *econtext, bool resultForNull)
Definition: execQual.c:5055
#define InstrCountFiltered1(node, delta)
Definition: execnodes.h:1093
#define NULL
Definition: c.h:226