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.
@@ -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