logidze 0.9.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +101 -5
- data/LICENSE.txt +1 -1
- data/README.md +309 -89
- data/lib/generators/logidze/fx_helper.rb +17 -0
- data/lib/generators/logidze/inject_sql.rb +18 -0
- data/lib/generators/logidze/install/USAGE +6 -1
- data/lib/generators/logidze/install/functions/logidze_compact_history.sql +38 -0
- data/lib/generators/logidze/install/functions/logidze_filter_keys.sql +27 -0
- data/lib/generators/logidze/install/functions/logidze_logger.sql +150 -0
- data/lib/generators/logidze/install/functions/logidze_snapshot.sql +24 -0
- data/lib/generators/logidze/install/functions/logidze_version.sql +20 -0
- data/lib/generators/logidze/install/install_generator.rb +61 -3
- data/lib/generators/logidze/install/templates/hstore.rb.erb +1 -1
- data/lib/generators/logidze/install/templates/migration.rb.erb +19 -232
- data/lib/generators/logidze/install/templates/migration_fx.rb.erb +41 -0
- data/lib/generators/logidze/model/model_generator.rb +60 -20
- data/lib/generators/logidze/model/templates/migration.rb.erb +57 -36
- data/lib/generators/logidze/model/triggers/logidze.sql +6 -0
- data/lib/logidze.rb +43 -21
- data/lib/logidze/engine.rb +4 -1
- data/lib/logidze/has_logidze.rb +12 -4
- data/lib/logidze/history.rb +7 -15
- data/lib/logidze/history/type.rb +1 -1
- data/lib/logidze/history/version.rb +6 -5
- data/lib/logidze/ignore_log_data.rb +11 -19
- data/lib/logidze/meta.rb +44 -17
- data/lib/logidze/model.rb +63 -46
- data/lib/logidze/version.rb +2 -1
- data/lib/logidze/versioned_association.rb +0 -1
- metadata +43 -103
- data/.gitignore +0 -40
- data/.hound.yml +0 -3
- data/.rubocop.yml +0 -94
- data/.travis.yml +0 -39
- data/Gemfile +0 -13
- data/Rakefile +0 -28
- data/bench/performance/README.md +0 -109
- data/bench/performance/diff_bench.rb +0 -36
- data/bench/performance/insert_bench.rb +0 -20
- data/bench/performance/memory_profile.rb +0 -53
- data/bench/performance/setup.rb +0 -308
- data/bench/performance/update_bench.rb +0 -36
- data/bench/triggers/Makefile +0 -56
- data/bench/triggers/Readme.md +0 -58
- data/bench/triggers/bench.sql +0 -6
- data/bench/triggers/hstore_trigger_setup.sql +0 -38
- data/bench/triggers/jsonb_minus_2_setup.sql +0 -47
- data/bench/triggers/jsonb_minus_setup.sql +0 -49
- data/bench/triggers/keys2_trigger_setup.sql +0 -44
- data/bench/triggers/keys_trigger_setup.sql +0 -50
- data/bin/console +0 -8
- data/bin/setup +0 -9
- data/gemfiles/rails42.gemfile +0 -5
- data/gemfiles/rails5.gemfile +0 -6
- data/gemfiles/rails52.gemfile +0 -6
- data/gemfiles/railsmaster.gemfile +0 -7
- data/lib/logidze/ignore_log_data/ignored_columns.rb +0 -46
- data/lib/logidze/ignore_log_data/missing_attribute_patch.rb +0 -16
- data/lib/logidze/migration.rb +0 -19
- data/logidze.gemspec +0 -33
data/bench/triggers/bench.sql
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
CREATE OR REPLACE FUNCTION hstore_logger() RETURNS TRIGGER AS $body$
|
2
|
-
DECLARE
|
3
|
-
changes_h jsonb;
|
4
|
-
size integer;
|
5
|
-
buffer jsonb;
|
6
|
-
BEGIN
|
7
|
-
size := jsonb_array_length(NEW.log);
|
8
|
-
|
9
|
-
changes_h := hstore_to_jsonb_loose(
|
10
|
-
hstore(NEW.*) - hstore(OLD.*)
|
11
|
-
);
|
12
|
-
|
13
|
-
NEW.log := jsonb_set(
|
14
|
-
NEW.log,
|
15
|
-
ARRAY[size::text],
|
16
|
-
jsonb_build_object(
|
17
|
-
'ts',
|
18
|
-
extract(epoch from now())::int,
|
19
|
-
'i',
|
20
|
-
(NEW.log#>>ARRAY[(size - 1)::text, 'i'])::int + 1,
|
21
|
-
'd',
|
22
|
-
changes_h
|
23
|
-
),
|
24
|
-
true
|
25
|
-
);
|
26
|
-
return NEW;
|
27
|
-
END;
|
28
|
-
$body$
|
29
|
-
LANGUAGE plpgsql;
|
30
|
-
|
31
|
-
|
32
|
-
ALTER TABLE pgbench_accounts ADD COLUMN log jsonb DEFAULT '[]' NOT NULL;
|
33
|
-
|
34
|
-
UPDATE pgbench_accounts SET log = to_jsonb(ARRAY[json_build_object('i', 0)])::jsonb;
|
35
|
-
|
36
|
-
CREATE TRIGGER hstore_log_accounts
|
37
|
-
BEFORE UPDATE ON pgbench_accounts FOR EACH ROW
|
38
|
-
EXECUTE PROCEDURE hstore_logger();
|
@@ -1,47 +0,0 @@
|
|
1
|
-
CREATE OR REPLACE FUNCTION jsonb_minus(arg1 jsonb, arg2 jsonb) RETURNS jsonb
|
2
|
-
AS $$
|
3
|
-
|
4
|
-
SELECT
|
5
|
-
COALESCE(json_object_agg(key, value), '{}')::jsonb
|
6
|
-
FROM
|
7
|
-
jsonb_each(arg1)
|
8
|
-
WHERE NOT jsonb_build_object(key, value) <@ arg2;
|
9
|
-
|
10
|
-
$$ LANGUAGE SQL;
|
11
|
-
|
12
|
-
CREATE OR REPLACE FUNCTION jsonb_minus_2_logger() RETURNS TRIGGER AS $body$
|
13
|
-
DECLARE
|
14
|
-
changes_h jsonb;
|
15
|
-
size integer;
|
16
|
-
buffer jsonb;
|
17
|
-
BEGIN
|
18
|
-
size := jsonb_array_length(NEW.log);
|
19
|
-
|
20
|
-
changes_h := jsonb_minus(row_to_json(OLD)::jsonb, row_to_json(NEW)::jsonb);
|
21
|
-
|
22
|
-
NEW.log := jsonb_set(
|
23
|
-
NEW.log,
|
24
|
-
ARRAY[size::text],
|
25
|
-
jsonb_build_object(
|
26
|
-
'ts',
|
27
|
-
extract(epoch from now())::int,
|
28
|
-
'i',
|
29
|
-
(NEW.log#>>ARRAY[(size - 1)::text, 'i'])::int + 1,
|
30
|
-
'd',
|
31
|
-
changes_h
|
32
|
-
),
|
33
|
-
true
|
34
|
-
);
|
35
|
-
return NEW;
|
36
|
-
END;
|
37
|
-
$body$
|
38
|
-
LANGUAGE plpgsql;
|
39
|
-
|
40
|
-
|
41
|
-
ALTER TABLE pgbench_accounts ADD COLUMN log jsonb DEFAULT '[]' NOT NULL;
|
42
|
-
|
43
|
-
UPDATE pgbench_accounts SET log = to_jsonb(ARRAY[json_build_object('i', 0)])::jsonb;
|
44
|
-
|
45
|
-
CREATE TRIGGER hstore_log_accounts
|
46
|
-
BEFORE UPDATE ON pgbench_accounts FOR EACH ROW
|
47
|
-
EXECUTE PROCEDURE jsonb_minus_2_logger();
|
@@ -1,49 +0,0 @@
|
|
1
|
-
CREATE OR REPLACE FUNCTION jsonb_minus(arg1 jsonb, arg2 jsonb) RETURNS jsonb
|
2
|
-
AS $$
|
3
|
-
|
4
|
-
SELECT
|
5
|
-
COALESCE(json_object_agg(key, value), '{}')::jsonb
|
6
|
-
FROM
|
7
|
-
jsonb_each(arg1)
|
8
|
-
WHERE
|
9
|
-
arg1 -> key <> arg2 -> key
|
10
|
-
OR arg2 -> key IS NULL;
|
11
|
-
|
12
|
-
$$ LANGUAGE SQL;
|
13
|
-
|
14
|
-
CREATE OR REPLACE FUNCTION jsonb_minus_logger() RETURNS TRIGGER AS $body$
|
15
|
-
DECLARE
|
16
|
-
changes_h jsonb;
|
17
|
-
size integer;
|
18
|
-
buffer jsonb;
|
19
|
-
BEGIN
|
20
|
-
size := jsonb_array_length(NEW.log);
|
21
|
-
|
22
|
-
changes_h := jsonb_minus(row_to_json(OLD)::jsonb, row_to_json(NEW)::jsonb);
|
23
|
-
|
24
|
-
NEW.log := jsonb_set(
|
25
|
-
NEW.log,
|
26
|
-
ARRAY[size::text],
|
27
|
-
jsonb_build_object(
|
28
|
-
'ts',
|
29
|
-
extract(epoch from now())::int,
|
30
|
-
'i',
|
31
|
-
(NEW.log#>>ARRAY[(size - 1)::text, 'i'])::int + 1,
|
32
|
-
'd',
|
33
|
-
changes_h
|
34
|
-
),
|
35
|
-
true
|
36
|
-
);
|
37
|
-
return NEW;
|
38
|
-
END;
|
39
|
-
$body$
|
40
|
-
LANGUAGE plpgsql;
|
41
|
-
|
42
|
-
|
43
|
-
ALTER TABLE pgbench_accounts ADD COLUMN log jsonb DEFAULT '[]' NOT NULL;
|
44
|
-
|
45
|
-
UPDATE pgbench_accounts SET log = to_jsonb(ARRAY[json_build_object('i', 0)])::jsonb;
|
46
|
-
|
47
|
-
CREATE TRIGGER hstore_log_accounts
|
48
|
-
BEFORE UPDATE ON pgbench_accounts FOR EACH ROW
|
49
|
-
EXECUTE PROCEDURE jsonb_minus_logger();
|
@@ -1,44 +0,0 @@
|
|
1
|
-
CREATE OR REPLACE FUNCTION keys_2_logger() RETURNS TRIGGER AS $body$
|
2
|
-
DECLARE
|
3
|
-
size integer;
|
4
|
-
old_j jsonb;
|
5
|
-
changes_j jsonb;
|
6
|
-
item record;
|
7
|
-
BEGIN
|
8
|
-
size := jsonb_array_length(NEW.log);
|
9
|
-
old_j := to_jsonb(OLD);
|
10
|
-
changes_j := to_jsonb(NEW);
|
11
|
-
|
12
|
-
FOR item in SELECT key as k, value as v FROM jsonb_each(old_j)
|
13
|
-
LOOP
|
14
|
-
IF changes_j->item.k = item.v THEN
|
15
|
-
changes_j := changes_j - item.k;
|
16
|
-
END IF;
|
17
|
-
END LOOP;
|
18
|
-
|
19
|
-
NEW.log := jsonb_set(
|
20
|
-
NEW.log,
|
21
|
-
ARRAY[size::text],
|
22
|
-
jsonb_build_object(
|
23
|
-
'ts',
|
24
|
-
extract(epoch from now())::int,
|
25
|
-
'i',
|
26
|
-
(NEW.log#>>ARRAY[(size - 1)::text, 'i'])::int + 1,
|
27
|
-
'd',
|
28
|
-
changes_j
|
29
|
-
),
|
30
|
-
true
|
31
|
-
);
|
32
|
-
return NEW;
|
33
|
-
END;
|
34
|
-
$body$
|
35
|
-
LANGUAGE plpgsql;
|
36
|
-
|
37
|
-
|
38
|
-
ALTER TABLE pgbench_accounts ADD COLUMN log jsonb DEFAULT '[]' NOT NULL;
|
39
|
-
|
40
|
-
UPDATE pgbench_accounts SET log = to_jsonb(ARRAY[json_build_object('i', 0)])::jsonb;
|
41
|
-
|
42
|
-
CREATE TRIGGER keys_log_accounts
|
43
|
-
BEFORE UPDATE ON pgbench_accounts FOR EACH ROW
|
44
|
-
EXECUTE PROCEDURE keys_2_logger();
|
@@ -1,50 +0,0 @@
|
|
1
|
-
CREATE OR REPLACE FUNCTION keys_logger() RETURNS TRIGGER AS $body$
|
2
|
-
DECLARE
|
3
|
-
changes_h jsonb;
|
4
|
-
size integer;
|
5
|
-
old_j jsonb;
|
6
|
-
new_j jsonb;
|
7
|
-
item record;
|
8
|
-
BEGIN
|
9
|
-
size := jsonb_array_length(NEW.log);
|
10
|
-
old_j := to_jsonb(OLD);
|
11
|
-
new_j := to_jsonb(NEW);
|
12
|
-
changes_h := '{}'::jsonb;
|
13
|
-
|
14
|
-
FOR item in SELECT key as k, value as v FROM jsonb_each(new_j)
|
15
|
-
LOOP
|
16
|
-
IF item.v <> jsonb_extract_path(old_j, item.k) THEN
|
17
|
-
changes_h := jsonb_set(
|
18
|
-
changes_h,
|
19
|
-
ARRAY[item.k],
|
20
|
-
item.v
|
21
|
-
);
|
22
|
-
END IF;
|
23
|
-
END LOOP;
|
24
|
-
|
25
|
-
NEW.log := jsonb_set(
|
26
|
-
NEW.log,
|
27
|
-
ARRAY[size::text],
|
28
|
-
jsonb_build_object(
|
29
|
-
'ts',
|
30
|
-
extract(epoch from now())::int,
|
31
|
-
'i',
|
32
|
-
(NEW.log#>>ARRAY[(size - 1)::text, 'i'])::int + 1,
|
33
|
-
'd',
|
34
|
-
changes_h
|
35
|
-
),
|
36
|
-
true
|
37
|
-
);
|
38
|
-
return NEW;
|
39
|
-
END;
|
40
|
-
$body$
|
41
|
-
LANGUAGE plpgsql;
|
42
|
-
|
43
|
-
|
44
|
-
ALTER TABLE pgbench_accounts ADD COLUMN log jsonb DEFAULT '[]' NOT NULL;
|
45
|
-
|
46
|
-
UPDATE pgbench_accounts SET log = to_jsonb(ARRAY[json_build_object('i', 0)])::jsonb;
|
47
|
-
|
48
|
-
CREATE TRIGGER keys_log_accounts
|
49
|
-
BEFORE UPDATE ON pgbench_accounts FOR EACH ROW
|
50
|
-
EXECUTE PROCEDURE keys_logger();
|
data/bin/console
DELETED
data/bin/setup
DELETED
data/gemfiles/rails42.gemfile
DELETED
data/gemfiles/rails5.gemfile
DELETED
data/gemfiles/rails52.gemfile
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Logidze
|
4
|
-
module IgnoreLogData
|
5
|
-
# Backports ignored_columns functionality to Rails < 5
|
6
|
-
module IgnoredColumns
|
7
|
-
module Base # :nodoc:
|
8
|
-
attr_writer :ignored_columns
|
9
|
-
|
10
|
-
def ignored_columns
|
11
|
-
@ignored_columns ||= []
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
module Relation # :nodoc:
|
16
|
-
private
|
17
|
-
|
18
|
-
def build_select(arel)
|
19
|
-
if select_values.blank? && klass.ignored_columns.any?
|
20
|
-
arel.project(*arel_columns(klass.column_names - klass.ignored_columns))
|
21
|
-
else
|
22
|
-
super
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
module Table # :nodoc:
|
28
|
-
def columns
|
29
|
-
super.reject { |column| ignored_columns.include?(column.name) }
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def ignored_columns
|
35
|
-
node.base_klass.ignored_columns
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
ActiveRecord::Base.extend(Logidze::IgnoreLogData::IgnoredColumns::Base)
|
43
|
-
ActiveRecord::Relation.include(Logidze::IgnoreLogData::IgnoredColumns::Relation)
|
44
|
-
ActiveRecord::Associations::JoinDependency::Aliases::Table.prepend(
|
45
|
-
Logidze::IgnoreLogData::IgnoredColumns::Table
|
46
|
-
)
|
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Logidze
|
4
|
-
module IgnoreLogData
|
5
|
-
# Rails attribute API defines attributes in a way, that it returns nil
|
6
|
-
# when data has not been loaded from the DB. We want it to imitate the behavior
|
7
|
-
# from Rails 4 - raise ActiveModel::MissingAttributeError
|
8
|
-
module MissingAttributePatch
|
9
|
-
def log_data
|
10
|
-
raise ActiveModel::MissingAttributeError if attributes["log_data"].nil?
|
11
|
-
|
12
|
-
super
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
data/lib/logidze/migration.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module Logidze
|
3
|
-
# Contains helpers for handling different PG versions
|
4
|
-
module Migration
|
5
|
-
# Checks whether pg function `current_setting` support `missing_ok` argument
|
6
|
-
# (since 9.6)
|
7
|
-
def current_setting_missing_supported?
|
8
|
-
ActiveRecord::Base.connection.send(:postgresql_version) >= 90_600
|
9
|
-
end
|
10
|
-
|
11
|
-
def current_setting(name)
|
12
|
-
if current_setting_missing_supported?
|
13
|
-
"current_setting('#{name}', true)"
|
14
|
-
else
|
15
|
-
"current_setting('#{name}')"
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
data/logidze.gemspec
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'logidze/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "logidze"
|
8
|
-
spec.version = Logidze::VERSION
|
9
|
-
spec.authors = ["palkan"]
|
10
|
-
spec.email = ["dementiev.vm@gmail.com"]
|
11
|
-
|
12
|
-
spec.summary = "PostgreSQL JSON-based auditing"
|
13
|
-
spec.description = "PostgreSQL JSON-based auditing"
|
14
|
-
spec.homepage = "http://github.com/palkan/logidze"
|
15
|
-
spec.license = "MIT"
|
16
|
-
|
17
|
-
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
-
spec.require_paths = ["lib"]
|
19
|
-
|
20
|
-
spec.add_dependency "rails", ">= 4.2"
|
21
|
-
|
22
|
-
spec.add_development_dependency "ammeter", "~> 1.1.3"
|
23
|
-
spec.add_development_dependency "bundler", "~> 1"
|
24
|
-
spec.add_development_dependency "database_cleaner", "~> 1.5"
|
25
|
-
spec.add_development_dependency "pg", "~>0.18"
|
26
|
-
spec.add_development_dependency "pry-byebug"
|
27
|
-
spec.add_development_dependency "rake", ">= 10.0"
|
28
|
-
spec.add_development_dependency "rspec-rails", ">= 3.4"
|
29
|
-
spec.add_development_dependency "rubocop", "~> 0.60.0"
|
30
|
-
spec.add_development_dependency "rubocop-md", "~> 0.2.0"
|
31
|
-
spec.add_development_dependency "simplecov", ">= 0.3.8"
|
32
|
-
spec.add_development_dependency "timecop", "~> 0.8"
|
33
|
-
end
|