From fcba5e74e566fd44535786b3f7018800ebfbab70 Mon Sep 17 00:00:00 2001 From: liipx Date: Thu, 6 Dec 2018 17:09:04 +0800 Subject: [PATCH] COL.007 reward --- advisor/heuristic.go | 51 +++++++++++++++++++++++++++++++++++++++ advisor/heuristic_test.go | 46 +++++++++++++++++++++++++++++++++++ advisor/index.go | 13 +++++++--- 3 files changed, 106 insertions(+), 4 deletions(-) diff --git a/advisor/heuristic.go b/advisor/heuristic.go index a6e0fd3..d432d86 100644 --- a/advisor/heuristic.go +++ b/advisor/heuristic.go @@ -3272,6 +3272,57 @@ func (q *Query4Audit) RuleMaxTextColsCount() Rule { return rule } +// RuleMaxTextColsCount COL.007 checking for existed table +func (idxAdv *IndexAdvisor) RuleMaxTextColsCount() Rule { + rule := HeuristicRules["OK"] + // 未开启测试环境不进行检查 + if common.Config.TestDSN.Disable { + return rule + } + + sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { + switch stmt := node.(type) { + case *sqlparser.DDL: + if stmt.Action != "alter" { + return true, nil + } + + tb := stmt.Table + + // 此处的检查需要在测试环境中的临时数据库中进行检查 + // 需要将测试环境 DSN 的数据库暂时指向临时数据库 + // 为了防止影响切换数据库环境会影响接下来的测试,需要在检查完后将原配置还原 + dbTmp := idxAdv.vEnv.Database + idxAdv.vEnv.Database = idxAdv.vEnv.DBRef[idxAdv.vEnv.Database] + defer func() { + idxAdv.vEnv.Database = dbTmp + }() + + // 添加字段的语句会在初始化环境的时候被执行 + // 只需要获取该标的 CREAET 语句,后再对该语句进行检查即可 + ddl, err := idxAdv.vEnv.ShowCreateTable(tb.Name.String()) + if err != nil { + common.Log.Error("RuleMaxTextColsCount create statement got failed: %s", err.Error()) + return false, err + } + + q, err := NewQuery4Audit(ddl) + if err != nil { + return false, err + } + + r := q.RuleMaxTextColsCount() + if r.Item != "OK" { + rule = r + return false, nil + } + } + return true, nil + }, idxAdv.Ast) + + return rule +} + // RuleAllowEngine TBL.002 func (q *Query4Audit) RuleAllowEngine() Rule { var rule = q.RuleOK() diff --git a/advisor/heuristic_test.go b/advisor/heuristic_test.go index 4ef4d21..1487bfe 100644 --- a/advisor/heuristic_test.go +++ b/advisor/heuristic_test.go @@ -23,7 +23,10 @@ import ( "github.com/XiaoMi/soar/common" + "github.com/XiaoMi/soar/env" "github.com/kr/pretty" + "strings" + "vitess.io/vitess/go/vt/sqlparser" ) // ALI.001 @@ -3113,6 +3116,49 @@ func TestRuleMaxTextColsCount(t *testing.T) { common.Log.Debug("Exiting function: %s", common.GetFunctionName()) } +// COL.007 +func TestRuleMaxTextColsCountWithEnv(t *testing.T) { + common.Log.Debug("Entering function: %s", common.GetFunctionName()) + dsn := common.Config.OnlineDSN + common.Config.OnlineDSN = common.Config.TestDSN + vEnv, rEnv := env.BuildEnv() + defer vEnv.CleanUp() + initSQLs := []string{ + `CREATE TABLE t1 (id int, title text, content blob);`, + "alter table t1 add column other text;", + } + + for _, sql := range initSQLs { + vEnv.BuildVirtualEnv(rEnv, sql) + + if !strings.HasPrefix(strings.ToLower(sql), "alter") { + continue + } + + stmt, syntaxErr := sqlparser.Parse(sql) + if syntaxErr != nil { + common.Log.Critical("Syntax Error: %v, SQL: %s", syntaxErr, sql) + } + + q := &Query4Audit{Query: sql, Stmt: stmt} + + idxAdvisor, err := NewAdvisor(vEnv, *rEnv, *q) + + if err != nil { + t.Error("NewAdvisor Error: ", err, "SQL: ", sql) + } + + if idxAdvisor != nil { + rule := idxAdvisor.RuleMaxTextColsCount() + if rule.Item != "COL.007" { + t.Error("Rule not match:", rule, "Expect : COL.007, SQL:", sql) + } + } + } + common.Log.Debug("Exiting function: %s", common.GetFunctionName()) + common.Config.OnlineDSN = dsn +} + // TBL.002 func TestRuleAllowEngine(t *testing.T) { common.Log.Debug("Entering function: %s", common.GetFunctionName()) diff --git a/advisor/index.go b/advisor/index.go index 0c00818..ace191c 100644 --- a/advisor/index.go +++ b/advisor/index.go @@ -111,7 +111,11 @@ func NewAdvisor(env *env.VirtualEnv, rEnv database.Connector, q Query4Audit) (*I } } - return nil, nil + return &IndexAdvisor{ + vEnv: env, + rEnv: rEnv, + Ast: q.Stmt, + }, nil case *sqlparser.DBDDL: // 忽略建库语句 @@ -1011,11 +1015,12 @@ func (idxAdv *IndexAdvisor) HeuristicCheck(q Query4Audit) map[string]Rule { } ruleFuncs := []func(*IndexAdvisor) Rule{ + (*IndexAdvisor).RuleMaxTextColsCount, // COL.007 (*IndexAdvisor).RuleImplicitConversion, // ARG.003 + (*IndexAdvisor).RuleGroupByConst, // CLA.004 + (*IndexAdvisor).RuleOrderByConst, // CLA.005 + (*IndexAdvisor).RuleUpdatePrimaryKey, // CLA.016 // (*IndexAdvisor).RuleImpossibleOuterJoin, // TODO: JOI.003, JOI.004 - (*IndexAdvisor).RuleGroupByConst, // CLA.004 - (*IndexAdvisor).RuleOrderByConst, // CLA.005 - (*IndexAdvisor).RuleUpdatePrimaryKey, // CLA.016 } for _, f := range ruleFuncs { -- GitLab