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

Merge branch 'dev' of github.com:XiaoMi/soar into dev

......@@ -832,7 +832,7 @@ func (q *Query4Audit) RuleAddDefaultValue() Rule {
}
switch c.Tp.Tp {
case mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob:
case mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob, mysql.TypeJSON:
colDefault = true
}
......@@ -855,7 +855,7 @@ func (q *Query4Audit) RuleAddDefaultValue() Rule {
}
switch c.Tp.Tp {
case mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob:
case mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob, mysql.TypeJSON:
colDefault = true
}
......@@ -2729,8 +2729,14 @@ func (q *Query4Audit) RuleAlterCharset() Rule {
for _, option := range spec.Options {
if option.Tp == tidb.TableOptionCharset ||
option.Tp == tidb.TableOptionCollate {
rule = HeuristicRules["ALT.001"]
break
//增加CONVERT TO的判断
convertReg, _ := regexp.Compile("convert to")
if convertReg.Match([]byte(strings.ToLower(q.Query))) {
break
} else {
rule = HeuristicRules["ALT.001"]
break
}
}
}
}
......@@ -2807,7 +2813,7 @@ func (q *Query4Audit) RuleBLOBNotNull() Rule {
continue
}
switch col.Tp.Tp {
case mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob:
case mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob, mysql.TypeJSON:
for _, opt := range col.Options {
if opt.Tp == tidb.ColumnOptionNotNull {
rule = HeuristicRules["COL.012"]
......@@ -2830,7 +2836,7 @@ func (q *Query4Audit) RuleBLOBNotNull() Rule {
continue
}
switch col.Tp.Tp {
case mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob:
case mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob, mysql.TypeJSON:
for _, opt := range col.Options {
if opt.Tp == tidb.ColumnOptionNotNull {
rule = HeuristicRules["COL.012"]
......@@ -3157,7 +3163,8 @@ func (q *Query4Audit) RuleColumnWithCharset() Rule {
for _, tk := range tks {
if tk.Type == ast.TokenTypeWord {
switch strings.TrimSpace(strings.ToLower(tk.Val)) {
case "national", "nvarchar", "nchar", "nvarchar(", "nchar(", "character":
//character移到后面检查
case "national", "nvarchar", "nchar", "nvarchar(", "nchar(":
rule = HeuristicRules["COL.014"]
return rule
}
......@@ -3173,6 +3180,16 @@ func (q *Query4Audit) RuleColumnWithCharset() Rule {
continue
}
if col.Tp.Charset != "" || col.Tp.Collate != "" {
if col.Tp.Charset == "binary" || col.Tp.Collate == "binary" {
continue
} else {
rule = HeuristicRules["COL.014"]
break
}
}
//在这里检查character
characterReg, _ := regexp.Compile("character set")
if characterReg.Match([]byte(strings.ToLower(q.Query))) {
rule = HeuristicRules["COL.014"]
break
}
......@@ -3187,6 +3204,15 @@ func (q *Query4Audit) RuleColumnWithCharset() Rule {
continue
}
if col.Tp.Charset != "" || col.Tp.Collate != "" {
if col.Tp.Charset == "binary" || col.Tp.Collate == "binary" {
continue
} else {
rule = HeuristicRules["COL.014"]
break
}
}
characterReg, _ := regexp.Compile("character set")
if characterReg.Match([]byte(strings.ToLower(q.Query))) {
rule = HeuristicRules["COL.014"]
break
}
......@@ -3391,7 +3417,7 @@ func (q *Query4Audit) RuleBlobDefaultValue() Rule {
continue
}
switch col.Tp.Tp {
case mysql.TypeBlob, mysql.TypeMediumBlob, mysql.TypeTinyBlob, mysql.TypeLongBlob:
case mysql.TypeBlob, mysql.TypeMediumBlob, mysql.TypeTinyBlob, mysql.TypeLongBlob, mysql.TypeJSON:
for _, opt := range col.Options {
if opt.Tp == tidb.ColumnOptionDefaultValue && opt.Expr.GetType().Tp != mysql.TypeNull {
rule = HeuristicRules["COL.015"]
......@@ -3410,7 +3436,7 @@ func (q *Query4Audit) RuleBlobDefaultValue() Rule {
continue
}
switch col.Tp.Tp {
case mysql.TypeBlob, mysql.TypeMediumBlob, mysql.TypeTinyBlob, mysql.TypeLongBlob:
case mysql.TypeBlob, mysql.TypeMediumBlob, mysql.TypeTinyBlob, mysql.TypeLongBlob, mysql.TypeJSON:
for _, opt := range col.Options {
if opt.Tp == tidb.ColumnOptionDefaultValue && opt.Expr.GetType().Tp != mysql.TypeNull {
rule = HeuristicRules["COL.015"]
......
......@@ -3265,17 +3265,24 @@ func TestRuleBlobDefaultValue(t *testing.T) {
sqls := [][]string{
{
"CREATE TABLE `tb` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `c` blob NOT NULL DEFAULT '', PRIMARY KEY (`id`));",
"CREATE TABLE `tb` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT, `c` json NOT NULL DEFAULT '', PRIMARY KEY (`id`));",
"alter table `tb` add column `c` blob NOT NULL DEFAULT '';",
"alter table `tb` add column `c` json NOT NULL DEFAULT '';",
},
{
"CREATE TABLE `tb` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `c` blob NOT NULL, PRIMARY KEY (`id`));",
"CREATE TABLE `tb` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `c` json NOT NULL, PRIMARY KEY (`id`));",
"CREATE TABLE `tb` (`col` text NOT NULL);",
"alter table `tb` add column `c` blob NOT NULL;",
"alter table `tb` add column `c` json NOT NULL;",
"ALTER TABLE tb ADD COLUMN a BLOB DEFAULT NULL",
"ALTER TABLE tb ADD COLUMN a JSON DEFAULT NULL",
"CREATE TABLE tb ( a BLOB DEFAULT NULL)",
"CREATE TABLE tb ( a JSON DEFAULT NULL)",
"alter TABLE `tbl` add column `c` longblob;",
"alter TABLE `tbl` add column `c` text;",
"alter TABLE `tbl` add column `c` blob;",
"alter TABLE `tbl` add column `c` json;",
},
}
......
......@@ -523,8 +523,8 @@ func init() {
"COL.012": {
Item: "COL.012",
Severity: "L5",
Summary: "BLOB 和 TEXT 类型的字段不建议设置为 NOT NULL",
Content: `BLOB 和 TEXT 类型的字段无法指定非 NULL 的默认值,如果添加了 NOT NULL 限制,写入数据时又未对该字段指定值可能导致写入失败。`,
Summary: "TEXT、BLOB 和 JSON 类型的字段不建议设置为 NOT NULL",
Content: `TEXT、BLOB 和 JSON 类型的字段无法指定非 NULL 的默认值,如果添加了 NOT NULL 限制,写入数据时又未对该字段指定值可能导致写入失败。`,
Case: "CREATE TABLE `tb`(`c` longblob NOT NULL);",
Func: (*Query4Audit).RuleBLOBNotNull,
},
......@@ -548,8 +548,8 @@ func init() {
"COL.015": {
Item: "COL.015",
Severity: "L4",
Summary: "TEXT 和 BLOB 类型的字段不可指定非 NULL 的默认值",
Content: `MySQL 数据库中 TEXT 和 BLOB 类型的字段不可指定非 NULL 的默认值。TEXT最大长度为2^16-1个字符,MEDIUMTEXT最大长度为2^32-1个字符,LONGTEXT最大长度为2^64-1个字符。`,
Summary: "TEXT、BLOB 和 JSON 类型的字段不可指定非 NULL 的默认值",
Content: `MySQL 数据库中 TEXT、BLOB 和 JSON 类型的字段不可指定非 NULL 的默认值。TEXT最大长度为2^16-1个字符,MEDIUMTEXT最大长度为2^32-1个字符,LONGTEXT最大长度为2^64-1个字符。`,
Case: "CREATE TABLE `tbl` (`c` blob DEFAULT NULL);",
Func: (*Query4Audit).RuleBlobDefaultValue,
},
......
......@@ -476,7 +476,7 @@ select c1,c2,c3 from tbl where c4 is null or c4 <> 1
* **Item**:COL.012
* **Severity**:L5
* **Content**:BLOB 和 TEXT 类型的字段无法指定非 NULL 的默认值,如果添加了 NOT NULL 限制,写入数据时又未对该字段指定值可能导致写入失败。
* **Content**:TEXT、BLOB 和 JSON 类型的字段无法指定非 NULL 的默认值,如果添加了 NOT NULL 限制,写入数据时又未对该字段指定值可能导致写入失败。
* **Case**:
```sql
......@@ -506,7 +506,7 @@ CREATE TABLE `tb2` ( `id` int(11) DEFAULT NULL, `col` char(10) CHARACTER SET utf
* **Item**:COL.015
* **Severity**:L4
* **Content**:MySQL 数据库中 TEXT 和 BLOB 类型的字段不可指定非 NULL 的默认值。TEXT最大长度为2^16-1个字符,MEDIUMTEXT最大长度为2^32-1个字符,LONGTEXT最大长度为2^64-1个字符。
* **Content**:MySQL 数据库中 TEXT、BLOB 和 JSON 类型的字段不可指定非 NULL 的默认值。TEXT最大长度为2^16-1个字符,MEDIUMTEXT最大长度为2^32-1个字符,LONGTEXT最大长度为2^64-1个字符。
* **Case**:
```sql
......
......@@ -40,6 +40,7 @@ tb;
20 select /*!50000 1,*/ 1;
21 UPDATE xxx SET c1=' LOGGER.error(""); }' WHERE id = 2 ;
22 UPDATE `xxx` SET aaa='a;' WHERE `id` = 15;
23 UPDATE `xxx` SET aaa='a -- b' WHERE `id` = 15;
0 select * from test\G
1 select 'hello\Gworld', col from test\G
2 -- select * from test\Ghello
......
......@@ -862,12 +862,12 @@ func SplitStatement(buf []byte, delimiter []byte) (string, string, []byte) {
b := buf[i]
// single line comment
if b == '-' {
if i+2 < len(buf) && buf[i+1] == '-' && buf[i+2] == ' ' {
if !quoted && i+2 < len(buf) && buf[i+1] == '-' && buf[i+2] == ' ' {
singleLineComment = true
i = i + 2
continue
}
if i+2 < len(buf) && i == 0 && buf[i+1] == '-' && (buf[i+2] == '\n' || buf[i+2] == '\r') {
if !quoted && i+2 < len(buf) && i == 0 && buf[i+1] == '-' && (buf[i+2] == '\n' || buf[i+2] == '\r') {
sql = "--\n"
break
}
......
......@@ -173,7 +173,8 @@ select col from tb;
[]byte(`select /*!50000 1,*/ 1;`), // 20
[]byte(`UPDATE xxx SET c1=' LOGGER.error(""); }' WHERE id = 2 ;`), // 21
[]byte("UPDATE `xxx` SET aaa='a;' WHERE `id` = 15;"), // 22
// []byte(`/* comment here */ SET MAX_JOIN_SIZE=#`), // 23
[]byte("UPDATE `xxx` SET aaa='a -- b' WHERE `id` = 15; UPDATE `xxx` SET aaa='c -- d' WHERE `id` = 16;"), // 23
// []byte(`/* comment here */ SET MAX_JOIN_SIZE=#`), // 24
}
// \G 分隔符
buf2s := [][]byte{
......
......@@ -70,6 +70,15 @@ type tableStatusRow struct {
Comment []byte // 注释
}
// 记录去除逗号类型是外健还是分区表
type deleteComaType int8
const (
_ deleteComaType = iota
CS
PART
)
// newTableStat 构造 table Stat 对象
func newTableStat(tableName string) *TableStatInfo {
return &TableStatInfo{
......@@ -478,21 +487,37 @@ func (db *Connector) ShowCreateTable(tableName string) (string, error) {
if len(lines) > 2 {
var noConstraint []string
relationReg, _ := regexp.Compile("CONSTRAINT")
partitionReg, _ := regexp.Compile("PARTITIONS")
var DeleteComaT deleteComaType
for _, line := range lines[1 : len(lines)-1] {
if relationReg.Match([]byte(line)) {
DeleteComaT = CS
continue
} else if partitionReg.Match([]byte(line)) {
DeleteComaT = PART
}
line = strings.TrimSuffix(line, ",")
noConstraint = append(noConstraint, line)
}
// 去除外键语句会使DDL中多一个','导致语法错误,要把多余的逗号去除
ddl = fmt.Sprint(
lines[0], "\n",
strings.Join(noConstraint, ",\n"), "\n",
lines[len(lines)-1],
)
// len(lines) > 2的判断方式有问题,如果是分区表也会判断成为外键语句,导致建表语句的逗号错乱
if DeleteComaT == CS {
ddl = fmt.Sprint(
lines[0], "\n",
strings.Join(noConstraint, ",\n"), "\n",
lines[len(lines)-1],
)
} else if DeleteComaT == PART {
ddl = fmt.Sprint(
lines[0], "\n",
strings.Join(noConstraint, ",\n"), "\n",
lines[len(lines)-3],
)
}
}
return ddl, err
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册