strong_migrations 1.3.1 → 1.4.0

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 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