strong_migrations 1.2.0 → 1.3.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 +4 -0
- data/README.md +2 -2
- data/lib/strong_migrations/adapters/postgresql_adapter.rb +9 -6
- data/lib/strong_migrations/checks.rb +22 -6
- data/lib/strong_migrations/error_messages.rb +1 -1
- data/lib/strong_migrations/version.rb +1 -1
- data/lib/tasks/strong_migrations.rake +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: 4da88a3161110bc4e7fd6cc989ea51e0db2e32681c8026db11ac74c763f253b3
|
4
|
+
data.tar.gz: 583cd8b1e9665842ff6017c6d7242dcbfd9583157327b33ec023d5357c4e799f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68356a9f5966f33a2a43f35a5f74ce21943798e4d85eb1c52710808dbac0efab6659d67a22d89aa4360cfc4f87e0dce6312e16f3a71dc0a739e87bb335d42f84
|
7
|
+
data.tar.gz: 67038470a20b75fd3dfb8642fea4775aedb08bff959255a44aa92271e2214300e9140f3d7cce21eae83e81ea314739c06999ce8d46a72f76f75f675e6c8914fb
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -135,7 +135,7 @@ class AddSomeColumnToUsers < ActiveRecord::Migration[7.0]
|
|
135
135
|
end
|
136
136
|
```
|
137
137
|
|
138
|
-
In Postgres 11+, MySQL 8.0.12+, and MariaDB 10.3.2+, this no longer requires a table rewrite and is safe.
|
138
|
+
In Postgres 11+, MySQL 8.0.12+, and MariaDB 10.3.2+, this no longer requires a table rewrite and is safe (except for volatile functions like `gen_random_uuid()`).
|
139
139
|
|
140
140
|
#### Good
|
141
141
|
|
@@ -681,7 +681,7 @@ Disable specific checks with:
|
|
681
681
|
StrongMigrations.disable_check(:add_index)
|
682
682
|
```
|
683
683
|
|
684
|
-
Check the [source code](https://github.com/ankane/strong_migrations/blob/master/lib/strong_migrations.rb) for the list of keys.
|
684
|
+
Check the [source code](https://github.com/ankane/strong_migrations/blob/master/lib/strong_migrations/error_messages.rb) for the list of keys.
|
685
685
|
|
686
686
|
## Down Migrations / Rollbacks
|
687
687
|
|
@@ -14,11 +14,7 @@ module StrongMigrations
|
|
14
14
|
target_version(StrongMigrations.target_postgresql_version) do
|
15
15
|
version = select_all("SHOW server_version_num").first["server_version_num"].to_i
|
16
16
|
# major and minor version
|
17
|
-
|
18
|
-
"#{version / 10000}.#{(version % 10000)}"
|
19
|
-
else
|
20
|
-
"#{version / 10000}.#{(version % 10000) / 100}"
|
21
|
-
end
|
17
|
+
"#{version / 10000}.#{(version % 10000)}"
|
22
18
|
end
|
23
19
|
end
|
24
20
|
end
|
@@ -76,7 +72,7 @@ module StrongMigrations
|
|
76
72
|
# but there doesn't seem to be a way to set/modify it
|
77
73
|
# https://wiki.postgresql.org/wiki/What%27s_new_in_PostgreSQL_9.2#Reduce_ALTER_TABLE_rewrites
|
78
74
|
when "numeric", "decimal"
|
79
|
-
# numeric and decimal are equivalent and can be used
|
75
|
+
# numeric and decimal are equivalent and can be used interchangeably
|
80
76
|
safe = ["numeric", "decimal"].include?(existing_type) &&
|
81
77
|
(
|
82
78
|
(
|
@@ -166,6 +162,13 @@ module StrongMigrations
|
|
166
162
|
!StrongMigrations.developer_env?
|
167
163
|
end
|
168
164
|
|
165
|
+
# default to true if unsure
|
166
|
+
def default_volatile?(default)
|
167
|
+
name = default.to_s.delete_suffix("()")
|
168
|
+
rows = select_all("SELECT provolatile FROM pg_proc WHERE proname = #{connection.quote(name)}").to_a
|
169
|
+
rows.empty? || rows.any? { |r| r["provolatile"] == "v" }
|
170
|
+
end
|
171
|
+
|
169
172
|
private
|
170
173
|
|
171
174
|
def set_timeout(setting, timeout)
|
@@ -32,7 +32,9 @@ module StrongMigrations
|
|
32
32
|
table, column, type = args
|
33
33
|
default = options[:default]
|
34
34
|
|
35
|
-
|
35
|
+
# Active Record has special case for uuid columns that allows function default values
|
36
|
+
# https://github.com/rails/rails/blob/v7.0.3.1/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb#L92-L93
|
37
|
+
if !default.nil? && (!adapter.add_column_default_safe? || (volatile = (postgresql? && type.to_s == "uuid" && default.to_s.include?("()") && adapter.default_volatile?(default))))
|
36
38
|
if options[:null] == false
|
37
39
|
options = options.except(:null)
|
38
40
|
append = "
|
@@ -44,9 +46,10 @@ Then add the NOT NULL constraint in separate migrations."
|
|
44
46
|
add_command: command_str("add_column", [table, column, type, options.except(:default)]),
|
45
47
|
change_command: command_str("change_column_default", [table, column, default]),
|
46
48
|
remove_command: command_str("remove_column", [table, column]),
|
47
|
-
code: backfill_code(table, column, default),
|
49
|
+
code: backfill_code(table, column, default, volatile),
|
48
50
|
append: append,
|
49
|
-
rewrite_blocks: adapter.rewrite_blocks
|
51
|
+
rewrite_blocks: adapter.rewrite_blocks,
|
52
|
+
default_type: (volatile ? "volatile" : "non-null")
|
50
53
|
elsif default.is_a?(Proc) && postgresql?
|
51
54
|
# adding a column with a VOLATILE default is not safe
|
52
55
|
# https://www.postgresql.org/docs/current/sql-altertable.html#SQL-ALTERTABLE-NOTES
|
@@ -226,9 +229,17 @@ Then add the foreign key in separate migrations."
|
|
226
229
|
safety_assured_str(add_code)
|
227
230
|
end
|
228
231
|
|
232
|
+
validate_constraint_code =
|
233
|
+
if safe_with_check_constraint
|
234
|
+
down_code = "#{add_constraint_code}\n #{command_str(:change_column_null, [table, column, true])}"
|
235
|
+
"def up\n #{validate_constraint_code}\n end\n\n def down\n #{down_code}\n end"
|
236
|
+
else
|
237
|
+
"def change\n #{validate_constraint_code}\n end"
|
238
|
+
end
|
239
|
+
|
229
240
|
raise_error :change_column_null_postgresql,
|
230
241
|
add_constraint_code: add_constraint_code,
|
231
|
-
validate_constraint_code:
|
242
|
+
validate_constraint_code: validate_constraint_code
|
232
243
|
end
|
233
244
|
elsif mysql? || mariadb?
|
234
245
|
unless adapter.strict_mode?
|
@@ -409,9 +420,14 @@ Then add the foreign key in separate migrations."
|
|
409
420
|
"#{command} #{str_args.join(", ")}"
|
410
421
|
end
|
411
422
|
|
412
|
-
def backfill_code(table, column, default)
|
423
|
+
def backfill_code(table, column, default, function = false)
|
413
424
|
model = table.to_s.classify
|
414
|
-
|
425
|
+
if function
|
426
|
+
# update_all(column: Arel.sql(default)) also works in newer versions of Active Record
|
427
|
+
"#{model}.unscoped.in_batches do |relation| \n relation.where(#{column}: nil).update_all(\"#{column} = #{default}\")\n sleep(0.01)\n end"
|
428
|
+
else
|
429
|
+
"#{model}.unscoped.in_batches do |relation| \n relation.update_all #{column}: #{default.inspect}\n sleep(0.01)\n end"
|
430
|
+
end
|
415
431
|
end
|
416
432
|
|
417
433
|
def new_table?(table)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module StrongMigrations
|
2
2
|
self.error_messages = {
|
3
3
|
add_column_default:
|
4
|
-
"Adding a column with a
|
4
|
+
"Adding a column with a %{default_type} default blocks %{rewrite_blocks} while the entire table is rewritten.
|
5
5
|
Instead, add the column without a default value, then change the default.
|
6
6
|
|
7
7
|
class %{migration_name} < ActiveRecord::Migration%{migration_suffix}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
namespace :strong_migrations do
|
2
|
-
# https://www.pgrs.net/2008/03/
|
2
|
+
# https://www.pgrs.net/2008/03/12/alphabetize-schema-rb-columns/
|
3
3
|
task :alphabetize_columns do
|
4
4
|
$stderr.puts "Dumping schema"
|
5
5
|
ActiveRecord::Base.logger.level = Logger::INFO
|
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: 1.
|
4
|
+
version: 1.3.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-
|
13
|
+
date: 2022-08-30 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|