aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeIndexscan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/nodeIndexscan.c')
-rw-r--r--src/backend/executor/nodeIndexscan.c225
1 files changed, 118 insertions, 107 deletions
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 51308d41014..0f9be0a129d 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.19 1998/07/27 19:37:57 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.20 1998/08/01 22:12:04 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -87,7 +87,6 @@ IndexNext(IndexScan *node)
IndexScanState *indexstate;
ScanDirection direction;
Snapshot snapshot;
- int indexPtr;
IndexScanDescPtr scanDescs;
IndexScanDesc scandesc;
Relation heapRelation;
@@ -95,7 +94,8 @@ IndexNext(IndexScan *node)
HeapTuple tuple;
TupleTableSlot *slot;
Buffer buffer = InvalidBuffer;
-
+ int numIndices;
+
/* ----------------
* extract necessary information from index scan node
* ----------------
@@ -105,54 +105,66 @@ IndexNext(IndexScan *node)
snapshot = estate->es_snapshot;
scanstate = node->scan.scanstate;
indexstate = node->indxstate;
- indexPtr = indexstate->iss_IndexPtr;
scanDescs = indexstate->iss_ScanDescs;
- scandesc = scanDescs[indexPtr];
heapRelation = scanstate->css_currentRelation;
-
+ numIndices = indexstate->iss_NumIndices;
slot = scanstate->css_ScanTupleSlot;
/* ----------------
* ok, now that we have what we need, fetch an index tuple.
- * ----------------
- */
-
- /* ----------------
* if scanning this index succeeded then return the
* appropriate heap tuple.. else return NULL.
* ----------------
*/
- while ((result = index_getnext(scandesc, direction)) != NULL)
+ while (indexstate->iss_IndexPtr < numIndices)
{
- tuple = heap_fetch(heapRelation, snapshot,
- &result->heap_iptr, &buffer);
- /* be tidy */
- pfree(result);
-
- if (tuple != NULL)
- {
- /* ----------------
- * store the scanned tuple in the scan tuple slot of
- * the scan state. Eventually we will only do this and not
- * return a tuple. Note: we pass 'false' because tuples
- * returned by amgetnext are pointers onto disk pages and
- * were not created with palloc() and so should not be pfree()'d.
- * ----------------
- */
- ExecStoreTuple(tuple, /* tuple to store */
- slot, /* slot to store in */
- buffer, /* buffer associated with tuple */
- false); /* don't pfree */
-
- return slot;
- }
- else
+ scandesc = scanDescs[indexstate->iss_IndexPtr];
+ while ((result = index_getnext(scandesc, direction)) != NULL)
{
+ tuple = heap_fetch(heapRelation, snapshot,
+ &result->heap_iptr, &buffer);
+ /* be tidy */
+ pfree(result);
+
+ if (tuple != NULL)
+ {
+ bool prev_matches = false;
+ int prev_index;
+
+ /* ----------------
+ * store the scanned tuple in the scan tuple slot of
+ * the scan state. Eventually we will only do this and not
+ * return a tuple. Note: we pass 'false' because tuples
+ * returned by amgetnext are pointers onto disk pages and
+ * were not created with palloc() and so should not be pfree()'d.
+ * ----------------
+ */
+ ExecStoreTuple(tuple, /* tuple to store */
+ slot, /* slot to store in */
+ buffer, /* buffer associated with tuple */
+ false); /* don't pfree */
+
+ for (prev_index = 0; prev_index < indexstate->iss_IndexPtr;
+ prev_index++)
+ {
+ if (ExecQual(nth(prev_index, node->indxqual),
+ scanstate->cstate.cs_ExprContext))
+ {
+ prev_matches = true;
+ break;
+ }
+ }
+ if (!prev_matches)
+ return slot;
+ else
+ ExecClearTuple(slot);
+ }
if (BufferIsValid(buffer))
ReleaseBuffer(buffer);
}
+ if (indexstate->iss_IndexPtr < numIndices)
+ indexstate->iss_IndexPtr++;
}
-
/* ----------------
* if we get here it means the index scan failed so we
* are at the end of the scan..
@@ -218,7 +230,6 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
int i;
Pointer *runtimeKeyInfo;
- int indexPtr;
int *numScanKeys;
List *indxqual;
List *qual;
@@ -238,69 +249,62 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
numIndices = indexstate->iss_NumIndices;
scanDescs = indexstate->iss_ScanDescs;
scanKeys = indexstate->iss_ScanKeys;
-
runtimeKeyInfo = (Pointer *) indexstate->iss_RuntimeKeyInfo;
+ indxqual = node->indxqual;
+ numScanKeys = indexstate->iss_NumScanKeys;
+ indexstate->iss_IndexPtr = 0;
+
+ /* it's possible in subselects */
+ if (exprCtxt == NULL)
+ exprCtxt = node->scan.scanstate->cstate.cs_ExprContext;
- if (runtimeKeyInfo != NULL)
- {
-
- /*
- * get the index qualifications and recalculate the appropriate
- * values
- */
- indexPtr = indexstate->iss_IndexPtr;
- indxqual = node->indxqual;
- qual = nth(indexPtr, indxqual);
- numScanKeys = indexstate->iss_NumScanKeys;
- n_keys = numScanKeys[indexPtr];
- run_keys = (int *) runtimeKeyInfo[indexPtr];
- scan_keys = (ScanKey) scanKeys[indexPtr];
+ if (exprCtxt != NULL)
+ node->scan.scanstate->cstate.cs_ExprContext->ecxt_outertuple =
+ exprCtxt->ecxt_outertuple;
- /* it's possible in subselects */
- if (exprCtxt == NULL)
- exprCtxt = node->scan.scanstate->cstate.cs_ExprContext;
-
- for (j = 0; j < n_keys; j++)
+ /*
+ * get the index qualifications and recalculate the appropriate
+ * values
+ */
+ for (i = 0; i < numIndices; i++)
+ {
+ if (runtimeKeyInfo && runtimeKeyInfo[i] != NULL)
{
-
- /*
- * 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.
- */
- if (run_keys[j] != NO_OP)
+ qual = nth(i, indxqual);
+ n_keys = numScanKeys[i];
+ run_keys = (int *) runtimeKeyInfo[i];
+ scan_keys = (ScanKey) scanKeys[i];
+
+ for (j = 0; j < n_keys; j++)
{
- clause = nth(j, qual);
- scanexpr = (run_keys[j] == RIGHT_OP) ?
- (Node *) get_rightop(clause) : (Node *) get_leftop(clause);
-
/*
- * pass in isDone but ignore it. We don't iterate in
- * quals
+ * 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.
*/
- scanvalue = (Datum)
- ExecEvalExpr(scanexpr, exprCtxt, &isNull, &isDone);
- scan_keys[j].sk_argument = scanvalue;
- if (isNull)
- scan_keys[j].sk_flags |= SK_ISNULL;
- else
- scan_keys[j].sk_flags &= ~SK_ISNULL;
+ if (run_keys[j] != NO_OP)
+ {
+ clause = nth(j, qual);
+ scanexpr = (run_keys[j] == RIGHT_OP) ?
+ (Node *) get_rightop(clause) : (Node *) get_leftop(clause);
+
+ /*
+ * pass in isDone but ignore it. We don't iterate in
+ * quals
+ */
+ scanvalue = (Datum)
+ ExecEvalExpr(scanexpr, exprCtxt, &isNull, &isDone);
+ scan_keys[j].sk_argument = scanvalue;
+ if (isNull)
+ scan_keys[j].sk_flags |= SK_ISNULL;
+ else
+ scan_keys[j].sk_flags &= ~SK_ISNULL;
+ }
}
+ sdesc = scanDescs[i];
+ skey = scanKeys[i];
+ index_rescan(sdesc, direction, skey);
}
- }
-
- /*
- * rescans all indices
- *
- * note: AMrescan assumes only one scan key. This may have to change if
- * we ever decide to support multiple keys.
- */
- for (i = 0; i < numIndices; i++)
- {
- sdesc = scanDescs[i];
- skey = scanKeys[i];
- index_rescan(sdesc, direction, skey);
- }
/* ----------------
* perhaps return something meaningful
@@ -322,19 +326,23 @@ ExecEndIndexScan(IndexScan *node)
{
CommonScanState *scanstate;
IndexScanState *indexstate;
+ Pointer *runtimeKeyInfo;
ScanKey *scanKeys;
+ int *numScanKeys;
int numIndices;
int i;
scanstate = node->scan.scanstate;
indexstate = node->indxstate;
-
+ runtimeKeyInfo = (Pointer *) indexstate->iss_RuntimeKeyInfo;
+
/* ----------------
* extract information from the node
* ----------------
*/
numIndices = indexstate->iss_NumIndices;
scanKeys = indexstate->iss_ScanKeys;
+ numScanKeys = indexstate->iss_NumScanKeys;
/* ----------------
* Free the projection info and the scan attribute info
@@ -362,7 +370,24 @@ ExecEndIndexScan(IndexScan *node)
if (scanKeys[i] != NULL)
pfree(scanKeys[i]);
}
+ pfree(scanKeys);
+ pfree(numScanKeys);
+
+ if (runtimeKeyInfo)
+ {
+ for (i = 0; i < numIndices; i++)
+ {
+ List *qual;
+ int n_keys;
+ qual = nth(i, indxqual);
+ n_keys = length(qual);
+ if (n_keys > 0)
+ pfree(runtimeKeyInfo[i]);
+ }
+ pfree(runtimeKeyInfo);
+ }
+
/* ----------------
* clear out tuple table slots
* ----------------
@@ -430,7 +455,7 @@ ExecIndexRestrPos(IndexScan *node)
/* ----------------------------------------------------------------
* ExecInitIndexScan
- *
+ *
* Initializes the index scan's state information, creates
* scan keys, and opens the base and index relations.
*
@@ -886,20 +911,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
if (have_runtime_keys)
indexstate->iss_RuntimeKeyInfo = (Pointer) runtimeKeyInfo;
else
- {
indexstate->iss_RuntimeKeyInfo = NULL;
- for (i = 0; i < numIndices; i++)
- {
- List *qual;
- int n_keys;
-
- qual = nth(i, indxqual);
- n_keys = length(qual);
- if (n_keys > 0)
- pfree(runtimeKeyInfo[i]);
- }
- pfree(runtimeKeyInfo);
- }
/* ----------------
* get the range table and direction information
@@ -991,6 +1003,5 @@ int
ExecCountSlotsIndexScan(IndexScan *node)
{
return ExecCountSlotsNode(outerPlan((Plan *) node)) +
- ExecCountSlotsNode(innerPlan((Plan *) node)) +
- INDEXSCAN_NSLOTS;
+ ExecCountSlotsNode(innerPlan((Plan *) node)) + INDEXSCAN_NSLOTS;
}