safe-pg-migrations 2.3.1 → 3.0.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: 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
  - - ">="