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.c122
1 files changed, 93 insertions, 29 deletions
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index 151345ab2ff..97a5b85516f 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -1504,11 +1504,69 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
break;
case JSONTYPE_DATE:
{
+ char buf[MAXDATELEN + 1];
+
+ JsonEncodeDateTime(buf, val, DATEOID);
+ appendStringInfo(result, "\"%s\"", buf);
+ }
+ break;
+ case JSONTYPE_TIMESTAMP:
+ {
+ char buf[MAXDATELEN + 1];
+
+ JsonEncodeDateTime(buf, val, TIMESTAMPOID);
+ appendStringInfo(result, "\"%s\"", buf);
+ }
+ break;
+ case JSONTYPE_TIMESTAMPTZ:
+ {
+ char buf[MAXDATELEN + 1];
+
+ JsonEncodeDateTime(buf, val, TIMESTAMPTZOID);
+ appendStringInfo(result, "\"%s\"", buf);
+ }
+ break;
+ case JSONTYPE_JSON:
+ /* JSON and JSONB output will already be escaped */
+ outputstr = OidOutputFunctionCall(outfuncoid, val);
+ appendStringInfoString(result, outputstr);
+ pfree(outputstr);
+ break;
+ case JSONTYPE_CAST:
+ /* outfuncoid refers to a cast function, not an output function */
+ jsontext = DatumGetTextPP(OidFunctionCall1(outfuncoid, val));
+ outputstr = text_to_cstring(jsontext);
+ appendStringInfoString(result, outputstr);
+ pfree(outputstr);
+ pfree(jsontext);
+ break;
+ default:
+ outputstr = OidOutputFunctionCall(outfuncoid, val);
+ escape_json(result, outputstr);
+ pfree(outputstr);
+ break;
+ }
+}
+
+/*
+ * Encode 'value' of datetime type 'typid' into JSON string in ISO format using
+ * optionally preallocated buffer 'buf'.
+ */
+char *
+JsonEncodeDateTime(char *buf, Datum value, Oid typid)
+{
+ if (!buf)
+ buf = palloc(MAXDATELEN + 1);
+
+ switch (typid)
+ {
+ case DATEOID:
+ {
DateADT date;
struct pg_tm tm;
- char buf[MAXDATELEN + 1];
- date = DatumGetDateADT(val);
+ date = DatumGetDateADT(value);
+
/* Same as date_out(), but forcing DateStyle */
if (DATE_NOT_FINITE(date))
EncodeSpecialDate(date, buf);
@@ -1518,17 +1576,40 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
&(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
EncodeDateOnly(&tm, USE_XSD_DATES, buf);
}
- appendStringInfo(result, "\"%s\"", buf);
}
break;
- case JSONTYPE_TIMESTAMP:
+ case TIMEOID:
+ {
+ TimeADT time = DatumGetTimeADT(value);
+ struct pg_tm tt,
+ *tm = &tt;
+ fsec_t fsec;
+
+ /* Same as time_out(), but forcing DateStyle */
+ time2tm(time, tm, &fsec);
+ EncodeTimeOnly(tm, fsec, false, 0, USE_XSD_DATES, buf);
+ }
+ break;
+ case TIMETZOID:
+ {
+ TimeTzADT *time = DatumGetTimeTzADTP(value);
+ struct pg_tm tt,
+ *tm = &tt;
+ fsec_t fsec;
+ int tz;
+
+ /* Same as timetz_out(), but forcing DateStyle */
+ timetz2tm(time, tm, &fsec, &tz);
+ EncodeTimeOnly(tm, fsec, true, tz, USE_XSD_DATES, buf);
+ }
+ break;
+ case TIMESTAMPOID:
{
Timestamp timestamp;
struct pg_tm tm;
fsec_t fsec;
- char buf[MAXDATELEN + 1];
- timestamp = DatumGetTimestamp(val);
+ timestamp = DatumGetTimestamp(value);
/* Same as timestamp_out(), but forcing DateStyle */
if (TIMESTAMP_NOT_FINITE(timestamp))
EncodeSpecialTimestamp(timestamp, buf);
@@ -1538,19 +1619,17 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("timestamp out of range")));
- appendStringInfo(result, "\"%s\"", buf);
}
break;
- case JSONTYPE_TIMESTAMPTZ:
+ case TIMESTAMPTZOID:
{
TimestampTz timestamp;
struct pg_tm tm;
int tz;
fsec_t fsec;
const char *tzn = NULL;
- char buf[MAXDATELEN + 1];
- timestamp = DatumGetTimestampTz(val);
+ timestamp = DatumGetTimestampTz(value);
/* Same as timestamptz_out(), but forcing DateStyle */
if (TIMESTAMP_NOT_FINITE(timestamp))
EncodeSpecialTimestamp(timestamp, buf);
@@ -1560,29 +1639,14 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("timestamp out of range")));
- appendStringInfo(result, "\"%s\"", buf);
}
break;
- case JSONTYPE_JSON:
- /* JSON and JSONB output will already be escaped */
- outputstr = OidOutputFunctionCall(outfuncoid, val);
- appendStringInfoString(result, outputstr);
- pfree(outputstr);
- break;
- case JSONTYPE_CAST:
- /* outfuncoid refers to a cast function, not an output function */
- jsontext = DatumGetTextPP(OidFunctionCall1(outfuncoid, val));
- outputstr = text_to_cstring(jsontext);
- appendStringInfoString(result, outputstr);
- pfree(outputstr);
- pfree(jsontext);
- break;
default:
- outputstr = OidOutputFunctionCall(outfuncoid, val);
- escape_json(result, outputstr);
- pfree(outputstr);
- break;
+ elog(ERROR, "unknown jsonb value datetime type oid %d", typid);
+ return NULL;
}
+
+ return buf;
}
/*