PostgreSQL Source Code  git master
nodeRecursiveunion.c File Reference
#include "postgres.h"
#include "executor/execdebug.h"
#include "executor/nodeRecursiveunion.h"
#include "miscadmin.h"
#include "utils/memutils.h"
Include dependency graph for nodeRecursiveunion.c:

Go to the source code of this file.

Functions

static void build_hash_table (RecursiveUnionState *rustate)
 
static TupleTableSlotExecRecursiveUnion (PlanState *pstate)
 
RecursiveUnionStateExecInitRecursiveUnion (RecursiveUnion *node, EState *estate, int eflags)
 
void ExecEndRecursiveUnion (RecursiveUnionState *node)
 
void ExecReScanRecursiveUnion (RecursiveUnionState *node)
 

Function Documentation

◆ build_hash_table()

static void build_hash_table ( RecursiveUnionState rustate)
static

Definition at line 32 of file nodeRecursiveunion.c.

References Assert, BuildTupleHashTable(), RecursiveUnion::dupColIdx, RecursiveUnionState::eqfuncoids, ExecGetResultType(), RecursiveUnionState::hashfunctions, RecursiveUnionState::hashtable, RecursiveUnion::numCols, RecursiveUnion::numGroups, outerPlanState, PlanState::plan, RecursiveUnionState::ps, RecursiveUnionState::tableContext, and RecursiveUnionState::tempContext.

Referenced by ExecInitRecursiveUnion(), and ExecReScanRecursiveUnion().

33 {
34  RecursiveUnion *node = (RecursiveUnion *) rustate->ps.plan;
36 
37  Assert(node->numCols > 0);
38  Assert(node->numGroups > 0);
39 
40  rustate->hashtable = BuildTupleHashTable(&rustate->ps,
41  desc,
42  node->numCols,
43  node->dupColIdx,
44  rustate->eqfuncoids,
45  rustate->hashfunctions,
46  node->numGroups,
47  0,
48  rustate->tableContext,
49  rustate->tempContext,
50  false);
51 }
FmgrInfo * hashfunctions
Definition: execnodes.h:1142
AttrNumber * dupColIdx
Definition: plannodes.h:301
MemoryContext tempContext
Definition: execnodes.h:1143
#define outerPlanState(node)
Definition: execnodes.h:965
TupleHashTable hashtable
Definition: execnodes.h:1144
Plan * plan
Definition: execnodes.h:911
MemoryContext tableContext
Definition: execnodes.h:1145
#define Assert(condition)
Definition: c.h:699
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:438
TupleHashTable BuildTupleHashTable(PlanState *parent, TupleDesc inputDesc, int numCols, AttrNumber *keyColIdx, Oid *eqfuncoids, FmgrInfo *hashfunctions, long nbuckets, Size additionalsize, MemoryContext tablecxt, MemoryContext tempcxt, bool use_variable_hash_iv)
Definition: execGrouping.c:152

◆ ExecEndRecursiveUnion()

void ExecEndRecursiveUnion ( RecursiveUnionState node)

Definition at line 270 of file nodeRecursiveunion.c.

References ExecClearTuple(), ExecEndNode(), innerPlanState, RecursiveUnionState::intermediate_table, MemoryContextDelete(), outerPlanState, RecursiveUnionState::ps, PlanState::ps_ResultTupleSlot, RecursiveUnionState::tableContext, RecursiveUnionState::tempContext, tuplestore_end(), and RecursiveUnionState::working_table.

Referenced by ExecEndNode().

