Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita239af0

Browse files
committed
Fix the various forms of AT TIME ZONE to accept either timezones found
in the zic database or zone names found in the date token table. Thispreserves the old ability to do AT TIME ZONE 'PST' along with the newability to do AT TIME ZONE 'PST8PDT'. Per gripe from Bricklen Anderson.Also, fix some inconsistencies in usage of TZ_STRLEN_MAX --- the oldcode had the potential for one-byte buffer overruns, though givenalignment considerations it's unlikely there was any real risk.
1 parent48123de commita239af0

File tree

6 files changed

+140
-88
lines changed

6 files changed

+140
-88
lines changed

‎doc/src/sgml/datetime.sgml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/datetime.sgml,v 2.46 2005/06/15 00:34:08 momjian Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/datetime.sgml,v 2.47 2005/09/09 02:31:48 tgl Exp $
33
-->
44

55
<appendix id="datetime-appendix">
@@ -990,9 +990,7 @@ $PostgreSQL: pgsql/doc/src/sgml/datetime.sgml,v 2.46 2005/06/15 00:34:08 momjian
990990
<para>
991991
<xref linkend="datetime-timezone-set-table"> shows the time zone
992992
names recognized by <productname>PostgreSQL</productname> as valid
993-
settings for the <xref linkend="guc-timezone"> parameter, and as
994-
parameters to the <literal>AT TIME ZONE function</> (see
995-
<xref linkend="functions-datetime-zoneconvert">). Note that
993+
settings for the <xref linkend="guc-timezone"> parameter. Note that
996994
these names are conceptually as well as practically different from
997995
the names shown in <xref linkend="datetime-timezone-input-table">:
998996
most of these names imply a local daylight-savings time rule, whereas
@@ -1006,7 +1004,7 @@ $PostgreSQL: pgsql/doc/src/sgml/datetime.sgml,v 2.46 2005/06/15 00:34:08 momjian
10061004
</para>
10071005

10081006
<table id="datetime-timezone-set-table">
1009-
<title>Time Zone Names for Setting <varname>timezone</> and <literal>AT TIME ZONE</></title>
1007+
<title>Time Zone Names for Setting <varname>timezone</></title>
10101008
<tgroup cols="1">
10111009
<thead>
10121010
<row>

‎doc/src/sgml/func.sgml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.283 2005/08/25 01:29:55 momjian Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.284 2005/09/09 02:31:48 tgl Exp $
33
PostgreSQL documentation
44
-->
55

@@ -5730,9 +5730,9 @@ SELECT date_trunc('year', TIMESTAMP '2001-02-16 20:38:40');
57305730
In these expressions, the desired time zone <replaceable>zone</> can be
57315731
specified either as a text string (e.g., <literal>'PST'</literal>)
57325732
or as an interval (e.g., <literal>INTERVAL '-08:00'</literal>).
5733-
In the text case, the available zone names are those shown in
5734-
<xref linkend="datetime-timezone-set-table">. The time zone can
5735-
also be implied using the default time zone for that session.
5733+
In the text case, the available zone names are those shown in either
5734+
<xref linkend="datetime-timezone-set-table"> or
5735+
<xref linkend="datetime-timezone-input-table">.
57365736
</para>
57375737

57385738
<para>

‎src/backend/utils/adt/date.c

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.119 2005/07/23 14:25:33 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.120 2005/09/09 02:31:49 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -2484,37 +2484,53 @@ timetz_zone(PG_FUNCTION_ARGS)
24842484
TimeTzADT*t=PG_GETARG_TIMETZADT_P(1);
24852485
TimeTzADT*result;
24862486
inttz;
2487-
chartzname[TZ_STRLEN_MAX];
2487+
chartzname[TZ_STRLEN_MAX+1];
24882488
intlen;
24892489
pg_tz*tzp;
2490-
structpg_tm*tm;
2491-
pg_time_tnow;
24922490

2493-
/* Find the specified timezone */
2494-
len= (VARSIZE(zone)-VARHDRSZ>TZ_STRLEN_MAX) ?
2495-
TZ_STRLEN_MAX :VARSIZE(zone)-VARHDRSZ;
2491+
/*
2492+
* Look up the requested timezone. First we look in the timezone
2493+
* database (to handle cases like "America/New_York"), and if that
2494+
* fails, we look in the date token table (to handle cases like "EST").
2495+
*/
2496+
len=Min(VARSIZE(zone)-VARHDRSZ,TZ_STRLEN_MAX);
24962497
memcpy(tzname,VARDATA(zone),len);
2497-
tzname[len]=0;
2498+
tzname[len]='\0';
24982499
tzp=pg_tzset(tzname);
2499-
if (!tzp) {
2500-
ereport(ERROR,
2501-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2502-
errmsg("time zone \"%s\" not recognized",tzname)));
2503-
PG_RETURN_NULL();
2500+
if (tzp)
2501+
{
2502+
/* Get the offset-from-GMT that is valid today for the selected zone */
2503+
pg_time_tnow;
2504+
structpg_tm*tm;
2505+
2506+
now=time(NULL);
2507+
tm=pg_localtime(&now,tzp);
2508+
tz=-tm->tm_gmtoff;
25042509
}
2510+
else
2511+
{
2512+
char*lowzone;
2513+
inttype,
2514+
val;
25052515

2506-
/* Get the offset-from-GMT that is valid today for the selected zone */
2507-
if ((now=time(NULL))<0||
2508-
(tm=pg_localtime(&now,tzp))==NULL) {
2509-
ereport(ERROR,
2510-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2511-
errmsg("could not determine current time")));
2512-
PG_RETURN_NULL();
2516+
lowzone=downcase_truncate_identifier(VARDATA(zone),
2517+
VARSIZE(zone)-VARHDRSZ,
2518+
false);
2519+
type=DecodeSpecial(0,lowzone,&val);
2520+
2521+
if (type==TZ||type==DTZ)
2522+
tz=val*60;
2523+
else
2524+
{
2525+
ereport(ERROR,
2526+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2527+
errmsg("time zone \"%s\" not recognized",tzname)));
2528+
tz=0;/* keep compiler quiet */
2529+
}
25132530
}
25142531

2515-
result= (TimeTzADT*)palloc(sizeof(TimeTzADT));
2532+
result= (TimeTzADT*)palloc(sizeof(TimeTzADT));
25162533

2517-
tz=-tm->tm_gmtoff;
25182534
#ifdefHAVE_INT64_TIMESTAMP
25192535
result->time=t->time+ (t->zone-tz)*USECS_PER_SEC;
25202536
while (result->time<INT64CONST(0))

‎src/backend/utils/adt/timestamp.c

