Re: hash_create API changes (was Re: speedup tidbitmap patch: hash BlockNumber) - Mailing list pgsql-hackers

From Tom Lane
Subject Re: hash_create API changes (was Re: speedup tidbitmap patch: hash BlockNumber)
Date
Msg-id 32316.1418869234@sss.pgh.pa.us
Whole thread Raw
In response to hash_create API changes (was Re: speedup tidbitmap patch: hash BlockNumber)  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: hash_create API changes (was Re: speedup tidbitmap patch: hash BlockNumber)  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-hackers
I wrote:
> However, there's another way we could attack this,
> which is to invent a new hash option flag bit that says "pick a suitable
> hash function for me, assuming that all bits of the specified key size are
> significant".  So instead of

>     ctl.keysize = sizeof(...);
>     ctl.entrysize = sizeof(...);
>     ctl.hash = tag_hash;
>     tab = hash_create("...", ..., &ctl,
>                       HASH_ELEM | HASH_FUNCTION);

> you'd write

>     ctl.keysize = sizeof(...);
>     ctl.entrysize = sizeof(...);
>     tab = hash_create("...", ..., &ctl,
>                       HASH_ELEM | HASH_BLOBS);

> which would save some code space and is arguably cleaner than the
> current approach of specifying some support functions and not others.

Here's a proposed patch along this line.  I left in oid_hash (in the
form of a macro) so that this does not cause any API break for existing
third-party modules.  However, no callers in our own code directly
refer to tag_hash or oid_hash anymore.

            regards, tom lane

diff --git a/contrib/pg_trgm/trgm_regexp.c b/contrib/pg_trgm/trgm_regexp.c
index 9f05053..f7a73cb 100644
*** a/contrib/pg_trgm/trgm_regexp.c
--- b/contrib/pg_trgm/trgm_regexp.c
*************** transformGraph(TrgmNFA *trgmNFA)
*** 915,925 ****
      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);

      /* Create initial state: ambiguous prefix, NFA's initial state */
      MemSet(&initkey, 0, sizeof(initkey));
--- 915,924 ----
      hashCtl.keysize = sizeof(TrgmStateKey);
      hashCtl.entrysize = sizeof(TrgmState);
      hashCtl.hcxt = CurrentMemoryContext;
      trgmNFA->states = hash_create("Trigram NFA",
                                    1024,
                                    &hashCtl,
!                                   HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);

      /* Create initial state: ambiguous prefix, NFA's initial state */
      MemSet(&initkey, 0, sizeof(initkey));
diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c
index 116be7d..61216e5 100644
*** a/contrib/postgres_fdw/connection.c
--- b/contrib/postgres_fdw/connection.c
*************** GetConnection(ForeignServer *server, Use
*** 109,120 ****
          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);

          /*
           * Register some callback functions that manage connection cleanup.
--- 109,119 ----
          MemSet(&ctl, 0, sizeof(ctl));
          ctl.keysize = sizeof(ConnCacheKey);
          ctl.entrysize = sizeof(ConnCacheEntry);
          /* allocate ConnectionHash in the cache context */
          ctl.hcxt = CacheMemoryContext;
          ConnectionHash = hash_create("postgres_fdw connections", 8,
                                       &ctl,
!                                      HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);

          /*
           * Register some callback functions that manage connection cleanup.
diff --git a/src/backend/access/gist/gistbuild.c b/src/backend/access/gist/gistbuild.c
index 5acc986..09a9df4 100644
*** a/src/backend/access/gist/gistbuild.c
--- b/src/backend/access/gist/gistbuild.c
*************** gistInitParentMap(GISTBuildState *builds
*** 1142,1153 ****
      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);
  }

  static void
--- 1142,1151 ----
      hashCtl.keysize = sizeof(BlockNumber);
      hashCtl.entrysize = sizeof(ParentMapEntry);
      hashCtl.hcxt = CurrentMemoryContext;
      buildstate->parentMap = hash_create("gistbuild parent map",
                                          1024,
                                          &hashCtl,
!                                       HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
  }

  static void
diff --git a/src/backend/access/gist/gistbuildbuffers.c b/src/backend/access/gist/gistbuildbuffers.c
index 577ea61..4937c38 100644
*** a/src/backend/access/gist/gistbuildbuffers.c
--- b/src/backend/access/gist/gistbuildbuffers.c
*************** gistInitBuildBuffers(int pagesPerBuffer,
*** 76,91 ****
       * nodeBuffersTab hash is association between index blocks and it's
       * buffers.
       */
      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);

      gfbb->bufferEmptyingQueue = NIL;

--- 76,89 ----
       * 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;
      gfbb->nodeBuffersTab = hash_create("gistbuildbuffers",
                                         1024,
                                         &hashCtl,
!                                        HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);

      gfbb->bufferEmptyingQueue = NIL;

diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index 4b132b7..9738865 100644
*** a/src/backend/access/heap/rewriteheap.c
--- b/src/backend/access/heap/rewriteheap.c
*************** begin_heap_rewrite(Relation old_heap, Re
*** 283,295 ****
      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_ctl.entrysize = sizeof(OldToNewMappingData);

--- 283,294 ----
      hash_ctl.keysize = sizeof(TidHashKey);
      hash_ctl.entrysize = sizeof(UnresolvedTupData);
      hash_ctl.hcxt = state->rs_cxt;

      state->rs_unresolved_tups =
          hash_create("Rewrite / Unresolved ctids",
                      128,        /* arbitrary initial size */
                      &hash_ctl,
!                     HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);

      hash_ctl.entrysize = sizeof(OldToNewMappingData);

*************** begin_heap_rewrite(Relation old_heap, Re
*** 297,303 ****
          hash_create("Rewrite / Old to new tid map",
                      128,        /* arbitrary initial size */
                      &hash_ctl,
!                     HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);

      MemoryContextSwitchTo(old_cxt);

--- 296,302 ----
          hash_create("Rewrite / Old to new tid map",
                      128,        /* arbitrary initial size */
                      &hash_ctl,
!                     HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);

      MemoryContextSwitchTo(old_cxt);

*************** logical_begin_heap_rewrite(RewriteState
*** 834,846 ****
      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);
  }

  /*
--- 833,844 ----
      hash_ctl.keysize = sizeof(TransactionId);
      hash_ctl.entrysize = sizeof(RewriteMappingFile);
      hash_ctl.hcxt = state->rs_cxt;

      state->rs_logical_mappings =
          hash_create("Logical rewrite mapping",
                      128,        /* arbitrary initial size */
                      &hash_ctl,
!                     HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
  }

  /*
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index ae323a0..89b2ba5 100644
*** a/src/backend/access/transam/xlogutils.c
--- b/src/backend/access/transam/xlogutils.c
*************** log_invalid_page(RelFileNode node, ForkN
*** 107,118 ****
          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);
      }

      /* we currently assume xl_invalid_page_key contains no padding */
