comparing two JSON objects in 9.3

Started by Felix Kundealmost 12 years ago3 messagesgeneral
Jump to latest
#1Felix Kunde
felix-kunde@gmx.de

<html><head></head><body><div style="font-family: Verdana;font-size: 12.0px;"><div>Ahoi</div>

<div>&nbsp;</div>

<div>I&#39;m developing an auditing mechanism where table contents are logged as JSON (github.com/fxku/audit).</div>

<div>At first I just logged the whole row everytime my triggers were fired.</div>

<div>Now I&#39;m trying to log only the old state of values that have changed.</div>

<div>&nbsp;</div>

<div>Therefore I compare the OLD and NEW entry by using json_each(json).</div>

<div>&nbsp;</div>

<div>SELECT old.key, old.value<br/>
FROM json_each(row_to_json(OLD)) old<br/>
LEFT OUTER JOIN json_each(row_to_json(NEW)) new ON old.key = new.key<br/>
WHERE new.value::text &lt;&gt; old.value::text OR new.key IS NULL;</div>

<div>&nbsp;</div>

<div>Now I aggregate the result to arrays of JSON and call this function, that I&#39;ve written:</div>

<div>
<div>CREATE OR REPLACE FUNCTION audit.build_json(json_keys ANYARRAY, json_values ANYARRAY) RETURNS JSON AS<br/>
&#36;&#36;<br/>
DECLARE<br/>
&nbsp; json_string TEXT := &#39;{&#39;;<br/>
&nbsp; delimeter TEXT := &#39;&#39;;<br/>
&nbsp; json_result JSON;<br/>
BEGIN<br/>
&nbsp; FOR i IN array_lower(json_keys, 1)..array_upper(json_keys, 1) LOOP<br/>
&nbsp;&nbsp;&nbsp; json_string := json_string &#124;&#124; delimeter &#124;&#124; json_keys[i] &#124;&#124; &#39;:&#39; &#124;&#124; json_values[i];<br/>
&nbsp;&nbsp;&nbsp; delimeter := &#39;,&#39;;<br/>
&nbsp; END LOOP;</div>

<div>&nbsp; json_string := json_string &#124;&#124; &#39;}&#39;;</div>

<div>&nbsp; EXECUTE format(&#39;SELECT %L::json&#39;, json_string) INTO json_result;<br/>
&nbsp; RETURN json_result;<br/>
END<br/>
&#36;&#36;<br/>
LANGUAGE plpgsql;</div>

<div>&nbsp;</div>

<div>In the end the call looks like this:</div>

<div>SELECT audit.build_json(array_agg(to_json(old.key)), array_agg(old.value))</div>

<div>FROM json_each(row_to_json(OLD)) old<br/>
LEFT OUTER JOIN json_each(row_to_json(NEW)) new ON old.key = new.key<br/>
WHERE new.value::text &lt;&gt; old.value::text OR new.key IS NULL;</div>
</div>

<div>&nbsp;</div>

<div>Everything works as expected, but it feels kinda ugly to me.</div>

<div>Any PG-JSON experts around to tell me a better solution?</div>

<div>Did i trapped into some &quot;YouShouldNot&quot;s?</div>

<div>&nbsp;</div>

<div>Regards!</div>

<div>Felix Kunde</div></div></body></html>

#2yuri.ivanenko@progforce.com
yuri.ivanenko@progforce.com
In reply to: Felix Kunde (#1)
Re: comparing two JSON objects in 9.3

Wow. This is exactly what I'm looking for . The standard audit from here
https://wiki.postgresql.org/wiki/Audit_trigger is not good enough for me - I
want to audit only changed values and ignore all other ones.
Thank you Felix!

Regards,
Yuri.

--
View this message in context: http://postgresql.nabble.com/comparing-two-JSON-objects-in-9-3-tp5803617p5896917.html
Sent from the PostgreSQL - general mailing list archive at Nabble.com.

--
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general

#3yuri.ivanenko@progforce.com
yuri.ivanenko@progforce.com
In reply to: yuri.ivanenko@progforce.com (#2)
Re: comparing two JSON objects in 9.3

There's also another way using hstore instead of json:
https://wiki.postgresql.org/wiki/Audit_trigger_91plus

--
View this message in context: http://postgresql.nabble.com/comparing-two-JSON-objects-in-9-3-tp5803617p5897128.html
Sent from the PostgreSQL - general mailing list archive at Nabble.com.

--
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general