strong_migrations 0.4.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -19
- data/README.md +112 -14
- data/lib/strong_migrations.rb +51 -5
- data/lib/strong_migrations/checker.rb +33 -14
- data/lib/strong_migrations/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 372efa1cc2267462dd7294cf7d39cd710941b223df3d38ec4d24fd7a91feb7ad
|
4
|
+
data.tar.gz: '0139953c4aee0b08a15e9169af644eca36aa3ecd49d5c7c23a678d7423c35233'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1d8049950bb0a8d38d01479b5a00e6ca9ed80878d2a7b8d21a8217efaf51e7727793d82845c9287c4e18619aa4a36d581b69de47e8ab48f16612ebf9188601c
|
7
|
+
data.tar.gz: 7b9f3a70ec40ffa42fe8e2928998de861cca4bcbdb23ad3ad9134b4fea09cc0228439b32cb8ec19910d5faf6f331445ba692bca1b8d0a5681d1d77df78554374
|
data/CHANGELOG.md
CHANGED
@@ -1,93 +1,99 @@
|
|
1
|
-
## 0.
|
1
|
+
## 0.5.0 (2019-12-05)
|
2
|
+
|
3
|
+
- Added ability to disable checks
|
4
|
+
- Added Postgres-specific check for `change_column_null`
|
5
|
+
- Added optional remove index check
|
6
|
+
|
7
|
+
## 0.4.2 (2019-10-27)
|
2
8
|
|
3
9
|
- Allow `add_reference` with concurrent indexes
|
4
10
|
|
5
|
-
## 0.4.1
|
11
|
+
## 0.4.1 (2019-07-12)
|
6
12
|
|
7
13
|
- Added `target_postgresql_version`
|
8
14
|
- Added `unscoped` to backfill instructions
|
9
15
|
|
10
|
-
## 0.4.0
|
16
|
+
## 0.4.0 (2019-05-27)
|
11
17
|
|
12
18
|
- Added check for `add_foreign_key`
|
13
19
|
- Fixed instructions for adding default value with NOT NULL constraint
|
14
20
|
- Removed support for Rails 4.2
|
15
21
|
|
16
|
-
## 0.3.1
|
22
|
+
## 0.3.1 (2018-10-18)
|
17
23
|
|
18
24
|
- Fixed error with `remove_column` and `type` argument
|
19
25
|
- Improved message customization
|
20
26
|
|
21
|
-
## 0.3.0
|
27
|
+
## 0.3.0 (2018-10-15)
|
22
28
|
|
23
29
|
- Added support for custom checks
|
24
30
|
- Adding a column with a non-null default value is safe in Postgres 11+
|
25
31
|
- Added checks for `add_belongs_to`, `remove_belongs_to`, `remove_columns`, and `remove_reference`
|
26
32
|
- Customized messages
|
27
33
|
|
28
|
-
## 0.2.3
|
34
|
+
## 0.2.3 (2018-07-22)
|
29
35
|
|
30
36
|
- Added check for `change_column_null`
|
31
37
|
- Added support for alphabetize columns with Makara
|
32
38
|
- Fixed migration reversibility with `auto_analyze`
|
33
39
|
|
34
|
-
## 0.2.2
|
40
|
+
## 0.2.2 (2018-02-14)
|
35
41
|
|
36
42
|
- Friendlier output
|
37
43
|
- Better method of hooking into ActiveRecord
|
38
44
|
|
39
|
-
## 0.2.1
|
45
|
+
## 0.2.1 (2018-02-07)
|
40
46
|
|
41
47
|
- Recommend `disable_ddl_transaction!` over `commit_db_transaction`
|
42
48
|
- Suggest `jsonb` over `json` in Postgres 9.4+
|
43
49
|
- Changing `varchar` to `text` is safe in Postgres 9.1+
|
44
50
|
- Do not check number of columns for unique indexes
|
45
51
|
|
46
|
-
## 0.2.0
|
52
|
+
## 0.2.0 (2018-01-07)
|
47
53
|
|
48
54
|
- Added customizable error messages
|
49
55
|
- Updated instructions for adding a column with a default value
|
50
56
|
|
51
|
-
## 0.1.9
|
57
|
+
## 0.1.9 (2017-06-14)
|
52
58
|
|
53
59
|
- Added `start_after` option
|
54
60
|
|
55
|
-
## 0.1.8
|
61
|
+
## 0.1.8 (2017-05-31)
|
56
62
|
|
57
63
|
- Fixed error with `create_table`
|
58
64
|
- Added check for executing arbitrary SQL
|
59
65
|
|
60
|
-
## 0.1.7
|
66
|
+
## 0.1.7 (2017-05-29)
|
61
67
|
|
62
68
|
- Added check for `force` option with `create_table`
|
63
69
|
- Added `auto_analyze` option
|
64
70
|
|
65
|
-
## 0.1.6
|
71
|
+
## 0.1.6 (2017-03-23)
|
66
72
|
|
67
73
|
- Adding an index to a newly created table is now safe
|
68
74
|
|
69
|
-
## 0.1.5
|
75
|
+
## 0.1.5 (2016-07-23)
|
70
76
|
|
71
77
|
- Fixed error with Ruby 2.3 frozen strings
|
72
78
|
|
73
|
-
## 0.1.4
|
79
|
+
## 0.1.4 (2016-03-22)
|
74
80
|
|
75
81
|
- Added alphabetize columns
|
76
82
|
|
77
|
-
## 0.1.3
|
83
|
+
## 0.1.3 (2016-03-12)
|
78
84
|
|
79
85
|
- Disabled dangerous rake tasks in production
|
80
86
|
- Added ability to use `SAFETY_ASSURED` env var
|
81
87
|
|
82
|
-
## 0.1.2
|
88
|
+
## 0.1.2 (2016-02-24)
|
83
89
|
|
84
90
|
- Skip checks on down migrations and rollbacks
|
85
91
|
- Added check for indexes with more than 3 columns
|
86
92
|
|
87
|
-
## 0.1.1
|
93
|
+
## 0.1.1 (2015-11-29)
|
88
94
|
|
89
95
|
- Fixed `add_index` check for MySQL
|
90
96
|
|
91
|
-
## 0.1.0
|
97
|
+
## 0.1.0 (2015-11-22)
|
92
98
|
|
93
99
|
- First release
|
data/README.md
CHANGED
@@ -34,10 +34,14 @@ The following operations can cause downtime or errors:
|
|
34
34
|
- [[+]](#renaming-or-changing-the-type-of-a-column) renaming a column
|
35
35
|
- [[+]](#renaming-a-table) renaming a table
|
36
36
|
- [[+]](#creating-a-table-with-the-force-option) creating a table with the `force` option
|
37
|
-
- [[+]](#using-change_column_null
|
37
|
+
- [[+]](#using-change_column_null) using `change_column_null`
|
38
38
|
- [[+]](#adding-a-json-column) adding a `json` column
|
39
39
|
|
40
|
-
|
40
|
+
Optional checks:
|
41
|
+
|
42
|
+
- [[+]](#removing-an-index) removing an index non-concurrently
|
43
|
+
|
44
|
+
Best practices:
|
41
45
|
|
42
46
|
- [[+]](#keeping-non-unique-indexes-to-three-columns-or-less) keeping non-unique indexes to three columns or less
|
43
47
|
|
@@ -82,6 +86,8 @@ end
|
|
82
86
|
|
83
87
|
### Adding a column with a default value
|
84
88
|
|
89
|
+
Note: This operation is safe in Postgres 11+.
|
90
|
+
|
85
91
|
#### Bad
|
86
92
|
|
87
93
|
Adding a column with a default value to an existing table causes the entire table to be rewritten.
|
@@ -94,8 +100,6 @@ class AddSomeColumnToUsers < ActiveRecord::Migration[6.0]
|
|
94
100
|
end
|
95
101
|
```
|
96
102
|
|
97
|
-
> This operation is safe in Postgres 11+
|
98
|
-
|
99
103
|
#### Good
|
100
104
|
|
101
105
|
Instead, add the column without a default value, then change the default.
|
@@ -153,7 +157,7 @@ end
|
|
153
157
|
|
154
158
|
#### Bad
|
155
159
|
|
156
|
-
In Postgres, adding
|
160
|
+
In Postgres, adding an index non-concurrently locks the table.
|
157
161
|
|
158
162
|
```ruby
|
159
163
|
class AddSomeIndexToUsers < ActiveRecord::Migration[6.0]
|
@@ -183,7 +187,7 @@ If you forget `disable_ddl_transaction!`, the migration will fail. Also, note th
|
|
183
187
|
|
184
188
|
#### Bad
|
185
189
|
|
186
|
-
Rails adds
|
190
|
+
Rails adds an index non-concurrently to references by default, which is problematic for Postgres.
|
187
191
|
|
188
192
|
```ruby
|
189
193
|
class AddReferenceToUsers < ActiveRecord::Migration[6.0]
|
@@ -207,13 +211,11 @@ class AddReferenceToUsers < ActiveRecord::Migration[6.0]
|
|
207
211
|
end
|
208
212
|
```
|
209
213
|
|
210
|
-
For polymorphic references, add a compound index on type and id.
|
211
|
-
|
212
214
|
### Adding a foreign key
|
213
215
|
|
214
216
|
#### Bad
|
215
217
|
|
216
|
-
In Postgres, new foreign keys are validated by default, which acquires
|
218
|
+
In Postgres, new foreign keys are validated by default, which acquires a `ShareRowExclusiveLock` that can be [expensive on large tables](https://travisofthenorth.com/blog/2017/2/2/postgres-adding-foreign-keys-with-zero-downtime).
|
217
219
|
|
218
220
|
```ruby
|
219
221
|
class AddForeignKeyOnUsers < ActiveRecord::Migration[6.0]
|
@@ -359,7 +361,49 @@ class CreateUsers < ActiveRecord::Migration[6.0]
|
|
359
361
|
end
|
360
362
|
```
|
361
363
|
|
362
|
-
### Using change_column_null
|
364
|
+
### Using change_column_null
|
365
|
+
|
366
|
+
#### Bad
|
367
|
+
|
368
|
+
In Postgres, setting `NOT NULL` on an existing column requires an `AccessExclusiveLock`, which is expensive on large tables.
|
369
|
+
|
370
|
+
```ruby
|
371
|
+
class SetSomeColumnNotNull < ActiveRecord::Migration[6.0]
|
372
|
+
def change
|
373
|
+
change_column_null :users, :some_column, false
|
374
|
+
end
|
375
|
+
end
|
376
|
+
```
|
377
|
+
|
378
|
+
#### Good
|
379
|
+
|
380
|
+
Instead, add a constraint:
|
381
|
+
|
382
|
+
```ruby
|
383
|
+
class SetSomeColumnNotNull < ActiveRecord::Migration[6.0]
|
384
|
+
def change
|
385
|
+
safety_assured do
|
386
|
+
execute 'ALTER TABLE "users" ADD CONSTRAINT "users_some_column_null" CHECK ("some_column" IS NOT NULL) NOT VALID'
|
387
|
+
end
|
388
|
+
end
|
389
|
+
end
|
390
|
+
```
|
391
|
+
|
392
|
+
Then validate it in a separate migration.
|
393
|
+
|
394
|
+
```ruby
|
395
|
+
class ValidateSomeColumnNotNull < ActiveRecord::Migration[6.0]
|
396
|
+
def change
|
397
|
+
safety_assured do
|
398
|
+
execute 'ALTER TABLE "users" VALIDATE CONSTRAINT "users_some_column_null"'
|
399
|
+
end
|
400
|
+
end
|
401
|
+
end
|
402
|
+
```
|
403
|
+
|
404
|
+
Note: This is not 100% the same as `NOT NULL` column constraint. Here’s a [good explanation](https://medium.com/doctolib/adding-a-not-null-constraint-on-pg-faster-with-minimal-locking-38b2c00c4d1c).
|
405
|
+
|
406
|
+
### Using change_column_null with a default value (non-Postgres)
|
363
407
|
|
364
408
|
#### Bad
|
365
409
|
|
@@ -385,11 +429,13 @@ class ChangeSomeColumnNull < ActiveRecord::Migration[6.0]
|
|
385
429
|
end
|
386
430
|
```
|
387
431
|
|
432
|
+
Note: In Postgres, `change_column_null` is still [not safe](#using-change_column_null) with this method.
|
433
|
+
|
388
434
|
### Adding a json column
|
389
435
|
|
390
436
|
#### Bad
|
391
437
|
|
392
|
-
In Postgres, there’s no equality operator for the `json` column type, which
|
438
|
+
In Postgres, there’s no equality operator for the `json` column type, which can cause errors for existing `SELECT DISTINCT` queries.
|
393
439
|
|
394
440
|
```ruby
|
395
441
|
class AddPropertiesToUsers < ActiveRecord::Migration[6.0]
|
@@ -411,6 +457,48 @@ class AddPropertiesToUsers < ActiveRecord::Migration[6.0]
|
|
411
457
|
end
|
412
458
|
```
|
413
459
|
|
460
|
+
## Optional Checks
|
461
|
+
|
462
|
+
Some operations rarely cause issues in practice, but can be checked if desired. Enable checks with:
|
463
|
+
|
464
|
+
```ruby
|
465
|
+
StrongMigrations.enable_check(:remove_index)
|
466
|
+
```
|
467
|
+
|
468
|
+
To start a check only after a specific migration, use:
|
469
|
+
|
470
|
+
```ruby
|
471
|
+
StrongMigrations.enable_check(:remove_index, start_after: 20170101000000)
|
472
|
+
```
|
473
|
+
|
474
|
+
### Removing an index
|
475
|
+
|
476
|
+
#### Bad
|
477
|
+
|
478
|
+
In Postgres, removing an index non-concurrently locks the table for a brief period.
|
479
|
+
|
480
|
+
```ruby
|
481
|
+
class RemoveSomeIndexFromUsers < ActiveRecord::Migration[6.0]
|
482
|
+
def change
|
483
|
+
remove_index :users, :some_column
|
484
|
+
end
|
485
|
+
end
|
486
|
+
```
|
487
|
+
|
488
|
+
#### Good
|
489
|
+
|
490
|
+
Remove indexes concurrently.
|
491
|
+
|
492
|
+
```ruby
|
493
|
+
class RemoveSomeIndexFromUsers < ActiveRecord::Migration[6.0]
|
494
|
+
disable_ddl_transaction!
|
495
|
+
|
496
|
+
def change
|
497
|
+
remove_index :users, column: :some_column, algorithm: :concurrently
|
498
|
+
end
|
499
|
+
end
|
500
|
+
```
|
501
|
+
|
414
502
|
## Best Practices
|
415
503
|
|
416
504
|
### Keeping non-unique indexes to three columns or less
|
@@ -439,7 +527,7 @@ class AddSomeIndexToUsers < ActiveRecord::Migration[6.0]
|
|
439
527
|
end
|
440
528
|
```
|
441
529
|
|
442
|
-
|
530
|
+
For Postgres, be sure to add them concurrently.
|
443
531
|
|
444
532
|
## Assuring Safety
|
445
533
|
|
@@ -469,7 +557,17 @@ end
|
|
469
557
|
|
470
558
|
Use the `stop!` method to stop migrations.
|
471
559
|
|
472
|
-
|
560
|
+
Note: Since `remove_column` always requires a `safety_assured` block, it’s not possible to add a custom check for `remove_column` operations.
|
561
|
+
|
562
|
+
## Disable Checks
|
563
|
+
|
564
|
+
Disable specific checks with:
|
565
|
+
|
566
|
+
```ruby
|
567
|
+
StrongMigrations.disable_check(:add_index)
|
568
|
+
```
|
569
|
+
|
570
|
+
Check the [source code](https://github.com/ankane/strong_migrations/blob/master/lib/strong_migrations.rb) for the list of keys.
|
473
571
|
|
474
572
|
## Existing Migrations
|
475
573
|
|
@@ -500,7 +598,7 @@ ActiveRecord::Base.dump_schema_after_migration = Rails.env.development? &&
|
|
500
598
|
|
501
599
|
## Schema Sanity
|
502
600
|
|
503
|
-
Columns can flip order in `db/schema.rb` when you have multiple developers. One way to prevent this is to [alphabetize them](https://www.pgrs.net/2008/03/
|
601
|
+
Columns can flip order in `db/schema.rb` when you have multiple developers. One way to prevent this is to [alphabetize them](https://www.pgrs.net/2008/03/12/alphabetize-schema-rb-columns/). Add to the end of your `Rakefile`:
|
504
602
|
|
505
603
|
```ruby
|
506
604
|
task "db:schema:dump": "strong_migrations:alphabetize_columns"
|
data/lib/strong_migrations.rb
CHANGED
@@ -9,7 +9,7 @@ require "strong_migrations/version"
|
|
9
9
|
|
10
10
|
module StrongMigrations
|
11
11
|
class << self
|
12
|
-
attr_accessor :auto_analyze, :start_after, :checks, :error_messages, :target_postgresql_version
|
12
|
+
attr_accessor :auto_analyze, :start_after, :checks, :error_messages, :target_postgresql_version, :enabled_checks
|
13
13
|
end
|
14
14
|
self.auto_analyze = false
|
15
15
|
self.start_after = 0
|
@@ -41,8 +41,8 @@ class Backfill%{migration_name} < ActiveRecord::Migration%{migration_suffix}
|
|
41
41
|
end%{append}",
|
42
42
|
|
43
43
|
add_column_json:
|
44
|
-
"There's no equality operator for the json column type, which
|
45
|
-
|
44
|
+
"There's no equality operator for the json column type, which can
|
45
|
+
cause errors for existing SELECT DISTINCT queries. Use jsonb instead.",
|
46
46
|
|
47
47
|
change_column:
|
48
48
|
"Changing the type of an existing column requires the entire
|
@@ -91,7 +91,7 @@ end",
|
|
91
91
|
6. Drop the old table",
|
92
92
|
|
93
93
|
add_reference:
|
94
|
-
"Adding
|
94
|
+
"Adding an index non-concurrently locks the table. Instead, use:
|
95
95
|
|
96
96
|
class %{migration_name} < ActiveRecord::Migration%{migration_suffix}
|
97
97
|
disable_ddl_transaction!
|
@@ -102,7 +102,18 @@ class %{migration_name} < ActiveRecord::Migration%{migration_suffix}
|
|
102
102
|
end",
|
103
103
|
|
104
104
|
add_index:
|
105
|
-
"Adding
|
105
|
+
"Adding an index non-concurrently locks the table. Instead, use:
|
106
|
+
|
107
|
+
class %{migration_name} < ActiveRecord::Migration%{migration_suffix}
|
108
|
+
disable_ddl_transaction!
|
109
|
+
|
110
|
+
def change
|
111
|
+
%{command}
|
112
|
+
end
|
113
|
+
end",
|
114
|
+
|
115
|
+
remove_index:
|
116
|
+
"Removing an index non-concurrently locks the table. Instead, use:
|
106
117
|
|
107
118
|
class %{migration_name} < ActiveRecord::Migration%{migration_suffix}
|
108
119
|
disable_ddl_transaction!
|
@@ -144,6 +155,23 @@ class Backfill%{migration_name} < ActiveRecord::Migration%{migration_suffix}
|
|
144
155
|
end
|
145
156
|
end",
|
146
157
|
|
158
|
+
change_column_null_postgresql:
|
159
|
+
"Setting NOT NULL on a column requires an AccessExclusiveLock,
|
160
|
+
which is expensive on large tables. Instead, use a constraint and
|
161
|
+
validate it in a separate migration with a more agreeable RowShareLock.
|
162
|
+
|
163
|
+
class %{migration_name} < ActiveRecord::Migration%{migration_suffix}
|
164
|
+
def change
|
165
|
+
%{add_constraint_code}
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
class Validate%{migration_name} < ActiveRecord::Migration%{migration_suffix}
|
170
|
+
def change
|
171
|
+
%{validate_constraint_code}
|
172
|
+
end
|
173
|
+
end",
|
174
|
+
|
147
175
|
add_foreign_key:
|
148
176
|
"New foreign keys are validated by default. This acquires an AccessExclusiveLock,
|
149
177
|
which is expensive on large tables. Instead, validate it in a separate migration
|
@@ -161,10 +189,28 @@ class Validate%{migration_name} < ActiveRecord::Migration%{migration_suffix}
|
|
161
189
|
end
|
162
190
|
end",
|
163
191
|
}
|
192
|
+
self.enabled_checks = (error_messages.keys - [:remove_index]).map { |k| [k, {}] }.to_h
|
164
193
|
|
165
194
|
def self.add_check(&block)
|
166
195
|
checks << block
|
167
196
|
end
|
197
|
+
|
198
|
+
def self.enable_check(check, start_after: nil)
|
199
|
+
enabled_checks[check] = {start_after: start_after}
|
200
|
+
end
|
201
|
+
|
202
|
+
def self.disable_check(check)
|
203
|
+
enabled_checks.delete(check)
|
204
|
+
end
|
205
|
+
|
206
|
+
def self.check_enabled?(check, version: nil)
|
207
|
+
if enabled_checks[check]
|
208
|
+
start_after = enabled_checks[check][:start_after] || StrongMigrations.start_after
|
209
|
+
!version || version > start_after
|
210
|
+
else
|
211
|
+
false
|
212
|
+
end
|
213
|
+
end
|
168
214
|
end
|
169
215
|
|
170
216
|
ActiveSupport.on_load(:active_record) do
|
@@ -59,9 +59,19 @@ module StrongMigrations
|
|
59
59
|
if columns.is_a?(Array) && columns.size > 3 && !options[:unique]
|
60
60
|
raise_error :add_index_columns, header: "Best practice"
|
61
61
|
end
|
62
|
-
if postgresql? && options[:algorithm] != :concurrently &&
|
62
|
+
if postgresql? && options[:algorithm] != :concurrently && !new_table?(table)
|
63
63
|
raise_error :add_index, command: command_str("add_index", [table, columns, options.merge(algorithm: :concurrently)])
|
64
64
|
end
|
65
|
+
when :remove_index
|
66
|
+
table, options = args
|
67
|
+
unless options.is_a?(Hash)
|
68
|
+
options = {column: options}
|
69
|
+
end
|
70
|
+
options ||= {}
|
71
|
+
|
72
|
+
if postgresql? && options[:algorithm] != :concurrently && !new_table?(table)
|
73
|
+
raise_error :remove_index, command: command_str("remove_index", [table, options.merge(algorithm: :concurrently)])
|
74
|
+
end
|
65
75
|
when :add_column
|
66
76
|
table, column, type, options = args
|
67
77
|
options ||= {}
|
@@ -73,13 +83,7 @@ module StrongMigrations
|
|
73
83
|
options = options.except(:null)
|
74
84
|
append = "
|
75
85
|
|
76
|
-
Then add the NOT NULL constraint.
|
77
|
-
|
78
|
-
class %{migration_name}NotNull < ActiveRecord::Migration%{migration_suffix}
|
79
|
-
def change
|
80
|
-
#{command_str("change_column_null", [table, column, false])}
|
81
|
-
end
|
82
|
-
end"
|
86
|
+
Then add the NOT NULL constraint."
|
83
87
|
end
|
84
88
|
|
85
89
|
raise_error :add_column_default,
|
@@ -133,9 +137,18 @@ end"
|
|
133
137
|
raise_error :execute, header: "Possibly dangerous operation"
|
134
138
|
when :change_column_null
|
135
139
|
table, column, null, default = args
|
136
|
-
if !null
|
137
|
-
|
138
|
-
|
140
|
+
if !null
|
141
|
+
if postgresql?
|
142
|
+
# match https://github.com/nullobject/rein
|
143
|
+
constraint_name = "#{table}_#{column}_null"
|
144
|
+
|
145
|
+
raise_error :change_column_null_postgresql,
|
146
|
+
add_constraint_code: constraint_str("ALTER TABLE %s ADD CONSTRAINT %s CHECK (%s IS NOT NULL) NOT VALID", [table, constraint_name, column]),
|
147
|
+
validate_constraint_code: constraint_str("ALTER TABLE %s VALIDATE CONSTRAINT %s", [table, constraint_name])
|
148
|
+
elsif !default.nil?
|
149
|
+
raise_error :change_column_null,
|
150
|
+
code: backfill_code(table, column, default)
|
151
|
+
end
|
139
152
|
end
|
140
153
|
when :add_foreign_key
|
141
154
|
from_table, to_table, options = args
|
@@ -159,8 +172,8 @@ end"
|
|
159
172
|
fk_name = options[:name] || "fk_rails_#{hashed_identifier}"
|
160
173
|
|
161
174
|
raise_error :add_foreign_key,
|
162
|
-
add_foreign_key_code:
|
163
|
-
validate_foreign_key_code:
|
175
|
+
add_foreign_key_code: constraint_str("ALTER TABLE %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s) NOT VALID", [from_table, fk_name, column, to_table, primary_key]),
|
176
|
+
validate_foreign_key_code: constraint_str("ALTER TABLE %s VALIDATE CONSTRAINT %s", [from_table, fk_name])
|
164
177
|
end
|
165
178
|
end
|
166
179
|
end
|
@@ -214,6 +227,8 @@ end"
|
|
214
227
|
end
|
215
228
|
|
216
229
|
def raise_error(message_key, header: nil, **vars)
|
230
|
+
return unless StrongMigrations.check_enabled?(message_key, version: version)
|
231
|
+
|
217
232
|
message = StrongMigrations.error_messages[message_key] || "Missing message"
|
218
233
|
|
219
234
|
vars[:migration_name] = self.class.name
|
@@ -229,7 +244,7 @@ end"
|
|
229
244
|
@migration.stop!(message.gsub(/%(?!{)/, "%%") % vars, header: header || "Dangerous operation detected")
|
230
245
|
end
|
231
246
|
|
232
|
-
def
|
247
|
+
def constraint_str(statement, identifiers)
|
233
248
|
# not all identifiers are tables, but this method of quoting should be fine
|
234
249
|
code = statement % identifiers.map { |v| connection.quote_table_name(v) }
|
235
250
|
"safety_assured do\n execute '#{code}' \n end"
|
@@ -262,5 +277,9 @@ end"
|
|
262
277
|
model = table.to_s.classify
|
263
278
|
"#{model}.unscoped.in_batches do |relation| \n relation.update_all #{column}: #{default.inspect}\n sleep(0.1)\n end"
|
264
279
|
end
|
280
|
+
|
281
|
+
def new_table?(table)
|
282
|
+
@new_tables.include?(table.to_s)
|
283
|
+
end
|
265
284
|
end
|
266
285
|
end
|
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.
|
4
|
+
version: 0.5.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: 2019-
|
13
|
+
date: 2019-12-05 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|