---------------------------------------------------------------- * 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 | { |
no test coverage detected