1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-11 20:28:21 +03:00

Fix corner case where SELECT FOR UPDATE could return a row twice.

In READ COMMITTED mode, if a SELECT FOR UPDATE discovers it has to redo
WHERE-clause checking on rows that have been updated since the SELECT's
snapshot, it invokes EvalPlanQual processing to do that.  If this first
occurs within a non-first child table of an inheritance tree, the previous
coding could accidentally re-return a matching row from an earlier,
already-scanned child table.  (And, to add insult to injury, I think this
could make it miss returning a row that should have been returned, if the
updated row that this happens on should still have passed the WHERE qual.)
Per report from Kyotaro Horiguchi; the added isolation test is based on his
test case.

This has been broken for quite awhile, so back-patch to all supported
branches.
This commit is contained in:
Tom Lane
2014-12-11 19:37:00 -05:00
parent 2646d2d4a9
commit 2db576ba8c
3 changed files with 61 additions and 0 deletions

View File

@ -194,7 +194,29 @@ lnext:
*/
if (!epq_started)
{
ListCell *lc2;
EvalPlanQualBegin(&node->lr_epqstate, estate);
/*
* Ensure that rels with already-visited rowmarks are told
* not to return tuples during the first EPQ test. We can
* exit this loop once it reaches the current rowmark;
* rels appearing later in the list will be set up
* correctly by the EvalPlanQualSetTuple call at the top
* of the loop.
*/
foreach(lc2, node->lr_arowMarks)
{
ExecAuxRowMark *aerm2 = (ExecAuxRowMark *) lfirst(lc2);
if (lc2 == lc)
break;
EvalPlanQualSetTuple(&node->lr_epqstate,
aerm2->rowmark->rti,
NULL);
}
epq_started = true;
}