From ca61cc95f6fac4457067a9055a1c10910adf8af8 Mon Sep 17 00:00:00 2001 From: nnuanyang Date: Tue, 19 Dec 2023 23:34:57 -0800 Subject: [PATCH] jsonb_set bug --- src/common/backend/utils/adt/jsonfuncs.cpp | 8 +-- src/test/regress/expected/jsonb.out | 72 ++++++++++++++-------- src/test/regress/sql/jsonb.sql | 4 ++ 3 files changed, 53 insertions(+), 31 deletions(-) diff --git a/src/common/backend/utils/adt/jsonfuncs.cpp b/src/common/backend/utils/adt/jsonfuncs.cpp index 5fb854b344..04aa1b6f1d 100644 --- a/src/common/backend/utils/adt/jsonfuncs.cpp +++ b/src/common/backend/utils/adt/jsonfuncs.cpp @@ -2740,8 +2740,8 @@ addJsonbToParseState(JsonbParseState **jbps, Jsonb *jb) elog(ERROR, "unexpected parent oe nested structure."); } } else { - while((type == JsonbIteratorNext(&it, &v, false)) != WJB_DONE) { - if (type = WJB_ELEM || type == WJB_KEY || type == WJB_VALUE) { + while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE) { + if (type == WJB_ELEM || type == WJB_KEY || type == WJB_VALUE) { (void)pushJsonbValue(jbps, type, &v); } else { (void)pushJsonbValue(jbps, type, NULL); @@ -2886,7 +2886,6 @@ static void setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_null if (!done && k.string.len == VARSIZE_ANY_EXHDR(pathelem) && memcmp(k.string.val, VARDATA_ANY(pathelem), k.string.len) == 0) { - done = true; if (level == path_len - 1) { /* @@ -2905,6 +2904,7 @@ static void setPathObject(JsonbIterator **it, Datum *path_elems, bool *path_null (void) pushJsonbValue(st, WJB_KEY, &k); addJsonbToParseState(st, newval); } + done = true; } else { (void) pushJsonbValue(st, r, &k); setPath(it, path_elems, path_nulls, path_len, @@ -3014,7 +3014,6 @@ static void setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls int r; if (i == idx && level < path_len) { - done = true; if (level == path_len - 1) { r = JsonbIteratorNext(it, &v, true); /* skip */ @@ -3032,6 +3031,7 @@ static void setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_REPLACE)) addJsonbToParseState(st, newval); + done = true; } else (void) setPath(it, path_elems, path_nulls, path_len, st, level + 1, newval, op_type); } else { diff --git a/src/test/regress/expected/jsonb.out b/src/test/regress/expected/jsonb.out index 8b0cedb7e2..16104bb7a1 100644 --- a/src/test/regress/expected/jsonb.out +++ b/src/test/regress/expected/jsonb.out @@ -2117,55 +2117,55 @@ select jsonb_insert('{"a": {"b": {"c": [0, 1, "test1", "test2"]}}}', '{a, b, c, (1 row) select jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '{"b": "value"}'); - jsonb_insert ------------------- - {"a": [0, 1, 2]} + jsonb_insert +---------------------------------- + {"a": [0, {"b": "value"}, 1, 2]} (1 row) select jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '["value1", "value2"]'); - jsonb_insert ------------------- - {"a": [0, 1, 2]} + jsonb_insert +---------------------------------------- + {"a": [0, ["value1", "value2"], 1, 2]} (1 row) -- jsonb_set select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{n}', '[1,2,3]'); - jsonb_set ----------------------------------------------------------- - {"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [2, 3]}} + jsonb_set +-------------------------------------------------------------------------- + {"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": [1, 2, 3]} (1 row) select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{b,-1}', '[1,2,3]'); - jsonb_set ------------------------------------------------------------------- - {"a": 1, "b": [1], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": null} + jsonb_set +----------------------------------------------------------------------------- + {"a": 1, "b": [1, [1, 2, 3]], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": null} (1 row) select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{d,1,0}', '[1,2,3]'); - jsonb_set ------------------------------------------------------------------- - {"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [3]}, "n": null} + jsonb_set +----------------------------------------------------------------------------- + {"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [[1, 2, 3], 3]}, "n": null} (1 row) select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{d,NULL,0}', '[1,2,3]'); ERROR: path element at position 2 is null CONTEXT: referenced column: jsonb_set select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{n}', '{"1": 2}'); - jsonb_set ----------------------------------------------------------- - {"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [2, 3]}} + jsonb_set +------------------------------------------------------------------------- + {"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": {"1": 2}} (1 row) select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{b,-1}', '{"1": 2}'); - jsonb_set ------------------------------------------------------------------- - {"a": 1, "b": [1], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": null} + jsonb_set +---------------------------------------------------------------------------- + {"a": 1, "b": [1, {"1": 2}], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": null} (1 row) select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{d,1,0}', '{"1": 2}'); - jsonb_set ------------------------------------------------------------------- - {"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [3]}, "n": null} + jsonb_set +---------------------------------------------------------------------------- + {"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [{"1": 2}, 3]}, "n": null} (1 row) select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{d,NULL,0}', '{"1": 2}'); @@ -2178,9 +2178,27 @@ select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::j (1 row) select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{b,-1}', '{"f": "test"}'); - jsonb_set ------------------------------------------------------------------- - {"a": 1, "b": [1], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": null} + jsonb_set +--------------------------------------------------------------------------------- + {"a": 1, "b": [1, {"f": "test"}], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": null} +(1 row) + +select jsonb_set('[{"f1":1,"f2":null},2,null,3]', '{0,f1}', '[2,3,4]', true); + jsonb_set +--------------------------------------------- + [{"f1": [2, 3, 4], "f2": null}, 2, null, 3] +(1 row) + +select jsonb_set('[{"f1":1,"f2":null},{"2":9},{"null":90},{"3":87}]', '{1,2}', '[2,3,4]', true); + jsonb_set +-------------------------------------------------------------------- + [{"f1": 1, "f2": null}, {"2": [2, 3, 4]}, {"null": 90}, {"3": 87}] +(1 row) + +select jsonb_set('[{"f1":1,"f2":null},{"2":9},{"null":90},{"3":87}]', '{-1,3}', '[2,3,4]', true); + jsonb_set +------------------------------------------------------------------- + [{"f1": 1, "f2": null}, {"2": 9}, {"null": 90}, {"3": [2, 3, 4]}] (1 row) -- prepend to array diff --git a/src/test/regress/sql/jsonb.sql b/src/test/regress/sql/jsonb.sql index 3a64dc3981..12eb37c654 100644 --- a/src/test/regress/sql/jsonb.sql +++ b/src/test/regress/sql/jsonb.sql @@ -501,6 +501,10 @@ select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::j select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{b,-1}', '"test"'); select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{b,-1}', '{"f": "test"}'); +select jsonb_set('[{"f1":1,"f2":null},2,null,3]', '{0,f1}', '[2,3,4]', true); +select jsonb_set('[{"f1":1,"f2":null},{"2":9},{"null":90},{"3":87}]', '{1,2}', '[2,3,4]', true); +select jsonb_set('[{"f1":1,"f2":null},{"2":9},{"null":90},{"3":87}]', '{-1,3}', '[2,3,4]', true); + -- prepend to array select jsonb_set('{"a":1,"b":[0,1,2],"c":{"d":4}}','{b,-33}','{"foo":123}'); -- append to array -- Gitee