PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
nodeCtescan.c File Reference
#include "postgres.h"
#include "executor/execdebug.h"
#include "executor/nodeCtescan.h"
#include "miscadmin.h"
Include dependency graph for nodeCtescan.c:

Go to the source code of this file.

Functions

static TupleTableSlotCteScanNext (CteScanState *node)
 
static bool CteScanRecheck (CteScanState *node, TupleTableSlot *slot)
 
static TupleTableSlotExecCteScan (PlanState *pstate)
 
CteScanStateExecInitCteScan (CteScan *node, EState *estate, int eflags)
 
void ExecEndCteScan (CteScanState *node)
 
void ExecReScanCteScan (CteScanState *node)
 

Function Documentation

static TupleTableSlot * CteScanNext ( CteScanState node)
static

Definition at line 31 of file nodeCtescan.c.

References CteScanState::cte_table, CteScanState::cteplanstate, CteScanState::eof_cte, EState::es_direction, ExecClearTuple(), ExecCopySlot(), ExecProcNode(), CteScanState::leader, NULL, ScanState::ps, CteScanState::readptr, ScanDirectionIsForward, CteScanState::ss, ScanState::ss_ScanTupleSlot, PlanState::state, TupIsNull, tuplestore_advance(), tuplestore_ateof(), tuplestore_gettupleslot(), tuplestore_puttupleslot(), and tuplestore_select_read_pointer().

Referenced by ExecCteScan().

32 {
33  EState *estate;
34  ScanDirection dir;
35  bool forward;
36  Tuplestorestate *tuplestorestate;
37  bool eof_tuplestore;
38  TupleTableSlot *slot;
39 
40  /*
41  * get state info from node
42  */
43  estate = node->ss.ps.state;
44  dir = estate->es_direction;
45  forward = ScanDirectionIsForward(dir);
46  tuplestorestate = node->leader->cte_table;
47  tuplestore_select_read_pointer(tuplestorestate, node->readptr);
48  slot = node->ss.ss_ScanTupleSlot;
49 
50  /*
51  * If we are not at the end of the tuplestore, or are going backwards, try
52  * to fetch a tuple from tuplestore.
53  */
54  eof_tuplestore = tuplestore_ateof(tuplestorestate);
55 
56  if (!forward && eof_tuplestore)
57  {
58  if (!node->leader->eof_cte)
59  {
60  /*
61  * When reversing direction at tuplestore EOF, the first
62  * gettupleslot call will fetch the last-added tuple; but we want
63  * to return the one before that, if possible. So do an extra
64  * fetch.
65  */
66  if (!tuplestore_advance(tuplestorestate, forward))
67  return NULL; /* the tuplestore must be empty */
68  }
69  eof_tuplestore = false;
70  }
71 
72  /*
73  * If we can fetch another tuple from the tuplestore, return it.
74  *
75  * Note: we have to use copy=true in the tuplestore_gettupleslot call,
76  * because we are sharing the tuplestore with other nodes that might write
77  * into the tuplestore before we get called again.
78  */
79  if (!eof_tuplestore)
80  {
81  if (tuplestore_gettupleslot(tuplestorestate, forward, true, slot))
82  return slot;
83  if (forward)
84  eof_tuplestore = true;
85  }
86 
87  /*
88  * If necessary, try to fetch another row from the CTE query.
89  *
90  * Note: the eof_cte state variable exists to short-circuit further calls
91  * of the CTE plan. It's not optional, unfortunately, because some plan
92  * node types are not robust about being called again when they've already
93  * returned NULL.
94  */
95  if (eof_tuplestore && !node->leader->eof_cte)
96  {
97  TupleTableSlot *cteslot;
98 
99  /*
100  * We can only get here with forward==true, so no need to worry about
101  * which direction the subplan will go.
102  */
103  cteslot = ExecProcNode(node->cteplanstate);
104  if (TupIsNull(cteslot))
105  {
106  node->leader->eof_cte = true;
107  return NULL;
108  }
109 
110  /*
111  * Append a copy of the returned tuple to tuplestore. NOTE: because
112  * our read pointer is certainly in EOF state, its read position will
113  * move forward over the added tuple. This is what we want. Also,
114  * any other readers will *not* move past the new tuple, which is what
115  * they want.
116  */
117  tuplestore_puttupleslot(tuplestorestate, cteslot);
118 
119  /*
120  * We MUST copy the CTE query's output tuple into our own slot. This
121  * is because other CteScan nodes might advance the CTE query before
122  * we are called again, and our output tuple must stay stable over
123  * that.
124  */
125  return ExecCopySlot(slot, cteslot);
126  }
127 
128  /*
129  * Nothing left ...
130  */
131  return ExecClearTuple(slot);
132 }
void tuplestore_puttupleslot(Tuplestorestate *state, TupleTableSlot *slot)
Definition: tuplestore.c:708
bool tuplestore_advance(Tuplestorestate *state, bool forward)
Definition: tuplestore.c:1110
#define ScanDirectionIsForward(direction)
Definition: sdir.h:55
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
struct CteScanState * leader
Definition: execnodes.h:1492
ScanState ss
Definition: execnodes.h:1487
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1098
EState * state
Definition: execnodes.h:846
ScanDirection es_direction
Definition: execnodes.h:428
PlanState ps
Definition: execnodes.h:1095
ScanDirection
Definition: sdir.h:22
#define TupIsNull(slot)
Definition: tuptable.h:138
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:244
TupleTableSlot * ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
Definition: execTuples.c:795
bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)
Definition: tuplestore.c:1078
#define NULL
Definition: c.h:229
PlanState * cteplanstate
Definition: execnodes.h:1490
void tuplestore_select_read_pointer(Tuplestorestate *state, int ptr)
Definition: tuplestore.c:473
bool tuplestore_ateof(Tuplestorestate *state)
Definition: tuplestore.c:557
Tuplestorestate * cte_table
Definition: execnodes.h:1494
static bool CteScanRecheck ( CteScanState node,
TupleTableSlot slot 
)
static

