Skip to content

Commit a947cc8

Browse files
authored
Support revert old column attributes (#58)
Support revert old column attributes
1 parent c1bffc9 commit a947cc8

File tree

10 files changed

+138
-71
lines changed

10 files changed

+138
-71
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,8 @@ CREATE TABLE user (
237237
//CREATE UNIQUE INDEX `idx_name_age` ON `user`(`name`, `age`);
238238

239239
println(sql1.StringDown())
240+
//ALTER TABLE `user` MODIFY COLUMN `id` int(11);
241+
//ALTER TABLE `user` MODIFY COLUMN `updated_at` datetime;
240242
//DROP INDEX `idx_name_age` ON `user`;
241243
}
242244
```

README_zh.md

+6-4
Original file line numberDiff line numberDiff line change
@@ -232,11 +232,13 @@ CREATE TABLE user (
232232

233233
sql1.Diff(*sql2)
234234
println(sql1.StringUp())
235-
// ALTER TABLE `user` MODIFY COLUMN `id` int(11) AUTO_INCREMENT PRIMARY KEY;
236-
// ALTER TABLE `user` MODIFY COLUMN `updated_at` datetime DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP();
237-
// CREATE UNIQUE INDEX `idx_name_age` ON `user`(`name`, `age`);
235+
//ALTER TABLE `user` MODIFY COLUMN `id` int(11) AUTO_INCREMENT PRIMARY KEY;
236+
//ALTER TABLE `user` MODIFY COLUMN `updated_at` datetime DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP();
237+
//CREATE UNIQUE INDEX `idx_name_age` ON `user`(`name`, `age`);
238238

239239
println(sql1.StringDown())
240-
// DROP INDEX `idx_name_age` ON `user`;
240+
//ALTER TABLE `user` MODIFY COLUMN `id` int(11);
241+
//ALTER TABLE `user` MODIFY COLUMN `updated_at` datetime;
242+
//DROP INDEX `idx_name_age` ON `user`;
241243
}
242244
```

avro/builder.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,19 @@ func getAvroType(col element.Column) interface{} {
5959
"type": "string",
6060
"connect.version": 1,
6161
"connect.parameters": map[string]string{
62-
"allowed": strings.Join(col.MysqlType.Elems, ","),
62+
"allowed": strings.Join(col.CurrentAttr.MysqlType.Elems, ","),
6363
},
6464
"connect.default": "init",
6565
"connect.name": "io.debezium.data.Enum",
6666
}
6767
}
6868

