Skip to content

Commit f00a584

Browse files
authored
ddl: check index key length when convert charset (#56964) (#57441)
close #56930
1 parent a276364 commit f00a584

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

ddl/ddl_api.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6041,6 +6041,10 @@ func checkAlterTableCharset(tblInfo *model.TableInfo, dbInfo *model.DBInfo, toCh
60416041
return doNothing, nil
60426042
}
60436043

6044+
if err = checkIndexLengthWithNewCharset(tblInfo, toCharset, toCollate); err != nil {
6045+
return doNothing, err
6046+
}
6047+
60446048
for _, col := range tblInfo.Columns {
60456049
if col.GetType() == mysql.TypeVarchar {
60466050
if err = types.IsVarcharTooBigFieldLength(col.GetFlen(), col.Name.O, toCharset); err != nil {
@@ -6064,6 +6068,30 @@ func checkAlterTableCharset(tblInfo *model.TableInfo, dbInfo *model.DBInfo, toCh
60646068
return doNothing, nil
60656069
}
60666070

6071+
func checkIndexLengthWithNewCharset(tblInfo *model.TableInfo, toCharset, toCollate string) error {
6072+
// Copy all columns and replace the charset and collate.
6073+
columns := make([]*model.ColumnInfo, 0, len(tblInfo.Columns))
6074+
for _, col := range tblInfo.Columns {
6075+
newCol := col.Clone()
6076+
if field_types.HasCharset(&newCol.FieldType) {
6077+
newCol.SetCharset(toCharset)
6078+
newCol.SetCollate(toCollate)
6079+
} else {
6080+
newCol.SetCharset(charset.CharsetBin)
6081+
newCol.SetCollate(charset.CharsetBin)
6082+
}
6083+
columns = append(columns, newCol)
6084+
}
6085+
6086+
for _, indexInfo := range tblInfo.Indices {
6087+
err := checkIndexPrefixLength(columns, indexInfo.Columns)
6088+
if err != nil {
6089+
return err
6090+
}
6091+
}
6092+
return nil
6093+
}
6094+
60676095
// RenameIndex renames an index.
60686096
// In TiDB, indexes are case-insensitive (so index 'a' and 'A" are considered the same index),
60696097
// but index names are case-sensitive (we can rename index 'a' to 'A')

ddl/ddl_api_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,3 +267,15 @@ func TestCreateDropCreateTable(t *testing.T) {
267267
require.Less(t, create0TS, dropTS, "first create should finish before drop")
268268
require.Less(t, dropTS, create1TS, "second create should finish after drop")
269269
}
270+
271+
func TestFix56930(t *testing.T) {
272+
store := testkit.CreateMockStore(t)
273+
tk := testkit.NewTestKit(t, store)
274+
tk.MustExec("use test")
275+
tk.MustExec("drop table if exists t; create table posts (id int auto_increment primary key, title varchar(500) character set utf8, subtitle varchar(500) character set utf8, unique key(title, subtitle));")
276+
tk.MustGetErrMsg("alter table posts convert to character set utf8mb4;", "[ddl:1071]Specified key was too long (4000 bytes); max key length is 3072 bytes")
277+
tk.MustExec("drop table if exists t; create table t(a varchar(1000) character set utf8, primary key(a));")
278+
tk.MustGetErrMsg("alter table t convert to character set utf8mb4;", "[ddl:1071]Specified key was too long (4000 bytes); max key length is 3072 bytes")
279+
tk.MustExec("drop table if exists t; create table t(a varchar(1000) character set utf8, key(a));")
280+
tk.MustGetErrMsg("alter table t convert to character set utf8mb4;", "[ddl:1071]Specified key was too long (4000 bytes); max key length is 3072 bytes")
281+
}

0 commit comments

Comments
 (0)