diff options
author | David Rowley | 2024-07-27 11:46:07 +0000 |
---|---|---|
committer | David Rowley | 2024-07-27 11:46:07 +0000 |
commit | 17a5871d9d58ea639b6d1ba4f0ce58462d55a33c (patch) | |
tree | 197ee9a63a458f6980870bb30f75f3693f449aa9 /contrib | |
parent | 67427f10093a9c50c79e1dbfdcd1698433e8a88f (diff) |
Optimize escaping of JSON strings
There were quite a few places where we either had a non-NUL-terminated
string or a text Datum which we needed to call escape_json() on. Many of
these places required that a temporary string was created due to the fact
that escape_json() needs a NUL-terminated cstring. For text types, those
first had to be converted to cstring before calling escape_json() on them.
Here we introduce two new functions to make escaping JSON more optimal:
escape_json_text() can be given a text Datum to append onto the given
buffer. This is more optimal as it foregoes the need to convert the text
Datum into a cstring. A temporary allocation is only required if the text
Datum needs to be detoasted.
escape_json_with_len() can be used when the length of the cstring is
already known or the given string isn't NUL-terminated. Having this
allows various places which were creating a temporary NUL-terminated
string to just call escape_json_with_len() without any temporary memory
allocations.
Discussion: https://postgr.es/m/CAApHDvpLXwMZvbCKcdGfU9XQjGCDm7tFpRdTXuB9PVgpNUYfEQ@mail.gmail.com
Reviewed-by: Melih Mutlu, Heikki Linnakangas
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/hstore/hstore_io.c | 41 |
1 files changed, 17 insertions, 24 deletions
diff --git a/contrib/hstore/hstore_io.c b/contrib/hstore/hstore_io.c index 999ddad76d9..2125436e40c 100644 --- a/contrib/hstore/hstore_io.c +++ b/contrib/hstore/hstore_io.c @@ -1343,23 +1343,20 @@ hstore_to_json_loose(PG_FUNCTION_ARGS) int count = HS_COUNT(in); char *base = STRPTR(in); HEntry *entries = ARRPTR(in); - StringInfoData tmp, - dst; + StringInfoData dst; if (count == 0) PG_RETURN_TEXT_P(cstring_to_text_with_len("{}", 2)); - initStringInfo(&tmp); initStringInfo(&dst); appendStringInfoChar(&dst, '{'); for (i = 0; i < count; i++) { - resetStringInfo(&tmp); - appendBinaryStringInfo(&tmp, HSTORE_KEY(entries, base, i), - HSTORE_KEYLEN(entries, i)); - escape_json(&dst, tmp.data); + escape_json_with_len(&dst, + HSTORE_KEY(entries, base, i), + HSTORE_KEYLEN(entries, i)); appendStringInfoString(&dst, ": "); if (HSTORE_VALISNULL(entries, i)) appendStringInfoString(&dst, "null"); @@ -1372,13 +1369,13 @@ hstore_to_json_loose(PG_FUNCTION_ARGS) appendStringInfoString(&dst, "false"); else { - resetStringInfo(&tmp); - appendBinaryStringInfo(&tmp, HSTORE_VAL(entries, base, i), - HSTORE_VALLEN(entries, i)); - if (IsValidJsonNumber(tmp.data, tmp.len)) - appendBinaryStringInfo(&dst, tmp.data, tmp.len); + char *str = HSTORE_VAL(entries, base, i); + int len = HSTORE_VALLEN(entries, i); + + if (IsValidJsonNumber(str, len)) + appendBinaryStringInfo(&dst, str, len); else - escape_json(&dst, tmp.data); + escape_json_with_len(&dst, str, len); } if (i + 1 != count) @@ -1398,32 +1395,28 @@ hstore_to_json(PG_FUNCTION_ARGS) int count = HS_COUNT(in); char *base = STRPTR(in); HEntry *entries = ARRPTR(in); - StringInfoData tmp, - dst; + StringInfoData dst; if (count == 0) PG_RETURN_TEXT_P(cstring_to_text_with_len("{}", 2)); - initStringInfo(&tmp); initStringInfo(&dst); appendStringInfoChar(&dst, '{'); for (i = 0; i < count; i++) { - resetStringInfo(&tmp); - appendBinaryStringInfo(&tmp, HSTORE_KEY(entries, base, i), - HSTORE_KEYLEN(entries, i)); - escape_json(&dst, tmp.data); + escape_json_with_len(&dst, + HSTORE_KEY(entries, base, i), + HSTORE_KEYLEN(entries, i)); appendStringInfoString(&dst, ": "); if (HSTORE_VALISNULL(entries, i)) appendStringInfoString(&dst, "null"); else { - resetStringInfo(&tmp); - appendBinaryStringInfo(&tmp, HSTORE_VAL(entries, base, i), - HSTORE_VALLEN(entries, i)); - escape_json(&dst, tmp.data); + escape_json_with_len(&dst, + HSTORE_VAL(entries, base, i), + HSTORE_VALLEN(entries, i)); } if (i + 1 != count) |