lhm 1.2.0 → 2.2.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 +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
|