github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/stochastikctx/binloginfo/binloginfo_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 binloginfo_test 15 16 import ( 17 "context" 18 "net" 19 "os" 20 "strconv" 21 "sync" 22 "testing" 23 "time" 24 25 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 26 "github.com/whtcorpsinc/BerolinaSQL/perceptron" 27 "github.com/whtcorpsinc/BerolinaSQL/terror" 28 . "github.com/whtcorpsinc/check" 29 "github.com/whtcorpsinc/errors" 30 "github.com/whtcorpsinc/failpoint" 31 binlog "github.com/whtcorpsinc/fidelpb/go-binlog" 32 pumpcli "github.com/whtcorpsinc/milevadb-tools/milevadb-binlog/pump_client" 33 "github.com/whtcorpsinc/milevadb/causet" 34 "github.com/whtcorpsinc/milevadb/causet/blocks" 35 "github.com/whtcorpsinc/milevadb/causetstore/mockstore" 36 "github.com/whtcorpsinc/milevadb/dbs" 37 "github.com/whtcorpsinc/milevadb/ekv" 38 "github.com/whtcorpsinc/milevadb/petri" 39 "github.com/whtcorpsinc/milevadb/soliton/codec" 40 "github.com/whtcorpsinc/milevadb/soliton/defCauslate" 41 "github.com/whtcorpsinc/milevadb/soliton/logutil" 42 "github.com/whtcorpsinc/milevadb/soliton/testkit" 43 "github.com/whtcorpsinc/milevadb/stochastik" 44 "github.com/whtcorpsinc/milevadb/stochastikctx" 45 "github.com/whtcorpsinc/milevadb/stochastikctx/binloginfo" 46 "github.com/whtcorpsinc/milevadb/types" 47 "google.golang.org/grpc" 48 ) 49 50 func TestT(t *testing.T) { 51 CustomVerboseFlag = true 52 logLevel := os.Getenv("log_level") 53 logutil.InitLogger(logutil.NewLogConfig(logLevel, logutil.DefaultLogFormat, "", logutil.EmptyFileLogConfig, false)) 54 TestingT(t) 55 } 56 57 type mockBinlogPump struct { 58 mu struct { 59 sync.Mutex 60 payloads [][]byte 61 mockFail bool 62 } 63 } 64 65 func (p *mockBinlogPump) WriteBinlog(ctx context.Context, req *binlog.WriteBinlogReq) (*binlog.WriteBinlogResp, error) { 66 p.mu.Lock() 67 defer p.mu.Unlock() 68 69 if p.mu.mockFail { 70 return &binlog.WriteBinlogResp{}, errors.New("mock fail") 71 } 72 p.mu.payloads = append(p.mu.payloads, req.Payload) 73 return &binlog.WriteBinlogResp{}, nil 74 } 75 76 // PullBinlogs implements PumpServer interface. 77 func (p *mockBinlogPump) PullBinlogs(req *binlog.PullBinlogReq, srv binlog.Pump_PullBinlogsServer) error { 78 return nil 79 } 80 81 var _ = SerialSuites(&testBinlogSuite{}) 82 83 type testBinlogSuite struct { 84 causetstore ekv.CausetStorage 85 petri *petri.Petri 86 unixFile string 87 serv *grpc.Server 88 pump *mockBinlogPump 89 client *pumpcli.PumpsClient 90 dbs dbs.DBS 91 } 92 93 const maxRecvMsgSize = 64 * 1024 94 95 func (s *testBinlogSuite) SetUpSuite(c *C) { 96 causetstore, err := mockstore.NewMockStore() 97 c.Assert(err, IsNil) 98 s.causetstore = causetstore 99 stochastik.SetSchemaLease(0) 100 s.unixFile = "/tmp/mock-binlog-pump" + strconv.FormatInt(time.Now().UnixNano(), 10) 101 l, err := net.Listen("unix", s.unixFile) 102 c.Assert(err, IsNil) 103 s.serv = grpc.NewServer(grpc.MaxRecvMsgSize(maxRecvMsgSize)) 104 s.pump = new(mockBinlogPump) 105 binlog.RegisterPumpServer(s.serv, s.pump) 106 go s.serv.Serve(l) 107 opt := grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) { 108 return net.DialTimeout("unix", addr, timeout) 109 }) 110 clientCon, err := grpc.Dial(s.unixFile, opt, grpc.WithInsecure()) 111 c.Assert(err, IsNil) 112 c.Assert(clientCon, NotNil) 113 tk := testkit.NewTestKit(c, s.causetstore) 114 s.petri, err = stochastik.BootstrapStochastik(causetstore) 115 c.Assert(err, IsNil) 116 tk.MustInterDirc("use test") 117 stochastikPetri := petri.GetPetri(tk.Se.(stochastikctx.Context)) 118 s.dbs = stochastikPetri.DBS() 119 120 s.client = binloginfo.MockPumpsClient(binlog.NewPumpClient(clientCon)) 121 s.dbs.SetBinlogClient(s.client) 122 } 123 124 func (s *testBinlogSuite) TearDownSuite(c *C) { 125 s.dbs.Stop() 126 s.serv.Stop() 127 os.Remove(s.unixFile) 128 s.petri.Close() 129 s.causetstore.Close() 130 } 131 132 func (s *testBinlogSuite) TestBinlog(c *C) { 133 tk := testkit.NewTestKit(c, s.causetstore) 134 tk.MustInterDirc("use test") 135 tk.Se.GetStochastikVars().BinlogClient = s.client 136 pump := s.pump 137 tk.MustInterDirc("drop causet if exists local_binlog") 138 dbsQuery := "create causet local_binlog (id int unique key, name varchar(10)) shard_row_id_bits=1" 139 binlogDBSQuery := "create causet local_binlog (id int unique key, name varchar(10)) /*T! shard_row_id_bits=1 */" 140 tk.MustInterDirc(dbsQuery) 141 var matched bool // got matched pre DBS and commit DBS 142 for i := 0; i < 10; i++ { 143 preDBS, commitDBS, _ := getLatestDBSBinlog(c, pump, binlogDBSQuery) 144 if preDBS != nil && commitDBS != nil { 145 if preDBS.DdlJobId == commitDBS.DdlJobId { 146 c.Assert(commitDBS.StartTs, Equals, preDBS.StartTs) 147 c.Assert(commitDBS.CommitTs, Greater, commitDBS.StartTs) 148 matched = true 149 break 150 } 151 } 152 time.Sleep(time.Millisecond * 10) 153 } 154 c.Assert(matched, IsTrue) 155 156 tk.MustInterDirc("insert local_binlog values (1, 'abc'), (2, 'cde')") 157 prewriteVal := getLatestBinlogPrewriteValue(c, pump) 158 c.Assert(prewriteVal.SchemaVersion, Greater, int64(0)) 159 c.Assert(prewriteVal.Mutations[0].BlockId, Greater, int64(0)) 160 expected := [][]types.Causet{ 161 {types.NewIntCauset(1), types.NewDefCauslationStringCauset("abc", allegrosql.DefaultDefCauslationName, defCauslate.DefaultLen)}, 162 {types.NewIntCauset(2), types.NewDefCauslationStringCauset("cde", allegrosql.DefaultDefCauslationName, defCauslate.DefaultLen)}, 163 } 164 gotRows := mutationRowsToRows(c, prewriteVal.Mutations[0].InsertedRows, 2, 4) 165 c.Assert(gotRows, DeepEquals, expected) 166 167 tk.MustInterDirc("uFIDelate local_binlog set name = 'xyz' where id = 2") 168 prewriteVal = getLatestBinlogPrewriteValue(c, pump) 169 oldRow := [][]types.Causet{ 170 {types.NewIntCauset(2), types.NewDefCauslationStringCauset("cde", allegrosql.DefaultDefCauslationName, defCauslate.DefaultLen)}, 171 } 172 newRow := [][]types.Causet{ 173 {types.NewIntCauset(2), types.NewDefCauslationStringCauset("xyz", allegrosql.DefaultDefCauslationName, defCauslate.DefaultLen)}, 174 } 175 gotRows = mutationRowsToRows(c, prewriteVal.Mutations[0].UFIDelatedRows, 1, 3) 176 c.Assert(gotRows, DeepEquals, oldRow) 177 178 gotRows = mutationRowsToRows(c, prewriteVal.Mutations[0].UFIDelatedRows, 7, 9) 179 c.Assert(gotRows, DeepEquals, newRow) 180 181 tk.MustInterDirc("delete from local_binlog where id = 1") 182 prewriteVal = getLatestBinlogPrewriteValue(c, pump) 183 gotRows = mutationRowsToRows(c, prewriteVal.Mutations[0].DeletedRows, 1, 3) 184 expected = [][]types.Causet{ 185 {types.NewIntCauset(1), types.NewDefCauslationStringCauset("abc", allegrosql.DefaultDefCauslationName, defCauslate.DefaultLen)}, 186 } 187 c.Assert(gotRows, DeepEquals, expected) 188 189 // Test causet primary key is not integer. 190 tk.MustInterDirc("set @@milevadb_enable_clustered_index=0;") 191 tk.MustInterDirc("create causet local_binlog2 (name varchar(64) primary key, age int)") 192 tk.MustInterDirc("insert local_binlog2 values ('abc', 16), ('def', 18)") 193 tk.MustInterDirc("delete from local_binlog2 where name = 'def'") 194 prewriteVal = getLatestBinlogPrewriteValue(c, pump) 195 c.Assert(prewriteVal.Mutations[0].Sequence[0], Equals, binlog.MutationType_DeleteRow) 196 197 expected = [][]types.Causet{ 198 {types.NewStringCauset("def"), types.NewIntCauset(18), types.NewIntCauset(-1), types.NewIntCauset(2)}, 199 } 200 gotRows = mutationRowsToRows(c, prewriteVal.Mutations[0].DeletedRows, 1, 3, 4, 5) 201 c.Assert(gotRows, DeepEquals, expected) 202 203 // Test Block don't have primary key. 204 tk.MustInterDirc("create causet local_binlog3 (c1 int, c2 int)") 205 tk.MustInterDirc("insert local_binlog3 values (1, 2), (1, 3), (2, 3)") 206 tk.MustInterDirc("uFIDelate local_binlog3 set c1 = 3 where c1 = 2") 207 prewriteVal = getLatestBinlogPrewriteValue(c, pump) 208 209 // The encoded uFIDelate event is [oldDefCausID1, oldDefCausVal1, oldDefCausID2, oldDefCausVal2, -1, handle, 210 // newDefCausID1, newDefCausVal2, newDefCausID2, newDefCausVal2, -1, handle] 211 gotRows = mutationRowsToRows(c, prewriteVal.Mutations[0].UFIDelatedRows, 7, 9) 212 expected = [][]types.Causet{ 213 {types.NewIntCauset(3), types.NewIntCauset(3)}, 214 } 215 c.Assert(gotRows, DeepEquals, expected) 216 expected = [][]types.Causet{ 217 {types.NewIntCauset(-1), types.NewIntCauset(3), types.NewIntCauset(-1), types.NewIntCauset(3)}, 218 } 219 gotRows = mutationRowsToRows(c, prewriteVal.Mutations[0].UFIDelatedRows, 4, 5, 10, 11) 220 c.Assert(gotRows, DeepEquals, expected) 221 222 tk.MustInterDirc("delete from local_binlog3 where c1 = 3 and c2 = 3") 223 prewriteVal = getLatestBinlogPrewriteValue(c, pump) 224 c.Assert(prewriteVal.Mutations[0].Sequence[0], Equals, binlog.MutationType_DeleteRow) 225 gotRows = mutationRowsToRows(c, prewriteVal.Mutations[0].DeletedRows, 1, 3, 4, 5) 226 expected = [][]types.Causet{ 227 {types.NewIntCauset(3), types.NewIntCauset(3), types.NewIntCauset(-1), types.NewIntCauset(3)}, 228 } 229 c.Assert(gotRows, DeepEquals, expected) 230 231 // Test Mutation Sequence. 232 tk.MustInterDirc("create causet local_binlog4 (c1 int primary key, c2 int)") 233 tk.MustInterDirc("insert local_binlog4 values (1, 1), (2, 2), (3, 2)") 234 tk.MustInterDirc("begin") 235 tk.MustInterDirc("delete from local_binlog4 where c1 = 1") 236 tk.MustInterDirc("insert local_binlog4 values (1, 1)") 237 tk.MustInterDirc("uFIDelate local_binlog4 set c2 = 3 where c1 = 3") 238 tk.MustInterDirc("commit") 239 prewriteVal = getLatestBinlogPrewriteValue(c, pump) 240 c.Assert(prewriteVal.Mutations[0].Sequence, DeepEquals, []binlog.MutationType{ 241 binlog.MutationType_DeleteRow, 242 binlog.MutationType_Insert, 243 binlog.MutationType_UFIDelate, 244 }) 245 246 // Test memex rollback. 247 tk.MustInterDirc("create causet local_binlog5 (c1 int primary key)") 248 tk.MustInterDirc("begin") 249 tk.MustInterDirc("insert into local_binlog5 value (1)") 250 // This memex execute fail and should not write binlog. 251 _, err := tk.InterDirc("insert into local_binlog5 value (4),(3),(1),(2)") 252 c.Assert(err, NotNil) 253 tk.MustInterDirc("commit") 254 prewriteVal = getLatestBinlogPrewriteValue(c, pump) 255 c.Assert(prewriteVal.Mutations[0].Sequence, DeepEquals, []binlog.MutationType{ 256 binlog.MutationType_Insert, 257 }) 258 259 checkBinlogCount(c, pump) 260 261 pump.mu.Lock() 262 originBinlogLen := len(pump.mu.payloads) 263 pump.mu.Unlock() 264 tk.MustInterDirc("set @@global.autocommit = 0") 265 tk.MustInterDirc("set @@global.autocommit = 1") 266 pump.mu.Lock() 267 newBinlogLen := len(pump.mu.payloads) 268 pump.mu.Unlock() 269 c.Assert(newBinlogLen, Equals, originBinlogLen) 270 } 271 272 func (s *testBinlogSuite) TestMaxRecvSize(c *C) { 273 info := &binloginfo.BinlogInfo{ 274 Data: &binlog.Binlog{ 275 Tp: binlog.BinlogType_Prewrite, 276 PrewriteValue: make([]byte, maxRecvMsgSize+1), 277 }, 278 Client: s.client, 279 } 280 binlogWR := info.WriteBinlog(1) 281 err := binlogWR.GetError() 282 c.Assert(err, NotNil) 283 c.Assert(terror.ErrCritical.Equal(err), IsFalse, Commentf("%v", err)) 284 } 285 286 func getLatestBinlogPrewriteValue(c *C, pump *mockBinlogPump) *binlog.PrewriteValue { 287 var bin *binlog.Binlog 288 pump.mu.Lock() 289 for i := len(pump.mu.payloads) - 1; i >= 0; i-- { 290 payload := pump.mu.payloads[i] 291 bin = new(binlog.Binlog) 292 bin.Unmarshal(payload) 293 if bin.Tp == binlog.BinlogType_Prewrite { 294 break 295 } 296 } 297 pump.mu.Unlock() 298 c.Assert(bin, NotNil) 299 preVal := new(binlog.PrewriteValue) 300 preVal.Unmarshal(bin.PrewriteValue) 301 return preVal 302 } 303 304 func getLatestDBSBinlog(c *C, pump *mockBinlogPump, dbsQuery string) (preDBS, commitDBS *binlog.Binlog, offset int) { 305 pump.mu.Lock() 306 for i := len(pump.mu.payloads) - 1; i >= 0; i-- { 307 payload := pump.mu.payloads[i] 308 bin := new(binlog.Binlog) 309 bin.Unmarshal(payload) 310 if bin.Tp == binlog.BinlogType_Commit && bin.DdlJobId > 0 { 311 commitDBS = bin 312 } 313 if bin.Tp == binlog.BinlogType_Prewrite && bin.DdlJobId != 0 { 314 preDBS = bin 315 } 316 if preDBS != nil && commitDBS != nil { 317 offset = i 318 break 319 } 320 } 321 pump.mu.Unlock() 322 c.Assert(preDBS.DdlJobId, Greater, int64(0)) 323 c.Assert(preDBS.StartTs, Greater, int64(0)) 324 c.Assert(preDBS.CommitTs, Equals, int64(0)) 325 c.Assert(string(preDBS.DdlQuery), Equals, dbsQuery) 326 return 327 } 328 329 func checkBinlogCount(c *C, pump *mockBinlogPump) { 330 var bin *binlog.Binlog 331 prewriteCount := 0 332 dbsCount := 0 333 pump.mu.Lock() 334 length := len(pump.mu.payloads) 335 for i := length - 1; i >= 0; i-- { 336 payload := pump.mu.payloads[i] 337 bin = new(binlog.Binlog) 338 bin.Unmarshal(payload) 339 if bin.Tp == binlog.BinlogType_Prewrite { 340 if bin.DdlJobId != 0 { 341 dbsCount++ 342 } else { 343 prewriteCount++ 344 } 345 } 346 } 347 pump.mu.Unlock() 348 c.Assert(dbsCount, Greater, 0) 349 match := false 350 for i := 0; i < 10; i++ { 351 pump.mu.Lock() 352 length = len(pump.mu.payloads) 353 pump.mu.Unlock() 354 if (prewriteCount+dbsCount)*2 == length { 355 match = true 356 break 357 } 358 time.Sleep(time.Millisecond * 10) 359 } 360 c.Assert(match, IsTrue) 361 } 362 363 func mutationRowsToRows(c *C, mutationRows [][]byte, defCausumnValueOffsets ...int) [][]types.Causet { 364 var rows = make([][]types.Causet, 0) 365 for _, mutationRow := range mutationRows { 366 datums, err := codec.Decode(mutationRow, 5) 367 c.Assert(err, IsNil) 368 for i := range datums { 369 if datums[i].HoTT() == types.HoTTBytes { 370 datums[i].SetBytesAsString(datums[i].GetBytes(), allegrosql.DefaultDefCauslationName, defCauslate.DefaultLen) 371 } 372 } 373 event := make([]types.Causet, 0, len(defCausumnValueOffsets)) 374 for _, defCausOff := range defCausumnValueOffsets { 375 event = append(event, datums[defCausOff]) 376 } 377 rows = append(rows, event) 378 } 379 return rows 380 } 381 382 func (s *testBinlogSuite) TestBinlogForSequence(c *C) { 383 c.Assert(failpoint.Enable("github.com/whtcorpsinc/milevadb/causetstore/einsteindb/mockSyncBinlogCommit", `return(true)`), IsNil) 384 defer func() { 385 c.Assert(failpoint.Disable("github.com/whtcorpsinc/milevadb/causetstore/einsteindb/mockSyncBinlogCommit"), IsNil) 386 }() 387 tk := testkit.NewTestKit(c, s.causetstore) 388 tk.MustInterDirc("use test") 389 s.pump.mu.Lock() 390 s.pump.mu.payloads = s.pump.mu.payloads[:0] 391 s.pump.mu.Unlock() 392 tk.Se.GetStochastikVars().BinlogClient = s.client 393 394 tk.MustInterDirc("drop sequence if exists seq") 395 // the default start = 1, increment = 1. 396 tk.MustInterDirc("create sequence seq cache 3") 397 // trigger the sequence cache allocation. 398 tk.MustQuery("select nextval(seq)").Check(testkit.Rows("1")) 399 sequenceBlock := testGetBlockByName(c, tk.Se, "test", "seq") 400 tc, ok := sequenceBlock.(*blocks.BlockCommon) 401 c.Assert(ok, Equals, true) 402 _, end, round := tc.GetSequenceCommon().GetSequenceBaseEndRound() 403 c.Assert(end, Equals, int64(3)) 404 c.Assert(round, Equals, int64(0)) 405 406 // Check the sequence binlog. 407 // Got matched pre DBS and commit DBS. 408 ok = mustGetDBSBinlog(s, "select setval(`test`.`seq`, 3)", c) 409 c.Assert(ok, IsTrue) 410 411 // Invalidate the current sequence cache. 412 tk.MustQuery("select setval(seq, 5)").Check(testkit.Rows("5")) 413 // trigger the next sequence cache allocation. 414 tk.MustQuery("select nextval(seq)").Check(testkit.Rows("6")) 415 _, end, round = tc.GetSequenceCommon().GetSequenceBaseEndRound() 416 c.Assert(end, Equals, int64(8)) 417 c.Assert(round, Equals, int64(0)) 418 ok = mustGetDBSBinlog(s, "select setval(`test`.`seq`, 8)", c) 419 c.Assert(ok, IsTrue) 420 421 tk.MustInterDirc("create database test2") 422 tk.MustInterDirc("use test2") 423 tk.MustInterDirc("drop sequence if exists seq2") 424 tk.MustInterDirc("create sequence seq2 start 1 increment -2 cache 3 minvalue -10 maxvalue 10 cycle") 425 // trigger the sequence cache allocation. 426 tk.MustQuery("select nextval(seq2)").Check(testkit.Rows("1")) 427 sequenceBlock = testGetBlockByName(c, tk.Se, "test2", "seq2") 428 tc, ok = sequenceBlock.(*blocks.BlockCommon) 429 c.Assert(ok, Equals, true) 430 _, end, round = tc.GetSequenceCommon().GetSequenceBaseEndRound() 431 c.Assert(end, Equals, int64(-3)) 432 c.Assert(round, Equals, int64(0)) 433 ok = mustGetDBSBinlog(s, "select setval(`test2`.`seq2`, -3)", c) 434 c.Assert(ok, IsTrue) 435 436 tk.MustQuery("select setval(seq2, -100)").Check(testkit.Rows("-100")) 437 // trigger the sequence cache allocation. 438 tk.MustQuery("select nextval(seq2)").Check(testkit.Rows("10")) 439 _, end, round = tc.GetSequenceCommon().GetSequenceBaseEndRound() 440 c.Assert(end, Equals, int64(6)) 441 c.Assert(round, Equals, int64(1)) 442 ok = mustGetDBSBinlog(s, "select setval(`test2`.`seq2`, 6)", c) 443 c.Assert(ok, IsTrue) 444 445 // Test dml txn is independent from sequence txn. 446 tk.MustInterDirc("drop sequence if exists seq") 447 tk.MustInterDirc("create sequence seq cache 3") 448 tk.MustInterDirc("drop causet if exists t") 449 tk.MustInterDirc("create causet t (a int default next value for seq)") 450 // sequence txn commit first then the dml txn. 451 tk.MustInterDirc("insert into t values(-1),(default),(-1),(default)") 452 // binlog list like [... dbs prewrite(offset), dbs commit, dml prewrite, dml commit] 453 _, _, offset := getLatestDBSBinlog(c, s.pump, "select setval(`test2`.`seq`, 3)") 454 s.pump.mu.Lock() 455 c.Assert(offset+3, Equals, len(s.pump.mu.payloads)-1) 456 s.pump.mu.Unlock() 457 } 458 459 // Sometimes this test doesn't clean up fail, let the function name begin with 'Z' 460 // so it runs last and would not disrupt other tests. 461 func (s *testBinlogSuite) TestZIgnoreError(c *C) { 462 tk := testkit.NewTestKit(c, s.causetstore) 463 tk.MustInterDirc("use test") 464 tk.Se.GetStochastikVars().BinlogClient = s.client 465 tk.MustInterDirc("drop causet if exists t") 466 tk.MustInterDirc("create causet t (id int)") 467 468 binloginfo.SetIgnoreError(true) 469 s.pump.mu.Lock() 470 s.pump.mu.mockFail = true 471 s.pump.mu.Unlock() 472 473 tk.MustInterDirc("insert into t values (1)") 474 tk.MustInterDirc("insert into t values (1)") 475 476 // Clean up. 477 s.pump.mu.Lock() 478 s.pump.mu.mockFail = false 479 s.pump.mu.Unlock() 480 binloginfo.DisableSkipBinlogFlag() 481 binloginfo.SetIgnoreError(false) 482 } 483 484 func (s *testBinlogSuite) TestPartitionedBlock(c *C) { 485 // This test checks partitioned causet write binlog with causet ID, rather than partition ID. 486 tk := testkit.NewTestKit(c, s.causetstore) 487 tk.MustInterDirc("use test") 488 tk.Se.GetStochastikVars().BinlogClient = s.client 489 tk.MustInterDirc("drop causet if exists t") 490 tk.MustInterDirc(`create causet t (id int) partition by range (id) ( 491 partition p0 values less than (1), 492 partition p1 values less than (4), 493 partition p2 values less than (7), 494 partition p3 values less than (10))`) 495 tids := make([]int64, 0, 10) 496 for i := 0; i < 10; i++ { 497 tk.MustInterDirc("insert into t values (?)", i) 498 prewriteVal := getLatestBinlogPrewriteValue(c, s.pump) 499 tids = append(tids, prewriteVal.Mutations[0].BlockId) 500 } 501 c.Assert(len(tids), Equals, 10) 502 for i := 1; i < 10; i++ { 503 c.Assert(tids[i], Equals, tids[0]) 504 } 505 } 506 507 func (s *testBinlogSuite) TestDeleteSchema(c *C) { 508 tk := testkit.NewTestKit(c, s.causetstore) 509 tk.MustInterDirc("use test") 510 tk.MustInterDirc("CREATE TABLE `b1` (`id` int(11) NOT NULL AUTO_INCREMENT, `job_id` varchar(50) NOT NULL, `split_job_id` varchar(30) DEFAULT NULL, PRIMARY KEY (`id`), KEY `b1` (`job_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;") 511 tk.MustInterDirc("CREATE TABLE `b2` (`id` int(11) NOT NULL AUTO_INCREMENT, `job_id` varchar(50) NOT NULL, `batch_class` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `bu` (`job_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4") 512 tk.MustInterDirc("insert into b2 (job_id, batch_class) values (2, 'TEST');") 513 tk.MustInterDirc("insert into b1 (job_id) values (2);") 514 515 // This test cover a bug that the final schemaReplicant and the binlog event inconsistent. 516 // The final schemaReplicant of this ALLEGROALLEGROSQL should be the schemaReplicant of causet b1, rather than the schemaReplicant of join result. 517 tk.MustInterDirc("delete from b1 where job_id in (select job_id from b2 where batch_class = 'TEST') or split_job_id in (select job_id from b2 where batch_class = 'TEST');") 518 tk.MustInterDirc("delete b1 from b2 right join b1 on b1.job_id = b2.job_id and batch_class = 'TEST';") 519 } 520 521 func (s *testBinlogSuite) TestAddSpecialComment(c *C) { 522 testCase := []struct { 523 input string 524 result string 525 }{ 526 { 527 "create causet t1 (id int ) shard_row_id_bits=2;", 528 "create causet t1 (id int ) /*T! shard_row_id_bits=2 */ ;", 529 }, 530 { 531 "create causet t1 (id int ) shard_row_id_bits=2 pre_split_regions=2;", 532 "create causet t1 (id int ) /*T! shard_row_id_bits=2 pre_split_regions=2 */ ;", 533 }, 534 { 535 "create causet t1 (id int ) shard_row_id_bits=2 pre_split_regions=2;", 536 "create causet t1 (id int ) /*T! shard_row_id_bits=2 pre_split_regions=2 */ ;", 537 }, 538 539 { 540 "create causet t1 (id int ) shard_row_id_bits=2 engine=innodb pre_split_regions=2;", 541 "create causet t1 (id int ) /*T! shard_row_id_bits=2 pre_split_regions=2 */ engine=innodb ;", 542 }, 543 { 544 "create causet t1 (id int ) pre_split_regions=2 shard_row_id_bits=2;", 545 "create causet t1 (id int ) /*T! shard_row_id_bits=2 pre_split_regions=2 */ ;", 546 }, 547 { 548 "create causet t6 (id int ) shard_row_id_bits=2 shard_row_id_bits=3 pre_split_regions=2;", 549 "create causet t6 (id int ) /*T! shard_row_id_bits=2 shard_row_id_bits=3 pre_split_regions=2 */ ;", 550 }, 551 { 552 "create causet t1 (id int primary key auto_random(2));", 553 "create causet t1 (id int primary key /*T![auto_rand] auto_random(2) */ );", 554 }, 555 { 556 "create causet t1 (id int primary key auto_random);", 557 "create causet t1 (id int primary key /*T![auto_rand] auto_random */ );", 558 }, 559 { 560 "create causet t1 (id int auto_random ( 4 ) primary key);", 561 "create causet t1 (id int /*T![auto_rand] auto_random ( 4 ) */ primary key);", 562 }, 563 { 564 "create causet t1 (id int auto_random ( 4 ) primary key);", 565 "create causet t1 (id int /*T![auto_rand] auto_random ( 4 ) */ primary key);", 566 }, 567 { 568 "create causet t1 (id int auto_random ( 3 ) primary key) auto_random_base = 100;", 569 "create causet t1 (id int /*T![auto_rand] auto_random ( 3 ) */ primary key) /*T![auto_rand_base] auto_random_base = 100 */ ;", 570 }, 571 { 572 "create causet t1 (id int auto_random primary key) auto_random_base = 50;", 573 "create causet t1 (id int /*T![auto_rand] auto_random */ primary key) /*T![auto_rand_base] auto_random_base = 50 */ ;", 574 }, 575 { 576 "create causet t1 (id int auto_increment key) auto_id_cache 100;", 577 "create causet t1 (id int auto_increment key) /*T![auto_id_cache] auto_id_cache 100 */ ;", 578 }, 579 { 580 "create causet t1 (id int auto_increment unique) auto_id_cache 10;", 581 "create causet t1 (id int auto_increment unique) /*T![auto_id_cache] auto_id_cache 10 */ ;", 582 }, 583 { 584 "create causet t1 (id int) auto_id_cache = 5;", 585 "create causet t1 (id int) /*T![auto_id_cache] auto_id_cache = 5 */ ;", 586 }, 587 { 588 "create causet t1 (id int) auto_id_cache=5;", 589 "create causet t1 (id int) /*T![auto_id_cache] auto_id_cache=5 */ ;", 590 }, 591 { 592 "create causet t1 (id int) /*T![auto_id_cache] auto_id_cache=5 */ ;", 593 "create causet t1 (id int) /*T![auto_id_cache] auto_id_cache=5 */ ;", 594 }, 595 } 596 for _, ca := range testCase { 597 re := binloginfo.AddSpecialComment(ca.input) 598 c.Assert(re, Equals, ca.result) 599 } 600 } 601 602 func mustGetDBSBinlog(s *testBinlogSuite, dbsQuery string, c *C) (matched bool) { 603 for i := 0; i < 10; i++ { 604 preDBS, commitDBS, _ := getLatestDBSBinlog(c, s.pump, dbsQuery) 605 if preDBS != nil && commitDBS != nil { 606 if preDBS.DdlJobId == commitDBS.DdlJobId { 607 c.Assert(commitDBS.StartTs, Equals, preDBS.StartTs) 608 c.Assert(commitDBS.CommitTs, Greater, commitDBS.StartTs) 609 matched = true 610 break 611 } 612 } 613 time.Sleep(time.Millisecond * 30) 614 } 615 return 616 } 617 618 func testGetBlockByName(c *C, ctx stochastikctx.Context, EDB, causet string) causet.Block { 619 dom := petri.GetPetri(ctx) 620 // Make sure the causet schemaReplicant is the new schemaReplicant. 621 err := dom.Reload() 622 c.Assert(err, IsNil) 623 tbl, err := dom.SchemaReplicant().BlockByName(perceptron.NewCIStr(EDB), perceptron.NewCIStr(causet)) 624 c.Assert(err, IsNil) 625 return tbl 626 }