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

update vendor & add go.mod

上级 ac810d3e
# CHANGELOG
## 2019-02
- add go.mod for go1.11
- add new -report-type query-type
- add new heuristic rule SEC.004
- fix #196 wrong ip/password will cause soar -check-config hangup
## 2019-01
- DOING: english translation
- add mysql environment verbose info
- add JSONFind function, which support JSON iterate
- add new test database `world_x`
......
......@@ -161,7 +161,7 @@ vendor: vitess pingcap-parser
.PHONY: lint
lint: build
@echo "$(CGREEN)Run linter check ...$(CEND)"
CGO_ENABLED=0 retool do gometalinter.v2 -j 1 --config doc/example/metalinter.json ./...
CGO_ENABLED=0 GOMODULE111=off retool do gometalinter.v2 -j 1 --config doc/example/metalinter.json ./...
retool do revive -formatter friendly --exclude vendor/... -config doc/example/revive.toml ./...
retool do golangci-lint --tests=false run
@echo "gometalinter check your code is pretty good"
......
......@@ -92,13 +92,13 @@ func SchemaMetaInfo(sql string, defaultDatabase string) []string {
table := gjson.Get(source, "Name.O")
if database.String() == "" {
if table.String() != "" {
tables = append(tables, fmt.Sprintf("`%s`.`%s`", defaultDatabase, table))
tables = append(tables, fmt.Sprintf("`%s`.`%s`", defaultDatabase, table.String()))
}
} else {
if table.String() != "" {
tables = append(tables, fmt.Sprintf("`%s`.`%s`", database, table))
tables = append(tables, fmt.Sprintf("`%s`.`%s`", database.String(), table.String()))
} else {
tables = append(tables, fmt.Sprintf("`%s`.`dual`", database))
tables = append(tables, fmt.Sprintf("`%s`.`dual`", database.String()))
}
}
}
......@@ -111,11 +111,11 @@ func SchemaMetaInfo(sql string, defaultDatabase string) []string {
tb := gjson.Get(table, "Name.O")
if db.String() == "" {
if tb.String() != "" {
tables = append(tables, fmt.Sprintf("`%s`.%s`", defaultDatabase, tb))
tables = append(tables, fmt.Sprintf("`%s`.%s`", defaultDatabase, tb.String()))
}
} else {
if tb.String() != "" {
tables = append(tables, fmt.Sprintf("`%s`.`%s`", db, tb))
tables = append(tables, fmt.Sprintf("`%s`.`%s`", db.String(), tb.String()))
}
}
}
......
......@@ -17,7 +17,9 @@
"vet"
],
"Exclude": [
"MagicWordSZjYPIDgod1M8XqYEwhsdlzv2SyAtjy8"
"MagicWordSZjYPIDgod1M8XqYEwhsdlzv2SyAtjy8",
"src/internal",
"src/runtime"
],
"Deadline": "5m"
}
module github.com/XiaoMi/soar
require (
github.com/StackExchange/wmi v0.0.0-20180725035823-b12b22c5341f
github.com/astaxie/beego v1.10.1
github.com/cznic/mathutil v0.0.0-20181021201202-eba54fb065b7
github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9
github.com/gedex/inflector v0.0.0-20170307190818-16278e9db813
github.com/go-ole/go-ole v0.0.0-20181122093336-ae2e2a20879a
github.com/go-sql-driver/mysql v0.0.0-20181218123637-c45f530f8e7f
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/golang/protobuf v0.0.0-20181005181728-ddf22928ea3c
github.com/kr/pretty v0.1.0
github.com/kr/text v0.1.0
github.com/percona/go-mysql v0.0.0-20180919090124-fcc026629575
github.com/pingcap/errors v0.11.0
github.com/pingcap/parser v0.0.0-20190219020213-64957c596663
github.com/pingcap/tidb v0.0.0-20190219020246-ed7bb0041703
github.com/pingcap/tipb v0.0.0-20181012112600-11e33c750323
github.com/pkg/errors v0.0.0-20190217225212-856c240a51a2
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446
github.com/russross/blackfriday v1.5.2
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca
github.com/shirou/gopsutil v0.0.0-20181121111905-852c7686b5e5
github.com/sirupsen/logrus v0.0.0-20180908091816-f3df9aeffda7
github.com/tidwall/gjson v1.1.3
github.com/tidwall/match v1.0.0
github.com/ziutek/mymysql v0.0.0-20180827085628-6b05b0cf718f
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16
golang.org/x/net v0.0.0-20181101160248-e11730110bbd
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33
golang.org/x/text v0.0.0-20181030141323-6f44c5a2ea40
google.golang.org/appengine v1.4.0
google.golang.org/genproto v0.0.0-20181101192439-c830210a61df
google.golang.org/grpc v0.0.0-20181101224342-59a2cfbdf927
gopkg.in/yaml.v2 v2.2.1
vitess.io/vitess v0.0.0-20190218033422-092479406b27
)
......@@ -692,8 +692,9 @@ func (n *CreateTableStmt) Restore(ctx *RestoreCtx) error {
return errors.Annotate(err, "An error occurred while splicing CreateTableStmt ReferTable")
}
}
if lenCols := len(n.Cols); lenCols > 0 {
lenCols := len(n.Cols)
lenConstraints := len(n.Constraints)
if lenCols+lenConstraints > 0 {
ctx.WritePlain("(")
for i, col := range n.Cols {
if i > 0 {
......@@ -1280,6 +1281,9 @@ func (n *TableOption) Restore(ctx *RestoreCtx) error {
}
case TableOptionStatsPersistent:
// TODO: not support
ctx.WriteKeyWord("STATS_PERSISTENT ")
ctx.WritePlain("= ")
ctx.WriteKeyWord("DEFAULT")
ctx.WritePlain(" /* TableOptionStatsPersistent is not supported */ ")
case TableOptionShardRowID:
ctx.WriteKeyWord("SHARD_ROW_ID_BITS ")
......@@ -1287,6 +1291,9 @@ func (n *TableOption) Restore(ctx *RestoreCtx) error {
ctx.WritePlainf("%d", n.UintValue)
case TableOptionPackKeys:
// TODO: not support
ctx.WriteKeyWord("PACK_KEYS ")
ctx.WritePlain("= ")
ctx.WriteKeyWord("DEFAULT")
ctx.WritePlain(" /* TableOptionPackKeys is not supported */ ")
default:
return errors.Errorf("invalid TableOption: %d", n.Tp)
......@@ -1537,6 +1544,9 @@ func (n *AlterTableSpec) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord(n.LockType.String())
case AlterTableAlgorithm:
// TODO: not support
ctx.WriteKeyWord("ALGORITHM ")
ctx.WritePlain("= ")
ctx.WriteKeyWord("DEFAULT")
ctx.WritePlain(" /* AlterTableAlgorithm is not supported */ ")
case AlterTableRenameIndex:
ctx.WriteKeyWord("RENAME INDEX ")
......@@ -1545,6 +1555,7 @@ func (n *AlterTableSpec) Restore(ctx *RestoreCtx) error {
ctx.WriteName(n.ToKey.O)
case AlterTableForce:
// TODO: not support
ctx.WriteKeyWord("FORCE")
ctx.WritePlain(" /* AlterTableForce is not supported */ ")
case AlterTableAddPartitions:
ctx.WriteKeyWord("ADD PARTITION")
......@@ -1758,21 +1769,26 @@ func (n *PartitionOptions) Restore(ctx *RestoreCtx) error {
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 n.Expr != nil {
ctx.WritePlain("(")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore PartitionOptions Expr")
}
if err := col.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while splicing PartitionOptions ColumnName: [%v]", i)
ctx.WritePlain(") ")
}
if len(n.ColumnNames) > 0 {
ctx.WriteKeyWord("COLUMNS")
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)
}
}
ctx.WritePlain(") ")
}
if n.Num > 0 {
ctx.WriteKeyWord("PARTITIONS ")
ctx.WritePlainf("%d", n.Num)
......
......@@ -194,12 +194,24 @@ func (n *TableName) Restore(ctx *RestoreCtx) error {
ctx.WritePlain(".")
}
ctx.WriteName(n.Name.String())
if len(n.PartitionNames) > 0 {
ctx.WriteKeyWord(" PARTITION")
ctx.WritePlain("(")
for i, v := range n.PartitionNames {
if i != 0 {
ctx.WritePlain(", ")
}
ctx.WriteName(v.String())
}
ctx.WritePlain(")")
}
for _, value := range n.IndexHints {
ctx.WritePlain(" ")
if err := value.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing IndexHints")
}
}
return nil
}
......@@ -1249,13 +1261,11 @@ func (n *InsertStmt) Restore(ctx *RestoreCtx) error {
} 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 err := n.Priority.Restore(ctx); err != nil {
return errors.Trace(err)
}
if n.Priority != mysql.NoPriority {
ctx.WritePlain(" ")
}
if n.IgnoreErr {
ctx.WriteKeyWord("IGNORE ")
......@@ -1295,6 +1305,7 @@ func (n *InsertStmt) Restore(ctx *RestoreCtx) error {
}
}
if n.Select != nil {
ctx.WritePlain(" ")
switch v := n.Select.(type) {
case *SelectStmt, *UnionStmt:
if err := v.Restore(ctx); err != nil {
......@@ -1420,9 +1431,11 @@ func (n *DeleteStmt) Restore(ctx *RestoreCtx) error {
ctx.WritePlain("*/ ")
}
switch n.Priority {
case mysql.LowPriority:
ctx.WriteKeyWord("LOW_PRIORITY ")
if err := n.Priority.Restore(ctx); err != nil {
return errors.Trace(err)
}
if n.Priority != mysql.NoPriority {
ctx.WritePlain(" ")
}
if n.Quick {
ctx.WriteKeyWord("QUICK ")
......@@ -1560,9 +1573,11 @@ func (n *UpdateStmt) Restore(ctx *RestoreCtx) error {
ctx.WritePlain("*/ ")
}
switch n.Priority {
case mysql.LowPriority:
ctx.WriteKeyWord("LOW_PRIORITY ")
if err := n.Priority.Restore(ctx); err != nil {
return errors.Trace(err)
}
if n.Priority != mysql.NoPriority {
ctx.WritePlain(" ")
}
if n.IgnoreErr {
ctx.WriteKeyWord("IGNORE ")
......@@ -1757,7 +1772,7 @@ type ShowStmt struct {
User *auth.UserIdentity // Used for show grants/create user.
IfNotExists bool // Used for `show create database if not exists`
// GlobalScope is used by show variables
// GlobalScope is used by `show variables` and `show bindings`
GlobalScope bool
Pattern *PatternLikeExpr
Where ExprNode
......@@ -1915,6 +1930,13 @@ func (n *ShowStmt) Restore(ctx *RestoreCtx) error {
restoreShowDatabaseNameOpt()
case ShowPlugins:
ctx.WriteKeyWord("PLUGINS")
case ShowBindings:
if n.GlobalScope {
ctx.WriteKeyWord("GLOBAL ")
} else {
ctx.WriteKeyWord("SESSION ")
}
ctx.WriteKeyWord("BINDINGS")
default:
return errors.New("Unknown ShowStmt type")
}
......
......@@ -115,7 +115,17 @@ type TraceStmt struct {
// Restore implements Node interface.
func (n *TraceStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("TRACE ")
if n.Format != "json" {
ctx.WriteKeyWord("FORMAT")
ctx.WritePlain(" = ")
ctx.WriteString(n.Format)
ctx.WritePlain(" ")
}
if err := n.Stmt.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore TraceStmt.Stmt")
}
return nil
}
// Accept implements Node Accept interface.
......@@ -505,6 +515,7 @@ const (
FlushTables
FlushPrivileges
FlushStatus
FlushTiDBPlugin
)
// FlushStmt is a statement to flush tables/privileges/optimizer costs and so on.
......@@ -515,6 +526,7 @@ type FlushStmt struct {
NoWriteToBinLog bool
Tables []*TableName // For FlushTableStmt, if Tables is empty, it means flush all tables.
ReadLock bool
Plugins []string
}
// Restore implements Node interface.
......@@ -543,6 +555,16 @@ func (n *FlushStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("PRIVILEGES")
case FlushStatus:
ctx.WriteKeyWord("STATUS")
case FlushTiDBPlugin:
ctx.WriteKeyWord("TIDB PLUGINS")
for i, v := range n.Plugins {
if i == 0 {
ctx.WritePlain(" ")
} else {
ctx.WritePlain(", ")
}
ctx.WritePlain(v)
}
default:
return errors.New("Unsupported type of FlushTables")
}
......@@ -900,7 +922,21 @@ type CreateBindingStmt struct {
}
func (n *CreateBindingStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("CREATE ")
if n.GlobalScope {
ctx.WriteKeyWord("GLOBAL ")
} else {
ctx.WriteKeyWord("SESSION ")
}
ctx.WriteKeyWord("BINDING FOR ")
if err := n.OriginSel.Restore(ctx); err != nil {
return errors.Trace(err)
}
ctx.WriteKeyWord(" USING ")
if err := n.HintedSel.Restore(ctx); err != nil {
return errors.Trace(err)
}
return nil
}
func (n *CreateBindingStmt) Accept(v Visitor) (Node, bool) {
......@@ -1222,9 +1258,7 @@ type PrivElem struct {
func (n *PrivElem) Restore(ctx *RestoreCtx) error {
switch n.Priv {
case 0:
// Do nothing for types that have no effect.
// Actually this should not happen since there is no way to determine its type.
return errors.New("Cannot determine privilege type")
ctx.WritePlain("/* UNSUPPORTED TYPE */")
case mysql.AllPriv:
ctx.WriteKeyWord("ALL")
case mysql.AlterPriv:
......@@ -1264,7 +1298,7 @@ func (n *PrivElem) Restore(ctx *RestoreCtx) error {
case mysql.ShowViewPriv:
ctx.WriteKeyWord("SHOW VIEW")
default:
return errors.New("Unsupported privilege type")
return errors.New("Undefined privilege type")
}
if n.Cols != nil {
ctx.WritePlain(" (")
......@@ -1314,7 +1348,7 @@ func (n ObjectTypeType) Restore(ctx *RestoreCtx) error {
case ObjectTypeNone:
// do nothing
case ObjectTypeTable:
ctx.WriteKeyWord("TABLE ")
ctx.WriteKeyWord("TABLE")
default:
return errors.New("Unsupported object type")
}
......@@ -1386,8 +1420,11 @@ func (n *RevokeStmt) Restore(ctx *RestoreCtx) error {
}
}
ctx.WriteKeyWord(" ON ")
if err := n.ObjectType.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore RevokeStmt.ObjectType")
if n.ObjectType != ObjectTypeNone {
if err := n.ObjectType.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore RevokeStmt.ObjectType")
}
ctx.WritePlain(" ")
}
if err := n.Level.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore RevokeStmt.Level")
......@@ -1436,16 +1473,21 @@ type GrantStmt struct {
func (n *GrantStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("GRANT ")
for i, v := range n.Privs {
if i != 0 {
if i != 0 && v.Priv != 0 {
ctx.WritePlain(", ")
} else if v.Priv == 0 {
ctx.WritePlain(" ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore GrantStmt.Privs[%d]", i)
}
}
ctx.WriteKeyWord(" ON ")
if err := n.ObjectType.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore GrantStmt.ObjectType")
if n.ObjectType != ObjectTypeNone {
if err := n.ObjectType.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore GrantStmt.ObjectType")
}
ctx.WritePlain(" ")
}
if err := n.Level.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore GrantStmt.Level")
......
// Copyright 2019 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 parser
import (
"bytes"
"crypto/sha256"
"fmt"
hash2 "hash"
"strings"
"sync"
"unicode"
)
// DigestHash generates the digest of statements.
// it will generate a hash on normalized form of statement text
// which removes general property of a statement but keeps specific property.
//
// for example: both DigestHash('select 1') and DigestHash('select 2') => e1c71d1661ae46e09b7aaec1c390957f0d6260410df4e4bc71b9c8d681021471
func DigestHash(sql string) (result string) {
d := digesterPool.Get().(*sqlDigester)
result = d.doDigest(sql)
digesterPool.Put(d)
return
}
// Normalize generates the normalized statements.
// it will get normalized form of statement text
// which removes general property of a statement but keeps specific property.
//
// for example: Normalize('select 1 from b where a = 1') => 'select ? from b where a = ?'
func Normalize(sql string) (result string) {
d := digesterPool.Get().(*sqlDigester)
result = d.doDigestText(sql)
digesterPool.Put(d)
return
}
var digesterPool = sync.Pool{
New: func() interface{} {
return &sqlDigester{
lexer: NewScanner(""),
hasher: sha256.New(),
}
},
}
// sqlDigester is used to compute DigestHash or Normalize for sql.
type sqlDigester struct {
buffer bytes.Buffer
lexer *Scanner
hasher hash2.Hash
tokens tokenDeque
}
func (d *sqlDigester) doDigest(sql string) (result string) {
d.normalize(sql)
d.hasher.Write(d.buffer.Bytes())
d.buffer.Reset()
result = fmt.Sprintf("%x", d.hasher.Sum(nil))
d.hasher.Reset()
return
}
func (d *sqlDigester) doDigestText(sql string) (result string) {
d.normalize(sql)
result = string(d.buffer.Bytes())
d.lexer.reset("")
d.buffer.Reset()
return
}
const (
// genericSymbol presents parameter holder ("?") in statement
// it can be any value as long as it is not repeated with other tokens.
genericSymbol = -1
// genericSymbolList presents parameter holder lists ("?, ?, ...") in statement
// it can be any value as long as it is not repeated with other tokens.
genericSymbolList = -2
)
func (d *sqlDigester) normalize(sql string) {
d.lexer.reset(sql)
for {
tok, pos, lit := d.lexer.scan()
if tok == unicode.ReplacementChar && d.lexer.r.eof() {
break
}
if pos.Offset == len(sql) {
break
}
currTok := token{tok, strings.ToLower(lit)}
if d.reduceOptimizerHint(&currTok) {
continue
}
d.reduceLit(&currTok)
d.tokens = append(d.tokens, currTok)
}
d.lexer.reset("")
for i, token := range d.tokens {
d.buffer.WriteString(token.lit)
if i != len(d.tokens)-1 {
d.buffer.WriteRune(' ')
}
}
d.tokens = d.tokens[:0]
}
func (d *sqlDigester) reduceOptimizerHint(tok *token) (reduced bool) {
// ignore /*+..*/
if tok.tok == hintBegin {
for {
tok, _, _ := d.lexer.scan()
if tok == 0 || (tok == unicode.ReplacementChar && d.lexer.r.eof()) {
break
}
if tok == hintEnd {
reduced = true
break
}
}
return
}
// ignore force/use/ignore index(x)
if tok.lit == "index" {
toks := d.tokens.back(1)
if len(toks) > 0 {
switch strings.ToLower(toks[0].lit) {
case "force", "use", "ignore":
for {
tok, _, lit := d.lexer.scan()
if tok == 0 || (tok == unicode.ReplacementChar && d.lexer.r.eof()) {
break
}
if lit == ")" {
reduced = true
d.tokens.popBack(1)
break
}
}
return
}
}
}
// ignore straight_join
if tok.lit == "straight_join" {
tok.lit = "join"
return
}
return
}
func (d *sqlDigester) reduceLit(currTok *token) {
if !d.isLit(*currTok) {
return
}
// count(*) => count(?)
if currTok.lit == "*" {
if d.isStarParam() {
currTok.tok = genericSymbol
currTok.lit = "?"
}
return
}
// "-x" or "+x" => "x"
if d.isPrefixByUnary(currTok.tok) {
d.tokens.popBack(1)
}
// "?, ?, ?, ?" => "..."
last2 := d.tokens.back(2)
if d.isGenericList(last2) {
d.tokens.popBack(2)
currTok.tok = genericSymbolList
currTok.lit = "..."
return
}
// order by n => order by n
if currTok.tok == intLit {
if d.isOrderOrGroupBy() {
return
}
}
// 2 => ?
currTok.tok = genericSymbol
currTok.lit = "?"
return
}
func (d *sqlDigester) isPrefixByUnary(currTok int) (isUnary bool) {
if !d.isNumLit(currTok) {
return
}
last := d.tokens.back(1)
if last == nil {
return
}
// a[0] != '-' and a[0] != '+'
if last[0].lit != "-" && last[0].lit != "+" {
return
}
last2 := d.tokens.back(2)
if last2 == nil {
isUnary = true
return
}
// '(-x' or ',-x' or ',+x' or '--x' or '+-x'
switch last2[0].lit {
case "(", ",", "+", "-", ">=", "is", "<=", "=", "<", ">":
isUnary = true
default:
}
// select -x or select +x
last2Lit := strings.ToLower(last2[0].lit)
if last2Lit == "select" {
isUnary = true
}
return
}
func (d *sqlDigester) isGenericList(last2 []token) (generic bool) {
if len(last2) < 2 {
return false
}
if !d.isComma(last2[1]) {
return false
}
switch last2[0].tok {
case genericSymbol, genericSymbolList:
generic = true
default:
}
return
}
func (d *sqlDigester) isOrderOrGroupBy() (orderOrGroupBy bool) {
var (
last []token
n int
)
// skip number item lists, e.g. "order by 1, 2, 3" should NOT convert to "order by ?, ?, ?"
for n = 2; ; n += 2 {
last = d.tokens.back(n)
if len(last) < 2 {
return false
}
if !d.isComma(last[1]) {
break
}
}
// handle group by number item list surround by "()", e.g. "group by (1, 2)" should not convert to "group by (?, ?)"
if last[1].lit == "(" {
last = d.tokens.back(n + 1)
if len(last) < 2 {
return false
}
}
orderOrGroupBy = (last[0].lit == "order" || last[0].lit == "group") && last[1].lit == "by"
return
}
func (d *sqlDigester) isStarParam() (starParam bool) {
last := d.tokens.back(1)
if last == nil {
starParam = false
return
}
starParam = last[0].lit == "("
return
}
func (d *sqlDigester) isLit(t token) (beLit bool) {
tok := t.tok
if d.isNumLit(tok) || tok == stringLit || tok == bitLit {
beLit = true
} else if t.lit == "*" {
beLit = true
}
return
}
func (d *sqlDigester) isNumLit(tok int) (beNum bool) {
switch tok {
case intLit, decLit, floatLit, hexLit:
beNum = true
default:
}
return
}
func (d *sqlDigester) isComma(tok token) (isComma bool) {
isComma = tok.lit == ","
return
}
type token struct {
tok int
lit string
}
type tokenDeque []token
func (s *tokenDeque) pushBack(t token) {
*s = append(*s, t)
}
func (s *tokenDeque) popBack(n int) (t []token) {
if len(*s) < n {
t = nil
return
}
t = (*s)[len(*s)-n:]
*s = (*s)[:len(*s)-n]
return
}
func (s *tokenDeque) back(n int) (t []token) {
if len(*s)-n < 0 {
return
}
t = (*s)[len(*s)-n:]
return
}
......@@ -9,8 +9,8 @@ require (
github.com/cznic/y v0.0.0-20170802143616-045f81c6662a
github.com/pingcap/check v0.0.0-20190102082844-67f458068fc8
github.com/pingcap/errors v0.11.0
github.com/pingcap/tidb v0.0.0-20190108123336-c68ee7318319
github.com/pingcap/tidb v0.0.0-20190218065808-69472bd1a6e9
github.com/pingcap/tipb v0.0.0-20190107072121-abbec73437b7
github.com/sirupsen/logrus v1.2.0
golang.org/x/text v0.3.0
github.com/sirupsen/logrus v1.3.0
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2
)
......@@ -348,6 +348,7 @@ func startWithDash(s *Scanner) (tok int, pos Pos, lit string) {
return
}
tok = int('-')
lit = "-"
s.r.inc()
return
}
......@@ -638,17 +639,31 @@ func startWithNumber(s *Scanner) (tok int, pos Pos, lit string) {
s.scanOct()
case ch1 == 'x' || ch1 == 'X':
s.r.inc()
p1 := s.r.pos()
s.scanHex()
p2 := s.r.pos()
// 0x, 0x7fz3 are identifier
if p1 == p2 || isDigit(s.r.peek()) {
s.r.incAsLongAs(isIdentChar)
return identifier, pos, s.r.data(&pos)
}
tok = hexLit
case ch1 == 'b':
s.r.inc()
p1 := s.r.pos()
s.scanBit()
p2 := s.r.pos()
// 0b, 0b123, 0b1ab are identifier
if p1 == p2 || isDigit(s.r.peek()) {
s.r.incAsLongAs(isIdentChar)
return identifier, pos, s.r.data(&pos)
}
tok = bitLit
case ch1 == '.':
return s.scanFloat(&pos)
case ch1 == 'B':
tok = unicode.ReplacementChar
return
s.r.incAsLongAs(isIdentChar)
return identifier, pos, s.r.data(&pos)
}
}
......@@ -716,11 +731,17 @@ func (s *Scanner) scanFloat(beg *Pos) (tok int, pos Pos, lit string) {
if ch0 == 'e' || ch0 == 'E' {
s.r.inc()
ch0 = s.r.peek()
if ch0 == '-' || ch0 == '+' {
if ch0 == '-' || ch0 == '+' || isDigit(ch0) {
s.r.inc()
s.scanDigits()
tok = floatLit
} else {
// D1 . D2 e XX when XX is not D3, parse the result to an identifier.
// 9e9e = 9e9(float) + e(identifier)
// 9est = 9est(identifier)
s.r.incAsLongAs(isIdentChar)
tok = identifier
}
s.scanDigits()
tok = floatLit
} else {
tok = decLit
}
......
......@@ -16,6 +16,9 @@ package mysql
import (
"fmt"
"strings"
. "github.com/pingcap/parser/format"
"github.com/pkg/errors"
)
func newInvalidModeErr(s string) error {
......@@ -715,6 +718,23 @@ func Str2Priority(val string) PriorityEnum {
}
}
// Restore implements Node interface.
func (n *PriorityEnum) Restore(ctx *RestoreCtx) error {
switch *n {
case NoPriority:
return nil
case LowPriority:
ctx.WriteKeyWord("LOW_PRIORITY")
case HighPriority:
ctx.WriteKeyWord("HIGH_PRIORITY")
case DelayedPriority:
ctx.WriteKeyWord("DELAYED")
default:
return errors.Errorf("undefined PriorityEnum Type[%d]", *n)
}
return nil
}
// PrimaryKeyName defines primary key name.
const (
PrimaryKeyName = "PRIMARY"
......
......@@ -673,6 +673,7 @@ import (
FieldAsNameOpt "Field alias name opt"
FieldList "field expression list"
FlushOption "Flush option"
PluginNameList "Plugin Name List"
TableRefsClause "Table references clause"
FuncDatetimePrec "Function datetime precision"
GlobalScope "The scope of variable"
......@@ -1745,7 +1746,7 @@ NowSymOptionFraction:
}
| NowSymFunc '(' NUM ')'
{
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP")}
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP"), Args: []ast.ExprNode{ast.NewValueExpr($3)}}
}
/*
......@@ -6255,6 +6256,16 @@ FlushStmt:
$$ = tmp
}
PluginNameList:
Identifier
{
$$ = []string{$1}
}
| PluginNameList ',' Identifier
{
$$ = append($1.([]string), $3)
}
FlushOption:
"PRIVILEGES"
{
......@@ -6268,6 +6279,13 @@ FlushOption:
Tp: ast.FlushStatus,
}
}
| "TIDB" "PLUGINS" PluginNameList
{
$$ = &ast.FlushStmt{
Tp: ast.FlushTiDBPlugin,
Plugins: $3.([]string),
}
}
| TableOrTables TableNameListOpt WithReadLockOpt
{
$$ = &ast.FlushStmt{
......
......@@ -221,7 +221,7 @@ func (ft *FieldType) Restore(ctx *format.RestoreCtx) error {
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:
case mysql.TypeBit, mysql.TypeShort, mysql.TypeTiny, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong, mysql.TypeVarchar, mysql.TypeString, mysql.TypeVarString, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeBlob, mysql.TypeLongBlob, mysql.TypeYear:
if ft.Flen > 0 {
ctx.WritePlainf("(%d)", ft.Flen)
}
......
......@@ -90,7 +90,13 @@ func (n *ValueExpr) Restore(ctx *format.RestoreCtx) error {
ctx.WritePlain(strconv.FormatFloat(n.GetFloat64(), 'e', -1, 32))
case types.KindFloat64:
ctx.WritePlain(strconv.FormatFloat(n.GetFloat64(), 'e', -1, 64))
case types.KindString, types.KindBytes:
case types.KindString:
if n.Type.Charset != "" && n.Type.Charset != mysql.DefaultCharset {
ctx.WritePlain("_")
ctx.WriteKeyWord(n.Type.Charset)
}
ctx.WriteString(n.GetString())
case types.KindBytes:
ctx.WriteString(n.GetString())
case types.KindMysqlDecimal:
ctx.WritePlain(n.GetMysqlDecimal().String())
......
Copyright (c) 2015, Dave Cheney <dave@cheney.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
PKGS := github.com/pkg/errors
SRCDIRS := $(shell go list -f '{{.Dir}}' $(PKGS))
GO := go
check: test vet gofmt misspell unconvert staticcheck ineffassign unparam
test:
$(GO) test $(PKGS)
vet: | test
$(GO) vet $(PKGS)
staticcheck:
$(GO) get honnef.co/go/tools/cmd/staticcheck
staticcheck -checks all $(PKGS)
misspell:
$(GO) get github.com/client9/misspell/cmd/misspell
misspell \
-locale GB \
-error \
*.md *.go
unconvert:
$(GO) get github.com/mdempsky/unconvert
unconvert -v $(PKGS)
ineffassign:
$(GO) get github.com/gordonklaus/ineffassign
find $(SRCDIRS) -name '*.go' | xargs ineffassign
pedantic: check errcheck
unparam:
$(GO) get mvdan.cc/unparam
unparam ./...
errcheck:
$(GO) get github.com/kisielk/errcheck
errcheck $(PKGS)
gofmt:
@echo Checking code is gofmted
@test -z "$(shell gofmt -s -l -d -e $(SRCDIRS) | tee /dev/stderr)"
# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge)
Package errors provides simple error handling primitives.
`go get github.com/pkg/errors`
The traditional error handling idiom in Go is roughly akin to
```go
if err != nil {
return err
}
```
which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error.
## Adding context to an error
The errors.Wrap function returns a new error that adds context to the original error. For example
```go
_, err := ioutil.ReadAll(r)
if err != nil {
return errors.Wrap(err, "read failed")
}
```
## Retrieving the cause of an error
Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`.
```go
type causer interface {
Cause() error
}
```
`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example:
```go
switch err := errors.Cause(err).(type) {
case *MyError:
// handle specifically
default:
// unknown error
}
```
[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors).
## Roadmap
With the upcoming [Go2 error proposals](https://go.googlesource.com/proposal/+/master/design/go2draft.md) this package is moving into maintenance mode. The roadmap for a 1.0 release is as follows:
- 0.9. Remove pre Go 1.9 support, address outstanding pull requests (if possible)
- 1.0. Final release.
## Contributing
Because of the Go2 errors changes, this package is not accepting proposals for new functionality. With that said, we welcome pull requests, bug fixes and issue reports.
Before sending a PR, please discuss your change by raising an issue.
## License
BSD-2-Clause
version: build-{build}.{branch}
clone_folder: C:\gopath\src\github.com\pkg\errors
shallow_clone: true # for startup speed
environment:
GOPATH: C:\gopath
platform:
- x64
# http://www.appveyor.com/docs/installed-software
install:
# some helpful output for debugging builds
- go version
- go env
# pre-installed MinGW at C:\MinGW is 32bit only
# but MSYS2 at C:\msys64 has mingw64
- set PATH=C:\msys64\mingw64\bin;%PATH%
- gcc --version
- g++ --version
build_script:
- go install -v ./...
test_script:
- set PATH=C:\gopath\bin;%PATH%
- go test -v ./...
#artifacts:
# - path: '%GOPATH%\bin\*.exe'
deploy: off
// Package errors provides simple error handling primitives.
//
// The traditional error handling idiom in Go is roughly akin to
//
// if err != nil {
// return err
// }
//
// which when applied recursively up the call stack results in error reports
// without context or debugging information. The errors package allows
// programmers to add context to the failure path in their code in a way
// that does not destroy the original value of the error.
//
// Adding context to an error
//
// The errors.Wrap function returns a new error that adds context to the
// original error by recording a stack trace at the point Wrap is called,
// together with the supplied message. For example
//
// _, err := ioutil.ReadAll(r)
// if err != nil {
// return errors.Wrap(err, "read failed")
// }
//
// If additional control is required, the errors.WithStack and
// errors.WithMessage functions destructure errors.Wrap into its component
// operations: annotating an error with a stack trace and with a message,
// respectively.
//
// Retrieving the cause of an error
//
// Using errors.Wrap constructs a stack of errors, adding context to the
// preceding error. Depending on the nature of the error it may be necessary
// to reverse the operation of errors.Wrap to retrieve the original error
// for inspection. Any error value which implements this interface
//
// type causer interface {
// Cause() error
// }
//
// can be inspected by errors.Cause. errors.Cause will recursively retrieve
// the topmost error that does not implement causer, which is assumed to be
// the original cause. For example:
//
// switch err := errors.Cause(err).(type) {
// case *MyError:
// // handle specifically
// default:
// // unknown error
// }
//
// Although the causer interface is not exported by this package, it is
// considered a part of its stable public interface.
//
// Formatted printing of errors
//
// All error values returned from this package implement fmt.Formatter and can
// be formatted by the fmt package. The following verbs are supported:
//
// %s print the error. If the error has a Cause it will be
// printed recursively.
// %v see %s
// %+v extended format. Each Frame of the error's StackTrace will
// be printed in detail.
//
// Retrieving the stack trace of an error or wrapper
//
// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
// invoked. This information can be retrieved with the following interface:
//
// type stackTracer interface {
// StackTrace() errors.StackTrace
// }
//
// The returned errors.StackTrace type is defined as
//
// type StackTrace []Frame
//
// The Frame type represents a call site in the stack trace. Frame supports
// the fmt.Formatter interface that can be used for printing information about
// the stack trace of this error. For example:
//
// if err, ok := err.(stackTracer); ok {
// for _, f := range err.StackTrace() {
// fmt.Printf("%+s:%d\n", f, f)
// }
// }
//
// Although the stackTracer interface is not exported by this package, it is
// considered a part of its stable public interface.
//
// See the documentation for Frame.Format for more details.
package errors
import (
"fmt"
"io"
)
// New returns an error with the supplied message.
// New also records the stack trace at the point it was called.
func New(message string) error {
return &fundamental{
msg: message,
stack: callers(),
}
}
// Errorf formats according to a format specifier and returns the string
// as a value that satisfies error.
// Errorf also records the stack trace at the point it was called.
func Errorf(format string, args ...interface{}) error {
return &fundamental{
msg: fmt.Sprintf(format, args...),
stack: callers(),
}
}
// fundamental is an error that has a message and a stack, but no caller.
type fundamental struct {
msg string
*stack
}
func (f *fundamental) Error() string { return f.msg }
func (f *fundamental) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
io.WriteString(s, f.msg)
f.stack.Format(s, verb)
return
}
fallthrough
case 's':
io.WriteString(s, f.msg)
case 'q':
fmt.Fprintf(s, "%q", f.msg)
}
}
// WithStack annotates err with a stack trace at the point WithStack was called.
// If err is nil, WithStack returns nil.
func WithStack(err error) error {
if err == nil {
return nil
}
return &withStack{
err,
callers(),
}
}
type withStack struct {
error
*stack
}
func (w *withStack) Cause() error { return w.error }
func (w *withStack) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
fmt.Fprintf(s, "%+v", w.Cause())
w.stack.Format(s, verb)
return
}
fallthrough
case 's':
io.WriteString(s, w.Error())
case 'q':
fmt.Fprintf(s, "%q", w.Error())
}
}
// Wrap returns an error annotating err with a stack trace
// at the point Wrap is called, and the supplied message.
// If err is nil, Wrap returns nil.
func Wrap(err error, message string) error {
if err == nil {
return nil
}
err = &withMessage{
cause: err,
msg: message,
}
return &withStack{
err,
callers(),
}
}
// Wrapf returns an error annotating err with a stack trace
// at the point Wrapf is called, and the format specifier.
// If err is nil, Wrapf returns nil.
func Wrapf(err error, format string, args ...interface{}) error {
if err == nil {
return nil
}
err = &withMessage{
cause: err,
msg: fmt.Sprintf(format, args...),
}
return &withStack{
err,
callers(),
}
}
// WithMessage annotates err with a new message.
// If err is nil, WithMessage returns nil.
func WithMessage(err error, message string) error {
if err == nil {
return nil
}
return &withMessage{
cause: err,
msg: message,
}
}
// WithMessagef annotates err with the format specifier.
// If err is nil, WithMessagef returns nil.
func WithMessagef(err error, format string, args ...interface{}) error {
if err == nil {
return nil
}
return &withMessage{
cause: err,
msg: fmt.Sprintf(format, args...),
}
}
type withMessage struct {
cause error
msg string
}
func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() }
func (w *withMessage) Cause() error { return w.cause }
func (w *withMessage) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
fmt.Fprintf(s, "%+v\n", w.Cause())
io.WriteString(s, w.msg)
return
}
fallthrough
case 's', 'q':
io.WriteString(s, w.Error())
}
}
// Cause returns the underlying cause of the error, if possible.
// An error value has a cause if it implements the following
// interface:
//
// type causer interface {
// Cause() error
// }
//
// If the error does not implement Cause, the original error will
// be returned. If the error is nil, nil will be returned without further
// investigation.
func Cause(err error) error {
type causer interface {
Cause() error
}
for err != nil {
cause, ok := err.(causer)
if !ok {
break
}
err = cause.Cause()
}
return err
}
package errors
import (
"fmt"
"io"
"path"
"runtime"
"strconv"
"strings"
)
// Frame represents a program counter inside a stack frame.
// For historical reasons if Frame is interpreted as a uintptr
// its value represents the program counter + 1.
type Frame uintptr
// pc returns the program counter for this frame;
// multiple frames may have the same PC value.
func (f Frame) pc() uintptr { return uintptr(f) - 1 }
// file returns the full path to the file that contains the
// function for this Frame's pc.
func (f Frame) file() string {
fn := runtime.FuncForPC(f.pc())
if fn == nil {
return "unknown"
}
file, _ := fn.FileLine(f.pc())
return file
}
// line returns the line number of source code of the
// function for this Frame's pc.
func (f Frame) line() int {
fn := runtime.FuncForPC(f.pc())
if fn == nil {
return 0
}
_, line := fn.FileLine(f.pc())
return line
}
// name returns the name of this function, if known.
func (f Frame) name() string {
fn := runtime.FuncForPC(f.pc())
if fn == nil {
return "unknown"
}
return fn.Name()
}
// Format formats the frame according to the fmt.Formatter interface.
//
// %s source file
// %d source line
// %n function name
// %v equivalent to %s:%d
//
// Format accepts flags that alter the printing of some verbs, as follows:
//
// %+s function name and path of source file relative to the compile time
// GOPATH separated by \n\t (<funcname>\n\t<path>)
// %+v equivalent to %+s:%d
func (f Frame) Format(s fmt.State, verb rune) {
switch verb {
case 's':
switch {
case s.Flag('+'):
io.WriteString(s, f.name())
io.WriteString(s, "\n\t")
io.WriteString(s, f.file())
default:
io.WriteString(s, path.Base(f.file()))
}
case 'd':
io.WriteString(s, strconv.Itoa(f.line()))
case 'n':
io.WriteString(s, funcname(f.name()))
case 'v':
f.Format(s, 's')
io.WriteString(s, ":")
f.Format(s, 'd')
}
}
// MarshalText formats a stacktrace Frame as a text string. The output is the
// same as that of fmt.Sprintf("%+v", f), but without newlines or tabs.
func (f Frame) MarshalText() ([]byte, error) {
name := f.name()
if name == "unknown" {
return []byte(name), nil
}
return []byte(fmt.Sprintf("%s %s:%d", name, f.file(), f.line())), nil
}
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
type StackTrace []Frame
// Format formats the stack of Frames according to the fmt.Formatter interface.
//
// %s lists source files for each Frame in the stack
// %v lists the source file and line number for each Frame in the stack
//
// Format accepts flags that alter the printing of some verbs, as follows:
//
// %+v Prints filename, function, and line number for each Frame in the stack.
func (st StackTrace) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
switch {
case s.Flag('+'):
for _, f := range st {
io.WriteString(s, "\n")
f.Format(s, verb)
}
case s.Flag('#'):
fmt.Fprintf(s, "%#v", []Frame(st))
default:
st.formatSlice(s, verb)
}
case 's':
st.formatSlice(s, verb)
}
}
// formatSlice will format this StackTrace into the given buffer as a slice of
// Frame, only valid when called with '%s' or '%v'.
func (st StackTrace) formatSlice(s fmt.State, verb rune) {
io.WriteString(s, "[")
for i, f := range st {
if i > 0 {
io.WriteString(s, " ")
}
f.Format(s, verb)
}
io.WriteString(s, "]")
}
// stack represents a stack of program counters.
type stack []uintptr
func (s *stack) Format(st fmt.State, verb rune) {
switch verb {
case 'v':
switch {
case st.Flag('+'):
for _, pc := range *s {
f := Frame(pc)
fmt.Fprintf(st, "\n%+v", f)
}
}
}
}
func (s *stack) StackTrace() StackTrace {
f := make([]Frame, len(*s))
for i := 0; i < len(f); i++ {
f[i] = Frame((*s)[i])
}
return f
}
func callers() *stack {
const depth = 32
var pcs [depth]uintptr
n := runtime.Callers(3, pcs[:])
var st stack = pcs[0:n]
return &st
}
// funcname removes the path prefix component of a function's name reported by func.Name().
func funcname(name string) string {
i := strings.LastIndex(name, "/")
name = name[i+1:]
i = strings.Index(name, ".")
return name[i+1:]
}
......@@ -111,106 +111,106 @@
"revisionTime": "2018-10-24T15:10:47Z"
},
{
"checksumSHA1": "MZWBKlzvcvOO6ORrDX//cN1qMyw=",
"checksumSHA1": "zdNB/SusrolFBEotWrfqZ08+MCk=",
"path": "github.com/pingcap/parser",
"revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-02-12T07:36:55Z"
"revision": "64957c596663a56fe176881aadea6baa4890f710",
"revisionTime": "2019-02-19T02:02:13Z"
},
{
"checksumSHA1": "qPX1edrnPa/EtgVB8IfB5KStU+U=",
"checksumSHA1": "JdLK0084PE81bjMLcH+qUZFq10M=",
"path": "github.com/pingcap/parser/ast",
"revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-02-12T07:36:55Z"
"revision": "64957c596663a56fe176881aadea6baa4890f710",
"revisionTime": "2019-02-19T02:02:13Z"
},
{
"checksumSHA1": "npMzF75Vg7tO28nM3MNFq7ciqRY=",
"path": "github.com/pingcap/parser/auth",
"revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-02-12T07:36:55Z"
"revision": "64957c596663a56fe176881aadea6baa4890f710",
"revisionTime": "2019-02-19T02:02:13Z"
},
{
"checksumSHA1": "t4UHo966WzU9Z0IJkyGHRp0loOk=",
"path": "github.com/pingcap/parser/charset",
"revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-02-12T07:36:55Z"
"revision": "64957c596663a56fe176881aadea6baa4890f710",
"revisionTime": "2019-02-19T02:02:13Z"
},
{
"checksumSHA1": "ohLJW2u9NJEzYIJL/AjOqcuKfMY=",
"path": "github.com/pingcap/parser/format",
"revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-02-12T07:36:55Z"
"revision": "64957c596663a56fe176881aadea6baa4890f710",
"revisionTime": "2019-02-19T02:02:13Z"
},
{
"checksumSHA1": "AqNgtzIGY8g7Ojd9ofE8EtKW2mk=",
"path": "github.com/pingcap/parser/model",
"revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-02-12T07:36:55Z"
"revision": "64957c596663a56fe176881aadea6baa4890f710",
"revisionTime": "2019-02-19T02:02:13Z"
},
{
"checksumSHA1": "4A/BJa0ZcUlrUay8dYVsweGgnZA=",
"checksumSHA1": "SrliCbNvJrQExC1gULpw7FAiE6s=",
"path": "github.com/pingcap/parser/mysql",
"revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-02-12T07:36:55Z"
"revision": "64957c596663a56fe176881aadea6baa4890f710",
"revisionTime": "2019-02-19T02:02:13Z"
},
{
"checksumSHA1": "olapD16WCMBU9vrA5PtlERGFfXw=",
"path": "github.com/pingcap/parser/opcode",
"revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-02-12T07:36:55Z"
"revision": "64957c596663a56fe176881aadea6baa4890f710",
"revisionTime": "2019-02-19T02:02:13Z"
},
{
"checksumSHA1": "TF2rMYy9ewgZpFsJb+jaGXXqZqc=",
"path": "github.com/pingcap/parser/terror",
"revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-02-12T07:36:55Z"
"revision": "64957c596663a56fe176881aadea6baa4890f710",
"revisionTime": "2019-02-19T02:02:13Z"
},
{
"checksumSHA1": "sCYsaxxXBau10NOc5tuYQEtmAu0=",
"checksumSHA1": "dxjAHfRcmXkQdf0HeueDrUO+BcM=",
"path": "github.com/pingcap/parser/types",
"revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-02-12T07:36:55Z"
"revision": "64957c596663a56fe176881aadea6baa4890f710",
"revisionTime": "2019-02-19T02:02:13Z"
},
{
"checksumSHA1": "uOrWw9c47zwN6COxonFJ0t2IMcM=",
"path": "github.com/pingcap/tidb/sessionctx/stmtctx",
"revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-02-12T09:47:48Z"
"revision": "ed7bb004170311e73664c280e77298760de74425",
"revisionTime": "2019-02-19T02:02:46Z"
},
{
"checksumSHA1": "IJSv0YocnSmIZRpgQJ1pLtHL8vY=",
"path": "github.com/pingcap/tidb/types",
"revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-02-12T09:47:48Z"
"revision": "ed7bb004170311e73664c280e77298760de74425",
"revisionTime": "2019-02-19T02:02:46Z"
},
{
"checksumSHA1": "fPdBwAtPVKOr7YAyOMnRxyHixoM=",
"path": "github.com/pingcap/tidb/types/json",
"revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-02-12T09:47:48Z"
"revision": "ed7bb004170311e73664c280e77298760de74425",
"revisionTime": "2019-02-19T02:02:46Z"
},
{
"checksumSHA1": "yKeU1hJFc7X3afXESYV0Wz5ZPXQ=",
"checksumSHA1": "tY4KSNzuTGm+dgV6ByZEGa6mv5E=",
"path": "github.com/pingcap/tidb/types/parser_driver",
"revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-02-12T09:47:48Z"
"revision": "ed7bb004170311e73664c280e77298760de74425",
"revisionTime": "2019-02-19T02:02:46Z"
},
{
"checksumSHA1": "OOig47D9TSVOUAYkNj2yJok1Hmo=",
"path": "github.com/pingcap/tidb/util/execdetails",
"revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-02-12T09:47:48Z"
"revision": "ed7bb004170311e73664c280e77298760de74425",
"revisionTime": "2019-02-19T02:02:46Z"
},
{
"checksumSHA1": "RdbHgQWMHjRtKjqPcTX81k1V3sw=",
"path": "github.com/pingcap/tidb/util/hack",
"revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-02-12T09:47:48Z"
"revision": "ed7bb004170311e73664c280e77298760de74425",
"revisionTime": "2019-02-19T02:02:46Z"
},
{
"checksumSHA1": "xSyepiuqsoaaeDch7cXeumvVHKM=",
"path": "github.com/pingcap/tidb/util/memory",
"revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-02-12T09:47:48Z"
"revision": "ed7bb004170311e73664c280e77298760de74425",
"revisionTime": "2019-02-19T02:02:46Z"
},
{
"checksumSHA1": "SmYeIK/fIYXNu8IKxD6HOVQVTuU=",
......@@ -224,6 +224,12 @@
"revision": "11e33c750323a0267a6aee335eaaeb7831bdae67",
"revisionTime": "2018-10-12T11:26:00Z"
},
{
"checksumSHA1": "I7hloldMJZTqUx6hbVDp5nk9fZQ=",
"path": "github.com/pkg/errors",
"revision": "856c240a51a2bf8fb8269ea7f3f9b046aadde36e",
"revisionTime": "2019-02-17T22:52:12Z"
},
{
"checksumSHA1": "N4NQU0O2rK3hBtB3nBDHrSzqrbM=",
"path": "github.com/remyoudompheng/bigfft",
......@@ -407,62 +413,62 @@
{
"checksumSHA1": "aKn1oKcY74N8TRLm3Ayt7Q4bbI4=",
"path": "vitess.io/vitess/go/bytes2",
"revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-02-12T02:13:30Z"
"revision": "092479406b27ae61a8fcd146a0e08af2d51a7245",
"revisionTime": "2019-02-18T03:34:22Z"
},
{
"checksumSHA1": "JVCEN4UGRmg3TofIBdzZMZ3G0Ww=",
"checksumSHA1": "bhE6CGQgZTIgLPp9lnvlKW/47xc=",
"path": "vitess.io/vitess/go/hack",
"revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-02-12T02:13:30Z"
"revision": "092479406b27ae61a8fcd146a0e08af2d51a7245",
"revisionTime": "2019-02-18T03:34:22Z"
},
{
"checksumSHA1": "F5pcGq+2W1FHEjgktTdKOE6W8mk=",
"checksumSHA1": "w4BH8HL/CgT6aBWojJeZHOj5DZg=",
"path": "vitess.io/vitess/go/sqltypes",
"revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-02-12T02:13:30Z"
"revision": "092479406b27ae61a8fcd146a0e08af2d51a7245",
"revisionTime": "2019-02-18T03:34:22Z"
},
{
"checksumSHA1": "vAIRxI6MHsq3x1hLQwIyw5AvqtI=",
"path": "vitess.io/vitess/go/vt/log",
"revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-02-12T02:13:30Z"
"revision": "092479406b27ae61a8fcd146a0e08af2d51a7245",
"revisionTime": "2019-02-18T03:34:22Z"
},
{
"checksumSHA1": "quYYG+uo3v5HIKvG4QQtRhLC0HY=",
"checksumSHA1": "nRmynSAD/uvTjH0/Ftr9Iz/VsN4=",
"path": "vitess.io/vitess/go/vt/proto/query",
"revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-02-12T02:13:30Z"
"revision": "092479406b27ae61a8fcd146a0e08af2d51a7245",
"revisionTime": "2019-02-18T03:34:22Z"
},
{
"checksumSHA1": "YLWTmL+rvz0htn0niRMrIUI6rKc=",
"path": "vitess.io/vitess/go/vt/proto/topodata",
"revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-02-12T02:13:30Z"
"revision": "092479406b27ae61a8fcd146a0e08af2d51a7245",
"revisionTime": "2019-02-18T03:34:22Z"
},
{
"checksumSHA1": "1gA4wbQ2DiVjeLJauYSQiuBJiE0=",
"path": "vitess.io/vitess/go/vt/proto/vtgate",
"revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-02-12T02:13:30Z"
"revision": "092479406b27ae61a8fcd146a0e08af2d51a7245",
"revisionTime": "2019-02-18T03:34:22Z"
},
{
"checksumSHA1": "qz32abYdmm9NfKTc++K0l1EvXXM=",
"path": "vitess.io/vitess/go/vt/proto/vtrpc",
"revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-02-12T02:13:30Z"
"revision": "092479406b27ae61a8fcd146a0e08af2d51a7245",
"revisionTime": "2019-02-18T03:34:22Z"
},
{
"checksumSHA1": "O/ukE4Sl85Une3Km+fk0zWdaw1k=",
"checksumSHA1": "lpx8L51nDqrhQis64dEBk7RI32k=",
"path": "vitess.io/vitess/go/vt/sqlparser",
"revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-02-12T02:13:30Z"
"revision": "092479406b27ae61a8fcd146a0e08af2d51a7245",
"revisionTime": "2019-02-18T03:34:22Z"
},
{
"checksumSHA1": "Jx+gOh/kiBDSZxEIWHyYn9brjdo=",
"path": "vitess.io/vitess/go/vt/vterrors",
"revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-02-12T02:13:30Z"
"revision": "092479406b27ae61a8fcd146a0e08af2d51a7245",
"revisionTime": "2019-02-18T03:34:22Z"
}
],
"rootPath": "github.com/XiaoMi/soar"
......
......@@ -23,53 +23,13 @@ import (
"unsafe"
)
// StringArena lets you consolidate allocations for a group of strings
// that have similar life length
type StringArena struct {
buf []byte
str string
}
// NewStringArena creates an arena of the specified size.
func NewStringArena(size int) *StringArena {
sa := &StringArena{buf: make([]byte, 0, size)}
pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&sa.buf))
pstring := (*reflect.StringHeader)(unsafe.Pointer(&sa.str))
pstring.Data = pbytes.Data
pstring.Len = pbytes.Cap
return sa
}
// NewString copies a byte slice into the arena and returns it as a string.
// If the arena is full, it returns a traditional go string.
func (sa *StringArena) NewString(b []byte) string {
if len(b) == 0 {
return ""
}
if len(sa.buf)+len(b) > cap(sa.buf) {
return string(b)
}
start := len(sa.buf)
sa.buf = append(sa.buf, b...)
return sa.str[start : start+len(b)]
}
// SpaceLeft returns the amount of space left in the arena.
func (sa *StringArena) SpaceLeft() int {
return cap(sa.buf) - len(sa.buf)
}
// String force casts a []byte to a string.
// USE AT YOUR OWN RISK
func String(b []byte) (s string) {
if len(b) == 0 {
return ""
}
pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&b))
pstring := (*reflect.StringHeader)(unsafe.Pointer(&s))
pstring.Data = pbytes.Data
pstring.Len = pbytes.Len
return
return *(*string)(unsafe.Pointer(&b))
}
// StringPointer returns &s[0], which is not allowed in go
......
......@@ -16,7 +16,9 @@ limitations under the License.
package sqltypes
import querypb "vitess.io/vitess/go/vt/proto/query"
import (
querypb "vitess.io/vitess/go/vt/proto/query"
)
// EventTokenMinimum returns an event token that is guaranteed to
// happen before both provided EventToken objects. Note it doesn't
......
......@@ -854,7 +854,7 @@ type ExecuteOptions struct {
// vitess also sets a rowcount limit on queries, the smallest value wins.
SqlSelectLimit int64 `protobuf:"varint,8,opt,name=sql_select_limit,json=sqlSelectLimit,proto3" json:"sql_select_limit,omitempty"`
TransactionIsolation ExecuteOptions_TransactionIsolation `protobuf:"varint,9,opt,name=transaction_isolation,json=transactionIsolation,proto3,enum=query.ExecuteOptions_TransactionIsolation" json:"transaction_isolation,omitempty"`
// skip_query_plan_cache specifies if the query plan shoud be cached by vitess.
// skip_query_plan_cache specifies if the query plan should be cached by vitess.
// By default all query plans are cached.
SkipQueryPlanCache bool `protobuf:"varint,10,opt,name=skip_query_plan_cache,json=skipQueryPlanCache,proto3" json:"skip_query_plan_cache,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
......
......@@ -17,7 +17,6 @@ limitations under the License.
package sqlparser
import (
"bytes"
"encoding/hex"
"encoding/json"
"errors"
......@@ -265,9 +264,9 @@ func String(node SQLNode) string {
}
// Append appends the SQLNode to the buffer.
func Append(buf *bytes.Buffer, node SQLNode) {
func Append(buf *strings.Builder, node SQLNode) {
tbuf := &TrackedBuffer{
Buffer: buf,
Builder: buf,
}
node.Format(tbuf)
}
......
......@@ -17,7 +17,7 @@ limitations under the License.
package sqlparser
import (
"bytes"
"strings"
"vitess.io/vitess/go/sqltypes"
)
......@@ -27,7 +27,7 @@ import (
// Encodable defines the interface for types that can
// be custom-encoded into SQL.
type Encodable interface {
EncodeSQL(buf *bytes.Buffer)
EncodeSQL(buf *strings.Builder)
}
// InsertValues is a custom SQL encoder for the values of
......@@ -35,7 +35,7 @@ type Encodable interface {
type InsertValues [][]sqltypes.Value
// EncodeSQL performs the SQL encoding for InsertValues.
func (iv InsertValues) EncodeSQL(buf *bytes.Buffer) {
func (iv InsertValues) EncodeSQL(buf *strings.Builder) {
for i, rows := range iv {
if i != 0 {
buf.WriteString(", ")
......@@ -60,7 +60,7 @@ type TupleEqualityList struct {
// EncodeSQL generates the where clause constraints for the tuple
// equality.
func (tpl *TupleEqualityList) EncodeSQL(buf *bytes.Buffer) {
func (tpl *TupleEqualityList) EncodeSQL(buf *strings.Builder) {
if len(tpl.Columns) == 1 {
tpl.encodeAsIn(buf)
return
......@@ -68,7 +68,7 @@ func (tpl *TupleEqualityList) EncodeSQL(buf *bytes.Buffer) {
tpl.encodeAsEquality(buf)
}
func (tpl *TupleEqualityList) encodeAsIn(buf *bytes.Buffer) {
func (tpl *TupleEqualityList) encodeAsIn(buf *strings.Builder) {
Append(buf, tpl.Columns[0])
buf.WriteString(" in (")
for i, r := range tpl.Rows {
......@@ -80,7 +80,7 @@ func (tpl *TupleEqualityList) encodeAsIn(buf *bytes.Buffer) {
buf.WriteByte(')')
}
func (tpl *TupleEqualityList) encodeAsEquality(buf *bytes.Buffer) {
func (tpl *TupleEqualityList) encodeAsEquality(buf *strings.Builder) {
for i, r := range tpl.Rows {
if i != 0 {
buf.WriteString(" or ")
......
......@@ -17,9 +17,9 @@ limitations under the License.
package sqlparser
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"vitess.io/vitess/go/sqltypes"
......@@ -47,28 +47,29 @@ func NewParsedQuery(node SQLNode) *ParsedQuery {
// GenerateQuery generates a query by substituting the specified
// bindVariables. The extras parameter specifies special parameters
// that can perform custom encoding.
func (pq *ParsedQuery) GenerateQuery(bindVariables map[string]*querypb.BindVariable, extras map[string]Encodable) ([]byte, error) {
func (pq *ParsedQuery) GenerateQuery(bindVariables map[string]*querypb.BindVariable, extras map[string]Encodable) (string, error) {
if len(pq.bindLocations) == 0 {
return []byte(pq.Query), nil
return pq.Query, nil
}
buf := bytes.NewBuffer(make([]byte, 0, len(pq.Query)))
var buf strings.Builder
buf.Grow(len(pq.Query))
current := 0
for _, loc := range pq.bindLocations {
buf.WriteString(pq.Query[current:loc.offset])
name := pq.Query[loc.offset : loc.offset+loc.length]
if encodable, ok := extras[name[1:]]; ok {
encodable.EncodeSQL(buf)
encodable.EncodeSQL(&buf)
} else {
supplied, _, err := FetchBindVar(name, bindVariables)
if err != nil {
return nil, err
return "", err
}
EncodeValue(buf, supplied)
EncodeValue(&buf, supplied)
}
current = loc.offset + loc.length
}
buf.WriteString(pq.Query[current:])
return buf.Bytes(), nil
return buf.String(), nil
}
// MarshalJSON is a custom JSON marshaler for ParsedQuery.
......@@ -78,7 +79,7 @@ func (pq *ParsedQuery) MarshalJSON() ([]byte, error) {
}
// EncodeValue encodes one bind variable value into the query.
func EncodeValue(buf *bytes.Buffer, value *querypb.BindVariable) {
func EncodeValue(buf *strings.Builder, value *querypb.BindVariable) {
if value.Type != querypb.Type_TUPLE {
// Since we already check for TUPLE, we don't expect an error.
v, _ := sqltypes.BindVariableToValue(value)
......
......@@ -17,8 +17,8 @@ limitations under the License.
package sqlparser
import (
"bytes"
"fmt"
"strings"
)
// NodeFormatter defines the signature of a custom node formatter
......@@ -33,7 +33,7 @@ type NodeFormatter func(buf *TrackedBuffer, node SQLNode)
// But you can supply a different formatting function if you
// want to generate a query that's different from the default.
type TrackedBuffer struct {
*bytes.Buffer
*strings.Builder
bindLocations []bindLocation
nodeFormatter NodeFormatter
}
......@@ -41,7 +41,7 @@ type TrackedBuffer struct {
// NewTrackedBuffer creates a new TrackedBuffer.
func NewTrackedBuffer(nodeFormatter NodeFormatter) *TrackedBuffer {
return &TrackedBuffer{
Buffer: new(bytes.Buffer),
Builder: new(strings.Builder),
nodeFormatter: nodeFormatter,
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册