69-
switch col.MysqlType.EvalType() {
69+
switch col.CurrentAttr.MysqlType.EvalType() {
7070
case types.ETInt:
7171
return "int"
7272

7373
case types.ETDecimal:
74-
displayFlen, displayDecimal := col.MysqlType.Flen, col.MysqlType.Decimal
74+
displayFlen, displayDecimal := col.CurrentAttr.MysqlType.Flen, col.CurrentAttr.MysqlType.Decimal
7575
return map[string]interface{}{
7676
"type": "bytes",
7777
"scale": displayDecimal,

element/column.go

+65-23
Original file line numberDiff line numberDiff line change
@@ -22,28 +22,34 @@ const (
2222
LowerRestoreFlag = format.RestoreStringSingleQuotes | format.RestoreKeyWordLowercase | format.RestoreNameLowercase | format.RestoreNameBackQuotes
2323
)
2424

25-
// Column ...
26-
type Column struct {
27-
Node
25+
type SqlAttr struct {
2826
MysqlType *types.FieldType
2927
PgType *ptypes.T
3028
LiteType *sqlite.Type
3129
Options []*ast.ColumnOption
3230
Comment string
3331
}
3432

33+
// Column ...
34+
type Column struct {
35+
Node
36+
37+
CurrentAttr SqlAttr
38+
PreviousAttr SqlAttr
39+
}
40+
3541
// GetType ...
3642
func (c Column) GetType() byte {
37-
if c.MysqlType != nil {
38-
return c.MysqlType.Tp
43+
if c.CurrentAttr.MysqlType != nil {
44+
return c.CurrentAttr.MysqlType.Tp
3945
}
4046

4147
return 0
4248
}
4349

4450
// HasDefaultValue ...
4551
func (c Column) HasDefaultValue() bool {
46-
for _, opt := range c.Options {
52+
for _, opt := range c.CurrentAttr.Options {
4753
if opt.Tp == ast.ColumnOptionDefaultValue {
4854
return true
4955
}
@@ -54,7 +60,7 @@ func (c Column) HasDefaultValue() bool {
5460

5561
func (c Column) hashValue() string {
5662
strHash := sql.EscapeSqlName(c.Name)
57-
strHash += c.typeDefinition()
63+
strHash += c.typeDefinition(false)
5864
hash := md5.Sum([]byte(strHash))
5965
return hex.EncodeToString(hash[:])
6066
}
@@ -71,7 +77,7 @@ func (c Column) migrationUp(tbName, after string, ident int) []string {
7177
strSql += strings.Repeat(" ", ident-len(c.Name))
7278
}
7379

74-
strSql += c.definition()
80+
strSql += c.definition(false)
7581

7682
if ident < 0 {
7783
if after != "" {
@@ -90,10 +96,27 @@ func (c Column) migrationUp(tbName, after string, ident int) []string {
9096
return []string{fmt.Sprintf(sql.AlterTableDropColumnStm(), sql.EscapeSqlName(tbName), sql.EscapeSqlName(c.Name))}
9197

9298
case MigrateModifyAction:
93-
def := strings.Replace(c.definition(), sql.PrimaryOption(), "", 1)
99+
def, isPk := c.pkDefinition(false)
100+
if isPk {
101+
if _, isPrevPk := c.pkDefinition(true); isPrevPk {
102+
// avoid repeat define primary key
103+
def = strings.Replace(def, " "+sql.PrimaryOption(), "", 1)
104+
}
105+
}
94106

95107
return []string{fmt.Sprintf(sql.AlterTableModifyColumnStm(), sql.EscapeSqlName(tbName), sql.EscapeSqlName(c.Name)+def)}
96108

109+
case MigrateRevertAction:
110+
prevDef, isPrevPk := c.pkDefinition(true)
111+
if isPrevPk {
112+
if _, isPk := c.pkDefinition(false); isPk {
113+
// avoid repeat define primary key
114+
prevDef = strings.Replace(prevDef, " "+sql.PrimaryOption(), "", 1)
115+
}
116+
}
117+
118+
return []string{fmt.Sprintf(sql.AlterTableModifyColumnStm(), sql.EscapeSqlName(tbName), sql.EscapeSqlName(c.Name)+prevDef)}
119+
97120
case MigrateRenameAction:
98121
return []string{fmt.Sprintf(sql.AlterTableRenameColumnStm(), sql.EscapeSqlName(tbName), sql.EscapeSqlName(c.OldName), sql.EscapeSqlName(c.Name))}
99122

@@ -103,12 +126,12 @@ func (c Column) migrationUp(tbName, after string, ident int) []string {
103126
}
104127

105128
func (c Column) migrationCommentUp(tbName string) []string {
106-
if c.Comment == "" || sql.GetDialect() != sql_templates.PostgresDialect {
129+
if c.CurrentAttr.Comment == "" || sql.GetDialect() != sql_templates.PostgresDialect {
107130
return nil
108131
}
109132

110133
// apply for postgres only
111-
return []string{fmt.Sprintf(sql.ColumnComment(), tbName, c.Name, c.Comment)}
134+
return []string{fmt.Sprintf(sql.ColumnComment(), tbName, c.Name, c.CurrentAttr.Comment)}
112135
}
113136

114137
func (c Column) migrationDown(tbName, after string) []string {
@@ -123,7 +146,7 @@ func (c Column) migrationDown(tbName, after string) []string {
123146
c.Action = MigrateAddAction
124147

125148
case MigrateModifyAction:
126-
return nil
149+
c.Action = MigrateRevertAction
127150

128151
case MigrateRenameAction:
129152
c.Name, c.OldName = c.OldName, c.Name
@@ -135,10 +158,19 @@ func (c Column) migrationDown(tbName, after string) []string {
135158
return c.migrationUp(tbName, after, -1)
136159
}
137160

138-
func (c Column) definition() string {
139-
strSql := c.typeDefinition()
161+
func (c Column) pkDefinition(isPrev bool) (string, bool) {
162+
attr := c.CurrentAttr
163+
if isPrev {
164+
attr = c.PreviousAttr
165+
}
166+
strSql := c.typeDefinition(isPrev)
167+
168+
isPrimaryKey := false
169+
for _, opt := range attr.Options {
170+
if opt.Tp == ast.ColumnOptionPrimaryKey {
171+
isPrimaryKey = true
172+
}
140173

141-
for _, opt := range c.Options {
142174
b := bytes.NewBufferString("")
143175
var ctx *format.RestoreCtx
144176

@@ -157,17 +189,27 @@ func (c Column) definition() string {
157189
strSql += " " + b.String()
158190
}
159191

160-
return strSql
192+
return strSql, isPrimaryKey
193+
}
194+
195+
func (c Column) definition(isPrev bool) string {
196+
def, _ := c.pkDefinition(isPrev)
197+
return def
161198
}
162199

163-
func (c Column) typeDefinition() string {
200+
func (c Column) typeDefinition(isPrev bool) string {
201+
attr := c.CurrentAttr
202+
if isPrev {
203+
attr = c.PreviousAttr
204+
}
205+
164206
switch {
165-
case sql.IsPostgres() && c.PgType != nil:
166-
return " " + c.PgType.SQLString()
167-
case sql.IsSqlite() && c.LiteType != nil:
168-
return " " + c.LiteType.Name.Name
169-
case c.MysqlType != nil:
170-
return " " + c.MysqlType.String()
207+
case sql.IsPostgres() && attr.PgType != nil:
208+
return " " + attr.PgType.SQLString()
209+
case sql.IsSqlite() && attr.LiteType != nil:
210+
return " " + attr.LiteType.Name.Name
211+
case attr.MysqlType != nil:
212+
return " " + attr.MysqlType.String()
171213
}
172214

173215
return "" // column type is empty

element/migration.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ func (m *Migration) AddComment(tbName, colName, comment string) {
150150
return
151151
}
152152

153-
m.Tables[id].Columns[colIdx].Comment = comment
153+
m.Tables[id].Columns[colIdx].CurrentAttr.Comment = comment
154154
}
155155

156156
// AddIndex ...

element/node.go

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ const (
1212
MigrateRemoveAction
1313
// MigrateModifyAction ...
1414
MigrateModifyAction
15+
// MigrateRevertAction ...
16+
MigrateRevertAction
1517
// MigrateRenameAction ...
1618
MigrateRenameAction
1719
)

element/table.go

+10-9
Original file line numberDiff line numberDiff line change
@@ -62,18 +62,18 @@ func (t *Table) AddColumn(col Column) {
6262
t.Columns[id] = col
6363

6464
default:
65-
t.Columns[id].Options = append(t.Columns[id].Options, col.Options...)
65+
t.Columns[id].CurrentAttr.Options = append(t.Columns[id].CurrentAttr.Options, col.CurrentAttr.Options...)
6666

67-
if size := len(t.Columns[id].Options); size > 0 {
68-
for i := range t.Columns[id].Options[:size-1] {
69-
if t.Columns[id].Options[i].Tp == ast.ColumnOptionPrimaryKey {
70-
t.Columns[id].Options[i], t.Columns[id].Options[size-1] = t.Columns[id].Options[size-1], t.Columns[id].Options[i]
67+
if size := len(t.Columns[id].CurrentAttr.Options); size > 0 {
68+
for i := range t.Columns[id].CurrentAttr.Options[:size-1] {
69+
if t.Columns[id].CurrentAttr.Options[i].Tp == ast.ColumnOptionPrimaryKey {
70+
t.Columns[id].CurrentAttr.Options[i], t.Columns[id].CurrentAttr.Options[size-1] = t.Columns[id].CurrentAttr.Options[size-1], t.Columns[id].CurrentAttr.Options[i]
7171
break
7272
}
7373
}
7474
}
7575

76-
t.Columns[id].MysqlType = col.MysqlType
76+
t.Columns[id].CurrentAttr.MysqlType = col.CurrentAttr.MysqlType
7777
return
7878
}
7979

@@ -291,10 +291,11 @@ func (t *Table) Diff(old Table) {
291291
for i := range t.Columns {
292292
if j := old.getIndexColumn(t.Columns[i].Name); t.Columns[i].Action == MigrateAddAction &&
293293
j >= 0 && old.Columns[j].Action != MigrateNoAction {
294-
if hasChangedMysqlOptions(t.Columns[i].Options, old.Columns[j].Options) ||
295-
hasChangedMysqlType(t.Columns[i].MysqlType, old.Columns[j].MysqlType) ||
296-
hasChangePostgresType(t.Columns[i].PgType, old.Columns[j].PgType) {
294+
if hasChangedMysqlOptions(t.Columns[i].CurrentAttr.Options, old.Columns[j].CurrentAttr.Options) ||
295+
hasChangedMysqlType(t.Columns[i].CurrentAttr.MysqlType, old.Columns[j].CurrentAttr.MysqlType) ||
296+
hasChangePostgresType(t.Columns[i].CurrentAttr.PgType, old.Columns[j].CurrentAttr.PgType) {
297297
t.Columns[i].Action = MigrateModifyAction
298+
t.Columns[i].PreviousAttr = old.Columns[j].CurrentAttr
298299
} else {
299300
t.Columns[i].Action = MigrateNoAction
300301
}

sql-parser/mysql.go

+25-17
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,13 @@ func (p *Parser) Enter(in ast.Node) (ast.Node, bool) {
7373
})
7474
} else {
7575
p.Migration.AddColumn(alter.Table.Text(), element.Column{
76-
Node: element.Node{Name: cols[0], Action: element.MigrateAddAction},
77-
MysqlType: nil,
78-
Options: []*ast.ColumnOption{
79-
{
80-
Tp: ast.ColumnOptionPrimaryKey,
76+
Node: element.Node{Name: cols[0], Action: element.MigrateAddAction},
77+
CurrentAttr: element.SqlAttr{
78+
MysqlType: nil,
79+
Options: []*ast.ColumnOption{
80+
{
81+
Tp: ast.ColumnOptionPrimaryKey,
82+
},
8183
},
8284
},
8385
})
@@ -113,9 +115,11 @@ func (p *Parser) Enter(in ast.Node) (ast.Node, bool) {
113115
if len(alter.Specs[i].NewColumns) > 0 {
114116
for j := range alter.Specs[i].NewColumns {
115117
col := element.Column{
116-
Node: element.Node{Name: alter.Specs[i].NewColumns[j].Name.Name.O, Action: element.MigrateModifyAction},
117-
MysqlType: alter.Specs[i].NewColumns[j].Tp,
118-
Comment: alter.Specs[i].Comment,
118+
Node: element.Node{Name: alter.Specs[i].NewColumns[j].Name.Name.O, Action: element.MigrateModifyAction},
119+
CurrentAttr: element.SqlAttr{
120+
MysqlType: alter.Specs[i].NewColumns[j].Tp,
121+
Comment: alter.Specs[i].Comment,
122+
},
119123
}
120124
p.Migration.AddColumn(alter.Table.Name.O, col)
121125
}
@@ -161,11 +165,13 @@ func (p *Parser) Enter(in ast.Node) (ast.Node, bool) {
161165
})
162166
} else {
163167
tb.AddColumn(element.Column{
164-
Node: element.Node{Name: cols[0], Action: element.MigrateAddAction},
165-
MysqlType: nil,
166-
Options: []*ast.ColumnOption{
167-
{
168-
Tp: ast.ColumnOptionPrimaryKey,
168+
Node: element.Node{Name: cols[0], Action: element.MigrateAddAction},
169+
CurrentAttr: element.SqlAttr{
170+
MysqlType: nil,
171+
Options: []*ast.ColumnOption{
172+
{
173+
Tp: ast.ColumnOptionPrimaryKey,
174+
},
169175
},
170176
},
171177
})
@@ -218,10 +224,12 @@ func (p *Parser) Enter(in ast.Node) (ast.Node, bool) {
218224
}
219225

220226
column := element.Column{
221-
Node: element.Node{Name: def.Name.Name.O, Action: element.MigrateAddAction},
222-
MysqlType: def.Tp,
223-
Options: def.Options,
224-
Comment: comment,
227+
Node: element.Node{Name: def.Name.Name.O, Action: element.MigrateAddAction},
228+
CurrentAttr: element.SqlAttr{
229+
MysqlType: def.Tp,
230+
Options: def.Options,
231+
Comment: comment,
232+
},
225233
}
226234
p.Migration.AddColumn("", column)
227235
}

sql-parser/postgresql.go

+16-10
Original file line numberDiff line numberDiff line change
@@ -92,20 +92,24 @@ func (p *Parser) walker(ctx interface{}, node interface{}) (stop bool) {
9292

9393
case *tree.AlterTableAlterColumnType:
9494
col := element.Column{
95-
Node: element.Node{Name: nc.Column.String(), Action: element.MigrateModifyAction},
96-
PgType: nc.ToType,
95+
Node: element.Node{Name: nc.Column.String(), Action: element.MigrateModifyAction},
96+
CurrentAttr: element.SqlAttr{
97+
PgType: nc.ToType,
98+
},
9799
}
98100
p.Migration.AddColumn(n.Table.String(), col)
99101

100102
case *tree.AlterTableSetDefault:
101103
if nc.Default != nil {
102104
col := element.Column{
103105
Node: element.Node{Name: nc.Column.String(), Action: element.MigrateModifyAction},
104-
Options: []*ast.ColumnOption{{
105-
Expr: nil,
106-
Tp: ast.ColumnOptionDefaultValue,
107-
StrValue: nc.Default.String(),
108-
}},
106+
CurrentAttr: element.SqlAttr{
107+
Options: []*ast.ColumnOption{{
108+
Expr: nil,
109+
Tp: ast.ColumnOptionDefaultValue,
110+
StrValue: nc.Default.String(),
111+
}},
112+
},
109113
}
110114
p.Migration.AddColumn(n.Table.String(), col)
111115
}
@@ -166,9 +170,11 @@ func postgresColumn(n *tree.ColumnTableDef) (element.Column, []element.Index) {
166170
}
167171

168172
return element.Column{
169-
Node: element.Node{Name: n.Name.String(), Action: element.MigrateAddAction},
170-
PgType: n.Type,
171-
Options: opts,
173+
Node: element.Node{Name: n.Name.String(), Action: element.MigrateAddAction},
174+
CurrentAttr: element.SqlAttr{
175+
PgType: n.Type,
176+
Options: opts,
177+
},
172178
}, indexes
173179
}
174180

0 commit comments

Comments
 (0)