alterity 0.9.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/alterity.rb +8 -8
- data/lib/alterity/configuration.rb +20 -30
- data/lib/alterity/default_configuration.rb +15 -0
- data/lib/alterity/mysql_client_additions.rb +2 -0
- data/lib/alterity/version.rb +1 -1
- data/spec/alterity_spec.rb +3 -1
- data/spec/bin/custom_config.rb +21 -0
- data/spec/bin/rails_app_migration_test.sh +64 -3
- data/spec/bin/test_custom_config_result.rb +20 -0
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b468009cfd8631b397ea59fcb1750aada7238d5b8910f6cc492cf4778bdc2fa6
|
4
|
+
data.tar.gz: 02e17258c42233d8198ad62cf15841d6c3fe78b4b2730f64100e1771693686a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8929653022fbcec5f31c5583c619d252547928319276b020021404ad38cdbf2a2fae1861f9748009fcc97f99c0bc7a07f698397d6c8d20d41bbd96251b7a3693
|
7
|
+
data.tar.gz: ec349e1dfee9361ef937e55fe8911da437fad1c7dfc74446ff7f7ce2608943e0755f238297e5073f8786b2a6a0d9dc71c6785a1b91f1d7b04efe4b4a548a1b46
|
data/lib/alterity.rb
CHANGED
@@ -8,14 +8,14 @@ require "alterity/railtie"
|
|
8
8
|
class Alterity
|
9
9
|
class << self
|
10
10
|
def process_sql_query(sql, &block)
|
11
|
-
case sql.strip
|
12
|
-
when /^alter
|
11
|
+
case sql.tr("\n", " ").strip
|
12
|
+
when /^alter\s+table\s+(?<table>.+?)\s+(?<updates>.+)/i
|
13
13
|
execute_alter($~[:table], $~[:updates])
|
14
|
-
when /^create
|
14
|
+
when /^create\s+index\s+(?<index>.+?)\s+on\s+(?<table>.+?)\s+(?<updates>.+)/i
|
15
15
|
execute_alter($~[:table], "ADD INDEX #{$~[:index]} #{$~[:updates]}")
|
16
|
-
when /^create
|
16
|
+
when /^create\s+unique\s+index\s+(?<index>.+?)\s+on\s+(?<table>.+?)\s+(?<updates>.+)/i
|
17
17
|
execute_alter($~[:table], "ADD UNIQUE INDEX #{$~[:index]} #{$~[:updates]}")
|
18
|
-
when /^drop
|
18
|
+
when /^drop\s+index\s+(?<index>.+?)\s+on\s+(?<table>.+)/i
|
19
19
|
execute_alter($~[:table], "DROP INDEX #{$~[:index]}")
|
20
20
|
else
|
21
21
|
block.call
|
@@ -38,9 +38,9 @@ class Alterity
|
|
38
38
|
def execute_alter(table, updates)
|
39
39
|
altered_table = table.delete("`")
|
40
40
|
alter_argument = %("#{updates.gsub('"', '\\"').gsub('`', '\\\`')}")
|
41
|
-
prepared_command = config.command.call(
|
41
|
+
prepared_command = config.command.call(altered_table, alter_argument).to_s.gsub(/\n/, "\\\n")
|
42
42
|
puts "[Alterity] Will execute: #{prepared_command}"
|
43
|
-
system(prepared_command)
|
43
|
+
system(prepared_command) || raise("[Alterity] Command failed")
|
44
44
|
end
|
45
45
|
|
46
46
|
def set_database_config
|
@@ -70,7 +70,7 @@ class Alterity
|
|
70
70
|
return if config.replicas_dsns.empty?
|
71
71
|
|
72
72
|
connection.execute <<~SQL
|
73
|
-
INSERT INTO #{table} (dsn)
|
73
|
+
INSERT INTO #{table} (dsn) VALUES
|
74
74
|
#{config.replicas_dsns.map { |dsn| "('#{dsn}')" }.join(',')}
|
75
75
|
SQL
|
76
76
|
end
|
@@ -13,46 +13,36 @@ class Alterity
|
|
13
13
|
class << self
|
14
14
|
def reset_state_and_configuration
|
15
15
|
self.config = Configuration.new
|
16
|
-
|
16
|
+
class << config
|
17
|
+
def replicas(database:, table:, dsns:)
|
18
|
+
return ArgumentError.new("database & table must be present") if database.blank? || table.blank?
|
19
|
+
|
20
|
+
self.replicas_dsns_database = database
|
21
|
+
self.replicas_dsns_table = table
|
22
|
+
self.replicas_dsns = dsns.uniq.map do |dsn|
|
23
|
+
parts = dsn.split(",")
|
24
|
+
# automatically add default port
|
25
|
+
parts << "P=3306" unless parts.any? { |part| part.start_with?("P=") }
|
26
|
+
# automatically remove master
|
27
|
+
next if parts.include?("h=#{host}") && parts.include?("P=#{port}")
|
28
|
+
|
29
|
+
parts.join(",")
|
30
|
+
end.compact
|
31
|
+
end
|
32
|
+
end
|
17
33
|
|
18
|
-
|
19
|
-
|
20
|
-
pt-online-schema-change
|
21
|
-
-h #{config.host}
|
22
|
-
-P #{config.port}
|
23
|
-
-u #{config.username}
|
24
|
-
--password=#{config.password}
|
25
|
-
--execute
|
26
|
-
D=#{config.database},t=#{altered_table}
|
27
|
-
--alter #{alter_argument}
|
28
|
-
SHELL
|
29
|
-
}
|
34
|
+
self.state = CurrentState.new
|
35
|
+
load "#{__dir__}/default_configuration.rb"
|
30
36
|
end
|
31
37
|
|
32
38
|
def configure
|
33
|
-
yield
|
39
|
+
yield config
|
34
40
|
end
|
35
41
|
|
36
42
|
def command=(new_command)
|
37
43
|
config.command = new_command
|
38
44
|
end
|
39
45
|
|
40
|
-
def replicas_dsns_table(database:, table:, dsns:)
|
41
|
-
return ArgumentError.new("database & table must be present") if database.blank? || table.blank?
|
42
|
-
|
43
|
-
config.replicas_dsns_database = database
|
44
|
-
config.replicas_dsns_table = table
|
45
|
-
config.replicas_dsns = dsns.uniq.map do |dsn|
|
46
|
-
parts = dsn.split(",")
|
47
|
-
# automatically add default port
|
48
|
-
parts << "P=3306" unless parts.any? { |part| part.start_with?("P=") }
|
49
|
-
# automatically remove master
|
50
|
-
next if parts.include?("h=#{config.host}") && parts.include?("P=#{config.port}")
|
51
|
-
|
52
|
-
parts.join(",")
|
53
|
-
end.compact
|
54
|
-
end
|
55
|
-
|
56
46
|
def disable
|
57
47
|
state.disabled = true
|
58
48
|
yield
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Alterity.configure do |config|
|
4
|
+
config.command = lambda { |altered_table, alter_argument|
|
5
|
+
parts = ["pt-online-schema-change"]
|
6
|
+
parts << %(-h "#{config.host}") if config.host.present?
|
7
|
+
parts << %(-P "#{config.port}") if config.port.present?
|
8
|
+
parts << %(-u "#{config.username}") if config.username.present?
|
9
|
+
parts << %(--password "#{config.password.gsub('"', '\\"')}") if config.password.present?
|
10
|
+
parts << "--execute"
|
11
|
+
parts << "D=#{config.database},t=#{altered_table}"
|
12
|
+
parts << "--alter #{alter_argument}"
|
13
|
+
parts.join(" ")
|
14
|
+
}
|
15
|
+
end
|
data/lib/alterity/version.rb
CHANGED
data/spec/alterity_spec.rb
CHANGED
@@ -9,8 +9,10 @@ RSpec.describe Alterity do
|
|
9
9
|
["CREATE INDEX `idx_users_on_col` ON `users` (col)", "`users`", "ADD INDEX `idx_users_on_col` (col)"],
|
10
10
|
["CREATE UNIQUE INDEX `idx_users_on_col` ON `users` (col)", "`users`", "ADD UNIQUE INDEX `idx_users_on_col` (col)"],
|
11
11
|
["DROP INDEX `idx_users_on_col` ON `users`", "`users`", "DROP INDEX `idx_users_on_col`"],
|
12
|
-
["alter table users drop col", "users", "drop col"]
|
12
|
+
["alter table users drop col", "users", "drop col"],
|
13
|
+
[" ALTER TABLE\n users\n DROP col", "users", "DROP col"]
|
13
14
|
].each do |(query, expected_table, expected_updates)|
|
15
|
+
puts query.inspect
|
14
16
|
expected_block = proc {}
|
15
17
|
expect(expected_block).not_to receive(:call)
|
16
18
|
expect(Alterity).to receive(:execute_alter).with(expected_table, expected_updates)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Alterity.configure do |config|
|
4
|
+
config.command = lambda { |altered_table, alter_argument|
|
5
|
+
string = config.to_h.slice(
|
6
|
+
*%i[host port username database replicas_dsns_database replicas_dsns_table replicas_dsns]
|
7
|
+
).to_s
|
8
|
+
system("echo '#{string}' > /tmp/custom_command_result.txt")
|
9
|
+
system("echo '#{altered_table}' >> /tmp/custom_command_result.txt")
|
10
|
+
system("echo '#{alter_argument}' >> /tmp/custom_command_result.txt")
|
11
|
+
}
|
12
|
+
|
13
|
+
config.replicas(
|
14
|
+
database: "percona",
|
15
|
+
table: "replicas_dsns",
|
16
|
+
dsns: [
|
17
|
+
"h=host1",
|
18
|
+
"h=host2"
|
19
|
+
]
|
20
|
+
)
|
21
|
+
end
|
@@ -1,7 +1,68 @@
|
|
1
1
|
#!/usr/bin/env bash
|
2
2
|
|
3
|
-
set -
|
3
|
+
set -euox pipefail
|
4
|
+
|
5
|
+
unset BUNDLE_GEMFILE # because we're going to create a new rails app here and use bundler
|
4
6
|
|
5
|
-
printenv
|
6
|
-
sudo apt update
|
7
7
|
sudo apt install percona-toolkit
|
8
|
+
|
9
|
+
# Fixes: `Cannot connect to MySQL: Cannot get MySQL var character_set_server: DBD::mysql::db selectrow_array failed: Table 'performance_schema.session_variables' doesn't exist [for Statement "SHOW VARIABLES LIKE 'character_set_server'"] at /usr/local/Cellar/percona-toolkit/3.3.0/libexec/bin/pt-online-schema-change line 2415.`
|
10
|
+
mysql -h $MYSQL_HOST -u $MYSQL_USERNAME -e 'set @@global.show_compatibility_56=ON'
|
11
|
+
|
12
|
+
gem install rails -v $RAILS_VERSION
|
13
|
+
|
14
|
+
rails new testapp \
|
15
|
+
--skip-action-mailer \
|
16
|
+
--skip-action-mailbox \
|
17
|
+
--skip-action-text \
|
18
|
+
--skip-active-job \
|
19
|
+
--skip-active-storage \
|
20
|
+
--skip-puma \
|
21
|
+
--skip-action-cable \
|
22
|
+
--skip-sprockets \
|
23
|
+
--skip-spring \
|
24
|
+
--skip-listen--skip-javascript \
|
25
|
+
--skip-turbolinks \
|
26
|
+
--skip-jbuilder--skip-test \
|
27
|
+
--skip-system-test \
|
28
|
+
--skip-bootsnap \
|
29
|
+
--skip-javascript \
|
30
|
+
--skip-webpack-install
|
31
|
+
|
32
|
+
cd testapp
|
33
|
+
|
34
|
+
# Sanity check:
|
35
|
+
# echo 'gem "mysql2"' >> Gemfile
|
36
|
+
|
37
|
+
echo 'gem "alterity", path: "../"' >> Gemfile
|
38
|
+
|
39
|
+
bundle
|
40
|
+
|
41
|
+
# Local machine test
|
42
|
+
# echo 'development:
|
43
|
+
# adapter: mysql2
|
44
|
+
# database: alterity_test' > config/database.yml
|
45
|
+
# bundle e rails db:drop db:create
|
46
|
+
|
47
|
+
echo 'development:
|
48
|
+
adapter: mysql2
|
49
|
+
database: <%= ENV.fetch("MYSQL_DATABASE") %>
|
50
|
+
host: <%= ENV.fetch("MYSQL_HOST") %>
|
51
|
+
username: <%= ENV.fetch("MYSQL_USERNAME") %>' > config/database.yml
|
52
|
+
|
53
|
+
bundle e rails g model shirt
|
54
|
+
|
55
|
+
bundle e rails g migration add_color_to_shirts color:string
|
56
|
+
|
57
|
+
# Test default configuration works as expected
|
58
|
+
bundle e rails db:migrate --trace
|
59
|
+
rails runner 'Shirt.columns.map(&:name).include?("color") || exit(1)'
|
60
|
+
|
61
|
+
# Now test custom command and replication setup
|
62
|
+
cp ../spec/bin/custom_config.rb config/initializers/alterity.rb
|
63
|
+
|
64
|
+
bundle e rails g migration add_color2_to_shirts color2:string
|
65
|
+
|
66
|
+
bundle e rails db:migrate --trace
|
67
|
+
|
68
|
+
ruby ../spec/bin/test_custom_config_result.rb
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
result = File.read("/tmp/custom_command_result.txt").downcase.strip
|
4
|
+
|
5
|
+
expected_result = %({:host=>"127.0.0.1", :port=>nil, :username=>"root", :database=>"alterity_test", :replicas_dsns_database=>"percona", :replicas_dsns_table=>"replicas_dsns", :replicas_dsns=>["h=host1,P=3306", "h=host2,P=3306"]}
|
6
|
+
shirts
|
7
|
+
"ADD \\`color2\\` VARCHAR(255)").downcase.strip
|
8
|
+
|
9
|
+
puts "Expected custom config result:"
|
10
|
+
puts expected_result
|
11
|
+
p expected_result.chars.map(&:hex)
|
12
|
+
|
13
|
+
puts "Custom config result:"
|
14
|
+
puts result
|
15
|
+
p result.chars.map(&:hex)
|
16
|
+
|
17
|
+
if result != expected_result
|
18
|
+
puts "=> mismatch"
|
19
|
+
exit(1)
|
20
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alterity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Maximin
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '6.1'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '6.1'
|
41
41
|
description: Execute your ActiveRecord migrations with Percona's pt-online-schema-change.
|
42
42
|
email:
|
43
43
|
- gems@chrismaximin.com
|
@@ -47,11 +47,14 @@ extra_rdoc_files: []
|
|
47
47
|
files:
|
48
48
|
- lib/alterity.rb
|
49
49
|
- lib/alterity/configuration.rb
|
50
|
+
- lib/alterity/default_configuration.rb
|
50
51
|
- lib/alterity/mysql_client_additions.rb
|
51
52
|
- lib/alterity/railtie.rb
|
52
53
|
- lib/alterity/version.rb
|
53
54
|
- spec/alterity_spec.rb
|
55
|
+
- spec/bin/custom_config.rb
|
54
56
|
- spec/bin/rails_app_migration_test.sh
|
57
|
+
- spec/bin/test_custom_config_result.rb
|
55
58
|
- spec/spec_helper.rb
|
56
59
|
homepage: https://github.com/gumroad/alterity
|
57
60
|
licenses:
|
@@ -81,5 +84,7 @@ specification_version: 4
|
|
81
84
|
summary: Execute your ActiveRecord migrations with Percona's pt-online-schema-change.
|
82
85
|
test_files:
|
83
86
|
- spec/alterity_spec.rb
|
87
|
+
- spec/bin/custom_config.rb
|
84
88
|
- spec/bin/rails_app_migration_test.sh
|
89
|
+
- spec/bin/test_custom_config_result.rb
|
85
90
|
- spec/spec_helper.rb
|