diff options
Diffstat (limited to 'src/backend/executor/nodeBitmapIndexscan.c')
-rw-r--r-- | src/backend/executor/nodeBitmapIndexscan.c | 234 |
1 files changed, 25 insertions, 209 deletions
diff --git a/src/backend/executor/nodeBitmapIndexscan.c b/src/backend/executor/nodeBitmapIndexscan.c index 73acd0c9520..19915a60599 100644 --- a/src/backend/executor/nodeBitmapIndexscan.c +++ b/src/backend/executor/nodeBitmapIndexscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapIndexscan.c,v 1.6 2005/04/24 18:16:38 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapIndexscan.c,v 1.7 2005/04/25 01:30:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -22,14 +22,11 @@ #include "postgres.h" #include "access/genam.h" -#include "access/heapam.h" #include "executor/execdebug.h" #include "executor/instrument.h" #include "executor/nodeBitmapIndexscan.h" +#include "executor/nodeIndexscan.h" #include "miscadmin.h" -#include "nodes/nodeFuncs.h" -#include "optimizer/clauses.h" -#include "parser/parsetree.h" /* ---------------------------------------------------------------- @@ -41,7 +38,7 @@ MultiExecBitmapIndexScan(BitmapIndexScanState *node) { #define MAX_TIDS 1024 TIDBitmap *tbm; - Oid indxid; + Oid indexid; Relation indexRelation; IndexScanDesc scandesc; ItemPointerData tids[MAX_TIDS]; @@ -70,8 +67,8 @@ MultiExecBitmapIndexScan(BitmapIndexScanState *node) * descriptors. Note we acquire no locks here; the index machinery * does its own locks and unlocks. */ - indxid = ((BitmapIndexScan *) node->ss.ps.plan)->indxid; - indexRelation = index_open(indxid); + indexid = ((BitmapIndexScan *) node->ss.ps.plan)->indexid; + indexRelation = index_open(indexid); scandesc = index_beginscan_multi(indexRelation, node->ss.ps.state->es_snapshot, node->biss_NumScanKeys, @@ -166,47 +163,10 @@ ExecBitmapIndexReScan(BitmapIndexScanState *node, ExprContext *exprCtxt) */ if (runtimeKeyInfo) { - int n_keys; - ScanKey scan_keys; - ExprState **run_keys; - int j; - - n_keys = node->biss_NumScanKeys; - scan_keys = node->biss_ScanKeys; - run_keys = runtimeKeyInfo; - - for (j = 0; j < n_keys; j++) - { - /* - * If we have a run-time key, then extract the run-time - * expression and evaluate it with respect to the current - * outer tuple. We then stick the result into the scan - * key. - * - * Note: the result of the eval could be a pass-by-ref value - * that's stored in the outer scan's tuple, not in - * econtext->ecxt_per_tuple_memory. We assume that the - * outer tuple will stay put throughout our scan. If this - * is wrong, we could copy the result into our context - * explicitly, but I think that's not necessary... - */ - if (run_keys[j] != NULL) - { - Datum scanvalue; - bool isNull; - - scanvalue = ExecEvalExprSwitchContext(run_keys[j], - econtext, - &isNull, - NULL); - scan_keys[j].sk_argument = scanvalue; - if (isNull) - scan_keys[j].sk_flags |= SK_ISNULL; - else - scan_keys[j].sk_flags &= ~SK_ISNULL; - } - } - + ExecIndexEvalRuntimeKeys(econtext, + runtimeKeyInfo, + node->biss_ScanKeys, + node->biss_NumScanKeys); node->biss_RuntimeKeysReady = true; } } @@ -237,6 +197,8 @@ BitmapIndexScanState * ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate) { BitmapIndexScanState *indexstate; + ScanKey scanKeys; + int numScanKeys; ExprState **runtimeKeyInfo; bool have_runtime_keys; @@ -262,7 +224,7 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate) * * We don't need to initialize targetlist or qual since neither are used. * - * Note: we don't initialize all of the indxqual expression, only the + * Note: we don't initialize all of the indexqual expression, only the * sub-parts corresponding to runtime keys (see below). */ @@ -271,169 +233,28 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate) /* * Initialize index-specific scan state */ - indexstate->biss_ScanKeys = NULL; - indexstate->biss_NumScanKeys = 0; - indexstate->biss_RuntimeKeyInfo = NULL; - indexstate->biss_RuntimeContext = NULL; indexstate->biss_RuntimeKeysReady = false; CXT1_printf("ExecInitBitmapIndexScan: context is %d\n", CurrentMemoryContext); /* - * initialize space for runtime key info (may not be needed) - */ - have_runtime_keys = false; - - /* * build the index scan keys from the index qualification */ - { - List *quals; - List *strategies; - List *subtypes; - ListCell *qual_cell; - ListCell *strategy_cell; - ListCell *subtype_cell; - int n_keys; - ScanKey scan_keys; - ExprState **run_keys; - int j; - - quals = node->indxqual; - strategies = node->indxstrategy; - subtypes = node->indxsubtype; - 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, "indxqual 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, "indxqual 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 *) indexstate); - 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 */ - } - - /* - * store the key information into the node. - */ - indexstate->biss_NumScanKeys = n_keys; - indexstate->biss_ScanKeys = scan_keys; - runtimeKeyInfo = run_keys; - } + have_runtime_keys = + ExecIndexBuildScanKeys((PlanState *) indexstate, + node->indexqual, + node->indexstrategy, + node->indexsubtype, + &runtimeKeyInfo, + &scanKeys, + &numScanKeys); + + indexstate->biss_RuntimeKeyInfo = runtimeKeyInfo; + indexstate->biss_ScanKeys = scanKeys; + indexstate->biss_NumScanKeys = numScanKeys; /* - * If all of our keys have the form (var op const), then we have no - * runtime keys so we store NULL in the runtime key info. Otherwise - * runtime key info contains an array of pointers to runtime key - * expressions. - * - * If we do have runtime keys, we need an ExprContext to evaluate them. + * If we have runtime keys, we need an ExprContext to evaluate them. * We could just create a "standard" plan node exprcontext, but to * keep the code looking similar to nodeIndexscan.c, it seems better * to stick with the approach of using a separate ExprContext. @@ -443,17 +264,12 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate) ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext; ExecAssignExprContext(estate, &indexstate->ss.ps); - indexstate->biss_RuntimeKeyInfo = runtimeKeyInfo; indexstate->biss_RuntimeContext = indexstate->ss.ps.ps_ExprContext; indexstate->ss.ps.ps_ExprContext = stdecontext; } else { - indexstate->biss_RuntimeKeyInfo = NULL; indexstate->biss_RuntimeContext = NULL; - /* Get rid of the speculatively-allocated flag array, too */ - if (runtimeKeyInfo) - pfree(runtimeKeyInfo); } /* We don't keep the table or index open across calls */ |