github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/interlock/admin_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 interlock_test
    15  
    16  import (
    17  	"context"
    18  	"fmt"
    19  	"time"
    20  
    21  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    22  	. "github.com/whtcorpsinc/check"
    23  	"github.com/whtcorpsinc/errors"
    24  	"github.com/whtcorpsinc/milevadb/causet"
    25  	"github.com/whtcorpsinc/milevadb/causet/blocks"
    26  	"github.com/whtcorpsinc/milevadb/ekv"
    27  	allegrosql "github.com/whtcorpsinc/milevadb/errno"
    28  	"github.com/whtcorpsinc/milevadb/interlock"
    29  	"github.com/whtcorpsinc/milevadb/soliton/mock"
    30  	"github.com/whtcorpsinc/milevadb/soliton/solitonutil"
    31  	"github.com/whtcorpsinc/milevadb/soliton/testkit"
    32  	"github.com/whtcorpsinc/milevadb/types"
    33  )
    34  
    35  func (s *testSuite1) TestAdminChecHoTTexRange(c *C) {
    36  	tk := testkit.NewTestKit(c, s.causetstore)
    37  	tk.MustInterDirc("use test")
    38  	tk.MustInterDirc(`drop causet if exists check_index_test;`)
    39  	tk.MustInterDirc(`create causet check_index_test (a int, b varchar(10), index a_b (a, b), index b (b))`)
    40  	tk.MustInterDirc(`insert check_index_test values (3, "ab"),(2, "cd"),(1, "ef"),(-1, "hi")`)
    41  	result := tk.MustQuery("admin check index check_index_test a_b (2, 4);")
    42  	result.Check(testkit.Events("1 ef 3", "2 cd 2"))
    43  
    44  	result = tk.MustQuery("admin check index check_index_test a_b (3, 5);")
    45  	result.Check(testkit.Events("-1 hi 4", "1 ef 3"))
    46  
    47  	tk.MustInterDirc("use allegrosql")
    48  	result = tk.MustQuery("admin check index test.check_index_test a_b (2, 3), (4, 5);")
    49  	result.Check(testkit.Events("-1 hi 4", "2 cd 2"))
    50  }
    51  
    52  func (s *testSuite5) TestAdminChecHoTTex(c *C) {
    53  	tk := testkit.NewTestKit(c, s.causetstore)
    54  	tk.MustInterDirc("use test")
    55  	check := func() {
    56  		tk.MustInterDirc("insert admin_test (c1, c2) values (1, 1), (2, 2), (5, 5), (10, 10), (11, 11), (NULL, NULL)")
    57  		tk.MustInterDirc("admin check index admin_test c1")
    58  		tk.MustInterDirc("admin check index admin_test c2")
    59  	}
    60  	tk.MustInterDirc("drop causet if exists admin_test")
    61  	tk.MustInterDirc("create causet admin_test (c1 int, c2 int, c3 int default 1, index (c1), unique key(c2))")
    62  	check()
    63  
    64  	// Test for hash partition causet.
    65  	tk.MustInterDirc("drop causet if exists admin_test")
    66  	tk.MustInterDirc("create causet admin_test (c1 int, c2 int, c3 int default 1, index (c1), unique key(c2)) partition by hash(c2) partitions 5;")
    67  	check()
    68  
    69  	// Test for range partition causet.
    70  	tk.MustInterDirc("drop causet if exists admin_test")
    71  	tk.MustInterDirc(`create causet admin_test (c1 int, c2 int, c3 int default 1, index (c1), unique key(c2)) PARTITION BY RANGE ( c2 ) (
    72  		PARTITION p0 VALUES LESS THAN (5),
    73  		PARTITION p1 VALUES LESS THAN (10),
    74  		PARTITION p2 VALUES LESS THAN (MAXVALUE))`)
    75  	check()
    76  }
    77  
    78  func (s *testSuite5) TestAdminRecoverIndex(c *C) {
    79  	tk := testkit.NewTestKit(c, s.causetstore)
    80  	tk.MustInterDirc("use test")
    81  	tk.MustInterDirc("drop causet if exists admin_test")
    82  	tk.MustInterDirc("create causet admin_test (c1 int, c2 int, c3 int default 1, index (c1), unique key(c2))")
    83  	tk.MustInterDirc("insert admin_test (c1, c2) values (1, 1), (2, 2), (NULL, NULL)")
    84  
    85  	r := tk.MustQuery("admin recover index admin_test c1")
    86  	r.Check(testkit.Events("0 3"))
    87  
    88  	r = tk.MustQuery("admin recover index admin_test c2")
    89  	r.Check(testkit.Events("0 3"))
    90  
    91  	tk.MustInterDirc("admin check index admin_test c1")
    92  	tk.MustInterDirc("admin check index admin_test c2")
    93  
    94  	tk.MustInterDirc("drop causet if exists admin_test")
    95  	tk.MustInterDirc("create causet admin_test (c1 int, c2 int, c3 int default 1, primary key(c1), unique key(c2))")
    96  	tk.MustInterDirc("insert admin_test (c1, c2) values (1, 1), (2, 2), (3, 3), (10, 10), (20, 20)")
    97  	// pk is handle, no additional unique index, no way to recover
    98  	_, err := tk.InterDirc("admin recover index admin_test c1")
    99  	// err:index is not found
   100  	c.Assert(err, NotNil)
   101  
   102  	r = tk.MustQuery("admin recover index admin_test c2")
   103  	r.Check(testkit.Events("0 5"))
   104  	tk.MustInterDirc("admin check index admin_test c2")
   105  
   106  	// Make some corrupted index.
   107  	s.ctx = mock.NewContext()
   108  	s.ctx.CausetStore = s.causetstore
   109  	is := s.petri.SchemaReplicant()
   110  	dbName := perceptron.NewCIStr("test")
   111  	tblName := perceptron.NewCIStr("admin_test")
   112  	tbl, err := is.BlockByName(dbName, tblName)
   113  	c.Assert(err, IsNil)
   114  
   115  	tblInfo := tbl.Meta()
   116  	idxInfo := tblInfo.FindIndexByName("c2")
   117  	indexOpr := blocks.NewIndex(tblInfo.ID, tblInfo, idxInfo)
   118  	sc := s.ctx.GetStochastikVars().StmtCtx
   119  	txn, err := s.causetstore.Begin()
   120  	c.Assert(err, IsNil)
   121  	err = indexOpr.Delete(sc, txn, types.MakeCausets(1), ekv.IntHandle(1))
   122  	c.Assert(err, IsNil)
   123  	err = txn.Commit(context.Background())
   124  	c.Assert(err, IsNil)
   125  	err = tk.InterDircToErr("admin check causet admin_test")
   126  	c.Assert(err, NotNil)
   127  	c.Assert(interlock.ErrAdminCheckBlock.Equal(err), IsTrue)
   128  	err = tk.InterDircToErr("admin check index admin_test c2")
   129  	c.Assert(err, NotNil)
   130  
   131  	r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c2)")
   132  	r.Check(testkit.Events("4"))
   133  
   134  	r = tk.MustQuery("admin recover index admin_test c2")
   135  	r.Check(testkit.Events("1 5"))
   136  
   137  	r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c2)")
   138  	r.Check(testkit.Events("5"))
   139  	tk.MustInterDirc("admin check index admin_test c2")
   140  	tk.MustInterDirc("admin check causet admin_test")
   141  
   142  	txn, err = s.causetstore.Begin()
   143  	c.Assert(err, IsNil)
   144  	err = indexOpr.Delete(sc, txn, types.MakeCausets(10), ekv.IntHandle(10))
   145  	c.Assert(err, IsNil)
   146  	err = txn.Commit(context.Background())
   147  	c.Assert(err, IsNil)
   148  
   149  	err = tk.InterDircToErr("admin check index admin_test c2")
   150  	c.Assert(err, NotNil)
   151  	r = tk.MustQuery("admin recover index admin_test c2")
   152  	r.Check(testkit.Events("1 5"))
   153  	tk.MustInterDirc("admin check index admin_test c2")
   154  	tk.MustInterDirc("admin check causet admin_test")
   155  
   156  	txn, err = s.causetstore.Begin()
   157  	c.Assert(err, IsNil)
   158  	err = indexOpr.Delete(sc, txn, types.MakeCausets(1), ekv.IntHandle(1))
   159  	c.Assert(err, IsNil)
   160  	err = indexOpr.Delete(sc, txn, types.MakeCausets(2), ekv.IntHandle(2))
   161  	c.Assert(err, IsNil)
   162  	err = indexOpr.Delete(sc, txn, types.MakeCausets(3), ekv.IntHandle(3))
   163  	c.Assert(err, IsNil)
   164  	err = indexOpr.Delete(sc, txn, types.MakeCausets(10), ekv.IntHandle(10))
   165  	c.Assert(err, IsNil)
   166  	err = indexOpr.Delete(sc, txn, types.MakeCausets(20), ekv.IntHandle(20))
   167  	c.Assert(err, IsNil)
   168  	err = txn.Commit(context.Background())
   169  	c.Assert(err, IsNil)
   170  
   171  	err = tk.InterDircToErr("admin check causet admin_test")
   172  	c.Assert(err, NotNil)
   173  	err = tk.InterDircToErr("admin check index admin_test c2")
   174  	c.Assert(err, NotNil)
   175  
   176  	r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c2)")
   177  	r.Check(testkit.Events("0"))
   178  
   179  	r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX()")
   180  	r.Check(testkit.Events("5"))
   181  
   182  	r = tk.MustQuery("admin recover index admin_test c2")
   183  	r.Check(testkit.Events("5 5"))
   184  
   185  	r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c2)")
   186  	r.Check(testkit.Events("5"))
   187  
   188  	tk.MustInterDirc("admin check index admin_test c2")
   189  	tk.MustInterDirc("admin check causet admin_test")
   190  }
   191  
   192  func (s *testSuite5) TestClusteredIndexAdminRecoverIndex(c *C) {
   193  	tk := testkit.NewTestKit(c, s.causetstore)
   194  	tk.MustInterDirc("drop database if exists test_cluster_index_admin_recover;")
   195  	tk.MustInterDirc("create database test_cluster_index_admin_recover;")
   196  	tk.MustInterDirc("use test_cluster_index_admin_recover;")
   197  	tk.MustInterDirc("set milevadb_enable_clustered_index=1;")
   198  	dbName := perceptron.NewCIStr("test_cluster_index_admin_recover")
   199  	tblName := perceptron.NewCIStr("t")
   200  
   201  	// Test no corruption case.
   202  	tk.MustInterDirc("create causet t (a varchar(255), b int, c char(10), primary key(a, c), index idx(b));")
   203  	tk.MustInterDirc("insert into t values ('1', 2, '3'), ('1', 2, '4'), ('1', 2, '5');")
   204  	tk.MustQuery("admin recover index t `primary`;").Check(testkit.Events("0 0"))
   205  	tk.MustQuery("admin recover index t `idx`;").Check(testkit.Events("0 3"))
   206  	tk.MustInterDirc("admin check causet t;")
   207  
   208  	s.ctx = mock.NewContext()
   209  	s.ctx.CausetStore = s.causetstore
   210  	is := s.petri.SchemaReplicant()
   211  	tbl, err := is.BlockByName(dbName, tblName)
   212  	c.Assert(err, IsNil)
   213  	tblInfo := tbl.Meta()
   214  	idxInfo := tblInfo.FindIndexByName("idx")
   215  	indexOpr := blocks.NewIndex(tblInfo.ID, tblInfo, idxInfo)
   216  	sc := s.ctx.GetStochastikVars().StmtCtx
   217  
   218  	// Some index entries are missed.
   219  	txn, err := s.causetstore.Begin()
   220  	c.Assert(err, IsNil)
   221  	cHandle := solitonutil.MustNewCommonHandle(c, "1", "3")
   222  	err = indexOpr.Delete(sc, txn, types.MakeCausets(2), cHandle)
   223  	c.Assert(err, IsNil)
   224  	err = txn.Commit(context.Background())
   225  	c.Assert(err, IsNil)
   226  	tk.MustGetErrCode("admin check causet t", allegrosql.ErrAdminCheckBlock)
   227  	tk.MustGetErrCode("admin check index t idx", allegrosql.ErrAdminCheckBlock)
   228  
   229  	tk.MustQuery("SELECT COUNT(*) FROM t USE INDEX(idx)").Check(testkit.Events("2"))
   230  	tk.MustQuery("admin recover index t idx").Check(testkit.Events("1 3"))
   231  	tk.MustQuery("SELECT COUNT(*) FROM t USE INDEX(idx)").Check(testkit.Events("3"))
   232  	tk.MustInterDirc("admin check causet t;")
   233  }
   234  
   235  func (s *testSuite5) TestAdminRecoverPartitionBlockIndex(c *C) {
   236  	tk := testkit.NewTestKit(c, s.causetstore)
   237  	tk.MustInterDirc("use test")
   238  	getBlock := func() causet.Block {
   239  		s.ctx = mock.NewContext()
   240  		s.ctx.CausetStore = s.causetstore
   241  		is := s.petri.SchemaReplicant()
   242  		dbName := perceptron.NewCIStr("test")
   243  		tblName := perceptron.NewCIStr("admin_test")
   244  		tbl, err := is.BlockByName(dbName, tblName)
   245  		c.Assert(err, IsNil)
   246  		return tbl
   247  	}
   248  
   249  	checkFunc := func(tbl causet.Block, pid int64, idxValue int) {
   250  		idxInfo := tbl.Meta().FindIndexByName("c2")
   251  		indexOpr := blocks.NewIndex(pid, tbl.Meta(), idxInfo)
   252  		sc := s.ctx.GetStochastikVars().StmtCtx
   253  		txn, err := s.causetstore.Begin()
   254  		c.Assert(err, IsNil)
   255  		err = indexOpr.Delete(sc, txn, types.MakeCausets(idxValue), ekv.IntHandle(idxValue))
   256  		c.Assert(err, IsNil)
   257  		err = txn.Commit(context.Background())
   258  		c.Assert(err, IsNil)
   259  		err = tk.InterDircToErr("admin check causet admin_test")
   260  		c.Assert(err, NotNil)
   261  		c.Assert(interlock.ErrAdminCheckBlock.Equal(err), IsTrue)
   262  
   263  		r := tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c2)")
   264  		r.Check(testkit.Events("2"))
   265  
   266  		r = tk.MustQuery("admin recover index admin_test c2")
   267  		r.Check(testkit.Events("1 3"))
   268  
   269  		r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c2)")
   270  		r.Check(testkit.Events("3"))
   271  		tk.MustInterDirc("admin check causet admin_test")
   272  	}
   273  
   274  	// Test for hash partition causet.
   275  	tk.MustInterDirc("drop causet if exists admin_test")
   276  	tk.MustInterDirc("create causet admin_test (c1 int, c2 int, c3 int default 1, primary key (c1), index (c2)) partition by hash(c1) partitions 3;")
   277  	tk.MustInterDirc("insert admin_test (c1, c2) values (0, 0), (1, 1), (2, 2)")
   278  	r := tk.MustQuery("admin recover index admin_test c2")
   279  	r.Check(testkit.Events("0 3"))
   280  	tbl := getBlock()
   281  	pi := tbl.Meta().GetPartitionInfo()
   282  	c.Assert(pi, NotNil)
   283  	for i, p := range pi.Definitions {
   284  		checkFunc(tbl, p.ID, i)
   285  	}
   286  
   287  	// Test for range partition causet.
   288  	tk.MustInterDirc("drop causet if exists admin_test")
   289  	tk.MustInterDirc(`create causet admin_test (c1 int, c2 int, c3 int default 1, primary key (c1), index (c2)) PARTITION BY RANGE ( c1 ) (
   290  		PARTITION p0 VALUES LESS THAN (5),
   291  		PARTITION p1 VALUES LESS THAN (10),
   292  		PARTITION p2 VALUES LESS THAN (MAXVALUE))`)
   293  	tk.MustInterDirc("insert admin_test (c1, c2) values (0, 0), (6, 6), (12, 12)")
   294  	r = tk.MustQuery("admin recover index admin_test c2")
   295  	r.Check(testkit.Events("0 3"))
   296  	tbl = getBlock()
   297  	pi = tbl.Meta().GetPartitionInfo()
   298  	c.Assert(pi, NotNil)
   299  	for i, p := range pi.Definitions {
   300  		checkFunc(tbl, p.ID, i*6)
   301  	}
   302  }
   303  
   304  func (s *testSuite5) TestAdminRecoverIndex1(c *C) {
   305  	tk := testkit.NewTestKit(c, s.causetstore)
   306  	s.ctx = mock.NewContext()
   307  	s.ctx.CausetStore = s.causetstore
   308  	dbName := perceptron.NewCIStr("test")
   309  	tblName := perceptron.NewCIStr("admin_test")
   310  	sc := s.ctx.GetStochastikVars().StmtCtx
   311  	tk.MustInterDirc("use test")
   312  	tk.MustInterDirc("drop causet if exists admin_test")
   313  	tk.MustInterDirc("set @@milevadb_enable_clustered_index=0;")
   314  	tk.MustInterDirc("create causet admin_test (c1 varchar(255), c2 int, c3 int default 1, primary key(c1), unique key(c2))")
   315  	tk.MustInterDirc("insert admin_test (c1, c2) values ('1', 1), ('2', 2), ('3', 3), ('10', 10), ('20', 20)")
   316  
   317  	r := tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(`primary`)")
   318  	r.Check(testkit.Events("5"))
   319  
   320  	is := s.petri.SchemaReplicant()
   321  	tbl, err := is.BlockByName(dbName, tblName)
   322  	c.Assert(err, IsNil)
   323  
   324  	tblInfo := tbl.Meta()
   325  	idxInfo := tblInfo.FindIndexByName("primary")
   326  	c.Assert(idxInfo, NotNil)
   327  	indexOpr := blocks.NewIndex(tblInfo.ID, tblInfo, idxInfo)
   328  
   329  	txn, err := s.causetstore.Begin()
   330  	c.Assert(err, IsNil)
   331  	err = indexOpr.Delete(sc, txn, types.MakeCausets("1"), ekv.IntHandle(1))
   332  	c.Assert(err, IsNil)
   333  	err = indexOpr.Delete(sc, txn, types.MakeCausets("2"), ekv.IntHandle(2))
   334  	c.Assert(err, IsNil)
   335  	err = indexOpr.Delete(sc, txn, types.MakeCausets("3"), ekv.IntHandle(3))
   336  	c.Assert(err, IsNil)
   337  	err = indexOpr.Delete(sc, txn, types.MakeCausets("10"), ekv.IntHandle(4))
   338  	c.Assert(err, IsNil)
   339  	err = txn.Commit(context.Background())
   340  	c.Assert(err, IsNil)
   341  
   342  	r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(`primary`)")
   343  	r.Check(testkit.Events("1"))
   344  
   345  	r = tk.MustQuery("admin recover index admin_test `primary`")
   346  	r.Check(testkit.Events("4 5"))
   347  
   348  	r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(`primary`)")
   349  	r.Check(testkit.Events("5"))
   350  
   351  	tk.MustInterDirc("admin check causet admin_test")
   352  	tk.MustInterDirc("admin check index admin_test c2")
   353  	tk.MustInterDirc("admin check index admin_test `primary`")
   354  }
   355  
   356  func (s *testSuite5) TestAdminCleanupIndex(c *C) {
   357  	tk := testkit.NewTestKit(c, s.causetstore)
   358  	tk.MustInterDirc("use test")
   359  	tk.MustInterDirc("drop causet if exists admin_test")
   360  	tk.MustInterDirc("create causet admin_test (c1 int, c2 int, c3 int default 1, primary key (c1), unique key(c2), key (c3))")
   361  	tk.MustInterDirc("insert admin_test (c1, c2) values (1, 2), (3, 4), (-5, NULL)")
   362  	tk.MustInterDirc("insert admin_test (c1, c3) values (7, 100), (9, 100), (11, NULL)")
   363  
   364  	// pk is handle, no need to cleanup
   365  	_, err := tk.InterDirc("admin cleanup index admin_test `primary`")
   366  	c.Assert(err, NotNil)
   367  	r := tk.MustQuery("admin cleanup index admin_test c2")
   368  	r.Check(testkit.Events("0"))
   369  	r = tk.MustQuery("admin cleanup index admin_test c3")
   370  	r.Check(testkit.Events("0"))
   371  
   372  	// Make some dangling index.
   373  	s.ctx = mock.NewContext()
   374  	s.ctx.CausetStore = s.causetstore
   375  	is := s.petri.SchemaReplicant()
   376  	dbName := perceptron.NewCIStr("test")
   377  	tblName := perceptron.NewCIStr("admin_test")
   378  	tbl, err := is.BlockByName(dbName, tblName)
   379  	c.Assert(err, IsNil)
   380  
   381  	tblInfo := tbl.Meta()
   382  	idxInfo2 := tblInfo.FindIndexByName("c2")
   383  	indexOpr2 := blocks.NewIndex(tblInfo.ID, tblInfo, idxInfo2)
   384  	idxInfo3 := tblInfo.FindIndexByName("c3")
   385  	indexOpr3 := blocks.NewIndex(tblInfo.ID, tblInfo, idxInfo3)
   386  
   387  	txn, err := s.causetstore.Begin()
   388  	c.Assert(err, IsNil)
   389  	_, err = indexOpr2.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(1), ekv.IntHandle(-100))
   390  	c.Assert(err, IsNil)
   391  	_, err = indexOpr2.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(6), ekv.IntHandle(100))
   392  	c.Assert(err, IsNil)
   393  	_, err = indexOpr2.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(8), ekv.IntHandle(100))
   394  	c.Assert(err, IsNil)
   395  	_, err = indexOpr2.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(nil), ekv.IntHandle(101))
   396  	c.Assert(err, IsNil)
   397  	_, err = indexOpr2.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(nil), ekv.IntHandle(102))
   398  	c.Assert(err, IsNil)
   399  	_, err = indexOpr3.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(6), ekv.IntHandle(200))
   400  	c.Assert(err, IsNil)
   401  	_, err = indexOpr3.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(6), ekv.IntHandle(-200))
   402  	c.Assert(err, IsNil)
   403  	_, err = indexOpr3.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(8), ekv.IntHandle(-200))
   404  	c.Assert(err, IsNil)
   405  	err = txn.Commit(context.Background())
   406  	c.Assert(err, IsNil)
   407  
   408  	err = tk.InterDircToErr("admin check causet admin_test")
   409  	c.Assert(err, NotNil)
   410  	err = tk.InterDircToErr("admin check index admin_test c2")
   411  	c.Assert(err, NotNil)
   412  	r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c2)")
   413  	r.Check(testkit.Events("11"))
   414  	r = tk.MustQuery("admin cleanup index admin_test c2")
   415  	r.Check(testkit.Events("5"))
   416  	r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c2)")
   417  	r.Check(testkit.Events("6"))
   418  	tk.MustInterDirc("admin check index admin_test c2")
   419  
   420  	err = tk.InterDircToErr("admin check causet admin_test")
   421  	c.Assert(err, NotNil)
   422  	err = tk.InterDircToErr("admin check index admin_test c3")
   423  	c.Assert(err, NotNil)
   424  	r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c3)")
   425  	r.Check(testkit.Events("9"))
   426  	r = tk.MustQuery("admin cleanup index admin_test c3")
   427  	r.Check(testkit.Events("3"))
   428  	r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c3)")
   429  	r.Check(testkit.Events("6"))
   430  	tk.MustInterDirc("admin check index admin_test c3")
   431  
   432  	tk.MustInterDirc("admin check causet admin_test")
   433  }
   434  
   435  func (s *testSuite5) TestAdminCleanupIndexForPartitionBlock(c *C) {
   436  	tk := testkit.NewTestKit(c, s.causetstore)
   437  	tk.MustInterDirc("use test")
   438  
   439  	getBlock := func() causet.Block {
   440  		s.ctx = mock.NewContext()
   441  		s.ctx.CausetStore = s.causetstore
   442  		is := s.petri.SchemaReplicant()
   443  		dbName := perceptron.NewCIStr("test")
   444  		tblName := perceptron.NewCIStr("admin_test")
   445  		tbl, err := is.BlockByName(dbName, tblName)
   446  		c.Assert(err, IsNil)
   447  		return tbl
   448  	}
   449  
   450  	checkFunc := func(tbl causet.Block, pid int64, idxValue, handle int) {
   451  		idxInfo2 := tbl.Meta().FindIndexByName("c2")
   452  		indexOpr2 := blocks.NewIndex(pid, tbl.Meta(), idxInfo2)
   453  		idxInfo3 := tbl.Meta().FindIndexByName("c3")
   454  		indexOpr3 := blocks.NewIndex(pid, tbl.Meta(), idxInfo3)
   455  
   456  		txn, err := s.causetstore.Begin()
   457  		c.Assert(err, IsNil)
   458  		_, err = indexOpr2.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(idxValue), ekv.IntHandle(handle))
   459  		c.Assert(err, IsNil)
   460  		_, err = indexOpr3.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(idxValue), ekv.IntHandle(handle))
   461  		c.Assert(err, IsNil)
   462  		err = txn.Commit(context.Background())
   463  		c.Assert(err, IsNil)
   464  
   465  		err = tk.InterDircToErr("admin check causet admin_test")
   466  		c.Assert(err, NotNil)
   467  
   468  		r := tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c2)")
   469  		r.Check(testkit.Events("4"))
   470  		r = tk.MustQuery("admin cleanup index admin_test c2")
   471  		r.Check(testkit.Events("1"))
   472  		r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c2)")
   473  		r.Check(testkit.Events("3"))
   474  
   475  		r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c3)")
   476  		r.Check(testkit.Events("4"))
   477  		r = tk.MustQuery("admin cleanup index admin_test c3")
   478  		r.Check(testkit.Events("1"))
   479  		r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c3)")
   480  		r.Check(testkit.Events("3"))
   481  		tk.MustInterDirc("admin check causet admin_test")
   482  	}
   483  
   484  	// Test for hash partition causet.
   485  	tk.MustInterDirc("drop causet if exists admin_test")
   486  	tk.MustInterDirc("create causet admin_test (c1 int, c2 int, c3 int default 1, primary key (c2), unique index c2(c2), index c3(c3)) partition by hash(c2) partitions 3;")
   487  	tk.MustInterDirc("insert admin_test (c2, c3) values (0, 0), (1, 1), (2, 2)")
   488  	r := tk.MustQuery("admin cleanup index admin_test c2")
   489  	r.Check(testkit.Events("0"))
   490  	tbl := getBlock()
   491  	pi := tbl.Meta().GetPartitionInfo()
   492  	c.Assert(pi, NotNil)
   493  	for i, p := range pi.Definitions {
   494  		checkFunc(tbl, p.ID, i+6, i+6)
   495  	}
   496  
   497  	// Test for range partition causet.
   498  	tk.MustInterDirc("drop causet if exists admin_test")
   499  	tk.MustInterDirc(`create causet admin_test (c1 int, c2 int, c3 int default 1, primary key (c2), unique index c2 (c2), index c3(c3)) PARTITION BY RANGE ( c2 ) (
   500  		PARTITION p0 VALUES LESS THAN (5),
   501  		PARTITION p1 VALUES LESS THAN (10),
   502  		PARTITION p2 VALUES LESS THAN (MAXVALUE))`)
   503  	tk.MustInterDirc("insert admin_test (c1, c2) values (0, 0), (6, 6), (12, 12)")
   504  	r = tk.MustQuery("admin cleanup index admin_test c2")
   505  	r.Check(testkit.Events("0"))
   506  	tbl = getBlock()
   507  	pi = tbl.Meta().GetPartitionInfo()
   508  	c.Assert(pi, NotNil)
   509  	for i, p := range pi.Definitions {
   510  		checkFunc(tbl, p.ID, i*6+1, i*6+1)
   511  	}
   512  }
   513  
   514  func (s *testSuite5) TestAdminCleanupIndexPKNotHandle(c *C) {
   515  	tk := testkit.NewTestKit(c, s.causetstore)
   516  	tk.MustInterDirc("use test")
   517  	tk.MustInterDirc("drop causet if exists admin_test")
   518  	tk.MustInterDirc("set @@milevadb_enable_clustered_index=0;")
   519  	tk.MustInterDirc("create causet admin_test (c1 int, c2 int, c3 int, primary key (c1, c2))")
   520  	tk.MustInterDirc("insert admin_test (c1, c2) values (1, 2), (3, 4), (-5, 5)")
   521  
   522  	r := tk.MustQuery("admin cleanup index admin_test `primary`")
   523  	r.Check(testkit.Events("0"))
   524  
   525  	// Make some dangling index.
   526  	s.ctx = mock.NewContext()
   527  	s.ctx.CausetStore = s.causetstore
   528  	is := s.petri.SchemaReplicant()
   529  	dbName := perceptron.NewCIStr("test")
   530  	tblName := perceptron.NewCIStr("admin_test")
   531  	tbl, err := is.BlockByName(dbName, tblName)
   532  	c.Assert(err, IsNil)
   533  
   534  	tblInfo := tbl.Meta()
   535  	idxInfo := tblInfo.FindIndexByName("primary")
   536  	indexOpr := blocks.NewIndex(tblInfo.ID, tblInfo, idxInfo)
   537  
   538  	txn, err := s.causetstore.Begin()
   539  	c.Assert(err, IsNil)
   540  	_, err = indexOpr.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(7, 10), ekv.IntHandle(-100))
   541  	c.Assert(err, IsNil)
   542  	_, err = indexOpr.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(4, 6), ekv.IntHandle(100))
   543  	c.Assert(err, IsNil)
   544  	_, err = indexOpr.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(-7, 4), ekv.IntHandle(101))
   545  	c.Assert(err, IsNil)
   546  	err = txn.Commit(context.Background())
   547  	c.Assert(err, IsNil)
   548  
   549  	err = tk.InterDircToErr("admin check causet admin_test")
   550  	c.Assert(err, NotNil)
   551  	err = tk.InterDircToErr("admin check index admin_test `primary`")
   552  	c.Assert(err, NotNil)
   553  	r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(`primary`)")
   554  	r.Check(testkit.Events("6"))
   555  	r = tk.MustQuery("admin cleanup index admin_test `primary`")
   556  	r.Check(testkit.Events("3"))
   557  	r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(`primary`)")
   558  	r.Check(testkit.Events("3"))
   559  	tk.MustInterDirc("admin check index admin_test `primary`")
   560  	tk.MustInterDirc("admin check causet admin_test")
   561  }
   562  
   563  func (s *testSuite5) TestAdminCleanupIndexMore(c *C) {
   564  	tk := testkit.NewTestKit(c, s.causetstore)
   565  	tk.MustInterDirc("use test")
   566  	tk.MustInterDirc("drop causet if exists admin_test")
   567  	tk.MustInterDirc("create causet admin_test (c1 int, c2 int, unique key (c1, c2), key (c2))")
   568  	tk.MustInterDirc("insert admin_test values (1, 2), (3, 4), (5, 6)")
   569  
   570  	tk.MustInterDirc("admin cleanup index admin_test c1")
   571  	tk.MustInterDirc("admin cleanup index admin_test c2")
   572  
   573  	// Make some dangling index.
   574  	s.ctx = mock.NewContext()
   575  	s.ctx.CausetStore = s.causetstore
   576  	is := s.petri.SchemaReplicant()
   577  	dbName := perceptron.NewCIStr("test")
   578  	tblName := perceptron.NewCIStr("admin_test")
   579  	tbl, err := is.BlockByName(dbName, tblName)
   580  	c.Assert(err, IsNil)
   581  
   582  	tblInfo := tbl.Meta()
   583  	idxInfo1 := tblInfo.FindIndexByName("c1")
   584  	indexOpr1 := blocks.NewIndex(tblInfo.ID, tblInfo, idxInfo1)
   585  	idxInfo2 := tblInfo.FindIndexByName("c2")
   586  	indexOpr2 := blocks.NewIndex(tblInfo.ID, tblInfo, idxInfo2)
   587  
   588  	txn, err := s.causetstore.Begin()
   589  	c.Assert(err, IsNil)
   590  	for i := 0; i < 2000; i++ {
   591  		c1 := int64(2*i + 7)
   592  		c2 := int64(2*i + 8)
   593  		_, err = indexOpr1.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(c1, c2), ekv.IntHandle(c1))
   594  		c.Assert(err, IsNil, Commentf(errors.ErrorStack(err)))
   595  		_, err = indexOpr2.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(c2), ekv.IntHandle(c1))
   596  		c.Assert(err, IsNil)
   597  	}
   598  	err = txn.Commit(context.Background())
   599  	c.Assert(err, IsNil)
   600  
   601  	err = tk.InterDircToErr("admin check causet admin_test")
   602  	c.Assert(err, NotNil)
   603  	err = tk.InterDircToErr("admin check index admin_test c1")
   604  	c.Assert(err, NotNil)
   605  	err = tk.InterDircToErr("admin check index admin_test c2")
   606  	c.Assert(err, NotNil)
   607  	r := tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX()")
   608  	r.Check(testkit.Events("3"))
   609  	r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c1)")
   610  	r.Check(testkit.Events("2003"))
   611  	r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c2)")
   612  	r.Check(testkit.Events("2003"))
   613  	r = tk.MustQuery("admin cleanup index admin_test c1")
   614  	r.Check(testkit.Events("2000"))
   615  	r = tk.MustQuery("admin cleanup index admin_test c2")
   616  	r.Check(testkit.Events("2000"))
   617  	r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c1)")
   618  	r.Check(testkit.Events("3"))
   619  	r = tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c2)")
   620  	r.Check(testkit.Events("3"))
   621  	tk.MustInterDirc("admin check index admin_test c1")
   622  	tk.MustInterDirc("admin check index admin_test c2")
   623  	tk.MustInterDirc("admin check causet admin_test")
   624  }
   625  
   626  func (s *testSuite5) TestClusteredAdminCleanupIndex(c *C) {
   627  	tk := testkit.NewTestKit(c, s.causetstore)
   628  	tk.MustInterDirc("use test")
   629  	tk.MustInterDirc("drop causet if exists admin_test")
   630  	tk.MustInterDirc("set milevadb_enable_clustered_index=1")
   631  	tk.MustInterDirc("create causet admin_test (c1 varchar(255), c2 int, c3 char(10) default 'c3', primary key (c1, c3), unique key(c2), key (c3))")
   632  	tk.MustInterDirc("insert admin_test (c1, c2) values ('c1_1', 2), ('c1_2', 4), ('c1_3', NULL)")
   633  	tk.MustInterDirc("insert admin_test (c1, c3) values ('c1_4', 'c3_4'), ('c1_5', 'c3_5'), ('c1_6', default)")
   634  
   635  	// Normally, there is no dangling index.
   636  	tk.MustQuery("admin cleanup index admin_test `primary`").Check(testkit.Events("0"))
   637  	tk.MustQuery("admin cleanup index admin_test `c2`").Check(testkit.Events("0"))
   638  	tk.MustQuery("admin cleanup index admin_test `c3`").Check(testkit.Events("0"))
   639  
   640  	// Make some dangling index.
   641  	s.ctx = mock.NewContext()
   642  	s.ctx.CausetStore = s.causetstore
   643  	tbl, err := s.petri.SchemaReplicant().BlockByName(perceptron.NewCIStr("test"), perceptron.NewCIStr("admin_test"))
   644  	c.Assert(err, IsNil)
   645  	// cleanup clustered primary key takes no effect.
   646  
   647  	tblInfo := tbl.Meta()
   648  	idxInfo2 := tblInfo.FindIndexByName("c2")
   649  	indexOpr2 := blocks.NewIndex(tblInfo.ID, tblInfo, idxInfo2)
   650  	idxInfo3 := tblInfo.FindIndexByName("c3")
   651  	indexOpr3 := blocks.NewIndex(tblInfo.ID, tblInfo, idxInfo3)
   652  
   653  	c2DanglingIdx := []struct {
   654  		handle ekv.Handle
   655  		idxVal []types.Causet
   656  	}{
   657  		{solitonutil.MustNewCommonHandle(c, "c1_10", "c3_10"), types.MakeCausets(10)},
   658  		{solitonutil.MustNewCommonHandle(c, "c1_10", "c3_11"), types.MakeCausets(11)},
   659  		{solitonutil.MustNewCommonHandle(c, "c1_12", "c3_12"), types.MakeCausets(12)},
   660  	}
   661  	c3DanglingIdx := []struct {
   662  		handle ekv.Handle
   663  		idxVal []types.Causet
   664  	}{
   665  		{solitonutil.MustNewCommonHandle(c, "c1_13", "c3_13"), types.MakeCausets("c3_13")},
   666  		{solitonutil.MustNewCommonHandle(c, "c1_14", "c3_14"), types.MakeCausets("c3_14")},
   667  		{solitonutil.MustNewCommonHandle(c, "c1_15", "c3_15"), types.MakeCausets("c3_15")},
   668  	}
   669  	txn, err := s.causetstore.Begin()
   670  	c.Assert(err, IsNil)
   671  	for _, di := range c2DanglingIdx {
   672  		_, err := indexOpr2.Create(s.ctx, txn.GetUnionStore(), di.idxVal, di.handle)
   673  		c.Assert(err, IsNil)
   674  	}
   675  	for _, di := range c3DanglingIdx {
   676  		_, err := indexOpr3.Create(s.ctx, txn.GetUnionStore(), di.idxVal, di.handle)
   677  		c.Assert(err, IsNil)
   678  	}
   679  	err = txn.Commit(context.Background())
   680  	c.Assert(err, IsNil)
   681  
   682  	err = tk.InterDircToErr("admin check causet admin_test")
   683  	c.Assert(err, NotNil)
   684  	err = tk.InterDircToErr("admin check index admin_test c2")
   685  	c.Assert(err, NotNil)
   686  	tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c2)").Check(testkit.Events("9"))
   687  	tk.MustQuery("admin cleanup index admin_test c2").Check(testkit.Events("3"))
   688  	tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c2)").Check(testkit.Events("6"))
   689  	tk.MustInterDirc("admin check index admin_test c2")
   690  
   691  	err = tk.InterDircToErr("admin check causet admin_test")
   692  	c.Assert(err, NotNil)
   693  	err = tk.InterDircToErr("admin check index admin_test c3")
   694  	c.Assert(err, NotNil)
   695  	tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c3)").Check(testkit.Events("9"))
   696  	tk.MustQuery("admin cleanup index admin_test c3").Check(testkit.Events("3"))
   697  	tk.MustQuery("SELECT COUNT(*) FROM admin_test USE INDEX(c3)").Check(testkit.Events("6"))
   698  	tk.MustInterDirc("admin check index admin_test c3")
   699  	tk.MustInterDirc("admin check causet admin_test")
   700  }
   701  
   702  func (s *testSuite3) TestAdminCheckPartitionBlockFailed(c *C) {
   703  	tk := testkit.NewTestKit(c, s.causetstore)
   704  	tk.MustInterDirc("use test")
   705  	tk.MustInterDirc("drop causet if exists admin_test_p")
   706  	tk.MustInterDirc("create causet admin_test_p (c1 int key,c2 int,c3 int,index idx(c2)) partition by hash(c1) partitions 4")
   707  	tk.MustInterDirc("insert admin_test_p (c1, c2, c3) values (0,0,0), (1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5)")
   708  	tk.MustInterDirc("admin check causet admin_test_p")
   709  
   710  	// Make some corrupted index. Build the index information.
   711  	s.ctx = mock.NewContext()
   712  	s.ctx.CausetStore = s.causetstore
   713  	is := s.petri.SchemaReplicant()
   714  	dbName := perceptron.NewCIStr("test")
   715  	tblName := perceptron.NewCIStr("admin_test_p")
   716  	tbl, err := is.BlockByName(dbName, tblName)
   717  	c.Assert(err, IsNil)
   718  	tblInfo := tbl.Meta()
   719  	idxInfo := tblInfo.Indices[0]
   720  	sc := s.ctx.GetStochastikVars().StmtCtx
   721  	tk.Se.GetStochastikVars().IndexLookupSize = 3
   722  	tk.Se.GetStochastikVars().MaxChunkSize = 3
   723  
   724  	// Reduce one event of index on partitions.
   725  	// Block count > index count.
   726  	for i := 0; i <= 5; i++ {
   727  		partitionIdx := i % len(tblInfo.GetPartitionInfo().Definitions)
   728  		indexOpr := blocks.NewIndex(tblInfo.GetPartitionInfo().Definitions[partitionIdx].ID, tblInfo, idxInfo)
   729  		txn, err := s.causetstore.Begin()
   730  		c.Assert(err, IsNil)
   731  		err = indexOpr.Delete(sc, txn, types.MakeCausets(i), ekv.IntHandle(i))
   732  		c.Assert(err, IsNil)
   733  		err = txn.Commit(context.Background())
   734  		c.Assert(err, IsNil)
   735  		err = tk.InterDircToErr("admin check causet admin_test_p")
   736  		c.Assert(err.Error(), Equals, fmt.Sprintf("[interlock:8003]admin_test_p err:[admin:8223]index:<nil> != record:&admin.RecordData{Handle:%d, Values:[]types.Causet{types.Causet{k:0x1, decimal:0x0, length:0x0, i:%d, defCauslation:\"\", b:[]uint8(nil), x:interface {}(nil)}}}", i, i))
   737  		c.Assert(interlock.ErrAdminCheckBlock.Equal(err), IsTrue)
   738  		// TODO: fix admin recover for partition causet.
   739  		//r := tk.MustQuery("admin recover index admin_test_p idx")
   740  		//r.Check(testkit.Events("0 0"))
   741  		//tk.MustInterDirc("admin check causet admin_test_p")
   742  		// Manual recover index.
   743  		txn, err = s.causetstore.Begin()
   744  		c.Assert(err, IsNil)
   745  		_, err = indexOpr.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(i), ekv.IntHandle(i))
   746  		c.Assert(err, IsNil)
   747  		err = txn.Commit(context.Background())
   748  		c.Assert(err, IsNil)
   749  		tk.MustInterDirc("admin check causet admin_test_p")
   750  	}
   751  
   752  	// Add one event of index on partitions.
   753  	// Block count < index count.
   754  	for i := 0; i <= 5; i++ {
   755  		partitionIdx := i % len(tblInfo.GetPartitionInfo().Definitions)
   756  		indexOpr := blocks.NewIndex(tblInfo.GetPartitionInfo().Definitions[partitionIdx].ID, tblInfo, idxInfo)
   757  		txn, err := s.causetstore.Begin()
   758  		c.Assert(err, IsNil)
   759  		_, err = indexOpr.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(i+8), ekv.IntHandle(i+8))
   760  		c.Assert(err, IsNil)
   761  		err = txn.Commit(context.Background())
   762  		c.Assert(err, IsNil)
   763  		err = tk.InterDircToErr("admin check causet admin_test_p")
   764  		c.Assert(err, NotNil)
   765  		c.Assert(err.Error(), Equals, fmt.Sprintf("handle %d, index:types.Causet{k:0x1, decimal:0x0, length:0x0, i:%d, defCauslation:\"\", b:[]uint8(nil), x:interface {}(nil)} != record:<nil>", i+8, i+8))
   766  		// TODO: fix admin recover for partition causet.
   767  		txn, err = s.causetstore.Begin()
   768  		c.Assert(err, IsNil)
   769  		err = indexOpr.Delete(sc, txn, types.MakeCausets(i+8), ekv.IntHandle(i+8))
   770  		c.Assert(err, IsNil)
   771  		err = txn.Commit(context.Background())
   772  		c.Assert(err, IsNil)
   773  		tk.MustInterDirc("admin check causet admin_test_p")
   774  	}
   775  
   776  	// Block count = index count, but the index value was wrong.
   777  	for i := 0; i <= 5; i++ {
   778  		partitionIdx := i % len(tblInfo.GetPartitionInfo().Definitions)
   779  		indexOpr := blocks.NewIndex(tblInfo.GetPartitionInfo().Definitions[partitionIdx].ID, tblInfo, idxInfo)
   780  		txn, err := s.causetstore.Begin()
   781  		c.Assert(err, IsNil)
   782  		_, err = indexOpr.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(i+8), ekv.IntHandle(i))
   783  		c.Assert(err, IsNil)
   784  		err = txn.Commit(context.Background())
   785  		c.Assert(err, IsNil)
   786  		err = tk.InterDircToErr("admin check causet admin_test_p")
   787  		c.Assert(err, NotNil)
   788  		c.Assert(err.Error(), Equals, fmt.Sprintf("defCaus c2, handle %d, index:types.Causet{k:0x1, decimal:0x0, length:0x0, i:%d, defCauslation:\"\", b:[]uint8(nil), x:interface {}(nil)} != record:types.Causet{k:0x1, decimal:0x0, length:0x0, i:%d, defCauslation:\"\", b:[]uint8(nil), x:interface {}(nil)}", i, i+8, i))
   789  		// TODO: fix admin recover for partition causet.
   790  		txn, err = s.causetstore.Begin()
   791  		c.Assert(err, IsNil)
   792  		err = indexOpr.Delete(sc, txn, types.MakeCausets(i+8), ekv.IntHandle(i))
   793  		c.Assert(err, IsNil)
   794  		err = txn.Commit(context.Background())
   795  		c.Assert(err, IsNil)
   796  		tk.MustInterDirc("admin check causet admin_test_p")
   797  	}
   798  }
   799  
   800  func (s *testSuite5) TestAdminCheckBlockFailed(c *C) {
   801  	tk := testkit.NewTestKit(c, s.causetstore)
   802  	tk.MustInterDirc("use test")
   803  	tk.MustInterDirc("drop causet if exists admin_test")
   804  	tk.MustInterDirc("create causet admin_test (c1 int, c2 int, c3 varchar(255) default '1', primary key(c1), key(c3), unique key(c2), key(c2, c3))")
   805  	tk.MustInterDirc("insert admin_test (c1, c2, c3) values (-10, -20, 'y'), (-1, -10, 'z'), (1, 11, 'a'), (2, 12, 'b'), (5, 15, 'c'), (10, 20, 'd'), (20, 30, 'e')")
   806  
   807  	// Make some corrupted index. Build the index information.
   808  	s.ctx = mock.NewContext()
   809  	s.ctx.CausetStore = s.causetstore
   810  	is := s.petri.SchemaReplicant()
   811  	dbName := perceptron.NewCIStr("test")
   812  	tblName := perceptron.NewCIStr("admin_test")
   813  	tbl, err := is.BlockByName(dbName, tblName)
   814  	c.Assert(err, IsNil)
   815  	tblInfo := tbl.Meta()
   816  	idxInfo := tblInfo.Indices[1]
   817  	indexOpr := blocks.NewIndex(tblInfo.ID, tblInfo, idxInfo)
   818  	sc := s.ctx.GetStochastikVars().StmtCtx
   819  	tk.Se.GetStochastikVars().IndexLookupSize = 3
   820  	tk.Se.GetStochastikVars().MaxChunkSize = 3
   821  
   822  	// Reduce one event of index.
   823  	// Block count > index count.
   824  	// Index c2 is missing 11.
   825  	txn, err := s.causetstore.Begin()
   826  	c.Assert(err, IsNil)
   827  	err = indexOpr.Delete(sc, txn, types.MakeCausets(-10), ekv.IntHandle(-1))
   828  	c.Assert(err, IsNil)
   829  	err = txn.Commit(context.Background())
   830  	c.Assert(err, IsNil)
   831  	err = tk.InterDircToErr("admin check causet admin_test")
   832  	c.Assert(err, NotNil)
   833  	c.Assert(err.Error(), Equals,
   834  		"[interlock:8003]admin_test err:[admin:8223]index:<nil> != record:&admin.RecordData{Handle:-1, Values:[]types.Causet{types.Causet{k:0x1, decimal:0x0, length:0x0, i:-10, defCauslation:\"\", b:[]uint8(nil), x:interface {}(nil)}}}")
   835  	c.Assert(interlock.ErrAdminCheckBlock.Equal(err), IsTrue)
   836  	r := tk.MustQuery("admin recover index admin_test c2")
   837  	r.Check(testkit.Events("1 7"))
   838  	tk.MustInterDirc("admin check causet admin_test")
   839  
   840  	// Add one event of index.
   841  	// Block count < index count.
   842  	// Index c2 has one more values than causet data: 0, and the handle 0 hasn't correlative record.
   843  	txn, err = s.causetstore.Begin()
   844  	c.Assert(err, IsNil)
   845  	_, err = indexOpr.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(0), ekv.IntHandle(0))
   846  	c.Assert(err, IsNil)
   847  	err = txn.Commit(context.Background())
   848  	c.Assert(err, IsNil)
   849  	err = tk.InterDircToErr("admin check causet admin_test")
   850  	c.Assert(err, NotNil)
   851  	c.Assert(err.Error(), Equals, "handle 0, index:types.Causet{k:0x1, decimal:0x0, length:0x0, i:0, defCauslation:\"\", b:[]uint8(nil), x:interface {}(nil)} != record:<nil>")
   852  
   853  	// Add one event of index.
   854  	// Block count < index count.
   855  	// Index c2 has two more values than causet data: 10, 13, and these handles have correlative record.
   856  	txn, err = s.causetstore.Begin()
   857  	c.Assert(err, IsNil)
   858  	err = indexOpr.Delete(sc, txn, types.MakeCausets(0), ekv.IntHandle(0))
   859  	c.Assert(err, IsNil)
   860  	// Make sure the index value "19" is smaller "21". Then we scan to "19" before "21".
   861  	_, err = indexOpr.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(19), ekv.IntHandle(10))
   862  	c.Assert(err, IsNil)
   863  	_, err = indexOpr.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(13), ekv.IntHandle(2))
   864  	c.Assert(err, IsNil)
   865  	err = txn.Commit(context.Background())
   866  	c.Assert(err, IsNil)
   867  	err = tk.InterDircToErr("admin check causet admin_test")
   868  	c.Assert(err, NotNil)
   869  	c.Assert(err.Error(), Equals, "defCaus c2, handle 2, index:types.Causet{k:0x1, decimal:0x0, length:0x0, i:13, defCauslation:\"\", b:[]uint8(nil), x:interface {}(nil)} != record:types.Causet{k:0x1, decimal:0x0, length:0x0, i:12, defCauslation:\"\", b:[]uint8(nil), x:interface {}(nil)}")
   870  
   871  	// Block count = index count.
   872  	// Two indices have the same handle.
   873  	txn, err = s.causetstore.Begin()
   874  	c.Assert(err, IsNil)
   875  	err = indexOpr.Delete(sc, txn, types.MakeCausets(13), ekv.IntHandle(2))
   876  	c.Assert(err, IsNil)
   877  	err = indexOpr.Delete(sc, txn, types.MakeCausets(12), ekv.IntHandle(2))
   878  	c.Assert(err, IsNil)
   879  	err = txn.Commit(context.Background())
   880  	c.Assert(err, IsNil)
   881  	err = tk.InterDircToErr("admin check causet admin_test")
   882  	c.Assert(err, NotNil)
   883  	c.Assert(err.Error(), Equals, "defCaus c2, handle 10, index:types.Causet{k:0x1, decimal:0x0, length:0x0, i:19, defCauslation:\"\", b:[]uint8(nil), x:interface {}(nil)} != record:types.Causet{k:0x1, decimal:0x0, length:0x0, i:20, defCauslation:\"\", b:[]uint8(nil), x:interface {}(nil)}")
   884  
   885  	// Block count = index count.
   886  	// Index c2 has one line of data is 19, the corresponding causet data is 20.
   887  	txn, err = s.causetstore.Begin()
   888  	c.Assert(err, IsNil)
   889  	_, err = indexOpr.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(12), ekv.IntHandle(2))
   890  	c.Assert(err, IsNil)
   891  	err = indexOpr.Delete(sc, txn, types.MakeCausets(20), ekv.IntHandle(10))
   892  	c.Assert(err, IsNil)
   893  	err = txn.Commit(context.Background())
   894  	c.Assert(err, IsNil)
   895  	err = tk.InterDircToErr("admin check causet admin_test")
   896  	c.Assert(err, NotNil)
   897  	c.Assert(err.Error(), Equals, "defCaus c2, handle 10, index:types.Causet{k:0x1, decimal:0x0, length:0x0, i:19, defCauslation:\"\", b:[]uint8(nil), x:interface {}(nil)} != record:types.Causet{k:0x1, decimal:0x0, length:0x0, i:20, defCauslation:\"\", b:[]uint8(nil), x:interface {}(nil)}")
   898  
   899  	// Recover records.
   900  	txn, err = s.causetstore.Begin()
   901  	c.Assert(err, IsNil)
   902  	err = indexOpr.Delete(sc, txn, types.MakeCausets(19), ekv.IntHandle(10))
   903  	c.Assert(err, IsNil)
   904  	_, err = indexOpr.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(20), ekv.IntHandle(10))
   905  	c.Assert(err, IsNil)
   906  	err = txn.Commit(context.Background())
   907  	c.Assert(err, IsNil)
   908  	tk.MustInterDirc("admin check causet admin_test")
   909  }
   910  
   911  func (s *testSuite8) TestAdminCheckBlock(c *C) {
   912  	// test NULL value.
   913  	tk := testkit.NewTestKit(c, s.causetstore)
   914  	tk.MustInterDirc("use test")
   915  	tk.MustInterDirc(`CREATE TABLE test_null (
   916  		a int(11) NOT NULL,
   917  		c int(11) NOT NULL,
   918  		PRIMARY KEY (a, c),
   919  		KEY idx_a (a)
   920  		) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin`)
   921  
   922  	tk.MustInterDirc(`insert into test_null(a, c) values(2, 2);`)
   923  	tk.MustInterDirc(`ALTER TABLE test_null ADD COLUMN b int NULL DEFAULT '1795454803' AFTER a;`)
   924  	tk.MustInterDirc(`ALTER TABLE test_null add index b(b);`)
   925  	tk.MustInterDirc("ADMIN CHECK TABLE test_null")
   926  
   927  	// Fix unflatten issue in CheckInterDirc.
   928  	tk.MustInterDirc(`drop causet if exists test`)
   929  	tk.MustInterDirc(`create causet test (
   930  		a time,
   931  		PRIMARY KEY (a)
   932  		);`)
   933  
   934  	tk.MustInterDirc(`insert into test set a='12:10:36';`)
   935  	tk.MustInterDirc(`admin check causet test`)
   936  
   937  	// Test decimal
   938  	tk.MustInterDirc(`drop causet if exists test`)
   939  	tk.MustInterDirc("CREATE TABLE test (  a decimal, PRIMARY KEY (a));")
   940  	tk.MustInterDirc("insert into test set a=10;")
   941  	tk.MustInterDirc("admin check causet test;")
   942  
   943  	// Test timestamp type check causet.
   944  	tk.MustInterDirc(`drop causet if exists test`)
   945  	tk.MustInterDirc(`create causet test ( a  TIMESTAMP, primary key(a) );`)
   946  	tk.MustInterDirc(`insert into test set a='2020-08-10 04:18:49';`)
   947  	tk.MustInterDirc(`admin check causet test;`)
   948  
   949  	// Test partitioned causet.
   950  	tk.MustInterDirc(`drop causet if exists test`)
   951  	tk.MustInterDirc(`create causet test (
   952  		      a int not null,
   953  		      c int not null,
   954  		      primary key (a, c),
   955  		      key idx_a (a)) partition by range (c) (
   956  		      partition p1 values less than (1),
   957  		      partition p2 values less than (4),
   958  		      partition p3 values less than (7),
   959  		      partition p4 values less than (11))`)
   960  	for i := 1; i <= 10; i++ {
   961  		tk.MustInterDirc(fmt.Sprintf("insert into test values (%d, %d);", i, i))
   962  	}
   963  	tk.MustInterDirc(`admin check causet test;`)
   964  
   965  	// Test index in virtual generated defCausumn.
   966  	tk.MustInterDirc(`drop causet if exists test`)
   967  	tk.MustInterDirc(`create causet test ( b json , c int as (JSON_EXTRACT(b,'$.d')), index idxc(c));`)
   968  	tk.MustInterDirc(`INSERT INTO test set b='{"d": 100}';`)
   969  	tk.MustInterDirc(`admin check causet test;`)
   970  	// Test prefix index.
   971  	tk.MustInterDirc(`drop causet if exists t`)
   972  	tk.MustInterDirc(`CREATE TABLE t (
   973  	  			ID CHAR(32) NOT NULL,
   974  	  			name CHAR(32) NOT NULL,
   975  	  			value CHAR(255),
   976  	  			INDEX indexIDname (ID(8),name(8)));`)
   977  	tk.MustInterDirc(`INSERT INTO t VALUES ('keyword','urlprefix','text/ /text');`)
   978  	tk.MustInterDirc(`admin check causet t;`)
   979  
   980  	tk.MustInterDirc("use allegrosql")
   981  	tk.MustInterDirc(`admin check causet test.t;`)
   982  	err := tk.InterDircToErr("admin check causet t")
   983  	c.Assert(err, NotNil)
   984  
   985  	// test add index on time type defCausumn which have default value
   986  	tk.MustInterDirc("use test")
   987  	tk.MustInterDirc(`drop causet if exists t1`)
   988  	tk.MustInterDirc(`CREATE TABLE t1 (c2 YEAR, PRIMARY KEY (c2))`)
   989  	tk.MustInterDirc(`INSERT INTO t1 SET c2 = '1912'`)
   990  	tk.MustInterDirc(`ALTER TABLE t1 ADD COLUMN c3 TIMESTAMP NULL DEFAULT '1976-08-29 16:28:11'`)
   991  	tk.MustInterDirc(`ALTER TABLE t1 ADD COLUMN c4 DATE      NULL DEFAULT '1976-08-29'`)
   992  	tk.MustInterDirc(`ALTER TABLE t1 ADD COLUMN c5 TIME      NULL DEFAULT '16:28:11'`)
   993  	tk.MustInterDirc(`ALTER TABLE t1 ADD COLUMN c6 YEAR      NULL DEFAULT '1976'`)
   994  	tk.MustInterDirc(`ALTER TABLE t1 ADD INDEX idx1 (c2, c3,c4,c5,c6)`)
   995  	tk.MustInterDirc(`ALTER TABLE t1 ADD INDEX idx2 (c2)`)
   996  	tk.MustInterDirc(`ALTER TABLE t1 ADD INDEX idx3 (c3)`)
   997  	tk.MustInterDirc(`ALTER TABLE t1 ADD INDEX idx4 (c4)`)
   998  	tk.MustInterDirc(`ALTER TABLE t1 ADD INDEX idx5 (c5)`)
   999  	tk.MustInterDirc(`ALTER TABLE t1 ADD INDEX idx6 (c6)`)
  1000  	tk.MustInterDirc(`admin check causet t1`)
  1001  
  1002  	// Test add index on decimal defCausumn.
  1003  	tk.MustInterDirc(`drop causet if exists td1;`)
  1004  	tk.MustInterDirc(`CREATE TABLE td1 (c2 INT NULL DEFAULT '70');`)
  1005  	tk.MustInterDirc(`INSERT INTO td1 SET c2 = '5';`)
  1006  	tk.MustInterDirc(`ALTER TABLE td1 ADD COLUMN c4 DECIMAL(12,8) NULL DEFAULT '213.41598062';`)
  1007  	tk.MustInterDirc(`ALTER TABLE td1 ADD INDEX id2 (c4) ;`)
  1008  	tk.MustInterDirc(`ADMIN CHECK TABLE td1;`)
  1009  
  1010  	// Test add not null defCausumn, then add index.
  1011  	tk.MustInterDirc(`drop causet if exists t1`)
  1012  	tk.MustInterDirc(`create causet t1 (a int);`)
  1013  	tk.MustInterDirc(`insert into t1 set a=2;`)
  1014  	tk.MustInterDirc(`alter causet t1 add defCausumn b timestamp not null;`)
  1015  	tk.MustInterDirc(`alter causet t1 add index(b);`)
  1016  	tk.MustInterDirc(`admin check causet t1;`)
  1017  
  1018  	// Test for index with change decimal precision.
  1019  	tk.MustInterDirc(`drop causet if exists t1`)
  1020  	tk.MustInterDirc(`create causet t1 (a decimal(2,1), index(a))`)
  1021  	tk.MustInterDirc(`insert into t1 set a='1.9'`)
  1022  	err = tk.InterDircToErr(`alter causet t1 modify defCausumn a decimal(3,2);`)
  1023  	c.Assert(err, NotNil)
  1024  	c.Assert(err.Error(), Equals, "[dbs:8200]Unsupported modify defCausumn: can't change decimal defCausumn precision")
  1025  	tk.MustInterDirc(`delete from t1;`)
  1026  	tk.MustInterDirc(`admin check causet t1;`)
  1027  }
  1028  
  1029  func (s *testSuite1) TestAdminCheckPrimaryIndex(c *C) {
  1030  	tk := testkit.NewTestKit(c, s.causetstore)
  1031  	tk.MustInterDirc("use test")
  1032  	tk.MustInterDirc("create causet t(a bigint unsigned primary key, b int, c int, index idx(a, b));")
  1033  	tk.MustInterDirc("insert into t values(1, 1, 1), (9223372036854775807, 2, 2);")
  1034  	tk.MustInterDirc("admin check index t idx;")
  1035  }
  1036  
  1037  func (s *testSuite5) TestAdminCheckWithSnapshot(c *C) {
  1038  	tk := testkit.NewTestKit(c, s.causetstore)
  1039  	tk.MustInterDirc("use test")
  1040  	tk.MustInterDirc("drop causet if exists admin_t_s")
  1041  	tk.MustInterDirc("create causet admin_t_s (a int, b int, key(a));")
  1042  	tk.MustInterDirc("insert into admin_t_s values (0,0),(1,1);")
  1043  	tk.MustInterDirc("admin check causet admin_t_s;")
  1044  	tk.MustInterDirc("admin check index admin_t_s a;")
  1045  
  1046  	snapshotTime := time.Now()
  1047  
  1048  	s.ctx = mock.NewContext()
  1049  	s.ctx.CausetStore = s.causetstore
  1050  	is := s.petri.SchemaReplicant()
  1051  	dbName := perceptron.NewCIStr("test")
  1052  	tblName := perceptron.NewCIStr("admin_t_s")
  1053  	tbl, err := is.BlockByName(dbName, tblName)
  1054  	c.Assert(err, IsNil)
  1055  
  1056  	tblInfo := tbl.Meta()
  1057  	idxInfo := tblInfo.FindIndexByName("a")
  1058  	idxOpr := blocks.NewIndex(tblInfo.ID, tblInfo, idxInfo)
  1059  	txn, err := s.causetstore.Begin()
  1060  	c.Assert(err, IsNil)
  1061  	_, err = idxOpr.Create(s.ctx, txn.GetUnionStore(), types.MakeCausets(2), ekv.IntHandle(100))
  1062  	c.Assert(err, IsNil)
  1063  	err = txn.Commit(context.Background())
  1064  	c.Assert(err, IsNil)
  1065  	err = tk.InterDircToErr("admin check causet admin_t_s")
  1066  	c.Assert(err, NotNil)
  1067  	err = tk.InterDircToErr("admin check index admin_t_s a")
  1068  	c.Assert(err, NotNil)
  1069  
  1070  	// For mockeinsteindb, safe point is not initialized, we manually insert it for snapshot to use.
  1071  	safePointName := "einsteindb_gc_safe_point"
  1072  	safePointValue := "20060102-15:04:05 -0700"
  1073  	safePointComment := "All versions after safe point can be accessed. (DO NOT EDIT)"
  1074  	uFIDelateSafePoint := fmt.Sprintf(`INSERT INTO allegrosql.milevadb VALUES ('%[1]s', '%[2]s', '%[3]s')
  1075  	ON DUPLICATE KEY
  1076  	UFIDelATE variable_value = '%[2]s', comment = '%[3]s'`, safePointName, safePointValue, safePointComment)
  1077  	tk.MustInterDirc(uFIDelateSafePoint)
  1078  	// For admin check causet when use snapshot.
  1079  	tk.MustInterDirc("set @@milevadb_snapshot = '" + snapshotTime.Format("2006-01-02 15:04:05.999999") + "'")
  1080  	tk.MustInterDirc("admin check causet admin_t_s;")
  1081  	tk.MustInterDirc("admin check index admin_t_s a;")
  1082  
  1083  	tk.MustInterDirc("set @@milevadb_snapshot = ''")
  1084  	err = tk.InterDircToErr("admin check causet admin_t_s")
  1085  	c.Assert(err, NotNil)
  1086  	err = tk.InterDircToErr("admin check index admin_t_s a")
  1087  	c.Assert(err, NotNil)
  1088  
  1089  	r := tk.MustQuery("admin cleanup index admin_t_s a")
  1090  	r.Check(testkit.Events("1"))
  1091  	tk.MustInterDirc("admin check causet admin_t_s;")
  1092  	tk.MustInterDirc("admin check index admin_t_s a;")
  1093  	tk.MustInterDirc("drop causet if exists admin_t_s")
  1094  }