1/*-------------------------------------------------------------------------
2 *
3 * nodeCtescan.c
4 * routines to handle CteScan nodes.
5 *
6 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/executor/nodeCtescan.c
12 *
13 *-------------------------------------------------------------------------
14 */
15
16#include "postgres.h"
17
18#include "executor/execdebug.h"
19#include "executor/nodeCtescan.h"
20#include "miscadmin.h"
21
22static TupleTableSlot *CteScanNext(CteScanState *node);
23
24/* ----------------------------------------------------------------
25 * CteScanNext
26 *
27 * This is a workhorse for ExecCteScan
28 * ----------------------------------------------------------------
29 */
30static TupleTableSlot *
31CteScanNext(CteScanState *node)
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 * There are corner cases where the subplan could change which
112 * tuplestore read pointer is active, so be sure to reselect ours
113 * before storing the tuple we got.
114 */
115 tuplestore_select_read_pointer(tuplestorestate, node->readptr);
116
117 /*
118 * Append a copy of the returned tuple to tuplestore. NOTE: because
119 * our read pointer is certainly in EOF state, its read position will
120 * move forward over the added tuple. This is what we want. Also,
121 * any other readers will *not* move past the new tuple, which is what
122 * they want.
123 */
124 tuplestore_puttupleslot(tuplestorestate, cteslot);
125
126 /*
127 * We MUST copy the CTE query's output tuple into our own slot. This
128 * is because other CteScan nodes might advance the CTE query before
129 * we are called again, and our output tuple must stay stable over
130 * that.
131 */
132 return ExecCopySlot(slot, cteslot);
133 }
134
135 /*
136 * Nothing left ...
137 */
138 return ExecClearTuple(slot);
139}
140
141/*
142 * CteScanRecheck -- access method routine to recheck a tuple in EvalPlanQual
143 */
144static bool
145CteScanRecheck(CteScanState *node, TupleTableSlot *slot)
146{
147 /* nothing to check */
148 return true;
149}
150
151/* ----------------------------------------------------------------
152 * ExecCteScan(node)
153 *
154 * Scans the CTE sequentially and returns the next qualifying tuple.
155 * We call the ExecScan() routine and pass it the appropriate
156 * access method functions.
157 * ----------------------------------------------------------------
158 */
159static TupleTableSlot *
160ExecCteScan(PlanState *pstate)
161{
162 CteScanState *node = castNode(CteScanState, pstate);
163
164 return ExecScan(&node->ss,
165 (ExecScanAccessMtd) CteScanNext,
166 (ExecScanRecheckMtd) CteScanRecheck);
167}
168
169
170/* ----------------------------------------------------------------
171 * ExecInitCteScan
172 * ----------------------------------------------------------------
173 */
174CteScanState *
175ExecInitCteScan(CteScan *node, EState *estate, int eflags)
176{
177 CteScanState *scanstate;
178 ParamExecData *prmdata;
179
180 /* check for unsupported flags */
181 Assert(!(eflags & EXEC_FLAG_MARK));
182
183 /*
184 * For the moment we have to force the tuplestore to allow REWIND, because
185 * we might be asked to rescan the CTE even though upper levels didn't
186 * tell us to be prepared to do it efficiently. Annoying, since this
187 * prevents truncation of the tuplestore. XXX FIXME
188 *
189 * Note: if we are in an EPQ recheck plan tree, it's likely that no access
190 * to the tuplestore is needed at all, making this even more annoying.
191 * It's not worth improving that as long as all the read pointers would
192 * have REWIND anyway, but if we ever improve this logic then that aspect
193 * should be considered too.
194 */
195 eflags |= EXEC_FLAG_REWIND;
196
197 /*
198 * CteScan should not have any children.
199 */
200 Assert(outerPlan(node) == NULL);
201 Assert(innerPlan(node) == NULL);
202
203 /*
204 * create new CteScanState for node
205 */
206 scanstate = makeNode(CteScanState);
207 scanstate->ss.ps.plan = (Plan *) node;
208 scanstate->ss.ps.state = estate;
209 scanstate->ss.ps.ExecProcNode = ExecCteScan;
210 scanstate->eflags = eflags;
211 scanstate->cte_table = NULL;
212 scanstate->eof_cte = false;
213
214 /*
215 * Find the already-initialized plan for the CTE query.
216 */
217 scanstate->cteplanstate = (PlanState *) list_nth(estate->es_subplanstates,
218 node->ctePlanId - 1);
219
220 /*
221 * The Param slot associated with the CTE query is used to hold a pointer
222 * to the CteState of the first CteScan node that initializes for this
223 * CTE. This node will be the one that holds the shared state for all the
224 * CTEs, particularly the shared tuplestore.
225 */
226 prmdata = &(estate->es_param_exec_vals[node->cteParam]);
227 Assert(prmdata->execPlan == NULL);
228 Assert(!prmdata->isnull);
229 scanstate->leader = castNode(CteScanState, DatumGetPointer(prmdata->value));
230 if (scanstate->leader == NULL)
231 {
232 /* I am the leader */
233 prmdata->value = PointerGetDatum(scanstate);
234 scanstate->leader = scanstate;
235 scanstate->cte_table = tuplestore_begin_heap(true, false, work_mem);
236 tuplestore_set_eflags(scanstate->cte_table, scanstate->eflags);
237 scanstate->readptr = 0;
238 }
239 else
240 {
241 /* Not the leader */
242 /* Create my own read pointer, and ensure it is at start */
243 scanstate->readptr =
244 tuplestore_alloc_read_pointer(scanstate->leader->cte_table,
245 scanstate->eflags);
246 tuplestore_select_read_pointer(scanstate->leader->cte_table,
247 scanstate->readptr);
248 tuplestore_rescan(scanstate->leader->cte_table);
249 }
250
251 /*
252 * Miscellaneous initialization
253 *
254 * create expression context for node
255 */
256 ExecAssignExprContext(estate, &scanstate->ss.ps);
257
258 /*
259 * The scan tuple type (ie, the rowtype we expect to find in the work
260 * table) is the same as the result rowtype of the CTE query.
261 */
262 ExecInitScanTupleSlot(estate, &scanstate->ss,
263 ExecGetResultType(scanstate->cteplanstate),
264 &TTSOpsMinimalTuple);
265
266 /*
267 * Initialize result type and projection.
268 */
269 ExecInitResultTypeTL(&scanstate->ss.ps);
270 ExecAssignScanProjectionInfo(&scanstate->ss);
271
272 /*
273 * initialize child expressions
274 */
275 scanstate->ss.ps.qual =
276 ExecInitQual(node->scan.plan.qual, (PlanState *) scanstate);
277
278 return scanstate;
279}
280
281/* ----------------------------------------------------------------
282 * ExecEndCteScan
283 *
284 * frees any storage allocated through C routines.
285 * ----------------------------------------------------------------
286 */
287void
288ExecEndCteScan(CteScanState *node)
289{
290 /*
291 * Free exprcontext
292 */
293 ExecFreeExprContext(&node->ss.ps);
294
295 /*
296 * clean out the tuple table
297 */
298 if (node->ss.ps.ps_ResultTupleSlot)
299 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
300 ExecClearTuple(node->ss.ss_ScanTupleSlot);
301
302 /*
303 * If I am the leader, free the tuplestore.
304 */
305 if (node->leader == node)
306 {
307 tuplestore_end(node->cte_table);
308 node->cte_table = NULL;
309 }
310}
311
312/* ----------------------------------------------------------------
313 * ExecReScanCteScan
314 *
315 * Rescans the relation.
316 * ----------------------------------------------------------------
317 */
318void
319ExecReScanCteScan(CteScanState *node)
320{
321 Tuplestorestate *tuplestorestate = node->leader->cte_table;
322
323 if (node->ss.ps.ps_ResultTupleSlot)
324 ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
325
326 ExecScanReScan(&node->ss);
327
328 /*
329 * Clear the tuplestore if a new scan of the underlying CTE is required.
330 * This implicitly resets all the tuplestore's read pointers. Note that
331 * multiple CTE nodes might redundantly clear the tuplestore; that's OK,
332 * and not unduly expensive. We'll stop taking this path as soon as
333 * somebody has attempted to read something from the underlying CTE
334 * (thereby causing its chgParam to be cleared).
335 */
336 if (node->leader->cteplanstate->chgParam != NULL)
337 {
338 tuplestore_clear(tuplestorestate);
339 node->leader->eof_cte = false;
340 }
341 else
342 {
343 /*
344 * Else, just rewind my own pointer. Either the underlying CTE
345 * doesn't need a rescan (and we can re-read what's in the tuplestore
346 * now), or somebody else already took care of it.
347 */
348 tuplestore_select_read_pointer(tuplestorestate, node->readptr);
349 tuplestore_rescan(tuplestorestate);
350 }
351}
352