/* ---------------------------------------------------------------- * ExecReScanRecursiveUnion * * Rescans the relation. * ---------------------------------------------------------------- */ void ExecReScanRecursiveUnion(RecursiveUnionState *node) { PlanState *outerPlan = outerPlanState(node); PlanState *innerPlan = innerPlanState(node); RecursiveUnion *plan = (RecursiveUnion *) node->ps.plan; /* * Set recursive term's chgParam to tell it that we'll modify the working * table and therefore it has to rescan. */ innerPlan->chgParam = bms_add_member(innerPlan->chgParam, plan->wtParam); /* * if chgParam of subnode is not null then plan will be re-scanned by * first ExecProcNode. Because of above, we only have to do this to the * non-recursive term. */ if (outerPlan->chgParam == NULL) ExecReScan(outerPlan); /* Release any hashtable storage */ if (node->tableContext) MemoryContextResetAndDeleteChildren(node->tableContext); /* And rebuild empty hashtable if needed */ if (plan->numCols > 0) build_hash_table(node); /* reset processing state */ node->recursing = false; node->intermediate_empty = true; tuplestore_clear(node->working_table); tuplestore_clear(node->intermediate_table); }
/* ---------------------------------------------------------------- * ExecReScanCteScan * * Rescans the relation. * ---------------------------------------------------------------- */ void ExecReScanCteScan(CteScanState *node) { Tuplestorestate *tuplestorestate = node->leader->cte_table; ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecScanReScan(&node->ss); /* * Clear the tuplestore if a new scan of the underlying CTE is required. * This implicitly resets all the tuplestore's read pointers. Note that * multiple CTE nodes might redundantly clear the tuplestore; that's OK, * and not unduly expensive. We'll stop taking this path as soon as * somebody has attempted to read something from the underlying CTE * (thereby causing its chgParam to be cleared). */ if (node->leader->cteplanstate->chgParam != NULL) { tuplestore_clear(tuplestorestate); node->leader->eof_cte = false; } else { /* * Else, just rewind my own pointer. Either the underlying CTE * doesn't need a rescan (and we can re-read what's in the tuplestore * now), or somebody else already took care of it. */ tuplestore_select_read_pointer(tuplestorestate, node->readptr); tuplestore_rescan(tuplestorestate); } }
/* ---------------------------------------------------------------- * ExecReScanCteScan * * Rescans the relation. * ---------------------------------------------------------------- */ void ExecReScanCteScan(CteScanState *node) { Tuplestorestate *tuplestorestate = node->leader->cte_table; ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecScanReScan(&node->ss); if (node->leader == node) { /* * The leader is responsible for clearing the tuplestore if a new scan * of the underlying CTE is required. */ if (node->cteplanstate->chgParam != NULL) { tuplestore_clear(tuplestorestate); node->eof_cte = false; } else { tuplestore_select_read_pointer(tuplestorestate, node->readptr); tuplestore_rescan(tuplestorestate); } } else { /* Not leader, so just rewind my own pointer */ tuplestore_select_read_pointer(tuplestorestate, node->readptr); tuplestore_rescan(tuplestorestate); } }