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

Commit f2e2054

Browse files
committed
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.
1 parent 0c12be8 commit f2e2054

File tree

2 files changed

+12
-8
lines changed

2 files changed

+12
-8
lines changed

contrib/postgres_fdw/postgres_fdw.c

+10-7
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,7 @@ postgresGetForeignPlan(PlannerInfo *root,
817817
}
818818
else
819819
{
820-
RowMarkClause *rc = get_parse_rowmark(root->parse, baserel->relid);
820+
PlanRowMark *rc = get_plan_rowmark(root->rowMarks, baserel->relid);
821821

822822
if (rc)
823823
{
@@ -830,15 +830,18 @@ postgresGetForeignPlan(PlannerInfo *root,
830830
* complete information about, and (b) it wouldn't work anyway on
831831
* older remote servers. Likewise, we don't worry about NOWAIT.
832832
*/
833-
switch (rc->strength)
833+
switch (rc->markType)
834834
{
835-
case LCS_FORKEYSHARE:
836-
case LCS_FORSHARE:
835+
case ROW_MARK_EXCLUSIVE:
836+
case ROW_MARK_NOKEYEXCLUSIVE:
837+
appendStringInfoString(&sql, " FOR UPDATE");
838+
break;
839+
case ROW_MARK_SHARE:
840+
case ROW_MARK_KEYSHARE:
837841
appendStringInfoString(&sql, " FOR SHARE");
838842
break;
839-
case LCS_FORNOKEYUPDATE:
840-
case LCS_FORUPDATE:
841-
appendStringInfoString(&sql, " FOR UPDATE");
843+
default:
844+
/* nothing needed */
842845
break;
843846
}
844847
}

src/backend/optimizer/plan/createplan.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "optimizer/planmain.h"
3535
#include "optimizer/planner.h"
3636
#include "optimizer/predtest.h"
37+
#include "optimizer/prep.h"
3738
#include "optimizer/restrictinfo.h"
3839
#include "optimizer/subselect.h"
3940
#include "optimizer/tlist.h"
@@ -1219,7 +1220,7 @@ create_indexscan_plan(PlannerInfo *root,
12191220
if (best_path->indexinfo->indpred)
12201221
{
12211222
if (baserelid != root->parse->resultRelation &&
1222-
get_parse_rowmark(root->parse, baserelid) == NULL)
1223+
get_plan_rowmark(root->rowMarks, baserelid) == NULL)
12231224
if (predicate_implied_by(clausel,
12241225
best_path->indexinfo->indpred))
12251226
continue; /* implied by index predicate */

0 commit comments

Comments
 (0)