From 5fecf226bc1a44bf2240199f7bd7c13fc9f3cc16 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Wed, 13 Aug 2025 19:38:50 +0900
Subject: [PATCH v5 07/15] Split VARATT_EXTERNAL_GET_POINTER for indirect and
 OID TOAST pointers

VARATT_EXTERNAL_GET_POINTER() is renamed to
VARATT_INDIRECT_GET_POINTER() with the external on-disk TOAST pointers
for OID values being now located within toast_external.c, splitting both
concepts completely.
---
 src/include/access/detoast.h               | 16 ++++++++--------
 src/backend/access/common/detoast.c        | 10 +++++-----
 src/backend/access/common/toast_external.c | 21 ++++++++++++++++++++-
 src/backend/utils/adt/expandeddatum.c      |  2 +-
 4 files changed, 34 insertions(+), 15 deletions(-)

diff --git a/src/include/access/detoast.h b/src/include/access/detoast.h
index b3ebad8b7cf9..31e9786848ef 100644
--- a/src/include/access/detoast.h
+++ b/src/include/access/detoast.h
@@ -13,17 +13,17 @@
 #define DETOAST_H
 
 /*
- * Macro to fetch the possibly-unaligned contents of an EXTERNAL datum
- * into a local "varatt_external_*" toast pointer, as supported
- * in toast_external.c and varatt.h.  This should be just a memcpy, but
- * some versions of gcc seem to produce broken code that assumes the datum
- * contents are aligned.  Introducing an explicit intermediate
- * "varattrib_1b_e *" variable seems to fix it.
+ * Macro to fetch the possibly-unaligned contents of an indirect datum
+ * into a local "varatt_indirect" toast pointer, as supported
+ * in varatt.h.  This should be just a memcpy, but some versions of gcc
+ * seem to produce broken code that assumes the datum contents are aligned.
+ * Introducing an explicit intermediate "varattrib_1b_e *" variable seems
+ * to fix it.
  */
-#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr) \
+#define VARATT_INDIRECT_GET_POINTER(toast_pointer, attr) \
 do { \
 	varattrib_1b_e *attre = (varattrib_1b_e *) (attr); \
-	Assert(VARATT_IS_EXTERNAL(attre)); \
+	Assert(VARATT_IS_EXTERNAL_INDIRECT(attre)); \
 	Assert(VARSIZE_EXTERNAL(attre) == sizeof(toast_pointer) + VARHDRSZ_EXTERNAL); \
 	memcpy(&(toast_pointer), VARDATA_EXTERNAL(attre), sizeof(toast_pointer)); \
 } while (0)
diff --git a/src/backend/access/common/detoast.c b/src/backend/access/common/detoast.c
index 8531c27439e4..b645988667f0 100644
--- a/src/backend/access/common/detoast.c
+++ b/src/backend/access/common/detoast.c
@@ -61,7 +61,7 @@ detoast_external_attr(struct varlena *attr)
 		 */
 		struct varatt_indirect redirect;
 
-		VARATT_EXTERNAL_GET_POINTER(redirect, attr);
+		VARATT_INDIRECT_GET_POINTER(redirect, attr);
 		attr = (struct varlena *) redirect.pointer;
 
 		/* nested indirect Datums aren't allowed */
@@ -138,7 +138,7 @@ detoast_attr(struct varlena *attr)
 		 */
 		struct varatt_indirect redirect;
 
-		VARATT_EXTERNAL_GET_POINTER(redirect, attr);
+		VARATT_INDIRECT_GET_POINTER(redirect, attr);
 		attr = (struct varlena *) redirect.pointer;
 
 		/* nested indirect Datums aren't allowed */
@@ -268,7 +268,7 @@ detoast_attr_slice(struct varlena *attr,
 	{
 		struct varatt_indirect redirect;
 
-		VARATT_EXTERNAL_GET_POINTER(redirect, attr);
+		VARATT_INDIRECT_GET_POINTER(redirect, attr);
 
 		/* nested indirect Datums aren't allowed */
 		Assert(!VARATT_IS_EXTERNAL_INDIRECT(redirect.pointer));
@@ -561,7 +561,7 @@ toast_raw_datum_size(Datum value)
 	{
 		struct varatt_indirect toast_pointer;
 
-		VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
+		VARATT_INDIRECT_GET_POINTER(toast_pointer, attr);
 
 		/* nested indirect Datums aren't allowed */
 		Assert(!VARATT_IS_EXTERNAL_INDIRECT(toast_pointer.pointer));
@@ -618,7 +618,7 @@ toast_datum_size(Datum value)
 	{
 		struct varatt_indirect toast_pointer;
 
-		VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
+		VARATT_INDIRECT_GET_POINTER(toast_pointer, attr);
 
 		/* nested indirect Datums aren't allowed */
 		Assert(!VARATT_IS_EXTERNAL_INDIRECT(attr));
diff --git a/src/backend/access/common/toast_external.c b/src/backend/access/common/toast_external.c
index d7bf2f7c69b2..8f58195051cf 100644
--- a/src/backend/access/common/toast_external.c
+++ b/src/backend/access/common/toast_external.c
@@ -26,6 +26,25 @@ static void ondisk_oid_to_external_data(struct varlena *attr,
 										toast_external_data *data);
 static struct varlena *ondisk_oid_create_external_data(toast_external_data data);
 
+/*
+ * Fetch the possibly-unaligned contents of an on-disk external TOAST with
+ * OID values into a local "varatt_external_oid" pointer.
+ *
+ * This should be just a memcpy, but some versions of gcc seem to produce
+ * broken code that assumes the datum contents are aligned.  Introducing
+ * an explicit intermediate "varattrib_1b_e *" variable seems to fix it.
+ */
+static inline void
+varatt_external_oid_get_pointer(varatt_external_oid *toast_pointer,
+								struct varlena *attr)
+{
+	varattrib_1b_e *attre = (varattrib_1b_e *) attr;
+
+	Assert(VARATT_IS_EXTERNAL_ONDISK_OID(attre));
+	Assert(VARSIZE_EXTERNAL(attre) == sizeof(varatt_external_oid) + VARHDRSZ_EXTERNAL);
+	memcpy(toast_pointer, VARDATA_EXTERNAL(attre), sizeof(varatt_external_oid));
+}
+
 /*
  * Decompressed size of an on-disk varlena; but note argument is a struct
  * varatt_external_oid.
@@ -168,7 +187,7 @@ ondisk_oid_to_external_data(struct varlena *attr, toast_external_data *data)
 {
 	varatt_external_oid external;
 
-	VARATT_EXTERNAL_GET_POINTER(external, attr);
+	varatt_external_oid_get_pointer(&external, attr);
 	data->rawsize = external.va_rawsize;
 
 	/*
diff --git a/src/backend/utils/adt/expandeddatum.c b/src/backend/utils/adt/expandeddatum.c
index 6b4b8eaf005c..4c04671d23ed 100644
--- a/src/backend/utils/adt/expandeddatum.c
+++ b/src/backend/utils/adt/expandeddatum.c
@@ -23,7 +23,7 @@
  * Given a Datum that is an expanded-object reference, extract the pointer.
  *
  * This is a bit tedious since the pointer may not be properly aligned;
- * compare VARATT_EXTERNAL_GET_POINTER().
+ * compare VARATT_INDIRECT_GET_POINTER().
  */
 ExpandedObjectHeader *
 DatumGetEOHP(Datum d)
-- 
2.50.0

