diff --git a/doc/src/sgml/ref/alter_system.sgml b/doc/src/sgml/ref/alter_system.sgml index 23c30efc8f853df9eb4652e45836df200ef95bfb..a6e32106e80206b2c58ac546092c083c3a40d319 100644 --- a/doc/src/sgml/ref/alter_system.sgml +++ b/doc/src/sgml/ref/alter_system.sgml @@ -22,6 +22,9 @@ PostgreSQL documentation <refsynopsisdiv> <synopsis> ALTER SYSTEM SET <replaceable class="PARAMETER">configuration_parameter</replaceable> { TO | = } { <replaceable class="PARAMETER">value</replaceable> | '<replaceable class="PARAMETER">value</replaceable>' | DEFAULT } + +ALTER SYSTEM RESET <replaceable class="PARAMETER">configuration_parameter</replaceable> +ALTER SYSTEM RESET ALL </synopsis> </refsynopsisdiv> @@ -30,10 +33,12 @@ ALTER SYSTEM SET <replaceable class="PARAMETER">configuration_parameter</replace <para> <command>ALTER SYSTEM</command> writes the configuration parameter - values to the <filename>postgresql.auto.conf</filename> file. With - <literal>DEFAULT</literal>, it removes a configuration entry from - <filename>postgresql.auto.conf</filename> file. The values will be - effective after reload of server configuration (SIGHUP) or in next + values to the <filename>postgresql.auto.conf</filename> file. + Setting the parameter to <literal>DEFAULT</literal>, or using the + <command>RESET</command> variant, removes the configuration entry from + <filename>postgresql.auto.conf</filename> file. Use <literal>RESET + ALL</literal> to clear all configuration entries. The values will + be effective after reload of server configuration (SIGHUP) or in next server start based on the type of configuration parameter modified. </para> diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 6f4d6455df69d2e31ea3c76c1bb38c577eb77e0d..b46dd7b008caf407aa29606ee3e2cd094e3f4d4f 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -411,7 +411,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type <istmt> insert_rest -%type <vsetstmt> generic_set set_rest set_rest_more SetResetClause FunctionSetResetClause +%type <vsetstmt> generic_set set_rest set_rest_more generic_reset reset_rest + SetResetClause FunctionSetResetClause %type <node> TableElement TypedTableElement ConstraintElem TableFuncElement %type <node> columnDef columnOptions @@ -1579,39 +1580,47 @@ NonReservedWord_or_Sconst: ; VariableResetStmt: - RESET var_name + RESET reset_rest { $$ = (Node *) $2; } + ; + +reset_rest: + generic_reset { $$ = $1; } + | TIME ZONE { VariableSetStmt *n = makeNode(VariableSetStmt); n->kind = VAR_RESET; - n->name = $2; - $$ = (Node *) n; + n->name = "timezone"; + $$ = n; } - | RESET TIME ZONE + | TRANSACTION ISOLATION LEVEL { VariableSetStmt *n = makeNode(VariableSetStmt); n->kind = VAR_RESET; - n->name = "timezone"; - $$ = (Node *) n; + n->name = "transaction_isolation"; + $$ = n; } - | RESET TRANSACTION ISOLATION LEVEL + | SESSION AUTHORIZATION { VariableSetStmt *n = makeNode(VariableSetStmt); n->kind = VAR_RESET; - n->name = "transaction_isolation"; - $$ = (Node *) n; + n->name = "session_authorization"; + $$ = n; } - | RESET SESSION AUTHORIZATION + ; + +generic_reset: + var_name { VariableSetStmt *n = makeNode(VariableSetStmt); n->kind = VAR_RESET; - n->name = "session_authorization"; - $$ = (Node *) n; + n->name = $1; + $$ = n; } - | RESET ALL + | ALL { VariableSetStmt *n = makeNode(VariableSetStmt); n->kind = VAR_RESET_ALL; - $$ = (Node *) n; + $$ = n; } ; @@ -8494,7 +8503,7 @@ DropdbStmt: DROP DATABASE database_name /***************************************************************************** * - * ALTER SYSTEM SET + * ALTER SYSTEM * * This is used to change configuration parameters persistently. *****************************************************************************/ @@ -8506,6 +8515,12 @@ AlterSystemStmt: n->setstmt = $4; $$ = (Node *)n; } + | ALTER SYSTEM_P RESET generic_reset + { + AlterSystemStmt *n = makeNode(AlterSystemStmt); + n->setstmt = $4; + $$ = (Node *)n; + } ; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 8c57803afe2694bdc0bfe0913c9a0d6fe9a4b4c0..af667f54ada520db97d45b8929458dba0c6c96d2 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -6696,6 +6696,8 @@ replace_auto_config_value(ConfigVariable **head_p, ConfigVariable **tail_p, * This function takes all previous configuration parameters * set by ALTER SYSTEM command and the currently set ones * and write them all to the automatic configuration file. + * It just writes an empty file incase user wants to reset + * all the parameters. * * The configuration parameters are written to a temporary * file then renamed to the final name. @@ -6710,6 +6712,7 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt) { char *name; char *value; + bool resetall = false; int Tmpfd = -1; FILE *infile; struct config_generic *record; @@ -6737,37 +6740,48 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt) break; case VAR_SET_DEFAULT: + case VAR_RESET: + value = NULL; + break; + + case VAR_RESET_ALL: value = NULL; + resetall = true; break; + default: elog(ERROR, "unrecognized alter system stmt type: %d", altersysstmt->setstmt->kind); break; } - record = find_option(name, false, LOG); - if (record == NULL) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("unrecognized configuration parameter \"%s\"", name))); + /* If we're resetting everything, there's no need to validate anything */ + if (!resetall) + { + record = find_option(name, false, LOG); + if (record == NULL) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("unrecognized configuration parameter \"%s\"", name))); - /* - * Don't allow the parameters which can't be set in configuration - * files to be set in PG_AUTOCONF_FILENAME file. - */ - if ((record->context == PGC_INTERNAL) || - (record->flags & GUC_DISALLOW_IN_FILE) || - (record->flags & GUC_DISALLOW_IN_AUTO_FILE)) - ereport(ERROR, - (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), - errmsg("parameter \"%s\" cannot be changed", - name))); - - if (!validate_conf_option(record, name, value, PGC_S_FILE, - ERROR, true, NULL, - &newextra)) - ereport(ERROR, - (errmsg("invalid value for parameter \"%s\": \"%s\"", name, value))); + /* + * Don't allow the parameters which can't be set in configuration + * files to be set in PG_AUTOCONF_FILENAME file. + */ + if ((record->context == PGC_INTERNAL) || + (record->flags & GUC_DISALLOW_IN_FILE) || + (record->flags & GUC_DISALLOW_IN_AUTO_FILE)) + ereport(ERROR, + (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), + errmsg("parameter \"%s\" cannot be changed", + name))); + + if (!validate_conf_option(record, name, value, PGC_S_FILE, + ERROR, true, NULL, + &newextra)) + ereport(ERROR, + (errmsg("invalid value for parameter \"%s\": \"%s\"", name, value))); + } /* @@ -6799,26 +6813,34 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt) PG_TRY(); { - if (stat(AutoConfFileName, &st) == 0) + /* + * If we're going to reset everything, then don't open the file, don't + * parse it, and don't do anything with the configuration list. Just + * write out an empty file. + */ + if (!resetall) { - /* open file PG_AUTOCONF_FILENAME */ - infile = AllocateFile(AutoConfFileName, "r"); - if (infile == NULL) - ereport(ERROR, - (errmsg("failed to open auto conf file \"%s\": %m ", - AutoConfFileName))); + if (stat(AutoConfFileName, &st) == 0) + { + /* open file PG_AUTOCONF_FILENAME */ + infile = AllocateFile(AutoConfFileName, "r"); + if (infile == NULL) + ereport(ERROR, + (errmsg("failed to open auto conf file \"%s\": %m ", + AutoConfFileName))); - /* parse it */ - ParseConfigFp(infile, AutoConfFileName, 0, LOG, &head, &tail); + /* parse it */ + ParseConfigFp(infile, AutoConfFileName, 0, LOG, &head, &tail); - FreeFile(infile); - } + FreeFile(infile); + } - /* - * replace with new value if the configuration parameter already - * exists OR add it as a new cofiguration parameter in the file. - */ - replace_auto_config_value(&head, &tail, AutoConfFileName, name, value); + /* + * replace with new value if the configuration parameter already + * exists OR add it as a new cofiguration parameter in the file. + */ + replace_auto_config_value(&head, &tail, AutoConfFileName, name, value); + } /* Write and sync the new contents to the temporary file */ write_auto_conf_file(Tmpfd, AutoConfTmpFileName, &head); diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index 76b2b04c1acd3186657a93a039a9c41b9cefe36e..8288b41f0a5ebbebe6c33b288fcf77bd9043d90e 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -545,7 +545,8 @@ static const SchemaQuery Query_for_list_of_matviews = { "SELECT name FROM "\ " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\ " WHERE context != 'internal') ss "\ -" WHERE substring(name,1,%d)='%s'" +" WHERE substring(name,1,%d)='%s'"\ +" UNION ALL SELECT 'all' ss" #define Query_for_list_of_set_vars \ "SELECT name FROM "\ @@ -963,7 +964,7 @@ psql_completion(const char *text, int start, int end) {"AGGREGATE", "COLLATION", "CONVERSION", "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN", "EVENT TRIGGER", "EXTENSION", "FOREIGN DATA WRAPPER", "FOREIGN TABLE", "FUNCTION", "GROUP", "INDEX", "LANGUAGE", "LARGE OBJECT", "MATERIALIZED VIEW", "OPERATOR", - "ROLE", "RULE", "SCHEMA", "SERVER", "SEQUENCE", "SYSTEM SET", "TABLE", + "ROLE", "RULE", "SCHEMA", "SERVER", "SEQUENCE", "SYSTEM", "TABLE", "TABLESPACE", "TEXT SEARCH", "TRIGGER", "TYPE", "USER", "USER MAPPING FOR", "VIEW", NULL}; @@ -1328,10 +1329,20 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH_LIST(list_ALTER_SERVER); } - /* ALTER SYSTEM SET <name> */ + /* ALTER SYSTEM SET, RESET, RESET ALL */ + else if (pg_strcasecmp(prev2_wd, "ALTER") == 0 && + pg_strcasecmp(prev_wd, "SYSTEM") == 0) + { + static const char *const list_ALTERSYSTEM[] = + {"SET", "RESET", NULL}; + + COMPLETE_WITH_LIST(list_ALTERSYSTEM); + } + /* ALTER SYSTEM SET|RESET <name> */ else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && pg_strcasecmp(prev2_wd, "SYSTEM") == 0 && - pg_strcasecmp(prev_wd, "SET") == 0) + (pg_strcasecmp(prev_wd, "SET") == 0 || + pg_strcasecmp(prev_wd, "RESET") == 0)) COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars); /* ALTER VIEW <name> */ else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&