diff options
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/access/heapam.h | 10 | ||||
-rw-r--r-- | src/include/access/htup.h | 71 | ||||
-rw-r--r-- | src/include/executor/tuptable.h | 25 | ||||
-rw-r--r-- | src/include/utils/tuplestore.h | 24 |
4 files changed, 112 insertions, 18 deletions
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index e016a527403..7301be4ae34 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.111 2006/05/10 23:18:39 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.112 2006/06/27 02:51:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -217,7 +217,13 @@ extern void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull); extern void heap_deformtuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, char *nulls); -extern void heap_freetuple(HeapTuple tuple); +extern void heap_freetuple(HeapTuple htup); +extern MinimalTuple heap_form_minimal_tuple(TupleDesc tupleDescriptor, + Datum *values, bool *isnull); +extern void heap_free_minimal_tuple(MinimalTuple mtup); +extern MinimalTuple heap_copy_minimal_tuple(MinimalTuple mtup); +extern HeapTuple heap_tuple_from_minimal_tuple(MinimalTuple mtup); +extern MinimalTuple minimal_tuple_from_heap_tuple(HeapTuple htup); extern HeapTuple heap_addheader(int natts, bool withoid, Size structlen, void *structure); diff --git a/src/include/access/htup.h b/src/include/access/htup.h index 57db9f84934..170ad657fb7 100644 --- a/src/include/access/htup.h +++ b/src/include/access/htup.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/htup.h,v 1.82 2006/05/10 23:18:39 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/htup.h,v 1.83 2006/06/27 02:51:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -31,7 +31,7 @@ */ #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 @@ -42,11 +42,10 @@ * 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. * @@ -101,7 +100,6 @@ * 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 @@ -141,6 +139,8 @@ typedef struct HeapTupleHeaderData ItemPointerData t_ctid; /* current TID of this or newer tuple */ + /* Fields below here must match MinimalTupleData! */ + int16 t_natts; /* number of attributes */ uint16 t_infomask; /* various flag bits, see below */ @@ -355,6 +355,62 @@ do { \ /* + * MinimalTuple is an alternate representation that is used for transient + * tuples inside the executor, in places where transaction status information + * is not required, the tuple rowtype is known, and shaving off a few bytes + * is worthwhile because we need to store many tuples. The representation + * is chosen so that tuple access routines can work with either full or + * minimal tuples via a HeapTupleData pointer structure. The access routines + * see no difference, except that they must not access the transaction status + * or t_ctid fields because those aren't there. + * + * For the most part, MinimalTuples should be accessed via TupleTableSlot + * routines. These routines will prevent access to the "system columns" + * and thereby prevent accidental use of the nonexistent fields. + * + * MinimalTupleData contains a length word, some padding, and fields matching + * HeapTupleHeaderData beginning with t_natts. The padding is chosen so that + * offsetof(t_natts) is the same modulo MAXIMUM_ALIGNOF in both structs. + * This makes data alignment rules equivalent in both cases. + * + * When a minimal tuple is accessed via a HeapTupleData pointer, t_data is + * set to point MINIMAL_TUPLE_OFFSET bytes before the actual start of the + * minimal tuple --- that is, where a full tuple matching the minimal tuple's + * data would start. This trick is what makes the structs seem equivalent. + * + * Note that t_hoff is computed the same as in a full tuple, hence it includes + * the MINIMAL_TUPLE_OFFSET distance. t_len does not include that, however. + */ +#define MINIMAL_TUPLE_OFFSET \ + ((offsetof(HeapTupleHeaderData, t_natts) - sizeof(uint32)) / MAXIMUM_ALIGNOF * MAXIMUM_ALIGNOF) +#define MINIMAL_TUPLE_PADDING \ + ((offsetof(HeapTupleHeaderData, t_natts) - sizeof(uint32)) % MAXIMUM_ALIGNOF) + +typedef struct MinimalTupleData +{ + uint32 t_len; /* actual length of minimal tuple */ + + char mt_padding[MINIMAL_TUPLE_PADDING]; + + /* Fields below here must match HeapTupleHeaderData! */ + + 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 */ +} MinimalTupleData; + +typedef MinimalTupleData *MinimalTuple; + + +/* * HeapTupleData is an in-memory data structure that points to a tuple. * * There are several ways in which this data structure is used: @@ -376,6 +432,11 @@ do { \ * it's difficult to tell apart from case #1. It should be used only in * limited contexts where the code knows that case #1 will never apply.) * + * * Separately allocated minimal tuple: t_data points MINIMAL_TUPLE_OFFSET + * bytes before the start of a MinimalTuple. As with the previous case, + * this can't be told apart from case #1 by inspection; code setting up + * or destroying this representation has to know what it's doing. + * * t_len should always be valid, except in the pointer-to-nothing case. * t_self and t_tableOid should be valid if the HeapTupleData points to * a disk buffer, or if it represents a copy of a tuple on disk. They diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h index b506651fbbd..85318351340 100644 --- a/src/include/executor/tuptable.h +++ b/src/include/executor/tuptable.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/executor/tuptable.h,v 1.31 2006/06/16 18:42:23 tgl Exp $ + * $PostgreSQL: pgsql/src/include/executor/tuptable.h,v 1.32 2006/06/27 02:51:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -23,7 +23,8 @@ * independent TupleTableSlots. There are several cases we need to handle: * 1. physical tuple in a disk buffer page * 2. physical tuple constructed in palloc'ed memory - * 3. "virtual" tuple consisting of Datum/isnull arrays + * 3. "minimal" physical tuple constructed in palloc'ed memory + * 4. "virtual" tuple consisting of Datum/isnull arrays * * The first two cases are similar in that they both deal with "materialized" * tuples, but resource management is different. For a tuple in a disk page @@ -31,6 +32,11 @@ * to the tuple is dropped; while for a palloc'd tuple we usually want the * tuple pfree'd when the TupleTableSlot's reference is dropped. * + * A "minimal" tuple is handled similarly to a palloc'd regular tuple. + * At present, minimal tuples never are stored in buffers, so there is no + * parallel to case 1. Note that a minimal tuple has no "system columns". + * (Actually, it could have an OID, but we have no need to access the OID.) + * * A "virtual" tuple is an optimization used to minimize physical data * copying in a nest of plan nodes. Any pass-by-reference Datums in the * tuple point to storage that is not directly associated with the @@ -83,6 +89,15 @@ * tts_values/tts_isnull are allocated when a descriptor is assigned to the * slot; they are of length equal to the descriptor's natts. * + * tts_mintuple must always be NULL if the slot does not hold a "minimal" + * tuple. When it does, tts_mintuple points to the actual MinimalTupleData + * object (the thing to be pfree'd if tts_shouldFree is true). In this case + * tts_tuple points at tts_minhdr and the fields of that are set correctly + * for access to the minimal tuple; in particular, tts_minhdr.t_data points + * MINIMAL_TUPLE_OFFSET bytes before tts_mintuple. (tts_mintuple is therefore + * redundant, but for code simplicity we store it explicitly anyway.) This + * case otherwise behaves identically to the regular-physical-tuple case. + * * tts_slow/tts_off are saved state for slot_deform_tuple, and should not * be touched by any other code. *---------- @@ -100,6 +115,8 @@ typedef struct TupleTableSlot int tts_nvalid; /* # of valid values in tts_values */ Datum *tts_values; /* current per-attribute values */ bool *tts_isnull; /* current per-attribute isnull flags */ + MinimalTuple tts_mintuple; /* set if it's a minimal tuple, else NULL */ + HeapTupleData tts_minhdr; /* workspace if it's a minimal tuple */ long tts_off; /* saved state for slot_deform_tuple */ } TupleTableSlot; @@ -133,10 +150,14 @@ extern TupleTableSlot *ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree); +extern TupleTableSlot *ExecStoreMinimalTuple(MinimalTuple mtup, + TupleTableSlot *slot, + bool shouldFree); extern TupleTableSlot *ExecClearTuple(TupleTableSlot *slot); extern TupleTableSlot *ExecStoreVirtualTuple(TupleTableSlot *slot); extern TupleTableSlot *ExecStoreAllNullTuple(TupleTableSlot *slot); extern HeapTuple ExecCopySlotTuple(TupleTableSlot *slot); +extern MinimalTuple ExecCopySlotMinimalTuple(TupleTableSlot *slot); extern HeapTuple ExecFetchSlotTuple(TupleTableSlot *slot); extern HeapTuple ExecMaterializeSlot(TupleTableSlot *slot); extern TupleTableSlot *ExecCopySlot(TupleTableSlot *dstslot, diff --git a/src/include/utils/tuplestore.h b/src/include/utils/tuplestore.h index a671bf438ff..62279344144 100644 --- a/src/include/utils/tuplestore.h +++ b/src/include/utils/tuplestore.h @@ -14,17 +14,23 @@ * A temporary file is used to handle the data if it exceeds the * space limit specified by the caller. * + * Beginning in Postgres 8.2, what is stored is just MinimalTuples; + * callers cannot expect valid system columns in regurgitated tuples. + * Also, we have changed the API to return tuples in TupleTableSlots, + * so that there is a check to prevent attempted access to system columns. + * * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/tuplestore.h,v 1.17 2006/03/05 15:59:08 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/tuplestore.h,v 1.18 2006/06/27 02:51:40 tgl Exp $ * *------------------------------------------------------------------------- */ #ifndef TUPLESTORE_H #define TUPLESTORE_H -#include "access/htup.h" +#include "executor/tuptable.h" + /* Tuplestorestate is an opaque type whose details are not known outside * tuplestore.c. @@ -32,7 +38,7 @@ typedef struct Tuplestorestate Tuplestorestate; /* - * Currently we only need to store HeapTuples, but it would be easy + * Currently we only need to store MinimalTuples, but it would be easy * to support the same behavior for IndexTuples and/or bare Datums. */ @@ -40,17 +46,17 @@ extern Tuplestorestate *tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes); -extern void tuplestore_puttuple(Tuplestorestate *state, void *tuple); +extern void tuplestore_puttupleslot(Tuplestorestate *state, + TupleTableSlot *slot); +extern void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple); /* tuplestore_donestoring() used to be required, but is no longer used */ #define tuplestore_donestoring(state) ((void) 0) /* backwards scan is only allowed if randomAccess was specified 'true' */ -extern void *tuplestore_gettuple(Tuplestorestate *state, bool forward, - bool *should_free); - -#define tuplestore_getheaptuple(state, forward, should_free) \ - ((HeapTuple) tuplestore_gettuple(state, forward, should_free)) +extern bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, + TupleTableSlot *slot); +extern bool tuplestore_advance(Tuplestorestate *state, bool forward); extern void tuplestore_end(Tuplestorestate *state); |