From 1771d675709984eaa6838ec6e6c8ac424001d0ce Mon Sep 17 00:00:00 2001 From: yj Date: Thu, 27 Sep 2018 18:02:05 +0800 Subject: [PATCH] ddl: allow enum to append values (#7767) --- ddl/db_change_test.go | 50 +++++++++++++++++++++++++++++++++++++++++++ ddl/ddl_api.go | 17 ++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/ddl/db_change_test.go b/ddl/db_change_test.go index 33eb71eee0bf0..b8550c4bcdd83 100644 --- a/ddl/db_change_test.go +++ b/ddl/db_change_test.go @@ -349,6 +349,56 @@ type expectQuery struct { rows []string } +func (s *testStateChangeSuite) TestAppendEnum(c *C) { + _, err := s.se.Execute(context.Background(), `create table t ( + c1 varchar(64), + c2 enum('N','Y') not null default 'N', + c3 timestamp on update current_timestamp, + c4 int primary key, + unique key idx2 (c2, c3))`) + c.Assert(err, IsNil) + defer s.se.Execute(context.Background(), "drop table t") + _, err = s.se.Execute(context.Background(), "insert into t values('a', 'N', '2017-07-01', 8)") + c.Assert(err, IsNil) + // Make sure these sqls use the the plan of index scan. + _, err = s.se.Execute(context.Background(), "drop stats t") + c.Assert(err, IsNil) + se, err := session.CreateSession(s.store) + c.Assert(err, IsNil) + _, err = se.Execute(context.Background(), "use test_db_state") + c.Assert(err, IsNil) + + _, err = s.se.Execute(context.Background(), "insert into t values('a', 'A', '2018-09-19', 9)") + c.Assert(err.Error(), Equals, "[table:1366]Incorrect enum value: 'A' for column 'c2' at row 1") + failAlterTableSQL1 := "alter table t change c2 c2 enum('N') DEFAULT 'N'" + _, err = s.se.Execute(context.Background(), failAlterTableSQL1) + c.Assert(err.Error(), Equals, "[ddl:203]unsupported modify column the number of enum column's elements is less than the original: 2") + failAlterTableSQL2 := "alter table t change c2 c2 int default 0" + _, err = s.se.Execute(context.Background(), failAlterTableSQL2) + c.Assert(err.Error(), Equals, "[ddl:203]unsupported modify column charset binary not match origin utf8") + alterTableSQL := "alter table t change c2 c2 enum('N','Y','A') DEFAULT 'A'" + _, err = s.se.Execute(context.Background(), alterTableSQL) + c.Assert(err, IsNil) + _, err = se.Execute(context.Background(), "insert into t values('a', 'A', '2018-09-20', 10)") + c.Assert(err, IsNil) + _, err = se.Execute(context.Background(), "insert into t (c1, c3, c4) values('a', '2018-09-21', 11)") + c.Assert(err, IsNil) + + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test_db_state") + result, err := s.execQuery(tk, "select c4, c2 from t order by c4 asc") + c.Assert(err, IsNil) + expected := []string{"8 N", "10 A", "11 A"} + checkResult(result, testkit.Rows(expected...)) + + _, err = s.se.Execute(context.Background(), "update t set c2='N' where c4 = 10") + c.Assert(err, IsNil) + result, err = s.execQuery(tk, "select c2 from t where c4 = 10") + c.Assert(err, IsNil) + expected = []string{"8 N", "10 N", "11 A"} + checkResult(result, testkit.Rows(expected...)) +} + // https://github.com/pingcap/tidb/pull/6249 fixes the following two test cases. func (s *testStateChangeSuite) TestWriteOnlyWriteNULL(c *C) { sqls := make([]sqlWithErr, 1) diff --git a/ddl/ddl_api.go b/ddl/ddl_api.go index 6ac34701538f2..70109e9214981 100644 --- a/ddl/ddl_api.go +++ b/ddl/ddl_api.go @@ -1457,7 +1457,22 @@ func modifiable(origin *types.FieldType, to *types.FieldType) error { return nil } case mysql.TypeEnum: - return errUnsupportedModifyColumn.GenWithStackByArgs("modify enum column is not supported") + if origin.Tp == to.Tp { + if len(to.Elems) < len(origin.Elems) { + msg := fmt.Sprintf("the number of enum column's elements is less than the original: %d", len(origin.Elems)) + return errUnsupportedModifyColumn.GenWithStackByArgs(msg) + } + for index, originElem := range origin.Elems { + toElem := to.Elems[index] + if originElem != toElem { + msg := fmt.Sprintf("cannot modify enum column value %s to %s", originElem, toElem) + return errUnsupportedModifyColumn.GenWithStackByArgs(msg) + } + } + return nil + } + msg := fmt.Sprintf("cannot modify enum type column's to type %s", to.String()) + return errUnsupportedModifyColumn.GenWithStackByArgs(msg) default: if origin.Tp == to.Tp { return nil