From 7aaf12edf5d10c8ed8954d5ae67bad3b6ed5f0d1 Mon Sep 17 00:00:00 2001
From: Aleksander Alekseev <aleksander@tigerdata.com>
Date: Tue, 3 Feb 2026 16:45:10 +0300
Subject: [PATCH v7] Avoid unnecessary type casting when using hash_any() /
 hash_any_extended()

hash_any() is merely a wrapper for hash_bytes(). Call it directly when possible
in order to avoid unnecessary type casting. Same for hash_any_extended() which
is just a wrapper for hash_bytes_extended().

Additionally, improve the comment for addHyperLogLog(). Previously the comment
suggested to use hash_any() whose return value is Datum. Since the argument of
addHyperLogLog() is uint32, recommending hash_bytes() is more appropriate.

Author: Aleksander Alekseev <aleksander@tigerdata.com>
Suggested-by: John Naylor <johncnaylorls@gmail.com>
Reviewed-by: John Naylor <johncnaylorls@gmail.com>
Discussion: https://postgr.es/m/CAJ7c6TMPhDRQMmkUHPv8oOK97B1mR8NRS61DgjpdaZUPAwaeZQ%40mail.gmail.com
---
 contrib/ltree/ltree_op.c                   |  4 ++--
 src/backend/access/tablesample/bernoulli.c |  4 ++--
 src/backend/access/tablesample/system.c    |  4 ++--
 src/backend/commands/async.c               | 10 ++++-----
 src/backend/lib/bloomfilter.c              |  2 +-
 src/backend/lib/hyperloglog.c              |  2 +-
 src/backend/nodes/bitmapset.c              |  4 ++--
 src/backend/nodes/queryjumblefuncs.c       | 10 ++++-----
 src/backend/tsearch/ts_typanalyze.c        |  4 ++--
 src/backend/utils/adt/bytea.c              |  4 ++--
 src/backend/utils/adt/jsonb_gin.c          |  2 +-
 src/backend/utils/adt/jsonb_util.c         | 10 ++++-----
 src/backend/utils/adt/numeric.c            | 26 +++++++++++-----------
 src/backend/utils/adt/varlena.c            |  4 ++--
 src/backend/utils/cache/funccache.c        |  8 +++----
 15 files changed, 49 insertions(+), 49 deletions(-)

diff --git a/contrib/ltree/ltree_op.c b/contrib/ltree/ltree_op.c
index 1f9f02cf453..c9cbd3e8ed7 100644
--- a/contrib/ltree/ltree_op.c
+++ b/contrib/ltree/ltree_op.c
@@ -181,7 +181,7 @@ hash_ltree(PG_FUNCTION_ARGS)
 
 	while (an > 0)
 	{
-		uint32		levelHash = DatumGetUInt32(hash_any((unsigned char *) al->name, al->len));
+		uint32		levelHash = hash_bytes((unsigned char *) al->name, al->len);
 
 		/*
 		 * Combine hash values of successive elements by multiplying the
@@ -224,7 +224,7 @@ hash_ltree_extended(PG_FUNCTION_ARGS)
 
 	while (an > 0)
 	{
-		uint64		levelHash = DatumGetUInt64(hash_any_extended((unsigned char *) al->name, al->len, seed));
+		uint64		levelHash = hash_bytes_extended((unsigned char *) al->name, al->len, seed);
 
 		result = (result << 5) - result + levelHash;
 
diff --git a/src/backend/access/tablesample/bernoulli.c b/src/backend/access/tablesample/bernoulli.c
index a8ec1e1b9ac..5d30277c732 100644
--- a/src/backend/access/tablesample/bernoulli.c
+++ b/src/backend/access/tablesample/bernoulli.c
@@ -214,8 +214,8 @@ bernoulli_nextsampletuple(SampleScanState *node,
 
 		hashinput[1] = tupoffset;
 
-		hash = DatumGetUInt32(hash_any((const unsigned char *) hashinput,
-									   (int) sizeof(hashinput)));
+		hash = hash_bytes((const unsigned char *) hashinput,
+						  (int) sizeof(hashinput));
 		if (hash < sampler->cutoff)
 			break;
 	}
diff --git a/src/backend/access/tablesample/system.c b/src/backend/access/tablesample/system.c
index a2b9ba8eea9..de13dd8cab9 100644
--- a/src/backend/access/tablesample/system.c
+++ b/src/backend/access/tablesample/system.c
@@ -202,8 +202,8 @@ system_nextsampleblock(SampleScanState *node, BlockNumber nblocks)
 
 		hashinput[0] = nextblock;
 
-		hash = DatumGetUInt32(hash_any((const unsigned char *) hashinput,
-									   (int) sizeof(hashinput)));
+		hash = hash_bytes((const unsigned char *) hashinput,
+						  (int) sizeof(hashinput));
 		if (hash < sampler->cutoff)
 			break;
 	}
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index 4069dde3ba6..b24dd63b3fa 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -674,9 +674,9 @@ globalChannelTableHash(const void *key, size_t size, void *arg)
 	const GlobalChannelKey *k = (const GlobalChannelKey *) key;
 	dshash_hash h;
 
-	h = DatumGetUInt32(hash_uint32(k->dboid));
-	h ^= DatumGetUInt32(hash_any((const unsigned char *) k->channel,
-								 strnlen(k->channel, NAMEDATALEN)));
+	h = murmurhash32(k->dboid);
+	h ^= hash_bytes((const unsigned char *) k->channel,
+					strnlen(k->channel, NAMEDATALEN));
 
 	return h;
 }
@@ -3251,8 +3251,8 @@ notification_hash(const void *key, Size keysize)
 
 	Assert(keysize == sizeof(Notification *));
 	/* We don't bother to include the payload's trailing null in the hash */
-	return DatumGetUInt32(hash_any((const unsigned char *) k->data,
-								   k->channel_len + k->payload_len + 1));
+	return hash_bytes((const unsigned char *) k->data,
+					  k->channel_len + k->payload_len + 1);
 }
 
 /*
diff --git a/src/backend/lib/bloomfilter.c b/src/backend/lib/bloomfilter.c
index 73b3768a172..369a1e870e8 100644
--- a/src/backend/lib/bloomfilter.c
+++ b/src/backend/lib/bloomfilter.c
@@ -256,7 +256,7 @@ k_hashes(bloom_filter *filter, uint32 *hashes, unsigned char *elem, size_t len)
 	int			i;
 
 	/* Use 64-bit hashing to get two independent 32-bit hashes */
