Skip to content

Commit 9c4cc9e

Browse files
committed
Fix broken jsonb_set() logic for replacing array elements.
Commit 0b62fd0 did a fairly sloppy job of refactoring setPath() to support jsonb_insert() along with jsonb_set(). In its defense, though, there was no regression test case exercising the case of replacing an existing element in a jsonb array. Per bug #14366 from Peng Sun. Back-patch to 9.6 where bug was introduced. Report: <20161012065349.1412.47858@wrigleys.postgresql.org>
1 parent ccbb852 commit 9c4cc9e

File tree

3 files changed

+13
-6
lines changed

3 files changed

+13
-6
lines changed

src/backend/utils/adt/jsonfuncs.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@
3434
#include "utils/typcache.h"
3535

3636
/* Operations available for setPath */
37-
#define JB_PATH_NOOP 0x0000
3837
#define JB_PATH_CREATE 0x0001
3938
#define JB_PATH_DELETE 0x0002
40-
#define JB_PATH_INSERT_BEFORE 0x0004
41-
#define JB_PATH_INSERT_AFTER 0x0008
39+
#define JB_PATH_REPLACE 0x0004
40+
#define JB_PATH_INSERT_BEFORE 0x0008
41+
#define JB_PATH_INSERT_AFTER 0x0010
4242
#define JB_PATH_CREATE_OR_INSERT \
4343
(JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER | JB_PATH_CREATE)
4444

@@ -3545,7 +3545,7 @@ jsonb_set(PG_FUNCTION_ARGS)
35453545
it = JsonbIteratorInit(&in->root);
35463546

35473547
res = setPath(&it, path_elems, path_nulls, path_len, &st,
3548-
0, newval, create ? JB_PATH_CREATE : JB_PATH_NOOP);
3548+
0, newval, create ? JB_PATH_CREATE : JB_PATH_REPLACE);
35493549

35503550
Assert(res != NULL);
35513551

@@ -4003,7 +4003,7 @@ setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
40034003
if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_INSERT_BEFORE))
40044004
(void) pushJsonbValue(st, r, &v);
40054005

4006-
if (op_type & JB_PATH_INSERT_AFTER)
4006+
if (op_type & (JB_PATH_INSERT_AFTER | JB_PATH_REPLACE))
40074007
addJsonbToParseState(st, newval);
40084008

40094009
done = true;
@@ -4035,7 +4035,7 @@ setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
40354035
}
40364036
}
40374037

4038-
if (op_type & JB_PATH_CREATE_OR_INSERT && !done &&
4038+
if ((op_type & JB_PATH_CREATE_OR_INSERT) && !done &&
40394039
level == path_len - 1 && i == nelems - 1)
40404040
{
40414041
addJsonbToParseState(st, newval);

src/test/regress/expected/jsonb.out

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3238,6 +3238,12 @@ select jsonb_set('[]','{1}','"b"', false);
32383238
[]
32393239
(1 row)
32403240

3241+
select jsonb_set('[{"f1":1,"f2":null},2,null,3]', '{0}','[2,3,4]', false);
3242+
jsonb_set
3243+
-------------------------
3244+
[[2, 3, 4], 2, null, 3]
3245+
(1 row)
3246+
32413247
-- jsonb_set adding instead of replacing
32423248
-- prepend to array
32433249
select jsonb_set('{"a":1,"b":[0,1,2],"c":{"d":4}}','{b,-33}','{"foo":123}');

src/test/regress/sql/jsonb.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,7 @@ select '[]'::jsonb #- '{a}';
814814
select jsonb_set('"a"','{a}','"b"'); --error
815815
select jsonb_set('{}','{a}','"b"', false);
816816
select jsonb_set('[]','{1}','"b"', false);
817+
select jsonb_set('[{"f1":1,"f2":null},2,null,3]', '{0}','[2,3,4]', false);
817818

818819
-- jsonb_set adding instead of replacing
819820

0 commit comments

Comments
 (0)