diff options
Diffstat (limited to 'src/backend/access/heap/heapam.c')
-rw-r--r-- | src/backend/access/heap/heapam.c | 85 |
1 files changed, 46 insertions, 39 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 5a4591e0451..570cf95eaf7 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -2352,27 +2352,26 @@ simple_heap_insert(Relation relation, HeapTuple tup) * * relation - table to be modified (caller must hold suitable lock) * tid - TID of tuple to be deleted - * ctid - output parameter, used only for failure case (see below) - * update_xmax - output parameter, used only for failure case (see below) * cid - delete command ID (used for visibility test, and stored into * cmax if successful) * crosscheck - if not InvalidSnapshot, also check tuple against this * wait - true if should wait for any conflicting update to commit/abort + * hufd - output parameter, filled in failure cases (see below) * * Normal, successful return value is HeapTupleMayBeUpdated, which * actually means we did delete it. Failure return codes are * HeapTupleSelfUpdated, HeapTupleUpdated, or HeapTupleBeingUpdated * (the last only possible if wait == false). * - * In the failure cases, the routine returns the tuple's t_ctid and t_xmax. - * If t_ctid is the same as tid, the tuple was deleted; if different, the - * tuple was updated, and t_ctid is the location of the replacement tuple. - * (t_xmax is needed to verify that the replacement tuple matches.) + * In the failure cases, the routine fills *hufd with the tuple's t_ctid, + * t_xmax, and t_cmax (the last only for HeapTupleSelfUpdated, since we + * cannot obtain cmax from a combocid generated by another transaction). + * See comments for struct HeapUpdateFailureData for additional info. */ HTSU_Result heap_delete(Relation relation, ItemPointer tid, - ItemPointer ctid, TransactionId *update_xmax, - CommandId cid, Snapshot crosscheck, bool wait) + CommandId cid, Snapshot crosscheck, bool wait, + HeapUpdateFailureData *hufd) { HTSU_Result result; TransactionId xid = GetCurrentTransactionId(); @@ -2533,8 +2532,12 @@ l1: result == HeapTupleUpdated || result == HeapTupleBeingUpdated); Assert(!(tp.t_data->t_infomask & HEAP_XMAX_INVALID)); - *ctid = tp.t_data->t_ctid; - *update_xmax = HeapTupleHeaderGetXmax(tp.t_data); + hufd->ctid = tp.t_data->t_ctid; + hufd->xmax = HeapTupleHeaderGetXmax(tp.t_data); + if (result == HeapTupleSelfUpdated) + hufd->cmax = HeapTupleHeaderGetCmax(tp.t_data); + else + hufd->cmax = 0; /* for lack of an InvalidCommandId value */ UnlockReleaseBuffer(buffer); if (have_tuple_lock) UnlockTuple(relation, &(tp.t_self), ExclusiveLock); @@ -2666,13 +2669,12 @@ void simple_heap_delete(Relation relation, ItemPointer tid) { HTSU_Result result; - ItemPointerData update_ctid; - TransactionId update_xmax; + HeapUpdateFailureData hufd; result = heap_delete(relation, tid, - &update_ctid, &update_xmax, GetCurrentCommandId(true), InvalidSnapshot, - true /* wait for commit */ ); + true /* wait for commit */, + &hufd); switch (result) { case HeapTupleSelfUpdated: @@ -2703,12 +2705,11 @@ simple_heap_delete(Relation relation, ItemPointer tid) * relation - table to be modified (caller must hold suitable lock) * otid - TID of old tuple to be replaced * newtup - newly constructed tuple data to store - * ctid - output parameter, used only for failure case (see below) - * update_xmax - output parameter, used only for failure case (see below) * cid - update command ID (used for visibility test, and stored into * cmax/cmin if successful) * crosscheck - if not InvalidSnapshot, also check old tuple against this * wait - true if should wait for any conflicting update to commit/abort + * hufd - output parameter, filled in failure cases (see below) * * Normal, successful return value is HeapTupleMayBeUpdated, which * actually means we *did* update it. Failure return codes are @@ -2721,15 +2722,15 @@ simple_heap_delete(Relation relation, ItemPointer tid) * update was done. However, any TOAST changes in the new tuple's * data are not reflected into *newtup. * - * In the failure cases, the routine returns the tuple's t_ctid and t_xmax. - * If t_ctid is the same as otid, the tuple was deleted; if different, the - * tuple was updated, and t_ctid is the location of the replacement tuple. - * (t_xmax is needed to verify that the replacement tuple matches.) + * In the failure cases, the routine fills *hufd with the tuple's t_ctid, + * t_xmax, and t_cmax (the last only for HeapTupleSelfUpdated, since we + * cannot obtain cmax from a combocid generated by another transaction). + * See comments for struct HeapUpdateFailureData for additional info. */ HTSU_Result heap_update(Relation relation, ItemPointer otid, HeapTuple newtup, - ItemPointer ctid, TransactionId *update_xmax, - CommandId cid, Snapshot crosscheck, bool wait) + CommandId cid, Snapshot crosscheck, bool wait, + HeapUpdateFailureData *hufd) { HTSU_Result result; TransactionId xid = GetCurrentTransactionId(); @@ -2908,8 +2909,12 @@ l2: result == HeapTupleUpdated || result == HeapTupleBeingUpdated); Assert(!(oldtup.t_data->t_infomask & HEAP_XMAX_INVALID)); - *ctid = oldtup.t_data->t_ctid; - *update_xmax = HeapTupleHeaderGetXmax(oldtup.t_data); + hufd->ctid = oldtup.t_data->t_ctid; + hufd->xmax = HeapTupleHeaderGetXmax(oldtup.t_data); + if (result == HeapTupleSelfUpdated) + hufd->cmax = HeapTupleHeaderGetCmax(oldtup.t_data); + else + hufd->cmax = 0; /* for lack of an InvalidCommandId value */ UnlockReleaseBuffer(buffer); if (have_tuple_lock) UnlockTuple(relation, &(oldtup.t_self), ExclusiveLock); @@ -3379,13 +3384,12 @@ void simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup) { HTSU_Result result; - ItemPointerData update_ctid; - TransactionId update_xmax; + HeapUpdateFailureData hufd; result = heap_update(relation, otid, tup, - &update_ctid, &update_xmax, GetCurrentCommandId(true), InvalidSnapshot, - true /* wait for commit */ ); + true /* wait for commit */, + &hufd); switch (result) { case HeapTupleSelfUpdated: @@ -3423,18 +3427,17 @@ simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup) * Output parameters: * *tuple: all fields filled in * *buffer: set to buffer holding tuple (pinned but not locked at exit) - * *ctid: set to tuple's t_ctid, but only in failure cases - * *update_xmax: set to tuple's xmax, but only in failure cases + * *hufd: filled in failure cases (see below) * * Function result may be: * HeapTupleMayBeUpdated: lock was successfully acquired * HeapTupleSelfUpdated: lock failed because tuple updated by self * HeapTupleUpdated: lock failed because tuple updated by other xact * - * In the failure cases, the routine returns the tuple's t_ctid and t_xmax. - * If t_ctid is the same as t_self, the tuple was deleted; if different, the - * tuple was updated, and t_ctid is the location of the replacement tuple. - * (t_xmax is needed to verify that the replacement tuple matches.) + * In the failure cases, the routine fills *hufd with the tuple's t_ctid, + * t_xmax, and t_cmax (the last only for HeapTupleSelfUpdated, since we + * cannot obtain cmax from a combocid generated by another transaction). + * See comments for struct HeapUpdateFailureData for additional info. * * * NOTES: because the shared-memory lock table is of finite size, but users @@ -3470,9 +3473,9 @@ simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup) * conflict for a tuple, we don't incur any extra overhead. */ HTSU_Result -heap_lock_tuple(Relation relation, HeapTuple tuple, Buffer *buffer, - ItemPointer ctid, TransactionId *update_xmax, - CommandId cid, LockTupleMode mode, bool nowait) +heap_lock_tuple(Relation relation, HeapTuple tuple, + CommandId cid, LockTupleMode mode, bool nowait, + Buffer *buffer, HeapUpdateFailureData *hufd) { HTSU_Result result; ItemPointer tid = &(tuple->t_self); @@ -3657,8 +3660,12 @@ l3: { Assert(result == HeapTupleSelfUpdated || result == HeapTupleUpdated); Assert(!(tuple->t_data->t_infomask & HEAP_XMAX_INVALID)); - *ctid = tuple->t_data->t_ctid; - *update_xmax = HeapTupleHeaderGetXmax(tuple->t_data); + hufd->ctid = tuple->t_data->t_ctid; + hufd->xmax = HeapTupleHeaderGetXmax(tuple->t_data); + if (result == HeapTupleSelfUpdated) + hufd->cmax = HeapTupleHeaderGetCmax(tuple->t_data); + else + hufd->cmax = 0; /* for lack of an InvalidCommandId value */ LockBuffer(*buffer, BUFFER_LOCK_UNLOCK); if (have_tuple_lock) UnlockTuple(relation, tid, tuple_lock_type); |