-	hash = DatumGetUInt64(hash_any_extended(elem, len, filter->seed));
+	hash = hash_bytes_extended(elem, len, filter->seed);
 	x = (uint32) hash;
 	y = (uint32) (hash >> 32);
 	m = filter->m;
diff --git a/src/backend/lib/hyperloglog.c b/src/backend/lib/hyperloglog.c
index 2b94b758fcf..5d2287bbf3f 100644
--- a/src/backend/lib/hyperloglog.c
+++ b/src/backend/lib/hyperloglog.c
@@ -158,7 +158,7 @@ freeHyperLogLog(hyperLogLogState *cState)
  * Adds element to the estimator, from caller-supplied hash.
  *
  * It is critical that the hash value passed be an actual hash value, typically
- * generated using hash_any().  The algorithm relies on a specific bit-pattern
+ * generated using hash_bytes().  The algorithm relies on a specific bit-pattern
  * observable in conjunction with stochastic averaging.  There must be a
  * uniform distribution of bits in hash values for each distinct original value
  * observed.
diff --git a/src/backend/nodes/bitmapset.c b/src/backend/nodes/bitmapset.c
index 4a12b047789..4dd97e55842 100644
--- a/src/backend/nodes/bitmapset.c
+++ b/src/backend/nodes/bitmapset.c
@@ -1546,8 +1546,8 @@ bms_hash_value(const Bitmapset *a)
 
 	if (a == NULL)
 		return 0;				/* All empty sets hash to 0 */
-	return DatumGetUInt32(hash_any((const unsigned char *) a->words,
-								   a->nwords * sizeof(bitmapword)));
+	return hash_bytes((const unsigned char *) a->words,
+					  a->nwords * sizeof(bitmapword));
 }
 
 /*
diff --git a/src/backend/nodes/queryjumblefuncs.c b/src/backend/nodes/queryjumblefuncs.c
index 094d2872644..e5f645dc29e 100644
--- a/src/backend/nodes/queryjumblefuncs.c
+++ b/src/backend/nodes/queryjumblefuncs.c
@@ -221,9 +221,9 @@ DoJumble(JumbleState *jstate, Node *node)
 		jstate->highest_extern_param_id = 0;
 
 	/* Process the jumble buffer and produce the hash value */
-	return DatumGetInt64(hash_any_extended(jstate->jumble,
-										   jstate->jumble_len,
-										   0));
+	return (int64) hash_bytes_extended(jstate->jumble,
+									   jstate->jumble_len,
+									   0);
 }
 
 /*
@@ -271,8 +271,8 @@ AppendJumbleInternal(JumbleState *jstate, const unsigned char *item,
 		{
 			int64		start_hash;
 
-			start_hash = DatumGetInt64(hash_any_extended(jumble,
-														 JUMBLE_SIZE, 0));
+			start_hash = (int64) hash_bytes_extended(jumble,
+													 JUMBLE_SIZE, 0);
 			memcpy(jumble, &start_hash, sizeof(start_hash));
 			jumble_len = sizeof(start_hash);
 		}
diff --git a/src/backend/tsearch/ts_typanalyze.c b/src/backend/tsearch/ts_typanalyze.c
index 48ee050e37f..6ca8ead3988 100644
--- a/src/backend/tsearch/ts_typanalyze.c
+++ b/src/backend/tsearch/ts_typanalyze.c
@@ -496,8 +496,8 @@ lexeme_hash(const void *key, Size keysize)
 {
 	const LexemeHashKey *l = (const LexemeHashKey *) key;
 
-	return DatumGetUInt32(hash_any((const unsigned char *) l->lexeme,
-								   l->length));
+	return hash_bytes((const unsigned char *) l->lexeme,
+					  l->length);
 }
 
 /*
diff --git a/src/backend/utils/adt/bytea.c b/src/backend/utils/adt/bytea.c
index da32f9c53c6..3b1b02a7125 100644
--- a/src/backend/utils/adt/bytea.c
+++ b/src/backend/utils/adt/bytea.c
@@ -1106,8 +1106,8 @@ bytea_abbrev_convert(Datum original, SortSupport ssup)
 	 * in order to compensate for cases where differences are past
 	 * PG_CACHE_LINE_SIZE bytes, so as to limit the overhead of hashing.
 	 */
-	hash = DatumGetUInt32(hash_any((unsigned char *) authoritative_data,
-								   Min(len, PG_CACHE_LINE_SIZE)));
+	hash = hash_bytes((unsigned char *) authoritative_data,
+					  Min(len, PG_CACHE_LINE_SIZE));
 
 	if (len > PG_CACHE_LINE_SIZE)
 		hash ^= murmurhash32((uint32) len);
