Simplify handling of the timezone GUC by making initdb choose the default.
authorTom Lane <[email protected]>
Fri, 9 Sep 2011 21:59:11 +0000 (17:59 -0400)
committerTom Lane <[email protected]>
Fri, 9 Sep 2011 21:59:11 +0000 (17:59 -0400)
We were doing some amazingly complicated things in order to avoid running
the very expensive identify_system_timezone() procedure during GUC
initialization.  But there is an obvious fix for that, which is to do it
once during initdb and have initdb install the system-specific default into
postgresql.conf, as it already does for most other GUC variables that need
system-environment-dependent defaults.  This means that the timezone (and
log_timezone) settings no longer have any magic behavior in the server.
Per discussion.

19 files changed:
doc/src/sgml/config.sgml
doc/src/sgml/datatype.sgml
doc/src/sgml/ref/set.sgml
src/backend/bootstrap/bootstrap.c
src/backend/commands/variable.c
src/backend/postmaster/postmaster.c
src/backend/tcop/postgres.c
src/backend/utils/error/elog.c
src/backend/utils/misc/guc-file.l
src/backend/utils/misc/guc.c
src/backend/utils/misc/postgresql.conf.sample
src/bin/initdb/.gitignore
src/bin/initdb/Makefile
src/bin/initdb/findtimezone.c [new file with mode: 0644]
src/bin/initdb/initdb.c
src/include/pgtime.h
src/include/utils/guc.h
src/timezone/localtime.c
src/timezone/pgtz.c

index 615b2b078bf9053f7f2f7f451886ab8c5c20b3df..f95f9cc8bd804d210bf951e93df99ccf80b75ff1 100644 (file)
@@ -3915,9 +3915,10 @@ FROM pg_stat_activity;
         Sets the time zone used for timestamps written in the server log.
         Unlike <xref linkend="guc-timezone">, this value is cluster-wide,
         so that all sessions will report timestamps consistently.
-        If not explicitly set, the server initializes this variable to the
-        time zone specified by its system environment.  See <xref
-        linkend="datatype-timezones"> for more information.
+        The built-in default is <literal>GMT</>, but that is typically
+        overridden in <filename>postgresql.conf</>; <application>initdb</>
+        will install a setting there corresponding to its system environment.
+        See <xref linkend="datatype-timezones"> for more information.
         This parameter can only be set in the <filename>postgresql.conf</>
         file or on the server command line.
        </para>
@@ -4963,9 +4964,10 @@ SET XML OPTION { DOCUMENT | CONTENT };
       <listitem>
        <para>
         Sets the time zone for displaying and interpreting time stamps.
-        If not explicitly set, the server initializes this variable to the
-        time zone specified by its system environment.  See <xref
-        linkend="datatype-timezones"> for more information.
+        The built-in default is <literal>GMT</>, but that is typically
+        overridden in <filename>postgresql.conf</>; <application>initdb</>
+        will install a setting there corresponding to its system environment.
+        See <xref linkend="datatype-timezones"> for more information.
        </para>
       </listitem>
      </varlistentry>
index 89b531fa1d205d5754eb25434cefa89f1300adc2..e7b3098f28ffb1b7f66c64a59fbba2c7a9a28222 100644 (file)
@@ -2286,7 +2286,7 @@ January 8 04:05:06 1999 PST
     but continue to be prone to arbitrary changes, particularly with
     respect to daylight-savings rules.
     <productname>PostgreSQL</productname> uses the widely-used
-    <literal>zoneinfo</> time zone database for information about
+    <literal>zoneinfo</> (Olson) time zone database for information about
     historical time zone rules.  For times in the future, the assumption
     is that the latest known rules for a given time zone will
     continue to be observed indefinitely far into the future.
@@ -2432,26 +2432,9 @@ January 8 04:05:06 1999 PST
      The <xref linkend="guc-timezone"> configuration parameter can
      be set in the file <filename>postgresql.conf</>, or in any of the
      other standard ways described in <xref linkend="runtime-config">.
-     There are also several special ways to set it:
+     There are also some special ways to set it:
 
      <itemizedlist>
-      <listitem>
-       <para>
-        If <varname>timezone</> is not specified in
-        <filename>postgresql.conf</> or as a server command-line option,
-        the server attempts to use the value of the <envar>TZ</envar>
-        environment variable as the default time zone.  If <envar>TZ</envar>
-        is not defined or is not any of the time zone names known to
-        <productname>PostgreSQL</productname>, the server attempts to
-        determine the operating system's default time zone by checking the
-        behavior of the C library function <literal>localtime()</>.  The
-        default time zone is selected as the closest match among
-        <productname>PostgreSQL</productname>'s known time zones.
-        (These rules are also used to choose the default value of
-        <xref linkend="guc-log-timezone">, if not specified.)
-       </para>
-      </listitem>
-
       <listitem>
        <para>
         The <acronym>SQL</acronym> command <command>SET TIME ZONE</command>
index 40e1bd4e607412dcc2b615215ca89c234f0d08cb..21745db4627bc90c2ab400ff851c20f71354fcca 100644 (file)
@@ -239,9 +239,7 @@ SELECT setseed(<replaceable>value</replaceable>);
          <listitem>
           <para>
            Set the time zone to your local time zone (that is, the
-           server's default value of <varname>timezone</>; if this
-           has not been explicitly set anywhere, it will be the zone that
-           the server's operating system defaults to).
+           server's default value of <varname>timezone</>).
           </para>
          </listitem>
         </varlistentry>
index e3dd472832eff616465be99200a8369d75ad7966..4fe08df350a9879dce73b0a44eac82e9bea7fbbb 100644 (file)
@@ -333,10 +333,6 @@ AuxiliaryProcessMain(int argc, char *argv[])
    {
        if (!SelectConfigFiles(userDoption, progname))
            proc_exit(1);
-       /* If timezone is not set, determine what the OS uses */
-       pg_timezone_initialize();
-       /* If timezone_abbreviations is not set, select default */
-       pg_timezone_abbrev_initialize();
    }
 
    /* Validate we have been given a reasonable-looking DataDir */
index 239acd07852908517fda4a6a7847b36bfc0e1f72..87c54b7d48043832e9df9a5cc3e9144f63958319 100644 (file)
@@ -259,23 +259,6 @@ check_timezone(char **newval, void **extra, GucSource source)
    char       *endptr;
    double      hours;
 
-   if (*newval == NULL)
-   {
-       /*
-        * The boot_val given for TimeZone in guc.c is NULL.  When we see this
-        * we just do nothing.  If this isn't overridden from the config file
-        * then pg_timezone_initialize() will eventually select a default
-        * value from the environment.  This hack has two purposes: to avoid
-        * wasting cycles loading values that might soon be overridden from
-        * the config file, and to avoid trying to read the timezone files
-        * during InitializeGUCOptions().  The latter doesn't work in an
-        * EXEC_BACKEND subprocess because my_exec_path hasn't been set yet
-        * and so we can't locate PGSHAREDIR.
-        */
-       Assert(source == PGC_S_DEFAULT);
-       return true;
-   }
-
    /*
     * Initialize the "extra" struct that will be passed to assign_timezone.
     * We don't want to change any of the three global variables except as
@@ -374,7 +357,7 @@ check_timezone(char **newval, void **extra, GucSource source)
                return false;
            }
 
-           if (!tz_acceptable(new_tz))
+           if (!pg_tz_acceptable(new_tz))
            {
                GUC_check_errmsg("time zone \"%s\" appears to use leap seconds",
                                 *newval);
@@ -427,10 +410,6 @@ assign_timezone(const char *newval, void *extra)
 {
    timezone_extra *myextra = (timezone_extra *) extra;
 
-   /* Do nothing for the boot_val default of NULL */
-   if (!myextra)
-       return;
-
    session_timezone = myextra->session_timezone;
    CTimeZone = myextra->CTimeZone;
    HasCTZSet = myextra->HasCTZSet;
@@ -490,20 +469,8 @@ check_log_timezone(char **newval, void **extra, GucSource source)
 {
    pg_tz      *new_tz;
 
-   if (*newval == NULL)
-   {
-       /*
-        * The boot_val given for log_timezone in guc.c is NULL.  When we see
-        * this we just do nothing.  If this isn't overridden from the config
-        * file then pg_timezone_initialize() will eventually select a default
-        * value from the environment.
-        */
-       Assert(source == PGC_S_DEFAULT);
-       return true;
-   }
-
    /*
-    * Otherwise assume it is a timezone name, and try to load it.
+    * Assume it is a timezone name, and try to load it.
     */
    new_tz = pg_tzset(*newval);
 
@@ -513,7 +480,7 @@ check_log_timezone(char **newval, void **extra, GucSource source)
        return false;
    }
 
-   if (!tz_acceptable(new_tz))
+   if (!pg_tz_acceptable(new_tz))
    {
        GUC_check_errmsg("time zone \"%s\" appears to use leap seconds",
                         *newval);
@@ -538,10 +505,6 @@ check_log_timezone(char **newval, void **extra, GucSource source)
 void
 assign_log_timezone(const char *newval, void *extra)
 {
-   /* Do nothing for the boot_val default of NULL */
-   if (!extra)
-       return;
-
    log_timezone = *((pg_tz **) extra);
 }
 
index df4a2aa885373095f0f27765961573d380cc353b..94b57fa7bbdeaf39ed533354365d375085ccc955 100644 (file)
@@ -795,21 +795,6 @@ PostmasterMain(int argc, char *argv[])
     */
    CreateDataDirLockFile(true);
 
-   /*
-    * If timezone is not set, determine what the OS uses.  (In theory this
-    * should be done during GUC initialization, but because it can take as
-    * much as several seconds, we delay it until after we've created the
-    * postmaster.pid file.  This prevents problems with boot scripts that
-    * expect the pidfile to appear quickly.  Also, we avoid problems with
-    * trying to locate the timezone files too early in initialization.)
-    */
-   pg_timezone_initialize();
-
-   /*
-    * Likewise, init timezone_abbreviations if not already set.
-    */
-   pg_timezone_abbrev_initialize();
-
    /*
     * Initialize SSL library, if specified.
     */
index b708328926adbd94faeeaa8ab66214257a987c73..072d50c39515187d9fc212ae8ab72e7858edb879 100644 (file)
@@ -3537,10 +3537,6 @@ PostgresMain(int argc, char *argv[], const char *username)
    {
        if (!SelectConfigFiles(userDoption, progname))
            proc_exit(1);
-       /* If timezone is not set, determine what the OS uses */
-       pg_timezone_initialize();
-       /* If timezone_abbreviations is not set, select default */
-       pg_timezone_abbrev_initialize();
    }
 
    /*
index 6e8e5aef4e0fe2f2771e38396b1c70827056e699..f0b3b1feb06b9a8d57b2bb6848331b794afc90d1 100644 (file)
--- a/