88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.90 2000/10/21 15:43:14 vadim Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.91 2000/10/24 09:56:07 vadim Exp $
1212 *
1313 *
1414 * INTERFACE ROUTINES
@@ -93,9 +93,13 @@ void heap_redo(XLogRecPtr lsn, XLogRecord *record);
9393void heap_undo (XLogRecPtr lsn , XLogRecord * record );
9494void heap_desc (char * buf , uint8 xl_info , char * rec );
9595
96+ XLogRecPtr log_heap_move (Relation reln , ItemPointerData from , HeapTuple newtup );
97+
9698/* comments are in heap_update */
9799static xl_heaptid _locked_tuple_ ;
98100static void _heap_unlock_tuple (void * data );
101+ static XLogRecPtr log_heap_update (Relation reln , ItemPointerData from ,
102+ HeapTuple newtup , bool move );
99103
100104static void HeapPageCleanup (Buffer buffer );
101105
@@ -1706,22 +1710,8 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
17061710#ifdef XLOG
17071711 /* XLOG stuff */
17081712 {
1709- xl_heap_update xlrec ;
1710- XLogRecPtr recptr ;
1711-
1712- xlrec .target .node = relation -> rd_node ;
1713- xlrec .target .cid = GetCurrentCommandId ();
1714- xlrec .target .tid = oldtup .t_self ;
1715- xlrec .newtid = newtup -> t_self ;
1716- xlrec .t_natts = newtup -> t_data -> t_natts ;
1717- xlrec .t_oid = newtup -> t_data -> t_oid ;
1718- xlrec .t_hoff = newtup -> t_data -> t_hoff ;
1719- xlrec .mask = newtup -> t_data -> t_infomask ;
1720-
1721- recptr = XLogInsert (RM_HEAP_ID , XLOG_HEAP_UPDATE ,
1722- (char * ) & xlrec , SizeOfHeapUpdate ,
1723- (char * ) newtup -> t_data + offsetof(HeapTupleHeaderData , t_bits ),
1724- newtup -> t_len - offsetof(HeapTupleHeaderData , t_bits ));
1713+ XLogRecPtr recptr = log_heap_update (relation ,
1714+ oldtup .t_self , newtup , false);
17251715
17261716 if (newbuf != buffer )
17271717 {
@@ -2019,6 +2009,54 @@ heap_restrpos(HeapScanDesc scan)
20192009
20202010#ifdef XLOG
20212011
2012+ static XLogRecPtr
2013+ log_heap_update (Relation reln , ItemPointerData from ,
2014+ HeapTuple newtup , bool move )
2015+ {
2016+ char tbuf [sizeof (xl_heap_update ) + 2 * sizeof (TransactionId )];
2017+ xl_heap_update * xlrec = (xl_heap_update * ) tbuf ;
2018+ int hsize = SizeOfHeapUpdate ;
2019+ XLogRecPtr recptr ;
2020+
2021+ xlrec -> target .node = reln -> rd_node ;
2022+ xlrec -> target .tid = from ;
2023+ xlrec -> newtid = newtup -> t_self ;
2024+ xlrec -> t_natts = newtup -> t_data -> t_natts ;
2025+ xlrec -> t_oid = newtup -> t_data -> t_oid ;
2026+ xlrec -> t_hoff = newtup -> t_data -> t_hoff ;
2027+ xlrec -> mask = newtup -> t_data -> t_infomask ;
2028+
2029+ if (move ) /* remember xmin & xmax */
2030+ {
2031+ TransactionId xmax ;
2032+
2033+ xlrec -> target .cid = (CommandId ) newtup -> t_data -> t_xmin ;
2034+ if (newtup -> t_data -> t_infomask & HEAP_XMAX_INVALID ||
2035+ newtup -> t_data -> t_infomask & HEAP_MARKED_FOR_UPDATE )
2036+ xmax = InvalidTransactionId ;
2037+ else
2038+ xmax = newtup -> t_data -> t_xmax ;
2039+ memcpy (tbuf + hsize , & xmax , sizeof (TransactionId ));
2040+ hsize += sizeof (TransactionId );
2041+ }
2042+ else
2043+ xlrec -> target .cid = GetCurrentCommandId ();
2044+
2045+ recptr = XLogInsert (RM_HEAP_ID ,
2046+ (move ) ? XLOG_HEAP_MOVE : XLOG_HEAP_UPDATE ,
2047+ tbuf , hsize ,
2048+ (char * ) newtup -> t_data + offsetof(HeapTupleHeaderData , t_bits ),
2049+ newtup -> t_len - offsetof(HeapTupleHeaderData , t_bits ));
2050+
2051+ return (recptr );
2052+ }
2053+
2054+ XLogRecPtr
2055+ log_heap_move (Relation reln , ItemPointerData from , HeapTuple newtup )
2056+ {
2057+ return (log_heap_update (reln , from , newtup , true));
2058+ }
2059+
20222060static void
20232061heap_xlog_delete (bool redo , XLogRecPtr lsn , XLogRecord * record )
20242062{
@@ -2159,6 +2197,7 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
21592197 htup -> t_hoff = xlrec -> t_hoff ;
21602198 htup -> t_xmin = record -> xl_xid ;
21612199 htup -> t_cmin = xlrec -> target .cid ;
2200+ htup -> t_xmax = htup -> t_cmax = 0 ;
21622201 htup -> t_infomask = HEAP_XMAX_INVALID | HEAP_XMIN_COMMITTED | xlrec -> mask ;
21632202
21642203 offnum = PageAddItem (page , (Item )htup , newlen ,
@@ -2210,8 +2249,11 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
22102249
22112250}
22122251
2252+ /*
2253+ * Handles UPDATE & MOVE
2254+ */
22132255static void
2214- heap_xlog_update (bool redo , XLogRecPtr lsn , XLogRecord * record )
2256+ heap_xlog_update (bool redo , XLogRecPtr lsn , XLogRecord * record , bool move )
22152257{
22162258 xl_heap_update * xlrec = (xl_heap_update * ) XLogRecGetData (record );
22172259 Relation reln = XLogOpenRelation (redo , RM_HEAP_ID , xlrec -> target .node );
@@ -2282,26 +2324,46 @@ heap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record)
22822324
22832325 if (redo )
22842326 {
2285- htup -> t_xmax = record -> xl_xid ;
2286- htup -> t_cmax = xlrec -> target .cid ;
2287- htup -> t_infomask &= ~(HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE );
2288- htup -> t_infomask |= HEAP_XMAX_COMMITTED ;
2327+ if (move )
2328+ {
2329+ TransactionIdStore (record -> xl_xid , (TransactionId * ) & (htup -> t_cmin ));
2330+ htup -> t_infomask &=
2331+ ~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_IN );
2332+ htup -> t_infomask |= HEAP_MOVED_OFF ;
2333+ }
2334+ else
2335+ {
2336+ htup -> t_xmax = record -> xl_xid ;
2337+ htup -> t_cmax = xlrec -> target .cid ;
2338+ htup -> t_infomask &= ~(HEAP_XMAX_COMMITTED |
2339+ HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE );
2340+ }
22892341 PageSetLSN (page , lsn );
22902342 PageSetSUI (page , ThisStartUpID );
22912343 UnlockAndWriteBuffer (buffer );
22922344 goto newt ;
22932345 }
22942346
22952347 /* undo... is it our tuple ? */
2296- if (htup -> t_xmax != record -> xl_xid || htup -> t_cmax != xlrec -> target .cid )
2348+ if ((! move && (htup -> t_xmax != record -> xl_xid ||
2349+ htup -> t_cmax != xlrec -> target .cid )) ||
2350+ xlrec -> target .cid != (CommandId ) htup -> t_xmin ||
2351+ htup -> t_cmin != (CommandId ) record -> xl_xid )
22972352 {
22982353 if (!InRecovery )
22992354 elog (STOP , "heap_update_undo: invalid old tuple in rollback" );
23002355 UnlockAndReleaseBuffer (buffer );
23012356 }
23022357 else /* undo */
23032358 {
2304- htup -> t_infomask |= HEAP_XMAX_INVALID ;
2359+ if (move )
2360+ {
2361+ htup -> t_infomask &= ~(HEAP_XMIN_INVALID |
2362+ HEAP_MOVED_IN | HEAP_MOVED_OFF );
2363+ htup -> t_infomask |= HEAP_XMIN_COMMITTED ;
2364+ }
2365+ else
2366+ htup -> t_infomask |= HEAP_XMAX_INVALID ;
23052367 UnlockAndWriteBuffer (buffer );
23062368 }
23072369
@@ -2329,25 +2391,45 @@ newt:;
23292391
23302392 if (redo )
23312393 {
2332- char tbuf [MaxTupleSize ];
2333- uint32 newlen = record -> xl_len - SizeOfHeapUpdate ;
2394+ char tbuf [MaxTupleSize ];
2395+ int hsize ;
2396+ uint32 newlen ;
23342397
23352398 if (XLByteLE (lsn , PageGetLSN (page ))) /* changes are applied */
23362399 {
23372400 UnlockAndReleaseBuffer (buffer );
23382401 return ;
23392402 }
23402403
2404+ hsize = SizeOfHeapUpdate ;
2405+ if (move )
2406+ hsize += sizeof (TransactionId );
2407+ newlen = record -> xl_len - hsize ;
2408+
23412409 htup = (HeapTupleHeader ) tbuf ;
23422410 memcpy (tbuf + offsetof(HeapTupleHeaderData , t_bits ),
2343- (char * )xlrec + SizeOfHeapUpdate , newlen );
2411+ (char * )xlrec + hsize , newlen );
23442412 newlen += offsetof(HeapTupleHeaderData , t_bits );
23452413 htup -> t_oid = xlrec -> t_oid ;
23462414 htup -> t_natts = xlrec -> t_natts ;
23472415 htup -> t_hoff = xlrec -> t_hoff ;
2348- htup -> t_xmin = record -> xl_xid ;
2349- htup -> t_cmin = xlrec -> target .cid ;
2350- htup -> t_infomask = HEAP_XMAX_INVALID | HEAP_XMIN_COMMITTED | xlrec -> mask ;
2416+ if (move )
2417+ {
2418+ htup -> t_xmin = (TransactionId ) xlrec -> target .cid ;
2419+ memcpy (& (htup -> t_xmax ),
2420+ (char * )xlrec + SizeOfHeapUpdate , sizeof (TransactionId ));
2421+ htup -> t_infomask = xlrec -> mask ;
2422+ htup -> t_infomask &= ~(HEAP_XMIN_COMMITTED |
2423+ HEAP_XMIN_INVALID | HEAP_MOVED_OFF );
2424+ htup -> t_infomask |= HEAP_MOVED_IN ;
2425+ }
2426+ else
2427+ {
2428+ htup -> t_xmin = record -> xl_xid ;
2429+ htup -> t_cmin = xlrec -> target .cid ;
2430+ htup -> t_xmax = htup -> t_cmax = 0 ;
2431+ htup -> t_infomask = HEAP_XMAX_INVALID | xlrec -> mask ;
2432+ }
23512433
23522434 offnum = PageAddItem (page , (Item )htup , newlen ,
23532435 ItemPointerGetOffsetNumber (& (xlrec -> newtid )),
@@ -2385,7 +2467,10 @@ newt:;
23852467
23862468 /* is it our tuple ? */
23872469 Assert (PageGetSUI (page ) == ThisStartUpID );
2388- if (htup -> t_xmin != record -> xl_xid || htup -> t_cmin != xlrec -> target .cid )
2470+ if ((! move && (htup -> t_xmin != record -> xl_xid ||
2471+ htup -> t_cmin != xlrec -> target .cid )) ||
2472+ xlrec -> target .cid != (CommandId ) htup -> t_xmin ||
2473+ htup -> t_cmin != (CommandId ) record -> xl_xid )
23892474 {
23902475 if (!InRecovery )
23912476 elog (STOP , "heap_update_undo: invalid new tuple in rollback" );
@@ -2448,11 +2533,9 @@ void heap_redo(XLogRecPtr lsn, XLogRecord *record)
24482533 else if (info == XLOG_HEAP_DELETE )
24492534 heap_xlog_delete (true, lsn , record );
24502535 else if (info == XLOG_HEAP_UPDATE )
2451- heap_xlog_update (true, lsn , record );
2452- #ifdef NOT_USED
2536+ heap_xlog_update (true, lsn , record , false);
24532537 else if (info == XLOG_HEAP_MOVE )
2454- heap_xlog_move (true , lsn , record );
2455- #endif
2538+ heap_xlog_update (true, lsn , record , true);
24562539 else
24572540 elog (STOP , "heap_redo: unknown op code %u" , info );
24582541}
@@ -2466,11 +2549,9 @@ void heap_undo(XLogRecPtr lsn, XLogRecord *record)
24662549 else if (info == XLOG_HEAP_DELETE )
24672550 heap_xlog_delete (false, lsn , record );
24682551 else if (info == XLOG_HEAP_UPDATE )
2469- heap_xlog_update (false, lsn , record );
2470- #ifdef NOT_USED
2552+ heap_xlog_update (false, lsn , record , false);
24712553 else if (info == XLOG_HEAP_MOVE )
2472- heap_xlog_move (false , lsn , record );
2473- #endif
2554+ heap_xlog_update (false, lsn , record , true);
24742555 else
24752556 elog (STOP , "heap_undo: unknown op code %u" , info );
24762557}
@@ -2509,19 +2590,13 @@ heap_desc(char *buf, uint8 xl_info, char* rec)
25092590 strcat (buf , "delete: " );
25102591 out_target (buf , & (xlrec -> target ));
25112592 }
2512- else if (info == XLOG_HEAP_UPDATE )
2593+ else if (info == XLOG_HEAP_UPDATE || info == XLOG_HEAP_MOVE )
25132594 {
25142595 xl_heap_update * xlrec = (xl_heap_update * ) rec ;
2515- strcat (buf , "update: " );
2516- out_target (buf , & (xlrec -> target ));
2517- sprintf (buf + strlen (buf ), "; new %u/%u" ,
2518- ItemPointerGetBlockNumber (& (xlrec -> newtid )),
2519- ItemPointerGetOffsetNumber (& (xlrec -> newtid )));
2520- }
2521- else if (info == XLOG_HEAP_MOVE )
2522- {
2523- xl_heap_move * xlrec = (xl_heap_move * ) rec ;
2524- strcat (buf , "move: " );
2596+ if (info == XLOG_HEAP_UPDATE )
2597+ strcat (buf , "update: " );
2598+ else
2599+ strcat (buf , "move: " );
25252600 out_target (buf , & (xlrec -> target ));
25262601 sprintf (buf + strlen (buf ), "; new %u/%u" ,
25272602 ItemPointerGetBlockNumber (& (xlrec -> newtid )),
0 commit comments