Definition at line 138 of file nodeCtescan.c.

Referenced by ExecCteScan().

139 {
140  /* nothing to check */
141  return true;
142 }
static TupleTableSlot* ExecCteScan ( PlanState pstate)
static

Definition at line 153 of file nodeCtescan.c.

References castNode, CteScanNext(), CteScanRecheck(), ExecScan(), and CteScanState::ss.

Referenced by ExecInitCteScan().

154 {
155  CteScanState *node = castNode(CteScanState, pstate);
156 
157  return ExecScan(&node->ss,
160 }
static bool CteScanRecheck(CteScanState *node, TupleTableSlot *slot)
Definition: nodeCtescan.c:138
#define castNode(_type_, nodeptr)
Definition: nodes.h:578
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:121
ScanState ss
Definition: execnodes.h:1487
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:407
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:408
static TupleTableSlot * CteScanNext(CteScanState *node)
Definition: nodeCtescan.c:31
void ExecEndCteScan ( CteScanState node)

Definition at line 280 of file nodeCtescan.c.

References CteScanState::cte_table, ExecClearTuple(), ExecFreeExprContext(), CteScanState::leader, NULL, ScanState::ps, PlanState::ps_ResultTupleSlot, CteScanState::ss, ScanState::ss_ScanTupleSlot, and tuplestore_end().

Referenced by ExecEndNode().

281 {
282  /*
283  * Free exprcontext
284  */
285  ExecFreeExprContext(&node->ss.ps);
286 
287  /*
288  * clean out the tuple table
289  */
292 
293  /*
294  * If I am the leader, free the tuplestore.
295  */
296  if (node->leader == node)
297  {
298  tuplestore_end(node->cte_table);
299  node->cte_table = NULL;
300  }
301 }
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
struct CteScanState * leader
Definition: execnodes.h:1492
ScanState ss
Definition: execnodes.h:1487
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1098
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:516
PlanState ps
Definition: execnodes.h:1095
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:877
#define NULL
Definition: c.h:229
void tuplestore_end(Tuplestorestate *state)
Definition: tuplestore.c:453
Tuplestorestate * cte_table
Definition: execnodes.h:1494
CteScanState* ExecInitCteScan ( CteScan node,
EState estate,
int  eflags 
)

Definition at line 168 of file nodeCtescan.c.

References Assert, castNode, CteScanState::cte_table, CteScan::cteParam, CteScan::ctePlanId, CteScanState::cteplanstate, DatumGetPointer, CteScanState::eflags, CteScanState::eof_cte, EState::es_param_exec_vals, EState::es_subplanstates, EXEC_FLAG_MARK, EXEC_FLAG_REWIND, ExecAssignExprContext(), ExecAssignResultTypeFromTL(), ExecAssignScanProjectionInfo(), ExecAssignScanType(), ExecCteScan(), ExecGetResultType(), ExecInitQual(), ExecInitResultTupleSlot(), ExecInitScanTupleSlot(), ParamExecData::execPlan, PlanState::ExecProcNode, innerPlan, ParamExecData::isnull, CteScanState::leader, list_nth(), makeNode, NULL, outerPlan, Scan::plan, PlanState::plan, PointerGetDatum, ScanState::ps, Plan::qual, PlanState::qual, CteScanState::readptr, CteScan::scan, CteScanState::ss, PlanState::state, tuplestore_alloc_read_pointer(), tuplestore_begin_heap(), tuplestore_rescan(), tuplestore_select_read_pointer(), tuplestore_set_eflags(), ParamExecData::value, and work_mem.

Referenced by ExecInitNode().

169 {
170  CteScanState *scanstate;
171  ParamExecData *prmdata;
172 
173  /* check for unsupported flags */
174  Assert(!(eflags & EXEC_FLAG_MARK));
175 
176  /*
177  * For the moment we have to force the tuplestore to allow REWIND, because
178  * we might be asked to rescan the CTE even though upper levels didn't
179  * tell us to be prepared to do it efficiently. Annoying, since this
180  * prevents truncation of the tuplestore. XXX FIXME
181  */
182  eflags |= EXEC_FLAG_REWIND;
183 
184  /*
185  * CteScan should not have any children.
186  */
187  Assert(outerPlan(node) == NULL);
188  Assert(innerPlan(node) == NULL);
189 
190  /*
191  * create new CteScanState for node
192  */
193  scanstate = makeNode(CteScanState);
194  scanstate->ss.ps.plan = (Plan *) node;
195  scanstate->ss.ps.state = estate;
196  scanstate->ss.ps.ExecProcNode = ExecCteScan;
197  scanstate->eflags = eflags;
198  scanstate->cte_table = NULL;
199  scanstate->eof_cte = false;
200 
201  /*
202  * Find the already-initialized plan for the CTE query.
203  */
204  scanstate->cteplanstate = (PlanState *) list_nth(estate->es_subplanstates,
205  node->ctePlanId - 1);
206 
207  /*
208  * The Param slot associated with the CTE query is used to hold a pointer
209  * to the CteState of the first CteScan node that initializes for this
210  * CTE. This node will be the one that holds the shared state for all the
211  * CTEs, particularly the shared tuplestore.
212  */
213  prmdata = &(estate->es_param_exec_vals[node->cteParam]);
214  Assert(prmdata->execPlan == NULL);
215  Assert(!prmdata->isnull);
216  scanstate->leader = castNode(CteScanState, DatumGetPointer(prmdata->value));
217  if (scanstate->leader == NULL)
218  {
219  /* I am the leader */
220  prmdata->value = PointerGetDatum(scanstate);
221  scanstate->leader = scanstate;
222  scanstate->cte_table = tuplestore_begin_heap(true, false, work_mem);
223  tuplestore_set_eflags(scanstate->cte_table, scanstate->eflags);
224  scanstate->readptr = 0;
225  }
226  else
227  {
228  /* Not the leader */
229  /* Create my own read pointer, and ensure it is at start */
230  scanstate->readptr =
232  scanstate->eflags);
234  scanstate->readptr);
235  tuplestore_rescan(scanstate->leader->cte_table);
236  }
237 
238  /*
239  * Miscellaneous initialization
240  *
241  * create expression context for node
242  */
243  ExecAssignExprContext(estate, &scanstate->ss.ps);
244 
245  /*
246  * initialize child expressions
247  */
248  scanstate->ss.ps.qual =
249  ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
250 
251  /*
252  * tuple table initialization
253  */
254  ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
255  ExecInitScanTupleSlot(estate, &scanstate->ss);
256 
257  /*
258  * The scan tuple type (ie, the rowtype we expect to find in the work
259  * table) is the same as the result rowtype of the CTE query.
260  */
261  ExecAssignScanType(&scanstate->ss,
262  ExecGetResultType(scanstate->cteplanstate));
263 
264  /*
265  * Initialize result tuple type and projection info.
266  */
267  ExecAssignResultTypeFromTL(&scanstate->ss.ps);
268  ExecAssignScanProjectionInfo(&scanstate->ss);
269 
270  return scanstate;
271 }
void tuplestore_rescan(Tuplestorestate *state)
Definition: tuplestore.c:1233
static TupleTableSlot * ExecCteScan(PlanState *pstate)
Definition: nodeCtescan.c:153
List * qual
Definition: plannodes.h:145
void * execPlan
Definition: params.h:99
Plan plan
Definition: plannodes.h:328
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate)
Definition: execTuples.c:842
#define castNode(_type_, nodeptr)
Definition: nodes.h:578
void tuplestore_set_eflags(Tuplestorestate *state, int eflags)
Definition: tuplestore.c:359
#define PointerGetDatum(X)
Definition: postgres.h:562
struct CteScanState * leader
Definition: execnodes.h:1492
ScanState ss
Definition: execnodes.h:1487
EState * state
Definition: execnodes.h:846
ExprState * ExecInitQual(List *qual, PlanState *parent)
Definition: execExpr.c:160
void ExecAssignResultTypeFromTL(PlanState *planstate)
Definition: execUtils.c:440
PlanState ps
Definition: execnodes.h:1095
ParamExecData * es_param_exec_vals
Definition: execnodes.h:463
int cteParam
Definition: plannodes.h:540
void ExecAssignScanProjectionInfo(ScanState *node)
Definition: execScan.c:235
bool isnull
Definition: params.h:101
void ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
Definition: execTuples.c:832
Scan scan
Definition: plannodes.h:538
#define innerPlan(node)
Definition: plannodes.h:173
void * list_nth(const List *list, int n)
Definition: list.c:410
int ctePlanId
Definition: plannodes.h:539
#define EXEC_FLAG_REWIND
Definition: executor.h:59
#define outerPlan(node)
Definition: plannodes.h:174
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:850
int work_mem
Definition: globals.c:113
Plan * plan
Definition: execnodes.h:844
#define makeNode(_type_)
Definition: nodes.h:557
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
#define EXEC_FLAG_MARK
Definition: executor.h:61
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:418
List * es_subplanstates
Definition: execnodes.h:483
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:469
ExprState * qual
Definition: execnodes.h:862
#define DatumGetPointer(X)
Definition: postgres.h:555
int tuplestore_alloc_read_pointer(Tuplestorestate *state, int eflags)
Definition: tuplestore.c:383
PlanState * cteplanstate
Definition: execnodes.h:1490
void tuplestore_select_read_pointer(Tuplestorestate *state, int ptr)
Definition: tuplestore.c:473
Datum value
Definition: params.h:100
void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
Definition: execUtils.c:540
Tuplestorestate * cte_table
Definition: execnodes.h:1494
void ExecReScanCteScan ( CteScanState node)

