aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/json.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/json.c')
-rw-r--r--src/backend/utils/adt/json.c55
1 files changed, 43 insertions, 12 deletions
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index 68132aea4bf..494a0285267 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -25,6 +25,7 @@
#include "parser/parse_coerce.h"
#include "utils/array.h"
#include "utils/builtins.h"
+#include "utils/date.h"
#include "utils/datetime.h"
#include "utils/lsyscache.h"
#include "utils/json.h"
@@ -55,8 +56,9 @@ typedef enum /* type categories for datum_to_json */
JSONTYPE_NULL, /* null, so we didn't bother to identify */
JSONTYPE_BOOL, /* boolean (built-in types only) */
JSONTYPE_NUMERIC, /* numeric (ditto) */
- JSONTYPE_TIMESTAMP, /* we use special formatting for timestamp */
- JSONTYPE_TIMESTAMPTZ, /* ... and timestamptz */
+ JSONTYPE_DATE, /* we use special formatting for datetimes */
+ JSONTYPE_TIMESTAMP,
+ JSONTYPE_TIMESTAMPTZ,
JSONTYPE_JSON, /* JSON itself (and JSONB) */
JSONTYPE_ARRAY, /* array */
JSONTYPE_COMPOSITE, /* composite */
@@ -1267,6 +1269,10 @@ json_categorize_type(Oid typoid,
*tcategory = JSONTYPE_NUMERIC;
break;
+ case DATEOID:
+ *tcategory = JSONTYPE_DATE;
+ break;
+
case TIMESTAMPOID:
*tcategory = JSONTYPE_TIMESTAMP;
break;
@@ -1348,7 +1354,7 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
tcategory == JSONTYPE_CAST))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("key value must be scalar, not array, composite, or json")));
+ errmsg("key value must be scalar, not array, composite, or json")));
switch (tcategory)
{
@@ -1388,6 +1394,30 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
}
pfree(outputstr);
break;
+ case JSONTYPE_DATE:
+ {
+ DateADT date;
+ struct pg_tm tm;
+ char buf[MAXDATELEN + 1];
+
+ date = DatumGetDateADT(val);
+
+ /* XSD doesn't support infinite values */
+ if (DATE_NOT_FINITE(date))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
+ errmsg("date out of range"),
+ errdetail("JSON does not support infinite date values.")));
+ else
+ {
+ j2date(date + POSTGRES_EPOCH_JDATE,
+ &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
+ EncodeDateOnly(&tm, USE_XSD_DATES, buf);
+ }
+
+ appendStringInfo(result, "\"%s\"", buf);
+ }
+ break;
case JSONTYPE_TIMESTAMP:
{
Timestamp timestamp;
@@ -1410,7 +1440,7 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("timestamp out of range")));
- appendStringInfo(result,"\"%s\"",buf);
+ appendStringInfo(result, "\"%s\"", buf);
}
break;
case JSONTYPE_TIMESTAMPTZ:
@@ -1437,7 +1467,7 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("timestamp out of range")));
- appendStringInfo(result,"\"%s\"",buf);
+ appendStringInfo(result, "\"%s\"", buf);
}
break;
case JSONTYPE_JSON:
@@ -2305,20 +2335,21 @@ escape_json(StringInfo buf, const char *str)
appendStringInfoString(buf, "\\\"");
break;
case '\\':
+
/*
* Unicode escapes are passed through as is. There is no
* requirement that they denote a valid character in the
* server encoding - indeed that is a big part of their
* usefulness.
*
- * All we require is that they consist of \uXXXX where
- * the Xs are hexadecimal digits. It is the responsibility
- * of the caller of, say, to_json() to make sure that the
- * unicode escape is valid.
+ * All we require is that they consist of \uXXXX where the Xs
+ * are hexadecimal digits. It is the responsibility of the
+ * caller of, say, to_json() to make sure that the unicode
+ * escape is valid.
*
- * In the case of a jsonb string value being escaped, the
- * only unicode escape that should be present is \u0000,
- * all the other unicode escapes will have been resolved.
+ * In the case of a jsonb string value being escaped, the only
+ * unicode escape that should be present is \u0000, all the
+ * other unicode escapes will have been resolved.
*/
if (p[1] == 'u' &&
isxdigit((unsigned char) p[2]) &&