PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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)
 
TupleTableSlotExecRecursiveUnion (RecursiveUnionState *node)
 
RecursiveUnionStateExecInitRecursiveUnion (RecursiveUnion *node, EState *estate, int eflags)
 
void ExecEndRecursiveUnion (RecursiveUnionState *node)
 
void ExecReScanRecursiveUnion (RecursiveUnionState *node)
 

Function Documentation

static void build_hash_table ( RecursiveUnionState rustate)
static

Definition at line 32 of file nodeRecursiveunion.c.

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

Referenced by ExecInitRecursiveUnion(), and ExecReScanRecursiveUnion().

33 {
34  RecursiveUnion *node = (RecursiveUnion *) rustate->ps.plan;
35 
36  Assert(node->numCols > 0);
37  Assert(node->numGroups > 0);
38 
39  rustate->hashtable = BuildTupleHashTable(node->numCols,
40  node->dupColIdx,
41  rustate->eqfunctions,
42  rustate->hashfunctions,
43  node->numGroups,
44  0,
45  rustate->tableContext,
46  rustate->tempContext,
47  false);
48 }
FmgrInfo * hashfunctions
Definition: execnodes.h:1026
AttrNumber * dupColIdx
Definition: plannodes.h:287
MemoryContext tempContext
Definition: execnodes.h:1027
FmgrInfo * eqfunctions
Definition: execnodes.h:1025
TupleHashTable hashtable
Definition: execnodes.h:1028
Plan * plan
Definition: execnodes.h:832
MemoryContext tableContext
Definition: execnodes.h:1029
#define Assert(condition)
Definition: c.h:675
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
void ExecEndRecursiveUnion ( RecursiveUnionState node)

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

265 {
266  /* Release tuplestores */
269 
270  /* free subsidiary stuff including hashtable */
271  if (node->tempContext)
273  if (node->tableContext)
275 
276  /*
277  * clean out the upper tuple table
278  */
280 
281  /*
282  * close down subplans
283  */
286 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
Tuplestorestate * intermediate_table
Definition: execnodes.h:1023
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:654
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:861
MemoryContext tempContext
Definition: execnodes.h:1027
#define outerPlanState(node)
Definition: execnodes.h:874
Tuplestorestate * working_table
Definition: execnodes.h:1022
MemoryContext tableContext
Definition: execnodes.h:1029
void tuplestore_end(Tuplestorestate *state)
Definition: tuplestore.c:453
#define innerPlanState(node)
Definition: execnodes.h:873
RecursiveUnionState* ExecInitRecursiveUnion ( RecursiveUnion node,
EState estate,
int  eflags 
)

Definition at line 159 of file nodeRecursiveunion.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), Assert, build_hash_table(), CurrentMemoryContext, RecursiveUnion::dupOperators, RecursiveUnionState::eqfunctions, EState::es_param_exec_vals, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, ExecAssignResultTypeFromTL(), ExecInitNode(), ExecInitResultTupleSlot(), ParamExecData::execPlan, execTuplesHashPrepare(), RecursiveUnionState::hashfunctions, RecursiveUnionState::hashtable, innerPlan, innerPlanState, RecursiveUnionState::intermediate_empty, RecursiveUnionState::intermediate_table, ParamExecData::isnull, makeNode, NIL, NULL, 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().