diff --git a/src/backend/utils/adt/jsonb_gin.c b/src/backend/utils/adt/jsonb_gin.c
index d72a6441c5e..f5dbd5589d3 100644
--- a/src/backend/utils/adt/jsonb_gin.c
+++ b/src/backend/utils/adt/jsonb_gin.c
@@ -1333,7 +1333,7 @@ make_text_key(char flag, const char *str, int len)
 	{
 		uint32		hashval;
 
-		hashval = DatumGetUInt32(hash_any((const unsigned char *) str, len));
+		hashval = hash_bytes((const unsigned char *) str, len);
 		snprintf(hashbuf, sizeof(hashbuf), "%08x", hashval);
 		str = hashbuf;
 		len = 8;
diff --git a/src/backend/utils/adt/jsonb_util.c b/src/backend/utils/adt/jsonb_util.c
index b23facb6dac..509082cfb94 100644
--- a/src/backend/utils/adt/jsonb_util.c
+++ b/src/backend/utils/adt/jsonb_util.c
@@ -1451,8 +1451,8 @@ JsonbHashScalarValue(const JsonbValue *scalarVal, uint32 *hash)
 			tmp = 0x01;
 			break;
 		case jbvString:
-			tmp = DatumGetUInt32(hash_any((const unsigned char *) scalarVal->val.string.val,
-										  scalarVal->val.string.len));
+			tmp = hash_bytes((const unsigned char *) scalarVal->val.string.val,
+							 scalarVal->val.string.len);
 			break;
 		case jbvNumeric:
 			/* Must hash equal numerics to equal hash codes */
@@ -1494,9 +1494,9 @@ JsonbHashScalarValueExtended(const JsonbValue *scalarVal, uint64 *hash,
 			tmp = seed + 0x01;
 			break;
 		case jbvString:
-			tmp = DatumGetUInt64(hash_any_extended((const unsigned char *) scalarVal->val.string.val,
-												   scalarVal->val.string.len,
-												   seed));
+			tmp = hash_bytes_extended((const unsigned char *) scalarVal->val.string.val,
+									  scalarVal->val.string.len,
+									  seed);
 			break;
 		case jbvNumeric:
 			tmp = DatumGetUInt64(DirectFunctionCall2(hash_numeric_extended,
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 238f2e89f1d..65e6c677e59 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -2717,8 +2717,8 @@ Datum
 hash_numeric(PG_FUNCTION_ARGS)
 {
 	Numeric		key = PG_GETARG_NUMERIC(0);
-	Datum		digit_hash;
-	Datum		result;
+	uint32		digit_hash;
+	uint32		result;
 	int			weight;
 	int			start_offset;
 	int			end_offset;
@@ -2780,13 +2780,13 @@ hash_numeric(PG_FUNCTION_ARGS)
 	 * this shouldn't affect correctness.
 	 */
 	hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
-	digit_hash = hash_any((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
-						  hash_len * sizeof(NumericDigit));
+	digit_hash = hash_bytes((unsigned char *) (NUMERIC_DIGITS(key) + start_offset),
+							hash_len * sizeof(NumericDigit));
 
 	/* Mix in the weight, via XOR */
 	result = digit_hash ^ weight;
 
-	PG_RETURN_DATUM(result);
+	PG_RETURN_UINT32(result);
 }
 
 /*
@@ -2798,8 +2798,8 @@ hash_numeric_extended(PG_FUNCTION_ARGS)
 {
 	Numeric		key = PG_GETARG_NUMERIC(0);
 	uint64		seed = PG_GETARG_INT64(1);
-	Datum		digit_hash;
-	Datum		result;
+	uint64		digit_hash;
+	uint64		result;
 	int			weight;
 	int			start_offset;
 	int			end_offset;
@@ -2840,14 +2840,14 @@ hash_numeric_extended(PG_FUNCTION_ARGS)
 	Assert(start_offset + end_offset < NUMERIC_NDIGITS(key));
 
 	hash_len = NUMERIC_NDIGITS(key) - start_offset - end_offset;
-	digit_hash = hash_any_extended((unsigned char *) (NUMERIC_DIGITS(key)
-													  + start_offset),
-								   hash_len * sizeof(NumericDigit),
-								   seed);
+	digit_hash = hash_bytes_extended((unsigned char *) (NUMERIC_DIGITS(key)
+														+ start_offset),
+									 hash_len * sizeof(NumericDigit),
+									 seed);
 
-	result = UInt64GetDatum(DatumGetUInt64(digit_hash) ^ weight);
+	result = digit_hash ^ weight;
 
-	PG_RETURN_DATUM(result);
+	PG_RETURN_UINT64(result);
 }
 
 
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index 910fc24313b..6c95fcb24b7 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -2154,8 +2154,8 @@ varstr_abbrev_convert(Datum original, SortSupport ssup)
 	 * in order to compensate for cases where differences are past
 	 * PG_CACHE_LINE_SIZE bytes, so as to limit the overhead of hashing.
 	 */
-	hash = DatumGetUInt32(hash_any((unsigned char *) authoritative_data,
-								   Min(len, PG_CACHE_LINE_SIZE)));
+	hash = hash_bytes((unsigned char *) authoritative_data,
+					  Min(len, PG_CACHE_LINE_SIZE));
 
 	if (len > PG_CACHE_LINE_SIZE)
 		hash ^= murmurhash32((uint32) len);
diff --git a/src/backend/utils/cache/funccache.c b/src/backend/utils/cache/funccache.c
index 43f031d53a2..64f7b51ac41 100644
--- a/src/backend/utils/cache/funccache.c
+++ b/src/backend/utils/cache/funccache.c
@@ -89,13 +89,13 @@ cfunc_hash(const void *key, Size keysize)
 
 	Assert(keysize == sizeof(CachedFunctionHashKey));
 	/* Hash all the fixed fields except callResultType */
-	h = DatumGetUInt32(hash_any((const unsigned char *) k,
-								offsetof(CachedFunctionHashKey, callResultType)));
+	h = hash_bytes((const unsigned char *) k,
+				   offsetof(CachedFunctionHashKey, callResultType));
 	/* Incorporate input argument types */
 	if (k->nargs > 0)
 		h = hash_combine(h,
-						 DatumGetUInt32(hash_any((const unsigned char *) k->argtypes,
-												 k->nargs * sizeof(Oid))));
+						 hash_bytes((const unsigned char *) k->argtypes,
+									k->nargs * sizeof(Oid)));
 	/* Incorporate callResultType if present */
 	if (k->callResultType)
 		h = hash_combine(h, hashRowType(k->callResultType));
-- 
2.43.0

