Created
April 6, 2021 11:18
-
-
Save jarppe/f3cdd32ec58a4bdfb29daa67ef6c3b78 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 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