github.com/pingcap/tidb/parser@v0.0.0-20231013125129-93a834a6bf8d/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 "net/url" 20 "strconv" 21 "strings" 22 23 "github.com/pingcap/errors" 24 "github.com/pingcap/failpoint" 25 "github.com/pingcap/tidb/parser/auth" 26 "github.com/pingcap/tidb/parser/format" 27 "github.com/pingcap/tidb/parser/model" 28 "github.com/pingcap/tidb/parser/mysql" 29 ) 30 31 var ( 32 _ StmtNode = &AdminStmt{} 33 _ StmtNode = &AlterUserStmt{} 34 _ StmtNode = &AlterRangeStmt{} 35 _ StmtNode = &BeginStmt{} 36 _ StmtNode = &BinlogStmt{} 37 _ StmtNode = &CommitStmt{} 38 _ StmtNode = &CreateUserStmt{} 39 _ StmtNode = &DeallocateStmt{} 40 _ StmtNode = &DoStmt{} 41 _ StmtNode = &ExecuteStmt{} 42 _ StmtNode = &ExplainStmt{} 43 _ StmtNode = &GrantStmt{} 44 _ StmtNode = &PrepareStmt{} 45 _ StmtNode = &RollbackStmt{} 46 _ StmtNode = &SetPwdStmt{} 47 _ StmtNode = &SetRoleStmt{} 48 _ StmtNode = &SetDefaultRoleStmt{} 49 _ StmtNode = &SetStmt{} 50 _ StmtNode = &SetSessionStatesStmt{} 51 _ StmtNode = &UseStmt{} 52 _ StmtNode = &FlushStmt{} 53 _ StmtNode = &KillStmt{} 54 _ StmtNode = &CreateBindingStmt{} 55 _ StmtNode = &DropBindingStmt{} 56 _ StmtNode = &SetBindingStmt{} 57 _ StmtNode = &ShutdownStmt{} 58 _ StmtNode = &RestartStmt{} 59 _ StmtNode = &RenameUserStmt{} 60 _ StmtNode = &HelpStmt{} 61 _ StmtNode = &PlanReplayerStmt{} 62 _ StmtNode = &CompactTableStmt{} 63 _ StmtNode = &SetResourceGroupStmt{} 64 65 _ Node = &PrivElem{} 66 _ Node = &VariableAssignment{} 67 ) 68 69 // Isolation level constants. 70 const ( 71 ReadCommitted = "READ-COMMITTED" 72 ReadUncommitted = "READ-UNCOMMITTED" 73 Serializable = "SERIALIZABLE" 74 RepeatableRead = "REPEATABLE-READ" 75 76 PumpType = "PUMP" 77 DrainerType = "DRAINER" 78 ) 79 80 // Transaction mode constants. 81 const ( 82 Optimistic = "OPTIMISTIC" 83 Pessimistic = "PESSIMISTIC" 84 ) 85 86 // TypeOpt is used for parsing data type option from SQL. 87 type TypeOpt struct { 88 IsUnsigned bool 89 IsZerofill bool 90 } 91 92 // FloatOpt is used for parsing floating-point type option from SQL. 93 // See http://dev.mysql.com/doc/refman/5.7/en/floating-point-types.html 94 type FloatOpt struct { 95 Flen int 96 Decimal int 97 } 98 99 // AuthOption is used for parsing create use statement. 100 type AuthOption struct { 101 // ByAuthString set as true, if AuthString is used for authorization. Otherwise, authorization is done by HashString. 102 ByAuthString bool 103 AuthString string 104 ByHashString bool 105 HashString string 106 AuthPlugin string 107 } 108 109 // Restore implements Node interface. 110 func (n *AuthOption) Restore(ctx *format.RestoreCtx) error { 111 ctx.WriteKeyWord("IDENTIFIED") 112 if n.AuthPlugin != "" { 113 ctx.WriteKeyWord(" WITH ") 114 ctx.WriteString(n.AuthPlugin) 115 } 116 if n.ByAuthString { 117 ctx.WriteKeyWord(" BY ") 118 ctx.WriteString(n.AuthString) 119 } else if n.ByHashString { 120 ctx.WriteKeyWord(" AS ") 121 ctx.WriteString(n.HashString) 122 } 123 return nil 124 } 125 126 // TraceStmt is a statement to trace what sql actually does at background. 127 type TraceStmt struct { 128 stmtNode 129 130 Stmt StmtNode 131 Format string 132 133 TracePlan bool 134 TracePlanTarget string 135 } 136 137 // Restore implements Node interface. 138 func (n *TraceStmt) Restore(ctx *format.RestoreCtx) error { 139 ctx.WriteKeyWord("TRACE ") 140 if n.TracePlan { 141 ctx.WriteKeyWord("PLAN ") 142 if n.TracePlanTarget != "" { 143 ctx.WriteKeyWord("TARGET") 144 ctx.WritePlain(" = ") 145 ctx.WriteString(n.TracePlanTarget) 146 ctx.WritePlain(" ") 147 } 148 } else if n.Format != "row" { 149 ctx.WriteKeyWord("FORMAT") 150 ctx.WritePlain(" = ") 151 ctx.WriteString(n.Format) 152 ctx.WritePlain(" ") 153 } 154 if err := n.Stmt.Restore(ctx); err != nil { 155 return errors.Annotate(err, "An error occurred while restore TraceStmt.Stmt") 156 } 157 return nil 158 } 159 160 // Accept implements Node Accept interface. 161 func (n *TraceStmt) Accept(v Visitor) (Node, bool) { 162 newNode, skipChildren := v.Enter(n) 163 if skipChildren { 164 return v.Leave(newNode) 165 } 166 n = newNode.(*TraceStmt) 167 node, ok := n.Stmt.Accept(v) 168 if !ok { 169 return n, false 170 } 171 n.Stmt = node.(StmtNode) 172 return v.Leave(n) 173 } 174 175 // ExplainForStmt is a statement to provite information about how is SQL statement executeing 176 // in connection #ConnectionID 177 // See https://dev.mysql.com/doc/refman/5.7/en/explain.html 178 type ExplainForStmt struct { 179 stmtNode 180 181 Format string 182 ConnectionID uint64 183 } 184 185 // Restore implements Node interface. 186 func (n *ExplainForStmt) Restore(ctx *format.RestoreCtx) error { 187 ctx.WriteKeyWord("EXPLAIN ") 188 ctx.WriteKeyWord("FORMAT ") 189 ctx.WritePlain("= ") 190 ctx.WriteString(n.Format) 191 ctx.WritePlain(" ") 192 ctx.WriteKeyWord("FOR ") 193 ctx.WriteKeyWord("CONNECTION ") 194 ctx.WritePlain(strconv.FormatUint(n.ConnectionID, 10)) 195 return nil 196 } 197 198 // Accept implements Node Accept interface. 199 func (n *ExplainForStmt) Accept(v Visitor) (Node, bool) { 200 newNode, skipChildren := v.Enter(n) 201 if skipChildren { 202 return v.Leave(newNode) 203 } 204 n = newNode.(*ExplainForStmt) 205 return v.Leave(n) 206 } 207 208 // ExplainStmt is a statement to provide information about how is SQL statement executed 209 // or get columns information in a table. 210 // See https://dev.mysql.com/doc/refman/5.7/en/explain.html 211 type ExplainStmt struct { 212 stmtNode 213 214 Stmt StmtNode 215 Format string 216 Analyze bool 217 } 218 219 // Restore implements Node interface. 220 func (n *ExplainStmt) Restore(ctx *format.RestoreCtx) error { 221 if showStmt, ok := n.Stmt.(*ShowStmt); ok { 222 ctx.WriteKeyWord("DESC ") 223 if err := showStmt.Table.Restore(ctx); err != nil { 224 return errors.Annotate(err, "An error occurred while restore ExplainStmt.ShowStmt.Table") 225 } 226 if showStmt.Column != nil { 227 ctx.WritePlain(" ") 228 if err := showStmt.Column.Restore(ctx); err != nil { 229 return errors.Annotate(err, "An error occurred while restore ExplainStmt.ShowStmt.Column") 230 } 231 } 232 return nil 233 } 234 ctx.WriteKeyWord("EXPLAIN ") 235 if n.Analyze { 236 ctx.WriteKeyWord("ANALYZE ") 237 } 238 if !n.Analyze || strings.ToLower(n.Format) != "row" { 239 ctx.WriteKeyWord("FORMAT ") 240 ctx.WritePlain("= ") 241 ctx.WriteString(n.Format) 242 ctx.WritePlain(" ") 243 } 244 if err := n.Stmt.Restore(ctx); err != nil { 245 return errors.Annotate(err, "An error occurred while restore ExplainStmt.Stmt") 246 } 247 return nil 248 } 249 250 // Accept implements Node Accept interface. 251 func (n *ExplainStmt) Accept(v Visitor) (Node, bool) { 252 newNode, skipChildren := v.Enter(n) 253 if skipChildren { 254 return v.Leave(newNode) 255 } 256 n = newNode.(*ExplainStmt) 257 node, ok := n.Stmt.Accept(v) 258 if !ok { 259 return n, false 260 } 261 n.Stmt = node.(StmtNode) 262 return v.Leave(n) 263 } 264 265 // PlanReplayerStmt is a statement to dump or load information for recreating plans 266 type PlanReplayerStmt struct { 267 stmtNode 268 269 Stmt StmtNode 270 Analyze bool 271 Load bool 272 HistoricalStatsInfo *AsOfClause 273 274 // Capture indicates 'plan replayer capture <sql_digest> <plan_digest>' 275 Capture bool 276 // Remove indicates `plan replayer capture remove <sql_digest> <plan_digest> 277 Remove bool 278 279 SQLDigest string 280 PlanDigest string 281 282 // File is used to store 2 cases: 283 // 1. plan replayer load 'file'; 284 // 2. plan replayer dump explain <analyze> 'file' 285 File string 286 287 // Fields below are currently useless. 288 289 // Where is the where clause in select statement. 290 Where ExprNode 291 // OrderBy is the ordering expression list. 292 OrderBy *OrderByClause 293 // Limit is the limit clause. 294 Limit *Limit 295 } 296 297 // Restore implements Node interface. 298 func (n *PlanReplayerStmt) Restore(ctx *format.RestoreCtx) error { 299 if n.Load { 300 ctx.WriteKeyWord("PLAN REPLAYER LOAD ") 301 ctx.WriteString(n.File) 302 return nil 303 } 304 if n.Capture { 305 ctx.WriteKeyWord("PLAN REPLAYER CAPTURE ") 306 ctx.WriteString(n.SQLDigest) 307 ctx.WriteKeyWord(" ") 308 ctx.WriteString(n.PlanDigest) 309 return nil 310 } 311 if n.Remove { 312 ctx.WriteKeyWord("PLAN REPLAYER CAPTURE REMOVE ") 313 ctx.WriteString(n.SQLDigest) 314 ctx.WriteKeyWord(" ") 315 ctx.WriteString(n.PlanDigest) 316 return nil 317 } 318 319 ctx.WriteKeyWord("PLAN REPLAYER DUMP ") 320 321 if n.HistoricalStatsInfo != nil { 322 ctx.WriteKeyWord("WITH STATS ") 323 if err := n.HistoricalStatsInfo.Restore(ctx); err != nil { 324 return errors.Annotate(err, "An error occurred while restore PlanReplayerStmt.HistoricalStatsInfo") 325 } 326 ctx.WriteKeyWord(" ") 327 } 328 if n.Analyze { 329 ctx.WriteKeyWord("EXPLAIN ANALYZE ") 330 } else { 331 ctx.WriteKeyWord("EXPLAIN ") 332 } 333 if n.Stmt == nil { 334 if len(n.File) > 0 { 335 ctx.WriteString(n.File) 336 return nil 337 } 338 ctx.WriteKeyWord("SLOW QUERY") 339 if n.Where != nil { 340 ctx.WriteKeyWord(" WHERE ") 341 if err := n.Where.Restore(ctx); err != nil { 342 return errors.Annotate(err, "An error occurred while restore PlanReplayerStmt.Where") 343 } 344 } 345 if n.OrderBy != nil { 346 ctx.WriteKeyWord(" ") 347 if err := n.OrderBy.Restore(ctx); err != nil { 348 return errors.Annotate(err, "An error occurred while restore PlanReplayerStmt.OrderBy") 349 } 350 } 351 if n.Limit != nil { 352 ctx.WriteKeyWord(" ") 353 if err := n.Limit.Restore(ctx); err != nil { 354 return errors.Annotate(err, "An error occurred while restore PlanReplayerStmt.Limit") 355 } 356 } 357 return nil 358 } 359 if err := n.Stmt.Restore(ctx); err != nil { 360 return errors.Annotate(err, "An error occurred while restore PlanReplayerStmt.Stmt") 361 } 362 return nil 363 } 364 365 // Accept implements Node Accept interface. 366 func (n *PlanReplayerStmt) Accept(v Visitor) (Node, bool) { 367 newNode, skipChildren := v.Enter(n) 368 if skipChildren { 369 return v.Leave(newNode) 370 } 371 372 n = newNode.(*PlanReplayerStmt) 373 374 if n.Load { 375 return v.Leave(n) 376 } 377 378 if n.HistoricalStatsInfo != nil { 379 info, ok := n.HistoricalStatsInfo.Accept(v) 380 if !ok { 381 return n, false 382 } 383 n.HistoricalStatsInfo = info.(*AsOfClause) 384 } 385 386 if n.Stmt == nil { 387 if n.Where != nil { 388 node, ok := n.Where.Accept(v) 389 if !ok { 390 return n, false 391 } 392 n.Where = node.(ExprNode) 393 } 394 395 if n.OrderBy != nil { 396 node, ok := n.OrderBy.Accept(v) 397 if !ok { 398 return n, false 399 } 400 n.OrderBy = node.(*OrderByClause) 401 } 402 403 if n.Limit != nil { 404 node, ok := n.Limit.Accept(v) 405 if !ok { 406 return n, false 407 } 408 n.Limit = node.(*Limit) 409 } 410 return v.Leave(n) 411 } 412 413 node, ok := n.Stmt.Accept(v) 414 if !ok { 415 return n, false 416 } 417 n.Stmt = node.(StmtNode) 418 return v.Leave(n) 419 } 420 421 type CompactReplicaKind string 422 423 const ( 424 // CompactReplicaKindAll means compacting both TiKV and TiFlash replicas. 425 CompactReplicaKindAll = "ALL" 426 427 // CompactReplicaKindTiFlash means compacting TiFlash replicas. 428 CompactReplicaKindTiFlash = "TIFLASH" 429 430 // CompactReplicaKindTiKV means compacting TiKV replicas. 431 CompactReplicaKindTiKV = "TIKV" 432 ) 433 434 // CompactTableStmt is a statement to manually compact a table. 435 type CompactTableStmt struct { 436 stmtNode 437 438 Table *TableName 439 PartitionNames []model.CIStr 440 ReplicaKind CompactReplicaKind 441 } 442 443 // Restore implements Node interface. 444 func (n *CompactTableStmt) Restore(ctx *format.RestoreCtx) error { 445 ctx.WriteKeyWord("ALTER TABLE ") 446 n.Table.restoreName(ctx) 447 448 ctx.WriteKeyWord(" COMPACT") 449 if len(n.PartitionNames) != 0 { 450 ctx.WriteKeyWord(" PARTITION ") 451 for i, partition := range n.PartitionNames { 452 if i != 0 { 453 ctx.WritePlain(",") 454 } 455 ctx.WriteName(partition.O) 456 } 457 } 458 if n.ReplicaKind != CompactReplicaKindAll { 459 ctx.WriteKeyWord(" ") 460 // Note: There is only TiFlash replica available now. TiKV will be added later. 461 ctx.WriteKeyWord(string(n.ReplicaKind)) 462 ctx.WriteKeyWord(" REPLICA") 463 } 464 return nil 465 } 466 467 // Accept implements Node Accept interface. 468 func (n *CompactTableStmt) Accept(v Visitor) (Node, bool) { 469 newNode, skipChildren := v.Enter(n) 470 if skipChildren { 471 return v.Leave(newNode) 472 } 473 n = newNode.(*CompactTableStmt) 474 node, ok := n.Table.Accept(v) 475 if !ok { 476 return n, false 477 } 478 n.Table = node.(*TableName) 479 return v.Leave(n) 480 } 481 482 // PrepareStmt is a statement to prepares a SQL statement which contains placeholders, 483 // and it is executed with ExecuteStmt and released with DeallocateStmt. 484 // See https://dev.mysql.com/doc/refman/5.7/en/prepare.html 485 type PrepareStmt struct { 486 stmtNode 487 488 Name string 489 SQLText string 490 SQLVar *VariableExpr 491 } 492 493 // Restore implements Node interface. 494 func (n *PrepareStmt) Restore(ctx *format.RestoreCtx) error { 495 ctx.WriteKeyWord("PREPARE ") 496 ctx.WriteName(n.Name) 497 ctx.WriteKeyWord(" FROM ") 498 if n.SQLText != "" { 499 ctx.WriteString(n.SQLText) 500 return nil 501 } 502 if n.SQLVar != nil { 503 if err := n.SQLVar.Restore(ctx); err != nil { 504 return errors.Annotate(err, "An error occurred while restore PrepareStmt.SQLVar") 505 } 506 return nil 507 } 508 return errors.New("An error occurred while restore PrepareStmt") 509 } 510 511 // Accept implements Node Accept interface. 512 func (n *PrepareStmt) Accept(v Visitor) (Node, bool) { 513 newNode, skipChildren := v.Enter(n) 514 if skipChildren { 515 return v.Leave(newNode) 516 } 517 n = newNode.(*PrepareStmt) 518 if n.SQLVar != nil { 519 node, ok := n.SQLVar.Accept(v) 520 if !ok { 521 return n, false 522 } 523 n.SQLVar = node.(*VariableExpr) 524 } 525 return v.Leave(n) 526 } 527 528 // DeallocateStmt is a statement to release PreparedStmt. 529 // See https://dev.mysql.com/doc/refman/5.7/en/deallocate-prepare.html 530 type DeallocateStmt struct { 531 stmtNode 532 533 Name string 534 } 535 536 // Restore implements Node interface. 537 func (n *DeallocateStmt) Restore(ctx *format.RestoreCtx) error { 538 ctx.WriteKeyWord("DEALLOCATE PREPARE ") 539 ctx.WriteName(n.Name) 540 return nil 541 } 542 543 // Accept implements Node Accept interface. 544 func (n *DeallocateStmt) Accept(v Visitor) (Node, bool) { 545 newNode, skipChildren := v.Enter(n) 546 if skipChildren { 547 return v.Leave(newNode) 548 } 549 n = newNode.(*DeallocateStmt) 550 return v.Leave(n) 551 } 552 553 // Prepared represents a prepared statement. 554 type Prepared struct { 555 Stmt StmtNode 556 StmtType string 557 Params []ParamMarkerExpr 558 SchemaVersion int64 559 CachedPlan interface{} 560 CachedNames interface{} 561 } 562 563 // ExecuteStmt is a statement to execute PreparedStmt. 564 // See https://dev.mysql.com/doc/refman/5.7/en/execute.html 565 type ExecuteStmt struct { 566 stmtNode 567 568 Name string 569 UsingVars []ExprNode 570 BinaryArgs interface{} 571 PrepStmt interface{} // the corresponding prepared statement 572 IdxInMulti int 573 574 // FromGeneralStmt indicates whether this execute-stmt is converted from a general query. 575 // e.g. select * from t where a>2 --> execute 'select * from t where a>?' using 2 576 FromGeneralStmt bool 577 } 578 579 // Restore implements Node interface. 580 func (n *ExecuteStmt) Restore(ctx *format.RestoreCtx) error { 581 ctx.WriteKeyWord("EXECUTE ") 582 ctx.WriteName(n.Name) 583 if len(n.UsingVars) > 0 { 584 ctx.WriteKeyWord(" USING ") 585 for i, val := range n.UsingVars { 586 if i != 0 { 587 ctx.WritePlain(",") 588 } 589 if err := val.Restore(ctx); err != nil { 590 return errors.Annotatef(err, "An error occurred while restore ExecuteStmt.UsingVars index %d", i) 591 } 592 } 593 } 594 return nil 595 } 596 597 // Accept implements Node Accept interface. 598 func (n *ExecuteStmt) Accept(v Visitor) (Node, bool) { 599 newNode, skipChildren := v.Enter(n) 600 if skipChildren { 601 return v.Leave(newNode) 602 } 603 n = newNode.(*ExecuteStmt) 604 for i, val := range n.UsingVars { 605 node, ok := val.Accept(v) 606 if !ok { 607 return n, false 608 } 609 n.UsingVars[i] = node.(ExprNode) 610 } 611 return v.Leave(n) 612 } 613 614 // BeginStmt is a statement to start a new transaction. 615 // See https://dev.mysql.com/doc/refman/5.7/en/commit.html 616 type BeginStmt struct { 617 stmtNode 618 Mode string 619 CausalConsistencyOnly bool 620 ReadOnly bool 621 // AS OF is used to read the data at a specific point of time. 622 // Should only be used when ReadOnly is true. 623 AsOf *AsOfClause 624 } 625 626 // Restore implements Node interface. 627 func (n *BeginStmt) Restore(ctx *format.RestoreCtx) error { 628 if n.Mode == "" { 629 if n.ReadOnly { 630 ctx.WriteKeyWord("START TRANSACTION READ ONLY") 631 if n.AsOf != nil { 632 ctx.WriteKeyWord(" ") 633 return n.AsOf.Restore(ctx) 634 } 635 } else if n.CausalConsistencyOnly { 636 ctx.WriteKeyWord("START TRANSACTION WITH CAUSAL CONSISTENCY ONLY") 637 } else { 638 ctx.WriteKeyWord("START TRANSACTION") 639 } 640 } else { 641 ctx.WriteKeyWord("BEGIN ") 642 ctx.WriteKeyWord(n.Mode) 643 } 644 return nil 645 } 646 647 // Accept implements Node Accept interface. 648 func (n *BeginStmt) Accept(v Visitor) (Node, bool) { 649 newNode, skipChildren := v.Enter(n) 650 if skipChildren { 651 return v.Leave(newNode) 652 } 653 654 if n.AsOf != nil { 655 node, ok := n.AsOf.Accept(v) 656 if !ok { 657 return n, false 658 } 659 n.AsOf = node.(*AsOfClause) 660 } 661 662 n = newNode.(*BeginStmt) 663 return v.Leave(n) 664 } 665 666 // BinlogStmt is an internal-use statement. 667 // We just parse and ignore it. 668 // See http://dev.mysql.com/doc/refman/5.7/en/binlog.html 669 type BinlogStmt struct { 670 stmtNode 671 Str string 672 } 673 674 // Restore implements Node interface. 675 func (n *BinlogStmt) Restore(ctx *format.RestoreCtx) error { 676 ctx.WriteKeyWord("BINLOG ") 677 ctx.WriteString(n.Str) 678 return nil 679 } 680 681 // Accept implements Node Accept interface. 682 func (n *BinlogStmt) Accept(v Visitor) (Node, bool) { 683 newNode, skipChildren := v.Enter(n) 684 if skipChildren { 685 return v.Leave(newNode) 686 } 687 n = newNode.(*BinlogStmt) 688 return v.Leave(n) 689 } 690 691 // CompletionType defines completion_type used in COMMIT and ROLLBACK statements 692 type CompletionType int8 693 694 const ( 695 // CompletionTypeDefault refers to NO_CHAIN 696 CompletionTypeDefault CompletionType = iota 697 CompletionTypeChain 698 CompletionTypeRelease 699 ) 700 701 func (n CompletionType) Restore(ctx *format.RestoreCtx) error { 702 switch n { 703 case CompletionTypeDefault: 704 case CompletionTypeChain: 705 ctx.WriteKeyWord(" AND CHAIN") 706 case CompletionTypeRelease: 707 ctx.WriteKeyWord(" RELEASE") 708 } 709 return nil 710 } 711 712 // CommitStmt is a statement to commit the current transaction. 713 // See https://dev.mysql.com/doc/refman/5.7/en/commit.html 714 type CommitStmt struct { 715 stmtNode 716 // CompletionType overwrites system variable `completion_type` within transaction 717 CompletionType CompletionType 718 } 719 720 // Restore implements Node interface. 721 func (n *CommitStmt) Restore(ctx *format.RestoreCtx) error { 722 ctx.WriteKeyWord("COMMIT") 723 if err := n.CompletionType.Restore(ctx); err != nil { 724 return errors.Annotate(err, "An error occurred while restore CommitStmt.CompletionType") 725 } 726 return nil 727 } 728 729 // Accept implements Node Accept interface. 730 func (n *CommitStmt) Accept(v Visitor) (Node, bool) { 731 newNode, skipChildren := v.Enter(n) 732 if skipChildren { 733 return v.Leave(newNode) 734 } 735 n = newNode.(*CommitStmt) 736 return v.Leave(n) 737 } 738 739 // RollbackStmt is a statement to roll back the current transaction. 740 // See https://dev.mysql.com/doc/refman/5.7/en/commit.html 741 type RollbackStmt struct { 742 stmtNode 743 // CompletionType overwrites system variable `completion_type` within transaction 744 CompletionType CompletionType 745 // SavepointName is the savepoint name. 746 SavepointName string 747 } 748 749 // Restore implements Node interface. 750 func (n *RollbackStmt) Restore(ctx *format.RestoreCtx) error { 751 ctx.WriteKeyWord("ROLLBACK") 752 if n.SavepointName != "" { 753 ctx.WritePlain(" TO ") 754 ctx.WritePlain(n.SavepointName) 755 } 756 if err := n.CompletionType.Restore(ctx); err != nil { 757 return errors.Annotate(err, "An error occurred while restore RollbackStmt.CompletionType") 758 } 759 return nil 760 } 761 762 // Accept implements Node Accept interface. 763 func (n *RollbackStmt) Accept(v Visitor) (Node, bool) { 764 newNode, skipChildren := v.Enter(n) 765 if skipChildren { 766 return v.Leave(newNode) 767 } 768 n = newNode.(*RollbackStmt) 769 return v.Leave(n) 770 } 771 772 // UseStmt is a statement to use the DBName database as the current database. 773 // See https://dev.mysql.com/doc/refman/5.7/en/use.html 774 type UseStmt struct { 775 stmtNode 776 777 DBName string 778 } 779 780 // Restore implements Node interface. 781 func (n *UseStmt) Restore(ctx *format.RestoreCtx) error { 782 ctx.WriteKeyWord("USE ") 783 ctx.WriteName(n.DBName) 784 return nil 785 } 786 787 // Accept implements Node Accept interface. 788 func (n *UseStmt) Accept(v Visitor) (Node, bool) { 789 newNode, skipChildren := v.Enter(n) 790 if skipChildren { 791 return v.Leave(newNode) 792 } 793 n = newNode.(*UseStmt) 794 return v.Leave(n) 795 } 796 797 const ( 798 // SetNames is the const for set names stmt. 799 // If VariableAssignment.Name == Names, it should be set names stmt. 800 SetNames = "SetNAMES" 801 // SetCharset is the const for set charset stmt. 802 SetCharset = "SetCharset" 803 ) 804 805 // VariableAssignment is a variable assignment struct. 806 type VariableAssignment struct { 807 node 808 Name string 809 Value ExprNode 810 IsGlobal bool 811 IsSystem bool 812 813 // ExtendValue is a way to store extended info. 814 // VariableAssignment should be able to store information for SetCharset/SetPWD Stmt. 815 // For SetCharsetStmt, Value is charset, ExtendValue is collation. 816 // TODO: Use SetStmt to implement set password statement. 817 ExtendValue ValueExpr 818 } 819 820 // Restore implements Node interface. 821 func (n *VariableAssignment) Restore(ctx *format.RestoreCtx) error { 822 if n.IsSystem { 823 ctx.WritePlain("@@") 824 if n.IsGlobal { 825 ctx.WriteKeyWord("GLOBAL") 826 } else { 827 ctx.WriteKeyWord("SESSION") 828 } 829 ctx.WritePlain(".") 830 } else if n.Name != SetNames && n.Name != SetCharset { 831 ctx.WriteKeyWord("@") 832 } 833 if n.Name == SetNames { 834 ctx.WriteKeyWord("NAMES ") 835 } else if n.Name == SetCharset { 836 ctx.WriteKeyWord("CHARSET ") 837 } else { 838 ctx.WriteName(n.Name) 839 ctx.WritePlain("=") 840 } 841 if err := n.Value.Restore(ctx); err != nil { 842 return errors.Annotate(err, "An error occurred while restore VariableAssignment.Value") 843 } 844 if n.ExtendValue != nil { 845 ctx.WriteKeyWord(" COLLATE ") 846 if err := n.ExtendValue.Restore(ctx); err != nil { 847 return errors.Annotate(err, "An error occurred while restore VariableAssignment.ExtendValue") 848 } 849 } 850 return nil 851 } 852 853 // Accept implements Node interface. 854 func (n *VariableAssignment) Accept(v Visitor) (Node, bool) { 855 newNode, skipChildren := v.Enter(n) 856 if skipChildren { 857 return v.Leave(newNode) 858 } 859 n = newNode.(*VariableAssignment) 860 node, ok := n.Value.Accept(v) 861 if !ok { 862 return n, false 863 } 864 n.Value = node.(ExprNode) 865 return v.Leave(n) 866 } 867 868 // FlushStmtType is the type for FLUSH statement. 869 type FlushStmtType int 870 871 // Flush statement types. 872 const ( 873 FlushNone FlushStmtType = iota 874 FlushTables 875 FlushPrivileges 876 FlushStatus 877 FlushTiDBPlugin 878 FlushHosts 879 FlushLogs 880 FlushClientErrorsSummary 881 ) 882 883 // LogType is the log type used in FLUSH statement. 884 type LogType int8 885 886 const ( 887 LogTypeDefault LogType = iota 888 LogTypeBinary 889 LogTypeEngine 890 LogTypeError 891 LogTypeGeneral 892 LogTypeSlow 893 ) 894 895 // FlushStmt is a statement to flush tables/privileges/optimizer costs and so on. 896 type FlushStmt struct { 897 stmtNode 898 899 Tp FlushStmtType // Privileges/Tables/... 900 NoWriteToBinLog bool 901 LogType LogType 902 Tables []*TableName // For FlushTableStmt, if Tables is empty, it means flush all tables. 903 ReadLock bool 904 Plugins []string 905 } 906 907 // Restore implements Node interface. 908 func (n *FlushStmt) Restore(ctx *format.RestoreCtx) error { 909 ctx.WriteKeyWord("FLUSH ") 910 if n.NoWriteToBinLog { 911 ctx.WriteKeyWord("NO_WRITE_TO_BINLOG ") 912 } 913 switch n.Tp { 914 case FlushTables: 915 ctx.WriteKeyWord("TABLES") 916 for i, v := range n.Tables { 917 if i == 0 { 918 ctx.WritePlain(" ") 919 } else { 920 ctx.WritePlain(", ") 921 } 922 if err := v.Restore(ctx); err != nil { 923 return errors.Annotatef(err, "An error occurred while restore FlushStmt.Tables[%d]", i) 924 } 925 } 926 if n.ReadLock { 927 ctx.WriteKeyWord(" WITH READ LOCK") 928 } 929 case FlushPrivileges: 930 ctx.WriteKeyWord("PRIVILEGES") 931 case FlushStatus: 932 ctx.WriteKeyWord("STATUS") 933 case FlushTiDBPlugin: 934 ctx.WriteKeyWord("TIDB PLUGINS") 935 for i, v := range n.Plugins { 936 if i == 0 { 937 ctx.WritePlain(" ") 938 } else { 939 ctx.WritePlain(", ") 940 } 941 ctx.WritePlain(v) 942 } 943 case FlushHosts: 944 ctx.WriteKeyWord("HOSTS") 945 case FlushLogs: 946 var logType string 947 switch n.LogType { 948 case LogTypeDefault: 949 logType = "LOGS" 950 case LogTypeBinary: 951 logType = "BINARY LOGS" 952 case LogTypeEngine: 953 logType = "ENGINE LOGS" 954 case LogTypeError: 955 logType = "ERROR LOGS" 956 case LogTypeGeneral: 957 logType = "GENERAL LOGS" 958 case LogTypeSlow: 959 logType = "SLOW LOGS" 960 } 961 ctx.WriteKeyWord(logType) 962 case FlushClientErrorsSummary: 963 ctx.WriteKeyWord("CLIENT_ERRORS_SUMMARY") 964 default: 965 return errors.New("Unsupported type of FlushStmt") 966 } 967 return nil 968 } 969 970 // Accept implements Node Accept interface. 971 func (n *FlushStmt) Accept(v Visitor) (Node, bool) { 972 newNode, skipChildren := v.Enter(n) 973 if skipChildren { 974 return v.Leave(newNode) 975 } 976 n = newNode.(*FlushStmt) 977 return v.Leave(n) 978 } 979 980 // KillStmt is a statement to kill a query or connection. 981 type KillStmt struct { 982 stmtNode 983 984 // Query indicates whether terminate a single query on this connection or the whole connection. 985 // If Query is true, terminates the statement the connection is currently executing, but leaves the connection itself intact. 986 // If Query is false, terminates the connection associated with the given ConnectionID, after terminating any statement the connection is executing. 987 Query bool 988 ConnectionID uint64 989 // TiDBExtension is used to indicate whether the user knows he is sending kill statement to the right tidb-server. 990 // When the SQL grammar is "KILL TIDB [CONNECTION | QUERY] connectionID", TiDBExtension will be set. 991 // It's a special grammar extension in TiDB. This extension exists because, when the connection is: 992 // client -> LVS proxy -> TiDB, and type Ctrl+C in client, the following action will be executed: 993 // new a connection; kill xxx; 994 // kill command may send to the wrong TiDB, because the exists of LVS proxy, and kill the wrong session. 995 // So, "KILL TIDB" grammar is introduced, and it REQUIRES DIRECT client -> TiDB TOPOLOGY. 996 // TODO: The standard KILL grammar will be supported once we have global connectionID. 997 TiDBExtension bool 998 999 Expr ExprNode 1000 } 1001 1002 // Restore implements Node interface. 1003 func (n *KillStmt) Restore(ctx *format.RestoreCtx) error { 1004 ctx.WriteKeyWord("KILL") 1005 if n.TiDBExtension { 1006 ctx.WriteKeyWord(" TIDB") 1007 } 1008 if n.Query { 1009 ctx.WriteKeyWord(" QUERY") 1010 } 1011 if n.Expr != nil { 1012 ctx.WriteKeyWord(" ") 1013 if err := n.Expr.Restore(ctx); err != nil { 1014 return errors.Trace(err) 1015 } 1016 } else { 1017 ctx.WritePlainf(" %d", n.ConnectionID) 1018 } 1019 return nil 1020 } 1021 1022 // Accept implements Node Accept interface. 1023 func (n *KillStmt) Accept(v Visitor) (Node, bool) { 1024 newNode, skipChildren := v.Enter(n) 1025 if skipChildren { 1026 return v.Leave(newNode) 1027 } 1028 n = newNode.(*KillStmt) 1029 return v.Leave(n) 1030 } 1031 1032 // SavepointStmt is the statement of SAVEPOINT. 1033 type SavepointStmt struct { 1034 stmtNode 1035 // Name is the savepoint name. 1036 Name string 1037 } 1038 1039 // Restore implements Node interface. 1040 func (n *SavepointStmt) Restore(ctx *format.RestoreCtx) error { 1041 ctx.WriteKeyWord("SAVEPOINT ") 1042 ctx.WritePlain(n.Name) 1043 return nil 1044 } 1045 1046 // Accept implements Node Accept interface. 1047 func (n *SavepointStmt) Accept(v Visitor) (Node, bool) { 1048 newNode, _ := v.Enter(n) 1049 n = newNode.(*SavepointStmt) 1050 return v.Leave(n) 1051 } 1052 1053 // ReleaseSavepointStmt is the statement of RELEASE SAVEPOINT. 1054 type ReleaseSavepointStmt struct { 1055 stmtNode 1056 // Name is the savepoint name. 1057 Name string 1058 } 1059 1060 // Restore implements Node interface. 1061 func (n *ReleaseSavepointStmt) Restore(ctx *format.RestoreCtx) error { 1062 ctx.WriteKeyWord("RELEASE SAVEPOINT ") 1063 ctx.WritePlain(n.Name) 1064 return nil 1065 } 1066 1067 // Accept implements Node Accept interface. 1068 func (n *ReleaseSavepointStmt) Accept(v Visitor) (Node, bool) { 1069 newNode, _ := v.Enter(n) 1070 n = newNode.(*ReleaseSavepointStmt) 1071 return v.Leave(n) 1072 } 1073 1074 // SetStmt is the statement to set variables. 1075 type SetStmt struct { 1076 stmtNode 1077 // Variables is the list of variable assignment. 1078 Variables []*VariableAssignment 1079 } 1080 1081 // Restore implements Node interface. 1082 func (n *SetStmt) Restore(ctx *format.RestoreCtx) error { 1083 ctx.WriteKeyWord("SET ") 1084 for i, v := range n.Variables { 1085 if i != 0 { 1086 ctx.WritePlain(", ") 1087 } 1088 if err := v.Restore(ctx); err != nil { 1089 return errors.Annotatef(err, "An error occurred while restore SetStmt.Variables[%d]", i) 1090 } 1091 } 1092 return nil 1093 } 1094 1095 // Accept implements Node Accept interface. 1096 func (n *SetStmt) Accept(v Visitor) (Node, bool) { 1097 newNode, skipChildren := v.Enter(n) 1098 if skipChildren { 1099 return v.Leave(newNode) 1100 } 1101 n = newNode.(*SetStmt) 1102 for i, val := range n.Variables { 1103 node, ok := val.Accept(v) 1104 if !ok { 1105 return n, false 1106 } 1107 n.Variables[i] = node.(*VariableAssignment) 1108 } 1109 return v.Leave(n) 1110 } 1111 1112 // SetConfigStmt is the statement to set cluster configs. 1113 type SetConfigStmt struct { 1114 stmtNode 1115 1116 Type string // TiDB, TiKV, PD 1117 Instance string // '127.0.0.1:3306' 1118 Name string // the variable name 1119 Value ExprNode 1120 } 1121 1122 func (n *SetConfigStmt) Restore(ctx *format.RestoreCtx) error { 1123 ctx.WriteKeyWord("SET CONFIG ") 1124 if n.Type != "" { 1125 ctx.WriteKeyWord(n.Type) 1126 } else { 1127 ctx.WriteString(n.Instance) 1128 } 1129 ctx.WritePlain(" ") 1130 ctx.WriteKeyWord(n.Name) 1131 ctx.WritePlain(" = ") 1132 return n.Value.Restore(ctx) 1133 } 1134 1135 func (n *SetConfigStmt) Accept(v Visitor) (Node, bool) { 1136 newNode, skipChildren := v.Enter(n) 1137 if skipChildren { 1138 return v.Leave(newNode) 1139 } 1140 n = newNode.(*SetConfigStmt) 1141 node, ok := n.Value.Accept(v) 1142 if !ok { 1143 return n, false 1144 } 1145 n.Value = node.(ExprNode) 1146 return v.Leave(n) 1147 } 1148 1149 // SetSessionStatesStmt is a statement to restore session states. 1150 type SetSessionStatesStmt struct { 1151 stmtNode 1152 1153 SessionStates string 1154 } 1155 1156 func (n *SetSessionStatesStmt) Restore(ctx *format.RestoreCtx) error { 1157 ctx.WriteKeyWord("SET SESSION_STATES ") 1158 ctx.WriteString(n.SessionStates) 1159 return nil 1160 } 1161 1162 func (n *SetSessionStatesStmt) Accept(v Visitor) (Node, bool) { 1163 newNode, skipChildren := v.Enter(n) 1164 if skipChildren { 1165 return v.Leave(newNode) 1166 } 1167 n = newNode.(*SetSessionStatesStmt) 1168 return v.Leave(n) 1169 } 1170 1171 /* 1172 // SetCharsetStmt is a statement to assign values to character and collation variables. 1173 // See https://dev.mysql.com/doc/refman/5.7/en/set-statement.html 1174 type SetCharsetStmt struct { 1175 stmtNode 1176 1177 Charset string 1178 Collate string 1179 } 1180 1181 // Accept implements Node Accept interface. 1182 func (n *SetCharsetStmt) Accept(v Visitor) (Node, bool) { 1183 newNode, skipChildren := v.Enter(n) 1184 if skipChildren { 1185 return v.Leave(newNode) 1186 } 1187 n = newNode.(*SetCharsetStmt) 1188 return v.Leave(n) 1189 } 1190 */ 1191 1192 // SetPwdStmt is a statement to assign a password to user account. 1193 // See https://dev.mysql.com/doc/refman/5.7/en/set-password.html 1194 type SetPwdStmt struct { 1195 stmtNode 1196 1197 User *auth.UserIdentity 1198 Password string 1199 } 1200 1201 // Restore implements Node interface. 1202 func (n *SetPwdStmt) Restore(ctx *format.RestoreCtx) error { 1203 ctx.WriteKeyWord("SET PASSWORD") 1204 if n.User != nil { 1205 ctx.WriteKeyWord(" FOR ") 1206 if err := n.User.Restore(ctx); err != nil { 1207 return errors.Annotate(err, "An error occurred while restore SetPwdStmt.User") 1208 } 1209 } 1210 ctx.WritePlain("=") 1211 ctx.WriteString(n.Password) 1212 return nil 1213 } 1214 1215 // SecureText implements SensitiveStatement interface. 1216 func (n *SetPwdStmt) SecureText() string { 1217 return fmt.Sprintf("set password for user %s", n.User) 1218 } 1219 1220 // Accept implements Node Accept interface. 1221 func (n *SetPwdStmt) Accept(v Visitor) (Node, bool) { 1222 newNode, skipChildren := v.Enter(n) 1223 if skipChildren { 1224 return v.Leave(newNode) 1225 } 1226 n = newNode.(*SetPwdStmt) 1227 return v.Leave(n) 1228 } 1229 1230 type ChangeStmt struct { 1231 stmtNode 1232 1233 NodeType string 1234 State string 1235 NodeID string 1236 } 1237 1238 // Restore implements Node interface. 1239 func (n *ChangeStmt) Restore(ctx *format.RestoreCtx) error { 1240 ctx.WriteKeyWord("CHANGE ") 1241 ctx.WriteKeyWord(n.NodeType) 1242 ctx.WriteKeyWord(" TO NODE_STATE ") 1243 ctx.WritePlain("=") 1244 ctx.WriteString(n.State) 1245 ctx.WriteKeyWord(" FOR NODE_ID ") 1246 ctx.WriteString(n.NodeID) 1247 return nil 1248 } 1249 1250 // SecureText implements SensitiveStatement interface. 1251 func (n *ChangeStmt) SecureText() string { 1252 return fmt.Sprintf("change %s to node_state='%s' for node_id '%s'", strings.ToLower(n.NodeType), n.State, n.NodeID) 1253 } 1254 1255 // Accept implements Node Accept interface. 1256 func (n *ChangeStmt) Accept(v Visitor) (Node, bool) { 1257 newNode, skipChildren := v.Enter(n) 1258 if skipChildren { 1259 return v.Leave(newNode) 1260 } 1261 n = newNode.(*ChangeStmt) 1262 return v.Leave(n) 1263 } 1264 1265 // SetRoleStmtType is the type for FLUSH statement. 1266 type SetRoleStmtType int 1267 1268 // SetRole statement types. 1269 const ( 1270 SetRoleDefault SetRoleStmtType = iota 1271 SetRoleNone 1272 SetRoleAll 1273 SetRoleAllExcept 1274 SetRoleRegular 1275 ) 1276 1277 type SetRoleStmt struct { 1278 stmtNode 1279 1280 SetRoleOpt SetRoleStmtType 1281 RoleList []*auth.RoleIdentity 1282 } 1283 1284 func (n *SetRoleStmt) Restore(ctx *format.RestoreCtx) error { 1285 ctx.WriteKeyWord("SET ROLE") 1286 switch n.SetRoleOpt { 1287 case SetRoleDefault: 1288 ctx.WriteKeyWord(" DEFAULT") 1289 case SetRoleNone: 1290 ctx.WriteKeyWord(" NONE") 1291 case SetRoleAll: 1292 ctx.WriteKeyWord(" ALL") 1293 case SetRoleAllExcept: 1294 ctx.WriteKeyWord(" ALL EXCEPT") 1295 } 1296 for i, role := range n.RoleList { 1297 ctx.WritePlain(" ") 1298 err := role.Restore(ctx) 1299 if err != nil { 1300 return errors.Annotate(err, "An error occurred while restore SetRoleStmt.RoleList") 1301 } 1302 if i != len(n.RoleList)-1 { 1303 ctx.WritePlain(",") 1304 } 1305 } 1306 return nil 1307 } 1308 1309 // Accept implements Node Accept interface. 1310 func (n *SetRoleStmt) Accept(v Visitor) (Node, bool) { 1311 newNode, skipChildren := v.Enter(n) 1312 if skipChildren { 1313 return v.Leave(newNode) 1314 } 1315 n = newNode.(*SetRoleStmt) 1316 return v.Leave(n) 1317 } 1318 1319 type SetDefaultRoleStmt struct { 1320 stmtNode 1321 1322 SetRoleOpt SetRoleStmtType 1323 RoleList []*auth.RoleIdentity 1324 UserList []*auth.UserIdentity 1325 } 1326 1327 func (n *SetDefaultRoleStmt) Restore(ctx *format.RestoreCtx) error { 1328 ctx.WriteKeyWord("SET DEFAULT ROLE") 1329 switch n.SetRoleOpt { 1330 case SetRoleNone: 1331 ctx.WriteKeyWord(" NONE") 1332 case SetRoleAll: 1333 ctx.WriteKeyWord(" ALL") 1334 default: 1335 } 1336 for i, role := range n.RoleList { 1337 ctx.WritePlain(" ") 1338 err := role.Restore(ctx) 1339 if err != nil { 1340 return errors.Annotate(err, "An error occurred while restore SetDefaultRoleStmt.RoleList") 1341 } 1342 if i != len(n.RoleList)-1 { 1343 ctx.WritePlain(",") 1344 } 1345 } 1346 ctx.WritePlain(" TO") 1347 for i, user := range n.UserList { 1348 ctx.WritePlain(" ") 1349 err := user.Restore(ctx) 1350 if err != nil { 1351 return errors.Annotate(err, "An error occurred while restore SetDefaultRoleStmt.UserList") 1352 } 1353 if i != len(n.UserList)-1 { 1354 ctx.WritePlain(",") 1355 } 1356 } 1357 return nil 1358 } 1359 1360 // Accept implements Node Accept interface. 1361 func (n *SetDefaultRoleStmt) Accept(v Visitor) (Node, bool) { 1362 newNode, skipChildren := v.Enter(n) 1363 if skipChildren { 1364 return v.Leave(newNode) 1365 } 1366 n = newNode.(*SetDefaultRoleStmt) 1367 return v.Leave(n) 1368 } 1369 1370 // UserSpec is used for parsing create user statement. 1371 type UserSpec struct { 1372 User *auth.UserIdentity 1373 AuthOpt *AuthOption 1374 IsRole bool 1375 } 1376 1377 // Restore implements Node interface. 1378 func (n *UserSpec) Restore(ctx *format.RestoreCtx) error { 1379 if err := n.User.Restore(ctx); err != nil { 1380 return errors.Annotate(err, "An error occurred while restore UserSpec.User") 1381 } 1382 if n.AuthOpt != nil { 1383 ctx.WritePlain(" ") 1384 if err := n.AuthOpt.Restore(ctx); err != nil { 1385 return errors.Annotate(err, "An error occurred while restore UserSpec.AuthOpt") 1386 } 1387 } 1388 return nil 1389 } 1390 1391 // SecurityString formats the UserSpec without password information. 1392 func (n *UserSpec) SecurityString() string { 1393 withPassword := false 1394 if opt := n.AuthOpt; opt != nil { 1395 if len(opt.AuthString) > 0 || len(opt.HashString) > 0 { 1396 withPassword = true 1397 } 1398 } 1399 if withPassword { 1400 return fmt.Sprintf("{%s password = ***}", n.User) 1401 } 1402 return n.User.String() 1403 } 1404 1405 // EncodedPassword returns the encoded password (which is the real data mysql.user). 1406 // The boolean value indicates input's password format is legal or not. 1407 func (n *UserSpec) EncodedPassword() (string, bool) { 1408 if n.AuthOpt == nil { 1409 return "", true 1410 } 1411 1412 opt := n.AuthOpt 1413 if opt.ByAuthString { 1414 switch opt.AuthPlugin { 1415 case mysql.AuthCachingSha2Password, mysql.AuthTiDBSM3Password: 1416 return auth.NewHashPassword(opt.AuthString, opt.AuthPlugin), true 1417 case mysql.AuthSocket: 1418 return "", true 1419 default: 1420 return auth.EncodePassword(opt.AuthString), true 1421 } 1422 } 1423 1424 // store the LDAP dn directly in the password field 1425 switch opt.AuthPlugin { 1426 case mysql.AuthLDAPSimple, mysql.AuthLDAPSASL: 1427 // TODO: validate the HashString to be a `dn` for LDAP 1428 // It seems fine to not validate here, and LDAP server will give an error when the client'll try to login this user. 1429 // The percona server implementation doesn't have a validation for this HashString. 1430 // However, returning an error for obvious wrong format is more friendly. 1431 return opt.HashString, true 1432 } 1433 1434 // In case we have 'IDENTIFIED WITH <plugin>' but no 'BY <password>' to set an empty password. 1435 if opt.HashString == "" { 1436 return opt.HashString, true 1437 } 1438 1439 // Not a legal password string. 1440 switch opt.AuthPlugin { 1441 case mysql.AuthCachingSha2Password: 1442 if len(opt.HashString) != mysql.SHAPWDHashLen { 1443 return "", false 1444 } 1445 case mysql.AuthTiDBSM3Password: 1446 if len(opt.HashString) != mysql.SM3PWDHashLen { 1447 return "", false 1448 } 1449 case "", mysql.AuthNativePassword: 1450 if len(opt.HashString) != (mysql.PWDHashLen+1) || !strings.HasPrefix(opt.HashString, "*") { 1451 return "", false 1452 } 1453 case mysql.AuthSocket: 1454 default: 1455 return "", false 1456 } 1457 return opt.HashString, true 1458 } 1459 1460 type AuthTokenOrTLSOption struct { 1461 Type AuthTokenOrTLSOptionType 1462 Value string 1463 } 1464 1465 func (t *AuthTokenOrTLSOption) Restore(ctx *format.RestoreCtx) error { 1466 switch t.Type { 1467 case TlsNone: 1468 ctx.WriteKeyWord("NONE") 1469 case Ssl: 1470 ctx.WriteKeyWord("SSL") 1471 case X509: 1472 ctx.WriteKeyWord("X509") 1473 case Cipher: 1474 ctx.WriteKeyWord("CIPHER ") 1475 ctx.WriteString(t.Value) 1476 case Issuer: 1477 ctx.WriteKeyWord("ISSUER ") 1478 ctx.WriteString(t.Value) 1479 case Subject: 1480 ctx.WriteKeyWord("SUBJECT ") 1481 ctx.WriteString(t.Value) 1482 case SAN: 1483 ctx.WriteKeyWord("SAN ") 1484 ctx.WriteString(t.Value) 1485 case TokenIssuer: 1486 ctx.WriteKeyWord("TOKEN_ISSUER ") 1487 ctx.WriteString(t.Value) 1488 default: 1489 return errors.Errorf("Unsupported AuthTokenOrTLSOption.Type %d", t.Type) 1490 } 1491 return nil 1492 } 1493 1494 type AuthTokenOrTLSOptionType int 1495 1496 const ( 1497 TlsNone AuthTokenOrTLSOptionType = iota 1498 Ssl 1499 X509 1500 Cipher 1501 Issuer 1502 Subject 1503 SAN 1504 TokenIssuer 1505 ) 1506 1507 func (t AuthTokenOrTLSOptionType) String() string { 1508 switch t { 1509 case TlsNone: 1510 return "NONE" 1511 case Ssl: 1512 return "SSL" 1513 case X509: 1514 return "X509" 1515 case Cipher: 1516 return "CIPHER" 1517 case Issuer: 1518 return "ISSUER" 1519 case Subject: 1520 return "SUBJECT" 1521 case SAN: 1522 return "SAN" 1523 case TokenIssuer: 1524 return "TOKEN_ISSUER" 1525 default: 1526 return "UNKNOWN" 1527 } 1528 } 1529 1530 const ( 1531 MaxQueriesPerHour = iota + 1 1532 MaxUpdatesPerHour 1533 MaxConnectionsPerHour 1534 MaxUserConnections 1535 ) 1536 1537 type ResourceOption struct { 1538 Type int 1539 Count int64 1540 } 1541 1542 func (r *ResourceOption) Restore(ctx *format.RestoreCtx) error { 1543 switch r.Type { 1544 case MaxQueriesPerHour: 1545 ctx.WriteKeyWord("MAX_QUERIES_PER_HOUR ") 1546 case MaxUpdatesPerHour: 1547 ctx.WriteKeyWord("MAX_UPDATES_PER_HOUR ") 1548 case MaxConnectionsPerHour: 1549 ctx.WriteKeyWord("MAX_CONNECTIONS_PER_HOUR ") 1550 case MaxUserConnections: 1551 ctx.WriteKeyWord("MAX_USER_CONNECTIONS ") 1552 default: 1553 return errors.Errorf("Unsupported ResourceOption.Type %d", r.Type) 1554 } 1555 ctx.WritePlainf("%d", r.Count) 1556 return nil 1557 } 1558 1559 const ( 1560 PasswordExpire = iota + 1 1561 PasswordExpireDefault 1562 PasswordExpireNever 1563 PasswordExpireInterval 1564 PasswordHistory 1565 PasswordHistoryDefault 1566 PasswordReuseInterval 1567 PasswordReuseDefault 1568 Lock 1569 Unlock 1570 FailedLoginAttempts 1571 PasswordLockTime 1572 PasswordLockTimeUnbounded 1573 UserCommentType 1574 UserAttributeType 1575 1576 UserResourceGroupName 1577 ) 1578 1579 type PasswordOrLockOption struct { 1580 Type int 1581 Count int64 1582 } 1583 1584 func (p *PasswordOrLockOption) Restore(ctx *format.RestoreCtx) error { 1585 switch p.Type { 1586 case PasswordExpire: 1587 ctx.WriteKeyWord("PASSWORD EXPIRE") 1588 case PasswordExpireDefault: 1589 ctx.WriteKeyWord("PASSWORD EXPIRE DEFAULT") 1590 case PasswordExpireNever: 1591 ctx.WriteKeyWord("PASSWORD EXPIRE NEVER") 1592 case PasswordExpireInterval: 1593 ctx.WriteKeyWord("PASSWORD EXPIRE INTERVAL") 1594 ctx.WritePlainf(" %d", p.Count) 1595 ctx.WriteKeyWord(" DAY") 1596 case Lock: 1597 ctx.WriteKeyWord("ACCOUNT LOCK") 1598 case Unlock: 1599 ctx.WriteKeyWord("ACCOUNT UNLOCK") 1600 case FailedLoginAttempts: 1601 ctx.WriteKeyWord("FAILED_LOGIN_ATTEMPTS") 1602 ctx.WritePlainf(" %d", p.Count) 1603 case PasswordLockTime: 1604 ctx.WriteKeyWord("PASSWORD_LOCK_TIME") 1605 ctx.WritePlainf(" %d", p.Count) 1606 case PasswordLockTimeUnbounded: 1607 ctx.WriteKeyWord("PASSWORD_LOCK_TIME UNBOUNDED") 1608 case PasswordHistory: 1609 ctx.WriteKeyWord("PASSWORD HISTORY") 1610 ctx.WritePlainf(" %d", p.Count) 1611 case PasswordHistoryDefault: 1612 ctx.WriteKeyWord("PASSWORD HISTORY DEFAULT") 1613 case PasswordReuseInterval: 1614 ctx.WriteKeyWord("PASSWORD REUSE INTERVAL") 1615 ctx.WritePlainf(" %d", p.Count) 1616 ctx.WriteKeyWord(" DAY") 1617 case PasswordReuseDefault: 1618 ctx.WriteKeyWord("PASSWORD REUSE INTERVAL DEFAULT") 1619 default: 1620 return errors.Errorf("Unsupported PasswordOrLockOption.Type %d", p.Type) 1621 } 1622 return nil 1623 } 1624 1625 type CommentOrAttributeOption struct { 1626 Type int 1627 Value string 1628 } 1629 1630 func (c *CommentOrAttributeOption) Restore(ctx *format.RestoreCtx) error { 1631 if c.Type == UserCommentType { 1632 ctx.WriteKeyWord(" COMMENT ") 1633 ctx.WriteString(c.Value) 1634 } else if c.Type == UserAttributeType { 1635 ctx.WriteKeyWord(" ATTRIBUTE ") 1636 ctx.WriteString(c.Value) 1637 } 1638 return nil 1639 } 1640 1641 type ResourceGroupNameOption struct { 1642 Value string 1643 } 1644 1645 func (c *ResourceGroupNameOption) Restore(ctx *format.RestoreCtx) error { 1646 ctx.WriteKeyWord(" RESOURCE GROUP ") 1647 ctx.WriteName(c.Value) 1648 return nil 1649 } 1650 1651 // CreateUserStmt creates user account. 1652 // See https://dev.mysql.com/doc/refman/8.0/en/create-user.html 1653 type CreateUserStmt struct { 1654 stmtNode 1655 1656 IsCreateRole bool 1657 IfNotExists bool 1658 Specs []*UserSpec 1659 AuthTokenOrTLSOptions []*AuthTokenOrTLSOption 1660 ResourceOptions []*ResourceOption 1661 PasswordOrLockOptions []*PasswordOrLockOption 1662 CommentOrAttributeOption *CommentOrAttributeOption 1663 ResourceGroupNameOption *ResourceGroupNameOption 1664 } 1665 1666 // Restore implements Node interface. 1667 func (n *CreateUserStmt) Restore(ctx *format.RestoreCtx) error { 1668 if n.IsCreateRole { 1669 ctx.WriteKeyWord("CREATE ROLE ") 1670 } else { 1671 ctx.WriteKeyWord("CREATE USER ") 1672 } 1673 if n.IfNotExists { 1674 ctx.WriteKeyWord("IF NOT EXISTS ") 1675 } 1676 for i, v := range n.Specs { 1677 if i != 0 { 1678 ctx.WritePlain(", ") 1679 } 1680 if err := v.Restore(ctx); err != nil { 1681 return errors.Annotatef(err, "An error occurred while restore CreateUserStmt.Specs[%d]", i) 1682 } 1683 } 1684 1685 if len(n.AuthTokenOrTLSOptions) != 0 { 1686 ctx.WriteKeyWord(" REQUIRE ") 1687 } 1688 1689 for i, option := range n.AuthTokenOrTLSOptions { 1690 if i != 0 { 1691 ctx.WriteKeyWord(" AND ") 1692 } 1693 if err := option.Restore(ctx); err != nil { 1694 return errors.Annotatef(err, "An error occurred while restore CreateUserStmt.AuthTokenOrTLSOptions[%d]", i) 1695 } 1696 } 1697 1698 if len(n.ResourceOptions) != 0 { 1699 ctx.WriteKeyWord(" WITH") 1700 } 1701 1702 for i, v := range n.ResourceOptions { 1703 ctx.WritePlain(" ") 1704 if err := v.Restore(ctx); err != nil { 1705 return errors.Annotatef(err, "An error occurred while restore CreateUserStmt.ResourceOptions[%d]", i) 1706 } 1707 } 1708 1709 for i, v := range n.PasswordOrLockOptions { 1710 ctx.WritePlain(" ") 1711 if err := v.Restore(ctx); err != nil { 1712 return errors.Annotatef(err, "An error occurred while restore CreateUserStmt.PasswordOrLockOptions[%d]", i) 1713 } 1714 } 1715 1716 if n.CommentOrAttributeOption != nil { 1717 if err := n.CommentOrAttributeOption.Restore(ctx); err != nil { 1718 return errors.Annotatef(err, "An error occurred while restore CreateUserStmt.CommentOrAttributeOption") 1719 } 1720 } 1721 1722 if n.ResourceGroupNameOption != nil { 1723 if err := n.ResourceGroupNameOption.Restore(ctx); err != nil { 1724 return errors.Annotatef(err, "An error occurred while restore CreateUserStmt.ResourceGroupNameOption") 1725 } 1726 } 1727 1728 return nil 1729 } 1730 1731 // Accept implements Node Accept interface. 1732 func (n *CreateUserStmt) Accept(v Visitor) (Node, bool) { 1733 newNode, skipChildren := v.Enter(n) 1734 if skipChildren { 1735 return v.Leave(newNode) 1736 } 1737 n = newNode.(*CreateUserStmt) 1738 return v.Leave(n) 1739 } 1740 1741 // SecureText implements SensitiveStatement interface. 1742 func (n *CreateUserStmt) SecureText() string { 1743 var buf bytes.Buffer 1744 buf.WriteString("create user") 1745 for _, user := range n.Specs { 1746 buf.WriteString(" ") 1747 buf.WriteString(user.SecurityString()) 1748 } 1749 return buf.String() 1750 } 1751 1752 // AlterUserStmt modifies user account. 1753 // See https://dev.mysql.com/doc/refman/8.0/en/alter-user.html 1754 type AlterUserStmt struct { 1755 stmtNode 1756 1757 IfExists bool 1758 CurrentAuth *AuthOption 1759 Specs []*UserSpec 1760 AuthTokenOrTLSOptions []*AuthTokenOrTLSOption 1761 ResourceOptions []*ResourceOption 1762 PasswordOrLockOptions []*PasswordOrLockOption 1763 CommentOrAttributeOption *CommentOrAttributeOption 1764 ResourceGroupNameOption *ResourceGroupNameOption 1765 } 1766 1767 // Restore implements Node interface. 1768 func (n *AlterUserStmt) Restore(ctx *format.RestoreCtx) error { 1769 ctx.WriteKeyWord("ALTER USER ") 1770 if n.IfExists { 1771 ctx.WriteKeyWord("IF EXISTS ") 1772 } 1773 if n.CurrentAuth != nil { 1774 ctx.WriteKeyWord("USER") 1775 ctx.WritePlain("() ") 1776 if err := n.CurrentAuth.Restore(ctx); err != nil { 1777 return errors.Annotate(err, "An error occurred while restore AlterUserStmt.CurrentAuth") 1778 } 1779 } 1780 for i, v := range n.Specs { 1781 if i != 0 { 1782 ctx.WritePlain(", ") 1783 } 1784 if err := v.Restore(ctx); err != nil { 1785 return errors.Annotatef(err, "An error occurred while restore AlterUserStmt.Specs[%d]", i) 1786 } 1787 } 1788 1789 if len(n.AuthTokenOrTLSOptions) != 0 { 1790 ctx.WriteKeyWord(" REQUIRE ") 1791 } 1792 1793 for i, option := range n.AuthTokenOrTLSOptions { 1794 if i != 0 { 1795 ctx.WriteKeyWord(" AND ") 1796 } 1797 if err := option.Restore(ctx); err != nil { 1798 return errors.Annotatef(err, "An error occurred while restore AlterUserStmt.AuthTokenOrTLSOptions[%d]", i) 1799 } 1800 } 1801 1802 if len(n.ResourceOptions) != 0 { 1803 ctx.WriteKeyWord(" WITH") 1804 } 1805 1806 for i, v := range n.ResourceOptions { 1807 ctx.WritePlain(" ") 1808 if err := v.Restore(ctx); err != nil { 1809 return errors.Annotatef(err, "An error occurred while restore AlterUserStmt.ResourceOptions[%d]", i) 1810 } 1811 } 1812 1813 for i, v := range n.PasswordOrLockOptions { 1814 ctx.WritePlain(" ") 1815 if err := v.Restore(ctx); err != nil { 1816 return errors.Annotatef(err, "An error occurred while restore AlterUserStmt.PasswordOrLockOptions[%d]", i) 1817 } 1818 } 1819 1820 if n.CommentOrAttributeOption != nil { 1821 if err := n.CommentOrAttributeOption.Restore(ctx); err != nil { 1822 return errors.Annotatef(err, "An error occurred while restore AlterUserStmt.CommentOrAttributeOption") 1823 } 1824 } 1825 1826 if n.ResourceGroupNameOption != nil { 1827 if err := n.ResourceGroupNameOption.Restore(ctx); err != nil { 1828 return errors.Annotatef(err, "An error occurred while restore AlterUserStmt.ResourceGroupNameOption") 1829 } 1830 } 1831 1832 return nil 1833 } 1834 1835 // SecureText implements SensitiveStatement interface. 1836 func (n *AlterUserStmt) SecureText() string { 1837 var buf bytes.Buffer 1838 buf.WriteString("alter user") 1839 for _, user := range n.Specs { 1840 buf.WriteString(" ") 1841 buf.WriteString(user.SecurityString()) 1842 } 1843 return buf.String() 1844 } 1845 1846 // Accept implements Node Accept interface. 1847 func (n *AlterUserStmt) Accept(v Visitor) (Node, bool) { 1848 newNode, skipChildren := v.Enter(n) 1849 if skipChildren { 1850 return v.Leave(newNode) 1851 } 1852 n = newNode.(*AlterUserStmt) 1853 return v.Leave(n) 1854 } 1855 1856 // AlterInstanceStmt modifies instance. 1857 // See https://dev.mysql.com/doc/refman/8.0/en/alter-instance.html 1858 type AlterInstanceStmt struct { 1859 stmtNode 1860 1861 ReloadTLS bool 1862 NoRollbackOnError bool 1863 } 1864 1865 // Restore implements Node interface. 1866 func (n *AlterInstanceStmt) Restore(ctx *format.RestoreCtx) error { 1867 ctx.WriteKeyWord("ALTER INSTANCE") 1868 if n.ReloadTLS { 1869 ctx.WriteKeyWord(" RELOAD TLS") 1870 } 1871 if n.NoRollbackOnError { 1872 ctx.WriteKeyWord(" NO ROLLBACK ON ERROR") 1873 } 1874 return nil 1875 } 1876 1877 // Accept implements Node Accept interface. 1878 func (n *AlterInstanceStmt) Accept(v Visitor) (Node, bool) { 1879 newNode, skipChildren := v.Enter(n) 1880 if skipChildren { 1881 return v.Leave(newNode) 1882 } 1883 n = newNode.(*AlterInstanceStmt) 1884 return v.Leave(n) 1885 } 1886 1887 // AlterRangeStmt modifies range configuration. 1888 type AlterRangeStmt struct { 1889 stmtNode 1890 RangeName model.CIStr 1891 PlacementOption *PlacementOption 1892 } 1893 1894 // Restore implements Node interface. 1895 func (n *AlterRangeStmt) Restore(ctx *format.RestoreCtx) error { 1896 ctx.WriteKeyWord("ALTER RANGE ") 1897 ctx.WriteName(n.RangeName.O) 1898 ctx.WritePlain(" ") 1899 if err := n.PlacementOption.Restore(ctx); err != nil { 1900 return errors.Annotate(err, "An error occurred while restore AlterRangeStmt.PlacementOption") 1901 } 1902 return nil 1903 } 1904 1905 // Accept implements Node Accept interface. 1906 func (n *AlterRangeStmt) Accept(v Visitor) (Node, bool) { 1907 newNode, skipChildren := v.Enter(n) 1908 if skipChildren { 1909 return v.Leave(newNode) 1910 } 1911 n = newNode.(*AlterRangeStmt) 1912 return v.Leave(n) 1913 } 1914 1915 // DropUserStmt creates user account. 1916 // See http://dev.mysql.com/doc/refman/5.7/en/drop-user.html 1917 type DropUserStmt struct { 1918 stmtNode 1919 1920 IfExists bool 1921 IsDropRole bool 1922 UserList []*auth.UserIdentity 1923 } 1924 1925 // Restore implements Node interface. 1926 func (n *DropUserStmt) Restore(ctx *format.RestoreCtx) error { 1927 if n.IsDropRole { 1928 ctx.WriteKeyWord("DROP ROLE ") 1929 } else { 1930 ctx.WriteKeyWord("DROP USER ") 1931 } 1932 if n.IfExists { 1933 ctx.WriteKeyWord("IF EXISTS ") 1934 } 1935 for i, v := range n.UserList { 1936 if i != 0 { 1937 ctx.WritePlain(", ") 1938 } 1939 if err := v.Restore(ctx); err != nil { 1940 return errors.Annotatef(err, "An error occurred while restore DropUserStmt.UserList[%d]", i) 1941 } 1942 } 1943 return nil 1944 } 1945 1946 // Accept implements Node Accept interface. 1947 func (n *DropUserStmt) Accept(v Visitor) (Node, bool) { 1948 newNode, skipChildren := v.Enter(n) 1949 if skipChildren { 1950 return v.Leave(newNode) 1951 } 1952 n = newNode.(*DropUserStmt) 1953 return v.Leave(n) 1954 } 1955 1956 // CreateBindingStmt creates sql binding hint. 1957 type CreateBindingStmt struct { 1958 stmtNode 1959 1960 GlobalScope bool 1961 OriginNode StmtNode 1962 HintedNode StmtNode 1963 PlanDigest string 1964 } 1965 1966 func (n *CreateBindingStmt) Restore(ctx *format.RestoreCtx) error { 1967 ctx.WriteKeyWord("CREATE ") 1968 if n.GlobalScope { 1969 ctx.WriteKeyWord("GLOBAL ") 1970 } else { 1971 ctx.WriteKeyWord("SESSION ") 1972 } 1973 if n.OriginNode == nil { 1974 ctx.WriteKeyWord("BINDING FROM HISTORY USING PLAN DIGEST ") 1975 ctx.WriteString(n.PlanDigest) 1976 } else { 1977 ctx.WriteKeyWord("BINDING FOR ") 1978 if err := n.OriginNode.Restore(ctx); err != nil { 1979 return errors.Trace(err) 1980 } 1981 ctx.WriteKeyWord(" USING ") 1982 if err := n.HintedNode.Restore(ctx); err != nil { 1983 return errors.Trace(err) 1984 } 1985 } 1986 return nil 1987 } 1988 1989 func (n *CreateBindingStmt) Accept(v Visitor) (Node, bool) { 1990 newNode, skipChildren := v.Enter(n) 1991 if skipChildren { 1992 return v.Leave(newNode) 1993 } 1994 n = newNode.(*CreateBindingStmt) 1995 if n.OriginNode != nil { 1996 origNode, ok := n.OriginNode.Accept(v) 1997 if !ok { 1998 return n, false 1999 } 2000 n.OriginNode = origNode.(StmtNode) 2001 hintedNode, ok := n.HintedNode.Accept(v) 2002 if !ok { 2003 return n, false 2004 } 2005 n.HintedNode = hintedNode.(StmtNode) 2006 } 2007 return v.Leave(n) 2008 } 2009 2010 // DropBindingStmt deletes sql binding hint. 2011 type DropBindingStmt struct { 2012 stmtNode 2013 2014 GlobalScope bool 2015 OriginNode StmtNode 2016 HintedNode StmtNode 2017 SQLDigest string 2018 } 2019 2020 func (n *DropBindingStmt) Restore(ctx *format.RestoreCtx) error { 2021 ctx.WriteKeyWord("DROP ") 2022 if n.GlobalScope { 2023 ctx.WriteKeyWord("GLOBAL ") 2024 } else { 2025 ctx.WriteKeyWord("SESSION ") 2026 } 2027 ctx.WriteKeyWord("BINDING FOR ") 2028 if n.OriginNode == nil { 2029 ctx.WriteKeyWord("SQL DIGEST ") 2030 ctx.WriteString(n.SQLDigest) 2031 } else { 2032 if err := n.OriginNode.Restore(ctx); err != nil { 2033 return errors.Trace(err) 2034 } 2035 if n.HintedNode != nil { 2036 ctx.WriteKeyWord(" USING ") 2037 if err := n.HintedNode.Restore(ctx); err != nil { 2038 return errors.Trace(err) 2039 } 2040 } 2041 } 2042 return nil 2043 } 2044 2045 func (n *DropBindingStmt) Accept(v Visitor) (Node, bool) { 2046 newNode, skipChildren := v.Enter(n) 2047 if skipChildren { 2048 return v.Leave(newNode) 2049 } 2050 n = newNode.(*DropBindingStmt) 2051 if n.OriginNode != nil { 2052 // OriginNode is nil means we build drop binding by sql digest 2053 origNode, ok := n.OriginNode.Accept(v) 2054 if !ok { 2055 return n, false 2056 } 2057 n.OriginNode = origNode.(StmtNode) 2058 if n.HintedNode != nil { 2059 hintedNode, ok := n.HintedNode.Accept(v) 2060 if !ok { 2061 return n, false 2062 } 2063 n.HintedNode = hintedNode.(StmtNode) 2064 } 2065 } 2066 return v.Leave(n) 2067 } 2068 2069 // BindingStatusType defines the status type for the binding 2070 type BindingStatusType int8 2071 2072 // Binding status types. 2073 const ( 2074 BindingStatusTypeEnabled BindingStatusType = iota 2075 BindingStatusTypeDisabled 2076 ) 2077 2078 // SetBindingStmt sets sql binding status. 2079 type SetBindingStmt struct { 2080 stmtNode 2081 2082 BindingStatusType BindingStatusType 2083 OriginNode StmtNode 2084 HintedNode StmtNode 2085 SQLDigest string 2086 } 2087 2088 func (n *SetBindingStmt) Restore(ctx *format.RestoreCtx) error { 2089 ctx.WriteKeyWord("SET ") 2090 ctx.WriteKeyWord("BINDING ") 2091 switch n.BindingStatusType { 2092 case BindingStatusTypeEnabled: 2093 ctx.WriteKeyWord("ENABLED ") 2094 case BindingStatusTypeDisabled: 2095 ctx.WriteKeyWord("DISABLED ") 2096 } 2097 ctx.WriteKeyWord("FOR ") 2098 if n.OriginNode == nil { 2099 ctx.WriteKeyWord("SQL DIGEST ") 2100 ctx.WriteString(n.SQLDigest) 2101 } else { 2102 if err := n.OriginNode.Restore(ctx); err != nil { 2103 return errors.Trace(err) 2104 } 2105 if n.HintedNode != nil { 2106 ctx.WriteKeyWord(" USING ") 2107 if err := n.HintedNode.Restore(ctx); err != nil { 2108 return errors.Trace(err) 2109 } 2110 } 2111 } 2112 return nil 2113 } 2114 2115 func (n *SetBindingStmt) Accept(v Visitor) (Node, bool) { 2116 newNode, skipChildren := v.Enter(n) 2117 if skipChildren { 2118 return v.Leave(newNode) 2119 } 2120 n = newNode.(*SetBindingStmt) 2121 if n.OriginNode != nil { 2122 // OriginNode is nil means we set binding stmt by sql digest 2123 origNode, ok := n.OriginNode.Accept(v) 2124 if !ok { 2125 return n, false 2126 } 2127 n.OriginNode = origNode.(StmtNode) 2128 if n.HintedNode != nil { 2129 hintedNode, ok := n.HintedNode.Accept(v) 2130 if !ok { 2131 return n, false 2132 } 2133 n.HintedNode = hintedNode.(StmtNode) 2134 } 2135 } 2136 return v.Leave(n) 2137 } 2138 2139 // Extended statistics types. 2140 const ( 2141 StatsTypeCardinality uint8 = iota 2142 StatsTypeDependency 2143 StatsTypeCorrelation 2144 ) 2145 2146 // StatisticsSpec is the specification for ADD /DROP STATISTICS. 2147 type StatisticsSpec struct { 2148 StatsName string 2149 StatsType uint8 2150 Columns []*ColumnName 2151 } 2152 2153 // CreateStatisticsStmt is a statement to create extended statistics. 2154 // Examples: 2155 // 2156 // CREATE STATISTICS stats1 (cardinality) ON t(a, b, c); 2157 // CREATE STATISTICS stats2 (dependency) ON t(a, b); 2158 // CREATE STATISTICS stats3 (correlation) ON t(a, b); 2159 type CreateStatisticsStmt struct { 2160 stmtNode 2161 2162 IfNotExists bool 2163 StatsName string 2164 StatsType uint8 2165 Table *TableName 2166 Columns []*ColumnName 2167 } 2168 2169 // Restore implements Node interface. 2170 func (n *CreateStatisticsStmt) Restore(ctx *format.RestoreCtx) error { 2171 ctx.WriteKeyWord("CREATE STATISTICS ") 2172 if n.IfNotExists { 2173 ctx.WriteKeyWord("IF NOT EXISTS ") 2174 } 2175 ctx.WriteName(n.StatsName) 2176 switch n.StatsType { 2177 case StatsTypeCardinality: 2178 ctx.WriteKeyWord(" (cardinality) ") 2179 case StatsTypeDependency: 2180 ctx.WriteKeyWord(" (dependency) ") 2181 case StatsTypeCorrelation: 2182 ctx.WriteKeyWord(" (correlation) ") 2183 } 2184 ctx.WriteKeyWord("ON ") 2185 if err := n.Table.Restore(ctx); err != nil { 2186 return errors.Annotate(err, "An error occurred while restore CreateStatisticsStmt.Table") 2187 } 2188 2189 ctx.WritePlain("(") 2190 for i, col := range n.Columns { 2191 if i != 0 { 2192 ctx.WritePlain(", ") 2193 } 2194 if err := col.Restore(ctx); err != nil { 2195 return errors.Annotatef(err, "An error occurred while restore CreateStatisticsStmt.Columns: [%v]", i) 2196 } 2197 } 2198 ctx.WritePlain(")") 2199 return nil 2200 } 2201 2202 // Accept implements Node Accept interface. 2203 func (n *CreateStatisticsStmt) Accept(v Visitor) (Node, bool) { 2204 newNode, skipChildren := v.Enter(n) 2205 if skipChildren { 2206 return v.Leave(newNode) 2207 } 2208 n = newNode.(*CreateStatisticsStmt) 2209 node, ok := n.Table.Accept(v) 2210 if !ok { 2211 return n, false 2212 } 2213 n.Table = node.(*TableName) 2214 for i, col := range n.Columns { 2215 node, ok = col.Accept(v) 2216 if !ok { 2217 return n, false 2218 } 2219 n.Columns[i] = node.(*ColumnName) 2220 } 2221 return v.Leave(n) 2222 } 2223 2224 // DropStatisticsStmt is a statement to drop extended statistics. 2225 // Examples: 2226 // 2227 // DROP STATISTICS stats1; 2228 type DropStatisticsStmt struct { 2229 stmtNode 2230 2231 StatsName string 2232 } 2233 2234 // Restore implements Node interface. 2235 func (n *DropStatisticsStmt) Restore(ctx *format.RestoreCtx) error { 2236 ctx.WriteKeyWord("DROP STATISTICS ") 2237 ctx.WriteName(n.StatsName) 2238 return nil 2239 } 2240 2241 // Accept implements Node Accept interface. 2242 func (n *DropStatisticsStmt) Accept(v Visitor) (Node, bool) { 2243 newNode, skipChildren := v.Enter(n) 2244 if skipChildren { 2245 return v.Leave(newNode) 2246 } 2247 n = newNode.(*DropStatisticsStmt) 2248 return v.Leave(n) 2249 } 2250 2251 // DoStmt is the struct for DO statement. 2252 type DoStmt struct { 2253 stmtNode 2254 2255 Exprs []ExprNode 2256 } 2257 2258 // Restore implements Node interface. 2259 func (n *DoStmt) Restore(ctx *format.RestoreCtx) error { 2260 ctx.WriteKeyWord("DO ") 2261 for i, v := range n.Exprs { 2262 if i != 0 { 2263 ctx.WritePlain(", ") 2264 } 2265 if err := v.Restore(ctx); err != nil { 2266 return errors.Annotatef(err, "An error occurred while restore DoStmt.Exprs[%d]", i) 2267 } 2268 } 2269 return nil 2270 } 2271 2272 // Accept implements Node Accept interface. 2273 func (n *DoStmt) Accept(v Visitor) (Node, bool) { 2274 newNode, skipChildren := v.Enter(n) 2275 if skipChildren { 2276 return v.Leave(newNode) 2277 } 2278 n = newNode.(*DoStmt) 2279 for i, val := range n.Exprs { 2280 node, ok := val.Accept(v) 2281 if !ok { 2282 return n, false 2283 } 2284 n.Exprs[i] = node.(ExprNode) 2285 } 2286 return v.Leave(n) 2287 } 2288 2289 // AdminStmtType is the type for admin statement. 2290 type AdminStmtType int 2291 2292 // Admin statement types. 2293 const ( 2294 AdminShowDDL = iota + 1 2295 AdminCheckTable 2296 AdminShowDDLJobs 2297 AdminCancelDDLJobs 2298 AdminPauseDDLJobs 2299 AdminResumeDDLJobs 2300 AdminCheckIndex 2301 AdminRecoverIndex 2302 AdminCleanupIndex 2303 AdminCheckIndexRange 2304 AdminShowDDLJobQueries 2305 AdminShowDDLJobQueriesWithRange 2306 AdminChecksumTable 2307 AdminShowSlow 2308 AdminShowNextRowID 2309 AdminReloadExprPushdownBlacklist 2310 AdminReloadOptRuleBlacklist 2311 AdminPluginDisable 2312 AdminPluginEnable 2313 AdminFlushBindings 2314 AdminCaptureBindings 2315 AdminEvolveBindings 2316 AdminReloadBindings 2317 AdminShowTelemetry 2318 AdminResetTelemetryID 2319 AdminReloadStatistics 2320 AdminFlushPlanCache 2321 ) 2322 2323 // HandleRange represents a range where handle value >= Begin and < End. 2324 type HandleRange struct { 2325 Begin int64 2326 End int64 2327 } 2328 2329 type StatementScope int 2330 2331 const ( 2332 StatementScopeNone StatementScope = iota 2333 StatementScopeSession 2334 StatementScopeInstance 2335 StatementScopeGlobal 2336 ) 2337 2338 // ShowSlowType defines the type for SlowSlow statement. 2339 type ShowSlowType int 2340 2341 const ( 2342 // ShowSlowTop is a ShowSlowType constant. 2343 ShowSlowTop ShowSlowType = iota 2344 // ShowSlowRecent is a ShowSlowType constant. 2345 ShowSlowRecent 2346 ) 2347 2348 // ShowSlowKind defines the kind for SlowSlow statement when the type is ShowSlowTop. 2349 type ShowSlowKind int 2350 2351 const ( 2352 // ShowSlowKindDefault is a ShowSlowKind constant. 2353 ShowSlowKindDefault ShowSlowKind = iota 2354 // ShowSlowKindInternal is a ShowSlowKind constant. 2355 ShowSlowKindInternal 2356 // ShowSlowKindAll is a ShowSlowKind constant. 2357 ShowSlowKindAll 2358 ) 2359 2360 // ShowSlow is used for the following command: 2361 // 2362 // admin show slow top [ internal | all] N 2363 // admin show slow recent N 2364 type ShowSlow struct { 2365 Tp ShowSlowType 2366 Count uint64 2367 Kind ShowSlowKind 2368 } 2369 2370 // Restore implements Node interface. 2371 func (n *ShowSlow) Restore(ctx *format.RestoreCtx) error { 2372 switch n.Tp { 2373 case ShowSlowRecent: 2374 ctx.WriteKeyWord("RECENT ") 2375 case ShowSlowTop: 2376 ctx.WriteKeyWord("TOP ") 2377 switch n.Kind { 2378 case ShowSlowKindDefault: 2379 // do nothing 2380 case ShowSlowKindInternal: 2381 ctx.WriteKeyWord("INTERNAL ") 2382 case ShowSlowKindAll: 2383 ctx.WriteKeyWord("ALL ") 2384 default: 2385 return errors.New("Unsupported kind of ShowSlowTop") 2386 } 2387 default: 2388 return errors.New("Unsupported type of ShowSlow") 2389 } 2390 ctx.WritePlainf("%d", n.Count) 2391 return nil 2392 } 2393 2394 // LimitSimple is the struct for Admin statement limit option. 2395 type LimitSimple struct { 2396 Count uint64 2397 Offset uint64 2398 } 2399 2400 // AdminStmt is the struct for Admin statement. 2401 type AdminStmt struct { 2402 stmtNode 2403 2404 Tp AdminStmtType 2405 Index string 2406 Tables []*TableName 2407 JobIDs []int64 2408 JobNumber int64 2409 2410 HandleRanges []HandleRange 2411 ShowSlow *ShowSlow 2412 Plugins []string 2413 Where ExprNode 2414 StatementScope StatementScope 2415 LimitSimple LimitSimple 2416 } 2417 2418 // Restore implements Node interface. 2419 func (n *AdminStmt) Restore(ctx *format.RestoreCtx) error { 2420 restoreTables := func() error { 2421 for i, v := range n.Tables { 2422 if i != 0 { 2423 ctx.WritePlain(", ") 2424 } 2425 if err := v.Restore(ctx); err != nil { 2426 return errors.Annotatef(err, "An error occurred while restore AdminStmt.Tables[%d]", i) 2427 } 2428 } 2429 return nil 2430 } 2431 restoreJobIDs := func() { 2432 for i, v := range n.JobIDs { 2433 if i != 0 { 2434 ctx.WritePlain(", ") 2435 } 2436 ctx.WritePlainf("%d", v) 2437 } 2438 } 2439 2440 ctx.WriteKeyWord("ADMIN ") 2441 switch n.Tp { 2442 case AdminShowDDL: 2443 ctx.WriteKeyWord("SHOW DDL") 2444 case AdminShowDDLJobs: 2445 ctx.WriteKeyWord("SHOW DDL JOBS") 2446 if n.JobNumber != 0 { 2447 ctx.WritePlainf(" %d", n.JobNumber) 2448 } 2449 if n.Where != nil { 2450 ctx.WriteKeyWord(" WHERE ") 2451 if err := n.Where.Restore(ctx); err != nil { 2452 return errors.Annotate(err, "An error occurred while restore ShowStmt.Where") 2453 } 2454 } 2455 case AdminShowNextRowID: 2456 ctx.WriteKeyWord("SHOW ") 2457 if err := restoreTables(); err != nil { 2458 return err 2459 } 2460 ctx.WriteKeyWord(" NEXT_ROW_ID") 2461 case AdminCheckTable: 2462 ctx.WriteKeyWord("CHECK TABLE ") 2463 if err := restoreTables(); err != nil { 2464 return err 2465 } 2466 case AdminCheckIndex: 2467 ctx.WriteKeyWord("CHECK INDEX ") 2468 if err := restoreTables(); err != nil { 2469 return err 2470 } 2471 ctx.WritePlainf(" %s", n.Index) 2472 case AdminRecoverIndex: 2473 ctx.WriteKeyWord("RECOVER INDEX ") 2474 if err := restoreTables(); err != nil { 2475 return err 2476 } 2477 ctx.WritePlainf(" %s", n.Index) 2478 case AdminCleanupIndex: 2479 ctx.WriteKeyWord("CLEANUP INDEX ") 2480 if err := restoreTables(); err != nil { 2481 return err 2482 } 2483 ctx.WritePlainf(" %s", n.Index) 2484 case AdminCheckIndexRange: 2485 ctx.WriteKeyWord("CHECK INDEX ") 2486 if err := restoreTables(); err != nil { 2487 return err 2488 } 2489 ctx.WritePlainf(" %s", n.Index) 2490 if n.HandleRanges != nil { 2491 ctx.WritePlain(" ") 2492 for i, v := range n.HandleRanges { 2493 if i != 0 { 2494 ctx.WritePlain(", ") 2495 } 2496 ctx.WritePlainf("(%d,%d)", v.Begin, v.End) 2497 } 2498 } 2499 case AdminChecksumTable: 2500 ctx.WriteKeyWord("CHECKSUM TABLE ") 2501 if err := restoreTables(); err != nil { 2502 return err 2503 } 2504 case AdminCancelDDLJobs: 2505 ctx.WriteKeyWord("CANCEL DDL JOBS ") 2506 restoreJobIDs() 2507 case AdminPauseDDLJobs: 2508 ctx.WriteKeyWord("PAUSE DDL JOBS ") 2509 restoreJobIDs() 2510 case AdminResumeDDLJobs: 2511 ctx.WriteKeyWord("RESUME DDL JOBS ") 2512 restoreJobIDs() 2513 case AdminShowDDLJobQueries: 2514 ctx.WriteKeyWord("SHOW DDL JOB QUERIES ") 2515 restoreJobIDs() 2516 case AdminShowDDLJobQueriesWithRange: 2517 ctx.WriteKeyWord("SHOW DDL JOB QUERIES LIMIT ") 2518 ctx.WritePlainf("%d, %d", n.LimitSimple.Offset, n.LimitSimple.Count) 2519 case AdminShowSlow: 2520 ctx.WriteKeyWord("SHOW SLOW ") 2521 if err := n.ShowSlow.Restore(ctx); err != nil { 2522 return errors.Annotate(err, "An error occurred while restore AdminStmt.ShowSlow") 2523 } 2524 case AdminReloadExprPushdownBlacklist: 2525 ctx.WriteKeyWord("RELOAD EXPR_PUSHDOWN_BLACKLIST") 2526 case AdminReloadOptRuleBlacklist: 2527 ctx.WriteKeyWord("RELOAD OPT_RULE_BLACKLIST") 2528 case AdminPluginEnable: 2529 ctx.WriteKeyWord("PLUGINS ENABLE") 2530 for i, v := range n.Plugins { 2531 if i == 0 { 2532 ctx.WritePlain(" ") 2533 } else { 2534 ctx.WritePlain(", ") 2535 } 2536 ctx.WritePlain(v) 2537 } 2538 case AdminPluginDisable: 2539 ctx.WriteKeyWord("PLUGINS DISABLE") 2540 for i, v := range n.Plugins { 2541 if i == 0 { 2542 ctx.WritePlain(" ") 2543 } else { 2544 ctx.WritePlain(", ") 2545 } 2546 ctx.WritePlain(v) 2547 } 2548 case AdminFlushBindings: 2549 ctx.WriteKeyWord("FLUSH BINDINGS") 2550 case AdminCaptureBindings: 2551 ctx.WriteKeyWord("CAPTURE BINDINGS") 2552 case AdminEvolveBindings: 2553 ctx.WriteKeyWord("EVOLVE BINDINGS") 2554 case AdminReloadBindings: 2555 ctx.WriteKeyWord("RELOAD BINDINGS") 2556 case AdminShowTelemetry: 2557 ctx.WriteKeyWord("SHOW TELEMETRY") 2558 case AdminResetTelemetryID: 2559 ctx.WriteKeyWord("RESET TELEMETRY_ID") 2560 case AdminReloadStatistics: 2561 ctx.WriteKeyWord("RELOAD STATS_EXTENDED") 2562 case AdminFlushPlanCache: 2563 if n.StatementScope == StatementScopeSession { 2564 ctx.WriteKeyWord("FLUSH SESSION PLAN_CACHE") 2565 } else if n.StatementScope == StatementScopeInstance { 2566 ctx.WriteKeyWord("FLUSH INSTANCE PLAN_CACHE") 2567 } else if n.StatementScope == StatementScopeGlobal { 2568 ctx.WriteKeyWord("FLUSH GLOBAL PLAN_CACHE") 2569 } 2570 default: 2571 return errors.New("Unsupported AdminStmt type") 2572 } 2573 return nil 2574 } 2575 2576 // Accept implements Node Accept interface. 2577 func (n *AdminStmt) Accept(v Visitor) (Node, bool) { 2578 newNode, skipChildren := v.Enter(n) 2579 if skipChildren { 2580 return v.Leave(newNode) 2581 } 2582 2583 n = newNode.(*AdminStmt) 2584 for i, val := range n.Tables { 2585 node, ok := val.Accept(v) 2586 if !ok { 2587 return n, false 2588 } 2589 n.Tables[i] = node.(*TableName) 2590 } 2591 2592 if n.Where != nil { 2593 node, ok := n.Where.Accept(v) 2594 if !ok { 2595 return n, false 2596 } 2597 n.Where = node.(ExprNode) 2598 } 2599 2600 return v.Leave(n) 2601 } 2602 2603 // RoleOrPriv is a temporary structure to be further processed into auth.RoleIdentity or PrivElem 2604 type RoleOrPriv struct { 2605 Symbols string // hold undecided symbols 2606 Node interface{} // hold auth.RoleIdentity or PrivElem that can be sure when parsing 2607 } 2608 2609 func (n *RoleOrPriv) ToRole() (*auth.RoleIdentity, error) { 2610 if n.Node != nil { 2611 if r, ok := n.Node.(*auth.RoleIdentity); ok { 2612 return r, nil 2613 } 2614 return nil, errors.Errorf("can't convert to RoleIdentity, type %T", n.Node) 2615 } 2616 return &auth.RoleIdentity{Username: n.Symbols, Hostname: "%"}, nil 2617 } 2618 2619 func (n *RoleOrPriv) ToPriv() (*PrivElem, error) { 2620 if n.Node != nil { 2621 if p, ok := n.Node.(*PrivElem); ok { 2622 return p, nil 2623 } 2624 return nil, errors.Errorf("can't convert to PrivElem, type %T", n.Node) 2625 } 2626 if len(n.Symbols) == 0 { 2627 return nil, errors.New("symbols should not be length 0") 2628 } 2629 return &PrivElem{Priv: mysql.ExtendedPriv, Name: n.Symbols}, nil 2630 } 2631 2632 // PrivElem is the privilege type and optional column list. 2633 type PrivElem struct { 2634 node 2635 2636 Priv mysql.PrivilegeType 2637 Cols []*ColumnName 2638 Name string 2639 } 2640 2641 // Restore implements Node interface. 2642 func (n *PrivElem) Restore(ctx *format.RestoreCtx) error { 2643 if n.Priv == mysql.AllPriv { 2644 ctx.WriteKeyWord("ALL") 2645 } else if n.Priv == mysql.ExtendedPriv { 2646 ctx.WriteKeyWord(n.Name) 2647 } else { 2648 str, ok := mysql.Priv2Str[n.Priv] 2649 if !ok { 2650 return errors.New("Undefined privilege type") 2651 } 2652 ctx.WriteKeyWord(str) 2653 } 2654 if n.Cols != nil { 2655 ctx.WritePlain(" (") 2656 for i, v := range n.Cols { 2657 if i != 0 { 2658 ctx.WritePlain(",") 2659 } 2660 if err := v.Restore(ctx); err != nil { 2661 return errors.Annotatef(err, "An error occurred while restore PrivElem.Cols[%d]", i) 2662 } 2663 } 2664 ctx.WritePlain(")") 2665 } 2666 return nil 2667 } 2668 2669 // Accept implements Node Accept interface. 2670 func (n *PrivElem) Accept(v Visitor) (Node, bool) { 2671 newNode, skipChildren := v.Enter(n) 2672 if skipChildren { 2673 return v.Leave(newNode) 2674 } 2675 n = newNode.(*PrivElem) 2676 for i, val := range n.Cols { 2677 node, ok := val.Accept(v) 2678 if !ok { 2679 return n, false 2680 } 2681 n.Cols[i] = node.(*ColumnName) 2682 } 2683 return v.Leave(n) 2684 } 2685 2686 // ObjectTypeType is the type for object type. 2687 type ObjectTypeType int 2688 2689 const ( 2690 // ObjectTypeNone is for empty object type. 2691 ObjectTypeNone ObjectTypeType = iota + 1 2692 // ObjectTypeTable means the following object is a table. 2693 ObjectTypeTable 2694 // ObjectTypeFunction means the following object is a stored function. 2695 ObjectTypeFunction 2696 // ObjectTypeProcedure means the following object is a stored procedure. 2697 ObjectTypeProcedure 2698 ) 2699 2700 // Restore implements Node interface. 2701 func (n ObjectTypeType) Restore(ctx *format.RestoreCtx) error { 2702 switch n { 2703 case ObjectTypeNone: 2704 // do nothing 2705 case ObjectTypeTable: 2706 ctx.WriteKeyWord("TABLE") 2707 case ObjectTypeFunction: 2708 ctx.WriteKeyWord("FUNCTION") 2709 case ObjectTypeProcedure: 2710 ctx.WriteKeyWord("PROCEDURE") 2711 default: 2712 return errors.New("Unsupported object type") 2713 } 2714 return nil 2715 } 2716 2717 // GrantLevelType is the type for grant level. 2718 type GrantLevelType int 2719 2720 const ( 2721 // GrantLevelNone is the dummy const for default value. 2722 GrantLevelNone GrantLevelType = iota + 1 2723 // GrantLevelGlobal means the privileges are administrative or apply to all databases on a given server. 2724 GrantLevelGlobal 2725 // GrantLevelDB means the privileges apply to all objects in a given database. 2726 GrantLevelDB 2727 // GrantLevelTable means the privileges apply to all columns in a given table. 2728 GrantLevelTable 2729 ) 2730 2731 // GrantLevel is used for store the privilege scope. 2732 type GrantLevel struct { 2733 Level GrantLevelType 2734 DBName string 2735 TableName string 2736 } 2737 2738 // Restore implements Node interface. 2739 func (n *GrantLevel) Restore(ctx *format.RestoreCtx) error { 2740 switch n.Level { 2741 case GrantLevelDB: 2742 if n.DBName == "" { 2743 ctx.WritePlain("*") 2744 } else { 2745 ctx.WriteName(n.DBName) 2746 ctx.WritePlain(".*") 2747 } 2748 case GrantLevelGlobal: 2749 ctx.WritePlain("*.*") 2750 case GrantLevelTable: 2751 if n.DBName != "" { 2752 ctx.WriteName(n.DBName) 2753 ctx.WritePlain(".") 2754 } 2755 ctx.WriteName(n.TableName) 2756 } 2757 return nil 2758 } 2759 2760 // RevokeStmt is the struct for REVOKE statement. 2761 type RevokeStmt struct { 2762 stmtNode 2763 2764 Privs []*PrivElem 2765 ObjectType ObjectTypeType 2766 Level *GrantLevel 2767 Users []*UserSpec 2768 } 2769 2770 // Restore implements Node interface. 2771 func (n *RevokeStmt) Restore(ctx *format.RestoreCtx) error { 2772 ctx.WriteKeyWord("REVOKE ") 2773 for i, v := range n.Privs { 2774 if i != 0 { 2775 ctx.WritePlain(", ") 2776 } 2777 if err := v.Restore(ctx); err != nil { 2778 return errors.Annotatef(err, "An error occurred while restore RevokeStmt.Privs[%d]", i) 2779 } 2780 } 2781 ctx.WriteKeyWord(" ON ") 2782 if n.ObjectType != ObjectTypeNone { 2783 if err := n.ObjectType.Restore(ctx); err != nil { 2784 return errors.Annotate(err, "An error occurred while restore RevokeStmt.ObjectType") 2785 } 2786 ctx.WritePlain(" ") 2787 } 2788 if err := n.Level.Restore(ctx); err != nil { 2789 return errors.Annotate(err, "An error occurred while restore RevokeStmt.Level") 2790 } 2791 ctx.WriteKeyWord(" FROM ") 2792 for i, v := range n.Users { 2793 if i != 0 { 2794 ctx.WritePlain(", ") 2795 } 2796 if err := v.Restore(ctx); err != nil { 2797 return errors.Annotatef(err, "An error occurred while restore RevokeStmt.Users[%d]", i) 2798 } 2799 } 2800 return nil 2801 } 2802 2803 // Accept implements Node Accept interface. 2804 func (n *RevokeStmt) Accept(v Visitor) (Node, bool) { 2805 newNode, skipChildren := v.Enter(n) 2806 if skipChildren { 2807 return v.Leave(newNode) 2808 } 2809 n = newNode.(*RevokeStmt) 2810 for i, val := range n.Privs { 2811 node, ok := val.Accept(v) 2812 if !ok { 2813 return n, false 2814 } 2815 n.Privs[i] = node.(*PrivElem) 2816 } 2817 return v.Leave(n) 2818 } 2819 2820 // RevokeStmt is the struct for REVOKE statement. 2821 type RevokeRoleStmt struct { 2822 stmtNode 2823 2824 Roles []*auth.RoleIdentity 2825 Users []*auth.UserIdentity 2826 } 2827 2828 // Restore implements Node interface. 2829 func (n *RevokeRoleStmt) Restore(ctx *format.RestoreCtx) error { 2830 ctx.WriteKeyWord("REVOKE ") 2831 for i, role := range n.Roles { 2832 if i != 0 { 2833 ctx.WritePlain(", ") 2834 } 2835 if err := role.Restore(ctx); err != nil { 2836 return errors.Annotatef(err, "An error occurred while restore RevokeRoleStmt.Roles[%d]", i) 2837 } 2838 } 2839 ctx.WriteKeyWord(" FROM ") 2840 for i, v := range n.Users { 2841 if i != 0 { 2842 ctx.WritePlain(", ") 2843 } 2844 if err := v.Restore(ctx); err != nil { 2845 return errors.Annotatef(err, "An error occurred while restore RevokeRoleStmt.Users[%d]", i) 2846 } 2847 } 2848 return nil 2849 } 2850 2851 // Accept implements Node Accept interface. 2852 func (n *RevokeRoleStmt) Accept(v Visitor) (Node, bool) { 2853 newNode, skipChildren := v.Enter(n) 2854 if skipChildren { 2855 return v.Leave(newNode) 2856 } 2857 n = newNode.(*RevokeRoleStmt) 2858 return v.Leave(n) 2859 } 2860 2861 // GrantStmt is the struct for GRANT statement. 2862 type GrantStmt struct { 2863 stmtNode 2864 2865 Privs []*PrivElem 2866 ObjectType ObjectTypeType 2867 Level *GrantLevel 2868 Users []*UserSpec 2869 AuthTokenOrTLSOptions []*AuthTokenOrTLSOption 2870 WithGrant bool 2871 } 2872 2873 // Restore implements Node interface. 2874 func (n *GrantStmt) Restore(ctx *format.RestoreCtx) error { 2875 ctx.WriteKeyWord("GRANT ") 2876 for i, v := range n.Privs { 2877 if i != 0 && v.Priv != 0 { 2878 ctx.WritePlain(", ") 2879 } else if v.Priv == 0 { 2880 ctx.WritePlain(" ") 2881 } 2882 if err := v.Restore(ctx); err != nil { 2883 return errors.Annotatef(err, "An error occurred while restore GrantStmt.Privs[%d]", i) 2884 } 2885 } 2886 ctx.WriteKeyWord(" ON ") 2887 if n.ObjectType != ObjectTypeNone { 2888 if err := n.ObjectType.Restore(ctx); err != nil { 2889 return errors.Annotate(err, "An error occurred while restore GrantStmt.ObjectType") 2890 } 2891 ctx.WritePlain(" ") 2892 } 2893 if err := n.Level.Restore(ctx); err != nil { 2894 return errors.Annotate(err, "An error occurred while restore GrantStmt.Level") 2895 } 2896 ctx.WriteKeyWord(" TO ") 2897 for i, v := range n.Users { 2898 if i != 0 { 2899 ctx.WritePlain(", ") 2900 } 2901 if err := v.Restore(ctx); err != nil { 2902 return errors.Annotatef(err, "An error occurred while restore GrantStmt.Users[%d]", i) 2903 } 2904 } 2905 if n.AuthTokenOrTLSOptions != nil { 2906 if len(n.AuthTokenOrTLSOptions) != 0 { 2907 ctx.WriteKeyWord(" REQUIRE ") 2908 } 2909 for i, option := range n.AuthTokenOrTLSOptions { 2910 if i != 0 { 2911 ctx.WriteKeyWord(" AND ") 2912 } 2913 if err := option.Restore(ctx); err != nil { 2914 return errors.Annotatef(err, "An error occurred while restore GrantStmt.AuthTokenOrTLSOptions[%d]", i) 2915 } 2916 } 2917 } 2918 if n.WithGrant { 2919 ctx.WriteKeyWord(" WITH GRANT OPTION") 2920 } 2921 return nil 2922 } 2923 2924 // SecureText implements SensitiveStatement interface. 2925 func (n *GrantStmt) SecureText() string { 2926 text := n.text 2927 // Filter "identified by xxx" because it would expose password information. 2928 idx := strings.Index(strings.ToLower(text), "identified") 2929 if idx > 0 { 2930 text = text[:idx] 2931 } 2932 return text 2933 } 2934 2935 // Accept implements Node Accept interface. 2936 func (n *GrantStmt) Accept(v Visitor) (Node, bool) { 2937 newNode, skipChildren := v.Enter(n) 2938 if skipChildren { 2939 return v.Leave(newNode) 2940 } 2941 n = newNode.(*GrantStmt) 2942 for i, val := range n.Privs { 2943 node, ok := val.Accept(v) 2944 if !ok { 2945 return n, false 2946 } 2947 n.Privs[i] = node.(*PrivElem) 2948 } 2949 return v.Leave(n) 2950 } 2951 2952 // GrantProxyStmt is the struct for GRANT PROXY statement. 2953 type GrantProxyStmt struct { 2954 stmtNode 2955 2956 LocalUser *auth.UserIdentity 2957 ExternalUsers []*auth.UserIdentity 2958 WithGrant bool 2959 } 2960 2961 // Accept implements Node Accept interface. 2962 func (n *GrantProxyStmt) Accept(v Visitor) (Node, bool) { 2963 newNode, skipChildren := v.Enter(n) 2964 if skipChildren { 2965 return v.Leave(newNode) 2966 } 2967 n = newNode.(*GrantProxyStmt) 2968 return v.Leave(n) 2969 } 2970 2971 // Restore implements Node interface. 2972 func (n *GrantProxyStmt) Restore(ctx *format.RestoreCtx) error { 2973 ctx.WriteKeyWord("GRANT PROXY ON ") 2974 if err := n.LocalUser.Restore(ctx); err != nil { 2975 return errors.Annotatef(err, "An error occurred while restore GrantProxyStmt.LocalUser") 2976 } 2977 ctx.WriteKeyWord(" TO ") 2978 for i, v := range n.ExternalUsers { 2979 if i != 0 { 2980 ctx.WritePlain(", ") 2981 } 2982 if err := v.Restore(ctx); err != nil { 2983 return errors.Annotatef(err, "An error occurred while restore GrantProxyStmt.ExternalUsers[%d]", i) 2984 } 2985 } 2986 if n.WithGrant { 2987 ctx.WriteKeyWord(" WITH GRANT OPTION") 2988 } 2989 return nil 2990 } 2991 2992 // GrantRoleStmt is the struct for GRANT TO statement. 2993 type GrantRoleStmt struct { 2994 stmtNode 2995 2996 Roles []*auth.RoleIdentity 2997 Users []*auth.UserIdentity 2998 } 2999 3000 // Accept implements Node Accept interface. 3001 func (n *GrantRoleStmt) Accept(v Visitor) (Node, bool) { 3002 newNode, skipChildren := v.Enter(n) 3003 if skipChildren { 3004 return v.Leave(newNode) 3005 } 3006 n = newNode.(*GrantRoleStmt) 3007 return v.Leave(n) 3008 } 3009 3010 // Restore implements Node interface. 3011 func (n *GrantRoleStmt) Restore(ctx *format.RestoreCtx) error { 3012 ctx.WriteKeyWord("GRANT ") 3013 if len(n.Roles) > 0 { 3014 for i, role := range n.Roles { 3015 if i != 0 { 3016 ctx.WritePlain(", ") 3017 } 3018 if err := role.Restore(ctx); err != nil { 3019 return errors.Annotatef(err, "An error occurred while restore GrantRoleStmt.Roles[%d]", i) 3020 } 3021 } 3022 } 3023 ctx.WriteKeyWord(" TO ") 3024 for i, v := range n.Users { 3025 if i != 0 { 3026 ctx.WritePlain(", ") 3027 } 3028 if err := v.Restore(ctx); err != nil { 3029 return errors.Annotatef(err, "An error occurred while restore GrantStmt.Users[%d]", i) 3030 } 3031 } 3032 return nil 3033 } 3034 3035 // SecureText implements SensitiveStatement interface. 3036 func (n *GrantRoleStmt) SecureText() string { 3037 text := n.text 3038 // Filter "identified by xxx" because it would expose password information. 3039 idx := strings.Index(strings.ToLower(text), "identified") 3040 if idx > 0 { 3041 text = text[:idx] 3042 } 3043 return text 3044 } 3045 3046 // ShutdownStmt is a statement to stop the TiDB server. 3047 // See https://dev.mysql.com/doc/refman/5.7/en/shutdown.html 3048 type ShutdownStmt struct { 3049 stmtNode 3050 } 3051 3052 // Restore implements Node interface. 3053 func (n *ShutdownStmt) Restore(ctx *format.RestoreCtx) error { 3054 ctx.WriteKeyWord("SHUTDOWN") 3055 return nil 3056 } 3057 3058 // Accept implements Node Accept interface. 3059 func (n *ShutdownStmt) Accept(v Visitor) (Node, bool) { 3060 newNode, skipChildren := v.Enter(n) 3061 if skipChildren { 3062 return v.Leave(newNode) 3063 } 3064 n = newNode.(*ShutdownStmt) 3065 return v.Leave(n) 3066 } 3067 3068 // RestartStmt is a statement to restart the TiDB server. 3069 // See https://dev.mysql.com/doc/refman/8.0/en/restart.html 3070 type RestartStmt struct { 3071 stmtNode 3072 } 3073 3074 // Restore implements Node interface. 3075 func (n *RestartStmt) Restore(ctx *format.RestoreCtx) error { 3076 ctx.WriteKeyWord("RESTART") 3077 return nil 3078 } 3079 3080 // Accept implements Node Accept interface. 3081 func (n *RestartStmt) Accept(v Visitor) (Node, bool) { 3082 newNode, skipChildren := v.Enter(n) 3083 if skipChildren { 3084 return v.Leave(newNode) 3085 } 3086 n = newNode.(*RestartStmt) 3087 return v.Leave(n) 3088 } 3089 3090 // HelpStmt is a statement for server side help 3091 // See https://dev.mysql.com/doc/refman/8.0/en/help.html 3092 type HelpStmt struct { 3093 stmtNode 3094 3095 Topic string 3096 } 3097 3098 // Restore implements Node interface. 3099 func (n *HelpStmt) Restore(ctx *format.RestoreCtx) error { 3100 ctx.WriteKeyWord("HELP ") 3101 ctx.WriteString(n.Topic) 3102 return nil 3103 } 3104 3105 // Accept implements Node Accept interface. 3106 func (n *HelpStmt) Accept(v Visitor) (Node, bool) { 3107 newNode, skipChildren := v.Enter(n) 3108 if skipChildren { 3109 return v.Leave(newNode) 3110 } 3111 n = newNode.(*HelpStmt) 3112 return v.Leave(n) 3113 } 3114 3115 // RenameUserStmt is a statement to rename a user. 3116 // See http://dev.mysql.com/doc/refman/5.7/en/rename-user.html 3117 type RenameUserStmt struct { 3118 stmtNode 3119 3120 UserToUsers []*UserToUser 3121 } 3122 3123 // Restore implements Node interface. 3124 func (n *RenameUserStmt) Restore(ctx *format.RestoreCtx) error { 3125 ctx.WriteKeyWord("RENAME USER ") 3126 for index, user2user := range n.UserToUsers { 3127 if index != 0 { 3128 ctx.WritePlain(", ") 3129 } 3130 if err := user2user.Restore(ctx); err != nil { 3131 return errors.Annotate(err, "An error occurred while restore RenameUserStmt.UserToUsers") 3132 } 3133 } 3134 return nil 3135 } 3136 3137 // Accept implements Node Accept interface. 3138 func (n *RenameUserStmt) Accept(v Visitor) (Node, bool) { 3139 newNode, skipChildren := v.Enter(n) 3140 if skipChildren { 3141 return v.Leave(newNode) 3142 } 3143 n = newNode.(*RenameUserStmt) 3144 3145 for i, t := range n.UserToUsers { 3146 node, ok := t.Accept(v) 3147 if !ok { 3148 return n, false 3149 } 3150 n.UserToUsers[i] = node.(*UserToUser) 3151 } 3152 return v.Leave(n) 3153 } 3154 3155 // UserToUser represents renaming old user to new user used in RenameUserStmt. 3156 type UserToUser struct { 3157 node 3158 OldUser *auth.UserIdentity 3159 NewUser *auth.UserIdentity 3160 } 3161 3162 // Restore implements Node interface. 3163 func (n *UserToUser) Restore(ctx *format.RestoreCtx) error { 3164 if err := n.OldUser.Restore(ctx); err != nil { 3165 return errors.Annotate(err, "An error occurred while restore UserToUser.OldUser") 3166 } 3167 ctx.WriteKeyWord(" TO ") 3168 if err := n.NewUser.Restore(ctx); err != nil { 3169 return errors.Annotate(err, "An error occurred while restore UserToUser.NewUser") 3170 } 3171 return nil 3172 } 3173 3174 // Accept implements Node Accept interface. 3175 func (n *UserToUser) Accept(v Visitor) (Node, bool) { 3176 newNode, skipChildren := v.Enter(n) 3177 if skipChildren { 3178 return v.Leave(newNode) 3179 } 3180 n = newNode.(*UserToUser) 3181 return v.Leave(n) 3182 } 3183 3184 type BRIEKind uint8 3185 type BRIEOptionType uint16 3186 3187 const ( 3188 BRIEKindBackup BRIEKind = iota 3189 BRIEKindCancelJob 3190 BRIEKindStreamStart 3191 BRIEKindStreamMetaData 3192 BRIEKindStreamStatus 3193 BRIEKindStreamPause 3194 BRIEKindStreamResume 3195 BRIEKindStreamStop 3196 BRIEKindStreamPurge 3197 BRIEKindRestore 3198 BRIEKindRestorePIT 3199 BRIEKindShowJob 3200 BRIEKindShowQuery 3201 BRIEKindShowBackupMeta 3202 // common BRIE options 3203 BRIEOptionRateLimit BRIEOptionType = iota + 1 3204 BRIEOptionConcurrency 3205 BRIEOptionChecksum 3206 BRIEOptionSendCreds 3207 BRIEOptionCheckpoint 3208 BRIEOptionStartTS 3209 BRIEOptionUntilTS 3210 // backup options 3211 BRIEOptionBackupTimeAgo 3212 BRIEOptionBackupTS 3213 BRIEOptionBackupTSO 3214 BRIEOptionLastBackupTS 3215 BRIEOptionLastBackupTSO 3216 BRIEOptionGCTTL 3217 // restore options 3218 BRIEOptionOnline 3219 BRIEOptionFullBackupStorage 3220 BRIEOptionRestoredTS 3221 // import options 3222 BRIEOptionAnalyze 3223 BRIEOptionBackend 3224 BRIEOptionOnDuplicate 3225 BRIEOptionSkipSchemaFiles 3226 BRIEOptionStrictFormat 3227 BRIEOptionTiKVImporter 3228 BRIEOptionResume 3229 // CSV options 3230 BRIEOptionCSVBackslashEscape 3231 BRIEOptionCSVDelimiter 3232 BRIEOptionCSVHeader 3233 BRIEOptionCSVNotNull 3234 BRIEOptionCSVNull 3235 BRIEOptionCSVSeparator 3236 BRIEOptionCSVTrimLastSeparators 3237 3238 BRIECSVHeaderIsColumns = ^uint64(0) 3239 ) 3240 3241 type BRIEOptionLevel uint64 3242 3243 const ( 3244 BRIEOptionLevelOff BRIEOptionLevel = iota // equals FALSE 3245 BRIEOptionLevelRequired // equals TRUE 3246 BRIEOptionLevelOptional 3247 ) 3248 3249 func (kind BRIEKind) String() string { 3250 switch kind { 3251 case BRIEKindBackup: 3252 return "BACKUP" 3253 case BRIEKindRestore: 3254 return "RESTORE" 3255 case BRIEKindStreamStart: 3256 return "BACKUP LOGS" 3257 case BRIEKindStreamStop: 3258 return "STOP BACKUP LOGS" 3259 case BRIEKindStreamPause: 3260 return "PAUSE BACKUP LOGS" 3261 case BRIEKindStreamResume: 3262 return "RESUME BACKUP LOGS" 3263 case BRIEKindStreamStatus: 3264 return "SHOW BACKUP LOGS STATUS" 3265 case BRIEKindStreamMetaData: 3266 return "SHOW BACKUP LOGS METADATA" 3267 case BRIEKindStreamPurge: 3268 return "PURGE BACKUP LOGS" 3269 case BRIEKindRestorePIT: 3270 return "RESTORE POINT" 3271 case BRIEKindShowJob: 3272 return "SHOW BR JOB" 3273 case BRIEKindShowQuery: 3274 return "SHOW BR JOB QUERY" 3275 case BRIEKindCancelJob: 3276 return "CANCEL BR JOB" 3277 case BRIEKindShowBackupMeta: 3278 return "SHOW BACKUP METADATA" 3279 default: 3280 return "" 3281 } 3282 } 3283 3284 func (kind BRIEOptionType) String() string { 3285 switch kind { 3286 case BRIEOptionRateLimit: 3287 return "RATE_LIMIT" 3288 case BRIEOptionConcurrency: 3289 return "CONCURRENCY" 3290 case BRIEOptionChecksum: 3291 return "CHECKSUM" 3292 case BRIEOptionSendCreds: 3293 return "SEND_CREDENTIALS_TO_TIKV" 3294 case BRIEOptionBackupTimeAgo, BRIEOptionBackupTS, BRIEOptionBackupTSO: 3295 return "SNAPSHOT" 3296 case BRIEOptionLastBackupTS, BRIEOptionLastBackupTSO: 3297 return "LAST_BACKUP" 3298 case BRIEOptionOnline: 3299 return "ONLINE" 3300 case BRIEOptionCheckpoint: 3301 return "CHECKPOINT" 3302 case BRIEOptionAnalyze: 3303 return "ANALYZE" 3304 case BRIEOptionBackend: 3305 return "BACKEND" 3306 case BRIEOptionOnDuplicate: 3307 return "ON_DUPLICATE" 3308 case BRIEOptionSkipSchemaFiles: 3309 return "SKIP_SCHEMA_FILES" 3310 case BRIEOptionStrictFormat: 3311 return "STRICT_FORMAT" 3312 case BRIEOptionTiKVImporter: 3313 return "TIKV_IMPORTER" 3314 case BRIEOptionResume: 3315 return "RESUME" 3316 case BRIEOptionCSVBackslashEscape: 3317 return "CSV_BACKSLASH_ESCAPE" 3318 case BRIEOptionCSVDelimiter: 3319 return "CSV_DELIMITER" 3320 case BRIEOptionCSVHeader: 3321 return "CSV_HEADER" 3322 case BRIEOptionCSVNotNull: 3323 return "CSV_NOT_NULL" 3324 case BRIEOptionCSVNull: 3325 return "CSV_NULL" 3326 case BRIEOptionCSVSeparator: 3327 return "CSV_SEPARATOR" 3328 case BRIEOptionCSVTrimLastSeparators: 3329 return "CSV_TRIM_LAST_SEPARATORS" 3330 case BRIEOptionFullBackupStorage: 3331 return "FULL_BACKUP_STORAGE" 3332 case BRIEOptionRestoredTS: 3333 return "RESTORED_TS" 3334 case BRIEOptionStartTS: 3335 return "START_TS" 3336 case BRIEOptionUntilTS: 3337 return "UNTIL_TS" 3338 case BRIEOptionGCTTL: 3339 return "GC_TTL" 3340 default: 3341 return "" 3342 } 3343 } 3344 3345 func (level BRIEOptionLevel) String() string { 3346 switch level { 3347 case BRIEOptionLevelOff: 3348 return "OFF" 3349 case BRIEOptionLevelOptional: 3350 return "OPTIONAL" 3351 case BRIEOptionLevelRequired: 3352 return "REQUIRED" 3353 default: 3354 return "" 3355 } 3356 } 3357 3358 type BRIEOption struct { 3359 Tp BRIEOptionType 3360 StrValue string 3361 UintValue uint64 3362 } 3363 3364 func (opt *BRIEOption) Restore(ctx *format.RestoreCtx) error { 3365 ctx.WriteKeyWord(opt.Tp.String()) 3366 ctx.WritePlain(" = ") 3367 switch opt.Tp { 3368 case BRIEOptionBackupTS, BRIEOptionLastBackupTS, BRIEOptionBackend, BRIEOptionOnDuplicate, BRIEOptionTiKVImporter, BRIEOptionCSVDelimiter, BRIEOptionCSVNull, BRIEOptionCSVSeparator, BRIEOptionFullBackupStorage, BRIEOptionRestoredTS, BRIEOptionStartTS, BRIEOptionUntilTS, BRIEOptionGCTTL: 3369 ctx.WriteString(opt.StrValue) 3370 case BRIEOptionBackupTimeAgo: 3371 ctx.WritePlainf("%d ", opt.UintValue/1000) 3372 ctx.WriteKeyWord("MICROSECOND AGO") 3373 case BRIEOptionRateLimit: 3374 ctx.WritePlainf("%d ", opt.UintValue/1048576) 3375 ctx.WriteKeyWord("MB") 3376 ctx.WritePlain("/") 3377 ctx.WriteKeyWord("SECOND") 3378 case BRIEOptionCSVHeader: 3379 if opt.UintValue == BRIECSVHeaderIsColumns { 3380 ctx.WriteKeyWord("COLUMNS") 3381 } else { 3382 ctx.WritePlainf("%d", opt.UintValue) 3383 } 3384 case BRIEOptionChecksum, BRIEOptionAnalyze: 3385 // BACKUP/RESTORE doesn't support OPTIONAL value for now, should warn at executor 3386 ctx.WriteKeyWord(BRIEOptionLevel(opt.UintValue).String()) 3387 default: 3388 ctx.WritePlainf("%d", opt.UintValue) 3389 } 3390 return nil 3391 } 3392 3393 // BRIEStmt is a statement for backup, restore, import and export. 3394 type BRIEStmt struct { 3395 stmtNode 3396 3397 Kind BRIEKind 3398 Schemas []string 3399 Tables []*TableName 3400 Storage string 3401 JobID int64 3402 Options []*BRIEOption 3403 } 3404 3405 func (n *BRIEStmt) Accept(v Visitor) (Node, bool) { 3406 newNode, skipChildren := v.Enter(n) 3407 if skipChildren { 3408 return v.Leave(newNode) 3409 } 3410 n = newNode.(*BRIEStmt) 3411 for i, val := range n.Tables { 3412 node, ok := val.Accept(v) 3413 if !ok { 3414 return n, false 3415 } 3416 n.Tables[i] = node.(*TableName) 3417 } 3418 return v.Leave(n) 3419 } 3420 3421 func (n *BRIEStmt) Restore(ctx *format.RestoreCtx) error { 3422 ctx.WriteKeyWord(n.Kind.String()) 3423 3424 switch n.Kind { 3425 case BRIEKindRestore, BRIEKindBackup: 3426 switch { 3427 case len(n.Tables) != 0: 3428 ctx.WriteKeyWord(" TABLE ") 3429 for index, table := range n.Tables { 3430 if index != 0 { 3431 ctx.WritePlain(", ") 3432 } 3433 if err := table.Restore(ctx); err != nil { 3434 return errors.Annotatef(err, "An error occurred while restore BRIEStmt.Tables[%d]", index) 3435 } 3436 } 3437 case len(n.Schemas) != 0: 3438 ctx.WriteKeyWord(" DATABASE ") 3439 for index, schema := range n.Schemas { 3440 if index != 0 { 3441 ctx.WritePlain(", ") 3442 } 3443 ctx.WriteName(schema) 3444 } 3445 default: 3446 ctx.WriteKeyWord(" DATABASE") 3447 ctx.WritePlain(" *") 3448 } 3449 3450 if n.Kind == BRIEKindBackup { 3451 ctx.WriteKeyWord(" TO ") 3452 ctx.WriteString(n.Storage) 3453 } else { 3454 ctx.WriteKeyWord(" FROM ") 3455 ctx.WriteString(n.Storage) 3456 } 3457 case BRIEKindCancelJob, BRIEKindShowJob, BRIEKindShowQuery: 3458 ctx.WritePlainf(" %d", n.JobID) 3459 case BRIEKindStreamStart: 3460 ctx.WriteKeyWord(" TO ") 3461 ctx.WriteString(n.Storage) 3462 case BRIEKindRestorePIT, BRIEKindStreamMetaData, BRIEKindShowBackupMeta, BRIEKindStreamPurge: 3463 ctx.WriteKeyWord(" FROM ") 3464 ctx.WriteString(n.Storage) 3465 } 3466 3467 for _, opt := range n.Options { 3468 ctx.WritePlain(" ") 3469 if err := opt.Restore(ctx); err != nil { 3470 return err 3471 } 3472 } 3473 3474 return nil 3475 } 3476 3477 // RedactURL redacts the secret tokens in the URL. only S3 url need redaction for now. 3478 // if the url is not a valid url, return the original string. 3479 func RedactURL(str string) string { 3480 // FIXME: this solution is not scalable, and duplicates some logic from BR. 3481 u, err := url.Parse(str) 3482 if err != nil { 3483 return str 3484 } 3485 scheme := u.Scheme 3486 failpoint.Inject("forceRedactURL", func() { 3487 scheme = "s3" 3488 }) 3489 if strings.ToLower(scheme) == "s3" { 3490 values := u.Query() 3491 for k := range values { 3492 // see below on why we normalize key 3493 // https://github.com/pingcap/tidb/blob/a7c0d95f16ea2582bb569278c3f829403e6c3a7e/br/pkg/storage/parse.go#L163 3494 normalizedKey := strings.ToLower(strings.ReplaceAll(k, "_", "-")) 3495 if normalizedKey == "access-key" || normalizedKey == "secret-access-key" || normalizedKey == "session-token" { 3496 values[k] = []string{"xxxxxx"} 3497 } 3498 } 3499 u.RawQuery = values.Encode() 3500 } 3501 return u.String() 3502 } 3503 3504 // SecureText implements SensitiveStmtNode 3505 func (n *BRIEStmt) SecureText() string { 3506 redactedStmt := &BRIEStmt{ 3507 Kind: n.Kind, 3508 Schemas: n.Schemas, 3509 Tables: n.Tables, 3510 Storage: RedactURL(n.Storage), 3511 Options: n.Options, 3512 } 3513 3514 var sb strings.Builder 3515 _ = redactedStmt.Restore(format.NewRestoreCtx(format.DefaultRestoreFlags, &sb)) 3516 return sb.String() 3517 } 3518 3519 type LoadDataActionTp int 3520 3521 const ( 3522 LoadDataPause LoadDataActionTp = iota 3523 LoadDataResume 3524 LoadDataCancel 3525 LoadDataDrop 3526 ) 3527 3528 // LoadDataActionStmt represent PAUSE/RESUME/CANCEL/DROP LOAD DATA JOB statement. 3529 type LoadDataActionStmt struct { 3530 stmtNode 3531 3532 Tp LoadDataActionTp 3533 JobID int64 3534 } 3535 3536 func (n *LoadDataActionStmt) Accept(v Visitor) (Node, bool) { 3537 newNode, _ := v.Enter(n) 3538 return v.Leave(newNode) 3539 } 3540 3541 func (n *LoadDataActionStmt) Restore(ctx *format.RestoreCtx) error { 3542 switch n.Tp { 3543 case LoadDataPause: 3544 ctx.WriteKeyWord("PAUSE LOAD DATA JOB ") 3545 case LoadDataResume: 3546 ctx.WriteKeyWord("RESUME LOAD DATA JOB ") 3547 case LoadDataCancel: 3548 ctx.WriteKeyWord("CANCEL LOAD DATA JOB ") 3549 case LoadDataDrop: 3550 ctx.WriteKeyWord("DROP LOAD DATA JOB ") 3551 default: 3552 return errors.Errorf("invalid load data action type: %d", n.Tp) 3553 } 3554 ctx.WritePlainf("%d", n.JobID) 3555 return nil 3556 } 3557 3558 type ImportIntoActionTp string 3559 3560 const ( 3561 ImportIntoCancel ImportIntoActionTp = "cancel" 3562 ) 3563 3564 // ImportIntoActionStmt represent CANCEL IMPORT INTO JOB statement. 3565 // will support pause/resume/drop later. 3566 type ImportIntoActionStmt struct { 3567 stmtNode 3568 3569 Tp ImportIntoActionTp 3570 JobID int64 3571 } 3572 3573 func (n *ImportIntoActionStmt) Accept(v Visitor) (Node, bool) { 3574 newNode, _ := v.Enter(n) 3575 return v.Leave(newNode) 3576 } 3577 3578 func (n *ImportIntoActionStmt) Restore(ctx *format.RestoreCtx) error { 3579 if n.Tp != ImportIntoCancel { 3580 return errors.Errorf("invalid IMPORT INTO action type: %s", n.Tp) 3581 } 3582 ctx.WriteKeyWord("CANCEL IMPORT JOB ") 3583 ctx.WritePlainf("%d", n.JobID) 3584 return nil 3585 } 3586 3587 // Ident is the table identifier composed of schema name and table name. 3588 type Ident struct { 3589 Schema model.CIStr 3590 Name model.CIStr 3591 } 3592 3593 // String implements fmt.Stringer interface. 3594 func (i Ident) String() string { 3595 if i.Schema.O == "" { 3596 return i.Name.O 3597 } 3598 return fmt.Sprintf("%s.%s", i.Schema, i.Name) 3599 } 3600 3601 // SelectStmtOpts wrap around select hints and switches 3602 type SelectStmtOpts struct { 3603 Distinct bool 3604 SQLBigResult bool 3605 SQLBufferResult bool 3606 SQLCache bool 3607 SQLSmallResult bool 3608 CalcFoundRows bool 3609 StraightJoin bool 3610 Priority mysql.PriorityEnum 3611 TableHints []*TableOptimizerHint 3612 ExplicitAll bool 3613 } 3614 3615 // TableOptimizerHint is Table level optimizer hint 3616 type TableOptimizerHint struct { 3617 node 3618 // HintName is the name or alias of the table(s) which the hint will affect. 3619 // Table hints has no schema info 3620 // It allows only table name or alias (if table has an alias) 3621 HintName model.CIStr 3622 // HintData is the payload of the hint. The actual type of this field 3623 // is defined differently as according `HintName`. Define as following: 3624 // 3625 // Statement Execution Time Optimizer Hints 3626 // See https://dev.mysql.com/doc/refman/5.7/en/optimizer-hints.html#optimizer-hints-execution-time 3627 // - MAX_EXECUTION_TIME => uint64 3628 // - MEMORY_QUOTA => int64 3629 // - QUERY_TYPE => model.CIStr 3630 // 3631 // Time Range is used to hint the time range of inspection tables 3632 // e.g: select /*+ time_range('','') */ * from information_schema.inspection_result. 3633 // - TIME_RANGE => ast.HintTimeRange 3634 // - READ_FROM_STORAGE => model.CIStr 3635 // - USE_TOJA => bool 3636 // - NTH_PLAN => int64 3637 HintData interface{} 3638 // QBName is the default effective query block of this hint. 3639 QBName model.CIStr 3640 Tables []HintTable 3641 Indexes []model.CIStr 3642 } 3643 3644 // HintTimeRange is the payload of `TIME_RANGE` hint 3645 type HintTimeRange struct { 3646 From string 3647 To string 3648 } 3649 3650 // HintSetVar is the payload of `SET_VAR` hint 3651 type HintSetVar struct { 3652 VarName string 3653 Value string 3654 } 3655 3656 // HintTable is table in the hint. It may have query block info. 3657 type HintTable struct { 3658 DBName model.CIStr 3659 TableName model.CIStr 3660 QBName model.CIStr 3661 PartitionList []model.CIStr 3662 } 3663 3664 func (ht *HintTable) Restore(ctx *format.RestoreCtx) { 3665 if ht.DBName.L != "" { 3666 ctx.WriteName(ht.DBName.String()) 3667 ctx.WriteKeyWord(".") 3668 } 3669 ctx.WriteName(ht.TableName.String()) 3670 if ht.QBName.L != "" { 3671 ctx.WriteKeyWord("@") 3672 ctx.WriteName(ht.QBName.String()) 3673 } 3674 if len(ht.PartitionList) > 0 { 3675 ctx.WriteKeyWord(" PARTITION") 3676 ctx.WritePlain("(") 3677 for i, p := range ht.PartitionList { 3678 if i > 0 { 3679 ctx.WritePlain(", ") 3680 } 3681 ctx.WriteName(p.String()) 3682 } 3683 ctx.WritePlain(")") 3684 } 3685 } 3686 3687 // Restore implements Node interface. 3688 func (n *TableOptimizerHint) Restore(ctx *format.RestoreCtx) error { 3689 ctx.WriteKeyWord(n.HintName.String()) 3690 ctx.WritePlain("(") 3691 if n.QBName.L != "" { 3692 if n.HintName.L != "qb_name" { 3693 ctx.WriteKeyWord("@") 3694 } 3695 ctx.WriteName(n.QBName.String()) 3696 } 3697 if n.HintName.L == "qb_name" && len(n.Tables) == 0 { 3698 ctx.WritePlain(")") 3699 return nil 3700 } 3701 // Hints without args except query block. 3702 switch n.HintName.L { 3703 case "mpp_1phase_agg", "mpp_2phase_agg", "hash_agg", "stream_agg", "agg_to_cop", "read_consistent_replica", "no_index_merge", "ignore_plan_cache", "limit_to_cop", "straight_join", "merge", "no_decorrelate": 3704 ctx.WritePlain(")") 3705 return nil 3706 } 3707 if n.QBName.L != "" { 3708 ctx.WritePlain(" ") 3709 } 3710 // Hints with args except query block. 3711 switch n.HintName.L { 3712 case "max_execution_time": 3713 ctx.WritePlainf("%d", n.HintData.(uint64)) 3714 case "resource_group": 3715 ctx.WriteName(n.HintData.(string)) 3716 case "nth_plan": 3717 ctx.WritePlainf("%d", n.HintData.(int64)) 3718 case "tidb_hj", "tidb_smj", "tidb_inlj", "hash_join", "hash_join_build", "hash_join_probe", "merge_join", "inl_join", "broadcast_join", "shuffle_join", "inl_hash_join", "inl_merge_join", "leading": 3719 for i, table := range n.Tables { 3720 if i != 0 { 3721 ctx.WritePlain(", ") 3722 } 3723 table.Restore(ctx) 3724 } 3725 case "use_index", "ignore_index", "use_index_merge", "force_index", "order_index", "no_order_index": 3726 n.Tables[0].Restore(ctx) 3727 ctx.WritePlain(" ") 3728 for i, index := range n.Indexes { 3729 if i != 0 { 3730 ctx.WritePlain(", ") 3731 } 3732 ctx.WriteName(index.String()) 3733 } 3734 case "qb_name": 3735 if len(n.Tables) > 0 { 3736 ctx.WritePlain(", ") 3737 for i, table := range n.Tables { 3738 if i != 0 { 3739 ctx.WritePlain(". ") 3740 } 3741 table.Restore(ctx) 3742 } 3743 } 3744 case "use_toja", "use_cascades": 3745 if n.HintData.(bool) { 3746 ctx.WritePlain("TRUE") 3747 } else { 3748 ctx.WritePlain("FALSE") 3749 } 3750 case "query_type": 3751 ctx.WriteKeyWord(n.HintData.(model.CIStr).String()) 3752 case "memory_quota": 3753 ctx.WritePlainf("%d MB", n.HintData.(int64)/1024/1024) 3754 case "read_from_storage": 3755 ctx.WriteKeyWord(n.HintData.(model.CIStr).String()) 3756 for i, table := range n.Tables { 3757 if i == 0 { 3758 ctx.WritePlain("[") 3759 } 3760 table.Restore(ctx) 3761 if i == len(n.Tables)-1 { 3762 ctx.WritePlain("]") 3763 } else { 3764 ctx.WritePlain(", ") 3765 } 3766 } 3767 case "time_range": 3768 hintData := n.HintData.(HintTimeRange) 3769 ctx.WriteString(hintData.From) 3770 ctx.WritePlain(", ") 3771 ctx.WriteString(hintData.To) 3772 case "set_var": 3773 hintData := n.HintData.(HintSetVar) 3774 ctx.WritePlain(hintData.VarName) 3775 ctx.WritePlain(" = ") 3776 ctx.WritePlain(hintData.Value) 3777 } 3778 ctx.WritePlain(")") 3779 return nil 3780 } 3781 3782 // Accept implements Node Accept interface. 3783 func (n *TableOptimizerHint) Accept(v Visitor) (Node, bool) { 3784 newNode, skipChildren := v.Enter(n) 3785 if skipChildren { 3786 return v.Leave(newNode) 3787 } 3788 n = newNode.(*TableOptimizerHint) 3789 return v.Leave(n) 3790 } 3791 3792 // TextString represent a string, it can be a binary literal. 3793 type TextString struct { 3794 Value string 3795 IsBinaryLiteral bool 3796 } 3797 3798 type BinaryLiteral interface { 3799 ToString() string 3800 } 3801 3802 // NewDecimal creates a types.Decimal value, it's provided by parser driver. 3803 var NewDecimal func(string) (interface{}, error) 3804 3805 // NewHexLiteral creates a types.HexLiteral value, it's provided by parser driver. 3806 var NewHexLiteral func(string) (interface{}, error) 3807 3808 // NewBitLiteral creates a types.BitLiteral value, it's provided by parser driver. 3809 var NewBitLiteral func(string) (interface{}, error) 3810 3811 // SetResourceGroupStmt is a statement to set the resource group name for current session. 3812 type SetResourceGroupStmt struct { 3813 stmtNode 3814 Name model.CIStr 3815 } 3816 3817 func (n *SetResourceGroupStmt) Restore(ctx *format.RestoreCtx) error { 3818 ctx.WriteKeyWord("SET RESOURCE GROUP ") 3819 ctx.WriteName(n.Name.O) 3820 return nil 3821 } 3822 3823 // Accept implements Node Accept interface. 3824 func (n *SetResourceGroupStmt) Accept(v Visitor) (Node, bool) { 3825 newNode, skipChildren := v.Enter(n) 3826 if skipChildren { 3827 return v.Leave(newNode) 3828 } 3829 n = newNode.(*SetResourceGroupStmt) 3830 return v.Leave(n) 3831 } 3832 3833 // CalibrateResourceType is the type for CalibrateResource statement. 3834 type CalibrateResourceType int 3835 3836 // calibrate resource [ workload < TPCC | OLTP_READ_WRITE | OLTP_READ_ONLY | OLTP_WRITE_ONLY | TPCH_10> ] 3837 const ( 3838 WorkloadNone CalibrateResourceType = iota 3839 TPCC 3840 OLTPREADWRITE 3841 OLTPREADONLY 3842 OLTPWRITEONLY 3843 TPCH10 3844 ) 3845 3846 func (n CalibrateResourceType) Restore(ctx *format.RestoreCtx) error { 3847 switch n { 3848 case TPCC: 3849 ctx.WriteKeyWord(" WORKLOAD TPCC") 3850 case OLTPREADWRITE: 3851 ctx.WriteKeyWord(" WORKLOAD OLTP_READ_WRITE") 3852 case OLTPREADONLY: 3853 ctx.WriteKeyWord(" WORKLOAD OLTP_READ_ONLY") 3854 case OLTPWRITEONLY: 3855 ctx.WriteKeyWord(" WORKLOAD OLTP_WRITE_ONLY") 3856 case TPCH10: 3857 ctx.WriteKeyWord(" WORKLOAD TPCH_10") 3858 } 3859 return nil 3860 } 3861 3862 // CalibrateResourceStmt is a statement to fetch the cluster RU capacity 3863 type CalibrateResourceStmt struct { 3864 stmtNode 3865 DynamicCalibrateResourceOptionList []*DynamicCalibrateResourceOption 3866 Tp CalibrateResourceType 3867 } 3868 3869 // Restore implements Node interface. 3870 func (n *CalibrateResourceStmt) Restore(ctx *format.RestoreCtx) error { 3871 ctx.WriteKeyWord("CALIBRATE RESOURCE") 3872 if err := n.Tp.Restore(ctx); err != nil { 3873 return errors.Annotate(err, "An error occurred while restore CalibrateResourceStmt.CalibrateResourceType") 3874 } 3875 for i, option := range n.DynamicCalibrateResourceOptionList { 3876 ctx.WritePlain(" ") 3877 if err := option.Restore(ctx); err != nil { 3878 return errors.Annotatef(err, "An error occurred while splicing DynamicCalibrateResourceOption: [%v]", i) 3879 } 3880 } 3881 return nil 3882 } 3883 3884 // Accept implements Node Accept interface. 3885 func (n *CalibrateResourceStmt) Accept(v Visitor) (Node, bool) { 3886 newNode, skipChildren := v.Enter(n) 3887 if skipChildren { 3888 return v.Leave(newNode) 3889 } 3890 n = newNode.(*CalibrateResourceStmt) 3891 for _, val := range n.DynamicCalibrateResourceOptionList { 3892 _, ok := val.Accept(v) 3893 if !ok { 3894 return n, false 3895 } 3896 } 3897 return v.Leave(n) 3898 } 3899 3900 type DynamicCalibrateType int 3901 3902 const ( 3903 // specific time 3904 CalibrateStartTime = iota 3905 CalibrateEndTime 3906 CalibrateDuration 3907 ) 3908 3909 type DynamicCalibrateResourceOption struct { 3910 stmtNode 3911 Tp DynamicCalibrateType 3912 StrValue string 3913 Ts ExprNode 3914 Unit TimeUnitType 3915 } 3916 3917 func (n *DynamicCalibrateResourceOption) Restore(ctx *format.RestoreCtx) error { 3918 switch n.Tp { 3919 case CalibrateStartTime: 3920 ctx.WriteKeyWord("START_TIME ") 3921 if err := n.Ts.Restore(ctx); err != nil { 3922 return errors.Annotate(err, "An error occurred while splicing DynamicCalibrateResourceOption StartTime") 3923 } 3924 case CalibrateEndTime: 3925 ctx.WriteKeyWord("END_TIME ") 3926 if err := n.Ts.Restore(ctx); err != nil { 3927 return errors.Annotate(err, "An error occurred while splicing DynamicCalibrateResourceOption EndTime") 3928 } 3929 case CalibrateDuration: 3930 ctx.WriteKeyWord("DURATION ") 3931 if len(n.StrValue) > 0 { 3932 ctx.WriteString(n.StrValue) 3933 } else { 3934 ctx.WriteKeyWord("INTERVAL ") 3935 if err := n.Ts.Restore(ctx); err != nil { 3936 return errors.Annotate(err, "An error occurred while restore DynamicCalibrateResourceOption DURATION TS") 3937 } 3938 ctx.WritePlain(" ") 3939 ctx.WriteKeyWord(n.Unit.String()) 3940 } 3941 default: 3942 return errors.Errorf("invalid DynamicCalibrateResourceOption: %d", n.Tp) 3943 } 3944 return nil 3945 } 3946 3947 // Accept implements Node Accept interface. 3948 func (n *DynamicCalibrateResourceOption) Accept(v Visitor) (Node, bool) { 3949 newNode, skipChildren := v.Enter(n) 3950 if skipChildren { 3951 return v.Leave(newNode) 3952 } 3953 n = newNode.(*DynamicCalibrateResourceOption) 3954 if n.Ts != nil { 3955 node, ok := n.Ts.Accept(v) 3956 if !ok { 3957 return n, false 3958 } 3959 n.Ts = node.(ExprNode) 3960 } 3961 return v.Leave(n) 3962 } 3963 3964 // DropQueryWatchStmt is a statement to drop a runaway watch item. 3965 type DropQueryWatchStmt struct { 3966 stmtNode 3967 IntValue int64 3968 } 3969 3970 func (n *DropQueryWatchStmt) Restore(ctx *format.RestoreCtx) error { 3971 ctx.WriteKeyWord("QUERY WATCH REMOVE ") 3972 ctx.WritePlainf("%d", n.IntValue) 3973 return nil 3974 } 3975 3976 // Accept implements Node Accept interface. 3977 func (n *DropQueryWatchStmt) Accept(v Visitor) (Node, bool) { 3978 newNode, _ := v.Enter(n) 3979 n = newNode.(*DropQueryWatchStmt) 3980 return v.Leave(n) 3981 } 3982 3983 // AddQueryWatchStmt is a statement to add a runaway watch item. 3984 type AddQueryWatchStmt struct { 3985 stmtNode 3986 QueryWatchOptionList []*QueryWatchOption 3987 } 3988 3989 func (n *AddQueryWatchStmt) Restore(ctx *format.RestoreCtx) error { 3990 ctx.WriteKeyWord("QUERY WATCH ADD") 3991 for i, option := range n.QueryWatchOptionList { 3992 ctx.WritePlain(" ") 3993 if err := option.Restore(ctx); err != nil { 3994 return errors.Annotatef(err, "An error occurred while splicing QueryWatchOptionList: [%v]", i) 3995 } 3996 } 3997 return nil 3998 } 3999 4000 // Accept implements Node Accept interface. 4001 func (n *AddQueryWatchStmt) Accept(v Visitor) (Node, bool) { 4002 newNode, _ := v.Enter(n) 4003 n = newNode.(*AddQueryWatchStmt) 4004 for _, val := range n.QueryWatchOptionList { 4005 _, ok := val.Accept(v) 4006 if !ok { 4007 return n, false 4008 } 4009 } 4010 return v.Leave(n) 4011 } 4012 4013 type QueryWatchOptionType int 4014 4015 const ( 4016 QueryWatchResourceGroup QueryWatchOptionType = iota 4017 QueryWatchAction 4018 QueryWatchType 4019 ) 4020 4021 // QueryWatchOption is used for parsing manual management of watching runaway queries option. 4022 type QueryWatchOption struct { 4023 stmtNode 4024 Tp QueryWatchOptionType 4025 StrValue model.CIStr 4026 IntValue int32 4027 ExprValue ExprNode 4028 BoolValue bool 4029 } 4030 4031 func (n *QueryWatchOption) Restore(ctx *format.RestoreCtx) error { 4032 switch n.Tp { 4033 case QueryWatchResourceGroup: 4034 ctx.WriteKeyWord("RESOURCE GROUP ") 4035 if n.ExprValue != nil { 4036 if err := n.ExprValue.Restore(ctx); err != nil { 4037 return errors.Annotatef(err, "An error occurred while splicing ExprValue: [%v]", n.ExprValue) 4038 } 4039 } else { 4040 ctx.WriteName(n.StrValue.O) 4041 } 4042 case QueryWatchAction: 4043 ctx.WriteKeyWord("ACTION ") 4044 ctx.WritePlain("= ") 4045 ctx.WriteKeyWord(model.RunawayActionType(n.IntValue).String()) 4046 case QueryWatchType: 4047 if n.BoolValue { 4048 ctx.WriteKeyWord("SQL TEXT ") 4049 ctx.WriteKeyWord(model.RunawayWatchType(n.IntValue).String()) 4050 ctx.WriteKeyWord(" TO ") 4051 } else { 4052 switch n.IntValue { 4053 case int32(model.WatchSimilar): 4054 ctx.WriteKeyWord("SQL DIGEST ") 4055 case int32(model.WatchPlan): 4056 ctx.WriteKeyWord("PLAN DIGEST ") 4057 } 4058 } 4059 if err := n.ExprValue.Restore(ctx); err != nil { 4060 return errors.Annotatef(err, "An error occurred while splicing ExprValue: [%v]", n.ExprValue) 4061 } 4062 } 4063 return nil 4064 } 4065 4066 // Accept implements Node Accept interface. 4067 func (n *QueryWatchOption) Accept(v Visitor) (Node, bool) { 4068 newNode, skipChildren := v.Enter(n) 4069 if skipChildren { 4070 return v.Leave(newNode) 4071 } 4072 n = newNode.(*QueryWatchOption) 4073 if n.ExprValue != nil { 4074 node, ok := n.ExprValue.Accept(v) 4075 if !ok { 4076 return n, false 4077 } 4078 n.ExprValue = node.(ExprNode) 4079 } 4080 return v.Leave(n) 4081 } 4082 4083 func CheckQueryWatchAppend(ops []*QueryWatchOption, newOp *QueryWatchOption) bool { 4084 for _, op := range ops { 4085 if op.Tp == newOp.Tp { 4086 return false 4087 } 4088 } 4089 return true 4090 }