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.c37
1 files changed, 29 insertions, 8 deletions
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index 71ae53ff975..0778d8dec92 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -220,13 +220,22 @@ datum_to_json_internal(Datum val, bool is_null, StringInfo result,
outputstr = OidOutputFunctionCall(outfuncoid, val);
/*
- * Don't call escape_json for a non-key if it's a valid JSON
- * number.
+ * Don't quote a non-key if it's a valid JSON number (i.e., not
+ * "Infinity", "-Infinity", or "NaN"). Since we know this is a
+ * numeric data type's output, we simplify and open-code the
+ * validation for better performance.
*/
- if (!key_scalar && IsValidJsonNumber(outputstr, strlen(outputstr)))
+ if (!key_scalar &&
+ ((*outputstr >= '0' && *outputstr <= '9') ||
+ (*outputstr == '-' &&
+ (outputstr[1] >= '0' && outputstr[1] <= '9'))))
appendStringInfoString(result, outputstr);
else
- escape_json(result, outputstr);
+ {
+ appendStringInfoChar(result, '"');
+ appendStringInfoString(result, outputstr);
+ appendStringInfoChar(result, '"');
+ }
pfree(outputstr);
break;
case JSONTYPE_DATE:
@@ -234,7 +243,9 @@ datum_to_json_internal(Datum val, bool is_null, StringInfo result,
char buf[MAXDATELEN + 1];
JsonEncodeDateTime(buf, val, DATEOID, NULL);
- appendStringInfo(result, "\"%s\"", buf);
+ appendStringInfoChar(result, '"');
+ appendStringInfoString(result, buf);
+ appendStringInfoChar(result, '"');
}
break;
case JSONTYPE_TIMESTAMP:
@@ -242,7 +253,9 @@ datum_to_json_internal(Datum val, bool is_null, StringInfo result,
char buf[MAXDATELEN + 1];
JsonEncodeDateTime(buf, val, TIMESTAMPOID, NULL);
- appendStringInfo(result, "\"%s\"", buf);
+ appendStringInfoChar(result, '"');
+ appendStringInfoString(result, buf);
+ appendStringInfoChar(result, '"');
}
break;
case JSONTYPE_TIMESTAMPTZ:
@@ -250,7 +263,9 @@ datum_to_json_internal(Datum val, bool is_null, StringInfo result,
char buf[MAXDATELEN + 1];
JsonEncodeDateTime(buf, val, TIMESTAMPTZOID, NULL);
- appendStringInfo(result, "\"%s\"", buf);
+ appendStringInfoChar(result, '"');
+ appendStringInfoString(result, buf);
+ appendStringInfoChar(result, '"');
}
break;
case JSONTYPE_JSON:
@@ -503,8 +518,14 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
int i;
bool needsep = false;
const char *sep;
+ int seplen;
+ /*
+ * We can avoid expensive strlen() calls by precalculating the separator
+ * length.
+ */
sep = use_line_feeds ? ",\n " : ",";
+ seplen = use_line_feeds ? strlen(",\n ") : strlen(",");
td = DatumGetHeapTupleHeader(composite);
@@ -533,7 +554,7 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
continue;
if (needsep)
- appendStringInfoString(result, sep);
+ appendBinaryStringInfo(result, sep, seplen);
needsep = true;
attname = NameStr(att->attname);