github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/syncer/dml_worker_test.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 syncer 15 16 import ( 17 "testing" 18 19 tiddl "github.com/pingcap/tidb/pkg/ddl" 20 "github.com/pingcap/tidb/pkg/parser" 21 "github.com/pingcap/tidb/pkg/parser/ast" 22 timodel "github.com/pingcap/tidb/pkg/parser/model" 23 timock "github.com/pingcap/tidb/pkg/util/mock" 24 cdcmodel "github.com/pingcap/tiflow/cdc/model" 25 "github.com/pingcap/tiflow/pkg/sqlmodel" 26 "github.com/stretchr/testify/require" 27 ) 28 29 func mockTableInfo(t *testing.T, sql string) *timodel.TableInfo { 30 t.Helper() 31 32 p := parser.New() 33 se := timock.NewContext() 34 node, err := p.ParseOneStmt(sql, "", "") 35 require.NoError(t, err) 36 ti, err := tiddl.MockTableInfo(se, node.(*ast.CreateTableStmt), 1) 37 require.NoError(t, err) 38 return ti 39 } 40 41 func TestGenSQL(t *testing.T) { 42 t.Parallel() 43 44 source := &cdcmodel.TableName{Schema: "db", Table: "tb"} 45 target := &cdcmodel.TableName{Schema: "targetSchema", Table: "targetTable"} 46 createSQL := "create table db.tb(id int primary key, col1 int unique not null, col2 int unique, name varchar(24))" 47 48 cases := []struct { 49 preValues []interface{} 50 postValues []interface{} 51 safeMode bool 52 53 expectedSQLs []string 54 expectedArgs [][]interface{} 55 }{ 56 { 57 nil, 58 []interface{}{1, 2, 3, "haha"}, 59 false, 60 61 []string{"INSERT INTO `targetSchema`.`targetTable` (`id`,`col1`,`col2`,`name`) VALUES (?,?,?,?)"}, 62 [][]interface{}{{1, 2, 3, "haha"}}, 63 }, 64 { 65 nil, 66 []interface{}{1, 2, 3, "haha"}, 67 true, 68 69 []string{"REPLACE INTO `targetSchema`.`targetTable` (`id`,`col1`,`col2`,`name`) VALUES (?,?,?,?)"}, 70 [][]interface{}{{1, 2, 3, "haha"}}, 71 }, 72 { 73 []interface{}{1, 2, 3, "haha"}, 74 nil, 75 false, 76 77 []string{"DELETE FROM `targetSchema`.`targetTable` WHERE `id` = ? LIMIT 1"}, 78 [][]interface{}{{1}}, 79 }, 80 { 81 []interface{}{1, 2, 3, "haha"}, 82 []interface{}{4, 5, 6, "hihi"}, 83 false, 84 85 []string{"UPDATE `targetSchema`.`targetTable` SET `id` = ?, `col1` = ?, `col2` = ?, `name` = ? WHERE `id` = ? LIMIT 1"}, 86 [][]interface{}{{4, 5, 6, "hihi", 1}}, 87 }, 88 { 89 []interface{}{1, 2, 3, "haha"}, 90 []interface{}{4, 5, 6, "hihi"}, 91 true, 92 93 []string{"DELETE FROM `targetSchema`.`targetTable` WHERE `id` = ? LIMIT 1", "REPLACE INTO `targetSchema`.`targetTable` (`id`,`col1`,`col2`,`name`) VALUES (?,?,?,?)"}, 94 [][]interface{}{{1}, {4, 5, 6, "hihi"}}, 95 }, 96 } 97 98 worker := &DMLWorker{} 99 100 for _, c := range cases { 101 tableInfo := mockTableInfo(t, createSQL) 102 change := sqlmodel.NewRowChange(source, target, c.preValues, c.postValues, tableInfo, nil, nil) 103 testEC := ec 104 if c.safeMode { 105 testEC = ecWithSafeMode 106 } 107 dmlJob := newDMLJob(change, testEC) 108 queries, args := worker.genSQLs([]*job{dmlJob}) 109 require.Equal(t, c.expectedSQLs, queries) 110 require.Equal(t, c.expectedArgs, args) 111 } 112 } 113 114 func TestJudgeKeyNotFound(t *testing.T) { 115 dmlWorker := &DMLWorker{ 116 compact: true, 117 multipleRows: true, 118 } 119 require.False(t, dmlWorker.judgeKeyNotFound(0, nil)) 120 dmlWorker.compact = false 121 require.False(t, dmlWorker.judgeKeyNotFound(0, nil)) 122 dmlWorker.multipleRows = false 123 require.False(t, dmlWorker.judgeKeyNotFound(0, nil)) 124 jobs := []*job{{safeMode: false}, {safeMode: true}} 125 require.False(t, dmlWorker.judgeKeyNotFound(0, jobs)) 126 jobs[1].safeMode = false 127 require.True(t, dmlWorker.judgeKeyNotFound(0, jobs)) 128 require.False(t, dmlWorker.judgeKeyNotFound(2, jobs)) 129 require.False(t, dmlWorker.judgeKeyNotFound(4, jobs)) 130 }