{
FmgrInfo flinfo; /* lookup info for target function */
Oid userid; /* userid to set, or InvalidOid */
- ArrayType *proconfig; /* GUC values to set, or NULL */
+ List *configNames; /* GUC names to set, or NIL */
+ List *configValues; /* GUC values to set, or NIL */
Datum arg; /* passthrough argument for plugin modules */
};
FmgrInfo *save_flinfo;
Oid save_userid;
int save_sec_context;
+ ListCell *lc1;
+ ListCell *lc2;
volatile int save_nestlevel;
PgStat_FunctionCallUsage fcusage;
&isnull);
if (!isnull)
{
+ ArrayType *array;
oldcxt = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
- fcache->proconfig = DatumGetArrayTypePCopy(datum);
+ array = DatumGetArrayTypeP(datum);
+ TransformGUCArray(array, &fcache->configNames,
+ &fcache->configValues);
MemoryContextSwitchTo(oldcxt);
}
/* 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->configNames != NIL) /* Need a new GUC nesting level */
save_nestlevel = NewGUCNestLevel();
else
save_nestlevel = 0; /* keep compiler quiet */
SetUserIdAndSecContext(fcache->userid,
save_sec_context | SECURITY_LOCAL_USERID_CHANGE);
- if (fcache->proconfig)
+ forboth(lc1, fcache->configNames, lc2, fcache->configValues)
{
- 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;
+ char *name = lfirst(lc1);
+ char *value = lfirst(lc2);
+
+ (void) set_config_option(name, value,
+ context, source,
+ action, true, 0, false);
}
/* function manager hook */
fcinfo->flinfo = save_flinfo;
- if (fcache->proconfig)
+ if (fcache->configNames != NIL)
AtEOXact_GUC(true, save_nestlevel);
if (OidIsValid(fcache->userid))
SetUserIdAndSecContext(save_userid, save_sec_context);
/*
- * 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 lists of names and values. The lists
+ * are 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)
+TransformGUCArray(ArrayType *array, List **names, List **values)
{
int i;
Assert(ARR_NDIM(array) == 1);
Assert(ARR_LBOUND(array)[0] == 1);
+ *names = NIL;
+ *values = NIL;
for (i = 1; i <= ARR_DIMS(array)[0]; i++)
{
Datum d;
continue;
}
+ *names = lappend(*names, name);
+ *values = lappend(*values, value);
+
+ pfree(s);
+ }
+}
+
+
+/*
+ * 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 *gucNames;
+ List *gucValues;
+ ListCell *lc1;
+ ListCell *lc2;
+
+ TransformGUCArray(array, &gucNames, &gucValues);
+ forboth(lc1, gucNames, lc2, gucValues)
+ {
+ char *name = lfirst(lc1);
+ char *value = lfirst(lc2);
+
(void) set_config_option(name, value,
context, source,
action, true, 0, false);
pfree(name);
pfree(value);
- pfree(s);
}
+
+ list_free(gucNames);
+ list_free(gucValues);
}
extern char *GetConfigOptionByName(const char *name, const char **varname,
bool missing_ok);
+extern void TransformGUCArray(ArrayType *array, List **configNames,
+ List **configValues);
extern void ProcessGUCArray(ArrayType *array,
GucContext context, GucSource source, GucAction action);
extern ArrayType *GUCArrayAdd(ArrayType *array, const char *name, const char *value);