diff --git a/executor/executor_test.go b/executor/executor_test.go index 98b5e4f6cc..34faa7730b 100644 --- a/executor/executor_test.go +++ b/executor/executor_test.go @@ -14,6 +14,7 @@ package executor_test import ( + "fmt" "strings" "testing" "time" @@ -161,6 +162,584 @@ func (s *testSuite) TestPrepared(c *C) { exec.Close() } +func (s *testSuite) fillData(tk *testkit.TestKit, table string) { + tk.MustExec("use test") + tk.MustExec(fmt.Sprintf("create table %s(id int not null default 1, name varchar(255), PRIMARY KEY(id));", table)) + + // insert data + tk.MustExec(fmt.Sprintf("insert INTO %s VALUES (1, \"hello\");", table)) + tk.CheckExecResult(1, 0) + tk.MustExec(fmt.Sprintf("insert into %s values (2, \"hello\");", table)) + tk.CheckExecResult(1, 0) +} + +func (s *testSuite) TestDelete(c *C) { + tk := testkit.NewTestKit(c, s.store) + s.fillData(tk, "delete_test") + + tk.MustExec(`update delete_test set name = "abc" where id = 2;`) + tk.CheckExecResult(1, 0) + + tk.MustExec(`delete from delete_test where id = 2 limit 1;`) + tk.CheckExecResult(1, 0) + + // Test delete with false condition + tk.MustExec(`delete from delete_test where 0;`) + tk.CheckExecResult(0, 0) + + tk.MustExec("insert into delete_test values (2, 'abc')") + tk.MustExec(`delete from delete_test where delete_test.id = 2 limit 1`) + tk.CheckExecResult(1, 0) + + // Select data + tk.MustExec("begin") + rows := tk.MustQuery(`SELECT * from delete_test limit 2;`) + rowStr := fmt.Sprintf("%v %v", "1", []byte("hello")) + rows.Check(testkit.Rows(rowStr)) + tk.MustExec("commit") + + tk.MustExec(`delete from delete_test ;`) + tk.CheckExecResult(1, 0) +} + +func (s *testSuite) fillDataMultiTable(tk *testkit.TestKit) { + tk.MustExec("use test") + tk.MustExec("drop table if exists t1, t2, t3") + // Create and fill table t1 + tk.MustExec("create table t1 (id int, data int);") + tk.MustExec("insert into t1 values (11, 121), (12, 122), (13, 123);") + tk.CheckExecResult(3, 0) + // Create and fill table t2 + tk.MustExec("create table t2 (id int, data int);") + tk.MustExec("insert into t2 values (11, 221), (22, 222), (23, 223);") + tk.CheckExecResult(3, 0) + // Create and fill table t3 + tk.MustExec("create table t3 (id int, data int);") + tk.MustExec("insert into t3 values (11, 321), (22, 322), (23, 323);") + tk.CheckExecResult(3, 0) +} + +func (s *testSuite) TestMultiTableDelete(c *C) { + tk := testkit.NewTestKit(c, s.store) + s.fillDataMultiTable(tk) + + tk.MustExec(`delete t1, t2 from t1 inner join t2 inner join t3 where t1.id=t2.id and t2.id=t3.id;`) + tk.CheckExecResult(2, 0) + + // Select data + r := tk.MustQuery("select * from t3") + c.Assert(r.Rows(), HasLen, 3) +} + +func (s *testSuite) TestQualifedDelete(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("drop table if exists t2") + tk.MustExec("create table t1 (c1 int, c2 int, index (c1))") + tk.MustExec("create table t2 (c1 int, c2 int)") + tk.MustExec("insert into t1 values (1, 1), (2, 2)") + + // delete with index + tk.MustExec("delete from t1 where t1.c1 = 1") + tk.CheckExecResult(1, 0) + + // delete with no index + tk.MustExec("delete from t1 where t1.c2 = 2") + tk.CheckExecResult(1, 0) + + r := tk.MustQuery("select * from t1") + c.Assert(r.Rows(), HasLen, 0) + + _, err := tk.Exec("delete from t1 as a where a.c1 = 1") + c.Assert(err, NotNil) + + tk.MustExec("insert into t1 values (1, 1), (2, 2)") + tk.MustExec("insert into t2 values (2, 1), (3,1)") + tk.MustExec("delete t1, t2 from t1 join t2 where t1.c1 = t2.c2") + tk.CheckExecResult(3, 0) + + tk.MustExec("insert into t2 values (2, 1), (3,1)") + tk.MustExec("delete a, b from t1 as a join t2 as b where a.c2 = b.c1") + tk.CheckExecResult(2, 0) + + _, err = tk.Exec("delete t1, t2 from t1 as a join t2 as b where a.c2 = b.c1") + c.Assert(err, NotNil) + + tk.MustExec("drop table t1, t2") +} + +func (s *testSuite) TestInsert(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + testSQL := `drop table if exists insert_test;create table insert_test (id int PRIMARY KEY AUTO_INCREMENT, c1 int, c2 int, c3 int default 1);` + tk.MustExec(testSQL) + testSQL = `insert insert_test (c1) values (1),(2),(NULL);` + tk.MustExec(testSQL) + + errInsertSelectSQL := `insert insert_test (c1) values ();` + tk.MustExec("begin") + _, err := tk.Exec(errInsertSelectSQL) + c.Assert(err, NotNil) + tk.MustExec("rollback") + + errInsertSelectSQL = `insert insert_test (c1, c2) values (1,2),(1);` + tk.MustExec("begin") + _, err = tk.Exec(errInsertSelectSQL) + c.Assert(err, NotNil) + tk.MustExec("rollback") + + errInsertSelectSQL = `insert insert_test (xxx) values (3);` + tk.MustExec("begin") + _, err = tk.Exec(errInsertSelectSQL) + c.Assert(err, NotNil) + tk.MustExec("rollback") + + errInsertSelectSQL = `insert insert_test_xxx (c1) values ();` + tk.MustExec("begin") + _, err = tk.Exec(errInsertSelectSQL) + c.Assert(err, NotNil) + tk.MustExec("rollback") + + insertSetSQL := `insert insert_test set c1 = 3;` + tk.MustExec(insertSetSQL) + + errInsertSelectSQL = `insert insert_test set c1 = 4, c1 = 5;` + tk.MustExec("begin") + _, err = tk.Exec(errInsertSelectSQL) + c.Assert(err, NotNil) + tk.MustExec("rollback") + + errInsertSelectSQL = `insert insert_test set xxx = 6;` + tk.MustExec("begin") + _, err = tk.Exec(errInsertSelectSQL) + c.Assert(err, NotNil) + tk.MustExec("rollback") + + insertSelectSQL := `create table insert_test_1 (id int, c1 int);` + tk.MustExec(insertSelectSQL) + insertSelectSQL = `insert insert_test_1 select id, c1 from insert_test;` + tk.MustExec(insertSelectSQL) + + insertSelectSQL = `create table insert_test_2 (id int, c1 int);` + tk.MustExec(insertSelectSQL) + insertSelectSQL = `insert insert_test_1 select id, c1 from insert_test union select id * 10, c1 * 10 from insert_test;` + tk.MustExec(insertSelectSQL) + + errInsertSelectSQL = `insert insert_test_1 select c1 from insert_test;` + tk.MustExec("begin") + _, err = tk.Exec(errInsertSelectSQL) + c.Assert(err, NotNil) + tk.MustExec("rollback") + + insertSQL := `insert into insert_test (id, c2) values (1, 1) on duplicate key update c2=10;` + tk.MustExec(insertSQL) + + insertSQL = `insert into insert_test (id, c2) values (1, 1) on duplicate key update insert_test.c2=10;` + tk.MustExec(insertSQL) + + _, err = tk.Exec(`insert into insert_test (id, c2) values(1, 1) on duplicate key update t.c2 = 10`) + c.Assert(err, NotNil) +} + +func (s *testSuite) TestInsertAutoInc(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + createSQL := `drop table if exists insert_autoinc_test; create table insert_autoinc_test (id int primary key auto_increment, c1 int);` + tk.MustExec(createSQL) + + insertSQL := `insert into insert_autoinc_test(c1) values (1), (2)` + tk.MustExec(insertSQL) + + tk.MustExec("begin") + r := tk.MustQuery("select * from insert_autoinc_test;") + rowStr1 := fmt.Sprintf("%v %v", "1", "1") + rowStr2 := fmt.Sprintf("%v %v", "2", "2") + r.Check(testkit.Rows(rowStr1, rowStr2)) + tk.MustExec("commit") +} + +func (s *testSuite) TestReplace(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + testSQL := `drop table if exists replace_test; + create table replace_test (id int PRIMARY KEY AUTO_INCREMENT, c1 int, c2 int, c3 int default 1);` + tk.MustExec(testSQL) + testSQL = `replace replace_test (c1) values (1),(2),(NULL);` + tk.MustExec(testSQL) + + errReplaceSQL := `replace replace_test (c1) values ();` + tk.MustExec("begin") + _, err := tk.Exec(errReplaceSQL) + c.Assert(err, NotNil) + tk.MustExec("rollback") + + errReplaceSQL = `replace replace_test (c1, c2) values (1,2),(1);` + tk.MustExec("begin") + _, err = tk.Exec(errReplaceSQL) + c.Assert(err, NotNil) + tk.MustExec("rollback") + + errReplaceSQL = `replace replace_test (xxx) values (3);` + tk.MustExec("begin") + _, err = tk.Exec(errReplaceSQL) + c.Assert(err, NotNil) + tk.MustExec("rollback") + + errReplaceSQL = `replace replace_test_xxx (c1) values ();` + tk.MustExec("begin") + _, err = tk.Exec(errReplaceSQL) + c.Assert(err, NotNil) + tk.MustExec("rollback") + + replaceSetSQL := `replace replace_test set c1 = 3;` + tk.MustExec(replaceSetSQL) + + errReplaceSetSQL := `replace replace_test set c1 = 4, c1 = 5;` + tk.MustExec("begin") + _, err = tk.Exec(errReplaceSetSQL) + c.Assert(err, NotNil) + tk.MustExec("rollback") + + errReplaceSetSQL = `replace replace_test set xxx = 6;` + tk.MustExec("begin") + _, err = tk.Exec(errReplaceSetSQL) + c.Assert(err, NotNil) + tk.MustExec("rollback") + + replaceSelectSQL := `create table replace_test_1 (id int, c1 int);` + tk.MustExec(replaceSelectSQL) + replaceSelectSQL = `replace replace_test_1 select id, c1 from replace_test;` + tk.MustExec(replaceSelectSQL) + + replaceSelectSQL = `create table replace_test_2 (id int, c1 int);` + tk.MustExec(replaceSelectSQL) + replaceSelectSQL = `replace replace_test_1 select id, c1 from replace_test union select id * 10, c1 * 10 from replace_test;` + tk.MustExec(replaceSelectSQL) + + errReplaceSelectSQL := `replace replace_test_1 select c1 from replace_test;` + tk.MustExec("begin") + _, err = tk.Exec(errReplaceSelectSQL) + c.Assert(err, NotNil) + tk.MustExec("rollback") + + replaceUniqueIndexSQL := `create table replace_test_3 (c1 int, c2 int, UNIQUE INDEX (c2));` + tk.MustExec(replaceUniqueIndexSQL) + replaceUniqueIndexSQL = `replace into replace_test_3 set c2=1;` + tk.MustExec(replaceUniqueIndexSQL) + replaceUniqueIndexSQL = `replace into replace_test_3 set c2=1;` + tk.MustExec(replaceUniqueIndexSQL) + c.Assert(int64(tk.Se.AffectedRows()), Equals, int64(1)) + replaceUniqueIndexSQL = `replace into replace_test_3 set c1=1, c2=1;` + tk.MustExec(replaceUniqueIndexSQL) + c.Assert(int64(tk.Se.AffectedRows()), Equals, int64(2)) + + replaceUniqueIndexSQL = `replace into replace_test_3 set c2=NULL;` + tk.MustExec(replaceUniqueIndexSQL) + replaceUniqueIndexSQL = `replace into replace_test_3 set c2=NULL;` + tk.MustExec(replaceUniqueIndexSQL) + c.Assert(int64(tk.Se.AffectedRows()), Equals, int64(1)) + + replaceUniqueIndexSQL = `create table replace_test_4 (c1 int, c2 int, c3 int, UNIQUE INDEX (c1, c2));` + tk.MustExec(replaceUniqueIndexSQL) + replaceUniqueIndexSQL = `replace into replace_test_4 set c2=NULL;` + tk.MustExec(replaceUniqueIndexSQL) + replaceUniqueIndexSQL = `replace into replace_test_4 set c2=NULL;` + tk.MustExec(replaceUniqueIndexSQL) + c.Assert(int64(tk.Se.AffectedRows()), Equals, int64(1)) + + replacePrimaryKeySQL := `create table replace_test_5 (c1 int, c2 int, c3 int, PRIMARY KEY (c1, c2));` + tk.MustExec(replacePrimaryKeySQL) + replacePrimaryKeySQL = `replace into replace_test_5 set c1=1, c2=2;` + tk.MustExec(replacePrimaryKeySQL) + replacePrimaryKeySQL = `replace into replace_test_5 set c1=1, c2=2;` + tk.MustExec(replacePrimaryKeySQL) + c.Assert(int64(tk.Se.AffectedRows()), Equals, int64(1)) +} + +func (s *testSuite) TestSelectWithoutFrom(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + + tk.MustExec("begin") + r := tk.MustQuery("select 1 + 2*3") + r.Check(testkit.Rows("7")) + tk.MustExec("commit") + + tk.MustExec("begin") + r = tk.MustQuery(`select _utf8"string";`) + r.Check(testkit.Rows("string")) + tk.MustExec("commit") +} + +func (s *testSuite) TestSelectOrderBy(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + s.fillData(tk, "select_order_test") + + tk.MustExec("begin") + // Test star field + r := tk.MustQuery("select * from select_order_test where id = 1 order by id limit 1 offset 0;") + rowStr := fmt.Sprintf("%v %v", 1, []byte("hello")) + r.Check(testkit.Rows(rowStr)) + tk.MustExec("commit") + + tk.MustExec("begin") + // Test multiple field + r = tk.MustQuery("select id, name from select_order_test where id = 1 group by id, name limit 1 offset 0;") + rowStr = fmt.Sprintf("%v %v", 1, []byte("hello")) + r.Check(testkit.Rows(rowStr)) + tk.MustExec("commit") + + tk.MustExec("drop table select_order_test") +} + +func (s *testSuite) TestSelectDistinct(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + s.fillData(tk, "select_distinct_test") + + tk.MustExec("begin") + r := tk.MustQuery("select distinct name from select_distinct_test;") + rowStr := fmt.Sprintf("%v", []byte("hello")) + r.Check(testkit.Rows(rowStr)) + tk.MustExec("commit") + + tk.MustExec("drop table select_distinct_test") +} + +func (s *testSuite) TestSelectHaving(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + s.fillData(tk, "select_having_test") + + tk.MustExec("begin") + r := tk.MustQuery("select id, name from select_having_test where id in (1,3) having name like 'he%';") + rowStr := fmt.Sprintf("%v %v", 1, []byte("hello")) + r.Check(testkit.Rows(rowStr)) + tk.MustExec("commit") + + tk.MustExec("drop table select_having_test") +} + +func (s *testSuite) TestSelectErrorRow(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + + tk.MustExec("begin") + _, err := tk.Exec("select row(1, 1) from test") + c.Assert(err, NotNil) + + _, err = tk.Exec("select * from test group by row(1, 1);") + c.Assert(err, NotNil) + + _, err = tk.Exec("select * from test order by row(1, 1);") + c.Assert(err, NotNil) + + _, err = tk.Exec("select * from test having row(1, 1);") + c.Assert(err, NotNil) + + _, err = tk.Exec("select (select 1, 1) from test;") + c.Assert(err, NotNil) + + _, err = tk.Exec("select * from test group by (select 1, 1);") + c.Assert(err, NotNil) + + _, err = tk.Exec("select * from test order by (select 1, 1);") + c.Assert(err, NotNil) + + _, err = tk.Exec("select * from test having (select 1, 1);") + c.Assert(err, NotNil) + + tk.MustExec("commit") +} + +func (s *testSuite) TestUpdate(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + s.fillData(tk, "update_test") + + updateStr := `UPDATE update_test SET name = "abc" where id > 0;` + tk.MustExec(updateStr) + tk.CheckExecResult(2, 0) + + // select data + tk.MustExec("begin") + r := tk.MustQuery(`SELECT * from update_test limit 2;`) + rowStr1 := fmt.Sprintf("%v %v", 1, []byte("abc")) + rowStr2 := fmt.Sprintf("%v %v", 2, []byte("abc")) + r.Check(testkit.Rows(rowStr1, rowStr2)) + tk.MustExec("commit") + + tk.MustExec(`UPDATE update_test SET name = "foo"`) + tk.CheckExecResult(2, 0) + + tk.MustExec("drop table update_test") +} + +func (s *testSuite) fillMultiTableForUpdate(tk *testkit.TestKit) { + // Create and fill table items + tk.MustExec("CREATE TABLE items (id int, price TEXT);") + tk.MustExec(`insert into items values (11, "items_price_11"), (12, "items_price_12"), (13, "items_price_13");`) + tk.CheckExecResult(3, 0) + // Create and fill table month + tk.MustExec("CREATE TABLE month (mid int, mprice TEXT);") + tk.MustExec(`insert into month values (11, "month_price_11"), (22, "month_price_22"), (13, "month_price_13");`) + tk.CheckExecResult(3, 0) +} + +func (s *testSuite) TestMultipleTableUpdate(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + s.fillMultiTableForUpdate(tk) + + tk.MustExec(`UPDATE items, month SET items.price=month.mprice WHERE items.id=month.mid;`) + tk.MustExec("begin") + r := tk.MustQuery("SELECT * FROM items") + rowStr1 := fmt.Sprintf("%v %v", 11, []byte("month_price_11")) + rowStr2 := fmt.Sprintf("%v %v", 12, []byte("items_price_12")) + rowStr3 := fmt.Sprintf("%v %v", 13, []byte("month_price_13")) + r.Check(testkit.Rows(rowStr1, rowStr2, rowStr3)) + tk.MustExec("commit") + + // Single-table syntax but with multiple tables + tk.MustExec(`UPDATE items join month on items.id=month.mid SET items.price=month.mid;`) + tk.MustExec("begin") + r = tk.MustQuery("SELECT * FROM items") + rowStr1 = fmt.Sprintf("%v %v", 11, []byte("11")) + rowStr2 = fmt.Sprintf("%v %v", 12, []byte("items_price_12")) + rowStr3 = fmt.Sprintf("%v %v", 13, []byte("13")) + r.Check(testkit.Rows(rowStr1, rowStr2, rowStr3)) + tk.MustExec("commit") + + // JoinTable with alias table name. + tk.MustExec(`UPDATE items T0 join month T1 on T0.id=T1.mid SET T0.price=T1.mprice;`) + tk.MustExec("begin") + r = tk.MustQuery("SELECT * FROM items") + rowStr1 = fmt.Sprintf("%v %v", 11, []byte("month_price_11")) + rowStr2 = fmt.Sprintf("%v %v", 12, []byte("items_price_12")) + rowStr3 = fmt.Sprintf("%v %v", 13, []byte("month_price_13")) + r.Check(testkit.Rows(rowStr1, rowStr2, rowStr3)) + tk.MustExec("commit") +} + +// For https://github.com/pingcap/tidb/issues/345 +func (s *testSuite) TestIssue345(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec(`drop table if exists t1, t2`) + tk.MustExec(`create table t1 (c1 int);`) + tk.MustExec(`create table t2 (c2 int);`) + tk.MustExec(`insert into t1 values (1);`) + tk.MustExec(`insert into t2 values (2);`) + tk.MustExec(`update t1, t2 set t1.c1 = 2, t2.c2 = 1;`) + tk.MustExec(`update t1, t2 set c1 = 2, c2 = 1;`) + tk.MustExec(`update t1 as a, t2 as b set a.c1 = 2, b.c2 = 1;`) + + // Check t1 content + tk.MustExec("begin") + r := tk.MustQuery("SELECT * FROM t1;") + r.Check(testkit.Rows("2")) + tk.MustExec("commit") + // Check t2 content + tk.MustExec("begin") + r = tk.MustQuery("SELECT * FROM t2;") + r.Check(testkit.Rows("1")) + tk.MustExec("commit") + + tk.MustExec(`update t1 as a, t2 as t1 set a.c1 = 1, t1.c2 = 2;`) + // Check t1 content + tk.MustExec("begin") + r = tk.MustQuery("SELECT * FROM t1;") + r.Check(testkit.Rows("1")) + tk.MustExec("commit") + // Check t2 content + tk.MustExec("begin") + r = tk.MustQuery("SELECT * FROM t2;") + r.Check(testkit.Rows("2")) + + _, err := tk.Exec(`update t1 as a, t2 set t1.c1 = 10;`) + c.Assert(err, NotNil) + + tk.MustExec("commit") +} + +func (s *testSuite) TestMultiUpdate(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + // fix https://github.com/pingcap/tidb/issues/369 + testSQL := ` + DROP TABLE IF EXISTS t1, t2; + create table t1 (c int); + create table t2 (c varchar(256)); + insert into t1 values (1), (2); + insert into t2 values ("a"), ("b"); + update t1, t2 set t1.c = 10, t2.c = "abc";` + tk.MustExec(testSQL) + + // fix https://github.com/pingcap/tidb/issues/376 + testSQL = `DROP TABLE IF EXISTS t1, t2; + create table t1 (c1 int); + create table t2 (c2 int); + insert into t1 values (1), (2); + insert into t2 values (1), (2); + update t1, t2 set t1.c1 = 10, t2.c2 = 2 where t2.c2 = 1;` + tk.MustExec(testSQL) + + r := tk.MustQuery("select * from t1") + r.Check(testkit.Rows("10", "10")) +} + +func (s *testSuite) TestUnion(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + + testSQL := `select 1 union select 0;` + tk.MustExec(testSQL) + + testSQL = `drop table if exists union_test; create table union_test(id int);` + tk.MustExec(testSQL) + + testSQL = `drop table if exists union_test;` + tk.MustExec(testSQL) + testSQL = `create table union_test(id int);` + tk.MustExec(testSQL) + testSQL = `insert union_test values (1),(2); select id from union_test union select 1;` + tk.MustExec(testSQL) + + testSQL = `select id from union_test union select id from union_test;` + tk.MustExec("begin") + r := tk.MustQuery(testSQL) + r.Check(testkit.Rows("1", "2")) + + r = tk.MustQuery("select 1 union all select 1") + r.Check(testkit.Rows("1", "1")) + + r = tk.MustQuery("select 1 union all select 1 union select 1") + r.Check(testkit.Rows("1")) + + r = tk.MustQuery("select 1 union (select 2) limit 1") + r.Check(testkit.Rows("1")) + + r = tk.MustQuery("select 1 union (select 2) limit 1, 1") + r.Check(testkit.Rows("2")) + + r = tk.MustQuery("select id from union_test union all (select 1) order by id desc") + r.Check(testkit.Rows("2", "1", "1")) + + r = tk.MustQuery("select id as a from union_test union (select 1) order by a desc") + r.Check(testkit.Rows("2", "1")) + + r = tk.MustQuery(`select null union select "abc"`) + rowStr1 := fmt.Sprintf("%v", nil) + r.Check(testkit.Rows(rowStr1, "abc")) + + r = tk.MustQuery(`select "abc" union select 1`) + r.Check(testkit.Rows("abc", "1")) + + tk.MustExec("commit") +} + func (s *testSuite) TestTablePKisHandleScan(c *C) { tk := testkit.NewTestKit(c, s.store) tk.MustExec("use test") diff --git a/parser/parser_test.go b/parser/parser_test.go index 7f30e22712..0f3da64c42 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -367,11 +367,6 @@ func (s *testParserSuite) TestBuiltin(c *C) { {`SELECT LOCATE('bar', 'foobarbar');`, true}, {`SELECT LOCATE('bar', 'foobarbar', 5);`, true}, - // For delete statement - {"DELETE t1, t2 FROM t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.id=t2.id AND t2.id=t3.id;", true}, - {"DELETE FROM t1, t2 USING t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.id=t2.id AND t2.id=t3.id;", true}, - {"DELETE t1, t2 FROM t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.id=t2.id AND t2.id=t3.id limit 10;", false}, - // For time fsp {"CREATE TABLE t( c1 TIME(2), c2 DATETIME(2), c3 TIMESTAMP(2) );", true}, diff --git a/stmt/stmts/create_test.go b/stmt/stmts/create_test.go deleted file mode 100644 index c2be22b330..0000000000 --- a/stmt/stmts/create_test.go +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2015 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// See the License for the specific language governing permissions and -// limitations under the License. - -package stmts_test - -import ( - "database/sql" - "fmt" - "testing" - - "github.com/ngaut/log" - . "github.com/pingcap/check" - "github.com/pingcap/tidb" - "github.com/pingcap/tidb/context" - "github.com/pingcap/tidb/mysql" - "github.com/pingcap/tidb/sessionctx/variable" - "github.com/pingcap/tidb/util/mock" -) - -func TestT(t *testing.T) { - TestingT(t) -} - -var _ = Suite(&testStmtSuite{}) - -type testStmtSuite struct { - dbName string - - testDB *sql.DB - createDBSql string - dropDBSql string - useDBSql string - createTableSql string - insertSql string - selectSql string - createSystemDBSQL string - createUserTableSQL string - createDBPrivTableSQL string - createTablePrivTableSQL string - createColumnPrivTableSQL string - - ctx context.Context -} - -func (s *testStmtSuite) SetUpTest(c *C) { - log.SetLevelByString("error") - s.dbName = "teststmts" - var err error - s.testDB, err = sql.Open(tidb.DriverName, tidb.EngineGoLevelDBMemory+"/"+s.dbName+"/"+s.dbName) - c.Assert(err, IsNil) - // create db - s.createDBSql = fmt.Sprintf("create database if not exists %s;", s.dbName) - s.dropDBSql = fmt.Sprintf("drop database if exists %s;", s.dbName) - s.useDBSql = fmt.Sprintf("use %s;", s.dbName) - s.createTableSql = ` - CREATE TABLE test(id INT NOT NULL DEFAULT 1, name varchar(255), PRIMARY KEY(id)); - CREATE TABLE test1(id INT NOT NULL DEFAULT 2, name varchar(255), PRIMARY KEY(id), INDEX name(name)); - CREATE TABLE test2(id INT NOT NULL DEFAULT 3, name varchar(255), PRIMARY KEY(id));` - - s.selectSql = `SELECT * from test limit 2;` - mustExec(c, s.testDB, s.createDBSql) - mustExec(c, s.testDB, s.useDBSql) - - s.createSystemDBSQL = fmt.Sprintf("create database if not exists %s;", mysql.SystemDB) - s.createUserTableSQL = tidb.CreateUserTable - s.createDBPrivTableSQL = tidb.CreateDBPrivTable - s.createTablePrivTableSQL = tidb.CreateTablePrivTable - s.createColumnPrivTableSQL = tidb.CreateColumnPrivTable - - mustExec(c, s.testDB, s.createSystemDBSQL) - mustExec(c, s.testDB, s.createUserTableSQL) - mustExec(c, s.testDB, s.createDBPrivTableSQL) - mustExec(c, s.testDB, s.createTablePrivTableSQL) - mustExec(c, s.testDB, s.createColumnPrivTableSQL) - - s.ctx = mock.NewContext() - variable.BindSessionVars(s.ctx) -} - -func (s *testStmtSuite) TearDownTest(c *C) { - // drop db - mustExec(c, s.testDB, s.dropDBSql) -} - -func mustBegin(c *C, currDB *sql.DB) *sql.Tx { - tx, err := currDB.Begin() - c.Assert(err, IsNil) - return tx -} - -func mustCommit(c *C, tx *sql.Tx) { - err := tx.Commit() - c.Assert(err, IsNil) -} - -func mustExecuteSql(c *C, tx *sql.Tx, sql string) sql.Result { - r, err := tx.Exec(sql) - c.Assert(err, IsNil, Commentf(sql)) - return r -} - -func mustExec(c *C, currDB *sql.DB, sql string) sql.Result { - tx := mustBegin(c, currDB) - r := mustExecuteSql(c, tx, sql) - mustCommit(c, tx) - return r -} - -func checkResult(c *C, r sql.Result, affectedRows int64, insertID int64) { - gotRows, err := r.RowsAffected() - c.Assert(err, IsNil) - c.Assert(gotRows, Equals, affectedRows) - - gotID, err := r.LastInsertId() - c.Assert(err, IsNil) - c.Assert(gotID, Equals, insertID) -} diff --git a/stmt/stmts/delete_test.go b/stmt/stmts/delete_test.go deleted file mode 100644 index d9f6fa3a2c..0000000000 --- a/stmt/stmts/delete_test.go +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2015 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// See the License for the specific language governing permissions and -// limitations under the License. - -package stmts_test - -import ( - "database/sql" - - . "github.com/pingcap/check" -) - -func (s *testStmtSuite) fillData(currDB *sql.DB, c *C) { - mustExec(c, currDB, s.createDBSql) - mustExec(c, currDB, s.useDBSql) - mustExec(c, currDB, s.createTableSql) - - // insert data - r := mustExec(c, currDB, `INSERT INTO test VALUES (1, "hello");`) - checkResult(c, r, 1, 0) - r = mustExec(c, currDB, `INSERT INTO test VALUES (2, "hello");`) - checkResult(c, r, 1, 0) -} - -func (s *testStmtSuite) fillDataMultiTable(currDB *sql.DB, c *C) { - // Create db - mustExec(c, currDB, s.createDBSql) - // Use db - mustExec(c, currDB, s.useDBSql) - // Create and fill table t1 - mustExec(c, currDB, "CREATE TABLE t1 (id int, data int);") - r := mustExec(c, currDB, "insert into t1 values (11, 121), (12, 122), (13, 123);") - checkResult(c, r, 3, 0) - // Create and fill table t2 - mustExec(c, currDB, "CREATE TABLE t2 (id int, data int);") - r = mustExec(c, currDB, "insert into t2 values (11, 221), (22, 222), (23, 223);") - checkResult(c, r, 3, 0) - // Create and fill table t3 - mustExec(c, currDB, "CREATE TABLE t3 (id int, data int);") - r = mustExec(c, currDB, "insert into t3 values (11, 321), (22, 322), (23, 323);") - checkResult(c, r, 3, 0) -} - -func (s *testStmtSuite) queryStrings(currDB *sql.DB, sql string, c *C) []string { - tx := mustBegin(c, currDB) - rows, err := tx.Query(sql) - c.Assert(err, IsNil) - defer rows.Close() - - var strs []string - for rows.Next() { - var str string - rows.Scan(&str) - strs = append(strs, str) - } - return strs -} - -func (s *testStmtSuite) TestDelete(c *C) { - s.fillData(s.testDB, c) - - r := mustExec(c, s.testDB, `UPDATE test SET name = "abc" where id = 2;`) - checkResult(c, r, 1, 0) - - r = mustExec(c, s.testDB, `DELETE from test where id = 2 limit 1;`) - checkResult(c, r, 1, 0) - - // Test delete with false condition - r = mustExec(c, s.testDB, `DELETE from test where 0;`) - checkResult(c, r, 0, 0) - - mustExec(c, s.testDB, "insert into test values (2, 'abc')") - r = mustExec(c, s.testDB, `delete from test where test.id = 2 limit 1`) - checkResult(c, r, 1, 0) - - // Select data - tx := mustBegin(c, s.testDB) - rows, err := tx.Query(s.selectSql) - c.Assert(err, IsNil) - - for rows.Next() { - var id int - var name string - rows.Scan(&id, &name) - c.Assert(id, Equals, 1) - c.Assert(name, Equals, "hello") - } - - rows.Close() - mustCommit(c, tx) - - r = mustExec(c, s.testDB, `DELETE from test;`) - checkResult(c, r, 1, 0) -} - -func (s *testStmtSuite) TestMultiTableDelete(c *C) { - s.fillDataMultiTable(s.testDB, c) - - r := mustExec(c, s.testDB, `DELETE t1, t2 FROM t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.id=t2.id AND t2.id=t3.id;`) - checkResult(c, r, 2, 0) - - // Select data - tx := mustBegin(c, s.testDB) - rows, err := tx.Query("select * from t3") - c.Assert(err, IsNil) - - cnt := 0 - for rows.Next() { - cnt++ - } - c.Assert(cnt, Equals, 3) - rows.Close() -} - -func (s *testStmtSuite) TestQualifedDelete(c *C) { - mustExec(c, s.testDB, "drop table if exists t1") - mustExec(c, s.testDB, "drop table if exists t2") - mustExec(c, s.testDB, "create table t1 (c1 int, c2 int, index (c1))") - mustExec(c, s.testDB, "create table t2 (c1 int, c2 int)") - mustExec(c, s.testDB, "insert into t1 values (1, 1), (2, 2)") - - // delete with index - r := mustExec(c, s.testDB, "delete from t1 where t1.c1 = 1") - checkResult(c, r, 1, 0) - - // delete with no index - r = mustExec(c, s.testDB, "delete from t1 where t1.c2 = 2") - checkResult(c, r, 1, 0) - - rows, err := s.testDB.Query("select * from t1") - c.Assert(err, IsNil) - cnt := 0 - for rows.Next() { - cnt++ - } - rows.Close() - c.Assert(cnt, Equals, 0) - - _, err = s.testDB.Exec("delete from t1 as a where a.c1 = 1") - c.Assert(err, NotNil) - - mustExec(c, s.testDB, "insert into t1 values (1, 1), (2, 2)") - mustExec(c, s.testDB, "insert into t2 values (2, 1), (3,1)") - - r = mustExec(c, s.testDB, "delete t1, t2 from t1 join t2 where t1.c1 = t2.c2") - checkResult(c, r, 3, 0) - - mustExec(c, s.testDB, "insert into t2 values (2, 1), (3,1)") - r = mustExec(c, s.testDB, "delete a, b from t1 as a join t2 as b where a.c2 = b.c1") - checkResult(c, r, 2, 0) - - _, err = s.testDB.Exec("delete t1, t2 from t1 as a join t2 as b where a.c2 = b.c1") - c.Assert(err, NotNil) - - mustExec(c, s.testDB, "drop table t1, t2") -} diff --git a/stmt/stmts/insert_test.go b/stmt/stmts/insert_test.go deleted file mode 100644 index 8277f22c57..0000000000 --- a/stmt/stmts/insert_test.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2015 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// See the License for the specific language governing permissions and -// limitations under the License. - -package stmts_test - -import ( - . "github.com/pingcap/check" -) - -func (s *testStmtSuite) TestInsert(c *C) { - testSQL := `drop table if exists insert_test;create table insert_test (id int PRIMARY KEY AUTO_INCREMENT, c1 int, c2 int, c3 int default 1);` - mustExec(c, s.testDB, testSQL) - testSQL = `insert insert_test (c1) values (1),(2),(NULL);` - mustExec(c, s.testDB, testSQL) - - errInsertSelectSQL := `insert insert_test (c1) values ();` - tx := mustBegin(c, s.testDB) - _, err := tx.Exec(errInsertSelectSQL) - c.Assert(err, NotNil) - tx.Rollback() - - errInsertSelectSQL = `insert insert_test (c1, c2) values (1,2),(1);` - tx = mustBegin(c, s.testDB) - _, err = tx.Exec(errInsertSelectSQL) - c.Assert(err, NotNil) - tx.Rollback() - - errInsertSelectSQL = `insert insert_test (xxx) values (3);` - tx = mustBegin(c, s.testDB) - _, err = tx.Exec(errInsertSelectSQL) - c.Assert(err, NotNil) - tx.Rollback() - - errInsertSelectSQL = `insert insert_test_xxx (c1) values ();` - tx = mustBegin(c, s.testDB) - _, err = tx.Exec(errInsertSelectSQL) - c.Assert(err, NotNil) - tx.Rollback() - - insertSetSQL := `insert insert_test set c1 = 3;` - mustExec(c, s.testDB, insertSetSQL) - - errInsertSelectSQL = `insert insert_test set c1 = 4, c1 = 5;` - tx = mustBegin(c, s.testDB) - _, err = tx.Exec(errInsertSelectSQL) - c.Assert(err, NotNil) - tx.Rollback() - - errInsertSelectSQL = `insert insert_test set xxx = 6;` - tx = mustBegin(c, s.testDB) - _, err = tx.Exec(errInsertSelectSQL) - c.Assert(err, NotNil) - tx.Rollback() - - insertSelectSQL := `create table insert_test_1 (id int, c1 int);` - mustExec(c, s.testDB, insertSelectSQL) - insertSelectSQL = `insert insert_test_1 select id, c1 from insert_test;` - mustExec(c, s.testDB, insertSelectSQL) - - insertSelectSQL = `create table insert_test_2 (id int, c1 int);` - mustExec(c, s.testDB, insertSelectSQL) - insertSelectSQL = `insert insert_test_1 select id, c1 from insert_test union select id * 10, c1 * 10 from insert_test;` - mustExec(c, s.testDB, insertSelectSQL) - - errInsertSelectSQL = `insert insert_test_1 select c1 from insert_test;` - tx = mustBegin(c, s.testDB) - _, err = tx.Exec(errInsertSelectSQL) - c.Assert(err, NotNil) - tx.Rollback() - - insertSQL := `insert into insert_test (id, c2) values (1, 1) on duplicate key update c2=10;` - mustExec(c, s.testDB, insertSQL) - - insertSQL = `insert into insert_test (id, c2) values (1, 1) on duplicate key update insert_test.c2=10;` - mustExec(c, s.testDB, insertSQL) - - _, err = s.testDB.Exec(`insert into insert_test (id, c2) values(1, 1) on duplicate key update t.c2 = 10`) - c.Assert(err, NotNil) -} - -func (s *testStmtSuite) TestInsertAutoInc(c *C) { - createSQL := `drop table if exists insert_autoinc_test; create table insert_autoinc_test (id int primary key auto_increment, c1 int);` - mustExec(c, s.testDB, createSQL) - - insertSQL := `insert into insert_autoinc_test(c1) values (1), (2)` - mustExec(c, s.testDB, insertSQL) - - tx := mustBegin(c, s.testDB) - rows, err := tx.Query("select * from insert_autoinc_test;") - c.Assert(err, IsNil) - - c.Assert(rows.Next(), IsTrue) - var id, c1 int - rows.Scan(&id, &c1) - c.Assert(id, Equals, 1) - c.Assert(c1, Equals, 1) - - c.Assert(rows.Next(), IsTrue) - rows.Scan(&id, &c1) - c.Assert(id, Equals, 2) - c.Assert(c1, Equals, 2) - - c.Assert(rows.Next(), IsFalse) - rows.Close() - mustCommit(c, tx) -} diff --git a/stmt/stmts/replace_test.go b/stmt/stmts/replace_test.go deleted file mode 100644 index 7ffe232f7f..0000000000 --- a/stmt/stmts/replace_test.go +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2015 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// See the License for the specific language governing permissions and -// limitations under the License. - -package stmts_test - -import ( - . "github.com/pingcap/check" -) - -func (s *testStmtSuite) TestReplace(c *C) { - testSQL := `drop table if exists replace_test; - create table replace_test (id int PRIMARY KEY AUTO_INCREMENT, c1 int, c2 int, c3 int default 1);` - mustExec(c, s.testDB, testSQL) - testSQL = `replace replace_test (c1) values (1),(2),(NULL);` - mustExec(c, s.testDB, testSQL) - - errReplaceSQL := `replace replace_test (c1) values ();` - tx := mustBegin(c, s.testDB) - _, err := tx.Exec(errReplaceSQL) - c.Assert(err, NotNil) - tx.Rollback() - - errReplaceSQL = `replace replace_test (c1, c2) values (1,2),(1);` - tx = mustBegin(c, s.testDB) - _, err = tx.Exec(errReplaceSQL) - c.Assert(err, NotNil) - tx.Rollback() - - errReplaceSQL = `replace replace_test (xxx) values (3);` - tx = mustBegin(c, s.testDB) - _, err = tx.Exec(errReplaceSQL) - c.Assert(err, NotNil) - tx.Rollback() - - errReplaceSQL = `replace replace_test_xxx (c1) values ();` - tx = mustBegin(c, s.testDB) - _, err = tx.Exec(errReplaceSQL) - c.Assert(err, NotNil) - tx.Rollback() - - replaceSetSQL := `replace replace_test set c1 = 3;` - mustExec(c, s.testDB, replaceSetSQL) - - errReplaceSetSQL := `replace replace_test set c1 = 4, c1 = 5;` - tx = mustBegin(c, s.testDB) - _, err = tx.Exec(errReplaceSetSQL) - c.Assert(err, NotNil) - tx.Rollback() - - errReplaceSetSQL = `replace replace_test set xxx = 6;` - tx = mustBegin(c, s.testDB) - _, err = tx.Exec(errReplaceSetSQL) - c.Assert(err, NotNil) - tx.Rollback() - - replaceSelectSQL := `create table replace_test_1 (id int, c1 int);` - mustExec(c, s.testDB, replaceSelectSQL) - replaceSelectSQL = `replace replace_test_1 select id, c1 from replace_test;` - mustExec(c, s.testDB, replaceSelectSQL) - - replaceSelectSQL = `create table replace_test_2 (id int, c1 int);` - mustExec(c, s.testDB, replaceSelectSQL) - replaceSelectSQL = `replace replace_test_1 select id, c1 from replace_test union select id * 10, c1 * 10 from replace_test;` - mustExec(c, s.testDB, replaceSelectSQL) - - errReplaceSelectSQL := `replace replace_test_1 select c1 from replace_test;` - tx = mustBegin(c, s.testDB) - _, err = tx.Exec(errReplaceSelectSQL) - c.Assert(err, NotNil) - tx.Rollback() - - replaceUniqueIndexSQL := `create table replace_test_3 (c1 int, c2 int, UNIQUE INDEX (c2));` - mustExec(c, s.testDB, replaceUniqueIndexSQL) - replaceUniqueIndexSQL = `replace into replace_test_3 set c2=1;` - mustExec(c, s.testDB, replaceUniqueIndexSQL) - replaceUniqueIndexSQL = `replace into replace_test_3 set c2=1;` - ret := mustExec(c, s.testDB, replaceUniqueIndexSQL) - rows, err := ret.RowsAffected() - c.Assert(err, IsNil) - c.Assert(rows, Equals, int64(1)) - replaceUniqueIndexSQL = `replace into replace_test_3 set c1=1, c2=1;` - ret = mustExec(c, s.testDB, replaceUniqueIndexSQL) - rows, err = ret.RowsAffected() - c.Assert(err, IsNil) - c.Assert(rows, Equals, int64(2)) - - replaceUniqueIndexSQL = `replace into replace_test_3 set c2=NULL;` - mustExec(c, s.testDB, replaceUniqueIndexSQL) - replaceUniqueIndexSQL = `replace into replace_test_3 set c2=NULL;` - ret = mustExec(c, s.testDB, replaceUniqueIndexSQL) - rows, err = ret.RowsAffected() - c.Assert(err, IsNil) - c.Assert(rows, Equals, int64(1)) - - replaceUniqueIndexSQL = `create table replace_test_4 (c1 int, c2 int, c3 int, UNIQUE INDEX (c1, c2));` - mustExec(c, s.testDB, replaceUniqueIndexSQL) - replaceUniqueIndexSQL = `replace into replace_test_4 set c2=NULL;` - mustExec(c, s.testDB, replaceUniqueIndexSQL) - replaceUniqueIndexSQL = `replace into replace_test_4 set c2=NULL;` - ret = mustExec(c, s.testDB, replaceUniqueIndexSQL) - rows, err = ret.RowsAffected() - c.Assert(err, IsNil) - c.Assert(rows, Equals, int64(1)) - - replacePrimaryKeySQL := `create table replace_test_5 (c1 int, c2 int, c3 int, PRIMARY KEY (c1, c2));` - mustExec(c, s.testDB, replacePrimaryKeySQL) - replacePrimaryKeySQL = `replace into replace_test_5 set c1=1, c2=2;` - mustExec(c, s.testDB, replacePrimaryKeySQL) - replacePrimaryKeySQL = `replace into replace_test_5 set c1=1, c2=2;` - ret = mustExec(c, s.testDB, replacePrimaryKeySQL) - rows, err = ret.RowsAffected() - c.Assert(err, IsNil) - c.Assert(rows, Equals, int64(1)) -} diff --git a/stmt/stmts/select_test.go b/stmt/stmts/select_test.go deleted file mode 100644 index 149fec1569..0000000000 --- a/stmt/stmts/select_test.go +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2015 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// See the License for the specific language governing permissions and -// limitations under the License. - -package stmts_test - -import ( - . "github.com/pingcap/check" -) - -func (s *testStmtSuite) TestSelectWithoutFrom(c *C) { - tx := mustBegin(c, s.testDB) - rows, err := tx.Query("select 1 + 2*3") - c.Assert(err, IsNil) - - var result int - for rows.Next() { - rows.Scan(&result) - c.Assert(result, Equals, 7) - } - - rows.Close() - mustCommit(c, tx) - - tx = mustBegin(c, s.testDB) - rows, err = tx.Query(`select _utf8"string";`) - c.Assert(err, IsNil) - matchRows(c, rows, [][]interface{}{{"string"}}) - rows.Close() - mustCommit(c, tx) -} - -func (s *testStmtSuite) TestSelectOrderBy(c *C) { - s.fillData(s.testDB, c) - - tx := mustBegin(c, s.testDB) - // Test star field - rows, err := tx.Query("select * from test where id = 1 order by id limit 1 offset 0;") - c.Assert(err, IsNil) - - for rows.Next() { - var id int - var name string - rows.Scan(&id, &name) - c.Assert(id, Equals, 1) - c.Assert(name, Equals, "hello") - } - - rows.Close() - mustCommit(c, tx) - - tx = mustBegin(c, s.testDB) - // Test multiple field - rows, err = tx.Query("select id, name from test where id = 1 group by id, name limit 1 offset 0;") - c.Assert(err, IsNil) - - for rows.Next() { - var id int - var name string - rows.Scan(&id, &name) - c.Assert(id, Equals, 1) - c.Assert(name, Equals, "hello") - } - - rows.Close() - mustCommit(c, tx) -} - -func (s *testStmtSuite) TestSelectDistinct(c *C) { - s.fillData(s.testDB, c) - - tx := mustBegin(c, s.testDB) - rows, err := tx.Query("select distinct name from test;") - c.Assert(err, IsNil) - - var cnt int - for rows.Next() { - var name string - rows.Scan(&name) - c.Assert(name, Equals, "hello") - cnt++ - } - c.Assert(cnt, Equals, 1) - rows.Close() - mustCommit(c, tx) -} - -func (s *testStmtSuite) TestSelectHaving(c *C) { - s.fillData(s.testDB, c) - tx := mustBegin(c, s.testDB) - rows, err := tx.Query("select id, name from test where id in (1,3) having name like 'he%';") - c.Assert(err, IsNil) - - for rows.Next() { - var id int - var name string - rows.Scan(&id, &name) - c.Assert(id, Equals, 1) - c.Assert(name, Equals, "hello") - } - - rows.Close() - mustCommit(c, tx) -} - -func (s *testStmtSuite) TestSelectErrorRow(c *C) { - tx := mustBegin(c, s.testDB) - _, err := tx.Query("select row(1, 1) from test") - c.Assert(err, NotNil) - - _, err = tx.Query("select * from test group by row(1, 1);") - c.Assert(err, NotNil) - - _, err = tx.Query("select * from test order by row(1, 1);") - c.Assert(err, NotNil) - - _, err = tx.Query("select * from test having row(1, 1);") - c.Assert(err, NotNil) - - _, err = tx.Query("select (select 1, 1) from test;") - c.Assert(err, NotNil) - - _, err = tx.Query("select * from test group by (select 1, 1);") - c.Assert(err, NotNil) - - _, err = tx.Query("select * from test order by (select 1, 1);") - c.Assert(err, NotNil) - - _, err = tx.Query("select * from test having (select 1, 1);") - c.Assert(err, NotNil) - - mustCommit(c, tx) -} diff --git a/stmt/stmts/union_test.go b/stmt/stmts/union_test.go deleted file mode 100644 index 8d7f4bfdad..0000000000 --- a/stmt/stmts/union_test.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2015 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// See the License for the specific language governing permissions and -// limitations under the License. - -package stmts_test - -import ( - "database/sql" - "fmt" - - . "github.com/pingcap/check" -) - -func (s *testStmtSuite) TestUnion(c *C) { - testSQL := `select 1 union select 0;` - mustExec(c, s.testDB, testSQL) - - testSQL = `drop table if exists union_test; create table union_test(id int);` - mustExec(c, s.testDB, testSQL) - - testSQL = `drop table if exists union_test;` - mustExec(c, s.testDB, testSQL) - testSQL = `create table union_test(id int);` - mustExec(c, s.testDB, testSQL) - testSQL = `insert union_test values (1),(2); select id from union_test union select 1;` - mustExec(c, s.testDB, testSQL) - - testSQL = `select id from union_test union select id from union_test;` - tx := mustBegin(c, s.testDB) - rows, err := tx.Query(testSQL) - c.Assert(err, IsNil) - matchRows(c, rows, [][]interface{}{{1}, {2}}) - - rows, err = tx.Query("select 1 union all select 1") - c.Assert(err, IsNil) - matchRows(c, rows, [][]interface{}{{1}, {1}}) - - rows, err = tx.Query("select 1 union all select 1 union select 1") - c.Assert(err, IsNil) - matchRows(c, rows, [][]interface{}{{1}}) - - rows, err = tx.Query("select 1 union (select 2) limit 1") - c.Assert(err, IsNil) - matchRows(c, rows, [][]interface{}{{1}}) - - rows, err = tx.Query("select 1 union (select 2) limit 1, 1") - c.Assert(err, IsNil) - matchRows(c, rows, [][]interface{}{{2}}) - - rows, err = tx.Query("select id from union_test union all (select 1) order by id desc") - c.Assert(err, IsNil) - matchRows(c, rows, [][]interface{}{{2}, {1}, {1}}) - - rows, err = tx.Query("select id as a from union_test union (select 1) order by a desc") - c.Assert(err, IsNil) - matchRows(c, rows, [][]interface{}{{2}, {1}}) - - rows, err = tx.Query(`select null union select "abc"`) - c.Assert(err, IsNil) - matchRows(c, rows, [][]interface{}{{nil}, {"abc"}}) - - rows, err = tx.Query(`select "abc" union select 1`) - c.Assert(err, IsNil) - matchRows(c, rows, [][]interface{}{{"abc"}, {"1"}}) - - mustCommit(c, tx) -} - -func dumpRows(c *C, rows *sql.Rows) [][]interface{} { - cols, err := rows.Columns() - c.Assert(err, IsNil) - ay := make([][]interface{}, 0) - for rows.Next() { - v := make([]interface{}, len(cols)) - for i := range v { - v[i] = new(interface{}) - } - err = rows.Scan(v...) - c.Assert(err, IsNil) - - for i := range v { - v[i] = *(v[i].(*interface{})) - } - ay = append(ay, v) - } - - rows.Close() - c.Assert(rows.Err(), IsNil) - return ay -} - -func matchRows(c *C, rows *sql.Rows, expected [][]interface{}) { - ay := dumpRows(c, rows) - c.Assert(len(ay), Equals, len(expected)) - for i := range ay { - match(c, ay[i], expected[i]...) - } -} - -func match(c *C, row []interface{}, expected ...interface{}) { - c.Assert(len(row), Equals, len(expected)) - for i := range row { - got := fmt.Sprintf("%v", row[i]) - need := fmt.Sprintf("%v", expected[i]) - c.Assert(got, Equals, need) - } -} diff --git a/stmt/stmts/update_test.go b/stmt/stmts/update_test.go deleted file mode 100644 index d0a57af22a..0000000000 --- a/stmt/stmts/update_test.go +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright 2015 PingCAP, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// See the License for the specific language governing permissions and -// limitations under the License. - -package stmts_test - -import ( - "database/sql" - - . "github.com/pingcap/check" - "github.com/pingcap/tidb" -) - -func (s *testStmtSuite) TestUpdate(c *C) { - testDB, err := sql.Open(tidb.DriverName, tidb.EngineGoLevelDBMemory+"tmp/"+s.dbName) - c.Assert(err, IsNil) - - s.fillData(testDB, c) - - updateStr := `UPDATE test SET name = "abc" where id > 0;` - - r := mustExec(c, testDB, updateStr) - checkResult(c, r, 2, 0) - - // select data - tx := mustBegin(c, testDB) - rows, err := tx.Query(s.selectSql) - c.Assert(err, IsNil) - - for rows.Next() { - var id int - var name string - rows.Scan(&id, &name) - c.Assert(name, Equals, "abc") - } - - rows.Close() - mustCommit(c, tx) - - r = mustExec(c, testDB, `UPDATE test SET name = "foo"`) - checkResult(c, r, 2, 0) -} - -func (s *testStmtSuite) fillMultiTableForUpdate(currDB *sql.DB, c *C) { - // Create db - mustExec(c, currDB, s.createDBSql) - // Use db - mustExec(c, currDB, s.useDBSql) - // Create and fill table items - mustExec(c, currDB, "CREATE TABLE items (id int, price TEXT);") - r := mustExec(c, currDB, `insert into items values (11, "items_price_11"), (12, "items_price_12"), (13, "items_price_13");`) - checkResult(c, r, 3, 0) - // Create and fill table month - mustExec(c, currDB, "CREATE TABLE month (mid int, mprice TEXT);") - r = mustExec(c, currDB, `insert into month values (11, "month_price_11"), (22, "month_price_22"), (13, "month_price_13");`) - checkResult(c, r, 3, 0) -} - -func (s *testStmtSuite) TestMultipleTableUpdate(c *C) { - testDB, err := sql.Open(tidb.DriverName, tidb.EngineGoLevelDBMemory+"tmp/"+s.dbName) - c.Assert(err, IsNil) - s.fillMultiTableForUpdate(testDB, c) - - r := mustExec(c, testDB, `UPDATE items, month SET items.price=month.mprice WHERE items.id=month.mid;`) - c.Assert(r, NotNil) - - tx := mustBegin(c, testDB) - rows, err := tx.Query("SELECT * FROM items") - c.Assert(err, IsNil) - - expectedResult := map[int]string{ - 11: "month_price_11", - 12: "items_price_12", - 13: "month_price_13", - } - for rows.Next() { - var ( - id int - price string - ) - rows.Scan(&id, &price) - c.Assert(price, Equals, expectedResult[id]) - } - rows.Close() - mustCommit(c, tx) - - // Single-table syntax but with multiple tables - r = mustExec(c, testDB, `UPDATE items join month on items.id=month.mid SET items.price=month.mid;`) - c.Assert(r, NotNil) - tx = mustBegin(c, testDB) - rows, err = tx.Query("SELECT * FROM items") - c.Assert(err, IsNil) - expectedResult = map[int]string{ - 11: "11", - 12: "items_price_12", - 13: "13", - } - for rows.Next() { - var ( - id int - price string - ) - rows.Scan(&id, &price) - c.Assert(price, Equals, expectedResult[id]) - } - rows.Close() - mustCommit(c, tx) - - // JoinTable with alias table name. - r = mustExec(c, testDB, `UPDATE items T0 join month T1 on T0.id=T1.mid SET T0.price=T1.mprice;`) - c.Assert(r, NotNil) - tx = mustBegin(c, testDB) - rows, err = tx.Query("SELECT * FROM items") - c.Assert(err, IsNil) - expectedResult = map[int]string{ - 11: "month_price_11", - 12: "items_price_12", - 13: "month_price_13", - } - for rows.Next() { - var ( - id int - price string - ) - rows.Scan(&id, &price) - c.Assert(price, Equals, expectedResult[id]) - } - rows.Close() - mustCommit(c, tx) -} - -// For https://github.com/pingcap/tidb/issues/345 -func (s *testStmtSuite) TestIssue345(c *C) { - testDB, err := sql.Open(tidb.DriverName, tidb.EngineGoLevelDBMemory+"tmp-issue345/"+s.dbName) - c.Assert(err, IsNil) - mustExec(c, testDB, `drop table if exists t1, t2`) - mustExec(c, testDB, `create table t1 (c1 int);`) - mustExec(c, testDB, `create table t2 (c2 int);`) - mustExec(c, testDB, `insert into t1 values (1);`) - mustExec(c, testDB, `insert into t2 values (2);`) - mustExec(c, testDB, `update t1, t2 set t1.c1 = 2, t2.c2 = 1;`) - mustExec(c, testDB, `update t1, t2 set c1 = 2, c2 = 1;`) - mustExec(c, testDB, `update t1 as a, t2 as b set a.c1 = 2, b.c2 = 1;`) - - // Check t1 content - tx := mustBegin(c, testDB) - rows, err := tx.Query("SELECT * FROM t1;") - matchRows(c, rows, [][]interface{}{{2}}) - rows.Close() - mustCommit(c, tx) - // Check t2 content - tx = mustBegin(c, testDB) - rows, err = tx.Query("SELECT * FROM t2;") - c.Assert(err, IsNil) - matchRows(c, rows, [][]interface{}{{1}}) - rows.Close() - mustCommit(c, tx) - - mustExec(c, testDB, `update t1 as a, t2 as t1 set a.c1 = 1, t1.c2 = 2;`) - // Check t1 content - tx = mustBegin(c, testDB) - rows, err = tx.Query("SELECT * FROM t1;") - c.Assert(err, IsNil) - matchRows(c, rows, [][]interface{}{{1}}) - rows.Close() - mustCommit(c, tx) - // Check t2 content - tx = mustBegin(c, testDB) - rows, err = tx.Query("SELECT * FROM t2;") - c.Assert(err, IsNil) - matchRows(c, rows, [][]interface{}{{2}}) - rows.Close() - - _, err = testDB.Exec(`update t1 as a, t2 set t1.c1 = 10;`) - c.Assert(err, NotNil) - - mustCommit(c, tx) -} - -func (s *testStmtSuite) TestMultiUpdate(c *C) { - // fix https://github.com/pingcap/tidb/issues/369 - testSQL := ` - DROP TABLE IF EXISTS t1, t2; - create table t1 (c int); - create table t2 (c varchar(256)); - insert into t1 values (1), (2); - insert into t2 values ("a"), ("b"); - update t1, t2 set t1.c = 10, t2.c = "abc";` - mustExec(c, s.testDB, testSQL) - - // fix https://github.com/pingcap/tidb/issues/376 - testSQL = `DROP TABLE IF EXISTS t1, t2; - create table t1 (c1 int); - create table t2 (c2 int); - insert into t1 values (1), (2); - insert into t2 values (1), (2); - update t1, t2 set t1.c1 = 10, t2.c2 = 2 where t2.c2 = 1;` - mustExec(c, s.testDB, testSQL) - - rows, err := s.testDB.Query("select * from t1") - c.Assert(err, IsNil) - matchRows(c, rows, [][]interface{}{{10}, {10}}) -} diff --git a/util/testkit/testkit.go b/util/testkit/testkit.go index a41d3f2505..5e0c99cedd 100644 --- a/util/testkit/testkit.go +++ b/util/testkit/testkit.go @@ -87,6 +87,12 @@ func (tk *TestKit) Exec(sql string, args ...interface{}) (ast.RecordSet, error) return rs, nil } +// CheckExecResult checks the affected rows and the insert id after executing MustExec. +func (tk *TestKit) CheckExecResult(affectedRows, insertID int64) { + tk.c.Assert(affectedRows, check.Equals, int64(tk.Se.AffectedRows())) + tk.c.Assert(insertID, check.Equals, int64(tk.Se.LastInsertID())) +} + // MustExec executes a sql statement and asserts nil error. func (tk *TestKit) MustExec(sql string, args ...interface{}) { _, err := tk.Exec(sql, args...)