Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
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.
641 lines
14 KiB
641 lines
14 KiB
// 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) |
|
}
|
|
|