github.com/XiaoMi/Gaea@v1.2.5/proxy/plan/decorator_column_name.go (about) 1 // Copyright 2019 The Gaea Authors. All Rights Reserved. 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package plan 16 17 import ( 18 "fmt" 19 20 "github.com/XiaoMi/Gaea/parser/ast" 21 "github.com/XiaoMi/Gaea/parser/format" 22 "github.com/XiaoMi/Gaea/proxy/router" 23 ) 24 25 // ColumnNameExprDecorator decorate ColumnNameExpr to rewrite table name 26 type ColumnNameExprDecorator struct { 27 *ast.ColumnNameExpr 28 Name *ColumnNameDecorator 29 } 30 31 // ColumnNameDecorator decorate ColumnName to rewrite table name 32 type ColumnNameDecorator struct { 33 origin *ast.ColumnName 34 rule router.Rule 35 result *RouteResult 36 isAlias bool 37 } 38 39 // NeedCreateColumnNameExprDecoratorInField check if ColumnNameExpr in field needs decoration 40 // 用于Field列表中判断列名是否需要装饰 41 // 如果db名和表名都不存在, 则不需要装饰 42 func NeedCreateColumnNameExprDecoratorInField(p *TableAliasStmtInfo, n *ast.ColumnNameExpr) (router.Rule, bool, bool, error) { 43 db, table, _ := getColumnInfoFromColumnName(n.Name) 44 if db == "" && table == "" { 45 return nil, false, false, nil 46 } 47 return needCreateColumnNameDecorator(p, n.Name) 48 } 49 50 // NeedCreateColumnNameExprDecoratorInCondition check if ColumnNameExpr in condition needs decoration 51 // 用于JOIN ON条件或WHERE条件中判断列名是否需要装饰 52 // 与上面的区别在于, 当只存在列名, 不存在db名和表名时, 还会根据列名去查找对应的条件 (因为装饰之后需要在比较条件中计算路由) 53 func NeedCreateColumnNameExprDecoratorInCondition(p *TableAliasStmtInfo, n *ast.ColumnNameExpr) (router.Rule, bool, bool, error) { 54 return needCreateColumnNameDecorator(p, n.Name) 55 } 56 57 // 是否需要装饰ColumnName, 需要则返回ture 58 // 在CreateColumnNameDecorator之前调用, 用来检查 59 // 返回结果bool表示是否需要创建装饰器 60 func needCreateColumnNameDecorator(p *TableAliasStmtInfo, n *ast.ColumnName) (router.Rule, bool, bool, error) { 61 db, table, column := getColumnInfoFromColumnName(n) 62 63 rule, ok, isAlias, err := p.GetSettedRuleFromColumnInfo(db, table, column) 64 if err != nil { 65 return nil, false, false, err 66 } 67 if !ok { 68 return nil, false, false, nil 69 } 70 71 return rule, true, isAlias, nil 72 } 73 74 // CreateColumnNameExprDecorator create ColumnNameExprDecorator 75 func CreateColumnNameExprDecorator(n *ast.ColumnNameExpr, rule router.Rule, isAlias bool, result *RouteResult) *ColumnNameExprDecorator { 76 columnName := createColumnNameDecorator(n.Name, rule, isAlias, result) 77 return &ColumnNameExprDecorator{ 78 ColumnNameExpr: n, 79 Name: columnName, 80 } 81 } 82 83 func createColumnNameDecorator(n *ast.ColumnName, rule router.Rule, isAlias bool, result *RouteResult) *ColumnNameDecorator { 84 ret := &ColumnNameDecorator{ 85 origin: n, 86 rule: rule, 87 result: result, 88 isAlias: isAlias, 89 } 90 return ret 91 } 92 93 // GetColumnInfo get column info, return db, table, column 94 func (c *ColumnNameDecorator) GetColumnInfo() (string, string, string) { 95 return getColumnInfoFromColumnName(c.origin) 96 } 97 98 // Restore implement ast.Node 99 func (c *ColumnNameDecorator) Restore(ctx *format.RestoreCtx) error { 100 tableIndex, err := c.result.GetCurrentTableIndex() 101 if err != nil { 102 return err 103 } 104 105 ruleType := c.rule.GetType() 106 107 // kingshard不需改写库名, mycat需要改写 108 if c.origin.Schema.O != "" { 109 if ruleType == router.GlobalTableRuleType { 110 dbName, err := c.rule.GetDatabaseNameByTableIndex(tableIndex) 111 if err != nil { 112 return fmt.Errorf("get mycat database name error: %v", err) 113 } 114 ctx.WriteName(dbName) 115 ctx.WritePlain(".") 116 } else if router.IsMycatShardingRule(ruleType) { 117 dbName, err := c.rule.GetDatabaseNameByTableIndex(tableIndex) 118 if err != nil { 119 return fmt.Errorf("get mycat database name error: %v", err) 120 } 121 ctx.WriteName(dbName) 122 ctx.WritePlain(".") 123 } else { 124 ctx.WriteName(c.origin.Schema.String()) 125 ctx.WritePlain(".") 126 } 127 } 128 129 // kingshard需要改写表名, mycat不需要改写, 全局表不需要改写 130 if c.origin.Table.O != "" { 131 if ruleType == router.GlobalTableRuleType { 132 ctx.WriteName(c.origin.Table.String()) 133 ctx.WritePlain(".") 134 } else if router.IsMycatShardingRule(ruleType) { 135 ctx.WriteName(c.origin.Table.String()) 136 ctx.WritePlain(".") 137 } else { 138 if c.isAlias { 139 ctx.WriteName(c.origin.Table.String()) 140 ctx.WritePlain(".") 141 } else { 142 ctx.WriteName(fmt.Sprintf("%s_%04d", c.origin.Table.String(), tableIndex)) 143 ctx.WritePlain(".") 144 } 145 } 146 } 147 148 // 列名不需要改写 149 ctx.WriteName(c.origin.Name.O) 150 151 return nil 152 } 153 154 // Accept implement ast.Node 155 // do nothing and return current decorator 156 func (c *ColumnNameDecorator) Accept(v ast.Visitor) (ast.Node, bool) { 157 return c, true 158 } 159 160 // Text implement ast.Node 161 func (c *ColumnNameDecorator) Text() string { 162 return c.origin.Text() 163 } 164 165 // SetText implement ast.Node 166 func (c *ColumnNameDecorator) SetText(text string) { 167 c.origin.SetText(text) 168 } 169 170 // Restore implement ast.Node 171 func (cc *ColumnNameExprDecorator) Restore(ctx *format.RestoreCtx) error { 172 if err := cc.Name.Restore(ctx); err != nil { 173 return fmt.Errorf("restore ColumnNameExprDecorator error: %v", err) 174 } 175 return nil 176 }