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, BuildTupleHashTableExt(), RecursiveUnion::dupColIdx, RecursiveUnion::dupCollations, RecursiveUnionState::eqfuncoids, EState::es_query_cxt, ExecGetResultType(), RecursiveUnionState::hashfunctions, RecursiveUnionState::hashtable, RecursiveUnion::numCols, RecursiveUnion::numGroups, outerPlanState, PlanState::plan, RecursiveUnionState::ps, PlanState::state, RecursiveUnionState::tableContext, and RecursiveUnionState::tempContext.

Referenced by ExecInitRecursiveUnion().

33 {
34  RecursiveUnion *node = (RecursiveUnion *) rustate->ps.plan;
36 
37  Assert(node->numCols > 0);
38  Assert(node->numGroups > 0);
39 
40  rustate->hashtable = BuildTupleHashTableExt(&rustate->ps,
41  desc,
42  node->numCols,
43  node->dupColIdx,
44  rustate->eqfuncoids,
45  rustate->hashfunctions,
46  node->dupCollations,
47  node->numGroups,
48  0,
49  rustate->ps.state->es_query_cxt,
50  rustate->tableContext,
51  rustate->tempContext,
52  false);
53 }
TupleHashTable BuildTupleHashTableExt(PlanState *parent, TupleDesc inputDesc, int numCols, AttrNumber *keyColIdx, const Oid *eqfuncoids, FmgrInfo *hashfunctions, Oid *collations, long nbuckets, Size additionalsize, MemoryContext metacxt, MemoryContext tablecxt, MemoryContext tempcxt, bool use_variable_hash_iv)
Definition: execGrouping.c:154
FmgrInfo * hashfunctions
Definition: execnodes.h:1277
EState * state
Definition: execnodes.h:941
MemoryContext es_query_cxt
Definition: execnodes.h:549
AttrNumber * dupColIdx
Definition: plannodes.h:302
MemoryContext tempContext
Definition: execnodes.h:1278
#define outerPlanState(node)
Definition: execnodes.h:1033
Oid * dupCollations
Definition: plannodes.h:304
TupleHashTable hashtable
Definition: execnodes.h:1279
Plan * plan
Definition: execnodes.h:939
MemoryContext tableContext
Definition: execnodes.h:1280
#define Assert(condition)
Definition: c.h:739
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:454

◆ ExecEndRecursiveUnion()

void ExecEndRecursiveUnion ( RecursiveUnionState node)

Definition at line 272 of file nodeRecursiveunion.c.

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

Referenced by ExecEndNode().

273 {
274  /* Release tuplestores */
277 
278  /* free subsidiary stuff including hashtable */
279  if (node->tempContext)
281  if (node->tableContext)
283 
284  /*
285  * close down subplans
286  */
289 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
Tuplestorestate * intermediate_table
Definition: execnodes.h:1274
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:537
MemoryContext tempContext
Definition: execnodes.h:1278
#define outerPlanState(node)
Definition: execnodes.h:1033
Tuplestorestate * working_table
Definition: execnodes.h:1273
MemoryContext tableContext
Definition: execnodes.h:1280
void tuplestore_end(Tuplestorestate *state)
Definition: tuplestore.c:453
#define innerPlanState(node)
Definition: execnodes.h:1032

◆ ExecInitRecursiveUnion()

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

Definition at line 167 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(), ExecInitResultTypeTL(), 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().

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

◆ ExecRecursiveUnion()

static TupleTableSlot* ExecRecursiveUnion ( PlanState pstate)
static

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

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

◆ ExecReScanRecursiveUnion()

void ExecReScanRecursiveUnion ( RecursiveUnionState node)

Definition at line 298 of file nodeRecursiveunion.c.

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

Referenced by ExecReScan().

299 {
302  RecursiveUnion *plan = (RecursiveUnion *) node->ps.plan;
303 
304  /*
305  * Set recursive term's chgParam to tell it that we'll modify the working
306  * table and therefore it has to rescan.
307  */
308  innerPlan->chgParam = bms_add_member(innerPlan->chgParam, plan->wtParam);
309 
310  /*
311  * if chgParam of subnode is not null then plan will be re-scanned by
312  * first ExecProcNode. Because of above, we only have to do this to the
313  * non-recursive term.
314  */
315  if (outerPlan->chgParam == NULL)
316  ExecReScan(outerPlan);
317 
318  /* Release any hashtable storage */
319  if (node->tableContext)
321 
322  /* Empty hashtable if needed */
323  if (plan->numCols > 0)
325 
326  /* reset processing state */
327  node->recursing = false;
328  node->intermediate_empty = true;
331 }
Tuplestorestate * intermediate_table
Definition: execnodes.h:1274
void ExecReScan(PlanState *node)
Definition: execAmi.c:75
void ResetTupleHashTable(TupleHashTable hashtable)
Definition: execGrouping.c:282
void tuplestore_clear(Tuplestorestate *state)
Definition: tuplestore.c:418
#define outerPlanState(node)
Definition: execnodes.h:1033
#define innerPlan(node)
Definition: plannodes.h:171
TupleHashTable hashtable
Definition: execnodes.h:1279
Bitmapset * chgParam
Definition: execnodes.h:971
Tuplestorestate * working_table
Definition: execnodes.h:1273
#define outerPlan(node)
Definition: plannodes.h:172
#define MemoryContextResetAndDeleteChildren(ctx)
Definition: memutils.h:67
Plan * plan
Definition: execnodes.h:939
MemoryContext tableContext
Definition: execnodes.h:1280
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
#define innerPlanState(node)
Definition: execnodes.h:1032