@@ -156,14 +156,19 @@ static Oid namespaceUser = InvalidOid;
156156
157157/* The above four values are valid only if baseSearchPathValid */
158158static bool baseSearchPathValid = true;
159+
160+ /*
161+ * Storage for search path cache. Clear searchPathCacheValid as a simple
162+ * way to invalidate *all* the cache entries, not just the active one.
163+ */
159164static bool searchPathCacheValid = false;
160165static MemoryContext SearchPathCacheContext = NULL ;
161166
162167typedef struct SearchPathCacheKey
163168{
164169 const char * searchPath ;
165170 Oid roleid ;
166- } SearchPathCacheKey ;
171+ } SearchPathCacheKey ;
167172
168173typedef struct SearchPathCacheEntry
169174{
@@ -176,7 +181,7 @@ typedef struct SearchPathCacheEntry
176181
177182 /* needed for simplehash */
178183 char status ;
179- } SearchPathCacheEntry ;
184+ } SearchPathCacheEntry ;
180185
181186/*
182187 * myTempNamespace is InvalidOid until and unless a TEMP namespace is set up
@@ -281,8 +286,8 @@ spcachekey_equal(SearchPathCacheKey a, SearchPathCacheKey b)
281286 */
282287#define SPCACHE_RESET_THRESHOLD 256
283288
284- static nsphash_hash * SearchPathCache = NULL ;
285- static SearchPathCacheEntry * LastSearchPathCacheEntry = NULL ;
289+ static nsphash_hash * SearchPathCache = NULL ;
290+ static SearchPathCacheEntry * LastSearchPathCacheEntry = NULL ;
286291
287292/*
288293 * Create or reset search_path cache as necessary.
@@ -296,8 +301,11 @@ spcache_init(void)
296301 SearchPathCache -> members < SPCACHE_RESET_THRESHOLD )
297302 return ;
298303
299- MemoryContextReset (SearchPathCacheContext );
304+ /* make sure we don't leave dangling pointers if nsphash_create fails */
305+ SearchPathCache = NULL ;
300306 LastSearchPathCacheEntry = NULL ;
307+
308+ MemoryContextReset (SearchPathCacheContext );
301309 /* arbitrary initial starting size of 16 elements */
302310 SearchPathCache = nsphash_create (SearchPathCacheContext , 16 , NULL );
303311 searchPathCacheValid = true;
@@ -325,8 +333,8 @@ spcache_lookup(const char *searchPath, Oid roleid)
325333 };
326334
327335 entry = nsphash_lookup (SearchPathCache , cachekey );
328-
329- LastSearchPathCacheEntry = entry ;
336+ if ( entry )
337+ LastSearchPathCacheEntry = entry ;
330338 return entry ;
331339 }
332340}
@@ -4267,7 +4275,7 @@ recomputeNamespacePath(void)
42674275{
42684276 Oid roleid = GetUserId ();
42694277 bool pathChanged ;
4270- const SearchPathCacheEntry * entry ;
4278+ const SearchPathCacheEntry * entry ;
42714279
42724280 /* Do nothing if path is already valid. */
42734281 if (baseSearchPathValid && namespaceUser == roleid )
@@ -4635,9 +4643,7 @@ check_search_path(char **newval, void **extra, GucSource source)
46354643 * schemas that don't exist; and often, we are not inside a transaction
46364644 * here and so can't consult the system catalogs anyway. So now, the only
46374645 * requirement is syntactic validity of the identifier list.
4638- */
4639-
4640- /*
4646+ *
46414647 * Checking only the syntactic validity also allows us to use the search
46424648 * path cache (if available) to avoid calling SplitIdentifierString() on
46434649 * the same string repeatedly.
@@ -4667,19 +4673,10 @@ check_search_path(char **newval, void **extra, GucSource source)
46674673 list_free (namelist );
46684674 return false;
46694675 }
4670-
4671- /*
4672- * We used to try to check that the named schemas exist, but there are
4673- * many valid use-cases for having search_path settings that include
4674- * schemas that don't exist; and often, we are not inside a transaction
4675- * here and so can't consult the system catalogs anyway. So now, the only
4676- * requirement is syntactic validity of the identifier list.
4677- */
4678-
46794676 pfree (rawname );
46804677 list_free (namelist );
46814678
4682- /* create empty cache entry */
4679+ /* OK to create empty cache entry */
46834680 if (use_cache )
46844681 (void ) spcache_insert (searchPath , roleid );
46854682
@@ -4732,8 +4729,9 @@ InitializeSearchPath(void)
47324729 }
47334730 else
47344731 {
4735- SearchPathCacheContext = AllocSetContextCreate (
4736- TopMemoryContext , "search_path processing cache" ,
4732+ /* Make the context we'll keep search path cache hashtable in */
4733+ SearchPathCacheContext = AllocSetContextCreate (TopMemoryContext ,
4734+ "search_path processing cache" ,
47374735 ALLOCSET_DEFAULT_SIZES );
47384736
47394737 /*
0 commit comments