Skip to content

Commit

Permalink
Fix compatibility for OnUpdate, OnDelete and other clauses (#331, #…
Browse files Browse the repository at this point in the history
  • Loading branch information
tangenta authored Nov 20, 2019
1 parent 7c50186 commit 9dc33a6
Show file tree
Hide file tree
Showing 7 changed files with 7,498 additions and 7,046 deletions.
77 changes: 75 additions & 2 deletions ast/ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,17 @@ func (n *IndexColName) Accept(v Visitor) (Node, bool) {
return v.Leave(n)
}

// MatchType is the type for reference match type.
type MatchType int

// match type
const (
MatchNone MatchType = iota
MatchFull
MatchPartial
MatchSimple
)

// 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 {
Expand All @@ -231,6 +242,7 @@ type ReferenceDef struct {
IndexColNames []*IndexColName
OnDelete *OnDeleteOpt
OnUpdate *OnUpdateOpt
Match MatchType
}

// Restore implements Node interface.
Expand All @@ -251,6 +263,17 @@ func (n *ReferenceDef) Restore(ctx *RestoreCtx) error {
}
}
ctx.WritePlain(")")
if n.Match != MatchNone {
ctx.WriteKeyWord(" MATCH ")
switch n.Match {
case MatchFull:
ctx.WriteKeyWord("FULL")
case MatchPartial:
ctx.WriteKeyWord("PARTIAL")
case MatchSimple:
ctx.WriteKeyWord("SIMPLE")
}
}
if n.OnDelete.ReferOpt != ReferOptionNoOption {
ctx.WritePlain(" ")
if err := n.OnDelete.Restore(ctx); err != nil {
Expand Down Expand Up @@ -308,6 +331,7 @@ const (
ReferOptionCascade
ReferOptionSetNull
ReferOptionNoAction
ReferOptionSetDefault
)

// String implements fmt.Stringer interface.
Expand All @@ -321,6 +345,8 @@ func (r ReferOptionType) String() string {
return "SET NULL"
case ReferOptionNoAction:
return "NO ACTION"
case ReferOptionSetDefault:
return "SET DEFAULT"
}
return ""
}
Expand Down Expand Up @@ -393,6 +419,7 @@ const (
ColumnOptionGenerated
ColumnOptionReference
ColumnOptionCollate
ColumnOptionCheck
)

var (
Expand All @@ -417,6 +444,8 @@ type ColumnOption struct {
// Refer is used for foreign key.
Refer *ReferenceDef
StrValue string
// Enforced is only for Check, default is true.
Enforced bool
}

// Restore implements Node interface.
Expand Down Expand Up @@ -473,6 +502,18 @@ func (n *ColumnOption) Restore(ctx *RestoreCtx) error {
}
ctx.WriteKeyWord("COLLATE ")
ctx.WritePlain(n.StrValue)
case ColumnOptionCheck:
ctx.WriteKeyWord("CHECK")
ctx.WritePlain("(")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Trace(err)
}
ctx.WritePlain(")")
if n.Enforced {
ctx.WriteKeyWord(" ENFORCED")
} else {
ctx.WriteKeyWord(" NOT ENFORCED")
}
default:
return errors.New("An error occurred while splicing ColumnOption")
}
Expand Down Expand Up @@ -562,6 +603,7 @@ const (
ConstraintUniqIndex
ConstraintForeignKey
ConstraintFulltext
ConstraintCheck
)

// Constraint is constraint for table definition.
Expand All @@ -576,6 +618,10 @@ type Constraint struct {
Refer *ReferenceDef // Used for foreign key.

Option *IndexOption // Index Options

Expr ExprNode // Used for Check

Enforced bool // Used for Check
}

