📄 htup.h
字号:
/*------------------------------------------------------------------------- * * htup.h * POSTGRES heap tuple definitions. * * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * $PostgreSQL: pgsql/src/include/access/htup.h,v 1.78 2005/10/15 02:49:42 momjian Exp $ * *------------------------------------------------------------------------- */#ifndef HTUP_H#define HTUP_H#include "storage/bufpage.h"#include "storage/relfilenode.h"#include "access/transam.h"/* * MaxTupleAttributeNumber limits the number of (user) columns in a tuple. * The key limit on this value is that the size of the fixed overhead for * a tuple, plus the size of the null-values bitmap (at 1 bit per column), * plus MAXALIGN alignment, must fit into t_hoff which is uint8. On most * machines the upper limit without making t_hoff wider would be a little * over 1700. We use round numbers here and for MaxHeapAttributeNumber * so that alterations in HeapTupleHeaderData layout won't change the * supported max number of columns. */#define MaxTupleAttributeNumber 1664 /* 8 * 208 *//*---------- * MaxHeapAttributeNumber limits the number of (user) columns in a table. * This should be somewhat less than MaxTupleAttributeNumber. It must be * at least one less, else we will fail to do UPDATEs on a maximal-width * table (because UPDATE has to form working tuples that include CTID). * In practice we want some additional daylight so that we can gracefully * support operations that add hidden "resjunk" columns, for example * SELECT * FROM wide_table ORDER BY foo, bar, baz. * In any case, depending on column data types you will likely be running * into the disk-block-based limit on overall tuple size if you have more * than a thousand or so columns. TOAST won't help. *---------- */#define MaxHeapAttributeNumber 1600 /* 8 * 200 *//*---------- * Heap tuple header. To avoid wasting space, the fields should be * layed out in such a way to avoid structure padding. * * Datums of composite types (row types) share the same general structure * as on-disk tuples, so that the same routines can be used to build and * examine them. However the requirements are slightly different: a Datum * does not need any transaction visibility information, and it does need * a length word and some embedded type information. We can achieve this * by overlaying the xmin/cmin/xmax/cmax/xvac fields of a heap tuple * with the fields needed in the Datum case. Typically, all tuples built * in-memory will be initialized with the Datum fields; but when a tuple is * about to be inserted in a table, the transaction fields will be filled, * overwriting the datum fields. * * The overall structure of a heap tuple looks like: * fixed fields (HeapTupleHeaderData struct) * nulls bitmap (if HEAP_HASNULL is set in t_infomask) * alignment padding (as needed to make user data MAXALIGN'd) * object ID (if HEAP_HASOID is set in t_infomask) * user data fields * * We store five "virtual" fields Xmin, Cmin, Xmax, Cmax, and Xvac in four * physical fields. Xmin, Cmin and Xmax are always really stored, but * Cmax and Xvac share a field. This works because we know that there are * only a limited number of states that a tuple can be in, and that Cmax * is only interesting for the lifetime of the deleting transaction. * This assumes that VACUUM FULL never tries to move a tuple whose Cmax * is still interesting (ie, delete-in-progress). * * Note that in 7.3 and 7.4 a similar idea was applied to Xmax and Cmin. * However, with the advent of subtransactions, a tuple may need both Xmax * and Cmin simultaneously, so this is no longer possible. * * A word about t_ctid: whenever a new tuple is stored on disk, its t_ctid * is initialized with its own TID (location). If the tuple is ever updated, * its t_ctid is changed to point to the replacement version of the tuple. * Thus, a tuple is the latest version of its row iff XMAX is invalid or * t_ctid points to itself (in which case, if XMAX is valid, the tuple is * either locked or deleted). One can follow the chain of t_ctid links * to find the newest version of the row. Beware however that VACUUM might * erase the pointed-to (newer) tuple before erasing the pointing (older) * tuple. Hence, when following a t_ctid link, it is necessary to check * to see if the referenced slot is empty or contains an unrelated tuple. * Check that the referenced tuple has XMIN equal to the referencing tuple's * XMAX to verify that it is actually the descendant version and not an * unrelated tuple stored into a slot recently freed by VACUUM. If either * check fails, one may assume that there is no live descendant version. * * Following the fixed header fields, the nulls bitmap is stored (beginning * at t_bits). The bitmap is *not* stored if t_infomask shows that there * are no nulls in the tuple. If an OID field is present (as indicated by * t_infomask), then it is stored just before the user data, which begins at * the offset shown by t_hoff. Note that t_hoff must be a multiple of * MAXALIGN. *---------- */typedef struct HeapTupleFields{ TransactionId t_xmin; /* inserting xact ID */ CommandId t_cmin; /* inserting command ID */ TransactionId t_xmax; /* deleting or locking xact ID */ union { CommandId t_cmax; /* deleting or locking command ID */ TransactionId t_xvac; /* VACUUM FULL xact ID */ } t_field4;} HeapTupleFields;typedef struct DatumTupleFields{ int32 datum_len; /* required to be a varlena type */ int32 datum_typmod; /* -1, or identifier of a record type */ Oid datum_typeid; /* composite type OID, or RECORDOID */ /* * Note: field ordering is chosen with thought that Oid might someday * widen to 64 bits. */} DatumTupleFields;typedef struct HeapTupleHeaderData{ union { HeapTupleFields t_heap; DatumTupleFields t_datum; } t_choice; ItemPointerData t_ctid; /* current TID of this or newer tuple */ int16 t_natts; /* number of attributes */ uint16 t_infomask; /* various flag bits, see below */ uint8 t_hoff; /* sizeof header incl. bitmap, padding */ /* ^ - 27 bytes - ^ */ bits8 t_bits[1]; /* bitmap of NULLs -- VARIABLE LENGTH */ /* MORE DATA FOLLOWS AT END OF STRUCT */} HeapTupleHeaderData;typedef HeapTupleHeaderData *HeapTupleHeader;/* * information stored in t_infomask: */#define HEAP_HASNULL 0x0001 /* has null attribute(s) */#define HEAP_HASVARWIDTH 0x0002 /* has variable-width attribute(s) */#define HEAP_HASEXTERNAL 0x0004 /* has external stored attribute(s) */#define HEAP_HASCOMPRESSED 0x0008 /* has compressed stored attribute(s) */#define HEAP_HASEXTENDED 0x000C /* the two above combined */#define HEAP_HASOID 0x0010 /* has an object-id field *//* 0x0020 is presently unused */#define HEAP_XMAX_EXCL_LOCK 0x0040 /* xmax is exclusive locker */#define HEAP_XMAX_SHARED_LOCK 0x0080 /* xmax is shared locker *//* if either LOCK bit is set, xmax hasn't deleted the tuple, only locked it */#define HEAP_IS_LOCKED (HEAP_XMAX_EXCL_LOCK | HEAP_XMAX_SHARED_LOCK)#define HEAP_XMIN_COMMITTED 0x0100 /* t_xmin committed */#define HEAP_XMIN_INVALID 0x0200 /* t_xmin invalid/aborted */#define HEAP_XMAX_COMMITTED 0x0400 /* t_xmax committed */#define HEAP_XMAX_INVALID 0x0800 /* t_xmax invalid/aborted */#define HEAP_XMAX_IS_MULTI 0x1000 /* t_xmax is a MultiXactId */#define HEAP_UPDATED 0x2000 /* this is UPDATEd version of row */#define HEAP_MOVED_OFF 0x4000 /* moved to another place by VACUUM * FULL */#define HEAP_MOVED_IN 0x8000 /* moved from another place by VACUUM * FULL */#define HEAP_MOVED (HEAP_MOVED_OFF | HEAP_MOVED_IN)#define HEAP_XACT_MASK 0xFFC0 /* visibility-related bits *//* * HeapTupleHeader accessor macros * * Note: beware of multiple evaluations of "tup" argument. But the Set * macros evaluate their other argument only once. */#define HeapTupleHeaderGetXmin(tup) \( \ (tup)->t_choice.t_heap.t_xmin \)#define HeapTupleHeaderSetXmin(tup, xid) \( \ TransactionIdStore((xid), &(tup)->t_choice.t_heap.t_xmin) \)#define HeapTupleHeaderGetXmax(tup) \( \ (tup)->t_choice.t_heap.t_xmax \)#define HeapTupleHeaderSetXmax(tup, xid) \( \ TransactionIdStore((xid), &(tup)->t_choice.t_heap.t_xmax) \)#define HeapTupleHeaderGetCmin(tup) \( \ (tup)->t_choice.t_heap.t_cmin \)#define HeapTupleHeaderSetCmin(tup, cid) \( \ (tup)->t_choice.t_heap.t_cmin = (cid) \)/* * Note: GetCmax will produce wrong answers after SetXvac has been executed * by a transaction other than the inserting one. We could check * HEAP_XMAX_INVALID and return FirstCommandId if it's clear, but since that * bit will be set again if the deleting transaction aborts, there'd be no * real gain in safety from the extra test. So, just rely on the caller not * to trust the value unless it's meaningful. */#define HeapTupleHeaderGetCmax(tup) \( \ (tup)->t_choice.t_heap.t_field4.t_cmax \)#define HeapTupleHeaderSetCmax(tup, cid) \do { \ Assert(!((tup)->t_infomask & HEAP_MOVED)); \ (tup)->t_choice.t_heap.t_field4.t_cmax = (cid); \} while (0)#define HeapTupleHeaderGetXvac(tup) \( \ ((tup)->t_infomask & HEAP_MOVED) ? \ (tup)->t_choice.t_heap.t_field4.t_xvac \ : \ InvalidTransactionId \)#define HeapTupleHeaderSetXvac(tup, xid) \do { \ Assert((tup)->t_infomask & HEAP_MOVED); \ TransactionIdStore((xid), &(tup)->t_choice.t_heap.t_field4.t_xvac); \} while (0)#define HeapTupleHeaderGetDatumLength(tup) \( \ (tup)->t_choice.t_datum.datum_len \)#define HeapTupleHeaderSetDatumLength(tup, len) \( \ (tup)->t_choice.t_datum.datum_len = (len) \)#define HeapTupleHeaderGetTypeId(tup) \( \ (tup)->t_choice.t_datum.datum_typeid \)#define HeapTupleHeaderSetTypeId(tup, typeid) \( \ (tup)->t_choice.t_datum.datum_typeid = (typeid) \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -