lhm 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,8 @@
1
+ # 1.3.0 (May 28, 2013)
2
+
3
+ * Add Lhm.cleanup method for removing copy tables, thanks @bogdan
4
+ * Limit copy table names to 64 characters, thanks @charliesome
5
+
1
6
  # 1.2.0 (February 22, 2013)
2
7
 
3
8
  * Added DataMapper support, no API changes for current users. Refer to the
data/README.md CHANGED
@@ -52,6 +52,11 @@ ActiveRecord 2.3.x and 3.x (mysql and mysql2 adapters), as well as DataMapper
52
52
  Lhm also works with dm-master-slave-adapter, it'll bind to the master before
53
53
  running the migrations.
54
54
 
55
+ ## Limitations
56
+
57
+ Lhm requires a monotonically increasing numeric Primary Key on the table, due to how
58
+ the Chunker works.
59
+
55
60
  ## Installation
56
61
 
57
62
  Install it via `gem install lhm` or add `gem "lhm"` to your Gemfile.
data/lib/lhm.rb CHANGED
@@ -34,8 +34,6 @@ module Lhm
34
34
  # @return [Boolean] Returns true if the migration finishes
35
35
  # @raise [Error] Raises Lhm::Error in case of a error and aborts the migration
36
36
  def self.change_table(table_name, options = {}, &block)
37
- connection = Connection.new(adapter)
38
-
39
37
  origin = Table.parse(table_name, connection)
40
38
  invoker = Invoker.new(origin, connection)
41
39
  block.call(invoker.migrator)
@@ -44,6 +42,23 @@ module Lhm
44
42
  true
45
43
  end
46
44
 
45
+ def self.cleanup(run = false)
46
+ lhm_tables = connection.select_values("show tables").select do |name|
47
+ name =~ /^lhm(a|n)_/
48
+ end
49
+ return true if lhm_tables.empty?
50
+ if run
51
+ lhm_tables.each do |table|
52
+ connection.execute("drop table #{table}")
53
+ end
54
+ true
55
+ else
56
+ puts "Existing LHM backup tables: #{lhm_tables.join(", ")}."
57
+ puts "Run Lhm.cleanup(true) to drop them all."
58
+ false
59
+ end
60
+ end
61
+
47
62
  def self.setup(adapter)
48
63
  @@adapter = adapter
49
64
  end
@@ -55,4 +70,10 @@ module Lhm
55
70
  ActiveRecord::Base.connection
56
71
  end
57
72
  end
73
+
74
+ protected
75
+ def self.connection
76
+ Connection.new(adapter)
77
+ end
78
+
58
79
  end
@@ -28,7 +28,7 @@ module Lhm
28
28
 
29
29
  def show_create(table_name)
30
30
  sql = "show create table `#{ table_name }`"
31
- select_values(sql).last
31
+ select_one(sql).values.last
32
32
  end
33
33
 
34
34
  def current_database
@@ -51,7 +51,7 @@ module Lhm
51
51
  end
52
52
 
53
53
  def select_values(sql)
54
- select_one(sql).values
54
+ select_all(sql)
55
55
  end
56
56
 
57
57
  def select_value(sql)
@@ -14,7 +14,7 @@ module Lhm
14
14
  end
15
15
 
16
16
  def archive_name
17
- "lhma_#{ startstamp }_#{ @origin.name }"
17
+ "lhma_#{ startstamp }_#{ @origin.name }"[0...64]
18
18
  end
19
19
 
20
20
  def intersection
@@ -2,5 +2,5 @@
2
2
  # Schmidt
3
3
 
4
4
  module Lhm
5
- VERSION = "1.2.0"
5
+ VERSION = "1.3.0"
6
6
  end
@@ -0,0 +1,34 @@
1
+ # Copyright (c) 2011 - 2013, SoundCloud Ltd., Rany Keddo, Tobias Bielohlawek, Tobias
2
+ # Schmidt
3
+
4
+ require File.expand_path(File.dirname(__FILE__)) + '/integration_helper'
5
+
6
+ require 'lhm'
7
+
8
+ describe Lhm, "cleanup" do
9
+ include IntegrationHelper
10
+ before(:each) { connect_master! }
11
+
12
+ describe "changes" do
13
+ before(:each) do
14
+ table_create(:users)
15
+ Lhm.change_table(:users, :atomic_switch => false) do |t|
16
+ t.add_column(:logins, "INT(12) DEFAULT '0'")
17
+ t.add_index(:logins)
18
+ end
19
+ end
20
+
21
+ it "should show temporary tables" do
22
+ output = capture_stdout do
23
+ Lhm.cleanup
24
+ end
25
+ output.must_include("Existing LHM backup tables")
26
+ output.must_match(/lhma_[0-9_]*_users/)
27
+ end
28
+
29
+ it "should delete temporary tables" do
30
+ Lhm.cleanup(true).must_equal(true)
31
+ Lhm.cleanup.must_equal(true)
32
+ end
33
+ end
34
+ end
@@ -50,6 +50,10 @@ module IntegrationHelper
50
50
  end
51
51
 
52
52
  Lhm.setup(adapter)
53
+ unless defined?(@@cleaned_up)
54
+ Lhm.cleanup(true)
55
+ @@cleaned_up = true
56
+ end
53
57
  @connection = Lhm::Connection.new(adapter)
54
58
  end
55
59
 
@@ -154,4 +158,17 @@ module IntegrationHelper
154
158
  def master_slave_mode?
155
159
  !!ENV["MASTER_SLAVE"]
156
160
  end
161
+
162
+ #
163
+ # Misc
164
+ #
165
+
166
+ def capture_stdout
167
+ out = StringIO.new
168
+ $stdout = out
169
+ yield
170
+ return out.string
171
+ ensure
172
+ $stdout = ::STDOUT
173
+ end
157
174
  end
@@ -20,4 +20,9 @@ describe Lhm::Migration do
20
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
+
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
+ migration.archive_name.size == 64
27
+ end
23
28
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lhm
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2013-02-22 00:00:00.000000000 Z
15
+ date: 2013-05-28 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: minitest
@@ -94,6 +94,7 @@ files:
94
94
  - spec/fixtures/users.ddl
95
95
  - spec/integration/atomic_switcher_spec.rb
96
96
  - spec/integration/chunker_spec.rb
97
+ - spec/integration/cleanup_spec.rb
97
98
  - spec/integration/entangler_spec.rb
98
99
  - spec/integration/integration_helper.rb
99
100
  - spec/integration/lhm_spec.rb
@@ -132,7 +133,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
132
133
  version: '0'
133
134
  requirements: []
134
135
  rubyforge_project:
135
- rubygems_version: 1.8.24
136
+ rubygems_version: 1.8.25
136
137
  signing_key:
137
138
  specification_version: 3
138
139
  summary: online schema changer for mysql