提交 a52b4fb1 编写于 作者: T Tom Lane

Adjust creation/destruction of TupleDesc data structure to reduce the

number of palloc calls.  This has a salutory impact on plpgsql operations
with record variables (which create and destroy tupdescs constantly)
and probably helps a bit in some other cases too.
上级 e3d7de6b
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* some of the executor utility code such as "ExecTypeFromTL" should be * some of the executor utility code such as "ExecTypeFromTL" should be
...@@ -31,19 +31,19 @@ ...@@ -31,19 +31,19 @@
#include "utils/typcache.h" #include "utils/typcache.h"
/* ---------------------------------------------------------------- /*
* CreateTemplateTupleDesc * CreateTemplateTupleDesc
* * This function allocates an empty tuple descriptor structure.
* This function allocates and zeros a tuple descriptor structure.
* *
* Tuple type ID information is initially set for an anonymous record type; * Tuple type ID information is initially set for an anonymous record type;
* caller can overwrite this if needed. * caller can overwrite this if needed.
* ----------------------------------------------------------------
*/ */
TupleDesc TupleDesc
CreateTemplateTupleDesc(int natts, bool hasoid) CreateTemplateTupleDesc(int natts, bool hasoid)
{ {
TupleDesc desc; TupleDesc desc;
char *stg;
int attroffset;
/* /*
* sanity checks * sanity checks
...@@ -51,15 +51,33 @@ CreateTemplateTupleDesc(int natts, bool hasoid) ...@@ -51,15 +51,33 @@ CreateTemplateTupleDesc(int natts, bool hasoid)
AssertArg(natts >= 0); AssertArg(natts >= 0);
/* /*
* Allocate enough memory for the tuple descriptor, and zero the * Allocate enough memory for the tuple descriptor, including the
* attrs[] array since TupleDescInitEntry assumes that the array is * attribute rows, and set up the attribute row pointers.
* filled with NULL 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) 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 else
desc->attrs = NULL; desc->attrs = NULL;
...@@ -75,15 +93,16 @@ CreateTemplateTupleDesc(int natts, bool hasoid) ...@@ -75,15 +93,16 @@ CreateTemplateTupleDesc(int natts, bool hasoid)
return desc; return desc;
} }
/* ---------------------------------------------------------------- /*
* CreateTupleDesc * CreateTupleDesc
*
* This function allocates a new TupleDesc pointing to a given * 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; * Tuple type ID information is initially set for an anonymous record type;
* caller can overwrite this if needed. * caller can overwrite this if needed.
* ----------------------------------------------------------------
*/ */
TupleDesc TupleDesc
CreateTupleDesc(int natts, bool hasoid, Form_pg_attribute *attrs) CreateTupleDesc(int natts, bool hasoid, Form_pg_attribute *attrs)
...@@ -106,14 +125,12 @@ CreateTupleDesc(int natts, bool hasoid, Form_pg_attribute *attrs) ...@@ -106,14 +125,12 @@ CreateTupleDesc(int natts, bool hasoid, Form_pg_attribute *attrs)
return desc; return desc;
} }
/* ---------------------------------------------------------------- /*
* CreateTupleDescCopy * CreateTupleDescCopy
*
* This function creates a new TupleDesc by copying from an existing * 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 TupleDesc
CreateTupleDescCopy(TupleDesc tupdesc) CreateTupleDescCopy(TupleDesc tupdesc)
...@@ -121,38 +138,25 @@ CreateTupleDescCopy(TupleDesc tupdesc) ...@@ -121,38 +138,25 @@ CreateTupleDescCopy(TupleDesc tupdesc)
TupleDesc desc; TupleDesc desc;
int i; int i;
desc = (TupleDesc) palloc(sizeof(struct tupleDesc)); desc = CreateTemplateTupleDesc(tupdesc->natts, tupdesc->tdhasoid);
desc->natts = tupdesc->natts;
if (desc->natts > 0) for (i = 0; i < desc->natts; i++)
{ {
desc->attrs = (Form_pg_attribute *) memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_TUPLE_SIZE);
palloc(desc->natts * sizeof(Form_pg_attribute)); desc->attrs[i]->attnotnull = false;
for (i = 0; i < desc->natts; i++) desc->attrs[i]->atthasdef = false;
{
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;
}
} }
else
desc->attrs = NULL;
desc->constr = NULL;
desc->tdtypeid = tupdesc->tdtypeid; desc->tdtypeid = tupdesc->tdtypeid;
desc->tdtypmod = tupdesc->tdtypmod; desc->tdtypmod = tupdesc->tdtypmod;
desc->tdhasoid = tupdesc->tdhasoid;
return desc; return desc;
} }
/* ---------------------------------------------------------------- /*
* CreateTupleDescCopyConstr * CreateTupleDescCopyConstr
*
* This function creates a new TupleDesc by copying from an existing * This function creates a new TupleDesc by copying from an existing
* TupleDesc (including its constraints and defaults) * TupleDesc (including its constraints and defaults).
* ----------------------------------------------------------------
*/ */
TupleDesc TupleDesc
CreateTupleDescCopyConstr(TupleDesc tupdesc) CreateTupleDescCopyConstr(TupleDesc tupdesc)
...@@ -161,20 +165,12 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc) ...@@ -161,20 +165,12 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc)
TupleConstr *constr = tupdesc->constr; TupleConstr *constr = tupdesc->constr;
int i; int i;
desc = (TupleDesc) palloc(sizeof(struct tupleDesc)); desc = CreateTemplateTupleDesc(tupdesc->natts, tupdesc->tdhasoid);
desc->natts = tupdesc->natts;
if (desc->natts > 0) for (i = 0; i < desc->natts; i++)
{ {
desc->attrs = (Form_pg_attribute *) memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_TUPLE_SIZE);
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);
}
} }
else
desc->attrs = NULL;
if (constr) if (constr)
{ {
...@@ -208,12 +204,9 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc) ...@@ -208,12 +204,9 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc)
desc->constr = cpy; desc->constr = cpy;
} }
else
desc->constr = NULL;
desc->tdtypeid = tupdesc->tdtypeid; desc->tdtypeid = tupdesc->tdtypeid;
desc->tdtypmod = tupdesc->tdtypmod; desc->tdtypmod = tupdesc->tdtypmod;
desc->tdhasoid = tupdesc->tdhasoid;
return desc; return desc;
} }
...@@ -226,10 +219,6 @@ FreeTupleDesc(TupleDesc tupdesc) ...@@ -226,10 +219,6 @@ FreeTupleDesc(TupleDesc tupdesc)
{ {
int i; 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)
{ {
if (tupdesc->constr->num_defval > 0) if (tupdesc->constr->num_defval > 0)
...@@ -379,12 +368,10 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2) ...@@ -379,12 +368,10 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
return true; return true;
} }
/* ---------------------------------------------------------------- /*
* TupleDescInitEntry * TupleDescInitEntry
*
* This function initializes a single attribute structure in * This function initializes a single attribute structure in
* a preallocated tuple descriptor. * a previously allocated tuple descriptor.
* ----------------------------------------------------------------
*/ */
void void
TupleDescInitEntry(TupleDesc desc, TupleDescInitEntry(TupleDesc desc,
...@@ -404,18 +391,12 @@ TupleDescInitEntry(TupleDesc desc, ...@@ -404,18 +391,12 @@ TupleDescInitEntry(TupleDesc desc,
AssertArg(PointerIsValid(desc)); AssertArg(PointerIsValid(desc));
AssertArg(attributeNumber >= 1); AssertArg(attributeNumber >= 1);
AssertArg(attributeNumber <= desc->natts); 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 * initialize the attribute fields
*/ */
att = desc->attrs[attributeNumber - 1];
att->attrelid = 0; /* dummy value */ att->attrelid = 0; /* dummy value */
/* /*
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.245 2005/03/04 20:21:05 tgl Exp $ * $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.246 2005/03/07 04:42:16 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -97,14 +97,11 @@ ConstructTupleDescriptor(Relation heapRelation, ...@@ -97,14 +97,11 @@ ConstructTupleDescriptor(Relation heapRelation,
for (i = 0; i < numatts; i++) for (i = 0; i < numatts; i++)
{ {
AttrNumber atnum = indexInfo->ii_KeyAttrNumbers[i]; AttrNumber atnum = indexInfo->ii_KeyAttrNumbers[i];
Form_pg_attribute to; Form_pg_attribute to = indexTupDesc->attrs[i];
HeapTuple tuple; HeapTuple tuple;
Form_pg_type typeTup; Form_pg_type typeTup;
Oid keyType; Oid keyType;
indexTupDesc->attrs[i] = to =
(Form_pg_attribute) palloc0(ATTRIBUTE_TUPLE_SIZE);
if (atnum != 0) if (atnum != 0)
{ {
/* Simple index column */ /* Simple index column */
...@@ -152,6 +149,8 @@ ConstructTupleDescriptor(Relation heapRelation, ...@@ -152,6 +149,8 @@ ConstructTupleDescriptor(Relation heapRelation,
/* Expressional index */ /* Expressional index */
Node *indexkey; Node *indexkey;
MemSet(to, 0, ATTRIBUTE_TUPLE_SIZE);
if (indexpr_item == NULL) /* shouldn't happen */ if (indexpr_item == NULL) /* shouldn't happen */
elog(ERROR, "too few entries in indexprs list"); elog(ERROR, "too few entries in indexprs list");
indexkey = (Node *) lfirst(indexpr_item); indexkey = (Node *) lfirst(indexpr_item);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -491,12 +491,8 @@ RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, ...@@ -491,12 +491,8 @@ RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
elog(ERROR, "invalid attribute number %d for %s", elog(ERROR, "invalid attribute number %d for %s",
attp->attnum, RelationGetRelationName(relation)); attp->attnum, RelationGetRelationName(relation));
relation->rd_att->attrs[attp->attnum - 1] = memcpy(relation->rd_att->attrs[attp->attnum - 1],
(Form_pg_attribute) MemoryContextAlloc(CacheMemoryContext, attp,
ATTRIBUTE_TUPLE_SIZE);
memcpy((char *) (relation->rd_att->attrs[attp->attnum - 1]),
(char *) attp,
ATTRIBUTE_TUPLE_SIZE); ATTRIBUTE_TUPLE_SIZE);
/* Update constraint/default info */ /* Update constraint/default info */
...@@ -1338,9 +1334,8 @@ formrdesc(const char *relationName, Oid relationReltype, ...@@ -1338,9 +1334,8 @@ formrdesc(const char *relationName, Oid relationReltype,
has_not_null = false; has_not_null = false;
for (i = 0; i < natts; i++) for (i = 0; i < natts; i++)
{ {
relation->rd_att->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE); memcpy(relation->rd_att->attrs[i],
memcpy((char *) relation->rd_att->attrs[i], &att[i],
(char *) &att[i],
ATTRIBUTE_TUPLE_SIZE); ATTRIBUTE_TUPLE_SIZE);
has_not_null |= att[i].attnotnull; has_not_null |= att[i].attnotnull;
/* make sure attcacheoff is valid */ /* make sure attcacheoff is valid */
...@@ -3044,9 +3039,8 @@ load_relcache_init_file(void) ...@@ -3044,9 +3039,8 @@ load_relcache_init_file(void)
{ {
if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len)) if ((nread = fread(&len, 1, sizeof(len), fp)) != sizeof(len))
goto read_failed; goto read_failed;
if (len != ATTRIBUTE_TUPLE_SIZE)
rel->rd_att->attrs[i] = (Form_pg_attribute) palloc(len); goto read_failed;
if ((nread = fread(rel->rd_att->attrs[i], 1, len, fp)) != len) if ((nread = fread(rel->rd_att->attrs[i], 1, len, fp)) != len)
goto read_failed; goto read_failed;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -42,13 +42,17 @@ typedef struct tupleConstr ...@@ -42,13 +42,17 @@ typedef struct tupleConstr
} TupleConstr; } TupleConstr;
/* /*
* This structure contains all information (i.e. from Classes * This struct is passed around within the backend to describe the structure
* pg_attribute, pg_attrdef, pg_constraint) for the structure of a tuple. * 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 * Note that only user attributes, not system attributes, are mentioned in
* TupleDesc; with the exception that tdhasoid indicates if OID is present. * 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 * rowtype) then tdtypeid identifies that type and tdtypmod is -1. Otherwise
* tdtypeid is RECORDOID, and tdtypmod can be either -1 for a fully anonymous * 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 * row type, or a value >= 0 to allow the rowtype to be looked up in the
...@@ -56,13 +60,13 @@ typedef struct tupleConstr ...@@ -56,13 +60,13 @@ typedef struct tupleConstr
*/ */
typedef struct tupleDesc typedef struct tupleDesc
{ {
int natts; /* Number of attributes in the tuple */ int natts; /* number of attributes in the tuple */
Form_pg_attribute *attrs; Form_pg_attribute *attrs;
/* attrs[N] is a pointer to the description of Attribute Number N+1. */ /* attrs[N] is a pointer to the description of Attribute Number N+1 */
TupleConstr *constr; TupleConstr *constr; /* constraints, or NULL if none */
Oid tdtypeid; /* composite type ID for tuple type */ Oid tdtypeid; /* composite type ID for tuple type */
int32 tdtypmod; /* typmod 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; } *TupleDesc;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册