By recent popular request in the ongoing discussion saga around merging the recovery.conf, I've added an "includeifexists" directive to the postgresql.conf in the attached patch. Demo:

$ tail -n 1 $PGDATA/postgresql.conf
include 'missing.conf'
$ pg_ctl start -l $PGLOG
server starting
$ tail -n 2 $PGLOG
LOG: could not open configuration file "/home/gsmith/pgwork/data/include-exists/missing.conf": No such file or directory FATAL: configuration file "/home/gsmith/pgwork/data/include-exists/postgresql.conf" contains errors
$ vi $PGDATA/postgresql.conf
$ tail -n 1 $PGDATA/postgresql.conf
includeifexists 'missing.conf'
$ pg_ctl start -l $PGLOG
server starting
$ tail -n 3 $PGLOG
LOG:  database system was shut down at 2011-11-16 00:17:36 EST
LOG:  database system is ready to accept connections
LOG:  autovacuum launcher started

There might be a cleaner way to write this that eliminates some of the cut and paste duplication between this and the regular include directive. I'm short on clever but full of brute force tonight.

--
Greg Smith   2ndQuadrant US    g...@2ndquadrant.com   Baltimore, MD
PostgreSQL Training, Services, and 24x7 Support  www.2ndQuadrant.us

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index d1e628f..da45ac1 100644
*** a/doc/src/sgml/config.sgml
--- b/doc/src/sgml/config.sgml
*************** include 'filename'
*** 91,96 ****
--- 91,107 ----
  
     <para>
      <indexterm>
+      <primary><literal>includeifexists</></primary>
+      <secondary>in configuration file</secondary>
+     </indexterm>
+     Use the same approach as the <literal>include</> directive, continuing
+     normally if the file does not exist.  A regular <literal>include</>
+     will stop with an error if the referenced file is missing, while
+     <literal>includeifexists</> does not.
+    </para>
+ 
+    <para>
+     <indexterm>
       <primary>SIGHUP</primary>
      </indexterm>
      The configuration file is reread whenever the main server process receives a
diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l
index a094c7a..6f26421 100644
*** a/src/backend/utils/misc/guc-file.l
--- b/src/backend/utils/misc/guc-file.l
*************** ProcessConfigFile(GucContext context)
*** 129,135 ****
  	/* Parse the file into a list of option names and values */
  	head = tail = NULL;
  
! 	if (!ParseConfigFile(ConfigFileName, NULL, 0, elevel, &head, &tail))
  	{
  		/* Syntax error(s) detected in the file, so bail out */
  		error = true;
--- 129,135 ----
  	/* Parse the file into a list of option names and values */
  	head = tail = NULL;
  
! 	if (!ParseConfigFile(ConfigFileName, NULL, true, 0, elevel, &head, &tail))
  	{
  		/* Syntax error(s) detected in the file, so bail out */
  		error = true;
*************** ProcessConfigFile(GucContext context)
*** 363,369 ****
   * and absolute-ifying the path name if necessary.
   */
  bool
! ParseConfigFile(const char *config_file, const char *calling_file,
  				int depth, int elevel,
  				ConfigVariable **head_p,
  				ConfigVariable **tail_p)
--- 363,369 ----
   * and absolute-ifying the path name if necessary.
   */
  bool
! ParseConfigFile(const char *config_file, const char *calling_file, bool strict,
  				int depth, int elevel,
  				ConfigVariable **head_p,
  				ConfigVariable **tail_p)
*************** ParseConfigFile(const char *config_file,
*** 414,424 ****
  	fp = AllocateFile(config_file, "r");
  	if (!fp)
  	{
! 		ereport(elevel,
! 				(errcode_for_file_access(),
! 				 errmsg("could not open configuration file \"%s\": %m",
! 						config_file)));
! 		return false;
  	}
  
  	OK = ParseConfigFp(fp, config_file, depth, elevel, head_p, tail_p);
--- 414,430 ----
  	fp = AllocateFile(config_file, "r");
  	if (!fp)
  	{
! 		if (strict)
! 		{
! 			ereport(elevel,
! 					(errcode_for_file_access(),
! 					 errmsg("could not open configuration file \"%s\": %m",
! 							config_file)));
! 			return false;
! 		}
! 
! 		/* Silently skip missing files if not asked to be strict */
! 		return OK;
  	}
  
  	OK = ParseConfigFp(fp, config_file, depth, elevel, head_p, tail_p);
*************** ParseConfigFp(FILE *fp, const char *conf
*** 512,518 ****
  		}
  
  		/* OK, process the option name and value */
! 		if (guc_name_compare(opt_name, "include") == 0)
  		{
  			/*
  			 * An include directive isn't a variable and should be processed
--- 518,541 ----
  		}
  
  		/* OK, process the option name and value */
! 		if (guc_name_compare(opt_name, "includeifexists") == 0)
! 		{
! 			/*
! 			 * An includeifexists directive isn't a variable and should be
! 			 * processed immediately.
! 			 */
! 			unsigned int save_ConfigFileLineno = ConfigFileLineno;
! 
! 			if (!ParseConfigFile(opt_value, config_file, false,
! 								 depth + 1, elevel,
! 								 head_p, tail_p))
! 				OK = false;
! 			yy_switch_to_buffer(lex_buffer);
! 			ConfigFileLineno = save_ConfigFileLineno;
! 			pfree(opt_name);
! 			pfree(opt_value);
! 		}
! 		else if (guc_name_compare(opt_name, "include") == 0)
  		{
  			/*
  			 * An include directive isn't a variable and should be processed
*************** ParseConfigFp(FILE *fp, const char *conf
*** 520,526 ****
  			 */
  			unsigned int save_ConfigFileLineno = ConfigFileLineno;
  
! 			if (!ParseConfigFile(opt_value, config_file,
  								 depth + 1, elevel,
  								 head_p, tail_p))
  				OK = false;
--- 543,549 ----
  			 */
  			unsigned int save_ConfigFileLineno = ConfigFileLineno;
  
! 			if (!ParseConfigFile(opt_value, config_file, true,
  								 depth + 1, elevel,
  								 head_p, tail_p))
  				OK = false;
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 8e3057a..52109e5 100644
*** a/src/include/utils/guc.h
--- b/src/include/utils/guc.h
*************** typedef struct ConfigVariable
*** 111,117 ****
  } ConfigVariable;
  
  extern bool ParseConfigFile(const char *config_file, const char *calling_file,
! 				int depth, int elevel,
  				ConfigVariable **head_p, ConfigVariable **tail_p);
  extern bool ParseConfigFp(FILE *fp, const char *config_file,
  			  int depth, int elevel,
--- 111,117 ----
  } ConfigVariable;
  
  extern bool ParseConfigFile(const char *config_file, const char *calling_file,
! 				bool strict, int depth, int elevel,
  				ConfigVariable **head_p, ConfigVariable **tail_p);
  extern bool ParseConfigFp(FILE *fp, const char *config_file,
  			  int depth, int elevel,
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to