Commit 4a14f13a authored by Tom Lane's avatar Tom Lane

Improve hash_create's API for selecting simple-binary-key hash functions.

Previously, if you wanted anything besides C-string hash keys, you had to
specify a custom hashing function to hash_create().  Nearly all such
callers were specifying tag_hash or oid_hash; which is tedious, and rather
error-prone, since a caller could easily miss the opportunity to optimize
by using hash_uint32 when appropriate.  Replace this with a design whereby
callers using simple binary-data keys just specify HASH_BLOBS and don't
need to mess with specific support functions.  hash_create() itself will
take care of optimizing when the key size is four bytes.

This nets out saving a few hundred bytes of code space, and offers
a measurable performance improvement in tidbitmap.c (which was not
exploiting the opportunity to use hash_uint32 for its 4-byte keys).
There might be some wins elsewhere too, I didn't analyze closely.

In future we could look into offering a similar optimized hashing function
for 8-byte keys.  Under this design that could be done in a centralized
and machine-independent fashion, whereas getting it right for keys of
platform-dependent sizes would've been notationally painful before.

For the moment, the old way still works fine, so as not to break source
code compatibility for loadable modules.  Eventually we might want to
remove tag_hash and friends from the exported API altogether, since there's
no real need for them to be explicitly referenced from outside dynahash.c.

