Merge pull request #935 from pingcap/zimuxia/move-test
*: Move statement tests to executor package
This commit is contained in:
@ -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")
|
||||
|
||||
@ -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},
|
||||
|
||||
|
||||
@ -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)
|
||||
}
|
||||
@ -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")
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
@ -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))
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
@ -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}})
|
||||
}
|
||||
@ -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...)
|
||||
|
||||
Reference in New Issue
Block a user