v4-0002-Optimize-check_search_path.patch
text/x-patch
Filename: v4-0002-Optimize-check_search_path.patch
Type: text/x-patch
Part: 1
Message:
Re: Faster "SET search_path"
Patch
Format: format-patch
Series: patch v4-0002
Subject: Optimize check_search_path().
| File | + | − |
|---|---|---|
| src/backend/catalog/namespace.c | 2 | 11 |
| src/backend/utils/adt/varlena.c | 70 | 0 |
| src/include/utils/varlena.h | 1 | 0 |
From 313136c308641d2dc47a19330cd134451224918e Mon Sep 17 00:00:00 2001
From: Jeff Davis <jeff@j-davis.com>
Date: Thu, 27 Jul 2023 15:23:51 -0700
Subject: [PATCH v4 2/4] Optimize check_search_path().
Introduce CheckIdentifierString(), which validates a string list of
identifiers without the work of actually storing them in a list.
This speeds up frequent search_path changes, such as when a function
has search_path set in proconfig. Based on profiling.
---
src/backend/catalog/namespace.c | 13 +-----
src/backend/utils/adt/varlena.c | 70 +++++++++++++++++++++++++++++++++
src/include/utils/varlena.h | 1 +
3 files changed, 73 insertions(+), 11 deletions(-)
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 1f76b5d7f7..f457f778cb 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -4101,19 +4101,13 @@ ResetTempTableNamespace(void)
bool
check_search_path(char **newval, void **extra, GucSource source)
{
- char *rawname;
- List *namelist;
-
- /* Need a modifiable copy of string */
- rawname = pstrdup(*newval);
+ char *rawname = *newval;
/* Parse string into list of identifiers */
- if (!SplitIdentifierString(rawname, ',', &namelist))
+ if (!CheckIdentifierString(rawname, ','))
{
/* syntax error in name list */
GUC_check_errdetail("List syntax is invalid.");
- pfree(rawname);
- list_free(namelist);
return false;
}
@@ -4125,9 +4119,6 @@ check_search_path(char **newval, void **extra, GucSource source)
* requirement is syntactic validity of the identifier list.
*/
- pfree(rawname);
- list_free(namelist);
-
return true;
}
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index b1ec5c32ce..c8d36fd868 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -3427,6 +3427,76 @@ textToQualifiedNameList(text *textval)
return result;
}
+/*
+ * Check that an identifier list is syntactically valid; that is, that there
+ * are no mismatched quotes and that identifiers are separated with the given
+ * separator. Empty identifiers are considered acceptable if (and only if)
+ * quoted.
+ *
+ * Note that an empty string is considered okay here, though not in
+ * textToQualifiedNameList.
+ */
+bool
+CheckIdentifierString(const char *rawstring, char separator)
+{
+ const char *nextp = rawstring;
+ bool done = false;
+
+ while (scanner_isspace(*nextp))
+ nextp++; /* skip leading whitespace */
+
+ if (*nextp == '\0')
+ return true; /* allow empty string */
+
+ /* At the top of the loop, we are at start of a new identifier. */
+ do
+ {
+ if (*nextp == '"')
+ {
+ for (;;)
+ {
+ nextp = strchr(nextp + 1, '"');
+ if (nextp == NULL)
+ return false; /* mismatched quotes */
+ if (nextp[1] != '"')
+ break; /* found end of quoted name */
+ nextp++;
+ }
+
+ nextp++;
+ }
+ else
+ {
+ /* Unquoted name --- extends to separator or whitespace */
+ const char *curname = nextp;
+ while (*nextp && *nextp != separator &&
+ !scanner_isspace(*nextp))
+ nextp++;
+ if (curname == nextp)
+ return false; /* empty unquoted name not allowed */
+ }
+
+ while (scanner_isspace(*nextp))
+ nextp++; /* skip trailing whitespace */
+
+ if (*nextp == separator)
+ {
+ nextp++;
+ while (scanner_isspace(*nextp))
+ nextp++; /* skip leading whitespace for next */
+ /* we expect another name, so done remains false */
+ }
+ else if (*nextp == '\0')
+ done = true;
+ else
+ return false; /* invalid syntax */
+
+ /* Loop back if we didn't reach end of string */
+ } while (!done);
+
+ return true;
+}
+
/*
* SplitIdentifierString --- parse a string containing identifiers
*
diff --git a/src/include/utils/varlena.h b/src/include/utils/varlena.h
index 77f5b24735..4ff0cecc91 100644
--- a/src/include/utils/varlena.h
+++ b/src/include/utils/varlena.h
@@ -27,6 +27,7 @@ extern int varstr_levenshtein_less_equal(const char *source, int slen,
int ins_c, int del_c, int sub_c,
int max_d, bool trusted);
extern List *textToQualifiedNameList(text *textval);
+extern bool CheckIdentifierString(const char *rawstring, char separator);
extern bool SplitIdentifierString(char *rawstring, char separator,
List **namelist);
extern bool SplitDirectoriesString(char *rawstring, char separator,
--
2.34.1