safe-pg-migrations 2.2.0 → 2.3.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: 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