📄 nodeindexscan.c
字号:
}/* ---------------------------------------------------------------- * ExecIndexRestrPos * ---------------------------------------------------------------- */voidExecIndexRestrPos(IndexScanState *node){ index_restrpos(node->iss_ScanDesc);}/* ---------------------------------------------------------------- * ExecInitIndexScan * * Initializes the index scan's state information, creates * scan keys, and opens the base and index relations. * * Note: index scans have 2 sets of state information because * we have to keep track of the base relation and the * index relation. * ---------------------------------------------------------------- */IndexScanState *ExecInitIndexScan(IndexScan *node, EState *estate){ IndexScanState *indexstate; ScanKey scanKeys; int numScanKeys; ExprState **runtimeKeyInfo; bool have_runtime_keys; RangeTblEntry *rtentry; Index relid; Oid reloid; Relation currentRelation; /* * create state structure */ indexstate = makeNode(IndexScanState); indexstate->ss.ps.plan = (Plan *) node; indexstate->ss.ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &indexstate->ss.ps); /* * initialize child expressions * * Note: we don't initialize all of the indexqual expression, only the * sub-parts corresponding to runtime keys (see below). The indexqualorig * expression is always initialized even though it will only be used in * some uncommon cases --- would be nice to improve that. (Problem is * that any SubPlans present in the expression must be found now...) */ indexstate->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) indexstate); indexstate->ss.ps.qual = (List *) ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) indexstate); indexstate->indexqualorig = (List *) ExecInitExpr((Expr *) node->indexqualorig, (PlanState *) indexstate);#define INDEXSCAN_NSLOTS 2 /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &indexstate->ss.ps); ExecInitScanTupleSlot(estate, &indexstate->ss); /* * Initialize index-specific scan state */ indexstate->iss_RuntimeKeysReady = false; CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext); /* * build the index scan keys from the index qualification */ have_runtime_keys = ExecIndexBuildScanKeys((PlanState *) indexstate, node->indexqual, node->indexstrategy, node->indexsubtype, &runtimeKeyInfo, &scanKeys, &numScanKeys); indexstate->iss_RuntimeKeyInfo = runtimeKeyInfo; indexstate->iss_ScanKeys = scanKeys; indexstate->iss_NumScanKeys = numScanKeys; /* * If we have runtime keys, we need an ExprContext to evaluate them. The * node's standard context won't do because we want to reset that context * for every tuple. So, build another context just like the other one... * -tgl 7/11/00 */ if (have_runtime_keys) { ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext; ExecAssignExprContext(estate, &indexstate->ss.ps); indexstate->iss_RuntimeContext = indexstate->ss.ps.ps_ExprContext; indexstate->ss.ps.ps_ExprContext = stdecontext; } else { indexstate->iss_RuntimeContext = NULL; } /* * open the base relation and acquire AccessShareLock on it. */ relid = node->scan.scanrelid; rtentry = rt_fetch(relid, estate->es_range_table); reloid = rtentry->relid; currentRelation = heap_open(reloid, AccessShareLock); indexstate->ss.ss_currentRelation = currentRelation; indexstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */ /* * get the scan type from the relation descriptor. */ ExecAssignScanType(&indexstate->ss, RelationGetDescr(currentRelation), false); /* * open the index relation and initialize relation and scan descriptors. * Note we acquire no locks here; the index machinery does its own locks * and unlocks. (We rely on having AccessShareLock on the parent table to * ensure the index won't go away!) */ indexstate->iss_RelationDesc = index_open(node->indexid); indexstate->iss_ScanDesc = index_beginscan(currentRelation, indexstate->iss_RelationDesc, estate->es_snapshot, numScanKeys, scanKeys); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&indexstate->ss.ps); ExecAssignScanProjectionInfo(&indexstate->ss); /* * all done. */ return indexstate;}/* * ExecIndexBuildScanKeys * Build the index scan keys from the index qualification * * Input params are: * * planstate: executor state node we are working for * quals: indexquals expressions * strategies: associated operator strategy numbers * subtypes: associated operator subtype OIDs * * Output params are: * * *runtimeKeyInfo: receives ptr to array of runtime key exprstates * (NULL if no runtime keys) * *scanKeys: receives ptr to array of ScanKeys * *numScanKeys: receives number of scankeys/runtime keys * * Return value is TRUE if any runtime key expressions were found, else FALSE. */boolExecIndexBuildScanKeys(PlanState *planstate, List *quals, List *strategies, List *subtypes, ExprState ***runtimeKeyInfo, ScanKey *scanKeys, int *numScanKeys){ bool have_runtime_keys = false; ListCell *qual_cell; ListCell *strategy_cell; ListCell *subtype_cell; int n_keys; ScanKey scan_keys; ExprState **run_keys; int j; n_keys = list_length(quals); scan_keys = (n_keys <= 0) ? NULL : (ScanKey) palloc(n_keys * sizeof(ScanKeyData)); run_keys = (n_keys <= 0) ? NULL : (ExprState **) palloc(n_keys * sizeof(ExprState *)); /* * for each opclause in the given qual, convert each qual's opclause into * a single scan key */ qual_cell = list_head(quals); strategy_cell = list_head(strategies); subtype_cell = list_head(subtypes); for (j = 0; j < n_keys; j++) { OpExpr *clause; /* one clause of index qual */ Expr *leftop; /* expr on lhs of operator */ Expr *rightop; /* expr on rhs ... */ int flags = 0; AttrNumber varattno; /* att number used in scan */ StrategyNumber strategy; /* op's strategy number */ Oid subtype; /* op's strategy subtype */ RegProcedure opfuncid; /* operator proc id used in scan */ Datum scanvalue; /* value used in scan (if const) */ /* * extract clause information from the qualification */ clause = (OpExpr *) lfirst(qual_cell); qual_cell = lnext(qual_cell); strategy = lfirst_int(strategy_cell); strategy_cell = lnext(strategy_cell); subtype = lfirst_oid(subtype_cell); subtype_cell = lnext(subtype_cell); if (!IsA(clause, OpExpr)) elog(ERROR, "indexqual is not an OpExpr"); opfuncid = clause->opfuncid; /* * Here we figure out the contents of the index qual. The usual case * is (var op const) which means we form a scan key for the attribute * listed in the var node and use the value of the const as comparison * data. * * If we don't have a const node, it means our scan key is a function * of information obtained during the execution of the plan, in which * case we need to recalculate the index scan key at run time. Hence, * we set have_runtime_keys to true and place the appropriate * subexpression in run_keys. The corresponding scan key values are * recomputed at run time. */ run_keys[j] = NULL; /* * determine information in leftop */ leftop = (Expr *) get_leftop((Expr *) clause); if (leftop && IsA(leftop, RelabelType)) leftop = ((RelabelType *) leftop)->arg; Assert(leftop != NULL); if (!(IsA(leftop, Var) && var_is_rel((Var *) leftop))) elog(ERROR, "indexqual doesn't have key on left side"); varattno = ((Var *) leftop)->varattno; /* * now determine information in rightop */ rightop = (Expr *) get_rightop((Expr *) clause); if (rightop && IsA(rightop, RelabelType)) rightop = ((RelabelType *) rightop)->arg; Assert(rightop != NULL); if (IsA(rightop, Const)) { /* * if the rightop is a const node then it means it identifies the * value to place in our scan key. */ scanvalue = ((Const *) rightop)->constvalue; if (((Const *) rightop)->constisnull) flags |= SK_ISNULL; } else { /* * otherwise, the rightop contains an expression evaluable at * runtime to figure out the value to place in our scan key. */ have_runtime_keys = true; run_keys[j] = ExecInitExpr(rightop, planstate); scanvalue = (Datum) 0; } /* * initialize the scan key's fields appropriately */ ScanKeyEntryInitialize(&scan_keys[j], flags, varattno, /* attribute number to scan */ strategy, /* op's strategy */ subtype, /* strategy subtype */ opfuncid, /* reg proc to use */ scanvalue); /* constant */ } /* If no runtime keys, get rid of speculatively-allocated array */ if (run_keys && !have_runtime_keys) { pfree(run_keys); run_keys = NULL; } /* * Return the info to our caller. */ *numScanKeys = n_keys; *scanKeys = scan_keys; *runtimeKeyInfo = run_keys; return have_runtime_keys;}intExecCountSlotsIndexScan(IndexScan *node){ return ExecCountSlotsNode(outerPlan((Plan *) node)) + ExecCountSlotsNode(innerPlan((Plan *) node)) + INDEXSCAN_NSLOTS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -