strong_migrations 1.2.0 → 1.3.1
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 +8 -0
- data/README.md +2 -2
- data/lib/strong_migrations/adapters/postgresql_adapter.rb +9 -6
- data/lib/strong_migrations/checks.rb +32 -9
- 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: b330db9323d9942a9e24a5fdc3ab75931030f859505cb9eef2f428df840b4dcc
|
4
|
+
data.tar.gz: 8aa1acd2debbc49206cf9b3928c16e85d4f2f47140142d4e9b981d1d54254e12
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2bce01385b02f0c005cae82cda4325f5332b400949cc0c5814a25c4bc30f78ff0a66730179dc52458bae242aa5cc4d1eb6be755696c731521580b3554f3eee6c
|
7
|
+
data.tar.gz: 72bcd4096a69bd3c8afd78caa43651b10bf5924318635adeb52308724751fa9fdbaeaa59e07a690a4a0915524afbab3487a8f1db17086c18e0b742c0d3de6b28
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## 1.3.1 (2022-09-21)
|
2
|
+
|
3
|
+
- Fixed check for `add_column` with `default: nil` with Postgres 10
|
4
|
+
|
5
|
+
## 1.3.0 (2022-08-30)
|
6
|
+
|
7
|
+
- Added check for `add_column` with `uuid` type and volatile default value
|
8
|
+
|
1
9
|
## 1.2.0 (2022-06-10)
|
2
10
|
|
3
11
|
- 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 = "
|
@@ -44,9 +48,10 @@ Then add the NOT NULL constraint in separate migrations."
|
|
44
48
|
add_command: command_str("add_column", [table, column, type, options.except(:default)]),
|
45
49
|
change_command: command_str("change_column_default", [table, column, default]),
|
46
50
|
remove_command: command_str("remove_column", [table, column]),
|
47
|
-
code: backfill_code(table, column, default),
|
51
|
+
code: backfill_code(table, column, default, volatile),
|
48
52
|
append: append,
|
49
|
-
rewrite_blocks: adapter.rewrite_blocks
|
53
|
+
rewrite_blocks: adapter.rewrite_blocks,
|
54
|
+
default_type: (volatile ? "volatile" : "non-null")
|
50
55
|
elsif default.is_a?(Proc) && postgresql?
|
51
56
|
# adding a column with a VOLATILE default is not safe
|
52
57
|
# https://www.postgresql.org/docs/current/sql-altertable.html#SQL-ALTERTABLE-NOTES
|
@@ -219,16 +224,22 @@ Then add the foreign key in separate migrations."
|
|
219
224
|
|
220
225
|
add_constraint_code =
|
221
226
|
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}])
|
227
|
+
command_str(:add_check_constraint, [table, "#{quote_column_if_needed(column)} IS NOT NULL", {name: constraint_name, validate: false}])
|
225
228
|
else
|
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,21 @@ 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
|
+
update_expr = "#{quote_column_if_needed(column)} = #{default}"
|
428
|
+
"#{model}.unscoped.in_batches do |relation| \n relation.where(#{column}: nil).update_all(#{update_expr.inspect})\n sleep(0.01)\n end"
|
429
|
+
else
|
430
|
+
"#{model}.unscoped.in_batches do |relation| \n relation.update_all #{column}: #{default.inspect}\n sleep(0.01)\n end"
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
# only quote when needed
|
435
|
+
# important! only use for display purposes
|
436
|
+
def quote_column_if_needed(column)
|
437
|
+
column.to_s =~ /\A[a-z0-9_]+\z/ ? column : connection.quote_column_name(column)
|
415
438
|
end
|
416
439
|
|
417
440
|
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.1
|
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-09-21 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|