diff --git a/doc/src/sgml/auth-delay.sgml b/doc/src/sgml/auth-delay.sgml index e377c980cab919a407294356f27ede0255e63897..91549ffe4f61e019645866fcd98a6f2fb2f52998 100644 --- a/doc/src/sgml/auth-delay.sgml +++ b/doc/src/sgml/auth-delay.sgml @@ -42,16 +42,14 @@ </variablelist> <para> - In order to set these parameters in your <filename>postgresql.conf</> file, - you will need to add <literal>auth_delay</> to - <xref linkend="guc-custom-variable-classes">. Typical usage might be: + These parameters must be set in <filename>postgresql.conf</>. + Typical usage might be: </para> <programlisting> # postgresql.conf shared_preload_libraries = 'auth_delay' -custom_variable_classes = 'auth_delay' auth_delay.milliseconds = '500' </programlisting> </sect2> diff --git a/doc/src/sgml/auto-explain.sgml b/doc/src/sgml/auto-explain.sgml index b16f9064ffc05d86637c054bc7b38221988b11db..6a8da566fbb200da0ab30f1cee5caee113645907 100644 --- a/doc/src/sgml/auto-explain.sgml +++ b/doc/src/sgml/auto-explain.sgml @@ -158,16 +158,14 @@ LOAD 'auto_explain'; </variablelist> <para> - In order to set these parameters in your <filename>postgresql.conf</> file, - you will need to add <literal>auto_explain</> to - <xref linkend="guc-custom-variable-classes">. Typical usage might be: + These parameters must be set in <filename>postgresql.conf</>. + Typical usage might be: </para> <programlisting> # postgresql.conf shared_preload_libraries = 'auto_explain' -custom_variable_classes = 'auto_explain' auto_explain.log_min_duration = '3s' </programlisting> </sect2> diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 3282ab4f20303a986b6057c59a4bb979e20d497a..fbcd455694bfee1a17b8ebcc6d2ac504a09d0833 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -5940,58 +5940,25 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' <para> This feature was designed to allow parameters not normally known to <productname>PostgreSQL</productname> to be added by add-on modules - (such as procedural languages). This allows add-on modules to be + (such as procedural languages). This allows extension modules to be configured in the standard ways. </para> - <variablelist> - - <varlistentry id="guc-custom-variable-classes" xreflabel="custom_variable_classes"> - <term><varname>custom_variable_classes</varname> (<type>string</type>)</term> - <indexterm> - <primary><varname>custom_variable_classes</> configuration parameter</primary> - </indexterm> - <listitem> - <para> - This variable specifies one or several class names to be used for - custom variables, in the form of a comma-separated list. A custom - variable is a variable not normally known - to <productname>PostgreSQL</productname> proper but used by some - add-on module. Such variables must have names consisting of a class - name, a dot, and a variable name. <varname>custom_variable_classes</> - specifies all the class names in use in a particular installation. - This parameter can only be set in the <filename>postgresql.conf</> - file or on the server command line. - </para> - - </listitem> - </varlistentry> - </variablelist> - <para> - The difficulty with setting custom variables in - <filename>postgresql.conf</> is that the file must be read before add-on - modules have been loaded, and so custom variables would ordinarily be - rejected as unknown. When <varname>custom_variable_classes</> is set, - the server will accept definitions of arbitrary variables within each - specified class. These variables will be treated as placeholders and - will have no function until the module that defines them is loaded. When a - module for a specific class is loaded, it will add the proper variable - definitions for its class name, convert any placeholder - values according to those definitions, and issue warnings for any - unrecognized placeholders of its class that remain. + Custom options have two-part names: an extension name, then a dot, then + the parameter name proper, much like qualified names in SQL. An example + is <literal>plpgsql.variable_conflict</>. </para> <para> - Here is an example of what <filename>postgresql.conf</> might contain - when using custom variables: - -<programlisting> -custom_variable_classes = 'plpgsql,plperl' -plpgsql.variable_conflict = use_variable -plperl.use_strict = true -plruby.use_strict = true # generates error: unknown class name -</programlisting> + Because custom options may need to be set in processes that have not + loaded the relevant extension module, <productname>PostgreSQL</> + will accept a setting for any two-part parameter name. Such variables + are treated as placeholders and have no function until the module that + defines them is loaded. When an extension module is loaded, it will add + its variable definitions, convert any placeholder values according to + those definitions, and issue warnings for any unrecognized placeholders + that begin with its extension name. </para> </sect1> diff --git a/doc/src/sgml/pgstatstatements.sgml b/doc/src/sgml/pgstatstatements.sgml index 52268c545d74a5baf8c601705dec66d82711c8a6..5a0230c428618b53069f6b2f38e2d4acdcdaebff 100644 --- a/doc/src/sgml/pgstatstatements.sgml +++ b/doc/src/sgml/pgstatstatements.sgml @@ -275,16 +275,13 @@ </para> <para> - In order to set any of these parameters in your - <filename>postgresql.conf</> file, - you will need to add <literal>pg_stat_statements</> to - <xref linkend="guc-custom-variable-classes">. Typical usage might be: + These parameters must be set in <filename>postgresql.conf</>. + Typical usage might be: <programlisting> # postgresql.conf shared_preload_libraries = 'pg_stat_statements' -custom_variable_classes = 'pg_stat_statements' pg_stat_statements.max = 10000 pg_stat_statements.track = all </programlisting> diff --git a/doc/src/sgml/plperl.sgml b/doc/src/sgml/plperl.sgml index b957757da64685450b5961a2ddc7c114c3dd3336..81b6de7adb67bd76c0a317e878833536f55913e8 100644 --- a/doc/src/sgml/plperl.sgml +++ b/doc/src/sgml/plperl.sgml @@ -1219,10 +1219,6 @@ CREATE TRIGGER test_valid_id_trig <para> This section lists configuration parameters that affect <application>PL/Perl</>. - To set any of these parameters before <application>PL/Perl</> has been loaded, - it is necessary to have added <quote><literal>plperl</></> to the - <xref linkend="guc-custom-variable-classes"> list in - <filename>postgresql.conf</filename>. </para> <variablelist> diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml index 84fb012d1f3942914f12445807f9e6c0aa62eaa9..c14c34cd322488bc326b3e703d8060f9f3371599 100644 --- a/doc/src/sgml/plpgsql.sgml +++ b/doc/src/sgml/plpgsql.sgml @@ -4007,11 +4007,8 @@ BEGIN <literal>use_column</> (where <literal>error</> is the factory default). This parameter affects subsequent compilations of statements in <application>PL/pgSQL</> functions, but not statements - already compiled in the current session. To set the parameter before - <application>PL/pgSQL</> has been loaded, it is necessary to have added - <quote><literal>plpgsql</></> to the <xref - linkend="guc-custom-variable-classes"> list in - <filename>postgresql.conf</filename>. Because changing this setting + already compiled in the current session. + Because changing this setting can cause unexpected changes in the behavior of <application>PL/pgSQL</> functions, it can only be changed by a superuser. </para> diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l index a7cf0378dca25f23c3dfed987c088663769e2bf5..7728544c5452650187e242d06d7b6c3353ef99d5 100644 --- a/src/backend/utils/misc/guc-file.l +++ b/src/backend/utils/misc/guc-file.l @@ -111,8 +111,6 @@ ProcessConfigFile(GucContext context) ConfigVariable *item, *head, *tail; - char *cvc = NULL; - struct config_string *cvc_struct; int i; /* @@ -138,50 +136,6 @@ ProcessConfigFile(GucContext context) goto cleanup_list; } - /* - * We need the proposed new value of custom_variable_classes to check - * custom variables with. ParseConfigFile ensured that if it's in - * the file, it's first in the list. But first check to see if we - * have an active value from the command line, which should override - * the file in any case. (Since there's no relevant env var, the - * only possible nondefault sources are the file and ARGV.) - */ - cvc_struct = (struct config_string *) - find_option("custom_variable_classes", false, elevel); - Assert(cvc_struct); - if (cvc_struct->gen.reset_source > PGC_S_FILE) - { - cvc = guc_strdup(elevel, cvc_struct->reset_val); - if (cvc == NULL) - { - error = true; - goto cleanup_list; - } - } - else if (head != NULL && - guc_name_compare(head->name, "custom_variable_classes") == 0) - { - /* - * Need to canonicalize the value by calling the check hook. - */ - void *extra = NULL; - - cvc = guc_strdup(elevel, head->value); - if (cvc == NULL) - { - error = true; - goto cleanup_list; - } - if (!call_string_check_hook(cvc_struct, &cvc, &extra, - PGC_S_FILE, elevel)) - { - error = true; - goto cleanup_list; - } - if (extra) - free(extra); - } - /* * Mark all extant GUC variables as not present in the config file. * We need this so that we can tell below which ones have been removed @@ -199,39 +153,29 @@ ProcessConfigFile(GucContext context) * quasi-syntactic check on the validity of the config file. It is * important that the postmaster and all backends agree on the results * of this phase, else we will have strange inconsistencies about which - * processes accept a config file update and which don't. Hence, custom - * variable names can only be checked against custom_variable_classes, - * not against any loadable modules that might (or might not) be present. - * Likewise, we don't attempt to validate the options' values here. + * processes accept a config file update and which don't. Hence, unknown + * custom variable names have to be accepted without complaint. For the + * same reason, we don't attempt to validate the options' values here. * * In addition, the GUC_IS_IN_FILE flag is set on each existing GUC * variable mentioned in the file. */ for (item = head; item; item = item->next) { - char *sep = strchr(item->name, GUC_QUALIFIER_SEPARATOR); struct config_generic *record; - if (sep) - { - /* Custom variable, so check against custom_variable_classes */ - if (!is_custom_class(item->name, sep - item->name, cvc)) - { - ereport(elevel, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("unrecognized configuration parameter \"%s\" in file \"%s\" line %u", - item->name, - item->filename, item->sourceline))); - error = true; - continue; - } - } - + /* + * Try to find the variable; but do not create a custom placeholder + * if it's not there already. + */ record = find_option(item->name, false, elevel); if (record) + { + /* Found, so mark it as present in file */ record->status |= GUC_IS_IN_FILE; - else if (!sep) + } + else if (strchr(item->name, GUC_QUALIFIER_SEPARATOR) == NULL) { /* Invalid non-custom variable, so complain */ ereport(elevel, @@ -382,8 +326,6 @@ ProcessConfigFile(GucContext context) cleanup_list: FreeConfigVariables(head); - if (cvc) - free(cvc); if (error) { @@ -581,40 +523,6 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel, pfree(opt_name); pfree(opt_value); } - else if (guc_name_compare(opt_name, "custom_variable_classes") == 0) - { - /* - * This variable must be processed first as it controls - * the validity of other variables; so it goes at the head - * of the result list. If we already found a value for it, - * replace with this one. - */ - item = *head_p; - if (item != NULL && - guc_name_compare(item->name, "custom_variable_classes") == 0) - { - /* replace existing head item */ - pfree(item->name); - pfree(item->value); - item->name = opt_name; - item->value = opt_value; - item->filename = pstrdup(config_file); - item->sourceline = ConfigFileLineno-1; - } - else - { - /* prepend to list */ - item = palloc(sizeof *item); - item->name = opt_name; - item->value = opt_value; - item->filename = pstrdup(config_file); - item->sourceline = ConfigFileLineno-1; - item->next = *head_p; - *head_p = item; - if (*tail_p == NULL) - *tail_p = item; - } - } else { /* ordinary variable, append to list */ diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index c5b14522d5fb0eec8beb545164727f128d716cd0..2fd4867d253ca97f1c1d10a31686f450a289b48e 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -178,7 +178,6 @@ static void assign_syslog_ident(const char *newval, void *extra); static void assign_session_replication_role(int newval, void *extra); static bool check_temp_buffers(int *newval, void **extra, GucSource source); static bool check_phony_autocommit(bool *newval, void **extra, GucSource source); -static bool check_custom_variable_classes(char **newval, void **extra, GucSource source); static bool check_debug_assertions(bool *newval, void **extra, GucSource source); static bool check_bonjour(bool *newval, void **extra, GucSource source); static bool check_ssl(bool *newval, void **extra, GucSource source); @@ -467,7 +466,6 @@ static char *log_timezone_string; static char *timezone_abbreviations_string; static char *XactIsoLevel_string; static char *session_authorization_string; -static char *custom_variable_classes; static int max_function_args; static int max_index_keys; static int max_identifier_length; @@ -2885,17 +2883,6 @@ static struct config_string ConfigureNamesString[] = NULL, NULL, NULL }, - { - {"custom_variable_classes", PGC_SIGHUP, CUSTOM_OPTIONS, - gettext_noop("Sets the list of known custom variable classes."), - NULL, - GUC_LIST_INPUT | GUC_LIST_QUOTE - }, - &custom_variable_classes, - NULL, - check_custom_variable_classes, NULL, NULL - }, - { {"data_directory", PGC_POSTMASTER, FILE_LOCATIONS, gettext_noop("Sets the server's data directory."), @@ -3623,8 +3610,7 @@ add_guc_variable(struct config_generic * var, int elevel) } /* - * Create and add a placeholder variable. It's presumed to belong - * to a valid custom variable class at this point. + * Create and add a placeholder variable for a custom variable name. */ static struct config_generic * add_placeholder_variable(const char *name, int elevel) @@ -3669,42 +3655,6 @@ add_placeholder_variable(const char *name, int elevel) return gen; } -/* - * Detect whether the portion of "name" before dotPos matches any custom - * variable class name listed in custom_var_classes. The latter must be - * formatted the way that assign_custom_variable_classes does it, ie, - * no whitespace. NULL is valid for custom_var_classes. - */ -static bool -is_custom_class(const char *name, int dotPos, const char *custom_var_classes) -{ - bool result = false; - const char *ccs = custom_var_classes; - - if (ccs != NULL) - { - const char *start = ccs; - - for (;; ++ccs) - { - char c = *ccs; - - if (c == '\0' || c == ',') - { - if (dotPos == ccs - start && strncmp(start, name, dotPos) == 0) - { - result = true; - break; - } - if (c == '\0') - break; - start = ccs + 1; - } - } - } - return result; -} - /* * Look up option NAME. If it exists, return a pointer to its record, * else return NULL. If create_placeholders is TRUE, we'll create a @@ -3745,13 +3695,9 @@ find_option(const char *name, bool create_placeholders, int elevel) if (create_placeholders) { /* - * Check if the name is qualified, and if so, check if the qualifier - * matches any custom variable class. If so, add a placeholder. + * Check if the name is qualified, and if so, add a placeholder. */ - const char *dot = strchr(name, GUC_QUALIFIER_SEPARATOR); - - if (dot != NULL && - is_custom_class(name, dot - name, custom_variable_classes)) + if (strchr(name, GUC_QUALIFIER_SEPARATOR) != NULL) return add_placeholder_variable(name, elevel); } @@ -7406,7 +7352,6 @@ write_nondefault_variables(GucContext context) { int elevel; FILE *fp; - struct config_generic *cvc_conf; int i; Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP); @@ -7426,20 +7371,9 @@ write_nondefault_variables(GucContext context) return; } - /* - * custom_variable_classes must be written out first; otherwise we might - * reject custom variable values while reading the file. - */ - cvc_conf = find_option("custom_variable_classes", false, ERROR); - if (cvc_conf) - write_one_nondefault_variable(fp, cvc_conf); - for (i = 0; i < num_guc_variables; i++) { - struct config_generic *gconf = guc_variables[i]; - - if (gconf != cvc_conf) - write_one_nondefault_variable(fp, gconf); + write_one_nondefault_variable(fp, guc_variables[i]); } if (FreeFile(fp)) @@ -7886,20 +7820,15 @@ validate_option_array_item(const char *name, const char *value, * permissions normally (ie, allow if variable is USERSET, or if it's * SUSET and user is superuser). * - * name is not known, but exists or can be created as a placeholder - * (implying it has a prefix listed in custom_variable_classes). We allow - * this case if you're a superuser, otherwise not. Superusers are assumed - * to know what they're doing. We can't allow it for other users, because - * when the placeholder is resolved it might turn out to be a SUSET - * variable; define_custom_variable assumes we checked that. + * name is not known, but exists or can be created as a placeholder (i.e., + * it has a prefixed name). We allow this case if you're a superuser, + * otherwise not. Superusers are assumed to know what they're doing. + * We can't allow it for other users, because when the placeholder is + * resolved it might turn out to be a SUSET variable; + * define_custom_variable assumes we checked that. * * name is not known and can't be created as a placeholder. Throw error, - * unless skipIfNoPermissions is true, in which case return FALSE. (It's - * tempting to allow this case to superusers, if the name is qualified but - * not listed in custom_variable_classes. That would ease restoring of - * dumps containing ALTER ROLE/DATABASE SET. However, it's not clear that - * this usage justifies such a loss of error checking. You can always fix - * custom_variable_classes before you restore.) + * unless skipIfNoPermissions is true, in which case return FALSE. */ gconf = find_option(name, true, WARNING); if (!gconf) @@ -7909,7 +7838,8 @@ validate_option_array_item(const char *name, const char *value, return false; ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("unrecognized configuration parameter \"%s\"", name))); + errmsg("unrecognized configuration parameter \"%s\"", + name))); } if (gconf->flags & GUC_CUSTOM_PLACEHOLDER) @@ -8262,69 +8192,6 @@ check_phony_autocommit(bool *newval, void **extra, GucSource source) return true; } -static bool -check_custom_variable_classes(char **newval, void **extra, GucSource source) -{ - /* - * Check syntax. newval must be a comma separated list of identifiers. - * Whitespace is allowed but removed from the result. - */ - bool hasSpaceAfterToken = false; - const char *cp = *newval; - int symLen = 0; - char c; - StringInfoData buf; - - /* Default NULL is OK */ - if (cp == NULL) - return true; - - initStringInfo(&buf); - while ((c = *cp++) != '\0') - { - if (isspace((unsigned char) c)) - { - if (symLen > 0) - hasSpaceAfterToken = true; - continue; - } - - if (c == ',') - { - if (symLen > 0) /* terminate identifier */ - { - appendStringInfoChar(&buf, ','); - symLen = 0; - } - hasSpaceAfterToken = false; - continue; - } - - if (hasSpaceAfterToken || !(isalnum((unsigned char) c) || c == '_')) - { - /* - * Syntax error due to token following space after token or - * non-identifier character - */ - pfree(buf.data); - return false; - } - appendStringInfoChar(&buf, c); - symLen++; - } - - /* Remove stray ',' at end */ - if (symLen == 0 && buf.len > 0) - buf.data[--buf.len] = '\0'; - - /* GUC wants the result malloc'd */ - free(*newval); - *newval = guc_strdup(LOG, buf.data); - - pfree(buf.data); - return true; -} - static bool check_debug_assertions(bool *newval, void **extra, GucSource source) { diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index a18f14ae253a432f4386682d2bcd55d61fd9dba3..5bb7e7117bc95c5cf1ba2bd312c707f4208999c5 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -560,4 +560,4 @@ # CUSTOMIZED OPTIONS #------------------------------------------------------------------------------ -#custom_variable_classes = '' # list of custom variable class names +# Add settings for extensions here diff --git a/src/pl/plperl/expected/plperl_init.out b/src/pl/plperl/expected/plperl_init.out index 4a04dbd6f37d43fab912206c1dd23ea89d0be11d..e8a8e9bd83d6dff6c034d154965c86be55b1303d 100644 --- a/src/pl/plperl/expected/plperl_init.out +++ b/src/pl/plperl/expected/plperl_init.out @@ -1,5 +1,5 @@ -- test plperl.on_plperl_init errors are fatal --- Avoid need for custom_variable_classes = 'plperl' +-- Must load plperl before we can set on_plperl_init LOAD 'plperl'; SET SESSION plperl.on_plperl_init = ' system("/nonesuch") '; SHOW plperl.on_plperl_init; diff --git a/src/pl/plperl/expected/plperl_shared.out b/src/pl/plperl/expected/plperl_shared.out index 1a6bf5ee4d42eba0492cfca5c7dee8ad6af321b8..67478ab454b4176955ca36e236edfd704222972b 100644 --- a/src/pl/plperl/expected/plperl_shared.out +++ b/src/pl/plperl/expected/plperl_shared.out @@ -1,6 +1,6 @@ -- test plperl.on_plperl_init via the shared hash -- (must be done before plperl is first used) --- Avoid need for custom_variable_classes = 'plperl' +-- Must load plperl before we can set on_plperl_init LOAD 'plperl'; -- testing on_plperl_init gets run, and that it can alter %_SHARED SET plperl.on_plperl_init = '$_SHARED{on_init} = 42'; diff --git a/src/pl/plperl/expected/plperlu.out b/src/pl/plperl/expected/plperlu.out index 25ac007b7a27b71558356c37adb2e2e9856b87b4..1ba07eed9dc835579e52bc50217075f64991dbbc 100644 --- a/src/pl/plperl/expected/plperlu.out +++ b/src/pl/plperl/expected/plperlu.out @@ -1,6 +1,6 @@ -- Use ONLY plperlu tests here. For plperl/plerlu combined tests -- see plperl_plperlu.sql --- Avoid need for custom_variable_classes = 'plperl' +-- Must load plperl before we can set on_plperlu_init LOAD 'plperl'; -- Test plperl.on_plperlu_init gets run SET plperl.on_plperlu_init = '$_SHARED{init} = 42'; diff --git a/src/pl/plperl/sql/plperl_init.sql b/src/pl/plperl/sql/plperl_init.sql index f6a32b9bae4792ab449ef62cdb717384adca6bd8..51ac9192bdfc4f77c08a841f0106304ee34e9e56 100644 --- a/src/pl/plperl/sql/plperl_init.sql +++ b/src/pl/plperl/sql/plperl_init.sql @@ -1,6 +1,6 @@ -- test plperl.on_plperl_init errors are fatal --- Avoid need for custom_variable_classes = 'plperl' +-- Must load plperl before we can set on_plperl_init LOAD 'plperl'; SET SESSION plperl.on_plperl_init = ' system("/nonesuch") '; diff --git a/src/pl/plperl/sql/plperl_shared.sql b/src/pl/plperl/sql/plperl_shared.sql index d367d32ff08266f9b0f1f558e704e785fd3420ec..d2fa8cbf93e7b7f63c49984b1432a93de65089a7 100644 --- a/src/pl/plperl/sql/plperl_shared.sql +++ b/src/pl/plperl/sql/plperl_shared.sql @@ -1,7 +1,7 @@ -- test plperl.on_plperl_init via the shared hash -- (must be done before plperl is first used) --- Avoid need for custom_variable_classes = 'plperl' +-- Must load plperl before we can set on_plperl_init LOAD 'plperl'; -- testing on_plperl_init gets run, and that it can alter %_SHARED diff --git a/src/pl/plperl/sql/plperlu.sql b/src/pl/plperl/sql/plperlu.sql index 125691e5f7ba7bad01aae0a7c71a20c251e9c69e..831b8f44604e1829e058394fed9c67ccf6e75c7f 100644 --- a/src/pl/plperl/sql/plperlu.sql +++ b/src/pl/plperl/sql/plperlu.sql @@ -1,7 +1,7 @@ -- Use ONLY plperlu tests here. For plperl/plerlu combined tests -- see plperl_plperlu.sql --- Avoid need for custom_variable_classes = 'plperl' +-- Must load plperl before we can set on_plperlu_init LOAD 'plperl'; -- Test plperl.on_plperlu_init gets run