public inbox for [email protected]
help / color / mirror / Atom feedFrom: Bertrand Drouvot <[email protected]>
Subject: [PATCH v1] Safer hash table initialization macro
Date: Tue, 2 Dec 2025 08:07:20 +0000
Currently to create a hash table, we do things like:
ctl.keysize = sizeof(<Type>);
ctl.entrysize = sizeof(<Struct>);
but that lead to 2 possible issues:
- we manually specify the type for keysize, which could become incorrect (from
the start) or if the key member's type changes.
- it may be possible to remove the key member without the compiler noticing it.
To fix those, this commit introduces a new HASH_ELEM_INIT macro that:
- requests the key member name
- ensures that it is at offset 0
- computes the key size based on the member
so that:
- the key member is explicitly referenced in the code (preventing "unused"
false positives)
- the key size is automatically computed from the actual member type (preventing
type mismatches)
- we enforce that the key is at offset 0
Also note that this commit adds HASH_ELEM_INIT_FULL for the rare cases where
the whole struct is the key.
---
contrib/dblink/dblink.c | 3 +-
.../pg_stat_statements/pg_stat_statements.c | 3 +-
contrib/pg_trgm/trgm_regexp.c | 3 +-
contrib/postgres_fdw/connection.c | 3 +-
contrib/postgres_fdw/shippable.c | 3 +-
contrib/tablefunc/tablefunc.c | 3 +-
src/backend/access/common/heaptuple.c | 3 +-
src/backend/access/gist/gistbuild.c | 3 +-
src/backend/access/gist/gistbuildbuffers.c | 3 +-
src/backend/access/hash/hashpage.c | 3 +-
src/backend/access/heap/rewriteheap.c | 8 ++---
src/backend/access/transam/xlogprefetcher.c | 3 +-
src/backend/access/transam/xlogutils.c | 3 +-
src/backend/catalog/pg_enum.c | 6 ++--
src/backend/catalog/pg_inherits.c | 3 +-
src/backend/catalog/storage.c | 6 ++--
src/backend/commands/async.c | 3 +-
src/backend/commands/prepare.c | 3 +-
src/backend/commands/sequence.c | 3 +-
src/backend/commands/tablecmds.c | 3 +-
src/backend/executor/nodeModifyTable.c | 3 +-
src/backend/nodes/extensible.c | 3 +-
src/backend/optimizer/util/plancat.c | 3 +-
src/backend/optimizer/util/predtest.c | 3 +-
src/backend/optimizer/util/relnode.c | 3 +-
src/backend/parser/parse_oper.c | 3 +-
src/backend/partitioning/partdesc.c | 3 +-
src/backend/postmaster/autovacuum.c | 6 ++--
src/backend/postmaster/checkpointer.c | 3 +-
.../replication/logical/applyparallelworker.c | 3 +-
src/backend/replication/logical/relation.c | 3 +-
.../replication/logical/reorderbuffer.c | 9 ++---
src/backend/replication/logical/tablesync.c | 3 +-
src/backend/replication/pgoutput/pgoutput.c | 3 +-
src/backend/storage/buffer/buf_table.c | 3 +-
src/backend/storage/buffer/bufmgr.c | 3 +-
src/backend/storage/buffer/localbuf.c | 3 +-
src/backend/storage/file/reinit.c | 3 +-
src/backend/storage/ipc/shmem.c | 3 +-
src/backend/storage/ipc/standby.c | 6 ++--
src/backend/storage/lmgr/lock.c | 12 +++----
src/backend/storage/lmgr/lwlock.c | 3 +-
src/backend/storage/lmgr/predicate.c | 12 +++----
src/backend/storage/smgr/smgr.c | 3 +-
src/backend/storage/sync/sync.c | 3 +-
src/backend/tsearch/ts_typanalyze.c | 3 +-
src/backend/utils/activity/wait_event.c | 6 ++--
src/backend/utils/adt/array_typanalyze.c | 6 ++--
src/backend/utils/adt/json.c | 3 +-
src/backend/utils/adt/jsonfuncs.c | 6 ++--
src/backend/utils/adt/mcxtfuncs.c | 3 +-
src/backend/utils/adt/ri_triggers.c | 9 ++---
src/backend/utils/adt/ruleutils.c | 3 +-
src/backend/utils/cache/attoptcache.c | 3 +-
src/backend/utils/cache/evtcache.c | 3 +-
src/backend/utils/cache/funccache.c | 3 +-
src/backend/utils/cache/relcache.c | 6 ++--
src/backend/utils/cache/relfilenumbermap.c | 3 +-
src/backend/utils/cache/spccache.c | 3 +-
src/backend/utils/cache/ts_cache.c | 9 ++---
src/backend/utils/cache/typcache.c | 9 ++---
src/backend/utils/fmgr/dfmgr.c | 3 +-
src/backend/utils/fmgr/fmgr.c | 3 +-
src/backend/utils/misc/guc.c | 3 +-
src/backend/utils/misc/injection_point.c | 3 +-
src/backend/utils/mmgr/portalmem.c | 4 +--
src/backend/utils/time/combocid.c | 3 +-
src/include/utils/hsearch.h | 35 +++++++++++++++++++
src/pl/plperl/plperl.c | 9 ++---
src/pl/plpgsql/src/pl_exec.c | 9 ++---
src/pl/plpython/plpy_plpymodule.c | 3 +-
src/pl/plpython/plpy_procedure.c | 3 +-
src/pl/tcl/pltcl.c | 6 ++--
src/timezone/pgtz.c | 3 +-
74 files changed, 138 insertions(+), 203 deletions(-)
5.0% contrib/
8.2% src/backend/access/
3.8% src/backend/catalog/
3.6% src/backend/commands/
6.2% src/backend/replication/logical/
7.6% src/backend/storage/lmgr/
8.3% src/backend/storage/
8.5% src/backend/utils/adt/
11.4% src/backend/utils/cache/
7.7% src/backend/utils/
10.6% src/backend/
7.7% src/include/utils/
3.0% src/pl/plpgsql/src/
6.6% src/pl/
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 8bf8fc8ea2f..4e9c9d9e644 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -2542,8 +2542,7 @@ createConnHash(void)
{
HASHCTL ctl;
- ctl.keysize = NAMEDATALEN;
- ctl.entrysize = sizeof(remoteConnHashEnt);
+ HASH_ELEM_INIT(ctl, remoteConnHashEnt, name);
return hash_create("Remote Con hash", NUMCONN, &ctl,
HASH_ELEM | HASH_STRINGS);
diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index 39208f80b5b..0da50496827 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -557,8 +557,7 @@ pgss_shmem_startup(void)
pgss->stats.stats_reset = GetCurrentTimestamp();
}
- info.keysize = sizeof(pgssHashKey);
- info.entrysize = sizeof(pgssEntry);
+ HASH_ELEM_INIT(info, pgssEntry, key);
pgss_hash = ShmemInitHash("pg_stat_statements hash",
pgss_max, pgss_max,
&info,
diff --git a/contrib/pg_trgm/trgm_regexp.c b/contrib/pg_trgm/trgm_regexp.c
index 149f9eb259c..200ccfaeb9e 100644
--- a/contrib/pg_trgm/trgm_regexp.c
+++ b/contrib/pg_trgm/trgm_regexp.c
@@ -906,8 +906,7 @@ transformGraph(TrgmNFA *trgmNFA)
trgmNFA->overflowed = false;
/* Create hashtable for states */
- hashCtl.keysize = sizeof(TrgmStateKey);
- hashCtl.entrysize = sizeof(TrgmState);
+ HASH_ELEM_INIT(hashCtl, TrgmState, stateKey);
hashCtl.hcxt = CurrentMemoryContext;
trgmNFA->states = hash_create("Trigram NFA",
1024,
diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c
index 953c2e0ab82..dee9c34d0fe 100644
--- a/contrib/postgres_fdw/connection.c
+++ b/contrib/postgres_fdw/connection.c
@@ -220,8 +220,7 @@ GetConnection(UserMapping *user, bool will_prep_stmt, PgFdwConnState **state)
pgfdw_we_get_result =
WaitEventExtensionNew("PostgresFdwGetResult");
- ctl.keysize = sizeof(ConnCacheKey);
- ctl.entrysize = sizeof(ConnCacheEntry);
+ HASH_ELEM_INIT(ctl, ConnCacheEntry, key);
ConnectionHash = hash_create("postgres_fdw connections", 8,
&ctl,
HASH_ELEM | HASH_BLOBS);
diff --git a/contrib/postgres_fdw/shippable.c b/contrib/postgres_fdw/shippable.c
index da3b13b207d..578d20f41a3 100644
--- a/contrib/postgres_fdw/shippable.c
+++ b/contrib/postgres_fdw/shippable.c
@@ -93,8 +93,7 @@ InitializeShippableCache(void)
HASHCTL ctl;
/* Create the hash table. */
- ctl.keysize = sizeof(ShippableCacheKey);
- ctl.entrysize = sizeof(ShippableCacheEntry);
+ HASH_ELEM_INIT(ctl, ShippableCacheEntry, key);
ShippableCacheHash =
hash_create("Shippability cache", 256, &ctl, HASH_ELEM | HASH_BLOBS);
diff --git a/contrib/tablefunc/tablefunc.c b/contrib/tablefunc/tablefunc.c
index 74afdc0977f..7bcff00af76 100644
--- a/contrib/tablefunc/tablefunc.c
+++ b/contrib/tablefunc/tablefunc.c
@@ -711,8 +711,7 @@ load_categories_hash(char *cats_sql, MemoryContext per_query_ctx)
MemoryContext SPIcontext;
/* initialize the category hash table */
- ctl.keysize = MAX_CATNAME_LEN;
- ctl.entrysize = sizeof(crosstab_HashEnt);
+ HASH_ELEM_INIT(ctl, crosstab_HashEnt, internal_catname);
ctl.hcxt = per_query_ctx;
/*
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index 74a52d87067..3c7038d5805 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -127,8 +127,7 @@ init_missing_cache()
{
HASHCTL hash_ctl;
- hash_ctl.keysize = sizeof(missing_cache_key);
- hash_ctl.entrysize = sizeof(missing_cache_key);
+ HASH_ELEM_INIT_FULL(hash_ctl, missing_cache_key);
hash_ctl.hcxt = TopMemoryContext;
hash_ctl.hash = missing_hash;
hash_ctl.match = missing_match;
diff --git a/src/backend/access/gist/gistbuild.c b/src/backend/access/gist/gistbuild.c
index be0fd5b753d..86ac61d869e 100644
--- a/src/backend/access/gist/gistbuild.c
+++ b/src/backend/access/gist/gistbuild.c
@@ -1517,8 +1517,7 @@ gistInitParentMap(GISTBuildState *buildstate)
{
HASHCTL hashCtl;
- hashCtl.keysize = sizeof(BlockNumber);
- hashCtl.entrysize = sizeof(ParentMapEntry);
+ HASH_ELEM_INIT(hashCtl, ParentMapEntry, childblkno);
hashCtl.hcxt = CurrentMemoryContext;
buildstate->parentMap = hash_create("gistbuild parent map",
1024,
diff --git a/src/backend/access/gist/gistbuildbuffers.c b/src/backend/access/gist/gistbuildbuffers.c
index 0707254d18e..92bec12f03d 100644
--- a/src/backend/access/gist/gistbuildbuffers.c
+++ b/src/backend/access/gist/gistbuildbuffers.c
@@ -72,8 +72,7 @@ gistInitBuildBuffers(int pagesPerBuffer, int levelStep, int maxLevel)
* nodeBuffersTab hash is association between index blocks and it's
* buffers.
*/
- hashCtl.keysize = sizeof(BlockNumber);
- hashCtl.entrysize = sizeof(GISTNodeBuffer);
+ HASH_ELEM_INIT(hashCtl, GISTNodeBuffer, nodeBlocknum);
hashCtl.hcxt = CurrentMemoryContext;
gfbb->nodeBuffersTab = hash_create("gistbuildbuffers",
1024,
diff --git a/src/backend/access/hash/hashpage.c b/src/backend/access/hash/hashpage.c
index b8e5bd005e5..1075af0c5d1 100644
--- a/src/backend/access/hash/hashpage.c
+++ b/src/backend/access/hash/hashpage.c
@@ -1368,8 +1368,7 @@ _hash_finish_split(Relation rel, Buffer metabuf, Buffer obuf, Bucket obucket,
bool found;
/* Initialize hash tables used to track TIDs */
- hash_ctl.keysize = sizeof(ItemPointerData);
- hash_ctl.entrysize = sizeof(ItemPointerData);
+ HASH_ELEM_INIT_FULL(hash_ctl, ItemPointerData);
hash_ctl.hcxt = CurrentMemoryContext;
tidhtab =
diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index 66ab48f0fe0..8e70758f5dc 100644
--- a/src/backend/access/heap/rewriteheap.c
+++ b/src/backend/access/heap/rewriteheap.c
@@ -263,8 +263,7 @@ begin_heap_rewrite(Relation old_heap, Relation new_heap, TransactionId oldest_xm
state->rs_bulkstate = smgr_bulk_start_rel(new_heap, MAIN_FORKNUM);
/* Initialize hash tables used to track update chains */
- hash_ctl.keysize = sizeof(TidHashKey);
- hash_ctl.entrysize = sizeof(UnresolvedTupData);
+ HASH_ELEM_INIT(hash_ctl, UnresolvedTupData, key);
hash_ctl.hcxt = state->rs_cxt;
state->rs_unresolved_tups =
@@ -273,7 +272,7 @@ begin_heap_rewrite(Relation old_heap, Relation new_heap, TransactionId oldest_xm
&hash_ctl,
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
- hash_ctl.entrysize = sizeof(OldToNewMappingData);
+ HASH_ELEM_INIT(hash_ctl, OldToNewMappingData, key);
state->rs_old_new_tid_map =
hash_create("Rewrite / Old to new tid map",
@@ -788,8 +787,7 @@ logical_begin_heap_rewrite(RewriteState state)
state->rs_begin_lsn = GetXLogInsertRecPtr();
state->rs_num_rewrite_mappings = 0;
- hash_ctl.keysize = sizeof(TransactionId);
- hash_ctl.entrysize = sizeof(RewriteMappingFile);
+ HASH_ELEM_INIT(hash_ctl, RewriteMappingFile, xid);
hash_ctl.hcxt = state->rs_cxt;
state->rs_logical_mappings =
diff --git a/src/backend/access/transam/xlogprefetcher.c b/src/backend/access/transam/xlogprefetcher.c
index ed3aacabc98..4a22432cbf3 100644
--- a/src/backend/access/transam/xlogprefetcher.c
+++ b/src/backend/access/transam/xlogprefetcher.c
@@ -367,8 +367,7 @@ XLogPrefetcherAllocate(XLogReaderState *reader)
prefetcher = palloc0(sizeof(XLogPrefetcher));
prefetcher->reader = reader;
- ctl.keysize = sizeof(RelFileLocator);
- ctl.entrysize = sizeof(XLogPrefetcherFilter);
+ HASH_ELEM_INIT(ctl, XLogPrefetcherFilter, rlocator);
prefetcher->filter_table = hash_create("XLogPrefetcherFilterTable", 1024,
&ctl, HASH_ELEM | HASH_BLOBS);
dlist_init(&prefetcher->filter_queue);
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index ce2a3e42146..15b5002c105 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -133,8 +133,7 @@ log_invalid_page(RelFileLocator locator, ForkNumber forkno, BlockNumber blkno,
/* create hash table when first needed */
HASHCTL ctl;
- ctl.keysize = sizeof(xl_invalid_page_key);
- ctl.entrysize = sizeof(xl_invalid_page);
+ HASH_ELEM_INIT(ctl, xl_invalid_page, key);
invalid_page_tab = hash_create("XLOG invalid-page table",
100,
diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c
index da9c2a46cfa..4b112b25673 100644
--- a/src/backend/catalog/pg_enum.c
+++ b/src/backend/catalog/pg_enum.c
@@ -269,8 +269,7 @@ init_uncommitted_enum_types(void)
{
HASHCTL hash_ctl;
- hash_ctl.keysize = sizeof(Oid);
- hash_ctl.entrysize = sizeof(Oid);
+ HASH_ELEM_INIT_FULL(hash_ctl, Oid);
hash_ctl.hcxt = TopTransactionContext;
uncommitted_enum_types = hash_create("Uncommitted enum types",
32,
@@ -286,8 +285,7 @@ init_uncommitted_enum_values(void)
{
HASHCTL hash_ctl;
- hash_ctl.keysize = sizeof(Oid);
- hash_ctl.entrysize = sizeof(Oid);
+ HASH_ELEM_INIT_FULL(hash_ctl, Oid);
hash_ctl.hcxt = TopTransactionContext;
uncommitted_enum_values = hash_create("Uncommitted enum values",
32,
diff --git a/src/backend/catalog/pg_inherits.c b/src/backend/catalog/pg_inherits.c
index 929bb53b620..2fd39535156 100644
--- a/src/backend/catalog/pg_inherits.c
+++ b/src/backend/catalog/pg_inherits.c
@@ -261,8 +261,7 @@ find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
*rel_numparents;
ListCell *l;
- ctl.keysize = sizeof(Oid);
- ctl.entrysize = sizeof(SeenRelsEntry);
+ HASH_ELEM_INIT(ctl, SeenRelsEntry, rel_id);
ctl.hcxt = CurrentMemoryContext;
seen_rels = hash_create("find_all_inheritors temporary table",
diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c
index c58e9418ac3..b3f74dc1dbc 100644
--- a/src/backend/catalog/storage.c
+++ b/src/backend/catalog/storage.c
@@ -93,8 +93,7 @@ AddPendingSync(const RelFileLocator *rlocator)
{
HASHCTL ctl;
- ctl.keysize = sizeof(RelFileLocator);
- ctl.entrysize = sizeof(PendingRelSync);
+ HASH_ELEM_INIT(ctl, PendingRelSync, rlocator);
ctl.hcxt = TopTransactionContext;
pendingSyncHash = hash_create("pending sync hash", 16, &ctl,
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
@@ -611,8 +610,7 @@ SerializePendingSyncs(Size maxSize, char *startAddress)
goto terminate;
/* Create temporary hash to collect active relfilelocators */
- ctl.keysize = sizeof(RelFileLocator);
- ctl.entrysize = sizeof(RelFileLocator);
+ HASH_ELEM_INIT_FULL(ctl, RelFileLocator);
ctl.hcxt = CurrentMemoryContext;
tmphash = hash_create("tmp relfilelocators",
hash_get_num_entries(pendingSyncHash), &ctl,
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index eb86402cae4..b9d7bc9b0b8 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -2418,8 +2418,7 @@ AddEventToPendingNotifies(Notification *n)
ListCell *l;
/* Create the hash table */
- hash_ctl.keysize = sizeof(Notification *);
- hash_ctl.entrysize = sizeof(struct NotificationHash);
+ HASH_ELEM_INIT(hash_ctl, struct NotificationHash, event);
hash_ctl.hash = notification_hash;
hash_ctl.match = notification_match;
hash_ctl.hcxt = CurTransactionContext;
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index 34b6410d6a2..64430de2b56 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -373,8 +373,7 @@ InitQueryHashTable(void)
{
HASHCTL hash_ctl;
- hash_ctl.keysize = NAMEDATALEN;
- hash_ctl.entrysize = sizeof(PreparedStatement);
+ HASH_ELEM_INIT(hash_ctl, PreparedStatement, stmt_name);
prepared_queries = hash_create("Prepared Queries",
32,
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 51567994126..cc03a3eebb1 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1115,8 +1115,7 @@ create_seq_hashtable(void)
{
HASHCTL ctl;
- ctl.keysize = sizeof(Oid);
- ctl.entrysize = sizeof(SeqTableData);
+ HASH_ELEM_INIT(ctl, SeqTableData, relid);
seqhashtab = hash_create("Sequence values", 16, &ctl,
HASH_ELEM | HASH_BLOBS);
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 07e5b95782e..abb67da2dd9 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -2158,8 +2158,7 @@ ExecuteTruncateGuts(List *explicit_rels,
HASHCTL hctl;
memset(&hctl, 0, sizeof(HASHCTL));
- hctl.keysize = sizeof(Oid);
- hctl.entrysize = sizeof(ForeignTruncateInfo);
+ HASH_ELEM_INIT(hctl, ForeignTruncateInfo, serverid);
hctl.hcxt = CurrentMemoryContext;
ft_htab = hash_create("TRUNCATE for Foreign Tables",
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index e44f1223886..8d97d0cd66e 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -5136,8 +5136,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
{
HASHCTL hash_ctl;
- hash_ctl.keysize = sizeof(Oid);
- hash_ctl.entrysize = sizeof(MTTargetRelLookup);
+ HASH_ELEM_INIT(hash_ctl, MTTargetRelLookup, relationOid);
hash_ctl.hcxt = CurrentMemoryContext;
mtstate->mt_resultOidHash =
hash_create("ModifyTable target hash",
diff --git a/src/backend/nodes/extensible.c b/src/backend/nodes/extensible.c
index 3ede1ee0f5d..f4f6b659f9f 100644
--- a/src/backend/nodes/extensible.c
+++ b/src/backend/nodes/extensible.c
@@ -47,8 +47,7 @@ RegisterExtensibleNodeEntry(HTAB **p_htable, const char *htable_label,
{
HASHCTL ctl;
- ctl.keysize = EXTNODENAME_MAX_LEN;
- ctl.entrysize = sizeof(ExtensibleNodeEntry);
+ HASH_ELEM_INIT(ctl, ExtensibleNodeEntry, extnodename);
*p_htable = hash_create(htable_label, 100, &ctl,
HASH_ELEM | HASH_STRINGS);
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 07f92fac239..36e9814cac5 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -697,8 +697,7 @@ get_relation_notnullatts(PlannerInfo *root, Relation relation)
HTAB *hashtab;
HASHCTL hash_ctl;
- hash_ctl.keysize = sizeof(Oid);
- hash_ctl.entrysize = sizeof(NotnullHashEntry);
+ HASH_ELEM_INIT(hash_ctl, NotnullHashEntry, relid);
hash_ctl.hcxt = CurrentMemoryContext;
hashtab = hash_create("Relation NOT NULL attnums",
diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c
index ac28573cd0a..0661d68a6c2 100644
--- a/src/backend/optimizer/util/predtest.c
+++ b/src/backend/optimizer/util/predtest.c
@@ -2119,8 +2119,7 @@ lookup_proof_cache(Oid pred_op, Oid clause_op, bool refute_it)
/* First time through: initialize the hash table */
HASHCTL ctl;
- ctl.keysize = sizeof(OprProofCacheKey);
- ctl.entrysize = sizeof(OprProofCacheEntry);
+ HASH_ELEM_INIT(ctl, OprProofCacheEntry, key);
OprProofCacheHash = hash_create("Btree proof lookup cache", 256,
&ctl, HASH_ELEM | HASH_BLOBS);
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 1158bc194c3..52bfab04567 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -605,8 +605,7 @@ build_join_rel_hash(PlannerInfo *root)
ListCell *l;
/* Create the hash table */
- hash_ctl.keysize = sizeof(Relids);
- hash_ctl.entrysize = sizeof(JoinHashEntry);
+ HASH_ELEM_INIT(hash_ctl, JoinHashEntry, join_relids);
hash_ctl.hash = bitmap_hash;
hash_ctl.match = bitmap_match;
hash_ctl.hcxt = CurrentMemoryContext;
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
index 7bd7a336fd6..9c1bfa05ebf 100644
--- a/src/backend/parser/parse_oper.c
+++ b/src/backend/parser/parse_oper.c
@@ -1030,8 +1030,7 @@ find_oper_cache_entry(OprCacheKey *key)
/* First time through: initialize the hash table */
HASHCTL ctl;
- ctl.keysize = sizeof(OprCacheKey);
- ctl.entrysize = sizeof(OprCacheEntry);
+ HASH_ELEM_INIT(ctl, OprCacheEntry, key);
OprCacheHash = hash_create("Operator lookup cache", 256,
&ctl, HASH_ELEM | HASH_BLOBS);
diff --git a/src/backend/partitioning/partdesc.c b/src/backend/partitioning/partdesc.c
index 328b4d450e4..e6f7b26ee98 100644
--- a/src/backend/partitioning/partdesc.c
+++ b/src/backend/partitioning/partdesc.c
@@ -429,8 +429,7 @@ CreatePartitionDirectory(MemoryContext mcxt, bool omit_detached)
pdir = palloc(sizeof(PartitionDirectoryData));
pdir->pdir_mcxt = mcxt;
- ctl.keysize = sizeof(Oid);
- ctl.entrysize = sizeof(PartitionDirectoryEntry);
+ HASH_ELEM_INIT(ctl, PartitionDirectoryEntry, reloid);
ctl.hcxt = mcxt;
pdir->pdir_hash = hash_create("partition directory", 256, &ctl,
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 1c38488f2cb..319fb82ebcc 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -937,8 +937,7 @@ rebuild_database_list(Oid newdb)
* score, and finally put the array elements into the new doubly linked
* list.
*/
- hctl.keysize = sizeof(Oid);
- hctl.entrysize = sizeof(avl_dbase);
+ HASH_ELEM_INIT(hctl, avl_dbase, adl_datid);
hctl.hcxt = tmpcxt;
dbhash = hash_create("autovacuum db hash", 20, &hctl, /* magic number here
* FIXME */
@@ -1977,8 +1976,7 @@ do_autovacuum(void)
pg_class_desc = CreateTupleDescCopy(RelationGetDescr(classRel));
/* create hash table for toast <-> main relid mapping */
- ctl.keysize = sizeof(Oid);
- ctl.entrysize = sizeof(av_relation);
+ HASH_ELEM_INIT(ctl, av_relation, ar_toastrelid);
table_toast_map = hash_create("TOAST to main relid map",
100,
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index e84e8663e96..972b61ec67e 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -1321,8 +1321,7 @@ CompactCheckpointerRequestQueue(void)
head = CheckpointerShmem->head;
/* Initialize temporary hash table */
- ctl.keysize = sizeof(CheckpointerRequest);
- ctl.entrysize = sizeof(struct CheckpointerSlotMapping);
+ HASH_ELEM_INIT(ctl, struct CheckpointerSlotMapping, request);
ctl.hcxt = CurrentMemoryContext;
htab = hash_create("CompactCheckpointerRequestQueue",
diff --git a/src/backend/replication/logical/applyparallelworker.c b/src/backend/replication/logical/applyparallelworker.c
index baa68c1ab6c..43c91ad5179 100644
--- a/src/backend/replication/logical/applyparallelworker.c
+++ b/src/backend/replication/logical/applyparallelworker.c
@@ -487,8 +487,7 @@ pa_allocate_worker(TransactionId xid)
HASHCTL ctl;
MemSet(&ctl, 0, sizeof(ctl));
- ctl.keysize = sizeof(TransactionId);
- ctl.entrysize = sizeof(ParallelApplyWorkerEntry);
+ HASH_ELEM_INIT(ctl, ParallelApplyWorkerEntry, xid);
ctl.hcxt = ApplyContext;
ParallelApplyTxnHash = hash_create("logical replication parallel apply workers hash",
diff --git a/src/backend/replication/logical/relation.c b/src/backend/replication/logical/relation.c
index 10b3d0d9b82..86061323bc1 100644
--- a/src/backend/replication/logical/relation.c
+++ b/src/backend/replication/logical/relation.c
@@ -619,8 +619,7 @@ logicalrep_partmap_init(void)
ALLOCSET_DEFAULT_SIZES);
/* Initialize the relation hash table. */
- ctl.keysize = sizeof(Oid); /* partition OID */
- ctl.entrysize = sizeof(LogicalRepPartMapEntry);
+ HASH_ELEM_INIT(ctl, LogicalRepPartMapEntry, partoid);
ctl.hcxt = LogicalRepPartMapContext;
LogicalRepPartMap = hash_create("logicalrep partition map cache", 64, &ctl,
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index eb6a84554b7..d2c2ee823c9 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -367,8 +367,7 @@ ReorderBufferAllocate(void)
SLAB_DEFAULT_BLOCK_SIZE,
SLAB_DEFAULT_BLOCK_SIZE);
- hash_ctl.keysize = sizeof(TransactionId);
- hash_ctl.entrysize = sizeof(ReorderBufferTXNByIdEnt);
+ HASH_ELEM_INIT(hash_ctl, ReorderBufferTXNByIdEnt, xid);
hash_ctl.hcxt = buffer->context;
buffer->by_txn = hash_create("ReorderBufferByXid", 1000, &hash_ctl,
@@ -1841,8 +1840,7 @@ ReorderBufferBuildTupleCidHash(ReorderBuffer *rb, ReorderBufferTXN *txn)
if (!rbtxn_has_catalog_changes(txn) || dlist_is_empty(&txn->tuplecids))
return;
- hash_ctl.keysize = sizeof(ReorderBufferTupleCidKey);
- hash_ctl.entrysize = sizeof(ReorderBufferTupleCidEnt);
+ HASH_ELEM_INIT(hash_ctl, ReorderBufferTupleCidEnt, key);
hash_ctl.hcxt = rb->context;
/*
@@ -4981,8 +4979,7 @@ ReorderBufferToastInitHash(ReorderBuffer *rb, ReorderBufferTXN *txn)
Assert(txn->toast_hash == NULL);
- hash_ctl.keysize = sizeof(Oid);
- hash_ctl.entrysize = sizeof(ReorderBufferToastEnt);
+ HASH_ELEM_INIT(hash_ctl, ReorderBufferToastEnt, chunk_id);
hash_ctl.hcxt = rb->context;
txn->toast_hash = hash_create("ReorderBufferToastHash", 5, &hash_ctl,
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c
index fa8e3bf969a..e9adaef36a9 100644
--- a/src/backend/replication/logical/tablesync.c
+++ b/src/backend/replication/logical/tablesync.c
@@ -392,8 +392,7 @@ ProcessSyncingTablesForApply(XLogRecPtr current_lsn)
{
HASHCTL ctl;
- ctl.keysize = sizeof(Oid);
- ctl.entrysize = sizeof(struct tablesync_start_time_mapping);
+ HASH_ELEM_INIT(ctl, struct tablesync_start_time_mapping, relid);
last_start_times = hash_create("Logical replication table sync worker start times",
256, &ctl, HASH_ELEM | HASH_BLOBS);
}
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index 942e1abdb58..755c2def1aa 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -1977,8 +1977,7 @@ init_rel_sync_cache(MemoryContext cachectx)
return;
/* Make a new hash table for the cache */
- ctl.keysize = sizeof(Oid);
- ctl.entrysize = sizeof(RelationSyncEntry);
+ HASH_ELEM_INIT(ctl, RelationSyncEntry, relid);
ctl.hcxt = cachectx;
RelationSyncCache = hash_create("logical replication output relation cache",
diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c
index 9d256559bab..350153ead43 100644
--- a/src/backend/storage/buffer/buf_table.c
+++ b/src/backend/storage/buffer/buf_table.c
@@ -55,8 +55,7 @@ InitBufTable(int size)
/* assume no locking is needed yet */
/* BufferTag maps to Buffer */
- info.keysize = sizeof(BufferTag);
- info.entrysize = sizeof(BufferLookupEnt);
+ HASH_ELEM_INIT(info, BufferLookupEnt, key);
info.num_partitions = NUM_BUFFER_PARTITIONS;
SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table",
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index f373cead95f..83a2232a6f6 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -4019,8 +4019,7 @@ InitBufferManagerAccess(void)
memset(&PrivateRefCountArray, 0, sizeof(PrivateRefCountArray));
- hash_ctl.keysize = sizeof(int32);
- hash_ctl.entrysize = sizeof(PrivateRefCountEntry);
+ HASH_ELEM_INIT(hash_ctl, PrivateRefCountEntry, buffer);
PrivateRefCountHash = hash_create("PrivateRefCount", 100, &hash_ctl,
HASH_ELEM | HASH_BLOBS);
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index 15aac7d1c9f..8b9e09ed4b0 100644
--- a/src/backend/storage/buffer/localbuf.c
+++ b/src/backend/storage/buffer/localbuf.c
@@ -779,8 +779,7 @@ InitLocalBuffers(void)
}
/* Create the lookup hash table */
- info.keysize = sizeof(BufferTag);
- info.entrysize = sizeof(LocalBufferLookupEnt);
+ HASH_ELEM_INIT(info, LocalBufferLookupEnt, key);
LocalBufHash = hash_create("Local Buffer Lookup Table",
nbufs,
diff --git a/src/backend/storage/file/reinit.c b/src/backend/storage/file/reinit.c
index 5c8275cf536..6a1438eadb4 100644
--- a/src/backend/storage/file/reinit.c
+++ b/src/backend/storage/file/reinit.c
@@ -184,8 +184,7 @@ ResetUnloggedRelationsInDbspaceDir(const char *dbspacedirname, int op)
* need to be reset. Otherwise, this cleanup operation would be
* O(n^2).
*/
- ctl.keysize = sizeof(Oid);
- ctl.entrysize = sizeof(unlogged_relation_entry);
+ HASH_ELEM_INIT(ctl, unlogged_relation_entry, relnumber);
ctl.hcxt = CurrentMemoryContext;
hash = hash_create("unlogged relation OIDs", 32, &ctl,
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index ee3408df301..15d7149c954 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -294,8 +294,7 @@ InitShmemIndex(void)
* initializing the ShmemIndex itself. The special "ShmemIndex" hash
* table name will tell ShmemInitStruct to fake it.
*/
- info.keysize = SHMEM_INDEX_KEYSIZE;
- info.entrysize = sizeof(ShmemIndexEnt);
+ HASH_ELEM_INIT(info, ShmemIndexEnt, key);
ShmemIndex = ShmemInitHash("ShmemIndex",
SHMEM_INDEX_SIZE, SHMEM_INDEX_SIZE,
diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c
index 4222bdab078..eca82020587 100644
--- a/src/backend/storage/ipc/standby.c
+++ b/src/backend/storage/ipc/standby.c
@@ -103,14 +103,12 @@ InitRecoveryTransactionEnvironment(void)
* Initialize the hash tables for tracking the locks held by each
* transaction.
*/
- hash_ctl.keysize = sizeof(xl_standby_lock);
- hash_ctl.entrysize = sizeof(RecoveryLockEntry);
+ HASH_ELEM_INIT(hash_ctl, RecoveryLockEntry, key);
RecoveryLockHash = hash_create("RecoveryLockHash",
64,
&hash_ctl,
HASH_ELEM | HASH_BLOBS);
- hash_ctl.keysize = sizeof(TransactionId);
- hash_ctl.entrysize = sizeof(RecoveryLockXidEntry);
+ HASH_ELEM_INIT(hash_ctl, RecoveryLockXidEntry, xid);
RecoveryLockXidHash = hash_create("RecoveryLockXidHash",
64,
&hash_ctl,
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index 9cb78ead105..e2f39d41406 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -459,8 +459,7 @@ LockManagerShmemInit(void)
* Allocate hash table for LOCK structs. This stores per-locked-object
* information.
*/
- info.keysize = sizeof(LOCKTAG);
- info.entrysize = sizeof(LOCK);
+ HASH_ELEM_INIT(info, LOCK, tag);
info.num_partitions = NUM_LOCK_PARTITIONS;
LockMethodLockHash = ShmemInitHash("LOCK hash",
@@ -477,8 +476,7 @@ LockManagerShmemInit(void)
* Allocate hash table for PROCLOCK structs. This stores
* per-lock-per-holder information.
*/
- info.keysize = sizeof(PROCLOCKTAG);
- info.entrysize = sizeof(PROCLOCK);
+ HASH_ELEM_INIT(info, PROCLOCK, tag);
info.hash = proclock_hash;
info.num_partitions = NUM_LOCK_PARTITIONS;
@@ -510,8 +508,7 @@ InitLockManagerAccess(void)
*/
HASHCTL info;
- info.keysize = sizeof(LOCALLOCKTAG);
- info.entrysize = sizeof(LOCALLOCK);
+ HASH_ELEM_INIT(info, LOCALLOCK, tag);
LockMethodLocalHash = hash_create("LOCALLOCK hash",
16,
@@ -3402,8 +3399,7 @@ CheckForSessionAndXactLocks(void)
LOCALLOCK *locallock;
/* Create a local hash table keyed by LOCKTAG only */
- hash_ctl.keysize = sizeof(LOCKTAG);
- hash_ctl.entrysize = sizeof(PerLockTagEntry);
+ HASH_ELEM_INIT(hash_ctl, PerLockTagEntry, lock);
hash_ctl.hcxt = CurrentMemoryContext;
lockhtab = hash_create("CheckForSessionAndXactLocks table",
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index 255cfa8fa95..47aed6c13c5 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -305,8 +305,7 @@ init_lwlock_stats(void)
ALLOCSET_DEFAULT_SIZES);
MemoryContextAllowInCriticalSection(lwlock_stats_cxt, true);
- ctl.keysize = sizeof(lwlock_stats_key);
- ctl.entrysize = sizeof(lwlock_stats);
+ HASH_ELEM_INIT(ctl, lwlock_stats, key);
ctl.hcxt = lwlock_stats_cxt;
lwlock_stats_htab = hash_create("lwlock stats", 16384, &ctl,
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c
index f12f8f77aad..571fa39b704 100644
--- a/src/backend/storage/lmgr/predicate.c
+++ b/src/backend/storage/lmgr/predicate.c
@@ -1163,8 +1163,7 @@ PredicateLockShmemInit(void)
* Allocate hash table for PREDICATELOCKTARGET structs. This stores
* per-predicate-lock-target information.
*/
- info.keysize = sizeof(PREDICATELOCKTARGETTAG);
- info.entrysize = sizeof(PREDICATELOCKTARGET);
+ HASH_ELEM_INIT(info, PREDICATELOCKTARGET, tag);
info.num_partitions = NUM_PREDICATELOCK_PARTITIONS;
PredicateLockTargetHash = ShmemInitHash("PREDICATELOCKTARGET hash",
@@ -1195,8 +1194,7 @@ PredicateLockShmemInit(void)
* Allocate hash table for PREDICATELOCK structs. This stores per
* xact-lock-of-a-target information.
*/
- info.keysize = sizeof(PREDICATELOCKTAG);
- info.entrysize = sizeof(PREDICATELOCK);
+ HASH_ELEM_INIT(info, PREDICATELOCK, tag);
info.hash = predicatelock_hash;
info.num_partitions = NUM_PREDICATELOCK_PARTITIONS;
@@ -1282,8 +1280,7 @@ PredicateLockShmemInit(void)
* Allocate hash table for SERIALIZABLEXID structs. This stores per-xid
* information for serializable transactions which have accessed data.
*/
- info.keysize = sizeof(SERIALIZABLEXIDTAG);
- info.entrysize = sizeof(SERIALIZABLEXID);
+ HASH_ELEM_INIT(info, SERIALIZABLEXID, tag);
SerializableXidHash = ShmemInitHash("SERIALIZABLEXID hash",
max_table_size,
@@ -1943,8 +1940,7 @@ CreateLocalPredicateLockHash(void)
/* Initialize the backend-local hash table of parent locks */
Assert(LocalPredicateLockHash == NULL);
- hash_ctl.keysize = sizeof(PREDICATELOCKTARGETTAG);
- hash_ctl.entrysize = sizeof(LOCALPREDICATELOCK);
+ HASH_ELEM_INIT(hash_ctl, LOCALPREDICATELOCK, tag);
LocalPredicateLockHash = hash_create("Local predicate lock",
max_predicate_locks_per_xact,
&hash_ctl,
diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c
index bce37a36d51..22da64f0bad 100644
--- a/src/backend/storage/smgr/smgr.c
+++ b/src/backend/storage/smgr/smgr.c
@@ -252,8 +252,7 @@ smgropen(RelFileLocator rlocator, ProcNumber backend)
/* First time through: initialize the hash table */
HASHCTL ctl;
- ctl.keysize = sizeof(RelFileLocatorBackend);
- ctl.entrysize = sizeof(SMgrRelationData);
+ HASH_ELEM_INIT(ctl, SMgrRelationData, smgr_rlocator);
SMgrRelationHash = hash_create("smgr relation table", 400,
&ctl, HASH_ELEM | HASH_BLOBS);
dlist_init(&unpinned_relns);
diff --git a/src/backend/storage/sync/sync.c b/src/backend/storage/sync/sync.c
index fc16db90133..654d4aeb51e 100644
--- a/src/backend/storage/sync/sync.c
+++ b/src/backend/storage/sync/sync.c
@@ -146,8 +146,7 @@ InitSync(void)
ALLOCSET_DEFAULT_SIZES);
MemoryContextAllowInCriticalSection(pendingOpsCxt, true);
- hash_ctl.keysize = sizeof(FileTag);
- hash_ctl.entrysize = sizeof(PendingFsyncEntry);
+ HASH_ELEM_INIT(hash_ctl, PendingFsyncEntry, tag);
hash_ctl.hcxt = pendingOpsCxt;
pendingOps = hash_create("Pending Ops Table",
100L,
diff --git a/src/backend/tsearch/ts_typanalyze.c b/src/backend/tsearch/ts_typanalyze.c
index 93aab00a3ca..3415b930fb5 100644
--- a/src/backend/tsearch/ts_typanalyze.c
+++ b/src/backend/tsearch/ts_typanalyze.c
@@ -180,8 +180,7 @@ compute_tsvector_stats(VacAttrStats *stats,
* worry about overflowing the initial size. Also we don't need to pay any
* attention to locking and memory management.
*/
- hash_ctl.keysize = sizeof(LexemeHashKey);
- hash_ctl.entrysize = sizeof(TrackItem);
+ HASH_ELEM_INIT(hash_ctl, TrackItem, key);
hash_ctl.hash = lexeme_hash;
hash_ctl.match = lexeme_match;
hash_ctl.hcxt = CurrentMemoryContext;
diff --git a/src/backend/utils/activity/wait_event.c b/src/backend/utils/activity/wait_event.c
index d9b8f34a355..b47de48f5d7 100644
--- a/src/backend/utils/activity/wait_event.c
+++ b/src/backend/utils/activity/wait_event.c
@@ -133,8 +133,7 @@ WaitEventCustomShmemInit(void)
}
/* initialize or attach the hash tables to store custom wait events */
- info.keysize = sizeof(uint32);
- info.entrysize = sizeof(WaitEventCustomEntryByInfo);
+ HASH_ELEM_INIT(info, WaitEventCustomEntryByInfo, wait_event_info);
WaitEventCustomHashByInfo =
ShmemInitHash("WaitEventCustom hash by wait event information",
WAIT_EVENT_CUSTOM_HASH_INIT_SIZE,
@@ -143,8 +142,7 @@ WaitEventCustomShmemInit(void)
HASH_ELEM | HASH_BLOBS);
/* key is a NULL-terminated string */
- info.keysize = sizeof(char[NAMEDATALEN]);
- info.entrysize = sizeof(WaitEventCustomEntryByName);
+ HASH_ELEM_INIT(info, WaitEventCustomEntryByName, wait_event_name);
WaitEventCustomHashByName =
ShmemInitHash("WaitEventCustom hash by name",
WAIT_EVENT_CUSTOM_HASH_INIT_SIZE,
diff --git a/src/backend/utils/adt/array_typanalyze.c b/src/backend/utils/adt/array_typanalyze.c
index 560b27f3ca7..db68c7a4127 100644
--- a/src/backend/utils/adt/array_typanalyze.c
+++ b/src/backend/utils/adt/array_typanalyze.c
@@ -276,8 +276,7 @@ compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
* worry about overflowing the initial size. Also we don't need to pay any
* attention to locking and memory management.
*/
- elem_hash_ctl.keysize = sizeof(Datum);
- elem_hash_ctl.entrysize = sizeof(TrackItem);
+ HASH_ELEM_INIT(elem_hash_ctl, TrackItem, key);
elem_hash_ctl.hash = element_hash;
elem_hash_ctl.match = element_match;
elem_hash_ctl.hcxt = CurrentMemoryContext;
@@ -287,8 +286,7 @@ compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
HASH_ELEM | HASH_FUNCTION | HASH_COMPARE | HASH_CONTEXT);
/* hashtable for array distinct elements counts */
- count_hash_ctl.keysize = sizeof(int);
- count_hash_ctl.entrysize = sizeof(DECountItem);
+ HASH_ELEM_INIT(count_hash_ctl, DECountItem, count);
count_hash_ctl.hcxt = CurrentMemoryContext;
count_tab = hash_create("Array distinct element count table",
64,
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index 06dd62f0008..39e1adee19f 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -936,8 +936,7 @@ json_unique_check_init(JsonUniqueCheckState *cxt)
HASHCTL ctl;
memset(&ctl, 0, sizeof(ctl));
- ctl.keysize = sizeof(JsonUniqueHashEntry);
- ctl.entrysize = sizeof(JsonUniqueHashEntry);
+ HASH_ELEM_INIT_FULL(ctl, JsonUniqueHashEntry);
ctl.hcxt = CurrentMemoryContext;
ctl.hash = json_unique_hash;
ctl.match = json_unique_hash_match;
diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c
index de32e329975..e7d06bdcde0 100644
--- a/src/backend/utils/adt/jsonfuncs.c
+++ b/src/backend/utils/adt/jsonfuncs.c
@@ -3816,8 +3816,7 @@ get_json_object_as_hash(const char *json, int len, const char *funcname,
JHashState *state;
JsonSemAction *sem;
- ctl.keysize = NAMEDATALEN;
- ctl.entrysize = sizeof(JsonHashEntry);
+ HASH_ELEM_INIT(ctl, JsonHashEntry, fname);
ctl.hcxt = CurrentMemoryContext;
tab = hash_create("json object hashtable",
100,
@@ -4230,8 +4229,7 @@ populate_recordset_object_start(void *state)
return JSON_SUCCESS;
/* Object at level 1: set up a new hash table for this object */
- ctl.keysize = NAMEDATALEN;
- ctl.entrysize = sizeof(JsonHashEntry);
+ HASH_ELEM_INIT(ctl, JsonHashEntry, fname);
ctl.hcxt = CurrentMemoryContext;
_state->json_hash = hash_create("json object hashtable",
100,
diff --git a/src/backend/utils/adt/mcxtfuncs.c b/src/backend/utils/adt/mcxtfuncs.c
index fe6dce9cba3..700403b7d3f 100644
--- a/src/backend/utils/adt/mcxtfuncs.c
+++ b/src/backend/utils/adt/mcxtfuncs.c
@@ -188,8 +188,7 @@ pg_get_backend_memory_contexts(PG_FUNCTION_ARGS)
HASHCTL ctl;
HTAB *context_id_lookup;
- ctl.keysize = sizeof(MemoryContext);
- ctl.entrysize = sizeof(MemoryContextId);
+ HASH_ELEM_INIT(ctl, MemoryContextId, context);
ctl.hcxt = CurrentMemoryContext;
context_id_lookup = hash_create("pg_get_backend_memory_contexts",
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index 059fc5ebf60..c48b8d3e1b2 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -2859,8 +2859,7 @@ ri_InitHashTables(void)
{
HASHCTL ctl;
- ctl.keysize = sizeof(Oid);
- ctl.entrysize = sizeof(RI_ConstraintInfo);
+ HASH_ELEM_INIT(ctl, RI_ConstraintInfo, constraint_id);
ri_constraint_cache = hash_create("RI constraint cache",
RI_INIT_CONSTRAINTHASHSIZE,
&ctl, HASH_ELEM | HASH_BLOBS);
@@ -2870,14 +2869,12 @@ ri_InitHashTables(void)
InvalidateConstraintCacheCallBack,
(Datum) 0);
- ctl.keysize = sizeof(RI_QueryKey);
- ctl.entrysize = sizeof(RI_QueryHashEntry);
+ HASH_ELEM_INIT(ctl, RI_QueryHashEntry, key);
ri_query_cache = hash_create("RI query cache",
RI_INIT_QUERYHASHSIZE,
&ctl, HASH_ELEM | HASH_BLOBS);
- ctl.keysize = sizeof(RI_CompareKey);
- ctl.entrysize = sizeof(RI_CompareHashEntry);
+ HASH_ELEM_INIT(ctl, RI_CompareHashEntry, key);
ri_compare_cache = hash_create("RI compare cache",
RI_INIT_QUERYHASHSIZE,
&ctl, HASH_ELEM | HASH_BLOBS);
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 6cf90be40bb..e2af22c6fb5 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3903,8 +3903,7 @@ set_rtable_names(deparse_namespace *dpns, List *parent_namespaces,
* We use a hash table to hold known names, so that this process is O(N)
* not O(N^2) for N names.
*/
- hash_ctl.keysize = NAMEDATALEN;
- hash_ctl.entrysize = sizeof(NameHashEntry);
+ HASH_ELEM_INIT(hash_ctl, NameHashEntry, name);
hash_ctl.hcxt = CurrentMemoryContext;
names_hash = hash_create("set_rtable_names names",
list_length(dpns->rtable),
diff --git a/src/backend/utils/cache/attoptcache.c b/src/backend/utils/cache/attoptcache.c
index 45d1e2be007..74f6221e737 100644
--- a/src/backend/utils/cache/attoptcache.c
+++ b/src/backend/utils/cache/attoptcache.c
@@ -99,8 +99,7 @@ InitializeAttoptCache(void)
HASHCTL ctl;
/* Initialize the hash table. */
- ctl.keysize = sizeof(AttoptCacheKey);
- ctl.entrysize = sizeof(AttoptCacheEntry);
+ HASH_ELEM_INIT(ctl, AttoptCacheEntry, key);
/*
* AttoptCacheEntry takes hash value from the system cache. For
diff --git a/src/backend/utils/cache/evtcache.c b/src/backend/utils/cache/evtcache.c
index b9d5a5998be..1eaecebbf58 100644
--- a/src/backend/utils/cache/evtcache.c
+++ b/src/backend/utils/cache/evtcache.c
@@ -113,8 +113,7 @@ BuildEventTriggerCache(void)
EventTriggerCacheState = ETCS_REBUILD_STARTED;
/* Create new hash table. */
- ctl.keysize = sizeof(EventTriggerEvent);
- ctl.entrysize = sizeof(EventTriggerCacheEntry);
+ HASH_ELEM_INIT(ctl, EventTriggerCacheEntry, event);
ctl.hcxt = EventTriggerCacheContext;
cache = hash_create("EventTriggerCacheHash", 32, &ctl,
HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
diff --git a/src/backend/utils/cache/funccache.c b/src/backend/utils/cache/funccache.c
index afc048a051e..cdb1b8477cd 100644
--- a/src/backend/utils/cache/funccache.c
+++ b/src/backend/utils/cache/funccache.c
@@ -63,8 +63,7 @@ cfunc_hashtable_init(void)
/* don't allow double-initialization */
Assert(cfunc_hashtable == NULL);
- ctl.keysize = sizeof(CachedFunctionHashKey);
- ctl.entrysize = sizeof(CachedFunctionHashEntry);
+ HASH_ELEM_INIT(ctl, CachedFunctionHashEntry, key);
ctl.hash = cfunc_hash;
ctl.match = cfunc_match;
cfunc_hashtable = hash_create("Cached function hash",
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 915d0bc9084..e366bff6a90 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -1684,8 +1684,7 @@ LookupOpclassInfo(Oid operatorClassOid,
if (!CacheMemoryContext)
CreateCacheMemoryContext();
- ctl.keysize = sizeof(Oid);
- ctl.entrysize = sizeof(OpClassCacheEnt);
+ HASH_ELEM_INIT(ctl, OpClassCacheEnt, opclassoid);
OpClassCache = hash_create("Operator class cache", 64,
&ctl, HASH_ELEM | HASH_BLOBS);
}
@@ -4013,8 +4012,7 @@ RelationCacheInitialize(void)
/*
* create hashtable that indexes the relcache
*/
- ctl.keysize = sizeof(Oid);
- ctl.entrysize = sizeof(RelIdCacheEnt);
+ HASH_ELEM_INIT(ctl, RelIdCacheEnt, reloid);
RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
&ctl, HASH_ELEM | HASH_BLOBS);
diff --git a/src/backend/utils/cache/relfilenumbermap.c b/src/backend/utils/cache/relfilenumbermap.c
index 0b6f9cf3fa1..50568dc4139 100644
--- a/src/backend/utils/cache/relfilenumbermap.c
+++ b/src/backend/utils/cache/relfilenumbermap.c
@@ -113,8 +113,7 @@ InitializeRelfilenumberMap(void)
* initialized when fmgr_info_cxt() above ERRORs out with an out of memory
* error.
*/
- ctl.keysize = sizeof(RelfilenumberMapKey);
- ctl.entrysize = sizeof(RelfilenumberMapEntry);
+ HASH_ELEM_INIT(ctl, RelfilenumberMapEntry, key);
ctl.hcxt = CacheMemoryContext;
RelfilenumberMapHash =
diff --git a/src/backend/utils/cache/spccache.c b/src/backend/utils/cache/spccache.c
index 23458599298..447e75787fd 100644
--- a/src/backend/utils/cache/spccache.c
+++ b/src/backend/utils/cache/spccache.c
@@ -80,8 +80,7 @@ InitializeTableSpaceCache(void)
HASHCTL ctl;
/* Initialize the hash table. */
- ctl.keysize = sizeof(Oid);
- ctl.entrysize = sizeof(TableSpaceCacheEntry);
+ HASH_ELEM_INIT(ctl, TableSpaceCacheEntry, oid);
TableSpaceCacheHash =
hash_create("TableSpace cache", 16, &ctl,
HASH_ELEM | HASH_BLOBS);
diff --git a/src/backend/utils/cache/ts_cache.c b/src/backend/utils/cache/ts_cache.c
index e8ae53238d0..b10e75b3d49 100644
--- a/src/backend/utils/cache/ts_cache.c
+++ b/src/backend/utils/cache/ts_cache.c
@@ -119,8 +119,7 @@ lookup_ts_parser_cache(Oid prsId)
/* First time through: initialize the hash table */
HASHCTL ctl;
- ctl.keysize = sizeof(Oid);
- ctl.entrysize = sizeof(TSParserCacheEntry);
+ HASH_ELEM_INIT(ctl, TSParserCacheEntry, prsId);
TSParserCacheHash = hash_create("Tsearch parser cache", 4,
&ctl, HASH_ELEM | HASH_BLOBS);
/* Flush cache on pg_ts_parser changes */
@@ -214,8 +213,7 @@ lookup_ts_dictionary_cache(Oid dictId)
/* First time through: initialize the hash table */
HASHCTL ctl;
- ctl.keysize = sizeof(Oid);
- ctl.entrysize = sizeof(TSDictionaryCacheEntry);
+ HASH_ELEM_INIT(ctl, TSDictionaryCacheEntry, dictId);
TSDictionaryCacheHash = hash_create("Tsearch dictionary cache", 8,
&ctl, HASH_ELEM | HASH_BLOBS);
/* Flush cache on pg_ts_dict and pg_ts_template changes */
@@ -365,8 +363,7 @@ init_ts_config_cache(void)
{
HASHCTL ctl;
- ctl.keysize = sizeof(Oid);
- ctl.entrysize = sizeof(TSConfigCacheEntry);
+ HASH_ELEM_INIT(ctl, TSConfigCacheEntry, cfgId);
TSConfigCacheHash = hash_create("Tsearch configuration cache", 16,
&ctl, HASH_ELEM | HASH_BLOBS);
/* Flush cache on pg_ts_config and pg_ts_config_map changes */
diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c
index 6a347698edf..0318fa45783 100644
--- a/src/backend/utils/cache/typcache.c
+++ b/src/backend/utils/cache/typcache.c
@@ -395,8 +395,7 @@ lookup_type_cache(Oid type_id, int flags)
HASHCTL ctl;
int allocsize;
- ctl.keysize = sizeof(Oid);
- ctl.entrysize = sizeof(TypeCacheEntry);
+ HASH_ELEM_INIT(ctl, TypeCacheEntry, type_id);
/*
* TypeCacheEntry takes hash value from the system cache. For
@@ -410,8 +409,7 @@ lookup_type_cache(Oid type_id, int flags)
Assert(RelIdToTypeIdCacheHash == NULL);
- ctl.keysize = sizeof(Oid);
- ctl.entrysize = sizeof(RelIdToTypeIdCacheEntry);
+ HASH_ELEM_INIT(ctl, RelIdToTypeIdCacheEntry, relid);
RelIdToTypeIdCacheHash = hash_create("Map from relid to OID of cached composite type", 64,
&ctl, HASH_ELEM | HASH_BLOBS);
@@ -2052,8 +2050,7 @@ assign_record_type_typmod(TupleDesc tupDesc)
/* First time through: initialize the hash table */
HASHCTL ctl;
- ctl.keysize = sizeof(TupleDesc); /* just the pointer */
- ctl.entrysize = sizeof(RecordCacheEntry);
+ HASH_ELEM_INIT(ctl, RecordCacheEntry, tupdesc);
ctl.hash = record_type_typmod_hash;
ctl.match = record_type_typmod_compare;
RecordCacheHash = hash_create("Record information cache", 64,
diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c
index 1366521f471..1b0f6cdad17 100644
--- a/src/backend/utils/fmgr/dfmgr.c
+++ b/src/backend/utils/fmgr/dfmgr.c
@@ -673,8 +673,7 @@ find_rendezvous_variable(const char *varName)
{
HASHCTL ctl;
- ctl.keysize = NAMEDATALEN;
- ctl.entrysize = sizeof(rendezvousHashEntry);
+ HASH_ELEM_INIT(ctl, rendezvousHashEntry, varName);
rendezvousHash = hash_create("Rendezvous variable hash",
16,
&ctl,
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 0fe63c6bb83..8cd1dfa1ae1 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -549,8 +549,7 @@ record_C_func(HeapTuple procedureTuple,
{
HASHCTL hash_ctl;
- hash_ctl.keysize = sizeof(Oid);
- hash_ctl.entrysize = sizeof(CFuncHashTabEntry);
+ HASH_ELEM_INIT(hash_ctl, CFuncHashTabEntry, fn_oid);
CFuncHash = hash_create("CFuncHash",
100,
&hash_ctl,
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index c6484aea087..3d66f5ab1b9 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -894,8 +894,7 @@ build_guc_variables(void)
*/
size_vars = num_vars + num_vars / 4;
- hash_ctl.keysize = sizeof(char *);
- hash_ctl.entrysize = sizeof(GUCHashEntry);
+ HASH_ELEM_INIT(hash_ctl, GUCHashEntry, gucname);
hash_ctl.hash = guc_name_hash;
hash_ctl.match = guc_name_match;
hash_ctl.hcxt = GUCMemoryContext;
diff --git a/src/backend/utils/misc/injection_point.c b/src/backend/utils/misc/injection_point.c
index d02618c7ffe..696d89cd125 100644
--- a/src/backend/utils/misc/injection_point.c
+++ b/src/backend/utils/misc/injection_point.c
@@ -129,8 +129,7 @@ injection_point_cache_add(const char *name,
{
HASHCTL hash_ctl;
- hash_ctl.keysize = sizeof(char[INJ_NAME_MAXLEN]);
- hash_ctl.entrysize = sizeof(InjectionPointCacheEntry);
+ HASH_ELEM_INIT(hash_ctl, InjectionPointCacheEntry, name);
hash_ctl.hcxt = TopMemoryContext;
InjectionPointCache = hash_create("InjectionPoint cache hash",
diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c
index 943da087c9f..8f89ac94ddd 100644
--- a/src/backend/utils/mmgr/portalmem.c
+++ b/src/backend/utils/mmgr/portalmem.c
@@ -111,8 +111,8 @@ EnablePortalManager(void)
"TopPortalContext",
ALLOCSET_DEFAULT_SIZES);
- ctl.keysize = MAX_PORTALNAME_LEN;
- ctl.entrysize = sizeof(PortalHashEnt);
+ HASH_ELEM_INIT(ctl, PortalHashEnt, portalname);
+
/*
* use PORTALS_PER_USER as a guess of how many hash table entries to
diff --git a/src/backend/utils/time/combocid.c b/src/backend/utils/time/combocid.c
index 1e815571570..676191f517e 100644
--- a/src/backend/utils/time/combocid.c
+++ b/src/backend/utils/time/combocid.c
@@ -223,8 +223,7 @@ GetComboCommandId(CommandId cmin, CommandId cmax)
sizeComboCids = CCID_ARRAY_SIZE;
usedComboCids = 0;
- hash_ctl.keysize = sizeof(ComboCidKeyData);
- hash_ctl.entrysize = sizeof(ComboCidEntryData);
+ HASH_ELEM_INIT(hash_ctl, ComboCidEntryData, key);
hash_ctl.hcxt = TopTransactionContext;
comboHash = hash_create("Combo CIDs",
diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h
index cb09a4cbe8c..8fb4ae82b26 100644
--- a/src/include/utils/hsearch.h
+++ b/src/include/utils/hsearch.h
@@ -107,6 +107,41 @@ typedef struct HASHCTL
/* max_dsize value to indicate expansible directory */
#define NO_MAX_DSIZE (-1)
+/*
+ * Initialize hash table elements with type safety.
+ *
+ * This macro sets up the keysize and entrysize fields of a HASHCTL structure
+ * in a type-safe manner. It ensures:
+ *
+ * 1. The key member is at offset 0 in the entry structure
+ * 2. The key size is derived from the actual member type
+ * 3. The key member is explicitly referenced
+ *
+ * This replaces the error prone pattern:
+ *
+ * ctl.keysize = sizeof(KeyType);
+ * ctl.entrysize = sizeof(MyHashEntry);
+ */
+#define HASH_ELEM_INIT(ctl, entrytype, keymember) \
+ do { \
+ StaticAssertStmt(offsetof(entrytype, keymember) == 0, \
+ #keymember " must be first member in " #entrytype); \
+ (ctl).keysize = sizeof(((entrytype *)0)->keymember); \
+ (ctl).entrysize = sizeof(entrytype); \
+ } while (0)
+
+/*
+ * Initialize hash table elements where the whole entry is the key.
+ *
+ * This macro is used for the special case where the hash table entry structure
+ * itself serves as the key.
+ */
+#define HASH_ELEM_INIT_FULL(ctl, entrytype) \
+ do { \
+ (ctl).keysize = sizeof(entrytype); \
+ (ctl).entrysize = sizeof(entrytype); \
+ } while (0)
+
/* hash_search operations */
typedef enum
{
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 73ba1748fe0..320c9019cd2 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -460,15 +460,13 @@ _PG_init(void)
/*
* Create hash tables.
*/
- hash_ctl.keysize = sizeof(Oid);
- hash_ctl.entrysize = sizeof(plperl_interp_desc);
+ HASH_ELEM_INIT(hash_ctl, plperl_interp_desc, user_id);
plperl_interp_hash = hash_create("PL/Perl interpreters",
8,
&hash_ctl,
HASH_ELEM | HASH_BLOBS);
- hash_ctl.keysize = sizeof(plperl_proc_key);
- hash_ctl.entrysize = sizeof(plperl_proc_ptr);
+ HASH_ELEM_INIT(hash_ctl, plperl_proc_ptr, proc_key);
plperl_proc_hash = hash_create("PL/Perl procedures",
32,
&hash_ctl,
@@ -580,8 +578,7 @@ select_perl_context(bool trusted)
{
HASHCTL hash_ctl;
- hash_ctl.keysize = NAMEDATALEN;
- hash_ctl.entrysize = sizeof(plperl_query_entry);
+ HASH_ELEM_INIT(hash_ctl, plperl_query_entry, query_name);
interp_desc->query_hash = hash_create("PL/Perl queries",
32,
&hash_ctl,
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index d19425b7a71..5185e8880ae 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -4052,8 +4052,7 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate,
/* Create the session-wide cast-expression hash if we didn't already */
if (cast_expr_hash == NULL)
{
- ctl.keysize = sizeof(plpgsql_CastHashKey);
- ctl.entrysize = sizeof(plpgsql_CastExprHashEntry);
+ HASH_ELEM_INIT(ctl, plpgsql_CastExprHashEntry, key);
cast_expr_hash = hash_create("PLpgSQL cast expressions",
16, /* start small and extend */
&ctl,
@@ -4065,8 +4064,7 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate,
{
estate->simple_eval_estate = simple_eval_estate;
/* Private cast hash just lives in function's main context */
- ctl.keysize = sizeof(plpgsql_CastHashKey);
- ctl.entrysize = sizeof(plpgsql_CastHashEntry);
+ HASH_ELEM_INIT(ctl, plpgsql_CastHashEntry, key);
ctl.hcxt = CurrentMemoryContext;
estate->cast_hash = hash_create("PLpgSQL private cast cache",
16, /* start small and extend */
@@ -4079,8 +4077,7 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate,
/* Create the session-wide cast-info hash table if we didn't already */
if (shared_cast_hash == NULL)
{
- ctl.keysize = sizeof(plpgsql_CastHashKey);
- ctl.entrysize = sizeof(plpgsql_CastHashEntry);
+ HASH_ELEM_INIT(ctl, plpgsql_CastHashEntry, key);
shared_cast_hash = hash_create("PLpgSQL cast cache",
16, /* start small and extend */
&ctl,
diff --git a/src/pl/plpython/plpy_plpymodule.c b/src/pl/plpython/plpy_plpymodule.c
index 89931612c5b..3931f4cecc4 100644
--- a/src/pl/plpython/plpy_plpymodule.c
+++ b/src/pl/plpython/plpy_plpymodule.c
@@ -193,8 +193,7 @@ PLy_add_exceptions(PyObject *plpy)
PLy_exc_spi_error = PLy_create_exception("plpy.SPIError", NULL, NULL,
"SPIError", plpy);
- hash_ctl.keysize = sizeof(int);
- hash_ctl.entrysize = sizeof(PLyExceptionEntry);
+ HASH_ELEM_INIT(hash_ctl, PLyExceptionEntry, sqlstate);
PLy_spi_exceptions = hash_create("PL/Python SPI exceptions", 256,
&hash_ctl, HASH_ELEM | HASH_BLOBS);
diff --git a/src/pl/plpython/plpy_procedure.c b/src/pl/plpython/plpy_procedure.c
index 655ab1d09ee..075e24c027c 100644
--- a/src/pl/plpython/plpy_procedure.c
+++ b/src/pl/plpython/plpy_procedure.c
@@ -31,8 +31,7 @@ init_procedure_caches(void)
{
HASHCTL hash_ctl;
- hash_ctl.keysize = sizeof(PLyProcedureKey);
- hash_ctl.entrysize = sizeof(PLyProcedureEntry);
+ HASH_ELEM_INIT(hash_ctl, PLyProcedureEntry, key);
PLy_procedure_cache = hash_create("PL/Python procedures", 32, &hash_ctl,
HASH_ELEM | HASH_BLOBS);
}
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 73d660e88a6..963d6b0d0a0 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -446,8 +446,7 @@ _PG_init(void)
/************************************************************
* Create the hash table for working interpreters
************************************************************/
- hash_ctl.keysize = sizeof(Oid);
- hash_ctl.entrysize = sizeof(pltcl_interp_desc);
+ HASH_ELEM_INIT(hash_ctl, pltcl_interp_desc, user_id);
pltcl_interp_htab = hash_create("PL/Tcl interpreters",
8,
&hash_ctl,
@@ -456,8 +455,7 @@ _PG_init(void)
/************************************************************
* Create the hash table for function lookup
************************************************************/
- hash_ctl.keysize = sizeof(pltcl_proc_key);
- hash_ctl.entrysize = sizeof(pltcl_proc_ptr);
+ HASH_ELEM_INIT(hash_ctl, pltcl_proc_ptr, proc_key);
pltcl_proc_htab = hash_create("PL/Tcl functions",
100,
&hash_ctl,
diff --git a/src/timezone/pgtz.c b/src/timezone/pgtz.c
index 504c0235ffb..24f411a6738 100644
--- a/src/timezone/pgtz.c
+++ b/src/timezone/pgtz.c
@@ -203,8 +203,7 @@ init_timezone_hashtable(void)
{
HASHCTL hash_ctl;
- hash_ctl.keysize = TZ_STRLEN_MAX + 1;
- hash_ctl.entrysize = sizeof(pg_tz_cache);
+ HASH_ELEM_INIT(hash_ctl, pg_tz_cache, tznameupper);
timezone_cache = hash_create("Timezones",
4,
--
2.34.1
--Mm7e/lTiPFa8Qm1V--
view thread (17+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected]
Subject: Re: [PATCH v1] Safer hash table initialization macro
In-Reply-To: <no-message-id-882680@localhost>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox