strong_migrations 1.3.1 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b330db9323d9942a9e24a5fdc3ab75931030f859505cb9eef2f428df840b4dcc
4
- data.tar.gz: 8aa1acd2debbc49206cf9b3928c16e85d4f2f47140142d4e9b981d1d54254e12
3
+ metadata.gz: 8cbc9cb28c4558aec3f349f8b394db58e0f1a52f5f554259c9ded55d13e70fa4
4
+ data.tar.gz: b739a47825673f01c2e7c328ff0e25dbe3e326d09d2af3ae611154861df1a645
5
5
  SHA512:
6
- metadata.gz: 2bce01385b02f0c005cae82cda4325f5332b400949cc0c5814a25c4bc30f78ff0a66730179dc52458bae242aa5cc4d1eb6be755696c731521580b3554f3eee6c
7
- data.tar.gz: 72bcd4096a69bd3c8afd78caa43651b10bf5924318635adeb52308724751fa9fdbaeaa59e07a690a4a0915524afbab3487a8f1db17086c18e0b742c0d3de6b28
6
+ metadata.gz: 4e86416fab6ffbbdb2838080acf49171f2327f0734d7960aa24476d91725156b94281b8c3661f7d672ea8f462542a74282231543b232155aad45c0ac11418a80
7
+ data.tar.gz: e1f11e93dd82cf002d20a9eb9568e011889c13b2c2154f9aae10996a6be17a7e4d8d4c88b85e03c07fd7d3e6feeeeccb31882418aef57c6d75401f556e2821b2
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ ## 1.4.0 (2022-10-31)
2
+
3
+ - Added check for `add_exclusion_constraint`
4
+ - Added support for `RACK_ENV`
5
+ - Fixed error when `Rails` defined without `Rails.env`
6
+ - Fixed error with `change_column_null` when table does not exist
7
+
8
+ ## 1.3.2 (2022-10-09)
9
+
10
+ - Improved error message for `add_column` with `default: nil` with Postgres 10
11
+
1
12
  ## 1.3.1 (2022-09-21)
2
13
 
3
14
  - Fixed check for `add_column` with `default: nil` with Postgres 10
data/README.md CHANGED
@@ -74,6 +74,7 @@ Postgres-specific checks:
74
74
  - [adding an index non-concurrently](#adding-an-index-non-concurrently)
75
75
  - [adding a reference](#adding-a-reference)
76
76
  - [adding a foreign key](#adding-a-foreign-key)
77
+ - [adding an exclusion constraint](#adding-an-exclusion-constraint)
77
78
  - [adding a json column](#adding-a-json-column)
78
79
  - [setting NOT NULL on an existing column](#setting-not-null-on-an-existing-column)
79
80
 
@@ -107,7 +108,7 @@ end
107
108
  end
108
109
  ```
109
110
 
110
- 2. Deploy code
111
+ 2. Deploy the code
111
112
  3. Write a migration to remove the column (wrap in `safety_assured` block)
112
113
 
113
114
  ```ruby
@@ -118,7 +119,7 @@ end
118
119
  end
119
120
  ```
120
121
 
121
- 4. Deploy and run migration
122
+ 4. Deploy and run the migration
122
123
  5. Remove the line added in step 1
123
124
 
124
125
  ### Adding a column with a default value
@@ -488,6 +489,24 @@ class ValidateForeignKeyOnUsers < ActiveRecord::Migration[7.0]
488
489
  end
489
490
  ```
490
491
 
492
+ ### Adding an exclusion constraint
493
+
494
+ #### Bad
495
+
496
+ In Postgres, adding an exclusion constraint blocks reads and writes while every row is checked.
497
+
498
+ ```ruby
499
+ class AddExclusionContraint < ActiveRecord::Migration[7.1]
500
+ def change
501
+ add_exclusion_constraint :users, "number WITH =", using: :gist
502
+ end
503
+ end
504
+ ```
505
+
506
+ #### Good
507
+
508
+ [Let us know](https://github.com/ankane/strong_migrations/issues/new) if you have a safe way to do this (exclusion constraints cannot be marked `NOT VALID`).
509
+
491
510
  ### Adding a json column
492
511
 
493
512
  #### Bad
@@ -18,6 +18,9 @@ module StrongMigrations
18
18
  end
19
19
 
20
20
  def set_statement_timeout(timeout)
21
+ # fix deprecation warning with Active Record 7.1
22
+ timeout = timeout.value if timeout.is_a?(ActiveSupport::Duration)
23
+
21
24
  select_all("SET max_statement_time = #{connection.quote(timeout)}")
22
25
  end
23
26
 
@@ -25,6 +25,9 @@ module StrongMigrations
25
25
  end
26
26
 
27
27
  def set_lock_timeout(timeout)
28
+ # fix deprecation warning with Active Record 7.1
29
+ timeout = timeout.value if timeout.is_a?(ActiveSupport::Duration)
30
+
28
31
  select_all("SET lock_wait_timeout = #{connection.quote(timeout)}")
29
32
  end
30
33
 
@@ -36,6 +36,8 @@ module StrongMigrations
36
36
  check_add_check_constraint(*args)
37
37
  when :add_column
38
38
  check_add_column(*args)
39
+ when :add_exclusion_constraint
40
+ check_add_exclusion_constraint(*args)
39
41
  when :add_foreign_key
40
42
  check_add_foreign_key(*args)
41
43
  when :add_index
@@ -44,14 +44,21 @@ module StrongMigrations
44
44
  Then add the NOT NULL constraint in separate migrations."
45
45
  end
46
46
 
47
- raise_error :add_column_default,
48
- add_command: command_str("add_column", [table, column, type, options.except(:default)]),
49
- change_command: command_str("change_column_default", [table, column, default]),
50
- remove_command: command_str("remove_column", [table, column]),
51
- code: backfill_code(table, column, default, volatile),
52
- append: append,
53
- rewrite_blocks: adapter.rewrite_blocks,
54
- default_type: (volatile ? "volatile" : "non-null")
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
55
62
  elsif default.is_a?(Proc) && postgresql?
56
63
  # adding a column with a VOLATILE default is not safe
57
64
  # https://www.postgresql.org/docs/current/sql-altertable.html#SQL-ALTERTABLE-NOTES
@@ -66,6 +73,14 @@ Then add the NOT NULL constraint in separate migrations."
66
73
  end
67
74
  end
68
75
 
76
+ def check_add_exclusion_constraint(*args)
77
+ table = args[0]
78
+
79
+ unless new_table?(table)
80
+ raise_error :add_exclusion_constraint
81
+ end
82
+ end
83
+
69
84
  # unlike add_index, we don't make an exception here for new tables
70
85
  #
71
86
  # with add_index, it's fine to lock a new table even after inserting data
@@ -163,7 +178,8 @@ Then add the foreign key in separate migrations."
163
178
  table, column, type = args
164
179
 
165
180
  safe = false
166
- existing_column = connection.columns(table).find { |c| c.name.to_s == column.to_s }
181
+ table_columns = connection.columns(table) rescue []
182
+ existing_column = table_columns.find { |c| c.name.to_s == column.to_s }
167
183
  if existing_column
168
184
  existing_type = existing_column.sql_type.sub(/\(\d+(,\d+)?\)/, "")
169
185
  safe = adapter.change_type_safe?(table, column, type, options, existing_column, existing_type)
@@ -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,
@@ -221,7 +231,10 @@ end",
221
231
 
222
232
  validate_check_constraint:
223
233
  "Validating a check constraint while writes are blocked is dangerous.
224
- Use disable_ddl_transaction! or a separate migration."
234
+ Use disable_ddl_transaction! or a separate migration.",
235
+
236
+ add_exclusion_constraint:
237
+ "Adding an exclusion constraint blocks reads and writes while every row is checked."
225
238
  }
226
239
  self.enabled_checks = (error_messages.keys - [:remove_index]).map { |k| [k, {}] }.to_h
227
240
  end
@@ -64,7 +64,7 @@ module StrongMigrations
64
64
  @migration.validate_check_constraint(table, **validate_options)
65
65
  end
66
66
  dir.down do
67
- @migration.remove_check_constraint(table, expression, **add_options)
67
+ @migration.remove_check_constraint(table, expression, **add_options.except(:validate))
68
68
  end
69
69
  end
70
70
  end
@@ -1,3 +1,3 @@
1
1
  module StrongMigrations
2
- VERSION = "1.3.1"
2
+ VERSION = "1.4.0"
3
3
  end
@@ -41,7 +41,17 @@ module StrongMigrations
41
41
 
42
42
  # private
43
43
  def self.developer_env?
44
- defined?(Rails) && (Rails.env.development? || Rails.env.test?)
44
+ env == "development" || env == "test"
45
+ end
46
+
47
+ # private
48
+ def self.env
49
+ if defined?(Rails.env)
50
+ Rails.env
51
+ else
52
+ # default to production for safety
53
+ ENV["RACK_ENV"] || "production"
54
+ end
45
55
  end
46
56
 
47
57
  def self.lock_timeout_limit
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.3.1
4
+ version: 1.4.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-09-21 00:00:00.000000000 Z
13
+ date: 2022-10-31 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord