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  }