diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 4020906..2dca6a9 100644 *** a/src/backend/access/heap/heapam.c --- b/src/backend/access/heap/heapam.c *************** simple_heap_insert(Relation relation, He *** 2041,2050 **** * 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.) */ HTSU_Result heap_delete(Relation relation, ItemPointer tid, --- 2041,2055 ---- * HeapTupleSelfUpdated, HeapTupleUpdated, or HeapTupleBeingUpdated * (the last only possible if wait == false). * ! * In case of a failure, the reason can be determined from the tuple's ! * t_ctid and t_xmax values returned in ctid and update_xmax. ! * If ctid is the same as otid and update_xmax is InvalidTransactionId the ! * tupe was neither updated nor deleted, but is invisible to the crosscheck ! * snapshot. If ctid equals otid and update_xmax is a valid transactionid, ! * the tuple was deleted by the transaction in update_xmax. ! * Otherwise, if ctid differes from otid, the tuple was updated and ctid is ! * the location of the replacement tuple; update_xmax should in this case be ! * used to verify that the replacement tuple matches. */ HTSU_Result heap_delete(Relation relation, ItemPointer tid, *************** l1: *** 2175,2191 **** { /* Perform additional check for transaction-snapshot mode RI updates */ if (!HeapTupleSatisfiesVisibility(&tp, crosscheck, buffer)) result = HeapTupleUpdated; } if (result != HeapTupleMayBeUpdated) { Assert(result == HeapTupleSelfUpdated || 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); UnlockReleaseBuffer(buffer); if (have_tuple_lock) UnlockTuple(relation, &(tp.t_self), ExclusiveLock); --- 2180,2203 ---- { /* Perform additional check for transaction-snapshot mode RI updates */ if (!HeapTupleSatisfiesVisibility(&tp, crosscheck, buffer)) + { result = HeapTupleUpdated; + *update_xmax = InvalidTransactionId; + } + } + else if (result != HeapTupleMayBeUpdated) + { + Assert(!(tp.t_data->t_infomask & HEAP_XMAX_INVALID)); + *update_xmax = HeapTupleHeaderGetXmax(tp.t_data); } + if (result != HeapTupleMayBeUpdated) { Assert(result == HeapTupleSelfUpdated || result == HeapTupleUpdated || result == HeapTupleBeingUpdated); *ctid = tp.t_data->t_ctid; UnlockReleaseBuffer(buffer); if (have_tuple_lock) UnlockTuple(relation, &(tp.t_self), ExclusiveLock); *************** simple_heap_delete(Relation relation, It *** 2363,2372 **** * 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.) */ HTSU_Result heap_update(Relation relation, ItemPointer otid, HeapTuple newtup, --- 2375,2389 ---- * update was done. However, any TOAST changes in the new tuple's * data are not reflected into *newtup. * ! * In case of a failure, the reason can be determined from the tuple's ! * t_ctid and t_xmax values returned in ctid and update_xmax. ! * If ctid is the same as otid and update_xmax is InvalidTransactionId the ! * tupe was neither updated nor deleted, but is invisible to the crosscheck ! * snapshot. If ctid equals otid and update_xmax is a valid transactionid, ! * the tuple was deleted by the transaction in update_xmax. ! * Otherwise, if ctid differes from otid, the tuple was updated and ctid is ! * the location of the replacement tuple; update_xmax should in this case be ! * used to verify that the replacement tuple matches. */ HTSU_Result heap_update(Relation relation, ItemPointer otid, HeapTuple newtup, *************** l2: *** 2527,2533 **** --- 2544,2558 ---- { /* Perform additional check for transaction-snapshot mode RI updates */ if (!HeapTupleSatisfiesVisibility(&oldtup, crosscheck, buffer)) + { result = HeapTupleUpdated; + *update_xmax = InvalidTransactionId; + } + } + else if (result != HeapTupleMayBeUpdated) + { + Assert(!(oldtup.t_data->t_infomask & HEAP_XMAX_INVALID)); + *update_xmax = HeapTupleHeaderGetXmax(oldtup.t_data); } if (result != HeapTupleMayBeUpdated) *************** l2: *** 2535,2543 **** Assert(result == HeapTupleSelfUpdated || 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); UnlockReleaseBuffer(buffer); if (have_tuple_lock) UnlockTuple(relation, &(oldtup.t_self), ExclusiveLock); --- 2560,2566 ----