aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeBitmapIndexscan.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-04-25 01:30:14 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-04-25 01:30:14 +0000
commit5b05185262fd562080ecfd675c7b3634a69851c0 (patch)
treeb9a9ff51a51e72d5076d6828584b30a504335303 /src/backend/executor/nodeBitmapIndexscan.c
parent186655e9a53b62f75e57bcfc218129a6cfe8ea68 (diff)
downloadpostgresql-5b05185262fd562080ecfd675c7b3634a69851c0.tar.gz
postgresql-5b05185262fd562080ecfd675c7b3634a69851c0.zip
Remove support for OR'd indexscans internal to a single IndexScan plan
node, as this behavior is now better done as a bitmap OR indexscan. This allows considerable simplification in nodeIndexscan.c itself as well as several planner modules concerned with indexscan plan generation. Also we can improve the sharing of code between regular and bitmap indexscans, since they are now working with nigh-identical Plan nodes.
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 */