safe-pg-migrations 2.2.0 → 2.3.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: 2ca207baa7afe377dff14c412d91032adf75dc6f37adea0b9e05c205f7857277
4
- data.tar.gz: c7cfe9a20a090734c26b874b7b50588455a752b9e1dfb53c050de4749f5834d0
3
+ metadata.gz: 2a0df9e7452f957e5b9d5bde43186d621c8b8b4dab8f0131e100c295f03876bf
4
+ data.tar.gz: 461407396bd567c37f8f361dcc45386691aa502828913b0954cc8e3cbe305fff
5
5
  SHA512:
6
- metadata.gz: 2acdce15510505d5c13278774472acb012f0154b9214a41c78b068fd5812dddb5f9bddb1c2ad24e4feb23d06c19f3f5bfe5ecddc8d38ed6c9745d21257a365fa
7
- data.tar.gz: 492776e5ab2b70fa14b71bec6b9171a481f57b310d6b6ca79ad8a572e4d4ef12c41a9b9dd4e50e2755fee9b686f6ee161b4e2f7581905539528ab06aed4bdabf
6
+ metadata.gz: 28e27ecdfd15480ae55a49357200f9b5e0ed4af1ac943973925ca5ac091c7b61ce50dca8047b6a24fe42a736a1214bfb56a08a7f791e59dfbce14587c10e7585
7
+ data.tar.gz: f70e209ad111bf97d7a0fa8aea884a3191bc5ee028b67d5e445a553549c00e86f01cd948368e7b3f93ee1713724877d9e67272f6e5729cc71b69cddbac62316d
data/README.md CHANGED
@@ -346,18 +346,11 @@ SafePgMigrations.config.retry_delay = 1.minute # Delay between retries for retry
346
346
  SafePgMigrations.config.max_tries = 5 # Number of retries before abortion of the migration
347
347
  ```
348
348
 
349
- ## Running tests
350
-
351
- ```bash
352
- bundle
353
- psql -h localhost -c 'CREATE DATABASE safe_pg_migrations_test'
354
- rake test
355
- ```
356
-
357
349
  ## Authors
358
350
 
359
351
  - [Matthieu Prat](https://github.com/matthieuprat)
360
352
  - [Romain Choquet](https://github.com/rchoquet)
353
+ - [Thomas Hareau](https://github.com/ThHareau)
361
354
  - [Paul-Etienne Coisne](https://github.com/coisnepe)
362
355
 
363
356
  ## License
@@ -6,9 +6,11 @@ require 'safe-pg-migrations/helpers/satisfied_helper'
6
6
  require 'safe-pg-migrations/helpers/index_helper'
7
7
  require 'safe-pg-migrations/helpers/batch_over'
8
8
  require 'safe-pg-migrations/helpers/session_setting_management'
9
+ require 'safe-pg-migrations/helpers/statements_helper'
9
10
  require 'safe-pg-migrations/plugins/verbose_sql_logger'
10
11
  require 'safe-pg-migrations/plugins/blocking_activity_logger'
11
12
  require 'safe-pg-migrations/plugins/statement_insurer/add_column'
13
+ require 'safe-pg-migrations/plugins/statement_insurer/change_column_null'
12
14
  require 'safe-pg-migrations/plugins/statement_insurer'
13
15
  require 'safe-pg-migrations/plugins/statement_retrier'
14
16
  require 'safe-pg-migrations/plugins/idempotent_statements'
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SafePgMigrations
4
+ module Helpers
5
+ module StatementsHelper
6
+ RETRIABLE_SCHEMA_STATEMENTS = %i[
7
+ add_check_constraint
8
+ add_column
9
+ add_foreign_key
10
+ change_column_default
11
+ change_column_null
12
+ create_table
13
+ remove_column
14
+ remove_foreign_key
15
+ drop_table
16
+ ].freeze
17
+ end
18
+ end
19
+ end
@@ -7,16 +7,9 @@ module SafePgMigrations
7
7
  module BlockingActivityLogger
8
8
  include Helpers::BlockingActivityFormatter
9
9
  include Helpers::BlockingActivitySelector
10
+ include Helpers::StatementsHelper
10
11
 
11
- %i[
12
- add_column
13
- remove_column
14
- add_foreign_key
15
- remove_foreign_key
16
- change_column_default
17
- change_column_null
18
- create_table
19
- ].each do |method|
12
+ RETRIABLE_SCHEMA_STATEMENTS.each do |method|
20
13
  define_method method do |*args, &block|
21
14
  log_context = lambda do
22
15
  break unless SafePgMigrations.config.sensitive_logger
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SafePgMigrations
4
+ module StatementInsurer
5
+ module ChangeColumnNull
6
+ def change_column_null(table_name, column_name, null, default = nil)
7
+ return super unless should_create_constraint? default, null
8
+
9
+ expression = "#{column_name} IS NOT NULL"
10
+ # constraint will be defined if the constraint was manually created in another migration
11
+ constraint = check_constraint_by_expression table_name, expression
12
+
13
+ default_name = check_constraint_name(table_name, expression: expression)
14
+ constraint_name = constraint&.name || default_name
15
+
16
+ add_check_constraint table_name, expression, name: constraint_name
17
+
18
+ Helpers::Logger.say_method_call :change_column_null, table_name, column_name, false
19
+ super table_name, column_name, false
20
+
21
+ return unless should_remove_constraint? default_name, constraint_name
22
+
23
+ Helpers::Logger.say_method_call :remove_check_constraint, table_name, expression, name: constraint_name
24
+ remove_check_constraint table_name, expression, name: constraint_name
25
+ end
26
+
27
+ private
28
+
29
+ def check_constraint_by_expression(table_name, expression)
30
+ check_constraints(table_name).detect { |check_constraint| check_constraint.expression = expression }
31
+ end
32
+
33
+ def should_create_constraint?(default, null)
34
+ !default && !null && Helpers::SatisfiedHelper.satisfies_change_column_null_requirements?
35
+ end
36
+
37
+ def should_remove_constraint?(default_name, constraint_name)
38
+ # we don't want to remove the constraint if it was created in another migration. The best guess we have here is
39
+ # that manually created constraint would likely have a name that is not the default name. This is not a perfect,
40
+ # a manually created constraint without a name would be removed. However, it is now replaced by the NOT NULL
41
+ # statement on the table, so this is not a big issue.
42
+ default_name == constraint_name
43
+ end
44
+ end
45
+ end
46
+ end
@@ -4,6 +4,7 @@ module SafePgMigrations
4
4
  module StatementInsurer
5
5
  include Helpers::SessionSettingManagement
6
6
  include AddColumn
7
+ include ChangeColumnNull
7
8
 
8
9
  def validate_check_constraint(table_name, **options)
9
10
  Helpers::Logger.say_method_call :validate_check_constraint, table_name, **options
@@ -73,18 +74,6 @@ module SafePgMigrations
73
74
  without_timeout { super(table_name, **options) }
74
75
  end
75
76
 
76
- def change_column_null(table_name, column_name, null, default = nil)
77
- return super if default || null || !Helpers::SatisfiedHelper.satisfies_change_column_null_requirements?
78
-
79
- add_check_constraint table_name, "#{column_name} IS NOT NULL"
80
-
81
- Helpers::Logger.say_method_call :change_column_null, table_name, column_name, false
82
- super table_name, column_name, false
83
-
84
- Helpers::Logger.say_method_call :remove_check_constraint, table_name, "#{column_name} IS NOT NULL"
85
- remove_check_constraint table_name, "#{column_name} IS NOT NULL"
86
- end
87
-
88
77
  def remove_column(table_name, column_name, *)
89
78
  foreign_key = foreign_key_for(table_name, column: column_name)
90
79
 
@@ -2,9 +2,7 @@
2
2
 
3
3
  module SafePgMigrations
4
4
  module StatementRetrier
5
- RETRIABLE_SCHEMA_STATEMENTS = %i[
6
- add_column add_foreign_key remove_foreign_key change_column_default change_column_null remove_column drop_table
7
- ].freeze
5
+ include Helpers::StatementsHelper
8
6
 
9
7
  RETRIABLE_SCHEMA_STATEMENTS.each do |method|
10
8
  define_method method do |*args, &block|
@@ -10,33 +10,7 @@ module SafePgMigrations
10
10
  ActiveRecord::Migration.singleton_class.prepend(SafePgMigrations::Migration::ClassMethods)
11
11
  end
12
12
 
13
- break unless Object.const_defined? :StrongMigrations
14
-
15
- StrongMigrations.add_check do |method, args|
16
- break unless method == :add_column
17
-
18
- options = args.last.is_a?(Hash) ? args.last : {}
19
-
20
- default_value_backfill = options.fetch(:default_value_backfill, :auto)
21
-
22
- if default_value_backfill == :update_in_batches
23
- check_message = <<~CHECK
24
- default_value_backfill: :update_in_batches will take time if the table is too big.
25
-
26
- Your configuration sets a pause of #{SafePgMigrations.config.backfill_pause} seconds between batches of
27
- #{SafePgMigrations.config.backfill_batch_size} rows. Each batch execution will take time as well. Please
28
- check that the estimated duration of the migration is acceptable before adding `safety_assured`.
29
- CHECK
30
-
31
- check_message += <<~CHECK if SafePgMigrations.config.default_value_backfill_threshold
32
-
33
- Also, please note that SafePgMigrations is configured to raise if the table has more than
34
- #{SafePgMigrations.config.default_value_backfill_threshold} rows.
35
- CHECK
36
-
37
- stop! check_message
38
- end
39
- end
13
+ SafePgMigrations::StrongMigrationsIntegration.initialize
40
14
  end
41
15
  end
42
16
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SafePgMigrations
4
- VERSION = '2.2.0'
4
+ VERSION = '2.3.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: safe-pg-migrations
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthieu Prat
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2023-07-06 00:00:00.000000000 Z
13
+ date: 2023-08-02 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -58,10 +58,12 @@ files:
58
58
  - lib/safe-pg-migrations/helpers/logger.rb
59
59
  - lib/safe-pg-migrations/helpers/satisfied_helper.rb
60
60
  - lib/safe-pg-migrations/helpers/session_setting_management.rb
61
+ - lib/safe-pg-migrations/helpers/statements_helper.rb
61
62
  - lib/safe-pg-migrations/plugins/blocking_activity_logger.rb
62
63
  - lib/safe-pg-migrations/plugins/idempotent_statements.rb
63
64
  - lib/safe-pg-migrations/plugins/statement_insurer.rb
64
65
  - lib/safe-pg-migrations/plugins/statement_insurer/add_column.rb
66
+ - lib/safe-pg-migrations/plugins/statement_insurer/change_column_null.rb
65
67
  - lib/safe-pg-migrations/plugins/statement_retrier.rb
66
68
  - lib/safe-pg-migrations/plugins/strong_migrations_integration.rb
67
69
  - lib/safe-pg-migrations/plugins/useless_statements_logger.rb