271 {
272  /* Release tuplestores */
275 
276  /* free subsidiary stuff including hashtable */
277  if (node->tempContext)
279  if (node->tableContext)
281 
282  /*
283  * clean out the upper tuple table
284  */
286 
287  /*
288  * close down subplans
289  */
292 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
Tuplestorestate * intermediate_table
Definition: execnodes.h:1139
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:539
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:475
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:945
MemoryContext tempContext
Definition: execnodes.h:1143
#define outerPlanState(node)
Definition: execnodes.h:965
Tuplestorestate * working_table
Definition: execnodes.h:1138
MemoryContext tableContext
Definition: execnodes.h:1145
void tuplestore_end(Tuplestorestate *state)
Definition: tuplestore.c:453
#define innerPlanState(node)
Definition: execnodes.h:964

◆ ExecInitRecursiveUnion()

RecursiveUnionState* ExecInitRecursiveUnion ( RecursiveUnion node,
EState estate,
int  eflags 
)

Definition at line 165 of file nodeRecursiveunion.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, build_hash_table(), CurrentMemoryContext, RecursiveUnion::dupOperators, RecursiveUnionState::eqfuncoids, EState::es_param_exec_vals, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, ExecInitNode(), ExecInitResultTupleSlotTL(), ParamExecData::execPlan, PlanState::ExecProcNode, ExecRecursiveUnion(), execTuplesHashPrepare(), RecursiveUnionState::hashfunctions, RecursiveUnionState::hashtable, innerPlan, innerPlanState, RecursiveUnionState::intermediate_empty, RecursiveUnionState::intermediate_table, ParamExecData::isnull, makeNode, NIL, RecursiveUnion::numCols, outerPlan, outerPlanState, RecursiveUnion::plan, PlanState::plan, PointerGetDatum, RecursiveUnionState::ps, PlanState::ps_ProjInfo, Plan::qual, RecursiveUnionState::recursing, PlanState::state, RecursiveUnionState::tableContext, RecursiveUnionState::tempContext, tuplestore_begin_heap(), ParamExecData::value, work_mem, RecursiveUnionState::working_table, and RecursiveUnion::wtParam.

Referenced by ExecInitNode().

166 {
167  RecursiveUnionState *rustate;
168  ParamExecData *prmdata;
169 
170  /* check for unsupported flags */
171  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
172 
173  /*
174  * create state structure
175  */
176  rustate = makeNode(RecursiveUnionState);
177  rustate->ps.plan = (Plan *) node;
178  rustate->ps.state = estate;
180 
181  rustate->eqfuncoids = NULL;
182  rustate->hashfunctions = NULL;
183  rustate->hashtable = NULL;
184  rustate->tempContext = NULL;
185  rustate->tableContext = NULL;
186 
187  /* initialize processing state */
188  rustate->recursing = false;
189  rustate->intermediate_empty = true;
190  rustate->working_table = tuplestore_begin_heap(false, false, work_mem);
191  rustate->intermediate_table = tuplestore_begin_heap(false, false, work_mem);
192 
193  /*
194  * If hashing, we need a per-tuple memory context for comparisons, and a
195  * longer-lived context to store the hash table. The table can't just be
196  * kept in the per-query context because we want to be able to throw it
197  * away when rescanning.
198  */
199  if (node->numCols > 0)
200  {
201  rustate->tempContext =
203  "RecursiveUnion",
205  rustate->tableContext =
207  "RecursiveUnion hash table",
209  }
210 
211  /*
212  * Make the state structure available to descendant WorkTableScan nodes
213  * via the Param slot reserved for it.
214  */
215  prmdata = &(estate->es_param_exec_vals[node->wtParam]);
216  Assert(prmdata->execPlan == NULL);
217  prmdata->value = PointerGetDatum(rustate);
218  prmdata->isnull = false;
219 
220  /*
221  * Miscellaneous initialization
222  *
223  * RecursiveUnion plans don't have expression contexts because they never
224  * call ExecQual or ExecProject.
225  */
226  Assert(node->plan.qual == NIL);
227 
228  /*
229  * RecursiveUnion nodes still have Result slots, which hold pointers to
230  * tuples, so we have to initialize them.
231  */
232  ExecInitResultTupleSlotTL(estate, &rustate->ps);
233 
234  /*
235  * Initialize result tuple type. (Note: we have to set up the result type
236  * before initializing child nodes, because nodeWorktablescan.c expects it
237  * to be valid.)
238  */
239  rustate->ps.ps_ProjInfo = NULL;
240 
241  /*
242  * initialize child nodes
243  */
244  outerPlanState(rustate) = ExecInitNode(outerPlan(node), estate, eflags);
245  innerPlanState(rustate) = ExecInitNode(innerPlan(node), estate, eflags);
246 
247  /*
248  * If hashing, precompute fmgr lookup data for inner loop, and create the
249  * hash table.
250  */
251  if (node->numCols > 0)
252  {
254  node->dupOperators,
255  &rustate->eqfuncoids,
256  &rustate->hashfunctions);
257  build_hash_table(rustate);
258  }
259 
260  return rustate;
261 }
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:147
void execTuplesHashPrepare(int numCols, Oid *eqOperators, Oid **eqFuncOids, FmgrInfo **hashFunctions)
Definition: execGrouping.c:95
void * execPlan
Definition: params.h:147
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:947
Tuplestorestate * intermediate_table
Definition: execnodes.h:1139
#define PointerGetDatum(X)
Definition: postgres.h:539
FmgrInfo * hashfunctions
Definition: execnodes.h:1142
EState * state
Definition: execnodes.h:913
ParamExecData * es_param_exec_vals
Definition: execnodes.h:518
bool isnull
Definition: params.h:149
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
#define EXEC_FLAG_BACKWARD
Definition: executor.h:60
MemoryContext tempContext
Definition: execnodes.h:1143
#define outerPlanState(node)
Definition: execnodes.h:965
#define innerPlan(node)
Definition: plannodes.h:175
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
TupleHashTable hashtable
Definition: execnodes.h:1144
static TupleTableSlot * ExecRecursiveUnion(PlanState *pstate)
Tuplestorestate * working_table
Definition: execnodes.h:1138
#define outerPlan(node)
Definition: plannodes.h:176
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:170
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:917
int work_mem
Definition: globals.c:122
void ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate)
Definition: execTuples.c:890
Plan * plan
Definition: execnodes.h:911
#define makeNode(_type_)
Definition: nodes.h:565
MemoryContext tableContext
Definition: execnodes.h:1145
#define Assert(condition)
Definition: c.h:699
#define EXEC_FLAG_MARK
Definition: executor.h:61
Oid * dupOperators
Definition: plannodes.h:302
static void build_hash_table(RecursiveUnionState *rustate)
Datum value
Definition: params.h:148
#define innerPlanState(node)
Definition: execnodes.h:964
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:139

