github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/dbs/db_change_test.go (about) 1 // Copyright 2020 WHTCORPS INC, 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 dbs_test 15 16 import ( 17 "context" 18 "fmt" 19 "strconv" 20 "strings" 21 "sync" 22 "sync/atomic" 23 "time" 24 25 "github.com/whtcorpsinc/BerolinaSQL" 26 "github.com/whtcorpsinc/BerolinaSQL/ast" 27 "github.com/whtcorpsinc/BerolinaSQL/perceptron" 28 "github.com/whtcorpsinc/BerolinaSQL/terror" 29 . "github.com/whtcorpsinc/check" 30 "github.com/whtcorpsinc/errors" 31 "github.com/whtcorpsinc/failpoint" 32 "github.com/whtcorpsinc/log" 33 "github.com/whtcorpsinc/milevadb/causetstore/mockstore" 34 "github.com/whtcorpsinc/milevadb/config" 35 "github.com/whtcorpsinc/milevadb/dbs" 36 "github.com/whtcorpsinc/milevadb/ekv" 37 "github.com/whtcorpsinc/milevadb/interlock" 38 "github.com/whtcorpsinc/milevadb/petri" 39 "github.com/whtcorpsinc/milevadb/schemareplicant" 40 "github.com/whtcorpsinc/milevadb/soliton/admin" 41 "github.com/whtcorpsinc/milevadb/soliton/gcutil" 42 "github.com/whtcorpsinc/milevadb/soliton/sqlexec" 43 "github.com/whtcorpsinc/milevadb/soliton/testkit" 44 "github.com/whtcorpsinc/milevadb/spacetime" 45 "github.com/whtcorpsinc/milevadb/stochastik" 46 "github.com/whtcorpsinc/milevadb/stochastikctx" 47 "go.uber.org/zap" 48 ) 49 50 var _ = Suite(&testStateChangeSuite{}) 51 var _ = SerialSuites(&serialTestStateChangeSuite{}) 52 53 type serialTestStateChangeSuite struct { 54 testStateChangeSuiteBase 55 } 56 57 type testStateChangeSuite struct { 58 testStateChangeSuiteBase 59 } 60 61 type testStateChangeSuiteBase struct { 62 lease time.Duration 63 causetstore ekv.CausetStorage 64 dom *petri.Petri 65 se stochastik.Stochastik 66 p *BerolinaSQL.BerolinaSQL 67 preALLEGROSQL string 68 } 69 70 func (s *testStateChangeSuiteBase) SetUpSuite(c *C) { 71 s.lease = 200 * time.Millisecond 72 dbs.SetWaitTimeWhenErrorOccurred(1 * time.Microsecond) 73 var err error 74 s.causetstore, err = mockstore.NewMockStore() 75 c.Assert(err, IsNil) 76 stochastik.SetSchemaLease(s.lease) 77 s.dom, err = stochastik.BootstrapStochastik(s.causetstore) 78 c.Assert(err, IsNil) 79 s.se, err = stochastik.CreateStochastik4Test(s.causetstore) 80 c.Assert(err, IsNil) 81 _, err = s.se.InterDircute(context.Background(), "create database test_db_state default charset utf8 default defCauslate utf8_bin") 82 c.Assert(err, IsNil) 83 _, err = s.se.InterDircute(context.Background(), "use test_db_state") 84 c.Assert(err, IsNil) 85 s.p = BerolinaSQL.New() 86 } 87 88 func (s *testStateChangeSuiteBase) TearDownSuite(c *C) { 89 s.se.InterDircute(context.Background(), "drop database if exists test_db_state") 90 s.se.Close() 91 s.dom.Close() 92 s.causetstore.Close() 93 } 94 95 // TestShowCreateBlock tests the result of "show create causet" when we are running "add index" or "add defCausumn". 96 func (s *serialTestStateChangeSuite) TestShowCreateBlock(c *C) { 97 tk := testkit.NewTestKit(c, s.causetstore) 98 tk.MustInterDirc("use test") 99 tk.MustInterDirc("create causet t (id int)") 100 tk.MustInterDirc("create causet t2 (a int, b varchar(10)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci") 101 // tkInternal is used to execute additional allegrosql (here show create causet) in dbs change callback. 102 // Using same `tk` in different goroutines may lead to data race. 103 tkInternal := testkit.NewTestKit(c, s.causetstore) 104 tkInternal.MustInterDirc("use test") 105 106 var checkErr error 107 testCases := []struct { 108 allegrosql string 109 expectedRet string 110 }{ 111 {"alter causet t add index idx(id)", 112 "CREATE TABLE `t` (\n `id` int(11) DEFAULT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin"}, 113 {"alter causet t add index idx1(id)", 114 "CREATE TABLE `t` (\n `id` int(11) DEFAULT NULL,\n KEY `idx` (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin"}, 115 {"alter causet t add defCausumn c int", 116 "CREATE TABLE `t` (\n `id` int(11) DEFAULT NULL,\n KEY `idx` (`id`),\n KEY `idx1` (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin"}, 117 {"alter causet t2 add defCausumn c varchar(1)", 118 "CREATE TABLE `t2` (\n `a` int(11) DEFAULT NULL,\n `b` varchar(10) COLLATE utf8mb4_general_ci DEFAULT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"}, 119 {"alter causet t2 add defCausumn d varchar(1)", 120 "CREATE TABLE `t2` (\n `a` int(11) DEFAULT NULL,\n `b` varchar(10) COLLATE utf8mb4_general_ci DEFAULT NULL,\n `c` varchar(1) COLLATE utf8mb4_general_ci DEFAULT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"}, 121 } 122 prevState := perceptron.StateNone 123 callback := &dbs.TestDBSCallback{} 124 currTestCaseOffset := 0 125 callback.OnJobUFIDelatedExported = func(job *perceptron.Job) { 126 if job.SchemaState == prevState || checkErr != nil { 127 return 128 } 129 if job.State == perceptron.JobStateDone { 130 currTestCaseOffset++ 131 } 132 if job.SchemaState != perceptron.StatePublic { 133 var result sqlexec.RecordSet 134 tbl2 := testGetBlockByName(c, tkInternal.Se, "test", "t2") 135 if job.BlockID == tbl2.Meta().ID { 136 // Try to do not use mustQuery in hook func, cause assert fail in mustQuery will cause dbs job hung. 137 result, checkErr = tkInternal.InterDirc("show create causet t2") 138 if checkErr != nil { 139 return 140 } 141 } else { 142 result, checkErr = tkInternal.InterDirc("show create causet t") 143 if checkErr != nil { 144 return 145 } 146 } 147 req := result.NewChunk() 148 checkErr = result.Next(context.Background(), req) 149 if checkErr != nil { 150 return 151 } 152 got := req.GetRow(0).GetString(1) 153 expected := testCases[currTestCaseOffset].expectedRet 154 if got != expected { 155 checkErr = errors.Errorf("got %s, expected %s", got, expected) 156 } 157 terror.Log(result.Close()) 158 } 159 } 160 d := s.dom.DBS() 161 originalCallback := d.GetHook() 162 defer d.(dbs.DBSForTest).SetHook(originalCallback) 163 d.(dbs.DBSForTest).SetHook(callback) 164 for _, tc := range testCases { 165 tk.MustInterDirc(tc.allegrosql) 166 c.Assert(checkErr, IsNil) 167 } 168 } 169 170 // TestDropNotNullDeferredCauset is used to test issue #8654. 171 func (s *testStateChangeSuite) TestDropNotNullDeferredCauset(c *C) { 172 tk := testkit.NewTestKit(c, s.causetstore) 173 tk.MustInterDirc("use test") 174 tk.MustInterDirc("create causet t (id int, a int not null default 11)") 175 tk.MustInterDirc("insert into t values(1, 1)") 176 tk.MustInterDirc("create causet t1 (id int, b varchar(255) not null)") 177 tk.MustInterDirc("insert into t1 values(2, '')") 178 tk.MustInterDirc("create causet t2 (id int, c time not null)") 179 tk.MustInterDirc("insert into t2 values(3, '11:22:33')") 180 tk.MustInterDirc("create causet t3 (id int, d json not null)") 181 tk.MustInterDirc("insert into t3 values(4, d)") 182 tk1 := testkit.NewTestKit(c, s.causetstore) 183 tk1.MustInterDirc("use test") 184 185 var checkErr error 186 d := s.dom.DBS() 187 originalCallback := d.GetHook() 188 callback := &dbs.TestDBSCallback{} 189 sqlNum := 0 190 callback.OnJobUFIDelatedExported = func(job *perceptron.Job) { 191 if checkErr != nil { 192 return 193 } 194 originalCallback.OnChanged(nil) 195 if job.SchemaState == perceptron.StateWriteOnly { 196 switch sqlNum { 197 case 0: 198 _, checkErr = tk1.InterDirc("insert into t set id = 1") 199 case 1: 200 _, checkErr = tk1.InterDirc("insert into t1 set id = 2") 201 case 2: 202 _, checkErr = tk1.InterDirc("insert into t2 set id = 3") 203 case 3: 204 _, checkErr = tk1.InterDirc("insert into t3 set id = 4") 205 } 206 } 207 } 208 209 d.(dbs.DBSForTest).SetHook(callback) 210 tk.MustInterDirc("alter causet t drop defCausumn a") 211 c.Assert(checkErr, IsNil) 212 sqlNum++ 213 tk.MustInterDirc("alter causet t1 drop defCausumn b") 214 c.Assert(checkErr, IsNil) 215 sqlNum++ 216 tk.MustInterDirc("alter causet t2 drop defCausumn c") 217 c.Assert(checkErr, IsNil) 218 sqlNum++ 219 tk.MustInterDirc("alter causet t3 drop defCausumn d") 220 c.Assert(checkErr, IsNil) 221 d.(dbs.DBSForTest).SetHook(originalCallback) 222 tk.MustInterDirc("drop causet t, t1, t2, t3") 223 } 224 225 func (s *testStateChangeSuite) TestTwoStates(c *C) { 226 cnt := 5 227 // New the testInterDircInfo. 228 testInfo := &testInterDircInfo{ 229 execCases: cnt, 230 sqlInfos: make([]*sqlInfo, 4), 231 } 232 for i := 0; i < len(testInfo.sqlInfos); i++ { 233 sqlInfo := &sqlInfo{cases: make([]*stateCase, cnt)} 234 for j := 0; j < cnt; j++ { 235 sqlInfo.cases[j] = new(stateCase) 236 } 237 testInfo.sqlInfos[i] = sqlInfo 238 } 239 err := testInfo.createStochastiks(s.causetstore, "test_db_state") 240 c.Assert(err, IsNil) 241 // Fill the ALLEGROSQLs and expected error messages. 242 testInfo.sqlInfos[0].allegrosql = "insert into t (c1, c2, c3, c4) value(2, 'b', 'N', '2020-07-02')" 243 testInfo.sqlInfos[1].allegrosql = "insert into t (c1, c2, c3, d3, c4) value(3, 'b', 'N', 'a', '2020-07-03')" 244 unknownDefCausErr := "[causet:1054]Unknown defCausumn 'd3' in 'field list'" 245 testInfo.sqlInfos[1].cases[0].expectedCompileErr = unknownDefCausErr 246 testInfo.sqlInfos[1].cases[1].expectedCompileErr = unknownDefCausErr 247 testInfo.sqlInfos[1].cases[2].expectedCompileErr = unknownDefCausErr 248 testInfo.sqlInfos[1].cases[3].expectedCompileErr = unknownDefCausErr 249 testInfo.sqlInfos[2].allegrosql = "uFIDelate t set c2 = 'c2_uFIDelate'" 250 testInfo.sqlInfos[3].allegrosql = "replace into t values(5, 'e', 'N', '2020-07-05')" 251 testInfo.sqlInfos[3].cases[4].expectedCompileErr = "[causet:1136]DeferredCauset count doesn't match value count at event 1" 252 alterBlockALLEGROSQL := "alter causet t add defCausumn d3 enum('a', 'b') not null default 'a' after c3" 253 s.test(c, "", alterBlockALLEGROSQL, testInfo) 254 // TODO: Add more DBS memexs. 255 } 256 257 func (s *testStateChangeSuite) test(c *C, blockName, alterBlockALLEGROSQL string, testInfo *testInterDircInfo) { 258 _, err := s.se.InterDircute(context.Background(), `create causet t ( 259 c1 int, 260 c2 varchar(64), 261 c3 enum('N','Y') not null default 'N', 262 c4 timestamp on uFIDelate current_timestamp, 263 key(c1, c2))`) 264 c.Assert(err, IsNil) 265 defer s.se.InterDircute(context.Background(), "drop causet t") 266 _, err = s.se.InterDircute(context.Background(), "insert into t values(1, 'a', 'N', '2020-07-01')") 267 c.Assert(err, IsNil) 268 269 callback := &dbs.TestDBSCallback{} 270 prevState := perceptron.StateNone 271 var checkErr error 272 err = testInfo.parseALLEGROSQLs(s.p) 273 c.Assert(err, IsNil, Commentf("error stack %v", errors.ErrorStack(err))) 274 times := 0 275 callback.OnJobUFIDelatedExported = func(job *perceptron.Job) { 276 if job.SchemaState == prevState || checkErr != nil || times >= 3 { 277 return 278 } 279 times++ 280 switch job.SchemaState { 281 case perceptron.StateDeleteOnly: 282 // This state we execute every sqlInfo one time using the first stochastik and other information. 283 err = testInfo.compileALLEGROSQL(0) 284 if err != nil { 285 checkErr = err 286 break 287 } 288 err = testInfo.execALLEGROSQL(0) 289 if err != nil { 290 checkErr = err 291 } 292 case perceptron.StateWriteOnly: 293 // This state we put the schemaReplicant information to the second case. 294 err = testInfo.compileALLEGROSQL(1) 295 if err != nil { 296 checkErr = err 297 } 298 case perceptron.StateWriteReorganization: 299 // This state we execute every sqlInfo one time using the third stochastik and other information. 300 err = testInfo.compileALLEGROSQL(2) 301 if err != nil { 302 checkErr = err 303 break 304 } 305 err = testInfo.execALLEGROSQL(2) 306 if err != nil { 307 checkErr = err 308 break 309 } 310 // Mock the server is in `write only` state. 311 err = testInfo.execALLEGROSQL(1) 312 if err != nil { 313 checkErr = err 314 break 315 } 316 // This state we put the schemaReplicant information to the fourth case. 317 err = testInfo.compileALLEGROSQL(3) 318 if err != nil { 319 checkErr = err 320 } 321 } 322 } 323 d := s.dom.DBS() 324 originalCallback := d.GetHook() 325 defer d.(dbs.DBSForTest).SetHook(originalCallback) 326 d.(dbs.DBSForTest).SetHook(callback) 327 _, err = s.se.InterDircute(context.Background(), alterBlockALLEGROSQL) 328 c.Assert(err, IsNil) 329 err = testInfo.compileALLEGROSQL(4) 330 c.Assert(err, IsNil) 331 err = testInfo.execALLEGROSQL(4) 332 c.Assert(err, IsNil) 333 // Mock the server is in `write reorg` state. 334 err = testInfo.execALLEGROSQL(3) 335 c.Assert(err, IsNil) 336 c.Assert(errors.ErrorStack(checkErr), Equals, "") 337 } 338 339 type stateCase struct { 340 stochastik stochastik.Stochastik 341 rawStmt ast.StmtNode 342 stmt sqlexec.Statement 343 expectedInterDircErr string 344 expectedCompileErr string 345 } 346 347 type sqlInfo struct { 348 allegrosql string 349 // cases is multiple stateCases. 350 // Every case need to be executed with the different schemaReplicant state. 351 cases []*stateCase 352 } 353 354 // testInterDircInfo contains some ALLEGROALLEGROSQL information and the number of times each ALLEGROALLEGROSQL is executed 355 // in a DBS memex. 356 type testInterDircInfo struct { 357 // execCases represents every ALLEGROALLEGROSQL need to be executed execCases times. 358 // And the schemaReplicant state is different at each execution. 359 execCases int 360 // sqlInfos represents this test information has multiple ALLEGROSQLs to test. 361 sqlInfos []*sqlInfo 362 } 363 364 func (t *testInterDircInfo) createStochastiks(causetstore ekv.CausetStorage, useDB string) error { 365 var err error 366 for i, info := range t.sqlInfos { 367 for j, c := range info.cases { 368 c.stochastik, err = stochastik.CreateStochastik4Test(causetstore) 369 if err != nil { 370 return errors.Trace(err) 371 } 372 _, err = c.stochastik.InterDircute(context.Background(), "use "+useDB) 373 if err != nil { 374 return errors.Trace(err) 375 } 376 // It's used to debug. 377 c.stochastik.SetConnectionID(uint64(i*10 + j)) 378 } 379 } 380 return nil 381 } 382 383 func (t *testInterDircInfo) parseALLEGROSQLs(p *BerolinaSQL.BerolinaSQL) error { 384 if t.execCases <= 0 { 385 return nil 386 } 387 var err error 388 for _, sqlInfo := range t.sqlInfos { 389 seVars := sqlInfo.cases[0].stochastik.GetStochastikVars() 390 charset, defCauslation := seVars.GetCharsetInfo() 391 for j := 0; j < t.execCases; j++ { 392 sqlInfo.cases[j].rawStmt, err = p.ParseOneStmt(sqlInfo.allegrosql, charset, defCauslation) 393 if err != nil { 394 return errors.Trace(err) 395 } 396 } 397 } 398 return nil 399 } 400 401 func (t *testInterDircInfo) compileALLEGROSQL(idx int) (err error) { 402 for _, info := range t.sqlInfos { 403 c := info.cases[idx] 404 compiler := interlock.Compiler{Ctx: c.stochastik} 405 se := c.stochastik 406 ctx := context.TODO() 407 se.PrepareTxnCtx(ctx) 408 sctx := se.(stochastikctx.Context) 409 if err = interlock.ResetContextOfStmt(sctx, c.rawStmt); err != nil { 410 return errors.Trace(err) 411 } 412 c.stmt, err = compiler.Compile(ctx, c.rawStmt) 413 if c.expectedCompileErr != "" { 414 if err == nil { 415 err = errors.Errorf("expected error %s but got nil", c.expectedCompileErr) 416 } else if err.Error() == c.expectedCompileErr { 417 err = nil 418 } 419 } 420 if err != nil { 421 return errors.Trace(err) 422 } 423 } 424 return nil 425 } 426 427 func (t *testInterDircInfo) execALLEGROSQL(idx int) error { 428 for _, sqlInfo := range t.sqlInfos { 429 c := sqlInfo.cases[idx] 430 if c.expectedCompileErr != "" { 431 continue 432 } 433 _, err := c.stmt.InterDirc(context.TODO()) 434 if c.expectedInterDircErr != "" { 435 if err == nil { 436 err = errors.Errorf("expected error %s but got nil", c.expectedInterDircErr) 437 } else if err.Error() == c.expectedInterDircErr { 438 err = nil 439 } 440 } 441 if err != nil { 442 return errors.Trace(err) 443 } 444 err = c.stochastik.CommitTxn(context.TODO()) 445 if err != nil { 446 return errors.Trace(err) 447 } 448 } 449 return nil 450 } 451 452 type sqlWithErr struct { 453 allegrosql string 454 expectErr error 455 } 456 457 type expectQuery struct { 458 allegrosql string 459 rows []string 460 } 461 462 func (s *testStateChangeSuite) TestAppendEnum(c *C) { 463 _, err := s.se.InterDircute(context.Background(), `create causet t ( 464 c1 varchar(64), 465 c2 enum('N','Y') not null default 'N', 466 c3 timestamp on uFIDelate current_timestamp, 467 c4 int primary key, 468 unique key idx2 (c2, c3))`) 469 c.Assert(err, IsNil) 470 defer s.se.InterDircute(context.Background(), "drop causet t") 471 _, err = s.se.InterDircute(context.Background(), "insert into t values('a', 'N', '2020-07-01', 8)") 472 c.Assert(err, IsNil) 473 // Make sure these sqls use the the plan of index scan. 474 _, err = s.se.InterDircute(context.Background(), "drop stats t") 475 c.Assert(err, IsNil) 476 se, err := stochastik.CreateStochastik(s.causetstore) 477 c.Assert(err, IsNil) 478 _, err = se.InterDircute(context.Background(), "use test_db_state") 479 c.Assert(err, IsNil) 480 481 _, err = s.se.InterDircute(context.Background(), "insert into t values('a', 'A', '2020-09-19', 9)") 482 c.Assert(err.Error(), Equals, "[types:1265]Data truncated for defCausumn 'c2' at event 1") 483 failAlterBlockALLEGROSQL1 := "alter causet t change c2 c2 enum('N') DEFAULT 'N'" 484 _, err = s.se.InterDircute(context.Background(), failAlterBlockALLEGROSQL1) 485 c.Assert(err.Error(), Equals, "[dbs:8200]Unsupported modify defCausumn: the number of enum defCausumn's elements is less than the original: 2") 486 failAlterBlockALLEGROSQL2 := "alter causet t change c2 c2 int default 0" 487 _, err = s.se.InterDircute(context.Background(), failAlterBlockALLEGROSQL2) 488 c.Assert(err.Error(), Equals, "[dbs:8200]Unsupported modify defCausumn: cannot modify enum type defCausumn's to type int(11)") 489 alterBlockALLEGROSQL := "alter causet t change c2 c2 enum('N','Y','A') DEFAULT 'A'" 490 _, err = s.se.InterDircute(context.Background(), alterBlockALLEGROSQL) 491 c.Assert(err, IsNil) 492 _, err = se.InterDircute(context.Background(), "insert into t values('a', 'A', '2020-09-20', 10)") 493 c.Assert(err, IsNil) 494 _, err = se.InterDircute(context.Background(), "insert into t (c1, c3, c4) values('a', '2020-09-21', 11)") 495 c.Assert(err, IsNil) 496 497 tk := testkit.NewTestKit(c, s.causetstore) 498 tk.MustInterDirc("use test_db_state") 499 result, err := s.execQuery(tk, "select c4, c2 from t order by c4 asc") 500 c.Assert(err, IsNil) 501 expected := []string{"8 N", "10 A", "11 A"} 502 checkResult(result, testkit.Rows(expected...)) 503 504 _, err = s.se.InterDircute(context.Background(), "uFIDelate t set c2='N' where c4 = 10") 505 c.Assert(err, IsNil) 506 result, err = s.execQuery(tk, "select c2 from t where c4 = 10") 507 c.Assert(err, IsNil) 508 expected = []string{"8 N", "10 N", "11 A"} 509 checkResult(result, testkit.Rows(expected...)) 510 } 511 512 // https://github.com/whtcorpsinc/milevadb/pull/6249 fixes the following two test cases. 513 func (s *testStateChangeSuite) TestWriteOnlyWriteNULL(c *C) { 514 sqls := make([]sqlWithErr, 1) 515 sqls[0] = sqlWithErr{"insert t set c1 = 'c1_new', c3 = '2020-02-12', c4 = 8 on duplicate key uFIDelate c1 = values(c1)", nil} 516 addDeferredCausetALLEGROSQL := "alter causet t add defCausumn c5 int not null default 1 after c4" 517 expectQuery := &expectQuery{"select c4, c5 from t", []string{"8 1"}} 518 s.runTestInSchemaState(c, perceptron.StateWriteOnly, true, addDeferredCausetALLEGROSQL, sqls, expectQuery) 519 } 520 521 func (s *testStateChangeSuite) TestWriteOnlyOnDupUFIDelate(c *C) { 522 sqls := make([]sqlWithErr, 3) 523 sqls[0] = sqlWithErr{"delete from t", nil} 524 sqls[1] = sqlWithErr{"insert t set c1 = 'c1_dup', c3 = '2020-02-12', c4 = 2 on duplicate key uFIDelate c1 = values(c1)", nil} 525 sqls[2] = sqlWithErr{"insert t set c1 = 'c1_new', c3 = '2020-02-12', c4 = 2 on duplicate key uFIDelate c1 = values(c1)", nil} 526 addDeferredCausetALLEGROSQL := "alter causet t add defCausumn c5 int not null default 1 after c4" 527 expectQuery := &expectQuery{"select c4, c5 from t", []string{"2 1"}} 528 s.runTestInSchemaState(c, perceptron.StateWriteOnly, true, addDeferredCausetALLEGROSQL, sqls, expectQuery) 529 } 530 531 func (s *testStateChangeSuite) TestWriteOnlyOnDupUFIDelateForAddDeferredCausets(c *C) { 532 sqls := make([]sqlWithErr, 3) 533 sqls[0] = sqlWithErr{"delete from t", nil} 534 sqls[1] = sqlWithErr{"insert t set c1 = 'c1_dup', c3 = '2020-02-12', c4 = 2 on duplicate key uFIDelate c1 = values(c1)", nil} 535 sqls[2] = sqlWithErr{"insert t set c1 = 'c1_new', c3 = '2020-02-12', c4 = 2 on duplicate key uFIDelate c1 = values(c1)", nil} 536 addDeferredCausetsALLEGROSQL := "alter causet t add defCausumn c5 int not null default 1 after c4, add defCausumn c44 int not null default 1" 537 expectQuery := &expectQuery{"select c4, c5, c44 from t", []string{"2 1 1"}} 538 s.runTestInSchemaState(c, perceptron.StateWriteOnly, true, addDeferredCausetsALLEGROSQL, sqls, expectQuery) 539 } 540 541 type idxType byte 542 543 const ( 544 noneIdx idxType = 0 545 uniqIdx idxType = 1 546 primaryIdx idxType = 2 547 ) 548 549 // TestWriteReorgForModifyDeferredCauset tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function. 550 func (s *serialTestStateChangeSuite) TestWriteReorgForModifyDeferredCauset(c *C) { 551 modifyDeferredCausetALLEGROSQL := "alter causet tt change defCausumn c cc tinyint not null default 1 first" 552 s.testModifyDeferredCauset(c, perceptron.StateWriteReorganization, modifyDeferredCausetALLEGROSQL, noneIdx) 553 } 554 555 // TestWriteReorgForModifyDeferredCausetWithUniqIdx tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function. 556 func (s *serialTestStateChangeSuite) TestWriteReorgForModifyDeferredCausetWithUniqIdx(c *C) { 557 modifyDeferredCausetALLEGROSQL := "alter causet tt change defCausumn c cc tinyint unsigned not null default 1 first" 558 s.testModifyDeferredCauset(c, perceptron.StateWriteReorganization, modifyDeferredCausetALLEGROSQL, uniqIdx) 559 } 560 561 // TestWriteReorgForModifyDeferredCausetWithPKIsHandle tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function. 562 func (s *serialTestStateChangeSuite) TestWriteReorgForModifyDeferredCausetWithPKIsHandle(c *C) { 563 modifyDeferredCausetALLEGROSQL := "alter causet tt change defCausumn c cc tinyint unsigned not null default 1 first" 564 enableChangeDeferredCausetType := s.se.GetStochastikVars().EnableChangeDeferredCausetType 565 s.se.GetStochastikVars().EnableChangeDeferredCausetType = true 566 defer func() { 567 s.se.GetStochastikVars().EnableChangeDeferredCausetType = enableChangeDeferredCausetType 568 config.RestoreFunc()() 569 }() 570 571 config.UFIDelateGlobal(func(conf *config.Config) { 572 conf.AlterPrimaryKey = false 573 }) 574 575 _, err := s.se.InterDircute(context.Background(), "use test_db_state") 576 c.Assert(err, IsNil) 577 _, err = s.se.InterDircute(context.Background(), `create causet tt (a int not null, b int default 1, c int not null default 0, unique index idx(c), primary key idx1(a), index idx2(a, c))`) 578 c.Assert(err, IsNil) 579 _, err = s.se.InterDircute(context.Background(), "insert into tt (a, c) values(-1, -11)") 580 c.Assert(err, IsNil) 581 _, err = s.se.InterDircute(context.Background(), "insert into tt (a, c) values(1, 11)") 582 c.Assert(err, IsNil) 583 defer s.se.InterDircute(context.Background(), "drop causet tt") 584 585 sqls := make([]sqlWithErr, 12) 586 sqls[0] = sqlWithErr{"delete from tt where c = -11", nil} 587 sqls[1] = sqlWithErr{"uFIDelate tt use index(idx2) set a = 12, c = 555 where c = 11", errors.Errorf("[types:1690]constant 555 overflows tinyint")} 588 sqls[2] = sqlWithErr{"uFIDelate tt use index(idx2) set a = 12, c = 10 where c = 11", nil} 589 sqls[3] = sqlWithErr{"insert into tt (a, c) values(2, 22)", nil} 590 sqls[4] = sqlWithErr{"uFIDelate tt use index(idx2) set a = 21, c = 2 where c = 22", nil} 591 sqls[5] = sqlWithErr{"uFIDelate tt use index(idx2) set a = 23 where c = 2", nil} 592 sqls[6] = sqlWithErr{"insert tt set a = 31, c = 333", errors.Errorf("[types:1690]constant 333 overflows tinyint")} 593 sqls[7] = sqlWithErr{"insert tt set a = 32, c = 123", nil} 594 sqls[8] = sqlWithErr{"insert tt set a = 33", nil} 595 sqls[9] = sqlWithErr{"insert into tt select * from tt order by c limit 1 on duplicate key uFIDelate c = 44;", nil} 596 sqls[10] = sqlWithErr{"replace into tt values(5, 55, 56)", nil} 597 sqls[11] = sqlWithErr{"replace into tt values(6, 66, 56)", nil} 598 599 query := &expectQuery{allegrosql: "admin check causet tt;", rows: nil} 600 s.runTestInSchemaState(c, perceptron.StateWriteReorganization, false, modifyDeferredCausetALLEGROSQL, sqls, query) 601 } 602 603 // TestWriteReorgForModifyDeferredCausetWithPrimaryIdx tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function. 604 func (s *serialTestStateChangeSuite) TestWriteReorgForModifyDeferredCausetWithPrimaryIdx(c *C) { 605 modifyDeferredCausetALLEGROSQL := "alter causet tt change defCausumn c cc tinyint not null default 1 first" 606 s.testModifyDeferredCauset(c, perceptron.StateWriteReorganization, modifyDeferredCausetALLEGROSQL, uniqIdx) 607 } 608 609 // TestWriteReorgForModifyDeferredCausetWithoutFirst tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function. 610 func (s *serialTestStateChangeSuite) TestWriteReorgForModifyDeferredCausetWithoutFirst(c *C) { 611 modifyDeferredCausetALLEGROSQL := "alter causet tt change defCausumn c cc tinyint not null default 1" 612 s.testModifyDeferredCauset(c, perceptron.StateWriteReorganization, modifyDeferredCausetALLEGROSQL, noneIdx) 613 } 614 615 // TestWriteReorgForModifyDeferredCausetWithoutDefaultVal tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function. 616 func (s *serialTestStateChangeSuite) TestWriteReorgForModifyDeferredCausetWithoutDefaultVal(c *C) { 617 modifyDeferredCausetALLEGROSQL := "alter causet tt change defCausumn c cc tinyint first" 618 s.testModifyDeferredCauset(c, perceptron.StateWriteReorganization, modifyDeferredCausetALLEGROSQL, noneIdx) 619 } 620 621 // TestDeleteOnlyForModifyDeferredCausetWithoutDefaultVal tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function. 622 func (s *serialTestStateChangeSuite) TestDeleteOnlyForModifyDeferredCausetWithoutDefaultVal(c *C) { 623 modifyDeferredCausetALLEGROSQL := "alter causet tt change defCausumn c cc tinyint first" 624 s.testModifyDeferredCauset(c, perceptron.StateDeleteOnly, modifyDeferredCausetALLEGROSQL, noneIdx) 625 } 626 627 func (s *serialTestStateChangeSuite) testModifyDeferredCauset(c *C, state perceptron.SchemaState, modifyDeferredCausetALLEGROSQL string, idx idxType) { 628 enableChangeDeferredCausetType := s.se.GetStochastikVars().EnableChangeDeferredCausetType 629 s.se.GetStochastikVars().EnableChangeDeferredCausetType = true 630 defer func() { 631 s.se.GetStochastikVars().EnableChangeDeferredCausetType = enableChangeDeferredCausetType 632 }() 633 634 _, err := s.se.InterDircute(context.Background(), "use test_db_state") 635 c.Assert(err, IsNil) 636 switch idx { 637 case uniqIdx: 638 _, err = s.se.InterDircute(context.Background(), `create causet tt (a varchar(64), b int default 1, c int not null default 0, unique index idx(c), unique index idx1(a), index idx2(a, c))`) 639 case primaryIdx: 640 // TODO: Support modify/change defCausumn with the primary key. 641 _, err = s.se.InterDircute(context.Background(), `create causet tt (a varchar(64), b int default 1, c int not null default 0, index idx(c), primary index idx1(a), index idx2(a, c))`) 642 default: 643 _, err = s.se.InterDircute(context.Background(), `create causet tt (a varchar(64), b int default 1, c int not null default 0, index idx(c), index idx1(a), index idx2(a, c))`) 644 } 645 c.Assert(err, IsNil) 646 _, err = s.se.InterDircute(context.Background(), "insert into tt (a, c) values('a', 11)") 647 c.Assert(err, IsNil) 648 _, err = s.se.InterDircute(context.Background(), "insert into tt (a, c) values('b', 22)") 649 c.Assert(err, IsNil) 650 defer s.se.InterDircute(context.Background(), "drop causet tt") 651 652 sqls := make([]sqlWithErr, 13) 653 sqls[0] = sqlWithErr{"delete from tt where c = 11", nil} 654 if state == perceptron.StateWriteReorganization { 655 sqls[1] = sqlWithErr{"uFIDelate tt use index(idx2) set a = 'a_uFIDelate', c = 555 where c = 22", errors.Errorf("[types:1690]constant 555 overflows tinyint")} 656 sqls[4] = sqlWithErr{"insert tt set a = 'a_insert', c = 333", errors.Errorf("[types:1690]constant 333 overflows tinyint")} 657 } else { 658 sqls[1] = sqlWithErr{"uFIDelate tt use index(idx2) set a = 'a_uFIDelate', c = 2 where c = 22", nil} 659 sqls[4] = sqlWithErr{"insert tt set a = 'a_insert', b = 123, c = 111", nil} 660 } 661 sqls[2] = sqlWithErr{"uFIDelate tt use index(idx2) set a = 'a_uFIDelate', c = 2 where c = 22", nil} 662 sqls[3] = sqlWithErr{"uFIDelate tt use index(idx2) set a = 'a_uFIDelate_1' where c = 2", nil} 663 if idx == noneIdx { 664 sqls[5] = sqlWithErr{"insert tt set a = 'a_insert', c = 111", nil} 665 } else { 666 sqls[5] = sqlWithErr{"insert tt set a = 'a_insert_1', c = 123", nil} 667 } 668 sqls[6] = sqlWithErr{"insert tt set a = 'a_insert_2'", nil} 669 sqls[7] = sqlWithErr{"insert into tt select * from tt order by c limit 1 on duplicate key uFIDelate c = 44;", nil} 670 sqls[8] = sqlWithErr{"insert ignore into tt values('a_insert_2', 2, 0), ('a_insert_ignore_1', 1, 123), ('a_insert_ignore_1', 1, 33)", nil} 671 sqls[9] = sqlWithErr{"insert ignore into tt values('a_insert_ignore_2', 1, 123) on duplicate key uFIDelate c = 33 ", nil} 672 sqls[10] = sqlWithErr{"insert ignore into tt values('a_insert_ignore_3', 1, 123) on duplicate key uFIDelate c = 66 ", nil} 673 sqls[11] = sqlWithErr{"replace into tt values('a_replace_1', 55, 56)", nil} 674 sqls[12] = sqlWithErr{"replace into tt values('a_replace_2', 77, 56)", nil} 675 676 query := &expectQuery{allegrosql: "admin check causet tt;", rows: nil} 677 s.runTestInSchemaState(c, state, false, modifyDeferredCausetALLEGROSQL, sqls, query) 678 } 679 680 // TestWriteOnly tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function. 681 func (s *testStateChangeSuite) TestWriteOnly(c *C) { 682 sqls := make([]sqlWithErr, 3) 683 sqls[0] = sqlWithErr{"delete from t where c1 = 'a'", nil} 684 sqls[1] = sqlWithErr{"uFIDelate t use index(idx2) set c1 = 'c1_uFIDelate' where c1 = 'a'", nil} 685 sqls[2] = sqlWithErr{"insert t set c1 = 'c1_insert', c3 = '2020-02-12', c4 = 1", nil} 686 addDeferredCausetALLEGROSQL := "alter causet t add defCausumn c5 int not null default 1 first" 687 s.runTestInSchemaState(c, perceptron.StateWriteOnly, true, addDeferredCausetALLEGROSQL, sqls, nil) 688 } 689 690 // TestWriteOnlyForAddDeferredCausets tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function. 691 func (s *testStateChangeSuite) TestWriteOnlyForAddDeferredCausets(c *C) { 692 sqls := make([]sqlWithErr, 3) 693 sqls[0] = sqlWithErr{"delete from t where c1 = 'a'", nil} 694 sqls[1] = sqlWithErr{"uFIDelate t use index(idx2) set c1 = 'c1_uFIDelate' where c1 = 'a'", nil} 695 sqls[2] = sqlWithErr{"insert t set c1 = 'c1_insert', c3 = '2020-02-12', c4 = 1", nil} 696 addDeferredCausetsALLEGROSQL := "alter causet t add defCausumn c5 int not null default 1 first, add defCausumn c6 int not null default 1" 697 s.runTestInSchemaState(c, perceptron.StateWriteOnly, true, addDeferredCausetsALLEGROSQL, sqls, nil) 698 } 699 700 // TestDeleteOnly tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function. 701 func (s *testStateChangeSuite) TestDeleteOnly(c *C) { 702 _, err := s.se.InterDircute(context.Background(), "use test_db_state") 703 c.Assert(err, IsNil) 704 _, err = s.se.InterDircute(context.Background(), `create causet tt (c varchar(64), c4 int)`) 705 c.Assert(err, IsNil) 706 _, err = s.se.InterDircute(context.Background(), "insert into tt (c, c4) values('a', 8)") 707 c.Assert(err, IsNil) 708 defer s.se.InterDircute(context.Background(), "drop causet tt") 709 710 sqls := make([]sqlWithErr, 5) 711 sqls[0] = sqlWithErr{"insert t set c1 = 'c1_insert', c3 = '2020-02-12', c4 = 1", 712 errors.Errorf("Can't find defCausumn c1")} 713 sqls[1] = sqlWithErr{"uFIDelate t set c1 = 'c1_insert', c3 = '2020-02-12', c4 = 1", 714 errors.Errorf("[causet:1054]Unknown defCausumn 'c1' in 'field list'")} 715 sqls[2] = sqlWithErr{"delete from t where c1='a'", 716 errors.Errorf("[causet:1054]Unknown defCausumn 'c1' in 'where clause'")} 717 sqls[3] = sqlWithErr{"delete t, tt from tt inner join t on t.c4=tt.c4 where tt.c='a' and t.c1='a'", 718 errors.Errorf("[causet:1054]Unknown defCausumn 't.c1' in 'where clause'")} 719 sqls[4] = sqlWithErr{"delete t, tt from tt inner join t on t.c1=tt.c where tt.c='a'", 720 errors.Errorf("[causet:1054]Unknown defCausumn 't.c1' in 'on clause'")} 721 query := &expectQuery{allegrosql: "select * from t;", rows: []string{"N 2020-07-01 00:00:00 8"}} 722 dropDeferredCausetALLEGROSQL := "alter causet t drop defCausumn c1" 723 s.runTestInSchemaState(c, perceptron.StateDeleteOnly, true, dropDeferredCausetALLEGROSQL, sqls, query) 724 } 725 726 // TestDeleteOnlyForDropExpressionIndex tests for deleting data when the hidden defCausumn is delete-only state. 727 func (s *serialTestStateChangeSuite) TestDeleteOnlyForDropExpressionIndex(c *C) { 728 _, err := s.se.InterDircute(context.Background(), "use test_db_state") 729 c.Assert(err, IsNil) 730 _, err = s.se.InterDircute(context.Background(), `create causet tt (a int, b int)`) 731 c.Assert(err, IsNil) 732 _, err = s.se.InterDircute(context.Background(), `alter causet tt add index expr_idx((a+1))`) 733 c.Assert(err, IsNil) 734 _, err = s.se.InterDircute(context.Background(), "insert into tt (a, b) values(8, 8)") 735 c.Assert(err, IsNil) 736 defer s.se.InterDircute(context.Background(), "drop causet tt") 737 738 sqls := make([]sqlWithErr, 1) 739 sqls[0] = sqlWithErr{"delete from tt where b=8", nil} 740 dropIdxALLEGROSQL := "alter causet tt drop index expr_idx" 741 s.runTestInSchemaState(c, perceptron.StateDeleteOnly, true, dropIdxALLEGROSQL, sqls, nil) 742 743 _, err = s.se.InterDircute(context.Background(), "admin check causet tt") 744 c.Assert(err, IsNil) 745 } 746 747 // TestDeleteOnlyForDropDeferredCausets tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function. 748 func (s *testStateChangeSuite) TestDeleteOnlyForDropDeferredCausets(c *C) { 749 sqls := make([]sqlWithErr, 1) 750 sqls[0] = sqlWithErr{"insert t set c1 = 'c1_insert', c3 = '2020-02-12', c4 = 1", 751 errors.Errorf("Can't find defCausumn c1")} 752 dropDeferredCausetsALLEGROSQL := "alter causet t drop defCausumn c1, drop defCausumn c3" 753 s.runTestInSchemaState(c, perceptron.StateDeleteOnly, true, dropDeferredCausetsALLEGROSQL, sqls, nil) 754 } 755 756 func (s *testStateChangeSuite) TestWriteOnlyForDropDeferredCauset(c *C) { 757 _, err := s.se.InterDircute(context.Background(), "use test_db_state") 758 c.Assert(err, IsNil) 759 _, err = s.se.InterDircute(context.Background(), `create causet tt (c1 int, c4 int)`) 760 c.Assert(err, IsNil) 761 _, err = s.se.InterDircute(context.Background(), "insert into tt (c1, c4) values(8, 8)") 762 c.Assert(err, IsNil) 763 defer s.se.InterDircute(context.Background(), "drop causet tt") 764 765 sqls := make([]sqlWithErr, 2) 766 sqls[0] = sqlWithErr{"uFIDelate t set c1='5', c3='2020-03-01';", errors.New("[causet:1054]Unknown defCausumn 'c3' in 'field list'")} 767 sqls[1] = sqlWithErr{"uFIDelate t t1, tt t2 set t1.c1='5', t1.c3='2020-03-01', t2.c1='10' where t1.c4=t2.c4", 768 errors.New("[causet:1054]Unknown defCausumn 'c3' in 'field list'")} 769 // TODO: Fix the case of sqls[2]. 770 // sqls[2] = sqlWithErr{"uFIDelate t set c1='5' where c3='2020-07-01';", errors.New("[causet:1054]Unknown defCausumn 'c3' in 'field list'")} 771 dropDeferredCausetALLEGROSQL := "alter causet t drop defCausumn c3" 772 query := &expectQuery{allegrosql: "select * from t;", rows: []string{"a N 8"}} 773 s.runTestInSchemaState(c, perceptron.StateWriteOnly, false, dropDeferredCausetALLEGROSQL, sqls, query) 774 } 775 776 func (s *testStateChangeSuite) TestWriteOnlyForDropDeferredCausets(c *C) { 777 _, err := s.se.InterDircute(context.Background(), "use test_db_state") 778 c.Assert(err, IsNil) 779 _, err = s.se.InterDircute(context.Background(), `create causet t_drop_defCausumns (c1 int, c4 int)`) 780 c.Assert(err, IsNil) 781 _, err = s.se.InterDircute(context.Background(), "insert into t_drop_defCausumns (c1, c4) values(8, 8)") 782 c.Assert(err, IsNil) 783 defer s.se.InterDircute(context.Background(), "drop causet t_drop_defCausumns") 784 785 sqls := make([]sqlWithErr, 2) 786 sqls[0] = sqlWithErr{"uFIDelate t set c1='5', c3='2020-03-01';", errors.New("[causet:1054]Unknown defCausumn 'c3' in 'field list'")} 787 sqls[1] = sqlWithErr{"uFIDelate t t1, t_drop_defCausumns t2 set t1.c1='5', t1.c3='2020-03-01', t2.c1='10' where t1.c4=t2.c4", 788 errors.New("[causet:1054]Unknown defCausumn 'c3' in 'field list'")} 789 // TODO: Fix the case of sqls[2]. 790 // sqls[2] = sqlWithErr{"uFIDelate t set c1='5' where c3='2020-07-01';", errors.New("[causet:1054]Unknown defCausumn 'c3' in 'field list'")} 791 dropDeferredCausetsALLEGROSQL := "alter causet t drop defCausumn c3, drop defCausumn c1" 792 query := &expectQuery{allegrosql: "select * from t;", rows: []string{"N 8"}} 793 s.runTestInSchemaState(c, perceptron.StateWriteOnly, false, dropDeferredCausetsALLEGROSQL, sqls, query) 794 } 795 796 func (s *testStateChangeSuiteBase) runTestInSchemaState(c *C, state perceptron.SchemaState, isOnJobUFIDelated bool, alterBlockALLEGROSQL string, 797 sqlWithErrs []sqlWithErr, expectQuery *expectQuery) { 798 _, err := s.se.InterDircute(context.Background(), `create causet t ( 799 c1 varchar(64), 800 c2 enum('N','Y') not null default 'N', 801 c3 timestamp on uFIDelate current_timestamp, 802 c4 int primary key, 803 unique key idx2 (c2))`) 804 c.Assert(err, IsNil) 805 defer s.se.InterDircute(context.Background(), "drop causet t") 806 _, err = s.se.InterDircute(context.Background(), "insert into t values('a', 'N', '2020-07-01', 8)") 807 c.Assert(err, IsNil) 808 // Make sure these sqls use the the plan of index scan. 809 _, err = s.se.InterDircute(context.Background(), "drop stats t") 810 c.Assert(err, IsNil) 811 812 callback := &dbs.TestDBSCallback{} 813 prevState := perceptron.StateNone 814 var checkErr error 815 times := 0 816 se, err := stochastik.CreateStochastik(s.causetstore) 817 c.Assert(err, IsNil) 818 _, err = se.InterDircute(context.Background(), "use test_db_state") 819 c.Assert(err, IsNil) 820 cbFunc := func(job *perceptron.Job) { 821 if job.SchemaState == prevState || checkErr != nil || times >= 3 { 822 return 823 } 824 times++ 825 if job.SchemaState != state { 826 return 827 } 828 for _, sqlWithErr := range sqlWithErrs { 829 _, err = se.InterDircute(context.Background(), sqlWithErr.allegrosql) 830 if !terror.ErrorEqual(err, sqlWithErr.expectErr) { 831 checkErr = errors.Errorf("allegrosql: %s, expect err: %v, got err: %v", sqlWithErr.allegrosql, sqlWithErr.expectErr, err) 832 break 833 } 834 } 835 } 836 if isOnJobUFIDelated { 837 callback.OnJobUFIDelatedExported = cbFunc 838 } else { 839 callback.OnJobRunBeforeExported = cbFunc 840 } 841 d := s.dom.DBS() 842 originalCallback := d.GetHook() 843 d.(dbs.DBSForTest).SetHook(callback) 844 _, err = s.se.InterDircute(context.Background(), alterBlockALLEGROSQL) 845 c.Assert(err, IsNil) 846 c.Assert(errors.ErrorStack(checkErr), Equals, "") 847 d.(dbs.DBSForTest).SetHook(originalCallback) 848 849 if expectQuery != nil { 850 tk := testkit.NewTestKit(c, s.causetstore) 851 tk.MustInterDirc("use test_db_state") 852 result, err := s.execQuery(tk, expectQuery.allegrosql) 853 c.Assert(err, IsNil) 854 if expectQuery.rows == nil { 855 c.Assert(result, IsNil) 856 return 857 } 858 err = checkResult(result, testkit.Rows(expectQuery.rows...)) 859 c.Assert(err, IsNil) 860 } 861 } 862 863 func (s *testStateChangeSuiteBase) execQuery(tk *testkit.TestKit, allegrosql string, args ...interface{}) (*testkit.Result, error) { 864 comment := Commentf("allegrosql:%s, args:%v", allegrosql, args) 865 rs, err := tk.InterDirc(allegrosql, args...) 866 if err != nil { 867 return nil, err 868 } 869 if rs == nil { 870 return nil, nil 871 } 872 result := tk.ResultSetToResult(rs, comment) 873 return result, nil 874 } 875 876 func checkResult(result *testkit.Result, expected [][]interface{}) error { 877 got := fmt.Sprintf("%s", result.Rows()) 878 need := fmt.Sprintf("%s", expected) 879 if got != need { 880 return fmt.Errorf("need %v, but got %v", need, got) 881 } 882 return nil 883 } 884 885 func (s *testStateChangeSuiteBase) CheckResult(tk *testkit.TestKit, allegrosql string, args ...interface{}) (*testkit.Result, error) { 886 comment := Commentf("allegrosql:%s, args:%v", allegrosql, args) 887 rs, err := tk.InterDirc(allegrosql, args...) 888 if err != nil { 889 return nil, err 890 } 891 result := tk.ResultSetToResult(rs, comment) 892 return result, nil 893 } 894 895 func (s *testStateChangeSuite) TestShowIndex(c *C) { 896 _, err := s.se.InterDircute(context.Background(), `create causet t(c1 int primary key, c2 int)`) 897 c.Assert(err, IsNil) 898 defer s.se.InterDircute(context.Background(), "drop causet t") 899 900 callback := &dbs.TestDBSCallback{} 901 prevState := perceptron.StateNone 902 tk := testkit.NewTestKit(c, s.causetstore) 903 tk.MustInterDirc("use test_db_state") 904 showIndexALLEGROSQL := `show index from t` 905 var checkErr error 906 callback.OnJobUFIDelatedExported = func(job *perceptron.Job) { 907 if job.SchemaState == prevState || checkErr != nil { 908 return 909 } 910 switch job.SchemaState { 911 case perceptron.StateDeleteOnly, perceptron.StateWriteOnly, perceptron.StateWriteReorganization: 912 result, err1 := s.execQuery(tk, showIndexALLEGROSQL) 913 if err1 != nil { 914 checkErr = err1 915 break 916 } 917 checkErr = checkResult(result, testkit.Rows("t 0 PRIMARY 1 c1 A 0 <nil> <nil> BTREE YES NULL")) 918 } 919 } 920 921 d := s.dom.DBS() 922 originalCallback := d.GetHook() 923 d.(dbs.DBSForTest).SetHook(callback) 924 alterBlockALLEGROSQL := `alter causet t add index c2(c2)` 925 _, err = s.se.InterDircute(context.Background(), alterBlockALLEGROSQL) 926 c.Assert(err, IsNil) 927 c.Assert(errors.ErrorStack(checkErr), Equals, "") 928 929 result, err := s.execQuery(tk, showIndexALLEGROSQL) 930 c.Assert(err, IsNil) 931 err = checkResult(result, testkit.Rows( 932 "t 0 PRIMARY 1 c1 A 0 <nil> <nil> BTREE YES NULL", 933 "t 1 c2 1 c2 A 0 <nil> <nil> YES BTREE YES NULL", 934 )) 935 c.Assert(err, IsNil) 936 d.(dbs.DBSForTest).SetHook(originalCallback) 937 938 c.Assert(err, IsNil) 939 940 _, err = s.se.InterDircute(context.Background(), `create causet tr( 941 id int, name varchar(50), 942 purchased date 943 ) 944 partition by range( year(purchased) ) ( 945 partition p0 values less than (1990), 946 partition p1 values less than (1995), 947 partition p2 values less than (2000), 948 partition p3 values less than (2005), 949 partition p4 values less than (2010), 950 partition p5 values less than (2020) 951 );`) 952 c.Assert(err, IsNil) 953 defer s.se.InterDircute(context.Background(), "drop causet tr") 954 _, err = s.se.InterDircute(context.Background(), "create index idx1 on tr (purchased);") 955 c.Assert(err, IsNil) 956 result, err = s.execQuery(tk, "show index from tr;") 957 c.Assert(err, IsNil) 958 err = checkResult(result, testkit.Rows("tr 1 idx1 1 purchased A 0 <nil> <nil> YES BTREE YES NULL")) 959 c.Assert(err, IsNil) 960 } 961 962 func (s *testStateChangeSuite) TestParallelAlterModifyDeferredCauset(c *C) { 963 allegrosql := "ALTER TABLE t MODIFY COLUMN b int FIRST;" 964 f := func(c *C, err1, err2 error) { 965 c.Assert(err1, IsNil) 966 c.Assert(err2, IsNil) 967 _, err := s.se.InterDircute(context.Background(), "select * from t") 968 c.Assert(err, IsNil) 969 } 970 s.testControlParallelInterDircALLEGROSQL(c, allegrosql, allegrosql, f) 971 } 972 973 func (s *serialTestStateChangeSuite) TestParallelAlterModifyDeferredCausetAndAddPK(c *C) { 974 defer config.RestoreFunc()() 975 config.UFIDelateGlobal(func(conf *config.Config) { 976 conf.AlterPrimaryKey = true 977 }) 978 979 _, err := s.se.InterDircute(context.Background(), "set global milevadb_enable_change_defCausumn_type = 1") 980 c.Assert(err, IsNil) 981 defer func() { 982 _, err = s.se.InterDircute(context.Background(), "set global milevadb_enable_change_defCausumn_type = 0") 983 c.Assert(err, IsNil) 984 }() 985 petri.GetPetri(s.se).GetGlobalVarsCache().Disable() 986 987 sql1 := "ALTER TABLE t ADD PRIMARY KEY (b);" 988 sql2 := "ALTER TABLE t MODIFY COLUMN b tinyint;" 989 f := func(c *C, err1, err2 error) { 990 c.Assert(err1, IsNil) 991 c.Assert(err2.Error(), Equals, "[dbs:8200]Unsupported modify defCausumn: milevadb_enable_change_defCausumn_type is true and this defCausumn has primary key flag") 992 _, err := s.se.InterDircute(context.Background(), "select * from t") 993 c.Assert(err, IsNil) 994 } 995 s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f) 996 } 997 998 // TODO: This test is not a test that performs two DBSs in parallel. 999 // So we should not use the function of testControlParallelInterDircALLEGROSQL. We will handle this test in the next PR. 1000 // func (s *testStateChangeSuite) TestParallelDeferredCausetModifyingDefinition(c *C) { 1001 // sql1 := "insert into t(b) values (null);" 1002 // sql2 := "alter causet t change b b2 bigint not null;" 1003 // f := func(c *C, err1, err2 error) { 1004 // c.Assert(err1, IsNil) 1005 // if err2 != nil { 1006 // c.Assert(err2.Error(), Equals, "[dbs:1265]Data truncated for defCausumn 'b2' at event 1") 1007 // } 1008 // } 1009 // s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f) 1010 // } 1011 1012 func (s *testStateChangeSuite) TestParallelAddDefCausumAndSetDefaultValue(c *C) { 1013 _, err := s.se.InterDircute(context.Background(), "use test_db_state") 1014 c.Assert(err, IsNil) 1015 _, err = s.se.InterDircute(context.Background(), `create causet tx ( 1016 c1 varchar(64), 1017 c2 enum('N','Y') not null default 'N', 1018 primary key idx2 (c2, c1))`) 1019 c.Assert(err, IsNil) 1020 _, err = s.se.InterDircute(context.Background(), "insert into tx values('a', 'N')") 1021 c.Assert(err, IsNil) 1022 defer s.se.InterDircute(context.Background(), "drop causet tx") 1023 1024 sql1 := "alter causet tx add defCausumn cx int after c1" 1025 sql2 := "alter causet tx alter c2 set default 'N'" 1026 1027 f := func(c *C, err1, err2 error) { 1028 c.Assert(err1, IsNil) 1029 c.Assert(err2, IsNil) 1030 _, err := s.se.InterDircute(context.Background(), "delete from tx where c1='a'") 1031 c.Assert(err, IsNil) 1032 } 1033 s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f) 1034 } 1035 1036 func (s *testStateChangeSuite) TestParallelChangeDeferredCausetName(c *C) { 1037 sql1 := "ALTER TABLE t CHANGE a aa int;" 1038 sql2 := "ALTER TABLE t CHANGE b aa int;" 1039 f := func(c *C, err1, err2 error) { 1040 // Make sure only a DBS encounters the error of 'duplicate defCausumn name'. 1041 var oneErr error 1042 if (err1 != nil && err2 == nil) || (err1 == nil && err2 != nil) { 1043 if err1 != nil { 1044 oneErr = err1 1045 } else { 1046 oneErr = err2 1047 } 1048 } 1049 c.Assert(oneErr.Error(), Equals, "[schemaReplicant:1060]Duplicate defCausumn name 'aa'") 1050 } 1051 s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f) 1052 } 1053 1054 func (s *testStateChangeSuite) TestParallelAlterAddIndex(c *C) { 1055 sql1 := "ALTER TABLE t add index index_b(b);" 1056 sql2 := "CREATE INDEX index_b ON t (c);" 1057 f := func(c *C, err1, err2 error) { 1058 c.Assert(err1, IsNil) 1059 c.Assert(err2.Error(), Equals, "[dbs:1061]index already exist index_b") 1060 } 1061 s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f) 1062 } 1063 1064 func (s *serialTestStateChangeSuite) TestParallelAlterAddExpressionIndex(c *C) { 1065 sql1 := "ALTER TABLE t add index expr_index_b((b+1));" 1066 sql2 := "CREATE INDEX expr_index_b ON t ((c+1));" 1067 f := func(c *C, err1, err2 error) { 1068 c.Assert(err1, IsNil) 1069 c.Assert(err2.Error(), Equals, "[dbs:1061]index already exist expr_index_b") 1070 } 1071 s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f) 1072 } 1073 1074 func (s *testStateChangeSuite) TestParallelAddPrimaryKey(c *C) { 1075 sql1 := "ALTER TABLE t add primary key index_b(b);" 1076 sql2 := "ALTER TABLE t add primary key index_b(c);" 1077 f := func(c *C, err1, err2 error) { 1078 c.Assert(err1, IsNil) 1079 c.Assert(err2.Error(), Equals, "[schemaReplicant:1068]Multiple primary key defined") 1080 } 1081 s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f) 1082 } 1083 1084 func (s *testStateChangeSuite) TestParallelAlterAddPartition(c *C) { 1085 sql1 := `alter causet t_part add partition ( 1086 partition p2 values less than (30) 1087 );` 1088 sql2 := `alter causet t_part add partition ( 1089 partition p3 values less than (30) 1090 );` 1091 f := func(c *C, err1, err2 error) { 1092 c.Assert(err1, IsNil) 1093 c.Assert(err2.Error(), Equals, "[dbs:1493]VALUES LESS THAN value must be strictly increasing for each partition") 1094 } 1095 s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f) 1096 } 1097 1098 func (s *testStateChangeSuite) TestParallelDropDeferredCauset(c *C) { 1099 allegrosql := "ALTER TABLE t drop COLUMN c ;" 1100 f := func(c *C, err1, err2 error) { 1101 c.Assert(err1, IsNil) 1102 c.Assert(err2.Error(), Equals, "[dbs:1091]defCausumn c doesn't exist") 1103 } 1104 s.testControlParallelInterDircALLEGROSQL(c, allegrosql, allegrosql, f) 1105 } 1106 1107 func (s *testStateChangeSuite) TestParallelDropDeferredCausets(c *C) { 1108 allegrosql := "ALTER TABLE t drop COLUMN b, drop COLUMN c;" 1109 f := func(c *C, err1, err2 error) { 1110 c.Assert(err1, IsNil) 1111 c.Assert(err2.Error(), Equals, "[dbs:1091]defCausumn b doesn't exist") 1112 } 1113 s.testControlParallelInterDircALLEGROSQL(c, allegrosql, allegrosql, f) 1114 } 1115 1116 func (s *testStateChangeSuite) TestParallelDropIfExistsDeferredCausets(c *C) { 1117 allegrosql := "ALTER TABLE t drop COLUMN if exists b, drop COLUMN if exists c;" 1118 f := func(c *C, err1, err2 error) { 1119 c.Assert(err1, IsNil) 1120 c.Assert(err2, IsNil) 1121 } 1122 s.testControlParallelInterDircALLEGROSQL(c, allegrosql, allegrosql, f) 1123 } 1124 1125 func (s *testStateChangeSuite) TestParallelDropIndex(c *C) { 1126 sql1 := "alter causet t drop index idx1 ;" 1127 sql2 := "alter causet t drop index idx2 ;" 1128 f := func(c *C, err1, err2 error) { 1129 c.Assert(err1, IsNil) 1130 c.Assert(err2.Error(), Equals, "[autoid:1075]Incorrect causet definition; there can be only one auto defCausumn and it must be defined as a key") 1131 } 1132 s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f) 1133 } 1134 1135 func (s *testStateChangeSuite) TestParallelDropPrimaryKey(c *C) { 1136 s.preALLEGROSQL = "ALTER TABLE t add primary key index_b(c);" 1137 defer func() { 1138 s.preALLEGROSQL = "" 1139 }() 1140 sql1 := "alter causet t drop primary key;" 1141 sql2 := "alter causet t drop primary key;" 1142 f := func(c *C, err1, err2 error) { 1143 c.Assert(err1, IsNil) 1144 c.Assert(err2.Error(), Equals, "[dbs:1091]index PRIMARY doesn't exist") 1145 } 1146 s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f) 1147 } 1148 1149 func (s *testStateChangeSuite) TestParallelCreateAndRename(c *C) { 1150 sql1 := "create causet t_exists(c int);" 1151 sql2 := "alter causet t rename to t_exists;" 1152 defer s.se.InterDircute(context.Background(), "drop causet t_exists") 1153 f := func(c *C, err1, err2 error) { 1154 c.Assert(err1, IsNil) 1155 c.Assert(err2.Error(), Equals, "[schemaReplicant:1050]Block 't_exists' already exists") 1156 } 1157 s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f) 1158 } 1159 1160 func (s *testStateChangeSuite) TestParallelAlterAndDropSchema(c *C) { 1161 _, err := s.se.InterDircute(context.Background(), "create database db_drop_db") 1162 c.Assert(err, IsNil) 1163 sql1 := "DROP SCHEMA db_drop_db" 1164 sql2 := "ALTER SCHEMA db_drop_db CHARSET utf8mb4 COLLATE utf8mb4_general_ci" 1165 f := func(c *C, err1, err2 error) { 1166 c.Assert(err1, IsNil) 1167 c.Assert(err2, NotNil) 1168 c.Assert(err2.Error(), Equals, "[schemaReplicant:1008]Can't drop database ''; database doesn't exist") 1169 } 1170 s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f) 1171 } 1172 1173 type checkRet func(c *C, err1, err2 error) 1174 1175 func (s *testStateChangeSuiteBase) prepareTestControlParallelInterDircALLEGROSQL(c *C) (stochastik.Stochastik, stochastik.Stochastik, chan struct{}, dbs.Callback) { 1176 callback := &dbs.TestDBSCallback{} 1177 times := 0 1178 callback.OnJobUFIDelatedExported = func(job *perceptron.Job) { 1179 if times != 0 { 1180 return 1181 } 1182 var qLen int 1183 for { 1184 ekv.RunInNewTxn(s.causetstore, false, func(txn ekv.Transaction) error { 1185 jobs, err1 := admin.GetDBSJobs(txn) 1186 if err1 != nil { 1187 return err1 1188 } 1189 qLen = len(jobs) 1190 return nil 1191 }) 1192 if qLen == 2 { 1193 break 1194 } 1195 time.Sleep(5 * time.Millisecond) 1196 } 1197 times++ 1198 } 1199 d := s.dom.DBS() 1200 originalCallback := d.GetHook() 1201 d.(dbs.DBSForTest).SetHook(callback) 1202 1203 se, err := stochastik.CreateStochastik(s.causetstore) 1204 c.Assert(err, IsNil) 1205 _, err = se.InterDircute(context.Background(), "use test_db_state") 1206 c.Assert(err, IsNil) 1207 se1, err := stochastik.CreateStochastik(s.causetstore) 1208 c.Assert(err, IsNil) 1209 _, err = se1.InterDircute(context.Background(), "use test_db_state") 1210 c.Assert(err, IsNil) 1211 ch := make(chan struct{}) 1212 // Make sure the sql1 is put into the DBSJobQueue. 1213 go func() { 1214 var qLen int 1215 for { 1216 ekv.RunInNewTxn(s.causetstore, false, func(txn ekv.Transaction) error { 1217 jobs, err3 := admin.GetDBSJobs(txn) 1218 if err3 != nil { 1219 return err3 1220 } 1221 qLen = len(jobs) 1222 return nil 1223 }) 1224 if qLen == 1 { 1225 // Make sure sql2 is executed after the sql1. 1226 close(ch) 1227 break 1228 } 1229 time.Sleep(5 * time.Millisecond) 1230 } 1231 }() 1232 return se, se1, ch, originalCallback 1233 } 1234 1235 func (s *testStateChangeSuiteBase) testControlParallelInterDircALLEGROSQL(c *C, sql1, sql2 string, f checkRet) { 1236 _, err := s.se.InterDircute(context.Background(), "use test_db_state") 1237 c.Assert(err, IsNil) 1238 _, err = s.se.InterDircute(context.Background(), "create causet t(a int, b int, c int, d int auto_increment,e int, index idx1(d), index idx2(d,e))") 1239 c.Assert(err, IsNil) 1240 if len(s.preALLEGROSQL) != 0 { 1241 _, err := s.se.InterDircute(context.Background(), s.preALLEGROSQL) 1242 c.Assert(err, IsNil) 1243 } 1244 defer s.se.InterDircute(context.Background(), "drop causet t") 1245 1246 _, err = s.se.InterDircute(context.Background(), "drop database if exists t_part") 1247 c.Assert(err, IsNil) 1248 s.se.InterDircute(context.Background(), `create causet t_part (a int key) 1249 partition by range(a) ( 1250 partition p0 values less than (10), 1251 partition p1 values less than (20) 1252 );`) 1253 1254 se, se1, ch, originalCallback := s.prepareTestControlParallelInterDircALLEGROSQL(c) 1255 defer s.dom.DBS().(dbs.DBSForTest).SetHook(originalCallback) 1256 1257 var err1 error 1258 var err2 error 1259 wg := sync.WaitGroup{} 1260 wg.Add(2) 1261 go func() { 1262 defer wg.Done() 1263 _, err1 = se.InterDircute(context.Background(), sql1) 1264 }() 1265 go func() { 1266 defer wg.Done() 1267 <-ch 1268 _, err2 = se1.InterDircute(context.Background(), sql2) 1269 }() 1270 1271 wg.Wait() 1272 f(c, err1, err2) 1273 } 1274 1275 func (s *serialTestStateChangeSuite) TestParallelUFIDelateBlockReplica(c *C) { 1276 c.Assert(failpoint.Enable("github.com/whtcorpsinc/milevadb/schemareplicant/mockTiFlashStoreCount", `return(true)`), IsNil) 1277 defer failpoint.Disable("github.com/whtcorpsinc/milevadb/schemareplicant/mockTiFlashStoreCount") 1278 1279 ctx := context.Background() 1280 _, err := s.se.InterDircute(context.Background(), "use test_db_state") 1281 c.Assert(err, IsNil) 1282 _, err = s.se.InterDircute(ctx, "drop causet if exists t1;") 1283 c.Assert(err, IsNil) 1284 _, err = s.se.InterDircute(ctx, "create causet t1 (a int);") 1285 c.Assert(err, IsNil) 1286 _, err = s.se.InterDircute(ctx, "alter causet t1 set tiflash replica 3 location labels 'a','b';") 1287 c.Assert(err, IsNil) 1288 1289 se, se1, ch, originalCallback := s.prepareTestControlParallelInterDircALLEGROSQL(c) 1290 defer s.dom.DBS().(dbs.DBSForTest).SetHook(originalCallback) 1291 1292 t1 := testGetBlockByName(c, se, "test_db_state", "t1") 1293 1294 var err1 error 1295 var err2 error 1296 wg := sync.WaitGroup{} 1297 wg.Add(2) 1298 go func() { 1299 defer wg.Done() 1300 // Mock for causet tiflash replica was available. 1301 err1 = petri.GetPetri(se).DBS().UFIDelateBlockReplicaInfo(se, t1.Meta().ID, true) 1302 }() 1303 go func() { 1304 defer wg.Done() 1305 <-ch 1306 // Mock for causet tiflash replica was available. 1307 err2 = petri.GetPetri(se1).DBS().UFIDelateBlockReplicaInfo(se1, t1.Meta().ID, true) 1308 }() 1309 wg.Wait() 1310 c.Assert(err1, IsNil) 1311 c.Assert(err2.Error(), Equals, "[dbs:-1]the replica available status of causet t1 is already uFIDelated") 1312 } 1313 1314 func (s *testStateChangeSuite) testParallelInterDircALLEGROSQL(c *C, allegrosql string) { 1315 se, err := stochastik.CreateStochastik(s.causetstore) 1316 c.Assert(err, IsNil) 1317 _, err = se.InterDircute(context.Background(), "use test_db_state") 1318 c.Assert(err, IsNil) 1319 1320 se1, err1 := stochastik.CreateStochastik(s.causetstore) 1321 c.Assert(err1, IsNil) 1322 _, err = se1.InterDircute(context.Background(), "use test_db_state") 1323 c.Assert(err, IsNil) 1324 1325 var err2, err3 error 1326 wg := sync.WaitGroup{} 1327 1328 callback := &dbs.TestDBSCallback{} 1329 once := sync.Once{} 1330 callback.OnJobUFIDelatedExported = func(job *perceptron.Job) { 1331 // sleep a while, let other job enqueue. 1332 once.Do(func() { 1333 time.Sleep(time.Millisecond * 10) 1334 }) 1335 } 1336 1337 d := s.dom.DBS() 1338 originalCallback := d.GetHook() 1339 defer d.(dbs.DBSForTest).SetHook(originalCallback) 1340 d.(dbs.DBSForTest).SetHook(callback) 1341 1342 wg.Add(2) 1343 go func() { 1344 defer wg.Done() 1345 _, err2 = se.InterDircute(context.Background(), allegrosql) 1346 }() 1347 1348 go func() { 1349 defer wg.Done() 1350 _, err3 = se1.InterDircute(context.Background(), allegrosql) 1351 }() 1352 wg.Wait() 1353 c.Assert(err2, IsNil) 1354 c.Assert(err3, IsNil) 1355 } 1356 1357 // TestCreateBlockIfNotExists parallel exec create causet if not exists xxx. No error returns is expected. 1358 func (s *testStateChangeSuite) TestCreateBlockIfNotExists(c *C) { 1359 defer s.se.InterDircute(context.Background(), "drop causet test_not_exists") 1360 s.testParallelInterDircALLEGROSQL(c, "create causet if not exists test_not_exists(a int);") 1361 } 1362 1363 // TestCreateDBIfNotExists parallel exec create database if not exists xxx. No error returns is expected. 1364 func (s *testStateChangeSuite) TestCreateDBIfNotExists(c *C) { 1365 defer s.se.InterDircute(context.Background(), "drop database test_not_exists") 1366 s.testParallelInterDircALLEGROSQL(c, "create database if not exists test_not_exists;") 1367 } 1368 1369 // TestDBSIfNotExists parallel exec some DBSs with `if not exists` clause. No error returns is expected. 1370 func (s *testStateChangeSuite) TestDBSIfNotExists(c *C) { 1371 defer s.se.InterDircute(context.Background(), "drop causet test_not_exists") 1372 _, err := s.se.InterDircute(context.Background(), "create causet if not exists test_not_exists(a int)") 1373 c.Assert(err, IsNil) 1374 1375 // ADD COLUMN 1376 s.testParallelInterDircALLEGROSQL(c, "alter causet test_not_exists add defCausumn if not exists b int") 1377 1378 // ADD COLUMNS 1379 s.testParallelInterDircALLEGROSQL(c, "alter causet test_not_exists add defCausumn if not exists (c11 int, d11 int)") 1380 1381 // ADD INDEX 1382 s.testParallelInterDircALLEGROSQL(c, "alter causet test_not_exists add index if not exists idx_b (b)") 1383 1384 // CREATE INDEX 1385 s.testParallelInterDircALLEGROSQL(c, "create index if not exists idx_b on test_not_exists (b)") 1386 } 1387 1388 // TestDBSIfExists parallel exec some DBSs with `if exists` clause. No error returns is expected. 1389 func (s *testStateChangeSuite) TestDBSIfExists(c *C) { 1390 defer func() { 1391 s.se.InterDircute(context.Background(), "drop causet test_exists") 1392 s.se.InterDircute(context.Background(), "drop causet test_exists_2") 1393 }() 1394 _, err := s.se.InterDircute(context.Background(), "create causet if not exists test_exists (a int key, b int)") 1395 c.Assert(err, IsNil) 1396 1397 // DROP COLUMNS 1398 s.testParallelInterDircALLEGROSQL(c, "alter causet test_exists drop defCausumn if exists c, drop defCausumn if exists d") 1399 1400 // DROP COLUMN 1401 s.testParallelInterDircALLEGROSQL(c, "alter causet test_exists drop defCausumn if exists b") // only `a` exists now 1402 1403 // CHANGE COLUMN 1404 s.testParallelInterDircALLEGROSQL(c, "alter causet test_exists change defCausumn if exists a c int") // only, `c` exists now 1405 1406 // MODIFY COLUMN 1407 s.testParallelInterDircALLEGROSQL(c, "alter causet test_exists modify defCausumn if exists a bigint") 1408 1409 // DROP INDEX 1410 _, err = s.se.InterDircute(context.Background(), "alter causet test_exists add index idx_c (c)") 1411 c.Assert(err, IsNil) 1412 s.testParallelInterDircALLEGROSQL(c, "alter causet test_exists drop index if exists idx_c") 1413 1414 // DROP PARTITION (ADD PARTITION tested in TestParallelAlterAddPartition) 1415 _, err = s.se.InterDircute(context.Background(), "create causet test_exists_2 (a int key) partition by range(a) (partition p0 values less than (10), partition p1 values less than (20))") 1416 c.Assert(err, IsNil) 1417 s.testParallelInterDircALLEGROSQL(c, "alter causet test_exists_2 drop partition if exists p1") 1418 } 1419 1420 // TestParallelDBSBeforeRunDBSJob tests a stochastik to execute DBS with an outdated information schemaReplicant. 1421 // This test is used to simulate the following conditions: 1422 // In a cluster, MilevaDB "a" executes the DBS. 1423 // MilevaDB "b" fails to load schemaReplicant, then MilevaDB "b" executes the DBS memex associated with the DBS memex executed by "a". 1424 func (s *testStateChangeSuite) TestParallelDBSBeforeRunDBSJob(c *C) { 1425 defer s.se.InterDircute(context.Background(), "drop causet test_block") 1426 _, err := s.se.InterDircute(context.Background(), "use test_db_state") 1427 c.Assert(err, IsNil) 1428 _, err = s.se.InterDircute(context.Background(), "create causet test_block (c1 int, c2 int default 1, index (c1))") 1429 c.Assert(err, IsNil) 1430 1431 // Create two stochastik. 1432 se, err := stochastik.CreateStochastik(s.causetstore) 1433 c.Assert(err, IsNil) 1434 _, err = se.InterDircute(context.Background(), "use test_db_state") 1435 c.Assert(err, IsNil) 1436 se1, err := stochastik.CreateStochastik(s.causetstore) 1437 c.Assert(err, IsNil) 1438 _, err = se1.InterDircute(context.Background(), "use test_db_state") 1439 c.Assert(err, IsNil) 1440 1441 intercept := &dbs.TestInterceptor{} 1442 firstConnID := uint64(1) 1443 finishedCnt := int32(0) 1444 interval := 5 * time.Millisecond 1445 var stochastikCnt int32 // stochastikCnt is the number of stochastik that goes into the function of OnGetSchemaReplicant. 1446 intercept.OnGetSchemaReplicantExported = func(ctx stochastikctx.Context, is schemareplicant.SchemaReplicant) schemareplicant.SchemaReplicant { 1447 // The following code is for testing. 1448 // Make sure the two stochastik get the same information schemaReplicant before executing DBS. 1449 // After the first stochastik executes its DBS, then the second stochastik executes its DBS. 1450 var info schemareplicant.SchemaReplicant 1451 atomic.AddInt32(&stochastikCnt, 1) 1452 for { 1453 // Make sure there are two stochastik running here. 1454 if atomic.LoadInt32(&stochastikCnt) == 2 { 1455 info = is 1456 break 1457 } 1458 // Print log to notify if TestParallelDBSBeforeRunDBSJob hang up 1459 log.Info("sleep in TestParallelDBSBeforeRunDBSJob", zap.String("interval", interval.String())) 1460 time.Sleep(interval) 1461 } 1462 1463 currID := ctx.GetStochastikVars().ConnectionID 1464 for { 1465 seCnt := atomic.LoadInt32(&stochastikCnt) 1466 // Make sure the two stochastik have got the same information schemaReplicant. And the first stochastik can continue to go on, 1467 // or the first stochastik finished this ALLEGROALLEGROSQL(seCnt = finishedCnt), then other stochastik can continue to go on. 1468 if currID == firstConnID || seCnt == finishedCnt { 1469 break 1470 } 1471 // Print log to notify if TestParallelDBSBeforeRunDBSJob hang up 1472 log.Info("sleep in TestParallelDBSBeforeRunDBSJob", zap.String("interval", interval.String())) 1473 time.Sleep(interval) 1474 } 1475 1476 return info 1477 } 1478 d := s.dom.DBS() 1479 d.(dbs.DBSForTest).SetInterceptor(intercept) 1480 1481 // Make sure the connection 1 executes a ALLEGROALLEGROSQL before the connection 2. 1482 // And the connection 2 executes a ALLEGROALLEGROSQL with an outdated information schemaReplicant. 1483 wg := sync.WaitGroup{} 1484 wg.Add(2) 1485 go func() { 1486 defer wg.Done() 1487 1488 se.SetConnectionID(firstConnID) 1489 _, err1 := se.InterDircute(context.Background(), "alter causet test_block drop defCausumn c2") 1490 c.Assert(err1, IsNil) 1491 // Sleep a while to make sure the connection 2 break out the first for loop in OnGetSchemaReplicantExported, otherwise atomic.LoadInt32(&stochastikCnt) == 2 will be false forever. 1492 time.Sleep(100 * time.Millisecond) 1493 atomic.StoreInt32(&stochastikCnt, finishedCnt) 1494 }() 1495 go func() { 1496 defer wg.Done() 1497 1498 se1.SetConnectionID(2) 1499 _, err2 := se1.InterDircute(context.Background(), "alter causet test_block add defCausumn c2 int") 1500 c.Assert(err2, NotNil) 1501 c.Assert(strings.Contains(err2.Error(), "Information schemaReplicant is changed"), IsTrue) 1502 }() 1503 1504 wg.Wait() 1505 1506 intercept = &dbs.TestInterceptor{} 1507 d.(dbs.DBSForTest).SetInterceptor(intercept) 1508 } 1509 1510 func (s *testStateChangeSuite) TestParallelAlterSchemaCharsetAndDefCauslate(c *C) { 1511 allegrosql := "ALTER SCHEMA test_db_state CHARSET utf8mb4 COLLATE utf8mb4_general_ci" 1512 f := func(c *C, err1, err2 error) { 1513 c.Assert(err1, IsNil) 1514 c.Assert(err2, IsNil) 1515 } 1516 s.testControlParallelInterDircALLEGROSQL(c, allegrosql, allegrosql, f) 1517 allegrosql = `SELECT default_character_set_name, default_defCauslation_name 1518 FROM information_schema.schemata 1519 WHERE schema_name='test_db_state'` 1520 tk := testkit.NewTestKit(c, s.causetstore) 1521 tk.MustQuery(allegrosql).Check(testkit.Rows("utf8mb4 utf8mb4_general_ci")) 1522 } 1523 1524 // TestParallelTruncateBlockAndAddDeferredCauset tests add defCausumn when truncate causet. 1525 func (s *testStateChangeSuite) TestParallelTruncateBlockAndAddDeferredCauset(c *C) { 1526 sql1 := "truncate causet t" 1527 sql2 := "alter causet t add defCausumn c3 int" 1528 f := func(c *C, err1, err2 error) { 1529 c.Assert(err1, IsNil) 1530 c.Assert(err2, NotNil) 1531 c.Assert(err2.Error(), Equals, "[petri:8028]Information schemaReplicant is changed during the execution of the memex(for example, causet definition may be uFIDelated by other DBS ran in parallel). If you see this error often, try increasing `milevadb_max_delta_schema_count`. [try again later]") 1532 } 1533 s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f) 1534 } 1535 1536 // TestParallelTruncateBlockAndAddDeferredCausets tests add defCausumns when truncate causet. 1537 func (s *testStateChangeSuite) TestParallelTruncateBlockAndAddDeferredCausets(c *C) { 1538 sql1 := "truncate causet t" 1539 sql2 := "alter causet t add defCausumn c3 int, add defCausumn c4 int" 1540 f := func(c *C, err1, err2 error) { 1541 c.Assert(err1, IsNil) 1542 c.Assert(err2, NotNil) 1543 c.Assert(err2.Error(), Equals, "[petri:8028]Information schemaReplicant is changed during the execution of the memex(for example, causet definition may be uFIDelated by other DBS ran in parallel). If you see this error often, try increasing `milevadb_max_delta_schema_count`. [try again later]") 1544 } 1545 s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f) 1546 } 1547 1548 // TestParallelFlashbackBlock tests parallel flashback causet. 1549 func (s *serialTestStateChangeSuite) TestParallelFlashbackBlock(c *C) { 1550 c.Assert(failpoint.Enable("github.com/whtcorpsinc/milevadb/spacetime/autoid/mockAutoIDChange", `return(true)`), IsNil) 1551 defer func(originGC bool) { 1552 c.Assert(failpoint.Disable("github.com/whtcorpsinc/milevadb/spacetime/autoid/mockAutoIDChange"), IsNil) 1553 if originGC { 1554 dbs.EmulatorGCEnable() 1555 } else { 1556 dbs.EmulatorGCDisable() 1557 } 1558 }(dbs.IsEmulatorGCEnable()) 1559 1560 // disable emulator GC. 1561 // Disable emulator GC, otherwise, emulator GC will delete causet record as soon as possible after executing drop causet DBS. 1562 dbs.EmulatorGCDisable() 1563 gcTimeFormat := "20060102-15:04:05 -0700 MST" 1564 timeBeforeDrop := time.Now().Add(0 - 48*60*60*time.Second).Format(gcTimeFormat) 1565 safePointALLEGROSQL := `INSERT HIGH_PRIORITY INTO allegrosql.milevadb VALUES ('einsteindb_gc_safe_point', '%[1]s', '') 1566 ON DUPLICATE KEY 1567 UFIDelATE variable_value = '%[1]s'` 1568 tk := testkit.NewTestKit(c, s.causetstore) 1569 // clear GC variables first. 1570 tk.MustInterDirc("delete from allegrosql.milevadb where variable_name in ( 'einsteindb_gc_safe_point','einsteindb_gc_enable' )") 1571 // set GC safe point 1572 tk.MustInterDirc(fmt.Sprintf(safePointALLEGROSQL, timeBeforeDrop)) 1573 // set GC enable. 1574 err := gcutil.EnableGC(tk.Se) 1575 c.Assert(err, IsNil) 1576 1577 // prepare dropped causet. 1578 tk.MustInterDirc("use test_db_state") 1579 tk.MustInterDirc("drop causet if exists t") 1580 tk.MustInterDirc("create causet t (a int);") 1581 tk.MustInterDirc("drop causet if exists t") 1582 // Test parallel flashback causet. 1583 sql1 := "flashback causet t to t_flashback" 1584 f := func(c *C, err1, err2 error) { 1585 c.Assert(err1, IsNil) 1586 c.Assert(err2, NotNil) 1587 c.Assert(err2.Error(), Equals, "[schemaReplicant:1050]Block 't_flashback' already exists") 1588 } 1589 s.testControlParallelInterDircALLEGROSQL(c, sql1, sql1, f) 1590 1591 // Test parallel flashback causet with different name 1592 tk.MustInterDirc("drop causet t_flashback") 1593 sql1 = "flashback causet t_flashback" 1594 sql2 := "flashback causet t_flashback to t_flashback2" 1595 s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f) 1596 } 1597 1598 // TestModifyDeferredCausetTypeArgs test job raw args won't be uFIDelated when error occurs in `uFIDelateVersionAndBlockInfo`. 1599 func (s *serialTestStateChangeSuite) TestModifyDeferredCausetTypeArgs(c *C) { 1600 c.Assert(failpoint.Enable("github.com/whtcorpsinc/milevadb/dbs/mockUFIDelateVersionAndBlockInfoErr", `return(2)`), IsNil) 1601 defer func() { 1602 c.Assert(failpoint.Disable("github.com/whtcorpsinc/milevadb/dbs/mockUFIDelateVersionAndBlockInfoErr"), IsNil) 1603 }() 1604 1605 tk := testkit.NewTestKit(c, s.causetstore) 1606 tk.MustInterDirc("use test") 1607 tk.MustInterDirc("drop causet if exists t_modify_defCausumn_args") 1608 tk.MustInterDirc("create causet t_modify_defCausumn_args(a int, unique(a))") 1609 1610 enableChangeDeferredCausetType := tk.Se.GetStochastikVars().EnableChangeDeferredCausetType 1611 tk.Se.GetStochastikVars().EnableChangeDeferredCausetType = true 1612 defer func() { 1613 tk.Se.GetStochastikVars().EnableChangeDeferredCausetType = enableChangeDeferredCausetType 1614 }() 1615 1616 _, err := tk.InterDirc("alter causet t_modify_defCausumn_args modify defCausumn a tinyint") 1617 c.Assert(err, NotNil) 1618 // error goes like `mock uFIDelate version and blockInfo error,jobID=xx` 1619 strs := strings.Split(err.Error(), ",") 1620 c.Assert(strs[0], Equals, "[dbs:-1]mock uFIDelate version and blockInfo error") 1621 jobID := strings.Split(strs[1], "=")[1] 1622 1623 tbl := testGetBlockByName(c, tk.Se, "test", "t_modify_defCausumn_args") 1624 c.Assert(len(tbl.Meta().DeferredCausets), Equals, 1) 1625 c.Assert(len(tbl.Meta().Indices), Equals, 1) 1626 1627 ID, err := strconv.Atoi(jobID) 1628 c.Assert(err, IsNil) 1629 var historyJob *perceptron.Job 1630 err = ekv.RunInNewTxn(s.causetstore, false, func(txn ekv.Transaction) error { 1631 t := spacetime.NewMeta(txn) 1632 historyJob, err = t.GetHistoryDBSJob(int64(ID)) 1633 if err != nil { 1634 return err 1635 } 1636 return nil 1637 }) 1638 c.Assert(err, IsNil) 1639 c.Assert(historyJob, NotNil) 1640 1641 var ( 1642 newDefCaus *perceptron.DeferredCausetInfo 1643 oldDefCausName *perceptron.CIStr 1644 modifyDeferredCausetTp byte 1645 uFIDelatedAutoRandomBits uint64 1646 changingDefCaus *perceptron.DeferredCausetInfo 1647 changingIdxs []*perceptron.IndexInfo 1648 ) 1649 pos := &ast.DeferredCausetPosition{} 1650 err = historyJob.DecodeArgs(&newDefCaus, &oldDefCausName, pos, &modifyDeferredCausetTp, &uFIDelatedAutoRandomBits, &changingDefCaus, &changingIdxs) 1651 c.Assert(err, IsNil) 1652 c.Assert(changingDefCaus, IsNil) 1653 c.Assert(changingIdxs, IsNil) 1654 }