diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/transam/xlog.c | 46 | ||||
-rw-r--r-- | src/backend/commands/variable.c | 113 | ||||
-rw-r--r-- | src/backend/postmaster/syslogger.c | 13 | ||||
-rw-r--r-- | src/backend/utils/adt/date.c | 6 | ||||
-rw-r--r-- | src/backend/utils/adt/datetime.c | 8 | ||||
-rw-r--r-- | src/backend/utils/adt/formatting.c | 4 | ||||
-rw-r--r-- | src/backend/utils/adt/nabstime.c | 8 | ||||
-rw-r--r-- | src/backend/utils/adt/timestamp.c | 14 | ||||
-rw-r--r-- | src/backend/utils/error/elog.c | 56 | ||||
-rw-r--r-- | src/backend/utils/misc/guc.c | 11 | ||||
-rw-r--r-- | src/backend/utils/misc/postgresql.conf.sample | 2 | ||||
-rw-r--r-- | src/include/commands/variable.h | 5 | ||||
-rw-r--r-- | src/include/pgtime.h | 5 | ||||
-rw-r--r-- | src/timezone/pgtz.c | 80 |
14 files changed, 237 insertions, 134 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 4c7024baa38..626143ff19b 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.276 2007/08/01 22:45:08 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.277 2007/08/04 01:26:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -437,7 +437,7 @@ static void writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI, uint32 endLogId, uint32 endLogSeg); static void WriteControlFile(void); static void ReadControlFile(void); -static char *str_time(time_t tnow); +static char *str_time(pg_time_t tnow); static void issue_xlog_fsync(void); #ifdef WAL_DEBUG @@ -4266,13 +4266,13 @@ BootStrapXLOG(void) } static char * -str_time(time_t tnow) +str_time(pg_time_t tnow) { static char buf[128]; - strftime(buf, sizeof(buf), - "%Y-%m-%d %H:%M:%S %Z", - localtime(&tnow)); + pg_strftime(buf, sizeof(buf), + "%Y-%m-%d %H:%M:%S %Z", + pg_localtime(&tnow, log_timezone)); return buf; } @@ -6290,7 +6290,7 @@ pg_start_backup(PG_FUNCTION_ARGS) char *backupidstr; XLogRecPtr checkpointloc; XLogRecPtr startpoint; - time_t stamp_time; + pg_time_t stamp_time; char strfbuf[128]; char xlogfilename[MAXFNAMELEN]; uint32 _logId; @@ -6368,16 +6368,11 @@ pg_start_backup(PG_FUNCTION_ARGS) XLByteToSeg(startpoint, _logId, _logSeg); XLogFileName(xlogfilename, ThisTimeLineID, _logId, _logSeg); - /* - * We deliberately use strftime/localtime not the src/timezone - * functions, so that backup labels will consistently be recorded in - * the same timezone regardless of TimeZone setting. This matches - * elog.c's practice. - */ - stamp_time = time(NULL); - strftime(strfbuf, sizeof(strfbuf), - "%Y-%m-%d %H:%M:%S %Z", - localtime(&stamp_time)); + /* Use the log timezone here, not the session timezone */ + stamp_time = (pg_time_t) time(NULL); + pg_strftime(strfbuf, sizeof(strfbuf), + "%Y-%m-%d %H:%M:%S %Z", + pg_localtime(&stamp_time, log_timezone)); /* * Check for existing backup label --- implies a backup is already @@ -6455,7 +6450,7 @@ pg_stop_backup(PG_FUNCTION_ARGS) text *result; XLogRecPtr startpoint; XLogRecPtr stoppoint; - time_t stamp_time; + pg_time_t stamp_time; char strfbuf[128]; char histfilepath[MAXPGPATH]; char startxlogfilename[MAXFNAMELEN]; @@ -6489,16 +6484,11 @@ pg_stop_backup(PG_FUNCTION_ARGS) XLByteToSeg(stoppoint, _logId, _logSeg); XLogFileName(stopxlogfilename, ThisTimeLineID, _logId, _logSeg); - /* - * We deliberately use strftime/localtime not the src/timezone functions, - * so that backup labels will consistently be recorded in the same - * timezone regardless of TimeZone setting. This matches elog.c's - * practice. - */ - stamp_time = time(NULL); - strftime(strfbuf, sizeof(strfbuf), - "%Y-%m-%d %H:%M:%S %Z", - localtime(&stamp_time)); + /* Use the log timezone here, not the session timezone */ + stamp_time = (pg_time_t) time(NULL); + pg_strftime(strfbuf, sizeof(strfbuf), + "%Y-%m-%d %H:%M:%S %Z", + pg_localtime(&stamp_time, log_timezone)); /* * Open the existing label file diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c index 1f6839cbd17..8a04a975ca1 100644 --- a/src/backend/commands/variable.c +++ b/src/backend/commands/variable.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/variable.c,v 1.120 2007/01/05 22:19:27 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/variable.c,v 1.121 2007/08/04 01:26:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -344,7 +344,7 @@ assign_timezone(const char *value, bool doit, GucSource source) */ if (doit) { - const char *curzone = pg_get_timezone_name(global_timezone); + const char *curzone = pg_get_timezone_name(session_timezone); if (curzone) value = curzone; @@ -381,7 +381,7 @@ assign_timezone(const char *value, bool doit, GucSource source) if (doit) { /* Save the changed TZ */ - global_timezone = new_tz; + session_timezone = new_tz; HasCTZSet = false; } } @@ -434,7 +434,112 @@ show_timezone(void) IntervalPGetDatum(&interval))); } else - tzn = pg_get_timezone_name(global_timezone); + tzn = pg_get_timezone_name(session_timezone); + + if (tzn != NULL) + return tzn; + + return "unknown"; +} + + +/* + * LOG_TIMEZONE + * + * For log_timezone, we don't support the interval-based methods of setting a + * zone, which are only there for SQL spec compliance not because they're + * actually useful. + */ + +/* + * assign_log_timezone: GUC assign_hook for log_timezone + */ +const char * +assign_log_timezone(const char *value, bool doit, GucSource source) +{ + char *result; + + if (pg_strcasecmp(value, "UNKNOWN") == 0) + { + /* + * UNKNOWN is the value shown as the "default" for log_timezone in + * guc.c. We interpret it as being a complete no-op; we don't + * change the timezone setting. Note that if there is a known + * timezone setting, we will return that name rather than UNKNOWN + * as the canonical spelling. + * + * During GUC initialization, since the timezone library isn't set + * up yet, pg_get_timezone_name will return NULL and we will leave + * the setting as UNKNOWN. If this isn't overridden from the + * config file then pg_timezone_initialize() will eventually + * select a default value from the environment. + */ + if (doit) + { + const char *curzone = pg_get_timezone_name(log_timezone); + + if (curzone) + value = curzone; + } + } + else + { + /* + * Otherwise assume it is a timezone name, and try to load it. + */ + pg_tz *new_tz; + + new_tz = pg_tzset(value); + + if (!new_tz) + { + ereport((source >= PGC_S_INTERACTIVE) ? ERROR : LOG, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("unrecognized time zone name: \"%s\"", + value))); + return NULL; + } + + if (!tz_acceptable(new_tz)) + { + ereport((source >= PGC_S_INTERACTIVE) ? ERROR : LOG, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("time zone \"%s\" appears to use leap seconds", + value), + errdetail("PostgreSQL does not support leap seconds."))); + return NULL; + } + + if (doit) + { + /* Save the changed TZ */ + log_timezone = new_tz; + } + } + + /* + * If we aren't going to do the assignment, just return OK indicator. + */ + if (!doit) + return value; + + /* + * Prepare the canonical string to return. GUC wants it malloc'd. + */ + result = strdup(value); + + return result; +} + +/* + * show_log_timezone: GUC show_hook for log_timezone + */ +const char * +show_log_timezone(void) +{ + const char *tzn; + + tzn = pg_get_timezone_name(log_timezone); if (tzn != NULL) return tzn; diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c index 00480600690..cd3793497bd 100644 --- a/src/backend/postmaster/syslogger.c +++ b/src/backend/postmaster/syslogger.c @@ -18,7 +18,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/postmaster/syslogger.c,v 1.35 2007/08/02 23:39:44 adunstan Exp $ + * $PostgreSQL: pgsql/src/backend/postmaster/syslogger.c,v 1.36 2007/08/04 01:26:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1038,7 +1038,6 @@ logfile_getname(pg_time_t timestamp) { char *filename; int len; - struct pg_tm *tm; filename = palloc(MAXPGPATH); @@ -1049,8 +1048,8 @@ logfile_getname(pg_time_t timestamp) if (strchr(Log_filename, '%')) { /* treat it as a strftime pattern */ - tm = pg_localtime(×tamp, global_timezone); - pg_strftime(filename + len, MAXPGPATH - len, Log_filename, tm); + pg_strftime(filename + len, MAXPGPATH - len, Log_filename, + pg_localtime(×tamp, log_timezone)); } else { @@ -1079,12 +1078,12 @@ set_next_rotation_time(void) /* * The requirements here are to choose the next time > now that is a * "multiple" of the log rotation interval. "Multiple" can be interpreted - * fairly loosely. In this version we align to local time rather than + * fairly loosely. In this version we align to log_timezone rather than * GMT. */ rotinterval = Log_RotationAge * SECS_PER_MINUTE; /* convert to seconds */ - now = time(NULL); - tm = pg_localtime(&now, global_timezone); + now = (pg_time_t) time(NULL); + tm = pg_localtime(&now, log_timezone); now += tm->tm_gmtoff; now -= now % rotinterval; now += rotinterval; diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c index efc965ae4c3..c3cc78977ff 100644 --- a/src/backend/utils/adt/date.c +++ b/src/backend/utils/adt/date.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.134 2007/07/06 04:15:58 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.135 2007/08/04 01:26:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -360,7 +360,7 @@ date2timestamptz(DateADT dateVal) tm->tm_hour = 0; tm->tm_min = 0; tm->tm_sec = 0; - tz = DetermineTimeZoneOffset(tm, global_timezone); + tz = DetermineTimeZoneOffset(tm, session_timezone); #ifdef HAVE_INT64_TIMESTAMP result = dateVal * USECS_PER_DAY + tz * USECS_PER_SEC; @@ -2239,7 +2239,7 @@ time_timetz(PG_FUNCTION_ARGS) GetCurrentDateTime(tm); time2tm(time, tm, &fsec); - tz = DetermineTimeZoneOffset(tm, global_timezone); + tz = DetermineTimeZoneOffset(tm, session_timezone); result = (TimeTzADT *) palloc(sizeof(TimeTzADT)); diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index ddd4fa6167d..742a328b280 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.181 2007/06/12 15:58:32 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.182 2007/08/04 01:26:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1325,7 +1325,7 @@ DecodeDateTime(char **field, int *ftype, int nf, if (fmask & DTK_M(DTZMOD)) return DTERR_BAD_FORMAT; - *tzp = DetermineTimeZoneOffset(tm, global_timezone); + *tzp = DetermineTimeZoneOffset(tm, session_timezone); } } @@ -1361,7 +1361,7 @@ DetermineTimeZoneOffset(struct pg_tm * tm, pg_tz *tzp) after_isdst; int res; - if (tzp == global_timezone && HasCTZSet) + if (tzp == session_timezone && HasCTZSet) { tm->tm_isdst = 0; /* for lack of a better idea */ return CTimeZone; @@ -2033,7 +2033,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf, tmp->tm_hour = tm->tm_hour; tmp->tm_min = tm->tm_min; tmp->tm_sec = tm->tm_sec; - *tzp = DetermineTimeZoneOffset(tmp, global_timezone); + *tzp = DetermineTimeZoneOffset(tmp, session_timezone); tm->tm_isdst = tmp->tm_isdst; } diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c index 0b54f72e6e0..f9ccd461d87 100644 --- a/src/backend/utils/adt/formatting.c +++ b/src/backend/utils/adt/formatting.c @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------- * formatting.c * - * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.130 2007/06/29 01:51:35 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/formatting.c,v 1.131 2007/08/04 01:26:53 tgl Exp $ * * * Portions Copyright (c) 1999-2007, PostgreSQL Global Development Group @@ -3286,7 +3286,7 @@ to_timestamp(PG_FUNCTION_ARGS) do_to_timestamp(date_txt, fmt, &tm, &fsec); - tz = DetermineTimeZoneOffset(&tm, global_timezone); + tz = DetermineTimeZoneOffset(&tm, session_timezone); if (tm2timestamp(&tm, fsec, &tz, &result) != 0) ereport(ERROR, diff --git a/src/backend/utils/adt/nabstime.c b/src/backend/utils/adt/nabstime.c index 3ec098a39f3..903ca5d6adf 100644 --- a/src/backend/utils/adt/nabstime.c +++ b/src/backend/utils/adt/nabstime.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/nabstime.c,v 1.150 2007/02/27 23:48:08 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/nabstime.c,v 1.151 2007/08/04 01:26:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -112,7 +112,7 @@ abstime2tm(AbsoluteTime _time, int *tzp, struct pg_tm * tm, char **tzn) time -= CTimeZone; if (!HasCTZSet && tzp != NULL) - tx = pg_localtime(&time, global_timezone); + tx = pg_localtime(&time, session_timezone); else tx = pg_gmtime(&time); @@ -474,7 +474,7 @@ timestamp_abstime(PG_FUNCTION_ARGS) result = NOEND_ABSTIME; else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) == 0) { - tz = DetermineTimeZoneOffset(tm, global_timezone); + tz = DetermineTimeZoneOffset(tm, session_timezone); result = tm2abstime(tm, tz); } else @@ -1591,7 +1591,7 @@ timeofday(PG_FUNCTION_ARGS) gettimeofday(&tp, NULL); tt = (pg_time_t) tp.tv_sec; pg_strftime(templ, sizeof(templ), "%a %b %d %H:%M:%S.%%06d %Y %Z", - pg_localtime(&tt, global_timezone)); + pg_localtime(&tt, session_timezone)); snprintf(buf, sizeof(buf), templ, tp.tv_usec); len = VARHDRSZ + strlen(buf); diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index 73b8fbfa308..8d2c9318d86 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.180 2007/07/18 03:13:13 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.181 2007/08/04 01:26:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1494,7 +1494,7 @@ recalc_t: if ((Timestamp) utime == dt) { struct pg_tm *tx = pg_localtime(&utime, - attimezone ? attimezone : global_timezone); + attimezone ? attimezone : session_timezone); tm->tm_year = tx->tm_year + 1900; tm->tm_mon = tx->tm_mon + 1; @@ -2675,7 +2675,7 @@ timestamptz_pl_interval(PG_FUNCTION_ARGS) if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]) tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]); - tz = DetermineTimeZoneOffset(tm, global_timezone); + tz = DetermineTimeZoneOffset(tm, session_timezone); if (tm2timestamp(tm, fsec, &tz, ×tamp) != 0) ereport(ERROR, @@ -2699,7 +2699,7 @@ timestamptz_pl_interval(PG_FUNCTION_ARGS) julian = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + span->day; j2date(julian, &tm->tm_year, &tm->tm_mon, &tm->tm_mday); - tz = DetermineTimeZoneOffset(tm, global_timezone); + tz = DetermineTimeZoneOffset(tm, session_timezone); if (tm2timestamp(tm, fsec, &tz, ×tamp) != 0) ereport(ERROR, @@ -3546,7 +3546,7 @@ timestamptz_trunc(PG_FUNCTION_ARGS) } if (redotz) - tz = DetermineTimeZoneOffset(tm, global_timezone); + tz = DetermineTimeZoneOffset(tm, session_timezone); if (tm2timestamp(tm, fsec, &tz, &result) != 0) ereport(ERROR, @@ -4010,7 +4010,7 @@ timestamp_part(PG_FUNCTION_ARGS) (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); - tz = DetermineTimeZoneOffset(tm, global_timezone); + tz = DetermineTimeZoneOffset(tm, session_timezone); if (tm2timestamp(tm, fsec, &tz, ×tamptz) != 0) ereport(ERROR, @@ -4549,7 +4549,7 @@ timestamp2timestamptz(Timestamp timestamp) (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); - tz = DetermineTimeZoneOffset(tm, global_timezone); + tz = DetermineTimeZoneOffset(tm, session_timezone); if (tm2timestamp(tm, fsec, &tz, &result) != 0) ereport(ERROR, diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index 78993a24ebe..d51dd0bf1af 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -42,7 +42,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.191 2007/08/02 23:39:44 adunstan Exp $ + * $PostgreSQL: pgsql/src/backend/utils/error/elog.c,v 1.192 2007/08/04 01:26:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1495,33 +1495,18 @@ log_line_prefix(StringInfo buf) break; case 'm': { - /* - * Note: for %m, %t, and %s we deliberately use the C - * library's strftime/localtime, and not the equivalent - * functions from src/timezone. This ensures that all - * backends will report log entries in the same timezone, - * namely whatever C-library setting they inherit from the - * postmaster. If we used src/timezone then local - * settings of the TimeZone GUC variable would confuse the - * log. - */ - time_t stamp_time; + struct timeval tv; + pg_time_t stamp_time; char strfbuf[128], msbuf[8]; - struct timeval tv; gettimeofday(&tv, NULL); - stamp_time = tv.tv_sec; + stamp_time = (pg_time_t) tv.tv_sec; - strftime(strfbuf, sizeof(strfbuf), - /* leave room for milliseconds... */ - /* Win32 timezone names are too long so don't print them */ -#ifndef WIN32 - "%Y-%m-%d %H:%M:%S %Z", -#else - "%Y-%m-%d %H:%M:%S ", -#endif - localtime(&stamp_time)); + pg_strftime(strfbuf, sizeof(strfbuf), + /* leave room for milliseconds... */ + "%Y-%m-%d %H:%M:%S %Z", + pg_localtime(&stamp_time, log_timezone)); /* 'paste' milliseconds into place... */ sprintf(msbuf, ".%03d", (int) (tv.tv_usec / 1000)); @@ -1532,32 +1517,23 @@ log_line_prefix(StringInfo buf) break; case 't': { - time_t stamp_time = time(NULL); + pg_time_t stamp_time = (pg_time_t) time(NULL); char strfbuf[128]; - strftime(strfbuf, sizeof(strfbuf), - /* Win32 timezone names are too long so don't print them */ -#ifndef WIN32 - "%Y-%m-%d %H:%M:%S %Z", -#else - "%Y-%m-%d %H:%M:%S", -#endif - localtime(&stamp_time)); + pg_strftime(strfbuf, sizeof(strfbuf), + "%Y-%m-%d %H:%M:%S %Z", + pg_localtime(&stamp_time, log_timezone)); appendStringInfoString(buf, strfbuf); } break; case 's': { + pg_time_t stamp_time = (pg_time_t) MyStartTime; char strfbuf[128]; - strftime(strfbuf, sizeof(strfbuf), - /* Win32 timezone names are too long so don't print them */ -#ifndef WIN32 - "%Y-%m-%d %H:%M:%S %Z", -#else - "%Y-%m-%d %H:%M:%S", -#endif - localtime(&MyStartTime)); + pg_strftime(strfbuf, sizeof(strfbuf), + "%Y-%m-%d %H:%M:%S %Z", + pg_localtime(&stamp_time, log_timezone)); appendStringInfoString(buf, strfbuf); } break; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index c30d8b50a05..fc35b14cf3f 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut <peter_e@gmx.net>. * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.408 2007/08/01 22:45:09 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.409 2007/08/04 01:26:54 tgl Exp $ * *-------------------------------------------------------------------- */ @@ -255,6 +255,7 @@ static char *server_encoding_string; static char *server_version_string; static int server_version_num; static char *timezone_string; +static char *log_timezone_string; static char *timezone_abbreviations_string; static char *XactIsoLevel_string; static char *data_directory; @@ -1984,6 +1985,14 @@ static struct config_string ConfigureNamesString[] = "", NULL, NULL }, + { + {"log_timezone", PGC_SIGHUP, LOGGING_WHAT, + gettext_noop("Sets the time zone to use in log messages."), + NULL + }, + &log_timezone_string, + "UNKNOWN", assign_log_timezone, show_log_timezone + }, { {"DateStyle", PGC_USERSET, CLIENT_CONN_LOCALE, diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index c87e4baf43d..ef6cae299cb 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -347,6 +347,8 @@ #log_temp_files = -1 # Log temporary files equal or larger # than specified number of kilobytes. # -1 disables; 0 logs all temp files +#log_timezone = unknown # actually, defaults to TZ + # environment setting #--------------------------------------------------------------------------- # RUNTIME STATISTICS diff --git a/src/include/commands/variable.h b/src/include/commands/variable.h index b1b308fbd0e..ba26233e7de 100644 --- a/src/include/commands/variable.h +++ b/src/include/commands/variable.h @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/commands/variable.h,v 1.29 2007/01/05 22:19:54 momjian Exp $ + * $PostgreSQL: pgsql/src/include/commands/variable.h,v 1.30 2007/08/04 01:26:54 tgl Exp $ */ #ifndef VARIABLE_H #define VARIABLE_H @@ -18,6 +18,9 @@ extern const char *assign_datestyle(const char *value, extern const char *assign_timezone(const char *value, bool doit, GucSource source); extern const char *show_timezone(void); +extern const char *assign_log_timezone(const char *value, + bool doit, GucSource source); +extern const char *show_log_timezone(void); extern const char *assign_XactIsoLevel(const char *value, bool doit, GucSource source); extern const char *show_XactIsoLevel(void); diff --git a/src/include/pgtime.h b/src/include/pgtime.h index f9056c90e0a..b1ff5eac44d 100644 --- a/src/include/pgtime.h +++ b/src/include/pgtime.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/include/pgtime.h,v 1.15 2007/01/05 22:19:50 momjian Exp $ + * $PostgreSQL: pgsql/src/include/pgtime.h,v 1.16 2007/08/04 01:26:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -62,7 +62,8 @@ extern pg_tzenum *pg_tzenumerate_start(void); extern pg_tz *pg_tzenumerate_next(pg_tzenum *dir); extern void pg_tzenumerate_end(pg_tzenum *dir); -extern pg_tz *global_timezone; +extern pg_tz *session_timezone; +extern pg_tz *log_timezone; /* Maximum length of a timezone name (not including trailing null) */ #define TZ_STRLEN_MAX 255 diff --git a/src/timezone/pgtz.c b/src/timezone/pgtz.c index ac97e981530..26ff1ea1129 100644 --- a/src/timezone/pgtz.c +++ b/src/timezone/pgtz.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/timezone/pgtz.c,v 1.51 2007/05/31 15:13:06 petere Exp $ + * $PostgreSQL: pgsql/src/timezone/pgtz.c,v 1.52 2007/08/04 01:26:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -27,8 +27,11 @@ #include "utils/guc.h" #include "utils/hsearch.h" -/* Current global timezone */ -pg_tz *global_timezone = NULL; +/* Current session timezone (controlled by TimeZone GUC) */ +pg_tz *session_timezone = NULL; + +/* Current log timezone (controlled by log_timezone GUC) */ +pg_tz *log_timezone = NULL; static char tzdir[MAXPGPATH]; @@ -38,8 +41,8 @@ static bool scan_directory_ci(const char *dirname, const char *fname, int fnamelen, char *canonname, int canonnamelen); static const char *identify_system_timezone(void); -static const char *select_default_timezone(void); -static bool set_global_timezone(const char *tzname); +static pg_tz *get_pg_tz_for_zone(const char *tzname); +static pg_tz *select_default_timezone(void); /* @@ -1196,51 +1199,51 @@ tz_acceptable(pg_tz *tz) /* - * Set the global timezone. Verify that it's acceptable first. + * Get a pg_tz struct for the given timezone name. Returns NULL if name + * is invalid or not an "acceptable" zone. */ -static bool -set_global_timezone(const char *tzname) +static pg_tz * +get_pg_tz_for_zone(const char *tzname) { - pg_tz *tznew; + pg_tz *tz; if (!tzname || !tzname[0]) - return false; + return NULL; - tznew = pg_tzset(tzname); - if (!tznew) - return false; + tz = pg_tzset(tzname); + if (!tz) + return NULL; - if (!tz_acceptable(tznew)) - return false; + if (!tz_acceptable(tz)) + return NULL; - global_timezone = tznew; - return true; + return tz; } /* - * Identify a suitable default timezone setting based on the environment, - * and make it active. + * Identify a suitable default timezone setting based on the environment. * * We first look to the TZ environment variable. If not found or not * recognized by our own code, we see if we can identify the timezone * from the behavior of the system timezone library. When all else fails, * fall back to GMT. */ -static const char * +static pg_tz * select_default_timezone(void) { - const char *def_tz; + pg_tz *def_tz; - def_tz = getenv("TZ"); - if (set_global_timezone(def_tz)) + def_tz = get_pg_tz_for_zone(getenv("TZ")); + if (def_tz) return def_tz; - def_tz = identify_system_timezone(); - if (set_global_timezone(def_tz)) + def_tz = get_pg_tz_for_zone(identify_system_timezone()); + if (def_tz) return def_tz; - if (set_global_timezone("GMT")) - return "GMT"; + def_tz = get_pg_tz_for_zone("GMT"); + if (def_tz) + return def_tz; ereport(FATAL, (errmsg("could not select a suitable default timezone"), @@ -1253,19 +1256,34 @@ select_default_timezone(void) * * This is called after initial loading of postgresql.conf. If no TimeZone * setting was found therein, we try to derive one from the environment. + * Likewise for log_timezone. */ void pg_timezone_initialize(void) { - /* Do we need to try to figure the timezone? */ + pg_tz *def_tz = NULL; + + /* Do we need to try to figure the session timezone? */ if (pg_strcasecmp(GetConfigOption("timezone"), "UNKNOWN") == 0) { - const char *def_tz; - /* Select setting */ def_tz = select_default_timezone(); + session_timezone = def_tz; + /* Tell GUC about the value. Will redundantly call pg_tzset() */ + SetConfigOption("timezone", pg_get_timezone_name(def_tz), + PGC_POSTMASTER, PGC_S_ARGV); + } + + /* What about the log timezone? */ + if (pg_strcasecmp(GetConfigOption("log_timezone"), "UNKNOWN") == 0) + { + /* Select setting, but don't duplicate work */ + if (!def_tz) + def_tz = select_default_timezone(); + log_timezone = def_tz; /* Tell GUC about the value. Will redundantly call pg_tzset() */ - SetConfigOption("timezone", def_tz, PGC_POSTMASTER, PGC_S_ARGV); + SetConfigOption("log_timezone", pg_get_timezone_name(def_tz), + PGC_POSTMASTER, PGC_S_ARGV); } } |