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

Commita303e4d

Browse files
committed
Extend the date type to support infinity and -infinity, analogously to
the timestamp types. Turns out this doesn't even reduce the availablerange of dates, since the restriction to dates that work for Julian-datearithmetic is much tighter than the int32 range anyway. Per a longstandingTODO item.
1 parent791359f commita303e4d

File tree

9 files changed

+206
-65
lines changed

9 files changed

+206
-65
lines changed

‎doc/src/sgml/datatype.sgml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.229 2008/10/03 15:37:18 petere Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.230 2008/10/14 17:12:32 tgl Exp $ -->
22

33
<chapter id="datatype">
44
<title id="datatype-title">Data Types</title>
@@ -2032,12 +2032,12 @@ January 8 04:05:06 1999 PST
20322032
</row>
20332033
<row>
20342034
<entry><literal>infinity</literal></entry>
2035-
<entry><type>timestamp</type></entry>
2035+
<entry><type>date</type>, <type>timestamp</type></entry>
20362036
<entry>later than all other time stamps</entry>
20372037
</row>
20382038
<row>
20392039
<entry><literal>-infinity</literal></entry>
2040-
<entry><type>timestamp</type></entry>
2040+
<entry><type>date</type>, <type>timestamp</type></entry>
20412041
<entry>earlier than all other time stamps</entry>
20422042
</row>
20432043
<row>

‎doc/src/sgml/func.sgml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.449 2008/10/13 16:25:19 tgl Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.450 2008/10/14 17:12:32 tgl Exp $ -->
22

33
<chapter id="functions">
44
<title>Functions and Operators</title>
@@ -5912,10 +5912,18 @@ SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
59125912
<entry><literal>3</literal></entry>
59135913
</row>
59145914

5915+
<row>
5916+
<entry><literal><function>isfinite</function>(<type>date</type>)</literal></entry>
5917+
<entry><type>boolean</type></entry>
5918+
<entry>Test for finite date (not +/-infinity)</entry>
5919+
<entry><literal>isfinite(date '2001-02-16')</literal></entry>
5920+
<entry><literal>true</literal></entry>
5921+
</row>
5922+
59155923
<row>
59165924
<entry><literal><function>isfinite</function>(<type>timestamp</type>)</literal></entry>
59175925
<entry><type>boolean</type></entry>
5918-
<entry>Test for finite time stamp (notequal toinfinity)</entry>
5926+
<entry>Test for finite time stamp (not+/-infinity)</entry>
59195927
<entry><literal>isfinite(timestamp '2001-02-16 21:28:30')</literal></entry>
59205928
<entry><literal>true</literal></entry>
59215929
</row>

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

Lines changed: 132 additions & 55 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.142 2008/07/07 18:09:46 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.143 2008/10/14 17:12:33 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -38,6 +38,7 @@
3838
#endif
3939

4040

41+
staticvoidEncodeSpecialDate(DateADTdt,char*str);
4142
staticinttime2tm(TimeADTtime,structpg_tm*tm,fsec_t*fsec);
4243
staticinttimetz2tm(TimeTzADT*time,structpg_tm*tm,fsec_t*fsec,int*tzp);
4344
staticinttm2time(structpg_tm*tm,fsec_tfsec,TimeADT*result);
@@ -147,6 +148,14 @@ date_in(PG_FUNCTION_ARGS)
147148
GetEpochTime(tm);
148149
break;
149150

151+
caseDTK_LATE:
152+
DATE_NOEND(date);
153+
PG_RETURN_DATEADT(date);
154+
155+
caseDTK_EARLY:
156+
DATE_NOBEGIN(date);
157+
PG_RETURN_DATEADT(date);
158+
150159
default:
151160
DateTimeParseError(DTERR_BAD_FORMAT,str,"date");
152161
break;
@@ -174,10 +183,14 @@ date_out(PG_FUNCTION_ARGS)
174183
*tm=&tt;
175184
charbuf[MAXDATELEN+1];
176185

177-
j2date(date+POSTGRES_EPOCH_JDATE,
178-
&(tm->tm_year),&(tm->tm_mon),&(tm->tm_mday));
179-
180-
EncodeDateOnly(tm,DateStyle,buf);
186+
if (DATE_NOT_FINITE(date))
187+
EncodeSpecialDate(date,buf);
188+
else
189+
{
190+
j2date(date+POSTGRES_EPOCH_JDATE,
191+
&(tm->tm_year),&(tm->tm_mon),&(tm->tm_mday));
192+
EncodeDateOnly(tm,DateStyle,buf);
193+
}
181194

182195
result=pstrdup(buf);
183196
PG_RETURN_CSTRING(result);
@@ -208,6 +221,20 @@ date_send(PG_FUNCTION_ARGS)
208221
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
209222
}
210223

224+
/*
225+
* Convert reserved date values to string.
226+
*/
227+
staticvoid
228+
EncodeSpecialDate(DateADTdt,char*str)
229+
{
230+
if (DATE_IS_NOBEGIN(dt))
231+
strcpy(str,EARLY);
232+
elseif (DATE_IS_NOEND(dt))
233+
strcpy(str,LATE);
234+
else/* shouldn't happen */
235+
elog(ERROR,"invalid argument for EncodeSpecialDate");
236+
}
237+
211238

212239
/*
213240
* Comparison functions for dates
@@ -280,6 +307,14 @@ date_cmp(PG_FUNCTION_ARGS)
280307
PG_RETURN_INT32(0);
281308
}
282309

310+
Datum
311+
date_finite(PG_FUNCTION_ARGS)
312+
{
313+
DateADTdate=PG_GETARG_DATEADT(0);
314+
315+
PG_RETURN_BOOL(!DATE_NOT_FINITE(date));
316+
}
317+
283318
Datum
284319
date_larger(PG_FUNCTION_ARGS)
285320
{
@@ -306,6 +341,11 @@ date_mi(PG_FUNCTION_ARGS)
306341
DateADTdateVal1=PG_GETARG_DATEADT(0);
307342
DateADTdateVal2=PG_GETARG_DATEADT(1);
308343

344+
if (DATE_NOT_FINITE(dateVal1)||DATE_NOT_FINITE(dateVal2))
345+
ereport(ERROR,
346+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
347+
errmsg("cannot subtract infinite dates")));
348+
309349
PG_RETURN_INT32((int32) (dateVal1-dateVal2));
310350
}
311351

@@ -318,6 +358,9 @@ date_pli(PG_FUNCTION_ARGS)
318358
DateADTdateVal=PG_GETARG_DATEADT(0);
319359
int32days=PG_GETARG_INT32(1);
320360

361+
if (DATE_NOT_FINITE(dateVal))
362+
days=0;/* can't change infinity */
363+
321364
PG_RETURN_DATEADT(dateVal+days);
322365
}
323366

@@ -329,6 +372,9 @@ date_mii(PG_FUNCTION_ARGS)
329372
DateADTdateVal=PG_GETARG_DATEADT(0);
330373
int32days=PG_GETARG_INT32(1);
331374

375+
if (DATE_NOT_FINITE(dateVal))
376+
days=0;/* can't change infinity */
377+
332378
PG_RETURN_DATEADT(dateVal-days);
333379
}
334380

@@ -342,18 +388,25 @@ date2timestamp(DateADT dateVal)
342388
{
343389
Timestampresult;
344390

391+
if (DATE_IS_NOBEGIN(dateVal))
392+
TIMESTAMP_NOBEGIN(result);
393+
elseif (DATE_IS_NOEND(dateVal))
394+
TIMESTAMP_NOEND(result);
395+
else
396+
{
345397
#ifdefHAVE_INT64_TIMESTAMP
346-
/* date is days since 2000, timestamp is microseconds since same... */
347-
result=dateVal*USECS_PER_DAY;
348-
/* Date's range is wider than timestamp's, so must check for overflow */
349-
if (result /USECS_PER_DAY!=dateVal)
350-
ereport(ERROR,
351-
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
352-
errmsg("date out of range for timestamp")));
398+
/* date is days since 2000, timestamp is microseconds since same... */
399+
result=dateVal*USECS_PER_DAY;
400+
/* Date's range is wider than timestamp's, so check for overflow */
401+
if (result /USECS_PER_DAY!=dateVal)
402+
ereport(ERROR,
403+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
404+
errmsg("date out of range for timestamp")));
353405
#else
354-
/* date is days since 2000, timestamp is seconds since same... */
355-
result=dateVal* (double)SECS_PER_DAY;
406+
/* date is days since 2000, timestamp is seconds since same... */
407+
result=dateVal* (double)SECS_PER_DAY;
356408
#endif
409+
}
357410

