diff --git a/executor/executor_test.go b/executor/executor_test.go index 1ae0306ad0911..988aa248a89de 100644 --- a/executor/executor_test.go +++ b/executor/executor_test.go @@ -274,6 +274,41 @@ func (s *testSuite) TestAdmin(c *C) { tk.MustExec("ALTER TABLE t1 ADD INDEX idx3 (c4);") tk.MustExec("admin check table t1;") + // For add index on virtual column + tk.MustExec("drop table if exists t1;") + tk.MustExec(`create table t1 ( + a int as (JSON_EXTRACT(k,'$.a')), + c double as (JSON_EXTRACT(k,'$.c')), + d decimal(20,10) as (JSON_EXTRACT(k,'$.d')), + e char(10) as (JSON_EXTRACT(k,'$.e')), + f date as (JSON_EXTRACT(k,'$.f')), + g time as (JSON_EXTRACT(k,'$.g')), + h datetime as (JSON_EXTRACT(k,'$.h')), + i timestamp as (JSON_EXTRACT(k,'$.i')), + j year as (JSON_EXTRACT(k,'$.j')), + k json);`) + + tk.MustExec("insert into t1 set k='{\"a\": 100,\"c\":1.234,\"d\":1.2340000000,\"e\":\"abcdefg\",\"f\":\"2018-09-28\",\"g\":\"12:59:59\",\"h\":\"2018-09-28 12:59:59\",\"i\":\"2018-09-28 16:40:33\",\"j\":\"2018\"}';") + tk.MustExec("alter table t1 add index idx_a(a);") + tk.MustExec("alter table t1 add index idx_c(c);") + tk.MustExec("alter table t1 add index idx_d(d);") + tk.MustExec("alter table t1 add index idx_e(e);") + tk.MustExec("alter table t1 add index idx_f(f);") + tk.MustExec("alter table t1 add index idx_g(g);") + tk.MustExec("alter table t1 add index idx_h(h);") + tk.MustExec("alter table t1 add index idx_j(j);") + tk.MustExec("alter table t1 add index idx_i(i);") + tk.MustExec("alter table t1 add index idx_m(a,c,d,e,f,g,h,i,j);") + tk.MustExec("admin check table t1;") + + tk.MustExec("drop table if exists t1;") + tk.MustExec("CREATE TABLE t1 (c1 int);") + tk.MustExec("INSERT INTO t1 SET c1 = 1;") + tk.MustExec("ALTER TABLE t1 ADD COLUMN cc1 CHAR(36) NULL DEFAULT '';") + tk.MustExec("ALTER TABLE t1 ADD COLUMN cc2 VARCHAR(36) NULL DEFAULT ''") + tk.MustExec("ALTER TABLE t1 ADD INDEX idx1 (cc1);") + tk.MustExec("ALTER TABLE t1 ADD INDEX idx2 (cc2);") + tk.MustExec("admin check table t1;") } func (s *testSuite) fillData(tk *testkit.TestKit, table string) { diff --git a/types/datum_test.go b/types/datum_test.go index b6a3d0bfb49fb..fc925ee7ecc5b 100644 --- a/types/datum_test.go +++ b/types/datum_test.go @@ -14,6 +14,8 @@ package types import ( + "reflect" + "testing" "time" . "github.com/pingcap/check" @@ -362,3 +364,39 @@ func (ts *testDatumSuite) TestCopyDatum(c *C) { } } } + +func prepareCompareDatums() ([]Datum, []Datum) { + vals := make([]Datum, 0, 5) + vals = append(vals, NewIntDatum(1)) + vals = append(vals, NewFloat64Datum(1.23)) + vals = append(vals, NewStringDatum("abcde")) + vals = append(vals, NewDecimalDatum(NewDecFromStringForTest("1.2345"))) + vals = append(vals, NewTimeDatum(Time{Time: FromGoTime(time.Date(2018, 3, 8, 16, 1, 0, 315313000, time.UTC)), Fsp: 6, Type: mysql.TypeTimestamp})) + + vals1 := make([]Datum, 0, 5) + vals1 = append(vals1, NewIntDatum(1)) + vals1 = append(vals1, NewFloat64Datum(1.23)) + vals1 = append(vals1, NewStringDatum("abcde")) + vals1 = append(vals1, NewDecimalDatum(NewDecFromStringForTest("1.2345"))) + vals1 = append(vals1, NewTimeDatum(Time{Time: FromGoTime(time.Date(2018, 3, 8, 16, 1, 0, 315313000, time.UTC)), Fsp: 6, Type: mysql.TypeTimestamp})) + return vals, vals1 +} + +func BenchmarkCompareDatum(b *testing.B) { + vals, vals1 := prepareCompareDatums() + sc := new(stmtctx.StatementContext) + b.ResetTimer() + for i := 0; i < b.N; i++ { + for j, v := range vals { + v.CompareDatum(sc, &vals1[j]) + } + } +} + +func BenchmarkCompareDatumByReflect(b *testing.B) { + vals, vals1 := prepareCompareDatums() + b.ResetTimer() + for i := 0; i < b.N; i++ { + reflect.DeepEqual(vals, vals1) + } +} diff --git a/util/admin/admin.go b/util/admin/admin.go index 3e767f73021d3..325d09df98fc4 100644 --- a/util/admin/admin.go +++ b/util/admin/admin.go @@ -16,7 +16,6 @@ package admin import ( "fmt" "io" - "reflect" "sort" "github.com/pingcap/tidb/expression" @@ -353,7 +352,7 @@ func checkIndexAndRecord(sessCtx sessionctx.Context, txn kv.Transaction, t table if err != nil { return errors.Trace(err) } - sc := new(stmtctx.StatementContext) + sc := sessCtx.GetSessionVars().StmtCtx for { vals1, h, err := it.Next() if terror.ErrorEqual(err, io.EOF) { @@ -391,15 +390,9 @@ func compareDatumSlice(sc *stmtctx.StatementContext, val1s, val2s []types.Datum) return false } for i, v := range val1s { - if v.Kind() == types.KindMysqlDecimal { - res, err := v.CompareDatum(sc, &val2s[i]) - if err != nil || res != 0 { - return false - } - } else { - if !reflect.DeepEqual(v, val2s[i]) { - return false - } + res, err := v.CompareDatum(sc, &val2s[i]) + if err != nil || res != 0 { + return false } } return true @@ -523,6 +516,7 @@ func CompareTableRecord(sessCtx sessionctx.Context, txn kv.Transaction, t table. } startKey := t.RecordKey(0) + sc := sessCtx.GetSessionVars().StmtCtx filterFunc := func(h int64, vals []types.Datum, cols []*table.Column) (bool, error) { vals2, ok := m[h] if !ok { @@ -534,7 +528,7 @@ func CompareTableRecord(sessCtx sessionctx.Context, txn kv.Transaction, t table. return true, nil } - if !reflect.DeepEqual(vals, vals2) { + if !compareDatumSlice(sc, vals, vals2) { record1 := &RecordData{Handle: h, Values: vals2} record2 := &RecordData{Handle: h, Values: vals} return false, ErrDataInConsistent.GenWithStack("data:%#v != record:%#v", record1, record2)