summaryrefslogtreecommitdiff
path: root/src/include/access/htup.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/access/htup.h')
-rw-r--r--src/include/access/htup.h291
1 files changed, 175 insertions, 116 deletions
diff --git a/src/include/access/htup.h b/src/include/access/htup.h
index a47e668f9b2..3d48b5f45a3 100644
--- a/src/include/access/htup.h
+++ b/src/include/access/htup.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/htup.h,v 1.64 2004/01/16 20:51:30 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/access/htup.h,v 1.65 2004/04/01 21:28:45 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -47,10 +47,19 @@
#define MaxHeapAttributeNumber 1600 /* 8 * 200 */
/*----------
- * On-disk heap tuple header. Currently this is also used as the header
- * format for tuples formed in memory, although in principle they could
- * be different. To avoid wasting space, the fields should be layed out
- * in such a way to avoid structure padding.
+ * 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)
@@ -96,7 +105,8 @@
* MAXALIGN.
*----------
*/
-typedef struct HeapTupleHeaderData
+
+typedef struct HeapTupleFields
{
TransactionId t_xmin; /* inserting xact ID */
@@ -111,6 +121,28 @@ typedef struct HeapTupleHeaderData
CommandId t_cmax; /* deleting command ID */
TransactionId t_xvac; /* VACUUM FULL xact ID */
} t_field3;
+} 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 */
@@ -169,31 +201,31 @@ typedef HeapTupleHeaderData *HeapTupleHeader;
#define HeapTupleHeaderGetXmin(tup) \
( \
- (tup)->t_xmin \
+ (tup)->t_choice.t_heap.t_xmin \
)
#define HeapTupleHeaderSetXmin(tup, xid) \
( \
- TransactionIdStore((xid), &(tup)->t_xmin) \
+ TransactionIdStore((xid), &(tup)->t_choice.t_heap.t_xmin) \
)
#define HeapTupleHeaderGetXmax(tup) \
( \
((tup)->t_infomask & HEAP_XMAX_IS_XMIN) ? \
- (tup)->t_xmin \
+ (tup)->t_choice.t_heap.t_xmin \
: \
- (tup)->t_field2.t_xmax \
+ (tup)->t_choice.t_heap.t_field2.t_xmax \
)
#define HeapTupleHeaderSetXmax(tup, xid) \
do { \
TransactionId _newxid = (xid); \
- if (TransactionIdEquals((tup)->t_xmin, _newxid)) \
+ if (TransactionIdEquals((tup)->t_choice.t_heap.t_xmin, _newxid)) \
(tup)->t_infomask |= HEAP_XMAX_IS_XMIN; \
else \
{ \
(tup)->t_infomask &= ~HEAP_XMAX_IS_XMIN; \
- TransactionIdStore(_newxid, &(tup)->t_field2.t_xmax); \
+ TransactionIdStore(_newxid, &(tup)->t_choice.t_heap.t_field2.t_xmax); \
} \
} while (0)
@@ -207,13 +239,13 @@ do { \
*/
#define HeapTupleHeaderGetCmin(tup) \
( \
- (tup)->t_field2.t_cmin \
+ (tup)->t_choice.t_heap.t_field2.t_cmin \
)
#define HeapTupleHeaderSetCmin(tup, cid) \
do { \
Assert((tup)->t_infomask & HEAP_XMAX_INVALID); \
- (tup)->t_field2.t_cmin = (cid); \
+ (tup)->t_choice.t_heap.t_field2.t_cmin = (cid); \
} while (0)
/*
@@ -222,19 +254,19 @@ do { \
*/
#define HeapTupleHeaderGetCmax(tup) \
( \
- (tup)->t_field3.t_cmax \
+ (tup)->t_choice.t_heap.t_field3.t_cmax \
)
#define HeapTupleHeaderSetCmax(tup, cid) \
do { \
Assert(!((tup)->t_infomask & HEAP_MOVED)); \
- (tup)->t_field3.t_cmax = (cid); \
+ (tup)->t_choice.t_heap.t_field3.t_cmax = (cid); \
} while (0)
#define HeapTupleHeaderGetXvac(tup) \
( \
((tup)->t_infomask & HEAP_MOVED) ? \
- (tup)->t_field3.t_xvac \
+ (tup)->t_choice.t_heap.t_field3.t_xvac \
: \
InvalidTransactionId \
)
@@ -242,9 +274,39 @@ do { \
#define HeapTupleHeaderSetXvac(tup, xid) \
do { \
Assert((tup)->t_infomask & HEAP_MOVED); \
- TransactionIdStore((xid), &(tup)->t_field3.t_xvac); \
+ TransactionIdStore((xid), &(tup)->t_choice.t_heap.t_field3.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) \
+)
+
+#define HeapTupleHeaderGetTypMod(tup) \
+( \
+ (tup)->t_choice.t_datum.datum_typmod \
+)
+
+#define HeapTupleHeaderSetTypMod(tup, typmod) \
+( \
+ (tup)->t_choice.t_datum.datum_typmod = (typmod) \
+)
+
#define HeapTupleHeaderGetOid(tup) \
( \
((tup)->t_infomask & HEAP_HASOID) ? \
@@ -261,95 +323,10 @@ do { \
/*
- * WAL record definitions for heapam.c's WAL operations
- *
- * XLOG allows to store some information in high 4 bits of log
- * record xl_info field
- */
-#define XLOG_HEAP_INSERT 0x00
-#define XLOG_HEAP_DELETE 0x10
-#define XLOG_HEAP_UPDATE 0x20
-#define XLOG_HEAP_MOVE 0x30
-#define XLOG_HEAP_CLEAN 0x40
-#define XLOG_HEAP_OPMASK 0x70
-/*
- * When we insert 1st item on new page in INSERT/UPDATE
- * we can (and we do) restore entire page in redo
- */
-#define XLOG_HEAP_INIT_PAGE 0x80
-
-/*
- * All what we need to find changed tuple (14 bytes)
- *
- * NB: on most machines, sizeof(xl_heaptid) will include some trailing pad
- * bytes for alignment. We don't want to store the pad space in the XLOG,
- * so use SizeOfHeapTid for space calculations. Similar comments apply for
- * the other xl_FOO structs.
- */
-typedef struct xl_heaptid
-{
- RelFileNode node;
- ItemPointerData tid; /* changed tuple id */
-} xl_heaptid;
-
-#define SizeOfHeapTid (offsetof(xl_heaptid, tid) + SizeOfIptrData)
-
-/* This is what we need to know about delete */
-typedef struct xl_heap_delete
-{
- xl_heaptid target; /* deleted tuple id */
-} xl_heap_delete;
-
-#define SizeOfHeapDelete (offsetof(xl_heap_delete, target) + SizeOfHeapTid)
-
-/*
- * We don't store the whole fixed part (HeapTupleHeaderData) of an inserted
- * or updated tuple in WAL; we can save a few bytes by reconstructing the
- * fields that are available elsewhere in the WAL record, or perhaps just
- * plain needn't be reconstructed. These are the fields we must store.
- * NOTE: t_hoff could be recomputed, but we may as well store it because
- * it will come for free due to alignment considerations.
+ * BITMAPLEN(NATTS) -
+ * Computes size of null bitmap given number of data columns.
*/
-typedef struct xl_heap_header
-{
- int16 t_natts;
- uint16 t_infomask;
- uint8 t_hoff;
-} xl_heap_header;
-
-#define SizeOfHeapHeader (offsetof(xl_heap_header, t_hoff) + sizeof(uint8))
-
-/* This is what we need to know about insert */
-typedef struct xl_heap_insert
-{
- xl_heaptid target; /* inserted tuple id */
- /* xl_heap_header & TUPLE DATA FOLLOWS AT END OF STRUCT */
-} xl_heap_insert;
-
-#define SizeOfHeapInsert (offsetof(xl_heap_insert, target) + SizeOfHeapTid)
-
-/* This is what we need to know about update|move */
-typedef struct xl_heap_update
-{
- xl_heaptid target; /* deleted tuple id */
- ItemPointerData newtid; /* new inserted tuple id */
- /* NEW TUPLE xl_heap_header (PLUS xmax & xmin IF MOVE OP) */
- /* and TUPLE DATA FOLLOWS AT END OF STRUCT */
-} xl_heap_update;
-
-#define SizeOfHeapUpdate (offsetof(xl_heap_update, newtid) + SizeOfIptrData)
-
-/* This is what we need to know about page cleanup */
-typedef struct xl_heap_clean
-{
- RelFileNode node;
- BlockNumber block;
- /* UNUSED OFFSET NUMBERS FOLLOW AT THE END */
-} xl_heap_clean;
-
-#define SizeOfHeapClean (offsetof(xl_heap_clean, block) + sizeof(BlockNumber))
-
-
+#define BITMAPLEN(NATTS) (((int)(NATTS) + 7) / 8)
/*
* MaxTupleSize is the maximum allowed size of a tuple, including header and
@@ -388,6 +365,7 @@ typedef struct xl_heap_clean
#define TableOidAttributeNumber (-7)
#define FirstLowInvalidHeapAttributeNumber (-8)
+
/*
* HeapTupleData is an in-memory data structure that points to a tuple.
*
@@ -417,22 +395,13 @@ typedef HeapTupleData *HeapTuple;
#define HEAPTUPLESIZE MAXALIGN(sizeof(HeapTupleData))
-
/*
* GETSTRUCT - given a HeapTuple pointer, return address of the user data
*/
#define GETSTRUCT(TUP) ((char *) ((TUP)->t_data) + (TUP)->t_data->t_hoff)
-
/*
- * BITMAPLEN(NATTS) -
- * Computes size of null bitmap given number of data columns.
- */
-#define BITMAPLEN(NATTS) (((int)(NATTS) + 7) / 8)
-
-/*
- * HeapTupleIsValid
- * True iff the heap tuple is valid.
+ * Accessor macros to be used with HeapTuple pointers.
*/
#define HeapTupleIsValid(tuple) PointerIsValid(tuple)
@@ -463,4 +432,94 @@ typedef HeapTupleData *HeapTuple;
#define HeapTupleSetOid(tuple, oid) \
HeapTupleHeaderSetOid((tuple)->t_data, (oid))
+
+/*
+ * WAL record definitions for heapam.c's WAL operations
+ *
+ * XLOG allows to store some information in high 4 bits of log
+ * record xl_info field
+ */
+#define XLOG_HEAP_INSERT 0x00
+#define XLOG_HEAP_DELETE 0x10
+#define XLOG_HEAP_UPDATE 0x20
+#define XLOG_HEAP_MOVE 0x30
+#define XLOG_HEAP_CLEAN 0x40
+#define XLOG_HEAP_OPMASK 0x70
+/*
+ * When we insert 1st item on new page in INSERT/UPDATE
+ * we can (and we do) restore entire page in redo
+ */
+#define XLOG_HEAP_INIT_PAGE 0x80
+
+/*
+ * All what we need to find changed tuple (14 bytes)
+ *
+ * NB: on most machines, sizeof(xl_heaptid) will include some trailing pad
+ * bytes for alignment. We don't want to store the pad space in the XLOG,
+ * so use SizeOfHeapTid for space calculations. Similar comments apply for
+ * the other xl_FOO structs.
+ */
+typedef struct xl_heaptid
+{
+ RelFileNode node;
+ ItemPointerData tid; /* changed tuple id */
+} xl_heaptid;
+
+#define SizeOfHeapTid (offsetof(xl_heaptid, tid) + SizeOfIptrData)
+
+/* This is what we need to know about delete */
+typedef struct xl_heap_delete
+{
+ xl_heaptid target; /* deleted tuple id */
+} xl_heap_delete;
+
+#define SizeOfHeapDelete (offsetof(xl_heap_delete, target) + SizeOfHeapTid)
+
+/*
+ * We don't store the whole fixed part (HeapTupleHeaderData) of an inserted
+ * or updated tuple in WAL; we can save a few bytes by reconstructing the
+ * fields that are available elsewhere in the WAL record, or perhaps just
+ * plain needn't be reconstructed. These are the fields we must store.
+ * NOTE: t_hoff could be recomputed, but we may as well store it because
+ * it will come for free due to alignment considerations.
+ */
+typedef struct xl_heap_header
+{
+ int16 t_natts;
+ uint16 t_infomask;
+ uint8 t_hoff;
+} xl_heap_header;
+
+#define SizeOfHeapHeader (offsetof(xl_heap_header, t_hoff) + sizeof(uint8))
+
+/* This is what we need to know about insert */
+typedef struct xl_heap_insert
+{
+ xl_heaptid target; /* inserted tuple id */
+ /* xl_heap_header & TUPLE DATA FOLLOWS AT END OF STRUCT */
+} xl_heap_insert;
+
+#define SizeOfHeapInsert (offsetof(xl_heap_insert, target) + SizeOfHeapTid)
+
+/* This is what we need to know about update|move */
+typedef struct xl_heap_update
+{
+ xl_heaptid target; /* deleted tuple id */
+ ItemPointerData newtid; /* new inserted tuple id */
+ /* NEW TUPLE xl_heap_header (PLUS xmax & xmin IF MOVE OP) */
+ /* and TUPLE DATA FOLLOWS AT END OF STRUCT */
+} xl_heap_update;
+
+#define SizeOfHeapUpdate (offsetof(xl_heap_update, newtid) + SizeOfIptrData)
+
+/* This is what we need to know about page cleanup */
+typedef struct xl_heap_clean
+{
+ RelFileNode node;
+ BlockNumber block;
+ /* UNUSED OFFSET NUMBERS FOLLOW AT THE END */
+} xl_heap_clean;
+
+#define SizeOfHeapClean (offsetof(xl_heap_clean, block) + sizeof(BlockNumber))
+
#endif /* HTUP_H */