lhm 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +5 -13
  2. data/.rubocop.yml +256 -0
  3. data/.travis.yml +2 -3
  4. data/CHANGELOG.md +21 -0
  5. data/README.md +30 -3
  6. data/Rakefile +2 -2
  7. data/bin/lhm-config.sh +7 -0
  8. data/bin/lhm-kill-queue +13 -15
  9. data/bin/lhm-spec-clobber.sh +1 -1
  10. data/bin/lhm-spec-grants.sh +2 -2
  11. data/bin/lhm-spec-setup-cluster.sh +1 -1
  12. data/gemfiles/ar-2.3_mysql.gemfile +1 -0
  13. data/lhm.gemspec +6 -6
  14. data/lib/lhm.rb +20 -8
  15. data/lib/lhm/atomic_switcher.rb +2 -1
  16. data/lib/lhm/chunker.rb +19 -19
  17. data/lib/lhm/command.rb +1 -1
  18. data/lib/lhm/connection.rb +12 -0
  19. data/lib/lhm/entangler.rb +5 -5
  20. data/lib/lhm/intersection.rb +29 -16
  21. data/lib/lhm/invoker.rb +3 -3
  22. data/lib/lhm/locked_switcher.rb +6 -6
  23. data/lib/lhm/migration.rb +5 -4
  24. data/lib/lhm/migrator.rb +39 -10
  25. data/lib/lhm/printer.rb +4 -6
  26. data/lib/lhm/sql_helper.rb +4 -4
  27. data/lib/lhm/table.rb +12 -12
  28. data/lib/lhm/version.rb +1 -1
  29. data/spec/fixtures/users.ddl +1 -1
  30. data/spec/integration/atomic_switcher_spec.rb +7 -7
  31. data/spec/integration/chunker_spec.rb +2 -2
  32. data/spec/integration/cleanup_spec.rb +34 -10
  33. data/spec/integration/entangler_spec.rb +11 -11
  34. data/spec/integration/integration_helper.rb +10 -3
  35. data/spec/integration/lhm_spec.rb +96 -46
  36. data/spec/integration/locked_switcher_spec.rb +7 -7
  37. data/spec/integration/table_spec.rb +15 -15
  38. data/spec/test_helper.rb +4 -4
  39. data/spec/unit/atomic_switcher_spec.rb +6 -6
  40. data/spec/unit/chunker_spec.rb +22 -9
  41. data/spec/unit/entangler_spec.rb +19 -19
  42. data/spec/unit/intersection_spec.rb +27 -15
  43. data/spec/unit/lhm_spec.rb +6 -6
  44. data/spec/unit/locked_switcher_spec.rb +14 -14
  45. data/spec/unit/migration_spec.rb +6 -6
  46. data/spec/unit/migrator_spec.rb +53 -41
  47. data/spec/unit/printer_spec.rb +7 -7
  48. data/spec/unit/sql_helper_spec.rb +10 -10
  49. data/spec/unit/table_spec.rb +11 -11
  50. data/spec/unit/throttler_spec.rb +12 -12
  51. metadata +12 -10
@@ -12,30 +12,30 @@ describe Lhm::LockedSwitcher do
12
12
 
13
13
  before(:each) { connect_master! }
14
14
 
15
- describe "switching" do
15
+ describe 'switching' do
16
16
  before(:each) do
17
- @origin = table_create("origin")
18
- @destination = table_create("destination")
17
+ @origin = table_create('origin')
18
+ @destination = table_create('destination')
19
19
  @migration = Lhm::Migration.new(@origin, @destination)
20
20
  end
21
21
 
22
- it "rename origin to archive" do
22
+ it 'rename origin to archive' do
23
23
  switcher = Lhm::LockedSwitcher.new(@migration, connection)
24
24
  switcher.run
25
25
 
26
26
  slave do
27
27
  table_exists?(@origin).must_equal true
28
- table_read(@migration.archive_name).columns.keys.must_include "origin"
28
+ table_read(@migration.archive_name).columns.keys.must_include 'origin'
29
29
  end
30
30
  end
31
31
 
32
- it "rename destination to origin" do
32
+ it 'rename destination to origin' do
33
33
  switcher = Lhm::LockedSwitcher.new(@migration, connection)
34
34
  switcher.run
35
35
 
36
36
  slave do
37
37
  table_exists?(@destination).must_equal false
38
- table_read(@origin.name).columns.keys.must_include "destination"
38
+ table_read(@origin.name).columns.keys.must_include 'destination'
39
39
  end
40
40
  end
41
41
  end
@@ -8,38 +8,38 @@ describe Lhm::Table do
8
8
  include IntegrationHelper
9
9
 
10
10
  describe Lhm::Table::Parser do
11
- describe "create table parsing" do
11
+ describe 'create table parsing' do
12
12
  before(:each) do
13
13
  connect_master!
14
14
  @table = table_create(:users)
15
15
  end
16
16
 
17
- it "should parse table name in show create table" do
18
- @table.name.must_equal("users")
17
+ it 'should parse table name in show create table' do
18
+ @table.name.must_equal('users')
19
19
  end
20
20
 
21
- it "should parse primary key" do
22
- @table.pk.must_equal("id")
21
+ it 'should parse primary key' do
22
+ @table.pk.must_equal('id')
23
23
  end
24
24
 
25
- it "should parse column type in show create table" do
26
- @table.columns["username"][:type].must_equal("varchar(255)")
25
+ it 'should parse column type in show create table' do
26
+ @table.columns['username'][:type].must_equal('varchar(255)')
27
27
  end
28
28
 
29
- it "should parse column metadata" do
30
- @table.columns["username"][:column_default].must_equal nil
29
+ it 'should parse column metadata' do
30
+ @table.columns['username'][:column_default].must_equal nil
31
31
  end
32
32
 
33
- it "should parse indices" do
33
+ it 'should parse indices' do
34
34
  @table.
35
- indices["index_users_on_username_and_created_at"].
36
- must_equal(["username", "created_at"])
35
+ indices['index_users_on_username_and_created_at'].
36
+ must_equal(['username', 'created_at'])
37
37
  end
38
38
 
39
- it "should parse index" do
39
+ it 'should parse index' do
40
40
  @table.
41
- indices["index_users_on_reference"].
42
- must_equal(["reference"])
41
+ indices['index_users_on_reference'].
42
+ must_equal(['reference'])
43
43
  end
44
44
  end
45
45
  end
@@ -4,12 +4,12 @@
4
4
  require 'minitest/autorun'
5
5
  require 'minitest/spec'
6
6
  require 'minitest/mock'
7
- require "pathname"
8
- require "lhm"
7
+ require 'pathname'
8
+ require 'lhm'
9
9
 
10
10
  $project = Pathname.new(File.dirname(__FILE__) + '/..').cleanpath
11
- $spec = $project.join("spec")
12
- $fixtures = $spec.join("fixtures")
11
+ $spec = $project.join('spec')
12
+ $fixtures = $spec.join('fixtures')
13
13
 
14
14
  begin
15
15
  require 'active_record'
@@ -12,19 +12,19 @@ describe Lhm::AtomicSwitcher do
12
12
 
13
13
  before(:each) do
14
14
  @start = Time.now
15
- @origin = Lhm::Table.new("origin")
16
- @destination = Lhm::Table.new("destination")
15
+ @origin = Lhm::Table.new('origin')
16
+ @destination = Lhm::Table.new('destination')
17
17
  @migration = Lhm::Migration.new(@origin, @destination, @start)
18
18
  @switcher = Lhm::AtomicSwitcher.new(@migration, nil)
19
19
  end
20
20
 
21
- describe "atomic switch" do
22
- it "should perform a single atomic rename" do
21
+ describe 'atomic switch' do
22
+ it 'should perform a single atomic rename' do
23
23
  @switcher.
24
24
  statements.
25
25
  must_equal([
26
- "rename table `origin` to `#{ @migration.archive_name }`, " +
27
- "`destination` to `origin`"
26
+ "rename table `origin` to `#{ @migration.archive_name }`, " \
27
+ '`destination` to `origin`'
28
28
  ])
29
29
  end
30
30
  end
@@ -12,14 +12,14 @@ describe Lhm::Chunker do
12
12
  include UnitHelper
13
13
 
14
14
  before(:each) do
15
- @origin = Lhm::Table.new("foo")
16
- @destination = Lhm::Table.new("bar")
15
+ @origin = Lhm::Table.new('foo')
16
+ @destination = Lhm::Table.new('bar')
17
17
  @migration = Lhm::Migration.new(@origin, @destination)
18
18
  @connection = MiniTest::Mock.new
19
19
  # This is a poor man's stub
20
20
  @throttler = Object.new
21
21
  def @throttler.run
22
- #noop
22
+ # noop
23
23
  end
24
24
  def @throttler.stride
25
25
  1
@@ -29,8 +29,8 @@ describe Lhm::Chunker do
29
29
  :limit => 10)
30
30
  end
31
31
 
32
- describe "#run" do
33
- it "chunks the result set according to the stride size" do
32
+ describe '#run' do
33
+ it 'chunks the result set according to the stride size' do
34
34
  def @throttler.stride
35
35
  2
36
36
  end
@@ -55,8 +55,8 @@ describe Lhm::Chunker do
55
55
  @connection.verify
56
56
  end
57
57
 
58
- it "handles stride changes during execution" do
59
- #roll our own stubbing
58
+ it 'handles stride changes during execution' do
59
+ # roll our own stubbing
60
60
  def @throttler.stride
61
61
  @run_count ||= 0
62
62
  @run_count = @run_count + 1
@@ -84,7 +84,20 @@ describe Lhm::Chunker do
84
84
  @connection.verify
85
85
  end
86
86
 
87
- it "separates filter conditions from chunking conditions" do
87
+ it 'correctly copies single record tables' do
88
+ @chunker = Lhm::Chunker.new(@migration, @connection, :throttler => @throttler,
89
+ :start => 1,
90
+ :limit => 1)
91
+
92
+ @connection.expect(:update, 1) do |stmt|
93
+ stmt.first =~ /between 1 and 1/
94
+ end
95
+
96
+ @chunker.run
97
+ @connection.verify
98
+ end
99
+
100
+ it 'separates filter conditions from chunking conditions' do
88
101
  @chunker = Lhm::Chunker.new(@migration, @connection, :throttler => @throttler,
89
102
  :start => 1,
90
103
  :limit => 2)
@@ -110,7 +123,7 @@ describe Lhm::Chunker do
110
123
  end
111
124
 
112
125
  def @migration.conditions
113
- "inner join bar on foo.id = bar.foo_id"
126
+ 'inner join bar on foo.id = bar.foo_id'
114
127
  end
115
128
 
116
129
  @chunker.run
@@ -11,44 +11,44 @@ describe Lhm::Entangler do
11
11
  include UnitHelper
12
12
 
13
13
  before(:each) do
14
- @origin = Lhm::Table.new("origin")
15
- @destination = Lhm::Table.new("destination")
14
+ @origin = Lhm::Table.new('origin')
15
+ @destination = Lhm::Table.new('destination')
16
16
  @migration = Lhm::Migration.new(@origin, @destination)
17
17
  @entangler = Lhm::Entangler.new(@migration)
18
18
  end
19
19
 
20
- describe "activation" do
20
+ describe 'activation' do
21
21
  before(:each) do
22
- @origin.columns["info"] = { :type => "varchar(255)" }
23
- @origin.columns["tags"] = { :type => "varchar(255)" }
22
+ @origin.columns['info'] = { :type => 'varchar(255)' }
23
+ @origin.columns['tags'] = { :type => 'varchar(255)' }
24
24
 
25
- @destination.columns["info"] = { :type => "varchar(255)" }
26
- @destination.columns["tags"] = { :type => "varchar(255)" }
25
+ @destination.columns['info'] = { :type => 'varchar(255)' }
26
+ @destination.columns['tags'] = { :type => 'varchar(255)' }
27
27
  end
28
28
 
29
- it "should create insert trigger to destination table" do
29
+ it 'should create insert trigger to destination table' do
30
30
  ddl = %Q{
31
31
  create trigger `lhmt_ins_origin`
32
32
  after insert on `origin` for each row
33
33
  replace into `destination` (`info`, `tags`) /* large hadron migration */
34
- values (NEW.`info`, NEW.`tags`)
34
+ values (`NEW`.`info`, `NEW`.`tags`)
35
35
  }
36
36
 
37
37
  @entangler.entangle.must_include strip(ddl)
38
38
  end
39
39
 
40
- it "should create an update trigger to the destination table" do
40
+ it 'should create an update trigger to the destination table' do
41
41
  ddl = %Q{
42
42
  create trigger `lhmt_upd_origin`
43
43
  after update on `origin` for each row
44
44
  replace into `destination` (`info`, `tags`) /* large hadron migration */
45
- values (NEW.`info`, NEW.`tags`)
45
+ values (`NEW`.`info`, `NEW`.`tags`)
46
46
  }
47
47
 
48
48
  @entangler.entangle.must_include strip(ddl)
49
49
  end
50
50
 
51
- it "should create a delete trigger to the destination table" do
51
+ it 'should create a delete trigger to the destination table' do
52
52
  ddl = %Q{
53
53
  create trigger `lhmt_del_origin`
54
54
  after delete on `origin` for each row
@@ -60,17 +60,17 @@ describe Lhm::Entangler do
60
60
  end
61
61
  end
62
62
 
63
- describe "removal" do
64
- it "should remove insert trigger" do
65
- @entangler.untangle.must_include("drop trigger if exists `lhmt_ins_origin`")
63
+ describe 'removal' do
64
+ it 'should remove insert trigger' do
65
+ @entangler.untangle.must_include('drop trigger if exists `lhmt_ins_origin`')
66
66
  end
67
67
 
68
- it "should remove update trigger" do
69
- @entangler.untangle.must_include("drop trigger if exists `lhmt_upd_origin`")
68
+ it 'should remove update trigger' do
69
+ @entangler.untangle.must_include('drop trigger if exists `lhmt_upd_origin`')
70
70
  end
71
71
 
72
- it "should remove delete trigger" do
73
- @entangler.untangle.must_include("drop trigger if exists `lhmt_del_origin`")
72
+ it 'should remove delete trigger' do
73
+ @entangler.untangle.must_include('drop trigger if exists `lhmt_del_origin`')
74
74
  end
75
75
  end
76
76
  end
@@ -9,31 +9,43 @@ require 'lhm/migrator'
9
9
  describe Lhm::Intersection do
10
10
  include UnitHelper
11
11
 
12
- it "should not have dropped changes" do
13
- origin = Lhm::Table.new("origin")
14
- origin.columns["dropped"] = varchar
15
- origin.columns["retained"] = varchar
12
+ it 'should not have dropped changes' do
13
+ origin = Lhm::Table.new('origin')
14
+ origin.columns['dropped'] = varchar
15
+ origin.columns['retained'] = varchar
16
16
 
17
- destination = Lhm::Table.new("destination")
18
- destination.columns["retained"] = varchar
17
+ destination = Lhm::Table.new('destination')
18
+ destination.columns['retained'] = varchar
19
19
 
20
20
  intersection = Lhm::Intersection.new(origin, destination)
21
- intersection.common.include?("dropped").must_equal(false)
21
+ intersection.destination.include?('dropped').must_equal(false)
22
22
  end
23
23
 
24
- it "should have unchanged columns" do
25
- origin = Lhm::Table.new("origin")
26
- origin.columns["dropped"] = varchar
27
- origin.columns["retained"] = varchar
24
+ it 'should have unchanged columns' do
25
+ origin = Lhm::Table.new('origin')
26
+ origin.columns['dropped'] = varchar
27
+ origin.columns['retained'] = varchar
28
28
 
29
- destination = Lhm::Table.new("destination")
30
- destination.columns["retained"] = varchar
29
+ destination = Lhm::Table.new('destination')
30
+ destination.columns['retained'] = varchar
31
31
 
32
32
  intersection = Lhm::Intersection.new(origin, destination)
33
- intersection.common.must_equal(["retained"])
33
+ intersection.destination.must_equal(['retained'])
34
+ end
35
+
36
+ it 'should have renamed columns' do
37
+ origin = Lhm::Table.new('origin')
38
+ origin.columns['old_name'] = varchar
39
+
40
+ destination = Lhm::Table.new('destination')
41
+ destination.columns['new_name'] = varchar
42
+
43
+ intersection = Lhm::Intersection.new(origin, destination, { 'old_name' => 'new_name' })
44
+ intersection.origin.must_equal(['old_name'])
45
+ intersection.destination.must_equal(['new_name'])
34
46
  end
35
47
 
36
48
  def varchar
37
- { :metadata => "VARCHAR(255)"}
49
+ { :metadata => 'VARCHAR(255)' }
38
50
  end
39
51
  end
@@ -8,22 +8,22 @@ describe Lhm do
8
8
  Lhm.remove_class_variable :@@logger if Lhm.class_variable_defined? :@@logger
9
9
  end
10
10
 
11
- describe "logger" do
11
+ describe 'logger' do
12
12
 
13
- it "should use the default parameters if no logger explicitly set" do
13
+ it 'should use the default parameters if no logger explicitly set' do
14
14
  Lhm.logger.must_be_kind_of Logger
15
15
  Lhm.logger.level.must_equal Logger::INFO
16
- Lhm.logger.instance_eval{ @logdev }.dev.must_equal STDOUT
16
+ Lhm.logger.instance_eval { @logdev }.dev.must_equal STDOUT
17
17
  end
18
18
 
19
- it "should use s new logger if set" do
19
+ it 'should use s new logger if set' do
20
20
  l = Logger.new('omg.ponies')
21
21
  l.level = Logger::ERROR
22
22
  Lhm.logger = l
23
23
 
24
24
  Lhm.logger.level.must_equal Logger::ERROR
25
- Lhm.logger.instance_eval{ @logdev }.dev.must_be_kind_of File
26
- Lhm.logger.instance_eval{ @logdev }.dev.path.must_equal 'omg.ponies'
25
+ Lhm.logger.instance_eval { @logdev }.dev.must_be_kind_of File
26
+ Lhm.logger.instance_eval { @logdev }.dev.path.must_equal 'omg.ponies'
27
27
  end
28
28
  end
29
29
  end
@@ -12,39 +12,39 @@ describe Lhm::LockedSwitcher do
12
12
 
13
13
  before(:each) do
14
14
  @start = Time.now
15
- @origin = Lhm::Table.new("origin")
16
- @destination = Lhm::Table.new("destination")
15
+ @origin = Lhm::Table.new('origin')
16
+ @destination = Lhm::Table.new('destination')
17
17
  @migration = Lhm::Migration.new(@origin, @destination, @start)
18
18
  @switcher = Lhm::LockedSwitcher.new(@migration, nil)
19
19
  end
20
20
 
21
- describe "uncommitted" do
22
- it "should disable autocommit first" do
21
+ describe 'uncommitted' do
22
+ it 'should disable autocommit first' do
23
23
  @switcher.
24
24
  statements[0..1].
25
25
  must_equal([
26
- "set @lhm_auto_commit = @@session.autocommit",
27
- "set session autocommit = 0"
26
+ 'set @lhm_auto_commit = @@session.autocommit',
27
+ 'set session autocommit = 0'
28
28
  ])
29
29
  end
30
30
 
31
- it "should reapply original autocommit settings at the end" do
31
+ it 'should reapply original autocommit settings at the end' do
32
32
  @switcher.
33
33
  statements[-1].
34
- must_equal("set session autocommit = @lhm_auto_commit")
34
+ must_equal('set session autocommit = @lhm_auto_commit')
35
35
  end
36
36
  end
37
37
 
38
- describe "switch" do
39
- it "should lock origin and destination table, switch, commit and unlock" do
38
+ describe 'switch' do
39
+ it 'should lock origin and destination table, switch, commit and unlock' do
40
40
  @switcher.
41
41
  switch.
42
42
  must_equal([
43
- "lock table `origin` write, `destination` write",
43
+ 'lock table `origin` write, `destination` write',
44
44
  "alter table `origin` rename `#{ @migration.archive_name }`",
45
- "alter table `destination` rename `origin`",
46
- "commit",
47
- "unlock tables"
45
+ 'alter table `destination` rename `origin`',
46
+ 'commit',
47
+ 'unlock tables'
48
48
  ])
49
49
  end
50
50
  end
@@ -11,18 +11,18 @@ describe Lhm::Migration do
11
11
 
12
12
  before(:each) do
13
13
  @start = Time.now
14
- @origin = Lhm::Table.new("origin")
15
- @destination = Lhm::Table.new("destination")
14
+ @origin = Lhm::Table.new('origin')
15
+ @destination = Lhm::Table.new('destination')
16
16
  @migration = Lhm::Migration.new(@origin, @destination, nil, @start)
17
17
  end
18
18
 
19
- it "should name archive" do
20
- stamp = "%Y_%m_%d_%H_%M_%S_#{ "%03d" % (@start.usec / 1000) }"
19
+ it 'should name archive' do
20
+ stamp = "%Y_%m_%d_%H_%M_%S_#{ '%03d' % (@start.usec / 1000) }"
21
21
  @migration.archive_name.must_equal "lhma_#{ @start.strftime(stamp) }_origin"
22
22
  end
23
23
 
24
- it "should limit table name to 64 characters" do
25
- migration = Lhm::Migration.new(OpenStruct.new(:name => "a_very_very_long_table_name_that_should_make_the_LHMA_table_go_over_64_chars"), nil)
24
+ it 'should limit table name to 64 characters' do
25
+ migration = Lhm::Migration.new(OpenStruct.new(:name => 'a_very_very_long_table_name_that_should_make_the_LHMA_table_go_over_64_chars'), nil)
26
26
  migration.archive_name.size == 64
27
27
  end
28
28
  end