160 {
161  RecursiveUnionState *rustate;
162  ParamExecData *prmdata;
163 
164  /* check for unsupported flags */
165  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
166 
167  /*
168  * create state structure
169  */
170  rustate = makeNode(RecursiveUnionState);
171  rustate->ps.plan = (Plan *) node;
172  rustate->ps.state = estate;
173 
174  rustate->eqfunctions = NULL;
175  rustate->hashfunctions = NULL;
176  rustate->hashtable = NULL;
177  rustate->tempContext = NULL;
178  rustate->tableContext = NULL;
179 
180  /* initialize processing state */
181  rustate->recursing = false;
182  rustate->intermediate_empty = true;
183  rustate->working_table = tuplestore_begin_heap(false, false, work_mem);
184  rustate->intermediate_table = tuplestore_begin_heap(false, false, work_mem);
185 
186  /*
187  * If hashing, we need a per-tuple memory context for comparisons, and a
188  * longer-lived context to store the hash table. The table can't just be
189  * kept in the per-query context because we want to be able to throw it
190  * away when rescanning.
191  */
192  if (node->numCols > 0)
193  {
194  rustate->tempContext =
196  "RecursiveUnion",
198  rustate->tableContext =
200  "RecursiveUnion hash table",
202  }
203 
204  /*
205  * Make the state structure available to descendant WorkTableScan nodes
206  * via the Param slot reserved for it.
207  */
208  prmdata = &(estate->es_param_exec_vals[node->wtParam]);
209  Assert(prmdata->execPlan == NULL);
210  prmdata->value = PointerGetDatum(rustate);
211  prmdata->isnull = false;
212 
213  /*
214  * Miscellaneous initialization
215  *
216  * RecursiveUnion plans don't have expression contexts because they never
217  * call ExecQual or ExecProject.
218  */
219  Assert(node->plan.qual == NIL);
220 
221  /*
222  * RecursiveUnion nodes still have Result slots, which hold pointers to
223  * tuples, so we have to initialize them.
224  */
225  ExecInitResultTupleSlot(estate, &rustate->ps);
226 
227  /*
228  * Initialize result tuple type and projection info. (Note: we have to
229  * set up the result type before initializing child nodes, because
230  * nodeWorktablescan.c expects it to be valid.)
231  */
232  ExecAssignResultTypeFromTL(&rustate->ps);
233  rustate->ps.ps_ProjInfo = NULL;
234 
235  /*
236  * initialize child nodes
237  */
238  outerPlanState(rustate) = ExecInitNode(outerPlan(node), estate, eflags);
239  innerPlanState(rustate) = ExecInitNode(innerPlan(node), estate, eflags);
240 
241  /*
242  * If hashing, precompute fmgr lookup data for inner loop, and create the
243  * hash table.
244  */
245  if (node->numCols > 0)
246  {
248  node->dupOperators,
249  &rustate->eqfunctions,
250  &rustate->hashfunctions);
251  build_hash_table(rustate);
252  }
253 
254  return rustate;
255 }
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:145
void * execPlan
Definition: params.h:99
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:863
Tuplestorestate * intermediate_table
Definition: execnodes.h:1023
#define PointerGetDatum(X)
Definition: postgres.h:562
FmgrInfo * hashfunctions
Definition: execnodes.h:1026
EState * state
Definition: execnodes.h:834
void execTuplesHashPrepare(int numCols, Oid *eqOperators, FmgrInfo **eqFunctions, FmgrInfo **hashFunctions)
Definition: execGrouping.c:233
void ExecAssignResultTypeFromTL(PlanState *planstate)
Definition: execUtils.c:440
ParamExecData * es_param_exec_vals
Definition: execnodes.h:463
bool isnull
Definition: params.h:101
void ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
Definition: execTuples.c:832
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
#define EXEC_FLAG_BACKWARD
Definition: executor.h:60
MemoryContext tempContext
Definition: execnodes.h:1027
#define outerPlanState(node)
Definition: execnodes.h:874
#define innerPlan(node)
Definition: plannodes.h:173
FmgrInfo * eqfunctions
Definition: execnodes.h:1025
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
TupleHashTable hashtable
Definition: execnodes.h:1028
Tuplestorestate * working_table
Definition: execnodes.h:1022
#define outerPlan(node)
Definition: plannodes.h:174
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
int work_mem
Definition: globals.c:113
Plan * plan
Definition: execnodes.h:832
#define makeNode(_type_)
Definition: nodes.h:557
MemoryContext tableContext
Definition: execnodes.h:1029
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define EXEC_FLAG_MARK
Definition: executor.h:61
Oid * dupOperators
Definition: plannodes.h:288
static void build_hash_table(RecursiveUnionState *rustate)
Datum value
Definition: params.h:100
#define innerPlanState(node)
Definition: execnodes.h:873
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:140
TupleTableSlot* ExecRecursiveUnion ( RecursiveUnionState node)

Definition at line 70 of file nodeRecursiveunion.c.

References bms_add_member(), PlanState::chgParam, ExecProcNode(), RecursiveUnionState::hashtable, innerPlan, innerPlanState, RecursiveUnionState::intermediate_empty, RecursiveUnionState::intermediate_table, LookupTupleHashEntry(), MemoryContextReset(), NULL, 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 ExecProcNode().

