-
-
Save twik/5040b9ebed542f2cdafddb03536fdc18 to your computer and use it in GitHub Desktop.
PostgreSQL function to produce diff of two jsonb objects. Does not support arrays.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- | |
-- Helper function to produce a diff of two jsonb values. | |
-- | |
-- Accepts: | |
-- val1: original jsonb value | |
-- val2: updated jsonb value | |
-- | |
-- Returns: | |
-- jsonb of changed values | |
-- | |
-- Examples: | |
-- val1: {"a": {"b": 1}} | |
-- val2: {"a": {"b": 1, "c": 2}} | |
-- returns: {"a": {"c": 2}} | |
-- | |
create or replace function jsonb_diff | |
(old jsonb, new jsonb) | |
returns jsonb | |
language 'plpgsql' | |
as | |
$$ | |
declare | |
result jsonb; | |
object_result jsonb; | |
k text; | |
v record; | |
empty jsonb = '{}'::jsonb; | |
begin | |
if old is null or jsonb_typeof(old) = 'null' | |
then | |
return new; | |
end if; | |
if new is null or jsonb_typeof(new) = 'null' | |
then | |
return empty; | |
end if; | |
result = old; | |
for k in select * from jsonb_object_keys(old) | |
loop | |
result = result || jsonb_build_object(k, null); | |
end loop; | |
for v in select * from jsonb_each(new) | |
loop | |
if jsonb_typeof(old -> v.key) = 'object' and jsonb_typeof(new -> v.key) = 'object' | |
then | |
object_result = audit_public.jsonb_diff(old -> v.key, new -> v.key); | |
if object_result = empty | |
then | |
result = result - v.key; | |
else | |
result = result || jsonb_build_object(v.key, object_result); | |
end if; | |
elsif old -> v.key = new -> v.key | |
then | |
result = result - v.key; | |
else | |
result = result || jsonb_build_object(v.key, v.value); | |
end if; | |
end loop; | |
return result; | |
end; | |
$$; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment