departure 8.0.0 → 8.2.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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +41 -2
  3. data/.pryrc +6 -6
  4. data/.standard.yml +9 -0
  5. data/AGENTS.md +77 -0
  6. data/Appraisals +11 -8
  7. data/CHANGELOG.md +16 -0
  8. data/Gemfile +8 -9
  9. data/Gemfile.lock +25 -11
  10. data/README.md +26 -4
  11. data/RELEASING.md +5 -4
  12. data/Rakefile +10 -10
  13. data/configuration.rb +3 -3
  14. data/departure.gemspec +26 -29
  15. data/gemfiles/rails_7_2.gemfile +2 -2
  16. data/gemfiles/rails_7_2.gemfile.lock +28 -11
  17. data/gemfiles/rails_8_0.gemfile +2 -2
  18. data/gemfiles/rails_8_0.gemfile.lock +28 -11
  19. data/gemfiles/rails_8_1.gemfile +3 -3
  20. data/gemfiles/rails_8_1.gemfile.lock +27 -11
  21. data/lib/active_record/connection_adapters/departure_adapter_behavior.rb +88 -0
  22. data/lib/active_record/connection_adapters/for_alter.rb +4 -10
  23. data/lib/active_record/connection_adapters/patch_connection_handling.rb +7 -6
  24. data/lib/active_record/connection_adapters/rails_7_2_departure_adapter.rb +17 -58
  25. data/lib/active_record/connection_adapters/rails_7_2_trilogy_adapter.rb +53 -0
  26. data/lib/active_record/connection_adapters/rails_8_0_departure_adapter.rb +26 -66
  27. data/lib/active_record/connection_adapters/rails_8_0_trilogy_adapter.rb +21 -0
  28. data/lib/active_record/connection_adapters/rails_8_1_mysql2_adapter.rb +23 -0
  29. data/lib/active_record/connection_adapters/rails_8_1_trilogy_adapter.rb +21 -0
  30. data/lib/departure/alter_argument.rb +6 -6
  31. data/lib/departure/cli_generator.rb +12 -12
  32. data/lib/departure/command.rb +1 -1
  33. data/lib/departure/configuration.rb +3 -3
  34. data/lib/departure/connection_details.rb +7 -7
  35. data/lib/departure/db_client.rb +5 -5
  36. data/lib/departure/dsn.rb +2 -2
  37. data/lib/departure/errors.rb +2 -2
  38. data/lib/departure/log_sanitizers/password_sanitizer.rb +1 -1
  39. data/lib/departure/logger.rb +2 -2
  40. data/lib/departure/migration.rb +40 -10
  41. data/lib/departure/option.rb +4 -4
  42. data/lib/departure/rails_adapter.rb +145 -85
  43. data/lib/departure/rails_patches/active_record_migrator_with_advisory_lock_patch.rb +2 -2
  44. data/lib/departure/railtie.rb +7 -5
  45. data/lib/departure/runner.rb +3 -3
  46. data/lib/departure/user_options.rb +1 -1
  47. data/lib/departure/version.rb +1 -1
  48. data/lib/departure.rb +21 -23
  49. data/lib/lhm/adapter.rb +12 -12
  50. data/lib/lhm/column_with_sql.rb +8 -8
  51. data/lib/lhm.rb +1 -1
  52. data/test_database.rb +10 -10
  53. metadata +12 -4
  54. data/.rubocop.yml +0 -66
  55. data/.rubocop_todo.yml +0 -238
  56. data/lib/active_record/connection_adapters/rails_8_1_departure_adapter.rb +0 -83
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- departure (8.0.0)
4
+ departure (8.2.0)
5
5
  activerecord (>= 7.2.0)
6
6
  mysql2 (>= 0.4.0, < 0.6.0)
7
7
  railties (>= 7.2.0)
@@ -167,7 +167,7 @@ GEM
167
167
  pp (0.6.3)
168
168
  prettyprint
169
169
  prettyprint (0.2.0)
170
- prism (1.6.0)
170
+ prism (1.9.0)
171
171
  pry (0.15.2)
172
172
  coderay (~> 1.1)
173
173
  method_source (~> 1.0)
@@ -240,7 +240,7 @@ GEM
240
240
  diff-lcs (>= 1.2.0, < 2.0)
241
241
  rspec-support (~> 3.13.0)
242
242
  rspec-support (3.13.6)
243
- rubocop (1.74.0)
243
+ rubocop (1.84.2)
244
244
  json (~> 2.3)
245
245
  language_server-protocol (~> 3.17.0.2)
246
246
  lint_roller (~> 1.1.0)
@@ -248,15 +248,16 @@ GEM
248
248
  parser (>= 3.3.0.2)
249
249
  rainbow (>= 2.2.2, < 4.0)
250
250
  regexp_parser (>= 2.9.3, < 3.0)
251
- rubocop-ast (>= 1.38.0, < 2.0)
251
+ rubocop-ast (>= 1.49.0, < 2.0)
252
252
  ruby-progressbar (~> 1.7)
253
253
  unicode-display_width (>= 2.4.0, < 4.0)
254
- rubocop-ast (1.47.1)
254
+ rubocop-ast (1.49.1)
255
255
  parser (>= 3.3.7.2)
256
- prism (~> 1.4)
257
- rubocop-performance (1.20.2)
258
- rubocop (>= 1.48.1, < 2.0)
259
- rubocop-ast (>= 1.30.0, < 2.0)
256
+ prism (~> 1.7)
257
+ rubocop-performance (1.26.1)
258
+ lint_roller (~> 1.1)
259
+ rubocop (>= 1.75.0, < 2.0)
260
+ rubocop-ast (>= 1.47.1, < 2.0)
260
261
  ruby-progressbar (1.13.0)
261
262
  securerandom (0.4.1)
262
263
  simplecov (0.13.0)
@@ -264,9 +265,25 @@ GEM
264
265
  json (>= 1.8, < 3)
265
266
  simplecov-html (~> 0.10.0)
266
267
  simplecov-html (0.10.2)
268
+ standard (1.54.0)
269
+ language_server-protocol (~> 3.17.0.2)
270
+ lint_roller (~> 1.0)
271
+ rubocop (~> 1.84.0)
272
+ standard-custom (~> 1.0.0)
273
+ standard-performance (~> 1.8)
274
+ standard-custom (1.0.2)
275
+ lint_roller (~> 1.0)
276
+ rubocop (~> 1.50)
277
+ standard-performance (1.9.0)
278
+ lint_roller (~> 1.1)
279
+ rubocop-performance (~> 1.26.0)
280
+ standardrb (1.0.1)
281
+ standard
267
282
  stringio (3.1.7)
268
283
  thor (1.4.0)
269
284
  timeout (0.4.4)
285
+ trilogy (2.12.6)
286
+ bigdecimal
270
287
  tsort (0.2.0)
271
288
  tzinfo (2.0.6)
272
289
  concurrent-ruby (~> 1.0)
@@ -306,8 +323,8 @@ DEPENDENCIES
306
323
  rake (>= 10.0)
307
324
  rspec (~> 3.4, >= 3.4.0)
308
325
  rspec-its (~> 1.2)
309
- rubocop (~> 1.74.0)
310
- rubocop-performance (~> 1.20.2)
326
+ standardrb
327
+ trilogy
311
328
  zeitwerk (< 2.7.0)
312
329
 
313
330
  BUNDLED WITH
@@ -7,9 +7,9 @@ gem "codeclimate-test-reporter", "~> 1.0.3", group: :test, require: nil
7
7
  gem "lhm"
8
8
  gem "logger"
9
9
  gem "mutex_m", require: false
10
- gem "rubocop", "~> 1.74.0", require: false
11
- gem "rubocop-performance", "~> 1.20.2", require: false
12
- gem "zeitwerk", "< 2.7.0"
13
10
  gem "rails", "8.1.1"
11
+ gem "standardrb", require: false
12
+ gem "trilogy"
13
+ gem "zeitwerk", "< 2.7.0"
14
14
 
15
15
  gemspec path: "../"
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- departure (8.0.0)
4
+ departure (8.2.0)
5
5
  activerecord (>= 7.2.0)
6
6
  mysql2 (>= 0.4.0, < 0.6.0)
7
7
  railties (>= 7.2.0)
@@ -169,7 +169,7 @@ GEM
169
169
  pp (0.6.3)
170
170
  prettyprint
171
171
  prettyprint (0.2.0)
172
- prism (1.6.0)
172
+ prism (1.9.0)
173
173
  pry (0.15.2)
174
174
  coderay (~> 1.1)
175
175
  method_source (~> 1.0)
@@ -243,7 +243,7 @@ GEM
243
243
  diff-lcs (>= 1.2.0, < 2.0)
244
244
  rspec-support (~> 3.13.0)
