]> granicus.if.org Git - postgresql/commitdiff
Improve hash_create's API for selecting simple-binary-key hash functions.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 18 Dec 2014 18:36:29 +0000 (13:36 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 18 Dec 2014 18:36:36 +0000 (13:36 -0500)
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

42 files changed:
contrib/pg_trgm/trgm_regexp.c
contrib/postgres_fdw/connection.c
src/backend/access/gist/gistbuild.c
src/backend/access/gist/gistbuildbuffers.c
src/backend/access/heap/rewriteheap.c
src/backend/access/transam/xlogutils.c
src/backend/commands/sequence.c
src/backend/nodes/tidbitmap.c
src/backend/optimizer/util/predtest.c
src/backend/parser/parse_oper.c
src/backend/postmaster/autovacuum.c
src/backend/postmaster/checkpointer.c
src/backend/postmaster/pgstat.c
src/backend/replication/logical/reorderbuffer.c
src/backend/storage/buffer/buf_table.c
src/backend/storage/buffer/bufmgr.c
src/backend/storage/buffer/localbuf.c
src/backend/storage/lmgr/lock.c
src/backend/storage/lmgr/lwlock.c
src/backend/storage/lmgr/predicate.c
src/backend/storage/smgr/md.c
src/backend/storage/smgr/smgr.c
src/backend/utils/adt/array_typanalyze.c
src/backend/utils/adt/pg_locale.c
src/backend/utils/adt/ri_triggers.c
src/backend/utils/cache/attoptcache.c
src/backend/utils/cache/evtcache.c
src/backend/utils/cache/relcache.c
src/backend/utils/cache/relfilenodemap.c
src/backend/utils/cache/spccache.c
src/backend/utils/cache/ts_cache.c
src/backend/utils/cache/typcache.c
src/backend/utils/fmgr/fmgr.c
src/backend/utils/hash/dynahash.c
src/backend/utils/hash/hashfn.c
src/backend/utils/time/combocid.c
src/include/utils/hsearch.h
src/pl/plperl/plperl.c
src/pl/plpgsql/src/pl_comp.c
src/pl/plpython/plpy_plpymodule.c
src/pl/plpython/plpy_procedure.c
src/pl/tcl/pltcl.c

index 9f050533c59853d487590dca194cea425ce583e2..f7a73cb72c214f29d225670667bba907b4bf1c3d 100644 (file)
@@ -915,11 +915,10 @@ transformGraph(TrgmNFA *trgmNFA)
        hashCtl.keysize = sizeof(TrgmStateKey);
        hashCtl.entrysize = sizeof(TrgmState);
        hashCtl.hcxt = CurrentMemoryContext;
-       hashCtl.hash = tag_hash;
        trgmNFA->states = hash_create("Trigram NFA",
                                                                  1024,
                                                                  &hashCtl,
-                                                                 HASH_ELEM | HASH_CONTEXT | HASH_FUNCTION);
+                                                                 HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
 
        /* Create initial state: ambiguous prefix, NFA's initial state */
        MemSet(&initkey, 0, sizeof(initkey));
