github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/ddl/index_test.go (about) 1 // Copyright 2015 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package ddl 15 16 import ( 17 "strings" 18 "time" 19 20 . "github.com/insionng/yougam/libraries/pingcap/check" 21 "github.com/insionng/yougam/libraries/pingcap/tidb/ast" 22 "github.com/insionng/yougam/libraries/pingcap/tidb/column" 23 "github.com/insionng/yougam/libraries/pingcap/tidb/context" 24 "github.com/insionng/yougam/libraries/pingcap/tidb/kv" 25 "github.com/insionng/yougam/libraries/pingcap/tidb/model" 26 "github.com/insionng/yougam/libraries/pingcap/tidb/table" 27 "github.com/insionng/yougam/libraries/pingcap/tidb/table/tables" 28 "github.com/insionng/yougam/libraries/pingcap/tidb/util/mock" 29 "github.com/insionng/yougam/libraries/pingcap/tidb/util/testleak" 30 "github.com/insionng/yougam/libraries/pingcap/tidb/util/types" 31 ) 32 33 var _ = Suite(&testIndexSuite{}) 34 35 type testIndexSuite struct { 36 store kv.Storage 37 dbInfo *model.DBInfo 38 39 d *ddl 40 } 41 42 func (s *testIndexSuite) SetUpSuite(c *C) { 43 trySkipTest(c) 44 45 s.store = testCreateStore(c, "test_index") 46 lease := 50 * time.Millisecond 47 s.d = newDDL(s.store, nil, nil, lease) 48 49 s.dbInfo = testSchemaInfo(c, s.d, "test_index") 50 testCreateSchema(c, mock.NewContext(), s.d, s.dbInfo) 51 } 52 53 func (s *testIndexSuite) TearDownSuite(c *C) { 54 trySkipTest(c) 55 56 testDropSchema(c, mock.NewContext(), s.d, s.dbInfo) 57 s.d.close() 58 59 err := s.store.Close() 60 c.Assert(err, IsNil) 61 } 62 63 func testCreateIndex(c *C, ctx context.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, unique bool, indexName string, colName string) *model.Job { 64 id, err := d.genGlobalID() 65 c.Assert(err, IsNil) 66 job := &model.Job{ 67 SchemaID: dbInfo.ID, 68 TableID: tblInfo.ID, 69 Type: model.ActionAddIndex, 70 Args: []interface{}{unique, model.NewCIStr(indexName), id, []*ast.IndexColName{{Column: &ast.ColumnName{Name: model.NewCIStr(colName)}, Length: 256}}}, 71 } 72 73 err = d.doDDLJob(ctx, job) 74 c.Assert(err, IsNil) 75 return job 76 } 77 78 func testDropIndex(c *C, ctx context.Context, d *ddl, dbInfo *model.DBInfo, tblInfo *model.TableInfo, indexName string) *model.Job { 79 job := &model.Job{ 80 SchemaID: dbInfo.ID, 81 TableID: tblInfo.ID, 82 Type: model.ActionDropIndex, 83 Args: []interface{}{model.NewCIStr(indexName)}, 84 } 85 86 err := d.doDDLJob(ctx, job) 87 c.Assert(err, IsNil) 88 return job 89 } 90 91 func (s *testIndexSuite) TestIndex(c *C) { 92 defer testleak.AfterTest(c)() 93 tblInfo := testTableInfo(c, s.d, "t1", 3) 94 ctx := testNewContext(c, s.d) 95 defer ctx.FinishTxn(true) 96 97 txn, err := ctx.GetTxn(true) 98 c.Assert(err, IsNil) 99 100 testCreateTable(c, ctx, s.d, s.dbInfo, tblInfo) 101 102 t := testGetTable(c, s.d, s.dbInfo.ID, tblInfo.ID) 103 104 num := 10 105 for i := 0; i < num; i++ { 106 _, err = t.AddRecord(ctx, types.MakeDatums(i, i, i)) 107 c.Assert(err, IsNil) 108 } 109 110 err = ctx.FinishTxn(false) 111 c.Assert(err, IsNil) 112 113 i := int64(0) 114 t.IterRecords(ctx, t.FirstKey(), t.Cols(), func(h int64, data []types.Datum, cols []*column.Col) (bool, error) { 115 c.Assert(data[0].GetInt64(), Equals, i) 116 i++ 117 return true, nil 118 }) 119 120 job := testCreateIndex(c, ctx, s.d, s.dbInfo, tblInfo, true, "c1_uni", "c1") 121 testCheckJobDone(c, s.d, job, true) 122 123 t = testGetTable(c, s.d, s.dbInfo.ID, tblInfo.ID) 124 index := tables.FindIndexByColName(t, "c1") 125 c.Assert(index, NotNil) 126 127 h, err := t.AddRecord(ctx, types.MakeDatums(num+1, 1, 1)) 128 c.Assert(err, IsNil) 129 130 h1, err := t.AddRecord(ctx, types.MakeDatums(num+1, 1, 1)) 131 c.Assert(err, NotNil) 132 c.Assert(h, Equals, h1) 133 134 h, err = t.AddRecord(ctx, types.MakeDatums(1, 1, 1)) 135 c.Assert(err, NotNil) 136 137 txn, err = ctx.GetTxn(true) 138 c.Assert(err, IsNil) 139 140 exist, _, err := index.X.Exist(txn, types.MakeDatums(1), h) 141 c.Assert(err, IsNil) 142 c.Assert(exist, IsTrue) 143 144 job = testDropIndex(c, ctx, s.d, s.dbInfo, tblInfo, "c1_uni") 145 testCheckJobDone(c, s.d, job, false) 146 147 t = testGetTable(c, s.d, s.dbInfo.ID, tblInfo.ID) 148 index1 := tables.FindIndexByColName(t, "c1") 149 c.Assert(index1, IsNil) 150 151 txn, err = ctx.GetTxn(true) 152 c.Assert(err, IsNil) 153 154 exist, _, err = index.X.Exist(txn, types.MakeDatums(1), h) 155 c.Assert(err, IsNil) 156 c.Assert(exist, IsFalse) 157 158 _, err = t.AddRecord(ctx, types.MakeDatums(1, 1, 1)) 159 c.Assert(err, IsNil) 160 } 161 162 func getIndex(t table.Table, name string) *column.IndexedCol { 163 for _, idx := range t.Indices() { 164 // only public index can be read. 165 166 if len(idx.Columns) == 1 && strings.EqualFold(idx.Columns[0].Name.L, name) { 167 return idx 168 } 169 } 170 return nil 171 } 172 173 func (s *testIndexSuite) testGetIndex(c *C, t table.Table, name string, isExist bool) { 174 index := tables.FindIndexByColName(t, name) 175 if isExist { 176 c.Assert(index, NotNil) 177 } else { 178 c.Assert(index, IsNil) 179 } 180 } 181 182 func (s *testIndexSuite) checkIndexKVExist(c *C, ctx context.Context, t table.Table, handle int64, indexCol *column.IndexedCol, columnValues []types.Datum, isExist bool) { 183 c.Assert(len(indexCol.Columns), Equals, len(columnValues)) 184 185 txn, err := ctx.GetTxn(true) 186 c.Assert(err, IsNil) 187 188 exist, _, err := indexCol.X.Exist(txn, columnValues, handle) 189 c.Assert(err, IsNil) 190 c.Assert(exist, Equals, isExist) 191 192 err = ctx.FinishTxn(false) 193 c.Assert(err, IsNil) 194 } 195 196 func (s *testIndexSuite) checkNoneIndex(c *C, ctx context.Context, d *ddl, tblInfo *model.TableInfo, handle int64, indexCol *column.IndexedCol, row []types.Datum) { 197 t := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) 198 199 columnValues := make([]types.Datum, len(indexCol.Columns)) 200 for i, column := range indexCol.Columns { 201 columnValues[i] = row[column.Offset] 202 } 203 204 s.checkIndexKVExist(c, ctx, t, handle, indexCol, columnValues, false) 205 s.testGetIndex(c, t, indexCol.Columns[0].Name.L, false) 206 } 207 208 func (s *testIndexSuite) checkDeleteOnlyIndex(c *C, ctx context.Context, d *ddl, tblInfo *model.TableInfo, handle int64, indexCol *column.IndexedCol, row []types.Datum, isDropped bool) { 209 t := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) 210 211 _, err := ctx.GetTxn(true) 212 c.Assert(err, IsNil) 213 214 i := int64(0) 215 err = t.IterRecords(ctx, t.FirstKey(), t.Cols(), func(h int64, data []types.Datum, cols []*column.Col) (bool, error) { 216 c.Assert(data, DeepEquals, row) 217 i++ 218 return true, nil 219 }) 220 c.Assert(err, IsNil) 221 c.Assert(i, Equals, int64(1)) 222 223 columnValues := make([]types.Datum, len(indexCol.Columns)) 224 for i, column := range indexCol.Columns { 225 columnValues[i] = row[column.Offset] 226 } 227 228 s.checkIndexKVExist(c, ctx, t, handle, indexCol, columnValues, isDropped) 229 230 // Test add a new row. 231 _, err = ctx.GetTxn(true) 232 c.Assert(err, IsNil) 233 234 newRow := types.MakeDatums(int64(11), int64(22), int64(33)) 235 handle, err = t.AddRecord(ctx, newRow) 236 c.Assert(err, IsNil) 237 238 _, err = ctx.GetTxn(true) 239 c.Assert(err, IsNil) 240 241 rows := [][]types.Datum{row, newRow} 242 243 i = int64(0) 244 t.IterRecords(ctx, t.FirstKey(), t.Cols(), func(h int64, data []types.Datum, cols []*column.Col) (bool, error) { 245 c.Assert(data, DeepEquals, rows[i]) 246 i++ 247 return true, nil 248 }) 249 c.Assert(i, Equals, int64(2)) 250 251 for i, column := range indexCol.Columns { 252 columnValues[i] = newRow[column.Offset] 253 } 254 255 s.checkIndexKVExist(c, ctx, t, handle, indexCol, columnValues, false) 256 257 // Test update a new row. 258 _, err = ctx.GetTxn(true) 259 c.Assert(err, IsNil) 260 261 newUpdateRow := types.MakeDatums(int64(44), int64(55), int64(66)) 262 touched := map[int]bool{0: true, 1: true, 2: true} 263 err = t.UpdateRecord(ctx, handle, newRow, newUpdateRow, touched) 264 c.Assert(err, IsNil) 265 266 s.checkIndexKVExist(c, ctx, t, handle, indexCol, columnValues, false) 267 268 for i, column := range indexCol.Columns { 269 columnValues[i] = newUpdateRow[column.Offset] 270 } 271 272 s.checkIndexKVExist(c, ctx, t, handle, indexCol, columnValues, false) 273 274 // Test remove a row. 275 _, err = ctx.GetTxn(true) 276 c.Assert(err, IsNil) 277 278 err = t.RemoveRecord(ctx, handle, newUpdateRow) 279 c.Assert(err, IsNil) 280 281 _, err = ctx.GetTxn(true) 282 c.Assert(err, IsNil) 283 284 i = int64(0) 285 t.IterRecords(ctx, t.FirstKey(), t.Cols(), func(h int64, data []types.Datum, cols []*column.Col) (bool, error) { 286 i++ 287 return true, nil 288 }) 289 c.Assert(i, Equals, int64(1)) 290 291 s.checkIndexKVExist(c, ctx, t, handle, indexCol, columnValues, false) 292 s.testGetIndex(c, t, indexCol.Columns[0].Name.L, false) 293 } 294 295 func (s *testIndexSuite) checkWriteOnlyIndex(c *C, ctx context.Context, d *ddl, tblInfo *model.TableInfo, handle int64, indexCol *column.IndexedCol, row []types.Datum, isDropped bool) { 296 t := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) 297 298 _, err := ctx.GetTxn(true) 299 c.Assert(err, IsNil) 300 301 i := int64(0) 302 err = t.IterRecords(ctx, t.FirstKey(), t.Cols(), func(h int64, data []types.Datum, cols []*column.Col) (bool, error) { 303 c.Assert(data, DeepEquals, row) 304 i++ 305 return true, nil 306 }) 307 c.Assert(err, IsNil) 308 c.Assert(i, Equals, int64(1)) 309 310 columnValues := make([]types.Datum, len(indexCol.Columns)) 311 for i, column := range indexCol.Columns { 312 columnValues[i] = row[column.Offset] 313 } 314 315 s.checkIndexKVExist(c, ctx, t, handle, indexCol, columnValues, isDropped) 316 317 // Test add a new row. 318 _, err = ctx.GetTxn(true) 319 c.Assert(err, IsNil) 320 321 newRow := types.MakeDatums(int64(11), int64(22), int64(33)) 322 handle, err = t.AddRecord(ctx, newRow) 323 c.Assert(err, IsNil) 324 325 _, err = ctx.GetTxn(true) 326 c.Assert(err, IsNil) 327 328 rows := [][]types.Datum{row, newRow} 329 330 i = int64(0) 331 t.IterRecords(ctx, t.FirstKey(), t.Cols(), func(h int64, data []types.Datum, cols []*column.Col) (bool, error) { 332 c.Assert(data, DeepEquals, rows[i]) 333 i++ 334 return true, nil 335 }) 336 c.Assert(i, Equals, int64(2)) 337 338 for i, column := range indexCol.Columns { 339 columnValues[i] = newRow[column.Offset] 340 } 341 342 s.checkIndexKVExist(c, ctx, t, handle, indexCol, columnValues, true) 343 344 // Test update a new row. 345 _, err = ctx.GetTxn(true) 346 c.Assert(err, IsNil) 347 348 newUpdateRow := types.MakeDatums(int64(44), int64(55), int64(66)) 349 touched := map[int]bool{0: true, 1: true, 2: true} 350 err = t.UpdateRecord(ctx, handle, newRow, newUpdateRow, touched) 351 c.Assert(err, IsNil) 352 353 s.checkIndexKVExist(c, ctx, t, handle, indexCol, columnValues, false) 354 355 for i, column := range indexCol.Columns { 356 columnValues[i] = newUpdateRow[column.Offset] 357 } 358 359 s.checkIndexKVExist(c, ctx, t, handle, indexCol, columnValues, true) 360 361 // Test remove a row. 362 _, err = ctx.GetTxn(true) 363 c.Assert(err, IsNil) 364 365 err = t.RemoveRecord(ctx, handle, newUpdateRow) 366 c.Assert(err, IsNil) 367 368 _, err = ctx.GetTxn(true) 369 c.Assert(err, IsNil) 370 371 i = int64(0) 372 t.IterRecords(ctx, t.FirstKey(), t.Cols(), func(h int64, data []types.Datum, cols []*column.Col) (bool, error) { 373 i++ 374 return true, nil 375 }) 376 c.Assert(i, Equals, int64(1)) 377 378 s.checkIndexKVExist(c, ctx, t, handle, indexCol, columnValues, false) 379 s.testGetIndex(c, t, indexCol.Columns[0].Name.L, false) 380 } 381 382 func (s *testIndexSuite) checkReorganizationIndex(c *C, ctx context.Context, d *ddl, tblInfo *model.TableInfo, handle int64, indexCol *column.IndexedCol, row []types.Datum, isDropped bool) { 383 t := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) 384 385 _, err := ctx.GetTxn(true) 386 c.Assert(err, IsNil) 387 388 i := int64(0) 389 err = t.IterRecords(ctx, t.FirstKey(), t.Cols(), func(h int64, data []types.Datum, cols []*column.Col) (bool, error) { 390 c.Assert(data, DeepEquals, row) 391 i++ 392 return true, nil 393 }) 394 c.Assert(err, IsNil) 395 c.Assert(i, Equals, int64(1)) 396 397 // Test add a new row. 398 _, err = ctx.GetTxn(true) 399 c.Assert(err, IsNil) 400 401 newRow := types.MakeDatums(int64(11), int64(22), int64(33)) 402 handle, err = t.AddRecord(ctx, newRow) 403 c.Assert(err, IsNil) 404 405 _, err = ctx.GetTxn(true) 406 c.Assert(err, IsNil) 407 408 rows := [][]types.Datum{row, newRow} 409 410 i = int64(0) 411 t.IterRecords(ctx, t.FirstKey(), t.Cols(), func(h int64, data []types.Datum, cols []*column.Col) (bool, error) { 412 c.Assert(data, DeepEquals, rows[i]) 413 i++ 414 return true, nil 415 }) 416 c.Assert(i, Equals, int64(2)) 417 418 columnValues := make([]types.Datum, len(indexCol.Columns)) 419 for i, column := range indexCol.Columns { 420 columnValues[i] = newRow[column.Offset] 421 } 422 423 s.checkIndexKVExist(c, ctx, t, handle, indexCol, columnValues, !isDropped) 424 425 // Test update a new row. 426 _, err = ctx.GetTxn(true) 427 c.Assert(err, IsNil) 428 429 newUpdateRow := types.MakeDatums(int64(44), int64(55), int64(66)) 430 touched := map[int]bool{0: true, 1: true, 2: true} 431 err = t.UpdateRecord(ctx, handle, newRow, newUpdateRow, touched) 432 c.Assert(err, IsNil) 433 434 s.checkIndexKVExist(c, ctx, t, handle, indexCol, columnValues, false) 435 436 for i, column := range indexCol.Columns { 437 columnValues[i] = newUpdateRow[column.Offset] 438 } 439 440 s.checkIndexKVExist(c, ctx, t, handle, indexCol, columnValues, !isDropped) 441 442 // Test remove a row. 443 _, err = ctx.GetTxn(true) 444 c.Assert(err, IsNil) 445 446 err = t.RemoveRecord(ctx, handle, newUpdateRow) 447 c.Assert(err, IsNil) 448 449 _, err = ctx.GetTxn(true) 450 c.Assert(err, IsNil) 451 452 i = int64(0) 453 t.IterRecords(ctx, t.FirstKey(), t.Cols(), func(h int64, data []types.Datum, cols []*column.Col) (bool, error) { 454 i++ 455 return true, nil 456 }) 457 c.Assert(i, Equals, int64(1)) 458 459 s.testGetIndex(c, t, indexCol.Columns[0].Name.L, false) 460 } 461 462 func (s *testIndexSuite) checkPublicIndex(c *C, ctx context.Context, d *ddl, tblInfo *model.TableInfo, handle int64, indexCol *column.IndexedCol, row []types.Datum) { 463 t := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) 464 465 _, err := ctx.GetTxn(true) 466 c.Assert(err, IsNil) 467 468 i := int64(0) 469 err = t.IterRecords(ctx, t.FirstKey(), t.Cols(), func(h int64, data []types.Datum, cols []*column.Col) (bool, error) { 470 c.Assert(data, DeepEquals, row) 471 i++ 472 return true, nil 473 }) 474 c.Assert(err, IsNil) 475 c.Assert(i, Equals, int64(1)) 476 477 columnValues := make([]types.Datum, len(indexCol.Columns)) 478 for i, column := range indexCol.Columns { 479 columnValues[i] = row[column.Offset] 480 } 481 482 s.checkIndexKVExist(c, ctx, t, handle, indexCol, columnValues, true) 483 484 // Test add a new row. 485 _, err = ctx.GetTxn(true) 486 c.Assert(err, IsNil) 487 488 newRow := types.MakeDatums(int64(11), int64(22), int64(33)) 489 handle, err = t.AddRecord(ctx, newRow) 490 c.Assert(err, IsNil) 491 492 _, err = ctx.GetTxn(true) 493 c.Assert(err, IsNil) 494 495 rows := [][]types.Datum{row, newRow} 496 497 i = int64(0) 498 t.IterRecords(ctx, t.FirstKey(), t.Cols(), func(h int64, data []types.Datum, cols []*column.Col) (bool, error) { 499 c.Assert(data, DeepEquals, rows[i]) 500 i++ 501 return true, nil 502 }) 503 c.Assert(i, Equals, int64(2)) 504 505 for i, column := range indexCol.Columns { 506 columnValues[i] = newRow[column.Offset] 507 } 508 509 s.checkIndexKVExist(c, ctx, t, handle, indexCol, columnValues, true) 510 511 // Test update a new row. 512 _, err = ctx.GetTxn(true) 513 c.Assert(err, IsNil) 514 515 newUpdateRow := types.MakeDatums(int64(44), int64(55), int64(66)) 516 touched := map[int]bool{0: true, 1: true, 2: true} 517 err = t.UpdateRecord(ctx, handle, newRow, newUpdateRow, touched) 518 c.Assert(err, IsNil) 519 520 s.checkIndexKVExist(c, ctx, t, handle, indexCol, columnValues, false) 521 522 for i, column := range indexCol.Columns { 523 columnValues[i] = newUpdateRow[column.Offset] 524 } 525 526 s.checkIndexKVExist(c, ctx, t, handle, indexCol, columnValues, true) 527 528 // Test remove a row. 529 _, err = ctx.GetTxn(true) 530 c.Assert(err, IsNil) 531 532 err = t.RemoveRecord(ctx, handle, newUpdateRow) 533 c.Assert(err, IsNil) 534 535 _, err = ctx.GetTxn(true) 536 c.Assert(err, IsNil) 537 538 i = int64(0) 539 t.IterRecords(ctx, t.FirstKey(), t.Cols(), func(h int64, data []types.Datum, cols []*column.Col) (bool, error) { 540 i++ 541 return true, nil 542 }) 543 c.Assert(i, Equals, int64(1)) 544 545 s.checkIndexKVExist(c, ctx, t, handle, indexCol, columnValues, false) 546 s.testGetIndex(c, t, indexCol.Columns[0].Name.L, true) 547 } 548 549 func (s *testIndexSuite) checkAddOrDropIndex(c *C, state model.SchemaState, d *ddl, tblInfo *model.TableInfo, handle int64, indexCol *column.IndexedCol, row []types.Datum, isDropped bool) { 550 ctx := testNewContext(c, d) 551 552 switch state { 553 case model.StateNone: 554 s.checkNoneIndex(c, ctx, d, tblInfo, handle, indexCol, row) 555 case model.StateDeleteOnly: 556 s.checkDeleteOnlyIndex(c, ctx, d, tblInfo, handle, indexCol, row, isDropped) 557 case model.StateWriteOnly: 558 s.checkWriteOnlyIndex(c, ctx, d, tblInfo, handle, indexCol, row, isDropped) 559 case model.StateWriteReorganization, model.StateDeleteReorganization: 560 s.checkReorganizationIndex(c, ctx, d, tblInfo, handle, indexCol, row, isDropped) 561 case model.StatePublic: 562 s.checkPublicIndex(c, ctx, d, tblInfo, handle, indexCol, row) 563 } 564 } 565 566 func (s *testIndexSuite) TestAddIndex(c *C) { 567 defer testleak.AfterTest(c)() 568 d := newDDL(s.store, nil, nil, 100*time.Millisecond) 569 tblInfo := testTableInfo(c, d, "t", 3) 570 ctx := testNewContext(c, d) 571 572 _, err := ctx.GetTxn(true) 573 c.Assert(err, IsNil) 574 575 testCreateTable(c, ctx, d, s.dbInfo, tblInfo) 576 577 t := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) 578 579 row := types.MakeDatums(int64(1), int64(2), int64(3)) 580 handle, err := t.AddRecord(ctx, row) 581 c.Assert(err, IsNil) 582 583 err = ctx.FinishTxn(false) 584 c.Assert(err, IsNil) 585 586 checkOK := false 587 588 tc := &testDDLCallback{} 589 tc.onJobUpdated = func(job *model.Job) { 590 if checkOK { 591 return 592 } 593 594 t := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) 595 indexCol := getIndex(t, "c1") 596 if indexCol == nil { 597 return 598 } 599 600 s.checkAddOrDropIndex(c, indexCol.State, d, tblInfo, handle, indexCol, row, false) 601 602 if indexCol.State == model.StatePublic { 603 checkOK = true 604 } 605 } 606 607 d.hook = tc 608 609 // Use local ddl for callback test. 610 s.d.close() 611 612 d.close() 613 d.start() 614 615 job := testCreateIndex(c, ctx, d, s.dbInfo, tblInfo, true, "c1_uni", "c1") 616 testCheckJobDone(c, d, job, true) 617 618 job = testCreateIndex(c, ctx, d, s.dbInfo, tblInfo, true, "c1", "c1") 619 testCheckJobDone(c, d, job, true) 620 621 _, err = ctx.GetTxn(true) 622 c.Assert(err, IsNil) 623 624 job = testDropTable(c, ctx, d, s.dbInfo, tblInfo) 625 testCheckJobDone(c, d, job, false) 626 627 err = ctx.FinishTxn(false) 628 c.Assert(err, IsNil) 629 630 d.close() 631 s.d.start() 632 } 633 634 func (s *testIndexSuite) TestDropIndex(c *C) { 635 defer testleak.AfterTest(c)() 636 d := newDDL(s.store, nil, nil, 100*time.Millisecond) 637 tblInfo := testTableInfo(c, d, "t", 3) 638 ctx := testNewContext(c, d) 639 640 _, err := ctx.GetTxn(true) 641 c.Assert(err, IsNil) 642 643 testCreateTable(c, ctx, d, s.dbInfo, tblInfo) 644 645 t := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) 646 647 row := types.MakeDatums(int64(1), int64(2), int64(3)) 648 handle, err := t.AddRecord(ctx, row) 649 c.Assert(err, IsNil) 650 651 err = ctx.FinishTxn(false) 652 c.Assert(err, IsNil) 653 654 job := testCreateIndex(c, ctx, s.d, s.dbInfo, tblInfo, true, "c1_uni", "c1") 655 testCheckJobDone(c, d, job, true) 656 657 err = ctx.FinishTxn(false) 658 c.Assert(err, IsNil) 659 660 checkOK := false 661 oldIndexCol := &column.IndexedCol{} 662 663 tc := &testDDLCallback{} 664 tc.onJobUpdated = func(job *model.Job) { 665 if checkOK { 666 return 667 } 668 669 t := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) 670 indexCol := getIndex(t, "c1") 671 if indexCol == nil { 672 s.checkAddOrDropIndex(c, model.StateNone, d, tblInfo, handle, oldIndexCol, row, true) 673 checkOK = true 674 return 675 } 676 677 s.checkAddOrDropIndex(c, indexCol.State, d, tblInfo, handle, indexCol, row, true) 678 oldIndexCol = indexCol 679 } 680 681 d.hook = tc 682 683 // Use local ddl for callback test. 684 s.d.close() 685 686 d.close() 687 d.start() 688 689 job = testDropIndex(c, ctx, d, s.dbInfo, tblInfo, "c1_uni") 690 testCheckJobDone(c, d, job, false) 691 692 _, err = ctx.GetTxn(true) 693 c.Assert(err, IsNil) 694 695 job = testDropTable(c, ctx, d, s.dbInfo, tblInfo) 696 testCheckJobDone(c, d, job, false) 697 698 err = ctx.FinishTxn(false) 699 c.Assert(err, IsNil) 700 701 d.close() 702 s.d.start() 703 } 704 705 func (s *testIndexSuite) TestAddIndexWithNullColumn(c *C) { 706 defer testleak.AfterTest(c)() 707 d := newDDL(s.store, nil, nil, 100*time.Millisecond) 708 tblInfo := testTableInfo(c, d, "t", 3) 709 // Change c2.DefaultValue to nil 710 tblInfo.Columns[1].DefaultValue = nil 711 ctx := testNewContext(c, d) 712 713 _, err := ctx.GetTxn(true) 714 c.Assert(err, IsNil) 715 716 testCreateTable(c, ctx, d, s.dbInfo, tblInfo) 717 718 t := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) 719 720 // c2 is nil, which is not stored in kv. 721 row := types.MakeDatums(int64(1), nil, int(2)) 722 handle, err := t.AddRecord(ctx, row) 723 c.Assert(err, IsNil) 724 725 err = ctx.FinishTxn(false) 726 c.Assert(err, IsNil) 727 728 checkOK := false 729 730 tc := &testDDLCallback{} 731 tc.onJobUpdated = func(job *model.Job) { 732 if checkOK { 733 return 734 } 735 736 t := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) 737 // Add index on c2. 738 indexCol := getIndex(t, "c2") 739 if indexCol == nil { 740 return 741 } 742 s.checkAddOrDropIndex(c, indexCol.State, d, tblInfo, handle, indexCol, row, false) 743 if indexCol.State == model.StatePublic { 744 checkOK = true 745 } 746 } 747 748 d.hook = tc 749 750 // Use local ddl for callback test. 751 s.d.close() 752 d.close() 753 d.start() 754 755 job := testCreateIndex(c, ctx, d, s.dbInfo, tblInfo, true, "c2", "c2") 756 testCheckJobDone(c, d, job, true) 757 758 _, err = ctx.GetTxn(true) 759 c.Assert(err, IsNil) 760 761 job = testDropTable(c, ctx, d, s.dbInfo, tblInfo) 762 testCheckJobDone(c, d, job, false) 763 764 err = ctx.FinishTxn(false) 765 c.Assert(err, IsNil) 766 767 d.close() 768 s.d.start() 769 }