Commit 65d6e4cb authored by Tatsuo Ishii's avatar Tatsuo Ishii

Add ALTER SYSTEM command to edit the server configuration file.

Patch contributed by Amit Kapila. Reviewed by Hari Babu, Masao Fujii,
Boszormenyi Zoltan, Andres Freund, Greg Smith and others.
parent dba5a9dd
...@@ -158,6 +158,19 @@ SET ENABLE_SEQSCAN TO OFF; ...@@ -158,6 +158,19 @@ SET ENABLE_SEQSCAN TO OFF;
require superuser permission to change via <command>SET</command> or require superuser permission to change via <command>SET</command> or
<command>ALTER</>. <command>ALTER</>.
</para> </para>
<para>
Another way to change configuration parameters persistently is by
use of <xref linkend="SQL-ALTERSYSTEM">
command, for example:
<screen>
ALTER SYSTEM SET checkpoint_timeout TO 600;
</screen>
This command will allow users to change values persistently
through SQL command. The values will be effective after reload of server configuration
(<acronym>SIGHUP</>) or server startup. The effect of this command is similar to when
user manually changes values in <filename>postgresql.conf</filename>.
</para>
</sect2> </sect2>
<sect2 id="config-setting-examining"> <sect2 id="config-setting-examining">
......
...@@ -30,6 +30,7 @@ Complete list of usable sgml source files in this directory. ...@@ -30,6 +30,7 @@ Complete list of usable sgml source files in this directory.
<!ENTITY alterSchema SYSTEM "alter_schema.sgml"> <!ENTITY alterSchema SYSTEM "alter_schema.sgml">
<!ENTITY alterServer SYSTEM "alter_server.sgml"> <!ENTITY alterServer SYSTEM "alter_server.sgml">
<!ENTITY alterSequence SYSTEM "alter_sequence.sgml"> <!ENTITY alterSequence SYSTEM "alter_sequence.sgml">
<!ENTITY alterSystem SYSTEM "alter_system.sgml">
<!ENTITY alterTable SYSTEM "alter_table.sgml"> <!ENTITY alterTable SYSTEM "alter_table.sgml">
<!ENTITY alterTableSpace SYSTEM "alter_tablespace.sgml"> <!ENTITY alterTableSpace SYSTEM "alter_tablespace.sgml">
<!ENTITY alterTSConfig SYSTEM "alter_tsconfig.sgml"> <!ENTITY alterTSConfig SYSTEM "alter_tsconfig.sgml">
......
<!--
doc/src/sgml/ref/alter_system.sgml
PostgreSQL documentation
-->
<refentry id="SQL-ALTERSYSTEM">
<refmeta>
<refentrytitle>ALTER SYSTEM</refentrytitle>
<manvolnum>7</manvolnum>
<refmiscinfo>SQL - Language Statements</refmiscinfo>
</refmeta>
<refnamediv>
<refname>ALTER SYSTEM</refname>
<refpurpose>change a server configuration parameter</refpurpose>
</refnamediv>
<indexterm zone="sql-altersystem">
<primary>ALTER SYSTEM</primary>
</indexterm>
<refsynopsisdiv>
<synopsis>
ALTER SYSTEM SET <replaceable class="PARAMETER">configuration_parameter</replaceable> { TO | = } { <replaceable class="PARAMETER">value</replaceable> | '<replaceable class="PARAMETER">value</replaceable>' | DEFAULT }
</synopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<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
server start based on the type of configuration parameter modified.
</para>
<para>
This command is not allowed inside transaction block or function.
</para>
<para>
See <xref linkend="config-setting"> for other ways to set the parameters and
how they become effective.
</para>
</refsect1>
<refsect1>
<title>Parameters</title>
<variablelist>
<varlistentry>
<term><replaceable class="parameter">configuration_parameter</replaceable></term>
<listitem>
<para>
Name of a settable run-time parameter. Available parameters are
documented in <xref linkend="runtime-config">.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="parameter">value</replaceable></term>
<listitem>
<para>
New value of parameter. Values can be specified as string
constants, identifiers, numbers, or comma-separated lists of
these, as appropriate for the particular parameter.
<literal>DEFAULT</literal> can be written to specify to remove the
parameter and its value from <filename>postgresql.auto.conf</filename>
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>
Set the <literal>wal_level</>:
<programlisting>
ALTER SYSTEM SET wal_level = hot_standby;
</programlisting>
</para>
<para>
Set the <literal>authentication_timeout</>:
<programlisting>
ALTER SYSTEM SET authentication_timeout = 10;
</programlisting></para>
</refsect1>
<refsect1>
<title>Compatibility</title>
<para>
The <command>ALTER SYSTEM</command> statement is a
<productname>PostgreSQL</productname> extension.
</para>
</refsect1>
<refsect1>
<title>See Also</title>
<simplelist type="inline">
<member><xref linkend="SQL-SET"></member>
<member><xref linkend="SQL-SHOW"></member>
</simplelist>
</refsect1>
</refentry>
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
&alterSchema; &alterSchema;
&alterSequence; &alterSequence;
&alterServer; &alterServer;
&alterSystem;
&alterTable; &alterTable;
&alterTableSpace; &alterTableSpace;
&alterTSConfig; &alterTSConfig;
......
...@@ -125,6 +125,12 @@ Item ...@@ -125,6 +125,12 @@ Item
<entry>Subdirectory containing WAL (Write Ahead Log) files</entry> <entry>Subdirectory containing WAL (Write Ahead Log) files</entry>
</row> </row>
<row>
<entry><filename>postgresql.auto.conf</></entry>
<entry>A file used for storing configuration parameters that are set by
<command>ALTER SYSTEM</command></entry>
</row>
<row> <row>
<entry><filename>postmaster.opts</></entry> <entry><filename>postmaster.opts</></entry>
<entry>A file recording the command-line options the server was <entry>A file recording the command-line options the server was
......
...@@ -3292,6 +3292,16 @@ _copyReplicaIdentityStmt(const ReplicaIdentityStmt *from) ...@@ -3292,6 +3292,16 @@ _copyReplicaIdentityStmt(const ReplicaIdentityStmt *from)
return newnode; return newnode;
} }
static AlterSystemStmt *
_copyAlterSystemStmt(const AlterSystemStmt * from)
{
AlterSystemStmt *newnode = makeNode(AlterSystemStmt);
COPY_NODE_FIELD(setstmt);
return newnode;
}
static CreateSeqStmt * static CreateSeqStmt *
_copyCreateSeqStmt(const CreateSeqStmt *from) _copyCreateSeqStmt(const CreateSeqStmt *from)
{ {
...@@ -4368,6 +4378,9 @@ copyObject(const void *from) ...@@ -4368,6 +4378,9 @@ copyObject(const void *from)
case T_ReplicaIdentityStmt: case T_ReplicaIdentityStmt:
retval = _copyReplicaIdentityStmt(from); retval = _copyReplicaIdentityStmt(from);
break; break;
case T_AlterSystemStmt:
retval = _copyAlterSystemStmt(from);
break;
case T_CreateSeqStmt: case T_CreateSeqStmt:
retval = _copyCreateSeqStmt(from); retval = _copyCreateSeqStmt(from);
break; break;
......
...@@ -1546,6 +1546,15 @@ _equalReplicaIdentityStmt(const ReplicaIdentityStmt *a, const ReplicaIdentityStm ...@@ -1546,6 +1546,15 @@ _equalReplicaIdentityStmt(const ReplicaIdentityStmt *a, const ReplicaIdentityStm
return true; return true;
} }
static bool
_equalAlterSystemStmt(const AlterSystemStmt * a, const AlterSystemStmt * b)
{
COMPARE_NODE_FIELD(setstmt);
return true;
}
static bool static bool
_equalCreateSeqStmt(const CreateSeqStmt *a, const CreateSeqStmt *b) _equalCreateSeqStmt(const CreateSeqStmt *a, const CreateSeqStmt *b)
{ {
...@@ -2838,6 +2847,9 @@ equal(const void *a, const void *b) ...@@ -2838,6 +2847,9 @@ equal(const void *a, const void *b)
case T_ReplicaIdentityStmt: case T_ReplicaIdentityStmt:
retval = _equalReplicaIdentityStmt(a, b); retval = _equalReplicaIdentityStmt(a, b);
break; break;
case T_AlterSystemStmt:
retval = _equalAlterSystemStmt(a, b);
break;
case T_CreateSeqStmt: case T_CreateSeqStmt:
retval = _equalCreateSeqStmt(a, b); retval = _equalCreateSeqStmt(a, b);
break; break;
......
...@@ -216,7 +216,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); ...@@ -216,7 +216,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
AlterEventTrigStmt AlterEventTrigStmt
AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt
AlterFdwStmt AlterForeignServerStmt AlterGroupStmt AlterFdwStmt AlterForeignServerStmt AlterGroupStmt
AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterSystemStmt AlterTableStmt
AlterExtensionStmt AlterExtensionContentsStmt AlterForeignTableStmt AlterExtensionStmt AlterExtensionContentsStmt AlterForeignTableStmt
AlterCompositeTypeStmt AlterUserStmt AlterUserMappingStmt AlterUserSetStmt AlterCompositeTypeStmt AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
AlterRoleStmt AlterRoleSetStmt AlterRoleStmt AlterRoleSetStmt
...@@ -397,7 +397,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); ...@@ -397,7 +397,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <istmt> insert_rest %type <istmt> insert_rest
%type <vsetstmt> set_rest set_rest_more SetResetClause FunctionSetResetClause %type <vsetstmt> generic_set set_rest set_rest_more SetResetClause FunctionSetResetClause
%type <node> TableElement TypedTableElement ConstraintElem TableFuncElement %type <node> TableElement TypedTableElement ConstraintElem TableFuncElement
%type <node> columnDef columnOptions %type <node> columnDef columnOptions
...@@ -724,6 +724,7 @@ stmt : ...@@ -724,6 +724,7 @@ stmt :
| AlterObjectSchemaStmt | AlterObjectSchemaStmt
| AlterOwnerStmt | AlterOwnerStmt
| AlterSeqStmt | AlterSeqStmt
| AlterSystemStmt
| AlterTableStmt | AlterTableStmt
| AlterCompositeTypeStmt | AlterCompositeTypeStmt
| AlterRoleSetStmt | AlterRoleSetStmt
...@@ -1333,7 +1334,7 @@ set_rest: ...@@ -1333,7 +1334,7 @@ set_rest:
| set_rest_more | set_rest_more
; ;
set_rest_more: /* Generic SET syntaxes: */ generic_set:
var_name TO var_list var_name TO var_list
{ {
VariableSetStmt *n = makeNode(VariableSetStmt); VariableSetStmt *n = makeNode(VariableSetStmt);
...@@ -1364,6 +1365,9 @@ set_rest_more: /* Generic SET syntaxes: */ ...@@ -1364,6 +1365,9 @@ set_rest_more: /* Generic SET syntaxes: */
n->name = $1; n->name = $1;
$$ = n; $$ = n;
} }
set_rest_more: /* Generic SET syntaxes: */
generic_set {$$ = $1;}
| var_name FROM CURRENT_P | var_name FROM CURRENT_P
{ {
VariableSetStmt *n = makeNode(VariableSetStmt); VariableSetStmt *n = makeNode(VariableSetStmt);
...@@ -8310,6 +8314,23 @@ DropdbStmt: DROP DATABASE database_name ...@@ -8310,6 +8314,23 @@ DropdbStmt: DROP DATABASE database_name
; ;
/*****************************************************************************
*
* ALTER SYSTEM SET
*
* This is used to change configuration parameters persistently.
*****************************************************************************/
AlterSystemStmt:
ALTER SYSTEM_P SET generic_set
{
AlterSystemStmt *n = makeNode(AlterSystemStmt);
n->setstmt = $4;
$$ = (Node *)n;
}
;
/***************************************************************************** /*****************************************************************************
* *
* Manipulate a domain * Manipulate a domain
......
...@@ -811,6 +811,13 @@ sendDir(char *path, int basepathlen, bool sizeonly) ...@@ -811,6 +811,13 @@ sendDir(char *path, int basepathlen, bool sizeonly)
strlen(PG_TEMP_FILE_PREFIX)) == 0) strlen(PG_TEMP_FILE_PREFIX)) == 0)
continue; continue;
/* skip auto conf temporary file */
if (strncmp(de->d_name,
PG_AUTOCONF_FILENAME ".temp",
sizeof(PG_AUTOCONF_FILENAME) + 4) == 0)
continue;
/* /*
* If there's a backup_label file, it belongs to a backup started by * If there's a backup_label file, it belongs to a backup started by
* the user with pg_start_backup(). It is *not* correct for this * the user with pg_start_backup(). It is *not* correct for this
......
...@@ -687,6 +687,11 @@ standard_ProcessUtility(Node *parsetree, ...@@ -687,6 +687,11 @@ standard_ProcessUtility(Node *parsetree,
ExplainQuery((ExplainStmt *) parsetree, queryString, params, dest); ExplainQuery((ExplainStmt *) parsetree, queryString, params, dest);
break; break;
case T_AlterSystemStmt:
PreventTransactionChain(isTopLevel, "ALTER SYSTEM");
AlterSystemSetConfigFile((AlterSystemStmt *) parsetree);
break;
case T_VariableSetStmt: case T_VariableSetStmt:
ExecSetVariableStmt((VariableSetStmt *) parsetree, isTopLevel); ExecSetVariableStmt((VariableSetStmt *) parsetree, isTopLevel);
break; break;
...@@ -2157,6 +2162,10 @@ CreateCommandTag(Node *parsetree) ...@@ -2157,6 +2162,10 @@ CreateCommandTag(Node *parsetree)
tag = "REFRESH MATERIALIZED VIEW"; tag = "REFRESH MATERIALIZED VIEW";
break; break;
case T_AlterSystemStmt:
tag = "ALTER SYSTEM";
break;
case T_VariableSetStmt: case T_VariableSetStmt:
switch (((VariableSetStmt *) parsetree)->kind) switch (((VariableSetStmt *) parsetree)->kind)
{ {
...@@ -2726,6 +2735,10 @@ GetCommandLogLevel(Node *parsetree) ...@@ -2726,6 +2735,10 @@ GetCommandLogLevel(Node *parsetree)
lev = LOGSTMT_DDL; lev = LOGSTMT_DDL;
break; break;
case T_AlterSystemStmt:
lev = LOGSTMT_ALL;
break;
case T_VariableSetStmt: case T_VariableSetStmt:
lev = LOGSTMT_ALL; lev = LOGSTMT_ALL;
break; break;
......
...@@ -120,6 +120,9 @@ ProcessConfigFile(GucContext context) ...@@ -120,6 +120,9 @@ ProcessConfigFile(GucContext context)
*head, *head,
*tail; *tail;
int i; int i;
char ConfigAutoFileName[MAXPGPATH];
char *ErrorConfFile;
char *CallingFileName;
/* /*
* Config files are processed on startup (by the postmaster only) * Config files are processed on startup (by the postmaster only)
...@@ -134,6 +137,8 @@ ProcessConfigFile(GucContext context) ...@@ -134,6 +137,8 @@ ProcessConfigFile(GucContext context)
*/ */
elevel = IsUnderPostmaster ? DEBUG2 : LOG; elevel = IsUnderPostmaster ? DEBUG2 : LOG;
ErrorConfFile = ConfigFileName;
/* Parse the file into a list of option names and values */ /* Parse the file into a list of option names and values */
head = tail = NULL; head = tail = NULL;
...@@ -144,6 +149,26 @@ ProcessConfigFile(GucContext context) ...@@ -144,6 +149,26 @@ ProcessConfigFile(GucContext context)
goto cleanup_list; goto cleanup_list;
} }
/*
* Parse postgresql.auto.conf file after postgresql.conf to replace
* parameters set by ALTER SYSTEM command. This file is present in
* data directory, however when called during initdb data directory is not
* set till this point, so use ConfigFile path which will be same.
*/
snprintf(ConfigAutoFileName,sizeof(ConfigAutoFileName),"%s", PG_AUTOCONF_FILENAME);
if (data_directory)
CallingFileName = NULL;
else
CallingFileName = ConfigFileName;
if (!ParseConfigFile(ConfigAutoFileName, CallingFileName, false, 0, elevel, &head, &tail))
{
/* Syntax error(s) detected in the file, so bail out */
error = true;
ErrorConfFile = ConfigAutoFileName;
goto cleanup_list;
}
/* /*
* Mark all extant GUC variables as not present in the config file. * 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 * We need this so that we can tell below which ones have been removed
...@@ -192,6 +217,7 @@ ProcessConfigFile(GucContext context) ...@@ -192,6 +217,7 @@ ProcessConfigFile(GucContext context)
item->name, item->name,
item->filename, item->sourceline))); item->filename, item->sourceline)));
error = true; error = true;
ErrorConfFile = item->filename;
} }
} }
...@@ -318,7 +344,10 @@ ProcessConfigFile(GucContext context) ...@@ -318,7 +344,10 @@ ProcessConfigFile(GucContext context)
} }
} }
else if (scres == 0) else if (scres == 0)
{
error = true; error = true;
ErrorConfFile = item->filename;
}
/* else no error but variable's active value was not changed */ /* else no error but variable's active value was not changed */
/* /*
...@@ -348,17 +377,17 @@ ProcessConfigFile(GucContext context) ...@@ -348,17 +377,17 @@ ProcessConfigFile(GucContext context)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_CONFIG_FILE_ERROR), (errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("configuration file \"%s\" contains errors", errmsg("configuration file \"%s\" contains errors",
ConfigFileName))); ErrorConfFile)));
else if (apply) else if (apply)
ereport(elevel, ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR), (errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("configuration file \"%s\" contains errors; unaffected changes were applied", errmsg("configuration file \"%s\" contains errors; unaffected changes were applied",
ConfigFileName))); ErrorConfFile)));
else else
ereport(elevel, ereport(elevel,
(errcode(ERRCODE_CONFIG_FILE_ERROR), (errcode(ERRCODE_CONFIG_FILE_ERROR),
errmsg("configuration file \"%s\" contains errors; no changes were applied", errmsg("configuration file \"%s\" contains errors; no changes were applied",
ConfigFileName))); ErrorConfFile)));
} }
} }
......
This diff is collapsed.
...@@ -1228,6 +1228,7 @@ setup_config(void) ...@@ -1228,6 +1228,7 @@ setup_config(void)
char repltok[MAXPGPATH]; char repltok[MAXPGPATH];
char path[MAXPGPATH]; char path[MAXPGPATH];
const char *default_timezone; const char *default_timezone;
char *autoconflines[3];
fputs(_("creating configuration files ... "), stdout); fputs(_("creating configuration files ... "), stdout);
fflush(stdout); fflush(stdout);
...@@ -1320,6 +1321,21 @@ setup_config(void) ...@@ -1320,6 +1321,21 @@ setup_config(void)
writefile(path, conflines); writefile(path, conflines);
chmod(path, S_IRUSR | S_IWUSR); chmod(path, S_IRUSR | S_IWUSR);
/*
* create the automatic configuration file to store the configuration
* parameters set by ALTER SYSTEM command. The parameters present in this
* file will override the value of parameters that exists before parse of
* this file.
*/
autoconflines[0] = pg_strdup("# Do not edit this file manually! \n");
autoconflines[1] = pg_strdup("# It will be overwritten by the ALTER SYSTEM command. \n");
autoconflines[2] = NULL;
sprintf(path, "%s/%s", pg_data, PG_AUTOCONF_FILENAME);
writefile(path, autoconflines);
chmod(path, S_IRUSR | S_IWUSR);
free(conflines); free(conflines);
......
...@@ -363,6 +363,7 @@ typedef enum NodeTag ...@@ -363,6 +363,7 @@ typedef enum NodeTag
T_AlterEventTrigStmt, T_AlterEventTrigStmt,
T_RefreshMatViewStmt, T_RefreshMatViewStmt,
T_ReplicaIdentityStmt, T_ReplicaIdentityStmt,
T_AlterSystemStmt,
/* /*
* TAGS FOR PARSE TREE NODES (parsenodes.h) * TAGS FOR PARSE TREE NODES (parsenodes.h)
......
...@@ -2471,6 +2471,16 @@ typedef struct DropdbStmt ...@@ -2471,6 +2471,16 @@ typedef struct DropdbStmt
bool missing_ok; /* skip error if db is missing? */ bool missing_ok; /* skip error if db is missing? */
} DropdbStmt; } DropdbStmt;
/* ----------------------
* Alter System Statement
* ----------------------
*/
typedef struct AlterSystemStmt
{
NodeTag type;
VariableSetStmt *setstmt; /* SET subcommand */
} AlterSystemStmt;
/* ---------------------- /* ----------------------
* Cluster Statement (support pbrown's cluster index implementation) * Cluster Statement (support pbrown's cluster index implementation)
* ---------------------- * ----------------------
......
...@@ -292,3 +292,10 @@ ...@@ -292,3 +292,10 @@
/* #define HEAPDEBUGALL */ /* #define HEAPDEBUGALL */
/* #define ACLDEBUG */ /* #define ACLDEBUG */
/* #define RTDEBUG */ /* #define RTDEBUG */
/*
* Automatic configuration file name for ALTER SYSTEM.
* This file will be used to store values of configuration parameters
* set by ALTER SYSTEM command
*/
#define PG_AUTOCONF_FILENAME "postgresql.auto.conf"
...@@ -81,6 +81,7 @@ typedef enum LWLockId ...@@ -81,6 +81,7 @@ typedef enum LWLockId
SyncRepLock, SyncRepLock,
BackgroundWorkerLock, BackgroundWorkerLock,
DynamicSharedMemoryControlLock, DynamicSharedMemoryControlLock,
AutoFileLock,
/* Individual lock IDs end here */ /* Individual lock IDs end here */
FirstBufMappingLock, FirstBufMappingLock,
FirstLockMgrLock = FirstBufMappingLock + NUM_BUFFER_PARTITIONS, FirstLockMgrLock = FirstBufMappingLock + NUM_BUFFER_PARTITIONS,
......
...@@ -326,6 +326,7 @@ extern bool parse_real(const char *value, double *result); ...@@ -326,6 +326,7 @@ extern bool parse_real(const char *value, double *result);
extern int set_config_option(const char *name, const char *value, extern int set_config_option(const char *name, const char *value,
GucContext context, GucSource source, GucContext context, GucSource source,
GucAction action, bool changeVal, int elevel); GucAction action, bool changeVal, int elevel);
extern void AlterSystemSetConfigFile(AlterSystemStmt * setstmt);
extern char *GetConfigOptionByName(const char *name, const char **varname); extern char *GetConfigOptionByName(const char *name, const char **varname);
extern void GetConfigOptionByNum(int varnum, const char **values, bool *noshow); extern void GetConfigOptionByNum(int varnum, const char **values, bool *noshow);
extern int GetNumConfigOptions(void); extern int GetNumConfigOptions(void);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment