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 22 static TupleTableSlot *CteScanNext(CteScanState *node); 23 24 /* ---------------------------------------------------------------- 25 * CteScanNext 26 * 27 * This is a workhorse for ExecCteScan 28 * ---------------------------------------------------------------- 29 */ 30 static TupleTableSlot * 31 CteScanNext(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 */ 144 static bool 145 CteScanRecheck(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 */ 159 static TupleTableSlot * 160 ExecCteScan(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 */ 174 CteScanState * 175 ExecInitCteScan(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 */ 287 void 288 ExecEndCteScan(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 */ 318 void 319 ExecReScanCteScan(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