aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeBitmapIndexscan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/nodeBitmapIndexscan.c')
-rw-r--r--src/backend/executor/nodeBitmapIndexscan.c234
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 */