aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeLockRows.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/nodeLockRows.c')
-rw-r--r--src/backend/executor/nodeLockRows.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/src/backend/executor/nodeLockRows.c b/src/backend/executor/nodeLockRows.c
index ec0825b460f..6474393d7f4 100644
--- a/src/backend/executor/nodeLockRows.c
+++ b/src/backend/executor/nodeLockRows.c
@@ -71,8 +71,7 @@ lnext:
bool isNull;
HeapTupleData tuple;
Buffer buffer;
- ItemPointerData update_ctid;
- TransactionId update_xmax;
+ HeapUpdateFailureData hufd;
LockTupleMode lockmode;
HTSU_Result test;
HeapTuple copyTuple;
@@ -117,15 +116,26 @@ lnext:
else
lockmode = LockTupleShared;
- test = heap_lock_tuple(erm->relation, &tuple, &buffer,
- &update_ctid, &update_xmax,
+ test = heap_lock_tuple(erm->relation, &tuple,
estate->es_output_cid,
- lockmode, erm->noWait);
+ lockmode, erm->noWait,
+ &buffer, &hufd);
ReleaseBuffer(buffer);
switch (test)
{
case HeapTupleSelfUpdated:
- /* treat it as deleted; do not process */
+ /*
+ * The target tuple was already updated or deleted by the
+ * current command, or by a later command in the current
+ * transaction. We *must* ignore the tuple in the former
+ * case, so as to avoid the "Halloween problem" of repeated
+ * update attempts. In the latter case it might be sensible
+ * to fetch the updated tuple instead, but doing so would
+ * require changing heap_lock_tuple as well as heap_update and
+ * heap_delete to not complain about updating "invisible"
+ * tuples, which seems pretty scary. So for now, treat the
+ * tuple as deleted and do not process.
+ */
goto lnext;
case HeapTupleMayBeUpdated:
@@ -137,8 +147,7 @@ lnext:
ereport(ERROR,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("could not serialize access due to concurrent update")));
- if (ItemPointerEquals(&update_ctid,
- &tuple.t_self))
+ if (ItemPointerEquals(&hufd.ctid, &tuple.t_self))
{
/* Tuple was deleted, so don't return it */
goto lnext;
@@ -146,7 +155,7 @@ lnext:
/* updated, so fetch and lock the updated version */
copyTuple = EvalPlanQualFetch(estate, erm->relation, lockmode,
- &update_ctid, update_xmax);
+ &hufd.ctid, hufd.xmax);
if (copyTuple == NULL)
{