--- 107,117 ----
          memset(&ctl, 0, sizeof(ctl));
          ctl.keysize = sizeof(xl_invalid_page_key);
          ctl.entrysize = sizeof(xl_invalid_page);

          invalid_page_tab = hash_create("XLOG invalid-page table",
                                         100,
                                         &ctl,
!                                        HASH_ELEM | HASH_BLOBS);
      }

      /* we currently assume xl_invalid_page_key contains no padding */
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index ba5b938..811e1d4 100644
*** a/src/backend/commands/sequence.c
--- b/src/backend/commands/sequence.c
*************** create_seq_hashtable(void)
*** 986,995 ****
      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);
  }

  /*
--- 986,994 ----
      memset(&ctl, 0, sizeof(ctl));
      ctl.keysize = sizeof(Oid);
      ctl.entrysize = sizeof(SeqTableData);

      seqhashtab = hash_create("Sequence values", 16, &ctl,
!                              HASH_ELEM | HASH_BLOBS);
  }

  /*
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index a880c81..3b07438 100644
*** a/src/backend/nodes/tidbitmap.c
--- b/src/backend/nodes/tidbitmap.c
*************** tbm_create_pagetable(TIDBitmap *tbm)
*** 221,232 ****
      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);

      /* If entry1 is valid, push it into the hashtable */
      if (tbm->status == TBM_ONE_PAGE)
--- 221,231 ----
      MemSet(&hash_ctl, 0, sizeof(hash_ctl));
      hash_ctl.keysize = sizeof(BlockNumber);
      hash_ctl.entrysize = sizeof(PagetableEntry);
      hash_ctl.hcxt = tbm->mcxt;
      tbm->pagetable = hash_create("TIDBitmap",
                                   128,    /* start small and extend */
                                   &hash_ctl,
!                                  HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);

      /* If entry1 is valid, push it into the hashtable */
      if (tbm->status == TBM_ONE_PAGE)
diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c
index 9f9a208..6daa058 100644
*** a/src/backend/optimizer/util/predtest.c
--- b/src/backend/optimizer/util/predtest.c
*************** lookup_proof_cache(Oid pred_op, Oid clau
*** 1711,1719 ****
          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);

          /* Arrange to flush cache on pg_amop changes */
          CacheRegisterSyscacheCallback(AMOPOPID,
--- 1711,1718 ----
          MemSet(&ctl, 0, sizeof(ctl));
          ctl.keysize = sizeof(OprProofCacheKey);
          ctl.entrysize = sizeof(OprProofCacheEntry);
          OprProofCacheHash = hash_create("Btree proof lookup cache", 256,
!                                         &ctl, HASH_ELEM | HASH_BLOBS);

          /* Arrange to flush cache on pg_amop changes */
          CacheRegisterSyscacheCallback(AMOPOPID,
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
index b65b632..11a6397 100644
*** a/src/backend/parser/parse_oper.c
--- b/src/backend/parser/parse_oper.c
*************** find_oper_cache_entry(OprCacheKey *key)
*** 1059,1067 ****
          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);

          /* Arrange to flush cache on pg_operator and pg_cast changes */
          CacheRegisterSyscacheCallback(OPERNAMENSP,
--- 1059,1066 ----
          MemSet(&ctl, 0, sizeof(ctl));
          ctl.keysize = sizeof(OprCacheKey);
          ctl.entrysize = sizeof(OprCacheEntry);
          OprCacheHash = hash_create("Operator lookup cache", 256,
!                                    &ctl, HASH_ELEM | HASH_BLOBS);

          /* Arrange to flush cache on pg_operator and pg_cast changes */
          CacheRegisterSyscacheCallback(OPERNAMENSP,
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 1d6e3f3..675f985 100644
*** a/src/backend/postmaster/autovacuum.c
--- b/src/backend/postmaster/autovacuum.c
*************** rebuild_database_list(Oid newdb)
*** 922,931 ****
       */
      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);

      /* start by inserting the new database */
      score = 0;
--- 922,930 ----
       */
      hctl.keysize = sizeof(Oid);
      hctl.entrysize = sizeof(avl_dbase);
      hctl.hcxt = tmpcxt;
      dbhash = hash_create("db hash", 20, &hctl,    /* magic number here FIXME */
!                          HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);

      /* start by inserting the new database */
      score = 0;
*************** do_autovacuum(void)
*** 1997,2008 ****
      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);

      /*
       * Scan pg_class to determine which tables to vacuum.
--- 1996,2006 ----
      MemSet(&ctl, 0, sizeof(ctl));
      ctl.keysize = sizeof(Oid);
      ctl.entrysize = sizeof(av_relation);

      table_toast_map = hash_create("TOAST to main relid map",
                                    100,
                                    &ctl,
!                                   HASH_ELEM | HASH_BLOBS);

      /*
       * Scan pg_class to determine which tables to vacuum.
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index 6c814ba..8a79d9b 100644
*** a/src/backend/postmaster/checkpointer.c
--- b/src/backend/postmaster/checkpointer.c
*************** CompactCheckpointerRequestQueue(void)
*** 1212,1224 ****
      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);

      /*
       * The basic idea here is that a request can be skipped if it's followed
--- 1212,1223 ----
      MemSet(&ctl, 0, sizeof(ctl));
      ctl.keysize = sizeof(CheckpointerRequest);
      ctl.entrysize = sizeof(struct CheckpointerSlotMapping);
      ctl.hcxt = CurrentMemoryContext;

      htab = hash_create("CompactCheckpointerRequestQueue",
                         CheckpointerShmem->num_requests,
                         &ctl,
!                        HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);

      /*
       * The basic idea here is that a request can be skipped if it's followed
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index f71fdeb..938fc29 100644
*** a/src/backend/postmaster/pgstat.c
--- b/src/backend/postmaster/pgstat.c
*************** pgstat_collect_oids(Oid catalogid)
*** 1132,1143 ****
      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);

      rel = heap_open(catalogid, AccessShareLock);
      snapshot = RegisterSnapshot(GetLatestSnapshot());
--- 1132,1142 ----
      memset(&hash_ctl, 0, sizeof(hash_ctl));
      hash_ctl.keysize = sizeof(Oid);
      hash_ctl.entrysize = sizeof(Oid);
      hash_ctl.hcxt = CurrentMemoryContext;
      htab = hash_create("Temporary table of OIDs",
                         PGSTAT_TAB_HASH_SIZE,
                         &hash_ctl,
!                        HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);

      rel = heap_open(catalogid, AccessShareLock);
      snapshot = RegisterSnapshot(GetLatestSnapshot());
*************** pgstat_init_function_usage(FunctionCallI
*** 1520,1530 ****
          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);
      }

      /* Get the stats entry for this function, create if necessary */
--- 1519,1528 ----
          memset(&hash_ctl, 0, sizeof(hash_ctl));
          hash_ctl.keysize = sizeof(Oid);
          hash_ctl.entrysize = sizeof(PgStat_BackendFunctionEntry);
          pgStatFunctions = hash_create("Function stat entries",
                                        PGSTAT_FUNCTION_HASH_SIZE,
                                        &hash_ctl,
!                                       HASH_ELEM | HASH_BLOBS);
      }

      /* Get the stats entry for this function, create if necessary */
*************** reset_dbentry_counters(PgStat_StatDBEntr
*** 3480,3498 ****
      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_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);
  }

  /*
--- 3478,3494 ----
      memset(&hash_ctl, 0, sizeof(hash_ctl));
      hash_ctl.keysize = sizeof(Oid);
      hash_ctl.entrysize = sizeof(PgStat_StatTabEntry);
      dbentry->tables = hash_create("Per-database table",
                                    PGSTAT_TAB_HASH_SIZE,
                                    &hash_ctl,
!                                   HASH_ELEM | HASH_BLOBS);

      hash_ctl.keysize = sizeof(Oid);
      hash_ctl.entrysize = sizeof(PgStat_StatFuncEntry);
      dbentry->functions = hash_create("Per-database function",
                                       PGSTAT_FUNCTION_HASH_SIZE,
                                       &hash_ctl,
!                                      HASH_ELEM | HASH_BLOBS);
  }

  /*
*************** pgstat_read_statsfiles(Oid onlydb, bool
*** 3899,3908 ****
      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);

      /*
       * Clear out global and archiver statistics so they start from zero in
--- 3895,3903 ----
      memset(&hash_ctl, 0, sizeof(hash_ctl));
      hash_ctl.keysize = sizeof(Oid);
      hash_ctl.entrysize = sizeof(PgStat_StatDBEntry);
      hash_ctl.hcxt = pgStatLocalContext;
      dbhash = hash_create("Databases hash", PGSTAT_DB_HASH_SIZE, &hash_ctl,
!                          HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);

      /*
       * Clear out global and archiver statistics so they start from zero in
*************** pgstat_read_statsfiles(Oid onlydb, bool
*** 4023,4043 ****
                  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_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);

                  /*
                   * If requested, read the data from the database-specific
--- 4018,4036 ----
                  memset(&hash_ctl, 0, sizeof(hash_ctl));
                  hash_ctl.keysize = sizeof(Oid);
                  hash_ctl.entrysize = sizeof(PgStat_StatTabEntry);
                  hash_ctl.hcxt = pgStatLocalContext;
                  dbentry->tables = hash_create("Per-database table",
                                                PGSTAT_TAB_HASH_SIZE,
                                                &hash_ctl,
!                                       HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);

                  hash_ctl.keysize = sizeof(Oid);
                  hash_ctl.entrysize = sizeof(PgStat_StatFuncEntry);
                  hash_ctl.hcxt = pgStatLocalContext;
                  dbentry->functions = hash_create("Per-database function",
                                                   PGSTAT_FUNCTION_HASH_SIZE,
                                                   &hash_ctl,
!                                       HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);

                  /*
                   * If requested, read the data from the database-specific
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index cd132c1..799ec84 100644
*** a/src/backend/replication/logical/reorderbuffer.c
--- b/src/backend/replication/logical/reorderbuffer.c
*************** ReorderBufferAllocate(void)
*** 245,255 ****

      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);

      buffer->by_txn_last_xid = InvalidTransactionId;
      buffer->by_txn_last_txn = NULL;
--- 245,254 ----

      hash_ctl.keysize = sizeof(TransactionId);
      hash_ctl.entrysize = sizeof(ReorderBufferTXNByIdEnt);
      hash_ctl.hcxt = buffer->context;

      buffer->by_txn = hash_create("ReorderBufferByXid", 1000, &hash_ctl,
!                                  HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);

      buffer->by_txn_last_xid = InvalidTransactionId;
      buffer->by_txn_last_txn = NULL;
*************** ReorderBufferBuildTupleCidHash(ReorderBu
*** 1111,1117 ****

      hash_ctl.keysize = sizeof(ReorderBufferTupleCidKey);
      hash_ctl.entrysize = sizeof(ReorderBufferTupleCidEnt);
-     hash_ctl.hash = tag_hash;
      hash_ctl.hcxt = rb->context;

      /*
--- 1110,1115 ----
*************** ReorderBufferBuildTupleCidHash(ReorderBu
*** 1120,1126 ****
       */
      txn->tuplecid_hash =
          hash_create("ReorderBufferTupleCid", txn->ntuplecids, &hash_ctl,
!                     HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);

      dlist_foreach(iter, &txn->tuplecids)
      {
--- 1118,1124 ----
       */
      txn->tuplecid_hash =
          hash_create("ReorderBufferTupleCid", txn->ntuplecids, &hash_ctl,
!                     HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);

      dlist_foreach(iter, &txn->tuplecids)
      {
*************** ReorderBufferToastInitHash(ReorderBuffer
*** 2434,2443 ****
      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);
  }

  /*
--- 2432,2440 ----
      memset(&hash_ctl, 0, sizeof(hash_ctl));
      hash_ctl.keysize = sizeof(Oid);
      hash_ctl.entrysize = sizeof(ReorderBufferToastEnt);
      hash_ctl.hcxt = rb->context;
      txn->toast_hash = hash_create("ReorderBufferToastHash", 5, &hash_ctl,
!                                   HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
  }

  /*
diff --git a/src/backend/storage/buffer/buf_table.c b/src/backend/storage/buffer/buf_table.c
index 7a38f2f..0750b63 100644
*** a/src/backend/storage/buffer/buf_table.c
--- b/src/backend/storage/buffer/buf_table.c
*************** InitBufTable(int size)
*** 59,71 ****
      /* 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);
  }

  /*
--- 59,70 ----
      /* BufferTag maps to Buffer */
      info.keysize = sizeof(BufferTag);
      info.entrysize = sizeof(BufferLookupEnt);
      info.num_partitions = NUM_BUFFER_PARTITIONS;

      SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table",
                                    size, size,
                                    &info,
!                                   HASH_ELEM | HASH_BLOBS | HASH_PARTITION);
  }

  /*
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 9b62aec..1b99e21 100644
*** a/src/backend/storage/buffer/bufmgr.c
--- b/src/backend/storage/buffer/bufmgr.c
*************** InitBufferPoolAccess(void)
*** 2063,2072 ****
      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);
  }

  /*
--- 2063,2071 ----
      MemSet(&hash_ctl, 0, sizeof(hash_ctl));
      hash_ctl.keysize = sizeof(int32);
      hash_ctl.entrysize = sizeof(PrivateRefCountArray);

      PrivateRefCountHash = hash_create("PrivateRefCount", 100, &hash_ctl,
!                                       HASH_ELEM | HASH_BLOBS);
  }

  /*
diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c
index 6c81be4..3768b02 100644
*** a/src/backend/storage/buffer/localbuf.c
--- b/src/backend/storage/buffer/localbuf.c
*************** InitLocalBuffers(void)
*** 415,426 ****
      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);

      if (!LocalBufHash)
          elog(ERROR, "could not initialize local buffer hash table");
--- 415,425 ----
      MemSet(&info, 0, sizeof(info));
      info.keysize = sizeof(BufferTag);
      info.entrysize = sizeof(LocalBufferLookupEnt);

      LocalBufHash = hash_create("Local Buffer Lookup Table",
                                 nbufs,
                                 &info,
!                                HASH_ELEM | HASH_BLOBS);

      if (!LocalBufHash)
          elog(ERROR, "could not initialize local buffer hash table");
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index cbe9574..173c9db 100644
*** a/src/backend/storage/lmgr/lock.c
--- b/src/backend/storage/lmgr/lock.c
*************** void
*** 373,379 ****
  InitLocks(void)
  {
      HASHCTL        info;
-     int            hash_flags;
      long        init_table_size,
                  max_table_size;
      bool        found;
--- 373,378 ----
*************** InitLocks(void)
*** 392,406 ****
      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);

      /* Assume an average of 2 holders per lock */
      max_table_size *= 2;
--- 391,403 ----
      MemSet(&info, 0, sizeof(info));
      info.keysize = sizeof(LOCKTAG);
      info.entrysize = sizeof(LOCK);
      info.num_partitions = NUM_LOCK_PARTITIONS;

      LockMethodLockHash = ShmemInitHash("LOCK hash",
                                         init_table_size,
                                         max_table_size,
                                         &info,
!                                     HASH_ELEM | HASH_BLOBS | HASH_PARTITION);

      /* Assume an average of 2 holders per lock */
      max_table_size *= 2;
*************** InitLocks(void)
*** 414,426 ****
      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);

      /*
       * Allocate fast-path structures.
--- 411,422 ----
      info.entrysize = sizeof(PROCLOCK);
      info.hash = proclock_hash;
      info.num_partitions = NUM_LOCK_PARTITIONS;

      LockMethodProcLockHash = ShmemInitHash("PROCLOCK hash",
                                             init_table_size,
                                             max_table_size,
                                             &info,
!                                  HASH_ELEM | HASH_FUNCTION | HASH_PARTITION);

      /*
       * Allocate fast-path structures.
*************** InitLocks(void)
*** 445,457 ****

      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);
  }


--- 441,451 ----

      info.keysize = sizeof(LOCALLOCKTAG);
      info.entrysize = sizeof(LOCALLOCK);

      LockMethodLocalHash = hash_create("LOCALLOCK hash",
                                        16,
                                        &info,
!                                       HASH_ELEM | HASH_BLOBS);
  }


diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index c9f8657..26a550f 100644
*** a/src/backend/storage/lmgr/lwlock.c
--- b/src/backend/storage/lmgr/lwlock.c
*************** init_lwlock_stats(void)
*** 167,176 ****
      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);
      if (!exit_registered)
      {
          on_shmem_exit(print_lwlock_stats, 0);
--- 167,175 ----
      MemSet(&ctl, 0, sizeof(ctl));
      ctl.keysize = sizeof(lwlock_stats_key);
      ctl.entrysize = sizeof(lwlock_stats);
      ctl.hcxt = lwlock_stats_cxt;
      lwlock_stats_htab = hash_create("lwlock stats", 16384, &ctl,
!                                     HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
      if (!exit_registered)
      {
          on_shmem_exit(print_lwlock_stats, 0);
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c
index f126118..e783955 100644
*** a/src/backend/storage/lmgr/predicate.c
--- b/src/backend/storage/lmgr/predicate.c
***************
*** 286,292 ****
   * the lock partition number from the hashcode.
   */
  #define PredicateLockTargetTagHashCode(predicatelocktargettag) \
!     (tag_hash((predicatelocktargettag), sizeof(PREDICATELOCKTARGETTAG)))

  /*
   * Given a predicate lock tag, and the hash for its target,
--- 286,292 ----
   * the lock partition number from the hashcode.
   */
  #define PredicateLockTargetTagHashCode(predicatelocktargettag) \
!     get_hash_value(PredicateLockTargetHash, predicatelocktargettag)

  /*
   * Given a predicate lock tag, and the hash for its target,
*************** void
*** 1095,1101 ****
  InitPredicateLocks(void)
  {
      HASHCTL        info;
-     int            hash_flags;
      long        max_table_size;
      Size        requestSize;
      bool        found;
--- 1095,1100 ----
*************** InitPredicateLocks(void)
*** 1113,1127 ****
      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);

      /* Assume an average of 2 xacts per target */
      max_table_size *= 2;
--- 1112,1125 ----
      MemSet(&info, 0, sizeof(info));
      info.keysize = sizeof(PREDICATELOCKTARGETTAG);
      info.entrysize = sizeof(PREDICATELOCKTARGET);
      info.num_partitions = NUM_PREDICATELOCK_PARTITIONS;

      PredicateLockTargetHash = ShmemInitHash("PREDICATELOCKTARGET hash",
                                              max_table_size,
                                              max_table_size,
                                              &info,
!                                             HASH_ELEM | HASH_BLOBS |
!                                             HASH_PARTITION | HASH_FIXED_SIZE);

      /* Assume an average of 2 xacts per target */
      max_table_size *= 2;
