@@ -1503,12 +1503,70 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
1503
1503
pfree (outputstr );
1504
1504
break ;
1505
1505
case JSONTYPE_DATE :
1506
+ {
1507
+ char buf [MAXDATELEN + 1 ];
1508
+
1509
+ JsonEncodeDateTime (buf , val , DATEOID );
1510
+ appendStringInfo (result , "\"%s\"" , buf );
1511
+ }
1512
+ break ;
1513
+ case JSONTYPE_TIMESTAMP :
1514
+ {
1515
+ char buf [MAXDATELEN + 1 ];
1516
+
1517
+ JsonEncodeDateTime (buf , val , TIMESTAMPOID );
1518
+ appendStringInfo (result , "\"%s\"" , buf );
1519
+ }
1520
+ break ;
1521
+ case JSONTYPE_TIMESTAMPTZ :
1522
+ {
1523
+ char buf [MAXDATELEN + 1 ];
1524
+
1525
+ JsonEncodeDateTime (buf , val , TIMESTAMPTZOID );
1526
+ appendStringInfo (result , "\"%s\"" , buf );
1527
+ }
1528
+ break ;
1529
+ case JSONTYPE_JSON :
1530
+ /* JSON and JSONB output will already be escaped */
1531
+ outputstr = OidOutputFunctionCall (outfuncoid , val );
1532
+ appendStringInfoString (result , outputstr );
1533
+ pfree (outputstr );
1534
+ break ;
1535
+ case JSONTYPE_CAST :
1536
+ /* outfuncoid refers to a cast function, not an output function */
1537
+ jsontext = DatumGetTextPP (OidFunctionCall1 (outfuncoid , val ));
1538
+ outputstr = text_to_cstring (jsontext );
1539
+ appendStringInfoString (result , outputstr );
1540
+ pfree (outputstr );
1541
+ pfree (jsontext );
1542
+ break ;
1543
+ default :
1544
+ outputstr = OidOutputFunctionCall (outfuncoid , val );
1545
+ escape_json (result , outputstr );
1546
+ pfree (outputstr );
1547
+ break ;
1548
+ }
1549
+ }
1550
+
1551
+ /*
1552
+ * Encode 'value' of datetime type 'typid' into JSON string in ISO format using
1553
+ * optionally preallocated buffer 'buf'.
1554
+ */
1555
+ char *
1556
+ JsonEncodeDateTime (char * buf , Datum value , Oid typid )
1557
+ {
1558
+ if (!buf )
1559
+ buf = palloc (MAXDATELEN + 1 );
1560
+
1561
+ switch (typid )
1562
+ {
1563
+ case DATEOID :
1506
1564
{
1507
1565
DateADT date ;
1508
1566
struct pg_tm tm ;
1509
- char buf [MAXDATELEN + 1 ];
1510
1567
1511
- date = DatumGetDateADT (val );
1568
+ date = DatumGetDateADT (value );
1569
+
1512
1570
/* Same as date_out(), but forcing DateStyle */
1513
1571
if (DATE_NOT_FINITE (date ))
1514
1572
EncodeSpecialDate (date , buf );
@@ -1518,17 +1576,40 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
1518
1576
& (tm .tm_year ), & (tm .tm_mon ), & (tm .tm_mday ));
1519
1577
EncodeDateOnly (& tm , USE_XSD_DATES , buf );
1520
1578
}
1521
- appendStringInfo (result , "\"%s\"" , buf );
1522
1579
}
1523
1580
break ;
1524
- case JSONTYPE_TIMESTAMP :
1581
+ case TIMEOID :
1582
+ {
1583
+ TimeADT time = DatumGetTimeADT (value );
1584
+ struct pg_tm tt ,
1585
+ * tm = & tt ;
1586
+ fsec_t fsec ;
1587
+
1588
+ /* Same as time_out(), but forcing DateStyle */
1589
+ time2tm (time , tm , & fsec );
1590
+ EncodeTimeOnly (tm , fsec , false, 0 , USE_XSD_DATES , buf );
1591
+ }
1592
+ break ;
1593
+ case TIMETZOID :
1594
+ {
1595
+ TimeTzADT * time = DatumGetTimeTzADTP (value );
1596
+ struct pg_tm tt ,
1597
+ * tm = & tt ;
1598
+ fsec_t fsec ;
1599
+ int tz ;
1600
+
1601
+ /* Same as timetz_out(), but forcing DateStyle */
1602
+ timetz2tm (time , tm , & fsec , & tz );
1603
+ EncodeTimeOnly (tm , fsec , true, tz , USE_XSD_DATES , buf );
1604
+ }
1605
+ break ;
1606
+ case TIMESTAMPOID :
1525
1607
{
1526
1608
Timestamp timestamp ;
1527
1609
struct pg_tm tm ;
1528
1610
fsec_t fsec ;
1529
- char buf [MAXDATELEN + 1 ];
1530
1611
1531
- timestamp = DatumGetTimestamp (val );
1612
+ timestamp = DatumGetTimestamp (value );
1532
1613
/* Same as timestamp_out(), but forcing DateStyle */
1533
1614
if (TIMESTAMP_NOT_FINITE (timestamp ))
1534
1615
EncodeSpecialTimestamp (timestamp , buf );
@@ -1538,19 +1619,17 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
1538
1619
ereport (ERROR ,
1539
1620
(errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
1540
1621
errmsg ("timestamp out of range" )));
1541
- appendStringInfo (result , "\"%s\"" , buf );
1542
1622
}
1543
1623
break ;
1544
- case JSONTYPE_TIMESTAMPTZ :
1624
+ case TIMESTAMPTZOID :
1545
1625
{
1546
1626
TimestampTz timestamp ;
1547
1627
struct pg_tm tm ;
1548
1628
int tz ;
1549
1629
fsec_t fsec ;
1550
1630
const char * tzn = NULL ;
1551
- char buf [MAXDATELEN + 1 ];
1552
1631
1553
- timestamp = DatumGetTimestampTz (val );
1632
+ timestamp = DatumGetTimestampTz (value );
1554
1633
/* Same as timestamptz_out(), but forcing DateStyle */
1555
1634
if (TIMESTAMP_NOT_FINITE (timestamp ))
1556
1635
EncodeSpecialTimestamp (timestamp , buf );
@@ -1560,29 +1639,14 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
1560
1639
ereport (ERROR ,
1561
1640
(errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
1562
1641
errmsg ("timestamp out of range" )));
1563
- appendStringInfo (result , "\"%s\"" , buf );
1564
1642
}
1565
1643
break ;
1566
- case JSONTYPE_JSON :
1567
- /* JSON and JSONB output will already be escaped */
1568
- outputstr = OidOutputFunctionCall (outfuncoid , val );
1569
- appendStringInfoString (result , outputstr );
1570
- pfree (outputstr );
1571
- break ;
1572
- case JSONTYPE_CAST :
1573
- /* outfuncoid refers to a cast function, not an output function */
1574
- jsontext = DatumGetTextPP (OidFunctionCall1 (outfuncoid , val ));
1575
- outputstr = text_to_cstring (jsontext );
1576
- appendStringInfoString (result , outputstr );
1577
- pfree (outputstr );
1578
- pfree (jsontext );
1579
- break ;
1580
1644
default :
1581
- outputstr = OidOutputFunctionCall (outfuncoid , val );
1582
- escape_json (result , outputstr );
1583
- pfree (outputstr );
1584
- break ;
1645
+ elog (ERROR , "unknown jsonb value datetime type oid %d" , typid );
1646
+ return NULL ;
1585
1647
}
1648
+
1649
+ return buf ;
1586
1650
}
1587
1651
1588
1652
/*
0 commit comments