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

Commit 79afe6e

Browse files
committed
Render infinite date/timestamps as 'infinity' for json/jsonb
Commit ab14a73 raised an error in these cases and later the behaviour was copied to jsonb. This is what the XML code, which we then adopted, does, as the XSD types don't accept infinite values. However, json dates and timestamps are just strings as far as json is concerned, so there is no reason not to render these values as 'infinity'. The json portion of this is backpatched to 9.4 where the behaviour was introduced. The jsonb portion only affects the development branch. Per gripe on pgsql-general.
1 parent d721151 commit 79afe6e

File tree

4 files changed

+76
-21
lines changed

4 files changed

+76
-21
lines changed

src/backend/utils/adt/json.c

+22-21
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
#include "utils/typcache.h"
3434
#include "utils/syscache.h"
3535

36+
/* String to output for infinite dates and timestamps */
37+
#define DT_INFINITY "\"infinity\""
38+
3639
/*
3740
* The context of the parser is maintained by the recursive descent
3841
* mechanism, but is passed explicitly to the error reporting routine
@@ -1427,20 +1430,18 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
14271430

14281431
date = DatumGetDateADT(val);
14291432

1430-
/* XSD doesn't support infinite values */
14311433
if (DATE_NOT_FINITE(date))
1432-
ereport(ERROR,
1433-
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1434-
errmsg("date out of range"),
1435-
errdetail("JSON does not support infinite date values.")));
1434+
{
1435+
/* we have to format infinity ourselves */
1436+
appendStringInfoString(result,DT_INFINITY);
1437+
}
14361438
else
14371439
{
14381440
j2date(date + POSTGRES_EPOCH_JDATE,
14391441
&(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
14401442
EncodeDateOnly(&tm, USE_XSD_DATES, buf);
1443+
appendStringInfo(result, "\"%s\"", buf);
14411444
}
1442-
1443-
appendStringInfo(result, "\"%s\"", buf);
14441445
}
14451446
break;
14461447
case JSONTYPE_TIMESTAMP:
@@ -1452,20 +1453,20 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
14521453

14531454
timestamp = DatumGetTimestamp(val);
14541455

1455-
/* XSD doesn't support infinite values */
14561456
if (TIMESTAMP_NOT_FINITE(timestamp))
1457-
ereport(ERROR,
1458-
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1459-
errmsg("timestamp out of range"),
1460-
errdetail("JSON does not support infinite timestamp values.")));
1457+
{
1458+
/* we have to format infinity ourselves */
1459+
appendStringInfoString(result,DT_INFINITY);
1460+
}
14611461
else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
1462+
{
14621463
EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
1464+
appendStringInfo(result, "\"%s\"", buf);
1465+
}
14631466
else
14641467
ereport(ERROR,
14651468
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
14661469
errmsg("timestamp out of range")));
1467-
1468-
appendStringInfo(result, "\"%s\"", buf);
14691470
}
14701471
break;
14711472
case JSONTYPE_TIMESTAMPTZ:
@@ -1479,20 +1480,20 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
14791480

14801481
timestamp = DatumGetTimestamp(val);
14811482

1482-
/* XSD doesn't support infinite values */
14831483
if (TIMESTAMP_NOT_FINITE(timestamp))
1484-
ereport(ERROR,
1485-
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
1486-
errmsg("timestamp out of range"),
1487-
errdetail("JSON does not support infinite timestamp values.")));
1484+
{
1485+
/* we have to format infinity ourselves */
1486+
appendStringInfoString(result,DT_INFINITY);
1487+
}
14881488
else if (timestamp2tm(timestamp, &tz, &tm, &fsec, &tzn, NULL) == 0)
1489+
{
14891490
EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
1491+
appendStringInfo(result, "\"%s\"", buf);
1492+
}
14901493
else
14911494
ereport(ERROR,
14921495
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
14931496
errmsg("timestamp out of range")));
1494-
1495-
appendStringInfo(result, "\"%s\"", buf);
14961497
}
14971498
break;
14981499
case JSONTYPE_JSON:

src/test/regress/expected/json.out

+24
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,30 @@ select to_json(timestamptz '2014-05-28 12:22:35.614298-04');
426426
(1 row)
427427

428428
COMMIT;
429+
select to_json(date '2014-05-28');
430+
to_json
431+
--------------
432+
"2014-05-28"
433+
(1 row)
434+
435+
select to_json(date 'Infinity');
436+
to_json
437+
------------
438+
"infinity"
439+
(1 row)
440+
441+
select to_json(timestamp 'Infinity');
442+
to_json
443+
------------
444+
"infinity"
445+
(1 row)
446+
447+
select to_json(timestamptz 'Infinity');
448+
to_json
449+
------------
450+
"infinity"
451+
(1 row)
452+
429453
--json_agg
430454
SELECT json_agg(q)
431455
FROM ( SELECT $$a$$ || x AS b, y AS c,

src/test/regress/expected/json_1.out

+24
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,30 @@ select to_json(timestamptz '2014-05-28 12:22:35.614298-04');
426426
(1 row)
427427

428428
COMMIT;
429+
select to_json(date '2014-05-28');
430+
to_json
431+
--------------
432+
"2014-05-28"
433+
(1 row)
434+
435+
select to_json(date 'Infinity');
436+
to_json
437+
------------
438+
"infinity"
439+
(1 row)
440+
441+
select to_json(timestamp 'Infinity');
442+
to_json
443+
------------
444+
"infinity"
445+
(1 row)
446+
447+
select to_json(timestamptz 'Infinity');
448+
to_json
449+
------------
450+
"infinity"
451+
(1 row)
452+
429453
--json_agg
430454
SELECT json_agg(q)
431455
FROM ( SELECT $$a$$ || x AS b, y AS c,

src/test/regress/sql/json.sql

+6
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,12 @@ SET LOCAL TIME ZONE -8;
111111
select to_json(timestamptz '2014-05-28 12:22:35.614298-04');
112112
COMMIT;
113113

114+
select to_json(date '2014-05-28');
115+
116+
select to_json(date 'Infinity');
117+
select to_json(timestamp 'Infinity');
118+
select to_json(timestamptz 'Infinity');
119+
114120
--json_agg
115121

116122
SELECT json_agg(q)

0 commit comments

Comments
 (0)