*************** InitPredicateLocks(void)
*** 1143,1155 ****
      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);

      /*
       * Compute size for serializable transaction hashtable. Note these
--- 1141,1153 ----
      info.entrysize = sizeof(PREDICATELOCK);
      info.hash = predicatelock_hash;
      info.num_partitions = NUM_PREDICATELOCK_PARTITIONS;

      PredicateLockHash = ShmemInitHash("PREDICATELOCK hash",
                                        max_table_size,
                                        max_table_size,
                                        &info,
!                                       HASH_ELEM | HASH_FUNCTION |
!                                       HASH_PARTITION | HASH_FIXED_SIZE);

      /*
       * Compute size for serializable transaction hashtable. Note these
*************** InitPredicateLocks(void)
*** 1224,1237 ****
      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);

      /*
       * Allocate space for tracking rw-conflicts in lists attached to the
--- 1222,1234 ----
      MemSet(&info, 0, sizeof(info));
      info.keysize = sizeof(SERIALIZABLEXIDTAG);
      info.entrysize = sizeof(SERIALIZABLEXID);

      SerializableXidHash = ShmemInitHash("SERIALIZABLEXID hash",
                                          max_table_size,
                                          max_table_size,
                                          &info,
!                                         HASH_ELEM | HASH_BLOBS |
!                                         HASH_FIXED_SIZE);

      /*
       * Allocate space for tracking rw-conflicts in lists attached to the
*************** GetSerializableTransactionSnapshotInt(Sn
*** 1793,1803 ****
      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);

      return snapshot;
  }
--- 1790,1799 ----
      MemSet(&hash_ctl, 0, sizeof(hash_ctl));
      hash_ctl.keysize = sizeof(PREDICATELOCKTARGETTAG);
      hash_ctl.entrysize = sizeof(LOCALPREDICATELOCK);
      LocalPredicateLockHash = hash_create("Local predicate lock",
                                           max_predicate_locks_per_xact,
                                           &hash_ctl,
!                                          HASH_ELEM | HASH_BLOBS);

      return snapshot;
  }
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index 167d61c..53d9188 100644
*** a/src/backend/storage/smgr/md.c
--- b/src/backend/storage/smgr/md.c
*************** mdinit(void)
*** 229,240 ****
          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);
          pendingUnlinks = NIL;
      }
  }
--- 229,239 ----
          MemSet(&hash_ctl, 0, sizeof(hash_ctl));
          hash_ctl.keysize = sizeof(RelFileNode);
          hash_ctl.entrysize = sizeof(PendingOperationEntry);
          hash_ctl.hcxt = pendingOpsCxt;
          pendingOpsTable = hash_create("Pending Ops Table",
                                        100L,
                                        &hash_ctl,
!                                       HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
          pendingUnlinks = NIL;
      }
  }
diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c
index d16f559..87be477 100644
*** a/src/backend/storage/smgr/smgr.c
--- b/src/backend/storage/smgr/smgr.c
*************** smgropen(RelFileNode rnode, BackendId ba
*** 146,154 ****
          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);
          first_unowned_reln = NULL;
      }

--- 146,153 ----
          MemSet(&ctl, 0, sizeof(ctl));
          ctl.keysize = sizeof(RelFileNodeBackend);
          ctl.entrysize = sizeof(SMgrRelationData);
          SMgrRelationHash = hash_create("smgr relation table", 400,
!                                        &ctl, HASH_ELEM | HASH_BLOBS);
          first_unowned_reln = NULL;
      }

diff --git a/src/backend/utils/adt/array_typanalyze.c b/src/backend/utils/adt/array_typanalyze.c
index 4d7e9c3..3653888 100644
*** a/src/backend/utils/adt/array_typanalyze.c
--- b/src/backend/utils/adt/array_typanalyze.c
*************** compute_array_stats(VacAttrStats *stats,
*** 290,301 ****
      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);

      /* Initialize counters. */
      b_current = 1;
--- 290,300 ----
      MemSet(&count_hash_ctl, 0, sizeof(count_hash_ctl));
      count_hash_ctl.keysize = sizeof(int);
      count_hash_ctl.entrysize = sizeof(DECountItem);
      count_hash_ctl.hcxt = CurrentMemoryContext;
      count_tab = hash_create("Array distinct element count table",
                              64,
                              &count_hash_ctl,
!                             HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);

      /* Initialize counters. */
      b_current = 1;
diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c
index 94bb5a4..1b68743 100644
*** a/src/backend/utils/adt/pg_locale.c
--- b/src/backend/utils/adt/pg_locale.c
*************** lookup_collation_cache(Oid collation, bo
*** 875,883 ****
          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);
      }

      cache_entry = hash_search(collation_cache, &collation, HASH_ENTER, &found);
--- 875,882 ----
          memset(&ctl, 0, sizeof(ctl));
          ctl.keysize = sizeof(Oid);
          ctl.entrysize = sizeof(collation_cache_entry);
          collation_cache = hash_create("Collation cache", 100, &ctl,
!                                       HASH_ELEM | HASH_BLOBS);
      }

      cache_entry = hash_search(collation_cache, &collation, HASH_ENTER, &found);
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index 2f02303..5c75390 100644
*** a/src/backend/utils/adt/ri_triggers.c
--- b/src/backend/utils/adt/ri_triggers.c
*************** ri_InitHashTables(void)
*** 3326,3335 ****
      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);

      /* Arrange to flush cache on pg_constraint changes */
      CacheRegisterSyscacheCallback(CONSTROID,
--- 3326,3334 ----
      memset(&ctl, 0, sizeof(ctl));
      ctl.keysize = sizeof(Oid);
      ctl.entrysize = sizeof(RI_ConstraintInfo);
      ri_constraint_cache = hash_create("RI constraint cache",
                                        RI_INIT_CONSTRAINTHASHSIZE,
!                                       &ctl, HASH_ELEM | HASH_BLOBS);

      /* Arrange to flush cache on pg_constraint changes */
      CacheRegisterSyscacheCallback(CONSTROID,
*************** ri_InitHashTables(void)
*** 3339,3356 ****
      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);

      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);
  }


