Tracking changes on JSONB column
edymerchk opened this issue · comments
Tell us about your environment
Ruby Version: 2.6.3p62
Rails Version: 6.0.3
PostgreSQL Version: 11.8
Logidze Version: 1.0.0
What did you do?
Tried to use logidze tracking a JSONB column
I have a table like:
create_table :users do |t|
t.jsonb :data
t.timestamps
end
and a trigger (generated by gem) like:
CREATE TRIGGER logidze_on_users
BEFORE UPDATE OR INSERT ON users FOR EACH ROW
WHEN (coalesce(current_setting('logidze.disabled', true), '') <> 'on')
-- Parameters: history_size_limit (integer), timestamp_column (text), filtered_columns (text[]),
-- include_columns (boolean), debounce_time_ms (integer)
EXECUTE PROCEDURE logidze_logger(null, 'updated_at', '{data}', true);
What did you expect to happen?
Store always the changes
in the same format
What actually happened?
First change is stored as JSON, but subsequent are Stringify
u = User.create!(data: {hello: 1})
u.update!(data: {hello: 2})
u.update!(data: {hello: 3})
u.reload.log_data =>
#<Logidze::History:0x00007f956b5d2908 @data={"h"=>[
{"c"=>{"data"=>{"hello"=>1}}, "v"=>1, "ts"=>1609790311222},
{"c"=>{"data"=>"{\"hello\": 2}"}, "v"=>2, "ts"=>1609790311226},
{"c"=>{"data"=>"{\"hello\": 3}"}, "v"=>3, "ts"=>1609790381173}],
"v"=>3}>
BTW! Thank you for this amazing gem!
Thanks for the report!
That's what happening here (a note to everyone who would like to pick this issue while I'm enjoying New Year holidays 🎄):
- We use
hstore_to_jsonb_loose
to efficiently calculate diffs between two JSONB objects—that happens only on UPDATE. - Initial snapshot doesn't use hstore, thus, we store JSONB as as.
To fix this we need to ensure that snapshots also stringify values.
P.S. @edymerchk except from the format difference, does it cause any issues? I guess, we handle this at the Ruby side correctly, i.e., both strings and Hashes are deserialized into Hashes.