Skip to content

Commit 404ca81

Browse files
authored
Merge pull request #18 from openark/enum-to-varchar
Convering enum to varchar
2 parents 33516f4 + 82bdf06 commit 404ca81

File tree

7 files changed

+81
-5
lines changed

7 files changed

+81
-5
lines changed

go/logic/inspect.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,10 @@ func (this *Inspector) inspectOriginalAndGhostTables() (err error) {
187187
if column.Name == mappedColumn.Name && column.Type == sql.DateTimeColumnType && mappedColumn.Type == sql.TimestampColumnType {
188188
this.migrationContext.MappedSharedColumns.SetConvertDatetimeToTimestamp(column.Name, this.migrationContext.ApplierTimeZone)
189189
}
190+
if column.Name == mappedColumn.Name && column.Type == sql.EnumColumnType && mappedColumn.Charset != "" {
191+
this.migrationContext.MappedSharedColumns.SetEnumToTextConversion(column.Name)
192+
this.migrationContext.MappedSharedColumns.SetEnumValues(column.Name, column.EnumValues)
193+
}
190194
}
191195

192196
for _, column := range this.migrationContext.UniqueKey.Columns.Columns() {
@@ -589,6 +593,7 @@ func (this *Inspector) applyColumnTypes(databaseName, tableName string, columnsL
589593
}
590594
if strings.HasPrefix(columnType, "enum") {
591595
column.Type = sql.EnumColumnType
596+
column.EnumValues = sql.ParseEnumValues(m.GetString("COLUMN_TYPE"))
592597
}
593598
if charset := m.GetString("CHARACTER_SET_NAME"); charset != "" {
594599
column.Charset = charset

go/sql/builder.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ func buildColumnsPreparedValues(columns *ColumnList) []string {
3838
var token string
3939
if column.timezoneConversion != nil {
4040
token = fmt.Sprintf("convert_tz(?, '%s', '%s')", column.timezoneConversion.ToTimezone, "+00:00")
41+
} else if column.enumToTextConversion {
42+
token = fmt.Sprintf("ELT(?, %s)", column.EnumValues)
4143
} else if column.Type == JSONColumnType {
4244
token = "convert(? using utf8mb4)"
4345
} else {
@@ -108,6 +110,8 @@ func BuildSetPreparedClause(columns *ColumnList) (result string, err error) {
108110
var setToken string
109111
if column.timezoneConversion != nil {
110112
setToken = fmt.Sprintf("%s=convert_tz(?, '%s', '%s')", EscapeName(column.Name), column.timezoneConversion.ToTimezone, "+00:00")
113+
} else if column.enumToTextConversion {
114+
setToken = fmt.Sprintf("%s=ELT(?, %s)", EscapeName(column.Name), column.EnumValues)
111115
} else if column.Type == JSONColumnType {
112116
setToken = fmt.Sprintf("%s=convert(? using utf8mb4)", EscapeName(column.Name))
113117
} else {

go/sql/parser.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ var (
3333
// ALTER TABLE tbl something
3434
regexp.MustCompile(`(?i)\balter\s+table\s+([\S]+)\s+(.*$)`),
3535
}
36+
enumValuesRegexp = regexp.MustCompile("^enum[(](.*)[)]$")
3637
)
3738

3839
type AlterTableParser struct {
@@ -205,3 +206,10 @@ func (this *AlterTableParser) HasExplicitTable() bool {
205206
func (this *AlterTableParser) GetAlterStatementOptions() string {
206207
return this.alterStatementOptions
207208
}
209+
210+
func ParseEnumValues(enumColumnType string) string {
211+
if submatch := enumValuesRegexp.FindStringSubmatch(enumColumnType); len(submatch) > 0 {
212+
return submatch[1]
213+
}
214+
return enumColumnType
215+
}

go/sql/parser_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,3 +322,21 @@ func TestParseAlterStatementExplicitTable(t *testing.T) {
322322
test.S(t).ExpectTrue(reflect.DeepEqual(parser.alterTokens, []string{"drop column b", "add index idx(i)"}))
323323
}
324324
}
325+
326+
func TestParseEnumValues(t *testing.T) {
327+
{
328+
s := "enum('red','green','blue','orange')"
329+
values := ParseEnumValues(s)
330+
test.S(t).ExpectEquals(values, "'red','green','blue','orange'")
331+
}
332+
{
333+
s := "('red','green','blue','orange')"
334+
values := ParseEnumValues(s)
335+
test.S(t).ExpectEquals(values, "('red','green','blue','orange')")
336+
}
337+
{
338+
s := "zzz"
339+
values := ParseEnumValues(s)
340+
test.S(t).ExpectEquals(values, "zzz")
341+
}
342+
}

go/sql/types.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ type TimezoneConversion struct {
3131
}
3232

3333
type Column struct {
34-
Name string
35-
IsUnsigned bool
36-
Charset string
37-
Type ColumnType
38-
timezoneConversion *TimezoneConversion
34+
Name string
35+
IsUnsigned bool
36+
Charset string
37+
Type ColumnType
38+
EnumValues string
39+
timezoneConversion *TimezoneConversion
40+
enumToTextConversion bool
3941
}
4042

4143
func (this *Column) convertArg(arg interface{}) interface{} {
@@ -179,6 +181,18 @@ func (this *ColumnList) HasTimezoneConversion(columnName string) bool {
179181
return this.GetColumn(columnName).timezoneConversion != nil
180182
}
181183

184+
func (this *ColumnList) SetEnumToTextConversion(columnName string) {
185+
this.GetColumn(columnName).enumToTextConversion = true
186+
}
187+
188+
func (this *ColumnList) IsEnumToTextConversion(columnName string) bool {
189+
return this.GetColumn(columnName).enumToTextConversion
190+
}
191+
192+
func (this *ColumnList) SetEnumValues(columnName string, enumValues string) {
193+
this.GetColumn(columnName).EnumValues = enumValues
194+
}
195+
182196
func (this *ColumnList) String() string {
183197
return strings.Join(this.Names(), ",")
184198
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
drop table if exists gh_ost_test;
2+
create table gh_ost_test (
3+
id int auto_increment,
4+
i int not null,
5+
e enum('red', 'green', 'blue', 'orange') null default null collate 'utf8_bin',
6+
primary key(id)
7+
) auto_increment=1;
8+
9+
insert into gh_ost_test values (null, 7, 'red');
10+
11+
drop event if exists gh_ost_test;
12+
delimiter ;;
13+
create event gh_ost_test
14+
on schedule every 1 second
15+
starts current_timestamp
16+
ends current_timestamp + interval 60 second
17+
on completion not preserve
18+
enable
19+
do
20+
begin
21+
insert into gh_ost_test values (null, 11, 'red');
22+
insert into gh_ost_test values (null, 13, 'green');
23+
insert into gh_ost_test values (null, 17, 'blue');
24+
set @last_insert_id := last_insert_id();
25+
update gh_ost_test set e='orange' where id = @last_insert_id;
26+
end ;;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--alter="change e e varchar(32) not null default ''"

0 commit comments

Comments
 (0)