v2-0001-Transform-proconfig-for-faster-execution.patch
text/x-patch
Filename: v2-0001-Transform-proconfig-for-faster-execution.patch
Type: text/x-patch
Part: 0
Message:
Re: Faster "SET search_path"
Patch
Format: format-patch
Series: patch v2-0001
Subject: Transform proconfig for faster execution.
| File | + | − |
|---|---|---|
| src/backend/utils/fmgr/fmgr.c | 18 | 9 |
| src/backend/utils/misc/guc.c | 40 | 9 |
| src/include/utils/guc.h | 1 | 0 |
From f0b826ffec2b21ea9eb595771ebc83d271f1e3a1 Mon Sep 17 00:00:00 2001
From: Jeff Davis <jeff@j-davis.com>
Date: Thu, 27 Jul 2023 15:11:42 -0700
Subject: [PATCH v2 1/3] Transform proconfig for faster execution.
Store function config settings as a list of (name, value) pairs to
avoid the need to parse for each function invocation.
---
src/backend/utils/fmgr/fmgr.c | 27 ++++++++++++-------
src/backend/utils/misc/guc.c | 49 ++++++++++++++++++++++++++++-------
src/include/utils/guc.h | 1 +
3 files changed, 59 insertions(+), 18 deletions(-)
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 9208c31fe0..3b49684991 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -612,7 +612,7 @@ struct fmgr_security_definer_cache
{
FmgrInfo flinfo; /* lookup info for target function */
Oid userid; /* userid to set, or InvalidOid */
- ArrayType *proconfig; /* GUC values to set, or NULL */
+ List *configList; /* GUC values to set, or NULL */
Datum arg; /* passthrough argument for plugin modules */
};
@@ -634,6 +634,7 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
FmgrInfo *save_flinfo;
Oid save_userid;
int save_sec_context;
+ ListCell *lc;
volatile int save_nestlevel;
PgStat_FunctionCallUsage fcusage;
@@ -666,8 +667,10 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
&isnull);
if (!isnull)
{
+ ArrayType *array;
oldcxt = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
- fcache->proconfig = DatumGetArrayTypePCopy(datum);
+ array = DatumGetArrayTypeP(datum);
+ fcache->configList = TransformGUCArray(array);
MemoryContextSwitchTo(oldcxt);
}
@@ -680,7 +683,7 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
/* GetUserIdAndSecContext is cheap enough that no harm in a wasted call */
GetUserIdAndSecContext(&save_userid, &save_sec_context);
- if (fcache->proconfig) /* Need a new GUC nesting level */
+ if (fcache->configList != NIL) /* Need a new GUC nesting level */
save_nestlevel = NewGUCNestLevel();
else
save_nestlevel = 0; /* keep compiler quiet */
@@ -689,12 +692,18 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
SetUserIdAndSecContext(fcache->userid,
save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
- if (fcache->proconfig)
+ foreach(lc, fcache->configList)
{
- ProcessGUCArray(fcache->proconfig,
- (superuser() ? PGC_SUSET : PGC_USERSET),
- PGC_S_SESSION,
- GUC_ACTION_SAVE);
+ GucContext context = superuser() ? PGC_SUSET : PGC_USERSET;
+ GucSource source = PGC_S_SESSION;
+ GucAction action = GUC_ACTION_SAVE;
+ List *pair = lfirst(lc);
+ char *name = linitial(pair);
+ char *value = lsecond(pair);
+
+ (void) set_config_option(name, value,
+ context, source,
+ action, true, 0, false);
}
/* function manager hook */
@@ -737,7 +746,7 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
fcinfo->flinfo = save_flinfo;
- if (fcache->proconfig)
+ if (fcache->configList != NIL)
AtEOXact_GUC(true, save_nestlevel);
if (OidIsValid(fcache->userid))
SetUserIdAndSecContext(save_userid, save_sec_context);
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 5308896c87..ea089de3ec 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -6213,17 +6213,15 @@ ParseLongOption(const char *string, char **name, char **value)
*cp = '_';
}
-
/*
- * Handle options fetched from pg_db_role_setting.setconfig,
- * pg_proc.proconfig, etc. Caller must specify proper context/source/action.
- *
- * The array parameter must be an array of TEXT (it must not be NULL).
+ * Transform array of GUC settings into a list of (name, value) pairs. The
+ * list is faster to process in cases where the settings must be applied
+ * repeatedly (e.g. for each function invocation).
*/
-void
-ProcessGUCArray(ArrayType *array,
- GucContext context, GucSource source, GucAction action)
+List *
+TransformGUCArray(ArrayType *array)
{
+ List *result = NIL;
int i;
Assert(array != NULL);
@@ -6238,6 +6236,7 @@ ProcessGUCArray(ArrayType *array,
char *s;
char *name;
char *value;
+ List *pair;
d = array_ref(array, 1, &i,
-1 /* varlenarray */ ,
@@ -6262,14 +6261,46 @@ ProcessGUCArray(ArrayType *array,
continue;
}
+ pair = list_make2(pstrdup(name), pstrdup(value));
+ result = lappend(result, pair);
+
+ pfree(name);
+ pfree(value);
+ pfree(s);
+ }
+
+ return result;
+}
+
+/*
+ * Handle options fetched from pg_db_role_setting.setconfig,
+ * pg_proc.proconfig, etc. Caller must specify proper context/source/action.
+ *
+ * The array parameter must be an array of TEXT (it must not be NULL).
+ */
+void
+ProcessGUCArray(ArrayType *array,
+ GucContext context, GucSource source, GucAction action)
+{
+ List *gucList = TransformGUCArray(array);
+ ListCell *lc;
+
+ foreach(lc, gucList)
+ {
+ List *pair = lfirst(lc);
+ char *name = linitial(pair);
+ char *value = lsecond(pair);
+
(void) set_config_option(name, value,
context, source,
action, true, 0, false);
pfree(name);
pfree(value);
- pfree(s);
+ list_free(pair);
}
+
+ list_free(gucList);
}
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 223a19f80d..713a121312 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -391,6 +391,7 @@ extern void AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt);
extern char *GetConfigOptionByName(const char *name, const char **varname,
bool missing_ok);
+extern List *TransformGUCArray(ArrayType *array);
extern void ProcessGUCArray(ArrayType *array,
GucContext context, GucSource source, GucAction action);
extern ArrayType *GUCArrayAdd(ArrayType *array, const char *name, const char *value);
--
2.34.1