github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/chaos/cases/generator.go (about) 1 // Copyright 2021 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 "fmt" 19 "math/rand" 20 21 config2 "github.com/pingcap/tiflow/dm/config" 22 ) 23 24 const ( 25 source1 = iota 26 source2 27 source3 28 ) 29 30 // SQL represents sql statement for a source. 31 type SQL struct { 32 statement string 33 source int 34 } 35 36 // SQLs represents sql statements in a group. 37 type SQLs []SQL 38 39 // Case represents a sqls test case. 40 type Case []SQLs 41 42 var ( 43 // add some flags column, so we can make sure the order of new column in optimsitic. 44 preSQLs1 = SQLs{ 45 {"ALTER TABLE %s.%s ADD COLUMN case3_flag1 INT, ADD COLUMN case3_flag2 INT, ADD COLUMN case3_flag3 INT", source1}, 46 {"ALTER TABLE %s.%s ADD COLUMN case3_flag1 INT, ADD COLUMN case3_flag2 INT, ADD COLUMN case3_flag3 INT", source2}, 47 {"ALTER TABLE %s.%s ADD COLUMN case3_flag1 INT, ADD COLUMN case3_flag2 INT, ADD COLUMN case3_flag3 INT", source3}, 48 {"ALTER TABLE %s.%s ADD COLUMN case4_flag1 INT, ADD COLUMN case4_flag2 INT, ADD COLUMN case4_flag3 INT", source1}, 49 {"ALTER TABLE %s.%s ADD COLUMN case4_flag1 INT, ADD COLUMN case4_flag2 INT, ADD COLUMN case4_flag3 INT", source2}, 50 {"ALTER TABLE %s.%s ADD COLUMN case4_flag1 INT, ADD COLUMN case4_flag2 INT, ADD COLUMN case4_flag3 INT", source3}, 51 {"ALTER TABLE %s.%s ADD COLUMN case5_flag1 INT, ADD COLUMN case5_flag2 INT, ADD COLUMN case5_flag3 INT;", source1}, 52 {"ALTER TABLE %s.%s ADD COLUMN case5_flag1 INT, ADD COLUMN case5_flag2 INT, ADD COLUMN case5_flag3 INT;", source2}, 53 {"ALTER TABLE %s.%s ADD COLUMN case5_flag1 INT, ADD COLUMN case5_flag2 INT, ADD COLUMN case5_flag3 INT;", source3}, 54 {"ALTER TABLE %s.%s ADD COLUMN case9_flag INT;", source1}, 55 {"ALTER TABLE %s.%s ADD COLUMN case9_flag INT;", source2}, 56 {"ALTER TABLE %s.%s ADD COLUMN case9_flag INT;", source3}, 57 } 58 59 // ALL ADD COLUMN, ALL DROP COLUMN. 60 case1 = Case{ 61 {{"ALTER TABLE %s.%s ADD COLUMN case1 INT;", source1}}, 62 {{"ALTER TABLE %s.%s ADD COLUMN case1 INT;", source2}}, 63 {{"ALTER TABLE %s.%s ADD COLUMN case1 INT;", source3}}, 64 {{"ALTER TABLE %s.%s DROP COLUMN case1;", source1}}, 65 {{"ALTER TABLE %s.%s DROP COLUMN case1;", source2}}, 66 {{"ALTER TABLE %s.%s DROP COLUMN case1;", source3}}, 67 } 68 // ADD COLUMN, DROP COLUMN for one source. 69 case2 = Case{ 70 {{"ALTER TABLE %s.%s ADD COLUMN case2 INT;", source1}}, 71 {{"ALTER TABLE %s.%s DROP COLUMN case2;", source1}}, 72 } 73 // ADD columns out of order. 74 case3 = Case{ 75 { 76 {"ALTER TABLE %s.%s DROP COLUMN case3_1;", source1}, 77 {"ALTER TABLE %s.%s DROP COLUMN case3_2;", source1}, 78 {"ALTER TABLE %s.%s DROP COLUMN case3_3;", source1}, 79 {"ALTER TABLE %s.%s DROP COLUMN case3_1;", source2}, 80 {"ALTER TABLE %s.%s DROP COLUMN case3_2;", source2}, 81 {"ALTER TABLE %s.%s DROP COLUMN case3_3;", source2}, 82 {"ALTER TABLE %s.%s DROP COLUMN case3_1;", source3}, 83 {"ALTER TABLE %s.%s DROP COLUMN case3_2;", source3}, 84 {"ALTER TABLE %s.%s DROP COLUMN case3_3;", source3}, 85 }, 86 {{"ALTER TABLE %s.%s ADD COLUMN case3_1 INT AFTER case3_flag1;", source1}}, 87 {{"ALTER TABLE %s.%s ADD COLUMN case3_2 INT AFTER case3_flag2;", source2}}, 88 {{"ALTER TABLE %s.%s ADD COLUMN case3_3 INT AFTER case3_flag3;", source3}}, 89 {{"ALTER TABLE %s.%s ADD COLUMN case3_2 INT AFTER case3_flag2;", source1}}, 90 {{"ALTER TABLE %s.%s ADD COLUMN case3_3 INT AFTER case3_flag3;", source2}}, 91 {{"ALTER TABLE %s.%s ADD COLUMN case3_1 INT AFTER case3_flag1;", source3}}, 92 {{"ALTER TABLE %s.%s ADD COLUMN case3_3 INT AFTER case3_flag3;", source1}}, 93 {{"ALTER TABLE %s.%s ADD COLUMN case3_1 INT AFTER case3_flag1;", source2}}, 94 {{"ALTER TABLE %s.%s ADD COLUMN case3_2 INT AFTER case3_flag2;", source3}}, 95 } 96 // MULTIPLE ADD COLUMN out of order. 97 case4 = Case{ 98 { 99 {"ALTER TABLE %s.%s DROP COLUMN case4_1, DROP COLUMN case4_2, DROP COLUMN case4_3;", source1}, 100 {"ALTER TABLE %s.%s DROP COLUMN case4_1, DROP COLUMN case4_2, DROP COLUMN case4_3;", source2}, 101 {"ALTER TABLE %s.%s DROP COLUMN case4_1, DROP COLUMN case4_2, DROP COLUMN case4_3;", source3}, 102 }, 103 {{"ALTER TABLE %s.%s ADD COLUMN case4_1 INT AFTER case4_flag1, ADD COLUMN case4_2 INT AFTER case4_flag2, ADD COLUMN case4_3 INT AFTER case4_flag3;", source1}}, 104 {{"ALTER TABLE %s.%s ADD COLUMN case4_2 INT AFTER case4_flag2, ADD COLUMN case4_3 INT AFTER case4_flag3, ADD COLUMN case4_1 INT AFTER case4_flag1;", source2}}, 105 {{"ALTER TABLE %s.%s ADD COLUMN case4_3 INT AFTER case4_flag3, ADD COLUMN case4_1 INT AFTER case4_flag1, ADD COLUMN case4_2 INT AFTER case4_flag2;", source3}}, 106 } 107 // MULTIPLE ADD COLUMN vs ADD columns. 108 case5 = Case{ 109 { 110 {"ALTER TABLE %s.%s DROP COLUMN case5_1;", source1}, 111 {"ALTER TABLE %s.%s DROP COLUMN case5_2;", source1}, 112 {"ALTER TABLE %s.%s DROP COLUMN case5_3;", source1}, 113 {"ALTER TABLE %s.%s DROP COLUMN case5_1;", source2}, 114 {"ALTER TABLE %s.%s DROP COLUMN case5_2;", source2}, 115 {"ALTER TABLE %s.%s DROP COLUMN case5_3;", source2}, 116 {"ALTER TABLE %s.%s DROP COLUMN case5_1;", source3}, 117 {"ALTER TABLE %s.%s DROP COLUMN case5_2;", source3}, 118 {"ALTER TABLE %s.%s DROP COLUMN case5_3;", source3}, 119 }, 120 {{"ALTER TABLE %s.%s ADD COLUMN case5_1 INT AFTER case5_flag1;", source1}}, 121 {{"ALTER TABLE %s.%s ADD COLUMN case5_2 INT AFTER case5_flag2, ADD COLUMN case5_1 INT AFTER case5_flag1;", source2}}, 122 {{"ALTER TABLE %s.%s ADD COLUMN case5_3 INT AFTER case5_flag3, ADD COLUMN case5_1 INT AFTER case5_flag1, ADD COLUMN case5_2 INT AFTER case5_flag2;", source3}}, 123 {{"ALTER TABLE %s.%s ADD COLUMN case5_3 INT AFTER case5_flag3;", source2}}, 124 {{"ALTER TABLE %s.%s ADD COLUMN case5_2 INT AFTER case5_flag2, ADD COLUMN case5_3 INT AFTER case5_flag3;", source1}}, 125 } 126 // ALL ADD INDEX, ALL DROP INDEX. 127 case6 = Case{ 128 {{"ALTER TABLE %s.%s ADD INDEX case6_idx(case3_flag1);", source1}}, 129 {{"ALTER TABLE %s.%s ADD INDEX case6_idx(case3_flag1);", source2}}, 130 {{"ALTER TABLE %s.%s ADD INDEX case6_idx(case3_flag1);", source3}}, 131 {{"ALTER TABLE %s.%s DROP INDEX case6_idx;", source1}}, 132 {{"ALTER TABLE %s.%s DROP INDEX case6_idx;", source2}}, 133 {{"ALTER TABLE %s.%s DROP INDEX case6_idx;", source3}}, 134 } 135 // ADD INDEX, DROP INDEX for one source. 136 case7 = Case{ 137 {{"ALTER TABLE %s.%s ADD INDEX case7_idx(uuid);", source1}}, 138 {{"ALTER TABLE %s.%s DROP INDEX case7_idx;", source1}}, 139 } 140 // ADD MULTI-COLUMN INDEX. 141 case8 = Case{ 142 { 143 {"ALTER TABLE %s.%s DROP INDEX case8_idx;", source1}, 144 {"ALTER TABLE %s.%s DROP INDEX case8_idx;", source2}, 145 {"ALTER TABLE %s.%s DROP INDEX case8_idx;", source3}, 146 }, 147 {{"ALTER TABLE %s.%s ADD INDEX case8_idx(case4_flag1, case4_flag2, case4_flag3);", source1}}, 148 {{"ALTER TABLE %s.%s ADD INDEX case8_idx(case4_flag1, case4_flag2, case4_flag3);", source2}}, 149 {{"ALTER TABLE %s.%s ADD INDEX case8_idx(case4_flag1, case4_flag2, case4_flag3);", source3}}, 150 } 151 // ADD COLUMN AND INDEX. 152 case9 = Case{ 153 { 154 {"ALTER TABLE %s.%s DROP INDEX case9_idx;", source1}, 155 {"ALTER TABLE %s.%s DROP INDEX case9_idx;", source2}, 156 {"ALTER TABLE %s.%s DROP INDEX case9_idx;", source3}, 157 {"ALTER TABLE %s.%s DROP COLUMN case9;", source1}, 158 {"ALTER TABLE %s.%s DROP COLUMN case9;", source2}, 159 {"ALTER TABLE %s.%s DROP COLUMN case9;", source3}, 160 }, 161 {{"ALTER TABLE %s.%s ADD COLUMN case9 INT AFTER case9_flag;", source1}}, 162 {{"ALTER TABLE %s.%s ADD INDEX case9_idx(case9);", source1}}, 163 {{"ALTER TABLE %s.%s ADD COLUMN case9 INT AFTER case9_flag;", source2}}, 164 {{"ALTER TABLE %s.%s ADD INDEX case9_idx(case9);", source2}}, 165 {{"ALTER TABLE %s.%s ADD COLUMN case9 INT AFTER case9_flag;", source3}}, 166 {{"ALTER TABLE %s.%s ADD INDEX case9_idx(case9);", source3}}, 167 } 168 cases = map[string][]Case{ 169 config2.ShardOptimistic: { 170 case1, 171 case2, 172 case3, 173 case4, 174 case5, 175 case6, 176 case7, 177 case8, 178 case9, 179 }, 180 config2.ShardPessimistic: {}, 181 "": {}, 182 } 183 preSQLs = map[string]SQLs{ 184 config2.ShardOptimistic: preSQLs1, 185 config2.ShardPessimistic: nil, 186 "": nil, 187 } 188 ) 189 190 // CaseGenerator generator test cases. 191 type CaseGenerator struct { 192 testCases []Case 193 testPreSQLs SQLs 194 sqlsChan chan SQLs 195 schema string 196 tables []string 197 } 198 199 // NewCaseGenerator creates a new CaseGenerator instance. 200 func NewCaseGenerator(shardMode string) *CaseGenerator { 201 g := &CaseGenerator{ 202 testCases: cases[shardMode], 203 sqlsChan: make(chan SQLs), 204 testPreSQLs: preSQLs[shardMode], 205 } 206 return g 207 } 208 209 // Start starts to generate sqls case. 210 func (g *CaseGenerator) Start(ctx context.Context, schema string, tables []string) { 211 g.schema = schema 212 g.tables = tables 213 go g.genSQLs(ctx) 214 } 215 216 func (g *CaseGenerator) genSQLs(ctx context.Context) { 217 for { 218 select { 219 case <-ctx.Done(): 220 return 221 default: 222 for _, table := range g.tables { 223 rand.Shuffle(len(g.testCases), func(i, j int) { g.testCases[i], g.testCases[j] = g.testCases[j], g.testCases[i] }) 224 casesNum := rand.Intn(len(g.testCases) + 1) 225 for i := 0; i < casesNum; i++ { 226 for _, sqls := range g.testCases[i] { 227 fullSqls := make(SQLs, len(sqls)) 228 copy(fullSqls, sqls) 229 for idx, sql := range fullSqls { 230 fullSqls[idx].statement = fmt.Sprintf(sql.statement, g.schema, table) 231 } 232 g.sqlsChan <- fullSqls 233 } 234 } 235 } 236 g.sqlsChan <- nil 237 } 238 } 239 } 240 241 // GetSQLs gets sql from CaseGenerator. 242 func (g *CaseGenerator) GetSQLs() SQLs { 243 return <-g.sqlsChan 244 } 245 246 // GetPreSQLs gets preSQLs from CaseGenerator. 247 func (g *CaseGenerator) GetPreSQLs() SQLs { 248 testPreSQLs := make(SQLs, 0, len(g.testPreSQLs)*len(g.tables)) 249 for _, table := range g.tables { 250 for _, sql := range g.testPreSQLs { 251 testPreSQLs = append(testPreSQLs, SQL{fmt.Sprintf(sql.statement, g.schema, table), sql.source}) 252 } 253 } 254 return testPreSQLs 255 }