diff options
Diffstat (limited to 'src/backend/executor/nodeIndexscan.c')
-rw-r--r-- | src/backend/executor/nodeIndexscan.c | 49 |
1 files changed, 48 insertions, 1 deletions
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index 0ece6c6702f..3a489b361c6 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.88 2003/12/30 20:05:05 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeIndexscan.c,v 1.89 2004/01/06 04:31:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -99,7 +99,9 @@ IndexNext(IndexScanState *node) ExprContext *econtext; ScanDirection direction; IndexScanDescPtr scanDescs; + List **lossyQuals; IndexScanDesc scandesc; + List *lossyQual; Index scanrelid; HeapTuple tuple; TupleTableSlot *slot; @@ -120,6 +122,7 @@ IndexNext(IndexScanState *node) direction = ForwardScanDirection; } scanDescs = node->iss_ScanDescs; + lossyQuals = node->iss_LossyQuals; numIndices = node->iss_NumIndices; econtext = node->ss.ps.ps_ExprContext; slot = node->ss.ss_ScanTupleSlot; @@ -188,6 +191,8 @@ IndexNext(IndexScanState *node) while (indexNumber < numIndices) { scandesc = scanDescs[node->iss_IndexPtr]; + lossyQual = lossyQuals[node->iss_IndexPtr]; + while ((tuple = index_getnext(scandesc, direction)) != NULL) { /* @@ -202,6 +207,22 @@ IndexNext(IndexScanState *node) false); /* don't pfree */ /* + * If any of the index operators involved in this scan are lossy, + * recheck them by evaluating the original operator clauses. + */ + if (lossyQual) + { + econtext->ecxt_scantuple = slot; + ResetExprContext(econtext); + if (!ExecQual(lossyQual, econtext, false)) + { + /* Fails lossy op, so drop it and loop back for another */ + ExecClearTuple(slot); + continue; + } + } + + /* * If it's a multiple-index scan, make sure not to double-report * a tuple matched by more than one index. (See notes above.) */ @@ -615,6 +636,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate) List *indxqual; List *indxstrategy; List *indxsubtype; + List *indxlossy; List *indxid; int i; int numIndices; @@ -623,6 +645,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate) int *numScanKeys; RelationPtr indexDescs; IndexScanDescPtr scanDescs; + List **lossyQuals; ExprState ***runtimeKeyInfo; bool have_runtime_keys; RangeTblEntry *rtentry; @@ -680,6 +703,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate) indexstate->iss_RuntimeKeysReady = false; indexstate->iss_RelationDescs = NULL; indexstate->iss_ScanDescs = NULL; + indexstate->iss_LossyQuals = NULL; /* * get the index node information @@ -699,6 +723,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate) scanKeys = (ScanKey *) palloc(numIndices * sizeof(ScanKey)); indexDescs = (RelationPtr) palloc(numIndices * sizeof(Relation)); scanDescs = (IndexScanDescPtr) palloc(numIndices * sizeof(IndexScanDesc)); + lossyQuals = (List **) palloc0(numIndices * sizeof(List *)); /* * initialize space for runtime key info (may not be needed) @@ -712,11 +737,13 @@ ExecInitIndexScan(IndexScan *node, EState *estate) indxqual = node->indxqual; indxstrategy = node->indxstrategy; indxsubtype = node->indxsubtype; + indxlossy = node->indxlossy; for (i = 0; i < numIndices; i++) { List *quals; List *strategies; List *subtypes; + List *lossyflags; int n_keys; ScanKey scan_keys; ExprState **run_keys; @@ -728,6 +755,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate) indxstrategy = lnext(indxstrategy); subtypes = lfirst(indxsubtype); indxsubtype = lnext(indxsubtype); + lossyflags = lfirst(indxlossy); + indxlossy = lnext(indxlossy); n_keys = length(quals); scan_keys = (n_keys <= 0) ? (ScanKey) NULL : (ScanKey) palloc(n_keys * sizeof(ScanKeyData)); @@ -747,6 +776,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate) AttrNumber varattno; /* att number used in scan */ StrategyNumber strategy; /* op's strategy number */ Oid subtype; /* op's strategy subtype */ + int lossy; /* op's recheck flag */ RegProcedure opfuncid; /* operator proc id used in scan */ Datum scanvalue; /* value used in scan (if const) */ @@ -759,6 +789,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate) strategies = lnext(strategies); subtype = lfirsto(subtypes); subtypes = lnext(subtypes); + lossy = lfirsti(lossyflags); + lossyflags = lnext(lossyflags); if (!IsA(clause, OpExpr)) elog(ERROR, "indxqual is not an OpExpr"); @@ -839,6 +871,20 @@ ExecInitIndexScan(IndexScan *node, EState *estate) subtype, /* strategy subtype */ opfuncid, /* reg proc to use */ scanvalue); /* constant */ + + /* + * If this operator is lossy, add its indxqualorig expression + * to the list of quals to recheck. The nth() calls here could + * be avoided by chasing the lists in parallel to all the other + * lists, but since lossy operators are very uncommon, it's + * probably a waste of time to do so. + */ + if (lossy) + { + lossyQuals[i] = lappend(lossyQuals[i], + nth(j, + (List *) nth(i, indexstate->indxqualorig))); + } } /* @@ -928,6 +974,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate) indexstate->iss_RelationDescs = indexDescs; indexstate->iss_ScanDescs = scanDescs; + indexstate->iss_LossyQuals = lossyQuals; /* * Initialize result tuple type and projection info. |