*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.105 2000/12/30 15:19:54 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.106 2001/01/07 22:14:31 tgl Exp $
*
*
* INTERFACE ROUTINES
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
WriteBuffer(buffer);
- if (IsSystemRelationName(RelationGetRelationName(relation)))
- RelationMark4RollbackHeapTuple(relation, tup);
+ /*
+ * If tuple is cachable, mark it for rollback from the caches
+ * in case we abort. Note it is OK to do this after WriteBuffer
+ * releases the buffer, because the "tup" data structure is all
+ * in local memory, not in the shared buffer.
+ */
+ RelationMark4RollbackHeapTuple(relation, tup);
return tup->t_data->t_oid;
}
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
- /* invalidate caches */
+ /*
+ * Mark tuple for invalidation from system caches at next command boundary.
+ * We have to do this before WriteBuffer because we need to look at the
+ * contents of the tuple, so we need to hold our refcount on the buffer.
+ */
RelationInvalidateHeapTuple(relation, &tp);
WriteBuffer(buffer);
buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(otid));
if (!BufferIsValid(buffer))
- elog(ERROR, "amreplace: failed ReadBuffer");
+ elog(ERROR, "heap_update: failed ReadBuffer");
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
dp = (PageHeader) BufferGetPage(buffer);
oldtup.t_data = (HeapTupleHeader) PageGetItem(dp, lp);
oldtup.t_len = ItemIdGetLength(lp);
oldtup.t_self = *otid;
+ /*
+ * Note: beyond this point, use oldtup not otid to refer to old tuple.
+ * otid may very well point at newtup->t_self, which we will overwrite
+ * with the new tuple's location, so there's great risk of confusion
+ * if we use otid anymore.
+ */
l2:
result = HeapTupleSatisfiesUpdate(&oldtup);
* after postmaster startup.
*/
_locked_tuple_.node = relation->rd_node;
- _locked_tuple_.tid = *otid;
+ _locked_tuple_.tid = oldtup.t_self;
XactPushRollback(_heap_unlock_tuple, (void*) &_locked_tuple_);
TransactionIdStore(GetCurrentTransactionId(), &(oldtup.t_data->t_xmax));
END_CRIT_CODE;
if (newbuf != buffer)
- {
LockBuffer(newbuf, BUFFER_LOCK_UNLOCK);
- WriteBuffer(newbuf);
- }
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
- WriteBuffer(buffer);
- /* invalidate caches */
+ /*
+ * Mark old tuple for invalidation from system caches at next command
+ * boundary. We have to do this before WriteBuffer because we need to
+ * look at the contents of the tuple, so we need to hold our refcount.
+ */
RelationInvalidateHeapTuple(relation, &oldtup);
+
+ if (newbuf != buffer)
+ WriteBuffer(newbuf);
+ WriteBuffer(buffer);
+
+ /*
+ * If new tuple is cachable, mark it for rollback from the caches
+ * in case we abort. Note it is OK to do this after WriteBuffer
+ * releases the buffer, because the "newtup" data structure is all
+ * in local memory, not in the shared buffer.
+ */
RelationMark4RollbackHeapTuple(relation, newtup);
return HeapTupleMayBeUpdated;