245
245
  rspec-support (3.13.6)
246
- rubocop (1.74.0)
246
+ rubocop (1.84.2)
247
247
  json (~> 2.3)
248
248
  language_server-protocol (~> 3.17.0.2)
249
249
  lint_roller (~> 1.1.0)
@@ -251,15 +251,16 @@ GEM
251
251
  parser (>= 3.3.0.2)
252
252
  rainbow (>= 2.2.2, < 4.0)
253
253
  regexp_parser (>= 2.9.3, < 3.0)
254
- rubocop-ast (>= 1.38.0, < 2.0)
254
+ rubocop-ast (>= 1.49.0, < 2.0)
255
255
  ruby-progressbar (~> 1.7)
256
256
  unicode-display_width (>= 2.4.0, < 4.0)
257
- rubocop-ast (1.47.1)
257
+ rubocop-ast (1.49.1)
258
258
  parser (>= 3.3.7.2)
259
- prism (~> 1.4)
260
- rubocop-performance (1.20.2)
261
- rubocop (>= 1.48.1, < 2.0)
262
- rubocop-ast (>= 1.30.0, < 2.0)
259
+ prism (~> 1.7)
260
+ rubocop-performance (1.26.1)
261
+ lint_roller (~> 1.1)
262
+ rubocop (>= 1.75.0, < 2.0)
263
+ rubocop-ast (>= 1.47.1, < 2.0)
263
264
  ruby-progressbar (1.13.0)
264
265
  securerandom (0.4.1)
265
266
  simplecov (0.13.0)
@@ -267,9 +268,24 @@ GEM
267
268
  json (>= 1.8, < 3)
268
269
  simplecov-html (~> 0.10.0)
269
270
  simplecov-html (0.10.2)
271
+ standard (1.54.0)
272
+ language_server-protocol (~> 3.17.0.2)
273
+ lint_roller (~> 1.0)
274
+ rubocop (~> 1.84.0)
275
+ standard-custom (~> 1.0.0)
276
+ standard-performance (~> 1.8)
277
+ standard-custom (1.0.2)
278
+ lint_roller (~> 1.0)
279
+ rubocop (~> 1.50)
280
+ standard-performance (1.9.0)
281
+ lint_roller (~> 1.1)
282
+ rubocop-performance (~> 1.26.0)
283
+ standardrb (1.0.1)
284
+ standard
270
285
  stringio (3.1.7)
271
286
  thor (1.4.0)
272
287
  timeout (0.4.4)
288
+ trilogy (2.9.0)
273
289
  tsort (0.2.0)
274
290
  tzinfo (2.0.6)
275
291
  concurrent-ruby (~> 1.0)
@@ -308,8 +324,8 @@ DEPENDENCIES
308
324
  rake (>= 10.0)
309
325
  rspec (~> 3.4, >= 3.4.0)
310
326
  rspec-its (~> 1.2)
311
- rubocop (~> 1.74.0)
312
- rubocop-performance (~> 1.20.2)
327
+ standardrb
328
+ trilogy
313
329
  zeitwerk (< 2.7.0)
314
330
 
315
331
  BUNDLED WITH
@@ -0,0 +1,88 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ # Behavior shared between the per-Rails-version Departure adapters.
4
+ # Adapters compose the pieces they need:
5
+ #
6
+ # - SchemaStatements: ALTER TABLE-friendly schema statements, so every DDL
7
+ # change goes through a statement pt-online-schema-change understands.
8
+ # - DbClientConnection: wraps the raw database client in a
9
+ # Departure::DbClient, which routes ALTER TABLE statements to
10
+ # pt-online-schema-change.
11
+ # - PerformQuery: intercepts ALTER TABLE statements through the
12
+ # perform_query hook available on Rails >= 8.0.
13
+ # - Rails8: the composition used by Rails >= 8.0 adapters.
14
+ module DepartureAdapterBehavior
15
+ module SchemaStatements
16
+ class SchemaCreation < ActiveRecord::ConnectionAdapters::MySQL::SchemaCreation
17
+ def visit_DropForeignKey(name) # standard:disable Naming/MethodName
18
+ fk_name =
19
+ if name =~ /^__(.+)/
20
+ Regexp.last_match(1)
21
+ else
22
+ "_#{name}"
23
+ end
24
+
25
+ "DROP FOREIGN KEY #{fk_name}"
26
+ end
27
+ end
28
+
29
+ def self.included(adapter_class)
30
+ adapter_class.const_set(:SchemaCreation, SchemaCreation)
31
+ adapter_class.include ForAlterStatements unless adapter_class.method_defined?(:change_column_for_alter)
32
+ end
33
+
34
+ # add_index is modified from the underlying mysql adapter implementation to ensure we add ALTER TABLE to it
35
+ def add_index(table_name, column_name, options = {})
36
+ index_definition, = add_index_options(table_name, column_name, **options)
37
+ execute <<-SQL.squish
38
+ ALTER TABLE #{quote_table_name(index_definition.table)}
39
+ ADD #{schema_creation.accept(index_definition)}
40
+ SQL
41
+ end
42
+
43
+ # remove_index is modified from the underlying mysql adapter implementation to ensure we add ALTER TABLE to it
44
+ def remove_index(table_name, column_name = nil, **options)
45
+ return if options[:if_exists] && !index_exists?(table_name, column_name, **options)
46
+
47
+ index_name = index_name_for_remove(table_name, column_name, options)
48
+
49
+ execute "ALTER TABLE #{quote_table_name(table_name)} DROP INDEX #{quote_column_name(index_name)}"
50
+ end
51
+
52
+ def schema_creation
53
+ self.class::SchemaCreation.new(self)
54
+ end
55
+ end
56
+
57
+ # Meant to be used with `extend`, so new_client can call super up to the
58
+ # underlying adapter's implementation.
59
+ module DbClientConnection
60
+ def new_client(config)
61
+ original_client = super
62
+
63
+ Departure::DbClient.new(config, original_client)
64
+ end
65
+ end
66
+
67
+ module PerformQuery
68
+ private
69
+
70
+ # rubocop:disable Metrics/ParameterLists
71
+ def perform_query(raw_connection, sql, binds, type_casted_binds, prepare:, notification_payload:, batch: false)
72
+ return raw_connection.send_to_pt_online_schema_change(sql) if raw_connection.alter_statement?(sql)
73
+
74
+ super
75
+ end
76
+ # rubocop:enable Metrics/ParameterLists
77
+ end
78
+
79
+ module Rails8
80
+ def self.included(adapter_class)
81
+ adapter_class.include SchemaStatements
82
+ adapter_class.extend DbClientConnection
83
+ adapter_class.include PerformQuery
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -1,12 +1,6 @@
1
- require 'active_record/connection_adapters/mysql/schema_statements'
1
+ require "active_record/connection_adapters/mysql/schema_statements"
2
2
 
3
3
  module ForAlterStatements
4
- class << self
5
- def included(_)
6
- STDERR.puts 'Including for_alter statements'
7
- end
8
- end
9
-
10
4
  def bulk_change_table(table_name, operations) #:nodoc:
11
5
  sqls = operations.flat_map do |command, args|
12
6
  table = args.shift
@@ -16,7 +10,7 @@ module ForAlterStatements
16
10
 
17
11
  raise "Unknown method called : #{method}(#{arguments.inspect})" unless respond_to?(method, true)
18
12
  public_send(method, table, *arguments)
19
- end.join(', ')
13
+ end.join(", ")
20
14
 
21
15
  execute("ALTER TABLE #{quote_table_name(table_name)} #{sqls}")
22
16
  end
@@ -37,7 +31,7 @@ module ForAlterStatements
37
31
  end
38
32
 
39
33
  def rename_column_for_alter(table_name, column_name, new_column_name)
40
- column = column_for(table_name, column_name)
34
+ column = column_for(table_name, column_name)
41
35
  options = {
42
36
  default: column.default,
43
37
  null: column.null,
@@ -45,7 +39,7 @@ module ForAlterStatements
45
39
  }
46
40
 
47
41
  columns_sql = "SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE #{quote(column_name)}"
48
- current_type = exec_query(columns_sql, 'SCHEMA').first['Type']
42
+ current_type = exec_query(columns_sql, "SCHEMA").first["Type"]
49
43
  td = create_table_definition(table_name)
50
44
  cd = td.new_column_definition(new_column_name, current_type, **options)
51
45
  schema_creation.accept(ActiveRecord::ConnectionAdapters::ChangeColumnDefinition.new(cd, column.name))
@@ -1,18 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_record/connection_handling'
3
+ require "active_record/connection_handling"
4
4
 
5
5
  module ActiveRecord
6
6
  module ConnectionHandling
7
7
  # Establishes a connection to the database that's used by all Active
8
8
  # Record objects.
9
9
  def percona_connection(config)
10
- if config[:username].nil?
11
- config = config.dup if config.frozen?
12
- config[:username] = 'root'
13
- end
10
+ config = config.dup
11
+ original_adapter = config.delete(:departure_original_adapter)
12
+ config[:username] ||= "root"
14
13
 
15
- Departure::RailsAdapter.for_current.create_connection_adapter(**config)
14
+ Departure::RailsAdapter
15
+ .for_current(db_connection_adapter: original_adapter)
16
+ .create_connection_adapter(**config)
16
17
  end
17
18
  end
18
19
  end
@@ -1,10 +1,11 @@
1
- require 'active_record/connection_adapters/abstract_mysql_adapter'
2
- require 'active_record/connection_adapters/statement_pool'
3
- require 'active_record/connection_adapters/mysql2_adapter'
4
- require 'active_record/connection_adapters/patch_connection_handling'
5
- require 'active_support/core_ext/string/filters'
6
- require 'departure'
7
- require 'forwardable'
1
+ require "active_record/connection_adapters/abstract_mysql_adapter"
2
+ require "active_record/connection_adapters/statement_pool"
3
+ require "active_record/connection_adapters/mysql2_adapter"
4
+ require "active_record/connection_adapters/patch_connection_handling"
5
+ require "active_support/core_ext/string/filters"
6
+ require "departure"
7
+ require "forwardable"
8
+ require "active_record/connection_adapters/departure_adapter_behavior"
8
9
 
9
10
  module ActiveRecord
10
11
  module ConnectionAdapters
@@ -17,24 +18,11 @@ module ActiveRecord
17
18
  end
18
19
  end
19
20
 
20
- class SchemaCreation < ActiveRecord::ConnectionAdapters::MySQL::SchemaCreation
21
- def visit_DropForeignKey(name) # rubocop:disable Style/MethodName
22
- fk_name =
23
- if name =~ /^__(.+)/
24
- Regexp.last_match(1)
25
- else
26
- "_#{name}"
27
- end
28
-
29
- "DROP FOREIGN KEY #{fk_name}"
30
- end
31
- end
32
-
33
21
  extend Forwardable
34
22
 
35
- include ForAlterStatements unless method_defined?(:change_column_for_alter)
23
+ include DepartureAdapterBehavior::SchemaStatements
36
24
 
37
- ADAPTER_NAME = 'Percona'.freeze
25
+ ADAPTER_NAME = "Percona".freeze
38
26
 
39
27
  def self.new_client(config)
40
28
  connection_details = Departure::ConnectionDetails.new(config)
@@ -45,7 +33,7 @@ module ActiveRecord
45
33
  percona_logger = Departure::LoggerFactory.build(sanitizers: sanitizers, verbose: verbose)
46
34
  cli_generator = Departure::CliGenerator.new(connection_details)
47
35
 
48
- mysql_adapter = ActiveRecord::ConnectionAdapters::Mysql2Adapter.new(config.merge(adapter: 'mysql2'))
36
+ mysql_adapter = ActiveRecord::ConnectionAdapters::Mysql2Adapter.new(config.merge(adapter: "mysql2"))
49
37
 
