Re: TupleDescCopy doesn't clear atthasdef, attnotnull, attidentity - Mailing list pgsql-hackers
From | Tom Lane |
---|---|
Subject | Re: TupleDescCopy doesn't clear atthasdef, attnotnull, attidentity |
Date | |
Msg-id | 31310.1515020488@sss.pgh.pa.us Whole thread Raw |
In response to | TupleDescCopy doesn't clear atthasdef, attnotnull, attidentity (Thomas Munro <thomas.munro@enterprisedb.com>) |
Responses |
Re: TupleDescCopy doesn't clear atthasdef, attnotnull, attidentity
Re: TupleDescCopy doesn't clear atthasdef, attnotnull, attidentity |
List | pgsql-hackers |
Thomas Munro <thomas.munro@enterprisedb.com> writes: > Andrew Gierth complained off-list that TupleDescCopy() doesn't clear > atthasdef. Yeah, that's an oversight. The function is new in commit > cc5f81366c36 and was written by me to support "flat" (pointer-free) > tuple descriptors for use in DSM. Following the example of > CreateTupleDescCopy() I think it should also clear attnotnull and > attidentity. Please see attached. I've pushed this with some editorialization. I added some comments, and noting that you have TupleDescCopy() copying the entire attribute array in one memcpy, I propagated that same approach into CreateTupleDescCopy and CreateTupleDescCopyConstr. This should make things a bit faster since memcpy can spend more time in its maximum-stride loop. The reason I note this explicitly is that I don't find it to be entirely safe. If ATTRIBUTE_FIXED_PART_SIZE were less than sizeof(FormData_pg_attribute) due to alignment padding at the end of the struct, I think we would get some valgrind complaints about copying uninitialized data, since there are code paths in which only the first ATTRIBUTE_FIXED_PART_SIZE bytes of each array entry get filled in. Now, currently I don't think there's any padding there anyway on any platform we support. But if we're going to do things like this, I think that we ought to explicitly make ATTRIBUTE_FIXED_PART_SIZE the same as sizeof(FormData_pg_attribute). Hence, I propose the attached follow-on patch. regards, tom lane diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c index f1f4423..67d3d3d 100644 *** a/src/backend/access/common/tupdesc.c --- b/src/backend/access/common/tupdesc.c *************** CreateTemplateTupleDesc(int natts, bool *** 57,65 **** * since we declare the array elements as FormData_pg_attribute for * notational convenience. However, we only guarantee that the first * ATTRIBUTE_FIXED_PART_SIZE bytes of each entry are valid; most code that ! * copies tupdesc entries around copies just that much. In principle that ! * could be less due to trailing padding, although with the current ! * definition of pg_attribute there probably isn't any padding. */ desc = (TupleDesc) palloc(offsetof(struct tupleDesc, attrs) + natts * sizeof(FormData_pg_attribute)); --- 57,69 ---- * since we declare the array elements as FormData_pg_attribute for * notational convenience. However, we only guarantee that the first * ATTRIBUTE_FIXED_PART_SIZE bytes of each entry are valid; most code that ! * copies tupdesc entries around copies just that much. Currently, that ! * symbol is just defined as sizeof(FormData_pg_attribute) anyway, so this ! * distinction is somewhat academic. If there were any trailing padding ! * space in FormData_pg_attribute, it'd be possible to define ! * ATTRIBUTE_FIXED_PART_SIZE to omit it, but that might cause complaints ! * from valgrind about copying uninitialized padding bytes, so it seems ! * best to keep them the same. */ desc = (TupleDesc) palloc(offsetof(struct tupleDesc, attrs) + natts * sizeof(FormData_pg_attribute)); diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h index 6104254..739e784 100644 *** a/src/include/catalog/pg_attribute.h --- b/src/include/catalog/pg_attribute.h *************** CATALOG(pg_attribute,1249) BKI_BOOTSTRAP *** 175,183 **** * guaranteed-not-null part of a pg_attribute row. This is in fact as much * of the row as gets copied into tuple descriptors, so don't expect you * can access fields beyond attcollation except in a real tuple! */ #define ATTRIBUTE_FIXED_PART_SIZE \ ! (offsetof(FormData_pg_attribute,attcollation) + sizeof(Oid)) /* ---------------- * Form_pg_attribute corresponds to a pointer to a tuple with --- 175,188 ---- * guaranteed-not-null part of a pg_attribute row. This is in fact as much * of the row as gets copied into tuple descriptors, so don't expect you * can access fields beyond attcollation except in a real tuple! + * + * Since the introduction of CATALOG_VARLEN, this can just be defined as + * sizeof(FormData_pg_attribute). It's possible that that would include + * some trailing alignment padding, but that's harmless (and anyway there + * is no such padding given the current contents of pg_attribute). */ #define ATTRIBUTE_FIXED_PART_SIZE \ ! sizeof(FormData_pg_attribute) /* ---------------- * Form_pg_attribute corresponds to a pointer to a tuple with
pgsql-hackers by date: