Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit ca4af30

Browse files
committed
Simplify handling of the timezone GUC by making initdb choose the default.
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.
1 parent a7801b6 commit ca4af30

File tree

19 files changed

+1372
-1367
lines changed

19 files changed

+1372
-1367
lines changed

doc/src/sgml/config.sgml

+8-6
Original file line numberDiff line numberDiff line change
@@ -3915,9 +3915,10 @@ FROM pg_stat_activity;
39153915
Sets the time zone used for timestamps written in the server log.
39163916
Unlike <xref linkend="guc-timezone">, this value is cluster-wide,
39173917
so that all sessions will report timestamps consistently.
3918-
If not explicitly set, the server initializes this variable to the
3919-
time zone specified by its system environment. See <xref
3920-
linkend="datatype-timezones"> for more information.
3918+
The built-in default is <literal>GMT</>, but that is typically
3919+
overridden in <filename>postgresql.conf</>; <application>initdb</>
3920+
will install a setting there corresponding to its system environment.
3921+
See <xref linkend="datatype-timezones"> for more information.
39213922
This parameter can only be set in the <filename>postgresql.conf</>
39223923
file or on the server command line.
39233924
</para>
@@ -4963,9 +4964,10 @@ SET XML OPTION { DOCUMENT | CONTENT };
49634964
<listitem>
49644965
<para>
49654966
Sets the time zone for displaying and interpreting time stamps.
4966-
If not explicitly set, the server initializes this variable to the
4967-
time zone specified by its system environment. See <xref
4968-
linkend="datatype-timezones"> for more information.
4967+
The built-in default is <literal>GMT</>, but that is typically
4968+
overridden in <filename>postgresql.conf</>; <application>initdb</>
4969+
will install a setting there corresponding to its system environment.
4970+
See <xref linkend="datatype-timezones"> for more information.
49694971
</para>
49704972
</listitem>
49714973
</varlistentry>

doc/src/sgml/datatype.sgml

+2-19
Original file line numberDiff line numberDiff line change
@@ -2286,7 +2286,7 @@ January 8 04:05:06 1999 PST
22862286
but continue to be prone to arbitrary changes, particularly with
22872287
respect to daylight-savings rules.
22882288
<productname>PostgreSQL</productname> uses the widely-used
2289-
<literal>zoneinfo</> time zone database for information about
2289+
<literal>zoneinfo</> (Olson) time zone database for information about
22902290
historical time zone rules. For times in the future, the assumption
22912291
is that the latest known rules for a given time zone will
22922292
continue to be observed indefinitely far into the future.
@@ -2432,26 +2432,9 @@ January 8 04:05:06 1999 PST
24322432
The <xref linkend="guc-timezone"> configuration parameter can
24332433
be set in the file <filename>postgresql.conf</>, or in any of the
24342434
other standard ways described in <xref linkend="runtime-config">.
2435-
There are also several special ways to set it:
2435+
There are also some special ways to set it:
24362436

24372437
<itemizedlist>
2438-
<listitem>
2439-
<para>
2440-
If <varname>timezone</> is not specified in
2441-
<filename>postgresql.conf</> or as a server command-line option,
2442-
the server attempts to use the value of the <envar>TZ</envar>
2443-
environment variable as the default time zone. If <envar>TZ</envar>
2444-
is not defined or is not any of the time zone names known to
2445-
<productname>PostgreSQL</productname>, the server attempts to
2446-
determine the operating system's default time zone by checking the
2447-
behavior of the C library function <literal>localtime()</>. The
2448-
default time zone is selected as the closest match among
2449-
<productname>PostgreSQL</productname>'s known time zones.
2450-
(These rules are also used to choose the default value of
2451-
<xref linkend="guc-log-timezone">, if not specified.)
2452-
</para>
2453-
</listitem>
2454-
24552438
<listitem>
24562439
<para>
24572440
The <acronym>SQL</acronym> command <command>SET TIME ZONE</command>

doc/src/sgml/ref/set.sgml

+1-3
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,7 @@ SELECT setseed(<replaceable>value</replaceable>);
239239
<listitem>
240240
<para>
241241
Set the time zone to your local time zone (that is, the
242-
server's default value of <varname>timezone</>; if this
243-
has not been explicitly set anywhere, it will be the zone that
244-
the server's operating system defaults to).
242+
server's default value of <varname>timezone</>).
245243
</para>
246244
</listitem>
247245
</varlistentry>

src/backend/bootstrap/bootstrap.c

-4
Original file line numberDiff line numberDiff line change
@@ -333,10 +333,6 @@ AuxiliaryProcessMain(int argc, char *argv[])
333333
{
334334
if (!SelectConfigFiles(userDoption, progname))
335335
proc_exit(1);
336-
/* If timezone is not set, determine what the OS uses */
337-
pg_timezone_initialize();
338-
/* If timezone_abbreviations is not set, select default */
339-
pg_timezone_abbrev_initialize();
340336
}
341337

342338
/* Validate we have been given a reasonable-looking DataDir */

src/backend/commands/variable.c

+3-40
Original file line numberDiff line numberDiff line change
@@ -259,23 +259,6 @@ check_timezone(char **newval, void **extra, GucSource source)
259259
char *endptr;
260260
double hours;
261261

262-
if (*newval == NULL)
263-
{
264-
/*
265-
* The boot_val given for TimeZone in guc.c is NULL. When we see this
266-
* we just do nothing. If this isn't overridden from the config file
267-
* then pg_timezone_initialize() will eventually select a default
268-
* value from the environment. This hack has two purposes: to avoid
269-
* wasting cycles loading values that might soon be overridden from
270-
* the config file, and to avoid trying to read the timezone files
271-
* during InitializeGUCOptions(). The latter doesn't work in an
272-
* EXEC_BACKEND subprocess because my_exec_path hasn't been set yet
273-
* and so we can't locate PGSHAREDIR.
274-
*/
275-
Assert(source == PGC_S_DEFAULT);
276-
return true;
277-
}
278-
279262
/*
280263
* Initialize the "extra" struct that will be passed to assign_timezone.
281264
* 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)
374357
return false;
375358
}
376359

377-
if (!tz_acceptable(new_tz))
360+
if (!pg_tz_acceptable(new_tz))
378361
{
379362
GUC_check_errmsg("time zone \"%s\" appears to use leap seconds",
380363
*newval);
@@ -427,10 +410,6 @@ assign_timezone(const char *newval, void *extra)
427410
{
428411
timezone_extra *myextra = (timezone_extra *) extra;
429412

430-
/* Do nothing for the boot_val default of NULL */
431-
if (!myextra)
432-
return;
433-
434413
session_timezone = myextra->session_timezone;
435414
CTimeZone = myextra->CTimeZone;
436415
HasCTZSet = myextra->HasCTZSet;
@@ -490,20 +469,8 @@ check_log_timezone(char **newval, void **extra, GucSource source)
490469
{
491470
pg_tz *new_tz;
492471

493-
if (*newval == NULL)
494-
{
495-
/*
496-
* The boot_val given for log_timezone in guc.c is NULL. When we see
497-
* this we just do nothing. If this isn't overridden from the config
498-
* file then pg_timezone_initialize() will eventually select a default
499-
* value from the environment.
500-
*/
501-
Assert(source == PGC_S_DEFAULT);
502-
return true;
503-
}
504-
505472
/*
506-
* Otherwise assume it is a timezone name, and try to load it.
473+
* Assume it is a timezone name, and try to load it.
507474
*/
508475
new_tz = pg_tzset(*newval);
509476

@@ -513,7 +480,7 @@ check_log_timezone(char **newval, void **extra, GucSource source)
513480
return false;
514481
}
515482

516-
if (!tz_acceptable(new_tz))
483+
if (!pg_tz_acceptable(new_tz))
517484
{
518485
GUC_check_errmsg("time zone \"%s\" appears to use leap seconds",
519486
*newval);
@@ -538,10 +505,6 @@ check_log_timezone(char **newval, void **extra, GucSource source)
538505
void
539506
assign_log_timezone(const char *newval, void *extra)
540507
{
541-
/* Do nothing for the boot_val default of NULL */
542-
if (!extra)
543-
return;
544-
545508
log_timezone = *((pg_tz **) extra);
546509
}
547510

src/backend/postmaster/postmaster.c

-15
Original file line numberDiff line numberDiff line change
@@ -795,21 +795,6 @@ PostmasterMain(int argc, char *argv[])
795795
*/
796796
CreateDataDirLockFile(true);
797797

798-
/*
799-
* If timezone is not set, determine what the OS uses. (In theory this
800-
* should be done during GUC initialization, but because it can take as
801-
* much as several seconds, we delay it until after we've created the
802-
* postmaster.pid file. This prevents problems with boot scripts that
803-
* expect the pidfile to appear quickly. Also, we avoid problems with
804-
* trying to locate the timezone files too early in initialization.)
805-
*/
806-
pg_timezone_initialize();
807-
808-
/*
809-
* Likewise, init timezone_abbreviations if not already set.
810-
*/
811-
pg_timezone_abbrev_initialize();
812-
813798
/*
814799
* Initialize SSL library, if specified.
815800
*/

src/backend/tcop/postgres.c

-4
Original file line numberDiff line numberDiff line change
@@ -3537,10 +3537,6 @@ PostgresMain(int argc, char *argv[], const char *username)
35373537
{
35383538
if (!SelectConfigFiles(userDoption, progname))
35393539
proc_exit(1);
3540-
/* If timezone is not set, determine what the OS uses */
3541-
pg_timezone_initialize();
3542-
/* If timezone_abbreviations is not set, select default */
3543-
pg_timezone_abbrev_initialize();
35443540
}
35453541

35463542
/*

src/backend/utils/error/elog.c

+9-20
Original file line numberDiff line numberDiff line change
@@ -1805,24 +1805,20 @@ setup_formatted_log_time(void)
18051805
{
18061806
struct timeval tv;
18071807
pg_time_t stamp_time;
1808-
pg_tz *tz;
18091808
char msbuf[8];
18101809

18111810
gettimeofday(&tv, NULL);
18121811
stamp_time = (pg_time_t) tv.tv_sec;
18131812

18141813
/*
1815-
* Normally we print log timestamps in log_timezone, but during startup we
1816-
* could get here before that's set. If so, fall back to gmt_timezone
1817-
* (which guc.c ensures is set up before Log_line_prefix can become
1818-
* nonempty).
1814+
* Note: we expect that guc.c will ensure that log_timezone is set up
1815+
* (at least with a minimal GMT value) before Log_line_prefix can become
1816+
* nonempty or CSV mode can be selected.
18191817
*/
1820-
tz = log_timezone ? log_timezone : gmt_timezone;
1821-
18221818
pg_strftime(formatted_log_time, FORMATTED_TS_LEN,
18231819
/* leave room for milliseconds... */
18241820
"%Y-%m-%d %H:%M:%S %Z",
1825-
pg_localtime(&stamp_time, tz));
1821+
pg_localtime(&stamp_time, log_timezone));
18261822

18271823
/* 'paste' milliseconds into place... */
18281824
sprintf(msbuf, ".%03d", (int) (tv.tv_usec / 1000));
@@ -1836,19 +1832,15 @@ static void
18361832
setup_formatted_start_time(void)
18371833
{
18381834
pg_time_t stamp_time = (pg_time_t) MyStartTime;
1839-
pg_tz *tz;
18401835

18411836
/*
1842-
* Normally we print log timestamps in log_timezone, but during startup we
1843-
* could get here before that's set. If so, fall back to gmt_timezone
1844-
* (which guc.c ensures is set up before Log_line_prefix can become
1845-
* nonempty).
1837+
* Note: we expect that guc.c will ensure that log_timezone is set up
1838+
* (at least with a minimal GMT value) before Log_line_prefix can become
1839+
* nonempty or CSV mode can be selected.
18461840
*/
1847-
tz = log_timezone ? log_timezone : gmt_timezone;
1848-
18491841
pg_strftime(formatted_start_time, FORMATTED_TS_LEN,
18501842
"%Y-%m-%d %H:%M:%S %Z",
1851-
pg_localtime(&stamp_time, tz));
1843+
pg_localtime(&stamp_time, log_timezone));
18521844
}
18531845

18541846
/*
@@ -1947,14 +1939,11 @@ log_line_prefix(StringInfo buf, ErrorData *edata)
19471939
case 't':
19481940
{
19491941
pg_time_t stamp_time = (pg_time_t) time(NULL);
1950-
pg_tz *tz;
19511942
char strfbuf[128];
19521943

1953-
tz = log_timezone ? log_timezone : gmt_timezone;
1954-
19551944
pg_strftime(strfbuf, sizeof(strfbuf),
19561945
"%Y-%m-%d %H:%M:%S %Z",
1957-
pg_localtime(&stamp_time, tz));
1946+
pg_localtime(&stamp_time, log_timezone));
19581947
appendStringInfoString(buf, strfbuf);
19591948
}
19601949
break;

src/backend/utils/misc/guc-file.l

-1
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,6 @@ ProcessConfigFile(GucContext context)
292292
if (context == PGC_SIGHUP)
293293
{
294294
InitializeGUCOptionsFromEnvironment();
295-
pg_timezone_initialize();
296295
pg_timezone_abbrev_initialize();
297296
/* this selects SQL_ASCII in processes not connected to a database */
298297
SetConfigOption("client_encoding", GetDatabaseEncodingName(),

src/backend/utils/misc/guc.c

+17-4
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ static bool check_log_stats(bool *newval, void **extra, GucSource source);
187187
static bool check_canonical_path(char **newval, void **extra, GucSource source);
188188
static bool check_timezone_abbreviations(char **newval, void **extra, GucSource source);
189189
static void assign_timezone_abbreviations(const char *newval, void *extra);
190+
static void pg_timezone_abbrev_initialize(void);
190191
static const char *show_archive_command(void);
191192
static void assign_tcp_keepalives_idle(int newval, void *extra);
192193
static void assign_tcp_keepalives_interval(int newval, void *extra);
@@ -2547,7 +2548,7 @@ static struct config_string ConfigureNamesString[] =
25472548
NULL
25482549
},
25492550
&log_timezone_string,
2550-
NULL,
2551+
"GMT",
25512552
check_log_timezone, assign_log_timezone, show_log_timezone
25522553
},
25532554

