88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.74 2000/07/02 22:00:27 momjian Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.75 2000/07/03 02:54:15 vadim Exp $
1212 *
1313 *
1414 * INTERFACE ROUTINES
@@ -1271,10 +1271,9 @@ heap_get_latest_tid(Relation relation,
12711271Oid
12721272heap_insert (Relation relation ,HeapTuple tup )
12731273{
1274- /* ----------------
1275- *increment access statistics
1276- * ----------------
1277- */
1274+ Buffer buffer ;
1275+
1276+ /* increment access statistics */
12781277tup -> tableOid = relation -> rd_id ;
12791278IncrHeapAccessStat (local_insert );
12801279IncrHeapAccessStat (global_insert );
@@ -1300,15 +1299,20 @@ heap_insert(Relation relation, HeapTuple tup)
13001299tup -> t_data -> t_infomask &= ~(HEAP_XACT_MASK );
13011300tup -> t_data -> t_infomask |=HEAP_XMAX_INVALID ;
13021301
1303- RelationPutHeapTupleAtEnd (relation ,tup );
1302+ /* Find buffer for this tuple */
1303+ buffer = RelationGetBufferForTuple (relation ,tup -> t_len ,InvalidBuffer );
1304+
1305+ /* NO ELOG(ERROR) from here till changes are logged */
1306+ RelationPutHeapTuple (relation ,buffer ,tup );
13041307
13051308#ifdef XLOG
13061309/* XLOG stuff */
13071310{
13081311xl_heap_insert xlrec ;
13091312xlrec .itid .dbId = relation -> rd_lockInfo .lockRelId .dbId ;
13101313xlrec .itid .relId = relation -> rd_lockInfo .lockRelId .relId ;
1311- XXX xlrec .itid .tid = tp .t_self ;
1314+ xlrec .itid .cid = GetCurrentCommandId ();
1315+ xlrec .itid .tid = tup -> t_self ;
13121316xlrec .t_natts = tup -> t_data -> t_natts ;
13131317xlrec .t_oid = tup -> t_data -> t_oid ;
13141318xlrec .t_hoff = tup -> t_data -> t_hoff ;
@@ -1319,10 +1323,14 @@ XXXxlrec.itid.tid = tp.t_self;
13191323(char * )tup -> t_data + offsetof(HeapTupleHeaderData ,tbits ),
13201324tup -> t_len - offsetof(HeapTupleHeaderData ,tbits ));
13211325
1322- dp -> pd_lsn = recptr ;
1326+ ((PageHeader )BufferGetPage (buffer ))-> pd_lsn = recptr ;
1327+ ((PageHeader )BufferGetPage (buffer ))-> pd_sui = ThisStartUpID ;
13231328}
13241329#endif
13251330
1331+ LockBuffer (buffer ,BUFFER_LOCK_UNLOCK );
1332+ WriteBuffer (buffer );
1333+
13261334if (IsSystemRelationName (RelationGetRelationName (relation )))
13271335RelationMark4RollbackHeapTuple (relation ,tup );
13281336
@@ -1417,11 +1425,13 @@ heap_delete(Relation relation, ItemPointer tid, ItemPointer ctid)
14171425xl_heap_delete xlrec ;
14181426xlrec .dtid .dbId = relation -> rd_lockInfo .lockRelId .dbId ;
14191427xlrec .dtid .relId = relation -> rd_lockInfo .lockRelId .relId ;
1428+ xlrec .dtid .cid = GetCurrentCommandId ();
14201429xlrec .dtid .tid = tp .t_self ;
14211430XLogRecPtr recptr = XLogInsert (RM_HEAP_ID ,XLOG_HEAP_DELETE ,
14221431(char * )xlrec ,sizeof (xlrec ),NULL ,0 );
14231432
14241433dp -> pd_lsn = recptr ;
1434+ dp -> pd_sui = ThisStartUpID ;
14251435}
14261436#endif
14271437
@@ -1451,7 +1461,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
14511461ItemId lp ;
14521462HeapTupleData oldtup ;
14531463PageHeader dp ;
1454- Buffer buffer ;
1464+ Buffer buffer , newbuf ;
14551465int result ;
14561466
14571467newtup -> tableOid = relation -> rd_id ;
@@ -1531,43 +1541,65 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
15311541newtup -> t_data -> t_infomask &= ~(HEAP_XACT_MASK );
15321542newtup -> t_data -> t_infomask |= (HEAP_XMAX_INVALID |HEAP_UPDATED );
15331543
1534- /* logically delete old item */
1544+ /* Find buffer for new tuple */
1545+
1546+ if ((unsigned )MAXALIGN (newtup -> t_len ) <=PageGetFreeSpace ((Page )dp ))
1547+ newbuf = buffer ;
1548+ else
1549+ newbuf = RelationGetBufferForTuple (relation ,newtup -> t_len ,buffer );
1550+
1551+ /* NO ELOG(ERROR) from here till changes are logged */
1552+
1553+ /* insert new tuple */
1554+ RelationPutHeapTuple (relation ,newbuf ,newtup );
1555+
1556+ /* logically delete old tuple */
15351557TransactionIdStore (GetCurrentTransactionId (),& (oldtup .t_data -> t_xmax ));
15361558oldtup .t_data -> t_cmax = GetCurrentCommandId ();
15371559oldtup .t_data -> t_infomask &= ~(HEAP_XMAX_COMMITTED |
15381560HEAP_XMAX_INVALID |HEAP_MARKED_FOR_UPDATE );
15391561
1540- /* insert new item */
1541- if ((unsigned )MAXALIGN (newtup -> t_len ) <=PageGetFreeSpace ((Page )dp ))
1542- RelationPutHeapTuple (relation ,buffer ,newtup );
1543- else
1562+ /* record address of new tuple in t_ctid of old one */
1563+ oldtup .t_data -> t_ctid = newtup -> t_self ;
1564+
1565+ #ifdef XLOG
1566+ /* XLOG stuff */
15441567{
1568+ xl_heap_update xlrec ;
1569+ xlrec .dtid .dbId = relation -> rd_lockInfo .lockRelId .dbId ;
1570+ xlrec .dtid .relId = relation -> rd_lockInfo .lockRelId .relId ;
1571+ xlrec .dtid .cid = GetCurrentCommandId ();
1572+ xlrec .itid .tid = newtup -> t_self ;
1573+ xlrec .t_natts = newtup -> t_data -> t_natts ;
1574+ xlrec .t_hoff = newtup -> t_data -> t_hoff ;
1575+ xlrec .mask = newtup -> t_data -> t_infomask ;
1576+
1577+ XLogRecPtr recptr = XLogInsert (RM_HEAP_ID ,XLOG_HEAP_UPDATE ,
1578+ (char * )xlrec ,sizeof (xlrec ),
1579+ (char * )newtup -> t_data + offsetof(HeapTupleHeaderData ,tbits ),
1580+ newtup -> t_len - offsetof(HeapTupleHeaderData ,tbits ));
15451581
1546- /*
1547- * New item won't fit on same page as old item, have to look for a
1548- * new place to put it. Note that we have to unlock current buffer
1549- * context - not good but RelationPutHeapTupleAtEnd uses extend
1550- * lock.
1551- */
1552- LockBuffer (buffer ,BUFFER_LOCK_UNLOCK );
1553- RelationPutHeapTupleAtEnd (relation ,newtup );
1554- LockBuffer (buffer ,BUFFER_LOCK_EXCLUSIVE );
1582+ if (newbuf != buffer )
1583+ {
1584+ ((PageHeader )BufferGetPage (newbuf ))-> pd_lsn = recptr ;
1585+ ((PageHeader )BufferGetPage (newbuf ))-> pd_sui = ThisStartUpID ;
1586+ }
1587+ ((PageHeader )BufferGetPage (buffer ))-> pd_lsn = recptr ;
1588+ ((PageHeader )BufferGetPage (buffer ))-> pd_sui = ThisStartUpID ;
15551589}
1556- /* mark for rollback caches */
1557- RelationMark4RollbackHeapTuple (relation ,newtup );
1558-
1559- /*
1560- * New item in place, now record address of new tuple in t_ctid of old
1561- * one.
1562- */
1563- oldtup .t_data -> t_ctid = newtup -> t_self ;
1590+ #endif
15641591
1592+ if (newbuf != buffer )
1593+ {
1594+ LockBuffer (newbuf ,BUFFER_LOCK_UNLOCK );
1595+ WriteBuffer (newbuf );
1596+ }
15651597LockBuffer (buffer ,BUFFER_LOCK_UNLOCK );
1598+ WriteBuffer (buffer );
15661599
15671600/* invalidate caches */
15681601RelationInvalidateHeapTuple (relation ,& oldtup );
1569-
1570- WriteBuffer (buffer );
1602+ RelationMark4RollbackHeapTuple (relation ,newtup );
15711603
15721604return HeapTupleMayBeUpdated ;
15731605}
@@ -1648,6 +1680,14 @@ heap_mark4update(Relation relation, HeapTuple tuple, Buffer *buffer)
16481680return result ;
16491681}
16501682
1683+ #ifdef XLOG
1684+ /*
1685+ * XLOG stuff: no logging is required as long as we have no
1686+ * savepoints. For savepoints private log could be used...
1687+ */
1688+ ((PageHeader )BufferGetPage (* buffer ))-> pd_sui = ThisStartUpID ;
1689+ #endif
1690+
16511691/* store transaction information of xact marking the tuple */
16521692TransactionIdStore (GetCurrentTransactionId (),& (tuple -> t_data -> t_xmax ));
16531693tuple -> t_data -> t_cmax = GetCurrentCommandId ();