palkan / logidze

Database changes log for Rails

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.