--- 3338,3353 ----
      memset(&ctl, 0, sizeof(ctl));
      ctl.keysize = sizeof(RI_QueryKey);
      ctl.entrysize = sizeof(RI_QueryHashEntry);
      ri_query_cache = hash_create("RI query cache",
                                   RI_INIT_QUERYHASHSIZE,
!                                  &ctl, HASH_ELEM | HASH_BLOBS);

      memset(&ctl, 0, sizeof(ctl));
      ctl.keysize = sizeof(RI_CompareKey);
      ctl.entrysize = sizeof(RI_CompareHashEntry);
      ri_compare_cache = hash_create("RI compare cache",
                                     RI_INIT_QUERYHASHSIZE,
!                                    &ctl, HASH_ELEM | HASH_BLOBS);
  }


diff --git a/src/backend/utils/cache/attoptcache.c b/src/backend/utils/cache/attoptcache.c
index 5fcf0dd..75e7ae6 100644
*** a/src/backend/utils/cache/attoptcache.c
--- b/src/backend/utils/cache/attoptcache.c
*************** InitializeAttoptCache(void)
*** 82,91 ****
      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);

      /* Make sure we've initialized CacheMemoryContext. */
      if (!CacheMemoryContext)
--- 82,90 ----
      MemSet(&ctl, 0, sizeof(ctl));
      ctl.keysize = sizeof(AttoptCacheKey);
      ctl.entrysize = sizeof(AttoptCacheEntry);
      AttoptCacheHash =
          hash_create("Attopt cache", 256, &ctl,
!                     HASH_ELEM | HASH_BLOBS);

      /* Make sure we've initialized CacheMemoryContext. */
      if (!CacheMemoryContext)
diff --git a/src/backend/utils/cache/evtcache.c b/src/backend/utils/cache/evtcache.c
index b9d442c..01051b0 100644
*** a/src/backend/utils/cache/evtcache.c
--- b/src/backend/utils/cache/evtcache.c
*************** BuildEventTriggerCache(void)
*** 123,132 ****
      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);

      /*
       * Prepare to scan pg_event_trigger in name order.
--- 123,131 ----
      MemSet(&ctl, 0, sizeof(ctl));
      ctl.keysize = sizeof(EventTriggerEvent);
      ctl.entrysize = sizeof(EventTriggerCacheEntry);
      ctl.hcxt = EventTriggerCacheContext;
      cache = hash_create("Event Trigger Cache", 32, &ctl,
!                         HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);

      /*
       * Prepare to scan pg_event_trigger in name order.
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 79244e5..c2e574d 100644
*** a/src/backend/utils/cache/relcache.c
--- b/src/backend/utils/cache/relcache.c
*************** LookupOpclassInfo(Oid operatorClassOid,
*** 1409,1417 ****
          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);

          /* Also make sure CacheMemoryContext exists */
          if (!CacheMemoryContext)
--- 1409,1416 ----
          MemSet(&ctl, 0, sizeof(ctl));
          ctl.keysize = sizeof(Oid);
          ctl.entrysize = sizeof(OpClassCacheEnt);
          OpClassCache = hash_create("Operator class cache", 64,
!                                    &ctl, HASH_ELEM | HASH_BLOBS);

          /* Also make sure CacheMemoryContext exists */
          if (!CacheMemoryContext)
*************** RelationCacheInitialize(void)
*** 3140,3148 ****
      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);

      /*
       * relation mapper needs to be initialized too
--- 3139,3146 ----
      MemSet(&ctl, 0, sizeof(ctl));
      ctl.keysize = sizeof(Oid);
      ctl.entrysize = sizeof(RelIdCacheEnt);
      RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
!                                   &ctl, HASH_ELEM | HASH_BLOBS);

      /*
       * relation mapper needs to be initialized too
diff --git a/src/backend/utils/cache/relfilenodemap.c b/src/backend/utils/cache/relfilenodemap.c
index 1e8429c..87813fa 100644
*** a/src/backend/utils/cache/relfilenodemap.c
--- b/src/backend/utils/cache/relfilenodemap.c
*************** InitializeRelfilenodeMap(void)
*** 115,121 ****
      MemSet(&ctl, 0, sizeof(ctl));
      ctl.keysize = sizeof(RelfilenodeMapKey);
      ctl.entrysize = sizeof(RelfilenodeMapEntry);
-     ctl.hash = tag_hash;
      ctl.hcxt = CacheMemoryContext;

      /*
--- 115,120 ----
*************** InitializeRelfilenodeMap(void)
*** 125,131 ****
       */
      RelfilenodeMapHash =
          hash_create("RelfilenodeMap cache", 1024, &ctl,
!                     HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);

      /* Watch for invalidation events. */
      CacheRegisterRelcacheCallback(RelfilenodeMapInvalidateCallback,
--- 124,130 ----
       */
      RelfilenodeMapHash =
          hash_create("RelfilenodeMap cache", 1024, &ctl,
!                     HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);

      /* Watch for invalidation events. */
      CacheRegisterRelcacheCallback(RelfilenodeMapInvalidateCallback,
diff --git a/src/backend/utils/cache/spccache.c b/src/backend/utils/cache/spccache.c
index 24e8679..6cbafaf 100644
*** a/src/backend/utils/cache/spccache.c
--- b/src/backend/utils/cache/spccache.c
*************** InitializeTableSpaceCache(void)
*** 81,90 ****
      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);

      /* Make sure we've initialized CacheMemoryContext. */
      if (!CacheMemoryContext)
--- 81,89 ----
      MemSet(&ctl, 0, sizeof(ctl));
      ctl.keysize = sizeof(Oid);
      ctl.entrysize = sizeof(TableSpaceCacheEntry);
      TableSpaceCacheHash =
          hash_create("TableSpace cache", 16, &ctl,
!                     HASH_ELEM | HASH_BLOBS);

      /* Make sure we've initialized CacheMemoryContext. */
      if (!CacheMemoryContext)
diff --git a/src/backend/utils/cache/ts_cache.c b/src/backend/utils/cache/ts_cache.c
index 5ff1461..46da303 100644
*** a/src/backend/utils/cache/ts_cache.c
--- b/src/backend/utils/cache/ts_cache.c
*************** lookup_ts_parser_cache(Oid prsId)
*** 120,128 ****
          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);
          /* Flush cache on pg_ts_parser changes */
          CacheRegisterSyscacheCallback(TSPARSEROID, InvalidateTSCacheCallBack,
                                        PointerGetDatum(TSParserCacheHash));
--- 120,127 ----
          MemSet(&ctl, 0, sizeof(ctl));
          ctl.keysize = sizeof(Oid);
          ctl.entrysize = sizeof(TSParserCacheEntry);
          TSParserCacheHash = hash_create("Tsearch parser cache", 4,
!                                         &ctl, HASH_ELEM | HASH_BLOBS);
          /* Flush cache on pg_ts_parser changes */
          CacheRegisterSyscacheCallback(TSPARSEROID, InvalidateTSCacheCallBack,
                                        PointerGetDatum(TSParserCacheHash));
*************** lookup_ts_dictionary_cache(Oid dictId)
*** 219,227 ****
          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);
          /* Flush cache on pg_ts_dict and pg_ts_template changes */
          CacheRegisterSyscacheCallback(TSDICTOID, InvalidateTSCacheCallBack,
                                        PointerGetDatum(TSDictionaryCacheHash));
--- 218,225 ----
          MemSet(&ctl, 0, sizeof(ctl));
          ctl.keysize = sizeof(Oid);
          ctl.entrysize = sizeof(TSDictionaryCacheEntry);
          TSDictionaryCacheHash = hash_create("Tsearch dictionary cache", 8,
!                                             &ctl, HASH_ELEM | HASH_BLOBS);
          /* Flush cache on pg_ts_dict and pg_ts_template changes */
          CacheRegisterSyscacheCallback(TSDICTOID, InvalidateTSCacheCallBack,
                                        PointerGetDatum(TSDictionaryCacheHash));
*************** init_ts_config_cache(void)
*** 368,376 ****
      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);
      /* Flush cache on pg_ts_config and pg_ts_config_map changes */
      CacheRegisterSyscacheCallback(TSCONFIGOID, InvalidateTSCacheCallBack,
                                    PointerGetDatum(TSConfigCacheHash));
--- 366,373 ----
      MemSet(&ctl, 0, sizeof(ctl));
      ctl.keysize = sizeof(Oid);
      ctl.entrysize = sizeof(TSConfigCacheEntry);
      TSConfigCacheHash = hash_create("Tsearch configuration cache", 16,
!                                     &ctl, HASH_ELEM | HASH_BLOBS);
      /* Flush cache on pg_ts_config and pg_ts_config_map changes */
      CacheRegisterSyscacheCallback(TSCONFIGOID, InvalidateTSCacheCallBack,
                                    PointerGetDatum(TSConfigCacheHash));
diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c
index 29aec3c..08e17b9 100644
*** a/src/backend/utils/cache/typcache.c
--- b/src/backend/utils/cache/typcache.c
*************** lookup_type_cache(Oid type_id, int flags
*** 166,174 ****
          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);

          /* Also set up callbacks for SI invalidations */
          CacheRegisterRelcacheCallback(TypeCacheRelCallback, (Datum) 0);
--- 166,173 ----
          MemSet(&ctl, 0, sizeof(ctl));
          ctl.keysize = sizeof(Oid);
          ctl.entrysize = sizeof(TypeCacheEntry);
          TypeCacheHash = hash_create("Type information cache", 64,
!                                     &ctl, HASH_ELEM | HASH_BLOBS);

          /* Also set up callbacks for SI invalidations */
          CacheRegisterRelcacheCallback(TypeCacheRelCallback, (Datum) 0);
*************** assign_record_type_typmod(TupleDesc tupD
*** 846,854 ****
          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);

          /* Also make sure CacheMemoryContext exists */
          if (!CacheMemoryContext)
--- 845,852 ----
          MemSet(&ctl, 0, sizeof(ctl));
          ctl.keysize = REC_HASH_KEYS * sizeof(Oid);
          ctl.entrysize = sizeof(RecordCacheEntry);
          RecordCacheHash = hash_create("Record information cache", 64,
!                                       &ctl, HASH_ELEM | HASH_BLOBS);

          /* Also make sure CacheMemoryContext exists */
          if (!CacheMemoryContext)
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index a95be05..e81c855 100644
*** a/src/backend/utils/fmgr/fmgr.c
--- b/src/backend/utils/fmgr/fmgr.c
*************** record_C_func(HeapTuple procedureTuple,
*** 540,550 ****
          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);
      }

      entry = (CFuncHashTabEntry *)
--- 540,549 ----
          MemSet(&hash_ctl, 0, sizeof(hash_ctl));
          hash_ctl.keysize = sizeof(Oid);
          hash_ctl.entrysize = sizeof(CFuncHashTabEntry);
          CFuncHash = hash_create("CFuncHash",
                                  100,
                                  &hash_ctl,
!                                 HASH_ELEM | HASH_BLOBS);
      }

      entry = (CFuncHashTabEntry *)
