diff options
Diffstat (limited to 'src/backend/utils/adt/jsonfuncs.c')
-rw-r--r-- | src/backend/utils/adt/jsonfuncs.c | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 376a9b7ab82..2d293da18ef 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -527,6 +527,12 @@ pg_parse_json_or_errsave(JsonLexContext *lex, JsonSemAction *sem, JsonLexContext * makeJsonLexContext(text *json, bool need_escapes) { + /* + * Most callers pass a detoasted datum, but it's not clear that they all + * do. pg_detoast_datum_packed() is cheap insurance. + */ + json = pg_detoast_datum_packed(json); + return makeJsonLexContextCstringLen(VARDATA_ANY(json), VARSIZE_ANY_EXHDR(json), GetDatabaseEncoding(), @@ -1559,9 +1565,11 @@ jsonb_get_element(Jsonb *jb, Datum *path, int npath, bool *isnull, bool as_text) { if (have_object) { + text *subscr = DatumGetTextPP(path[i]); + jbvp = getKeyJsonValueFromContainer(container, - VARDATA(path[i]), - VARSIZE(path[i]) - VARHDRSZ, + VARDATA_ANY(subscr), + VARSIZE_ANY_EXHDR(subscr), NULL); } else if (have_array) @@ -1734,8 +1742,8 @@ push_path(JsonbParseState **st, int level, Datum *path_elems, { /* text, an object is expected */ newkey.type = jbvString; - newkey.val.string.len = VARSIZE_ANY_EXHDR(path_elems[i]); - newkey.val.string.val = VARDATA_ANY(path_elems[i]); + newkey.val.string.val = c; + newkey.val.string.len = strlen(c); (void) pushJsonbValue(st, WJB_BEGIN_OBJECT, NULL); (void) pushJsonbValue(st, WJB_KEY, &newkey); @@ -4456,6 +4464,7 @@ jsonb_delete_array(PG_FUNCTION_ARGS) if (keys_nulls[i]) continue; + /* We rely on the array elements not being toasted */ keyptr = VARDATA_ANY(keys_elems[i]); keylen = VARSIZE_ANY_EXHDR(keys_elems[i]); if (keylen == v.val.string.len && @@ -4977,6 +4986,7 @@ setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls, int path_len, JsonbParseState **st, int level, JsonbValue *newval, uint32 npairs, int op_type) { + text *pathelem = NULL; int i; JsonbValue k, v; @@ -4984,6 +4994,11 @@ setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls, if (level >= path_len || path_nulls[level]) done = true; + else + { + /* The path Datum could be toasted, in which case we must detoast it */ + pathelem = DatumGetTextPP(path_elems[level]); + } /* empty object is a special case for create */ if ((npairs == 0) && (op_type & JB_PATH_CREATE_OR_INSERT) && @@ -4992,8 +5007,8 @@ setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls, JsonbValue newkey; newkey.type = jbvString; - newkey.val.string.len = VARSIZE_ANY_EXHDR(path_elems[level]); - newkey.val.string.val = VARDATA_ANY(path_elems[level]); + newkey.val.string.val = VARDATA_ANY(pathelem); + newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem); (void) pushJsonbValue(st, WJB_KEY, &newkey); (void) pushJsonbValue(st, WJB_VALUE, newval); @@ -5006,8 +5021,8 @@ setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls, Assert(r == WJB_KEY); if (!done && - k.val.string.len == VARSIZE_ANY_EXHDR(path_elems[level]) && - memcmp(k.val.string.val, VARDATA_ANY(path_elems[level]), + k.val.string.len == VARSIZE_ANY_EXHDR(pathelem) && + memcmp(k.val.string.val, VARDATA_ANY(pathelem), k.val.string.len) == 0) { done = true; @@ -5047,8 +5062,8 @@ setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls, JsonbValue newkey; newkey.type = jbvString; - newkey.val.string.len = VARSIZE_ANY_EXHDR(path_elems[level]); - newkey.val.string.val = VARDATA_ANY(path_elems[level]); + newkey.val.string.val = VARDATA_ANY(pathelem); + newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem); (void) pushJsonbValue(st, WJB_KEY, &newkey); (void) pushJsonbValue(st, WJB_VALUE, newval); @@ -5091,8 +5106,8 @@ setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_nulls, JsonbValue newkey; newkey.type = jbvString; - newkey.val.string.len = VARSIZE_ANY_EXHDR(path_elems[level]); - newkey.val.string.val = VARDATA_ANY(path_elems[level]); + newkey.val.string.val = VARDATA_ANY(pathelem); + newkey.val.string.len = VARSIZE_ANY_EXHDR(pathelem); (void) pushJsonbValue(st, WJB_KEY, &newkey); (void) push_path(st, level, path_elems, path_nulls, @@ -5505,6 +5520,8 @@ transform_jsonb_string_values(Jsonb *jsonb, void *action_state, if ((type == WJB_VALUE || type == WJB_ELEM) && v.type == jbvString) { out = transform_action(action_state, v.val.string.val, v.val.string.len); + /* out is probably not toasted, but let's be sure */ + out = pg_detoast_datum_packed(out); v.val.string.val = VARDATA_ANY(out); v.val.string.len = VARSIZE_ANY_EXHDR(out); res = pushJsonbValue(&st, type, type < WJB_BEGIN_ARRAY ? &v : NULL); |