mirror of
https://github.com/postgres/postgres.git
synced 2025-11-19 13:42:17 +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:
@@ -3133,18 +3133,6 @@ populate_scalar(ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv,
|
||||
|
||||
json = jsv->val.json.str;
|
||||
Assert(json);
|
||||
if (len >= 0)
|
||||
{
|
||||
/* Need to copy non-null-terminated string */
|
||||
str = palloc(len + 1 * sizeof(char));
|
||||
memcpy(str, json, len);
|
||||
str[len] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
/* string is already null-terminated */
|
||||
str = unconstify(char *, json);
|
||||
}
|
||||
|
||||
/* If converting to json/jsonb, make string into valid JSON literal */
|
||||
if ((typid == JSONOID || typid == JSONBOID) &&
|
||||
@@ -3153,12 +3141,24 @@ populate_scalar(ScalarIOData *io, Oid typid, int32 typmod, JsValue *jsv,
|
||||
StringInfoData buf;
|
||||
|
||||
initStringInfo(&buf);
|
||||
escape_json(&buf, str);
|
||||
/* free temporary buffer */
|
||||
if (str != json)
|
||||
pfree(str);
|
||||
if (len >= 0)
|
||||
escape_json_with_len(&buf, json, len);
|
||||
else
|
||||
escape_json(&buf, json);
|
||||
str = buf.data;
|
||||
}
|
||||
else if (len >= 0)
|
||||
{
|
||||
/* create a NUL-terminated version */
|
||||
str = palloc(len + 1);
|
||||
memcpy(str, json, len);
|
||||
str[len] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
/* string is already NUL-terminated */
|
||||
str = unconstify(char *, json);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -5936,7 +5936,7 @@ transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype
|
||||
{
|
||||
text *out = _state->action(_state->action_state, token, strlen(token));
|
||||
|
||||
escape_json(_state->strval, text_to_cstring(out));
|
||||
escape_json_text(_state->strval, out);
|
||||
}
|
||||
else
|
||||
appendStringInfoString(_state->strval, token);
|
||||
|
||||
Reference in New Issue
Block a user