358411
returnresult;
359412
}
@@ -366,24 +419,30 @@ date2timestamptz(DateADT dateVal)
366419
*tm=&tt;
367420
inttz;
368421

369-
j2date(dateVal+POSTGRES_EPOCH_JDATE,
370-
&(tm->tm_year),&(tm->tm_mon),&(tm->tm_mday));
371-
372-
tm->tm_hour=0;
373-
tm->tm_min=0;
374-
tm->tm_sec=0;
375-
tz=DetermineTimeZoneOffset(tm,session_timezone);
422+
if (DATE_IS_NOBEGIN(dateVal))
423+
TIMESTAMP_NOBEGIN(result);
424+
elseif (DATE_IS_NOEND(dateVal))
425+
TIMESTAMP_NOEND(result);
426+
else
427+
{
428+
j2date(dateVal+POSTGRES_EPOCH_JDATE,
429+
&(tm->tm_year),&(tm->tm_mon),&(tm->tm_mday));
430+
tm->tm_hour=0;
431+
tm->tm_min=0;
432+
tm->tm_sec=0;
433+
tz=DetermineTimeZoneOffset(tm,session_timezone);
376434

377435
#ifdefHAVE_INT64_TIMESTAMP
378-
result=dateVal*USECS_PER_DAY+tz*USECS_PER_SEC;
379-
/* Date's range is wider than timestamp's, so must check for overflow */
380-
if ((result-tz*USECS_PER_SEC) /USECS_PER_DAY!=dateVal)
381-
ereport(ERROR,
382-
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
383-
errmsg("date out of range for timestamp")));
436+
result=dateVal*USECS_PER_DAY+tz*USECS_PER_SEC;
437+
/* Date's range is wider than timestamp's, so check for overflow */
438+
if ((result-tz*USECS_PER_SEC) /USECS_PER_DAY!=dateVal)
439+
ereport(ERROR,
440+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
441+
errmsg("date out of range for timestamp")));
384442
#else
385-
result=dateVal* (double)SECS_PER_DAY+tz;
443+
result=dateVal* (double)SECS_PER_DAY+tz;
386444
#endif
445+
}
387446

388447
returnresult;
389448
}
@@ -797,15 +856,19 @@ timestamp_date(PG_FUNCTION_ARGS)
797856
*tm=&tt;
798857
fsec_tfsec;
799858

800-
if (TIMESTAMP_NOT_FINITE(timestamp))
801-
PG_RETURN_NULL();
802-
803-
if (timestamp2tm(timestamp,NULL,tm,&fsec,NULL,NULL)!=0)
804-
ereport(ERROR,
805-
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
806-
errmsg("timestamp out of range")));
859+
if (TIMESTAMP_IS_NOBEGIN(timestamp))
860+
DATE_NOBEGIN(result);
861+
elseif (TIMESTAMP_IS_NOEND(timestamp))
862+
DATE_NOEND(result);
863+
else
864+
{
865+
if (timestamp2tm(timestamp,NULL,tm,&fsec,NULL,NULL)!=0)
866+
ereport(ERROR,
867+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
868+
errmsg("timestamp out of range")));
807869

808-
result=date2j(tm->tm_year,tm->tm_mon,tm->tm_mday)-POSTGRES_EPOCH_JDATE;
870+
result=date2j(tm->tm_year,tm->tm_mon,tm->tm_mday)-POSTGRES_EPOCH_JDATE;
871+
}
809872

810873
PG_RETURN_DATEADT(result);
811874
}
@@ -840,15 +903,19 @@ timestamptz_date(PG_FUNCTION_ARGS)
840903
inttz;
841904
char*tzn;
842905

843-
if (TIMESTAMP_NOT_FINITE(timestamp))
844-
PG_RETURN_NULL();
845-
846-
if (timestamp2tm(timestamp,&tz,tm,&fsec,&tzn,NULL)!=0)
847-
ereport(ERROR,
848-
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
849-
errmsg("timestamp out of range")));
906+
if (TIMESTAMP_IS_NOBEGIN(timestamp))
907+
DATE_NOBEGIN(result);
908+
elseif (TIMESTAMP_IS_NOEND(timestamp))
909+
DATE_NOEND(result);
910+
else
911+
{
912+
if (timestamp2tm(timestamp,&tz,tm,&fsec,&tzn,NULL)!=0)
913+
ereport(ERROR,
914+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
915+
errmsg("timestamp out of range")));
850916

