Repository: pingcap/tidb (Go)

Issue:
executor: mocktikv panic
## Bug Report

Please answer these questions before submitting your issue. Thanks!

### 1. What did you do?
```
CREATE TABLE `V` (
  `pk` int(11) NOT NULL AUTO_INCREMENT,
  `col_varchar_10_utf8_not_null` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  `col_varchar_1024_utf8` varchar(1024) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
  `col_int` int(11) DEFAULT NULL,
  `col_varchar_10_latin1_not_null` varchar(10) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
  `col_int_not_null` int(11) NOT NULL,
  `col_varchar_1024_latin1` varchar(1024) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
  `col_varchar_1024_utf8_not_null` varchar(1024) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  `col_varchar_1024_latin1_not_null` varchar(1024) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
  `col_varchar_10_latin1` varchar(10) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
  `col_varchar_10_utf8` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
  PRIMARY KEY (`pk`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=2000001;
/*!40101 SET character_set_client = @saved_cs_client */;

LOCK TABLES `V` WRITE;
/*!40000 ALTER TABLE `V` DISABLE KEYS */;
INSERT INTO `V` VALUES (1,'g',NULL,8,'b',0,'o','s','b','j','k');
INSERT INTO `V` VALUES (2,'f','s',8,'p',9,'q','a','c',NULL,'j');
INSERT INTO `V` VALUES (3,'k','t',9,'f',7,'s','b','r','t','l');
INSERT INTO `V` VALUES (4,'h','q',NULL,'x',1,NULL,'d','c','f',NULL);
INSERT INTO `V` VALUES (5,'a','h',2,'o',9,NULL,'d','g',NULL,'g');
INSERT INTO `V` VALUES (6,'u','c',2,'l',4,'b','s','o','j','l');
INSERT INTO `V` VALUES (7,'m',NULL,8,'j',2,'r','s','d',NULL,NULL);
INSERT INTO `V` VALUES (8,'u','o',4,'w',0,'l','p','a','f','l');
INSERT INTO `V` VALUES (9,'h','i',9,'d',7,'e','f','g','g','f');
INSERT INTO `V` VALUES (10,'f',NULL,3,'s',5,'u','a','z','n','l');
INSERT INTO `V` VALUES (11,'c','u',NULL,'v',3,'o','t','c','g','q');
INSERT INTO `V` VALUES (12,'o',NULL,5,'d',3,NULL,'t','z','t','b');
INSERT INTO `V` VALUES (13,'g','i',0,'o',0,'i','y','m','x','r');
INSERT INTO `V` VALUES (14,'y','b',7,'h',3,'a','h','j','y','a');
INSERT INTO `V` VALUES (15,'l','q',NULL,'d',1,'r','s','d','i','z');
INSERT INTO `V` VALUES (16,'e','q',1,'y',4,'q','i','h','t','b');
INSERT INTO `V` VALUES (17,'g','u',1,'e',2,'e','p','b','j','l');
INSERT INTO `V` VALUES (18,'t','k',9,'y',6,'q','h','n','k',NULL);
INSERT INTO `V` VALUES (19,'h','m',7,'z',0,'t','u','r','x','f');
INSERT INTO `V` VALUES (20,'l','p',NULL,'s',6,NULL,'s','d',NULL,'r');
INSERT INTO `V` VALUES (21,'z','n',NULL,'d',2,'d','z','k','e','a');


CREATE TABLE `F` (
  `col_int_not_null` int(11) NOT NULL,
  `col_varchar_1024_utf8` varchar(1024) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
  `col_varchar_10_utf8` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
  `col_varchar_10_latin1` varchar(10) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
  `col_varchar_1024_latin1` varchar(1024) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
  `col_varchar_1024_latin1_not_null` varchar(1024) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
  `col_varchar_1024_utf8_not_null` varchar(1024) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  `col_varchar_10_utf8_not_null` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  `pk` int(11) NOT NULL AUTO_INCREMENT,
  `col_varchar_10_latin1_not_null` varchar(10) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL,
  `col_int` int(11) DEFAULT NULL,
  PRIMARY KEY (`pk`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=2000001;
/*!40101 SET character_set_client = @saved_cs_client */;

LOCK TABLES `F` WRITE;
/*!40000 ALTER TABLE `F` DISABLE KEYS */;
INSERT INTO `F` VALUES (9,NULL,NULL,'y','r','w','b','o',1,'e',1);
INSERT INTO `F` VALUES (3,'a','z','l',NULL,'e','f','j',2,'g',0);
```

```
 SELECT    table1 . `col_int` AS field1 , table1 . `col_int` AS field2 , table1 . `col_int` AS field3 FROM  V AS table1  LEFT  JOIN F AS table2 ON  table1 . `col_int` =  table2 . `col_int`  WHERE table1 . `col_int` != 2  HAVING (field2 >= 5 OR field1 < 132) ORDER BY field1, field2, field3 DESC LIMIT 2 ;
```

### 2. What did you expect to see?
run correctly

### 3. What did you see instead?
```
[ERROR] [coprocessor.go:657] ["copIteratorWork meet panic"] [r={}] ["stack trace"="github.com/pingcap/tidb/store/tikv.(*copIteratorWorker).handleTask.func1\n\t/home/tidb/fzh/hashjoin/tidb/store/tikv/coprocessor.go:659\nruntime.gopanic\n\t/usr/lib/golang/src/runtime/panic.go:679\nruntime.goPanicIndex\n\t/usr/lib/golang/src/runtime/panic.go:75\ngithub.com/pingcap/tidb/store/mockstore/mocktikv.(*topNExec).evalTopN\n\t/home/tidb/fzh/hashjoin/tidb/store/mockstore/mocktikv/executor.go:596\ngithub.com/pingcap/tidb/store/mockstore/mocktikv.(*topNExec).innerNext\n\t/home/tidb/fzh/hashjoin/tidb/store/mockstore/mocktikv/executor.go:548\ngithub.com/pingcap/tidb/store/mockstore/mocktikv.(*topNExec).Next\n\t/home/tidb/fzh/hashjoin/tidb/store/mockstore/mocktikv/executor.go:565\ngithub.com/pingcap/tidb/store/mockstore/mocktikv.(*rpcHandler).handleCopDAGRequest\n\t/home/tidb/fzh/hashjoin/tidb/store/mockstore/mocktikv/cop_handler_dag.go:74\ngithub.com/pingcap/tidb/store/mockstore/mocktikv.(*RPCClient).SendRequest\n\t/home/tidb/fzh/hashjoin/tidb/store/mockstore/mocktikv/rpc.go:992\ngithub.com/pingcap/tidb/store/tikv.(*RegionRequestSender).sendReqToRegion\n\t/home/tidb/fzh/hashjoin/tidb/store/tikv/region_request.go:199\ngithub.com/pingcap/tidb/store/tikv.(*RegionRequestSender).SendReqCtx\n\t/home/tidb/fzh/hashjoin/tidb/store/tikv/region_request.go:162\ngithub.com/pingcap/tidb/store/tikv.(*clientHelper).SendReqCtx\n\t/home/tidb/fzh/hashjoin/tidb/store/tikv/coprocessor.go:814\ngithub.com/pingcap/tidb/store/tikv.(*copIteratorWorker).handleTaskOnce\n\t/home/tidb/fzh/hashjoin/tidb/store/tikv/coprocessor.go:729\ngithub.com/pingcap/tidb/store/tikv.(*copIteratorWorker).handleTask\n\t/home/tidb/fzh/hashjoin/tidb/store/tikv/coprocessor.go:667\ngithub.com/pingcap/tidb/store/tikv.(*copIteratorWorker).run\n\t/home/tidb/fzh/hashjoin/tidb/store/tikv/coprocessor.go:489"]

```
### 4. What version of TiDB are you using? (`tidb-server -V` or run `select tidb_version();` on TiDB)
| 5.7.25-TiDB-v4.0.0-beta-523-g7eba696bb-dirty |



Discussion:
This is a bug in mocktikv, the sqls can run successfully on tikv.
Change this line: https://github.com/pingcap/tidb/blob/master/store/mockstore/mocktikv/executor.go#L589
to 		`key: make([]types.Datum, len(e.orderByExprs)),` can fix this problem.
So as #15766 
verified on
master: v4.0.0-beta.2-524-g73fe3ca4d
release-4.0: v4.0.0




Patch:
diff --git a/store/mockstore/mocktikv/executor.go b/store/mockstore/mocktikv/executor.go
index ae1cb1a8fbf47..7a90b1f15af81 100644
--- a/store/mockstore/mocktikv/executor.go
+++ b/store/mockstore/mocktikv/executor.go
@@ -586,7 +586,7 @@ func (e *topNExec) Next(ctx context.Context) (value [][]byte, err error) {
 // And this function will check if this record can replace one of the old records.
 func (e *topNExec) evalTopN(value [][]byte) error {
 	newRow := &sortRow{
-		key: make([]types.Datum, len(value)),
+		key: make([]types.Datum, len(e.orderByExprs)),
 	}
 	err := e.evalCtx.decodeRelatedColumnVals(e.relatedColOffsets, value, e.row)
 	if err != nil {


Test patch:
diff --git a/store/mockstore/mocktikv/executor_test.go b/store/mockstore/mocktikv/executor_test.go
index 76d784c6450d0..1b81ba5c150a3 100644
--- a/store/mockstore/mocktikv/executor_test.go
+++ b/store/mockstore/mocktikv/executor_test.go
@@ -107,3 +107,18 @@ func (s *testExecutorSuite) TestResolvedLargeTxnLocks(c *C) {
 	_, ok := errors.Cause(pairs[0].Err).(*mocktikv.ErrLocked)
 	c.Assert(ok, IsTrue)
 }
+
+func (s *testExecutorSuite) TestIssue15662(c *C) {
+	tk := testkit.NewTestKit(c, s.store)
+
+	tk.MustExec("use test")
+
+	tk.MustExec("create table V (id int primary key, col_int int)")
+	tk.MustExec("insert into V values (1, 8)")
+
+	tk.MustExec("create table F (id int primary key, col_int int)")
+	tk.MustExec("insert into F values (1, 8)")
+
+	tk.MustQuery("select table1.`col_int` as field1, table1.`col_int` as field2 from V as table1 left join F as table2 on table1.`col_int` = table2.`col_int` order by field1, field2 desc limit 2").
+		Check(testkit.Rows("8 8"))
+}