xmigra 1.5.1 → 1.6.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 +4 -4
- data/lib/xmigra/db_support/mssql.rb +43 -0
- data/lib/xmigra/db_support/psql.rb +45 -0
- data/lib/xmigra/declarative_migration.rb +160 -0
- data/lib/xmigra/declarative_support/table.rb +590 -0
- data/lib/xmigra/declarative_support.rb +158 -0
- data/lib/xmigra/impdecl_migration_adder.rb +249 -0
- data/lib/xmigra/migration.rb +10 -3
- data/lib/xmigra/migration_chain.rb +22 -8
- data/lib/xmigra/migration_conflict.rb +27 -0
- data/lib/xmigra/new_access_artifact_adder.rb +44 -0
- data/lib/xmigra/new_index_adder.rb +33 -0
- data/lib/xmigra/new_migration_adder.rb +10 -6
- data/lib/xmigra/permission_script_writer.rb +11 -5
- data/lib/xmigra/program.rb +231 -23
- data/lib/xmigra/schema_updater.rb +28 -5
- data/lib/xmigra/vcs_support/git.rb +189 -8
- data/lib/xmigra/vcs_support/svn.rb +107 -1
- data/lib/xmigra/version.rb +1 -1
- data/lib/xmigra.rb +47 -2
- data/test/git_vcs.rb +64 -4
- data/test/new_files.rb +14 -0
- data/test/runner.rb +49 -4
- data/test/structure_declarative.rb +811 -0
- data/test/utils.rb +17 -2
- metadata +10 -2
@@ -0,0 +1,811 @@
|
|
1
|
+
DECLARATIVE_DIR = Pathname('structure/declarative')
|
2
|
+
|
3
|
+
def add_foo_declarative(object_tag = '!table', options={})
|
4
|
+
DECLARATIVE_DIR.mkpath unless DECLARATIVE_DIR.exist?
|
5
|
+
(decl_file = DECLARATIVE_DIR.join('foo.yaml')).open('w') do |f|
|
6
|
+
f.print("--- #{object_tag}
|
7
|
+
columns:
|
8
|
+
- name: id
|
9
|
+
type: bigint
|
10
|
+
primary key: true
|
11
|
+
#{options[:id_extra_info].to_s.lines.join("\n ")}
|
12
|
+
|
13
|
+
- name: weapon
|
14
|
+
type: varchar(32)
|
15
|
+
#{options[:weapon_extra_info].to_s.lines.join("\n ")}
|
16
|
+
")
|
17
|
+
end
|
18
|
+
return decl_file
|
19
|
+
end
|
20
|
+
|
21
|
+
def make_first_commit
|
22
|
+
File.open('README.md', 'w') do |f|
|
23
|
+
f.puts "This is a sample"
|
24
|
+
end
|
25
|
+
do_or_die %Q{git add README.md}, "Unable to add README.md to git index"
|
26
|
+
do_or_die %Q{git commit -m "first commit"}, "Unable to make first commit"
|
27
|
+
end
|
28
|
+
|
29
|
+
run_test "XMigra detects new declarative file" do
|
30
|
+
in_xmigra_schema do
|
31
|
+
add_foo_declarative
|
32
|
+
|
33
|
+
tool = XMigra::SchemaUpdater.new('.')
|
34
|
+
tool.load_plugin!
|
35
|
+
assert("Migration chain incomplete") {tool.migrations.complete?}
|
36
|
+
assert("Migration chain misses some migrations") {tool.migrations.includes_all?}
|
37
|
+
assert_raises(XMigra::DeclarativeMigration::MissingImplementationError) do
|
38
|
+
tool.update_sql
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
run_test "MigrationChain provides DeclarativeMigration::Missing for new file" do
|
44
|
+
in_xmigra_schema do
|
45
|
+
decl_file = add_foo_declarative
|
46
|
+
|
47
|
+
tool = XMigra::SchemaUpdater.new('.')
|
48
|
+
assert_eq(
|
49
|
+
tool.migrations.path,
|
50
|
+
Pathname('structure')
|
51
|
+
)
|
52
|
+
assert_eq(
|
53
|
+
tool.migrations.path.join(XMigra::DeclarativeMigration::SUBDIR),
|
54
|
+
Pathname('structure/declarative')
|
55
|
+
)
|
56
|
+
assert_eq(
|
57
|
+
Dir.glob('structure/declarative/*.yaml'),
|
58
|
+
['structure/declarative/foo.yaml']
|
59
|
+
)
|
60
|
+
assert_include(
|
61
|
+
tool.migrations.latest_declarative_implementations.keys,
|
62
|
+
decl_file.expand_path
|
63
|
+
)
|
64
|
+
assert_eq(
|
65
|
+
tool.migrations.latest_declarative_implementations[decl_file],
|
66
|
+
XMigra::DeclarativeMigration::Missing
|
67
|
+
)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
run_test "XMigra can create an implementing migration for creation" do
|
72
|
+
in_xmigra_schema do
|
73
|
+
do_or_die "git init", "Unable to initialize git repository"
|
74
|
+
decl_file = add_foo_declarative
|
75
|
+
|
76
|
+
# tool = XMigra::ImpdeclMigrationAdder.new('.')
|
77
|
+
# new_fpath = tool.add_migration_implementing_changes(decl_file)
|
78
|
+
XMigra::Program.run(
|
79
|
+
['impdecl', '--no-edit', decl_file.to_s]
|
80
|
+
)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
run_test "XMigra can create an implementing migration for adoption" do
|
85
|
+
in_xmigra_schema do
|
86
|
+
do_or_die "git init", "Unable to initialize git repository"
|
87
|
+
decl_file = add_foo_declarative
|
88
|
+
|
89
|
+
XMigra::Program.run(
|
90
|
+
['impdecl', '--adopt', '--no-edit', decl_file.to_s]
|
91
|
+
)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
run_test "Generated migration implementing adoption has no sql" do
|
96
|
+
in_xmigra_schema do
|
97
|
+
do_or_die "git init", "Unable to initialize git repository"
|
98
|
+
decl_file = add_foo_declarative
|
99
|
+
|
100
|
+
tool = XMigra::ImpdeclMigrationAdder.new('.')
|
101
|
+
new_fpath = tool.add_migration_implementing_changes(decl_file, :adopt=>true)
|
102
|
+
|
103
|
+
impdecl_data = YAML.load_file(new_fpath)
|
104
|
+
assert {!impdecl_data.has_key? 'sql'}
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
run_test "Adoption migrations are valid when generating upgrade" do
|
109
|
+
in_xmigra_schema do
|
110
|
+
do_or_die "git init", "Unable to initialize git repository"
|
111
|
+
make_first_commit
|
112
|
+
decl_file = add_foo_declarative
|
113
|
+
|
114
|
+
XMigra::Program.run(
|
115
|
+
['impdecl', '--adopt', '--no-edit', decl_file.to_s]
|
116
|
+
)
|
117
|
+
|
118
|
+
XMigra::Program.run(['upgrade'])
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
run_test "XMigra does not allow renunciation for new declarative" do
|
123
|
+
in_xmigra_schema do
|
124
|
+
do_or_die "git init", "Unable to initialize git repository"
|
125
|
+
decl_file = add_foo_declarative
|
126
|
+
|
127
|
+
assert_raises(XMigra::Program::ArgumentError) do
|
128
|
+
XMigra::Program.run(
|
129
|
+
['impdecl', '--renounce', '--no-edit', decl_file.to_s]
|
130
|
+
)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
run_test "XMigra can build an upgrade script including an impdecl migration" do
|
136
|
+
in_xmigra_schema do
|
137
|
+
do_or_die "git init", "Unable to initialize git repository"
|
138
|
+
make_first_commit
|
139
|
+
decl_file = add_foo_declarative
|
140
|
+
|
141
|
+
tool = XMigra::ImpdeclMigrationAdder.new('.')
|
142
|
+
new_fpath = tool.add_migration_implementing_changes(decl_file)
|
143
|
+
|
144
|
+
impdecl_data = YAML.load_file(new_fpath)
|
145
|
+
impdecl_data.delete(XMigra::DeclarativeMigration::QUALIFICATION_KEY)
|
146
|
+
impdecl_data['sql'] = '
|
147
|
+
CREATE TABLE foo (
|
148
|
+
id BIGINT PRIMARY KEY,
|
149
|
+
weapon VARCHAR(64)
|
150
|
+
);
|
151
|
+
'
|
152
|
+
File.open(new_fpath, 'w') do |f|
|
153
|
+
$xmigra_yamler.dump(impdecl_data, f)
|
154
|
+
end
|
155
|
+
|
156
|
+
tool = XMigra::SchemaUpdater.new('.')
|
157
|
+
assert("SchemaUpdater does not know Git specifics") {tool.is_a? XMigra::GitSpecifics}
|
158
|
+
assert("At least one migration does not know Git specifics") do
|
159
|
+
tool.migrations.all? {|m| m.is_a? XMigra::GitSpecifics}
|
160
|
+
end
|
161
|
+
tool.update_sql
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
run_test "XMigra can create an implementing migration for revision" do
|
166
|
+
in_xmigra_schema do
|
167
|
+
do_or_die "git init", "Unable to initialize git repository"
|
168
|
+
decl_file = add_foo_declarative
|
169
|
+
|
170
|
+
tool = XMigra::ImpdeclMigrationAdder.new('.')
|
171
|
+
new_fpath = tool.add_migration_implementing_changes(decl_file)
|
172
|
+
|
173
|
+
impdecl_data = YAML.load_file(new_fpath)
|
174
|
+
impdecl_data.delete(XMigra::DeclarativeMigration::QUALIFICATION_KEY)
|
175
|
+
impdecl_data['sql'] = '
|
176
|
+
CREATE TABLE foo (
|
177
|
+
id BIGINT PRIMARY KEY,
|
178
|
+
weapon VARCHAR(64)
|
179
|
+
);
|
180
|
+
'
|
181
|
+
File.open(new_fpath, 'w') do |f|
|
182
|
+
$xmigra_yamler.dump(impdecl_data, f)
|
183
|
+
end
|
184
|
+
|
185
|
+
do_or_die %Q{git add "#{decl_file}" "#{new_fpath}"}
|
186
|
+
do_or_die %Q{git commit -m "Create foo table"}
|
187
|
+
|
188
|
+
decl_data = YAML.load_file(decl_file)
|
189
|
+
decl_data['columns'] << {
|
190
|
+
'name'=>'caliber',
|
191
|
+
'type'=>'float(53)',
|
192
|
+
}
|
193
|
+
decl_file.open('w') do |f|
|
194
|
+
$xmigra_yamler.dump(decl_data, f)
|
195
|
+
end
|
196
|
+
|
197
|
+
tool = XMigra::ImpdeclMigrationAdder.new('.')
|
198
|
+
new_fpath2 = tool.add_migration_implementing_changes(decl_file)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
run_test "XMigra detects mismatched implementing migration and declarative" do
|
203
|
+
in_xmigra_schema do
|
204
|
+
do_or_die "git init", "Unable to initialize git repository"
|
205
|
+
decl_file = add_foo_declarative
|
206
|
+
|
207
|
+
tool = XMigra::ImpdeclMigrationAdder.new('.')
|
208
|
+
new_fpath = tool.add_migration_implementing_changes(decl_file)
|
209
|
+
|
210
|
+
impdecl_data = YAML.load_file(new_fpath)
|
211
|
+
impdecl_data.delete(XMigra::DeclarativeMigration::QUALIFICATION_KEY)
|
212
|
+
impdecl_data['sql'] = '
|
213
|
+
CREATE TABLE foo (
|
214
|
+
id BIGINT PRIMARY KEY,
|
215
|
+
weapon VARCHAR(64)
|
216
|
+
);
|
217
|
+
'
|
218
|
+
File.open(new_fpath, 'w') do |f|
|
219
|
+
$xmigra_yamler.dump(impdecl_data, f)
|
220
|
+
end
|
221
|
+
|
222
|
+
do_or_die %Q{git add "#{decl_file}" "#{new_fpath}"}
|
223
|
+
do_or_die %Q{git commit -m "Create foo table"}
|
224
|
+
|
225
|
+
decl_data = YAML.load_file(decl_file)
|
226
|
+
decl_data['columns'] << {
|
227
|
+
'name'=>'caliber',
|
228
|
+
'type'=>'float(53)',
|
229
|
+
}
|
230
|
+
decl_file.open('w') do |f|
|
231
|
+
$xmigra_yamler.dump(decl_data, f)
|
232
|
+
end
|
233
|
+
|
234
|
+
tool = XMigra::ImpdeclMigrationAdder.new('.')
|
235
|
+
tool.add_migration_implementing_changes(decl_file)
|
236
|
+
|
237
|
+
decl_data = YAML.load_file(decl_file)
|
238
|
+
decl_data['columns'] << {
|
239
|
+
'name'=>'dweomer',
|
240
|
+
'type'=>'text',
|
241
|
+
}
|
242
|
+
decl_file.open('w') do |f|
|
243
|
+
$xmigra_yamler.dump(decl_data, f)
|
244
|
+
end
|
245
|
+
|
246
|
+
tool = XMigra::SchemaUpdater.new('.')
|
247
|
+
assert_raises XMigra::DeclarativeMigration::MissingImplementationError do
|
248
|
+
tool.update_sql
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
run_test "XMigra does not allow adoption for revised declarative" do
|
254
|
+
in_xmigra_schema do
|
255
|
+
do_or_die "git init", "Unable to initialize git repository"
|
256
|
+
decl_file = add_foo_declarative
|
257
|
+
|
258
|
+
tool = XMigra::ImpdeclMigrationAdder.new('.')
|
259
|
+
new_fpath = tool.add_migration_implementing_changes(decl_file)
|
260
|
+
|
261
|
+
impdecl_data = YAML.load_file(new_fpath)
|
262
|
+
impdecl_data.delete(XMigra::DeclarativeMigration::QUALIFICATION_KEY)
|
263
|
+
impdecl_data['sql'] = '
|
264
|
+
CREATE TABLE foo (
|
265
|
+
id BIGINT PRIMARY KEY,
|
266
|
+
weapon VARCHAR(64)
|
267
|
+
);
|
268
|
+
'
|
269
|
+
File.open(new_fpath, 'w') do |f|
|
270
|
+
$xmigra_yamler.dump(impdecl_data, f)
|
271
|
+
end
|
272
|
+
|
273
|
+
do_or_die %Q{git add "#{decl_file}" "#{new_fpath}"}
|
274
|
+
do_or_die %Q{git commit -m "Create foo table"}
|
275
|
+
|
276
|
+
decl_data = YAML.load_file(decl_file)
|
277
|
+
decl_data['columns'] << {
|
278
|
+
'name'=>'caliber',
|
279
|
+
'type'=>'float(53)',
|
280
|
+
}
|
281
|
+
decl_file.open('w') do |f|
|
282
|
+
$xmigra_yamler.dump(decl_data, f)
|
283
|
+
end
|
284
|
+
|
285
|
+
assert_raises(XMigra::Program::ArgumentError) do
|
286
|
+
XMigra::Program.run(
|
287
|
+
['impdecl', '--adopt', '--no-edit', decl_file.to_s]
|
288
|
+
)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
run_test "A declarative is only revised after an implementing migration" do
|
294
|
+
in_xmigra_schema do
|
295
|
+
do_or_die "git init", "Unable to initialize git repository"
|
296
|
+
decl_file = add_foo_declarative
|
297
|
+
|
298
|
+
do_or_die %Q{git add "#{decl_file}"}
|
299
|
+
do_or_die %Q{git commit -m "Create foo table"}
|
300
|
+
|
301
|
+
decl_data = YAML.load_file(decl_file)
|
302
|
+
decl_data['columns'] << {
|
303
|
+
'name'=>'caliber',
|
304
|
+
'type'=>'float(53)',
|
305
|
+
}
|
306
|
+
decl_file.open('w') do |f|
|
307
|
+
$xmigra_yamler.dump(decl_data, f)
|
308
|
+
end
|
309
|
+
|
310
|
+
XMigra::Program.run(
|
311
|
+
['impdecl', '--adopt', '--no-edit', decl_file.to_s]
|
312
|
+
)
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
run_test "XMigra does not allow renunciation for revised declarative" do
|
317
|
+
in_xmigra_schema do
|
318
|
+
do_or_die "git init", "Unable to initialize git repository"
|
319
|
+
decl_file = add_foo_declarative
|
320
|
+
|
321
|
+
tool = XMigra::ImpdeclMigrationAdder.new('.')
|
322
|
+
new_fpath = tool.add_migration_implementing_changes(decl_file)
|
323
|
+
|
324
|
+
impdecl_data = YAML.load_file(new_fpath)
|
325
|
+
impdecl_data.delete(XMigra::DeclarativeMigration::QUALIFICATION_KEY)
|
326
|
+
impdecl_data['sql'] = '
|
327
|
+
CREATE TABLE foo (
|
328
|
+
id BIGINT PRIMARY KEY,
|
329
|
+
weapon VARCHAR(64)
|
330
|
+
);
|
331
|
+
'
|
332
|
+
File.open(new_fpath, 'w') do |f|
|
333
|
+
$xmigra_yamler.dump(impdecl_data, f)
|
334
|
+
end
|
335
|
+
|
336
|
+
do_or_die %Q{git add "#{decl_file}" "#{new_fpath}"}
|
337
|
+
do_or_die %Q{git commit -m "Create foo table"}
|
338
|
+
|
339
|
+
decl_data = YAML.load_file(decl_file)
|
340
|
+
decl_data['columns'] << {
|
341
|
+
'name'=>'caliber',
|
342
|
+
'type'=>'float(53)',
|
343
|
+
}
|
344
|
+
decl_file.open('w') do |f|
|
345
|
+
$xmigra_yamler.dump(decl_data, f)
|
346
|
+
end
|
347
|
+
|
348
|
+
assert_raises(XMigra::Program::ArgumentError) do
|
349
|
+
XMigra::Program.run(
|
350
|
+
['impdecl', '--renounce', '--no-edit', decl_file.to_s]
|
351
|
+
)
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
run_test "XMigra can create an implementing migration for destruction" do
|
357
|
+
in_xmigra_schema do
|
358
|
+
do_or_die "git init", "Unable to initialize git repository"
|
359
|
+
decl_file = add_foo_declarative
|
360
|
+
|
361
|
+
tool = XMigra::ImpdeclMigrationAdder.new('.')
|
362
|
+
new_fpath = tool.add_migration_implementing_changes(decl_file)
|
363
|
+
|
364
|
+
impdecl_data = YAML.load_file(new_fpath)
|
365
|
+
impdecl_data.delete(XMigra::DeclarativeMigration::QUALIFICATION_KEY)
|
366
|
+
impdecl_data['sql'] = '
|
367
|
+
CREATE TABLE foo (
|
368
|
+
id BIGINT PRIMARY KEY,
|
369
|
+
weapon VARCHAR(64)
|
370
|
+
);
|
371
|
+
'
|
372
|
+
File.open(new_fpath, 'w') do |f|
|
373
|
+
$xmigra_yamler.dump(impdecl_data, f)
|
374
|
+
end
|
375
|
+
|
376
|
+
do_or_die %Q{git add "#{decl_file}" "#{new_fpath}"}
|
377
|
+
do_or_die %Q{git commit -m "Create foo table"}
|
378
|
+
|
379
|
+
decl_file.delete
|
380
|
+
|
381
|
+
tool = XMigra::ImpdeclMigrationAdder.new('.')
|
382
|
+
new_fpath2 = tool.add_migration_implementing_changes(decl_file)
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
run_test "XMigra can create an implementing migration for renunciation" do
|
387
|
+
in_xmigra_schema do
|
388
|
+
do_or_die "git init", "Unable to initialize git repository"
|
389
|
+
decl_file = add_foo_declarative
|
390
|
+
|
391
|
+
tool = XMigra::ImpdeclMigrationAdder.new('.')
|
392
|
+
new_fpath = tool.add_migration_implementing_changes(decl_file)
|
393
|
+
|
394
|
+
impdecl_data = YAML.load_file(new_fpath)
|
395
|
+
impdecl_data.delete(XMigra::DeclarativeMigration::QUALIFICATION_KEY)
|
396
|
+
impdecl_data['sql'] = '
|
397
|
+
CREATE TABLE foo (
|
398
|
+
id BIGINT PRIMARY KEY,
|
399
|
+
weapon VARCHAR(64)
|
400
|
+
);
|
401
|
+
'
|
402
|
+
File.open(new_fpath, 'w') do |f|
|
403
|
+
$xmigra_yamler.dump(impdecl_data, f)
|
404
|
+
end
|
405
|
+
|
406
|
+
do_or_die %Q{git add "#{decl_file}" "#{new_fpath}"}
|
407
|
+
do_or_die %Q{git commit -m "Create foo table"}
|
408
|
+
|
409
|
+
decl_file.delete
|
410
|
+
|
411
|
+
XMigra::Program.run(
|
412
|
+
['impdecl', '--renounce', '--no-edit', decl_file.to_s]
|
413
|
+
)
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
run_test "Generated migration implementing destruction has no sql" do
|
418
|
+
in_xmigra_schema do
|
419
|
+
do_or_die "git init", "Unable to initialize git repository"
|
420
|
+
decl_file = add_foo_declarative
|
421
|
+
|
422
|
+
tool = XMigra::ImpdeclMigrationAdder.new('.')
|
423
|
+
new_fpath = tool.add_migration_implementing_changes(decl_file)
|
424
|
+
|
425
|
+
impdecl_data = YAML.load_file(new_fpath)
|
426
|
+
impdecl_data.delete(XMigra::DeclarativeMigration::QUALIFICATION_KEY)
|
427
|
+
impdecl_data['sql'] = '
|
428
|
+
CREATE TABLE foo (
|
429
|
+
id BIGINT PRIMARY KEY,
|
430
|
+
weapon VARCHAR(64)
|
431
|
+
);
|
432
|
+
'
|
433
|
+
File.open(new_fpath, 'w') do |f|
|
434
|
+
$xmigra_yamler.dump(impdecl_data, f)
|
435
|
+
end
|
436
|
+
|
437
|
+
do_or_die %Q{git add "#{decl_file}" "#{new_fpath}"}
|
438
|
+
do_or_die %Q{git commit -m "Create foo table"}
|
439
|
+
|
440
|
+
decl_file.delete
|
441
|
+
|
442
|
+
tool = XMigra::ImpdeclMigrationAdder.new('.')
|
443
|
+
new_fpath = tool.add_migration_implementing_changes(decl_file, :renounce=>true)
|
444
|
+
|
445
|
+
impdecl_data = YAML.load_file(new_fpath)
|
446
|
+
assert {!impdecl_data.has_key? 'sql'}
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
run_test "XMigra does not allow adoption for deleted declarative" do
|
451
|
+
in_xmigra_schema do
|
452
|
+
do_or_die "git init", "Unable to initialize git repository"
|
453
|
+
decl_file = add_foo_declarative
|
454
|
+
|
455
|
+
tool = XMigra::ImpdeclMigrationAdder.new('.')
|
456
|
+
new_fpath = tool.add_migration_implementing_changes(decl_file)
|
457
|
+
|
458
|
+
impdecl_data = YAML.load_file(new_fpath)
|
459
|
+
impdecl_data.delete(XMigra::DeclarativeMigration::QUALIFICATION_KEY)
|
460
|
+
impdecl_data['sql'] = '
|
461
|
+
CREATE TABLE foo (
|
462
|
+
id BIGINT PRIMARY KEY,
|
463
|
+
weapon VARCHAR(64)
|
464
|
+
);
|
465
|
+
'
|
466
|
+
File.open(new_fpath, 'w') do |f|
|
467
|
+
$xmigra_yamler.dump(impdecl_data, f)
|
468
|
+
end
|
469
|
+
|
470
|
+
do_or_die %Q{git add "#{decl_file}" "#{new_fpath}"}
|
471
|
+
do_or_die %Q{git commit -m "Create foo table"}
|
472
|
+
|
473
|
+
decl_file.delete
|
474
|
+
|
475
|
+
assert_raises XMigra::Program::ArgumentError do
|
476
|
+
XMigra::Program.run(
|
477
|
+
['impdecl', '--adopt', '--no-edit', decl_file.to_s]
|
478
|
+
)
|
479
|
+
end
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
483
|
+
class ImpdeclSupportMockFactory
|
484
|
+
def initialize
|
485
|
+
@instances = []
|
486
|
+
end
|
487
|
+
|
488
|
+
attr_reader :instances
|
489
|
+
|
490
|
+
class Instance
|
491
|
+
include XMigra::ImpdeclMigrationAdder::SupportedDatabaseObject
|
492
|
+
|
493
|
+
def initialize(name, declared_structure)
|
494
|
+
@name = name
|
495
|
+
@declared_structure = declared_structure
|
496
|
+
|
497
|
+
@creation_calls = []
|
498
|
+
@revision_calls = []
|
499
|
+
@destruction_calls = []
|
500
|
+
end
|
501
|
+
|
502
|
+
attr_reader :name, :declared_structure
|
503
|
+
attr_reader :creation_calls, :revision_calls, :destruction_calls
|
504
|
+
|
505
|
+
def creation_sql(*args)
|
506
|
+
@creation_calls << args
|
507
|
+
method :check_execution_environment_sql
|
508
|
+
return nil
|
509
|
+
end
|
510
|
+
|
511
|
+
def sql_to_effect_from(*args)
|
512
|
+
@revision_calls << args
|
513
|
+
method :check_execution_environment_sql
|
514
|
+
return nil
|
515
|
+
end
|
516
|
+
|
517
|
+
def destruction_sql(*args)
|
518
|
+
@destruction_calls << args
|
519
|
+
method :check_execution_environment_sql
|
520
|
+
return nil
|
521
|
+
end
|
522
|
+
end
|
523
|
+
|
524
|
+
def new(name, declared_structure)
|
525
|
+
Instance.new(name, declared_structure).tap do |instance|
|
526
|
+
@instances << instance
|
527
|
+
end
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
def has_dbspecifics(o)
|
532
|
+
XMigra::DatabaseSupportModules.find {|m| o.kind_of? m}
|
533
|
+
end
|
534
|
+
|
535
|
+
run_test "XMigra uses an associated handler to generate construction SQL" do
|
536
|
+
in_xmigra_schema do
|
537
|
+
do_or_die "git init", "Unable to initialize git repository"
|
538
|
+
test_tag = "!test_tag_value"
|
539
|
+
decl_file = add_foo_declarative(test_tag)
|
540
|
+
|
541
|
+
support_mock_factory = ImpdeclSupportMockFactory.new
|
542
|
+
XMigra::ImpdeclMigrationAdder.register_support_type(
|
543
|
+
test_tag,
|
544
|
+
support_mock_factory
|
545
|
+
) do
|
546
|
+
tool = XMigra::ImpdeclMigrationAdder.new('.')
|
547
|
+
tool.strict = true
|
548
|
+
assert {has_dbspecifics(tool)}
|
549
|
+
assert_include(
|
550
|
+
XMigra::DatabaseSupportModules,
|
551
|
+
tool.instance_variable_get(:@db_specifics)
|
552
|
+
)
|
553
|
+
assert {!tool.instance_variable_get(:@db_specifics).nil?}
|
554
|
+
tool.add_migration_implementing_changes(decl_file)
|
555
|
+
end
|
556
|
+
|
557
|
+
# Check that using XMigra::ImpdeclMigrationAdder#register_support_type with
|
558
|
+
# a block does not polute the support type mapping outside the block
|
559
|
+
assert {XMigra::ImpdeclMigrationAdder.support_type(test_tag).nil?}
|
560
|
+
|
561
|
+
# support_mock_factory should have created exactly 1 instance
|
562
|
+
assert_eq(support_mock_factory.instances.length, 1)
|
563
|
+
sql_factory = support_mock_factory.instances[0]
|
564
|
+
|
565
|
+
|
566
|
+
assert {sql_factory.instance_of? ImpdeclSupportMockFactory::Instance}
|
567
|
+
assert_eq(sql_factory.name, 'foo')
|
568
|
+
assert {sql_factory.declared_structure.kind_of? Hash}
|
569
|
+
assert_eq(sql_factory.creation_calls, [[]])
|
570
|
+
assert_eq(sql_factory.revision_calls, [])
|
571
|
+
assert_eq(sql_factory.destruction_calls, [])
|
572
|
+
assert {has_dbspecifics(sql_factory)}
|
573
|
+
end
|
574
|
+
end
|
575
|
+
|
576
|
+
run_test "XMigra uses an associated handler to generate revision SQL" do
|
577
|
+
in_xmigra_schema do
|
578
|
+
do_or_die "git init", "Unable to initialize git repository"
|
579
|
+
test_tag = "!test_tag_value"
|
580
|
+
decl_file = add_foo_declarative(test_tag)
|
581
|
+
|
582
|
+
tool = XMigra::ImpdeclMigrationAdder.new('.')
|
583
|
+
new_fpath = tool.add_migration_implementing_changes(decl_file)
|
584
|
+
|
585
|
+
impdecl_data = YAML.load_file(new_fpath)
|
586
|
+
impdecl_data.delete(XMigra::DeclarativeMigration::QUALIFICATION_KEY)
|
587
|
+
impdecl_data['sql'] = '
|
588
|
+
CREATE TABLE foo (
|
589
|
+
id BIGINT PRIMARY KEY,
|
590
|
+
weapon VARCHAR(64)
|
591
|
+
);
|
592
|
+
'
|
593
|
+
File.open(new_fpath, 'w') do |f|
|
594
|
+
$xmigra_yamler.dump(impdecl_data, f)
|
595
|
+
end
|
596
|
+
|
597
|
+
do_or_die %Q{git add "#{decl_file}" "#{new_fpath}"}
|
598
|
+
do_or_die %Q{git commit -m "Create foo table"}
|
599
|
+
|
600
|
+
decl_tree = YAML.parse_stream(decl_file.read)
|
601
|
+
columns_seq = decl_tree.children[0].children[0].children[1]
|
602
|
+
columns_seq.children << YAML.parse(YAML.dump({
|
603
|
+
'name'=>'caliber',
|
604
|
+
'type'=>'float(53)',
|
605
|
+
})).children[0]
|
606
|
+
decl_file.open('w') do |f|
|
607
|
+
f.write(decl_tree.to_yaml)
|
608
|
+
end
|
609
|
+
|
610
|
+
support_mock_factory = ImpdeclSupportMockFactory.new
|
611
|
+
XMigra::ImpdeclMigrationAdder.register_support_type(
|
612
|
+
test_tag,
|
613
|
+
support_mock_factory
|
614
|
+
) do
|
615
|
+
tool = XMigra::ImpdeclMigrationAdder.new('.')
|
616
|
+
tool.strict = true
|
617
|
+
tool.add_migration_implementing_changes(decl_file)
|
618
|
+
end
|
619
|
+
|
620
|
+
assert_eq(support_mock_factory.instances.length, 2)
|
621
|
+
old_state, sql_factory = support_mock_factory.instances
|
622
|
+
[:creation_calls, :revision_calls, :destruction_calls].each do |mname|
|
623
|
+
assert_eq(old_state.send(mname), [])
|
624
|
+
end
|
625
|
+
assert_eq(sql_factory.creation_calls, [])
|
626
|
+
assert_eq(sql_factory.revision_calls, [[old_state]])
|
627
|
+
assert_eq(sql_factory.destruction_calls, [])
|
628
|
+
end
|
629
|
+
end
|
630
|
+
|
631
|
+
run_test "XMigra uses an associated handler to generate destruction SQL" do
|
632
|
+
in_xmigra_schema do
|
633
|
+
do_or_die "git init", "Unable to initialize git repository"
|
634
|
+
test_tag = "!test_tag_value"
|
635
|
+
decl_file = add_foo_declarative(test_tag)
|
636
|
+
|
637
|
+
tool = XMigra::ImpdeclMigrationAdder.new('.')
|
638
|
+
new_fpath = tool.add_migration_implementing_changes(decl_file)
|
639
|
+
|
640
|
+
impdecl_data = YAML.load_file(new_fpath)
|
641
|
+
impdecl_data.delete(XMigra::DeclarativeMigration::QUALIFICATION_KEY)
|
642
|
+
impdecl_data['sql'] = '
|
643
|
+
CREATE TABLE foo (
|
644
|
+
id BIGINT PRIMARY KEY,
|
645
|
+
weapon VARCHAR(64)
|
646
|
+
);
|
647
|
+
'
|
648
|
+
File.open(new_fpath, 'w') do |f|
|
649
|
+
$xmigra_yamler.dump(impdecl_data, f)
|
650
|
+
end
|
651
|
+
|
652
|
+
do_or_die %Q{git add "#{decl_file}" "#{new_fpath}"}
|
653
|
+
do_or_die %Q{git commit -m "Create foo table"}
|
654
|
+
|
655
|
+
decl_file.delete
|
656
|
+
|
657
|
+
support_mock_factory = ImpdeclSupportMockFactory.new
|
658
|
+
XMigra::ImpdeclMigrationAdder.register_support_type(
|
659
|
+
test_tag,
|
660
|
+
support_mock_factory
|
661
|
+
) do
|
662
|
+
tool = XMigra::ImpdeclMigrationAdder.new('.')
|
663
|
+
tool.strict = true
|
664
|
+
tool.add_migration_implementing_changes(decl_file)
|
665
|
+
end
|
666
|
+
|
667
|
+
assert_eq(support_mock_factory.instances.length, 1)
|
668
|
+
sql_factory = support_mock_factory.instances[0]
|
669
|
+
assert_eq(sql_factory.creation_calls, [])
|
670
|
+
assert_eq(sql_factory.revision_calls, [])
|
671
|
+
assert_eq(sql_factory.destruction_calls, [[]])
|
672
|
+
end
|
673
|
+
end
|
674
|
+
|
675
|
+
run_test "DeclarativeSupport::Table can create tables with \"NOT NULL\" columns" do
|
676
|
+
in_xmigra_schema do
|
677
|
+
do_or_die "git init", "Unable to initialize git repository"
|
678
|
+
decl_file = add_foo_declarative("!table")
|
679
|
+
|
680
|
+
deserializer = XMigra::ImpdeclMigrationAdder::SupportedObjectDeserializer.new(decl_file.basename('.yaml').to_s, XMigra::NoSpecifics)
|
681
|
+
table_yaml = YAML.parse_file(decl_file)
|
682
|
+
table = deserializer.deserialize(table_yaml.children[0])
|
683
|
+
table.get_column('weapon').nullable = false
|
684
|
+
|
685
|
+
assert('weapon column did not have "NOT NULL"') do
|
686
|
+
table.table_creation_items.any? do |i|
|
687
|
+
next unless i.kind_of?(XMigra::DeclarativeSupport::Table::ColumnCreationFragment)
|
688
|
+
next unless i.column.name == 'weapon'
|
689
|
+
next unless i.creation_sql =~ /NOT\s+NULL/
|
690
|
+
true
|
691
|
+
end
|
692
|
+
end
|
693
|
+
end
|
694
|
+
end
|
695
|
+
|
696
|
+
run_test "DeclarativeSupport::Table can add or remove \"NOT NULL\" from columns" do
|
697
|
+
in_xmigra_schema do
|
698
|
+
do_or_die "git init", "Unable to initialize git repository"
|
699
|
+
decl_file = add_foo_declarative
|
700
|
+
|
701
|
+
deserializer = XMigra::ImpdeclMigrationAdder::SupportedObjectDeserializer.new(decl_file.basename('.yaml').to_s, XMigra::PgSQLSpecifics)
|
702
|
+
table_yaml = YAML.parse_file(decl_file)
|
703
|
+
table_null = deserializer.deserialize(table_yaml.children[0])
|
704
|
+
table_notnull = deserializer.deserialize(table_yaml.children[0])
|
705
|
+
table_notnull.get_column('weapon').nullable = false
|
706
|
+
|
707
|
+
delta = XMigra::DeclarativeSupport::Table::Delta.new(table_null, table_notnull)
|
708
|
+
assert_eq(delta.constraints_to_drop, [])
|
709
|
+
assert_eq(delta.new_columns, [])
|
710
|
+
assert_eq(delta.removed_columns, [])
|
711
|
+
assert_eq(delta.new_constraint_sql_clauses, [])
|
712
|
+
assert_eq(delta.altered_column_pairs.length, 1)
|
713
|
+
stmts = table_notnull.alter_table_columns_sql_statements(delta.altered_column_pairs)
|
714
|
+
assert_eq(stmts.length, 1)
|
715
|
+
assert_eq(stmts[0].gsub(/\s+/, ' ').upcase, "ALTER TABLE FOO ALTER COLUMN WEAPON SET NOT NULL;")
|
716
|
+
|
717
|
+
delta = XMigra::DeclarativeSupport::Table::Delta.new(table_notnull, table_null)
|
718
|
+
assert_eq(delta.constraints_to_drop, [])
|
719
|
+
assert_eq(delta.new_columns, [])
|
720
|
+
assert_eq(delta.removed_columns, [])
|
721
|
+
assert_eq(delta.new_constraint_sql_clauses, [])
|
722
|
+
assert_eq(delta.altered_column_pairs.length, 1)
|
723
|
+
stmts = table_null.alter_table_columns_sql_statements(delta.altered_column_pairs)
|
724
|
+
assert_eq(stmts.length, 1)
|
725
|
+
assert_eq(stmts[0].gsub(/\s+/, ' ').upcase, "ALTER TABLE FOO ALTER COLUMN WEAPON DROP NOT NULL;")
|
726
|
+
end
|
727
|
+
end
|
728
|
+
|
729
|
+
run_test "DeclarativeSupport::Table can create tables including columns with defaults" do
|
730
|
+
in_xmigra_schema do
|
731
|
+
do_or_die "git init", "Unable to initialize git repository"
|
732
|
+
decl_file = add_foo_declarative
|
733
|
+
|
734
|
+
deserializer = XMigra::ImpdeclMigrationAdder::SupportedObjectDeserializer.new(decl_file.basename('.yaml').to_s, XMigra::NoSpecifics)
|
735
|
+
table_yaml = YAML.parse_file(decl_file)
|
736
|
+
table = deserializer.deserialize(table_yaml.children[0])
|
737
|
+
table.add_default('weapon', "'knife'")
|
738
|
+
|
739
|
+
assert('weapon column does not have default') do
|
740
|
+
table.table_creation_items.any? do |i|
|
741
|
+
next unless i.kind_of?(XMigra::DeclarativeSupport::Table::ColumnCreationFragment)
|
742
|
+
next unless i.column.name == 'weapon'
|
743
|
+
next unless i.creation_sql =~ /DEFAULT\s+'knife'/
|
744
|
+
true
|
745
|
+
end
|
746
|
+
end
|
747
|
+
assert('default rendered as table constraint during table creation') do
|
748
|
+
!table.table_creation_items.any? do |i|
|
749
|
+
i.kind_of?(XMigra::DeclarativeSupport::Table::DefaultConstraint)
|
750
|
+
end
|
751
|
+
end
|
752
|
+
end
|
753
|
+
end
|
754
|
+
|
755
|
+
run_test "DeclarativeSupport::Table can add default constraints to or remove them from columns" do
|
756
|
+
in_xmigra_schema do
|
757
|
+
do_or_die "git init", "Unable to initialize git repository"
|
758
|
+
decl_file = add_foo_declarative
|
759
|
+
|
760
|
+
deserializer = XMigra::ImpdeclMigrationAdder::SupportedObjectDeserializer.new(decl_file.basename('.yaml').to_s, XMigra::PgSQLSpecifics)
|
761
|
+
table_yaml = YAML.parse_file(decl_file)
|
762
|
+
table_notdefaulted = deserializer.deserialize(table_yaml.children[0])
|
763
|
+
table_defaulted = deserializer.deserialize(table_yaml.children[0])
|
764
|
+
table_defaulted.add_default('weapon', "'knife'")
|
765
|
+
|
766
|
+
delta = XMigra::DeclarativeSupport::Table::Delta.new(table_notdefaulted, table_defaulted)
|
767
|
+
assert_eq(delta.new_columns, [])
|
768
|
+
assert_eq(delta.altered_column_pairs, [])
|
769
|
+
assert_eq(delta.removed_columns, [])
|
770
|
+
assert_eq(delta.constraints_to_drop, [])
|
771
|
+
assert_eq(delta.new_constraint_sql_clauses.length, 1)
|
772
|
+
assert_eq(
|
773
|
+
delta.new_constraint_sql_clauses[0].gsub(/\s+/, ' ').upcase,
|
774
|
+
"CONSTRAINT DF_WEAPON DEFAULT 'KNIFE' FOR WEAPON"
|
775
|
+
)
|
776
|
+
|
777
|
+
delta = XMigra::DeclarativeSupport::Table::Delta.new(table_defaulted, table_notdefaulted)
|
778
|
+
assert_eq(delta.new_columns, [])
|
779
|
+
assert_eq(delta.altered_column_pairs, [])
|
780
|
+
assert_eq(delta.removed_columns, [])
|
781
|
+
assert_eq(delta.new_constraint_sql_clauses, [])
|
782
|
+
assert_eq(delta.constraints_to_drop.length, 1)
|
783
|
+
assert_eq(delta.constraints_to_drop[0], "DF_weapon")
|
784
|
+
end
|
785
|
+
end
|
786
|
+
|
787
|
+
run_test "DeclarativeSupport::Table can alter an existing default constraint on a column" do
|
788
|
+
in_xmigra_schema do
|
789
|
+
do_or_die "git init", "Unable to initialize git repository"
|
790
|
+
decl_file = add_foo_declarative
|
791
|
+
|
792
|
+
deserializer = XMigra::ImpdeclMigrationAdder::SupportedObjectDeserializer.new(decl_file.basename('.yaml').to_s, XMigra::PgSQLSpecifics)
|
793
|
+
table_yaml = YAML.parse_file(decl_file)
|
794
|
+
table_old = deserializer.deserialize(table_yaml.children[0])
|
795
|
+
table_old.add_default('weapon', "'knife'")
|
796
|
+
table_new = deserializer.deserialize(table_yaml.children[0])
|
797
|
+
table_new.add_default('weapon', "'rock'")
|
798
|
+
|
799
|
+
delta = XMigra::DeclarativeSupport::Table::Delta.new(table_old, table_new)
|
800
|
+
assert_eq(delta.new_columns, [])
|
801
|
+
assert_eq(delta.altered_column_pairs, [])
|
802
|
+
assert_eq(delta.removed_columns, [])
|
803
|
+
assert_eq(delta.constraints_to_drop.length, 1)
|
804
|
+
assert_eq(delta.constraints_to_drop[0], "DF_weapon")
|
805
|
+
assert_eq(delta.new_constraint_sql_clauses.length, 1)
|
806
|
+
assert_eq(
|
807
|
+
delta.new_constraint_sql_clauses[0].gsub(/\s+/, ' ').upcase,
|
808
|
+
"CONSTRAINT DF_WEAPON DEFAULT 'ROCK' FOR WEAPON"
|
809
|
+
)
|
810
|
+
end
|
811
|
+
end
|