*** a/doc/src/sgml/config.sgml
--- b/doc/src/sgml/config.sgml
***************
*** 158,163 **** SET ENABLE_SEQSCAN TO OFF;
--- 158,176 ----
       require superuser permission to change via <command>SET</command> or
       <command>ALTER</>.
      </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 id="config-setting-examining">
*** a/doc/src/sgml/ref/allfiles.sgml
--- b/doc/src/sgml/ref/allfiles.sgml
***************
*** 30,35 **** Complete list of usable sgml source files in this directory.
--- 30,36 ----
  <!ENTITY alterSchema        SYSTEM "alter_schema.sgml">
  <!ENTITY alterServer        SYSTEM "alter_server.sgml">
  <!ENTITY alterSequence      SYSTEM "alter_sequence.sgml">
+ <!ENTITY alterSystem        SYSTEM "alter_system.sgml">
  <!ENTITY alterTable         SYSTEM "alter_table.sgml">
  <!ENTITY alterTableSpace    SYSTEM "alter_tablespace.sgml">
  <!ENTITY alterTSConfig      SYSTEM "alter_tsconfig.sgml">
*** /dev/null
--- b/doc/src/sgml/ref/alter_system.sgml
***************
*** 0 ****
--- 1,114 ----
+ <!--
+ 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>
*** a/doc/src/sgml/reference.sgml
--- b/doc/src/sgml/reference.sgml
***************
*** 58,63 ****
--- 58,64 ----
     &alterSchema;
     &alterSequence;
     &alterServer;
+    &alterSystem;
     &alterTable;
     &alterTableSpace;
     &alterTSConfig;
*** a/doc/src/sgml/storage.sgml
--- b/doc/src/sgml/storage.sgml
***************
*** 34,40 **** these required items, the cluster configuration files
  <filename>postgresql.conf</filename>, <filename>pg_hba.conf</filename>, and
  <filename>pg_ident.conf</filename> are traditionally stored in
  <varname>PGDATA</> (although in <productname>PostgreSQL</productname> 8.0 and
! later, it is possible to place them elsewhere).
  </para>
  
  <table tocentry="1" id="pgdata-contents-table">
--- 34,41 ----
  <filename>postgresql.conf</filename>, <filename>pg_hba.conf</filename>, and
  <filename>pg_ident.conf</filename> are traditionally stored in
  <varname>PGDATA</> (although in <productname>PostgreSQL</productname> 8.0 and
! later, it is possible to place them elsewhere). By default directory config is stored
! in <varname>PGDATA</>, however it needs to be kept along with <filename>postgresql.conf</filename>.
  </para>
  
  <table tocentry="1" id="pgdata-contents-table">
***************
*** 57,62 **** Item
--- 58,68 ----
  </row>
  
  <row>
+  <entry><filename>config</></entry>
+  <entry>Subdirectory containing generated configuration files</entry>
+ </row>
+ 
+ <row>
   <entry><filename>base</></entry>
   <entry>Subdirectory containing per-database subdirectories</entry>
  </row>
***************
*** 253,258 **** where <replaceable>PPP</> is the PID of the owning backend and
--- 259,269 ----
  <replaceable>NNN</> distinguishes different temporary files of that backend.
  </para>
  
+ <para>
+ Configuration variables changed by command <acronym>ALTER SYSTEM</> will be stored in
+ <varname>PGDATA</><filename>/config</>.
+ </para>
+ 
  </sect1>
  
  <sect1 id="storage-toast">
*** a/src/backend/nodes/copyfuncs.c
--- b/src/backend/nodes/copyfuncs.c
***************
*** 3247,3252 **** _copyRefreshMatViewStmt(const RefreshMatViewStmt *from)
--- 3247,3262 ----
  	return newnode;
  }
  
+ static AlterSystemStmt *
+ _copyAlterSystemStmt(const AlterSystemStmt * from)
+ {
+ 	AlterSystemStmt *newnode = makeNode(AlterSystemStmt);
+ 
+ 	COPY_NODE_FIELD(setstmt);
+ 
+ 	return newnode;
+ }
+ 
  static CreateSeqStmt *
  _copyCreateSeqStmt(const CreateSeqStmt *from)
  {
***************
*** 4320,4325 **** copyObject(const void *from)
--- 4330,4338 ----
  		case T_RefreshMatViewStmt:
  			retval = _copyRefreshMatViewStmt(from);
  			break;
+ 		case T_AlterSystemStmt:
+ 			retval = _copyAlterSystemStmt(from);
+ 			break;
  		case T_CreateSeqStmt:
  			retval = _copyCreateSeqStmt(from);
  			break;
*** a/src/backend/nodes/equalfuncs.c
--- b/src/backend/nodes/equalfuncs.c
***************
*** 1528,1533 **** _equalRefreshMatViewStmt(const RefreshMatViewStmt *a, const RefreshMatViewStmt *
--- 1528,1542 ----
  }
  
  static bool
+ _equalAlterSystemStmt(const AlterSystemStmt * a, const AlterSystemStmt * b)
+ {
+ 	COMPARE_NODE_FIELD(setstmt);
+ 
+ 	return true;
+ }
+ 
+ 
+ static bool
  _equalCreateSeqStmt(const CreateSeqStmt *a, const CreateSeqStmt *b)
  {
  	COMPARE_NODE_FIELD(sequence);
***************
*** 2790,2795 **** equal(const void *a, const void *b)
--- 2799,2807 ----
  		case T_RefreshMatViewStmt:
  			retval = _equalRefreshMatViewStmt(a, b);
  			break;
+ 		case T_AlterSystemStmt:
+ 			retval = _equalAlterSystemStmt(a, b);
+ 			break;
  		case T_CreateSeqStmt:
  			retval = _equalCreateSeqStmt(a, b);
  			break;
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 216,222 **** static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
  		AlterEventTrigStmt
  		AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt
  		AlterFdwStmt AlterForeignServerStmt AlterGroupStmt
! 		AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
  		AlterExtensionStmt AlterExtensionContentsStmt AlterForeignTableStmt
  		AlterCompositeTypeStmt AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
  		AlterRoleStmt AlterRoleSetStmt
--- 216,222 ----
  		AlterEventTrigStmt
  		AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterEnumStmt
  		AlterFdwStmt AlterForeignServerStmt AlterGroupStmt
! 		AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterSystemStmt AlterTableStmt
  		AlterExtensionStmt AlterExtensionContentsStmt AlterForeignTableStmt
  		AlterCompositeTypeStmt AlterUserStmt AlterUserMappingStmt AlterUserSetStmt
  		AlterRoleStmt AlterRoleSetStmt
***************
*** 395,401 **** static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
  
  %type <istmt>	insert_rest
  
! %type <vsetstmt> set_rest set_rest_more SetResetClause FunctionSetResetClause
  
  %type <node>	TableElement TypedTableElement ConstraintElem TableFuncElement
  %type <node>	columnDef columnOptions
--- 395,401 ----
  
  %type <istmt>	insert_rest
  
! %type <vsetstmt> generic_set set_rest set_rest_more SetResetClause FunctionSetResetClause
  
  %type <node>	TableElement TypedTableElement ConstraintElem TableFuncElement
  %type <node>	columnDef columnOptions
***************
*** 719,724 **** stmt :
--- 719,725 ----
  			| AlterObjectSchemaStmt
  			| AlterOwnerStmt
  			| AlterSeqStmt
+ 			| AlterSystemStmt
  			| AlterTableStmt
  			| AlterCompositeTypeStmt
  			| AlterRoleSetStmt
***************
*** 1328,1334 **** set_rest:
  			| set_rest_more
  			;
  
! set_rest_more:	/* Generic SET syntaxes: */
  			var_name TO var_list
  				{
  					VariableSetStmt *n = makeNode(VariableSetStmt);
--- 1329,1335 ----
  			| set_rest_more
  			;
  
! generic_set:
  			var_name TO var_list
  				{
  					VariableSetStmt *n = makeNode(VariableSetStmt);
***************
*** 1359,1364 **** set_rest_more:	/* Generic SET syntaxes: */
--- 1360,1368 ----
  					n->name = $1;
  					$$ = n;
  				}
+ 
+ set_rest_more:	/* Generic SET syntaxes: */
+ 			generic_set 						{$$ = $1;}
  			| var_name FROM CURRENT_P
  				{
  					VariableSetStmt *n = makeNode(VariableSetStmt);
***************
*** 8242,8247 **** DropdbStmt: DROP DATABASE database_name
--- 8246,8268 ----
  
  /*****************************************************************************
   *
+  *		ALTER SYSTEM SET
+  *
+  * Command to edit postgresql.conf
+  *****************************************************************************/
+ 
+ AlterSystemStmt:
+ 			ALTER SYSTEM_P SET generic_set
+ 				{
+ 					AlterSystemStmt *n = makeNode(AlterSystemStmt);
+ 					n->setstmt = $4;
+ 					$$ = (Node *)n;
+ 				}
+ 		;
+ 
+ 
+ /*****************************************************************************
+  *
   * Manipulate a domain
   *
   *****************************************************************************/
*** a/src/backend/replication/basebackup.c
--- b/src/backend/replication/basebackup.c
***************
*** 803,808 **** sendDir(char *path, int basepathlen, bool sizeonly)
--- 803,815 ----
  					strlen(PG_TEMP_FILE_PREFIX)) == 0)
  			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
  		 * the user with pg_start_backup(). It is *not* correct for this
*** a/src/backend/tcop/utility.c
--- b/src/backend/tcop/utility.c
***************
*** 687,692 **** standard_ProcessUtility(Node *parsetree,
--- 687,697 ----
  			ExplainQuery((ExplainStmt *) parsetree, queryString, params, dest);
  			break;
  
+ 		case T_AlterSystemStmt:
+ 			PreventTransactionChain(isTopLevel, "ALTER SYSTEM");
+ 			AlterSystemSetConfigFile((AlterSystemStmt *) parsetree);
+ 			break;
+ 
  		case T_VariableSetStmt:
  			ExecSetVariableStmt((VariableSetStmt *) parsetree);
  			break;
***************
*** 2155,2160 **** CreateCommandTag(Node *parsetree)
--- 2160,2169 ----
  			tag = "REFRESH MATERIALIZED VIEW";
  			break;
  
+ 		case T_AlterSystemStmt:
+ 			tag = "ALTER SYSTEM";
+ 			break;
+ 
  		case T_VariableSetStmt:
  			switch (((VariableSetStmt *) parsetree)->kind)
  			{
***************
*** 2721,2726 **** GetCommandLogLevel(Node *parsetree)
--- 2730,2739 ----
  			lev = LOGSTMT_DDL;
  			break;
  
+ 		case T_AlterSystemStmt:
+ 			lev = LOGSTMT_ALL;
+ 			break;
+ 
  		case T_VariableSetStmt:
  			lev = LOGSTMT_ALL;
  			break;
*** a/src/backend/utils/misc/guc-file.l
--- b/src/backend/utils/misc/guc-file.l
***************
*** 134,139 **** ProcessConfigFile(GucContext context)
--- 134,146 ----
  	 */
  	elevel = IsUnderPostmaster ? DEBUG2 : LOG;
  
+ 	/*
+ 	 * to warn user if postgresql.auto.conf is not accessible
+ 	 * so that he doesn't expect parameters set by ALTER SYSTEM
+ 	 * command will be effective
+ 	 */
+ 	autoconf_errcause = AUTOCONF_DIR_NOT_PARSED;
+ 
  	/* Parse the file into a list of option names and values */
  	head = tail = NULL;
  
***************
*** 144,149 **** ProcessConfigFile(GucContext context)
--- 151,170 ----
  		goto cleanup_list;
  	}
  
+ 	if (autoconf_errcause != AUTOCONF_FILE_ACCESS && context != PGC_SIGHUP)
+ 	{
+ 		if (autoconf_errcause == AUTOCONF_DIR_PARSED)
+ 			ereport(elevel,
+ 				(errmsg("configuration parameters changed with ALTER SYSTEM command will not be effective"),
+ 				errdetail("file \"%s\" containing configuration parameters is not accessible.", PG_AUTOCONF_FILENAME)));
+ 
+ 		else
+ 			ereport(elevel,
+ 			(errmsg("configuration parameters changed with ALTER SYSTEM command will not be effective"),
+ 			errdetail("default include directive for  \"%s\" folder is not present in postgresql.conf", PG_AUTOCONF_DIR)));
+ 
+ 	}
+ 
  	/*
  	 * 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
***************
*** 690,695 **** cleanup:
--- 711,720 ----
  
  /*
   * Read and parse all config files in a subdirectory in alphabetical order
+  *
+  * While parsing, it records if it has parsed postgresql.auto.conf file.
+  * This information can be used after parsing to ensure if the parameters
+  * set by ALTER SYSTEM SET command will be effective.
   */
  bool
  ParseConfigDirectory(const char *includedir,
***************
*** 705,710 **** ParseConfigDirectory(const char *includedir,
--- 730,740 ----
  	int			num_filenames = 0;
  	int			size_filenames = 0;
  	bool		status;
+ 	char 	   *ConfigAutoDir;
+ 	char		ConfigDir[MAXPGPATH];
+ 	char 	   *ConfigAutoFileName;
+ 	char		Filename[MAXPGPATH];
+ 
  
  	directory = AbsoluteConfigLocation(includedir, calling_file);
  	d = AllocateDir(directory);
***************
*** 717,722 **** ParseConfigDirectory(const char *includedir,
--- 747,761 ----
  		return false;
  	}
  
+ 	 /*
+ 	  * remember the accessability of config directory and auto conf file
+ 	  * so that it can be used after parsing for giving warning to user
+ 	  */
+ 	snprintf(ConfigDir,sizeof(ConfigDir),"%s", PG_AUTOCONF_DIR);
+ 	ConfigAutoDir = AbsoluteConfigLocation(ConfigDir, ConfigFileName);
+ 	if (depth == 1 && strcmp(ConfigAutoDir, directory) == 0)
+ 		autoconf_errcause = AUTOCONF_DIR_PARSED;
+ 
  	/*
  	 * Read the directory and put the filenames in an array, so we can sort
  	 * them prior to processing the contents.
***************
*** 744,749 **** ParseConfigDirectory(const char *includedir,
--- 783,793 ----
  		{
  			if (!S_ISDIR(st.st_mode))
  			{
+ 				snprintf(Filename,sizeof(Filename),"%s/%s", PG_AUTOCONF_DIR, PG_AUTOCONF_FILENAME);
+ 				ConfigAutoFileName = AbsoluteConfigLocation(Filename, ConfigFileName);
+ 				if (depth == 1 && strcmp(ConfigAutoFileName, filename) == 0)
+ 					autoconf_errcause = AUTOCONF_FILE_ACCESS;
+ 
  				/* Add file to list, increasing its size in blocks of 32 */
  				if (num_filenames == size_filenames)
  				{
*** a/src/backend/utils/misc/guc.c
--- b/src/backend/utils/misc/guc.c
***************
*** 57,68 ****
--- 57,70 ----
  #include "postmaster/postmaster.h"
  #include "postmaster/syslogger.h"
  #include "postmaster/walwriter.h"
+ #include "port.h"
  #include "replication/syncrep.h"
  #include "replication/walreceiver.h"
  #include "replication/walsender.h"
  #include "storage/bufmgr.h"
  #include "storage/standby.h"
  #include "storage/fd.h"
+ #include "storage/lwlock.h"
  #include "storage/proc.h"
  #include "storage/predicate.h"
  #include "tcop/tcopprot.h"
***************
*** 204,209 **** static char *config_enum_get_options(struct config_enum * record,
--- 206,215 ----
  						const char *prefix, const char *suffix,
  						const char *separator);
  
+ static int validate_conf_option(struct config_generic * record,
+ 					 const char *name, const char *value, int elevel,
+ 					 bool freemem, void *newval, void **newextra);
+ 
  
  /*
   * Options for enum values defined in this module.
***************
*** 3414,3419 **** static void ShowAllGUCConfig(DestReceiver *dest);
--- 3420,3428 ----
  static char *_ShowOption(struct config_generic * record, bool use_units);
  static bool validate_option_array_item(const char *name, const char *value,
  						   bool skipIfNoPermissions);
+ static void write_auto_conf_file(int fd, const char *filename, ConfigVariable **head_p);
+ static void replace_auto_config_value(ConfigVariable **head_p, ConfigVariable **tail_p,
+ 						  char *config_file, char *name, char *value);
  
  
  /*
***************
*** 5176,5181 **** config_enum_get_options(struct config_enum * record, const char *prefix,
--- 5185,5404 ----
  	return retstr.data;
  }
  
+ /*
+  * Validates configuration parameter and value, by calling check hook functions
+  * depending on record's vartype. It validates if the parameter
+  * value given is in range of expected predefined value for that parameter.
+  *
+  * freemem - true indicates memory for newval and newextra will be
+  *			 freed in this function, false indicates it will be freed
+  *			 by caller.
+  * Return value:
+  *	1: the value is valid
+  *	0: the name or value is invalid
+  */
+ int
+ validate_conf_option(struct config_generic * record,
+ 					 const char *name, const char *value, int elevel,
+ 					 bool freemem, void *newval, void **newextra)
+ {
+ 	/*
+ 	 * Validate the value for the passed record, to ensure it is in expected
+ 	 * range.
+ 	 */
+ 	switch (record->vartype)
+ 	{
+ 
+ 		case PGC_BOOL:
+ 			{
+ 				struct config_bool *conf = (struct config_bool *) record;
+ 				bool		tmpnewval;
+ 
+ 				if (newval == NULL)
+ 					newval = &tmpnewval;
+ 
+ 				if (value != NULL)
+ 				{
+ 					if (!parse_bool(value, newval))
+ 					{
+ 						ereport(elevel,
+ 								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ 						  errmsg("parameter \"%s\" requires a Boolean value",
+ 								 name)));
+ 						return 0;
+ 					}
+ 
+ 					if (!call_bool_check_hook(conf, newval, newextra,
+ 											  PGC_S_FILE, elevel))
+ 						return 0;
+ 
+ 					if (*newextra && freemem)
+ 						free(*newextra);
+ 				}
+ 			}
+ 			break;
+ 		case PGC_INT:
+ 			{
+ 				struct config_int *conf = (struct config_int *) record;
+ 				int			tmpnewval;
+ 
+ 				if (newval == NULL)
+ 					newval = &tmpnewval;
+ 
+ 				if (value != NULL)
+ 				{
+ 					const char *hintmsg;
+ 
+ 					if (!parse_int(value, newval, conf->gen.flags, &hintmsg))
+ 					{
+ 						ereport(elevel,
+ 								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ 						 errmsg("invalid value for parameter \"%s\": \"%s\"",
+ 								name, value),
+ 								 hintmsg ? errhint("%s", _(hintmsg)) : 0));
+ 						return 0;
+ 					}
+ 
+ 					if (*((int *) newval) < conf->min || *((int *) newval) > conf->max)
+ 					{
+ 						ereport(elevel,
+ 								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ 								 errmsg("%d is outside the valid range for parameter \"%s\" (%d .. %d)",
+ 							*((int *) newval), name, conf->min, conf->max)));
+ 						return 0;
+ 					}
+ 
+ 					if (!call_int_check_hook(conf, newval, newextra,
+ 											 PGC_S_FILE, elevel))
+ 						return 0;
+ 
+ 					if (*newextra && freemem)
+ 						free(*newextra);
+ 				}
+ 			}
+ 			break;
+ 		case PGC_REAL:
+ 			{
+ 				struct config_real *conf = (struct config_real *) record;
+ 				double		tmpnewval;
+ 
+ 				if (newval == NULL)
+ 					newval = &tmpnewval;
+ 
+ 				if (value != NULL)
+ 				{
+ 					if (!parse_real(value, newval))
+ 					{
+ 						ereport(elevel,
+ 								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ 						  errmsg("parameter \"%s\" requires a numeric value",
+ 								 name)));
+ 						return 0;
+ 					}
+ 
+ 					if (*((double *) newval) < conf->min || *((double *) newval) > conf->max)
+ 					{
+ 						ereport(elevel,
+ 								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ 								 errmsg("%g is outside the valid range for parameter \"%s\" (%g .. %g)",
+ 						 *((double *) newval), name, conf->min, conf->max)));
+ 						return 0;
+ 					}
+ 
+ 					if (!call_real_check_hook(conf, newval, newextra,
+ 											  PGC_S_FILE, elevel))
+ 						return 0;
+ 
+ 					if (*newextra && freemem)
+ 						free(*newextra);
+ 				}
+ 			}
+ 			break;
+ 		case PGC_STRING:
+ 			{
+ 				struct config_string *conf = (struct config_string *) record;
+ 				char	   *tempPtr;
+ 				char	  **tmpnewval = newval;
+ 
+ 				if (newval == NULL)
+ 					tmpnewval = &tempPtr;
+ 
+ 				if (value != NULL)
+ 				{
+ 					/*
+ 					 * The value passed by the caller could be transient, so
+ 					 * we always strdup it.
+ 					 */
+ 					*tmpnewval = guc_strdup(elevel, value);
+ 					if (*tmpnewval == NULL)
+ 						return 0;
+ 
+ 					/*
+ 					 * The only built-in "parsing" check we have is to apply
+ 					 * truncation if GUC_IS_NAME.
+ 					 */
+ 					if (conf->gen.flags & GUC_IS_NAME)
+ 						truncate_identifier(*tmpnewval, strlen(*tmpnewval), true);
+ 
+ 					if (!call_string_check_hook(conf, tmpnewval, newextra,
+ 												PGC_S_FILE, elevel))
+ 					{
+ 						free(*tmpnewval);
+ 						return 0;
+ 					}
+ 
+ 					/* Free the malloc'd data if any */
+ 					if (freemem)
+ 					{
+ 						if (*tmpnewval != NULL)
+ 							free(*tmpnewval);
+ 						if (*newextra != NULL)
+ 							free(*newextra);
+ 					}
+ 				}
+ 			}
+ 			break;
+ 		case PGC_ENUM:
+ 			{
+ 				struct config_enum *conf = (struct config_enum *) record;
+ 				int			tmpnewval;
+ 
+ 				if (newval == NULL)
+ 					newval = &tmpnewval;
+ 
+ 				if (value != NULL)
+ 				{
+ 					if (!config_enum_lookup_by_name(conf, value, newval))
+ 					{
+ 						char	   *hintmsg;
+ 
+ 						hintmsg = config_enum_get_options(conf,
+ 														"Available values: ",
+ 														  ".", ", ");
+ 
+ 						ereport(ERROR,
+ 								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ 						 errmsg("invalid value for parameter \"%s\": \"%s\"",
+ 								name, value),
+ 								 hintmsg ? errhint("%s", _(hintmsg)) : 0));
+ 
+ 						if (hintmsg != NULL)
+ 							pfree(hintmsg);
+ 						return 0;
+ 					}
+ 					if (!call_enum_check_hook(conf, newval, newextra,
+ 											  PGC_S_FILE, LOG))
+ 						return 0;
+ 
+ 					if (*newextra && freemem)
+ 						free(*newextra);
+ 				}
+ 			}
+ 			break;
+ 	}
+ 	return 1;
+ }
+ 
  
  /*
   * Sets option `name' to given value.
***************
*** 5424,5439 **** set_config_option(const char *name, const char *value,
  
  				if (value)
  				{
! 					if (!parse_bool(value, &newval))
! 					{
! 						ereport(elevel,
! 								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 						  errmsg("parameter \"%s\" requires a Boolean value",
! 								 name)));
! 						return 0;
! 					}
! 					if (!call_bool_check_hook(conf, &newval, &newextra,
! 											  source, elevel))
  						return 0;
  				}
  				else if (source == PGC_S_DEFAULT)
--- 5647,5654 ----
  
  				if (value)
  				{
! 					if (!validate_conf_option(record, name, value, elevel,
! 											  false, &newval, &newextra))
  						return 0;
  				}
  				else if (source == PGC_S_DEFAULT)
***************
*** 5517,5544 **** set_config_option(const char *name, const char *value,
  
  				if (value)
  				{
! 					const char *hintmsg;
! 
! 					if (!parse_int(value, &newval, conf->gen.flags, &hintmsg))
! 					{
! 						ereport(elevel,
! 								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 						 errmsg("invalid value for parameter \"%s\": \"%s\"",
! 								name, value),
! 								 hintmsg ? errhint("%s", _(hintmsg)) : 0));
! 						return 0;
! 					}
! 					if (newval < conf->min || newval > conf->max)
! 					{
! 						ereport(elevel,
! 								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 								 errmsg("%d is outside the valid range for parameter \"%s\" (%d .. %d)",
! 										newval, name, conf->min, conf->max)));
! 						return 0;
! 					}
! 					if (!call_int_check_hook(conf, &newval, &newextra,
! 											 source, elevel))
  						return 0;
  				}
  				else if (source == PGC_S_DEFAULT)
  				{
--- 5732,5741 ----
  
  				if (value)
  				{
! 					if (!validate_conf_option(record, name, value, elevel,
! 											  false, &newval, &newextra))
  						return 0;
+ 
  				}
  				else if (source == PGC_S_DEFAULT)
  				{
***************
*** 5621,5645 **** set_config_option(const char *name, const char *value,
  
  				if (value)
  				{
! 					if (!parse_real(value, &newval))
! 					{
! 						ereport(elevel,
! 								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 						  errmsg("parameter \"%s\" requires a numeric value",
! 								 name)));
! 						return 0;
! 					}
! 					if (newval < conf->min || newval > conf->max)
! 					{
! 						ereport(elevel,
! 								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 								 errmsg("%g is outside the valid range for parameter \"%s\" (%g .. %g)",
! 										newval, name, conf->min, conf->max)));
! 						return 0;
! 					}
! 					if (!call_real_check_hook(conf, &newval, &newextra,
! 											  source, elevel))
  						return 0;
  				}
  				else if (source == PGC_S_DEFAULT)
  				{
--- 5818,5827 ----
  
  				if (value)
  				{
! 					if (!validate_conf_option(record, name, value, elevel,
! 											  false, &newval, &newextra))
  						return 0;
+ 
  				}
  				else if (source == PGC_S_DEFAULT)
  				{
***************
*** 5722,5748 **** set_config_option(const char *name, const char *value,
  
  				if (value)
  				{
! 					/*
! 					 * The value passed by the caller could be transient, so
! 					 * we always strdup it.
! 					 */
! 					newval = guc_strdup(elevel, value);
! 					if (newval == NULL)
  						return 0;
  
