33create or replace function jsonb_patch_add (target jsonb, path text [], value jsonb)
44returns jsonb
55as $$
6- with x as (
7- select jsonb_typeof(jsonb_extract_path(target, variadic trim_array(path , 1 ))) as t
8- )
9- select jsonb_set(target, path , value, true)
10- from x
11- where x .t = ' object'
12- union all
13- select jsonb_insert(target, path , value)
14- from x
15- where x .t = ' array' and path [array_length(path , 1 )] is distinct from ' -'
16- union all
17- select jsonb_insert(target, trim_array(path , 1 ) || array[' -1' ], value, true)
18- from x
19- where x .t = ' array' and path [array_length(path , 1 )] = ' -'
20- limit 1
21- $$
22- language sql
6+ declare
7+ target_type text := jsonb_typeof(jsonb_extract_path(target, variadic trim_array(path , 1 )));
8+ begin
9+ case
10+ when target_type = ' object'
11+ then return jsonb_set(target, path , value, true);
12+ when target_type = ' array' and path [array_length(path , 1 )] = ' -'
13+ then return jsonb_insert(target, trim_array(path , 1 ) || array[' -1' ], value, true);
14+ when target_type = ' array'
15+ then return jsonb_insert(target, path , value);
16+ else return null ;
17+ end case;
18+ end $$
19+ language plpgsql
2320immutable;
2421
2522create or replace function jsonb_patch_remove (target jsonb, path text [])
@@ -36,22 +33,13 @@ immutable;
3633
3734create or replace function jsonb_patch_move (target jsonb, _from text [], path text [])
3835returns jsonb
39- as $$
40- with old as (
41- select jsonb_extract_path(target, variadic _from) as value
42- )
43-
44- select @extschema@.jsonb_patch_add(@extschema@.jsonb_patch_remove(target, _from), path , value)
45- from old
46- $$
36+ as $$ select @extschema@.jsonb_patch_add(@extschema@.jsonb_patch_remove(target, _from), path , jsonb_extract_path(target, variadic _from)) $$
4737language sql
4838immutable;
4939
5040create or replace function jsonb_patch_copy (target jsonb, _from text [], path text [])
5141returns jsonb
52- as $$
53- select @extschema@.jsonb_patch_add(target, path , jsonb_extract_path(target, variadic _from))
54- $$
42+ as $$ select @extschema@.jsonb_patch_add(target, path , jsonb_extract_path(target, variadic _from)) $$
5543language sql
5644immutable;
5745
@@ -67,53 +55,40 @@ as $$ select array_remove(string_to_array(path, '/'), '') $$
6755language sql
6856immutable;
6957
58+ -- Apply a single patch operation to an object.
7059create or replace function jsonb_patch_apply (target jsonb, patch jsonb)
7160returns jsonb
7261as $$
7362declare
74- op text := patch- >> ' op' ;
7563 path text [] := @extschema@.jsonb_patch_split_path(patch- >> ' path' );
76- rv jsonb;
7764begin
7865 case patch- >> ' op'
79- when ' add' then rv := @extschema@.jsonb_patch_add(target, path , patch- > ' value' );
80- when ' remove' then rv := @extschema@.jsonb_patch_remove(target, path );
81- when ' replace' then rv := @extschema@.jsonb_patch_replace(target, path , patch- > ' value' );
82- when ' move' then rv := @extschema@.jsonb_patch_move(target, @extschema@.jsonb_patch_split_path(patch- >> ' from' ), path );
83- when ' copy' then rv := @extschema@.jsonb_patch_copy(target, @extschema@.jsonb_patch_split_path(patch- >> ' from' ), path );
84- when ' test' then rv := @extschema@.jsonb_patch_test(target, path , patch- > ' value' );
66+ when ' add' then return @extschema@.jsonb_patch_add(target, path , patch- > ' value' );
67+ when ' remove' then return @extschema@.jsonb_patch_remove(target, path );
68+ when ' replace' then return @extschema@.jsonb_patch_replace(target, path , patch- > ' value' );
69+ when ' move' then return @extschema@.jsonb_patch_move(target, @extschema@.jsonb_patch_split_path(patch- >> ' from' ), path );
70+ when ' copy' then return @extschema@.jsonb_patch_copy(target, @extschema@.jsonb_patch_split_path(patch- >> ' from' ), path );
71+ when ' test' then return @extschema@.jsonb_patch_test(target, path , patch- > ' value' );
72+ else return null ;
8573 end case;
86-
87- return rv;
8874end $$
8975language plpgsql
9076immutable;
9177
92- create or replace function jsonb_coalesce (variadic jsonb[])
93- returns jsonb
94- as $$
95- select value
96- from unnest($1 ) as value
97- where value is not null and jsonb_typeof(value) != ' null'
98- limit 1
99- $$
100- language sql
101- immutable;
102-
103- create or replace function jsonb_patch_agg (target jsonb, patch jsonb, base jsonb)
104- returns jsonb
105- as $$ select @extschema@.jsonb_patch_apply(@extschema@.jsonb_coalesce(target, base), patch) $$
106- language sql
107- immutable;
108-
109- create or replace aggregate jsonb_patch_agg (jsonb, jsonb) (
110- sfunc = @extschema@.jsonb_patch_agg,
111- stype = jsonb,
112- initcond = null
113- );
114-
11578create or replace function jsonb_patch (target jsonb, patches jsonb)
11679returns jsonb
117- as $$ select jsonb_patch_agg(value, target) from jsonb_array_elements(patches) $$
118- language sql
80+ as $$
81+ declare
82+ patch jsonb;
83+ result jsonb := target;
84+ begin
85+ for patch in select * from jsonb_array_elements(patches) loop
86+ result := @extschema@.jsonb_patch_apply(result, patch);
87+ if result is null then
88+ return null ;
89+ end if;
90+ end loop;
91+ return result;
92+ end $$
93+ language plpgsql
11994immutable;
0 commit comments