You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
642 lines
14 KiB
642 lines
14 KiB
8 years ago
|
// Copyright 2015 PingCAP, Inc.
|
||
|
//
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
// you may not use this file except in compliance with the License.
|
||
|
// You may obtain a copy of the License at
|
||
|
//
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
//
|
||
|
// Unless required by applicable law or agreed to in writing, software
|
||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
// See the License for the specific language governing permissions and
|
||
|
// limitations under the License.
|
||
|
|
||
|
package ast
|
||
|
|
||
|
import (
|
||
|
"github.com/pingcap/tidb/model"
|
||
|
"github.com/pingcap/tidb/util/types"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
_ DDLNode = &AlterTableStmt{}
|
||
|
_ DDLNode = &CreateDatabaseStmt{}
|
||
|
_ DDLNode = &CreateIndexStmt{}
|
||
|
_ DDLNode = &CreateTableStmt{}
|
||
|
_ DDLNode = &DropDatabaseStmt{}
|
||
|
_ DDLNode = &DropIndexStmt{}
|
||
|
_ DDLNode = &DropTableStmt{}
|
||
|
_ DDLNode = &TruncateTableStmt{}
|
||
|
|
||
|
_ Node = &AlterTableSpec{}
|
||
|
_ Node = &ColumnDef{}
|
||
|
_ Node = &ColumnOption{}
|
||
|
_ Node = &ColumnPosition{}
|
||
|
_ Node = &Constraint{}
|
||
|
_ Node = &IndexColName{}
|
||
|
_ Node = &ReferenceDef{}
|
||
|
)
|
||
|
|
||
|
// CharsetOpt is used for parsing charset option from SQL.
|
||
|
type CharsetOpt struct {
|
||
|
Chs string
|
||
|
Col string
|
||
|
}
|
||
|
|
||
|
// DatabaseOptionType is the type for database options.
|
||
|
type DatabaseOptionType int
|
||
|
|
||
|
// Database option types.
|
||
|
const (
|
||
|
DatabaseOptionNone DatabaseOptionType = iota
|
||
|
DatabaseOptionCharset
|
||
|
DatabaseOptionCollate
|
||
|
)
|
||
|
|
||
|
// DatabaseOption represents database option.
|
||
|
type DatabaseOption struct {
|
||
|
Tp DatabaseOptionType
|
||
|
Value string
|
||
|
}
|
||
|
|
||
|
// CreateDatabaseStmt is a statement to create a database.
|
||
|
// See: https://dev.mysql.com/doc/refman/5.7/en/create-database.html
|
||
|
type CreateDatabaseStmt struct {
|
||
|
ddlNode
|
||
|
|
||
|
IfNotExists bool
|
||
|
Name string
|
||
|
Options []*DatabaseOption
|
||
|
}
|
||
|
|
||
|
// Accept implements Node Accept interface.
|
||
|
func (n *CreateDatabaseStmt) Accept(v Visitor) (Node, bool) {
|
||
|
newNode, skipChildren := v.Enter(n)
|
||
|
if skipChildren {
|
||
|
return v.Leave(newNode)
|
||
|
}
|
||
|
n = newNode.(*CreateDatabaseStmt)
|
||
|
return v.Leave(n)
|
||
|
}
|
||
|
|
||
|
// DropDatabaseStmt is a statement to drop a database and all tables in the database.
|
||
|
// See: https://dev.mysql.com/doc/refman/5.7/en/drop-database.html
|
||
|
type DropDatabaseStmt struct {
|
||
|
ddlNode
|
||
|
|
||
|
IfExists bool
|
||
|
Name string
|
||
|
}
|
||
|
|
||
|
// Accept implements Node Accept interface.
|
||
|
func (n *DropDatabaseStmt) Accept(v Visitor) (Node, bool) {
|
||
|
newNode, skipChildren := v.Enter(n)
|
||
|
if skipChildren {
|
||
|
return v.Leave(newNode)
|
||
|
}
|
||
|
n = newNode.(*DropDatabaseStmt)
|
||
|
return v.Leave(n)
|
||
|
}
|
||
|
|
||
|
// IndexColName is used for parsing index column name from SQL.
|
||
|
type IndexColName struct {
|
||
|
node
|
||
|
|
||
|
Column *ColumnName
|
||
|
Length int
|
||
|
}
|
||
|
|
||
|
// Accept implements Node Accept interface.
|
||
|
func (n *IndexColName) Accept(v Visitor) (Node, bool) {
|
||
|
newNode, skipChildren := v.Enter(n)
|
||
|
if skipChildren {
|
||
|
return v.Leave(newNode)
|
||
|
}
|
||
|
n = newNode.(*IndexColName)
|
||
|
node, ok := n.Column.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.Column = node.(*ColumnName)
|
||
|
return v.Leave(n)
|
||
|
}
|
||
|
|
||
|
// ReferenceDef is used for parsing foreign key reference option from SQL.
|
||
|
// See: http://dev.mysql.com/doc/refman/5.7/en/create-table-foreign-keys.html
|
||
|
type ReferenceDef struct {
|
||
|
node
|
||
|
|
||
|
Table *TableName
|
||
|
IndexColNames []*IndexColName
|
||
|
}
|
||
|
|
||
|
// Accept implements Node Accept interface.
|
||
|
func (n *ReferenceDef) Accept(v Visitor) (Node, bool) {
|
||
|
newNode, skipChildren := v.Enter(n)
|
||
|
if skipChildren {
|
||
|
return v.Leave(newNode)
|
||
|
}
|
||
|
n = newNode.(*ReferenceDef)
|
||
|
node, ok := n.Table.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.Table = node.(*TableName)
|
||
|
for i, val := range n.IndexColNames {
|
||
|
node, ok = val.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.IndexColNames[i] = node.(*IndexColName)
|
||
|
}
|
||
|
return v.Leave(n)
|
||
|
}
|
||
|
|
||
|
// ColumnOptionType is the type for ColumnOption.
|
||
|
type ColumnOptionType int
|
||
|
|
||
|
// ColumnOption types.
|
||
|
const (
|
||
|
ColumnOptionNoOption ColumnOptionType = iota
|
||
|
ColumnOptionPrimaryKey
|
||
|
ColumnOptionNotNull
|
||
|
ColumnOptionAutoIncrement
|
||
|
ColumnOptionDefaultValue
|
||
|
ColumnOptionUniq
|
||
|
ColumnOptionIndex
|
||
|
ColumnOptionUniqIndex
|
||
|
ColumnOptionKey
|
||
|
ColumnOptionUniqKey
|
||
|
ColumnOptionNull
|
||
|
ColumnOptionOnUpdate // For Timestamp and Datetime only.
|
||
|
ColumnOptionFulltext
|
||
|
ColumnOptionComment
|
||
|
)
|
||
|
|
||
|
// ColumnOption is used for parsing column constraint info from SQL.
|
||
|
type ColumnOption struct {
|
||
|
node
|
||
|
|
||
|
Tp ColumnOptionType
|
||
|
// The value For Default or On Update.
|
||
|
Expr ExprNode
|
||
|
}
|
||
|
|
||
|
// Accept implements Node Accept interface.
|
||
|
func (n *ColumnOption) Accept(v Visitor) (Node, bool) {
|
||
|
newNode, skipChildren := v.Enter(n)
|
||
|
if skipChildren {
|
||
|
return v.Leave(newNode)
|
||
|
}
|
||
|
n = newNode.(*ColumnOption)
|
||
|
if n.Expr != nil {
|
||
|
node, ok := n.Expr.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.Expr = node.(ExprNode)
|
||
|
}
|
||
|
return v.Leave(n)
|
||
|
}
|
||
|
|
||
|
// IndexOption is the index options.
|
||
|
// KEY_BLOCK_SIZE [=] value
|
||
|
// | index_type
|
||
|
// | WITH PARSER parser_name
|
||
|
// | COMMENT 'string'
|
||
|
// See: http://dev.mysql.com/doc/refman/5.7/en/create-table.html
|
||
|
type IndexOption struct {
|
||
|
node
|
||
|
|
||
|
KeyBlockSize uint64
|
||
|
Tp model.IndexType
|
||
|
Comment string
|
||
|
}
|
||
|
|
||
|
// Accept implements Node Accept interface.
|
||
|
func (n *IndexOption) Accept(v Visitor) (Node, bool) {
|
||
|
newNode, skipChildren := v.Enter(n)
|
||
|
if skipChildren {
|
||
|
return v.Leave(newNode)
|
||
|
}
|
||
|
n = newNode.(*IndexOption)
|
||
|
return v.Leave(n)
|
||
|
}
|
||
|
|
||
|
// ConstraintType is the type for Constraint.
|
||
|
type ConstraintType int
|
||
|
|
||
|
// ConstraintTypes
|
||
|
const (
|
||
|
ConstraintNoConstraint ConstraintType = iota
|
||
|
ConstraintPrimaryKey
|
||
|
ConstraintKey
|
||
|
ConstraintIndex
|
||
|
ConstraintUniq
|
||
|
ConstraintUniqKey
|
||
|
ConstraintUniqIndex
|
||
|
ConstraintForeignKey
|
||
|
ConstraintFulltext
|
||
|
)
|
||
|
|
||
|
// Constraint is constraint for table definition.
|
||
|
type Constraint struct {
|
||
|
node
|
||
|
|
||
|
Tp ConstraintType
|
||
|
Name string
|
||
|
|
||
|
// Used for PRIMARY KEY, UNIQUE, ......
|
||
|
Keys []*IndexColName
|
||
|
|
||
|
// Used for foreign key.
|
||
|
Refer *ReferenceDef
|
||
|
|
||
|
// Index Options
|
||
|
Option *IndexOption
|
||
|
}
|
||
|
|
||
|
// Accept implements Node Accept interface.
|
||
|
func (n *Constraint) Accept(v Visitor) (Node, bool) {
|
||
|
newNode, skipChildren := v.Enter(n)
|
||
|
if skipChildren {
|
||
|
return v.Leave(newNode)
|
||
|
}
|
||
|
n = newNode.(*Constraint)
|
||
|
for i, val := range n.Keys {
|
||
|
node, ok := val.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.Keys[i] = node.(*IndexColName)
|
||
|
}
|
||
|
if n.Refer != nil {
|
||
|
node, ok := n.Refer.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.Refer = node.(*ReferenceDef)
|
||
|
}
|
||
|
if n.Option != nil {
|
||
|
node, ok := n.Option.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.Option = node.(*IndexOption)
|
||
|
}
|
||
|
return v.Leave(n)
|
||
|
}
|
||
|
|
||
|
// ColumnDef is used for parsing column definition from SQL.
|
||
|
type ColumnDef struct {
|
||
|
node
|
||
|
|
||
|
Name *ColumnName
|
||
|
Tp *types.FieldType
|
||
|
Options []*ColumnOption
|
||
|
}
|
||
|
|
||
|
// Accept implements Node Accept interface.
|
||
|
func (n *ColumnDef) Accept(v Visitor) (Node, bool) {
|
||
|
newNode, skipChildren := v.Enter(n)
|
||
|
if skipChildren {
|
||
|
return v.Leave(newNode)
|
||
|
}
|
||
|
n = newNode.(*ColumnDef)
|
||
|
node, ok := n.Name.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.Name = node.(*ColumnName)
|
||
|
for i, val := range n.Options {
|
||
|
node, ok := val.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.Options[i] = node.(*ColumnOption)
|
||
|
}
|
||
|
return v.Leave(n)
|
||
|
}
|
||
|
|
||
|
// CreateTableStmt is a statement to create a table.
|
||
|
// See: https://dev.mysql.com/doc/refman/5.7/en/create-table.html
|
||
|
type CreateTableStmt struct {
|
||
|
ddlNode
|
||
|
|
||
|
IfNotExists bool
|
||
|
Table *TableName
|
||
|
Cols []*ColumnDef
|
||
|
Constraints []*Constraint
|
||
|
Options []*TableOption
|
||
|
}
|
||
|
|
||
|
// Accept implements Node Accept interface.
|
||
|
func (n *CreateTableStmt) Accept(v Visitor) (Node, bool) {
|
||
|
newNode, skipChildren := v.Enter(n)
|
||
|
if skipChildren {
|
||
|
return v.Leave(newNode)
|
||
|
}
|
||
|
n = newNode.(*CreateTableStmt)
|
||
|
node, ok := n.Table.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.Table = node.(*TableName)
|
||
|
for i, val := range n.Cols {
|
||
|
node, ok = val.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.Cols[i] = node.(*ColumnDef)
|
||
|
}
|
||
|
for i, val := range n.Constraints {
|
||
|
node, ok = val.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.Constraints[i] = node.(*Constraint)
|
||
|
}
|
||
|
return v.Leave(n)
|
||
|
}
|
||
|
|
||
|
// DropTableStmt is a statement to drop one or more tables.
|
||
|
// See: https://dev.mysql.com/doc/refman/5.7/en/drop-table.html
|
||
|
type DropTableStmt struct {
|
||
|
ddlNode
|
||
|
|
||
|
IfExists bool
|
||
|
Tables []*TableName
|
||
|
}
|
||
|
|
||
|
// Accept implements Node Accept interface.
|
||
|
func (n *DropTableStmt) Accept(v Visitor) (Node, bool) {
|
||
|
newNode, skipChildren := v.Enter(n)
|
||
|
if skipChildren {
|
||
|
return v.Leave(newNode)
|
||
|
}
|
||
|
n = newNode.(*DropTableStmt)
|
||
|
for i, val := range n.Tables {
|
||
|
node, ok := val.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.Tables[i] = node.(*TableName)
|
||
|
}
|
||
|
return v.Leave(n)
|
||
|
}
|
||
|
|
||
|
// CreateIndexStmt is a statement to create an index.
|
||
|
// See: https://dev.mysql.com/doc/refman/5.7/en/create-index.html
|
||
|
type CreateIndexStmt struct {
|
||
|
ddlNode
|
||
|
|
||
|
IndexName string
|
||
|
Table *TableName
|
||
|
Unique bool
|
||
|
IndexColNames []*IndexColName
|
||
|
}
|
||
|
|
||
|
// Accept implements Node Accept interface.
|
||
|
func (n *CreateIndexStmt) Accept(v Visitor) (Node, bool) {
|
||
|
newNode, skipChildren := v.Enter(n)
|
||
|
if skipChildren {
|
||
|
return v.Leave(newNode)
|
||
|
}
|
||
|
n = newNode.(*CreateIndexStmt)
|
||
|
node, ok := n.Table.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.Table = node.(*TableName)
|
||
|
for i, val := range n.IndexColNames {
|
||
|
node, ok = val.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.IndexColNames[i] = node.(*IndexColName)
|
||
|
}
|
||
|
return v.Leave(n)
|
||
|
}
|
||
|
|
||
|
// DropIndexStmt is a statement to drop the index.
|
||
|
// See: https://dev.mysql.com/doc/refman/5.7/en/drop-index.html
|
||
|
type DropIndexStmt struct {
|
||
|
ddlNode
|
||
|
|
||
|
IfExists bool
|
||
|
IndexName string
|
||
|
Table *TableName
|
||
|
}
|
||
|
|
||
|
// Accept implements Node Accept interface.
|
||
|
func (n *DropIndexStmt) Accept(v Visitor) (Node, bool) {
|
||
|
newNode, skipChildren := v.Enter(n)
|
||
|
if skipChildren {
|
||
|
return v.Leave(newNode)
|
||
|
}
|
||
|
n = newNode.(*DropIndexStmt)
|
||
|
node, ok := n.Table.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.Table = node.(*TableName)
|
||
|
return v.Leave(n)
|
||
|
}
|
||
|
|
||
|
// TableOptionType is the type for TableOption
|
||
|
type TableOptionType int
|
||
|
|
||
|
// TableOption types.
|
||
|
const (
|
||
|
TableOptionNone TableOptionType = iota
|
||
|
TableOptionEngine
|
||
|
TableOptionCharset
|
||
|
TableOptionCollate
|
||
|
TableOptionAutoIncrement
|
||
|
TableOptionComment
|
||
|
TableOptionAvgRowLength
|
||
|
TableOptionCheckSum
|
||
|
TableOptionCompression
|
||
|
TableOptionConnection
|
||
|
TableOptionPassword
|
||
|
TableOptionKeyBlockSize
|
||
|
TableOptionMaxRows
|
||
|
TableOptionMinRows
|
||
|
TableOptionDelayKeyWrite
|
||
|
TableOptionRowFormat
|
||
|
)
|
||
|
|
||
|
// RowFormat types
|
||
|
const (
|
||
|
RowFormatDefault uint64 = iota + 1
|
||
|
RowFormatDynamic
|
||
|
RowFormatFixed
|
||
|
RowFormatCompressed
|
||
|
RowFormatRedundant
|
||
|
RowFormatCompact
|
||
|
)
|
||
|
|
||
|
// TableOption is used for parsing table option from SQL.
|
||
|
type TableOption struct {
|
||
|
Tp TableOptionType
|
||
|
StrValue string
|
||
|
UintValue uint64
|
||
|
}
|
||
|
|
||
|
// ColumnPositionType is the type for ColumnPosition.
|
||
|
type ColumnPositionType int
|
||
|
|
||
|
// ColumnPosition Types
|
||
|
const (
|
||
|
ColumnPositionNone ColumnPositionType = iota
|
||
|
ColumnPositionFirst
|
||
|
ColumnPositionAfter
|
||
|
)
|
||
|
|
||
|
// ColumnPosition represent the position of the newly added column
|
||
|
type ColumnPosition struct {
|
||
|
node
|
||
|
// ColumnPositionNone | ColumnPositionFirst | ColumnPositionAfter
|
||
|
Tp ColumnPositionType
|
||
|
// RelativeColumn is the column the newly added column after if type is ColumnPositionAfter
|
||
|
RelativeColumn *ColumnName
|
||
|
}
|
||
|
|
||
|
// Accept implements Node Accept interface.
|
||
|
func (n *ColumnPosition) Accept(v Visitor) (Node, bool) {
|
||
|
newNode, skipChildren := v.Enter(n)
|
||
|
if skipChildren {
|
||
|
return v.Leave(newNode)
|
||
|
}
|
||
|
n = newNode.(*ColumnPosition)
|
||
|
if n.RelativeColumn != nil {
|
||
|
node, ok := n.RelativeColumn.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.RelativeColumn = node.(*ColumnName)
|
||
|
}
|
||
|
return v.Leave(n)
|
||
|
}
|
||
|
|
||
|
// AlterTableType is the type for AlterTableSpec.
|
||
|
type AlterTableType int
|
||
|
|
||
|
// AlterTable types.
|
||
|
const (
|
||
|
AlterTableOption AlterTableType = iota + 1
|
||
|
AlterTableAddColumn
|
||
|
AlterTableAddConstraint
|
||
|
AlterTableDropColumn
|
||
|
AlterTableDropPrimaryKey
|
||
|
AlterTableDropIndex
|
||
|
AlterTableDropForeignKey
|
||
|
|
||
|
// TODO: Add more actions
|
||
|
)
|
||
|
|
||
|
// AlterTableSpec represents alter table specification.
|
||
|
type AlterTableSpec struct {
|
||
|
node
|
||
|
|
||
|
Tp AlterTableType
|
||
|
Name string
|
||
|
Constraint *Constraint
|
||
|
Options []*TableOption
|
||
|
Column *ColumnDef
|
||
|
DropColumn *ColumnName
|
||
|
Position *ColumnPosition
|
||
|
}
|
||
|
|
||
|
// Accept implements Node Accept interface.
|
||
|
func (n *AlterTableSpec) Accept(v Visitor) (Node, bool) {
|
||
|
newNode, skipChildren := v.Enter(n)
|
||
|
if skipChildren {
|
||
|
return v.Leave(newNode)
|
||
|
}
|
||
|
n = newNode.(*AlterTableSpec)
|
||
|
if n.Constraint != nil {
|
||
|
node, ok := n.Constraint.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.Constraint = node.(*Constraint)
|
||
|
}
|
||
|
if n.Column != nil {
|
||
|
node, ok := n.Column.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.Column = node.(*ColumnDef)
|
||
|
}
|
||
|
if n.DropColumn != nil {
|
||
|
node, ok := n.DropColumn.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.DropColumn = node.(*ColumnName)
|
||
|
}
|
||
|
if n.Position != nil {
|
||
|
node, ok := n.Position.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.Position = node.(*ColumnPosition)
|
||
|
}
|
||
|
return v.Leave(n)
|
||
|
}
|
||
|
|
||
|
// AlterTableStmt is a statement to change the structure of a table.
|
||
|
// See: https://dev.mysql.com/doc/refman/5.7/en/alter-table.html
|
||
|
type AlterTableStmt struct {
|
||
|
ddlNode
|
||
|
|
||
|
Table *TableName
|
||
|
Specs []*AlterTableSpec
|
||
|
}
|
||
|
|
||
|
// Accept implements Node Accept interface.
|
||
|
func (n *AlterTableStmt) Accept(v Visitor) (Node, bool) {
|
||
|
newNode, skipChildren := v.Enter(n)
|
||
|
if skipChildren {
|
||
|
return v.Leave(newNode)
|
||
|
}
|
||
|
n = newNode.(*AlterTableStmt)
|
||
|
node, ok := n.Table.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.Table = node.(*TableName)
|
||
|
for i, val := range n.Specs {
|
||
|
node, ok = val.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.Specs[i] = node.(*AlterTableSpec)
|
||
|
}
|
||
|
return v.Leave(n)
|
||
|
}
|
||
|
|
||
|
// TruncateTableStmt is a statement to empty a table completely.
|
||
|
// See: https://dev.mysql.com/doc/refman/5.7/en/truncate-table.html
|
||
|
type TruncateTableStmt struct {
|
||
|
ddlNode
|
||
|
|
||
|
Table *TableName
|
||
|
}
|
||
|
|
||
|
// Accept implements Node Accept interface.
|
||
|
func (n *TruncateTableStmt) Accept(v Visitor) (Node, bool) {
|
||
|
newNode, skipChildren := v.Enter(n)
|
||
|
if skipChildren {
|
||
|
return v.Leave(newNode)
|
||
|
}
|
||
|
n = newNode.(*TruncateTableStmt)
|
||
|
node, ok := n.Table.Accept(v)
|
||
|
if !ok {
|
||
|
return n, false
|
||
|
}
|
||
|
n.Table = node.(*TableName)
|
||
|
return v.Leave(n)
|
||
|
}
|