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

     1  // Copyright 2015 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 plan
    15  
    16  import (
    17  	"math"
    18  
    19  	"github.com/insionng/yougam/libraries/golang/protobuf/proto"
    20  	"github.com/insionng/yougam/libraries/juju/errors"
    21  	"github.com/insionng/yougam/libraries/ngaut/log"
    22  	"github.com/insionng/yougam/libraries/pingcap/tidb/ast"
    23  	"github.com/insionng/yougam/libraries/pingcap/tidb/infoschema"
    24  	"github.com/insionng/yougam/libraries/pingcap/tidb/model"
    25  	"github.com/insionng/yougam/libraries/pingcap/tidb/mysql"
    26  	"github.com/insionng/yougam/libraries/pingcap/tidb/parser/opcode"
    27  	"github.com/insionng/yougam/libraries/pingcap/tidb/terror"
    28  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/charset"
    29  	"github.com/insionng/yougam/libraries/pingcap/tidb/util/types"
    30  )
    31  
    32  // Error instances.
    33  var (
    34  	ErrUnsupportedType      = terror.ClassOptimizerPlan.New(CodeUnsupportedType, "Unsupported type")
    35  	SystemInternalErrorType = terror.ClassOptimizerPlan.New(SystemInternalError, "System internal error")
    36  )
    37  
    38  // Error codes.
    39  const (
    40  	CodeUnsupportedType terror.ErrCode = 1
    41  	SystemInternalError terror.ErrCode = 2
    42  )
    43  
    44  // BuildPlan builds a plan from a node.
    45  // It returns ErrUnsupportedType if ast.Node type is not supported yet.
    46  func BuildPlan(node ast.Node, sb SubQueryBuilder) (Plan, error) {
    47  	builder := planBuilder{sb: sb}
    48  	p := builder.build(node)
    49  	return p, builder.err
    50  }
    51  
    52  // planBuilder builds Plan from an ast.Node.
    53  // It just builds the ast node straightforwardly.
    54  type planBuilder struct {
    55  	err    error
    56  	hasAgg bool
    57  	sb     SubQueryBuilder
    58  	obj    interface{}
    59  }
    60  
    61  func (b *planBuilder) build(node ast.Node) Plan {
    62  	switch x := node.(type) {
    63  	case *ast.AdminStmt:
    64  		return b.buildAdmin(x)
    65  	case *ast.AlterTableStmt:
    66  		return b.buildDDL(x)
    67  	case *ast.CreateDatabaseStmt:
    68  		return b.buildDDL(x)
    69  	case *ast.CreateIndexStmt:
    70  		return b.buildDDL(x)
    71  	case *ast.CreateTableStmt:
    72  		return b.buildDDL(x)
    73  	case *ast.DeallocateStmt:
    74  		return &Deallocate{Name: x.Name}
    75  	case *ast.DeleteStmt:
    76  		return b.buildDelete(x)
    77  	case *ast.DropDatabaseStmt:
    78  		return b.buildDDL(x)
    79  	case *ast.DropIndexStmt:
    80  		return b.buildDDL(x)
    81  	case *ast.DropTableStmt:
    82  		return b.buildDDL(x)
    83  	case *ast.ExecuteStmt:
    84  		return &Execute{Name: x.Name, UsingVars: x.UsingVars}
    85  	case *ast.ExplainStmt:
    86  		return b.buildExplain(x)
    87  	case *ast.InsertStmt:
    88  		return b.buildInsert(x)
    89  	case *ast.PrepareStmt:
    90  		return b.buildPrepare(x)
    91  	case *ast.SelectStmt:
    92  		if UseNewPlanner {
    93  			return b.buildNewSelect(x)
    94  		}
    95  		return b.buildSelect(x)
    96  	case *ast.UnionStmt:
    97  		return b.buildUnion(x)
    98  	case *ast.UpdateStmt:
    99  		return b.buildUpdate(x)
   100  	case *ast.UseStmt:
   101  		return b.buildSimple(x)
   102  	case *ast.SetCharsetStmt:
   103  		return b.buildSimple(x)
   104  	case *ast.SetStmt:
   105  		return b.buildSimple(x)
   106  	case *ast.ShowStmt:
   107  		return b.buildShow(x)
   108  	case *ast.DoStmt:
   109  		return b.buildSimple(x)
   110  	case *ast.BeginStmt:
   111  		return b.buildSimple(x)
   112  	case *ast.CommitStmt:
   113  		return b.buildSimple(x)
   114  	case *ast.RollbackStmt:
   115  		return b.buildSimple(x)
   116  	case *ast.CreateUserStmt:
   117  		return b.buildSimple(x)
   118  	case *ast.SetPwdStmt:
   119  		return b.buildSimple(x)
   120  	case *ast.GrantStmt:
   121  		return b.buildSimple(x)
   122  	case *ast.TruncateTableStmt:
   123  		return b.buildDDL(x)
   124  	}
   125  	b.err = ErrUnsupportedType.Gen("Unsupported type %T", node)
   126  	return nil
   127  }
   128  
   129  // Detect aggregate function or groupby clause.
   130  func (b *planBuilder) detectSelectAgg(sel *ast.SelectStmt) bool {
   131  	if sel.GroupBy != nil {
   132  		return true
   133  	}
   134  	for _, f := range sel.GetResultFields() {
   135  		if ast.HasAggFlag(f.Expr) {
   136  			return true
   137  		}
   138  	}
   139  	if sel.Having != nil {
   140  		if ast.HasAggFlag(sel.Having.Expr) {
   141  			return true
   142  		}
   143  	}
   144  	if sel.OrderBy != nil {
   145  		for _, item := range sel.OrderBy.Items {
   146  			if ast.HasAggFlag(item.Expr) {
   147  				return true
   148  			}
   149  		}
   150  	}
   151  	return false
   152  }
   153  
   154  // extractSelectAgg extracts aggregate functions and converts ColumnNameExpr to aggregate function.
   155  func (b *planBuilder) extractSelectAgg(sel *ast.SelectStmt) []*ast.AggregateFuncExpr {
   156  	extractor := &ast.AggregateFuncExtractor{AggFuncs: make([]*ast.AggregateFuncExpr, 0)}
   157  	for _, f := range sel.GetResultFields() {
   158  		n, ok := f.Expr.Accept(extractor)
   159  		if !ok {
   160  			b.err = errors.New("Failed to extract agg expr!")
   161  			return nil
   162  		}
   163  		ve, ok := f.Expr.(*ast.ValueExpr)
   164  		if ok && len(f.Column.Name.O) > 0 {
   165  			agg := &ast.AggregateFuncExpr{
   166  				F:    ast.AggFuncFirstRow,
   167  				Args: []ast.ExprNode{ve},
   168  			}
   169  			extractor.AggFuncs = append(extractor.AggFuncs, agg)
   170  			n = agg
   171  		}
   172  		f.Expr = n.(ast.ExprNode)
   173  	}
   174  	// Extract agg funcs from having clause.
   175  	if sel.Having != nil {
   176  		n, ok := sel.Having.Expr.Accept(extractor)
   177  		if !ok {
   178  			b.err = errors.New("Failed to extract agg expr from having clause")
   179  			return nil
   180  		}
   181  		sel.Having.Expr = n.(ast.ExprNode)
   182  	}
   183  	// Extract agg funcs from orderby clause.
   184  	if sel.OrderBy != nil {
   185  		for _, item := range sel.OrderBy.Items {
   186  			n, ok := item.Expr.Accept(extractor)
   187  			if !ok {
   188  				b.err = errors.New("Failed to extract agg expr from orderby clause")
   189  				return nil
   190  			}
   191  			item.Expr = n.(ast.ExprNode)
   192  			// If item is PositionExpr, we need to rebind it.
   193  			// For PositionExpr will refer to a ResultField in fieldlist.
   194  			// After extract AggExpr from fieldlist, it may be changed (See the code above).
   195  			if pe, ok := item.Expr.(*ast.PositionExpr); ok {
   196  				pe.Refer = sel.GetResultFields()[pe.N-1]
   197  			}
   198  		}
   199  	}
   200  	return extractor.AggFuncs
   201  }
   202  
   203  func (b *planBuilder) buildSubquery(n ast.Node) {
   204  	sv := &subqueryVisitor{
   205  		builder: b,
   206  	}
   207  	_, ok := n.Accept(sv)
   208  	if !ok {
   209  		log.Errorf("Extract subquery error")
   210  	}
   211  }
   212  
   213  func (b *planBuilder) buildSelect(sel *ast.SelectStmt) Plan {
   214  	var aggFuncs []*ast.AggregateFuncExpr
   215  	hasAgg := b.detectSelectAgg(sel)
   216  	canPushLimit := !hasAgg
   217  	if hasAgg {
   218  		aggFuncs = b.extractSelectAgg(sel)
   219  	}
   220  	// Build subquery
   221  	// Convert subquery to expr with plan
   222  	b.buildSubquery(sel)
   223  	var p Plan
   224  	if sel.From != nil {
   225  		p = b.buildFrom(sel)
   226  		if b.err != nil {
   227  			return nil
   228  		}
   229  		if sel.LockTp != ast.SelectLockNone {
   230  			p = b.buildSelectLock(p, sel.LockTp)
   231  			if b.err != nil {
   232  				return nil
   233  			}
   234  		}
   235  		if hasAgg {
   236  			p = b.buildAggregate(p, aggFuncs, sel.GroupBy)
   237  		}
   238  		p = b.buildSelectFields(p, sel.GetResultFields())
   239  		if b.err != nil {
   240  			return nil
   241  		}
   242  	} else {
   243  		canPushLimit = false
   244  		if sel.Where != nil {
   245  			p = b.buildTableDual(sel)
   246  		}
   247  		if hasAgg {
   248  			p = b.buildAggregate(p, aggFuncs, nil)
   249  		}
   250  		p = b.buildSelectFields(p, sel.GetResultFields())
   251  		if b.err != nil {
   252  			return nil
   253  		}
   254  	}
   255  	if sel.Having != nil {
   256  		p = b.buildHaving(p, sel.Having)
   257  		if b.err != nil {
   258  			return nil
   259  		}
   260  	}
   261  	if sel.Distinct {
   262  		canPushLimit = false
   263  		p = b.buildDistinct(p)
   264  		if b.err != nil {
   265  			return nil
   266  		}
   267  	}
   268  	if sel.OrderBy != nil && !pushOrder(p, sel.OrderBy.Items) {
   269  		canPushLimit = false
   270  		p = b.buildSort(p, sel.OrderBy.Items)
   271  		if b.err != nil {
   272  			return nil
   273  		}
   274  	}
   275  	if sel.Limit != nil {
   276  		if canPushLimit {
   277  			pushLimit(p, sel.Limit)
   278  		}
   279  		p = b.buildLimit(p, sel.Limit)
   280  		if b.err != nil {
   281  			return nil
   282  		}
   283  	}
   284  	return p
   285  }
   286  
   287  func (b *planBuilder) buildFrom(sel *ast.SelectStmt) Plan {
   288  	from := sel.From.TableRefs
   289  	if from.Right == nil {
   290  		return b.buildTableSource(sel)
   291  	}
   292  	return b.buildJoin(sel)
   293  }
   294  
   295  func (b *planBuilder) buildTableSource(sel *ast.SelectStmt) Plan {
   296  	from := sel.From.TableRefs
   297  	ts, ok := from.Left.(*ast.TableSource)
   298  	if !ok {
   299  		b.err = ErrUnsupportedType.Gen("Unsupported type %T", from.Left)
   300  		return nil
   301  	}
   302  	var bestPlan Plan
   303  	switch v := ts.Source.(type) {
   304  	case *ast.TableName:
   305  	case *ast.SelectStmt:
   306  		bestPlan = b.buildSelect(v)
   307  	case *ast.UnionStmt:
   308  		bestPlan = b.buildUnion(v)
   309  	}
   310  	if bestPlan != nil {
   311  		return bestPlan
   312  	}
   313  	tn, ok := ts.Source.(*ast.TableName)
   314  	if !ok {
   315  		b.err = ErrUnsupportedType.Gen("Unsupported type %T", ts.Source)
   316  		return nil
   317  	}
   318  	conditions := splitWhere(sel.Where)
   319  	path := &joinPath{table: tn, conditions: conditions}
   320  	candidates := b.buildAllAccessMethodsPlan(path)
   321  	var lowestCost float64
   322  	for _, v := range candidates {
   323  		cost := EstimateCost(b.buildPseudoSelectPlan(v, sel))
   324  		if bestPlan == nil {
   325  			bestPlan = v
   326  			lowestCost = cost
   327  		}
   328  		if cost <= lowestCost {
   329  			bestPlan = v
   330  			lowestCost = cost
   331  		}
   332  	}
   333  	return bestPlan
   334  }
   335  
   336  func (b *planBuilder) buildAllAccessMethodsPlan(path *joinPath) []Plan {
   337  	indices, includeTableScan := b.availableIndices(path.table)
   338  	var candidates []Plan
   339  	if includeTableScan {
   340  		p := b.buildTableScanPlan(path)
   341  		candidates = append(candidates, p)
   342  	}
   343  	for _, index := range indices {
   344  		ip := b.buildIndexScanPlan(index, path)
   345  		candidates = append(candidates, ip)
   346  	}
   347  	return candidates
   348  }
   349  
   350  func (b *planBuilder) availableIndices(table *ast.TableName) (indices []*model.IndexInfo, includeTableScan bool) {
   351  	var usableHints []*ast.IndexHint
   352  	for _, hint := range table.IndexHints {
   353  		if hint.HintScope == ast.HintForScan {
   354  			usableHints = append(usableHints, hint)
   355  		}
   356  	}
   357  	if len(usableHints) == 0 {
   358  		return table.TableInfo.Indices, true
   359  	}
   360  	var hasUse bool
   361  	var ignores []*model.IndexInfo
   362  	for _, hint := range usableHints {
   363  		switch hint.HintType {
   364  		case ast.HintUse, ast.HintForce:
   365  			// Currently we don't distinguish between Force and Use because our cost estimation is not reliable.
   366  			hasUse = true
   367  			for _, idxName := range hint.IndexNames {
   368  				idx := findIndexByName(table.TableInfo.Indices, idxName)
   369  				if idx != nil {
   370  					indices = append(indices, idx)
   371  				}
   372  			}
   373  		case ast.HintIgnore:
   374  			// Collect all the ignore index hints.
   375  			for _, idxName := range hint.IndexNames {
   376  				idx := findIndexByName(table.TableInfo.Indices, idxName)
   377  				if idx != nil {
   378  					ignores = append(ignores, idx)
   379  				}
   380  			}
   381  		}
   382  	}
   383  	indices = removeIgnores(indices, ignores)
   384  	// If we have got FORCE or USE index hint, table scan is excluded.
   385  	if len(indices) != 0 {
   386  		return indices, false
   387  	}
   388  	if hasUse {
   389  		// Empty use hint means don't use any index.
   390  		return nil, true
   391  	}
   392  	if len(ignores) == 0 {
   393  		return table.TableInfo.Indices, true
   394  	}
   395  	for _, idx := range table.TableInfo.Indices {
   396  		// Exclude ignored index.
   397  		if findIndexByName(ignores, idx.Name) == nil {
   398  			indices = append(indices, idx)
   399  		}
   400  	}
   401  	return indices, true
   402  }
   403  
   404  func removeIgnores(indices, ignores []*model.IndexInfo) []*model.IndexInfo {
   405  	if len(ignores) == 0 {
   406  		return indices
   407  	}
   408  	var remainedIndices []*model.IndexInfo
   409  	for _, index := range indices {
   410  		if findIndexByName(ignores, index.Name) == nil {
   411  			remainedIndices = append(remainedIndices, index)
   412  		}
   413  	}
   414  	return remainedIndices
   415  }
   416  
   417  func findIndexByName(indices []*model.IndexInfo, name model.CIStr) *model.IndexInfo {
   418  	for _, idx := range indices {
   419  		if idx.Name.L == name.L {
   420  			return idx
   421  		}
   422  	}
   423  	return nil
   424  }
   425  
   426  func (b *planBuilder) buildTableDual(sel *ast.SelectStmt) Plan {
   427  	dual := &TableDual{FilterConditions: splitWhere(sel.Where)}
   428  	ret := ast.ResultField{}
   429  	dual.SetFields([]*ast.ResultField{&ret})
   430  	return dual
   431  }
   432  
   433  func getTableAsName(fields []*ast.ResultField) *model.CIStr {
   434  	if len(fields) > 0 {
   435  		return &fields[0].TableAsName
   436  	}
   437  	return nil
   438  }
   439  
   440  func (b *planBuilder) buildTableScanPlan(path *joinPath) Plan {
   441  	tn := path.table
   442  	p := &TableScan{
   443  		Table:     tn.TableInfo,
   444  		TableName: tn,
   445  	}
   446  	// Equal condition contains a column from previous joined table.
   447  	p.RefAccess = len(path.eqConds) > 0
   448  	p.SetFields(tn.GetResultFields())
   449  	p.TableAsName = getTableAsName(p.Fields())
   450  	var pkName model.CIStr
   451  	if p.Table.PKIsHandle {
   452  		for _, colInfo := range p.Table.Columns {
   453  			if mysql.HasPriKeyFlag(colInfo.Flag) {
   454  				pkName = colInfo.Name
   455  			}
   456  		}
   457  	}
   458  	for _, con := range path.conditions {
   459  		if pkName.L != "" {
   460  			checker := conditionChecker{tableName: tn.TableInfo.Name, pkName: pkName}
   461  			if checker.check(con) {
   462  				p.AccessConditions = append(p.AccessConditions, con)
   463  			} else {
   464  				p.FilterConditions = append(p.FilterConditions, con)
   465  			}
   466  		} else {
   467  			p.FilterConditions = append(p.FilterConditions, con)
   468  		}
   469  	}
   470  	return p
   471  }
   472  
   473  func (b *planBuilder) buildIndexScanPlan(index *model.IndexInfo, path *joinPath) Plan {
   474  	tn := path.table
   475  	ip := &IndexScan{Table: tn.TableInfo, Index: index, TableName: tn}
   476  	ip.RefAccess = len(path.eqConds) > 0
   477  	ip.SetFields(tn.GetResultFields())
   478  	ip.TableAsName = getTableAsName(ip.Fields())
   479  
   480  	condMap := map[ast.ExprNode]bool{}
   481  	for _, con := range path.conditions {
   482  		condMap[con] = true
   483  	}
   484  out:
   485  	// Build equal access conditions first.
   486  	// Starts from the first index column, if equal condition is found, add it to access conditions,
   487  	// proceed to the next index column. until we can't find any equal condition for the column.
   488  	for ip.AccessEqualCount < len(index.Columns) {
   489  		for con := range condMap {
   490  			binop, ok := con.(*ast.BinaryOperationExpr)
   491  			if !ok || binop.Op != opcode.EQ {
   492  				continue
   493  			}
   494  			if ast.IsPreEvaluable(binop.L) {
   495  				binop.L, binop.R = binop.R, binop.L
   496  			}
   497  			if !ast.IsPreEvaluable(binop.R) {
   498  				continue
   499  			}
   500  			cn, ok2 := binop.L.(*ast.ColumnNameExpr)
   501  			if !ok2 || cn.Refer.Column.Name.L != index.Columns[ip.AccessEqualCount].Name.L {
   502  				continue
   503  			}
   504  			ip.AccessConditions = append(ip.AccessConditions, con)
   505  			delete(condMap, con)
   506  			ip.AccessEqualCount++
   507  			continue out
   508  		}
   509  		break
   510  	}
   511  
   512  	for con := range condMap {
   513  		if ip.AccessEqualCount < len(ip.Index.Columns) {
   514  			// Try to add non-equal access condition for index column at AccessEqualCount.
   515  			checker := conditionChecker{tableName: tn.TableInfo.Name, idx: index, columnOffset: ip.AccessEqualCount}
   516  			if checker.check(con) {
   517  				ip.AccessConditions = append(ip.AccessConditions, con)
   518  			} else {
   519  				ip.FilterConditions = append(ip.FilterConditions, con)
   520  			}
   521  		} else {
   522  			ip.FilterConditions = append(ip.FilterConditions, con)
   523  		}
   524  	}
   525  	return ip
   526  }
   527  
   528  // buildPseudoSelectPlan pre-builds more complete plans that may affect total cost.
   529  // Also set OutOfOrder and NoLimit property.
   530  func (b *planBuilder) buildPseudoSelectPlan(p Plan, sel *ast.SelectStmt) Plan {
   531  	if sel.OrderBy == nil {
   532  		return p
   533  	}
   534  	if sel.GroupBy != nil {
   535  		return p
   536  	}
   537  	if !pushOrder(p, sel.OrderBy.Items) {
   538  		switch x := p.(type) {
   539  		case *IndexScan:
   540  			x.OutOfOrder = true
   541  			x.NoLimit = true
   542  		}
   543  		np := &Sort{ByItems: sel.OrderBy.Items}
   544  		addChild(np, p)
   545  		p = np
   546  	}
   547  	if sel.Limit != nil {
   548  		np := &Limit{Offset: sel.Limit.Offset, Count: sel.Limit.Count}
   549  		addChild(np, p)
   550  		np.SetLimit(0)
   551  		p = np
   552  	} else {
   553  		switch x := p.(type) {
   554  		case *IndexScan:
   555  			x.NoLimit = true
   556  		}
   557  	}
   558  	return p
   559  }
   560  
   561  func (b *planBuilder) buildSelectLock(src Plan, lock ast.SelectLockType) *SelectLock {
   562  	selectLock := &SelectLock{
   563  		Lock: lock,
   564  	}
   565  	addChild(selectLock, src)
   566  	selectLock.SetFields(src.Fields())
   567  	return selectLock
   568  }
   569  
   570  func (b *planBuilder) buildSelectFields(src Plan, fields []*ast.ResultField) Plan {
   571  	selectFields := &SelectFields{}
   572  	addChild(selectFields, src)
   573  	selectFields.SetFields(fields)
   574  	return selectFields
   575  }
   576  
   577  func (b *planBuilder) buildAggregate(src Plan, aggFuncs []*ast.AggregateFuncExpr, groupby *ast.GroupByClause) Plan {
   578  	// Add aggregate plan.
   579  	aggPlan := &Aggregate{
   580  		AggFuncs: aggFuncs,
   581  	}
   582  	addChild(aggPlan, src)
   583  	if src != nil {
   584  		aggPlan.SetFields(src.Fields())
   585  	}
   586  	if groupby != nil {
   587  		aggPlan.GroupByItems = groupby.Items
   588  	}
   589  	return aggPlan
   590  }
   591  
   592  func (b *planBuilder) buildHaving(src Plan, having *ast.HavingClause) Plan {
   593  	p := &Having{
   594  		Conditions: splitWhere(having.Expr),
   595  	}
   596  	addChild(p, src)
   597  	p.SetFields(src.Fields())
   598  	return p
   599  }
   600  
   601  func (b *planBuilder) buildSort(src Plan, byItems []*ast.ByItem) Plan {
   602  	sort := &Sort{
   603  		ByItems: byItems,
   604  	}
   605  	addChild(sort, src)
   606  	sort.SetFields(src.Fields())
   607  	return sort
   608  }
   609  
   610  func (b *planBuilder) buildLimit(src Plan, limit *ast.Limit) Plan {
   611  	li := &Limit{
   612  		Offset: limit.Offset,
   613  		Count:  limit.Count,
   614  	}
   615  	if s, ok := src.(*Sort); ok {
   616  		s.ExecLimit = li
   617  		return s
   618  	}
   619  	addChild(li, src)
   620  	li.SetFields(src.Fields())
   621  	return li
   622  }
   623  
   624  func (b *planBuilder) buildPrepare(x *ast.PrepareStmt) Plan {
   625  	p := &Prepare{
   626  		Name: x.Name,
   627  	}
   628  	if x.SQLVar != nil {
   629  		p.SQLText, _ = x.SQLVar.GetValue().(string)
   630  	} else {
   631  		p.SQLText = x.SQLText
   632  	}
   633  	return p
   634  }
   635  
   636  func (b *planBuilder) buildAdmin(as *ast.AdminStmt) Plan {
   637  	var p Plan
   638  
   639  	switch as.Tp {
   640  	case ast.AdminCheckTable:
   641  		p = &CheckTable{Tables: as.Tables}
   642  	case ast.AdminShowDDL:
   643  		p = &ShowDDL{}
   644  		p.SetFields(buildShowDDLFields())
   645  	default:
   646  		b.err = ErrUnsupportedType.Gen("Unsupported type %T", as)
   647  	}
   648  
   649  	return p
   650  }
   651  
   652  func buildShowDDLFields() []*ast.ResultField {
   653  	rfs := make([]*ast.ResultField, 0, 6)
   654  	rfs = append(rfs, buildResultField("", "SCHEMA_VER", mysql.TypeLonglong, 4))
   655  	rfs = append(rfs, buildResultField("", "OWNER", mysql.TypeVarchar, 64))
   656  	rfs = append(rfs, buildResultField("", "JOB", mysql.TypeVarchar, 128))
   657  	rfs = append(rfs, buildResultField("", "BG_SCHEMA_VER", mysql.TypeLonglong, 4))
   658  	rfs = append(rfs, buildResultField("", "BG_OWNER", mysql.TypeVarchar, 64))
   659  	rfs = append(rfs, buildResultField("", "BG_JOB", mysql.TypeVarchar, 128))
   660  
   661  	return rfs
   662  }
   663  
   664  func buildResultField(tableName, name string, tp byte, size int) *ast.ResultField {
   665  	cs := charset.CharsetBin
   666  	cl := charset.CharsetBin
   667  	flag := mysql.UnsignedFlag
   668  	if tp == mysql.TypeVarchar || tp == mysql.TypeBlob {
   669  		cs = mysql.DefaultCharset
   670  		cl = mysql.DefaultCollationName
   671  		flag = 0
   672  	}
   673  
   674  	fieldType := types.FieldType{
   675  		Charset: cs,
   676  		Collate: cl,
   677  		Tp:      tp,
   678  		Flen:    size,
   679  		Flag:    uint(flag),
   680  	}
   681  	colInfo := &model.ColumnInfo{
   682  		Name:      model.NewCIStr(name),
   683  		FieldType: fieldType,
   684  	}
   685  	expr := &ast.ValueExpr{}
   686  	expr.SetType(&fieldType)
   687  
   688  	return &ast.ResultField{
   689  		Column:       colInfo,
   690  		ColumnAsName: colInfo.Name,
   691  		TableAsName:  model.NewCIStr(tableName),
   692  		DBName:       model.NewCIStr(infoschema.Name),
   693  		Expr:         expr,
   694  	}
   695  }
   696  
   697  func pushLimit(p Plan, limit *ast.Limit) {
   698  	switch x := p.(type) {
   699  	case *IndexScan:
   700  		limitCount := limit.Offset + limit.Count
   701  		if limitCount < math.MaxInt64 {
   702  			x.LimitCount = proto.Int64(int64(limitCount))
   703  		}
   704  	case *TableScan:
   705  		limitCount := limit.Offset + limit.Count
   706  		if limitCount < math.MaxInt64 {
   707  			x.LimitCount = proto.Int64(int64(limitCount))
   708  		}
   709  	default:
   710  		child := x.GetChildByIndex(0)
   711  		if child != nil {
   712  			pushLimit(child, limit)
   713  		}
   714  	}
   715  }
   716  
   717  // pushOrder tries to push order by items to the plan, returns true if
   718  // order is pushed.
   719  func pushOrder(p Plan, items []*ast.ByItem) bool {
   720  	switch x := p.(type) {
   721  	case *Aggregate:
   722  		return false
   723  	case *IndexScan:
   724  		if len(items) > len(x.Index.Columns) {
   725  			return false
   726  		}
   727  		var hasDesc bool
   728  		var hasAsc bool
   729  		for i, item := range items {
   730  			var rf *ast.ResultField
   731  			switch y := item.Expr.(type) {
   732  			case *ast.ColumnNameExpr:
   733  				rf = y.Refer
   734  			case *ast.PositionExpr:
   735  				rf = y.Refer
   736  			default:
   737  				return false
   738  			}
   739  			if rf.Table.Name.L != x.Table.Name.L || rf.Column.Name.L != x.Index.Columns[i].Name.L {
   740  				return false
   741  			}
   742  			if item.Desc {
   743  				if hasAsc {
   744  					return false
   745  				}
   746  				hasDesc = true
   747  			} else {
   748  				if hasDesc {
   749  					return false
   750  				}
   751  				hasAsc = true
   752  			}
   753  		}
   754  		x.Desc = hasDesc
   755  		return true
   756  	case *TableScan:
   757  		if len(items) != 1 || !x.Table.PKIsHandle {
   758  			return false
   759  		}
   760  		var refer *ast.ResultField
   761  		switch x := items[0].Expr.(type) {
   762  		case *ast.ColumnNameExpr:
   763  			refer = x.Refer
   764  		case *ast.PositionExpr:
   765  			refer = x.Refer
   766  		default:
   767  			return false
   768  		}
   769  		if mysql.HasPriKeyFlag(refer.Column.Flag) {
   770  			x.Desc = items[0].Desc
   771  			return true
   772  		}
   773  		return false
   774  	case *JoinOuter:
   775  		return false
   776  	case *JoinInner:
   777  		return false
   778  	case *Sort:
   779  		// Sort plan should not be checked here as there should only be one sort plan in a plan tree.
   780  		return false
   781  	default:
   782  		child := x.GetChildByIndex(0)
   783  		if child != nil {
   784  			return pushOrder(child, items)
   785  		}
   786  	}
   787  	return false
   788  }
   789  
   790  // splitWhere split a where expression to a list of AND conditions.
   791  func splitWhere(where ast.ExprNode) []ast.ExprNode {
   792  	var conditions []ast.ExprNode
   793  	switch x := where.(type) {
   794  	case nil:
   795  	case *ast.BinaryOperationExpr:
   796  		if x.Op == opcode.AndAnd {
   797  			conditions = append(conditions, splitWhere(x.L)...)
   798  			conditions = append(conditions, splitWhere(x.R)...)
   799  		} else {
   800  			conditions = append(conditions, x)
   801  		}
   802  	case *ast.ParenthesesExpr:
   803  		conditions = append(conditions, splitWhere(x.Expr)...)
   804  	default:
   805  		conditions = append(conditions, where)
   806  	}
   807  	return conditions
   808  }
   809  
   810  // SubQueryBuilder is the interface for building SubQuery executor.
   811  type SubQueryBuilder interface {
   812  	Build(p Plan) ast.SubqueryExec
   813  }
   814  
   815  // subqueryVisitor visits AST and handles SubqueryExpr.
   816  type subqueryVisitor struct {
   817  	builder *planBuilder
   818  }
   819  
   820  func (se *subqueryVisitor) Enter(in ast.Node) (out ast.Node, skipChildren bool) {
   821  	switch x := in.(type) {
   822  	case *ast.SubqueryExpr:
   823  		p := se.builder.build(x.Query)
   824  		// The expr pointor is copyed into ResultField when running name resolver.
   825  		// So we can not just replace the expr node in AST. We need to put SubQuery into the expr.
   826  		// See: optimizer.nameResolver.createResultFields()
   827  		x.SubqueryExec = se.builder.sb.Build(p)
   828  		return in, true
   829  	case *ast.Join:
   830  		// SubSelect in from clause will be handled in buildJoin().
   831  		return in, true
   832  	}
   833  	return in, false
   834  }
   835  
   836  func (se *subqueryVisitor) Leave(in ast.Node) (out ast.Node, ok bool) {
   837  	return in, true
   838  }
   839  
   840  func (b *planBuilder) buildUnion(union *ast.UnionStmt) Plan {
   841  	sels := make([]Plan, len(union.SelectList.Selects))
   842  	for i, sel := range union.SelectList.Selects {
   843  		if UseNewPlanner {
   844  			sels[i] = b.buildNewSelect(sel)
   845  		} else {
   846  			sels[i] = b.buildSelect(sel)
   847  		}
   848  	}
   849  	var p Plan
   850  	p = &Union{
   851  		Selects: sels,
   852  		basePlan: basePlan{
   853  			children: sels,
   854  		},
   855  	}
   856  	unionFields := union.GetResultFields()
   857  	for _, sel := range sels {
   858  		for i, f := range sel.Fields() {
   859  			if i == len(unionFields) {
   860  				b.err = errors.New("The used SELECT statements have a different number of columns")
   861  				return nil
   862  			}
   863  			uField := unionFields[i]
   864  			/*
   865  			 * The lengths of the columns in the UNION result take into account the values retrieved by all of the SELECT statements
   866  			 * SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);
   867  			 * +---------------+
   868  			 * | REPEAT('a',1) |
   869  			 * +---------------+
   870  			 * | a             |
   871  			 * | bbbbbbbbbb    |
   872  			 * +---------------+
   873  			 */
   874  			if f.Column.Flen > uField.Column.Flen {
   875  				uField.Column.Flen = f.Column.Flen
   876  			}
   877  			// For select nul union select "abc", we should not convert "abc" to nil.
   878  			// And the result field type should be VARCHAR.
   879  			if uField.Column.Tp == 0 || uField.Column.Tp == mysql.TypeNull {
   880  				uField.Column.Tp = f.Column.Tp
   881  			}
   882  		}
   883  		addChild(p, sel)
   884  	}
   885  	for _, v := range unionFields {
   886  		v.Expr.SetType(&v.Column.FieldType)
   887  	}
   888  
   889  	p.SetFields(unionFields)
   890  	if union.Distinct {
   891  		p = b.buildDistinct(p)
   892  	}
   893  	if union.OrderBy != nil {
   894  		p = b.buildSort(p, union.OrderBy.Items)
   895  	}
   896  	if union.Limit != nil {
   897  		p = b.buildLimit(p, union.Limit)
   898  	}
   899  	return p
   900  }
   901  
   902  func (b *planBuilder) buildDistinct(src Plan) Plan {
   903  	d := &Distinct{}
   904  	addChild(d, src)
   905  	d.SetFields(src.Fields())
   906  	return d
   907  }
   908  
   909  func (b *planBuilder) buildUpdate(update *ast.UpdateStmt) Plan {
   910  	sel := &ast.SelectStmt{From: update.TableRefs, Where: update.Where, OrderBy: update.Order, Limit: update.Limit}
   911  	p := b.buildFrom(sel)
   912  	for _, v := range p.Fields() {
   913  		v.Referenced = true
   914  	}
   915  	if sel.OrderBy != nil && !pushOrder(p, sel.OrderBy.Items) {
   916  		p = b.buildSort(p, sel.OrderBy.Items)
   917  		if b.err != nil {
   918  			return nil
   919  		}
   920  	}
   921  	if sel.Limit != nil {
   922  		pushLimit(p, sel.Limit)
   923  		p = b.buildLimit(p, sel.Limit)
   924  		if b.err != nil {
   925  			return nil
   926  		}
   927  	}
   928  	orderedList := b.buildUpdateLists(update.List, p.Fields())
   929  	if b.err != nil {
   930  		return nil
   931  	}
   932  	return &Update{OrderedList: orderedList, SelectPlan: p, basePlan: basePlan{children: []Plan{p}}}
   933  }
   934  
   935  func (b *planBuilder) buildUpdateLists(list []*ast.Assignment, fields []*ast.ResultField) []*ast.Assignment {
   936  	newList := make([]*ast.Assignment, len(fields))
   937  	for _, assign := range list {
   938  		offset, err := columnOffsetInFields(assign.Column, fields)
   939  		if err != nil {
   940  			b.err = errors.Trace(err)
   941  			return nil
   942  		}
   943  		newList[offset] = assign
   944  	}
   945  	return newList
   946  }
   947  
   948  func (b *planBuilder) buildDelete(del *ast.DeleteStmt) Plan {
   949  	sel := &ast.SelectStmt{From: del.TableRefs, Where: del.Where, OrderBy: del.Order, Limit: del.Limit}
   950  	p := b.buildFrom(sel)
   951  	for _, v := range p.Fields() {
   952  		v.Referenced = true
   953  	}
   954  	if sel.OrderBy != nil && !pushOrder(p, sel.OrderBy.Items) {
   955  		p = b.buildSort(p, sel.OrderBy.Items)
   956  		if b.err != nil {
   957  			return nil
   958  		}
   959  	}
   960  	if sel.Limit != nil {
   961  		pushLimit(p, sel.Limit)
   962  		p = b.buildLimit(p, sel.Limit)
   963  		if b.err != nil {
   964  			return nil
   965  		}
   966  	}
   967  	var tables []*ast.TableName
   968  	if del.Tables != nil {
   969  		tables = del.Tables.Tables
   970  	}
   971  	return &Delete{
   972  		Tables:       tables,
   973  		IsMultiTable: del.IsMultiTable,
   974  		SelectPlan:   p,
   975  		basePlan:     basePlan{children: []Plan{p}},
   976  	}
   977  }
   978  
   979  func columnOffsetInFields(cn *ast.ColumnName, fields []*ast.ResultField) (int, error) {
   980  	offset := -1
   981  	tableNameL := cn.Table.L
   982  	columnNameL := cn.Name.L
   983  	if tableNameL != "" {
   984  		for i, f := range fields {
   985  			// Check table name.
   986  			if f.TableAsName.L != "" {
   987  				if tableNameL != f.TableAsName.L {
   988  					continue
   989  				}
   990  			} else {
   991  				if tableNameL != f.Table.Name.L {
   992  					continue
   993  				}
   994  			}
   995  			// Check column name.
   996  			if f.ColumnAsName.L != "" {
   997  				if columnNameL != f.ColumnAsName.L {
   998  					continue
   999  				}
  1000  			} else {
  1001  				if columnNameL != f.Column.Name.L {
  1002  					continue
  1003  				}
  1004  			}
  1005  
  1006  			offset = i
  1007  		}
  1008  	} else {
  1009  		for i, f := range fields {
  1010  			matchAsName := f.ColumnAsName.L != "" && f.ColumnAsName.L == columnNameL
  1011  			matchColumnName := f.ColumnAsName.L == "" && f.Column.Name.L == columnNameL
  1012  			if matchAsName || matchColumnName {
  1013  				if offset != -1 {
  1014  					return -1, errors.Errorf("column %s is ambiguous.", cn.Name.O)
  1015  				}
  1016  				offset = i
  1017  			}
  1018  		}
  1019  	}
  1020  	if offset == -1 {
  1021  		return -1, errors.Errorf("column %s not found", cn.Name.O)
  1022  	}
  1023  	return offset, nil
  1024  }
  1025  
  1026  func (b *planBuilder) buildShow(show *ast.ShowStmt) Plan {
  1027  	var p Plan
  1028  	p = &Show{
  1029  		Tp:     show.Tp,
  1030  		DBName: show.DBName,
  1031  		Table:  show.Table,
  1032  		Column: show.Column,
  1033  		Flag:   show.Flag,
  1034  		Full:   show.Full,
  1035  		User:   show.User,
  1036  	}
  1037  	p.SetFields(show.GetResultFields())
  1038  	var conditions []ast.ExprNode
  1039  	if show.Pattern != nil {
  1040  		conditions = append(conditions, show.Pattern)
  1041  	}
  1042  	if show.Where != nil {
  1043  		conditions = append(conditions, show.Where)
  1044  	}
  1045  	if len(conditions) != 0 {
  1046  		filter := &Filter{Conditions: conditions}
  1047  		addChild(filter, p)
  1048  		p = filter
  1049  	}
  1050  	return p
  1051  }
  1052  
  1053  func (b *planBuilder) buildSimple(node ast.StmtNode) Plan {
  1054  	return &Simple{Statement: node}
  1055  }
  1056  
  1057  func (b *planBuilder) buildInsert(insert *ast.InsertStmt) Plan {
  1058  	insertPlan := &Insert{
  1059  		Table:       insert.Table,
  1060  		Columns:     insert.Columns,
  1061  		Lists:       insert.Lists,
  1062  		Setlist:     insert.Setlist,
  1063  		OnDuplicate: insert.OnDuplicate,
  1064  		IsReplace:   insert.IsReplace,
  1065  		Priority:    insert.Priority,
  1066  	}
  1067  	if insert.Select != nil {
  1068  		insertPlan.SelectPlan = b.build(insert.Select)
  1069  		addChild(insertPlan, insertPlan.SelectPlan)
  1070  		if b.err != nil {
  1071  			return nil
  1072  		}
  1073  	}
  1074  	return insertPlan
  1075  }
  1076  
  1077  func (b *planBuilder) buildDDL(node ast.DDLNode) Plan {
  1078  	return &DDL{Statement: node}
  1079  }
  1080  
  1081  func (b *planBuilder) buildExplain(explain *ast.ExplainStmt) Plan {
  1082  	if show, ok := explain.Stmt.(*ast.ShowStmt); ok {
  1083  		return b.buildShow(show)
  1084  	}
  1085  	targetPlan := b.build(explain.Stmt)
  1086  	if b.err != nil {
  1087  		return nil
  1088  	}
  1089  	p := &Explain{StmtPlan: targetPlan}
  1090  	addChild(p, targetPlan)
  1091  	p.SetFields(buildExplainFields())
  1092  	return p
  1093  }
  1094  
  1095  // See: https://dev.mysql.com/doc/refman/5.7/en/explain-output.html
  1096  func buildExplainFields() []*ast.ResultField {
  1097  	rfs := make([]*ast.ResultField, 0, 10)
  1098  	rfs = append(rfs, buildResultField("", "id", mysql.TypeLonglong, 4))
  1099  	rfs = append(rfs, buildResultField("", "select_type", mysql.TypeVarchar, 128))
  1100  	rfs = append(rfs, buildResultField("", "table", mysql.TypeVarchar, 128))
  1101  	rfs = append(rfs, buildResultField("", "type", mysql.TypeVarchar, 128))
  1102  	rfs = append(rfs, buildResultField("", "possible_keys", mysql.TypeVarchar, 128))
  1103  	rfs = append(rfs, buildResultField("", "key", mysql.TypeVarchar, 128))
  1104  	rfs = append(rfs, buildResultField("", "key_len", mysql.TypeVarchar, 128))
  1105  	rfs = append(rfs, buildResultField("", "ref", mysql.TypeVarchar, 128))
  1106  	rfs = append(rfs, buildResultField("", "rows", mysql.TypeVarchar, 128))
  1107  	rfs = append(rfs, buildResultField("", "Extra", mysql.TypeVarchar, 128))
  1108  	return rfs
  1109  }