diff --git a/src/backend/utils/hash/dynahash.c b/src/backend/utils/hash/dynahash.c
index 2b99e4b..798cfb2 100644
*** a/src/backend/utils/hash/dynahash.c
--- b/src/backend/utils/hash/dynahash.c
*************** hash_create(const char *tabname, long ne
*** 305,312 ****
--- 305,326 ----
      hashp->tabname = (char *) (hashp + 1);
      strcpy(hashp->tabname, tabname);

+     /*
+      * Select the appropriate hash function.  Caller can specify a custom hash
+      * function, or can set the HASH_BLOBS flag to select an appropriate hash
+      * function for fixed-size binary keys; the default is to select a hash
+      * function suitable for null-terminated string keys.
+      */
      if (flags & HASH_FUNCTION)
          hashp->hash = info->hash;
+     else if (flags & HASH_BLOBS)
+     {
+         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 */

diff --git a/src/backend/utils/hash/hashfn.c b/src/backend/utils/hash/hashfn.c
index a12f98f..adb0bd9 100644
*** a/src/backend/utils/hash/hashfn.c
--- b/src/backend/utils/hash/hashfn.c
*************** tag_hash(const void *key, Size keysize)
*** 55,69 ****
  }

  /*
!  * oid_hash: hash function for keys that are OIDs
   *
   * (tag_hash works for this case too, but is slower)
   */
  uint32
! oid_hash(const void *key, Size keysize)
  {
!     Assert(keysize == sizeof(Oid));
!     return DatumGetUInt32(hash_uint32((uint32) *((const Oid *) key)));
  }

  /*
--- 55,69 ----
  }

  /*
!  * uint32_hash: hash function for keys that are uint32 or int32
   *
   * (tag_hash works for this case too, but is slower)
   */
  uint32
! uint32_hash(const void *key, Size keysize)
  {
!     Assert(keysize == sizeof(uint32));
!     return DatumGetUInt32(hash_uint32(*((const uint32 *) key)));
  }

  /*
diff --git a/src/backend/utils/time/combocid.c b/src/backend/utils/time/combocid.c
index a70c754..ea7a905 100644
*** a/src/backend/utils/time/combocid.c
--- b/src/backend/utils/time/combocid.c
*************** GetComboCommandId(CommandId cmin, Comman
*** 218,230 ****
          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);

          comboCids = (ComboCidKeyData *)
              MemoryContextAlloc(TopTransactionContext,
--- 218,229 ----
          memset(&hash_ctl, 0, sizeof(hash_ctl));
          hash_ctl.keysize = sizeof(ComboCidKeyData);
          hash_ctl.entrysize = sizeof(ComboCidEntryData);
          hash_ctl.hcxt = TopTransactionContext;

          comboHash = hash_create("Combo CIDs",
                                  CCID_HASH_SIZE,
                                  &hash_ctl,
!                                 HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);

          comboCids = (ComboCidKeyData *)
              MemoryContextAlloc(TopTransactionContext,
diff --git a/src/include/utils/hsearch.h b/src/include/utils/hsearch.h
index 77974a1..a2eb7bc 100644
*** a/src/include/utils/hsearch.h
--- b/src/include/utils/hsearch.h
*************** typedef struct HASHCTL
*** 93,98 ****
--- 93,99 ----
  #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_BLOBS        0x2000    /* Use support functions for binary keys */


  /* max_dsize value to indicate expansible directory */
*************** extern void AtEOSubXact_HashTables(bool
*** 143,153 ****

  /*
   * prototypes for functions in hashfn.c
   */
  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 bitmap_hash(const void *key, Size keysize);
  extern int    bitmap_match(const void *key1, const void *key2, Size keysize);

  #endif   /* HSEARCH_H */
--- 144,160 ----

  /*
   * 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 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 */
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 5629571..492c1ef 100644
*** a/src/pl/plperl/plperl.c
--- b/src/pl/plperl/plperl.c
*************** _PG_init(void)
*** 456,475 ****
      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);

      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);

      /*
       * Save the default opmask.
--- 456,473 ----
      memset(&hash_ctl, 0, sizeof(hash_ctl));
      hash_ctl.keysize = sizeof(Oid);
      hash_ctl.entrysize = sizeof(plperl_interp_desc);
      plperl_interp_hash = hash_create("PL/Perl interpreters",
                                       8,
                                       &hash_ctl,
!                                      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);
      plperl_proc_hash = hash_create("PL/Perl procedures",
                                     32,
                                     &hash_ctl,
!                                    HASH_ELEM | HASH_BLOBS);

      /*
       * Save the default opmask.
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index d2fd685..24dc371 100644
*** a/src/pl/plpgsql/src/pl_comp.c
--- b/src/pl/plpgsql/src/pl_comp.c
*************** plpgsql_HashTableInit(void)
*** 2519,2529 ****
      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);
  }

  static PLpgSQL_function *
--- 2519,2528 ----
      memset(&ctl, 0, sizeof(ctl));
      ctl.keysize = sizeof(PLpgSQL_func_hashkey);
      ctl.entrysize = sizeof(plpgsql_HashEnt);
      plpgsql_HashTable = hash_create("PLpgSQL function cache",
                                      FUNCS_PER_USER,
                                      &ctl,
!                                     HASH_ELEM | HASH_BLOBS);
  }

  static PLpgSQL_function *
diff --git a/src/pl/plpython/plpy_plpymodule.c b/src/pl/plpython/plpy_plpymodule.c
index 37ea2a4..b8dc891 100644
*** a/src/pl/plpython/plpy_plpymodule.c
--- b/src/pl/plpython/plpy_plpymodule.c
*************** PLy_add_exceptions(PyObject *plpy)
*** 226,234 ****
      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);

      PLy_generate_spi_exceptions(excmod, PLy_exc_spi_error);
  }
--- 226,233 ----
      memset(&hash_ctl, 0, sizeof(hash_ctl));
      hash_ctl.keysize = sizeof(int);
      hash_ctl.entrysize = sizeof(PLyExceptionEntry);
      PLy_spi_exceptions = hash_create("SPI exceptions", 256,
!                                      &hash_ctl, HASH_ELEM | HASH_BLOBS);

      PLy_generate_spi_exceptions(excmod, PLy_exc_spi_error);
  }
diff --git a/src/pl/plpython/plpy_procedure.c b/src/pl/plpython/plpy_procedure.c
index fad80b2..bd48301 100644
*** a/src/pl/plpython/plpy_procedure.c
--- b/src/pl/plpython/plpy_procedure.c
*************** init_procedure_caches(void)
*** 39,47 ****
      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);
  }

  /*
--- 39,46 ----
      memset(&hash_ctl, 0, sizeof(hash_ctl));
      hash_ctl.keysize = sizeof(PLyProcedureKey);
      hash_ctl.entrysize = sizeof(PLyProcedureEntry);
      PLy_procedure_cache = hash_create("PL/Python procedures", 32, &hash_ctl,
!                                       HASH_ELEM | HASH_BLOBS);
  }

  /*
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index a53cca4..8f98046 100644
*** a/src/pl/tcl/pltcl.c
--- b/src/pl/tcl/pltcl.c
*************** _PG_init(void)
*** 378,388 ****
      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);

      /************************************************************
       * Create the hash table for function lookup
--- 378,387 ----
      memset(&hash_ctl, 0, sizeof(hash_ctl));
      hash_ctl.keysize = sizeof(Oid);
      hash_ctl.entrysize = sizeof(pltcl_interp_desc);
      pltcl_interp_htab = hash_create("PL/Tcl interpreters",
                                      8,
                                      &hash_ctl,
!                                     HASH_ELEM | HASH_BLOBS);

      /************************************************************
       * Create the hash table for function lookup
*************** _PG_init(void)
*** 390,400 ****
      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);

      pltcl_pm_init_done = true;
  }
--- 389,398 ----
      memset(&hash_ctl, 0, sizeof(hash_ctl));
      hash_ctl.keysize = sizeof(pltcl_proc_key);
      hash_ctl.entrysize = sizeof(pltcl_proc_ptr);
      pltcl_proc_htab = hash_create("PL/Tcl functions",
                                    100,
                                    &hash_ctl,
!                                   HASH_ELEM | HASH_BLOBS);

      pltcl_pm_init_done = true;
  }

pgsql-hackers by date:

Previous
From: Etsuro Fujita
Date:
Subject: Re: inherit support for foreign tables
Next
From: Michael Paquier
Date:
Subject: Re: no test programs in contrib