Commit fa63749d authored by Tom Lane's avatar Tom Lane

Fix oversight in indexscan plan creation. I recently added code to use

predicate_implied_by() to detect redundant filter conditions, but forgot
that predicate_implied_by() assumes its first argument contains only
immutable functions.  Add a check to guarantee that.  Also, test to see
if filter conditions can be discarded because they are redundant with
the predicate of a partial index.
parent e9f11c6b
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.198 2005/09/24 22:54:37 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.199 2005/10/06 16:01:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -819,7 +819,9 @@ create_indexscan_plan(PlannerInfo *root, ...@@ -819,7 +819,9 @@ create_indexscan_plan(PlannerInfo *root,
* (particularly with OR'd index conditions) we may have scan_clauses * (particularly with OR'd index conditions) we may have scan_clauses
* that are not equal to, but are logically implied by, the index quals; * that are not equal to, but are logically implied by, the index quals;
* so we also try a predicate_implied_by() check to see if we can discard * so we also try a predicate_implied_by() check to see if we can discard
* quals that way. * quals that way. (predicate_implied_by assumes its first input contains
* only immutable functions, so we have to check that.) We can also
* discard quals that are implied by a partial index's predicate.
* *
* While at it, we strip off the RestrictInfos to produce a list of * While at it, we strip off the RestrictInfos to produce a list of
* plain expressions. * plain expressions.
...@@ -832,9 +834,15 @@ create_indexscan_plan(PlannerInfo *root, ...@@ -832,9 +834,15 @@ create_indexscan_plan(PlannerInfo *root,
Assert(IsA(rinfo, RestrictInfo)); Assert(IsA(rinfo, RestrictInfo));
if (list_member_ptr(nonlossy_indexquals, rinfo)) if (list_member_ptr(nonlossy_indexquals, rinfo))
continue; continue;
if (predicate_implied_by(list_make1(rinfo->clause), if (!contain_mutable_functions((Node *) rinfo->clause))
nonlossy_indexquals)) {
continue; List *clausel = list_make1(rinfo->clause);
if (predicate_implied_by(clausel, nonlossy_indexquals))
continue;
if (predicate_implied_by(clausel, best_path->indexinfo->indpred))
continue;
}
qpqual = lappend(qpqual, rinfo->clause); qpqual = lappend(qpqual, rinfo->clause);
} }
...@@ -916,6 +924,14 @@ create_bitmap_scan_plan(PlannerInfo *root, ...@@ -916,6 +924,14 @@ create_bitmap_scan_plan(PlannerInfo *root,
* OR'd index conditions) we may have scan_clauses that are not equal to, * OR'd index conditions) we may have scan_clauses that are not equal to,
* but are logically implied by, the index quals; so we also try a * but are logically implied by, the index quals; so we also try a
* predicate_implied_by() check to see if we can discard quals that way. * predicate_implied_by() check to see if we can discard quals that way.
* (predicate_implied_by assumes its first input contains only immutable
* functions, so we have to check that.) We can also discard quals that
* are implied by a partial index's predicate.
*
* XXX For the moment, we only consider partial index predicates in the
* simple single-index-scan case. Is it worth trying to be smart about
* more complex cases? Perhaps create_bitmap_subplan should be made to
* include predicate info in what it constructs.
*/ */
qpqual = NIL; qpqual = NIL;
foreach(l, scan_clauses) foreach(l, scan_clauses)
...@@ -924,9 +940,20 @@ create_bitmap_scan_plan(PlannerInfo *root, ...@@ -924,9 +940,20 @@ create_bitmap_scan_plan(PlannerInfo *root,
if (list_member(indexquals, clause)) if (list_member(indexquals, clause))
continue; continue;
if (predicate_implied_by(list_make1(clause), if (!contain_mutable_functions(clause))
indexquals)) {
continue; List *clausel = list_make1(clause);
if (predicate_implied_by(clausel, indexquals))
continue;
if (IsA(best_path->bitmapqual, IndexPath))
{
IndexPath *ipath = (IndexPath *) best_path->bitmapqual;
if (predicate_implied_by(clausel, ipath->indexinfo->indpred))
continue;
}
}
qpqual = lappend(qpqual, clause); qpqual = lappend(qpqual, clause);
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.2 2005/07/23 21:05:47 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.3 2005/10/06 16:01:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -47,7 +47,7 @@ static bool btree_predicate_proof(Expr *predicate, Node *clause, ...@@ -47,7 +47,7 @@ static bool btree_predicate_proof(Expr *predicate, Node *clause,
* valid, but no worse consequences will ensue. * valid, but no worse consequences will ensue.
* *
* We assume the predicate has already been checked to contain only * We assume the predicate has already been checked to contain only
* immutable functions and operators. (In current use this is true * immutable functions and operators. (In most current uses this is true
* because the predicate is part of an index predicate that has passed * because the predicate is part of an index predicate that has passed
* CheckPredicate().) We dare not make deductions based on non-immutable * CheckPredicate().) We dare not make deductions based on non-immutable
* functions, because they might change answers between the time we make * functions, because they might change answers between the time we make
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment