aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/transam/xlog.c46
-rw-r--r--src/backend/commands/variable.c113
-rw-r--r--src/backend/postmaster/syslogger.c13
-rw-r--r--src/backend/utils/adt/date.c6
-rw-r--r--src/backend/utils/adt/datetime.c8
-rw-r--r--src/backend/utils/adt/formatting.c4
-rw-r--r--src/backend/utils/adt/nabstime.c8
-rw-r--r--src/backend/utils/adt/timestamp.c14
-rw-r--r--src/backend/utils/error/elog.c56
-rw-r--r--src/backend/utils/misc/guc.c11
-rw-r--r--src/backend/utils/misc/postgresql.conf.sample2
-rw-r--r--src/include/commands/variable.h5
-rw-r--r--src/include/pgtime.h5
-rw-r--r--src/timezone/pgtz.c80
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(&timestamp, global_timezone);
- pg_strftime(filename + len, MAXPGPATH - len, Log_filename, tm);
+ pg_strftime(filename + len, MAXPGPATH - len, Log_filename,
+ pg_localtime(&timestamp, 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, &timestamp) != 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, &timestamp) != 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, &timestamptz) != 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);
}
}