Skip to content

Commit

Permalink
merge release 3.0 to release 3.1 (pingcap#710)
Browse files Browse the repository at this point in the history
  • Loading branch information
bb7133 authored and jackysp committed Jan 7, 2020
1 parent 288fe52 commit aba8860
Show file tree
Hide file tree
Showing 13 changed files with 7,663 additions and 7,254 deletions.
37 changes: 34 additions & 3 deletions ast/dml.go
Original file line number Diff line number Diff line change
Expand Up @@ -2440,8 +2440,11 @@ func (n *FrameBound) Accept(v Visitor) (Node, bool) {
type SplitRegionStmt struct {
dmlNode

Table *TableName
IndexName model.CIStr
Table *TableName
IndexName model.CIStr
PartitionNames []model.CIStr

SplitSyntaxOpt *SplitSyntaxOption

SplitOpt *SplitOption
}
Expand All @@ -2453,11 +2456,39 @@ type SplitOption struct {
ValueLists [][]ExprNode
}

type SplitSyntaxOption struct {
HasRegionFor bool
HasPartition bool
}

func (n *SplitRegionStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("SPLIT TABLE ")
ctx.WriteKeyWord("SPLIT ")
if n.SplitSyntaxOpt != nil {
if n.SplitSyntaxOpt.HasRegionFor {
ctx.WriteKeyWord("REGION FOR ")
}
if n.SplitSyntaxOpt.HasPartition {
ctx.WriteKeyWord("PARTITION ")

}
}
ctx.WriteKeyWord("TABLE ")

if err := n.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore SplitIndexRegionStmt.Table")
}
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(")")
}

if len(n.IndexName.L) > 0 {
ctx.WriteKeyWord(" INDEX ")
ctx.WriteName(n.IndexName.String())
Expand Down
154 changes: 94 additions & 60 deletions ast/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ var (
_ StmtNode = &KillStmt{}
_ StmtNode = &CreateBindingStmt{}
_ StmtNode = &DropBindingStmt{}
_ StmtNode = &ShutdownStmt{}

_ Node = &PrivElem{}
_ Node = &VariableAssignment{}
Expand Down Expand Up @@ -975,12 +976,12 @@ const (
Subject
)

type TslOption struct {
type TLSOption struct {
Type int
Value string
}

func (t *TslOption) Restore(ctx *RestoreCtx) error {
func (t *TLSOption) Restore(ctx *RestoreCtx) error {
switch t.Type {
case TslNone:
ctx.WriteKeyWord("NONE")
Expand All @@ -995,10 +996,10 @@ func (t *TslOption) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("ISSUER ")
ctx.WriteString(t.Value)
case Subject:
ctx.WriteKeyWord("CIPHER")
ctx.WriteKeyWord("SUBJECT ")
ctx.WriteString(t.Value)
default:
return errors.Errorf("Unsupported TslOption.Type %d", t.Type)
return errors.Errorf("Unsupported TLSOption.Type %d", t.Type)
}
return nil
}
Expand Down Expand Up @@ -1055,7 +1056,7 @@ func (p *PasswordOrLockOption) Restore(ctx *RestoreCtx) error {
case PasswordExpireNever:
ctx.WriteKeyWord("PASSWORD EXPIRE NEVER")
case PasswordExpireInterval:
ctx.WriteKeyWord("PASSWORD EXPIRE NEVER")
ctx.WriteKeyWord("PASSWORD EXPIRE INTERVAL")
ctx.WritePlainf(" %d", p.Count)
ctx.WriteKeyWord(" DAY")
case Lock:
Expand All @@ -1076,7 +1077,7 @@ type CreateUserStmt struct {
IsCreateRole bool
IfNotExists bool
Specs []*UserSpec
TslOptions []*TslOption
TLSOptions []*TLSOption
ResourceOptions []*ResourceOption
PasswordOrLockOptions []*PasswordOrLockOption
}
Expand All @@ -1100,19 +1101,16 @@ func (n *CreateUserStmt) Restore(ctx *RestoreCtx) error {
}
}

tslOptionLen := len(n.TslOptions)

if tslOptionLen != 0 {
if len(n.TLSOptions) != 0 {
ctx.WriteKeyWord(" REQUIRE ")
}

// Restore `tslOptions` reversely to keep order the same with original sql
for i := tslOptionLen; i > 0; i-- {
if i != tslOptionLen {
for i, option := range n.TLSOptions {
if i != 0 {
ctx.WriteKeyWord(" AND ")
}
if err := n.TslOptions[i-1].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore CreateUserStmt.TslOptions[%d]", i)
if err := option.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore CreateUserStmt.TLSOptions[%d]", i)
}
}

Expand Down Expand Up @@ -1162,9 +1160,12 @@ func (n *CreateUserStmt) SecureText() string {
type AlterUserStmt struct {
stmtNode

IfExists bool
CurrentAuth *AuthOption
Specs []*UserSpec
IfExists bool
CurrentAuth *AuthOption
Specs []*UserSpec
TLSOptions []*TLSOption
ResourceOptions []*ResourceOption
PasswordOrLockOptions []*PasswordOrLockOption
}

// Restore implements Node interface.
Expand All @@ -1188,6 +1189,37 @@ func (n *AlterUserStmt) Restore(ctx *RestoreCtx) error {
return errors.Annotatef(err, "An error occurred while restore AlterUserStmt.Specs[%d]", i)
}
}

if len(n.TLSOptions) != 0 {
ctx.WriteKeyWord(" REQUIRE ")
}

for i, option := range n.TLSOptions {
if i != 0 {
ctx.WriteKeyWord(" AND ")
}
if err := option.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AlterUserStmt.TLSOptions[%d]", i)
}
}

if len(n.ResourceOptions) != 0 {
ctx.WriteKeyWord(" WITH")
}

for i, v := range n.ResourceOptions {
ctx.WritePlain(" ")
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AlterUserStmt.ResourceOptions[%d]", i)
}
}

for i, v := range n.PasswordOrLockOptions {
ctx.WritePlain(" ")
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AlterUserStmt.PasswordOrLockOptions[%d]", i)
}
}
return nil
}

Expand Down Expand Up @@ -1612,51 +1644,17 @@ type PrivElem struct {

// Restore implements Node interface.
func (n *PrivElem) Restore(ctx *RestoreCtx) error {
switch n.Priv {
case 0:
if n.Priv == 0 {
ctx.WritePlain("/* UNSUPPORTED TYPE */")
case mysql.AllPriv:
} else if n.Priv == mysql.AllPriv {
ctx.WriteKeyWord("ALL")
case mysql.AlterPriv:
ctx.WriteKeyWord("ALTER")
case mysql.CreatePriv:
ctx.WriteKeyWord("CREATE")
case mysql.CreateUserPriv:
ctx.WriteKeyWord("CREATE USER")
case mysql.CreateRolePriv:
ctx.WriteKeyWord("CREATE ROLE")
case mysql.TriggerPriv:
ctx.WriteKeyWord("TRIGGER")
case mysql.DeletePriv:
ctx.WriteKeyWord("DELETE")
case mysql.DropPriv:
ctx.WriteKeyWord("DROP")
case mysql.ProcessPriv:
ctx.WriteKeyWord("PROCESS")
case mysql.ExecutePriv:
ctx.WriteKeyWord("EXECUTE")
case mysql.IndexPriv:
ctx.WriteKeyWord("INDEX")
case mysql.InsertPriv:
ctx.WriteKeyWord("INSERT")
case mysql.SelectPriv:
ctx.WriteKeyWord("SELECT")
case mysql.SuperPriv:
ctx.WriteKeyWord("SUPER")
case mysql.ShowDBPriv:
ctx.WriteKeyWord("SHOW DATABASES")
case mysql.UpdatePriv:
ctx.WriteKeyWord("UPDATE")
case mysql.GrantPriv:
ctx.WriteKeyWord("GRANT OPTION")
case mysql.ReferencesPriv:
ctx.WriteKeyWord("REFERENCES")
case mysql.CreateViewPriv:
ctx.WriteKeyWord("CREATE VIEW")
case mysql.ShowViewPriv:
ctx.WriteKeyWord("SHOW VIEW")
default:
return errors.New("Undefined privilege type")
} else {
str, ok := mysql.Priv2Str[n.Priv]
if ok {
ctx.WriteKeyWord(str)
} else {
return errors.New("Undefined privilege type")
}
}
if n.Cols != nil {
ctx.WritePlain(" (")
Expand Down Expand Up @@ -1865,6 +1863,7 @@ type GrantStmt struct {
ObjectType ObjectTypeType
Level *GrantLevel
Users []*UserSpec
TLSOptions []*TLSOption
WithGrant bool
}

Expand Down Expand Up @@ -1900,6 +1899,19 @@ func (n *GrantStmt) Restore(ctx *RestoreCtx) error {
return errors.Annotatef(err, "An error occurred while restore GrantStmt.Users[%d]", i)
}
}
if n.TLSOptions != nil {
if len(n.TLSOptions) != 0 {
ctx.WriteKeyWord(" REQUIRE ")
}
for i, option := range n.TLSOptions {
if i != 0 {
ctx.WriteKeyWord(" AND ")
}
if err := option.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore GrantStmt.TLSOptions[%d]", i)
}
}
}
if n.WithGrant {
ctx.WriteKeyWord(" WITH GRANT OPTION")
}
Expand Down Expand Up @@ -1988,6 +2000,28 @@ func (n *GrantRoleStmt) SecureText() string {
return text
}

// ShutdownStmt is a statement to stop the TiDB server.
// See https://dev.mysql.com/doc/refman/5.7/en/shutdown.html
type ShutdownStmt struct {
stmtNode
}

// Restore implements Node interface.
func (n *ShutdownStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("SHUTDOWN")
return nil
}

// Accept implements Node Accept interface.
func (n *ShutdownStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*ShutdownStmt)
return v.Leave(n)
}

// Ident is the table identifier composed of schema name and table name.
type Ident struct {
Schema model.CIStr
Expand Down
4 changes: 3 additions & 1 deletion ast/misc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ func (ts *testMiscSuite) TestMiscVisitorCover(c *C) {
&VariableAssignment{Value: valueExpr},
&KillStmt{},
&DropStatsStmt{Table: &TableName{}},
&ShutdownStmt{},
}

for _, v := range stmts {
Expand Down Expand Up @@ -130,7 +131,8 @@ load data infile '/tmp/t.csv' into table t fields terminated by 'ab' enclosed by
// test Change Pump or drainer status sql parser
func (ts *testMiscSuite) TestChangeStmt(c *C) {
sql := `change pump to node_state='paused' for node_id '127.0.0.1:8249';
change drainer to node_state='paused' for node_id '127.0.0.1:8249';`
change drainer to node_state='paused' for node_id '127.0.0.1:8249';
shutdown;`

p := parser.New()
stmts, _, err := p.Parse(sql, "", "")
Expand Down
33 changes: 32 additions & 1 deletion digester.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,41 @@ import (
"crypto/sha256"
"fmt"
hash2 "hash"
"reflect"
"strings"
"sync"
"unicode"
"unsafe"
)

// 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
//
// Deprecated: It is logically consistent with NormalizeDigest.
func DigestHash(sql string) (result string) {
d := digesterPool.Get().(*sqlDigester)
result = d.doDigest(sql)
digesterPool.Put(d)
return
}

// DigestNormalized generates the digest of a normalized sql.
// it will generate a hash on a normalized sql.
// Normalize + DigestNormalized equals to NormalizeDigest.
//
// for example: DigestNormalized('select ?')
// DigestNormalized should be called with a normalized SQL string (like 'select ?') generated by function Normalize.
// do not call with SQL which is not normalized, DigestNormalized('select 1') and DigestNormalized('select 2') is not the same
func DigestNormalized(normalized string) (result string) {
d := digesterPool.Get().(*sqlDigester)
result = d.doDigestNormalized(normalized)
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.
Expand All @@ -47,7 +65,7 @@ func Normalize(sql string) (result string) {
return
}

// NormalizeDigest combines Normalize and DigestHash into one method.
// NormalizeDigest combines Normalize and DigestNormalized into one method.
func NormalizeDigest(sql string) (normalized, digest string) {
d := digesterPool.Get().(*sqlDigester)
normalized, digest = d.doNormalizeDigest(sql)
Expand All @@ -72,6 +90,19 @@ type sqlDigester struct {
tokens tokenDeque
}

func (d *sqlDigester) doDigestNormalized(normalized string) (result string) {
hdr := *(*reflect.StringHeader)(unsafe.Pointer(&normalized))
b := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
Data: hdr.Data,
Len: hdr.Len,
Cap: hdr.Len,
}))
d.hasher.Write(b)
result = fmt.Sprintf("%x", d.hasher.Sum(nil))
d.hasher.Reset()
return
}

func (d *sqlDigester) doDigest(sql string) (result string) {
d.normalize(sql)
d.hasher.Write(d.buffer.Bytes())
Expand Down
Loading

0 comments on commit aba8860

Please sign in to comment.