◆ ExecRecursiveUnion()

static TupleTableSlot* ExecRecursiveUnion ( PlanState pstate)
static

Definition at line 73 of file nodeRecursiveunion.c.

References bms_add_member(), castNode, CHECK_FOR_INTERRUPTS, PlanState::chgParam, ExecProcNode(), RecursiveUnionState::hashtable, innerPlan, innerPlanState, RecursiveUnionState::intermediate_empty, RecursiveUnionState::intermediate_table, LookupTupleHashEntry(), MemoryContextReset(), RecursiveUnion::numCols, outerPlan, outerPlanState, PlanState::plan, RecursiveUnionState::ps, RecursiveUnionState::recursing, RecursiveUnionState::tempContext, TupIsNull, tuplestore_begin_heap(), tuplestore_end(), tuplestore_puttupleslot(), work_mem, RecursiveUnionState::working_table, and RecursiveUnion::wtParam.

Referenced by ExecInitRecursiveUnion().

74 {
78  RecursiveUnion *plan = (RecursiveUnion *) node->ps.plan;
79  TupleTableSlot *slot;
80  bool isnew;
81 
83 
84  /* 1. Evaluate non-recursive term */
85  if (!node->recursing)
86  {
87  for (;;)
88  {
89  slot = ExecProcNode(outerPlan);
90  if (TupIsNull(slot))
91  break;
92  if (plan->numCols > 0)
93  {
94  /* Find or build hashtable entry for this tuple's group */
95  LookupTupleHashEntry(node->hashtable, slot, &isnew);
96  /* Must reset temp context after each hashtable lookup */
98  /* Ignore tuple if already seen */
99  if (!isnew)
100  continue;
101  }
102  /* Each non-duplicate tuple goes to the working table ... */
104  /* ... and to the caller */
105  return slot;
106  }
107  node->recursing = true;
108  }
109 
110  /* 2. Execute recursive term */
111  for (;;)
112  {
113  slot = ExecProcNode(innerPlan);
114  if (TupIsNull(slot))
115  {
116  /* Done if there's nothing in the intermediate table */
117  if (node->intermediate_empty)
118  break;
119 
120  /* done with old working table ... */
122 
123  /* intermediate table becomes working table */
124  node->working_table = node->intermediate_table;
125 
126  /* create new empty intermediate table */
127  node->intermediate_table = tuplestore_begin_heap(false, false,
128  work_mem);
129  node->intermediate_empty = true;
130 
131  /* reset the recursive term */
132  innerPlan->chgParam = bms_add_member(innerPlan->chgParam,
133  plan->wtParam);
134 
135  /* and continue fetching from recursive term */
136  continue;
137  }
138 
139  if (plan->numCols > 0)
140  {
141  /* Find or build hashtable entry for this tuple's group */
142  LookupTupleHashEntry(node->hashtable, slot, &isnew);
143  /* Must reset temp context after each hashtable lookup */
145  /* Ignore tuple if already seen */
146  if (!isnew)
147  continue;
148  }
149 
150  /* Else, tuple is good; stash it in intermediate table ... */
151  node->intermediate_empty = false;
153  /* ... and return it */
154  return slot;
155  }
156 
157  return NULL;
158 }
void tuplestore_puttupleslot(Tuplestorestate *state, TupleTableSlot *slot)
Definition: tuplestore.c:708
Tuplestorestate * intermediate_table
Definition: execnodes.h:1139
#define castNode(_type_, nodeptr)
Definition: nodes.h:586
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:136
MemoryContext tempContext
Definition: execnodes.h:1143
#define outerPlanState(node)
Definition: execnodes.h:965
#define innerPlan(node)
Definition: plannodes.h:175
#define TupIsNull(slot)
Definition: tuptable.h:146
TupleHashEntry LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew)
Definition: execGrouping.c:233
TupleHashTable hashtable
Definition: execnodes.h:1144
Bitmapset * chgParam
Definition: execnodes.h:940
Tuplestorestate * working_table
Definition: execnodes.h:1138
#define outerPlan(node)
Definition: plannodes.h:176
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:233
int work_mem
Definition: globals.c:122
Plan * plan
Definition: execnodes.h:911
void tuplestore_end(Tuplestorestate *state)
Definition: tuplestore.c:453
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:764
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define innerPlanState(node)
Definition: execnodes.h:964

