1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/hanchuanchuan-goInception

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
misc.go 52 КБ
Копировать Редактировать Исходные данные Просмотреть построчно История
hanchuanchuan Отправлено 4 лет назад c64eddf
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160
// Copyright 2015 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 ast
import (
"bytes"
"fmt"
"strconv"
"strings"
"github.com/hanchuanchuan/goInception/format"
. "github.com/hanchuanchuan/goInception/format"
"github.com/hanchuanchuan/goInception/model"
"github.com/hanchuanchuan/goInception/mysql"
"github.com/hanchuanchuan/goInception/util/auth"
"github.com/pingcap/errors"
)
var (
_ StmtNode = &AdminStmt{}
_ StmtNode = &AlterUserStmt{}
_ StmtNode = &BeginStmt{}
_ StmtNode = &BinlogStmt{}
_ StmtNode = &CommitStmt{}
_ StmtNode = &CreateUserStmt{}
_ StmtNode = &DeallocateStmt{}
_ StmtNode = &DoStmt{}
_ StmtNode = &ExecuteStmt{}
_ StmtNode = &ExplainStmt{}
_ StmtNode = &GrantStmt{}
_ StmtNode = &PrepareStmt{}
_ StmtNode = &RollbackStmt{}
_ StmtNode = &SetPwdStmt{}
_ StmtNode = &SetStmt{}
_ StmtNode = &UseStmt{}
_ StmtNode = &FlushStmt{}
_ StmtNode = &KillStmt{}
_ Node = &PrivElem{}
_ Node = &VariableAssignment{}
)
// Isolation level constants.
const (
ReadCommitted = "READ-COMMITTED"
ReadUncommitted = "READ-UNCOMMITTED"
Serializable = "SERIALIZABLE"
RepeatableRead = "REPEATABLE-READ"
// Valid formats for explain statement.
ExplainFormatROW = "row"
ExplainFormatDOT = "dot"
PumpType = "PUMP"
DrainerType = "DRAINER"
)
// Transaction mode constants.
const (
Optimistic = "OPTIMISTIC"
Pessimistic = "PESSIMISTIC"
)
var (
// ExplainFormats stores the valid formats for explain statement, used by validator.
ExplainFormats = []string{
ExplainFormatROW,
ExplainFormatDOT,
}
)
// TypeOpt is used for parsing data type option from SQL.
type TypeOpt struct {
IsUnsigned bool
IsZerofill bool
}
// FloatOpt is used for parsing floating-point type option from SQL.
// See http://dev.mysql.com/doc/refman/5.7/en/floating-point-types.html
type FloatOpt struct {
Flen int
Decimal int
}
// AuthOption is used for parsing create use statement.
type AuthOption struct {
// ByAuthString set as true, if AuthString is used for authorization. Otherwise, authorization is done by HashString.
ByAuthString bool
AuthString string
HashString string
// TODO: support auth_plugin
}
// Restore implements Node interface.
func (n *AuthOption) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("IDENTIFIED BY ")
if n.ByAuthString {
ctx.WriteString(n.AuthString)
} else {
ctx.WriteKeyWord("PASSWORD ")
ctx.WriteString(n.HashString)
}
return nil
}
// TraceStmt is a statement to trace what sql actually does at background.
type TraceStmt struct {
stmtNode
Stmt StmtNode
Format string
}
// Restore implements Node interface.
func (n *TraceStmt) Restore(ctx *RestoreCtx) error {
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.
func (n *TraceStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*TraceStmt)
node, ok := n.Stmt.Accept(v)
if !ok {
return n, false
}
n.Stmt = node.(DMLNode)
return v.Leave(n)
}
// ExplainForStmt is a statement to provite information about how is SQL statement executeing
// in connection #ConnectionID
// See https://dev.mysql.com/doc/refman/5.7/en/explain.html
type ExplainForStmt struct {
stmtNode
Format string
ConnectionID uint64
}
// Restore implements Node interface.
func (n *ExplainForStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("EXPLAIN ")
ctx.WriteKeyWord("FORMAT ")
ctx.WritePlain("= ")
ctx.WriteString(n.Format)
ctx.WritePlain(" ")
ctx.WriteKeyWord("FOR ")
ctx.WriteKeyWord("CONNECTION ")
ctx.WritePlain(strconv.FormatUint(n.ConnectionID, 10))
return nil
}
// Accept implements Node Accept interface.
func (n *ExplainForStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*ExplainForStmt)
return v.Leave(n)
}
// ExplainStmt is a statement to provide information about how is SQL statement executed
// or get columns information in a table.
// See https://dev.mysql.com/doc/refman/5.7/en/explain.html
type ExplainStmt struct {
stmtNode
Stmt StmtNode
Format string
Analyze bool
}
// Restore implements Node interface.
func (n *ExplainStmt) Restore(ctx *RestoreCtx) error {
if showStmt, ok := n.Stmt.(*ShowStmt); ok {
ctx.WriteKeyWord("DESC ")
if err := showStmt.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore ExplainStmt.ShowStmt.Table")
}
if showStmt.Column != nil {
ctx.WritePlain(" ")
if err := showStmt.Column.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore ExplainStmt.ShowStmt.Column")
}
}
return nil
}
ctx.WriteKeyWord("EXPLAIN ")
if n.Analyze {
ctx.WriteKeyWord("ANALYZE ")
} else {
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 ExplainStmt.Stmt")
}
return nil
}
// Accept implements Node Accept interface.
func (n *ExplainStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*ExplainStmt)
node, ok := n.Stmt.Accept(v)
if !ok {
return n, false
}
n.Stmt = node.(DMLNode)
return v.Leave(n)
}
// PrepareStmt is a statement to prepares a SQL statement which contains placeholders,
// and it is executed with ExecuteStmt and released with DeallocateStmt.
// See https://dev.mysql.com/doc/refman/5.7/en/prepare.html
type PrepareStmt struct {
stmtNode
Name string
SQLText string
SQLVar *VariableExpr
}
// Restore implements Node interface.
func (n *PrepareStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("PREPARE ")
ctx.WriteName(n.Name)
ctx.WriteKeyWord(" FROM ")
if n.SQLText != "" {
ctx.WriteString(n.SQLText)
return nil
}
if n.SQLVar != nil {
if err := n.SQLVar.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore PrepareStmt.SQLVar")
}
return nil
}
return errors.New("An error occurred while restore PrepareStmt")
}
// Accept implements Node Accept interface.
func (n *PrepareStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*PrepareStmt)
if n.SQLVar != nil {
node, ok := n.SQLVar.Accept(v)
if !ok {
return n, false
}
n.SQLVar = node.(*VariableExpr)
}
return v.Leave(n)
}
// DeallocateStmt is a statement to release PreparedStmt.
// See https://dev.mysql.com/doc/refman/5.7/en/deallocate-prepare.html
type DeallocateStmt struct {
stmtNode
Name string
}
// Restore implements Node interface.
func (n *DeallocateStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("DEALLOCATE PREPARE ")
ctx.WriteName(n.Name)
return nil
}
// Accept implements Node Accept interface.
func (n *DeallocateStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*DeallocateStmt)
return v.Leave(n)
}
// Prepared represents a prepared statement.
type Prepared struct {
Stmt StmtNode
Params []*ParamMarkerExpr
SchemaVersion int64
UseCache bool
}
// ExecuteStmt is a statement to execute PreparedStmt.
// See https://dev.mysql.com/doc/refman/5.7/en/execute.html
type ExecuteStmt struct {
stmtNode
Name string
UsingVars []ExprNode
ExecID uint32
}
// Restore implements Node interface.
func (n *ExecuteStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("EXECUTE ")
ctx.WriteName(n.Name)
if len(n.UsingVars) > 0 {
ctx.WriteKeyWord(" USING ")
for i, val := range n.UsingVars {
if i != 0 {
ctx.WritePlain(",")
}
if err := val.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore ExecuteStmt.UsingVars index %d", i)
}
}
}
return nil
}
// Accept implements Node Accept interface.
func (n *ExecuteStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*ExecuteStmt)
for i, val := range n.UsingVars {
node, ok := val.Accept(v)
if !ok {
return n, false
}
n.UsingVars[i] = node.(ExprNode)
}
return v.Leave(n)
}
// BeginStmt is a statement to start a new transaction.
// See https://dev.mysql.com/doc/refman/5.7/en/commit.html
type BeginStmt struct {
stmtNode
Mode string
}
// Restore implements Node interface.
func (n *BeginStmt) Restore(ctx *RestoreCtx) error {
if n.Mode == "" {
ctx.WriteKeyWord("START TRANSACTION")
} else {
ctx.WriteKeyWord("BEGIN ")
ctx.WriteKeyWord(n.Mode)
}
return nil
}
// Accept implements Node Accept interface.
func (n *BeginStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*BeginStmt)
return v.Leave(n)
}
// BinlogStmt is an internal-use statement.
// We just parse and ignore it.
// See http://dev.mysql.com/doc/refman/5.7/en/binlog.html
type BinlogStmt struct {
stmtNode
Str string
}
// Restore implements Node interface.
func (n *BinlogStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("BINLOG ")
ctx.WriteString(n.Str)
return nil
}
// Accept implements Node Accept interface.
func (n *BinlogStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*BinlogStmt)
return v.Leave(n)
}
// CommitStmt is a statement to commit the current transaction.
// See https://dev.mysql.com/doc/refman/5.7/en/commit.html
type CommitStmt struct {
stmtNode
}
// Restore implements Node interface.
func (n *CommitStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("COMMIT")
return nil
}
// Accept implements Node Accept interface.
func (n *CommitStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*CommitStmt)
return v.Leave(n)
}
// RollbackStmt is a statement to roll back the current transaction.
// See https://dev.mysql.com/doc/refman/5.7/en/commit.html
type RollbackStmt struct {
stmtNode
}
// Restore implements Node interface.
func (n *RollbackStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("ROLLBACK")
return nil
}
// Accept implements Node Accept interface.
func (n *RollbackStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*RollbackStmt)
return v.Leave(n)
}
// UseStmt is a statement to use the DBName database as the current database.
// See https://dev.mysql.com/doc/refman/5.7/en/use.html
type UseStmt struct {
stmtNode
DBName string
}
// Restore implements Node interface.
func (n *UseStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("USE ")
ctx.WriteName(n.DBName)
return nil
}
// Accept implements Node Accept interface.
func (n *UseStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*UseStmt)
return v.Leave(n)
}
const (
// SetNames is the const for set names/charset stmt.
// If VariableAssignment.Name == Names, it should be set names/charset stmt.
SetNames = "SetNAMES"
)
// VariableAssignment is a variable assignment struct.
type VariableAssignment struct {
node
Name string
Value ExprNode
IsGlobal bool
IsSystem bool
IsLevel bool
// ExtendValue is a way to store extended info.
// VariableAssignment should be able to store information for SetCharset/SetPWD Stmt.
// For SetCharsetStmt, Value is charset, ExtendValue is collation.
// TODO: Use SetStmt to implement set password statement.
ExtendValue *ValueExpr
}
// Restore implements Node interface.
func (n *VariableAssignment) Restore(ctx *RestoreCtx) error {
if n.IsSystem {
ctx.WritePlain("@@")
if n.IsGlobal {
ctx.WriteKeyWord("GLOBAL")
} else {
ctx.WriteKeyWord("SESSION")
}
ctx.WritePlain(".")
} else if n.Name != SetNames {
ctx.WriteKeyWord("@")
}
if n.Name == SetNames {
ctx.WriteKeyWord("NAMES ")
} else {
ctx.WriteName(n.Name)
ctx.WritePlain("=")
}
if err := n.Value.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore VariableAssignment.Value")
}
if n.ExtendValue != nil {
ctx.WriteKeyWord(" COLLATE ")
if err := n.ExtendValue.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore VariableAssignment.ExtendValue")
}
}
return nil
}
// Accept implements Node interface.
func (n *VariableAssignment) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*VariableAssignment)
node, ok := n.Value.Accept(v)
if !ok {
return n, false
}
n.Value = node.(ExprNode)
return v.Leave(n)
}
// FlushStmtType is the type for FLUSH statement.
type FlushStmtType int
// Flush statement types.
const (
FlushNone FlushStmtType = iota
FlushTables
FlushPrivileges
FlushStatus
FlushTiDBPlugin
)
// FlushStmt is a statement to flush tables/privileges/optimizer costs and so on.
type FlushStmt struct {
stmtNode
Tp FlushStmtType // Privileges/Tables/...
NoWriteToBinLog bool
Tables []*TableName // For FlushTableStmt, if Tables is empty, it means flush all tables.
ReadLock bool
Plugins []string
}
// Restore implements Node interface.
func (n *FlushStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("FLUSH ")
if n.NoWriteToBinLog {
ctx.WriteKeyWord("NO_WRITE_TO_BINLOG ")
}
switch n.Tp {
case FlushTables:
ctx.WriteKeyWord("TABLES")
for i, v := range n.Tables {
if i == 0 {
ctx.WritePlain(" ")
} else {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FlushStmt.Tables[%d]", i)
}
}
if n.ReadLock {
ctx.WriteKeyWord(" WITH READ LOCK")
}
case FlushPrivileges:
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")
}
return nil
}
// Accept implements Node Accept interface.
func (n *FlushStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*FlushStmt)
return v.Leave(n)
}
// KillStmt is a statement to kill a query or connection.
type KillStmt struct {
stmtNode
// Query indicates whether terminate a single query on this connection or the whole connection.
// If Query is true, terminates the statement the connection is currently executing, but leaves the connection itself intact.
// If Query is false, terminates the connection associated with the given ConnectionID, after terminating any statement the connection is executing.
Query bool
ConnectionID uint64
// TiDBExtension is used to indicate whether the user knows he is sending kill statement to the right tidb-server.
// When the SQL grammar is "KILL TIDB [CONNECTION | QUERY] connectionID", TiDBExtension will be set.
// It's a special grammar extension in TiDB. This extension exists because, when the connection is:
// client -> LVS proxy -> TiDB, and type Ctrl+C in client, the following action will be executed:
// new a connection; kill xxx;
// kill command may send to the wrong TiDB, because the exists of LVS proxy, and kill the wrong session.
// So, "KILL TIDB" grammar is introduced, and it REQUIRES DIRECT client -> TiDB TOPOLOGY.
// TODO: The standard KILL grammar will be supported once we have global connectionID.
TiDBExtension bool
}
// Restore implements Node interface.
func (n *KillStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("KILL")
if n.TiDBExtension {
ctx.WriteKeyWord(" TIDB")
}
if n.Query {
ctx.WriteKeyWord(" QUERY")
}
ctx.WritePlainf(" %d", n.ConnectionID)
return nil
}
// Accept implements Node Accept interface.
func (n *KillStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*KillStmt)
return v.Leave(n)
}
// SetStmt is the statement to set variables.
type SetStmt struct {
stmtNode
// Variables is the list of variable assignment.
Variables []*VariableAssignment
}
// Restore implements Node interface.
func (n *SetStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("SET ")
for i, v := range n.Variables {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore SetStmt.Variables[%d]", i)
}
}
return nil
}
// Accept implements Node Accept interface.
func (n *SetStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*SetStmt)
for i, val := range n.Variables {
node, ok := val.Accept(v)
if !ok {
return n, false
}
n.Variables[i] = node.(*VariableAssignment)
}
return v.Leave(n)
}
/*
// SetCharsetStmt is a statement to assign values to character and collation variables.
// See https://dev.mysql.com/doc/refman/5.7/en/set-statement.html
type SetCharsetStmt struct {
stmtNode
Charset string
Collate string
}
// Accept implements Node Accept interface.
func (n *SetCharsetStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*SetCharsetStmt)
return v.Leave(n)
}
*/
// SetPwdStmt is a statement to assign a password to user account.
// See https://dev.mysql.com/doc/refman/5.7/en/set-password.html
type SetPwdStmt struct {
stmtNode
User *auth.UserIdentity
Password string
}
// Restore implements Node interface.
func (n *SetPwdStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("SET PASSWORD")
if n.User != nil {
ctx.WriteKeyWord(" FOR ")
if err := n.User.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore SetPwdStmt.User")
}
}
ctx.WritePlain("=")
ctx.WriteString(n.Password)
return nil
}
// SecureText implements SensitiveStatement interface.
func (n *SetPwdStmt) SecureText() string {
return fmt.Sprintf("set password for user %s", n.User)
}
// Accept implements Node Accept interface.
func (n *SetPwdStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*SetPwdStmt)
return v.Leave(n)
}
type ChangeStmt struct {
stmtNode
NodeType string
State string
NodeID string
}
// Restore implements Node interface.
func (n *ChangeStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("CHANGE ")
ctx.WriteKeyWord(n.NodeType)
ctx.WriteKeyWord(" TO NODE_STATE ")
ctx.WritePlain("=")
ctx.WriteString(n.State)
ctx.WriteKeyWord(" FOR NODE_ID ")
ctx.WriteString(n.NodeID)
return nil
}
// SecureText implements SensitiveStatement interface.
func (n *ChangeStmt) SecureText() string {
return fmt.Sprintf("change %s to node_state='%s' for node_id '%s'", strings.ToLower(n.NodeType), n.State, n.NodeID)
}
// Accept implements Node Accept interface.
func (n *ChangeStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*ChangeStmt)
return v.Leave(n)
}
// SetRoleStmtType is the type for FLUSH statement.
type SetRoleStmtType int
// SetRole statement types.
const (
SetRoleDefault SetRoleStmtType = iota
SetRoleNone
SetRoleAll
SetRoleAllExcept
SetRoleRegular
)
type SetRoleStmt struct {
stmtNode
SetRoleOpt SetRoleStmtType
RoleList []*auth.RoleIdentity
}
func (n *SetRoleStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("SET ROLE")
switch n.SetRoleOpt {
case SetRoleDefault:
ctx.WriteKeyWord(" DEFAULT")
case SetRoleNone:
ctx.WriteKeyWord(" NONE")
case SetRoleAll:
ctx.WriteKeyWord(" ALL")
case SetRoleAllExcept:
ctx.WriteKeyWord(" ALL EXCEPT")
}
for i, role := range n.RoleList {
ctx.WritePlain(" ")
err := role.Restore(ctx)
if err != nil {
return errors.Annotate(err, "An error occurred while restore SetRoleStmt.RoleList")
}
if i != len(n.RoleList)-1 {
ctx.WritePlain(",")
}
}
return nil
}
// Accept implements Node Accept interface.
func (n *SetRoleStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*SetRoleStmt)
return v.Leave(n)
}
type SetDefaultRoleStmt struct {
stmtNode
SetRoleOpt SetRoleStmtType
RoleList []*auth.RoleIdentity
UserList []*auth.UserIdentity
}
func (n *SetDefaultRoleStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("SET DEFAULT ROLE")
switch n.SetRoleOpt {
case SetRoleNone:
ctx.WriteKeyWord(" NONE")
case SetRoleAll:
ctx.WriteKeyWord(" ALL")
default:
}
for i, role := range n.RoleList {
ctx.WritePlain(" ")
err := role.Restore(ctx)
if err != nil {
return errors.Annotate(err, "An error occurred while restore SetDefaultRoleStmt.RoleList")
}
if i != len(n.RoleList)-1 {
ctx.WritePlain(",")
}
}
ctx.WritePlain(" TO")
for i, user := range n.UserList {
ctx.WritePlain(" ")
err := user.Restore(ctx)
if err != nil {
return errors.Annotate(err, "An error occurred while restore SetDefaultRoleStmt.UserList")
}
if i != len(n.UserList)-1 {
ctx.WritePlain(",")
}
}
return nil
}
// Accept implements Node Accept interface.
func (n *SetDefaultRoleStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*SetDefaultRoleStmt)
return v.Leave(n)
}
// UserSpec is used for parsing create user statement.
type UserSpec struct {
User *auth.UserIdentity
AuthOpt *AuthOption
IsRole bool
}
// Restore implements Node interface.
func (n *UserSpec) Restore(ctx *RestoreCtx) error {
if err := n.User.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore UserSpec.User")
}
if n.AuthOpt != nil {
ctx.WritePlain(" ")
if err := n.AuthOpt.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore UserSpec.AuthOpt")
}
}
return nil
}
// SecurityString formats the UserSpec without password information.
func (n *UserSpec) SecurityString() string {
withPassword := false
if opt := n.AuthOpt; opt != nil {
if len(opt.AuthString) > 0 || len(opt.HashString) > 0 {
withPassword = true
}
}
if withPassword {
return fmt.Sprintf("{%s password = ***}", n.User)
}
return n.User.String()
}
// EncodedPassword returns the encoded password (which is the real data mysql.user).
// The boolean value indicates input's password format is legal or not.
func (n *UserSpec) EncodedPassword() (string, bool) {
if n.AuthOpt == nil {
return "", true
}
opt := n.AuthOpt
if opt.ByAuthString {
return auth.EncodePassword(opt.AuthString), true
}
// Not a legal password string.
if len(opt.HashString) != 41 || !strings.HasPrefix(opt.HashString, "*") {
return "", false
}
return opt.HashString, true
}
const (
TslNone = iota
Ssl
X509
Cipher
Issuer
Subject
)
type TslOption struct {
Type int
Value string
}
func (t *TslOption) Restore(ctx *RestoreCtx) error {
switch t.Type {
case TslNone:
ctx.WriteKeyWord("NONE")
case Ssl:
ctx.WriteKeyWord("SSL")
case X509:
ctx.WriteKeyWord("X509")
case Cipher:
ctx.WriteKeyWord("CIPHER ")
ctx.WriteString(t.Value)
case Issuer:
ctx.WriteKeyWord("ISSUER ")
ctx.WriteString(t.Value)
case Subject:
ctx.WriteKeyWord("CIPHER")
ctx.WriteString(t.Value)
default:
return errors.Errorf("Unsupported TslOption.Type %d", t.Type)
}
return nil
}
const (
MaxQueriesPerHour = iota + 1
MaxUpdatesPerHour
MaxConnectionsPerHour
MaxUserConnections
)
type ResourceOption struct {
Type int
Count int64
}
func (r *ResourceOption) Restore(ctx *RestoreCtx) error {
switch r.Type {
case MaxQueriesPerHour:
ctx.WriteKeyWord("MAX_QUERIES_PER_HOUR ")
case MaxUpdatesPerHour:
ctx.WriteKeyWord("MAX_UPDATES_PER_HOUR ")
case MaxConnectionsPerHour:
ctx.WriteKeyWord("MAX_CONNECTIONS_PER_HOUR ")
case MaxUserConnections:
ctx.WriteKeyWord("MAX_USER_CONNECTIONS ")
default:
return errors.Errorf("Unsupported ResourceOption.Type %d", r.Type)
}
ctx.WritePlainf("%d", r.Count)
return nil
}
const (
PasswordExpire = iota + 1
PasswordExpireDefault
PasswordExpireNever
PasswordExpireInterval
Lock
Unlock
)
type PasswordOrLockOption struct {
Type int
Count int64
}
func (p *PasswordOrLockOption) Restore(ctx *RestoreCtx) error {
switch p.Type {
case PasswordExpire:
ctx.WriteKeyWord("PASSWORD EXPIRE")
case PasswordExpireDefault:
ctx.WriteKeyWord("PASSWORD EXPIRE DEFAULT")
case PasswordExpireNever:
ctx.WriteKeyWord("PASSWORD EXPIRE NEVER")
case PasswordExpireInterval:
ctx.WriteKeyWord("PASSWORD EXPIRE NEVER")
ctx.WritePlainf(" %d", p.Count)
ctx.WriteKeyWord(" DAY")
case Lock:
ctx.WriteKeyWord("ACCOUNT LOCK")
case Unlock:
ctx.WriteKeyWord("ACCOUNT UNLOCK")
default:
return errors.Errorf("Unsupported PasswordOrLockOption.Type %d", p.Type)
}
return nil
}
// CreateUserStmt creates user account.
// See https://dev.mysql.com/doc/refman/5.7/en/create-user.html
type CreateUserStmt struct {
stmtNode
IsCreateRole bool
IfNotExists bool
Specs []*UserSpec
TslOptions []*TslOption
ResourceOptions []*ResourceOption
PasswordOrLockOptions []*PasswordOrLockOption
}
// Restore implements Node interface.
func (n *CreateUserStmt) Restore(ctx *RestoreCtx) error {
if n.IsCreateRole {
ctx.WriteKeyWord("CREATE ROLE ")
} else {
ctx.WriteKeyWord("CREATE USER ")
}
if n.IfNotExists {
ctx.WriteKeyWord("IF NOT EXISTS ")
}
for i, v := range n.Specs {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore CreateUserStmt.Specs[%d]", i)
}
}
tslOptionLen := len(n.TslOptions)
if tslOptionLen != 0 {
ctx.WriteKeyWord(" REQUIRE ")
}
// Restore `tslOptions` reversely to keep order the same with original sql
for i := tslOptionLen; i > 0; i-- {
if i != tslOptionLen {
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 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 CreateUserStmt.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 CreateUserStmt.PasswordOrLockOptions[%d]", i)
}
}
return nil
}
// Accept implements Node Accept interface.
func (n *CreateUserStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*CreateUserStmt)
return v.Leave(n)
}
// SecureText implements SensitiveStatement interface.
func (n *CreateUserStmt) SecureText() string {
var buf bytes.Buffer
buf.WriteString("create user")
for _, user := range n.Specs {
buf.WriteString(" ")
buf.WriteString(user.SecurityString())
}
return buf.String()
}
// AlterUserStmt modifies user account.
// See https://dev.mysql.com/doc/refman/5.7/en/alter-user.html
type AlterUserStmt struct {
stmtNode
IfExists bool
CurrentAuth *AuthOption
Specs []*UserSpec
}
// Restore implements Node interface.
func (n *AlterUserStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("ALTER USER ")
if n.IfExists {
ctx.WriteKeyWord("IF EXISTS ")
}
if n.CurrentAuth != nil {
ctx.WriteKeyWord("USER")
ctx.WritePlain("() ")
if err := n.CurrentAuth.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterUserStmt.CurrentAuth")
}
}
for i, v := range n.Specs {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AlterUserStmt.Specs[%d]", i)
}
}
return nil
}
// SecureText implements SensitiveStatement interface.
func (n *AlterUserStmt) SecureText() string {
var buf bytes.Buffer
buf.WriteString("alter user")
for _, user := range n.Specs {
buf.WriteString(" ")
buf.WriteString(user.SecurityString())
}
return buf.String()
}
// Accept implements Node Accept interface.
func (n *AlterUserStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*AlterUserStmt)
return v.Leave(n)
}
// DropUserStmt creates user account.
// See http://dev.mysql.com/doc/refman/5.7/en/drop-user.html
type DropUserStmt struct {
stmtNode
IfExists bool
IsDropRole bool
UserList []*auth.UserIdentity
}
// Restore implements Node interface.
func (n *DropUserStmt) Restore(ctx *RestoreCtx) error {
if n.IsDropRole {
ctx.WriteKeyWord("DROP ROLE ")
} else {
ctx.WriteKeyWord("DROP USER ")
}
if n.IfExists {
ctx.WriteKeyWord("IF EXISTS ")
}
for i, v := range n.UserList {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore DropUserStmt.UserList[%d]", i)
}
}
return nil
}
// Accept implements Node Accept interface.
func (n *DropUserStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*DropUserStmt)
return v.Leave(n)
}
// CreateBindingStmt creates sql binding hint.
type CreateBindingStmt struct {
stmtNode
GlobalScope bool
OriginSel StmtNode
HintedSel StmtNode
}
func (n *CreateBindingStmt) Restore(ctx *RestoreCtx) error {
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) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*CreateBindingStmt)
selnode, ok := n.OriginSel.Accept(v)
if !ok {
return n, false
}
n.OriginSel = selnode.(*SelectStmt)
hintedSelnode, ok := n.HintedSel.Accept(v)
if !ok {
return n, false
}
n.HintedSel = hintedSelnode.(*SelectStmt)
return v.Leave(n)
}
// DropBindingStmt deletes sql binding hint.
type DropBindingStmt struct {
stmtNode
GlobalScope bool
OriginSel StmtNode
}
func (n *DropBindingStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
func (n *DropBindingStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*DropBindingStmt)
selnode, ok := n.OriginSel.Accept(v)
if !ok {
return n, false
}
n.OriginSel = selnode.(*SelectStmt)
return v.Leave(n)
}
// DoStmt is the struct for DO statement.
type DoStmt struct {
stmtNode
Exprs []ExprNode
}
// Restore implements Node interface.
func (n *DoStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("DO ")
for i, v := range n.Exprs {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore DoStmt.Exprs[%d]", i)
}
}
return nil
}
// Accept implements Node Accept interface.
func (n *DoStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*DoStmt)
for i, val := range n.Exprs {
node, ok := val.Accept(v)
if !ok {
return n, false
}
n.Exprs[i] = node.(ExprNode)
}
return v.Leave(n)
}
// AdminStmtType is the type for admin statement.
type AdminStmtType int
// Admin statement types.
const (
AdminShowDDL = iota + 1
AdminCheckTable
AdminShowDDLJobs
AdminCancelDDLJobs
AdminCheckIndex
AdminRecoverIndex
AdminCleanupIndex
AdminCheckIndexRange
AdminShowDDLJobQueries
AdminChecksumTable
AdminShowSlow
AdminShowNextRowID
AdminReloadExprPushdownBlacklist
AdminReloadOptRuleBlacklist
AdminPluginDisable
AdminPluginEnable
)
// HandleRange represents a range where handle value >= Begin and < End.
type HandleRange struct {
Begin int64
End int64
}
// ShowSlowType defines the type for SlowSlow statement.
type ShowSlowType int
const (
// ShowSlowTop is a ShowSlowType constant.
ShowSlowTop ShowSlowType = iota
// ShowSlowRecent is a ShowSlowType constant.
ShowSlowRecent
)
// ShowSlowKind defines the kind for SlowSlow statement when the type is ShowSlowTop.
type ShowSlowKind int
const (
// ShowSlowKindDefault is a ShowSlowKind constant.
ShowSlowKindDefault ShowSlowKind = iota
// ShowSlowKindInternal is a ShowSlowKind constant.
ShowSlowKindInternal
// ShowSlowKindAll is a ShowSlowKind constant.
ShowSlowKindAll
)
// ShowSlow is used for the following command:
// admin show slow top [ internal | all] N
// admin show slow recent N
type ShowSlow struct {
Tp ShowSlowType
Count uint64
Kind ShowSlowKind
}
// Restore implements Node interface.
func (n *ShowSlow) Restore(ctx *RestoreCtx) error {
switch n.Tp {
case ShowSlowRecent:
ctx.WriteKeyWord("RECENT ")
case ShowSlowTop:
ctx.WriteKeyWord("TOP ")
switch n.Kind {
case ShowSlowKindDefault:
// do nothing
case ShowSlowKindInternal:
ctx.WriteKeyWord("INTERNAL ")
case ShowSlowKindAll:
ctx.WriteKeyWord("ALL ")
default:
return errors.New("Unsupported kind of ShowSlowTop")
}
default:
return errors.New("Unsupported type of ShowSlow")
}
ctx.WritePlainf("%d", n.Count)
return nil
}
// AdminStmt is the struct for Admin statement.
type AdminStmt struct {
stmtNode
Tp AdminStmtType
Index string
Tables []*TableName
JobIDs []int64
JobNumber int64
HandleRanges []HandleRange
ShowSlow *ShowSlow
Plugins []string
}
// Restore implements Node interface.
func (n *AdminStmt) Restore(ctx *RestoreCtx) error {
restoreTables := func() error {
for i, v := range n.Tables {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AdminStmt.Tables[%d]", i)
}
}
return nil
}
restoreJobIDs := func() {
for i, v := range n.JobIDs {
if i != 0 {
ctx.WritePlain(", ")
}
ctx.WritePlainf("%d", v)
}
}
ctx.WriteKeyWord("ADMIN ")
switch n.Tp {
case AdminShowDDL:
ctx.WriteKeyWord("SHOW DDL")
case AdminShowDDLJobs:
ctx.WriteKeyWord("SHOW DDL JOBS")
if n.JobNumber != 0 {
ctx.WritePlainf(" %d", n.JobNumber)
}
case AdminShowNextRowID:
ctx.WriteKeyWord("SHOW ")
if err := restoreTables(); err != nil {
return err
}
ctx.WriteKeyWord(" NEXT_ROW_ID")
case AdminCheckTable:
ctx.WriteKeyWord("CHECK TABLE ")
if err := restoreTables(); err != nil {
return err
}
case AdminCheckIndex:
ctx.WriteKeyWord("CHECK INDEX ")
if err := restoreTables(); err != nil {
return err
}
ctx.WritePlainf(" %s", n.Index)
case AdminRecoverIndex:
ctx.WriteKeyWord("RECOVER INDEX ")
if err := restoreTables(); err != nil {
return err
}
ctx.WritePlainf(" %s", n.Index)
case AdminCleanupIndex:
ctx.WriteKeyWord("CLEANUP INDEX ")
if err := restoreTables(); err != nil {
return err
}
ctx.WritePlainf(" %s", n.Index)
case AdminCheckIndexRange:
ctx.WriteKeyWord("CHECK INDEX ")
if err := restoreTables(); err != nil {
return err
}
ctx.WritePlainf(" %s", n.Index)
if n.HandleRanges != nil {
ctx.WritePlain(" ")
for i, v := range n.HandleRanges {
if i != 0 {
ctx.WritePlain(", ")
}
ctx.WritePlainf("(%d,%d)", v.Begin, v.End)
}
}
case AdminChecksumTable:
ctx.WriteKeyWord("CHECKSUM TABLE ")
if err := restoreTables(); err != nil {
return err
}
case AdminCancelDDLJobs:
ctx.WriteKeyWord("CANCEL DDL JOBS ")
restoreJobIDs()
case AdminShowDDLJobQueries:
ctx.WriteKeyWord("SHOW DDL JOB QUERIES ")
restoreJobIDs()
case AdminShowSlow:
ctx.WriteKeyWord("SHOW SLOW ")
if err := n.ShowSlow.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AdminStmt.ShowSlow")
}
case AdminReloadExprPushdownBlacklist:
ctx.WriteKeyWord("RELOAD EXPR_PUSHDOWN_BLACKLIST")
case AdminReloadOptRuleBlacklist:
ctx.WriteKeyWord("RELOAD OPT_RULE_BLACKLIST")
case AdminPluginEnable:
ctx.WriteKeyWord("PLUGINS ENABLE")
for i, v := range n.Plugins {
if i == 0 {
ctx.WritePlain(" ")
} else {
ctx.WritePlain(", ")
}
ctx.WritePlain(v)
}
case AdminPluginDisable:
ctx.WriteKeyWord("PLUGINS DISABLE")
for i, v := range n.Plugins {
if i == 0 {
ctx.WritePlain(" ")
} else {
ctx.WritePlain(", ")
}
ctx.WritePlain(v)
}
default:
return errors.New("Unsupported AdminStmt type")
}
return nil
}
// Accept implements Node Accept interface.
func (n *AdminStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*AdminStmt)
for i, val := range n.Tables {
node, ok := val.Accept(v)
if !ok {
return n, false
}
n.Tables[i] = node.(*TableName)
}
return v.Leave(n)
}
// PrivElem is the privilege type and optional column list.
type PrivElem struct {
node
Priv mysql.PrivilegeType
Cols []*ColumnName
}
// Restore implements Node interface.
func (n *PrivElem) Restore(ctx *RestoreCtx) error {
switch n.Priv {
case 0:
ctx.WritePlain("/* UNSUPPORTED TYPE */")
case 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")
}
if n.Cols != nil {
ctx.WritePlain(" (")
for i, v := range n.Cols {
if i != 0 {
ctx.WritePlain(",")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore PrivElem.Cols[%d]", i)
}
}
ctx.WritePlain(")")
}
return nil
}
// Accept implements Node Accept interface.
func (n *PrivElem) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*PrivElem)
for i, val := range n.Cols {
node, ok := val.Accept(v)
if !ok {
return n, false
}
n.Cols[i] = node.(*ColumnName)
}
return v.Leave(n)
}
// ObjectTypeType is the type for object type.
type ObjectTypeType int
const (
// ObjectTypeNone is for empty object type.
ObjectTypeNone ObjectTypeType = iota + 1
// ObjectTypeTable means the following object is a table.
ObjectTypeTable
)
// Restore implements Node interface.
func (n ObjectTypeType) Restore(ctx *RestoreCtx) error {
switch n {
case ObjectTypeNone:
// do nothing
case ObjectTypeTable:
ctx.WriteKeyWord("TABLE")
default:
return errors.New("Unsupported object type")
}
return nil
}
// GrantLevelType is the type for grant level.
type GrantLevelType int
const (
// GrantLevelNone is the dummy const for default value.
GrantLevelNone GrantLevelType = iota + 1
// GrantLevelGlobal means the privileges are administrative or apply to all databases on a given server.
GrantLevelGlobal
// GrantLevelDB means the privileges apply to all objects in a given database.
GrantLevelDB
// GrantLevelTable means the privileges apply to all columns in a given table.
GrantLevelTable
)
// GrantLevel is used for store the privilege scope.
type GrantLevel struct {
Level GrantLevelType
DBName string
TableName string
}
// Restore implements Node interface.
func (n *GrantLevel) Restore(ctx *RestoreCtx) error {
switch n.Level {
case GrantLevelDB:
if n.DBName == "" {
ctx.WritePlain("*")
} else {
ctx.WriteName(n.DBName)
ctx.WritePlain(".*")
}
case GrantLevelGlobal:
ctx.WritePlain("*.*")
case GrantLevelTable:
if n.DBName != "" {
ctx.WriteName(n.DBName)
ctx.WritePlain(".")
}
ctx.WriteName(n.TableName)
}
return nil
}
// RevokeStmt is the struct for REVOKE statement.
type RevokeStmt struct {
stmtNode
Privs []*PrivElem
ObjectType ObjectTypeType
Level *GrantLevel
Users []*UserSpec
}
// Restore implements Node interface.
func (n *RevokeStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("REVOKE ")
for i, v := range n.Privs {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore RevokeStmt.Privs[%d]", i)
}
}
ctx.WriteKeyWord(" ON ")
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")
}
ctx.WriteKeyWord(" FROM ")
for i, v := range n.Users {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore RevokeStmt.Users[%d]", i)
}
}
return nil
}
// Accept implements Node Accept interface.
func (n *RevokeStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*RevokeStmt)
for i, val := range n.Privs {
node, ok := val.Accept(v)
if !ok {
return n, false
}
n.Privs[i] = node.(*PrivElem)
}
return v.Leave(n)
}
// RevokeStmt is the struct for REVOKE statement.
type RevokeRoleStmt struct {
stmtNode
Roles []*auth.RoleIdentity
Users []*auth.UserIdentity
}
// Restore implements Node interface.
func (n *RevokeRoleStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("REVOKE ")
for i, role := range n.Roles {
if i != 0 {
ctx.WritePlain(", ")
}
if err := role.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore RevokeRoleStmt.Roles[%d]", i)
}
}
ctx.WriteKeyWord(" FROM ")
for i, v := range n.Users {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore RevokeRoleStmt.Users[%d]", i)
}
}
return nil
}
// Accept implements Node Accept interface.
func (n *RevokeRoleStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*RevokeRoleStmt)
return v.Leave(n)
}
// GrantStmt is the struct for GRANT statement.
type GrantStmt struct {
stmtNode
Privs []*PrivElem
ObjectType ObjectTypeType
Level *GrantLevel
Users []*UserSpec
WithGrant bool
}
// Restore implements Node interface.
func (n *GrantStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("GRANT ")
for i, v := range n.Privs {
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 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")
}
ctx.WriteKeyWord(" TO ")
for i, v := range n.Users {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore GrantStmt.Users[%d]", i)
}
}
if n.WithGrant {
ctx.WriteKeyWord(" WITH GRANT OPTION")
}
return nil
}
// SecureText implements SensitiveStatement interface.
func (n *GrantStmt) SecureText() string {
text := n.text
// Filter "identified by xxx" because it would expose password information.
idx := strings.Index(strings.ToLower(text), "identified")
if idx > 0 {
text = text[:idx]
}
return text
}
// Accept implements Node Accept interface.
func (n *GrantStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*GrantStmt)
for i, val := range n.Privs {
node, ok := val.Accept(v)
if !ok {
return n, false
}
n.Privs[i] = node.(*PrivElem)
}
return v.Leave(n)
}
// GrantRoleStmt is the struct for GRANT TO statement.
type GrantRoleStmt struct {
stmtNode
Roles []*auth.RoleIdentity
Users []*auth.UserIdentity
}
// Accept implements Node Accept interface.
func (n *GrantRoleStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*GrantRoleStmt)
return v.Leave(n)
}
// Restore implements Node interface.
func (n *GrantRoleStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("GRANT ")
if len(n.Roles) > 0 {
for i, role := range n.Roles {
if i != 0 {
ctx.WritePlain(", ")
}
if err := role.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore GrantRoleStmt.Roles[%d]", i)
}
}
}
ctx.WriteKeyWord(" TO ")
for i, v := range n.Users {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore GrantStmt.Users[%d]", i)
}
}
return nil
}
// SecureText implements SensitiveStatement interface.
func (n *GrantRoleStmt) SecureText() string {
text := n.text
// Filter "identified by xxx" because it would expose password information.
idx := strings.Index(strings.ToLower(text), "identified")
if idx > 0 {
text = text[:idx]
}
return text
}
// Ident is the table identifier composed of schema name and table name.
type Ident struct {
Schema model.CIStr
Name model.CIStr
}
// String implements fmt.Stringer interface.
func (i Ident) String() string {
if i.Schema.O == "" {
return i.Name.O
}
return fmt.Sprintf("%s.%s", i.Schema, i.Name)
}
// SelectStmtOpts wrap around select hints and switches
type SelectStmtOpts struct {
Distinct bool
SQLBigResult bool
SQLBufferResult bool
SQLCache bool
SQLSmallResult bool
CalcFoundRows bool
StraightJoin bool
Priority mysql.PriorityEnum
TableHints []*TableOptimizerHint
}
// TableOptimizerHint is Table level optimizer hint
type TableOptimizerHint struct {
node
// HintName is the name or alias of the table(s) which the hint will affect.
// Table hints has no schema info
// It allows only table name or alias (if table has an alias)
HintName model.CIStr
// HintData is the payload of the hint. The actual type of this field
// is defined differently as according `HintName`. Define as following:
//
// Statement Execution Time Optimizer Hints
// See https://dev.mysql.com/doc/refman/5.7/en/optimizer-hints.html#optimizer-hints-execution-time
// - MAX_EXECUTION_TIME => uint64
// - MEMORY_QUOTA => int64
// - QUERY_TYPE => model.CIStr
//
// Time Range is used to hint the time range of inspection tables
// e.g: select /*+ time_range('','') */ * from information_schema.inspection_result.
// - TIME_RANGE => ast.HintTimeRange
// - READ_FROM_STORAGE => model.CIStr
// - USE_TOJA => bool
HintData interface{}
// QBName is the default effective query block of this hint.
QBName model.CIStr
Tables []HintTable
Indexes []model.CIStr
// Statement Execution Time Optimizer Hints
// See https://dev.mysql.com/doc/refman/5.7/en/optimizer-hints.html#optimizer-hints-execution-time
MaxExecutionTime uint64
}
// HintTimeRange is the payload of `TIME_RANGE` hint
type HintTimeRange struct {
From string
To string
}
// HintTable is table in the hint. It may have query block info.
type HintTable struct {
DBName model.CIStr
TableName model.CIStr
QBName model.CIStr
}
func (ht *HintTable) Restore(ctx *format.RestoreCtx) {
if ht.DBName.L != "" {
ctx.WriteName(ht.DBName.String())
ctx.WriteKeyWord(".")
}
ctx.WriteName(ht.TableName.String())
if ht.QBName.L != "" {
ctx.WriteKeyWord("@")
ctx.WriteName(ht.QBName.String())
}
}
// Restore implements Node interface.
func (n *TableOptimizerHint) Restore(ctx *format.RestoreCtx) error {
ctx.WriteKeyWord(n.HintName.String())
ctx.WritePlain("(")
if n.QBName.L != "" {
if n.HintName.L != "qb_name" {
ctx.WriteKeyWord("@")
}
ctx.WriteName(n.QBName.String())
}
// Hints without args except query block.
switch n.HintName.L {
case "hash_agg", "stream_agg", "agg_to_cop", "read_consistent_replica", "no_index_merge", "qb_name", "ignore_plan_cache":
ctx.WritePlain(")")
return nil
}
if n.QBName.L != "" {
ctx.WritePlain(" ")
}
// Hints with args except query block.
switch n.HintName.L {
case "max_execution_time":
ctx.WritePlainf("%d", n.HintData.(uint64))
case "tidb_hj", "tidb_smj", "tidb_inlj", "hash_join", "merge_join", "inl_join":
for i, table := range n.Tables {
if i != 0 {
ctx.WritePlain(", ")
}
table.Restore(ctx)
}
case "use_index", "ignore_index", "use_index_merge":
n.Tables[0].Restore(ctx)
ctx.WritePlain(" ")
for i, index := range n.Indexes {
if i != 0 {
ctx.WritePlain(", ")
}
ctx.WriteName(index.String())
}
case "use_toja", "use_cascades":
if n.HintData.(bool) {
ctx.WritePlain("TRUE")
} else {
ctx.WritePlain("FALSE")
}
case "query_type":
ctx.WriteKeyWord(n.HintData.(model.CIStr).String())
case "memory_quota":
ctx.WritePlainf("%d MB", n.HintData.(int64)/1024/1024)
case "read_from_storage":
ctx.WriteKeyWord(n.HintData.(model.CIStr).String())
for i, table := range n.Tables {
if i == 0 {
ctx.WritePlain("[")
}
table.Restore(ctx)
if i == len(n.Tables)-1 {
ctx.WritePlain("]")
} else {
ctx.WritePlain(", ")
}
}
case "time_range":
hintData := n.HintData.(HintTimeRange)
ctx.WriteString(hintData.From)
ctx.WritePlain(", ")
ctx.WriteString(hintData.To)
}
ctx.WritePlain(")")
return nil
}
// Accept implements Node Accept interface.
func (n *TableOptimizerHint) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*TableOptimizerHint)
return v.Leave(n)
}
// NewDecimal creates a types.Decimal value, it's provided by parser driver.
var NewDecimal func(string) (interface{}, error)
// NewHexLiteral creates a types.HexLiteral value, it's provided by parser driver.
var NewHexLiteral func(string) (interface{}, error)
// NewBitLiteral creates a types.BitLiteral value, it's provided by parser driver.
var NewBitLiteral func(string) (interface{}, error)

Комментарий ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/hanchuanchuan-goInception.git
git@gitlife.ru:oschina-mirror/hanchuanchuan-goInception.git
oschina-mirror
hanchuanchuan-goInception
hanchuanchuan-goInception
v1.2.5