func checkIndexAndRecord(txn kv.Transaction, t table.Table, idx table.Index) error { it, err := idx.SeekFirst(txn) if err != nil { return errors.Trace(err) } defer it.Close() cols := make([]*table.Column, len(idx.Meta().Columns)) for i, col := range idx.Meta().Columns { cols[i] = t.Cols()[col.Offset] } for { vals1, h, err := it.Next() if terror.ErrorEqual(err, io.EOF) { break } else if err != nil { return errors.Trace(err) } vals2, err := rowWithCols(txn, t, h, cols) if terror.ErrorEqual(err, kv.ErrNotExist) { record := &RecordData{Handle: h, Values: vals1} err = errDateNotEqual.Gen("index:%v != record:%v", record, nil) } if err != nil { return errors.Trace(err) } if !reflect.DeepEqual(vals1, vals2) { record1 := &RecordData{Handle: h, Values: vals1} record2 := &RecordData{Handle: h, Values: vals2} return errDateNotEqual.Gen("index:%v != record:%v", record1, record2) } } return nil }
func (s *testDBSuite) testAddIndex(c *C) { done := make(chan struct{}, 1) num := 100 // first add some rows for i := 0; i < num; i++ { s.mustExec(c, "insert into t1 values (?, ?, ?)", i, i, i) } go func() { s.mustExec(c, "create index c3_index on t1 (c3)") done <- struct{}{} }() deletedKeys := make(map[int]struct{}) ticker := time.NewTicker(s.lease / 2) defer ticker.Stop() LOOP: for { select { case <-done: break LOOP case <-ticker.C: step := 10 // delete some rows, and add some data for i := num; i < num+step; i++ { n := rand.Intn(num) deletedKeys[n] = struct{}{} s.mustExec(c, "delete from t1 where c1 = ?", n) s.mustExec(c, "insert into t1 values (?, ?, ?)", i, i, i) } num += step } } // get exists keys keys := make([]int, 0, num) for i := 0; i < num; i++ { if _, ok := deletedKeys[i]; ok { continue } keys = append(keys, i) } // test index key for _, key := range keys { rows := s.mustQuery(c, "select c1 from t1 where c3 = ?", key) matchRows(c, rows, [][]interface{}{{key}}) } // test delete key not in index for key := range deletedKeys { rows := s.mustQuery(c, "select c1 from t1 where c3 = ?", key) matchRows(c, rows, nil) } // test index range for i := 0; i < 100; i++ { index := rand.Intn(len(keys) - 3) rows := s.mustQuery(c, "select c1 from t1 where c3 >= ? limit 3", keys[index]) matchRows(c, rows, [][]interface{}{{keys[index]}, {keys[index+1]}, {keys[index+2]}}) } // TODO: support explain in future. //rows := s.mustQuery(c, "explain select c1 from t1 where c3 >= 100") //ay := dumpRows(c, rows) //c.Assert(strings.Contains(fmt.Sprintf("%v", ay), "c3_index"), IsTrue) // get all row handles ctx := s.s.(context.Context) t := s.testGetTable(c, "t1") handles := make(map[int64]struct{}) err := t.IterRecords(ctx, t.FirstKey(), t.Cols(), func(h int64, data []types.Datum, cols []*table.Column) (bool, error) { handles[h] = struct{}{} return true, nil }) c.Assert(err, IsNil) // check in index var nidx table.Index for _, tidx := range t.Indices() { if tidx.Meta().Name.L == "c3_index" { nidx = tidx break } } // Make sure there is index with name c3_index c.Assert(nidx, NotNil) c.Assert(nidx.Meta().ID, Greater, int64(0)) txn, err := ctx.GetTxn(true) c.Assert(err, IsNil) defer ctx.RollbackTxn() it, err := nidx.SeekFirst(txn) c.Assert(err, IsNil) defer it.Close() for { _, h, err := it.Next() if terror.ErrorEqual(err, io.EOF) { break } c.Assert(err, IsNil) _, ok := handles[h] c.Assert(ok, IsTrue) delete(handles, h) } c.Assert(handles, HasLen, 0) }