github.com/XiaoMi/Gaea@v1.2.5/proxy/plan/decorator_table_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 "github.com/pingcap/errors" 24 ) 25 26 // TableNameDecorator decorate TableName 27 type TableNameDecorator struct { 28 origin *ast.TableName 29 rule router.Rule 30 result *RouteResult 31 } 32 33 // NeedCreateTableNameDecoratorWithoutAlias check if TableName without alias needs decorate 34 // 不带表别名时, 只用StmtInfo就可以判断 35 func NeedCreateTableNameDecoratorWithoutAlias(p *StmtInfo, n *ast.TableName) (router.Rule, bool, error) { 36 db, table := getTableInfoFromTableName(n) 37 38 rule, err := p.RecordShardTable(db, table) 39 if err != nil { 40 return nil, false, fmt.Errorf("record shard table in SelectPlan error, db: %s, table, %s, err: %v", db, table, err) 41 } 42 43 return rule, true, nil 44 } 45 46 // NeedCreateTableNameDecorator check if TableName with alias needs decorate 47 // SELECT语句可能带有表别名, 需要记录表别名 48 func NeedCreateTableNameDecorator(p *TableAliasStmtInfo, n *ast.TableName, alias string) (router.Rule, bool, error) { 49 db, table := getTableInfoFromTableName(n) 50 51 rule, err := p.RecordShardTable(db, table, alias) 52 if err != nil { 53 return nil, false, fmt.Errorf("record shard table in SelectPlan error, db: %s, table, %s, alias: %s, err: %v", db, table, alias, err) 54 } 55 56 return rule, true, nil 57 } 58 59 // CreateTableNameDecorator create TableNameDecorator 60 // the table has been checked before 61 func CreateTableNameDecorator(n *ast.TableName, rule router.Rule, result *RouteResult) (*TableNameDecorator, error) { 62 if len(n.PartitionNames) != 0 { 63 return nil, fmt.Errorf("TableName does not support PartitionNames in sharding") 64 } 65 66 ret := &TableNameDecorator{ 67 origin: n, 68 rule: rule, 69 result: result, 70 } 71 72 return ret, nil 73 } 74 75 // Restore implement ast.Node 76 func (t *TableNameDecorator) Restore(ctx *format.RestoreCtx) error { 77 tableIndex, err := t.result.GetCurrentTableIndex() 78 if err != nil { 79 return err 80 } 81 82 ruleType := t.rule.GetType() 83 84 // kingshard不需改写库名, mycat需要改写, 全局表需要改写 85 if t.origin.Schema.String() != "" { 86 if ruleType == router.GlobalTableRuleType { 87 dbName, err := t.rule.GetDatabaseNameByTableIndex(tableIndex) 88 if err != nil { 89 return fmt.Errorf("get mycat database name error: %v", err) 90 } 91 ctx.WriteName(dbName) 92 ctx.WritePlain(".") 93 } else if router.IsMycatShardingRule(ruleType) { 94 dbName, err := t.rule.GetDatabaseNameByTableIndex(tableIndex) 95 if err != nil { 96 return fmt.Errorf("get mycat database name error: %v", err) 97 } 98 ctx.WriteName(dbName) 99 ctx.WritePlain(".") 100 } else { 101 ctx.WriteName(t.origin.Schema.String()) 102 ctx.WritePlain(".") 103 } 104 } 105 106 // kingshard需要改写表名, mycat不需要改写, 全局表需要改写 107 if ruleType == router.GlobalTableRuleType { 108 ctx.WriteName(t.origin.Name.String()) 109 } else if router.IsMycatShardingRule(ruleType) { 110 ctx.WriteName(t.origin.Name.String()) 111 } else { 112 ctx.WriteName(fmt.Sprintf("%s_%04d", t.origin.Name.String(), tableIndex)) 113 } 114 115 for _, value := range t.origin.IndexHints { 116 ctx.WritePlain(" ") 117 if err := value.Restore(ctx); err != nil { 118 return errors.Annotate(err, "An error occurred while splicing IndexHints") 119 } 120 } 121 return nil 122 } 123 124 // Accept implement ast.Node 125 // do nothing and return current decorator 126 func (t *TableNameDecorator) Accept(v ast.Visitor) (ast.Node, bool) { 127 return t, true 128 } 129 130 // Text implement ast.Node 131 func (t *TableNameDecorator) Text() string { 132 return t.origin.Text() 133 } 134 135 // SetText implement ast.Node 136 func (t *TableNameDecorator) SetText(text string) { 137 t.origin.SetText(text) 138 }