diff options
| author | Tom Lane | 2004-04-01 21:28:47 +0000 |
|---|---|---|
| committer | Tom Lane | 2004-04-01 21:28:47 +0000 |
| commit | 375369acd1c621bdc683c58bc9c31d4e79d14849 (patch) | |
| tree | f29974842cea4105c92da6031bac736ddf5f833a /src/include/access | |
| parent | 8590a62b75d3dba24609eb46b34fac13ed881d9e (diff) | |
Replace TupleTableSlot convention for whole-row variables and function
results with tuples as ordinary varlena Datums. This commit does not
in itself do much for us, except eliminate the horrid memory leak
associated with evaluation of whole-row variables. However, it lays the
groundwork for allowing composite types as table columns, and perhaps
some other useful features as well. Per my proposal of a few days ago.
Diffstat (limited to 'src/include/access')
| -rw-r--r-- | src/include/access/heapam.h | 7 | ||||
| -rw-r--r-- | src/include/access/htup.h | 291 | ||||
| -rw-r--r-- | src/include/access/tupdesc.h | 16 |
3 files changed, 192 insertions, 122 deletions
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index c6579ea2462..9f91d81107d 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.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/heapam.h,v 1.87 2004/03/11 01:47:41 ishii Exp $ + * $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.88 2004/04/01 21:28:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -111,11 +111,12 @@ extern Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, fastgetattr((tup), (attnum), (tupleDesc), (isnull)) \ ) \ : \ - heap_getsysattr((tup), (attnum), (isnull)) \ + heap_getsysattr((tup), (attnum), (tupleDesc), (isnull)) \ ) \ ) -extern Datum heap_getsysattr(HeapTuple tup, int attnum, bool *isnull); +extern Datum heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, + bool *isnull); /* ---------------- 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 */ diff --git a/src/include/access/tupdesc.h b/src/include/access/tupdesc.h index bf4e3aa1055..c7e560c0c65 100644 --- a/src/include/access/tupdesc.h +++ b/src/include/access/tupdesc.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/tupdesc.h,v 1.42 2003/11/29 22:40:55 pgsql Exp $ + * $PostgreSQL: pgsql/src/include/access/tupdesc.h,v 1.43 2004/04/01 21:28:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -44,6 +44,15 @@ typedef struct tupleConstr /* * This structure contains all information (i.e. from Classes * pg_attribute, pg_attrdef, pg_constraint) for the structure of a tuple. + * + * Note that only user attributes, not system attributes, are mentioned in + * TupleDesc; with the exception that tdhasoid indicates if OID is present. + * + * If the tuple is known to correspond to a named rowtype (such as a table's + * rowtype) then tdtypeid identifies that type and tdtypmod is -1. Otherwise + * tdtypeid is RECORDOID, and tdtypmod can be either -1 for a fully anonymous + * row type, or a value >= 0 to allow the rowtype to be looked up in the + * typcache.c type cache. */ typedef struct tupleDesc { @@ -51,6 +60,8 @@ typedef struct tupleDesc Form_pg_attribute *attrs; /* attrs[N] is a pointer to the description of Attribute Number N+1. */ TupleConstr *constr; + Oid tdtypeid; /* composite type ID for tuple type */ + int32 tdtypmod; /* typmod for tuple type */ bool tdhasoid; /* Tuple has oid attribute in its header */ } *TupleDesc; @@ -73,8 +84,7 @@ extern void TupleDescInitEntry(TupleDesc desc, const char *attributeName, Oid oidtypeid, int32 typmod, - int attdim, - bool attisset); + int attdim); extern TupleDesc BuildDescForRelation(List *schema); |
