diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 66d21b2b2c3defcabf969d0912a7611a11055b54..e1b48fb4f53061f5b06653c67275dc0b323bffd0 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -15,7 +15,6 @@
  */
 #include "postgres.h"
 
-#include "access/hash.h"
 #include "access/transam.h"
 #include "catalog/pg_type.h"
 #include "nodes/makefuncs.h"
@@ -1830,14 +1829,11 @@ record_plan_function_dependency(PlannerInfo *root, Oid funcid)
 		/*
 		 * It would work to use any syscache on pg_proc, but the easiest is
 		 * PROCOID since we already have the function's OID at hand.  Note
-		 * that plancache.c knows we use PROCOID.  Also, we're perhaps
-		 * assuming more than we should about how CatalogCacheComputeHashValue
-		 * computes hash values...
+		 * that plancache.c knows we use PROCOID.
 		 */
 		inval_item->cacheId = PROCOID;
-		inval_item->hashValue =
-			DatumGetUInt32(DirectFunctionCall1(hashoid,
-											   ObjectIdGetDatum(funcid)));
+		inval_item->hashValue = GetSysCacheHashValue1(PROCOID,
+													  ObjectIdGetDatum(funcid));
 
 		root->glob->invalItems = lappend(root->glob->invalItems, inval_item);
 	}
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index acd0518748d68d13c276e57f371a642d36885d21..ea3daa599ca000ca4cbe491a59ffb377ebdc56cb 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -1281,6 +1281,46 @@ ReleaseCatCache(HeapTuple tuple)
 }
 
 
+/*
+ *	GetCatCacheHashValue
+ *
+ *		Compute the hash value for a given set of search keys.
+ *
+ * The reason for exposing this as part of the API is that the hash value is
+ * exposed in cache invalidation operations, so there are places outside the
+ * catcache code that need to be able to compute the hash values.
+ */
+uint32
+GetCatCacheHashValue(CatCache *cache,
+					 Datum v1,
+					 Datum v2,
+					 Datum v3,
+					 Datum v4)
+{
+	ScanKeyData cur_skey[CATCACHE_MAXKEYS];
+
+	/*
+	 * one-time startup overhead for each cache
+	 */
+	if (cache->cc_tupdesc == NULL)
+		CatalogCacheInitializeCache(cache);
+
+	/*
+	 * initialize the search key information
+	 */
+	memcpy(cur_skey, cache->cc_skey, sizeof(cur_skey));
+	cur_skey[0].sk_argument = v1;
+	cur_skey[1].sk_argument = v2;
+	cur_skey[2].sk_argument = v3;
+	cur_skey[3].sk_argument = v4;
+
+	/*
+	 * calculate the hash value
+	 */
+	return CatalogCacheComputeHashValue(cache, cache->cc_nkeys, cur_skey);
+}
+
+
 /*
  *	SearchCatCacheList
  *
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 78ce0b881a59c411d5e51f99fed84612e4c08f44..c365ec7597a8fb8e92c4df7e7da571f119d4f98e 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -1050,6 +1050,30 @@ SysCacheGetAttr(int cacheId, HeapTuple tup,
 						isNull);
 }
 
+/*
+ * GetSysCacheHashValue
+ *
+ * Get the hash value that would be used for a tuple in the specified cache
+ * with the given search keys.
+ *
+ * The reason for exposing this as part of the API is that the hash value is
+ * exposed in cache invalidation operations, so there are places outside the
+ * catcache code that need to be able to compute the hash values.
+ */
+uint32
+GetSysCacheHashValue(int cacheId,
+					 Datum key1,
+					 Datum key2,
+					 Datum key3,
+					 Datum key4)
+{
+	if (cacheId < 0 || cacheId >= SysCacheSize ||
+		!PointerIsValid(SysCache[cacheId]))
+		elog(ERROR, "invalid cache ID: %d", cacheId);
+
+	return GetCatCacheHashValue(SysCache[cacheId], key1, key2, key3, key4);
+}
+
 /*
  * List-search interface
  */
diff --git a/src/include/utils/catcache.h b/src/include/utils/catcache.h
index bc19ef0255f740d24dfbb42c48c2527f5863a6b0..d91700a07e373b25836d7baef9f6fe3d585d5f4d 100644
--- a/src/include/utils/catcache.h
+++ b/src/include/utils/catcache.h
@@ -174,6 +174,10 @@ extern HeapTuple SearchCatCache(CatCache *cache,
 			   Datum v3, Datum v4);
 extern void ReleaseCatCache(HeapTuple tuple);
 
+extern uint32 GetCatCacheHashValue(CatCache *cache,
+					 Datum v1, Datum v2,
+					 Datum v3, Datum v4);
+
 extern CatCList *SearchCatCacheList(CatCache *cache, int nkeys,
 				   Datum v1, Datum v2,
 				   Datum v3, Datum v4);
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index 0b539dba750174e1f32ce49b3cbd969ac7df3655..d59dd4e0c7038fa2796f4d30855548b31a7daad7 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -113,6 +113,9 @@ extern bool SearchSysCacheExistsAttName(Oid relid, const char *attname);
 extern Datum SysCacheGetAttr(int cacheId, HeapTuple tup,
 				AttrNumber attributeNumber, bool *isNull);
 
+extern uint32 GetSysCacheHashValue(int cacheId,
+					 Datum key1, Datum key2, Datum key3, Datum key4);
+
 /* list-search interface.  Users of this must import catcache.h too */
 extern struct catclist *SearchSysCacheList(int cacheId, int nkeys,
 				   Datum key1, Datum key2, Datum key3, Datum key4);
@@ -158,6 +161,15 @@ extern struct catclist *SearchSysCacheList(int cacheId, int nkeys,
 #define GetSysCacheOid4(cacheId, key1, key2, key3, key4) \
 	GetSysCacheOid(cacheId, key1, key2, key3, key4)
 
+#define GetSysCacheHashValue1(cacheId, key1) \
+	GetSysCacheHashValue(cacheId, key1, 0, 0, 0)
+#define GetSysCacheHashValue2(cacheId, key1, key2) \
+	GetSysCacheHashValue(cacheId, key1, key2, 0, 0)
+#define GetSysCacheHashValue3(cacheId, key1, key2, key3) \
+	GetSysCacheHashValue(cacheId, key1, key2, key3, 0)
+#define GetSysCacheHashValue4(cacheId, key1, key2, key3, key4) \
+	GetSysCacheHashValue(cacheId, key1, key2, key3, key4)
+
 #define SearchSysCacheList1(cacheId, key1) \
 	SearchSysCacheList(cacheId, 1, key1, 0, 0, 0)
 #define SearchSysCacheList2(cacheId, key1, key2) \