#endif
-static int time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec);
-static int timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp);
static int tm2time(struct pg_tm *tm, fsec_t fsec, TimeADT *result);
static int tm2timetz(struct pg_tm *tm, fsec_t fsec, int tz, TimeTzADT *result);
static void AdjustTimeForTypmod(TimeADT *time, int32 typmod);
* If out of this range, leave as UTC (in practice that could only happen
* if pg_time_t is just 32 bits) - thomas 97/05/27
*/
-static int
+int
time2tm(TimeADT time, struct pg_tm *tm, fsec_t *fsec)
{
tm->tm_hour = time / USECS_PER_HOUR;
/* timetz2tm()
* Convert TIME WITH TIME ZONE data type to POSIX time structure.
*/
-static int
+int
timetz2tm(TimeTzADT *time, struct pg_tm *tm, fsec_t *fsec, int *tzp)
{
TimeOffset trem = time->time;
pfree(outputstr);
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);
&(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);
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);
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;
}
/*
}
break;
case JSONBTYPE_DATE:
- {
- DateADT date;
- struct pg_tm tm;
- char buf[MAXDATELEN + 1];
-
- date = DatumGetDateADT(val);
- /* Same as date_out(), but forcing DateStyle */
- if (DATE_NOT_FINITE(date))
- EncodeSpecialDate(date, buf);
- else
- {
- j2date(date + POSTGRES_EPOCH_JDATE,
- &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
- EncodeDateOnly(&tm, USE_XSD_DATES, buf);
- }
- jb.type = jbvString;
- jb.val.string.len = strlen(buf);
- jb.val.string.val = pstrdup(buf);
- }
+ jb.type = jbvString;
+ jb.val.string.val = JsonEncodeDateTime(NULL, val, DATEOID);
+ jb.val.string.len = strlen(jb.val.string.val);
break;
case JSONBTYPE_TIMESTAMP:
- {
- Timestamp timestamp;
- struct pg_tm tm;
- fsec_t fsec;
- char buf[MAXDATELEN + 1];
-
- timestamp = DatumGetTimestamp(val);
- /* Same as timestamp_out(), but forcing DateStyle */
- if (TIMESTAMP_NOT_FINITE(timestamp))
- EncodeSpecialTimestamp(timestamp, buf);
- else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
- EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
- else
- ereport(ERROR,
- (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
- errmsg("timestamp out of range")));
- jb.type = jbvString;
- jb.val.string.len = strlen(buf);
- jb.val.string.val = pstrdup(buf);
- }
+ jb.type = jbvString;
+ jb.val.string.val = JsonEncodeDateTime(NULL, val, TIMESTAMPOID);
+ jb.val.string.len = strlen(jb.val.string.val);
break;
case JSONBTYPE_TIMESTAMPTZ:
- {
- TimestampTz timestamp;
- struct pg_tm tm;
- int tz;
- fsec_t fsec;
- const char *tzn = NULL;
- char buf[MAXDATELEN + 1];
-
- timestamp = DatumGetTimestampTz(val);
- /* Same as timestamptz_out(), but forcing DateStyle */
- if (TIMESTAMP_NOT_FINITE(timestamp))
- EncodeSpecialTimestamp(timestamp, buf);
- else if (timestamp2tm(timestamp, &tz, &tm, &fsec, &tzn, NULL) == 0)
- EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
- else
- ereport(ERROR,
- (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
- errmsg("timestamp out of range")));
- jb.type = jbvString;
- jb.val.string.len = strlen(buf);
- jb.val.string.val = pstrdup(buf);
- }
+ jb.type = jbvString;
+ jb.val.string.val = JsonEncodeDateTime(NULL, val, TIMESTAMPTZOID);
+ jb.val.string.len = strlen(jb.val.string.val);
break;
case JSONBTYPE_JSONCAST:
case JSONBTYPE_JSON: