2525#include "parser/parse_coerce.h"
2626#include "utils/array.h"
2727#include "utils/builtins.h"
28+ #include "utils/date.h"
2829#include "utils/datetime.h"
2930#include "utils/lsyscache.h"
3031#include "utils/json.h"
@@ -55,8 +56,9 @@ typedef enum /* type categories for datum_to_json */
5556 JSONTYPE_NULL , /* null, so we didn't bother to identify */
5657 JSONTYPE_BOOL , /* boolean (built-in types only) */
5758 JSONTYPE_NUMERIC , /* numeric (ditto) */
58- JSONTYPE_TIMESTAMP , /* we use special formatting for timestamp */
59- JSONTYPE_TIMESTAMPTZ , /* ... and timestamptz */
59+ JSONTYPE_DATE , /* we use special formatting for datetimes */
60+ JSONTYPE_TIMESTAMP ,
61+ JSONTYPE_TIMESTAMPTZ ,
6062 JSONTYPE_JSON , /* JSON itself (and JSONB) */
6163 JSONTYPE_ARRAY , /* array */
6264 JSONTYPE_COMPOSITE , /* composite */
@@ -1267,6 +1269,10 @@ json_categorize_type(Oid typoid,
12671269 * tcategory = JSONTYPE_NUMERIC ;
12681270 break ;
12691271
1272+ case DATEOID :
1273+ * tcategory = JSONTYPE_DATE ;
1274+ break ;
1275+
12701276 case TIMESTAMPOID :
12711277 * tcategory = JSONTYPE_TIMESTAMP ;
12721278 break ;
@@ -1348,7 +1354,7 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
13481354 tcategory == JSONTYPE_CAST ))
13491355 ereport (ERROR ,
13501356 (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1351- errmsg ("key value must be scalar, not array, composite, or json" )));
1357+ errmsg ("key value must be scalar, not array, composite, or json" )));
13521358
13531359 switch (tcategory )
13541360 {
@@ -1388,6 +1394,30 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
13881394 }
13891395 pfree (outputstr );
13901396 break ;
1397+ case JSONTYPE_DATE :
1398+ {
1399+ DateADT date ;
1400+ struct pg_tm tm ;
1401+ char buf [MAXDATELEN + 1 ];
1402+
1403+ date = DatumGetDateADT (val );
1404+
1405+ /* XSD doesn't support infinite values */
1406+ if (DATE_NOT_FINITE (date ))
1407+ ereport (ERROR ,
1408+ (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
1409+ errmsg ("date out of range" ),
1410+ errdetail ("JSON does not support infinite date values." )));
1411+ else
1412+ {
1413+ j2date (date + POSTGRES_EPOCH_JDATE ,
1414+ & (tm .tm_year ), & (tm .tm_mon ), & (tm .tm_mday ));
1415+ EncodeDateOnly (& tm , USE_XSD_DATES , buf );
1416+ }
1417+
1418+ appendStringInfo (result , "\"%s\"" , buf );
1419+ }
1420+ break ;
13911421 case JSONTYPE_TIMESTAMP :
13921422 {
13931423 Timestamp timestamp ;
@@ -1410,7 +1440,7 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
14101440 (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
14111441 errmsg ("timestamp out of range" )));
14121442
1413- appendStringInfo (result ,"\"%s\"" ,buf );
1443+ appendStringInfo (result , "\"%s\"" , buf );
14141444 }
14151445 break ;
14161446 case JSONTYPE_TIMESTAMPTZ :
@@ -1437,7 +1467,7 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
14371467 (errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
14381468 errmsg ("timestamp out of range" )));
14391469
1440- appendStringInfo (result ,"\"%s\"" ,buf );
1470+ appendStringInfo (result , "\"%s\"" , buf );
14411471 }
14421472 break ;
14431473 case JSONTYPE_JSON :
@@ -2305,20 +2335,21 @@ escape_json(StringInfo buf, const char *str)
23052335 appendStringInfoString (buf , "\\\"" );
23062336 break ;
23072337 case '\\' :
2338+
23082339 /*
23092340 * Unicode escapes are passed through as is. There is no
23102341 * requirement that they denote a valid character in the
23112342 * server encoding - indeed that is a big part of their
23122343 * usefulness.
23132344 *
2314- * All we require is that they consist of \uXXXX where
2315- * the Xs are hexadecimal digits. It is the responsibility
2316- * of the caller of, say, to_json() to make sure that the
2317- * unicode escape is valid.
2345+ * All we require is that they consist of \uXXXX where the Xs
2346+ * are hexadecimal digits. It is the responsibility of the
2347+ * caller of, say, to_json() to make sure that the unicode
2348+ * escape is valid.
23182349 *
2319- * In the case of a jsonb string value being escaped, the
2320- * only unicode escape that should be present is \u0000,
2321- * all the other unicode escapes will have been resolved.
2350+ * In the case of a jsonb string value being escaped, the only
2351+ * unicode escape that should be present is \u0000, all the
2352+ * other unicode escapes will have been resolved.
23222353 */
23232354 if (p [1 ] == 'u' &&
23242355 isxdigit ((unsigned char ) p [2 ]) &&
0 commit comments