github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/tests/handle_error/run.sh (about)

     1  #!/bin/bash
     2  
     3  set -eu
     4  
     5  cur=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
     6  source $cur/../_utils/test_prepare
     7  source $cur/../_utils/handle_error_lib.sh
     8  WORK_DIR=$TEST_DIR/$TEST_NAME
     9  
    10  # skip modify column, two sources, no sharding
    11  function DM_SKIP_ERROR_CASE() {
    12  	run_sql_source1 "insert into ${db}.${tb1} values(1);"
    13  	run_sql_source2 "insert into ${db}.${tb2} values(2);"
    14  	run_sql_source1 "alter table ${db}.${tb1} add column new_col1 int;"
    15  	run_sql_source2 "alter table ${db}.${tb2} add column new_col1 int;"
    16  	run_sql_source1 "insert into ${db}.${tb1} values(3,3);"
    17  	run_sql_source2 "insert into ${db}.${tb2} values(4,4);"
    18  
    19  	# not support in TiDB
    20  	run_sql_source1 "alter table ${db}.${tb1} modify id varchar(10);"
    21  	run_sql_source2 "alter table ${db}.${tb2} modify id varchar(10);"
    22  	run_sql_source1 "insert into ${db}.${tb1} values('aaa',5);"
    23  	run_sql_source2 "insert into ${db}.${tb2} values('bbb',6);"
    24  
    25  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
    26  		"query-status test" \
    27  		"Unsupported modify column" 2
    28  
    29  	# begin to handle error
    30  	# skip all sources
    31  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
    32  		"binlog skip test" \
    33  		"\"result\": true" 3
    34  
    35  	# insert fail
    36  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
    37  		"query-status test" \
    38  		"Error .*: Incorrect int value" 2
    39  
    40  	# skip one source
    41  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
    42  		"binlog skip test -s mysql-replica-01" \
    43  		"only support to handle ddl error currently" 1
    44  
    45  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
    46  		"query-status test" \
    47  		"\"stage\": \"Paused\"" 2
    48  
    49  	# skip all sources
    50  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
    51  		"binlog skip test" \
    52  		"only support to handle ddl error currently" 2
    53  
    54  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
    55  		"query-status test" \
    56  		"\"stage\": \"Paused\"" 2
    57  }
    58  
    59  function DM_SKIP_ERROR() {
    60  	run_case SKIP_ERROR "double-source-no-sharding" "init_table 11 22" "clean_table" ""
    61  }
    62  
    63  # replace add column unique
    64  # one source, one table, no sharding
    65  function DM_REPLACE_ERROR_CASE() {
    66  	run_sql_source1 "insert into ${db}.${tb1} values(1,1);"
    67  
    68  	# error in TiDB
    69  	run_sql_source1 "alter table ${db}.${tb1} add column new_col text, add column c int unique;"
    70  	run_sql_source1 "insert into ${db}.${tb1} values(2,2,'haha',2);"
    71  
    72  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
    73  		"query-status test" \
    74  		"unsupported add column .* constraint UNIQUE KEY" 1 \
    75  		"origin SQL: \[alter table ${db}.${tb1} add column new_col text, add column c int unique\]" 1
    76  
    77  	# replace sql
    78  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
    79  		"binlog replace test alter table ${db}.${tb1} add column new_col text, add column c int; alter table ${db}.${tb1} add unique(c);" \
    80  		"\"result\": true" 2
    81  
    82  	run_sql_source1 "insert into ${db}.${tb1} values(3,3,'hihi',3);"
    83  
    84  	run_sql_tidb_with_retry "select count(1) from ${db}.${tb1};" "count(1): 3"
    85  }
    86  
    87  function DM_REPLACE_ERROR() {
    88  	run_case REPLACE_ERROR "double-source-no-sharding" \
    89  		"run_sql_source1 \"create table ${db}.${tb1} (a int unique, b int);\"" \
    90  		"clean_table" ""
    91  }
    92  
    93  # two source, 4 tables
    94  # source1: tb1 first ddl -> tb1 second ddl -> tb2 first ddl -> tb2 second ddl
    95  # source2: tb1 first ddl -> tb1 second ddl -> tb2 first ddl -> tb2 second ddl
    96  function DM_CROSS_DDL_SHARDING_CASE() {
    97  	# 11/21 first ddl
    98  	run_sql_source1 "alter table ${db}.${tb1} add column c int;"
    99  	run_sql_source2 "alter table ${db}.${tb1} add column c int;"
   100  	run_sql_source1 "insert into ${db}.${tb1} values(1,1,1);"
   101  	run_sql_source1 "insert into ${db}.${tb1} values(11,11,11);"
   102  	run_sql_source2 "insert into ${db}.${tb1} values(2,2,2);"
   103  	run_sql_source2 "insert into ${db}.${tb1} values(22,22,22);"
   104  
   105  	# 11/21 second ddl
   106  	run_sql_source1 "alter table ${db}.${tb1} add column d int;"
   107  	run_sql_source1 "insert into ${db}.${tb1} values(3,3,3,3);"
   108  	run_sql_source2 "alter table ${db}.${tb1} add column d int;"
   109  	run_sql_source2 "insert into ${db}.${tb1} values(6,6,6,6);"
   110  
   111  	# 12/22 first ddl
   112  	run_sql_source1 "alter table ${db}.${tb2} add column c int;"
   113  	run_sql_source2 "alter table ${db}.${tb2} add column c int;"
   114  	run_sql_source1 "insert into ${db}.${tb2} values(4,4,4);"
   115  	run_sql_source2 "insert into ${db}.${tb2} values(5,5,5);"
   116  
   117  	# 12/22 second ddl
   118  	run_sql_source1 "alter table ${db}.${tb2} add column d int;"
   119  	run_sql_source2 "alter table ${db}.${tb2} add column d int;"
   120  	run_sql_source1 "insert into ${db}.${tb2} values(7,7,7,7);"
   121  	run_sql_source2 "insert into ${db}.${tb2} values(8,8,8,8);"
   122  
   123  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   124  		"query-status test" \
   125  		"\"stage\": \"Running\"" 4
   126  
   127  	run_sql_tidb_with_retry "select count(1) from ${db}.${tb}" "count(1): 10"
   128  }
   129  
   130  function DM_CROSS_DDL_SHARDING() {
   131  	run_case CROSS_DDL_SHARDING "double-source-pessimistic" \
   132  		"run_sql_source1 \"create table ${db}.${tb1} (a int primary key, b int);\"; \
   133       run_sql_source1 \"create table ${db}.${tb2} (a int primary key, b int);\"; \
   134       run_sql_source2 \"create table ${db}.${tb1} (a int primary key, b int);\"; \
   135       run_sql_source2 \"create table ${db}.${tb2} (a int primary key, b int);\"" \
   136  		"clean_table" "pessimistic"
   137  
   138  	run_case CROSS_DDL_SHARDING "double-source-optimistic" \
   139  		"run_sql_source1 \"create table ${db}.${tb1} (a int primary key, b int);\"; \
   140       run_sql_source1 \"create table ${db}.${tb2} (a int primary key, b int);\"; \
   141       run_sql_source2 \"create table ${db}.${tb1} (a int primary key, b int);\"; \
   142       run_sql_source2 \"create table ${db}.${tb2} (a int primary key, b int);\"" \
   143  		"clean_table" "optimistic"
   144  }
   145  
   146  # one source, one table, no sharding
   147  function DM_INJECT_DDL_ERROR_CASE() {
   148  	run_sql_source1 "insert into ${db}.${tb1} values(1,1);"
   149  	run_sql_source2 "insert into ${db}.${tb2} values(1,1);"
   150  
   151  	# error in TiDB
   152  	run_sql_source1 "alter table ${db}.${tb1} add column c int default 100 unique not null;"
   153  	run_sql_source1 "insert into ${db}.${tb1} values(2,2,2);"
   154  	run_sql_source2 "alter table ${db}.${tb2} add column c int default 100 unique not null;"
   155  	run_sql_source2 "insert into ${db}.${tb2} values(2,2,2);"
   156  
   157  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   158  		"query-status test" \
   159  		"unsupported add column .* constraint UNIQUE KEY" 2
   160  
   161  	# replace sql but there has a mistake which is use 'c' as pk
   162  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   163  		"binlog replace test -s mysql-replica-01 alter table ${db}.${tb1} add column c int default 100; alter table ${db}.${tb1} add primary key (c);" \
   164  		"\"result\": true" 2
   165  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   166  		"binlog replace test -s mysql-replica-02 alter table ${db}.${tb2} add column c int default 100; alter table ${db}.${tb2} add primary key (c);" \
   167  		"\"result\": true" 2
   168  
   169  	# error in TiDB
   170  	run_sql_source1 "alter table ${db}.${tb1} modify column c double;"
   171  	run_sql_source1 "insert into ${db}.${tb1} values(3,3,3.5);"
   172  	run_sql_source2 "alter table ${db}.${tb2} modify column c double;"
   173  	run_sql_source2 "insert into ${db}.${tb2} values(3,3,3.5);"
   174  
   175  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   176  		"query-status test" \
   177  		"Unsupported modify column: this column has primary key flag" 2
   178  
   179  	# inject sqls
   180  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   181  		"binlog inject test -s mysql-replica-01 alter table ${db}.${tb1} drop primary key; alter table ${db}.${tb1} add unique(c);" \
   182  		"\"result\": true" 2
   183  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   184  		"binlog inject test -s mysql-replica-02 alter table ${db}.${tb2} drop primary key; alter table ${db}.${tb2} add unique(c);" \
   185  		"\"result\": true" 2
   186  
   187  	run_sql_tidb_with_retry "select count(1) from ${db}.${tb1} where c = 3.5;" "count(1): 1"
   188  	run_sql_tidb_with_retry "select count(1) from ${db}.${tb2} where c = 3.5;" "count(1): 1"
   189  }
   190  
   191  function DM_INJECT_DDL_ERROR_SHARDING_BASE_CASE() {
   192  	# trigger a flush checkpoint
   193  	run_sql_source1 "alter table ${db}.${tb1} add key (b);"
   194  	run_sql_source2 "alter table ${db}.${tb1} add key (b);"
   195  
   196  	run_sql_source1 "alter table ${db}.${tb1} add column c int default 100 unique not null;"
   197  	run_sql_source2 "alter table ${db}.${tb1} add column c int default 100 unique not null;"
   198  	run_sql_source1 "insert into ${db}.${tb1} values(1,1,1);"
   199  	run_sql_source2 "insert into ${db}.${tb1} values(2,2,2);"
   200  
   201  	# begin to handle error
   202  	if [[ "$1" = "pessimistic" ]]; then
   203  		# first ddl: unsupported error
   204  		run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   205  			"query-status test" \
   206  			'"ErrScope": "downstream"' 1 \
   207  			"unsupported add column .* constraint UNIQUE KEY" 1
   208  
   209  		# replace first ddl into two ddls, but add c as pk
   210  		run_sql_tidb "alter table ${db}.${tb} add column c int default 100; alter table ${db}.${tb} add primary key (c);"
   211  		# unlock for non DDL lock owner
   212  		run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   213  			"unlock-ddl-lock test-\`handle_error\`.\`tb\` --force-remove"
   214  		# skip for DDL lock owner
   215  		run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   216  			"binlog skip test" \
   217  			"\"result\": true" 2
   218  
   219  		run_sql_source1 "alter table ${db}.${tb1} modify column c double;"
   220  		run_sql_source1 "insert into ${db}.${tb1} values(3,3,3.5);"
   221  
   222  		run_sql_source2 "alter table ${db}.${tb1} modify column c double;"
   223  		run_sql_source2 "insert into ${db}.${tb1} values(4,4,4.5);"
   224  
   225  		# second ddl: unsupported error
   226  		run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   227  			"query-status test" \
   228  			'"ErrScope": "downstream"' 1 \
   229  			"Unsupported modify column: this column has primary key flag" 1
   230  
   231  		run_sql_tidb "alter table ${db}.${tb} drop primary key; alter table ${db}.${tb} add unique(c);"
   232  		# unlock for non DDL lock owner
   233  		run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   234  			"unlock-ddl-lock test-\`handle_error\`.\`tb\` --force-remove"
   235  		# skip for DDL lock owner
   236  		run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   237  			"binlog skip test" \
   238  			"\"result\": true" 2
   239  	else
   240  		# first ddl: unsupported error
   241  		run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   242  			"query-status test" \
   243  			'"ErrScope": "downstream"' 2 \
   244  			"unsupported add column .* constraint UNIQUE KEY" 2
   245  
   246  		run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   247  			"binlog replace test alter table ${db}.${tb1} add column c int default 100; alter table ${db}.${tb1} add primary key (c);" \
   248  			"\"result\": true" 3
   249  
   250  		run_sql_source1 "alter table ${db}.${tb1} drop column c;"
   251  		run_sql_source2 "alter table ${db}.${tb1} drop column c;"
   252  
   253  		check_log_contain_with_retry 'receive redirection operation from master' $WORK_DIR/worker1/log/dm-worker.log $WORK_DIR/worker2/log/dm-worker.log
   254  		run_sql_source1 "insert into ${db}.${tb1} values(3,3);"
   255  		run_sql_source2 "insert into ${db}.${tb1} values(4,4);"
   256  	fi
   257  
   258  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   259  		"query-status test" \
   260  		"\"stage\": \"Running\"" 4
   261  
   262  	run_sql_tidb_with_retry "select count(1) from ${db}.${tb}" "count(1): 4"
   263  }
   264  
   265  # two source, 4 tables
   266  function DM_INJECT_DDL_ERROR_SHARDING_BASE2_CASE() {
   267  	# 11/21 first ddl
   268  	run_sql_source1 "alter table ${db}.${tb1} add column c varchar(20) character set utf32;"
   269  	run_sql_source2 "alter table ${db}.${tb1} add column c varchar(20) character set utf32"
   270  	run_sql_source1 "insert into ${db}.${tb1} values(1,1,1);"
   271  	run_sql_source2 "insert into ${db}.${tb1} values(2,2,2);"
   272  
   273  	# 12/22 first ddl
   274  	run_sql_source1 "alter table ${db}.${tb2} add column c varchar(20) character set utf32"
   275  	run_sql_source2 "alter table ${db}.${tb2} add column c varchar(20) character set utf32"
   276  	run_sql_source1 "insert into ${db}.${tb2} values(4,4,4);"
   277  	run_sql_source2 "insert into ${db}.${tb2} values(5,5,5);"
   278  
   279  	# 11/21 first ddl error
   280  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   281  		"query-status test" \
   282  		"Unknown character set" 2
   283  
   284  	# replace 11/21 first ddl
   285  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   286  		"binlog replace test alter table ${db}.${tb1} add column c varchar(20); alter table ${db}.${tb1} add primary key (c);" \
   287  		"\"result\": true" 3
   288  
   289  	if [[ "$1" = "pessimistic" ]]; then
   290  		# 11/21 second ddl
   291  		run_sql_source1 "alter table ${db}.${tb1} modify column c varchar(30);"
   292  		run_sql_source2 "alter table ${db}.${tb1} modify column c varchar(30);"
   293  		run_sql_source1 "insert into ${db}.${tb1} values(3,3,3.5);"
   294  		run_sql_source2 "insert into ${db}.${tb1} values(6,6,6.6);"
   295  
   296  		# 12/22 second ddl
   297  		run_sql_source1 "alter table ${db}.${tb2} modify column c varchar(30);"
   298  		run_sql_source2 "alter table ${db}.${tb2} modify column c varchar(30);"
   299  		run_sql_source1 "insert into ${db}.${tb2} values(7,7,7.7);"
   300  		run_sql_source2 "insert into ${db}.${tb2} values(8,8,8.8);"
   301  
   302  		# 12/22 first ddl now report error
   303  		run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   304  			"query-status test" \
   305  			"Unknown character set" 2
   306  
   307  		# replace 12/22 first ddl into two ddls
   308  		run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   309  			"binlog replace test -s mysql-replica-01,mysql-replica-02 alter table ${db}.${tb2} add column c varchar(20); alter table ${db}.${tb2} add primary key (c);" \
   310  			"\"result\": true" 3
   311  	else
   312  		# 11/21 second ddl
   313  		run_sql_source1 "alter table ${db}.${tb1} drop column c;"
   314  		run_sql_source2 "alter table ${db}.${tb1} drop column c;"
   315  		run_sql_source1 "insert into ${db}.${tb1} values(3,3);"
   316  		run_sql_source2 "insert into ${db}.${tb1} values(6,6);"
   317  
   318  		# 12/22 second ddl
   319  		run_sql_source1 "alter table ${db}.${tb2} drop column c;"
   320  		run_sql_source2 "alter table ${db}.${tb2} drop column c;"
   321  
   322  		# 12/22 first ddl error
   323  		run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   324  			"query-status test" \
   325  			"Unknown character set" 2
   326  
   327  		# replace 12/22 first ddl
   328  		run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   329  			"binlog replace test alter table ${db}.${tb2} add column c varchar(20); alter table ${db}.${tb2} add primary key (c);" \
   330  			"\"result\": true" 3
   331  
   332  		check_log_contain_with_retry 'receive redirection operation from master' $WORK_DIR/worker1/log/dm-worker.log $WORK_DIR/worker2/log/dm-worker.log
   333  		run_sql_source1 "insert into ${db}.${tb2} values(7,7);"
   334  		run_sql_source2 "insert into ${db}.${tb2} values(8,8);"
   335  	fi
   336  
   337  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   338  		"query-status test" \
   339  		"\"stage\": \"Running\"" 4
   340  
   341  	run_sql_tidb_with_retry "select count(1) from ${db}.${tb}" "count(1): 8"
   342  }
   343  
   344  function DM_INJECT_DDL_ERROR() {
   345  	run_case INJECT_DDL_ERROR "double-source-no-sharding" \
   346  		"run_sql_source1 \"create table ${db}.${tb1} (a int unique, b int);\"; \
   347       run_sql_source2 \"create table ${db}.${tb2} (a int unique, b int);\"" \
   348  		"clean_table" ""
   349  
   350  	run_case INJECT_DDL_ERROR_SHARDING_BASE "double-source-pessimistic" \
   351  		"run_sql_source1 \"create table ${db}.${tb1} (a int unique, b int);\"; \
   352       run_sql_source2 \"create table ${db}.${tb1} (a int unique, b int);\"" \
   353  		"clean_table" "pessimistic"
   354  	run_case INJECT_DDL_ERROR_SHARDING_BASE "double-source-optimistic" \
   355  		"run_sql_source1 \"create table ${db}.${tb1} (a int unique, b int);\"; \
   356       run_sql_source2 \"create table ${db}.${tb1} (a int unique, b int);\"" \
   357  		"clean_table" "optimistic"
   358  
   359  	run_case INJECT_DDL_ERROR_SHARDING_BASE2 "double-source-pessimistic" \
   360  		"run_sql_source1 \"create table ${db}.${tb1} (a int unique, b int);\"; \
   361       run_sql_source1 \"create table ${db}.${tb2} (a int unique, b int);\"; \
   362       run_sql_source2 \"create table ${db}.${tb1} (a int unique, b int);\"; \
   363       run_sql_source2 \"create table ${db}.${tb2} (a int unique, b int);\"" \
   364  		"clean_table" "pessimistic"
   365  	run_case INJECT_DDL_ERROR_SHARDING_BASE2 "double-source-optimistic" \
   366  		"run_sql_source1 \"create table ${db}.${tb1} (a int unique, b int);\"; \
   367       run_sql_source1 \"create table ${db}.${tb2} (a int unique, b int);\"; \
   368       run_sql_source2 \"create table ${db}.${tb1} (a int unique, b int);\"; \
   369       run_sql_source2 \"create table ${db}.${tb2} (a int unique, b int);\"" \
   370  		"clean_table" "optimistic"
   371  }
   372  
   373  function DM_INJECT_DML_ERROR_CASE() {
   374  	run_sql_source1 "insert into ${db}.${tb1} values(1,1);"
   375  	run_sql_source2 "insert into ${db}.${tb2} values(1,1);"
   376  
   377  	# error in TiDB
   378  	run_sql_source1 "alter table ${db}.${tb1} add column c varchar(10) unique;"
   379  	run_sql_source1 "insert into ${db}.${tb1} values(2,2,'22');"
   380  	run_sql_source2 "alter table ${db}.${tb2} add column c varchar(10) unique;"
   381  	run_sql_source2 "insert into ${db}.${tb2} values(2,2,'22');"
   382  
   383  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   384  		"query-status test" \
   385  		"unsupported add column .* constraint UNIQUE KEY" 1
   386  
   387  	# replace sql but there has a mistake which is add unque to column 'b'
   388  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   389  		"binlog replace test -s mysql-replica-01 alter table ${db}.${tb1} add column c varchar(10); alter table ${db}.${tb1} add unique (b);" \
   390  		"\"result\": true" 2
   391  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   392  		"binlog replace test -s mysql-replica-02 alter table ${db}.${tb2} add column c varchar(10); alter table ${db}.${tb2} add unique (b);" \
   393  		"\"result\": true" 2
   394  
   395  	# error in TiDB, the second dml will be error
   396  	run_sql_source1 "start transaction;insert into ${db}.${tb1} values(3,3,'33');insert into ${db}.${tb1} values(4,2,'44');insert into ${db}.${tb1} values(5,2,'55');commit;"
   397  	run_sql_source2 "start transaction;insert into ${db}.${tb2} values(3,3,'33');insert into ${db}.${tb2} values(4,2,'44');insert into ${db}.${tb2} values(5,2,'55');commit;"
   398  
   399  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   400  		"query-status test" \
   401  		"Duplicate entry '2' for key 'b'" 4
   402  
   403  	# inject sqls
   404  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   405  		"binlog inject test -s mysql-replica-01 alter table ${db}.${tb1} drop index b;alter table ${db}.${tb1} add unique(c);" \
   406  		"\"result\": true" 2
   407  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   408  		"binlog inject test -s mysql-replica-02 alter table ${db}.${tb2} drop index b;alter table ${db}.${tb2} add unique(c);" \
   409  		"\"result\": true" 2
   410  
   411  	run_sql_tidb_with_retry "select count(1) from ${db}.${tb1} where b = 2;" "count(1): 3"
   412  	run_sql_tidb_with_retry "select count(1) from ${db}.${tb2} where b = 2;" "count(1): 3"
   413  }
   414  
   415  # TODO inject at dml will support at other pr
   416  function DM_INJECT_DML_ERROR() {
   417  	run_case INJECT_DML_ERROR "double-source-no-sharding" \
   418  		"run_sql_source1 \"create table ${db}.${tb1} (a int primary key, b int);\"; \
   419       run_sql_source2 \"create table ${db}.${tb2} (a int primary key, b int);\"" \
   420  		"clean_table" ""
   421  }
   422  
   423  function DM_LIST_ERROR_CASE() {
   424  	run_sql_source1 "insert into ${db}.${tb1} values(1, 1);"
   425  	run_sql_source1 "alter table ${db}.${tb1} add column c int default 100; alter table ${db}.${tb1} add primary key (c)"
   426  	run_sql_source1 "alter table ${db}.${tb1} modify c varchar(10);"
   427  	run_sql_source1 "alter table ${db}.${tb1} modify c varchar(20);"
   428  	run_sql_source1 "alter table ${db}.${tb1} modify c double;"
   429  
   430  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   431  		"query-status test" \
   432  		"Unsupported modify column: this column has primary key flag" 1
   433  
   434  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   435  		"binlog list test" \
   436  		"\"msg\": \"\[\]\"" 1
   437  
   438  	first_pos1=$(get_start_pos 127.0.0.1:$MASTER_PORT $source1)
   439  	first_name1=$(get_start_name 127.0.0.1:$MASTER_PORT $source1)
   440  	second_pos1=$(get_next_query_pos $MYSQL_PORT1 $MYSQL_PASSWORD1 $first_pos1)
   441  	third_pos1=$(get_next_query_pos $MYSQL_PORT1 $MYSQL_PASSWORD1 $second_pos1)
   442  
   443  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   444  		"binlog skip test -b $first_name1:$second_pos1" \
   445  		"\"result\": true" 2
   446  
   447  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   448  		"query-status test" \
   449  		"Unsupported modify column: this column has primary key flag" 1
   450  
   451  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   452  		"binlog list test" \
   453  		'\"msg\": \"\[{\\\"op\\\":1,\\\"task\\\":\\\"test\\\",\\\"binlogPos\\\":\\\"('${first_name1}', '${second_pos1}')\\\"}\]\"' 1
   454  
   455  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   456  		"binlog inject test -b $first_name1:$third_pos1 alter table ${db}.${tb1} drop primary key; alter table ${db}.${tb1} add unique (c);" \
   457  		"\"result\": true" 2
   458  
   459  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   460  		"query-status test" \
   461  		"Unsupported modify column: this column has primary key flag" 1
   462  
   463  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   464  		"binlog list test" \
   465  		'\"msg\": \"\[{\\\"op\\\":1,\\\"task\\\":\\\"test\\\",\\\"binlogPos\\\":\\\"('${first_name1}', '${second_pos1}')\\\"},{\\\"op\\\":4,\\\"task\\\":\\\"test\\\",\\\"binlogPos\\\":\\\"('${first_name1}', '${third_pos1}')\\\",\\\"sqls\\\":\[\\\"alter table handle_error.tb1 drop primary key;\\\",\\\" alter table handle_error.tb1 add unique (c);\\\"\]}\]\"' 1
   466  
   467  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   468  		"binlog skip test" \
   469  		"\"result\": true" 2
   470  
   471  	run_sql_source1 "insert into ${db}.${tb1} values(2,1,2.2);"
   472  
   473  	run_sql_tidb_with_retry "select count(1) from ${db}.${tb} where c = 2.2;" "count(1): 1"
   474  }
   475  
   476  function DM_LIST_ERROR() {
   477  	run_case LIST_ERROR "single-source-no-sharding" \
   478  		"run_sql_source1 \"create table ${db}.${tb1} (a int unique, b int);\"" \
   479  		"clean_table" ""
   480  }
   481  
   482  # test handle_error fail on second replace ddl
   483  # two sources, two tables
   484  function DM_REPLACE_ERROR_MULTIPLE_CASE() {
   485  	run_sql_source1 "alter table ${db}.${tb1} add column a varchar(20) character set utf32 unique, add column b varchar(20) character set utf32 unique;"
   486  	run_sql_source2 "alter table ${db}.${tb1} add column a varchar(20) character set utf32 unique, add column b varchar(20) character set utf32 unique;"
   487  	run_sql_source1 "insert into ${db}.${tb1} values(1,1,1);"
   488  	run_sql_source2 "insert into ${db}.${tb1} values(2,2,2);"
   489  
   490  	# 11, 21 unsupported error
   491  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   492  		"query-status test" \
   493  		"Unknown character set" 2
   494  
   495  	# begin to handle error
   496  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   497  		"binlog replace test \"alter table ${db}.${tb1} add column a varchar(20); alter table ${db}.${tb1} add unique idx(a); alter table ${db}.${tb1} add column b varchar(20); alter table ${db}.${tb1} add unique idx2(b);\"" \
   498  		"\"result\": true" 3
   499  
   500  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   501  		"query-status test" \
   502  		"\"stage\": \"Running\"" 4
   503  
   504  	run_sql_tidb_with_retry "select count(1) from ${db}.${tb};" "count(1): 2"
   505  }
   506  
   507  function DM_REPLACE_ERROR_MULTIPLE() {
   508  	run_case REPLACE_ERROR_MULTIPLE "double-source-pessimistic" "init_table 11 21" "clean_table" "pessimistic"
   509  	run_case REPLACE_ERROR_MULTIPLE "double-source-optimistic" "init_table 11 21" "clean_table" "optimistic"
   510  }
   511  
   512  function DM_EXEC_ERROR_SKIP_CASE() {
   513  	run_sql_source1 "insert into ${db}.${tb1} values(1,1,1);"
   514  	run_sql_source2 "insert into ${db}.${tb1} values(2,2,2);"
   515  	run_sql_tidb "insert into ${db}.${tb} values(3,1,1);"
   516  	run_sql_tidb "insert into ${db}.${tb} values(4,2,2);"
   517  	run_sql_tidb_with_retry "select count(1) from ${db}.${tb};" "count(1): 4"
   518  
   519  	run_sql_source1 "alter table ${db}.${tb1} add unique index ua(a);"
   520  	run_sql_source2 "alter table ${db}.${tb1} add unique index ua(a);"
   521  
   522  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   523  		"query-status test" \
   524  		"Error 1062 (23000): Duplicate " 1
   525  
   526  	run_sql_tidb "insert into ${db}.${tb} values(5,3,3);"
   527  	run_sql_tidb "insert into ${db}.${tb} values(6,4,4);"
   528  
   529  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   530  		"binlog skip test" \
   531  		"\"result\": true" 2
   532  
   533  	run_sql_tidb_with_retry "select count(1) from ${db}.${tb};" "count(1): 6"
   534  }
   535  
   536  function DM_EXEC_ERROR_SKIP() {
   537  	run_case EXEC_ERROR_SKIP "double-source-pessimistic" \
   538  		"run_sql_source1 \"create table ${db}.${tb1} (id int primary key, a int, b int);\"; \
   539        run_sql_source2 \"create table ${db}.${tb1} (id int primary key, a int, b int);\"" \
   540  		"clean_table" "pessimistic"
   541  	run_case EXEC_ERROR_SKIP "double-source-optimistic" \
   542  		"run_sql_source1 \"create table ${db}.${tb1} (id int primary key, a int, b int);\"; \
   543        run_sql_source2 \"create table ${db}.${tb1} (id int primary key, a int, b int);\"" \
   544  		"clean_table" "optimistic"
   545  }
   546  
   547  function DM_SKIP_INCOMPATIBLE_DDL_CASE() {
   548  	run_sql_source1 "insert into ${db}.${tb1} values(1);"
   549  
   550  	run_sql_source1 "CREATE FUNCTION ${db}.hello (s CHAR(20)) RETURNS CHAR(50) DETERMINISTIC RETURN CONCAT('Hello, ',s,'!');"
   551  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   552  		"query-status test" \
   553  		"\"stage\": \"Running\"" 2
   554  
   555  	run_sql_source1 "/*!50003 drop function ${db}.hello*/;"
   556  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   557  		"query-status test" \
   558  		"drop function $(hello)" 2 \
   559  		"Please confirm your DDL statement is correct and needed." 1
   560  
   561  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   562  		"binlog skip test" \
   563  		"\"result\": true" 2
   564  
   565  	run_sql_source1 "insert into ${db}.${tb1} values(2);"
   566  	check_sync_diff $WORK_DIR $cur/conf/diff_config.toml
   567  }
   568  
   569  function DM_SKIP_INCOMPATIBLE_DDL() {
   570  	run_case SKIP_INCOMPATIBLE_DDL "single-source-no-sharding" "init_table 11" "clean_table" ""
   571  }
   572  
   573  # FIXME: uncomment this after support replace sql for ddl locks
   574  #function DM_REPLACE_DEFAULT_VALUE_CASE() {
   575  #	run_sql_source1 "insert into ${db}.${tb1} values(1);"
   576  #	run_sql_source2 "insert into ${db}.${tb1} values(2);"
   577  #	run_sql_source2 "insert into ${db}.${tb2} values(3);"
   578  #
   579  #	run_sql_source1 "alter table ${db}.${tb1} add new_col1 int default 1;"
   580  #	run_sql_source1 "insert into ${db}.${tb1} values(4,4);"
   581  #	run_sql_source2 "insert into ${db}.${tb1} values(5);"
   582  #	run_sql_source2 "insert into ${db}.${tb2} values(6);"
   583  #
   584  #	# make sure order is source1.table1, source2.table1, source2.table2
   585  #	run_sql_tidb_with_retry "select count(1) from ${db}.${tb}" "count(1): 6"
   586  #
   587  #	run_sql_source2 "alter table ${db}.${tb1} add new_col1 int default 2;"
   588  #	run_sql_source1 "insert into ${db}.${tb1} values(7,7);"
   589  #	run_sql_source2 "insert into ${db}.${tb1} values(8,8);"
   590  #	run_sql_source2 "insert into ${db}.${tb2} values(9);"
   591  #	run_sql_source2 "alter table ${db}.${tb2} add new_col1 int default 3;"
   592  #	run_sql_source1 "insert into ${db}.${tb1} values(10,10);"
   593  #	run_sql_source2 "insert into ${db}.${tb1} values(11,11);"
   594  #	run_sql_source2 "insert into ${db}.${tb2} values(12,12);"
   595  #
   596  #	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   597  #		"query-status test" \
   598  #		"because schema conflict detected" 1
   599  #
   600  #	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   601  #		"binlog replace test -s mysql-replica-02 alter table ${db}.${tb1} add new_col1 int default 1;" \
   602  #		"\"result\": true" 2
   603  #
   604  #	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   605  #		"query-status test" \
   606  #		"because schema conflict detected" 1
   607  #
   608  #	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   609  #		"binlog replace test -s mysql-replica-02 alter table ${db}.${tb2} add new_col1 int default 1;" \
   610  #		"\"result\": true" 2
   611  #
   612  #	run_sql_source1 "alter table ${db}.${tb1} add new_col2 int;"
   613  #	run_sql_source2 "alter table ${db}.${tb1} add new_col2 int;"
   614  #	run_sql_source2 "alter table ${db}.${tb2} add new_col2 int;"
   615  #	run_sql_source1 "insert into ${db}.${tb1} values(13,13,13);"
   616  #	run_sql_source2 "insert into ${db}.${tb1} values(14,14,14);"
   617  #	run_sql_source2 "insert into ${db}.${tb2} values(15,15,15);"
   618  #
   619  #	# WARN: some data different
   620  #	# all the value before alter table in TiDB will be 1, while upstream table is 1, 2 or 3
   621  #	run_sql_tidb_with_retry "select count(1) from ${db}.${tb}" "count(1): 15"
   622  #
   623  #	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   624  #		"query-status test" \
   625  #		"\"result\": true" 3
   626  #}
   627  
   628  function DM_REPLACE_DEFAULT_VALUE() {
   629  	run_case REPLACE_DEFAULT_VALUE "double-source-optimistic" "init_table 11 21 22" "clean_table" ""
   630  }
   631  
   632  function DM_4202_CASE() {
   633  	run_sql_source1 "insert into ${db}.${tb1} values(1);"
   634  	run_sql_source1 "alter table ${db}.${tb1} modify id varchar(10);"
   635  
   636  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   637  		"query-status test" \
   638  		"Unsupported modify column" 1
   639  
   640  	start_location=$(get_start_location 127.0.0.1:$MASTER_PORT $source1)
   641  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   642  		"binlog skip test -b $start_location" \
   643  		"\"result\": true" 2
   644  
   645  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   646  		"query-status test" \
   647  		"\"result\": true" 2
   648  
   649  	run_sql_source1 "insert into ${db}.${tb1} values(2);"
   650  	run_sql_tidb_with_retry "select count(1) from ${db}.${tb};" "count(1): 2"
   651  }
   652  
   653  function DM_4202() {
   654  	run_case 4202 "single-source-no-sharding" "init_table 11" "clean_table" ""
   655  }
   656  
   657  function DM_4204_CASE() {
   658  	run_sql_source1 "insert into ${db}.${tb1} values(1);"
   659  	run_sql_source1 "alter table ${db}.${tb1} modify id varchar(10);"
   660  
   661  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   662  		"query-status test" \
   663  		"Unsupported modify column" 1
   664  
   665  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   666  		"binlog skip test" \
   667  		"\"result\": true" 2
   668  
   669  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   670  		"query-status test" \
   671  		"\"result\": true" 2
   672  
   673  	run_sql_source1 "insert into ${db}.${tb1} values(2);"
   674  	run_sql_tidb_with_retry "select count(1) from ${db}.${tb};" "count(1): 2"
   675  }
   676  
   677  function DM_4204() {
   678  	run_case 4204 "single-source-no-sharding" "init_table 11" "clean_table" ""
   679  }
   680  
   681  # 4206, 4208
   682  function DM_4206_CASE() {
   683  	run_sql_source1 "insert into ${db}.${tb1} values(1);"
   684  	run_sql_source2 "insert into ${db}.${tb1} values(2);"
   685  	run_sql_source1 "alter table ${db}.${tb1} modify id varchar(10);"
   686  	run_sql_source2 "alter table ${db}.${tb1} modify id varchar(10);"
   687  	run_sql_source1 "alter table ${db}.${tb1} modify id varchar(20);"
   688  	run_sql_source2 "alter table ${db}.${tb1} modify id varchar(20);"
   689  
   690  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   691  		"query-status test" \
   692  		"Unsupported modify column: this column has primary key flag" 2
   693  
   694  	first_pos1=$(get_start_pos 127.0.0.1:$MASTER_PORT $source1)
   695  	first_pos2=$(get_start_pos 127.0.0.1:$MASTER_PORT $source2)
   696  	first_name1=$(get_start_name 127.0.0.1:$MASTER_PORT $source1)
   697  	first_name2=$(get_start_name 127.0.0.1:$MASTER_PORT $source2)
   698  
   699  	second_pos1=$(get_next_query_pos $MYSQL_PORT1 $MYSQL_PASSWORD1 $first_pos1)
   700  	second_pos2=$(get_next_query_pos $MYSQL_PORT2 $MYSQL_PASSWORD2 $first_pos2)
   701  
   702  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   703  		"binlog skip test -b $first_name1:$second_pos1 -s $source1" \
   704  		"\"result\": true" 2
   705  
   706  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   707  		"query-status test" \
   708  		"Unsupported modify column: this column has primary key flag" 2
   709  
   710  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   711  		"binlog skip test -b $first_name1:$first_pos1 -s $source1" \
   712  		"\"result\": true" 2
   713  
   714  	run_sql_source1 "insert into ${db}.${tb1} values(3);"
   715  
   716  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   717  		"query-status test" \
   718  		"Unsupported modify column: this column has primary key flag" 1
   719  
   720  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   721  		"binlog skip test -b $first_name2:$first_pos2 -s $source2" \
   722  		"\"result\": true" 2
   723  
   724  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   725  		"query-status test" \
   726  		"Unsupported modify column: this column has primary key flag" 1
   727  
   728  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   729  		"binlog skip test -b $first_name2:$second_pos2 -s $source2" \
   730  		"\"result\": true" 2
   731  
   732  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   733  		"query-status test" \
   734  		"\"result\": true" 3
   735  
   736  	run_sql_source2 "insert into ${db}.${tb1} values(4);"
   737  
   738  	run_sql_tidb_with_retry "select count(1) from ${db}.${tb};" "count(1): 4"
   739  }
   740  
   741  function DM_4206() {
   742  	run_case 4206 "double-source-pessimistic" "init_table 11 21" "clean_table" "pessimistic"
   743  	run_case 4206 "double-source-optimistic" "init_table 11 21" "clean_table" "optimistic"
   744  }
   745  
   746  function DM_4207_CASE() {
   747  	run_sql_source1 "insert into ${db}.${tb1} values(1);"
   748  	run_sql_source2 "insert into ${db}.${tb1} values(2);"
   749  	run_sql_source1 "alter table ${db}.${tb1} modify id varchar(10);"
   750  	run_sql_source2 "alter table ${db}.${tb1} modify id varchar(10);"
   751  
   752  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   753  		"query-status test" \
   754  		"Unsupported modify column" 2
   755  
   756  	start_location1=$(get_start_location 127.0.0.1:$MASTER_PORT $source1)
   757  	start_location2=$(get_start_location 127.0.0.1:$MASTER_PORT $source2)
   758  
   759  	if [ "$start_location1" = "$start_location2" ]; then
   760  		run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   761  			"binlog skip test -b $start_location1" \
   762  			"\"result\": true" 3
   763  	else
   764  		# WARN: may skip unknown event like later insert, test will fail
   765  		# It hasn't happened yet.
   766  		run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   767  			"binlog skip test -b $start_location1" \
   768  			"\"result\": true" 3
   769  
   770  		run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   771  			"query-status test" \
   772  			"Unsupported modify column" 1
   773  
   774  		run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   775  			"binlog skip test -b $start_location2" \
   776  			"\"result\": true" 3
   777  	fi
   778  
   779  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   780  		"query-status test" \
   781  		"\"result\": true" 3
   782  
   783  	run_sql_source1 "insert into ${db}.${tb1} values(3);"
   784  	run_sql_source2 "insert into ${db}.${tb1} values(4);"
   785  
   786  	run_sql_tidb_with_retry "select count(1) from ${db}.${tb} where id<100;" "count(1): 4"
   787  }
   788  
   789  function DM_4207() {
   790  	run_case 4207 "double-source-pessimistic" "init_table 11 21" "clean_table" "pessimistic"
   791  	run_case 4207 "double-source-optimistic" "init_table 11 21" "clean_table" "optimistic"
   792  
   793  	# test different error locations
   794  	run_case 4207 "double-source-pessimistic" "init_table 11 21;run_sql_source1 \"insert into ${db}.${tb1} values(100);\"" "clean_table" "pessimistic"
   795  	run_case 4207 "double-source-optimistic" "init_table 11 21;run_sql_source1 \"insert into ${db}.${tb1} values(100);\"" "clean_table" "optimistic"
   796  }
   797  
   798  function DM_4209_CASE() {
   799  	run_sql_source1 "insert into ${db}.${tb1} values(1);"
   800  	run_sql_source2 "insert into ${db}.${tb1} values(2);"
   801  	run_sql_source1 "alter table ${db}.${tb1} modify id varchar(10);"
   802  	run_sql_source2 "alter table ${db}.${tb1} modify id varchar(10);"
   803  
   804  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   805  		"query-status test" \
   806  		"Unsupported modify column" 2
   807  
   808  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   809  		"binlog skip test -s $source1" \
   810  		"\"result\": true" 2
   811  
   812  	run_sql_source1 "insert into ${db}.${tb1} values(3);"
   813  
   814  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   815  		"query-status test" \
   816  		"Unsupported modify column" 1
   817  
   818  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   819  		"binlog skip test -s $source2" \
   820  		"\"result\": true" 2
   821  
   822  	run_sql_source2 "insert into ${db}.${tb1} values(4);"
   823  
   824  	run_sql_tidb_with_retry "select count(1) from ${db}.${tb};" "count(1): 4"
   825  }
   826  
   827  function DM_4209() {
   828  	run_case 4209 "double-source-pessimistic" "init_table 11 21" "clean_table" "pessimistic"
   829  	run_case 4209 "double-source-optimistic" "init_table 11 21" "clean_table" "optimistic"
   830  }
   831  
   832  function DM_4211_CASE() {
   833  	run_sql_source1 "insert into ${db}.${tb1} values(1);"
   834  	run_sql_source1 "alter table ${db}.${tb1} add column c int unique;"
   835  
   836  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   837  		"query-status test" \
   838  		"unsupported add column .* constraint UNIQUE KEY" 1
   839  
   840  	run_sql_source1 "insert into ${db}.${tb1} values(2,2);"
   841  
   842  	start_location=$(get_start_location 127.0.0.1:$MASTER_PORT $source1)
   843  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   844  		"binlog replace test --binlog-pos $start_location alter table ${db}.${tb1} add column c int;" \
   845  		"\"result\": true" 2
   846  
   847  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   848  		"query-status test" \
   849  		"\"result\": true" 2
   850  
   851  	run_sql_source1 "insert into ${db}.${tb1} values(3,3);"
   852  
   853  	run_sql_tidb_with_retry "select count(1) from ${db}.${tb};" "count(1): 3"
   854  }
   855  
   856  function DM_4211() {
   857  	run_case 4211 "single-source-no-sharding" "init_table 11" "clean_table" ""
   858  }
   859  
   860  function DM_4213_CASE() {
   861  	run_sql_source1 "insert into ${db}.${tb1} values(1);"
   862  	run_sql_source1 "alter table ${db}.${tb1} add column c int unique;"
   863  
   864  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   865  		"query-status test" \
   866  		"unsupported add column .* constraint UNIQUE KEY" 1
   867  
   868  	run_sql_source1 "insert into ${db}.${tb1} values(2,2);"
   869  
   870  	run_dm_ctl $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   871  		"binlog replace test alter table ${db}.${tb1} add column c int;alter table ${db}.${tb1} add unique(c);" \
   872  		"\"result\": true" 2
   873  
   874  	run_dm_ctl_with_retry $WORK_DIR "127.0.0.1:$MASTER_PORT" \
   875  		"query-status test" \
   876  		"\"result\": true" 2
   877  
   878  	run_sql_source1 "insert into ${db}.${tb1} values(3,3);"
   879  
   880  	run_sql_tidb_with_retry "select count(1) from ${db}.${tb};" "count(1): 3"
   881  }
   882  
   883  function DM_4213() {
   884  	run_case 4213 "single-source-no-sharding" "init_table 11" "clean_table" ""
   885  }
   886  
   887  function run() {
   888  	init_cluster
   889  	init_database
   890  
   891  	DM_INJECT_DDL_ERROR
   892  	# TODO inject at dml will support at other pr
   893  	# DM_INJECT_DML_ERROR
   894  	DM_LIST_ERROR
   895  	DM_SKIP_ERROR
   896  	DM_REPLACE_ERROR
   897  	DM_CROSS_DDL_SHARDING
   898  	DM_REPLACE_ERROR_MULTIPLE
   899  	DM_EXEC_ERROR_SKIP
   900  	DM_SKIP_INCOMPATIBLE_DDL
   901  	# FIXME: uncomment this after support replace sql for ddl locks
   902  	#	DM_REPLACE_DEFAULT_VALUE
   903  
   904  	implement=(4202 4204 4206 4207 4209 4211 4213)
   905  	for i in ${implement[@]}; do
   906  		DM_${i}
   907  		sleep 1
   908  	done
   909  }
   910  
   911  cleanup_data $db
   912  # also cleanup dm processes in case of last run failed
   913  cleanup_process $*
   914  run $*
   915  cleanup_process $*
   916  
   917  echo "[$(date)] <<<<<< test case $TEST_NAME success! >>>>>>"