From 47b425c9f3e34f5910f9b27f158efefbb2c942f4 Mon Sep 17 00:00:00 2001 From: Leon Zhang Date: Fri, 22 Jan 2021 22:42:02 +0800 Subject: [PATCH] ADD ARG.014 Rule and some doc fix --- advisor/heuristic.go | 6 +++++- advisor/rules.go | 10 +++++++++- doc/heuristic.md | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/advisor/heuristic.go b/advisor/heuristic.go index 258e614..813e1de 100644 --- a/advisor/heuristic.go +++ b/advisor/heuristic.go @@ -2553,7 +2553,7 @@ func (q *Query4Audit) RuleTruncateTable() Rule { return rule } -// RuleIn ARG.005 && ARG.004 +// RuleIn ARG.005 && ARG.004 && ARG.014 func (q *Query4Audit) RuleIn() Rule { var rule = q.RuleOK() err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { @@ -2562,6 +2562,10 @@ func (q *Query4Audit) RuleIn() Rule { switch strings.ToLower(n.Operator) { case "in": switch r := n.Right.(type) { + case sqlparser.ColTuple: + // id in (1, 2, id), always true. + rule = HeuristicRules["ARG.014"] + return false, nil case sqlparser.ValTuple: // IN (NULL) for _, v := range r { diff --git a/advisor/rules.go b/advisor/rules.go index f7f9334..0f25b89 100644 --- a/advisor/rules.go +++ b/advisor/rules.go @@ -280,6 +280,14 @@ func init() { Case: "CREATE TABLE tb (a varchar(10) default '“”'", Func: (*Query4Audit).RuleFullWidthQuote, }, + "ARG.014": { + Item: "ARG.014", + Severity: "L4", + Summary: "IN 条件中存在列名,可能导致数据匹配范围扩大", + Content: `如:delete from t where id in(1, 2, id) 可能会导致全表数据误删除。请仔细检查 IN 条件的正确性。`, + Case: "select id from t where id in(1, 2, id)", + Func: (*Query4Audit).RuleIn, + }, "CLA.001": { Item: "CLA.001", Severity: "L4", @@ -506,7 +514,7 @@ func init() { "COL.010": { Item: "COL.010", Severity: "L2", - Summary: "不建议使用 ENUM 数据类型", + Summary: "不建议使用 ENUM/BIT/SET 数据类型", Content: `ENUM 定义了列中值的类型,使用字符串表示 ENUM 里的值时,实际存储在列中的数据是这些值在定义时的序数。因此,这列的数据是字节对齐的,当您进行一次排序查询时,结果是按照实际存储的序数值排序的,而不是按字符串值的字母顺序排序的。这可能不是您所希望的。没有什么语法支持从 ENUM 或者 check 约束中添加或删除一个值;您只能使用一个新的集合重新定义这一列。如果您打算废弃一个选项,您可能会为历史数据而烦恼。作为一种策略,改变元数据——也就是说,改变表和列的定义——应该是不常见的,并且要注意测试和质量保证。有一个更好的解决方案来约束一列中的可选值:创建一张检查表,每一行包含一个允许在列中出现的候选值;然后在引用新表的旧表上声明一个外键约束。`, Case: "create table tab1(status ENUM('new','in progress','fixed'))", Func: (*Query4Audit).RuleValuesInDefinition, diff --git a/doc/heuristic.md b/doc/heuristic.md index 9731c97..27c4a02 100644 --- a/doc/heuristic.md +++ b/doc/heuristic.md @@ -452,7 +452,7 @@ create table t1(id int,name char(20),last_time date) ```sql CREATE TABLE tab2 (p_id BIGINT UNSIGNED NOT NULL,a_id BIGINT UNSIGNED NOT NULL,hours float not null,PRIMARY KEY (p_id, a_id)) ``` -## 不建议使用 ENUM 数据类型 +## 不建议使用 ENUM/BIT/SET 数据类型 * **Item**:COL.010 * **Severity**:L2 -- GitLab