postgres.git / summary / log / commit / refs

commit    2ae8a01ca1af074c166e3f882869dfe307b91b2c
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Fri Dec 12 02:02:31 2014 +0000
First released in: 9.5.0, 9.0.19, 9.1.15, 9.2.10, 9.3.6, 9.4.0

    Fix planning of SELECT FOR UPDATE on child table with partial index.
    
    Ordinarily we can omit checking of a WHERE condition that matches a partial
    index's condition, when we are using an indexscan on that partial index.
    However, in SELECT FOR UPDATE we must include the "redundant" filter
    condition in the plan so that it gets checked properly in an EvalPlanQual
    recheck.  The planner got this mostly right, but improperly omitted the
    filter condition if the index in question was on an inheritance child
    table.  In READ COMMITTED mode, this could result in incorrectly returning
    just-updated rows that no longer satisfy the filter condition.
    
    The cause of the error is using get_parse_rowmark() when get_plan_rowmark()
    is what should be used during planning.  In 9.3 and up, also fix the same
    mistake in contrib/postgres_fdw.  It's currently harmless there (for lack
    of inheritance support) but wrong is wrong, and the incorrect code might
    get copied to someplace where it's more significant.
    
    Report and fix by Kyotaro Horiguchi.  Back-patch to all supported branches.


contrib/postgres_fdw/postgres_fdw.c | 19 +++++++++++-------- src/backend/optimizer/plan/createplan.c | 3 ++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c index f7ab0857a91..0d629e6687b 100644 --- a/contrib/postgres_fdw/postgres_fdw.c +++ b/contrib/postgres_fdw/postgres_fdw.c @@ -819,7 +819,7 @@ postgresGetForeignPlan(PlannerInfo *root, } else { - RowMarkClause *rc = get_parse_rowmark(root->parse, baserel->relid); + PlanRowMark *rc = get_plan_rowmark(root->rowMarks, baserel->relid); if (rc) { @@ -832,15 +832,18 @@ postgresGetForeignPlan(PlannerInfo *root, * complete information about, and (b) it wouldn't work anyway on * older remote servers. Likewise, we don't worry about NOWAIT. */ - switch (rc->strength) + switch (rc->markType) { - case LCS_FORKEYSHARE: - case LCS_FORSHARE: - appendStringInfo(&sql, " FOR SHARE"); + case ROW_MARK_EXCLUSIVE: + case ROW_MARK_NOKEYEXCLUSIVE: + appendStringInfoString(&sql, " FOR UPDATE"); break; - case LCS_FORNOKEYUPDATE: - case LCS_FORUPDATE: - appendStringInfo(&sql, " FOR UPDATE"); + case ROW_MARK_SHARE: + case ROW_MARK_KEYSHARE: + appendStringInfoString(&sql, " FOR SHARE"); + break; + default: + /* nothing needed */ break; } } diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 48b87a0f112..38cc2ca2de6 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -34,6 +34,7 @@ #include "optimizer/planmain.h" #include "optimizer/planner.h" #include "optimizer/predtest.h" +#include "optimizer/prep.h" #include "optimizer/restrictinfo.h" #include "optimizer/subselect.h" #include "optimizer/tlist.h" @@ -1221,7 +1222,7 @@ create_indexscan_plan(PlannerInfo *root, if (best_path->indexinfo->indpred) { if (baserelid != root->parse->resultRelation && - get_parse_rowmark(root->parse, baserelid) == NULL) + get_plan_rowmark(root->rowMarks, baserelid) == NULL) if (predicate_implied_by(clausel, best_path->indexinfo->indpred)) continue; /* implied by index predicate */ [parent: f14196c35973]