diff options
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/access/htup.h | 279 | ||||
-rw-r--r-- | src/include/access/tupdesc.h | 32 | ||||
-rw-r--r-- | src/include/catalog/catversion.h | 4 | ||||
-rw-r--r-- | src/include/catalog/heap.h | 3 | ||||
-rw-r--r-- | src/include/executor/executor.h | 4 | ||||
-rw-r--r-- | src/include/pg_config.h.in | 8 | ||||
-rw-r--r-- | src/include/storage/bufpage.h | 60 |
7 files changed, 199 insertions, 191 deletions
diff --git a/src/include/access/htup.h b/src/include/access/htup.h index f1d9748f5c5..3bede1bfa3a 100644 --- a/src/include/access/htup.h +++ b/src/include/access/htup.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: htup.h,v 1.58 2002/08/25 17:20:01 tgl Exp $ + * $Id: htup.h,v 1.59 2002/09/02 01:05:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -46,33 +46,69 @@ */ #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. + * be different. To avoid wasting space, the fields should be layed out + * in such a way to avoid structure padding. + * + * 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 just three physical fields. Xmin is always really stored, but + * Cmin and Xmax share a field, as do Cmax and Xvac. This works because + * we know that there are only a limited number of states that a tuple can + * be in, and that Cmin and Cmax are only interesting for the lifetime of + * the inserting and deleting transactions respectively. We have the + * following possible states of a tuple: + * + * XMIN CMIN XMAX CMAX XVAC + * + * NEW (never deleted, not moved by vacuum): + * valid valid invalid invalid invalid * - * To avoid wasting space, the attributes should be layed out in such a - * way to reduce structure padding. Note that t_hoff is the offset to - * the start of the user data, and so must be a multiple of MAXALIGN. - * Also note that we omit the nulls bitmap if t_infomask shows that there - * are no nulls in the tuple. + * DELETED BY CREATING XACT: + * valid valid = XMIN valid invalid + * + * DELETED BY OTHER XACT: + * valid unneeded valid valid invalid + * + * MOVED BY VACUUM FULL: + * valid unneeded maybe-valid unneeded valid + * + * This assumes that VACUUM FULL never tries to move a tuple whose Cmin or + * Cmax is still interesting (ie, insert-in-progress or delete-in-progress). + * + * This table shows that if we use an infomask bit to handle the case + * XMAX=XMIN specially, we never need to store Cmin and Xmax at the same + * time. Nor do we need to store Cmax and Xvac at the same time. + * + * 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. + *---------- */ -/* -** We store five "virtual" fields Xmin, Cmin, Xmax, Cmax, and Xvac -** in three physical fields t_xmin, t_cid, t_xmax: -** CommandId Cmin; insert CID stamp -** CommandId Cmax; delete CommandId stamp -** TransactionId Xmin; insert XID stamp -** TransactionId Xmax; delete XID stamp -** TransactionId Xvac; used by VACCUUM -** -** This assumes, that a CommandId can be stored in a TransactionId. -*/ typedef struct HeapTupleHeaderData { - TransactionId t_xmin; /* Xmin -- 4 bytes each */ - TransactionId t_cid; /* Cmin, Cmax, Xvac */ - TransactionId t_xmax; /* Xmax, Cmax */ + TransactionId t_xmin; /* inserting xact ID */ + + union { + CommandId t_cmin; /* inserting command ID */ + TransactionId t_xmax; /* deleting xact ID */ + } t_field2; + + union { + CommandId t_cmax; /* deleting command ID */ + TransactionId t_xvac; /* VACUUM FULL xact ID */ + } t_field3; ItemPointerData t_ctid; /* current TID of this or newer tuple */ @@ -101,11 +137,12 @@ typedef HeapTupleHeaderData *HeapTupleHeader; #define HEAP_HASCOMPRESSED 0x0008 /* has compressed stored * attribute(s) */ #define HEAP_HASEXTENDED 0x000C /* the two above combined */ - -#define HEAP_XMIN_IS_XMAX 0x0040 /* created and deleted in the */ - /* same transaction */ -#define HEAP_XMAX_UNLOGGED 0x0080 /* to lock tuple for update */ - /* without logging */ +#define HEAP_HASOID 0x0010 /* has an object-id field */ +/* bit 0x0020 is presently unused */ +#define HEAP_XMAX_IS_XMIN 0x0040 /* created and deleted in the + * same transaction */ +#define HEAP_XMAX_UNLOGGED 0x0080 /* to lock tuple for update + * without logging */ #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 */ @@ -113,143 +150,111 @@ typedef HeapTupleHeaderData *HeapTupleHeader; #define HEAP_MARKED_FOR_UPDATE 0x1000 /* marked for UPDATE */ #define HEAP_UPDATED 0x2000 /* this is UPDATEd version of row */ #define HEAP_MOVED_OFF 0x4000 /* moved to another place by - * vacuum */ + * VACUUM FULL */ #define HEAP_MOVED_IN 0x8000 /* moved from another place by - * vacuum */ + * VACUUM FULL */ #define HEAP_MOVED (HEAP_MOVED_OFF | HEAP_MOVED_IN) -#define HEAP_XACT_MASK 0xFFF0 /* visibility-related bits */ - -/* paranoid checking */ - -#ifdef DEBUG_TUPLE_ACCESS - -#define HeapTupleHeaderExpectedLen(tup, withoid) \ - MAXALIGN(offsetof(HeapTupleHeaderData, t_bits) + \ - (((tup)->t_infomask & HEAP_HASNULL) \ - ? BITMAPLEN((tup)->t_natts) : 0) + \ - ((withoid) ? sizeof(Oid) : 0) \ - ) - -#define AssertHeapTupleHeaderHoffIsValid(tup, withoid) \ - AssertMacro((tup)->t_hoff == HeapTupleHeaderExpectedLen(tup, withoid)) - -#else - -#define AssertHeapTupleHeaderHoffIsValid(tup, withoid) ((void)true) - -#endif /* DEBUG_TUPLE_ACCESS */ - +#define HEAP_XACT_MASK 0xFFC0 /* visibility-related bits */ -/* HeapTupleHeader accessor macros */ -#define HeapTupleHeaderGetOid(tup) \ -( \ - AssertHeapTupleHeaderHoffIsValid(tup, true), \ - *((Oid *)((char *)(tup) + (tup)->t_hoff - sizeof(Oid))) \ -) - -#define HeapTupleHeaderSetOid(tup, oid) \ -( \ - AssertHeapTupleHeaderHoffIsValid(tup, true), \ - *((Oid *)((char *)(tup) + (tup)->t_hoff - sizeof(Oid))) = (oid) \ -) - +/* + * 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_xmin \ ) -#define HeapTupleHeaderGetXmax(tup) \ -( \ - ((tup)->t_infomask & HEAP_XMIN_IS_XMAX) ? \ - (tup)->t_xmin \ - : \ - (tup)->t_xmax \ -) - -/* no AssertMacro, because this is read as a system-defined attribute */ -#define HeapTupleHeaderGetCmin(tup) \ +#define HeapTupleHeaderSetXmin(tup, xid) \ ( \ - ((tup)->t_infomask & HEAP_MOVED) ? \ - FirstCommandId \ - : \ - ( \ - ((tup)->t_infomask & (HEAP_XMIN_IS_XMAX | HEAP_XMAX_INVALID)) ? \ - (CommandId) (tup)->t_cid \ - : \ - FirstCommandId \ - ) \ + TransactionIdStore((xid), &(tup)->t_xmin) \ ) -#define HeapTupleHeaderGetCmax(tup) \ +#define HeapTupleHeaderGetXmax(tup) \ ( \ - ((tup)->t_infomask & HEAP_MOVED) ? \ - FirstCommandId \ + ((tup)->t_infomask & HEAP_XMAX_IS_XMIN) ? \ + (tup)->t_xmin \ : \ - ( \ - ((tup)->t_infomask & (HEAP_XMIN_IS_XMAX | HEAP_XMAX_INVALID)) ? \ - (CommandId) (tup)->t_xmax \ - : \ - (CommandId) (tup)->t_cid \ - ) \ -) - -#define HeapTupleHeaderGetXvac(tup) \ -( \ - AssertMacro((tup)->t_infomask & HEAP_MOVED), \ - (tup)->t_cid \ -) - - -#define HeapTupleHeaderSetXmin(tup, xid) \ -( \ - TransactionIdStore((xid), &(tup)->t_xmin) \ + (tup)->t_field2.t_xmax \ ) -#define HeapTupleHeaderSetXminInvalid(tup) \ -do { \ - (tup)->t_infomask &= ~HEAP_XMIN_IS_XMAX; \ - StoreInvalidTransactionId(&(tup)->t_xmin); \ -} while (0) - #define HeapTupleHeaderSetXmax(tup, xid) \ do { \ - if (TransactionIdEquals((tup)->t_xmin, (xid))) \ - (tup)->t_infomask |= HEAP_XMIN_IS_XMAX; \ + TransactionId _newxid = (xid); \ + if (TransactionIdEquals((tup)->t_xmin, _newxid)) \ + (tup)->t_infomask |= HEAP_XMAX_IS_XMIN; \ else \ { \ - (tup)->t_infomask &= ~HEAP_XMIN_IS_XMAX; \ - TransactionIdStore((xid), &(tup)->t_xmax); \ + (tup)->t_infomask &= ~HEAP_XMAX_IS_XMIN; \ + TransactionIdStore(_newxid, &(tup)->t_field2.t_xmax); \ } \ } while (0) -#define HeapTupleHeaderSetXmaxInvalid(tup) \ -do { \ - (tup)->t_infomask &= ~HEAP_XMIN_IS_XMAX; \ - StoreInvalidTransactionId(&(tup)->t_xmax); \ -} while (0) +/* + * Note: GetCmin will produce wrong answers after SetXmax 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 HeapTupleHeaderGetCmin(tup) \ +( \ + (tup)->t_field2.t_cmin \ +) #define HeapTupleHeaderSetCmin(tup, cid) \ do { \ - Assert(!((tup)->t_infomask & HEAP_MOVED)); \ - TransactionIdStore((TransactionId) (cid), &(tup)->t_cid); \ + Assert((tup)->t_infomask & HEAP_XMAX_INVALID); \ + (tup)->t_field2.t_cmin = (cid); \ } while (0) +/* + * As with GetCmin, we can't completely ensure that GetCmax can detect whether + * a valid command ID is available, and there's little point in a partial test. + */ +#define HeapTupleHeaderGetCmax(tup) \ +( \ + (tup)->t_field3.t_cmax \ +) + #define HeapTupleHeaderSetCmax(tup, cid) \ do { \ Assert(!((tup)->t_infomask & HEAP_MOVED)); \ - if ((tup)->t_infomask & HEAP_XMIN_IS_XMAX) \ - TransactionIdStore((TransactionId) (cid), &(tup)->t_xmax); \ - else \ - TransactionIdStore((TransactionId) (cid), &(tup)->t_cid); \ + (tup)->t_field3.t_cmax = (cid); \ } while (0) +#define HeapTupleHeaderGetXvac(tup) \ +( \ + ((tup)->t_infomask & HEAP_MOVED) ? \ + (tup)->t_field3.t_xvac \ + : \ + InvalidTransactionId \ +) + #define HeapTupleHeaderSetXvac(tup, xid) \ do { \ Assert((tup)->t_infomask & HEAP_MOVED); \ - TransactionIdStore((xid), &(tup)->t_cid); \ + TransactionIdStore((xid), &(tup)->t_field3.t_xvac); \ +} while (0) + +#define HeapTupleHeaderGetOid(tup) \ +( \ + ((tup)->t_infomask & HEAP_HASOID) ? \ + *((Oid *) ((char *)(tup) + (tup)->t_hoff - sizeof(Oid))) \ + : \ + InvalidOid \ +) + +#define HeapTupleHeaderSetOid(tup, oid) \ +do { \ + Assert((tup)->t_infomask & HEAP_HASOID); \ + *((Oid *) ((char *)(tup) + (tup)->t_hoff - sizeof(Oid))) = (oid); \ } while (0) @@ -400,12 +405,10 @@ typedef HeapTupleData *HeapTuple; #define HEAPTUPLESIZE MAXALIGN(sizeof(HeapTupleData)) -/* ---------------- - * support macros - * ---------------- +/* + * GETSTRUCT - given a HeapTuple pointer, return address of the user data */ -#define GETSTRUCT(TUP) (((char *)((HeapTuple)(TUP))->t_data) + \ - ((HeapTuple)(TUP))->t_data->t_hoff) +#define GETSTRUCT(TUP) ((char *) ((TUP)->t_data) + (TUP)->t_data->t_hoff) /* @@ -421,24 +424,24 @@ typedef HeapTupleData *HeapTuple; #define HeapTupleIsValid(tuple) PointerIsValid(tuple) #define HeapTupleNoNulls(tuple) \ - (!(((HeapTuple) (tuple))->t_data->t_infomask & HEAP_HASNULL)) + (!((tuple)->t_data->t_infomask & HEAP_HASNULL)) #define HeapTupleAllFixed(tuple) \ - (!(((HeapTuple) (tuple))->t_data->t_infomask & HEAP_HASVARWIDTH)) + (!((tuple)->t_data->t_infomask & HEAP_HASVARWIDTH)) #define HeapTupleHasExternal(tuple) \ - ((((HeapTuple)(tuple))->t_data->t_infomask & HEAP_HASEXTERNAL) != 0) + (((tuple)->t_data->t_infomask & HEAP_HASEXTERNAL) != 0) #define HeapTupleHasCompressed(tuple) \ - ((((HeapTuple)(tuple))->t_data->t_infomask & HEAP_HASCOMPRESSED) != 0) + (((tuple)->t_data->t_infomask & HEAP_HASCOMPRESSED) != 0) #define HeapTupleHasExtended(tuple) \ - ((((HeapTuple)(tuple))->t_data->t_infomask & HEAP_HASEXTENDED) != 0) + (((tuple)->t_data->t_infomask & HEAP_HASEXTENDED) != 0) #define HeapTupleGetOid(tuple) \ - HeapTupleHeaderGetOid(((HeapTuple)(tuple))->t_data) + HeapTupleHeaderGetOid((tuple)->t_data) #define HeapTupleSetOid(tuple, oid) \ - HeapTupleHeaderSetOid(((HeapTuple)(tuple))->t_data, (oid)) + HeapTupleHeaderSetOid((tuple)->t_data, (oid)) #endif /* HTUP_H */ diff --git a/src/include/access/tupdesc.h b/src/include/access/tupdesc.h index c8c9839985e..09512a322e1 100644 --- a/src/include/access/tupdesc.h +++ b/src/include/access/tupdesc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: tupdesc.h,v 1.37 2002/07/20 05:16:59 momjian Exp $ + * $Id: tupdesc.h,v 1.38 2002/09/02 01:05:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -41,14 +41,9 @@ typedef struct tupleConstr bool has_not_null; } TupleConstr; -typedef char hasoid_t; -#define WITHOID 'C' -#define WITHOUTOID 'S' -#define UNDEFOID '?' -#define BoolToHasOid(b) ((b) ? WITHOID : WITHOUTOID) /* * This structure contains all information (i.e. from Classes - * pg_attribute, pg_attrdef, pg_constraint) for a tuple. + * pg_attribute, pg_attrdef, pg_constraint) for the structure of a tuple. */ typedef struct tupleDesc { @@ -56,29 +51,14 @@ typedef struct tupleDesc Form_pg_attribute *attrs; /* attrs[N] is a pointer to the description of Attribute Number N+1. */ TupleConstr *constr; - hasoid_t tdhasoid; /* Tuple has an oid attribute in its header */ + bool tdhasoid; /* Tuple has oid attribute in its header */ } *TupleDesc; -#ifdef DEBUG_TUPLE_ACCESS -#define AssertTupleDescHasOidIsValid(td) \ - Assert(((td)->tdhasoid == WITHOID) || ((td)->tdhasoid == WITHOUTOID)) -#define AssertTupleDescHasOid(td) \ - Assert((td)->tdhasoid == WITHOID) -#define AssertTupleDescHasNoOid(td) \ - Assert((td)->tdhasoid == WITHOUTOID) +extern TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid); -#else - -#define AssertTupleDescHasOidIsValid(td) -#define AssertTupleDescHasOid(td) -#define AssertTupleDescHasNoOid(td) - -#endif - -extern TupleDesc CreateTemplateTupleDesc(int natts, hasoid_t withoid); - -extern TupleDesc CreateTupleDesc(int natts, Form_pg_attribute *attrs); +extern TupleDesc CreateTupleDesc(int natts, bool hasoid, + Form_pg_attribute *attrs); extern TupleDesc CreateTupleDescCopy(TupleDesc tupdesc); diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index f561dee66b1..652009104fe 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: catversion.h,v 1.156 2002/08/31 17:14:28 tgl Exp $ + * $Id: catversion.h,v 1.157 2002/09/02 01:05:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200208311 +#define CATALOG_VERSION_NO 200209011 #endif diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h index f45c61515ad..b1f5dc8600c 100644 --- a/src/include/catalog/heap.h +++ b/src/include/catalog/heap.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: heap.h,v 1.55 2002/08/02 18:15:09 tgl Exp $ + * $Id: heap.h,v 1.56 2002/09/02 01:05:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -41,7 +41,6 @@ extern Oid heap_create_with_catalog(const char *relname, TupleDesc tupdesc, char relkind, bool shared_relation, - bool relhasoids, bool allow_system_table_mods); extern void heap_drop_with_catalog(Oid rid); diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 3fbf63567ac..f2fa81857cd 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: executor.h,v 1.76 2002/08/30 23:59:46 tgl Exp $ + * $Id: executor.h,v 1.77 2002/09/02 01:05:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -122,7 +122,7 @@ extern void ExecInitScanTupleSlot(EState *estate, extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate); extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate, TupleDesc tupType); -extern TupleDesc ExecTypeFromTL(List *targetList, hasoid_t withoid); +extern TupleDesc ExecTypeFromTL(List *targetList, bool hasoid); extern void SetChangedParamList(Plan *node, List *newchg); typedef struct TupOutputState diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index a64be7fcf2a..670c80a4030 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -8,7 +8,7 @@ * or in pg_config.h afterwards. Of course, if you edit pg_config.h, then your * changes will be overwritten the next time you run configure. * - * $Id: pg_config.h.in,v 1.29 2002/08/29 08:03:22 ishii Exp $ + * $Id: pg_config.h.in,v 1.30 2002/09/02 01:05:06 tgl Exp $ */ #ifndef PG_CONFIG_H @@ -298,12 +298,6 @@ /* #define ACLDEBUG */ /* #define RTDEBUG */ /* #define GISTDEBUG */ -/* - * DEBUG_TUPLE_ACCESS enables paranoid assertions during - * elimination of oids from the fixed sized part of HeapTupleHeader. - * This is expected to be undef'd after v7.3 release at the latest. - */ -#define DEBUG_TUPLE_ACCESS /* * defining unsafe floats will make float4 and float8 ops faster diff --git a/src/include/storage/bufpage.h b/src/include/storage/bufpage.h index a9fc0f7a2a2..7a6080a1bcd 100644 --- a/src/include/storage/bufpage.h +++ b/src/include/storage/bufpage.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: bufpage.h,v 1.51 2002/08/06 19:37:10 tgl Exp $ + * $Id: bufpage.h,v 1.52 2002/09/02 01:05:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -97,12 +97,20 @@ typedef uint16 LocationIndex; * pd_lower - offset to start of free space. * pd_upper - offset to end of free space. * pd_special - offset to start of special space. - * pd_pagesize - size in bytes. - * Minimum possible page size is perhaps 64B to fit - * page header, opaque space and a minimal tuple; - * of course, in reality you want it much bigger. - * On the high end, we can only support pages up - * to 32KB because lp_off/lp_len are 15 bits. + * pd_pagesize_version - size in bytes and page layout version number. + * + * The page version number and page size are packed together into a single + * uint16 field. This is for historical reasons: before PostgreSQL 7.3, + * there was no concept of a page version number, and doing it this way + * lets us pretend that pre-7.3 databases have page version number zero. + * We constrain page sizes to be multiples of 256, leaving the low eight + * bytes available for a version number. + * + * Minimum possible page size is perhaps 64B to fit page header, opaque space + * and a minimal tuple; of course, in reality you want it much bigger, so + * the constraint on pagesize mod 256 is not an important restriction. + * On the high end, we can only support pages up to 32KB because lp_off/lp_len + * are 15 bits. */ typedef struct PageHeaderData { @@ -116,12 +124,18 @@ typedef struct PageHeaderData LocationIndex pd_lower; /* offset to start of free space */ LocationIndex pd_upper; /* offset to end of free space */ LocationIndex pd_special; /* offset to start of special space */ - uint16 pd_pagesize; + uint16 pd_pagesize_version; ItemIdData pd_linp[1]; /* beginning of line pointer array */ } PageHeaderData; typedef PageHeaderData *PageHeader; +/* + * Page layout version number 0 is for pre-7.3 Postgres releases. The + * current version number is 1, denoting a new HeapTupleHeader layout. + */ +#define PG_PAGE_LAYOUT_VERSION 1 + /* ---------------------------------------------------------------- * page support macros @@ -178,7 +192,7 @@ typedef PageHeaderData *PageHeader; ((char *) (&((PageHeader) (page))->pd_linp[0])) /* ---------------- - * macros to access opaque space + * macros to access page size info * ---------------- */ @@ -203,14 +217,32 @@ typedef PageHeaderData *PageHeader; * however, it can be called on a page for which there is no buffer. */ #define PageGetPageSize(page) \ - ((Size) ((PageHeader) (page))->pd_pagesize) + ((Size) (((PageHeader) (page))->pd_pagesize_version & (uint16) 0xFF00)) /* - * PageSetPageSize - * Sets the page size of a page. + * PageGetPageLayoutVersion + * Returns the page layout version of a page. + * + * this can only be called on a formatted page (unlike + * BufferGetPageSize, which can be called on an unformatted page). + * however, it can be called on a page for which there is no buffer. */ -#define PageSetPageSize(page, size) \ - (((PageHeader) (page))->pd_pagesize = (size)) +#define PageGetPageLayoutVersion(page) \ + (((PageHeader) (page))->pd_pagesize_version & 0x00FF) + +/* + * PageSetPageSizeAndVersion + * Sets the page size and page layout version number of a page. + * + * We could support setting these two values separately, but there's + * no real need for it at the moment. + */ +#define PageSetPageSizeAndVersion(page, size, version) \ +( \ + AssertMacro(((size) & 0xFF00) == (size)), \ + AssertMacro(((version) & 0x00FF) == (version)), \ + ((PageHeader) (page))->pd_pagesize_version = (size) | (version) \ +) /* ---------------- * page special data macros |