Documentation ¶
Overview ¶
Package ast is an interface for Abstract Syntax Tree parser
Index ¶
- Constants
- Variables
- func AlterAffectTable(stmt sqlparser.Statement) string
- func Compress(sql string) string
- func FindAllCols(node sqlparser.SQLNode, targets ...string) []*common.Column
- func FindAllCondition(node sqlparser.SQLNode) []interface{}
- func FindColumn(node sqlparser.SQLNode) []*common.Column
- func FindEQColsInJoinCond(node sqlparser.SQLNode) []*common.Column
- func FindEQColsInWhere(node sqlparser.SQLNode) []*common.Column
- func FindGroupByCols(node sqlparser.SQLNode) []*common.Column
- func FindINEQColsInJoinCond(node sqlparser.SQLNode) []*common.Column
- func FindINEQColsInWhere(node sqlparser.SQLNode) []*common.Column
- func FindJoinCols(node sqlparser.SQLNode) [][]*common.Column
- func FindJoinTable(node sqlparser.SQLNode, meta common.Meta) common.Meta
- func FindOrderByCols(node sqlparser.SQLNode) []*common.Column
- func FindSubquery(depth int, node sqlparser.SQLNode, queries ...string) []string
- func FindWhereEQ(node sqlparser.SQLNode) []*common.Column
- func FindWhereINEQ(node sqlparser.SQLNode) []*common.Column
- func GetMeta(stmt sqlparser.Statement, meta common.Meta) common.Meta
- func GetSubqueryDepth(node sqlparser.SQLNode) int
- func GetTableFromExprs(exprs sqlparser.TableExprs, metas ...common.Meta) common.Meta
- func IsMysqlKeyword(name string) bool
- func LeftNewLines(buf []byte) int
- func ListRewriteRules(rules []Rule)
- func MergeAlterTables(sqls ...string) map[string]string
- func MysqlEscapeString(source string) (string, error)
- func NewLines(buf []byte) int
- func Pretty(sql string, method string) (output string)
- func PrintPrettyStmtNode(sql, charset, collation string)
- func RewriteRuleMatch(name string) bool
- func SplitStatement(buf []byte, delimiter []byte) (string, []byte)
- func TiParse(sql, charset, collation string) ([]ast.StmtNode, error)
- type NodeItem
- type NodeList
- type Rewrite
- func (rw *Rewrite) Rewrite() *Rewrite
- func (rw *Rewrite) RewriteAddOrderByNull() *Rewrite
- func (rw *Rewrite) RewriteAlwaysTrue() (reWriter *Rewrite)
- func (rw *Rewrite) RewriteAutoIncrement() *Rewrite
- func (rw *Rewrite) RewriteCountStar() *Rewrite
- func (rw *Rewrite) RewriteDML2Select() *Rewrite
- func (rw *Rewrite) RewriteDelimiter() *Rewrite
- func (rw *Rewrite) RewriteDistinctStar() *Rewrite
- func (rw *Rewrite) RewriteGroupByConst() *Rewrite
- func (rw *Rewrite) RewriteHaving() *Rewrite
- func (rw *Rewrite) RewriteInNull() *Rewrite
- func (rw *Rewrite) RewriteInnoDB() *Rewrite
- func (rw *Rewrite) RewriteInsertColumns() *Rewrite
- func (rw *Rewrite) RewriteIntWidth() *Rewrite
- func (rw *Rewrite) RewriteJoin2SubQuery() *Rewrite
- func (rw *Rewrite) RewriteOr2In() *Rewrite
- func (rw *Rewrite) RewriteOr2Union() *Rewrite
- func (rw *Rewrite) RewriteRemoveDMLOrderBy() *Rewrite
- func (rw *Rewrite) RewriteRmParenthesis() *Rewrite
- func (rw *Rewrite) RewriteStandard() *Rewrite
- func (rw *Rewrite) RewriteStar2Columns() *Rewrite
- func (rw *Rewrite) RewriteSubQuery2Join() *Rewrite
- func (rw *Rewrite) RewriteTruncate() *Rewrite
- func (rw *Rewrite) RewriteUnionAll() *Rewrite
- type Rule
- type TiVisitor
- type Token
Constants ¶
const ( TokenTypeWhitespace = 0 TokenTypeWord = 1 TokenTypeQuote = 2 TokenTypeBacktickQuote = 3 TokenTypeReserved = 4 TokenTypeReservedToplevel = 5 TokenTypeReservedNewline = 6 TokenTypeBoundary = 7 TokenTypeComment = 8 TokenTypeBlockComment = 9 TokenTypeNumber = 10 TokenTypeError = 11 TokenTypeVariable = 12 )
TokenType
Variables ¶
var RewriteRules = []Rule{ { Name: "dml2select", Description: "将数据库更新请求转换为只读查询请求,便于执行EXPLAIN", Original: "DELETE FROM film WHERE length > 100", Suggest: "select * from film where length > 100", Func: (*Rewrite).RewriteDML2Select, }, { Name: "star2columns", Description: "为SELECT *补全表的列信息", Original: "SELECT * FROM film", Suggest: "select film.film_id, film.title from film", Func: (*Rewrite).RewriteStar2Columns, }, { Name: "insertcolumns", Description: "为INSERT补全表的列信息", Original: "insert into film values(1,2,3,4,5)", Suggest: "insert into film(film_id, title, description, release_year, language_id) values (1, 2, 3, 4, 5)", Func: (*Rewrite).RewriteInsertColumns, }, { Name: "having", Description: "将查询的HAVING子句改写为WHERE中的查询条件", Original: "SELECT state, COUNT(*) FROM Drivers GROUP BY state HAVING state IN ('GA', 'TX') ORDER BY state", Suggest: "select state, COUNT(*) from Drivers where state in ('GA', 'TX') group by state order by state asc", Func: (*Rewrite).RewriteHaving, }, { Name: "orderbynull", Description: "如果GROUP BY语句不指定ORDER BY条件会导致无谓的排序产生,如果不需要排序建议添加ORDER BY NULL", Original: "SELECT sum(col1) FROM tbl GROUP BY col", Suggest: "select sum(col1) from tbl group by col order by null", Func: (*Rewrite).RewriteAddOrderByNull, }, { Name: "unionall", Description: "可以接受重复的时间,使用UNION ALL替代UNION以提高查询效率", Original: "select country_id from city union select country_id from country", Suggest: "select country_id from city union all select country_id from country", Func: (*Rewrite).RewriteUnionAll, }, { Name: "or2in", Description: "将同一列不同条件的OR查询转写为IN查询", Original: "select country_id from city where col1 = 1 or (col2 = 1 or col2 = 2 ) or col1 = 3;", Suggest: "select country_id from city where (col2 in (1, 2)) or col1 in (1, 3);", Func: (*Rewrite).RewriteOr2In, }, { Name: "innull", Description: "如果IN条件中可能有NULL值而又想匹配NULL值时,建议添加OR col IS NULL", Original: "暂不支持", Suggest: "暂不支持", Func: (*Rewrite).RewriteInNull, }, { Name: "or2union", Description: "将不同列的OR查询转为UNION查询,建议结合unionall重写策略一起使用", Original: "暂不支持", Suggest: "暂不支持", Func: (*Rewrite).RewriteOr2Union, }, { Name: "dmlorderby", Description: "删除DML更新操作中无意义的ORDER BY", Original: "DELETE FROM tbl WHERE col1=1 ORDER BY col", Suggest: "delete from tbl where col1 = 1", Func: (*Rewrite).RewriteRemoveDMLOrderBy, }, { Name: "sub2join", Description: "将子查询转换为JOIN查询", Original: "暂不支持", Suggest: "暂不支持", Func: (*Rewrite).RewriteSubQuery2Join, }, { Name: "join2sub", Description: "将JOIN查询转换为子查询", Original: "暂不支持", Suggest: "暂不支持", Func: (*Rewrite).RewriteJoin2SubQuery, }, { Name: "distinctstar", Description: "DISTINCT *对有主键的表没有意义,可以将DISTINCT删掉", Original: "SELECT DISTINCT * FROM film;", Suggest: "SELECT * FROM film", Func: (*Rewrite).RewriteDistinctStar, }, { Name: "standard", Description: "SQL标准化,如:关键字转换为小写", Original: "SELECT sum(col1) FROM tbl GROUP BY 1;", Suggest: "select sum(col1) from tbl group by 1", Func: (*Rewrite).RewriteStandard, }, { Name: "mergealter", Description: "合并同一张表的多条ALTER语句", Original: "ALTER TABLE t2 DROP COLUMN c;ALTER TABLE t2 DROP COLUMN d;", Suggest: "ALTER TABLE t2 DROP COLUMN c, DROP COLUMN d;", }, { Name: "alwaystrue", Description: "删除无用的恒真判断条件", Original: "SELECT count(col) FROM tbl where 'a'= 'a' or ('b' = 'b' and a = 'b');", Suggest: "select count(col) from tbl where (a = 'b');", Func: (*Rewrite).RewriteAlwaysTrue, }, { Name: "countstar", Description: "不建议使用COUNT(col)或COUNT(常量),建议改写为COUNT(*)", Original: "SELECT count(col) FROM tbl GROUP BY 1;", Suggest: "SELECT count(*) FROM tbl GROUP BY 1;", Func: (*Rewrite).RewriteCountStar, }, { Name: "innodb", Description: "建表时建议使用InnoDB引擎,非InnoDB引擎表自动转InnoDB", Original: "CREATE TABLE t1(id bigint(20) NOT NULL AUTO_INCREMENT);", Suggest: "create table t1 (\n\tid bigint(20) not null auto_increment\n) ENGINE=InnoDB;", Func: (*Rewrite).RewriteInnoDB, }, { Name: "autoincrement", Description: "将autoincrement初始化为1", Original: "CREATE TABLE t1(id bigint(20) NOT NULL AUTO_INCREMENT) ENGINE=InnoDB AUTO_INCREMENT=123802;", Suggest: "create table t1(id bigint(20) not null auto_increment) ENGINE=InnoDB auto_increment=1;", Func: (*Rewrite).RewriteAutoIncrement, }, { Name: "intwidth", Description: "整型数据类型修改默认显示宽度", Original: "create table t1 (id int(20) not null auto_increment) ENGINE=InnoDB;", Suggest: "create table t1 (id int(10) not null auto_increment) ENGINE=InnoDB;", Func: (*Rewrite).RewriteIntWidth, }, { Name: "truncate", Description: "不带WHERE条件的DELETE操作建议修改为TRUNCATE", Original: "DELETE FROM tbl", Suggest: "truncate table tbl", Func: (*Rewrite).RewriteTruncate, }, { Name: "rmparenthesis", Description: "去除没有意义的括号", Original: "select col from table where (col = 1);", Suggest: "select col from table where col = 1;", Func: (*Rewrite).RewriteRmParenthesis, }, { Name: "delimiter", Description: "补全DELIMITER", Original: "use sakila", Suggest: "use sakila;", Func: (*Rewrite).RewriteDelimiter, }, }
RewriteRules SQL重写规则,注意这个规则是有序的,先后顺序不能乱
var TokenString = map[int]string{}/* 216 elements not displayed */
TokenString sqlparser tokens
Functions ¶
func AlterAffectTable ¶
AlterAffectTable 获取ALTER影响的库表名,返回:`db`.`table`
func FindAllCols ¶
FindAllCols 获取AST中某个节点下所有的columns
func FindAllCondition ¶
FindAllCondition 获取AST中所有的condition条件
func FindColumn ¶
FindColumn 从传入的node中获取所有可能加索引的的column信息
func FindEQColsInJoinCond ¶
FindEQColsInJoinCond 获取 join condition 中应转为whereEQ条件的列
func FindEQColsInWhere ¶
FindEQColsInWhere 获取等值条件信息 将所有值得加索引的condition条件信息进行过滤
func FindGroupByCols ¶
FindGroupByCols 获取groupBy中可能需要加索引的列信息
func FindINEQColsInJoinCond ¶
FindINEQColsInJoinCond 获取 join condition 中应转为whereINEQ条件的列
func FindINEQColsInWhere ¶
FindINEQColsInWhere 获取非等值条件中可能需要加索引的列 将所有值得加索引的condition条件信息进行过滤 TODO: 将where条件中隐含的join条件合并到join condition中
func FindJoinCols ¶
FindJoinCols 获取 join condition 中使用到的列(必须是 `列 operator 列` 的情况。 如果列对应的值或是function,则应该移到where condition中) 某些where条件隐含在Join条件中(INNER JOIN)
func FindJoinTable ¶
FindJoinTable 获取 Join 中需要添加索引的表 join 优化添加索引分为三种类型:1. inner join, 2. left join, 3.right join 针对三种优化类型,需要三种不同的索引添加方案: 1. inner join 需要对 join 左右的表添加索引 2. left join 由于左表为全表扫描,需要对右表的关联列添加索引。 3. right join 与 left join 相反,需要对左表的关联列添加索引。 以上添加索引的策略前提为join的表为实体表而非临时表。
func FindOrderByCols ¶
FindOrderByCols 为索引优化获取orderBy中可能添加索引的列信息
func FindSubquery ¶
FindSubquery 拆分subquery,获取最深层的subquery 为索引优化获取subquery中包含的列信息
func FindWhereEQ ¶
FindWhereEQ 找到Where中的等值条件
func FindWhereINEQ ¶
FindWhereINEQ 找到Where条件中的非等值条件
func GetMeta ¶
GetMeta 获取元数据信息,构建到db->table层级。 从 SQL 或 Statement 中获取表信息,并返回。当 meta 不为 nil 时,返回值会将新老 meta 合并去重
func GetSubqueryDepth ¶
GetSubqueryDepth 获取一条SQL的嵌套深度
func GetTableFromExprs ¶
GetTableFromExprs 从sqlparser.Exprs中获取所有的库表
func MergeAlterTables ¶
MergeAlterTables mergealter: 将同一张表的多条ALTER语句合成一条ALTER语句 @input: sql, alter string @output: [[db.]table]sql, 如果找不到DB,key为表名;如果找得到DB,key为db.table
func MysqlEscapeString ¶
MysqlEscapeString mysql_real_escape_string https://github.com/liule/golang_escape
func PrintPrettyStmtNode ¶
func PrintPrettyStmtNode(sql, charset, collation string)
PrintPrettyStmtNode 打印TiParse语法树
func SplitStatement ¶
SplitStatement SQL切分
Types ¶
type NodeItem ¶
type NodeItem struct { ID int // NodeItem在List中的编号,与顺序有关 Prev *NodeItem // 前一个节点 Self sqlparser.SQLNode // 自身指向的AST Node Next *NodeItem // 后一个节点 Array *NodeList // 指针指向所在的链表,用于快速跳转node }
NodeItem 链表节点
type NodeList ¶
NodeList 链表结构体
func NewNodeList ¶
NewNodeList 从抽象语法树中构造一个链表
type Rewrite ¶
type Rewrite struct { SQL string NewSQL string Stmt sqlparser.Statement Columns common.TableColumns }
Rewrite 用于重写SQL
func NewRewrite ¶
NewRewrite 返回一个*Rewrite对象,如果SQL无法被正常解析,将错误输出到日志中,返回一个nil
func (*Rewrite) RewriteAddOrderByNull ¶
RewriteAddOrderByNull orderbynull: 对应CLA.008,GROUP BY无排序要求时添加ORDER BY NULL
func (*Rewrite) RewriteAlwaysTrue ¶
RewriteAlwaysTrue alwaystrue: 删除恒真条件
func (*Rewrite) RewriteAutoIncrement ¶
RewriteAutoIncrement autoincrement: 将auto_increment设置为1
func (*Rewrite) RewriteCountStar ¶
RewriteCountStar countstar: 将COUNT(col)改写为COUNT(*) COUNT(DISTINCT col)不能替换为COUNT(*)
func (*Rewrite) RewriteDML2Select ¶
RewriteDML2Select dml2select: DML转成SELECT,兼容低版本的EXPLAIN
func (*Rewrite) RewriteDelimiter ¶
RewriteDelimiter delimiter: 补分号,可以指定不同的DELIMITER
func (*Rewrite) RewriteDistinctStar ¶
RewriteDistinctStar distinctstar: 对应DIS.003,将多余的`DISTINCT *`删除
func (*Rewrite) RewriteGroupByConst ¶
RewriteGroupByConst 对应CLA.004,将GROUP BY CONST替换为列名 TODO:
func (*Rewrite) RewriteHaving ¶
RewriteHaving having: 对应CLA.013,使用WHERE过滤条件替代HAVING
func (*Rewrite) RewriteInNull ¶
RewriteInNull innull: TODO: 对应ARG.004
func (*Rewrite) RewriteInnoDB ¶
RewriteInnoDB innodb: 为未指定Engine的表默认添加InnoDB引擎,将其他存储引擎转为InnoDB
func (*Rewrite) RewriteInsertColumns ¶
RewriteInsertColumns insertcolumns: 对应COL.002,INSERT补全列名
func (*Rewrite) RewriteIntWidth ¶
RewriteIntWidth intwidth: int类型转为int(10),bigint类型转为bigint(20)
func (*Rewrite) RewriteJoin2SubQuery ¶
RewriteJoin2SubQuery join2sub: TODO: https://mariadb.com/kb/en/library/subqueries-and-joins/
func (*Rewrite) RewriteOr2In ¶
RewriteOr2In or2in: 同一列的OR过滤条件使用IN()替代,如果值有相等的会进行合并
func (*Rewrite) RewriteOr2Union ¶
RewriteOr2Union or2union: 将OR查询转写为UNION ALL TODO: 暂无对应HeuristicRules https://sqlperformance.com/2014/09/sql-plan/rewriting-queries-improve-performance
func (*Rewrite) RewriteRemoveDMLOrderBy ¶
RewriteRemoveDMLOrderBy dmlorderby: 对应RES.004,删除无LIMIT条件时UPDATE, DELETE中包含的ORDER BY
func (*Rewrite) RewriteRmParenthesis ¶
RewriteRmParenthesis rmparenthesis: 去除无意义的括号
func (*Rewrite) RewriteStandard ¶
RewriteStandard standard: 使用vitess提供的String功能将抽象语法树转写回SQL,注意:这可能转写失败。
func (*Rewrite) RewriteStar2Columns ¶
RewriteStar2Columns star2columns: 对应COL.001,SELECT补全*指代的列名
func (*Rewrite) RewriteSubQuery2Join ¶
RewriteSubQuery2Join 将subquery转写成join
func (*Rewrite) RewriteTruncate ¶
RewriteTruncate truncate: DELETE全表修改为TRUNCATE TABLE
func (*Rewrite) RewriteUnionAll ¶
RewriteUnionAll unionall: 不介意重复数据的情况下使用union all替换union
type Rule ¶
type Rule struct { Name string `json:"Name"` Description string `json:"Description"` Original string `json:"Original"` // 错误示范。为空或"暂不支持"不会出现在list-rewrite-rules中 Suggest string `json:"Suggest"` // 正确示范。 Func func(*Rewrite) *Rewrite `json:"-"` // 如果不定义Func需要多条SQL联动改写 }
Rule SQL重写规则