*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.108 2004/12/31 21:59:07 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.109 2005/03/07 04:42:16 tgl Exp $
*
* NOTES
* some of the executor utility code such as "ExecTypeFromTL" should be
#include "utils/typcache.h"
-/* ----------------------------------------------------------------
- * CreateTemplateTupleDesc
- *
- * This function allocates and zeros a tuple descriptor structure.
+/*
+ * CreateTemplateTupleDesc
+ * This function allocates an empty tuple descriptor structure.
*
* Tuple type ID information is initially set for an anonymous record type;
* caller can overwrite this if needed.
- * ----------------------------------------------------------------
*/
TupleDesc
CreateTemplateTupleDesc(int natts, bool hasoid)
{
TupleDesc desc;
+ char *stg;
+ int attroffset;
/*
* sanity checks
AssertArg(natts >= 0);
/*
- * Allocate enough memory for the tuple descriptor, and zero the
- * attrs[] array since TupleDescInitEntry assumes that the array is
- * filled with NULL pointers.
+ * Allocate enough memory for the tuple descriptor, including the
+ * attribute rows, and set up the attribute row pointers.
+ *
+ * Note: we assume that sizeof(struct tupleDesc) is a multiple of
+ * the struct pointer alignment requirement, and hence we don't need
+ * to insert alignment padding between the struct and the array of
+ * attribute row pointers.
*/
- desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
+ attroffset = sizeof(struct tupleDesc) + natts * sizeof(Form_pg_attribute);
+ attroffset = MAXALIGN(attroffset);
+ stg = palloc(attroffset + natts * MAXALIGN(ATTRIBUTE_TUPLE_SIZE));
+ desc = (TupleDesc) stg;
if (natts > 0)
- desc->attrs = (Form_pg_attribute *)
- palloc0(natts * sizeof(Form_pg_attribute));
+ {
+ Form_pg_attribute *attrs;
+ int i;
+
+ attrs = (Form_pg_attribute *) (stg + sizeof(struct tupleDesc));
+ desc->attrs = attrs;
+ stg += attroffset;
+ for (i = 0; i < natts; i++)
+ {
+ attrs[i] = (Form_pg_attribute) stg;
+ stg += MAXALIGN(ATTRIBUTE_TUPLE_SIZE);
+ }
+ }
else
desc->attrs = NULL;
return desc;
}
-/* ----------------------------------------------------------------
- * CreateTupleDesc
- *
+/*
+ * CreateTupleDesc
* This function allocates a new TupleDesc pointing to a given
- * Form_pg_attribute array
+ * Form_pg_attribute array.
+ *
+ * Note: if the TupleDesc is ever freed, the Form_pg_attribute array
+ * will not be freed thereby.
*
* Tuple type ID information is initially set for an anonymous record type;
* caller can overwrite this if needed.
- * ----------------------------------------------------------------
*/
TupleDesc
CreateTupleDesc(int natts, bool hasoid, Form_pg_attribute *attrs)
return desc;
}
-/* ----------------------------------------------------------------
- * CreateTupleDescCopy
- *
+/*
+ * CreateTupleDescCopy
* This function creates a new TupleDesc by copying from an existing
- * TupleDesc
+ * TupleDesc.
*
- * !!! Constraints and defaults are not copied !!!
- * ----------------------------------------------------------------
+ * !!! Constraints and defaults are not copied !!!
*/
TupleDesc
CreateTupleDescCopy(TupleDesc tupdesc)
TupleDesc desc;
int i;
- desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
- desc->natts = tupdesc->natts;
- if (desc->natts > 0)
+ desc = CreateTemplateTupleDesc(tupdesc->natts, tupdesc->tdhasoid);
+
+ for (i = 0; i < desc->natts; i++)
{
- desc->attrs = (Form_pg_attribute *)
- palloc(desc->natts * sizeof(Form_pg_attribute));
- for (i = 0; i < desc->natts; i++)
- {
- desc->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
- memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_TUPLE_SIZE);
- desc->attrs[i]->attnotnull = false;
- desc->attrs[i]->atthasdef = false;
- }
+ memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_TUPLE_SIZE);
+ desc->attrs[i]->attnotnull = false;
+ desc->attrs[i]->atthasdef = false;
}
- else
- desc->attrs = NULL;
-
- desc->constr = NULL;
desc->tdtypeid = tupdesc->tdtypeid;
desc->tdtypmod = tupdesc->tdtypmod;
- desc->tdhasoid = tupdesc->tdhasoid;
return desc;
}
-/* ----------------------------------------------------------------
- * CreateTupleDescCopyConstr
- *
+/*
+ * CreateTupleDescCopyConstr
* This function creates a new TupleDesc by copying from an existing
- * TupleDesc (including its constraints and defaults)
- * ----------------------------------------------------------------
+ * TupleDesc (including its constraints and defaults).
*/
TupleDesc
CreateTupleDescCopyConstr(TupleDesc tupdesc)
TupleConstr *constr = tupdesc->constr;
int i;
- desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
- desc->natts = tupdesc->natts;
- if (desc->natts > 0)
+ desc = CreateTemplateTupleDesc(tupdesc->natts, tupdesc->tdhasoid);
+
+ for (i = 0; i < desc->natts; i++)
{
- desc->attrs = (Form_pg_attribute *)
- palloc(desc->natts * sizeof(Form_pg_attribute));
- for (i = 0; i < desc->natts; i++)
- {
- desc->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
- memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_TUPLE_SIZE);
- }
+ memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_TUPLE_SIZE);
}
- else
- desc->attrs = NULL;
if (constr)
{
desc->constr = cpy;
}
- else
- desc->constr = NULL;
desc->tdtypeid = tupdesc->tdtypeid;
desc->tdtypmod = tupdesc->tdtypmod;
- desc->tdhasoid = tupdesc->tdhasoid;
return desc;
}
{
int i;
- for (i = 0; i < tupdesc->natts; i++)
- pfree(tupdesc->attrs[i]);
- if (tupdesc->attrs)
- pfree(tupdesc->attrs);
if (tupdesc->constr)
{
if (tupdesc->constr->num_defval > 0)
return true;
}
-/* ----------------------------------------------------------------
- * TupleDescInitEntry
- *
+/*
+ * TupleDescInitEntry
* This function initializes a single attribute structure in
- * a preallocated tuple descriptor.
- * ----------------------------------------------------------------
+ * a previously allocated tuple descriptor.
*/
void
TupleDescInitEntry(TupleDesc desc,
AssertArg(PointerIsValid(desc));
AssertArg(attributeNumber >= 1);
AssertArg(attributeNumber <= desc->natts);
- AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1]));
-
- /*
- * allocate storage for this attribute
- */
-
- att = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
- desc->attrs[attributeNumber - 1] = att;
/*
* initialize the attribute fields
*/
+ att = desc->attrs[attributeNumber - 1];
+
att->attrelid = 0; /* dummy value */
/*
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.215 2005/01/10 20:02:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.216 2005/03/07 04:42:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
elog(ERROR, "invalid attribute number %d for %s",
attp->attnum, RelationGetRelationName(relation));
- relation->rd_att->attrs[attp->attnum - 1] =
- (Form_pg_attribute) MemoryContextAlloc(CacheMemoryContext,
- ATTRIBUTE_TUPLE_SIZE);
-
- memcpy((char *) (relation->rd_att->attrs[attp->attnum - 1]),
- (char *) attp,
+ memcpy(relation->rd_att->attrs[attp->attnum - 1],
+ attp,
ATTRIBUTE_TUPLE_SIZE);
/* Update constraint/default info */
has_not_null = false;
for (i = 0; i < natts; i++)
{
- relation->rd_att->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
- memcpy((char *) relation->rd_att->attrs[i],
- (char *) &att[i],
+ memcpy(relation->rd_att->attrs[i],
+ &att[i],
ATTRIBUTE_TUPLE_SIZE);
has_not_null |= att[i].attnotnull;
/* make sure attcacheoff is valid */
{
if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
goto read_failed;
-
- rel->rd_att->attrs[i] = (Form_pg_attribute) palloc(len);
-
+ if (len != ATTRIBUTE_TUPLE_SIZE)
+ goto read_failed;
if ((nread = fread(rel->rd_att->attrs[i], 1, len, fp)) != len)
goto read_failed;
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/tupdesc.h,v 1.46 2004/12/31 22:03:21 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/access/tupdesc.h,v 1.47 2005/03/07 04:42:17 tgl Exp $
*
*-------------------------------------------------------------------------
*/
} TupleConstr;
/*
- * This structure contains all information (i.e. from Classes
- * pg_attribute, pg_attrdef, pg_constraint) for the structure of a tuple.
+ * This struct is passed around within the backend to describe the structure
+ * of tuples. For tuples coming from on-disk relations, the information is
+ * collected from the pg_attribute, pg_attrdef, and pg_constraint catalogs.
+ * Transient row types (such as the result of a join query) have anonymous
+ * TupleDesc structs that generally omit any constraint info; therefore the
+ * structure is designed to let the constraints be omitted efficiently.
*
* 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
+ * If the tupdesc 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
*/
typedef struct tupleDesc
{
- int natts; /* Number of attributes in the tuple */
+ int natts; /* number of attributes in the tuple */
Form_pg_attribute *attrs;
- /* attrs[N] is a pointer to the description of Attribute Number N+1. */
- TupleConstr *constr;
+ /* attrs[N] is a pointer to the description of Attribute Number N+1 */
+ TupleConstr *constr; /* constraints, or NULL if none */
Oid tdtypeid; /* composite type ID for tuple type */
int32 tdtypmod; /* typmod for tuple type */
- bool tdhasoid; /* Tuple has oid attribute in its header */
+ bool tdhasoid; /* tuple has oid attribute in its header */
} *TupleDesc;