77 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
88 * Portions Copyright (c) 1994, Regents of the University of California
99 *
10- * $Id: htup.h,v 1.54 2002/06/20 20:29:43 momjian Exp $
10+ * $Id: htup.h,v 1.55 2002/07/02 05:46:14 momjian Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
5757 * Also note that we omit the nulls bitmap if t_infomask shows that there
5858 * are no nulls in the tuple.
5959 */
60+ /*
61+ ** We store five "virtual" fields Xmin, Cmin, Xmax, Cmax, and Xvac
62+ ** in three physical fields t_xmin, t_cid, t_xmax:
63+ ** CommandId Cmin;insert CID stamp
64+ ** CommandId Cmax;delete CommandId stamp
65+ ** TransactionId Xmin;insert XID stamp
66+ ** TransactionId Xmax;delete XID stamp
67+ ** TransactionId Xvac;used by VACCUUM
68+ **
69+ ** This assumes, that a CommandId can be stored in a TransactionId.
70+ */
6071typedef struct HeapTupleHeaderData
6172{
6273Oid t_oid ;/* OID of this tuple -- 4 bytes */
6374
64- CommandId t_cmin ;/* insert CID stamp -- 4 bytes each */
65- CommandId t_cmax ;/* delete CommandId stamp */
66-
67- TransactionId t_xmin ;/* insert XID stamp -- 4 bytes each */
68- TransactionId t_xmax ;/* delete XID stamp */
75+ TransactionId t_xmin ;/* Xmin -- 4 bytes each */
76+ TransactionId t_cid ;/* Cmin, Cmax, Xvac */
77+ TransactionId t_xmax ;/* Xmax, Cmax */
6978
7079ItemPointerData t_ctid ;/* current TID of this or newer tuple */
7180
@@ -75,7 +84,7 @@ typedef struct HeapTupleHeaderData
7584
7685uint8 t_hoff ;/* sizeof header incl. bitmap, padding */
7786
78- /* ^ -31 bytes - ^ */
87+ /* ^ -27 bytes - ^ */
7988
8089bits8 t_bits [1 ];/* bitmap of NULLs -- VARIABLE LENGTH */
8190
@@ -96,6 +105,8 @@ typedef HeapTupleHeaderData *HeapTupleHeader;
96105 * attribute(s) */
97106#define HEAP_HASEXTENDED 0x000C/* the two above combined */
98107
108+ #define HEAP_XMIN_IS_XMAX 0x0040/* created and deleted in the */
109+ /* same transaction */
99110#define HEAP_XMAX_UNLOGGED 0x0080/* to lock tuple for update */
100111/* without logging */
101112#define HEAP_XMIN_COMMITTED 0x0100/* t_xmin committed */
@@ -108,6 +119,7 @@ typedef HeapTupleHeaderData *HeapTupleHeader;
108119 * vacuum */
109120#define HEAP_MOVED_IN 0x8000/* moved from another place by
110121 * vacuum */
122+ #define HEAP_MOVED (HEAP_MOVED_OFF | HEAP_MOVED_IN)
111123
112124#define HEAP_XACT_MASK 0xFFF0/* visibility-related bits */
113125
@@ -116,53 +128,100 @@ typedef HeapTupleHeaderData *HeapTupleHeader;
116128/* HeapTupleHeader accessor macros */
117129
118130#define HeapTupleHeaderGetXmin (tup ) \
119- ((tup)->t_xmin)
131+ ( \
132+ (tup)->t_xmin \
133+ )
120134
121135#define HeapTupleHeaderGetXmax (tup ) \
122- ((tup)->t_xmax)
136+ ( \
137+ ((tup)->t_infomask & HEAP_XMIN_IS_XMAX) ? \
138+ (tup)->t_xmin \
139+ : \
140+ (tup)->t_xmax \
141+ )
123142
124- /* no AssertMacro, because this is read as a system-defined attributealso */
143+ /* no AssertMacro, because this is read as a system-defined attribute */
125144#define HeapTupleHeaderGetCmin (tup ) \
126145( \
127- (tup)->t_cmin \
146+ ((tup)->t_infomask & HEAP_MOVED) ? \
147+ FirstCommandId \
148+ : \
149+ ( \
150+ ((tup)->t_infomask & (HEAP_XMIN_IS_XMAX | HEAP_XMAX_INVALID)) ? \
151+ (CommandId) (tup)->t_cid \
152+ : \
153+ FirstCommandId \
154+ ) \
128155)
129156
130157#define HeapTupleHeaderGetCmax (tup ) \
131- ((tup)->t_cmax)
158+ ( \
159+ ((tup)->t_infomask & HEAP_MOVED) ? \
160+ FirstCommandId \
161+ : \
162+ ( \
163+ ((tup)->t_infomask & (HEAP_XMIN_IS_XMAX | HEAP_XMAX_INVALID)) ? \
164+ (CommandId) (tup)->t_xmax \
165+ : \
166+ (CommandId) (tup)->t_cid \
167+ ) \
168+ )
132169
133170#define HeapTupleHeaderGetXvac (tup ) \
134171( \
135- AssertMacro((tup)->t_infomask &(HEAP_MOVED_IN | HEAP_MOVED_OFF) ), \
136- (TransactionId) ( tup)->t_cmin \
172+ AssertMacro((tup)->t_infomask &HEAP_MOVED ), \
173+ (tup)->t_cid \
137174)
138175
139176
140177#define HeapTupleHeaderSetXmin (tup ,xid ) \
141- (TransactionIdStore((xid), &(tup)->t_xmin))
178+ ( \
179+ TransactionIdStore((xid), &(tup)->t_xmin) \
180+ )
142181
143182#define HeapTupleHeaderSetXminInvalid (tup ) \
144- (StoreInvalidTransactionId(&(tup)->t_xmin))
183+ do { \
184+ (tup)->t_infomask &= ~HEAP_XMIN_IS_XMAX; \
185+ StoreInvalidTransactionId(&(tup)->t_xmin); \
186+ } while (0)
145187
146188#define HeapTupleHeaderSetXmax (tup ,xid ) \
147- (TransactionIdStore((xid), &(tup)->t_xmax))
189+ do { \
190+ if (TransactionIdEquals((tup)->t_xmin, (xid))) \
191+ (tup)->t_infomask |= HEAP_XMIN_IS_XMAX; \
192+ else \
193+ { \
194+ (tup)->t_infomask &= ~HEAP_XMIN_IS_XMAX; \
195+ TransactionIdStore((xid), &(tup)->t_xmax); \
196+ } \
197+ } while (0)
148198
149199#define HeapTupleHeaderSetXmaxInvalid (tup ) \
150- (StoreInvalidTransactionId(&(tup)->t_xmax))
200+ do { \
201+ (tup)->t_infomask &= ~HEAP_XMIN_IS_XMAX; \
202+ StoreInvalidTransactionId(&(tup)->t_xmax); \
203+ } while (0)
151204
152205#define HeapTupleHeaderSetCmin (tup ,cid ) \
153- ( \
154- AssertMacro (!((tup)->t_infomask &(HEAP_MOVED_IN | HEAP_MOVED_OFF))), \
155- (tup)->t_cmin = (cid) \
156- )
206+ do { \
207+ Assert (!((tup)->t_infomask &HEAP_MOVED)); \
208+ TransactionIdStore((TransactionId) (cid), &(tup)->t_cid); \
209+ } while (0 )
157210
158211#define HeapTupleHeaderSetCmax (tup ,cid ) \
159- ((tup)->t_cmax = (cid))
212+ do { \
213+ Assert(!((tup)->t_infomask & HEAP_MOVED)); \
214+ if ((tup)->t_infomask & HEAP_XMIN_IS_XMAX) \
215+ TransactionIdStore((TransactionId) (cid), &(tup)->t_xmax); \
216+ else \
217+ TransactionIdStore((TransactionId) (cid), &(tup)->t_cid); \
218+ } while (0)
160219
161220#define HeapTupleHeaderSetXvac (tup ,xid ) \
162- ( \
163- AssertMacro ((tup)->t_infomask &(HEAP_MOVED_IN | HEAP_MOVED_OFF)), \
164- TransactionIdStore((xid),(TransactionId *) &(( tup)->t_cmin)) \
165- )
221+ do { \
222+ Assert ((tup)->t_infomask &HEAP_MOVED); \
223+ TransactionIdStore((xid),&( tup)->t_cid); \
224+ } while (0 )
166225
167226
168227/*