// Restore implements Node interface.
Expand All @@ -597,6 +643,24 @@ func (n *Constraint) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("UNIQUE INDEX")
case ConstraintFulltext:
ctx.WriteKeyWord("FULLTEXT")
case ConstraintCheck:
if n.Name != "" {
ctx.WriteKeyWord("CONSTRAINT ")
ctx.WriteName(n.Name)
ctx.WritePlain(" ")
}
ctx.WriteKeyWord("CHECK")
ctx.WritePlain("(")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Trace(err)
}
ctx.WritePlain(") ")
if n.Enforced {
ctx.WriteKeyWord("ENFORCED")
} else {
ctx.WriteKeyWord("NOT ENFORCED")
}
return nil
}

if n.Tp == ConstraintForeignKey {
Expand Down Expand Up @@ -1701,8 +1765,17 @@ func (n *AlterTableSpec) Restore(ctx *RestoreCtx) error {
}
if len(n.NewColumns[0].Options) == 1 {
ctx.WriteKeyWord("SET DEFAULT ")
if err := n.NewColumns[0].Options[0].Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.NewColumns[0].Options[0].Expr")
expr := n.NewColumns[0].Options[0].Expr
if valueExpr, ok := expr.(ValueExpr); ok {
if err := valueExpr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.NewColumns[0].Options[0].Expr")
}
} else {
ctx.WritePlain("(")
if err := expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.NewColumns[0].Options[0].Expr")
}
ctx.WritePlain(")")
}
} else {
ctx.WriteKeyWord(" DROP DEFAULT")
Expand Down
4 changes: 4 additions & 0 deletions ast/ddl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ func (ts *testDDLSuite) TestDDLOnDeleteRestore(c *C) {
return node.(*CreateTableStmt).Constraints[1].Refer.OnDelete
}
RunNodeRestoreTest(c, testCases, "CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) %s)", extractNodeFunc)
RunNodeRestoreTest(c, testCases, "CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) on update CASCADE %s)", extractNodeFunc)
RunNodeRestoreTest(c, testCases, "CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) %s on update CASCADE)", extractNodeFunc)
}

func (ts *testDDLSuite) TestDDLOnUpdateRestore(c *C) {
Expand All @@ -100,6 +102,8 @@ func (ts *testDDLSuite) TestDDLOnUpdateRestore(c *C) {
return node.(*CreateTableStmt).Constraints[1].Refer.OnUpdate
}
RunNodeRestoreTest(c, testCases, "CREATE TABLE child ( id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE %s )", extractNodeFunc)
RunNodeRestoreTest(c, testCases, "CREATE TABLE child ( id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) %s ON DELETE CASCADE)", extractNodeFunc)
RunNodeRestoreTest(c, testCases, "CREATE TABLE child ( id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) %s )", extractNodeFunc)
}

func (ts *testDDLSuite) TestDDLIndexOption(c *C) {
Expand Down
4 changes: 4 additions & 0 deletions misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ var tokenMap = map[string]int{
"ENABLE": enable,
"ENCLOSED": enclosed,
"END": end,
"ENFORCED": enforced,
"ENGINE": engine,
"ENGINES": engines,
"ENUM": enum,
Expand Down Expand Up @@ -351,6 +352,7 @@ var tokenMap = map[string]int{
"LONGTEXT": longtextType,
"LOW_PRIORITY": lowPriority,
"MASTER": master,
"MATCH": match,
"MAX": max,
"MAX_CONNECTIONS_PER_HOUR": maxConnectionsPerHour,
"MAX_EXECUTION_TIME": maxExecutionTime,
Expand Down Expand Up @@ -402,6 +404,7 @@ var tokenMap = map[string]int{
"OUTER": outer,
"PACK_KEYS": packKeys,
"PAGE": pageSym,
"PARTIAL": partial,
"PARTITION": partition,
"PARTITIONS": partitions,
"PASSWORD": password,
Expand Down Expand Up @@ -467,6 +470,7 @@ var tokenMap = map[string]int{
"SHARED": shared,
"SHOW": show,
"SIGNED": signed,
"SIMPLE": simple,
"SLAVE": slave,
"SLOW": slow,
"SMALLINT": smallIntType,
Expand Down
Loading

0 comments on commit 9dc33a6

Please sign in to comment.