diff --git a/executor/builder.go b/executor/builder.go index 5848120299..41691995c1 100644 --- a/executor/builder.go +++ b/executor/builder.go @@ -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, diff --git a/executor/executor.go b/executor/executor.go index a00940672e..50fc6cace9 100644 --- a/executor/executor.go +++ b/executor/executor.go @@ -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 diff --git a/kv/index_iter_test.go b/kv/index_iter_test.go index 969e2093d3..4d92eb2ff8 100644 --- a/kv/index_iter_test.go +++ b/kv/index_iter_test.go @@ -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)) +} diff --git a/session_test.go b/session_test.go index 7bfbaf8376..8021ac46a7 100644 --- a/session_test.go +++ b/session_test.go @@ -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) }