From d4bf3c9c94305e692349fb6fe0c67e483b72ae87 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 7 Mar 2012 14:51:13 -0500 Subject: [PATCH] Expose an API for calculating catcache hash values. Now that cache invalidation callbacks get only a hash value, and not a tuple TID (per commits 632ae6829f7abda34e15082c91d9dfb3fc0f298b and b5282aa893e565b7844f8237462cb843438cdd5e), the only way they can restrict what they invalidate is to know what the hash values mean. setrefs.c was doing this via a hard-wired assumption but that seems pretty grotty, and it'll only get worse as more cases come up. So let's expose a calculation function that takes the same parameters as SearchSysCache. Per complaint from Marko Kreen. --- src/backend/optimizer/plan/setrefs.c | 10 +++---- src/backend/utils/cache/catcache.c | 40 ++++++++++++++++++++++++++++ src/backend/utils/cache/syscache.c | 24 +++++++++++++++++ src/include/utils/catcache.h | 4 +++ src/include/utils/syscache.h | 12 +++++++++ 5 files changed, 83 insertions(+), 7 deletions(-) diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 66d21b2b2c..e1b48fb4f5 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 acd0518748..ea3daa599c 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 78ce0b881a..c365ec7597 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 bc19ef0255..d91700a07e 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 0b539dba75..d59dd4e0c7 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) \ -- 2.40.0