From a7a7e9d7106d87fd416113d84ebc1e4172f2468f Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sat, 9 Aug 2025 12:04:44 -0400
Subject: [PATCH v1 2/3] Grab the low-hanging fruit from forcing sizeof(Datum)
 to 8.

Remove conditionally-compiled code for smaller Datum widths.
I also fixed up a few more places that were not using
DatumGetIntXX where they should.

One thing I remembered while preparing this part is that SP-GiST
stores pass-by-value prefix keys as Datums, so that the on-disk
representation depends on sizeof(Datum).  That's even more
unfortunate than the existing commentary makes it out to be,
because now there is a hazard that the change of sizeof(Datum)
will break SP-GiST indexes on 32-bit machines.  It appears that
there are no existing SP-GiST opclasses that are actually
affected; and if there are some that I didn't find, the number
of installations that are using them on 32-bit machines is
doubtless tiny.  So I'm proceeding on the assumption that we
can get away with this, but it's something to worry about.

(gininsert.c looks like it has a similar problem, but it's okay
because the "tuples" it's constructing are just transient data
within the tuplesort step.  That's pretty poorly documented
though, so I added some comments.)

Discussion: https://postgr.es/m/1749799.1752797397@sss.pgh.pa.us
---
 doc/src/sgml/xfunc.sgml                |   3 +-
 src/backend/access/gin/gininsert.c     |   5 +-
 src/backend/access/gist/gistproc.c     |  10 +--
 src/backend/access/nbtree/nbtcompare.c |  20 -----
 src/backend/catalog/pg_type.c          |   2 -
 src/backend/utils/adt/mac.c            |  27 +++----
 src/backend/utils/adt/network.c        |   8 +-
 src/backend/utils/adt/numeric.c        | 106 ++-----------------------
 src/backend/utils/adt/timestamp.c      |  21 -----
 src/backend/utils/adt/uuid.c           |   6 +-
 src/backend/utils/adt/varlena.c        |  12 +--
 src/backend/utils/sort/tuplesort.c     |   8 --
 src/include/access/gin_tuple.h         |   4 +-
 src/include/access/spgist_private.h    |  10 ++-
 src/include/access/tupmacs.h           |   4 -
 src/include/port/pg_bswap.h            |  15 +---
 src/include/utils/sortsupport.h        |   4 -
 17 files changed, 44 insertions(+), 221 deletions(-)

diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index 30219f432d9..f116d0648e5 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -2051,8 +2051,7 @@ PG_MODULE_MAGIC_EXT(
     </para>
 
     <para>
-     By-value  types  can  only be 1, 2, or 4 bytes in length
-     (also 8 bytes, if <literal>sizeof(Datum)</literal> is 8 on your machine).
+     By-value types can only be 1, 2, 4, or 8 bytes in length.
      You should be careful to define your types such that they will be the
      same size (in bytes) on all architectures.  For example, the
      <literal>long</literal> type is dangerous because it is 4 bytes on some
diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c
index 47b1898a064..e9d4b27427e 100644
--- a/src/backend/access/gin/gininsert.c
+++ b/src/backend/access/gin/gininsert.c
@@ -2189,7 +2189,10 @@ typedef struct
  * we simply copy the whole Datum, so that we don't have to care about stuff
  * like endianess etc. We could make it a little bit smaller, but it's not
  * worth it - it's a tiny fraction of the data, and we need to MAXALIGN the
- * start of the TID list anyway. So we wouldn't save anything.
+ * start of the TID list anyway. So we wouldn't save anything. (This would
+ * not be a good idea for the permanent in-index data, since we'd prefer
+ * that that not depend on sizeof(Datum). But this is just a transient
+ * representation to use while sorting the data.)
  *
  * The TID list is serialized as compressed - it's highly compressible, and
  * we already have ginCompressPostingList for this purpose. The list may be
diff --git a/src/backend/access/gist/gistproc.c b/src/backend/access/gist/gistproc.c
index 392163cb229..a6ab7db5465 100644
--- a/src/backend/access/gist/gistproc.c
+++ b/src/backend/access/gist/gistproc.c
@@ -1707,8 +1707,8 @@ gist_bbox_zorder_cmp(Datum a, Datum b, SortSupport ssup)
  * Abbreviated version of Z-order comparison
  *
  * The abbreviated format is a Z-order value computed from the two 32-bit