Lines changed: 90 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.151 2005/08/25 05:01:43 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.152 2005/09/09 02:31:49 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1014,7 +1014,7 @@ dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
10141014
* 0 on success
10151015
*-1 on out of range
10161016
*
1017-
* If attimezone is NULL, the global timezone (includingpossblly brute forced
1017+
* If attimezone is NULL, the global timezone (includingpossibly brute forced
10181018
* timezone) will be used.
10191019
*/
10201020
int
@@ -1113,8 +1113,8 @@ timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, char **tzn,
11131113
utime= (pg_time_t)dt;
11141114
if ((Timestamp)utime==dt)
11151115
{
1116-
structpg_tm*tx=pg_localtime(&utime, (attimezone!=NULL) ?
1117-
attimezone :global_timezone);
1116+
structpg_tm*tx=pg_localtime(&utime,
1117+
attimezone?attimezone:global_timezone);
11181118

11191119
tm->tm_year=tx->tm_year+1900;
11201120
tm->tm_mon=tx->tm_mon+1;
@@ -3948,48 +3948,64 @@ Datum
39483948
timestamp_zone(PG_FUNCTION_ARGS)
39493949
{
39503950
text*zone=PG_GETARG_TEXT_P(0);
3951-
Timestamptimestamp=PG_GETARG_TIMESTAMP(1);
3951+
Timestamptimestamp=PG_GETARG_TIMESTAMP(1);
39523952
TimestampTzresult;
39533953
inttz;
39543954
pg_tz*tzp;
3955-
chartzname[TZ_STRLEN_MAX+1];
3955+
chartzname[TZ_STRLEN_MAX+1];
39563956
intlen;
3957-
structpg_tmtm;
3958-
fsec_tfsec;
3959-
boolfail;
39603957

39613958
if (TIMESTAMP_NOT_FINITE(timestamp))
39623959
PG_RETURN_TIMESTAMPTZ(timestamp);
39633960

3964-
/* Find the specified timezone */
3965-
len= (VARSIZE(zone)-VARHDRSZ>TZ_STRLEN_MAX) ?
3966-
TZ_STRLEN_MAX :VARSIZE(zone)-VARHDRSZ;
3961+
/*
3962+
* Look up the requested timezone. First we look in the timezone
3963+
* database (to handle cases like "America/New_York"), and if that
3964+
* fails, we look in the date token table (to handle cases like "EST").
3965+
*/
3966+
len=Min(VARSIZE(zone)-VARHDRSZ,TZ_STRLEN_MAX);
39673967
memcpy(tzname,VARDATA(zone),len);
3968-
tzname[len]=0;
3968+
tzname[len]='\0';
39693969
tzp=pg_tzset(tzname);
3970-
if (!tzp)
3970+
if (tzp)
39713971
{
3972-
ereport(ERROR,
3973-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3974-
errmsg("time zone \"%s\" not recognised",
3975-
tzname)));
3976-
PG_RETURN_NULL();
3977-
}
3972+
/* Apply the timezone change */
3973+
structpg_tmtm;
3974+
fsec_tfsec;
39783975

3979-
/* Apply the timezone change */
3980-
fail= (timestamp2tm(timestamp,NULL,&tm,&fsec,NULL,tzp)!=0);
3981-
if (!fail)
3982-
{
3976+
if (timestamp2tm(timestamp,NULL,&tm,&fsec,NULL,tzp)!=0)
3977+
ereport(ERROR,
3978+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
3979+
errmsg("timestamp out of range")));
39833980
tz=DetermineTimeZoneOffset(&tm,tzp);
3984-
fail= (tm2timestamp(&tm,fsec,&tz,&result)!=0);
3981+
if (tm2timestamp(&tm,fsec,&tz,&result)!=0)
3982+
ereport(ERROR,
3983+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3984+
errmsg("could not convert to time zone \"%s\"",
3985+
tzname)));
39853986
}
3986-
if (fail)
3987+
else
39873988
{
3988-
ereport(ERROR,
3989-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3990-
errmsg("could not convert to time zone \"%s\"",
3991-
tzname)));
3992-
PG_RETURN_NULL();
3989+
char*lowzone;
3990+
inttype,
3991+
val;
3992+
3993+
lowzone=downcase_truncate_identifier(VARDATA(zone),
3994+
VARSIZE(zone)-VARHDRSZ,
3995+
false);
3996+
type=DecodeSpecial(0,lowzone,&val);
3997+
3998+
if (type==TZ||type==DTZ)
3999+
tz=-(val*60);
4000+
else
4001+
{
4002+
ereport(ERROR,
4003+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4004+
errmsg("time zone \"%s\" not recognized",tzname)));
4005+
tz=0;/* keep compiler quiet */
4006+
}
4007+
4008+
result=dt2local(timestamp,tz);
39934009
}
39944010

39954011
PG_RETURN_TIMESTAMPTZ(result);
@@ -4109,37 +4125,59 @@ timestamptz_zone(PG_FUNCTION_ARGS)
41094125
Timestampresult;
41104126
inttz;
41114127
pg_tz*tzp;
4112-
chartzname[TZ_STRLEN_MAX];
4128+
chartzname[TZ_STRLEN_MAX+1];
41134129
intlen;
4114-
structpg_tmtm;
4115-
fsec_tfsec=0;
41164130

41174131
if (TIMESTAMP_NOT_FINITE(timestamp))
4118-
PG_RETURN_NULL();
4132+
PG_RETURN_TIMESTAMP(timestamp);
41194133