- 					/*
- 					 * The only built-in "parsing" check we have is to apply
- 					 * truncation if GUC_IS_NAME.
- 					 */
- 					if (conf->gen.flags & GUC_IS_NAME)
- 						truncate_identifier(newval, strlen(newval), true);
- 
- 					if (!call_string_check_hook(conf, &newval, &newextra,
- 												source, elevel))
- 					{
- 						free(newval);
- 						return 0;
- 					}
  				}
  				else if (source == PGC_S_DEFAULT)
  				{
--- 5904,5913 ----
  
  				if (value)
  				{
! 					if (!validate_conf_option(record, name, value, elevel,
! 											  false, &newval, &newextra))
  						return 0;
  
  				}
  				else if (source == PGC_S_DEFAULT)
  				{
***************
*** 5848,5874 **** set_config_option(const char *name, const char *value,
  
  				if (value)
  				{
! 					if (!config_enum_lookup_by_name(conf, value, &newval))
! 					{
! 						char	   *hintmsg;
! 
! 						hintmsg = config_enum_get_options(conf,
! 														"Available values: ",
! 														  ".", ", ");
! 
! 						ereport(elevel,
! 								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 						 errmsg("invalid value for parameter \"%s\": \"%s\"",
! 								name, value),
! 								 hintmsg ? errhint("%s", _(hintmsg)) : 0));
! 
! 						if (hintmsg)
! 							pfree(hintmsg);
! 						return 0;
! 					}
! 					if (!call_enum_check_hook(conf, &newval, &newextra,
! 											  source, elevel))
  						return 0;
  				}
  				else if (source == PGC_S_DEFAULT)
  				{
--- 6013,6022 ----
  
  				if (value)
  				{
! 					if (!validate_conf_option(record, name, value, elevel,
! 											  false, &newval, &newextra))
  						return 0;
+ 
  				}
  				else if (source == PGC_S_DEFAULT)
  				{
***************
*** 6237,6242 **** flatten_set_variable_args(const char *name, List *args)
--- 6385,6705 ----
  	return buf.data;
  }
  
+ /*
+  * Writes updated configuration parameter values into
+  * postgresql.auto.conf.temp file. It traverses the list of parameters
+  * and quote the string values before writing them to temporaray file.
+  */
+ static void
+ write_auto_conf_file(int fd, const char *filename, ConfigVariable **head_p)
+ {
+ 	ConfigVariable *item;
+ 	StringInfoData buf;
+ 
+ 	initStringInfo(&buf);
+ 	appendStringInfoString(&buf, "# Do not edit this file manually! \n");
+ 	appendStringInfoString(&buf, "# It will be overwritten by ALTER SYSTEM command. \n");
+ 
+ 	/*
+ 	 * traverse the list of parameters, quote the string parameter and write
+ 	 * it file. Once all parameters are written fsync the file.
+ 	 */
+ 
+ 	for (item = *head_p; item != NULL; item = item->next)
+ 	{
+ 		char	   *escaped;
+ 
+ 		appendStringInfoString(&buf, item->name);
+ 		appendStringInfoString(&buf, " = ");
+ 
+ 		appendStringInfoString(&buf, "\'");
+ 		escaped = escape_single_quotes_ascii(item->value);
+ 		appendStringInfoString(&buf, escaped);
+ 		free(escaped);
+ 		appendStringInfoString(&buf, "\'");
+ 
+ 		appendStringInfoString(&buf, "\n");
+ 
+ 		if (write(fd, buf.data, buf.len) < 0)
+ 			ereport(ERROR,
+ 					(errmsg("failed to write to \"%s\" file", filename)));
+ 		resetStringInfo(&buf);
+ 	}
+ 
+ 	if (pg_fsync(fd) != 0)
+ 		ereport(ERROR,
+ 				(errcode_for_file_access(),
+ 				 errmsg("could not fsync file \"%s\": %m", filename)));
+ 
+ 	pfree(buf.data);
+ }
+ 
+ 
+ /*
+  * This function takes list of all configuration parameters in postgresql.auto.conf
+  * and parameter to be updated as input arguments and replace the updated
+  * configuration parameter value in a list.
+  * If the parameter to be updated is new then it is appended to the
+  * list of parameters.
+  */
+ static void
+ replace_auto_config_value(ConfigVariable **head_p, ConfigVariable **tail_p,
+ 						  char *config_file,
+ 						  char *name, char *value)
+ {
+ 	ConfigVariable *item,
+ 			   *prev = NULL;
+ 
+ 	if (*head_p != NULL)
+ 	{
+ 		for (item = *head_p; item != NULL; item = item->next)
+ 		{
+ 			if (strcmp(item->name, name) == 0)
+ 			{
+ 				pfree(item->value);
+ 				if (value != NULL)
+ 					/* update the parameter value */
+ 					item->value = pstrdup(value);
+ 				else
+ 				{
+ 					/* delete the configuration parameter from list */
+ 					if (*head_p == item)
+ 						*head_p = item->next;
+ 					else
+ 						prev->next = item->next;
+ 
+ 					if (*tail_p == item)
+ 						*tail_p = prev;
+ 
+ 					pfree(item->name);
+ 					pfree(item->filename);
+ 					pfree(item);
+ 				}
+ 				return;
+ 			}
+ 			prev = item;
+ 		}
+ 	}
+ 
+ 	if (value == NULL)
+ 		return;
+ 
+ 	item = palloc(sizeof *item);
+ 	item->name = pstrdup(name);
+ 	item->value = pstrdup(value);
+ 	item->filename = pstrdup(config_file);
+ 	item->next = NULL;
+ 
+ 	if (*head_p == NULL)
+ 	{
+ 		item->sourceline = 1;
+ 		*head_p = item;
+ 	}
+ 	else
+ 	{
+ 		item->sourceline = (*tail_p)->sourceline + 1;
+ 		(*tail_p)->next = item;
+ 	}
+ 
+ 	*tail_p = item;
+ 
+ 	return;
+ }
+ 
+ 
+ /*
+  * Persist the configuration parameter value.
+  *
+  * 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.
+  *
+  * The configuration parameters are written to a temporary
+  * file then renamed to the final name. The template for the
+  * temporary file is postgresql.auto.conf.temp.
+  *
+  * An LWLock is used to serialize writing to the same file.
+  *
+  * In case of an error, we leave the original automatic
+  * configuration file (postgresql.auto.conf) intact.
+  * A stale temporary file may be left behind in case we crash.
+  * Such files are removed on the next server restart.
+  */
+ void
+ AlterSystemSetConfigFile(AlterSystemStmt * altersysstmt)
+ {
+ 	char	   *name;
+ 	char	   *value;
+ 	int			Tmpfd = -1;
+ 	FILE	   *infile;
+ 	struct config_generic *record;
+ 	ConfigVariable *head = NULL;
+ 	ConfigVariable *tail = NULL;
+ 	char		ConfigFileDir[MAXPGPATH];
+ 	char		AutoConfFileName[MAXPGPATH];
+ 	char		AutoConfTmpFileName[MAXPGPATH];
+ 	struct stat st;
+ 	void	   *newextra = NULL;
+ 
+ 	if (!superuser())
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ 			 (errmsg("must be superuser to execute ALTER SYSTEM command"))));
+ 
+ 	/*
+ 	 * Validate the name and arguments [value1, value2 ... ].
+ 	 */
+ 	name = altersysstmt->setstmt->name;
+ 
+ 	switch (altersysstmt->setstmt->kind)
+ 	{
+ 		case VAR_SET_VALUE:
+ 			value = ExtractSetVariableArgs(altersysstmt->setstmt);
+ 			break;
+ 
+ 		case VAR_SET_DEFAULT:
+ 			value = NULL;
+ 			break;
+ 		default:
+ 			elog(ERROR, "unrecognized alter system stmt type: %d",
+ 				 altersysstmt->setstmt->kind);
+ 			break;
+ 	}
+ 
+ 	record = find_option(name, true, LOG);
+ 	if (record == NULL)
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_UNDEFINED_OBJECT),
+ 			   errmsg("unrecognized configuration parameter \"%s\"", name)));
+ 
+ 	if ((record->context == PGC_INTERNAL) ||
+ 		(record->flags & GUC_DISALLOW_IN_FILE))
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
+ 				 errmsg("parameter \"%s\" cannot be changed",
+ 						name)));
+ 
+ 	if (!validate_conf_option(record, name, value, ERROR,
+ 							  true, NULL, &newextra))
+ 		ereport(ERROR,
+ 		(errmsg("invalid value for parameter \"%s\": \"%s\"", name, value)));
+ 
+ 
+ 	/*
+ 	 * The "config" directory should follow the postgresql.conf file directory
+ 	 * not the data_directory. The same is validated while parsing the
+ 	 * postgresql.conf configuration file. So while framing the name for
+ 	 * postgresql.auto.conf and it's temp file we need to follow the
+ 	 * postgresql.conf file directory.
+ 	 */
+ 	StrNCpy(ConfigFileDir, ConfigFileName, sizeof(ConfigFileDir));
+ 	get_parent_directory(ConfigFileDir);
+ 
+ 	/* Frame config dir, auto conf file and auto conf sample temp file names */
+ 	snprintf(AutoConfFileName, sizeof(AutoConfFileName), "%s/%s/%s",
+ 			 ConfigFileDir,
+ 			 PG_AUTOCONF_DIR,
+ 			 PG_AUTOCONF_FILENAME);
+ 	snprintf(AutoConfTmpFileName, sizeof(AutoConfTmpFileName), "%s/%s/%s.%s",
+ 			 ConfigFileDir,
+ 			 PG_AUTOCONF_DIR,
+ 			 PG_AUTOCONF_FILENAME,
+ 			 "temp");
+ 
+ 	/*
+ 	 * Verify if include_dir for postgresql.auto.conf file exists in
+ 	 * postgresql.conf. If it doesn't exist then warn the user that parameters
+ 	 * changed with this command will not be effective.
+ 	 */
+ 	autoconf_errcause = AUTOCONF_DIR_NOT_PARSED;
+ 
+ 	if (!ParseConfigFile(ConfigFileName, NULL, false, 0, LOG, &head, &tail))
+ 		ereport(ERROR,
+ 				(errmsg("configuration file \"%s\" contains errors; parameters changed by "
+ 					 "this command will not be effective", ConfigFileName)));
+ 
+ 	/*
+ 	 * ignore the list of options as we are intersted to just ensure the
+ 	 * existence of include directive for config folder.
+ 	 */
+ 	head = tail = NULL;
+ 
+ 	if (autoconf_errcause == AUTOCONF_DIR_NOT_PARSED)
+ 		ereport(WARNING,
+ 				(errmsg("configuration parameters changed by this command will not be effective"),
+ 				 errdetail("default include directive for  \"%s\" folder is not present in postgresql.conf", PG_AUTOCONF_DIR)));
+ 
+ 	/*
+ 	 * one backend is allowed to operate on .auto.conf file, to ensure that we
+ 	 * need to update the contents of the file with AutoFileLock. To ensure
+ 	 * crash safety, first the contents are written to temporary file and then
+ 	 * rename it to postgresql.auto.conf
+ 	 */
+ 
+ 	LWLockAcquire(AutoFileLock, LW_EXCLUSIVE);
+ 
+ 	Tmpfd = open(AutoConfTmpFileName, O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
+ 	if (Tmpfd < 0)
+ 		ereport(ERROR,
+ 				(errcode_for_file_access(),
+ 				 errmsg("failed to open auto conf temp file \"%s\": %m ",
+ 						AutoConfTmpFileName)));
+ 
+ 	PG_TRY();
+ 	{
+ 		if (stat(AutoConfFileName, &st) == 0)
+ 		{
+ 			/* open postgresql.auto.conf file */
+ 			infile = AllocateFile(AutoConfFileName, "r");
+ 			if (infile == NULL)
+ 				ereport(ERROR,
+ 						(errmsg("failed to open auto conf file \"%s\": %m ",
+ 								AutoConfFileName)));
+ 
+ 			/* Parse the postgresql.auto.conf file */
+ 			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 postgresql.auto.conf.temp file */
+ 		write_auto_conf_file(Tmpfd, AutoConfTmpFileName, &head);
+ 
+ 		close(Tmpfd);
+ 		Tmpfd = -1;
+ 
+ 		/*
+ 		 * As the rename is atomic operation, if any problem occurs after this
+ 		 * at max it can loose the parameters set by last ALTER SYSTEM
+ 		 * command.
+ 		 */
+ 		if (rename(AutoConfTmpFileName, AutoConfFileName) < 0)
+ 			ereport(ERROR,
+ 					(errcode_for_file_access(),
+ 					 errmsg("could not rename file \"%s\" to \"%s\" : %m",
+ 							AutoConfTmpFileName, AutoConfFileName)));
+ 	}
+ 	PG_CATCH();
+ 	{
+ 		if (Tmpfd >= 0)
+ 			close(Tmpfd);
+ 
+ 		unlink(AutoConfTmpFileName);
+ 		FreeConfigVariables(head);
+ 		PG_RE_THROW();
+ 	}
+ 	PG_END_TRY();
+ 
+ 	FreeConfigVariables(head);
+ 	LWLockRelease(AutoFileLock);
+ 	return;
+ }
  
  /*
   * SET command
*** a/src/backend/utils/misc/postgresql.conf.sample
--- b/src/backend/utils/misc/postgresql.conf.sample
***************
*** 584,589 ****
--- 584,598 ----
  #include_if_exists = 'exists.conf'	# include file only if it exists
  #include = 'special.conf'		# include file
  
+ # This includes the default configuration directory included to support
+ # ALTER SYSTEM statement.
+ #
+ # WARNING: User should not remove below include_dir or directory config,
+ #          as both are required to make ALTER SYSTEM command work.
+ #          Any configuration parameter values specified after this line
+ #          will override the values set by ALTER SYSTEM statement.
+ #include_dir = 'config'
+ 
  
  #------------------------------------------------------------------------------
  # CUSTOMIZED OPTIONS
*** a/src/bin/initdb/initdb.c
--- b/src/bin/initdb/initdb.c
***************
*** 193,199 **** const char *subdirs[] = {
  	"base/1",
  	"pg_tblspc",
  	"pg_stat",
! 	"pg_stat_tmp"
  };
  
  
--- 193,200 ----
  	"base/1",
  	"pg_tblspc",
  	"pg_stat",
! 	"pg_stat_tmp",
! 	PG_AUTOCONF_DIR
  };
  
  
***************
*** 1182,1187 **** setup_config(void)
--- 1183,1190 ----
  	char		repltok[MAXPGPATH];
  	char		path[MAXPGPATH];
  	const char *default_timezone;
+ 	char	  *autoconflines[3];
+ 	char     tempautobuf[256];
  
  	fputs(_("creating configuration files ... "), stdout);
  	fflush(stdout);
***************
*** 1264,1274 **** setup_config(void)
--- 1267,1298 ----
  		conflines = replace_token(conflines, "#log_timezone = 'GMT'", repltok);
  	}
  
+ 	snprintf(repltok, sizeof(repltok), "include_dir = '" PG_AUTOCONF_DIR "'");
+ 	conflines = replace_token(conflines, "#include_dir = 'config'", repltok);
+ 
  	snprintf(path, sizeof(path), "%s/postgresql.conf", pg_data);
  
  	writefile(path, conflines);
  	chmod(path, S_IRUSR | S_IWUSR);
  
+ 	/*
+ 	 * create the automatic configuration file to store the configuration
+ 	 * parameters set by ALTER SYSTEM command. This file will be included in
+ 	 * postgresql.conf and the parameters present in this file will override
+ 	 * the values of parameters that exists before include of this file.
+ 	 */
+ 
+ 	strcpy(tempautobuf,"# Do not edit this file manually! \n");
+ 	autoconflines[0] = pg_strdup(tempautobuf);
+ 	strcpy(tempautobuf,"# It will be overwritten by the ALTER SYSTEM command. \n");
+ 	autoconflines[1] = pg_strdup(tempautobuf);
+ 	autoconflines[2] = NULL;
+ 	
+ 	sprintf(path, "%s/%s/%s", pg_data, PG_AUTOCONF_DIR, PG_AUTOCONF_FILENAME);
+ 
+ 	writefile(path,autoconflines);
+ 	chmod(path, S_IRUSR | S_IWUSR);
+ 
  	free(conflines);
  
  
*** a/src/include/nodes/nodes.h
--- b/src/include/nodes/nodes.h
***************
*** 362,367 **** typedef enum NodeTag
--- 362,368 ----
  	T_CreateEventTrigStmt,
  	T_AlterEventTrigStmt,
  	T_RefreshMatViewStmt,
+ 	T_AlterSystemStmt,
  
  	/*
  	 * TAGS FOR PARSE TREE NODES (parsenodes.h)
*** a/src/include/nodes/parsenodes.h
--- b/src/include/nodes/parsenodes.h
***************
*** 2393,2398 **** typedef struct DropdbStmt
--- 2393,2408 ----
  } DropdbStmt;
  
  /* ----------------------
+  *		Alter System Statement
+  * ----------------------
+  */
+ typedef struct AlterSystemStmt
+ {
+ 	NodeTag		type;
+ 	VariableSetStmt *setstmt;	/* SET subcommand */
+ }	AlterSystemStmt;
+ 
+ /* ----------------------
   *		Cluster Statement (support pbrown's cluster index implementation)
   * ----------------------
   */
*** a/src/include/pg_config_manual.h
--- b/src/include/pg_config_manual.h
***************
*** 281,283 ****
--- 281,290 ----
  /* #define HEAPDEBUGALL */
  /* #define ACLDEBUG */
  /* #define RTDEBUG */
+ 
+ /*
+  * Automatic configuration directory and file name
+  * for ALTER SYSTEM.
+  */
+ #define PG_AUTOCONF_DIR			"config"
+ #define PG_AUTOCONF_FILENAME		"postgresql.auto.conf"
*** a/src/include/storage/lwlock.h
--- b/src/include/storage/lwlock.h
***************
*** 79,84 **** typedef enum LWLockId
--- 79,85 ----
  	SerializablePredicateLockListLock,
  	OldSerXidLock,
  	SyncRepLock,
+ 	AutoFileLock,
  	/* Individual lock IDs end here */
  	FirstBufMappingLock,
  	FirstLockMgrLock = FirstBufMappingLock + NUM_BUFFER_PARTITIONS,
*** a/src/include/utils/guc.h
--- b/src/include/utils/guc.h
***************
*** 167,172 **** typedef enum
--- 167,192 ----
  #define GUC_QUALIFIER_SEPARATOR '.'
  
  /*
+   * Saved info for Auto Config Directory parse error
+   * We have to detect 2 different errors with these 3 enum values
+   * Error's to be detected are
+   * a. include directive for auto conf file is commented/missed from postgresql.conf file
+   * b. file postgresql.auto.conf is not accessible
+   * Before parsing config file initialize autoconf_errcause to AUTOCONF_DIR_NOT_PARSED
+   * During parse, it will set autoconf_errcause to AUTOCONF_DIR_PARSED, if config directory is parsed
+   * and set autoconf_errcause to AUTOCONF_FILE_ACCESS if file postgresql.conf is accessible
+   * After parse based on value of autoconf_errcause, it will distinguish between above 2 errors
+   */
+ typedef enum
+ {
+ 	AUTOCONF_DIR_NOT_PARSED,
+ 	AUTOCONF_DIR_PARSED,
+ 	AUTOCONF_FILE_ACCESS
+ }	AutoConfErrorCause;
+ 
+ AutoConfErrorCause autoconf_errcause;
+ 
+ /*
   * bit values in "flags" of a GUC variable
   */
  #define GUC_LIST_INPUT			0x0001	/* input can be list format */
***************
*** 322,327 **** extern bool parse_real(const char *value, double *result);
--- 342,348 ----
  extern int set_config_option(const char *name, const char *value,
  				  GucContext context, GucSource source,
  				  GucAction action, bool changeVal, 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);
  extern int	GetNumConfigOptions(void);
*** /dev/null
--- b/src/test/regress/expected/alter_system.out
***************
*** 0 ****
--- 1,161 ----
+ -- parameters that can be set after reload of conf file with SIGHUP 
+ ALTER SYSTEM SET authentication_timeout = 10;
+ ALTER SYSTEM SET vacuum_cost_delay To 200;
+ ERROR:  200 is outside the valid range for parameter "vacuum_cost_delay" (0 .. 100)
+ ALTER SYSTEM SET bgwriter_lru_multiplier = 3.2;
+ ALTER SYSTEM SET full_page_writes = off;
+ ALTER SYSTEM SET synchronous_commit To off;
+ ALTER SYSTEM SET synchronous_standby_names = 'standby1, standby2';
+ ALTER SYSTEM SET seq_page_cost = 0.9;
+ ALTER SYSTEM SET autovacuum_naptime To 30;
+ ALTER SYSTEM SET search_path = 'public';
+ ALTER SYSTEM SET default_tablespace = '';
+ ALTER SYSTEM SET checkpoint_timeout = 1;
+ ERROR:  1 is outside the valid range for parameter "checkpoint_timeout" (30 .. 3600)
+ ALTER SYSTEM SET checkpoint_timeout = 3700;
+ ERROR:  3700 is outside the valid range for parameter "checkpoint_timeout" (30 .. 3600)
+ ALTER SYSTEM SET checkpoint_timeout = 90;
+ ALTER SYSTEM SET restart_after_crash TO on;
+ ALTER SYSTEM SET work_mem = '2 MB';
+ -- reload the new configurations.
+ SELECT pg_reload_conf();
+  pg_reload_conf 
+ ----------------
+  t
+ (1 row)
+ 
+ SELECT pg_sleep(1);
+  pg_sleep 
+ ----------
+  
+ (1 row)
+ 
+ SHOW authentication_timeout;
+  authentication_timeout 
+ ------------------------
+  10s
+ (1 row)
+ 
+ SHOW vacuum_cost_delay;
+  vacuum_cost_delay 
+ -------------------
+  0
+ (1 row)
+ 
+ SHOW bgwriter_lru_multiplier;
+  bgwriter_lru_multiplier 
+ -------------------------
+  3.2
+ (1 row)
+ 
+ SHOW full_page_writes;
+  full_page_writes 
+ ------------------
+  off
+ (1 row)
+ 
+ SHOW synchronous_commit;
+  synchronous_commit 
+ --------------------
+  off
+ (1 row)
+ 
+ SHOW synchronous_standby_names;
+  synchronous_standby_names 
+ ---------------------------
+  standby1, standby2
+ (1 row)
+ 
+ SHOW seq_page_cost;
+  seq_page_cost 
+ ---------------
+  0.9
+ (1 row)
+ 
+ SHOW autovacuum_naptime;
+  autovacuum_naptime 
+ --------------------
+  30s
+ (1 row)
+ 
+ SHOW search_path;
+  search_path 
+ -------------
+  public
+ (1 row)
+ 
+ SHOW default_tablespace;
+  default_tablespace 
+ --------------------
+  
+ (1 row)
+ 
+ SHOW checkpoint_timeout;
+  checkpoint_timeout 
+ --------------------
+  90s
+ (1 row)
+ 
+ SHOW restart_after_crash;
+  restart_after_crash 
+ ---------------------
+  on
+ (1 row)
+ 
+ SHOW work_mem;
+  work_mem 
+ ----------
+  2MB
+ (1 row)
+ 
+ -- Reset all parameters which are set above.
+ ALTER SYSTEM SET authentication_timeout To default;
+ ALTER SYSTEM SET vacuum_cost_delay = default;
+ ALTER SYSTEM SET bgwriter_lru_multiplier To default;
+ ALTER SYSTEM SET full_page_writes To default;
+ ALTER SYSTEM SET synchronous_commit = default;
+ ALTER SYSTEM SET synchronous_standby_names To default;
+ ALTER SYSTEM SET seq_page_cost To default;
+ ALTER SYSTEM SET autovacuum_naptime = default;
+ ALTER SYSTEM SET search_path To default;
+ ALTER SYSTEM SET default_tablespace To default;
+ ALTER SYSTEM SET checkpoint_timeout To default;
+ ALTER SYSTEM SET restart_after_crash = default;
+ ALTER SYSTEM SET work_mem = default;
+ SELECT pg_reload_conf();
+  pg_reload_conf 
+ ----------------
+  t
+ (1 row)
+ 
+ SELECT pg_sleep(1);
+  pg_sleep 
+ ----------
+  
+ (1 row)
+ 
+ -- set a configuration parameter inside a function
+ CREATE OR REPLACE FUNCTION change_conf() RETURNS INTEGER as
+ $$
+ begin
+ ALTER SYSTEM SET enable_hashagg=off;
+ return 1;
+ end;
+ $$ Language plpgsql;
+ SELECT change_conf();
+ ERROR:  ALTER SYSTEM cannot be executed from a function or multi-command string
+ CONTEXT:  SQL statement "ALTER SYSTEM SET enable_hashagg=off"
+ PL/pgSQL function change_conf() line 3 at SQL statement
+ drop function change_conf();
+ -- Normal user tries to set configuration parameter
+ create user test password 'test';
+ SET SESSION AUTHORIZATION test;
+ alter system set enable_seqscan=off;
+ ERROR:  must be superuser to execute ALTER SYSTEM command
+ \c -
+ drop user test;
+ -- In a transaction block tries to set configuration parameter
+ start transaction;
+ alter system set enable_hashagg=off;
+ ERROR:  ALTER SYSTEM cannot run inside a transaction block
+ commit;
*** a/src/test/regress/parallel_schedule
--- b/src/test/regress/parallel_schedule
***************
*** 109,111 **** test: plancache limit plpgsql copy2 temp domain rangefuncs prepare without_oid c
--- 109,114 ----
  
  # run stats by itself because its delay may be insufficient under heavy load
  test: stats
+ 
+ # run alter system by itself because it modifies the configuration parameters
+ test: alter_system
*** a/src/test/regress/serial_schedule
--- b/src/test/regress/serial_schedule
***************
*** 139,141 **** test: largeobject
--- 139,142 ----
  test: with
  test: xml
  test: stats
+ test: alter_system
*** /dev/null
--- b/src/test/regress/sql/alter_system.sql
***************
*** 0 ****
--- 1,78 ----
+ -- parameters that can be set after reload of conf file with SIGHUP 
+ ALTER SYSTEM SET authentication_timeout = 10;
+ ALTER SYSTEM SET vacuum_cost_delay To 200;
+ ALTER SYSTEM SET bgwriter_lru_multiplier = 3.2;
+ ALTER SYSTEM SET full_page_writes = off;
+ ALTER SYSTEM SET synchronous_commit To off;
+ ALTER SYSTEM SET synchronous_standby_names = 'standby1, standby2';
+ ALTER SYSTEM SET seq_page_cost = 0.9;
+ ALTER SYSTEM SET autovacuum_naptime To 30;
+ ALTER SYSTEM SET search_path = 'public';
+ ALTER SYSTEM SET default_tablespace = '';
+ ALTER SYSTEM SET checkpoint_timeout = 1;
+ ALTER SYSTEM SET checkpoint_timeout = 3700;
+ ALTER SYSTEM SET checkpoint_timeout = 90;
+ ALTER SYSTEM SET restart_after_crash TO on;
+ ALTER SYSTEM SET work_mem = '2 MB';
+ 
+ -- reload the new configurations.
+ SELECT pg_reload_conf();
+ SELECT pg_sleep(1);
+ 
+ SHOW authentication_timeout;
+ SHOW vacuum_cost_delay;
+ SHOW bgwriter_lru_multiplier;
+ SHOW full_page_writes;
+ SHOW synchronous_commit;
+ SHOW synchronous_standby_names;
+ SHOW seq_page_cost;
+ SHOW autovacuum_naptime;
+ SHOW search_path;
+ SHOW default_tablespace;
+ SHOW checkpoint_timeout;
+ SHOW restart_after_crash;
+ SHOW work_mem;
+ 
+ -- Reset all parameters which are set above.
+ ALTER SYSTEM SET authentication_timeout To default;
+ ALTER SYSTEM SET vacuum_cost_delay = default;
+ ALTER SYSTEM SET bgwriter_lru_multiplier To default;
+ ALTER SYSTEM SET full_page_writes To default;
+ ALTER SYSTEM SET synchronous_commit = default;
+ ALTER SYSTEM SET synchronous_standby_names To default;
+ ALTER SYSTEM SET seq_page_cost To default;
+ ALTER SYSTEM SET autovacuum_naptime = default;
+ ALTER SYSTEM SET search_path To default;
+ ALTER SYSTEM SET default_tablespace To default;
+ ALTER SYSTEM SET checkpoint_timeout To default;
+ ALTER SYSTEM SET restart_after_crash = default;
+ ALTER SYSTEM SET work_mem = default;
+ 
+ SELECT pg_reload_conf();
+ SELECT pg_sleep(1);
+ 
+ -- set a configuration parameter inside a function
+ CREATE OR REPLACE FUNCTION change_conf() RETURNS INTEGER as
+ $$
+ begin
+ ALTER SYSTEM SET enable_hashagg=off;
+ return 1;
+ end;
+ $$ Language plpgsql;
+ 
+ SELECT change_conf();
+ 
+ drop function change_conf();
+ 
+ -- Normal user tries to set configuration parameter
+ create user test password 'test';
+ SET SESSION AUTHORIZATION test;
+ alter system set enable_seqscan=off;
+ \c -
+ drop user test;
+ 
+ -- In a transaction block tries to set configuration parameter
+ start transaction;
+ alter system set enable_hashagg=off;
+ commit;
+ 
