mimi-db 0.2.3 → 0.2.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f6c134a70d22d57cb28bc7eef7dd2dea944f743c
4
- data.tar.gz: 9f7088a8658380872586ef77d273d4b9db8a4f22
3
+ metadata.gz: 7d8e5f05648963455f22f4495aeed73bbab8edd4
4
+ data.tar.gz: b519848493d926249f1be91a586e80aaceff153e
5
5
  SHA512:
6
- metadata.gz: 64fb09362a80c2b1d60f671d4672862a4a70753024509c5a08091dfc5c8c846ba5df476190918f15d5e0968dae0abc4e3282a4dc18d2303cc7acaf0f8f2caa98
7
- data.tar.gz: 6f6a42c8af65974cc9ddf7fcd4785e10cf0c1c2b16efc9320bda145ad3048b459304e41a82c3acad5ad38aec9ca76542363239de7f138740ff0e0de67c54dc25
6
+ metadata.gz: 0f61958bb7e08cbf6d2ed28e8ed566a983f38365894257eb84b5ed579da21b248cfbd6898a964d267b22e1d22a6b806c6c0add014afa245a143c997a0a784fbf
7
+ data.tar.gz: 5256b301a6bd6891cf3cf47698ae34608b9b68858b7d39c1854da2bfc041779b2dfacd101c6b7306b569d91e95c28298beae2aadbec97c3f3ba872a273783ff0
@@ -83,24 +83,28 @@ module Mimi
83
83
 
84
84
  def run_change_table!
85
85
  diff = Mimi::DB::Dictate::SchemaDiff.diff(from_schema, to_schema)
86
- if diff.empty?
86
+ if diff[:columns].empty? && diff[:indexes].empty?
87
87
  logger.info "- no changes: #{table_name}"
88
88
  return
89
89
  end
90
90
  logger.info "- ALTER TABLE: #{table_name}"
91
- run_change_table_columns!(diff[:columns]) if diff[:columns]
92
- run_change_table_indexes!(diff[:indexes]) if diff[:indexes]
91
+ run_change_table_columns!(diff[:columns]) unless diff[:columns].empty?
92
+ run_change_table_indexes!(diff[:indexes]) unless diff[:indexes].empty?
93
93
  end
94
94
 
95
95
  def run_change_table_columns!(diff_columns)
96
- diff_columns[:remove]&.each { |c| drop_column!(table_name, c) }
97
- diff_columns[:change]&.each { |c| change_column!(table_name, c) }
98
- diff_columns[:add]&.each { |c| add_column!(table_name, c) }
96
+ diff_columns.each do |c, diff|
97
+ drop_column!(table_name, c) if diff[:from] && diff[:to].nil?
98
+ change_column!(table_name, diff[:to]) if diff[:from] && diff[:to]
99
+ add_column!(table_name, diff[:to]) if diff[:from].nil? && diff[:to]
100
+ end
99
101
  end
100
102
 
101
103
  def run_change_table_indexes!(diff_indexes)
102
- diff_indexes[:remove]&.each { |i| drop_index!(table_name, i) }
103
- diff_indexes[:add]&.each { |i| add_index!(table_name, i) }
104
+ diff_indexes.each do |i, diff|
105
+ drop_index!(table_name, diff[:from]) if diff[:from] && diff[:to].nil?
106
+ add_index!(table_name, diff[:to]) if diff[:from].nil? && diff[:to]
107
+ end
104
108
  end
105
109
 
106
110
  def run_create_table!
@@ -15,58 +15,35 @@ module Mimi
15
15
  #
16
16
  # Compares two schema definitions
17
17
  #
18
- # @return [Hash] :columns, :indexes => :add, :remove, :change
18
+ # @return [Hash] :columns, :indexes => :from, :to
19
19
  #
20
20
  def self.diff(from, to, opts = {})
21
21
  options = DEFAULT_OPTIONS.merge(opts)
22
- from_column_names = from.columns.values.map(&:name)
23
- to_column_names = to.columns.values.map(&:name)
24
- columns_names_remove = from_column_names - to_column_names
25
- columns_names_add = to_column_names - from_column_names
26
- columns_add = to.columns.values.select do |c|
27
- columns_names_add.include?(c.name)
22
+ result = { table_name: from.table_name, columns: {}, indexes: {} }
23
+ all_column_names = (from.columns.values.map(&:name) + to.columns.values.map(&:name)).uniq
24
+ all_column_names.each do |c|
25
+ if from.columns[c] && to.columns[c].nil?
26
+ result[:columns][c] = { from: from.columns[c], to: nil }
27
+ elsif from.columns[c] && to.columns[c] && !(from.columns[c] == to.columns[c])
28
+ result[:columns][c] = { from: from.columns[c], to: to.columns[c] }
29
+ elsif from.columns[c].nil? && to.columns[c]
30
+ result[:columns][c] = { from: nil, to: to.columns[c] }
31
+ end
32
+ end
33
+ from_indexes = from.indexes.map { |i| [i.columns, i] }.to_h
34
+ to_indexes = to.indexes.map { |i| [i.columns, i] }.to_h
35
+ all_index_cols = (from_indexes.keys + to_indexes.keys).uniq
36
+ all_index_cols.each do |cc|
37
+ if from_indexes[cc] && to_indexes[cc].nil?
38
+ result[:indexes][cc] = { from: from_indexes[cc], to: nil }
39
+ elsif from_indexes[cc] && to_indexes[cc]
40
+ # index diff is not supported
41
+ elsif from_indexes[cc].nil? && to_indexes[cc]
42
+ result[:indexes][cc] = { from: nil, to: to_indexes[cc]}
43
+ end
28
44
  end
29
- columns_change = to.columns.values.reject do |c|
30
- res = from.columns[c.name].nil? || from.columns[c.name] == c
31
- res ||= c.type == :primary_key unless options[:force_primary_key]
32
- end
33
- from_indexes_c = from.indexes.map(&:columns).uniq
34
- to_indexes_c = to.indexes.map(&:columns).uniq
35
- # ignore primary key indexes
36
- from_indexes_c -= [[from.primary_key&.name]]
37
- to_indexes_c -= [[to.primary_key&.name]]
38
45
 
39
- indexes_c_remove = from_indexes_c - to_indexes_c
40
- indexes_c_add = to_indexes_c - from_indexes_c
41
- indexes_remove = from.indexes.select do |idx|
42
- indexes_c_remove.include?(idx.columns)
43
- end
44
- indexes_add = to.indexes.select do |idx|
45
- indexes_c_add.include?(idx.columns)
46
- end
47
-
48
- diff = {}
49
- unless columns_names_remove.empty?
50
- diff[:columns] ||= {}
51
- diff[:columns][:remove] = columns_names_remove
52
- end
53
- unless columns_change.empty?
54
- diff[:columns] ||= {}
55
- diff[:columns][:change] = columns_change
56
- end
57
- unless columns_add.empty?
58
- diff[:columns] ||= {}
59
- diff[:columns][:add] = columns_add
60
- end
61
- unless indexes_remove.empty?
62
- diff[:indexes] ||= {}
63
- diff[:indexes][:remove] = indexes_remove
64
- end
65
- unless indexes_add.empty?
66
- diff[:indexes] ||= {}
67
- diff[:indexes][:add] = indexes_add
68
- end
69
- diff
46
+ result
70
47
  end
71
48
  end # module SchemaDiff
72
49
  end # module Dictate
@@ -85,6 +85,31 @@ module Mimi
85
85
  logger.error "DB::Dictate failed to update DB schema: #{e}"
86
86
  raise
87
87
  end
88
+
89
+ # Diff existing DB schema and the target schema
90
+ #
91
+ # @param opts [Hash]
92
+ # @return [Hash]
93
+ #
94
+ def self.diff_schema!(opts = {})
95
+ logger = opts[:logger] || ActiveRecord::Base.logger
96
+ diff = { add_tables: [], change_tables: [], drop_tables: []}
97
+ Mimi::DB.all_table_names.each do |t|
98
+ m = Mimi::DB::Dictate::Migrator.new(t, opts)
99
+ if m.from_schema && m.to_schema.nil?
100
+ diff[:drop_tables] << t
101
+ elsif m.from_schema && m.to_schema
102
+ t_diff = Mimi::DB::Dictate::SchemaDiff.diff(m.from_schema, m.to_schema)
103
+ diff[:change_tables] << t_diff unless t_diff[:columns].empty? && t_diff[:indexes].empty?
104
+ elsif m.from_schema.nil? && m.to_schema
105
+ diff[:add_tables] << m.to_schema
106
+ end
107
+ end
108
+ diff
109
+ rescue StandardError => e
110
+ logger.error "DB::Dictate failed to update DB schema: #{e}"
111
+ raise
112
+ end
88
113
  end # module Dictate
89
114
  end # module DB
90
115
  end # module Mimi
@@ -60,6 +60,34 @@ module Mimi
60
60
  Mimi::DB::Dictate.update_schema!(opts)
61
61
  end
62
62
 
63
+ # Discovers differences between existing DB schema and target schema
64
+ # defined in models.
65
+ #
66
+ # @example
67
+ # Mimi::DB.diff_schema
68
+ #
69
+ # # =>
70
+ # # {
71
+ # # add_tables: [<table_schema1>, <table_schema2> ...],
72
+ # # change_tables: [
73
+ # # { table_name: ...,
74
+ # # columns: {
75
+ # # "<column_name1>" => {
76
+ # # from: { <column_definition or nil> },
77
+ # # to: { <column_definition or nil> }
78
+ # # }
79
+ # # }
80
+ # # }, ...
81
+ # # ],
82
+ # # drop_tables: [<table_name1>, ...]
83
+ # # }
84
+ # @return [Hash]
85
+ #
86
+ def diff_schema!(opts = {})
87
+ opts[:logger] ||= Mimi::DB.logger
88
+ Mimi::DB::Dictate.diff_schema(opts)
89
+ end
90
+
63
91
  # Creates the database specified in the current configuration.
64
92
  #
65
93
  def create!
@@ -1,5 +1,5 @@
1
1
  module Mimi
2
2
  module DB
3
- VERSION = '0.2.3'.freeze
3
+ VERSION = '0.2.4'.freeze
4
4
  end
5
5
  end
data/lib/tasks/db.rake CHANGED
@@ -59,6 +59,14 @@ namespace :db do
59
59
  logger.info "* Updating database schema (DRY RUN): #{Mimi::DB.module_options[:db_database]}"
60
60
  Mimi::DB.update_schema!(destructive: true, dry_run: true)
61
61
  end
62
+
63
+ desc 'Display differences between existing DB schema and target schema'
64
+ task diff: :"db:start" do
65
+ logger.info "* Diff database schema: #{Mimi::DB.module_options[:db_database]}"
66
+ diff = Mimi::DB.diff_schema(destructive: true, dry_run: true)
67
+ require 'pp'
68
+ pp diff
69
+ end
62
70
  end
63
71
  end
64
72
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mimi-db
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Kukushkin