Skip to content

Commit

Permalink
ddl: restricting altering the utf8 charset to utf8mb4 (#9107)
Browse files Browse the repository at this point in the history
  • Loading branch information
ciscoxll authored Jan 22, 2019
1 parent 63936cc commit cfb6311
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 20 deletions.
57 changes: 42 additions & 15 deletions ddl/db_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -527,24 +527,47 @@ func (s *testIntegrationSuite) TestNullGeneratedColumn(c *C) {
func (s *testIntegrationSuite) TestChangingCharsetToUtf8(c *C) {
tk := testkit.NewTestKit(c, s.store)

tk.MustExec("USE test")
tk.MustExec("create table t(a char(10) charset latin1)")
tk.MustExec("alter table t modify column a char(10) charset latin1")
tk.MustExec("alter table t modify column a char(10) charset utf8")
tk.MustExec("alter table t modify column a char(10) charset utf8mb4")
rs, err := tk.Exec("alter table t modify column a char(10) charset utf8mb4 collate utf8bin")
tk.MustExec("use test")
tk.MustExec("create table t1(a varchar(20) charset utf8)")
tk.MustExec("insert into t1 values (?)", "t1_value")

tk.MustExec("alter table t1 modify column a varchar(20) charset utf8mb4")
tk.MustQuery("select * from t1;").Check(testkit.Rows("t1_value"))

tk.MustExec("create table t(a varchar(20) charset latin1)")
tk.MustExec("insert into t values (?)", "t_value")

tk.MustExec("alter table t modify column a varchar(20) charset latin1")
tk.MustQuery("select * from t;").Check(testkit.Rows("t_value"))

rs, err := tk.Exec("alter table t modify column a varchar(20) charset utf8")
if rs != nil {
rs.Close()
}
c.Assert(err, NotNil)
tk.MustExec("alter table t modify column a char(10) charset utf8mb4 collate utf8mb4_bin")
rs, err = tk.Exec("alter table t modify column a char(10) charset utf8 collate utf8_bin")
c.Assert(err.Error(), Equals, "[ddl:210]unsupported modify charset from latin1 to utf8")
rs, err = tk.Exec("alter table t modify column a varchar(20) charset utf8mb4")
if rs != nil {
rs.Close()
}
c.Assert(err, NotNil)
c.Assert(err.Error(), Equals, "[ddl:210]unsupported modify charset from latin1 to utf8mb4")

rs, err = tk.Exec("alter table t modify column a varchar(20) charset utf8mb4 collate utf8bin")
if rs != nil {
rs.Close()
}
c.Assert(err, NotNil)
rs, err = tk.Exec("alter table t modify column a varchar(20) charset utf8 collate utf8_bin")
if rs != nil {
rs.Close()
}
c.Assert(err, NotNil)
rs, err = tk.Exec("alter table t modify column a varchar(20) charset utf8mb4 collate utf8mb4_general_ci")
if rs != nil {
rs.Close()
}
c.Assert(err, NotNil)
tk.MustExec("alter table t modify column a char(10) charset utf8mb4 collate utf8mb4_general_ci")
}

func (s *testIntegrationSuite) TestChangingTableCharset(c *C) {
Expand All @@ -557,20 +580,24 @@ func (s *testIntegrationSuite) TestChangingTableCharset(c *C) {
rs.Close()
}
c.Assert(err.Error(), Equals, "Unknown charset gbk")
tk.MustExec("alter table t charset utf8")
tk.MustExec("alter table t charset utf8 collate utf8_bin")
rs, err = tk.Exec("alter table t charset utf8")
if rs != nil {
rs.Close()
}
c.Assert(err.Error(), Equals, "[ddl:210]unsupported modify charset from latin1 to utf8")

rs, err = tk.Exec("alter table t charset utf8 collate latin1_bin")
if rs != nil {
rs.Close()
}
c.Assert(err, NotNil)
tk.MustExec("alter table t charset utf8mb4")
tk.MustExec("alter table t charset utf8mb4 collate utf8mb4_bin")

rs, err = tk.Exec("alter table t charset utf8 collate utf8_bin")
rs, err = tk.Exec("alter table t charset utf8mb4")
if rs != nil {
rs.Close()
}
c.Assert(err.Error(), Equals, "[ddl:210]unsupported modify charset from latin1 to utf8mb4")

rs, err = tk.Exec("alter table t charset utf8mb4 collate utf8mb4_bin")
c.Assert(err, NotNil)
}

Expand Down
22 changes: 21 additions & 1 deletion ddl/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2051,7 +2051,7 @@ func (s *testDBSuite) TestCheckTooBigFieldLength(c *C) {
s.tk.MustExec("create table tr_03 (id int, name varchar(65534), purchased date ) default charset=latin1;")

s.tk.MustExec("drop table if exists tr_04;")
s.tk.MustExec("create table tr_04 (a varchar(20000) ) default charset utf8;")
s.tk.MustExec("create table tr_04 (a varchar(20000)) default charset utf8;")
s.testErrorCode(c, "alter table tr_04 convert to character set utf8mb4;", tmysql.ErrTooBigFieldlength)
s.testErrorCode(c, "create table tr (id int, name varchar(30000), purchased date ) default charset=utf8 collate=utf8_bin;", tmysql.ErrTooBigFieldlength)
s.testErrorCode(c, "create table tr (id int, name varchar(20000) charset utf8mb4, purchased date ) default charset=utf8 collate=utf8;", tmysql.ErrTooBigFieldlength)
Expand All @@ -2063,6 +2063,26 @@ func (s *testDBSuite) TestCheckTooBigFieldLength(c *C) {
s.tk.MustExec("alter table tr_05 modify column a varchar(16000) charset utf8mb4;")
}

func (s *testDBSuite) TestCheckConvertToCharacter(c *C) {
s.tk = testkit.NewTestKit(c, s.store)
s.tk.MustExec("use test")
s.tk.MustExec("drop table if exists t")
defer s.tk.MustExec("drop table t")
s.tk.MustExec("create table t(a varchar(10) charset binary);")
ctx := s.tk.Se.(sessionctx.Context)
is := domain.GetDomain(ctx).InfoSchema()
t, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
rs, err := s.tk.Exec("alter table t modify column a varchar(10) charset utf8 collate utf8_bin")
c.Assert(err, NotNil)
rs, err = s.tk.Exec("alter table t modify column a varchar(10) charset utf8mb4 collate utf8mb4_bin")
c.Assert(err, NotNil)
rs, err = s.tk.Exec("alter table t modify column a varchar(10) charset latin collate latin1_bin")
c.Assert(err, NotNil)
if rs != nil {
rs.Close()
}
c.Assert(t.Cols()[0].Charset, Equals, "binary")
}
func (s *testDBSuite) TestModifyColumnRollBack(c *C) {
s.tk = testkit.NewTestKit(c, s.store)
s.mustExec(c, "use test_db")
Expand Down
6 changes: 2 additions & 4 deletions ddl/ddl_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -1855,10 +1855,8 @@ func modifiableCharsetAndCollation(toCharset, toCollate, origCharset, origCollat
if !charset.ValidCharsetAndCollation(toCharset, toCollate) {
return ErrUnknownCharacterSet.GenWithStackByArgs(toCharset, toCollate)
}

if toCharset == charset.CharsetUTF8MB4 || (toCharset == charset.CharsetUTF8 && origCharset != charset.CharsetUTF8MB4) {
// TiDB treats all the data as utf8mb4, so we support changing the charset to utf8mb4.
// And not allow to change utf8mb4 to utf8.
if toCharset == charset.CharsetUTF8MB4 && origCharset == charset.CharsetUTF8 {
// TiDB only allow utf8 to be changed to utf8mb4.
return nil
}

Expand Down

0 comments on commit cfb6311

Please sign in to comment.