departure 4.0.1 → 6.3.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 +5 -5
- data/.codeclimate.yml +8 -0
- data/.gitignore +1 -0
- data/.pryrc +11 -0
- data/.rubocop.yml +60 -0
- data/.travis.yml +19 -2
- data/CHANGELOG.md +56 -0
- data/Dockerfile +32 -0
- data/Gemfile +2 -1
- data/LICENSE.txt +2 -1
- data/README.md +56 -15
- data/RELEASING.md +1 -1
- data/bin/console +3 -3
- data/bin/rspec +6 -7
- data/config.yml.erb +4 -0
- data/configuration.rb +3 -2
- data/departure.gemspec +14 -9
- data/docker-compose.yml +23 -0
- data/lib/active_record/connection_adapters/for_alter.rb +91 -0
- data/lib/active_record/connection_adapters/percona_adapter.rb +75 -17
- data/lib/departure.rb +11 -49
- data/lib/departure/alter_argument.rb +10 -4
- data/lib/departure/cli_generator.rb +2 -3
- data/lib/departure/command.rb +3 -3
- data/lib/departure/configuration.rb +2 -1
- data/lib/departure/connection_base.rb +9 -0
- data/lib/departure/connection_details.rb +29 -3
- data/lib/departure/dsn.rb +0 -2
- data/lib/departure/log_sanitizers/password_sanitizer.rb +2 -1
- data/lib/departure/logger.rb +1 -2
- data/lib/departure/logger_factory.rb +0 -1
- data/lib/departure/migration.rb +104 -0
- data/lib/departure/option.rb +4 -4
- data/lib/departure/railtie.rb +6 -13
- data/lib/departure/runner.rb +0 -2
- data/lib/departure/version.rb +1 -1
- data/lib/lhm.rb +1 -3
- data/lib/lhm/adapter.rb +1 -3
- data/lib/lhm/column_with_sql.rb +8 -4
- data/lib/lhm/column_with_type.rb +0 -2
- data/test_database.rb +37 -9
- metadata +55 -33
- data/config.yml +0 -3
data/departure.gemspec
CHANGED
@@ -1,30 +1,35 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
|
2
3
|
lib = File.expand_path('../lib', __FILE__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
|
5
6
|
require 'departure/version'
|
6
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', '<= 6.1'])
|
11
|
+
|
7
12
|
Gem::Specification.new do |spec|
|
8
13
|
spec.name = 'departure'
|
9
14
|
spec.version = Departure::VERSION
|
10
|
-
spec.authors = ['Ilya Zayats', 'Pau Pérez', 'Fran Casas', 'Jorge Morante', 'Enrico Stano', 'Adrian Serafin']
|
11
|
-
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']
|
12
17
|
|
13
|
-
spec.summary = %q
|
14
|
-
spec.description = %q
|
15
|
-
spec.homepage = '
|
18
|
+
spec.summary = %q(pt-online-schema-change runner for ActiveRecord migrations)
|
19
|
+
spec.description = %q(Execute your ActiveRecord migrations with Percona's pt-online-schema-change. Formerly known as Percona Migrator.)
|
20
|
+
spec.homepage = 'https://github.com/departurerb/departure'
|
16
21
|
spec.license = 'MIT'
|
17
22
|
|
18
23
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
24
|
spec.require_paths = ['lib']
|
20
25
|
|
21
|
-
spec.add_runtime_dependency '
|
22
|
-
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.3'
|
23
29
|
|
24
|
-
spec.add_development_dependency 'bundler', '~> 1.10'
|
25
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
|
data/docker-compose.yml
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
version: '2'
|
2
|
+
services:
|
3
|
+
db:
|
4
|
+
image: mysql/mysql-server
|
5
|
+
ports:
|
6
|
+
- "3306:3306"
|
7
|
+
environment:
|
8
|
+
MYSQL_DATABASE: departure_test
|
9
|
+
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
|
10
|
+
MYSQL_ROOT_HOST: '%'
|
11
|
+
rails:
|
12
|
+
build: .
|
13
|
+
links:
|
14
|
+
- db
|
15
|
+
depends_on:
|
16
|
+
- db
|
17
|
+
tty: true
|
18
|
+
stdin_open: true
|
19
|
+
environment:
|
20
|
+
PERCONA_DB_USER: root
|
21
|
+
PERCONA_DB_HOST: db
|
22
|
+
PERCONA_DB_PASSWORD:
|
23
|
+
PERCONA_DB_NAME: departure_test
|
@@ -0,0 +1,91 @@
|
|
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
|
+
index_name, index_type, index_columns, _,
|
56
|
+
index_algorithm, index_using = add_index_options(table_name, column_name, options)
|
57
|
+
|
58
|
+
index_algorithm[0, 0] = ', ' if index_algorithm.present?
|
59
|
+
"ADD #{index_type} INDEX #{quote_column_name(index_name)} #{index_using} (#{index_columns})#{index_algorithm}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def remove_index_for_alter(table_name, options = {})
|
63
|
+
index_name = index_name_for_remove(table_name, options)
|
64
|
+
"DROP INDEX #{quote_column_name(index_name)}"
|
65
|
+
end
|
66
|
+
|
67
|
+
def add_timestamps_for_alter(table_name, options = {})
|
68
|
+
[
|
69
|
+
add_column_for_alter(table_name, :created_at, :datetime, options),
|
70
|
+
add_column_for_alter(table_name, :updated_at, :datetime, options)
|
71
|
+
]
|
72
|
+
end
|
73
|
+
|
74
|
+
def remove_timestamps_for_alter(table_name, _options = {})
|
75
|
+
[remove_column_for_alter(table_name, :updated_at), remove_column_for_alter(table_name, :created_at)]
|
76
|
+
end
|
77
|
+
|
78
|
+
def add_column_for_alter(table_name, column_name, type, options = {})
|
79
|
+
td = create_table_definition(table_name)
|
80
|
+
cd = td.new_column_definition(column_name, type, options)
|
81
|
+
schema_creation.accept(ActiveRecord::ConnectionAdapters::AddColumnDefinition.new(cd))
|
82
|
+
end
|
83
|
+
|
84
|
+
def remove_column_for_alter(_table_name, column_name, _type = nil, _options = {})
|
85
|
+
"DROP COLUMN #{quote_column_name(column_name)}"
|
86
|
+
end
|
87
|
+
|
88
|
+
def remove_columns_for_alter(table_name, *column_names)
|
89
|
+
column_names.map { |column_name| remove_column_for_alter(table_name, column_name) }
|
90
|
+
end
|
91
|
+
end
|
@@ -9,10 +9,12 @@ module ActiveRecord
|
|
9
9
|
# Establishes a connection to the database that's used by all Active
|
10
10
|
# Record objects.
|
11
11
|
def percona_connection(config)
|
12
|
+
if config[:username].nil?
|
13
|
+
config = config.dup if config.frozen?
|
14
|
+
config[:username] = 'root'
|
15
|
+
end
|
12
16
|
mysql2_connection = mysql2_connection(config)
|
13
17
|
|
14
|
-
config[:username] = 'root' if config[:username].nil?
|
15
|
-
|
16
18
|
connection_details = Departure::ConnectionDetails.new(config)
|
17
19
|
verbose = ActiveRecord::Migration.verbose
|
18
20
|
sanitizers = [
|
@@ -40,32 +42,54 @@ module ActiveRecord
|
|
40
42
|
|
41
43
|
module ConnectionAdapters
|
42
44
|
class DepartureAdapter < AbstractMysqlAdapter
|
43
|
-
|
44
|
-
class Column < AbstractMysqlAdapter::Column
|
45
|
+
class Column < ActiveRecord::ConnectionAdapters::MySQL::Column
|
45
46
|
def adapter
|
46
47
|
DepartureAdapter
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
51
|
+
class SchemaCreation < ActiveRecord::ConnectionAdapters::MySQL::SchemaCreation
|
52
|
+
def visit_DropForeignKey(name) # rubocop:disable Naming/MethodName
|
53
|
+
fk_name =
|
54
|
+
if name =~ /^__(.+)/
|
55
|
+
Regexp.last_match(1)
|
56
|
+
else
|
57
|
+
"_#{name}"
|
58
|
+
end
|
59
|
+
|
60
|
+
"DROP FOREIGN KEY #{fk_name}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
50
64
|
extend Forwardable
|
51
65
|
|
66
|
+
unless method_defined?(:change_column_for_alter)
|
67
|
+
include ForAlterStatements
|
68
|
+
end
|
69
|
+
|
52
70
|
ADAPTER_NAME = 'Percona'.freeze
|
53
71
|
|
54
72
|
def_delegators :mysql_adapter, :last_inserted_id, :each_hash, :set_field_encoding
|
55
73
|
|
56
74
|
def initialize(connection, _logger, connection_options, _config)
|
75
|
+
@mysql_adapter = connection_options[:mysql_adapter]
|
57
76
|
super
|
58
77
|
@prepared_statements = false
|
59
|
-
|
78
|
+
end
|
79
|
+
|
80
|
+
def write_query?(sql) # :nodoc:
|
81
|
+
!ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
|
82
|
+
:desc, :describe, :set, :show, :use
|
83
|
+
).match?(sql)
|
60
84
|
end
|
61
85
|
|
62
86
|
def exec_delete(sql, name, binds)
|
63
87
|
execute(to_sql(sql, binds), name)
|
64
88
|
@connection.affected_rows
|
65
89
|
end
|
66
|
-
alias
|
90
|
+
alias exec_update exec_delete
|
67
91
|
|
68
|
-
def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
|
92
|
+
def exec_insert(sql, name, binds, pk = nil, sequence_name = nil) # rubocop:disable Lint/UnusedMethodArgument, Metrics/LineLength
|
69
93
|
execute(to_sql(sql, binds), name)
|
70
94
|
end
|
71
95
|
|
@@ -76,8 +100,9 @@ module ActiveRecord
|
|
76
100
|
|
77
101
|
# Executes a SELECT query and returns an array of rows. Each row is an
|
78
102
|
# array of field values.
|
79
|
-
|
80
|
-
|
103
|
+
|
104
|
+
def select_rows(arel, name = nil, binds = [])
|
105
|
+
select_all(arel, name, binds).rows
|
81
106
|
end
|
82
107
|
|
83
108
|
# Executes a SELECT query and returns an array of record hashes with the
|
@@ -91,9 +116,11 @@ module ActiveRecord
|
|
91
116
|
true
|
92
117
|
end
|
93
118
|
|
94
|
-
|
95
|
-
|
119
|
+
# rubocop:disable Metrics/ParameterLists
|
120
|
+
def new_column(field, default, type_metadata, null, table_name, default_function, collation, comment)
|
121
|
+
Column.new(field, default, type_metadata, null, table_name, default_function, collation, comment)
|
96
122
|
end
|
123
|
+
# rubocop:enable Metrics/ParameterLists
|
97
124
|
|
98
125
|
# Adds a new index to the table
|
99
126
|
#
|
@@ -101,25 +128,56 @@ module ActiveRecord
|
|
101
128
|
# @param column_name [String, Symbol]
|
102
129
|
# @param options [Hash] optional
|
103
130
|
def add_index(table_name, column_name, options = {})
|
104
|
-
|
105
|
-
|
131
|
+
if ActiveRecord::VERSION::STRING >= '6.1'
|
132
|
+
index, algorithm, if_not_exists = add_index_options(table_name, column_name, options)
|
133
|
+
create_index = CreateIndexDefinition.new(index, algorithm, if_not_exists)
|
134
|
+
execute schema_creation.accept(create_index)
|
135
|
+
else
|
136
|
+
index_name, index_type, index_columns, index_options = add_index_options(table_name, column_name, options)
|
137
|
+
execute "ALTER TABLE #{quote_table_name(table_name)} ADD #{index_type} INDEX #{quote_column_name(index_name)} (#{index_columns})#{index_options}" # rubocop:disable Metrics/LineLength
|
138
|
+
end
|
106
139
|
end
|
107
140
|
|
108
141
|
# Remove the given index from the table.
|
109
142
|
#
|
110
143
|
# @param table_name [String, Symbol]
|
111
144
|
# @param options [Hash] optional
|
112
|
-
def remove_index(table_name, options
|
113
|
-
|
145
|
+
def remove_index(table_name, *args, **options)
|
146
|
+
column_name = args.first
|
147
|
+
if column_name
|
148
|
+
return if options[:if_exists] && !index_exists?(table_name, column_name, **options)
|
149
|
+
index_name = index_name_for_remove(table_name, column_name, **options)
|
150
|
+
else
|
151
|
+
index_name = index_name_for_remove(table_name, options)
|
152
|
+
end
|
114
153
|
execute "ALTER TABLE #{quote_table_name(table_name)} DROP INDEX #{quote_column_name(index_name)}"
|
115
154
|
end
|
116
155
|
|
156
|
+
def schema_creation
|
157
|
+
SchemaCreation.new(self)
|
158
|
+
end
|
159
|
+
|
160
|
+
def change_table(table_name, _options = {})
|
161
|
+
recorder = ActiveRecord::Migration::CommandRecorder.new(self)
|
162
|
+
yield update_table_definition(table_name, recorder)
|
163
|
+
bulk_change_table(table_name, recorder.commands)
|
164
|
+
end
|
165
|
+
|
117
166
|
# Returns the MySQL error number from the exception. The
|
118
167
|
# AbstractMysqlAdapter requires it to be implemented
|
119
|
-
def error_number(_exception)
|
120
|
-
end
|
168
|
+
def error_number(_exception); end
|
121
169
|
|
122
170
|
def full_version
|
171
|
+
if ActiveRecord::VERSION::MAJOR < 6
|
172
|
+
get_full_version
|
173
|
+
else
|
174
|
+
schema_cache.database_version.full_version_string
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
# This is a method defined in Rails 6.0, and we have no control over the
|
179
|
+
# naming of this method.
|
180
|
+
def get_full_version # rubocop:disable Naming/AccessorMethodName
|
123
181
|
mysql_adapter.raw_connection.server_info[:version]
|
124
182
|
end
|
125
183
|
|
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,55 +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
|
-
class << self
|
35
|
-
alias_method(:original_migrate, :migrate)
|
36
|
-
end
|
37
|
-
|
38
|
-
# Checks whether arguments are being passed through PERCONA_ARGS when running
|
39
|
-
# the db:migrate rake task
|
40
|
-
#
|
41
|
-
# @raise [ArgumentsNotSupported] if PERCONA_ARGS has any value
|
42
|
-
def migrate(migrations_paths, target_version = nil, &block)
|
43
|
-
raise ArgumentsNotSupported if ENV['PERCONA_ARGS'].present?
|
44
|
-
original_migrate(migrations_paths, target_version, &block)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
ActiveRecord::Migration.class_eval do
|
49
|
-
alias_method :original_migrate, :migrate
|
50
|
-
|
51
|
-
# Replaces the current connection adapter with the PerconaAdapter and
|
52
|
-
# patches LHM, then it continues with the regular migration process.
|
53
|
-
#
|
54
|
-
# @param direction [Symbol] :up or :down
|
55
|
-
def migrate(direction)
|
56
|
-
reconnect_with_percona
|
57
|
-
include_foreigner if defined?(Foreigner)
|
58
|
-
|
59
|
-
::Lhm.migration = self
|
60
|
-
original_migrate(direction)
|
61
|
-
end
|
62
|
-
|
63
|
-
# Includes the Foreigner's Mysql2Adapter implemention in
|
64
|
-
# DepartureAdapter to support foreign keys
|
65
|
-
def include_foreigner
|
66
|
-
Foreigner::Adapter.safe_include(
|
67
|
-
:DepartureAdapter,
|
68
|
-
Foreigner::ConnectionAdapters::Mysql2Adapter
|
69
|
-
)
|
70
|
-
end
|
71
|
-
|
72
|
-
# Make all connections in the connection pool to use PerconaAdapter
|
73
|
-
# instead of the current adapter.
|
74
|
-
def reconnect_with_percona
|
75
|
-
connection_config = ActiveRecord::Base
|
76
|
-
.connection_config.merge(adapter: 'percona')
|
77
|
-
ActiveRecord::Base.establish_connection(connection_config)
|
78
|
-
end
|
79
|
-
end
|
41
|
+
# No-op left for compatibility
|
80
42
|
end
|
81
43
|
end
|
@@ -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
|
@@ -37,7 +41,9 @@ module Departure
|
|
37
41
|
def parsed_statement
|
38
42
|
@parsed_statement ||= statement
|
39
43
|
.gsub(ALTER_TABLE_REGEX, '')
|
40
|
-
.gsub('`','\\\`')
|
44
|
+
.gsub('`', '\\\`')
|
45
|
+
.gsub(/\\n/, '')
|
46
|
+
.gsub('"', '\\\"')
|
41
47
|
end
|
42
48
|
end
|
43
49
|
end
|
@@ -5,12 +5,11 @@ require 'departure/connection_details'
|
|
5
5
|
require 'departure/user_options'
|
6
6
|
|
7
7
|
module Departure
|
8
|
-
|
9
8
|
# Generates the equivalent Percona's pt-online-schema-change command to the
|
10
9
|
# given SQL statement
|
11
10
|
#
|
12
|
-
# --no-check-alter is used to allow running CHANGE COLUMN statements. For
|
13
|
-
#
|
11
|
+
# --no-check-alter is used to allow running CHANGE COLUMN statements. For more details, check:
|
12
|
+
# www.percona.com/doc/percona-toolkit/2.2/pt-online-schema-change.html#cmdoption-pt-online-schema-change--[no]check-alter # rubocop:disable Metrics/LineLength
|
14
13
|
#
|
15
14
|
class CliGenerator
|
16
15
|
COMMAND_NAME = 'pt-online-schema-change'.freeze
|