4120-
/* Find the specified zone */
4121-
len= (VARSIZE(zone)-VARHDRSZ>TZ_STRLEN_MAX) ?
4122-
TZ_STRLEN_MAX :VARSIZE(zone)-VARHDRSZ;
4134+
/*
4135+
* Look up the requested timezone. First we look in the timezone
4136+
* database (to handle cases like "America/New_York"), and if that
4137+
* fails, we look in the date token table (to handle cases like "EST").
4138+
*/
4139+
len=Min(VARSIZE(zone)-VARHDRSZ,TZ_STRLEN_MAX);
41234140
memcpy(tzname,VARDATA(zone),len);
4124-
tzname[len]=0;
4141+
tzname[len]='\0';
41254142
tzp=pg_tzset(tzname);
4126-
4127-
if (!tzp)
4143+
if (tzp)
41284144
{
4129-
ereport(ERROR,
4130-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4131-
errmsg("time zone \"%s\" not recognized",tzname)));
4145+
/* Apply the timezone change */
4146+
structpg_tmtm;
4147+
fsec_tfsec;
41324148

4133-
PG_RETURN_NULL();
4149+
if (timestamp2tm(timestamp,&tz,&tm,&fsec,NULL,tzp)!=0)
4150+
ereport(ERROR,
4151+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
4152+
errmsg("timestamp out of range")));
4153+
if (tm2timestamp(&tm,fsec,NULL,&result)!=0)
4154+
ereport(ERROR,
4155+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4156+
errmsg("could not convert to time zone \"%s\"",
4157+
tzname)));
41344158
}
4159+
else
4160+
{
4161+
char*lowzone;
4162+
inttype,
4163+
val;
41354164

4136-
if (timestamp2tm(timestamp,&tz,&tm,&fsec,NULL,tzp)!=0||
4137-
tm2timestamp(&tm,fsec,NULL,&result))
4138-
{
4139-
ereport(ERROR,
4140-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4141-
errmsg("could not to convert to time zone \"%s\"",tzname)));
4142-
PG_RETURN_NULL();
4165+
lowzone=downcase_truncate_identifier(VARDATA(zone),
4166+
VARSIZE(zone)-VARHDRSZ,
4167+
false);
4168+
type=DecodeSpecial(0,lowzone,&val);
4169+
4170+
if (type==TZ||type==DTZ)
4171+
tz=val*60;
4172+
else
4173+
{
4174+
ereport(ERROR,
4175+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4176+
errmsg("time zone \"%s\" not recognized",tzname)));
4177+
tz=0;/* keep compiler quiet */
4178+
}
4179+
4180+
result=dt2local(timestamp,tz);
41434181
}
41444182

41454183
PG_RETURN_TIMESTAMP(result);

‎src/include/pgtime.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
77
*
88
* IDENTIFICATION
9-
* $PostgreSQL: pgsql/src/include/pgtime.h,v 1.9 2005/07/22 03:46:34 momjian Exp $
9+
* $PostgreSQL: pgsql/src/include/pgtime.h,v 1.10 2005/09/09 02:31:49 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -58,7 +58,7 @@ extern const char *pg_get_timezone_name(pg_tz *tz);
5858

5959
externpg_tz*global_timezone;
6060

61-
/* Maximum length of a timezone name */
61+
/* Maximum length of a timezone name(not including trailing null)*/
6262
#defineTZ_STRLEN_MAX 255
6363

6464
#endif/* _PGTIME_H */

‎src/timezone/pgtz.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
77
*
88
* IDENTIFICATION
9-
* $PostgreSQL: pgsql/src/timezone/pgtz.c,v 1.36 2005/06/26 23:32:34 tgl Exp $
9+
* $PostgreSQL: pgsql/src/timezone/pgtz.c,v 1.37 2005/09/09 02:31:50 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -974,7 +974,7 @@ init_timezone_hashtable(void)
974974

975975
MemSet(&hash_ctl,0,sizeof(hash_ctl));
976976

977-
hash_ctl.keysize=TZ_STRLEN_MAX;
977+
hash_ctl.keysize=TZ_STRLEN_MAX+1;
978978
hash_ctl.entrysize=sizeof(pg_tz);
979979

980980
timezone_cache=hash_create("Timezones",
@@ -997,7 +997,7 @@ pg_tzset(const char *name)
997997
pg_tz*tzp;
998998
pg_tztz;
999999

1000-
if (strlen(name) >=TZ_STRLEN_MAX)
1000+
if (strlen(name)>TZ_STRLEN_MAX)
10011001
returnNULL;/* not going to fit */
10021002

10031003
if (!timezone_cache)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp