Thomas Munro <[email protected]> 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