index 116be7ddcb77ce2509e8c4d538fc988d8f80b991..61216e5cc03ad8be517ffe0066be85ebe2a5ee0a 100644 (file)
@@ -109,12 +109,11 @@ GetConnection(ForeignServer *server, UserMapping *user,
                MemSet(&ctl, 0, sizeof(ctl));
                ctl.keysize = sizeof(ConnCacheKey);
                ctl.entrysize = sizeof(ConnCacheEntry);
-               ctl.hash = tag_hash;
                /* allocate ConnectionHash in the cache context */
                ctl.hcxt = CacheMemoryContext;
                ConnectionHash = hash_create("postgres_fdw connections", 8,
                                                                         &ctl,
-                                                                  HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+                                                                        HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
 
                /*
                 * Register some callback functions that manage connection cleanup.
index 5acc986585a8e2d6aeac800f867fdf8899f4c5a9..09a9df4974b008019a70171e9a7d43d11c998aa9 100644 (file)
@@ -1142,12 +1142,10 @@ gistInitParentMap(GISTBuildState *buildstate)
        hashCtl.keysize = sizeof(BlockNumber);
        hashCtl.entrysize = sizeof(ParentMapEntry);
        hashCtl.hcxt = CurrentMemoryContext;
-       hashCtl.hash = oid_hash;
        buildstate->parentMap = hash_create("gistbuild parent map",
                                                                                1024,
                                                                                &hashCtl,
-                                                                               HASH_ELEM | HASH_CONTEXT
-                                                                               | HASH_FUNCTION);
+                                                                         HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
 }
 
 static void
index 577ea613b11f8a13eda9425b6dd6df7d491f8548..4937c38b4ef0df81199299934881d8cfbf9b141e 100644 (file)
@@ -76,16 +76,14 @@ gistInitBuildBuffers(int pagesPerBuffer, int levelStep, int maxLevel)
         * nodeBuffersTab hash is association between index blocks and it's
         * buffers.
         */
+       memset(&hashCtl, 0, sizeof(hashCtl));
        hashCtl.keysize = sizeof(BlockNumber);
        hashCtl.entrysize = sizeof(GISTNodeBuffer);
        hashCtl.hcxt = CurrentMemoryContext;
-       hashCtl.hash = tag_hash;
-       hashCtl.match = memcmp;
        gfbb->nodeBuffersTab = hash_create("gistbuildbuffers",
                                                                           1024,
                                                                           &hashCtl,
-                                                                          HASH_ELEM | HASH_CONTEXT
-                                                                          | HASH_FUNCTION | HASH_COMPARE);
+                                                                          HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
 
        gfbb->bufferEmptyingQueue = NIL;
 
index 4b132b7d016891bc4faf74eb9203366bbbe1812a..97388657863b4ddfc403d9d88d9375fb82a92217 100644 (file)
@@ -283,13 +283,12 @@ begin_heap_rewrite(Relation old_heap, Relation new_heap, TransactionId oldest_xm
        hash_ctl.keysize = sizeof(TidHashKey);
        hash_ctl.entrysize = sizeof(UnresolvedTupData);
        hash_ctl.hcxt = state->rs_cxt;
-       hash_ctl.hash = tag_hash;
 
        state->rs_unresolved_tups =
                hash_create("Rewrite / Unresolved ctids",
                                        128,            /* arbitrary initial size */
                                        &hash_ctl,
-                                       HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+                                       HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
 
        hash_ctl.entrysize = sizeof(OldToNewMappingData);
 
@@ -297,7 +296,7 @@ begin_heap_rewrite(Relation old_heap, Relation new_heap, TransactionId oldest_xm
                hash_create("Rewrite / Old to new tid map",
                                        128,            /* arbitrary initial size */
                                        &hash_ctl,
-                                       HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+                                       HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
 
        MemoryContextSwitchTo(old_cxt);
 
@@ -834,13 +833,12 @@ logical_begin_heap_rewrite(RewriteState state)
        hash_ctl.keysize = sizeof(TransactionId);
        hash_ctl.entrysize = sizeof(RewriteMappingFile);
        hash_ctl.hcxt = state->rs_cxt;
-       hash_ctl.hash = tag_hash;
 
        state->rs_logical_mappings =
                hash_create("Logical rewrite mapping",
                                        128,            /* arbitrary initial size */
                                        &hash_ctl,
-                                       HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+                                       HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
 }
 
 /*
index ae323a0db87f6db005928147730346fafdfd2dc7..89b2ba5b08cea44e873a47af81f6f3054865b80b 100644 (file)
@@ -107,12 +107,11 @@ log_invalid_page(RelFileNode node, ForkNumber forkno, BlockNumber blkno,
                memset(&ctl, 0, sizeof(ctl));
                ctl.keysize = sizeof(xl_invalid_page_key);
                ctl.entrysize = sizeof(xl_invalid_page);
-               ctl.hash = tag_hash;
 
                invalid_page_tab = hash_create("XLOG invalid-page table",
                                                                           100,
                                                                           &ctl,
-                                                                          HASH_ELEM | HASH_FUNCTION);
+                                                                          HASH_ELEM | HASH_BLOBS);
        }
 
        /* we currently assume xl_invalid_page_key contains no padding */
index ba5b938863cb492632f9c45acb3c29b8d363165a..811e1d488040eebf767c44dfd368c9df00cb6c55 100644 (file)
@@ -986,10 +986,9 @@ create_seq_hashtable(void)
        memset(&ctl, 0, sizeof(ctl));
        ctl.keysize = sizeof(Oid);
        ctl.entrysize = sizeof(SeqTableData);
-       ctl.hash = oid_hash;
 
        seqhashtab = hash_create("Sequence values", 16, &ctl,
-                                                        HASH_ELEM | HASH_FUNCTION);
+                                                        HASH_ELEM | HASH_BLOBS);
 }
 
 /*
index a880c81cf1c8fc3cb14b4b5d9b007b171c91b19c..3b074381f4ddf9a16dad9fa1ae6138773551ca20 100644 (file)
@@ -221,12 +221,11 @@ tbm_create_pagetable(TIDBitmap *tbm)
        MemSet(&hash_ctl, 0, sizeof(hash_ctl));
        hash_ctl.keysize = sizeof(BlockNumber);
        hash_ctl.entrysize = sizeof(PagetableEntry);
-       hash_ctl.hash = tag_hash;
        hash_ctl.hcxt = tbm->mcxt;
        tbm->pagetable = hash_create("TIDBitmap",
                                                                 128,   /* start small and extend */
                                                                 &hash_ctl,
-                                                                HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+                                                                HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
 
        /* If entry1 is valid, push it into the hashtable */
        if (tbm->status == TBM_ONE_PAGE)
index 9f9a208d3e621baa750d773cd991d25bcbcb84f7..6daa0588a6cbf3700ee16a054a5ac35be815a718 100644 (file)
@@ -1711,9 +1711,8 @@ lookup_proof_cache(Oid pred_op, Oid clause_op, bool refute_it)
                MemSet(&ctl, 0, sizeof(ctl));
                ctl.keysize = sizeof(OprProofCacheKey);
                ctl.entrysize = sizeof(OprProofCacheEntry);
-               ctl.hash = tag_hash;
                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 */
                CacheRegisterSyscacheCallback(AMOPOPID,
index b65b632f17e41a1f76a7d58b735c3a2a2efae3ce..11a6397a4d51eb1851999cbfbcd690a65154ab1d 100644 (file)
@@ -1059,9 +1059,8 @@ find_oper_cache_entry(OprCacheKey *key)
                MemSet(&ctl, 0, sizeof(ctl));
                ctl.keysize = sizeof(OprCacheKey);
                ctl.entrysize = sizeof(OprCacheEntry);
-               ctl.hash = tag_hash;
                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 */
                CacheRegisterSyscacheCallback(OPERNAMENSP,
index 1d6e3f35f94a67fec37b38c7991c2b40a4132dfa..675f985eadacc09004ee735ae822e060487821e3 100644 (file)
@@ -922,10 +922,9 @@ rebuild_database_list(Oid newdb)
         */
        hctl.keysize = sizeof(Oid);
        hctl.entrysize = sizeof(avl_dbase);
-       hctl.hash = oid_hash;
        hctl.hcxt = tmpcxt;
        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 */
        score = 0;
@@ -1997,12 +1996,11 @@ do_autovacuum(void)
        MemSet(&ctl, 0, sizeof(ctl));
        ctl.keysize = sizeof(Oid);
        ctl.entrysize = sizeof(av_relation);
-       ctl.hash = oid_hash;
 
        table_toast_map = hash_create("TOAST to main relid map",
                                                                  100,
                                                                  &ctl,
-                                                                 HASH_ELEM | HASH_FUNCTION);
+                                                                 HASH_ELEM | HASH_BLOBS);
 
        /*
         * Scan pg_class to determine which tables to vacuum.
index 6c814ba0be8fc732de2ba3093d4e6b64843437de..8a79d9b23ad95083bc38b86dd7aa907bcabcfb68 100644 (file)
@@ -1212,13 +1212,12 @@ CompactCheckpointerRequestQueue(void)
        MemSet(&ctl, 0, sizeof(ctl));
        ctl.keysize = sizeof(CheckpointerRequest);
        ctl.entrysize = sizeof(struct CheckpointerSlotMapping);
-       ctl.hash = tag_hash;
        ctl.hcxt = CurrentMemoryContext;
 
        htab = hash_create("CompactCheckpointerRequestQueue",
                                           CheckpointerShmem->num_requests,
                                           &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
index 6672b8bae51688df7e740a6e8df6267fc9f8f13d..17bfc0bd159c7c2b4064d139a066b1174501ab2c 100644 (file)
@@ -1132,12 +1132,11 @@ pgstat_collect_oids(Oid catalogid)
        memset(&hash_ctl, 0, sizeof(hash_ctl));
        hash_ctl.keysize = sizeof(Oid);
        hash_ctl.entrysize = sizeof(Oid);
-       hash_ctl.hash = oid_hash;
        hash_ctl.hcxt = CurrentMemoryContext;
        htab = hash_create("Temporary table of OIDs",
                                           PGSTAT_TAB_HASH_SIZE,
                                           &hash_ctl,
-                                          HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+                                          HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
 
        rel = heap_open(catalogid, AccessShareLock);
        snapshot = RegisterSnapshot(GetLatestSnapshot());
@@ -1520,11 +1519,10 @@ pgstat_init_function_usage(FunctionCallInfoData *fcinfo,
                memset(&hash_ctl, 0, sizeof(hash_ctl));
                hash_ctl.keysize = sizeof(Oid);
                hash_ctl.entrysize = sizeof(PgStat_BackendFunctionEntry);
-               hash_ctl.hash = oid_hash;
                pgStatFunctions = hash_create("Function stat entries",
                                                                          PGSTAT_FUNCTION_HASH_SIZE,
                                                                          &hash_ctl,
-                                                                         HASH_ELEM | HASH_FUNCTION);
+                                                                         HASH_ELEM | HASH_BLOBS);
        }
 
        /* Get the stats entry for this function, create if necessary */
@@ -3483,19 +3481,17 @@ reset_dbentry_counters(PgStat_StatDBEntry *dbentry)
        memset(&hash_ctl, 0, sizeof(hash_ctl));
        hash_ctl.keysize = sizeof(Oid);
        hash_ctl.entrysize = sizeof(PgStat_StatTabEntry);
-       hash_ctl.hash = oid_hash;
        dbentry->tables = hash_create("Per-database table",
                                                                  PGSTAT_TAB_HASH_SIZE,
                                                                  &hash_ctl,
-                                                                 HASH_ELEM | HASH_FUNCTION);
+                                                                 HASH_ELEM | HASH_BLOBS);
 
        hash_ctl.keysize = sizeof(Oid);
        hash_ctl.entrysize = sizeof(PgStat_StatFuncEntry);
-       hash_ctl.hash = oid_hash;
        dbentry->functions = hash_create("Per-database function",
                                                                         PGSTAT_FUNCTION_HASH_SIZE,
                                                                         &hash_ctl,
-                                                                        HASH_ELEM | HASH_FUNCTION);
+                                                                        HASH_ELEM | HASH_BLOBS);
 }
 
 /*
@@ -3902,10 +3898,9 @@ pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep)
        memset(&hash_ctl, 0, sizeof(hash_ctl));
        hash_ctl.keysize = sizeof(Oid);
        hash_ctl.entrysize = sizeof(PgStat_StatDBEntry);
-       hash_ctl.hash = oid_hash;
        hash_ctl.hcxt = pgStatLocalContext;
        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
@@ -4026,21 +4021,19 @@ pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep)
                                memset(&hash_ctl, 0, sizeof(hash_ctl));
                                hash_ctl.keysize = sizeof(Oid);
                                hash_ctl.entrysize = sizeof(PgStat_StatTabEntry);
-                               hash_ctl.hash = oid_hash;
                                hash_ctl.hcxt = pgStatLocalContext;
                                dbentry->tables = hash_create("Per-database table",
                                                                                          PGSTAT_TAB_HASH_SIZE,
                                                                                          &hash_ctl,
-                                                                  HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+                                                                         HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
 
                                hash_ctl.keysize = sizeof(Oid);
                                hash_ctl.entrysize = sizeof(PgStat_StatFuncEntry);
-                               hash_ctl.hash = oid_hash;
                                hash_ctl.hcxt = pgStatLocalContext;
                                dbentry->functions = hash_create("Per-database function",
                                                                                                 PGSTAT_FUNCTION_HASH_SIZE,
                                                                                                 &hash_ctl,
-                                                                  HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+                                                                         HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
 
                                /*
                                 * If requested, read the data from the database-specific
index cd132c16adf7872ed1803ab38e9483ad4159fd0e..799ec8430ce6dcd65226c978bcecf6e22c8d85df 100644 (file)
@@ -245,11 +245,10 @@ ReorderBufferAllocate(void)
 
        hash_ctl.keysize = sizeof(TransactionId);
        hash_ctl.entrysize = sizeof(ReorderBufferTXNByIdEnt);
-       hash_ctl.hash = tag_hash;
        hash_ctl.hcxt = buffer->context;
 
        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_txn = NULL;
@@ -1111,7 +1110,6 @@ ReorderBufferBuildTupleCidHash(ReorderBuffer *rb, ReorderBufferTXN *txn)
 
        hash_ctl.keysize = sizeof(ReorderBufferTupleCidKey);
        hash_ctl.entrysize = sizeof(ReorderBufferTupleCidEnt);
-       hash_ctl.hash = tag_hash;
        hash_ctl.hcxt = rb->context;
 
        /*
@@ -1120,7 +1118,7 @@ ReorderBufferBuildTupleCidHash(ReorderBuffer *rb, ReorderBufferTXN *txn)
         */
        txn->tuplecid_hash =
                hash_create("ReorderBufferTupleCid", txn->ntuplecids, &hash_ctl,
-                                       HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+                                       HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
 
        dlist_foreach(iter, &txn->tuplecids)
        {
@@ -2434,10 +2432,9 @@ ReorderBufferToastInitHash(ReorderBuffer *rb, ReorderBufferTXN *txn)
        memset(&hash_ctl, 0, sizeof(hash_ctl));
        hash_ctl.keysize = sizeof(Oid);
        hash_ctl.entrysize = sizeof(ReorderBufferToastEnt);
-       hash_ctl.hash = tag_hash;
        hash_ctl.hcxt = rb->context;
        txn->toast_hash = hash_create("ReorderBufferToastHash", 5, &hash_ctl,
-                                                                 HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+                                                                 HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
 }
 
 /*
index 7a38f2f15099520c7384725030282841ba34c83f..0750b639db603cf58d95e666275798c4d7ffd3aa 100644 (file)
@@ -59,13 +59,12 @@ InitBufTable(int size)
        /* BufferTag maps to Buffer */
        info.keysize = sizeof(BufferTag);
        info.entrysize = sizeof(BufferLookupEnt);
-       info.hash = tag_hash;
        info.num_partitions = NUM_BUFFER_PARTITIONS;
 
        SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table",
                                                                  size, size,
                                                                  &info,
-                                                                 HASH_ELEM | HASH_FUNCTION | HASH_PARTITION);
+                                                                 HASH_ELEM | HASH_BLOBS | HASH_PARTITION);
 }
 
 /*
index 9b62aecd9178fc37d99dc735d6304d308f15aa9f..1b99e216f125b82ad96c1409a72373fc0c7bd0f6 100644 (file)
@@ -2063,10 +2063,9 @@ InitBufferPoolAccess(void)
        MemSet(&hash_ctl, 0, sizeof(hash_ctl));
        hash_ctl.keysize = sizeof(int32);
        hash_ctl.entrysize = sizeof(PrivateRefCountArray);
-       hash_ctl.hash = oid_hash; /* a bit more efficient than tag_hash */
 
        PrivateRefCountHash = hash_create("PrivateRefCount", 100, &hash_ctl,
-                                                                         HASH_ELEM | HASH_FUNCTION);
+                                                                         HASH_ELEM | HASH_BLOBS);
 }
 
 /*
index 6c81be4237709c1603ea0c6f05eab741264700ae..3768b0212674b7b09d506edc82f98dc8a16dc5ec 100644 (file)
@@ -415,12 +415,11 @@ InitLocalBuffers(void)
        MemSet(&info, 0, sizeof(info));
        info.keysize = sizeof(BufferTag);
        info.entrysize = sizeof(LocalBufferLookupEnt);
-       info.hash = tag_hash;
 
        LocalBufHash = hash_create("Local Buffer Lookup Table",
                                                           nbufs,
                                                           &info,
-                                                          HASH_ELEM | HASH_FUNCTION);
+                                                          HASH_ELEM | HASH_BLOBS);
 
        if (!LocalBufHash)
                elog(ERROR, "could not initialize local buffer hash table");
index cbe957475641e9e48f9c032e66ef9b6fbe1fa3a6..173c9db52e2d3504ceb7f1cb2854871815891e24 100644 (file)
@@ -373,7 +373,6 @@ void
 InitLocks(void)
 {
        HASHCTL         info;
-       int                     hash_flags;
        long            init_table_size,
                                max_table_size;
        bool            found;
@@ -392,15 +391,13 @@ InitLocks(void)
        MemSet(&info, 0, sizeof(info));
        info.keysize = sizeof(LOCKTAG);
        info.entrysize = sizeof(LOCK);
-       info.hash = tag_hash;
        info.num_partitions = NUM_LOCK_PARTITIONS;
-       hash_flags = (HASH_ELEM | HASH_FUNCTION | HASH_PARTITION);
 
        LockMethodLockHash = ShmemInitHash("LOCK hash",
                                                                           init_table_size,
                                                                           max_table_size,
                                                                           &info,
-                                                                          hash_flags);
+                                                                       HASH_ELEM | HASH_BLOBS | HASH_PARTITION);
 
        /* Assume an average of 2 holders per lock */
        max_table_size *= 2;
@@ -414,13 +411,12 @@ InitLocks(void)
        info.entrysize = sizeof(PROCLOCK);
        info.hash = proclock_hash;
        info.num_partitions = NUM_LOCK_PARTITIONS;
-       hash_flags = (HASH_ELEM | HASH_FUNCTION | HASH_PARTITION);
 
        LockMethodProcLockHash = ShmemInitHash("PROCLOCK hash",
                                                                                   init_table_size,
                                                                                   max_table_size,
                                                                                   &info,
-                                                                                  hash_flags);
+                                                                HASH_ELEM | HASH_FUNCTION | HASH_PARTITION);
 
        /*
         * Allocate fast-path structures.
@@ -445,13 +441,11 @@ InitLocks(void)
 
        info.keysize = sizeof(LOCALLOCKTAG);
        info.entrysize = sizeof(LOCALLOCK);
-       info.hash = tag_hash;
-       hash_flags = (HASH_ELEM | HASH_FUNCTION);
 
        LockMethodLocalHash = hash_create("LOCALLOCK hash",
                                                                          16,
                                                                          &info,
-                                                                         hash_flags);
+                                                                         HASH_ELEM | HASH_BLOBS);
 }
 
 
index c9f86571fd339967373987685137404d1bfe69d9..26a550f50824271f26248e4e0d4f3ce4127239a5 100644 (file)
@@ -167,10 +167,9 @@ init_lwlock_stats(void)
        MemSet(&ctl, 0, sizeof(ctl));
        ctl.keysize = sizeof(lwlock_stats_key);
        ctl.entrysize = sizeof(lwlock_stats);
-       ctl.hash = tag_hash;
        ctl.hcxt = lwlock_stats_cxt;
        lwlock_stats_htab = hash_create("lwlock stats", 16384, &ctl,
-                                                                       HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+                                                                       HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
        if (!exit_registered)
        {
                on_shmem_exit(print_lwlock_stats, 0);
index f1261181c9ee0d461e9a3710b1d6afc430e08626..e783955a40afb8f1ccc24e088d6084a581caad69 100644 (file)
  * the lock partition number from the hashcode.
  */
 #define PredicateLockTargetTagHashCode(predicatelocktargettag) \
-       (tag_hash((predicatelocktargettag), sizeof(PREDICATELOCKTARGETTAG)))
+       get_hash_value(PredicateLockTargetHash, predicatelocktargettag)
 
 /*
  * Given a predicate lock tag, and the hash for its target,
@@ -1095,7 +1095,6 @@ void
 InitPredicateLocks(void)
 {
        HASHCTL         info;
-       int                     hash_flags;
        long            max_table_size;
        Size            requestSize;
        bool            found;
@@ -1113,15 +1112,14 @@ InitPredicateLocks(void)
        MemSet(&info, 0, sizeof(info));
        info.keysize = sizeof(PREDICATELOCKTARGETTAG);
        info.entrysize = sizeof(PREDICATELOCKTARGET);
-       info.hash = tag_hash;
        info.num_partitions = NUM_PREDICATELOCK_PARTITIONS;
-       hash_flags = (HASH_ELEM | HASH_FUNCTION | HASH_PARTITION | HASH_FIXED_SIZE);
 
        PredicateLockTargetHash = ShmemInitHash("PREDICATELOCKTARGET hash",
                                                                                        max_table_size,
                                                                                        max_table_size,
                                                                                        &info,
-                                                                                       hash_flags);
+                                                                                       HASH_ELEM | HASH_BLOBS |
+                                                                                       HASH_PARTITION | HASH_FIXED_SIZE);
 
        /* Assume an average of 2 xacts per target */
        max_table_size *= 2;
