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

daily update

  1. update vendor pingcap/parser
  2. Makefile add docker contain stop wait
  3. -report-type=rewrite when syntax error, print error info not empty
上级 b237d5e2
......@@ -169,6 +169,7 @@ release: build
docker:
@echo "\033[92mBuild mysql test enviorment\033[0m"
@docker stop soar-mysql 2>/dev/null || true
@docker wait soar-mysql 2>/dev/null || true
@echo "docker run --name soar-mysql $(MYSQL_RELEASE):$(MYSQL_VERSION)"
@docker run --name soar-mysql --rm -d \
-e MYSQL_ROOT_PASSWORD=1tIsB1g3rt \
......
......@@ -32,7 +32,12 @@ import (
// TiParse TiDB 语法解析
func TiParse(sql, charset, collation string) ([]ast.StmtNode, error) {
p := parser.New()
return p.Parse(sql, charset, collation)
stmt, warn, err := p.Parse(sql, charset, collation)
// TODO: bypass warning info
for _, w := range warn {
common.Log.Warn(w.Error())
}
return stmt, err
}
// PrintPrettyStmtNode 打印TiParse语法树
......
......@@ -185,7 +185,7 @@ func main() {
if syntaxErr != nil {
errContent := fmt.Sprintf("At SQL %d : %v", sqlCounter, syntaxErr)
common.Log.Warning(errContent)
if common.Config.OnlySyntaxCheck {
if common.Config.OnlySyntaxCheck || common.Config.ReportType == "rewrite" {
fmt.Println(errContent)
os.Exit(1)
}
......
......@@ -363,7 +363,30 @@ type IndexOption struct {
// Restore implements Node interface.
func (n *IndexOption) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
hasPrevOption := false
if n.KeyBlockSize > 0 {
ctx.WriteKeyWord("KEY_BLOCK_SIZE")
ctx.WritePlainf("=%d", n.KeyBlockSize)
hasPrevOption = true
}
if n.Tp != model.IndexTypeInvalid {
if hasPrevOption {
ctx.WritePlain(" ")
}
ctx.WriteKeyWord("USING ")
ctx.WritePlain(n.Tp.String())
hasPrevOption = true
}
if n.Comment != "" {
if hasPrevOption {
ctx.WritePlain(" ")
}
ctx.WriteKeyWord("COMMENT ")
ctx.WriteString(n.Comment)
}
return nil
}
// Accept implements Node Accept interface.
......@@ -752,7 +775,18 @@ type DropIndexStmt struct {
// Restore implements Node interface.
func (n *DropIndexStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("DROP INDEX ")
if n.IfExists {
ctx.WriteKeyWord("IF EXISTS ")
}
ctx.WriteName(n.IndexName)
ctx.WriteKeyWord(" ON ")
if err := n.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while add index")
}
return nil
}
// Accept implements Node Accept interface.
......
......@@ -1084,7 +1084,17 @@ type Limit struct {
// Restore implements Node interface.
func (n *Limit) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("LIMIT ")
if n.Offset != nil {
if err := n.Offset.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore Limit.Offset")
}
ctx.WritePlain(",")
}
if err := n.Count.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore Limit.Count")
}
return nil
}
// Accept implements Node Accept interface.
......
......@@ -523,7 +523,15 @@ type DefaultExpr struct {
// Restore implements Node interface.
func (n *DefaultExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("DEFAULT")
if n.Name != nil {
ctx.WritePlain("(")
if err := n.Name.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore DefaultExpr.Name")
}
ctx.WritePlain(")")
}
return nil
}
// Format the ExprNode into a Writer.
......@@ -707,7 +715,20 @@ type IsTruthExpr struct {
// Restore implements Node interface.
func (n *IsTruthExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Trace(err)
}
if n.Not {
ctx.WriteKeyWord(" IS NOT")
} else {
ctx.WriteKeyWord(" IS")
}
if n.True > 0 {
ctx.WriteKeyWord(" TRUE")
} else {
ctx.WriteKeyWord(" FALSE")
}
return nil
}
// Format the ExprNode into a Writer.
......@@ -758,7 +779,21 @@ type PatternLikeExpr struct {
// Restore implements Node interface.
func (n *PatternLikeExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore PatternLikeExpr.Expr")
}
if n.Not {
ctx.WriteKeyWord(" NOT LIKE ")
} else {
ctx.WriteKeyWord(" LIKE ")
}
if err := n.Pattern.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore PatternLikeExpr.Pattern")
}
return nil
}
// Format the ExprNode into a Writer.
......@@ -906,7 +941,21 @@ type PatternRegexpExpr struct {
// Restore implements Node interface.
func (n *PatternRegexpExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore PatternRegexpExpr.Expr")
}
if n.Not {
ctx.WriteKeyWord(" NOT REGEXP ")
} else {
ctx.WriteKeyWord(" REGEXP ")
}
if err := n.Pattern.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore PatternRegexpExpr.Pattern")
}
return nil
}
// Format the ExprNode into a Writer.
......@@ -1025,7 +1074,14 @@ type ValuesExpr struct {
// Restore implements Node interface.
func (n *ValuesExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("VALUES")
ctx.WritePlain("(")
if err := n.Column.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore ValuesExpr.Column")
}
ctx.WritePlain(")")
return nil
}
// Format the ExprNode into a Writer.
......
......@@ -68,7 +68,12 @@ type DropStatsStmt struct {
// Restore implements Node interface.
func (n *DropStatsStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("DROP STATS ")
if err := n.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while add table")
}
return nil
}
// Accept implements Node Accept interface.
......
......@@ -38,6 +38,7 @@ type Scanner struct {
buf bytes.Buffer
errs []error
warns []error
stmtStartPos int
// For scanning such kind of comment: /*! MySQL-specific code */ or /*+ optimizer hint */
......@@ -88,9 +89,9 @@ func (s *optimizerHintScanner) scan() (tok int, pos Pos, lit string) {
return
}
// Errors returns the errors during a scan.
func (s *Scanner) Errors() []error {
return s.errs
// Errors returns the errors and warns during a scan.
func (s *Scanner) Errors() (warns []error, errs []error) {
return s.warns, s.errs
}
// reset resets the sql string to be scanned.
......@@ -98,6 +99,7 @@ func (s *Scanner) reset(sql string) {
s.r = reader{s: sql, p: Pos{Line: 1}}
s.buf.Reset()
s.errs = s.errs[:0]
s.warns = s.warns[:0]
s.stmtStartPos = 0
s.specialComment = nil
}
......
......@@ -2926,6 +2926,8 @@ IndexOptionList:
opt1.Comment = opt2.Comment
} else if opt2.Tp != 0 {
opt1.Tp = opt2.Tp
} else if opt2.KeyBlockSize > 0 {
opt1.KeyBlockSize = opt2.KeyBlockSize
}
$$ = opt1
}
......@@ -2936,8 +2938,7 @@ IndexOption:
"KEY_BLOCK_SIZE" EqOpt LengthNum
{
$$ = &ast.IndexOption{
// TODO bug should be fix here!
// KeyBlockSize: $1.(uint64),
KeyBlockSize: $3.(uint64),
}
}
| IndexType
......@@ -5190,6 +5191,11 @@ TableOptimizerHints:
{
$$ = $2
}
| hintBegin error hintEnd
{
yyerrok()
parser.lastErrorAsWarn()
}
HintTableList:
Identifier
......
......@@ -90,7 +90,7 @@ func New() *Parser {
// Parse parses a query string to raw ast.StmtNode.
// If charset or collation is "", default charset and collation will be used.
func (parser *Parser) Parse(sql, charset, collation string) ([]ast.StmtNode, error) {
func (parser *Parser) Parse(sql, charset, collation string) (stmt []ast.StmtNode, warns []error, err error) {
if charset == "" {
charset = mysql.DefaultCharset
}
......@@ -107,19 +107,33 @@ func (parser *Parser) Parse(sql, charset, collation string) ([]ast.StmtNode, err
l = &parser.lexer
yyParse(l, parser)
if len(l.Errors()) != 0 {
return nil, errors.Trace(l.Errors()[0])
warns, errs := l.Errors()
if len(warns) > 0 {
warns = append([]error(nil), warns...)
} else {
warns = nil
}
if len(errs) != 0 {
return nil, warns, errors.Trace(errs[0])
}
for _, stmt := range parser.result {
ast.SetFlag(stmt)
}
return parser.result, nil
return parser.result, warns, nil
}
func (parser *Parser) lastErrorAsWarn() {
if len(parser.lexer.errs) == 0 {
return
}
parser.lexer.warns = append(parser.lexer.warns, parser.lexer.errs[len(parser.lexer.errs)-1])
parser.lexer.errs = parser.lexer.errs[:len(parser.lexer.errs)-1]
}
// ParseOneStmt parses a query and returns an ast.StmtNode.
// The query must have one statement, otherwise ErrSyntax is returned.
func (parser *Parser) ParseOneStmt(sql, charset, collation string) (ast.StmtNode, error) {
stmts, err := parser.Parse(sql, charset, collation)
stmts, _, err := parser.Parse(sql, charset, collation)
if err != nil {
return nil, errors.Trace(err)
}
......
......@@ -65,8 +65,29 @@ type StatementContext struct {
// mu struct holds variables that change during execution.
mu struct {
sync.Mutex
affectedRows uint64
foundRows uint64
affectedRows uint64
foundRows uint64
/*
following variables are ported from 'COPY_INFO' struct of MySQL server source,
they are used to count rows for INSERT/REPLACE/UPDATE queries:
If a row is inserted then the copied variable is incremented.
If a row is updated by the INSERT ... ON DUPLICATE KEY UPDATE and the
new data differs from the old one then the copied and the updated
variables are incremented.
The touched variable is incremented if a row was touched by the update part
of the INSERT ... ON DUPLICATE KEY UPDATE no matter whether the row
was actually changed or not.
see https://github.com/mysql/mysql-server/blob/d2029238d6d9f648077664e4cdd611e231a6dc14/sql/sql_data_change.h#L60 for more details
*/
records uint64
updated uint64
copied uint64
touched uint64
message string
warnings []SQLWarn
histogramsNotLoad bool
execDetails execdetails.ExecDetails
......@@ -122,6 +143,81 @@ func (sc *StatementContext) AddFoundRows(rows uint64) {
sc.mu.Unlock()
}
// RecordRows is used to generate info message
func (sc *StatementContext) RecordRows() uint64 {
sc.mu.Lock()
rows := sc.mu.records
sc.mu.Unlock()
return rows
}
// AddRecordRows adds record rows.
func (sc *StatementContext) AddRecordRows(rows uint64) {
sc.mu.Lock()
sc.mu.records += rows
sc.mu.Unlock()
}
// UpdatedRows is used to generate info message
func (sc *StatementContext) UpdatedRows() uint64 {
sc.mu.Lock()
rows := sc.mu.updated
sc.mu.Unlock()
return rows
}
// AddUpdatedRows adds updated rows.
func (sc *StatementContext) AddUpdatedRows(rows uint64) {
sc.mu.Lock()
sc.mu.updated += rows
sc.mu.Unlock()
}
// CopiedRows is used to generate info message
func (sc *StatementContext) CopiedRows() uint64 {
sc.mu.Lock()
rows := sc.mu.copied
sc.mu.Unlock()
return rows
}
// AddCopiedRows adds copied rows.
func (sc *StatementContext) AddCopiedRows(rows uint64) {
sc.mu.Lock()
sc.mu.copied += rows
sc.mu.Unlock()
}
// TouchedRows is used to generate info message
func (sc *StatementContext) TouchedRows() uint64 {
sc.mu.Lock()
rows := sc.mu.touched
sc.mu.Unlock()
return rows
}
// AddTouchedRows adds touched rows.
func (sc *StatementContext) AddTouchedRows(rows uint64) {
sc.mu.Lock()
sc.mu.touched += rows
sc.mu.Unlock()
}
// GetMessage returns the extra message of the last executed command, if there is no message, it returns empty string
func (sc *StatementContext) GetMessage() string {
sc.mu.Lock()
msg := sc.mu.message
sc.mu.Unlock()
return msg
}
// SetMessage sets the info message generated by some commands
func (sc *StatementContext) SetMessage(msg string) {
sc.mu.Lock()
sc.mu.message = msg
sc.mu.Unlock()
}
// GetWarnings gets warnings.
func (sc *StatementContext) GetWarnings() []SQLWarn {
sc.mu.Lock()
......@@ -247,6 +343,11 @@ func (sc *StatementContext) ResetForRetry() {
sc.mu.Lock()
sc.mu.affectedRows = 0
sc.mu.foundRows = 0
sc.mu.records = 0
sc.mu.updated = 0
sc.mu.copied = 0
sc.mu.touched = 0
sc.mu.message = ""
sc.mu.warnings = nil
sc.mu.Unlock()
sc.TableIDs = sc.TableIDs[:0]
......
......@@ -105,106 +105,106 @@
"revisionTime": "2018-10-24T15:10:47Z"
},
{
"checksumSHA1": "fjZ4hf54cBBlV260wsAMZJ5T3po=",
"checksumSHA1": "cbEXJvrHC69taa1/5o/VlbkZy/g=",
"path": "github.com/pingcap/parser",
"revision": "deacf026787e7b6867b7083dcc461393ac700224",
"revisionTime": "2018-12-18T07:19:12Z"
"revision": "651ad7108326d8bc3991288d749bb6c778135216",
"revisionTime": "2018-12-21T12:21:43Z"
},
{
"checksumSHA1": "dk8IFRGPUrMidLa7QfmI/prTXTA=",
"checksumSHA1": "9pUt2OvfLX8RpWG8gq4efJ33eQw=",
"path": "github.com/pingcap/parser/ast",
"revision": "deacf026787e7b6867b7083dcc461393ac700224",
"revisionTime": "2018-12-18T07:19:12Z"
"revision": "651ad7108326d8bc3991288d749bb6c778135216",
"revisionTime": "2018-12-21T12:21:43Z"
},
{
"checksumSHA1": "skWGV4FNvD3vr+5olepaPPnylUw=",
"path": "github.com/pingcap/parser/auth",
"revision": "deacf026787e7b6867b7083dcc461393ac700224",
"revisionTime": "2018-12-18T07:19:12Z"
"revision": "651ad7108326d8bc3991288d749bb6c778135216",
"revisionTime": "2018-12-21T12:21:43Z"
},
{
"checksumSHA1": "t4UHo966WzU9Z0IJkyGHRp0loOk=",
"path": "github.com/pingcap/parser/charset",
"revision": "deacf026787e7b6867b7083dcc461393ac700224",
"revisionTime": "2018-12-18T07:19:12Z"
"revision": "651ad7108326d8bc3991288d749bb6c778135216",
"revisionTime": "2018-12-21T12:21:43Z"
},
{
"checksumSHA1": "SInoXbsRe0tnBwmatmtZYfSFbdk=",
"path": "github.com/pingcap/parser/format",
"revision": "deacf026787e7b6867b7083dcc461393ac700224",
"revisionTime": "2018-12-18T07:19:12Z"
"revision": "651ad7108326d8bc3991288d749bb6c778135216",
"revisionTime": "2018-12-21T12:21:43Z"
},
{
"checksumSHA1": "WZYTGDMnc1UfTdjdZoBbISsnpRY=",
"path": "github.com/pingcap/parser/model",
"revision": "deacf026787e7b6867b7083dcc461393ac700224",
"revisionTime": "2018-12-18T07:19:12Z"
"revision": "651ad7108326d8bc3991288d749bb6c778135216",
"revisionTime": "2018-12-21T12:21:43Z"
},
{
"checksumSHA1": "QBa9yiMDQNl2cLLwqlRoNTpCPNg=",
"path": "github.com/pingcap/parser/mysql",
"revision": "deacf026787e7b6867b7083dcc461393ac700224",
"revisionTime": "2018-12-18T07:19:12Z"
"revision": "651ad7108326d8bc3991288d749bb6c778135216",
"revisionTime": "2018-12-21T12:21:43Z"
},
{
"checksumSHA1": "+O6CYIE0jT8pIDxWRP9FtKwFZjI=",
"path": "github.com/pingcap/parser/opcode",
"revision": "deacf026787e7b6867b7083dcc461393ac700224",
"revisionTime": "2018-12-18T07:19:12Z"
"revision": "651ad7108326d8bc3991288d749bb6c778135216",
"revisionTime": "2018-12-21T12:21:43Z"
},
{
"checksumSHA1": "XvnUllvwMYd6HrMvMiKnn4cGN2M=",
"path": "github.com/pingcap/parser/terror",
"revision": "deacf026787e7b6867b7083dcc461393ac700224",
"revisionTime": "2018-12-18T07:19:12Z"
"revision": "651ad7108326d8bc3991288d749bb6c778135216",
"revisionTime": "2018-12-21T12:21:43Z"
},
{
"checksumSHA1": "YoDiJ3sniNqxkP5X/BDkx6efteA=",
"path": "github.com/pingcap/parser/types",
"revision": "deacf026787e7b6867b7083dcc461393ac700224",
"revisionTime": "2018-12-18T07:19:12Z"
"revision": "651ad7108326d8bc3991288d749bb6c778135216",
"revisionTime": "2018-12-21T12:21:43Z"
},
{
"checksumSHA1": "fWqL/7jTYOiqDNmiUcQi3u45Hw0=",
"checksumSHA1": "+0bf1l46m6GG7JtACNufnZG0OUw=",
"path": "github.com/pingcap/tidb/sessionctx/stmtctx",
"revision": "4899ce5e923b5833cc684ea8d301f73773718330",
"revisionTime": "2018-12-18T06:47:23Z"
"revision": "20a468d558505d4643ce38fa59fa7884099b5a08",
"revisionTime": "2018-12-21T11:27:58Z"
},
{
"checksumSHA1": "kXyszfR2fQ6bHvuCCFlHRkt1mF0=",
"path": "github.com/pingcap/tidb/types",
"revision": "4899ce5e923b5833cc684ea8d301f73773718330",
"revisionTime": "2018-12-18T06:47:23Z"
"revision": "20a468d558505d4643ce38fa59fa7884099b5a08",
"revisionTime": "2018-12-21T11:27:58Z"
},
{
"checksumSHA1": "DWVD7+ygtT66IQ+cqXmMJ5OVqUk=",
"path": "github.com/pingcap/tidb/types/json",
"revision": "4899ce5e923b5833cc684ea8d301f73773718330",
"revisionTime": "2018-12-18T06:47:23Z"
"revision": "20a468d558505d4643ce38fa59fa7884099b5a08",
"revisionTime": "2018-12-21T11:27:58Z"
},
{
"checksumSHA1": "6vi/eCZXqNTa5eAUpxDZet4LPlY=",
"path": "github.com/pingcap/tidb/types/parser_driver",
"revision": "4899ce5e923b5833cc684ea8d301f73773718330",
"revisionTime": "2018-12-18T06:47:23Z"
"revision": "20a468d558505d4643ce38fa59fa7884099b5a08",
"revisionTime": "2018-12-21T11:27:58Z"
},
{
"checksumSHA1": "s709bhSrG2Ec35406mGtrySid4s=",
"path": "github.com/pingcap/tidb/util/execdetails",
"revision": "4899ce5e923b5833cc684ea8d301f73773718330",
"revisionTime": "2018-12-18T06:47:23Z"
"revision": "20a468d558505d4643ce38fa59fa7884099b5a08",
"revisionTime": "2018-12-21T11:27:58Z"
},
{
"checksumSHA1": "nUC7zVoAMNR2a+z2iGqHoN2AkFE=",
"path": "github.com/pingcap/tidb/util/hack",
"revision": "4899ce5e923b5833cc684ea8d301f73773718330",
"revisionTime": "2018-12-18T06:47:23Z"
"revision": "20a468d558505d4643ce38fa59fa7884099b5a08",
"revisionTime": "2018-12-21T11:27:58Z"
},
{
"checksumSHA1": "xSyepiuqsoaaeDch7cXeumvVHKM=",
"path": "github.com/pingcap/tidb/util/memory",
"revision": "4899ce5e923b5833cc684ea8d301f73773718330",
"revisionTime": "2018-12-18T06:47:23Z"
"revision": "20a468d558505d4643ce38fa59fa7884099b5a08",
"revisionTime": "2018-12-21T11:27:58Z"
},
{
"checksumSHA1": "SmYeIK/fIYXNu8IKxD6HOVQVTuU=",
......@@ -401,62 +401,62 @@
{
"checksumSHA1": "aKn1oKcY74N8TRLm3Ayt7Q4bbI4=",
"path": "vitess.io/vitess/go/bytes2",
"revision": "bbff624145ae9e6c797b2a1b9e04fdddc92af3a9",
"revisionTime": "2018-12-18T04:30:55Z"
"revision": "1cf2530230d76e3bfa1ce99a51163de960ec57e2",
"revisionTime": "2018-12-21T16:58:43Z"
},
{
"checksumSHA1": "JVCEN4UGRmg3TofIBdzZMZ3G0Ww=",
"path": "vitess.io/vitess/go/hack",
"revision": "bbff624145ae9e6c797b2a1b9e04fdddc92af3a9",
"revisionTime": "2018-12-18T04:30:55Z"
"revision": "1cf2530230d76e3bfa1ce99a51163de960ec57e2",
"revisionTime": "2018-12-21T16:58:43Z"
},
{
"checksumSHA1": "F5pcGq+2W1FHEjgktTdKOE6W8mk=",
"path": "vitess.io/vitess/go/sqltypes",
"revision": "bbff624145ae9e6c797b2a1b9e04fdddc92af3a9",
"revisionTime": "2018-12-18T04:30:55Z"
"revision": "1cf2530230d76e3bfa1ce99a51163de960ec57e2",
"revisionTime": "2018-12-21T16:58:43Z"
},
{
"checksumSHA1": "ntFIQYkBS51G6y+FEkjFW40+HOU=",
"path": "vitess.io/vitess/go/vt/log",
"revision": "bbff624145ae9e6c797b2a1b9e04fdddc92af3a9",
"revisionTime": "2018-12-18T04:30:55Z"
"revision": "1cf2530230d76e3bfa1ce99a51163de960ec57e2",
"revisionTime": "2018-12-21T16:58:43Z"
},
{
"checksumSHA1": "tPQFPwbMdjuX0qjNl4Zl8zc37JQ=",
"path": "vitess.io/vitess/go/vt/proto/query",
"revision": "bbff624145ae9e6c797b2a1b9e04fdddc92af3a9",
"revisionTime": "2018-12-18T04:30:55Z"
"revision": "1cf2530230d76e3bfa1ce99a51163de960ec57e2",
"revisionTime": "2018-12-21T16:58:43Z"
},
{
"checksumSHA1": "o0tR/c7lgr0pLkxk7CdvjiNDAKU=",
"path": "vitess.io/vitess/go/vt/proto/topodata",
"revision": "bbff624145ae9e6c797b2a1b9e04fdddc92af3a9",
"revisionTime": "2018-12-18T04:30:55Z"
"revision": "1cf2530230d76e3bfa1ce99a51163de960ec57e2",
"revisionTime": "2018-12-21T16:58:43Z"
},
{
"checksumSHA1": "77UojBqi0yyeQvR70j7C3kcKclQ=",
"path": "vitess.io/vitess/go/vt/proto/vtgate",
"revision": "bbff624145ae9e6c797b2a1b9e04fdddc92af3a9",
"revisionTime": "2018-12-18T04:30:55Z"
"revision": "1cf2530230d76e3bfa1ce99a51163de960ec57e2",
"revisionTime": "2018-12-21T16:58:43Z"
},
{
"checksumSHA1": "QpWGhoVDwM+8+sgYLI/YU+95iGU=",
"path": "vitess.io/vitess/go/vt/proto/vtrpc",
"revision": "bbff624145ae9e6c797b2a1b9e04fdddc92af3a9",
"revisionTime": "2018-12-18T04:30:55Z"
"revision": "1cf2530230d76e3bfa1ce99a51163de960ec57e2",
"revisionTime": "2018-12-21T16:58:43Z"
},
{
"checksumSHA1": "lENrUY/YyxwYFHYN+21TBH92P3U=",
"checksumSHA1": "IDe+9Bn42lZVsuoYO/epdguiErk=",
"path": "vitess.io/vitess/go/vt/sqlparser",
"revision": "bbff624145ae9e6c797b2a1b9e04fdddc92af3a9",
"revisionTime": "2018-12-18T04:30:55Z"
"revision": "1cf2530230d76e3bfa1ce99a51163de960ec57e2",
"revisionTime": "2018-12-21T16:58:43Z"
},
{
"checksumSHA1": "Jx+gOh/kiBDSZxEIWHyYn9brjdo=",
"path": "vitess.io/vitess/go/vt/vterrors",
"revision": "bbff624145ae9e6c797b2a1b9e04fdddc92af3a9",
"revisionTime": "2018-12-18T04:30:55Z"
"revision": "1cf2530230d76e3bfa1ce99a51163de960ec57e2",
"revisionTime": "2018-12-21T16:58:43Z"
}
],
"rootPath": "github.com/XiaoMi/soar"
......
......@@ -3691,7 +3691,7 @@ mustEscape:
}
func compliantName(in string) string {
var buf bytes.Buffer
var buf strings.Builder
for i, c := range in {
if !isLetter(uint16(c)) {
if i == 0 || !isDigit(uint16(c)) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册