github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/executor/executor_xapi.go (about)

     1  // Copyright 2016 PingCAP, 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 executor
    15  
    16  import (
    17  	"math"
    18  	"sort"
    19  	"sync"
    20  	"time"
    21  
    22  	"github.com/insionng/yougam/libraries/golang/protobuf/proto"
    23  	"github.com/insionng/yougam/libraries/juju/errors"
    24  	"github.com/insionng/yougam/libraries/ngaut/log"
    25  	"github.com/insionng/yougam/libraries/pingcap/tidb/ast"
    26  	"github.com/insionng/yougam/libraries/pingcap/tidb/context"
    27  	"github.com/insionng/yougam/libraries/pingcap/tidb/evaluator"
    28  	"github.com/insionng/yougam/libraries/pingcap/tidb/kv"
    29  	"github.com/insionng/yougam/libraries/pingcap/tidb/model"
    30  	"github.com/insionng/yougam/libraries/pingcap/tidb/mysql"
    31  	"github.com/insionng/yougam/libraries/pingcap/tidb/optimizer/plan"
    32  	"github.com/insionng/yougam/libraries/pingcap/tidb/parser/opcode"
    33  	"github.com/insionng/yougam/libraries/pingcap/tidb/table"
    34  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/codec"
    35  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/types"
    36  	"github.com/insionng/yougam/libraries/pingcap/tidb/xapi"
    37  	"github.com/insionng/yougam/libraries/pingcap/tidb/xapi/tablecodec"
    38  	"github.com/insionng/yougam/libraries/pingcap/tipb/go-tipb"
    39  )
    40  
    41  // XSelectTableExec represents XAPI select executor.
    42  type XSelectTableExec struct {
    43  	table            table.Table
    44  	tablePlan        *plan.TableScan
    45  	where            *tipb.Expr
    46  	ctx              context.Context
    47  	result           *xapi.SelectResult
    48  	subResult        *xapi.SubResult
    49  	supportDesc      bool
    50  	allFiltersPushed bool
    51  }
    52  
    53  // Next implements Executor Next interface.
    54  func (e *XSelectTableExec) Next() (*Row, error) {
    55  	if e.result == nil {
    56  		err := e.doRequest()
    57  		if err != nil {
    58  			return nil, errors.Trace(err)
    59  		}
    60  	}
    61  	for {
    62  		if e.subResult == nil {
    63  			var err error
    64  			startTs := time.Now()
    65  			e.subResult, err = e.result.Next()
    66  			if err != nil {
    67  				return nil, errors.Trace(err)
    68  			}
    69  			if e.subResult == nil {
    70  				return nil, nil
    71  			}
    72  			log.Debugf("[TIME_TABLE_SCAN] %v", time.Now().Sub(startTs))
    73  		}
    74  		h, rowData, err := e.subResult.Next()
    75  		if err != nil {
    76  			return nil, errors.Trace(err)
    77  		}
    78  		if rowData == nil {
    79  			e.subResult = nil
    80  			continue
    81  		}
    82  		fullRowData := make([]types.Datum, len(e.tablePlan.Fields()))
    83  		var j int
    84  		for i, field := range e.tablePlan.Fields() {
    85  			if field.Referenced {
    86  				fullRowData[i] = rowData[j]
    87  				field.Expr.SetDatum(rowData[j])
    88  				j++
    89  			}
    90  		}
    91  		return resultRowToRow(e.table, h, fullRowData, e.tablePlan.TableAsName), nil
    92  	}
    93  }
    94  
    95  // Fields implements Executor Fields interface.
    96  func (e *XSelectTableExec) Fields() []*ast.ResultField {
    97  	return e.tablePlan.Fields()
    98  }
    99  
   100  // Close implements Executor Close interface.
   101  func (e *XSelectTableExec) Close() error {
   102  	if e.result != nil {
   103  		e.result.Close()
   104  	}
   105  	return nil
   106  }
   107  
   108  func resultRowToRow(t table.Table, h int64, data []types.Datum, tableAsName *model.CIStr) *Row {
   109  	entry := &RowKeyEntry{
   110  		Handle:      h,
   111  		Tbl:         t,
   112  		TableAsName: tableAsName,
   113  	}
   114  	return &Row{Data: data, RowKeys: []*RowKeyEntry{entry}}
   115  }
   116  
   117  func (e *XSelectTableExec) doRequest() error {
   118  	txn, err := e.ctx.GetTxn(false)
   119  	if err != nil {
   120  		return errors.Trace(err)
   121  	}
   122  	selReq := new(tipb.SelectRequest)
   123  	startTs := txn.StartTS()
   124  	selReq.StartTs = &startTs
   125  	selReq.Fields = resultFieldsToPBExpression(e.tablePlan.Fields())
   126  	selReq.Where = e.where
   127  	selReq.Ranges = tableRangesToPBRanges(e.tablePlan.Ranges)
   128  	if e.supportDesc {
   129  		if e.tablePlan.Desc {
   130  			selReq.OrderBy = append(selReq.OrderBy, &tipb.ByItem{Desc: &e.tablePlan.Desc})
   131  		}
   132  		// Limit can be pushed only if desc is supported.
   133  		if e.allFiltersPushed {
   134  			selReq.Limit = e.tablePlan.LimitCount
   135  		}
   136  	}
   137  	columns := make([]*model.ColumnInfo, 0, len(e.tablePlan.Fields()))
   138  	for _, v := range e.tablePlan.Fields() {
   139  		if v.Referenced {
   140  			columns = append(columns, v.Column)
   141  		}
   142  	}
   143  	selReq.TableInfo = &tipb.TableInfo{
   144  		TableId: proto.Int64(e.table.Meta().ID),
   145  	}
   146  	selReq.TableInfo.Columns = tablecodec.ColumnsToProto(columns, e.table.Meta().PKIsHandle)
   147  	e.result, err = xapi.Select(txn.GetClient(), selReq, 1)
   148  	if err != nil {
   149  		return errors.Trace(err)
   150  	}
   151  	return nil
   152  }
   153  
   154  // XSelectIndexExec represents XAPI select index executor.
   155  type XSelectIndexExec struct {
   156  	table       table.Table
   157  	indexPlan   *plan.IndexScan
   158  	ctx         context.Context
   159  	where       *tipb.Expr
   160  	supportDesc bool
   161  
   162  	tasks      []*lookupTableTask
   163  	taskCursor int
   164  	indexOrder map[int64]int
   165  
   166  	mu sync.Mutex
   167  }
   168  
   169  // BaseLookupTableTaskSize represents base number of handles for a lookupTableTask.
   170  var BaseLookupTableTaskSize = 1024
   171  
   172  // MaxLookupTableTaskSize represents max number of handles for a lookupTableTask.
   173  var MaxLookupTableTaskSize = 1024
   174  
   175  const (
   176  	taskNew int = iota
   177  	taskRunning
   178  	taskDone
   179  )
   180  
   181  type lookupTableTask struct {
   182  	handles []int64
   183  	rows    []*Row
   184  	cursor  int
   185  	status  int
   186  	done    bool
   187  	doneCh  chan error
   188  }
   189  
   190  // Fields implements Executor Fields interface.
   191  func (e *XSelectIndexExec) Fields() []*ast.ResultField {
   192  	return e.indexPlan.Fields()
   193  }
   194  
   195  // Next implements Executor Next interface.
   196  func (e *XSelectIndexExec) Next() (*Row, error) {
   197  	if e.tasks == nil {
   198  		startTs := time.Now()
   199  		handles, err := e.fetchHandles()
   200  		if err != nil {
   201  			return nil, errors.Trace(err)
   202  		}
   203  		log.Debugf("[TIME_INDEX_SCAN] time: %v handles: %d", time.Now().Sub(startTs), len(handles))
   204  		e.buildTableTasks(handles)
   205  		limitCount := int64(-1)
   206  		if e.indexPlan.LimitCount != nil {
   207  			limitCount = *e.indexPlan.LimitCount
   208  		}
   209  		concurrency := 2
   210  		if e.indexPlan.NoLimit {
   211  			concurrency = len(e.tasks)
   212  		} else if limitCount > int64(BaseLookupTableTaskSize) {
   213  			concurrency = int(limitCount/int64(BaseLookupTableTaskSize) + 1)
   214  		}
   215  		log.Debugf("[TIME_INDEX_TABLE_CONCURRENT_SCAN] start %d workers", concurrency)
   216  		e.runTableTasks(concurrency)
   217  	}
   218  	for {
   219  		if e.taskCursor >= len(e.tasks) {
   220  			return nil, nil
   221  		}
   222  		task := e.tasks[e.taskCursor]
   223  		if !task.done {
   224  			startTs := time.Now()
   225  			err := <-task.doneCh
   226  			if err != nil {
   227  				return nil, errors.Trace(err)
   228  			}
   229  			task.done = true
   230  			log.Debugf("[TIME_INDEX_TABLE_SCAN] time: %v handles: %d", time.Now().Sub(startTs), len(task.handles))
   231  		}
   232  		if task.cursor < len(task.rows) {
   233  			row := task.rows[task.cursor]
   234  			for i, field := range e.indexPlan.Fields() {
   235  				field.Expr.SetDatum(row.Data[i])
   236  			}
   237  			task.cursor++
   238  			return row, nil
   239  		}
   240  		e.taskCursor++
   241  	}
   242  }
   243  
   244  func (e *XSelectIndexExec) pickAndExecTask() {
   245  	for {
   246  		// Pick a new task.
   247  		e.mu.Lock()
   248  		var task *lookupTableTask
   249  		for _, t := range e.tasks {
   250  			if t.status == taskNew {
   251  				task = t
   252  				task.status = taskRunning
   253  				break
   254  			}
   255  		}
   256  		e.mu.Unlock()
   257  		if task == nil {
   258  			// No more task to run.
   259  			break
   260  		}
   261  		// Execute the picked task.
   262  		err := e.executeTask(task)
   263  		e.mu.Lock()
   264  		task.status = taskDone
   265  		e.mu.Unlock()
   266  		task.doneCh <- err
   267  	}
   268  }
   269  
   270  func (e *XSelectIndexExec) runTableTasks(n int) {
   271  	for i := 0; i < n && i < len(e.tasks); i++ {
   272  		go e.pickAndExecTask()
   273  	}
   274  }
   275  
   276  func (e *XSelectIndexExec) executeTask(task *lookupTableTask) error {
   277  	sort.Sort(int64Slice(task.handles))
   278  	tblResult, err := e.doTableRequest(task.handles)
   279  	if err != nil {
   280  		return errors.Trace(err)
   281  	}
   282  	task.rows, err = e.extractRowsFromTableResult(e.table, tblResult)
   283  	if err != nil {
   284  		return errors.Trace(err)
   285  	}
   286  	if !e.indexPlan.OutOfOrder {
   287  		// Restore the index order.
   288  		sorter := &rowsSorter{order: e.indexOrder, rows: task.rows}
   289  		if e.indexPlan.Desc && !e.supportDesc {
   290  			sort.Sort(sort.Reverse(sorter))
   291  		} else {
   292  			sort.Sort(sorter)
   293  		}
   294  	}
   295  	return nil
   296  }
   297  
   298  // Close implements Executor Close interface.
   299  func (e *XSelectIndexExec) Close() error {
   300  	return nil
   301  }
   302  
   303  // fetchHandle fetches all handles from the index.
   304  // This should be optimized to fetch handles in batch.
   305  func (e *XSelectIndexExec) fetchHandles() ([]int64, error) {
   306  	idxResult, err := e.doIndexRequest()
   307  	if err != nil {
   308  		return nil, errors.Trace(err)
   309  	}
   310  	handles, err := extractHandlesFromIndexResult(idxResult)
   311  	if err != nil {
   312  		return nil, errors.Trace(err)
   313  	}
   314  	if !e.indexPlan.OutOfOrder {
   315  		// Save the index order.
   316  		e.indexOrder = make(map[int64]int)
   317  		for i, h := range handles {
   318  			e.indexOrder[h] = i
   319  		}
   320  	}
   321  	return handles, nil
   322  }
   323  
   324  func (e *XSelectIndexExec) buildTableTasks(handles []int64) {
   325  	// Build tasks with increasing batch size.
   326  	var taskSizes []int
   327  	total := len(handles)
   328  	batchSize := BaseLookupTableTaskSize
   329  	for total > 0 {
   330  		if batchSize > total {
   331  			batchSize = total
   332  		}
   333  		taskSizes = append(taskSizes, batchSize)
   334  		total -= batchSize
   335  		if batchSize < MaxLookupTableTaskSize {
   336  			batchSize *= 2
   337  		}
   338  	}
   339  	if e.indexPlan.Desc && !e.supportDesc {
   340  		// Reverse tasks sizes.
   341  		for i := 0; i < len(taskSizes)/2; i++ {
   342  			j := len(taskSizes) - i - 1
   343  			taskSizes[i], taskSizes[j] = taskSizes[j], taskSizes[i]
   344  		}
   345  	}
   346  	e.tasks = make([]*lookupTableTask, len(taskSizes))
   347  	for i, size := range taskSizes {
   348  		task := &lookupTableTask{
   349  			handles: handles[:size],
   350  		}
   351  		task.doneCh = make(chan error, 1)
   352  		handles = handles[size:]
   353  		e.tasks[i] = task
   354  	}
   355  	if e.indexPlan.Desc && !e.supportDesc {
   356  		// Reverse tasks order.
   357  		for i := 0; i < len(e.tasks)/2; i++ {
   358  			j := len(e.tasks) - i - 1
   359  			e.tasks[i], e.tasks[j] = e.tasks[j], e.tasks[i]
   360  		}
   361  	}
   362  }
   363  
   364  type rowsSorter struct {
   365  	order map[int64]int
   366  	rows  []*Row
   367  }
   368  
   369  func (s *rowsSorter) Less(i, j int) bool {
   370  	x := s.order[s.rows[i].RowKeys[0].Handle]
   371  	y := s.order[s.rows[j].RowKeys[0].Handle]
   372  	return x < y
   373  }
   374  
   375  func (s *rowsSorter) Len() int {
   376  	return len(s.rows)
   377  }
   378  
   379  func (s *rowsSorter) Swap(i, j int) {
   380  	s.rows[i], s.rows[j] = s.rows[j], s.rows[i]
   381  }
   382  
   383  func (e *XSelectIndexExec) doIndexRequest() (*xapi.SelectResult, error) {
   384  	txn, err := e.ctx.GetTxn(false)
   385  	if err != nil {
   386  		return nil, errors.Trace(err)
   387  	}
   388  	selIdxReq := new(tipb.SelectRequest)
   389  	startTs := txn.StartTS()
   390  	selIdxReq.StartTs = &startTs
   391  	selIdxReq.IndexInfo = tablecodec.IndexToProto(e.table.Meta(), e.indexPlan.Index)
   392  	if len(e.indexPlan.FilterConditions) == 0 {
   393  		// Push limit to index request only if there is not filter conditions.
   394  		selIdxReq.Limit = e.indexPlan.LimitCount
   395  	}
   396  	if e.indexPlan.Desc {
   397  		selIdxReq.OrderBy = append(selIdxReq.OrderBy, &tipb.ByItem{Desc: &e.indexPlan.Desc})
   398  	}
   399  	fieldTypes := make([]*types.FieldType, len(e.indexPlan.Index.Columns))
   400  	for i, v := range e.indexPlan.Index.Columns {
   401  		fieldTypes[i] = &(e.table.Cols()[v.Offset].FieldType)
   402  	}
   403  	selIdxReq.Ranges, err = indexRangesToPBRanges(e.indexPlan.Ranges, fieldTypes)
   404  	if err != nil {
   405  		return nil, errors.Trace(err)
   406  	}
   407  	concurrency := 1
   408  	if e.indexPlan.OutOfOrder {
   409  		concurrency = 10
   410  	}
   411  	return xapi.Select(txn.GetClient(), selIdxReq, concurrency)
   412  }
   413  
   414  func (e *XSelectIndexExec) doTableRequest(handles []int64) (*xapi.SelectResult, error) {
   415  	txn, err := e.ctx.GetTxn(false)
   416  	if err != nil {
   417  		return nil, errors.Trace(err)
   418  	}
   419  	// The handles are not in original index order, so we can't push limit here.
   420  	selTableReq := new(tipb.SelectRequest)
   421  	startTs := txn.StartTS()
   422  	selTableReq.StartTs = &startTs
   423  	columns := make([]*model.ColumnInfo, 0, len(e.indexPlan.Fields()))
   424  	for _, v := range e.indexPlan.Fields() {
   425  		if v.Referenced {
   426  			columns = append(columns, v.Column)
   427  		}
   428  	}
   429  	selTableReq.TableInfo = &tipb.TableInfo{
   430  		TableId: proto.Int64(e.table.Meta().ID),
   431  	}
   432  	selTableReq.TableInfo.Columns = tablecodec.ColumnsToProto(columns, e.table.Meta().PKIsHandle)
   433  	selTableReq.Fields = resultFieldsToPBExpression(e.indexPlan.Fields())
   434  	for _, h := range handles {
   435  		if h == math.MaxInt64 {
   436  			// We can't convert MaxInt64 into an left closed, right open range.
   437  			continue
   438  		}
   439  		pbRange := new(tipb.KeyRange)
   440  		pbRange.Low = codec.EncodeInt(nil, h)
   441  		pbRange.High = kv.Key(pbRange.Low).PrefixNext()
   442  		selTableReq.Ranges = append(selTableReq.Ranges, pbRange)
   443  	}
   444  	selTableReq.Where = e.where
   445  	return xapi.Select(txn.GetClient(), selTableReq, 10)
   446  }
   447  
   448  // conditionsToPBExpr tries to convert filter conditions to a tipb.Expr.
   449  // not supported conditions will be returned in remained.
   450  func (b *executorBuilder) conditionsToPBExpr(client kv.Client, exprs []ast.ExprNode, tn *ast.TableName) (pbexpr *tipb.Expr,
   451  	remained []ast.ExprNode) {
   452  	for _, expr := range exprs {
   453  		v := b.exprToPBExpr(client, expr, tn)
   454  		if v == nil {
   455  			remained = append(remained, expr)
   456  		} else {
   457  			if pbexpr == nil {
   458  				pbexpr = v
   459  			} else {
   460  				// merge multiple converted pb expression into an AND expression.
   461  				pbexpr = &tipb.Expr{Tp: tipb.ExprType_And.Enum(), Children: []*tipb.Expr{pbexpr, v}}
   462  			}
   463  		}
   464  	}
   465  	return
   466  }
   467  
   468  func resultFieldsToPBExpression(fields []*ast.ResultField) []*tipb.Expr {
   469  	return nil
   470  }
   471  
   472  func tableRangesToPBRanges(tableRanges []plan.TableRange) []*tipb.KeyRange {
   473  	hrs := make([]*tipb.KeyRange, 0, len(tableRanges))
   474  	for _, tableRange := range tableRanges {
   475  		pbRange := new(tipb.KeyRange)
   476  		pbRange.Low = codec.EncodeInt(nil, tableRange.LowVal)
   477  		hi := tableRange.HighVal
   478  		if hi != math.MaxInt64 {
   479  			hi++
   480  		}
   481  		pbRange.High = codec.EncodeInt(nil, hi)
   482  		hrs = append(hrs, pbRange)
   483  	}
   484  	return hrs
   485  }
   486  
   487  func indexRangesToPBRanges(ranges []*plan.IndexRange, fieldTypes []*types.FieldType) ([]*tipb.KeyRange, error) {
   488  	keyRanges := make([]*tipb.KeyRange, 0, len(ranges))
   489  	for _, ran := range ranges {
   490  		err := convertIndexRangeTypes(ran, fieldTypes)
   491  		if err != nil {
   492  			return nil, errors.Trace(err)
   493  		}
   494  		low, err := codec.EncodeKey(nil, ran.LowVal...)
   495  		if err != nil {
   496  			return nil, errors.Trace(err)
   497  		}
   498  		if ran.LowExclude {
   499  			low = []byte(kv.Key(low).PrefixNext())
   500  		}
   501  		high, err := codec.EncodeKey(nil, ran.HighVal...)
   502  		if err != nil {
   503  			return nil, errors.Trace(err)
   504  		}
   505  		if !ran.HighExclude {
   506  			high = []byte(kv.Key(high).PrefixNext())
   507  		}
   508  		keyRanges = append(keyRanges, &tipb.KeyRange{Low: low, High: high})
   509  	}
   510  	return keyRanges, nil
   511  }
   512  
   513  func convertIndexRangeTypes(ran *plan.IndexRange, fieldTypes []*types.FieldType) error {
   514  	for i := range ran.LowVal {
   515  		if ran.LowVal[i].Kind() == types.KindMinNotNull {
   516  			ran.LowVal[i].SetBytes([]byte{})
   517  			continue
   518  		}
   519  		converted, err := ran.LowVal[i].ConvertTo(fieldTypes[i])
   520  		if err != nil {
   521  			return errors.Trace(err)
   522  		}
   523  		cmp, err := converted.CompareDatum(ran.LowVal[i])
   524  		if err != nil {
   525  			return errors.Trace(err)
   526  		}
   527  		ran.LowVal[i] = converted
   528  		if cmp == 0 {
   529  			continue
   530  		}
   531  		if cmp < 0 && !ran.LowExclude {
   532  			// For int column a, a >= 1.1 is converted to a > 1.
   533  			ran.LowExclude = true
   534  		} else if cmp > 0 && ran.LowExclude {
   535  			// For int column a, a > 1.9 is converted to a >= 2.
   536  			ran.LowExclude = false
   537  		}
   538  		// The converted value has changed, the other column values doesn't matter.
   539  		// For equal condition, converted value changed means there will be no match.
   540  		// For non equal condition, this column would be the last one to build the range.
   541  		// Break here to prevent the rest columns modify LowExclude again.
   542  		break
   543  	}
   544  	for i := range ran.HighVal {
   545  		if ran.HighVal[i].Kind() == types.KindMaxValue {
   546  			continue
   547  		}
   548  		converted, err := ran.HighVal[i].ConvertTo(fieldTypes[i])
   549  		if err != nil {
   550  			return errors.Trace(err)
   551  		}
   552  		cmp, err := converted.CompareDatum(ran.HighVal[i])
   553  		if err != nil {
   554  			return errors.Trace(err)
   555  		}
   556  		ran.HighVal[i] = converted
   557  		if cmp == 0 {
   558  			continue
   559  		}
   560  		// For int column a, a < 1.1 is converted to a <= 1.
   561  		if cmp < 0 && ran.HighExclude {
   562  			ran.HighExclude = false
   563  		}
   564  		// For int column a, a <= 1.9 is converted to a < 2.
   565  		if cmp > 0 && !ran.HighExclude {
   566  			ran.HighExclude = true
   567  		}
   568  		break
   569  	}
   570  	return nil
   571  }
   572  
   573  func extractHandlesFromIndexResult(idxResult *xapi.SelectResult) ([]int64, error) {
   574  	var handles []int64
   575  	for {
   576  		subResult, err := idxResult.Next()
   577  		if err != nil {
   578  			return nil, errors.Trace(err)
   579  		}
   580  		if subResult == nil {
   581  			break
   582  		}
   583  		subHandles, err := extractHandlesFromIndexSubResult(subResult)
   584  		if err != nil {
   585  			return nil, errors.Trace(err)
   586  		}
   587  		handles = append(handles, subHandles...)
   588  	}
   589  	return handles, nil
   590  }
   591  
   592  func extractHandlesFromIndexSubResult(subResult *xapi.SubResult) ([]int64, error) {
   593  	var handles []int64
   594  	for {
   595  		h, data, err := subResult.Next()
   596  		if err != nil {
   597  			return nil, errors.Trace(err)
   598  		}
   599  		if data == nil {
   600  			break
   601  		}
   602  		handles = append(handles, h)
   603  	}
   604  	return handles, nil
   605  }
   606  
   607  func (e *XSelectIndexExec) extractRowsFromTableResult(t table.Table, tblResult *xapi.SelectResult) ([]*Row, error) {
   608  	var rows []*Row
   609  	for {
   610  		subResult, err := tblResult.Next()
   611  		if err != nil {
   612  			return nil, errors.Trace(err)
   613  		}
   614  		if subResult == nil {
   615  			break
   616  		}
   617  		subRows, err := e.extractRowsFromSubResult(t, subResult)
   618  		if err != nil {
   619  			return nil, errors.Trace(err)
   620  		}
   621  		rows = append(rows, subRows...)
   622  	}
   623  	return rows, nil
   624  }
   625  
   626  func (e *XSelectIndexExec) extractRowsFromSubResult(t table.Table, subResult *xapi.SubResult) ([]*Row, error) {
   627  	var rows []*Row
   628  	for {
   629  		h, rowData, err := subResult.Next()
   630  		if err != nil {
   631  			return nil, errors.Trace(err)
   632  		}
   633  		if rowData == nil {
   634  			break
   635  		}
   636  		fullRowData := make([]types.Datum, len(e.indexPlan.Fields()))
   637  		var j int
   638  		for i, field := range e.indexPlan.Fields() {
   639  			if field.Referenced {
   640  				fullRowData[i] = rowData[j]
   641  				j++
   642  			}
   643  		}
   644  		row := resultRowToRow(t, h, fullRowData, e.indexPlan.TableAsName)
   645  		rows = append(rows, row)
   646  	}
   647  	return rows, nil
   648  }
   649  
   650  type int64Slice []int64
   651  
   652  func (p int64Slice) Len() int           { return len(p) }
   653  func (p int64Slice) Less(i, j int) bool { return p[i] < p[j] }
   654  func (p int64Slice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
   655  
   656  // exprToPBExpr converts an ast.ExprNode to a tipb.Expr, if not supported, nil will be returned.
   657  func (b *executorBuilder) exprToPBExpr(client kv.Client, expr ast.ExprNode, tn *ast.TableName) *tipb.Expr {
   658  	switch x := expr.(type) {
   659  	case *ast.ValueExpr, *ast.ParamMarkerExpr:
   660  		return b.datumToPBExpr(client, *expr.GetDatum())
   661  	case *ast.ColumnNameExpr:
   662  		return b.columnNameToPBExpr(client, x, tn)
   663  	case *ast.BinaryOperationExpr:
   664  		return b.binopToPBExpr(client, x, tn)
   665  	case *ast.ParenthesesExpr:
   666  		return b.exprToPBExpr(client, x.Expr, tn)
   667  	case *ast.PatternLikeExpr:
   668  		return b.likeToPBExpr(client, x, tn)
   669  	case *ast.UnaryOperationExpr:
   670  		return b.unaryToPBExpr(client, x, tn)
   671  	case *ast.PatternInExpr:
   672  		return b.patternInToPBExpr(client, x, tn)
   673  	case *ast.SubqueryExpr:
   674  		return b.subqueryToPBExpr(client, x)
   675  	default:
   676  		return nil
   677  	}
   678  }
   679  
   680  func (b *executorBuilder) columnNameToPBExpr(client kv.Client, column *ast.ColumnNameExpr, tn *ast.TableName) *tipb.Expr {
   681  	if !client.SupportRequestType(kv.ReqTypeSelect, int64(tipb.ExprType_ColumnRef)) {
   682  		return nil
   683  	}
   684  	// Zero Column ID is not a column from table, can not support for now.
   685  	if column.Refer.Column.ID == 0 {
   686  		return nil
   687  	}
   688  	switch column.Refer.Expr.GetType().Tp {
   689  	case mysql.TypeBit, mysql.TypeSet, mysql.TypeEnum, mysql.TypeDecimal, mysql.TypeNewDecimal, mysql.TypeGeometry,
   690  		mysql.TypeDate, mysql.TypeNewDate, mysql.TypeDatetime, mysql.TypeDuration, mysql.TypeTimestamp, mysql.TypeYear:
   691  		return nil
   692  	}
   693  	matched := false
   694  	for _, f := range tn.GetResultFields() {
   695  		if f.TableName == column.Refer.TableName && f.Column.ID == column.Refer.Column.ID {
   696  			matched = true
   697  			break
   698  		}
   699  	}
   700  	if matched {
   701  		pbExpr := new(tipb.Expr)
   702  		pbExpr.Tp = tipb.ExprType_ColumnRef.Enum()
   703  		pbExpr.Val = codec.EncodeInt(nil, column.Refer.Column.ID)
   704  		return pbExpr
   705  	}
   706  	// If the column ID is in fields, it means the column is from an outer table,
   707  	// its value is available to use.
   708  	return b.datumToPBExpr(client, *column.Refer.Expr.GetDatum())
   709  }
   710  
   711  func (b *executorBuilder) datumToPBExpr(client kv.Client, d types.Datum) *tipb.Expr {
   712  	var tp tipb.ExprType
   713  	var val []byte
   714  	switch d.Kind() {
   715  	case types.KindNull:
   716  		tp = tipb.ExprType_Null
   717  	case types.KindInt64:
   718  		tp = tipb.ExprType_Int64
   719  		val = codec.EncodeInt(nil, d.GetInt64())
   720  	case types.KindUint64:
   721  		tp = tipb.ExprType_Uint64
   722  		val = codec.EncodeUint(nil, d.GetUint64())
   723  	case types.KindString:
   724  		tp = tipb.ExprType_String
   725  		val = d.GetBytes()
   726  	case types.KindBytes:
   727  		tp = tipb.ExprType_Bytes
   728  		val = d.GetBytes()
   729  	case types.KindFloat32:
   730  		tp = tipb.ExprType_Float32
   731  		val = codec.EncodeFloat(nil, d.GetFloat64())
   732  	case types.KindFloat64:
   733  		tp = tipb.ExprType_Float64
   734  		val = codec.EncodeFloat(nil, d.GetFloat64())
   735  	default:
   736  		return nil
   737  	}
   738  	if !client.SupportRequestType(kv.ReqTypeSelect, int64(tp)) {
   739  		return nil
   740  	}
   741  	return &tipb.Expr{Tp: tp.Enum(), Val: val}
   742  }
   743  
   744  func (b *executorBuilder) binopToPBExpr(client kv.Client, expr *ast.BinaryOperationExpr, tn *ast.TableName) *tipb.Expr {
   745  	var tp tipb.ExprType
   746  	switch expr.Op {
   747  	case opcode.LT:
   748  		tp = tipb.ExprType_LT
   749  	case opcode.LE:
   750  		tp = tipb.ExprType_LE
   751  	case opcode.EQ:
   752  		tp = tipb.ExprType_EQ
   753  	case opcode.NE:
   754  		tp = tipb.ExprType_NE
   755  	case opcode.GE:
   756  		tp = tipb.ExprType_GE
   757  	case opcode.GT:
   758  		tp = tipb.ExprType_GT
   759  	case opcode.NullEQ:
   760  		tp = tipb.ExprType_NullEQ
   761  	case opcode.AndAnd:
   762  		tp = tipb.ExprType_And
   763  	case opcode.OrOr:
   764  		tp = tipb.ExprType_Or
   765  	default:
   766  		return nil
   767  	}
   768  	if !client.SupportRequestType(kv.ReqTypeSelect, int64(tp)) {
   769  		return nil
   770  	}
   771  	leftExpr := b.exprToPBExpr(client, expr.L, tn)
   772  	if leftExpr == nil {
   773  		return nil
   774  	}
   775  	rightExpr := b.exprToPBExpr(client, expr.R, tn)
   776  	if rightExpr == nil {
   777  		return nil
   778  	}
   779  	return &tipb.Expr{Tp: tp.Enum(), Children: []*tipb.Expr{leftExpr, rightExpr}}
   780  }
   781  
   782  // Only patterns like 'abc', '%abc', 'abc%', '%abc%' can be converted to *tipb.Expr for now.
   783  func (b *executorBuilder) likeToPBExpr(client kv.Client, expr *ast.PatternLikeExpr, tn *ast.TableName) *tipb.Expr {
   784  	if expr.Escape != '\\' {
   785  		return nil
   786  	}
   787  	patternDatum := expr.Pattern.GetDatum()
   788  	if patternDatum.Kind() != types.KindString {
   789  		return nil
   790  	}
   791  	patternStr := patternDatum.GetString()
   792  	for i, r := range patternStr {
   793  		switch r {
   794  		case '\\', '_':
   795  			return nil
   796  		case '%':
   797  			if i != 0 && i != len(patternStr)-1 {
   798  				return nil
   799  			}
   800  		}
   801  	}
   802  	patternExpr := b.exprToPBExpr(client, expr.Pattern, tn)
   803  	if patternExpr == nil {
   804  		return nil
   805  	}
   806  	targetExpr := b.exprToPBExpr(client, expr.Expr, tn)
   807  	if targetExpr == nil {
   808  		return nil
   809  	}
   810  	likeExpr := &tipb.Expr{Tp: tipb.ExprType_Like.Enum(), Children: []*tipb.Expr{targetExpr, patternExpr}}
   811  	if !expr.Not {
   812  		return likeExpr
   813  	}
   814  	return &tipb.Expr{Tp: tipb.ExprType_Not.Enum(), Children: []*tipb.Expr{likeExpr}}
   815  }
   816  
   817  func (b *executorBuilder) unaryToPBExpr(client kv.Client, expr *ast.UnaryOperationExpr, tn *ast.TableName) *tipb.Expr {
   818  	switch expr.Op {
   819  	case opcode.Not:
   820  		if !client.SupportRequestType(kv.ReqTypeSelect, int64(tipb.ExprType_Not)) {
   821  			return nil
   822  		}
   823  	default:
   824  		return nil
   825  	}
   826  	child := b.exprToPBExpr(client, expr.V, tn)
   827  	if child == nil {
   828  		return nil
   829  	}
   830  	return &tipb.Expr{Tp: tipb.ExprType_Not.Enum(), Children: []*tipb.Expr{child}}
   831  }
   832  
   833  func (b *executorBuilder) subqueryToPBExpr(client kv.Client, expr *ast.SubqueryExpr) *tipb.Expr {
   834  	if !client.SupportRequestType(kv.ReqTypeSelect, int64(tipb.ExprType_ValueList)) {
   835  		return nil
   836  	}
   837  	if expr.Correlated || len(expr.Query.GetResultFields()) != 1 {
   838  		// We only push down evaluated non-correlated subquery which has only one field.
   839  		return nil
   840  	}
   841  	err := evaluator.EvalSubquery(b.ctx, expr)
   842  	if err != nil {
   843  		b.err = errors.Trace(err)
   844  		return nil
   845  	}
   846  	if expr.Datum.Kind() != types.KindRow {
   847  		// Do not push down datum kind is not row.
   848  		return nil
   849  	}
   850  	return b.datumsToValueList(expr.Datum.GetRow())
   851  }
   852  
   853  func (b *executorBuilder) patternInToPBExpr(client kv.Client, expr *ast.PatternInExpr, tn *ast.TableName) *tipb.Expr {
   854  	if !client.SupportRequestType(kv.ReqTypeSelect, int64(tipb.ExprType_In)) {
   855  		return nil
   856  	}
   857  	pbExpr := b.exprToPBExpr(client, expr.Expr, tn)
   858  	if pbExpr == nil {
   859  		return nil
   860  	}
   861  	var listExpr *tipb.Expr
   862  	if expr.Sel != nil {
   863  		listExpr = b.exprToPBExpr(client, expr.Sel, tn)
   864  	} else {
   865  		listExpr = b.exprListToPBExpr(client, expr.List, tn)
   866  	}
   867  	if listExpr == nil {
   868  		return nil
   869  	}
   870  	inExpr := &tipb.Expr{Tp: tipb.ExprType_In.Enum(), Children: []*tipb.Expr{pbExpr, listExpr}}
   871  	if !expr.Not {
   872  		return inExpr
   873  	}
   874  	return &tipb.Expr{Tp: tipb.ExprType_Not.Enum(), Children: []*tipb.Expr{inExpr}}
   875  }
   876  
   877  func (b *executorBuilder) exprListToPBExpr(client kv.Client, list []ast.ExprNode, tn *ast.TableName) *tipb.Expr {
   878  	if !client.SupportRequestType(kv.ReqTypeSelect, int64(tipb.ExprType_ValueList)) {
   879  		return nil
   880  	}
   881  	// Only list of *ast.ValueExpr can be push down.
   882  	datums := make([]types.Datum, 0, len(list))
   883  	for _, v := range list {
   884  		x, ok := v.(*ast.ValueExpr)
   885  		if !ok {
   886  			return nil
   887  		}
   888  		if b.datumToPBExpr(client, x.Datum) == nil {
   889  			return nil
   890  		}
   891  		datums = append(datums, x.Datum)
   892  	}
   893  	return b.datumsToValueList(datums)
   894  }
   895  
   896  func (b *executorBuilder) datumsToValueList(datums []types.Datum) *tipb.Expr {
   897  	// Don't push value list that has different datum kind.
   898  	prevKind := types.KindNull
   899  	for _, d := range datums {
   900  		if prevKind == types.KindNull {
   901  			prevKind = d.Kind()
   902  		}
   903  		if d.Kind() != types.KindNull && d.Kind() != prevKind {
   904  			return nil
   905  		}
   906  	}
   907  	err := types.SortDatums(datums)
   908  	if err != nil {
   909  		b.err = errors.Trace(err)
   910  		return nil
   911  	}
   912  	val, err := codec.EncodeValue(nil, datums...)
   913  	if err != nil {
   914  		b.err = errors.Trace(err)
   915  		return nil
   916  	}
   917  	return &tipb.Expr{Tp: tipb.ExprType_ValueList.Enum(), Val: val}
   918  }