@@ -1143,13 +1141,13 @@ InitPredicateLocks(void)
        info.entrysize = sizeof(PREDICATELOCK);
        info.hash = predicatelock_hash;
        info.num_partitions = NUM_PREDICATELOCK_PARTITIONS;
-       hash_flags = (HASH_ELEM | HASH_FUNCTION | HASH_PARTITION | HASH_FIXED_SIZE);
 
        PredicateLockHash = ShmemInitHash("PREDICATELOCK hash",
                                                                          max_table_size,
                                                                          max_table_size,
                                                                          &info,
-                                                                         hash_flags);
+                                                                         HASH_ELEM | HASH_FUNCTION |
+                                                                         HASH_PARTITION | HASH_FIXED_SIZE);
 
        /*
         * Compute size for serializable transaction hashtable. Note these
@@ -1224,14 +1222,13 @@ InitPredicateLocks(void)
        MemSet(&info, 0, sizeof(info));
        info.keysize = sizeof(SERIALIZABLEXIDTAG);
        info.entrysize = sizeof(SERIALIZABLEXID);
-       info.hash = tag_hash;
-       hash_flags = (HASH_ELEM | HASH_FUNCTION | HASH_FIXED_SIZE);
 
        SerializableXidHash = ShmemInitHash("SERIALIZABLEXID hash",
                                                                                max_table_size,
                                                                                max_table_size,
                                                                                &info,
-                                                                               hash_flags);
+                                                                               HASH_ELEM | HASH_BLOBS |
+                                                                               HASH_FIXED_SIZE);
 
        /*
         * Allocate space for tracking rw-conflicts in lists attached to the
@@ -1793,11 +1790,10 @@ GetSerializableTransactionSnapshotInt(Snapshot snapshot,
        MemSet(&hash_ctl, 0, sizeof(hash_ctl));
        hash_ctl.keysize = sizeof(PREDICATELOCKTARGETTAG);
        hash_ctl.entrysize = sizeof(LOCALPREDICATELOCK);
-       hash_ctl.hash = tag_hash;
        LocalPredicateLockHash = hash_create("Local predicate lock",
                                                                                 max_predicate_locks_per_xact,
                                                                                 &hash_ctl,
-                                                                                HASH_ELEM | HASH_FUNCTION);
+                                                                                HASH_ELEM | HASH_BLOBS);
 
        return snapshot;
 }
index 167d61c1afecc655860d3f49aeeb6d67fc003a62..53d9188e18b443bdf127fb3b01ca4ac568a4086c 100644 (file)
@@ -229,12 +229,11 @@ mdinit(void)
                MemSet(&hash_ctl, 0, sizeof(hash_ctl));
                hash_ctl.keysize = sizeof(RelFileNode);
                hash_ctl.entrysize = sizeof(PendingOperationEntry);
-               hash_ctl.hash = tag_hash;
                hash_ctl.hcxt = pendingOpsCxt;
                pendingOpsTable = hash_create("Pending Ops Table",
                                                                          100L,
                                                                          &hash_ctl,
-                                                                  HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+                                                                         HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
                pendingUnlinks = NIL;
        }
 }
index d16f5592983af31096eea1a3c6ba699926619145..87be47709fcc15e23cbbffe38df7413f89a34ed4 100644 (file)
@@ -146,9 +146,8 @@ smgropen(RelFileNode rnode, BackendId backend)
                MemSet(&ctl, 0, sizeof(ctl));
                ctl.keysize = sizeof(RelFileNodeBackend);
                ctl.entrysize = sizeof(SMgrRelationData);
-               ctl.hash = tag_hash;
                SMgrRelationHash = hash_create("smgr relation table", 400,
-                                                                          &ctl, HASH_ELEM | HASH_FUNCTION);
+                                                                          &ctl, HASH_ELEM | HASH_BLOBS);
                first_unowned_reln = NULL;
        }
 
index 4d7e9c311fb610ce36a87531c3dbe8dc03c297d3..3653888f39900e83c7e92860d4445cf4ac1ab4a6 100644 (file)
@@ -290,12 +290,11 @@ compute_array_stats(VacAttrStats *stats, AnalyzeAttrFetchFunc fetchfunc,
        MemSet(&count_hash_ctl, 0, sizeof(count_hash_ctl));
        count_hash_ctl.keysize = sizeof(int);
        count_hash_ctl.entrysize = sizeof(DECountItem);
-       count_hash_ctl.hash = tag_hash;
        count_hash_ctl.hcxt = CurrentMemoryContext;
        count_tab = hash_create("Array distinct element count table",
                                                        64,
                                                        &count_hash_ctl,
-                                                       HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+                                                       HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
 
        /* Initialize counters. */
        b_current = 1;
index 94bb5a47bb730aff35ddd8408b497186fbeabeab..1b6874303d57d0569a321b1750dcf9fd93583ace 100644 (file)
@@ -875,9 +875,8 @@ lookup_collation_cache(Oid collation, bool set_flags)
                memset(&ctl, 0, sizeof(ctl));
                ctl.keysize = sizeof(Oid);
                ctl.entrysize = sizeof(collation_cache_entry);
-               ctl.hash = oid_hash;
                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);
index 2f0230384f42a0f3d9c2397f7b8fd2ad3070edd6..5c75390ce4911b8c2b2f899f4c41ab994446a302 100644 (file)
@@ -3326,10 +3326,9 @@ ri_InitHashTables(void)
        memset(&ctl, 0, sizeof(ctl));
        ctl.keysize = sizeof(Oid);
        ctl.entrysize = sizeof(RI_ConstraintInfo);
-       ctl.hash = oid_hash;
        ri_constraint_cache = hash_create("RI constraint cache",
                                                                          RI_INIT_CONSTRAINTHASHSIZE,
-                                                                         &ctl, HASH_ELEM | HASH_FUNCTION);
+                                                                         &ctl, HASH_ELEM | HASH_BLOBS);
 
        /* Arrange to flush cache on pg_constraint changes */
        CacheRegisterSyscacheCallback(CONSTROID,
@@ -3339,18 +3338,16 @@ ri_InitHashTables(void)
        memset(&ctl, 0, sizeof(ctl));
        ctl.keysize = sizeof(RI_QueryKey);
        ctl.entrysize = sizeof(RI_QueryHashEntry);
-       ctl.hash = tag_hash;
        ri_query_cache = hash_create("RI query cache",
                                                                 RI_INIT_QUERYHASHSIZE,
-                                                                &ctl, HASH_ELEM | HASH_FUNCTION);
+                                                                &ctl, HASH_ELEM | HASH_BLOBS);
 
        memset(&ctl, 0, sizeof(ctl));
        ctl.keysize = sizeof(RI_CompareKey);
        ctl.entrysize = sizeof(RI_CompareHashEntry);
-       ctl.hash = tag_hash;
        ri_compare_cache = hash_create("RI compare cache",
                                                                   RI_INIT_QUERYHASHSIZE,
-                                                                  &ctl, HASH_ELEM | HASH_FUNCTION);
+                                                                  &ctl, HASH_ELEM | HASH_BLOBS);
 }
 
 
index 5fcf0dd7c75bf7d283846f7bdd24535bcfa203a2..75e7ae60caca9493c8410c175266bd3ad5e96913 100644 (file)
@@ -82,10 +82,9 @@ InitializeAttoptCache(void)
        MemSet(&ctl, 0, sizeof(ctl));
        ctl.keysize = sizeof(AttoptCacheKey);
        ctl.entrysize = sizeof(AttoptCacheEntry);
-       ctl.hash = tag_hash;
        AttoptCacheHash =
                hash_create("Attopt cache", 256, &ctl,
-                                       HASH_ELEM | HASH_FUNCTION);
+                                       HASH_ELEM | HASH_BLOBS);
 
        /* Make sure we've initialized CacheMemoryContext. */
        if (!CacheMemoryContext)
index b9d442cdfc93045058e6e33d25d591a9e543d21e..01051b08a0dd1fe1818ddef5f77f451a5b874cb1 100644 (file)
@@ -123,10 +123,9 @@ BuildEventTriggerCache(void)
        MemSet(&ctl, 0, sizeof(ctl));
        ctl.keysize = sizeof(EventTriggerEvent);
        ctl.entrysize = sizeof(EventTriggerCacheEntry);
-       ctl.hash = tag_hash;
        ctl.hcxt = EventTriggerCacheContext;
        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.
index 79244e5686512a0de81d8609e5cd5d7b5015503c..c2e574da4827ca57e31e0f24b1f883cd5f42bb0f 100644 (file)
@@ -1409,9 +1409,8 @@ LookupOpclassInfo(Oid operatorClassOid,
                MemSet(&ctl, 0, sizeof(ctl));
                ctl.keysize = sizeof(Oid);
                ctl.entrysize = sizeof(OpClassCacheEnt);
-               ctl.hash = oid_hash;
                OpClassCache = hash_create("Operator class cache", 64,
-                                                                  &ctl, HASH_ELEM | HASH_FUNCTION);
+                                                                  &ctl, HASH_ELEM | HASH_BLOBS);
 
                /* Also make sure CacheMemoryContext exists */
                if (!CacheMemoryContext)
@@ -3140,9 +3139,8 @@ RelationCacheInitialize(void)
        MemSet(&ctl, 0, sizeof(ctl));
        ctl.keysize = sizeof(Oid);
        ctl.entrysize = sizeof(RelIdCacheEnt);
-       ctl.hash = oid_hash;
        RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
-                                                                 &ctl, HASH_ELEM | HASH_FUNCTION);
+                                                                 &ctl, HASH_ELEM | HASH_BLOBS);
 
        /*
         * relation mapper needs to be initialized too
index 1e8429c64c335c9607c164d91e829439f1f1006a..87813fa52cb4d16a01c2b467f36cc4ebf3a4e358 100644 (file)
@@ -115,7 +115,6 @@ InitializeRelfilenodeMap(void)
        MemSet(&ctl, 0, sizeof(ctl));
        ctl.keysize = sizeof(RelfilenodeMapKey);
        ctl.entrysize = sizeof(RelfilenodeMapEntry);
-       ctl.hash = tag_hash;
        ctl.hcxt = CacheMemoryContext;
 
        /*
@@ -125,7 +124,7 @@ InitializeRelfilenodeMap(void)
         */
        RelfilenodeMapHash =
                hash_create("RelfilenodeMap cache", 1024, &ctl,
-                                       HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+                                       HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
 
        /* Watch for invalidation events. */
        CacheRegisterRelcacheCallback(RelfilenodeMapInvalidateCallback,
index 24e8679e2547c95c4b55b5530383b503e28a52f3..6cbafaf691987bbe71ca47c60a5e43a334172dcf 100644 (file)
@@ -81,10 +81,9 @@ InitializeTableSpaceCache(void)
        MemSet(&ctl, 0, sizeof(ctl));
        ctl.keysize = sizeof(Oid);
        ctl.entrysize = sizeof(TableSpaceCacheEntry);
-       ctl.hash = oid_hash;
        TableSpaceCacheHash =
                hash_create("TableSpace cache", 16, &ctl,
-                                       HASH_ELEM | HASH_FUNCTION);
+                                       HASH_ELEM | HASH_BLOBS);
 
        /* Make sure we've initialized CacheMemoryContext. */
        if (!CacheMemoryContext)
index 5ff1461f7d818de3643fbadd13312ed76c8d2e59..46da30357bb5e238d7dcf923c1e9600eba702916 100644 (file)
@@ -120,9 +120,8 @@ lookup_ts_parser_cache(Oid prsId)
                MemSet(&ctl, 0, sizeof(ctl));
                ctl.keysize = sizeof(Oid);
                ctl.entrysize = sizeof(TSParserCacheEntry);
-               ctl.hash = oid_hash;
                TSParserCacheHash = hash_create("Tsearch parser cache", 4,
-                                                                               &ctl, HASH_ELEM | HASH_FUNCTION);
+                                                                               &ctl, HASH_ELEM | HASH_BLOBS);
                /* Flush cache on pg_ts_parser changes */
                CacheRegisterSyscacheCallback(TSPARSEROID, InvalidateTSCacheCallBack,
                                                                          PointerGetDatum(TSParserCacheHash));
@@ -219,9 +218,8 @@ lookup_ts_dictionary_cache(Oid dictId)
                MemSet(&ctl, 0, sizeof(ctl));
                ctl.keysize = sizeof(Oid);
                ctl.entrysize = sizeof(TSDictionaryCacheEntry);
-               ctl.hash = oid_hash;
                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 */
                CacheRegisterSyscacheCallback(TSDICTOID, InvalidateTSCacheCallBack,
                                                                          PointerGetDatum(TSDictionaryCacheHash));
@@ -368,9 +366,8 @@ init_ts_config_cache(void)
        MemSet(&ctl, 0, sizeof(ctl));
        ctl.keysize = sizeof(Oid);
        ctl.entrysize = sizeof(TSConfigCacheEntry);
-       ctl.hash = oid_hash;
        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 */
        CacheRegisterSyscacheCallback(TSCONFIGOID, InvalidateTSCacheCallBack,
                                                                  PointerGetDatum(TSConfigCacheHash));
index 29aec3cf743c9fdc131484a0faf262e9ebbf3341..08e17b92d22db0f2726e782880e8b96fccf24db5 100644 (file)
@@ -166,9 +166,8 @@ lookup_type_cache(Oid type_id, int flags)
                MemSet(&ctl, 0, sizeof(ctl));
                ctl.keysize = sizeof(Oid);
                ctl.entrysize = sizeof(TypeCacheEntry);
-               ctl.hash = oid_hash;
                TypeCacheHash = hash_create("Type information cache", 64,
-                                                                       &ctl, HASH_ELEM | HASH_FUNCTION);
+                                                                       &ctl, HASH_ELEM | HASH_BLOBS);
 
                /* Also set up callbacks for SI invalidations */
                CacheRegisterRelcacheCallback(TypeCacheRelCallback, (Datum) 0);
@@ -846,9 +845,8 @@ assign_record_type_typmod(TupleDesc tupDesc)
                MemSet(&ctl, 0, sizeof(ctl));
                ctl.keysize = REC_HASH_KEYS * sizeof(Oid);
                ctl.entrysize = sizeof(RecordCacheEntry);
-               ctl.hash = tag_hash;
                RecordCacheHash = hash_create("Record information cache", 64,
-                                                                         &ctl, HASH_ELEM | HASH_FUNCTION);
+                                                                         &ctl, HASH_ELEM | HASH_BLOBS);
 
                /* Also make sure CacheMemoryContext exists */
                if (!CacheMemoryContext)
index a95be056dae434c75caee1499f040dd9c15cdf2e..e81c855315239d024beb965c036e6961983367e7 100644 (file)
@@ -540,11 +540,10 @@ record_C_func(HeapTuple procedureTuple,
                MemSet(&hash_ctl, 0, sizeof(hash_ctl));
                hash_ctl.keysize = sizeof(Oid);
                hash_ctl.entrysize = sizeof(CFuncHashTabEntry);
-               hash_ctl.hash = oid_hash;
                CFuncHash = hash_create("CFuncHash",
                                                                100,
                                                                &hash_ctl,
-                                                               HASH_ELEM | HASH_FUNCTION);
+                                                               HASH_ELEM | HASH_BLOBS);
        }
 
        entry = (CFuncHashTabEntry *)
index 2b99e4b5218c0319d653f4124f0872462aa4ca7c..5f6d6cbbde5ac215df8a216b0f80d273d7de18cd 100644 (file)
  * in local memory, we typically use palloc() which will throw error on
  * 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) 1994, Regents of the University of California
  *
@@ -305,15 +319,32 @@ hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
        hashp->tabname = (char *) (hashp + 1);
        strcpy(hashp->tabname, tabname);
 
+       /*
+        * Select the appropriate hash function (see comments at head of file).
+        */
        if (flags & HASH_FUNCTION)
                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
                hashp->hash = string_hash;              /* default hash function */
 
        /*
         * 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
-        * 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)
                hashp->match = info->match;
@@ -332,6 +363,7 @@ hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
        else
                hashp->keycopy = memcpy;
 
+       /* And select the entry allocation function, too. */
        if (flags & HASH_ALLOC)
                hashp->alloc = info->alloc;
        else
index a12f98f2f2584be961b3c0880492c8e4523bba58..adb0bd9564cdbb42aa89eef0fcc389c3267446ee 100644 (file)
@@ -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)
  */
 uint32
-oid_hash(const void *key, Size keysize)
+uint32_hash(const void *key, Size keysize)
 {
-       Assert(keysize == sizeof(Oid));
-       return DatumGetUInt32(hash_uint32((uint32) *((const Oid *) key)));
+       Assert(keysize == sizeof(uint32));
+       return DatumGetUInt32(hash_uint32(*((const uint32 *) key)));
 }
 
 /*
index a70c7542c92d624114beeae6499a5db2abb7bb2d..ea7a905db4a42fa3b418c1337cdd223f37faa6f8 100644 (file)
@@ -218,13 +218,12 @@ GetComboCommandId(CommandId cmin, CommandId cmax)
                memset(&hash_ctl, 0, sizeof(hash_ctl));
                hash_ctl.keysize = sizeof(ComboCidKeyData);
                hash_ctl.entrysize = sizeof(ComboCidEntryData);
-               hash_ctl.hash = tag_hash;
                hash_ctl.hcxt = TopTransactionContext;
 
                comboHash = hash_create("Combo CIDs",
                                                                CCID_HASH_SIZE,
                                                                &hash_ctl,
-                                                               HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
+                                                               HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
 
                comboCids = (ComboCidKeyData *)
                        MemoryContextAlloc(TopTransactionContext,
index 77974a193b2798d0d3c5f215dcaef35857db8899..dfdf658ddf0dcacbca98885073798eb4be0da03b 100644 (file)
@@ -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
- * 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.)
  */
 typedef void *(*HashCopyFunc) (void *dest, const void *src, Size keysize);
@@ -80,19 +80,20 @@ typedef struct HASHCTL
 } HASHCTL;
 
 /* Flags to indicate which parameters are supplied */
