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  }