Definition at line 310 of file nodeCtescan.c.

References PlanState::chgParam, CteScanState::cte_table, CteScanState::cteplanstate, CteScanState::eof_cte, ExecClearTuple(), ExecScanReScan(), CteScanState::leader, NULL, ScanState::ps, PlanState::ps_ResultTupleSlot, CteScanState::readptr, CteScanState::ss, tuplestore_clear(), tuplestore_rescan(), and tuplestore_select_read_pointer().

Referenced by ExecReScan().

311 {
312  Tuplestorestate *tuplestorestate = node->leader->cte_table;
313 
315 
316  ExecScanReScan(&node->ss);
317 
318  /*
319  * Clear the tuplestore if a new scan of the underlying CTE is required.
320  * This implicitly resets all the tuplestore's read pointers. Note that
321  * multiple CTE nodes might redundantly clear the tuplestore; that's OK,
322  * and not unduly expensive. We'll stop taking this path as soon as
323  * somebody has attempted to read something from the underlying CTE
324  * (thereby causing its chgParam to be cleared).
325  */
326  if (node->leader->cteplanstate->chgParam != NULL)
327  {
328  tuplestore_clear(tuplestorestate);
329  node->leader->eof_cte = false;
330  }
331  else
332  {
333  /*
334  * Else, just rewind my own pointer. Either the underlying CTE
335  * doesn't need a rescan (and we can re-read what's in the tuplestore
336  * now), or somebody else already took care of it.
337  */
338  tuplestore_select_read_pointer(tuplestorestate, node->readptr);
339  tuplestore_rescan(tuplestorestate);
340  }
341 }
void tuplestore_rescan(Tuplestorestate *state)
Definition: tuplestore.c:1233
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
struct CteScanState * leader
Definition: execnodes.h:1492
ScanState ss
Definition: execnodes.h:1487
PlanState ps
Definition: execnodes.h:1095
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:877
void tuplestore_clear(Tuplestorestate *state)
Definition: tuplestore.c:418
Bitmapset * chgParam
Definition: execnodes.h:872
#define NULL
Definition: c.h:229
PlanState * cteplanstate
Definition: execnodes.h:1490
void ExecScanReScan(ScanState *node)
Definition: execScan.c:327
void tuplestore_select_read_pointer(Tuplestorestate *state, int ptr)
Definition: tuplestore.c:473
Tuplestorestate * cte_table
Definition: execnodes.h:1494