From 86f6080503a5e986e7daf771d5d7970f36cc2fe6 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Thu, 18 Sep 2025 09:48:44 +0900
Subject: [PATCH v2] Document no-padding rule for PgStat_HashKey

This removes a couple of memset(0) calls, as we don't want padding in
it.  While on it, add a cheap assertion checking that no padding is
introduced in the structure, by checking that the size of PgStat_HashKey
matches with the sum of the field sizes.
---
 src/include/utils/pgstat_internal.h       | 17 ++++++++++++++++-
 src/backend/utils/activity/pgstat.c       |  5 +----
 src/backend/utils/activity/pgstat_shmem.c | 10 ++--------
 3 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/src/include/utils/pgstat_internal.h b/src/include/utils/pgstat_internal.h
index 6cf00008f633..bf75ebcef31c 100644
--- a/src/include/utils/pgstat_internal.h
+++ b/src/include/utils/pgstat_internal.h
@@ -48,7 +48,13 @@
  * PgStatShared_Common as the first element.
  */
 
-/* struct for shared statistics hash entry key. */
+/*
+ * Struct for shared statistics hash entry key.
+ *
+ * NB: We assume that this struct contains no padding.  Also, 8 bytes
+ * allocated for the object ID are good enough to ensure the uniqueness
+ * of the hash key, hence the addition of new fields is not recommended.
+ */
 typedef struct PgStat_HashKey
 {
 	PgStat_Kind kind;			/* statistics entry kind */
@@ -57,6 +63,15 @@ typedef struct PgStat_HashKey
 								 * identifier. */
 } PgStat_HashKey;
 
+/*
+ * PgStat_HashKey should not have any padding.  Checking that the structure
+ * size matches with the sum of each field is a check simple enough to
+ * enforce this policy.
+ */
+StaticAssertDecl((sizeof(PgStat_Kind) + sizeof(uint64) + sizeof(Oid)) ==
+				 sizeof(PgStat_HashKey),
+				 "PgStat_HashKey should have no padding");
+
 /*
  * Shared statistics hash entry. Doesn't itself contain any stats, but points
  * to them (with ->body). That allows the stats entries themselves to be of
diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c
index f8e91484e36b..73c2ced3f4e2 100644
--- a/src/backend/utils/activity/pgstat.c
+++ b/src/backend/utils/activity/pgstat.c
@@ -932,7 +932,7 @@ pgstat_clear_snapshot(void)
 void *
 pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, uint64 objid)
 {
-	PgStat_HashKey key;
+	PgStat_HashKey key = {0};
 	PgStat_EntryRef *entry_ref;
 	void	   *stats_data;
 	const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
@@ -943,9 +943,6 @@ pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, uint64 objid)
 
 	pgstat_prep_snapshot();
 
-	/* clear padding */
-	memset(&key, 0, sizeof(struct PgStat_HashKey));
-
 	key.kind = kind;
 	key.dboid = dboid;
 	key.objid = objid;
diff --git a/src/backend/utils/activity/pgstat_shmem.c b/src/backend/utils/activity/pgstat_shmem.c
index 9dc3212f7dd0..ca36fd247f64 100644
--- a/src/backend/utils/activity/pgstat_shmem.c
+++ b/src/backend/utils/activity/pgstat_shmem.c
@@ -456,14 +456,11 @@ PgStat_EntryRef *
 pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, uint64 objid, bool create,
 					 bool *created_entry)
 {
-	PgStat_HashKey key;
+	PgStat_HashKey key = {0};
 	PgStatShared_HashEntry *shhashent;
 	PgStatShared_Common *shheader = NULL;
 	PgStat_EntryRef *entry_ref;
 
-	/* clear padding */
-	memset(&key, 0, sizeof(struct PgStat_HashKey));
-
 	key.kind = kind;
 	key.dboid = dboid;
 	key.objid = objid;
@@ -988,13 +985,10 @@ pgstat_drop_database_and_contents(Oid dboid)
 bool
 pgstat_drop_entry(PgStat_Kind kind, Oid dboid, uint64 objid)
 {
-	PgStat_HashKey key;
+	PgStat_HashKey key = {0};
 	PgStatShared_HashEntry *shent;
 	bool		freed = true;
 
-	/* clear padding */
-	memset(&key, 0, sizeof(struct PgStat_HashKey));
-
 	key.kind = kind;
 	key.dboid = dboid;
 	key.objid = objid;
-- 
2.51.0

