aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Davis <jdavis@postgresql.org>2023-11-20 15:53:42 -0800
committerJeff Davis <jdavis@postgresql.org>2023-11-20 15:53:42 -0800
commitad57c2a7c58665c14236a999435d37ba59eb7fc4 (patch)
treef2f58d066b85d427d4120a40259d46230b3b140e
parent8efa301532c8c93938e04451a74754c91b0b760d (diff)
downloadpostgresql-ad57c2a7c58665c14236a999435d37ba59eb7fc4.tar.gz
postgresql-ad57c2a7c58665c14236a999435d37ba59eb7fc4.zip
Optimize check_search_path() by using SearchPathCache.
A hash lookup is faster than re-validating the string, particularly because we use SplitIdentifierString() for validation. Important when search_path changes frequently. Discussion: https://postgr.es/m/04c8592dbd694e4114a3ed87139a7a04e4363030.camel%40j-davis.com
-rw-r--r--src/backend/catalog/namespace.c56
1 files changed, 54 insertions, 2 deletions
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index d74f6181a9c..5027efc91d6 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -235,6 +235,10 @@ static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
* when a function has search_path set in proconfig. Add a search path cache
* that can be used by recomputeNamespacePath().
*
+ * The cache is also used to remember already-validated strings in
+ * check_search_path() to avoid the need to call SplitIdentifierString()
+ * repeatedly.
+ *
* The search path cache is based on a wrapper around a simplehash hash table
* (nsphash, defined below). The spcache wrapper deals with OOM while trying
* to initialize a key, and also offers a more convenient API.
@@ -297,6 +301,21 @@ spcache_init(void)
}
/*
+ * Look up entry in search path cache without inserting. Returns NULL if not
+ * present.
+ */
+static SearchPathCacheEntry *
+spcache_lookup(const char *searchPath, Oid roleid)
+{
+ SearchPathCacheKey cachekey = {
+ .searchPath = searchPath,
+ .roleid = roleid
+ };
+
+ return nsphash_lookup(SearchPathCache, cachekey);
+}
+
+/*
* Look up or insert entry in search path cache.
*
* Initialize key safely, so that OOM does not leave an entry without a valid
@@ -4578,11 +4597,40 @@ ResetTempTableNamespace(void)
bool
check_search_path(char **newval, void **extra, GucSource source)
{
+ Oid roleid = InvalidOid;
+ const char *searchPath = *newval;
char *rawname;
List *namelist;
+ bool use_cache = (SearchPathCacheContext != NULL);
- /* Need a modifiable copy of string */
- rawname = pstrdup(*newval);
+ /*
+ * We used to try to check that the named schemas exist, but there are
+ * many valid use-cases for having search_path settings that include
+ * schemas that don't exist; and often, we are not inside a transaction
+ * here and so can't consult the system catalogs anyway. So now, the only
+ * requirement is syntactic validity of the identifier list.
+ */
+
+ /*
+ * Checking only the syntactic validity also allows us to use the search
+ * path cache (if available) to avoid calling SplitIdentifierString() on
+ * the same string repeatedly.
+ */
+ if (use_cache)
+ {
+ spcache_init();
+
+ roleid = GetUserId();
+
+ if (spcache_lookup(searchPath, roleid) != NULL)
+ return true;
+ }
+
+ /*
+ * Ensure validity check succeeds before creating cache entry.
+ */
+
+ rawname = pstrdup(searchPath); /* need a modifiable copy */
/* Parse string into list of identifiers */
if (!SplitIdentifierString(rawname, ',', &namelist))
@@ -4605,6 +4653,10 @@ check_search_path(char **newval, void **extra, GucSource source)
pfree(rawname);
list_free(namelist);
+ /* create empty cache entry */
+ if (use_cache)
+ (void) spcache_insert(searchPath, roleid);
+
return true;
}