v2-0001-Make-type-Datum-be-8-bytes-wide-everywhere.patch
text/x-diff
Filename: v2-0001-Make-type-Datum-be-8-bytes-wide-everywhere.patch
Type: text/x-diff
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v2-0001
Subject: Make type Datum be 8 bytes wide everywhere.
| File | + | − |
|---|---|---|
| src/backend/storage/ipc/ipc.c | 1 | 1 |
| src/backend/utils/resowner/resowner.c | 2 | 5 |
| src/include/nodes/nodes.h | 6 | 2 |
| src/include/pg_config_manual.h | 4 | 9 |
| src/include/postgres.h | 13 | 8 |
From 594400bcdd9637a1f77f22ef0664cce7046ef1f5 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Tue, 12 Aug 2025 14:53:35 -0400
Subject: [PATCH v2 1/3] Make type Datum be 8 bytes wide everywhere.
This patch makes sizeof(Datum) be 8 on all platforms including
32-bit ones. The objective is to allow USE_FLOAT8_BYVAL to be true
everywhere, and in consequence to remove a lot of code that is
specific to pass-by-reference handling of float8, int8, etc. In this
way we can reduce the maintenance effort involved in supporting 32-bit
platforms, without going so far as to actually desupport them. Since
Datum is strictly an in-memory concept, this has no impact on on-disk
storage, though an initdb or pg_upgrade will be needed to fix affected
pg_type.typbyval entries (and also Const nodes in stored queries).
We have required platforms to support [u]int64 for ages, so this
breaks no supported platform. We can expect that this change will
make 32-bit builds a bit slower and more memory-hungry, although being
able to use pass-by-value handling of 8-byte types may buy back some
of that. But we stopped optimizing for 32-bit cases a long time ago,
and this seems like just another step on that path.
This initial patch simply forces the correct type definition and
USE_FLOAT8_BYVAL setting, and cleans up a couple of minor compiler
complaints that ensued. This is sufficient for testing purposes.
In the wake of a bunch of Datum-conversion cleanups by Peter
Eisentraut, this now compiles cleanly with gcc on a 32-bit platform.
(I'd only tested the previous version with clang, which it turns out
is less picky than gcc about width-changing coercions.)
There is a good deal of now-dead code that I'll remove in separate
follow-up patches.
XXX don't forget catversion bump.
Discussion: https://postgr.es/m/1749799.1752797397@sss.pgh.pa.us
---
src/backend/storage/ipc/ipc.c | 2 +-
src/backend/utils/resowner/resowner.c | 7 ++-----
src/include/nodes/nodes.h | 8 ++++++--
src/include/pg_config_manual.h | 13 ++++---------
src/include/postgres.h | 21 +++++++++++++--------
5 files changed, 26 insertions(+), 25 deletions(-)
diff --git a/src/backend/storage/ipc/ipc.c b/src/backend/storage/ipc/ipc.c
index 567739b5be9..2704e80b3a7 100644
--- a/src/backend/storage/ipc/ipc.c
+++ b/src/backend/storage/ipc/ipc.c
@@ -399,7 +399,7 @@ cancel_before_shmem_exit(pg_on_exit_callback function, Datum arg)
before_shmem_exit_list[before_shmem_exit_index - 1].arg == arg)
--before_shmem_exit_index;
else
- elog(ERROR, "before_shmem_exit callback (%p,0x%" PRIxPTR ") is not the latest entry",
+ elog(ERROR, "before_shmem_exit callback (%p,0x%" PRIx64 ") is not the latest entry",
function, arg);
}
diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c
index d39f3e1b655..fca84ded6dd 100644
--- a/src/backend/utils/resowner/resowner.c
+++ b/src/backend/utils/resowner/resowner.c
@@ -231,11 +231,8 @@ hash_resource_elem(Datum value, const ResourceOwnerDesc *kind)
* 'kind' into the hash. Just add it with hash_combine(), it perturbs the
* result enough for our purposes.
*/
-#if SIZEOF_DATUM == 8
- return hash_combine64(murmurhash64((uint64) value), (uint64) kind);
-#else
- return hash_combine(murmurhash32((uint32) value), (uint32) kind);
-#endif
+ return hash_combine64(murmurhash64((uint64) value),
+ (uint64) (uintptr_t) kind);
}
/*
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index fbe333d88fa..b2dc380b57b 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -188,6 +188,8 @@ castNodeImpl(NodeTag type, void *ptr)
* ----------------------------------------------------------------
*/
+#ifndef FRONTEND
+
/*
* nodes/{outfuncs.c,print.c}
*/
@@ -198,7 +200,7 @@ extern void outNode(struct StringInfoData *str, const void *obj);
extern void outToken(struct StringInfoData *str, const char *s);
extern void outBitmapset(struct StringInfoData *str,
const struct Bitmapset *bms);
-extern void outDatum(struct StringInfoData *str, uintptr_t value,
+extern void outDatum(struct StringInfoData *str, Datum value,
int typlen, bool typbyval);
extern char *nodeToString(const void *obj);
extern char *nodeToStringWithLocations(const void *obj);
@@ -212,7 +214,7 @@ extern void *stringToNode(const char *str);
extern void *stringToNodeWithLocations(const char *str);
#endif
extern struct Bitmapset *readBitmapset(void);
-extern uintptr_t readDatum(bool typbyval);
+extern Datum readDatum(bool typbyval);
extern bool *readBoolCols(int numCols);
extern int *readIntCols(int numCols);
extern Oid *readOidCols(int numCols);
@@ -235,6 +237,8 @@ extern void *copyObjectImpl(const void *from);
*/
extern bool equal(const void *a, const void *b);
+#endif /* !FRONTEND */
+
/*
* Typedef for parse location. This is just an int, but this way
diff --git a/src/include/pg_config_manual.h b/src/include/pg_config_manual.h
index 125d3eb5fff..7e1aa422332 100644
--- a/src/include/pg_config_manual.h
+++ b/src/include/pg_config_manual.h
@@ -74,17 +74,12 @@
#define PARTITION_MAX_KEYS 32
/*
- * Decide whether built-in 8-byte types, including float8, int8, and
- * timestamp, are passed by value. This is on by default if sizeof(Datum) >=
- * 8 (that is, on 64-bit platforms). If sizeof(Datum) < 8 (32-bit platforms),
- * this must be off. We keep this here as an option so that it is easy to
- * test the pass-by-reference code paths on 64-bit platforms.
- *
- * Changing this requires an initdb.
+ * This symbol is now vestigial: built-in 8-byte types, including float8,
+ * int8, and timestamp, are always passed by value since we require Datum
+ * to be wide enough to permit that. We continue to define the symbol here
+ * so as not to unnecessarily break extension code.
*/
-#if SIZEOF_VOID_P >= 8
#define USE_FLOAT8_BYVAL 1
-#endif
/*
diff --git a/src/include/postgres.h b/src/include/postgres.h
index 8a41a668687..e81829bfa6f 100644
--- a/src/include/postgres.h
+++ b/src/include/postgres.h
@@ -58,15 +58,22 @@
/*
* A Datum contains either a value of a pass-by-value type or a pointer to a
- * value of a pass-by-reference type. Therefore, we require:
- *
- * sizeof(Datum) == sizeof(void *) == 4 or 8
+ * value of a pass-by-reference type. Therefore, we must have
+ * sizeof(Datum) >= sizeof(void *). No current or foreseeable Postgres
+ * platform has pointers wider than 8 bytes, and standardizing on Datum being
+ * exactly 8 bytes has advantages in reducing cross-platform differences.
*
* The functions below and the analogous functions for other types should be used to
* convert between a Datum and the appropriate C type.
*/
-typedef uintptr_t Datum;
+typedef uint64_t Datum;
+
+/*
+ * This symbol is now vestigial, but we continue to define it so as not to
+ * unnecessarily break extension code.
+ */
+#define SIZEOF_DATUM 8
/*
* A NullableDatum is used in places where both a Datum and its nullness needs
@@ -83,8 +90,6 @@ typedef struct NullableDatum
/* due to alignment padding this could be used for flags for free */
} NullableDatum;
-#define SIZEOF_DATUM SIZEOF_VOID_P
-
/*
* DatumGetBool
* Returns boolean value of a datum.
@@ -316,7 +321,7 @@ CommandIdGetDatum(CommandId X)
static inline Pointer
DatumGetPointer(Datum X)
{
- return (Pointer) X;
+ return (Pointer) (uintptr_t) X;
}
/*
@@ -326,7 +331,7 @@ DatumGetPointer(Datum X)
static inline Datum
PointerGetDatum(const void *X)
{
- return (Datum) X;
+ return (Datum) (uintptr_t) X;
}
/*
--
2.43.7