github.com/XiaoMi/Gaea@v1.2.5/parser/ast/misc.go (about) 1 // Copyright 2015 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package ast 15 16 import ( 17 "bytes" 18 "fmt" 19 "strings" 20 21 "github.com/pingcap/errors" 22 23 "github.com/XiaoMi/Gaea/mysql" 24 "github.com/XiaoMi/Gaea/parser/auth" 25 "github.com/XiaoMi/Gaea/parser/format" 26 "github.com/XiaoMi/Gaea/parser/model" 27 ) 28 29 var ( 30 _ StmtNode = &AdminStmt{} 31 _ StmtNode = &AlterUserStmt{} 32 _ StmtNode = &BeginStmt{} 33 _ StmtNode = &BinlogStmt{} 34 _ StmtNode = &CommitStmt{} 35 _ StmtNode = &CreateUserStmt{} 36 _ StmtNode = &DeallocateStmt{} 37 _ StmtNode = &DoStmt{} 38 _ StmtNode = &ExecuteStmt{} 39 _ StmtNode = &ExplainStmt{} 40 _ StmtNode = &GrantStmt{} 41 _ StmtNode = &PrepareStmt{} 42 _ StmtNode = &RollbackStmt{} 43 _ StmtNode = &SetPwdStmt{} 44 _ StmtNode = &SetStmt{} 45 _ StmtNode = &UseStmt{} 46 _ StmtNode = &FlushStmt{} 47 _ StmtNode = &KillStmt{} 48 _ StmtNode = &CreateBindingStmt{} 49 _ StmtNode = &DropBindingStmt{} 50 _ StmtNode = &SavepointStmt{} 51 52 _ Node = &PrivElem{} 53 _ Node = &VariableAssignment{} 54 ) 55 56 // Isolation level constants. 57 const ( 58 ReadCommitted = "READ-COMMITTED" 59 ReadUncommitted = "READ-UNCOMMITTED" 60 Serializable = "SERIALIZABLE" 61 RepeatableRead = "REPEATABLE-READ" 62 63 // Valid formats for explain statement. 64 ExplainFormatROW = "row" 65 ExplainFormatDOT = "dot" 66 ) 67 68 var ( 69 // ExplainFormats stores the valid formats for explain statement, used by validator. 70 ExplainFormats = []string{ 71 ExplainFormatROW, 72 ExplainFormatDOT, 73 } 74 ) 75 76 // TypeOpt is used for parsing data type option from SQL. 77 type TypeOpt struct { 78 IsUnsigned bool 79 IsZerofill bool 80 } 81 82 // FloatOpt is used for parsing floating-point type option from SQL. 83 // See http://dev.mysql.com/doc/refman/5.7/en/floating-point-types.html 84 type FloatOpt struct { 85 Flen int 86 Decimal int 87 } 88 89 // AuthOption is used for parsing create use statement. 90 type AuthOption struct { 91 // ByAuthString set as true, if AuthString is used for authorization. Otherwise, authorization is done by HashString. 92 ByAuthString bool 93 AuthString string 94 HashString string 95 // TODO: support auth_plugin 96 } 97 98 // Restore implements Node interface. 99 func (n *AuthOption) Restore(ctx *format.RestoreCtx) error { 100 ctx.WriteKeyWord("IDENTIFIED BY ") 101 if n.ByAuthString { 102 ctx.WriteString(n.AuthString) 103 } else { 104 ctx.WriteKeyWord("PASSWORD ") 105 ctx.WriteString(n.HashString) 106 } 107 return nil 108 } 109 110 // TraceStmt is a statement to trace what sql actually does at background. 111 type TraceStmt struct { 112 stmtNode 113 114 Stmt StmtNode 115 Format string 116 } 117 118 // Restore implements Node interface. 119 func (n *TraceStmt) Restore(ctx *format.RestoreCtx) error { 120 ctx.WriteKeyWord("TRACE ") 121 if n.Format != "json" { 122 ctx.WriteKeyWord("FORMAT") 123 ctx.WritePlain(" = ") 124 ctx.WriteString(n.Format) 125 ctx.WritePlain(" ") 126 } 127 if err := n.Stmt.Restore(ctx); err != nil { 128 return errors.Annotate(err, "An error occurred while restore TraceStmt.Stmt") 129 } 130 return nil 131 } 132 133 // Accept implements Node Accept interface. 134 func (n *TraceStmt) Accept(v Visitor) (Node, bool) { 135 newNode, skipChildren := v.Enter(n) 136 if skipChildren { 137 return v.Leave(newNode) 138 } 139 n = newNode.(*TraceStmt) 140 node, ok := n.Stmt.Accept(v) 141 if !ok { 142 return n, false 143 } 144 n.Stmt = node.(DMLNode) 145 return v.Leave(n) 146 } 147 148 // ExplainStmt is a statement to provide information about how is SQL statement executed 149 // or get columns information in a table. 150 // See https://dev.mysql.com/doc/refman/5.7/en/explain.html 151 type ExplainStmt struct { 152 stmtNode 153 154 Stmt StmtNode 155 Format string 156 Analyze bool 157 } 158 159 // Restore implements Node interface. 160 func (n *ExplainStmt) Restore(ctx *format.RestoreCtx) error { 161 if showStmt, ok := n.Stmt.(*ShowStmt); ok { 162 ctx.WriteKeyWord("DESC ") 163 if err := showStmt.Table.Restore(ctx); err != nil { 164 return errors.Annotate(err, "An error occurred while restore ExplainStmt.ShowStmt.Table") 165 } 166 if showStmt.Column != nil { 167 ctx.WritePlain(" ") 168 if err := showStmt.Column.Restore(ctx); err != nil { 169 return errors.Annotate(err, "An error occurred while restore ExplainStmt.ShowStmt.Column") 170 } 171 } 172 return nil 173 } 174 ctx.WriteKeyWord("EXPLAIN ") 175 if n.Analyze { 176 ctx.WriteKeyWord("ANALYZE ") 177 } else { 178 ctx.WriteKeyWord("FORMAT ") 179 ctx.WritePlain("= ") 180 ctx.WriteString(n.Format) 181 ctx.WritePlain(" ") 182 } 183 if err := n.Stmt.Restore(ctx); err != nil { 184 return errors.Annotate(err, "An error occurred while restore ExplainStmt.Stmt") 185 } 186 return nil 187 } 188 189 // Accept implements Node Accept interface. 190 func (n *ExplainStmt) Accept(v Visitor) (Node, bool) { 191 newNode, skipChildren := v.Enter(n) 192 if skipChildren { 193 return v.Leave(newNode) 194 } 195 n = newNode.(*ExplainStmt) 196 node, ok := n.Stmt.Accept(v) 197 if !ok { 198 return n, false 199 } 200 n.Stmt = node.(DMLNode) 201 return v.Leave(n) 202 } 203 204 // PrepareStmt is a statement to prepares a SQL statement which contains placeholders, 205 // and it is executed with ExecuteStmt and released with DeallocateStmt. 206 // See https://dev.mysql.com/doc/refman/5.7/en/prepare.html 207 type PrepareStmt struct { 208 stmtNode 209 210 Name string 211 SQLText string 212 SQLVar *VariableExpr 213 } 214 215 // Restore implements Node interface. 216 func (n *PrepareStmt) Restore(ctx *format.RestoreCtx) error { 217 ctx.WriteKeyWord("PREPARE ") 218 ctx.WriteName(n.Name) 219 ctx.WriteKeyWord(" FROM ") 220 if n.SQLText != "" { 221 ctx.WriteString(n.SQLText) 222 return nil 223 } 224 if n.SQLVar != nil { 225 if err := n.SQLVar.Restore(ctx); err != nil { 226 return errors.Annotate(err, "An error occurred while restore PrepareStmt.SQLVar") 227 } 228 return nil 229 } 230 return errors.New("An error occurred while restore PrepareStmt") 231 } 232 233 // Accept implements Node Accept interface. 234 func (n *PrepareStmt) Accept(v Visitor) (Node, bool) { 235 newNode, skipChildren := v.Enter(n) 236 if skipChildren { 237 return v.Leave(newNode) 238 } 239 n = newNode.(*PrepareStmt) 240 if n.SQLVar != nil { 241 node, ok := n.SQLVar.Accept(v) 242 if !ok { 243 return n, false 244 } 245 n.SQLVar = node.(*VariableExpr) 246 } 247 return v.Leave(n) 248 } 249 250 // DeallocateStmt is a statement to release PreparedStmt. 251 // See https://dev.mysql.com/doc/refman/5.7/en/deallocate-prepare.html 252 type DeallocateStmt struct { 253 stmtNode 254 255 Name string 256 } 257 258 // Restore implements Node interface. 259 func (n *DeallocateStmt) Restore(ctx *format.RestoreCtx) error { 260 ctx.WriteKeyWord("DEALLOCATE PREPARE ") 261 ctx.WriteName(n.Name) 262 return nil 263 } 264 265 // Accept implements Node Accept interface. 266 func (n *DeallocateStmt) Accept(v Visitor) (Node, bool) { 267 newNode, skipChildren := v.Enter(n) 268 if skipChildren { 269 return v.Leave(newNode) 270 } 271 n = newNode.(*DeallocateStmt) 272 return v.Leave(n) 273 } 274 275 // Prepared represents a prepared statement. 276 type Prepared struct { 277 Stmt StmtNode 278 Params []ParamMarkerExpr 279 SchemaVersion int64 280 UseCache bool 281 } 282 283 // ExecuteStmt is a statement to execute PreparedStmt. 284 // See https://dev.mysql.com/doc/refman/5.7/en/execute.html 285 type ExecuteStmt struct { 286 stmtNode 287 288 Name string 289 UsingVars []ExprNode 290 ExecID uint32 291 } 292 293 // Restore implements Node interface. 294 func (n *ExecuteStmt) Restore(ctx *format.RestoreCtx) error { 295 ctx.WriteKeyWord("EXECUTE ") 296 ctx.WriteName(n.Name) 297 if len(n.UsingVars) > 0 { 298 ctx.WriteKeyWord(" USING ") 299 for i, val := range n.UsingVars { 300 if i != 0 { 301 ctx.WritePlain(",") 302 } 303 if err := val.Restore(ctx); err != nil { 304 return errors.Annotatef(err, "An error occurred while restore ExecuteStmt.UsingVars index %d", i) 305 } 306 } 307 } 308 return nil 309 } 310 311 // Accept implements Node Accept interface. 312 func (n *ExecuteStmt) Accept(v Visitor) (Node, bool) { 313 newNode, skipChildren := v.Enter(n) 314 if skipChildren { 315 return v.Leave(newNode) 316 } 317 n = newNode.(*ExecuteStmt) 318 for i, val := range n.UsingVars { 319 node, ok := val.Accept(v) 320 if !ok { 321 return n, false 322 } 323 n.UsingVars[i] = node.(ExprNode) 324 } 325 return v.Leave(n) 326 } 327 328 // BeginStmt is a statement to start a new transaction. 329 // See https://dev.mysql.com/doc/refman/5.7/en/commit.html 330 type BeginStmt struct { 331 stmtNode 332 } 333 334 // Restore implements Node interface. 335 func (n *BeginStmt) Restore(ctx *format.RestoreCtx) error { 336 ctx.WriteKeyWord("START TRANSACTION") 337 return nil 338 } 339 340 // Accept implements Node Accept interface. 341 func (n *BeginStmt) Accept(v Visitor) (Node, bool) { 342 newNode, skipChildren := v.Enter(n) 343 if skipChildren { 344 return v.Leave(newNode) 345 } 346 n = newNode.(*BeginStmt) 347 return v.Leave(n) 348 } 349 350 // BinlogStmt is an internal-use statement. 351 // We just parse and ignore it. 352 // See http://dev.mysql.com/doc/refman/5.7/en/binlog.html 353 type BinlogStmt struct { 354 stmtNode 355 Str string 356 } 357 358 // Restore implements Node interface. 359 func (n *BinlogStmt) Restore(ctx *format.RestoreCtx) error { 360 ctx.WriteKeyWord("BINLOG ") 361 ctx.WriteString(n.Str) 362 return nil 363 } 364 365 // Accept implements Node Accept interface. 366 func (n *BinlogStmt) Accept(v Visitor) (Node, bool) { 367 newNode, skipChildren := v.Enter(n) 368 if skipChildren { 369 return v.Leave(newNode) 370 } 371 n = newNode.(*BinlogStmt) 372 return v.Leave(n) 373 } 374 375 // CommitStmt is a statement to commit the current transaction. 376 // See https://dev.mysql.com/doc/refman/5.7/en/commit.html 377 type CommitStmt struct { 378 stmtNode 379 } 380 381 // Restore implements Node interface. 382 func (n *CommitStmt) Restore(ctx *format.RestoreCtx) error { 383 ctx.WriteKeyWord("COMMIT") 384 return nil 385 } 386 387 // Accept implements Node Accept interface. 388 func (n *CommitStmt) Accept(v Visitor) (Node, bool) { 389 newNode, skipChildren := v.Enter(n) 390 if skipChildren { 391 return v.Leave(newNode) 392 } 393 n = newNode.(*CommitStmt) 394 return v.Leave(n) 395 } 396 397 // RollbackStmt is a statement to roll back the current transaction. 398 // See https://dev.mysql.com/doc/refman/5.7/en/commit.html 399 type RollbackStmt struct { 400 stmtNode 401 Savepoint string 402 } 403 404 // Restore implements Node interface. 405 func (n *RollbackStmt) Restore(ctx *format.RestoreCtx) error { 406 ctx.WriteKeyWord("ROLLBACK") 407 if n.Savepoint != "" { 408 ctx.WriteKeyWord(" TO SAVEPOINT ") 409 ctx.WritePlain(n.Savepoint) 410 } 411 return nil 412 } 413 414 // Accept implements Node Accept interface. 415 func (n *RollbackStmt) Accept(v Visitor) (Node, bool) { 416 newNode, skipChildren := v.Enter(n) 417 if skipChildren { 418 return v.Leave(newNode) 419 } 420 n = newNode.(*RollbackStmt) 421 return v.Leave(n) 422 } 423 424 type SavepointStmt struct { 425 stmtNode 426 Savepoint string 427 Release bool 428 } 429 430 // Restore implements Node interface. 431 func (n *SavepointStmt) Restore(ctx *format.RestoreCtx) error { 432 if n.Release { 433 ctx.WriteKeyWord("RELEASE ") 434 } 435 ctx.WriteKeyWord("SAVEPOINT ") 436 ctx.WritePlain(n.Savepoint) 437 return nil 438 } 439 440 // Accept implements Node Accept interface. 441 func (n *SavepointStmt) Accept(v Visitor) (Node, bool) { 442 newNode, skipChildren := v.Enter(n) 443 if skipChildren { 444 return v.Leave(newNode) 445 } 446 n = newNode.(*SavepointStmt) 447 return v.Leave(n) 448 } 449 450 // UseStmt is a statement to use the DBName database as the current database. 451 // See https://dev.mysql.com/doc/refman/5.7/en/use.html 452 type UseStmt struct { 453 stmtNode 454 455 DBName string 456 } 457 458 // Restore implements Node interface. 459 func (n *UseStmt) Restore(ctx *format.RestoreCtx) error { 460 ctx.WriteKeyWord("USE ") 461 ctx.WriteName(n.DBName) 462 return nil 463 } 464 465 // Accept implements Node Accept interface. 466 func (n *UseStmt) Accept(v Visitor) (Node, bool) { 467 newNode, skipChildren := v.Enter(n) 468 if skipChildren { 469 return v.Leave(newNode) 470 } 471 n = newNode.(*UseStmt) 472 return v.Leave(n) 473 } 474 475 const ( 476 // SetNames is the const for set names/charset stmt. 477 // If VariableAssignment.Name == Names, it should be set names/charset stmt. 478 SetNames = "SetNAMES" 479 ) 480 481 // VariableAssignment is a variable assignment struct. 482 type VariableAssignment struct { 483 node 484 Name string 485 Value ExprNode 486 IsGlobal bool 487 IsSystem bool 488 489 // ExtendValue is a way to store extended info. 490 // VariableAssignment should be able to store information for SetCharset/SetPWD Stmt. 491 // For SetCharsetStmt, Value is charset, ExtendValue is collation. 492 // TODO: Use SetStmt to implement set password statement. 493 ExtendValue ValueExpr 494 } 495 496 // Restore implements Node interface. 497 func (n *VariableAssignment) Restore(ctx *format.RestoreCtx) error { 498 if n.IsSystem { 499 ctx.WritePlain("@@") 500 if n.IsGlobal { 501 ctx.WriteKeyWord("GLOBAL") 502 } else { 503 ctx.WriteKeyWord("SESSION") 504 } 505 ctx.WritePlain(".") 506 } else if n.Name != SetNames { 507 ctx.WriteKeyWord("@") 508 } 509 if n.Name == SetNames { 510 ctx.WriteKeyWord("NAMES ") 511 } else { 512 ctx.WriteName(n.Name) 513 ctx.WritePlain("=") 514 } 515 if err := n.Value.Restore(ctx); err != nil { 516 return errors.Annotate(err, "An error occurred while restore VariableAssignment.Value") 517 } 518 if n.ExtendValue != nil { 519 ctx.WriteKeyWord(" COLLATE ") 520 if err := n.ExtendValue.Restore(ctx); err != nil { 521 return errors.Annotate(err, "An error occurred while restore VariableAssignment.ExtendValue") 522 } 523 } 524 return nil 525 } 526 527 // Accept implements Node interface. 528 func (n *VariableAssignment) Accept(v Visitor) (Node, bool) { 529 newNode, skipChildren := v.Enter(n) 530 if skipChildren { 531 return v.Leave(newNode) 532 } 533 n = newNode.(*VariableAssignment) 534 node, ok := n.Value.Accept(v) 535 if !ok { 536 return n, false 537 } 538 n.Value = node.(ExprNode) 539 return v.Leave(n) 540 } 541 542 // FlushStmtType is the type for FLUSH statement. 543 type FlushStmtType int 544 545 // Flush statement types. 546 const ( 547 FlushNone FlushStmtType = iota 548 FlushTables 549 FlushPrivileges 550 FlushStatus 551 FlushTiDBPlugin 552 ) 553 554 // FlushStmt is a statement to flush tables/privileges/optimizer costs and so on. 555 type FlushStmt struct { 556 stmtNode 557 558 Tp FlushStmtType // Privileges/Tables/... 559 NoWriteToBinLog bool 560 Tables []*TableName // For FlushTableStmt, if Tables is empty, it means flush all tables. 561 ReadLock bool 562 Plugins []string 563 } 564 565 // Restore implements Node interface. 566 func (n *FlushStmt) Restore(ctx *format.RestoreCtx) error { 567 ctx.WriteKeyWord("FLUSH ") 568 if n.NoWriteToBinLog { 569 ctx.WriteKeyWord("NO_WRITE_TO_BINLOG ") 570 } 571 switch n.Tp { 572 case FlushTables: 573 ctx.WriteKeyWord("TABLES") 574 for i, v := range n.Tables { 575 if i == 0 { 576 ctx.WritePlain(" ") 577 } else { 578 ctx.WritePlain(", ") 579 } 580 if err := v.Restore(ctx); err != nil { 581 return errors.Annotatef(err, "An error occurred while restore FlushStmt.Tables[%d]", i) 582 } 583 } 584 if n.ReadLock { 585 ctx.WriteKeyWord(" WITH READ LOCK") 586 } 587 case FlushPrivileges: 588 ctx.WriteKeyWord("PRIVILEGES") 589 case FlushStatus: 590 ctx.WriteKeyWord("STATUS") 591 case FlushTiDBPlugin: 592 ctx.WriteKeyWord("TIDB PLUGINS") 593 for i, v := range n.Plugins { 594 if i == 0 { 595 ctx.WritePlain(" ") 596 } else { 597 ctx.WritePlain(", ") 598 } 599 ctx.WritePlain(v) 600 } 601 default: 602 return errors.New("Unsupported type of FlushTables") 603 } 604 return nil 605 } 606 607 // Accept implements Node Accept interface. 608 func (n *FlushStmt) Accept(v Visitor) (Node, bool) { 609 newNode, skipChildren := v.Enter(n) 610 if skipChildren { 611 return v.Leave(newNode) 612 } 613 n = newNode.(*FlushStmt) 614 return v.Leave(n) 615 } 616 617 // KillStmt is a statement to kill a query or connection. 618 type KillStmt struct { 619 stmtNode 620 621 // Query indicates whether terminate a single query on this connection or the whole connection. 622 // If Query is true, terminates the statement the connection is currently executing, but leaves the connection itself intact. 623 // If Query is false, terminates the connection associated with the given ConnectionID, after terminating any statement the connection is executing. 624 Query bool 625 ConnectionID uint64 626 // TiDBExtension is used to indicate whether the user knows he is sending kill statement to the right tidb-server. 627 // When the SQL grammar is "KILL TIDB [CONNECTION | QUERY] connectionID", TiDBExtension will be set. 628 // It's a special grammar extension in TiDB. This extension exists because, when the connection is: 629 // client -> LVS proxy -> TiDB, and type Ctrl+C in client, the following action will be executed: 630 // new a connection; kill xxx; 631 // kill command may send to the wrong TiDB, because the exists of LVS proxy, and kill the wrong session. 632 // So, "KILL TIDB" grammar is introduced, and it REQUIRES DIRECT client -> TiDB TOPOLOGY. 633 // TODO: The standard KILL grammar will be supported once we have global connectionID. 634 TiDBExtension bool 635 } 636 637 // Restore implements Node interface. 638 func (n *KillStmt) Restore(ctx *format.RestoreCtx) error { 639 ctx.WriteKeyWord("KILL") 640 if n.TiDBExtension { 641 ctx.WriteKeyWord(" TIDB") 642 } 643 if n.Query { 644 ctx.WriteKeyWord(" QUERY") 645 } 646 ctx.WritePlainf(" %d", n.ConnectionID) 647 return nil 648 } 649 650 // Accept implements Node Accept interface. 651 func (n *KillStmt) Accept(v Visitor) (Node, bool) { 652 newNode, skipChildren := v.Enter(n) 653 if skipChildren { 654 return v.Leave(newNode) 655 } 656 n = newNode.(*KillStmt) 657 return v.Leave(n) 658 } 659 660 // SetStmt is the statement to set variables. 661 type SetStmt struct { 662 stmtNode 663 // Variables is the list of variable assignment. 664 Variables []*VariableAssignment 665 } 666 667 // Restore implements Node interface. 668 func (n *SetStmt) Restore(ctx *format.RestoreCtx) error { 669 ctx.WriteKeyWord("SET ") 670 for i, v := range n.Variables { 671 if i != 0 { 672 ctx.WritePlain(", ") 673 } 674 if err := v.Restore(ctx); err != nil { 675 return errors.Annotatef(err, "An error occurred while restore SetStmt.Variables[%d]", i) 676 } 677 } 678 return nil 679 } 680 681 // Accept implements Node Accept interface. 682 func (n *SetStmt) Accept(v Visitor) (Node, bool) { 683 newNode, skipChildren := v.Enter(n) 684 if skipChildren { 685 return v.Leave(newNode) 686 } 687 n = newNode.(*SetStmt) 688 for i, val := range n.Variables { 689 node, ok := val.Accept(v) 690 if !ok { 691 return n, false 692 } 693 n.Variables[i] = node.(*VariableAssignment) 694 } 695 return v.Leave(n) 696 } 697 698 /* 699 // SetCharsetStmt is a statement to assign values to character and collation variables. 700 // See https://dev.mysql.com/doc/refman/5.7/en/set-statement.html 701 type SetCharsetStmt struct { 702 stmtNode 703 704 Charset string 705 Collate string 706 } 707 708 // Accept implements Node Accept interface. 709 func (n *SetCharsetStmt) Accept(v Visitor) (Node, bool) { 710 newNode, skipChildren := v.Enter(n) 711 if skipChildren { 712 return v.Leave(newNode) 713 } 714 n = newNode.(*SetCharsetStmt) 715 return v.Leave(n) 716 } 717 */ 718 719 // SetPwdStmt is a statement to assign a password to user account. 720 // See https://dev.mysql.com/doc/refman/5.7/en/set-password.html 721 type SetPwdStmt struct { 722 stmtNode 723 724 User *auth.UserIdentity 725 Password string 726 } 727 728 // Restore implements Node interface. 729 func (n *SetPwdStmt) Restore(ctx *format.RestoreCtx) error { 730 ctx.WriteKeyWord("SET PASSWORD") 731 if n.User != nil { 732 ctx.WriteKeyWord(" FOR ") 733 if err := n.User.Restore(ctx); err != nil { 734 return errors.Annotate(err, "An error occurred while restore SetPwdStmt.User") 735 } 736 } 737 ctx.WritePlain("=") 738 ctx.WriteString(n.Password) 739 return nil 740 } 741 742 // SecureText implements SensitiveStatement interface. 743 func (n *SetPwdStmt) SecureText() string { 744 return fmt.Sprintf("set password for user %s", n.User) 745 } 746 747 // Accept implements Node Accept interface. 748 func (n *SetPwdStmt) Accept(v Visitor) (Node, bool) { 749 newNode, skipChildren := v.Enter(n) 750 if skipChildren { 751 return v.Leave(newNode) 752 } 753 n = newNode.(*SetPwdStmt) 754 return v.Leave(n) 755 } 756 757 // UserSpec is used for parsing create user statement. 758 type UserSpec struct { 759 User *auth.UserIdentity 760 AuthOpt *AuthOption 761 IsRole bool 762 } 763 764 // Restore implements Node interface. 765 func (n *UserSpec) Restore(ctx *format.RestoreCtx) error { 766 if err := n.User.Restore(ctx); err != nil { 767 return errors.Annotate(err, "An error occurred while restore UserSpec.User") 768 } 769 if n.AuthOpt != nil { 770 ctx.WritePlain(" ") 771 if err := n.AuthOpt.Restore(ctx); err != nil { 772 return errors.Annotate(err, "An error occurred while restore UserSpec.AuthOpt") 773 } 774 } 775 return nil 776 } 777 778 // SecurityString formats the UserSpec without password information. 779 func (n *UserSpec) SecurityString() string { 780 withPassword := false 781 if opt := n.AuthOpt; opt != nil { 782 if len(opt.AuthString) > 0 || len(opt.HashString) > 0 { 783 withPassword = true 784 } 785 } 786 if withPassword { 787 return fmt.Sprintf("{%s password = ***}", n.User) 788 } 789 return n.User.String() 790 } 791 792 // EncodedPassword returns the encoded password (which is the real data mysql.user). 793 // The boolean value indicates input's password format is legal or not. 794 func (n *UserSpec) EncodedPassword() (string, bool) { 795 if n.AuthOpt == nil { 796 return "", true 797 } 798 799 opt := n.AuthOpt 800 if opt.ByAuthString { 801 return auth.EncodePassword(opt.AuthString), true 802 } 803 804 // Not a legal password string. 805 if len(opt.HashString) != 41 || !strings.HasPrefix(opt.HashString, "*") { 806 return "", false 807 } 808 return opt.HashString, true 809 } 810 811 // CreateUserStmt creates user account. 812 // See https://dev.mysql.com/doc/refman/5.7/en/create-user.html 813 type CreateUserStmt struct { 814 stmtNode 815 816 IsCreateRole bool 817 IfNotExists bool 818 Specs []*UserSpec 819 } 820 821 // Restore implements Node interface. 822 func (n *CreateUserStmt) Restore(ctx *format.RestoreCtx) error { 823 if n.IsCreateRole { 824 ctx.WriteKeyWord("CREATE ROLE ") 825 } else { 826 ctx.WriteKeyWord("CREATE USER ") 827 } 828 if n.IfNotExists { 829 ctx.WriteKeyWord("IF NOT EXISTS ") 830 } 831 for i, v := range n.Specs { 832 if i != 0 { 833 ctx.WritePlain(", ") 834 } 835 if err := v.Restore(ctx); err != nil { 836 return errors.Annotatef(err, "An error occurred while restore CreateUserStmt.Specs[%d]", i) 837 } 838 } 839 return nil 840 } 841 842 // Accept implements Node Accept interface. 843 func (n *CreateUserStmt) Accept(v Visitor) (Node, bool) { 844 newNode, skipChildren := v.Enter(n) 845 if skipChildren { 846 return v.Leave(newNode) 847 } 848 n = newNode.(*CreateUserStmt) 849 return v.Leave(n) 850 } 851 852 // SecureText implements SensitiveStatement interface. 853 func (n *CreateUserStmt) SecureText() string { 854 var buf bytes.Buffer 855 buf.WriteString("create user") 856 for _, user := range n.Specs { 857 buf.WriteString(" ") 858 buf.WriteString(user.SecurityString()) 859 } 860 return buf.String() 861 } 862 863 // AlterUserStmt modifies user account. 864 // See https://dev.mysql.com/doc/refman/5.7/en/alter-user.html 865 type AlterUserStmt struct { 866 stmtNode 867 868 IfExists bool 869 CurrentAuth *AuthOption 870 Specs []*UserSpec 871 } 872 873 // Restore implements Node interface. 874 func (n *AlterUserStmt) Restore(ctx *format.RestoreCtx) error { 875 ctx.WriteKeyWord("ALTER USER ") 876 if n.IfExists { 877 ctx.WriteKeyWord("IF EXISTS ") 878 } 879 if n.CurrentAuth != nil { 880 ctx.WriteKeyWord("USER") 881 ctx.WritePlain("() ") 882 if err := n.CurrentAuth.Restore(ctx); err != nil { 883 return errors.Annotate(err, "An error occurred while restore AlterUserStmt.CurrentAuth") 884 } 885 } 886 for i, v := range n.Specs { 887 if i != 0 { 888 ctx.WritePlain(", ") 889 } 890 if err := v.Restore(ctx); err != nil { 891 return errors.Annotatef(err, "An error occurred while restore AlterUserStmt.Specs[%d]", i) 892 } 893 } 894 return nil 895 } 896 897 // SecureText implements SensitiveStatement interface. 898 func (n *AlterUserStmt) SecureText() string { 899 var buf bytes.Buffer 900 buf.WriteString("alter user") 901 for _, user := range n.Specs { 902 buf.WriteString(" ") 903 buf.WriteString(user.SecurityString()) 904 } 905 return buf.String() 906 } 907 908 // Accept implements Node Accept interface. 909 func (n *AlterUserStmt) Accept(v Visitor) (Node, bool) { 910 newNode, skipChildren := v.Enter(n) 911 if skipChildren { 912 return v.Leave(newNode) 913 } 914 n = newNode.(*AlterUserStmt) 915 return v.Leave(n) 916 } 917 918 // DropUserStmt creates user account. 919 // See http://dev.mysql.com/doc/refman/5.7/en/drop-user.html 920 type DropUserStmt struct { 921 stmtNode 922 923 IfExists bool 924 UserList []*auth.UserIdentity 925 } 926 927 // Restore implements Node interface. 928 func (n *DropUserStmt) Restore(ctx *format.RestoreCtx) error { 929 ctx.WriteKeyWord("DROP USER ") 930 if n.IfExists { 931 ctx.WriteKeyWord("IF EXISTS ") 932 } 933 for i, v := range n.UserList { 934 if i != 0 { 935 ctx.WritePlain(", ") 936 } 937 if err := v.Restore(ctx); err != nil { 938 return errors.Annotatef(err, "An error occurred while restore DropUserStmt.UserList[%d]", i) 939 } 940 } 941 return nil 942 } 943 944 // Accept implements Node Accept interface. 945 func (n *DropUserStmt) Accept(v Visitor) (Node, bool) { 946 newNode, skipChildren := v.Enter(n) 947 if skipChildren { 948 return v.Leave(newNode) 949 } 950 n = newNode.(*DropUserStmt) 951 return v.Leave(n) 952 } 953 954 // CreateBindingStmt creates sql binding hint. 955 type CreateBindingStmt struct { 956 stmtNode 957 958 GlobalScope bool 959 OriginSel StmtNode 960 HintedSel StmtNode 961 } 962 963 // Restore CreateBindingStmt restore 964 func (n *CreateBindingStmt) Restore(ctx *format.RestoreCtx) error { 965 ctx.WriteKeyWord("CREATE ") 966 if n.GlobalScope { 967 ctx.WriteKeyWord("GLOBAL ") 968 } else { 969 ctx.WriteKeyWord("SESSION ") 970 } 971 ctx.WriteKeyWord("BINDING FOR ") 972 if err := n.OriginSel.Restore(ctx); err != nil { 973 return errors.Trace(err) 974 } 975 ctx.WriteKeyWord(" USING ") 976 if err := n.HintedSel.Restore(ctx); err != nil { 977 return errors.Trace(err) 978 } 979 return nil 980 } 981 982 // Accept for visit CreateBindingStmt 983 func (n *CreateBindingStmt) Accept(v Visitor) (Node, bool) { 984 newNode, skipChildren := v.Enter(n) 985 if skipChildren { 986 return v.Leave(newNode) 987 } 988 n = newNode.(*CreateBindingStmt) 989 selnode, ok := n.OriginSel.Accept(v) 990 if !ok { 991 return n, false 992 } 993 n.OriginSel = selnode.(*SelectStmt) 994 hintedSelnode, ok := n.HintedSel.Accept(v) 995 if !ok { 996 return n, false 997 } 998 n.HintedSel = hintedSelnode.(*SelectStmt) 999 return v.Leave(n) 1000 } 1001 1002 // DropBindingStmt deletes sql binding hint. 1003 type DropBindingStmt struct { 1004 stmtNode 1005 1006 GlobalScope bool 1007 OriginSel StmtNode 1008 } 1009 1010 // Restore restore DropBindingStmt 1011 func (n *DropBindingStmt) Restore(ctx *format.RestoreCtx) error { 1012 return errors.New("Not implemented") 1013 } 1014 1015 // Accept DropBindingStmt for visit DropBindingStmt 1016 func (n *DropBindingStmt) Accept(v Visitor) (Node, bool) { 1017 newNode, skipChildren := v.Enter(n) 1018 if skipChildren { 1019 return v.Leave(newNode) 1020 } 1021 n = newNode.(*DropBindingStmt) 1022 selnode, ok := n.OriginSel.Accept(v) 1023 if !ok { 1024 return n, false 1025 } 1026 n.OriginSel = selnode.(*SelectStmt) 1027 return v.Leave(n) 1028 } 1029 1030 // DoStmt is the struct for DO statement. 1031 type DoStmt struct { 1032 stmtNode 1033 1034 Exprs []ExprNode 1035 } 1036 1037 // Restore implements Node interface. 1038 func (n *DoStmt) Restore(ctx *format.RestoreCtx) error { 1039 ctx.WriteKeyWord("DO ") 1040 for i, v := range n.Exprs { 1041 if i != 0 { 1042 ctx.WritePlain(", ") 1043 } 1044 if err := v.Restore(ctx); err != nil { 1045 return errors.Annotatef(err, "An error occurred while restore DoStmt.Exprs[%d]", i) 1046 } 1047 } 1048 return nil 1049 } 1050 1051 // Accept implements Node Accept interface. 1052 func (n *DoStmt) Accept(v Visitor) (Node, bool) { 1053 newNode, skipChildren := v.Enter(n) 1054 if skipChildren { 1055 return v.Leave(newNode) 1056 } 1057 n = newNode.(*DoStmt) 1058 for i, val := range n.Exprs { 1059 node, ok := val.Accept(v) 1060 if !ok { 1061 return n, false 1062 } 1063 n.Exprs[i] = node.(ExprNode) 1064 } 1065 return v.Leave(n) 1066 } 1067 1068 // AdminStmtType is the type for admin statement. 1069 type AdminStmtType int 1070 1071 // Admin statement types. 1072 const ( 1073 AdminShowDDL = iota + 1 1074 AdminCheckTable 1075 AdminShowDDLJobs 1076 AdminCancelDDLJobs 1077 AdminCheckIndex 1078 AdminRecoverIndex 1079 AdminCleanupIndex 1080 AdminCheckIndexRange 1081 AdminShowDDLJobQueries 1082 AdminChecksumTable 1083 AdminShowSlow 1084 AdminShowNextRowID 1085 AdminRestoreTable 1086 ) 1087 1088 // HandleRange represents a range where handle value >= Begin and < End. 1089 type HandleRange struct { 1090 Begin int64 1091 End int64 1092 } 1093 1094 // ShowSlowType defines the type for SlowSlow statement. 1095 type ShowSlowType int 1096 1097 const ( 1098 // ShowSlowTop is a ShowSlowType constant. 1099 ShowSlowTop ShowSlowType = iota 1100 // ShowSlowRecent is a ShowSlowType constant. 1101 ShowSlowRecent 1102 ) 1103 1104 // ShowSlowKind defines the kind for SlowSlow statement when the type is ShowSlowTop. 1105 type ShowSlowKind int 1106 1107 const ( 1108 // ShowSlowKindDefault is a ShowSlowKind constant. 1109 ShowSlowKindDefault ShowSlowKind = iota 1110 // ShowSlowKindInternal is a ShowSlowKind constant. 1111 ShowSlowKindInternal 1112 // ShowSlowKindAll is a ShowSlowKind constant. 1113 ShowSlowKindAll 1114 ) 1115 1116 // ShowSlow is used for the following command: 1117 // admin show slow top [ internal | all] N 1118 // admin show slow recent N 1119 type ShowSlow struct { 1120 Tp ShowSlowType 1121 Count uint64 1122 Kind ShowSlowKind 1123 } 1124 1125 // Restore implements Node interface. 1126 func (n *ShowSlow) Restore(ctx *format.RestoreCtx) error { 1127 switch n.Tp { 1128 case ShowSlowRecent: 1129 ctx.WriteKeyWord("RECENT ") 1130 case ShowSlowTop: 1131 ctx.WriteKeyWord("TOP ") 1132 switch n.Kind { 1133 case ShowSlowKindDefault: 1134 // do nothing 1135 case ShowSlowKindInternal: 1136 ctx.WriteKeyWord("INTERNAL ") 1137 case ShowSlowKindAll: 1138 ctx.WriteKeyWord("ALL ") 1139 default: 1140 return errors.New("Unsupported kind of ShowSlowTop") 1141 } 1142 default: 1143 return errors.New("Unsupported type of ShowSlow") 1144 } 1145 ctx.WritePlainf("%d", n.Count) 1146 return nil 1147 } 1148 1149 // AdminStmt is the struct for Admin statement. 1150 type AdminStmt struct { 1151 stmtNode 1152 1153 Tp AdminStmtType 1154 Index string 1155 Tables []*TableName 1156 JobIDs []int64 1157 JobNumber int64 1158 1159 HandleRanges []HandleRange 1160 ShowSlow *ShowSlow 1161 } 1162 1163 // Restore implements Node interface. 1164 func (n *AdminStmt) Restore(ctx *format.RestoreCtx) error { 1165 restoreTables := func() error { 1166 for i, v := range n.Tables { 1167 if i != 0 { 1168 ctx.WritePlain(", ") 1169 } 1170 if err := v.Restore(ctx); err != nil { 1171 return errors.Annotatef(err, "An error occurred while restore AdminStmt.Tables[%d]", i) 1172 } 1173 } 1174 return nil 1175 } 1176 restoreJobIDs := func() { 1177 for i, v := range n.JobIDs { 1178 if i != 0 { 1179 ctx.WritePlain(", ") 1180 } 1181 ctx.WritePlainf("%d", v) 1182 } 1183 } 1184 1185 ctx.WriteKeyWord("ADMIN ") 1186 switch n.Tp { 1187 case AdminShowDDL: 1188 ctx.WriteKeyWord("SHOW DDL") 1189 case AdminShowDDLJobs: 1190 ctx.WriteKeyWord("SHOW DDL JOBS") 1191 if n.JobNumber != 0 { 1192 ctx.WritePlainf(" %d", n.JobNumber) 1193 } 1194 case AdminShowNextRowID: 1195 ctx.WriteKeyWord("SHOW ") 1196 if err := restoreTables(); err != nil { 1197 return err 1198 } 1199 ctx.WriteKeyWord(" NEXT_ROW_ID") 1200 case AdminCheckTable: 1201 ctx.WriteKeyWord("CHECK TABLE ") 1202 if err := restoreTables(); err != nil { 1203 return err 1204 } 1205 case AdminCheckIndex: 1206 ctx.WriteKeyWord("CHECK INDEX ") 1207 if err := restoreTables(); err != nil { 1208 return err 1209 } 1210 ctx.WritePlainf(" %s", n.Index) 1211 case AdminRecoverIndex: 1212 ctx.WriteKeyWord("RECOVER INDEX ") 1213 if err := restoreTables(); err != nil { 1214 return err 1215 } 1216 ctx.WritePlainf(" %s", n.Index) 1217 case AdminRestoreTable: 1218 ctx.WriteKeyWord("RESTORE TABLE ") 1219 if n.JobIDs != nil { 1220 ctx.WriteKeyWord("BY JOB ") 1221 restoreJobIDs() 1222 } else { 1223 if err := restoreTables(); err != nil { 1224 return err 1225 } 1226 if n.JobNumber != 0 { 1227 ctx.WritePlainf(" %d", n.JobNumber) 1228 } 1229 } 1230 case AdminCleanupIndex: 1231 ctx.WriteKeyWord("CLEANUP INDEX ") 1232 if err := restoreTables(); err != nil { 1233 return err 1234 } 1235 ctx.WritePlainf(" %s", n.Index) 1236 case AdminCheckIndexRange: 1237 ctx.WriteKeyWord("CHECK INDEX ") 1238 if err := restoreTables(); err != nil { 1239 return err 1240 } 1241 ctx.WritePlainf(" %s", n.Index) 1242 if n.HandleRanges != nil { 1243 ctx.WritePlain(" ") 1244 for i, v := range n.HandleRanges { 1245 if i != 0 { 1246 ctx.WritePlain(", ") 1247 } 1248 ctx.WritePlainf("(%d,%d)", v.Begin, v.End) 1249 } 1250 } 1251 case AdminChecksumTable: 1252 ctx.WriteKeyWord("CHECKSUM TABLE ") 1253 if err := restoreTables(); err != nil { 1254 return err 1255 } 1256 case AdminCancelDDLJobs: 1257 ctx.WriteKeyWord("CANCEL DDL JOBS ") 1258 restoreJobIDs() 1259 case AdminShowDDLJobQueries: 1260 ctx.WriteKeyWord("SHOW DDL JOB QUERIES ") 1261 restoreJobIDs() 1262 case AdminShowSlow: 1263 ctx.WriteKeyWord("SHOW SLOW ") 1264 if err := n.ShowSlow.Restore(ctx); err != nil { 1265 return errors.Annotate(err, "An error occurred while restore AdminStmt.ShowSlow") 1266 } 1267 default: 1268 return errors.New("Unsupported AdminStmt type") 1269 } 1270 return nil 1271 } 1272 1273 // Accept implements Node Accept interface. 1274 func (n *AdminStmt) Accept(v Visitor) (Node, bool) { 1275 newNode, skipChildren := v.Enter(n) 1276 if skipChildren { 1277 return v.Leave(newNode) 1278 } 1279 1280 n = newNode.(*AdminStmt) 1281 for i, val := range n.Tables { 1282 node, ok := val.Accept(v) 1283 if !ok { 1284 return n, false 1285 } 1286 n.Tables[i] = node.(*TableName) 1287 } 1288 1289 return v.Leave(n) 1290 } 1291 1292 // PrivElem is the privilege type and optional column list. 1293 type PrivElem struct { 1294 node 1295 1296 Priv mysql.PrivilegeType 1297 Cols []*ColumnName 1298 } 1299 1300 // Restore implements Node interface. 1301 func (n *PrivElem) Restore(ctx *format.RestoreCtx) error { 1302 switch n.Priv { 1303 case 0: 1304 ctx.WritePlain("/* UNSUPPORTED TYPE */") 1305 case mysql.AllPriv: 1306 ctx.WriteKeyWord("ALL") 1307 case mysql.AlterPriv: 1308 ctx.WriteKeyWord("ALTER") 1309 case mysql.CreatePriv: 1310 ctx.WriteKeyWord("CREATE") 1311 case mysql.CreateUserPriv: 1312 ctx.WriteKeyWord("CREATE USER") 1313 case mysql.CreateRolePriv: 1314 ctx.WriteKeyWord("CREATE ROLE") 1315 case mysql.TriggerPriv: 1316 ctx.WriteKeyWord("TRIGGER") 1317 case mysql.DeletePriv: 1318 ctx.WriteKeyWord("DELETE") 1319 case mysql.DropPriv: 1320 ctx.WriteKeyWord("DROP") 1321 case mysql.ProcessPriv: 1322 ctx.WriteKeyWord("PROCESS") 1323 case mysql.ExecutePriv: 1324 ctx.WriteKeyWord("EXECUTE") 1325 case mysql.IndexPriv: 1326 ctx.WriteKeyWord("INDEX") 1327 case mysql.InsertPriv: 1328 ctx.WriteKeyWord("INSERT") 1329 case mysql.SelectPriv: 1330 ctx.WriteKeyWord("SELECT") 1331 case mysql.SuperPriv: 1332 ctx.WriteKeyWord("SUPER") 1333 case mysql.ShowDBPriv: 1334 ctx.WriteKeyWord("SHOW DATABASES") 1335 case mysql.UpdatePriv: 1336 ctx.WriteKeyWord("UPDATE") 1337 case mysql.GrantPriv: 1338 ctx.WriteKeyWord("GRANT OPTION") 1339 case mysql.ReferencesPriv: 1340 ctx.WriteKeyWord("REFERENCES") 1341 case mysql.CreateViewPriv: 1342 ctx.WriteKeyWord("CREATE VIEW") 1343 case mysql.ShowViewPriv: 1344 ctx.WriteKeyWord("SHOW VIEW") 1345 default: 1346 return errors.New("Undefined privilege type") 1347 } 1348 if n.Cols != nil { 1349 ctx.WritePlain(" (") 1350 for i, v := range n.Cols { 1351 if i != 0 { 1352 ctx.WritePlain(",") 1353 } 1354 if err := v.Restore(ctx); err != nil { 1355 return errors.Annotatef(err, "An error occurred while restore PrivElem.Cols[%d]", i) 1356 } 1357 } 1358 ctx.WritePlain(")") 1359 } 1360 return nil 1361 } 1362 1363 // Accept implements Node Accept interface. 1364 func (n *PrivElem) Accept(v Visitor) (Node, bool) { 1365 newNode, skipChildren := v.Enter(n) 1366 if skipChildren { 1367 return v.Leave(newNode) 1368 } 1369 n = newNode.(*PrivElem) 1370 for i, val := range n.Cols { 1371 node, ok := val.Accept(v) 1372 if !ok { 1373 return n, false 1374 } 1375 n.Cols[i] = node.(*ColumnName) 1376 } 1377 return v.Leave(n) 1378 } 1379 1380 // ObjectTypeType is the type for object type. 1381 type ObjectTypeType int 1382 1383 const ( 1384 // ObjectTypeNone is for empty object type. 1385 ObjectTypeNone ObjectTypeType = iota + 1 1386 // ObjectTypeTable means the following object is a table. 1387 ObjectTypeTable 1388 ) 1389 1390 // Restore implements Node interface. 1391 func (n ObjectTypeType) Restore(ctx *format.RestoreCtx) error { 1392 switch n { 1393 case ObjectTypeNone: 1394 // do nothing 1395 case ObjectTypeTable: 1396 ctx.WriteKeyWord("TABLE") 1397 default: 1398 return errors.New("Unsupported object type") 1399 } 1400 return nil 1401 } 1402 1403 // GrantLevelType is the type for grant level. 1404 type GrantLevelType int 1405 1406 const ( 1407 // GrantLevelNone is the dummy const for default value. 1408 GrantLevelNone GrantLevelType = iota + 1 1409 // GrantLevelGlobal means the privileges are administrative or apply to all databases on a given server. 1410 GrantLevelGlobal 1411 // GrantLevelDB means the privileges apply to all objects in a given database. 1412 GrantLevelDB 1413 // GrantLevelTable means the privileges apply to all columns in a given table. 1414 GrantLevelTable 1415 ) 1416 1417 // GrantLevel is used for store the privilege scope. 1418 type GrantLevel struct { 1419 Level GrantLevelType 1420 DBName string 1421 TableName string 1422 } 1423 1424 // Restore implements Node interface. 1425 func (n *GrantLevel) Restore(ctx *format.RestoreCtx) error { 1426 switch n.Level { 1427 case GrantLevelDB: 1428 if n.DBName == "" { 1429 ctx.WritePlain("*") 1430 } else { 1431 ctx.WriteName(n.DBName) 1432 ctx.WritePlain(".*") 1433 } 1434 case GrantLevelGlobal: 1435 ctx.WritePlain("*.*") 1436 case GrantLevelTable: 1437 if n.DBName != "" { 1438 ctx.WriteName(n.DBName) 1439 ctx.WritePlain(".") 1440 } 1441 ctx.WriteName(n.TableName) 1442 } 1443 return nil 1444 } 1445 1446 // RevokeStmt is the struct for REVOKE statement. 1447 type RevokeStmt struct { 1448 stmtNode 1449 1450 Privs []*PrivElem 1451 ObjectType ObjectTypeType 1452 Level *GrantLevel 1453 Users []*UserSpec 1454 } 1455 1456 // Restore implements Node interface. 1457 func (n *RevokeStmt) Restore(ctx *format.RestoreCtx) error { 1458 ctx.WriteKeyWord("REVOKE ") 1459 for i, v := range n.Privs { 1460 if i != 0 { 1461 ctx.WritePlain(", ") 1462 } 1463 if err := v.Restore(ctx); err != nil { 1464 return errors.Annotatef(err, "An error occurred while restore RevokeStmt.Privs[%d]", i) 1465 } 1466 } 1467 ctx.WriteKeyWord(" ON ") 1468 if n.ObjectType != ObjectTypeNone { 1469 if err := n.ObjectType.Restore(ctx); err != nil { 1470 return errors.Annotate(err, "An error occurred while restore RevokeStmt.ObjectType") 1471 } 1472 ctx.WritePlain(" ") 1473 } 1474 if err := n.Level.Restore(ctx); err != nil { 1475 return errors.Annotate(err, "An error occurred while restore RevokeStmt.Level") 1476 } 1477 ctx.WriteKeyWord(" FROM ") 1478 for i, v := range n.Users { 1479 if i != 0 { 1480 ctx.WritePlain(", ") 1481 } 1482 if err := v.Restore(ctx); err != nil { 1483 return errors.Annotatef(err, "An error occurred while restore RevokeStmt.Users[%d]", i) 1484 } 1485 } 1486 return nil 1487 } 1488 1489 // Accept implements Node Accept interface. 1490 func (n *RevokeStmt) Accept(v Visitor) (Node, bool) { 1491 newNode, skipChildren := v.Enter(n) 1492 if skipChildren { 1493 return v.Leave(newNode) 1494 } 1495 n = newNode.(*RevokeStmt) 1496 for i, val := range n.Privs { 1497 node, ok := val.Accept(v) 1498 if !ok { 1499 return n, false 1500 } 1501 n.Privs[i] = node.(*PrivElem) 1502 } 1503 return v.Leave(n) 1504 } 1505 1506 // GrantStmt is the struct for GRANT statement. 1507 type GrantStmt struct { 1508 stmtNode 1509 1510 Privs []*PrivElem 1511 ObjectType ObjectTypeType 1512 Level *GrantLevel 1513 Users []*UserSpec 1514 WithGrant bool 1515 } 1516 1517 // Restore implements Node interface. 1518 func (n *GrantStmt) Restore(ctx *format.RestoreCtx) error { 1519 ctx.WriteKeyWord("GRANT ") 1520 for i, v := range n.Privs { 1521 if i != 0 && v.Priv != 0 { 1522 ctx.WritePlain(", ") 1523 } else if v.Priv == 0 { 1524 ctx.WritePlain(" ") 1525 } 1526 if err := v.Restore(ctx); err != nil { 1527 return errors.Annotatef(err, "An error occurred while restore GrantStmt.Privs[%d]", i) 1528 } 1529 } 1530 ctx.WriteKeyWord(" ON ") 1531 if n.ObjectType != ObjectTypeNone { 1532 if err := n.ObjectType.Restore(ctx); err != nil { 1533 return errors.Annotate(err, "An error occurred while restore GrantStmt.ObjectType") 1534 } 1535 ctx.WritePlain(" ") 1536 } 1537 if err := n.Level.Restore(ctx); err != nil { 1538 return errors.Annotate(err, "An error occurred while restore GrantStmt.Level") 1539 } 1540 ctx.WriteKeyWord(" TO ") 1541 for i, v := range n.Users { 1542 if i != 0 { 1543 ctx.WritePlain(", ") 1544 } 1545 if err := v.Restore(ctx); err != nil { 1546 return errors.Annotatef(err, "An error occurred while restore GrantStmt.Users[%d]", i) 1547 } 1548 } 1549 if n.WithGrant { 1550 ctx.WriteKeyWord(" WITH GRANT OPTION") 1551 } 1552 return nil 1553 } 1554 1555 // SecureText implements SensitiveStatement interface. 1556 func (n *GrantStmt) SecureText() string { 1557 text := n.text 1558 // Filter "identified by xxx" because it would expose password information. 1559 idx := strings.Index(strings.ToLower(text), "identified") 1560 if idx > 0 { 1561 text = text[:idx] 1562 } 1563 return text 1564 } 1565 1566 // Accept implements Node Accept interface. 1567 func (n *GrantStmt) Accept(v Visitor) (Node, bool) { 1568 newNode, skipChildren := v.Enter(n) 1569 if skipChildren { 1570 return v.Leave(newNode) 1571 } 1572 n = newNode.(*GrantStmt) 1573 for i, val := range n.Privs { 1574 node, ok := val.Accept(v) 1575 if !ok { 1576 return n, false 1577 } 1578 n.Privs[i] = node.(*PrivElem) 1579 } 1580 return v.Leave(n) 1581 } 1582 1583 // Ident is the table identifier composed of schema name and table name. 1584 type Ident struct { 1585 Schema model.CIStr 1586 Name model.CIStr 1587 } 1588 1589 // String implements fmt.Stringer interface. 1590 func (i Ident) String() string { 1591 if i.Schema.O == "" { 1592 return i.Name.O 1593 } 1594 return fmt.Sprintf("%s.%s", i.Schema, i.Name) 1595 } 1596 1597 // SelectStmtOpts wrap around select hints and switches 1598 type SelectStmtOpts struct { 1599 Distinct bool 1600 SQLCache bool 1601 CalcFoundRows bool 1602 StraightJoin bool 1603 Priority mysql.PriorityEnum 1604 TableHints []*TableOptimizerHint 1605 } 1606 1607 // TableOptimizerHint is Table level optimizer hint 1608 type TableOptimizerHint struct { 1609 node 1610 // HintName is the name or alias of the table(s) which the hint will affect. 1611 // Table hints has no schema info 1612 // It allows only table name or alias (if table has an alias) 1613 HintName model.CIStr 1614 Tables []model.CIStr 1615 // Statement Execution Time Optimizer Hints 1616 // See https://dev.mysql.com/doc/refman/5.7/en/optimizer-hints.html#optimizer-hints-execution-time 1617 MaxExecutionTime uint64 1618 } 1619 1620 // Restore implements Node interface. 1621 func (n *TableOptimizerHint) Restore(ctx *format.RestoreCtx) error { 1622 ctx.WriteKeyWord(n.HintName.String()) 1623 ctx.WritePlain("(") 1624 if n.HintName.L == "max_execution_time" { 1625 ctx.WritePlainf("%d", n.MaxExecutionTime) 1626 } else { 1627 for i, table := range n.Tables { 1628 if i != 0 { 1629 ctx.WritePlain(", ") 1630 } 1631 ctx.WriteName(table.String()) 1632 } 1633 } 1634 ctx.WritePlain(")") 1635 return nil 1636 } 1637 1638 // Accept implements Node Accept interface. 1639 func (n *TableOptimizerHint) Accept(v Visitor) (Node, bool) { 1640 newNode, skipChildren := v.Enter(n) 1641 if skipChildren { 1642 return v.Leave(newNode) 1643 } 1644 n = newNode.(*TableOptimizerHint) 1645 return v.Leave(n) 1646 } 1647 1648 // NewDecimal creates a types.Decimal value, it's provided by parser driver. 1649 var NewDecimal func(string) (interface{}, error) 1650 1651 // NewHexLiteral creates a types.HexLiteral value, it's provided by parser driver. 1652 var NewHexLiteral func(string) (interface{}, error) 1653 1654 // NewBitLiteral creates a types.BitLiteral value, it's provided by parser driver. 1655 var NewBitLiteral func(string) (interface{}, error)