851-
result=date2j(tm->tm_year,tm->tm_mon,tm->tm_mday)-POSTGRES_EPOCH_JDATE;
917+
result=date2j(tm->tm_year,tm->tm_mon,tm->tm_mday)-POSTGRES_EPOCH_JDATE;
918+
}
852919

853920
PG_RETURN_DATEADT(result);
854921
}
@@ -869,16 +936,19 @@ abstime_date(PG_FUNCTION_ARGS)
869936
switch (abstime)
870937
{
871938
caseINVALID_ABSTIME:
872-
caseNOSTART_ABSTIME:
873-
caseNOEND_ABSTIME:
874939
ereport(ERROR,
875940
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
876941
errmsg("cannot convert reserved abstime value to date")));
942+
result=0;/* keep compiler quiet */
943+
break;
877944

878-
/*
879-
* pretend to drop through to make compiler think that result will
880-
* be set
881-
*/
945+
caseNOSTART_ABSTIME:
946+
DATE_NOBEGIN(result);
947+
break;
948+
949+
caseNOEND_ABSTIME:
950+
DATE_NOEND(result);
951+
break;
882952

883953
default:
884954
abstime2tm(abstime,&tz,tm,NULL);
@@ -1452,9 +1522,9 @@ datetime_timestamp(PG_FUNCTION_ARGS)
14521522
TimeADTtime=PG_GETARG_TIMEADT(1);
14531523
Timestampresult;
14541524

1455-
result=DatumGetTimestamp(DirectFunctionCall1(date_timestamp,
1456-
DateADTGetDatum(date)));
1457-
result+=time;
1525+
result=date2timestamp(date);
1526+
if (!TIMESTAMP_NOT_FINITE(result))
1527+
result+=time;
14581528

14591529
PG_RETURN_TIMESTAMP(result);
14601530
}
@@ -2304,11 +2374,18 @@ datetimetz_timestamptz(PG_FUNCTION_ARGS)
23042374
TimeTzADT*time=PG_GETARG_TIMETZADT_P(1);
23052375
TimestampTzresult;
23062376

2377+
if (DATE_IS_NOBEGIN(date))
2378+
TIMESTAMP_NOBEGIN(result);
2379+
elseif (DATE_IS_NOEND(date))
2380+
TIMESTAMP_NOEND(result);
2381+
else
2382+
{
23072383
#ifdefHAVE_INT64_TIMESTAMP
2308-
result=date*USECS_PER_DAY+time->time+time->zone*USECS_PER_SEC;
2384+
result=date*USECS_PER_DAY+time->time+time->zone*USECS_PER_SEC;
23092385
#else
2310-
result=date* (double)SECS_PER_DAY+time->time+time->zone;
2386+
result=date* (double)SECS_PER_DAY+time->time+time->zone;
23112387
#endif
2388+
}
23122389

23132390
PG_RETURN_TIMESTAMP(result);
23142391
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.78 2008/10/09 15:49:04 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.79 2008/10/14 17:12:33 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -1632,6 +1632,11 @@ map_sql_value_to_xml_value(Datum value, Oid type)
16321632
charbuf[MAXDATELEN+1];
16331633

16341634
date=DatumGetDateADT(value);
1635+
/* XSD doesn't support infinite values */
1636+
if (DATE_NOT_FINITE(date))
1637+
ereport(ERROR,
1638+
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1639+
errmsg("date out of range")));
16351640
j2date(date+POSTGRES_EPOCH_JDATE,
16361641
&(tm.tm_year),&(tm.tm_mon),&(tm.tm_mday));
16371642
EncodeDateOnly(&tm,USE_XSD_DATES,buf);

‎src/include/catalog/catversion.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
3838
* Portions Copyright (c) 1994, Regents of the University of California
3939
*
40-
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.497 2008/10/13 16:25:19 tgl Exp $
40+
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.498 2008/10/14 17:12:33 tgl Exp $
4141
*
4242
*-------------------------------------------------------------------------
4343
*/
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/*yyyymmddN */
56-
#defineCATALOG_VERSION_NO200810131
56+
#defineCATALOG_VERSION_NO200810141
5757

5858
#endif

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp