departure 6.1.0 → 6.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/workflows/test.yml +45 -0
- data/.gitignore +2 -0
- data/.pryrc +11 -0
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +36 -0
- data/README.md +47 -9
- data/RELEASING.md +1 -1
- data/bin/console +1 -1
- data/departure.gemspec +11 -6
- data/lib/active_record/connection_adapters/for_alter.rb +97 -0
- data/lib/active_record/connection_adapters/percona_adapter.rb +80 -11
- data/lib/departure/alter_argument.rb +9 -3
- data/lib/departure/command.rb +9 -4
- data/lib/departure/configuration.rb +3 -1
- data/lib/departure/connection_base.rb +11 -0
- data/lib/departure/connection_details.rb +19 -1
- data/lib/departure/migration.rb +104 -0
- data/lib/departure/railtie.rb +6 -13
- data/lib/departure/runner.rb +3 -2
- data/lib/departure/version.rb +1 -1
- data/lib/departure.rb +11 -34
- data/lib/lhm/column_with_sql.rb +1 -1
- data/test_database.rb +11 -14
- metadata +67 -24
- data/.travis.yml +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8e9b07d68819910b4f867268d8680b65677e6c11fe91b7f5c2f3a4b62cee627a
|
4
|
+
data.tar.gz: daf4792210ea603d0732fae6daebe97fcbea253960067d800495b49b6c2aa866
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ba37179c249db07bc0770288ff6103ee4502846488319356bb2aad94738dd5727c42fea899e97aaccb974d5e0bd6f06d475ee0f922d460ec0cc2a2a0ad95f4b
|
7
|
+
data.tar.gz: 9c5acbc1f3b3064341f371e584c3e3da4f326d9f3bfc9a32d844dccdd12bf50c4c6c4519c5742f086fbb4261e252fc31fa6c5cf5777f1d028da4e4798d127aa8
|
@@ -0,0 +1,45 @@
|
|
1
|
+
name: Test
|
2
|
+
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
test:
|
7
|
+
strategy:
|
8
|
+
fail-fast: false
|
9
|
+
matrix:
|
10
|
+
ruby:
|
11
|
+
- 2.5
|
12
|
+
- 2.6
|
13
|
+
- 2.7
|
14
|
+
rails:
|
15
|
+
- 5.2.0
|
16
|
+
- 6.0.0
|
17
|
+
- 6.1.0
|
18
|
+
include:
|
19
|
+
- ruby: 2.4
|
20
|
+
rails: 5.2.0
|
21
|
+
- ruby: 2.7
|
22
|
+
rails: 7.0.1
|
23
|
+
- ruby: 3.0
|
24
|
+
rails: 6.1.0
|
25
|
+
env:
|
26
|
+
PERCONA_DB_USER: root
|
27
|
+
PERCONA_DB_PASSWORD: root
|
28
|
+
RAILS_VERSION: "~> ${{ matrix.rails }}"
|
29
|
+
runs-on: ubuntu-latest
|
30
|
+
steps:
|
31
|
+
- uses: actions/checkout@v2
|
32
|
+
- uses: ruby/setup-ruby@v1
|
33
|
+
with:
|
34
|
+
ruby-version: ${{ matrix.ruby }}
|
35
|
+
bundler-cache: true
|
36
|
+
- name: "Add Percona GPG key"
|
37
|
+
run: sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 9334A25F8507EFA5
|
38
|
+
- name: "Add Percona APT repository"
|
39
|
+
run: echo "deb http://repo.percona.com/apt `lsb_release -cs` main" | sudo tee -a /etc/apt/sources.list
|
40
|
+
- run: sudo apt-get update -qq
|
41
|
+
- run: sudo apt-get install percona-toolkit
|
42
|
+
- name: Start MySQL server
|
43
|
+
run: sudo systemctl start mysql.service
|
44
|
+
- run: bin/setup
|
45
|
+
- run: bundle exec rake
|
data/.gitignore
CHANGED
data/.pryrc
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
if defined?(PryByebug)
|
2
|
+
Pry.commands.alias_command 'c', 'continue'
|
3
|
+
Pry.commands.alias_command 's', 'step'
|
4
|
+
Pry.commands.alias_command 'n', 'next'
|
5
|
+
Pry.commands.alias_command 'f', 'finish'
|
6
|
+
Pry.commands.alias_command 'w', 'pry-backtrace'
|
7
|
+
|
8
|
+
Pry::Commands.command(/^$/, 'repeat last command') do
|
9
|
+
pry_instance.run_command Pry.history.to_a.last
|
10
|
+
end
|
11
|
+
end
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,42 @@ Please follow the format in [Keep a Changelog](http://keepachangelog.com/)
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [6.4.0] - 2020-06-23
|
10
|
+
|
11
|
+
- Support for ActiveRecord 6.1.4
|
12
|
+
- Relax mysql2 requirement to allow mysql2 0.5.4
|
13
|
+
- Support Rails 6' #upsert_all
|
14
|
+
|
15
|
+
## [6.3.0] - 2020-06-23
|
16
|
+
|
17
|
+
- Support for ActiveRecord 6.1
|
18
|
+
|
19
|
+
## [6.2.0] - 2020-06-23
|
20
|
+
|
21
|
+
### Added
|
22
|
+
|
23
|
+
- Support for ActiveRecord 6.0
|
24
|
+
- Support for ActiveRecord 5.2
|
25
|
+
- Relax mysql2 requirement to allow mysql2 0.5.3
|
26
|
+
- Support to batch multiple changes at once with #change_table
|
27
|
+
- Support for connection to MySQL server over SSL
|
28
|
+
|
29
|
+
### Changed
|
30
|
+
|
31
|
+
- Depend only in railties and activerecord instead of rails gem
|
32
|
+
|
33
|
+
### Deprecated
|
34
|
+
### Removed
|
35
|
+
### Fixed
|
36
|
+
|
37
|
+
- Fix support for removing foreign keys
|
38
|
+
- Fix PERCONA_ARGS syntax for critical-load option
|
39
|
+
- Make sure quotes in ALTER TABLE get correctly escaped
|
40
|
+
- Fixes for regex handling
|
41
|
+
- Fix LHM compatibility
|
42
|
+
|
43
|
+
## [6.1.0] - 2018-02-27
|
44
|
+
|
9
45
|
### Added
|
10
46
|
### Changed
|
11
47
|
|
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
# Departure
|
1
|
+
# Departure
|
2
|
+
|
3
|
+
![Build Status](https://img.shields.io/travis/departurerb/departure?style=for-the-badge) ![Code Climate maintainability](https://img.shields.io/codeclimate/maintainability/departurerb/departure?style=for-the-badge) ![GitHub commits since latest release (by date)](https://img.shields.io/github/commits-since/departurerb/departure/latest/master?style=for-the-badge)
|
2
4
|
|
3
5
|
Departure is an **ActiveRecord connection adapter** that allows running
|
4
6
|
**MySQL online and non-blocking DDL** through `ActiveRecord::Migration` without needing
|
@@ -99,7 +101,7 @@ $ PERCONA_ARGS='--chunk-time=1' bundle exec rake db:migrate:up VERSION=xxx
|
|
99
101
|
or even mulitple arguments
|
100
102
|
|
101
103
|
```ruby
|
102
|
-
$ PERCONA_ARGS='--chunk-time=1 --critical-load=55' bundle exec rake db:migrate:up VERSION=xxx
|
104
|
+
$ PERCONA_ARGS='--chunk-time=1 --critical-load Threads_running=55' bundle exec rake db:migrate:up VERSION=xxx
|
103
105
|
```
|
104
106
|
|
105
107
|
Use caution when using PERCONA_ARGS with `db:migrate`, as your args will be applied
|
@@ -112,7 +114,7 @@ using `global_percona_args` option.
|
|
112
114
|
|
113
115
|
```ruby
|
114
116
|
Departure.configure do |config|
|
115
|
-
config.global_percona_args = '--chunk-time=1 --critical-load=55'
|
117
|
+
config.global_percona_args = '--chunk-time=1 --critical-load Threads_running=55'
|
116
118
|
end
|
117
119
|
```
|
118
120
|
|
@@ -145,6 +147,39 @@ end
|
|
145
147
|
It's strongly recommended to name it after this gems name, such as
|
146
148
|
`config/initializers/departure.rb`
|
147
149
|
|
150
|
+
### Disable on per-migration basis
|
151
|
+
|
152
|
+
Departure gem is enabled by default.
|
153
|
+
In order to disable it on a particular migration the method `disable_departure!` should be used.
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
class UseDepartureMigration < ActiveRecord::Migration[5.2]
|
157
|
+
disable_departure!
|
158
|
+
|
159
|
+
def up
|
160
|
+
# ...
|
161
|
+
end
|
162
|
+
# ...
|
163
|
+
end
|
164
|
+
```
|
165
|
+
|
166
|
+
### Enable on per-migration basis
|
167
|
+
|
168
|
+
If you wish to only have Departure enabled per-migration, set `config.enabled_by_default = false` in the configure block of your departure initializer.
|
169
|
+
|
170
|
+
Then, add a `uses_departure!` statement in migrations where Departure should be used:
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
class UseDepartureMigration < ActiveRecord::Migration[5.2]
|
174
|
+
uses_departure!
|
175
|
+
|
176
|
+
def up
|
177
|
+
# ...
|
178
|
+
end
|
179
|
+
# ...
|
180
|
+
end
|
181
|
+
```
|
182
|
+
|
148
183
|
## How it works
|
149
184
|
|
150
185
|
When booting your Rails app, Departure extends the
|
@@ -154,19 +189,19 @@ it using the `DepartureAdapter` instead of the one you defined in your
|
|
154
189
|
|
155
190
|
Then, when any migration DSL methods such as `add_column` or `create_table` are
|
156
191
|
executed, they all go to the
|
157
|
-
[DepartureAdapter](https://github.com/
|
192
|
+
[DepartureAdapter](https://github.com/departurerb/departure/blob/master/lib/active_record/connection_adapters/departure_adapter.rb).
|
158
193
|
There, the methods that require `ALTER TABLE` SQL statements, like `add_column`,
|
159
194
|
are overriden to get executed with
|
160
|
-
[Departure::Runner](https://github.com/
|
195
|
+
[Departure::Runner](https://github.com/departurerb/departure/blob/master/lib/departure/runner.rb),
|
161
196
|
which deals with the `pt-online-schema-change` binary. All the others, like
|
162
197
|
`create_table`, are delegated to the ActiveRecord's built in Mysql2Adapter and
|
163
198
|
so they follow the regular path.
|
164
199
|
|
165
|
-
[Departure::Runner](https://github.com/
|
200
|
+
[Departure::Runner](https://github.com/departurerb/departure/blob/master/lib/departure/runner.rb)
|
166
201
|
spawns a new process that runs the `pt-online-schema-change` binary present in
|
167
|
-
the system, with the
|
202
|
+
the system, with the appropriate arguments for the generated SQL.
|
168
203
|
|
169
|
-
When
|
204
|
+
When any errors occur, an `ActiveRecord::StatementInvalid` exception is
|
170
205
|
raised and the migration is aborted, as all other ActiveRecord connection
|
171
206
|
adapters.
|
172
207
|
|
@@ -191,7 +226,7 @@ git commits and tags, and push the `.gem` file to
|
|
191
226
|
## Contributing
|
192
227
|
|
193
228
|
Bug reports and pull requests are welcome on GitHub at
|
194
|
-
https://github.com/
|
229
|
+
https://github.com/departurerb/departure. They need to be opened against
|
195
230
|
`master` or `v3.2` only if the changes fix a bug in Rails 3.2 apps.
|
196
231
|
|
197
232
|
Please note that this project is released with a Contributor Code of Conduct. By
|
@@ -208,3 +243,6 @@ You can consult the changelog [here](CHANGELOG.md)
|
|
208
243
|
The gem is available as open source under the terms of the [MIT
|
209
244
|
License](http://opensource.org/licenses/MIT).
|
210
245
|
|
246
|
+
![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/departurerb/departure?style=for-the-badge)
|
247
|
+
![GitHub issues](https://img.shields.io/github/issues/departurerb/departure?style=for-the-badge)
|
248
|
+
|
data/RELEASING.md
CHANGED
data/bin/console
CHANGED
data/departure.gemspec
CHANGED
@@ -5,11 +5,15 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
|
6
6
|
require 'departure/version'
|
7
7
|
|
8
|
+
# This environment variable is set on CI to facilitate testing with multiple
|
9
|
+
# versions of Rails.
|
10
|
+
RAILS_DEPENDENCY_VERSION = ENV.fetch('RAILS_VERSION', ['>= 5.2.0', '!= 7.0.0', '< 7.1'])
|
11
|
+
|
8
12
|
Gem::Specification.new do |spec|
|
9
13
|
spec.name = 'departure'
|
10
14
|
spec.version = Departure::VERSION
|
11
|
-
spec.authors = ['Ilya Zayats', 'Pau Pérez', 'Fran Casas', 'Jorge Morante', 'Enrico Stano', 'Adrian Serafin', 'Kirk Haines']
|
12
|
-
spec.email = ['ilya.zayats@redbooth.com', 'pau.perez@redbooth.com', '
|
15
|
+
spec.authors = ['Ilya Zayats', 'Pau Pérez', 'Fran Casas', 'Jorge Morante', 'Enrico Stano', 'Adrian Serafin', 'Kirk Haines', 'Guillermo Iguaran']
|
16
|
+
spec.email = ['ilya.zayats@redbooth.com', 'pau.perez@redbooth.com', 'nflamel@gmail.com', 'jorge.morante@redbooth.com', 'adrian@softmad.pl', 'wyhaines@gmail.com', 'guilleiguaran@gmail.com']
|
13
17
|
|
14
18
|
spec.summary = %q(pt-online-schema-change runner for ActiveRecord migrations)
|
15
19
|
spec.description = %q(Execute your ActiveRecord migrations with Percona's pt-online-schema-change. Formerly known as Percona Migrator.)
|
@@ -19,12 +23,13 @@ Gem::Specification.new do |spec|
|
|
19
23
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
20
24
|
spec.require_paths = ['lib']
|
21
25
|
|
22
|
-
spec.add_runtime_dependency '
|
23
|
-
spec.add_runtime_dependency '
|
26
|
+
spec.add_runtime_dependency 'railties', *Array(RAILS_DEPENDENCY_VERSION)
|
27
|
+
spec.add_runtime_dependency 'activerecord', *Array(RAILS_DEPENDENCY_VERSION)
|
28
|
+
spec.add_runtime_dependency 'mysql2', '>= 0.4.0', '<= 0.5.4'
|
24
29
|
|
25
|
-
spec.add_development_dependency 'rake', '
|
30
|
+
spec.add_development_dependency 'rake', '>= 10.0'
|
26
31
|
spec.add_development_dependency 'rspec', '~> 3.4', '>= 3.4.0'
|
27
32
|
spec.add_development_dependency 'rspec-its', '~> 1.2'
|
28
|
-
spec.add_development_dependency 'byebug'
|
33
|
+
spec.add_development_dependency 'pry-byebug'
|
29
34
|
spec.add_development_dependency 'climate_control', '~> 0.0.3'
|
30
35
|
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'active_record/connection_adapters/mysql/schema_statements'
|
2
|
+
|
3
|
+
module ForAlterStatements
|
4
|
+
class << self
|
5
|
+
def included(_)
|
6
|
+
STDERR.puts 'Including for_alter statements'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def bulk_change_table(table_name, operations) #:nodoc:
|
11
|
+
sqls = operations.flat_map do |command, args|
|
12
|
+
table = args.shift
|
13
|
+
arguments = args
|
14
|
+
|
15
|
+
method = :"#{command}_for_alter"
|
16
|
+
|
17
|
+
raise "Unknown method called : #{method}(#{arguments.inspect})" unless respond_to?(method, true)
|
18
|
+
public_send(method, table, *arguments)
|
19
|
+
end.join(', ')
|
20
|
+
|
21
|
+
execute("ALTER TABLE #{quote_table_name(table_name)} #{sqls}")
|
22
|
+
end
|
23
|
+
|
24
|
+
def change_column_for_alter(table_name, column_name, type, options = {})
|
25
|
+
column = column_for(table_name, column_name)
|
26
|
+
type ||= column.sql_type
|
27
|
+
|
28
|
+
options = {
|
29
|
+
default: column.default,
|
30
|
+
null: column.null,
|
31
|
+
comment: column.comment
|
32
|
+
}.merge(options)
|
33
|
+
|
34
|
+
td = create_table_definition(table_name)
|
35
|
+
cd = td.new_column_definition(column.name, type, **options)
|
36
|
+
schema_creation.accept(ActiveRecord::ConnectionAdapters::ChangeColumnDefinition.new(cd, column.name))
|
37
|
+
end
|
38
|
+
|
39
|
+
def rename_column_for_alter(table_name, column_name, new_column_name)
|
40
|
+
column = column_for(table_name, column_name)
|
41
|
+
options = {
|
42
|
+
default: column.default,
|
43
|
+
null: column.null,
|
44
|
+
auto_increment: column.auto_increment?
|
45
|
+
}
|
46
|
+
|
47
|
+
columns_sql = "SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE #{quote(column_name)}"
|
48
|
+
current_type = exec_query(columns_sql, 'SCHEMA').first['Type']
|
49
|
+
td = create_table_definition(table_name)
|
50
|
+
cd = td.new_column_definition(new_column_name, current_type, **options)
|
51
|
+
schema_creation.accept(ActiveRecord::ConnectionAdapters::ChangeColumnDefinition.new(cd, column.name))
|
52
|
+
end
|
53
|
+
|
54
|
+
def add_index_for_alter(table_name, column_name, options = {})
|
55
|
+
if ActiveRecord::VERSION::STRING >= '6.1'
|
56
|
+
index_definition, = add_index_options(table_name, column_name, **options)
|
57
|
+
|
58
|
+
"ADD #{schema_creation.accept(index_definition)}"
|
59
|
+
else
|
60
|
+
index_name, index_type, index_columns, _,
|
61
|
+
index_algorithm, index_using = add_index_options(table_name, column_name, **options)
|
62
|
+
index_algorithm[0, 0] = ', ' if index_algorithm.present?
|
63
|
+
|
64
|
+
"ADD #{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns})#{index_algorithm}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def remove_index_for_alter(table_name, column_name, options = {})
|
69
|
+
index_name = index_name_for_remove(table_name, column_name, options)
|
70
|
+
"DROP INDEX #{quote_column_name(index_name)}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def add_timestamps_for_alter(table_name, options = {})
|
74
|
+
[
|
75
|
+
add_column_for_alter(table_name, :created_at, :datetime, options),
|
76
|
+
add_column_for_alter(table_name, :updated_at, :datetime, options)
|
77
|
+
]
|
78
|
+
end
|
79
|
+
|
80
|
+
def remove_timestamps_for_alter(table_name, _options = {})
|
81
|
+
[remove_column_for_alter(table_name, :updated_at), remove_column_for_alter(table_name, :created_at)]
|
82
|
+
end
|
83
|
+
|
84
|
+
def add_column_for_alter(table_name, column_name, type, options = {})
|
85
|
+
td = create_table_definition(table_name)
|
86
|
+
cd = td.new_column_definition(column_name, type, **options)
|
87
|
+
schema_creation.accept(ActiveRecord::ConnectionAdapters::AddColumnDefinition.new(cd))
|
88
|
+
end
|
89
|
+
|
90
|
+
def remove_column_for_alter(_table_name, column_name, _type = nil, _options = {})
|
91
|
+
"DROP COLUMN #{quote_column_name(column_name)}"
|
92
|
+
end
|
93
|
+
|
94
|
+
def remove_columns_for_alter(table_name, *column_names, **options)
|
95
|
+
column_names.map { |column_name| remove_column_for_alter(table_name, column_name) }
|
96
|
+
end
|
97
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'active_record/connection_adapters/abstract_mysql_adapter'
|
2
2
|
require 'active_record/connection_adapters/statement_pool'
|
3
3
|
require 'active_record/connection_adapters/mysql2_adapter'
|
4
|
+
require 'active_support/core_ext/string/filters'
|
4
5
|
require 'departure'
|
5
6
|
require 'forwardable'
|
6
7
|
|
@@ -9,7 +10,10 @@ module ActiveRecord
|
|
9
10
|
# Establishes a connection to the database that's used by all Active
|
10
11
|
# Record objects.
|
11
12
|
def percona_connection(config)
|
12
|
-
|
13
|
+
if config[:username].nil?
|
14
|
+
config = config.dup if config.frozen?
|
15
|
+
config[:username] = 'root'
|
16
|
+
end
|
13
17
|
mysql2_connection = mysql2_connection(config)
|
14
18
|
|
15
19
|
connection_details = Departure::ConnectionDetails.new(config)
|
@@ -39,18 +43,34 @@ module ActiveRecord
|
|
39
43
|
|
40
44
|
module ConnectionAdapters
|
41
45
|
class DepartureAdapter < AbstractMysqlAdapter
|
42
|
-
|
43
46
|
class Column < ActiveRecord::ConnectionAdapters::MySQL::Column
|
44
47
|
def adapter
|
45
48
|
DepartureAdapter
|
46
49
|
end
|
47
50
|
end
|
48
51
|
|
52
|
+
class SchemaCreation < ActiveRecord::ConnectionAdapters::MySQL::SchemaCreation
|
53
|
+
def visit_DropForeignKey(name) # rubocop:disable Naming/MethodName
|
54
|
+
fk_name =
|
55
|
+
if name =~ /^__(.+)/
|
56
|
+
Regexp.last_match(1)
|
57
|
+
else
|
58
|
+
"_#{name}"
|
59
|
+
end
|
60
|
+
|
61
|
+
"DROP FOREIGN KEY #{fk_name}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
49
65
|
extend Forwardable
|
50
66
|
|
67
|
+
unless method_defined?(:change_column_for_alter)
|
68
|
+
include ForAlterStatements
|
69
|
+
end
|
70
|
+
|
51
71
|
ADAPTER_NAME = 'Percona'.freeze
|
52
72
|
|
53
|
-
def_delegators :mysql_adapter, :
|
73
|
+
def_delegators :mysql_adapter, :each_hash, :set_field_encoding
|
54
74
|
|
55
75
|
def initialize(connection, _logger, connection_options, _config)
|
56
76
|
@mysql_adapter = connection_options[:mysql_adapter]
|
@@ -58,6 +78,12 @@ module ActiveRecord
|
|
58
78
|
@prepared_statements = false
|
59
79
|
end
|
60
80
|
|
81
|
+
def write_query?(sql) # :nodoc:
|
82
|
+
!ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
|
83
|
+
:desc, :describe, :set, :show, :use
|
84
|
+
).match?(sql)
|
85
|
+
end
|
86
|
+
|
61
87
|
def exec_delete(sql, name, binds)
|
62
88
|
execute(to_sql(sql, binds), name)
|
63
89
|
@connection.affected_rows
|
@@ -68,9 +94,10 @@ module ActiveRecord
|
|
68
94
|
execute(to_sql(sql, binds), name)
|
69
95
|
end
|
70
96
|
|
71
|
-
def exec_query(sql, name = 'SQL', _binds = [])
|
97
|
+
def exec_query(sql, name = 'SQL', _binds = [], **_kwargs)
|
72
98
|
result = execute(sql, name)
|
73
|
-
|
99
|
+
fields = result.fields if defined?(result.fields)
|
100
|
+
ActiveRecord::Result.new(fields, result.to_a)
|
74
101
|
end
|
75
102
|
|
76
103
|
# Executes a SELECT query and returns an array of rows. Each row is an
|
@@ -82,8 +109,8 @@ module ActiveRecord
|
|
82
109
|
|
83
110
|
# Executes a SELECT query and returns an array of record hashes with the
|
84
111
|
# column names as keys and column values as values.
|
85
|
-
def select(sql, name = nil, binds = [])
|
86
|
-
exec_query(sql, name, binds)
|
112
|
+
def select(sql, name = nil, binds = [], **kwargs)
|
113
|
+
exec_query(sql, name, binds, **kwargs)
|
87
114
|
end
|
88
115
|
|
89
116
|
# Returns true, as this adapter supports migrations
|
@@ -103,27 +130,69 @@ module ActiveRecord
|
|
103
130
|
# @param column_name [String, Symbol]
|
104
131
|
# @param options [Hash] optional
|
105
132
|
def add_index(table_name, column_name, options = {})
|
106
|
-
|
107
|
-
|
133
|
+
if ActiveRecord::VERSION::STRING >= '6.1'
|
134
|
+
index_definition, = add_index_options(table_name, column_name, **options)
|
135
|
+
execute <<-SQL.squish
|
136
|
+
ALTER TABLE #{quote_table_name(index_definition.table)}
|
137
|
+
ADD #{schema_creation.accept(index_definition)}
|
138
|
+
SQL
|
139
|
+
else
|
140
|
+
index_name, index_type, index_columns, index_options = add_index_options(table_name, column_name, **options)
|
141
|
+
execute <<-SQL.squish
|
142
|
+
ALTER TABLE #{quote_table_name(table_name)}
|
143
|
+
ADD #{index_type} INDEX
|
144
|
+
#{quote_column_name(index_name)} (#{index_columns})#{index_options}
|
145
|
+
SQL
|
146
|
+
end
|
108
147
|
end
|
109
148
|
|
110
149
|
# Remove the given index from the table.
|
111
150
|
#
|
112
151
|
# @param table_name [String, Symbol]
|
113
152
|
# @param options [Hash] optional
|
114
|
-
def remove_index(table_name,
|
115
|
-
|
153
|
+
def remove_index(table_name, column_name = nil, **options)
|
154
|
+
if ActiveRecord::VERSION::STRING >= '6.1'
|
155
|
+
return if options[:if_exists] && !index_exists?(table_name, column_name, **options)
|
156
|
+
index_name = index_name_for_remove(table_name, column_name, options)
|
157
|
+
else
|
158
|
+
index_name = index_name_for_remove(table_name, options)
|
159
|
+
end
|
160
|
+
|
116
161
|
execute "ALTER TABLE #{quote_table_name(table_name)} DROP INDEX #{quote_column_name(index_name)}"
|
117
162
|
end
|
118
163
|
|
164
|
+
def schema_creation
|
165
|
+
SchemaCreation.new(self)
|
166
|
+
end
|
167
|
+
|
168
|
+
def change_table(table_name, _options = {})
|
169
|
+
recorder = ActiveRecord::Migration::CommandRecorder.new(self)
|
170
|
+
yield update_table_definition(table_name, recorder)
|
171
|
+
bulk_change_table(table_name, recorder.commands)
|
172
|
+
end
|
173
|
+
|
119
174
|
# Returns the MySQL error number from the exception. The
|
120
175
|
# AbstractMysqlAdapter requires it to be implemented
|
121
176
|
def error_number(_exception); end
|
122
177
|
|
123
178
|
def full_version
|
179
|
+
if ActiveRecord::VERSION::MAJOR < 6
|
180
|
+
get_full_version
|
181
|
+
else
|
182
|
+
schema_cache.database_version.full_version_string
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# This is a method defined in Rails 6.0, and we have no control over the
|
187
|
+
# naming of this method.
|
188
|
+
def get_full_version # rubocop:disable Naming/AccessorMethodName
|
124
189
|
mysql_adapter.raw_connection.server_info[:version]
|
125
190
|
end
|
126
191
|
|
192
|
+
def last_inserted_id(result)
|
193
|
+
mysql_adapter.send(:last_inserted_id, result)
|
194
|
+
end
|
195
|
+
|
127
196
|
private
|
128
197
|
|
129
198
|
attr_reader :mysql_adapter
|
@@ -4,7 +4,7 @@ module Departure
|
|
4
4
|
# Represents the '--alter' argument of Percona's pt-online-schema-change
|
5
5
|
# See https://www.percona.com/doc/percona-toolkit/2.0/pt-online-schema-change.html
|
6
6
|
class AlterArgument
|
7
|
-
ALTER_TABLE_REGEX = /\AALTER TABLE
|
7
|
+
ALTER_TABLE_REGEX = /\AALTER TABLE [^\s]*[\n]* /
|
8
8
|
|
9
9
|
attr_reader :table_name
|
10
10
|
|
@@ -17,8 +17,12 @@ module Departure
|
|
17
17
|
|
18
18
|
match = statement.match(ALTER_TABLE_REGEX)
|
19
19
|
raise InvalidAlterStatement unless match
|
20
|
-
|
21
|
-
|
20
|
+
# Separates the ALTER TABLE from the table_name
|
21
|
+
#
|
22
|
+
# Removes the grave marks, if they are there, so we can get the table_name
|
23
|
+
@table_name = String(match)
|
24
|
+
.split(' ')[2]
|
25
|
+
.delete('`')
|
22
26
|
end
|
23
27
|
|
24
28
|
# Returns the '--alter' pt-online-schema-change argument as a string. See
|
@@ -38,6 +42,8 @@ module Departure
|
|
38
42
|
@parsed_statement ||= statement
|
39
43
|
.gsub(ALTER_TABLE_REGEX, '')
|
40
44
|
.gsub('`', '\\\`')
|
45
|
+
.gsub(/\\n/, '')
|
46
|
+
.gsub('"', '\\\"')
|
41
47
|
end
|
42
48
|
end
|
43
49
|
end
|
data/lib/departure/command.rb
CHANGED
@@ -8,10 +8,11 @@ module Departure
|
|
8
8
|
# @param command_line [String]
|
9
9
|
# @param error_log_path [String]
|
10
10
|
# @param logger [#write_no_newline]
|
11
|
-
def initialize(command_line, error_log_path, logger)
|
11
|
+
def initialize(command_line, error_log_path, logger, redirect_stderr)
|
12
12
|
@command_line = command_line
|
13
13
|
@error_log_path = error_log_path
|
14
14
|
@logger = logger
|
15
|
+
@redirect_stderr = redirect_stderr
|
15
16
|
end
|
16
17
|
|
17
18
|
# Executes the command returning its status. It also prints its stdout to
|
@@ -35,7 +36,7 @@ module Departure
|
|
35
36
|
|
36
37
|
private
|
37
38
|
|
38
|
-
attr_reader :command_line, :error_log_path, :logger, :status
|
39
|
+
attr_reader :command_line, :error_log_path, :logger, :status, :redirect_stderr
|
39
40
|
|
40
41
|
# Runs the command in a separate process, capturing its stdout and
|
41
42
|
# execution status
|
@@ -56,11 +57,15 @@ module Departure
|
|
56
57
|
end
|
57
58
|
|
58
59
|
# Builds the actual command including stderr redirection to the specified
|
59
|
-
# log file
|
60
|
+
# log file or stdout
|
60
61
|
#
|
61
62
|
# @return [String]
|
62
63
|
def full_command
|
63
|
-
|
64
|
+
if redirect_stderr
|
65
|
+
"#{command_line} 2> #{error_log_path}"
|
66
|
+
else
|
67
|
+
"#{command_line} 2>&1"
|
68
|
+
end
|
64
69
|
end
|
65
70
|
|
66
71
|
# Validates the status of the execution
|
@@ -1,11 +1,13 @@
|
|
1
1
|
module Departure
|
2
2
|
class Configuration
|
3
|
-
attr_accessor :tmp_path, :global_percona_args
|
3
|
+
attr_accessor :tmp_path, :global_percona_args, :enabled_by_default, :redirect_stderr
|
4
4
|
|
5
5
|
def initialize
|
6
6
|
@tmp_path = '.'.freeze
|
7
7
|
@error_log_filename = 'departure_error.log'.freeze
|
8
8
|
@global_percona_args = nil
|
9
|
+
@enabled_by_default = true
|
10
|
+
@redirect_stderr = true
|
9
11
|
end
|
10
12
|
|
11
13
|
def error_log_path
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Departure
|
2
|
+
class ConnectionBase < ActiveRecord::Base
|
3
|
+
def self.establish_connection(config = nil)
|
4
|
+
super.tap do
|
5
|
+
ActiveRecord::Base.connection_specification_name = connection_specification_name
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class OriginalAdapterConnection < ConnectionBase; end
|
11
|
+
end
|
@@ -15,7 +15,7 @@ module Departure
|
|
15
15
|
#
|
16
16
|
# @return [String]
|
17
17
|
def to_s
|
18
|
-
@to_s ||= "
|
18
|
+
@to_s ||= "#{host_argument} -P #{port} -u #{user} #{password_argument}"
|
19
19
|
end
|
20
20
|
|
21
21
|
# TODO: Doesn't the abstract adapter already handle this somehow?
|
@@ -40,6 +40,17 @@ module Departure
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
+
# Returns the host fragment of the details string, adds ssl options if needed
|
44
|
+
#
|
45
|
+
# @return [String]
|
46
|
+
def host_argument
|
47
|
+
host_string = host
|
48
|
+
if ssl_ca.present?
|
49
|
+
host_string += ";mysql_ssl=1;mysql_ssl_client_ca=#{ssl_ca}"
|
50
|
+
end
|
51
|
+
"-h \"#{host_string}\""
|
52
|
+
end
|
53
|
+
|
43
54
|
private
|
44
55
|
|
45
56
|
attr_reader :connection_data
|
@@ -74,5 +85,12 @@ module Departure
|
|
74
85
|
def port
|
75
86
|
connection_data.fetch(:port, DEFAULT_PORT)
|
76
87
|
end
|
88
|
+
|
89
|
+
# Returns the database' SSL CA certificate.
|
90
|
+
#
|
91
|
+
# @return [String]
|
92
|
+
def ssl_ca
|
93
|
+
connection_data.fetch(:sslca, nil)
|
94
|
+
end
|
77
95
|
end
|
78
96
|
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Departure
|
2
|
+
# Hooks Departure into Rails migrations by replacing the configured database
|
3
|
+
# adapter.
|
4
|
+
#
|
5
|
+
# It also patches ActiveRecord's #migrate method so that it patches LHM
|
6
|
+
# first. This will make migrations written with LHM to go through the
|
7
|
+
# regular Rails Migration DSL.
|
8
|
+
module Migration
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
included do
|
12
|
+
# Holds the name of the adapter that was configured by the app.
|
13
|
+
mattr_accessor :original_adapter
|
14
|
+
|
15
|
+
# Declare on a per-migration class basis whether or not to use Departure.
|
16
|
+
# The default for this attribute is set based on
|
17
|
+
# Departure.configuration.enabled_by_default (default true).
|
18
|
+
class_attribute :uses_departure
|
19
|
+
self.uses_departure = true
|
20
|
+
|
21
|
+
alias_method :active_record_migrate, :migrate
|
22
|
+
remove_method :migrate
|
23
|
+
end
|
24
|
+
|
25
|
+
module ClassMethods
|
26
|
+
# Declare `uses_departure!` in the class body of your migration to enable
|
27
|
+
# Departure for that migration only when
|
28
|
+
# Departure.configuration.enabled_by_default is false.
|
29
|
+
def uses_departure!
|
30
|
+
self.uses_departure = true
|
31
|
+
end
|
32
|
+
|
33
|
+
# Declare `disable_departure!` in the class body of your migration to
|
34
|
+
# disable Departure for that migration only (when
|
35
|
+
# Departure.configuration.enabled_by_default is true, the default).
|
36
|
+
def disable_departure!
|
37
|
+
self.uses_departure = false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Replaces the current connection adapter with the PerconaAdapter and
|
42
|
+
# patches LHM, then it continues with the regular migration process.
|
43
|
+
#
|
44
|
+
# @param direction [Symbol] :up or :down
|
45
|
+
def departure_migrate(direction)
|
46
|
+
reconnect_with_percona
|
47
|
+
include_foreigner if defined?(Foreigner)
|
48
|
+
|
49
|
+
::Lhm.migration = self
|
50
|
+
active_record_migrate(direction)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Migrate with or without Departure based on uses_departure class
|
54
|
+
# attribute.
|
55
|
+
def migrate(direction)
|
56
|
+
if uses_departure?
|
57
|
+
departure_migrate(direction)
|
58
|
+
else
|
59
|
+
reconnect_without_percona
|
60
|
+
active_record_migrate(direction)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Includes the Foreigner's Mysql2Adapter implemention in
|
65
|
+
# DepartureAdapter to support foreign keys
|
66
|
+
def include_foreigner
|
67
|
+
Foreigner::Adapter.safe_include(
|
68
|
+
:DepartureAdapter,
|
69
|
+
Foreigner::ConnectionAdapters::Mysql2Adapter
|
70
|
+
)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Make all connections in the connection pool to use PerconaAdapter
|
74
|
+
# instead of the current adapter.
|
75
|
+
def reconnect_with_percona
|
76
|
+
return if connection_config[:adapter] == 'percona'
|
77
|
+
Departure::ConnectionBase.establish_connection(connection_config.merge(adapter: 'percona'))
|
78
|
+
end
|
79
|
+
|
80
|
+
# Reconnect without percona adapter when Departure is disabled but was
|
81
|
+
# enabled in a previous migration.
|
82
|
+
def reconnect_without_percona
|
83
|
+
return unless connection_config[:adapter] == 'percona'
|
84
|
+
Departure::OriginalAdapterConnection.establish_connection(connection_config.merge(adapter: original_adapter))
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
# Capture the type of the adapter configured by the app if not already set.
|
90
|
+
def connection_config
|
91
|
+
configuration_hash.tap do |config|
|
92
|
+
self.class.original_adapter ||= config[:adapter]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
private def configuration_hash
|
97
|
+
if ActiveRecord::VERSION::STRING >= '6.1'
|
98
|
+
ActiveRecord::Base.connection_db_config.configuration_hash
|
99
|
+
else
|
100
|
+
ActiveRecord::Base.connection_config
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
data/lib/departure/railtie.rb
CHANGED
@@ -6,23 +6,16 @@ module Departure
|
|
6
6
|
class Railtie < Rails::Railtie
|
7
7
|
railtie_name :departure
|
8
8
|
|
9
|
-
# It drops all previous database connections and reconnects using this
|
10
|
-
# PerconaAdapter. By doing this, all later ActiveRecord methods called in
|
11
|
-
# the migration will use this adapter instead of Mysql2Adapter.
|
12
|
-
#
|
13
|
-
# It also patches ActiveRecord's #migrate method so that it patches LHM
|
14
|
-
# first. This will make migrations written with LHM to go through the
|
15
|
-
# regular Rails Migration DSL.
|
16
|
-
initializer 'departure.configure_rails_initialization' do
|
17
|
-
ActiveSupport.on_load(:active_record) do
|
18
|
-
Departure.load
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
9
|
initializer 'departure.configure' do |app|
|
23
10
|
Departure.configure do |config|
|
24
11
|
config.tmp_path = app.paths['tmp'].first
|
25
12
|
end
|
26
13
|
end
|
14
|
+
|
15
|
+
config.after_initialize do
|
16
|
+
Departure.configure do |dc|
|
17
|
+
ActiveRecord::Migration.uses_departure = dc.enabled_by_default
|
18
|
+
end
|
19
|
+
end
|
27
20
|
end
|
28
21
|
end
|
data/lib/departure/runner.rb
CHANGED
@@ -15,6 +15,7 @@ module Departure
|
|
15
15
|
@cli_generator = cli_generator
|
16
16
|
@mysql_adapter = mysql_adapter
|
17
17
|
@error_log_path = config.error_log_path
|
18
|
+
@redirect_stderr = config.redirect_stderr
|
18
19
|
end
|
19
20
|
|
20
21
|
# Executes the passed sql statement using pt-online-schema-change for ALTER
|
@@ -44,12 +45,12 @@ module Departure
|
|
44
45
|
# @param command_line [String]
|
45
46
|
# @return [Boolean]
|
46
47
|
def execute(command_line)
|
47
|
-
Command.new(command_line, error_log_path, logger).run
|
48
|
+
Command.new(command_line, error_log_path, logger, redirect_stderr).run
|
48
49
|
end
|
49
50
|
|
50
51
|
private
|
51
52
|
|
52
|
-
attr_reader :logger, :cli_generator, :mysql_adapter, :error_log_path
|
53
|
+
attr_reader :logger, :cli_generator, :mysql_adapter, :error_log_path, :redirect_stderr
|
53
54
|
|
54
55
|
# Checks whether the sql statement is an ALTER TABLE
|
55
56
|
#
|
data/lib/departure/version.rb
CHANGED
data/lib/departure.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'active_record'
|
2
2
|
require 'active_support/all'
|
3
3
|
|
4
|
+
require 'active_record/connection_adapters/for_alter'
|
5
|
+
|
4
6
|
require 'departure/version'
|
5
7
|
require 'departure/log_sanitizers/password_sanitizer'
|
6
8
|
require 'departure/runner'
|
@@ -11,12 +13,20 @@ require 'departure/logger_factory'
|
|
11
13
|
require 'departure/configuration'
|
12
14
|
require 'departure/errors'
|
13
15
|
require 'departure/command'
|
16
|
+
require 'departure/connection_base'
|
17
|
+
require 'departure/migration'
|
14
18
|
|
15
19
|
require 'departure/railtie' if defined?(Rails)
|
16
20
|
|
17
21
|
# We need the OS not to buffer the IO to see pt-osc's output while migrating
|
18
22
|
$stdout.sync = true
|
19
23
|
|
24
|
+
ActiveSupport.on_load(:active_record) do
|
25
|
+
ActiveRecord::Migration.class_eval do
|
26
|
+
include Departure::Migration
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
20
30
|
module Departure
|
21
31
|
class << self
|
22
32
|
attr_accessor :configuration
|
@@ -27,40 +37,7 @@ module Departure
|
|
27
37
|
yield(configuration)
|
28
38
|
end
|
29
39
|
|
30
|
-
# Hooks Percona Migrator into Rails migrations by replacing the configured
|
31
|
-
# database adapter
|
32
40
|
def self.load
|
33
|
-
|
34
|
-
alias_method :original_migrate, :migrate
|
35
|
-
|
36
|
-
# Replaces the current connection adapter with the PerconaAdapter and
|
37
|
-
# patches LHM, then it continues with the regular migration process.
|
38
|
-
#
|
39
|
-
# @param direction [Symbol] :up or :down
|
40
|
-
def migrate(direction)
|
41
|
-
reconnect_with_percona
|
42
|
-
include_foreigner if defined?(Foreigner)
|
43
|
-
|
44
|
-
::Lhm.migration = self
|
45
|
-
original_migrate(direction)
|
46
|
-
end
|
47
|
-
|
48
|
-
# Includes the Foreigner's Mysql2Adapter implemention in
|
49
|
-
# DepartureAdapter to support foreign keys
|
50
|
-
def include_foreigner
|
51
|
-
Foreigner::Adapter.safe_include(
|
52
|
-
:DepartureAdapter,
|
53
|
-
Foreigner::ConnectionAdapters::Mysql2Adapter
|
54
|
-
)
|
55
|
-
end
|
56
|
-
|
57
|
-
# Make all connections in the connection pool to use PerconaAdapter
|
58
|
-
# instead of the current adapter.
|
59
|
-
def reconnect_with_percona
|
60
|
-
connection_config = ActiveRecord::Base
|
61
|
-
.connection_config.merge(adapter: 'percona')
|
62
|
-
ActiveRecord::Base.establish_connection(connection_config)
|
63
|
-
end
|
64
|
-
end
|
41
|
+
# No-op left for compatibility
|
65
42
|
end
|
66
43
|
end
|
data/lib/lhm/column_with_sql.rb
CHANGED
@@ -52,7 +52,7 @@ module Lhm
|
|
52
52
|
#
|
53
53
|
# @return [column_factory]
|
54
54
|
def column
|
55
|
-
cast_type = ActiveRecord::Base.connection.lookup_cast_type
|
55
|
+
cast_type = ActiveRecord::Base.connection.send(:lookup_cast_type, definition)
|
56
56
|
metadata = ActiveRecord::ConnectionAdapters::SqlTypeMetadata.new(
|
57
57
|
type: cast_type.type,
|
58
58
|
sql_type: definition,
|
data/test_database.rb
CHANGED
@@ -6,8 +6,6 @@ require 'active_record/connection_adapters/mysql2_adapter'
|
|
6
6
|
# the tests.
|
7
7
|
#
|
8
8
|
class TestDatabase
|
9
|
-
|
10
|
-
|
11
9
|
# Constructor
|
12
10
|
#
|
13
11
|
# @param config [Hash]
|
@@ -33,10 +31,10 @@ class TestDatabase
|
|
33
31
|
# Creates the ActiveRecord's schema_migrations table required for
|
34
32
|
# migrations to work. Before, it drops the table if it already exists
|
35
33
|
def drop_and_create_schema_migrations_table
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
34
|
+
sql = [
|
35
|
+
"USE #{@database}",
|
36
|
+
'DROP TABLE IF EXISTS schema_migrations',
|
37
|
+
'CREATE TABLE schema_migrations ( version varchar(255) COLLATE utf8_unicode_ci NOT NULL, UNIQUE KEY unique_schema_migrations (version)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci'
|
40
38
|
]
|
41
39
|
|
42
40
|
run_commands(sql)
|
@@ -58,19 +56,17 @@ class TestDatabase
|
|
58
56
|
def drop_and_create_comments_table
|
59
57
|
sql = [
|
60
58
|
"USE #{@database}",
|
61
|
-
|
62
|
-
|
59
|
+
'DROP TABLE IF EXISTS comments',
|
60
|
+
'CREATE TABLE comments ( id bigint(20) NOT NULL AUTO_INCREMENT, PRIMARY KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci'
|
63
61
|
]
|
64
62
|
|
65
63
|
run_commands(sql)
|
66
64
|
end
|
67
65
|
|
68
66
|
def run_commands(sql)
|
69
|
-
conn.execute(
|
70
|
-
sql.each { |str|
|
71
|
-
|
72
|
-
}
|
73
|
-
conn.execute("COMMIT")
|
67
|
+
conn.execute('START TRANSACTION')
|
68
|
+
sql.each { |str| conn.execute(str) }
|
69
|
+
conn.execute('COMMIT')
|
74
70
|
end
|
75
71
|
|
76
72
|
def conn
|
@@ -78,6 +74,7 @@ class TestDatabase
|
|
78
74
|
host: @config['hostname'],
|
79
75
|
username: @config['username'],
|
80
76
|
password: @config['password'],
|
81
|
-
reconnect: true
|
77
|
+
reconnect: true
|
78
|
+
)
|
82
79
|
end
|
83
80
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: departure
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ilya Zayats
|
@@ -11,51 +11,96 @@ authors:
|
|
11
11
|
- Enrico Stano
|
12
12
|
- Adrian Serafin
|
13
13
|
- Kirk Haines
|
14
|
+
- Guillermo Iguaran
|
14
15
|
autorequire:
|
15
16
|
bindir: bin
|
16
17
|
cert_chain: []
|
17
|
-
date:
|
18
|
+
date: 2022-08-04 00:00:00.000000000 Z
|
18
19
|
dependencies:
|
19
20
|
- !ruby/object:Gem::Dependency
|
20
|
-
name:
|
21
|
+
name: railties
|
21
22
|
requirement: !ruby/object:Gem::Requirement
|
22
23
|
requirements:
|
23
|
-
- - "
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 5.2.0
|
27
|
+
- - "!="
|
24
28
|
- !ruby/object:Gem::Version
|
25
|
-
version:
|
29
|
+
version: 7.0.0
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '7.1'
|
26
33
|
type: :runtime
|
27
34
|
prerelease: false
|
28
35
|
version_requirements: !ruby/object:Gem::Requirement
|
29
36
|
requirements:
|
30
|
-
- - "
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 5.2.0
|
40
|
+
- - "!="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 7.0.0
|
43
|
+
- - "<"
|
31
44
|
- !ruby/object:Gem::Version
|
32
|
-
version:
|
45
|
+
version: '7.1'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: activerecord
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 5.2.0
|
53
|
+
- - "!="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 7.0.0
|
56
|
+
- - "<"
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '7.1'
|
59
|
+
type: :runtime
|
60
|
+
prerelease: false
|
61
|
+
version_requirements: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 5.2.0
|
66
|
+
- - "!="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 7.0.0
|
69
|
+
- - "<"
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '7.1'
|
33
72
|
- !ruby/object:Gem::Dependency
|
34
73
|
name: mysql2
|
35
74
|
requirement: !ruby/object:Gem::Requirement
|
36
75
|
requirements:
|
37
|
-
- - "
|
76
|
+
- - ">="
|
38
77
|
- !ruby/object:Gem::Version
|
39
78
|
version: 0.4.0
|
79
|
+
- - "<="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 0.5.4
|
40
82
|
type: :runtime
|
41
83
|
prerelease: false
|
42
84
|
version_requirements: !ruby/object:Gem::Requirement
|
43
85
|
requirements:
|
44
|
-
- - "
|
86
|
+
- - ">="
|
45
87
|
- !ruby/object:Gem::Version
|
46
88
|
version: 0.4.0
|
89
|
+
- - "<="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: 0.5.4
|
47
92
|
- !ruby/object:Gem::Dependency
|
48
93
|
name: rake
|
49
94
|
requirement: !ruby/object:Gem::Requirement
|
50
95
|
requirements:
|
51
|
-
- - "
|
96
|
+
- - ">="
|
52
97
|
- !ruby/object:Gem::Version
|
53
98
|
version: '10.0'
|
54
99
|
type: :development
|
55
100
|
prerelease: false
|
56
101
|
version_requirements: !ruby/object:Gem::Requirement
|
57
102
|
requirements:
|
58
|
-
- - "
|
103
|
+
- - ">="
|
59
104
|
- !ruby/object:Gem::Version
|
60
105
|
version: '10.0'
|
61
106
|
- !ruby/object:Gem::Dependency
|
@@ -93,25 +138,19 @@ dependencies:
|
|
93
138
|
- !ruby/object:Gem::Version
|
94
139
|
version: '1.2'
|
95
140
|
- !ruby/object:Gem::Dependency
|
96
|
-
name: byebug
|
141
|
+
name: pry-byebug
|
97
142
|
requirement: !ruby/object:Gem::Requirement
|
98
143
|
requirements:
|
99
|
-
- - "~>"
|
100
|
-
- !ruby/object:Gem::Version
|
101
|
-
version: '8.2'
|
102
144
|
- - ">="
|
103
145
|
- !ruby/object:Gem::Version
|
104
|
-
version:
|
146
|
+
version: '0'
|
105
147
|
type: :development
|
106
148
|
prerelease: false
|
107
149
|
version_requirements: !ruby/object:Gem::Requirement
|
108
150
|
requirements:
|
109
|
-
- - "~>"
|
110
|
-
- !ruby/object:Gem::Version
|
111
|
-
version: '8.2'
|
112
151
|
- - ">="
|
113
152
|
- !ruby/object:Gem::Version
|
114
|
-
version:
|
153
|
+
version: '0'
|
115
154
|
- !ruby/object:Gem::Dependency
|
116
155
|
name: climate_control
|
117
156
|
requirement: !ruby/object:Gem::Requirement
|
@@ -131,19 +170,21 @@ description: Execute your ActiveRecord migrations with Percona's pt-online-schem
|
|
131
170
|
email:
|
132
171
|
- ilya.zayats@redbooth.com
|
133
172
|
- pau.perez@redbooth.com
|
134
|
-
-
|
173
|
+
- nflamel@gmail.com
|
135
174
|
- jorge.morante@redbooth.com
|
136
175
|
- adrian@softmad.pl
|
137
176
|
- wyhaines@gmail.com
|
177
|
+
- guilleiguaran@gmail.com
|
138
178
|
executables: []
|
139
179
|
extensions: []
|
140
180
|
extra_rdoc_files: []
|
141
181
|
files:
|
142
182
|
- ".codeclimate.yml"
|
183
|
+
- ".github/workflows/test.yml"
|
143
184
|
- ".gitignore"
|
185
|
+
- ".pryrc"
|
144
186
|
- ".rspec"
|
145
187
|
- ".rubocop.yml"
|
146
|
-
- ".travis.yml"
|
147
188
|
- CHANGELOG.md
|
148
189
|
- CODE_OF_CONDUCT.md
|
149
190
|
- Dockerfile
|
@@ -159,18 +200,21 @@ files:
|
|
159
200
|
- configuration.rb
|
160
201
|
- departure.gemspec
|
161
202
|
- docker-compose.yml
|
203
|
+
- lib/active_record/connection_adapters/for_alter.rb
|
162
204
|
- lib/active_record/connection_adapters/percona_adapter.rb
|
163
205
|
- lib/departure.rb
|
164
206
|
- lib/departure/alter_argument.rb
|
165
207
|
- lib/departure/cli_generator.rb
|
166
208
|
- lib/departure/command.rb
|
167
209
|
- lib/departure/configuration.rb
|
210
|
+
- lib/departure/connection_base.rb
|
168
211
|
- lib/departure/connection_details.rb
|
169
212
|
- lib/departure/dsn.rb
|
170
213
|
- lib/departure/errors.rb
|
171
214
|
- lib/departure/log_sanitizers/password_sanitizer.rb
|
172
215
|
- lib/departure/logger.rb
|
173
216
|
- lib/departure/logger_factory.rb
|
217
|
+
- lib/departure/migration.rb
|
174
218
|
- lib/departure/null_logger.rb
|
175
219
|
- lib/departure/option.rb
|
176
220
|
- lib/departure/railtie.rb
|
@@ -201,8 +245,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
201
245
|
- !ruby/object:Gem::Version
|
202
246
|
version: '0'
|
203
247
|
requirements: []
|
204
|
-
|
205
|
-
rubygems_version: 2.4.5.2
|
248
|
+
rubygems_version: 3.3.7
|
206
249
|
signing_key:
|
207
250
|
specification_version: 4
|
208
251
|
summary: pt-online-schema-change runner for ActiveRecord migrations
|
data/.travis.yml
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
rvm:
|
3
|
-
- 2.2.8
|
4
|
-
before_install:
|
5
|
-
- sudo apt-key adv --keyserver keys.gnupg.net --recv-keys 8507EFA5
|
6
|
-
- echo "deb http://repo.percona.com/apt `lsb_release -cs` main" | sudo tee -a /etc/apt/sources.list
|
7
|
-
- sudo apt-get update -qq
|
8
|
-
- sudo apt-get install percona-toolkit
|
9
|
-
- gem update bundler
|
10
|
-
|
11
|
-
install: bin/setup
|
12
|
-
|
13
|
-
after_success:
|
14
|
-
- codeclimate-test-reporter
|