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

support new heuristic rules check

  COL.014 support NVARCHAR
  COL.013 support zero time
上级 68128b73
...@@ -27,9 +27,11 @@ import ( ...@@ -27,9 +27,11 @@ import (
"github.com/XiaoMi/soar/ast" "github.com/XiaoMi/soar/ast"
"github.com/XiaoMi/soar/common" "github.com/XiaoMi/soar/common"
"github.com/XiaoMi/soar/database" "github.com/XiaoMi/soar/database"
"github.com/gedex/inflector" "github.com/gedex/inflector"
"github.com/percona/go-mysql/query" "github.com/percona/go-mysql/query"
tidb "github.com/pingcap/parser/ast" tidb "github.com/pingcap/parser/ast"
"github.com/pingcap/parser/format"
"github.com/pingcap/parser/mysql" "github.com/pingcap/parser/mysql"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"vitess.io/vitess/go/vt/sqlparser" "vitess.io/vitess/go/vt/sqlparser"
...@@ -2870,11 +2872,20 @@ func (q *Query4Audit) RuleTimestampDefault() Rule { ...@@ -2870,11 +2872,20 @@ func (q *Query4Audit) RuleTimestampDefault() Rule {
if col.Tp == nil { if col.Tp == nil {
continue continue
} }
if col.Tp.Tp == mysql.TypeTimestamp { switch col.Tp.Tp {
case mysql.TypeTimestamp, mysql.TypeDate, mysql.TypeDatetime, mysql.TypeNewDate:
hasDefault := false hasDefault := false
var sb strings.Builder
ctx := format.NewRestoreCtx(format.DefaultRestoreFlags, &sb)
for _, option := range col.Options { for _, option := range col.Options {
if option.Tp == tidb.ColumnOptionDefaultValue { if option.Tp == tidb.ColumnOptionDefaultValue {
hasDefault = true hasDefault = true
if err := option.Restore(ctx); err == nil {
if strings.HasPrefix(sb.String(), `DEFAULT '0`) ||
strings.HasPrefix(sb.String(), `DEFAULT 0`) {
hasDefault = false
}
}
} }
} }
if !hasDefault { if !hasDefault {
...@@ -2894,11 +2905,20 @@ func (q *Query4Audit) RuleTimestampDefault() Rule { ...@@ -2894,11 +2905,20 @@ func (q *Query4Audit) RuleTimestampDefault() Rule {
if col.Tp == nil { if col.Tp == nil {
continue continue
} }
if col.Tp.Tp == mysql.TypeTimestamp { var sb strings.Builder
ctx := format.NewRestoreCtx(format.DefaultRestoreFlags, &sb)
switch col.Tp.Tp {
case mysql.TypeTimestamp, mysql.TypeDate, mysql.TypeDatetime, mysql.TypeNewDate:
hasDefault := false hasDefault := false
for _, option := range col.Options { for _, option := range col.Options {
if option.Tp == tidb.ColumnOptionDefaultValue { if option.Tp == tidb.ColumnOptionDefaultValue {
hasDefault = true hasDefault = true
if err := option.Restore(ctx); err == nil {
if strings.HasPrefix(sb.String(), `DEFAULT '0`) ||
strings.HasPrefix(sb.String(), `DEFAULT 0`) {
hasDefault = false
}
}
} }
} }
if !hasDefault { if !hasDefault {
...@@ -2938,6 +2958,16 @@ func (q *Query4Audit) RuleAutoIncrementInitNotZero() Rule { ...@@ -2938,6 +2958,16 @@ func (q *Query4Audit) RuleAutoIncrementInitNotZero() Rule {
// RuleColumnWithCharset COL.014 // RuleColumnWithCharset COL.014
func (q *Query4Audit) RuleColumnWithCharset() Rule { func (q *Query4Audit) RuleColumnWithCharset() Rule {
var rule = q.RuleOK() var rule = q.RuleOK()
tks := ast.Tokenize(q.Query)
for _, tk := range tks {
if tk.Type == ast.TokenTypeWord {
switch strings.TrimSpace(strings.ToLower(tk.Val)) {
case "national", "nvarchar", "nchar", "nvarchar(", "nchar(", "character":
rule = HeuristicRules["COL.014"]
return rule
}
}
}
switch q.Stmt.(type) { switch q.Stmt.(type) {
case *sqlparser.DDL: case *sqlparser.DDL:
for _, tiStmt := range q.TiStmt { for _, tiStmt := range q.TiStmt {
......
...@@ -2769,6 +2769,9 @@ func TestRuleTimestampDefault(t *testing.T) { ...@@ -2769,6 +2769,9 @@ func TestRuleTimestampDefault(t *testing.T) {
{ {
"CREATE TABLE tbl( `id` bigint not null, `create_time` timestamp) ENGINE=InnoDB DEFAULT CHARSET=utf8;", "CREATE TABLE tbl( `id` bigint not null, `create_time` timestamp) ENGINE=InnoDB DEFAULT CHARSET=utf8;",
"ALTER TABLE t1 MODIFY b timestamp NOT NULL;", "ALTER TABLE t1 MODIFY b timestamp NOT NULL;",
`ALTER TABLE t1 ADD c_time timestamp NOT NULL default "0000-00-00"`,
`ALTER TABLE t1 ADD c_time timestamp NOT NULL default 0`,
`ALTER TABLE t1 ADD c_time datetime NOT NULL default 0`,
}, },
{ {
"CREATE TABLE tbl (`id` bigint not null, `update_time` timestamp default current_timestamp)", "CREATE TABLE tbl (`id` bigint not null, `update_time` timestamp default current_timestamp)",
...@@ -2850,6 +2853,8 @@ func TestRuleColumnWithCharset(t *testing.T) { ...@@ -2850,6 +2853,8 @@ func TestRuleColumnWithCharset(t *testing.T) {
{ {
"CREATE TABLE `tb2` ( `id` int(11) DEFAULT NULL, `col` char(10) CHARACTER SET utf8 DEFAULT NULL)", "CREATE TABLE `tb2` ( `id` int(11) DEFAULT NULL, `col` char(10) CHARACTER SET utf8 DEFAULT NULL)",
"alter table tb2 change col col char(10) CHARACTER SET utf8 DEFAULT NULL;", "alter table tb2 change col col char(10) CHARACTER SET utf8 DEFAULT NULL;",
"CREATE TABLE tb (a nvarchar(10))",
"CREATE TABLE tb (a nchar(10))",
}, },
// 反面的例子 // 反面的例子
{ {
......
...@@ -523,8 +523,8 @@ func init() { ...@@ -523,8 +523,8 @@ func init() {
"COL.013": { "COL.013": {
Item: "COL.013", Item: "COL.013",
Severity: "L4", Severity: "L4",
Summary: "TIMESTAMP 类型未设置默认值", Summary: "TIMESTAMP 类型默认值检查异常",
Content: `TIMESTAMP 类型未设置默认值`, Content: `TIMESTAMP 类型建议设置默认值,且不建议使用 0 或 0000-00-00 00:00:00 作为默认值。可以考虑使用 1970-08-02 01:01:01`,
Case: "CREATE TABLE tbl( `id` bigint not null, `create_time` timestamp);", Case: "CREATE TABLE tbl( `id` bigint not null, `create_time` timestamp);",
Func: (*Query4Audit).RuleTimestampDefault, Func: (*Query4Audit).RuleTimestampDefault,
}, },
......
...@@ -472,11 +472,11 @@ select c1,c2,c3 from tbl where c4 is null or c4 <> 1 ...@@ -472,11 +472,11 @@ select c1,c2,c3 from tbl where c4 is null or c4 <> 1
```sql ```sql
CREATE TABLE `tb`(`c` longblob NOT NULL); CREATE TABLE `tb`(`c` longblob NOT NULL);
``` ```
## TIMESTAMP 类型未设置默认值 ## TIMESTAMP 类型默认值检查异常
* **Item**:COL.013 * **Item**:COL.013
* **Severity**:L4 * **Severity**:L4
* **Content**:TIMESTAMP 类型未设置默认值 * **Content**:TIMESTAMP 类型建议设置默认值,且不建议使用 0 或 0000-00-00 00:00:00 作为默认值。可以考虑使用 1970-08-02 01:01:01
* **Case**: * **Case**:
```sql ```sql
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册