safe-pg-migrations 2.3.1 → 3.0.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 +2 -2
- data/lib/safe-pg-migrations/plugins/blocking_activity_logger.rb +2 -5
- data/lib/safe-pg-migrations/plugins/idempotent_statements.rb +23 -21
- data/lib/safe-pg-migrations/plugins/statement_insurer/add_column.rb +3 -4
- data/lib/safe-pg-migrations/plugins/statement_insurer.rb +10 -14
- data/lib/safe-pg-migrations/plugins/statement_retrier.rb +2 -3
- data/lib/safe-pg-migrations/plugins/strong_migrations_integration.rb +7 -10
- data/lib/safe-pg-migrations/plugins/useless_statements_logger.rb +5 -9
- data/lib/safe-pg-migrations/version.rb +1 -1
- metadata +8 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2e58bfc8a79c0b54a368c49a1fc720e33582220b472c81c3556158aa4d3e8f05
|
4
|
+
data.tar.gz: a112e1ade2a57568cdebee942d0a4f4f5eef1fcfb19db576d30c25eacf7fc04d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b28dcf7b252ebe311258b1c3ba4badfa0f365d40b53209e66b51c459a8fd960c3ceb452a378d0feb5785ec8f7632f575d53b9ec543e1de016729066d5e9ed42
|
7
|
+
data.tar.gz: 3338baf96b5d82f6055f6b59691fb42f0560e1d18c4a372685e9bc9ae40f55b58b1382bc8347e13b0d8628b754abae85f4d6c9d57437888efa334f9f82029e7b
|
data/README.md
CHANGED
@@ -10,22 +10,19 @@ module SafePgMigrations
|
|
10
10
|
include Helpers::StatementsHelper
|
11
11
|
|
12
12
|
RETRIABLE_SCHEMA_STATEMENTS.each do |method|
|
13
|
-
define_method method do |*args, &block|
|
13
|
+
define_method method do |*args, **options, &block|
|
14
14
|
log_context = lambda do
|
15
15
|
break unless SafePgMigrations.config.sensitive_logger
|
16
16
|
|
17
|
-
options = args.last.is_a?(Hash) ? args.last : {}
|
18
|
-
|
19
17
|
Helpers::Logger.say "Executing #{SafePgMigrations.current_migration.name}",
|
20
18
|
sensitive: true, warn_sensitive_logs: false
|
21
19
|
Helpers::Logger.say_method_call method, *args, **options, sensitive: true, warn_sensitive_logs: false
|
22
20
|
end
|
23
21
|
|
24
22
|
log_blocking_queries_after_lock(log_context) do
|
25
|
-
super(*args, &block)
|
23
|
+
super(*args, **options, &block)
|
26
24
|
end
|
27
25
|
end
|
28
|
-
ruby2_keywords method
|
29
26
|
end
|
30
27
|
|
31
28
|
%i[add_index remove_index].each do |method|
|
@@ -4,8 +4,7 @@ module SafePgMigrations
|
|
4
4
|
module IdempotentStatements
|
5
5
|
include Helpers::IndexHelper
|
6
6
|
|
7
|
-
|
8
|
-
options = args.last.is_a?(Hash) ? args.last : {}
|
7
|
+
def add_index(table_name, column_name, **options)
|
9
8
|
index_definition = index_definition(table_name, column_name, **options)
|
10
9
|
|
11
10
|
return super unless index_name_exists?(index_definition.table, index_definition.name)
|
@@ -15,42 +14,44 @@ module SafePgMigrations
|
|
15
14
|
return
|
16
15
|
end
|
17
16
|
|
18
|
-
remove_index(table_name,
|
17
|
+
remove_index(table_name, column_name, **options)
|
19
18
|
super
|
20
19
|
end
|
21
20
|
|
22
|
-
|
21
|
+
def add_column(table_name, column_name, type, **options)
|
23
22
|
if column_exists?(table_name, column_name) && !column_exists?(table_name, column_name, type)
|
24
23
|
error_message = "/!\\ Column '#{column_name}' already exists in '#{table_name}' with a different type"
|
25
24
|
raise error_message
|
26
25
|
end
|
27
26
|
|
28
|
-
|
27
|
+
options_without_default_value_backfill = options.except(:default_value_backfill)
|
29
28
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
29
|
+
if column_exists?(table_name, column_name, type)
|
30
|
+
log_message(<<~MESSAGE.squish
|
31
|
+
/!\\ Column '#{column_name}' already exists in '#{table_name}' with the same type (#{type}).
|
32
|
+
Skipping statement.
|
33
|
+
MESSAGE
|
34
|
+
)
|
35
|
+
else
|
36
|
+
super(table_name, column_name, type, **options_without_default_value_backfill)
|
37
|
+
end
|
35
38
|
end
|
36
39
|
|
37
|
-
|
40
|
+
def remove_column(table_name, column_name, type = nil, **options)
|
38
41
|
return super if column_exists?(table_name, column_name)
|
39
42
|
|
40
43
|
log_message("/!\\ Column '#{column_name}' not found on table '#{table_name}'. Skipping statement.")
|
41
44
|
end
|
42
45
|
|
43
|
-
|
44
|
-
|
45
|
-
index_name = options.key?(:name) ? options[:name].to_s : index_name(table_name, options)
|
46
|
+
def remove_index(table_name, column_name = nil, **options)
|
47
|
+
index_name = options.key?(:name) ? options[:name].to_s : index_name(table_name, column: column_name)
|
46
48
|
|
47
49
|
return super if index_name_exists?(table_name, index_name)
|
48
50
|
|
49
51
|
log_message("/!\\ Index '#{index_name}' not found on table '#{table_name}'. Skipping statement.")
|
50
52
|
end
|
51
53
|
|
52
|
-
|
53
|
-
options = args.last.is_a?(Hash) ? args.last : {}
|
54
|
+
def add_foreign_key(from_table, to_table, **options)
|
54
55
|
sub_options = options.slice(:name, :column)
|
55
56
|
return super unless foreign_key_exists?(from_table, sub_options.present? ? nil : to_table, **sub_options)
|
56
57
|
|
@@ -64,13 +65,12 @@ module SafePgMigrations
|
|
64
65
|
log_message("/!\\ Foreign key '#{from_table}' -> '#{reference_name}' does not exist. Skipping statement.")
|
65
66
|
end
|
66
67
|
|
67
|
-
|
68
|
-
options = args.last.is_a?(Hash) ? args.last : {}
|
68
|
+
def create_table(table_name, **options)
|
69
69
|
return super if options[:force] || !table_exists?(table_name)
|
70
70
|
|
71
71
|
Helpers::Logger.say "/!\\ Table '#{table_name}' already exists.", sub_item: true
|
72
72
|
|
73
|
-
td = create_table_definition(table_name,
|
73
|
+
td = create_table_definition(table_name, **options)
|
74
74
|
|
75
75
|
yield td if block_given?
|
76
76
|
|
@@ -82,8 +82,10 @@ module SafePgMigrations
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def add_check_constraint(table_name, expression, **options)
|
85
|
+
options_without_validate = options.except(:validate)
|
85
86
|
constraint_definition = check_constraint_for table_name,
|
86
|
-
**check_constraint_options(table_name, expression,
|
87
|
+
**check_constraint_options(table_name, expression,
|
88
|
+
options_without_validate)
|
87
89
|
|
88
90
|
return super if constraint_definition.nil?
|
89
91
|
|
@@ -123,7 +125,7 @@ module SafePgMigrations
|
|
123
125
|
)
|
124
126
|
end
|
125
127
|
|
126
|
-
|
128
|
+
def drop_table(table_name, **options)
|
127
129
|
return super if table_exists?(table_name)
|
128
130
|
|
129
131
|
log_message("/!\\ Table '#{table_name} does not exist. Skipping statement.")
|
@@ -3,12 +3,11 @@
|
|
3
3
|
module SafePgMigrations
|
4
4
|
module StatementInsurer
|
5
5
|
module AddColumn
|
6
|
-
|
7
|
-
options = args.last.is_a?(Hash) && args.last
|
8
|
-
options ||= {}
|
9
|
-
|
6
|
+
def add_column(table_name, column_name, type, **options)
|
10
7
|
return super if should_keep_default_implementation?(**options)
|
11
8
|
|
9
|
+
options.delete(:default_value_backfill)
|
10
|
+
|
12
11
|
raise <<~ERROR unless backfill_column_default_safe?(table_name)
|
13
12
|
Table #{table_name} has more than #{SafePgMigrations.config.default_value_backfill_threshold} rows.
|
14
13
|
Backfilling the default value for column #{column_name} on table #{table_name} would take too long.
|
@@ -30,8 +30,7 @@ module SafePgMigrations
|
|
30
30
|
without_statement_timeout { super }
|
31
31
|
end
|
32
32
|
|
33
|
-
|
34
|
-
options = args.last.is_a?(Hash) ? args.last : {}
|
33
|
+
def add_foreign_key(from_table, to_table, **options)
|
35
34
|
validate_present = options.key?(:validate)
|
36
35
|
options[:validate] = false unless validate_present
|
37
36
|
|
@@ -43,7 +42,7 @@ module SafePgMigrations
|
|
43
42
|
validate_foreign_key from_table, sub_options.present? ? nil : to_table, **sub_options
|
44
43
|
end
|
45
44
|
|
46
|
-
|
45
|
+
def create_table(*)
|
47
46
|
super do |td|
|
48
47
|
yield td if block_given?
|
49
48
|
td.indexes.map! do |key, index_options|
|
@@ -53,9 +52,7 @@ module SafePgMigrations
|
|
53
52
|
end
|
54
53
|
end
|
55
54
|
|
56
|
-
|
57
|
-
options = args_options.last.is_a?(Hash) ? args_options.last : {}
|
58
|
-
|
55
|
+
def add_index(table_name, column_name, **options)
|
59
56
|
if options[:algorithm] == :default
|
60
57
|
options.delete :algorithm
|
61
58
|
else
|
@@ -66,29 +63,28 @@ module SafePgMigrations
|
|
66
63
|
without_timeout { super(table_name, column_name, **options) }
|
67
64
|
end
|
68
65
|
|
69
|
-
|
70
|
-
options = args.last.is_a?(Hash) ? args.last : { column: args.last }
|
66
|
+
def remove_index(table_name, column_name = nil, **options)
|
71
67
|
options[:algorithm] = :concurrently unless options.key?(:algorithm)
|
72
68
|
|
73
|
-
Helpers::Logger.say_method_call(:remove_index, table_name, **options)
|
74
|
-
without_timeout { super(table_name, **options) }
|
69
|
+
Helpers::Logger.say_method_call(:remove_index, table_name, column_name, **options)
|
70
|
+
without_timeout { super(table_name, column_name, **options) }
|
75
71
|
end
|
76
72
|
|
77
|
-
def remove_column(table_name, column_name,
|
73
|
+
def remove_column(table_name, column_name, type = nil, **options)
|
78
74
|
foreign_key = foreign_key_for(table_name, column: column_name)
|
79
75
|
|
80
76
|
remove_foreign_key(table_name, name: foreign_key.name) if foreign_key
|
81
77
|
super
|
82
78
|
end
|
83
79
|
|
84
|
-
|
80
|
+
def drop_table(table_name, **options)
|
85
81
|
foreign_keys(table_name).each do |foreign_key|
|
86
82
|
remove_foreign_key(table_name, name: foreign_key.name)
|
87
83
|
end
|
88
84
|
|
89
|
-
Helpers::Logger.say_method_call :drop_table, table_name,
|
85
|
+
Helpers::Logger.say_method_call :drop_table, table_name, **options
|
90
86
|
|
91
|
-
super
|
87
|
+
super
|
92
88
|
end
|
93
89
|
end
|
94
90
|
end
|
@@ -5,10 +5,9 @@ module SafePgMigrations
|
|
5
5
|
include Helpers::StatementsHelper
|
6
6
|
|
7
7
|
RETRIABLE_SCHEMA_STATEMENTS.each do |method|
|
8
|
-
define_method method do |*args, &block|
|
9
|
-
retry_if_lock_timeout { super(*args, &block) }
|
8
|
+
define_method method do |*args, **options, &block|
|
9
|
+
retry_if_lock_timeout { super(*args, **options, &block) }
|
10
10
|
end
|
11
|
-
ruby2_keywords method
|
12
11
|
end
|
13
12
|
|
14
13
|
private
|
@@ -54,22 +54,19 @@ module SafePgMigrations
|
|
54
54
|
].freeze
|
55
55
|
|
56
56
|
SAFE_METHODS.each do |method|
|
57
|
-
define_method method do |*args|
|
58
|
-
return super(*args) unless respond_to?(:safety_assured)
|
57
|
+
define_method method do |*args, **options|
|
58
|
+
return super(*args, **options) unless respond_to?(:safety_assured)
|
59
59
|
|
60
|
-
safety_assured { super(*args) }
|
60
|
+
safety_assured { super(*args, **options) }
|
61
61
|
end
|
62
|
-
ruby2_keywords method
|
63
62
|
end
|
64
63
|
|
65
|
-
|
66
|
-
return super
|
64
|
+
def add_column(table_name, *args, **options)
|
65
|
+
return super unless respond_to?(:safety_assured)
|
67
66
|
|
68
|
-
|
67
|
+
return safety_assured { super } if options.fetch(:default_value_backfill, :auto) == :auto
|
69
68
|
|
70
|
-
|
71
|
-
|
72
|
-
super(table_name, *args)
|
69
|
+
super
|
73
70
|
end
|
74
71
|
end
|
75
72
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module SafePgMigrations
|
4
4
|
module UselessStatementsLogger
|
5
5
|
class << self
|
6
|
-
|
6
|
+
def warn_useless(action, link = nil, *args)
|
7
7
|
Helpers::Logger.say(
|
8
8
|
"/!\\ No need to explicitly use #{action}, safe-pg-migrations does it for you", *args
|
9
9
|
)
|
@@ -11,28 +11,24 @@ module SafePgMigrations
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
options = args.last.is_a?(Hash) ? args.last : {}
|
14
|
+
def add_index(table_name, column_name, **options)
|
16
15
|
warn_for_index(**options)
|
17
16
|
super
|
18
17
|
end
|
19
18
|
|
20
|
-
|
21
|
-
options = args.last.is_a?(Hash) ? args.last : {}
|
19
|
+
def remove_index(table_name, column_name = nil, **options)
|
22
20
|
warn_for_index(**options) unless options.empty?
|
23
21
|
super
|
24
22
|
end
|
25
23
|
|
26
|
-
|
27
|
-
options = args.last.is_a?(Hash) ? args.last : {}
|
24
|
+
def add_foreign_key(from_table, to_table, **options)
|
28
25
|
if options[:validate] == false
|
29
26
|
UselessStatementsLogger.warn_useless '`validate: :false`', 'https://github.com/doctolib/safe-pg-migrations#safe_add_foreign_key'
|
30
27
|
end
|
31
28
|
super
|
32
29
|
end
|
33
30
|
|
34
|
-
|
35
|
-
options = args.last.is_a?(Hash) ? args.last : {}
|
31
|
+
def add_check_constraint(table_name, expression, **options)
|
36
32
|
if options[:validate] == false
|
37
33
|
UselessStatementsLogger.warn_useless '`validate: :false`', 'https://github.com/doctolib/safe-pg-migrations#safe_add_check_constraint'
|
38
34
|
end
|
metadata
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: safe-pg-migrations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthieu Prat
|
8
8
|
- Romain Choquet
|
9
9
|
- Thomas Hareau
|
10
|
+
- Charles Delannoy
|
10
11
|
autorequire:
|
11
12
|
bindir: bin
|
12
13
|
cert_chain: []
|
13
|
-
date: 2023-
|
14
|
+
date: 2023-12-11 00:00:00.000000000 Z
|
14
15
|
dependencies:
|
15
16
|
- !ruby/object:Gem::Dependency
|
16
17
|
name: activerecord
|
@@ -18,40 +19,28 @@ dependencies:
|
|
18
19
|
requirements:
|
19
20
|
- - ">="
|
20
21
|
- !ruby/object:Gem::Version
|
21
|
-
version: '6.
|
22
|
-
- - "<"
|
23
|
-
- !ruby/object:Gem::Version
|
24
|
-
version: 7.1.x
|
22
|
+
version: '6.1'
|
25
23
|
type: :runtime
|
26
24
|
prerelease: false
|
27
25
|
version_requirements: !ruby/object:Gem::Requirement
|
28
26
|
requirements:
|
29
27
|
- - ">="
|
30
28
|
- !ruby/object:Gem::Version
|
31
|
-
version: '6.
|
32
|
-
- - "<"
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
-
version: 7.1.x
|
29
|
+
version: '6.1'
|
35
30
|
- !ruby/object:Gem::Dependency
|
36
31
|
name: activesupport
|
37
32
|
requirement: !ruby/object:Gem::Requirement
|
38
33
|
requirements:
|
39
34
|
- - ">="
|
40
35
|
- !ruby/object:Gem::Version
|
41
|
-
version: '6.
|
42
|
-
- - "<"
|
43
|
-
- !ruby/object:Gem::Version
|
44
|
-
version: 7.1.x
|
36
|
+
version: '6.1'
|
45
37
|
type: :runtime
|
46
38
|
prerelease: false
|
47
39
|
version_requirements: !ruby/object:Gem::Requirement
|
48
40
|
requirements:
|
49
41
|
- - ">="
|
50
42
|
- !ruby/object:Gem::Version
|
51
|
-
version: '6.
|
52
|
-
- - "<"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: 7.1.x
|
43
|
+
version: '6.1'
|
55
44
|
description: Make your PG migrations safe.
|
56
45
|
email:
|
57
46
|
executables: []
|
@@ -102,7 +91,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
102
91
|
requirements:
|
103
92
|
- - ">="
|
104
93
|
- !ruby/object:Gem::Version
|
105
|
-
version: '
|
94
|
+
version: '3.0'
|
106
95
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
96
|
requirements:
|
108
97
|
- - ">="
|