-#define HASH_PARTITION 0x001   /* Hashtable is used w/partitioned locking */
-#define HASH_SEGMENT   0x002   /* Set segment size */
-#define HASH_DIRSIZE   0x004   /* Set directory size (initial and max) */
-#define HASH_FFACTOR   0x008   /* Set fill factor */
-#define HASH_FUNCTION  0x010   /* Set user defined hash function */
-#define HASH_ELEM              0x020   /* Set keysize and entrysize */
-#define HASH_SHARED_MEM 0x040  /* Hashtable is in shared memory */
-#define HASH_ATTACH            0x080   /* Do not initialize hctl */
-#define HASH_ALLOC             0x100   /* Set memory allocator */
-#define HASH_CONTEXT   0x200   /* Set memory allocation context */
-#define HASH_COMPARE   0x400   /* Set user defined comparison function */
-#define HASH_KEYCOPY   0x800   /* Set user defined key-copying function */
-#define HASH_FIXED_SIZE 0x1000 /* Initial size is a hard limit */
+#define HASH_PARTITION 0x0001  /* Hashtable is used w/partitioned locking */
+#define HASH_SEGMENT   0x0002  /* Set segment size */
+#define HASH_DIRSIZE   0x0004  /* Set directory size (initial and max) */
+#define HASH_FFACTOR   0x0008  /* Set fill factor */
+#define HASH_ELEM              0x0010  /* Set keysize and entrysize */
+#define HASH_BLOBS             0x0020  /* Select support functions for binary keys */
+#define HASH_FUNCTION  0x0040  /* Set user defined hash function */
+#define HASH_COMPARE   0x0080  /* Set user defined comparison function */
+#define HASH_KEYCOPY   0x0100  /* Set user defined key-copying function */
+#define HASH_ALLOC             0x0200  /* Set memory allocator */
+#define HASH_CONTEXT   0x0400  /* Set memory allocation context */
+#define HASH_SHARED_MEM 0x0800 /* Hashtable is in shared memory */
+#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 */
@@ -143,11 +144,17 @@ extern void AtEOSubXact_HashTables(bool isCommit, int nestDepth);
 
 /*
  * 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 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 int     bitmap_match(const void *key1, const void *key2, Size keysize);
 
+#define oid_hash uint32_hash   /* Remove me eventually */
+
 #endif   /* HSEARCH_H */
index 56295715a18b56fdf8281fda8d6a9252ac994c63..492c1ef4d24b93a47fc01396e94f3ab6f30a3f42 100644 (file)
@@ -456,20 +456,18 @@ _PG_init(void)
        memset(&hash_ctl, 0, sizeof(hash_ctl));
        hash_ctl.keysize = sizeof(Oid);
        hash_ctl.entrysize = sizeof(plperl_interp_desc);
-       hash_ctl.hash = oid_hash;
        plperl_interp_hash = hash_create("PL/Perl interpreters",
                                                                         8,
                                                                         &hash_ctl,
-                                                                        HASH_ELEM | HASH_FUNCTION);
+                                                                        HASH_ELEM | HASH_BLOBS);
 
        memset(&hash_ctl, 0, sizeof(hash_ctl));
        hash_ctl.keysize = sizeof(plperl_proc_key);
        hash_ctl.entrysize = sizeof(plperl_proc_ptr);
-       hash_ctl.hash = tag_hash;
        plperl_proc_hash = hash_create("PL/Perl procedures",
                                                                   32,
                                                                   &hash_ctl,
-                                                                  HASH_ELEM | HASH_FUNCTION);
+                                                                  HASH_ELEM | HASH_BLOBS);
 
        /*
         * Save the default opmask.
index d2fd685c35dc18a8c59408674d94b18cfc9fd725..24dc371d62316cc3b661f2a5368e9ef750a98241 100644 (file)
@@ -2519,11 +2519,10 @@ plpgsql_HashTableInit(void)
        memset(&ctl, 0, sizeof(ctl));
        ctl.keysize = sizeof(PLpgSQL_func_hashkey);
        ctl.entrysize = sizeof(plpgsql_HashEnt);
-       ctl.hash = tag_hash;
        plpgsql_HashTable = hash_create("PLpgSQL function cache",
                                                                        FUNCS_PER_USER,
                                                                        &ctl,
-                                                                       HASH_ELEM | HASH_FUNCTION);
+                                                                       HASH_ELEM | HASH_BLOBS);
 }
 
 static PLpgSQL_function *
index 37ea2a490d963eecdbebd07889ad9a4e0aa0f7c1..b8dc891e3730795eb8add6704d6a83d58002277e 100644 (file)
@@ -226,9 +226,8 @@ PLy_add_exceptions(PyObject *plpy)
        memset(&hash_ctl, 0, sizeof(hash_ctl));
        hash_ctl.keysize = sizeof(int);
        hash_ctl.entrysize = sizeof(PLyExceptionEntry);
-       hash_ctl.hash = tag_hash;
        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);
 }
index fad80b242e75a9a11a2e8214d6b08695bfc30216..bd483012d35a73e52343a0597262f3695e007b68 100644 (file)
@@ -39,9 +39,8 @@ init_procedure_caches(void)
        memset(&hash_ctl, 0, sizeof(hash_ctl));
        hash_ctl.keysize = sizeof(PLyProcedureKey);
        hash_ctl.entrysize = sizeof(PLyProcedureEntry);
-       hash_ctl.hash = tag_hash;
        PLy_procedure_cache = hash_create("PL/Python procedures", 32, &hash_ctl,
-                                                                         HASH_ELEM | HASH_FUNCTION);
+                                                                         HASH_ELEM | HASH_BLOBS);
 }
 
 /*
index a53cca4f27518082a9474f5831dbf464ab6e312d..8f9804696e5bd1f2bd1f040aa24b1f3b8846e6a9 100644 (file)
@@ -378,11 +378,10 @@ _PG_init(void)
        memset(&hash_ctl, 0, sizeof(hash_ctl));
        hash_ctl.keysize = sizeof(Oid);
        hash_ctl.entrysize = sizeof(pltcl_interp_desc);
-       hash_ctl.hash = oid_hash;
        pltcl_interp_htab = hash_create("PL/Tcl interpreters",
                                                                        8,
                                                                        &hash_ctl,
-                                                                       HASH_ELEM | HASH_FUNCTION);
+                                                                       HASH_ELEM | HASH_BLOBS);
 
        /************************************************************
         * Create the hash table for function lookup
@@ -390,11 +389,10 @@ _PG_init(void)
        memset(&hash_ctl, 0, sizeof(hash_ctl));
        hash_ctl.keysize = sizeof(pltcl_proc_key);
        hash_ctl.entrysize = sizeof(pltcl_proc_ptr);
-       hash_ctl.hash = tag_hash;
        pltcl_proc_htab = hash_create("PL/Tcl functions",
                                                                  100,
                                                                  &hash_ctl,
-                                                                 HASH_ELEM | HASH_FUNCTION);
+                                                                 HASH_ELEM | HASH_BLOBS);
 
        pltcl_pm_init_done = true;
 }