50
38
  Departure::Runner.new(
51
39
  percona_logger,
@@ -60,7 +48,7 @@ module ActiveRecord
60
48
  @config[:flags] ||= 0
61
49
 
62
50
  if @config[:flags].is_a? Array
63
- @config[:flags].push 'FOUND_ROWS'
51
+ @config[:flags].push "FOUND_ROWS"
64
52
  else
65
53
  @config[:flags] |= ::Mysql2::Client::FOUND_ROWS
66
54
  end
@@ -79,18 +67,18 @@ module ActiveRecord
79
67
 
80
68
  @raw_connection.affected_rows
81
69
  end
82
- alias exec_update exec_delete
70
+ alias_method :exec_update, :exec_delete
83
71
 
84
- def exec_insert(sql, name, binds, pky = nil, sequence_name = nil, returning: nil) # rubocop:disable Lint/UnusedMethodArgument, Metrics/Metrics/ParameterLists
72
+ def exec_insert(sql, name, binds, pky = nil, sequence_name = nil, returning: nil) # standard:disable Lint/UnusedMethodArgument
85
73
  execute(to_sql(sql, binds), name)
86
74
  end
87
75
 
88
- def internal_exec_query(sql, name = 'SQL', _binds = [], **_kwargs) # :nodoc:
76
+ def internal_exec_query(sql, name = "SQL", _binds = [], **_kwargs) # :nodoc:
89
77
  result = execute(sql, name)
90
78
  fields = result.fields if defined?(result.fields)
91
79
  ActiveRecord::Result.new(fields || [], result.to_a)
92
80
  end
93
- alias exec_query internal_exec_query
81
+ alias_method :exec_query, :internal_exec_query
94
82
 
95
83
  # Executes a SELECT query and returns an array of rows. Each row is an
96
84
  # array of field values.
@@ -114,35 +102,6 @@ module ActiveRecord
114
102
  Column.new(...)
115
103
  end
116
104
 
117
- # Adds a new index to the table
118
- #
119
- # @param table_name [String, Symbol]
120
- # @param column_name [String, Symbol]
121
- # @param options [Hash] optional
122
- def add_index(table_name, column_name, options = {})
123
- index_definition, = add_index_options(table_name, column_name, **options)
124
- execute <<-SQL.squish
125
- ALTER TABLE #{quote_table_name(index_definition.table)}
126
- ADD #{schema_creation.accept(index_definition)}
127
- SQL
128
- end
129
-
130
- # Remove the given index from the table.
131
- #
132
- # @param table_name [String, Symbol]
133
- # @param options [Hash] optional
134
- def remove_index(table_name, column_name = nil, **options)
135
- return if options[:if_exists] && !index_exists?(table_name, column_name, **options)
136
-
137
- index_name = index_name_for_remove(table_name, column_name, options)
138
-
139
- execute "ALTER TABLE #{quote_table_name(table_name)} DROP INDEX #{quote_column_name(index_name)}"
140
- end
141
-
142
- def schema_creation
143
- SchemaCreation.new(self)
144
- end
145
-
146
105
  def change_table(table_name, _options = {})
147
106
  recorder = ActiveRecord::Migration::CommandRecorder.new(self)
148
107
  yield update_table_definition(table_name, recorder)
@@ -153,7 +112,7 @@ module ActiveRecord
153
112
  get_full_version
154
113
  end
155
114
 
156
- def get_full_version # rubocop:disable Style/AccessorMethodName
115
+ def get_full_version # standard:disable Naming/AccessorMethodName
157
116
  return @get_full_version if defined? @get_full_version
158
117
 
159
118
  with_raw_connection do |conn|
@@ -0,0 +1,53 @@
1
+ require "active_record/connection_adapters/abstract_mysql_adapter"
2
+ require "active_record/connection_adapters/trilogy_adapter"
3
+ require "active_record/connection_adapters/patch_connection_handling"
4
+ require "departure"
5
+ require "active_record/connection_adapters/departure_adapter_behavior"
6
+
7
+ module ActiveRecord
8
+ module ConnectionAdapters
9
+ class Rails72TrilogyAdapter < ActiveRecord::ConnectionAdapters::TrilogyAdapter
10
+ class Column < ActiveRecord::ConnectionAdapters::MySQL::Column
11
+ def adapter
12
+ Rails72TrilogyAdapter
13
+ end
14
+ end
15
+
16
+ ADAPTER_NAME = "Percona".freeze
17
+
18
+ include DepartureAdapterBehavior::SchemaStatements
19
+ extend DepartureAdapterBehavior::DbClientConnection
20
+
21
+ def new_column(...)
22
+ Column.new(...)
23
+ end
24
+
25
+ private
26
+
27
+ # Rails 7.2 has no perform_query hook, so the interception happens here:
28
+ # the DbClient wrapper routes ALTER TABLE statements to
29
+ # pt-online-schema-change, which yields a Process::Status instead of a
30
+ # Trilogy::Result.
31
+ def raw_execute(sql, name, async: false, allow_retry: false, materialize_transactions: true)
32
+ log(sql, name, async: async) do |notification_payload|
33
+ with_raw_connection(allow_retry: allow_retry, materialize_transactions: materialize_transactions) do |conn|
34
+ sync_timezone_changes(conn)
35
+ result = conn.query(sql)
36
+ while conn.more_results_exist?
37
+ conn.next_result
38
+ end
39
+ verified!
40
+ handle_warnings(sql)
41
+ if result.is_a?(Process::Status)
42
+ notification_payload[:exit_code] = result.exitstatus
43
+ notification_payload[:exit_pid] = result.pid
44
+ elsif result.respond_to?(:count)
45
+ notification_payload[:row_count] = result.count
46
+ end
47
+ result
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end