lhm 1.2.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/.rubocop.yml +256 -0
- data/.travis.yml +5 -1
- data/CHANGELOG.md +26 -0
- data/README.md +87 -8
- data/Rakefile +6 -4
- data/bin/lhm-config.sh +7 -0
- data/bin/lhm-kill-queue +13 -15
- data/bin/lhm-spec-clobber.sh +5 -4
- data/bin/lhm-spec-grants.sh +2 -2
- data/bin/lhm-spec-setup-cluster.sh +2 -3
- data/gemfiles/ar-2.3_mysql.gemfile +2 -1
- data/gemfiles/ar-3.2_mysql.gemfile +1 -1
- data/gemfiles/ar-3.2_mysql2.gemfile +1 -1
- data/gemfiles/dm_mysql.gemfile +1 -1
- data/lhm.gemspec +7 -8
- data/lib/lhm/atomic_switcher.rb +2 -1
- data/lib/lhm/chunker.rb +51 -39
- data/lib/lhm/command.rb +4 -2
- data/lib/lhm/connection.rb +14 -2
- data/lib/lhm/entangler.rb +5 -5
- data/lib/lhm/intersection.rb +29 -16
- data/lib/lhm/invoker.rb +31 -10
- data/lib/lhm/locked_switcher.rb +6 -6
- data/lib/lhm/migration.rb +7 -5
- data/lib/lhm/migrator.rb +57 -9
- data/lib/lhm/printer.rb +54 -0
- data/lib/lhm/sql_helper.rb +4 -4
- data/lib/lhm/table.rb +12 -12
- data/lib/lhm/throttler/time.rb +29 -0
- data/lib/lhm/throttler.rb +32 -0
- data/lib/lhm/version.rb +1 -1
- data/lib/lhm.rb +71 -6
- data/spec/.lhm.example +1 -1
- data/spec/README.md +20 -13
- data/spec/fixtures/lines.ddl +7 -0
- data/spec/fixtures/permissions.ddl +5 -0
- data/spec/fixtures/tracks.ddl +5 -0
- data/spec/fixtures/users.ddl +4 -2
- data/spec/integration/atomic_switcher_spec.rb +7 -7
- data/spec/integration/chunker_spec.rb +11 -5
- data/spec/integration/cleanup_spec.rb +72 -0
- data/spec/integration/entangler_spec.rb +11 -11
- data/spec/integration/integration_helper.rb +49 -17
- data/spec/integration/lhm_spec.rb +157 -37
- data/spec/integration/locked_switcher_spec.rb +7 -7
- data/spec/integration/table_spec.rb +15 -17
- data/spec/test_helper.rb +28 -0
- data/spec/unit/atomic_switcher_spec.rb +6 -6
- data/spec/unit/chunker_spec.rb +95 -73
- data/spec/unit/datamapper_connection_spec.rb +1 -0
- data/spec/unit/entangler_spec.rb +19 -19
- data/spec/unit/intersection_spec.rb +27 -15
- data/spec/unit/lhm_spec.rb +29 -0
- data/spec/unit/locked_switcher_spec.rb +14 -14
- data/spec/unit/migration_spec.rb +10 -5
- data/spec/unit/migrator_spec.rb +53 -41
- data/spec/unit/printer_spec.rb +79 -0
- data/spec/unit/sql_helper_spec.rb +10 -10
- data/spec/unit/table_spec.rb +11 -11
- data/spec/unit/throttler_spec.rb +73 -0
- data/spec/unit/unit_helper.rb +1 -13
- metadata +63 -24
- data/spec/bootstrap.rb +0 -13
@@ -1,19 +1,13 @@
|
|
1
1
|
# Copyright (c) 2011 - 2013, SoundCloud Ltd., Rany Keddo, Tobias Bielohlawek, Tobias
|
2
2
|
# Schmidt
|
3
|
-
|
4
|
-
require
|
5
|
-
|
3
|
+
require 'test_helper'
|
4
|
+
require 'yaml'
|
6
5
|
begin
|
7
|
-
require '
|
8
|
-
begin
|
9
|
-
require 'mysql2'
|
10
|
-
rescue LoadError
|
11
|
-
require 'mysql'
|
12
|
-
end
|
6
|
+
require 'active_support'
|
13
7
|
rescue LoadError
|
14
|
-
require 'dm-core'
|
15
|
-
require 'dm-mysql-adapter'
|
16
8
|
end
|
9
|
+
$password = YAML.load_file(File.expand_path(File.dirname(__FILE__)) + '/database.yml')['password'] rescue nil
|
10
|
+
|
17
11
|
require 'lhm/table'
|
18
12
|
require 'lhm/sql_helper'
|
19
13
|
require 'lhm/connection'
|
@@ -42,14 +36,19 @@ module IntegrationHelper
|
|
42
36
|
:host => '127.0.0.1',
|
43
37
|
:database => 'lhm',
|
44
38
|
:username => 'root',
|
45
|
-
:port => port
|
39
|
+
:port => port,
|
40
|
+
:password => $password
|
46
41
|
)
|
47
42
|
adapter = ActiveRecord::Base.connection
|
48
43
|
elsif defined?(DataMapper)
|
49
|
-
adapter = DataMapper.setup(:default, "mysql://root@localhost:#{port}/lhm")
|
44
|
+
adapter = DataMapper.setup(:default, "mysql://root:#{$password}@localhost:#{port}/lhm")
|
50
45
|
end
|
51
46
|
|
52
47
|
Lhm.setup(adapter)
|
48
|
+
unless defined?(@@cleaned_up)
|
49
|
+
Lhm.cleanup(true)
|
50
|
+
@@cleaned_up = true
|
51
|
+
end
|
53
52
|
@connection = Lhm::Connection.new(adapter)
|
54
53
|
end
|
55
54
|
|
@@ -87,7 +86,6 @@ module IntegrationHelper
|
|
87
86
|
connect_master!
|
88
87
|
end
|
89
88
|
|
90
|
-
|
91
89
|
yield block
|
92
90
|
|
93
91
|
if master_slave_mode?
|
@@ -109,6 +107,10 @@ module IntegrationHelper
|
|
109
107
|
table_read(fixture_name)
|
110
108
|
end
|
111
109
|
|
110
|
+
def table_rename(from_name, to_name)
|
111
|
+
execute "rename table `#{ from_name }` to `#{ to_name }`"
|
112
|
+
end
|
113
|
+
|
112
114
|
def table_read(fixture_name)
|
113
115
|
Lhm::Table.parse(fixture_name, @connection)
|
114
116
|
end
|
@@ -127,7 +129,7 @@ module IntegrationHelper
|
|
127
129
|
end
|
128
130
|
|
129
131
|
def count_all(table)
|
130
|
-
query = "select count(*) from
|
132
|
+
query = "select count(*) from `#{ table }`"
|
131
133
|
select_value(query).to_i
|
132
134
|
end
|
133
135
|
|
@@ -141,7 +143,7 @@ module IntegrationHelper
|
|
141
143
|
non_unique = type == :non_unique ? 1 : 0
|
142
144
|
|
143
145
|
!!select_one(%Q<
|
144
|
-
show indexes in
|
146
|
+
show indexes in `#{ table_name }`
|
145
147
|
where key_name = '#{ key_name }'
|
146
148
|
and non_unique = #{ non_unique }
|
147
149
|
>)
|
@@ -152,6 +154,36 @@ module IntegrationHelper
|
|
152
154
|
#
|
153
155
|
|
154
156
|
def master_slave_mode?
|
155
|
-
!!ENV[
|
157
|
+
!!ENV['MASTER_SLAVE']
|
158
|
+
end
|
159
|
+
|
160
|
+
#
|
161
|
+
# Misc
|
162
|
+
#
|
163
|
+
|
164
|
+
def capture_stdout
|
165
|
+
out = StringIO.new
|
166
|
+
$stdout = out
|
167
|
+
yield
|
168
|
+
return out.string
|
169
|
+
ensure
|
170
|
+
$stdout = ::STDOUT
|
171
|
+
end
|
172
|
+
|
173
|
+
def simulate_failed_migration
|
174
|
+
Lhm::Entangler.class_eval do
|
175
|
+
alias_method :old_after, :after
|
176
|
+
def after
|
177
|
+
true
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
yield
|
182
|
+
ensure
|
183
|
+
Lhm::Entangler.class_eval do
|
184
|
+
undef_method :after
|
185
|
+
alias_method :after, :old_after
|
186
|
+
undef_method :old_after
|
187
|
+
end
|
156
188
|
end
|
157
189
|
end
|
@@ -3,33 +3,71 @@
|
|
3
3
|
|
4
4
|
require File.expand_path(File.dirname(__FILE__)) + '/integration_helper'
|
5
5
|
|
6
|
-
require 'lhm'
|
7
|
-
|
8
6
|
describe Lhm do
|
9
7
|
include IntegrationHelper
|
10
8
|
|
11
9
|
before(:each) { connect_master! }
|
12
10
|
|
13
|
-
describe
|
11
|
+
describe 'changes' do
|
14
12
|
before(:each) do
|
15
13
|
table_create(:users)
|
14
|
+
table_create(:tracks)
|
15
|
+
table_create(:permissions)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'when providing a subset of data to copy' do
|
19
|
+
|
20
|
+
before do
|
21
|
+
execute('insert into tracks set id = 13, public = 0')
|
22
|
+
11.times { |n| execute("insert into tracks set id = #{n + 1}, public = 1") }
|
23
|
+
11.times { |n| execute("insert into permissions set track_id = #{n + 1}") }
|
24
|
+
|
25
|
+
Lhm.change_table(:permissions, :atomic_switch => false) do |t|
|
26
|
+
t.filter('inner join tracks on tracks.`id` = permissions.`track_id` and tracks.`public` = 1')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'when no additional data is inserted into the table' do
|
31
|
+
|
32
|
+
it 'migrates the existing data' do
|
33
|
+
slave do
|
34
|
+
count_all(:permissions).must_equal(11)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'when additional data is inserted' do
|
40
|
+
|
41
|
+
before do
|
42
|
+
execute('insert into tracks set id = 14, public = 0')
|
43
|
+
execute('insert into tracks set id = 15, public = 1')
|
44
|
+
execute('insert into permissions set track_id = 14')
|
45
|
+
execute('insert into permissions set track_id = 15')
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'migrates all data' do
|
49
|
+
slave do
|
50
|
+
count_all(:permissions).must_equal(13)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
16
54
|
end
|
17
55
|
|
18
|
-
it
|
56
|
+
it 'should add a column' do
|
19
57
|
Lhm.change_table(:users, :atomic_switch => false) do |t|
|
20
58
|
t.add_column(:logins, "INT(12) DEFAULT '0'")
|
21
59
|
end
|
22
60
|
|
23
61
|
slave do
|
24
|
-
table_read(:users).columns[
|
25
|
-
:type =>
|
26
|
-
:is_nullable =>
|
62
|
+
table_read(:users).columns['logins'].must_equal({
|
63
|
+
:type => 'int(12)',
|
64
|
+
:is_nullable => 'YES',
|
27
65
|
:column_default => '0'
|
28
66
|
})
|
29
67
|
end
|
30
68
|
end
|
31
69
|
|
32
|
-
it
|
70
|
+
it 'should copy all rows' do
|
33
71
|
23.times { |n| execute("insert into users set reference = '#{ n }'") }
|
34
72
|
|
35
73
|
Lhm.change_table(:users, :atomic_switch => false) do |t|
|
@@ -41,17 +79,17 @@ describe Lhm do
|
|
41
79
|
end
|
42
80
|
end
|
43
81
|
|
44
|
-
it
|
82
|
+
it 'should remove a column' do
|
45
83
|
Lhm.change_table(:users, :atomic_switch => false) do |t|
|
46
84
|
t.remove_column(:comment)
|
47
85
|
end
|
48
86
|
|
49
87
|
slave do
|
50
|
-
table_read(:users).columns[
|
88
|
+
table_read(:users).columns['comment'].must_equal nil
|
51
89
|
end
|
52
90
|
end
|
53
91
|
|
54
|
-
it
|
92
|
+
it 'should add an index' do
|
55
93
|
Lhm.change_table(:users, :atomic_switch => false) do |t|
|
56
94
|
t.add_index([:comment, :created_at])
|
57
95
|
end
|
@@ -61,7 +99,7 @@ describe Lhm do
|
|
61
99
|
end
|
62
100
|
end
|
63
101
|
|
64
|
-
it
|
102
|
+
it 'should add an index with a custom name' do
|
65
103
|
Lhm.change_table(:users, :atomic_switch => false) do |t|
|
66
104
|
t.add_index([:comment, :created_at], :my_index_name)
|
67
105
|
end
|
@@ -71,7 +109,7 @@ describe Lhm do
|
|
71
109
|
end
|
72
110
|
end
|
73
111
|
|
74
|
-
it
|
112
|
+
it 'should add an index on a column with a reserved name' do
|
75
113
|
Lhm.change_table(:users, :atomic_switch => false) do |t|
|
76
114
|
t.add_index(:group)
|
77
115
|
end
|
@@ -81,7 +119,7 @@ describe Lhm do
|
|
81
119
|
end
|
82
120
|
end
|
83
121
|
|
84
|
-
it
|
122
|
+
it 'should add a unqiue index' do
|
85
123
|
Lhm.change_table(:users, :atomic_switch => false) do |t|
|
86
124
|
t.add_unique_index(:comment)
|
87
125
|
end
|
@@ -91,7 +129,7 @@ describe Lhm do
|
|
91
129
|
end
|
92
130
|
end
|
93
131
|
|
94
|
-
it
|
132
|
+
it 'should remove an index' do
|
95
133
|
Lhm.change_table(:users, :atomic_switch => false) do |t|
|
96
134
|
t.remove_index([:username, :created_at])
|
97
135
|
end
|
@@ -101,62 +139,144 @@ describe Lhm do
|
|
101
139
|
end
|
102
140
|
end
|
103
141
|
|
104
|
-
it
|
142
|
+
it 'should remove an index with a custom name' do
|
143
|
+
Lhm.change_table(:users, :atomic_switch => false) do |t|
|
144
|
+
t.remove_index([:username, :group])
|
145
|
+
end
|
146
|
+
|
147
|
+
slave do
|
148
|
+
index?(:users, :index_with_a_custom_name).must_equal(false)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'should remove an index with a custom name by name' do
|
105
153
|
Lhm.change_table(:users, :atomic_switch => false) do |t|
|
106
|
-
t.remove_index(:
|
154
|
+
t.remove_index(:irrelevant_column_name, :index_with_a_custom_name)
|
107
155
|
end
|
108
156
|
|
109
157
|
slave do
|
110
|
-
index?(:users, :
|
158
|
+
index?(:users, :index_with_a_custom_name).must_equal(false)
|
111
159
|
end
|
112
160
|
end
|
113
161
|
|
114
|
-
it
|
162
|
+
it 'should apply a ddl statement' do
|
115
163
|
Lhm.change_table(:users, :atomic_switch => false) do |t|
|
116
|
-
t.ddl(
|
164
|
+
t.ddl('alter table %s add column flag tinyint(1)' % t.name)
|
117
165
|
end
|
118
166
|
|
119
167
|
slave do
|
120
|
-
table_read(:users).columns[
|
121
|
-
:type =>
|
122
|
-
:is_nullable =>
|
168
|
+
table_read(:users).columns['flag'].must_equal({
|
169
|
+
:type => 'tinyint(1)',
|
170
|
+
:is_nullable => 'YES',
|
123
171
|
:column_default => nil
|
124
172
|
})
|
125
173
|
end
|
126
174
|
end
|
127
175
|
|
128
|
-
it
|
176
|
+
it 'should change a column' do
|
129
177
|
Lhm.change_table(:users, :atomic_switch => false) do |t|
|
130
178
|
t.change_column(:comment, "varchar(20) DEFAULT 'none' NOT NULL")
|
131
179
|
end
|
132
180
|
|
133
181
|
slave do
|
134
|
-
table_read(:users).columns[
|
135
|
-
:type =>
|
136
|
-
:is_nullable =>
|
137
|
-
:column_default =>
|
182
|
+
table_read(:users).columns['comment'].must_equal({
|
183
|
+
:type => 'varchar(20)',
|
184
|
+
:is_nullable => 'NO',
|
185
|
+
:column_default => 'none'
|
138
186
|
})
|
139
187
|
end
|
140
188
|
end
|
141
189
|
|
142
|
-
it
|
190
|
+
it 'should change the last column in a table' do
|
143
191
|
table_create(:small_table)
|
144
192
|
|
145
193
|
Lhm.change_table(:small_table, :atomic_switch => false) do |t|
|
146
|
-
t.change_column(:id,
|
194
|
+
t.change_column(:id, 'int(5)')
|
195
|
+
end
|
196
|
+
|
197
|
+
slave do
|
198
|
+
table_read(:small_table).columns['id'].must_equal({
|
199
|
+
:type => 'int(5)',
|
200
|
+
:is_nullable => 'NO',
|
201
|
+
:column_default => '0'
|
202
|
+
})
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'should rename a column' do
|
207
|
+
table_create(:users)
|
208
|
+
|
209
|
+
execute("INSERT INTO users (username) VALUES ('a user')")
|
210
|
+
Lhm.change_table(:users, :atomic_switch => false) do |t|
|
211
|
+
t.rename_column(:username, :login)
|
212
|
+
end
|
213
|
+
|
214
|
+
slave do
|
215
|
+
table_data = table_read(:users)
|
216
|
+
table_data.columns['username'].must_equal(nil)
|
217
|
+
table_read(:users).columns['login'].must_equal({
|
218
|
+
:type => 'varchar(255)',
|
219
|
+
:is_nullable => 'YES',
|
220
|
+
:column_default => nil
|
221
|
+
})
|
222
|
+
|
223
|
+
# DM & AR versions of select_one return different structures. The
|
224
|
+
# real test is whether the data was copied
|
225
|
+
result = select_one('SELECT login from users')
|
226
|
+
result = result['login'] if result.respond_to?(:has_key?)
|
227
|
+
result.must_equal('a user')
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'should rename a column with a default' do
|
232
|
+
table_create(:users)
|
233
|
+
|
234
|
+
execute("INSERT INTO users (username) VALUES ('a user')")
|
235
|
+
Lhm.change_table(:users, :atomic_switch => false) do |t|
|
236
|
+
t.rename_column(:group, :fnord)
|
147
237
|
end
|
148
238
|
|
149
239
|
slave do
|
150
|
-
table_read(:
|
151
|
-
|
152
|
-
|
153
|
-
:
|
240
|
+
table_data = table_read(:users)
|
241
|
+
table_data.columns['group'].must_equal(nil)
|
242
|
+
table_read(:users).columns['fnord'].must_equal({
|
243
|
+
:type => 'varchar(255)',
|
244
|
+
:is_nullable => 'YES',
|
245
|
+
:column_default => 'Superfriends'
|
154
246
|
})
|
247
|
+
|
248
|
+
# DM & AR versions of select_one return different structures. The
|
249
|
+
# real test is whether the data was copied
|
250
|
+
result = select_one('SELECT `fnord` from users')
|
251
|
+
result = result['fnord'] if result.respond_to?(:has_key?)
|
252
|
+
result.must_equal('Superfriends')
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'works when mysql reserved words are used' do
|
257
|
+
table_create(:lines)
|
258
|
+
execute("insert into `lines` set id = 1, `between` = 'foo'")
|
259
|
+
execute("insert into `lines` set id = 2, `between` = 'bar'")
|
260
|
+
|
261
|
+
Lhm.change_table(:lines) do |t|
|
262
|
+
t.add_column('by', 'varchar(10)')
|
263
|
+
t.remove_column('lines')
|
264
|
+
t.add_index('by')
|
265
|
+
t.add_unique_index('between')
|
266
|
+
t.remove_index('by')
|
267
|
+
end
|
268
|
+
|
269
|
+
slave do
|
270
|
+
table_read(:lines).columns.must_include 'by'
|
271
|
+
table_read(:lines).columns.wont_include 'lines'
|
272
|
+
index_on_columns?(:lines, ['between'], :unique).must_equal true
|
273
|
+
index_on_columns?(:lines, ['by']).must_equal false
|
274
|
+
count_all(:lines).must_equal(2)
|
155
275
|
end
|
156
276
|
end
|
157
277
|
|
158
|
-
describe
|
159
|
-
it
|
278
|
+
describe 'parallel' do
|
279
|
+
it 'should perserve inserts during migration' do
|
160
280
|
50.times { |n| execute("insert into users set reference = '#{ n }'") }
|
161
281
|
|
162
282
|
insert = Thread.new do
|
@@ -180,7 +300,7 @@ describe Lhm do
|
|
180
300
|
end
|
181
301
|
end
|
182
302
|
|
183
|
-
it
|
303
|
+
it 'should perserve deletes during migration' do
|
184
304
|
50.times { |n| execute("insert into users set reference = '#{ n }'") }
|
185
305
|
|
186
306
|
delete = Thread.new do
|
@@ -12,30 +12,30 @@ describe Lhm::LockedSwitcher do
|
|
12
12
|
|
13
13
|
before(:each) { connect_master! }
|
14
14
|
|
15
|
-
describe
|
15
|
+
describe 'switching' do
|
16
16
|
before(:each) do
|
17
|
-
@origin = table_create(
|
18
|
-
@destination = table_create(
|
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
|
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
|
28
|
+
table_read(@migration.archive_name).columns.keys.must_include 'origin'
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
it
|
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
|
38
|
+
table_read(@origin.name).columns.keys.must_include 'destination'
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
@@ -2,46 +2,44 @@
|
|
2
2
|
# Schmidt
|
3
3
|
|
4
4
|
require File.expand_path(File.dirname(__FILE__)) + '/integration_helper'
|
5
|
-
|
6
|
-
require 'lhm'
|
7
5
|
require 'lhm/table'
|
8
6
|
|
9
7
|
describe Lhm::Table do
|
10
8
|
include IntegrationHelper
|
11
9
|
|
12
10
|
describe Lhm::Table::Parser do
|
13
|
-
describe
|
11
|
+
describe 'create table parsing' do
|
14
12
|
before(:each) do
|
15
13
|
connect_master!
|
16
14
|
@table = table_create(:users)
|
17
15
|
end
|
18
16
|
|
19
|
-
it
|
20
|
-
@table.name.must_equal(
|
17
|
+
it 'should parse table name in show create table' do
|
18
|
+
@table.name.must_equal('users')
|
21
19
|
end
|
22
20
|
|
23
|
-
it
|
24
|
-
@table.pk.must_equal(
|
21
|
+
it 'should parse primary key' do
|
22
|
+
@table.pk.must_equal('id')
|
25
23
|
end
|
26
24
|
|
27
|
-
it
|
28
|
-
@table.columns[
|
25
|
+
it 'should parse column type in show create table' do
|
26
|
+
@table.columns['username'][:type].must_equal('varchar(255)')
|
29
27
|
end
|
30
28
|
|
31
|
-
it
|
32
|
-
@table.columns[
|
29
|
+
it 'should parse column metadata' do
|
30
|
+
@table.columns['username'][:column_default].must_equal nil
|
33
31
|
end
|
34
32
|
|
35
|
-
it
|
33
|
+
it 'should parse indices' do
|
36
34
|
@table.
|
37
|
-
indices[
|
38
|
-
must_equal([
|
35
|
+
indices['index_users_on_username_and_created_at'].
|
36
|
+
must_equal(['username', 'created_at'])
|
39
37
|
end
|
40
38
|
|
41
|
-
it
|
39
|
+
it 'should parse index' do
|
42
40
|
@table.
|
43
|
-
indices[
|
44
|
-
must_equal([
|
41
|
+
indices['index_users_on_reference'].
|
42
|
+
must_equal(['reference'])
|
45
43
|
end
|
46
44
|
end
|
47
45
|
end
|
data/spec/test_helper.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Copyright (c) 2011 - 2013, SoundCloud Ltd., Rany Keddo, Tobias Bielohlawek, Tobias
|
2
|
+
# Schmidt
|
3
|
+
|
4
|
+
require 'minitest/autorun'
|
5
|
+
require 'minitest/spec'
|
6
|
+
require 'minitest/mock'
|
7
|
+
require 'pathname'
|
8
|
+
require 'lhm'
|
9
|
+
|
10
|
+
$project = Pathname.new(File.dirname(__FILE__) + '/..').cleanpath
|
11
|
+
$spec = $project.join('spec')
|
12
|
+
$fixtures = $spec.join('fixtures')
|
13
|
+
|
14
|
+
begin
|
15
|
+
require 'active_record'
|
16
|
+
begin
|
17
|
+
require 'mysql2'
|
18
|
+
rescue LoadError
|
19
|
+
require 'mysql'
|
20
|
+
end
|
21
|
+
rescue LoadError
|
22
|
+
require 'dm-core'
|
23
|
+
require 'dm-mysql-adapter'
|
24
|
+
end
|
25
|
+
|
26
|
+
logger = Logger.new STDOUT
|
27
|
+
logger.level = Logger::WARN
|
28
|
+
Lhm.logger = logger
|
@@ -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(
|
16
|
-
@destination = Lhm::Table.new(
|
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
|
22
|
-
it
|
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
|
-
|
26
|
+
"rename table `origin` to `#{ @migration.archive_name }`, " \
|
27
|
+
'`destination` to `origin`'
|
28
28
|
])
|
29
29
|
end
|
30
30
|
end
|