mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-21 08:29:39 +08:00
The 8.1 planner removes WHERE quals from the plan when the quals are
implied by the predicate of a partial index being used to scan a table. However, this optimization is unsafe in an UPDATE, DELETE, or SELECT FOR UPDATE query, because the quals need to be rechecked by EvalPlanQual if there's an update conflict. Per example from Jean-Samuel Reynaud.
This commit is contained in:
parent
ff49a020ca
commit
1e3593ce16
@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.208 2006/03/05 15:58:29 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.209 2006/04/25 16:54:09 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -816,8 +816,12 @@ create_indexscan_plan(PlannerInfo *root,
|
||||
* 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 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.
|
||||
* immutable functions, so we have to check that.)
|
||||
*
|
||||
* We can also discard quals that are implied by a partial index's
|
||||
* predicate, but only in a plain SELECT; when scanning a target relation
|
||||
* of UPDATE/DELETE/SELECT FOR UPDATE, we must leave such quals in the
|
||||
* plan so that they'll be properly rechecked by EvalPlanQual testing.
|
||||
*
|
||||
* While at it, we strip off the RestrictInfos to produce a list of plain
|
||||
* expressions.
|
||||
@ -836,8 +840,14 @@ create_indexscan_plan(PlannerInfo *root,
|
||||
|
||||
if (predicate_implied_by(clausel, nonlossy_indexquals))
|
||||
continue;
|
||||
if (predicate_implied_by(clausel, best_path->indexinfo->indpred))
|
||||
continue;
|
||||
if (best_path->indexinfo->indpred)
|
||||
{
|
||||
if (baserelid != root->parse->resultRelation &&
|
||||
!list_member_int(root->parse->rowMarks, baserelid))
|
||||
if (predicate_implied_by(clausel,
|
||||
best_path->indexinfo->indpred))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
qpqual = lappend(qpqual, rinfo->clause);
|
||||
}
|
||||
@ -920,8 +930,12 @@ create_bitmap_scan_plan(PlannerInfo *root,
|
||||
* 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 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.
|
||||
* functions, so we have to check that.)
|
||||
*
|
||||
* We can also discard quals that are implied by a partial index's
|
||||
* predicate, but only in a plain SELECT; when scanning a target relation
|
||||
* of UPDATE/DELETE/SELECT FOR UPDATE, we must leave such quals in the
|
||||
* plan so that they'll be properly rechecked by EvalPlanQual testing.
|
||||
*
|
||||
* 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
|
||||
@ -945,8 +959,14 @@ create_bitmap_scan_plan(PlannerInfo *root,
|
||||
{
|
||||
IndexPath *ipath = (IndexPath *) best_path->bitmapqual;
|
||||
|
||||
if (predicate_implied_by(clausel, ipath->indexinfo->indpred))
|
||||
continue;
|
||||
if (ipath->indexinfo->indpred)
|
||||
{
|
||||
if (baserelid != root->parse->resultRelation &&
|
||||
!list_member_int(root->parse->rowMarks, baserelid))
|
||||
if (predicate_implied_by(clausel,
|
||||
ipath->indexinfo->indpred))
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
qpqual = lappend(qpqual, clause);
|
||||
@ -1303,7 +1323,9 @@ create_nestloop_plan(PlannerInfo *root,
|
||||
* join quals; failing to prove that doesn't result in an incorrect
|
||||
* plan. It is the right way to proceed because adding more quals to
|
||||
* the stuff we got from the original query would just make it harder
|
||||
* to detect duplication.
|
||||
* to detect duplication. (Also, to change this we'd have to be
|
||||
* wary of UPDATE/DELETE/SELECT FOR UPDATE target relations; see
|
||||
* notes above about EvalPlanQual.)
|
||||
*/
|
||||
BitmapHeapPath *innerpath = (BitmapHeapPath *) best_path->innerjoinpath;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user