mirror of
https://github.com/postgres/postgres.git
synced 2025-06-11 20:28:21 +03:00
Fix misbehavior of EvalPlanQual checks with multiple result relations.
The idea of EvalPlanQual is that we replace the query's scan of the result relation with a single injected tuple, and see if we get a tuple out, thereby implying that the injected tuple still passes the query quals. (In join cases, other relations in the query are still scanned normally.) This logic was not updated when commit86dc90056
made it possible for a single DML query plan to have multiple result relations, when the query target relation has inheritance or partition children. We replaced the output for the current result relation successfully, but other result relations were still scanned normally; thus, if any other result relation contained a tuple satisfying the quals, we'd think the EPQ check passed, even if it did not pass for the injected tuple itself. This would lead to update or delete actions getting performed when they should have been skipped due to a conflicting concurrent update in READ COMMITTED isolation mode. Fix by blocking all sibling result relations from emitting tuples during an EvalPlanQual recheck. In the back branches, the fix is complicated a bit by the need to not change the size of struct EPQState (else we'd have ABI-breaking changes in offsets in struct ModifyTableState). Like the back-patches of3f7836ff6
and4b3e37993
, add a separately palloc'd struct to avoid that. The logic is the same as in HEAD otherwise. This is only a live bug back to v14 where86dc90056
came in. However, I chose to back-patch the test cases further, on the grounds that this whole area is none too well tested. I skipped doing so in v11 though because none of the test applied cleanly, and it didn't quite seem worth extra work for a branch with only six months to live. Per report from Ante Krešić (via Aleksander Alekseev) Discussion: https://postgr.es/m/CAJ7c6TMBTN3rcz4=AjYhLPD_w3FFT0Wq_C15jxCDn8U4tZnH1g@mail.gmail.com
This commit is contained in:
@ -108,7 +108,6 @@ lnext:
|
||||
/* this child is inactive right now */
|
||||
erm->ermActive = false;
|
||||
ItemPointerSetInvalid(&(erm->curCtid));
|
||||
ExecClearTuple(markSlot);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -370,7 +369,7 @@ ExecInitLockRows(LockRows *node, EState *estate, int eflags)
|
||||
|
||||
/* Now we have the info needed to set up EPQ state */
|
||||
EvalPlanQualInit(&lrstate->lr_epqstate, estate,
|
||||
outerPlan, epq_arowmarks, node->epqParam);
|
||||
outerPlan, epq_arowmarks, node->epqParam, NIL);
|
||||
|
||||
return lrstate;
|
||||
}
|
||||
|
Reference in New Issue
Block a user