/* ---------------------------------------------------------------- * 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); } }
/* ---------------------------------------------------------------- * ExecReScanIndexScan(node) * * Recalculates the values of any scan keys whose value depends on * information known at runtime, then rescans the indexed relation. * * Updating the scan key was formerly done separately in * ExecUpdateIndexScanKeys. Integrating it into ReScan makes * rescans of indices and relations/general streams more uniform. * ---------------------------------------------------------------- */ void ExecReScanIndexScan(IndexScanState *node) { /* * If we are doing runtime key calculations (ie, any of the index key * values weren't simple Consts), compute the new key values. But first, * reset the context so we don't leak memory as each outer tuple is * scanned. Note this assumes that we will recalculate *all* runtime keys * on each call. */ if (node->iss_NumRuntimeKeys != 0) { ExprContext *econtext = node->iss_RuntimeContext; ResetExprContext(econtext); ExecIndexEvalRuntimeKeys(econtext, node->iss_RuntimeKeys, node->iss_NumRuntimeKeys); } node->iss_RuntimeKeysReady = true; /* reset index scan */ index_rescan(node->iss_ScanDesc, node->iss_ScanKeys, node->iss_NumScanKeys, node->iss_OrderByKeys, node->iss_NumOrderByKeys); ExecScanReScan(&node->ss); }
/* ---------------------------------------------------------------- * ExecReScanForeignScan * * Rescans the relation. * ---------------------------------------------------------------- */ void ExecReScanForeignScan(ForeignScanState *node) { node->fdwroutine->ReScanForeignScan(node); ExecScanReScan(&node->ss); }
/* ---------------------------------------------------------------- * ExecReScanFunctionScan * * Rescans the relation. * ---------------------------------------------------------------- */ void ExecReScanFunctionScan(FunctionScanState *node) { ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecScanReScan(&node->ss); /* * If we haven't materialized yet, just return. */ if (!node->tuplestorestate) return; /* * Here we have a choice whether to drop the tuplestore (and recompute the * function outputs) or just rescan it. We must recompute if the * expression contains parameters, else we rescan. XXX maybe we should * recompute if the function is volatile? */ if (node->ss.ps.chgParam != NULL) { tuplestore_end(node->tuplestorestate); node->tuplestorestate = NULL; } else tuplestore_rescan(node->tuplestorestate); }
/* ---------------------------------------------------------------- * ExecReScanBitmapHeapScan(node) * ---------------------------------------------------------------- */ void ExecReScanBitmapHeapScan(BitmapHeapScanState *node) { /* rescan to release any page pin */ heap_rescan(node->ss.ss_currentScanDesc, NULL); if (node->tbmiterator) tbm_end_iterate(node->tbmiterator); if (node->prefetch_iterator) tbm_end_iterate(node->prefetch_iterator); if (node->tbm) tbm_free(node->tbm); node->tbm = NULL; node->tbmiterator = NULL; node->tbmres = NULL; node->prefetch_iterator = NULL; ExecScanReScan(&node->ss); /* * if chgParam of subnode is not null then plan will be re-scanned by * first ExecProcNode. */ if (node->ss.ps.lefttree->chgParam == NULL) ExecReScan(node->ss.ps.lefttree); }
/* ---------------------------------------------------------------- * 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); } }
/* ---------------------------------------------------------------- * ExecReScanBitmapHeapScan(node) * ---------------------------------------------------------------- */ void ExecReScanBitmapHeapScan(BitmapHeapScanState *node) { PlanState *outerPlan = outerPlanState(node); /* rescan to release any page pin */ heap_rescan(node->ss.ss_currentScanDesc, NULL); if (node->tbmiterator) tbm_end_iterate(node->tbmiterator); if (node->prefetch_iterator) tbm_end_iterate(node->prefetch_iterator); if (node->shared_tbmiterator) tbm_end_shared_iterate(node->shared_tbmiterator); if (node->shared_prefetch_iterator) tbm_end_shared_iterate(node->shared_prefetch_iterator); if (node->tbm) tbm_free(node->tbm); node->tbm = NULL; node->tbmiterator = NULL; node->tbmres = NULL; node->prefetch_iterator = NULL; node->initialized = false; node->shared_tbmiterator = NULL; node->shared_prefetch_iterator = NULL; ExecScanReScan(&node->ss); /* * if chgParam of subnode is not null then plan will be re-scanned by * first ExecProcNode. */ if (outerPlan->chgParam == NULL) ExecReScan(outerPlan); }
/* ---------------------------------------------------------------- * ExecReScanWorkTableScan * * Rescans the relation. * ---------------------------------------------------------------- */ void ExecReScanWorkTableScan(WorkTableScanState *node) { ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecScanReScan(&node->ss); /* No need (or way) to rescan if ExecWorkTableScan not called yet */ if (node->rustate) tuplestore_rescan(node->rustate->working_table); }
/* ---------------------------------------------------------------- * ExecReScanSeqScan * * Rescans the relation. * ---------------------------------------------------------------- */ void ExecReScanSeqScan(SeqScanState *node) { HeapScanDesc scan; scan = node->ss_currentScanDesc; heap_rescan(scan, /* scan desc */ NULL); /* new scan keys */ ExecScanReScan((ScanState *) node); }
/* ---------------------------------------------------------------- * ExecReScanBitmapHeapScan(node) * ---------------------------------------------------------------- */ void ExecReScanBitmapHeapScan(BitmapHeapScanState *node) { PlanState *outerPlan = outerPlanState(node); /* rescan to release any page pin */ heap_rescan(node->ss.ss_currentScanDesc, NULL); if (node->tbmiterator) tbm_end_iterate(node->tbmiterator); if (node->prefetch_iterator) tbm_end_iterate(node->prefetch_iterator); if (node->shared_tbmiterator) tbm_end_shared_iterate(node->shared_tbmiterator); if (node->shared_prefetch_iterator) tbm_end_shared_iterate(node->shared_prefetch_iterator); if (node->tbm) tbm_free(node->tbm); node->tbm = NULL; node->tbmiterator = NULL; node->tbmres = NULL; node->prefetch_iterator = NULL; node->initialized = false; node->shared_tbmiterator = NULL; node->shared_prefetch_iterator = NULL; /* Reset parallel bitmap state, if present */ if (node->pstate) { dsa_area *dsa = node->ss.ps.state->es_query_dsa; node->pstate->state = BM_INITIAL; if (DsaPointerIsValid(node->pstate->tbmiterator)) tbm_free_shared_area(dsa, node->pstate->tbmiterator); if (DsaPointerIsValid(node->pstate->prefetch_iterator)) tbm_free_shared_area(dsa, node->pstate->prefetch_iterator); node->pstate->tbmiterator = InvalidDsaPointer; node->pstate->prefetch_iterator = InvalidDsaPointer; } ExecScanReScan(&node->ss); /* * if chgParam of subnode is not null then plan will be re-scanned by * first ExecProcNode. */ if (outerPlan->chgParam == NULL) ExecReScan(outerPlan); }
/* ---------------------------------------------------------------- * ExecIndexReScan(node) * * Recalculates the value of the scan keys whose value depends on * information known at runtime and rescans the indexed relation. * Updating the scan key was formerly done separately in * ExecUpdateIndexScanKeys. Integrating it into ReScan makes * rescans of indices and relations/general streams more uniform. * ---------------------------------------------------------------- */ void ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt) { ExprContext *econtext; econtext = node->iss_RuntimeContext; /* context for runtime keys */ if (econtext) { /* * If we are being passed an outer tuple, save it for runtime key * calc. We also need to link it into the "regular" per-tuple * econtext, so it can be used during indexqualorig evaluations. */ if (exprCtxt != NULL) { ExprContext *stdecontext; econtext->ecxt_outertuple = exprCtxt->ecxt_outertuple; stdecontext = node->ss.ps.ps_ExprContext; stdecontext->ecxt_outertuple = exprCtxt->ecxt_outertuple; } /* * Reset the runtime-key context so we don't leak memory as each outer * tuple is scanned. Note this assumes that we will recalculate *all* * runtime keys on each call. */ ResetExprContext(econtext); } /* * If we are doing runtime key calculations (ie, the index keys depend on * data from an outer scan), compute the new key values */ if (node->iss_NumRuntimeKeys != 0) ExecIndexEvalRuntimeKeys(econtext, node->iss_RuntimeKeys, node->iss_NumRuntimeKeys); node->iss_RuntimeKeysReady = true; /* reset index scan */ index_rescan(node->iss_ScanDesc, node->iss_ScanKeys); ExecScanReScan(&node->ss); }
/* ---------------------------------------------------------------- * ExecReScanForeignScan * * Rescans the relation. * ---------------------------------------------------------------- */ void ExecReScanForeignScan(ForeignScanState *node) { PlanState *outerPlan = outerPlanState(node); node->fdwroutine->ReScanForeignScan(node); /* * If chgParam of subnode is not null then plan will be re-scanned by * first ExecProcNode. outerPlan may also be NULL, in which case there * is nothing to rescan at all. */ if (outerPlan != NULL && outerPlan->chgParam == NULL) ExecReScan(outerPlan); ExecScanReScan(&node->ss); }
/* ---------------------------------------------------------------- * ExecReScanIndexOnlyScan(node) * * Recalculates the values of any scan keys whose value depends on * information known at runtime, then rescans the indexed relation. * * Updating the scan key was formerly done separately in * ExecUpdateIndexScanKeys. Integrating it into ReScan makes * rescans of indices and relations/general streams more uniform. * ---------------------------------------------------------------- */ void ExecReScanIndexOnlyScan(IndexOnlyScanState *node) { bool reset_parallel_scan = true; /* * If we are here to just update the scan keys, then don't reset parallel * scan. For detailed reason behind this look in the comments for * ExecReScanIndexScan. */ if (node->ioss_NumRuntimeKeys != 0 && !node->ioss_RuntimeKeysReady) reset_parallel_scan = false; /* * If we are doing runtime key calculations (ie, any of the index key * values weren't simple Consts), compute the new key values. But first, * reset the context so we don't leak memory as each outer tuple is * scanned. Note this assumes that we will recalculate *all* runtime keys * on each call. */ if (node->ioss_NumRuntimeKeys != 0) { ExprContext *econtext = node->ioss_RuntimeContext; ResetExprContext(econtext); ExecIndexEvalRuntimeKeys(econtext, node->ioss_RuntimeKeys, node->ioss_NumRuntimeKeys); } node->ioss_RuntimeKeysReady = true; /* reset index scan */ if (node->ioss_ScanDesc) { index_rescan(node->ioss_ScanDesc, node->ioss_ScanKeys, node->ioss_NumScanKeys, node->ioss_OrderByKeys, node->ioss_NumOrderByKeys); if (reset_parallel_scan && node->ioss_ScanDesc->parallel_scan) index_parallelrescan(node->ioss_ScanDesc); } ExecScanReScan(&node->ss); }
/* ---------------------------------------------------------------- * ExecReScanSubqueryScan * * Rescans the relation. * ---------------------------------------------------------------- */ void ExecReScanSubqueryScan(subquery_ss *node) { ExecScanReScan(&node->ss); /* * ExecReScan doesn't know about my subplan, so I have to do * changed-parameter signaling myself. This is just as well, because the * subplan has its own memory context in which its chgParam state lives. */ if (node->ss.ps.chgParam != NULL) UpdateChangedParamSet(node->subplan, node->ss.ps.chgParam); /* * if chgParam of subnode is not null then plan will be re-scanned by * first exec_proc_node. */ if (node->subplan->chgParam == NULL) ExecReScan(node->subplan); }
/* ---------------------------------------------------------------- * ExecReScanForeignScan * * Rescans the relation. * ---------------------------------------------------------------- */ void ExecReScanForeignScan(foreign_ss *node) { node->fdwroutine->ReScanForeignScan(node); ExecScanReScan(&node->ss); }