@@ -101,10 +101,10 @@ func (s *testSuite) TestAdminRecoverIndex(c *C) {
101101 c .Assert (err , IsNil )
102102 err = txn .Commit (context .Background ())
103103 c .Assert (err , IsNil )
104- _ , err = tk .Exec ("admin check table admin_test" )
104+ err = tk .ExecToErr ("admin check table admin_test" )
105105 c .Assert (err , NotNil )
106106 c .Assert (executor .ErrAdminCheckTable .Equal (err ), IsTrue )
107- _ , err = tk .Exec ("admin check index admin_test c2" )
107+ err = tk .ExecToErr ("admin check index admin_test c2" )
108108 c .Assert (err , NotNil )
109109
110110 r = tk .MustQuery ("SELECT COUNT(*) FROM admin_test USE INDEX(c2)" )
@@ -125,7 +125,7 @@ func (s *testSuite) TestAdminRecoverIndex(c *C) {
125125 err = txn .Commit (context .Background ())
126126 c .Assert (err , IsNil )
127127
128- _ , err = tk .Exec ("admin check index admin_test c2" )
128+ err = tk .ExecToErr ("admin check index admin_test c2" )
129129 c .Assert (err , NotNil )
130130 r = tk .MustQuery ("admin recover index admin_test c2" )
131131 r .Check (testkit .Rows ("1 5" ))
@@ -147,9 +147,9 @@ func (s *testSuite) TestAdminRecoverIndex(c *C) {
147147 err = txn .Commit (context .Background ())
148148 c .Assert (err , IsNil )
149149
150- _ , err = tk .Exec ("admin check table admin_test" )
150+ err = tk .ExecToErr ("admin check table admin_test" )
151151 c .Assert (err , NotNil )
152- _ , err = tk .Exec ("admin check index admin_test c2" )
152+ err = tk .ExecToErr ("admin check index admin_test c2" )
153153 c .Assert (err , NotNil )
154154
155155 r = tk .MustQuery ("SELECT COUNT(*) FROM admin_test USE INDEX(c2)" )
@@ -271,9 +271,9 @@ func (s *testSuite) TestAdminCleanupIndex(c *C) {
271271 err = txn .Commit (context .Background ())
272272 c .Assert (err , IsNil )
273273
274- _ , err = tk .Exec ("admin check table admin_test" )
274+ err = tk .ExecToErr ("admin check table admin_test" )
275275 c .Assert (err , NotNil )
276- _ , err = tk .Exec ("admin check index admin_test c2" )
276+ err = tk .ExecToErr ("admin check index admin_test c2" )
277277 c .Assert (err , NotNil )
278278 r = tk .MustQuery ("SELECT COUNT(*) FROM admin_test USE INDEX(c2)" )
279279 r .Check (testkit .Rows ("11" ))
@@ -283,9 +283,9 @@ func (s *testSuite) TestAdminCleanupIndex(c *C) {
283283 r .Check (testkit .Rows ("6" ))
284284 tk .MustExec ("admin check index admin_test c2" )
285285
286- _ , err = tk .Exec ("admin check table admin_test" )
286+ err = tk .ExecToErr ("admin check table admin_test" )
287287 c .Assert (err , NotNil )
288- _ , err = tk .Exec ("admin check index admin_test c3" )
288+ err = tk .ExecToErr ("admin check index admin_test c3" )
289289 c .Assert (err , NotNil )
290290 r = tk .MustQuery ("SELECT COUNT(*) FROM admin_test USE INDEX(c3)" )
291291 r .Check (testkit .Rows ("9" ))
@@ -332,9 +332,9 @@ func (s *testSuite) TestAdminCleanupIndexPKNotHandle(c *C) {
332332 err = txn .Commit (context .Background ())
333333 c .Assert (err , IsNil )
334334
335- _ , err = tk .Exec ("admin check table admin_test" )
335+ err = tk .ExecToErr ("admin check table admin_test" )
336336 c .Assert (err , NotNil )
337- _ , err = tk .Exec ("admin check index admin_test `primary`" )
337+ err = tk .ExecToErr ("admin check index admin_test `primary`" )
338338 c .Assert (err , NotNil )
339339 r = tk .MustQuery ("SELECT COUNT(*) FROM admin_test USE INDEX(`primary`)" )
340340 r .Check (testkit .Rows ("6" ))
@@ -384,11 +384,11 @@ func (s *testSuite) TestAdminCleanupIndexMore(c *C) {
384384 err = txn .Commit (context .Background ())
385385 c .Assert (err , IsNil )
386386
387- _ , err = tk .Exec ("admin check table admin_test" )
387+ err = tk .ExecToErr ("admin check table admin_test" )
388388 c .Assert (err , NotNil )
389- _ , err = tk .Exec ("admin check index admin_test c1" )
389+ err = tk .ExecToErr ("admin check index admin_test c1" )
390390 c .Assert (err , NotNil )
391- _ , err = tk .Exec ("admin check index admin_test c2" )
391+ err = tk .ExecToErr ("admin check index admin_test c2" )
392392 c .Assert (err , NotNil )
393393 r := tk .MustQuery ("SELECT COUNT(*) FROM admin_test" )
394394 r .Check (testkit .Rows ("3" ))
@@ -409,6 +409,112 @@ func (s *testSuite) TestAdminCleanupIndexMore(c *C) {
409409 tk .MustExec ("admin check table admin_test" )
410410}
411411
412+ func (s * testSuite ) TestAdminCheckTableFailed (c * C ) {
413+ tk := testkit .NewTestKit (c , s .store )
414+ tk .MustExec ("use test" )
415+ tk .MustExec ("drop table if exists admin_test" )
416+ tk .MustExec ("create table admin_test (c1 int, c2 int, c3 varchar(255) default '1', primary key(c1), key(c3), unique key(c2), key(c2, c3))" )
417+ tk .MustExec ("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')" )
418+
419+ // Make some corrupted index. Build the index information.
420+ s .ctx = mock .NewContext ()
421+ s .ctx .Store = s .store
422+ is := s .domain .InfoSchema ()
423+ dbName := model .NewCIStr ("test" )
424+ tblName := model .NewCIStr ("admin_test" )
425+ tbl , err := is .TableByName (dbName , tblName )
426+ c .Assert (err , IsNil )
427+ tblInfo := tbl .Meta ()
428+ idxInfo := tblInfo .Indices [1 ]
429+ indexOpr := tables .NewIndex (tblInfo .ID , tblInfo , idxInfo )
430+ sc := s .ctx .GetSessionVars ().StmtCtx
431+ tk .Se .GetSessionVars ().IndexLookupSize = 3
432+ tk .Se .GetSessionVars ().MaxChunkSize = 3
433+
434+ // Reduce one row of index.
435+ // Table count > index count.
436+ // Index c2 is missing 11.
437+ txn , err := s .store .Begin ()
438+ c .Assert (err , IsNil )
439+ err = indexOpr .Delete (sc , txn , types .MakeDatums (- 10 ), - 1 )
440+ c .Assert (err , IsNil )
441+ err = txn .Commit (context .Background ())
442+ c .Assert (err , IsNil )
443+ err = tk .ExecToErr ("admin check table admin_test" )
444+ c .Assert (err .Error (), Equals ,
445+ "[executor:8003]admin_test err:[admin:1]index:<nil> != record:&admin.RecordData{Handle:-1, Values:[]types.Datum{types.Datum{k:0x1, collation:0x0, decimal:0x0, length:0x0, i:-10, b:[]uint8(nil), x:interface {}(nil)}}}" )
446+ c .Assert (executor .ErrAdminCheckTable .Equal (err ), IsTrue )
447+ r := tk .MustQuery ("admin recover index admin_test c2" )
448+ r .Check (testkit .Rows ("1 7" ))
449+ tk .MustExec ("admin check table admin_test" )
450+
451+ // Add one row of index.
452+ // Table count < index count.
453+ // Index c2 has one more values than table data: 0, and the handle 0 hasn't correlative record.
454+ txn , err = s .store .Begin ()
455+ c .Assert (err , IsNil )
456+ _ , err = indexOpr .Create (s .ctx , txn , types .MakeDatums (0 ), 0 )
457+ c .Assert (err , IsNil )
458+ err = txn .Commit (context .Background ())
459+ c .Assert (err , IsNil )
460+ err = tk .ExecToErr ("admin check table admin_test" )
461+ c .Assert (err .Error (), Equals , "handle 0, index:types.Datum{k:0x1, collation:0x0, decimal:0x0, length:0x0, i:0, b:[]uint8(nil), x:interface {}(nil)} != record:<nil>" )
462+
463+ // Add one row of index.
464+ // Table count < index count.
465+ // Index c2 has two more values than table data: 10, 13, and these handles have correlative record.
466+ txn , err = s .store .Begin ()
467+ c .Assert (err , IsNil )
468+ err = indexOpr .Delete (sc , txn , types .MakeDatums (0 ), 0 )
469+ c .Assert (err , IsNil )
470+ // Make sure the index value "19" is smaller "21". Then we scan to "19" before "21".
471+ _ , err = indexOpr .Create (s .ctx , txn , types .MakeDatums (19 ), 10 )
472+ c .Assert (err , IsNil )
473+ _ , err = indexOpr .Create (s .ctx , txn , types .MakeDatums (13 ), 2 )
474+ c .Assert (err , IsNil )
475+ err = txn .Commit (context .Background ())
476+ c .Assert (err , IsNil )
477+ err = tk .ExecToErr ("admin check table admin_test" )
478+ c .Assert (err .Error (), Equals , "col c2, handle 2, index:types.Datum{k:0x1, collation:0x0, decimal:0x0, length:0x0, i:13, b:[]uint8(nil), x:interface {}(nil)} != record:types.Datum{k:0x1, collation:0x0, decimal:0x0, length:0x0, i:12, b:[]uint8(nil), x:interface {}(nil)}" )
479+
480+ // Table count = index count.
481+ // Two indices have the same handle.
482+ txn , err = s .store .Begin ()
483+ c .Assert (err , IsNil )
484+ err = indexOpr .Delete (sc , txn , types .MakeDatums (13 ), 2 )
485+ c .Assert (err , IsNil )
486+ err = indexOpr .Delete (sc , txn , types .MakeDatums (12 ), 2 )
487+ c .Assert (err , IsNil )
488+ err = txn .Commit (context .Background ())
489+ c .Assert (err , IsNil )
490+ err = tk .ExecToErr ("admin check table admin_test" )
491+ c .Assert (err .Error (), Equals , "col c2, handle 10, index:types.Datum{k:0x1, collation:0x0, decimal:0x0, length:0x0, i:19, b:[]uint8(nil), x:interface {}(nil)} != record:types.Datum{k:0x1, collation:0x0, decimal:0x0, length:0x0, i:20, b:[]uint8(nil), x:interface {}(nil)}" )
492+
493+ // Table count = index count.
494+ // Index c2 has one line of data is 19, the corresponding table data is 20.
495+ txn , err = s .store .Begin ()
496+ c .Assert (err , IsNil )
497+ _ , err = indexOpr .Create (s .ctx , txn , types .MakeDatums (12 ), 2 )
498+ c .Assert (err , IsNil )
499+ err = indexOpr .Delete (sc , txn , types .MakeDatums (20 ), 10 )
500+ c .Assert (err , IsNil )
501+ err = txn .Commit (context .Background ())
502+ c .Assert (err , IsNil )
503+ err = tk .ExecToErr ("admin check table admin_test" )
504+ c .Assert (err .Error (), Equals , "col c2, handle 10, index:types.Datum{k:0x1, collation:0x0, decimal:0x0, length:0x0, i:19, b:[]uint8(nil), x:interface {}(nil)} != record:types.Datum{k:0x1, collation:0x0, decimal:0x0, length:0x0, i:20, b:[]uint8(nil), x:interface {}(nil)}" )
505+
506+ // Recover records.
507+ txn , err = s .store .Begin ()
508+ c .Assert (err , IsNil )
509+ err = indexOpr .Delete (sc , txn , types .MakeDatums (19 ), 10 )
510+ c .Assert (err , IsNil )
511+ _ , err = indexOpr .Create (s .ctx , txn , types .MakeDatums (20 ), 10 )
512+ c .Assert (err , IsNil )
513+ err = txn .Commit (context .Background ())
514+ c .Assert (err , IsNil )
515+ tk .MustExec ("admin check table admin_test" )
516+ }
517+
412518func (s * testSuite ) TestAdminCheckTable (c * C ) {
413519 // test NULL value.
414520 tk := testkit .NewTestKit (c , s .store )
@@ -466,22 +572,22 @@ func (s *testSuite) TestAdminCheckTable(c *C) {
466572
467573 // Test index in virtual generated column.
468574 tk .MustExec (`drop table if exists test` )
469- tk .MustExec (`create table test ( b json , c int as (JSON_EXTRACT(b,'$.d')) , index idxc(c));` )
575+ tk .MustExec (`create table test ( b json , c int as (JSON_EXTRACT(b,'$.d')), index idxc(c));` )
470576 tk .MustExec (`INSERT INTO test set b='{"d": 100}';` )
471577 tk .MustExec (`admin check table test;` )
472578 // Test prefix index.
473579 tk .MustExec (`drop table if exists t` )
474580 tk .MustExec (`CREATE TABLE t (
475- ID CHAR(32) NOT NULL,
476- name CHAR(32) NOT NULL,
477- value CHAR(255),
478- INDEX indexIDname (ID(8),name(8)));` )
581+ ID CHAR(32) NOT NULL,
582+ name CHAR(32) NOT NULL,
583+ value CHAR(255),
584+ INDEX indexIDname (ID(8),name(8)));` )
479585 tk .MustExec (`INSERT INTO t VALUES ('keyword','urlprefix','text/ /text');` )
480586 tk .MustExec (`admin check table t;` )
481587
482588 tk .MustExec ("use mysql" )
483589 tk .MustExec (`admin check table test.t;` )
484- _ , err := tk .Exec ("admin check table t" )
590+ err := tk .ExecToErr ("admin check table t" )
485591 c .Assert (err , NotNil )
486592
487593 // test add index on time type column which have default value
@@ -521,7 +627,7 @@ func (s *testSuite) TestAdminCheckTable(c *C) {
521627 tk .MustExec (`drop table if exists t1` )
522628 tk .MustExec (`create table t1 (a decimal(2,1), index(a))` )
523629 tk .MustExec (`insert into t1 set a='1.9'` )
524- _ , err = tk .Exec (`alter table t1 modify column a decimal(3,2);` )
630+ err = tk .ExecToErr (`alter table t1 modify column a decimal(3,2);` )
525631 c .Assert (err , NotNil )
526632 c .Assert (err .Error (), Equals , "[ddl:203]unsupported modify decimal column precision" )
527633 tk .MustExec (`delete from t1;` )
0 commit comments