71 {
74  RecursiveUnion *plan = (RecursiveUnion *) node->ps.plan;
75  TupleTableSlot *slot;
76  bool isnew;
77 
78  /* 1. Evaluate non-recursive term */
79  if (!node->recursing)
80  {
81  for (;;)
82  {
83  slot = ExecProcNode(outerPlan);
84  if (TupIsNull(slot))
85  break;
86  if (plan->numCols > 0)
87  {
88  /* Find or build hashtable entry for this tuple's group */
89  LookupTupleHashEntry(node->hashtable, slot, &isnew);
90  /* Must reset temp context after each hashtable lookup */
92  /* Ignore tuple if already seen */
93  if (!isnew)
94  continue;
95  }
96  /* Each non-duplicate tuple goes to the working table ... */
98  /* ... and to the caller */
99  return slot;
100  }
101  node->recursing = true;
102  }
103 
104  /* 2. Execute recursive term */
105  for (;;)
106  {
107  slot = ExecProcNode(innerPlan);
108  if (TupIsNull(slot))
109  {
110  /* Done if there's nothing in the intermediate table */
111  if (node->intermediate_empty)
112  break;
113 
114  /* done with old working table ... */
116 
117  /* intermediate table becomes working table */
118  node->working_table = node->intermediate_table;
119 
120  /* create new empty intermediate table */
121  node->intermediate_table = tuplestore_begin_heap(false, false,
122  work_mem);
123  node->intermediate_empty = true;
124 
125  /* reset the recursive term */
126  innerPlan->chgParam = bms_add_member(innerPlan->chgParam,
127  plan->wtParam);
128 
129  /* and continue fetching from recursive term */
130  continue;
131  }
132 
133  if (plan->numCols > 0)
134  {
135  /* Find or build hashtable entry for this tuple's group */
136  LookupTupleHashEntry(node->hashtable, slot, &isnew);
137  /* Must reset temp context after each hashtable lookup */
139  /* Ignore tuple if already seen */
140  if (!isnew)
141  continue;
142  }
143 
144  /* Else, tuple is good; stash it in intermediate table ... */
145  node->intermediate_empty = false;
147  /* ... and return it */
148  return slot;
149  }
150 
151  return NULL;
152 }
void tuplestore_puttupleslot(Tuplestorestate *state, TupleTableSlot *slot)
Definition: tuplestore.c:708
TupleTableSlot * ExecProcNode(PlanState *node)
Definition: execProcnode.c:398
Tuplestorestate * intermediate_table
Definition: execnodes.h:1023
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
MemoryContext tempContext
Definition: execnodes.h:1027
#define outerPlanState(node)
Definition: execnodes.h:874
#define innerPlan(node)
Definition: plannodes.h:173
#define TupIsNull(slot)
Definition: tuptable.h:138
TupleHashEntry LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew)
Definition: execGrouping.c:351
TupleHashTable hashtable
Definition: execnodes.h:1028
Bitmapset * chgParam
Definition: execnodes.h:856
Tuplestorestate * working_table
Definition: execnodes.h:1022
#define outerPlan(node)
Definition: plannodes.h:174
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
int work_mem
Definition: globals.c:113
Plan * plan
Definition: execnodes.h:832
#define NULL
Definition: c.h:229
void tuplestore_end(Tuplestorestate *state)
Definition: tuplestore.c:453
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:698
#define innerPlanState(node)
Definition: execnodes.h:873
void ExecReScanRecursiveUnion ( RecursiveUnionState node)

Definition at line 295 of file nodeRecursiveunion.c.

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

Referenced by ExecReScan().

296 {
299  RecursiveUnion *plan = (RecursiveUnion *) node->ps.plan;
300 
301  /*
302  * Set recursive term's chgParam to tell it that we'll modify the working
303  * table and therefore it has to rescan.
304  */
305  innerPlan->chgParam = bms_add_member(innerPlan->chgParam, plan->wtParam);
306 
307  /*
308  * if chgParam of subnode is not null then plan will be re-scanned by
309  * first ExecProcNode. Because of above, we only have to do this to the
310  * non-recursive term.
311  */
312  if (outerPlan->chgParam == NULL)
313  ExecReScan(outerPlan);
314 
315  /* Release any hashtable storage */
316  if (node->tableContext)
318 
319  /* And rebuild empty hashtable if needed */
320  if (plan->numCols > 0)
321  build_hash_table(node);
322 
323  /* reset processing state */
324  node->recursing = false;
325  node->intermediate_empty = true;
328 }
Tuplestorestate * intermediate_table
Definition: execnodes.h:1023
void ExecReScan(PlanState *node)
Definition: execAmi.c:75
void tuplestore_clear(Tuplestorestate *state)
Definition: tuplestore.c:418
#define outerPlanState(node)
Definition: execnodes.h:874
#define innerPlan(node)
Definition: plannodes.h:173
Bitmapset * chgParam
Definition: execnodes.h:856
Tuplestorestate * working_table
Definition: execnodes.h:1022
#define outerPlan(node)
Definition: plannodes.h:174
#define MemoryContextResetAndDeleteChildren(ctx)
Definition: memutils.h:67
Plan * plan
Definition: execnodes.h:832
MemoryContext tableContext
Definition: execnodes.h:1029
#define NULL
Definition: c.h:229
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:698
static void build_hash_table(RecursiveUnionState *rustate)
#define innerPlanState(node)
Definition: execnodes.h:873