Support ALTER SYSTEM RESET command.

This patch allows us to execute ALTER SYSTEM RESET command to
remove the configuration entry from postgresql.auto.conf.

Vik Fearing, reviewed by Amit Kapila and me.
This commit is contained in:
Fujii Masao 2014-09-02 16:06:58 +09:00
parent 79ee6370ee
commit 7dfab04a8a
4 changed files with 117 additions and 64 deletions

View File

@ -22,6 +22,9 @@ PostgreSQL documentation
<refsynopsisdiv> <refsynopsisdiv>
<synopsis> <synopsis>
ALTER SYSTEM SET <replaceable class="PARAMETER">configuration_parameter</replaceable> { TO | = } { <replaceable class="PARAMETER">value</replaceable> | '<replaceable class="PARAMETER">value</replaceable>' | DEFAULT } 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> </synopsis>
</refsynopsisdiv> </refsynopsisdiv>
@ -30,10 +33,12 @@ ALTER SYSTEM SET <replaceable class="PARAMETER">configuration_parameter</replace
<para> <para>
<command>ALTER SYSTEM</command> writes the configuration parameter <command>ALTER SYSTEM</command> writes the configuration parameter
values to the <filename>postgresql.auto.conf</filename> file. With values to the <filename>postgresql.auto.conf</filename> file.
<literal>DEFAULT</literal>, it removes a configuration entry from Setting the parameter to <literal>DEFAULT</literal>, or using the
<filename>postgresql.auto.conf</filename> file. The values will be <command>RESET</command> variant, removes the configuration entry from
effective after reload of server configuration (SIGHUP) or in next <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. server start based on the type of configuration parameter modified.
</para> </para>

View File

@ -398,7 +398,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <istmt> insert_rest %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> TableElement TypedTableElement ConstraintElem TableFuncElement
%type <node> columnDef columnOptions %type <node> columnDef columnOptions
@ -1564,39 +1565,47 @@ NonReservedWord_or_Sconst:
; ;
VariableResetStmt: VariableResetStmt:
RESET var_name RESET reset_rest { $$ = (Node *) $2; }
{ ;
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_RESET; reset_rest:
n->name = $2; generic_reset { $$ = $1; }
$$ = (Node *) n; | TIME ZONE
}
| RESET TIME ZONE
{ {
VariableSetStmt *n = makeNode(VariableSetStmt); VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_RESET; n->kind = VAR_RESET;
n->name = "timezone"; n->name = "timezone";
$$ = (Node *) n; $$ = n;
} }
| RESET TRANSACTION ISOLATION LEVEL | TRANSACTION ISOLATION LEVEL
{ {
VariableSetStmt *n = makeNode(VariableSetStmt); VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_RESET; n->kind = VAR_RESET;
n->name = "transaction_isolation"; n->name = "transaction_isolation";
$$ = (Node *) n; $$ = n;
} }
| RESET SESSION AUTHORIZATION | SESSION AUTHORIZATION
{ {
VariableSetStmt *n = makeNode(VariableSetStmt); VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_RESET; n->kind = VAR_RESET;
n->name = "session_authorization"; n->name = "session_authorization";
$$ = (Node *) n; $$ = n;
} }
| RESET ALL ;
generic_reset:
var_name
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_RESET;
n->name = $1;
$$ = n;
}
| ALL
{ {
VariableSetStmt *n = makeNode(VariableSetStmt); VariableSetStmt *n = makeNode(VariableSetStmt);
n->kind = VAR_RESET_ALL; n->kind = VAR_RESET_ALL;
$$ = (Node *) n; $$ = n;
} }
; ;
@ -8442,7 +8451,7 @@ DropdbStmt: DROP DATABASE database_name
/***************************************************************************** /*****************************************************************************
* *
* ALTER SYSTEM SET * ALTER SYSTEM
* *
* This is used to change configuration parameters persistently. * This is used to change configuration parameters persistently.
*****************************************************************************/ *****************************************************************************/
@ -8454,6 +8463,12 @@ AlterSystemStmt:
n->setstmt = $4; n->setstmt = $4;
$$ = (Node *)n; $$ = (Node *)n;
} }
| ALTER SYSTEM_P RESET generic_reset
{
AlterSystemStmt *n = makeNode(AlterSystemStmt);
n->setstmt = $4;
$$ = (Node *)n;
}
; ;

View File

@ -6691,6 +6691,8 @@ replace_auto_config_value(ConfigVariable **head_p, ConfigVariable **tail_p,
* This function takes all previous configuration parameters * This function takes all previous configuration parameters
* set by ALTER SYSTEM command and the currently set ones * set by ALTER SYSTEM command and the currently set ones
* and write them all to the automatic configuration file. * 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 * The configuration parameters are written to a temporary
* file then renamed to the final name. * file then renamed to the final name.
@ -6705,6 +6707,7 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
{ {
char *name; char *name;
char *value; char *value;
bool resetall = false;
int Tmpfd = -1; int Tmpfd = -1;
FILE *infile; FILE *infile;
struct config_generic *record; struct config_generic *record;
@ -6732,37 +6735,48 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
break; break;
case VAR_SET_DEFAULT: case VAR_SET_DEFAULT:
case VAR_RESET:
value = NULL; value = NULL;
break; break;
case VAR_RESET_ALL:
value = NULL;
resetall = true;
break;
default: default:
elog(ERROR, "unrecognized alter system stmt type: %d", elog(ERROR, "unrecognized alter system stmt type: %d",
altersysstmt->setstmt->kind); altersysstmt->setstmt->kind);
break; break;
} }
record = find_option(name, false, LOG); /* If we're resetting everything, there's no need to validate anything */
if (record == NULL) if (!resetall)
ereport(ERROR, {
(errcode(ERRCODE_UNDEFINED_OBJECT), record = find_option(name, false, LOG);
errmsg("unrecognized configuration parameter \"%s\"", name))); 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 * Don't allow the parameters which can't be set in configuration
* files to be set in PG_AUTOCONF_FILENAME file. * files to be set in PG_AUTOCONF_FILENAME file.
*/ */
if ((record->context == PGC_INTERNAL) || if ((record->context == PGC_INTERNAL) ||
(record->flags & GUC_DISALLOW_IN_FILE) || (record->flags & GUC_DISALLOW_IN_FILE) ||
(record->flags & GUC_DISALLOW_IN_AUTO_FILE)) (record->flags & GUC_DISALLOW_IN_AUTO_FILE))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
errmsg("parameter \"%s\" cannot be changed", errmsg("parameter \"%s\" cannot be changed",
name))); name)));
if (!validate_conf_option(record, name, value, PGC_S_FILE, if (!validate_conf_option(record, name, value, PGC_S_FILE,
ERROR, true, NULL, ERROR, true, NULL,
&newextra)) &newextra))
ereport(ERROR, ereport(ERROR,
(errmsg("invalid value for parameter \"%s\": \"%s\"", name, value))); (errmsg("invalid value for parameter \"%s\": \"%s\"", name, value)));
}
/* /*
@ -6794,26 +6808,34 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
PG_TRY(); PG_TRY();
{ {
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);
FreeFile(infile);
}
/* /*
* replace with new value if the configuration parameter already * If we're going to reset everything, then don't open the file, don't
* exists OR add it as a new cofiguration parameter in the file. * parse it, and don't do anything with the configuration list. Just
* write out an empty file.
*/ */
replace_auto_config_value(&head, &tail, AutoConfFileName, name, value); if (!resetall)
{
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);
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);
}
/* Write and sync the new contents to the temporary file */ /* Write and sync the new contents to the temporary file */
write_auto_conf_file(Tmpfd, AutoConfTmpFileName, &head); write_auto_conf_file(Tmpfd, AutoConfTmpFileName, &head);

View File

@ -545,7 +545,8 @@ static const SchemaQuery Query_for_list_of_matviews = {
"SELECT name FROM "\ "SELECT name FROM "\
" (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\ " (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\
" WHERE context != 'internal') ss "\ " 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 \ #define Query_for_list_of_set_vars \
"SELECT name FROM "\ "SELECT name FROM "\
@ -949,7 +950,7 @@ psql_completion(const char *text, int start, int end)
{"AGGREGATE", "COLLATION", "CONVERSION", "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN", {"AGGREGATE", "COLLATION", "CONVERSION", "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN",
"EVENT TRIGGER", "EXTENSION", "FOREIGN DATA WRAPPER", "FOREIGN TABLE", "FUNCTION", "EVENT TRIGGER", "EXTENSION", "FOREIGN DATA WRAPPER", "FOREIGN TABLE", "FUNCTION",
"GROUP", "INDEX", "LANGUAGE", "LARGE OBJECT", "MATERIALIZED VIEW", "OPERATOR", "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", "TABLESPACE", "TEXT SEARCH", "TRIGGER", "TYPE",
"USER", "USER MAPPING FOR", "VIEW", NULL}; "USER", "USER MAPPING FOR", "VIEW", NULL};
@ -1340,10 +1341,20 @@ psql_completion(const char *text, int start, int end)
COMPLETE_WITH_LIST(list_ALTER_SERVER); 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 && else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
pg_strcasecmp(prev2_wd, "SYSTEM") == 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); COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars);
/* ALTER VIEW <name> */ /* ALTER VIEW <name> */
else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&