1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-21 00:42:43 +03:00

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
This commit is contained in:
David Rowley
2024-07-27 23:46:07 +12:00
parent 67427f1009
commit 17a5871d9d
7 changed files with 151 additions and 101 deletions

View File

@@ -523,6 +523,8 @@ printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey,
{
JsonPathItem elem;
int i;
int32 len;
char *str;
check_stack_depth();
CHECK_FOR_INTERRUPTS();
@@ -533,7 +535,8 @@ printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey,
appendStringInfoString(buf, "null");
break;
case jpiString:
escape_json(buf, jspGetString(v, NULL));
str = jspGetString(v, &len);
escape_json_with_len(buf, str, len);
break;
case jpiNumeric:
if (jspHasNext(v))
@@ -662,7 +665,8 @@ printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey,
case jpiKey:
if (inKey)
appendStringInfoChar(buf, '.');
escape_json(buf, jspGetString(v, NULL));
str = jspGetString(v, &len);
escape_json_with_len(buf, str, len);
break;
case jpiCurrent:
Assert(!inKey);
@@ -674,7 +678,8 @@ printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey,
break;
case jpiVariable:
appendStringInfoChar(buf, '$');
escape_json(buf, jspGetString(v, NULL));
str = jspGetString(v, &len);
escape_json_with_len(buf, str, len);
break;
case jpiFilter:
appendStringInfoString(buf, "?(");
@@ -732,7 +737,9 @@ printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey,
appendStringInfoString(buf, " like_regex ");
escape_json(buf, v->content.like_regex.pattern);
escape_json_with_len(buf,
v->content.like_regex.pattern,
v->content.like_regex.patternlen);
if (v->content.like_regex.flags)
{