diff options
Diffstat (limited to 'src/include/access/htup.h')
-rw-r--r-- | src/include/access/htup.h | 291 |
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 */ |