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.
This commit is contained in:
parent
e9f11c6b64
commit
fa63749d21
@ -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,
|
|||||||
* (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,
|
|||||||
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,
|
|||||||
* 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,
|
|||||||
|
|
||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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,
|
|||||||
* 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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user