88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.108 2004/12/31 21:59:07 pgsql Exp $
11+ * $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.109 2005/03/07 04:42:16 tgl Exp $
1212 *
1313 * NOTES
1414 * some of the executor utility code such as "ExecTypeFromTL" should be
3131#include "utils/typcache.h"
3232
3333
34- /* ----------------------------------------------------------------
35- *CreateTemplateTupleDesc
36- *
37- *This function allocates and zeros a tuple descriptor structure.
34+ /*
35+ * CreateTemplateTupleDesc
36+ *This function allocates an empty tuple descriptor structure.
3837 *
3938 * Tuple type ID information is initially set for an anonymous record type;
4039 * caller can overwrite this if needed.
41- * ----------------------------------------------------------------
4240 */
4341TupleDesc
4442CreateTemplateTupleDesc (int natts ,bool hasoid )
4543{
4644TupleDesc desc ;
45+ char * stg ;
46+ int attroffset ;
4747
4848/*
4949 * sanity checks
5050 */
5151AssertArg (natts >=0 );
5252
5353/*
54- * Allocate enough memory for the tuple descriptor, and zero the
55- * attrs[] array since TupleDescInitEntry assumes that the array is
56- * filled with NULL pointers.
54+ * Allocate enough memory for the tuple descriptor, including the
55+ * attribute rows, and set up the attribute row pointers.
56+ *
57+ * Note: we assume that sizeof(struct tupleDesc) is a multiple of
58+ * the struct pointer alignment requirement, and hence we don't need
59+ * to insert alignment padding between the struct and the array of
60+ * attribute row pointers.
5761 */
58- desc = (TupleDesc )palloc (sizeof (struct tupleDesc ));
62+ attroffset = sizeof (struct tupleDesc )+ natts * sizeof (Form_pg_attribute );
63+ attroffset = MAXALIGN (attroffset );
64+ stg = palloc (attroffset + natts * MAXALIGN (ATTRIBUTE_TUPLE_SIZE ));
65+ desc = (TupleDesc )stg ;
5966
6067if (natts > 0 )
61- desc -> attrs = (Form_pg_attribute * )
62- palloc0 (natts * sizeof (Form_pg_attribute ));
68+ {
69+ Form_pg_attribute * attrs ;
70+ int i ;
71+
72+ attrs = (Form_pg_attribute * ) (stg + sizeof (struct tupleDesc ));
73+ desc -> attrs = attrs ;
74+ stg += attroffset ;
75+ for (i = 0 ;i < natts ;i ++ )
76+ {
77+ attrs [i ]= (Form_pg_attribute )stg ;
78+ stg += MAXALIGN (ATTRIBUTE_TUPLE_SIZE );
79+ }
80+ }
6381else
6482desc -> attrs = NULL ;
6583
@@ -75,15 +93,16 @@ CreateTemplateTupleDesc(int natts, bool hasoid)
7593return desc ;
7694}
7795
78- /* ----------------------------------------------------------------
79- *CreateTupleDesc
80- *
96+ /*
97+ * CreateTupleDesc
8198 *This function allocates a new TupleDesc pointing to a given
82- *Form_pg_attribute array
99+ *Form_pg_attribute array.
100+ *
101+ * Note: if the TupleDesc is ever freed, the Form_pg_attribute array
102+ * will not be freed thereby.
83103 *
84104 * Tuple type ID information is initially set for an anonymous record type;
85105 * caller can overwrite this if needed.
86- * ----------------------------------------------------------------
87106 */
88107TupleDesc
89108CreateTupleDesc (int natts ,bool hasoid ,Form_pg_attribute * attrs )
@@ -106,53 +125,38 @@ CreateTupleDesc(int natts, bool hasoid, Form_pg_attribute *attrs)
106125return desc ;
107126}
108127
109- /* ----------------------------------------------------------------
110- *CreateTupleDescCopy
111- *
128+ /*
129+ * CreateTupleDescCopy
112130 *This function creates a new TupleDesc by copying from an existing
113- *TupleDesc
131+ *TupleDesc.
114132 *
115- *!!! Constraints and defaults are not copied !!!
116- * ----------------------------------------------------------------
133+ * !!! Constraints and defaults are not copied !!!
117134 */
118135TupleDesc
119136CreateTupleDescCopy (TupleDesc tupdesc )
120137{
121138TupleDesc desc ;
122139int i ;
123140
124- desc = ( TupleDesc ) palloc ( sizeof ( struct tupleDesc ) );
125- desc -> natts = tupdesc -> natts ;
126- if ( desc -> natts > 0 )
141+ desc = CreateTemplateTupleDesc ( tupdesc -> natts , tupdesc -> tdhasoid );
142+
143+ for ( i = 0 ; i < desc -> natts ; i ++ )
127144{
128- desc -> attrs = (Form_pg_attribute * )
129- palloc (desc -> natts * sizeof (Form_pg_attribute ));
130- for (i = 0 ;i < desc -> natts ;i ++ )
131- {
132- desc -> attrs [i ]= (Form_pg_attribute )palloc (ATTRIBUTE_TUPLE_SIZE );
133- memcpy (desc -> attrs [i ],tupdesc -> attrs [i ],ATTRIBUTE_TUPLE_SIZE );
134- desc -> attrs [i ]-> attnotnull = false;
135- desc -> attrs [i ]-> atthasdef = false;
136- }
145+ memcpy (desc -> attrs [i ],tupdesc -> attrs [i ],ATTRIBUTE_TUPLE_SIZE );
146+ desc -> attrs [i ]-> attnotnull = false;
147+ desc -> attrs [i ]-> atthasdef = false;
137148}
138- else
139- desc -> attrs = NULL ;
140-
141- desc -> constr = NULL ;
142149
143150desc -> tdtypeid = tupdesc -> tdtypeid ;
144151desc -> tdtypmod = tupdesc -> tdtypmod ;
145- desc -> tdhasoid = tupdesc -> tdhasoid ;
146152
147153return desc ;
148154}
149155
150- /* ----------------------------------------------------------------
151- *CreateTupleDescCopyConstr
152- *
156+ /*
157+ * CreateTupleDescCopyConstr
153158 *This function creates a new TupleDesc by copying from an existing
154- *TupleDesc (including its constraints and defaults)
155- * ----------------------------------------------------------------
159+ *TupleDesc (including its constraints and defaults).
156160 */
157161TupleDesc
158162CreateTupleDescCopyConstr (TupleDesc tupdesc )
@@ -161,20 +165,12 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc)
161165TupleConstr * constr = tupdesc -> constr ;
162166int i ;
163167
164- desc = ( TupleDesc ) palloc ( sizeof ( struct tupleDesc ) );
165- desc -> natts = tupdesc -> natts ;
166- if ( desc -> natts > 0 )
168+ desc = CreateTemplateTupleDesc ( tupdesc -> natts , tupdesc -> tdhasoid );
169+
170+ for ( i = 0 ; i < desc -> natts ; i ++ )
167171{
168- desc -> attrs = (Form_pg_attribute * )
169- palloc (desc -> natts * sizeof (Form_pg_attribute ));
170- for (i = 0 ;i < desc -> natts ;i ++ )
171- {
172- desc -> attrs [i ]= (Form_pg_attribute )palloc (ATTRIBUTE_TUPLE_SIZE );
173- memcpy (desc -> attrs [i ],tupdesc -> attrs [i ],ATTRIBUTE_TUPLE_SIZE );
174- }
172+ memcpy (desc -> attrs [i ],tupdesc -> attrs [i ],ATTRIBUTE_TUPLE_SIZE );
175173}
176- else
177- desc -> attrs = NULL ;
178174
179175if (constr )
180176{
@@ -208,12 +204,9 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc)
208204
209205desc -> constr = cpy ;
210206}
211- else
212- desc -> constr = NULL ;
213207
214208desc -> tdtypeid = tupdesc -> tdtypeid ;
215209desc -> tdtypmod = tupdesc -> tdtypmod ;
216- desc -> tdhasoid = tupdesc -> tdhasoid ;
217210
218211return desc ;
219212}
@@ -226,10 +219,6 @@ FreeTupleDesc(TupleDesc tupdesc)
226219{
227220int i ;
228221
229- for (i = 0 ;i < tupdesc -> natts ;i ++ )
230- pfree (tupdesc -> attrs [i ]);
231- if (tupdesc -> attrs )
232- pfree (tupdesc -> attrs );
233222if (tupdesc -> constr )
234223{
235224if (tupdesc -> constr -> num_defval > 0 )
@@ -379,12 +368,10 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
379368return true;
380369}
381370
382- /* ----------------------------------------------------------------
383- *TupleDescInitEntry
384- *
371+ /*
372+ * TupleDescInitEntry
385373 *This function initializes a single attribute structure in
386- *a preallocated tuple descriptor.
387- * ----------------------------------------------------------------
374+ *a previously allocated tuple descriptor.
388375 */
389376void
390377TupleDescInitEntry (TupleDesc desc ,
@@ -404,18 +391,12 @@ TupleDescInitEntry(TupleDesc desc,
404391AssertArg (PointerIsValid (desc ));
405392AssertArg (attributeNumber >=1 );
406393AssertArg (attributeNumber <=desc -> natts );
407- AssertArg (!PointerIsValid (desc -> attrs [attributeNumber - 1 ]));
408-
409- /*
410- * allocate storage for this attribute
411- */
412-
413- att = (Form_pg_attribute )palloc (ATTRIBUTE_TUPLE_SIZE );
414- desc -> attrs [attributeNumber - 1 ]= att ;
415394
416395/*
417396 * initialize the attribute fields
418397 */
398+ att = desc -> attrs [attributeNumber - 1 ];
399+
419400att -> attrelid = 0 ;/* dummy value */
420401
421402/*