Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

parser: implement Restore for CreateTableStmt #170

Merged
merged 19 commits into from
Jan 15, 2019
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 128 additions & 8 deletions ast/ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -533,13 +533,18 @@ func (n *Constraint) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("UNIQUE KEY")
case ConstraintUniqIndex:
ctx.WriteKeyWord("UNIQUE INDEX")
case ConstraintForeignKey:
ctx.WriteKeyWord("FOREIGN KEY")
case ConstraintFulltext:
ctx.WriteKeyWord("FULLTEXT")
}

if n.Name != "" {
if n.Tp == ConstraintForeignKey {
ctx.WriteKeyWord("CONSTRAINT ")
if n.Name != "" {
ctx.WriteName(n.Name)
ctx.WritePlain(" ")
}
ctx.WriteKeyWord("FOREIGN KEY ")
} else if n.Name != "" {
ctx.WritePlain(" ")
ctx.WriteName(n.Name)
}
Expand Down Expand Up @@ -624,9 +629,6 @@ func (n *ColumnDef) Restore(ctx *RestoreCtx) error {
}
}
for i, options := range n.Options {
if i > 0 {
ctx.WritePlain(",")
}
ctx.WritePlain(" ")
if err := options.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while splicing ColumnDef ColumnOption: [%v]", i)
Expand Down Expand Up @@ -675,7 +677,76 @@ type CreateTableStmt struct {

// Restore implements Node interface.
func (n *CreateTableStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("CREATE TABLE ")
if n.IfNotExists {
ctx.WriteKeyWord("IF NOT EXISTS ")
}

if err := n.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing CreateTableStmt Table")
}
ctx.WritePlain(" ")
if n.ReferTable != nil {
ctx.WriteKeyWord("LIKE ")
if err := n.ReferTable.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing CreateTableStmt ReferTable")
}
}

if lenCols := len(n.Cols); lenCols > 0 {
ctx.WritePlain("(")
for i, col := range n.Cols {
feloxx marked this conversation as resolved.
Show resolved Hide resolved
if i > 0 {
ctx.WritePlain(",")
}
if err := col.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while splicing CreateTableStmt ColumnDef: [%v]", i)
}
}
for i, constraint := range n.Constraints {
if i > 0 || lenCols >= 1 {
ctx.WritePlain(",")
}
if err := constraint.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while splicing CreateTableStmt Constraints: [%v]", i)
}
}
ctx.WritePlain(")")
}

for i, option := range n.Options {
ctx.WritePlain(" ")
if err := option.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while splicing CreateTableStmt TableOption: [%v]", i)
}
}

if n.Partition != nil {
ctx.WritePlain(" ")
if err := n.Partition.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing CreateTableStmt Partition")
}
}

if n.Select != nil {
ctx.WritePlain(" ")

switch n.OnDuplicate {
case OnDuplicateCreateTableSelectError:
// nothing output
case OnDuplicateCreateTableSelectIgnore:
ctx.WriteKeyWord("IGNORE ")
case OnDuplicateCreateTableSelectReplace:
ctx.WriteKeyWord("REPLACE ")
}

ctx.WriteKeyWord("AS ")
feloxx marked this conversation as resolved.
Show resolved Hide resolved
if err := n.Select.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing CreateTableStmt Select")
}
}

return nil
}

// Accept implements Node Accept interface.
Expand Down Expand Up @@ -1349,7 +1420,7 @@ func (n *AlterTableSpec) Restore(ctx *RestoreCtx) error {
ctx.WritePlain(")")
}
case AlterTableAddConstraint:
ctx.WriteKeyWord("ADD CONSTRAINT ")
ctx.WriteKeyWord("ADD ")
if err := n.Constraint.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.Constraint")
}
Expand Down Expand Up @@ -1624,3 +1695,52 @@ type PartitionOptions struct {
Definitions []*PartitionDefinition
Num uint64
}

func (n *PartitionOptions) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("PARTITION BY ")
switch n.Tp {
case model.PartitionTypeRange:
ctx.WriteKeyWord("RANGE ")
case model.PartitionTypeHash:
ctx.WriteKeyWord("HASH ")
case model.PartitionTypeList:
return errors.New("TiDB Parser ignore the `PartitionTypeList` type now")
default:
return errors.Errorf("invalid model.PartitionType: %d", n.Tp)
}

ctx.WritePlain("(")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore PartitionOptions Expr")
}
ctx.WritePlain(") ")

for i, col := range n.ColumnNames {
if i > 0 {
ctx.WritePlain(",")
}
if err := col.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while splicing PartitionOptions ColumnName: [%v]", i)
}
}

