strong_migrations 0.7.8 → 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.
@@ -1,3 +1,3 @@
1
1
  module StrongMigrations
2
- VERSION = "0.7.8"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -1,11 +1,19 @@
1
1
  # dependencies
2
2
  require "active_support"
3
3
 
4
+ # adapters
5
+ require "strong_migrations/adapters/abstract_adapter"
6
+ require "strong_migrations/adapters/mysql_adapter"
7
+ require "strong_migrations/adapters/mariadb_adapter"
8
+ require "strong_migrations/adapters/postgresql_adapter"
9
+
4
10
  # modules
11
+ require "strong_migrations/checks"
5
12
  require "strong_migrations/safe_methods"
6
13
  require "strong_migrations/checker"
7
14
  require "strong_migrations/database_tasks"
8
15
  require "strong_migrations/migration"
16
+ require "strong_migrations/migrator"
9
17
  require "strong_migrations/version"
10
18
 
11
19
  # integrations
@@ -14,235 +22,21 @@ require "strong_migrations/railtie" if defined?(Rails)
14
22
  module StrongMigrations
15
23
  class Error < StandardError; end
16
24
  class UnsafeMigration < Error; end
25
+ class UnsupportedVersion < Error; end
17
26
 
18
27
  class << self
19
28
  attr_accessor :auto_analyze, :start_after, :checks, :error_messages,
20
29
  :target_postgresql_version, :target_mysql_version, :target_mariadb_version,
21
30
  :enabled_checks, :lock_timeout, :statement_timeout, :check_down, :target_version,
22
- :safe_by_default
31
+ :safe_by_default, :target_sql_mode, :lock_timeout_retries, :lock_timeout_retry_delay
23
32
  attr_writer :lock_timeout_limit
24
33
  end
25
34
  self.auto_analyze = false
26
35
  self.start_after = 0
36
+ self.lock_timeout_retries = 0
37
+ self.lock_timeout_retry_delay = 10 # seconds
27
38
  self.checks = []
28
39
  self.safe_by_default = false
29
- self.error_messages = {
30
- add_column_default:
31
- "Adding a column with a non-null default blocks %{rewrite_blocks} while the entire table is rewritten.
32
- Instead, add the column without a default value, then change the default.
33
-
34
- class %{migration_name} < ActiveRecord::Migration%{migration_suffix}
35
- def up
36
- %{add_command}
37
- %{change_command}
38
- end
39
-
40
- def down
41
- %{remove_command}
42
- end
43
- end
44
-
45
- Then backfill the existing rows in the Rails console or a separate migration with disable_ddl_transaction!.
46
-
47
- class Backfill%{migration_name} < ActiveRecord::Migration%{migration_suffix}
48
- disable_ddl_transaction!
49
-
50
- def up
51
- %{code}
52
- end
53
- end",
54
-
55
- add_column_json:
56
- "There's no equality operator for the json column type, which can cause errors for
57
- existing SELECT DISTINCT queries in your application. Use jsonb instead.
58
-
59
- class %{migration_name} < ActiveRecord::Migration%{migration_suffix}
60
- def change
61
- %{command}
62
- end
63
- end",
64
-
65
- change_column:
66
- "Changing the type of an existing column blocks %{rewrite_blocks}
67
- while the entire table is rewritten. A safer approach is to:
68
-
69
- 1. Create a new column
70
- 2. Write to both columns
71
- 3. Backfill data from the old column to the new column
72
- 4. Move reads from the old column to the new column
73
- 5. Stop writing to the old column
74
- 6. Drop the old column",
75
-
76
- change_column_with_not_null:
77
- "Changing the type is safe, but setting NOT NULL is not.",
78
-
79
- remove_column: "Active Record caches attributes, which causes problems
80
- when removing columns. Be sure to ignore the column%{column_suffix}:
81
-
82
- class %{model} < %{base_model}
83
- %{code}
84
- end
85
-
86
- Deploy the code, then wrap this step in a safety_assured { ... } block.
87
-
88
- class %{migration_name} < ActiveRecord::Migration%{migration_suffix}
89
- def change
90
- safety_assured { %{command} }
91
- end
92
- end",
93
-
94
- rename_column:
95
- "Renaming a column that's in use will cause errors
96
- in your application. A safer approach is to:
97
-
98
- 1. Create a new column
99
- 2. Write to both columns
100
- 3. Backfill data from the old column to new column
101
- 4. Move reads from the old column to the new column
102
- 5. Stop writing to the old column
103
- 6. Drop the old column",
104
-
105
- rename_table:
106
- "Renaming a table that's in use will cause errors
107
- in your application. A safer approach is to:
108
-
109
- 1. Create a new table. Don't forget to recreate indexes from the old table
110
- 2. Write to both tables
111
- 3. Backfill data from the old table to new table
112
- 4. Move reads from the old table to the new table
113
- 5. Stop writing to the old table
114
- 6. Drop the old table",
115
-
116
- add_reference:
117
- "%{headline} Instead, use:
118
-
119
- class %{migration_name} < ActiveRecord::Migration%{migration_suffix}
120
- disable_ddl_transaction!
121
-
122
- def change
123
- %{command}
124
- end
125
- end",
126
-
127
- add_index:
128
- "Adding an index non-concurrently blocks writes. Instead, use:
129
-
130
- class %{migration_name} < ActiveRecord::Migration%{migration_suffix}
131
- disable_ddl_transaction!
132
-
133
- def change
134
- %{command}
135
- end
136
- end",
137
-
138
- remove_index:
139
- "Removing an index non-concurrently blocks writes. Instead, use:
140
-
141
- class %{migration_name} < ActiveRecord::Migration%{migration_suffix}
142
- disable_ddl_transaction!
143
-
144
- def change
145
- %{command}
146
- end
147
- end",
148
-
149
- add_index_columns:
150
- "Adding a non-unique index with more than three columns rarely improves performance.
151
- Instead, start an index with columns that narrow down the results the most.",
152
-
153
- change_table:
154
- "Strong Migrations does not support inspecting what happens inside a
155
- change_table block, so cannot help you here. Please make really sure that what
156
- you're doing is safe before proceeding, then wrap it in a safety_assured { ... } block.",
157
-
158
- create_table:
159
- "The force option will destroy existing tables.
160
- If this is intended, drop the existing table first.
161
- Otherwise, remove the force option.",
162
-
163
- execute:
164
- "Strong Migrations does not support inspecting what happens inside an
165
- execute call, so cannot help you here. Please make really sure that what
166
- you're doing is safe before proceeding, then wrap it in a safety_assured { ... } block.",
167
-
168
- change_column_null:
169
- "Passing a default value to change_column_null runs a single UPDATE query,
170
- which can cause downtime. Instead, backfill the existing rows in the
171
- Rails console or a separate migration with disable_ddl_transaction!.
172
-
173
- class Backfill%{migration_name} < ActiveRecord::Migration%{migration_suffix}
174
- disable_ddl_transaction!
175
-
176
- def up
177
- %{code}
178
- end
179
- end",
180
-
181
- change_column_null_postgresql:
182
- "Setting NOT NULL on an existing column blocks reads and writes while every row is checked.
183
- Instead, add a check constraint and validate it in a separate migration.
184
-
185
- class %{migration_name} < ActiveRecord::Migration%{migration_suffix}
186
- def change
187
- %{add_constraint_code}
188
- end
189
- end
190
-
191
- class Validate%{migration_name} < ActiveRecord::Migration%{migration_suffix}
192
- def change
193
- %{validate_constraint_code}
194
- end
195
- end",
196
-
197
- change_column_null_mysql:
198
- "Setting NOT NULL on an existing column is not safe with your database engine.",
199
-
200
- add_foreign_key:
201
- "Adding a foreign key blocks writes on both tables. Instead,
202
- add the foreign key without validating existing rows,
203
- then validate them in a separate migration.
204
-
205
- class %{migration_name} < ActiveRecord::Migration%{migration_suffix}
206
- def change
207
- %{add_foreign_key_code}
208
- end
209
- end
210
-
211
- class Validate%{migration_name} < ActiveRecord::Migration%{migration_suffix}
212
- def change
213
- %{validate_foreign_key_code}
214
- end
215
- end",
216
-
217
- validate_foreign_key:
218
- "Validating a foreign key while writes are blocked is dangerous.
219
- Use disable_ddl_transaction! or a separate migration.",
220
-
221
- add_check_constraint:
222
- "Adding a check constraint key blocks reads and writes while every row is checked.
223
- Instead, add the check constraint without validating existing rows,
224
- then validate them in a separate migration.
225
-
226
- class %{migration_name} < ActiveRecord::Migration%{migration_suffix}
227
- def change
228
- %{add_check_constraint_code}
229
- end
230
- end
231
-
232
- class Validate%{migration_name} < ActiveRecord::Migration%{migration_suffix}
233
- def change
234
- %{validate_check_constraint_code}
235
- end
236
- end",
237
-
238
- add_check_constraint_mysql:
239
- "Adding a check constraint to an existing table is not safe with your database engine.",
240
-
241
- validate_check_constraint:
242
- "Validating a check constraint while writes are blocked is dangerous.
243
- Use disable_ddl_transaction! or a separate migration."
244
- }
245
- self.enabled_checks = (error_messages.keys - [:remove_index]).map { |k| [k, {}] }.to_h
246
40
  self.check_down = false
247
41
 
248
42
  # private
@@ -279,8 +73,12 @@ Use disable_ddl_transaction! or a separate migration."
279
73
  end
280
74
  end
281
75
 
76
+ # load error messages
77
+ require "strong_migrations/error_messages"
78
+
282
79
  ActiveSupport.on_load(:active_record) do
283
80
  ActiveRecord::Migration.prepend(StrongMigrations::Migration)
81
+ ActiveRecord::Migrator.prepend(StrongMigrations::Migrator)
284
82
 
285
83
  if defined?(ActiveRecord::Tasks::DatabaseTasks)
286
84
  ActiveRecord::Tasks::DatabaseTasks.singleton_class.prepend(StrongMigrations::DatabaseTasks)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: strong_migrations
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.8
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2021-08-03 00:00:00.000000000 Z
13
+ date: 2022-03-21 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -18,87 +18,17 @@ dependencies:
18
18
  requirements:
19
19
  - - ">="
20
20
  - !ruby/object:Gem::Version
21
- version: '5'
21
+ version: '5.2'
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
- version: '5'
29
- - !ruby/object:Gem::Dependency
30
- name: bundler
31
- requirement: !ruby/object:Gem::Requirement
32
- requirements:
33
- - - ">="
34
- - !ruby/object:Gem::Version
35
- version: '0'
36
- type: :development
37
- prerelease: false
38
- version_requirements: !ruby/object:Gem::Requirement
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- version: '0'
43
- - !ruby/object:Gem::Dependency
44
- name: rake
45
- requirement: !ruby/object:Gem::Requirement
46
- requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: '0'
50
- type: :development
51
- prerelease: false
52
- version_requirements: !ruby/object:Gem::Requirement
53
- requirements:
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- version: '0'
57
- - !ruby/object:Gem::Dependency
58
- name: minitest
59
- requirement: !ruby/object:Gem::Requirement
60
- requirements:
61
- - - ">="
62
- - !ruby/object:Gem::Version
63
- version: '0'
64
- type: :development
65
- prerelease: false
66
- version_requirements: !ruby/object:Gem::Requirement
67
- requirements:
68
- - - ">="
69
- - !ruby/object:Gem::Version
70
- version: '0'
71
- - !ruby/object:Gem::Dependency
72
- name: pg
73
- requirement: !ruby/object:Gem::Requirement
74
- requirements:
75
- - - ">="
76
- - !ruby/object:Gem::Version
77
- version: '0'
78
- type: :development
79
- prerelease: false
80
- version_requirements: !ruby/object:Gem::Requirement
81
- requirements:
82
- - - ">="
83
- - !ruby/object:Gem::Version
84
- version: '0'
85
- - !ruby/object:Gem::Dependency
86
- name: mysql2
87
- requirement: !ruby/object:Gem::Requirement
88
- requirements:
89
- - - ">="
90
- - !ruby/object:Gem::Version
91
- version: '0'
92
- type: :development
93
- prerelease: false
94
- version_requirements: !ruby/object:Gem::Requirement
95
- requirements:
96
- - - ">="
97
- - !ruby/object:Gem::Version
98
- version: '0'
28
+ version: '5.2'
99
29
  description:
100
30
  email:
101
- - andrew@chartkick.com
31
+ - andrew@ankane.org
102
32
  - bob.remeika@gmail.com
103
33
  executables: []
104
34
  extensions: []
@@ -111,10 +41,17 @@ files:
111
41
  - lib/generators/strong_migrations/install_generator.rb
112
42
  - lib/generators/strong_migrations/templates/initializer.rb.tt
113
43
  - lib/strong_migrations.rb
44
+ - lib/strong_migrations/adapters/abstract_adapter.rb
45
+ - lib/strong_migrations/adapters/mariadb_adapter.rb
46
+ - lib/strong_migrations/adapters/mysql_adapter.rb
47
+ - lib/strong_migrations/adapters/postgresql_adapter.rb
114
48
  - lib/strong_migrations/alphabetize_columns.rb
115
49
  - lib/strong_migrations/checker.rb
50
+ - lib/strong_migrations/checks.rb
116
51
  - lib/strong_migrations/database_tasks.rb
52
+ - lib/strong_migrations/error_messages.rb
117
53
  - lib/strong_migrations/migration.rb
54
+ - lib/strong_migrations/migrator.rb
118
55
  - lib/strong_migrations/railtie.rb
119
56
  - lib/strong_migrations/safe_methods.rb
120
57
  - lib/strong_migrations/version.rb
@@ -131,14 +68,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
131
68
  requirements:
132
69
  - - ">="
133
70
  - !ruby/object:Gem::Version
134
- version: '2.4'
71
+ version: '2.6'
135
72
  required_rubygems_version: !ruby/object:Gem::Requirement
136
73
  requirements:
137
74
  - - ">="
138
75
  - !ruby/object:Gem::Version
139
76
  version: '0'
140
77
  requirements: []
141
- rubygems_version: 3.2.22
78
+ rubygems_version: 3.3.7
142
79
  signing_key:
143
80
  specification_version: 4
144
81
  summary: Catch unsafe migrations in development