strong_migrations 0.8.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.
@@ -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.8.0
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: 2022-02-10 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
@@ -41,10 +41,17 @@ files:
41
41
  - lib/generators/strong_migrations/install_generator.rb
42
42
  - lib/generators/strong_migrations/templates/initializer.rb.tt
43
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
44
48
  - lib/strong_migrations/alphabetize_columns.rb
45
49
  - lib/strong_migrations/checker.rb
50
+ - lib/strong_migrations/checks.rb
46
51
  - lib/strong_migrations/database_tasks.rb
52
+ - lib/strong_migrations/error_messages.rb
47
53
  - lib/strong_migrations/migration.rb
54
+ - lib/strong_migrations/migrator.rb
48
55
  - lib/strong_migrations/railtie.rb
49
56
  - lib/strong_migrations/safe_methods.rb
50
57
  - lib/strong_migrations/version.rb
@@ -68,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
68
75
  - !ruby/object:Gem::Version
69
76
  version: '0'
70
77
  requirements: []
71
- rubygems_version: 3.3.3
78
+ rubygems_version: 3.3.7
72
79
  signing_key:
73
80
  specification_version: 4
74
81
  summary: Catch unsafe migrations in development