@@ -410,6 +410,224 @@ func TestDropMultiColumnConstraint(t *testing.T) {
410
410
})
411
411
}
412
412
413
+ func TestDropMultiColumnConstraintInMultiOperationMigrations (t * testing.T ) {
414
+ t .Parallel ()
415
+
416
+ ExecuteTests (t , TestCases {
417
+ {
418
+ name : "rename table, drop constraint" ,
419
+ migrations : []migrations.Migration {
420
+ {
421
+ Name : "01_create_table" ,
422
+ Operations : migrations.Operations {
423
+ & migrations.OpCreateTable {
424
+ Name : "items" ,
425
+ Columns : []migrations.Column {
426
+ {
427
+ Name : "id" ,
428
+ Type : "int" ,
429
+ Pk : true ,
430
+ },
431
+ {
432
+ Name : "name" ,
433
+ Type : "varchar(255)" ,
434
+ Nullable : true ,
435
+ Check : & migrations.CheckConstraint {
436
+ Name : "check_name_length" ,
437
+ Constraint : "length(name) > 3" ,
438
+ },
439
+ },
440
+ },
441
+ },
442
+ },
443
+ },
444
+ {
445
+ Name : "02_multi_operation" ,
446
+ Operations : migrations.Operations {
447
+ & migrations.OpRenameTable {
448
+ From : "items" ,
449
+ To : "products" ,
450
+ },
451
+ & migrations.OpDropMultiColumnConstraint {
452
+ Table : "products" ,
453
+ Name : "check_name_length" ,
454
+ Down : map [string ]string {
455
+ "name" : "SELECT CASE WHEN length(name) <= 3 THEN LPAD(name, 4, '-') ELSE name END" ,
456
+ },
457
+ Up : map [string ]string {
458
+ "name" : "name" ,
459
+ },
460
+ },
461
+ },
462
+ },
463
+ },
464
+ afterStart : func (t * testing.T , db * sql.DB , schema string ) {
465
+ // Can insert a row into the new schema that violates the constraint
466
+ MustInsert (t , db , schema , "02_multi_operation" , "products" , map [string ]string {
467
+ "id" : "1" ,
468
+ "name" : "a" ,
469
+ })
470
+
471
+ // Can't insert a row into the old schema that violates the constraint
472
+ MustNotInsert (t , db , schema , "01_create_table" , "items" , map [string ]string {
473
+ "id" : "2" ,
474
+ "name" : "b" ,
475
+ }, testutils .CheckViolationErrorCode )
476
+
477
+ // Can insert a row into the old schema that meets the constraint
478
+ MustInsert (t , db , schema , "01_create_table" , "items" , map [string ]string {
479
+ "id" : "2" ,
480
+ "name" : "bananas" ,
481
+ })
482
+
483
+ // The new view has the expected rows
484
+ rows := MustSelect (t , db , schema , "02_multi_operation" , "products" )
485
+ assert .Equal (t , []map [string ]any {
486
+ {"id" : 1 , "name" : "a" },
487
+ {"id" : 2 , "name" : "bananas" },
488
+ }, rows )
489
+
490
+ // The old view has the expected rows
491
+ rows = MustSelect (t , db , schema , "01_create_table" , "items" )
492
+ assert .Equal (t , []map [string ]any {
493
+ {"id" : 1 , "name" : "---a" }, // rewritten by the down migration
494
+ {"id" : 2 , "name" : "bananas" },
495
+ }, rows )
496
+ },
497
+ afterRollback : func (t * testing.T , db * sql.DB , schema string ) {
498
+ // The table has been cleaned up
499
+ TableMustBeCleanedUp (t , db , schema , "items" , "name" )
500
+ },
501
+ afterComplete : func (t * testing.T , db * sql.DB , schema string ) {
502
+ // Can insert a row into the new schema that violates the constraint
503
+ MustInsert (t , db , schema , "02_multi_operation" , "products" , map [string ]string {
504
+ "id" : "3" ,
505
+ "name" : "c" ,
506
+ })
507
+
508
+ // The new view has the expected rows
509
+ rows := MustSelect (t , db , schema , "02_multi_operation" , "products" )
510
+ assert .Equal (t , []map [string ]any {
511
+ {"id" : 1 , "name" : "---a" },
512
+ {"id" : 2 , "name" : "bananas" },
513
+ {"id" : 3 , "name" : "c" },
514
+ }, rows )
515
+
516
+ // The table has been cleaned up
517
+ TableMustBeCleanedUp (t , db , schema , "products" , "name" )
518
+ },
519
+ },
520
+ {
521
+ name : "rename table, rename column, drop constraint" ,
522
+ migrations : []migrations.Migration {
523
+ {
524
+ Name : "01_create_table" ,
525
+ Operations : migrations.Operations {
526
+ & migrations.OpCreateTable {
527
+ Name : "items" ,
528
+ Columns : []migrations.Column {
529
+ {
530
+ Name : "id" ,
531
+ Type : "int" ,
532
+ Pk : true ,
533
+ },
534
+ {
535
+ Name : "name" ,
536
+ Type : "varchar(255)" ,
537
+ Nullable : true ,
538
+ Check : & migrations.CheckConstraint {
539
+ Name : "check_name_length" ,
540
+ Constraint : "length(name) > 3" ,
541
+ },
542
+ },
543
+ },
544
+ },
545
+ },
546
+ },
547
+ {
548
+ Name : "02_multi_operation" ,
549
+ Operations : migrations.Operations {
550
+ & migrations.OpRenameTable {
551
+ From : "items" ,
552
+ To : "products" ,
553
+ },
554
+ & migrations.OpRenameColumn {
555
+ Table : "products" ,
556
+ From : "name" ,
557
+ To : "item_name" ,
558
+ },
559
+ & migrations.OpDropMultiColumnConstraint {
560
+ Table : "products" ,
561
+ Name : "check_name_length" ,
562
+ Down : map [string ]string {
563
+ "item_name" : "SELECT CASE WHEN length(item_name) <= 3 THEN LPAD(item_name, 4, '-') ELSE item_name END" ,
564
+ },
565
+ Up : map [string ]string {
566
+ "item_name" : "item_name" ,
567
+ },
568
+ },
569
+ },
570
+ },
571
+ },
572
+ afterStart : func (t * testing.T , db * sql.DB , schema string ) {
573
+ // Can insert a row into the new schema that violates the constraint
574
+ MustInsert (t , db , schema , "02_multi_operation" , "products" , map [string ]string {
575
+ "id" : "1" ,
576
+ "item_name" : "a" ,
577
+ })
578
+
579
+ // Can't insert a row into the old schema that violates the constraint
580
+ MustNotInsert (t , db , schema , "01_create_table" , "items" , map [string ]string {
581
+ "id" : "2" ,
582
+ "name" : "b" ,
583
+ }, testutils .CheckViolationErrorCode )
584
+
585
+ // Can insert a row into the old schema that meets the constraint
586
+ MustInsert (t , db , schema , "01_create_table" , "items" , map [string ]string {
587
+ "id" : "2" ,
588
+ "name" : "bananas" ,
589
+ })
590
+
591
+ // The new view has the expected rows
592
+ rows := MustSelect (t , db , schema , "02_multi_operation" , "products" )
593
+ assert .Equal (t , []map [string ]any {
594
+ {"id" : 1 , "item_name" : "a" },
595
+ {"id" : 2 , "item_name" : "bananas" },
596
+ }, rows )
597
+
598
+ // The old view has the expected rows
599
+ rows = MustSelect (t , db , schema , "01_create_table" , "items" )
600
+ assert .Equal (t , []map [string ]any {
601
+ {"id" : 1 , "name" : "---a" }, // rewritten by the down migration
602
+ {"id" : 2 , "name" : "bananas" },
603
+ }, rows )
604
+ },
605
+ afterRollback : func (t * testing.T , db * sql.DB , schema string ) {
606
+ // The table has been cleaned up
607
+ TableMustBeCleanedUp (t , db , schema , "items" , "name" )
608
+ },
609
+ afterComplete : func (t * testing.T , db * sql.DB , schema string ) {
610
+ // Can insert a row into the new schema that violates the constraint
611
+ MustInsert (t , db , schema , "02_multi_operation" , "products" , map [string ]string {
612
+ "id" : "3" ,
613
+ "item_name" : "c" ,
614
+ })
615
+
616
+ // The new view has the expected rows
617
+ rows := MustSelect (t , db , schema , "02_multi_operation" , "products" )
618
+ assert .Equal (t , []map [string ]any {
619
+ {"id" : 1 , "item_name" : "---a" },
620
+ {"id" : 2 , "item_name" : "bananas" },
621
+ {"id" : 3 , "item_name" : "c" },
622
+ }, rows )
623
+
624
+ // The table has been cleaned up
625
+ TableMustBeCleanedUp (t , db , schema , "products" , "name" )
626
+ },
627
+ },
628
+ })
629
+ }
630
+
413
631
func TestDropMultiColumnConstraintValidation (t * testing.T ) {
414
632
t .Parallel ()
415
633
0 commit comments