func checkRecordAndIndex(txn kv.Transaction, t table.Table, idx *column.IndexedCol) error { cols := make([]*column.Col, len(idx.Columns)) for i, col := range idx.Columns { cols[i] = t.Cols()[col.Offset] } startKey := t.RecordKey(0, nil) kvIndex := kv.NewKVIndex(t.IndexPrefix(), idx.Name.L, idx.ID, idx.Unique) filterFunc := func(h1 int64, vals1 []interface{}, cols []*column.Col) (bool, error) { isExist, h2, err := kvIndex.Exist(txn, vals1, h1) if terror.ErrorEqual(err, kv.ErrKeyExists) { record1 := &RecordData{Handle: h1, Values: vals1} record2 := &RecordData{Handle: h2, Values: vals1} return false, errors.Errorf("index:%v != record:%v", record2, record1) } if err != nil { return false, errors.Trace(err) } if !isExist { record := &RecordData{Handle: h1, Values: vals1} return false, errors.Errorf("index:%v != record:%v", nil, record) } return true, nil } err := t.IterRecords(txn, startKey, cols, filterFunc) if err != nil { return errors.Trace(err) } return nil }
func (d *ddl) dropTableIndex(t table.Table, indexInfo *model.IndexInfo) error { prefix := kv.GenIndexPrefix(t.IndexPrefix(), indexInfo.Name.L) prefixBytes := []byte(prefix) keys := make([]string, maxBatchSize) for { keys := keys[0:0] err := kv.RunInNewTxn(d.store, false, func(txn kv.Transaction) error { iter, err := txn.Seek(prefixBytes) if err != nil { return errors.Trace(err) } defer iter.Close() for i := 0; i < maxBatchSize; i++ { if iter.Valid() && strings.HasPrefix(iter.Key(), prefix) { keys = append(keys, iter.Key()) err = iter.Next() if err != nil { return errors.Trace(err) } } else { break } } return nil }) // if err or delete no keys, return. if err != nil || len(keys) == 0 { return errors.Trace(err) } // delete index key one by one for _, key := range keys { err = kv.RunInNewTxn(d.store, true, func(txn kv.Transaction) error { if err := d.isReorgRunnable(txn); err != nil { return errors.Trace(err) } err1 := txn.Delete([]byte(key)) // if key doesn't exist, skip this error. if err1 != nil && !terror.ErrorEqual(err1, kv.ErrNotExist) { return errors.Trace(err1) } return nil }) if err != nil { return errors.Trace(err) } } } }
func (d *ddl) buildIndex(ctx context.Context, t table.Table, idxInfo *model.IndexInfo, unique bool) error { firstKey := t.FirstKey() prefix := t.KeyPrefix() txn, err := ctx.GetTxn(false) if err != nil { return errors.Trace(err) } it, err := txn.Seek([]byte(firstKey)) if err != nil { return errors.Trace(err) } defer it.Close() for it.Valid() && strings.HasPrefix(it.Key(), prefix) { var err error handle, err := util.DecodeHandleFromRowKey(it.Key()) log.Info("building index...", handle) if err != nil { return errors.Trace(err) } // TODO: v is timestamp ? // fetch datas cols := t.Cols() var vals []interface{} for _, v := range idxInfo.Columns { var ( data []byte val interface{} ) col := cols[v.Offset] k := t.RecordKey(handle, col) data, err = txn.Get([]byte(k)) if err != nil { return errors.Trace(err) } val, err = t.DecodeValue(data, col) if err != nil { return errors.Trace(err) } vals = append(vals, val) } // build index kvX := kv.NewKVIndex(t.IndexPrefix(), idxInfo.Name.L, unique) err = kvX.Create(txn, vals, handle) if err != nil { return errors.Trace(err) } rk := []byte(t.RecordKey(handle, nil)) it, err = kv.NextUntil(it, util.RowKeyPrefixFilter(rk)) if err != nil { return errors.Trace(err) } } return nil }
func (d *ddl) backfillTableIndex(t table.Table, indexInfo *model.IndexInfo, handles []int64, reorgInfo *reorgInfo) error { kvX := kv.NewKVIndex(t.IndexPrefix(), indexInfo.Name.L, indexInfo.ID, indexInfo.Unique) for _, handle := range handles { log.Debug("[ddl] building index...", handle) err := kv.RunInNewTxn(d.store, true, func(txn kv.Transaction) error { if err := d.isReorgRunnable(txn); err != nil { return errors.Trace(err) } // first check row exists exist, err := checkRowExist(txn, t, handle) if err != nil { return errors.Trace(err) } else if !exist { // row doesn't exist, skip it. return nil } var vals []interface{} vals, err = fetchRowColVals(txn, t, handle, indexInfo) if err != nil { return errors.Trace(err) } exist, _, err = kvX.Exist(txn, vals, handle) if err != nil { return errors.Trace(err) } else if exist { // index already exists, skip it. return nil } err = lockRow(txn, t, handle) if err != nil { return errors.Trace(err) } // create the index. err = kvX.Create(txn, vals, handle) if err != nil { return errors.Trace(err) } // update reorg next handle return errors.Trace(reorgInfo.UpdateHandle(txn, handle)) }) if err != nil { return errors.Trace(err) } } return nil }
func (d *ddl) dropTableData(t table.Table) error { // delete table data err := d.delKeysWithPrefix(t.RecordPrefix()) if err != nil { return errors.Trace(err) } // delete table index err = d.delKeysWithPrefix(t.IndexPrefix()) return errors.Trace(err) }
func checkIndexAndRecord(txn kv.Transaction, t table.Table, idx *column.IndexedCol) error { kvIndex := kv.NewKVIndex(t.IndexPrefix(), idx.Name.L, idx.ID, idx.Unique) it, err := kvIndex.SeekFirst(txn) if err != nil { return errors.Trace(err) } defer it.Close() cols := make([]*column.Col, len(idx.Columns)) for i, col := range idx.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 := t.RowWithCols(txn, h, cols) if terror.ErrorEqual(err, kv.ErrNotExist) { record := &RecordData{Handle: h, Values: vals1} err = errors.Errorf("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 errors.Errorf("index:%v != record:%v", record1, record2) } } return nil }
func (d *ddl) dropTableIndex(t table.Table, indexInfo *model.IndexInfo) error { prefix := kv.GenIndexPrefix(t.IndexPrefix(), indexInfo.ID) err := d.delKeysWithPrefix(prefix) return errors.Trace(err) }