github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/tests/integration_tests/default_value/main.go (about) 1 // Copyright 2022 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package main 15 16 import ( 17 "context" 18 "database/sql" 19 "flag" 20 "fmt" 21 "os" 22 "reflect" 23 "runtime" 24 "strings" 25 "sync" 26 "sync/atomic" 27 "time" 28 29 guuid "github.com/google/uuid" 30 "github.com/pingcap/errors" 31 "github.com/pingcap/log" 32 "github.com/pingcap/tiflow/pkg/workerpool" 33 "github.com/pingcap/tiflow/tests/integration_tests/util" 34 "go.uber.org/zap" 35 ) 36 37 var finishIdx int32 38 39 func main() { 40 cfg := util.NewConfig() 41 err := cfg.Parse(os.Args[1:]) 42 switch errors.Cause(err) { 43 case nil: 44 case flag.ErrHelp: 45 os.Exit(0) 46 default: 47 log.S().Errorf("parse cmd flags err %s\n", err) 48 os.Exit(2) 49 } 50 51 sourceDB0, err := util.CreateDB(cfg.SourceDBCfg[0]) 52 if err != nil { 53 log.S().Fatal(err) 54 } 55 defer func() { 56 if err := util.CloseDB(sourceDB0); err != nil { 57 log.S().Errorf("Failed to close source database: %s\n", err) 58 } 59 }() 60 sourceDB1, err := util.CreateDB(cfg.SourceDBCfg[1]) 61 if err != nil { 62 log.S().Fatal(err) 63 } 64 defer func() { 65 if err := util.CloseDB(sourceDB1); err != nil { 66 log.S().Errorf("Failed to close source database: %s\n", err) 67 } 68 }() 69 70 util.MustExec(sourceDB0, "create database mark;") 71 var wg sync.WaitGroup 72 start := time.Now() 73 defer func() { 74 log.S().Infof("DefaultValue integration tests take %v", time.Since(start)) 75 }() 76 wg.Add(2) 77 go testMultiDDLs([]*sql.DB{sourceDB0, sourceDB1}, &wg) 78 go testGetDefaultValue([]*sql.DB{sourceDB0, sourceDB1}, &wg) 79 wg.Wait() 80 util.MustExec(sourceDB0, "create table mark.finish_mark(a int primary key);") 81 } 82 83 // for every DDL, run the DDL continuously, and one goroutine for one TiDB instance to do some DML op 84 func testGetDefaultValue(srcs []*sql.DB, wg *sync.WaitGroup) { 85 defer wg.Done() 86 start := time.Now() 87 defer func() { 88 log.S().Infof("testGetDefaultValue take %v", time.Since(start)) 89 }() 90 91 var wg2 sync.WaitGroup 92 for i, ddlFunc := range []func(context.Context, *sql.DB){ 93 modifyColumnDefaultValueDDL1, modifyColumnDefaultValueDDL2, 94 } { 95 wg2.Add(1) 96 go func(i int, ddlFunc func(context.Context, *sql.DB)) { 97 defer wg2.Done() 98 testName := getFunctionName(ddlFunc) 99 log.S().Info("running ddl test: ", i, " ", testName) 100 101 var wg1 sync.WaitGroup 102 ctx, cancel := context.WithCancel(context.Background()) 103 104 for idx, src := range srcs { 105 wg1.Add(1) 106 go func(i int, s *sql.DB) { 107 dml(ctx, s, testName, i, nil) 108 defer wg1.Done() 109 }(idx, src) 110 } 111 112 time.Sleep(5 * time.Millisecond) 113 114 wg1.Add(1) 115 go func() { 116 ddlFunc(ctx, srcs[0]) 117 cancel() 118 wg1.Done() 119 }() 120 121 wg1.Wait() 122 123 util.MustExec(srcs[0], fmt.Sprintf("create table mark.finish_mark_%d(a int primary key);", atomic.AddInt32(&finishIdx, 1))) 124 }(i, ddlFunc) 125 } 126 wg2.Wait() 127 } 128 129 func getFunctionName(i interface{}) string { 130 strs := strings.Split(runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name(), ".") 131 return strs[len(strs)-1] 132 } 133 134 func ignoreableError(err error) bool { 135 knownErrorList := []string{ 136 "Error 1146", // table doesn't exist 137 "Error 1049", // database doesn't exist 138 "Error 1054", // unknown column 139 } 140 for _, e := range knownErrorList { 141 if strings.HasPrefix(err.Error(), e) { 142 return true 143 } 144 } 145 return false 146 } 147 148 // TODO: need cover the scenarios: update existing old value 149 func dml(ctx context.Context, db *sql.DB, table string, id int, defaultValue interface{}) { 150 var err error 151 var i int 152 var insertSuccess int 153 var deleteSuccess int 154 var insertSQL string 155 var updateSQL string 156 157 if defaultValue != nil { 158 insertSQL = fmt.Sprintf("insert into test.`%s`(id1, id2, v1) values(?,?,?)", table) 159 } else { 160 insertSQL = fmt.Sprintf("insert into test.`%s`(id1, id2) values(?,?)", table) 161 } 162 deleteSQL := fmt.Sprintf("delete from test.`%s` where id1 = ? or id2 = ?", table) 163 164 // When meet `not null+no default` and `update`, it may trigger strict sql mode error 165 if defaultValue == nil { 166 updateSQL = fmt.Sprintf("update test.`%s` set v0=13 where id1 = ? or id2 = ?", table) 167 } 168 169 for i = 0; ; i++ { 170 if defaultValue != nil { 171 _, err = db.Exec(insertSQL, i+id*10000000, i+id*10000000+1, defaultValue) 172 } else { 173 _, err = db.Exec(insertSQL, i+id*10000000, i+id*10000000+1) 174 } 175 if err == nil { 176 insertSuccess++ 177 if insertSuccess%100 == 0 { 178 log.S().Info(id, " insert success: ", insertSuccess) 179 } 180 } 181 if err != nil && !ignoreableError(err) { 182 log.Fatal("unexpected error when executing sql", zap.Error(err)) 183 } 184 185 if i%2 == 0 { 186 if defaultValue == nil { 187 _, err := db.Exec(updateSQL, i+id*100000000, i+id*100000000+1) 188 if err != nil && !ignoreableError(err) { 189 log.Fatal("unexpected error when executing sql", zap.Error(err)) 190 } 191 } 192 193 result, err := db.Exec(deleteSQL, i+id*100000000, i+id*100000000+1) 194 if err == nil { 195 rows, _ := result.RowsAffected() 196 if rows != 0 { 197 deleteSuccess++ 198 if deleteSuccess%100 == 0 { 199 log.S().Info(id, " delete success: ", deleteSuccess) 200 } 201 } 202 } 203 if err != nil && !ignoreableError(err) { 204 log.Fatal("unexpected error when executing sql", zap.Error(err)) 205 } 206 } 207 208 if i%100 == 0 { 209 time.Sleep(100 * time.Millisecond) 210 } 211 212 select { 213 case <-ctx.Done(): 214 return 215 default: 216 } 217 } 218 } 219 220 // Test `add column default null` + `modify column default xxx`/`alter column set default xxx` 221 // DefaultValue will be changed by modify column/alter column, but OriginalDefaultValue 222 // is only assigned by `add column default xxx` 223 func modifyColumnDefaultValueDDL1(ctx context.Context, db *sql.DB) { 224 testName := getFunctionName(modifyColumnDefaultValueDDL1) 225 mustCreateTable(db, testName) 226 227 modifyColumnFmts := []string{ 228 "alter table test.`%s` modify column v1 int default ?", 229 "alter table test.`%s` alter column v1 set default ?", 230 } 231 232 for _, modifyFmt := range modifyColumnFmts { 233 for value := 1; value < 3; value++ { 234 select { 235 case <-ctx.Done(): 236 return 237 default: 238 } 239 240 var defaultValue interface{} 241 242 if value%2 != 0 { 243 defaultValue = value 244 } else { 245 // use default null 246 defaultValue = nil 247 } 248 249 sql := fmt.Sprintf(modifyFmt, testName) 250 util.MustExec(db, sql, defaultValue) 251 time.Sleep(3 * time.Millisecond) 252 } 253 } 254 } 255 256 // Test `add column default xxx` + `modify column default xxx`/`alter column set default xxx` 257 // DefaultValue will be changed by modify column/alter column, but OriginalDefaultValue 258 // is only assigned by `add column default xxx` 259 func modifyColumnDefaultValueDDL2(ctx context.Context, db *sql.DB) { 260 testName := getFunctionName(modifyColumnDefaultValueDDL2) 261 mustCreateTable(db, testName) 262 sql := fmt.Sprintf("alter table test.`%s` drop column v1", testName) 263 util.MustExec(db, sql) 264 sql = fmt.Sprintf("alter table test.`%s` add column v1 int default 11", testName) 265 util.MustExec(db, sql) 266 267 modifyColumnFmts := []string{ 268 "alter table test.`%s` modify column v1 int default ?", 269 "alter table test.`%s` alter column v1 set default ? ", 270 } 271 272 for _, modifyFmt := range modifyColumnFmts { 273 for value := 1; value < 3; value++ { 274 select { 275 case <-ctx.Done(): 276 return 277 default: 278 } 279 280 var defaultValue interface{} 281 282 if value%2 != 0 { 283 defaultValue = value 284 } else { 285 // use default null 286 defaultValue = nil 287 } 288 289 sql := fmt.Sprintf(modifyFmt, testName) 290 util.MustExec(db, sql, defaultValue) 291 time.Sleep(3 * time.Millisecond) 292 } 293 } 294 } 295 296 func ddlZeroValueFunc(ctx context.Context, db *sql.DB, format string, table string, 297 defaultValue interface{}, 298 ) { 299 // drop column at first 300 fm := fmt.Sprintf("alter table test.`%s` drop column v1", table) 301 util.MustExec(db, fm) 302 303 for value := 1; value < 3; value++ { 304 select { 305 case <-ctx.Done(): 306 return 307 default: 308 } 309 // add column 310 sql := fmt.Sprintf(format, table) 311 util.MustExec(db, sql) 312 time.Sleep(3 * time.Millisecond) 313 // drop column 314 sql = fmt.Sprintf("alter table test.`%s` drop column v1", table) 315 util.MustExec(db, sql) 316 time.Sleep(3 * time.Millisecond) 317 } 318 } 319 320 func ddlDefaultValueFunc(ctx context.Context, db *sql.DB, format string, table string, 321 defaultValue interface{}, 322 ) { 323 for value := 1; value < 3; value++ { 324 select { 325 case <-ctx.Done(): 326 return 327 default: 328 } 329 sql := fmt.Sprintf("alter table test.`%s` drop column v1", table) 330 util.MustExec(db, sql) 331 time.Sleep(3 * time.Millisecond) 332 333 var notNULL string 334 335 if value%2 == 0 { 336 // use default <value> not null 337 notNULL = "not null" 338 } 339 sql = fmt.Sprintf(format, table, notNULL) 340 util.MustExec(db, sql, defaultValue) 341 time.Sleep(3 * time.Millisecond) 342 } 343 } 344 345 func testMultiDDLs(srcs []*sql.DB, wg *sync.WaitGroup) { 346 defer wg.Done() 347 348 type Unit struct { 349 Fmt string 350 DefaultValue interface{} 351 DDLFunc func(context.Context, *sql.DB, string, string, interface{}) 352 NoDMLParas bool 353 } 354 355 Units := []Unit{ 356 ///////////////// Zero Value Cases 357 // Test `column not null` + drop column(online DDL/delete-only state), which will trigger GetZeroValue 358 // NOTICE: when meet `add column xxx not null`, TiDB will add OriginalDefaultValue automatically 359 // Not null + no default value 360 // date and time data type 361 { 362 "alter table test.`%s` add column v1 date not null", 363 "2020-10-10", 364 ddlZeroValueFunc, 365 false, 366 }, 367 { 368 "alter table test.`%s` add column v1 datetime not null", 369 "2020-10-10 10:10:10", 370 ddlZeroValueFunc, 371 false, 372 }, 373 { 374 "alter table test.`%s` add column v1 timestamp not null", 375 "2020-10-10 10:10:10", 376 ddlZeroValueFunc, 377 false, 378 }, 379 { 380 "alter table test.`%s` add column v1 time not null", 381 "10:10:10", 382 ddlZeroValueFunc, 383 false, 384 }, 385 { 386 "alter table test.`%s` add column v1 year not null", 387 "2020", 388 ddlZeroValueFunc, 389 false, 390 }, 391 { 392 // For int year default 393 "alter table test.`%s` add column v1 year not null", 394 2020, 395 ddlZeroValueFunc, 396 false, 397 }, 398 /* 399 // normal cases, we may transfer to test-infra to reduce cost 400 { 401 "alter table test.`%s` add column v1 datetime(5) not null", 402 "2020-10-10 10:10:10.9999", 403 ddlZeroValueFunc, 404 false, 405 }, 406 { 407 "alter table test.`%s` add column v1 timestamp(5) not null", 408 "2020-10-10 10:10:10.9999", 409 ddlZeroValueFunc, 410 false, 411 }, 412 { 413 "alter table test.`%s` add column v1 time(5) not null", 414 "10:10:10.9999", 415 ddlZeroValueFunc, 416 false, 417 }, 418 */ 419 // numeric data type 420 { 421 // default bit[1] 422 "alter table test.`%s` add column v1 bit not null", 423 []byte{0x01}, 424 ddlZeroValueFunc, 425 false, 426 }, 427 { 428 "alter table test.`%s` add column v1 tinyint not null", 429 -13, 430 ddlZeroValueFunc, 431 false, 432 }, 433 /* 434 { 435 "alter table test.`%s` add column v1 mediumint not null", 436 -13, 437 ddlZeroValueFunc, 438 false, 439 }, 440 { 441 "alter table test.`%s` add column v1 int not null", 442 -13, 443 ddlZeroValueFunc, 444 false, 445 }, 446 { 447 "alter table test.`%s` add column v1 bigint not null", 448 -13, 449 ddlZeroValueFunc, 450 false, 451 }, 452 */ 453 { 454 "alter table test.`%s` add column v1 decimal(5) not null", 455 -13, 456 ddlZeroValueFunc, 457 false, 458 }, 459 { 460 "alter table test.`%s` add column v1 float not null", 461 -13.13, 462 ddlZeroValueFunc, 463 false, 464 }, 465 { 466 "alter table test.`%s` add column v1 double not null", 467 -13.13, 468 ddlZeroValueFunc, 469 false, 470 }, 471 /* 472 // normal cases, we may transfer to test-infra to reduce cost 473 { 474 "alter table test.`%s` add column v1 bit(4) not null", 475 []byte{0x03}, 476 ddlZeroValueFunc, 477 false, 478 }, 479 { 480 "alter table test.`%s` add column v1 tinyint(4) unsigned not null", 481 13, 482 ddlZeroValueFunc, 483 false, 484 }, 485 { 486 "alter table test.`%s` add column v1 mediumint(4) unsigned not null", 487 13, 488 ddlZeroValueFunc, 489 false, 490 }, 491 { 492 "alter table test.`%s` add column v1 int(4) unsigned not null", 493 13, 494 ddlZeroValueFunc, 495 false, 496 }, 497 { 498 "alter table test.`%s` add column v1 bigint(4) unsigned not null", 499 13, 500 ddlZeroValueFunc, 501 false, 502 }, 503 { 504 "alter table test.`%s` add column v1 decimal(5,2) unsigned not null", 505 13.13, 506 ddlZeroValueFunc, 507 false, 508 }, 509 { 510 "alter table test.`%s` add column v1 float(5,2) unsigned not null", 511 13.13, 512 ddlZeroValueFunc, 513 false, 514 }, 515 { 516 "alter table test.`%s` add column v1 double(5,2) unsigned not null", 517 13.13, 518 ddlZeroValueFunc, 519 false, 520 }, 521 */ 522 // string data type 523 { 524 "alter table test.`%s` add column v1 char(10) not null", 525 "char", 526 ddlZeroValueFunc, 527 false, 528 }, 529 { 530 "alter table test.`%s` add column v1 varchar(10) not null", 531 "varchar", 532 ddlZeroValueFunc, 533 false, 534 }, 535 { 536 "alter table test.`%s` add column v1 binary(10) not null", 537 "binary", 538 ddlZeroValueFunc, 539 false, 540 }, 541 { 542 "alter table test.`%s` add column v1 varbinary(10) not null", 543 "varbinary", 544 ddlZeroValueFunc, 545 false, 546 }, 547 { 548 "alter table test.`%s` add column v1 blob not null", 549 "blob", 550 ddlZeroValueFunc, 551 false, 552 }, 553 { 554 "alter table test.`%s` add column v1 text not null", 555 "text", 556 ddlZeroValueFunc, 557 false, 558 }, 559 { 560 "alter table test.`%s` add column v1 enum('e0', 'e1') not null", 561 "e1", 562 ddlZeroValueFunc, 563 false, 564 }, 565 { 566 "alter table test.`%s` add column v1 set('e0', 'e1') not null", 567 "e0,e1", 568 ddlZeroValueFunc, 569 false, 570 }, 571 // json data type 572 { 573 "alter table test.`%s` add column v1 json not null", 574 "[99, {\"id\": \"HK500\", \"cost\": 75.99}, [\"hot\", \"cold\"]]", 575 ddlZeroValueFunc, 576 false, 577 }, 578 579 ////////////////////// Default Value Cases 580 // [TODO] add some dynamic type here, CURRENT_TIMESTAMP 581 // Ref: https://dev.mysql.com/doc/refman/8.0/en/data-type-defaults.html 582 // Test add column with different column type 583 // All OriginalDefaultValue is string type 584 // date and time data type 585 { 586 "alter table test.`%s` add column v1 date default ? %s", 587 "2020-10-10", 588 ddlDefaultValueFunc, 589 true, 590 }, 591 { 592 "alter table test.`%s` add column v1 datetime default ? %s", 593 "2020-10-10 10:10:10", 594 ddlDefaultValueFunc, 595 true, 596 }, 597 { 598 "alter table test.`%s` add column v1 timestamp default ? %s", 599 "2020-10-10 10:10:10", 600 ddlDefaultValueFunc, 601 true, 602 }, 603 { 604 "alter table test.`%s` add column v1 time default ? %s", 605 "10:10:10", 606 ddlDefaultValueFunc, 607 true, 608 }, 609 { 610 "alter table test.`%s` add column v1 year default ? %s", 611 "2020", 612 ddlDefaultValueFunc, 613 true, 614 }, 615 { 616 // For int year default 617 "alter table test.`%s` add column v1 year default ? %s", 618 2020, 619 ddlDefaultValueFunc, 620 true, 621 }, 622 /* 623 { 624 "alter table test.`%s` add column v1 datetime(5) default ? %s", 625 "2020-10-10 10:10:10.9999", 626 ddlDefaultValueFunc, 627 true, 628 }, 629 { 630 "alter table test.`%s` add column v1 timestamp(5) default ? %s", 631 "2020-10-10 10:10:10.9999", 632 ddlDefaultValueFunc, 633 true, 634 }, 635 { 636 "alter table test.`%s` add column v1 time(5) default ? %s", 637 "10:10:10.9999", 638 ddlDefaultValueFunc, 639 true, 640 }, 641 */ 642 // numeric data type 643 { 644 // default bit[1] 645 "alter table test.`%s` add column v1 bit default ? %s", 646 []byte{0x01}, 647 ddlDefaultValueFunc, 648 true, 649 }, 650 { 651 "alter table test.`%s` add column v1 tinyint default ? %s", 652 -13, 653 ddlDefaultValueFunc, 654 true, 655 }, 656 /* 657 // normal cases, we may transfer to test-infra to reduce cost 658 { 659 "alter table test.`%s` add column v1 mediumint default ? %s", 660 -13, 661 ddlDefaultValueFunc, 662 true, 663 }, 664 { 665 "alter table test.`%s` add column v1 int default ? %s", 666 -13, 667 ddlDefaultValueFunc, 668 true, 669 }, 670 { 671 "alter table test.`%s` add column v1 bigint default ? %s", 672 -13, 673 ddlDefaultValueFunc, 674 true, 675 }, 676 */ 677 { 678 "alter table test.`%s` add column v1 decimal(5) default ? %s", 679 -13, 680 ddlDefaultValueFunc, 681 true, 682 }, 683 { 684 "alter table test.`%s` add column v1 float default ? %s", 685 -13.13, 686 ddlDefaultValueFunc, 687 true, 688 }, 689 { 690 "alter table test.`%s` add column v1 double default ? %s", 691 -13.13, 692 ddlDefaultValueFunc, 693 true, 694 }, 695 /* 696 { 697 "alter table test.`%s` add column v1 bit(4) default ? %s", 698 []byte{0x03}, 699 ddlDefaultValueFunc, 700 true, 701 }, 702 { 703 "alter table test.`%s` add column v1 tinyint(4) unsigned default ? %s", 704 13, 705 ddlDefaultValueFunc, 706 true, 707 }, 708 { 709 "alter table test.`%s` add column v1 mediumint(4) unsigned default ? %s", 710 13, 711 ddlDefaultValueFunc, 712 true, 713 }, 714 { 715 "alter table test.`%s` add column v1 int(4) unsigned default ? %s", 716 13, 717 ddlDefaultValueFunc, 718 true, 719 }, 720 { 721 "alter table test.`%s` add column v1 bigint(4) unsigned default ? %s", 722 13, 723 ddlDefaultValueFunc, 724 true, 725 }, 726 { 727 "alter table test.`%s` add column v1 decimal(5,2) unsigned default ? %s", 728 13.13, 729 ddlDefaultValueFunc, 730 true, 731 }, 732 { 733 "alter table test.`%s` add column v1 float(5,2) unsigned default ? %s", 734 13.13, 735 ddlDefaultValueFunc, 736 true, 737 }, 738 { 739 "alter table test.`%s` add column v1 double(5,2) unsigned default ? %s", 740 13.13, 741 ddlDefaultValueFunc, 742 true, 743 }, 744 */ 745 // string data type 746 { 747 "alter table test.`%s` add column v1 char(10) default ? %s", 748 "char", 749 ddlDefaultValueFunc, 750 true, 751 }, 752 { 753 "alter table test.`%s` add column v1 varchar(10) default ? %s", 754 "varchar", 755 ddlDefaultValueFunc, 756 true, 757 }, 758 { 759 "alter table test.`%s` add column v1 binary(10) default ? %s", 760 "binary", 761 ddlDefaultValueFunc, 762 true, 763 }, 764 { 765 "alter table test.`%s` add column v1 varbinary(10) default ? %s", 766 "varbinary", 767 ddlDefaultValueFunc, 768 true, 769 }, 770 /* 771 // The BLOB, TEXT, GEOMETRY, and JSON data types cannot be assigned a default value. 772 { 773 "alter table test.`%s` add column v1 blob default ? %s", 774 "blob", 775 ddlDefaultValueFunc, 776 }, 777 // The BLOB, TEXT, GEOMETRY, and JSON data types cannot be assigned a default value. 778 { 779 "alter table test.`%s` add column v1 text default ? %s", 780 "text", 781 ddlDefaultValueFunc, 782 }, 783 */ 784 { 785 "alter table test.`%s` add column v1 enum('e0', 'e1') default ? %s", 786 "e1", 787 ddlDefaultValueFunc, 788 true, 789 }, 790 { 791 "alter table test.`%s` add column v1 set('e0', 'e1') default ? %s", 792 "e0,e1", 793 ddlDefaultValueFunc, 794 true, 795 }, 796 797 /* 798 // json, https://dev.mysql.com/doc/refman/5.7/en/data-type-defaults.html 799 // The BLOB, TEXT, GEOMETRY, and JSON data types cannot be assigned a default value. 800 { 801 "alter table test.`%s` add column v1 json default ? %s", 802 "[99, {\"id\": \"HK500\", \"cost\": 75.99}, [\"hot\", \"cold\"]]", 803 ddlDefaultValueFunc, 804 }, 805 */ 806 } 807 808 testName := getFunctionName(testMultiDDLs) 809 810 start := time.Now() 811 defer func() { 812 log.S().Info("testMultiDDLs take %v", time.Since(start)) 813 }() 814 815 ctx, cancel := context.WithCancel(context.Background()) 816 defer cancel() 817 pool := workerpool.NewDefaultAsyncPool(8) 818 go func() { 819 pool.Run(ctx) 820 }() 821 822 var wg1 sync.WaitGroup 823 // seperate every case to different table 824 for i, unit := range Units { 825 wg1.Add(1) 826 827 pool.Go(ctx, func() { 828 defer wg1.Done() 829 830 // use uuid here to avoid table name conflict 831 uuid := guuid.New().String() 832 uuid = strings.ReplaceAll(uuid, "-", "_") 833 newTbName := testName + uuid 834 mustCreateTable(srcs[0], newTbName) 835 log.S().Info("running ddl test: ", newTbName) 836 837 var wg2 sync.WaitGroup 838 ctx, cancel2 := context.WithCancel(context.Background()) 839 840 // start dml 841 for idx, src := range srcs { 842 wg2.Add(1) 843 go func(i int, s *sql.DB) { 844 if unit.NoDMLParas { 845 dml(ctx, s, newTbName, i, nil) 846 } else { 847 dml(ctx, s, newTbName, i, unit.DefaultValue) 848 } 849 wg2.Done() 850 }(idx+i*2, src) 851 } 852 853 time.Sleep(5 * time.Millisecond) 854 855 // start ddl 856 wg2.Add(1) 857 go func() { 858 unit.DDLFunc(ctx, srcs[0], unit.Fmt, newTbName, unit.DefaultValue) 859 cancel2() 860 wg2.Done() 861 }() 862 863 wg2.Wait() 864 }) 865 } 866 867 wg1.Wait() 868 util.MustExec(srcs[0], fmt.Sprintf("create table mark.finish_mark_%d(a int primary key);", atomic.AddInt32(&finishIdx, 1))) 869 } 870 871 const ( 872 createDatabaseSQL = "create database if not exists test" 873 createTableSQL = ` 874 create table if not exists test.%s 875 ( 876 id1 int unique key not null, 877 id2 int unique key not null, 878 v0 int default 11, 879 v1 int default null 880 ) 881 ` 882 ) 883 884 func mustCreateTable(db *sql.DB, tableName string) { 885 util.MustExec(db, createDatabaseSQL) 886 sql := fmt.Sprintf(createTableSQL, tableName) 887 util.MustExec(db, sql) 888 } 889 890 func mustCreateTableWithConn(ctx context.Context, conn *sql.Conn, tableName string) { 891 util.MustExecWithConn(ctx, conn, createDatabaseSQL) 892 sql := fmt.Sprintf(createTableSQL, tableName) 893 util.MustExecWithConn(ctx, conn, sql) 894 }