github.com/XiaoMi/Gaea@v1.2.5/parser/ast/ddl.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 "github.com/pingcap/errors" 18 19 "github.com/XiaoMi/Gaea/parser/auth" 20 "github.com/XiaoMi/Gaea/parser/format" 21 "github.com/XiaoMi/Gaea/parser/model" 22 "github.com/XiaoMi/Gaea/parser/types" 23 ) 24 25 var ( 26 _ DDLNode = &AlterTableStmt{} 27 _ DDLNode = &CreateDatabaseStmt{} 28 _ DDLNode = &CreateIndexStmt{} 29 _ DDLNode = &CreateTableStmt{} 30 _ DDLNode = &CreateViewStmt{} 31 _ DDLNode = &DropDatabaseStmt{} 32 _ DDLNode = &DropIndexStmt{} 33 _ DDLNode = &DropTableStmt{} 34 _ DDLNode = &RenameTableStmt{} 35 _ DDLNode = &TruncateTableStmt{} 36 37 _ Node = &AlterTableSpec{} 38 _ Node = &ColumnDef{} 39 _ Node = &ColumnOption{} 40 _ Node = &ColumnPosition{} 41 _ Node = &Constraint{} 42 _ Node = &IndexColName{} 43 _ Node = &ReferenceDef{} 44 ) 45 46 // CharsetOpt is used for parsing charset option from SQL. 47 type CharsetOpt struct { 48 Chs string 49 Col string 50 } 51 52 // DatabaseOptionType is the type for database options. 53 type DatabaseOptionType int 54 55 // Database option types. 56 const ( 57 DatabaseOptionNone DatabaseOptionType = iota 58 DatabaseOptionCharset 59 DatabaseOptionCollate 60 ) 61 62 // DatabaseOption represents database option. 63 type DatabaseOption struct { 64 Tp DatabaseOptionType 65 Value string 66 } 67 68 // Restore implements Node interface. 69 func (n *DatabaseOption) Restore(ctx *format.RestoreCtx) error { 70 switch n.Tp { 71 case DatabaseOptionCharset: 72 ctx.WriteKeyWord("CHARACTER SET") 73 ctx.WritePlain(" = ") 74 ctx.WritePlain(n.Value) 75 case DatabaseOptionCollate: 76 ctx.WriteKeyWord("COLLATE") 77 ctx.WritePlain(" = ") 78 ctx.WritePlain(n.Value) 79 default: 80 return errors.Errorf("invalid DatabaseOptionType: %d", n.Tp) 81 } 82 return nil 83 } 84 85 // CreateDatabaseStmt is a statement to create a database. 86 // See https://dev.mysql.com/doc/refman/5.7/en/create-database.html 87 type CreateDatabaseStmt struct { 88 ddlNode 89 90 IfNotExists bool 91 Name string 92 Options []*DatabaseOption 93 } 94 95 // Restore implements Node interface. 96 func (n *CreateDatabaseStmt) Restore(ctx *format.RestoreCtx) error { 97 ctx.WriteKeyWord("CREATE DATABASE ") 98 if n.IfNotExists { 99 ctx.WriteKeyWord("IF NOT EXISTS ") 100 } 101 ctx.WriteName(n.Name) 102 for _, option := range n.Options { 103 ctx.WritePlain(" ") 104 err := option.Restore(ctx) 105 if err != nil { 106 return errors.Trace(err) 107 } 108 } 109 return nil 110 } 111 112 // Accept implements Node Accept interface. 113 func (n *CreateDatabaseStmt) Accept(v Visitor) (Node, bool) { 114 newNode, skipChildren := v.Enter(n) 115 if skipChildren { 116 return v.Leave(newNode) 117 } 118 n = newNode.(*CreateDatabaseStmt) 119 return v.Leave(n) 120 } 121 122 // DropDatabaseStmt is a statement to drop a database and all tables in the database. 123 // See https://dev.mysql.com/doc/refman/5.7/en/drop-database.html 124 type DropDatabaseStmt struct { 125 ddlNode 126 127 IfExists bool 128 Name string 129 } 130 131 // Restore implements Node interface. 132 func (n *DropDatabaseStmt) Restore(ctx *format.RestoreCtx) error { 133 ctx.WriteKeyWord("DROP DATABASE ") 134 if n.IfExists { 135 ctx.WriteKeyWord("IF EXISTS ") 136 } 137 ctx.WriteName(n.Name) 138 return nil 139 } 140 141 // Accept implements Node Accept interface. 142 func (n *DropDatabaseStmt) Accept(v Visitor) (Node, bool) { 143 newNode, skipChildren := v.Enter(n) 144 if skipChildren { 145 return v.Leave(newNode) 146 } 147 n = newNode.(*DropDatabaseStmt) 148 return v.Leave(n) 149 } 150 151 // IndexColName is used for parsing index column name from SQL. 152 type IndexColName struct { 153 node 154 155 Column *ColumnName 156 Length int 157 } 158 159 // Restore implements Node interface. 160 func (n *IndexColName) Restore(ctx *format.RestoreCtx) error { 161 if err := n.Column.Restore(ctx); err != nil { 162 return errors.Annotate(err, "An error occurred while splicing IndexColName") 163 } 164 if n.Length > 0 { 165 ctx.WritePlainf("(%d)", n.Length) 166 } 167 return nil 168 } 169 170 // Accept implements Node Accept interface. 171 func (n *IndexColName) Accept(v Visitor) (Node, bool) { 172 newNode, skipChildren := v.Enter(n) 173 if skipChildren { 174 return v.Leave(newNode) 175 } 176 n = newNode.(*IndexColName) 177 node, ok := n.Column.Accept(v) 178 if !ok { 179 return n, false 180 } 181 n.Column = node.(*ColumnName) 182 return v.Leave(n) 183 } 184 185 // ReferenceDef is used for parsing foreign key reference option from SQL. 186 // See http://dev.mysql.com/doc/refman/5.7/en/create-table-foreign-keys.html 187 type ReferenceDef struct { 188 node 189 190 Table *TableName 191 IndexColNames []*IndexColName 192 OnDelete *OnDeleteOpt 193 OnUpdate *OnUpdateOpt 194 } 195 196 // Restore implements Node interface. 197 func (n *ReferenceDef) Restore(ctx *format.RestoreCtx) error { 198 if n.Table != nil { 199 ctx.WriteKeyWord("REFERENCES ") 200 if err := n.Table.Restore(ctx); err != nil { 201 return errors.Annotate(err, "An error occurred while splicing ReferenceDef") 202 } 203 } 204 ctx.WritePlain("(") 205 for i, indexColNames := range n.IndexColNames { 206 if i > 0 { 207 ctx.WritePlain(", ") 208 } 209 if err := indexColNames.Restore(ctx); err != nil { 210 return errors.Annotatef(err, "An error occurred while splicing IndexColNames: [%v]", i) 211 } 212 } 213 ctx.WritePlain(")") 214 if n.OnDelete.ReferOpt != ReferOptionNoOption { 215 ctx.WritePlain(" ") 216 if err := n.OnDelete.Restore(ctx); err != nil { 217 return errors.Annotate(err, "An error occurred while splicing OnDelete") 218 } 219 } 220 if n.OnUpdate.ReferOpt != ReferOptionNoOption { 221 ctx.WritePlain(" ") 222 if err := n.OnUpdate.Restore(ctx); err != nil { 223 return errors.Annotate(err, "An error occurred while splicing OnUpdate") 224 } 225 } 226 return nil 227 } 228 229 // Accept implements Node Accept interface. 230 func (n *ReferenceDef) Accept(v Visitor) (Node, bool) { 231 newNode, skipChildren := v.Enter(n) 232 if skipChildren { 233 return v.Leave(newNode) 234 } 235 n = newNode.(*ReferenceDef) 236 node, ok := n.Table.Accept(v) 237 if !ok { 238 return n, false 239 } 240 n.Table = node.(*TableName) 241 for i, val := range n.IndexColNames { 242 node, ok = val.Accept(v) 243 if !ok { 244 return n, false 245 } 246 n.IndexColNames[i] = node.(*IndexColName) 247 } 248 onDelete, ok := n.OnDelete.Accept(v) 249 if !ok { 250 return n, false 251 } 252 n.OnDelete = onDelete.(*OnDeleteOpt) 253 onUpdate, ok := n.OnUpdate.Accept(v) 254 if !ok { 255 return n, false 256 } 257 n.OnUpdate = onUpdate.(*OnUpdateOpt) 258 return v.Leave(n) 259 } 260 261 // ReferOptionType is the type for refer options. 262 type ReferOptionType int 263 264 // Refer option types. 265 const ( 266 ReferOptionNoOption ReferOptionType = iota 267 ReferOptionRestrict 268 ReferOptionCascade 269 ReferOptionSetNull 270 ReferOptionNoAction 271 ) 272 273 // String implements fmt.Stringer interface. 274 func (r ReferOptionType) String() string { 275 switch r { 276 case ReferOptionRestrict: 277 return "RESTRICT" 278 case ReferOptionCascade: 279 return "CASCADE" 280 case ReferOptionSetNull: 281 return "SET NULL" 282 case ReferOptionNoAction: 283 return "NO ACTION" 284 } 285 return "" 286 } 287 288 // OnDeleteOpt is used for optional on delete clause. 289 type OnDeleteOpt struct { 290 node 291 ReferOpt ReferOptionType 292 } 293 294 // Restore implements Node interface. 295 func (n *OnDeleteOpt) Restore(ctx *format.RestoreCtx) error { 296 if n.ReferOpt != ReferOptionNoOption { 297 ctx.WriteKeyWord("ON DELETE ") 298 ctx.WriteKeyWord(n.ReferOpt.String()) 299 } 300 return nil 301 } 302 303 // Accept implements Node Accept interface. 304 func (n *OnDeleteOpt) Accept(v Visitor) (Node, bool) { 305 newNode, skipChildren := v.Enter(n) 306 if skipChildren { 307 return v.Leave(newNode) 308 } 309 n = newNode.(*OnDeleteOpt) 310 return v.Leave(n) 311 } 312 313 // OnUpdateOpt is used for optional on update clause. 314 type OnUpdateOpt struct { 315 node 316 ReferOpt ReferOptionType 317 } 318 319 // Restore implements Node interface. 320 func (n *OnUpdateOpt) Restore(ctx *format.RestoreCtx) error { 321 if n.ReferOpt != ReferOptionNoOption { 322 ctx.WriteKeyWord("ON UPDATE ") 323 ctx.WriteKeyWord(n.ReferOpt.String()) 324 } 325 return nil 326 } 327 328 // Accept implements Node Accept interface. 329 func (n *OnUpdateOpt) Accept(v Visitor) (Node, bool) { 330 newNode, skipChildren := v.Enter(n) 331 if skipChildren { 332 return v.Leave(newNode) 333 } 334 n = newNode.(*OnUpdateOpt) 335 return v.Leave(n) 336 } 337 338 // ColumnOptionType is the type for ColumnOption. 339 type ColumnOptionType int 340 341 // ColumnOption types. 342 const ( 343 ColumnOptionNoOption ColumnOptionType = iota 344 ColumnOptionPrimaryKey 345 ColumnOptionNotNull 346 ColumnOptionAutoIncrement 347 ColumnOptionDefaultValue 348 ColumnOptionUniqKey 349 ColumnOptionNull 350 ColumnOptionOnUpdate // For Timestamp and Datetime only. 351 ColumnOptionFulltext 352 ColumnOptionComment 353 ColumnOptionGenerated 354 ColumnOptionReference 355 ) 356 357 // ColumnOption is used for parsing column constraint info from SQL. 358 type ColumnOption struct { 359 node 360 361 Tp ColumnOptionType 362 // Expr is used for ColumnOptionDefaultValue/ColumnOptionOnUpdateColumnOptionGenerated. 363 // For ColumnOptionDefaultValue or ColumnOptionOnUpdate, it's the target value. 364 // For ColumnOptionGenerated, it's the target expression. 365 Expr ExprNode 366 // Stored is only for ColumnOptionGenerated, default is false. 367 Stored bool 368 // Refer is used for foreign key. 369 Refer *ReferenceDef 370 } 371 372 // Restore implements Node interface. 373 func (n *ColumnOption) Restore(ctx *format.RestoreCtx) error { 374 switch n.Tp { 375 case ColumnOptionNoOption: 376 return nil 377 case ColumnOptionPrimaryKey: 378 ctx.WriteKeyWord("PRIMARY KEY") 379 case ColumnOptionNotNull: 380 ctx.WriteKeyWord("NOT NULL") 381 case ColumnOptionAutoIncrement: 382 ctx.WriteKeyWord("AUTO_INCREMENT") 383 case ColumnOptionDefaultValue: 384 ctx.WriteKeyWord("DEFAULT ") 385 if err := n.Expr.Restore(ctx); err != nil { 386 return errors.Annotate(err, "An error occurred while splicing ColumnOption DefaultValue Expr") 387 } 388 case ColumnOptionUniqKey: 389 ctx.WriteKeyWord("UNIQUE KEY") 390 case ColumnOptionNull: 391 ctx.WriteKeyWord("NULL") 392 case ColumnOptionOnUpdate: 393 ctx.WriteKeyWord("ON UPDATE ") 394 if err := n.Expr.Restore(ctx); err != nil { 395 return errors.Annotate(err, "An error occurred while splicing ColumnOption ON UPDATE Expr") 396 } 397 case ColumnOptionFulltext: 398 return errors.New("TiDB Parser ignore the `ColumnOptionFulltext` type now") 399 case ColumnOptionComment: 400 ctx.WriteKeyWord("COMMENT ") 401 if err := n.Expr.Restore(ctx); err != nil { 402 return errors.Annotate(err, "An error occurred while splicing ColumnOption COMMENT Expr") 403 } 404 case ColumnOptionGenerated: 405 ctx.WriteKeyWord("GENERATED ALWAYS AS") 406 ctx.WritePlain("(") 407 if err := n.Expr.Restore(ctx); err != nil { 408 return errors.Annotate(err, "An error occurred while splicing ColumnOption GENERATED ALWAYS Expr") 409 } 410 ctx.WritePlain(")") 411 if n.Stored { 412 ctx.WriteKeyWord(" STORED") 413 } else { 414 ctx.WriteKeyWord(" VIRTUAL") 415 } 416 case ColumnOptionReference: 417 if err := n.Refer.Restore(ctx); err != nil { 418 return errors.Annotate(err, "An error occurred while splicing ColumnOption ReferenceDef") 419 } 420 default: 421 return errors.New("An error occurred while splicing ColumnOption") 422 } 423 return nil 424 } 425 426 // Accept implements Node Accept interface. 427 func (n *ColumnOption) Accept(v Visitor) (Node, bool) { 428 newNode, skipChildren := v.Enter(n) 429 if skipChildren { 430 return v.Leave(newNode) 431 } 432 n = newNode.(*ColumnOption) 433 if n.Expr != nil { 434 node, ok := n.Expr.Accept(v) 435 if !ok { 436 return n, false 437 } 438 n.Expr = node.(ExprNode) 439 } 440 return v.Leave(n) 441 } 442 443 // IndexOption is the index options. 444 // KEY_BLOCK_SIZE [=] value 445 // | index_type 446 // | WITH PARSER parser_name 447 // | COMMENT 'string' 448 // See http://dev.mysql.com/doc/refman/5.7/en/create-table.html 449 type IndexOption struct { 450 node 451 452 KeyBlockSize uint64 453 Tp model.IndexType 454 Comment string 455 } 456 457 // Restore implements Node interface. 458 func (n *IndexOption) Restore(ctx *format.RestoreCtx) error { 459 hasPrevOption := false 460 if n.KeyBlockSize > 0 { 461 ctx.WriteKeyWord("KEY_BLOCK_SIZE") 462 ctx.WritePlainf("=%d", n.KeyBlockSize) 463 hasPrevOption = true 464 } 465 466 if n.Tp != model.IndexTypeInvalid { 467 if hasPrevOption { 468 ctx.WritePlain(" ") 469 } 470 ctx.WriteKeyWord("USING ") 471 ctx.WritePlain(n.Tp.String()) 472 hasPrevOption = true 473 } 474 475 if n.Comment != "" { 476 if hasPrevOption { 477 ctx.WritePlain(" ") 478 } 479 ctx.WriteKeyWord("COMMENT ") 480 ctx.WriteString(n.Comment) 481 } 482 return nil 483 } 484 485 // Accept implements Node Accept interface. 486 func (n *IndexOption) Accept(v Visitor) (Node, bool) { 487 newNode, skipChildren := v.Enter(n) 488 if skipChildren { 489 return v.Leave(newNode) 490 } 491 n = newNode.(*IndexOption) 492 return v.Leave(n) 493 } 494 495 // ConstraintType is the type for Constraint. 496 type ConstraintType int 497 498 // ConstraintTypes 499 const ( 500 ConstraintNoConstraint ConstraintType = iota 501 ConstraintPrimaryKey 502 ConstraintKey 503 ConstraintIndex 504 ConstraintUniq 505 ConstraintUniqKey 506 ConstraintUniqIndex 507 ConstraintForeignKey 508 ConstraintFulltext 509 ) 510 511 // Constraint is constraint for table definition. 512 type Constraint struct { 513 node 514 515 Tp ConstraintType 516 Name string 517 518 Keys []*IndexColName // Used for PRIMARY KEY, UNIQUE, ...... 519 520 Refer *ReferenceDef // Used for foreign key. 521 522 Option *IndexOption // Index Options 523 } 524 525 // Restore implements Node interface. 526 func (n *Constraint) Restore(ctx *format.RestoreCtx) error { 527 switch n.Tp { 528 case ConstraintNoConstraint: 529 return nil 530 case ConstraintPrimaryKey: 531 ctx.WriteKeyWord("PRIMARY KEY") 532 case ConstraintKey: 533 ctx.WriteKeyWord("KEY") 534 case ConstraintIndex: 535 ctx.WriteKeyWord("INDEX") 536 case ConstraintUniq: 537 ctx.WriteKeyWord("UNIQUE") 538 case ConstraintUniqKey: 539 ctx.WriteKeyWord("UNIQUE KEY") 540 case ConstraintUniqIndex: 541 ctx.WriteKeyWord("UNIQUE INDEX") 542 case ConstraintFulltext: 543 ctx.WriteKeyWord("FULLTEXT") 544 } 545 546 if n.Tp == ConstraintForeignKey { 547 ctx.WriteKeyWord("CONSTRAINT ") 548 if n.Name != "" { 549 ctx.WriteName(n.Name) 550 ctx.WritePlain(" ") 551 } 552 ctx.WriteKeyWord("FOREIGN KEY ") 553 } else if n.Name != "" { 554 ctx.WritePlain(" ") 555 ctx.WriteName(n.Name) 556 } 557 558 ctx.WritePlain("(") 559 for i, keys := range n.Keys { 560 if i > 0 { 561 ctx.WritePlain(", ") 562 } 563 if err := keys.Restore(ctx); err != nil { 564 return errors.Annotatef(err, "An error occurred while splicing Constraint Keys: [%v]", i) 565 } 566 } 567 ctx.WritePlain(")") 568 569 if n.Refer != nil { 570 ctx.WritePlain(" ") 571 if err := n.Refer.Restore(ctx); err != nil { 572 return errors.Annotate(err, "An error occurred while splicing Constraint Refer") 573 } 574 } 575 576 if n.Option != nil { 577 ctx.WritePlain(" ") 578 if err := n.Option.Restore(ctx); err != nil { 579 return errors.Annotate(err, "An error occurred while splicing Constraint Option") 580 } 581 } 582 583 return nil 584 } 585 586 // Accept implements Node Accept interface. 587 func (n *Constraint) Accept(v Visitor) (Node, bool) { 588 newNode, skipChildren := v.Enter(n) 589 if skipChildren { 590 return v.Leave(newNode) 591 } 592 n = newNode.(*Constraint) 593 for i, val := range n.Keys { 594 node, ok := val.Accept(v) 595 if !ok { 596 return n, false 597 } 598 n.Keys[i] = node.(*IndexColName) 599 } 600 if n.Refer != nil { 601 node, ok := n.Refer.Accept(v) 602 if !ok { 603 return n, false 604 } 605 n.Refer = node.(*ReferenceDef) 606 } 607 if n.Option != nil { 608 node, ok := n.Option.Accept(v) 609 if !ok { 610 return n, false 611 } 612 n.Option = node.(*IndexOption) 613 } 614 return v.Leave(n) 615 } 616 617 // ColumnDef is used for parsing column definition from SQL. 618 type ColumnDef struct { 619 node 620 621 Name *ColumnName 622 Tp *types.FieldType 623 Options []*ColumnOption 624 } 625 626 // Restore implements Node interface. 627 func (n *ColumnDef) Restore(ctx *format.RestoreCtx) error { 628 if err := n.Name.Restore(ctx); err != nil { 629 return errors.Annotate(err, "An error occurred while splicing ColumnDef Name") 630 } 631 if n.Tp != nil { 632 ctx.WritePlain(" ") 633 if err := n.Tp.Restore(ctx); err != nil { 634 return errors.Annotate(err, "An error occurred while splicing ColumnDef Type") 635 } 636 } 637 for i, options := range n.Options { 638 ctx.WritePlain(" ") 639 if err := options.Restore(ctx); err != nil { 640 return errors.Annotatef(err, "An error occurred while splicing ColumnDef ColumnOption: [%v]", i) 641 } 642 } 643 return nil 644 } 645 646 // Accept implements Node Accept interface. 647 func (n *ColumnDef) Accept(v Visitor) (Node, bool) { 648 newNode, skipChildren := v.Enter(n) 649 if skipChildren { 650 return v.Leave(newNode) 651 } 652 n = newNode.(*ColumnDef) 653 node, ok := n.Name.Accept(v) 654 if !ok { 655 return n, false 656 } 657 n.Name = node.(*ColumnName) 658 for i, val := range n.Options { 659 node, ok := val.Accept(v) 660 if !ok { 661 return n, false 662 } 663 n.Options[i] = node.(*ColumnOption) 664 } 665 return v.Leave(n) 666 } 667 668 // CreateTableStmt is a statement to create a table. 669 // See https://dev.mysql.com/doc/refman/5.7/en/create-table.html 670 type CreateTableStmt struct { 671 ddlNode 672 673 IfNotExists bool 674 Table *TableName 675 ReferTable *TableName 676 Cols []*ColumnDef 677 Constraints []*Constraint 678 Options []*TableOption 679 Partition *PartitionOptions 680 OnDuplicate OnDuplicateCreateTableSelectType 681 Select ResultSetNode 682 } 683 684 // Restore implements Node interface. 685 func (n *CreateTableStmt) Restore(ctx *format.RestoreCtx) error { 686 ctx.WriteKeyWord("CREATE TABLE ") 687 if n.IfNotExists { 688 ctx.WriteKeyWord("IF NOT EXISTS ") 689 } 690 691 if err := n.Table.Restore(ctx); err != nil { 692 return errors.Annotate(err, "An error occurred while splicing CreateTableStmt Table") 693 } 694 ctx.WritePlain(" ") 695 if n.ReferTable != nil { 696 ctx.WriteKeyWord("LIKE ") 697 if err := n.ReferTable.Restore(ctx); err != nil { 698 return errors.Annotate(err, "An error occurred while splicing CreateTableStmt ReferTable") 699 } 700 } 701 lenCols := len(n.Cols) 702 lenConstraints := len(n.Constraints) 703 if lenCols+lenConstraints > 0 { 704 ctx.WritePlain("(") 705 for i, col := range n.Cols { 706 if i > 0 { 707 ctx.WritePlain(",") 708 } 709 if err := col.Restore(ctx); err != nil { 710 return errors.Annotatef(err, "An error occurred while splicing CreateTableStmt ColumnDef: [%v]", i) 711 } 712 } 713 for i, constraint := range n.Constraints { 714 if i > 0 || lenCols >= 1 { 715 ctx.WritePlain(",") 716 } 717 if err := constraint.Restore(ctx); err != nil { 718 return errors.Annotatef(err, "An error occurred while splicing CreateTableStmt Constraints: [%v]", i) 719 } 720 } 721 ctx.WritePlain(")") 722 } 723 724 for i, option := range n.Options { 725 ctx.WritePlain(" ") 726 if err := option.Restore(ctx); err != nil { 727 return errors.Annotatef(err, "An error occurred while splicing CreateTableStmt TableOption: [%v]", i) 728 } 729 } 730 731 if n.Partition != nil { 732 ctx.WritePlain(" ") 733 if err := n.Partition.Restore(ctx); err != nil { 734 return errors.Annotate(err, "An error occurred while splicing CreateTableStmt Partition") 735 } 736 } 737 738 if n.Select != nil { 739 switch n.OnDuplicate { 740 case OnDuplicateCreateTableSelectError: 741 ctx.WriteKeyWord(" AS ") 742 case OnDuplicateCreateTableSelectIgnore: 743 ctx.WriteKeyWord(" IGNORE AS ") 744 case OnDuplicateCreateTableSelectReplace: 745 ctx.WriteKeyWord(" REPLACE AS ") 746 } 747 748 if err := n.Select.Restore(ctx); err != nil { 749 return errors.Annotate(err, "An error occurred while splicing CreateTableStmt Select") 750 } 751 } 752 753 return nil 754 } 755 756 // Accept implements Node Accept interface. 757 func (n *CreateTableStmt) Accept(v Visitor) (Node, bool) { 758 newNode, skipChildren := v.Enter(n) 759 if skipChildren { 760 return v.Leave(newNode) 761 } 762 n = newNode.(*CreateTableStmt) 763 node, ok := n.Table.Accept(v) 764 if !ok { 765 return n, false 766 } 767 n.Table = node.(*TableName) 768 if n.ReferTable != nil { 769 node, ok = n.ReferTable.Accept(v) 770 if !ok { 771 return n, false 772 } 773 n.ReferTable = node.(*TableName) 774 } 775 for i, val := range n.Cols { 776 node, ok = val.Accept(v) 777 if !ok { 778 return n, false 779 } 780 n.Cols[i] = node.(*ColumnDef) 781 } 782 for i, val := range n.Constraints { 783 node, ok = val.Accept(v) 784 if !ok { 785 return n, false 786 } 787 n.Constraints[i] = node.(*Constraint) 788 } 789 if n.Select != nil { 790 node, ok := n.Select.Accept(v) 791 if !ok { 792 return n, false 793 } 794 n.Select = node.(ResultSetNode) 795 } 796 797 return v.Leave(n) 798 } 799 800 // DropTableStmt is a statement to drop one or more tables. 801 // See https://dev.mysql.com/doc/refman/5.7/en/drop-table.html 802 type DropTableStmt struct { 803 ddlNode 804 805 IfExists bool 806 Tables []*TableName 807 IsView bool 808 } 809 810 // Restore implements Node interface. 811 func (n *DropTableStmt) Restore(ctx *format.RestoreCtx) error { 812 if n.IsView { 813 ctx.WriteKeyWord("DROP VIEW ") 814 } else { 815 ctx.WriteKeyWord("DROP TABLE ") 816 } 817 if n.IfExists { 818 ctx.WriteKeyWord("IF EXISTS ") 819 } 820 821 for index, table := range n.Tables { 822 if index != 0 { 823 ctx.WritePlain(", ") 824 } 825 if err := table.Restore(ctx); err != nil { 826 return errors.Annotatef(err, "An error occurred while restore DropTableStmt.Tables[%d]", index) 827 } 828 } 829 830 return nil 831 } 832 833 // Accept implements Node Accept interface. 834 func (n *DropTableStmt) Accept(v Visitor) (Node, bool) { 835 newNode, skipChildren := v.Enter(n) 836 if skipChildren { 837 return v.Leave(newNode) 838 } 839 n = newNode.(*DropTableStmt) 840 for i, val := range n.Tables { 841 node, ok := val.Accept(v) 842 if !ok { 843 return n, false 844 } 845 n.Tables[i] = node.(*TableName) 846 } 847 return v.Leave(n) 848 } 849 850 // RenameTableStmt is a statement to rename a table. 851 // See http://dev.mysql.com/doc/refman/5.7/en/rename-table.html 852 type RenameTableStmt struct { 853 ddlNode 854 855 OldTable *TableName 856 NewTable *TableName 857 858 // TableToTables is only useful for syncer which depends heavily on tidb parser to do some dirty work for now. 859 // TODO: Refactor this when you are going to add full support for multiple schema changes. 860 TableToTables []*TableToTable 861 } 862 863 // Restore implements Node interface. 864 func (n *RenameTableStmt) Restore(ctx *format.RestoreCtx) error { 865 ctx.WriteKeyWord("RENAME TABLE ") 866 for index, table2table := range n.TableToTables { 867 if index != 0 { 868 ctx.WritePlain(", ") 869 } 870 if err := table2table.Restore(ctx); err != nil { 871 return errors.Annotate(err, "An error occurred while restore RenameTableStmt.TableToTables") 872 } 873 } 874 return nil 875 } 876 877 // Accept implements Node Accept interface. 878 func (n *RenameTableStmt) Accept(v Visitor) (Node, bool) { 879 newNode, skipChildren := v.Enter(n) 880 if skipChildren { 881 return v.Leave(newNode) 882 } 883 n = newNode.(*RenameTableStmt) 884 node, ok := n.OldTable.Accept(v) 885 if !ok { 886 return n, false 887 } 888 n.OldTable = node.(*TableName) 889 node, ok = n.NewTable.Accept(v) 890 if !ok { 891 return n, false 892 } 893 n.NewTable = node.(*TableName) 894 895 for i, t := range n.TableToTables { 896 node, ok := t.Accept(v) 897 if !ok { 898 return n, false 899 } 900 n.TableToTables[i] = node.(*TableToTable) 901 } 902 903 return v.Leave(n) 904 } 905 906 // TableToTable represents renaming old table to new table used in RenameTableStmt. 907 type TableToTable struct { 908 node 909 OldTable *TableName 910 NewTable *TableName 911 } 912 913 // Restore implements Node interface. 914 func (n *TableToTable) Restore(ctx *format.RestoreCtx) error { 915 if err := n.OldTable.Restore(ctx); err != nil { 916 return errors.Annotate(err, "An error occurred while restore TableToTable.OldTable") 917 } 918 ctx.WriteKeyWord(" TO ") 919 if err := n.NewTable.Restore(ctx); err != nil { 920 return errors.Annotate(err, "An error occurred while restore TableToTable.NewTable") 921 } 922 return nil 923 } 924 925 // Accept implements Node Accept interface. 926 func (n *TableToTable) Accept(v Visitor) (Node, bool) { 927 newNode, skipChildren := v.Enter(n) 928 if skipChildren { 929 return v.Leave(newNode) 930 } 931 n = newNode.(*TableToTable) 932 node, ok := n.OldTable.Accept(v) 933 if !ok { 934 return n, false 935 } 936 n.OldTable = node.(*TableName) 937 node, ok = n.NewTable.Accept(v) 938 if !ok { 939 return n, false 940 } 941 n.NewTable = node.(*TableName) 942 return v.Leave(n) 943 } 944 945 // CreateViewStmt is a statement to create a View. 946 // See https://dev.mysql.com/doc/refman/5.7/en/create-view.html 947 type CreateViewStmt struct { 948 ddlNode 949 950 OrReplace bool 951 ViewName *TableName 952 Cols []model.CIStr 953 Select StmtNode 954 Algorithm model.ViewAlgorithm 955 Definer *auth.UserIdentity 956 Security model.ViewSecurity 957 CheckOption model.ViewCheckOption 958 } 959 960 // Restore implements Node interface. 961 func (n *CreateViewStmt) Restore(ctx *format.RestoreCtx) error { 962 ctx.WriteKeyWord("CREATE ") 963 if n.OrReplace { 964 ctx.WriteKeyWord("OR REPLACE ") 965 } 966 ctx.WriteKeyWord("ALGORITHM") 967 ctx.WritePlain(" = ") 968 ctx.WriteKeyWord(n.Algorithm.String()) 969 ctx.WriteKeyWord(" DEFINER") 970 ctx.WritePlain(" = ") 971 972 // todo Use n.Definer.Restore(ctx) to replace this part 973 if n.Definer.CurrentUser { 974 ctx.WriteKeyWord("current_user") 975 } else { 976 ctx.WriteName(n.Definer.Username) 977 if n.Definer.Hostname != "" { 978 ctx.WritePlain("@") 979 ctx.WriteName(n.Definer.Hostname) 980 } 981 } 982 983 ctx.WriteKeyWord(" SQL SECURITY ") 984 ctx.WriteKeyWord(n.Security.String()) 985 ctx.WriteKeyWord(" VIEW ") 986 987 if err := n.ViewName.Restore(ctx); err != nil { 988 return errors.Annotate(err, "An error occurred while create CreateViewStmt.ViewName") 989 } 990 991 for i, col := range n.Cols { 992 if i == 0 { 993 ctx.WritePlain(" (") 994 } else { 995 ctx.WritePlain(",") 996 } 997 ctx.WriteName(col.O) 998 if i == len(n.Cols)-1 { 999 ctx.WritePlain(")") 1000 } 1001 } 1002 1003 ctx.WriteKeyWord(" AS ") 1004 1005 if err := n.Select.Restore(ctx); err != nil { 1006 return errors.Annotate(err, "An error occurred while create CreateViewStmt.Select") 1007 } 1008 1009 if n.CheckOption != model.CheckOptionCascaded { 1010 ctx.WriteKeyWord(" WITH ") 1011 ctx.WriteKeyWord(n.CheckOption.String()) 1012 ctx.WriteKeyWord(" CHECK OPTION") 1013 } 1014 return nil 1015 } 1016 1017 // Accept implements Node Accept interface. 1018 func (n *CreateViewStmt) Accept(v Visitor) (Node, bool) { 1019 newNode, skipChildren := v.Enter(n) 1020 if skipChildren { 1021 return v.Leave(newNode) 1022 } 1023 n = newNode.(*CreateViewStmt) 1024 node, ok := n.ViewName.Accept(v) 1025 if !ok { 1026 return n, false 1027 } 1028 n.ViewName = node.(*TableName) 1029 selnode, ok := n.Select.Accept(v) 1030 if !ok { 1031 return n, false 1032 } 1033 n.Select = selnode.(*SelectStmt) 1034 return v.Leave(n) 1035 } 1036 1037 // CreateIndexStmt is a statement to create an index. 1038 // See https://dev.mysql.com/doc/refman/5.7/en/create-index.html 1039 type CreateIndexStmt struct { 1040 ddlNode 1041 1042 IndexName string 1043 Table *TableName 1044 Unique bool 1045 IndexColNames []*IndexColName 1046 IndexOption *IndexOption 1047 } 1048 1049 // Restore implements Node interface. 1050 func (n *CreateIndexStmt) Restore(ctx *format.RestoreCtx) error { 1051 ctx.WriteKeyWord("CREATE ") 1052 if n.Unique { 1053 ctx.WriteKeyWord("UNIQUE ") 1054 } 1055 ctx.WriteKeyWord("INDEX ") 1056 ctx.WriteName(n.IndexName) 1057 ctx.WriteKeyWord(" ON ") 1058 if err := n.Table.Restore(ctx); err != nil { 1059 return errors.Annotate(err, "An error occurred while restore CreateIndexStmt.Table") 1060 } 1061 1062 ctx.WritePlain(" (") 1063 for i, indexColName := range n.IndexColNames { 1064 if i != 0 { 1065 ctx.WritePlain(", ") 1066 } 1067 if err := indexColName.Restore(ctx); err != nil { 1068 return errors.Annotatef(err, "An error occurred while restore CreateIndexStmt.IndexColNames: [%v]", i) 1069 } 1070 } 1071 ctx.WritePlain(")") 1072 1073 if n.IndexOption.Tp != model.IndexTypeInvalid || n.IndexOption.KeyBlockSize > 0 || n.IndexOption.Comment != "" { 1074 ctx.WritePlain(" ") 1075 if err := n.IndexOption.Restore(ctx); err != nil { 1076 return errors.Annotate(err, "An error occurred while restore CreateIndexStmt.IndexOption") 1077 } 1078 } 1079 1080 return nil 1081 } 1082 1083 // Accept implements Node Accept interface. 1084 func (n *CreateIndexStmt) Accept(v Visitor) (Node, bool) { 1085 newNode, skipChildren := v.Enter(n) 1086 if skipChildren { 1087 return v.Leave(newNode) 1088 } 1089 n = newNode.(*CreateIndexStmt) 1090 node, ok := n.Table.Accept(v) 1091 if !ok { 1092 return n, false 1093 } 1094 n.Table = node.(*TableName) 1095 for i, val := range n.IndexColNames { 1096 node, ok = val.Accept(v) 1097 if !ok { 1098 return n, false 1099 } 1100 n.IndexColNames[i] = node.(*IndexColName) 1101 } 1102 if n.IndexOption != nil { 1103 node, ok := n.IndexOption.Accept(v) 1104 if !ok { 1105 return n, false 1106 } 1107 n.IndexOption = node.(*IndexOption) 1108 } 1109 return v.Leave(n) 1110 } 1111 1112 // DropIndexStmt is a statement to drop the index. 1113 // See https://dev.mysql.com/doc/refman/5.7/en/drop-index.html 1114 type DropIndexStmt struct { 1115 ddlNode 1116 1117 IfExists bool 1118 IndexName string 1119 Table *TableName 1120 } 1121 1122 // Restore implements Node interface. 1123 func (n *DropIndexStmt) Restore(ctx *format.RestoreCtx) error { 1124 ctx.WriteKeyWord("DROP INDEX ") 1125 if n.IfExists { 1126 ctx.WriteKeyWord("IF EXISTS ") 1127 } 1128 ctx.WriteName(n.IndexName) 1129 ctx.WriteKeyWord(" ON ") 1130 1131 if err := n.Table.Restore(ctx); err != nil { 1132 return errors.Annotate(err, "An error occurred while add index") 1133 } 1134 1135 return nil 1136 } 1137 1138 // Accept implements Node Accept interface. 1139 func (n *DropIndexStmt) Accept(v Visitor) (Node, bool) { 1140 newNode, skipChildren := v.Enter(n) 1141 if skipChildren { 1142 return v.Leave(newNode) 1143 } 1144 n = newNode.(*DropIndexStmt) 1145 node, ok := n.Table.Accept(v) 1146 if !ok { 1147 return n, false 1148 } 1149 n.Table = node.(*TableName) 1150 return v.Leave(n) 1151 } 1152 1153 // TableOptionType is the type for TableOption 1154 type TableOptionType int 1155 1156 // TableOption types. 1157 const ( 1158 TableOptionNone TableOptionType = iota 1159 TableOptionEngine 1160 TableOptionCharset 1161 TableOptionCollate 1162 TableOptionAutoIncrement 1163 TableOptionComment 1164 TableOptionAvgRowLength 1165 TableOptionCheckSum 1166 TableOptionCompression 1167 TableOptionConnection 1168 TableOptionPassword 1169 TableOptionKeyBlockSize 1170 TableOptionMaxRows 1171 TableOptionMinRows 1172 TableOptionDelayKeyWrite 1173 TableOptionRowFormat 1174 TableOptionStatsPersistent 1175 TableOptionShardRowID 1176 TableOptionPackKeys 1177 ) 1178 1179 // RowFormat types 1180 const ( 1181 RowFormatDefault uint64 = iota + 1 1182 RowFormatDynamic 1183 RowFormatFixed 1184 RowFormatCompressed 1185 RowFormatRedundant 1186 RowFormatCompact 1187 ) 1188 1189 // OnDuplicateCreateTableSelectType is the option that handle unique key values in 'CREATE TABLE ... SELECT'. 1190 // See https://dev.mysql.com/doc/refman/5.7/en/create-table-select.html 1191 type OnDuplicateCreateTableSelectType int 1192 1193 // OnDuplicateCreateTableSelect types 1194 const ( 1195 OnDuplicateCreateTableSelectError OnDuplicateCreateTableSelectType = iota 1196 OnDuplicateCreateTableSelectIgnore 1197 OnDuplicateCreateTableSelectReplace 1198 ) 1199 1200 // TableOption is used for parsing table option from SQL. 1201 type TableOption struct { 1202 Tp TableOptionType 1203 StrValue string 1204 UintValue uint64 1205 } 1206 1207 // Restore table option restore 1208 func (n *TableOption) Restore(ctx *format.RestoreCtx) error { 1209 switch n.Tp { 1210 case TableOptionEngine: 1211 ctx.WriteKeyWord("ENGINE ") 1212 ctx.WritePlain("= ") 1213 if n.StrValue != "" { 1214 ctx.WritePlain(n.StrValue) 1215 } else { 1216 ctx.WritePlain("''") 1217 } 1218 case TableOptionCharset: 1219 ctx.WriteKeyWord("DEFAULT CHARACTER SET ") 1220 ctx.WritePlain("= ") 1221 ctx.WriteKeyWord(n.StrValue) 1222 case TableOptionCollate: 1223 ctx.WriteKeyWord("DEFAULT COLLATE ") 1224 ctx.WritePlain("= ") 1225 ctx.WriteKeyWord(n.StrValue) 1226 case TableOptionAutoIncrement: 1227 ctx.WriteKeyWord("AUTO_INCREMENT ") 1228 ctx.WritePlain("= ") 1229 ctx.WritePlainf("%d", n.UintValue) 1230 case TableOptionComment: 1231 ctx.WriteKeyWord("COMMENT ") 1232 ctx.WritePlain("= ") 1233 ctx.WriteString(n.StrValue) 1234 case TableOptionAvgRowLength: 1235 ctx.WriteKeyWord("AVG_ROW_LENGTH ") 1236 ctx.WritePlain("= ") 1237 ctx.WritePlainf("%d", n.UintValue) 1238 case TableOptionCheckSum: 1239 ctx.WriteKeyWord("CHECKSUM ") 1240 ctx.WritePlain("= ") 1241 ctx.WritePlainf("%d", n.UintValue) 1242 case TableOptionCompression: 1243 ctx.WriteKeyWord("COMPRESSION ") 1244 ctx.WritePlain("= ") 1245 ctx.WriteString(n.StrValue) 1246 case TableOptionConnection: 1247 ctx.WriteKeyWord("CONNECTION ") 1248 ctx.WritePlain("= ") 1249 ctx.WriteString(n.StrValue) 1250 case TableOptionPassword: 1251 ctx.WriteKeyWord("PASSWORD ") 1252 ctx.WritePlain("= ") 1253 ctx.WriteString(n.StrValue) 1254 case TableOptionKeyBlockSize: 1255 ctx.WriteKeyWord("KEY_BLOCK_SIZE ") 1256 ctx.WritePlain("= ") 1257 ctx.WritePlainf("%d", n.UintValue) 1258 case TableOptionMaxRows: 1259 ctx.WriteKeyWord("MAX_ROWS ") 1260 ctx.WritePlain("= ") 1261 ctx.WritePlainf("%d", n.UintValue) 1262 case TableOptionMinRows: 1263 ctx.WriteKeyWord("MIN_ROWS ") 1264 ctx.WritePlain("= ") 1265 ctx.WritePlainf("%d", n.UintValue) 1266 case TableOptionDelayKeyWrite: 1267 ctx.WriteKeyWord("DELAY_KEY_WRITE ") 1268 ctx.WritePlain("= ") 1269 ctx.WritePlainf("%d", n.UintValue) 1270 case TableOptionRowFormat: 1271 ctx.WriteKeyWord("ROW_FORMAT ") 1272 ctx.WritePlain("= ") 1273 switch n.UintValue { 1274 case RowFormatDefault: 1275 ctx.WriteKeyWord("DEFAULT") 1276 case RowFormatDynamic: 1277 ctx.WriteKeyWord("DYNAMIC") 1278 case RowFormatFixed: 1279 ctx.WriteKeyWord("FIXED") 1280 case RowFormatCompressed: 1281 ctx.WriteKeyWord("COMPRESSED") 1282 case RowFormatRedundant: 1283 ctx.WriteKeyWord("REDUNDANT") 1284 case RowFormatCompact: 1285 ctx.WriteKeyWord("COMPACT") 1286 default: 1287 return errors.Errorf("invalid TableOption: TableOptionRowFormat: %d", n.UintValue) 1288 } 1289 case TableOptionStatsPersistent: 1290 // TODO: not support 1291 ctx.WriteKeyWord("STATS_PERSISTENT ") 1292 ctx.WritePlain("= ") 1293 ctx.WriteKeyWord("DEFAULT") 1294 ctx.WritePlain(" /* TableOptionStatsPersistent is not supported */ ") 1295 case TableOptionShardRowID: 1296 ctx.WriteKeyWord("SHARD_ROW_ID_BITS ") 1297 ctx.WritePlain("= ") 1298 ctx.WritePlainf("%d", n.UintValue) 1299 case TableOptionPackKeys: 1300 // TODO: not support 1301 ctx.WriteKeyWord("PACK_KEYS ") 1302 ctx.WritePlain("= ") 1303 ctx.WriteKeyWord("DEFAULT") 1304 ctx.WritePlain(" /* TableOptionPackKeys is not supported */ ") 1305 default: 1306 return errors.Errorf("invalid TableOption: %d", n.Tp) 1307 } 1308 return nil 1309 } 1310 1311 // ColumnPositionType is the type for ColumnPosition. 1312 type ColumnPositionType int 1313 1314 // ColumnPosition Types 1315 const ( 1316 ColumnPositionNone ColumnPositionType = iota 1317 ColumnPositionFirst 1318 ColumnPositionAfter 1319 ) 1320 1321 // ColumnPosition represent the position of the newly added column 1322 type ColumnPosition struct { 1323 node 1324 // Tp is either ColumnPositionNone, ColumnPositionFirst or ColumnPositionAfter. 1325 Tp ColumnPositionType 1326 // RelativeColumn is the column the newly added column after if type is ColumnPositionAfter 1327 RelativeColumn *ColumnName 1328 } 1329 1330 // Restore implements Node interface. 1331 func (n *ColumnPosition) Restore(ctx *format.RestoreCtx) error { 1332 switch n.Tp { 1333 case ColumnPositionNone: 1334 // do nothing 1335 case ColumnPositionFirst: 1336 ctx.WriteKeyWord("FIRST") 1337 case ColumnPositionAfter: 1338 ctx.WriteKeyWord("AFTER ") 1339 if err := n.RelativeColumn.Restore(ctx); err != nil { 1340 return errors.Annotate(err, "An error occurred while restore ColumnPosition.RelativeColumn") 1341 } 1342 default: 1343 return errors.Errorf("invalid ColumnPositionType: %d", n.Tp) 1344 } 1345 return nil 1346 } 1347 1348 // Accept implements Node Accept interface. 1349 func (n *ColumnPosition) Accept(v Visitor) (Node, bool) { 1350 newNode, skipChildren := v.Enter(n) 1351 if skipChildren { 1352 return v.Leave(newNode) 1353 } 1354 n = newNode.(*ColumnPosition) 1355 if n.RelativeColumn != nil { 1356 node, ok := n.RelativeColumn.Accept(v) 1357 if !ok { 1358 return n, false 1359 } 1360 n.RelativeColumn = node.(*ColumnName) 1361 } 1362 return v.Leave(n) 1363 } 1364 1365 // AlterTableType is the type for AlterTableSpec. 1366 type AlterTableType int 1367 1368 // AlterTable types. 1369 const ( 1370 AlterTableOption AlterTableType = iota + 1 1371 AlterTableAddColumns 1372 AlterTableAddConstraint 1373 AlterTableDropColumn 1374 AlterTableDropPrimaryKey 1375 AlterTableDropIndex 1376 AlterTableDropForeignKey 1377 AlterTableModifyColumn 1378 AlterTableChangeColumn 1379 AlterTableRenameTable 1380 AlterTableAlterColumn 1381 AlterTableLock 1382 AlterTableAlgorithm 1383 AlterTableRenameIndex 1384 AlterTableForce 1385 AlterTableAddPartitions 1386 AlterTableCoalescePartitions 1387 AlterTableDropPartition 1388 AlterTableTruncatePartition 1389 1390 // TODO: Add more actions 1391 ) 1392 1393 // LockType is the type for AlterTableSpec. 1394 // See https://dev.mysql.com/doc/refman/5.7/en/alter-table.html#alter-table-concurrency 1395 type LockType byte 1396 1397 func (n LockType) String() string { 1398 switch n { 1399 case LockTypeNone: 1400 return "NONE" 1401 case LockTypeDefault: 1402 return "DEFAULT" 1403 case LockTypeShared: 1404 return "SHARED" 1405 case LockTypeExclusive: 1406 return "EXCLUSIVE" 1407 } 1408 return "" 1409 } 1410 1411 // Lock Types. 1412 const ( 1413 LockTypeNone LockType = iota + 1 1414 LockTypeDefault 1415 LockTypeShared 1416 LockTypeExclusive 1417 ) 1418 1419 // AlterAlgorithm is the algorithm of the DDL operations. 1420 // See https://dev.mysql.com/doc/refman/8.0/en/alter-table.html#alter-table-performance. 1421 type AlterAlgorithm byte 1422 1423 // DDL alter algorithms. 1424 // For now, TiDB only supported inplace and instance algorithms. If the user specify `copy`, 1425 // will get an error. 1426 const ( 1427 AlterAlgorithmDefault AlterAlgorithm = iota 1428 AlterAlgorithmCopy 1429 AlterAlgorithmInplace 1430 AlterAlgorithmInstant 1431 ) 1432 1433 func (a AlterAlgorithm) String() string { 1434 switch a { 1435 case AlterAlgorithmDefault: 1436 return "DEFAULT" 1437 case AlterAlgorithmCopy: 1438 return "COPY" 1439 case AlterAlgorithmInplace: 1440 return "INPLACE" 1441 case AlterAlgorithmInstant: 1442 return "INSTANT" 1443 default: 1444 return "DEFAULT" 1445 } 1446 } 1447 1448 // AlterTableSpec represents alter table specification. 1449 type AlterTableSpec struct { 1450 node 1451 1452 Tp AlterTableType 1453 Name string 1454 Constraint *Constraint 1455 Options []*TableOption 1456 NewTable *TableName 1457 NewColumns []*ColumnDef 1458 OldColumnName *ColumnName 1459 Position *ColumnPosition 1460 LockType LockType 1461 Algorithm AlterAlgorithm 1462 Comment string 1463 FromKey model.CIStr 1464 ToKey model.CIStr 1465 PartDefinitions []*PartitionDefinition 1466 Num uint64 1467 } 1468 1469 // Restore implements Node interface. 1470 func (n *AlterTableSpec) Restore(ctx *format.RestoreCtx) error { 1471 switch n.Tp { 1472 case AlterTableOption: 1473 switch { 1474 case len(n.Options) == 2 && 1475 n.Options[0].Tp == TableOptionCharset && 1476 n.Options[1].Tp == TableOptionCollate: 1477 ctx.WriteKeyWord("CONVERT TO CHARACTER SET ") 1478 ctx.WriteKeyWord(n.Options[0].StrValue) 1479 ctx.WriteKeyWord(" COLLATE ") 1480 ctx.WriteKeyWord(n.Options[1].StrValue) 1481 default: 1482 for i, opt := range n.Options { 1483 if i != 0 { 1484 ctx.WritePlain(", ") 1485 } 1486 if err := opt.Restore(ctx); err != nil { 1487 return errors.Annotatef(err, "An error occurred while restore AlterTableSpec.Options[%d]", i) 1488 } 1489 } 1490 } 1491 case AlterTableAddColumns: 1492 ctx.WriteKeyWord("ADD COLUMN ") 1493 if n.Position != nil && len(n.NewColumns) == 1 { 1494 if err := n.NewColumns[0].Restore(ctx); err != nil { 1495 return errors.Annotatef(err, "An error occurred while restore AlterTableSpec.NewColumns[%d]", 0) 1496 } 1497 if n.Position.Tp != ColumnPositionNone { 1498 ctx.WritePlain(" ") 1499 } 1500 if err := n.Position.Restore(ctx); err != nil { 1501 return errors.Annotate(err, "An error occurred while restore AlterTableSpec.Position") 1502 } 1503 } else { 1504 ctx.WritePlain("(") 1505 for i, col := range n.NewColumns { 1506 if i != 0 { 1507 ctx.WritePlain(", ") 1508 } 1509 if err := col.Restore(ctx); err != nil { 1510 return errors.Annotatef(err, "An error occurred while restore AlterTableSpec.NewColumns[%d]", i) 1511 } 1512 } 1513 ctx.WritePlain(")") 1514 } 1515 case AlterTableAddConstraint: 1516 ctx.WriteKeyWord("ADD ") 1517 if err := n.Constraint.Restore(ctx); err != nil { 1518 return errors.Annotate(err, "An error occurred while restore AlterTableSpec.Constraint") 1519 } 1520 case AlterTableDropColumn: 1521 ctx.WriteKeyWord("DROP COLUMN ") 1522 if err := n.OldColumnName.Restore(ctx); err != nil { 1523 return errors.Annotate(err, "An error occurred while restore AlterTableSpec.OldColumnName") 1524 } 1525 // TODO: RestrictOrCascadeOpt not support 1526 case AlterTableDropPrimaryKey: 1527 ctx.WriteKeyWord("DROP PRIMARY KEY") 1528 case AlterTableDropIndex: 1529 ctx.WriteKeyWord("DROP INDEX ") 1530 ctx.WriteName(n.Name) 1531 case AlterTableDropForeignKey: 1532 ctx.WriteKeyWord("DROP FOREIGN KEY ") 1533 ctx.WriteName(n.Name) 1534 case AlterTableModifyColumn: 1535 ctx.WriteKeyWord("MODIFY COLUMN ") 1536 if err := n.NewColumns[0].Restore(ctx); err != nil { 1537 return errors.Annotate(err, "An error occurred while restore AlterTableSpec.NewColumns[0]") 1538 } 1539 if n.Position.Tp != ColumnPositionNone { 1540 ctx.WritePlain(" ") 1541 } 1542 if err := n.Position.Restore(ctx); err != nil { 1543 return errors.Annotate(err, "An error occurred while restore AlterTableSpec.Position") 1544 } 1545 case AlterTableChangeColumn: 1546 ctx.WriteKeyWord("CHANGE COLUMN ") 1547 if err := n.OldColumnName.Restore(ctx); err != nil { 1548 return errors.Annotate(err, "An error occurred while restore AlterTableSpec.OldColumnName") 1549 } 1550 ctx.WritePlain(" ") 1551 if err := n.NewColumns[0].Restore(ctx); err != nil { 1552 return errors.Annotate(err, "An error occurred while restore AlterTableSpec.NewColumns[0]") 1553 } 1554 if n.Position.Tp != ColumnPositionNone { 1555 ctx.WritePlain(" ") 1556 } 1557 if err := n.Position.Restore(ctx); err != nil { 1558 return errors.Annotate(err, "An error occurred while restore AlterTableSpec.Position") 1559 } 1560 case AlterTableRenameTable: 1561 ctx.WriteKeyWord("RENAME AS ") 1562 if err := n.NewTable.Restore(ctx); err != nil { 1563 return errors.Annotate(err, "An error occurred while restore AlterTableSpec.NewTable") 1564 } 1565 case AlterTableAlterColumn: 1566 ctx.WriteKeyWord("ALTER COLUMN ") 1567 if err := n.NewColumns[0].Restore(ctx); err != nil { 1568 return errors.Annotate(err, "An error occurred while restore AlterTableSpec.NewColumns[0]") 1569 } 1570 if len(n.NewColumns[0].Options) == 1 { 1571 ctx.WriteKeyWord("SET DEFAULT ") 1572 if err := n.NewColumns[0].Options[0].Expr.Restore(ctx); err != nil { 1573 return errors.Annotate(err, "An error occurred while restore AlterTableSpec.NewColumns[0].Options[0].Expr") 1574 } 1575 } else { 1576 ctx.WriteKeyWord(" DROP DEFAULT") 1577 } 1578 case AlterTableLock: 1579 ctx.WriteKeyWord("LOCK ") 1580 ctx.WritePlain("= ") 1581 ctx.WriteKeyWord(n.LockType.String()) 1582 case AlterTableAlgorithm: 1583 ctx.WriteKeyWord("ALGORITHM ") 1584 ctx.WritePlain("= ") 1585 ctx.WriteKeyWord(n.Algorithm.String()) 1586 case AlterTableRenameIndex: 1587 ctx.WriteKeyWord("RENAME INDEX ") 1588 ctx.WriteName(n.FromKey.O) 1589 ctx.WriteKeyWord(" TO ") 1590 ctx.WriteName(n.ToKey.O) 1591 case AlterTableForce: 1592 // TODO: not support 1593 ctx.WriteKeyWord("FORCE") 1594 ctx.WritePlain(" /* AlterTableForce is not supported */ ") 1595 case AlterTableAddPartitions: 1596 ctx.WriteKeyWord("ADD PARTITION") 1597 if n.PartDefinitions != nil { 1598 ctx.WritePlain(" (") 1599 for i, def := range n.PartDefinitions { 1600 if i != 0 { 1601 ctx.WritePlain(", ") 1602 } 1603 if err := def.Restore(ctx); err != nil { 1604 return errors.Annotatef(err, "An error occurred while restore AlterTableSpec.PartDefinitions[%d]", i) 1605 } 1606 } 1607 ctx.WritePlain(")") 1608 } else if n.Num != 0 { 1609 ctx.WriteKeyWord(" PARTITIONS ") 1610 ctx.WritePlainf("%d", n.Num) 1611 } 1612 case AlterTableCoalescePartitions: 1613 ctx.WriteKeyWord("COALESCE PARTITION ") 1614 ctx.WritePlainf("%d", n.Num) 1615 case AlterTableDropPartition: 1616 ctx.WriteKeyWord("DROP PARTITION ") 1617 ctx.WriteName(n.Name) 1618 case AlterTableTruncatePartition: 1619 ctx.WriteKeyWord("TRUNCATE PARTITION ") 1620 ctx.WriteName(n.Name) 1621 default: 1622 // TODO: not support 1623 ctx.WritePlainf(" /* AlterTableType(%d) is not supported */ ", n.Tp) 1624 } 1625 return nil 1626 } 1627 1628 // Accept implements Node Accept interface. 1629 func (n *AlterTableSpec) Accept(v Visitor) (Node, bool) { 1630 newNode, skipChildren := v.Enter(n) 1631 if skipChildren { 1632 return v.Leave(newNode) 1633 } 1634 n = newNode.(*AlterTableSpec) 1635 if n.Constraint != nil { 1636 node, ok := n.Constraint.Accept(v) 1637 if !ok { 1638 return n, false 1639 } 1640 n.Constraint = node.(*Constraint) 1641 } 1642 if n.NewTable != nil { 1643 node, ok := n.NewTable.Accept(v) 1644 if !ok { 1645 return n, false 1646 } 1647 n.NewTable = node.(*TableName) 1648 } 1649 for _, col := range n.NewColumns { 1650 node, ok := col.Accept(v) 1651 if !ok { 1652 return n, false 1653 } 1654 col = node.(*ColumnDef) 1655 } 1656 if n.OldColumnName != nil { 1657 node, ok := n.OldColumnName.Accept(v) 1658 if !ok { 1659 return n, false 1660 } 1661 n.OldColumnName = node.(*ColumnName) 1662 } 1663 if n.Position != nil { 1664 node, ok := n.Position.Accept(v) 1665 if !ok { 1666 return n, false 1667 } 1668 n.Position = node.(*ColumnPosition) 1669 } 1670 return v.Leave(n) 1671 } 1672 1673 // AlterTableStmt is a statement to change the structure of a table. 1674 // See https://dev.mysql.com/doc/refman/5.7/en/alter-table.html 1675 type AlterTableStmt struct { 1676 ddlNode 1677 1678 Table *TableName 1679 Specs []*AlterTableSpec 1680 } 1681 1682 // Restore implements Node interface. 1683 func (n *AlterTableStmt) Restore(ctx *format.RestoreCtx) error { 1684 ctx.WriteKeyWord("ALTER TABLE ") 1685 if err := n.Table.Restore(ctx); err != nil { 1686 return errors.Annotate(err, "An error occurred while restore AlterTableStmt.Table") 1687 } 1688 for i, spec := range n.Specs { 1689 if i == 0 { 1690 ctx.WritePlain(" ") 1691 } else { 1692 ctx.WritePlain(", ") 1693 } 1694 if err := spec.Restore(ctx); err != nil { 1695 return errors.Annotatef(err, "An error occurred while restore AlterTableStmt.Specs[%d]", i) 1696 } 1697 } 1698 return nil 1699 } 1700 1701 // Accept implements Node Accept interface. 1702 func (n *AlterTableStmt) Accept(v Visitor) (Node, bool) { 1703 newNode, skipChildren := v.Enter(n) 1704 if skipChildren { 1705 return v.Leave(newNode) 1706 } 1707 n = newNode.(*AlterTableStmt) 1708 node, ok := n.Table.Accept(v) 1709 if !ok { 1710 return n, false 1711 } 1712 n.Table = node.(*TableName) 1713 for i, val := range n.Specs { 1714 node, ok = val.Accept(v) 1715 if !ok { 1716 return n, false 1717 } 1718 n.Specs[i] = node.(*AlterTableSpec) 1719 } 1720 return v.Leave(n) 1721 } 1722 1723 // TruncateTableStmt is a statement to empty a table completely. 1724 // See https://dev.mysql.com/doc/refman/5.7/en/truncate-table.html 1725 type TruncateTableStmt struct { 1726 ddlNode 1727 1728 Table *TableName 1729 } 1730 1731 // Restore implements Node interface. 1732 func (n *TruncateTableStmt) Restore(ctx *format.RestoreCtx) error { 1733 ctx.WriteKeyWord("TRUNCATE TABLE ") 1734 if err := n.Table.Restore(ctx); err != nil { 1735 return errors.Annotate(err, "An error occurred while restore TruncateTableStmt.Table") 1736 } 1737 return nil 1738 } 1739 1740 // Accept implements Node Accept interface. 1741 func (n *TruncateTableStmt) Accept(v Visitor) (Node, bool) { 1742 newNode, skipChildren := v.Enter(n) 1743 if skipChildren { 1744 return v.Leave(newNode) 1745 } 1746 n = newNode.(*TruncateTableStmt) 1747 node, ok := n.Table.Accept(v) 1748 if !ok { 1749 return n, false 1750 } 1751 n.Table = node.(*TableName) 1752 return v.Leave(n) 1753 } 1754 1755 // PartitionDefinition defines a single partition. 1756 type PartitionDefinition struct { 1757 Name model.CIStr 1758 LessThan []ExprNode 1759 MaxValue bool 1760 Comment string 1761 } 1762 1763 // Restore implements Node interface. 1764 func (n *PartitionDefinition) Restore(ctx *format.RestoreCtx) error { 1765 ctx.WriteKeyWord("PARTITION ") 1766 ctx.WriteName(n.Name.O) 1767 if n.LessThan != nil { 1768 ctx.WriteKeyWord(" VALUES LESS THAN ") 1769 ctx.WritePlain("(") 1770 for k, less := range n.LessThan { 1771 if err := less.Restore(ctx); err != nil { 1772 return errors.Annotatef(err, "An error occurred while restore PartitionDefinition.LessThan[%d]", k) 1773 } 1774 } 1775 ctx.WritePlain(")") 1776 } 1777 if n.Comment != "" { 1778 ctx.WriteKeyWord(" COMMENT ") 1779 ctx.WritePlain("= ") 1780 ctx.WriteString(n.Comment) 1781 } 1782 return nil 1783 } 1784 1785 // PartitionOptions specifies the partition options. 1786 type PartitionOptions struct { 1787 Tp model.PartitionType 1788 Expr ExprNode 1789 ColumnNames []*ColumnName 1790 Definitions []*PartitionDefinition 1791 Num uint64 1792 } 1793 1794 // Restore ctx partition options restore 1795 func (n *PartitionOptions) Restore(ctx *format.RestoreCtx) error { 1796 ctx.WriteKeyWord("PARTITION BY ") 1797 switch n.Tp { 1798 case model.PartitionTypeRange: 1799 ctx.WriteKeyWord("RANGE ") 1800 case model.PartitionTypeHash: 1801 ctx.WriteKeyWord("HASH ") 1802 case model.PartitionTypeList: 1803 return errors.New("TiDB Parser ignore the `PartitionTypeList` type now") 1804 default: 1805 return errors.Errorf("invalid model.PartitionType: %d", n.Tp) 1806 } 1807 1808 if n.Expr != nil { 1809 ctx.WritePlain("(") 1810 if err := n.Expr.Restore(ctx); err != nil { 1811 return errors.Annotate(err, "An error occurred while restore PartitionOptions Expr") 1812 } 1813 ctx.WritePlain(") ") 1814 } 1815 if len(n.ColumnNames) > 0 { 1816 ctx.WriteKeyWord("COLUMNS") 1817 ctx.WritePlain("(") 1818 for i, col := range n.ColumnNames { 1819 if i > 0 { 1820 ctx.WritePlain(",") 1821 } 1822 if err := col.Restore(ctx); err != nil { 1823 return errors.Annotatef(err, "An error occurred while splicing PartitionOptions ColumnName: [%v]", i) 1824 } 1825 } 1826 ctx.WritePlain(") ") 1827 } 1828 if n.Num > 0 { 1829 ctx.WriteKeyWord("PARTITIONS ") 1830 ctx.WritePlainf("%d", n.Num) 1831 } 1832 1833 if len(n.Definitions) > 0 { 1834 ctx.WritePlain("(") 1835 for i, def := range n.Definitions { 1836 if i > 0 { 1837 ctx.WritePlain(",") 1838 } 1839 if err := def.Restore(ctx); err != nil { 1840 return errors.Annotatef(err, "An error occurred while splicing PartitionOptions Definitions: [%v]", i) 1841 } 1842 } 1843 ctx.WritePlain(")") 1844 } 1845 1846 return nil 1847 }