1 Star 0 Fork 58

woerwin/tidb

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
new_session_test.go 53.05 KB
一键复制 编辑 原始数据 按行查看 历史
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468
// 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_test
import (
"fmt"
"math"
"sync"
"sync/atomic"
"time"
. "github.com/pingcap/check"
"github.com/pingcap/tidb"
"github.com/pingcap/tidb/context"
"github.com/pingcap/tidb/domain"
"github.com/pingcap/tidb/executor"
"github.com/pingcap/tidb/kv"
"github.com/pingcap/tidb/model"
"github.com/pingcap/tidb/mysql"
"github.com/pingcap/tidb/parser"
"github.com/pingcap/tidb/privilege/privileges"
"github.com/pingcap/tidb/sessionctx"
"github.com/pingcap/tidb/sessionctx/variable"
"github.com/pingcap/tidb/store/tikv"
"github.com/pingcap/tidb/store/tikv/mock-tikv"
"github.com/pingcap/tidb/table/tables"
"github.com/pingcap/tidb/terror"
"github.com/pingcap/tidb/util/auth"
"github.com/pingcap/tidb/util/sqlexec"
"github.com/pingcap/tidb/util/testkit"
"github.com/pingcap/tidb/util/testleak"
"github.com/pingcap/tidb/util/types"
)
var _ = Suite(&testSessionSuite{})
type testSessionSuite struct {
cluster *mocktikv.Cluster
mvccStore *mocktikv.MvccStore
store kv.Storage
dom *domain.Domain
}
func (s *testSessionSuite) SetUpSuite(c *C) {
testleak.BeforeTest()
s.cluster = mocktikv.NewCluster()
mocktikv.BootstrapWithSingleStore(s.cluster)
s.mvccStore = mocktikv.NewMvccStore()
store, err := tikv.NewMockTikvStore(
tikv.WithCluster(s.cluster),
tikv.WithMVCCStore(s.mvccStore),
)
c.Assert(err, IsNil)
s.store = store
tidb.SetSchemaLease(0)
tidb.SetStatsLease(0)
s.dom, err = tidb.BootstrapSession(s.store)
c.Assert(err, IsNil)
}
func (s *testSessionSuite) TearDownSuite(c *C) {
s.dom.Close()
s.store.Close()
testleak.AfterTest(c)()
}
func (s *testSessionSuite) TearDownTest(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
r := tk.MustQuery("show tables")
for _, tb := range r.Rows() {
tableName := tb[0]
tk.MustExec(fmt.Sprintf("drop table %v", tableName))
}
}
func (s *testSessionSuite) TestErrorRollback(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("drop table if exists t_rollback")
tk.MustExec("create table t_rollback (c1 int, c2 int, primary key(c1))")
tk.MustExec("insert into t_rollback values (0, 0)")
var wg sync.WaitGroup
cnt := 4
wg.Add(cnt)
num := 100
// retry forever
tidb.SetCommitRetryLimit(math.MaxInt64)
defer tidb.SetCommitRetryLimit(10)
for i := 0; i < cnt; i++ {
go func() {
defer wg.Done()
localTk := testkit.NewTestKitWithInit(c, s.store)
for j := 0; j < num; j++ {
localTk.Exec("insert into t_rollback values (1, 1)")
localTk.MustExec("update t_rollback set c2 = c2 + 1 where c1 = 0")
}
}()
}
wg.Wait()
tk.MustQuery("select c2 from t_rollback where c1 = 0").Check(testkit.Rows(fmt.Sprint(cnt * num)))
}
func (s *testSessionSuite) TestQueryString(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("create table mutil1 (a int);create table multi2 (a int)")
queryStr := tk.Se.Value(context.QueryString)
c.Assert(queryStr, Equals, "create table multi2 (a int)")
}
func (s *testSessionSuite) TestAffectedRows(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(id TEXT)")
tk.MustExec(`INSERT INTO t VALUES ("a");`)
c.Assert(int(tk.Se.AffectedRows()), Equals, 1)
tk.MustExec(`INSERT INTO t VALUES ("b");`)
c.Assert(int(tk.Se.AffectedRows()), Equals, 1)
tk.MustExec(`UPDATE t set id = 'c' where id = 'a';`)
c.Assert(int(tk.Se.AffectedRows()), Equals, 1)
tk.MustExec(`UPDATE t set id = 'a' where id = 'a';`)
c.Assert(int(tk.Se.AffectedRows()), Equals, 0)
tk.MustQuery(`SELECT * from t`).Check(testkit.Rows("c", "b"))
c.Assert(int(tk.Se.AffectedRows()), Equals, 0)
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (id int, data int)")
tk.MustExec(`INSERT INTO t VALUES (1, 0), (0, 0), (1, 1);`)
tk.MustExec(`UPDATE t set id = 1 where data = 0;`)
c.Assert(int(tk.Se.AffectedRows()), Equals, 1)
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (id int, c1 timestamp);")
tk.MustExec(`insert t values(1, 0);`)
tk.MustExec(`UPDATE t set id = 1 where id = 1;`)
c.Assert(int(tk.Se.AffectedRows()), Equals, 0)
// With ON DUPLICATE KEY UPDATE, the affected-rows value per row is 1 if the row is inserted as a new row,
// 2 if an existing row is updated, and 0 if an existing row is set to its current values.
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (c1 int PRIMARY KEY, c2 int);")
tk.MustExec(`insert t values(1, 1);`)
tk.MustExec(`insert into t values (1, 1) on duplicate key update c2=2;`)
c.Assert(int(tk.Se.AffectedRows()), Equals, 2)
tk.MustExec(`insert into t values (1, 1) on duplicate key update c2=2;`)
c.Assert(int(tk.Se.AffectedRows()), Equals, 0)
tk.MustExec("drop table if exists test")
createSQL := `CREATE TABLE test (
id VARCHAR(36) PRIMARY KEY NOT NULL,
factor INTEGER NOT NULL DEFAULT 2);`
tk.MustExec(createSQL)
insertSQL := `INSERT INTO test(id) VALUES('id') ON DUPLICATE KEY UPDATE factor=factor+3;`
tk.MustExec(insertSQL)
c.Assert(int(tk.Se.AffectedRows()), Equals, 1)
tk.MustExec(insertSQL)
c.Assert(int(tk.Se.AffectedRows()), Equals, 2)
tk.MustExec(insertSQL)
c.Assert(int(tk.Se.AffectedRows()), Equals, 2)
tk.Se.SetClientCapability(mysql.ClientFoundRows)
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (id int, data int)")
tk.MustExec(`INSERT INTO t VALUES (1, 0), (0, 0), (1, 1);`)
tk.MustExec(`UPDATE t set id = 1 where data = 0;`)
c.Assert(int(tk.Se.AffectedRows()), Equals, 2)
}
// See http://dev.mysql.com/doc/refman/5.7/en/commit.html
func (s *testSessionSuite) TestRowLock(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk1 := testkit.NewTestKitWithInit(c, s.store)
tk2 := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("drop table if exists t")
c.Assert(tk.Se.Txn(), IsNil)
tk.MustExec("create table t (c1 int, c2 int, c3 int)")
tk.MustExec("insert t values (11, 2, 3)")
tk.MustExec("insert t values (12, 2, 3)")
tk.MustExec("insert t values (13, 2, 3)")
tk1.MustExec("begin")
tk1.MustExec("update t set c2=21 where c1=11")
tk2.MustExec("begin")
tk2.MustExec("update t set c2=211 where c1=11")
tk2.MustExec("commit")
// tk1 will retry and the final value is 21
tk1.MustExec("commit")
// Check the result is correct
tk.MustQuery("select c2 from t where c1=11").Check(testkit.Rows("21"))
tk1.MustExec("begin")
tk1.MustExec("update t set c2=21 where c1=11")
tk2.MustExec("begin")
tk2.MustExec("update t set c2=22 where c1=12")
tk2.MustExec("commit")
tk1.MustExec("commit")
}
// See https://dev.mysql.com/doc/internals/en/status-flags.html
func (s *testSessionSuite) TestAutocommit(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("drop table if exists t;")
c.Assert(int(tk.Se.Status()&mysql.ServerStatusAutocommit), Greater, 0)
tk.MustExec("create table t (id BIGINT PRIMARY KEY AUTO_INCREMENT NOT NULL)")
c.Assert(int(tk.Se.Status()&mysql.ServerStatusAutocommit), Greater, 0)
tk.MustExec("insert t values ()")
c.Assert(int(tk.Se.Status()&mysql.ServerStatusAutocommit), Greater, 0)
tk.MustExec("begin")
c.Assert(int(tk.Se.Status()&mysql.ServerStatusAutocommit), Greater, 0)
tk.MustExec("insert t values ()")
c.Assert(int(tk.Se.Status()&mysql.ServerStatusAutocommit), Greater, 0)
tk.MustExec("drop table if exists t")
c.Assert(int(tk.Se.Status()&mysql.ServerStatusAutocommit), Greater, 0)
tk.MustExec("create table t (id BIGINT PRIMARY KEY AUTO_INCREMENT NOT NULL)")
c.Assert(int(tk.Se.Status()&mysql.ServerStatusAutocommit), Greater, 0)
tk.MustExec("set autocommit=0")
c.Assert(int(tk.Se.Status()&mysql.ServerStatusAutocommit), Equals, 0)
tk.MustExec("insert t values ()")
c.Assert(int(tk.Se.Status()&mysql.ServerStatusAutocommit), Equals, 0)
tk.MustExec("commit")
c.Assert(int(tk.Se.Status()&mysql.ServerStatusAutocommit), Equals, 0)
tk.MustExec("drop table if exists t")
c.Assert(int(tk.Se.Status()&mysql.ServerStatusAutocommit), Equals, 0)
tk.MustExec("set autocommit='On'")
c.Assert(int(tk.Se.Status()&mysql.ServerStatusAutocommit), Greater, 0)
}
func (s *testSessionSuite) TestGlobalVarAccessor(c *C) {
varName := "max_allowed_packet"
varValue := "67108864" // This is the default value for max_allowed_packet
varValue1 := "4194305"
varValue2 := "4194306"
tk := testkit.NewTestKitWithInit(c, s.store)
se := tk.Se.(variable.GlobalVarAccessor)
// Get globalSysVar twice and get the same value
v, err := se.GetGlobalSysVar(varName)
c.Assert(err, IsNil)
c.Assert(v, Equals, varValue)
v, err = se.GetGlobalSysVar(varName)
c.Assert(err, IsNil)
c.Assert(v, Equals, varValue)
// Set global var to another value
err = se.SetGlobalSysVar(varName, varValue1)
c.Assert(err, IsNil)
v, err = se.GetGlobalSysVar(varName)
c.Assert(err, IsNil)
c.Assert(v, Equals, varValue1)
c.Assert(tk.Se.CommitTxn(), IsNil)
tk1 := testkit.NewTestKitWithInit(c, s.store)
se1 := tk1.Se.(variable.GlobalVarAccessor)
v, err = se1.GetGlobalSysVar(varName)
c.Assert(err, IsNil)
c.Assert(v, Equals, varValue1)
err = se1.SetGlobalSysVar(varName, varValue2)
c.Assert(err, IsNil)
v, err = se1.GetGlobalSysVar(varName)
c.Assert(err, IsNil)
c.Assert(v, Equals, varValue2)
c.Assert(tk1.Se.CommitTxn(), IsNil)
// Make sure the change is visible to any client that accesses that global variable.
v, err = se.GetGlobalSysVar(varName)
c.Assert(err, IsNil)
c.Assert(v, Equals, varValue2)
}
func (s *testSessionSuite) TestRetryResetStmtCtx(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.Se.Execute("create table retrytxn (a int unique, b int)")
tk.MustExec("insert retrytxn values (1, 1)")
tk.MustExec("begin")
tk.MustExec("update retrytxn set b = b + 1 where a = 1")
// Make retryable error.
tk1 := testkit.NewTestKitWithInit(c, s.store)
tk1.MustExec("update retrytxn set b = b + 1 where a = 1")
err := tk.Se.CommitTxn()
c.Assert(err, IsNil)
c.Assert(tk.Se.AffectedRows(), Equals, uint64(1))
}
func (s *testSessionSuite) TestRetryCleanTxn(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("create table retrytxn (a int unique, b int)")
tk.MustExec("insert retrytxn values (1, 1)")
tk.MustExec("begin")
tk.MustExec("update retrytxn set b = b + 1 where a = 1")
// Make retryable error.
tk1 := testkit.NewTestKitWithInit(c, s.store)
tk1.MustExec("update retrytxn set b = b + 1 where a = 1")
// Hijack retry history, add a statement that returns error.
history := tidb.GetHistory(tk.Se)
stmtNode, err := parser.New().ParseOneStmt("insert retrytxn values (2, 'a')", "", "")
c.Assert(err, IsNil)
stmt, _ := tidb.Compile(tk.Se, stmtNode)
executor.ResetStmtCtx(tk.Se, stmtNode)
history.Add(0, stmt, tk.Se.GetSessionVars().StmtCtx)
_, err = tk.Exec("commit")
c.Assert(err, NotNil)
c.Assert(tk.Se.Txn(), IsNil)
c.Assert(tk.Se.GetSessionVars().InTxn(), IsFalse)
}
// TestTruncateAlloc tests that the auto_increment ID does not reuse the old table's allocator.
func (s *testSessionSuite) TestTruncateAlloc(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("create table truncate_id (a int primary key auto_increment)")
tk.MustExec("insert truncate_id values (), (), (), (), (), (), (), (), (), ()")
tk.MustExec("truncate table truncate_id")
tk.MustExec("insert truncate_id values (), (), (), (), (), (), (), (), (), ()")
tk.MustQuery("select a from truncate_id where a > 11").Check(testkit.Rows())
}
func (s *testSessionSuite) TestString(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("select 1")
// here to check the panic bug in String() when txn is nil after committed.
c.Log(tk.Se.String())
}
func (s *testSessionSuite) TestDatabase(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
// Test database.
tk.MustExec("create database xxx")
tk.MustExec("drop database xxx")
tk.MustExec("drop database if exists xxx")
tk.MustExec("create database xxx")
tk.MustExec("create database if not exists xxx")
tk.MustExec("drop database if exists xxx")
// Test schema.
tk.MustExec("create schema xxx")
tk.MustExec("drop schema xxx")
tk.MustExec("drop schema if exists xxx")
tk.MustExec("create schema xxx")
tk.MustExec("create schema if not exists xxx")
tk.MustExec("drop schema if exists xxx")
}
func (s *testSessionSuite) TestExecRestrictedSQL(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
r, _, err := tk.Se.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(tk.Se, "select 1;")
c.Assert(err, IsNil)
c.Assert(len(r), Equals, 1)
}
// See https://dev.mysql.com/doc/internals/en/status-flags.html
func (s *testSessionSuite) TestInTrans(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("drop table if exists t;")
tk.MustExec("create table t (id BIGINT PRIMARY KEY AUTO_INCREMENT NOT NULL)")
tk.MustExec("insert t values ()")
tk.MustExec("begin")
c.Assert(tk.Se.Txn().Valid(), IsTrue)
tk.MustExec("insert t values ()")
c.Assert(tk.Se.Txn().Valid(), IsTrue)
tk.MustExec("drop table if exists t;")
c.Assert(tk.Se.Txn(), IsNil)
tk.MustExec("create table t (id BIGINT PRIMARY KEY AUTO_INCREMENT NOT NULL)")
c.Assert(tk.Se.Txn(), IsNil)
tk.MustExec("insert t values ()")
c.Assert(tk.Se.Txn(), IsNil)
tk.MustExec("commit")
tk.MustExec("insert t values ()")
tk.MustExec("set autocommit=0")
tk.MustExec("begin")
c.Assert(tk.Se.Txn().Valid(), IsTrue)
tk.MustExec("insert t values ()")
c.Assert(tk.Se.Txn().Valid(), IsTrue)
tk.MustExec("commit")
c.Assert(tk.Se.Txn(), IsNil)
tk.MustExec("insert t values ()")
c.Assert(tk.Se.Txn().Valid(), IsTrue)
tk.MustExec("commit")
c.Assert(tk.Se.Txn(), IsNil)
tk.MustExec("set autocommit=1")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (id BIGINT PRIMARY KEY AUTO_INCREMENT NOT NULL)")
tk.MustExec("begin")
c.Assert(tk.Se.Txn().Valid(), IsTrue)
tk.MustExec("insert t values ()")
c.Assert(tk.Se.Txn().Valid(), IsTrue)
tk.MustExec("rollback")
c.Assert(tk.Se.Txn().Valid(), IsFalse)
}
func (s *testSessionSuite) TestRetryPreparedStmt(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk1 := testkit.NewTestKitWithInit(c, s.store)
tk2 := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("drop table if exists t")
c.Assert(tk.Se.Txn(), IsNil)
tk.MustExec("create table t (c1 int, c2 int, c3 int)")
tk.MustExec("insert t values (11, 2, 3)")
tk1.MustExec("begin")
tk1.MustExec("update t set c2=? where c1=11;", 21)
tk2.MustExec("begin")
tk2.MustExec("update t set c2=? where c1=11", 22)
tk2.MustExec("commit")
tk1.MustExec("commit")
tk.MustQuery("select c2 from t where c1=11").Check(testkit.Rows("21"))
}
func (s *testSessionSuite) TestSession(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("ROLLBACK;")
tk.Se.Close()
}
func (s *testSessionSuite) TestSessionAuth(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "Any not exist username with zero password!", Hostname: "anyhost"}, []byte(""), []byte("")), IsFalse)
}
func (s *testSessionSuite) TestSkipWithGrant(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
save1 := privileges.Enable
save2 := privileges.SkipWithGrant
privileges.Enable = true
privileges.SkipWithGrant = false
c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "user_not_exist"}, []byte("yyy"), []byte("zzz")), IsFalse)
privileges.SkipWithGrant = true
c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "xxx", Hostname: "%"}, []byte("yyy"), []byte("zzz")), IsTrue)
c.Assert(tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, []byte(""), []byte("")), IsTrue)
tk.MustExec("create table t (id int)")
privileges.Enable = save1
privileges.SkipWithGrant = save2
}
func (s *testSessionSuite) TestLastInsertID(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
// insert
tk.MustExec("create table t (c1 int not null auto_increment, c2 int, PRIMARY KEY (c1))")
tk.MustExec("insert into t set c2 = 11")
tk.MustQuery("select last_insert_id()").Check(testkit.Rows("1"))
tk.MustExec("insert into t (c2) values (22), (33), (44)")
tk.MustQuery("select last_insert_id()").Check(testkit.Rows("2"))
tk.MustExec("insert into t (c1, c2) values (10, 55)")
tk.MustQuery("select last_insert_id()").Check(testkit.Rows("2"))
// replace
tk.MustExec("replace t (c2) values(66)")
tk.MustQuery("select * from t").Check(testkit.Rows("1 11", "2 22", "3 33", "4 44", "10 55", "11 66"))
tk.MustQuery("select last_insert_id()").Check(testkit.Rows("11"))
// update
tk.MustExec("update t set c1=last_insert_id(c1 + 100)")
tk.MustQuery("select * from t").Check(testkit.Rows("101 11", "102 22", "103 33", "104 44", "110 55", "111 66"))
tk.MustQuery("select last_insert_id()").Check(testkit.Rows("111"))
tk.MustExec("insert into t (c2) values (77)")
tk.MustQuery("select last_insert_id()").Check(testkit.Rows("112"))
// drop
tk.MustExec("drop table t")
tk.MustQuery("select last_insert_id()").Check(testkit.Rows("112"))
tk.MustExec("create table t (c2 int, c3 int, c1 int not null auto_increment, PRIMARY KEY (c1))")
tk.MustExec("insert into t set c2 = 30")
// insert values
lastInsertID := tk.Se.LastInsertID()
tk.MustExec("prepare stmt1 from 'insert into t (c2) values (?)'")
tk.MustExec("set @v1=10")
tk.MustExec("set @v2=20")
tk.MustExec("execute stmt1 using @v1")
tk.MustExec("execute stmt1 using @v2")
tk.MustExec("deallocate prepare stmt1")
currLastInsertID := tk.Se.GetSessionVars().PrevLastInsertID
tk.MustQuery("select c1 from t where c2 = 20").Check(testkit.Rows(fmt.Sprint(currLastInsertID)))
c.Assert(lastInsertID+2, Equals, currLastInsertID)
}
func (s *testSessionSuite) TestPrimaryKeyAutoIncrement(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (id BIGINT PRIMARY KEY AUTO_INCREMENT NOT NULL, name varchar(255) UNIQUE NOT NULL, status int)")
tk.MustExec("insert t (name) values (?)", "abc")
id := tk.Se.LastInsertID()
c.Check(id != 0, IsTrue)
tk1 := testkit.NewTestKitWithInit(c, s.store)
tk1.MustQuery("select * from t").Check(testkit.Rows(fmt.Sprintf("%d abc <nil>", id)))
tk.MustExec("update t set name = 'abc', status = 1 where id = ?", id)
tk1.MustQuery("select * from t").Check(testkit.Rows(fmt.Sprintf("%d abc 1", id)))
// Check for pass bool param to tidb prepared statement
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (id tinyint)")
tk.MustExec("insert t values (?)", true)
tk.MustQuery("select * from t").Check(testkit.Rows("1"))
}
func (s *testSessionSuite) TestAutoIncrementID(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (id BIGINT PRIMARY KEY AUTO_INCREMENT NOT NULL)")
tk.MustExec("insert t values ()")
tk.MustExec("insert t values ()")
tk.MustExec("insert t values ()")
tk.MustExec("drop table if exists t;")
tk.MustExec("create table t (id BIGINT PRIMARY KEY AUTO_INCREMENT NOT NULL)")
tk.MustExec("insert t values ()")
lastID := tk.Se.LastInsertID()
c.Assert(lastID, Less, uint64(4))
tk.MustExec("insert t () values ()")
c.Assert(tk.Se.LastInsertID(), Greater, lastID)
lastID = tk.Se.LastInsertID()
tk.MustExec("insert t values (100)")
c.Assert(tk.Se.LastInsertID(), Equals, uint64(100))
// If the auto_increment column value is given, it uses the value of the latest row.
tk.MustExec("insert t values (120), (112)")
c.Assert(tk.Se.LastInsertID(), Equals, uint64(112))
// The last_insert_id function only use last auto-generated id.
tk.MustQuery("select last_insert_id()").Check(testkit.Rows(fmt.Sprint(lastID)))
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (i tinyint unsigned not null auto_increment, primary key (i));")
tk.MustExec("insert into t set i = 254;")
tk.MustExec("insert t values ()")
// The last insert ID doesn't care about primary key, it is set even if its a normal index column.
tk.MustExec("create table autoid (id int auto_increment, index (id))")
tk.MustExec("insert autoid values ()")
c.Assert(tk.Se.LastInsertID(), Greater, uint64(0))
tk.MustExec("insert autoid values (100)")
c.Assert(tk.Se.LastInsertID(), Equals, uint64(100))
tk.MustQuery("select last_insert_id(20)").Check(testkit.Rows(fmt.Sprint(20)))
tk.MustQuery("select last_insert_id()").Check(testkit.Rows(fmt.Sprint(20)))
}
func (s *testSessionSuite) TestAutoIncrementWithRetry(c *C) {
// test for https://github.com/pingcap/tidb/issues/827
tk := testkit.NewTestKitWithInit(c, s.store)
tk1 := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("create table t (c2 int, c1 int not null auto_increment, PRIMARY KEY (c1))")
tk.MustExec("insert into t (c2) values (1), (2), (3), (4), (5)")
// insert values
lastInsertID := tk.Se.LastInsertID()
tk.MustExec("begin")
tk.MustExec("insert into t (c2) values (11), (12), (13)")
tk.MustQuery("select c1 from t where c2 = 11").Check(testkit.Rows("6"))
tk.MustExec("update t set c2 = 33 where c2 = 1")
tk1.MustExec("update t set c2 = 22 where c2 = 1")
tk.MustExec("commit")
tk.MustQuery("select c1 from t where c2 = 11").Check(testkit.Rows("6"))
currLastInsertID := tk.Se.GetSessionVars().PrevLastInsertID
c.Assert(lastInsertID+5, Equals, currLastInsertID)
// insert set
lastInsertID = currLastInsertID
tk.MustExec("begin")
tk.MustExec("insert into t set c2 = 31")
tk.MustQuery("select c1 from t where c2 = 31").Check(testkit.Rows("9"))
tk.MustExec("update t set c2 = 44 where c2 = 2")
tk1.MustExec("update t set c2 = 55 where c2 = 2")
tk.MustExec("commit")
tk.MustQuery("select c1 from t where c2 = 31").Check(testkit.Rows("9"))
currLastInsertID = tk.Se.GetSessionVars().PrevLastInsertID
c.Assert(lastInsertID+3, Equals, currLastInsertID)
// replace
lastInsertID = currLastInsertID
tk.MustExec("begin")
tk.MustExec("insert into t (c2) values (21), (22), (23)")
tk.MustQuery("select c1 from t where c2 = 21").Check(testkit.Rows("10"))
tk.MustExec("update t set c2 = 66 where c2 = 3")
tk1.MustExec("update t set c2 = 77 where c2 = 3")
tk.MustExec("commit")
tk.MustQuery("select c1 from t where c2 = 21").Check(testkit.Rows("10"))
currLastInsertID = tk.Se.GetSessionVars().PrevLastInsertID
c.Assert(lastInsertID+1, Equals, currLastInsertID)
// update
lastInsertID = currLastInsertID
tk.MustExec("begin")
tk.MustExec("insert into t set c2 = 41")
tk.MustExec("update t set c1 = 0 where c2 = 41")
tk.MustQuery("select c1 from t where c2 = 41").Check(testkit.Rows("0"))
tk.MustExec("update t set c2 = 88 where c2 = 4")
tk1.MustExec("update t set c2 = 99 where c2 = 4")
tk.MustExec("commit")
tk.MustQuery("select c1 from t where c2 = 41").Check(testkit.Rows("0"))
currLastInsertID = tk.Se.GetSessionVars().PrevLastInsertID
c.Assert(lastInsertID+3, Equals, currLastInsertID)
// prepare
lastInsertID = currLastInsertID
tk.MustExec("begin")
tk.MustExec("prepare stmt from 'insert into t (c2) values (?)'")
tk.MustExec("set @v1=100")
tk.MustExec("set @v2=200")
tk.MustExec("set @v3=300")
tk.MustExec("execute stmt using @v1")
tk.MustExec("execute stmt using @v2")
tk.MustExec("execute stmt using @v3")
tk.MustExec("deallocate prepare stmt")
tk.MustQuery("select c1 from t where c2 = 12").Check(testkit.Rows("7"))
tk.MustExec("update t set c2 = 111 where c2 = 5")
tk1.MustExec("update t set c2 = 222 where c2 = 5")
tk.MustExec("commit")
tk.MustQuery("select c1 from t where c2 = 12").Check(testkit.Rows("7"))
currLastInsertID = tk.Se.GetSessionVars().PrevLastInsertID
c.Assert(lastInsertID+3, Equals, currLastInsertID)
}
func (s *testSessionSuite) TestPrepare(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("create table t(id TEXT)")
tk.MustExec(`INSERT INTO t VALUES ("id");`)
id, ps, fields, err := tk.Se.PrepareStmt("select id+? from t")
c.Assert(err, IsNil)
c.Assert(fields, HasLen, 1)
c.Assert(id, Equals, uint32(1))
c.Assert(ps, Equals, 1)
tk.MustExec(`set @a=1`)
_, err = tk.Se.ExecutePreparedStmt(id, "1")
c.Assert(err, IsNil)
err = tk.Se.DropPreparedStmt(id)
c.Assert(err, IsNil)
tk.MustExec("prepare stmt from 'select 1+?'")
tk.MustExec("set @v1=100")
tk.MustQuery("execute stmt using @v1").Check(testkit.Rows("101"))
tk.MustExec("set @v2=200")
tk.MustQuery("execute stmt using @v2").Check(testkit.Rows("201"))
tk.MustExec("set @v3=300")
tk.MustQuery("execute stmt using @v3").Check(testkit.Rows("301"))
tk.MustExec("deallocate prepare stmt")
// Execute prepared statements for more than one time.
tk.MustExec("create table multiexec (a int, b int)")
tk.MustExec("insert multiexec values (1, 1), (2, 2)")
id, _, _, err = tk.Se.PrepareStmt("select a from multiexec where b = ? order by b")
c.Assert(err, IsNil)
rs, err := tk.Se.ExecutePreparedStmt(id, 1)
c.Assert(err, IsNil)
rs.Close()
rs, err = tk.Se.ExecutePreparedStmt(id, 2)
rs.Close()
c.Assert(err, IsNil)
}
func (s *testSessionSuite) TestSpecifyIndexPrefixLength(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
_, err := tk.Exec("create table t (c1 char, index(c1(3)));")
// ERROR 1089 (HY000): Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys
c.Assert(err, NotNil)
_, err = tk.Exec("create table t (c1 int, index(c1(3)));")
// ERROR 1089 (HY000): Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys
c.Assert(err, NotNil)
_, err = tk.Exec("create table t (c1 bit(10), index(c1(3)));")
// ERROR 1089 (HY000): Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys
c.Assert(err, NotNil)
tk.MustExec("create table t (c1 char, c2 int, c3 bit(10));")
_, err = tk.Exec("create index idx_c1 on t (c1(3));")
// ERROR 1089 (HY000): Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys
c.Assert(err, NotNil)
_, err = tk.Exec("create index idx_c1 on t (c2(3));")
// ERROR 1089 (HY000): Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys
c.Assert(err, NotNil)
_, err = tk.Exec("create index idx_c1 on t (c3(3));")
// ERROR 1089 (HY000): Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys
c.Assert(err, NotNil)
tk.MustExec("drop table if exists t;")
_, err = tk.Exec("create table t (c1 int, c2 blob, c3 varchar(64), index(c2));")
// ERROR 1170 (42000): BLOB/TEXT column 'c2' used in key specification without a key length
c.Assert(err, NotNil)
tk.MustExec("create table t (c1 int, c2 blob, c3 varchar(64));")
_, err = tk.Exec("create index idx_c1 on t (c2);")
// ERROR 1170 (42000): BLOB/TEXT column 'c2' used in key specification without a key length
c.Assert(err, NotNil)
_, err = tk.Exec("create index idx_c1 on t (c2(555555));")
// ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
c.Assert(err, NotNil)
_, err = tk.Exec("create index idx_c1 on t (c1(5))")
// ERROR 1089 (HY000): Incorrect prefix key;
// the used key part isn't a string, the used length is longer than the key part,
// or the storage engine doesn't support unique prefix keys
c.Assert(err, NotNil)
tk.MustExec("create index idx_c1 on t (c1);")
tk.MustExec("create index idx_c2 on t (c2(3));")
tk.MustExec("create unique index idx_c3 on t (c3(5));")
tk.MustExec("insert into t values (3, 'abc', 'def');")
tk.MustQuery("select c2 from t where c2 = 'abc';").Check(testkit.Rows("abc"))
tk.MustExec("insert into t values (4, 'abcd', 'xxx');")
tk.MustExec("insert into t values (4, 'abcf', 'yyy');")
tk.MustQuery("select c2 from t where c2 = 'abcf';").Check(testkit.Rows("abcf"))
tk.MustQuery("select c2 from t where c2 = 'abcd';").Check(testkit.Rows("abcd"))
tk.MustExec("insert into t values (4, 'ignore', 'abcdeXXX');")
_, err = tk.Exec("insert into t values (5, 'ignore', 'abcdeYYY');")
// ERROR 1062 (23000): Duplicate entry 'abcde' for key 'idx_c3'
c.Assert(err, NotNil)
tk.MustQuery("select c3 from t where c3 = 'abcde';").Check(testkit.Rows())
tk.MustExec("delete from t where c3 = 'abcdeXXX';")
tk.MustExec("delete from t where c2 = 'abc';")
tk.MustQuery("select c2 from t where c2 > 'abcd';").Check(testkit.Rows("abcf"))
tk.MustQuery("select c2 from t where c2 < 'abcf';").Check(testkit.Rows("abcd"))
tk.MustQuery("select c2 from t where c2 >= 'abcd';").Check(testkit.Rows("abcd", "abcf"))
tk.MustQuery("select c2 from t where c2 <= 'abcf';").Check(testkit.Rows("abcd", "abcf"))
tk.MustQuery("select c2 from t where c2 != 'abc';").Check(testkit.Rows("abcd", "abcf"))
tk.MustQuery("select c2 from t where c2 != 'abcd';").Check(testkit.Rows("abcf"))
tk.MustExec("drop table if exists t1;")
tk.MustExec("create table t1 (a int, b char(255), key(a, b(20)));")
tk.MustExec("insert into t1 values (0, '1');")
tk.MustExec("update t1 set b = b + 1 where a = 0;")
tk.MustQuery("select b from t1 where a = 0;").Check(testkit.Rows("2"))
// test union index.
tk.MustExec("drop table if exists t;")
tk.MustExec("create table t (a text, b text, c int, index (a(3), b(3), c));")
tk.MustExec("insert into t values ('abc', 'abcd', 1);")
tk.MustExec("insert into t values ('abcx', 'abcf', 2);")
tk.MustExec("insert into t values ('abcy', 'abcf', 3);")
tk.MustExec("insert into t values ('bbc', 'abcd', 4);")
tk.MustExec("insert into t values ('bbcz', 'abcd', 5);")
tk.MustExec("insert into t values ('cbck', 'abd', 6);")
tk.MustQuery("select c from t where a = 'abc' and b <= 'abc';").Check(testkit.Rows())
tk.MustQuery("select c from t where a = 'abc' and b <= 'abd';").Check(testkit.Rows("1"))
tk.MustQuery("select c from t where a < 'cbc' and b > 'abcd';").Check(testkit.Rows("2", "3"))
tk.MustQuery("select c from t where a <= 'abd' and b > 'abc';").Check(testkit.Rows("1", "2", "3"))
tk.MustQuery("select c from t where a < 'bbcc' and b = 'abcd';").Check(testkit.Rows("1", "4"))
tk.MustQuery("select c from t where a > 'bbcf';").Check(testkit.Rows("5", "6"))
}
func (s *testSessionSuite) TestResultField(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("create table t (id int);")
tk.MustExec(`INSERT INTO t VALUES (1);`)
tk.MustExec(`INSERT INTO t VALUES (2);`)
r, err := tk.Exec(`SELECT count(*) from t;`)
c.Assert(err, IsNil)
fields, err := r.Fields()
c.Assert(err, IsNil)
c.Assert(len(fields), Equals, 1)
field := fields[0].Column
c.Assert(field.Tp, Equals, mysql.TypeLonglong)
c.Assert(field.Flen, Equals, 21)
}
func (s *testSessionSuite) TestResultType(c *C) {
// Testcase for https://github.com/pingcap/tidb/issues/325
tk := testkit.NewTestKitWithInit(c, s.store)
rs, err := tk.Exec(`select cast(null as char(30))`)
c.Assert(err, IsNil)
row, err := rs.Next()
c.Assert(err, IsNil)
c.Assert(row.Data[0].GetValue(), IsNil)
fs, err := rs.Fields()
c.Assert(err, IsNil)
c.Assert(fs[0].Column.FieldType.Tp, Equals, mysql.TypeVarString)
}
func (s *testSessionSuite) TestFieldText(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("create table t (a int)")
tests := []struct {
sql string
field string
}{
{"select distinct(a) from t", "a"},
{"select (1)", "1"},
{"select (1+1)", "(1+1)"},
{"select a from t", "a"},
{"select ((a+1)) from t", "((a+1))"},
{"select 1 /*!32301 +1 */;", "1 +1 "},
{"select /*!32301 1 +1 */;", "1 +1 "},
{"/*!32301 select 1 +1 */;", "1 +1 "},
{"select 1 + /*!32301 1 +1 */;", "1 + 1 +1 "},
{"select 1 /*!32301 + 1, 1 */;", "1 + 1"},
{"select /*!32301 1, 1 +1 */;", "1"},
{"select /*!32301 1 + 1, */ +1;", "1 + 1"},
}
for _, tt := range tests {
results, err := tk.Se.Execute(tt.sql)
c.Assert(err, IsNil)
result := results[0]
fields, err := result.Fields()
c.Assert(err, IsNil)
c.Assert(fields[0].ColumnAsName.O, Equals, tt.field)
}
}
func (s *testSessionSuite) TestIndexMaxLength(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("drop table if exists t;")
// create simple index at table creation
_, err := tk.Exec("create table t (c1 varchar(3073), index(c1));")
// ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
c.Assert(err, NotNil)
// create simple index after table creation
tk.MustExec("create table t (c1 varchar(3073));")
_, err = tk.Exec("create index idx_c1 on t(c1) ")
// ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
c.Assert(err, NotNil)
// create compound index at table creation
tk.MustExec("drop table if exists t;")
_, err = tk.Exec("create table t (c1 varchar(3072), c2 varchar(1), index(c1, c2));")
// ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
c.Assert(err, NotNil)
_, err = tk.Exec("create table t (c1 varchar(3072), c2 char(1), index(c1, c2));")
// ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
c.Assert(err, NotNil)
_, err = tk.Exec("create table t (c1 varchar(3072), c2 char, index(c1, c2));")
// ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
c.Assert(err, NotNil)
_, err = tk.Exec("create table t (c1 varchar(3072), c2 date, index(c1, c2));")
// ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
c.Assert(err, NotNil)
_, err = tk.Exec("create table t (c1 varchar(3068), c2 timestamp(1), index(c1, c2));")
// ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
c.Assert(err, NotNil)
tk.MustExec("create table t (c1 varchar(3068), c2 bit(26), index(c1, c2));") // 26 bit = 4 bytes
tk.MustExec("drop table if exists t;")
tk.MustExec("create table t (c1 varchar(3068), c2 bit(32), index(c1, c2));") // 32 bit = 4 bytes
tk.MustExec("drop table if exists t;")
_, err = tk.Exec("create table t (c1 varchar(3068), c2 bit(33), index(c1, c2));")
// ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
c.Assert(err, NotNil)
// create compound index after table creation
tk.MustExec("create table t (c1 varchar(3072), c2 varchar(1));")
_, err = tk.Exec("create index idx_c1_c2 on t(c1, c2);")
// ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
c.Assert(err, NotNil)
tk.MustExec("drop table if exists t;")
tk.MustExec("create table t (c1 varchar(3072), c2 char(1));")
_, err = tk.Exec("create index idx_c1_c2 on t(c1, c2);")
// ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
c.Assert(err, NotNil)
tk.MustExec("drop table if exists t;")
tk.MustExec("create table t (c1 varchar(3072), c2 char);")
_, err = tk.Exec("create index idx_c1_c2 on t(c1, c2);")
// ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
c.Assert(err, NotNil)
tk.MustExec("drop table if exists t;")
tk.MustExec("create table t (c1 varchar(3072), c2 date);")
_, err = tk.Exec("create index idx_c1_c2 on t(c1, c2);")
// ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
c.Assert(err, NotNil)
tk.MustExec("drop table if exists t;")
tk.MustExec("create table t (c1 varchar(3068), c2 timestamp(1));")
_, err = tk.Exec("create index idx_c1_c2 on t(c1, c2);")
// ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes
c.Assert(err, NotNil)
}
func (s *testSessionSuite) TestIndexColumnLength(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("create table t (c1 int, c2 blob);")
tk.MustExec("create index idx_c1 on t(c1);")
tk.MustExec("create index idx_c2 on t(c2(6));")
is := s.dom.InfoSchema()
tab, err2 := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
c.Assert(err2, Equals, nil)
idxC1Cols := tables.FindIndexByColName(tab, "c1").Meta().Columns
c.Assert(idxC1Cols[0].Length, Equals, types.UnspecifiedLength)
idxC2Cols := tables.FindIndexByColName(tab, "c2").Meta().Columns
c.Assert(idxC2Cols[0].Length, Equals, 6)
}
func (s *testSessionSuite) TestIgnoreForeignKey(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
sqlText := `CREATE TABLE address (
id bigint(20) NOT NULL AUTO_INCREMENT,
user_id bigint(20) NOT NULL,
PRIMARY KEY (id),
CONSTRAINT FK_7rod8a71yep5vxasb0ms3osbg FOREIGN KEY (user_id) REFERENCES waimaiqa.user (id),
INDEX FK_7rod8a71yep5vxasb0ms3osbg (user_id) comment ''
) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ROW_FORMAT=COMPACT COMMENT='' CHECKSUM=0 DELAY_KEY_WRITE=0;`
tk.MustExec(sqlText)
}
// TestISColumns tests information_schema.columns.
func (s *testSessionSuite) TestISColumns(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("select ORDINAL_POSITION from INFORMATION_SCHEMA.COLUMNS;")
tk.MustQuery("SELECT CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.CHARACTER_SETS WHERE CHARACTER_SET_NAME = 'utf8mb4'").Check(testkit.Rows("utf8mb4"))
}
func (s *testSessionSuite) TestRetry(c *C) {
// For https://github.com/pingcap/tidb/issues/571
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("begin")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (c int)")
tk.MustExec("insert t values (1), (2), (3)")
tk.MustExec("commit")
tk1 := testkit.NewTestKitWithInit(c, s.store)
tk2 := testkit.NewTestKitWithInit(c, s.store)
tk3 := testkit.NewTestKitWithInit(c, s.store)
tk3.MustExec("SET SESSION autocommit=0;")
// retry forever
tidb.SetCommitRetryLimit(math.MaxInt64)
defer tidb.SetCommitRetryLimit(10)
var wg sync.WaitGroup
wg.Add(3)
f1 := func() {
defer wg.Done()
for i := 0; i < 30; i++ {
tk1.MustExec("update t set c = 1;")
}
}
f2 := func() {
defer wg.Done()
for i := 0; i < 30; i++ {
tk2.MustExec("update t set c = ?;", 1)
}
}
f3 := func() {
defer wg.Done()
for i := 0; i < 30; i++ {
tk3.MustExec("begin")
tk3.MustExec("update t set c = 1;")
tk3.MustExec("commit")
}
}
go f1()
go f2()
go f3()
wg.Wait()
}
func (s *testSessionSuite) TestMultiStmts(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("drop table if exists t1; create table t1(id int ); insert into t1 values (1);")
tk.MustQuery("select * from t1;").Check(testkit.Rows("1"))
}
func (s *testSessionSuite) TestDecimal(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("drop table if exists t;")
tk.MustExec("create table t (a decimal unique);")
tk.MustExec("insert t values ('100');")
_, err := tk.Exec("insert t values ('1e2');")
c.Check(err, NotNil)
}
func (s *testSessionSuite) TestParser(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
// test for https://github.com/pingcap/tidb/pull/177
tk.MustExec("CREATE TABLE `t1` ( `a` char(3) NOT NULL default '', `b` char(3) NOT NULL default '', `c` char(3) NOT NULL default '', PRIMARY KEY (`a`,`b`,`c`)) ENGINE=InnoDB;")
tk.MustExec("CREATE TABLE `t2` ( `a` char(3) NOT NULL default '', `b` char(3) NOT NULL default '', `c` char(3) NOT NULL default '', PRIMARY KEY (`a`,`b`,`c`)) ENGINE=InnoDB;")
tk.MustExec(`INSERT INTO t1 VALUES (1,1,1);`)
tk.MustExec(`INSERT INTO t2 VALUES (1,1,1);`)
tk.MustExec(`PREPARE my_stmt FROM "SELECT t1.b, count(*) FROM t1 group by t1.b having count(*) > ALL (SELECT COUNT(*) FROM t2 WHERE t2.a=1 GROUP By t2.b)";`)
tk.MustExec(`EXECUTE my_stmt;`)
tk.MustExec(`EXECUTE my_stmt;`)
tk.MustExec(`deallocate prepare my_stmt;`)
tk.MustExec(`drop table t1,t2;`)
}
func (s *testSessionSuite) TestOnDuplicate(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
// test for https://github.com/pingcap/tidb/pull/454
tk.MustExec("drop table if exists t")
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t1 (c1 int, c2 int, c3 int);")
tk.MustExec("insert into t1 set c1=1, c2=2, c3=1;")
tk.MustExec("create table t (c1 int, c2 int, c3 int, primary key (c1));")
tk.MustExec("insert into t set c1=1, c2=4;")
tk.MustExec("insert into t select * from t1 limit 1 on duplicate key update c3=3333;")
}
func (s *testSessionSuite) TestReplace(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
// test for https://github.com/pingcap/tidb/pull/456
tk.MustExec("drop table if exists t")
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t1 (c1 int, c2 int, c3 int);")
tk.MustExec("replace into t1 set c1=1, c2=2, c3=1;")
tk.MustExec("create table t (c1 int, c2 int, c3 int, primary key (c1));")
tk.MustExec("replace into t set c1=1, c2=4;")
tk.MustExec("replace into t select * from t1 limit 1;")
}
func (s *testSessionSuite) TestDelete(c *C) {
// test for https://github.com/pingcap/tidb/pull/1135
tk := testkit.NewTestKitWithInit(c, s.store)
tk1 := testkit.NewTestKit(c, s.store)
tk1.MustExec("create database test1")
tk1.MustExec("use test1")
tk1.MustExec("create table t (F1 VARCHAR(30));")
tk1.MustExec("insert into t (F1) values ('1'), ('4');")
tk.MustExec("create table t (F1 VARCHAR(30));")
tk.MustExec("insert into t (F1) values ('1'), ('2');")
tk.MustExec("delete m1 from t m2,t m1 where m1.F1>1;")
tk.MustQuery("select * from t;").Check(testkit.Rows("1"))
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (F1 VARCHAR(30));")
tk.MustExec("insert into t (F1) values ('1'), ('2');")
tk.MustExec("delete m1 from t m1,t m2 where true and m1.F1<2;")
tk.MustQuery("select * from t;").Check(testkit.Rows("2"))
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (F1 VARCHAR(30));")
tk.MustExec("insert into t (F1) values ('1'), ('2');")
tk.MustExec("delete m1 from t m1,t m2 where false;")
tk.MustQuery("select * from t;").Check(testkit.Rows("1", "2"))
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (F1 VARCHAR(30));")
tk.MustExec("insert into t (F1) values ('1'), ('2');")
tk.MustExec("delete m1, m2 from t m1,t m2 where m1.F1>m2.F1;")
tk.MustQuery("select * from t;").Check(testkit.Rows())
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (F1 VARCHAR(30));")
tk.MustExec("insert into t (F1) values ('1'), ('2');")
tk.MustExec("delete test1.t from test1.t inner join test.t where test1.t.F1 > test.t.F1")
tk1.MustQuery("select * from t;").Check(testkit.Rows("1"))
}
func (s *testSessionSuite) TestUnique(c *C) {
// test for https://github.com/pingcap/tidb/pull/461
tk := testkit.NewTestKitWithInit(c, s.store)
tk1 := testkit.NewTestKitWithInit(c, s.store)
tk2 := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec(`CREATE TABLE test ( id int(11) UNSIGNED NOT NULL AUTO_INCREMENT, val int UNIQUE, PRIMARY KEY (id)); `)
tk.MustExec("begin;")
tk.MustExec("insert into test(id, val) values(1, 1);")
tk1.MustExec("begin;")
tk1.MustExec("insert into test(id, val) values(2, 2);")
tk2.MustExec("begin;")
tk2.MustExec("insert into test(id, val) values(1, 2);")
tk2.MustExec("commit;")
_, err := tk.Exec("commit")
c.Assert(err, NotNil)
// Check error type and error message
c.Assert(terror.ErrorEqual(err, kv.ErrKeyExists), IsTrue)
c.Assert(err.Error(), Equals, "[kv:1062]Duplicate entry '1' for key 'PRIMARY'")
_, err = tk1.Exec("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'")
// Test for https://github.com/pingcap/tidb/issues/463
tk.MustExec("drop table test;")
tk.MustExec(`CREATE TABLE test (
id int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
val int UNIQUE,
PRIMARY KEY (id)
);`)
tk.MustExec("insert into test(id, val) values(1, 1);")
_, err = tk.Exec("insert into test(id, val) values(2, 1);")
c.Assert(err, NotNil)
tk.MustExec("insert into test(id, val) values(2, 2);")
tk.MustExec("begin;")
tk.MustExec("insert into test(id, val) values(3, 3);")
_, err = tk.Exec("insert into test(id, val) values(4, 3);")
c.Assert(err, NotNil)
tk.MustExec("insert into test(id, val) values(4, 4);")
tk.MustExec("commit;")
tk1.MustExec("begin;")
tk1.MustExec("insert into test(id, val) values(5, 6);")
tk.MustExec("begin;")
tk.MustExec("insert into test(id, val) values(20, 6);")
tk.MustExec("commit;")
_, err = tk1.Exec("commit")
tk1.MustExec("insert into test(id, val) values(5, 5);")
tk.MustExec("drop table test;")
tk.MustExec(`CREATE TABLE test (
id int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
val1 int UNIQUE,
val2 int UNIQUE,
PRIMARY KEY (id)
);`)
tk.MustExec("insert into test(id, val1, val2) values(1, 1, 1);")
tk.MustExec("insert into test(id, val1, val2) values(2, 2, 2);")
_, err = tk.Exec("update test set val1 = 3, val2 = 2 where id = 1;")
tk.MustExec("insert into test(id, val1, val2) values(3, 3, 3);")
}
func (s *testSessionSuite) TestSet(c *C) {
// Test for https://github.com/pingcap/tidb/issues/1114
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("set @tmp = 0")
tk.MustExec("set @tmp := @tmp + 1")
tk.MustQuery("select @tmp").Check(testkit.Rows("1"))
tk.MustQuery("select @tmp1 = 1, @tmp2 := 2").Check(testkit.Rows("<nil> 2"))
tk.MustQuery("select @tmp1 := 11, @tmp2").Check(testkit.Rows("11 2"))
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (c int);")
tk.MustExec("insert into t values (1),(2);")
tk.MustExec("update t set c = 3 WHERE c = @var:= 1")
tk.MustQuery("select * from t").Check(testkit.Rows("3", "2"))
tk.MustQuery("select @tmp := count(*) from t").Check(testkit.Rows("2"))
tk.MustQuery("select @tmp := c-2 from t where c=3").Check(testkit.Rows("1"))
}
func (s *testSessionSuite) TestMySQLTypes(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustQuery(`select 0x01 + 1, x'4D7953514C' = "MySQL"`).Check(testkit.Rows("2 1"))
tk.MustQuery(`select 0b01 + 1, 0b01000001 = "A"`).Check(testkit.Rows("2 1"))
}
func (s *testSessionSuite) TestIssue986(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
sqlText := `CREATE TABLE address (
id bigint(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id));`
tk.MustExec(sqlText)
tk.MustExec(`insert into address values ('10')`)
}
func (s *testSessionSuite) TestIssue1089(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustQuery("select cast(0.5 as unsigned)")
tk.MustQuery("select cast(-0.5 as signed)")
}
func (s *testSessionSuite) TestTableInfoMeta(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
checkResult := func(affectedRows uint64, insertID uint64) {
gotRows := tk.Se.AffectedRows()
c.Assert(gotRows, Equals, affectedRows)
gotID := tk.Se.LastInsertID()
c.Assert(gotID, Equals, insertID)
}
// create table
tk.MustExec("CREATE TABLE tbl_test(id INT NOT NULL DEFAULT 1, name varchar(255), PRIMARY KEY(id));")
// insert data
tk.MustExec(`INSERT INTO tbl_test VALUES (1, "hello");`)
checkResult(1, 0)
tk.MustExec(`INSERT INTO tbl_test VALUES (2, "hello");`)
checkResult(1, 0)
tk.MustExec(`UPDATE tbl_test SET name = "abc" where id = 2;`)
checkResult(1, 0)
tk.MustExec(`DELETE from tbl_test where id = 2;`)
checkResult(1, 0)
// select data
tk.MustQuery("select * from tbl_test").Check(testkit.Rows("1 hello"))
}
func (s *testSessionSuite) TestCaseInsensitive(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("create table T (a text, B int)")
tk.MustExec("insert t (A, b) values ('aaa', 1)")
rs, _ := tk.Exec("select * from t")
fields, err := rs.Fields()
c.Assert(err, IsNil)
c.Assert(fields[0].ColumnAsName.O, Equals, "a")
c.Assert(fields[1].ColumnAsName.O, Equals, "B")
rs, _ = tk.Exec("select A, b from t")
fields, err = rs.Fields()
c.Assert(err, IsNil)
c.Assert(fields[0].ColumnAsName.O, Equals, "A")
c.Assert(fields[1].ColumnAsName.O, Equals, "b")
rs, _ = tk.Exec("select a as A from t where A > 0")
fields, err = rs.Fields()
c.Assert(err, IsNil)
c.Assert(fields[0].ColumnAsName.O, Equals, "A")
tk.MustExec("update T set b = B + 1")
tk.MustExec("update T set B = b + 1")
tk.MustQuery("select b from T").Check(testkit.Rows("3"))
}
// Testcase for delete panic
func (s *testSessionSuite) TestDeletePanic(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("create table t (c int)")
tk.MustExec("insert into t values (1), (2), (3)")
tk.MustExec("delete from `t` where `c` = ?", 1)
tk.MustExec("delete from `t` where `c` = ?", 2)
}
var _ = Suite(&testSchemaSuite{})
type testSchemaSuite struct {
cluster *mocktikv.Cluster
mvccStore *mocktikv.MvccStore
store kv.Storage
lease time.Duration
dom *domain.Domain
checkLeak func()
}
func (s *testSchemaSuite) TearDownTest(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
r := tk.MustQuery("show tables")
for _, tb := range r.Rows() {
tableName := tb[0]
tk.MustExec(fmt.Sprintf("drop table %v", tableName))
}
}
func (s *testSchemaSuite) SetUpSuite(c *C) {
testleak.BeforeTest()
s.cluster = mocktikv.NewCluster()
mocktikv.BootstrapWithSingleStore(s.cluster)
s.mvccStore = mocktikv.NewMvccStore()
store, err := tikv.NewMockTikvStore(
tikv.WithCluster(s.cluster),
tikv.WithMVCCStore(s.mvccStore),
)
c.Assert(err, IsNil)
s.store = store
s.lease = 20 * time.Millisecond
tidb.SetSchemaLease(s.lease)
tidb.SetStatsLease(0)
dom, err := tidb.BootstrapSession(s.store)
c.Assert(err, IsNil)
s.dom = dom
}
func (s *testSchemaSuite) TestLoadSchemaFailed(c *C) {
atomic.StoreInt32(&tidb.SchemaOutOfDateRetryTimes, int32(3))
atomic.StoreInt64(&tidb.SchemaOutOfDateRetryInterval, int64(20*time.Millisecond))
defer func() {
atomic.StoreInt32(&tidb.SchemaOutOfDateRetryTimes, 10)
atomic.StoreInt64(&tidb.SchemaOutOfDateRetryInterval, int64(500*time.Millisecond))
}()
tk := testkit.NewTestKitWithInit(c, s.store)
tk1 := testkit.NewTestKitWithInit(c, s.store)
tk2 := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("create table t (a int);")
tk.MustExec("create table t1 (a int);")
tk.MustExec("create table t2 (a int);")
tk1.MustExec("begin")
tk2.MustExec("begin")
// Make sure loading information schema is failed and server is invalid.
sessionctx.GetDomain(tk.Se).MockReloadFailed.SetValue(true)
err := sessionctx.GetDomain(tk.Se).Reload()
c.Assert(err, NotNil)
lease := sessionctx.GetDomain(tk.Se).DDL().GetLease()
time.Sleep(lease * 2)
// Make sure executing insert statement is failed when server is invalid.
_, err = tk.Exec("insert t values (100);")
c.Check(err, NotNil)
tk1.MustExec("insert t1 values (100);")
tk2.MustExec("insert t2 values (100);")
_, err = tk1.Exec("commit")
c.Check(err, NotNil)
ver, err := s.store.CurrentVersion()
c.Assert(err, IsNil)
c.Assert(ver, NotNil)
sessionctx.GetDomain(tk.Se).MockReloadFailed.SetValue(false)
time.Sleep(lease * 2)
tk.MustExec("drop table if exists t;")
tk.MustExec("create table t (a int);")
tk.MustExec("insert t values (100);")
// Make sure insert to table t2 transaction executes.
tk2.MustExec("commit")
}
func (s *testSchemaSuite) TearDownSuite(c *C) {
s.dom.Close()
s.store.Close()
testleak.AfterTest(c)()
}
func (s *testSchemaSuite) TestSchemaCheckerSQL(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk1 := testkit.NewTestKitWithInit(c, s.store)
// create table
tk.MustExec(`create table t (id int, c int);`)
tk.MustExec(`create table t1 (id int, c int);`)
// insert data
tk.MustExec(`insert into t values(1, 1);`)
// The schema version is out of date in the first transaction, but the SQL can be retried.
tk.MustExec(`begin;`)
tk1.MustExec(`alter table t add index idx(c);`)
tk.MustExec(`insert into t1 values(2, 2);`)
tk.MustExec(`commit;`)
// The schema version is out of date in the first transaction, and the SQL can't be retried.
tidb.SchemaChangedWithoutRetry = true
defer func() {
tidb.SchemaChangedWithoutRetry = false
}()
tk.MustExec(`begin;`)
tk1.MustExec(`alter table t modify column c bigint;`)
tk.MustExec(`insert into t values(3, 3);`)
_, err := tk.Exec(`commit;`)
c.Assert(terror.ErrorEqual(err, domain.ErrInfoSchemaChanged), IsTrue, Commentf("err %v", err))
// But the transaction related table IDs aren't in the updated table IDs.
tk.MustExec(`begin;`)
tk1.MustExec(`alter table t add index idx2(c);`)
tk.MustExec(`insert into t1 values(4, 4);`)
tk.MustExec(`commit;`)
// Test for "select for update".
tk.MustExec(`begin;`)
tk1.MustExec(`alter table t add index idx3(c);`)
tk.MustQuery(`select * from t for update`)
_, err = tk.Exec(`commit;`)
c.Assert(terror.ErrorEqual(err, domain.ErrInfoSchemaChanged), IsTrue, Commentf("err %v", err))
}
func (s *testSchemaSuite) TestPrepareStmtCommitWhenSchemaChanged(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk1 := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("create table t (a int, b int)")
tk1.MustExec("prepare stmt from 'insert into t values (?, ?)'")
tk1.MustExec("set @a = 1")
// Commit find unrelated schema change.
tk1.MustExec("begin")
tk.MustExec("create table t1 (id int)")
tk1.MustExec("execute stmt using @a, @a")
tk1.MustExec("commit")
// TODO: PrepareStmt should handle this.
//tk1.MustExec("begin")
//tk.MustExec("alter table t drop column b")
//tk1.MustExec("execute stmt using @a, @a")
//_, err := tk1.Exec("commit")
//c.Assert(terror.ErrorEqual(err, executor.ErrWrongValueCountOnRow), IsTrue, Commentf("err %v", err))
}
func (s *testSchemaSuite) TestCommitWhenSchemaChanged(c *C) {
tk := testkit.NewTestKitWithInit(c, s.store)
tk1 := testkit.NewTestKitWithInit(c, s.store)
tk.MustExec("create table t (a int, b int)")
tk1.MustExec("begin")
tk1.MustExec("insert into t values (1, 1)")
tk.MustExec("alter table t drop column b")
// When s2 commit, it will find schema already changed.
tk1.MustExec("insert into t values (4, 4)")
_, err := tk1.Exec("commit")
c.Assert(terror.ErrorEqual(err, executor.ErrWrongValueCountOnRow), IsTrue)
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/woerwin/tidb.git
git@gitee.com:woerwin/tidb.git
woerwin
tidb
tidb
master

搜索帮助