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 */
5556JSONTYPE_NULL ,/* null, so we didn't bother to identify */
5657JSONTYPE_BOOL ,/* boolean (built-in types only) */
5758JSONTYPE_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 ,
6062JSONTYPE_JSON ,/* JSON itself (and JSONB) */
6163JSONTYPE_ARRAY ,/* array */
6264JSONTYPE_COMPOSITE ,/* composite */
@@ -1267,6 +1269,10 @@ json_categorize_type(Oid typoid,
12671269* tcategory = JSONTYPE_NUMERIC ;
12681270break ;
12691271
1272+ case DATEOID :
1273+ * tcategory = JSONTYPE_DATE ;
1274+ break ;
1275+
12701276case TIMESTAMPOID :
12711277* tcategory = JSONTYPE_TIMESTAMP ;
12721278break ;
@@ -1348,7 +1354,7 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
13481354tcategory == JSONTYPE_CAST ))
13491355ereport (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
13531359switch (tcategory )
13541360{
@@ -1388,6 +1394,30 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
13881394}
13891395pfree (outputstr );
13901396break ;
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 ;
13911421case JSONTYPE_TIMESTAMP :
13921422{
13931423Timestamp timestamp ;
@@ -1410,7 +1440,7 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
14101440(errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
14111441errmsg ("timestamp out of range" )));
14121442
1413- appendStringInfo (result ,"\"%s\"" ,buf );
1443+ appendStringInfo (result ,"\"%s\"" ,buf );
14141444}
14151445break ;
14161446case JSONTYPE_TIMESTAMPTZ :
@@ -1437,7 +1467,7 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
14371467(errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
14381468errmsg ("timestamp out of range" )));
14391469
1440- appendStringInfo (result ,"\"%s\"" ,buf );
1470+ appendStringInfo (result ,"\"%s\"" ,buf );
14411471}
14421472break ;
14431473case JSONTYPE_JSON :
@@ -2305,20 +2335,21 @@ escape_json(StringInfo buf, const char *str)
23052335appendStringInfoString (buf ,"\\\"" );
23062336break ;
23072337case '\\' :
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 */
23232354if (p [1 ]== 'u' &&
23242355isxdigit ((unsignedchar )p [2 ])&&