未验证 提交 86afd238 编写于 作者: martianzhang's avatar martianzhang 提交者: GitHub

polish code before lunar new year (#193)

* add test case  and notes

* vendor update

* use `tput setaf/srg0` set color in Makefile

* fix loadExternalResource fail cause panic
上级 b1860bb1
...@@ -18,13 +18,10 @@ BUILD_TIME=`date +%Y%m%d%H%M` ...@@ -18,13 +18,10 @@ BUILD_TIME=`date +%Y%m%d%H%M`
COMMIT_VERSION=`git rev-parse HEAD` COMMIT_VERSION=`git rev-parse HEAD`
# colors compatible setting # colors compatible setting
COLOR_ENABLE=$(shell tput colors > /dev/null; echo $$?) CRED:=$(shell tput setaf 1 2>/dev/null)
ifeq "$(COLOR_ENABLE)" "0" CGREEN:=$(shell tput setaf 2 2>/dev/null)
CRED=$(shell printf "\033[91m") CYELLOW:=$(shell tput setaf 3 2>/dev/null)
CGREEN=$(shell printf "\033[92m") CEND:=$(shell tput sgr0 2>/dev/null)
CYELLOW=$(shell printf "\033[93m")
CEND=$(shell printf "\033[0m")
endif
# Add mysql version for testing `MYSQL_RELEASE=percona MYSQL_VERSION=5.7 make docker` # Add mysql version for testing `MYSQL_RELEASE=percona MYSQL_VERSION=5.7 make docker`
# MySQL 5.1 `MYSQL_RELEASE=vsamov/mysql-5.1.73 make docker` # MySQL 5.1 `MYSQL_RELEASE=vsamov/mysql-5.1.73 make docker`
...@@ -161,8 +158,6 @@ pingcap-parser: tidb ...@@ -161,8 +158,6 @@ pingcap-parser: tidb
.PHONY: vendor .PHONY: vendor
vendor: vitess pingcap-parser vendor: vitess pingcap-parser
# gometalinter # gometalinter
# 如果有不想改的lint问题可以使用metalinter.sh加黑名单
#@bash doc/example/metalinter.sh
.PHONY: lint .PHONY: lint
lint: build lint: build
@echo "$(CGREEN)Run linter check ...$(CEND)" @echo "$(CGREEN)Run linter check ...$(CEND)"
......
...@@ -44,41 +44,38 @@ func MarkdownEscape(str string) string { ...@@ -44,41 +44,38 @@ func MarkdownEscape(str string) string {
return str return str
} }
// // loadExternalResource load js/css resource from http[s] url
func loadExternalResource(resource string) string { func loadExternalResource(resource string) string {
var content string var content string
var body []byte var body []byte
if strings.HasPrefix(resource, "http") { if strings.HasPrefix(resource, "http") {
resp, err := http.Get(resource) resp, err := http.Get(resource)
if err == nil { if err != nil {
body, err = ioutil.ReadAll(resp.Body) Log.Error("http.Get %s Error: %v", resource, err)
if err == nil { return content
content = string(body)
} else {
Log.Debug("ioutil.ReadAll %s Error: %v", resource, err)
} }
defer resp.Body.Close()
body, err = ioutil.ReadAll(resp.Body)
if err != nil {
Log.Error("ioutil.ReadAll %s Error: %v", resource, err)
} else { } else {
Log.Debug("http.Get %s Error: %v", resource, err) content = string(body)
} }
defer resp.Body.Close()
} else { } else {
fd, err := os.Open(resource) fd, err := os.Open(resource)
defer func() {
err = fd.Close()
if err != nil { if err != nil {
Log.Error("loadExternalResource(%s) fd.Close failed: %s", resource, err.Error()) Log.Error("os.Open %s Error: %v", resource, err)
return content
} }
}() defer fd.Close()
if err == nil {
body, err = ioutil.ReadAll(fd) body, err = ioutil.ReadAll(fd)
if err != nil { if err != nil {
Log.Debug("ioutil.ReadAll %s Error: %v", resource, err) Log.Error("ioutil.ReadAll %s Error: %v", resource, err)
} else { } else {
content = string(body) content = string(body)
} }
} else {
Log.Debug("os.Open %s Error: %v", resource, err)
}
} }
return content return content
} }
......
...@@ -27,8 +27,8 @@ allow-online-as-test: true ...@@ -27,8 +27,8 @@ allow-online-as-test: true
drop-test-temporary: true drop-test-temporary: true
# 语法检查小工具 # 语法检查小工具
only-syntax-check: false only-syntax-check: false
sampling-data-factor: 100 sampling-statistic-target: 100
sampling: true sampling: false
# 日志级别,[0:Emergency, 1:Alert, 2:Critical, 3:Error, 4:Warning, 5:Notice, 6:Informational, 7:Debug] # 日志级别,[0:Emergency, 1:Alert, 2:Critical, 3:Error, 4:Warning, 5:Notice, 6:Informational, 7:Debug]
log-level: 7 log-level: 7
log-output: ${your_log_dir}/soar.log log-output: ${your_log_dir}/soar.log
...@@ -78,6 +78,10 @@ soar -h ...@@ -78,6 +78,10 @@ soar -h
### 命令行参数配置DSN ### 命令行参数配置DSN
SOAR 最新版本已经使用`go-sql-driver`替代了`mymysql`,DSN将使用`go-sql-driver`格式并且保持向前兼容,请参考[go-sql-driver](https://github.com/go-sql-driver/mysql#dsn-data-source-name)文档。
**以下DSN格式不再推荐使用**
> 账号密码中如包含特殊符号(如:'@',':','/'等)可在配置文件中设置,存在特殊字符的情况不适合在命令行中使用。目前`soar`只支持 tcp 协议的 MySQL 数据库连接方式,如需要配置本机MySQL环境建议将`localhost`修改为'127.0.0.1',并检查对应的 'user'@'127.0.0.1' 账号是否存在。 > 账号密码中如包含特殊符号(如:'@',':','/'等)可在配置文件中设置,存在特殊字符的情况不适合在命令行中使用。目前`soar`只支持 tcp 协议的 MySQL 数据库连接方式,如需要配置本机MySQL环境建议将`localhost`修改为'127.0.0.1',并检查对应的 'user'@'127.0.0.1' 账号是否存在。
```bash ```bash
......
...@@ -99,9 +99,9 @@ func BuildEnv() (*VirtualEnv, *database.Connector) { ...@@ -99,9 +99,9 @@ func BuildEnv() (*VirtualEnv, *database.Connector) {
common.Config.OnlineDSN.Disable = true common.Config.OnlineDSN.Disable = true
} }
// 判断测试环境与remote环境版本是否一致 // 判断测试环境与线上环境版本是否一致,要求测试环境版本不低于线上环境
if vEnvVersion < rEnvVersion { if vEnvVersion < rEnvVersion {
common.Log.Warning("TestDSN MySQL version older than OnlineDSN(%d), TestDSN(%d) will not be used", vEnvVersion, rEnvVersion) common.Log.Warning("TestDSN MySQL version older than OnlineDSN(%d), TestDSN(%d) will not be used", rEnvVersion, vEnvVersion)
common.Config.TestDSN.Disable = true common.Config.TestDSN.Disable = true
} }
......
# Query: C3FAEDA6AD6D762B
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH = 86
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: E969B9297DA79BA6
★ ★ ★ ★ ☆ 90分
```sql
SELECT
*
FROM
film
WHERE
LENGTH IS NULL
```
## 应尽量避免在 WHERE 子句中对字段进行 NULL 值判断
* **Item:** ARG.006
* **Severity:** L1
* **Content:** 使用 IS NULL 或 IS NOT NULL 将可能导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null;可以在num上设置默认值0,确保表中 num 列没有 NULL 值,然后这样查询: select id from t where num=0;
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 8A106444D14B9880
★ ★ ★ ☆ ☆ 60分
```sql
SELECT
*
FROM
film
HAVING
title = 'abc'
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 不建议使用 HAVING 子句
* **Item:** CLA.013
* **Severity:** L3
* **Content:** 将查询的 HAVING 子句改写为 WHERE 中的查询条件,可以在查询处理期间使用索引。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: A0C5E62C724A121A
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
sakila. film
WHERE
LENGTH >= 60
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 868317D1973FD1B0
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH BETWEEN 60
AND 84
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 707FE669669FA075
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
title LIKE 'AIR%'
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: DF916439ABD07664
★ ★ ★ ★ ☆ 90分
```sql
SELECT
*
FROM
film
WHERE
title IS NOT NULL
```
## 应尽量避免在 WHERE 子句中对字段进行 NULL 值判断
* **Item:** ARG.006
* **Severity:** L1
* **Content:** 使用 IS NULL 或 IS NOT NULL 将可能导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null;可以在num上设置默认值0,确保表中 num 列没有 NULL 值,然后这样查询: select id from t where num=0;
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: B9336971FF3D3792
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH = 114
AND title = 'ALABAMA DEVIL'
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 68E48001ECD53152
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH > 100
AND title = 'ALABAMA DEVIL'
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 12FF1DAA3D425FA9
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH > 100
AND language_id < 10
AND title = 'xyz'
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: E84CBAAC2E12BDEA
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH > 100
AND language_id < 10
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 6A0F035BD4E01018
★ ★ ★ ★ ☆ 85分
```sql
SELECT
release_year, SUM( LENGTH)
FROM
film
WHERE
LENGTH = 123
AND language_id = 1
GROUP BY
release_year
```
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item:** CLA.008
* **Severity:** L2
* **Content:** 默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。
## 使用 SUM(COL) 时需注意 NPE 问题
* **Item:** FUN.006
* **Severity:** L1
* **Content:** 当某一列的值全是 NULL 时,COUNT(COL) 的返回结果为0,但 SUM(COL) 的返回结果为 NULL,因此使用 SUM() 时需注意 NPE 问题。可以使用如下方式来避免 SUM 的 NPE 问题: SELECT IF(ISNULL(SUM(COL)), 0, SUM(COL)) FROM tbl
# Query: 23D176AEA2947002
★ ★ ★ ★ ☆ 85分
```sql
SELECT
release_year, SUM( LENGTH)
FROM
film
WHERE
LENGTH >= 123
GROUP BY
release_year
```
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item:** CLA.008
* **Severity:** L2
* **Content:** 默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。
## 使用 SUM(COL) 时需注意 NPE 问题
* **Item:** FUN.006
* **Severity:** L1
* **Content:** 当某一列的值全是 NULL 时,COUNT(COL) 的返回结果为0,但 SUM(COL) 的返回结果为 NULL,因此使用 SUM() 时需注意 NPE 问题。可以使用如下方式来避免 SUM 的 NPE 问题: SELECT IF(ISNULL(SUM(COL)), 0, SUM(COL)) FROM tbl
# Query: 73DDF6E6D9E40384
★ ★ ★ ☆ ☆ 65分
```sql
SELECT
release_year, language_id, SUM( LENGTH)
FROM
film
GROUP BY
release_year, language_id
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item:** CLA.008
* **Severity:** L2
* **Content:** 默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。
## 使用 SUM(COL) 时需注意 NPE 问题
* **Item:** FUN.006
* **Severity:** L1
* **Content:** 当某一列的值全是 NULL 时,COUNT(COL) 的返回结果为0,但 SUM(COL) 的返回结果为 NULL,因此使用 SUM() 时需注意 NPE 问题。可以使用如下方式来避免 SUM 的 NPE 问题: SELECT IF(ISNULL(SUM(COL)), 0, SUM(COL)) FROM tbl
# Query: B3C502B4AA344196
★ ★ ★ ☆ ☆ 75分
```sql
SELECT
release_year, SUM( LENGTH)
FROM
film
WHERE
LENGTH = 123
GROUP BY
release_year, (LENGTH+ language_id)
```
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item:** CLA.008
* **Severity:** L2
* **Content:** 默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。
## GROUP BY 的条件为表达式
* **Item:** CLA.010
* **Severity:** L2
* **Content:** 当 GROUP BY 条件为表达式或函数时会使用到临时表,如果在未指定 WHERE 或 WHERE 条件返回的结果集较大时性能会很差。
## 使用 SUM(COL) 时需注意 NPE 问题
* **Item:** FUN.006
* **Severity:** L1
* **Content:** 当某一列的值全是 NULL 时,COUNT(COL) 的返回结果为0,但 SUM(COL) 的返回结果为 NULL,因此使用 SUM() 时需注意 NPE 问题。可以使用如下方式来避免 SUM 的 NPE 问题: SELECT IF(ISNULL(SUM(COL)), 0, SUM(COL)) FROM tbl
# Query: 47044E1FE1A965A5
★ ★ ★ ☆ ☆ 70分
```sql
SELECT
release_year, SUM( film_id)
FROM
film
GROUP BY
release_year
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item:** CLA.008
* **Severity:** L2
* **Content:** 默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。
# Query: 2BA1217F6C8CF0AB
★ ★ ☆ ☆ ☆ 45分
```sql
SELECT
*
FROM
address
GROUP BY
address, district
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item:** CLA.008
* **Severity:** L2
* **Content:** 默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
## 非确定性的 GROUP BY
* **Item:** RES.001
* **Severity:** L4
* **Content:** SQL返回的列既不在聚合函数中也不是 GROUP BY 表达式的列中,因此这些值的结果将是非确定性的。如:select a, b, c from tbl where foo="bar" group by a,该 SQL 返回的结果就是不确定的。
# Query: 863A85207E4F410D
★ ★ ★ ★ ☆ 80分
```sql
SELECT
title
FROM
film
WHERE
ABS( language_id) = 3
GROUP BY
title
```
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item:** CLA.008
* **Severity:** L2
* **Content:** 默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。
## 避免在 WHERE 条件中使用函数或其他运算符
* **Item:** FUN.001
* **Severity:** L2
* **Content:** 虽然在 SQL 中使用函数可以简化很多复杂的查询,但使用了函数的查询无法利用表中已经建立的索引,该查询将会是全表扫描,性能较差。通常建议将列名写在比较运算符左侧,将查询过滤条件放在比较运算符右侧。也不建议在查询比较条件两侧书写多余的括号,这会对阅读产生比较大的困扰。
# Query: DF59FD602E4AA368
★ ★ ★ ★ ☆ 80分
```sql
SELECT
language_id
FROM
film
WHERE
LENGTH = 123
GROUP BY
release_year
ORDER BY
language_id
```
## 非确定性的 GROUP BY
* **Item:** RES.001
* **Severity:** L4
* **Content:** SQL返回的列既不在聚合函数中也不是 GROUP BY 表达式的列中,因此这些值的结果将是非确定性的。如:select a, b, c from tbl where foo="bar" group by a,该 SQL 返回的结果就是不确定的。
# Query: F6DBEAA606D800FC
★ ★ ★ ★ ★ 100分
```sql
SELECT
release_year
FROM
film
WHERE
LENGTH = 123
GROUP BY
release_year
ORDER BY
release_year
```
## OK
# Query: 6E9B96CA3F0E6BDA
★ ★ ★ ☆ ☆ 65分
```sql
SELECT
*
FROM
film
WHERE
LENGTH = 123
ORDER BY
release_year ASC, language_id DESC
```
## ORDER BY 语句对多个不同条件使用不同方向的排序无法使用索引
* **Item:** CLA.007
* **Severity:** L2
* **Content:** ORDER BY 子句中的所有表达式必须按统一的 ASC 或 DESC 方向排序,以便利用索引。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
## ORDER BY 多个列但排序方向不同时可能无法使用索引
* **Item:** KEY.008
* **Severity:** L4
* **Content:** 在 MySQL 8.0之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。
# Query: 2EAACFD7030EA528
★ ★ ★ ★ ★ 100分
```sql
SELECT
release_year
FROM
film
WHERE
LENGTH = 123
GROUP BY
release_year
ORDER BY
release_year
LIMIT
10
```
## OK
# Query: 5CE2F187DBF2A710
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH = 123
ORDER BY
release_year
LIMIT
10
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: E75234155B5E2E14
★ ★ ★ ☆ ☆ 75分
```sql
SELECT
*
FROM
film
ORDER BY
release_year
LIMIT
10
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: AFEEBF10A8D74E32
★ ★ ★ ★ ☆ 80分
```sql
SELECT
film_id
FROM
film
ORDER BY
release_year
LIMIT
10
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
# Query: 965D5AC955824512
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH > 100
ORDER BY
LENGTH
LIMIT
10
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 1E2CF4145EE706A5
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH < 100
ORDER BY
LENGTH
LIMIT
10
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: A314542EEE8571EE
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
customer
WHERE
address_id in (224, 510)
ORDER BY
last_name
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 0BE2D79E2F1E7CB0
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
release_year = 2016
AND LENGTH != 1
ORDER BY
title
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
## '!=' 运算符是非标准的
* **Item:** STA.001
* **Severity:** L0
* **Content:** "<>"才是标准SQL中的不等于运算符。
# Query: 4E73AA068370E6A8
★ ★ ★ ★ ★ 100分
```sql
SELECT
title
FROM
film
WHERE
release_year = 1995
```
## OK
# Query: BA7111449E4F1122
★ ★ ★ ★ ★ 100分
```sql
SELECT
title, replacement_cost
FROM
film
WHERE
language_id = 5
AND LENGTH = 70
```
## OK
# Query: B13E0ACEAF8F3119
★ ★ ★ ★ ★ 100分
```sql
SELECT
title
FROM
film
WHERE
language_id > 5
AND LENGTH > 70
```
## OK
# Query: A3FAB6027484B88B
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH = 100
AND title = 'xyz'
ORDER BY
release_year
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: CB42080E9F35AB07
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH > 100
AND title = 'xyz'
ORDER BY
release_year
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: C4A212A42400411D
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH > 100
ORDER BY
release_year
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 4ECCA9568BE69E68
★ ★ ★ ☆ ☆ 75分
```sql
SELECT
*
FROM
city a
INNER JOIN country b ON a. country_id= b. country_id
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 485D56FC88BBBDB9
★ ★ ★ ☆ ☆ 75分
```sql
SELECT
*
FROM
city a
LEFT JOIN country b ON a. country_id= b. country_id
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 0D0DABACEDFF5765
★ ★ ★ ☆ ☆ 75分
```sql
SELECT
*
FROM
city a
RIGHT JOIN country b ON a. country_id= b. country_id
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 1E56C6CCEA2131CC
★ ★ ★ ★ ☆ 90分
```sql
SELECT
*
FROM
city a
LEFT JOIN country b ON a. country_id= b. country_id
WHERE
b. last_update IS NULL
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 应尽量避免在 WHERE 子句中对字段进行 NULL 值判断
* **Item:** ARG.006
* **Severity:** L1
* **Content:** 使用 IS NULL 或 IS NOT NULL 将可能导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null;可以在num上设置默认值0,确保表中 num 列没有 NULL 值,然后这样查询: select id from t where num=0;
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: F5D30BCAC1E206A1
★ ★ ★ ★ ☆ 90分
```sql
SELECT
*
FROM
city a
RIGHT JOIN country b ON a. country_id= b. country_id
WHERE
a. last_update IS NULL
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 应尽量避免在 WHERE 子句中对字段进行 NULL 值判断
* **Item:** ARG.006
* **Severity:** L1
* **Content:** 使用 IS NULL 或 IS NOT NULL 将可能导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null;可以在num上设置默认值0,确保表中 num 列没有 NULL 值,然后这样查询: select id from t where num=0;
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 17D5BCF21DC2364C
★ ★ ★ ☆ ☆ 65分
```sql
SELECT
*
FROM
city a
LEFT JOIN country b ON a. country_id= b. country_id
UNION
SELECT
*
FROM
city a
RIGHT JOIN country b ON a. country_id= b. country_id
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
## 如果您不在乎重复的话,建议使用 UNION ALL 替代 UNION
* **Item:** SUB.002
* **Severity:** L2
* **Content:** 与去除重复的UNION不同,UNION ALL允许重复元组。如果您不关心重复元组,那么使用UNION ALL将是一个更快的选项。
# Query: A4911095C201896F
★ ★ ★ ★ ☆ 85分
```sql
SELECT
*
FROM
city a
RIGHT JOIN country b ON a. country_id= b. country_id
WHERE
a. last_update IS NULL
UNION
SELECT
*
FROM
city a
LEFT JOIN country b ON a. country_id= b. country_id
WHERE
b. last_update IS NULL
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
## 如果您不在乎重复的话,建议使用 UNION ALL 替代 UNION
* **Item:** SUB.002
* **Severity:** L2
* **Content:** 与去除重复的UNION不同,UNION ALL允许重复元组。如果您不关心重复元组,那么使用UNION ALL将是一个更快的选项。
# Query: 3FF20E28EC9CBEF9
★ ★ ★ ★ ☆ 80分
```sql
SELECT
country_id, last_update
FROM
city NATURAL
JOIN country
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
# Query: 5C547F08EADBB131
★ ★ ★ ★ ☆ 80分
```sql
SELECT
country_id, last_update
FROM
city NATURAL
LEFT JOIN country
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
# Query: AF0C1EB58B23D2FA
★ ★ ★ ★ ☆ 80分
```sql
SELECT
country_id, last_update
FROM
city NATURAL
RIGHT JOIN country
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
# Query: 626571EAE84E2C8A
★ ★ ★ ★ ☆ 80分
```sql
SELECT
a. country_id, a. last_update
FROM
city a STRAIGHT_JOIN country b ON a. country_id= b. country_id
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
# Query: 50F2AB4243CE2071
★ ★ ★ ☆ ☆ 60分
```sql
SELECT
a. address, a. postal_code
FROM
sakila. address a
WHERE
a. city_id IN (
SELECT
c. city_id
FROM
sakila. city c)
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## MySQL 对子查询的优化效果不佳
* **Item:** SUB.001
* **Severity:** L4
* **Content:** MySQL 将外部查询中的每一行作为依赖子查询执行子查询。 这是导致严重性能问题的常见原因。这可能会在 MySQL 5.6 版本中得到改善, 但对于5.1及更早版本, 建议将该类查询分别重写为 JOIN 或 LEFT OUTER JOIN。
# Query: 584CCEC8069B6947
★ ★ ☆ ☆ ☆ 40分
```sql
SELECT
city
FROM(
SELECT
city_id
FROM
city
WHERE
city = "A Corua (La Corua)"
ORDER BY
last_update DESC
LIMIT
50, 10) I
JOIN city ON (I. city_id = city. city_id)
JOIN country ON (country. country_id = city. country_id)
ORDER BY
city DESC
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 同一张表被连接两次
* **Item:** JOI.002
* **Severity:** L4
* **Content:** 相同的表在 FROM 子句中至少出现两次,可以简化为对该表的单次访问。
## MySQL 对子查询的优化效果不佳
* **Item:** SUB.001
* **Severity:** L4
* **Content:** MySQL 将外部查询中的每一行作为依赖子查询执行子查询。 这是导致严重性能问题的常见原因。这可能会在 MySQL 5.6 版本中得到改善, 但对于5.1及更早版本, 建议将该类查询分别重写为 JOIN 或 LEFT OUTER JOIN。
# Query: 7F02E23D44A38A6D
★ ★ ★ ★ ☆ 80分
```sql
DELETE city, country
FROM
city
INNER JOIN country using (country_id)
WHERE
city. city_id = 1
```
## 不建议使用联表删除或更新
* **Item:** JOI.007
* **Severity:** L4
* **Content:** 当需要同时删除或更新多张表时建议使用简单语句,一条 SQL 只删除或更新一张表,尽量不要将多张表的操作在同一条语句。
## 使用DELETE/DROP/TRUNCATE等操作时注意备份
* **Item:** SEC.003
* **Severity:** L0
* **Content:** 在执行高危操作之前对数据进行备份是十分有必要的。
# Query: F8314ABD1CBF2FF1
★ ★ ★ ★ ☆ 80分
```sql
DELETE city
FROM
city
LEFT JOIN country ON city. country_id = country. country_id
WHERE
country. country IS NULL
```
## 不建议使用联表删除或更新
* **Item:** JOI.007
* **Severity:** L4
* **Content:** 当需要同时删除或更新多张表时建议使用简单语句,一条 SQL 只删除或更新一张表,尽量不要将多张表的操作在同一条语句。
## 使用DELETE/DROP/TRUNCATE等操作时注意备份
* **Item:** SEC.003
* **Severity:** L0
* **Content:** 在执行高危操作之前对数据进行备份是十分有必要的。
# Query: 1A53649C43122975
★ ★ ★ ★ ☆ 80分
```sql
DELETE a1, a2
FROM
city AS a1
INNER JOIN country AS a2
WHERE
a1. country_id= a2. country_id
```
## 不建议使用联表删除或更新
* **Item:** JOI.007
* **Severity:** L4
* **Content:** 当需要同时删除或更新多张表时建议使用简单语句,一条 SQL 只删除或更新一张表,尽量不要将多张表的操作在同一条语句。
## 使用DELETE/DROP/TRUNCATE等操作时注意备份
* **Item:** SEC.003
* **Severity:** L0
* **Content:** 在执行高危操作之前对数据进行备份是十分有必要的。
# Query: B862978586C6338B
★ ★ ★ ★ ☆ 80分
```sql
DELETE FROM
a1, a2 USING city AS a1
INNER JOIN country AS a2
WHERE
a1. country_id= a2. country_id
```
## 不建议使用联表删除或更新
* **Item:** JOI.007
* **Severity:** L4
* **Content:** 当需要同时删除或更新多张表时建议使用简单语句,一条 SQL 只删除或更新一张表,尽量不要将多张表的操作在同一条语句。
## 使用DELETE/DROP/TRUNCATE等操作时注意备份
* **Item:** SEC.003
* **Severity:** L0
* **Content:** 在执行高危操作之前对数据进行备份是十分有必要的。
# Query: F16FD63381EF8299
★ ★ ★ ★ ★ 100分
```sql
DELETE FROM
film
WHERE
LENGTH > 100
```
## 使用DELETE/DROP/TRUNCATE等操作时注意备份
* **Item:** SEC.003
* **Severity:** L0
* **Content:** 在执行高危操作之前对数据进行备份是十分有必要的。
# Query: 08CFE41C7D20AAC8
★ ★ ★ ★ ☆ 80分
```sql
UPDATE
city
INNER JOIN country USING( country_id)
SET
city. city = 'Abha',
city. last_update = '2006-02-15 04:45:25',
country. country = 'Afghanistan'
WHERE
city. city_id= 10
```
## 不建议使用联表删除或更新
* **Item:** JOI.007
* **Severity:** L4
* **Content:** 当需要同时删除或更新多张表时建议使用简单语句,一条 SQL 只删除或更新一张表,尽量不要将多张表的操作在同一条语句。
# Query: C15BDF2C73B5B7ED
★ ★ ★ ★ ☆ 80分
```sql
UPDATE
city
INNER JOIN country ON city. country_id = country. country_id
INNER JOIN address ON city. city_id = address. city_id
SET
city. city = 'Abha',
city. last_update = '2006-02-15 04:45:25',
country. country = 'Afghanistan'
WHERE
city. city_id= 10
```
## 不建议使用联表删除或更新
* **Item:** JOI.007
* **Severity:** L4
* **Content:** 当需要同时删除或更新多张表时建议使用简单语句,一条 SQL 只删除或更新一张表,尽量不要将多张表的操作在同一条语句。
# Query: FCD1ABF36F8CDAD7
★ ★ ★ ★ ★ 100分
```sql
UPDATE
city, country
SET
city. city = 'Abha',
city. last_update = '2006-02-15 04:45:25',
country. country = 'Afghanistan'
WHERE
city. country_id = country. country_id
AND city. city_id= 10
```
## OK
# Query: FE409EB794EE91CF
★ ★ ★ ★ ★ 100分
```sql
UPDATE
film
SET
LENGTH = 10
WHERE
language_id = 20
```
## OK
# Query: 3656B13CC4F888E2
★ ★ ★ ☆ ☆ 65分
```sql
INSERT INTO city (country_id)
SELECT
country_id
FROM
country
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## INSERT INTO xx SELECT 加锁粒度较大请谨慎
* **Item:** LCK.001
* **Severity:** L3
* **Content:** INSERT INTO xx SELECT 加锁粒度较大请谨慎
# Query: 2F7439623B712317
★ ★ ★ ★ ★ 100分
```sql
INSERT INTO city (country_id)
VALUES
(1),
(2),
(3)
```
## OK
# Query: 11EC7AAACC97DC0F
★ ★ ★ ★ ☆ 85分
```sql
INSERT INTO city (country_id)
SELECT
10
FROM
DUAL
```
## INSERT INTO xx SELECT 加锁粒度较大请谨慎
* **Item:** LCK.001
* **Severity:** L3
* **Content:** INSERT INTO xx SELECT 加锁粒度较大请谨慎
# Query: E3DDA1A929236E72
★ ★ ★ ☆ ☆ 65分
```sql
REPLACE INTO city (country_id)
SELECT
country_id
FROM
country
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## INSERT INTO xx SELECT 加锁粒度较大请谨慎
* **Item:** LCK.001
* **Severity:** L3
* **Content:** INSERT INTO xx SELECT 加锁粒度较大请谨慎
# Query: 466F1AC2F5851149
★ ★ ★ ★ ★ 100分
```sql
REPLACE INTO city (country_id)
VALUES
(1),
(2),
(3)
```
## OK
# Query: A7973BDD268F926E
★ ★ ★ ★ ☆ 85分
```sql
REPLACE INTO city (country_id)
SELECT
10
FROM
DUAL
```
## INSERT INTO xx SELECT 加锁粒度较大请谨慎
* **Item:** LCK.001
* **Severity:** L3
* **Content:** INSERT INTO xx SELECT 加锁粒度较大请谨慎
# Query: 105C870D5DFB6710
★ ★ ★ ☆ ☆ 65分
```sql
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
film
) film
) film
) film
) film
) film
) film
) film
) film
) film
) film
) film
) film
) film
) film
) film
) film
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 执行计划中嵌套连接深度过深
* **Item:** SUB.004
* **Severity:** L3
* **Content:** MySQL对子查询的优化效果不佳,MySQL将外部查询中的每一行作为依赖子查询执行子查询。 这是导致严重性能问题的常见原因。
# Query: 16C2B14E7DAA9906
★ ☆ ☆ ☆ ☆ 35分
```sql
SELECT
*
FROM
film
WHERE
language_id = (
SELECT
language_id
FROM
language
LIMIT
1)
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
## 未使用 ORDER BY 的 LIMIT 查询
* **Item:** RES.002
* **Severity:** L4
* **Content:** 没有 ORDER BY 的 LIMIT 会导致非确定性的结果,这取决于查询执行计划。
## MySQL 对子查询的优化效果不佳
* **Item:** SUB.001
* **Severity:** L4
* **Content:** MySQL 将外部查询中的每一行作为依赖子查询执行子查询。 这是导致严重性能问题的常见原因。这可能会在 MySQL 5.6 版本中得到改善, 但对于5.1及更早版本, 建议将该类查询分别重写为 JOIN 或 LEFT OUTER JOIN。
# Query: 16CB4628D2597D40
★ ★ ★ ☆ ☆ 65分
```sql
SELECT
*
FROM
city i
LEFT JOIN country o ON i. city_id= o. country_id
UNION
SELECT
*
FROM
city i
RIGHT JOIN country o ON i. city_id= o. country_id
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
## 如果您不在乎重复的话,建议使用 UNION ALL 替代 UNION
* **Item:** SUB.002
* **Severity:** L2
* **Content:** 与去除重复的UNION不同,UNION ALL允许重复元组。如果您不关心重复元组,那么使用UNION ALL将是一个更快的选项。
# Query: EA50643B01E139A8
★ ★ ☆ ☆ ☆ 45分
```sql
SELECT
*
FROM
(
SELECT
*
FROM
actor
WHERE
last_update= '2006-02-15 04:34:33'
AND last_name= 'CHASE'
) t
WHERE
last_update= '2006-02-15 04:34:33'
AND last_name= 'CHASE'
GROUP BY
first_name
```
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item:** CLA.008
* **Severity:** L2
* **Content:** 默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
## 非确定性的 GROUP BY
* **Item:** RES.001
* **Severity:** L4
* **Content:** SQL返回的列既不在聚合函数中也不是 GROUP BY 表达式的列中,因此这些值的结果将是非确定性的。如:select a, b, c from tbl where foo="bar" group by a,该 SQL 返回的结果就是不确定的。
## MySQL 对子查询的优化效果不佳
* **Item:** SUB.001
* **Severity:** L4
* **Content:** MySQL 将外部查询中的每一行作为依赖子查询执行子查询。 这是导致严重性能问题的常见原因。这可能会在 MySQL 5.6 版本中得到改善, 但对于5.1及更早版本, 建议将该类查询分别重写为 JOIN 或 LEFT OUTER JOIN。
# Query: 7598A4EDE6CFA6BE
★ ★ ★ ★ ☆ 85分
```sql
SELECT
*
FROM
city i
LEFT JOIN country o ON i. city_id= o. country_id
WHERE
o. country_id is null
UNION
SELECT
*
FROM
city i
RIGHT JOIN country o ON i. city_id= o. country_id
WHERE
i. city_id is null
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
## 如果您不在乎重复的话,建议使用 UNION ALL 替代 UNION
* **Item:** SUB.002
* **Severity:** L2
* **Content:** 与去除重复的UNION不同,UNION ALL允许重复元组。如果您不关心重复元组,那么使用UNION ALL将是一个更快的选项。
# Query: 1E8B70E30062FD13
★ ★ ★ ★ ☆ 80分
```sql
SELECT
first_name, last_name, email
FROM
customer STRAIGHT_JOIN address ON customer. address_id= address. address_id
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
# Query: E48A20D0413512DA
★ ☆ ☆ ☆ ☆ 30分
```sql
SELECT
ID, name
FROM
(
SELECT
address
FROM
customer_list
WHERE
SID= 1
ORDER BY
phone
LIMIT
50, 10) a
JOIN customer_list l ON (a. address= l. address)
JOIN city c ON (c. city= l. city)
ORDER BY
phone desc
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## ORDER BY 语句对多个不同条件使用不同方向的排序无法使用索引
* **Item:** CLA.007
* **Severity:** L2
* **Content:** ORDER BY 子句中的所有表达式必须按统一的 ASC 或 DESC 方向排序,以便利用索引。
## 同一张表被连接两次
* **Item:** JOI.002
* **Severity:** L4
* **Content:** 相同的表在 FROM 子句中至少出现两次,可以简化为对该表的单次访问。
## MySQL 对子查询的优化效果不佳
* **Item:** SUB.001
* **Severity:** L4
* **Content:** MySQL 将外部查询中的每一行作为依赖子查询执行子查询。 这是导致严重性能问题的常见原因。这可能会在 MySQL 5.6 版本中得到改善, 但对于5.1及更早版本, 建议将该类查询分别重写为 JOIN 或 LEFT OUTER JOIN。
# Query: B0BA5A7079EA16B3
★ ★ ★ ★ ☆ 85分
```sql
SELECT
*
FROM
film
WHERE
DATE( last_update) = '2006-02-15'
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
## 避免在 WHERE 条件中使用函数或其他运算符
* **Item:** FUN.001
* **Severity:** L2
* **Content:** 虽然在 SQL 中使用函数可以简化很多复杂的查询,但使用了函数的查询无法利用表中已经建立的索引,该查询将会是全表扫描,性能较差。通常建议将列名写在比较运算符左侧,将查询过滤条件放在比较运算符右侧。也不建议在查询比较条件两侧书写多余的括号,这会对阅读产生比较大的困扰。
# Query: 18A2AD1395A58EAE
★ ★ ★ ☆ ☆ 60分
```sql
SELECT
last_update
FROM
film
GROUP BY
DATE( last_update)
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item:** CLA.008
* **Severity:** L2
* **Content:** 默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。
## GROUP BY 的条件为表达式
* **Item:** CLA.010
* **Severity:** L2
* **Content:** 当 GROUP BY 条件为表达式或函数时会使用到临时表,如果在未指定 WHERE 或 WHERE 条件返回的结果集较大时性能会很差。
# Query: 60F234BA33AAC132
★ ★ ★ ☆ ☆ 70分
```sql
SELECT
last_update
FROM
film
ORDER BY
DATE( last_update)
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## ORDER BY 的条件为表达式
* **Item:** CLA.009
* **Severity:** L2
* **Content:** 当 ORDER BY 条件为表达式或函数时会使用到临时表,如果在未指定 WHERE 或 WHERE 条件返回的结果集较大时性能会很差。
# Query: 1ED2B7ECBA4215E1
★ ★ ★ ★ ☆ 90分
```sql
SELECT
description
FROM
film
WHERE
description IN( 'NEWS',
'asd'
)
GROUP BY
description
```
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item:** CLA.008
* **Severity:** L2
* **Content:** 默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。
# Query: 255BAC03F56CDBC7
★ ★ ★ ★ ★ 100分
```sql
ALTER TABLE
address
ADD
index idx_city_id( city_id)
```
## OK
# Query: C315BC4EE0F4E523
★ ★ ★ ★ ★ 100分
```sql
ALTER TABLE
inventory
ADD
index `idx_store_film` (
`store_id`, `film_id`)
```
## 提醒:请将索引属性顺序与查询对齐
* **Item:** KEY.004
* **Severity:** L0
* **Content:** 如果为列创建复合索引,请确保查询属性与索引属性的顺序相同,以便DBMS在处理查询时使用索引。如果查询和索引属性订单没有对齐,那么DBMS可能无法在查询处理期间使用索引。
# Query: 9BB74D074BA0727C
★ ★ ★ ★ ★ 100分
```sql
ALTER TABLE
inventory
ADD
index `idx_store_film` (
`store_id`, `film_id`),
ADD
index `idx_store_film` (
`store_id`, `film_id`),
ADD
index `idx_store_film` (
`store_id`, `film_id`)
```
## 提醒:请将索引属性顺序与查询对齐
* **Item:** KEY.004
* **Severity:** L0
* **Content:** 如果为列创建复合索引,请确保查询属性与索引属性的顺序相同,以便DBMS在处理查询时使用索引。如果查询和索引属性订单没有对齐,那么DBMS可能无法在查询处理期间使用索引。
# Query: C95B5C028C8FFF95
★ ★ ☆ ☆ ☆ 40分
```sql
SELECT
DATE_FORMAT( t. last_update, '%Y-%m-%d'
),
COUNT( DISTINCT (
t. city))
FROM
city t
WHERE
t. last_update > '2018-10-22 00:00:00'
AND t. city LIKE '%Chrome%'
AND t. city = 'eip'
GROUP BY
DATE_FORMAT( t. last_update, '%Y-%m-%d'
)
ORDER BY
DATE_FORMAT( t. last_update, '%Y-%m-%d'
)
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 不建议使用前项通配符查找
* **Item:** ARG.001
* **Severity:** L4
* **Content:** 例如 "%foo",查询参数有一个前项通配符的情况无法使用已有索引。
## ORDER BY 的条件为表达式
* **Item:** CLA.009
* **Severity:** L2
* **Content:** 当 ORDER BY 条件为表达式或函数时会使用到临时表,如果在未指定 WHERE 或 WHERE 条件返回的结果集较大时性能会很差。
## GROUP BY 的条件为表达式
* **Item:** CLA.010
* **Severity:** L2
* **Content:** 当 GROUP BY 条件为表达式或函数时会使用到临时表,如果在未指定 WHERE 或 WHERE 条件返回的结果集较大时性能会很差。
## ORDER BY 多个列但排序方向不同时可能无法使用索引
* **Item:** KEY.008
* **Severity:** L4
* **Content:** 在 MySQL 8.0之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。
# Query: C11ECE7AE5F80CE5
★ ★ ☆ ☆ ☆ 45分
```sql
create table hello. t (id int unsigned)
```
## 建议为表添加注释
* **Item:** CLA.011
* **Severity:** L1
* **Content:** 为表添加注释能够使得表的意义更明确,从而为日后的维护带来极大的便利。
## 请为列添加默认值
* **Item:** COL.004
* **Severity:** L1
* **Content:** 请为列添加默认值,如果是 ALTER 操作,请不要忘记将原字段的默认值写上。字段无默认值,当表较大时无法在线变更表结构。
## 列未添加注释
* **Item:** COL.005
* **Severity:** L1
* **Content:** 建议对表中每个列添加注释,来明确每个列在表中的含义及作用。
## 未指定主键或主键非 int 或 bigint
* **Item:** KEY.007
* **Severity:** L4
* **Content:** 未指定主键或主键非 int 或 bigint,建议将主键设置为 int unsigned 或 bigint unsigned。
## 请为表选择合适的存储引擎
* **Item:** TBL.002
* **Severity:** L4
* **Content:** 建表或修改表的存储引擎时建议使用推荐的存储引擎,如:innodb
# Query: 291F95B7DCB74C21
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
tb
WHERE
data >= ''
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 084DA3E3EE38DD85
★ ★ ★ ★ ★ 100分
```sql
ALTER TABLE
tb alter column id
DROP
DEFAULT
```
## OK
# Query: C3FAEDA6AD6D762B
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH = 86
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: E969B9297DA79BA6
★ ★ ★ ★ ☆ 90分
```sql
SELECT
*
FROM
film
WHERE
LENGTH IS NULL
```
## 应尽量避免在 WHERE 子句中对字段进行 NULL 值判断
* **Item:** ARG.006
* **Severity:** L1
* **Content:** 使用 IS NULL 或 IS NOT NULL 将可能导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null;可以在num上设置默认值0,确保表中 num 列没有 NULL 值,然后这样查询: select id from t where num=0;
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 8A106444D14B9880
★ ★ ★ ☆ ☆ 60分
```sql
SELECT
*
FROM
film
HAVING
title = 'abc'
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 不建议使用 HAVING 子句
* **Item:** CLA.013
* **Severity:** L3
* **Content:** 将查询的 HAVING 子句改写为 WHERE 中的查询条件,可以在查询处理期间使用索引。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: A0C5E62C724A121A
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
sakila. film
WHERE
LENGTH >= 60
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 868317D1973FD1B0
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH BETWEEN 60
AND 84
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 707FE669669FA075
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
title LIKE 'AIR%'
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: DF916439ABD07664
★ ★ ★ ★ ☆ 90分
```sql
SELECT
*
FROM
film
WHERE
title IS NOT NULL
```
## 应尽量避免在 WHERE 子句中对字段进行 NULL 值判断
* **Item:** ARG.006
* **Severity:** L1
* **Content:** 使用 IS NULL 或 IS NOT NULL 将可能导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null;可以在num上设置默认值0,确保表中 num 列没有 NULL 值,然后这样查询: select id from t where num=0;
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: B9336971FF3D3792
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH = 114
AND title = 'ALABAMA DEVIL'
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 68E48001ECD53152
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH > 100
AND title = 'ALABAMA DEVIL'
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 12FF1DAA3D425FA9
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH > 100
AND language_id < 10
AND title = 'xyz'
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: E84CBAAC2E12BDEA
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH > 100
AND language_id < 10
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 6A0F035BD4E01018
★ ★ ★ ★ ☆ 85分
```sql
SELECT
release_year, SUM( LENGTH)
FROM
film
WHERE
LENGTH = 123
AND language_id = 1
GROUP BY
release_year
```
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item:** CLA.008
* **Severity:** L2
* **Content:** 默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。
## 使用 SUM(COL) 时需注意 NPE 问题
* **Item:** FUN.006
* **Severity:** L1
* **Content:** 当某一列的值全是 NULL 时,COUNT(COL) 的返回结果为0,但 SUM(COL) 的返回结果为 NULL,因此使用 SUM() 时需注意 NPE 问题。可以使用如下方式来避免 SUM 的 NPE 问题: SELECT IF(ISNULL(SUM(COL)), 0, SUM(COL)) FROM tbl
# Query: 23D176AEA2947002
★ ★ ★ ★ ☆ 85分
```sql
SELECT
release_year, SUM( LENGTH)
FROM
film
WHERE
LENGTH >= 123
GROUP BY
release_year
```
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item:** CLA.008
* **Severity:** L2
* **Content:** 默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。
## 使用 SUM(COL) 时需注意 NPE 问题
* **Item:** FUN.006
* **Severity:** L1
* **Content:** 当某一列的值全是 NULL 时,COUNT(COL) 的返回结果为0,但 SUM(COL) 的返回结果为 NULL,因此使用 SUM() 时需注意 NPE 问题。可以使用如下方式来避免 SUM 的 NPE 问题: SELECT IF(ISNULL(SUM(COL)), 0, SUM(COL)) FROM tbl
# Query: 73DDF6E6D9E40384
★ ★ ★ ☆ ☆ 65分
```sql
SELECT
release_year, language_id, SUM( LENGTH)
FROM
film
GROUP BY
release_year, language_id
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item:** CLA.008
* **Severity:** L2
* **Content:** 默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。
## 使用 SUM(COL) 时需注意 NPE 问题
* **Item:** FUN.006
* **Severity:** L1
* **Content:** 当某一列的值全是 NULL 时,COUNT(COL) 的返回结果为0,但 SUM(COL) 的返回结果为 NULL,因此使用 SUM() 时需注意 NPE 问题。可以使用如下方式来避免 SUM 的 NPE 问题: SELECT IF(ISNULL(SUM(COL)), 0, SUM(COL)) FROM tbl
# Query: B3C502B4AA344196
★ ★ ★ ☆ ☆ 75分
```sql
SELECT
release_year, SUM( LENGTH)
FROM
film
WHERE
LENGTH = 123
GROUP BY
release_year, (LENGTH+ language_id)
```
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item:** CLA.008
* **Severity:** L2
* **Content:** 默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。
## GROUP BY 的条件为表达式
* **Item:** CLA.010
* **Severity:** L2
* **Content:** 当 GROUP BY 条件为表达式或函数时会使用到临时表,如果在未指定 WHERE 或 WHERE 条件返回的结果集较大时性能会很差。
## 使用 SUM(COL) 时需注意 NPE 问题
* **Item:** FUN.006
* **Severity:** L1
* **Content:** 当某一列的值全是 NULL 时,COUNT(COL) 的返回结果为0,但 SUM(COL) 的返回结果为 NULL,因此使用 SUM() 时需注意 NPE 问题。可以使用如下方式来避免 SUM 的 NPE 问题: SELECT IF(ISNULL(SUM(COL)), 0, SUM(COL)) FROM tbl
# Query: 47044E1FE1A965A5
★ ★ ★ ☆ ☆ 70分
```sql
SELECT
release_year, SUM( film_id)
FROM
film
GROUP BY
release_year
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item:** CLA.008
* **Severity:** L2
* **Content:** 默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。
# Query: 2BA1217F6C8CF0AB
★ ★ ☆ ☆ ☆ 45分
```sql
SELECT
*
FROM
address
GROUP BY
address, district
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item:** CLA.008
* **Severity:** L2
* **Content:** 默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
## 非确定性的 GROUP BY
* **Item:** RES.001
* **Severity:** L4
* **Content:** SQL返回的列既不在聚合函数中也不是 GROUP BY 表达式的列中,因此这些值的结果将是非确定性的。如:select a, b, c from tbl where foo="bar" group by a,该 SQL 返回的结果就是不确定的。
# Query: 863A85207E4F410D
★ ★ ★ ★ ☆ 80分
```sql
SELECT
title
FROM
film
WHERE
ABS( language_id) = 3
GROUP BY
title
```
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item:** CLA.008
* **Severity:** L2
* **Content:** 默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。
## 避免在 WHERE 条件中使用函数或其他运算符
* **Item:** FUN.001
* **Severity:** L2
* **Content:** 虽然在 SQL 中使用函数可以简化很多复杂的查询,但使用了函数的查询无法利用表中已经建立的索引,该查询将会是全表扫描,性能较差。通常建议将列名写在比较运算符左侧,将查询过滤条件放在比较运算符右侧。也不建议在查询比较条件两侧书写多余的括号,这会对阅读产生比较大的困扰。
# Query: DF59FD602E4AA368
★ ★ ★ ★ ☆ 80分
```sql
SELECT
language_id
FROM
film
WHERE
LENGTH = 123
GROUP BY
release_year
ORDER BY
language_id
```
## 非确定性的 GROUP BY
* **Item:** RES.001
* **Severity:** L4
* **Content:** SQL返回的列既不在聚合函数中也不是 GROUP BY 表达式的列中,因此这些值的结果将是非确定性的。如:select a, b, c from tbl where foo="bar" group by a,该 SQL 返回的结果就是不确定的。
# Query: F6DBEAA606D800FC
★ ★ ★ ★ ★ 100分
```sql
SELECT
release_year
FROM
film
WHERE
LENGTH = 123
GROUP BY
release_year
ORDER BY
release_year
```
## OK
# Query: 6E9B96CA3F0E6BDA
★ ★ ★ ☆ ☆ 65分
```sql
SELECT
*
FROM
film
WHERE
LENGTH = 123
ORDER BY
release_year ASC, language_id DESC
```
## ORDER BY 语句对多个不同条件使用不同方向的排序无法使用索引
* **Item:** CLA.007
* **Severity:** L2
* **Content:** ORDER BY 子句中的所有表达式必须按统一的 ASC 或 DESC 方向排序,以便利用索引。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
## ORDER BY 多个列但排序方向不同时可能无法使用索引
* **Item:** KEY.008
* **Severity:** L4
* **Content:** 在 MySQL 8.0之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。
# Query: 2EAACFD7030EA528
★ ★ ★ ★ ★ 100分
```sql
SELECT
release_year
FROM
film
WHERE
LENGTH = 123
GROUP BY
release_year
ORDER BY
release_year
LIMIT
10
```
## OK
# Query: 5CE2F187DBF2A710
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH = 123
ORDER BY
release_year
LIMIT
10
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: E75234155B5E2E14
★ ★ ★ ☆ ☆ 75分
```sql
SELECT
*
FROM
film
ORDER BY
release_year
LIMIT
10
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: AFEEBF10A8D74E32
★ ★ ★ ★ ☆ 80分
```sql
SELECT
film_id
FROM
film
ORDER BY
release_year
LIMIT
10
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
# Query: 965D5AC955824512
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH > 100
ORDER BY
LENGTH
LIMIT
10
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 1E2CF4145EE706A5
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH < 100
ORDER BY
LENGTH
LIMIT
10
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: A314542EEE8571EE
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
customer
WHERE
address_id in (224, 510)
ORDER BY
last_name
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 0BE2D79E2F1E7CB0
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
release_year = 2016
AND LENGTH != 1
ORDER BY
title
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
## '!=' 运算符是非标准的
* **Item:** STA.001
* **Severity:** L0
* **Content:** "<>"才是标准SQL中的不等于运算符。
# Query: 4E73AA068370E6A8
★ ★ ★ ★ ★ 100分
```sql
SELECT
title
FROM
film
WHERE
release_year = 1995
```
## OK
# Query: BA7111449E4F1122
★ ★ ★ ★ ★ 100分
```sql
SELECT
title, replacement_cost
FROM
film
WHERE
language_id = 5
AND LENGTH = 70
```
## OK
# Query: B13E0ACEAF8F3119
★ ★ ★ ★ ★ 100分
```sql
SELECT
title
FROM
film
WHERE
language_id > 5
AND LENGTH > 70
```
## OK
# Query: A3FAB6027484B88B
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH = 100
AND title = 'xyz'
ORDER BY
release_year
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: CB42080E9F35AB07
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH > 100
AND title = 'xyz'
ORDER BY
release_year
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: C4A212A42400411D
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
film
WHERE
LENGTH > 100
ORDER BY
release_year
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 4ECCA9568BE69E68
★ ★ ★ ☆ ☆ 75分
```sql
SELECT
*
FROM
city a
INNER JOIN country b ON a. country_id= b. country_id
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 485D56FC88BBBDB9
★ ★ ★ ☆ ☆ 75分
```sql
SELECT
*
FROM
city a
LEFT JOIN country b ON a. country_id= b. country_id
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 0D0DABACEDFF5765
★ ★ ★ ☆ ☆ 75分
```sql
SELECT
*
FROM
city a
RIGHT JOIN country b ON a. country_id= b. country_id
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 1E56C6CCEA2131CC
★ ★ ★ ★ ☆ 90分
```sql
SELECT
*
FROM
city a
LEFT JOIN country b ON a. country_id= b. country_id
WHERE
b. last_update IS NULL
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 应尽量避免在 WHERE 子句中对字段进行 NULL 值判断
* **Item:** ARG.006
* **Severity:** L1
* **Content:** 使用 IS NULL 或 IS NOT NULL 将可能导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null;可以在num上设置默认值0,确保表中 num 列没有 NULL 值,然后这样查询: select id from t where num=0;
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: F5D30BCAC1E206A1
★ ★ ★ ★ ☆ 90分
```sql
SELECT
*
FROM
city a
RIGHT JOIN country b ON a. country_id= b. country_id
WHERE
a. last_update IS NULL
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 应尽量避免在 WHERE 子句中对字段进行 NULL 值判断
* **Item:** ARG.006
* **Severity:** L1
* **Content:** 使用 IS NULL 或 IS NOT NULL 将可能导致引擎放弃使用索引而进行全表扫描,如:select id from t where num is null;可以在num上设置默认值0,确保表中 num 列没有 NULL 值,然后这样查询: select id from t where num=0;
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 17D5BCF21DC2364C
★ ★ ★ ☆ ☆ 65分
```sql
SELECT
*
FROM
city a
LEFT JOIN country b ON a. country_id= b. country_id
UNION
SELECT
*
FROM
city a
RIGHT JOIN country b ON a. country_id= b. country_id
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
## 如果您不在乎重复的话,建议使用 UNION ALL 替代 UNION
* **Item:** SUB.002
* **Severity:** L2
* **Content:** 与去除重复的UNION不同,UNION ALL允许重复元组。如果您不关心重复元组,那么使用UNION ALL将是一个更快的选项。
# Query: A4911095C201896F
★ ★ ★ ★ ☆ 85分
```sql
SELECT
*
FROM
city a
RIGHT JOIN country b ON a. country_id= b. country_id
WHERE
a. last_update IS NULL
UNION
SELECT
*
FROM
city a
LEFT JOIN country b ON a. country_id= b. country_id
WHERE
b. last_update IS NULL
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
## 如果您不在乎重复的话,建议使用 UNION ALL 替代 UNION
* **Item:** SUB.002
* **Severity:** L2
* **Content:** 与去除重复的UNION不同,UNION ALL允许重复元组。如果您不关心重复元组,那么使用UNION ALL将是一个更快的选项。
# Query: 3FF20E28EC9CBEF9
★ ★ ★ ★ ☆ 80分
```sql
SELECT
country_id, last_update
FROM
city NATURAL
JOIN country
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
# Query: 5C547F08EADBB131
★ ★ ★ ★ ☆ 80分
```sql
SELECT
country_id, last_update
FROM
city NATURAL
LEFT JOIN country
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
# Query: AF0C1EB58B23D2FA
★ ★ ★ ★ ☆ 80分
```sql
SELECT
country_id, last_update
FROM
city NATURAL
RIGHT JOIN country
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
# Query: 626571EAE84E2C8A
★ ★ ★ ★ ☆ 80分
```sql
SELECT
a. country_id, a. last_update
FROM
city a STRAIGHT_JOIN country b ON a. country_id= b. country_id
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
# Query: 50F2AB4243CE2071
★ ★ ★ ☆ ☆ 60分
```sql
SELECT
a. address, a. postal_code
FROM
sakila. address a
WHERE
a. city_id IN (
SELECT
c. city_id
FROM
sakila. city c)
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## MySQL 对子查询的优化效果不佳
* **Item:** SUB.001
* **Severity:** L4
* **Content:** MySQL 将外部查询中的每一行作为依赖子查询执行子查询。 这是导致严重性能问题的常见原因。这可能会在 MySQL 5.6 版本中得到改善, 但对于5.1及更早版本, 建议将该类查询分别重写为 JOIN 或 LEFT OUTER JOIN。
# Query: 584CCEC8069B6947
★ ★ ☆ ☆ ☆ 40分
```sql
SELECT
city
FROM(
SELECT
city_id
FROM
city
WHERE
city = "A Corua (La Corua)"
ORDER BY
last_update DESC
LIMIT
50, 10) I
JOIN city ON (I. city_id = city. city_id)
JOIN country ON (country. country_id = city. country_id)
ORDER BY
city DESC
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 同一张表被连接两次
* **Item:** JOI.002
* **Severity:** L4
* **Content:** 相同的表在 FROM 子句中至少出现两次,可以简化为对该表的单次访问。
## MySQL 对子查询的优化效果不佳
* **Item:** SUB.001
* **Severity:** L4
* **Content:** MySQL 将外部查询中的每一行作为依赖子查询执行子查询。 这是导致严重性能问题的常见原因。这可能会在 MySQL 5.6 版本中得到改善, 但对于5.1及更早版本, 建议将该类查询分别重写为 JOIN 或 LEFT OUTER JOIN。
# Query: 7F02E23D44A38A6D
★ ★ ★ ★ ☆ 80分
```sql
DELETE city, country
FROM
city
INNER JOIN country using (country_id)
WHERE
city. city_id = 1
```
## 不建议使用联表删除或更新
* **Item:** JOI.007
* **Severity:** L4
* **Content:** 当需要同时删除或更新多张表时建议使用简单语句,一条 SQL 只删除或更新一张表,尽量不要将多张表的操作在同一条语句。
## 使用DELETE/DROP/TRUNCATE等操作时注意备份
* **Item:** SEC.003
* **Severity:** L0
* **Content:** 在执行高危操作之前对数据进行备份是十分有必要的。
# Query: F8314ABD1CBF2FF1
★ ★ ★ ★ ☆ 80分
```sql
DELETE city
FROM
city
LEFT JOIN country ON city. country_id = country. country_id
WHERE
country. country IS NULL
```
## 不建议使用联表删除或更新
* **Item:** JOI.007
* **Severity:** L4
* **Content:** 当需要同时删除或更新多张表时建议使用简单语句,一条 SQL 只删除或更新一张表,尽量不要将多张表的操作在同一条语句。
## 使用DELETE/DROP/TRUNCATE等操作时注意备份
* **Item:** SEC.003
* **Severity:** L0
* **Content:** 在执行高危操作之前对数据进行备份是十分有必要的。
# Query: 1A53649C43122975
★ ★ ★ ★ ☆ 80分
```sql
DELETE a1, a2
FROM
city AS a1
INNER JOIN country AS a2
WHERE
a1. country_id= a2. country_id
```
## 不建议使用联表删除或更新
* **Item:** JOI.007
* **Severity:** L4
* **Content:** 当需要同时删除或更新多张表时建议使用简单语句,一条 SQL 只删除或更新一张表,尽量不要将多张表的操作在同一条语句。
## 使用DELETE/DROP/TRUNCATE等操作时注意备份
* **Item:** SEC.003
* **Severity:** L0
* **Content:** 在执行高危操作之前对数据进行备份是十分有必要的。
# Query: B862978586C6338B
★ ★ ★ ★ ☆ 80分
```sql
DELETE FROM
a1, a2 USING city AS a1
INNER JOIN country AS a2
WHERE
a1. country_id= a2. country_id
```
## 不建议使用联表删除或更新
* **Item:** JOI.007
* **Severity:** L4
* **Content:** 当需要同时删除或更新多张表时建议使用简单语句,一条 SQL 只删除或更新一张表,尽量不要将多张表的操作在同一条语句。
## 使用DELETE/DROP/TRUNCATE等操作时注意备份
* **Item:** SEC.003
* **Severity:** L0
* **Content:** 在执行高危操作之前对数据进行备份是十分有必要的。
# Query: F16FD63381EF8299
★ ★ ★ ★ ★ 100分
```sql
DELETE FROM
film
WHERE
LENGTH > 100
```
## 使用DELETE/DROP/TRUNCATE等操作时注意备份
* **Item:** SEC.003
* **Severity:** L0
* **Content:** 在执行高危操作之前对数据进行备份是十分有必要的。
# Query: 08CFE41C7D20AAC8
★ ★ ★ ★ ☆ 80分
```sql
UPDATE
city
INNER JOIN country USING( country_id)
SET
city. city = 'Abha',
city. last_update = '2006-02-15 04:45:25',
country. country = 'Afghanistan'
WHERE
city. city_id= 10
```
## 不建议使用联表删除或更新
* **Item:** JOI.007
* **Severity:** L4
* **Content:** 当需要同时删除或更新多张表时建议使用简单语句,一条 SQL 只删除或更新一张表,尽量不要将多张表的操作在同一条语句。
# Query: C15BDF2C73B5B7ED
★ ★ ★ ★ ☆ 80分
```sql
UPDATE
city
INNER JOIN country ON city. country_id = country. country_id
INNER JOIN address ON city. city_id = address. city_id
SET
city. city = 'Abha',
city. last_update = '2006-02-15 04:45:25',
country. country = 'Afghanistan'
WHERE
city. city_id= 10
```
## 不建议使用联表删除或更新
* **Item:** JOI.007
* **Severity:** L4
* **Content:** 当需要同时删除或更新多张表时建议使用简单语句,一条 SQL 只删除或更新一张表,尽量不要将多张表的操作在同一条语句。
# Query: FCD1ABF36F8CDAD7
★ ★ ★ ★ ★ 100分
```sql
UPDATE
city, country
SET
city. city = 'Abha',
city. last_update = '2006-02-15 04:45:25',
country. country = 'Afghanistan'
WHERE
city. country_id = country. country_id
AND city. city_id= 10
```
## OK
# Query: FE409EB794EE91CF
★ ★ ★ ★ ★ 100分
```sql
UPDATE
film
SET
LENGTH = 10
WHERE
language_id = 20
```
## OK
# Query: 3656B13CC4F888E2
★ ★ ★ ☆ ☆ 65分
```sql
INSERT INTO city (country_id)
SELECT
country_id
FROM
country
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## INSERT INTO xx SELECT 加锁粒度较大请谨慎
* **Item:** LCK.001
* **Severity:** L3
* **Content:** INSERT INTO xx SELECT 加锁粒度较大请谨慎
# Query: 2F7439623B712317
★ ★ ★ ★ ★ 100分
```sql
INSERT INTO city (country_id)
VALUES
(1),
(2),
(3)
```
## OK
# Query: 11EC7AAACC97DC0F
★ ★ ★ ★ ☆ 85分
```sql
INSERT INTO city (country_id)
SELECT
10
FROM
DUAL
```
## INSERT INTO xx SELECT 加锁粒度较大请谨慎
* **Item:** LCK.001
* **Severity:** L3
* **Content:** INSERT INTO xx SELECT 加锁粒度较大请谨慎
# Query: E3DDA1A929236E72
★ ★ ★ ☆ ☆ 65分
```sql
REPLACE INTO city (country_id)
SELECT
country_id
FROM
country
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## INSERT INTO xx SELECT 加锁粒度较大请谨慎
* **Item:** LCK.001
* **Severity:** L3
* **Content:** INSERT INTO xx SELECT 加锁粒度较大请谨慎
# Query: 466F1AC2F5851149
★ ★ ★ ★ ★ 100分
```sql
REPLACE INTO city (country_id)
VALUES
(1),
(2),
(3)
```
## OK
# Query: A7973BDD268F926E
★ ★ ★ ★ ☆ 85分
```sql
REPLACE INTO city (country_id)
SELECT
10
FROM
DUAL
```
## INSERT INTO xx SELECT 加锁粒度较大请谨慎
* **Item:** LCK.001
* **Severity:** L3
* **Content:** INSERT INTO xx SELECT 加锁粒度较大请谨慎
# Query: 105C870D5DFB6710
★ ★ ★ ☆ ☆ 65分
```sql
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
(
SELECT
film_id
FROM
film
) film
) film
) film
) film
) film
) film
) film
) film
) film
) film
) film
) film
) film
) film
) film
) film
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 执行计划中嵌套连接深度过深
* **Item:** SUB.004
* **Severity:** L3
* **Content:** MySQL对子查询的优化效果不佳,MySQL将外部查询中的每一行作为依赖子查询执行子查询。 这是导致严重性能问题的常见原因。
# Query: 16C2B14E7DAA9906
★ ☆ ☆ ☆ ☆ 35分
```sql
SELECT
*
FROM
film
WHERE
language_id = (
SELECT
language_id
FROM
language
LIMIT
1)
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
## 未使用 ORDER BY 的 LIMIT 查询
* **Item:** RES.002
* **Severity:** L4
* **Content:** 没有 ORDER BY 的 LIMIT 会导致非确定性的结果,这取决于查询执行计划。
## MySQL 对子查询的优化效果不佳
* **Item:** SUB.001
* **Severity:** L4
* **Content:** MySQL 将外部查询中的每一行作为依赖子查询执行子查询。 这是导致严重性能问题的常见原因。这可能会在 MySQL 5.6 版本中得到改善, 但对于5.1及更早版本, 建议将该类查询分别重写为 JOIN 或 LEFT OUTER JOIN。
# Query: 16CB4628D2597D40
★ ★ ★ ☆ ☆ 65分
```sql
SELECT
*
FROM
city i
LEFT JOIN country o ON i. city_id= o. country_id
UNION
SELECT
*
FROM
city i
RIGHT JOIN country o ON i. city_id= o. country_id
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
## 如果您不在乎重复的话,建议使用 UNION ALL 替代 UNION
* **Item:** SUB.002
* **Severity:** L2
* **Content:** 与去除重复的UNION不同,UNION ALL允许重复元组。如果您不关心重复元组,那么使用UNION ALL将是一个更快的选项。
# Query: EA50643B01E139A8
★ ★ ☆ ☆ ☆ 45分
```sql
SELECT
*
FROM
(
SELECT
*
FROM
actor
WHERE
last_update= '2006-02-15 04:34:33'
AND last_name= 'CHASE'
) t
WHERE
last_update= '2006-02-15 04:34:33'
AND last_name= 'CHASE'
GROUP BY
first_name
```
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item:** CLA.008
* **Severity:** L2
* **Content:** 默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
## 非确定性的 GROUP BY
* **Item:** RES.001
* **Severity:** L4
* **Content:** SQL返回的列既不在聚合函数中也不是 GROUP BY 表达式的列中,因此这些值的结果将是非确定性的。如:select a, b, c from tbl where foo="bar" group by a,该 SQL 返回的结果就是不确定的。
## MySQL 对子查询的优化效果不佳
* **Item:** SUB.001
* **Severity:** L4
* **Content:** MySQL 将外部查询中的每一行作为依赖子查询执行子查询。 这是导致严重性能问题的常见原因。这可能会在 MySQL 5.6 版本中得到改善, 但对于5.1及更早版本, 建议将该类查询分别重写为 JOIN 或 LEFT OUTER JOIN。
# Query: 7598A4EDE6CFA6BE
★ ★ ★ ★ ☆ 85分
```sql
SELECT
*
FROM
city i
LEFT JOIN country o ON i. city_id= o. country_id
WHERE
o. country_id is null
UNION
SELECT
*
FROM
city i
RIGHT JOIN country o ON i. city_id= o. country_id
WHERE
i. city_id is null
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
## 如果您不在乎重复的话,建议使用 UNION ALL 替代 UNION
* **Item:** SUB.002
* **Severity:** L2
* **Content:** 与去除重复的UNION不同,UNION ALL允许重复元组。如果您不关心重复元组,那么使用UNION ALL将是一个更快的选项。
# Query: 1E8B70E30062FD13
★ ★ ★ ★ ☆ 80分
```sql
SELECT
first_name, last_name, email
FROM
customer STRAIGHT_JOIN address ON customer. address_id= address. address_id
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
# Query: E48A20D0413512DA
★ ☆ ☆ ☆ ☆ 30分
```sql
SELECT
ID, name
FROM
(
SELECT
address
FROM
customer_list
WHERE
SID= 1
ORDER BY
phone
LIMIT
50, 10) a
JOIN customer_list l ON (a. address= l. address)
JOIN city c ON (c. city= l. city)
ORDER BY
phone desc
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## ORDER BY 语句对多个不同条件使用不同方向的排序无法使用索引
* **Item:** CLA.007
* **Severity:** L2
* **Content:** ORDER BY 子句中的所有表达式必须按统一的 ASC 或 DESC 方向排序,以便利用索引。
## 同一张表被连接两次
* **Item:** JOI.002
* **Severity:** L4
* **Content:** 相同的表在 FROM 子句中至少出现两次,可以简化为对该表的单次访问。
## MySQL 对子查询的优化效果不佳
* **Item:** SUB.001
* **Severity:** L4
* **Content:** MySQL 将外部查询中的每一行作为依赖子查询执行子查询。 这是导致严重性能问题的常见原因。这可能会在 MySQL 5.6 版本中得到改善, 但对于5.1及更早版本, 建议将该类查询分别重写为 JOIN 或 LEFT OUTER JOIN。
# Query: B0BA5A7079EA16B3
★ ★ ★ ★ ☆ 85分
```sql
SELECT
*
FROM
film
WHERE
DATE( last_update) = '2006-02-15'
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
## 避免在 WHERE 条件中使用函数或其他运算符
* **Item:** FUN.001
* **Severity:** L2
* **Content:** 虽然在 SQL 中使用函数可以简化很多复杂的查询,但使用了函数的查询无法利用表中已经建立的索引,该查询将会是全表扫描,性能较差。通常建议将列名写在比较运算符左侧,将查询过滤条件放在比较运算符右侧。也不建议在查询比较条件两侧书写多余的括号,这会对阅读产生比较大的困扰。
# Query: 18A2AD1395A58EAE
★ ★ ★ ☆ ☆ 60分
```sql
SELECT
last_update
FROM
film
GROUP BY
DATE( last_update)
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item:** CLA.008
* **Severity:** L2
* **Content:** 默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。
## GROUP BY 的条件为表达式
* **Item:** CLA.010
* **Severity:** L2
* **Content:** 当 GROUP BY 条件为表达式或函数时会使用到临时表,如果在未指定 WHERE 或 WHERE 条件返回的结果集较大时性能会很差。
# Query: 60F234BA33AAC132
★ ★ ★ ☆ ☆ 70分
```sql
SELECT
last_update
FROM
film
ORDER BY
DATE( last_update)
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## ORDER BY 的条件为表达式
* **Item:** CLA.009
* **Severity:** L2
* **Content:** 当 ORDER BY 条件为表达式或函数时会使用到临时表,如果在未指定 WHERE 或 WHERE 条件返回的结果集较大时性能会很差。
# Query: 1ED2B7ECBA4215E1
★ ★ ★ ★ ☆ 90分
```sql
SELECT
description
FROM
film
WHERE
description IN( 'NEWS',
'asd'
)
GROUP BY
description
```
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item:** CLA.008
* **Severity:** L2
* **Content:** 默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。
# Query: 255BAC03F56CDBC7
★ ★ ★ ★ ★ 100分
```sql
ALTER TABLE
address
ADD
index idx_city_id( city_id)
```
## OK
# Query: C315BC4EE0F4E523
★ ★ ★ ★ ★ 100分
```sql
ALTER TABLE
inventory
ADD
index `idx_store_film` (
`store_id`, `film_id`)
```
## 提醒:请将索引属性顺序与查询对齐
* **Item:** KEY.004
* **Severity:** L0
* **Content:** 如果为列创建复合索引,请确保查询属性与索引属性的顺序相同,以便DBMS在处理查询时使用索引。如果查询和索引属性订单没有对齐,那么DBMS可能无法在查询处理期间使用索引。
# Query: 9BB74D074BA0727C
★ ★ ★ ★ ★ 100分
```sql
ALTER TABLE
inventory
ADD
index `idx_store_film` (
`store_id`, `film_id`),
ADD
index `idx_store_film` (
`store_id`, `film_id`),
ADD
index `idx_store_film` (
`store_id`, `film_id`)
```
## 提醒:请将索引属性顺序与查询对齐
* **Item:** KEY.004
* **Severity:** L0
* **Content:** 如果为列创建复合索引,请确保查询属性与索引属性的顺序相同,以便DBMS在处理查询时使用索引。如果查询和索引属性订单没有对齐,那么DBMS可能无法在查询处理期间使用索引。
# Query: C95B5C028C8FFF95
★ ★ ☆ ☆ ☆ 40分
```sql
SELECT
DATE_FORMAT( t. last_update, '%Y-%m-%d'
),
COUNT( DISTINCT (
t. city))
FROM
city t
WHERE
t. last_update > '2018-10-22 00:00:00'
AND t. city LIKE '%Chrome%'
AND t. city = 'eip'
GROUP BY
DATE_FORMAT( t. last_update, '%Y-%m-%d'
)
ORDER BY
DATE_FORMAT( t. last_update, '%Y-%m-%d'
)
```
## 建议使用 AS 关键字显示声明一个别名
* **Item:** ALI.001
* **Severity:** L0
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## 不建议使用前项通配符查找
* **Item:** ARG.001
* **Severity:** L4
* **Content:** 例如 "%foo",查询参数有一个前项通配符的情况无法使用已有索引。
## ORDER BY 的条件为表达式
* **Item:** CLA.009
* **Severity:** L2
* **Content:** 当 ORDER BY 条件为表达式或函数时会使用到临时表,如果在未指定 WHERE 或 WHERE 条件返回的结果集较大时性能会很差。
## GROUP BY 的条件为表达式
* **Item:** CLA.010
* **Severity:** L2
* **Content:** 当 GROUP BY 条件为表达式或函数时会使用到临时表,如果在未指定 WHERE 或 WHERE 条件返回的结果集较大时性能会很差。
## ORDER BY 多个列但排序方向不同时可能无法使用索引
* **Item:** KEY.008
* **Severity:** L4
* **Content:** 在 MySQL 8.0之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。
# Query: C11ECE7AE5F80CE5
★ ★ ☆ ☆ ☆ 45分
```sql
create table hello. t (id int unsigned)
```
## 建议为表添加注释
* **Item:** CLA.011
* **Severity:** L1
* **Content:** 为表添加注释能够使得表的意义更明确,从而为日后的维护带来极大的便利。
## 请为列添加默认值
* **Item:** COL.004
* **Severity:** L1
* **Content:** 请为列添加默认值,如果是 ALTER 操作,请不要忘记将原字段的默认值写上。字段无默认值,当表较大时无法在线变更表结构。
## 列未添加注释
* **Item:** COL.005
* **Severity:** L1
* **Content:** 建议对表中每个列添加注释,来明确每个列在表中的含义及作用。
## 未指定主键或主键非 int 或 bigint
* **Item:** KEY.007
* **Severity:** L4
* **Content:** 未指定主键或主键非 int 或 bigint,建议将主键设置为 int unsigned 或 bigint unsigned。
## 请为表选择合适的存储引擎
* **Item:** TBL.002
* **Severity:** L4
* **Content:** 建表或修改表的存储引擎时建议使用推荐的存储引擎,如:innodb
# Query: 291F95B7DCB74C21
★ ★ ★ ★ ☆ 95分
```sql
SELECT
*
FROM
tb
WHERE
data >= ''
```
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
# Query: 084DA3E3EE38DD85
★ ★ ★ ★ ★ 100分
```sql
ALTER TABLE
tb alter column id
DROP
DEFAULT
```
## OK
<head>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<title>soar report check</title>
<script>!function(e,E){"object"==typeof exports&&"object"==typeof module?module.exports=E():"function"==typeof define&&define.amd?define([],E):"object"==typeof exports?exports.sqlFormatter=E():e.sqlFormatter=E()}(this,function(){return function(e){function E(n){if(t[n])return t[n].exports;var r=t[n]={exports:{},id:n,loaded:!1};return e[n].call(r.exports,r,r.exports,E),r.loaded=!0,r.exports}var t={};return E.m=e,E.c=t,E.p="",E(0)}([function(e,E,t){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}E.__esModule=!0;var r=t(18),T=n(r),R=t(19),o=n(R),N=t(20),A=n(N),I=t(21),O=n(I);E["default"]={format:function(e,E){switch(E=E||{},E.language){case"db2":return new T["default"](E).format(e);case"n1ql":return new o["default"](E).format(e);case"pl/sql":return new A["default"](E).format(e);case"sql":case void 0:return new O["default"](E).format(e);default:throw Error("Unsupported SQL dialect: "+E.language)}}},e.exports=E["default"]},function(e,E){"use strict";E.__esModule=!0,E["default"]=function(e,E){if(!(e instanceof E))throw new TypeError("Cannot call a class as a function")}},function(e,E,t){var n=t(39),r="object"==typeof self&&self&&self.Object===Object&&self,T=n||r||Function("return this")();e.exports=T},function(e,E,t){function n(e,E){var t=T(e,E);return r(t)?t:void 0}var r=t(33),T=t(41);e.exports=n},function(e,E,t){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}E.__esModule=!0;var r=t(1),T=n(r),R=t(66),o=n(R),N=t(7),A=n(N),I=t(15),O=n(I),i=t(16),S=n(i),u=t(17),L=n(u),C=function(){function e(E,t){(0,T["default"])(this,e),this.cfg=E||{},this.indentation=new O["default"](this.cfg.indent),this.inlineBlock=new S["default"],this.params=new L["default"](this.cfg.params),this.tokenizer=t,this.previousReservedWord={}}return e.prototype.format=function(e){var E=this.tokenizer.tokenize(e),t=this.getFormattedQueryFromTokens(E);return t.trim()},e.prototype.getFormattedQueryFromTokens=function(e){var E=this,t="";return e.forEach(function(n,r){n.type!==A["default"].WHITESPACE&&(n.type===A["default"].LINE_COMMENT?t=E.formatLineComment(n,t):n.type===A["default"].BLOCK_COMMENT?t=E.formatBlockComment(n,t):n.type===A["default"].RESERVED_TOPLEVEL?(t=E.formatToplevelReservedWord(n,t),E.previousReservedWord=n):n.type===A["default"].RESERVED_NEWLINE?(t=E.formatNewlineReservedWord(n,t),E.previousReservedWord=n):n.type===A["default"].RESERVED?(t=E.formatWithSpaces(n,t),E.previousReservedWord=n):t=n.type===A["default"].OPEN_PAREN?E.formatOpeningParentheses(e,r,t):n.type===A["default"].CLOSE_PAREN?E.formatClosingParentheses(n,t):n.type===A["default"].PLACEHOLDER?E.formatPlaceholder(n,t):","===n.value?E.formatComma(n,t):":"===n.value?E.formatWithSpaceAfter(n,t):"."===n.value||";"===n.value?E.formatWithoutSpaces(n,t):E.formatWithSpaces(n,t))}),t},e.prototype.formatLineComment=function(e,E){return this.addNewline(E+e.value)},e.prototype.formatBlockComment=function(e,E){return this.addNewline(this.addNewline(E)+this.indentComment(e.value))},e.prototype.indentComment=function(e){return e.replace(/\n/g,"\n"+this.indentation.getIndent())},e.prototype.formatToplevelReservedWord=function(e,E){return this.indentation.decreaseTopLevel(),E=this.addNewline(E),this.indentation.increaseToplevel(),E+=this.equalizeWhitespace(e.value),this.addNewline(E)},e.prototype.formatNewlineReservedWord=function(e,E){return this.addNewline(E)+this.equalizeWhitespace(e.value)+" "},e.prototype.equalizeWhitespace=function(e){return e.replace(/\s+/g," ")},e.prototype.formatOpeningParentheses=function(e,E,t){var n=e[E-1];return n&&n.type!==A["default"].WHITESPACE&&n.type!==A["default"].OPEN_PAREN&&(t=(0,o["default"])(t)),t+=e[E].value,this.inlineBlock.beginIfPossible(e,E),this.inlineBlock.isActive()||(this.indentation.increaseBlockLevel(),t=this.addNewline(t)),t},e.prototype.formatClosingParentheses=function(e,E){return this.inlineBlock.isActive()?(this.inlineBlock.end(),this.formatWithSpaceAfter(e,E)):(this.indentation.decreaseBlockLevel(),this.formatWithSpaces(e,this.addNewline(E)))},e.prototype.formatPlaceholder=function(e,E){return E+this.params.get(e)+" "},e.prototype.formatComma=function(e,E){return E=(0,o["default"])(E)+e.value+" ",this.inlineBlock.isActive()?E:/^LIMIT$/i.test(this.previousReservedWord.value)?E:this.addNewline(E)},e.prototype.formatWithSpaceAfter=function(e,E){return(0,o["default"])(E)+e.value+" "},e.prototype.formatWithoutSpaces=function(e,E){return(0,o["default"])(E)+e.value},e.prototype.formatWithSpaces=function(e,E){return E+e.value+" "},e.prototype.addNewline=function(e){return(0,o["default"])(e)+"\n"+this.indentation.getIndent()},e}();E["default"]=C,e.exports=E["default"]},function(e,E,t){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}E.__esModule=!0;var r=t(1),T=n(r),R=t(58),o=n(R),N=t(53),A=n(N),I=t(7),O=n(I),i=function(){function e(E){(0,T["default"])(this,e),this.WHITESPACE_REGEX=/^(\s+)/,this.NUMBER_REGEX=/^((-\s*)?[0-9]+(\.[0-9]+)?|0x[0-9a-fA-F]+|0b[01]+)\b/,this.OPERATOR_REGEX=/^(!=|<>|==|<=|>=|!<|!>|\|\||::|->>|->|~~\*|~~|!~~\*|!~~|~\*|!~\*|!~|.)/,this.BLOCK_COMMENT_REGEX=/^(\/\*[^]*?(?:\*\/|$))/,this.LINE_COMMENT_REGEX=this.createLineCommentRegex(E.lineCommentTypes),this.RESERVED_TOPLEVEL_REGEX=this.createReservedWordRegex(E.reservedToplevelWords),this.RESERVED_NEWLINE_REGEX=this.createReservedWordRegex(E.reservedNewlineWords),this.RESERVED_PLAIN_REGEX=this.createReservedWordRegex(E.reservedWords),this.WORD_REGEX=this.createWordRegex(E.specialWordChars),this.STRING_REGEX=this.createStringRegex(E.stringTypes),this.OPEN_PAREN_REGEX=this.createParenRegex(E.openParens),this.CLOSE_PAREN_REGEX=this.createParenRegex(E.closeParens),this.INDEXED_PLACEHOLDER_REGEX=this.createPlaceholderRegex(E.indexedPlaceholderTypes,"[0-9]*"),this.IDENT_NAMED_PLACEHOLDER_REGEX=this.createPlaceholderRegex(E.namedPlaceholderTypes,"[a-zA-Z0-9._$]+"),this.STRING_NAMED_PLACEHOLDER_REGEX=this.createPlaceholderRegex(E.namedPlaceholderTypes,this.createStringPattern(E.stringTypes))}return e.prototype.createLineCommentRegex=function(e){return RegExp("^((?:"+e.map(function(e){return(0,A["default"])(e)}).join("|")+").*?(?:\n|$))")},e.prototype.createReservedWordRegex=function(e){var E=e.join("|").replace(/ /g,"\\s+");return RegExp("^("+E+")\\b","i")},e.prototype.createWordRegex=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];return RegExp("^([\\w"+e.join("")+"]+)")},e.prototype.createStringRegex=function(e){return RegExp("^("+this.createStringPattern(e)+")")},e.prototype.createStringPattern=function(e){var E={"``":"((`[^`]*($|`))+)","[]":"((\\[[^\\]]*($|\\]))(\\][^\\]]*($|\\]))*)",'""':'(("[^"\\\\]*(?:\\\\.[^"\\\\]*)*("|$))+)',"''":"(('[^'\\\\]*(?:\\\\.[^'\\\\]*)*('|$))+)","N''":"((N'[^N'\\\\]*(?:\\\\.[^N'\\\\]*)*('|$))+)"};return e.map(function(e){return E[e]}).join("|")},e.prototype.createParenRegex=function(e){var E=this;return RegExp("^("+e.map(function(e){return E.escapeParen(e)}).join("|")+")","i")},e.prototype.escapeParen=function(e){return 1===e.length?(0,A["default"])(e):"\\b"+e+"\\b"},e.prototype.createPlaceholderRegex=function(e,E){if((0,o["default"])(e))return!1;var t=e.map(A["default"]).join("|");return RegExp("^((?:"+t+")(?:"+E+"))")},e.prototype.tokenize=function(e){for(var E=[],t=void 0;e.length;)t=this.getNextToken(e,t),e=e.substring(t.value.length),E.push(t);return E},e.prototype.getNextToken=function(e,E){return this.getWhitespaceToken(e)||this.getCommentToken(e)||this.getStringToken(e)||this.getOpenParenToken(e)||this.getCloseParenToken(e)||this.getPlaceholderToken(e)||this.getNumberToken(e)||this.getReservedWordToken(e,E)||this.getWordToken(e)||this.getOperatorToken(e)},e.prototype.getWhitespaceToken=function(e){return this.getTokenOnFirstMatch({input:e,type:O["default"].WHITESPACE,regex:this.WHITESPACE_REGEX})},e.prototype.getCommentToken=function(e){return this.getLineCommentToken(e)||this.getBlockCommentToken(e)},e.prototype.getLineCommentToken=function(e){return this.getTokenOnFirstMatch({input:e,type:O["default"].LINE_COMMENT,regex:this.LINE_COMMENT_REGEX})},e.prototype.getBlockCommentToken=function(e){return this.getTokenOnFirstMatch({input:e,type:O["default"].BLOCK_COMMENT,regex:this.BLOCK_COMMENT_REGEX})},e.prototype.getStringToken=function(e){return this.getTokenOnFirstMatch({input:e,type:O["default"].STRING,regex:this.STRING_REGEX})},e.prototype.getOpenParenToken=function(e){return this.getTokenOnFirstMatch({input:e,type:O["default"].OPEN_PAREN,regex:this.OPEN_PAREN_REGEX})},e.prototype.getCloseParenToken=function(e){return this.getTokenOnFirstMatch({input:e,type:O["default"].CLOSE_PAREN,regex:this.CLOSE_PAREN_REGEX})},e.prototype.getPlaceholderToken=function(e){return this.getIdentNamedPlaceholderToken(e)||this.getStringNamedPlaceholderToken(e)||this.getIndexedPlaceholderToken(e)},e.prototype.getIdentNamedPlaceholderToken=function(e){return this.getPlaceholderTokenWithKey({input:e,regex:this.IDENT_NAMED_PLACEHOLDER_REGEX,parseKey:function(e){return e.slice(1)}})},e.prototype.getStringNamedPlaceholderToken=function(e){var E=this;return this.getPlaceholderTokenWithKey({input:e,regex:this.STRING_NAMED_PLACEHOLDER_REGEX,parseKey:function(e){return E.getEscapedPlaceholderKey({key:e.slice(2,-1),quoteChar:e.slice(-1)})}})},e.prototype.getIndexedPlaceholderToken=function(e){return this.getPlaceholderTokenWithKey({input:e,regex:this.INDEXED_PLACEHOLDER_REGEX,parseKey:function(e){return e.slice(1)}})},e.prototype.getPlaceholderTokenWithKey=function(e){var E=e.input,t=e.regex,n=e.parseKey,r=this.getTokenOnFirstMatch({input:E,regex:t,type:O["default"].PLACEHOLDER});return r&&(r.key=n(r.value)),r},e.prototype.getEscapedPlaceholderKey=function(e){var E=e.key,t=e.quoteChar;return E.replace(RegExp((0,A["default"])("\\")+t,"g"),t)},e.prototype.getNumberToken=function(e){return this.getTokenOnFirstMatch({input:e,type:O["default"].NUMBER,regex:this.NUMBER_REGEX})},e.prototype.getOperatorToken=function(e){return this.getTokenOnFirstMatch({input:e,type:O["default"].OPERATOR,regex:this.OPERATOR_REGEX})},e.prototype.getReservedWordToken=function(e,E){if(!E||!E.value||"."!==E.value)return this.getToplevelReservedToken(e)||this.getNewlineReservedToken(e)||this.getPlainReservedToken(e)},e.prototype.getToplevelReservedToken=function(e){return this.getTokenOnFirstMatch({input:e,type:O["default"].RESERVED_TOPLEVEL,regex:this.RESERVED_TOPLEVEL_REGEX})},e.prototype.getNewlineReservedToken=function(e){return this.getTokenOnFirstMatch({input:e,type:O["default"].RESERVED_NEWLINE,regex:this.RESERVED_NEWLINE_REGEX})},e.prototype.getPlainReservedToken=function(e){return this.getTokenOnFirstMatch({input:e,type:O["default"].RESERVED,regex:this.RESERVED_PLAIN_REGEX})},e.prototype.getWordToken=function(e){return this.getTokenOnFirstMatch({input:e,type:O["default"].WORD,regex:this.WORD_REGEX})},e.prototype.getTokenOnFirstMatch=function(e){var E=e.input,t=e.type,n=e.regex,r=E.match(n);if(r)return{type:t,value:r[1]}},e}();E["default"]=i,e.exports=E["default"]},function(e,E){function t(e){var E=typeof e;return null!=e&&("object"==E||"function"==E)}e.exports=t},function(e,E){"use strict";E.__esModule=!0,E["default"]={WHITESPACE:"whitespace",WORD:"word",STRING:"string",RESERVED:"reserved",RESERVED_TOPLEVEL:"reserved-toplevel",RESERVED_NEWLINE:"reserved-newline",OPERATOR:"operator",OPEN_PAREN:"open-paren",CLOSE_PAREN:"close-paren",LINE_COMMENT:"line-comment",BLOCK_COMMENT:"block-comment",NUMBER:"number",PLACEHOLDER:"placeholder"},e.exports=E["default"]},function(e,E,t){function n(e){return null!=e&&T(e.length)&&!r(e)}var r=t(12),T=t(59);e.exports=n},function(e,E,t){function n(e){return null==e?"":r(e)}var r=t(10);e.exports=n},function(e,E,t){function n(e){if("string"==typeof e)return e;if(T(e))return N?N.call(e):"";var E=e+"";return"0"==E&&1/e==-R?"-0":E}var r=t(26),T=t(14),R=1/0,o=r?r.prototype:void 0,N=o?o.toString:void 0;e.exports=n},function(e,E){function t(e){if(null!=e){try{return r.call(e)}catch(E){}try{return e+""}catch(E){}}return""}var n=Function.prototype,r=n.toString;e.exports=t},function(e,E,t){function n(e){var E=r(e)?N.call(e):"";return E==T||E==R}var r=t(6),T="[object Function]",R="[object GeneratorFunction]",o=Object.prototype,N=o.toString;e.exports=n},function(e,E){function t(e){return null!=e&&"object"==typeof e}e.exports=t},function(e,E,t){function n(e){return"symbol"==typeof e||r(e)&&o.call(e)==T}var r=t(13),T="[object Symbol]",R=Object.prototype,o=R.toString;e.exports=n},function(e,E,t){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}E.__esModule=!0;var r=t(1),T=n(r),R=t(61),o=n(R),N=t(60),A=n(N),I="top-level",O="block-level",i=function(){function e(E){(0,T["default"])(this,e),this.indent=E||" ",this.indentTypes=[]}return e.prototype.getIndent=function(){return(0,o["default"])(this.indent,this.indentTypes.length)},e.prototype.increaseToplevel=function(){this.indentTypes.push(I)},e.prototype.increaseBlockLevel=function(){this.indentTypes.push(O)},e.prototype.decreaseTopLevel=function(){(0,A["default"])(this.indentTypes)===I&&this.indentTypes.pop()},e.prototype.decreaseBlockLevel=function(){for(;this.indentTypes.length>0;){var e=this.indentTypes.pop();if(e!==I)break}},e}();E["default"]=i,e.exports=E["default"]},function(e,E,t){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}E.__esModule=!0;var r=t(1),T=n(r),R=t(7),o=n(R),N=50,A=function(){function e(){(0,T["default"])(this,e),this.level=0}return e.prototype.beginIfPossible=function(e,E){0===this.level&&this.isInlineBlock(e,E)?this.level=1:this.level>0?this.level++:this.level=0},e.prototype.end=function(){this.level--},e.prototype.isActive=function(){return this.level>0},e.prototype.isInlineBlock=function(e,E){for(var t=0,n=0,r=E;e.length>r;r++){var T=e[r];if(t+=T.value.length,t>N)return!1;if(T.type===o["default"].OPEN_PAREN)n++;else if(T.type===o["default"].CLOSE_PAREN&&(n--,0===n))return!0;if(this.isForbiddenToken(T))return!1}return!1},e.prototype.isForbiddenToken=function(e){var E=e.type,t=e.value;return E===o["default"].RESERVED_TOPLEVEL||E===o["default"].RESERVED_NEWLINE||E===o["default"].COMMENT||E===o["default"].BLOCK_COMMENT||";"===t},e}();E["default"]=A,e.exports=E["default"]},function(e,E,t){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}E.__esModule=!0;var r=t(1),T=n(r),R=function(){function e(E){(0,T["default"])(this,e),this.params=E,this.index=0}return e.prototype.get=function(e){var E=e.key,t=e.value;return this.params?E?this.params[E]:this.params[this.index++]:t},e}();E["default"]=R,e.exports=E["default"]},function(e,E,t){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}E.__esModule=!0;var r=t(1),T=n(r),R=t(4),o=n(R),N=t(5),A=n(N),I=["ABS","ACTIVATE","ALIAS","ALL","ALLOCATE","ALLOW","ALTER","ANY","ARE","ARRAY","AS","ASC","ASENSITIVE","ASSOCIATE","ASUTIME","ASYMMETRIC","AT","ATOMIC","ATTRIBUTES","AUDIT","AUTHORIZATION","AUX","AUXILIARY","AVG","BEFORE","BEGIN","BETWEEN","BIGINT","BINARY","BLOB","BOOLEAN","BOTH","BUFFERPOOL","BY","CACHE","CALL","CALLED","CAPTURE","CARDINALITY","CASCADED","CASE","CAST","CCSID","CEIL","CEILING","CHAR","CHARACTER","CHARACTER_LENGTH","CHAR_LENGTH","CHECK","CLOB","CLONE","CLOSE","CLUSTER","COALESCE","COLLATE","COLLECT","COLLECTION","COLLID","COLUMN","COMMENT","COMMIT","CONCAT","CONDITION","CONNECT","CONNECTION","CONSTRAINT","CONTAINS","CONTINUE","CONVERT","CORR","CORRESPONDING","COUNT","COUNT_BIG","COVAR_POP","COVAR_SAMP","CREATE","CROSS","CUBE","CUME_DIST","CURRENT","CURRENT_DATE","CURRENT_DEFAULT_TRANSFORM_GROUP","CURRENT_LC_CTYPE","CURRENT_PATH","CURRENT_ROLE","CURRENT_SCHEMA","CURRENT_SERVER","CURRENT_TIME","CURRENT_TIMESTAMP","CURRENT_TIMEZONE","CURRENT_TRANSFORM_GROUP_FOR_TYPE","CURRENT_USER","CURSOR","CYCLE","DATA","DATABASE","DATAPARTITIONNAME","DATAPARTITIONNUM","DATE","DAY","DAYS","DB2GENERAL","DB2GENRL","DB2SQL","DBINFO","DBPARTITIONNAME","DBPARTITIONNUM","DEALLOCATE","DEC","DECIMAL","DECLARE","DEFAULT","DEFAULTS","DEFINITION","DELETE","DENSERANK","DENSE_RANK","DEREF","DESCRIBE","DESCRIPTOR","DETERMINISTIC","DIAGNOSTICS","DISABLE","DISALLOW","DISCONNECT","DISTINCT","DO","DOCUMENT","DOUBLE","DROP","DSSIZE","DYNAMIC","EACH","EDITPROC","ELEMENT","ELSE","ELSEIF","ENABLE","ENCODING","ENCRYPTION","END","END-EXEC","ENDING","ERASE","ESCAPE","EVERY","EXCEPTION","EXCLUDING","EXCLUSIVE","EXEC","EXECUTE","EXISTS","EXIT","EXP","EXPLAIN","EXTENDED","EXTERNAL","EXTRACT","FALSE","FENCED","FETCH","FIELDPROC","FILE","FILTER","FINAL","FIRST","FLOAT","FLOOR","FOR","FOREIGN","FREE","FULL","FUNCTION","FUSION","GENERAL","GENERATED","GET","GLOBAL","GOTO","GRANT","GRAPHIC","GROUP","GROUPING","HANDLER","HASH","HASHED_VALUE","HINT","HOLD","HOUR","HOURS","IDENTITY","IF","IMMEDIATE","IN","INCLUDING","INCLUSIVE","INCREMENT","INDEX","INDICATOR","INDICATORS","INF","INFINITY","INHERIT","INNER","INOUT","INSENSITIVE","INSERT","INT","INTEGER","INTEGRITY","INTERSECTION","INTERVAL","INTO","IS","ISOBID","ISOLATION","ITERATE","JAR","JAVA","KEEP","KEY","LABEL","LANGUAGE","LARGE","LATERAL","LC_CTYPE","LEADING","LEAVE","LEFT","LIKE","LINKTYPE","LN","LOCAL","LOCALDATE","LOCALE","LOCALTIME","LOCALTIMESTAMP","LOCATOR","LOCATORS","LOCK","LOCKMAX","LOCKSIZE","LONG","LOOP","LOWER","MAINTAINED","MATCH","MATERIALIZED","MAX","MAXVALUE","MEMBER","MERGE","METHOD","MICROSECOND","MICROSECONDS","MIN","MINUTE","MINUTES","MINVALUE","MOD","MODE","MODIFIES","MODULE","MONTH","MONTHS","MULTISET","NAN","NATIONAL","NATURAL","NCHAR","NCLOB","NEW","NEW_TABLE","NEXTVAL","NO","NOCACHE","NOCYCLE","NODENAME","NODENUMBER","NOMAXVALUE","NOMINVALUE","NONE","NOORDER","NORMALIZE","NORMALIZED","NOT","NULL","NULLIF","NULLS","NUMERIC","NUMPARTS","OBID","OCTET_LENGTH","OF","OFFSET","OLD","OLD_TABLE","ON","ONLY","OPEN","OPTIMIZATION","OPTIMIZE","OPTION","ORDER","OUT","OUTER","OVER","OVERLAPS","OVERLAY","OVERRIDING","PACKAGE","PADDED","PAGESIZE","PARAMETER","PART","PARTITION","PARTITIONED","PARTITIONING","PARTITIONS","PASSWORD","PATH","PERCENTILE_CONT","PERCENTILE_DISC","PERCENT_RANK","PIECESIZE","PLAN","POSITION","POWER","PRECISION","PREPARE","PREVVAL","PRIMARY","PRIQTY","PRIVILEGES","PROCEDURE","PROGRAM","PSID","PUBLIC","QUERY","QUERYNO","RANGE","RANK","READ","READS","REAL","RECOVERY","RECURSIVE","REF","REFERENCES","REFERENCING","REFRESH","REGR_AVGX","REGR_AVGY","REGR_COUNT","REGR_INTERCEPT","REGR_R2","REGR_SLOPE","REGR_SXX","REGR_SXY","REGR_SYY","RELEASE","RENAME","REPEAT","RESET","RESIGNAL","RESTART","RESTRICT","RESULT","RESULT_SET_LOCATOR","RETURN","RETURNS","REVOKE","RIGHT","ROLE","ROLLBACK","ROLLUP","ROUND_CEILING","ROUND_DOWN","ROUND_FLOOR","ROUND_HALF_DOWN","ROUND_HALF_EVEN","ROUND_HALF_UP","ROUND_UP","ROUTINE","ROW","ROWNUMBER","ROWS","ROWSET","ROW_NUMBER","RRN","RUN","SAVEPOINT","SCHEMA","SCOPE","SCRATCHPAD","SCROLL","SEARCH","SECOND","SECONDS","SECQTY","SECURITY","SENSITIVE","SEQUENCE","SESSION","SESSION_USER","SIGNAL","SIMILAR","SIMPLE","SMALLINT","SNAN","SOME","SOURCE","SPECIFIC","SPECIFICTYPE","SQL","SQLEXCEPTION","SQLID","SQLSTATE","SQLWARNING","SQRT","STACKED","STANDARD","START","STARTING","STATEMENT","STATIC","STATMENT","STAY","STDDEV_POP","STDDEV_SAMP","STOGROUP","STORES","STYLE","SUBMULTISET","SUBSTRING","SUM","SUMMARY","SYMMETRIC","SYNONYM","SYSFUN","SYSIBM","SYSPROC","SYSTEM","SYSTEM_USER","TABLE","TABLESAMPLE","TABLESPACE","THEN","TIME","TIMESTAMP","TIMEZONE_HOUR","TIMEZONE_MINUTE","TO","TRAILING","TRANSACTION","TRANSLATE","TRANSLATION","TREAT","TRIGGER","TRIM","TRUE","TRUNCATE","TYPE","UESCAPE","UNDO","UNIQUE","UNKNOWN","UNNEST","UNTIL","UPPER","USAGE","USER","USING","VALIDPROC","VALUE","VARCHAR","VARIABLE","VARIANT","VARYING","VAR_POP","VAR_SAMP","VCAT","VERSION","VIEW","VOLATILE","VOLUMES","WHEN","WHENEVER","WHILE","WIDTH_BUCKET","WINDOW","WITH","WITHIN","WITHOUT","WLM","WRITE","XMLELEMENT","XMLEXISTS","XMLNAMESPACES","YEAR","YEARS"],O=["ADD","AFTER","ALTER COLUMN","ALTER TABLE","DELETE FROM","EXCEPT","FETCH FIRST","FROM","GROUP BY","GO","HAVING","INSERT INTO","INTERSECT","LIMIT","ORDER BY","SELECT","SET CURRENT SCHEMA","SET SCHEMA","SET","UNION ALL","UPDATE","VALUES","WHERE"],i=["AND","CROSS JOIN","INNER JOIN","JOIN","LEFT JOIN","LEFT OUTER JOIN","OR","OUTER JOIN","RIGHT JOIN","RIGHT OUTER JOIN"],S=void 0,u=function(){function e(E){(0,T["default"])(this,e),this.cfg=E}return e.prototype.format=function(e){return S||(S=new A["default"]({reservedWords:I,reservedToplevelWords:O,reservedNewlineWords:i,stringTypes:['""',"''","``","[]"],openParens:["("],closeParens:[")"],indexedPlaceholderTypes:["?"],namedPlaceholderTypes:[":"],lineCommentTypes:["--"],specialWordChars:["#","@"]})),new o["default"](this.cfg,S).format(e)},e}();E["default"]=u,e.exports=E["default"]},function(e,E,t){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}E.__esModule=!0;var r=t(1),T=n(r),R=t(4),o=n(R),N=t(5),A=n(N),I=["ALL","ALTER","ANALYZE","AND","ANY","ARRAY","AS","ASC","BEGIN","BETWEEN","BINARY","BOOLEAN","BREAK","BUCKET","BUILD","BY","CALL","CASE","CAST","CLUSTER","COLLATE","COLLECTION","COMMIT","CONNECT","CONTINUE","CORRELATE","COVER","CREATE","DATABASE","DATASET","DATASTORE","DECLARE","DECREMENT","DELETE","DERIVED","DESC","DESCRIBE","DISTINCT","DO","DROP","EACH","ELEMENT","ELSE","END","EVERY","EXCEPT","EXCLUDE","EXECUTE","EXISTS","EXPLAIN","FALSE","FETCH","FIRST","FLATTEN","FOR","FORCE","FROM","FUNCTION","GRANT","GROUP","GSI","HAVING","IF","IGNORE","ILIKE","IN","INCLUDE","INCREMENT","INDEX","INFER","INLINE","INNER","INSERT","INTERSECT","INTO","IS","JOIN","KEY","KEYS","KEYSPACE","KNOWN","LAST","LEFT","LET","LETTING","LIKE","LIMIT","LSM","MAP","MAPPING","MATCHED","MATERIALIZED","MERGE","MINUS","MISSING","NAMESPACE","NEST","NOT","NULL","NUMBER","OBJECT","OFFSET","ON","OPTION","OR","ORDER","OUTER","OVER","PARSE","PARTITION","PASSWORD","PATH","POOL","PREPARE","PRIMARY","PRIVATE","PRIVILEGE","PROCEDURE","PUBLIC","RAW","REALM","REDUCE","RENAME","RETURN","RETURNING","REVOKE","RIGHT","ROLE","ROLLBACK","SATISFIES","SCHEMA","SELECT","SELF","SEMI","SET","SHOW","SOME","START","STATISTICS","STRING","SYSTEM","THEN","TO","TRANSACTION","TRIGGER","TRUE","TRUNCATE","UNDER","UNION","UNIQUE","UNKNOWN","UNNEST","UNSET","UPDATE","UPSERT","USE","USER","USING","VALIDATE","VALUE","VALUED","VALUES","VIA","VIEW","WHEN","WHERE","WHILE","WITH","WITHIN","WORK","XOR"],O=["DELETE FROM","EXCEPT ALL","EXCEPT","EXPLAIN DELETE FROM","EXPLAIN UPDATE","EXPLAIN UPSERT","FROM","GROUP BY","HAVING","INFER","INSERT INTO","INTERSECT ALL","INTERSECT","LET","LIMIT","MERGE","NEST","ORDER BY","PREPARE","SELECT","SET CURRENT SCHEMA","SET SCHEMA","SET","UNION ALL","UNION","UNNEST","UPDATE","UPSERT","USE KEYS","VALUES","WHERE"],i=["AND","INNER JOIN","JOIN","LEFT JOIN","LEFT OUTER JOIN","OR","OUTER JOIN","RIGHT JOIN","RIGHT OUTER JOIN","XOR"],S=void 0,u=function(){function e(E){(0,T["default"])(this,e),this.cfg=E}return e.prototype.format=function(e){return S||(S=new A["default"]({reservedWords:I,reservedToplevelWords:O,reservedNewlineWords:i,stringTypes:['""',"''","``"],openParens:["(","[","{"],closeParens:[")","]","}"],namedPlaceholderTypes:["$"],lineCommentTypes:["#","--"]})),new o["default"](this.cfg,S).format(e)},e}();E["default"]=u,e.exports=E["default"]},function(e,E,t){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}E.__esModule=!0;var r=t(1),T=n(r),R=t(4),o=n(R),N=t(5),A=n(N),I=["A","ACCESSIBLE","AGENT","AGGREGATE","ALL","ALTER","ANY","ARRAY","AS","ASC","AT","ATTRIBUTE","AUTHID","AVG","BETWEEN","BFILE_BASE","BINARY_INTEGER","BINARY","BLOB_BASE","BLOCK","BODY","BOOLEAN","BOTH","BOUND","BULK","BY","BYTE","C","CALL","CALLING","CASCADE","CASE","CHAR_BASE","CHAR","CHARACTER","CHARSET","CHARSETFORM","CHARSETID","CHECK","CLOB_BASE","CLONE","CLOSE","CLUSTER","CLUSTERS","COALESCE","COLAUTH","COLLECT","COLUMNS","COMMENT","COMMIT","COMMITTED","COMPILED","COMPRESS","CONNECT","CONSTANT","CONSTRUCTOR","CONTEXT","CONTINUE","CONVERT","COUNT","CRASH","CREATE","CREDENTIAL","CURRENT","CURRVAL","CURSOR","CUSTOMDATUM","DANGLING","DATA","DATE_BASE","DATE","DAY","DECIMAL","DEFAULT","DEFINE","DELETE","DESC","DETERMINISTIC","DIRECTORY","DISTINCT","DO","DOUBLE","DROP","DURATION","ELEMENT","ELSIF","EMPTY","ESCAPE","EXCEPTIONS","EXCLUSIVE","EXECUTE","EXISTS","EXIT","EXTENDS","EXTERNAL","EXTRACT","FALSE","FETCH","FINAL","FIRST","FIXED","FLOAT","FOR","FORALL","FORCE","FROM","FUNCTION","GENERAL","GOTO","GRANT","GROUP","HASH","HEAP","HIDDEN","HOUR","IDENTIFIED","IF","IMMEDIATE","IN","INCLUDING","INDEX","INDEXES","INDICATOR","INDICES","INFINITE","INSTANTIABLE","INT","INTEGER","INTERFACE","INTERVAL","INTO","INVALIDATE","IS","ISOLATION","JAVA","LANGUAGE","LARGE","LEADING","LENGTH","LEVEL","LIBRARY","LIKE","LIKE2","LIKE4","LIKEC","LIMITED","LOCAL","LOCK","LONG","MAP","MAX","MAXLEN","MEMBER","MERGE","MIN","MINUS","MINUTE","MLSLABEL","MOD","MODE","MONTH","MULTISET","NAME","NAN","NATIONAL","NATIVE","NATURAL","NATURALN","NCHAR","NEW","NEXTVAL","NOCOMPRESS","NOCOPY","NOT","NOWAIT","NULL","NULLIF","NUMBER_BASE","NUMBER","OBJECT","OCICOLL","OCIDATE","OCIDATETIME","OCIDURATION","OCIINTERVAL","OCILOBLOCATOR","OCINUMBER","OCIRAW","OCIREF","OCIREFCURSOR","OCIROWID","OCISTRING","OCITYPE","OF","OLD","ON","ONLY","OPAQUE","OPEN","OPERATOR","OPTION","ORACLE","ORADATA","ORDER","ORGANIZATION","ORLANY","ORLVARY","OTHERS","OUT","OVERLAPS","OVERRIDING","PACKAGE","PARALLEL_ENABLE","PARAMETER","PARAMETERS","PARENT","PARTITION","PASCAL","PCTFREE","PIPE","PIPELINED","PLS_INTEGER","PLUGGABLE","POSITIVE","POSITIVEN","PRAGMA","PRECISION","PRIOR","PRIVATE","PROCEDURE","PUBLIC","RAISE","RANGE","RAW","READ","REAL","RECORD","REF","REFERENCE","RELEASE","RELIES_ON","REM","REMAINDER","RENAME","RESOURCE","RESULT_CACHE","RESULT","RETURN","RETURNING","REVERSE","REVOKE","ROLLBACK","ROW","ROWID","ROWNUM","ROWTYPE","SAMPLE","SAVE","SAVEPOINT","SB1","SB2","SB4","SECOND","SEGMENT","SELF","SEPARATE","SEQUENCE","SERIALIZABLE","SHARE","SHORT","SIZE_T","SIZE","SMALLINT","SOME","SPACE","SPARSE","SQL","SQLCODE","SQLDATA","SQLERRM","SQLNAME","SQLSTATE","STANDARD","START","STATIC","STDDEV","STORED","STRING","STRUCT","STYLE","SUBMULTISET","SUBPARTITION","SUBSTITUTABLE","SUBTYPE","SUCCESSFUL","SUM","SYNONYM","SYSDATE","TABAUTH","TABLE","TDO","THE","THEN","TIME","TIMESTAMP","TIMEZONE_ABBR","TIMEZONE_HOUR","TIMEZONE_MINUTE","TIMEZONE_REGION","TO","TRAILING","TRANSACTION","TRANSACTIONAL","TRIGGER","TRUE","TRUSTED","TYPE","UB1","UB2","UB4","UID","UNDER","UNIQUE","UNPLUG","UNSIGNED","UNTRUSTED","USE","USER","USING","VALIDATE","VALIST","VALUE","VARCHAR","VARCHAR2","VARIABLE","VARIANCE","VARRAY","VARYING","VIEW","VIEWS","VOID","WHENEVER","WHILE","WITH","WORK","WRAPPED","WRITE","YEAR","ZONE"],O=["ADD","ALTER COLUMN","ALTER TABLE","BEGIN","CONNECT BY","DECLARE","DELETE FROM","DELETE","END","EXCEPT","EXCEPTION","FETCH FIRST","FROM","GROUP BY","HAVING","INSERT INTO","INSERT","INTERSECT","LIMIT","LOOP","MODIFY","ORDER BY","SELECT","SET CURRENT SCHEMA","SET SCHEMA","SET","START WITH","UNION ALL","UNION","UPDATE","VALUES","WHERE"],i=["AND","CROSS APPLY","CROSS JOIN","ELSE","END","INNER JOIN","JOIN","LEFT JOIN","LEFT OUTER JOIN","OR","OUTER APPLY","OUTER JOIN","RIGHT JOIN","RIGHT OUTER JOIN","WHEN","XOR"],S=void 0,u=function(){function e(E){(0,T["default"])(this,e),this.cfg=E}return e.prototype.format=function(e){return S||(S=new A["default"]({reservedWords:I,reservedToplevelWords:O,reservedNewlineWords:i,stringTypes:['""',"N''","''","``"],openParens:["(","CASE"],closeParens:[")","END"],indexedPlaceholderTypes:["?"],namedPlaceholderTypes:[":"],lineCommentTypes:["--"],specialWordChars:["_","$","#",".","@"]})),new o["default"](this.cfg,S).format(e)},e}();E["default"]=u,e.exports=E["default"]},function(e,E,t){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}E.__esModule=!0;var r=t(1),T=n(r),R=t(4),o=n(R),N=t(5),A=n(N),I=["ACCESSIBLE","ACTION","AGAINST","AGGREGATE","ALGORITHM","ALL","ALTER","ANALYSE","ANALYZE","AS","ASC","AUTOCOMMIT","AUTO_INCREMENT","BACKUP","BEGIN","BETWEEN","BINLOG","BOTH","CASCADE","CASE","CHANGE","CHANGED","CHARACTER SET","CHARSET","CHECK","CHECKSUM","COLLATE","COLLATION","COLUMN","COLUMNS","COMMENT","COMMIT","COMMITTED","COMPRESSED","CONCURRENT","CONSTRAINT","CONTAINS","CONVERT","CREATE","CROSS","CURRENT_TIMESTAMP","DATABASE","DATABASES","DAY","DAY_HOUR","DAY_MINUTE","DAY_SECOND","DEFAULT","DEFINER","DELAYED","DELETE","DESC","DESCRIBE","DETERMINISTIC","DISTINCT","DISTINCTROW","DIV","DO","DROP","DUMPFILE","DUPLICATE","DYNAMIC","ELSE","ENCLOSED","END","ENGINE","ENGINES","ENGINE_TYPE","ESCAPE","ESCAPED","EVENTS","EXEC","EXECUTE","EXISTS","EXPLAIN","EXTENDED","FAST","FETCH","FIELDS","FILE","FIRST","FIXED","FLUSH","FOR","FORCE","FOREIGN","FULL","FULLTEXT","FUNCTION","GLOBAL","GRANT","GRANTS","GROUP_CONCAT","HEAP","HIGH_PRIORITY","HOSTS","HOUR","HOUR_MINUTE","HOUR_SECOND","IDENTIFIED","IF","IFNULL","IGNORE","IN","INDEX","INDEXES","INFILE","INSERT","INSERT_ID","INSERT_METHOD","INTERVAL","INTO","INVOKER","IS","ISOLATION","KEY","KEYS","KILL","LAST_INSERT_ID","LEADING","LEVEL","LIKE","LINEAR","LINES","LOAD","LOCAL","LOCK","LOCKS","LOGS","LOW_PRIORITY","MARIA","MASTER","MASTER_CONNECT_RETRY","MASTER_HOST","MASTER_LOG_FILE","MATCH","MAX_CONNECTIONS_PER_HOUR","MAX_QUERIES_PER_HOUR","MAX_ROWS","MAX_UPDATES_PER_HOUR","MAX_USER_CONNECTIONS","MEDIUM","MERGE","MINUTE","MINUTE_SECOND","MIN_ROWS","MODE","MODIFY","MONTH","MRG_MYISAM","MYISAM","NAMES","NATURAL","NOT","NOW()","NULL","OFFSET","ON DELETE","ON UPDATE","ON","ONLY","OPEN","OPTIMIZE","OPTION","OPTIONALLY","OUTFILE","PACK_KEYS","PAGE","PARTIAL","PARTITION","PARTITIONS","PASSWORD","PRIMARY","PRIVILEGES","PROCEDURE","PROCESS","PROCESSLIST","PURGE","QUICK","RAID0","RAID_CHUNKS","RAID_CHUNKSIZE","RAID_TYPE","RANGE","READ","READ_ONLY","READ_WRITE","REFERENCES","REGEXP","RELOAD","RENAME","REPAIR","REPEATABLE","REPLACE","REPLICATION","RESET","RESTORE","RESTRICT","RETURN","RETURNS","REVOKE","RLIKE","ROLLBACK","ROW","ROWS","ROW_FORMAT","SECOND","SECURITY","SEPARATOR","SERIALIZABLE","SESSION","SHARE","SHOW","SHUTDOWN","SLAVE","SONAME","SOUNDS","SQL","SQL_AUTO_IS_NULL","SQL_BIG_RESULT","SQL_BIG_SELECTS","SQL_BIG_TABLES","SQL_BUFFER_RESULT","SQL_CACHE","SQL_CALC_FOUND_ROWS","SQL_LOG_BIN","SQL_LOG_OFF","SQL_LOG_UPDATE","SQL_LOW_PRIORITY_UPDATES","SQL_MAX_JOIN_SIZE","SQL_NO_CACHE","SQL_QUOTE_SHOW_CREATE","SQL_SAFE_UPDATES","SQL_SELECT_LIMIT","SQL_SLAVE_SKIP_COUNTER","SQL_SMALL_RESULT","SQL_WARNINGS","START","STARTING","STATUS","STOP","STORAGE","STRAIGHT_JOIN","STRING","STRIPED","SUPER","TABLE","TABLES","TEMPORARY","TERMINATED","THEN","TO","TRAILING","TRANSACTIONAL","TRUE","TRUNCATE","TYPE","TYPES","UNCOMMITTED","UNIQUE","UNLOCK","UNSIGNED","USAGE","USE","USING","VARIABLES","VIEW","WHEN","WITH","WORK","WRITE","YEAR_MONTH"],O=["ADD","AFTER","ALTER COLUMN","ALTER TABLE","DELETE FROM","EXCEPT","FETCH FIRST","FROM","GROUP BY","GO","HAVING","INSERT INTO","INSERT","INTERSECT","LIMIT","MODIFY","ORDER BY","SELECT","SET CURRENT SCHEMA","SET SCHEMA","SET","UNION ALL","UNION","UPDATE","VALUES","WHERE"],i=["AND","CROSS APPLY","CROSS JOIN","ELSE","INNER JOIN","JOIN","LEFT JOIN","LEFT OUTER JOIN","OR","OUTER APPLY","OUTER JOIN","RIGHT JOIN","RIGHT OUTER JOIN","WHEN","XOR"],S=void 0,u=function(){function e(E){(0,T["default"])(this,e),this.cfg=E}return e.prototype.format=function(e){return S||(S=new A["default"]({reservedWords:I,reservedToplevelWords:O,reservedNewlineWords:i,stringTypes:['""',"N''","''","``","[]"],openParens:["(","CASE"],closeParens:[")","END"],indexedPlaceholderTypes:["?"],namedPlaceholderTypes:["@",":"],lineCommentTypes:["#","--"]})),new o["default"](this.cfg,S).format(e)},e}();E["default"]=u,e.exports=E["default"]},function(e,E,t){var n=t(3),r=t(2),T=n(r,"DataView");e.exports=T},function(e,E,t){var n=t(3),r=t(2),T=n(r,"Map");e.exports=T},function(e,E,t){var n=t(3),r=t(2),T=n(r,"Promise");e.exports=T},function(e,E,t){var n=t(3),r=t(2),T=n(r,"Set");e.exports=T},function(e,E,t){var n=t(2),r=n.Symbol;e.exports=r},function(e,E,t){var n=t(3),r=t(2),T=n(r,"WeakMap");e.exports=T},function(e,E){function t(e){return e.split("")}e.exports=t},function(e,E){function t(e,E,t,n){for(var r=e.length,T=t+(n?1:-1);n?T--:++T<r;)if(E(e[T],T,e))return T;
return-1}e.exports=t},function(e,E){function t(e){return r.call(e)}var n=Object.prototype,r=n.toString;e.exports=t},function(e,E,t){function n(e,E,t){return E===E?R(e,E,t):r(e,T,t)}var r=t(29),T=t(32),R=t(49);e.exports=n},function(e,E){function t(e){return e!==e}e.exports=t},function(e,E,t){function n(e){if(!R(e)||T(e))return!1;var E=r(e)?u:A;return E.test(o(e))}var r=t(12),T=t(45),R=t(6),o=t(11),N=/[\\^$.*+?()[\]{}|]/g,A=/^\[object .+?Constructor\]$/,I=Function.prototype,O=Object.prototype,i=I.toString,S=O.hasOwnProperty,u=RegExp("^"+i.call(S).replace(N,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");e.exports=n},function(e,E){function t(e,E){var t="";if(!e||1>E||E>n)return t;do E%2&&(t+=e),E=r(E/2),E&&(e+=e);while(E);return t}var n=9007199254740991,r=Math.floor;e.exports=t},function(e,E){function t(e,E,t){var n=-1,r=e.length;0>E&&(E=-E>r?0:r+E),t=t>r?r:t,0>t&&(t+=r),r=E>t?0:t-E>>>0,E>>>=0;for(var T=Array(r);++n<r;)T[n]=e[n+E];return T}e.exports=t},function(e,E,t){function n(e,E,t){var n=e.length;return t=void 0===t?n:t,E||n>t?r(e,E,t):e}var r=t(35);e.exports=n},function(e,E,t){function n(e,E){for(var t=e.length;t--&&r(E,e[t],0)>-1;);return t}var r=t(31);e.exports=n},function(e,E,t){var n=t(2),r=n["__core-js_shared__"];e.exports=r},function(e,E){(function(E){var t="object"==typeof E&&E&&E.Object===Object&&E;e.exports=t}).call(E,function(){return this}())},function(e,E,t){var n=t(22),r=t(23),T=t(24),R=t(25),o=t(27),N=t(30),A=t(11),I="[object Map]",O="[object Object]",i="[object Promise]",S="[object Set]",u="[object WeakMap]",L="[object DataView]",C=Object.prototype,s=C.toString,a=A(n),f=A(r),c=A(T),p=A(R),l=A(o),D=N;(n&&D(new n(new ArrayBuffer(1)))!=L||r&&D(new r)!=I||T&&D(T.resolve())!=i||R&&D(new R)!=S||o&&D(new o)!=u)&&(D=function(e){var E=s.call(e),t=E==O?e.constructor:void 0,n=t?A(t):void 0;if(n)switch(n){case a:return L;case f:return I;case c:return i;case p:return S;case l:return u}return E}),e.exports=D},function(e,E){function t(e,E){return null==e?void 0:e[E]}e.exports=t},function(e,E){function t(e){return N.test(e)}var n="\\ud800-\\udfff",r="\\u0300-\\u036f\\ufe20-\\ufe23",T="\\u20d0-\\u20f0",R="\\ufe0e\\ufe0f",o="\\u200d",N=RegExp("["+o+n+r+T+R+"]");e.exports=t},function(e,E){function t(e,E){return E=null==E?n:E,!!E&&("number"==typeof e||r.test(e))&&e>-1&&e%1==0&&E>e}var n=9007199254740991,r=/^(?:0|[1-9]\d*)$/;e.exports=t},function(e,E,t){function n(e,E,t){if(!o(t))return!1;var n=typeof E;return!!("number"==n?T(t)&&R(E,t.length):"string"==n&&E in t)&&r(t[E],e)}var r=t(52),T=t(8),R=t(43),o=t(6);e.exports=n},function(e,E,t){function n(e){return!!T&&T in e}var r=t(38),T=function(){var e=/[^.]+$/.exec(r&&r.keys&&r.keys.IE_PROTO||"");return e?"Symbol(src)_1."+e:""}();e.exports=n},function(e,E){function t(e){var E=e&&e.constructor,t="function"==typeof E&&E.prototype||n;return e===t}var n=Object.prototype;e.exports=t},function(e,E,t){var n=t(48),r=n(Object.keys,Object);e.exports=r},function(e,E){function t(e,E){return function(t){return e(E(t))}}e.exports=t},function(e,E){function t(e,E,t){for(var n=t-1,r=e.length;++n<r;)if(e[n]===E)return n;return-1}e.exports=t},function(e,E,t){function n(e){return T(e)?R(e):r(e)}var r=t(28),T=t(42),R=t(51);e.exports=n},function(e,E){function t(e){return e.match(c)||[]}var n="\\ud800-\\udfff",r="\\u0300-\\u036f\\ufe20-\\ufe23",T="\\u20d0-\\u20f0",R="\\ufe0e\\ufe0f",o="["+n+"]",N="["+r+T+"]",A="\\ud83c[\\udffb-\\udfff]",I="(?:"+N+"|"+A+")",O="[^"+n+"]",i="(?:\\ud83c[\\udde6-\\uddff]){2}",S="[\\ud800-\\udbff][\\udc00-\\udfff]",u="\\u200d",L=I+"?",C="["+R+"]?",s="(?:"+u+"(?:"+[O,i,S].join("|")+")"+C+L+")*",a=C+L+s,f="(?:"+[O+N+"?",N,i,S,o].join("|")+")",c=RegExp(A+"(?="+A+")|"+f+a,"g");e.exports=t},function(e,E){function t(e,E){return e===E||e!==e&&E!==E}e.exports=t},function(e,E,t){function n(e){return e=r(e),e&&R.test(e)?e.replace(T,"\\$&"):e}var r=t(9),T=/[\\^$.*+?()[\]{}|]/g,R=RegExp(T.source);e.exports=n},function(e,E,t){function n(e){return r(e)&&o.call(e,"callee")&&(!A.call(e,"callee")||N.call(e)==T)}var r=t(56),T="[object Arguments]",R=Object.prototype,o=R.hasOwnProperty,N=R.toString,A=R.propertyIsEnumerable;e.exports=n},function(e,E){var t=Array.isArray;e.exports=t},function(e,E,t){function n(e){return T(e)&&r(e)}var r=t(8),T=t(13);e.exports=n},function(e,E,t){(function(e){var n=t(2),r=t(62),T="object"==typeof E&&E&&!E.nodeType&&E,R=T&&"object"==typeof e&&e&&!e.nodeType&&e,o=R&&R.exports===T,N=o?n.Buffer:void 0,A=N?N.isBuffer:void 0,I=A||r;e.exports=I}).call(E,t(67)(e))},function(e,E,t){function n(e){if(o(e)&&(R(e)||"string"==typeof e||"function"==typeof e.splice||N(e)||T(e)))return!e.length;var E=r(e);if(E==O||E==i)return!e.size;if(A(e))return!I(e).length;for(var t in e)if(u.call(e,t))return!1;return!0}var r=t(40),T=t(54),R=t(55),o=t(8),N=t(57),A=t(46),I=t(47),O="[object Map]",i="[object Set]",S=Object.prototype,u=S.hasOwnProperty;e.exports=n},function(e,E){function t(e){return"number"==typeof e&&e>-1&&e%1==0&&n>=e}var n=9007199254740991;e.exports=t},function(e,E){function t(e){var E=e?e.length:0;return E?e[E-1]:void 0}e.exports=t},function(e,E,t){function n(e,E,t){return E=(t?T(e,E,t):void 0===E)?1:R(E),r(o(e),E)}var r=t(34),T=t(44),R=t(64),o=t(9);e.exports=n},function(e,E){function t(){return!1}e.exports=t},function(e,E,t){function n(e){if(!e)return 0===e?e:0;if(e=r(e),e===T||e===-T){var E=0>e?-1:1;return E*R}return e===e?e:0}var r=t(65),T=1/0,R=1.7976931348623157e308;e.exports=n},function(e,E,t){function n(e){var E=r(e),t=E%1;return E===E?t?E-t:E:0}var r=t(63);e.exports=n},function(e,E,t){function n(e){if("number"==typeof e)return e;if(T(e))return R;if(r(e)){var E="function"==typeof e.valueOf?e.valueOf():e;e=r(E)?E+"":E}if("string"!=typeof e)return 0===e?e:+e;e=e.replace(o,"");var t=A.test(e);return t||I.test(e)?O(e.slice(2),t?2:8):N.test(e)?R:+e}var r=t(6),T=t(14),R=NaN,o=/^\s+|\s+$/g,N=/^[-+]0x[0-9a-f]+$/i,A=/^0b[01]+$/i,I=/^0o[0-7]+$/i,O=parseInt;e.exports=n},function(e,E,t){function n(e,E,t){if(e=N(e),e&&(t||void 0===E))return e.replace(A,"");if(!e||!(E=r(E)))return e;var n=o(e),I=R(n,o(E))+1;return T(n,0,I).join("")}var r=t(10),T=t(36),R=t(37),o=t(50),N=t(9),A=/\s+$/;e.exports=n},function(e,E){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children=[],e.webpackPolyfill=1),e}}])});
function escape2Html(str) {
var arrEntities = {'lt': '<', 'gt': '>', 'nbsp': '', 'amp': '&', 'quot': '"'};
return str.replace(/&(lt|gt|nbsp|amp|quot);/ig, function (all, t) {
return arrEntities[t];
});
}
function load() {
let codeList = document.getElementsByClassName('language-sql');
for (let i = 0 ;i<codeList.length;i++) {
codeList[i].innerHTML = window.sqlFormatter.format(escape2Html(codeList[i].innerHTML))
}
};
</script>
<style id="soar_md">
a:link,a:visited{text-decoration:none}h3,h4{margin-top:2em}h5,h6{margin-top:20px}h3,h4,h5,h6{margin-bottom:.5em;color:#000}body,h1,h2,h3,h4,h5,h6{color:#000}ol,ul{margin:0 0 0 30px;padding:0 0 12px 6px}ol,ol ol{list-style-position:outside}table td p,table th p{margin-bottom:0}input,select{vertical-align:middle;padding:0}h5,h6,input,select{padding:0}hr,table,textarea{width:100%}body{margin:20px auto;width:800px;background-color:#fff;font:13px "Myriad Pro","Lucida Grande",Lucida,Verdana,sans-serif}h1,table th p{font-weight:700}a:link{color:#00f}a:visited{color:#00a}a:active,a:hover{color:#f60;text-decoration:underline}* html code,* html pre{font-size:101%}code,pre{font-size:11px;font-family:monaco,courier,consolas,monospace}pre{border:1px solid #c7cfd5;background:#f1f5f9;margin:20px 0;padding:8px;text-align:left}hr{color:#919699;size:1;noshade:"noshade"}h1,h2,h3,h4,h5,h6{font-family:"Myriad Pro","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:700}h1{margin-top:1em;margin-bottom:25px;font-size:30px}h2{margin-top:2.5em;font-size:24px;padding-bottom:2px;border-bottom:1px solid #919699}h3{font-size:17px}h4{font-size:15px}h5{font-size:13px}h6{font-size:11px}table td,table th{font-size:12px;border-bottom:1px solid #919699;border-right:1px solid #919699}p{margin-top:0;margin-bottom:10px}ul{list-style:square}li{margin-top:7px}ol{list-style-type:decimal}ol ol{list-style-type:lower-alpha;margin:7px 0 0 30px;padding:0 0 0 10px}ul ul{margin-left:40px;padding:0 0 0 6px}li>p{display:inline}li>a+p,li>p+p{display:block}table{border-top:1px solid #919699;border-left:1px solid #919699;border-spacing:0}table th{padding:4px 8px;background:#E2E2E2}table td{padding:8px;vertical-align:top}table td p+p,table td p+p+p{margin-top:5px}form{margin:0}button{margin:3px 0 10px}input{margin:0 0 5px}select{margin:0 0 3px}textarea{margin:0 0 10px}
</style>
</head>
<body onload=load()>
<h1>Query: 687D590364E29465</h1>
<p>★ ★ ★ ☆ ☆ 75分</p>
<pre><code class="language-sql">select * from film
</code></pre>
<h2>最外层 SELECT 未指定 WHERE 条件</h2>
<ul>
<li><p><strong>Item:</strong> CLA.001</p></li>
<li><p><strong>Severity:</strong> L4</p></li>
<li><p><strong>Content:</strong> SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。</p></li>
</ul>
<h2>不建议使用 SELECT * 类型查询</h2>
<ul>
<li><p><strong>Item:</strong> COL.001</p></li>
<li><p><strong>Severity:</strong> L1</p></li>
<li><p><strong>Content:</strong> 当表结构变更时,使用 * 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。</p></li>
</ul>
{
"687D590364E29465": {
"CLA.001": {
"Item": "CLA.001",
"Severity": "L4",
"Summary": "最外层 SELECT 未指定 WHERE 条件",
"Content": "SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。",
"Case": "select id from tbl",
"Position": 0
},
"COL.001": {
"Item": "COL.001",
"Severity": "L1",
"Summary": "不建议使用 SELECT * 类型查询",
"Content": "当表结构变更时,使用 * 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。",
"Case": "select * from tbl where id=1",
"Position": 0
}
}
}
# Query: 687D590364E29465
★ ★ ★ ☆ ☆ 75分
```sql
SELECT
*
FROM
film
```
## 最外层 SELECT 未指定 WHERE 条件
* **Item:** CLA.001
* **Severity:** L4
* **Content:** SELECT 语句没有 WHERE 子句,可能检查比预期更多的行(全表扫描)。对于 SELECT COUNT(\*) 类型的请求如果不要求精度,建议使用 SHOW TABLE STATUS 或 EXPLAIN 替代。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
* **Severity:** L1
* **Content:** 当表结构变更时,使用 \* 通配符选择所有列将导致查询的含义和行为会发生更改,可能导致查询返回更多的数据。
online-dsn:
user: online-test
password: '********'
net: tcp
addr: 192.168.12.200:3307
schema: information_schema
charset: utf8mb4
collation: utf8mb4_general_ci
loc: GMT
tls: dsfsfdsf
server-public-key: AAAAB3NzaC1yc2EAAAADAQABAAABAQC0JFhoEgrl5/51UHlIIlfWwhiJLR/EEeF8enGnY0PnAldLQ8STdWD8Um2BUtVjgE9COl1X3mN4vMvnSm8A6aPn66enHn0hKzwh1GvcuZNTPgeaZyGKWG0kcvbziUjAPsxxvRvvoaUspSkRYAP/9vpq3SImJKuIHCPfjnGMurKV1n7W/QfpmNjUEwYOswDjL1Ik6Jy6Lrzf8T0hQEy+dYoV4zNM0HcROCXFuu1LyG+WTch3FW660BecNT8+c4sVTHuUMXgGot8OUtwgfXrt5ZL5as7cuyKiWsLVrtrtvL3T0ZHlV8qxQ3DT1gqjSw6jBOzyDOx3jwthAbdsWjyK4Oqp
maxallowedpacket: 419437
params:
charset: utf8mb4
timeout: 60
read-timeout: 70
write-timeout: 80
allow-native-passwords: false
allow-old-passwords: true
disable: false
test-dsn:
user: test-user
password: '********'
net: tcp
addr: 192.168.12.34:3309
schema: information_schema
charset: utf8mb4
collation: utf8mb4_general_ci
loc: GMT
tls: aabbbaa
server-public-key: this is a tset serverpublic
maxallowedpacket: 4194309
params:
charset: utf8mb4
timeout: 50
read-timeout: 40
write-timeout: 30
allow-native-passwords: false
allow-old-passwords: true
disable: false
allow-online-as-test: true
drop-test-temporary: false
cleanup-test-database: true
only-syntax-check: true
sampling-statistic-target: 110
sampling: true
sampling-condition: aaa
profiling: true
trace: true
explain: false
delimiter: ;
log-level: 3
log-output: /dev/null
report-type: html
report-css: sdfs
report-javascript: sdfsd
report-title: SQL优化分析报告-test
markdown-extensions: 92
markdown-html-flags: 10
ignore-rules:
- COL.012
rewrite-rules:
- delimiter
- orderbynull
- groupbyconst
- dmlorderby
- having
- star2columns
- insertcolumns
- distinctstar
blacklist: /tmp/blacklist
max-join-table-count: 12
max-group-by-cols-count: 15
max-distinct-count: 7
max-index-cols-count: 2
max-text-cols-count: 3
max-total-rows: 9999991
max-query-cost: 9992
spaghetti-query-length: 2041
allow-drop-index: true
max-in-count: 101
max-index-bytes-percolumn: 762
max-index-bytes: 3073
allow-charsets:
- utf8
- utf8mb4
allow-collates: []
allow-engines:
- innodb
- tokudb
max-index-count: 12
max-column-count: 41
max-value-count: 102
index-prefix: idx_
unique-key-prefix: uk_
max-subquery-depth: 6
max-varchar-length: 1022
column-not-allow-type:
- boolean
min-cardinality: 2
explain-sql-report-type: pretty
explain-type: extended
explain-format: traditional
explain-warn-select-type:
- ""
explain-warn-access-type:
- ALL
explain-max-keys: 31
explain-min-keys: 10
explain-max-rows: 10002
explain-warn-extra:
- Using temporary
- Using filesort
explain-max-filtered: 120
explain-warn-scalability:
- O(log(n))
show-warnings: true
show-last-query-cost: true
query: ""
list-heuristic-rules: true
list-rewrite-rules: true
list-test-sqls: true
list-report-types: true
verbose: true
dry-run: false
max-pretty-sql-length: 1022
...@@ -2,41 +2,139 @@ ...@@ -2,41 +2,139 @@
load test_helper load test_helper
# 1. 检查版本输出格式是否正确
# 2. 检查版本是否为当天编译的
@test "Test soar version" { @test "Test soar version" {
run ${SOAR_BIN} -version run ${SOAR_BIN} -version
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
[ "${lines[0]%% *}" == "Version:" ] [ "${lines[0]%% *}" == "Version:" ]
[ "${lines[1]%% *}" == "Branch:" ] [ "${lines[1]%% *}" == "Branch:" ]
[ "${lines[2]%% *}" == "Compile:" ] [ "${lines[2]%% *}" == "Compile:" ]
[ $(expr "${lines[2]}" : "Compile: $(date +'%Y-%m-%d').*") -ne 0 ] [ $(expr "${lines[2]}" : "Compile: $(date +'%Y-%m-%d').*") -ne 0 ] # 检查当前版本是否为今日编译的
} }
# 3. 无参数执行是否正确
@test "No arguments prints message" { @test "No arguments prints message" {
run ${SOAR_BIN} run ${SOAR_BIN}
[ $status -eq 1 ] [ $status -eq 1 ]
[ "${lines[0]}" == 'Args format error, use --help see how to use it!' ] [ "${lines[0]}" == 'Args format error, use --help see how to use it!' ]
} }
# 4. 检查输出的默认值是否改变 soar -print-config 加log-outpt 是因为日志默认是相对路径
@test "Run default printconfig cases" { @test "Run default printconfig cases" {
${SOAR_BIN} -print-config -log-output=/dev/null > ${BATS_TMP_DIRNAME}/${BATS_TEST_NAME}.golden ${SOAR_BIN} -print-config -log-output=/dev/null > ${BATS_TMP_DIRNAME}/${BATS_TEST_NAME}.golden
run golden_diff run golden_diff
[ $status -eq 0 ] [ $status -eq 0 ]
} }
# 5. soar 使用 config 配置文件路径是否正确
# 13. soar -check-config 数据库连接配置检查 *
# soar 数据库测试(线上、线下、-allow-online-as-test)
@test "Check config cases" { @test "Check config cases" {
run ${SOAR_BIN_ENV} -check-config run ${SOAR_BIN_ENV} -check-config
[ $status -eq 0 ] [ $status -eq 0 ]
[ -z ${output} ] [ -z ${output} ]
} }
# 6. soar 使用配置文件修改默认参数是否正确
# 注意:不启用的配置为默认配置项目
@test "Check the default config of the changes" {
${SOAR_BIN} -config ${BATS_FIXTURE_DIRNAME}/${BATS_TEST_NAME}.golden -print-config -log-output=/dev/null > ${BATS_TMP_DIRNAME}/${BATS_TEST_NAME}.golden
run golden_diff
[ $status -eq 0 ]
}
# 8. 执行 soar -query 为文件时是否正常
@test "Check soar query for input file" {
${SOAR_BIN} -query <(${SOAR_BIN} -list-test-sqls) > ${BATS_TMP_DIRNAME}/${BATS_TEST_NAME}.golden
run golden_diff
[ $status -eq 0 ]
}
# 9. 管道输入 SQL 是否正常
@test "Check soar for pipe input" {
${SOAR_BIN} -list-test-sqls |${SOAR_BIN} > ${BATS_TMP_DIRNAME}/${BATS_TEST_NAME}.golden
run golden_diff
[ $status -eq 0 ]
}
# 10. report 为 json 格式是否正常
@test "Check soar report for json" {
${SOAR_BIN} -query "select * from film" \
-report-type json > ${BATS_TMP_DIRNAME}/${BATS_TEST_NAME}.golden
run golden_diff
[ $status -eq 0 ]
}
# 10. report 为 markdown 格式是否正常
@test "Check soar report for markdown" {
${SOAR_BIN} -query "select * from film" \
-report-type markdown > ${BATS_TMP_DIRNAME}/${BATS_TEST_NAME}.golden
run golden_diff
[ $status -eq 0 ]
}
# 11. report 格式 html 检查
@test "Check soar report for html" {
${SOAR_BIN} -query "select * from film" \
-report-title "soar report check" \
-report-type html > ${BATS_TMP_DIRNAME}/${BATS_TEST_NAME}.golden
run golden_diff
[ $status -eq 0 ]
}
# 12. 黑名单功能是否正常
# soar 的日志和黑名单的相对路径都相对于 soar 的二进制文件路径说的
@test "Check soar blacklist" {
run ${SOAR_BIN} -blacklist ../etc/soar.blacklist -query "show processlist;"
[ $status -eq 0 ]
[ -z ${output} ]
}
# 13. soar -check-config 数据库连接配置检查 *
# 参见 5
# 14. soar -help 检查
@test "Check soar help" {
run ${SOAR_BIN} -help
[ $status -eq 2 ]
[ "${#lines[@]}" -gt 30 ]
}
# 15. soar 数据库测试(线上、线下、-allow-online-as-test)
# 参见 5
# 16. 语法检查(正确)
@test "Syntax Check OK" { @test "Syntax Check OK" {
run ${SOAR_BIN} -query "select * from film" -only-syntax-check run ${SOAR_BIN} -query "select * from film" -only-syntax-check
[ $status -eq 0 ] [ $status -eq 0 ]
[ -z $ouput ] [ -z $ouput ]
} }
# 16. 语法检查(错误)
@test "Syntax Check Error" { @test "Syntax Check Error" {
run ${SOAR_BIN} -query "select * frm film" -only-syntax-check run ${SOAR_BIN} -query "select * frm film" -only-syntax-check
[ $status -eq 1 ] [ $status -eq 1 ]
[ -n $ouput ] [ -n $ouput ]
} }
# 17. dsn 检查
@test "Check soar test dsn root:passwd@host:port/db" {
run ${SOAR_BIN} -online-dsn="root:pase@D@192.168.12.11:3306/testDB" -print-config
[ $(expr "$output" : ".*user: root") -ne 0 ]
[ $(expr "$output" : ".*addr: 192.168.12.11:3306") -ne 0 ]
[ $(expr "$output" : ".*schema: testDB") -ne 0 ]
[ $(expr "$output" : ".*charset: utf8") -ne 0 ]
}
# 18. 日志中是否含有密码
@test "Check log has password" {
${SOAR_BIN_ENV} -query "select * from film" -log-level=7
run grep "1tIsB1g3rt" ${SOAR_BIN}.log
[ ${status} -eq 1 ]
}
# 18. 输出中是否含有密码
@test "Check stdout has password" {
run ${SOAR_BIN_ENV} -query "select * from film" -log-level=7
[ $(expr "$output" : ".*1tIsB1g3rt.*") -eq 0 ]
[ ${status} -eq 0 ]
}
...@@ -6,4 +6,3 @@ load test_helper ...@@ -6,4 +6,3 @@ load test_helper
run ${SOAR_BIN} -query "select * from film where length > 120" run ${SOAR_BIN} -query "select * from film where length > 120"
[ $status -eq 0 ] [ $status -eq 0 ]
} }
...@@ -370,7 +370,51 @@ type ColumnOption struct { ...@@ -370,7 +370,51 @@ type ColumnOption struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *ColumnOption) Restore(ctx *RestoreCtx) error { func (n *ColumnOption) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") switch n.Tp {
case ColumnOptionNoOption:
return nil
case ColumnOptionPrimaryKey:
ctx.WriteKeyWord("PRIMARY KEY")
case ColumnOptionNotNull:
ctx.WriteKeyWord("NOT NULL")
case ColumnOptionAutoIncrement:
ctx.WriteKeyWord("AUTO_INCREMENT")
case ColumnOptionDefaultValue:
ctx.WriteKeyWord("DEFAULT ")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing ColumnOption DefaultValue Expr")
}
case ColumnOptionUniqKey:
ctx.WriteKeyWord("UNIQUE KEY")
case ColumnOptionNull:
ctx.WriteKeyWord("NULL")
case ColumnOptionOnUpdate:
ctx.WriteKeyWord("ON UPDATE ")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing ColumnOption ON UPDATE Expr")
}
case ColumnOptionFulltext:
return errors.New("TiDB Parser ignore the `ColumnOptionFulltext` type now")
case ColumnOptionComment:
ctx.WriteKeyWord("COMMENT ")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing ColumnOption COMMENT Expr")
}
case ColumnOptionGenerated:
ctx.WriteKeyWord("GENERATED ALWAYS AS")
ctx.WritePlain("(")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing ColumnOption GENERATED ALWAYS Expr")
}
ctx.WritePlain(")")
case ColumnOptionReference:
if err := n.Refer.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing ColumnOption ReferenceDef")
}
default:
return errors.New("An error occurred while splicing ColumnOption")
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -489,13 +533,18 @@ func (n *Constraint) Restore(ctx *RestoreCtx) error { ...@@ -489,13 +533,18 @@ func (n *Constraint) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("UNIQUE KEY") ctx.WriteKeyWord("UNIQUE KEY")
case ConstraintUniqIndex: case ConstraintUniqIndex:
ctx.WriteKeyWord("UNIQUE INDEX") ctx.WriteKeyWord("UNIQUE INDEX")
case ConstraintForeignKey:
ctx.WriteKeyWord("FOREIGN KEY")
case ConstraintFulltext: case ConstraintFulltext:
ctx.WriteKeyWord("FULLTEXT") ctx.WriteKeyWord("FULLTEXT")
} }
if n.Tp == ConstraintForeignKey {
ctx.WriteKeyWord("CONSTRAINT ")
if n.Name != "" { if n.Name != "" {
ctx.WriteName(n.Name)
ctx.WritePlain(" ")
}
ctx.WriteKeyWord("FOREIGN KEY ")
} else if n.Name != "" {
ctx.WritePlain(" ") ctx.WritePlain(" ")
ctx.WriteName(n.Name) ctx.WriteName(n.Name)
} }
...@@ -570,7 +619,22 @@ type ColumnDef struct { ...@@ -570,7 +619,22 @@ type ColumnDef struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *ColumnDef) Restore(ctx *RestoreCtx) error { func (n *ColumnDef) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") if err := n.Name.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing ColumnDef Name")
}
if n.Tp != nil {
ctx.WritePlain(" ")
if err := n.Tp.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing ColumnDef Type")
}
}
for i, options := range n.Options {
ctx.WritePlain(" ")
if err := options.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while splicing ColumnDef ColumnOption: [%v]", i)
}
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -613,7 +677,73 @@ type CreateTableStmt struct { ...@@ -613,7 +677,73 @@ type CreateTableStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *CreateTableStmt) Restore(ctx *RestoreCtx) error { func (n *CreateTableStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") ctx.WriteKeyWord("CREATE TABLE ")
if n.IfNotExists {
ctx.WriteKeyWord("IF NOT EXISTS ")
}
if err := n.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing CreateTableStmt Table")
}
ctx.WritePlain(" ")
if n.ReferTable != nil {
ctx.WriteKeyWord("LIKE ")
if err := n.ReferTable.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing CreateTableStmt ReferTable")
}
}
if lenCols := len(n.Cols); lenCols > 0 {
ctx.WritePlain("(")
for i, col := range n.Cols {
if i > 0 {
ctx.WritePlain(",")
}
if err := col.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while splicing CreateTableStmt ColumnDef: [%v]", i)
}
}
for i, constraint := range n.Constraints {
if i > 0 || lenCols >= 1 {
ctx.WritePlain(",")
}
if err := constraint.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while splicing CreateTableStmt Constraints: [%v]", i)
}
}
ctx.WritePlain(")")
}
for i, option := range n.Options {
ctx.WritePlain(" ")
if err := option.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while splicing CreateTableStmt TableOption: [%v]", i)
}
}
if n.Partition != nil {
ctx.WritePlain(" ")
if err := n.Partition.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing CreateTableStmt Partition")
}
}
if n.Select != nil {
switch n.OnDuplicate {
case OnDuplicateCreateTableSelectError:
ctx.WriteKeyWord(" AS ")
case OnDuplicateCreateTableSelectIgnore:
ctx.WriteKeyWord(" IGNORE AS ")
case OnDuplicateCreateTableSelectReplace:
ctx.WriteKeyWord(" REPLACE AS ")
}
if err := n.Select.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing CreateTableStmt Select")
}
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -822,7 +952,59 @@ type CreateViewStmt struct { ...@@ -822,7 +952,59 @@ type CreateViewStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *CreateViewStmt) Restore(ctx *RestoreCtx) error { func (n *CreateViewStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") ctx.WriteKeyWord("CREATE ")
if n.OrReplace {
ctx.WriteKeyWord("OR REPLACE ")
}
ctx.WriteKeyWord("ALGORITHM")
ctx.WritePlain(" = ")
ctx.WriteKeyWord(n.Algorithm.String())
ctx.WriteKeyWord(" DEFINER")
ctx.WritePlain(" = ")
// todo Use n.Definer.Restore(ctx) to replace this part
if n.Definer.CurrentUser {
ctx.WriteKeyWord("current_user")
} else {
ctx.WriteName(n.Definer.Username)
if n.Definer.Hostname != "" {
ctx.WritePlain("@")
ctx.WriteName(n.Definer.Hostname)
}
}
ctx.WriteKeyWord(" SQL SECURITY ")
ctx.WriteKeyWord(n.Security.String())
ctx.WriteKeyWord(" VIEW ")
if err := n.ViewName.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while create CreateViewStmt.ViewName")
}
for i, col := range n.Cols {
if i == 0 {
ctx.WritePlain(" (")
} else {
ctx.WritePlain(",")
}
ctx.WriteName(col.O)
if i == len(n.Cols)-1 {
ctx.WritePlain(")")
}
}
ctx.WriteKeyWord(" AS ")
if err := n.Select.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while create CreateViewStmt.Select")
}
if n.CheckOption != model.CheckOptionCascaded {
ctx.WriteKeyWord(" WITH ")
ctx.WriteKeyWord(n.CheckOption.String())
ctx.WriteKeyWord(" CHECK OPTION")
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -859,7 +1041,36 @@ type CreateIndexStmt struct { ...@@ -859,7 +1041,36 @@ type CreateIndexStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *CreateIndexStmt) Restore(ctx *RestoreCtx) error { func (n *CreateIndexStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") ctx.WriteKeyWord("CREATE ")
if n.Unique {
ctx.WriteKeyWord("UNIQUE ")
}
ctx.WriteKeyWord("INDEX ")
ctx.WriteName(n.IndexName)
ctx.WriteKeyWord(" ON ")
if err := n.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore CreateIndexStmt.Table")
}
ctx.WritePlain(" (")
for i, indexColName := range n.IndexColNames {
if i != 0 {
ctx.WritePlain(", ")
}
if err := indexColName.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore CreateIndexStmt.IndexColNames: [%v]", i)
}
}
ctx.WritePlain(")")
if n.IndexOption.Tp != model.IndexTypeInvalid || n.IndexOption.KeyBlockSize > 0 || n.IndexOption.Comment != "" {
ctx.WritePlain(" ")
if err := n.IndexOption.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore CreateIndexStmt.IndexOption")
}
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -986,6 +1197,103 @@ type TableOption struct { ...@@ -986,6 +1197,103 @@ type TableOption struct {
UintValue uint64 UintValue uint64
} }
func (n *TableOption) Restore(ctx *RestoreCtx) error {
switch n.Tp {
case TableOptionEngine:
ctx.WriteKeyWord("ENGINE ")
ctx.WritePlain("= ")
if n.StrValue != "" {
ctx.WritePlain(n.StrValue)
} else {
ctx.WritePlain("''")
}
case TableOptionCharset:
ctx.WriteKeyWord("DEFAULT CHARACTER SET ")
ctx.WritePlain("= ")
ctx.WriteKeyWord(n.StrValue)
case TableOptionCollate:
ctx.WriteKeyWord("DEFAULT COLLATE ")
ctx.WritePlain("= ")
ctx.WriteKeyWord(n.StrValue)
case TableOptionAutoIncrement:
ctx.WriteKeyWord("AUTO_INCREMENT ")
ctx.WritePlain("= ")
ctx.WritePlainf("%d", n.UintValue)
case TableOptionComment:
ctx.WriteKeyWord("COMMENT ")
ctx.WritePlain("= ")
ctx.WriteString(n.StrValue)
case TableOptionAvgRowLength:
ctx.WriteKeyWord("AVG_ROW_LENGTH ")
ctx.WritePlain("= ")
ctx.WritePlainf("%d", n.UintValue)
case TableOptionCheckSum:
ctx.WriteKeyWord("CHECKSUM ")
ctx.WritePlain("= ")
ctx.WritePlainf("%d", n.UintValue)
case TableOptionCompression:
ctx.WriteKeyWord("COMPRESSION ")
ctx.WritePlain("= ")
ctx.WriteString(n.StrValue)
case TableOptionConnection:
ctx.WriteKeyWord("CONNECTION ")
ctx.WritePlain("= ")
ctx.WriteString(n.StrValue)
case TableOptionPassword:
ctx.WriteKeyWord("PASSWORD ")
ctx.WritePlain("= ")
ctx.WriteString(n.StrValue)
case TableOptionKeyBlockSize:
ctx.WriteKeyWord("KEY_BLOCK_SIZE ")
ctx.WritePlain("= ")
ctx.WritePlainf("%d", n.UintValue)
case TableOptionMaxRows:
ctx.WriteKeyWord("MAX_ROWS ")
ctx.WritePlain("= ")
ctx.WritePlainf("%d", n.UintValue)
case TableOptionMinRows:
ctx.WriteKeyWord("MIN_ROWS ")
ctx.WritePlain("= ")
ctx.WritePlainf("%d", n.UintValue)
case TableOptionDelayKeyWrite:
ctx.WriteKeyWord("DELAY_KEY_WRITE ")
ctx.WritePlain("= ")
ctx.WritePlainf("%d", n.UintValue)
case TableOptionRowFormat:
ctx.WriteKeyWord("ROW_FORMAT ")
ctx.WritePlain("= ")
switch n.UintValue {
case RowFormatDefault:
ctx.WriteKeyWord("DEFAULT")
case RowFormatDynamic:
ctx.WriteKeyWord("DYNAMIC")
case RowFormatFixed:
ctx.WriteKeyWord("FIXED")
case RowFormatCompressed:
ctx.WriteKeyWord("COMPRESSED")
case RowFormatRedundant:
ctx.WriteKeyWord("REDUNDANT")
case RowFormatCompact:
ctx.WriteKeyWord("COMPACT")
default:
return errors.Errorf("invalid TableOption: TableOptionRowFormat: %d", n.UintValue)
}
case TableOptionStatsPersistent:
// TODO: not support
ctx.WritePlain(" /* TableOptionStatsPersistent is not supported */ ")
case TableOptionShardRowID:
ctx.WriteKeyWord("SHARD_ROW_ID_BITS ")
ctx.WritePlain("= ")
ctx.WritePlainf("%d", n.UintValue)
case TableOptionPackKeys:
// TODO: not support
ctx.WritePlain(" /* TableOptionPackKeys is not supported */ ")
default:
return errors.Errorf("invalid TableOption: %d", n.Tp)
}
return nil
}
// ColumnPositionType is the type for ColumnPosition. // ColumnPositionType is the type for ColumnPosition.
type ColumnPositionType int type ColumnPositionType int
...@@ -1072,6 +1380,20 @@ const ( ...@@ -1072,6 +1380,20 @@ const (
// See https://dev.mysql.com/doc/refman/5.7/en/alter-table.html#alter-table-concurrency // See https://dev.mysql.com/doc/refman/5.7/en/alter-table.html#alter-table-concurrency
type LockType byte type LockType byte
func (n LockType) String() string {
switch n {
case LockTypeNone:
return "NONE"
case LockTypeDefault:
return "DEFAULT"
case LockTypeShared:
return "SHARED"
case LockTypeExclusive:
return "EXCLUSIVE"
}
return ""
}
// Lock Types. // Lock Types.
const ( const (
LockTypeNone LockType = iota + 1 LockTypeNone LockType = iota + 1
...@@ -1102,7 +1424,159 @@ type AlterTableSpec struct { ...@@ -1102,7 +1424,159 @@ type AlterTableSpec struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *AlterTableSpec) Restore(ctx *RestoreCtx) error { func (n *AlterTableSpec) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") switch n.Tp {
case AlterTableOption:
switch {
case len(n.Options) == 2 &&
n.Options[0].Tp == TableOptionCharset &&
n.Options[1].Tp == TableOptionCollate:
ctx.WriteKeyWord("CONVERT TO CHARACTER SET ")
ctx.WriteKeyWord(n.Options[0].StrValue)
ctx.WriteKeyWord(" COLLATE ")
ctx.WriteKeyWord(n.Options[1].StrValue)
default:
for i, opt := range n.Options {
if i != 0 {
ctx.WritePlain(", ")
}
if err := opt.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AlterTableSpec.Options[%d]", i)
}
}
}
case AlterTableAddColumns:
ctx.WriteKeyWord("ADD COLUMN ")
if n.Position != nil && len(n.NewColumns) == 1 {
if err := n.NewColumns[0].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AlterTableSpec.NewColumns[%d]", 0)
}
if n.Position.Tp != ColumnPositionNone {
ctx.WritePlain(" ")
}
if err := n.Position.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.Position")
}
} else {
ctx.WritePlain("(")
for i, col := range n.NewColumns {
if i != 0 {
ctx.WritePlain(", ")
}
if err := col.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AlterTableSpec.NewColumns[%d]", i)
}
}
ctx.WritePlain(")")
}
case AlterTableAddConstraint:
ctx.WriteKeyWord("ADD ")
if err := n.Constraint.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.Constraint")
}
case AlterTableDropColumn:
ctx.WriteKeyWord("DROP COLUMN ")
if err := n.OldColumnName.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.OldColumnName")
}
// TODO: RestrictOrCascadeOpt not support
case AlterTableDropPrimaryKey:
ctx.WriteKeyWord("DROP PRIMARY KEY")
case AlterTableDropIndex:
ctx.WriteKeyWord("DROP INDEX ")
ctx.WriteName(n.Name)
case AlterTableDropForeignKey:
ctx.WriteKeyWord("DROP FOREIGN KEY ")
ctx.WriteName(n.Name)
case AlterTableModifyColumn:
ctx.WriteKeyWord("MODIFY COLUMN ")
if err := n.NewColumns[0].Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.NewColumns[0]")
}
if n.Position.Tp != ColumnPositionNone {
ctx.WritePlain(" ")
}
if err := n.Position.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.Position")
}
case AlterTableChangeColumn:
ctx.WriteKeyWord("CHANGE COLUMN ")
if err := n.OldColumnName.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.OldColumnName")
}
ctx.WritePlain(" ")
if err := n.NewColumns[0].Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.NewColumns[0]")
}
if n.Position.Tp != ColumnPositionNone {
ctx.WritePlain(" ")
}
if err := n.Position.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.Position")
}
case AlterTableRenameTable:
ctx.WriteKeyWord("RENAME AS ")
if err := n.NewTable.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.NewTable")
}
case AlterTableAlterColumn:
ctx.WriteKeyWord("ALTER COLUMN ")
if err := n.NewColumns[0].Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.NewColumns[0]")
}
if len(n.NewColumns[0].Options) == 1 {
ctx.WriteKeyWord("SET DEFAULT ")
if err := n.NewColumns[0].Options[0].Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.NewColumns[0].Options[0].Expr")
}
} else {
ctx.WriteKeyWord(" DROP DEFAULT")
}
case AlterTableLock:
ctx.WriteKeyWord("LOCK ")
ctx.WritePlain("= ")
ctx.WriteKeyWord(n.LockType.String())
case AlterTableAlgorithm:
// TODO: not support
ctx.WritePlain(" /* AlterTableAlgorithm is not supported */ ")
case AlterTableRenameIndex:
ctx.WriteKeyWord("RENAME INDEX ")
ctx.WriteName(n.FromKey.O)
ctx.WriteKeyWord(" TO ")
ctx.WriteName(n.ToKey.O)
case AlterTableForce:
// TODO: not support
ctx.WritePlain(" /* AlterTableForce is not supported */ ")
case AlterTableAddPartitions:
ctx.WriteKeyWord("ADD PARTITION")
if n.PartDefinitions != nil {
ctx.WritePlain(" (")
for i, def := range n.PartDefinitions {
if i != 0 {
ctx.WritePlain(", ")
}
if err := def.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AlterTableSpec.PartDefinitions[%d]", i)
}
}
ctx.WritePlain(")")
} else if n.Num != 0 {
ctx.WriteKeyWord(" PARTITIONS ")
ctx.WritePlainf("%d", n.Num)
}
case AlterTableCoalescePartitions:
ctx.WriteKeyWord("COALESCE PARTITION ")
ctx.WritePlainf("%d", n.Num)
case AlterTableDropPartition:
ctx.WriteKeyWord("DROP PARTITION ")
ctx.WriteName(n.Name)
case AlterTableTruncatePartition:
ctx.WriteKeyWord("TRUNCATE PARTITION ")
ctx.WriteName(n.Name)
default:
// TODO: not support
ctx.WritePlainf(" /* AlterTableType(%d) is not supported */ ", n.Tp)
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -1161,7 +1635,21 @@ type AlterTableStmt struct { ...@@ -1161,7 +1635,21 @@ type AlterTableStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *AlterTableStmt) Restore(ctx *RestoreCtx) error { func (n *AlterTableStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") ctx.WriteKeyWord("ALTER TABLE ")
if err := n.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableStmt.Table")
}
for i, spec := range n.Specs {
if i == 0 {
ctx.WritePlain(" ")
} else {
ctx.WritePlain(", ")
}
if err := spec.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AlterTableStmt.Specs[%d]", i)
}
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -1226,6 +1714,28 @@ type PartitionDefinition struct { ...@@ -1226,6 +1714,28 @@ type PartitionDefinition struct {
Comment string Comment string
} }
// Restore implements Node interface.
func (n *PartitionDefinition) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("PARTITION ")
ctx.WriteName(n.Name.O)
if n.LessThan != nil {
ctx.WriteKeyWord(" VALUES LESS THAN ")
ctx.WritePlain("(")
for k, less := range n.LessThan {
if err := less.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore PartitionDefinition.LessThan[%d]", k)
}
}
ctx.WritePlain(")")
}
if n.Comment != "" {
ctx.WriteKeyWord(" COMMENT ")
ctx.WritePlain("= ")
ctx.WriteString(n.Comment)
}
return nil
}
// PartitionOptions specifies the partition options. // PartitionOptions specifies the partition options.
type PartitionOptions struct { type PartitionOptions struct {
Tp model.PartitionType Tp model.PartitionType
...@@ -1234,3 +1744,52 @@ type PartitionOptions struct { ...@@ -1234,3 +1744,52 @@ type PartitionOptions struct {
Definitions []*PartitionDefinition Definitions []*PartitionDefinition
Num uint64 Num uint64
} }
func (n *PartitionOptions) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("PARTITION BY ")
switch n.Tp {
case model.PartitionTypeRange:
ctx.WriteKeyWord("RANGE ")
case model.PartitionTypeHash:
ctx.WriteKeyWord("HASH ")
case model.PartitionTypeList:
return errors.New("TiDB Parser ignore the `PartitionTypeList` type now")
default:
return errors.Errorf("invalid model.PartitionType: %d", n.Tp)
}
ctx.WritePlain("(")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore PartitionOptions Expr")
}
ctx.WritePlain(") ")
for i, col := range n.ColumnNames {
if i > 0 {
ctx.WritePlain(",")
}
if err := col.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while splicing PartitionOptions ColumnName: [%v]", i)
}
}
if n.Num > 0 {
ctx.WriteKeyWord("PARTITIONS ")
ctx.WritePlainf("%d", n.Num)
}
if len(n.Definitions) > 0 {
ctx.WritePlain("(")
for i, def := range n.Definitions {
if i > 0 {
ctx.WritePlain(",")
}
if err := def.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while splicing PartitionOptions Definitions: [%v]", i)
}
}
ctx.WritePlain(")")
}
return nil
}
...@@ -184,6 +184,7 @@ type TableName struct { ...@@ -184,6 +184,7 @@ type TableName struct {
TableInfo *model.TableInfo TableInfo *model.TableInfo
IndexHints []*IndexHint IndexHints []*IndexHint
PartitionNames []model.CIStr
} }
// Restore implements Node interface. // Restore implements Node interface.
...@@ -756,7 +757,110 @@ type SelectStmt struct { ...@@ -756,7 +757,110 @@ type SelectStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *SelectStmt) Restore(ctx *RestoreCtx) error { func (n *SelectStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") ctx.WriteKeyWord("SELECT ")
if n.SelectStmtOpts.Priority > 0 {
ctx.WriteKeyWord(mysql.Priority2Str[n.SelectStmtOpts.Priority])
ctx.WritePlain(" ")
}
if !n.SelectStmtOpts.SQLCache {
ctx.WriteKeyWord("SQL_NO_CACHE ")
}
if n.TableHints != nil && len(n.TableHints) != 0 {
ctx.WritePlain("/*+ ")
for i, tableHint := range n.TableHints {
if err := tableHint.Restore(ctx); err != nil {
errors.Annotatef(err, "An error occurred while restore SelectStmt.TableHints[%d]", i)
}
}
ctx.WritePlain("*/ ")
}
if n.Distinct {
ctx.WriteKeyWord("DISTINCT ")
}
if n.SelectStmtOpts.StraightJoin {
ctx.WriteKeyWord("STRAIGHT_JOIN ")
}
if n.Fields != nil {
for i, field := range n.Fields.Fields {
if i != 0 {
ctx.WritePlain(",")
}
if err := field.Restore(ctx); err != nil {
errors.Annotatef(err, "An error occurred while restore SelectStmt.Fields[%d]", i)
}
}
}
if n.From != nil {
ctx.WriteKeyWord(" FROM ")
if err := n.From.Restore(ctx); err != nil {
errors.Annotate(err, "An error occurred while restore SelectStmt.From")
}
}
if n.From == nil && n.Where != nil {
ctx.WriteKeyWord(" FROM DUAL")
}
if n.Where != nil {
ctx.WriteKeyWord(" WHERE ")
if err := n.Where.Restore(ctx); err != nil {
errors.Annotate(err, "An error occurred while restore SelectStmt.Where")
}
}
if n.GroupBy != nil {
ctx.WritePlain(" ")
if err := n.GroupBy.Restore(ctx); err != nil {
errors.Annotate(err, "An error occurred while restore SelectStmt.GroupBy")
}
}
if n.Having != nil {
ctx.WritePlain(" ")
if err := n.Having.Restore(ctx); err != nil {
errors.Annotate(err, "An error occurred while restore SelectStmt.Having")
}
}
if n.WindowSpecs != nil {
ctx.WriteKeyWord(" WINDOW ")
for i, windowsSpec := range n.WindowSpecs {
if i != 0 {
ctx.WritePlain(",")
}
if err := windowsSpec.Restore(ctx); err != nil {
errors.Annotatef(err, "An error occurred while restore SelectStmt.WindowSpec[%d]", i)
}
}
}
if n.OrderBy != nil {
ctx.WritePlain(" ")
if err := n.OrderBy.Restore(ctx); err != nil {
errors.Annotate(err, "An error occurred while restore SelectStmt.OrderBy")
}
}
if n.Limit != nil {
ctx.WritePlain(" ")
if err := n.Limit.Restore(ctx); err != nil {
errors.Annotate(err, "An error occurred while restore SelectStmt.Limit")
}
}
switch n.LockTp {
case SelectLockInShareMode:
ctx.WriteKeyWord(" LOCK ")
ctx.WriteKeyWord(n.LockTp.String())
case SelectLockForUpdate:
ctx.WritePlain(" ")
ctx.WriteKeyWord(n.LockTp.String())
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -855,7 +959,24 @@ type UnionSelectList struct { ...@@ -855,7 +959,24 @@ type UnionSelectList struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *UnionSelectList) Restore(ctx *RestoreCtx) error { func (n *UnionSelectList) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") for i, selectStmt := range n.Selects {
if i != 0 {
ctx.WriteKeyWord(" UNION ")
if !selectStmt.IsAfterUnionDistinct {
ctx.WriteKeyWord("ALL ")
}
}
if selectStmt.IsInBraces {
ctx.WritePlain("(")
}
if err := selectStmt.Restore(ctx); err != nil {
errors.Annotate(err, "An error occurred while restore UnionSelectList.SelectStmt")
}
if selectStmt.IsInBraces {
ctx.WritePlain(")")
}
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -888,7 +1009,24 @@ type UnionStmt struct { ...@@ -888,7 +1009,24 @@ type UnionStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *UnionStmt) Restore(ctx *RestoreCtx) error { func (n *UnionStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") if err := n.SelectList.Restore(ctx); err != nil {
errors.Annotate(err, "An error occurred while restore UnionStmt.SelectList")
}
if n.OrderBy != nil {
ctx.WritePlain(" ")
if err := n.OrderBy.Restore(ctx); err != nil {
errors.Annotate(err, "An error occurred while restore UnionStmt.OrderBy")
}
}
if n.Limit != nil {
ctx.WritePlain(" ")
if err := n.Limit.Restore(ctx); err != nil {
errors.Annotate(err, "An error occurred while restore UnionStmt.Limit")
}
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -979,7 +1117,36 @@ type LoadDataStmt struct { ...@@ -979,7 +1117,36 @@ type LoadDataStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *LoadDataStmt) Restore(ctx *RestoreCtx) error { func (n *LoadDataStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") ctx.WriteKeyWord("LOAD DATA ")
if n.IsLocal {
ctx.WriteKeyWord("LOCAL ")
}
ctx.WriteKeyWord("INFILE ")
ctx.WriteString(n.Path)
ctx.WriteKeyWord(" INTO TABLE ")
if err := n.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore LoadDataStmt.Table")
}
n.FieldsInfo.Restore(ctx)
n.LinesInfo.Restore(ctx)
if n.IgnoreLines != 0 {
ctx.WriteKeyWord(" IGNORE ")
ctx.WritePlainf("%d", n.IgnoreLines)
ctx.WriteKeyWord(" LINES")
}
if len(n.Columns) != 0 {
ctx.WritePlain(" (")
for i, column := range n.Columns {
if i != 0 {
ctx.WritePlain(",")
}
if err := column.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore LoadDataStmt.Columns")
}
}
ctx.WritePlain(")")
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -1013,12 +1180,52 @@ type FieldsClause struct { ...@@ -1013,12 +1180,52 @@ type FieldsClause struct {
Escaped byte Escaped byte
} }
// Restore for FieldsClause
func (n *FieldsClause) Restore(ctx *RestoreCtx) error {
if n.Terminated != "\t" || n.Escaped != '\\' {
ctx.WriteKeyWord(" FIELDS")
if n.Terminated != "\t" {
ctx.WriteKeyWord(" TERMINATED BY ")
ctx.WriteString(n.Terminated)
}
if n.Enclosed != 0 {
ctx.WriteKeyWord(" ENCLOSED BY ")
ctx.WriteString(string(n.Enclosed))
}
if n.Escaped != '\\' {
ctx.WriteKeyWord(" ESCAPED BY ")
if n.Escaped == 0 {
ctx.WritePlain("''")
} else {
ctx.WriteString(string(n.Escaped))
}
}
}
return nil
}
// LinesClause represents lines references clause in load data statement. // LinesClause represents lines references clause in load data statement.
type LinesClause struct { type LinesClause struct {
Starting string Starting string
Terminated string Terminated string
} }
// Restore for LinesClause
func (n *LinesClause) Restore(ctx *RestoreCtx) error {
if n.Starting != "" || n.Terminated != "\n" {
ctx.WriteKeyWord(" LINES")
if n.Starting != "" {
ctx.WriteKeyWord(" STARTING BY ")
ctx.WriteString(n.Starting)
}
if n.Terminated != "\n" {
ctx.WriteKeyWord(" TERMINATED BY ")
ctx.WriteString(n.Terminated)
}
}
return nil
}
// InsertStmt is a statement to insert new rows into an existing table. // InsertStmt is a statement to insert new rows into an existing table.
// See https://dev.mysql.com/doc/refman/5.7/en/insert.html // See https://dev.mysql.com/doc/refman/5.7/en/insert.html
type InsertStmt struct { type InsertStmt struct {
...@@ -1037,7 +1244,90 @@ type InsertStmt struct { ...@@ -1037,7 +1244,90 @@ type InsertStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *InsertStmt) Restore(ctx *RestoreCtx) error { func (n *InsertStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") if n.IsReplace {
ctx.WriteKeyWord("REPLACE ")
} else {
ctx.WriteKeyWord("INSERT ")
}
switch n.Priority {
case mysql.LowPriority:
ctx.WriteKeyWord("LOW_PRIORITY ")
case mysql.HighPriority:
ctx.WriteKeyWord("HIGH_PRIORITY ")
case mysql.DelayedPriority:
ctx.WriteKeyWord("DELAYED ")
}
if n.IgnoreErr {
ctx.WriteKeyWord("IGNORE ")
}
ctx.WriteKeyWord("INTO ")
if err := n.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore InsertStmt.Table")
}
if n.Columns != nil {
ctx.WritePlain(" (")
for i, v := range n.Columns {
if i != 0 {
ctx.WritePlain(",")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore InsertStmt.Columns[%d]", i)
}
}
ctx.WritePlain(")")
}
if n.Lists != nil {
ctx.WriteKeyWord(" VALUES ")
for i, row := range n.Lists {
if i != 0 {
ctx.WritePlain(",")
}
ctx.WritePlain("(")
for j, v := range row {
if j != 0 {
ctx.WritePlain(",")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore InsertStmt.Lists[%d][%d]", i, j)
}
}
ctx.WritePlain(")")
}
}
if n.Select != nil {
switch v := n.Select.(type) {
case *SelectStmt, *UnionStmt:
if err := v.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore InsertStmt.Select")
}
default:
return errors.Errorf("Incorrect type for InsertStmt.Select: %T", v)
}
}
if n.Setlist != nil {
ctx.WriteKeyWord(" SET ")
for i, v := range n.Setlist {
if i != 0 {
ctx.WritePlain(",")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore InsertStmt.Setlist[%d]", i)
}
}
}
if n.OnDuplicate != nil {
ctx.WriteKeyWord(" ON DUPLICATE KEY UPDATE ")
for i, v := range n.OnDuplicate {
if i != 0 {
ctx.WritePlain(",")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore InsertStmt.OnDuplicate[%d]", i)
}
}
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -1294,6 +1584,7 @@ const ( ...@@ -1294,6 +1584,7 @@ const (
ShowStatus ShowStatus
ShowCollation ShowCollation
ShowCreateTable ShowCreateTable
ShowCreateView
ShowCreateUser ShowCreateUser
ShowGrants ShowGrants
ShowTriggers ShowTriggers
...@@ -1311,6 +1602,7 @@ const ( ...@@ -1311,6 +1602,7 @@ const (
ShowMasterStatus ShowMasterStatus
ShowPrivileges ShowPrivileges
ShowErrors ShowErrors
ShowBindings
) )
// ShowStmt is a statement to provide information about databases, tables, columns and so on. // ShowStmt is a statement to provide information about databases, tables, columns and so on.
...@@ -1336,7 +1628,170 @@ type ShowStmt struct { ...@@ -1336,7 +1628,170 @@ type ShowStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *ShowStmt) Restore(ctx *RestoreCtx) error { func (n *ShowStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") restoreOptFull := func() {
if n.Full {
ctx.WriteKeyWord("FULL ")
}
}
restoreShowDatabaseNameOpt := func() {
if n.DBName != "" {
// FROM OR IN
ctx.WriteKeyWord(" IN ")
ctx.WriteName(n.DBName)
}
}
restoreGlobalScope := func() {
if n.GlobalScope {
ctx.WriteKeyWord("GLOBAL ")
} else {
ctx.WriteKeyWord("SESSION ")
}
}
restoreShowLikeOrWhereOpt := func() error {
if n.Pattern != nil && n.Pattern.Pattern != nil {
ctx.WriteKeyWord(" LIKE ")
if err := n.Pattern.Pattern.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore ShowStmt.Pattern")
}
} else if n.Where != nil {
ctx.WriteKeyWord(" WHERE ")
if err := n.Where.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore ShowStmt.Where")
}
}
return nil
}
restoreUserName := func() error {
if n.User.CurrentUser {
ctx.WriteKeyWord("CURRENT_USER")
} else {
ctx.WriteString(n.User.Username)
if n.User.Hostname != "" {
ctx.WritePlain("@")
ctx.WriteString(n.User.Hostname)
}
}
return nil
}
ctx.WriteKeyWord("SHOW ")
switch n.Tp {
case ShowCreateTable:
ctx.WriteKeyWord("CREATE TABLE ")
if err := n.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore ShowStmt.Table")
}
case ShowCreateView:
ctx.WriteKeyWord("CREATE VIEW ")
if err := n.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore ShowStmt.VIEW")
}
case ShowCreateDatabase:
ctx.WriteKeyWord("CREATE DATABASE ")
if n.IfNotExists {
ctx.WriteKeyWord("IF NOT EXISTS ")
}
ctx.WriteName(n.DBName)
case ShowCreateUser:
ctx.WriteKeyWord("CREATE USER ")
restoreUserName()
case ShowGrants:
ctx.WriteKeyWord("GRANTS")
if n.User != nil {
ctx.WriteKeyWord(" FOR ")
restoreUserName()
}
case ShowMasterStatus:
ctx.WriteKeyWord("MASTER STATUS")
case ShowProcessList:
restoreOptFull()
ctx.WriteKeyWord("PROCESSLIST")
case ShowStatsMeta:
ctx.WriteKeyWord("STATS_META")
if err := restoreShowLikeOrWhereOpt(); err != nil {
return err
}
case ShowStatsHistograms:
ctx.WriteKeyWord("STATS_HISTOGRAMS")
if err := restoreShowLikeOrWhereOpt(); err != nil {
return err
}
case ShowStatsBuckets:
ctx.WriteKeyWord("STATS_BUCKETS")
if err := restoreShowLikeOrWhereOpt(); err != nil {
return err
}
case ShowStatsHealthy:
ctx.WriteKeyWord("STATS_HEALTHY")
if err := restoreShowLikeOrWhereOpt(); err != nil {
return err
}
case ShowProfiles:
ctx.WriteKeyWord("PROFILES")
case ShowPrivileges:
ctx.WriteKeyWord("PRIVILEGES")
// ShowTargetFilterable
default:
switch n.Tp {
case ShowEngines:
ctx.WriteKeyWord("ENGINES")
case ShowDatabases:
ctx.WriteKeyWord("DATABASES")
case ShowCharset:
ctx.WriteKeyWord("CHARSET")
case ShowTables:
restoreOptFull()
ctx.WriteKeyWord("TABLES")
restoreShowDatabaseNameOpt()
case ShowTableStatus:
ctx.WriteKeyWord("TABLE STATUS")
restoreShowDatabaseNameOpt()
case ShowIndex:
// here can be INDEX INDEXES KEYS
// FROM or IN
ctx.WriteKeyWord("INDEX IN ")
if err := n.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while resotre ShowStmt.Table")
} // TODO: remember to check this case
case ShowColumns: // equivalent to SHOW FIELDS
restoreOptFull()
ctx.WriteKeyWord("COLUMNS")
if n.Table != nil {
// FROM or IN
ctx.WriteKeyWord(" IN ")
if err := n.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while resotre ShowStmt.Table")
}
}
restoreShowDatabaseNameOpt()
case ShowWarnings:
ctx.WriteKeyWord("WARNINGS")
case ShowErrors:
ctx.WriteKeyWord("ERRORS")
case ShowVariables:
restoreGlobalScope()
ctx.WriteKeyWord("VARIABLES")
case ShowStatus:
restoreGlobalScope()
ctx.WriteKeyWord("STATUS")
case ShowCollation:
ctx.WriteKeyWord("COLLATION")
case ShowTriggers:
ctx.WriteKeyWord("TRIGGERS")
restoreShowDatabaseNameOpt()
case ShowProcedureStatus:
ctx.WriteKeyWord("PROCEDURE STATUS")
case ShowEvents:
ctx.WriteKeyWord("EVENTS")
restoreShowDatabaseNameOpt()
case ShowPlugins:
ctx.WriteKeyWord("PLUGINS")
default:
return errors.New("Unknown ShowStmt type")
}
restoreShowLikeOrWhereOpt()
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
......
...@@ -158,7 +158,7 @@ func (n *BinaryOperationExpr) Restore(ctx *RestoreCtx) error { ...@@ -158,7 +158,7 @@ func (n *BinaryOperationExpr) Restore(ctx *RestoreCtx) error {
if err := n.L.Restore(ctx); err != nil { if err := n.L.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred when restore BinaryOperationExpr.L") return errors.Annotate(err, "An error occurred when restore BinaryOperationExpr.L")
} }
if err := n.Op.Restore(ctx.In); err != nil { if err := n.Op.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred when restore BinaryOperationExpr.Op") return errors.Annotate(err, "An error occurred when restore BinaryOperationExpr.Op")
} }
if err := n.R.Restore(ctx); err != nil { if err := n.R.Restore(ctx); err != nil {
...@@ -347,7 +347,12 @@ type SubqueryExpr struct { ...@@ -347,7 +347,12 @@ type SubqueryExpr struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *SubqueryExpr) Restore(ctx *RestoreCtx) error { func (n *SubqueryExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") ctx.WritePlain("(")
if err := n.Query.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore SubqueryExpr.Query")
}
ctx.WritePlain(")")
return nil
} }
// Format the ExprNode into a Writer. // Format the ExprNode into a Writer.
...@@ -388,7 +393,21 @@ type CompareSubqueryExpr struct { ...@@ -388,7 +393,21 @@ type CompareSubqueryExpr struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *CompareSubqueryExpr) Restore(ctx *RestoreCtx) error { func (n *CompareSubqueryExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") if err := n.L.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore CompareSubqueryExpr.L")
}
if err := n.Op.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore CompareSubqueryExpr.Op")
}
if n.All {
ctx.WriteKeyWord("ALL ")
} else {
ctx.WriteKeyWord("ANY ")
}
if err := n.R.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore CompareSubqueryExpr.R")
}
return nil
} }
// Format the ExprNode into a Writer. // Format the ExprNode into a Writer.
...@@ -569,7 +588,15 @@ type ExistsSubqueryExpr struct { ...@@ -569,7 +588,15 @@ type ExistsSubqueryExpr struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *ExistsSubqueryExpr) Restore(ctx *RestoreCtx) error { func (n *ExistsSubqueryExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") if n.Not {
ctx.WriteKeyWord("NOT EXISTS ")
} else {
ctx.WriteKeyWord("EXISTS ")
}
if err := n.Sel.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore ExistsSubqueryExpr.Sel")
}
return nil
} }
// Format the ExprNode into a Writer. // Format the ExprNode into a Writer.
...@@ -615,6 +642,11 @@ func (n *PatternInExpr) Restore(ctx *RestoreCtx) error { ...@@ -615,6 +642,11 @@ func (n *PatternInExpr) Restore(ctx *RestoreCtx) error {
} else { } else {
ctx.WriteKeyWord(" IN ") ctx.WriteKeyWord(" IN ")
} }
if n.Sel != nil {
if err := n.Sel.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore PatternInExpr.Sel")
}
} else {
ctx.WritePlain("(") ctx.WritePlain("(")
for i, expr := range n.List { for i, expr := range n.List {
if i != 0 { if i != 0 {
...@@ -624,12 +656,8 @@ func (n *PatternInExpr) Restore(ctx *RestoreCtx) error { ...@@ -624,12 +656,8 @@ func (n *PatternInExpr) Restore(ctx *RestoreCtx) error {
return errors.Annotatef(err, "An error occurred while restore PatternInExpr.List[%d]", i) return errors.Annotatef(err, "An error occurred while restore PatternInExpr.List[%d]", i)
} }
} }
if n.Sel != nil {
if err := n.Sel.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore PatternInExpr.Sel")
}
}
ctx.WritePlain(")") ctx.WritePlain(")")
}
return nil return nil
} }
...@@ -817,6 +845,12 @@ func (n *PatternLikeExpr) Restore(ctx *RestoreCtx) error { ...@@ -817,6 +845,12 @@ func (n *PatternLikeExpr) Restore(ctx *RestoreCtx) error {
return errors.Annotate(err, "An error occurred while restore PatternLikeExpr.Pattern") return errors.Annotate(err, "An error occurred while restore PatternLikeExpr.Pattern")
} }
escape := string(n.Escape)
if escape != "\\" {
ctx.WriteKeyWord(" ESCAPE ")
ctx.WriteString(escape)
}
return nil return nil
} }
...@@ -1071,7 +1105,7 @@ type UnaryOperationExpr struct { ...@@ -1071,7 +1105,7 @@ type UnaryOperationExpr struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *UnaryOperationExpr) Restore(ctx *RestoreCtx) error { func (n *UnaryOperationExpr) Restore(ctx *RestoreCtx) error {
if err := n.Op.Restore(ctx.In); err != nil { if err := n.Op.Restore(ctx); err != nil {
return errors.Trace(err) return errors.Trace(err)
} }
if err := n.V.Restore(ctx); err != nil { if err := n.V.Restore(ctx); err != nil {
......
...@@ -16,6 +16,7 @@ package ast ...@@ -16,6 +16,7 @@ package ast
import ( import (
"fmt" "fmt"
"io" "io"
"strings"
"github.com/pingcap/errors" "github.com/pingcap/errors"
. "github.com/pingcap/parser/format" . "github.com/pingcap/parser/format"
...@@ -340,15 +341,7 @@ func (n *FuncCallExpr) Restore(ctx *RestoreCtx) error { ...@@ -340,15 +341,7 @@ func (n *FuncCallExpr) Restore(ctx *RestoreCtx) error {
} }
ctx.WriteKeyWord(" USING ") ctx.WriteKeyWord(" USING ")
ctx.WriteKeyWord(n.Args[1].GetType().Charset) ctx.WriteKeyWord(n.Args[1].GetType().Charset)
case "adddate": case "adddate", "subdate", "date_add", "date_sub":
if err := n.Args[0].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
}
ctx.WritePlain(", ")
if err := n.Args[1].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
}
case "date_add":
if err := n.Args[0].Restore(ctx); err != nil { if err := n.Args[0].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr") return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
} }
...@@ -413,6 +406,15 @@ func (n *FuncCallExpr) Restore(ctx *RestoreCtx) error { ...@@ -413,6 +406,15 @@ func (n *FuncCallExpr) Restore(ctx *RestoreCtx) error {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr") return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
} }
} }
case "timestampdiff", "timestampadd":
ctx.WriteKeyWord(n.Args[0].(ValueExpr).GetString())
for i := 1; i < len(n.Args); {
ctx.WritePlain(", ")
if err := n.Args[i].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
}
i++
}
default: default:
for i, argv := range n.Args { for i, argv := range n.Args {
if i != 0 { if i != 0 {
...@@ -644,12 +646,28 @@ func (n *AggregateFuncExpr) Restore(ctx *RestoreCtx) error { ...@@ -644,12 +646,28 @@ func (n *AggregateFuncExpr) Restore(ctx *RestoreCtx) error {
if n.Distinct { if n.Distinct {
ctx.WriteKeyWord("DISTINCT ") ctx.WriteKeyWord("DISTINCT ")
} }
switch strings.ToLower(n.F) {
case "group_concat":
for i := 0; i < len(n.Args)-1; i++ {
if i != 0 {
ctx.WritePlain(", ")
}
if err := n.Args[i].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AggregateFuncExpr.Args[%d]", i)
}
}
ctx.WriteKeyWord(" SEPARATOR ")
if err := n.Args[len(n.Args)-1].Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AggregateFuncExpr.Args SEPARATOR")
}
default:
for i, argv := range n.Args { for i, argv := range n.Args {
if i != 0 { if i != 0 {
ctx.WritePlain(", ") ctx.WritePlain(", ")
} }
if err := argv.Restore(ctx); err != nil { if err := argv.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AggregateFuncExpr.Args %d", i) return errors.Annotatef(err, "An error occurred while restore AggregateFuncExpr.Args[%d]", i)
}
} }
} }
ctx.WritePlain(")") ctx.WritePlain(")")
......
...@@ -44,6 +44,8 @@ var ( ...@@ -44,6 +44,8 @@ var (
_ StmtNode = &UseStmt{} _ StmtNode = &UseStmt{}
_ StmtNode = &FlushStmt{} _ StmtNode = &FlushStmt{}
_ StmtNode = &KillStmt{} _ StmtNode = &KillStmt{}
_ StmtNode = &CreateBindingStmt{}
_ StmtNode = &DropBindingStmt{}
_ Node = &PrivElem{} _ Node = &PrivElem{}
_ Node = &VariableAssignment{} _ Node = &VariableAssignment{}
...@@ -685,6 +687,64 @@ func (n *DropUserStmt) Accept(v Visitor) (Node, bool) { ...@@ -685,6 +687,64 @@ func (n *DropUserStmt) Accept(v Visitor) (Node, bool) {
return v.Leave(n) return v.Leave(n)
} }
// CreateBindingStmt creates sql binding hint.
type CreateBindingStmt struct {
stmtNode
GlobalScope bool
OriginSel StmtNode
HintedSel StmtNode
}
func (n *CreateBindingStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
func (n *CreateBindingStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*CreateBindingStmt)
selnode, ok := n.OriginSel.Accept(v)
if !ok {
return n, false
}
n.OriginSel = selnode.(*SelectStmt)
hintedSelnode, ok := n.HintedSel.Accept(v)
if !ok {
return n, false
}
n.HintedSel = hintedSelnode.(*SelectStmt)
return v.Leave(n)
}
// DropBindingStmt deletes sql binding hint.
type DropBindingStmt struct {
stmtNode
GlobalScope bool
OriginSel StmtNode
}
func (n *DropBindingStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
func (n *DropBindingStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*DropBindingStmt)
selnode, ok := n.OriginSel.Accept(v)
if !ok {
return n, false
}
n.OriginSel = selnode.(*SelectStmt)
return v.Leave(n)
}
// DoStmt is the struct for DO statement. // DoStmt is the struct for DO statement.
type DoStmt struct { type DoStmt struct {
stmtNode stmtNode
...@@ -985,7 +1045,20 @@ type TableOptimizerHint struct { ...@@ -985,7 +1045,20 @@ type TableOptimizerHint struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *TableOptimizerHint) Restore(ctx *RestoreCtx) error { func (n *TableOptimizerHint) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") ctx.WriteKeyWord(n.HintName.String())
ctx.WritePlain("(")
if n.HintName.L == "max_execution_time" {
ctx.WritePlainf("%d", n.MaxExecutionTime)
} else {
for i, table := range n.Tables {
if i != 0 {
ctx.WritePlain(", ")
}
ctx.WriteName(table.String())
}
}
ctx.WritePlain(")")
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
......
...@@ -19,3 +19,12 @@ jobs: ...@@ -19,3 +19,12 @@ jobs:
- run: - run:
name: "Build & Test" name: "Build & Test"
command: make test command: make test
- run:
name: "Integration Test"
command: |
cd /go/src/github.com/pingcap/
git clone git@github.com:pingcap/tidb.git
cd tidb
rm go.sum
GO111MODULE=on go mod edit -replace github.com/pingcap/parser=github.com/${CIRCLE_PR_USERNAME:-$CIRCLE_PROJECT_USERNAME}/${CIRCLE_PR_REPONAME:-$CIRCLE_PROJECT_REPONAME}@$CIRCLE_SHA1
make test
...@@ -2,15 +2,15 @@ module github.com/pingcap/parser ...@@ -2,15 +2,15 @@ module github.com/pingcap/parser
require ( require (
github.com/cznic/golex v0.0.0-20181122101858-9c343928389c // indirect github.com/cznic/golex v0.0.0-20181122101858-9c343928389c // indirect
github.com/cznic/mathutil v0.0.0-20181021201202-eba54fb065b7 github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548
github.com/cznic/parser v0.0.0-20160622100904-31edd927e5b1 github.com/cznic/parser v0.0.0-20160622100904-31edd927e5b1
github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65 github.com/cznic/sortutil v0.0.0-20181122101858-f5f958428db8
github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186 github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186
github.com/cznic/y v0.0.0-20170802143616-045f81c6662a github.com/cznic/y v0.0.0-20170802143616-045f81c6662a
github.com/pingcap/check v0.0.0-20190102082844-67f458068fc8 github.com/pingcap/check v0.0.0-20190102082844-67f458068fc8
github.com/pingcap/errors v0.11.0 github.com/pingcap/errors v0.11.0
github.com/pingcap/tidb v0.0.0-20180108134023-971629b9477a github.com/pingcap/tidb v0.0.0-20190108123336-c68ee7318319
github.com/pingcap/tipb v0.0.0-20181012112600-11e33c750323 github.com/pingcap/tipb v0.0.0-20190107072121-abbec73437b7
github.com/sirupsen/logrus v1.2.0 github.com/sirupsen/logrus v1.2.0
golang.org/x/text v0.3.0 golang.org/x/text v0.3.0
) )
...@@ -23,12 +23,14 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbp ...@@ -23,12 +23,14 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbp
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cznic/golex v0.0.0-20181122101858-9c343928389c h1:G8zTsaqyVfIHpgMFcGgdbhHSFhlNc77rAKkhVbQ9kQg= github.com/cznic/golex v0.0.0-20181122101858-9c343928389c h1:G8zTsaqyVfIHpgMFcGgdbhHSFhlNc77rAKkhVbQ9kQg=
github.com/cznic/golex v0.0.0-20181122101858-9c343928389c/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc= github.com/cznic/golex v0.0.0-20181122101858-9c343928389c/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc=
github.com/cznic/mathutil v0.0.0-20181021201202-eba54fb065b7 h1:y+DH9ARrWiiNBV+6waYP2IPcsRbxdU1qsnycPfShF4c=
github.com/cznic/mathutil v0.0.0-20181021201202-eba54fb065b7/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= github.com/cznic/mathutil v0.0.0-20181021201202-eba54fb065b7/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM=
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 h1:iwZdTE0PVqJCos1vaoKsclOGD3ADKpshg3SRtYBbwso=
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM=
github.com/cznic/parser v0.0.0-20160622100904-31edd927e5b1 h1:uWcWCkSP+E1w1z8r082miT+c+9vzg+5UdrgGCo15lMo= github.com/cznic/parser v0.0.0-20160622100904-31edd927e5b1 h1:uWcWCkSP+E1w1z8r082miT+c+9vzg+5UdrgGCo15lMo=
github.com/cznic/parser v0.0.0-20160622100904-31edd927e5b1/go.mod h1:2B43mz36vGZNZEwkWi8ayRSSUXLfjL8OkbzwW4NcPMM= github.com/cznic/parser v0.0.0-20160622100904-31edd927e5b1/go.mod h1:2B43mz36vGZNZEwkWi8ayRSSUXLfjL8OkbzwW4NcPMM=
github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65 h1:hxuZop6tSoOi0sxFzoGGYdRqNrPubyaIf9KoBG9tPiE=
github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ= github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ=
github.com/cznic/sortutil v0.0.0-20181122101858-f5f958428db8 h1:LpMLYGyy67BoAFGda1NeOBQwqlv7nUXpm+rIVHGxZZ4=
github.com/cznic/sortutil v0.0.0-20181122101858-f5f958428db8/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ=
github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186 h1:0rkFMAbn5KBKNpJyHQ6Prb95vIKanmAe62KxsrN+sqA= github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186 h1:0rkFMAbn5KBKNpJyHQ6Prb95vIKanmAe62KxsrN+sqA=
github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc= github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc=
github.com/cznic/y v0.0.0-20170802143616-045f81c6662a h1:N2rDAvHuM46OGscJkGX4Dw4BBqZgg6mGNGLYs5utVVo= github.com/cznic/y v0.0.0-20170802143616-045f81c6662a h1:N2rDAvHuM46OGscJkGX4Dw4BBqZgg6mGNGLYs5utVVo=
...@@ -119,13 +121,14 @@ github.com/pingcap/kvproto v0.0.0-20181203065228-c14302da291c/go.mod h1:Ja9XPjot ...@@ -119,13 +121,14 @@ github.com/pingcap/kvproto v0.0.0-20181203065228-c14302da291c/go.mod h1:Ja9XPjot
github.com/pingcap/parser v0.0.0-20190108044100-02812c3c22e7/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA= github.com/pingcap/parser v0.0.0-20190108044100-02812c3c22e7/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA=
github.com/pingcap/pd v2.1.0-rc.4+incompatible h1:/buwGk04aHO5odk/+O8ZOXGs4qkUjYTJ2UpCJXna8NE= github.com/pingcap/pd v2.1.0-rc.4+incompatible h1:/buwGk04aHO5odk/+O8ZOXGs4qkUjYTJ2UpCJXna8NE=
github.com/pingcap/pd v2.1.0-rc.4+incompatible/go.mod h1:nD3+EoYes4+aNNODO99ES59V83MZSI+dFbhyr667a0E= github.com/pingcap/pd v2.1.0-rc.4+incompatible/go.mod h1:nD3+EoYes4+aNNODO99ES59V83MZSI+dFbhyr667a0E=
github.com/pingcap/tidb v0.0.0-20180108134023-971629b9477a h1:+UaU3bgZJtmgn1IJOWQU63z+HaVNhOfyxT8puMZ32rc= github.com/pingcap/tidb v0.0.0-20190108123336-c68ee7318319 h1:ltRU5YUxYpW29ywVKnFXIRRTnY6r2cYxauB79L5gU2E=
github.com/pingcap/tidb v0.0.0-20180108134023-971629b9477a/go.mod h1:ytMJRc0YwJxWtwJpuu60xXIXHSTGwi1jhmt3TnxifYw= github.com/pingcap/tidb v0.0.0-20190108123336-c68ee7318319/go.mod h1:qXpdYNt83vgSegvc/TNcxKGiAo4Pa4EtIJl0ka7yGXE=
github.com/pingcap/tidb-tools v2.1.1-0.20181218072513-b2235d442b06+incompatible h1:Bsd+NHosPVowEGB3BCx+2d8wUQGDTXSSC5ljeNS6cXo= github.com/pingcap/tidb-tools v2.1.3-0.20190104033906-883b07a04a73+incompatible h1:Ba48wwPwPq5hd1kkQpgua49dqB5cthC2zXVo7fUUDec=
github.com/pingcap/tidb-tools v2.1.1-0.20181218072513-b2235d442b06+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= github.com/pingcap/tidb-tools v2.1.3-0.20190104033906-883b07a04a73+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM=
github.com/pingcap/tipb v0.0.0-20170310053819-1043caee48da/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI= github.com/pingcap/tipb v0.0.0-20170310053819-1043caee48da/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI=
github.com/pingcap/tipb v0.0.0-20181012112600-11e33c750323 h1:mRKKzRjDNaUNPnAkPAHnRqpNmwNWBX1iA+hxlmvQ93I=
github.com/pingcap/tipb v0.0.0-20181012112600-11e33c750323/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI= github.com/pingcap/tipb v0.0.0-20181012112600-11e33c750323/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI=
github.com/pingcap/tipb v0.0.0-20190107072121-abbec73437b7 h1:wnjdQRhybddDesBVBKyOLUPgDaOFdtqA92pduBgWvVQ=
github.com/pingcap/tipb v0.0.0-20190107072121-abbec73437b7/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
......
...@@ -533,6 +533,8 @@ var tokenMap = map[string]int{ ...@@ -533,6 +533,8 @@ var tokenMap = map[string]int{
"YEAR": yearType, "YEAR": yearType,
"YEAR_MONTH": yearMonth, "YEAR_MONTH": yearMonth,
"ZEROFILL": zerofill, "ZEROFILL": zerofill,
"BINDING": binding,
"BINDINGS": bindings,
} }
// See https://dev.mysql.com/doc/refman/5.7/en/function-resolution.html for details // See https://dev.mysql.com/doc/refman/5.7/en/function-resolution.html for details
......
...@@ -511,6 +511,11 @@ func (m SQLMode) HasNoAutoCreateUserMode() bool { ...@@ -511,6 +511,11 @@ func (m SQLMode) HasNoAutoCreateUserMode() bool {
return m&ModeNoAutoCreateUser == ModeNoAutoCreateUser return m&ModeNoAutoCreateUser == ModeNoAutoCreateUser
} }
// HasAllowInvalidDatesMode detects if 'ALLOW_INVALID_DATES' mode is set in SQLMode
func (m SQLMode) HasAllowInvalidDatesMode() bool {
return m&ModeAllowInvalidDates == ModeAllowInvalidDates
}
// consts for sql modes. // consts for sql modes.
const ( const (
ModeNone SQLMode = 0 ModeNone SQLMode = 0
...@@ -546,6 +551,7 @@ const ( ...@@ -546,6 +551,7 @@ const (
ModeHighNotPrecedence ModeHighNotPrecedence
ModeNoEngineSubstitution ModeNoEngineSubstitution
ModePadCharToFullLength ModePadCharToFullLength
ModeAllowInvalidDates
) )
// FormatSQLModeStr re-format 'SQL_MODE' variable. // FormatSQLModeStr re-format 'SQL_MODE' variable.
...@@ -623,6 +629,7 @@ var Str2SQLMode = map[string]SQLMode{ ...@@ -623,6 +629,7 @@ var Str2SQLMode = map[string]SQLMode{
"HIGH_NOT_PRECEDENCE": ModeHighNotPrecedence, "HIGH_NOT_PRECEDENCE": ModeHighNotPrecedence,
"NO_ENGINE_SUBSTITUTION": ModeNoEngineSubstitution, "NO_ENGINE_SUBSTITUTION": ModeNoEngineSubstitution,
"PAD_CHAR_TO_FULL_LENGTH": ModePadCharToFullLength, "PAD_CHAR_TO_FULL_LENGTH": ModePadCharToFullLength,
"ALLOW_INVALID_DATES": ModeAllowInvalidDates,
} }
// CombinationSQLMode is the special modes that provided as shorthand for combinations of mode values. // CombinationSQLMode is the special modes that provided as shorthand for combinations of mode values.
......
...@@ -901,7 +901,7 @@ const ( ...@@ -901,7 +901,7 @@ const (
ErrWindowFrameEndIllegal = 3585 ErrWindowFrameEndIllegal = 3585
ErrWindowFrameIllegal = 3586 ErrWindowFrameIllegal = 3586
ErrWindowRangeFrameOrderType = 3587 ErrWindowRangeFrameOrderType = 3587
ErrWindowRangeFrameTEMPORALType = 3588 ErrWindowRangeFrameTemporalType = 3588
ErrWindowRangeFrameNumericType = 3589 ErrWindowRangeFrameNumericType = 3589
ErrWindowRangeBoundNotConstant = 3590 ErrWindowRangeBoundNotConstant = 3590
ErrWindowDuplicateName = 3591 ErrWindowDuplicateName = 3591
...@@ -918,6 +918,15 @@ const ( ...@@ -918,6 +918,15 @@ const (
ErrMemExceedThreshold = 8001 ErrMemExceedThreshold = 8001
ErrForUpdateCantRetry = 8002 ErrForUpdateCantRetry = 8002
ErrAdminCheckTable = 8003 ErrAdminCheckTable = 8003
ErrInvalidPluginID = 8101
ErrInvalidPluginManifest = 8102
ErrInvalidPluginName = 8103
ErrInvalidPluginVersion = 8104
ErrDuplicatePlugin = 8105
ErrInvalidPluginSysVarName = 8106
ErrRequireVersionCheckFail = 8107
ErrUnsupportedReloadPlugin = 8018
ErrUnsupportedReloadPluginVar = 8019
// TiKV/PD errors. // TiKV/PD errors.
ErrPDServerTimeout = 9001 ErrPDServerTimeout = 9001
......
...@@ -250,7 +250,7 @@ var MySQLErrName = map[uint16]string{ ...@@ -250,7 +250,7 @@ var MySQLErrName = map[uint16]string{
ErrWrongTypeForVar: "Incorrect argument type to variable '%-.64s'", ErrWrongTypeForVar: "Incorrect argument type to variable '%-.64s'",
ErrVarCantBeRead: "Variable '%-.64s' can only be set, not read", ErrVarCantBeRead: "Variable '%-.64s' can only be set, not read",
ErrCantUseOptionHere: "Incorrect usage/placement of '%s'", ErrCantUseOptionHere: "Incorrect usage/placement of '%s'",
ErrNotSupportedYet: "This version of MySQL doesn't yet support '%s'", ErrNotSupportedYet: "This version of TiDB doesn't yet support '%s'",
ErrMasterFatalErrorReadingBinlog: "Got fatal error %d from master when reading data from binary log: '%-.320s'", ErrMasterFatalErrorReadingBinlog: "Got fatal error %d from master when reading data from binary log: '%-.320s'",
ErrSlaveIgnoredTable: "Slave SQL thread ignored the query because of replicate-*-table rules", ErrSlaveIgnoredTable: "Slave SQL thread ignored the query because of replicate-*-table rules",
ErrIncorrectGlobalLocalVar: "Variable '%-.192s' is a %s variable", ErrIncorrectGlobalLocalVar: "Variable '%-.192s' is a %s variable",
...@@ -898,7 +898,7 @@ var MySQLErrName = map[uint16]string{ ...@@ -898,7 +898,7 @@ var MySQLErrName = map[uint16]string{
ErrWindowFrameEndIllegal: "Window '%s': frame end cannot be UNBOUNDED PRECEDING.", ErrWindowFrameEndIllegal: "Window '%s': frame end cannot be UNBOUNDED PRECEDING.",
ErrWindowFrameIllegal: "Window '%s': frame start or end is negative, NULL or of non-integral type", ErrWindowFrameIllegal: "Window '%s': frame start or end is negative, NULL or of non-integral type",
ErrWindowRangeFrameOrderType: "Window '%s' with RANGE N PRECEDING/FOLLOWING frame requires exactly one ORDER BY expression, of numeric or temporal type", ErrWindowRangeFrameOrderType: "Window '%s' with RANGE N PRECEDING/FOLLOWING frame requires exactly one ORDER BY expression, of numeric or temporal type",
ErrWindowRangeFrameTEMPORALType: "Window '%s' with RANGE frame has ORDER BY expression of datetime type. Only INTERVAL bound value allowed.", ErrWindowRangeFrameTemporalType: "Window '%s' with RANGE frame has ORDER BY expression of datetime type. Only INTERVAL bound value allowed.",
ErrWindowRangeFrameNumericType: "Window '%s' with RANGE frame has ORDER BY expression of numeric type, INTERVAL bound value not allowed.", ErrWindowRangeFrameNumericType: "Window '%s' with RANGE frame has ORDER BY expression of numeric type, INTERVAL bound value not allowed.",
ErrWindowRangeBoundNotConstant: "Window '%s' has a non-constant frame bound.", ErrWindowRangeBoundNotConstant: "Window '%s' has a non-constant frame bound.",
ErrWindowDuplicateName: "Window '%s' is defined twice.", ErrWindowDuplicateName: "Window '%s' is defined twice.",
...@@ -916,6 +916,16 @@ var MySQLErrName = map[uint16]string{ ...@@ -916,6 +916,16 @@ var MySQLErrName = map[uint16]string{
ErrForUpdateCantRetry: "[%d] can not retry select for update statement", ErrForUpdateCantRetry: "[%d] can not retry select for update statement",
ErrAdminCheckTable: "TiDB admin check table failed.", ErrAdminCheckTable: "TiDB admin check table failed.",
ErrInvalidPluginID: "Wrong plugin id: %s, valid plugin id is [name]-[version], both name and version should not contain '-'",
ErrInvalidPluginManifest: "Cannot read plugin %s's manifest",
ErrInvalidPluginName: "Plugin load with %s but got wrong name %s",
ErrInvalidPluginVersion: "Plugin load with %s but got %s",
ErrDuplicatePlugin: "Plugin [%s] is redeclared",
ErrInvalidPluginSysVarName: "Plugin %s's sysVar %s must start with its plugin name %s",
ErrRequireVersionCheckFail: "Plugin %s require %s be %v but got %v",
ErrUnsupportedReloadPlugin: "Plugin %s isn't loaded so cannot be reloaded",
ErrUnsupportedReloadPluginVar: "Reload plugin with different sysVar is unsupported %v",
// TiKV/PD errors. // TiKV/PD errors.
ErrPDServerTimeout: "PD server timeout", ErrPDServerTimeout: "PD server timeout",
ErrTiKVServerTimeout: "TiKV server timeout", ErrTiKVServerTimeout: "TiKV server timeout",
......
...@@ -18,6 +18,7 @@ import ( ...@@ -18,6 +18,7 @@ import (
"io" "io"
"github.com/pingcap/errors" "github.com/pingcap/errors"
. "github.com/pingcap/parser/format"
) )
// Op is opcode type. // Op is opcode type.
...@@ -102,9 +103,9 @@ func (o Op) String() string { ...@@ -102,9 +103,9 @@ func (o Op) String() string {
} }
var opsLiteral = map[Op]string{ var opsLiteral = map[Op]string{
LogicAnd: "&&", LogicAnd: " AND ",
LogicOr: "||", LogicOr: " OR ",
LogicXor: "^", LogicXor: " XOR ",
LeftShift: "<<", LeftShift: "<<",
RightShift: ">>", RightShift: ">>",
GE: ">=", GE: ">=",
...@@ -140,9 +141,9 @@ func (o Op) Format(w io.Writer) { ...@@ -140,9 +141,9 @@ func (o Op) Format(w io.Writer) {
} }
// Restore the Op into a Writer // Restore the Op into a Writer
func (o Op) Restore(w io.Writer) error { func (o Op) Restore(ctx *RestoreCtx) error {
if v, ok := opsLiteral[o]; ok { if v, ok := opsLiteral[o]; ok {
fmt.Fprint(w, v) ctx.WriteKeyWord(v)
return nil return nil
} }
return errors.Errorf("Invalid opcode type %d during restoring AST to SQL text", o) return errors.Errorf("Invalid opcode type %d during restoring AST to SQL text", o)
......
因为 它太大了无法显示 source diff 。你可以改为 查看blob
...@@ -423,6 +423,8 @@ import ( ...@@ -423,6 +423,8 @@ import (
value "VALUE" value "VALUE"
variables "VARIABLES" variables "VARIABLES"
view "VIEW" view "VIEW"
binding "BINDING"
bindings "BINDINGS"
warnings "WARNINGS" warnings "WARNINGS"
identSQLErrors "ERRORS" identSQLErrors "ERRORS"
week "WEEK" week "WEEK"
...@@ -573,6 +575,7 @@ import ( ...@@ -573,6 +575,7 @@ import (
CreateUserStmt "CREATE User statement" CreateUserStmt "CREATE User statement"
CreateDatabaseStmt "Create Database Statement" CreateDatabaseStmt "Create Database Statement"
CreateIndexStmt "CREATE INDEX statement" CreateIndexStmt "CREATE INDEX statement"
CreateBindingStmt "CREATE BINDING statement"
DoStmt "Do statement" DoStmt "Do statement"
DropDatabaseStmt "DROP DATABASE statement" DropDatabaseStmt "DROP DATABASE statement"
DropIndexStmt "DROP INDEX statement" DropIndexStmt "DROP INDEX statement"
...@@ -580,6 +583,7 @@ import ( ...@@ -580,6 +583,7 @@ import (
DropTableStmt "DROP TABLE statement" DropTableStmt "DROP TABLE statement"
DropUserStmt "DROP USER" DropUserStmt "DROP USER"
DropViewStmt "DROP VIEW statement" DropViewStmt "DROP VIEW statement"
DropBindingStmt "DROP BINDING statement"
DeallocateStmt "Deallocate prepared statement" DeallocateStmt "Deallocate prepared statement"
DeleteFromStmt "DELETE FROM statement" DeleteFromStmt "DELETE FROM statement"
EmptyStmt "empty statement" EmptyStmt "empty statement"
...@@ -723,6 +727,7 @@ import ( ...@@ -723,6 +727,7 @@ import (
PartitionDefinitionListOpt "Partition definition list option" PartitionDefinitionListOpt "Partition definition list option"
PartitionOpt "Partition option" PartitionOpt "Partition option"
PartitionNameList "Partition name list" PartitionNameList "Partition name list"
PartitionNameListOpt "table partition names list optional"
PartitionNumOpt "PARTITION NUM option" PartitionNumOpt "PARTITION NUM option"
PartDefValuesOpt "VALUES {LESS THAN {(expr | value_list) | MAXVALUE} | IN {value_list}" PartDefValuesOpt "VALUES {LESS THAN {(expr | value_list) | MAXVALUE} | IN {value_list}"
PartDefOptionsOpt "PartDefOptionList option" PartDefOptionsOpt "PartDefOptionList option"
...@@ -2988,7 +2993,7 @@ UnReservedKeyword: ...@@ -2988,7 +2993,7 @@ UnReservedKeyword:
| "COLLATION" | "COMMENT" | "AVG_ROW_LENGTH" | "CONNECTION" | "CHECKSUM" | "COMPRESSION" | "KEY_BLOCK_SIZE" | "MASTER" | "MAX_ROWS" | "COLLATION" | "COMMENT" | "AVG_ROW_LENGTH" | "CONNECTION" | "CHECKSUM" | "COMPRESSION" | "KEY_BLOCK_SIZE" | "MASTER" | "MAX_ROWS"
| "MIN_ROWS" | "NATIONAL" | "ROW_FORMAT" | "QUARTER" | "GRANTS" | "TRIGGERS" | "DELAY_KEY_WRITE" | "ISOLATION" | "JSON" | "MIN_ROWS" | "NATIONAL" | "ROW_FORMAT" | "QUARTER" | "GRANTS" | "TRIGGERS" | "DELAY_KEY_WRITE" | "ISOLATION" | "JSON"
| "REPEATABLE" | "RESPECT" | "COMMITTED" | "UNCOMMITTED" | "ONLY" | "SERIALIZABLE" | "LEVEL" | "VARIABLES" | "SQL_CACHE" | "INDEXES" | "PROCESSLIST" | "REPEATABLE" | "RESPECT" | "COMMITTED" | "UNCOMMITTED" | "ONLY" | "SERIALIZABLE" | "LEVEL" | "VARIABLES" | "SQL_CACHE" | "INDEXES" | "PROCESSLIST"
| "SQL_NO_CACHE" | "DISABLE" | "ENABLE" | "REVERSE" | "PRIVILEGES" | "NO" | "BINLOG" | "FUNCTION" | "VIEW" | "MODIFY" | "EVENTS" | "PARTITIONS" | "SQL_NO_CACHE" | "DISABLE" | "ENABLE" | "REVERSE" | "PRIVILEGES" | "NO" | "BINLOG" | "FUNCTION" | "VIEW" | "BINDING" | "BINDINGS" | "MODIFY" | "EVENTS" | "PARTITIONS"
| "NONE" | "NULLS" | "SUPER" | "EXCLUSIVE" | "STATS_PERSISTENT" | "ROW_COUNT" | "COALESCE" | "MONTH" | "PROCESS" | "PROFILES" | "NONE" | "NULLS" | "SUPER" | "EXCLUSIVE" | "STATS_PERSISTENT" | "ROW_COUNT" | "COALESCE" | "MONTH" | "PROCESS" | "PROFILES"
| "MICROSECOND" | "MINUTE" | "PLUGINS" | "PRECEDING" | "QUERY" | "QUERIES" | "SECOND" | "SEPARATOR" | "SHARE" | "SHARED" | "SLOW" | "MAX_CONNECTIONS_PER_HOUR" | "MAX_QUERIES_PER_HOUR" | "MAX_UPDATES_PER_HOUR" | "MICROSECOND" | "MINUTE" | "PLUGINS" | "PRECEDING" | "QUERY" | "QUERIES" | "SECOND" | "SEPARATOR" | "SHARE" | "SHARED" | "SLOW" | "MAX_CONNECTIONS_PER_HOUR" | "MAX_QUERIES_PER_HOUR" | "MAX_UPDATES_PER_HOUR"
| "MAX_USER_CONNECTIONS" | "REPLICATION" | "CLIENT" | "SLAVE" | "RELOAD" | "TEMPORARY" | "ROUTINE" | "EVENT" | "ALGORITHM" | "DEFINER" | "INVOKER" | "MERGE" | "TEMPTABLE" | "UNDEFINED" | "SECURITY" | "CASCADED" | "RECOVER" | "MAX_USER_CONNECTIONS" | "REPLICATION" | "CLIENT" | "SLAVE" | "RELOAD" | "TEMPORARY" | "ROUTINE" | "EVENT" | "ALGORITHM" | "DEFINER" | "INVOKER" | "MERGE" | "TEMPTABLE" | "UNDEFINED" | "SECURITY" | "CASCADED" | "RECOVER"
...@@ -4719,7 +4724,7 @@ WindowFrameStart: ...@@ -4719,7 +4724,7 @@ WindowFrameStart:
} }
| "INTERVAL" Expression TimeUnit "PRECEDING" | "INTERVAL" Expression TimeUnit "PRECEDING"
{ {
$$ = ast.FrameBound{Type: ast.Preceding, Expr: ast.NewValueExpr($2), Unit: ast.NewValueExpr($3),} $$ = ast.FrameBound{Type: ast.Preceding, Expr: $2, Unit: ast.NewValueExpr($3),}
} }
| "CURRENT" "ROW" | "CURRENT" "ROW"
{ {
...@@ -4751,7 +4756,7 @@ WindowFrameBound: ...@@ -4751,7 +4756,7 @@ WindowFrameBound:
} }
| "INTERVAL" Expression TimeUnit "FOLLOWING" | "INTERVAL" Expression TimeUnit "FOLLOWING"
{ {
$$ = ast.FrameBound{Type: ast.Following, Expr: ast.NewValueExpr($2), Unit: ast.NewValueExpr($3),} $$ = ast.FrameBound{Type: ast.Following, Expr: $2, Unit: ast.NewValueExpr($3),}
} }
OptWindowingClause: OptWindowingClause:
...@@ -4937,11 +4942,12 @@ TableRef: ...@@ -4937,11 +4942,12 @@ TableRef:
} }
TableFactor: TableFactor:
TableName TableAsNameOpt IndexHintListOpt TableName PartitionNameListOpt TableAsNameOpt IndexHintListOpt
{ {
tn := $1.(*ast.TableName) tn := $1.(*ast.TableName)
tn.IndexHints = $3.([]*ast.IndexHint) tn.PartitionNames = $2.([]model.CIStr)
$$ = &ast.TableSource{Source: tn, AsName: $2.(model.CIStr)} tn.IndexHints = $4.([]*ast.IndexHint)
$$ = &ast.TableSource{Source: tn, AsName: $3.(model.CIStr)}
} }
| '(' SelectStmt ')' TableAsName | '(' SelectStmt ')' TableAsName
{ {
...@@ -4959,6 +4965,16 @@ TableFactor: ...@@ -4959,6 +4965,16 @@ TableFactor:
$$ = $2 $$ = $2
} }
PartitionNameListOpt:
/* empty */
{
$$ = []model.CIStr{}
}
| "PARTITION" '(' PartitionNameList ')'
{
$$ = $3
}
TableAsNameOpt: TableAsNameOpt:
{ {
$$ = model.CIStr{} $$ = model.CIStr{}
...@@ -5764,11 +5780,26 @@ AdminStmt: ...@@ -5764,11 +5780,26 @@ AdminStmt:
Index: string($5), Index: string($5),
} }
} }
| "ADMIN" "RESTORE" "TABLE" "BY" "JOB" NumList | "ADMIN" "RESTORE" "TABLE" "BY" "JOB" NUM
{ {
$$ = &ast.AdminStmt{ $$ = &ast.AdminStmt{
Tp: ast.AdminRestoreTable, Tp: ast.AdminRestoreTable,
JobIDs: $6.([]int64), JobIDs: []int64{$6.(int64)},
}
}
| "ADMIN" "RESTORE" "TABLE" TableName
{
$$ = &ast.AdminStmt{
Tp: ast.AdminRestoreTable,
Tables: []*ast.TableName{$4.(*ast.TableName)},
}
}
| "ADMIN" "RESTORE" "TABLE" TableName NUM
{
$$ = &ast.AdminStmt{
Tp: ast.AdminRestoreTable,
Tables: []*ast.TableName{$4.(*ast.TableName)},
JobNumber: $5.(int64),
} }
} }
| "ADMIN" "CLEANUP" "INDEX" TableName Identifier | "ADMIN" "CLEANUP" "INDEX" TableName Identifier
...@@ -5884,7 +5915,7 @@ ShowStmt: ...@@ -5884,7 +5915,7 @@ ShowStmt:
{ {
stmt := $2.(*ast.ShowStmt) stmt := $2.(*ast.ShowStmt)
if $3 != nil { if $3 != nil {
if x, ok := $3.(*ast.PatternLikeExpr); ok { if x, ok := $3.(*ast.PatternLikeExpr); ok && x.Expr == nil {
stmt.Pattern = x stmt.Pattern = x
} else { } else {
stmt.Where = $3.(ast.ExprNode) stmt.Where = $3.(ast.ExprNode)
...@@ -5899,6 +5930,13 @@ ShowStmt: ...@@ -5899,6 +5930,13 @@ ShowStmt:
Table: $4.(*ast.TableName), Table: $4.(*ast.TableName),
} }
} }
| "SHOW" "CREATE" "VIEW" TableName
{
$$ = &ast.ShowStmt{
Tp: ast.ShowCreateView,
Table: $4.(*ast.TableName),
}
}
| "SHOW" "CREATE" "DATABASE" IfNotExists DBName | "SHOW" "CREATE" "DATABASE" IfNotExists DBName
{ {
$$ = &ast.ShowStmt{ $$ = &ast.ShowStmt{
...@@ -5947,7 +5985,7 @@ ShowStmt: ...@@ -5947,7 +5985,7 @@ ShowStmt:
Tp: ast.ShowStatsMeta, Tp: ast.ShowStatsMeta,
} }
if $3 != nil { if $3 != nil {
if x, ok := $3.(*ast.PatternLikeExpr); ok { if x, ok := $3.(*ast.PatternLikeExpr); ok && x.Expr == nil {
stmt.Pattern = x stmt.Pattern = x
} else { } else {
stmt.Where = $3.(ast.ExprNode) stmt.Where = $3.(ast.ExprNode)
...@@ -5961,7 +5999,7 @@ ShowStmt: ...@@ -5961,7 +5999,7 @@ ShowStmt:
Tp: ast.ShowStatsHistograms, Tp: ast.ShowStatsHistograms,
} }
if $3 != nil { if $3 != nil {
if x, ok := $3.(*ast.PatternLikeExpr); ok { if x, ok := $3.(*ast.PatternLikeExpr); ok && x.Expr == nil {
stmt.Pattern = x stmt.Pattern = x
} else { } else {
stmt.Where = $3.(ast.ExprNode) stmt.Where = $3.(ast.ExprNode)
...@@ -5975,7 +6013,7 @@ ShowStmt: ...@@ -5975,7 +6013,7 @@ ShowStmt:
Tp: ast.ShowStatsBuckets, Tp: ast.ShowStatsBuckets,
} }
if $3 != nil { if $3 != nil {
if x, ok := $3.(*ast.PatternLikeExpr); ok { if x, ok := $3.(*ast.PatternLikeExpr); ok && x.Expr == nil {
stmt.Pattern = x stmt.Pattern = x
} else { } else {
stmt.Where = $3.(ast.ExprNode) stmt.Where = $3.(ast.ExprNode)
...@@ -5989,7 +6027,7 @@ ShowStmt: ...@@ -5989,7 +6027,7 @@ ShowStmt:
Tp: ast.ShowStatsHealthy, Tp: ast.ShowStatsHealthy,
} }
if $3 != nil { if $3 != nil {
if x, ok := $3.(*ast.PatternLikeExpr); ok { if x, ok := $3.(*ast.PatternLikeExpr); ok && x.Expr == nil {
stmt.Pattern = x stmt.Pattern = x
} else { } else {
stmt.Where = $3.(ast.ExprNode) stmt.Where = $3.(ast.ExprNode)
...@@ -6102,6 +6140,13 @@ ShowTargetFilterable: ...@@ -6102,6 +6140,13 @@ ShowTargetFilterable:
GlobalScope: $1.(bool), GlobalScope: $1.(bool),
} }
} }
| GlobalScope "BINDINGS"
{
$$ = &ast.ShowStmt{
Tp: ast.ShowBindings,
GlobalScope: $1.(bool),
}
}
| "COLLATION" | "COLLATION"
{ {
$$ = &ast.ShowStmt{ $$ = &ast.ShowStmt{
...@@ -6277,6 +6322,7 @@ Statement: ...@@ -6277,6 +6322,7 @@ Statement:
| CreateTableStmt | CreateTableStmt
| CreateViewStmt | CreateViewStmt
| CreateUserStmt | CreateUserStmt
| CreateBindingStmt
| DoStmt | DoStmt
| DropDatabaseStmt | DropDatabaseStmt
| DropIndexStmt | DropIndexStmt
...@@ -6284,6 +6330,7 @@ Statement: ...@@ -6284,6 +6330,7 @@ Statement:
| DropViewStmt | DropViewStmt
| DropUserStmt | DropUserStmt
| DropStatsStmt | DropStatsStmt
| DropBindingStmt
| FlushStmt | FlushStmt
| GrantStmt | GrantStmt
| InsertIntoStmt | InsertIntoStmt
...@@ -7285,6 +7332,55 @@ HashString: ...@@ -7285,6 +7332,55 @@ HashString:
$$ = $1 $$ = $1
} }
/*******************************************************************
*
* Create Binding Statement
*
* Example:
* CREATE GLOBAL BINDING FOR select Col1,Col2 from table USING select Col1,Col2 from table use index(Col1)
*******************************************************************/
CreateBindingStmt:
"CREATE" GlobalScope "BINDING" "FOR" SelectStmt "USING" SelectStmt
{
startOffset := parser.startOffset(&yyS[yypt-2])
endOffset := parser.startOffset(&yyS[yypt-1])
selStmt := $5.(*ast.SelectStmt)
selStmt.SetText(strings.TrimSpace(parser.src[startOffset:endOffset]))
startOffset = parser.startOffset(&yyS[yypt])
hintedSelStmt := $7.(*ast.SelectStmt)
hintedSelStmt.SetText(strings.TrimSpace(parser.src[startOffset:]))
x := &ast.CreateBindingStmt {
OriginSel: selStmt,
HintedSel: hintedSelStmt,
GlobalScope: $2.(bool),
}
$$ = x
}
/*******************************************************************
*
* Drop Binding Statement
*
* Example:
* DROP GLOBAL BINDING FOR select Col1,Col2 from table
*******************************************************************/
DropBindingStmt:
"DROP" GlobalScope "BINDING" "FOR" SelectStmt
{
startOffset := parser.startOffset(&yyS[yypt])
selStmt := $5.(*ast.SelectStmt)
selStmt.SetText(strings.TrimSpace(parser.src[startOffset:]))
x := &ast.DropBindingStmt {
OriginSel: selStmt,
GlobalScope: $2.(bool),
}
$$ = x
}
/************************************************************************************* /*************************************************************************************
* Grant statement * Grant statement
* See https://dev.mysql.com/doc/refman/5.7/en/grant.html * See https://dev.mysql.com/doc/refman/5.7/en/grant.html
......
...@@ -82,6 +82,7 @@ const ( ...@@ -82,6 +82,7 @@ const (
ClassJSON ClassJSON
ClassTiKV ClassTiKV
ClassSession ClassSession
ClassPlugin
// Add more as needed. // Add more as needed.
) )
...@@ -109,6 +110,7 @@ var errClz2Str = map[ErrClass]string{ ...@@ -109,6 +110,7 @@ var errClz2Str = map[ErrClass]string{
ClassJSON: "json", ClassJSON: "json",
ClassTiKV: "tikv", ClassTiKV: "tikv",
ClassSession: "session", ClassSession: "session",
ClassPlugin: "plugin",
} }
// String implements fmt.Stringer interface. // String implements fmt.Stringer interface.
......
...@@ -195,6 +195,61 @@ func (ft *FieldType) String() string { ...@@ -195,6 +195,61 @@ func (ft *FieldType) String() string {
return strings.Join(strs, " ") return strings.Join(strs, " ")
} }
// Restore implements Node interface.
func (ft *FieldType) Restore(ctx *format.RestoreCtx) error {
ctx.WriteKeyWord(TypeToStr(ft.Tp, ft.Charset))
switch ft.Tp {
case mysql.TypeEnum, mysql.TypeSet:
ctx.WritePlain("(")
for i, e := range ft.Elems {
if i != 0 {
ctx.WritePlain(",")
}
ctx.WriteString(e)
}
ctx.WritePlain(")")
case mysql.TypeTimestamp, mysql.TypeDatetime, mysql.TypeDuration:
if ft.Flen > 0 && ft.Decimal > 0 {
ctx.WritePlainf("(%d)", ft.Decimal)
}
case mysql.TypeDouble, mysql.TypeFloat:
if ft.Flen > 0 && ft.Decimal > 0 {
ctx.WritePlainf("(%d,%d)", ft.Flen, ft.Decimal)
}
case mysql.TypeNewDecimal:
if ft.Flen > 0 && ft.Decimal > 0 {
ctx.WritePlainf("(%d,%d)", ft.Flen, ft.Decimal)
}
case mysql.TypeBit, mysql.TypeShort, mysql.TypeTiny, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong, mysql.TypeVarchar, mysql.TypeString, mysql.TypeVarString:
if ft.Flen > 0 {
ctx.WritePlainf("(%d)", ft.Flen)
}
}
if mysql.HasUnsignedFlag(ft.Flag) {
ctx.WriteKeyWord(" UNSIGNED")
}
if mysql.HasZerofillFlag(ft.Flag) {
ctx.WriteKeyWord(" ZEROFILL")
}
if mysql.HasBinaryFlag(ft.Flag) && ft.Charset != charset.CharsetBin {
ctx.WriteKeyWord(" BINARY")
}
if IsTypeChar(ft.Tp) || IsTypeBlob(ft.Tp) {
if ft.Charset != "" && ft.Charset != charset.CharsetBin {
ctx.WriteKeyWord(" CHARACTER SET " + ft.Charset)
}
if ft.Collate != "" && ft.Collate != charset.CharsetBin {
ctx.WriteKeyWord(" COLLATE ")
ctx.WritePlain(ft.Collate)
}
}
return nil
}
// FormatAsCastType is used for write AST back to string. // FormatAsCastType is used for write AST back to string.
func (ft *FieldType) FormatAsCastType(w io.Writer) { func (ft *FieldType) FormatAsCastType(w io.Writer) {
switch ft.Tp { switch ft.Tp {
......
...@@ -47,8 +47,10 @@ type StatementContext struct { ...@@ -47,8 +47,10 @@ type StatementContext struct {
// If IsDDLJobInQueue is true, it means the DDL job is in the queue of storage, and it can be handled by the DDL worker. // If IsDDLJobInQueue is true, it means the DDL job is in the queue of storage, and it can be handled by the DDL worker.
IsDDLJobInQueue bool IsDDLJobInQueue bool
InInsertStmt bool InInsertStmt bool
InUpdateOrDeleteStmt bool InUpdateStmt bool
InDeleteStmt bool
InSelectStmt bool InSelectStmt bool
InLoadDataStmt bool
IgnoreTruncate bool IgnoreTruncate bool
IgnoreZeroInDate bool IgnoreZeroInDate bool
DupKeyAsWarning bool DupKeyAsWarning bool
...@@ -61,6 +63,7 @@ type StatementContext struct { ...@@ -61,6 +63,7 @@ type StatementContext struct {
PadCharToFullLength bool PadCharToFullLength bool
BatchCheck bool BatchCheck bool
InNullRejectCheck bool InNullRejectCheck bool
AllowInvalidDate bool
// mu struct holds variables that change during execution. // mu struct holds variables that change during execution.
mu struct { mu struct {
...@@ -379,3 +382,21 @@ func (sc *StatementContext) GetExecDetails() execdetails.ExecDetails { ...@@ -379,3 +382,21 @@ func (sc *StatementContext) GetExecDetails() execdetails.ExecDetails {
sc.mu.Unlock() sc.mu.Unlock()
return details return details
} }
// ShouldClipToZero indicates whether values less than 0 should be clipped to 0 for unsigned integer types.
// This is the case for `insert`, `update`, `alter table` and `load data infile` statements, when not in strict SQL mode.
// see https://dev.mysql.com/doc/refman/5.7/en/out-of-range-and-overflow.html
func (sc *StatementContext) ShouldClipToZero() bool {
// TODO: Currently altering column of integer to unsigned integer is not supported.
// If it is supported one day, that case should be added here.
return sc.InInsertStmt || sc.InLoadDataStmt
}
// ShouldIgnoreOverflowError indicates whether we should ignore the error when type conversion overflows,
// so we can leave it for further processing like clipping values less than 0 to 0 for unsigned integer types.
func (sc *StatementContext) ShouldIgnoreOverflowError() bool {
if (sc.InInsertStmt && sc.TruncateAsWarning) || sc.InLoadDataStmt {
return true
}
return false
}
...@@ -106,7 +106,11 @@ func ConvertUintToInt(val uint64, upperBound int64, tp byte) (int64, error) { ...@@ -106,7 +106,11 @@ func ConvertUintToInt(val uint64, upperBound int64, tp byte) (int64, error) {
} }
// ConvertIntToUint converts an int value to an uint value. // ConvertIntToUint converts an int value to an uint value.
func ConvertIntToUint(val int64, upperBound uint64, tp byte) (uint64, error) { func ConvertIntToUint(sc *stmtctx.StatementContext, val int64, upperBound uint64, tp byte) (uint64, error) {
if sc.ShouldClipToZero() && val < 0 {
return 0, overflow(val, tp)
}
if uint64(val) > upperBound { if uint64(val) > upperBound {
return upperBound, overflow(val, tp) return upperBound, overflow(val, tp)
} }
...@@ -124,9 +128,12 @@ func ConvertUintToUint(val uint64, upperBound uint64, tp byte) (uint64, error) { ...@@ -124,9 +128,12 @@ func ConvertUintToUint(val uint64, upperBound uint64, tp byte) (uint64, error) {
} }
// ConvertFloatToUint converts a float value to an uint value. // ConvertFloatToUint converts a float value to an uint value.
func ConvertFloatToUint(fval float64, upperBound uint64, tp byte) (uint64, error) { func ConvertFloatToUint(sc *stmtctx.StatementContext, fval float64, upperBound uint64, tp byte) (uint64, error) {
val := RoundFloat(fval) val := RoundFloat(fval)
if val < 0 { if val < 0 {
if sc.ShouldClipToZero() {
return 0, overflow(val, tp)
}
return uint64(int64(val)), overflow(val, tp) return uint64(int64(val)), overflow(val, tp)
} }
...@@ -322,14 +329,12 @@ func floatStrToIntStr(sc *stmtctx.StatementContext, validFloat string, oriStr st ...@@ -322,14 +329,12 @@ func floatStrToIntStr(sc *stmtctx.StatementContext, validFloat string, oriStr st
if intCnt <= 0 { if intCnt <= 0 {
intStr = "0" intStr = "0"
if intCnt == 0 && len(digits) > 0 { if intCnt == 0 && len(digits) > 0 {
dotIdx = -1
intStr = roundIntStr(digits[0], intStr) intStr = roundIntStr(digits[0], intStr)
} }
return intStr, nil return intStr, nil
} }
if intCnt == 1 && (digits[0] == '-' || digits[0] == '+') { if intCnt == 1 && (digits[0] == '-' || digits[0] == '+') {
intStr = "0" intStr = "0"
dotIdx = 0
if len(digits) > 1 { if len(digits) > 1 {
intStr = roundIntStr(digits[1], intStr) intStr = roundIntStr(digits[1], intStr)
} }
...@@ -400,7 +405,7 @@ func ConvertJSONToInt(sc *stmtctx.StatementContext, j json.BinaryJSON, unsigned ...@@ -400,7 +405,7 @@ func ConvertJSONToInt(sc *stmtctx.StatementContext, j json.BinaryJSON, unsigned
return ConvertFloatToInt(f, lBound, uBound, mysql.TypeDouble) return ConvertFloatToInt(f, lBound, uBound, mysql.TypeDouble)
} }
bound := UnsignedUpperBound[mysql.TypeLonglong] bound := UnsignedUpperBound[mysql.TypeLonglong]
u, err := ConvertFloatToUint(f, bound, mysql.TypeDouble) u, err := ConvertFloatToUint(sc, f, bound, mysql.TypeDouble)
return int64(u), errors.Trace(err) return int64(u), errors.Trace(err)
case json.TypeCodeString: case json.TypeCodeString:
return StrToInt(sc, hack.String(j.GetString())) return StrToInt(sc, hack.String(j.GetString()))
...@@ -423,7 +428,7 @@ func ConvertJSONToFloat(sc *stmtctx.StatementContext, j json.BinaryJSON) (float6 ...@@ -423,7 +428,7 @@ func ConvertJSONToFloat(sc *stmtctx.StatementContext, j json.BinaryJSON) (float6
case json.TypeCodeInt64: case json.TypeCodeInt64:
return float64(j.GetInt64()), nil return float64(j.GetInt64()), nil
case json.TypeCodeUint64: case json.TypeCodeUint64:
u, err := ConvertIntToUint(j.GetInt64(), UnsignedUpperBound[mysql.TypeLonglong], mysql.TypeLonglong) u, err := ConvertIntToUint(sc, j.GetInt64(), UnsignedUpperBound[mysql.TypeLonglong], mysql.TypeLonglong)
return float64(u), errors.Trace(err) return float64(u), errors.Trace(err)
case json.TypeCodeFloat64: case json.TypeCodeFloat64:
return j.GetFloat64(), nil return j.GetFloat64(), nil
......
...@@ -218,6 +218,12 @@ func (d *Datum) SetNull() { ...@@ -218,6 +218,12 @@ func (d *Datum) SetNull() {
d.x = nil d.x = nil
} }
// SetMinNotNull sets datum to minNotNull value.
func (d *Datum) SetMinNotNull() {
d.k = KindMinNotNull
d.x = nil
}
// GetBinaryLiteral gets Bit value // GetBinaryLiteral gets Bit value
func (d *Datum) GetBinaryLiteral() BinaryLiteral { func (d *Datum) GetBinaryLiteral() BinaryLiteral {
return d.b return d.b
...@@ -866,21 +872,21 @@ func (d *Datum) convertToUint(sc *stmtctx.StatementContext, target *FieldType) ( ...@@ -866,21 +872,21 @@ func (d *Datum) convertToUint(sc *stmtctx.StatementContext, target *FieldType) (
) )
switch d.k { switch d.k {
case KindInt64: case KindInt64:
val, err = ConvertIntToUint(d.GetInt64(), upperBound, tp) val, err = ConvertIntToUint(sc, d.GetInt64(), upperBound, tp)
case KindUint64: case KindUint64:
val, err = ConvertUintToUint(d.GetUint64(), upperBound, tp) val, err = ConvertUintToUint(d.GetUint64(), upperBound, tp)
case KindFloat32, KindFloat64: case KindFloat32, KindFloat64:
val, err = ConvertFloatToUint(d.GetFloat64(), upperBound, tp) val, err = ConvertFloatToUint(sc, d.GetFloat64(), upperBound, tp)
case KindString, KindBytes: case KindString, KindBytes:
val, err = StrToUint(sc, d.GetString()) uval, err1 := StrToUint(sc, d.GetString())
if err != nil { if err1 != nil && ErrOverflow.Equal(err1) && !sc.ShouldIgnoreOverflowError() {
return ret, errors.Trace(err) return ret, errors.Trace(err1)
} }
val, err = ConvertUintToUint(val, upperBound, tp) val, err = ConvertUintToUint(uval, upperBound, tp)
if err != nil { if err != nil {
return ret, errors.Trace(err) return ret, errors.Trace(err)
} }
ret.SetUint64(val) err = err1
case KindMysqlTime: case KindMysqlTime:
dec := d.GetMysqlTime().ToNumber() dec := d.GetMysqlTime().ToNumber()
err = dec.Round(dec, 0, ModeHalfEven) err = dec.Round(dec, 0, ModeHalfEven)
...@@ -888,7 +894,7 @@ func (d *Datum) convertToUint(sc *stmtctx.StatementContext, target *FieldType) ( ...@@ -888,7 +894,7 @@ func (d *Datum) convertToUint(sc *stmtctx.StatementContext, target *FieldType) (
if err == nil { if err == nil {
err = err1 err = err1
} }
val, err1 = ConvertIntToUint(ival, upperBound, tp) val, err1 = ConvertIntToUint(sc, ival, upperBound, tp)
if err == nil { if err == nil {
err = err1 err = err1
} }
...@@ -897,18 +903,18 @@ func (d *Datum) convertToUint(sc *stmtctx.StatementContext, target *FieldType) ( ...@@ -897,18 +903,18 @@ func (d *Datum) convertToUint(sc *stmtctx.StatementContext, target *FieldType) (
err = dec.Round(dec, 0, ModeHalfEven) err = dec.Round(dec, 0, ModeHalfEven)
ival, err1 := dec.ToInt() ival, err1 := dec.ToInt()
if err1 == nil { if err1 == nil {
val, err = ConvertIntToUint(ival, upperBound, tp) val, err = ConvertIntToUint(sc, ival, upperBound, tp)
} }
case KindMysqlDecimal: case KindMysqlDecimal:
fval, err1 := d.GetMysqlDecimal().ToFloat64() fval, err1 := d.GetMysqlDecimal().ToFloat64()
val, err = ConvertFloatToUint(fval, upperBound, tp) val, err = ConvertFloatToUint(sc, fval, upperBound, tp)
if err == nil { if err == nil {
err = err1 err = err1
} }
case KindMysqlEnum: case KindMysqlEnum:
val, err = ConvertFloatToUint(d.GetMysqlEnum().ToNumber(), upperBound, tp) val, err = ConvertFloatToUint(sc, d.GetMysqlEnum().ToNumber(), upperBound, tp)
case KindMysqlSet: case KindMysqlSet:
val, err = ConvertFloatToUint(d.GetMysqlSet().ToNumber(), upperBound, tp) val, err = ConvertFloatToUint(sc, d.GetMysqlSet().ToNumber(), upperBound, tp)
case KindBinaryLiteral, KindMysqlBit: case KindBinaryLiteral, KindMysqlBit:
val, err = d.GetBinaryLiteral().ToInt(sc) val, err = d.GetBinaryLiteral().ToInt(sc)
case KindMysqlJSON: case KindMysqlJSON:
...@@ -1138,7 +1144,7 @@ func ProduceDecWithSpecifiedTp(dec *MyDecimal, tp *FieldType, sc *stmtctx.Statem ...@@ -1138,7 +1144,7 @@ func ProduceDecWithSpecifiedTp(dec *MyDecimal, tp *FieldType, sc *stmtctx.Statem
return nil, errors.Trace(err) return nil, errors.Trace(err)
} }
if !dec.IsZero() && frac > decimal && dec.Compare(&old) != 0 { if !dec.IsZero() && frac > decimal && dec.Compare(&old) != 0 {
if sc.InInsertStmt || sc.InUpdateOrDeleteStmt { if sc.InInsertStmt || sc.InUpdateStmt || sc.InDeleteStmt {
// fix https://github.com/pingcap/tidb/issues/3895 // fix https://github.com/pingcap/tidb/issues/3895
// fix https://github.com/pingcap/tidb/issues/5532 // fix https://github.com/pingcap/tidb/issues/5532
sc.AppendWarning(ErrTruncated) sc.AppendWarning(ErrTruncated)
...@@ -1612,75 +1618,6 @@ func (d *Datum) convergeType(hasUint, hasDecimal, hasFloat *bool) (x Datum) { ...@@ -1612,75 +1618,6 @@ func (d *Datum) convergeType(hasUint, hasDecimal, hasFloat *bool) (x Datum) {
return x return x
} }
// CoerceDatum changes type.
// If a or b is Float, changes the both to Float.
// Else if a or b is Decimal, changes the both to Decimal.
// Else if a or b is Uint and op is not div, mod, or intDiv changes the both to Uint.
func CoerceDatum(sc *stmtctx.StatementContext, a, b Datum) (x, y Datum, err error) {
if a.IsNull() || b.IsNull() {
return x, y, nil
}
var hasUint, hasDecimal, hasFloat bool
x = a.convergeType(&hasUint, &hasDecimal, &hasFloat)
y = b.convergeType(&hasUint, &hasDecimal, &hasFloat)
if hasFloat {
switch x.Kind() {
case KindInt64:
x.SetFloat64(float64(x.GetInt64()))
case KindUint64:
x.SetFloat64(float64(x.GetUint64()))
case KindMysqlEnum:
x.SetFloat64(x.GetMysqlEnum().ToNumber())
case KindMysqlSet:
x.SetFloat64(x.GetMysqlSet().ToNumber())
case KindMysqlDecimal:
var fval float64
fval, err = x.ToFloat64(sc)
if err != nil {
return x, y, errors.Trace(err)
}
x.SetFloat64(fval)
}
switch y.Kind() {
case KindInt64:
y.SetFloat64(float64(y.GetInt64()))
case KindUint64:
y.SetFloat64(float64(y.GetUint64()))
case KindBinaryLiteral, KindMysqlBit:
var fval uint64
fval, err = y.GetBinaryLiteral().ToInt(sc)
if err != nil {
return x, y, errors.Trace(err)
}
y.SetFloat64(float64(fval))
case KindMysqlEnum:
y.SetFloat64(y.GetMysqlEnum().ToNumber())
case KindMysqlSet:
y.SetFloat64(y.GetMysqlSet().ToNumber())
case KindMysqlDecimal:
var fval float64
fval, err = y.ToFloat64(sc)
if err != nil {
return x, y, errors.Trace(err)
}
y.SetFloat64(fval)
}
} else if hasDecimal {
var dec *MyDecimal
dec, err = ConvertDatumToDecimal(sc, x)
if err != nil {
return x, y, errors.Trace(err)
}
x.SetMysqlDecimal(dec)
dec, err = ConvertDatumToDecimal(sc, y)
if err != nil {
return x, y, errors.Trace(err)
}
y.SetMysqlDecimal(dec)
}
return
}
// NewDatum creates a new Datum from an interface{}. // NewDatum creates a new Datum from an interface{}.
func NewDatum(in interface{}) (d Datum) { func NewDatum(in interface{}) (d Datum) {
switch x := in.(type) { switch x := in.(type) {
......
...@@ -217,7 +217,7 @@ func (bj BinaryJSON) objectSearchKey(key []byte) (BinaryJSON, bool) { ...@@ -217,7 +217,7 @@ func (bj BinaryJSON) objectSearchKey(key []byte) (BinaryJSON, bool) {
idx := sort.Search(elemCount, func(i int) bool { idx := sort.Search(elemCount, func(i int) bool {
return bytes.Compare(bj.objectGetKey(i), key) >= 0 return bytes.Compare(bj.objectGetKey(i), key) >= 0
}) })
if idx < elemCount && bytes.Compare(bj.objectGetKey(idx), key) == 0 { if idx < elemCount && bytes.Equal(bj.objectGetKey(idx), key) {
return bj.objectGetVal(idx), true return bj.objectGetVal(idx), true
} }
return BinaryJSON{}, false return BinaryJSON{}, false
......
...@@ -234,6 +234,23 @@ func (d *MyDecimal) removeLeadingZeros() (wordIdx int, digitsInt int) { ...@@ -234,6 +234,23 @@ func (d *MyDecimal) removeLeadingZeros() (wordIdx int, digitsInt int) {
return return
} }
func (d *MyDecimal) removeTrailingZeros() (lastWordIdx int, digitsFrac int) {
digitsFrac = int(d.digitsFrac)
i := ((digitsFrac - 1) % digitsPerWord) + 1
lastWordIdx = digitsToWords(int(d.digitsInt)) + digitsToWords(int(d.digitsFrac))
for digitsFrac > 0 && d.wordBuf[lastWordIdx-1] == 0 {
digitsFrac -= i
i = digitsPerWord
lastWordIdx--
}
if digitsFrac > 0 {
digitsFrac -= countTrailingZeroes(9-((digitsFrac-1)%digitsPerWord), d.wordBuf[lastWordIdx-1])
} else {
digitsFrac = 0
}
return
}
// ToString converts decimal to its printable string representation without rounding. // ToString converts decimal to its printable string representation without rounding.
// //
// RETURN VALUE // RETURN VALUE
...@@ -1212,6 +1229,26 @@ func (d *MyDecimal) ToBin(precision, frac int) ([]byte, error) { ...@@ -1212,6 +1229,26 @@ func (d *MyDecimal) ToBin(precision, frac int) ([]byte, error) {
return bin, err return bin, err
} }
// ToHashKey removes the leading and trailing zeros and generates a hash key.
// Two Decimals dec0 and dec1 with different fraction will generate the same hash keys if dec0.Compare(dec1) == 0.
func (d *MyDecimal) ToHashKey() ([]byte, error) {
_, digitsInt := d.removeLeadingZeros()
_, digitsFrac := d.removeTrailingZeros()
prec := digitsInt + digitsFrac
if prec == 0 { // zeroDecimal
prec = 1
}
buf, err := d.ToBin(prec, digitsFrac)
if err == ErrTruncated {
// This err is caused by shorter digitsFrac;
// After removing the trailing zeros from a Decimal,
// so digitsFrac may be less than the real digitsFrac of the Decimal,
// thus ErrTruncated may be raised, we can ignore it here.
err = nil
}
return buf, err
}
// PrecisionAndFrac returns the internal precision and frac number. // PrecisionAndFrac returns the internal precision and frac number.
func (d *MyDecimal) PrecisionAndFrac() (precision, frac int) { func (d *MyDecimal) PrecisionAndFrac() (precision, frac int) {
frac = int(d.digitsFrac) frac = int(d.digitsFrac)
...@@ -1326,7 +1363,6 @@ func (d *MyDecimal) FromBin(bin []byte, precision, frac int) (binSize int, err e ...@@ -1326,7 +1363,6 @@ func (d *MyDecimal) FromBin(bin []byte, precision, frac int) (binSize int, err e
*d = zeroMyDecimal *d = zeroMyDecimal
return binSize, ErrBadNumber return binSize, ErrBadNumber
} }
wordIdx++
} }
if d.digitsInt == 0 && d.digitsFrac == 0 { if d.digitsInt == 0 && d.digitsFrac == 0 {
...@@ -1760,7 +1796,7 @@ func DecimalMul(from1, from2, to *MyDecimal) error { ...@@ -1760,7 +1796,7 @@ func DecimalMul(from1, from2, to *MyDecimal) error {
wordsFracTo = wordsFrac1 + wordsFrac2 wordsFracTo = wordsFrac1 + wordsFrac2
idx1 = wordsInt1 idx1 = wordsInt1
idx2 = wordsInt2 idx2 = wordsInt2
idxTo = 0 idxTo int
tmp1 = wordsIntTo tmp1 = wordsIntTo
tmp2 = wordsFracTo tmp2 = wordsFracTo
) )
...@@ -1991,7 +2027,6 @@ func doDivMod(from1, from2, to, mod *MyDecimal, fracIncr int) error { ...@@ -1991,7 +2027,6 @@ func doDivMod(from1, from2, to, mod *MyDecimal, fracIncr int) error {
idxTo++ idxTo++
digitsIntTo++ digitsIntTo++
} }
digitsIntTo++
} }
i = digitsToWords(prec1) i = digitsToWords(prec1)
len1 := i + digitsToWords(2*frac2+fracIncr+1) + 1 len1 := i + digitsToWords(2*frac2+fracIncr+1) + 1
...@@ -2003,7 +2038,7 @@ func doDivMod(from1, from2, to, mod *MyDecimal, fracIncr int) error { ...@@ -2003,7 +2038,7 @@ func doDivMod(from1, from2, to, mod *MyDecimal, fracIncr int) error {
copy(tmp1, from1.wordBuf[idx1:idx1+i]) copy(tmp1, from1.wordBuf[idx1:idx1+i])
start1 := 0 start1 := 0
stop1 := len1 var stop1 int
start2 := idx2 start2 := idx2
stop2 := idx2 + digitsToWords(prec2) - 1 stop2 := idx2 + digitsToWords(prec2) - 1
......
...@@ -232,8 +232,7 @@ func (v weekBehaviour) test(flag weekBehaviour) bool { ...@@ -232,8 +232,7 @@ func (v weekBehaviour) test(flag weekBehaviour) bool {
} }
func weekMode(mode int) weekBehaviour { func weekMode(mode int) weekBehaviour {
var weekFormat weekBehaviour weekFormat := weekBehaviour(mode & 7)
weekFormat = weekBehaviour(mode & 7)
if (weekFormat & weekBehaviourMondayFirst) == 0 { if (weekFormat & weekBehaviourMondayFirst) == 0 {
weekFormat ^= weekBehaviourFirstWeekday weekFormat ^= weekBehaviourFirstWeekday
} }
......
...@@ -474,18 +474,20 @@ func (t *Time) FromPackedUint(packed uint64) error { ...@@ -474,18 +474,20 @@ func (t *Time) FromPackedUint(packed uint64) error {
// FIXME: See https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_zero_in_date // FIXME: See https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_zero_in_date
func (t *Time) check(sc *stmtctx.StatementContext) error { func (t *Time) check(sc *stmtctx.StatementContext) error {
allowZeroInDate := false allowZeroInDate := false
allowInvalidDate := false
// We should avoid passing sc as nil here as far as possible. // We should avoid passing sc as nil here as far as possible.
if sc != nil { if sc != nil {
allowZeroInDate = sc.IgnoreZeroInDate allowZeroInDate = sc.IgnoreZeroInDate
allowInvalidDate = sc.AllowInvalidDate
} }
var err error var err error
switch t.Type { switch t.Type {
case mysql.TypeTimestamp: case mysql.TypeTimestamp:
err = checkTimestampType(sc, t.Time) err = checkTimestampType(sc, t.Time)
case mysql.TypeDatetime: case mysql.TypeDatetime:
err = checkDatetimeType(t.Time, allowZeroInDate) err = checkDatetimeType(t.Time, allowZeroInDate, allowInvalidDate)
case mysql.TypeDate: case mysql.TypeDate:
err = checkDateType(t.Time, allowZeroInDate) err = checkDateType(t.Time, allowZeroInDate, allowInvalidDate)
} }
return errors.Trace(err) return errors.Trace(err)
} }
...@@ -1344,7 +1346,7 @@ func TimeFromDays(num int64) Time { ...@@ -1344,7 +1346,7 @@ func TimeFromDays(num int64) Time {
} }
} }
func checkDateType(t MysqlTime, allowZeroInDate bool) error { func checkDateType(t MysqlTime, allowZeroInDate, allowInvalidDate bool) error {
year, month, day := t.Year(), t.Month(), t.Day() year, month, day := t.Year(), t.Month(), t.Day()
if year == 0 && month == 0 && day == 0 { if year == 0 && month == 0 && day == 0 {
return nil return nil
...@@ -1358,7 +1360,7 @@ func checkDateType(t MysqlTime, allowZeroInDate bool) error { ...@@ -1358,7 +1360,7 @@ func checkDateType(t MysqlTime, allowZeroInDate bool) error {
return errors.Trace(err) return errors.Trace(err)
} }
if err := checkMonthDay(year, month, day); err != nil { if err := checkMonthDay(year, month, day, allowInvalidDate); err != nil {
return errors.Trace(err) return errors.Trace(err)
} }
...@@ -1377,18 +1379,20 @@ func checkDateRange(t MysqlTime) error { ...@@ -1377,18 +1379,20 @@ func checkDateRange(t MysqlTime) error {
return nil return nil
} }
func checkMonthDay(year, month, day int) error { func checkMonthDay(year, month, day int, allowInvalidDate bool) error {
if month < 0 || month > 12 { if month < 0 || month > 12 {
return errors.Trace(ErrInvalidTimeFormat.GenWithStackByArgs(month)) return errors.Trace(ErrInvalidTimeFormat.GenWithStackByArgs(month))
} }
maxDay := 31 maxDay := 31
if !allowInvalidDate {
if month > 0 { if month > 0 {
maxDay = maxDaysInMonth[month-1] maxDay = maxDaysInMonth[month-1]
} }
if month == 2 && year%4 != 0 { if month == 2 && year%4 != 0 {
maxDay = 28 maxDay = 28
} }
}
if day < 0 || day > maxDay { if day < 0 || day > maxDay {
return errors.Trace(ErrInvalidTimeFormat.GenWithStackByArgs(day)) return errors.Trace(ErrInvalidTimeFormat.GenWithStackByArgs(day))
...@@ -1427,8 +1431,8 @@ func checkTimestampType(sc *stmtctx.StatementContext, t MysqlTime) error { ...@@ -1427,8 +1431,8 @@ func checkTimestampType(sc *stmtctx.StatementContext, t MysqlTime) error {
return nil return nil
} }
func checkDatetimeType(t MysqlTime, allowZeroInDate bool) error { func checkDatetimeType(t MysqlTime, allowZeroInDate, allowInvalidDate bool) error {
if err := checkDateType(t, allowZeroInDate); err != nil { if err := checkDateType(t, allowZeroInDate, allowInvalidDate); err != nil {
return errors.Trace(err) return errors.Trace(err)
} }
...@@ -2027,10 +2031,7 @@ func (t *Time) StrToDate(sc *stmtctx.StatementContext, date, format string) bool ...@@ -2027,10 +2031,7 @@ func (t *Time) StrToDate(sc *stmtctx.StatementContext, date, format string) bool
t.Time = tm t.Time = tm
t.Type = mysql.TypeDatetime t.Type = mysql.TypeDatetime
if t.check(sc) != nil { return t.check(sc) == nil
return false
}
return true
} }
// mysqlTimeFix fixes the MysqlTime use the values in the context. // mysqlTimeFix fixes the MysqlTime use the values in the context.
......
...@@ -53,13 +53,13 @@ type CommitDetails struct { ...@@ -53,13 +53,13 @@ type CommitDetails struct {
func (d ExecDetails) String() string { func (d ExecDetails) String() string {
parts := make([]string, 0, 6) parts := make([]string, 0, 6)
if d.ProcessTime > 0 { if d.ProcessTime > 0 {
parts = append(parts, fmt.Sprintf("process_time:%v", d.ProcessTime)) parts = append(parts, fmt.Sprintf("process_time:%vs", d.ProcessTime.Seconds()))
} }
if d.WaitTime > 0 { if d.WaitTime > 0 {
parts = append(parts, fmt.Sprintf("wait_time:%v", d.WaitTime)) parts = append(parts, fmt.Sprintf("wait_time:%vs", d.WaitTime.Seconds()))
} }
if d.BackoffTime > 0 { if d.BackoffTime > 0 {
parts = append(parts, fmt.Sprintf("backoff_time:%v", d.BackoffTime)) parts = append(parts, fmt.Sprintf("backoff_time:%vs", d.BackoffTime.Seconds()))
} }
if d.RequestCount > 0 { if d.RequestCount > 0 {
parts = append(parts, fmt.Sprintf("request_count:%d", d.RequestCount)) parts = append(parts, fmt.Sprintf("request_count:%d", d.RequestCount))
...@@ -73,23 +73,23 @@ func (d ExecDetails) String() string { ...@@ -73,23 +73,23 @@ func (d ExecDetails) String() string {
commitDetails := d.CommitDetail commitDetails := d.CommitDetail
if commitDetails != nil { if commitDetails != nil {
if commitDetails.PrewriteTime > 0 { if commitDetails.PrewriteTime > 0 {
parts = append(parts, fmt.Sprintf("prewrite_time:%v", commitDetails.PrewriteTime)) parts = append(parts, fmt.Sprintf("prewrite_time:%vs", commitDetails.PrewriteTime.Seconds()))
} }
if commitDetails.CommitTime > 0 { if commitDetails.CommitTime > 0 {
parts = append(parts, fmt.Sprintf("commit_time:%v", commitDetails.CommitTime)) parts = append(parts, fmt.Sprintf("commit_time:%vs", commitDetails.CommitTime.Seconds()))
} }
if commitDetails.GetCommitTsTime > 0 { if commitDetails.GetCommitTsTime > 0 {
parts = append(parts, fmt.Sprintf("get_commit_ts_time:%v", commitDetails.GetCommitTsTime)) parts = append(parts, fmt.Sprintf("get_commit_ts_time:%vs", commitDetails.GetCommitTsTime.Seconds()))
} }
if commitDetails.TotalBackoffTime > 0 { if commitDetails.TotalBackoffTime > 0 {
parts = append(parts, fmt.Sprintf("total_backoff_time:%v", commitDetails.TotalBackoffTime)) parts = append(parts, fmt.Sprintf("total_backoff_time:%vs", commitDetails.TotalBackoffTime.Seconds()))
} }
resolveLockTime := atomic.LoadInt64(&commitDetails.ResolveLockTime) resolveLockTime := atomic.LoadInt64(&commitDetails.ResolveLockTime)
if resolveLockTime > 0 { if resolveLockTime > 0 {
parts = append(parts, fmt.Sprintf("resolve_lock_time:%d", time.Duration(resolveLockTime))) parts = append(parts, fmt.Sprintf("resolve_lock_time:%vs", time.Duration(resolveLockTime).Seconds()))
} }
if commitDetails.LocalLatchTime > 0 { if commitDetails.LocalLatchTime > 0 {
parts = append(parts, fmt.Sprintf("local_latch_wait_time:%v", commitDetails.LocalLatchTime)) parts = append(parts, fmt.Sprintf("local_latch_wait_time:%vs", commitDetails.LocalLatchTime.Seconds()))
} }
if commitDetails.WriteKeys > 0 { if commitDetails.WriteKeys > 0 {
parts = append(parts, fmt.Sprintf("write_keys:%d", commitDetails.WriteKeys)) parts = append(parts, fmt.Sprintf("write_keys:%d", commitDetails.WriteKeys))
......
...@@ -111,106 +111,106 @@ ...@@ -111,106 +111,106 @@
"revisionTime": "2018-10-24T15:10:47Z" "revisionTime": "2018-10-24T15:10:47Z"
}, },
{ {
"checksumSHA1": "DJypl3jfSRspsBR2fc6eyBktkq4=", "checksumSHA1": "g4MBFiIkIQ8l4DWYGu60F8jPamQ=",
"path": "github.com/pingcap/parser", "path": "github.com/pingcap/parser",
"revision": "35fab0be7fca9ea7f7b5350af83a8d1e2775abe4", "revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade",
"revisionTime": "2019-01-08T10:41:42Z" "revisionTime": "2019-01-20T15:33:11Z"
}, },
{ {
"checksumSHA1": "+IqkkjB5E83Q1mUjZ1V+75iHocA=", "checksumSHA1": "n+s4Mdz2iK2Bm5LtsGr1vE6KE6A=",
"path": "github.com/pingcap/parser/ast", "path": "github.com/pingcap/parser/ast",
"revision": "35fab0be7fca9ea7f7b5350af83a8d1e2775abe4", "revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade",
"revisionTime": "2019-01-08T10:41:42Z" "revisionTime": "2019-01-20T15:33:11Z"
}, },
{ {
"checksumSHA1": "skWGV4FNvD3vr+5olepaPPnylUw=", "checksumSHA1": "skWGV4FNvD3vr+5olepaPPnylUw=",
"path": "github.com/pingcap/parser/auth", "path": "github.com/pingcap/parser/auth",
"revision": "35fab0be7fca9ea7f7b5350af83a8d1e2775abe4", "revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade",
"revisionTime": "2019-01-08T10:41:42Z" "revisionTime": "2019-01-20T15:33:11Z"
}, },
{ {
"checksumSHA1": "t4UHo966WzU9Z0IJkyGHRp0loOk=", "checksumSHA1": "t4UHo966WzU9Z0IJkyGHRp0loOk=",
"path": "github.com/pingcap/parser/charset", "path": "github.com/pingcap/parser/charset",
"revision": "35fab0be7fca9ea7f7b5350af83a8d1e2775abe4", "revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade",
"revisionTime": "2019-01-08T10:41:42Z" "revisionTime": "2019-01-20T15:33:11Z"
}, },
{ {
"checksumSHA1": "ohLJW2u9NJEzYIJL/AjOqcuKfMY=", "checksumSHA1": "ohLJW2u9NJEzYIJL/AjOqcuKfMY=",
"path": "github.com/pingcap/parser/format", "path": "github.com/pingcap/parser/format",
"revision": "35fab0be7fca9ea7f7b5350af83a8d1e2775abe4", "revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade",
"revisionTime": "2019-01-08T10:41:42Z" "revisionTime": "2019-01-20T15:33:11Z"
}, },
{ {
"checksumSHA1": "ZADwr2/PcEd9VI3XF9OvN4HkJ+8=", "checksumSHA1": "ZADwr2/PcEd9VI3XF9OvN4HkJ+8=",
"path": "github.com/pingcap/parser/model", "path": "github.com/pingcap/parser/model",
"revision": "35fab0be7fca9ea7f7b5350af83a8d1e2775abe4", "revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade",
"revisionTime": "2019-01-08T10:41:42Z" "revisionTime": "2019-01-20T15:33:11Z"
}, },
{ {
"checksumSHA1": "ge+W5BLlgqKIlvmappsPTLgVJLk=", "checksumSHA1": "0YvCqsNHKFZEA7vfi3Fq+eYkjW4=",
"path": "github.com/pingcap/parser/mysql", "path": "github.com/pingcap/parser/mysql",
"revision": "35fab0be7fca9ea7f7b5350af83a8d1e2775abe4", "revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade",
"revisionTime": "2019-01-08T10:41:42Z" "revisionTime": "2019-01-20T15:33:11Z"
}, },
{ {
"checksumSHA1": "mxpiJJ3b08I0o0Sd2rJLYMwz7uw=", "checksumSHA1": "olapD16WCMBU9vrA5PtlERGFfXw=",
"path": "github.com/pingcap/parser/opcode", "path": "github.com/pingcap/parser/opcode",
"revision": "35fab0be7fca9ea7f7b5350af83a8d1e2775abe4", "revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade",
"revisionTime": "2019-01-08T10:41:42Z" "revisionTime": "2019-01-20T15:33:11Z"
}, },
{ {
"checksumSHA1": "XvnUllvwMYd6HrMvMiKnn4cGN2M=", "checksumSHA1": "TF2rMYy9ewgZpFsJb+jaGXXqZqc=",
"path": "github.com/pingcap/parser/terror", "path": "github.com/pingcap/parser/terror",
"revision": "35fab0be7fca9ea7f7b5350af83a8d1e2775abe4", "revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade",
"revisionTime": "2019-01-08T10:41:42Z" "revisionTime": "2019-01-20T15:33:11Z"
}, },
{ {
"checksumSHA1": "CpuZhpMNeho4tIFPwY2GUDvuEfQ=", "checksumSHA1": "sCYsaxxXBau10NOc5tuYQEtmAu0=",
"path": "github.com/pingcap/parser/types", "path": "github.com/pingcap/parser/types",
"revision": "35fab0be7fca9ea7f7b5350af83a8d1e2775abe4", "revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade",
"revisionTime": "2019-01-08T10:41:42Z" "revisionTime": "2019-01-20T15:33:11Z"
}, },
{ {
"checksumSHA1": "MxoLdFWi8nwd0uqTJnYqw+JaDAY=", "checksumSHA1": "uOrWw9c47zwN6COxonFJ0t2IMcM=",
"path": "github.com/pingcap/tidb/sessionctx/stmtctx", "path": "github.com/pingcap/tidb/sessionctx/stmtctx",
"revision": "c68ee7318319b34fbad53d5abf18275b0273ae41", "revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70",
"revisionTime": "2019-01-08T12:33:36Z" "revisionTime": "2019-01-20T14:44:10Z"
}, },
{ {
"checksumSHA1": "1PFyexjkPlACP5S2pRrT6TsjcQ0=", "checksumSHA1": "kENit8Wf5S1qoj0HVt2GIgH1khI=",
"path": "github.com/pingcap/tidb/types", "path": "github.com/pingcap/tidb/types",
"revision": "c68ee7318319b34fbad53d5abf18275b0273ae41", "revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70",
"revisionTime": "2019-01-08T12:33:36Z" "revisionTime": "2019-01-20T14:44:10Z"
}, },
{ {
"checksumSHA1": "DWVD7+ygtT66IQ+cqXmMJ5OVqUk=", "checksumSHA1": "7PiTQPW4ftgZIg8KBGCHZjdc0hE=",
"path": "github.com/pingcap/tidb/types/json", "path": "github.com/pingcap/tidb/types/json",
"revision": "c68ee7318319b34fbad53d5abf18275b0273ae41", "revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70",
"revisionTime": "2019-01-08T12:33:36Z" "revisionTime": "2019-01-20T14:44:10Z"
}, },
{ {
"checksumSHA1": "yKeU1hJFc7X3afXESYV0Wz5ZPXQ=", "checksumSHA1": "yKeU1hJFc7X3afXESYV0Wz5ZPXQ=",
"path": "github.com/pingcap/tidb/types/parser_driver", "path": "github.com/pingcap/tidb/types/parser_driver",
"revision": "c68ee7318319b34fbad53d5abf18275b0273ae41", "revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70",
"revisionTime": "2019-01-08T12:33:36Z" "revisionTime": "2019-01-20T14:44:10Z"
}, },
{ {
"checksumSHA1": "SS7twHZofFKr8w/pwIKmkp3u5qU=", "checksumSHA1": "OOig47D9TSVOUAYkNj2yJok1Hmo=",
"path": "github.com/pingcap/tidb/util/execdetails", "path": "github.com/pingcap/tidb/util/execdetails",
"revision": "c68ee7318319b34fbad53d5abf18275b0273ae41", "revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70",
"revisionTime": "2019-01-08T12:33:36Z" "revisionTime": "2019-01-20T14:44:10Z"
}, },
{ {
"checksumSHA1": "nUC7zVoAMNR2a+z2iGqHoN2AkFE=", "checksumSHA1": "nUC7zVoAMNR2a+z2iGqHoN2AkFE=",
"path": "github.com/pingcap/tidb/util/hack", "path": "github.com/pingcap/tidb/util/hack",
"revision": "c68ee7318319b34fbad53d5abf18275b0273ae41", "revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70",
"revisionTime": "2019-01-08T12:33:36Z" "revisionTime": "2019-01-20T14:44:10Z"
}, },
{ {
"checksumSHA1": "xSyepiuqsoaaeDch7cXeumvVHKM=", "checksumSHA1": "xSyepiuqsoaaeDch7cXeumvVHKM=",
"path": "github.com/pingcap/tidb/util/memory", "path": "github.com/pingcap/tidb/util/memory",
"revision": "c68ee7318319b34fbad53d5abf18275b0273ae41", "revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70",
"revisionTime": "2019-01-08T12:33:36Z" "revisionTime": "2019-01-20T14:44:10Z"
}, },
{ {
"checksumSHA1": "SmYeIK/fIYXNu8IKxD6HOVQVTuU=", "checksumSHA1": "SmYeIK/fIYXNu8IKxD6HOVQVTuU=",
...@@ -407,62 +407,62 @@ ...@@ -407,62 +407,62 @@
{ {
"checksumSHA1": "aKn1oKcY74N8TRLm3Ayt7Q4bbI4=", "checksumSHA1": "aKn1oKcY74N8TRLm3Ayt7Q4bbI4=",
"path": "vitess.io/vitess/go/bytes2", "path": "vitess.io/vitess/go/bytes2",
"revision": "42f5c760cca59b18c4ea877284f36eb0be7d6468", "revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665",
"revisionTime": "2019-01-06T20:12:04Z" "revisionTime": "2019-01-19T07:50:08Z"
}, },
{ {
"checksumSHA1": "JVCEN4UGRmg3TofIBdzZMZ3G0Ww=", "checksumSHA1": "JVCEN4UGRmg3TofIBdzZMZ3G0Ww=",
"path": "vitess.io/vitess/go/hack", "path": "vitess.io/vitess/go/hack",
"revision": "42f5c760cca59b18c4ea877284f36eb0be7d6468", "revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665",
"revisionTime": "2019-01-06T20:12:04Z" "revisionTime": "2019-01-19T07:50:08Z"
}, },
{ {
"checksumSHA1": "F5pcGq+2W1FHEjgktTdKOE6W8mk=", "checksumSHA1": "F5pcGq+2W1FHEjgktTdKOE6W8mk=",
"path": "vitess.io/vitess/go/sqltypes", "path": "vitess.io/vitess/go/sqltypes",
"revision": "42f5c760cca59b18c4ea877284f36eb0be7d6468", "revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665",
"revisionTime": "2019-01-06T20:12:04Z" "revisionTime": "2019-01-19T07:50:08Z"
}, },
{ {
"checksumSHA1": "ntFIQYkBS51G6y+FEkjFW40+HOU=", "checksumSHA1": "vAIRxI6MHsq3x1hLQwIyw5AvqtI=",
"path": "vitess.io/vitess/go/vt/log", "path": "vitess.io/vitess/go/vt/log",
"revision": "42f5c760cca59b18c4ea877284f36eb0be7d6468", "revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665",
"revisionTime": "2019-01-06T20:12:04Z" "revisionTime": "2019-01-19T07:50:08Z"
}, },
{ {
"checksumSHA1": "HHIcl3lpWkzLARkkNv94fVaObjo=", "checksumSHA1": "quYYG+uo3v5HIKvG4QQtRhLC0HY=",
"path": "vitess.io/vitess/go/vt/proto/query", "path": "vitess.io/vitess/go/vt/proto/query",
"revision": "42f5c760cca59b18c4ea877284f36eb0be7d6468", "revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665",
"revisionTime": "2019-01-06T20:12:04Z" "revisionTime": "2019-01-19T07:50:08Z"
}, },
{ {
"checksumSHA1": "YLWTmL+rvz0htn0niRMrIUI6rKc=", "checksumSHA1": "YLWTmL+rvz0htn0niRMrIUI6rKc=",
"path": "vitess.io/vitess/go/vt/proto/topodata", "path": "vitess.io/vitess/go/vt/proto/topodata",
"revision": "42f5c760cca59b18c4ea877284f36eb0be7d6468", "revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665",
"revisionTime": "2019-01-06T20:12:04Z" "revisionTime": "2019-01-19T07:50:08Z"
}, },
{ {
"checksumSHA1": "tNNlcSFFnlOauS2hXnrz/zA/wfk=", "checksumSHA1": "tNNlcSFFnlOauS2hXnrz/zA/wfk=",
"path": "vitess.io/vitess/go/vt/proto/vtgate", "path": "vitess.io/vitess/go/vt/proto/vtgate",
"revision": "42f5c760cca59b18c4ea877284f36eb0be7d6468", "revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665",
"revisionTime": "2019-01-06T20:12:04Z" "revisionTime": "2019-01-19T07:50:08Z"
}, },
{ {
"checksumSHA1": "qz32abYdmm9NfKTc++K0l1EvXXM=", "checksumSHA1": "qz32abYdmm9NfKTc++K0l1EvXXM=",
"path": "vitess.io/vitess/go/vt/proto/vtrpc", "path": "vitess.io/vitess/go/vt/proto/vtrpc",
"revision": "42f5c760cca59b18c4ea877284f36eb0be7d6468", "revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665",
"revisionTime": "2019-01-06T20:12:04Z" "revisionTime": "2019-01-19T07:50:08Z"
}, },
{ {
"checksumSHA1": "IDe+9Bn42lZVsuoYO/epdguiErk=", "checksumSHA1": "3yiiEdMrUONYMNI84Bs/KONvW94=",
"path": "vitess.io/vitess/go/vt/sqlparser", "path": "vitess.io/vitess/go/vt/sqlparser",
"revision": "42f5c760cca59b18c4ea877284f36eb0be7d6468", "revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665",
"revisionTime": "2019-01-06T20:12:04Z" "revisionTime": "2019-01-19T07:50:08Z"
}, },
{ {
"checksumSHA1": "Jx+gOh/kiBDSZxEIWHyYn9brjdo=", "checksumSHA1": "Jx+gOh/kiBDSZxEIWHyYn9brjdo=",
"path": "vitess.io/vitess/go/vt/vterrors", "path": "vitess.io/vitess/go/vt/vterrors",
"revision": "42f5c760cca59b18c4ea877284f36eb0be7d6468", "revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665",
"revisionTime": "2019-01-06T20:12:04Z" "revisionTime": "2019-01-19T07:50:08Z"
} }
], ],
"rootPath": "github.com/XiaoMi/soar" "rootPath": "github.com/XiaoMi/soar"
......
...@@ -5,7 +5,10 @@ ...@@ -5,7 +5,10 @@
package log package log
import "github.com/golang/glog" import (
"flag"
"github.com/golang/glog"
)
// Level is used with V() to test log verbosity. // Level is used with V() to test log verbosity.
type Level = glog.Level type Level = glog.Level
...@@ -52,3 +55,7 @@ var ( ...@@ -52,3 +55,7 @@ var (
// FatalDepth formats arguments like fmt.Print and uses depth to choose which call frame to log. // FatalDepth formats arguments like fmt.Print and uses depth to choose which call frame to log.
FatalDepth = glog.FatalDepth FatalDepth = glog.FatalDepth
) )
func init() {
flag.Uint64Var(&glog.MaxSize, "log_rotate_max_size", glog.MaxSize, "size in bytes at which logs are rotated (glog.MaxSize)")
}
...@@ -95,7 +95,7 @@ func (x MySqlFlag) String() string { ...@@ -95,7 +95,7 @@ func (x MySqlFlag) String() string {
return proto.EnumName(MySqlFlag_name, int32(x)) return proto.EnumName(MySqlFlag_name, int32(x))
} }
func (MySqlFlag) EnumDescriptor() ([]byte, []int) { func (MySqlFlag) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{0} return fileDescriptor_query_b0bca749772b6512, []int{0}
} }
// Flag allows us to qualify types by their common properties. // Flag allows us to qualify types by their common properties.
...@@ -134,7 +134,7 @@ func (x Flag) String() string { ...@@ -134,7 +134,7 @@ func (x Flag) String() string {
return proto.EnumName(Flag_name, int32(x)) return proto.EnumName(Flag_name, int32(x))
} }
func (Flag) EnumDescriptor() ([]byte, []int) { func (Flag) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{1} return fileDescriptor_query_b0bca749772b6512, []int{1}
} }
// Type defines the various supported data types in bind vars // Type defines the various supported data types in bind vars
...@@ -315,7 +315,7 @@ func (x Type) String() string { ...@@ -315,7 +315,7 @@ func (x Type) String() string {
return proto.EnumName(Type_name, int32(x)) return proto.EnumName(Type_name, int32(x))
} }
func (Type) EnumDescriptor() ([]byte, []int) { func (Type) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{2} return fileDescriptor_query_b0bca749772b6512, []int{2}
} }
// TransactionState represents the state of a distributed transaction. // TransactionState represents the state of a distributed transaction.
...@@ -345,7 +345,7 @@ func (x TransactionState) String() string { ...@@ -345,7 +345,7 @@ func (x TransactionState) String() string {
return proto.EnumName(TransactionState_name, int32(x)) return proto.EnumName(TransactionState_name, int32(x))
} }
func (TransactionState) EnumDescriptor() ([]byte, []int) { func (TransactionState) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{3} return fileDescriptor_query_b0bca749772b6512, []int{3}
} }
type ExecuteOptions_IncludedFields int32 type ExecuteOptions_IncludedFields int32
...@@ -371,7 +371,7 @@ func (x ExecuteOptions_IncludedFields) String() string { ...@@ -371,7 +371,7 @@ func (x ExecuteOptions_IncludedFields) String() string {
return proto.EnumName(ExecuteOptions_IncludedFields_name, int32(x)) return proto.EnumName(ExecuteOptions_IncludedFields_name, int32(x))
} }
func (ExecuteOptions_IncludedFields) EnumDescriptor() ([]byte, []int) { func (ExecuteOptions_IncludedFields) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{6, 0} return fileDescriptor_query_b0bca749772b6512, []int{6, 0}
} }
type ExecuteOptions_Workload int32 type ExecuteOptions_Workload int32
...@@ -400,7 +400,7 @@ func (x ExecuteOptions_Workload) String() string { ...@@ -400,7 +400,7 @@ func (x ExecuteOptions_Workload) String() string {
return proto.EnumName(ExecuteOptions_Workload_name, int32(x)) return proto.EnumName(ExecuteOptions_Workload_name, int32(x))
} }
func (ExecuteOptions_Workload) EnumDescriptor() ([]byte, []int) { func (ExecuteOptions_Workload) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{6, 1} return fileDescriptor_query_b0bca749772b6512, []int{6, 1}
} }
type ExecuteOptions_TransactionIsolation int32 type ExecuteOptions_TransactionIsolation int32
...@@ -411,6 +411,9 @@ const ( ...@@ -411,6 +411,9 @@ const (
ExecuteOptions_READ_COMMITTED ExecuteOptions_TransactionIsolation = 2 ExecuteOptions_READ_COMMITTED ExecuteOptions_TransactionIsolation = 2
ExecuteOptions_READ_UNCOMMITTED ExecuteOptions_TransactionIsolation = 3 ExecuteOptions_READ_UNCOMMITTED ExecuteOptions_TransactionIsolation = 3
ExecuteOptions_SERIALIZABLE ExecuteOptions_TransactionIsolation = 4 ExecuteOptions_SERIALIZABLE ExecuteOptions_TransactionIsolation = 4
// This is not an "official" transaction level but it will do a
// START TRANSACTION WITH CONSISTENT SNAPSHOT, READ ONLY
ExecuteOptions_CONSISTENT_SNAPSHOT_READ_ONLY ExecuteOptions_TransactionIsolation = 5
) )
var ExecuteOptions_TransactionIsolation_name = map[int32]string{ var ExecuteOptions_TransactionIsolation_name = map[int32]string{
...@@ -419,6 +422,7 @@ var ExecuteOptions_TransactionIsolation_name = map[int32]string{ ...@@ -419,6 +422,7 @@ var ExecuteOptions_TransactionIsolation_name = map[int32]string{
2: "READ_COMMITTED", 2: "READ_COMMITTED",
3: "READ_UNCOMMITTED", 3: "READ_UNCOMMITTED",
4: "SERIALIZABLE", 4: "SERIALIZABLE",
5: "CONSISTENT_SNAPSHOT_READ_ONLY",
} }
var ExecuteOptions_TransactionIsolation_value = map[string]int32{ var ExecuteOptions_TransactionIsolation_value = map[string]int32{
"DEFAULT": 0, "DEFAULT": 0,
...@@ -426,13 +430,14 @@ var ExecuteOptions_TransactionIsolation_value = map[string]int32{ ...@@ -426,13 +430,14 @@ var ExecuteOptions_TransactionIsolation_value = map[string]int32{
"READ_COMMITTED": 2, "READ_COMMITTED": 2,
"READ_UNCOMMITTED": 3, "READ_UNCOMMITTED": 3,
"SERIALIZABLE": 4, "SERIALIZABLE": 4,
"CONSISTENT_SNAPSHOT_READ_ONLY": 5,
} }
func (x ExecuteOptions_TransactionIsolation) String() string { func (x ExecuteOptions_TransactionIsolation) String() string {
return proto.EnumName(ExecuteOptions_TransactionIsolation_name, int32(x)) return proto.EnumName(ExecuteOptions_TransactionIsolation_name, int32(x))
} }
func (ExecuteOptions_TransactionIsolation) EnumDescriptor() ([]byte, []int) { func (ExecuteOptions_TransactionIsolation) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{6, 2} return fileDescriptor_query_b0bca749772b6512, []int{6, 2}
} }
// The category of one statement. // The category of one statement.
...@@ -459,7 +464,7 @@ func (x StreamEvent_Statement_Category) String() string { ...@@ -459,7 +464,7 @@ func (x StreamEvent_Statement_Category) String() string {
return proto.EnumName(StreamEvent_Statement_Category_name, int32(x)) return proto.EnumName(StreamEvent_Statement_Category_name, int32(x))
} }
func (StreamEvent_Statement_Category) EnumDescriptor() ([]byte, []int) { func (StreamEvent_Statement_Category) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{12, 0, 0} return fileDescriptor_query_b0bca749772b6512, []int{12, 0, 0}
} }
type SplitQueryRequest_Algorithm int32 type SplitQueryRequest_Algorithm int32
...@@ -482,7 +487,7 @@ func (x SplitQueryRequest_Algorithm) String() string { ...@@ -482,7 +487,7 @@ func (x SplitQueryRequest_Algorithm) String() string {
return proto.EnumName(SplitQueryRequest_Algorithm_name, int32(x)) return proto.EnumName(SplitQueryRequest_Algorithm_name, int32(x))
} }
func (SplitQueryRequest_Algorithm) EnumDescriptor() ([]byte, []int) { func (SplitQueryRequest_Algorithm) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{50, 0} return fileDescriptor_query_b0bca749772b6512, []int{50, 0}
} }
// Target describes what the client expects the tablet is. // Target describes what the client expects the tablet is.
...@@ -503,7 +508,7 @@ func (m *Target) Reset() { *m = Target{} } ...@@ -503,7 +508,7 @@ func (m *Target) Reset() { *m = Target{} }
func (m *Target) String() string { return proto.CompactTextString(m) } func (m *Target) String() string { return proto.CompactTextString(m) }
func (*Target) ProtoMessage() {} func (*Target) ProtoMessage() {}
func (*Target) Descriptor() ([]byte, []int) { func (*Target) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{0} return fileDescriptor_query_b0bca749772b6512, []int{0}
} }
func (m *Target) XXX_Unmarshal(b []byte) error { func (m *Target) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Target.Unmarshal(m, b) return xxx_messageInfo_Target.Unmarshal(m, b)
...@@ -571,7 +576,7 @@ func (m *VTGateCallerID) Reset() { *m = VTGateCallerID{} } ...@@ -571,7 +576,7 @@ func (m *VTGateCallerID) Reset() { *m = VTGateCallerID{} }
func (m *VTGateCallerID) String() string { return proto.CompactTextString(m) } func (m *VTGateCallerID) String() string { return proto.CompactTextString(m) }
func (*VTGateCallerID) ProtoMessage() {} func (*VTGateCallerID) ProtoMessage() {}
func (*VTGateCallerID) Descriptor() ([]byte, []int) { func (*VTGateCallerID) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{1} return fileDescriptor_query_b0bca749772b6512, []int{1}
} }
func (m *VTGateCallerID) XXX_Unmarshal(b []byte) error { func (m *VTGateCallerID) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_VTGateCallerID.Unmarshal(m, b) return xxx_messageInfo_VTGateCallerID.Unmarshal(m, b)
...@@ -627,7 +632,7 @@ func (m *EventToken) Reset() { *m = EventToken{} } ...@@ -627,7 +632,7 @@ func (m *EventToken) Reset() { *m = EventToken{} }
func (m *EventToken) String() string { return proto.CompactTextString(m) } func (m *EventToken) String() string { return proto.CompactTextString(m) }
func (*EventToken) ProtoMessage() {} func (*EventToken) ProtoMessage() {}
func (*EventToken) Descriptor() ([]byte, []int) { func (*EventToken) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{2} return fileDescriptor_query_b0bca749772b6512, []int{2}
} }
func (m *EventToken) XXX_Unmarshal(b []byte) error { func (m *EventToken) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_EventToken.Unmarshal(m, b) return xxx_messageInfo_EventToken.Unmarshal(m, b)
...@@ -681,7 +686,7 @@ func (m *Value) Reset() { *m = Value{} } ...@@ -681,7 +686,7 @@ func (m *Value) Reset() { *m = Value{} }
func (m *Value) String() string { return proto.CompactTextString(m) } func (m *Value) String() string { return proto.CompactTextString(m) }
func (*Value) ProtoMessage() {} func (*Value) ProtoMessage() {}
func (*Value) Descriptor() ([]byte, []int) { func (*Value) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{3} return fileDescriptor_query_b0bca749772b6512, []int{3}
} }
func (m *Value) XXX_Unmarshal(b []byte) error { func (m *Value) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Value.Unmarshal(m, b) return xxx_messageInfo_Value.Unmarshal(m, b)
...@@ -730,7 +735,7 @@ func (m *BindVariable) Reset() { *m = BindVariable{} } ...@@ -730,7 +735,7 @@ func (m *BindVariable) Reset() { *m = BindVariable{} }
func (m *BindVariable) String() string { return proto.CompactTextString(m) } func (m *BindVariable) String() string { return proto.CompactTextString(m) }
func (*BindVariable) ProtoMessage() {} func (*BindVariable) ProtoMessage() {}
func (*BindVariable) Descriptor() ([]byte, []int) { func (*BindVariable) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{4} return fileDescriptor_query_b0bca749772b6512, []int{4}
} }
func (m *BindVariable) XXX_Unmarshal(b []byte) error { func (m *BindVariable) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BindVariable.Unmarshal(m, b) return xxx_messageInfo_BindVariable.Unmarshal(m, b)
...@@ -787,7 +792,7 @@ func (m *BoundQuery) Reset() { *m = BoundQuery{} } ...@@ -787,7 +792,7 @@ func (m *BoundQuery) Reset() { *m = BoundQuery{} }
func (m *BoundQuery) String() string { return proto.CompactTextString(m) } func (m *BoundQuery) String() string { return proto.CompactTextString(m) }
func (*BoundQuery) ProtoMessage() {} func (*BoundQuery) ProtoMessage() {}
func (*BoundQuery) Descriptor() ([]byte, []int) { func (*BoundQuery) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{5} return fileDescriptor_query_b0bca749772b6512, []int{5}
} }
func (m *BoundQuery) XXX_Unmarshal(b []byte) error { func (m *BoundQuery) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BoundQuery.Unmarshal(m, b) return xxx_messageInfo_BoundQuery.Unmarshal(m, b)
...@@ -861,7 +866,7 @@ func (m *ExecuteOptions) Reset() { *m = ExecuteOptions{} } ...@@ -861,7 +866,7 @@ func (m *ExecuteOptions) Reset() { *m = ExecuteOptions{} }
func (m *ExecuteOptions) String() string { return proto.CompactTextString(m) } func (m *ExecuteOptions) String() string { return proto.CompactTextString(m) }
func (*ExecuteOptions) ProtoMessage() {} func (*ExecuteOptions) ProtoMessage() {}
func (*ExecuteOptions) Descriptor() ([]byte, []int) { func (*ExecuteOptions) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{6} return fileDescriptor_query_b0bca749772b6512, []int{6}
} }
func (m *ExecuteOptions) XXX_Unmarshal(b []byte) error { func (m *ExecuteOptions) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ExecuteOptions.Unmarshal(m, b) return xxx_messageInfo_ExecuteOptions.Unmarshal(m, b)
...@@ -967,7 +972,7 @@ func (m *Field) Reset() { *m = Field{} } ...@@ -967,7 +972,7 @@ func (m *Field) Reset() { *m = Field{} }
func (m *Field) String() string { return proto.CompactTextString(m) } func (m *Field) String() string { return proto.CompactTextString(m) }
func (*Field) ProtoMessage() {} func (*Field) ProtoMessage() {}
func (*Field) Descriptor() ([]byte, []int) { func (*Field) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{7} return fileDescriptor_query_b0bca749772b6512, []int{7}
} }
func (m *Field) XXX_Unmarshal(b []byte) error { func (m *Field) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Field.Unmarshal(m, b) return xxx_messageInfo_Field.Unmarshal(m, b)
...@@ -1075,7 +1080,7 @@ func (m *Row) Reset() { *m = Row{} } ...@@ -1075,7 +1080,7 @@ func (m *Row) Reset() { *m = Row{} }
func (m *Row) String() string { return proto.CompactTextString(m) } func (m *Row) String() string { return proto.CompactTextString(m) }
func (*Row) ProtoMessage() {} func (*Row) ProtoMessage() {}
func (*Row) Descriptor() ([]byte, []int) { func (*Row) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{8} return fileDescriptor_query_b0bca749772b6512, []int{8}
} }
func (m *Row) XXX_Unmarshal(b []byte) error { func (m *Row) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Row.Unmarshal(m, b) return xxx_messageInfo_Row.Unmarshal(m, b)
...@@ -1127,7 +1132,7 @@ func (m *ResultExtras) Reset() { *m = ResultExtras{} } ...@@ -1127,7 +1132,7 @@ func (m *ResultExtras) Reset() { *m = ResultExtras{} }
func (m *ResultExtras) String() string { return proto.CompactTextString(m) } func (m *ResultExtras) String() string { return proto.CompactTextString(m) }
func (*ResultExtras) ProtoMessage() {} func (*ResultExtras) ProtoMessage() {}
func (*ResultExtras) Descriptor() ([]byte, []int) { func (*ResultExtras) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{9} return fileDescriptor_query_b0bca749772b6512, []int{9}
} }
func (m *ResultExtras) XXX_Unmarshal(b []byte) error { func (m *ResultExtras) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ResultExtras.Unmarshal(m, b) return xxx_messageInfo_ResultExtras.Unmarshal(m, b)
...@@ -1185,7 +1190,7 @@ func (m *QueryResult) Reset() { *m = QueryResult{} } ...@@ -1185,7 +1190,7 @@ func (m *QueryResult) Reset() { *m = QueryResult{} }
func (m *QueryResult) String() string { return proto.CompactTextString(m) } func (m *QueryResult) String() string { return proto.CompactTextString(m) }
func (*QueryResult) ProtoMessage() {} func (*QueryResult) ProtoMessage() {}
func (*QueryResult) Descriptor() ([]byte, []int) { func (*QueryResult) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{10} return fileDescriptor_query_b0bca749772b6512, []int{10}
} }
func (m *QueryResult) XXX_Unmarshal(b []byte) error { func (m *QueryResult) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_QueryResult.Unmarshal(m, b) return xxx_messageInfo_QueryResult.Unmarshal(m, b)
...@@ -1254,7 +1259,7 @@ func (m *QueryWarning) Reset() { *m = QueryWarning{} } ...@@ -1254,7 +1259,7 @@ func (m *QueryWarning) Reset() { *m = QueryWarning{} }
func (m *QueryWarning) String() string { return proto.CompactTextString(m) } func (m *QueryWarning) String() string { return proto.CompactTextString(m) }
func (*QueryWarning) ProtoMessage() {} func (*QueryWarning) ProtoMessage() {}
func (*QueryWarning) Descriptor() ([]byte, []int) { func (*QueryWarning) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{11} return fileDescriptor_query_b0bca749772b6512, []int{11}
} }
func (m *QueryWarning) XXX_Unmarshal(b []byte) error { func (m *QueryWarning) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_QueryWarning.Unmarshal(m, b) return xxx_messageInfo_QueryWarning.Unmarshal(m, b)
...@@ -1305,7 +1310,7 @@ func (m *StreamEvent) Reset() { *m = StreamEvent{} } ...@@ -1305,7 +1310,7 @@ func (m *StreamEvent) Reset() { *m = StreamEvent{} }
func (m *StreamEvent) String() string { return proto.CompactTextString(m) } func (m *StreamEvent) String() string { return proto.CompactTextString(m) }
func (*StreamEvent) ProtoMessage() {} func (*StreamEvent) ProtoMessage() {}
func (*StreamEvent) Descriptor() ([]byte, []int) { func (*StreamEvent) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{12} return fileDescriptor_query_b0bca749772b6512, []int{12}
} }
func (m *StreamEvent) XXX_Unmarshal(b []byte) error { func (m *StreamEvent) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StreamEvent.Unmarshal(m, b) return xxx_messageInfo_StreamEvent.Unmarshal(m, b)
...@@ -1358,7 +1363,7 @@ func (m *StreamEvent_Statement) Reset() { *m = StreamEvent_Statement{} } ...@@ -1358,7 +1363,7 @@ func (m *StreamEvent_Statement) Reset() { *m = StreamEvent_Statement{} }
func (m *StreamEvent_Statement) String() string { return proto.CompactTextString(m) } func (m *StreamEvent_Statement) String() string { return proto.CompactTextString(m) }
func (*StreamEvent_Statement) ProtoMessage() {} func (*StreamEvent_Statement) ProtoMessage() {}
func (*StreamEvent_Statement) Descriptor() ([]byte, []int) { func (*StreamEvent_Statement) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{12, 0} return fileDescriptor_query_b0bca749772b6512, []int{12, 0}
} }
func (m *StreamEvent_Statement) XXX_Unmarshal(b []byte) error { func (m *StreamEvent_Statement) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StreamEvent_Statement.Unmarshal(m, b) return xxx_messageInfo_StreamEvent_Statement.Unmarshal(m, b)
...@@ -1430,7 +1435,7 @@ func (m *ExecuteRequest) Reset() { *m = ExecuteRequest{} } ...@@ -1430,7 +1435,7 @@ func (m *ExecuteRequest) Reset() { *m = ExecuteRequest{} }
func (m *ExecuteRequest) String() string { return proto.CompactTextString(m) } func (m *ExecuteRequest) String() string { return proto.CompactTextString(m) }
func (*ExecuteRequest) ProtoMessage() {} func (*ExecuteRequest) ProtoMessage() {}
func (*ExecuteRequest) Descriptor() ([]byte, []int) { func (*ExecuteRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{13} return fileDescriptor_query_b0bca749772b6512, []int{13}
} }
func (m *ExecuteRequest) XXX_Unmarshal(b []byte) error { func (m *ExecuteRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ExecuteRequest.Unmarshal(m, b) return xxx_messageInfo_ExecuteRequest.Unmarshal(m, b)
...@@ -1504,7 +1509,7 @@ func (m *ExecuteResponse) Reset() { *m = ExecuteResponse{} } ...@@ -1504,7 +1509,7 @@ func (m *ExecuteResponse) Reset() { *m = ExecuteResponse{} }
func (m *ExecuteResponse) String() string { return proto.CompactTextString(m) } func (m *ExecuteResponse) String() string { return proto.CompactTextString(m) }
func (*ExecuteResponse) ProtoMessage() {} func (*ExecuteResponse) ProtoMessage() {}
func (*ExecuteResponse) Descriptor() ([]byte, []int) { func (*ExecuteResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{14} return fileDescriptor_query_b0bca749772b6512, []int{14}
} }
func (m *ExecuteResponse) XXX_Unmarshal(b []byte) error { func (m *ExecuteResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ExecuteResponse.Unmarshal(m, b) return xxx_messageInfo_ExecuteResponse.Unmarshal(m, b)
...@@ -1548,7 +1553,7 @@ func (m *ResultWithError) Reset() { *m = ResultWithError{} } ...@@ -1548,7 +1553,7 @@ func (m *ResultWithError) Reset() { *m = ResultWithError{} }
func (m *ResultWithError) String() string { return proto.CompactTextString(m) } func (m *ResultWithError) String() string { return proto.CompactTextString(m) }
func (*ResultWithError) ProtoMessage() {} func (*ResultWithError) ProtoMessage() {}
func (*ResultWithError) Descriptor() ([]byte, []int) { func (*ResultWithError) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{15} return fileDescriptor_query_b0bca749772b6512, []int{15}
} }
func (m *ResultWithError) XXX_Unmarshal(b []byte) error { func (m *ResultWithError) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ResultWithError.Unmarshal(m, b) return xxx_messageInfo_ResultWithError.Unmarshal(m, b)
...@@ -1600,7 +1605,7 @@ func (m *ExecuteBatchRequest) Reset() { *m = ExecuteBatchRequest{} } ...@@ -1600,7 +1605,7 @@ func (m *ExecuteBatchRequest) Reset() { *m = ExecuteBatchRequest{} }
func (m *ExecuteBatchRequest) String() string { return proto.CompactTextString(m) } func (m *ExecuteBatchRequest) String() string { return proto.CompactTextString(m) }
func (*ExecuteBatchRequest) ProtoMessage() {} func (*ExecuteBatchRequest) ProtoMessage() {}
func (*ExecuteBatchRequest) Descriptor() ([]byte, []int) { func (*ExecuteBatchRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{16} return fileDescriptor_query_b0bca749772b6512, []int{16}
} }
func (m *ExecuteBatchRequest) XXX_Unmarshal(b []byte) error { func (m *ExecuteBatchRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ExecuteBatchRequest.Unmarshal(m, b) return xxx_messageInfo_ExecuteBatchRequest.Unmarshal(m, b)
...@@ -1681,7 +1686,7 @@ func (m *ExecuteBatchResponse) Reset() { *m = ExecuteBatchResponse{} } ...@@ -1681,7 +1686,7 @@ func (m *ExecuteBatchResponse) Reset() { *m = ExecuteBatchResponse{} }
func (m *ExecuteBatchResponse) String() string { return proto.CompactTextString(m) } func (m *ExecuteBatchResponse) String() string { return proto.CompactTextString(m) }
func (*ExecuteBatchResponse) ProtoMessage() {} func (*ExecuteBatchResponse) ProtoMessage() {}
func (*ExecuteBatchResponse) Descriptor() ([]byte, []int) { func (*ExecuteBatchResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{17} return fileDescriptor_query_b0bca749772b6512, []int{17}
} }
func (m *ExecuteBatchResponse) XXX_Unmarshal(b []byte) error { func (m *ExecuteBatchResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ExecuteBatchResponse.Unmarshal(m, b) return xxx_messageInfo_ExecuteBatchResponse.Unmarshal(m, b)
...@@ -1715,6 +1720,7 @@ type StreamExecuteRequest struct { ...@@ -1715,6 +1720,7 @@ type StreamExecuteRequest struct {
Target *Target `protobuf:"bytes,3,opt,name=target,proto3" json:"target,omitempty"` Target *Target `protobuf:"bytes,3,opt,name=target,proto3" json:"target,omitempty"`
Query *BoundQuery `protobuf:"bytes,4,opt,name=query,proto3" json:"query,omitempty"` Query *BoundQuery `protobuf:"bytes,4,opt,name=query,proto3" json:"query,omitempty"`
Options *ExecuteOptions `protobuf:"bytes,5,opt,name=options,proto3" json:"options,omitempty"` Options *ExecuteOptions `protobuf:"bytes,5,opt,name=options,proto3" json:"options,omitempty"`
TransactionId int64 `protobuf:"varint,6,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
...@@ -1724,7 +1730,7 @@ func (m *StreamExecuteRequest) Reset() { *m = StreamExecuteRequest{} } ...@@ -1724,7 +1730,7 @@ func (m *StreamExecuteRequest) Reset() { *m = StreamExecuteRequest{} }
func (m *StreamExecuteRequest) String() string { return proto.CompactTextString(m) } func (m *StreamExecuteRequest) String() string { return proto.CompactTextString(m) }
func (*StreamExecuteRequest) ProtoMessage() {} func (*StreamExecuteRequest) ProtoMessage() {}
func (*StreamExecuteRequest) Descriptor() ([]byte, []int) { func (*StreamExecuteRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{18} return fileDescriptor_query_b0bca749772b6512, []int{18}
} }
func (m *StreamExecuteRequest) XXX_Unmarshal(b []byte) error { func (m *StreamExecuteRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StreamExecuteRequest.Unmarshal(m, b) return xxx_messageInfo_StreamExecuteRequest.Unmarshal(m, b)
...@@ -1779,6 +1785,13 @@ func (m *StreamExecuteRequest) GetOptions() *ExecuteOptions { ...@@ -1779,6 +1785,13 @@ func (m *StreamExecuteRequest) GetOptions() *ExecuteOptions {
return nil return nil
} }
func (m *StreamExecuteRequest) GetTransactionId() int64 {
if m != nil {
return m.TransactionId
}
return 0
}
// StreamExecuteResponse is the returned value from StreamExecute // StreamExecuteResponse is the returned value from StreamExecute
type StreamExecuteResponse struct { type StreamExecuteResponse struct {
Result *QueryResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` Result *QueryResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"`
...@@ -1791,7 +1804,7 @@ func (m *StreamExecuteResponse) Reset() { *m = StreamExecuteResponse{} } ...@@ -1791,7 +1804,7 @@ func (m *StreamExecuteResponse) Reset() { *m = StreamExecuteResponse{} }
func (m *StreamExecuteResponse) String() string { return proto.CompactTextString(m) } func (m *StreamExecuteResponse) String() string { return proto.CompactTextString(m) }
func (*StreamExecuteResponse) ProtoMessage() {} func (*StreamExecuteResponse) ProtoMessage() {}
func (*StreamExecuteResponse) Descriptor() ([]byte, []int) { func (*StreamExecuteResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{19} return fileDescriptor_query_b0bca749772b6512, []int{19}
} }
func (m *StreamExecuteResponse) XXX_Unmarshal(b []byte) error { func (m *StreamExecuteResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StreamExecuteResponse.Unmarshal(m, b) return xxx_messageInfo_StreamExecuteResponse.Unmarshal(m, b)
...@@ -1833,7 +1846,7 @@ func (m *BeginRequest) Reset() { *m = BeginRequest{} } ...@@ -1833,7 +1846,7 @@ func (m *BeginRequest) Reset() { *m = BeginRequest{} }
func (m *BeginRequest) String() string { return proto.CompactTextString(m) } func (m *BeginRequest) String() string { return proto.CompactTextString(m) }
func (*BeginRequest) ProtoMessage() {} func (*BeginRequest) ProtoMessage() {}
func (*BeginRequest) Descriptor() ([]byte, []int) { func (*BeginRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{20} return fileDescriptor_query_b0bca749772b6512, []int{20}
} }
func (m *BeginRequest) XXX_Unmarshal(b []byte) error { func (m *BeginRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BeginRequest.Unmarshal(m, b) return xxx_messageInfo_BeginRequest.Unmarshal(m, b)
...@@ -1893,7 +1906,7 @@ func (m *BeginResponse) Reset() { *m = BeginResponse{} } ...@@ -1893,7 +1906,7 @@ func (m *BeginResponse) Reset() { *m = BeginResponse{} }
func (m *BeginResponse) String() string { return proto.CompactTextString(m) } func (m *BeginResponse) String() string { return proto.CompactTextString(m) }
func (*BeginResponse) ProtoMessage() {} func (*BeginResponse) ProtoMessage() {}
func (*BeginResponse) Descriptor() ([]byte, []int) { func (*BeginResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{21} return fileDescriptor_query_b0bca749772b6512, []int{21}
} }
func (m *BeginResponse) XXX_Unmarshal(b []byte) error { func (m *BeginResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BeginResponse.Unmarshal(m, b) return xxx_messageInfo_BeginResponse.Unmarshal(m, b)
...@@ -1935,7 +1948,7 @@ func (m *CommitRequest) Reset() { *m = CommitRequest{} } ...@@ -1935,7 +1948,7 @@ func (m *CommitRequest) Reset() { *m = CommitRequest{} }
func (m *CommitRequest) String() string { return proto.CompactTextString(m) } func (m *CommitRequest) String() string { return proto.CompactTextString(m) }
func (*CommitRequest) ProtoMessage() {} func (*CommitRequest) ProtoMessage() {}
func (*CommitRequest) Descriptor() ([]byte, []int) { func (*CommitRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{22} return fileDescriptor_query_b0bca749772b6512, []int{22}
} }
func (m *CommitRequest) XXX_Unmarshal(b []byte) error { func (m *CommitRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CommitRequest.Unmarshal(m, b) return xxx_messageInfo_CommitRequest.Unmarshal(m, b)
...@@ -1994,7 +2007,7 @@ func (m *CommitResponse) Reset() { *m = CommitResponse{} } ...@@ -1994,7 +2007,7 @@ func (m *CommitResponse) Reset() { *m = CommitResponse{} }
func (m *CommitResponse) String() string { return proto.CompactTextString(m) } func (m *CommitResponse) String() string { return proto.CompactTextString(m) }
func (*CommitResponse) ProtoMessage() {} func (*CommitResponse) ProtoMessage() {}
func (*CommitResponse) Descriptor() ([]byte, []int) { func (*CommitResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{23} return fileDescriptor_query_b0bca749772b6512, []int{23}
} }
func (m *CommitResponse) XXX_Unmarshal(b []byte) error { func (m *CommitResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CommitResponse.Unmarshal(m, b) return xxx_messageInfo_CommitResponse.Unmarshal(m, b)
...@@ -2029,7 +2042,7 @@ func (m *RollbackRequest) Reset() { *m = RollbackRequest{} } ...@@ -2029,7 +2042,7 @@ func (m *RollbackRequest) Reset() { *m = RollbackRequest{} }
func (m *RollbackRequest) String() string { return proto.CompactTextString(m) } func (m *RollbackRequest) String() string { return proto.CompactTextString(m) }
func (*RollbackRequest) ProtoMessage() {} func (*RollbackRequest) ProtoMessage() {}
func (*RollbackRequest) Descriptor() ([]byte, []int) { func (*RollbackRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{24} return fileDescriptor_query_b0bca749772b6512, []int{24}
} }
func (m *RollbackRequest) XXX_Unmarshal(b []byte) error { func (m *RollbackRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RollbackRequest.Unmarshal(m, b) return xxx_messageInfo_RollbackRequest.Unmarshal(m, b)
...@@ -2088,7 +2101,7 @@ func (m *RollbackResponse) Reset() { *m = RollbackResponse{} } ...@@ -2088,7 +2101,7 @@ func (m *RollbackResponse) Reset() { *m = RollbackResponse{} }
func (m *RollbackResponse) String() string { return proto.CompactTextString(m) } func (m *RollbackResponse) String() string { return proto.CompactTextString(m) }
func (*RollbackResponse) ProtoMessage() {} func (*RollbackResponse) ProtoMessage() {}
func (*RollbackResponse) Descriptor() ([]byte, []int) { func (*RollbackResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{25} return fileDescriptor_query_b0bca749772b6512, []int{25}
} }
func (m *RollbackResponse) XXX_Unmarshal(b []byte) error { func (m *RollbackResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RollbackResponse.Unmarshal(m, b) return xxx_messageInfo_RollbackResponse.Unmarshal(m, b)
...@@ -2124,7 +2137,7 @@ func (m *PrepareRequest) Reset() { *m = PrepareRequest{} } ...@@ -2124,7 +2137,7 @@ func (m *PrepareRequest) Reset() { *m = PrepareRequest{} }
func (m *PrepareRequest) String() string { return proto.CompactTextString(m) } func (m *PrepareRequest) String() string { return proto.CompactTextString(m) }
func (*PrepareRequest) ProtoMessage() {} func (*PrepareRequest) ProtoMessage() {}
func (*PrepareRequest) Descriptor() ([]byte, []int) { func (*PrepareRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{26} return fileDescriptor_query_b0bca749772b6512, []int{26}
} }
func (m *PrepareRequest) XXX_Unmarshal(b []byte) error { func (m *PrepareRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_PrepareRequest.Unmarshal(m, b) return xxx_messageInfo_PrepareRequest.Unmarshal(m, b)
...@@ -2190,7 +2203,7 @@ func (m *PrepareResponse) Reset() { *m = PrepareResponse{} } ...@@ -2190,7 +2203,7 @@ func (m *PrepareResponse) Reset() { *m = PrepareResponse{} }
func (m *PrepareResponse) String() string { return proto.CompactTextString(m) } func (m *PrepareResponse) String() string { return proto.CompactTextString(m) }
func (*PrepareResponse) ProtoMessage() {} func (*PrepareResponse) ProtoMessage() {}
func (*PrepareResponse) Descriptor() ([]byte, []int) { func (*PrepareResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{27} return fileDescriptor_query_b0bca749772b6512, []int{27}
} }
func (m *PrepareResponse) XXX_Unmarshal(b []byte) error { func (m *PrepareResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_PrepareResponse.Unmarshal(m, b) return xxx_messageInfo_PrepareResponse.Unmarshal(m, b)
...@@ -2225,7 +2238,7 @@ func (m *CommitPreparedRequest) Reset() { *m = CommitPreparedRequest{} } ...@@ -2225,7 +2238,7 @@ func (m *CommitPreparedRequest) Reset() { *m = CommitPreparedRequest{} }
func (m *CommitPreparedRequest) String() string { return proto.CompactTextString(m) } func (m *CommitPreparedRequest) String() string { return proto.CompactTextString(m) }
func (*CommitPreparedRequest) ProtoMessage() {} func (*CommitPreparedRequest) ProtoMessage() {}
func (*CommitPreparedRequest) Descriptor() ([]byte, []int) { func (*CommitPreparedRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{28} return fileDescriptor_query_b0bca749772b6512, []int{28}
} }
func (m *CommitPreparedRequest) XXX_Unmarshal(b []byte) error { func (m *CommitPreparedRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CommitPreparedRequest.Unmarshal(m, b) return xxx_messageInfo_CommitPreparedRequest.Unmarshal(m, b)
...@@ -2284,7 +2297,7 @@ func (m *CommitPreparedResponse) Reset() { *m = CommitPreparedResponse{} ...@@ -2284,7 +2297,7 @@ func (m *CommitPreparedResponse) Reset() { *m = CommitPreparedResponse{}
func (m *CommitPreparedResponse) String() string { return proto.CompactTextString(m) } func (m *CommitPreparedResponse) String() string { return proto.CompactTextString(m) }
func (*CommitPreparedResponse) ProtoMessage() {} func (*CommitPreparedResponse) ProtoMessage() {}
func (*CommitPreparedResponse) Descriptor() ([]byte, []int) { func (*CommitPreparedResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{29} return fileDescriptor_query_b0bca749772b6512, []int{29}
} }
func (m *CommitPreparedResponse) XXX_Unmarshal(b []byte) error { func (m *CommitPreparedResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CommitPreparedResponse.Unmarshal(m, b) return xxx_messageInfo_CommitPreparedResponse.Unmarshal(m, b)
...@@ -2320,7 +2333,7 @@ func (m *RollbackPreparedRequest) Reset() { *m = RollbackPreparedRequest ...@@ -2320,7 +2333,7 @@ func (m *RollbackPreparedRequest) Reset() { *m = RollbackPreparedRequest
func (m *RollbackPreparedRequest) String() string { return proto.CompactTextString(m) } func (m *RollbackPreparedRequest) String() string { return proto.CompactTextString(m) }
func (*RollbackPreparedRequest) ProtoMessage() {} func (*RollbackPreparedRequest) ProtoMessage() {}
func (*RollbackPreparedRequest) Descriptor() ([]byte, []int) { func (*RollbackPreparedRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{30} return fileDescriptor_query_b0bca749772b6512, []int{30}
} }
func (m *RollbackPreparedRequest) XXX_Unmarshal(b []byte) error { func (m *RollbackPreparedRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RollbackPreparedRequest.Unmarshal(m, b) return xxx_messageInfo_RollbackPreparedRequest.Unmarshal(m, b)
...@@ -2386,7 +2399,7 @@ func (m *RollbackPreparedResponse) Reset() { *m = RollbackPreparedRespon ...@@ -2386,7 +2399,7 @@ func (m *RollbackPreparedResponse) Reset() { *m = RollbackPreparedRespon
func (m *RollbackPreparedResponse) String() string { return proto.CompactTextString(m) } func (m *RollbackPreparedResponse) String() string { return proto.CompactTextString(m) }
func (*RollbackPreparedResponse) ProtoMessage() {} func (*RollbackPreparedResponse) ProtoMessage() {}
func (*RollbackPreparedResponse) Descriptor() ([]byte, []int) { func (*RollbackPreparedResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{31} return fileDescriptor_query_b0bca749772b6512, []int{31}
} }
func (m *RollbackPreparedResponse) XXX_Unmarshal(b []byte) error { func (m *RollbackPreparedResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RollbackPreparedResponse.Unmarshal(m, b) return xxx_messageInfo_RollbackPreparedResponse.Unmarshal(m, b)
...@@ -2422,7 +2435,7 @@ func (m *CreateTransactionRequest) Reset() { *m = CreateTransactionReque ...@@ -2422,7 +2435,7 @@ func (m *CreateTransactionRequest) Reset() { *m = CreateTransactionReque
func (m *CreateTransactionRequest) String() string { return proto.CompactTextString(m) } func (m *CreateTransactionRequest) String() string { return proto.CompactTextString(m) }
func (*CreateTransactionRequest) ProtoMessage() {} func (*CreateTransactionRequest) ProtoMessage() {}
func (*CreateTransactionRequest) Descriptor() ([]byte, []int) { func (*CreateTransactionRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{32} return fileDescriptor_query_b0bca749772b6512, []int{32}
} }
func (m *CreateTransactionRequest) XXX_Unmarshal(b []byte) error { func (m *CreateTransactionRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CreateTransactionRequest.Unmarshal(m, b) return xxx_messageInfo_CreateTransactionRequest.Unmarshal(m, b)
...@@ -2488,7 +2501,7 @@ func (m *CreateTransactionResponse) Reset() { *m = CreateTransactionResp ...@@ -2488,7 +2501,7 @@ func (m *CreateTransactionResponse) Reset() { *m = CreateTransactionResp
func (m *CreateTransactionResponse) String() string { return proto.CompactTextString(m) } func (m *CreateTransactionResponse) String() string { return proto.CompactTextString(m) }
func (*CreateTransactionResponse) ProtoMessage() {} func (*CreateTransactionResponse) ProtoMessage() {}
func (*CreateTransactionResponse) Descriptor() ([]byte, []int) { func (*CreateTransactionResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{33} return fileDescriptor_query_b0bca749772b6512, []int{33}
} }
func (m *CreateTransactionResponse) XXX_Unmarshal(b []byte) error { func (m *CreateTransactionResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CreateTransactionResponse.Unmarshal(m, b) return xxx_messageInfo_CreateTransactionResponse.Unmarshal(m, b)
...@@ -2524,7 +2537,7 @@ func (m *StartCommitRequest) Reset() { *m = StartCommitRequest{} } ...@@ -2524,7 +2537,7 @@ func (m *StartCommitRequest) Reset() { *m = StartCommitRequest{} }
func (m *StartCommitRequest) String() string { return proto.CompactTextString(m) } func (m *StartCommitRequest) String() string { return proto.CompactTextString(m) }
func (*StartCommitRequest) ProtoMessage() {} func (*StartCommitRequest) ProtoMessage() {}
func (*StartCommitRequest) Descriptor() ([]byte, []int) { func (*StartCommitRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{34} return fileDescriptor_query_b0bca749772b6512, []int{34}
} }
func (m *StartCommitRequest) XXX_Unmarshal(b []byte) error { func (m *StartCommitRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StartCommitRequest.Unmarshal(m, b) return xxx_messageInfo_StartCommitRequest.Unmarshal(m, b)
...@@ -2590,7 +2603,7 @@ func (m *StartCommitResponse) Reset() { *m = StartCommitResponse{} } ...@@ -2590,7 +2603,7 @@ func (m *StartCommitResponse) Reset() { *m = StartCommitResponse{} }
func (m *StartCommitResponse) String() string { return proto.CompactTextString(m) } func (m *StartCommitResponse) String() string { return proto.CompactTextString(m) }
func (*StartCommitResponse) ProtoMessage() {} func (*StartCommitResponse) ProtoMessage() {}
func (*StartCommitResponse) Descriptor() ([]byte, []int) { func (*StartCommitResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{35} return fileDescriptor_query_b0bca749772b6512, []int{35}
} }
func (m *StartCommitResponse) XXX_Unmarshal(b []byte) error { func (m *StartCommitResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StartCommitResponse.Unmarshal(m, b) return xxx_messageInfo_StartCommitResponse.Unmarshal(m, b)
...@@ -2626,7 +2639,7 @@ func (m *SetRollbackRequest) Reset() { *m = SetRollbackRequest{} } ...@@ -2626,7 +2639,7 @@ func (m *SetRollbackRequest) Reset() { *m = SetRollbackRequest{} }
func (m *SetRollbackRequest) String() string { return proto.CompactTextString(m) } func (m *SetRollbackRequest) String() string { return proto.CompactTextString(m) }
func (*SetRollbackRequest) ProtoMessage() {} func (*SetRollbackRequest) ProtoMessage() {}
func (*SetRollbackRequest) Descriptor() ([]byte, []int) { func (*SetRollbackRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{36} return fileDescriptor_query_b0bca749772b6512, []int{36}
} }
func (m *SetRollbackRequest) XXX_Unmarshal(b []byte) error { func (m *SetRollbackRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SetRollbackRequest.Unmarshal(m, b) return xxx_messageInfo_SetRollbackRequest.Unmarshal(m, b)
...@@ -2692,7 +2705,7 @@ func (m *SetRollbackResponse) Reset() { *m = SetRollbackResponse{} } ...@@ -2692,7 +2705,7 @@ func (m *SetRollbackResponse) Reset() { *m = SetRollbackResponse{} }
func (m *SetRollbackResponse) String() string { return proto.CompactTextString(m) } func (m *SetRollbackResponse) String() string { return proto.CompactTextString(m) }
func (*SetRollbackResponse) ProtoMessage() {} func (*SetRollbackResponse) ProtoMessage() {}
func (*SetRollbackResponse) Descriptor() ([]byte, []int) { func (*SetRollbackResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{37} return fileDescriptor_query_b0bca749772b6512, []int{37}
} }
func (m *SetRollbackResponse) XXX_Unmarshal(b []byte) error { func (m *SetRollbackResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SetRollbackResponse.Unmarshal(m, b) return xxx_messageInfo_SetRollbackResponse.Unmarshal(m, b)
...@@ -2727,7 +2740,7 @@ func (m *ConcludeTransactionRequest) Reset() { *m = ConcludeTransactionR ...@@ -2727,7 +2740,7 @@ func (m *ConcludeTransactionRequest) Reset() { *m = ConcludeTransactionR
func (m *ConcludeTransactionRequest) String() string { return proto.CompactTextString(m) } func (m *ConcludeTransactionRequest) String() string { return proto.CompactTextString(m) }
func (*ConcludeTransactionRequest) ProtoMessage() {} func (*ConcludeTransactionRequest) ProtoMessage() {}
func (*ConcludeTransactionRequest) Descriptor() ([]byte, []int) { func (*ConcludeTransactionRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{38} return fileDescriptor_query_b0bca749772b6512, []int{38}
} }
func (m *ConcludeTransactionRequest) XXX_Unmarshal(b []byte) error { func (m *ConcludeTransactionRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ConcludeTransactionRequest.Unmarshal(m, b) return xxx_messageInfo_ConcludeTransactionRequest.Unmarshal(m, b)
...@@ -2786,7 +2799,7 @@ func (m *ConcludeTransactionResponse) Reset() { *m = ConcludeTransaction ...@@ -2786,7 +2799,7 @@ func (m *ConcludeTransactionResponse) Reset() { *m = ConcludeTransaction
func (m *ConcludeTransactionResponse) String() string { return proto.CompactTextString(m) } func (m *ConcludeTransactionResponse) String() string { return proto.CompactTextString(m) }
func (*ConcludeTransactionResponse) ProtoMessage() {} func (*ConcludeTransactionResponse) ProtoMessage() {}
func (*ConcludeTransactionResponse) Descriptor() ([]byte, []int) { func (*ConcludeTransactionResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{39} return fileDescriptor_query_b0bca749772b6512, []int{39}
} }
func (m *ConcludeTransactionResponse) XXX_Unmarshal(b []byte) error { func (m *ConcludeTransactionResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ConcludeTransactionResponse.Unmarshal(m, b) return xxx_messageInfo_ConcludeTransactionResponse.Unmarshal(m, b)
...@@ -2821,7 +2834,7 @@ func (m *ReadTransactionRequest) Reset() { *m = ReadTransactionRequest{} ...@@ -2821,7 +2834,7 @@ func (m *ReadTransactionRequest) Reset() { *m = ReadTransactionRequest{}
func (m *ReadTransactionRequest) String() string { return proto.CompactTextString(m) } func (m *ReadTransactionRequest) String() string { return proto.CompactTextString(m) }
func (*ReadTransactionRequest) ProtoMessage() {} func (*ReadTransactionRequest) ProtoMessage() {}
func (*ReadTransactionRequest) Descriptor() ([]byte, []int) { func (*ReadTransactionRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{40} return fileDescriptor_query_b0bca749772b6512, []int{40}
} }
func (m *ReadTransactionRequest) XXX_Unmarshal(b []byte) error { func (m *ReadTransactionRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReadTransactionRequest.Unmarshal(m, b) return xxx_messageInfo_ReadTransactionRequest.Unmarshal(m, b)
...@@ -2881,7 +2894,7 @@ func (m *ReadTransactionResponse) Reset() { *m = ReadTransactionResponse ...@@ -2881,7 +2894,7 @@ func (m *ReadTransactionResponse) Reset() { *m = ReadTransactionResponse
func (m *ReadTransactionResponse) String() string { return proto.CompactTextString(m) } func (m *ReadTransactionResponse) String() string { return proto.CompactTextString(m) }
func (*ReadTransactionResponse) ProtoMessage() {} func (*ReadTransactionResponse) ProtoMessage() {}
func (*ReadTransactionResponse) Descriptor() ([]byte, []int) { func (*ReadTransactionResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{41} return fileDescriptor_query_b0bca749772b6512, []int{41}
} }
func (m *ReadTransactionResponse) XXX_Unmarshal(b []byte) error { func (m *ReadTransactionResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReadTransactionResponse.Unmarshal(m, b) return xxx_messageInfo_ReadTransactionResponse.Unmarshal(m, b)
...@@ -2924,7 +2937,7 @@ func (m *BeginExecuteRequest) Reset() { *m = BeginExecuteRequest{} } ...@@ -2924,7 +2937,7 @@ func (m *BeginExecuteRequest) Reset() { *m = BeginExecuteRequest{} }
func (m *BeginExecuteRequest) String() string { return proto.CompactTextString(m) } func (m *BeginExecuteRequest) String() string { return proto.CompactTextString(m) }
func (*BeginExecuteRequest) ProtoMessage() {} func (*BeginExecuteRequest) ProtoMessage() {}
func (*BeginExecuteRequest) Descriptor() ([]byte, []int) { func (*BeginExecuteRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{42} return fileDescriptor_query_b0bca749772b6512, []int{42}
} }
func (m *BeginExecuteRequest) XXX_Unmarshal(b []byte) error { func (m *BeginExecuteRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BeginExecuteRequest.Unmarshal(m, b) return xxx_messageInfo_BeginExecuteRequest.Unmarshal(m, b)
...@@ -2997,7 +3010,7 @@ func (m *BeginExecuteResponse) Reset() { *m = BeginExecuteResponse{} } ...@@ -2997,7 +3010,7 @@ func (m *BeginExecuteResponse) Reset() { *m = BeginExecuteResponse{} }
func (m *BeginExecuteResponse) String() string { return proto.CompactTextString(m) } func (m *BeginExecuteResponse) String() string { return proto.CompactTextString(m) }
func (*BeginExecuteResponse) ProtoMessage() {} func (*BeginExecuteResponse) ProtoMessage() {}
func (*BeginExecuteResponse) Descriptor() ([]byte, []int) { func (*BeginExecuteResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{43} return fileDescriptor_query_b0bca749772b6512, []int{43}
} }
func (m *BeginExecuteResponse) XXX_Unmarshal(b []byte) error { func (m *BeginExecuteResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BeginExecuteResponse.Unmarshal(m, b) return xxx_messageInfo_BeginExecuteResponse.Unmarshal(m, b)
...@@ -3055,7 +3068,7 @@ func (m *BeginExecuteBatchRequest) Reset() { *m = BeginExecuteBatchReque ...@@ -3055,7 +3068,7 @@ func (m *BeginExecuteBatchRequest) Reset() { *m = BeginExecuteBatchReque
func (m *BeginExecuteBatchRequest) String() string { return proto.CompactTextString(m) } func (m *BeginExecuteBatchRequest) String() string { return proto.CompactTextString(m) }
func (*BeginExecuteBatchRequest) ProtoMessage() {} func (*BeginExecuteBatchRequest) ProtoMessage() {}
func (*BeginExecuteBatchRequest) Descriptor() ([]byte, []int) { func (*BeginExecuteBatchRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{44} return fileDescriptor_query_b0bca749772b6512, []int{44}
} }
func (m *BeginExecuteBatchRequest) XXX_Unmarshal(b []byte) error { func (m *BeginExecuteBatchRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BeginExecuteBatchRequest.Unmarshal(m, b) return xxx_messageInfo_BeginExecuteBatchRequest.Unmarshal(m, b)
...@@ -3135,7 +3148,7 @@ func (m *BeginExecuteBatchResponse) Reset() { *m = BeginExecuteBatchResp ...@@ -3135,7 +3148,7 @@ func (m *BeginExecuteBatchResponse) Reset() { *m = BeginExecuteBatchResp
func (m *BeginExecuteBatchResponse) String() string { return proto.CompactTextString(m) } func (m *BeginExecuteBatchResponse) String() string { return proto.CompactTextString(m) }
func (*BeginExecuteBatchResponse) ProtoMessage() {} func (*BeginExecuteBatchResponse) ProtoMessage() {}
func (*BeginExecuteBatchResponse) Descriptor() ([]byte, []int) { func (*BeginExecuteBatchResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{45} return fileDescriptor_query_b0bca749772b6512, []int{45}
} }
func (m *BeginExecuteBatchResponse) XXX_Unmarshal(b []byte) error { func (m *BeginExecuteBatchResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BeginExecuteBatchResponse.Unmarshal(m, b) return xxx_messageInfo_BeginExecuteBatchResponse.Unmarshal(m, b)
...@@ -3192,7 +3205,7 @@ func (m *MessageStreamRequest) Reset() { *m = MessageStreamRequest{} } ...@@ -3192,7 +3205,7 @@ func (m *MessageStreamRequest) Reset() { *m = MessageStreamRequest{} }
func (m *MessageStreamRequest) String() string { return proto.CompactTextString(m) } func (m *MessageStreamRequest) String() string { return proto.CompactTextString(m) }
func (*MessageStreamRequest) ProtoMessage() {} func (*MessageStreamRequest) ProtoMessage() {}
func (*MessageStreamRequest) Descriptor() ([]byte, []int) { func (*MessageStreamRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{46} return fileDescriptor_query_b0bca749772b6512, []int{46}
} }
func (m *MessageStreamRequest) XXX_Unmarshal(b []byte) error { func (m *MessageStreamRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_MessageStreamRequest.Unmarshal(m, b) return xxx_messageInfo_MessageStreamRequest.Unmarshal(m, b)
...@@ -3252,7 +3265,7 @@ func (m *MessageStreamResponse) Reset() { *m = MessageStreamResponse{} } ...@@ -3252,7 +3265,7 @@ func (m *MessageStreamResponse) Reset() { *m = MessageStreamResponse{} }
func (m *MessageStreamResponse) String() string { return proto.CompactTextString(m) } func (m *MessageStreamResponse) String() string { return proto.CompactTextString(m) }
func (*MessageStreamResponse) ProtoMessage() {} func (*MessageStreamResponse) ProtoMessage() {}
func (*MessageStreamResponse) Descriptor() ([]byte, []int) { func (*MessageStreamResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{47} return fileDescriptor_query_b0bca749772b6512, []int{47}
} }
func (m *MessageStreamResponse) XXX_Unmarshal(b []byte) error { func (m *MessageStreamResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_MessageStreamResponse.Unmarshal(m, b) return xxx_messageInfo_MessageStreamResponse.Unmarshal(m, b)
...@@ -3296,7 +3309,7 @@ func (m *MessageAckRequest) Reset() { *m = MessageAckRequest{} } ...@@ -3296,7 +3309,7 @@ func (m *MessageAckRequest) Reset() { *m = MessageAckRequest{} }
func (m *MessageAckRequest) String() string { return proto.CompactTextString(m) } func (m *MessageAckRequest) String() string { return proto.CompactTextString(m) }
func (*MessageAckRequest) ProtoMessage() {} func (*MessageAckRequest) ProtoMessage() {}
func (*MessageAckRequest) Descriptor() ([]byte, []int) { func (*MessageAckRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{48} return fileDescriptor_query_b0bca749772b6512, []int{48}
} }
func (m *MessageAckRequest) XXX_Unmarshal(b []byte) error { func (m *MessageAckRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_MessageAckRequest.Unmarshal(m, b) return xxx_messageInfo_MessageAckRequest.Unmarshal(m, b)
...@@ -3366,7 +3379,7 @@ func (m *MessageAckResponse) Reset() { *m = MessageAckResponse{} } ...@@ -3366,7 +3379,7 @@ func (m *MessageAckResponse) Reset() { *m = MessageAckResponse{} }
func (m *MessageAckResponse) String() string { return proto.CompactTextString(m) } func (m *MessageAckResponse) String() string { return proto.CompactTextString(m) }
func (*MessageAckResponse) ProtoMessage() {} func (*MessageAckResponse) ProtoMessage() {}
func (*MessageAckResponse) Descriptor() ([]byte, []int) { func (*MessageAckResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{49} return fileDescriptor_query_b0bca749772b6512, []int{49}
} }
func (m *MessageAckResponse) XXX_Unmarshal(b []byte) error { func (m *MessageAckResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_MessageAckResponse.Unmarshal(m, b) return xxx_messageInfo_MessageAckResponse.Unmarshal(m, b)
...@@ -3414,7 +3427,7 @@ func (m *SplitQueryRequest) Reset() { *m = SplitQueryRequest{} } ...@@ -3414,7 +3427,7 @@ func (m *SplitQueryRequest) Reset() { *m = SplitQueryRequest{} }
func (m *SplitQueryRequest) String() string { return proto.CompactTextString(m) } func (m *SplitQueryRequest) String() string { return proto.CompactTextString(m) }
func (*SplitQueryRequest) ProtoMessage() {} func (*SplitQueryRequest) ProtoMessage() {}
func (*SplitQueryRequest) Descriptor() ([]byte, []int) { func (*SplitQueryRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{50} return fileDescriptor_query_b0bca749772b6512, []int{50}
} }
func (m *SplitQueryRequest) XXX_Unmarshal(b []byte) error { func (m *SplitQueryRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SplitQueryRequest.Unmarshal(m, b) return xxx_messageInfo_SplitQueryRequest.Unmarshal(m, b)
...@@ -3505,7 +3518,7 @@ func (m *QuerySplit) Reset() { *m = QuerySplit{} } ...@@ -3505,7 +3518,7 @@ func (m *QuerySplit) Reset() { *m = QuerySplit{} }
func (m *QuerySplit) String() string { return proto.CompactTextString(m) } func (m *QuerySplit) String() string { return proto.CompactTextString(m) }
func (*QuerySplit) ProtoMessage() {} func (*QuerySplit) ProtoMessage() {}
func (*QuerySplit) Descriptor() ([]byte, []int) { func (*QuerySplit) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{51} return fileDescriptor_query_b0bca749772b6512, []int{51}
} }
func (m *QuerySplit) XXX_Unmarshal(b []byte) error { func (m *QuerySplit) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_QuerySplit.Unmarshal(m, b) return xxx_messageInfo_QuerySplit.Unmarshal(m, b)
...@@ -3552,7 +3565,7 @@ func (m *SplitQueryResponse) Reset() { *m = SplitQueryResponse{} } ...@@ -3552,7 +3565,7 @@ func (m *SplitQueryResponse) Reset() { *m = SplitQueryResponse{} }
func (m *SplitQueryResponse) String() string { return proto.CompactTextString(m) } func (m *SplitQueryResponse) String() string { return proto.CompactTextString(m) }
func (*SplitQueryResponse) ProtoMessage() {} func (*SplitQueryResponse) ProtoMessage() {}
func (*SplitQueryResponse) Descriptor() ([]byte, []int) { func (*SplitQueryResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{52} return fileDescriptor_query_b0bca749772b6512, []int{52}
} }
func (m *SplitQueryResponse) XXX_Unmarshal(b []byte) error { func (m *SplitQueryResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SplitQueryResponse.Unmarshal(m, b) return xxx_messageInfo_SplitQueryResponse.Unmarshal(m, b)
...@@ -3590,7 +3603,7 @@ func (m *StreamHealthRequest) Reset() { *m = StreamHealthRequest{} } ...@@ -3590,7 +3603,7 @@ func (m *StreamHealthRequest) Reset() { *m = StreamHealthRequest{} }
func (m *StreamHealthRequest) String() string { return proto.CompactTextString(m) } func (m *StreamHealthRequest) String() string { return proto.CompactTextString(m) }
func (*StreamHealthRequest) ProtoMessage() {} func (*StreamHealthRequest) ProtoMessage() {}
func (*StreamHealthRequest) Descriptor() ([]byte, []int) { func (*StreamHealthRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{53} return fileDescriptor_query_b0bca749772b6512, []int{53}
} }
func (m *StreamHealthRequest) XXX_Unmarshal(b []byte) error { func (m *StreamHealthRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StreamHealthRequest.Unmarshal(m, b) return xxx_messageInfo_StreamHealthRequest.Unmarshal(m, b)
...@@ -3649,7 +3662,7 @@ func (m *RealtimeStats) Reset() { *m = RealtimeStats{} } ...@@ -3649,7 +3662,7 @@ func (m *RealtimeStats) Reset() { *m = RealtimeStats{} }
func (m *RealtimeStats) String() string { return proto.CompactTextString(m) } func (m *RealtimeStats) String() string { return proto.CompactTextString(m) }
func (*RealtimeStats) ProtoMessage() {} func (*RealtimeStats) ProtoMessage() {}
func (*RealtimeStats) Descriptor() ([]byte, []int) { func (*RealtimeStats) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{54} return fileDescriptor_query_b0bca749772b6512, []int{54}
} }
func (m *RealtimeStats) XXX_Unmarshal(b []byte) error { func (m *RealtimeStats) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RealtimeStats.Unmarshal(m, b) return xxx_messageInfo_RealtimeStats.Unmarshal(m, b)
...@@ -3737,7 +3750,7 @@ func (m *AggregateStats) Reset() { *m = AggregateStats{} } ...@@ -3737,7 +3750,7 @@ func (m *AggregateStats) Reset() { *m = AggregateStats{} }
func (m *AggregateStats) String() string { return proto.CompactTextString(m) } func (m *AggregateStats) String() string { return proto.CompactTextString(m) }
func (*AggregateStats) ProtoMessage() {} func (*AggregateStats) ProtoMessage() {}
func (*AggregateStats) Descriptor() ([]byte, []int) { func (*AggregateStats) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{55} return fileDescriptor_query_b0bca749772b6512, []int{55}
} }
func (m *AggregateStats) XXX_Unmarshal(b []byte) error { func (m *AggregateStats) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_AggregateStats.Unmarshal(m, b) return xxx_messageInfo_AggregateStats.Unmarshal(m, b)
...@@ -3849,7 +3862,7 @@ func (m *StreamHealthResponse) Reset() { *m = StreamHealthResponse{} } ...@@ -3849,7 +3862,7 @@ func (m *StreamHealthResponse) Reset() { *m = StreamHealthResponse{} }
func (m *StreamHealthResponse) String() string { return proto.CompactTextString(m) } func (m *StreamHealthResponse) String() string { return proto.CompactTextString(m) }
func (*StreamHealthResponse) ProtoMessage() {} func (*StreamHealthResponse) ProtoMessage() {}
func (*StreamHealthResponse) Descriptor() ([]byte, []int) { func (*StreamHealthResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{56} return fileDescriptor_query_b0bca749772b6512, []int{56}
} }
func (m *StreamHealthResponse) XXX_Unmarshal(b []byte) error { func (m *StreamHealthResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StreamHealthResponse.Unmarshal(m, b) return xxx_messageInfo_StreamHealthResponse.Unmarshal(m, b)
...@@ -3933,7 +3946,7 @@ func (m *UpdateStreamRequest) Reset() { *m = UpdateStreamRequest{} } ...@@ -3933,7 +3946,7 @@ func (m *UpdateStreamRequest) Reset() { *m = UpdateStreamRequest{} }
func (m *UpdateStreamRequest) String() string { return proto.CompactTextString(m) } func (m *UpdateStreamRequest) String() string { return proto.CompactTextString(m) }
func (*UpdateStreamRequest) ProtoMessage() {} func (*UpdateStreamRequest) ProtoMessage() {}
func (*UpdateStreamRequest) Descriptor() ([]byte, []int) { func (*UpdateStreamRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{57} return fileDescriptor_query_b0bca749772b6512, []int{57}
} }
func (m *UpdateStreamRequest) XXX_Unmarshal(b []byte) error { func (m *UpdateStreamRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_UpdateStreamRequest.Unmarshal(m, b) return xxx_messageInfo_UpdateStreamRequest.Unmarshal(m, b)
...@@ -4000,7 +4013,7 @@ func (m *UpdateStreamResponse) Reset() { *m = UpdateStreamResponse{} } ...@@ -4000,7 +4013,7 @@ func (m *UpdateStreamResponse) Reset() { *m = UpdateStreamResponse{} }
func (m *UpdateStreamResponse) String() string { return proto.CompactTextString(m) } func (m *UpdateStreamResponse) String() string { return proto.CompactTextString(m) }
func (*UpdateStreamResponse) ProtoMessage() {} func (*UpdateStreamResponse) ProtoMessage() {}
func (*UpdateStreamResponse) Descriptor() ([]byte, []int) { func (*UpdateStreamResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{58} return fileDescriptor_query_b0bca749772b6512, []int{58}
} }
func (m *UpdateStreamResponse) XXX_Unmarshal(b []byte) error { func (m *UpdateStreamResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_UpdateStreamResponse.Unmarshal(m, b) return xxx_messageInfo_UpdateStreamResponse.Unmarshal(m, b)
...@@ -4042,7 +4055,7 @@ func (m *TransactionMetadata) Reset() { *m = TransactionMetadata{} } ...@@ -4042,7 +4055,7 @@ func (m *TransactionMetadata) Reset() { *m = TransactionMetadata{} }
func (m *TransactionMetadata) String() string { return proto.CompactTextString(m) } func (m *TransactionMetadata) String() string { return proto.CompactTextString(m) }
func (*TransactionMetadata) ProtoMessage() {} func (*TransactionMetadata) ProtoMessage() {}
func (*TransactionMetadata) Descriptor() ([]byte, []int) { func (*TransactionMetadata) Descriptor() ([]byte, []int) {
return fileDescriptor_query_1e32bb78b6357529, []int{59} return fileDescriptor_query_b0bca749772b6512, []int{59}
} }
func (m *TransactionMetadata) XXX_Unmarshal(b []byte) error { func (m *TransactionMetadata) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_TransactionMetadata.Unmarshal(m, b) return xxx_messageInfo_TransactionMetadata.Unmarshal(m, b)
...@@ -4164,210 +4177,212 @@ func init() { ...@@ -4164,210 +4177,212 @@ func init() {
proto.RegisterEnum("query.SplitQueryRequest_Algorithm", SplitQueryRequest_Algorithm_name, SplitQueryRequest_Algorithm_value) proto.RegisterEnum("query.SplitQueryRequest_Algorithm", SplitQueryRequest_Algorithm_name, SplitQueryRequest_Algorithm_value)
} }
func init() { proto.RegisterFile("query.proto", fileDescriptor_query_1e32bb78b6357529) } func init() { proto.RegisterFile("query.proto", fileDescriptor_query_b0bca749772b6512) }
var fileDescriptor_query_1e32bb78b6357529 = []byte{ var fileDescriptor_query_b0bca749772b6512 = []byte{
// 3231 bytes of a gzipped FileDescriptorProto // 3259 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0x4b, 0x73, 0x1b, 0xc7, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0xcd, 0x73, 0x1b, 0xc9,
0x76, 0xd6, 0xe0, 0x41, 0x02, 0x07, 0x04, 0xd8, 0x6c, 0x90, 0x12, 0x44, 0xf9, 0xda, 0xcc, 0xdc, 0x75, 0xd7, 0xe0, 0x8b, 0xc0, 0x03, 0x01, 0x36, 0x1b, 0xa4, 0x84, 0xe5, 0x7e, 0xd1, 0x63, 0xaf,
0xab, 0x7b, 0x19, 0xde, 0x1b, 0x4a, 0xa6, 0x64, 0x45, 0xb1, 0x1d, 0x47, 0x43, 0x70, 0x28, 0xc3, 0xcd, 0xd0, 0x0e, 0xa5, 0xe5, 0xca, 0x8a, 0xb2, 0x76, 0x1c, 0x0d, 0xc1, 0xa1, 0x16, 0x16, 0x30,
0xc2, 0x4b, 0x8d, 0x81, 0x64, 0xa9, 0x5c, 0x35, 0x35, 0x04, 0x5a, 0xe0, 0x14, 0x07, 0x33, 0xd0, 0x80, 0x1a, 0x03, 0xc9, 0xda, 0x72, 0xd5, 0xd4, 0x10, 0x68, 0x81, 0x53, 0x1c, 0xcc, 0x40, 0x33,
0xcc, 0x80, 0x14, 0x77, 0x4a, 0x1c, 0xe7, 0xfd, 0x70, 0x9e, 0x8e, 0x93, 0x8a, 0x93, 0xaa, 0xec, 0x03, 0x52, 0xbc, 0x29, 0x71, 0x9c, 0xef, 0xc4, 0x9b, 0xcf, 0x8d, 0x93, 0xca, 0x56, 0xaa, 0x72,
0xf3, 0x1b, 0x52, 0xf9, 0x01, 0xd9, 0x65, 0x91, 0x64, 0x91, 0x45, 0x2a, 0x95, 0x45, 0xaa, 0x5c, 0xcf, 0xdf, 0x90, 0xca, 0x21, 0xc7, 0xdc, 0x72, 0x48, 0x72, 0xc8, 0x21, 0x95, 0xca, 0xcd, 0x95,
0x59, 0x65, 0x91, 0x45, 0x2a, 0xd5, 0x8f, 0x19, 0x0c, 0x48, 0xe8, 0x61, 0xe5, 0x6e, 0x28, 0x7b, 0x53, 0x0e, 0x39, 0xa4, 0x52, 0xfd, 0x31, 0x83, 0x01, 0x89, 0x95, 0x64, 0x25, 0x17, 0x6a, 0x7d,
0xd7, 0x7d, 0xce, 0xe9, 0xc7, 0xf7, 0x9d, 0x33, 0xa7, 0x7b, 0xba, 0x1b, 0x0a, 0x8f, 0xc7, 0xd4, 0xeb, 0x7e, 0xef, 0xf5, 0xc7, 0xef, 0xf7, 0xde, 0xbc, 0xee, 0xe9, 0x6e, 0x28, 0x3f, 0x99, 0xd2,
0x3f, 0xde, 0x1c, 0xf9, 0x5e, 0xe8, 0xe1, 0x2c, 0xaf, 0xac, 0x96, 0x42, 0x6f, 0xe4, 0xf5, 0xad, 0xe0, 0x6c, 0x67, 0x12, 0xf8, 0x91, 0x8f, 0xf3, 0xbc, 0xb2, 0x51, 0x8d, 0xfc, 0x89, 0x3f, 0xb4,
0xd0, 0x12, 0xe2, 0xd5, 0xc2, 0x61, 0xe8, 0x8f, 0x7a, 0xa2, 0xa2, 0x7e, 0xa6, 0xc0, 0x9c, 0x61, 0x23, 0x5b, 0x88, 0x37, 0xca, 0x27, 0x51, 0x30, 0x19, 0x88, 0x8a, 0xfa, 0x43, 0x05, 0x0a, 0xa6,
0xf9, 0x03, 0x1a, 0xe2, 0x55, 0xc8, 0x1d, 0xd0, 0xe3, 0x60, 0x64, 0xf5, 0x68, 0x45, 0x59, 0x53, 0x1d, 0x8c, 0x68, 0x84, 0x37, 0xa0, 0x78, 0x4c, 0xcf, 0xc2, 0x89, 0x3d, 0xa0, 0x75, 0x65, 0x53,
0xd6, 0xf3, 0x24, 0xae, 0xe3, 0x65, 0xc8, 0x06, 0xfb, 0x96, 0xdf, 0xaf, 0xa4, 0xb8, 0x42, 0x54, 0xd9, 0x2a, 0x91, 0xa4, 0x8e, 0xd7, 0x20, 0x1f, 0x1e, 0xd9, 0xc1, 0xb0, 0x9e, 0xe1, 0x0a, 0x51,
0xf0, 0x3b, 0x50, 0x08, 0xad, 0x3d, 0x87, 0x86, 0x66, 0x78, 0x3c, 0xa2, 0x95, 0xf4, 0x9a, 0xb2, 0xc1, 0xdf, 0x84, 0x72, 0x64, 0x1f, 0xba, 0x34, 0xb2, 0xa2, 0xb3, 0x09, 0xad, 0x67, 0x37, 0x95,
0x5e, 0xda, 0x5a, 0xde, 0x8c, 0xc7, 0x33, 0xb8, 0xd2, 0x38, 0x1e, 0x51, 0x02, 0x61, 0x5c, 0xc6, 0xad, 0xea, 0xee, 0xda, 0x4e, 0x32, 0x9e, 0xc9, 0x95, 0xe6, 0xd9, 0x84, 0x12, 0x88, 0x92, 0x32,
0x18, 0x32, 0x3d, 0xea, 0x38, 0x95, 0x0c, 0xef, 0x8b, 0x97, 0xd5, 0x1d, 0x28, 0xdd, 0x33, 0x6e, 0xc6, 0x90, 0x1b, 0x50, 0xd7, 0xad, 0xe7, 0x78, 0x5f, 0xbc, 0xac, 0xee, 0x43, 0xf5, 0x81, 0x79,
0x5b, 0x21, 0xad, 0x5a, 0x8e, 0x43, 0xfd, 0xda, 0x0e, 0x9b, 0xce, 0x38, 0xa0, 0xbe, 0x6b, 0x0d, 0xd7, 0x8e, 0x68, 0xc3, 0x76, 0x5d, 0x1a, 0x34, 0xf7, 0xd9, 0x74, 0xa6, 0x21, 0x0d, 0x3c, 0x7b,
0xe3, 0xe9, 0x44, 0x75, 0x7c, 0x1e, 0xe6, 0x06, 0xbe, 0x37, 0x1e, 0x05, 0x95, 0xd4, 0x5a, 0x7a, 0x9c, 0x4c, 0x27, 0xae, 0xe3, 0xab, 0x50, 0x18, 0x05, 0xfe, 0x74, 0x12, 0xd6, 0x33, 0x9b, 0xd9,
0x3d, 0x4f, 0x64, 0x4d, 0xfd, 0x04, 0x40, 0x3f, 0xa4, 0x6e, 0x68, 0x78, 0x07, 0xd4, 0xc5, 0x6f, 0xad, 0x12, 0x91, 0x35, 0xf5, 0xfb, 0x00, 0xfa, 0x09, 0xf5, 0x22, 0xd3, 0x3f, 0xa6, 0x1e, 0x7e,
0x40, 0x3e, 0xb4, 0x87, 0x34, 0x08, 0xad, 0xe1, 0x88, 0x77, 0x91, 0x26, 0x13, 0xc1, 0x33, 0x20, 0x0b, 0x4a, 0x91, 0x33, 0xa6, 0x61, 0x64, 0x8f, 0x27, 0xbc, 0x8b, 0x2c, 0x99, 0x09, 0x3e, 0x07,
0xad, 0x42, 0x6e, 0xe4, 0x05, 0x76, 0x68, 0x7b, 0x2e, 0xc7, 0x93, 0x27, 0x71, 0x5d, 0xfd, 0x00, 0xd2, 0x06, 0x14, 0x27, 0x7e, 0xe8, 0x44, 0x8e, 0xef, 0x71, 0x3c, 0x25, 0x92, 0xd4, 0xd5, 0xef,
0xb2, 0xf7, 0x2c, 0x67, 0x4c, 0xf1, 0x5b, 0x90, 0xe1, 0x80, 0x15, 0x0e, 0xb8, 0xb0, 0x29, 0x48, 0x40, 0xfe, 0x81, 0xed, 0x4e, 0x29, 0x7e, 0x17, 0x72, 0x1c, 0xb0, 0xc2, 0x01, 0x97, 0x77, 0x04,
0xe7, 0x38, 0xb9, 0x82, 0xf5, 0x7d, 0xc8, 0x2c, 0x79, 0xdf, 0x0b, 0x44, 0x54, 0xd4, 0x03, 0x58, 0xe9, 0x1c, 0x27, 0x57, 0xb0, 0xbe, 0x4f, 0x98, 0x25, 0xef, 0x7b, 0x99, 0x88, 0x8a, 0x7a, 0x0c,
0xd8, 0xb6, 0xdd, 0xfe, 0x3d, 0xcb, 0xb7, 0x19, 0x19, 0xaf, 0xd8, 0x0d, 0xfe, 0x01, 0xcc, 0xf1, 0xcb, 0x7b, 0x8e, 0x37, 0x7c, 0x60, 0x07, 0x0e, 0x23, 0xe3, 0x15, 0xbb, 0xc1, 0x5f, 0x81, 0x02,
0x42, 0x50, 0x49, 0xaf, 0xa5, 0xd7, 0x0b, 0x5b, 0x0b, 0xb2, 0x21, 0x9f, 0x1b, 0x91, 0x3a, 0xf5, 0x2f, 0x84, 0xf5, 0xec, 0x66, 0x76, 0xab, 0xbc, 0xbb, 0x2c, 0x1b, 0xf2, 0xb9, 0x11, 0xa9, 0x53,
0xef, 0x15, 0x80, 0x6d, 0x6f, 0xec, 0xf6, 0xef, 0x32, 0x25, 0x46, 0x90, 0x0e, 0x1e, 0x3b, 0x92, 0xff, 0x4e, 0x01, 0xd8, 0xf3, 0xa7, 0xde, 0xf0, 0x3e, 0x53, 0x62, 0x04, 0xd9, 0xf0, 0x89, 0x2b,
0x48, 0x56, 0xc4, 0x77, 0xa0, 0xb4, 0x67, 0xbb, 0x7d, 0xf3, 0x50, 0x4e, 0x47, 0x70, 0x59, 0xd8, 0x89, 0x64, 0x45, 0x7c, 0x0f, 0xaa, 0x87, 0x8e, 0x37, 0xb4, 0x4e, 0xe4, 0x74, 0x04, 0x97, 0xe5,
0xfa, 0x81, 0xec, 0x6e, 0xd2, 0x78, 0x33, 0x39, 0xeb, 0x40, 0x77, 0x43, 0xff, 0x98, 0x14, 0xf7, 0xdd, 0xaf, 0xc8, 0xee, 0x66, 0x8d, 0x77, 0xd2, 0xb3, 0x0e, 0x75, 0x2f, 0x0a, 0xce, 0x48, 0xe5,
0x92, 0xb2, 0xd5, 0x2e, 0xe0, 0xd3, 0x46, 0x6c, 0xd0, 0x03, 0x7a, 0x1c, 0x0d, 0x7a, 0x40, 0x8f, 0x30, 0x2d, 0xdb, 0xe8, 0x03, 0xbe, 0x68, 0xc4, 0x06, 0x3d, 0xa6, 0x67, 0xf1, 0xa0, 0xc7, 0xf4,
0xf1, 0xcf, 0x26, 0x11, 0x15, 0xb6, 0xca, 0xd1, 0x58, 0x89, 0xb6, 0x12, 0xe6, 0xbb, 0xa9, 0x9b, 0x0c, 0xff, 0x5c, 0x1a, 0x51, 0x79, 0xb7, 0x16, 0x8f, 0x95, 0x6a, 0x2b, 0x61, 0x7e, 0x98, 0xb9,
0x8a, 0xfa, 0x9f, 0x59, 0x28, 0xe9, 0x4f, 0x68, 0x6f, 0x1c, 0xd2, 0xd6, 0x88, 0xf9, 0x20, 0xc0, 0xad, 0xa8, 0x3f, 0x2a, 0x40, 0x55, 0x7f, 0x4a, 0x07, 0xd3, 0x88, 0x76, 0x26, 0xcc, 0x07, 0x21,
0x9b, 0x50, 0xb6, 0xdd, 0x9e, 0x33, 0xee, 0x53, 0x93, 0x32, 0x57, 0x9b, 0x21, 0xf3, 0x35, 0xef, 0xde, 0x81, 0x9a, 0xe3, 0x0d, 0xdc, 0xe9, 0x90, 0x5a, 0x94, 0xb9, 0xda, 0x8a, 0x98, 0xaf, 0x79,
0x2f, 0x47, 0x96, 0xa4, 0x2a, 0x11, 0x04, 0x1a, 0x94, 0x7b, 0xde, 0x70, 0x64, 0xf9, 0xd3, 0xf6, 0x7f, 0x45, 0xb2, 0x2a, 0x55, 0xa9, 0x20, 0xd0, 0xa0, 0x36, 0xf0, 0xc7, 0x13, 0x3b, 0x98, 0xb7,
0x69, 0x3e, 0xfe, 0x92, 0x1c, 0x7f, 0x62, 0x4f, 0x96, 0xa4, 0x75, 0xa2, 0x8b, 0x06, 0x2c, 0xca, 0xcf, 0xf2, 0xf1, 0x57, 0xe5, 0xf8, 0x33, 0x7b, 0xb2, 0x2a, 0xad, 0x53, 0x5d, 0xb4, 0x61, 0x45,
0x7e, 0xfb, 0xe6, 0x23, 0x9b, 0x3a, 0xfd, 0x80, 0x87, 0x6e, 0x29, 0xa6, 0x6a, 0x7a, 0x8a, 0x9b, 0xf6, 0x3b, 0xb4, 0x1e, 0x3b, 0xd4, 0x1d, 0x86, 0x3c, 0x74, 0xab, 0x09, 0x55, 0xf3, 0x53, 0xdc,
0x35, 0x69, 0xbc, 0xcb, 0x6d, 0x49, 0xc9, 0x9e, 0xaa, 0xe3, 0x0d, 0x58, 0xea, 0x39, 0x36, 0x9b, 0x69, 0x4a, 0xe3, 0x03, 0x6e, 0x4b, 0xaa, 0xce, 0x5c, 0x1d, 0x6f, 0xc3, 0xea, 0xc0, 0x75, 0xd8,
0xca, 0x23, 0x46, 0xb1, 0xe9, 0x7b, 0x47, 0x41, 0x25, 0xcb, 0xe7, 0xbf, 0x28, 0x14, 0xbb, 0x4c, 0x54, 0x1e, 0x33, 0x8a, 0xad, 0xc0, 0x3f, 0x0d, 0xeb, 0x79, 0x3e, 0xff, 0x15, 0xa1, 0x38, 0x60,
0x4e, 0xbc, 0xa3, 0x00, 0xbf, 0x0b, 0xb9, 0x23, 0xcf, 0x3f, 0x70, 0x3c, 0xab, 0x5f, 0x99, 0xe3, 0x72, 0xe2, 0x9f, 0x86, 0xf8, 0x43, 0x28, 0x9e, 0xfa, 0xc1, 0xb1, 0xeb, 0xdb, 0xc3, 0x7a, 0x81,
0x63, 0xbe, 0x39, 0x7b, 0xcc, 0xfb, 0xd2, 0x8a, 0xc4, 0xf6, 0x78, 0x1d, 0x50, 0xf0, 0xd8, 0x31, 0x8f, 0xf9, 0xce, 0xe2, 0x31, 0x1f, 0x4a, 0x2b, 0x92, 0xd8, 0xe3, 0x2d, 0x40, 0xe1, 0x13, 0xd7,
0x03, 0xea, 0xd0, 0x5e, 0x68, 0x3a, 0xf6, 0xd0, 0x0e, 0x2b, 0x39, 0xfe, 0x15, 0x94, 0x82, 0xc7, 0x0a, 0xa9, 0x4b, 0x07, 0x91, 0xe5, 0x3a, 0x63, 0x27, 0xaa, 0x17, 0xf9, 0x57, 0x50, 0x0d, 0x9f,
0x4e, 0x87, 0x8b, 0xeb, 0x4c, 0x8a, 0x4d, 0x58, 0x09, 0x7d, 0xcb, 0x0d, 0xac, 0x1e, 0xeb, 0xcc, 0xb8, 0x3d, 0x2e, 0x6e, 0x31, 0x29, 0xb6, 0x60, 0x3d, 0x0a, 0x6c, 0x2f, 0xb4, 0x07, 0xac, 0x33,
0xb4, 0x03, 0xcf, 0xb1, 0xf8, 0x17, 0x90, 0xe7, 0x43, 0x6e, 0xcc, 0x1e, 0xd2, 0x98, 0x34, 0xa9, 0xcb, 0x09, 0x7d, 0xd7, 0xe6, 0x5f, 0x40, 0x89, 0x0f, 0xb9, 0xbd, 0x78, 0x48, 0x73, 0xd6, 0xa4,
0x45, 0x2d, 0xc8, 0x72, 0x38, 0x43, 0x8a, 0xdf, 0x86, 0x95, 0xe0, 0xc0, 0x1e, 0x99, 0xbc, 0x1f, 0x19, 0xb7, 0x20, 0x6b, 0xd1, 0x02, 0x29, 0x7e, 0x1f, 0xd6, 0xc3, 0x63, 0x67, 0x62, 0xf1, 0x7e,
0x73, 0xe4, 0x58, 0xae, 0xd9, 0xb3, 0x7a, 0xfb, 0xb4, 0x02, 0x1c, 0x36, 0x66, 0x4a, 0x1e, 0x6a, 0xac, 0x89, 0x6b, 0x7b, 0xd6, 0xc0, 0x1e, 0x1c, 0xd1, 0x3a, 0x70, 0xd8, 0x98, 0x29, 0x79, 0xa8,
0x6d, 0xc7, 0x72, 0xab, 0x4c, 0xa3, 0xbe, 0x07, 0xa5, 0x69, 0x1e, 0xf1, 0x12, 0x14, 0x8d, 0x07, 0x75, 0x5d, 0xdb, 0x6b, 0x30, 0x8d, 0xfa, 0x2d, 0xa8, 0xce, 0xf3, 0x88, 0x57, 0xa1, 0x62, 0x3e,
0x6d, 0xdd, 0xd4, 0x9a, 0x3b, 0x66, 0x53, 0x6b, 0xe8, 0xe8, 0x1c, 0x2e, 0x42, 0x9e, 0x8b, 0x5a, 0xea, 0xea, 0x96, 0x66, 0xec, 0x5b, 0x86, 0xd6, 0xd6, 0xd1, 0x15, 0x5c, 0x81, 0x12, 0x17, 0x75,
0xcd, 0xfa, 0x03, 0xa4, 0xe0, 0x79, 0x48, 0x6b, 0xf5, 0x3a, 0x4a, 0xa9, 0x37, 0x21, 0x17, 0x11, 0x8c, 0xd6, 0x23, 0xa4, 0xe0, 0x25, 0xc8, 0x6a, 0xad, 0x16, 0xca, 0xa8, 0xb7, 0xa1, 0x18, 0x13,
0x82, 0x17, 0xa1, 0xd0, 0x6d, 0x76, 0xda, 0x7a, 0xb5, 0xb6, 0x5b, 0xd3, 0x77, 0xd0, 0x39, 0x9c, 0x82, 0x57, 0xa0, 0xdc, 0x37, 0x7a, 0x5d, 0xbd, 0xd1, 0x3c, 0x68, 0xea, 0xfb, 0xe8, 0x0a, 0x2e,
0x83, 0x4c, 0xab, 0x6e, 0xb4, 0x91, 0x22, 0x4a, 0x5a, 0x1b, 0xa5, 0x58, 0xcb, 0x9d, 0x6d, 0x0d, 0x42, 0xae, 0xd3, 0x32, 0xbb, 0x48, 0x11, 0x25, 0xad, 0x8b, 0x32, 0xac, 0xe5, 0xfe, 0x9e, 0x86,
0xa5, 0xd5, 0x10, 0x96, 0x67, 0xe1, 0xc2, 0x05, 0x98, 0xdf, 0xd1, 0x77, 0xb5, 0x6e, 0xdd, 0x40, 0xb2, 0xea, 0xa7, 0x0a, 0xac, 0x2d, 0x02, 0x86, 0xcb, 0xb0, 0xb4, 0xaf, 0x1f, 0x68, 0xfd, 0x96,
0xe7, 0x70, 0x19, 0x16, 0x89, 0xde, 0xd6, 0x35, 0x43, 0xdb, 0xae, 0xeb, 0x26, 0xd1, 0xb5, 0x1d, 0x89, 0xae, 0xe0, 0x1a, 0xac, 0x10, 0xbd, 0xab, 0x6b, 0xa6, 0xb6, 0xd7, 0xd2, 0x2d, 0xa2, 0x6b,
0xa4, 0x60, 0x0c, 0x25, 0x56, 0x32, 0xab, 0xad, 0x46, 0xa3, 0x66, 0x18, 0xfa, 0x0e, 0x4a, 0xe1, 0xfb, 0x48, 0xc1, 0x18, 0xaa, 0xac, 0x64, 0x35, 0x3a, 0xed, 0x76, 0xd3, 0x34, 0xf5, 0x7d, 0x94,
0x65, 0x40, 0x5c, 0xd6, 0x6d, 0x4e, 0xa4, 0x69, 0x8c, 0x60, 0xa1, 0xa3, 0x93, 0x9a, 0x56, 0xaf, 0xc1, 0x6b, 0x80, 0xb8, 0xac, 0x6f, 0xcc, 0xa4, 0x59, 0x8c, 0x60, 0xb9, 0xa7, 0x93, 0xa6, 0xd6,
0x3d, 0x64, 0x1d, 0xa0, 0xcc, 0x47, 0x99, 0x9c, 0x82, 0x52, 0xea, 0x17, 0x29, 0xc8, 0x72, 0xac, 0x6a, 0x7e, 0xcc, 0x3a, 0x40, 0x39, 0xfc, 0x25, 0x78, 0xbb, 0xd1, 0x31, 0x7a, 0xcd, 0x9e, 0xa9,
0x2c, 0x43, 0x26, 0xf2, 0x1e, 0x2f, 0xc7, 0xd9, 0x22, 0xf5, 0x9c, 0x6c, 0xc1, 0x93, 0xac, 0xcc, 0x1b, 0xa6, 0xd5, 0x33, 0xb4, 0x6e, 0xef, 0xa3, 0x8e, 0xc9, 0x7b, 0x16, 0xe0, 0xf2, 0xdf, 0xcd,
0x5b, 0xa2, 0x82, 0x2f, 0x41, 0xde, 0xf3, 0x07, 0xa6, 0xd0, 0x88, 0x8c, 0x9b, 0xf3, 0xfc, 0x01, 0x15, 0x15, 0x94, 0x51, 0x3f, 0xcd, 0x40, 0x9e, 0xf3, 0xc1, 0xb2, 0x68, 0x2a, 0x37, 0xf2, 0x72,
0x4f, 0xcd, 0x2c, 0xdb, 0xb1, 0x44, 0xbd, 0x67, 0x05, 0x94, 0x47, 0x60, 0x9e, 0xc4, 0x75, 0x7c, 0x92, 0x51, 0x32, 0xcf, 0xc9, 0x28, 0x3c, 0x11, 0xcb, 0xdc, 0x26, 0x2a, 0xf8, 0x4d, 0x28, 0xf9,
0x11, 0x98, 0x9d, 0xc9, 0xe7, 0x31, 0xc7, 0x75, 0xf3, 0x9e, 0x3f, 0x68, 0xb2, 0xa9, 0x7c, 0x1f, 0xc1, 0xc8, 0x12, 0x1a, 0x91, 0x95, 0x8b, 0x7e, 0x30, 0xe2, 0xe9, 0x9b, 0x65, 0x44, 0x96, 0xcc,
0x8a, 0x3d, 0xcf, 0x19, 0x0f, 0x5d, 0xd3, 0xa1, 0xee, 0x20, 0xdc, 0xaf, 0xcc, 0xaf, 0x29, 0xeb, 0x0f, 0xed, 0x90, 0xf2, 0x28, 0x2d, 0x91, 0xa4, 0x8e, 0xdf, 0x00, 0x66, 0x67, 0xf1, 0x79, 0x14,
0x45, 0xb2, 0x20, 0x84, 0x75, 0x2e, 0xc3, 0x15, 0x98, 0xef, 0xed, 0x5b, 0x7e, 0x40, 0x45, 0xd4, 0xb8, 0x6e, 0xc9, 0x0f, 0x46, 0x06, 0x9b, 0xca, 0x97, 0xa1, 0x32, 0xf0, 0xdd, 0xe9, 0xd8, 0xb3,
0x15, 0x49, 0x54, 0xe5, 0xa3, 0xd2, 0x9e, 0x3d, 0xb4, 0x9c, 0x80, 0x47, 0x58, 0x91, 0xc4, 0x75, 0x5c, 0xea, 0x8d, 0xa2, 0xa3, 0xfa, 0xd2, 0xa6, 0xb2, 0x55, 0x21, 0xcb, 0x42, 0xd8, 0xe2, 0x32,
0x06, 0xe2, 0x91, 0x63, 0x0d, 0x02, 0x1e, 0x19, 0x45, 0x22, 0x2a, 0xea, 0xcf, 0x43, 0x9a, 0x78, 0x5c, 0x87, 0xa5, 0xc1, 0x91, 0x1d, 0x84, 0x54, 0x44, 0x66, 0x85, 0xc4, 0x55, 0x3e, 0x2a, 0x1d,
0x47, 0xac, 0x4b, 0x31, 0x60, 0x50, 0x51, 0xd6, 0xd2, 0xeb, 0x98, 0x44, 0x55, 0xb6, 0x20, 0xc8, 0x38, 0x63, 0xdb, 0x0d, 0x79, 0x14, 0x56, 0x48, 0x52, 0x67, 0x20, 0x1e, 0xbb, 0xf6, 0x28, 0xe4,
0x9c, 0x28, 0x52, 0x65, 0x94, 0x05, 0x3f, 0x81, 0x05, 0x42, 0x83, 0xb1, 0x13, 0xea, 0x4f, 0x42, 0xd1, 0x53, 0x21, 0xa2, 0xa2, 0xfe, 0x02, 0x64, 0x89, 0x7f, 0xca, 0xba, 0x14, 0x03, 0x86, 0x75,
0xdf, 0x0a, 0xf0, 0x16, 0x14, 0x92, 0x59, 0x40, 0x79, 0x56, 0x16, 0x00, 0x3a, 0xf9, 0xfc, 0x2b, 0x65, 0x33, 0xbb, 0x85, 0x49, 0x5c, 0x65, 0x8b, 0x86, 0xcc, 0x9b, 0x22, 0x9d, 0xc6, 0x99, 0xf2,
0x30, 0xff, 0xc8, 0xa7, 0xc1, 0x3e, 0xf5, 0x65, 0x96, 0x89, 0xaa, 0x2c, 0xc7, 0x16, 0x78, 0xd8, 0xfb, 0xb0, 0x4c, 0x68, 0x38, 0x75, 0x23, 0xfd, 0x69, 0x14, 0xd8, 0x21, 0xde, 0x85, 0x72, 0x3a,
0x8a, 0x31, 0x58, 0x66, 0x96, 0xf9, 0x41, 0x99, 0xca, 0xcc, 0xdc, 0xa9, 0x44, 0xea, 0x18, 0x7b, 0x53, 0x28, 0x9f, 0x97, 0x29, 0x80, 0xce, 0x52, 0x44, 0x1d, 0x96, 0x1e, 0x07, 0x34, 0x3c, 0xa2,
0xec, 0x93, 0x37, 0xad, 0x47, 0x8f, 0x68, 0x2f, 0xa4, 0x62, 0x01, 0xca, 0x90, 0x05, 0x26, 0xd4, 0x81, 0xcc, 0x44, 0x71, 0x95, 0xe5, 0xe1, 0x32, 0x0f, 0x6d, 0x31, 0x06, 0xcb, 0xde, 0x32, 0x87,
0xa4, 0x8c, 0xb9, 0xcd, 0x76, 0x03, 0xea, 0x87, 0xa6, 0xdd, 0xe7, 0x0e, 0xcd, 0x90, 0x9c, 0x10, 0x28, 0x73, 0xd9, 0x9b, 0x3b, 0x95, 0x48, 0x1d, 0x63, 0x8f, 0xa5, 0x05, 0xcb, 0x7e, 0xfc, 0x98,
0xd4, 0xfa, 0xf8, 0x4d, 0xc8, 0xf0, 0xa4, 0x91, 0xe1, 0xa3, 0x80, 0x1c, 0x85, 0x78, 0x47, 0x84, 0x0e, 0x22, 0x2a, 0x16, 0xa9, 0x1c, 0x59, 0x66, 0x42, 0x4d, 0xca, 0x98, 0xdb, 0x1c, 0x2f, 0xa4,
0xcb, 0xf1, 0x8f, 0x61, 0x8e, 0x72, 0xbc, 0xdc, 0xa9, 0x93, 0x34, 0x9b, 0xa4, 0x82, 0x48, 0x13, 0x41, 0x64, 0x39, 0x43, 0xee, 0xd0, 0x1c, 0x29, 0x0a, 0x41, 0x73, 0x88, 0xdf, 0x81, 0x1c, 0x4f,
0xf5, 0x7d, 0x58, 0xe0, 0x18, 0xee, 0x5b, 0xbe, 0x6b, 0xbb, 0x03, 0xbe, 0x3a, 0x7b, 0x7d, 0x11, 0x2c, 0x39, 0x3e, 0x0a, 0xc8, 0x51, 0x88, 0x7f, 0x4a, 0xb8, 0x1c, 0x7f, 0x1d, 0x0a, 0x94, 0xe3,
0x7b, 0x45, 0xc2, 0xcb, 0x8c, 0x82, 0x21, 0x0d, 0x02, 0x6b, 0x40, 0xe5, 0x6a, 0x19, 0x55, 0xd5, 0xe5, 0x4e, 0x9d, 0xa5, 0xe2, 0x34, 0x15, 0x44, 0x9a, 0xa8, 0xdf, 0x86, 0x65, 0x8e, 0xe1, 0xa1,
0xbf, 0x4e, 0x43, 0xa1, 0x13, 0xfa, 0xd4, 0x1a, 0x72, 0xf6, 0xf0, 0xfb, 0x00, 0x41, 0x68, 0x85, 0x1d, 0x78, 0x8e, 0x37, 0xe2, 0x2b, 0xb8, 0x3f, 0x14, 0xb1, 0x57, 0x21, 0xbc, 0xcc, 0x28, 0x18,
0x74, 0x48, 0xdd, 0x30, 0xa2, 0xe1, 0x0d, 0x39, 0x7c, 0xc2, 0x6e, 0xb3, 0x13, 0x19, 0x91, 0x84, 0xd3, 0x30, 0xb4, 0x47, 0x54, 0xae, 0xa8, 0x71, 0x55, 0xfd, 0xab, 0x2c, 0x94, 0x7b, 0x51, 0x40,
0xfd, 0x49, 0xf7, 0xa4, 0x5e, 0xc2, 0x3d, 0xab, 0x5f, 0xa5, 0x20, 0x1f, 0xf7, 0x86, 0x35, 0xc8, 0xed, 0x31, 0x67, 0x0f, 0x7f, 0x1b, 0x20, 0x8c, 0xec, 0x88, 0x8e, 0xa9, 0x17, 0xc5, 0x34, 0xbc,
0xf5, 0xac, 0x90, 0x0e, 0x3c, 0xff, 0x58, 0xae, 0xab, 0x97, 0x9f, 0x37, 0xfa, 0x66, 0x55, 0x1a, 0x25, 0x87, 0x4f, 0xd9, 0xed, 0xf4, 0x62, 0x23, 0x92, 0xb2, 0x3f, 0xef, 0x9e, 0xcc, 0x4b, 0xb8,
0x93, 0xb8, 0x19, 0xfe, 0x1e, 0x88, 0xcd, 0x8a, 0x08, 0x7d, 0x81, 0x37, 0xcf, 0x25, 0x3c, 0xf8, 0x67, 0xe3, 0xb3, 0x0c, 0x94, 0x92, 0xde, 0xb0, 0x06, 0xc5, 0x81, 0x1d, 0xd1, 0x91, 0x1f, 0x9c,
0xdf, 0x05, 0x3c, 0xf2, 0xed, 0xa1, 0xe5, 0x1f, 0x9b, 0x07, 0xf4, 0x38, 0x5a, 0x10, 0xd2, 0x33, 0xc9, 0xb5, 0xf7, 0xbd, 0xe7, 0x8d, 0xbe, 0xd3, 0x90, 0xc6, 0x24, 0x69, 0x86, 0xdf, 0x06, 0xb1,
0x1c, 0x8e, 0xa4, 0xdd, 0x1d, 0x7a, 0x2c, 0x53, 0xd8, 0xcd, 0xe9, 0xb6, 0x32, 0x64, 0x4f, 0xbb, 0xa1, 0x11, 0xa1, 0x2f, 0xf0, 0x96, 0xb8, 0x84, 0x07, 0xff, 0x87, 0x80, 0x27, 0x81, 0x33, 0xb6,
0x31, 0xd1, 0x92, 0xaf, 0xea, 0x41, 0xb4, 0x7e, 0x67, 0x79, 0x74, 0xb3, 0xa2, 0xfa, 0x23, 0xc8, 0x83, 0x33, 0xeb, 0x98, 0x9e, 0xc5, 0x8b, 0x46, 0x76, 0x81, 0xc3, 0x91, 0xb4, 0xbb, 0x47, 0xcf,
0x45, 0x93, 0xc7, 0x79, 0xc8, 0xea, 0xbe, 0xef, 0xf9, 0xe8, 0x1c, 0xcf, 0x64, 0x8d, 0xba, 0x48, 0x64, 0x9a, 0xbb, 0x3d, 0xdf, 0x56, 0x86, 0xec, 0x45, 0x37, 0xa6, 0x5a, 0xf2, 0x95, 0x3f, 0x8c,
0x86, 0x3b, 0x3b, 0x2c, 0x19, 0xfe, 0x5d, 0x2a, 0x5e, 0x44, 0x09, 0x7d, 0x3c, 0xa6, 0x41, 0x88, 0xd7, 0xf8, 0x3c, 0x8f, 0x6e, 0x56, 0x54, 0xbf, 0x06, 0xc5, 0x78, 0xf2, 0xb8, 0x04, 0x79, 0x3d,
0x7f, 0x09, 0xca, 0x94, 0x47, 0x9a, 0x7d, 0x48, 0xcd, 0x1e, 0xdf, 0x71, 0xb1, 0x38, 0x13, 0x9f, 0x08, 0xfc, 0x00, 0x5d, 0xe1, 0xd9, 0xae, 0xdd, 0x12, 0x09, 0x73, 0x7f, 0x9f, 0x25, 0xcc, 0xbf,
0xc3, 0xe2, 0xa6, 0xd8, 0x20, 0x46, 0x3b, 0x31, 0xb2, 0x14, 0xdb, 0x4a, 0x51, 0x1f, 0xeb, 0x50, 0xcd, 0x24, 0x0b, 0x2d, 0xa1, 0x4f, 0xa6, 0x34, 0x8c, 0xf0, 0x2f, 0x43, 0x8d, 0xf2, 0x48, 0x73,
0xb6, 0x87, 0x43, 0xda, 0xb7, 0xad, 0x30, 0xd9, 0x81, 0x70, 0xd8, 0x4a, 0xb4, 0x21, 0x99, 0xda, 0x4e, 0xa8, 0x35, 0xe0, 0xbb, 0x32, 0x16, 0x67, 0xe2, 0x73, 0x58, 0xd9, 0x11, 0x9b, 0xc8, 0x78,
0xd0, 0x91, 0xa5, 0xb8, 0x45, 0xdc, 0xcd, 0x65, 0x98, 0x0b, 0xf9, 0xe6, 0x53, 0xae, 0xc7, 0xc5, 0xb7, 0x46, 0x56, 0x13, 0x5b, 0x29, 0x1a, 0x62, 0x1d, 0x6a, 0xce, 0x78, 0x4c, 0x87, 0x8e, 0x1d,
0x28, 0xab, 0x71, 0x21, 0x91, 0x4a, 0xfc, 0x23, 0x10, 0x5b, 0x59, 0x9e, 0xbf, 0x26, 0x01, 0x31, 0xa5, 0x3b, 0x10, 0x0e, 0x5b, 0x8f, 0x37, 0x2d, 0x73, 0x9b, 0x3e, 0xb2, 0x9a, 0xb4, 0x48, 0xba,
0xd9, 0xa1, 0x10, 0xa1, 0xc7, 0x97, 0xa1, 0x34, 0xb5, 0x90, 0xf5, 0x39, 0x61, 0x69, 0x52, 0x4c, 0x79, 0x0f, 0x0a, 0x11, 0xdf, 0xa0, 0xca, 0x35, 0xbb, 0x12, 0x67, 0x35, 0x2e, 0x24, 0x52, 0x89,
0xae, 0x4a, 0x7d, 0x7c, 0x05, 0xe6, 0x3d, 0xb1, 0x88, 0xf1, 0xcc, 0x36, 0x99, 0xf1, 0xf4, 0x0a, 0xbf, 0x06, 0x62, 0xbb, 0xcb, 0xf3, 0xd7, 0x2c, 0x20, 0x66, 0xbb, 0x18, 0x22, 0xf4, 0xf8, 0x3d,
0x47, 0x22, 0x2b, 0xf5, 0x17, 0x61, 0x31, 0x66, 0x30, 0x18, 0x79, 0x6e, 0x40, 0xf1, 0x06, 0xcc, 0xa8, 0xce, 0x2d, 0x76, 0x43, 0x4e, 0x58, 0x96, 0x54, 0xd2, 0x2b, 0xd7, 0x10, 0x5f, 0x87, 0x25,
0xf9, 0xfc, 0x73, 0x92, 0xac, 0x61, 0xd9, 0x45, 0x22, 0x1f, 0x10, 0x69, 0xa1, 0xf6, 0x61, 0x51, 0x5f, 0x2c, 0x74, 0x3c, 0xb3, 0xcd, 0x66, 0x3c, 0xbf, 0x0a, 0x92, 0xd8, 0x4a, 0xfd, 0x25, 0x58,
0x48, 0xee, 0xdb, 0xe1, 0x3e, 0x77, 0x14, 0xbe, 0x0c, 0x59, 0xca, 0x0a, 0x27, 0x38, 0x27, 0xed, 0x49, 0x18, 0x0c, 0x27, 0xbe, 0x17, 0x52, 0xbc, 0x0d, 0x85, 0x80, 0x7f, 0x4e, 0x92, 0x35, 0x2c,
0x2a, 0xd7, 0x13, 0xa1, 0x4d, 0x8c, 0x92, 0x7a, 0xe1, 0x28, 0xff, 0x95, 0x82, 0xb2, 0x9c, 0xe5, 0xbb, 0x48, 0xe5, 0x03, 0x22, 0x2d, 0xd4, 0x21, 0xac, 0x08, 0xc9, 0x43, 0x27, 0x3a, 0xe2, 0x8e,
0xb6, 0x15, 0xf6, 0xf6, 0xcf, 0xa8, 0xb3, 0x7f, 0x0c, 0xf3, 0x4c, 0x6e, 0xc7, 0x1f, 0xc6, 0x0c, 0xc2, 0xef, 0x41, 0x9e, 0xb2, 0xc2, 0x39, 0xce, 0x49, 0xb7, 0xc1, 0xf5, 0x44, 0x68, 0x53, 0xa3,
0x77, 0x47, 0x16, 0xcc, 0xe1, 0x56, 0x60, 0x26, 0xbc, 0x2b, 0x37, 0x52, 0x45, 0x2b, 0x48, 0x2c, 0x64, 0x5e, 0x38, 0xca, 0x7f, 0x66, 0xa0, 0x26, 0x67, 0xb9, 0x67, 0x47, 0x83, 0xa3, 0x4b, 0xea,
0xe3, 0x33, 0xe2, 0x62, 0xee, 0x05, 0x71, 0x31, 0xff, 0x52, 0x71, 0xb1, 0x03, 0xcb, 0xd3, 0x8c, 0xec, 0xaf, 0xc3, 0x12, 0x93, 0x3b, 0xc9, 0x87, 0xb1, 0xc0, 0xdd, 0xb1, 0x05, 0x73, 0xb8, 0x1d,
0xcb, 0xe0, 0xf8, 0x09, 0xcc, 0x0b, 0xa7, 0x44, 0x29, 0x70, 0x96, 0xdf, 0x22, 0x13, 0xf5, 0xaf, 0x5a, 0x29, 0xef, 0xca, 0xcd, 0x56, 0xc5, 0x0e, 0x53, 0x2b, 0xfd, 0x82, 0xb8, 0x28, 0xbc, 0x20,
0x52, 0xb0, 0x2c, 0xb3, 0xd3, 0xb7, 0xe3, 0x33, 0x4d, 0xf0, 0x9c, 0x7d, 0x29, 0x9e, 0xab, 0xb0, 0x2e, 0x96, 0x5e, 0x2a, 0x2e, 0xf6, 0x61, 0x6d, 0x9e, 0x71, 0x19, 0x1c, 0xdf, 0x80, 0x25, 0xe1,
0x72, 0x82, 0xa0, 0x57, 0xf8, 0x0a, 0xbf, 0x56, 0x60, 0x61, 0x9b, 0x0e, 0x6c, 0xf7, 0x8c, 0xd2, 0x94, 0x38, 0x05, 0x2e, 0xf2, 0x5b, 0x6c, 0xa2, 0xfe, 0x7d, 0x06, 0xd6, 0x64, 0x76, 0xfa, 0x62,
0x9b, 0x60, 0x2d, 0xf3, 0x52, 0xac, 0xdd, 0x80, 0xa2, 0xc4, 0x2b, 0xd9, 0x3a, 0xfd, 0x19, 0x28, 0x7c, 0xa6, 0x29, 0x9e, 0xf3, 0x2f, 0xc3, 0xf3, 0x4b, 0xfa, 0x4f, 0x6d, 0xc0, 0xfa, 0x39, 0x1e,
0x33, 0x3e, 0x03, 0xf5, 0xdf, 0x15, 0x28, 0x56, 0xbd, 0xe1, 0xd0, 0x0e, 0xcf, 0x28, 0x53, 0xa7, 0x5f, 0xe1, 0x63, 0xfd, 0x89, 0x02, 0xcb, 0x7b, 0x74, 0xe4, 0x78, 0x97, 0xd4, 0x0b, 0x29, 0x72,
0x71, 0x66, 0x66, 0xe1, 0x44, 0x50, 0x8a, 0x60, 0x0a, 0x82, 0xd4, 0xff, 0x50, 0x60, 0x91, 0x78, 0x73, 0x2f, 0x15, 0xc4, 0xb7, 0xa0, 0x22, 0xf1, 0x4a, 0xb6, 0x2e, 0xb2, 0xad, 0x2c, 0x62, 0xfb,
0x8e, 0xb3, 0x67, 0xf5, 0x0e, 0x5e, 0x6f, 0xec, 0x18, 0xd0, 0x04, 0xa8, 0x44, 0xff, 0x3f, 0x0a, 0xdf, 0x15, 0xa8, 0x34, 0xfc, 0xf1, 0xd8, 0x89, 0x2e, 0x29, 0x53, 0x17, 0x71, 0xe6, 0x16, 0xe1,
0x94, 0xda, 0x3e, 0x65, 0x7f, 0xbf, 0xaf, 0x35, 0x78, 0xb6, 0xc5, 0xed, 0x87, 0x72, 0x73, 0x90, 0x44, 0x50, 0x8d, 0x61, 0x0a, 0x82, 0xd4, 0xff, 0x50, 0x60, 0x85, 0xf8, 0xae, 0x7b, 0x68, 0x0f,
0x27, 0xbc, 0xac, 0x2e, 0xc1, 0x62, 0x8c, 0x5d, 0xf2, 0xf1, 0xcf, 0x0a, 0xac, 0x88, 0x00, 0x91, 0x8e, 0x5f, 0x6f, 0xec, 0x18, 0xd0, 0x0c, 0xa8, 0x44, 0xff, 0xdf, 0x0a, 0x54, 0xbb, 0x01, 0x65,
0x9a, 0xfe, 0x19, 0xa5, 0x25, 0xc2, 0x9b, 0x49, 0xe0, 0xad, 0xc0, 0xf9, 0x93, 0xd8, 0x24, 0xec, 0x3f, 0xd2, 0xaf, 0x35, 0x78, 0xb6, 0x13, 0x1e, 0x46, 0x72, 0x0f, 0x51, 0x22, 0xbc, 0xac, 0xae,
0x4f, 0x53, 0x70, 0x21, 0x8a, 0x8d, 0x33, 0x0e, 0xfc, 0xff, 0x11, 0x0f, 0xab, 0x50, 0x39, 0x4d, 0xc2, 0x4a, 0x82, 0x5d, 0xf2, 0xf1, 0xcf, 0x0a, 0xac, 0x8b, 0x00, 0x91, 0x9a, 0xe1, 0x25, 0xa5,
0x82, 0x64, 0xe8, 0xf3, 0x14, 0x54, 0xaa, 0x3e, 0xb5, 0x42, 0x9a, 0xd8, 0x64, 0xbc, 0x3e, 0xb1, 0x25, 0xc6, 0x9b, 0x4b, 0xe1, 0xad, 0xc3, 0xd5, 0xf3, 0xd8, 0x24, 0xec, 0x1f, 0x64, 0xe0, 0x5a,
0x81, 0xdf, 0x86, 0x85, 0x91, 0xe5, 0x87, 0x76, 0xcf, 0x1e, 0x59, 0xec, 0x37, 0x2e, 0xcb, 0xf7, 0x1c, 0x1b, 0x97, 0x1c, 0xf8, 0xff, 0x21, 0x1e, 0x36, 0xa0, 0x7e, 0x91, 0x04, 0xc9, 0xd0, 0x27,
0x30, 0x27, 0x3a, 0x98, 0x32, 0x51, 0x2f, 0xc1, 0xc5, 0x19, 0x8c, 0x48, 0xbe, 0xfe, 0x57, 0x01, 0x19, 0xa8, 0x37, 0x02, 0x6a, 0x47, 0x34, 0xb5, 0x17, 0x79, 0x7d, 0x62, 0x03, 0xbf, 0x0f, 0xcb,
0xdc, 0x09, 0x2d, 0x3f, 0xfc, 0x16, 0xac, 0x2a, 0x33, 0x83, 0x69, 0x05, 0xca, 0x53, 0xf8, 0x93, 0x13, 0x3b, 0x88, 0x9c, 0x81, 0x33, 0xb1, 0xd9, 0xdf, 0x5e, 0x9e, 0x6f, 0x75, 0xce, 0x75, 0x30,
0xbc, 0xd0, 0xf0, 0x5b, 0xb1, 0xe2, 0x3c, 0x93, 0x97, 0x24, 0x7e, 0xc9, 0xcb, 0xbf, 0x2a, 0xb0, 0x67, 0xa2, 0xbe, 0x09, 0x6f, 0x2c, 0x60, 0x44, 0xf2, 0xf5, 0x3f, 0x0a, 0xe0, 0x5e, 0x64, 0x07,
0x5a, 0xf5, 0xc4, 0xe9, 0xdf, 0x6b, 0xf9, 0x85, 0xa9, 0xdf, 0x83, 0x4b, 0x33, 0x01, 0x4a, 0x02, 0xd1, 0x17, 0x60, 0x55, 0x59, 0x18, 0x4c, 0xeb, 0x50, 0x9b, 0xc3, 0x9f, 0xe6, 0x85, 0x46, 0x5f,
0xfe, 0x45, 0x81, 0xf3, 0x84, 0x5a, 0xfd, 0xd7, 0x13, 0xfc, 0x5d, 0xb8, 0x70, 0x0a, 0x9c, 0xdc, 0x88, 0x15, 0xe7, 0x73, 0x79, 0x49, 0xe3, 0x97, 0xbc, 0xfc, 0xab, 0x02, 0x1b, 0x0d, 0x5f, 0x1c,
0xa1, 0xde, 0x80, 0xdc, 0x90, 0x86, 0x56, 0xdf, 0x0a, 0x2d, 0x09, 0x69, 0x35, 0xea, 0x77, 0x62, 0x24, 0xbe, 0x96, 0x5f, 0x98, 0xfa, 0x36, 0xbc, 0xb9, 0x10, 0xa0, 0x24, 0xe0, 0x5f, 0x14, 0xb8,
0xdd, 0x90, 0x16, 0x24, 0xb6, 0x55, 0xbf, 0x4a, 0x41, 0x99, 0xef, 0x75, 0xbf, 0xfb, 0x83, 0x9a, 0x4a, 0xa8, 0x3d, 0x7c, 0x3d, 0xc1, 0xdf, 0x87, 0x6b, 0x17, 0xc0, 0xc9, 0x1d, 0xea, 0x2d, 0x28,
0xfd, 0x2f, 0xf0, 0xb9, 0x02, 0xcb, 0xd3, 0x04, 0xc5, 0xff, 0x04, 0x3f, 0xed, 0x83, 0x88, 0x19, 0x8e, 0x69, 0x64, 0x0f, 0xed, 0xc8, 0x96, 0x90, 0x36, 0xe2, 0x7e, 0x67, 0xd6, 0x6d, 0x69, 0x41,
0x09, 0x21, 0x3d, 0x6b, 0x0b, 0xfa, 0x0f, 0x29, 0xa8, 0x24, 0xa7, 0xf4, 0xdd, 0xa1, 0xc5, 0xf4, 0x12, 0x5b, 0xf5, 0xb3, 0x0c, 0xd4, 0xf8, 0x5e, 0xf7, 0x67, 0x3f, 0x5a, 0x8b, 0xff, 0x05, 0x3e,
0xa1, 0xc5, 0x37, 0x3e, 0xa5, 0xfa, 0x42, 0x81, 0x8b, 0x33, 0x08, 0xfd, 0x66, 0x8e, 0x4e, 0x1c, 0x51, 0x60, 0x6d, 0x9e, 0xa0, 0xe4, 0x9f, 0xe0, 0xff, 0xfb, 0xbc, 0x62, 0x41, 0x42, 0xc8, 0x2e,
0x5d, 0xa4, 0x5e, 0x78, 0x74, 0xf1, 0xb2, 0xae, 0xfe, 0x27, 0x05, 0x96, 0x1b, 0xe2, 0xc4, 0x58, 0xda, 0x82, 0xfe, 0x43, 0x06, 0xea, 0xe9, 0x29, 0xfd, 0xec, 0x6c, 0x63, 0xfe, 0x6c, 0xe3, 0xa7,
0xfc, 0xc7, 0x9f, 0xdd, 0x6c, 0xc6, 0x0f, 0x85, 0x33, 0x93, 0x7b, 0x19, 0xb5, 0x0a, 0x2b, 0x27, 0x3e, 0xcc, 0xfa, 0x54, 0x81, 0x37, 0x16, 0x10, 0xfa, 0xd3, 0x39, 0x3a, 0x75, 0xc2, 0x91, 0x79,
0xa0, 0xbd, 0xc2, 0xd9, 0xc4, 0x7f, 0x2b, 0xb0, 0x24, 0x7b, 0xd1, 0xce, 0xec, 0x46, 0x60, 0x06, 0xe1, 0x09, 0xc7, 0xcb, 0xba, 0xfa, 0x9f, 0x14, 0x58, 0x6b, 0x8b, 0x83, 0x65, 0xf1, 0x1f, 0x7f,
0x3b, 0xf8, 0x4d, 0x48, 0xdb, 0xfd, 0x68, 0x07, 0x39, 0x7d, 0x53, 0xcd, 0x14, 0xea, 0x2d, 0xc0, 0x79, 0xb3, 0x19, 0x3f, 0x3b, 0xce, 0xcd, 0xae, 0x6f, 0xd4, 0x06, 0xac, 0x9f, 0x83, 0xf6, 0x0a,
0x49, 0xdc, 0xaf, 0x40, 0xdd, 0x3f, 0xa6, 0x61, 0xa9, 0x33, 0x72, 0xec, 0x50, 0x2a, 0x5f, 0xef, 0x67, 0x13, 0xff, 0xa5, 0xc0, 0xaa, 0xec, 0x45, 0xbb, 0xb4, 0x1b, 0x81, 0x05, 0xec, 0xe0, 0x77,
0xc4, 0xff, 0x33, 0xb0, 0x10, 0x30, 0xb0, 0xa6, 0xb8, 0x6b, 0xe3, 0xc4, 0xe6, 0x49, 0x81, 0xcb, 0x20, 0xeb, 0x0c, 0xe3, 0x1d, 0xe4, 0xfc, 0xa5, 0x37, 0x53, 0xa8, 0x77, 0x00, 0xa7, 0x71, 0xbf,
0xaa, 0x5c, 0x84, 0xdf, 0x82, 0x42, 0x64, 0x32, 0x76, 0x43, 0x79, 0xd2, 0x09, 0xd2, 0x62, 0xec, 0x02, 0x75, 0xff, 0x98, 0x85, 0xd5, 0xde, 0xc4, 0x75, 0x22, 0xa9, 0x7c, 0xbd, 0x13, 0xff, 0x97,
0x86, 0xf8, 0x3a, 0x5c, 0x70, 0xc7, 0x43, 0x7e, 0xef, 0x6c, 0x8e, 0xa8, 0x1f, 0xdd, 0xca, 0x5a, 0x60, 0x39, 0x64, 0x60, 0x2d, 0x71, 0x25, 0xc7, 0x89, 0x2d, 0x91, 0x32, 0x97, 0x35, 0xb8, 0x08,
0x7e, 0x74, 0x3f, 0x5c, 0x76, 0xc7, 0x43, 0xe2, 0x1d, 0x05, 0x6d, 0xea, 0x8b, 0x5b, 0x59, 0xcb, 0xbf, 0x0b, 0xe5, 0xd8, 0x64, 0xea, 0x45, 0xf2, 0x40, 0x0d, 0xa4, 0xc5, 0xd4, 0x8b, 0xf0, 0x4d,
0x0f, 0xf1, 0x2d, 0xc8, 0x5b, 0xce, 0xc0, 0xf3, 0xed, 0x70, 0x7f, 0x28, 0x2f, 0x86, 0xd5, 0xe8, 0xb8, 0xe6, 0x4d, 0xc7, 0xfc, 0x0a, 0xdb, 0x9a, 0xd0, 0x20, 0xbe, 0xe0, 0xb5, 0x83, 0xf8, 0xaa,
0x6a, 0xe5, 0x24, 0xfd, 0x9b, 0x5a, 0x64, 0x49, 0x26, 0x8d, 0xd4, 0x9f, 0x40, 0x3e, 0x96, 0x63, 0xb9, 0xe6, 0x4d, 0xc7, 0xc4, 0x3f, 0x0d, 0xbb, 0x34, 0x10, 0x17, 0xbc, 0x76, 0x10, 0xe1, 0x3b,
0x04, 0x0b, 0xfa, 0xdd, 0xae, 0x56, 0x37, 0x3b, 0xed, 0x7a, 0xcd, 0xe8, 0x88, 0xcb, 0xdc, 0xdd, 0x50, 0xb2, 0xdd, 0x91, 0x1f, 0x38, 0xd1, 0xd1, 0x58, 0xde, 0x31, 0xab, 0xf1, 0x0d, 0xcc, 0x79,
0x6e, 0xbd, 0x6e, 0x76, 0xaa, 0x5a, 0x13, 0x29, 0x2a, 0x01, 0xe0, 0x5d, 0xf2, 0xce, 0x27, 0x04, 0xfa, 0x77, 0xb4, 0xd8, 0x92, 0xcc, 0x1a, 0xa9, 0xdf, 0x80, 0x52, 0x22, 0xc7, 0x08, 0x96, 0xf5,
0x29, 0x2f, 0x20, 0xe8, 0x12, 0xe4, 0x7d, 0xef, 0x48, 0x62, 0x4f, 0x71, 0x38, 0x39, 0xdf, 0x3b, 0xfb, 0x7d, 0xad, 0x65, 0xf5, 0xba, 0xad, 0xa6, 0xd9, 0x13, 0xf7, 0xc2, 0x07, 0xfd, 0x56, 0xcb,
0xe2, 0xc8, 0x55, 0x0d, 0x70, 0x72, 0xae, 0x32, 0xda, 0x12, 0xc9, 0x5b, 0x99, 0x4a, 0xde, 0x93, 0xea, 0x35, 0x34, 0x03, 0x29, 0x2a, 0x01, 0xe0, 0x5d, 0xf2, 0xce, 0x67, 0x04, 0x29, 0x2f, 0x20,
0xf1, 0xe3, 0xe4, 0x2d, 0xb6, 0xf2, 0xec, 0x3b, 0xff, 0x90, 0x5a, 0x4e, 0x18, 0xad, 0x57, 0xea, 0xe8, 0x4d, 0x28, 0x05, 0xfe, 0xa9, 0xc4, 0x9e, 0xe1, 0x70, 0x8a, 0x81, 0x7f, 0xca, 0x91, 0xab,
0xdf, 0xa4, 0xa0, 0x48, 0x98, 0xc4, 0x1e, 0xd2, 0x4e, 0x68, 0x85, 0x01, 0xf3, 0xd4, 0x3e, 0x37, 0x1a, 0xe0, 0xf4, 0x5c, 0x65, 0xb4, 0xa5, 0x92, 0xb7, 0x32, 0x97, 0xbc, 0x67, 0xe3, 0x27, 0xc9,
0x31, 0x27, 0x69, 0x37, 0x4f, 0x0a, 0x42, 0x26, 0x2e, 0x01, 0xb6, 0x60, 0x25, 0xa0, 0x3d, 0xcf, 0x5b, 0x6c, 0xe5, 0xd9, 0x77, 0xfe, 0x11, 0xb5, 0xdd, 0x28, 0x5e, 0xaf, 0xd4, 0xbf, 0xce, 0x40,
0xed, 0x07, 0xe6, 0x1e, 0xdd, 0xb7, 0xdd, 0xbe, 0x39, 0xb4, 0x82, 0x50, 0xde, 0x33, 0x16, 0x49, 0x85, 0x30, 0x89, 0x33, 0xa6, 0xbd, 0xc8, 0x8e, 0x42, 0xe6, 0xa9, 0x23, 0x6e, 0x62, 0xcd, 0xd2,
0x59, 0x2a, 0xb7, 0xb9, 0xae, 0xc1, 0x55, 0xf8, 0x2a, 0x2c, 0xef, 0xd9, 0xae, 0xe3, 0x0d, 0xcc, 0x6e, 0x89, 0x94, 0x85, 0x4c, 0xdc, 0x15, 0xec, 0xc2, 0x7a, 0x48, 0x07, 0xbe, 0x37, 0x0c, 0xad,
0x91, 0x63, 0x1d, 0x53, 0x3f, 0x90, 0x50, 0x59, 0x78, 0x65, 0x09, 0x16, 0xba, 0xb6, 0x50, 0x09, 0x43, 0x7a, 0xe4, 0x78, 0x43, 0x6b, 0x6c, 0x87, 0x91, 0xbc, 0x8e, 0xac, 0x90, 0x9a, 0x54, 0xee,
0x77, 0x3f, 0x84, 0x8d, 0x99, 0xa3, 0x98, 0x8f, 0x6c, 0x27, 0xa4, 0x3e, 0xed, 0x9b, 0x3e, 0x1d, 0x71, 0x5d, 0x9b, 0xab, 0xf0, 0x0d, 0x58, 0x3b, 0x74, 0x3c, 0xd7, 0x1f, 0x59, 0x13, 0xd7, 0x3e,
0x39, 0x76, 0x4f, 0x5c, 0xf9, 0x8b, 0xbd, 0xfb, 0x0f, 0x67, 0x0c, 0xbd, 0x2b, 0xcd, 0xc9, 0xc4, 0xa3, 0x41, 0x28, 0xa1, 0xb2, 0xf0, 0xca, 0x13, 0x2c, 0x74, 0x5d, 0xa1, 0x12, 0xee, 0xfe, 0x18,
0x9a, 0xb1, 0xdd, 0x1b, 0x8d, 0xcd, 0x31, 0xbf, 0x1a, 0x64, 0xab, 0x98, 0x42, 0x72, 0xbd, 0xd1, 0xb6, 0x17, 0x8e, 0x62, 0x3d, 0x76, 0xdc, 0x88, 0x06, 0x74, 0x68, 0x05, 0x74, 0xe2, 0x3a, 0x03,
0xb8, 0xcb, 0xea, 0x18, 0x41, 0xfa, 0xf1, 0x48, 0x2c, 0x5e, 0x0a, 0x61, 0x45, 0xf5, 0x6b, 0x05, 0xf1, 0x7a, 0x40, 0xec, 0xdd, 0xbf, 0xba, 0x60, 0xe8, 0x03, 0x69, 0x4e, 0x66, 0xd6, 0x8c, 0xed,
0x4a, 0xda, 0x60, 0xe0, 0xd3, 0x81, 0x15, 0x4a, 0x9a, 0xae, 0xc2, 0xb2, 0xa0, 0xe4, 0xd8, 0x94, 0xc1, 0x64, 0x6a, 0x4d, 0xf9, 0x0d, 0x22, 0x5b, 0xc5, 0x14, 0x52, 0x1c, 0x4c, 0xa6, 0x7d, 0x56,
0x6f, 0x89, 0x04, 0x1e, 0x45, 0xe0, 0x91, 0x3a, 0xf1, 0x92, 0x28, 0x0a, 0xdf, 0xf3, 0x63, 0x77, 0xc7, 0x08, 0xb2, 0x4f, 0x26, 0x62, 0xf1, 0x52, 0x08, 0x2b, 0xaa, 0x3f, 0x51, 0xa0, 0xaa, 0x8d,
0x66, 0x9b, 0x14, 0x6f, 0xb3, 0x1c, 0x6b, 0x93, 0xad, 0x7e, 0x01, 0x2e, 0xce, 0x66, 0x61, 0x68, 0x46, 0x01, 0x1d, 0xd9, 0x91, 0xa4, 0xe9, 0x06, 0xac, 0x09, 0x4a, 0xce, 0x2c, 0xf9, 0x2c, 0x49,
0x8b, 0xd7, 0x20, 0x45, 0x72, 0x7e, 0x06, 0xe8, 0x86, 0xed, 0x3e, 0xa7, 0xa9, 0xf5, 0x84, 0xf3, 0xe0, 0x51, 0x04, 0x1e, 0xa9, 0x13, 0x8f, 0x92, 0xe2, 0xf0, 0xbd, 0x3a, 0xf5, 0x16, 0xb6, 0xc9,
0xf5, 0x8c, 0xa6, 0xd6, 0x13, 0xf5, 0xdf, 0xe2, 0xa3, 0xfd, 0x28, 0x5c, 0xe2, 0xd5, 0x38, 0xca, 0xf0, 0x36, 0x6b, 0x89, 0x36, 0xdd, 0xea, 0x17, 0xe1, 0x8d, 0xc5, 0x2c, 0x8c, 0x1d, 0xf1, 0xb0,
0x0b, 0xca, 0xf3, 0xf2, 0x42, 0x05, 0xe6, 0x03, 0xea, 0x1f, 0xda, 0xee, 0x20, 0xba, 0x7b, 0x96, 0xa4, 0x42, 0xae, 0x2e, 0x00, 0xdd, 0x76, 0xbc, 0xe7, 0x34, 0xb5, 0x9f, 0x72, 0xbe, 0x3e, 0xa7,
0x55, 0xdc, 0x81, 0x1f, 0x4a, 0xec, 0xf4, 0x49, 0x48, 0x7d, 0xd7, 0x72, 0x9c, 0x63, 0x53, 0x1c, 0xa9, 0xfd, 0x54, 0xfd, 0xb7, 0xe4, 0x06, 0x20, 0x0e, 0x97, 0x64, 0x35, 0x8e, 0xf3, 0x82, 0xf2,
0x54, 0xb8, 0x21, 0xed, 0x9b, 0x93, 0x97, 0x4f, 0x62, 0x45, 0xfe, 0xbe, 0xb0, 0xd6, 0x63, 0x63, 0xbc, 0xbc, 0x50, 0x87, 0xa5, 0x90, 0x06, 0x27, 0x8e, 0x37, 0x8a, 0xaf, 0xa8, 0x65, 0x15, 0xf7,
0x12, 0xdb, 0x1a, 0xf1, 0x9b, 0xa8, 0xf7, 0xa0, 0xe4, 0xcb, 0x20, 0x36, 0x03, 0xe6, 0x1e, 0x99, 0xe0, 0xab, 0x12, 0x3b, 0x7d, 0x1a, 0xd1, 0xc0, 0xb3, 0x5d, 0xf7, 0xcc, 0x12, 0x07, 0x15, 0x5e,
0x8f, 0x96, 0xe3, 0x0b, 0xe4, 0x44, 0x84, 0x93, 0xa2, 0x3f, 0x15, 0xf0, 0x1f, 0xc0, 0xa2, 0x15, 0x44, 0x87, 0xd6, 0xec, 0x11, 0x95, 0x58, 0x91, 0xbf, 0x2c, 0xac, 0xf5, 0xc4, 0x98, 0x24, 0xb6,
0xf9, 0x56, 0xb6, 0x9e, 0xde, 0xb7, 0x4c, 0x7b, 0x9e, 0x94, 0xac, 0xe9, 0x48, 0xb8, 0x09, 0x0b, 0x66, 0xf2, 0xbc, 0xea, 0x5b, 0x50, 0x0d, 0x64, 0x10, 0x5b, 0x21, 0x73, 0x8f, 0xcc, 0x47, 0x6b,
0x12, 0x91, 0xe5, 0xd8, 0xd6, 0x64, 0x63, 0x7b, 0xe2, 0x39, 0x99, 0xc6, 0x94, 0x44, 0x3e, 0x3c, 0xc9, 0x3d, 0x73, 0x2a, 0xc2, 0x49, 0x25, 0x98, 0x0b, 0xf8, 0xef, 0xc0, 0x8a, 0x1d, 0xfb, 0x56,
0xe3, 0x15, 0xf6, 0x1f, 0x5d, 0xee, 0x8e, 0xfa, 0xbc, 0xa7, 0x33, 0xbc, 0xbb, 0x48, 0xbe, 0x3d, 0xb6, 0x9e, 0xdf, 0xb7, 0xcc, 0x7b, 0x9e, 0x54, 0xed, 0xf9, 0x48, 0xb8, 0x0d, 0xcb, 0x12, 0x91,
0xcb, 0x4c, 0xbf, 0x3d, 0x9b, 0x7e, 0xcb, 0x96, 0x3d, 0xf1, 0x96, 0x4d, 0xbd, 0x05, 0xcb, 0xd3, 0xed, 0x3a, 0xf6, 0x6c, 0x63, 0x7b, 0xee, 0x65, 0x9a, 0xc6, 0x94, 0x44, 0xbe, 0x61, 0xe3, 0x15,
0xf8, 0x65, 0x94, 0xad, 0x43, 0x96, 0xdf, 0x94, 0x9f, 0x58, 0x46, 0x13, 0x57, 0xe1, 0x44, 0x18, 0xf6, 0x1f, 0x5d, 0xeb, 0x4f, 0x86, 0xbc, 0xa7, 0x4b, 0xbc, 0xbb, 0x48, 0x3f, 0x63, 0xcb, 0xcd,
0xa8, 0x7f, 0xab, 0x40, 0x79, 0xc6, 0x2f, 0x56, 0xfc, 0xff, 0xa6, 0x24, 0x8e, 0x87, 0x7e, 0x0e, 0x3f, 0x63, 0x9b, 0x7f, 0x16, 0x97, 0x3f, 0xf7, 0x2c, 0x4e, 0xbd, 0x03, 0x6b, 0xf3, 0xf8, 0x65,
0xb2, 0xfc, 0xce, 0x5e, 0x3e, 0x45, 0xb9, 0x70, 0xfa, 0x0f, 0x8d, 0xdf, 0xaf, 0x13, 0x61, 0xc5, 0x94, 0x6d, 0x41, 0x9e, 0x5f, 0xa8, 0x9f, 0x5b, 0x46, 0x53, 0x37, 0xe6, 0x44, 0x18, 0xa8, 0x7f,
0x12, 0x21, 0x0f, 0xa8, 0x1e, 0x3f, 0x1f, 0x8a, 0x76, 0x88, 0x05, 0x26, 0x13, 0x47, 0x46, 0xa7, 0xa3, 0x40, 0x6d, 0xc1, 0x2f, 0x56, 0xf2, 0xff, 0xa6, 0xa4, 0x8e, 0x87, 0x7e, 0x1e, 0xf2, 0xfc,
0x0f, 0x9c, 0x32, 0x2f, 0x3c, 0x70, 0xda, 0xf8, 0xc3, 0x34, 0xe4, 0x1b, 0xc7, 0x9d, 0xc7, 0xce, 0x6a, 0x5f, 0xbe, 0x58, 0xb9, 0x76, 0xf1, 0x0f, 0x8d, 0x5f, 0xc3, 0x13, 0x61, 0xc5, 0x12, 0x21,
0xae, 0x63, 0x0d, 0xf8, 0x05, 0x78, 0xa3, 0x6d, 0x3c, 0x40, 0xe7, 0xf0, 0x12, 0x14, 0x9b, 0x2d, 0x0f, 0xa8, 0x01, 0x3f, 0x1f, 0x8a, 0x77, 0x88, 0x65, 0x26, 0x13, 0x47, 0x46, 0x17, 0x0f, 0x9c,
0xc3, 0x6c, 0xb2, 0xa5, 0x64, 0xb7, 0xae, 0xdd, 0x46, 0x0a, 0x5b, 0x6b, 0xda, 0xa4, 0x66, 0xde, 0x72, 0x2f, 0x3c, 0x70, 0xda, 0xfe, 0xc3, 0x2c, 0x94, 0xda, 0x67, 0xbd, 0x27, 0xee, 0x81, 0x6b,
0xd1, 0x1f, 0x08, 0x49, 0x0a, 0x97, 0x61, 0xb1, 0xdb, 0xac, 0xdd, 0xed, 0xea, 0x13, 0x61, 0x06, 0x8f, 0xf8, 0x3d, 0x79, 0xbb, 0x6b, 0x3e, 0x42, 0x57, 0xf0, 0x2a, 0x54, 0x8c, 0x8e, 0x69, 0x19,
0xaf, 0xc0, 0x52, 0xa3, 0x5b, 0x37, 0x6a, 0xed, 0x7a, 0x42, 0x9c, 0x63, 0xeb, 0xd2, 0x76, 0xbd, 0x6c, 0x29, 0x39, 0x68, 0x69, 0x77, 0x91, 0xc2, 0xd6, 0x9a, 0x2e, 0x69, 0x5a, 0xf7, 0xf4, 0x47,
0xb5, 0x2d, 0xaa, 0x88, 0xf5, 0xdf, 0x6d, 0x76, 0x6a, 0xb7, 0x9b, 0xfa, 0x8e, 0x10, 0xad, 0x31, 0x42, 0x92, 0xc1, 0x35, 0x58, 0xe9, 0x1b, 0xcd, 0xfb, 0x7d, 0x7d, 0x26, 0xcc, 0xe1, 0x75, 0x58,
0xd1, 0x43, 0x9d, 0xb4, 0x76, 0x6b, 0xd1, 0x90, 0xb7, 0x30, 0x82, 0xc2, 0x76, 0xad, 0xa9, 0x11, 0x6d, 0xf7, 0x5b, 0x66, 0xb3, 0xdb, 0x4a, 0x89, 0x8b, 0x6c, 0x5d, 0xda, 0x6b, 0x75, 0xf6, 0x44,
0xd9, 0xcb, 0x53, 0x05, 0x97, 0x20, 0xaf, 0x37, 0xbb, 0x0d, 0x59, 0x4f, 0xe1, 0x0a, 0x94, 0xb5, 0x15, 0xb1, 0xfe, 0xfb, 0x46, 0xaf, 0x79, 0xd7, 0xd0, 0xf7, 0x85, 0x68, 0x93, 0x89, 0x3e, 0xd6,
0xae, 0xd1, 0x32, 0x6b, 0xcd, 0x2a, 0xd1, 0x1b, 0x7a, 0xd3, 0x90, 0x9a, 0x0c, 0x2e, 0x43, 0xc9, 0x49, 0xe7, 0xa0, 0x19, 0x0f, 0x79, 0x07, 0x23, 0x28, 0xef, 0x35, 0x0d, 0x8d, 0xc8, 0x5e, 0x9e,
0xa8, 0x35, 0xf4, 0x8e, 0xa1, 0x35, 0xda, 0x52, 0xc8, 0x66, 0x91, 0xeb, 0xe8, 0x91, 0x0d, 0xc2, 0x29, 0xb8, 0x0a, 0x25, 0xdd, 0xe8, 0xb7, 0x65, 0x3d, 0x83, 0xeb, 0x50, 0xd3, 0xfa, 0x66, 0xc7,
0xab, 0xb0, 0xd2, 0x6c, 0x99, 0xf2, 0x49, 0x92, 0x79, 0x4f, 0xab, 0x77, 0x75, 0xa9, 0x5b, 0xc3, 0x6a, 0x1a, 0x0d, 0xa2, 0xb7, 0x75, 0xc3, 0x94, 0x9a, 0x1c, 0xae, 0x41, 0xd5, 0x6c, 0xb6, 0xf5,
0x17, 0x00, 0xb7, 0x9a, 0x66, 0xb7, 0xbd, 0xa3, 0x19, 0xba, 0xd9, 0x6c, 0xdd, 0x97, 0x8a, 0x5b, 0x9e, 0xa9, 0xb5, 0xbb, 0x52, 0xc8, 0x66, 0x51, 0xec, 0xe9, 0xb1, 0x0d, 0xc2, 0x1b, 0xb0, 0x6e,
0xb8, 0x04, 0xb9, 0xc9, 0x0c, 0x9e, 0x32, 0x16, 0x8a, 0x6d, 0x8d, 0x18, 0x13, 0xb0, 0x4f, 0x9f, 0x74, 0x2c, 0xf9, 0xb8, 0xc9, 0x7a, 0xa0, 0xb5, 0xfa, 0xba, 0xd4, 0x6d, 0xe2, 0x6b, 0x80, 0x3b,
0x32, 0xb2, 0xe0, 0x36, 0x69, 0x75, 0xdb, 0x13, 0xb3, 0x25, 0x28, 0x48, 0xb2, 0xa4, 0x28, 0xc3, 0x86, 0xd5, 0xef, 0xee, 0x6b, 0xa6, 0x6e, 0x19, 0x9d, 0x87, 0x52, 0x71, 0x07, 0x57, 0xa1, 0x38,
0x44, 0xdb, 0xb5, 0x66, 0x35, 0x9e, 0xdf, 0xd3, 0xdc, 0x6a, 0x0a, 0x29, 0x1b, 0x07, 0x90, 0xe1, 0x9b, 0xc1, 0x33, 0xc6, 0x42, 0xa5, 0xab, 0x11, 0x73, 0x06, 0xf6, 0xd9, 0x33, 0x46, 0x16, 0xdc,
0xee, 0xc8, 0x41, 0xa6, 0xd9, 0x6a, 0xea, 0xe8, 0x1c, 0x5e, 0x04, 0xa8, 0x75, 0x6a, 0x4d, 0x43, 0x25, 0x9d, 0x7e, 0x77, 0x66, 0xb6, 0x0a, 0x65, 0x49, 0x96, 0x14, 0xe5, 0x98, 0x68, 0xaf, 0x69,
0xbf, 0x4d, 0xb4, 0x3a, 0x83, 0xcd, 0x05, 0x11, 0x81, 0x0c, 0xed, 0x02, 0xcc, 0xd7, 0x3a, 0xbb, 0x34, 0x92, 0xf9, 0x3d, 0x2b, 0x6e, 0x64, 0x90, 0xb2, 0x7d, 0x0c, 0x39, 0xee, 0x8e, 0x22, 0xe4,
0xf5, 0x96, 0x66, 0x48, 0x98, 0xb5, 0xce, 0xdd, 0x6e, 0xcb, 0x60, 0x4a, 0x84, 0x0b, 0x30, 0x57, 0x8c, 0x8e, 0xa1, 0xa3, 0x2b, 0x78, 0x05, 0xa0, 0xd9, 0x6b, 0x1a, 0xa6, 0x7e, 0x97, 0x68, 0x2d,
0xeb, 0x18, 0xfa, 0xc7, 0x06, 0xc3, 0xc5, 0x75, 0x82, 0x55, 0xf4, 0xf4, 0xd6, 0xc6, 0x97, 0x69, 0x06, 0x9b, 0x0b, 0x62, 0x02, 0x19, 0xda, 0x65, 0x58, 0x6a, 0xf6, 0x0e, 0x5a, 0x1d, 0xcd, 0x94,
0xc8, 0xf0, 0xf7, 0xa4, 0x45, 0xc8, 0x73, 0x6f, 0x1b, 0x0f, 0xda, 0x6c, 0xc8, 0x3c, 0x64, 0x6a, 0x30, 0x9b, 0xbd, 0xfb, 0xfd, 0x8e, 0xc9, 0x94, 0x08, 0x97, 0xa1, 0xd0, 0xec, 0x99, 0xfa, 0xf7,
0x4d, 0xe3, 0x26, 0xfa, 0xe5, 0x14, 0x06, 0xc8, 0x76, 0x79, 0xf9, 0x57, 0xe6, 0x58, 0xb9, 0xd6, 0x4c, 0x86, 0x8b, 0xeb, 0x04, 0xab, 0xe8, 0xd9, 0x9d, 0xed, 0x1f, 0x67, 0x21, 0xc7, 0x9f, 0xa6,
0x34, 0xde, 0xbe, 0x81, 0x3e, 0x4d, 0xb1, 0x6e, 0xbb, 0xa2, 0xf2, 0xab, 0x91, 0x62, 0xeb, 0x3a, 0x56, 0xa0, 0xc4, 0xbd, 0x6d, 0x3e, 0xea, 0xb2, 0x21, 0x4b, 0x90, 0x6b, 0x1a, 0xe6, 0x6d, 0xf4,
0xfa, 0x2c, 0x56, 0x6c, 0x5d, 0x47, 0xbf, 0x16, 0x29, 0xae, 0x6d, 0xa1, 0x5f, 0x8f, 0x15, 0xd7, 0x2b, 0x19, 0x0c, 0x90, 0xef, 0xf3, 0xf2, 0xaf, 0x16, 0x58, 0xb9, 0x69, 0x98, 0xef, 0xdf, 0x42,
0xb6, 0xd0, 0x6f, 0x44, 0x8a, 0x1b, 0xd7, 0xd1, 0x6f, 0xc6, 0x8a, 0x1b, 0xd7, 0xd1, 0x6f, 0xcd, 0x3f, 0xc8, 0xb0, 0x6e, 0xfb, 0xa2, 0xf2, 0x6b, 0xb1, 0x62, 0xf7, 0x26, 0xfa, 0x61, 0xa2, 0xd8,
0x31, 0x2c, 0x1c, 0xc9, 0xb5, 0x2d, 0xf4, 0xdb, 0xb9, 0xb8, 0x76, 0xe3, 0x3a, 0xfa, 0x9d, 0x1c, 0xbd, 0x89, 0x7e, 0x3d, 0x56, 0x7c, 0xb0, 0x8b, 0x7e, 0x23, 0x51, 0x7c, 0xb0, 0x8b, 0x7e, 0x33,
0xf3, 0x7f, 0xec, 0x55, 0xf4, 0xbb, 0x88, 0x4d, 0x93, 0x39, 0x08, 0xfd, 0x1e, 0x2f, 0x32, 0x15, 0x56, 0xdc, 0xba, 0x89, 0x7e, 0x2b, 0x51, 0xdc, 0xba, 0x89, 0x7e, 0xbb, 0xc0, 0xb0, 0x70, 0x24,
0xfa, 0x7d, 0xc4, 0x30, 0x32, 0x29, 0xaf, 0x7e, 0xce, 0x35, 0x0f, 0x74, 0x8d, 0xa0, 0x3f, 0x98, 0x1f, 0xec, 0xa2, 0xdf, 0x29, 0x26, 0xb5, 0x5b, 0x37, 0xd1, 0xef, 0x16, 0x99, 0xff, 0x13, 0xaf,
0x13, 0x2f, 0xd0, 0xaa, 0xb5, 0x86, 0x56, 0x47, 0x98, 0xb7, 0x60, 0xac, 0xfc, 0xd1, 0x55, 0x56, 0xa2, 0xdf, 0x43, 0x6c, 0x9a, 0xcc, 0x41, 0xe8, 0xf7, 0x79, 0x91, 0xa9, 0xd0, 0x8f, 0x10, 0xc3,
0x64, 0xe1, 0x89, 0xfe, 0xb8, 0xcd, 0x06, 0xbc, 0xa7, 0x91, 0xea, 0x87, 0x1a, 0x41, 0x7f, 0x72, 0xc8, 0xa4, 0xbc, 0xfa, 0x09, 0xd7, 0x3c, 0xd2, 0x35, 0x82, 0xfe, 0xa0, 0x20, 0xde, 0xb2, 0x35,
0x95, 0x0d, 0x78, 0x4f, 0x23, 0x92, 0xaf, 0x3f, 0x6d, 0x33, 0x43, 0xae, 0xfa, 0xe2, 0x2a, 0x9b, 0x9a, 0x6d, 0xad, 0x85, 0x30, 0x6f, 0xc1, 0x58, 0xf9, 0xa3, 0x1b, 0xac, 0xc8, 0xc2, 0x13, 0xfd,
0xb4, 0x94, 0xff, 0x59, 0x1b, 0xe7, 0x20, 0xbd, 0x5d, 0x33, 0xd0, 0x97, 0x7c, 0x34, 0x16, 0xa2, 0x71, 0x97, 0x0d, 0xf8, 0x40, 0x23, 0x8d, 0x8f, 0x34, 0x82, 0xfe, 0xe4, 0x06, 0x1b, 0xf0, 0x81,
0xe8, 0xcf, 0x11, 0x13, 0x76, 0x74, 0x03, 0xfd, 0x05, 0x13, 0x66, 0x8d, 0x6e, 0xbb, 0xae, 0xa3, 0x46, 0x24, 0x5f, 0x7f, 0xda, 0x65, 0x86, 0x5c, 0xf5, 0xe9, 0x0d, 0x36, 0x69, 0x29, 0xff, 0xb3,
0x37, 0xd8, 0xe4, 0x6e, 0xeb, 0xad, 0x86, 0x6e, 0x90, 0x07, 0xe8, 0x2f, 0xb9, 0xf9, 0x47, 0x9d, 0x2e, 0x2e, 0x42, 0x76, 0xaf, 0x69, 0xa2, 0x1f, 0xf3, 0xd1, 0x58, 0x88, 0xa2, 0x3f, 0x47, 0x4c,
0x56, 0x13, 0x7d, 0x85, 0x70, 0x09, 0x40, 0xff, 0xb8, 0x4d, 0xf4, 0x4e, 0xa7, 0xd6, 0x6a, 0xa2, 0xd8, 0xd3, 0x4d, 0xf4, 0x17, 0x4c, 0x98, 0x37, 0xfb, 0xdd, 0x96, 0x8e, 0xde, 0x62, 0x93, 0xbb,
0xb7, 0x36, 0x76, 0x01, 0x9d, 0x4c, 0x07, 0x0c, 0x40, 0xb7, 0x79, 0xa7, 0xd9, 0xba, 0xdf, 0x44, 0xab, 0x77, 0xda, 0xba, 0x49, 0x1e, 0xa1, 0xbf, 0xe4, 0xe6, 0xdf, 0xed, 0x75, 0x0c, 0xf4, 0x19,
0xe7, 0x58, 0xa5, 0x4d, 0xf4, 0xb6, 0x46, 0x74, 0xa4, 0x60, 0x80, 0x39, 0xf1, 0x3e, 0x0e, 0xa5, 0xc2, 0x55, 0x00, 0xfd, 0x7b, 0x5d, 0xa2, 0xf7, 0x7a, 0xcd, 0x8e, 0x81, 0xde, 0xdd, 0x3e, 0x00,
0xf0, 0x02, 0xe4, 0x48, 0xab, 0x5e, 0xdf, 0xd6, 0xaa, 0x77, 0x50, 0x7a, 0xfb, 0x1d, 0x58, 0xb4, 0x74, 0x3e, 0x1d, 0x30, 0x00, 0x7d, 0xe3, 0x9e, 0xd1, 0x79, 0x68, 0xa0, 0x2b, 0xac, 0xd2, 0x25,
0xbd, 0xcd, 0x43, 0x3b, 0xa4, 0x41, 0x20, 0x5e, 0x2c, 0x3f, 0x54, 0x65, 0xcd, 0xf6, 0xae, 0x88, 0x7a, 0x57, 0x23, 0x3a, 0x52, 0x30, 0x40, 0x41, 0xbc, 0xb4, 0x43, 0x19, 0xbc, 0x0c, 0x45, 0xd2,
0xd2, 0x95, 0x81, 0x77, 0xe5, 0x30, 0xbc, 0xc2, 0xb5, 0x57, 0x78, 0xc6, 0xd8, 0x9b, 0xe3, 0x95, 0x69, 0xb5, 0xf6, 0xb4, 0xc6, 0x3d, 0x94, 0xdd, 0xfb, 0x26, 0xac, 0x38, 0xfe, 0xce, 0x89, 0x13,
0x6b, 0xff, 0x17, 0x00, 0x00, 0xff, 0xff, 0xda, 0x0b, 0x47, 0xfb, 0x0f, 0x2d, 0x00, 0x00, 0xd1, 0x30, 0x14, 0x8f, 0x9f, 0x3f, 0x56, 0x65, 0xcd, 0xf1, 0xaf, 0x8b, 0xd2, 0xf5, 0x91, 0x7f,
0xfd, 0x24, 0xba, 0xce, 0xb5, 0xd7, 0x79, 0xc6, 0x38, 0x2c, 0xf0, 0xca, 0x07, 0xff, 0x1b, 0x00,
0x00, 0xff, 0xff, 0x0e, 0x62, 0xd9, 0x82, 0x5a, 0x2d, 0x00, 0x00,
} }
...@@ -31,6 +31,7 @@ import ( ...@@ -31,6 +31,7 @@ import (
) )
// These constants are used to identify the SQL statement type. // These constants are used to identify the SQL statement type.
// Changing this list will require reviewing all calls to Preview.
const ( const (
StmtSelect = iota StmtSelect = iota
StmtStream StmtStream
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册