Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Xiaomi
soar
提交
5c36e33c
S
soar
项目概览
Xiaomi
/
soar
大约 2 年 前同步成功
通知
467
Star
8513
Fork
1329
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
S
soar
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
5c36e33c
编写于
8月 18, 2020
作者:
L
LonelyChick
提交者:
GitHub
8月 18, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #262 from LonelyChick/dev
COL.014 modify the judgment about the character set;COL.012/COL.015 a…
上级
68f4730f
1b2c6850
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
78 addition
and
20 deletion
+78
-20
advisor/heuristic.go
advisor/heuristic.go
+35
-9
advisor/heuristic_test.go
advisor/heuristic_test.go
+7
-0
advisor/rules.go
advisor/rules.go
+4
-4
advisor/testdata/TestListHeuristicRules.golden
advisor/testdata/TestListHeuristicRules.golden
+2
-2
database/show.go
database/show.go
+30
-5
未找到文件。
advisor/heuristic.go
浏览文件 @
5c36e33c
...
...
@@ -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
}
...
...
@@ -2677,8 +2677,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
}
}
}
}
...
...
@@ -2755,7 +2761,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"
]
...
...
@@ -2778,7 +2784,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"
]
...
...
@@ -3105,7 +3111,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
}
...
...
@@ -3121,6 +3128,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
}
...
...
@@ -3135,6 +3152,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
}
...
...
@@ -3339,7 +3365,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"
]
...
...
@@ -3358,7 +3384,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"
]
...
...
advisor/heuristic_test.go
浏览文件 @
5c36e33c
...
...
@@ -3258,17 +3258,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;"
,
},
}
...
...
advisor/rules.go
浏览文件 @
5c36e33c
...
...
@@ -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
,
},
...
...
advisor/testdata/TestListHeuristicRules.golden
浏览文件 @
5c36e33c
...
...
@@ -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
...
...
database/show.go
浏览文件 @
5c36e33c
...
...
@@ -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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录