aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/access/common/tupdesc.c71
-rw-r--r--src/include/access/tupdesc.h29
2 files changed, 69 insertions, 31 deletions
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index 9fec6e33865..8cff6236e19 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -57,17 +57,13 @@ ResourceOwnerForgetTupleDesc(ResourceOwner owner, TupleDesc tupdesc)
}
/*
- * populate_compact_attribute
- * Fill in the corresponding CompactAttribute element from the
- * Form_pg_attribute for the given attribute number. This must be called
- * whenever a change is made to a Form_pg_attribute in the TupleDesc.
+ * populate_compact_attribute_internal
+ * Helper function for populate_compact_attribute()
*/
-void
-populate_compact_attribute(TupleDesc tupdesc, int attnum)
+static inline void
+populate_compact_attribute_internal(Form_pg_attribute src,
+ CompactAttribute *dst)
{
- Form_pg_attribute src = TupleDescAttr(tupdesc, attnum);
- CompactAttribute *dst = &tupdesc->compact_attrs[attnum];
-
memset(dst, 0, sizeof(CompactAttribute));
dst->attcacheoff = -1;
@@ -102,6 +98,63 @@ populate_compact_attribute(TupleDesc tupdesc, int attnum)
}
/*
+ * populate_compact_attribute
+ * Fill in the corresponding CompactAttribute element from the
+ * Form_pg_attribute for the given attribute number. This must be called
+ * whenever a change is made to a Form_pg_attribute in the TupleDesc.
+ */
+void
+populate_compact_attribute(TupleDesc tupdesc, int attnum)
+{
+ Form_pg_attribute src = TupleDescAttr(tupdesc, attnum);
+ CompactAttribute *dst;
+
+ /*
+ * Don't use TupleDescCompactAttr to prevent infinite recursion in assert
+ * builds.
+ */
+ dst = &tupdesc->compact_attrs[attnum];
+
+ populate_compact_attribute_internal(src, dst);
+}
+
+#ifdef USE_ASSERT_CHECKING
+/*
+ * verify_compact_attribute
+ * In Assert enabled builds, we verify that the CompactAttribute is
+ * populated correctly. This helps find bugs in places such as ALTER
+ * TABLE where code makes changes to the FormData_pg_attribute but
+ * forgets to call populate_compact_attribute().
+ *
+ * This is used in TupleDescCompactAttr(), but declared here to allow access
+ * to populate_compact_attribute_internal().
+ */
+void
+verify_compact_attribute(TupleDesc tupdesc, int attnum)
+{
+ CompactAttribute *cattr = &tupdesc->compact_attrs[attnum];
+ Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum);
+ CompactAttribute tmp;
+
+ /*
+ * Populate the temporary CompactAttribute from the corresponding
+ * Form_pg_attribute
+ */
+ populate_compact_attribute_internal(attr, &tmp);
+
+ /*
+ * Make the attcacheoff match since it's been reset to -1 by
+ * populate_compact_attribute_internal.
+ */
+ tmp.attcacheoff = cattr->attcacheoff;
+
+ /* Check the freshly populated CompactAttribute matches the TupleDesc's */
+ Assert(memcmp(&tmp, cattr, sizeof(CompactAttribute)) == 0);
+}
+#endif
+
+
+/*
* CreateTemplateTupleDesc
* This function allocates an empty tuple descriptor structure.
*
diff --git a/src/include/access/tupdesc.h b/src/include/access/tupdesc.h
index e61a4affa46..05ccd2465fc 100644
--- a/src/include/access/tupdesc.h
+++ b/src/include/access/tupdesc.h
@@ -158,6 +158,10 @@ TupleDescAttr(TupleDesc tupdesc, int i)
#undef TupleDescAttrAddress
+#ifdef USE_ASSERT_CHECKING
+extern void verify_compact_attribute(TupleDesc, int attnum);
+#endif
+
/*
* Accessor for the i'th CompactAttribute element of tupdesc.
*/
@@ -165,30 +169,11 @@ static inline CompactAttribute *
TupleDescCompactAttr(TupleDesc tupdesc, int i)
{
CompactAttribute *cattr = &tupdesc->compact_attrs[i];
-#ifdef USE_ASSERT_CHECKING
- CompactAttribute snapshot;
- /*
- * In Assert enabled builds we verify that the CompactAttribute is
- * populated correctly. This helps find bugs in places such as ALTER
- * TABLE where code makes changes to the FormData_pg_attribute but forgets
- * to call populate_compact_attribute.
- */
-
- /*
- * Take a snapshot of how the CompactAttribute is now before calling
- * populate_compact_attribute to make it up-to-date with the
- * FormData_pg_attribute.
- */
- memcpy(&snapshot, cattr, sizeof(CompactAttribute));
-
- populate_compact_attribute(tupdesc, i);
-
- /* reset attcacheoff back to what it was */
- cattr->attcacheoff = snapshot.attcacheoff;
+#ifdef USE_ASSERT_CHECKING
- /* Ensure the snapshot matches the freshly populated CompactAttribute */
- Assert(memcmp(&snapshot, cattr, sizeof(CompactAttribute)) == 0);
+ /* Check that the CompactAttribute is correctly populated */
+ verify_compact_attribute(tupdesc, i);
#endif
return cattr;