diff --git a/session/session_legacy_test.go b/session/session_legacy_test.go index b2ccb156754c2..a758dc026d167 100644 --- a/session/session_legacy_test.go +++ b/session/session_legacy_test.go @@ -20,7 +20,6 @@ import ( "fmt" "net" "strconv" - "sync" "time" . "github.com/pingcap/check" @@ -29,7 +28,6 @@ import ( "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/parser/auth" - "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/session" @@ -37,7 +35,6 @@ import ( "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/store/driver" "github.com/pingcap/tidb/store/mockstore" - "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/testkit" "github.com/pingcap/tidb/util/testleak" @@ -51,8 +48,6 @@ var withTiKV = flag.Bool("with-tikv", false, "run tests with TiKV cluster starte var _ = flag.String("pd-addrs", "127.0.0.1:2379", "workaroundGoCheckFlags: pd-addrs") var _ = Suite(&testSessionSuite{}) -var _ = Suite(&testSessionSuite2{}) -var _ = Suite(&testSessionSuite3{}) type testSessionSuiteBase struct { cluster testutils.Cluster @@ -64,14 +59,6 @@ type testSessionSuite struct { testSessionSuiteBase } -type testSessionSuite2 struct { - testSessionSuiteBase -} - -type testSessionSuite3 struct { - testSessionSuiteBase -} - func clearTiKVStorage(store kv.Storage) error { txn, err := store.Begin() if err != nil { @@ -185,33 +172,6 @@ func (s *testSessionSuiteBase) TearDownTest(c *C) { } } -func (s *testSessionSuite2) TestErrorRollback(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("drop table if exists t_rollback") - tk.MustExec("create table t_rollback (c1 int, c2 int, primary key(c1))") - tk.MustExec("insert into t_rollback values (0, 0)") - - var wg sync.WaitGroup - cnt := 4 - wg.Add(cnt) - num := 20 - - for i := 0; i < cnt; i++ { - go func() { - defer wg.Done() - localTk := testkit.NewTestKitWithInit(c, s.store) - localTk.MustExec("set @@session.tidb_retry_limit = 100") - for j := 0; j < num; j++ { - localTk.Exec("insert into t_rollback values (1, 1)") - localTk.MustExec("update t_rollback set c2 = c2 + 1 where c1 = 0") - } - }() - } - - wg.Wait() - tk.MustQuery("select c2 from t_rollback where c1 = 0").Check(testkit.Rows(fmt.Sprint(cnt * num))) -} - func (s *testSessionSuite) TestQueryString(c *C) { tk := testkit.NewTestKitWithInit(c, s.store) @@ -305,49 +265,6 @@ func (s *testSessionSuite) TestAffectedRows(c *C) { c.Assert(int(tk.Se.AffectedRows()), Equals, 2) } -func (s *testSessionSuite3) TestLastMessage(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(id TEXT)") - - // Insert - tk.MustExec(`INSERT INTO t VALUES ("a");`) - tk.CheckLastMessage("") - tk.MustExec(`INSERT INTO t VALUES ("b"), ("c");`) - tk.CheckLastMessage("Records: 2 Duplicates: 0 Warnings: 0") - - // Update - tk.MustExec(`UPDATE t set id = 'c' where id = 'a';`) - c.Assert(int(tk.Se.AffectedRows()), Equals, 1) - tk.CheckLastMessage("Rows matched: 1 Changed: 1 Warnings: 0") - tk.MustExec(`UPDATE t set id = 'a' where id = 'a';`) - c.Assert(int(tk.Se.AffectedRows()), Equals, 0) - tk.CheckLastMessage("Rows matched: 0 Changed: 0 Warnings: 0") - - // Replace - tk.MustExec(`drop table if exists t, t1; - create table t (c1 int PRIMARY KEY, c2 int); - create table t1 (a1 int, a2 int);`) - tk.MustExec(`INSERT INTO t VALUES (1,1)`) - tk.MustExec(`REPLACE INTO t VALUES (2,2)`) - tk.CheckLastMessage("") - tk.MustExec(`INSERT INTO t1 VALUES (1,10), (3,30);`) - tk.CheckLastMessage("Records: 2 Duplicates: 0 Warnings: 0") - tk.MustExec(`REPLACE INTO t SELECT * from t1`) - tk.CheckLastMessage("Records: 2 Duplicates: 1 Warnings: 0") - - // Check insert with CLIENT_FOUND_ROWS is set - tk.Se.SetClientCapability(mysql.ClientFoundRows) - tk.MustExec(`drop table if exists t, t1; - create table t (c1 int PRIMARY KEY, c2 int); - create table t1 (a1 int, a2 int);`) - tk.MustExec(`INSERT INTO t1 VALUES (1, 10), (2, 2), (3, 30);`) - tk.MustExec(`INSERT INTO t1 VALUES (1, 10), (2, 20), (3, 30);`) - tk.MustExec(`INSERT INTO t SELECT * FROM t1 ON DUPLICATE KEY UPDATE c2=a2;`) - tk.CheckLastMessage("Records: 6 Duplicates: 3 Warnings: 0") -} - // TestRowLock . See http://dev.mysql.com/doc/refman/5.7/en/commit.html. func (s *testSessionSuite) TestRowLock(c *C) { tk := testkit.NewTestKitWithInit(c, s.store) @@ -849,694 +766,3 @@ func (s *testSessionSuite) TestBinaryReadOnly(c *C) { c.Assert(session.GetHistory(tk.Se).Count(), Equals, 2) tk.MustExec("commit") } - -func (s *testSessionSuite) TestPrepare(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("create table t(id TEXT)") - tk.MustExec(`INSERT INTO t VALUES ("id");`) - id, ps, _, err := tk.Se.PrepareStmt("select id+? from t") - ctx := context.Background() - c.Assert(err, IsNil) - c.Assert(id, Equals, uint32(1)) - c.Assert(ps, Equals, 1) - tk.MustExec(`set @a=1`) - rs, err := tk.Se.ExecutePreparedStmt(ctx, id, []types.Datum{types.NewDatum("1")}) - c.Assert(err, IsNil) - rs.Close() - err = tk.Se.DropPreparedStmt(id) - c.Assert(err, IsNil) - - tk.MustExec("prepare stmt from 'select 1+?'") - tk.MustExec("set @v1=100") - tk.MustQuery("execute stmt using @v1").Check(testkit.Rows("101")) - - tk.MustExec("set @v2=200") - tk.MustQuery("execute stmt using @v2").Check(testkit.Rows("201")) - - tk.MustExec("set @v3=300") - tk.MustQuery("execute stmt using @v3").Check(testkit.Rows("301")) - tk.MustExec("deallocate prepare stmt") - - // Execute prepared statements for more than one time. - tk.MustExec("create table multiexec (a int, b int)") - tk.MustExec("insert multiexec values (1, 1), (2, 2)") - id, _, _, err = tk.Se.PrepareStmt("select a from multiexec where b = ? order by b") - c.Assert(err, IsNil) - rs, err = tk.Se.ExecutePreparedStmt(ctx, id, []types.Datum{types.NewDatum(1)}) - c.Assert(err, IsNil) - rs.Close() - rs, err = tk.Se.ExecutePreparedStmt(ctx, id, []types.Datum{types.NewDatum(2)}) - rs.Close() - c.Assert(err, IsNil) -} - -func (s *testSessionSuite2) TestSpecifyIndexPrefixLength(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - _, err := tk.Exec("create table t (c1 char, index(c1(3)));") - // ERROR 1089 (HY000): Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys - c.Assert(err, NotNil) - - _, err = tk.Exec("create table t (c1 int, index(c1(3)));") - // ERROR 1089 (HY000): Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys - c.Assert(err, NotNil) - - _, err = tk.Exec("create table t (c1 bit(10), index(c1(3)));") - // ERROR 1089 (HY000): Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys - c.Assert(err, NotNil) - - tk.MustExec("create table t (c1 char, c2 int, c3 bit(10));") - - _, err = tk.Exec("create index idx_c1 on t (c1(3));") - // ERROR 1089 (HY000): Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys - c.Assert(err, NotNil) - - _, err = tk.Exec("create index idx_c1 on t (c2(3));") - // ERROR 1089 (HY000): Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys - c.Assert(err, NotNil) - - _, err = tk.Exec("create index idx_c1 on t (c3(3));") - // ERROR 1089 (HY000): Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys - c.Assert(err, NotNil) - - tk.MustExec("drop table if exists t;") - - _, err = tk.Exec("create table t (c1 int, c2 blob, c3 varchar(64), index(c2));") - // ERROR 1170 (42000): BLOB/TEXT column 'c2' used in key specification without a key length - c.Assert(err, NotNil) - - tk.MustExec("create table t (c1 int, c2 blob, c3 varchar(64));") - _, err = tk.Exec("create index idx_c1 on t (c2);") - // ERROR 1170 (42000): BLOB/TEXT column 'c2' used in key specification without a key length - c.Assert(err, NotNil) - - _, err = tk.Exec("create index idx_c1 on t (c2(555555));") - // ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes - c.Assert(err, NotNil) - - _, err = tk.Exec("create index idx_c1 on t (c1(5))") - // ERROR 1089 (HY000): Incorrect prefix key; - // the used key part isn't a string, the used length is longer than the key part, - // or the storage engine doesn't support unique prefix keys - c.Assert(err, NotNil) - - tk.MustExec("create index idx_c1 on t (c1);") - tk.MustExec("create index idx_c2 on t (c2(3));") - tk.MustExec("create unique index idx_c3 on t (c3(5));") - - tk.MustExec("insert into t values (3, 'abc', 'def');") - tk.MustQuery("select c2 from t where c2 = 'abc';").Check(testkit.Rows("abc")) - - tk.MustExec("insert into t values (4, 'abcd', 'xxx');") - tk.MustExec("insert into t values (4, 'abcf', 'yyy');") - tk.MustQuery("select c2 from t where c2 = 'abcf';").Check(testkit.Rows("abcf")) - tk.MustQuery("select c2 from t where c2 = 'abcd';").Check(testkit.Rows("abcd")) - - tk.MustExec("insert into t values (4, 'ignore', 'abcdeXXX');") - _, err = tk.Exec("insert into t values (5, 'ignore', 'abcdeYYY');") - // ERROR 1062 (23000): Duplicate entry 'abcde' for key 'idx_c3' - c.Assert(err, NotNil) - tk.MustQuery("select c3 from t where c3 = 'abcde';").Check(testkit.Rows()) - - tk.MustExec("delete from t where c3 = 'abcdeXXX';") - tk.MustExec("delete from t where c2 = 'abc';") - - tk.MustQuery("select c2 from t where c2 > 'abcd';").Check(testkit.Rows("abcf")) - tk.MustQuery("select c2 from t where c2 < 'abcf';").Check(testkit.Rows("abcd")) - tk.MustQuery("select c2 from t where c2 >= 'abcd';").Check(testkit.Rows("abcd", "abcf")) - tk.MustQuery("select c2 from t where c2 <= 'abcf';").Check(testkit.Rows("abcd", "abcf")) - tk.MustQuery("select c2 from t where c2 != 'abc';").Check(testkit.Rows("abcd", "abcf")) - tk.MustQuery("select c2 from t where c2 != 'abcd';").Check(testkit.Rows("abcf")) - - tk.MustExec("drop table if exists t1;") - tk.MustExec("create table t1 (a int, b char(255), key(a, b(20)));") - tk.MustExec("insert into t1 values (0, '1');") - tk.MustExec("update t1 set b = b + 1 where a = 0;") - tk.MustQuery("select b from t1 where a = 0;").Check(testkit.Rows("2")) - - // test union index. - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a text, b text, c int, index (a(3), b(3), c));") - tk.MustExec("insert into t values ('abc', 'abcd', 1);") - tk.MustExec("insert into t values ('abcx', 'abcf', 2);") - tk.MustExec("insert into t values ('abcy', 'abcf', 3);") - tk.MustExec("insert into t values ('bbc', 'abcd', 4);") - tk.MustExec("insert into t values ('bbcz', 'abcd', 5);") - tk.MustExec("insert into t values ('cbck', 'abd', 6);") - tk.MustQuery("select c from t where a = 'abc' and b <= 'abc';").Check(testkit.Rows()) - tk.MustQuery("select c from t where a = 'abc' and b <= 'abd';").Check(testkit.Rows("1")) - tk.MustQuery("select c from t where a < 'cbc' and b > 'abcd';").Check(testkit.Rows("2", "3")) - tk.MustQuery("select c from t where a <= 'abd' and b > 'abc';").Check(testkit.Rows("1", "2", "3")) - tk.MustQuery("select c from t where a < 'bbcc' and b = 'abcd';").Check(testkit.Rows("1", "4")) - tk.MustQuery("select c from t where a > 'bbcf';").Check(testkit.Rows("5", "6")) -} - -func (s *testSessionSuite) TestResultField(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("create table t (id int);") - - tk.MustExec(`INSERT INTO t VALUES (1);`) - tk.MustExec(`INSERT INTO t VALUES (2);`) - r, err := tk.Exec(`SELECT count(*) from t;`) - c.Assert(err, IsNil) - fields := r.Fields() - c.Assert(err, IsNil) - c.Assert(len(fields), Equals, 1) - field := fields[0].Column - c.Assert(field.GetType(), Equals, mysql.TypeLonglong) - c.Assert(field.GetFlen(), Equals, 21) -} - -func (s *testSessionSuite) TestResultType(c *C) { - // Testcase for https://github.com/pingcap/tidb/issues/325 - tk := testkit.NewTestKitWithInit(c, s.store) - rs, err := tk.Exec(`select cast(null as char(30))`) - c.Assert(err, IsNil) - req := rs.NewChunk(nil) - err = rs.Next(context.Background(), req) - c.Assert(err, IsNil) - c.Assert(req.GetRow(0).IsNull(0), IsTrue) - c.Assert(rs.Fields()[0].Column.FieldType.GetType(), Equals, mysql.TypeVarString) -} - -func (s *testSessionSuite) TestFieldText(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("create table t (a int)") - tests := []struct { - sql string - field string - }{ - {"select distinct(a) from t", "a"}, - {"select (1)", "1"}, - {"select (1+1)", "(1+1)"}, - {"select a from t", "a"}, - {"select ((a+1)) from t", "((a+1))"}, - {"select 1 /*!32301 +1 */;", "1 +1 "}, - {"select /*!32301 1 +1 */;", "1 +1 "}, - {"/*!32301 select 1 +1 */;", "1 +1 "}, - {"select 1 + /*!32301 1 +1 */;", "1 + 1 +1 "}, - {"select 1 /*!32301 + 1, 1 */;", "1 + 1"}, - {"select /*!32301 1, 1 +1 */;", "1"}, - {"select /*!32301 1 + 1, */ +1;", "1 + 1"}, - } - for _, tt := range tests { - result, err := tk.Exec(tt.sql) - c.Assert(err, IsNil) - c.Assert(result.Fields()[0].ColumnAsName.O, Equals, tt.field) - } -} - -func (s *testSessionSuite3) TestIndexMaxLength(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("create database test_index_max_length") - tk.MustExec("use test_index_max_length") - - // create simple index at table creation - tk.MustGetErrCode("create table t (c1 varchar(3073), index(c1)) charset = ascii;", mysql.ErrTooLongKey) - - // create simple index after table creation - tk.MustExec("create table t (c1 varchar(3073)) charset = ascii;") - tk.MustGetErrCode("create index idx_c1 on t(c1) ", mysql.ErrTooLongKey) - tk.MustExec("drop table t;") - - // create compound index at table creation - tk.MustGetErrCode("create table t (c1 varchar(3072), c2 varchar(1), index(c1, c2)) charset = ascii;", mysql.ErrTooLongKey) - tk.MustGetErrCode("create table t (c1 varchar(3072), c2 char(1), index(c1, c2)) charset = ascii;", mysql.ErrTooLongKey) - tk.MustGetErrCode("create table t (c1 varchar(3072), c2 char, index(c1, c2)) charset = ascii;", mysql.ErrTooLongKey) - tk.MustGetErrCode("create table t (c1 varchar(3072), c2 date, index(c1, c2)) charset = ascii;", mysql.ErrTooLongKey) - tk.MustGetErrCode("create table t (c1 varchar(3069), c2 timestamp(1), index(c1, c2)) charset = ascii;", mysql.ErrTooLongKey) - - tk.MustExec("create table t (c1 varchar(3068), c2 bit(26), index(c1, c2)) charset = ascii;") // 26 bit = 4 bytes - tk.MustExec("drop table t;") - tk.MustExec("create table t (c1 varchar(3068), c2 bit(32), index(c1, c2)) charset = ascii;") // 32 bit = 4 bytes - tk.MustExec("drop table t;") - tk.MustGetErrCode("create table t (c1 varchar(3068), c2 bit(33), index(c1, c2)) charset = ascii;", mysql.ErrTooLongKey) - - // create compound index after table creation - tk.MustExec("create table t (c1 varchar(3072), c2 varchar(1)) charset = ascii;") - tk.MustGetErrCode("create index idx_c1_c2 on t(c1, c2);", mysql.ErrTooLongKey) - tk.MustExec("drop table t;") - - tk.MustExec("create table t (c1 varchar(3072), c2 char(1)) charset = ascii;") - tk.MustGetErrCode("create index idx_c1_c2 on t(c1, c2);", mysql.ErrTooLongKey) - tk.MustExec("drop table t;") - - tk.MustExec("create table t (c1 varchar(3072), c2 char) charset = ascii;") - tk.MustGetErrCode("create index idx_c1_c2 on t(c1, c2);", mysql.ErrTooLongKey) - tk.MustExec("drop table t;") - - tk.MustExec("create table t (c1 varchar(3072), c2 date) charset = ascii;") - tk.MustGetErrCode("create index idx_c1_c2 on t(c1, c2);", mysql.ErrTooLongKey) - tk.MustExec("drop table t;") - - tk.MustExec("create table t (c1 varchar(3069), c2 timestamp(1)) charset = ascii;") - tk.MustGetErrCode("create index idx_c1_c2 on t(c1, c2);", mysql.ErrTooLongKey) - tk.MustExec("drop table t;") - - // Test charsets other than `ascii`. - assertCharsetLimit := func(charset string, bytesPerChar int) { - base := 3072 / bytesPerChar - tk.MustGetErrCode(fmt.Sprintf("create table t (a varchar(%d) primary key) charset=%s", base+1, charset), mysql.ErrTooLongKey) - tk.MustExec(fmt.Sprintf("create table t (a varchar(%d) primary key) charset=%s", base, charset)) - tk.MustExec("drop table if exists t") - } - assertCharsetLimit("binary", 1) - assertCharsetLimit("latin1", 1) - assertCharsetLimit("utf8", 3) - assertCharsetLimit("utf8mb4", 4) - - // Test types bit length limit. - assertTypeLimit := func(tp string, limitBitLength int) { - base := 3072 - limitBitLength - tk.MustGetErrCode(fmt.Sprintf("create table t (a blob(10000), b %s, index idx(a(%d), b))", tp, base+1), mysql.ErrTooLongKey) - tk.MustExec(fmt.Sprintf("create table t (a blob(10000), b %s, index idx(a(%d), b))", tp, base)) - tk.MustExec("drop table if exists t") - } - - assertTypeLimit("tinyint", 1) - assertTypeLimit("smallint", 2) - assertTypeLimit("mediumint", 3) - assertTypeLimit("int", 4) - assertTypeLimit("integer", 4) - assertTypeLimit("bigint", 8) - assertTypeLimit("float", 4) - assertTypeLimit("float(24)", 4) - assertTypeLimit("float(25)", 8) - assertTypeLimit("decimal(9)", 4) - assertTypeLimit("decimal(10)", 5) - assertTypeLimit("decimal(17)", 8) - assertTypeLimit("year", 1) - assertTypeLimit("date", 3) - assertTypeLimit("time", 3) - assertTypeLimit("datetime", 8) - assertTypeLimit("timestamp", 4) -} - -func (s *testSessionSuite2) TestIndexColumnLength(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("create table t (c1 int, c2 blob);") - tk.MustExec("create index idx_c1 on t(c1);") - tk.MustExec("create index idx_c2 on t(c2(6));") - - is := s.dom.InfoSchema() - tab, err2 := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) - c.Assert(err2, Equals, nil) - - idxC1Cols := tables.FindIndexByColName(tab, "c1").Meta().Columns - c.Assert(idxC1Cols[0].Length, Equals, types.UnspecifiedLength) - - idxC2Cols := tables.FindIndexByColName(tab, "c2").Meta().Columns - c.Assert(idxC2Cols[0].Length, Equals, 6) -} - -func (s *testSessionSuite2) TestIgnoreForeignKey(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - sqlText := `CREATE TABLE address ( - id bigint(20) NOT NULL AUTO_INCREMENT, - user_id bigint(20) NOT NULL, - PRIMARY KEY (id), - CONSTRAINT FK_7rod8a71yep5vxasb0ms3osbg FOREIGN KEY (user_id) REFERENCES waimaiqa.user (id), - INDEX FK_7rod8a71yep5vxasb0ms3osbg (user_id) comment '' - ) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ROW_FORMAT=COMPACT COMMENT='' CHECKSUM=0 DELAY_KEY_WRITE=0;` - tk.MustExec(sqlText) -} - -// TestISColumns tests information_schema.columns. -func (s *testSessionSuite3) TestISColumns(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("select ORDINAL_POSITION from INFORMATION_SCHEMA.COLUMNS;") - tk.MustQuery("SELECT CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.CHARACTER_SETS WHERE CHARACTER_SET_NAME = 'utf8mb4'").Check(testkit.Rows("utf8mb4")) -} - -func (s *testSessionSuite3) TestMultiStmts(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("drop table if exists t1; create table t1(id int ); insert into t1 values (1);") - tk.MustQuery("select * from t1;").Check(testkit.Rows("1")) -} - -func (s *testSessionSuite2) TestLastExecuteDDLFlag(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1(id int)") - c.Assert(tk.Se.Value(sessionctx.LastExecuteDDL), NotNil) - tk.MustExec("insert into t1 values (1)") - c.Assert(tk.Se.Value(sessionctx.LastExecuteDDL), IsNil) -} - -func (s *testSessionSuite3) TestDecimal(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t (a decimal unique);") - tk.MustExec("insert t values ('100');") - _, err := tk.Exec("insert t values ('1e2');") - c.Check(err, NotNil) -} - -func (s *testSessionSuite2) TestParser(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - // test for https://github.com/pingcap/tidb/pull/177 - tk.MustExec("CREATE TABLE `t1` ( `a` char(3) NOT NULL default '', `b` char(3) NOT NULL default '', `c` char(3) NOT NULL default '', PRIMARY KEY (`a`,`b`,`c`)) ENGINE=InnoDB;") - tk.MustExec("CREATE TABLE `t2` ( `a` char(3) NOT NULL default '', `b` char(3) NOT NULL default '', `c` char(3) NOT NULL default '', PRIMARY KEY (`a`,`b`,`c`)) ENGINE=InnoDB;") - tk.MustExec(`INSERT INTO t1 VALUES (1,1,1);`) - tk.MustExec(`INSERT INTO t2 VALUES (1,1,1);`) - tk.MustExec(`PREPARE my_stmt FROM "SELECT t1.b, count(*) FROM t1 group by t1.b having count(*) > ALL (SELECT COUNT(*) FROM t2 WHERE t2.a=1 GROUP By t2.b)";`) - tk.MustExec(`EXECUTE my_stmt;`) - tk.MustExec(`EXECUTE my_stmt;`) - tk.MustExec(`deallocate prepare my_stmt;`) - tk.MustExec(`drop table t1,t2;`) -} - -func (s *testSessionSuite3) TestOnDuplicate(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - // test for https://github.com/pingcap/tidb/pull/454 - tk.MustExec("drop table if exists t") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (c1 int, c2 int, c3 int);") - tk.MustExec("insert into t1 set c1=1, c2=2, c3=1;") - tk.MustExec("create table t (c1 int, c2 int, c3 int, primary key (c1));") - tk.MustExec("insert into t set c1=1, c2=4;") - tk.MustExec("insert into t select * from t1 limit 1 on duplicate key update c3=3333;") -} - -func (s *testSessionSuite2) TestReplace(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - // test for https://github.com/pingcap/tidb/pull/456 - tk.MustExec("drop table if exists t") - tk.MustExec("drop table if exists t1") - tk.MustExec("create table t1 (c1 int, c2 int, c3 int);") - tk.MustExec("replace into t1 set c1=1, c2=2, c3=1;") - tk.MustExec("create table t (c1 int, c2 int, c3 int, primary key (c1));") - tk.MustExec("replace into t set c1=1, c2=4;") - tk.MustExec("replace into t select * from t1 limit 1;") -} - -func (s *testSessionSuite3) TestDelete(c *C) { - // test for https://github.com/pingcap/tidb/pull/1135 - - tk := testkit.NewTestKitWithInit(c, s.store) - tk1 := testkit.NewTestKit(c, s.store) - tk1.MustExec("create database test1") - tk1.MustExec("use test1") - tk1.MustExec("create table t (F1 VARCHAR(30));") - tk1.MustExec("insert into t (F1) values ('1'), ('4');") - - tk.MustExec("create table t (F1 VARCHAR(30));") - tk.MustExec("insert into t (F1) values ('1'), ('2');") - tk.MustExec("delete m1 from t m2,t m1 where m1.F1>1;") - tk.MustQuery("select * from t;").Check(testkit.Rows("1")) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (F1 VARCHAR(30));") - tk.MustExec("insert into t (F1) values ('1'), ('2');") - tk.MustExec("delete m1 from t m1,t m2 where true and m1.F1<2;") - tk.MustQuery("select * from t;").Check(testkit.Rows("2")) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (F1 VARCHAR(30));") - tk.MustExec("insert into t (F1) values ('1'), ('2');") - tk.MustExec("delete m1 from t m1,t m2 where false;") - tk.MustQuery("select * from t;").Check(testkit.Rows("1", "2")) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (F1 VARCHAR(30));") - tk.MustExec("insert into t (F1) values ('1'), ('2');") - tk.MustExec("delete m1, m2 from t m1,t m2 where m1.F1>m2.F1;") - tk.MustQuery("select * from t;").Check(testkit.Rows()) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (F1 VARCHAR(30));") - tk.MustExec("insert into t (F1) values ('1'), ('2');") - tk.MustExec("delete test1.t from test1.t inner join test.t where test1.t.F1 > test.t.F1") - tk1.MustQuery("select * from t;").Check(testkit.Rows("1")) -} - -func (s *testSessionSuite2) TestResetCtx(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk1 := testkit.NewTestKitWithInit(c, s.store) - - tk.MustExec("create table t (i int auto_increment not null key);") - tk.MustExec("insert into t values (1);") - tk.MustExec("set @@tidb_disable_txn_auto_retry = 0") - tk.MustExec("begin;") - tk.MustExec("insert into t values (10);") - tk.MustExec("update t set i = i + row_count();") - tk.MustQuery("select * from t;").Check(testkit.Rows("2", "11")) - - tk1.MustExec("update t set i = 0 where i = 1;") - tk1.MustQuery("select * from t;").Check(testkit.Rows("0")) - - tk.MustExec("commit;") - tk.MustQuery("select * from t;").Check(testkit.Rows("1", "11")) - - tk.MustExec("delete from t where i = 11;") - tk.MustExec("begin;") - tk.MustExec("insert into t values ();") - tk.MustExec("update t set i = i + last_insert_id() + 1;") - tk.MustQuery("select * from t;").Check(testkit.Rows("14", "25")) - - tk1.MustExec("update t set i = 0 where i = 1;") - tk1.MustQuery("select * from t;").Check(testkit.Rows("0")) - - tk.MustExec("commit;") - tk.MustQuery("select * from t;").Check(testkit.Rows("13", "25")) -} - -func (s *testSessionSuite3) TestUnique(c *C) { - // test for https://github.com/pingcap/tidb/pull/461 - - tk := testkit.NewTestKitWithInit(c, s.store) - tk1 := testkit.NewTestKitWithInit(c, s.store) - tk2 := testkit.NewTestKitWithInit(c, s.store) - - tk.MustExec("set @@tidb_disable_txn_auto_retry = 0") - tk1.MustExec("set @@tidb_disable_txn_auto_retry = 0") - tk.MustExec(`CREATE TABLE test ( id int(11) UNSIGNED NOT NULL AUTO_INCREMENT, val int UNIQUE, PRIMARY KEY (id)); `) - tk.MustExec("begin;") - tk.MustExec("insert into test(id, val) values(1, 1);") - tk1.MustExec("begin;") - tk1.MustExec("insert into test(id, val) values(2, 2);") - tk2.MustExec("begin;") - tk2.MustExec("insert into test(id, val) values(1, 2);") - tk2.MustExec("commit;") - _, err := tk.Exec("commit") - c.Assert(err, NotNil) - // Check error type and error message - c.Assert(terror.ErrorEqual(err, kv.ErrKeyExists), IsTrue, Commentf("err %v", err)) - c.Assert(err.Error(), Equals, "previous statement: insert into test(id, val) values(1, 1);: [kv:1062]Duplicate entry '1' for key 'PRIMARY'") - - _, err = tk1.Exec("commit") - c.Assert(err, NotNil) - c.Assert(terror.ErrorEqual(err, kv.ErrKeyExists), IsTrue, Commentf("err %v", err)) - c.Assert(err.Error(), Equals, "previous statement: insert into test(id, val) values(2, 2);: [kv:1062]Duplicate entry '2' for key 'val'") - - // Test for https://github.com/pingcap/tidb/issues/463 - tk.MustExec("drop table test;") - tk.MustExec(`CREATE TABLE test ( - id int(11) UNSIGNED NOT NULL AUTO_INCREMENT, - val int UNIQUE, - PRIMARY KEY (id) - );`) - tk.MustExec("insert into test(id, val) values(1, 1);") - _, err = tk.Exec("insert into test(id, val) values(2, 1);") - c.Assert(err, NotNil) - tk.MustExec("insert into test(id, val) values(2, 2);") - - tk.MustExec("begin;") - tk.MustExec("insert into test(id, val) values(3, 3);") - _, err = tk.Exec("insert into test(id, val) values(4, 3);") - c.Assert(err, NotNil) - tk.MustExec("insert into test(id, val) values(4, 4);") - tk.MustExec("commit;") - - tk1.MustExec("begin;") - tk1.MustExec("insert into test(id, val) values(5, 6);") - tk.MustExec("begin;") - tk.MustExec("insert into test(id, val) values(20, 6);") - tk.MustExec("commit;") - tk1.Exec("commit") - tk1.MustExec("insert into test(id, val) values(5, 5);") - - tk.MustExec("drop table test;") - tk.MustExec(`CREATE TABLE test ( - id int(11) UNSIGNED NOT NULL AUTO_INCREMENT, - val1 int UNIQUE, - val2 int UNIQUE, - PRIMARY KEY (id) - );`) - tk.MustExec("insert into test(id, val1, val2) values(1, 1, 1);") - tk.MustExec("insert into test(id, val1, val2) values(2, 2, 2);") - tk.Exec("update test set val1 = 3, val2 = 2 where id = 1;") - tk.MustExec("insert into test(id, val1, val2) values(3, 3, 3);") -} - -func (s *testSessionSuite2) TestSet(c *C) { - // Test for https://github.com/pingcap/tidb/issues/1114 - - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("set @tmp = 0") - tk.MustExec("set @tmp := @tmp + 1") - tk.MustQuery("select @tmp").Check(testkit.Rows("1")) - tk.MustQuery("select @tmp1 = 1, @tmp2 := 2").Check(testkit.Rows(" 2")) - tk.MustQuery("select @tmp1 := 11, @tmp2").Check(testkit.Rows("11 2")) - - tk.MustExec("drop table if exists t") - tk.MustExec("create table t (c int);") - tk.MustExec("insert into t values (1),(2);") - tk.MustExec("update t set c = 3 WHERE c = @var:= 1") - tk.MustQuery("select * from t").Check(testkit.Rows("3", "2")) - tk.MustQuery("select @tmp := count(*) from t").Check(testkit.Rows("2")) - tk.MustQuery("select @tmp := c-2 from t where c=3").Check(testkit.Rows("1")) -} - -func (s *testSessionSuite3) TestMySQLTypes(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustQuery(`select 0x01 + 1, x'4D7953514C' = "MySQL"`).Check(testkit.Rows("2 1")) - tk.MustQuery(`select 0b01 + 1, 0b01000001 = "A"`).Check(testkit.Rows("2 1")) -} - -func (s *testSessionSuite2) TestIssue986(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - sqlText := `CREATE TABLE address ( - id bigint(20) NOT NULL AUTO_INCREMENT, - PRIMARY KEY (id));` - tk.MustExec(sqlText) - tk.MustExec(`insert into address values ('10')`) -} - -func (s *testSessionSuite3) TestCast(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustQuery("select cast(0.5 as unsigned)") - tk.MustQuery("select cast(-0.5 as signed)") - tk.MustQuery("select hex(cast(0x10 as binary(2)))").Check(testkit.Rows("1000")) -} - -func (s *testSessionSuite2) TestTableInfoMeta(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - checkResult := func(affectedRows uint64, insertID uint64) { - gotRows := tk.Se.AffectedRows() - c.Assert(gotRows, Equals, affectedRows) - - gotID := tk.Se.LastInsertID() - c.Assert(gotID, Equals, insertID) - } - - // create table - tk.MustExec("CREATE TABLE tbl_test(id INT NOT NULL DEFAULT 1, name varchar(255), PRIMARY KEY(id));") - - // insert data - tk.MustExec(`INSERT INTO tbl_test VALUES (1, "hello");`) - checkResult(1, 0) - - tk.MustExec(`INSERT INTO tbl_test VALUES (2, "hello");`) - checkResult(1, 0) - - tk.MustExec(`UPDATE tbl_test SET name = "abc" where id = 2;`) - checkResult(1, 0) - - tk.MustExec(`DELETE from tbl_test where id = 2;`) - checkResult(1, 0) - - // select data - tk.MustQuery("select * from tbl_test").Check(testkit.Rows("1 hello")) -} - -func (s *testSessionSuite3) TestCaseInsensitive(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - - tk.MustExec("create table T (a text, B int)") - tk.MustExec("insert t (A, b) values ('aaa', 1)") - rs, err := tk.Exec("select * from t") - c.Assert(err, IsNil) - fields := rs.Fields() - c.Assert(fields[0].ColumnAsName.O, Equals, "a") - c.Assert(fields[1].ColumnAsName.O, Equals, "B") - rs.Close() - - rs, err = tk.Exec("select A, b from t") - c.Assert(err, IsNil) - fields = rs.Fields() - c.Assert(fields[0].ColumnAsName.O, Equals, "A") - c.Assert(fields[1].ColumnAsName.O, Equals, "b") - rs.Close() - - rs, err = tk.Exec("select a as A from t where A > 0") - c.Assert(err, IsNil) - fields = rs.Fields() - c.Assert(fields[0].ColumnAsName.O, Equals, "A") - rs.Close() - - tk.MustExec("update T set b = B + 1") - tk.MustExec("update T set B = b + 1") - tk.MustQuery("select b from T").Check(testkit.Rows("3")) -} - -// TestDeletePanic is for delete panic -func (s *testSessionSuite2) TestDeletePanic(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("create table t (c int)") - tk.MustExec("insert into t values (1), (2), (3)") - tk.MustExec("delete from `t` where `c` = ?", 1) - tk.MustExec("delete from `t` where `c` = ?", 2) -} - -func (s *testSessionSuite2) TestInformationSchemaCreateTime(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("create table t (c int)") - tk.MustExec(`set @@time_zone = 'Asia/Shanghai'`) - ret := tk.MustQuery("select create_time from information_schema.tables where table_name='t';") - // Make sure t1 is greater than t. - time.Sleep(time.Second) - tk.MustExec("alter table t modify c int default 11") - ret1 := tk.MustQuery("select create_time from information_schema.tables where table_name='t';") - ret2 := tk.MustQuery("show table status like 't'") - c.Assert(ret1.Rows()[0][0].(string), Equals, ret2.Rows()[0][11].(string)) - t, err := types.ParseDatetime(nil, ret.Rows()[0][0].(string)) - c.Assert(err, IsNil) - t1, err := types.ParseDatetime(nil, ret1.Rows()[0][0].(string)) - c.Assert(err, IsNil) - r := t1.Compare(t) - c.Assert(r, Equals, 1) - // Check that time_zone changes makes the create_time different - tk.MustExec(`set @@time_zone = 'Europe/Amsterdam'`) - ret = tk.MustQuery(`select create_time from information_schema.tables where table_name='t'`) - ret2 = tk.MustQuery(`show table status like 't'`) - c.Assert(ret.Rows()[0][0].(string), Equals, ret2.Rows()[0][11].(string)) - t, err = types.ParseDatetime(nil, ret.Rows()[0][0].(string)) - c.Assert(err, IsNil) - // Asia/Shanghai 2022-02-17 17:40:05 > Europe/Amsterdam 2022-02-17 10:40:05 - r = t1.Compare(t) - c.Assert(r, Equals, 1) -} - -func (s *testSessionSuite2) TestStatementErrorInTransaction(c *C) { - tk := testkit.NewTestKitWithInit(c, s.store) - tk.MustExec("create table statement_side_effect (c int primary key)") - tk.MustExec("begin") - tk.MustExec("insert into statement_side_effect values (1)") - _, err := tk.Exec("insert into statement_side_effect value (2),(3),(4),(1)") - c.Assert(err, NotNil) - tk.MustQuery(`select * from statement_side_effect`).Check(testkit.Rows("1")) - tk.MustExec("commit") - tk.MustQuery(`select * from statement_side_effect`).Check(testkit.Rows("1")) - - tk.MustExec("drop table if exists test;") - tk.MustExec(`create table test ( - a int(11) DEFAULT NULL, - b int(11) DEFAULT NULL - ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;`) - tk.MustExec("insert into test values (1, 2), (1, 2), (1, 1), (1, 1);") - - tk.MustExec("start transaction;") - // In the transaction, statement error should not rollback the transaction. - _, err = tk.Exec("update tset set b=11 where a=1 and b=2;") - c.Assert(err, NotNil) - // Test for a bug that last line rollback and exit transaction, this line autocommit. - tk.MustExec("update test set b = 11 where a = 1 and b = 2;") - tk.MustExec("rollback") - tk.MustQuery("select * from test where a = 1 and b = 11").Check(testkit.Rows()) -} diff --git a/tests/realtikvtest/sessiontest/session_test.go b/tests/realtikvtest/sessiontest/session_test.go index 5da90803d154b..271d6032bda11 100644 --- a/tests/realtikvtest/sessiontest/session_test.go +++ b/tests/realtikvtest/sessiontest/session_test.go @@ -19,6 +19,7 @@ import ( "fmt" "sort" "strings" + "sync" "testing" "time" @@ -33,9 +34,11 @@ import ( "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/privilege/privileges" "github.com/pingcap/tidb/session" + "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/store/copr" "github.com/pingcap/tidb/store/mockstore" + "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/tests/realtikvtest" "github.com/pingcap/tidb/types" @@ -2209,3 +2212,849 @@ func TestSetGlobalTZ(t *testing.T) { tk1 := testkit.NewTestKit(t, store) tk1.MustQuery("show variables like 'time_zone'").Check(testkit.Rows("time_zone +00:00")) } + +func TestErrorRollback(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t_rollback") + tk.MustExec("create table t_rollback (c1 int, c2 int, primary key(c1))") + tk.MustExec("insert into t_rollback values (0, 0)") + + var wg sync.WaitGroup + cnt := 4 + wg.Add(cnt) + num := 20 + + for i := 0; i < cnt; i++ { + go func() { + defer wg.Done() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@session.tidb_retry_limit = 100") + for j := 0; j < num; j++ { + _, _ = tk.Exec("insert into t_rollback values (1, 1)") + tk.MustExec("update t_rollback set c2 = c2 + 1 where c1 = 0") + } + }() + } + + wg.Wait() + tk.MustQuery("select c2 from t_rollback where c1 = 0").Check(testkit.Rows(fmt.Sprint(cnt * num))) +} + +func TestDeletePanic(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (c int)") + tk.MustExec("insert into t values (1), (2), (3)") + tk.MustExec("delete from `t` where `c` = ?", 1) + tk.MustExec("delete from `t` where `c` = ?", 2) +} + +func TestInformationSchemaCreateTime(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (c int)") + tk.MustExec(`set @@time_zone = 'Asia/Shanghai'`) + ret := tk.MustQuery("select create_time from information_schema.tables where table_name='t';") + // Make sure t1 is greater than t. + time.Sleep(time.Second) + tk.MustExec("alter table t modify c int default 11") + ret1 := tk.MustQuery("select create_time from information_schema.tables where table_name='t';") + ret2 := tk.MustQuery("show table status like 't'") + require.Equal(t, ret2.Rows()[0][11].(string), ret1.Rows()[0][0].(string)) + typ1, err := types.ParseDatetime(nil, ret.Rows()[0][0].(string)) + require.NoError(t, err) + typ2, err := types.ParseDatetime(nil, ret1.Rows()[0][0].(string)) + require.NoError(t, err) + r := typ2.Compare(typ1) + require.Equal(t, 1, r) + // Check that time_zone changes makes the create_time different + tk.MustExec(`set @@time_zone = 'Europe/Amsterdam'`) + ret = tk.MustQuery(`select create_time from information_schema.tables where table_name='t'`) + ret2 = tk.MustQuery(`show table status like 't'`) + require.Equal(t, ret2.Rows()[0][11].(string), ret.Rows()[0][0].(string)) + typ3, err := types.ParseDatetime(nil, ret.Rows()[0][0].(string)) + require.NoError(t, err) + // Asia/Shanghai 2022-02-17 17:40:05 > Europe/Amsterdam 2022-02-17 10:40:05 + r = typ2.Compare(typ3) + require.Equal(t, 1, r) +} + +func TestPrepare(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(id TEXT)") + tk.MustExec(`INSERT INTO t VALUES ("id");`) + id, ps, _, err := tk.Session().PrepareStmt("select id+? from t") + ctx := context.Background() + require.NoError(t, err) + require.Equal(t, uint32(1), id) + require.Equal(t, 1, ps) + tk.MustExec(`set @a=1`) + rs, err := tk.Session().ExecutePreparedStmt(ctx, id, []types.Datum{types.NewDatum("1")}) + require.NoError(t, err) + require.NoError(t, rs.Close()) + err = tk.Session().DropPreparedStmt(id) + require.NoError(t, err) + + tk.MustExec("prepare stmt from 'select 1+?'") + tk.MustExec("set @v1=100") + tk.MustQuery("execute stmt using @v1").Check(testkit.Rows("101")) + + tk.MustExec("set @v2=200") + tk.MustQuery("execute stmt using @v2").Check(testkit.Rows("201")) + + tk.MustExec("set @v3=300") + tk.MustQuery("execute stmt using @v3").Check(testkit.Rows("301")) + tk.MustExec("deallocate prepare stmt") + + // Execute prepared statements for more than one time. + tk.MustExec("create table multiexec (a int, b int)") + tk.MustExec("insert multiexec values (1, 1), (2, 2)") + id, _, _, err = tk.Session().PrepareStmt("select a from multiexec where b = ? order by b") + require.NoError(t, err) + rs, err = tk.Session().ExecutePreparedStmt(ctx, id, []types.Datum{types.NewDatum(1)}) + require.NoError(t, err) + require.NoError(t, rs.Close()) + rs, err = tk.Session().ExecutePreparedStmt(ctx, id, []types.Datum{types.NewDatum(2)}) + require.NoError(t, err) + require.NoError(t, rs.Close()) +} + +func TestSpecifyIndexPrefixLength(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + _, err := tk.Exec("create table t (c1 char, index(c1(3)));") + // ERROR 1089 (HY000): Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys + require.Error(t, err) + + _, err = tk.Exec("create table t (c1 int, index(c1(3)));") + // ERROR 1089 (HY000): Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys + require.Error(t, err) + + _, err = tk.Exec("create table t (c1 bit(10), index(c1(3)));") + // ERROR 1089 (HY000): Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys + require.Error(t, err) + + tk.MustExec("create table t (c1 char, c2 int, c3 bit(10));") + + _, err = tk.Exec("create index idx_c1 on t (c1(3));") + // ERROR 1089 (HY000): Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys + require.Error(t, err) + + _, err = tk.Exec("create index idx_c1 on t (c2(3));") + // ERROR 1089 (HY000): Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys + require.Error(t, err) + + _, err = tk.Exec("create index idx_c1 on t (c3(3));") + // ERROR 1089 (HY000): Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys + require.Error(t, err) + + tk.MustExec("drop table if exists t;") + + _, err = tk.Exec("create table t (c1 int, c2 blob, c3 varchar(64), index(c2));") + // ERROR 1170 (42000): BLOB/TEXT column 'c2' used in key specification without a key length + require.Error(t, err) + + tk.MustExec("create table t (c1 int, c2 blob, c3 varchar(64));") + _, err = tk.Exec("create index idx_c1 on t (c2);") + // ERROR 1170 (42000): BLOB/TEXT column 'c2' used in key specification without a key length + require.Error(t, err) + + _, err = tk.Exec("create index idx_c1 on t (c2(555555));") + // ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes + require.Error(t, err) + + _, err = tk.Exec("create index idx_c1 on t (c1(5))") + // ERROR 1089 (HY000): Incorrect prefix key; + // the used key part isn't a string, the used length is longer than the key part, + // or the storage engine doesn't support unique prefix keys + require.Error(t, err) + + tk.MustExec("create index idx_c1 on t (c1);") + tk.MustExec("create index idx_c2 on t (c2(3));") + tk.MustExec("create unique index idx_c3 on t (c3(5));") + + tk.MustExec("insert into t values (3, 'abc', 'def');") + tk.MustQuery("select c2 from t where c2 = 'abc';").Check(testkit.Rows("abc")) + + tk.MustExec("insert into t values (4, 'abcd', 'xxx');") + tk.MustExec("insert into t values (4, 'abcf', 'yyy');") + tk.MustQuery("select c2 from t where c2 = 'abcf';").Check(testkit.Rows("abcf")) + tk.MustQuery("select c2 from t where c2 = 'abcd';").Check(testkit.Rows("abcd")) + + tk.MustExec("insert into t values (4, 'ignore', 'abcdeXXX');") + _, err = tk.Exec("insert into t values (5, 'ignore', 'abcdeYYY');") + // ERROR 1062 (23000): Duplicate entry 'abcde' for key 'idx_c3' + require.Error(t, err) + tk.MustQuery("select c3 from t where c3 = 'abcde';").Check(testkit.Rows()) + + tk.MustExec("delete from t where c3 = 'abcdeXXX';") + tk.MustExec("delete from t where c2 = 'abc';") + + tk.MustQuery("select c2 from t where c2 > 'abcd';").Check(testkit.Rows("abcf")) + tk.MustQuery("select c2 from t where c2 < 'abcf';").Check(testkit.Rows("abcd")) + tk.MustQuery("select c2 from t where c2 >= 'abcd';").Check(testkit.Rows("abcd", "abcf")) + tk.MustQuery("select c2 from t where c2 <= 'abcf';").Check(testkit.Rows("abcd", "abcf")) + tk.MustQuery("select c2 from t where c2 != 'abc';").Check(testkit.Rows("abcd", "abcf")) + tk.MustQuery("select c2 from t where c2 != 'abcd';").Check(testkit.Rows("abcf")) + + tk.MustExec("drop table if exists t1;") + tk.MustExec("create table t1 (a int, b char(255), key(a, b(20)));") + tk.MustExec("insert into t1 values (0, '1');") + tk.MustExec("update t1 set b = b + 1 where a = 0;") + tk.MustQuery("select b from t1 where a = 0;").Check(testkit.Rows("2")) + + // test union index. + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a text, b text, c int, index (a(3), b(3), c));") + tk.MustExec("insert into t values ('abc', 'abcd', 1);") + tk.MustExec("insert into t values ('abcx', 'abcf', 2);") + tk.MustExec("insert into t values ('abcy', 'abcf', 3);") + tk.MustExec("insert into t values ('bbc', 'abcd', 4);") + tk.MustExec("insert into t values ('bbcz', 'abcd', 5);") + tk.MustExec("insert into t values ('cbck', 'abd', 6);") + tk.MustQuery("select c from t where a = 'abc' and b <= 'abc';").Check(testkit.Rows()) + tk.MustQuery("select c from t where a = 'abc' and b <= 'abd';").Check(testkit.Rows("1")) + tk.MustQuery("select c from t where a < 'cbc' and b > 'abcd';").Check(testkit.Rows("2", "3")) + tk.MustQuery("select c from t where a <= 'abd' and b > 'abc';").Check(testkit.Rows("1", "2", "3")) + tk.MustQuery("select c from t where a < 'bbcc' and b = 'abcd';").Check(testkit.Rows("1", "4")) + tk.MustQuery("select c from t where a > 'bbcf';").Check(testkit.Rows("5", "6")) +} + +func TestResultField(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (id int);") + + tk.MustExec(`INSERT INTO t VALUES (1);`) + tk.MustExec(`INSERT INTO t VALUES (2);`) + r, err := tk.Exec(`SELECT count(*) from t;`) + require.NoError(t, err) + fields := r.Fields() + require.NoError(t, err) + require.Len(t, fields, 1) + field := fields[0].Column + require.Equal(t, mysql.TypeLonglong, field.GetType()) + require.Equal(t, 21, field.GetFlen()) +} + +// Testcase for https://github.com/pingcap/tidb/issues/325 +func TestResultType(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + rs, err := tk.Exec(`select cast(null as char(30))`) + require.NoError(t, err) + req := rs.NewChunk(nil) + err = rs.Next(context.Background(), req) + require.NoError(t, err) + require.True(t, req.GetRow(0).IsNull(0)) + require.Equal(t, mysql.TypeVarString, rs.Fields()[0].Column.FieldType.GetType()) +} + +func TestFieldText(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (a int)") + tests := []struct { + sql string + field string + }{ + {"select distinct(a) from t", "a"}, + {"select (1)", "1"}, + {"select (1+1)", "(1+1)"}, + {"select a from t", "a"}, + {"select ((a+1)) from t", "((a+1))"}, + {"select 1 /*!32301 +1 */;", "1 +1 "}, + {"select /*!32301 1 +1 */;", "1 +1 "}, + {"/*!32301 select 1 +1 */;", "1 +1 "}, + {"select 1 + /*!32301 1 +1 */;", "1 + 1 +1 "}, + {"select 1 /*!32301 + 1, 1 */;", "1 + 1"}, + {"select /*!32301 1, 1 +1 */;", "1"}, + {"select /*!32301 1 + 1, */ +1;", "1 + 1"}, + } + for _, tt := range tests { + result, err := tk.Exec(tt.sql) + require.NoError(t, err) + require.Equal(t, tt.field, result.Fields()[0].ColumnAsName.O) + } +} + +func TestIndexMaxLength(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create database test_index_max_length") + tk.MustExec("use test_index_max_length") + + // create simple index at table creation + tk.MustGetErrCode("create table t (c1 varchar(3073), index(c1)) charset = ascii;", mysql.ErrTooLongKey) + + // create simple index after table creation + tk.MustExec("create table t (c1 varchar(3073)) charset = ascii;") + tk.MustGetErrCode("create index idx_c1 on t(c1) ", mysql.ErrTooLongKey) + tk.MustExec("drop table t;") + + // create compound index at table creation + tk.MustGetErrCode("create table t (c1 varchar(3072), c2 varchar(1), index(c1, c2)) charset = ascii;", mysql.ErrTooLongKey) + tk.MustGetErrCode("create table t (c1 varchar(3072), c2 char(1), index(c1, c2)) charset = ascii;", mysql.ErrTooLongKey) + tk.MustGetErrCode("create table t (c1 varchar(3072), c2 char, index(c1, c2)) charset = ascii;", mysql.ErrTooLongKey) + tk.MustGetErrCode("create table t (c1 varchar(3072), c2 date, index(c1, c2)) charset = ascii;", mysql.ErrTooLongKey) + tk.MustGetErrCode("create table t (c1 varchar(3069), c2 timestamp(1), index(c1, c2)) charset = ascii;", mysql.ErrTooLongKey) + + tk.MustExec("create table t (c1 varchar(3068), c2 bit(26), index(c1, c2)) charset = ascii;") // 26 bit = 4 bytes + tk.MustExec("drop table t;") + tk.MustExec("create table t (c1 varchar(3068), c2 bit(32), index(c1, c2)) charset = ascii;") // 32 bit = 4 bytes + tk.MustExec("drop table t;") + tk.MustGetErrCode("create table t (c1 varchar(3068), c2 bit(33), index(c1, c2)) charset = ascii;", mysql.ErrTooLongKey) + + // create compound index after table creation + tk.MustExec("create table t (c1 varchar(3072), c2 varchar(1)) charset = ascii;") + tk.MustGetErrCode("create index idx_c1_c2 on t(c1, c2);", mysql.ErrTooLongKey) + tk.MustExec("drop table t;") + + tk.MustExec("create table t (c1 varchar(3072), c2 char(1)) charset = ascii;") + tk.MustGetErrCode("create index idx_c1_c2 on t(c1, c2);", mysql.ErrTooLongKey) + tk.MustExec("drop table t;") + + tk.MustExec("create table t (c1 varchar(3072), c2 char) charset = ascii;") + tk.MustGetErrCode("create index idx_c1_c2 on t(c1, c2);", mysql.ErrTooLongKey) + tk.MustExec("drop table t;") + + tk.MustExec("create table t (c1 varchar(3072), c2 date) charset = ascii;") + tk.MustGetErrCode("create index idx_c1_c2 on t(c1, c2);", mysql.ErrTooLongKey) + tk.MustExec("drop table t;") + + tk.MustExec("create table t (c1 varchar(3069), c2 timestamp(1)) charset = ascii;") + tk.MustGetErrCode("create index idx_c1_c2 on t(c1, c2);", mysql.ErrTooLongKey) + tk.MustExec("drop table t;") + + // Test charsets other than `ascii`. + assertCharsetLimit := func(charset string, bytesPerChar int) { + base := 3072 / bytesPerChar + tk.MustGetErrCode(fmt.Sprintf("create table t (a varchar(%d) primary key) charset=%s", base+1, charset), mysql.ErrTooLongKey) + tk.MustExec(fmt.Sprintf("create table t (a varchar(%d) primary key) charset=%s", base, charset)) + tk.MustExec("drop table if exists t") + } + assertCharsetLimit("binary", 1) + assertCharsetLimit("latin1", 1) + assertCharsetLimit("utf8", 3) + assertCharsetLimit("utf8mb4", 4) + + // Test types bit length limit. + assertTypeLimit := func(tp string, limitBitLength int) { + base := 3072 - limitBitLength + tk.MustGetErrCode(fmt.Sprintf("create table t (a blob(10000), b %s, index idx(a(%d), b))", tp, base+1), mysql.ErrTooLongKey) + tk.MustExec(fmt.Sprintf("create table t (a blob(10000), b %s, index idx(a(%d), b))", tp, base)) + tk.MustExec("drop table if exists t") + } + + assertTypeLimit("tinyint", 1) + assertTypeLimit("smallint", 2) + assertTypeLimit("mediumint", 3) + assertTypeLimit("int", 4) + assertTypeLimit("integer", 4) + assertTypeLimit("bigint", 8) + assertTypeLimit("float", 4) + assertTypeLimit("float(24)", 4) + assertTypeLimit("float(25)", 8) + assertTypeLimit("decimal(9)", 4) + assertTypeLimit("decimal(10)", 5) + assertTypeLimit("decimal(17)", 8) + assertTypeLimit("year", 1) + assertTypeLimit("date", 3) + assertTypeLimit("time", 3) + assertTypeLimit("datetime", 8) + assertTypeLimit("timestamp", 4) +} + +func TestIndexColumnLength(t *testing.T) { + store, dom, clean := realtikvtest.CreateMockStoreAndDomainAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (c1 int, c2 blob);") + tk.MustExec("create index idx_c1 on t(c1);") + tk.MustExec("create index idx_c2 on t(c2(6));") + + is := dom.InfoSchema() + tab, err2 := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) + require.NoError(t, err2) + + idxC1Cols := tables.FindIndexByColName(tab, "c1").Meta().Columns + require.Equal(t, types.UnspecifiedLength, idxC1Cols[0].Length) + + idxC2Cols := tables.FindIndexByColName(tab, "c2").Meta().Columns + require.Equal(t, 6, idxC2Cols[0].Length) +} + +func TestIgnoreForeignKey(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + sqlText := `CREATE TABLE address ( + id bigint(20) NOT NULL AUTO_INCREMENT, + user_id bigint(20) NOT NULL, + PRIMARY KEY (id), + CONSTRAINT FK_7rod8a71yep5vxasb0ms3osbg FOREIGN KEY (user_id) REFERENCES waimaiqa.user (id), + INDEX FK_7rod8a71yep5vxasb0ms3osbg (user_id) comment '' + ) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ROW_FORMAT=COMPACT COMMENT='' CHECKSUM=0 DELAY_KEY_WRITE=0;` + tk.MustExec(sqlText) +} + +// TestISColumns tests information_schema.columns. +func TestISColumns(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("select ORDINAL_POSITION from INFORMATION_SCHEMA.COLUMNS;") + tk.MustQuery("SELECT CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.CHARACTER_SETS WHERE CHARACTER_SET_NAME = 'utf8mb4'").Check(testkit.Rows("utf8mb4")) +} + +func TestMultiStmts(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1; create table t1(id int ); insert into t1 values (1);") + tk.MustQuery("select * from t1;").Check(testkit.Rows("1")) +} + +func TestLastExecuteDDLFlag(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1(id int)") + require.NotNil(t, tk.Session().Value(sessionctx.LastExecuteDDL)) + tk.MustExec("insert into t1 values (1)") + require.Nil(t, tk.Session().Value(sessionctx.LastExecuteDDL)) +} + +func TestDecimal(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t (a decimal unique);") + tk.MustExec("insert t values ('100');") + _, err := tk.Exec("insert t values ('1e2');") + require.NotNil(t, err) +} + +func TestParser(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + // test for https://github.com/pingcap/tidb/pull/177 + tk.MustExec("CREATE TABLE `t1` ( `a` char(3) NOT NULL default '', `b` char(3) NOT NULL default '', `c` char(3) NOT NULL default '', PRIMARY KEY (`a`,`b`,`c`)) ENGINE=InnoDB;") + tk.MustExec("CREATE TABLE `t2` ( `a` char(3) NOT NULL default '', `b` char(3) NOT NULL default '', `c` char(3) NOT NULL default '', PRIMARY KEY (`a`,`b`,`c`)) ENGINE=InnoDB;") + tk.MustExec(`INSERT INTO t1 VALUES (1,1,1);`) + tk.MustExec(`INSERT INTO t2 VALUES (1,1,1);`) + tk.MustExec(`PREPARE my_stmt FROM "SELECT t1.b, count(*) FROM t1 group by t1.b having count(*) > ALL (SELECT COUNT(*) FROM t2 WHERE t2.a=1 GROUP By t2.b)";`) + tk.MustExec(`EXECUTE my_stmt;`) + tk.MustExec(`EXECUTE my_stmt;`) + tk.MustExec(`deallocate prepare my_stmt;`) + tk.MustExec(`drop table t1,t2;`) +} + +func TestOnDuplicate(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + // test for https://github.com/pingcap/tidb/pull/454 + tk.MustExec("drop table if exists t") + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 (c1 int, c2 int, c3 int);") + tk.MustExec("insert into t1 set c1=1, c2=2, c3=1;") + tk.MustExec("create table t (c1 int, c2 int, c3 int, primary key (c1));") + tk.MustExec("insert into t set c1=1, c2=4;") + tk.MustExec("insert into t select * from t1 limit 1 on duplicate key update c3=3333;") +} + +func TestReplace(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + // test for https://github.com/pingcap/tidb/pull/456 + tk.MustExec("drop table if exists t") + tk.MustExec("drop table if exists t1") + tk.MustExec("create table t1 (c1 int, c2 int, c3 int);") + tk.MustExec("replace into t1 set c1=1, c2=2, c3=1;") + tk.MustExec("create table t (c1 int, c2 int, c3 int, primary key (c1));") + tk.MustExec("replace into t set c1=1, c2=4;") + tk.MustExec("replace into t select * from t1 limit 1;") +} + +func TestDelete(t *testing.T) { + // test for https://github.com/pingcap/tidb/pull/1135 + + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("create database test1") + tk1.MustExec("use test1") + tk1.MustExec("create table t (F1 VARCHAR(30));") + tk1.MustExec("insert into t (F1) values ('1'), ('4');") + + tk.MustExec("create table t (F1 VARCHAR(30));") + tk.MustExec("insert into t (F1) values ('1'), ('2');") + tk.MustExec("delete m1 from t m2,t m1 where m1.F1>1;") + tk.MustQuery("select * from t;").Check(testkit.Rows("1")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (F1 VARCHAR(30));") + tk.MustExec("insert into t (F1) values ('1'), ('2');") + tk.MustExec("delete m1 from t m1,t m2 where true and m1.F1<2;") + tk.MustQuery("select * from t;").Check(testkit.Rows("2")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (F1 VARCHAR(30));") + tk.MustExec("insert into t (F1) values ('1'), ('2');") + tk.MustExec("delete m1 from t m1,t m2 where false;") + tk.MustQuery("select * from t;").Check(testkit.Rows("1", "2")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (F1 VARCHAR(30));") + tk.MustExec("insert into t (F1) values ('1'), ('2');") + tk.MustExec("delete m1, m2 from t m1,t m2 where m1.F1>m2.F1;") + tk.MustQuery("select * from t;").Check(testkit.Rows()) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (F1 VARCHAR(30));") + tk.MustExec("insert into t (F1) values ('1'), ('2');") + tk.MustExec("delete test1.t from test1.t inner join test.t where test1.t.F1 > test.t.F1") + tk1.MustQuery("select * from t;").Check(testkit.Rows("1")) +} + +func TestResetCtx(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") + + tk.MustExec("create table t (i int auto_increment not null key);") + tk.MustExec("insert into t values (1);") + tk.MustExec("set @@tidb_disable_txn_auto_retry = 0") + tk.MustExec("begin;") + tk.MustExec("insert into t values (10);") + tk.MustExec("update t set i = i + row_count();") + tk.MustQuery("select * from t;").Check(testkit.Rows("2", "11")) + + tk1.MustExec("update t set i = 0 where i = 1;") + tk1.MustQuery("select * from t;").Check(testkit.Rows("0")) + + tk.MustExec("commit;") + tk.MustQuery("select * from t;").Check(testkit.Rows("1", "11")) + + tk.MustExec("delete from t where i = 11;") + tk.MustExec("begin;") + tk.MustExec("insert into t values ();") + tk.MustExec("update t set i = i + last_insert_id() + 1;") + tk.MustQuery("select * from t;").Check(testkit.Rows("14", "25")) + + tk1.MustExec("update t set i = 0 where i = 1;") + tk1.MustQuery("select * from t;").Check(testkit.Rows("0")) + + tk.MustExec("commit;") + tk.MustQuery("select * from t;").Check(testkit.Rows("13", "25")) +} + +// test for https://github.com/pingcap/tidb/pull/461 +func TestUnique(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk1 := testkit.NewTestKit(t, store) + tk1.MustExec("use test") + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + + tk.MustExec("set @@tidb_disable_txn_auto_retry = 0") + tk1.MustExec("set @@tidb_disable_txn_auto_retry = 0") + tk.MustExec(`CREATE TABLE test ( id int(11) UNSIGNED NOT NULL AUTO_INCREMENT, val int UNIQUE, PRIMARY KEY (id)); `) + tk.MustExec("begin;") + tk.MustExec("insert into test(id, val) values(1, 1);") + tk1.MustExec("begin;") + tk1.MustExec("insert into test(id, val) values(2, 2);") + tk2.MustExec("begin;") + tk2.MustExec("insert into test(id, val) values(1, 2);") + tk2.MustExec("commit;") + _, err := tk.Exec("commit") + require.Error(t, err) + // Check error type and error message + require.True(t, terror.ErrorEqual(err, kv.ErrKeyExists), fmt.Sprintf("err %v", err)) + require.Equal(t, "previous statement: insert into test(id, val) values(1, 1);: [kv:1062]Duplicate entry '1' for key 'PRIMARY'", err.Error()) + + _, err = tk1.Exec("commit") + require.Error(t, err) + require.True(t, terror.ErrorEqual(err, kv.ErrKeyExists), fmt.Sprintf("err %v", err)) + require.Equal(t, "previous statement: insert into test(id, val) values(2, 2);: [kv:1062]Duplicate entry '2' for key 'val'", err.Error()) + + // Test for https://github.com/pingcap/tidb/issues/463 + tk.MustExec("drop table test;") + tk.MustExec(`CREATE TABLE test ( + id int(11) UNSIGNED NOT NULL AUTO_INCREMENT, + val int UNIQUE, + PRIMARY KEY (id) + );`) + tk.MustExec("insert into test(id, val) values(1, 1);") + _, err = tk.Exec("insert into test(id, val) values(2, 1);") + require.Error(t, err) + tk.MustExec("insert into test(id, val) values(2, 2);") + + tk.MustExec("begin;") + tk.MustExec("insert into test(id, val) values(3, 3);") + _, err = tk.Exec("insert into test(id, val) values(4, 3);") + require.Error(t, err) + tk.MustExec("insert into test(id, val) values(4, 4);") + tk.MustExec("commit;") + + tk1.MustExec("begin;") + tk1.MustExec("insert into test(id, val) values(5, 6);") + tk.MustExec("begin;") + tk.MustExec("insert into test(id, val) values(20, 6);") + tk.MustExec("commit;") + _, _ = tk1.Exec("commit") + tk1.MustExec("insert into test(id, val) values(5, 5);") + + tk.MustExec("drop table test;") + tk.MustExec(`CREATE TABLE test ( + id int(11) UNSIGNED NOT NULL AUTO_INCREMENT, + val1 int UNIQUE, + val2 int UNIQUE, + PRIMARY KEY (id) + );`) + tk.MustExec("insert into test(id, val1, val2) values(1, 1, 1);") + tk.MustExec("insert into test(id, val1, val2) values(2, 2, 2);") + _, _ = tk.Exec("update test set val1 = 3, val2 = 2 where id = 1;") + tk.MustExec("insert into test(id, val1, val2) values(3, 3, 3);") +} + +// Test for https://github.com/pingcap/tidb/issues/1114 +func TestSet(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @tmp = 0") + tk.MustExec("set @tmp := @tmp + 1") + tk.MustQuery("select @tmp").Check(testkit.Rows("1")) + tk.MustQuery("select @tmp1 = 1, @tmp2 := 2").Check(testkit.Rows(" 2")) + tk.MustQuery("select @tmp1 := 11, @tmp2").Check(testkit.Rows("11 2")) + + tk.MustExec("drop table if exists t") + tk.MustExec("create table t (c int);") + tk.MustExec("insert into t values (1),(2);") + tk.MustExec("update t set c = 3 WHERE c = @var:= 1") + tk.MustQuery("select * from t").Check(testkit.Rows("3", "2")) + tk.MustQuery("select @tmp := count(*) from t").Check(testkit.Rows("2")) + tk.MustQuery("select @tmp := c-2 from t where c=3").Check(testkit.Rows("1")) +} + +func TestMySQLTypes(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustQuery(`select 0x01 + 1, x'4D7953514C' = "MySQL"`).Check(testkit.Rows("2 1")) + tk.MustQuery(`select 0b01 + 1, 0b01000001 = "A"`).Check(testkit.Rows("2 1")) +} + +func TestIssue986(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + sqlText := `CREATE TABLE address ( + id bigint(20) NOT NULL AUTO_INCREMENT, + PRIMARY KEY (id));` + tk.MustExec(sqlText) + tk.MustExec(`insert into address values ('10')`) +} + +func TestCast(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustQuery("select cast(0.5 as unsigned)") + tk.MustQuery("select cast(-0.5 as signed)") + tk.MustQuery("select hex(cast(0x10 as binary(2)))").Check(testkit.Rows("1000")) +} + +func TestTableInfoMeta(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + checkResult := func(affectedRows uint64, insertID uint64) { + gotRows := tk.Session().AffectedRows() + require.Equal(t, affectedRows, gotRows) + + gotID := tk.Session().LastInsertID() + require.Equal(t, insertID, gotID) + } + + // create table + tk.MustExec("CREATE TABLE tbl_test(id INT NOT NULL DEFAULT 1, name varchar(255), PRIMARY KEY(id));") + + // insert data + tk.MustExec(`INSERT INTO tbl_test VALUES (1, "hello");`) + checkResult(1, 0) + + tk.MustExec(`INSERT INTO tbl_test VALUES (2, "hello");`) + checkResult(1, 0) + + tk.MustExec(`UPDATE tbl_test SET name = "abc" where id = 2;`) + checkResult(1, 0) + + tk.MustExec(`DELETE from tbl_test where id = 2;`) + checkResult(1, 0) + + // select data + tk.MustQuery("select * from tbl_test").Check(testkit.Rows("1 hello")) +} + +func TestCaseInsensitive(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + + tk.MustExec("create table T (a text, B int)") + tk.MustExec("insert t (A, b) values ('aaa', 1)") + rs, err := tk.Exec("select * from t") + require.NoError(t, err) + fields := rs.Fields() + require.Equal(t, "a", fields[0].ColumnAsName.O) + require.Equal(t, "B", fields[1].ColumnAsName.O) + require.NoError(t, rs.Close()) + + rs, err = tk.Exec("select A, b from t") + require.NoError(t, err) + fields = rs.Fields() + require.Equal(t, "A", fields[0].ColumnAsName.O) + require.Equal(t, "b", fields[1].ColumnAsName.O) + require.NoError(t, rs.Close()) + + rs, err = tk.Exec("select a as A from t where A > 0") + require.NoError(t, err) + fields = rs.Fields() + require.Equal(t, "A", fields[0].ColumnAsName.O) + require.NoError(t, rs.Close()) + + tk.MustExec("update T set b = B + 1") + tk.MustExec("update T set B = b + 1") + tk.MustQuery("select b from T").Check(testkit.Rows("3")) +} + +func TestLastMessage(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(id TEXT)") + + // Insert + tk.MustExec(`INSERT INTO t VALUES ("a");`) + tk.CheckLastMessage("") + tk.MustExec(`INSERT INTO t VALUES ("b"), ("c");`) + tk.CheckLastMessage("Records: 2 Duplicates: 0 Warnings: 0") + + // Update + tk.MustExec(`UPDATE t set id = 'c' where id = 'a';`) + require.Equal(t, uint64(1), tk.Session().AffectedRows()) + tk.CheckLastMessage("Rows matched: 1 Changed: 1 Warnings: 0") + tk.MustExec(`UPDATE t set id = 'a' where id = 'a';`) + require.Equal(t, uint64(0), tk.Session().AffectedRows()) + tk.CheckLastMessage("Rows matched: 0 Changed: 0 Warnings: 0") + + // Replace + tk.MustExec(`drop table if exists t, t1; + create table t (c1 int PRIMARY KEY, c2 int); + create table t1 (a1 int, a2 int);`) + tk.MustExec(`INSERT INTO t VALUES (1,1)`) + tk.MustExec(`REPLACE INTO t VALUES (2,2)`) + tk.CheckLastMessage("") + tk.MustExec(`INSERT INTO t1 VALUES (1,10), (3,30);`) + tk.CheckLastMessage("Records: 2 Duplicates: 0 Warnings: 0") + tk.MustExec(`REPLACE INTO t SELECT * from t1`) + tk.CheckLastMessage("Records: 2 Duplicates: 1 Warnings: 0") + + // Check insert with CLIENT_FOUND_ROWS is set + tk.Session().SetClientCapability(mysql.ClientFoundRows) + tk.MustExec(`drop table if exists t, t1; + create table t (c1 int PRIMARY KEY, c2 int); + create table t1 (a1 int, a2 int);`) + tk.MustExec(`INSERT INTO t1 VALUES (1, 10), (2, 2), (3, 30);`) + tk.MustExec(`INSERT INTO t1 VALUES (1, 10), (2, 20), (3, 30);`) + tk.MustExec(`INSERT INTO t SELECT * FROM t1 ON DUPLICATE KEY UPDATE c2=a2;`) + tk.CheckLastMessage("Records: 6 Duplicates: 3 Warnings: 0") +} diff --git a/tests/realtikvtest/txntest/txn_test.go b/tests/realtikvtest/txntest/txn_test.go index 7dc1f69f5f80d..6a3133e4430f1 100644 --- a/tests/realtikvtest/txntest/txn_test.go +++ b/tests/realtikvtest/txntest/txn_test.go @@ -149,3 +149,33 @@ func TestSetTransactionIsolationOneSho(t *testing.T) { _, err = tk.Session().Execute(ctx, "set transaction isolation level read committed") require.Error(t, err) } + +func TestStatementErrorInTransaction(t *testing.T) { + store, clean := realtikvtest.CreateMockStoreAndSetup(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table statement_side_effect (c int primary key)") + tk.MustExec("begin") + tk.MustExec("insert into statement_side_effect values (1)") + require.Error(t, tk.ExecToErr("insert into statement_side_effect value (2),(3),(4),(1)")) + tk.MustQuery(`select * from statement_side_effect`).Check(testkit.Rows("1")) + tk.MustExec("commit") + tk.MustQuery(`select * from statement_side_effect`).Check(testkit.Rows("1")) + + tk.MustExec("drop table if exists test;") + tk.MustExec(`create table test ( + a int(11) DEFAULT NULL, + b int(11) DEFAULT NULL + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;`) + tk.MustExec("insert into test values (1, 2), (1, 2), (1, 1), (1, 1);") + + tk.MustExec("start transaction;") + // In the transaction, statement error should not rollback the transaction. + require.Error(t, tk.ExecToErr("update tset set b=11 where a=1 and b=2;")) + // Test for a bug that last line rollback and exit transaction, this line autocommit. + tk.MustExec("update test set b = 11 where a = 1 and b = 2;") + tk.MustExec("rollback") + tk.MustQuery("select * from test where a = 1 and b = 11").Check(testkit.Rows()) +}