strong_migrations 1.2.0 → 1.3.2
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 +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +2 -2
- data/lib/strong_migrations/adapters/postgresql_adapter.rb +9 -6
- data/lib/strong_migrations/checks.rb +44 -14
- data/lib/strong_migrations/error_messages.rb +11 -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: 227ddfd8f939d855d93232f5d30d02a0c219f46c6393d98e2be5d8756c445e33
|
4
|
+
data.tar.gz: bde562f14e23d1fc7a1209e075efffad03454594b842bcde3c7b1ec6fa3046b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 972103d956c2a8cdff88e478401f18459eabe93d7260107b5c19908cc76bef9451b19e99852511d8a8675639b076107d79d26a6046308d4627afc88f580afc76
|
7
|
+
data.tar.gz: 3bf1e422cf0d5cd4297bf63a6121570e5afa9acddccf42c4fa7a21eac40fa0cc6d5fca04e2227a45132d7efde0b7f702bb90f3be916097079f9b569cdd04ba50
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
## 1.3.2 (2022-10-09)
|
2
|
+
|
3
|
+
- Improved error message for `add_column` with `default: nil` with Postgres 10
|
4
|
+
|
5
|
+
## 1.3.1 (2022-09-21)
|
6
|
+
|
7
|
+
- Fixed check for `add_column` with `default: nil` with Postgres 10
|
8
|
+
|
9
|
+
## 1.3.0 (2022-08-30)
|
10
|
+
|
11
|
+
- Added check for `add_column` with `uuid` type and volatile default value
|
12
|
+
|
1
13
|
## 1.2.0 (2022-06-10)
|
2
14
|
|
3
15
|
- Added check for index corruption with Postgres 14.0 to 14.3
|
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,11 @@ module StrongMigrations
|
|
32
32
|
table, column, type = args
|
33
33
|
default = options[:default]
|
34
34
|
|
35
|
-
|
35
|
+
# Check key since DEFAULT NULL behaves differently from no default
|
36
|
+
#
|
37
|
+
# Also, Active Record has special case for uuid columns that allows function default values
|
38
|
+
# https://github.com/rails/rails/blob/v7.0.3.1/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb#L92-L93
|
39
|
+
if options.key?(:default) && (!adapter.add_column_default_safe? || (volatile = (postgresql? && type.to_s == "uuid" && default.to_s.include?("()") && adapter.default_volatile?(default))))
|
36
40
|
if options[:null] == false
|
37
41
|
options = options.except(:null)
|
38
42
|
append = "
|
@@ -40,13 +44,21 @@ module StrongMigrations
|
|
40
44
|
Then add the NOT NULL constraint in separate migrations."
|
41
45
|
end
|
42
46
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
if default.nil?
|
48
|
+
raise_error :add_column_default_null,
|
49
|
+
command: command_str("add_column", [table, column, type, options.except(:default)]),
|
50
|
+
append: append,
|
51
|
+
rewrite_blocks: adapter.rewrite_blocks
|
52
|
+
else
|
53
|
+
raise_error :add_column_default,
|
54
|
+
add_command: command_str("add_column", [table, column, type, options.except(:default)]),
|
55
|
+
change_command: command_str("change_column_default", [table, column, default]),
|
56
|
+
remove_command: command_str("remove_column", [table, column]),
|
57
|
+
code: backfill_code(table, column, default, volatile),
|
58
|
+
append: append,
|
59
|
+
rewrite_blocks: adapter.rewrite_blocks,
|
60
|
+
default_type: (volatile ? "volatile" : "non-null")
|
61
|
+
end
|
50
62
|
elsif default.is_a?(Proc) && postgresql?
|
51
63
|
# adding a column with a VOLATILE default is not safe
|
52
64
|
# https://www.postgresql.org/docs/current/sql-altertable.html#SQL-ALTERTABLE-NOTES
|
@@ -219,16 +231,22 @@ Then add the foreign key in separate migrations."
|
|
219
231
|
|
220
232
|
add_constraint_code =
|
221
233
|
if constraint_methods
|
222
|
-
#
|
223
|
-
expr_column = column.to_s =~ /\A[a-z0-9_]+\z/ ? column : connection.quote_column_name(column)
|
224
|
-
command_str(:add_check_constraint, [table, "#{expr_column} IS NOT NULL", {name: constraint_name, validate: false}])
|
234
|
+
command_str(:add_check_constraint, [table, "#{quote_column_if_needed(column)} IS NOT NULL", {name: constraint_name, validate: false}])
|
225
235
|
else
|
226
236
|
safety_assured_str(add_code)
|
227
237
|
end
|
228
238
|
|
239
|
+
validate_constraint_code =
|
240
|
+
if safe_with_check_constraint
|
241
|
+
down_code = "#{add_constraint_code}\n #{command_str(:change_column_null, [table, column, true])}"
|
242
|
+
"def up\n #{validate_constraint_code}\n end\n\n def down\n #{down_code}\n end"
|
243
|
+
else
|
244
|
+
"def change\n #{validate_constraint_code}\n end"
|
245
|
+
end
|
246
|
+
|
229
247
|
raise_error :change_column_null_postgresql,
|
230
248
|
add_constraint_code: add_constraint_code,
|
231
|
-
validate_constraint_code:
|
249
|
+
validate_constraint_code: validate_constraint_code
|
232
250
|
end
|
233
251
|
elsif mysql? || mariadb?
|
234
252
|
unless adapter.strict_mode?
|
@@ -409,9 +427,21 @@ Then add the foreign key in separate migrations."
|
|
409
427
|
"#{command} #{str_args.join(", ")}"
|
410
428
|
end
|
411
429
|
|
412
|
-
def backfill_code(table, column, default)
|
430
|
+
def backfill_code(table, column, default, function = false)
|
413
431
|
model = table.to_s.classify
|
414
|
-
|
432
|
+
if function
|
433
|
+
# update_all(column: Arel.sql(default)) also works in newer versions of Active Record
|
434
|
+
update_expr = "#{quote_column_if_needed(column)} = #{default}"
|
435
|
+
"#{model}.unscoped.in_batches do |relation| \n relation.where(#{column}: nil).update_all(#{update_expr.inspect})\n sleep(0.01)\n end"
|
436
|
+
else
|
437
|
+
"#{model}.unscoped.in_batches do |relation| \n relation.update_all #{column}: #{default.inspect}\n sleep(0.01)\n end"
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
# only quote when needed
|
442
|
+
# important! only use for display purposes
|
443
|
+
def quote_column_if_needed(column)
|
444
|
+
column.to_s =~ /\A[a-z0-9_]+\z/ ? column : connection.quote_column_name(column)
|
415
445
|
end
|
416
446
|
|
417
447
|
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}
|
@@ -25,6 +25,16 @@ class Backfill%{migration_name} < ActiveRecord::Migration%{migration_suffix}
|
|
25
25
|
end
|
26
26
|
end",
|
27
27
|
|
28
|
+
add_column_default_null:
|
29
|
+
"Adding a column with a null default blocks %{rewrite_blocks} while the entire table is rewritten.
|
30
|
+
Instead, add the column without a default value.
|
31
|
+
|
32
|
+
class %{migration_name} < ActiveRecord::Migration%{migration_suffix}
|
33
|
+
def change
|
34
|
+
%{command}
|
35
|
+
end
|
36
|
+
end",
|
37
|
+
|
28
38
|
add_column_default_callable:
|
29
39
|
"Strong Migrations does not support inspecting callable default values.
|
30
40
|
Please make really sure you're not calling a VOLATILE function,
|
@@ -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.2
|
4
|
+
version: 1.3.2
|
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-10-10 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|