@@ -2827,7 +2828,7 @@ static struct config_string ConfigureNamesString[] =
28272828
GUC_REPORT
28282829
},
28292830
&timezone_string,
2830-
NULL,
2831+
"GMT",
28312832
check_timezone, assign_timezone, show_timezone
28322833
},
28332834
{
@@ -3817,7 +3818,7 @@ InitializeGUCOptions(void)
38173818
* Before log_line_prefix could possibly receive a nonempty setting, make
38183819
* sure that timezone processing is minimally alive (see elog.c).
38193820
*/
3820-
pg_timezone_pre_initialize();
3821+
pg_timezone_initialize();
38213822

38223823
/*
38233824
* Build sorted array of all GUC variables.
@@ -4114,6 +4115,15 @@ SelectConfigFiles(const char *userDoption, const char *progname)
41144115
*/
41154116
SetConfigOption("data_directory", DataDir, PGC_POSTMASTER, PGC_S_OVERRIDE);
41164117

4118+
/*
4119+
* If timezone_abbreviations wasn't set in the configuration file, install
4120+
* the default value. We do it this way because we can't safely install
4121+
* a "real" value until my_exec_path is set, which may not have happened
4122+
* when InitializeGUCOptions runs, so the bootstrap default value cannot
4123+
* be the real desired default.
4124+
*/
4125+
pg_timezone_abbrev_initialize();
4126+
41174127
/*
41184128
* Figure out where pg_hba.conf is, and make sure the path is absolute.
41194129
*/
@@ -8444,8 +8454,11 @@ assign_timezone_abbreviations(const char *newval, void *extra)
84448454
* This is called after initial loading of postgresql.conf. If no
84458455
* timezone_abbreviations setting was found therein, select default.
84468456
* If a non-default value is already installed, nothing will happen.
8457+
*
8458+
* This can also be called from ProcessConfigFile to establish the default
8459+
* value after a postgresql.conf entry for it is removed.
84478460
*/
8448-
void
8461+
static void
84498462
pg_timezone_abbrev_initialize(void)
84508463
{
84518464
SetConfigOption("timezone_abbreviations", "Default",

src/backend/utils/misc/postgresql.conf.sample

+2-2
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@
406406
#log_temp_files = -1 # log temporary files equal or larger
407407
# than the specified size in kilobytes;
408408
# -1 disables, 0 logs all temp files
409-
#log_timezone = '(defaults to server environment setting)'
409+
#log_timezone = 'GMT'
410410

411411

412412
#------------------------------------------------------------------------------
@@ -486,7 +486,7 @@
486486

487487
#datestyle = 'iso, mdy'
488488
#intervalstyle = 'postgres'
489-
#timezone = '(defaults to server environment setting)'
489+
#timezone = 'GMT'
490490
#timezone_abbreviations = 'Default' # Select the set of available time zone
491491
# abbreviations. Currently, there are
492492
# Default

src/bin/initdb/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/encnames.c
22
/pqsignal.c
3+
/localtime.c
34

45
/initdb

0 commit comments

Comments
 (0)