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 +4 -4
- data/README.md +1 -8
- data/lib/safe-pg-migrations/base.rb +2 -0
- data/lib/safe-pg-migrations/helpers/statements_helper.rb +19 -0
- data/lib/safe-pg-migrations/plugins/blocking_activity_logger.rb +2 -9
- data/lib/safe-pg-migrations/plugins/statement_insurer/change_column_null.rb +46 -0
- data/lib/safe-pg-migrations/plugins/statement_insurer.rb +1 -12
- data/lib/safe-pg-migrations/plugins/statement_retrier.rb +1 -3
- data/lib/safe-pg-migrations/railtie.rb +1 -27
- data/lib/safe-pg-migrations/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2a0df9e7452f957e5b9d5bde43186d621c8b8b4dab8f0131e100c295f03876bf
|
4
|
+
data.tar.gz: 461407396bd567c37f8f361dcc45386691aa502828913b0954cc8e3cbe305fff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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.
|
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-
|
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
|