Teodor Sigaev and Tom Lane
parent ba94518a
...@@ -915,11 +915,10 @@ transformGraph(TrgmNFA *trgmNFA) ...@@ -915,11 +915,10 @@ transformGraph(TrgmNFA *trgmNFA)
hashCtl.keysize = sizeof(TrgmStateKey); hashCtl.keysize = sizeof(TrgmStateKey);
hashCtl.entrysize = sizeof(TrgmState); hashCtl.entrysize = sizeof(TrgmState);
hashCtl.hcxt = CurrentMemoryContext; hashCtl.hcxt = CurrentMemoryContext;
hashCtl.hash = tag_hash;
trgmNFA->states = hash_create("Trigram NFA", trgmNFA->states = hash_create("Trigram NFA",
1024, 1024,
&hashCtl, &hashCtl,
HASH_ELEM | HASH_CONTEXT | HASH_FUNCTION); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
/* Create initial state: ambiguous prefix, NFA's initial state */ /* Create initial state: ambiguous prefix, NFA's initial state */
MemSet(&initkey, 0, sizeof(initkey)); MemSet(&initkey, 0, sizeof(initkey));
......
...@@ -109,12 +109,11 @@ GetConnection(ForeignServer *server, UserMapping *user, ...@@ -109,12 +109,11 @@ GetConnection(ForeignServer *server, UserMapping *user,
MemSet(&ctl, 0, sizeof(ctl)); MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(ConnCacheKey); ctl.keysize = sizeof(ConnCacheKey);
ctl.entrysize = sizeof(ConnCacheEntry); ctl.entrysize = sizeof(ConnCacheEntry);
ctl.hash = tag_hash;
/* allocate ConnectionHash in the cache context */ /* allocate ConnectionHash in the cache context */
ctl.hcxt = CacheMemoryContext; ctl.hcxt = CacheMemoryContext;
ConnectionHash = hash_create("postgres_fdw connections", 8, ConnectionHash = hash_create("postgres_fdw connections", 8,
&ctl, &ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
/* /*
* Register some callback functions that manage connection cleanup. * Register some callback functions that manage connection cleanup.
......
...@@ -1142,12 +1142,10 @@ gistInitParentMap(GISTBuildState *buildstate) ...@@ -1142,12 +1142,10 @@ gistInitParentMap(GISTBuildState *buildstate)
hashCtl.keysize = sizeof(BlockNumber); hashCtl.keysize = sizeof(BlockNumber);
hashCtl.entrysize = sizeof(ParentMapEntry); hashCtl.entrysize = sizeof(ParentMapEntry);
hashCtl.hcxt = CurrentMemoryContext; hashCtl.hcxt = CurrentMemoryContext;
hashCtl.hash = oid_hash;
buildstate->parentMap = hash_create("gistbuild parent map", buildstate->parentMap = hash_create("gistbuild parent map",
1024, 1024,
&hashCtl, &hashCtl,
HASH_ELEM | HASH_CONTEXT HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
| HASH_FUNCTION);
} }
static void static void
......
...@@ -76,16 +76,14 @@ gistInitBuildBuffers(int pagesPerBuffer, int levelStep, int maxLevel) ...@@ -76,16 +76,14 @@ gistInitBuildBuffers(int pagesPerBuffer, int levelStep, int maxLevel)
* nodeBuffersTab hash is association between index blocks and it's * nodeBuffersTab hash is association between index blocks and it's
* buffers. * buffers.
*/ */
memset(&hashCtl, 0, sizeof(hashCtl));
hashCtl.keysize = sizeof(BlockNumber); hashCtl.keysize = sizeof(BlockNumber);
hashCtl.entrysize = sizeof(GISTNodeBuffer); hashCtl.entrysize = sizeof(GISTNodeBuffer);
hashCtl.hcxt = CurrentMemoryContext; hashCtl.hcxt = CurrentMemoryContext;
hashCtl.hash = tag_hash;
hashCtl.match = memcmp;
gfbb->nodeBuffersTab = hash_create("gistbuildbuffers", gfbb->nodeBuffersTab = hash_create("gistbuildbuffers",
1024, 1024,
&hashCtl, &hashCtl,
HASH_ELEM | HASH_CONTEXT HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
| HASH_FUNCTION | HASH_COMPARE);
gfbb->bufferEmptyingQueue = NIL; gfbb->bufferEmptyingQueue = NIL;
......
...@@ -283,13 +283,12 @@ begin_heap_rewrite(Relation old_heap, Relation new_heap, TransactionId oldest_xm ...@@ -283,13 +283,12 @@ begin_heap_rewrite(Relation old_heap, Relation new_heap, TransactionId oldest_xm
hash_ctl.keysize = sizeof(TidHashKey); hash_ctl.keysize = sizeof(TidHashKey);
hash_ctl.entrysize = sizeof(UnresolvedTupData); hash_ctl.entrysize = sizeof(UnresolvedTupData);
hash_ctl.hcxt = state->rs_cxt; hash_ctl.hcxt = state->rs_cxt;
hash_ctl.hash = tag_hash;
state->rs_unresolved_tups = state->rs_unresolved_tups =
hash_create("Rewrite / Unresolved ctids", hash_create("Rewrite / Unresolved ctids",
128, /* arbitrary initial size */ 128, /* arbitrary initial size */
&hash_ctl, &hash_ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
hash_ctl.entrysize = sizeof(OldToNewMappingData); hash_ctl.entrysize = sizeof(OldToNewMappingData);
...@@ -297,7 +296,7 @@ begin_heap_rewrite(Relation old_heap, Relation new_heap, TransactionId oldest_xm ...@@ -297,7 +296,7 @@ begin_heap_rewrite(Relation old_heap, Relation new_heap, TransactionId oldest_xm
hash_create("Rewrite / Old to new tid map", hash_create("Rewrite / Old to new tid map",
128, /* arbitrary initial size */ 128, /* arbitrary initial size */
&hash_ctl, &hash_ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
MemoryContextSwitchTo(old_cxt); MemoryContextSwitchTo(old_cxt);
...@@ -834,13 +833,12 @@ logical_begin_heap_rewrite(RewriteState state) ...@@ -834,13 +833,12 @@ logical_begin_heap_rewrite(RewriteState state)
hash_ctl.keysize = sizeof(TransactionId); hash_ctl.keysize = sizeof(TransactionId);
hash_ctl.entrysize = sizeof(RewriteMappingFile); hash_ctl.entrysize = sizeof(RewriteMappingFile);
hash_ctl.hcxt = state->rs_cxt; hash_ctl.hcxt = state->rs_cxt;
hash_ctl.hash = tag_hash;
state->rs_logical_mappings = state->rs_logical_mappings =
hash_create("Logical rewrite mapping", hash_create("Logical rewrite mapping",
128, /* arbitrary initial size */ 128, /* arbitrary initial size */
&hash_ctl, &hash_ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
} }
/* /*
......
...@@ -107,12 +107,11 @@ log_invalid_page(RelFileNode node, ForkNumber forkno, BlockNumber blkno, ...@@ -107,12 +107,11 @@ log_invalid_page(RelFileNode node, ForkNumber forkno, BlockNumber blkno,
memset(&ctl, 0, sizeof(ctl)); memset(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(xl_invalid_page_key); ctl.keysize = sizeof(xl_invalid_page_key);
ctl.entrysize = sizeof(xl_invalid_page); ctl.entrysize = sizeof(xl_invalid_page);
ctl.hash = tag_hash;
invalid_page_tab = hash_create("XLOG invalid-page table", invalid_page_tab = hash_create("XLOG invalid-page table",
100, 100,
&ctl, &ctl,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_BLOBS);
} }
/* we currently assume xl_invalid_page_key contains no padding */ /* we currently assume xl_invalid_page_key contains no padding */
......
...@@ -986,10 +986,9 @@ create_seq_hashtable(void) ...@@ -986,10 +986,9 @@ create_seq_hashtable(void)
memset(&ctl, 0, sizeof(ctl)); memset(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(Oid); ctl.keysize = sizeof(Oid);
ctl.entrysize = sizeof(SeqTableData); ctl.entrysize = sizeof(SeqTableData);
ctl.hash = oid_hash;
seqhashtab = hash_create("Sequence values", 16, &ctl, seqhashtab = hash_create("Sequence values", 16, &ctl,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_BLOBS);
} }
/* /*
......
...@@ -221,12 +221,11 @@ tbm_create_pagetable(TIDBitmap *tbm) ...@@ -221,12 +221,11 @@ tbm_create_pagetable(TIDBitmap *tbm)
MemSet(&hash_ctl, 0, sizeof(hash_ctl)); MemSet(&hash_ctl, 0, sizeof(hash_ctl));
hash_ctl.keysize = sizeof(BlockNumber); hash_ctl.keysize = sizeof(BlockNumber);
hash_ctl.entrysize = sizeof(PagetableEntry); hash_ctl.entrysize = sizeof(PagetableEntry);
hash_ctl.hash = tag_hash;
hash_ctl.hcxt = tbm->mcxt; hash_ctl.hcxt = tbm->mcxt;
tbm->pagetable = hash_create("TIDBitmap", tbm->pagetable = hash_create("TIDBitmap",
128, /* start small and extend */ 128, /* start small and extend */
&hash_ctl, &hash_ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
/* If entry1 is valid, push it into the hashtable */ /* If entry1 is valid, push it into the hashtable */
if (tbm->status == TBM_ONE_PAGE) if (tbm->status == TBM_ONE_PAGE)
......
...@@ -1711,9 +1711,8 @@ lookup_proof_cache(Oid pred_op, Oid clause_op, bool refute_it) ...@@ -1711,9 +1711,8 @@ lookup_proof_cache(Oid pred_op, Oid clause_op, bool refute_it)
MemSet(&ctl, 0, sizeof(ctl)); MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(OprProofCacheKey); ctl.keysize = sizeof(OprProofCacheKey);
ctl.entrysize = sizeof(OprProofCacheEntry); ctl.entrysize = sizeof(OprProofCacheEntry);
ctl.hash = tag_hash;
OprProofCacheHash = hash_create("Btree proof lookup cache", 256, OprProofCacheHash = hash_create("Btree proof lookup cache", 256,
&ctl, HASH_ELEM | HASH_FUNCTION); &ctl, HASH_ELEM | HASH_BLOBS);
/* Arrange to flush cache on pg_amop changes */ /* Arrange to flush cache on pg_amop changes */
CacheRegisterSyscacheCallback(AMOPOPID, CacheRegisterSyscacheCallback(AMOPOPID,
......
...@@ -1059,9 +1059,8 @@ find_oper_cache_entry(OprCacheKey *key) ...@@ -1059,9 +1059,8 @@ find_oper_cache_entry(OprCacheKey *key)
MemSet(&ctl, 0, sizeof(ctl)); MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(OprCacheKey); ctl.keysize = sizeof(OprCacheKey);
ctl.entrysize = sizeof(OprCacheEntry); ctl.entrysize = sizeof(OprCacheEntry);
ctl.hash = tag_hash;
OprCacheHash = hash_create("Operator lookup cache", 256, OprCacheHash = hash_create("Operator lookup cache", 256,
&ctl, HASH_ELEM | HASH_FUNCTION); &ctl, HASH_ELEM | HASH_BLOBS);
/* Arrange to flush cache on pg_operator and pg_cast changes */ /* Arrange to flush cache on pg_operator and pg_cast changes */
CacheRegisterSyscacheCallback(OPERNAMENSP, CacheRegisterSyscacheCallback(OPERNAMENSP,
......
...@@ -922,10 +922,9 @@ rebuild_database_list(Oid newdb) ...@@ -922,10 +922,9 @@ rebuild_database_list(Oid newdb)
*/ */
hctl.keysize = sizeof(Oid); hctl.keysize = sizeof(Oid);
hctl.entrysize = sizeof(avl_dbase); hctl.entrysize = sizeof(avl_dbase);
hctl.hash = oid_hash;
hctl.hcxt = tmpcxt; hctl.hcxt = tmpcxt;
dbhash = hash_create("db hash", 20, &hctl, /* magic number here FIXME */ dbhash = hash_create("db hash", 20, &hctl, /* magic number here FIXME */
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
/* start by inserting the new database */ /* start by inserting the new database */
score = 0; score = 0;
...@@ -1997,12 +1996,11 @@ do_autovacuum(void) ...@@ -1997,12 +1996,11 @@ do_autovacuum(void)
MemSet(&ctl, 0, sizeof(ctl)); MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(Oid); ctl.keysize = sizeof(Oid);
ctl.entrysize = sizeof(av_relation); ctl.entrysize = sizeof(av_relation);
ctl.hash = oid_hash;
table_toast_map = hash_create("TOAST to main relid map", table_toast_map = hash_create("TOAST to main relid map",
100, 100,
&ctl, &ctl,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_BLOBS);
/* /*
* Scan pg_class to determine which tables to vacuum. * Scan pg_class to determine which tables to vacuum.
......
...@@ -1212,13 +1212,12 @@ CompactCheckpointerRequestQueue(void) ...@@ -1212,13 +1212,12 @@ CompactCheckpointerRequestQueue(void)
MemSet(&ctl, 0, sizeof(ctl)); MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(CheckpointerRequest); ctl.keysize = sizeof(CheckpointerRequest);
ctl.entrysize = sizeof(struct CheckpointerSlotMapping); ctl.entrysize = sizeof(struct CheckpointerSlotMapping);
ctl.hash = tag_hash;
ctl.hcxt = CurrentMemoryContext; ctl.hcxt = CurrentMemoryContext;
htab = hash_create("CompactCheckpointerRequestQueue", htab = hash_create("CompactCheckpointerRequestQueue",
CheckpointerShmem->num_requests, CheckpointerShmem->num_requests,
&ctl, &ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
/* /*
* The basic idea here is that a request can be skipped if it's followed * The basic idea here is that a request can be skipped if it's followed
......
...@@ -1132,12 +1132,11 @@ pgstat_collect_oids(Oid catalogid) ...@@ -1132,12 +1132,11 @@ pgstat_collect_oids(Oid catalogid)
memset(&hash_ctl, 0, sizeof(hash_ctl)); memset(&hash_ctl, 0, sizeof(hash_ctl));
hash_ctl.keysize = sizeof(Oid); hash_ctl.keysize = sizeof(Oid);
hash_ctl.entrysize = sizeof(Oid); hash_ctl.entrysize = sizeof(Oid);
hash_ctl.hash = oid_hash;
hash_ctl.hcxt = CurrentMemoryContext; hash_ctl.hcxt = CurrentMemoryContext;
htab = hash_create("Temporary table of OIDs", htab = hash_create("Temporary table of OIDs",
PGSTAT_TAB_HASH_SIZE, PGSTAT_TAB_HASH_SIZE,
&hash_ctl, &hash_ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
rel = heap_open(catalogid, AccessShareLock); rel = heap_open(catalogid, AccessShareLock);
snapshot = RegisterSnapshot(GetLatestSnapshot()); snapshot = RegisterSnapshot(GetLatestSnapshot());
...@@ -1520,11 +1519,10 @@ pgstat_init_function_usage(FunctionCallInfoData *fcinfo, ...@@ -1520,11 +1519,10 @@ pgstat_init_function_usage(FunctionCallInfoData *fcinfo,
memset(&hash_ctl, 0, sizeof(hash_ctl)); memset(&hash_ctl, 0, sizeof(hash_ctl));
hash_ctl.keysize = sizeof(Oid); hash_ctl.keysize = sizeof(Oid);
hash_ctl.entrysize = sizeof(PgStat_BackendFunctionEntry); hash_ctl.entrysize = sizeof(PgStat_BackendFunctionEntry);
hash_ctl.hash = oid_hash;
pgStatFunctions = hash_create("Function stat entries", pgStatFunctions = hash_create("Function stat entries",
PGSTAT_FUNCTION_HASH_SIZE, PGSTAT_FUNCTION_HASH_SIZE,
&hash_ctl, &hash_ctl,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_BLOBS);
} }
/* Get the stats entry for this function, create if necessary */ /* Get the stats entry for this function, create if necessary */
...@@ -3483,19 +3481,17 @@ reset_dbentry_counters(PgStat_StatDBEntry *dbentry) ...@@ -3483,19 +3481,17 @@ reset_dbentry_counters(PgStat_StatDBEntry *dbentry)
memset(&hash_ctl, 0, sizeof(hash_ctl)); memset(&hash_ctl, 0, sizeof(hash_ctl));
hash_ctl.keysize = sizeof(Oid); hash_ctl.keysize = sizeof(Oid);
hash_ctl.entrysize = sizeof(PgStat_StatTabEntry); hash_ctl.entrysize = sizeof(PgStat_StatTabEntry);
hash_ctl.hash = oid_hash;
dbentry->tables = hash_create("Per-database table", dbentry->tables = hash_create("Per-database table",
PGSTAT_TAB_HASH_SIZE, PGSTAT_TAB_HASH_SIZE,
&hash_ctl, &hash_ctl,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_BLOBS);
hash_ctl.keysize = sizeof(Oid); hash_ctl.keysize = sizeof(Oid);
hash_ctl.entrysize = sizeof(PgStat_StatFuncEntry); hash_ctl.entrysize = sizeof(PgStat_StatFuncEntry);
hash_ctl.hash = oid_hash;
dbentry->functions = hash_create("Per-database function", dbentry->functions = hash_create("Per-database function",
PGSTAT_FUNCTION_HASH_SIZE, PGSTAT_FUNCTION_HASH_SIZE,
&hash_ctl, &hash_ctl,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_BLOBS);
} }
/* /*
...@@ -3902,10 +3898,9 @@ pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep) ...@@ -3902,10 +3898,9 @@ pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep)
memset(&hash_ctl, 0, sizeof(hash_ctl)); memset(&hash_ctl, 0, sizeof(hash_ctl));
hash_ctl.keysize = sizeof(Oid); hash_ctl.keysize = sizeof(Oid);
hash_ctl.entrysize = sizeof(PgStat_StatDBEntry); hash_ctl.entrysize = sizeof(PgStat_StatDBEntry);
hash_ctl.hash = oid_hash;
hash_ctl.hcxt = pgStatLocalContext; hash_ctl.hcxt = pgStatLocalContext;
dbhash = hash_create("Databases hash", PGSTAT_DB_HASH_SIZE, &hash_ctl, dbhash = hash_create("Databases hash", PGSTAT_DB_HASH_SIZE, &hash_ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
/* /*
* Clear out global and archiver statistics so they start from zero in * Clear out global and archiver statistics so they start from zero in
...@@ -4026,21 +4021,19 @@ pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep) ...@@ -4026,21 +4021,19 @@ pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep)
memset(&hash_ctl, 0, sizeof(hash_ctl)); memset(&hash_ctl, 0, sizeof(hash_ctl));
hash_ctl.keysize = sizeof(Oid); hash_ctl.keysize = sizeof(Oid);
hash_ctl.entrysize = sizeof(PgStat_StatTabEntry); hash_ctl.entrysize = sizeof(PgStat_StatTabEntry);
hash_ctl.hash = oid_hash;
hash_ctl.hcxt = pgStatLocalContext; hash_ctl.hcxt = pgStatLocalContext;
dbentry->tables = hash_create("Per-database table", dbentry->tables = hash_create("Per-database table",
PGSTAT_TAB_HASH_SIZE, PGSTAT_TAB_HASH_SIZE,
&hash_ctl, &hash_ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
hash_ctl.keysize = sizeof(Oid); hash_ctl.keysize = sizeof(Oid);
hash_ctl.entrysize = sizeof(PgStat_StatFuncEntry); hash_ctl.entrysize = sizeof(PgStat_StatFuncEntry);
hash_ctl.hash = oid_hash;
hash_ctl.hcxt = pgStatLocalContext; hash_ctl.hcxt = pgStatLocalContext;
dbentry->functions = hash_create("Per-database function", dbentry->functions = hash_create("Per-database function",
PGSTAT_FUNCTION_HASH_SIZE, PGSTAT_FUNCTION_HASH_SIZE,
&hash_ctl, &hash_ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
/* /*
* If requested, read the data from the database-specific * If requested, read the data from the database-specific
......
...@@ -245,11 +245,10 @@ ReorderBufferAllocate(void) ...@@ -245,11 +245,10 @@ ReorderBufferAllocate(void)
hash_ctl.keysize = sizeof(TransactionId); hash_ctl.keysize = sizeof(TransactionId);
hash_ctl.entrysize = sizeof(ReorderBufferTXNByIdEnt); hash_ctl.entrysize = sizeof(ReorderBufferTXNByIdEnt);
hash_ctl.hash = tag_hash;
hash_ctl.hcxt = buffer->context; hash_ctl.hcxt = buffer->context;
buffer->by_txn = hash_create("ReorderBufferByXid", 1000, &hash_ctl, buffer->by_txn = hash_create("ReorderBufferByXid", 1000, &hash_ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
buffer->by_txn_last_xid = InvalidTransactionId; buffer->by_txn_last_xid = InvalidTransactionId;
buffer->by_txn_last_txn = NULL; buffer->by_txn_last_txn = NULL;
...@@ -1111,7 +1110,6 @@ ReorderBufferBuildTupleCidHash(ReorderBuffer *rb, ReorderBufferTXN *txn) ...@@ -1111,7 +1110,6 @@ ReorderBufferBuildTupleCidHash(ReorderBuffer *rb, ReorderBufferTXN *txn)
hash_ctl.keysize = sizeof(ReorderBufferTupleCidKey); hash_ctl.keysize = sizeof(ReorderBufferTupleCidKey);
hash_ctl.entrysize = sizeof(ReorderBufferTupleCidEnt); hash_ctl.entrysize = sizeof(ReorderBufferTupleCidEnt);
hash_ctl.hash = tag_hash;
hash_ctl.hcxt = rb->context; hash_ctl.hcxt = rb->context;
/* /*
...@@ -1120,7 +1118,7 @@ ReorderBufferBuildTupleCidHash(ReorderBuffer *rb, ReorderBufferTXN *txn) ...@@ -1120,7 +1118,7 @@ ReorderBufferBuildTupleCidHash(ReorderBuffer *rb, ReorderBufferTXN *txn)
*/ */
txn->tuplecid_hash = txn->tuplecid_hash =
hash_create("ReorderBufferTupleCid", txn->ntuplecids, &hash_ctl, hash_create("ReorderBufferTupleCid", txn->ntuplecids, &hash_ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
dlist_foreach(iter, &txn->tuplecids) dlist_foreach(iter, &txn->tuplecids)
{ {
...@@ -2434,10 +2432,9 @@ ReorderBufferToastInitHash(ReorderBuffer *rb, ReorderBufferTXN *txn) ...@@ -2434,10 +2432,9 @@ ReorderBufferToastInitHash(ReorderBuffer *rb, ReorderBufferTXN *txn)
memset(&hash_ctl, 0, sizeof(hash_ctl)); memset(&hash_ctl, 0, sizeof(hash_ctl));
hash_ctl.keysize = sizeof(Oid); hash_ctl.keysize = sizeof(Oid);
hash_ctl.entrysize = sizeof(ReorderBufferToastEnt); hash_ctl.entrysize = sizeof(ReorderBufferToastEnt);
hash_ctl.hash = tag_hash;
hash_ctl.hcxt = rb->context; hash_ctl.hcxt = rb->context;
txn->toast_hash = hash_create("ReorderBufferToastHash", 5, &hash_ctl, txn->toast_hash = hash_create("ReorderBufferToastHash", 5, &hash_ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
} }
/* /*
......
...@@ -59,13 +59,12 @@ InitBufTable(int size) ...@@ -59,13 +59,12 @@ InitBufTable(int size)
/* BufferTag maps to Buffer */ /* BufferTag maps to Buffer */
info.keysize = sizeof(BufferTag); info.keysize = sizeof(BufferTag);
info.entrysize = sizeof(BufferLookupEnt); info.entrysize = sizeof(BufferLookupEnt);
info.hash = tag_hash;
info.num_partitions = NUM_BUFFER_PARTITIONS; info.num_partitions = NUM_BUFFER_PARTITIONS;
SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table", SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table",
size, size, size, size,
&info, &info,
HASH_ELEM | HASH_FUNCTION | HASH_PARTITION); HASH_ELEM | HASH_BLOBS | HASH_PARTITION);
} }
/* /*
......
...@@ -2063,10 +2063,9 @@ InitBufferPoolAccess(void) ...@@ -2063,10 +2063,9 @@ InitBufferPoolAccess(void)
MemSet(&hash_ctl, 0, sizeof(hash_ctl)); MemSet(&hash_ctl, 0, sizeof(hash_ctl));
hash_ctl.keysize = sizeof(int32); hash_ctl.keysize = sizeof(int32);
hash_ctl.entrysize = sizeof(PrivateRefCountArray); hash_ctl.entrysize = sizeof(PrivateRefCountArray);
hash_ctl.hash = oid_hash; /* a bit more efficient than tag_hash */
PrivateRefCountHash = hash_create("PrivateRefCount", 100, &hash_ctl, PrivateRefCountHash = hash_create("PrivateRefCount", 100, &hash_ctl,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_BLOBS);
} }
/* /*
......
...@@ -415,12 +415,11 @@ InitLocalBuffers(void) ...@@ -415,12 +415,11 @@ InitLocalBuffers(void)
MemSet(&info, 0, sizeof(info)); MemSet(&info, 0, sizeof(info));
info.keysize = sizeof(BufferTag); info.keysize = sizeof(BufferTag);
info.entrysize = sizeof(LocalBufferLookupEnt); info.entrysize = sizeof(LocalBufferLookupEnt);
info.hash = tag_hash;
LocalBufHash = hash_create("Local Buffer Lookup Table", LocalBufHash = hash_create("Local Buffer Lookup Table",
nbufs, nbufs,
&info, &info,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_BLOBS);
if (!LocalBufHash) if (!LocalBufHash)
elog(ERROR, "could not initialize local buffer hash table"); elog(ERROR, "could not initialize local buffer hash table");
......
...@@ -373,7 +373,6 @@ void ...@@ -373,7 +373,6 @@ void
InitLocks(void) InitLocks(void)
{ {
HASHCTL info; HASHCTL info;
int hash_flags;
long init_table_size, long init_table_size,
max_table_size; max_table_size;
bool found; bool found;
...@@ -392,15 +391,13 @@ InitLocks(void) ...@@ -392,15 +391,13 @@ InitLocks(void)
MemSet(&info, 0, sizeof(info)); MemSet(&info, 0, sizeof(info));
info.keysize = sizeof(LOCKTAG); info.keysize = sizeof(LOCKTAG);
info.entrysize = sizeof(LOCK); info.entrysize = sizeof(LOCK);
info.hash = tag_hash;
info.num_partitions = NUM_LOCK_PARTITIONS; info.num_partitions = NUM_LOCK_PARTITIONS;
hash_flags = (HASH_ELEM | HASH_FUNCTION | HASH_PARTITION);
LockMethodLockHash = ShmemInitHash("LOCK hash", LockMethodLockHash = ShmemInitHash("LOCK hash",
init_table_size, init_table_size,
max_table_size, max_table_size,
&info, &info,
hash_flags); HASH_ELEM | HASH_BLOBS | HASH_PARTITION);
/* Assume an average of 2 holders per lock */ /* Assume an average of 2 holders per lock */
max_table_size *= 2; max_table_size *= 2;
...@@ -414,13 +411,12 @@ InitLocks(void) ...@@ -414,13 +411,12 @@ InitLocks(void)
info.entrysize = sizeof(PROCLOCK); info.entrysize = sizeof(PROCLOCK);
info.hash = proclock_hash; info.hash = proclock_hash;
info.num_partitions = NUM_LOCK_PARTITIONS; info.num_partitions = NUM_LOCK_PARTITIONS;
hash_flags = (HASH_ELEM | HASH_FUNCTION | HASH_PARTITION);
LockMethodProcLockHash = ShmemInitHash("PROCLOCK hash", LockMethodProcLockHash = ShmemInitHash("PROCLOCK hash",
init_table_size, init_table_size,
max_table_size, max_table_size,
&info, &info,
hash_flags); HASH_ELEM | HASH_FUNCTION | HASH_PARTITION);
/* /*
* Allocate fast-path structures. * Allocate fast-path structures.
...@@ -445,13 +441,11 @@ InitLocks(void) ...@@ -445,13 +441,11 @@ InitLocks(void)
info.keysize = sizeof(LOCALLOCKTAG); info.keysize = sizeof(LOCALLOCKTAG);
info.entrysize = sizeof(LOCALLOCK); info.entrysize = sizeof(LOCALLOCK);
info.hash = tag_hash;
hash_flags = (HASH_ELEM | HASH_FUNCTION);
LockMethodLocalHash = hash_create("LOCALLOCK hash", LockMethodLocalHash = hash_create("LOCALLOCK hash",
16, 16,
&info, &info,
hash_flags); HASH_ELEM | HASH_BLOBS);
} }
......
...@@ -167,10 +167,9 @@ init_lwlock_stats(void) ...@@ -167,10 +167,9 @@ init_lwlock_stats(void)
MemSet(&ctl, 0, sizeof(ctl)); MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(lwlock_stats_key); ctl.keysize = sizeof(lwlock_stats_key);
ctl.entrysize = sizeof(lwlock_stats); ctl.entrysize = sizeof(lwlock_stats);
ctl.hash = tag_hash;
ctl.hcxt = lwlock_stats_cxt; ctl.hcxt = lwlock_stats_cxt;
lwlock_stats_htab = hash_create("lwlock stats", 16384, &ctl, lwlock_stats_htab = hash_create("lwlock stats", 16384, &ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
if (!exit_registered) if (!exit_registered)
{ {
on_shmem_exit(print_lwlock_stats, 0); on_shmem_exit(print_lwlock_stats, 0);
......
...@@ -286,7 +286,7 @@ ...@@ -286,7 +286,7 @@
* the lock partition number from the hashcode. * the lock partition number from the hashcode.
*/ */
#define PredicateLockTargetTagHashCode(predicatelocktargettag) \ #define PredicateLockTargetTagHashCode(predicatelocktargettag) \
(tag_hash((predicatelocktargettag), sizeof(PREDICATELOCKTARGETTAG))) get_hash_value(PredicateLockTargetHash, predicatelocktargettag)
/* /*
* Given a predicate lock tag, and the hash for its target, * Given a predicate lock tag, and the hash for its target,
...@@ -1095,7 +1095,6 @@ void ...@@ -1095,7 +1095,6 @@ void
InitPredicateLocks(void) InitPredicateLocks(void)
{ {
HASHCTL info; HASHCTL info;
int hash_flags;
long max_table_size; long max_table_size;
Size requestSize; Size requestSize;
bool found; bool found;
...@@ -1113,15 +1112,14 @@ InitPredicateLocks(void) ...@@ -1113,15 +1112,14 @@ InitPredicateLocks(void)
MemSet(&info, 0, sizeof(info)); MemSet(&info, 0, sizeof(info));
info.keysize = sizeof(PREDICATELOCKTARGETTAG); info.keysize = sizeof(PREDICATELOCKTARGETTAG);
info.entrysize = sizeof(PREDICATELOCKTARGET); info.entrysize = sizeof(PREDICATELOCKTARGET);
info.hash = tag_hash;
info.num_partitions = NUM_PREDICATELOCK_PARTITIONS; info.num_partitions = NUM_PREDICATELOCK_PARTITIONS;
hash_flags = (HASH_ELEM | HASH_FUNCTION | HASH_PARTITION | HASH_FIXED_SIZE);
PredicateLockTargetHash = ShmemInitHash("PREDICATELOCKTARGET hash", PredicateLockTargetHash = ShmemInitHash("PREDICATELOCKTARGET hash",
max_table_size, max_table_size,
max_table_size, max_table_size,
&info, &info,
hash_flags); HASH_ELEM | HASH_BLOBS |
HASH_PARTITION | HASH_FIXED_SIZE);
/* Assume an average of 2 xacts per target */ /* Assume an average of 2 xacts per target */
max_table_size *= 2; max_table_size *= 2;
...@@ -1143,13 +1141,13 @@ InitPredicateLocks(void) ...@@ -1143,13 +1141,13 @@ InitPredicateLocks(void)
info.entrysize = sizeof(PREDICATELOCK); info.entrysize = sizeof(PREDICATELOCK);
info.hash = predicatelock_hash; info.hash = predicatelock_hash;
info.num_partitions = NUM_PREDICATELOCK_PARTITIONS; info.num_partitions = NUM_PREDICATELOCK_PARTITIONS;
hash_flags = (HASH_ELEM | HASH_FUNCTION | HASH_PARTITION | HASH_FIXED_SIZE);
PredicateLockHash = ShmemInitHash("PREDICATELOCK hash", PredicateLockHash = ShmemInitHash("PREDICATELOCK hash",
max_table_size, max_table_size,
max_table_size, max_table_size,
&info, &info,
hash_flags); HASH_ELEM | HASH_FUNCTION |
HASH_PARTITION | HASH_FIXED_SIZE);
/* /*
* Compute size for serializable transaction hashtable. Note these * Compute size for serializable transaction hashtable. Note these
...@@ -1224,14 +1222,13 @@ InitPredicateLocks(void) ...@@ -1224,14 +1222,13 @@ InitPredicateLocks(void)
MemSet(&info, 0, sizeof(info)); MemSet(&info, 0, sizeof(info));
info.keysize = sizeof(SERIALIZABLEXIDTAG); info.keysize = sizeof(SERIALIZABLEXIDTAG);
info.entrysize = sizeof(SERIALIZABLEXID); info.entrysize = sizeof(SERIALIZABLEXID);
info.hash = tag_hash;
hash_flags = (HASH_ELEM | HASH_FUNCTION | HASH_FIXED_SIZE);
SerializableXidHash = ShmemInitHash("SERIALIZABLEXID hash", SerializableXidHash = ShmemInitHash("SERIALIZABLEXID hash",
max_table_size, max_table_size,
max_table_size, max_table_size,
&info, &info,
hash_flags); HASH_ELEM | HASH_BLOBS |
HASH_FIXED_SIZE);
/* /*
* Allocate space for tracking rw-conflicts in lists attached to the * Allocate space for tracking rw-conflicts in lists attached to the
...@@ -1793,11 +1790,10 @@ GetSerializableTransactionSnapshotInt(Snapshot snapshot, ...@@ -1793,11 +1790,10 @@ GetSerializableTransactionSnapshotInt(Snapshot snapshot,
MemSet(&hash_ctl, 0, sizeof(hash_ctl)); MemSet(&hash_ctl, 0, sizeof(hash_ctl));
hash_ctl.keysize = sizeof(PREDICATELOCKTARGETTAG); hash_ctl.keysize = sizeof(PREDICATELOCKTARGETTAG);
hash_ctl.entrysize = sizeof(LOCALPREDICATELOCK); hash_ctl.entrysize = sizeof(LOCALPREDICATELOCK);
hash_ctl.hash = tag_hash;
LocalPredicateLockHash = hash_create("Local predicate lock", LocalPredicateLockHash = hash_create("Local predicate lock",
max_predicate_locks_per_xact, max_predicate_locks_per_xact,
&hash_ctl, &hash_ctl,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_BLOBS);
return snapshot; return snapshot;
} }
......
...@@ -229,12 +229,11 @@ mdinit(void) ...@@ -229,12 +229,11 @@ mdinit(void)
MemSet(&hash_ctl, 0, sizeof(hash_ctl)); MemSet(&hash_ctl, 0, sizeof(hash_ctl));
hash_ctl.keysize = sizeof(RelFileNode); hash_ctl.keysize = sizeof(RelFileNode);
hash_ctl.entrysize = sizeof(PendingOperationEntry); hash_ctl.entrysize = sizeof(PendingOperationEntry);
hash_ctl.hash = tag_hash;
hash_ctl.hcxt = pendingOpsCxt; hash_ctl.hcxt = pendingOpsCxt;
pendingOpsTable = hash_create("Pending Ops Table", pendingOpsTable = hash_create("Pending Ops Table",
100L, 100L,
&hash_ctl, &hash_ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
pendingUnlinks = NIL; pendingUnlinks = NIL;
} }
} }
......
...@@ -146,9 +146,8 @@ smgropen(RelFileNode rnode, BackendId backend) ...@@ -146,9 +146,8 @@ smgropen(RelFileNode rnode, BackendId backend)
MemSet(&ctl, 0, sizeof(ctl)); MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(RelFileNodeBackend); ctl.keysize = sizeof(RelFileNodeBackend);
ctl.entrysize = sizeof(SMgrRelationData); ctl.entrysize = sizeof(SMgrRelationData);
ctl.hash = tag_hash;
SMgrRelationHash = hash_create("smgr relation table", 400, SMgrRelationHash = hash_create("smgr relation table", 400,
&ctl, HASH_ELEM | HASH_FUNCTION); &ctl, HASH_ELEM | HASH_BLOBS);
first_unowned_reln = NULL; first_unowned_reln = NULL;
} }
......
...@@ -290,12 +290,11 @@ compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc, ...@@ -290,12 +290,11 @@ compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
MemSet(&count_hash_ctl, 0, sizeof(count_hash_ctl)); MemSet(&count_hash_ctl, 0, sizeof(count_hash_ctl));
count_hash_ctl.keysize = sizeof(int); count_hash_ctl.keysize = sizeof(int);
count_hash_ctl.entrysize = sizeof(DECountItem); count_hash_ctl.entrysize = sizeof(DECountItem);
count_hash_ctl.hash = tag_hash;
count_hash_ctl.hcxt = CurrentMemoryContext; count_hash_ctl.hcxt = CurrentMemoryContext;
count_tab = hash_create("Array distinct element count table", count_tab = hash_create("Array distinct element count table",
64, 64,
&count_hash_ctl, &count_hash_ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
/* Initialize counters. */ /* Initialize counters. */
b_current = 1; b_current = 1;
......
...@@ -875,9 +875,8 @@ lookup_collation_cache(Oid collation, bool set_flags) ...@@ -875,9 +875,8 @@ lookup_collation_cache(Oid collation, bool set_flags)
memset(&ctl, 0, sizeof(ctl)); memset(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(Oid); ctl.keysize = sizeof(Oid);
ctl.entrysize = sizeof(collation_cache_entry); ctl.entrysize = sizeof(collation_cache_entry);
ctl.hash = oid_hash;
collation_cache = hash_create("Collation cache", 100, &ctl, collation_cache = hash_create("Collation cache", 100, &ctl,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_BLOBS);
} }
cache_entry = hash_search(collation_cache, &collation, HASH_ENTER, &found); cache_entry = hash_search(collation_cache, &collation, HASH_ENTER, &found);
......
...@@ -3326,10 +3326,9 @@ ri_InitHashTables(void) ...@@ -3326,10 +3326,9 @@ ri_InitHashTables(void)
memset(&ctl, 0, sizeof(ctl)); memset(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(Oid); ctl.keysize = sizeof(Oid);
ctl.entrysize = sizeof(RI_ConstraintInfo); ctl.entrysize = sizeof(RI_ConstraintInfo);
ctl.hash = oid_hash;
ri_constraint_cache = hash_create("RI constraint cache", ri_constraint_cache = hash_create("RI constraint cache",
RI_INIT_CONSTRAINTHASHSIZE, RI_INIT_CONSTRAINTHASHSIZE,
&ctl, HASH_ELEM | HASH_FUNCTION); &ctl, HASH_ELEM | HASH_BLOBS);
/* Arrange to flush cache on pg_constraint changes */ /* Arrange to flush cache on pg_constraint changes */
CacheRegisterSyscacheCallback(CONSTROID, CacheRegisterSyscacheCallback(CONSTROID,
...@@ -3339,18 +3338,16 @@ ri_InitHashTables(void) ...@@ -3339,18 +3338,16 @@ ri_InitHashTables(void)
memset(&ctl, 0, sizeof(ctl)); memset(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(RI_QueryKey); ctl.keysize = sizeof(RI_QueryKey);
ctl.entrysize = sizeof(RI_QueryHashEntry); ctl.entrysize = sizeof(RI_QueryHashEntry);
ctl.hash = tag_hash;
ri_query_cache = hash_create("RI query cache", ri_query_cache = hash_create("RI query cache",
RI_INIT_QUERYHASHSIZE, RI_INIT_QUERYHASHSIZE,
&ctl, HASH_ELEM | HASH_FUNCTION); &ctl, HASH_ELEM | HASH_BLOBS);
memset(&ctl, 0, sizeof(ctl)); memset(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(RI_CompareKey); ctl.keysize = sizeof(RI_CompareKey);
ctl.entrysize = sizeof(RI_CompareHashEntry); ctl.entrysize = sizeof(RI_CompareHashEntry);
ctl.hash = tag_hash;
ri_compare_cache = hash_create("RI compare cache", ri_compare_cache = hash_create("RI compare cache",
RI_INIT_QUERYHASHSIZE, RI_INIT_QUERYHASHSIZE,
&ctl, HASH_ELEM | HASH_FUNCTION); &ctl, HASH_ELEM | HASH_BLOBS);
} }
......
...@@ -82,10 +82,9 @@ InitializeAttoptCache(void) ...@@ -82,10 +82,9 @@ InitializeAttoptCache(void)
MemSet(&ctl, 0, sizeof(ctl)); MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(AttoptCacheKey); ctl.keysize = sizeof(AttoptCacheKey);
ctl.entrysize = sizeof(AttoptCacheEntry); ctl.entrysize = sizeof(AttoptCacheEntry);
ctl.hash = tag_hash;
AttoptCacheHash = AttoptCacheHash =
hash_create("Attopt cache", 256, &ctl, hash_create("Attopt cache", 256, &ctl,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_BLOBS);
/* Make sure we've initialized CacheMemoryContext. */ /* Make sure we've initialized CacheMemoryContext. */
if (!CacheMemoryContext) if (!CacheMemoryContext)
......
...@@ -123,10 +123,9 @@ BuildEventTriggerCache(void) ...@@ -123,10 +123,9 @@ BuildEventTriggerCache(void)
MemSet(&ctl, 0, sizeof(ctl)); MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(EventTriggerEvent); ctl.keysize = sizeof(EventTriggerEvent);
ctl.entrysize = sizeof(EventTriggerCacheEntry); ctl.entrysize = sizeof(EventTriggerCacheEntry);
ctl.hash = tag_hash;
ctl.hcxt = EventTriggerCacheContext; ctl.hcxt = EventTriggerCacheContext;
cache = hash_create("Event Trigger Cache", 32, &ctl, cache = hash_create("Event Trigger Cache", 32, &ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
/* /*
* Prepare to scan pg_event_trigger in name order. * Prepare to scan pg_event_trigger in name order.
......
...@@ -1409,9 +1409,8 @@ LookupOpclassInfo(Oid operatorClassOid, ...@@ -1409,9 +1409,8 @@ LookupOpclassInfo(Oid operatorClassOid,
MemSet(&ctl, 0, sizeof(ctl)); MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(Oid); ctl.keysize = sizeof(Oid);
ctl.entrysize = sizeof(OpClassCacheEnt); ctl.entrysize = sizeof(OpClassCacheEnt);
ctl.hash = oid_hash;
OpClassCache = hash_create("Operator class cache", 64, OpClassCache = hash_create("Operator class cache", 64,
&ctl, HASH_ELEM | HASH_FUNCTION); &ctl, HASH_ELEM | HASH_BLOBS);
/* Also make sure CacheMemoryContext exists */ /* Also make sure CacheMemoryContext exists */
if (!CacheMemoryContext) if (!CacheMemoryContext)
...@@ -3140,9 +3139,8 @@ RelationCacheInitialize(void) ...@@ -3140,9 +3139,8 @@ RelationCacheInitialize(void)
MemSet(&ctl, 0, sizeof(ctl)); MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(Oid); ctl.keysize = sizeof(Oid);
ctl.entrysize = sizeof(RelIdCacheEnt); ctl.entrysize = sizeof(RelIdCacheEnt);
ctl.hash = oid_hash;
RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE, RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
&ctl, HASH_ELEM | HASH_FUNCTION); &ctl, HASH_ELEM | HASH_BLOBS);
/* /*
* relation mapper needs to be initialized too * relation mapper needs to be initialized too
......
...@@ -115,7 +115,6 @@ InitializeRelfilenodeMap(void) ...@@ -115,7 +115,6 @@ InitializeRelfilenodeMap(void)
MemSet(&ctl, 0, sizeof(ctl)); MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(RelfilenodeMapKey); ctl.keysize = sizeof(RelfilenodeMapKey);
ctl.entrysize = sizeof(RelfilenodeMapEntry); ctl.entrysize = sizeof(RelfilenodeMapEntry);
ctl.hash = tag_hash;
ctl.hcxt = CacheMemoryContext; ctl.hcxt = CacheMemoryContext;
/* /*
...@@ -125,7 +124,7 @@ InitializeRelfilenodeMap(void) ...@@ -125,7 +124,7 @@ InitializeRelfilenodeMap(void)
*/ */
RelfilenodeMapHash = RelfilenodeMapHash =
hash_create("RelfilenodeMap cache", 1024, &ctl, hash_create("RelfilenodeMap cache", 1024, &ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
/* Watch for invalidation events. */ /* Watch for invalidation events. */
CacheRegisterRelcacheCallback(RelfilenodeMapInvalidateCallback, CacheRegisterRelcacheCallback(RelfilenodeMapInvalidateCallback,
......
...@@ -81,10 +81,9 @@ InitializeTableSpaceCache(void) ...@@ -81,10 +81,9 @@ InitializeTableSpaceCache(void)
MemSet(&ctl, 0, sizeof(ctl)); MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(Oid); ctl.keysize = sizeof(Oid);
ctl.entrysize = sizeof(TableSpaceCacheEntry); ctl.entrysize = sizeof(TableSpaceCacheEntry);
ctl.hash = oid_hash;
TableSpaceCacheHash = TableSpaceCacheHash =
hash_create("TableSpace cache", 16, &ctl, hash_create("TableSpace cache", 16, &ctl,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_BLOBS);
/* Make sure we've initialized CacheMemoryContext. */ /* Make sure we've initialized CacheMemoryContext. */
if (!CacheMemoryContext) if (!CacheMemoryContext)
......
...@@ -120,9 +120,8 @@ lookup_ts_parser_cache(Oid prsId) ...@@ -120,9 +120,8 @@ lookup_ts_parser_cache(Oid prsId)
MemSet(&ctl, 0, sizeof(ctl)); MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(Oid); ctl.keysize = sizeof(Oid);
ctl.entrysize = sizeof(TSParserCacheEntry); ctl.entrysize = sizeof(TSParserCacheEntry);
ctl.hash = oid_hash;
TSParserCacheHash = hash_create("Tsearch parser cache", 4, TSParserCacheHash = hash_create("Tsearch parser cache", 4,
&ctl, HASH_ELEM | HASH_FUNCTION); &ctl, HASH_ELEM | HASH_BLOBS);
/* Flush cache on pg_ts_parser changes */ /* Flush cache on pg_ts_parser changes */
CacheRegisterSyscacheCallback(TSPARSEROID, InvalidateTSCacheCallBack, CacheRegisterSyscacheCallback(TSPARSEROID, InvalidateTSCacheCallBack,
PointerGetDatum(TSParserCacheHash)); PointerGetDatum(TSParserCacheHash));
...@@ -219,9 +218,8 @@ lookup_ts_dictionary_cache(Oid dictId) ...@@ -219,9 +218,8 @@ lookup_ts_dictionary_cache(Oid dictId)
MemSet(&ctl, 0, sizeof(ctl)); MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(Oid); ctl.keysize = sizeof(Oid);
ctl.entrysize = sizeof(TSDictionaryCacheEntry); ctl.entrysize = sizeof(TSDictionaryCacheEntry);
ctl.hash = oid_hash;
TSDictionaryCacheHash = hash_create("Tsearch dictionary cache", 8, TSDictionaryCacheHash = hash_create("Tsearch dictionary cache", 8,
&ctl, HASH_ELEM | HASH_FUNCTION); &ctl, HASH_ELEM | HASH_BLOBS);
/* Flush cache on pg_ts_dict and pg_ts_template changes */ /* Flush cache on pg_ts_dict and pg_ts_template changes */
CacheRegisterSyscacheCallback(TSDICTOID, InvalidateTSCacheCallBack, CacheRegisterSyscacheCallback(TSDICTOID, InvalidateTSCacheCallBack,
PointerGetDatum(TSDictionaryCacheHash)); PointerGetDatum(TSDictionaryCacheHash));
...@@ -368,9 +366,8 @@ init_ts_config_cache(void) ...@@ -368,9 +366,8 @@ init_ts_config_cache(void)
MemSet(&ctl, 0, sizeof(ctl)); MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(Oid); ctl.keysize = sizeof(Oid);
ctl.entrysize = sizeof(TSConfigCacheEntry); ctl.entrysize = sizeof(TSConfigCacheEntry);
ctl.hash = oid_hash;
TSConfigCacheHash = hash_create("Tsearch configuration cache", 16, TSConfigCacheHash = hash_create("Tsearch configuration cache", 16,
&ctl, HASH_ELEM | HASH_FUNCTION); &ctl, HASH_ELEM | HASH_BLOBS);
/* Flush cache on pg_ts_config and pg_ts_config_map changes */ /* Flush cache on pg_ts_config and pg_ts_config_map changes */
CacheRegisterSyscacheCallback(TSCONFIGOID, InvalidateTSCacheCallBack, CacheRegisterSyscacheCallback(TSCONFIGOID, InvalidateTSCacheCallBack,
PointerGetDatum(TSConfigCacheHash)); PointerGetDatum(TSConfigCacheHash));
......
...@@ -166,9 +166,8 @@ lookup_type_cache(Oid type_id, int flags) ...@@ -166,9 +166,8 @@ lookup_type_cache(Oid type_id, int flags)
MemSet(&ctl, 0, sizeof(ctl)); MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(Oid); ctl.keysize = sizeof(Oid);
ctl.entrysize = sizeof(TypeCacheEntry); ctl.entrysize = sizeof(TypeCacheEntry);
ctl.hash = oid_hash;
TypeCacheHash = hash_create("Type information cache", 64, TypeCacheHash = hash_create("Type information cache", 64,
&ctl, HASH_ELEM | HASH_FUNCTION); &ctl, HASH_ELEM | HASH_BLOBS);
/* Also set up callbacks for SI invalidations */ /* Also set up callbacks for SI invalidations */
CacheRegisterRelcacheCallback(TypeCacheRelCallback, (Datum) 0); CacheRegisterRelcacheCallback(TypeCacheRelCallback, (Datum) 0);
...@@ -846,9 +845,8 @@ assign_record_type_typmod(TupleDesc tupDesc) ...@@ -846,9 +845,8 @@ assign_record_type_typmod(TupleDesc tupDesc)
MemSet(&ctl, 0, sizeof(ctl)); MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = REC_HASH_KEYS * sizeof(Oid); ctl.keysize = REC_HASH_KEYS * sizeof(Oid);
ctl.entrysize = sizeof(RecordCacheEntry); ctl.entrysize = sizeof(RecordCacheEntry);
ctl.hash = tag_hash;
RecordCacheHash = hash_create("Record information cache", 64, RecordCacheHash = hash_create("Record information cache", 64,
&ctl, HASH_ELEM | HASH_FUNCTION); &ctl, HASH_ELEM | HASH_BLOBS);
/* Also make sure CacheMemoryContext exists */ /* Also make sure CacheMemoryContext exists */
if (!CacheMemoryContext) if (!CacheMemoryContext)
......
...@@ -540,11 +540,10 @@ record_C_func(HeapTuple procedureTuple, ...@@ -540,11 +540,10 @@ record_C_func(HeapTuple procedureTuple,
MemSet(&hash_ctl, 0, sizeof(hash_ctl)); MemSet(&hash_ctl, 0, sizeof(hash_ctl));
hash_ctl.keysize = sizeof(Oid); hash_ctl.keysize = sizeof(Oid);
hash_ctl.entrysize = sizeof(CFuncHashTabEntry); hash_ctl.entrysize = sizeof(CFuncHashTabEntry);
hash_ctl.hash = oid_hash;
CFuncHash = hash_create("CFuncHash", CFuncHash = hash_create("CFuncHash",
100, 100,
&hash_ctl, &hash_ctl,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_BLOBS);
} }
entry = (CFuncHashTabEntry *) entry = (CFuncHashTabEntry *)
......
...@@ -26,6 +26,20 @@ ...@@ -26,6 +26,20 @@
* in local memory, we typically use palloc() which will throw error on * in local memory, we typically use palloc() which will throw error on
* failure. The code in this file has to cope with both cases. * failure. The code in this file has to cope with both cases.
* *
* dynahash.c provides support for these types of lookup keys:
*
* 1. Null-terminated C strings (truncated if necessary to fit in keysize),
* compared as though by strcmp(). This is the default behavior.
*
* 2. Arbitrary binary data of size keysize, compared as though by memcmp().
* (Caller must ensure there are no undefined padding bits in the keys!)
* This is selected by specifying HASH_BLOBS flag to hash_create.
*
* 3. More complex key behavior can be selected by specifying user-supplied
* hashing, comparison, and/or key-copying functions. At least a hashing
* function must be supplied; comparison defaults to memcmp() and key copying
* to memcpy() when a user-defined hashing function is selected.
*
* Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
...@@ -305,15 +319,32 @@ hash_create(const char *tabname, long nelem, HASHCTL *info, int flags) ...@@ -305,15 +319,32 @@ hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
hashp->tabname = (char *) (hashp + 1); hashp->tabname = (char *) (hashp + 1);
strcpy(hashp->tabname, tabname); strcpy(hashp->tabname, tabname);
/*
* Select the appropriate hash function (see comments at head of file).
*/
if (flags & HASH_FUNCTION) if (flags & HASH_FUNCTION)
hashp->hash = info->hash; hashp->hash = info->hash;
else if (flags & HASH_BLOBS)
{
/* We can optimize hashing for common key sizes */
Assert(flags & HASH_ELEM);
if (info->keysize == sizeof(uint32))
hashp->hash = uint32_hash;
else
hashp->hash = tag_hash;
}
else else
hashp->hash = string_hash; /* default hash function */ hashp->hash = string_hash; /* default hash function */
/* /*
* If you don't specify a match function, it defaults to string_compare if * If you don't specify a match function, it defaults to string_compare if
* you used string_hash (either explicitly or by default) and to memcmp * you used string_hash (either explicitly or by default) and to memcmp
* otherwise. (Prior to PostgreSQL 7.4, memcmp was always used.) * otherwise.
*
* Note: explicitly specifying string_hash is deprecated, because this
* might not work for callers in loadable modules on some platforms due to
* referencing a trampoline instead of the string_hash function proper.
* Just let it default, eh?
*/ */
if (flags & HASH_COMPARE) if (flags & HASH_COMPARE)
hashp->match = info->match; hashp->match = info->match;
...@@ -332,6 +363,7 @@ hash_create(const char *tabname, long nelem, HASHCTL *info, int flags) ...@@ -332,6 +363,7 @@ hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
else else
hashp->keycopy = memcpy; hashp->keycopy = memcpy;
/* And select the entry allocation function, too. */
if (flags & HASH_ALLOC) if (flags & HASH_ALLOC)
hashp->alloc = info->alloc; hashp->alloc = info->alloc;
else else
......
...@@ -55,15 +55,15 @@ tag_hash(const void *key, Size keysize) ...@@ -55,15 +55,15 @@ tag_hash(const void *key, Size keysize)
} }
/* /*
* oid_hash: hash function for keys that are OIDs * uint32_hash: hash function for keys that are uint32 or int32
* *
* (tag_hash works for this case too, but is slower) * (tag_hash works for this case too, but is slower)
*/ */
uint32 uint32
oid_hash(const void *key, Size keysize) uint32_hash(const void *key, Size keysize)
{ {
Assert(keysize == sizeof(Oid)); Assert(keysize == sizeof(uint32));
return DatumGetUInt32(hash_uint32((uint32) *((const Oid *) key))); return DatumGetUInt32(hash_uint32(*((const uint32 *) key)));
} }
/* /*
......
...@@ -218,13 +218,12 @@ GetComboCommandId(CommandId cmin, CommandId cmax) ...@@ -218,13 +218,12 @@ GetComboCommandId(CommandId cmin, CommandId cmax)
memset(&hash_ctl, 0, sizeof(hash_ctl)); memset(&hash_ctl, 0, sizeof(hash_ctl));
hash_ctl.keysize = sizeof(ComboCidKeyData); hash_ctl.keysize = sizeof(ComboCidKeyData);
hash_ctl.entrysize = sizeof(ComboCidEntryData); hash_ctl.entrysize = sizeof(ComboCidEntryData);
hash_ctl.hash = tag_hash;
hash_ctl.hcxt = TopTransactionContext; hash_ctl.hcxt = TopTransactionContext;
comboHash = hash_create("Combo CIDs", comboHash = hash_create("Combo CIDs",
CCID_HASH_SIZE, CCID_HASH_SIZE,
&hash_ctl, &hash_ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
comboCids = (ComboCidKeyData *) comboCids = (ComboCidKeyData *)
MemoryContextAlloc(TopTransactionContext, MemoryContextAlloc(TopTransactionContext,
......
...@@ -31,7 +31,7 @@ typedef int (*HashCompareFunc) (const void *key1, const void *key2, ...@@ -31,7 +31,7 @@ typedef int (*HashCompareFunc) (const void *key1, const void *key2,
/* /*
* Key copying functions must have this signature. The return value is not * Key copying functions must have this signature. The return value is not
* used. (The definition is set up to allow memcpy() and strncpy() to be * used. (The definition is set up to allow memcpy() and strlcpy() to be
* used directly.) * used directly.)
*/ */
typedef void *(*HashCopyFunc) (void *dest, const void *src, Size keysize); typedef void *(*HashCopyFunc) (void *dest, const void *src, Size keysize);
...@@ -80,19 +80,20 @@ typedef struct HASHCTL ...@@ -80,19 +80,20 @@ typedef struct HASHCTL
} HASHCTL; } HASHCTL;
/* Flags to indicate which parameters are supplied */ /* Flags to indicate which parameters are supplied */
#define HASH_PARTITION 0x001 /* Hashtable is used w/partitioned locking */ #define HASH_PARTITION 0x0001 /* Hashtable is used w/partitioned locking */
#define HASH_SEGMENT 0x002 /* Set segment size */ #define HASH_SEGMENT 0x0002 /* Set segment size */
#define HASH_DIRSIZE 0x004 /* Set directory size (initial and max) */ #define HASH_DIRSIZE 0x0004 /* Set directory size (initial and max) */
#define HASH_FFACTOR 0x008 /* Set fill factor */ #define HASH_FFACTOR 0x0008 /* Set fill factor */
#define HASH_FUNCTION 0x010 /* Set user defined hash function */ #define HASH_ELEM 0x0010 /* Set keysize and entrysize */
#define HASH_ELEM 0x020 /* Set keysize and entrysize */ #define HASH_BLOBS 0x0020 /* Select support functions for binary keys */
#define HASH_SHARED_MEM 0x040 /* Hashtable is in shared memory */ #define HASH_FUNCTION 0x0040 /* Set user defined hash function */
#define HASH_ATTACH 0x080 /* Do not initialize hctl */ #define HASH_COMPARE 0x0080 /* Set user defined comparison function */
#define HASH_ALLOC 0x100 /* Set memory allocator */ #define HASH_KEYCOPY 0x0100 /* Set user defined key-copying function */
#define HASH_CONTEXT 0x200 /* Set memory allocation context */ #define HASH_ALLOC 0x0200 /* Set memory allocator */
#define HASH_COMPARE 0x400 /* Set user defined comparison function */ #define HASH_CONTEXT 0x0400 /* Set memory allocation context */
#define HASH_KEYCOPY 0x800 /* Set user defined key-copying function */ #define HASH_SHARED_MEM 0x0800 /* Hashtable is in shared memory */
#define HASH_FIXED_SIZE 0x1000 /* Initial size is a hard limit */ #define HASH_ATTACH 0x1000 /* Do not initialize hctl */
#define HASH_FIXED_SIZE 0x2000 /* Initial size is a hard limit */
/* max_dsize value to indicate expansible directory */ /* max_dsize value to indicate expansible directory */
...@@ -143,11 +144,17 @@ extern void AtEOSubXact_HashTables(bool isCommit, int nestDepth); ...@@ -143,11 +144,17 @@ extern void AtEOSubXact_HashTables(bool isCommit, int nestDepth);
/* /*
* prototypes for functions in hashfn.c * prototypes for functions in hashfn.c
*
* Note: It is deprecated for callers of hash_create to explicitly specify
* string_hash, tag_hash, uint32_hash, or oid_hash. Just set HASH_BLOBS or
* not. Use HASH_FUNCTION only when you want something other than those.
*/ */
extern uint32 string_hash(const void *key, Size keysize); extern uint32 string_hash(const void *key, Size keysize);
extern uint32 tag_hash(const void *key, Size keysize); extern uint32 tag_hash(const void *key, Size keysize);
extern uint32 oid_hash(const void *key, Size keysize); extern uint32 uint32_hash(const void *key, Size keysize);
extern uint32 bitmap_hash(const void *key, Size keysize); extern uint32 bitmap_hash(const void *key, Size keysize);
extern int bitmap_match(const void *key1, const void *key2, Size keysize); extern int bitmap_match(const void *key1, const void *key2, Size keysize);
#define oid_hash uint32_hash /* Remove me eventually */
#endif /* HSEARCH_H */ #endif /* HSEARCH_H */
...@@ -456,20 +456,18 @@ _PG_init(void) ...@@ -456,20 +456,18 @@ _PG_init(void)
memset(&hash_ctl, 0, sizeof(hash_ctl)); memset(&hash_ctl, 0, sizeof(hash_ctl));
hash_ctl.keysize = sizeof(Oid); hash_ctl.keysize = sizeof(Oid);
hash_ctl.entrysize = sizeof(plperl_interp_desc); hash_ctl.entrysize = sizeof(plperl_interp_desc);
hash_ctl.hash = oid_hash;
plperl_interp_hash = hash_create("PL/Perl interpreters", plperl_interp_hash = hash_create("PL/Perl interpreters",
8, 8,
&hash_ctl, &hash_ctl,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_BLOBS);
memset(&hash_ctl, 0, sizeof(hash_ctl)); memset(&hash_ctl, 0, sizeof(hash_ctl));
hash_ctl.keysize = sizeof(plperl_proc_key); hash_ctl.keysize = sizeof(plperl_proc_key);
hash_ctl.entrysize = sizeof(plperl_proc_ptr); hash_ctl.entrysize = sizeof(plperl_proc_ptr);
hash_ctl.hash = tag_hash;
plperl_proc_hash = hash_create("PL/Perl procedures", plperl_proc_hash = hash_create("PL/Perl procedures",
32, 32,
&hash_ctl, &hash_ctl,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_BLOBS);
/* /*
* Save the default opmask. * Save the default opmask.
......
...@@ -2519,11 +2519,10 @@ plpgsql_HashTableInit(void) ...@@ -2519,11 +2519,10 @@ plpgsql_HashTableInit(void)
memset(&ctl, 0, sizeof(ctl)); memset(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(PLpgSQL_func_hashkey); ctl.keysize = sizeof(PLpgSQL_func_hashkey);
ctl.entrysize = sizeof(plpgsql_HashEnt); ctl.entrysize = sizeof(plpgsql_HashEnt);
ctl.hash = tag_hash;
plpgsql_HashTable = hash_create("PLpgSQL function cache", plpgsql_HashTable = hash_create("PLpgSQL function cache",
FUNCS_PER_USER, FUNCS_PER_USER,
&ctl, &ctl,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_BLOBS);
} }
static PLpgSQL_function * static PLpgSQL_function *
......
...@@ -226,9 +226,8 @@ PLy_add_exceptions(PyObject *plpy) ...@@ -226,9 +226,8 @@ PLy_add_exceptions(PyObject *plpy)
memset(&hash_ctl, 0, sizeof(hash_ctl)); memset(&hash_ctl, 0, sizeof(hash_ctl));
hash_ctl.keysize = sizeof(int); hash_ctl.keysize = sizeof(int);
hash_ctl.entrysize = sizeof(PLyExceptionEntry); hash_ctl.entrysize = sizeof(PLyExceptionEntry);
hash_ctl.hash = tag_hash;
PLy_spi_exceptions = hash_create("SPI exceptions", 256, PLy_spi_exceptions = hash_create("SPI exceptions", 256,
&hash_ctl, HASH_ELEM | HASH_FUNCTION); &hash_ctl, HASH_ELEM | HASH_BLOBS);
PLy_generate_spi_exceptions(excmod, PLy_exc_spi_error); PLy_generate_spi_exceptions(excmod, PLy_exc_spi_error);
} }
......
...@@ -39,9 +39,8 @@ init_procedure_caches(void) ...@@ -39,9 +39,8 @@ init_procedure_caches(void)
memset(&hash_ctl, 0, sizeof(hash_ctl)); memset(&hash_ctl, 0, sizeof(hash_ctl));
hash_ctl.keysize = sizeof(PLyProcedureKey); hash_ctl.keysize = sizeof(PLyProcedureKey);
hash_ctl.entrysize = sizeof(PLyProcedureEntry); hash_ctl.entrysize = sizeof(PLyProcedureEntry);
hash_ctl.hash = tag_hash;
PLy_procedure_cache = hash_create("PL/Python procedures", 32, &hash_ctl, PLy_procedure_cache = hash_create("PL/Python procedures", 32, &hash_ctl,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_BLOBS);
} }
/* /*
......
...@@ -378,11 +378,10 @@ _PG_init(void) ...@@ -378,11 +378,10 @@ _PG_init(void)
memset(&hash_ctl, 0, sizeof(hash_ctl)); memset(&hash_ctl, 0, sizeof(hash_ctl));
hash_ctl.keysize = sizeof(Oid); hash_ctl.keysize = sizeof(Oid);
hash_ctl.entrysize = sizeof(pltcl_interp_desc); hash_ctl.entrysize = sizeof(pltcl_interp_desc);
hash_ctl.hash = oid_hash;
pltcl_interp_htab = hash_create("PL/Tcl interpreters", pltcl_interp_htab = hash_create("PL/Tcl interpreters",
8, 8,
&hash_ctl, &hash_ctl,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_BLOBS);
/************************************************************ /************************************************************
* Create the hash table for function lookup * Create the hash table for function lookup
...@@ -390,11 +389,10 @@ _PG_init(void) ...@@ -390,11 +389,10 @@ _PG_init(void)
memset(&hash_ctl, 0, sizeof(hash_ctl)); memset(&hash_ctl, 0, sizeof(hash_ctl));
hash_ctl.keysize = sizeof(pltcl_proc_key); hash_ctl.keysize = sizeof(pltcl_proc_key);
hash_ctl.entrysize = sizeof(pltcl_proc_ptr); hash_ctl.entrysize = sizeof(pltcl_proc_ptr);
hash_ctl.hash = tag_hash;
pltcl_proc_htab = hash_create("PL/Tcl functions", pltcl_proc_htab = hash_create("PL/Tcl functions",
100, 100,
&hash_ctl, &hash_ctl,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_BLOBS);
pltcl_pm_init_done = true; pltcl_pm_init_done = true;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment