diff options
author | Bruce Momjian <bruce@momjian.us> | 1998-08-01 22:12:13 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 1998-08-01 22:12:13 +0000 |
commit | 0a2e5cdfc90ff60d8995409a8640a4d6f16a343d (patch) | |
tree | ea60044a4f68934a0c2b75ad3e32fd010517d418 /src/backend/executor/nodeIndexscan.c | |
parent | 0668aa88179cce20362bad88c9f0be0a461bb699 (diff) | |
download | postgresql-0a2e5cdfc90ff60d8995409a8640a4d6f16a343d.tar.gz postgresql-0a2e5cdfc90ff60d8995409a8640a4d6f16a343d.zip |
Allow index use with OR clauses.
Diffstat (limited to 'src/backend/executor/nodeIndexscan.c')
-rw-r--r-- | src/backend/executor/nodeIndexscan.c | 225 |
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; } |