Hi, On Mon, Dec 01, 2025 at 03:44:41PM +0100, Jelte Fennema-Nio wrote: > On Mon, 1 Dec 2025 at 14:45, Bertrand Drouvot > <[email protected]> wrote: > > Thoughts? > > I think the hashtable creation API in postgres is so terrible that it > actively discourages usage.
Thanks for sharing your thoughts! > So I'm definitely in favor of improving this API (probably by adding a > few new functions). I have a few main thoughts on what could be > improved: > > 1. Automatically determine keysize and entrysize given a keymember and > entrytype (like you suggested). PFA a patch introducing and using the new macro. Note that it also introduces HASH_ELEM_INIT_FULL for the rare cases where the whole struct is the key. Also one case remains untouched: $ git grep "entrysize = sizeof" "*.c" src/backend/replication/logical/relation.c: ctl.entrysize = sizeof(LogicalRepRelMapEntry); That's because the key is a member of a nested struct so that the new macro can not be used. As there is only one occurrence of it, I think we can keep it as it is. But we could create a dedicated macro for those cases if we feel the need. Now that I'm writing this, that might be a better idea: that way we'd avoid any "entrysize/keysize = " in the .c files. Also a nice side effect of using the macros: 138 insertions(+), 203 deletions(-) > 2. Autodect most of the flags. > a. HASH_PARTITION, HASH_SEGMENT, HASH_FUNCTION, HASH_DIRSIZE, > HASH_COMPARE, HASH_KEYCOPY, HASH_ALLOC can all be simply be detected > based on the relevant fields from HASHCTL. Passing them in explicitly > is just duplication that causes code noise and is easy to forget > accidentally. > b. HASH_ELEM is useless noise because it is required > c. HASH_BLOBS could be the default (and maybe use HASH_STRINGS by > default if the keytype is char*) > 3. Default to CurrentMemoryContext instead of TopMemoryContext. Like > all of the other functions that allocate, because right now it's way > too easy to accidentally use TopMemoryContext when you did not intend > to. > 4. Have a creation function that doesn't require HASHCTL at all (just > takes entrytype and keymember and maybe a version of this that takes a > memorycontext). Thanks for the above suggestions! I did not think so deep as you did during your Citus time, but will think about those too. I suggest we move forward one step at a time, first step being the new macros. Does that make sense to you? Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com
>From ade7d7f0ec65018c364429106808db16c68e2990 Mon Sep 17 00:00:00 2001 From: Bertrand Drouvot <[email protected]> Date: Tue, 2 Dec 2025 08:07:20 +0000 Subject: [PATCH v1] Safer hash table initialization macro 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
