diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index 9a0afa4..ed15c74 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -814,11 +814,11 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, if (client_min_messages < WARNING) (void) set_config_option("client_min_messages", "warning", PGC_USERSET, PGC_S_SESSION, - GUC_ACTION_SAVE, true, 0); + GUC_ACTION_SAVE, 0); if (log_min_messages < WARNING) (void) set_config_option("log_min_messages", "warning", PGC_SUSET, PGC_S_SESSION, - GUC_ACTION_SAVE, true, 0); + GUC_ACTION_SAVE, 0); /* * Set up the search path to contain the target schema, then the schemas @@ -843,7 +843,7 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, (void) set_config_option("search_path", pathbuf.data, PGC_USERSET, PGC_S_SESSION, - GUC_ACTION_SAVE, true, 0); + GUC_ACTION_SAVE, 0); /* * Set creating_extension and related variables so that diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index e4d7b2c..364c763 100644 --- a/src/backend/utils/adt/ri_triggers.c +++ b/src/backend/utils/adt/ri_triggers.c @@ -2410,7 +2410,7 @@ RI_Initial_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel) snprintf(workmembuf, sizeof(workmembuf), "%d", maintenance_work_mem); (void) set_config_option("work_mem", workmembuf, PGC_USERSET, PGC_S_SESSION, - GUC_ACTION_SAVE, true, 0); + GUC_ACTION_SAVE, 0); if (SPI_connect() != SPI_OK_CONNECT) elog(ERROR, "SPI_connect failed"); diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l index e6e1109..f1fbf43 100644 --- a/src/backend/utils/misc/guc-file.l +++ b/src/backend/utils/misc/guc-file.l @@ -264,7 +264,7 @@ ProcessConfigFile(GucContext context) /* Now we can re-apply the wired-in default (i.e., the boot_val) */ if (set_config_option(gconf->name, NULL, context, PGC_S_DEFAULT, - GUC_ACTION_SET, true, 0) > 0) + GUC_ACTION_SET, 0) > 0) { /* Log the change if appropriate */ if (context == PGC_SIGHUP) @@ -319,7 +319,7 @@ ProcessConfigFile(GucContext context) scres = set_config_option(item->name, item->value, context, PGC_S_FILE, - GUC_ACTION_SET, true, 0); + GUC_ACTION_SET, 0); if (scres > 0) { /* variable was updated, so log the change if appropriate */ diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 6c52db8..8ff4421 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -513,6 +513,7 @@ const char *const GucContext_Names[] = /* PGC_POSTMASTER */ "postmaster", /* PGC_SIGHUP */ "sighup", /* PGC_BACKEND */ "backend", + /* PGC_BACKEND_USERSET */ "backend(userset)", /* PGC_SUSET */ "superuser", /* PGC_USERSET */ "user" }; @@ -2898,7 +2899,7 @@ static struct config_string ConfigureNamesString[] = }, { - {"local_preload_libraries", PGC_BACKEND, CLIENT_CONN_PRELOAD, + {"local_preload_libraries", PGC_BACKEND_USERSET, CLIENT_CONN_PRELOAD, gettext_noop("Lists unprivileged shared libraries to preload into each backend."), NULL, GUC_LIST_INPUT | GUC_LIST_QUOTE @@ -4552,6 +4553,8 @@ push_old_value(struct config_generic * gconf, GucAction action) { GucStack *stack; + Assert(action != GUC_ACTION_CHECK); + /* If we're not inside a nest level, do nothing */ if (GUCNestLevel == 0) return; @@ -4587,6 +4590,12 @@ push_old_value(struct config_generic * gconf, GucAction action) /* Could only have a prior SAVE of same variable */ Assert(stack->state == GUC_SAVE); break; + case GUC_ACTION_CHECK: + /* + * This is compiler warning silencer. + * This action is blocked at the beginning of this function. + */ + break; } Assert(guc_dirty); /* must be set already */ return; @@ -4613,6 +4622,12 @@ push_old_value(struct config_generic * gconf, GucAction action) case GUC_ACTION_SAVE: stack->state = GUC_SAVE; break; + case GUC_ACTION_CHECK: + /* + * This is compiler warning silencer. + * This action is blocked at the beginning of this function. + */ + break; } stack->source = gconf->source; stack->scontext = gconf->scontext; @@ -5593,11 +5608,12 @@ validate_conf_option(struct config_generic * record, const char *name, int set_config_option(const char *name, const char *value, GucContext context, GucSource source, - GucAction action, bool changeVal, int elevel) + GucAction action, int elevel) { struct config_generic *record; bool prohibitValueChange = false; bool makeDefault; + bool changeVal = (action != GUC_ACTION_CHECK); if (elevel == 0) { @@ -5681,6 +5697,30 @@ set_config_option(const char *name, const char *value, * signals to individual backends only. */ break; + case PGC_BACKEND_USERSET: + /* + * The behavior of parameter checking for PGC_BACKEND_USERSET is + * the same to PGC_USERSET. + */ + if (action == GUC_ACTION_CHECK) + break; + + /* + * Setting the value of the PGC_BACKEND_USERSET parameters should + * be set during initializing backend, having + * context=PGC_SUSET/source=PGC_S_USER. + */ + if (action != GUC_ACTION_SET || + context != PGC_SUSET || source != PGC_S_USER || + !IsInitProcessingMode()) + { + ereport(elevel, + (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), + errmsg("parameter \"%s\" should be set by ALTER USER.", + name))); + return 0; + } + break; case PGC_BACKEND: if (context == PGC_SIGHUP) { @@ -6311,7 +6351,7 @@ SetConfigOption(const char *name, const char *value, GucContext context, GucSource source) { (void) set_config_option(name, value, context, source, - GUC_ACTION_SET, true, 0); + GUC_ACTION_SET, 0); } @@ -6868,7 +6908,6 @@ ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel) (superuser() ? PGC_SUSET : PGC_USERSET), PGC_S_SESSION, action, - true, 0); break; case VAR_SET_MULTI: @@ -6957,7 +6996,6 @@ ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel) (superuser() ? PGC_SUSET : PGC_USERSET), PGC_S_SESSION, action, - true, 0); break; case VAR_RESET_ALL: @@ -7003,7 +7041,6 @@ SetPGVariable(const char *name, List *args, bool is_local) (superuser() ? PGC_SUSET : PGC_USERSET), PGC_S_SESSION, is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET, - true, 0); } @@ -7047,7 +7084,6 @@ set_config_by_name(PG_FUNCTION_ARGS) (superuser() ? PGC_SUSET : PGC_USERSET), PGC_S_SESSION, is_local ? GUC_ACTION_LOCAL : GUC_ACTION_SET, - true, 0); /* get the new current value */ @@ -7169,7 +7205,7 @@ define_custom_variable(struct config_generic * variable) (void) set_config_option(name, pHolder->reset_val, pHolder->gen.reset_scontext, pHolder->gen.reset_source, - GUC_ACTION_SET, true, WARNING); + GUC_ACTION_SET, WARNING); /* That should not have resulted in stacking anything */ Assert(variable->stack == NULL); @@ -7225,30 +7261,30 @@ reapply_stacked_values(struct config_generic * variable, case GUC_SAVE: (void) set_config_option(name, curvalue, curscontext, cursource, - GUC_ACTION_SAVE, true, WARNING); + GUC_ACTION_SAVE, WARNING); break; case GUC_SET: (void) set_config_option(name, curvalue, curscontext, cursource, - GUC_ACTION_SET, true, WARNING); + GUC_ACTION_SET, WARNING); break; case GUC_LOCAL: (void) set_config_option(name, curvalue, curscontext, cursource, - GUC_ACTION_LOCAL, true, WARNING); + GUC_ACTION_LOCAL, WARNING); break; case GUC_SET_LOCAL: /* first, apply the masked value as SET */ (void) set_config_option(name, stack->masked.val.stringval, stack->masked_scontext, PGC_S_SESSION, - GUC_ACTION_SET, true, WARNING); + GUC_ACTION_SET, WARNING); /* then apply the current value as LOCAL */ (void) set_config_option(name, curvalue, curscontext, cursource, - GUC_ACTION_LOCAL, true, WARNING); + GUC_ACTION_LOCAL, WARNING); break; } @@ -7272,7 +7308,7 @@ reapply_stacked_values(struct config_generic * variable, { (void) set_config_option(name, curvalue, curscontext, cursource, - GUC_ACTION_SET, true, WARNING); + GUC_ACTION_SET, WARNING); variable->stack = NULL; } } @@ -8396,7 +8432,7 @@ read_nondefault_variables(void) (void) set_config_option(varname, varvalue, varscontext, varsource, - GUC_ACTION_SET, true, 0); + GUC_ACTION_SET, 0); if (varsourcefile[0]) set_config_sourcefile(varname, varsourcefile, varsourceline); @@ -8499,7 +8535,7 @@ ProcessGUCArray(ArrayType *array, (void) set_config_option(name, value, context, source, - action, true, 0); + action, 0); free(name); if (value) @@ -8802,7 +8838,7 @@ validate_option_array_item(const char *name, const char *value, /* test for permissions and valid option value */ (void) set_config_option(name, value, superuser() ? PGC_SUSET : PGC_USERSET, - PGC_S_TEST, GUC_ACTION_SET, false, 0); + PGC_S_TEST, GUC_ACTION_CHECK, 0); return true; } diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index 0a729c1..8284337 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -54,6 +54,7 @@ typedef enum PGC_POSTMASTER, PGC_SIGHUP, PGC_BACKEND, + PGC_BACKEND_USERSET, PGC_SUSET, PGC_USERSET } GucContext; @@ -165,7 +166,8 @@ typedef enum /* Types of set_config_option actions */ GUC_ACTION_SET, /* regular SET command */ GUC_ACTION_LOCAL, /* SET LOCAL command */ - GUC_ACTION_SAVE /* function SET option, or temp assignment */ + GUC_ACTION_SAVE, /* function SET option, or temp assignment */ + GUC_ACTION_CHECK /* make no change, check only */ } GucAction; #define GUC_QUALIFIER_SEPARATOR '.' @@ -327,7 +329,7 @@ extern bool parse_int(const char *value, int *result, int flags, extern bool parse_real(const char *value, double *result); extern int set_config_option(const char *name, const char *value, GucContext context, GucSource source, - GucAction action, bool changeVal, int elevel); + GucAction action, int elevel); extern void AlterSystemSetConfigFile(AlterSystemStmt *setstmt); extern char *GetConfigOptionByName(const char *name, const char **varname); extern void GetConfigOptionByNum(int varnum, const char **values, bool *noshow);