@@ -235,6 +235,10 @@ static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
235235 * when a function has search_path set in proconfig. Add a search path cache
236236 * that can be used by recomputeNamespacePath().
237237 *
238+ * The cache is also used to remember already-validated strings in
239+ * check_search_path() to avoid the need to call SplitIdentifierString()
240+ * repeatedly.
241+ *
238242 * The search path cache is based on a wrapper around a simplehash hash table
239243 * (nsphash, defined below). The spcache wrapper deals with OOM while trying
240244 * to initialize a key, and also offers a more convenient API.
@@ -296,6 +300,21 @@ spcache_init(void)
296300 searchPathCacheValid = true;
297301}
298302
303+ /*
304+ * Look up entry in search path cache without inserting. Returns NULL if not
305+ * present.
306+ */
307+ static SearchPathCacheEntry *
308+ spcache_lookup (const char * searchPath , Oid roleid )
309+ {
310+ SearchPathCacheKey cachekey = {
311+ .searchPath = searchPath ,
312+ .roleid = roleid
313+ };
314+
315+ return nsphash_lookup (SearchPathCache , cachekey );
316+ }
317+
299318/*
300319 * Look up or insert entry in search path cache.
301320 *
@@ -4578,11 +4597,40 @@ ResetTempTableNamespace(void)
45784597bool
45794598check_search_path (char * * newval , void * * extra , GucSource source )
45804599{
4600+ Oid roleid = InvalidOid ;
4601+ const char * searchPath = * newval ;
45814602 char * rawname ;
45824603 List * namelist ;
4604+ bool use_cache = (SearchPathCacheContext != NULL );
45834605
4584- /* Need a modifiable copy of string */
4585- rawname = pstrdup (* newval );
4606+ /*
4607+ * We used to try to check that the named schemas exist, but there are
4608+ * many valid use-cases for having search_path settings that include
4609+ * schemas that don't exist; and often, we are not inside a transaction
4610+ * here and so can't consult the system catalogs anyway. So now, the only
4611+ * requirement is syntactic validity of the identifier list.
4612+ */
4613+
4614+ /*
4615+ * Checking only the syntactic validity also allows us to use the search
4616+ * path cache (if available) to avoid calling SplitIdentifierString() on
4617+ * the same string repeatedly.
4618+ */
4619+ if (use_cache )
4620+ {
4621+ spcache_init ();
4622+
4623+ roleid = GetUserId ();
4624+
4625+ if (spcache_lookup (searchPath , roleid ) != NULL )
4626+ return true;
4627+ }
4628+
4629+ /*
4630+ * Ensure validity check succeeds before creating cache entry.
4631+ */
4632+
4633+ rawname = pstrdup (searchPath ); /* need a modifiable copy */
45864634
45874635 /* Parse string into list of identifiers */
45884636 if (!SplitIdentifierString (rawname , ',' , & namelist ))
@@ -4605,6 +4653,10 @@ check_search_path(char **newval, void **extra, GucSource source)
46054653 pfree (rawname );
46064654 list_free (namelist );
46074655
4656+ /* create empty cache entry */
4657+ if (use_cache )
4658+ (void ) spcache_insert (searchPath , roleid );
4659+
46084660 return true;
46094661}
46104662
0 commit comments