提交 d9f6ef72 编写于 作者: martianzhang's avatar martianzhang

for test coverage

上级 407db8a0
......@@ -31,7 +31,13 @@ func TestDigestExplainText(t *testing.T) {
| 1 | SIMPLE | city | ref | idx_fk_country_id,idx_country_id_city,idx_all,idx_other | idx_fk_country_id | 2 | sakila.country.country_id | 2 | Using index |
+----+-------------+---------+-------+---------------------------------------------------------+-------------------+---------+---------------------------+------+-------------+`
common.Config.ReportType = "explain-digest"
err := common.GoldenDiff(func() { DigestExplainText(text) }, t.Name(), update)
err := common.GoldenDiff(func() {
DigestExplainText(text)
orgReportType := common.Config.ReportType
common.Config.ReportType = "html"
DigestExplainText(text)
common.Config.ReportType = orgReportType
}, t.Name(), update)
if nil != err {
t.Fatal(err)
}
......
......@@ -312,7 +312,7 @@ func (rw *Rewrite) RewriteStandard() *Rewrite {
return rw
}
// RewriteAlwaysTrue alwaystrue: 删除恒真条件
// RewriteAlwaysTrue always true: 删除恒真条件
func (rw *Rewrite) RewriteAlwaysTrue() (reWriter *Rewrite) {
array := NewNodeList(rw.Stmt)
tNode := array.Head
......@@ -340,7 +340,7 @@ func isAlwaysTrue(expr *sqlparser.ComparisonExpr) bool {
expr.Operator = "!="
case "<=>":
expr.Operator = "="
case ">=", "<=", "!=", "=":
case ">=", "<=", "!=", "=", ">", "<":
default:
return false
}
......
......@@ -433,10 +433,18 @@ func TestRewriteAlwaysTrue(t *testing.T) {
"input": "SELECT count(col) FROM tbl where 1>=1;",
"output": "select count(col) from tbl",
},
{
"input": "SELECT count(col) FROM tbl where 2>1;",
"output": "select count(col) from tbl",
},
{
"input": "SELECT count(col) FROM tbl where 1<=1;",
"output": "select count(col) from tbl",
},
{
"input": "SELECT count(col) FROM tbl where 1<2;",
"output": "select count(col) from tbl",
},
{
"input": "SELECT count(col) FROM tbl where 1=1 and 2=2;",
"output": "select count(col) from tbl",
......@@ -461,6 +469,10 @@ func TestRewriteAlwaysTrue(t *testing.T) {
"input": "SELECT count(col) FROM tbl where (1=1);",
"output": "select count(col) from tbl",
},
{
"input": "SELECT count(col) FROM tbl where a=1;",
"output": "select count(col) from tbl where a = 1",
},
{
"input": "SELECT count(col) FROM tbl where ('a'= 'a' or 'b' = 'b') and a = 'b';",
"output": "select count(col) from tbl where a = 'b'",
......@@ -777,6 +789,10 @@ func TestListRewriteRules(t *testing.T) {
common.Log.Debug("Entering function: %s", common.GetFunctionName())
err := common.GoldenDiff(func() {
ListRewriteRules(RewriteRules)
orgReportType := common.Config.ReportType
common.Config.ReportType = "json"
ListRewriteRules(RewriteRules)
common.Config.ReportType = orgReportType
}, t.Name(), update)
if err != nil {
t.Error(err)
......
......@@ -270,3 +270,143 @@ use sakila
```sql
use sakila;
```
[
{
"Name": "dml2select",
"Description": "将数据库更新请求转换为只读查询请求,便于执行EXPLAIN",
"Original": "DELETE FROM film WHERE length \u003e 100",
"Suggest": "select * from film where length \u003e 100"
},
{
"Name": "star2columns",
"Description": "为SELECT *补全表的列信息",
"Original": "SELECT * FROM film",
"Suggest": "select film.film_id, film.title from film"
},
{
"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)"
},
{
"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"
},
{
"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"
},
{
"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"
},
{
"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);"
},
{
"Name": "innull",
"Description": "如果 IN 条件中可能有 NULL 值而又想匹配 NULL 值时,建议添加OR col IS NULL",
"Original": "暂不支持",
"Suggest": "暂不支持"
},
{
"Name": "or2union",
"Description": "将不同列的 OR 查询转为 UNION 查询,建议结合 unionall 重写策略一起使用",
"Original": "暂不支持",
"Suggest": "暂不支持"
},
{
"Name": "dmlorderby",
"Description": "删除 DML 更新操作中无意义的 ORDER BY",
"Original": "DELETE FROM tbl WHERE col1=1 ORDER BY col",
"Suggest": "delete from tbl where col1 = 1"
},
{
"Name": "sub2join",
"Description": "将子查询转换为JOIN查询",
"Original": "暂不支持",
"Suggest": "暂不支持"
},
{
"Name": "join2sub",
"Description": "将JOIN查询转换为子查询",
"Original": "暂不支持",
"Suggest": "暂不支持"
},
{
"Name": "distinctstar",
"Description": "DISTINCT *对有主键的表没有意义,可以将DISTINCT删掉",
"Original": "SELECT DISTINCT * FROM film;",
"Suggest": "SELECT * FROM film"
},
{
"Name": "standard",
"Description": "SQL标准化,如:关键字转换为小写",
"Original": "SELECT sum(col1) FROM tbl GROUP BY 1;",
"Suggest": "select sum(col1) from tbl group by 1"
},
{
"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');"
},
{
"Name": "countstar",
"Description": "不建议使用COUNT(col)或COUNT(常量),建议改写为COUNT(*)",
"Original": "SELECT count(col) FROM tbl GROUP BY 1;",
"Suggest": "SELECT count(*) FROM tbl GROUP BY 1;"
},
{
"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;"
},
{
"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;"
},
{
"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;"
},
{
"Name": "truncate",
"Description": "不带 WHERE 条件的 DELETE 操作建议修改为 TRUNCATE",
"Original": "DELETE FROM tbl",
"Suggest": "truncate table tbl"
},
{
"Name": "rmparenthesis",
"Description": "去除没有意义的括号",
"Original": "select col from table where (col = 1);",
"Suggest": "select col from table where col = 1;"
},
{
"Name": "delimiter",
"Description": "补全DELIMITER",
"Original": "use sakila",
"Suggest": "use sakila;"
}
]
......@@ -604,6 +604,9 @@ func MySQLExplainWarnings(exp *ExplainInfo) string {
// MySQLExplainQueryCost 将last_query_cost信息补充到评审结果中
func MySQLExplainQueryCost(exp *ExplainInfo) string {
var content string
if exp == nil {
return content
}
if exp.QueryCost > 0 {
tmp := fmt.Sprintf("%.3f\n", exp.QueryCost)
......@@ -819,7 +822,7 @@ func parseTraditionalExplainText(content string) (explainRows []*ExplainRow, err
}
// filtered may larger than 100.00
// https://bugs.mysql.com/bug.php?id=34124
if filtered > 100.00 {
if filtered >= 100.00 {
filtered = 100.00
}
......@@ -1039,6 +1042,7 @@ func ParseExplainResult(res QueryResult, formatType int) (exp *ExplainInfo, err
// Explain 获取 SQL 的 explain 信息
func (db *Connector) Explain(sql string, explainType int, formatType int) (exp *ExplainInfo, err error) {
exp = &ExplainInfo{SQL: sql}
if explainType != TraditionalExplainType {
formatType = TraditionalFormatExplain
}
......@@ -1054,13 +1058,14 @@ func (db *Connector) Explain(sql string, explainType int, formatType int) (exp *
}()
// 执行EXPLAIN请求
sql = db.explainQuery(sql, explainType, formatType)
res, err := db.Query(sql)
exp.SQL = db.explainQuery(sql, explainType, formatType)
res, err := db.Query(exp.SQL)
if err != nil {
return exp, err
}
// 解析mysql结果,输出ExplainInfo
exp, err = ParseExplainResult(res, formatType)
exp.SQL = sql
return exp, err
}
......
......@@ -17,6 +17,7 @@
package database
import (
"fmt"
"testing"
"github.com/XiaoMi/soar/common"
......@@ -2439,12 +2440,13 @@ func TestMySQLExplainWarnings(t *testing.T) {
func TestMySQLExplainQueryCost(t *testing.T) {
common.Log.Debug("Entering function: %s", common.GetFunctionName())
expInfo, err := connTest.Explain("select 1", TraditionalExplainType, TraditionalFormatExplain)
if err != nil {
t.Error(err)
}
err = common.GoldenDiff(func() {
MySQLExplainQueryCost(expInfo)
err := common.GoldenDiff(func() {
expInfo, err := connTest.Explain("select 1", TraditionalExplainType, TraditionalFormatExplain)
fmt.Println(err, MySQLExplainQueryCost(expInfo))
expInfo, err = connTest.Explain("select 1", ExtendedExplainType, TraditionalFormatExplain)
fmt.Println(err, MySQLExplainQueryCost(expInfo))
expInfo, err = connTest.Explain("select 1", TraditionalExplainType, JSONFormatExplain)
fmt.Println(err, MySQLExplainQueryCost(expInfo))
}, t.Name(), update)
if err != nil {
t.Error(err)
......
......@@ -279,6 +279,7 @@ func (db *Connector) dangerousQuery(query string) bool {
"show",
"explain",
"describe",
"desc",
}
for _, prefix := range whiteList {
......
......@@ -30,6 +30,10 @@ func TestProfiling(t *testing.T) {
t.Error(err)
}
pretty.Println(rows)
_, err = connTest.Profiling("delete from film")
if err == nil {
t.Error(err)
}
common.Log.Debug("Exiting function: %s", common.GetFunctionName())
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册