CreateTemplateTupleDesc(int natts, bool hasoid)
{
TupleDesc desc;
- char *stg;
- int attroffset;
/*
* sanity checks
/*
* 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.
- *
- * Note: Only the fixed part of pg_attribute rows is included in tuple
- * descriptors, so we only need ATTRIBUTE_FIXED_PART_SIZE space per attr.
- * That might need alignment padding, however.
+ * attribute rows.
*/
- attroffset = sizeof(struct tupleDesc) + natts * sizeof(Form_pg_attribute);
- attroffset = MAXALIGN(attroffset);
- stg = palloc(attroffset + natts * MAXALIGN(ATTRIBUTE_FIXED_PART_SIZE));
- desc = (TupleDesc) stg;
-
- if (natts > 0)
- {
- 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_FIXED_PART_SIZE);
- }
- }
- else
- desc->attrs = NULL;
+ desc = (TupleDesc) palloc(offsetof(struct tupleDesc, attrs) +
+ natts * sizeof(FormData_pg_attribute));
/*
* Initialize other fields of the tupdesc.
/*
* CreateTupleDesc
- * This function allocates a new TupleDesc pointing to a given
+ * This function allocates a new TupleDesc by copying a given
* 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.
*/
CreateTupleDesc(int natts, bool hasoid, Form_pg_attribute *attrs)
{
TupleDesc desc;
+ int i;
- /*
- * sanity checks
- */
- AssertArg(natts >= 0);
+ desc = CreateTemplateTupleDesc(natts, hasoid);
- desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
- desc->attrs = attrs;
- desc->natts = natts;
- desc->constr = NULL;
- desc->tdtypeid = RECORDOID;
- desc->tdtypmod = -1;
- desc->tdhasoid = hasoid;
- desc->tdrefcount = -1; /* assume not reference-counted */
+ for (i = 0; i < natts; ++i)
+ memcpy(TupleDescAttr(desc, i), attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
return desc;
}
for (i = 0; i < desc->natts; i++)
{
- memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
- desc->attrs[i]->attnotnull = false;
- desc->attrs[i]->atthasdef = false;
- desc->attrs[i]->attidentity = '\0';
+ Form_pg_attribute att = TupleDescAttr(desc, i);
+
+ memcpy(att, &tupdesc->attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
+ att->attnotnull = false;
+ att->atthasdef = false;
+ att->attidentity = '\0';
}
desc->tdtypeid = tupdesc->tdtypeid;
typedef struct tupleDesc
{
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; /* 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 */
int tdrefcount; /* reference count, or -1 if not counting */
+ TupleConstr *constr; /* constraints, or NULL if none */
+ /* attrs[N] is the description of Attribute Number N+1 */
+ FormData_pg_attribute attrs[FLEXIBLE_ARRAY_MEMBER];
} *TupleDesc;
/* Accessor for the i'th attribute of tupdesc. */
-#define TupleDescAttr(tupdesc, i) ((tupdesc)->attrs[(i)])
+#define TupleDescAttr(tupdesc, i) (&(tupdesc)->attrs[(i)])
extern TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid);