executor: make seek value with the same length of the index columns.
For composite index with 2 columns, if we just pass one value in `Seek`, we will get the wrong result. So this change create the seek value with the length of the composite index.
This commit is contained in:
@ -84,7 +84,7 @@ func (b *executorBuilder) buildIndexScan(v *plan.IndexScan) Executor {
|
||||
}
|
||||
e := &IndexScanExec{
|
||||
tbl: tbl,
|
||||
idx: idx.X,
|
||||
idx: idx,
|
||||
fields: v.Fields(),
|
||||
ctx: b.ctx,
|
||||
Desc: v.Desc,
|
||||
|
||||
@ -19,6 +19,7 @@ import (
|
||||
|
||||
"github.com/juju/errors"
|
||||
"github.com/pingcap/tidb/ast"
|
||||
"github.com/pingcap/tidb/column"
|
||||
"github.com/pingcap/tidb/context"
|
||||
"github.com/pingcap/tidb/kv"
|
||||
"github.com/pingcap/tidb/optimizer/evaluator"
|
||||
@ -177,8 +178,8 @@ func (e *IndexRangeExec) Fields() []*ast.ResultField {
|
||||
// Next implements Executor Next interface.
|
||||
func (e *IndexRangeExec) Next() (*Row, error) {
|
||||
if e.iter == nil {
|
||||
seekVals := make([]interface{}, len(e.lowVals))
|
||||
for i := 0; i < len(seekVals); i++ {
|
||||
seekVals := make([]interface{}, len(e.scan.idx.Columns))
|
||||
for i := 0; i < len(e.lowVals); i++ {
|
||||
var err error
|
||||
if e.lowVals[i] == plan.MinNotNullVal {
|
||||
seekVals[i] = []byte{}
|
||||
@ -189,12 +190,11 @@ func (e *IndexRangeExec) Next() (*Row, error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
txn, err := e.scan.ctx.GetTxn(false)
|
||||
if err != nil {
|
||||
return nil, errors.Trace(err)
|
||||
}
|
||||
e.iter, _, err = e.scan.idx.Seek(txn, seekVals)
|
||||
e.iter, _, err = e.scan.idx.X.Seek(txn, seekVals)
|
||||
if err != nil {
|
||||
return nil, types.EOFAsNil(err)
|
||||
}
|
||||
@ -315,7 +315,7 @@ func (e *IndexRangeExec) Close() error {
|
||||
// IndexScanExec represents an index scan executor.
|
||||
type IndexScanExec struct {
|
||||
tbl table.Table
|
||||
idx kv.Index
|
||||
idx *column.IndexedCol
|
||||
fields []*ast.ResultField
|
||||
Ranges []*IndexRangeExec
|
||||
Desc bool
|
||||
|
||||
@ -143,3 +143,23 @@ func (s *testIndexSuite) TestIndex(c *C) {
|
||||
err = txn.Commit()
|
||||
c.Assert(err, IsNil)
|
||||
}
|
||||
|
||||
func (s *testIndexSuite) TestCombineIndexSeek(c *C) {
|
||||
index := kv.NewKVIndex("i", "test", 1, false)
|
||||
|
||||
txn, err := s.s.Begin()
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
values := []interface{}{"abc", "def"}
|
||||
err = index.Create(txn, values, 1)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
index2 := kv.NewKVIndex("i", "test", 1, false)
|
||||
iter, hit, err := index2.Seek(txn, []interface{}{"abc", nil})
|
||||
defer iter.Close()
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(hit, IsFalse)
|
||||
_, h, err := iter.Next()
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(h, Equals, int64(1))
|
||||
}
|
||||
|
||||
@ -1364,6 +1364,13 @@ func (s *testSessionSuite) TestMultiColumnIndex(c *C) {
|
||||
checkPlan(c, se, sql, expectedExplain)
|
||||
mustExecMatch(c, se, sql, [][]interface{}{{1}})
|
||||
|
||||
// Test varchar type.
|
||||
mustExecSQL(c, se, "drop table t;")
|
||||
mustExecSQL(c, se, "create table t (c1 varchar(64), c2 varchar(64), index c1_c2 (c1, c2));")
|
||||
mustExecSQL(c, se, "insert into t values ('abc', 'def')")
|
||||
sql = "select c1 from t where c1 = 'abc'"
|
||||
mustExecMatch(c, se, sql, [][]interface{}{{[]byte("abc")}})
|
||||
|
||||
err := se.Close()
|
||||
c.Assert(err, IsNil)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user