github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/optimizer/optimizer.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 optimizer 15 16 import ( 17 "github.com/insionng/yougam/libraries/juju/errors" 18 "github.com/insionng/yougam/libraries/pingcap/tidb/ast" 19 "github.com/insionng/yougam/libraries/pingcap/tidb/context" 20 "github.com/insionng/yougam/libraries/pingcap/tidb/infoschema" 21 "github.com/insionng/yougam/libraries/pingcap/tidb/mysql" 22 "github.com/insionng/yougam/libraries/pingcap/tidb/optimizer/plan" 23 "github.com/insionng/yougam/libraries/pingcap/tidb/terror" 24 ) 25 26 // Optimize does optimization and creates a Plan. 27 // The node must be prepared first. 28 func Optimize(ctx context.Context, node ast.Node, sb plan.SubQueryBuilder) (plan.Plan, error) { 29 // We have to infer type again because after parameter is set, the expression type may change. 30 if err := InferType(node); err != nil { 31 return nil, errors.Trace(err) 32 } 33 if err := logicOptimize(ctx, node); err != nil { 34 return nil, errors.Trace(err) 35 } 36 p, err := plan.BuildPlan(node, sb) 37 if err != nil { 38 return nil, errors.Trace(err) 39 } 40 if plan.UseNewPlanner { 41 _, err = plan.PredicatePushDown(p, []ast.ExprNode{}) 42 if err != nil { 43 return nil, errors.Trace(err) 44 } 45 } 46 err = plan.Refine(p) 47 if err != nil { 48 return nil, errors.Trace(err) 49 } 50 return p, nil 51 } 52 53 // Prepare prepares a raw statement parsed from parser. 54 // The statement must be prepared before it can be passed to optimize function. 55 // We pass InfoSchema instead of getting from Context in case it is changed after resolving name. 56 func Prepare(is infoschema.InfoSchema, ctx context.Context, node ast.Node) error { 57 ast.SetFlag(node) 58 if err := Preprocess(node, is, ctx); err != nil { 59 return errors.Trace(err) 60 } 61 if err := Validate(node, true); err != nil { 62 return errors.Trace(err) 63 } 64 return nil 65 } 66 67 // Optimizer error codes. 68 const ( 69 CodeOneColumn terror.ErrCode = 1 70 CodeSameColumns terror.ErrCode = 2 71 CodeMultiWildCard terror.ErrCode = 3 72 CodeUnsupported terror.ErrCode = 4 73 CodeInvalidGroupFuncUse terror.ErrCode = 5 74 CodeIllegalReference terror.ErrCode = 6 75 ) 76 77 // Optimizer base errors. 78 var ( 79 ErrOneColumn = terror.ClassOptimizer.New(CodeOneColumn, "Operand should contain 1 column(s)") 80 ErrSameColumns = terror.ClassOptimizer.New(CodeSameColumns, "Operands should contain same columns") 81 ErrMultiWildCard = terror.ClassOptimizer.New(CodeMultiWildCard, "wildcard field exist more than once") 82 ErrUnSupported = terror.ClassOptimizer.New(CodeUnsupported, "unsupported") 83 ErrInvalidGroupFuncUse = terror.ClassOptimizer.New(CodeInvalidGroupFuncUse, "Invalid use of group function") 84 ErrIllegalReference = terror.ClassOptimizer.New(CodeIllegalReference, "Illegal reference") 85 ) 86 87 func init() { 88 mySQLErrCodes := map[terror.ErrCode]uint16{ 89 CodeOneColumn: mysql.ErrOperandColumns, 90 CodeSameColumns: mysql.ErrOperandColumns, 91 CodeMultiWildCard: mysql.ErrParse, 92 CodeInvalidGroupFuncUse: mysql.ErrInvalidGroupFuncUse, 93 CodeIllegalReference: mysql.ErrIllegalReference, 94 } 95 terror.ErrClassToMySQLCodes[terror.ClassOptimizer] = mySQLErrCodes 96 }