summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/createplan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/createplan.c')
-rw-r--r--src/backend/optimizer/plan/createplan.c574
1 files changed, 199 insertions, 375 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 21af9f7e3e2..0ce65a93d19 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.184 2005/04/23 01:29:15 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.185 2005/04/25 01:30:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -47,13 +47,14 @@ static Plan *create_unique_plan(Query *root, UniquePath *best_path);
static SeqScan *create_seqscan_plan(Query *root, Path *best_path,
List *tlist, List *scan_clauses);
static IndexScan *create_indexscan_plan(Query *root, IndexPath *best_path,
- List *tlist, List *scan_clauses);
+ List *tlist, List *scan_clauses,
+ List **nonlossy_clauses);
static BitmapHeapScan *create_bitmap_scan_plan(Query *root,
BitmapHeapPath *best_path,
List *tlist, List *scan_clauses);
-static Plan *create_bitmap_subplan(Query *root, Path *bitmapqual);
+static Plan *create_bitmap_subplan(Query *root, Path *bitmapqual,
+ List **qual, List **indexqual);
static List *create_bitmap_qual(Path *bitmapqual);
-static List *create_bitmap_indxqual(Path *bitmapqual);
static TidScan *create_tidscan_plan(Query *root, TidPath *best_path,
List *tlist, List *scan_clauses);
static SubqueryScan *create_subqueryscan_plan(Query *root, Path *best_path,
@@ -66,31 +67,26 @@ static MergeJoin *create_mergejoin_plan(Query *root, MergePath *best_path,
Plan *outer_plan, Plan *inner_plan);
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 **indxstrategy,
- List **indxsubtype,
- List **indxlossy);
-static void fix_indxqual_sublist(List *indexqual, IndexOptInfo *index,
- List **fixed_quals,
- List **strategy,
- List **subtype,
- List **lossy);
-static Node *fix_indxqual_operand(Node *node, IndexOptInfo *index,
+static void fix_indexqual_references(List *indexquals, IndexPath *index_path,
+ List **fixed_indexquals,
+ List **nonlossy_indexquals,
+ List **indexstrategy,
+ List **indexsubtype);
+static Node *fix_indexqual_operand(Node *node, IndexOptInfo *index,
Oid *opclass);
static List *get_switched_clauses(List *clauses, Relids outerrelids);
static void copy_path_costsize(Plan *dest, Path *src);
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 *indxlossy,
+ Oid indexid, List *indexqual, List *indexqualorig,
+ List *indexstrategy, List *indexsubtype,
ScanDirection indexscandir);
-static BitmapIndexScan *make_bitmap_indexscan(Index scanrelid, Oid indxid,
- List *indxqual,
- List *indxqualorig,
- List *indxstrategy,
- List *indxsubtype);
+static BitmapIndexScan *make_bitmap_indexscan(Index scanrelid, Oid indexid,
+ List *indexqual,
+ List *indexqualorig,
+ List *indexstrategy,
+ List *indexsubtype);
static BitmapHeapScan *make_bitmap_heapscan(List *qptlist,
List *qpqual,
Plan *lefttree,
@@ -236,7 +232,8 @@ create_scan_plan(Query *root, Path *best_path)
plan = (Scan *) create_indexscan_plan(root,
(IndexPath *) best_path,
tlist,
- scan_clauses);
+ scan_clauses,
+ NULL);
break;
case T_BitmapHeapScan:
@@ -701,121 +698,84 @@ create_seqscan_plan(Query *root, Path *best_path,
* Returns an indexscan plan for the base relation scanned by 'best_path'
* with restriction clauses 'scan_clauses' and targetlist 'tlist'.
*
- * The indexquals list of the path contains a sublist of implicitly-ANDed
- * qual conditions for each scan of the index(es); if there is more than one
- * scan then the retrieved tuple sets are ORed together. The indexquals
- * and indexinfo lists must have the same length, ie, the number of scans
- * that will occur. Note it is possible for a qual condition sublist
- * to be empty --- then no index restrictions will be applied during that
- * scan.
+ * The indexquals list of the path contains implicitly-ANDed qual conditions.
+ * The list can be empty --- then no index restrictions will be applied during
+ * the scan.
+ *
+ * If nonlossy_clauses isn't NULL, *nonlossy_clauses receives a list of the
+ * nonlossy indexquals.
*/
static IndexScan *
create_indexscan_plan(Query *root,
IndexPath *best_path,
List *tlist,
- List *scan_clauses)
+ List *scan_clauses,
+ List **nonlossy_clauses)
{
- List *indxquals = best_path->indexquals;
+ List *indexquals = best_path->indexquals;
Index baserelid = best_path->path.parent->relid;
+ Oid indexoid = best_path->indexinfo->indexoid;
List *qpqual;
- Expr *indxqual_or_expr = NULL;
- List *stripped_indxquals;
- List *fixed_indxquals;
- List *indxstrategy;
- List *indxsubtype;
- List *indxlossy;
- List *indexids;
- ListCell *l;
+ List *stripped_indexquals;
+ List *fixed_indexquals;
+ List *nonlossy_indexquals;
+ List *indexstrategy;
+ List *indexsubtype;
IndexScan *scan_plan;
/* it should be a base rel... */
Assert(baserelid > 0);
Assert(best_path->path.parent->rtekind == RTE_RELATION);
- /* Build list of index OIDs */
- indexids = NIL;
- foreach(l, best_path->indexinfo)
- {
- IndexOptInfo *index = (IndexOptInfo *) lfirst(l);
-
- indexids = lappend_oid(indexids, index->indexoid);
- }
-
/*
* Build "stripped" indexquals structure (no RestrictInfos) to pass to
- * executor as indxqualorig
+ * executor as indexqualorig
*/
- stripped_indxquals = NIL;
- foreach(l, indxquals)
- {
- List *andlist = (List *) lfirst(l);
-
- stripped_indxquals = lappend(stripped_indxquals,
- get_actual_clauses(andlist));
- }
+ stripped_indexquals = get_actual_clauses(indexquals);
/*
* 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 gets strategy info and looks for "lossy" operators.
*/
- fix_indxqual_references(indxquals, best_path,
- &fixed_indxquals,
- &indxstrategy, &indxsubtype, &indxlossy);
+ fix_indexqual_references(indexquals, best_path,
+ &fixed_indexquals,
+ &nonlossy_indexquals,
+ &indexstrategy,
+ &indexsubtype);
+
+ /* pass back nonlossy quals if caller wants 'em */
+ if (nonlossy_clauses)
+ *nonlossy_clauses = nonlossy_indexquals;
/*
- * If this is a innerjoin scan, the indexclauses will contain join
+ * If this is an innerjoin scan, the indexclauses will contain join
* clauses that are not present in scan_clauses (since the passed-in
* 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 special operator, we need to make sure it gets into the
* scan_clauses.
+ *
+ * Note: pointer comparison should be enough to determine RestrictInfo
+ * matches.
*/
if (best_path->isjoininner)
- {
- /*
- * We don't currently support OR indexscans in joins, so we only
- * need to worry about the plain AND case. Also, pointer
- * comparison should be enough to determine RestrictInfo matches.
- */
- Assert(list_length(best_path->indexclauses) == 1);
- scan_clauses = list_union_ptr(scan_clauses,
- (List *) linitial(best_path->indexclauses));
- }
-
- /* Reduce RestrictInfo list to bare expressions */
- scan_clauses = get_actual_clauses(scan_clauses);
+ scan_clauses = list_union_ptr(scan_clauses, best_path->indexclauses);
/*
* The qpqual list must contain all restrictions not automatically
* 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.
+ * there are any "special" operators involved then they must be included
+ * in qpqual. Also, any lossy index operators must be rechecked in
+ * the qpqual. The upshot is that qpquals must contain scan_clauses
+ * minus whatever appears in nonlossy_indexquals.
*/
- if (list_length(indxquals) > 1)
- {
- /*
- * Build an expression representation of the indexqual, expanding
- * the implicit OR and AND semantics of the first- and
- * 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 = list_difference(scan_clauses, list_make1(indxqual_or_expr));
- }
- else
- {
- /*
- * Here, we can simply treat the first sublist as an independent
- * set of qual expressions, since there is no top-level OR
- * behavior.
- */
- Assert(stripped_indxquals != NIL);
- qpqual = list_difference(scan_clauses, linitial(stripped_indxquals));
- }
+ qpqual = list_difference_ptr(scan_clauses, nonlossy_indexquals);
+
+ /* Reduce RestrictInfo list to bare expressions */
+ qpqual = get_actual_clauses(qpqual);
/* Sort clauses into best execution order */
qpqual = order_qual_clauses(root, qpqual);
@@ -824,12 +784,11 @@ create_indexscan_plan(Query *root,
scan_plan = make_indexscan(tlist,
qpqual,
baserelid,
- indexids,
- fixed_indxquals,
- stripped_indxquals,
- indxstrategy,
- indxsubtype,
- indxlossy,
+ indexoid,
+ fixed_indexquals,
+ stripped_indexquals,
+ indexstrategy,
+ indexsubtype,
best_path->indexscandir);
copy_path_costsize(&scan_plan->scan.plan, &best_path->path);
@@ -861,14 +820,9 @@ create_bitmap_scan_plan(Query *root,
Assert(baserelid > 0);
Assert(best_path->path.parent->rtekind == RTE_RELATION);
- /* Process the bitmapqual tree into a Plan tree */
- bitmapqualplan = create_bitmap_subplan(root, best_path->bitmapqual);
-
- /* Process the bitmapqual tree into an expression tree, too */
- bitmapqualorig = create_bitmap_qual(best_path->bitmapqual);
-
- /* Also extract the true index conditions */
- indexquals = create_bitmap_indxqual(best_path->bitmapqual);
+ /* Process the bitmapqual tree into a Plan tree and qual lists */
+ bitmapqualplan = create_bitmap_subplan(root, best_path->bitmapqual,
+ &bitmapqualorig, &indexquals);
/* Reduce RestrictInfo list to bare expressions */
scan_clauses = get_actual_clauses(scan_clauses);
@@ -922,70 +876,101 @@ create_bitmap_scan_plan(Query *root,
/*
* Given a bitmapqual tree, generate the Plan tree that implements it
+ *
+ * As byproducts, we also return in *qual and *indexqual the qual lists
+ * (in implicit-AND form, without RestrictInfos) describing the original index
+ * conditions and the generated indexqual conditions. The latter is made to
+ * exclude lossy index operators.
*/
static Plan *
-create_bitmap_subplan(Query *root, Path *bitmapqual)
+create_bitmap_subplan(Query *root, Path *bitmapqual,
+ List **qual, List **indexqual)
{
Plan *plan;
if (IsA(bitmapqual, BitmapAndPath))
{
BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;
- List *newlist = NIL;
+ List *subplans = NIL;
+ List *subquals = NIL;
+ List *subindexquals = NIL;
ListCell *l;
foreach(l, apath->bitmapquals)
{
- Plan *subplan = create_bitmap_subplan(root, lfirst(l));
-
- newlist = lappend(newlist, subplan);
+ Plan *subplan;
+ List *subqual;
+ List *subindexqual;
+
+ subplan = create_bitmap_subplan(root, (Path *) lfirst(l),
+ &subqual, &subindexqual);
+ subplans = lappend(subplans, subplan);
+ subquals = list_concat(subquals, subqual);
+ subindexquals = list_concat(subindexquals, subindexqual);
}
- plan = (Plan *) make_bitmap_and(newlist);
+ plan = (Plan *) make_bitmap_and(subplans);
plan->startup_cost = apath->path.startup_cost;
plan->total_cost = apath->path.total_cost;
plan->plan_rows =
clamp_row_est(apath->bitmapselectivity * apath->path.parent->tuples);
plan->plan_width = 0; /* meaningless */
+ *qual = subquals;
+ *indexqual = subindexquals;
}
else if (IsA(bitmapqual, BitmapOrPath))
{
BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;
- List *newlist = NIL;
+ List *subplans = NIL;
+ List *subquals = NIL;
+ List *subindexquals = NIL;
ListCell *l;
foreach(l, opath->bitmapquals)
{
- Plan *subplan = create_bitmap_subplan(root, lfirst(l));
-
- newlist = lappend(newlist, subplan);
+ Plan *subplan;
+ List *subqual;
+ List *subindexqual;
+
+ subplan = create_bitmap_subplan(root, (Path *) lfirst(l),
+ &subqual, &subindexqual);
+ subplans = lappend(subplans, subplan);
+ subquals = lappend(subquals,
+ make_ands_explicit(subqual));
+ subindexquals = lappend(subindexquals,
+ make_ands_explicit(subindexqual));
}
- plan = (Plan *) make_bitmap_or(newlist);
+ plan = (Plan *) make_bitmap_or(subplans);
plan->startup_cost = opath->path.startup_cost;
plan->total_cost = opath->path.total_cost;
plan->plan_rows =
clamp_row_est(opath->bitmapselectivity * opath->path.parent->tuples);
plan->plan_width = 0; /* meaningless */
+ *qual = list_make1(make_orclause(subquals));
+ *indexqual = list_make1(make_orclause(subindexquals));
}
else if (IsA(bitmapqual, IndexPath))
{
IndexPath *ipath = (IndexPath *) bitmapqual;
IndexScan *iscan;
+ List *nonlossy_clauses;
/* Use the regular indexscan plan build machinery... */
- iscan = create_indexscan_plan(root, ipath, NIL, NIL);
- Assert(list_length(iscan->indxid) == 1);
+ iscan = create_indexscan_plan(root, ipath, NIL, NIL,
+ &nonlossy_clauses);
/* then convert to a bitmap indexscan */
plan = (Plan *) make_bitmap_indexscan(iscan->scan.scanrelid,
- linitial_oid(iscan->indxid),
- linitial(iscan->indxqual),
- linitial(iscan->indxqualorig),
- linitial(iscan->indxstrategy),
- linitial(iscan->indxsubtype));
+ iscan->indexid,
+ iscan->indexqual,
+ iscan->indexqualorig,
+ iscan->indexstrategy,
+ iscan->indexsubtype);
plan->startup_cost = 0.0;
plan->total_cost = ipath->indextotalcost;
plan->plan_rows =
clamp_row_est(ipath->indexselectivity * ipath->path.parent->tuples);
plan->plan_width = 0; /* meaningless */
+ *qual = get_actual_clauses(ipath->indexclauses);
+ *indexqual = get_actual_clauses(nonlossy_clauses);
}
else
{
@@ -1041,8 +1026,7 @@ create_bitmap_qual(Path *bitmapqual)
{
IndexPath *ipath = (IndexPath *) bitmapqual;
- Assert(list_length(ipath->indexclauses) == 1);
- result = get_actual_clauses(linitial(ipath->indexclauses));
+ result = get_actual_clauses(ipath->indexclauses);
}
else
{
@@ -1054,132 +1038,27 @@ create_bitmap_qual(Path *bitmapqual)
}
/*
- * Same as above, except extract the indxqual conditions (which are different
- * if there are special index operators or lossy operators involved).
- *
- * The result essentially represents the conditions the indexscan guarantees
- * to enforce, which may be weaker than the original qual expressions.
+ * Given a bitmapqual tree, generate the equivalent RestrictInfo list.
*/
-static List *
-create_bitmap_indxqual(Path *bitmapqual)
+List *
+create_bitmap_restriction(Path *bitmapqual)
{
- List *result;
- List *sublist;
+ List *bitmapquals;
+ List *bitmapclauses;
ListCell *l;
- if (IsA(bitmapqual, BitmapAndPath))
- {
- BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;
+ bitmapquals = create_bitmap_qual(bitmapqual);
- result = NIL;
- foreach(l, apath->bitmapquals)
- {
- sublist = create_bitmap_indxqual(lfirst(l));
- result = list_concat(result, sublist);
- }
- }
- else if (IsA(bitmapqual, BitmapOrPath))
+ /* must convert qual list to restrictinfos ... painful ... */
+ bitmapclauses = NIL;
+ foreach(l, bitmapquals)
{
- BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;
- List *newlist = NIL;
-
- foreach(l, opath->bitmapquals)
- {
- sublist = create_bitmap_indxqual(lfirst(l));
- if (sublist == NIL)
- {
- /* constant TRUE input yields constant TRUE OR result */
- return NIL;
- }
- newlist = lappend(newlist, make_ands_explicit(sublist));
- }
- result = list_make1(make_orclause(newlist));
- }
- else if (IsA(bitmapqual, IndexPath))
- {
- IndexPath *ipath = (IndexPath *) bitmapqual;
- IndexOptInfo *index;
-
- Assert(list_length(ipath->indexinfo) == 1);
- index = linitial(ipath->indexinfo);
-
- /*
- * We have to remove "lossy" index operators from the result, since
- * the index isn't guaranteeing they are enforced. (This will lead
- * to the operators being rechecked as qpquals of the BitmapHeapScan
- * node.)
- *
- * XXX look at restructuring to share code better with
- * fix_indxqual_references()
- */
- result = NIL;
- Assert(list_length(ipath->indexquals) == 1);
- foreach(l, (List *) linitial(ipath->indexquals))
- {
- RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
- OpExpr *clause;
- Oid opno;
- Node *indexkey;
- Oid opclass;
- int stratno;
- Oid stratsubtype;
- bool recheck;
-
- Assert(IsA(rinfo, RestrictInfo));
- clause = (OpExpr *) rinfo->clause;
- if (!IsA(clause, OpExpr) || list_length(clause->args) != 2)
- elog(ERROR, "indexqual clause is not binary opclause");
- opno = clause->opno;
-
- /*
- * Check to see if the indexkey is on the right; if so, commute
- * the operator. The indexkey should be the side that refers to
- * (only) the base relation.
- */
- if (!bms_equal(rinfo->left_relids, index->rel->relids))
- {
- opno = get_commutator(opno);
- if (!OidIsValid(opno))
- elog(ERROR, "could not find commutator for operator %u",
- clause->opno);
- indexkey = lsecond(clause->args);
- }
- else
- indexkey = linitial(clause->args);
-
- /*
- * Identify the index attribute and get the index opclass.
- * We use fix_indxqual_operand() which does a little more
- * than we really need, but it will do.
- */
- (void) fix_indxqual_operand(indexkey,
- index,
- &opclass);
-
- /*
- * 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(opno, opclass,
- &stratno, &stratsubtype, &recheck);
-
- /*
- * Finally, we can include the clause in the result if it's
- * not a lossy operator.
- */
- if (!recheck)
- result = lappend(result, clause);
- }
- }
- else
- {
- elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual));
- result = NIL; /* keep compiler quiet */
+ bitmapclauses = lappend(bitmapclauses,
+ make_restrictinfo((Expr *) lfirst(l),
+ true, true));
}
- return result;
+ return bitmapclauses;
}
/*
@@ -1299,10 +1178,7 @@ create_nestloop_plan(Query *root,
* An index is being used to reduce the number of tuples scanned
* in the inner relation. If there are join clauses being used
* with the index, we may remove those join clauses from the list
- * of clauses that have to be checked as qpquals at the join node
- * --- but only if there's just one indexscan in the inner path
- * (otherwise, several different sets of clauses are being ORed
- * together).
+ * of clauses that have to be checked as qpquals at the join node.
*
* We can also remove any join clauses that are redundant with those
* being used in the index scan; prior redundancy checks will not
@@ -1313,15 +1189,13 @@ create_nestloop_plan(Query *root,
* not a special innerjoin path.
*/
IndexPath *innerpath = (IndexPath *) best_path->innerjoinpath;
- List *indexclauses = innerpath->indexclauses;
- if (innerpath->isjoininner &&
- list_length(indexclauses) == 1) /* single indexscan? */
+ if (innerpath->isjoininner)
{
joinrestrictclauses =
select_nonredundant_join_clauses(root,
joinrestrictclauses,
- linitial(indexclauses),
+ innerpath->indexclauses,
IS_OUTER_JOIN(best_path->jointype));
}
}
@@ -1334,21 +1208,9 @@ create_nestloop_plan(Query *root,
if (innerpath->isjoininner)
{
- List *bitmapquals;
List *bitmapclauses;
- ListCell *l;
-
- bitmapquals = create_bitmap_qual(innerpath->bitmapqual);
-
- /* must convert qual list to restrictinfos ... painful ... */
- bitmapclauses = NIL;
- foreach(l, bitmapquals)
- {
- bitmapclauses = lappend(bitmapclauses,
- make_restrictinfo((Expr *) lfirst(l),
- true, true));
- }
+ bitmapclauses = create_bitmap_restriction(innerpath->bitmapqual);
joinrestrictclauses =
select_nonredundant_join_clauses(root,
joinrestrictclauses,
@@ -1542,95 +1404,54 @@ create_hashjoin_plan(Query *root,
*****************************************************************************/
/*
- * fix_indxqual_references
+ * fix_indexqual_references
* Adjust indexqual clauses to the form the executor's indexqual
* machinery needs, and check for recheckable (lossy) index conditions.
*
- * We have four tasks here:
+ * We have five 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.)
- * * 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 "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.
+ * left.
+ * * We must construct lists of operator strategy numbers and subtypes
+ * for the top-level operators of each index clause.
+ * * We must detect any lossy index operators. The API is that we return
+ * a list of the input clauses whose operators are NOT lossy.
*
- * fixed_indexquals receives a modified copy of the indexqual list --- the
+ * fixed_indexquals receives a modified copy of the indexquals 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).
*
- * 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 **indxstrategy,
- List **indxsubtype,
- List **indxlossy)
-{
- List *index_info = index_path->indexinfo;
- ListCell *iq,
- *ii;
-
- *fixed_indexquals = NIL;
- *indxstrategy = NIL;
- *indxsubtype = NIL;
- *indxlossy = NIL;
- forboth(iq, indexquals, ii, index_info)
- {
- List *indexqual = (List *) lfirst(iq);
- IndexOptInfo *index = (IndexOptInfo *) lfirst(ii);
- List *fixed_qual;
- List *strategy;
- List *subtype;
- List *lossy;
-
- fix_indxqual_sublist(indexqual, index,
- &fixed_qual, &strategy, &subtype, &lossy);
- *fixed_indexquals = lappend(*fixed_indexquals, fixed_qual);
- *indxstrategy = lappend(*indxstrategy, strategy);
- *indxsubtype = lappend(*indxsubtype, subtype);
- *indxlossy = lappend(*indxlossy, lossy);
- }
-}
-
-/*
- * Fix the sublist of indexquals to be used in a particular scan.
- *
- * 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.) Then determine the operator's strategy number and subtype
- * number, and check for lossy index behavior.
+ * nonlossy_indexquals receives a list of the original input clauses (with
+ * RestrictInfos) that contain non-lossy operators.
*
- * Returns four lists:
- * the list of fixed indexquals
- * the integer list of strategy numbers
- * the OID list of strategy subtypes
- * the integer list of lossiness flags (1/0)
+ * indexstrategy receives an integer list of strategy numbers.
+ * indexsubtype receives an OID list of strategy subtypes.
*/
static void
-fix_indxqual_sublist(List *indexqual, IndexOptInfo *index,
- List **fixed_quals,
- List **strategy,
- List **subtype,
- List **lossy)
+fix_indexqual_references(List *indexquals, IndexPath *index_path,
+ List **fixed_indexquals,
+ List **nonlossy_indexquals,
+ List **indexstrategy,
+ List **indexsubtype)
{
+ IndexOptInfo *index = index_path->indexinfo;
ListCell *l;
- *fixed_quals = NIL;
- *strategy = NIL;
- *subtype = NIL;
- *lossy = NIL;
- foreach(l, indexqual)
+ *fixed_indexquals = NIL;
+ *nonlossy_indexquals = NIL;
+ *indexstrategy = NIL;
+ *indexsubtype = NIL;
+
+ /*
+ * 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.) Then determine the operator's strategy
+ * number and subtype number, and check for lossy index behavior.
+ */
+ foreach(l, indexquals)
{
RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
OpExpr *clause;
@@ -1642,7 +1463,8 @@ fix_indxqual_sublist(List *indexqual, IndexOptInfo *index,
Assert(IsA(rinfo, RestrictInfo));
clause = (OpExpr *) rinfo->clause;
- if (!IsA(clause, OpExpr) ||list_length(clause->args) != 2)
+ if (!IsA(clause, OpExpr) ||
+ list_length(clause->args) != 2)
elog(ERROR, "indexqual clause is not binary opclause");
/*
@@ -1666,11 +1488,12 @@ fix_indxqual_sublist(List *indexqual, IndexOptInfo *index,
* Now, determine which index attribute this is, change the
* indexkey operand as needed, and get the index opclass.
*/
- linitial(newclause->args) = fix_indxqual_operand(linitial(newclause->args),
- index,
- &opclass);
+ linitial(newclause->args) =
+ fix_indexqual_operand(linitial(newclause->args),
+ index,
+ &opclass);
- *fixed_quals = lappend(*fixed_quals, newclause);
+ *fixed_indexquals = lappend(*fixed_indexquals, newclause);
/*
* Look up the (possibly commuted) operator in the operator class
@@ -1681,14 +1504,17 @@ fix_indxqual_sublist(List *indexqual, IndexOptInfo *index,
get_op_opclass_properties(newclause->opno, opclass,
&stratno, &stratsubtype, &recheck);
- *strategy = lappend_int(*strategy, stratno);
- *subtype = lappend_oid(*subtype, stratsubtype);
- *lossy = lappend_int(*lossy, (int) recheck);
+ *indexstrategy = lappend_int(*indexstrategy, stratno);
+ *indexsubtype = lappend_oid(*indexsubtype, stratsubtype);
+
+ /* If it's not lossy, add to nonlossy_indexquals */
+ if (!recheck)
+ *nonlossy_indexquals = lappend(*nonlossy_indexquals, rinfo);
}
}
static Node *
-fix_indxqual_operand(Node *node, IndexOptInfo *index, Oid *opclass)
+fix_indexqual_operand(Node *node, IndexOptInfo *index, Oid *opclass)
{
/*
* We represent index keys by Var nodes having the varno of the base
@@ -1923,12 +1749,11 @@ static IndexScan *
make_indexscan(List *qptlist,
List *qpqual,
Index scanrelid,
- List *indxid,
- List *indxqual,
- List *indxqualorig,
- List *indxstrategy,
- List *indxsubtype,
- List *indxlossy,
+ Oid indexid,
+ List *indexqual,
+ List *indexqualorig,
+ List *indexstrategy,
+ List *indexsubtype,
ScanDirection indexscandir)
{
IndexScan *node = makeNode(IndexScan);
@@ -1940,24 +1765,23 @@ make_indexscan(List *qptlist,
plan->lefttree = NULL;
plan->righttree = NULL;
node->scan.scanrelid = scanrelid;
- node->indxid = indxid;
- node->indxqual = indxqual;
- node->indxqualorig = indxqualorig;
- node->indxstrategy = indxstrategy;
- node->indxsubtype = indxsubtype;
- node->indxlossy = indxlossy;
- node->indxorderdir = indexscandir;
+ node->indexid = indexid;
+ node->indexqual = indexqual;
+ node->indexqualorig = indexqualorig;
+ node->indexstrategy = indexstrategy;
+ node->indexsubtype = indexsubtype;
+ node->indexorderdir = indexscandir;
return node;
}
static BitmapIndexScan *
make_bitmap_indexscan(Index scanrelid,
- Oid indxid,
- List *indxqual,
- List *indxqualorig,
- List *indxstrategy,
- List *indxsubtype)
+ Oid indexid,
+ List *indexqual,
+ List *indexqualorig,
+ List *indexstrategy,
+ List *indexsubtype)
{
BitmapIndexScan *node = makeNode(BitmapIndexScan);
Plan *plan = &node->scan.plan;
@@ -1968,11 +1792,11 @@ make_bitmap_indexscan(Index scanrelid,
plan->lefttree = NULL;
plan->righttree = NULL;
node->scan.scanrelid = scanrelid;
- node->indxid = indxid;
- node->indxqual = indxqual;
- node->indxqualorig = indxqualorig;
- node->indxstrategy = indxstrategy;
- node->indxsubtype = indxsubtype;
+ node->indexid = indexid;
+ node->indexqual = indexqual;
+ node->indexqualorig = indexqualorig;
+ node->indexstrategy = indexstrategy;
+ node->indexsubtype = indexsubtype;
return node;
}