aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/executor/nodeIndexscan.c49
-rw-r--r--src/backend/nodes/copyfuncs.c13
-rw-r--r--src/backend/nodes/outfuncs.c12
-rw-r--r--src/backend/optimizer/path/costsize.c7
-rw-r--r--src/backend/optimizer/plan/createplan.c154
-rw-r--r--src/backend/optimizer/plan/setrefs.c6
-rw-r--r--src/include/nodes/execnodes.h4
-rw-r--r--src/include/nodes/plannodes.h3
8 files changed, 134 insertions, 114 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.
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 75c2fa898d9..18a8a369e69 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.273 2004/01/05 05:07:35 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.274 2004/01/06 04:31:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -284,6 +284,17 @@ _copyIndexScan(IndexScan *from)
}
newnode->indxsubtype = newsubtype;
}
+ /* this can become COPY_NODE_FIELD when intlists are normal objects: */
+ {
+ List *newstrat = NIL;
+ List *tmp;
+
+ foreach(tmp, from->indxlossy)
+ {
+ newstrat = lappend(newstrat, listCopy(lfirst(tmp)));
+ }
+ newnode->indxlossy = newstrat;
+ }
COPY_SCALAR_FIELD(indxorderdir);
return newnode;
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 1a78769e8f2..ce80cae4bdb 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.228 2004/01/05 23:39:53 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.229 2004/01/06 04:31:01 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
@@ -356,6 +356,16 @@ _outIndexScan(StringInfo str, IndexScan *node)
_outOidList(str, lfirst(tmp));
}
}
+ /* this can become WRITE_NODE_FIELD when intlists are normal objects: */
+ {
+ List *tmp;
+
+ appendStringInfo(str, " :indxlossy ");
+ foreach(tmp, node->indxlossy)
+ {
+ _outIntList(str, lfirst(tmp));
+ }
+ }
WRITE_ENUM_FIELD(indxorderdir, ScanDirection);
}
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 7353e73462b..3f9416c20ac 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -49,7 +49,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.121 2004/01/05 23:39:54 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.122 2004/01/06 04:31:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -384,10 +384,6 @@ cost_index(Path *path, Query *root,
* some of the indexquals are join clauses and shouldn't be
* subtracted. Rather than work out exactly how much to subtract, we
* don't subtract anything.
- *
- * XXX For a lossy index, not all the quals will be removed and so we
- * really shouldn't subtract their costs; but detecting that seems
- * more expensive than it's worth.
*/
startup_cost += baserel->baserestrictcost.startup;
cpu_per_tuple = cpu_tuple_cost + baserel->baserestrictcost.per_tuple;
@@ -397,6 +393,7 @@ cost_index(Path *path, Query *root,
QualCost index_qual_cost;
cost_qual_eval(&index_qual_cost, indexQuals);
+ /* any startup cost still has to be paid ... */
cpu_per_tuple -= index_qual_cost.per_tuple;
}
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 591cf47f8c6..a1030c8779c 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.164 2004/01/05 23:39:54 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.165 2004/01/06 04:31:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -62,16 +62,16 @@ static HashJoin *create_hashjoin_plan(Query *root, HashPath *best_path,
Plan *outer_plan, Plan *inner_plan);
static void fix_indxqual_references(List *indexquals, IndexPath *index_path,
List **fixed_indexquals,
- List **recheck_indexquals,
List **indxstrategy,
- List **indxsubtype);
+ List **indxsubtype,
+ List **indxlossy);
static void fix_indxqual_sublist(List *indexqual,
Relids baserelids, int baserelid,
IndexOptInfo *index,
List **fixed_quals,
- List **recheck_quals,
List **strategy,
- List **subtype);
+ List **subtype,
+ List **lossy);
static Node *fix_indxqual_operand(Node *node, int baserelid,
IndexOptInfo *index,
Oid *opclass);
@@ -82,7 +82,7 @@ static void copy_plan_costsize(Plan *dest, Plan *src);
static SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid);
static IndexScan *make_indexscan(List *qptlist, List *qpqual, Index scanrelid,
List *indxid, List *indxqual, List *indxqualorig,
- List *indxstrategy, List *indxsubtype,
+ List *indxstrategy, List *indxsubtype, List *indxlossy,
ScanDirection indexscandir);
static TidScan *make_tidscan(List *qptlist, List *qpqual, Index scanrelid,
List *tideval);
@@ -718,9 +718,9 @@ create_indexscan_plan(Query *root,
Expr *indxqual_or_expr = NULL;
List *stripped_indxquals;
List *fixed_indxquals;
- List *recheck_indxquals;
List *indxstrategy;
List *indxsubtype;
+ List *indxlossy;
FastList indexids;
List *i;
IndexScan *scan_plan;
@@ -735,8 +735,8 @@ create_indexscan_plan(Query *root,
* value is just the rel's baserestrictinfo list). We must add these
* clauses to scan_clauses to ensure they get checked. In most cases
* we will remove the join clauses again below, but if a join clause
- * contains a lossy or special operator, we need to make sure it gets
- * into scan_clauses.
+ * contains a special operator, we need to make sure it gets into the
+ * scan_clauses.
*/
if (best_path->isjoininner)
{
@@ -780,22 +780,19 @@ create_indexscan_plan(Query *root,
/*
* The qpqual list must contain all restrictions not automatically
- * handled by the index. Normally the predicates in the indexquals are
- * checked fully by the index, but if the index is "lossy" for a
- * particular operator (as signaled by the amopreqcheck flag in
- * pg_amop), then we need to double-check that predicate in qpqual,
- * because the index may return more tuples than match the predicate.
- *
- * Since the indexquals were generated from the restriction clauses given
- * by scan_clauses, there will normally be duplications between the lists.
- * We get rid of the duplicates, then add back if lossy.
+ * handled by the index. All the predicates in the indexquals will
+ * be checked (either by the index itself, or by nodeIndexscan.c), but
+ * if there are any "special" operators involved then they must be
+ * added to qpqual. The upshot is that qpquals must contain scan_clauses
+ * minus whatever appears in indxquals.
*/
if (length(indxquals) > 1)
{
/*
* Build an expression representation of the indexqual, expanding
* the implicit OR and AND semantics of the first- and
- * second-level lists.
+ * second-level lists. (The odds that this will exactly match any
+ * scan_clause are not great; perhaps we need more smarts here.)
*/
indxqual_or_expr = make_expr_from_indexclauses(indxquals);
qpqual = set_difference(scan_clauses, makeList1(indxqual_or_expr));
@@ -814,34 +811,11 @@ create_indexscan_plan(Query *root,
/*
* The executor needs a copy with the indexkey on the left of each
* clause and with index attr numbers substituted for table ones. This
- * pass also looks for "lossy" operators.
+ * pass also gets strategy info and looks for "lossy" operators.
*/
fix_indxqual_references(indxquals, best_path,
- &fixed_indxquals, &recheck_indxquals,
- &indxstrategy, &indxsubtype);
-
- /*
- * If there were any "lossy" operators, need to add back the
- * appropriate qual clauses to the qpqual. When there is just one
- * indexscan being performed (ie, we have simple AND semantics), we
- * can just add the lossy clauses themselves to qpqual. If we have
- * OR-of-ANDs, we'd better add the entire original indexquals to make
- * sure that the semantics are correct.
- */
- if (recheck_indxquals != NIL)
- {
- if (indxqual_or_expr)
- {
- /* Better do a deep copy of the original scanclauses */
- qpqual = lappend(qpqual, copyObject(indxqual_or_expr));
- }
- else
- {
- /* Subroutine already copied quals, so just append to list */
- Assert(length(recheck_indxquals) == 1);
- qpqual = nconc(qpqual, (List *) lfirst(recheck_indxquals));
- }
- }
+ &fixed_indxquals,
+ &indxstrategy, &indxsubtype, &indxlossy);
/* Finally ready to build the plan node */
scan_plan = make_indexscan(tlist,
@@ -852,6 +826,7 @@ create_indexscan_plan(Query *root,
stripped_indxquals,
indxstrategy,
indxsubtype,
+ indxlossy,
best_path->indexscandir);
copy_path_costsize(&scan_plan->scan.plan, &best_path->path);
@@ -1197,76 +1172,64 @@ create_hashjoin_plan(Query *root,
* Adjust indexqual clauses to the form the executor's indexqual
* machinery needs, and check for recheckable (lossy) index conditions.
*
- * We have five tasks here:
+ * We have four tasks here:
* * Remove RestrictInfo nodes from the input clauses.
* * Index keys must be represented by Var nodes with varattno set to the
* index's attribute number, not the attribute number in the original rel.
* * If the index key is on the right, commute the clause to put it on the
* left. (Someday the executor might not need this, but for now it does.)
- * * If the indexable operator is marked 'amopreqcheck' in pg_amop, then
- * the index is "lossy" for this operator: it may return more tuples than
- * actually satisfy the operator condition. For each such operator, we
- * must add (the original form of) the indexqual clause to the "qpquals"
- * of the indexscan node, where the operator will be re-evaluated to
- * ensure it passes.
- * * We must construct lists of operator strategy numbers and subtypes for
- * the top-level operators of each index clause.
+ * * We must construct lists of operator strategy numbers, subtypes, and
+ * recheck (lossy-operator) flags for the top-level operators of each
+ * index clause.
*
- * Both the input list and the output lists have the form of lists of sublists
- * of qual clauses --- the top-level list has one entry for each indexscan
- * to be performed. The semantics are OR-of-ANDs. Note however that the
- * input list contains RestrictInfos, while the output lists do not.
+ * Both the input list and the "fixed" output list have the form of lists of
+ * sublists of qual clauses --- the top-level list has one entry for each
+ * indexscan to be performed. The semantics are OR-of-ANDs. Note however
+ * that the input list contains RestrictInfos, while the output list doesn't.
*
* fixed_indexquals receives a modified copy of the indexqual list --- the
* original is not changed. Note also that the copy shares no substructure
* with the original; this is needed in case there is a subplan in it (we need
* two separate copies of the subplan tree, or things will go awry).
*
- * recheck_indexquals similarly receives a copy of whichever clauses
- * need rechecking.
- *
* indxstrategy receives a list of integer sublists of strategy numbers.
* indxsubtype receives a list of OID sublists of strategy subtypes.
+ * indxlossy receives a list of integer sublists of lossy-operator booleans.
*/
static void
fix_indxqual_references(List *indexquals, IndexPath *index_path,
- List **fixed_indexquals, List **recheck_indexquals,
- List **indxstrategy, List **indxsubtype)
+ List **fixed_indexquals,
+ List **indxstrategy,
+ List **indxsubtype,
+ List **indxlossy)
{
- FastList fixed_quals;
- FastList recheck_quals;
Relids baserelids = index_path->path.parent->relids;
int baserelid = index_path->path.parent->relid;
List *ixinfo = index_path->indexinfo;
List *i;
- FastListInit(&fixed_quals);
- FastListInit(&recheck_quals);
+ *fixed_indexquals = NIL;
*indxstrategy = NIL;
*indxsubtype = NIL;
+ *indxlossy = NIL;
foreach(i, indexquals)
{
List *indexqual = lfirst(i);
IndexOptInfo *index = (IndexOptInfo *) lfirst(ixinfo);
List *fixed_qual;
- List *recheck_qual;
List *strategy;
List *subtype;
+ List *lossy;
fix_indxqual_sublist(indexqual, baserelids, baserelid, index,
- &fixed_qual, &recheck_qual,
- &strategy, &subtype);
- FastAppend(&fixed_quals, fixed_qual);
- if (recheck_qual != NIL)
- FastAppend(&recheck_quals, recheck_qual);
+ &fixed_qual, &strategy, &subtype, &lossy);
+ *fixed_indexquals = lappend(*fixed_indexquals, fixed_qual);
*indxstrategy = lappend(*indxstrategy, strategy);
*indxsubtype = lappend(*indxsubtype, subtype);
+ *indxlossy = lappend(*indxlossy, lossy);
ixinfo = lnext(ixinfo);
}
-
- *fixed_indexquals = FastListValue(&fixed_quals);
- *recheck_indexquals = FastListValue(&recheck_quals);
}
/*
@@ -1274,34 +1237,30 @@ fix_indxqual_references(List *indexquals, IndexPath *index_path,
*
* For each qual clause, commute if needed to put the indexkey operand on the
* left, and then fix its varattno. (We do not need to change the other side
- * of the clause.) Also change the operator if necessary, check for
- * lossy index behavior, and determine the operator's strategy number and
- * subtype number.
+ * of the clause.) Then determine the operator's strategy number and subtype
+ * number, and check for lossy index behavior.
*
* Returns four lists:
* the list of fixed indexquals
- * the list (usually empty) of original clauses that must be rechecked
- * as qpquals because the index is lossy for this operator type
* the integer list of strategy numbers
* the OID list of strategy subtypes
+ * the integer list of lossiness flags (1/0)
*/
static void
fix_indxqual_sublist(List *indexqual,
Relids baserelids, int baserelid,
IndexOptInfo *index,
List **fixed_quals,
- List **recheck_quals,
List **strategy,
- List **subtype)
+ List **subtype,
+ List **lossy)
{
- FastList fixed_qual;
- FastList recheck_qual;
List *i;
- FastListInit(&fixed_qual);
- FastListInit(&recheck_qual);
+ *fixed_quals = NIL;
*strategy = NIL;
*subtype = NIL;
+ *lossy = NIL;
foreach(i, indexqual)
{
RestrictInfo *rinfo = (RestrictInfo *) lfirst(i);
@@ -1344,29 +1303,20 @@ fix_indxqual_sublist(List *indexqual,
index,
&opclass);
- FastAppend(&fixed_qual, newclause);
+ *fixed_quals = lappend(*fixed_quals, newclause);
/*
- * Look up the operator in the operator class to get its strategy
- * numbers and the recheck indicator. This also double-checks that
- * we found an operator matching the index.
+ * Look up the (possibly commuted) operator in the operator class to
+ * get its strategy numbers and the recheck indicator. This also
+ * double-checks that we found an operator matching the index.
*/
get_op_opclass_properties(newclause->opno, opclass,
&stratno, &stratsubtype, &recheck);
*strategy = lappendi(*strategy, stratno);
*subtype = lappendo(*subtype, stratsubtype);
-
- /*
- * If index is lossy for this operator, add (a copy of) original form
- * of clause to recheck list.
- */
- if (recheck)
- FastAppend(&recheck_qual, copyObject((Node *) clause));
+ *lossy = lappendi(*lossy, (int) recheck);
}
-
- *fixed_quals = FastListValue(&fixed_qual);
- *recheck_quals = FastListValue(&recheck_qual);
}
static Node *
@@ -1612,6 +1562,7 @@ make_indexscan(List *qptlist,
List *indxqualorig,
List *indxstrategy,
List *indxsubtype,
+ List *indxlossy,
ScanDirection indexscandir)
{
IndexScan *node = makeNode(IndexScan);
@@ -1628,6 +1579,7 @@ make_indexscan(List *qptlist,
node->indxqualorig = indxqualorig;
node->indxstrategy = indxstrategy;
node->indxsubtype = indxsubtype;
+ node->indxlossy = indxlossy;
node->indxorderdir = indexscandir;
return node;
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 8f64ef1488e..faf4eb29bee 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.99 2003/11/29 19:51:50 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.100 2004/01/06 04:31:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -362,8 +362,8 @@ set_join_references(Join *join, List *rtable)
/*
* We must fix the inner qpqual too, if it has join
- * clauses (this could happen if the index is lossy: some
- * indxquals may get rechecked as qpquals).
+ * clauses (this could happen if special operators are
+ * involved: some indxquals may get rechecked as qpquals).
*/
if (NumRelids((Node *) inner_plan->qual) > 1)
inner_plan->qual = join_references(inner_plan->qual,
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 48385d16f31..21d32dec857 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.109 2003/12/18 22:23:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.110 2004/01/06 04:31:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -776,6 +776,7 @@ typedef ScanState SeqScanState;
* RuntimeKeysReady true if runtime Skeys have been computed
* RelationDescs ptr to array of relation descriptors
* ScanDescs ptr to array of scan descriptors
+ * LossyQuals ptr to array of qual lists for lossy operators
* DupHash hashtable for recognizing dups in multiple scan
* MaxHash max # entries we will allow in hashtable
* ----------------
@@ -795,6 +796,7 @@ typedef struct IndexScanState
bool iss_RuntimeKeysReady;
RelationPtr iss_RelationDescs;
IndexScanDescPtr iss_ScanDescs;
+ List **iss_LossyQuals;
HTAB *iss_DupHash;
long iss_MaxHash;
} IndexScanState;
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 580b9dec192..be8b121e251 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.72 2003/11/29 22:41:06 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.73 2004/01/06 04:31:01 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -166,6 +166,7 @@ typedef struct IndexScan
List *indxqualorig; /* the same in original form */
List *indxstrategy; /* list of sublists of strategy numbers */
List *indxsubtype; /* list of sublists of strategy subtypes */
+ List *indxlossy; /* list of sublists of lossy flags (ints) */
ScanDirection indxorderdir; /* forward or backward or don't care */
} IndexScan;