database_consistency 1.1.7 → 1.1.12
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/lib/database_consistency/checkers/association_checkers/foreign_key_checker.rb +9 -2
- data/lib/database_consistency/checkers/association_checkers/foreign_key_type_checker.rb +29 -38
- data/lib/database_consistency/checkers/validators_fraction_checkers/column_presence_checker.rb +10 -5
- data/lib/database_consistency/configuration.rb +9 -1
- data/lib/database_consistency/databases/types/base.rb +12 -0
- data/lib/database_consistency/databases/types/sqlite.rb +3 -2
- data/lib/database_consistency/helper.rb +16 -0
- data/lib/database_consistency/version.rb +1 -1
- metadata +19 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 908211c725197dadbe72f2f7c8f2f47d48a55ed546c57d2f512b9b2978fb325a
|
4
|
+
data.tar.gz: 4b18e433573c598b25906dce98554516f3c54bacbd897b59c8f72c6d9577a53d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 43ea449cc58c970f99deb81936461d2f267a107934ad93cfb1f73ef0e0a8e46c97d9ba5085a54538828d162ca06638ad35afb907fa51de661df30bad9527cefc
|
7
|
+
data.tar.gz: 799f1975507dababf597ca140655377e90a1480af4422080349027b03ef7ef9dbade4125e95f317ef3d873706e82f1c24991c9c9600a08cb3dca3e6ff2bbc8e0
|
@@ -9,14 +9,21 @@ module DatabaseConsistency
|
|
9
9
|
private
|
10
10
|
|
11
11
|
# We skip check when:
|
12
|
+
# - underlying models belong to different databases
|
12
13
|
# - association isn't belongs_to association
|
13
14
|
# - association is polymorphic
|
14
15
|
def preconditions
|
15
|
-
supported? &&
|
16
|
+
supported? &&
|
17
|
+
association.belongs_to? && !association.polymorphic? &&
|
18
|
+
same_database?
|
19
|
+
end
|
20
|
+
|
21
|
+
def same_database?
|
22
|
+
Helper.connection_config(model) == Helper.connection_config(association.klass)
|
16
23
|
end
|
17
24
|
|
18
25
|
def supported?
|
19
|
-
return false if ActiveRecord::VERSION::MAJOR < 5 &&
|
26
|
+
return false if ActiveRecord::VERSION::MAJOR < 5 && Helper.adapter == 'sqlite3'
|
20
27
|
|
21
28
|
true
|
22
29
|
end
|
@@ -2,18 +2,9 @@
|
|
2
2
|
|
3
3
|
module DatabaseConsistency
|
4
4
|
module Checkers
|
5
|
-
# This class checks if association's foreign key type
|
5
|
+
# This class checks if association's foreign key type covers associated model's primary key (same or bigger)
|
6
6
|
class ForeignKeyTypeChecker < AssociationChecker
|
7
|
-
INCONSISTENT_TYPE =
|
8
|
-
|
9
|
-
TYPES = {
|
10
|
-
'serial' => 'integer',
|
11
|
-
'integer' => 'integer',
|
12
|
-
'int' => 'integer',
|
13
|
-
'bigserial' => 'bigint',
|
14
|
-
'bigint' => 'bigint',
|
15
|
-
'bigint unsigned' => 'bigint unsigned'
|
16
|
-
}.freeze
|
7
|
+
INCONSISTENT_TYPE = "foreign key (%a_f) with type (%a_t) doesn't cover primary key (%b_f) with type (%b_t)"
|
17
8
|
|
18
9
|
private
|
19
10
|
|
@@ -32,12 +23,12 @@ module DatabaseConsistency
|
|
32
23
|
end
|
33
24
|
|
34
25
|
# Table of possible statuses
|
35
|
-
# | type
|
36
|
-
# |
|
37
|
-
# |
|
38
|
-
# |
|
26
|
+
# | type | status |
|
27
|
+
# | ------------- | ------ |
|
28
|
+
# | covers | ok |
|
29
|
+
# | doesn't cover | fail |
|
39
30
|
def check
|
40
|
-
if converted_type(
|
31
|
+
if converted_type(associated_column).cover?(converted_type(primary_column))
|
41
32
|
report_template(:ok)
|
42
33
|
else
|
43
34
|
report_template(:fail, render_text)
|
@@ -51,40 +42,40 @@ module DatabaseConsistency
|
|
51
42
|
INCONSISTENT_TYPE
|
52
43
|
.gsub('%a_t', type(associated_column))
|
53
44
|
.gsub('%a_f', associated_key)
|
54
|
-
.gsub('%b_t', type(
|
55
|
-
.gsub('%b_f',
|
45
|
+
.gsub('%b_t', type(primary_column))
|
46
|
+
.gsub('%b_f', primary_key)
|
56
47
|
end
|
57
48
|
|
58
49
|
# @return [String]
|
59
|
-
def
|
60
|
-
@
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
66
|
-
).to_s
|
50
|
+
def primary_key
|
51
|
+
@primary_key ||= if belongs_to_association?
|
52
|
+
association.association_primary_key
|
53
|
+
else
|
54
|
+
association.active_record_primary_key
|
55
|
+
end.to_s
|
67
56
|
end
|
68
57
|
|
69
58
|
# @return [String]
|
70
59
|
def associated_key
|
71
|
-
@associated_key ||=
|
72
|
-
if belongs_to_association?
|
73
|
-
association.association_primary_key
|
74
|
-
else
|
75
|
-
association.foreign_key
|
76
|
-
end
|
77
|
-
).to_s
|
60
|
+
@associated_key ||= association.foreign_key.to_s
|
78
61
|
end
|
79
62
|
|
80
63
|
# @return [ActiveRecord::ConnectionAdapters::Column]
|
81
|
-
def
|
82
|
-
@
|
64
|
+
def primary_column
|
65
|
+
@primary_column ||= if belongs_to_association?
|
66
|
+
column(association.klass, primary_key)
|
67
|
+
else
|
68
|
+
column(association.active_record, primary_key)
|
69
|
+
end
|
83
70
|
end
|
84
71
|
|
85
72
|
# @return [ActiveRecord::ConnectionAdapters::Column]
|
86
73
|
def associated_column
|
87
|
-
@associated_column ||=
|
74
|
+
@associated_column ||= if belongs_to_association?
|
75
|
+
column(association.active_record, associated_key)
|
76
|
+
else
|
77
|
+
column(association.klass, associated_key)
|
78
|
+
end
|
88
79
|
end
|
89
80
|
|
90
81
|
# @return [DatabaseConsistency::Databases::Factory]
|
@@ -116,9 +107,9 @@ module DatabaseConsistency
|
|
116
107
|
|
117
108
|
# @param [ActiveRecord::ConnectionAdapters::Column]
|
118
109
|
#
|
119
|
-
# @return [
|
110
|
+
# @return [DatabaseConsistency::Databases::Types::Base]
|
120
111
|
def converted_type(column)
|
121
|
-
database_factory.type(type(column))
|
112
|
+
database_factory.type(type(column))
|
122
113
|
end
|
123
114
|
|
124
115
|
# @return [Boolean]
|
data/lib/database_consistency/checkers/validators_fraction_checkers/column_presence_checker.rb
CHANGED
@@ -18,7 +18,11 @@ module DatabaseConsistency
|
|
18
18
|
|
19
19
|
# We skip the check when there are no presence validators
|
20
20
|
def preconditions
|
21
|
-
validators.any?
|
21
|
+
validators.any? && !association?
|
22
|
+
end
|
23
|
+
|
24
|
+
def association?
|
25
|
+
model._reflect_on_association(attribute)&.macro == :has_one
|
22
26
|
end
|
23
27
|
|
24
28
|
# Table of possible statuses
|
@@ -34,13 +38,13 @@ module DatabaseConsistency
|
|
34
38
|
report_template(:fail, e.message)
|
35
39
|
end
|
36
40
|
|
37
|
-
def
|
41
|
+
def weak_option?
|
38
42
|
validators.all? { |validator| validator.options.slice(*WEAK_OPTIONS).any? }
|
39
43
|
end
|
40
44
|
|
41
45
|
def report_message
|
42
46
|
can_be_null = column.null
|
43
|
-
has_weak_option =
|
47
|
+
has_weak_option = weak_option?
|
44
48
|
|
45
49
|
return report_template(:ok) if can_be_null == has_weak_option
|
46
50
|
return report_template(:fail, POSSIBLE_NULL) unless can_be_null
|
@@ -53,8 +57,9 @@ module DatabaseConsistency
|
|
53
57
|
end
|
54
58
|
|
55
59
|
def column
|
56
|
-
@column ||= regular_column ||
|
57
|
-
|
60
|
+
@column ||= regular_column ||
|
61
|
+
association_reference_column ||
|
62
|
+
(raise Errors::MissingField, "column (#{attribute}) is missing in table (#{model.table_name}) but used for presence validation") # rubocop:disable Layout/LineLength
|
58
63
|
end
|
59
64
|
|
60
65
|
def regular_column
|
@@ -11,7 +11,7 @@ module DatabaseConsistency
|
|
11
11
|
@configuration = Array(filepaths).each_with_object({}) do |filepath, result|
|
12
12
|
content =
|
13
13
|
if filepath && File.exist?(filepath)
|
14
|
-
data =
|
14
|
+
data = load_yaml_config_file(filepath)
|
15
15
|
data.is_a?(Hash) ? data : {}
|
16
16
|
else
|
17
17
|
{}
|
@@ -53,6 +53,14 @@ module DatabaseConsistency
|
|
53
53
|
|
54
54
|
attr_reader :configuration
|
55
55
|
|
56
|
+
def load_yaml_config_file(filepath)
|
57
|
+
if YAML.respond_to?(:safe_load_file)
|
58
|
+
YAML.safe_load_file(filepath, aliases: true)
|
59
|
+
else
|
60
|
+
YAML.load_file(filepath)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
56
64
|
def combine_configs!(config, new_config)
|
57
65
|
config.merge!(new_config) do |_key, val, new_val|
|
58
66
|
if val.is_a?(Hash) && new_val.is_a?(Hash)
|
@@ -7,6 +7,11 @@ module DatabaseConsistency
|
|
7
7
|
class Base
|
8
8
|
attr_reader :type
|
9
9
|
|
10
|
+
COVERED_TYPES = {
|
11
|
+
'bigint' => %w[integer bigint],
|
12
|
+
'integer' => %w[integer smallint]
|
13
|
+
}.freeze
|
14
|
+
|
10
15
|
# @param [String] type
|
11
16
|
def initialize(type)
|
12
17
|
@type = type
|
@@ -16,6 +21,13 @@ module DatabaseConsistency
|
|
16
21
|
def convert
|
17
22
|
type
|
18
23
|
end
|
24
|
+
|
25
|
+
# @param [DatabaseConsistency::Databases::Types::Base]
|
26
|
+
#
|
27
|
+
# @return [Boolean]
|
28
|
+
def cover?(other_type)
|
29
|
+
(COVERED_TYPES[convert] || [convert]).include?(other_type.convert)
|
30
|
+
end
|
19
31
|
end
|
20
32
|
end
|
21
33
|
end
|
@@ -7,9 +7,10 @@ module DatabaseConsistency
|
|
7
7
|
class Sqlite < Base
|
8
8
|
TYPES = {
|
9
9
|
'bigserial' => 'bigint',
|
10
|
-
'bigint' => 'bigint',
|
11
10
|
'serial' => 'integer',
|
12
|
-
'integer' => '
|
11
|
+
'integer(8)' => 'bigint',
|
12
|
+
'integer(4)' => 'integer',
|
13
|
+
'integer(2)' => 'smallint'
|
13
14
|
}.freeze
|
14
15
|
|
15
16
|
# @return [String]
|
@@ -5,6 +5,22 @@ module DatabaseConsistency
|
|
5
5
|
module Helper
|
6
6
|
module_function
|
7
7
|
|
8
|
+
def adapter
|
9
|
+
if ActiveRecord::Base.respond_to?(:connection_config)
|
10
|
+
ActiveRecord::Base.connection_config[:adapter]
|
11
|
+
else
|
12
|
+
ActiveRecord::Base.connection_db_config.configuration_hash[:adapter]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def connection_config(klass)
|
17
|
+
if klass.respond_to?(:connection_config)
|
18
|
+
klass.connection_config
|
19
|
+
else
|
20
|
+
klass.connection_db_config.configuration_hash
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
8
24
|
# Returns list of models to check
|
9
25
|
def models
|
10
26
|
ActiveRecord::Base.descendants.delete_if(&:abstract_class?).delete_if do |klass|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: database_consistency
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evgeniy Demin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -56,14 +56,14 @@ dependencies:
|
|
56
56
|
name: pg
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0.2'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0.2'
|
69
69
|
- !ruby/object:Gem::Dependency
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '3.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec_junit_formatter
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.4'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.4'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: rubocop
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -185,7 +199,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
185
199
|
- !ruby/object:Gem::Version
|
186
200
|
version: '0'
|
187
201
|
requirements: []
|
188
|
-
rubygems_version: 3.
|
202
|
+
rubygems_version: 3.2.22
|
189
203
|
signing_key:
|
190
204
|
specification_version: 4
|
191
205
|
summary: Provide an easy way to check the consistency of the database constraints
|