- * floats. If SIZEOF_DATUM == 8, the 64-bit Z-order value fits fully in the
- * abbreviated Datum, otherwise use its most significant bits.
+ * floats.  Now that SIZEOF_DATUM is always 8, the 64-bit Z-order value
+ * always fits fully in the abbreviated Datum.
  */
 static Datum
 gist_bbox_zorder_abbrev_convert(Datum original, SortSupport ssup)
@@ -1718,11 +1718,7 @@ gist_bbox_zorder_abbrev_convert(Datum original, SortSupport ssup)
 
 	z = point_zorder_internal(p->x, p->y);
 
-#if SIZEOF_DATUM == 8
-	return (Datum) z;
-#else
-	return (Datum) (z >> 32);
-#endif
+	return UInt64GetDatum(z);
 }
 
 /*
diff --git a/src/backend/access/nbtree/nbtcompare.c b/src/backend/access/nbtree/nbtcompare.c
index e1b52acd20d..188c27b4925 100644
--- a/src/backend/access/nbtree/nbtcompare.c
+++ b/src/backend/access/nbtree/nbtcompare.c
@@ -278,32 +278,12 @@ btint8cmp(PG_FUNCTION_ARGS)
 		PG_RETURN_INT32(A_LESS_THAN_B);
 }
 
-#if SIZEOF_DATUM < 8
-static int
-btint8fastcmp(Datum x, Datum y, SortSupport ssup)
-{
-	int64		a = DatumGetInt64(x);
-	int64		b = DatumGetInt64(y);
-
-	if (a > b)
-		return A_GREATER_THAN_B;
-	else if (a == b)
-		return 0;
-	else
-		return A_LESS_THAN_B;
-}
-#endif
-
 Datum
 btint8sortsupport(PG_FUNCTION_ARGS)
 {
 	SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
 
-#if SIZEOF_DATUM >= 8
 	ssup->comparator = ssup_datum_signed_cmp;
-#else
-	ssup->comparator = btint8fastcmp;
-#endif
 	PG_RETURN_VOID();
 }
 
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index 1ec523ee3e5..8b5c427c097 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -285,7 +285,6 @@ TypeCreate(Oid newTypeOid,
 						 errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
 								alignment, internalSize)));
 		}
-#if SIZEOF_DATUM == 8
 		else if (internalSize == (int16) sizeof(Datum))
 		{
 			if (alignment != TYPALIGN_DOUBLE)
@@ -294,7 +293,6 @@ TypeCreate(Oid newTypeOid,
 						 errmsg("alignment \"%c\" is invalid for passed-by-value type of size %d",
 								alignment, internalSize)));
 		}
-#endif
 		else
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
diff --git a/src/backend/utils/adt/mac.c b/src/backend/utils/adt/mac.c
index 3644e9735f5..bb38ef2f5e4 100644
--- a/src/backend/utils/adt/mac.c
+++ b/src/backend/utils/adt/mac.c
@@ -481,33 +481,26 @@ macaddr_abbrev_convert(Datum original, SortSupport ssup)
 	Datum		res;
 
 	/*
-	 * On a 64-bit machine, zero out the 8-byte datum and copy the 6 bytes of
-	 * the MAC address in. There will be two bytes of zero padding on the end
-	 * of the least significant bits.
+	 * Zero out the 8-byte Datum and copy in the 6 bytes of the MAC address.
+	 * There will be two bytes of zero padding on the end of the least
+	 * significant bits.
 	 */
-#if SIZEOF_DATUM == 8
-	memset(&res, 0, SIZEOF_DATUM);
+	StaticAssertStmt(sizeof(res) >= sizeof(macaddr),
+					 "Datum is too small for macaddr");
+	memset(&res, 0, sizeof(res));
 	memcpy(&res, authoritative, sizeof(macaddr));
-#else							/* SIZEOF_DATUM != 8 */
-	memcpy(&res, authoritative, SIZEOF_DATUM);
-#endif
 	uss->input_count += 1;
 
 	/*
-	 * Cardinality estimation. The estimate uses uint32, so on a 64-bit
-	 * architecture, XOR the two 32-bit halves together to produce slightly
-	 * more entropy. The two zeroed bytes won't have any practical impact on
-	 * this operation.
+	 * Cardinality estimation. The estimate uses uint32, so XOR the two 32-bit
+	 * halves together to produce slightly more entropy. The two zeroed bytes
+	 * won't have any practical impact on this operation.
 	 */
 	if (uss->estimating)
 	{
 		uint32		tmp;
 
-#if SIZEOF_DATUM == 8
-		tmp = (uint32) res ^ (uint32) ((uint64) res >> 32);
-#else							/* SIZEOF_DATUM != 8 */
-		tmp = (uint32) res;
-#endif
+		tmp = DatumGetUInt32(res) ^ (uint32) (DatumGetUInt64(res) >> 32);
 
 		addHyperLogLog(&uss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
 	}
diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c
index 9fd211b2d45..a269b36abe8 100644
--- a/src/backend/utils/adt/network.c
+++ b/src/backend/utils/adt/network.c
@@ -701,7 +701,6 @@ network_abbrev_convert(Datum original, SortSupport ssup)
 		network = ipaddr_datum;
 	}
 
-#if SIZEOF_DATUM == 8
 	if (ip_family(authoritative) == PGSQL_AF_INET)
 	{
 		/*
@@ -750,7 +749,6 @@ network_abbrev_convert(Datum original, SortSupport ssup)
 		res |= network | netmask_size | subnet;
 	}
 	else
-#endif
 	{
 		/*
 		 * 4 byte datums, or IPv6 with 8 byte datums: Use as many of the
@@ -767,11 +765,7 @@ network_abbrev_convert(Datum original, SortSupport ssup)
 	{
 		uint32		tmp;
 
-#if SIZEOF_DATUM == 8
-		tmp = (uint32) res ^ (uint32) ((uint64) res >> 32);
-#else							/* SIZEOF_DATUM != 8 */
-		tmp = (uint32) res;
-#endif
+		tmp = DatumGetUInt32(res) ^ (uint32) (DatumGetUInt64(res) >> 32);
 
 		addHyperLogLog(&uss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
 	}
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 122f2efab8b..256a1a49419 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -392,30 +392,21 @@ typedef struct NumericSumAccum
 
 /*
  * We define our own macros for packing and unpacking abbreviated-key
- * representations for numeric values in order to avoid depending on
- * USE_FLOAT8_BYVAL.  The type of abbreviation we use is based only on
- * the size of a datum, not the argument-passing convention for float8.
+ * representations, just to have a notational indication that that's
+ * what we're doing.  Now that SIZEOF_DATUM is always 8, we can rely
+ * on fitting an int64 into Datum.
  *
- * The range of abbreviations for finite values is from +PG_INT64/32_MAX
- * to -PG_INT64/32_MAX.  NaN has the abbreviation PG_INT64/32_MIN, and we
+ * The range of abbreviations for finite values is from +PG_INT64_MAX
+ * to -PG_INT64_MAX.  NaN has the abbreviation PG_INT64_MIN, and we
  * define the sort ordering to make that work out properly (see further
  * comments below).  PINF and NINF share the abbreviations of the largest
  * and smallest finite abbreviation classes.
  */
-#define NUMERIC_ABBREV_BITS (SIZEOF_DATUM * BITS_PER_BYTE)
-#if SIZEOF_DATUM == 8
-#define NumericAbbrevGetDatum(X) ((Datum) (X))
-#define DatumGetNumericAbbrev(X) ((int64) (X))
+#define NumericAbbrevGetDatum(X) Int64GetDatum(X)
+#define DatumGetNumericAbbrev(X) DatumGetInt64(X)
 #define NUMERIC_ABBREV_NAN		 NumericAbbrevGetDatum(PG_INT64_MIN)
 #define NUMERIC_ABBREV_PINF		 NumericAbbrevGetDatum(-PG_INT64_MAX)
 #define NUMERIC_ABBREV_NINF		 NumericAbbrevGetDatum(PG_INT64_MAX)
-#else
-#define NumericAbbrevGetDatum(X) ((Datum) (X))
-#define DatumGetNumericAbbrev(X) ((int32) (X))
-#define NUMERIC_ABBREV_NAN		 NumericAbbrevGetDatum(PG_INT32_MIN)
-#define NUMERIC_ABBREV_PINF		 NumericAbbrevGetDatum(-PG_INT32_MAX)
-#define NUMERIC_ABBREV_NINF		 NumericAbbrevGetDatum(PG_INT32_MAX)
-#endif
 
 
 /* ----------
@@ -2328,7 +2319,7 @@ numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup)
 }
 
 /*
- * Abbreviate a NumericVar according to the available bit size.
+ * Abbreviate a NumericVar into the 64-bit sortsupport size.
  *
  * The 31-bit value is constructed as:
  *
@@ -2372,9 +2363,6 @@ numeric_cmp_abbrev(Datum x, Datum y, SortSupport ssup)
  * with all bits zero. This allows simple comparisons to work on the composite
  * value.
  */
-
-#if NUMERIC_ABBREV_BITS == 64
-
 static Datum
 numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
 {
@@ -2426,84 +2414,6 @@ numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
 	return NumericAbbrevGetDatum(result);
 }
 
-#endif							/* NUMERIC_ABBREV_BITS == 64 */
-
-#if NUMERIC_ABBREV_BITS == 32
-
-static Datum
-numeric_abbrev_convert_var(const NumericVar *var, NumericSortSupport *nss)
-{
-	int			ndigits = var->ndigits;
-	int			weight = var->weight;
-	int32		result;
-
-	if (ndigits == 0 || weight < -11)
-	{
-		result = 0;
-	}
-	else if (weight > 20)
-	{
-		result = PG_INT32_MAX;
-	}
-	else
-	{
-		NumericDigit nxt1 = (ndigits > 1) ? var->digits[1] : 0;
-
-		weight = (weight + 11) * 4;
-
-		result = var->digits[0];
-
-		/*
-		 * "result" now has 1 to 4 nonzero decimal digits. We pack in more
-		 * digits to make 7 in total (largest we can fit in 24 bits)
-		 */
-
-		if (result > 999)
-		{
-			/* already have 4 digits, add 3 more */
-			result = (result * 1000) + (nxt1 / 10);
-			weight += 3;
-		}
-		else if (result > 99)
-		{
-			/* already have 3 digits, add 4 more */
-			result = (result * 10000) + nxt1;
-			weight += 2;
-		}
-		else if (result > 9)
-		{
-			NumericDigit nxt2 = (ndigits > 2) ? var->digits[2] : 0;
-
-			/* already have 2 digits, add 5 more */
-			result = (result * 100000) + (nxt1 * 10) + (nxt2 / 1000);
-			weight += 1;
-		}
-		else
-		{
-			NumericDigit nxt2 = (ndigits > 2) ? var->digits[2] : 0;
-
-			/* already have 1 digit, add 6 more */
-			result = (result * 1000000) + (nxt1 * 100) + (nxt2 / 100);
-		}
-
-		result = result | (weight << 24);
-	}
-
-	/* the abbrev is negated relative to the original */
-	if (var->sign == NUMERIC_POS)
-		result = -result;
-
-	if (nss->estimating)
-	{
-		uint32		tmp = (uint32) result;
-
-		addHyperLogLog(&nss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
-	}
-
-	return NumericAbbrevGetDatum(result);
-}
-
-#endif							/* NUMERIC_ABBREV_BITS == 32 */
 
 /*
  * Ordinary (non-sortsupport) comparisons follow.
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index e640b48205b..3e5f9dc1458 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -2275,33 +2275,12 @@ timestamp_cmp(PG_FUNCTION_ARGS)
 	PG_RETURN_INT32(timestamp_cmp_internal(dt1, dt2));
 }
 
-#if SIZEOF_DATUM < 8
-/* note: this is used for timestamptz also */
-static int
-timestamp_fastcmp(Datum x, Datum y, SortSupport ssup)
-{
-	Timestamp	a = DatumGetTimestamp(x);
-	Timestamp	b = DatumGetTimestamp(y);
-
-	return timestamp_cmp_internal(a, b);
-}
-#endif
-
 Datum
 timestamp_sortsupport(PG_FUNCTION_ARGS)
 {
 	SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
 
-#if SIZEOF_DATUM >= 8
-
-	/*
-	 * If this build has pass-by-value timestamps, then we can use a standard
-	 * comparator function.
-	 */
 	ssup->comparator = ssup_datum_signed_cmp;
-#else
-	ssup->comparator = timestamp_fastcmp;
-#endif
 	PG_RETURN_VOID();
 }
 
diff --git a/src/backend/utils/adt/uuid.c b/src/backend/utils/adt/uuid.c
index bce7309c183..7413239f7af 100644
--- a/src/backend/utils/adt/uuid.c
+++ b/src/backend/utils/adt/uuid.c
@@ -398,11 +398,7 @@ uuid_abbrev_convert(Datum original, SortSupport ssup)
 	{
 		uint32		tmp;
 
-#if SIZEOF_DATUM == 8
-		tmp = (uint32) res ^ (uint32) ((uint64) res >> 32);
-#else							/* SIZEOF_DATUM != 8 */
-		tmp = (uint32) res;
-#endif
+		tmp = DatumGetUInt32(res) ^ (uint32) (DatumGetUInt64(res) >> 32);
 
 		addHyperLogLog(&uss->abbr_card, DatumGetUInt32(hash_uint32(tmp)));
 	}
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index 11b442a5941..4fc3f0886a4 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -2132,18 +2132,12 @@ varstr_abbrev_convert(Datum original, SortSupport ssup)
 	addHyperLogLog(&sss->full_card, hash);
 
 	/* Hash abbreviated key */
-#if SIZEOF_DATUM == 8
 	{
-		uint32		lohalf,
-					hihalf;
+		uint32		tmp;
 
-		lohalf = (uint32) res;
-		hihalf = (uint32) (res >> 32);
-		hash = DatumGetUInt32(hash_uint32(lohalf ^ hihalf));
+		tmp = DatumGetUInt32(res) ^ (uint32) (DatumGetUInt64(res) >> 32);
+		hash = DatumGetUInt32(hash_uint32(tmp));
 	}
-#else							/* SIZEOF_DATUM != 8 */
-	hash = DatumGetUInt32(hash_uint32((uint32) res));
-#endif
 
 	addHyperLogLog(&sss->abbr_card, hash);
 
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index 65ab83fff8b..5d4411dc33f 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -512,7 +512,6 @@ qsort_tuple_unsigned_compare(SortTuple *a, SortTuple *b, Tuplesortstate *state)
 	return state->base.comparetup_tiebreak(a, b, state);
 }
 
-#if SIZEOF_DATUM >= 8
 /* Used if first key's comparator is ssup_datum_signed_cmp */
 static pg_attribute_always_inline int
 qsort_tuple_signed_compare(SortTuple *a, SortTuple *b, Tuplesortstate *state)
@@ -535,7 +534,6 @@ qsort_tuple_signed_compare(SortTuple *a, SortTuple *b, Tuplesortstate *state)
 
 	return state->base.comparetup_tiebreak(a, b, state);
 }
