vitess.io/vitess@v0.16.2/go/vt/vtgate/planbuilder/expression_converter.go (about) 1 /* 2 Copyright 2020 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package planbuilder 18 19 import ( 20 "fmt" 21 "strings" 22 23 "vitess.io/vitess/go/vt/vtgate/planbuilder/plancontext" 24 25 "vitess.io/vitess/go/mysql/collations" 26 "vitess.io/vitess/go/vt/sqlparser" 27 "vitess.io/vitess/go/vt/vtgate/engine" 28 "vitess.io/vitess/go/vt/vtgate/evalengine" 29 ) 30 31 type expressionConverter struct { 32 tabletExpressions []sqlparser.Expr 33 } 34 35 func booleanValues(astExpr sqlparser.Expr) evalengine.Expr { 36 var ( 37 ON = evalengine.NewLiteralInt(1) 38 OFF = evalengine.NewLiteralInt(0) 39 ) 40 switch node := astExpr.(type) { 41 case *sqlparser.Literal: 42 //set autocommit = 'on' 43 if node.Type == sqlparser.StrVal { 44 switch strings.ToLower(node.Val) { 45 case "on": 46 return ON 47 case "off": 48 return OFF 49 } 50 } 51 case *sqlparser.ColName: 52 //set autocommit = on 53 switch node.Name.Lowered() { 54 case "on": 55 return ON 56 case "off": 57 return OFF 58 } 59 } 60 return nil 61 } 62 63 func identifierAsStringValue(astExpr sqlparser.Expr) evalengine.Expr { 64 colName, isColName := astExpr.(*sqlparser.ColName) 65 if isColName { 66 // TODO@collations: proper collation for column name 67 return evalengine.NewLiteralString([]byte(colName.Name.Lowered()), collations.TypedCollation{}) 68 } 69 return nil 70 } 71 72 func (ec *expressionConverter) convert(astExpr sqlparser.Expr, boolean, identifierAsString bool) (evalengine.Expr, error) { 73 if boolean { 74 evalExpr := booleanValues(astExpr) 75 if evalExpr != nil { 76 return evalExpr, nil 77 } 78 } 79 if identifierAsString { 80 evalExpr := identifierAsStringValue(astExpr) 81 if evalExpr != nil { 82 return evalExpr, nil 83 } 84 } 85 evalExpr, err := evalengine.Translate(astExpr, nil) 86 if err != nil { 87 if !strings.Contains(err.Error(), evalengine.ErrTranslateExprNotSupported) { 88 return nil, err 89 } 90 evalExpr = &evalengine.Column{Offset: len(ec.tabletExpressions)} 91 ec.tabletExpressions = append(ec.tabletExpressions, astExpr) 92 } 93 return evalExpr, nil 94 } 95 96 func (ec *expressionConverter) source(vschema plancontext.VSchema) (engine.Primitive, error) { 97 if len(ec.tabletExpressions) == 0 { 98 return &engine.SingleRow{}, nil 99 } 100 ks, dest, err := resolveDestination(vschema) 101 if err != nil { 102 return nil, err 103 } 104 105 var expr []string 106 for _, e := range ec.tabletExpressions { 107 expr = append(expr, sqlparser.String(e)) 108 } 109 query := fmt.Sprintf("select %s from dual", strings.Join(expr, ",")) 110 111 primitive := &engine.Send{ 112 Keyspace: ks, 113 TargetDestination: dest, 114 Query: query, 115 IsDML: false, 116 SingleShardOnly: true, 117 } 118 return primitive, nil 119 }