◆ ExecReScanRecursiveUnion()

void ExecReScanRecursiveUnion ( RecursiveUnionState node)

Definition at line 301 of file nodeRecursiveunion.c.

References bms_add_member(), build_hash_table(), PlanState::chgParam, ExecReScan(), innerPlan, innerPlanState, RecursiveUnionState::intermediate_empty, RecursiveUnionState::intermediate_table, MemoryContextResetAndDeleteChildren, RecursiveUnion::numCols, outerPlan, outerPlanState, PlanState::plan, RecursiveUnionState::ps, RecursiveUnionState::recursing, RecursiveUnionState::tableContext, tuplestore_clear(), RecursiveUnionState::working_table, and RecursiveUnion::wtParam.

Referenced by ExecReScan().

302 {
305  RecursiveUnion *plan = (RecursiveUnion *) node->ps.plan;
306 
307  /*
308  * Set recursive term's chgParam to tell it that we'll modify the working
309  * table and therefore it has to rescan.
310  */
311  innerPlan->chgParam = bms_add_member(innerPlan->chgParam, plan->wtParam);
312 
313  /*
314  * if chgParam of subnode is not null then plan will be re-scanned by
315  * first ExecProcNode. Because of above, we only have to do this to the
316  * non-recursive term.
317  */
318  if (outerPlan->chgParam == NULL)
319  ExecReScan(outerPlan);
320 
321  /* Release any hashtable storage */
322  if (node->tableContext)
324 
325  /* And rebuild empty hashtable if needed */
326  if (plan->numCols > 0)
327  build_hash_table(node);
328 
329  /* reset processing state */
330  node->recursing = false;
331  node->intermediate_empty = true;
334 }
Tuplestorestate * intermediate_table
Definition: execnodes.h:1139
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
void tuplestore_clear(Tuplestorestate *state)
Definition: tuplestore.c:418
#define outerPlanState(node)
Definition: execnodes.h:965
#define innerPlan(node)
Definition: plannodes.h:175
Bitmapset * chgParam
Definition: execnodes.h:940
Tuplestorestate * working_table
Definition: execnodes.h:1138
#define outerPlan(node)
Definition: plannodes.h:176
#define MemoryContextResetAndDeleteChildren(ctx)
Definition: memutils.h:67
Plan * plan
Definition: execnodes.h:911
MemoryContext tableContext
Definition: execnodes.h:1145
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:764
static void build_hash_table(RecursiveUnionState *rustate)
#define innerPlanState(node)
Definition: execnodes.h:964