-#endif
 
 /* Used if first key's comparator is ssup_datum_int32_cmp */
 static pg_attribute_always_inline int
@@ -578,7 +576,6 @@ qsort_tuple_int32_compare(SortTuple *a, SortTuple *b, Tuplesortstate *state)
 #define ST_DEFINE
 #include "lib/sort_template.h"
 
-#if SIZEOF_DATUM >= 8
 #define ST_SORT qsort_tuple_signed
 #define ST_ELEMENT_TYPE SortTuple
 #define ST_COMPARE(a, b, state) qsort_tuple_signed_compare(a, b, state)
@@ -587,7 +584,6 @@ qsort_tuple_int32_compare(SortTuple *a, SortTuple *b, Tuplesortstate *state)
 #define ST_SCOPE static
 #define ST_DEFINE
 #include "lib/sort_template.h"
-#endif
 
 #define ST_SORT qsort_tuple_int32
 #define ST_ELEMENT_TYPE SortTuple
@@ -2692,7 +2688,6 @@ tuplesort_sort_memtuples(Tuplesortstate *state)
 									 state);
 				return;
 			}
-#if SIZEOF_DATUM >= 8
 			else if (state->base.sortKeys[0].comparator == ssup_datum_signed_cmp)
 			{
 				qsort_tuple_signed(state->memtuples,
@@ -2700,7 +2695,6 @@ tuplesort_sort_memtuples(Tuplesortstate *state)
 								   state);
 				return;
 			}
