/* ---------------------------------------------------------------- * 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); }
/* ---------------------------------------------------------------- * 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) { EState *estate; ExprContext *econtext; Index scanrelid; estate = node->ss.ps.state; econtext = node->iss_RuntimeContext; /* context for runtime keys */ scanrelid = ((IndexScan *) node->ss.ps.plan)->scan.scanrelid; node->ss.ps.ps_TupFromTlist = false; 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; /* If this is re-scanning of PlanQual ... */ if (estate->es_evTuple != NULL && estate->es_evTuple[scanrelid - 1] != NULL) { estate->es_evTupleNull[scanrelid - 1] = false; return; } /* reset index scan */ index_rescan(node->iss_ScanDesc, node->iss_ScanKeys); }
/* ---------------------------------------------------------------- * ExecBitmapIndexReScan(node) * * Recalculates the value of the scan keys whose value depends on * information known at runtime and rescans the indexed relation. * ---------------------------------------------------------------- */ void ExecBitmapIndexReScan(BitmapIndexScanState *node, ExprContext *exprCtxt) { ExprContext *econtext; econtext = node->biss_RuntimeContext; /* context for runtime keys */ if (econtext) { /* * If we are being passed an outer tuple, save it for runtime key * calc. */ if (exprCtxt != NULL) econtext->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. * * Array keys are also treated as runtime keys; note that if we return * with biss_RuntimeKeysReady still false, then there is an empty array * key so no index scan is needed. */ if (node->biss_NumRuntimeKeys != 0) ExecIndexEvalRuntimeKeys(econtext, node->biss_RuntimeKeys, node->biss_NumRuntimeKeys); if (node->biss_NumArrayKeys != 0) node->biss_RuntimeKeysReady = ExecIndexEvalArrayKeys(econtext, node->biss_ArrayKeys, node->biss_NumArrayKeys); else node->biss_RuntimeKeysReady = true; /* reset index scan */ if (node->biss_RuntimeKeysReady) index_rescan(node->biss_ScanDesc, node->biss_ScanKeys); }
/* ---------------------------------------------------------------- * 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); }
/* ---------------------------------------------------------------- * ExecBitmapIndexReScan(node) * * Recalculates the value of the scan keys whose value depends on * information known at runtime and rescans the indexed relation. * ---------------------------------------------------------------- */ void ExecBitmapIndexReScan(BitmapIndexScanState *node, ExprContext *exprCtxt) { ExprContext *econtext; ExprState **runtimeKeyInfo; econtext = node->biss_RuntimeContext; /* context for runtime keys */ runtimeKeyInfo = node->biss_RuntimeKeyInfo; if (econtext) { /* * If we are being passed an outer tuple, save it for runtime key * calc. */ if (exprCtxt != NULL) econtext->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 (runtimeKeyInfo) { ExecIndexEvalRuntimeKeys(econtext, runtimeKeyInfo, node->biss_ScanKeys, node->biss_NumScanKeys); node->biss_RuntimeKeysReady = true; } /* reset index scan */ index_rescan(node->biss_ScanDesc, node->biss_ScanKeys); if (node->odbiss_ScanDesc != NULL) index_rescan(node->odbiss_ScanDesc, node->biss_ScanKeys); }
/* ---------------------------------------------------------------- * 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); }
/* ---------------------------------------------------------------- * ExecReScanBitmapIndexScan(node) * * Recalculates the values of any scan keys whose value depends on * information known at runtime, then rescans the indexed relation. * ---------------------------------------------------------------- */ void ExecReScanBitmapIndexScan(BitmapIndexScanState *node) { ExprContext *econtext = node->biss_RuntimeContext; /* * 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. */ if (econtext) ResetExprContext(econtext); /* * If we are doing runtime key calculations (ie, any of the index key * values weren't simple Consts), compute the new key values. * * Array keys are also treated as runtime keys; note that if we return * with biss_RuntimeKeysReady still false, then there is an empty array * key so no index scan is needed. */ if (node->biss_NumRuntimeKeys != 0) ExecIndexEvalRuntimeKeys(econtext, node->biss_RuntimeKeys, node->biss_NumRuntimeKeys); if (node->biss_NumArrayKeys != 0) node->biss_RuntimeKeysReady = ExecIndexEvalArrayKeys(econtext, node->biss_ArrayKeys, node->biss_NumArrayKeys); else node->biss_RuntimeKeysReady = true; /* reset index scan */ if (node->biss_RuntimeKeysReady) index_rescan(node->biss_ScanDesc, node->biss_ScanKeys, node->biss_NumScanKeys, NULL, 0); }
/* * This function initializes a part and returns true if a new index has been prepared for scanning. */ static bool initNextIndexToScan(DynamicIndexScanState *node) { IndexScanState *indexState = &(node->indexScanState); DynamicIndexScan *dynamicIndexScan = (DynamicIndexScan *)node->indexScanState.ss.ps.plan; /* Load new index when the scanning of the previous index is done. */ if (indexState->ss.scan_state == SCAN_INIT || indexState->ss.scan_state == SCAN_DONE) { /* This is the oid of a partition of the table (*not* index) */ Oid *pid = hash_seq_search(&node->pidxStatus); if (pid == NULL) { /* Return if all parts have been scanned. */ node->shouldCallHashSeqTerm = false; return false; } /* Collect number of partitions scanned in EXPLAIN ANALYZE */ if(NULL != indexState->ss.ps.instrument) { Instrumentation *instr = indexState->ss.ps.instrument; instr->numPartScanned ++; } DynamicIndexScan_ReMapColumns(node, *pid); /* * The is the oid of the partition of an *index*. Note: a partitioned table * has a root and a set of partitions (may be multi-level). An index * on a partitioned table also has a root and a set of index partitions. * We started at table level, and now we are fetching the oid of an index * partition. */ Oid pindex = getPhysicalIndexRelid(dynamicIndexScan->logicalIndexInfo, *pid); Assert(OidIsValid(pindex)); Relation currentRelation = OpenScanRelationByOid(*pid); indexState->ss.ss_currentRelation = currentRelation; for (int i=0; i < DYNAMICINDEXSCAN_NSLOTS; i++) { indexState->ss.ss_ScanTupleSlot[i].tts_tableOid = *pid; } ExecAssignScanType(&indexState->ss, RelationGetDescr(currentRelation)); ScanState *scanState = (ScanState *)node; MemoryContextReset(node->partitionMemoryContext); MemoryContext oldCxt = MemoryContextSwitchTo(node->partitionMemoryContext); /* Initialize child expressions */ scanState->ps.qual = (List *)ExecInitExpr((Expr *)scanState->ps.plan->qual, (PlanState*)scanState); scanState->ps.targetlist = (List *)ExecInitExpr((Expr *)scanState->ps.plan->targetlist, (PlanState*)scanState); ExecAssignScanProjectionInfo(scanState); EState *estate = indexState->ss.ps.state; indexState->iss_RelationDesc = OpenIndexRelation(estate, pindex, *pid); /* * build the index scan keys from the index qualification */ ExecIndexBuildScanKeys((PlanState *) indexState, indexState->iss_RelationDesc, dynamicIndexScan->indexqual, dynamicIndexScan->indexstrategy, dynamicIndexScan->indexsubtype, &indexState->iss_ScanKeys, &indexState->iss_NumScanKeys, &indexState->iss_RuntimeKeys, &indexState->iss_NumRuntimeKeys, NULL, NULL); MemoryContextSwitchTo(oldCxt); ExprContext *econtext = indexState->iss_RuntimeContext; /* context for runtime keys */ if (indexState->iss_NumRuntimeKeys != 0) { ExecIndexEvalRuntimeKeys(econtext, indexState->iss_RuntimeKeys, indexState->iss_NumRuntimeKeys); } indexState->iss_RuntimeKeysReady = true; /* * Initialize result tuple type and projection info. */ TupleDesc td = indexState->ss.ps.ps_ResultTupleSlot->tts_tupleDescriptor; if (td) { pfree(td); td = NULL; } ExecAssignResultTypeFromTL(&indexState->ss.ps); ExecAssignScanProjectionInfo(&indexState->ss); indexState->iss_ScanDesc = index_beginscan(currentRelation, indexState->iss_RelationDesc, estate->es_snapshot, indexState->iss_NumScanKeys, indexState->iss_ScanKeys); indexState->ss.scan_state = SCAN_SCAN; } return true; }