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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: da23106f1db5b2a4f626e37170f2d26f8642f52ffda4775d972822b12156b301
4
- data.tar.gz: 49ede8d6b233b0d0c9b26efc5d62be4be99e08111b39beec9c4904928ae31e72
3
+ metadata.gz: 2e58bfc8a79c0b54a368c49a1fc720e33582220b472c81c3556158aa4d3e8f05
4
+ data.tar.gz: a112e1ade2a57568cdebee942d0a4f4f5eef1fcfb19db576d30c25eacf7fc04d
5
5
  SHA512:
6
- metadata.gz: 79502033f2e447bea822504895d62ad31e3aa78957c164cfa63a4b857f0282f0e19e0e2a848eba25c8f02cb447fed06316c7c5a1cd2e9f5a021cb9b5a9e178f7
7
- data.tar.gz: cd0fb8724abf3ddc17d818fc664e4445cb2b27e87b5644ccb22be5cbe106383792b23ae2ce32c4ad7a6641ad965a8412afe52758b87a9086d2f8cdd979c698cd
6
+ metadata.gz: 7b28dcf7b252ebe311258b1c3ba4badfa0f365d40b53209e66b51c459a8fd960c3ceb452a378d0feb5785ec8f7632f575d53b9ec543e1de016729066d5e9ed42
7
+ data.tar.gz: 3338baf96b5d82f6055f6b59691fb42f0560e1d18c4a372685e9bc9ae40f55b58b1382bc8347e13b0d8628b754abae85f4d6c9d57437888efa334f9f82029e7b
data/README.md CHANGED
@@ -6,8 +6,8 @@ ActiveRecord migrations for Postgres made safe.
6
6
 
7
7
  ## Requirements
8
8
 
9
- - Ruby 2.7+
10
- - Rails 6.0+
9
+ - Ruby 3.0+
10
+ - Rails 6.1+
11
11
  - PostgreSQL 11.7+
12
12
 
13
13
  ## Usage
@@ -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
- ruby2_keywords def add_index(table_name, column_name, *args)
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, name: index_definition.name)
17
+ remove_index(table_name, column_name, **options)
19
18
  super
20
19
  end
21
20
 
22
- ruby2_keywords def add_column(table_name, column_name, type, *)
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
- return super unless column_exists?(table_name, column_name, type)
27
+ options_without_default_value_backfill = options.except(:default_value_backfill)
29
28
 
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
- )
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
- ruby2_keywords def remove_column(table_name, column_name, type = nil, *)
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
- ruby2_keywords def remove_index(table_name, *args)
44
- options = args.last.is_a?(Hash) ? args.last : {}
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
- ruby2_keywords def add_foreign_key(from_table, to_table, *args)
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
- ruby2_keywords def create_table(table_name, *args)
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, *args)
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, options)
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
- ruby2_keywords def drop_table(table_name, *)
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
- ruby2_keywords def add_column(table_name, column_name, type, *args)
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
- ruby2_keywords def add_foreign_key(from_table, to_table, *args)
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
- ruby2_keywords def create_table(*)
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
- ruby2_keywords def add_index(table_name, column_name, *args_options)
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
- ruby2_keywords def remove_index(table_name, *args)
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
- ruby2_keywords def drop_table(table_name, *args)
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, *args
85
+ Helpers::Logger.say_method_call :drop_table, table_name, **options
90
86
 
91
- super(table_name, *args)
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
- ruby2_keywords def add_column(table_name, *args)
66
- return super(table_name, *args) unless respond_to?(:safety_assured)
64
+ def add_column(table_name, *args, **options)
65
+ return super unless respond_to?(:safety_assured)
67
66
 
68
- options = args.last.is_a?(Hash) ? args.last : {}
67
+ return safety_assured { super } if options.fetch(:default_value_backfill, :auto) == :auto
69
68
 
70
- return safety_assured { super(table_name, *args) } if options.fetch(:default_value_backfill, :auto) == :auto
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
- ruby2_keywords def warn_useless(action, link = nil, *args)
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
- ruby2_keywords def add_index(*args)
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
- ruby2_keywords def remove_index(table_name, *args)
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
- ruby2_keywords def add_foreign_key(*args)
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
- ruby2_keywords def add_check_constraint(*args)
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SafePgMigrations
4
- VERSION = '2.3.1'
4
+ VERSION = '3.0.0'
5
5
  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: 2.3.1
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-10-16 00:00:00.000000000 Z
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.0'
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.0'
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.0'
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.0'
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: '2.7'
94
+ version: '3.0'
106
95
  required_rubygems_version: !ruby/object:Gem::Requirement
107
96
  requirements:
108
97
  - - ">="