Skip to content

Commit

Permalink
Add actual check of --error command not just that an error exists (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
mjonss authored Nov 24, 2023
1 parent 77628a8 commit 17b728e
Show file tree
Hide file tree
Showing 10 changed files with 7,359 additions and 18 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mysql-tester
gen_perror
### STS ###
.apt_generated
.classpath
Expand Down
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ default: build
build:
go build -o mysql-tester ./src

test:
debug:
go build -gcflags="all=-N -l" -o mysql-tester ./src

test: build
go test -cover ./...
#./mysql-tester -check-error

tidy:
go mod tidy
Expand All @@ -15,3 +19,5 @@ clean:
go clean -i ./...
rm -rf mysql-tester

gen_perror: generate_perror/main.go
go build -o gen_perror ./generate_perror
183 changes: 183 additions & 0 deletions generate_perror/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
// Copyright 2023 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
"bufio"
"flag"
"fmt"
"log"
"os"
"os/exec"
"regexp"
"sort"
"strconv"
)

const (
fileHeader = `// Copyright 2023 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
// Generated by generate_perror/main.go
package main
var MysqlErrNameToNum = map[string]int{
`
)

var (
tidbCodePath string
)

func init() {
flag.StringVar(&tidbCodePath, "path", "../tidb", "Path to TiDB source code root directory.")
}

func checkNewErr(errCode string, i int, nameToNum map[string]int) {
if v, ok := nameToNum[errCode]; ok {
if i != v {
if errCode != "handler" {
// Ignore the HA_ERR codes, which are all 'handler'
log.Printf("Duplicate error errCode %s (%d != %d)", errCode, i, v)
}
}
} else {
nameToNum[errCode] = i
}
}

func scanErrCodeFile(fileName string, nameToNum map[string]int) {
f, err := os.Open(fileName)
if err != nil {
log.Fatal(err)
}
defer f.Close()
s := bufio.NewScanner(f)
r := regexp.MustCompile(`^\s+(\w+)*\s+=\s+(\d+)$`)
for s.Scan() {
m := r.FindStringSubmatch(s.Text())
if m != nil && len(m) == 3 && m[1] != "" && m[2] != "" {
i, err := strconv.Atoi(m[2])
if err != nil {
log.Fatal(err)
}
checkNewErr(m[1], i, nameToNum)
}
}
if s.Err() != nil {
log.Fatal(s.Err())
}
}

type ErrorCodeAndName struct {
Code int
Name string
}

func main() {
NameToNum := make(map[string]int)

// First extract the known error names => numbers from TiDB errno module

// Second extract the known error names => numbers from TiDB parser/mysql module

// Last use the perror program to extract error names from 1..20000 from MySQL

flag.Parse()

scanErrCodeFile(filepath.Join(tidbCodePath, "/pkg/errno/errcode.go"), NameToNum)
errnoCodes := len(NameToNum)
log.Printf("Got %d error codes from errno/errcode.go!", errnoCodes)
scanErrCodeFile(tidbCodePath+"/pkg/parser/mysql/errcode.go", NameToNum)
parserCodes := len(NameToNum) - errnoCodes
log.Printf("Got %d New error codes from parser/mysql/errcode.go!", parserCodes)

// similar to:
//seq 1 100000 | xargs perror 2> /dev/null | grep '^MySQL error code MY-[0-9]* ([A-Z_]*).*' | sed 's/^MySQL error code MY-0*\([[:digit:]]*\) (\([^)]*\)).*/"\2": \1,/'
maxError := 20000
log.Printf("Running perror for error codes 1..%d, may take some time...", maxError)
for i := 1; i <= maxError; i++ {
if i%1000 == 0 {
fmt.Printf("\r%d", i)
}
cmd := exec.Command("perror", strconv.Itoa(i))
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Fatal(err)
}
if err = cmd.Start(); err != nil {
log.Fatal(err)
}
s := bufio.NewScanner(stdout)
r := regexp.MustCompile(`^MySQL error code MY-0*(\d+) \((\w+)\)`)
for s.Scan() {
m := r.FindStringSubmatch(s.Text())
if m != nil && len(m) == 3 && m[1] != "" && m[2] != "" {
c, err := strconv.Atoi(m[1])
if err != nil {
log.Fatal(err)
}
if c != i {
log.Fatalf("perror gave error with wrong number? (Want: %d Got: %d)", i, c)
}
checkNewErr(m[2], i, NameToNum)
}
}
cmd.Wait()
}
if maxError >= 1000 {
fmt.Printf("\r")
}
log.Printf("Got %d New error codes from perror!", len(NameToNum)-parserCodes-errnoCodes)
f, err := os.Create("perror.go")
if err != nil {
log.Fatal(err)
}
defer f.Close()
w := bufio.NewWriter(f)
_, err = w.WriteString(fileHeader)

if err != nil {
log.Fatal(err)
}

codes := make([]ErrorCodeAndName, 0, len(NameToNum))
for k, v := range NameToNum {
codes = append(codes, ErrorCodeAndName{Code: v, Name: k})
}
sort.Slice(codes, func(i, j int) bool {
return codes[i].Code < codes[j].Code || codes[i].Code == codes[j].Code && codes[i].Name < codes[j].Name
})
for i, _ := range codes {
_, err = w.WriteString("\t\"" + codes[i].Name + `": ` + strconv.Itoa(codes[i].Code) + ",\n")
if err != nil {
log.Fatal(err)
}
}
_, err = w.WriteString("}\n")
if err != nil {
log.Fatal(err)
}
w.Flush()
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/pingcap/mysql-tester

go 1.19
go 1.21

require (
// It forks from github.com/go-sql-driver/mysql v1.7.1
Expand Down
20 changes: 20 additions & 0 deletions r/example.result
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,25 @@ insert into t values(1, 1), (2, 2), (3, 3), (4, 4), (5, 5);
select * from t where a = 1;
a b
1 1
SELECT 1 FROM NON_EXISTING_TABLE;
Error 1146 (42S02): Table 'example.NON_EXISTING_TABLE' doesn't exist
SELECT 2 FROM NON_EXISTING_TABLE;
SELECT 3 FROM NON_EXISTING_TABLE;
Got one of the listed errors
SELECT 4;
4
4
SELECT 5;
5
5
SELECT 6;
6
6
1 SELECT;
Error 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your TiDB version for the right syntax to use line 1 column 1 near "1 SELECT;"
2 SELECT;
3 SELECT;
Got one of the listed errors
explain analyze format='brief' select * from t;
id estRows actRows task access object execution info operator info memory disk
TableReader 10000.00 5 root NULL time:<num>, loops:<num>, RU:<num>, cop_task: {num:<num>, max:<num>, proc_keys:<num>, rpc_num:<num>, rpc_time:<num>, copr_cache_hit_ratio:<num>, build_task_duration:<num>, max_distsql_concurrency:<num>} data:TableFullScan <num> Bytes N/A
Expand All @@ -26,3 +45,4 @@ info:
INSERT t1 VALUES (1, 1), (1, 1) ON DUPLICATE KEY UPDATE f1 = 2, f2 = 2;
affected rows: 3
info: Records: 2 Duplicates: 1 Warnings: 0
use `test`;;
2 changes: 2 additions & 0 deletions r/extensions.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
SELECT 1 FROM NON_EXISTING_TABLE;
Got one of the listed errors
Loading

0 comments on commit 17b728e

Please sign in to comment.