-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathjson_set.sql
64 lines (63 loc) · 2.02 KB
/
json_set.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
CREATE OR REPLACE FUNCTION "json_set"(
"json" json,
"key_path" TEXT[],
"value_to_set" anyelement,
"create_missing" boolean default true
)
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT CASE COALESCE(array_length("key_path", 1), 0)
WHEN 0 THEN to_json("value_to_set")
WHEN 1 THEN
(SELECT CASE WHEN ("json" -> "key_path"[1]) IS NULL AND "create_missing" = false
THEN "json"
ELSE
(SELECT CASE WHEN json_typeof("json") = 'array'
THEN (SELECT concat(
'[',
array_to_string(
((select ((array_agg(a))[0:("key_path"[1]::integer)])::varchar[] from json_array_elements("json") a)::varchar[] ||
to_json("value_to_set")::varchar) ||
(select ((array_agg(a))[("key_path"[1]::integer + 2):(array_length(array_agg(a), 1))])::varchar[] from json_array_elements("json") a)::varchar[]
, ', '),
']'
)::json)
ELSE (SELECT concat('{', string_agg(to_json("key") || ':' || "value", ','), '}')::json
FROM (SELECT *
FROM json_each("json")
WHERE "key" <> "key_path"[1]
UNION ALL
SELECT "key_path"[1], to_json("value_to_set")) AS "fields")
END)
END)
ELSE "json_set"(
"json",
ARRAY["key_path"[l]],
"json_set"(
COALESCE(NULLIF(("json" -> "key_path"[l])::text, 'null'), '{}')::json,
"key_path"[l+1:u],
"value_to_set",
"create_missing"
),
"create_missing"
)
END
FROM array_lower("key_path", 1) l,
array_upper("key_path", 1) u
$function$;
CREATE OR REPLACE FUNCTION json_set(
"json" json,
"key_path" varchar,
"value_to_set" anyelement,
"create_missing" boolean default true
)
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT json_set("json", string_to_array("key_path", '.'), "value_to_set", "create_missing");
$function$;