621 lines
21 KiB
Go
621 lines
21 KiB
Go
// 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 tidb
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
. "github.com/pingcap/check"
|
|
"github.com/pingcap/tidb/domain"
|
|
"github.com/pingcap/tidb/kv"
|
|
"github.com/pingcap/tidb/terror"
|
|
"github.com/pingcap/tidb/util/testleak"
|
|
)
|
|
|
|
var (
|
|
_ = Suite(&testSessionSuite{})
|
|
)
|
|
|
|
type testSessionSuite struct {
|
|
dbName string
|
|
createDBSQL string
|
|
dropDBSQL string
|
|
useDBSQL string
|
|
createTableSQL string
|
|
dropTableSQL string
|
|
selectSQL string
|
|
|
|
store kv.Storage
|
|
dom *domain.Domain
|
|
}
|
|
|
|
func (s *testSessionSuite) SetUpSuite(c *C) {
|
|
s.dbName = "test_session_db"
|
|
s.dropTableSQL = `Drop TABLE if exists t;`
|
|
s.createTableSQL = `CREATE TABLE t(id TEXT);`
|
|
s.selectSQL = `SELECT * from t;`
|
|
|
|
s.store = newStore(c, s.dbName)
|
|
dom, err := BootstrapSession(s.store)
|
|
c.Assert(err, IsNil)
|
|
s.dom = dom
|
|
}
|
|
|
|
func (s *testSessionSuite) TearDownSuite(c *C) {
|
|
removeStore(c, s.dbName)
|
|
s.dom.Close()
|
|
err := s.store.Close()
|
|
c.Assert(err, IsNil)
|
|
}
|
|
|
|
func (s *testSessionSuite) TestSchemaCheckerSimple(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
lease := 5 * time.Millisecond
|
|
validator := domain.NewSchemaValidator(lease)
|
|
checker := &schemaLeaseChecker{SchemaValidator: validator}
|
|
|
|
// Add some schema versions and delta table IDs.
|
|
ts := uint64(time.Now().UnixNano())
|
|
validator.Update(ts, 0, 2, []int64{1})
|
|
validator.Update(ts, 2, 4, []int64{2})
|
|
|
|
// checker's schema version is the same as the current schema version.
|
|
checker.schemaVer = 4
|
|
err := checker.Check(ts)
|
|
c.Assert(err, IsNil)
|
|
|
|
// checker's schema version is less than the current schema version, and it doesn't exist in validator's items.
|
|
// checker's related table ID isn't in validator's changed table IDs.
|
|
checker.schemaVer = 2
|
|
checker.relatedTableIDs = []int64{3}
|
|
err = checker.Check(ts)
|
|
c.Assert(err, IsNil)
|
|
// The checker's schema version isn't in validator's items.
|
|
checker.schemaVer = 1
|
|
checker.relatedTableIDs = []int64{3}
|
|
err = checker.Check(ts)
|
|
c.Assert(terror.ErrorEqual(err, domain.ErrInfoSchemaChanged), IsTrue)
|
|
// checker's related table ID is in validator's changed table IDs.
|
|
checker.relatedTableIDs = []int64{2}
|
|
err = checker.Check(ts)
|
|
c.Assert(terror.ErrorEqual(err, domain.ErrInfoSchemaChanged), IsTrue)
|
|
|
|
// validator's latest schema version is expired.
|
|
time.Sleep(lease + time.Microsecond)
|
|
checker.schemaVer = 4
|
|
checker.relatedTableIDs = []int64{3}
|
|
err = checker.Check(ts)
|
|
c.Assert(err, IsNil)
|
|
nowTS := uint64(time.Now().UnixNano())
|
|
// Use checker.SchemaValidator.Check instead of checker.Check here because backoff make CI slow.
|
|
result := checker.SchemaValidator.Check(nowTS, checker.schemaVer, checker.relatedTableIDs)
|
|
c.Assert(result, Equals, domain.ResultUnknown)
|
|
}
|
|
|
|
func (s *testSessionSuite) TestIssue827(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
dbName := "test_issue827"
|
|
dropDBSQL := fmt.Sprintf("drop database %s;", dbName)
|
|
se := newSession(c, s.store, dbName)
|
|
se1 := newSession(c, s.store, dbName)
|
|
|
|
mustExecSQL(c, se, "drop table if exists t1")
|
|
c.Assert(se.(*session).txn, IsNil)
|
|
mustExecSQL(c, se, "create table t1 (c2 int, c3 int, c1 int not null auto_increment, PRIMARY KEY (c1))")
|
|
mustExecSQL(c, se, "insert into t1 set c2 = 30")
|
|
|
|
mustExecSQL(c, se, "drop table if exists t")
|
|
c.Assert(se.(*session).txn, IsNil)
|
|
mustExecSQL(c, se, "create table t (c2 int, c1 int not null auto_increment, PRIMARY KEY (c1))")
|
|
mustExecSQL(c, se, "insert into t (c2) values (1), (2), (3), (4), (5)")
|
|
|
|
// insert values
|
|
lastInsertID := se.LastInsertID()
|
|
mustExecSQL(c, se, "begin")
|
|
mustExecSQL(c, se, "insert into t (c2) values (11), (12), (13)")
|
|
rs, err := exec(se, "select c1 from t where c2 = 11")
|
|
c.Assert(err, IsNil)
|
|
expect, err := GetRows(rs)
|
|
c.Assert(err, IsNil)
|
|
_, err = exec(se, "update t set c2 = 33 where c2 = 1")
|
|
c.Assert(err, IsNil)
|
|
|
|
mustExecSQL(c, se1, "begin")
|
|
mustExecSQL(c, se1, "update t set c2 = 22 where c2 = 1")
|
|
mustExecSQL(c, se1, "commit")
|
|
|
|
_, err = exec(se, "commit")
|
|
c.Assert(err, IsNil)
|
|
|
|
rs, err = exec(se, "select c1 from t where c2 = 11")
|
|
c.Assert(err, IsNil)
|
|
r, err := GetRows(rs)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(r, DeepEquals, expect)
|
|
currLastInsertID := se.GetSessionVars().PrevLastInsertID
|
|
c.Assert(lastInsertID+5, Equals, currLastInsertID)
|
|
|
|
// insert set
|
|
lastInsertID = currLastInsertID
|
|
mustExecSQL(c, se, "begin")
|
|
mustExecSQL(c, se, "insert into t set c2 = 31")
|
|
rs, err = exec(se, "select c1 from t where c2 = 31")
|
|
c.Assert(err, IsNil)
|
|
expect, err = GetRows(rs)
|
|
c.Assert(err, IsNil)
|
|
_, err = exec(se, "update t set c2 = 44 where c2 = 2")
|
|
c.Assert(err, IsNil)
|
|
|
|
mustExecSQL(c, se1, "begin")
|
|
mustExecSQL(c, se1, "update t set c2 = 55 where c2 = 2")
|
|
mustExecSQL(c, se1, "commit")
|
|
|
|
_, err = exec(se, "commit")
|
|
c.Assert(err, IsNil)
|
|
|
|
rs, err = exec(se, "select c1 from t where c2 = 31")
|
|
c.Assert(err, IsNil)
|
|
r, err = GetRows(rs)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(r, DeepEquals, expect)
|
|
currLastInsertID = se.GetSessionVars().PrevLastInsertID
|
|
c.Assert(lastInsertID+3, Equals, currLastInsertID)
|
|
|
|
// replace
|
|
lastInsertID = currLastInsertID
|
|
mustExecSQL(c, se, "begin")
|
|
mustExecSQL(c, se, "insert into t (c2) values (21), (22), (23)")
|
|
rs, err = exec(se, "select c1 from t where c2 = 21")
|
|
c.Assert(err, IsNil)
|
|
expect, err = GetRows(rs)
|
|
c.Assert(err, IsNil)
|
|
_, err = exec(se, "update t set c2 = 66 where c2 = 3")
|
|
c.Assert(err, IsNil)
|
|
|
|
mustExecSQL(c, se1, "begin")
|
|
mustExecSQL(c, se1, "update t set c2 = 77 where c2 = 3")
|
|
mustExecSQL(c, se1, "commit")
|
|
|
|
_, err = exec(se, "commit")
|
|
c.Assert(err, IsNil)
|
|
|
|
rs, err = exec(se, "select c1 from t where c2 = 21")
|
|
c.Assert(err, IsNil)
|
|
r, err = GetRows(rs)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(r, DeepEquals, expect)
|
|
currLastInsertID = se.GetSessionVars().PrevLastInsertID
|
|
c.Assert(lastInsertID+1, Equals, currLastInsertID)
|
|
|
|
// update
|
|
lastInsertID = currLastInsertID
|
|
mustExecSQL(c, se, "begin")
|
|
mustExecSQL(c, se, "insert into t set c2 = 41")
|
|
mustExecSQL(c, se, "update t set c1 = 0 where c2 = 41")
|
|
rs, err = exec(se, "select c1 from t where c2 = 41")
|
|
c.Assert(err, IsNil)
|
|
expect, err = GetRows(rs)
|
|
c.Assert(err, IsNil)
|
|
_, err = exec(se, "update t set c2 = 88 where c2 = 4")
|
|
c.Assert(err, IsNil)
|
|
|
|
mustExecSQL(c, se1, "begin")
|
|
mustExecSQL(c, se1, "update t set c2 = 99 where c2 = 4")
|
|
mustExecSQL(c, se1, "commit")
|
|
|
|
_, err = exec(se, "commit")
|
|
c.Assert(err, IsNil)
|
|
|
|
rs, err = exec(se, "select c1 from t where c2 = 41")
|
|
c.Assert(err, IsNil)
|
|
r, err = GetRows(rs)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(r, DeepEquals, expect)
|
|
currLastInsertID = se.GetSessionVars().PrevLastInsertID
|
|
c.Assert(lastInsertID+3, Equals, currLastInsertID)
|
|
|
|
// prepare
|
|
lastInsertID = currLastInsertID
|
|
mustExecSQL(c, se, "begin")
|
|
mustExecSQL(c, se, "prepare stmt from 'insert into t (c2) values (?)'")
|
|
mustExecSQL(c, se, "set @v1=100")
|
|
mustExecSQL(c, se, "set @v2=200")
|
|
mustExecSQL(c, se, "set @v3=300")
|
|
mustExecSQL(c, se, "execute stmt using @v1")
|
|
mustExecSQL(c, se, "execute stmt using @v2")
|
|
mustExecSQL(c, se, "execute stmt using @v3")
|
|
mustExecSQL(c, se, "deallocate prepare stmt")
|
|
rs, err = exec(se, "select c1 from t where c2 = 12")
|
|
c.Assert(err, IsNil)
|
|
expect, err = GetRows(rs)
|
|
c.Assert(err, IsNil)
|
|
_, err = exec(se, "update t set c2 = 111 where c2 = 5")
|
|
c.Assert(err, IsNil)
|
|
|
|
mustExecSQL(c, se1, "begin")
|
|
mustExecSQL(c, se1, "update t set c2 = 222 where c2 = 5")
|
|
mustExecSQL(c, se1, "commit")
|
|
|
|
_, err = exec(se, "commit")
|
|
c.Assert(err, IsNil)
|
|
|
|
rs, err = exec(se, "select c1 from t where c2 = 12")
|
|
c.Assert(err, IsNil)
|
|
r, err = GetRows(rs)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(r, DeepEquals, expect)
|
|
currLastInsertID = se.GetSessionVars().PrevLastInsertID
|
|
c.Assert(lastInsertID+3, Equals, currLastInsertID)
|
|
|
|
mustExecSQL(c, se, dropDBSQL)
|
|
se.Close()
|
|
se1.Close()
|
|
}
|
|
|
|
func (s *testSessionSuite) TestIssue996(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
dbName := "test_issue827"
|
|
dropDBSQL := fmt.Sprintf("drop database %s;", dbName)
|
|
se := newSession(c, s.store, dbName)
|
|
|
|
mustExecSQL(c, se, "drop table if exists t")
|
|
c.Assert(se.(*session).txn, IsNil)
|
|
mustExecSQL(c, se, "create table t (c2 int, c3 int, c1 int not null auto_increment, PRIMARY KEY (c1))")
|
|
mustExecSQL(c, se, "insert into t set c2 = 30")
|
|
|
|
// insert values
|
|
lastInsertID := se.LastInsertID()
|
|
mustExecSQL(c, se, "prepare stmt1 from 'insert into t (c2) values (?)'")
|
|
mustExecSQL(c, se, "set @v1=10")
|
|
mustExecSQL(c, se, "set @v2=20")
|
|
mustExecSQL(c, se, "execute stmt1 using @v1")
|
|
mustExecSQL(c, se, "execute stmt1 using @v2")
|
|
mustExecSQL(c, se, "deallocate prepare stmt1")
|
|
rs, err := exec(se, "select c1 from t where c2 = 20")
|
|
c.Assert(err, IsNil)
|
|
r, err := GetRows(rs)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(r, NotNil)
|
|
currLastInsertID := se.GetSessionVars().PrevLastInsertID
|
|
c.Assert(r[0][0].GetValue(), DeepEquals, int64(currLastInsertID))
|
|
c.Assert(lastInsertID+2, Equals, currLastInsertID)
|
|
|
|
mustExecSQL(c, se, dropDBSQL)
|
|
}
|
|
|
|
func (s *testSessionSuite) TestIssue986(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
sqlText := `CREATE TABLE address (
|
|
id bigint(20) NOT NULL AUTO_INCREMENT,
|
|
PRIMARY KEY (id));`
|
|
dbName := "test_issue827"
|
|
dropDBSQL := fmt.Sprintf("drop database %s;", dbName)
|
|
se := newSession(c, s.store, dbName)
|
|
mustExecSQL(c, se, sqlText)
|
|
sqlText = `insert into address values ('10')`
|
|
mustExecSQL(c, se, sqlText)
|
|
|
|
mustExecSQL(c, se, dropDBSQL)
|
|
}
|
|
|
|
func (s *testSessionSuite) TestIssue1089(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
dbName := "test_issue1089"
|
|
dropDBSQL := fmt.Sprintf("drop database %s;", dbName)
|
|
se := newSession(c, s.store, dbName)
|
|
|
|
r := mustExecSQL(c, se, "select cast(0.5 as unsigned)")
|
|
row, err := r.Next()
|
|
c.Assert(err, IsNil)
|
|
match(c, row.Data, 1)
|
|
r = mustExecSQL(c, se, "select cast(-0.5 as signed)")
|
|
row, err = r.Next()
|
|
c.Assert(err, IsNil)
|
|
match(c, row.Data, -1)
|
|
|
|
mustExecSQL(c, se, dropDBSQL)
|
|
}
|
|
|
|
func (s *testSessionSuite) TestIssue1135(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
dbName := "test_issue1135"
|
|
dropDBSQL1 := fmt.Sprintf("drop database %s;", dbName)
|
|
dropDBSQL2 := fmt.Sprintf("drop database %s;", dbName+"1")
|
|
se := newSession(c, s.store, dbName)
|
|
se1 := newSession(c, s.store, dbName+"1")
|
|
|
|
mustExecSQL(c, se1, "drop table if exists t")
|
|
mustExecSQL(c, se1, "create table t (F1 VARCHAR(30));")
|
|
mustExecSQL(c, se1, "insert into t (F1) values ('1'), ('4');")
|
|
|
|
mustExecSQL(c, se, "drop table if exists t")
|
|
mustExecSQL(c, se, "create table t (F1 VARCHAR(30));")
|
|
mustExecSQL(c, se, "insert into t (F1) values ('1'), ('2');")
|
|
mustExecSQL(c, se, "delete m1 from t m2,t m1 where m1.F1>1;")
|
|
r := mustExecSQL(c, se, "select * from t;")
|
|
row, err := r.Next()
|
|
c.Assert(err, IsNil)
|
|
match(c, row.Data, []interface{}{'1'})
|
|
|
|
mustExecSQL(c, se, "drop table if exists t")
|
|
mustExecSQL(c, se, "create table t (F1 VARCHAR(30));")
|
|
mustExecSQL(c, se, "insert into t (F1) values ('1'), ('2');")
|
|
mustExecSQL(c, se, "delete m1 from t m1,t m2 where true and m1.F1<2;")
|
|
r = mustExecSQL(c, se, "select * from t;")
|
|
row, err = r.Next()
|
|
c.Assert(err, IsNil)
|
|
match(c, row.Data, []interface{}{'2'})
|
|
|
|
mustExecSQL(c, se, "drop table if exists t")
|
|
mustExecSQL(c, se, "create table t (F1 VARCHAR(30));")
|
|
mustExecSQL(c, se, "insert into t (F1) values ('1'), ('2');")
|
|
mustExecSQL(c, se, "delete m1 from t m1,t m2 where false;")
|
|
r = mustExecSQL(c, se, "select * from t;")
|
|
row, err = r.Next()
|
|
c.Assert(err, IsNil)
|
|
match(c, row.Data, []interface{}{'1'})
|
|
row, err = r.Next()
|
|
c.Assert(err, IsNil)
|
|
match(c, row.Data, []interface{}{'2'})
|
|
|
|
mustExecSQL(c, se, "drop table if exists t")
|
|
mustExecSQL(c, se, "create table t (F1 VARCHAR(30));")
|
|
mustExecSQL(c, se, "insert into t (F1) values ('1'), ('2');")
|
|
mustExecSQL(c, se, "delete m1, m2 from t m1,t m2 where m1.F1>m2.F1;")
|
|
r = mustExecSQL(c, se, "select * from t;")
|
|
row, err = r.Next()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(row, IsNil)
|
|
|
|
mustExecSQL(c, se, "drop table if exists t")
|
|
mustExecSQL(c, se, "create table t (F1 VARCHAR(30));")
|
|
mustExecSQL(c, se, "insert into t (F1) values ('1'), ('2');")
|
|
sql := fmt.Sprintf("delete %s.t from %s.t inner join %s.t where %s.t.F1 > %s.t.F1",
|
|
dbName+"1", dbName+"1", dbName, dbName+"1", dbName)
|
|
mustExecSQL(c, se1, sql)
|
|
r = mustExecSQL(c, se1, "select * from t;")
|
|
row, err = r.Next()
|
|
c.Assert(err, IsNil)
|
|
match(c, row.Data, []interface{}{'1'})
|
|
|
|
mustExecSQL(c, se, dropDBSQL1)
|
|
mustExecSQL(c, se, dropDBSQL2)
|
|
}
|
|
|
|
func (s *testSessionSuite) TestIssue1114(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
dbName := "test_issue1114"
|
|
dropDBSQL := fmt.Sprintf("drop database %s;", dbName)
|
|
se := newSession(c, s.store, dbName)
|
|
|
|
mustExecSQL(c, se, "set @tmp = 0")
|
|
mustExecSQL(c, se, "set @tmp := @tmp + 1")
|
|
r := mustExecSQL(c, se, "select @tmp")
|
|
row, err := r.Next()
|
|
c.Assert(err, IsNil)
|
|
match(c, row.Data, 1)
|
|
|
|
r = mustExecSQL(c, se, "select @tmp1 = 1, @tmp2 := 2")
|
|
row, err = r.Next()
|
|
c.Assert(err, IsNil)
|
|
match(c, row.Data, nil, 2)
|
|
|
|
r = mustExecSQL(c, se, "select @tmp1 := 11, @tmp2")
|
|
row, err = r.Next()
|
|
c.Assert(err, IsNil)
|
|
match(c, row.Data, 11, 2)
|
|
|
|
mustExecSQL(c, se, "drop table if exists t")
|
|
mustExecSQL(c, se, "create table t (c int);")
|
|
mustExecSQL(c, se, "insert into t values (1),(2);")
|
|
mustExecSQL(c, se, "update t set c = 3 WHERE c = @var:= 1")
|
|
r = mustExecSQL(c, se, "select * from t")
|
|
row, err = r.Next()
|
|
c.Assert(err, IsNil)
|
|
match(c, row.Data, 3)
|
|
row, err = r.Next()
|
|
c.Assert(err, IsNil)
|
|
match(c, row.Data, 2)
|
|
|
|
r = mustExecSQL(c, se, "select @tmp := count(*) from t")
|
|
row, err = r.Next()
|
|
c.Assert(err, IsNil)
|
|
match(c, row.Data, 2)
|
|
|
|
r = mustExecSQL(c, se, "select @tmp := c-2 from t where c=3")
|
|
row, err = r.Next()
|
|
c.Assert(err, IsNil)
|
|
match(c, row.Data, 1)
|
|
|
|
mustExecSQL(c, se, dropDBSQL)
|
|
}
|
|
|
|
func (s *testSessionSuite) TestMySQLTypes(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
dbName := "test_mysql_types"
|
|
dropDBSQL := fmt.Sprintf("drop database %s;", dbName)
|
|
se := newSession(c, s.store, dbName)
|
|
|
|
r := mustExecSQL(c, se, `select 0x01 + 1, x'4D7953514C' = "MySQL"`)
|
|
row, err := r.Next()
|
|
c.Assert(err, IsNil)
|
|
match(c, row.Data, 2, 1)
|
|
r.Close()
|
|
|
|
r = mustExecSQL(c, se, `select 0b01 + 1, 0b01000001 = "A"`)
|
|
row, err = r.Next()
|
|
c.Assert(err, IsNil)
|
|
match(c, row.Data, 2, 1)
|
|
r.Close()
|
|
|
|
mustExecSQL(c, se, dropDBSQL)
|
|
}
|
|
|
|
func (s *testSessionSuite) TestHaving(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
dbName := "test_having"
|
|
dropDBSQL := fmt.Sprintf("drop database %s;", dbName)
|
|
se := newSession(c, s.store, dbName)
|
|
mustExecFailed(c, se, "select c1 from t having c2")
|
|
mustExecFailed(c, se, "select c1 from t having c2 + 1")
|
|
mustExecFailed(c, se, "select c1 from t group by c2 + 1 having c2")
|
|
mustExecFailed(c, se, "select c1 from t group by c2 + 1 having c2 + 1")
|
|
mustExecFailed(c, se, "select c1 as c2, c2 from t having c2")
|
|
mustExecFailed(c, se, "select c1 as c2, c2 from t having c2 + 1")
|
|
mustExecFailed(c, se, "select c1 as a, c2 as a from t having a")
|
|
mustExecFailed(c, se, "select c1 as a, c2 as a from t having a + 1")
|
|
mustExecFailed(c, se, "select c1 + 1 from t having c1")
|
|
mustExecFailed(c, se, "select c1 + 1 from t having c1 + 1")
|
|
mustExecFailed(c, se, "select a.c1 as c, b.c1 as d from t as a, t as b having c1")
|
|
mustExecFailed(c, se, "select 1 from t having sum(avg(c1))")
|
|
|
|
mustExecSQL(c, se, dropDBSQL)
|
|
}
|
|
|
|
func (s *testSessionSuite) TestIssue461(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
dbName := "test_issue461"
|
|
dropDBSQL := fmt.Sprintf("drop database %s;", dbName)
|
|
se1 := newSession(c, s.store, dbName)
|
|
mustExecSQL(c, se1,
|
|
`CREATE TABLE test ( id int(11) UNSIGNED NOT NULL AUTO_INCREMENT, val int UNIQUE, PRIMARY KEY (id)); `)
|
|
mustExecSQL(c, se1, "begin;")
|
|
mustExecSQL(c, se1, "insert into test(id, val) values(1, 1);")
|
|
se2 := newSession(c, s.store, dbName)
|
|
mustExecSQL(c, se2, "begin;")
|
|
mustExecSQL(c, se2, "insert into test(id, val) values(2, 2);")
|
|
se3 := newSession(c, s.store, dbName)
|
|
mustExecSQL(c, se3, "begin;")
|
|
mustExecSQL(c, se3, "insert into test(id, val) values(1, 2);")
|
|
mustExecSQL(c, se3, "commit;")
|
|
_, err := se1.Execute("commit")
|
|
c.Assert(err, NotNil)
|
|
// Check error type and error message
|
|
c.Assert(terror.ErrorEqual(err, kv.ErrKeyExists), IsTrue)
|
|
c.Assert(err.Error(), Equals, "[kv:1062]Duplicate entry '1' for key 'PRIMARY'")
|
|
|
|
_, err = se2.Execute("commit")
|
|
c.Assert(err, NotNil)
|
|
c.Assert(terror.ErrorEqual(err, kv.ErrKeyExists), IsTrue)
|
|
c.Assert(err.Error(), Equals, "[kv:1062]Duplicate entry '2' for key 'val'")
|
|
|
|
se := newSession(c, s.store, dbName)
|
|
mustExecSQL(c, se, "drop table test;")
|
|
mustExecSQL(c, se, dropDBSQL)
|
|
}
|
|
|
|
func (s *testSessionSuite) TestIssue463(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
// Testcase for https://github.com/pingcap/tidb/issues/463
|
|
dbName := "test_issue463"
|
|
dropDBSQL := fmt.Sprintf("drop database %s;", dbName)
|
|
se := newSession(c, s.store, dbName)
|
|
mustExecSQL(c, se, "DROP TABLE IF EXISTS test")
|
|
mustExecSQL(c, se,
|
|
`CREATE TABLE test (
|
|
id int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
val int UNIQUE,
|
|
PRIMARY KEY (id)
|
|
);`)
|
|
mustExecSQL(c, se, "insert into test(id, val) values(1, 1);")
|
|
mustExecFailed(c, se, "insert into test(id, val) values(2, 1);")
|
|
mustExecSQL(c, se, "insert into test(id, val) values(2, 2);")
|
|
|
|
mustExecSQL(c, se, "begin;")
|
|
mustExecSQL(c, se, "insert into test(id, val) values(3, 3);")
|
|
mustExecFailed(c, se, "insert into test(id, val) values(4, 3);")
|
|
mustExecSQL(c, se, "insert into test(id, val) values(4, 4);")
|
|
mustExecSQL(c, se, "commit;")
|
|
se1 := newSession(c, s.store, dbName)
|
|
mustExecSQL(c, se1, "begin;")
|
|
mustExecSQL(c, se1, "insert into test(id, val) values(5, 6);")
|
|
mustExecSQL(c, se, "begin;")
|
|
mustExecSQL(c, se, "insert into test(id, val) values(20, 6);")
|
|
mustExecSQL(c, se, "commit;")
|
|
mustExecFailed(c, se1, "commit;")
|
|
mustExecSQL(c, se1, "insert into test(id, val) values(5, 5);")
|
|
|
|
mustExecSQL(c, se, "drop table test;")
|
|
|
|
mustExecSQL(c, se,
|
|
`CREATE TABLE test (
|
|
id int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
val1 int UNIQUE,
|
|
val2 int UNIQUE,
|
|
PRIMARY KEY (id)
|
|
);`)
|
|
mustExecSQL(c, se, "insert into test(id, val1, val2) values(1, 1, 1);")
|
|
mustExecSQL(c, se, "insert into test(id, val1, val2) values(2, 2, 2);")
|
|
mustExecFailed(c, se, "update test set val1 = 3, val2 = 2 where id = 1;")
|
|
mustExecSQL(c, se, "insert into test(id, val1, val2) values(3, 3, 3);")
|
|
mustExecSQL(c, se, "drop table test;")
|
|
|
|
mustExecSQL(c, se, dropDBSQL)
|
|
}
|
|
|
|
func (s *testSessionSuite) TestIssue177(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
dbName := "test_issue177"
|
|
dropDBSQL := fmt.Sprintf("drop database %s;", dbName)
|
|
se := newSession(c, s.store, dbName)
|
|
mustExecSQL(c, se, `drop table if exists t1;`)
|
|
mustExecSQL(c, se, `drop table if exists t2;`)
|
|
mustExecSQL(c, se, "CREATE TABLE `t1` ( `a` char(3) NOT NULL default '', `b` char(3) NOT NULL default '', `c` char(3) NOT NULL default '', PRIMARY KEY (`a`,`b`,`c`)) ENGINE=InnoDB;")
|
|
mustExecSQL(c, se, "CREATE TABLE `t2` ( `a` char(3) NOT NULL default '', `b` char(3) NOT NULL default '', `c` char(3) NOT NULL default '', PRIMARY KEY (`a`,`b`,`c`)) ENGINE=InnoDB;")
|
|
mustExecSQL(c, se, `INSERT INTO t1 VALUES (1,1,1);`)
|
|
mustExecSQL(c, se, `INSERT INTO t2 VALUES (1,1,1);`)
|
|
mustExecSQL(c, se, `PREPARE my_stmt FROM "SELECT t1.b, count(*) FROM t1 group by t1.b having count(*) > ALL (SELECT COUNT(*) FROM t2 WHERE t2.a=1 GROUP By t2.b)";`)
|
|
mustExecSQL(c, se, `EXECUTE my_stmt;`)
|
|
mustExecSQL(c, se, `EXECUTE my_stmt;`)
|
|
mustExecSQL(c, se, `deallocate prepare my_stmt;`)
|
|
mustExecSQL(c, se, `drop table t1,t2;`)
|
|
|
|
mustExecSQL(c, se, dropDBSQL)
|
|
}
|
|
|
|
func (s *testSessionSuite) TestIssue454(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
dbName := "test_issue454"
|
|
dropDBSQL := fmt.Sprintf("drop database %s;", dbName)
|
|
se := newSession(c, s.store, dbName)
|
|
|
|
mustExecSQL(c, se, "drop table if exists t")
|
|
mustExecSQL(c, se, "drop table if exists t1")
|
|
mustExecSQL(c, se, "create table t1 (c1 int, c2 int, c3 int);")
|
|
mustExecSQL(c, se, "insert into t1 set c1=1, c2=2, c3=1;")
|
|
mustExecSQL(c, se, "create table t (c1 int, c2 int, c3 int, primary key (c1));")
|
|
mustExecSQL(c, se, "insert into t set c1=1, c2=4;")
|
|
mustExecSQL(c, se, "insert into t select * from t1 limit 1 on duplicate key update c3=3333;")
|
|
|
|
mustExecSQL(c, se, dropDBSQL)
|
|
}
|
|
|
|
func (s *testSessionSuite) TestIssue456(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
dbName := "test_issue456"
|
|
dropDBSQL := fmt.Sprintf("drop database %s;", dbName)
|
|
se := newSession(c, s.store, dbName)
|
|
|
|
mustExecSQL(c, se, "drop table if exists t")
|
|
mustExecSQL(c, se, "drop table if exists t1")
|
|
mustExecSQL(c, se, "create table t1 (c1 int, c2 int, c3 int);")
|
|
mustExecSQL(c, se, "replace into t1 set c1=1, c2=2, c3=1;")
|
|
mustExecSQL(c, se, "create table t (c1 int, c2 int, c3 int, primary key (c1));")
|
|
mustExecSQL(c, se, "replace into t set c1=1, c2=4;")
|
|
mustExecSQL(c, se, "replace into t select * from t1 limit 1;")
|
|
|
|
mustExecSQL(c, se, dropDBSQL)
|
|
}
|