Skip to content

Commit a63b1b5

Browse files
committed
feat: <100
1 parent f0c31c1 commit a63b1b5

File tree

2 files changed

+40
-64
lines changed

2 files changed

+40
-64
lines changed

pg_jsonpatch--1.0.0.sql

Lines changed: 38 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,20 @@
33
create or replace function jsonb_patch_add(target jsonb, path text[], value jsonb)
44
returns jsonb
55
as $$
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
2320
immutable;
2421

2522
create or replace function jsonb_patch_remove(target jsonb, path text[])
@@ -36,22 +33,13 @@ immutable;
3633

3734
create or replace function jsonb_patch_move(target jsonb, _from text[], path text[])
3835
returns 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)) $$
4737
language sql
4838
immutable;
4939

5040
create or replace function jsonb_patch_copy(target jsonb, _from text[], path text[])
5141
returns 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)) $$
5543
language sql
5644
immutable;
5745

@@ -67,53 +55,40 @@ as $$ select array_remove(string_to_array(path, '/'), '') $$
6755
language sql
6856
immutable;
6957

58+
-- Apply a single patch operation to an object.
7059
create or replace function jsonb_patch_apply(target jsonb, patch jsonb)
7160
returns jsonb
7261
as $$
7362
declare
74-
op text := patch->>'op';
7563
path text[] := @extschema@.jsonb_patch_split_path(patch->>'path');
76-
rv jsonb;
7764
begin
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;
8874
end $$
8975
language plpgsql
9076
immutable;
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-
11578
create or replace function jsonb_patch(target jsonb, patches jsonb)
11679
returns 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
11994
immutable;

test.sql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ select
9090
from (
9191
values
9292
('{"op":"replace","path":"/a/b/c","value":42}'::jsonb),
93-
('{"op":"test","path":"/a/b/c","value":"C"}')
93+
('{"op":"test","path":"/a/b/c","value":"C"}'),
94+
('{"op":"add","path":"/a/b/d","value":"foo"}'::jsonb)
9495
) as patches(patch);
9596

9697
select plan(count(*)::int) from test_cases;

0 commit comments

Comments
 (0)