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  }