strong_migrations 1.3.2 → 1.4.1

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: 227ddfd8f939d855d93232f5d30d02a0c219f46c6393d98e2be5d8756c445e33
4
- data.tar.gz: bde562f14e23d1fc7a1209e075efffad03454594b842bcde3c7b1ec6fa3046b4
3
+ metadata.gz: a296161cd1d5cdd070c94c34bd250feb2d62cb7b5274205007bab92e50dc7d0a
4
+ data.tar.gz: e95730e625ed31bb3745c0c55fddf4aa2cd6d7d99607add097d23ae1181a8b50
5
5
  SHA512:
6
- metadata.gz: 972103d956c2a8cdff88e478401f18459eabe93d7260107b5c19908cc76bef9451b19e99852511d8a8675639b076107d79d26a6046308d4627afc88f580afc76
7
- data.tar.gz: 3bf1e422cf0d5cd4297bf63a6121570e5afa9acddccf42c4fa7a21eac40fa0cc6d5fca04e2227a45132d7efde0b7f702bb90f3be916097079f9b569cdd04ba50
6
+ metadata.gz: '03479a3996622262cad8eab0843f6fdd266e041d854ab49ced8dd334e6c9709556f6887f7708d1eeab87f98524bb558e813457f5f0cbb4c16323557353438680'
7
+ data.tar.gz: 263a6238d3cc34d1211f7f6c6410248f8ee104e475f04f5e3687efb8602389ab26b12ec9155a6e782fc828e733af85b9315e9a282b5589d39f5891b46a5a83e6
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ ## 1.4.1 (2023-01-05)
2
+
3
+ - Added support for multiple databases to `target_version`
4
+
5
+ ## 1.4.0 (2022-10-31)
6
+
7
+ - Added check for `add_exclusion_constraint`
8
+ - Added support for `RACK_ENV`
9
+ - Fixed error when `Rails` defined without `Rails.env`
10
+ - Fixed error with `change_column_null` when table does not exist
11
+
1
12
  ## 1.3.2 (2022-10-09)
2
13
 
3
14
  - Improved error message 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
@@ -805,6 +824,12 @@ The major version works well for Postgres, while the full version is recommended
805
824
 
806
825
  For safety, this option only affects development and test environments. In other environments, the actual server version is always used.
807
826
 
827
+ If your app has multiple databases with different versions, with Rails 6.1+, you can use:
828
+
829
+ ```ruby
830
+ StrongMigrations.target_version = {primary: 13, catalog: 15}
831
+ ```
832
+
808
833
  ## Analyze Tables
809
834
 
810
835
  Analyze tables automatically (to update planner statistics) after an index is added. Create an initializer with:
@@ -50,7 +50,23 @@ module StrongMigrations
50
50
  target_version ||= StrongMigrations.target_version
51
51
  version =
52
52
  if target_version && StrongMigrations.developer_env?
53
- target_version.to_s
53
+ if target_version.is_a?(Hash)
54
+ # Active Record 6.0 supports multiple databases
55
+ # but connection.pool.spec.name always returns "primary"
56
+ # in migrations with rails db:migrate
57
+ if ActiveRecord::VERSION::STRING.to_f < 6.1
58
+ # error class is not shown in db:migrate output so ensure message is descriptive
59
+ raise StrongMigrations::Error, "StrongMigrations.target_version does not support multiple databases for Active Record < 6.1"
60
+ end
61
+
62
+ db_config_name = connection.pool.db_config.name
63
+ target_version.stringify_keys.fetch(db_config_name) do
64
+ # error class is not shown in db:migrate output so ensure message is descriptive
65
+ raise StrongMigrations::Error, "StrongMigrations.target_version is not configured for :#{db_config_name} database"
66
+ end.to_s
67
+ else
68
+ target_version.to_s
69
+ end
54
70
  else
55
71
  yield
56
72
  end
@@ -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
@@ -73,6 +73,14 @@ Then add the NOT NULL constraint in separate migrations."
73
73
  end
74
74
  end
75
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
+
76
84
  # unlike add_index, we don't make an exception here for new tables
77
85
  #
78
86
  # with add_index, it's fine to lock a new table even after inserting data
@@ -170,7 +178,8 @@ Then add the foreign key in separate migrations."
170
178
  table, column, type = args
171
179
 
172
180
  safe = false
173
- 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 }
174
183
  if existing_column
175
184
  existing_type = existing_column.sql_type.sub(/\(\d+(,\d+)?\)/, "")
176
185
  safe = adapter.change_type_safe?(table, column, type, options, existing_column, existing_type)
@@ -231,7 +231,10 @@ end",
231
231
 
232
232
  validate_check_constraint:
233
233
  "Validating a check constraint while writes are blocked is dangerous.
234
- 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."
235
238
  }
236
239
  self.enabled_checks = (error_messages.keys - [:remove_index]).map { |k| [k, {}] }.to_h
237
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.2"
2
+ VERSION = "1.4.1"
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.2
4
+ version: 1.4.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-10-10 00:00:00.000000000 Z
13
+ date: 2023-01-05 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -75,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
75
75
  - !ruby/object:Gem::Version
76
76
  version: '0'
77
77
  requirements: []
78
- rubygems_version: 3.3.7
78
+ rubygems_version: 3.4.1
79
79
  signing_key:
80
80
  specification_version: 4
81
81
  summary: Catch unsafe migrations in development