-#endif
 			else if (state->base.sortKeys[0].comparator == ssup_datum_int32_cmp)
 			{
 				qsort_tuple_int32(state->memtuples,
@@ -3146,7 +3140,6 @@ ssup_datum_unsigned_cmp(Datum x, Datum y, SortSupport ssup)
 		return 0;
 }
 
-#if SIZEOF_DATUM >= 8
 int
 ssup_datum_signed_cmp(Datum x, Datum y, SortSupport ssup)
 {
@@ -3160,7 +3153,6 @@ ssup_datum_signed_cmp(Datum x, Datum y, SortSupport ssup)
 	else
 		return 0;
 }
-#endif
 
 int
 ssup_datum_int32_cmp(Datum x, Datum y, SortSupport ssup)
diff --git a/src/include/access/gin_tuple.h b/src/include/access/gin_tuple.h
index 702f7d12889..b4f103dec9a 100644
--- a/src/include/access/gin_tuple.h
+++ b/src/include/access/gin_tuple.h
@@ -15,7 +15,9 @@
 #include "utils/sortsupport.h"
 
 /*
- * Data for one key in a GIN index.
+ * Data for one key in a GIN index.  (This is not the permanent in-index
+ * representation, but just a convenient format to use during the tuplesort
+ * stage of building a new GIN index.)
  */
 typedef struct GinTuple
 {
diff --git a/src/include/access/spgist_private.h b/src/include/access/spgist_private.h
index cb43a278f46..fdda7f4c639 100644
--- a/src/include/access/spgist_private.h
+++ b/src/include/access/spgist_private.h
@@ -285,10 +285,12 @@ typedef struct SpGistCache
  * If the prefix datum is of a pass-by-value type, it is stored in its
  * Datum representation, that is its on-disk representation is of length
  * sizeof(Datum).  This is a fairly unfortunate choice, because in no other
- * place does Postgres use Datum as an on-disk representation; it creates
- * an unnecessary incompatibility between 32-bit and 64-bit builds.  But the
- * compatibility loss is mostly theoretical since MAXIMUM_ALIGNOF typically
- * differs between such builds, too.  Anyway we're stuck with it now.
+ * place does Postgres use Datum as an on-disk representation.  Formerly it
+ * meant an unnecessary incompatibility between 32-bit and 64-bit builds, and
+ * as of v19 it instead creates a hazard for binary upgrades on 32-bit builds.
+ * Fortunately, that hazard seems mostly theoretical for lack of affected
+ * opclasses.  Going forward, we will be using a fixed size of Datum so that
+ * there's no longer any pressing reason to change this.
  */
 typedef struct SpGistInnerTupleData
 {
diff --git a/src/include/access/tupmacs.h b/src/include/access/tupmacs.h
index 6240ec930e7..7ef006fa7eb 100644
--- a/src/include/access/tupmacs.h
+++ b/src/include/access/tupmacs.h
@@ -62,10 +62,8 @@ fetch_att(const void *T, bool attbyval, int attlen)
 				return Int16GetDatum(*((const int16 *) T));
 			case sizeof(int32):
 				return Int32GetDatum(*((const int32 *) T));
-#if SIZEOF_DATUM == 8
 			case sizeof(Datum):
 				return *((const Datum *) T);
-#endif
 			default:
 				elog(ERROR, "unsupported byval length: %d", attlen);
 				return 0;
@@ -221,11 +219,9 @@ store_att_byval(void *T, Datum newdatum, int attlen)
 		case sizeof(int32):
 			*(int32 *) T = DatumGetInt32(newdatum);
 			break;
-#if SIZEOF_DATUM == 8
 		case sizeof(Datum):
 			*(Datum *) T = newdatum;
 			break;
-#endif
 		default:
 			elog(ERROR, "unsupported byval length: %d", attlen);
 	}
diff --git a/src/include/port/pg_bswap.h b/src/include/port/pg_bswap.h
index 33648433c63..f823588f58f 100644
--- a/src/include/port/pg_bswap.h
+++ b/src/include/port/pg_bswap.h
@@ -130,8 +130,7 @@ pg_bswap64(uint64 x)
 
 /*
  * Rearrange the bytes of a Datum from big-endian order into the native byte
- * order.  On big-endian machines, this does nothing at all.  Note that the C
- * type Datum is an unsigned integer type on all platforms.
+ * order.  On big-endian machines, this does nothing at all.
  *
  * One possible application of the DatumBigEndianToNative() macro is to make
  * bitwise comparisons cheaper.  A simple 3-way comparison of Datums
@@ -141,20 +140,14 @@ pg_bswap64(uint64 x)
  * without any special transformation occurring first.
  *
  * If SIZEOF_DATUM is not defined, then postgres.h wasn't included and these
- * macros probably shouldn't be used, so we define nothing.  Note that
- * SIZEOF_DATUM == 8 would evaluate as 0 == 8 in that case, potentially
- * leading to the wrong implementation being selected and confusing errors, so
- * defining nothing is safest.
+ * macros probably shouldn't be used, so we define nothing.  (DatumGetUInt64
+ * and UInt64GetDatum won't be available either.)
  */
 #ifdef SIZEOF_DATUM
 #ifdef WORDS_BIGENDIAN
 #define		DatumBigEndianToNative(x)	(x)
 #else							/* !WORDS_BIGENDIAN */
-#if SIZEOF_DATUM == 8
-#define		DatumBigEndianToNative(x)	pg_bswap64(x)
-#else							/* SIZEOF_DATUM != 8 */
-#define		DatumBigEndianToNative(x)	pg_bswap32(x)
-#endif							/* SIZEOF_DATUM == 8 */
+#define		DatumBigEndianToNative(x)	UInt64GetDatum(pg_bswap64(DatumGetUInt64(x)))
 #endif							/* WORDS_BIGENDIAN */
 #endif							/* SIZEOF_DATUM */
 
diff --git a/src/include/utils/sortsupport.h b/src/include/utils/sortsupport.h
index b7abaf7802d..c64527e2ee9 100644
--- a/src/include/utils/sortsupport.h
+++ b/src/include/utils/sortsupport.h
@@ -262,7 +262,6 @@ ApplyUnsignedSortComparator(Datum datum1, bool isNull1,
 	return compare;
 }
 
-#if SIZEOF_DATUM >= 8
 static inline int
 ApplySignedSortComparator(Datum datum1, bool isNull1,
 						  Datum datum2, bool isNull2,
@@ -296,7 +295,6 @@ ApplySignedSortComparator(Datum datum1, bool isNull1,
 
 	return compare;
 }
-#endif
 
 static inline int
 ApplyInt32SortComparator(Datum datum1, bool isNull1,
@@ -376,9 +374,7 @@ ApplySortAbbrevFullComparator(Datum datum1, bool isNull1,
  * are eligible for faster sorting.
  */
 extern int	ssup_datum_unsigned_cmp(Datum x, Datum y, SortSupport ssup);
-#if SIZEOF_DATUM >= 8
 extern int	ssup_datum_signed_cmp(Datum x, Datum y, SortSupport ssup);
-#endif
 extern int	ssup_datum_int32_cmp(Datum x, Datum y, SortSupport ssup);
 
 /* Other functions in utils/sort/sortsupport.c */
-- 
2.43.7

