1 /*-------------------------------------------------------------------------
4 * POSTGRES heap tuple definitions.
7 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
10 * $Id: htup.h,v 1.61 2002/09/26 22:46:29 tgl Exp $
12 *-------------------------------------------------------------------------
17 #include "storage/bufpage.h"
18 #include "storage/relfilenode.h"
19 #include "access/transam.h"
23 * MaxTupleAttributeNumber limits the number of (user) columns in a tuple.
24 * The key limit on this value is that the size of the fixed overhead for
25 * a tuple, plus the size of the null-values bitmap (at 1 bit per column),
26 * plus MAXALIGN alignment, must fit into t_hoff which is uint8. On most
27 * machines the upper limit without making t_hoff wider would be a little
28 * over 1700. We use round numbers here and for MaxHeapAttributeNumber
29 * so that alterations in HeapTupleHeaderData layout won't change the
30 * supported max number of columns.
32 #define MaxTupleAttributeNumber 1664 /* 8 * 208 */
35 * MaxHeapAttributeNumber limits the number of (user) columns in a table.
36 * This should be somewhat less than MaxTupleAttributeNumber. It must be
37 * at least one less, else we will fail to do UPDATEs on a maximal-width
38 * table (because UPDATE has to form working tuples that include CTID).
39 * In practice we want some additional daylight so that we can gracefully
40 * support operations that add hidden "resjunk" columns, for example
41 * SELECT * FROM wide_table ORDER BY foo, bar, baz.
42 * In any case, depending on column data types you will likely be running
43 * into the disk-block-based limit on overall tuple size if you have more
44 * than a thousand or so columns. TOAST won't help.
47 #define MaxHeapAttributeNumber 1600 /* 8 * 200 */
50 * On-disk heap tuple header. Currently this is also used as the header
51 * format for tuples formed in memory, although in principle they could
52 * be different. To avoid wasting space, the fields should be layed out
53 * in such a way to avoid structure padding.
55 * The overall structure of a heap tuple looks like:
56 * fixed fields (HeapTupleHeaderData struct)
57 * nulls bitmap (if HEAP_HASNULL is set in t_infomask)
58 * alignment padding (as needed to make user data MAXALIGN'd)
59 * object ID (if HEAP_HASOID is set in t_infomask)
62 * We store five "virtual" fields Xmin, Cmin, Xmax, Cmax, and Xvac
63 * in just three physical fields. Xmin is always really stored, but
64 * Cmin and Xmax share a field, as do Cmax and Xvac. This works because
65 * we know that there are only a limited number of states that a tuple can
66 * be in, and that Cmin and Cmax are only interesting for the lifetime of
67 * the inserting and deleting transactions respectively. We have the
68 * following possible states of a tuple:
70 * XMIN CMIN XMAX CMAX XVAC
72 * NEW (never deleted, not moved by vacuum):
73 * valid valid invalid invalid invalid
75 * DELETED BY CREATING XACT:
76 * valid valid = XMIN valid invalid
78 * DELETED BY OTHER XACT:
79 * valid unneeded valid valid invalid
81 * MOVED BY VACUUM FULL:
82 * valid unneeded maybe-valid unneeded valid
84 * This assumes that VACUUM FULL never tries to move a tuple whose Cmin or
85 * Cmax is still interesting (ie, insert-in-progress or delete-in-progress).
87 * This table shows that if we use an infomask bit to handle the case
88 * XMAX=XMIN specially, we never need to store Cmin and Xmax at the same
89 * time. Nor do we need to store Cmax and Xvac at the same time.
91 * Following the fixed header fields, the nulls bitmap is stored (beginning
92 * at t_bits). The bitmap is *not* stored if t_infomask shows that there
93 * are no nulls in the tuple. If an OID field is present (as indicated by
94 * t_infomask), then it is stored just before the user data, which begins at
95 * the offset shown by t_hoff. Note that t_hoff must be a multiple of
99 typedef struct HeapTupleHeaderData
101 TransactionId t_xmin; /* inserting xact ID */
105 CommandId t_cmin; /* inserting command ID */
106 TransactionId t_xmax; /* deleting xact ID */
111 CommandId t_cmax; /* deleting command ID */
112 TransactionId t_xvac; /* VACUUM FULL xact ID */
115 ItemPointerData t_ctid; /* current TID of this or newer tuple */
117 int16 t_natts; /* number of attributes */
119 uint16 t_infomask; /* various flag bits, see below */
121 uint8 t_hoff; /* sizeof header incl. bitmap, padding */
123 /* ^ - 23 bytes - ^ */
125 bits8 t_bits[1]; /* bitmap of NULLs -- VARIABLE LENGTH */
127 /* MORE DATA FOLLOWS AT END OF STRUCT */
128 } HeapTupleHeaderData;
130 typedef HeapTupleHeaderData *HeapTupleHeader;
133 * information stored in t_infomask:
135 #define HEAP_HASNULL 0x0001 /* has null attribute(s) */
136 #define HEAP_HASVARWIDTH 0x0002 /* has variable-width attribute(s) */
137 #define HEAP_HASEXTERNAL 0x0004 /* has external stored
139 #define HEAP_HASCOMPRESSED 0x0008 /* has compressed stored
141 #define HEAP_HASEXTENDED 0x000C /* the two above combined */
142 #define HEAP_HASOID 0x0010 /* has an object-id field */
143 /* bit 0x0020 is presently unused */
144 #define HEAP_XMAX_IS_XMIN 0x0040 /* created and deleted in the same
146 #define HEAP_XMAX_UNLOGGED 0x0080 /* to lock tuple for update
148 #define HEAP_XMIN_COMMITTED 0x0100 /* t_xmin committed */
149 #define HEAP_XMIN_INVALID 0x0200 /* t_xmin invalid/aborted */
150 #define HEAP_XMAX_COMMITTED 0x0400 /* t_xmax committed */
151 #define HEAP_XMAX_INVALID 0x0800 /* t_xmax invalid/aborted */
152 #define HEAP_MARKED_FOR_UPDATE 0x1000 /* marked for UPDATE */
153 #define HEAP_UPDATED 0x2000 /* this is UPDATEd version of row */
154 #define HEAP_MOVED_OFF 0x4000 /* moved to another place by
156 #define HEAP_MOVED_IN 0x8000 /* moved from another place by
158 #define HEAP_MOVED (HEAP_MOVED_OFF | HEAP_MOVED_IN)
160 #define HEAP_XACT_MASK 0xFFC0 /* visibility-related bits */
164 * HeapTupleHeader accessor macros
166 * Note: beware of multiple evaluations of "tup" argument. But the Set
167 * macros evaluate their other argument only once.
170 #define HeapTupleHeaderGetXmin(tup) \
175 #define HeapTupleHeaderSetXmin(tup, xid) \
177 TransactionIdStore((xid), &(tup)->t_xmin) \
180 #define HeapTupleHeaderGetXmax(tup) \
182 ((tup)->t_infomask & HEAP_XMAX_IS_XMIN) ? \
185 (tup)->t_field2.t_xmax \
188 #define HeapTupleHeaderSetXmax(tup, xid) \
190 TransactionId _newxid = (xid); \
191 if (TransactionIdEquals((tup)->t_xmin, _newxid)) \
192 (tup)->t_infomask |= HEAP_XMAX_IS_XMIN; \
195 (tup)->t_infomask &= ~HEAP_XMAX_IS_XMIN; \
196 TransactionIdStore(_newxid, &(tup)->t_field2.t_xmax); \
201 * Note: GetCmin will produce wrong answers after SetXmax has been executed
202 * by a transaction other than the inserting one. We could check
203 * HEAP_XMAX_INVALID and return FirstCommandId if it's clear, but since that
204 * bit will be set again if the deleting transaction aborts, there'd be no
205 * real gain in safety from the extra test. So, just rely on the caller not
206 * to trust the value unless it's meaningful.
208 #define HeapTupleHeaderGetCmin(tup) \
210 (tup)->t_field2.t_cmin \
213 #define HeapTupleHeaderSetCmin(tup, cid) \
215 Assert((tup)->t_infomask & HEAP_XMAX_INVALID); \
216 (tup)->t_field2.t_cmin = (cid); \
220 * As with GetCmin, we can't completely ensure that GetCmax can detect whether
221 * a valid command ID is available, and there's little point in a partial test.
223 #define HeapTupleHeaderGetCmax(tup) \
225 (tup)->t_field3.t_cmax \
228 #define HeapTupleHeaderSetCmax(tup, cid) \
230 Assert(!((tup)->t_infomask & HEAP_MOVED)); \
231 (tup)->t_field3.t_cmax = (cid); \
234 #define HeapTupleHeaderGetXvac(tup) \
236 ((tup)->t_infomask & HEAP_MOVED) ? \
237 (tup)->t_field3.t_xvac \
239 InvalidTransactionId \
242 #define HeapTupleHeaderSetXvac(tup, xid) \
244 Assert((tup)->t_infomask & HEAP_MOVED); \
245 TransactionIdStore((xid), &(tup)->t_field3.t_xvac); \
248 #define HeapTupleHeaderGetOid(tup) \
250 ((tup)->t_infomask & HEAP_HASOID) ? \
251 *((Oid *) ((char *)(tup) + (tup)->t_hoff - sizeof(Oid))) \
256 #define HeapTupleHeaderSetOid(tup, oid) \
258 Assert((tup)->t_infomask & HEAP_HASOID); \
259 *((Oid *) ((char *)(tup) + (tup)->t_hoff - sizeof(Oid))) = (oid); \
264 * WAL record definitions for heapam.c's WAL operations
266 * XLOG allows to store some information in high 4 bits of log
267 * record xl_info field
269 #define XLOG_HEAP_INSERT 0x00
270 #define XLOG_HEAP_DELETE 0x10
271 #define XLOG_HEAP_UPDATE 0x20
272 #define XLOG_HEAP_MOVE 0x30
273 #define XLOG_HEAP_CLEAN 0x40
274 #define XLOG_HEAP_OPMASK 0x70
276 * When we insert 1st item on new page in INSERT/UPDATE
277 * we can (and we do) restore entire page in redo
279 #define XLOG_HEAP_INIT_PAGE 0x80
282 * All what we need to find changed tuple (14 bytes)
284 * NB: on most machines, sizeof(xl_heaptid) will include some trailing pad
285 * bytes for alignment. We don't want to store the pad space in the XLOG,
286 * so use SizeOfHeapTid for space calculations. Similar comments apply for
287 * the other xl_FOO structs.
289 typedef struct xl_heaptid
292 ItemPointerData tid; /* changed tuple id */
295 #define SizeOfHeapTid (offsetof(xl_heaptid, tid) + SizeOfIptrData)
297 /* This is what we need to know about delete */
298 typedef struct xl_heap_delete
300 xl_heaptid target; /* deleted tuple id */
303 #define SizeOfHeapDelete (offsetof(xl_heap_delete, target) + SizeOfHeapTid)
306 * We don't store the whole fixed part (HeapTupleHeaderData) of an inserted
307 * or updated tuple in WAL; we can save a few bytes by reconstructing the
308 * fields that are available elsewhere in the WAL record, or perhaps just
309 * plain needn't be reconstructed. These are the fields we must store.
310 * NOTE: t_hoff could be recomputed, but we may as well store it because
311 * it will come for free due to alignment considerations.
313 typedef struct xl_heap_header
320 #define SizeOfHeapHeader (offsetof(xl_heap_header, t_hoff) + sizeof(uint8))
322 /* This is what we need to know about insert */
323 typedef struct xl_heap_insert
325 xl_heaptid target; /* inserted tuple id */
326 /* xl_heap_header & TUPLE DATA FOLLOWS AT END OF STRUCT */
329 #define SizeOfHeapInsert (offsetof(xl_heap_insert, target) + SizeOfHeapTid)
331 /* This is what we need to know about update|move */
332 typedef struct xl_heap_update
334 xl_heaptid target; /* deleted tuple id */
335 ItemPointerData newtid; /* new inserted tuple id */
336 /* NEW TUPLE xl_heap_header (PLUS xmax & xmin IF MOVE OP) */
337 /* and TUPLE DATA FOLLOWS AT END OF STRUCT */
340 #define SizeOfHeapUpdate (offsetof(xl_heap_update, newtid) + SizeOfIptrData)
342 /* This is what we need to know about page cleanup */
343 typedef struct xl_heap_clean
347 /* UNUSED OFFSET NUMBERS FOLLOW AT THE END */
350 #define SizeOfHeapClean (offsetof(xl_heap_clean, block) + sizeof(BlockNumber))
355 * MaxTupleSize is the maximum allowed size of a tuple, including header and
356 * MAXALIGN alignment padding. Basically it's BLCKSZ minus the other stuff
357 * that has to be on a disk page. The "other stuff" includes access-method-
358 * dependent "special space", which we assume will be no more than
359 * MaxSpecialSpace bytes (currently, on heap pages it's actually zero).
361 * NOTE: we do not need to count an ItemId for the tuple because
362 * sizeof(PageHeaderData) includes the first ItemId on the page.
364 #define MaxSpecialSpace 32
366 #define MaxTupleSize \
367 (BLCKSZ - MAXALIGN(sizeof(PageHeaderData) + MaxSpecialSpace))
370 * MaxAttrSize is a somewhat arbitrary upper limit on the declared size of
371 * data fields of char(n) and similar types. It need not have anything
372 * directly to do with the *actual* upper limit of varlena values, which
373 * is currently 1Gb (see struct varattrib in postgres.h). I've set it
374 * at 10Mb which seems like a reasonable number --- tgl 8/6/00.
376 #define MaxAttrSize (10 * 1024 * 1024)
380 * Attribute numbers for the system-defined attributes
382 #define SelfItemPointerAttributeNumber (-1)
383 #define ObjectIdAttributeNumber (-2)
384 #define MinTransactionIdAttributeNumber (-3)
385 #define MinCommandIdAttributeNumber (-4)
386 #define MaxTransactionIdAttributeNumber (-5)
387 #define MaxCommandIdAttributeNumber (-6)
388 #define TableOidAttributeNumber (-7)
389 #define FirstLowInvalidHeapAttributeNumber (-8)
392 * HeapTupleData is an in-memory data structure that points to a tuple.
394 * This new HeapTuple for version >= 6.5 and this is why it was changed:
396 * 1. t_len moved off on-disk tuple data - ItemIdData is used to get len;
397 * 2. t_ctid above is not self tuple TID now - it may point to
398 * updated version of tuple (required by MVCC);
399 * 3. someday someone let tuple to cross block boundaries -
400 * he have to add something below...
403 * Up to now t_data could be NULL, the memory location directly following
404 * HeapTupleData, or pointing into a buffer. Now, it could also point to
405 * a separate allocation that was done in the t_datamcxt memory context.
407 typedef struct HeapTupleData
409 uint32 t_len; /* length of *t_data */
410 ItemPointerData t_self; /* SelfItemPointer */
411 Oid t_tableOid; /* table the tuple came from */
412 MemoryContext t_datamcxt; /* memory context of allocation */
413 HeapTupleHeader t_data; /* -> tuple header and data */
416 typedef HeapTupleData *HeapTuple;
418 #define HEAPTUPLESIZE MAXALIGN(sizeof(HeapTupleData))
422 * GETSTRUCT - given a HeapTuple pointer, return address of the user data
424 #define GETSTRUCT(TUP) ((char *) ((TUP)->t_data) + (TUP)->t_data->t_hoff)
429 * Computes size of null bitmap given number of data columns.
431 #define BITMAPLEN(NATTS) (((int)(NATTS) + 7) / 8)
435 * True iff the heap tuple is valid.
437 #define HeapTupleIsValid(tuple) PointerIsValid(tuple)
439 #define HeapTupleNoNulls(tuple) \
440 (!((tuple)->t_data->t_infomask & HEAP_HASNULL))
442 #define HeapTupleAllFixed(tuple) \
443 (!((tuple)->t_data->t_infomask & HEAP_HASVARWIDTH))
445 #define HeapTupleHasExternal(tuple) \
446 (((tuple)->t_data->t_infomask & HEAP_HASEXTERNAL) != 0)
448 #define HeapTupleHasCompressed(tuple) \
449 (((tuple)->t_data->t_infomask & HEAP_HASCOMPRESSED) != 0)
451 #define HeapTupleHasExtended(tuple) \
452 (((tuple)->t_data->t_infomask & HEAP_HASEXTENDED) != 0)
454 #define HeapTupleGetOid(tuple) \
455 HeapTupleHeaderGetOid((tuple)->t_data)
457 #define HeapTupleSetOid(tuple, oid) \
458 HeapTupleHeaderSetOid((tuple)->t_data, (oid))