if n.Num > 0 {
ctx.WriteKeyWord("PARTITIONS ")
ctx.WritePlainf("%d", n.Num)
}

if len(n.Definitions) > 0 {
ctx.WritePlain("(")
for i, def := range n.Definitions {
if i > 0 {
ctx.WritePlain(",")
}
if err := def.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while splicing PartitionOptions Definitions: [%v]", i)
}
}
ctx.WritePlain(")")
}

return nil
}
31 changes: 17 additions & 14 deletions ast/ddl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,10 @@ func (ts *testDDLSuite) TestDDLConstraintRestore(c *C) {
{"fulltext INDEX full_id (parent_id)", "FULLTEXT `full_id`(`parent_id`)"},
{"PRIMARY KEY (id)", "PRIMARY KEY(`id`)"},
{"PRIMARY KEY (id) key_block_size = 32 using hash comment 'hello'", "PRIMARY KEY(`id`) KEY_BLOCK_SIZE=32 USING HASH COMMENT 'hello'"},
{"FOREIGN KEY (parent_id(2),hello(4)) REFERENCES parent(id) ON DELETE CASCADE", "FOREIGN KEY(`parent_id`(2), `hello`(4)) REFERENCES `parent`(`id`) ON DELETE CASCADE"},
{"FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE ON UPDATE RESTRICT", "FOREIGN KEY(`parent_id`) REFERENCES `parent`(`id`) ON DELETE CASCADE ON UPDATE RESTRICT"},
{"CONSTRAINT FOREIGN KEY (parent_id(2),hello(4)) REFERENCES parent(id) ON DELETE CASCADE", "CONSTRAINT FOREIGN KEY (`parent_id`(2), `hello`(4)) REFERENCES `parent`(`id`) ON DELETE CASCADE"},
{"CONSTRAINT FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE ON UPDATE RESTRICT", "CONSTRAINT FOREIGN KEY (`parent_id`) REFERENCES `parent`(`id`) ON DELETE CASCADE ON UPDATE RESTRICT"},
{"CONSTRAINT fk_123 FOREIGN KEY (parent_id(2),hello(4)) REFERENCES parent(id) ON DELETE CASCADE", "CONSTRAINT `fk_123` FOREIGN KEY (`parent_id`(2), `hello`(4)) REFERENCES `parent`(`id`) ON DELETE CASCADE"},
{"CONSTRAINT fk_123 FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE ON UPDATE RESTRICT", "CONSTRAINT `fk_123` FOREIGN KEY (`parent_id`) REFERENCES `parent`(`id`) ON DELETE CASCADE ON UPDATE RESTRICT"},
}
extractNodeFunc := func(node Node) Node {
return node.(*CreateTableStmt).Constraints[0]
Expand Down Expand Up @@ -329,18 +331,19 @@ func (ts *testDDLSuite) TestAlterTableSpecRestore(c *C) {
{"ADD COLUMN a SMALLINT UNSIGNED FIRST", "ADD COLUMN `a` SMALLINT UNSIGNED FIRST"},
{"ADD COLUMN a SMALLINT UNSIGNED AFTER b", "ADD COLUMN `a` SMALLINT UNSIGNED AFTER `b`"},
{"ADD COLUMN name mediumtext CHARACTER SET UTF8MB4 COLLATE utf8mb4_unicode_ci NOT NULL", "ADD COLUMN `name` MEDIUMTEXT CHARACTER SET UTF8MB4 COLLATE utf8mb4_unicode_ci NOT NULL"},
{"ADD CONSTRAINT INDEX par_ind (parent_id)", "ADD CONSTRAINT INDEX `par_ind`(`parent_id`)"},
{"ADD CONSTRAINT INDEX par_ind (parent_id(6))", "ADD CONSTRAINT INDEX `par_ind`(`parent_id`(6))"},
{"ADD CONSTRAINT key par_ind (parent_id)", "ADD CONSTRAINT INDEX `par_ind`(`parent_id`)"},
{"ADD CONSTRAINT unique par_ind (parent_id)", "ADD CONSTRAINT UNIQUE `par_ind`(`parent_id`)"},
{"ADD CONSTRAINT unique key par_ind (parent_id)", "ADD CONSTRAINT UNIQUE `par_ind`(`parent_id`)"},
{"ADD CONSTRAINT unique index par_ind (parent_id)", "ADD CONSTRAINT UNIQUE `par_ind`(`parent_id`)"},
{"ADD CONSTRAINT fulltext key full_id (parent_id)", "ADD CONSTRAINT FULLTEXT `full_id`(`parent_id`)"},
{"ADD CONSTRAINT fulltext INDEX full_id (parent_id)", "ADD CONSTRAINT FULLTEXT `full_id`(`parent_id`)"},
{"ADD CONSTRAINT PRIMARY KEY (id)", "ADD CONSTRAINT PRIMARY KEY(`id`)"},
{"ADD CONSTRAINT PRIMARY KEY (id) key_block_size = 32 using hash comment 'hello'", "ADD CONSTRAINT PRIMARY KEY(`id`) KEY_BLOCK_SIZE=32 USING HASH COMMENT 'hello'"},
{"ADD CONSTRAINT FOREIGN KEY (parent_id(2),hello(4)) REFERENCES parent(id) ON DELETE CASCADE", "ADD CONSTRAINT FOREIGN KEY(`parent_id`(2), `hello`(4)) REFERENCES `parent`(`id`) ON DELETE CASCADE"},
{"ADD CONSTRAINT FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE ON UPDATE RESTRICT", "ADD CONSTRAINT FOREIGN KEY(`parent_id`) REFERENCES `parent`(`id`) ON DELETE CASCADE ON UPDATE RESTRICT"},
{"ADD CONSTRAINT INDEX par_ind (parent_id)", "ADD INDEX `par_ind`(`parent_id`)"},
{"ADD CONSTRAINT INDEX par_ind (parent_id(6))", "ADD INDEX `par_ind`(`parent_id`(6))"},
{"ADD CONSTRAINT key par_ind (parent_id)", "ADD INDEX `par_ind`(`parent_id`)"},
{"ADD CONSTRAINT unique par_ind (parent_id)", "ADD UNIQUE `par_ind`(`parent_id`)"},
{"ADD CONSTRAINT unique key par_ind (parent_id)", "ADD UNIQUE `par_ind`(`parent_id`)"},
{"ADD CONSTRAINT unique index par_ind (parent_id)", "ADD UNIQUE `par_ind`(`parent_id`)"},
{"ADD CONSTRAINT fulltext key full_id (parent_id)", "ADD FULLTEXT `full_id`(`parent_id`)"},
{"ADD CONSTRAINT fulltext INDEX full_id (parent_id)", "ADD FULLTEXT `full_id`(`parent_id`)"},
{"ADD CONSTRAINT PRIMARY KEY (id)", "ADD PRIMARY KEY(`id`)"},
{"ADD CONSTRAINT PRIMARY KEY (id) key_block_size = 32 using hash comment 'hello'", "ADD PRIMARY KEY(`id`) KEY_BLOCK_SIZE=32 USING HASH COMMENT 'hello'"},
{"ADD CONSTRAINT FOREIGN KEY (parent_id(2),hello(4)) REFERENCES parent(id) ON DELETE CASCADE", "ADD CONSTRAINT FOREIGN KEY (`parent_id`(2), `hello`(4)) REFERENCES `parent`(`id`) ON DELETE CASCADE"},
{"ADD CONSTRAINT FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE ON UPDATE RESTRICT", "ADD CONSTRAINT FOREIGN KEY (`parent_id`) REFERENCES `parent`(`id`) ON DELETE CASCADE ON UPDATE RESTRICT"},
{"ADD CONSTRAINT fk_123 FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE ON UPDATE RESTRICT", "ADD CONSTRAINT `fk_123` FOREIGN KEY (`parent_id`) REFERENCES `parent`(`id`) ON DELETE CASCADE ON UPDATE RESTRICT"},
feloxx marked this conversation as resolved.
Show resolved Hide resolved
{"DROP COLUMN a", "DROP COLUMN `a`"},
{"DROP COLUMN a RESTRICT", "DROP COLUMN `a`"},
{"DROP COLUMN a CASCADE", "DROP COLUMN `a`"},
Expand Down
8 changes: 7 additions & 1 deletion ast/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"github.com/pingcap/parser"
. "github.com/pingcap/parser/ast"
. "github.com/pingcap/parser/format"
driver "github.com/pingcap/tidb/types/parser_driver"
"github.com/pingcap/tidb/types/parser_driver"
)

var _ = Suite(&testCacheableSuite{})
Expand Down Expand Up @@ -66,6 +66,12 @@ type nodeTextCleaner struct {
func (checker *nodeTextCleaner) Enter(in Node) (out Node, skipChildren bool) {
in.SetText("")
switch node := in.(type) {
case *Constraint:
if node.Option != nil {
if node.Option.KeyBlockSize == 0x0 && node.Option.Tp == 0 && node.Option.Comment == "" {
node.Option = nil
}
}
case *FuncCallExpr:
node.FnName.O = strings.ToLower(node.FnName.O)
switch node.FnName.L {
Expand Down
Loading