|
24 | 24 | #include "parser/parse_coerce.h"
|
25 | 25 | #include "utils/array.h"
|
26 | 26 | #include "utils/builtins.h"
|
| 27 | +#include "utils/formatting.h" |
27 | 28 | #include "utils/lsyscache.h"
|
28 | 29 | #include "utils/json.h"
|
29 | 30 | #include "utils/jsonapi.h"
|
@@ -53,13 +54,22 @@ typedef enum /* type categories for datum_to_json */
|
53 | 54 | JSONTYPE_NULL, /* null, so we didn't bother to identify */
|
54 | 55 | JSONTYPE_BOOL, /* boolean (built-in types only) */
|
55 | 56 | JSONTYPE_NUMERIC, /* numeric (ditto) */
|
| 57 | + JSONTYPE_TIMESTAMP, /* we use special formatting for timestamp */ |
| 58 | + JSONTYPE_TIMESTAMPTZ, /* ... and timestamptz */ |
56 | 59 | JSONTYPE_JSON, /* JSON itself (and JSONB) */
|
57 | 60 | JSONTYPE_ARRAY, /* array */
|
58 | 61 | JSONTYPE_COMPOSITE, /* composite */
|
59 | 62 | JSONTYPE_CAST, /* something with an explicit cast to JSON */
|
60 | 63 | JSONTYPE_OTHER /* all else */
|
61 | 64 | } JsonTypeCategory;
|
62 | 65 |
|
| 66 | +/* |
| 67 | + * to_char formats to turn timestamps and timpstamptzs into json strings |
| 68 | + * that are ISO 8601 compliant |
| 69 | + */ |
| 70 | +#define TS_ISO8601_FMT "\\\"YYYY-MM-DD\"T\"HH24:MI:SS.US\\\"" |
| 71 | +#define TSTZ_ISO8601_FMT "\\\"YYYY-MM-DD\"T\"HH24:MI:SS.USOF\\\"" |
| 72 | + |
63 | 73 | static inline void json_lex(JsonLexContext *lex);
|
64 | 74 | static inline void json_lex_string(JsonLexContext *lex);
|
65 | 75 | static inline void json_lex_number(JsonLexContext *lex, char *s, bool *num_err);
|
@@ -1262,6 +1272,14 @@ json_categorize_type(Oid typoid,
|
1262 | 1272 | *tcategory = JSONTYPE_NUMERIC;
|
1263 | 1273 | break;
|
1264 | 1274 |
|
| 1275 | + case TIMESTAMPOID: |
| 1276 | + *tcategory = JSONTYPE_TIMESTAMP; |
| 1277 | + break; |
| 1278 | + |
| 1279 | + case TIMESTAMPTZOID: |
| 1280 | + *tcategory = JSONTYPE_TIMESTAMPTZ; |
| 1281 | + break; |
| 1282 | + |
1265 | 1283 | case JSONOID:
|
1266 | 1284 | case JSONBOID:
|
1267 | 1285 | *tcategory = JSONTYPE_JSON;
|
@@ -1375,6 +1393,29 @@ datum_to_json(Datum val, bool is_null, StringInfo result,
|
1375 | 1393 | }
|
1376 | 1394 | pfree(outputstr);
|
1377 | 1395 | break;
|
| 1396 | + case JSONTYPE_TIMESTAMP: |
| 1397 | + /* |
| 1398 | + * The timestamp format used here provides for quoting the string, |
| 1399 | + * so no escaping is required. |
| 1400 | + */ |
| 1401 | + jsontext = DatumGetTextP( |
| 1402 | + DirectFunctionCall2(timestamp_to_char, val, |
| 1403 | + CStringGetTextDatum(TS_ISO8601_FMT))); |
| 1404 | + outputstr = text_to_cstring(jsontext); |
| 1405 | + appendStringInfoString(result, outputstr); |
| 1406 | + pfree(outputstr); |
| 1407 | + pfree(jsontext); |
| 1408 | + break; |
| 1409 | + case JSONTYPE_TIMESTAMPTZ: |
| 1410 | + /* same comment as for timestamp above */ |
| 1411 | + jsontext = DatumGetTextP( |
| 1412 | + DirectFunctionCall2(timestamptz_to_char, val, |
| 1413 | + CStringGetTextDatum(TSTZ_ISO8601_FMT))); |
| 1414 | + outputstr = text_to_cstring(jsontext); |
| 1415 | + appendStringInfoString(result, outputstr); |
| 1416 | + pfree(outputstr); |
| 1417 | + pfree(jsontext); |
| 1418 | + break; |
1378 | 1419 | case JSONTYPE_JSON:
|
1379 | 1420 | /* JSON and JSONB output will already be escaped */
|
1380 | 1421 | outputstr = OidOutputFunctionCall(outfuncoid, val);
|
|
0 commit comments