Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1e3593c

Browse files
committed
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.
1 parent ff49a02 commit 1e3593c

File tree

1 file changed

+32
-10
lines changed

1 file changed

+32
-10
lines changed

src/backend/optimizer/plan/createplan.c

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.208 2006/03/05 15:58:29 momjian Exp $
13+
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.209 2006/04/25 16:54:09 tgl Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -816,8 +816,12 @@ create_indexscan_plan(PlannerInfo *root,
816816
* are not equal to, but are logically implied by, the index quals; so we
817817
* also try a predicate_implied_by() check to see if we can discard quals
818818
* that way. (predicate_implied_by assumes its first input contains only
819-
* immutable functions, so we have to check that.) We can also discard
820-
* quals that are implied by a partial index's predicate.
819+
* immutable functions, so we have to check that.)
820+
*
821+
* We can also discard quals that are implied by a partial index's
822+
* predicate, but only in a plain SELECT; when scanning a target relation
823+
* of UPDATE/DELETE/SELECT FOR UPDATE, we must leave such quals in the
824+
* plan so that they'll be properly rechecked by EvalPlanQual testing.
821825
*
822826
* While at it, we strip off the RestrictInfos to produce a list of plain
823827
* expressions.
@@ -836,8 +840,14 @@ create_indexscan_plan(PlannerInfo *root,
836840

837841
if (predicate_implied_by(clausel, nonlossy_indexquals))
838842
continue;
839-
if (predicate_implied_by(clausel, best_path->indexinfo->indpred))
840-
continue;
843+
if (best_path->indexinfo->indpred)
844+
{
845+
if (baserelid != root->parse->resultRelation &&
846+
!list_member_int(root->parse->rowMarks, baserelid))
847+
if (predicate_implied_by(clausel,
848+
best_path->indexinfo->indpred))
849+
continue;
850+
}
841851
}
842852
qpqual = lappend(qpqual, rinfo->clause);
843853
}
@@ -920,8 +930,12 @@ create_bitmap_scan_plan(PlannerInfo *root,
920930
* but are logically implied by, the index quals; so we also try a
921931
* predicate_implied_by() check to see if we can discard quals that way.
922932
* (predicate_implied_by assumes its first input contains only immutable
923-
* functions, so we have to check that.) We can also discard quals that
924-
* are implied by a partial index's predicate.
933+
* functions, so we have to check that.)
934+
*
935+
* We can also discard quals that are implied by a partial index's
936+
* predicate, but only in a plain SELECT; when scanning a target relation
937+
* of UPDATE/DELETE/SELECT FOR UPDATE, we must leave such quals in the
938+
* plan so that they'll be properly rechecked by EvalPlanQual testing.
925939
*
926940
* XXX For the moment, we only consider partial index predicates in the
927941
* simple single-index-scan case. Is it worth trying to be smart about
@@ -945,8 +959,14 @@ create_bitmap_scan_plan(PlannerInfo *root,
945959
{
946960
IndexPath *ipath = (IndexPath *) best_path->bitmapqual;
947961

948-
if (predicate_implied_by(clausel, ipath->indexinfo->indpred))
949-
continue;
962+
if (ipath->indexinfo->indpred)
963+
{
964+
if (baserelid != root->parse->resultRelation &&
965+
!list_member_int(root->parse->rowMarks, baserelid))
966+
if (predicate_implied_by(clausel,
967+
ipath->indexinfo->indpred))
968+
continue;
969+
}
950970
}
951971
}
952972
qpqual = lappend(qpqual, clause);
@@ -1303,7 +1323,9 @@ create_nestloop_plan(PlannerInfo *root,
13031323
* join quals; failing to prove that doesn't result in an incorrect
13041324
* plan. It is the right way to proceed because adding more quals to
13051325
* the stuff we got from the original query would just make it harder
1306-
* to detect duplication.
1326+
* to detect duplication. (Also, to change this we'd have to be
1327+
* wary of UPDATE/DELETE/SELECT FOR UPDATE target relations; see
1328+
* notes above about EvalPlanQual.)
13071329
*/
13081330
BitmapHeapPath *innerpath = (BitmapHeapPath *) best_path->innerjoinpath;
13091331

0 commit comments

Comments
 (0)