percona_migrator 0.1.0.rc.4 → 0.1.0.rc.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9e5da0e5e83003f39f3fbfda94fd8ae258d79052
4
- data.tar.gz: 4ce4629ba354e7d4cd49345ef5298c33caef63e2
3
+ metadata.gz: e7301e478b66a555e4abe723cd9429914fba7820
4
+ data.tar.gz: fbf40c010ac9272f913b1e79285cb5f61fb11839
5
5
  SHA512:
6
- metadata.gz: 4e1956e97df24759066e4b9ded281074330720274e20a54d6ae07b9b6a64fd292555e2a1a87f7c7ba09752c6c9dc7a0a36016ea6de018de3d8d59211bd718496
7
- data.tar.gz: 11c8a7816627e264a7bd887e50c454145127519f79de24ff2433af3c77ea42a1326f773781e7748a363da053c3a6098374872a90206d2e5e3dbccb61a747f9db
6
+ metadata.gz: 39543206254ddc6f383446adca091ead90f3ac4a879dad0f7b246b8443d3bbeadc5eb95500fa26040fb8c28ef6182ad94e0620a1a4e8dd593f885f057555ed41
7
+ data.tar.gz: 011386f3f3e8866fb9db4c19c98f9e050c4899168bb5c0eb9d78ddd56451ad5eeb89caaa3973f7574f21038b89dbcda4f511353103c760f577007043e8f82af0
data/CHANGELOG.md CHANGED
@@ -6,13 +6,23 @@ Please follow the format in [Keep a Changelog](http://keepachangelog.com/)
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.1.0.rc.5] - 2016-03-29
10
+
11
+ ### Changed
12
+
13
+ - Raise a ActiveRecord::StatementInvalid on failed migration. It also provides
14
+ more detailed error message when possible such as pt-onlin-schema-change
15
+ being missing.
16
+
9
17
  ## [0.1.0.rc.4] - 2016-03-15
10
18
 
11
19
  ### Added
12
20
 
13
21
  - Support #drop_table
14
- - Support [Foreigner gem](https://github.com/matthuhiggins/foreigner) foreign
15
- keys in Rails 3 apps that use it.
22
+ - Support for foreing keys in db/schema.rb when using [Foreigner
23
+ gem](https://github.com/matthuhiggins/foreigner) in Rails 3 apps. This allows to
24
+ define foreign keys with #execute, but does not provide support for
25
+ #add_foreign_key yet.
16
26
 
17
27
  ## [0.1.0.rc.3] - 2016-03-10
18
28
 
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
+
5
+ gem "codeclimate-test-reporter", group: :test, require: nil
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # PerconaMigrator [![Build Status](https://travis-ci.org/redbooth/percona_migrator.svg?branch=master)](https://travis-ci.org/redbooth/percona_migrator)
1
+ # PerconaMigrator [![Build Status](https://travis-ci.org/redbooth/percona_migrator.svg?branch=master)](https://travis-ci.org/redbooth/percona_migrator) [![Code Climate](https://codeclimate.com/github/redbooth/percona_migrator/badges/gpa.svg)](https://codeclimate.com/github/redbooth/percona_migrator)
2
2
 
3
3
  Percona Migrator is a tool for running online and non-blocking
4
4
  DDL `ActiveRecord::Migrations` using `pt-online-schema-change` command-line tool of
data/Rakefile CHANGED
@@ -6,12 +6,12 @@ require './test_database'
6
6
 
7
7
  RSpec::Core::RakeTask.new(:spec)
8
8
 
9
- task :default => :spec
9
+ task default: :spec
10
10
 
11
11
  namespace :db do
12
12
  desc 'Create the test database'
13
13
  task :create do
14
14
  config = Configuration.new
15
- TestDatabase.new(config).create_test_database
15
+ TestDatabase.new(config).setup_test_database
16
16
  end
17
17
  end
@@ -83,7 +83,7 @@ module ActiveRecord
83
83
  def add_column(table_name, column_name, type, options = {})
84
84
  super
85
85
  command = cli_generator.generate(table_name, @sql)
86
- runner.execute(command)
86
+ log(@sql, nil) { runner.execute(command) }
87
87
  end
88
88
 
89
89
  # Removes the column(s) from the table definition
@@ -93,7 +93,7 @@ module ActiveRecord
93
93
  def remove_column(table_name, *column_names)
94
94
  super
95
95
  command = cli_generator.generate(table_name, @sql)
96
- runner.execute(command)
96
+ log(@sql, nil) { runner.execute(command) }
97
97
  end
98
98
 
99
99
  # Adds a new index to the table
@@ -106,7 +106,7 @@ module ActiveRecord
106
106
  execute "ADD #{index_type} INDEX #{quote_column_name(index_name)} (#{index_columns})#{index_options}"
107
107
 
108
108
  command = cli_generator.generate(table_name, @sql)
109
- runner.execute(command)
109
+ log(@sql, nil) { runner.execute(command) }
110
110
  end
111
111
 
112
112
  # Remove the given index from the table.
@@ -118,7 +118,7 @@ module ActiveRecord
118
118
  execute "DROP INDEX #{quote_column_name(index_name)}"
119
119
 
120
120
  command = cli_generator.generate(table_name, @sql)
121
- runner.execute(command)
121
+ log(@sql, nil) { runner.execute(command) }
122
122
  end
123
123
 
124
124
  # Records the SQL statement to be executed. This is used to then delegate
@@ -139,7 +139,7 @@ module ActiveRecord
139
139
  def percona_execute(sql, name)
140
140
  if alter_statement?(sql)
141
141
  command = cli_generator.parse_statement(sql)
142
- runner.execute(command)
142
+ log(sql, nil) { runner.execute(command) }
143
143
  else
144
144
  mysql_adapter.execute(sql, name)
145
145
  end
@@ -154,6 +154,9 @@ module ActiveRecord
154
154
  yield mysql_adapter.execute(sql, name)
155
155
  end
156
156
 
157
+ def error_number(exception)
158
+ end
159
+
157
160
  private
158
161
 
159
162
  attr_reader :mysql_adapter, :logger, :runner, :cli_generator
@@ -47,7 +47,7 @@ module PerconaMigrator
47
47
  end
48
48
 
49
49
  # Generates the percona command. Fills all the connection credentials from
50
- # the current AR connection, but that can amended via ENV-vars:
50
+ # the current AR connection, but that can be amended via ENV-vars:
51
51
  # PERCONA_DB_HOST, PERCONA_DB_USER, PERCONA_DB_PASSWORD, PERCONA_DB_NAME
52
52
  # Table name can't not be amended, it populates automatically from the
53
53
  # migration data
@@ -59,7 +59,7 @@ module PerconaMigrator
59
59
  alter_argument = AlterArgument.new(statement)
60
60
  dsn = DSN.new(database, table_name)
61
61
 
62
- "#{to_s} #{dsn} #{alter_argument}"
62
+ "#{self} #{dsn} #{alter_argument}"
63
63
  end
64
64
 
65
65
  # Generates the percona command for a raw MySQL statement. Fills all the
@@ -74,7 +74,7 @@ module PerconaMigrator
74
74
  alter_argument = AlterArgument.new(statement)
75
75
  dsn = DSN.new(database, alter_argument.table_name)
76
76
 
77
- "#{to_s} #{dsn} #{alter_argument}"
77
+ "#{self} #{dsn} #{alter_argument}"
78
78
  end
79
79
 
80
80
  private
@@ -1,23 +1,48 @@
1
1
  require 'open3'
2
2
 
3
3
  module PerconaMigrator
4
+ class Error < StandardError; end
5
+
6
+ # Used when for whatever reason we couldn't get the spawned process'
7
+ # status.
8
+ class NoStatusError < Error
9
+ def message
10
+ 'Status could not be retrieved'.freeze
11
+ end
12
+ end
13
+
14
+ # Used when the spawned process failed by receiving a signal.
15
+ # pt-online-schema-change returns "SIGSEGV (signal 11)" on failures.
16
+ class SignalError < Error
17
+ attr_reader :status
18
+
19
+ # Constructor
20
+ #
21
+ # @param status [Process::Status]
22
+ def initialize(status)
23
+ super
24
+ @status = status
25
+ end
26
+
27
+ def message
28
+ status.to_s
29
+ end
30
+ end
31
+
32
+ class CommandNotFoundError < Error
33
+ def message
34
+ 'Please install pt-online-schema-change. Check: https://www.percona.com/doc/percona-toolkit for further details'
35
+ end
36
+ end
4
37
 
5
38
  # It executes pt-online-schema-change commands in a new process and gets its
6
39
  # output and status
7
40
  class Runner
41
+ COMMAND_NOT_FOUND = 127
8
42
 
9
43
  NONE = "\e[0m"
10
44
  CYAN = "\e[38;5;86m"
11
45
  GREEN = "\e[32m"
12
- RED = "\e[31m"
13
-
14
- # Executes the given command printing the output to the logger
15
- #
16
- # @param command [String]
17
- # @param logger [IO]
18
- def self.execute(command, logger)
19
- new(command, logger).execute
20
- end
21
46
 
22
47
  # Constructor
23
48
  #
@@ -33,11 +58,7 @@ module PerconaMigrator
33
58
  # @return [Boolean]
34
59
  def execute(command)
35
60
  @command = command
36
-
37
- log_started
38
- run_command
39
- log_finished
40
-
61
+ logging { run_command }
41
62
  status
42
63
  end
43
64
 
@@ -45,6 +66,15 @@ module PerconaMigrator
45
66
 
46
67
  attr_reader :command, :logger, :status
47
68
 
69
+ # Logs the start and end of the execution
70
+ #
71
+ # @yield
72
+ def logging
73
+ log_started
74
+ yield
75
+ log_finished
76
+ end
77
+
48
78
  # TODO: log as a migration logger subitem
49
79
  #
50
80
  # Logs when the execution started
@@ -56,33 +86,24 @@ module PerconaMigrator
56
86
  #
57
87
  # @raise [Errno::ENOENT] if pt-online-schema-change can't be found
58
88
  def run_command
59
- Open3.popen2(command) do |_stdin, stdout, process|
60
- @status = process.value
61
- logger.info stdout.read
62
- end
63
-
64
- if status.nil?
65
- Kernel.warn("Error running '#{command}': status could not be retrieved")
89
+ message = nil
90
+ Open3.popen3(command) do |_stdin, stdout, stderr, waith_thr|
91
+ @status = waith_thr.value
92
+ message = stderr.read
93
+ logger.info(stdout.read)
66
94
  end
67
95
 
68
- if status && status.signaled?
69
- Kernel.warn("Error running '#{command}': #{status.to_s}")
70
- end
96
+ raise NoStatusError if status.nil?
97
+ raise SignalError.new(status) if status.signaled?
98
+ raise CommandNotFoundError if status.exitstatus == COMMAND_NOT_FOUND
71
99
 
72
- rescue Errno::ENOENT
73
- raise Errno::ENOENT, "Please install pt-online-schema-change. Check: https://www.percona.com/doc/percona-toolkit"
100
+ raise Error, message unless status.success?
74
101
  end
75
102
 
76
- # Logs the status of the execution once it's finished
103
+ # Logs the status of the execution once it's finished. At this point we
104
+ # know it's a success
77
105
  def log_finished
78
- return unless status
79
-
80
- value = status.exitstatus
81
- return unless value
82
-
83
- message = value.zero? ? "#{GREEN}Done!#{NONE}" : "#{RED}Failed!#{NONE}"
84
-
85
- logger.info("\n#{message}")
106
+ logger.info("\n#{GREEN}Done!#{NONE}")
86
107
  end
87
108
  end
88
109
  end
@@ -1,3 +1,3 @@
1
1
  module PerconaMigrator
2
- VERSION = '0.1.0.rc.4'.freeze
2
+ VERSION = '0.1.0.rc.5'.freeze
3
3
  end
data/test_database.rb CHANGED
@@ -1,17 +1,33 @@
1
+ # Setups the test database with the schema_migrations table that ActiveRecord
2
+ # requires for the migrations, plus a table for the Comment model used throught
3
+ # the tests.
4
+ #
1
5
  class TestDatabase
6
+
7
+ # Constructor
8
+ #
9
+ # @param config [Hash]
2
10
  def initialize(config)
3
11
  @config = config
4
12
  end
5
13
 
6
- # Creates the percona_migrator_test database and comments table in it
7
- def create_test_database
8
- %x(#{mysql_command} "DROP DATABASE IF EXISTS percona_migrator_test; CREATE DATABASE percona_migrator_test DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci")
9
- %x(#{mysql_command} "USE percona_migrator_test; DROP TABLE IF EXISTS comments; CREATE TABLE comments (id int(12) NOT NULL AUTO_INCREMENT, PRIMARY KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;")
14
+ # Creates the test database, the schema_migrations and the comments tables.
15
+ # It drops any of them if they already exist
16
+ def setup
17
+ setup_test_database
18
+ drop_and_create_schema_migrations_table
19
+ end
20
+
21
+ # Creates the percona_migrator_test database and the comments table in it.
22
+ # Before, it drops both if they already exist
23
+ def setup_test_database
24
+ drop_and_create_test_database
25
+ drop_and_create_comments_table
10
26
  end
11
27
 
12
28
  # Creates the ActiveRecord's schema_migrations table required for
13
- # migrations to work
14
- def create_schema_migrations_table
29
+ # migrations to work. Before, it drops the table if it already exists
30
+ def drop_and_create_schema_migrations_table
15
31
  %x(#{mysql_command} "USE percona_migrator_test; DROP TABLE IF EXISTS schema_migrations; 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")
16
32
  end
17
33
 
@@ -19,6 +35,16 @@ class TestDatabase
19
35
 
20
36
  attr_reader :config
21
37
 
38
+ def drop_and_create_test_database
39
+ %x(#{mysql_command} "DROP DATABASE IF EXISTS percona_migrator_test; CREATE DATABASE percona_migrator_test DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci;")
40
+ end
41
+
42
+ def drop_and_create_comments_table
43
+ %x(#{mysql_command} "USE percona_migrator_test; DROP TABLE IF EXISTS comments; CREATE TABLE comments ( id int(12) NOT NULL AUTO_INCREMENT, PRIMARY KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;")
44
+ end
45
+
46
+ # Returns the command to run the mysql client. It uses the crendentials from
47
+ # the provided config
22
48
  def mysql_command
23
49
  "mysql --user=#{config['username']} --password=#{config['password']} -e"
24
50
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: percona_migrator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.rc.4
4
+ version: 0.1.0.rc.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ilya Zayats
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-03-15 00:00:00.000000000 Z
13
+ date: 2016-03-29 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rails