Files
tidb/pkg/executor/test/executor/executor_test.go

3084 lines
132 KiB
Go

// Copyright 2022 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,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package executor
import (
"archive/zip"
"context"
"fmt"
"math/rand"
"os"
"path/filepath"
"reflect"
"runtime"
"strconv"
"strings"
"sync"
"testing"
"time"
"github.com/golang/protobuf/proto"
"github.com/pingcap/errors"
"github.com/pingcap/failpoint"
"github.com/pingcap/tidb/pkg/config"
"github.com/pingcap/tidb/pkg/ddl"
"github.com/pingcap/tidb/pkg/domain"
"github.com/pingcap/tidb/pkg/domain/infosync"
"github.com/pingcap/tidb/pkg/executor"
"github.com/pingcap/tidb/pkg/executor/internal/exec"
"github.com/pingcap/tidb/pkg/expression"
"github.com/pingcap/tidb/pkg/infoschema"
"github.com/pingcap/tidb/pkg/kv"
"github.com/pingcap/tidb/pkg/meta"
"github.com/pingcap/tidb/pkg/meta/autoid"
"github.com/pingcap/tidb/pkg/meta/model"
"github.com/pingcap/tidb/pkg/parser"
pmodel "github.com/pingcap/tidb/pkg/parser/model"
"github.com/pingcap/tidb/pkg/parser/mysql"
"github.com/pingcap/tidb/pkg/parser/terror"
"github.com/pingcap/tidb/pkg/planner"
plannercore "github.com/pingcap/tidb/pkg/planner/core"
"github.com/pingcap/tidb/pkg/planner/core/base"
"github.com/pingcap/tidb/pkg/planner/core/resolve"
"github.com/pingcap/tidb/pkg/session"
"github.com/pingcap/tidb/pkg/sessionctx"
"github.com/pingcap/tidb/pkg/sessionctx/stmtctx"
"github.com/pingcap/tidb/pkg/sessionctx/variable"
"github.com/pingcap/tidb/pkg/sessiontxn"
"github.com/pingcap/tidb/pkg/store/mockstore"
"github.com/pingcap/tidb/pkg/table/tables"
"github.com/pingcap/tidb/pkg/tablecodec"
"github.com/pingcap/tidb/pkg/testkit"
"github.com/pingcap/tidb/pkg/testkit/testdata"
"github.com/pingcap/tidb/pkg/types"
"github.com/pingcap/tidb/pkg/util"
"github.com/pingcap/tidb/pkg/util/dbterror/exeerrors"
"github.com/pingcap/tidb/pkg/util/dbterror/plannererrors"
"github.com/pingcap/tidb/pkg/util/memory"
"github.com/pingcap/tidb/pkg/util/mock"
"github.com/pingcap/tidb/pkg/util/replayer"
"github.com/pingcap/tidb/pkg/util/rowcodec"
"github.com/pingcap/tidb/pkg/util/sqlexec"
"github.com/pingcap/tidb/pkg/util/timeutil"
"github.com/pingcap/tipb/go-tipb"
"github.com/stretchr/testify/require"
"github.com/tikv/client-go/v2/oracle"
"github.com/tikv/client-go/v2/testutils"
)
func checkFileName(s string) bool {
files := []string{
"config.toml",
"debug_trace/debug_trace0.json",
"meta.txt",
"stats/test.t_dump_single.json",
"schema/test.t_dump_single.schema.txt",
"schema/schema_meta.txt",
"table_tiflash_replica.txt",
"variables.toml",
"session_bindings.sql",
"global_bindings.sql",
"sql/sql0.sql",
"explain.txt",
"statsMem/test.t_dump_single.txt",
"sql_meta.toml",
}
for _, f := range files {
if strings.Compare(f, s) == 0 {
return true
}
}
return false
}
func TestPlanReplayer(t *testing.T) {
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/pkg/infoschema/mockTiFlashStoreCount", `return(true)`))
defer func() {
require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/pkg/infoschema/mockTiFlashStoreCount"))
}()
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int, b int, index idx_a(a))")
tk.MustExec("alter table t set tiflash replica 1")
tk.MustQuery("plan replayer dump explain select * from t where a=10")
defer os.RemoveAll(replayer.GetPlanReplayerDirName())
tk.MustQuery("plan replayer dump explain select /*+ read_from_storage(tiflash[t]) */ * from t")
tk.MustExec("create table t1 (a int)")
tk.MustExec("create table t2 (a int)")
tk.MustExec("create definer=`root`@`127.0.0.1` view v1 as select * from t1")
tk.MustExec("create definer=`root`@`127.0.0.1` view v2 as select * from v1")
tk.MustQuery("plan replayer dump explain with tmp as (select a from t1 group by t1.a) select * from tmp, t2 where t2.a=tmp.a;")
tk.MustQuery("plan replayer dump explain select * from t1 where t1.a > (with cte1 as (select 1) select count(1) from cte1);")
tk.MustQuery("plan replayer dump explain select * from v1")
tk.MustQuery("plan replayer dump explain select * from v2")
require.True(t, len(tk.Session().GetSessionVars().LastPlanReplayerToken) > 0)
// clear the status table and assert
tk.MustExec("delete from mysql.plan_replayer_status")
tk.MustQuery("plan replayer dump explain select * from v2")
token := tk.Session().GetSessionVars().LastPlanReplayerToken
rows := tk.MustQuery(fmt.Sprintf("select * from mysql.plan_replayer_status where token = '%v'", token)).Rows()
require.Len(t, rows, 1)
}
func TestPlanReplayerCaptureSEM(t *testing.T) {
originSEM := config.GetGlobalConfig().Security.EnableSEM
defer func() {
config.GetGlobalConfig().Security.EnableSEM = originSEM
}()
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("plan replayer capture '123' '123';")
tk.MustExec("create table t(id int)")
tk.MustQuery("plan replayer dump explain select * from t")
defer os.RemoveAll(replayer.GetPlanReplayerDirName())
tk.MustQuery("select count(*) from mysql.plan_replayer_status").Check(testkit.Rows("1"))
}
func TestPlanReplayerCapture(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("plan replayer capture '123' '123';")
tk.MustQuery("select sql_digest, plan_digest from mysql.plan_replayer_task;").Check(testkit.Rows("123 123"))
tk.MustGetErrMsg("plan replayer capture '123' '123';", "plan replayer capture task already exists")
tk.MustExec("plan replayer capture remove '123' '123'")
tk.MustQuery("select count(*) from mysql.plan_replayer_task;").Check(testkit.Rows("0"))
tk.MustExec("create table t(id int)")
tk.MustExec("prepare stmt from 'update t set id = ? where id = ? + 1';")
tk.MustExec("SET @number = 5;")
tk.MustExec("execute stmt using @number,@number")
_, sqlDigest := tk.Session().GetSessionVars().StmtCtx.SQLDigest()
_, planDigest := tk.Session().GetSessionVars().StmtCtx.GetPlanDigest()
tk.MustExec("SET @@tidb_enable_plan_replayer_capture = ON;")
tk.MustExec("SET @@global.tidb_enable_historical_stats_for_capture='ON'")
tk.MustExec(fmt.Sprintf("plan replayer capture '%v' '%v'", sqlDigest.String(), planDigest.String()))
err := dom.GetPlanReplayerHandle().CollectPlanReplayerTask()
require.NoError(t, err)
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/pkg/domain/shouldDumpStats", "return(true)"))
defer require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/pkg/domain/shouldDumpStats"))
tk.MustExec("execute stmt using @number,@number")
task := dom.GetPlanReplayerHandle().DrainTask()
require.NotNil(t, task)
}
func TestPlanReplayerContinuesCapture(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("set @@global.tidb_enable_historical_stats='OFF'")
_, err := tk.Exec("set @@global.tidb_enable_plan_replayer_continuous_capture='ON'")
require.Error(t, err)
require.Equal(t, err.Error(), "tidb_enable_historical_stats should be enabled before enabling tidb_enable_plan_replayer_continuous_capture")
tk.MustExec("set @@global.tidb_enable_historical_stats='ON'")
tk.MustExec("set @@global.tidb_enable_plan_replayer_continuous_capture='ON'")
prHandle := dom.GetPlanReplayerHandle()
tk.MustExec("delete from mysql.plan_replayer_status;")
tk.MustExec("use test")
tk.MustExec("create table t(id int);")
tk.MustExec("set @@tidb_enable_plan_replayer_continuous_capture = 'ON'")
tk.MustQuery("select * from t;")
task := prHandle.DrainTask()
require.NotNil(t, task)
worker := prHandle.GetWorker()
success := worker.HandleTask(task)
defer os.RemoveAll(replayer.GetPlanReplayerDirName())
require.True(t, success)
tk.MustQuery("select count(*) from mysql.plan_replayer_status").Check(testkit.Rows("1"))
}
func TestPlanReplayerDumpSingle(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t_dump_single")
tk.MustExec("create table t_dump_single(a int)")
res := tk.MustQuery("plan replayer dump explain select * from t_dump_single")
defer os.RemoveAll(replayer.GetPlanReplayerDirName())
path := testdata.ConvertRowsToStrings(res.Rows())
reader, err := zip.OpenReader(filepath.Join(replayer.GetPlanReplayerDirName(), path[0]))
require.NoError(t, err)
defer func() { require.NoError(t, reader.Close()) }()
for _, file := range reader.File {
require.True(t, checkFileName(file.Name), file.Name)
}
}
func TestTimezonePushDown(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t (ts timestamp)")
defer tk.MustExec("drop table t")
tk.MustExec(`insert into t values ("2018-09-13 10:02:06")`)
systemTZ := timeutil.SystemLocation()
require.NotEqual(t, "System", systemTZ.String())
require.NotEqual(t, "Local", systemTZ.String())
ctx := context.Background()
count := 0
ctx1 := context.WithValue(ctx, "CheckSelectRequestHook", func(req *kv.Request) {
count++
dagReq := new(tipb.DAGRequest)
require.NoError(t, proto.Unmarshal(req.Data, dagReq))
require.Equal(t, systemTZ.String(), dagReq.GetTimeZoneName())
})
rs, err := tk.Session().Execute(ctx1, `select * from t where ts = "2018-09-13 10:02:06"`)
require.NoError(t, err)
rs[0].Close()
tk.MustExec(`set time_zone="System"`)
rs, err = tk.Session().Execute(ctx1, `select * from t where ts = "2018-09-13 10:02:06"`)
require.NoError(t, err)
rs[0].Close()
require.Equal(t, 2, count) // Make sure the hook function is called.
}
func TestNotFillCacheFlag(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t (id int primary key)")
tk.MustExec("insert into t values (1)")
tests := []struct {
sql string
expect bool
}{
{"select SQL_NO_CACHE * from t", true},
{"select SQL_CACHE * from t", false},
{"select * from t", false},
}
count := 0
ctx := context.Background()
for _, test := range tests {
ctx1 := context.WithValue(ctx, "CheckSelectRequestHook", func(req *kv.Request) {
count++
comment := fmt.Sprintf("sql=%s, expect=%v, get=%v", test.sql, test.expect, req.NotFillCache)
require.Equal(t, test.expect, req.NotFillCache, comment)
})
rs, err := tk.Session().Execute(ctx1, test.sql)
require.NoError(t, err)
tk.ResultSetToResult(rs[0], fmt.Sprintf("sql: %v", test.sql))
}
require.Equal(t, len(tests), count) // Make sure the hook function is called.
}
func TestCheckIndex(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(t)
ctx := mock.NewContext()
ctx.Store = store
se, err := session.CreateSession4Test(store)
require.NoError(t, err)
defer se.Close()
_, err = se.Execute(context.Background(), "create database test_admin")
require.NoError(t, err)
_, err = se.Execute(context.Background(), "use test_admin")
require.NoError(t, err)
_, err = se.Execute(context.Background(), "create table t (pk int primary key, c int default 1, c1 int default 1, unique key c(c))")
require.NoError(t, err)
is := dom.InfoSchema()
db := pmodel.NewCIStr("test_admin")
dbInfo, ok := is.SchemaByName(db)
require.True(t, ok)
tblName := pmodel.NewCIStr("t")
tbl, err := is.TableByName(context.Background(), db, tblName)
require.NoError(t, err)
tbInfo := tbl.Meta()
alloc := autoid.NewAllocator(dom, dbInfo.ID, tbInfo.ID, false, autoid.RowIDAllocType)
tb, err := tables.TableFromMeta(autoid.NewAllocators(false, alloc), tbInfo)
require.NoError(t, err)
_, err = se.Execute(context.Background(), "admin check index t c")
require.NoError(t, err)
_, err = se.Execute(context.Background(), "admin check index t C")
require.NoError(t, err)
// set data to:
// index data (handle, data): (1, 10), (2, 20)
// table data (handle, data): (1, 10), (2, 20)
recordVal1 := types.MakeDatums(int64(1), int64(10), int64(11))
recordVal2 := types.MakeDatums(int64(2), int64(20), int64(21))
require.NoError(t, sessiontxn.NewTxn(context.Background(), ctx))
txn, err := ctx.Txn(true)
require.NoError(t, err)
_, err = tb.AddRecord(ctx.GetTableCtx(), txn, recordVal1)
require.NoError(t, err)
_, err = tb.AddRecord(ctx.GetTableCtx(), txn, recordVal2)
require.NoError(t, err)
require.NoError(t, txn.Commit(context.Background()))
mockCtx := mock.NewContext()
idx := tb.Indices()[0]
_, err = se.Execute(context.Background(), "admin check index t idx_inexistent")
require.Error(t, err)
require.Contains(t, err.Error(), "not exist")
// set data to:
// index data (handle, data): (1, 10), (2, 20), (3, 30)
// table data (handle, data): (1, 10), (2, 20), (4, 40)
txn, err = store.Begin()
require.NoError(t, err)
_, err = idx.Create(mockCtx.GetTableCtx(), txn, types.MakeDatums(int64(30)), kv.IntHandle(3), nil)
require.NoError(t, err)
key := tablecodec.EncodeRowKey(tb.Meta().ID, kv.IntHandle(4).Encoded())
setColValue(t, txn, key, types.NewDatum(int64(40)))
err = txn.Commit(context.Background())
require.NoError(t, err)
_, err = se.Execute(context.Background(), "admin check index t c")
require.Error(t, err)
require.Equal(t, "[admin:8223]data inconsistency in table: t, index: c, handle: 3, index-values:\"handle: 3, values: [KindInt64 30]\" != record-values:\"\"", err.Error())
// set data to:
// index data (handle, data): (1, 10), (2, 20), (3, 30), (4, 40)
// table data (handle, data): (1, 10), (2, 20), (4, 40)
txn, err = store.Begin()
require.NoError(t, err)
_, err = idx.Create(mockCtx.GetTableCtx(), txn, types.MakeDatums(int64(40)), kv.IntHandle(4), nil)
require.NoError(t, err)
err = txn.Commit(context.Background())
require.NoError(t, err)
_, err = se.Execute(context.Background(), "admin check index t c")
require.Error(t, err)
require.EqualError(t, err, "[admin:8223]data inconsistency in table: t, index: c, handle: 3, index-values:\"handle: 3, values: [KindInt64 30]\" != record-values:\"\"")
// set data to:
// index data (handle, data): (1, 10), (4, 40)
// table data (handle, data): (1, 10), (2, 20), (4, 40)
txn, err = store.Begin()
require.NoError(t, err)
err = idx.Delete(mockCtx.GetTableCtx(), txn, types.MakeDatums(int64(30)), kv.IntHandle(3))
require.NoError(t, err)
err = idx.Delete(mockCtx.GetTableCtx(), txn, types.MakeDatums(int64(20)), kv.IntHandle(2))
require.NoError(t, err)
err = txn.Commit(context.Background())
require.NoError(t, err)
_, err = se.Execute(context.Background(), "admin check index t c")
require.Error(t, err)
require.EqualError(t, err, "[admin:8223]data inconsistency in table: t, index: c, handle: 2, index-values:\"\" != record-values:\"handle: 2, values: [KindInt64 20]\"")
// TODO: pass the case below:
// set data to:
// index data (handle, data): (1, 10), (4, 40), (2, 30)
// table data (handle, data): (1, 10), (2, 20), (4, 40)
}
func setColValue(t *testing.T, txn kv.Transaction, key kv.Key, v types.Datum) {
row := []types.Datum{v, {}}
colIDs := []int64{2, 3}
sc := stmtctx.NewStmtCtxWithTimeZone(time.Local)
rd := rowcodec.Encoder{Enable: true}
value, err := tablecodec.EncodeRow(sc.TimeZone(), row, colIDs, nil, nil, nil, &rd)
require.NoError(t, err)
err = txn.Set(key, value)
require.NoError(t, err)
}
func TestTimestampDefaultValueTimeZone(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("set time_zone = '+08:00'")
tk.MustExec(`create table t (a int, b timestamp default "2019-01-17 14:46:14")`)
tk.MustExec("insert into t set a=1")
r := tk.MustQuery(`show create table t`)
r.Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL,\n" + " `b` timestamp DEFAULT '2019-01-17 14:46:14'\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin"))
tk.MustExec("set time_zone = '+00:00'")
tk.MustExec("insert into t set a=2")
r = tk.MustQuery(`show create table t`)
r.Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL,\n" + " `b` timestamp DEFAULT '2019-01-17 06:46:14'\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin"))
r = tk.MustQuery(`select a,b from t order by a`)
r.Check(testkit.Rows("1 2019-01-17 06:46:14", "2 2019-01-17 06:46:14"))
// Test the column's version is greater than ColumnInfoVersion1.
is := domain.GetDomain(tk.Session()).InfoSchema()
require.NotNil(t, is)
tb, err := is.TableByName(context.Background(), pmodel.NewCIStr("test"), pmodel.NewCIStr("t"))
require.NoError(t, err)
tb.Cols()[1].Version = model.ColumnInfoVersion1 + 1
tk.MustExec("insert into t set a=3")
r = tk.MustQuery(`select a,b from t order by a`)
r.Check(testkit.Rows("1 2019-01-17 06:46:14", "2 2019-01-17 06:46:14", "3 2019-01-17 06:46:14"))
tk.MustExec("delete from t where a=3")
// Change time zone back.
tk.MustExec("set time_zone = '+08:00'")
r = tk.MustQuery(`select a,b from t order by a`)
r.Check(testkit.Rows("1 2019-01-17 14:46:14", "2 2019-01-17 14:46:14"))
tk.MustExec("set time_zone = '-08:00'")
r = tk.MustQuery(`show create table t`)
r.Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL,\n" + " `b` timestamp DEFAULT '2019-01-16 22:46:14'\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin"))
// test zero default value in multiple time zone.
defer tk.MustExec(fmt.Sprintf("set @@sql_mode='%s'", tk.MustQuery("select @@sql_mode").Rows()[0][0]))
tk.MustExec("set @@sql_mode='STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION';")
tk.MustExec("drop table if exists t")
tk.MustExec("set time_zone = '+08:00'")
tk.MustExec(`create table t (a int, b timestamp default "0000-00-00 00")`)
tk.MustExec("insert into t set a=1")
r = tk.MustQuery(`show create table t`)
r.Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL,\n" + " `b` timestamp DEFAULT '0000-00-00 00:00:00'\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin"))
tk.MustExec("set time_zone = '+00:00'")
tk.MustExec("insert into t set a=2")
r = tk.MustQuery(`show create table t`)
r.Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL,\n" + " `b` timestamp DEFAULT '0000-00-00 00:00:00'\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin"))
tk.MustExec("set time_zone = '-08:00'")
tk.MustExec("insert into t set a=3")
r = tk.MustQuery(`show create table t`)
r.Check(testkit.Rows("t CREATE TABLE `t` (\n" + " `a` int(11) DEFAULT NULL,\n" + " `b` timestamp DEFAULT '0000-00-00 00:00:00'\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin"))
r = tk.MustQuery(`select a,b from t order by a`)
r.Check(testkit.Rows("1 0000-00-00 00:00:00", "2 0000-00-00 00:00:00", "3 0000-00-00 00:00:00"))
// test add timestamp column default current_timestamp.
tk.MustExec(`drop table if exists t`)
tk.MustExec(`set time_zone = 'Asia/Shanghai'`)
tk.MustExec(`create table t (a int)`)
tk.MustExec(`insert into t set a=1`)
tk.MustExec(`alter table t add column b timestamp not null default current_timestamp;`)
timeIn8 := tk.MustQuery("select b from t").Rows()[0][0]
tk.MustExec(`set time_zone = '+00:00'`)
timeIn0 := tk.MustQuery("select b from t").Rows()[0][0]
require.NotEqual(t, timeIn8, timeIn0)
datumTimeIn8, err := expression.GetTimeValue(tk.Session().GetExprCtx(), timeIn8, mysql.TypeTimestamp, 0, nil)
require.NoError(t, err)
tIn8To0 := datumTimeIn8.GetMysqlTime()
timeZoneIn8, err := time.LoadLocation("Asia/Shanghai")
require.NoError(t, err)
err = tIn8To0.ConvertTimeZone(timeZoneIn8, time.UTC)
require.NoError(t, err)
require.Equal(t, tIn8To0.String(), timeIn0)
// test add index.
tk.MustExec(`alter table t add index(b);`)
tk.MustExec("admin check table t")
tk.MustExec(`set time_zone = '+05:00'`)
tk.MustExec("admin check table t")
// 1. add a timestamp general column
// 2. add the index
tk.MustExec(`drop table if exists t`)
// change timezone
tk.MustExec(`set time_zone = 'Asia/Shanghai'`)
tk.MustExec(`create table t(a timestamp default current_timestamp)`)
tk.MustExec(`insert into t set a="20220413154712"`)
tk.MustExec(`alter table t add column b timestamp as (a+1) virtual;`)
// change timezone
tk.MustExec(`set time_zone = '+05:00'`)
tk.MustExec(`insert into t set a="20220413154840"`)
tk.MustExec(`alter table t add index(b);`)
tk.MustExec("admin check table t")
tk.MustExec(`set time_zone = '-03:00'`)
tk.MustExec("admin check table t")
}
func TestTiDBCurrentTS(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustQuery("select @@tidb_current_ts").Check(testkit.Rows("0"))
tk.MustExec("begin")
rows := tk.MustQuery("select @@tidb_current_ts").Rows()
tsStr := rows[0][0].(string)
txn, err := tk.Session().Txn(true)
require.NoError(t, err)
require.Equal(t, fmt.Sprintf("%d", txn.StartTS()), tsStr)
tk.MustExec("begin")
rows = tk.MustQuery("select @@tidb_current_ts").Rows()
newTsStr := rows[0][0].(string)
txn, err = tk.Session().Txn(true)
require.NoError(t, err)
require.Equal(t, fmt.Sprintf("%d", txn.StartTS()), newTsStr)
require.NotEqual(t, tsStr, newTsStr)
tk.MustExec("commit")
tk.MustQuery("select @@tidb_current_ts").Check(testkit.Rows("0"))
err = tk.ExecToErr("set @@tidb_current_ts = '1'")
require.True(t, terror.ErrorEqual(err, variable.ErrIncorrectScope), fmt.Sprintf("err: %v", err))
}
func TestTiDBLastTxnInfo(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (a int primary key)")
tk.MustQuery("select @@tidb_last_txn_info").Check(testkit.Rows(""))
tk.MustExec("insert into t values (1)")
rows1 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts')").Rows()
require.Greater(t, rows1[0][0].(string), "0")
require.Less(t, rows1[0][0].(string), rows1[0][1].(string))
tk.MustExec("begin")
tk.MustQuery("select a from t where a = 1").Check(testkit.Rows("1"))
rows2 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts'), @@tidb_current_ts").Rows()
tk.MustExec("commit")
rows3 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts')").Rows()
require.Equal(t, rows1[0][0], rows2[0][0])
require.Equal(t, rows1[0][1], rows2[0][1])
require.Equal(t, rows1[0][0], rows3[0][0])
require.Equal(t, rows1[0][1], rows3[0][1])
require.Less(t, rows2[0][1], rows2[0][2])
tk.MustExec("begin")
tk.MustExec("update t set a = a + 1 where a = 1")
rows4 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts'), @@tidb_current_ts").Rows()
tk.MustExec("commit")
rows5 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts')").Rows()
require.Equal(t, rows1[0][0], rows4[0][0])
require.Equal(t, rows1[0][1], rows4[0][1])
require.Equal(t, rows5[0][0], rows4[0][2])
require.Less(t, rows4[0][1], rows4[0][2])
require.Less(t, rows4[0][2], rows5[0][1])
tk.MustExec("begin")
tk.MustExec("update t set a = a + 1 where a = 2")
tk.MustExec("rollback")
rows6 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts')").Rows()
require.Equal(t, rows5[0][0], rows6[0][0])
require.Equal(t, rows5[0][1], rows6[0][1])
tk.MustExec("begin optimistic")
tk.MustExec("insert into t values (2)")
err := tk.ExecToErr("commit")
require.Error(t, err)
rows7 := tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts'), json_extract(@@tidb_last_txn_info, '$.error')").Rows()
require.Greater(t, rows7[0][0], rows5[0][0])
require.Equal(t, "0", rows7[0][1])
require.Contains(t, err.Error(), rows7[0][1])
err = tk.ExecToErr("set @@tidb_last_txn_info = '{}'")
require.True(t, terror.ErrorEqual(err, variable.ErrIncorrectScope), fmt.Sprintf("err: %v", err))
}
func TestTiDBLastQueryInfo(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (a int primary key, v int)")
tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.start_ts')").Check(testkit.Rows("0 0"))
toUint64 := func(str any) uint64 {
res, err := strconv.ParseUint(str.(string), 10, 64)
require.NoError(t, err)
return res
}
tk.MustExec("select * from t")
rows := tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.for_update_ts')").Rows()
require.Greater(t, toUint64(rows[0][0]), uint64(0))
require.Equal(t, rows[0][1], rows[0][0])
tk.MustExec("insert into t values (1, 10)")
rows = tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.for_update_ts')").Rows()
require.Greater(t, toUint64(rows[0][0]), uint64(0))
require.Equal(t, rows[0][1], rows[0][0])
// tidb_last_txn_info is still valid after checking query info.
rows = tk.MustQuery("select json_extract(@@tidb_last_txn_info, '$.start_ts'), json_extract(@@tidb_last_txn_info, '$.commit_ts')").Rows()
require.Greater(t, toUint64(rows[0][0]), uint64(0))
require.Less(t, rows[0][0].(string), rows[0][1].(string))
tk.MustExec("begin pessimistic")
tk.MustExec("select * from t")
rows = tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.for_update_ts')").Rows()
require.Greater(t, toUint64(rows[0][0]), uint64(0))
require.Equal(t, rows[0][1], rows[0][0])
tk2 := testkit.NewTestKit(t, store)
tk2.MustExec("use test")
tk2.MustExec("update t set v = 11 where a = 1")
tk.MustExec("select * from t")
rows = tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.for_update_ts')").Rows()
require.Greater(t, toUint64(rows[0][0]), uint64(0))
require.Equal(t, rows[0][1], rows[0][0])
tk.MustExec("update t set v = 12 where a = 1")
rows = tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.for_update_ts')").Rows()
require.Greater(t, toUint64(rows[0][0]), uint64(0))
require.Less(t, toUint64(rows[0][0]), toUint64(rows[0][1]))
tk.MustExec("commit")
tk.MustExec("set transaction isolation level read committed")
tk.MustExec("begin pessimistic")
tk.MustExec("select * from t")
rows = tk.MustQuery("select json_extract(@@tidb_last_query_info, '$.start_ts'), json_extract(@@tidb_last_query_info, '$.for_update_ts')").Rows()
require.Greater(t, toUint64(rows[0][0]), uint64(0))
require.Less(t, toUint64(rows[0][0]), toUint64(rows[0][1]))
tk.MustExec("rollback")
}
func TestPartitionHashCode(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec(`create table t(c1 bigint, c2 bigint, c3 bigint, primary key(c1)) partition by hash (c1) partitions 4;`)
var wg util.WaitGroupWrapper
for i := 0; i < 5; i++ {
wg.Run(func() {
tk1 := testkit.NewTestKit(t, store)
tk1.MustExec("use test")
for i := 0; i < 5; i++ {
tk1.MustExec("select * from t")
}
})
}
wg.Wait()
}
func TestPrevStmtDesensitization(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test;")
tk.MustExec(fmt.Sprintf("set @@session.%v=1", variable.TiDBRedactLog))
defer tk.MustExec(fmt.Sprintf("set @@session.%v=0", variable.TiDBRedactLog))
tk.MustExec("create table t (a int, unique key (a))")
tk.MustExec("begin")
tk.MustExec("insert into t values (1),(2)")
require.Equal(t, "insert into `t` values ( ... )", tk.Session().GetSessionVars().PrevStmt.String())
tk.MustGetErrMsg("insert into t values (1)", `[kv:1062]Duplicate entry '?' for key 't.a'`)
}
func TestIssue19148(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a decimal(16, 2));")
tk.MustExec("select * from t where a > any_value(a);")
is := domain.GetDomain(tk.Session()).InfoSchema()
tblInfo, err := is.TableByName(context.Background(), pmodel.NewCIStr("test"), pmodel.NewCIStr("t"))
require.NoError(t, err)
require.Zero(t, tblInfo.Meta().Columns[0].GetFlag())
}
func TestOOMActionPriority(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t0")
tk.MustExec("drop table if exists t1")
tk.MustExec("drop table if exists t2")
tk.MustExec("drop table if exists t3")
tk.MustExec("drop table if exists t4")
tk.MustExec("create table t0(a int)")
tk.MustExec("insert into t0 values(1)")
tk.MustExec("create table t1(a int)")
tk.MustExec("insert into t1 values(1)")
tk.MustExec("create table t2(a int)")
tk.MustExec("insert into t2 values(1)")
tk.MustExec("create table t3(a int)")
tk.MustExec("insert into t3 values(1)")
tk.MustExec("create table t4(a int)")
tk.MustExec("insert into t4 values(1)")
tk.MustQuery("select * from t0 join t1 join t2 join t3 join t4 order by t0.a").Check(testkit.Rows("1 1 1 1 1"))
action := tk.Session().GetSessionVars().StmtCtx.MemTracker.GetFallbackForTest(true)
// All actions are finished and removed.
require.Equal(t, action.GetPriority(), int64(memory.DefLogPriority))
}
// Test invoke Close without invoking Open before for each operators.
func TestUnreasonablyClose(t *testing.T) {
store := testkit.CreateMockStore(t)
is := infoschema.MockInfoSchema([]*model.TableInfo{plannercore.MockSignedTable(), plannercore.MockUnsignedTable()})
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("set tidb_cost_model_version=2")
// To enable the shuffleExec operator.
tk.MustExec("set @@tidb_merge_join_concurrency=4")
var opsNeedsCovered = []base.PhysicalPlan{
&plannercore.PhysicalHashJoin{},
&plannercore.PhysicalMergeJoin{},
&plannercore.PhysicalIndexJoin{},
&plannercore.PhysicalIndexHashJoin{},
&plannercore.PhysicalTableReader{},
&plannercore.PhysicalIndexReader{},
&plannercore.PhysicalIndexLookUpReader{},
&plannercore.PhysicalIndexMergeReader{},
&plannercore.PhysicalApply{},
&plannercore.PhysicalHashAgg{},
&plannercore.PhysicalStreamAgg{},
&plannercore.PhysicalLimit{},
&plannercore.PhysicalSort{},
&plannercore.PhysicalTopN{},
&plannercore.PhysicalCTE{},
&plannercore.PhysicalCTETable{},
&plannercore.PhysicalMaxOneRow{},
&plannercore.PhysicalProjection{},
&plannercore.PhysicalSelection{},
&plannercore.PhysicalTableDual{},
&plannercore.PhysicalWindow{},
&plannercore.PhysicalShuffle{},
&plannercore.PhysicalUnionAll{},
}
opsNeedsCoveredMask := uint64(1<<len(opsNeedsCovered) - 1)
opsAlreadyCoveredMask := uint64(0)
p := parser.New()
for i, tc := range []string{
"select /*+ hash_join(t1)*/ * from t t1 join t t2 on t1.a = t2.a",
"select /*+ merge_join(t1)*/ * from t t1 join t t2 on t1.f = t2.f",
"select /*+ merge_join(t1)*/ t1.f, t2.f from t t1 join t t2 on t1.f = t2.f",
"select t.f from t use index(f)",
"select /*+ inl_join(t1) */ * from t t1 join t t2 on t1.f=t2.f",
"select /*+ inl_hash_join(t1) */ * from t t1 join t t2 on t1.f=t2.f",
"SELECT count(1) FROM (SELECT (SELECT min(a) FROM t as t2 WHERE t2.a > t1.a) AS a from t as t1) t",
"select /*+ hash_agg() */ count(f) from t group by a",
"select /*+ stream_agg() */ count(f) from t",
"select * from t order by a, f",
"select * from t order by a, f limit 1",
"select * from t limit 1",
"select (select t1.a from t t1 where t1.a > t2.a) as a from t t2;",
"select a + 1 from t",
"select count(*) a from t having a > 1",
"select * from t where a = 1.1",
"with recursive cte1(c1) as (select 1 union select c1 + 1 from cte1 limit 5 offset 0) select * from cte1",
"select /*+use_index_merge(t, c_d_e, f)*/ * from t where c < 1 or f > 2",
"select sum(f) over (partition by f) from t",
"select /*+ merge_join(t1)*/ * from t t1 join t t2 on t1.d = t2.d",
"select a from t union all select a from t",
} {
comment := fmt.Sprintf("case:%v sql:%s", i, tc)
stmt, err := p.ParseOneStmt(tc, "", "")
require.NoError(t, err, comment)
err = sessiontxn.NewTxn(context.Background(), tk.Session())
require.NoError(t, err, comment)
err = sessiontxn.GetTxnManager(tk.Session()).OnStmtStart(context.TODO(), stmt)
require.NoError(t, err, comment)
executorBuilder := executor.NewMockExecutorBuilderForTest(tk.Session(), is)
nodeW := resolve.NewNodeW(stmt)
p, _, _ := planner.Optimize(context.TODO(), tk.Session(), nodeW, is)
require.NotNil(t, p)
// This for loop level traverses the plan tree to get which operators are covered.
var hasCTE bool
for child := []base.PhysicalPlan{p.(base.PhysicalPlan)}; len(child) != 0; {
newChild := make([]base.PhysicalPlan, 0, len(child))
for _, ch := range child {
found := false
for k, t := range opsNeedsCovered {
if reflect.TypeOf(t) == reflect.TypeOf(ch) {
opsAlreadyCoveredMask |= 1 << k
found = true
break
}
}
require.True(t, found, fmt.Sprintf("case: %v sql: %s operator %v is not registered in opsNeedsCoveredMask", i, tc, reflect.TypeOf(ch)))
switch x := ch.(type) {
case *plannercore.PhysicalCTE:
newChild = append(newChild, x.RecurPlan)
newChild = append(newChild, x.SeedPlan)
hasCTE = true
continue
case *plannercore.PhysicalShuffle:
newChild = append(newChild, x.DataSources...)
newChild = append(newChild, x.Tails...)
continue
}
newChild = append(newChild, ch.Children()...)
}
child = newChild
}
if hasCTE {
// Normally CTEStorages will be setup in ResetContextOfStmt.
// But the following case call e.Close() directly, instead of calling session.ExecStmt(), which calls ResetContextOfStmt.
// So need to setup CTEStorages manually.
tk.Session().GetSessionVars().StmtCtx.CTEStorageMap = map[int]*executor.CTEStorages{}
}
e := executorBuilder.Build(p)
func() {
defer func() {
r := recover()
buf := make([]byte, 4096)
stackSize := runtime.Stack(buf, false)
buf = buf[:stackSize]
require.Nil(t, r, fmt.Sprintf("case: %v\n sql: %s\n error stack: %v", i, tc, string(buf)))
}()
require.NoError(t, e.Close(), comment)
}()
}
// The following code is used to make sure all the operators registered
// in opsNeedsCoveredMask are covered.
commentBuf := strings.Builder{}
if opsAlreadyCoveredMask != opsNeedsCoveredMask {
for i := range opsNeedsCovered {
if opsAlreadyCoveredMask&(1<<i) != 1<<i {
commentBuf.WriteString(fmt.Sprintf(" %v", reflect.TypeOf(opsNeedsCovered[i])))
}
}
}
require.Equal(t, opsNeedsCoveredMask, opsAlreadyCoveredMask, fmt.Sprintf("these operators are not covered %s", commentBuf.String()))
}
func TestTwiceCloseUnionExec(t *testing.T) {
store := testkit.CreateMockStore(t)
is := infoschema.MockInfoSchema([]*model.TableInfo{plannercore.MockSignedTable(), plannercore.MockUnsignedTable()})
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("set tidb_cost_model_version=2")
// To enable the shuffleExec operator.
tk.MustExec("set @@tidb_merge_join_concurrency=4")
p := parser.New()
for i, tc := range []string{
"select /*+ stream_agg()*/ sum(a+1) from (select /*+ stream_agg()*/ sum(a+1) as a from t t1 union all select a from t t2) t1 union all select a from t t2",
} {
comment := fmt.Sprintf("case:%v sql:%s", i, tc)
stmt, err := p.ParseOneStmt(tc, "", "")
require.NoError(t, err, comment)
err = sessiontxn.NewTxn(context.Background(), tk.Session())
require.NoError(t, err, comment)
err = sessiontxn.GetTxnManager(tk.Session()).OnStmtStart(context.TODO(), stmt)
require.NoError(t, err, comment)
executorBuilder := executor.NewMockExecutorBuilderForTest(tk.Session(), is)
nodeW := resolve.NewNodeW(stmt)
p, _, _ := planner.Optimize(context.TODO(), tk.Session(), nodeW, is)
e := executorBuilder.Build(p)
chk := exec.NewFirstChunk(e)
require.NoError(t, exec.Open(context.Background(), e), comment)
require.NoError(t, e.Next(context.Background(), chk), comment)
require.NoError(t, exec.Close(e), comment)
chk.Reset()
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/pkg/executor/aggregate/mockStreamAggExecBaseExecutorOpenReturnedError", `return(true)`))
require.NoError(t, exec.Open(context.Background(), e), comment)
err = e.Next(context.Background(), chk)
require.EqualError(t, err, "mock StreamAggExec.baseExecutor.Open returned error")
require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/pkg/executor/aggregate/mockStreamAggExecBaseExecutorOpenReturnedError"))
exec.Close(e)
// No leak.
}
}
func TestPointGetPreparedPlan(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("drop database if exists ps_text")
defer tk.MustExec("drop database if exists ps_text")
tk.MustExec("create database ps_text")
tk.MustExec("use ps_text")
tk.MustExec(`create table t (a int, b int, c int,
primary key k_a(a),
unique key k_b(b))`)
tk.MustExec("insert into t values (1, 1, 1)")
tk.MustExec("insert into t values (2, 2, 2)")
tk.MustExec("insert into t values (3, 3, 3)")
pspk1Id, _, _, err := tk.Session().PrepareStmt("select * from t where a = ?")
require.NoError(t, err)
tk.Session().GetSessionVars().PreparedStmts[pspk1Id].(*plannercore.PlanCacheStmt).StmtCacheable = false
pspk2Id, _, _, err := tk.Session().PrepareStmt("select * from t where ? = a ")
require.NoError(t, err)
tk.Session().GetSessionVars().PreparedStmts[pspk2Id].(*plannercore.PlanCacheStmt).StmtCacheable = false
ctx := context.Background()
// first time plan generated
rs, err := tk.Session().ExecutePreparedStmt(ctx, pspk1Id, expression.Args2Expressions4Test(0))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(nil)
// using the generated plan but with different params
rs, err = tk.Session().ExecutePreparedStmt(ctx, pspk1Id, expression.Args2Expressions4Test(1))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 1 1"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, pspk1Id, expression.Args2Expressions4Test(2))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("2 2 2"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, pspk2Id, expression.Args2Expressions4Test(3))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("3 3 3"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, pspk2Id, expression.Args2Expressions4Test(0))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(nil)
rs, err = tk.Session().ExecutePreparedStmt(ctx, pspk2Id, expression.Args2Expressions4Test(1))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 1 1"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, pspk2Id, expression.Args2Expressions4Test(2))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("2 2 2"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, pspk2Id, expression.Args2Expressions4Test(3))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("3 3 3"))
// unique index
psuk1Id, _, _, err := tk.Session().PrepareStmt("select * from t where b = ? ")
require.NoError(t, err)
tk.Session().GetSessionVars().PreparedStmts[psuk1Id].(*plannercore.PlanCacheStmt).StmtCacheable = false
rs, err = tk.Session().ExecutePreparedStmt(ctx, psuk1Id, expression.Args2Expressions4Test(1))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 1 1"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, psuk1Id, expression.Args2Expressions4Test(2))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("2 2 2"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, psuk1Id, expression.Args2Expressions4Test(3))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("3 3 3"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, psuk1Id, expression.Args2Expressions4Test(0))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(nil)
// test schema changed, cached plan should be invalidated
tk.MustExec("alter table t add column col4 int default 10 after c")
rs, err = tk.Session().ExecutePreparedStmt(ctx, pspk1Id, expression.Args2Expressions4Test(0))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(nil)
rs, err = tk.Session().ExecutePreparedStmt(ctx, pspk1Id, expression.Args2Expressions4Test(1))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 1 1 10"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, pspk1Id, expression.Args2Expressions4Test(2))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("2 2 2 10"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, pspk2Id, expression.Args2Expressions4Test(3))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("3 3 3 10"))
tk.MustExec("alter table t drop index k_b")
rs, err = tk.Session().ExecutePreparedStmt(ctx, psuk1Id, expression.Args2Expressions4Test(1))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 1 1 10"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, psuk1Id, expression.Args2Expressions4Test(2))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("2 2 2 10"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, psuk1Id, expression.Args2Expressions4Test(3))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("3 3 3 10"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, psuk1Id, expression.Args2Expressions4Test(0))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(nil)
tk.MustExec(`insert into t values(4, 3, 3, 11)`)
rs, err = tk.Session().ExecutePreparedStmt(ctx, psuk1Id, expression.Args2Expressions4Test(1))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 1 1 10"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, psuk1Id, expression.Args2Expressions4Test(2))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("2 2 2 10"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, psuk1Id, expression.Args2Expressions4Test(3))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("3 3 3 10", "4 3 3 11"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, psuk1Id, expression.Args2Expressions4Test(0))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(nil)
tk.MustExec("delete from t where a = 4")
tk.MustExec("alter table t add index k_b(b)")
rs, err = tk.Session().ExecutePreparedStmt(ctx, psuk1Id, expression.Args2Expressions4Test(1))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 1 1 10"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, psuk1Id, expression.Args2Expressions4Test(2))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("2 2 2 10"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, psuk1Id, expression.Args2Expressions4Test(3))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("3 3 3 10"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, psuk1Id, expression.Args2Expressions4Test(0))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(nil)
// use pk again
rs, err = tk.Session().ExecutePreparedStmt(ctx, pspk2Id, expression.Args2Expressions4Test(3))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("3 3 3 10"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, pspk1Id, expression.Args2Expressions4Test(3))
require.NoError(t, err)
tk.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("3 3 3 10"))
}
func TestPointGetPreparedPlanWithCommitMode(t *testing.T) {
store := testkit.CreateMockStore(t)
setTxnTk := testkit.NewTestKit(t, store)
setTxnTk.MustExec("set global tidb_txn_mode=''")
tk1 := testkit.NewTestKit(t, store)
tk1.MustExec("drop database if exists ps_text")
defer tk1.MustExec("drop database if exists ps_text")
tk1.MustExec("create database ps_text")
tk1.MustExec("use ps_text")
tk1.MustExec(`create table t (a int, b int, c int,
primary key k_a(a),
unique key k_b(b))`)
tk1.MustExec("insert into t values (1, 1, 1)")
tk1.MustExec("insert into t values (2, 2, 2)")
tk1.MustExec("insert into t values (3, 3, 3)")
pspk1Id, _, _, err := tk1.Session().PrepareStmt("select * from t where a = ?")
require.NoError(t, err)
tk1.Session().GetSessionVars().PreparedStmts[pspk1Id].(*plannercore.PlanCacheStmt).StmtCacheable = false
ctx := context.Background()
// first time plan generated
rs, err := tk1.Session().ExecutePreparedStmt(ctx, pspk1Id, expression.Args2Expressions4Test(0))
require.NoError(t, err)
tk1.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(nil)
// using the generated plan but with different params
rs, err = tk1.Session().ExecutePreparedStmt(ctx, pspk1Id, expression.Args2Expressions4Test(1))
require.NoError(t, err)
tk1.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 1 1"))
// next start a non autocommit txn
tk1.MustExec("set autocommit = 0")
tk1.MustExec("begin")
// try to exec using point get plan(this plan should not go short path)
rs, err = tk1.Session().ExecutePreparedStmt(ctx, pspk1Id, expression.Args2Expressions4Test(1))
require.NoError(t, err)
tk1.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 1 1"))
// update rows
tk2 := testkit.NewTestKit(t, store)
tk2.MustExec("use ps_text")
tk2.MustExec("update t set c = c + 10 where c = 1")
// try to point get again
rs, err = tk1.Session().ExecutePreparedStmt(ctx, pspk1Id, expression.Args2Expressions4Test(1))
require.NoError(t, err)
tk1.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 1 1"))
// try to update in session 1
tk1.MustExec("update t set c = c + 10 where c = 1")
err = tk1.ExecToErr("commit")
require.True(t, kv.ErrWriteConflict.Equal(err), fmt.Sprintf("error: %s", err))
// verify
rs, err = tk1.Session().ExecutePreparedStmt(ctx, pspk1Id, expression.Args2Expressions4Test(1))
require.NoError(t, err)
tk1.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("1 1 11"))
rs, err = tk1.Session().ExecutePreparedStmt(ctx, pspk1Id, expression.Args2Expressions4Test(2))
require.NoError(t, err)
tk1.ResultSetToResult(rs, fmt.Sprintf("%v", rs)).Check(testkit.Rows("2 2 2"))
tk2.MustQuery("select * from t where a = 1").Check(testkit.Rows("1 1 11"))
}
func TestPointUpdatePreparedPlan(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("drop database if exists pu_test")
defer tk.MustExec("drop database if exists pu_test")
tk.MustExec("create database pu_test")
tk.MustExec("use pu_test")
tk.MustExec(`create table t (a int, b int, c int,
primary key k_a(a),
unique key k_b(b))`)
tk.MustExec("insert into t values (1, 1, 1)")
tk.MustExec("insert into t values (2, 2, 2)")
tk.MustExec("insert into t values (3, 3, 3)")
updateID1, pc, _, err := tk.Session().PrepareStmt(`update t set c = c + 1 where a = ?`)
require.NoError(t, err)
tk.Session().GetSessionVars().PreparedStmts[updateID1].(*plannercore.PlanCacheStmt).StmtCacheable = false
require.Equal(t, 1, pc)
updateID2, pc, _, err := tk.Session().PrepareStmt(`update t set c = c + 2 where ? = a`)
require.NoError(t, err)
tk.Session().GetSessionVars().PreparedStmts[updateID2].(*plannercore.PlanCacheStmt).StmtCacheable = false
require.Equal(t, 1, pc)
ctx := context.Background()
// first time plan generated
rs, err := tk.Session().ExecutePreparedStmt(ctx, updateID1, expression.Args2Expressions4Test(3))
require.Nil(t, rs)
require.NoError(t, err)
tk.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 4"))
// using the generated plan but with different params
rs, err = tk.Session().ExecutePreparedStmt(ctx, updateID1, expression.Args2Expressions4Test(3))
require.Nil(t, rs)
require.NoError(t, err)
tk.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 5"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, updateID1, expression.Args2Expressions4Test(3))
require.Nil(t, rs)
require.NoError(t, err)
tk.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 6"))
// updateID2
rs, err = tk.Session().ExecutePreparedStmt(ctx, updateID2, expression.Args2Expressions4Test(3))
require.Nil(t, rs)
require.NoError(t, err)
tk.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 8"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, updateID2, expression.Args2Expressions4Test(3))
require.Nil(t, rs)
require.NoError(t, err)
tk.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 10"))
// unique index
updUkID1, _, _, err := tk.Session().PrepareStmt(`update t set c = c + 10 where b = ?`)
require.NoError(t, err)
tk.Session().GetSessionVars().PreparedStmts[updUkID1].(*plannercore.PlanCacheStmt).StmtCacheable = false
rs, err = tk.Session().ExecutePreparedStmt(ctx, updUkID1, expression.Args2Expressions4Test(3))
require.Nil(t, rs)
require.NoError(t, err)
tk.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 20"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, updUkID1, expression.Args2Expressions4Test(3))
require.Nil(t, rs)
require.NoError(t, err)
tk.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 30"))
// test schema changed, cached plan should be invalidated
tk.MustExec("alter table t add column col4 int default 10 after c")
rs, err = tk.Session().ExecutePreparedStmt(ctx, updateID1, expression.Args2Expressions4Test(3))
require.Nil(t, rs)
require.NoError(t, err)
tk.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 31 10"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, updateID1, expression.Args2Expressions4Test(3))
require.Nil(t, rs)
require.NoError(t, err)
tk.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 32 10"))
tk.MustExec("alter table t drop index k_b")
rs, err = tk.Session().ExecutePreparedStmt(ctx, updUkID1, expression.Args2Expressions4Test(3))
require.Nil(t, rs)
require.NoError(t, err)
tk.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 42 10"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, updUkID1, expression.Args2Expressions4Test(3))
require.Nil(t, rs)
require.NoError(t, err)
tk.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 52 10"))
tk.MustExec("alter table t add unique index k_b(b)")
rs, err = tk.Session().ExecutePreparedStmt(ctx, updUkID1, expression.Args2Expressions4Test(3))
require.Nil(t, rs)
require.NoError(t, err)
tk.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 62 10"))
rs, err = tk.Session().ExecutePreparedStmt(ctx, updUkID1, expression.Args2Expressions4Test(3))
require.Nil(t, rs)
require.NoError(t, err)
tk.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 72 10"))
tk.MustQuery("select * from t where a = 1").Check(testkit.Rows("1 1 1 10"))
tk.MustQuery("select * from t where a = 2").Check(testkit.Rows("2 2 2 10"))
}
func TestPointUpdatePreparedPlanWithCommitMode(t *testing.T) {
store := testkit.CreateMockStore(t)
setTxnTk := testkit.NewTestKit(t, store)
setTxnTk.MustExec("set global tidb_txn_mode=''")
tk1 := testkit.NewTestKit(t, store)
tk1.MustExec("drop database if exists pu_test2")
defer tk1.MustExec("drop database if exists pu_test2")
tk1.MustExec("create database pu_test2")
tk1.MustExec("use pu_test2")
tk1.MustExec(`create table t (a int, b int, c int,
primary key k_a(a),
unique key k_b(b))`)
tk1.MustExec("insert into t values (1, 1, 1)")
tk1.MustExec("insert into t values (2, 2, 2)")
tk1.MustExec("insert into t values (3, 3, 3)")
ctx := context.Background()
updateID1, _, _, err := tk1.Session().PrepareStmt(`update t set c = c + 1 where a = ?`)
tk1.Session().GetSessionVars().PreparedStmts[updateID1].(*plannercore.PlanCacheStmt).StmtCacheable = false
require.NoError(t, err)
// first time plan generated
rs, err := tk1.Session().ExecutePreparedStmt(ctx, updateID1, expression.Args2Expressions4Test(3))
require.Nil(t, rs)
require.NoError(t, err)
tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 4"))
rs, err = tk1.Session().ExecutePreparedStmt(ctx, updateID1, expression.Args2Expressions4Test(3))
require.Nil(t, rs)
require.NoError(t, err)
tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 5"))
// next start a non autocommit txn
tk1.MustExec("set autocommit = 0")
tk1.MustExec("begin")
// try to exec using point get plan(this plan should not go short path)
rs, err = tk1.Session().ExecutePreparedStmt(ctx, updateID1, expression.Args2Expressions4Test(3))
require.Nil(t, rs)
require.NoError(t, err)
tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 6"))
// update rows
tk2 := testkit.NewTestKit(t, store)
tk2.MustExec("use pu_test2")
tk2.MustExec(`prepare pu2 from "update t set c = c + 2 where ? = a "`)
tk2.MustExec("set @p3 = 3")
tk2.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 5"))
tk2.MustExec("execute pu2 using @p3")
tk2.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 7"))
tk2.MustExec("execute pu2 using @p3")
tk2.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 9"))
// try to update in session 1
tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 6"))
err = tk1.ExecToErr("commit")
require.True(t, kv.ErrWriteConflict.Equal(err), fmt.Sprintf("error: %s", err))
// verify
tk2.MustQuery("select * from t where a = 1").Check(testkit.Rows("1 1 1"))
tk1.MustQuery("select * from t where a = 2").Check(testkit.Rows("2 2 2"))
tk2.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 9"))
tk1.MustQuery("select * from t where a = 2").Check(testkit.Rows("2 2 2"))
tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 9"))
// again next start a non autocommit txn
tk1.MustExec("set autocommit = 0")
tk1.MustExec("begin")
rs, err = tk1.Session().ExecutePreparedStmt(ctx, updateID1, expression.Args2Expressions4Test(3))
require.Nil(t, rs)
require.NoError(t, err)
tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 10"))
rs, err = tk1.Session().ExecutePreparedStmt(ctx, updateID1, expression.Args2Expressions4Test(3))
require.Nil(t, rs)
require.NoError(t, err)
tk1.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 11"))
tk1.MustExec("commit")
tk2.MustQuery("select * from t where a = 3").Check(testkit.Rows("3 3 11"))
}
func TestApplyCache(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test;")
tk.MustExec("set tidb_cost_model_version=2")
tk.MustExec("drop table if exists t;")
tk.MustExec("create table t(a int, index idx(a));")
tk.MustExec("insert into t values (1),(1),(1),(1),(1),(1),(1),(1),(1);")
tk.MustExec("analyze table t;")
result := tk.MustQuery("explain analyze SELECT count(a) FROM (SELECT (SELECT min(a) FROM t as t2 WHERE t2.a > t1.a) AS a from t as t1) t;")
require.Contains(t, result.Rows()[1][0], "Apply")
var (
ind int
flag bool
)
value := (result.Rows()[1][5]).(string)
for ind = 0; ind < len(value)-5; ind++ {
if value[ind:ind+5] == "cache" {
flag = true
break
}
}
require.True(t, flag)
require.Equal(t, "cache:ON, cacheHitRatio:88.889%", value[ind:])
tk.MustExec("drop table if exists t;")
tk.MustExec("create table t(a int, index idx(a));")
tk.MustExec("insert into t values (1),(2),(3),(4),(5),(6),(7),(8),(9);")
tk.MustExec("analyze table t;")
result = tk.MustQuery("explain analyze SELECT count(a) FROM (SELECT (SELECT min(a) FROM t as t2 WHERE t2.a > t1.a) AS a from t as t1) t;")
require.Contains(t, result.Rows()[1][0], "Apply")
flag = false
value = (result.Rows()[1][5]).(string)
for ind = 0; ind < len(value)-5; ind++ {
if value[ind:ind+5] == "cache" {
flag = true
break
}
}
require.True(t, flag)
require.Equal(t, "cache:OFF", value[ind:])
}
func TestCollectDMLRuntimeStats(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t1 (a int, b int, unique index (a))")
testSQLs := []string{
"insert ignore into t1 values (5,5);",
"insert into t1 values (5,5) on duplicate key update a=a+1;",
"replace into t1 values (5,6),(6,7)",
"update t1 set a=a+1 where a=6;",
}
getRootStats := func() string {
info := tk.Session().ShowProcess()
require.NotNil(t, info)
p, ok := info.Plan.(base.Plan)
require.True(t, ok)
stats := tk.Session().GetSessionVars().StmtCtx.RuntimeStatsColl.GetRootStats(p.ID())
return stats.String()
}
for _, sql := range testSQLs {
tk.MustExec(sql)
require.Regexp(t, "time.*loops.*Get.*num_rpc.*total_time.*", getRootStats())
}
// Test for lock keys stats.
tk.MustExec("begin pessimistic")
tk.MustExec("update t1 set b=b+1")
require.Regexp(t, "time.*lock_keys.*time.* region.* keys.* lock_rpc:.* rpc_count.*", getRootStats())
tk.MustExec("rollback")
tk.MustExec("begin pessimistic")
tk.MustQuery("select * from t1 for update").Check(testkit.Rows("5 6", "7 7"))
require.Regexp(t, "time.*lock_keys.*time.* region.* keys.* lock_rpc:.* rpc_count.*", getRootStats())
tk.MustExec("rollback")
tk.MustExec("begin pessimistic")
tk.MustExec("insert ignore into t1 values (9,9)")
require.Regexp(t, "time:.*, loops:.*, prepare:.*, check_insert: {total_time:.*, mem_insert_time:.*, prefetch:.*, rpc:{BatchGet:{num_rpc:.*, total_time:.*}}}.*", getRootStats())
tk.MustExec("rollback")
tk.MustExec("begin pessimistic")
tk.MustExec("insert into t1 values (10,10) on duplicate key update a=a+1")
require.Regexp(t, "time:.*, loops:.*, prepare:.*, check_insert: {total_time:.*, mem_insert_time:.*, prefetch:.*, rpc:{BatchGet:{num_rpc:.*, total_time:.*}.*", getRootStats())
tk.MustExec("rollback")
tk.MustExec("begin pessimistic")
tk.MustExec("insert into t1 values (1,2)")
require.Regexp(t, "time:.*, loops:.*, prepare:.*, insert:.*", getRootStats())
tk.MustExec("rollback")
tk.MustExec("begin pessimistic")
tk.MustExec("insert ignore into t1 values(11,11) on duplicate key update `a`=`a`+1")
require.Regexp(t, "time:.*, loops:.*, prepare:.*, check_insert: {total_time:.*, mem_insert_time:.*, prefetch:.*, rpc:.*}", getRootStats())
tk.MustExec("rollback")
tk.MustExec("begin pessimistic")
tk.MustExec("replace into t1 values (1,4)")
require.Regexp(t, "time:.*, loops:.*, prefetch:.*, rpc:.*", getRootStats())
tk.MustExec("rollback")
}
func TestTableSampleTemporaryTable(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
// For mocktikv, safe point is not initialized, we manually insert it for snapshot to use.
safePointName := "tikv_gc_safe_point"
safePointValue := "20160102-15:04:05 -0700"
safePointComment := "All versions after safe point can be accessed. (DO NOT EDIT)"
updateSafePoint := fmt.Sprintf(`INSERT INTO mysql.tidb VALUES ('%[1]s', '%[2]s', '%[3]s')
ON DUPLICATE KEY
UPDATE variable_value = '%[2]s', comment = '%[3]s'`, safePointName, safePointValue, safePointComment)
tk.MustExec(updateSafePoint)
tk.MustExec("use test")
tk.MustExec("drop table if exists tmp1")
tk.MustExec("create global temporary table tmp1 " +
"(id int not null primary key, code int not null, value int default null, unique key code(code))" +
"on commit delete rows")
tk.MustExec("use test")
tk.MustExec("drop table if exists tmp2")
tk.MustExec("create temporary table tmp2 (id int not null primary key, code int not null, value int default null, unique key code(code));")
// sleep 1us to make test stale
time.Sleep(time.Microsecond)
// test tablesample return empty for global temporary table
tk.MustQuery("select * from tmp1 tablesample regions()").Check(testkit.Rows())
tk.MustExec("begin")
tk.MustExec("insert into tmp1 values (1, 1, 1)")
tk.MustQuery("select * from tmp1 tablesample regions()").Check(testkit.Rows())
tk.MustExec("commit")
// tablesample for global temporary table should not return error for compatibility of tools like dumpling
tk.MustExec("set @@tidb_snapshot=NOW(6)")
tk.MustQuery("select * from tmp1 tablesample regions()").Check(testkit.Rows())
tk.MustExec("begin")
tk.MustQuery("select * from tmp1 tablesample regions()").Check(testkit.Rows())
tk.MustExec("commit")
tk.MustExec("set @@tidb_snapshot=''")
// test tablesample returns error for local temporary table
tk.MustGetErrMsg("select * from tmp2 tablesample regions()", "TABLESAMPLE clause can not be applied to local temporary tables")
tk.MustExec("begin")
tk.MustExec("insert into tmp2 values (1, 1, 1)")
tk.MustGetErrMsg("select * from tmp2 tablesample regions()", "TABLESAMPLE clause can not be applied to local temporary tables")
tk.MustExec("commit")
tk.MustGetErrMsg("select * from tmp2 tablesample regions()", "TABLESAMPLE clause can not be applied to local temporary tables")
}
func TestGetResultRowsCount(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t (a int)")
for i := 1; i <= 10; i++ {
tk.MustExec(fmt.Sprintf("insert into t values (%v)", i))
}
cases := []struct {
sql string
row int64
}{
{"select * from t", 10},
{"select * from t where a < 0", 0},
{"select * from t where a <= 3", 3},
{"insert into t values (11)", 0},
{"replace into t values (12)", 0},
{"update t set a=13 where a=12", 0},
}
for _, ca := range cases {
if strings.HasPrefix(ca.sql, "select") {
tk.MustQuery(ca.sql)
} else {
tk.MustExec(ca.sql)
}
info := tk.Session().ShowProcess()
require.NotNil(t, info)
p, ok := info.Plan.(base.Plan)
require.True(t, ok)
cnt := executor.GetResultRowsCount(tk.Session().GetSessionVars().StmtCtx, p)
require.Equal(t, ca.row, cnt, fmt.Sprintf("sql: %v", ca.sql))
}
}
func TestAdminShowDDLJobs(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("create database if not exists test_admin_show_ddl_jobs")
tk.MustExec("use test_admin_show_ddl_jobs")
tk.MustExec("create table t (a int);")
re := tk.MustQuery("admin show ddl jobs 1")
row := re.Rows()[0]
require.Equal(t, "test_admin_show_ddl_jobs", row[1])
jobID, err := strconv.Atoi(row[0].(string))
require.NoError(t, err)
job, err := ddl.GetHistoryJobByID(tk.Session(), int64(jobID))
require.NoError(t, err)
require.NotNil(t, job)
// Test for compatibility. Old TiDB version doesn't have SchemaName field, and the BinlogInfo maybe nil.
// See PR: 11561.
job.BinlogInfo = nil
job.SchemaName = ""
err = sessiontxn.NewTxnInStmt(context.Background(), tk.Session())
require.NoError(t, err)
txn, err := tk.Session().Txn(true)
require.NoError(t, err)
err = meta.NewMutator(txn).AddHistoryDDLJob(job, true)
require.NoError(t, err)
tk.Session().StmtCommit(context.Background())
re = tk.MustQuery("admin show ddl jobs 1")
row = re.Rows()[0]
require.Equal(t, "test_admin_show_ddl_jobs", row[1])
re = tk.MustQuery("admin show ddl jobs 1 where job_type='create table'")
row = re.Rows()[0]
require.Equal(t, "test_admin_show_ddl_jobs", row[1])
require.Equal(t, "<nil>", row[10])
// Test the START_TIME and END_TIME field.
tk.MustExec(`set @@time_zone = 'Asia/Shanghai'`)
re = tk.MustQuery("admin show ddl jobs where end_time is not NULL")
row = re.Rows()[0]
createTime, err := types.ParseDatetime(types.DefaultStmtNoWarningContext, row[8].(string))
require.NoError(t, err)
startTime, err := types.ParseDatetime(types.DefaultStmtNoWarningContext, row[9].(string))
require.NoError(t, err)
endTime, err := types.ParseDatetime(types.DefaultStmtNoWarningContext, row[10].(string))
require.NoError(t, err)
tk.MustExec(`set @@time_zone = 'Europe/Amsterdam'`)
re = tk.MustQuery("admin show ddl jobs where end_time is not NULL")
row2 := re.Rows()[0]
require.NotEqual(t, row[8], row2[8])
require.NotEqual(t, row[9], row2[9])
require.NotEqual(t, row[10], row2[10])
createTime2, err := types.ParseDatetime(types.DefaultStmtNoWarningContext, row2[8].(string))
require.NoError(t, err)
startTime2, err := types.ParseDatetime(types.DefaultStmtNoWarningContext, row2[9].(string))
require.NoError(t, err)
endTime2, err := types.ParseDatetime(types.DefaultStmtNoWarningContext, row2[10].(string))
require.NoError(t, err)
loc, err := time.LoadLocation("Asia/Shanghai")
require.NoError(t, err)
loc2, err := time.LoadLocation("Europe/Amsterdam")
require.NoError(t, err)
tt, err := createTime.GoTime(loc)
require.NoError(t, err)
t2, err := createTime2.GoTime(loc2)
require.NoError(t, err)
require.Equal(t, t2.In(time.UTC), tt.In(time.UTC))
tt, err = startTime.GoTime(loc)
require.NoError(t, err)
t2, err = startTime2.GoTime(loc2)
require.NoError(t, err)
require.Equal(t, t2.In(time.UTC), tt.In(time.UTC))
tt, err = endTime.GoTime(loc)
require.NoError(t, err)
t2, err = endTime2.GoTime(loc2)
require.NoError(t, err)
require.Equal(t, t2.In(time.UTC), tt.In(time.UTC))
}
func TestAdminShowDDLJobsInfo(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
// Test for issue: https://github.com/pingcap/tidb/issues/29915
tk.MustExec("create placement policy x followers=4;")
tk.MustExec("create placement policy y " +
"PRIMARY_REGION=\"cn-east-1\" " +
"REGIONS=\"cn-east-1, cn-east-2\" " +
"FOLLOWERS=2")
tk.MustExec("create database if not exists test_admin_show_ddl_jobs")
tk.MustExec("use test_admin_show_ddl_jobs")
tk.MustExec("create table t (a int);")
tk.MustExec("create table t1 (a int);")
tk.MustExec("alter table t placement policy x;")
require.Equal(t, "alter table placement", tk.MustQuery("admin show ddl jobs 1").Rows()[0][3])
tk.MustExec("rename table t to tt, t1 to tt1")
require.Equal(t, "rename tables", tk.MustQuery("admin show ddl jobs 1").Rows()[0][3])
tk.MustExec("create table tt2 (c int) PARTITION BY RANGE (c) " +
"(PARTITION p0 VALUES LESS THAN (6)," +
"PARTITION p1 VALUES LESS THAN (11)," +
"PARTITION p2 VALUES LESS THAN (16)," +
"PARTITION p3 VALUES LESS THAN (21));")
tk.MustExec("alter table tt2 partition p0 placement policy y")
require.Equal(t, "alter table partition placement", tk.MustQuery("admin show ddl jobs 1").Rows()[0][3])
tk.MustExec("alter table tt1 cache")
require.Equal(t, "alter table cache", tk.MustQuery("admin show ddl jobs 1").Rows()[0][3])
tk.MustExec("alter table tt1 nocache")
require.Equal(t, "alter table nocache", tk.MustQuery("admin show ddl jobs 1").Rows()[0][3])
}
func TestUnion2(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
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)`
tk.MustExec(testSQL)
testSQL = `select * from (select id from union_test union select id from union_test) t order by id;`
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 as a union (select 2) order by a limit 1")
r.Check(testkit.Rows("1"))
r = tk.MustQuery("select 1 as a union (select 2) order by a 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 as a union (select "abc") order by a`)
r.Check(testkit.Rows("<nil>", "abc"))
r = tk.MustQuery(`select "abc" as a union (select 1) order by a`)
r.Check(testkit.Rows("1", "abc"))
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t1 (c int, d int)")
tk.MustExec("insert t1 values (NULL, 1)")
tk.MustExec("insert t1 values (1, 1)")
tk.MustExec("insert t1 values (1, 2)")
tk.MustExec("drop table if exists t2")
tk.MustExec("create table t2 (c int, d int)")
tk.MustExec("insert t2 values (1, 3)")
tk.MustExec("insert t2 values (1, 1)")
tk.MustExec("drop table if exists t3")
tk.MustExec("create table t3 (c int, d int)")
tk.MustExec("insert t3 values (3, 2)")
tk.MustExec("insert t3 values (4, 3)")
r = tk.MustQuery(`select sum(c1), c2 from (select c c1, d c2 from t1 union all select d c1, c c2 from t2 union all select c c1, d c2 from t3) x group by c2 order by c2`)
r.Check(testkit.Rows("5 1", "4 2", "4 3"))
tk.MustExec("drop table if exists t1, t2, t3")
tk.MustExec("create table t1 (a int primary key)")
tk.MustExec("create table t2 (a int primary key)")
tk.MustExec("create table t3 (a int primary key)")
tk.MustExec("insert t1 values (7), (8)")
tk.MustExec("insert t2 values (1), (9)")
tk.MustExec("insert t3 values (2), (3)")
r = tk.MustQuery("select * from t1 union all select * from t2 union all (select * from t3) order by a limit 2")
r.Check(testkit.Rows("1", "2"))
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1 (a int)")
tk.MustExec("create table t2 (a int)")
tk.MustExec("insert t1 values (2), (1)")
tk.MustExec("insert t2 values (3), (4)")
r = tk.MustQuery("select * from t1 union all (select * from t2) order by a limit 1")
r.Check(testkit.Rows("1"))
r = tk.MustQuery("select (select * from t1 where a != t.a union all (select * from t2 where a != t.a) order by a limit 1) from t1 t")
r.Check(testkit.Rows("1", "2"))
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (id int unsigned primary key auto_increment, c1 int, c2 int, index c1_c2 (c1, c2))")
tk.MustExec("insert into t (c1, c2) values (1, 1)")
tk.MustExec("insert into t (c1, c2) values (1, 2)")
tk.MustExec("insert into t (c1, c2) values (2, 3)")
r = tk.MustQuery("select * from (select * from t where t.c1 = 1 union select * from t where t.id = 1) s order by s.id")
r.Check(testkit.Rows("1 1 1", "2 1 2"))
tk.MustExec("drop table if exists t")
tk.MustExec("CREATE TABLE t (f1 DATE)")
tk.MustExec("INSERT INTO t VALUES ('1978-11-26')")
r = tk.MustQuery("SELECT f1+0 FROM t UNION SELECT f1+0 FROM t")
r.Check(testkit.Rows("19781126"))
tk.MustExec("drop table if exists t")
tk.MustExec("CREATE TABLE t (a int, b int)")
tk.MustExec("INSERT INTO t VALUES ('1', '1')")
r = tk.MustQuery("select b from (SELECT * FROM t UNION ALL SELECT a, b FROM t order by a) t")
r.Check(testkit.Rows("1", "1"))
tk.MustExec("drop table if exists t")
tk.MustExec("CREATE TABLE t (a DECIMAL(4,2))")
tk.MustExec("INSERT INTO t VALUE(12.34)")
r = tk.MustQuery("SELECT 1 AS c UNION select a FROM t")
r.Sort().Check(testkit.Rows("1.00", "12.34"))
// #issue3771
r = tk.MustQuery("SELECT 'a' UNION SELECT CONCAT('a', -4)")
r.Sort().Check(testkit.Rows("a", "a-4"))
// test race
tk.MustQuery("SELECT @x:=0 UNION ALL SELECT @x:=0 UNION ALL SELECT @x")
// test field tp
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("CREATE TABLE t1 (a date)")
tk.MustExec("CREATE TABLE t2 (a date)")
tk.MustExec("SELECT a from t1 UNION select a FROM t2")
tk.MustQuery("show create table t1").Check(testkit.Rows("t1 CREATE TABLE `t1` (\n" + " `a` date DEFAULT NULL\n" + ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin"))
// Move from session test.
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1 (c double);")
tk.MustExec("create table t2 (c double);")
tk.MustExec("insert into t1 value (73);")
tk.MustExec("insert into t2 value (930);")
// If set unspecified column flen to 0, it will cause bug in union.
// This test is used to prevent the bug reappear.
tk.MustQuery("select c from t1 union (select c from t2) order by c").Check(testkit.Rows("73", "930"))
// issue 5703
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a date)")
tk.MustExec("insert into t value ('2017-01-01'), ('2017-01-02')")
r = tk.MustQuery("(select a from t where a < 0) union (select a from t where a > 0) order by a")
r.Check(testkit.Rows("2017-01-01", "2017-01-02"))
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int)")
tk.MustExec("insert into t value(0),(0)")
tk.MustQuery("select 1 from (select a from t union all select a from t) tmp").Check(testkit.Rows("1", "1", "1", "1"))
tk.MustQuery("select 10 as a from dual union select a from t order by a desc limit 1 ").Check(testkit.Rows("10"))
tk.MustQuery("select -10 as a from dual union select a from t order by a limit 1 ").Check(testkit.Rows("-10"))
tk.MustQuery("select count(1) from (select a from t union all select a from t) tmp").Check(testkit.Rows("4"))
err := tk.ExecToErr("select 1 from (select a from t limit 1 union all select a from t limit 1) tmp")
require.Error(t, err)
terr := errors.Cause(err).(*terror.Error)
require.Equal(t, errors.ErrCode(mysql.ErrWrongUsage), terr.Code())
err = tk.ExecToErr("select 1 from (select a from t order by a union all select a from t limit 1) tmp")
require.Error(t, err)
terr = errors.Cause(err).(*terror.Error)
require.Equal(t, errors.ErrCode(mysql.ErrWrongUsage), terr.Code())
tk.MustGetDBError("(select a from t order by a) union all select a from t limit 1 union all select a from t limit 1", plannererrors.ErrWrongUsage)
tk.MustExec("(select a from t limit 1) union all select a from t limit 1")
tk.MustExec("(select a from t order by a) union all select a from t order by a")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int)")
tk.MustExec("insert into t value(1),(2),(3)")
tk.MustQuery("(select a from t order by a limit 2) union all (select a from t order by a desc limit 2) order by a desc limit 1,2").Check(testkit.Rows("2", "2"))
tk.MustQuery("select a from t union all select a from t order by a desc limit 5").Check(testkit.Rows("3", "3", "2", "2", "1"))
tk.MustQuery("(select a from t order by a desc limit 2) union all select a from t group by a order by a").Check(testkit.Rows("1", "2", "2", "3", "3"))
tk.MustQuery("(select a from t order by a desc limit 2) union all select 33 as a order by a desc limit 2").Check(testkit.Rows("33", "3"))
tk.MustQuery("select 1 union select 1 union all select 1").Check(testkit.Rows("1", "1"))
tk.MustQuery("select 1 union all select 1 union select 1").Check(testkit.Rows("1"))
tk.MustExec("drop table if exists t1, t2")
tk.MustExec(`create table t1(a bigint, b bigint);`)
tk.MustExec(`create table t2(a bigint, b bigint);`)
tk.MustExec(`insert into t1 values(1, 1);`)
tk.MustExec(`insert into t1 select * from t1;`)
tk.MustExec(`insert into t1 select * from t1;`)
tk.MustExec(`insert into t1 select * from t1;`)
tk.MustExec(`insert into t1 select * from t1;`)
tk.MustExec(`insert into t1 select * from t1;`)
tk.MustExec(`insert into t1 select * from t1;`)
tk.MustExec(`insert into t2 values(1, 1);`)
tk.MustExec(`set @@tidb_init_chunk_size=2;`)
tk.MustExec(`set @@sql_mode="";`)
tk.MustQuery(`select count(*) from (select t1.a, t1.b from t1 left join t2 on t1.a=t2.a union all select t1.a, t1.a from t1 left join t2 on t1.a=t2.a) tmp;`).Check(testkit.Rows("128"))
tk.MustQuery(`select tmp.a, count(*) from (select t1.a, t1.b from t1 left join t2 on t1.a=t2.a union all select t1.a, t1.a from t1 left join t2 on t1.a=t2.a) tmp;`).Check(testkit.Rows("1 128"))
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int, b int)")
tk.MustExec("insert into t value(1 ,2)")
tk.MustQuery("select a, b from (select a, 0 as d, b from t union all select a, 0 as d, b from t) test;").Check(testkit.Rows("1 2", "1 2"))
// #issue 8141
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t1(a int, b int)")
tk.MustExec("insert into t1 value(1,2),(1,1),(2,2),(2,2),(3,2),(3,2)")
tk.MustExec("set @@tidb_init_chunk_size=2;")
tk.MustQuery("select count(*) from (select a as c, a as d from t1 union all select a, b from t1) t;").Check(testkit.Rows("12"))
// #issue 8189 and #issue 8199
tk.MustExec("drop table if exists t1")
tk.MustExec("drop table if exists t2")
tk.MustExec("CREATE TABLE t1 (a int not null, b char (10) not null)")
tk.MustExec("insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c')")
tk.MustExec("CREATE TABLE t2 (a int not null, b char (10) not null)")
tk.MustExec("insert into t2 values(1,'a'),(2,'b'),(3,'c'),(3,'c')")
tk.MustQuery("select a from t1 union select a from t1 order by (select a+1);").Check(testkit.Rows("1", "2", "3"))
// #issue 8201
for i := 0; i < 4; i++ {
tk.MustQuery("SELECT(SELECT 0 AS a FROM dual UNION SELECT 1 AS a FROM dual ORDER BY a ASC LIMIT 1) AS dev").Check(testkit.Rows("0"))
}
// #issue 8231
tk.MustExec("drop table if exists t1")
tk.MustExec("CREATE TABLE t1 (uid int(1))")
tk.MustExec("INSERT INTO t1 SELECT 150")
tk.MustQuery("SELECT 'a' UNION SELECT uid FROM t1 order by 1 desc;").Check(testkit.Rows("a", "150"))
// #issue 8196
tk.MustExec("drop table if exists t1")
tk.MustExec("drop table if exists t2")
tk.MustExec("CREATE TABLE t1 (a int not null, b char (10) not null)")
tk.MustExec("insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c')")
tk.MustExec("CREATE TABLE t2 (a int not null, b char (10) not null)")
tk.MustExec("insert into t2 values(3,'c'),(4,'d'),(5,'f'),(6,'e')")
tk.MustExec("analyze table t1")
tk.MustExec("analyze table t2")
tk.MustGetErrMsg("(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b",
"[planner:1250]Table 't1' from one of the SELECTs cannot be used in global ORDER clause")
// #issue 9900
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int, b decimal(6, 3))")
tk.MustExec("insert into t values(1, 1.000)")
tk.MustQuery("select count(distinct a), sum(distinct a), avg(distinct a) from (select a from t union all select b from t) tmp;").Check(testkit.Rows("1 1.000 1.0000000"))
// #issue 23832
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a bit(20), b float, c double, d int)")
tk.MustExec("insert into t values(10, 10, 10, 10), (1, -1, 2, -2), (2, -2, 1, 1), (2, 1.1, 2.1, 10.1)")
tk.MustQuery("select a from t union select 10 order by a").Check(testkit.Rows("1", "2", "10"))
}
func TestUnionLimit(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists union_limit")
tk.MustExec("create table union_limit (id int) partition by hash(id) partitions 30")
for i := 0; i < 60; i++ {
tk.MustExec(fmt.Sprintf("insert into union_limit values (%d)", i))
}
// Cover the code for worker count limit in the union executor.
tk.MustQuery("select * from union_limit limit 10")
}
func TestLowResolutionTSORead(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("set @@autocommit=1")
tk.MustExec("use test")
tk.MustExec("create table low_resolution_tso(a int key)")
tk.MustExec("insert low_resolution_tso values (1)")
// enable low resolution tso
require.False(t, tk.Session().GetSessionVars().UseLowResolutionTSO())
tk.MustExec("set @@tidb_low_resolution_tso = 'on'")
require.True(t, tk.Session().GetSessionVars().UseLowResolutionTSO())
tk.MustQuery("select * from low_resolution_tso")
err := tk.ExecToErr("update low_resolution_tso set a = 2")
require.Error(t, err)
tk.MustExec("set @@tidb_low_resolution_tso = 'off'")
tk.MustExec("update low_resolution_tso set a = 2")
tk.MustQuery("select * from low_resolution_tso").Check(testkit.Rows("2"))
// Test select for update could not be executed when `tidb_low_resolution_tso` is enabled.
type testCase struct {
optimistic bool
pointGet bool
}
cases := []testCase{
{true, true},
{true, false},
{false, true},
{false, false},
}
tk.MustExec("set @@tidb_low_resolution_tso = 'on'")
for _, test := range cases {
if test.optimistic {
tk.MustExec("begin optimistic")
} else {
tk.MustExec("begin")
}
var err error
if test.pointGet {
err = tk.ExecToErr("select * from low_resolution_tso where a = 1 for update")
} else {
err = tk.ExecToErr("select * from low_resolution_tso for update")
}
require.Error(t, err)
tk.MustExec("rollback")
}
tk.MustQuery("select * from low_resolution_tso for update")
tk.MustQuery("select * from low_resolution_tso where a = 1 for update")
origPessimisticAutoCommit := config.GetGlobalConfig().PessimisticTxn.PessimisticAutoCommit.Load()
config.GetGlobalConfig().PessimisticTxn.PessimisticAutoCommit.Store(true)
defer func() {
config.GetGlobalConfig().PessimisticTxn.PessimisticAutoCommit.Store(origPessimisticAutoCommit)
}()
err = tk.ExecToErr("select * from low_resolution_tso where a = 1 for update")
require.Error(t, err)
err = tk.ExecToErr("select * from low_resolution_tso for update")
require.Error(t, err)
}
func TestLowResolutionTSOReadScope(t *testing.T) {
store := testkit.CreateMockStore(t)
tk1 := testkit.NewTestKit(t, store)
require.False(t, tk1.Session().GetSessionVars().UseLowResolutionTSO())
tk1.MustExec("set global tidb_low_resolution_tso = 'on'")
tk2 := testkit.NewTestKit(t, store)
require.True(t, tk2.Session().GetSessionVars().UseLowResolutionTSO())
}
func TestAdapterStatement(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.Session().GetSessionVars().TxnCtx.InfoSchema = domain.GetDomain(tk.Session()).InfoSchema()
compiler := &executor.Compiler{Ctx: tk.Session()}
s := parser.New()
stmtNode, err := s.ParseOneStmt("select 1", "", "")
require.NoError(t, err)
stmt, err := compiler.Compile(context.TODO(), stmtNode)
require.NoError(t, err)
require.Equal(t, "select 1", stmt.OriginText())
stmtNode, err = s.ParseOneStmt("create table test.t (a int)", "", "")
require.NoError(t, err)
stmt, err = compiler.Compile(context.TODO(), stmtNode)
require.NoError(t, err)
require.Equal(t, "create table test.t (a int)", stmt.OriginText())
}
func TestIsPointGet(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use mysql")
ctx := tk.Session().(sessionctx.Context)
tests := map[string]bool{
"select * from help_topic where name='aaa'": false,
"select 1 from help_topic where name='aaa'": false,
"select * from help_topic where help_topic_id=1": true,
"select * from help_topic where help_category_id=1": false,
}
s := parser.New()
for sqlStr, result := range tests {
stmtNode, err := s.ParseOneStmt(sqlStr, "", "")
require.NoError(t, err)
preprocessorReturn := &plannercore.PreprocessorReturn{}
nodeW := resolve.NewNodeW(stmtNode)
err = plannercore.Preprocess(context.Background(), ctx, nodeW, plannercore.WithPreprocessorReturn(preprocessorReturn))
require.NoError(t, err)
p, _, err := planner.Optimize(context.TODO(), ctx, nodeW, preprocessorReturn.InfoSchema)
require.NoError(t, err)
ret := plannercore.IsPointGetWithPKOrUniqueKeyByAutoCommit(ctx.GetSessionVars(), p)
require.Equal(t, result, ret)
}
}
func TestPointGetOrderby(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t (i int key)")
require.Equal(t, tk.ExecToErr("select * from t where i = 1 order by j limit 10;").Error(), "[planner:1054]Unknown column 'j' in 'order clause'")
}
func TestClusteredIndexIsPointGet(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("drop database if exists test_cluster_index_is_point_get;")
tk.MustExec("create database test_cluster_index_is_point_get;")
tk.MustExec("use test_cluster_index_is_point_get;")
tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn
tk.MustExec("drop table if exists t;")
tk.MustExec("create table t (a varchar(255), b int, c char(10), primary key (c, a));")
ctx := tk.Session().(sessionctx.Context)
tests := map[string]bool{
"select 1 from t where a='x'": false,
"select * from t where c='x'": false,
"select * from t where a='x' and c='x'": true,
"select * from t where a='x' and c='x' and b=1": false,
}
s := parser.New()
for sqlStr, result := range tests {
stmtNode, err := s.ParseOneStmt(sqlStr, "", "")
require.NoError(t, err)
preprocessorReturn := &plannercore.PreprocessorReturn{}
nodeW := resolve.NewNodeW(stmtNode)
err = plannercore.Preprocess(context.Background(), ctx, nodeW, plannercore.WithPreprocessorReturn(preprocessorReturn))
require.NoError(t, err)
p, _, err := planner.Optimize(context.TODO(), ctx, nodeW, preprocessorReturn.InfoSchema)
require.NoError(t, err)
ret := plannercore.IsPointGetWithPKOrUniqueKeyByAutoCommit(ctx.GetSessionVars(), p)
require.Equal(t, result, ret)
}
}
func TestColumnName(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (c int, d int)")
// disable only full group by
tk.MustExec("set sql_mode='STRICT_TRANS_TABLES'")
rs, err := tk.Exec("select 1 + c, count(*) from t")
require.NoError(t, err)
fields := rs.Fields()
require.Len(t, fields, 2)
require.Equal(t, "1 + c", fields[0].Column.Name.L)
require.Equal(t, "1 + c", fields[0].ColumnAsName.L)
require.Equal(t, "count(*)", fields[1].Column.Name.L)
require.Equal(t, "count(*)", fields[1].ColumnAsName.L)
require.NoError(t, rs.Close())
rs, err = tk.Exec("select (c) > all (select c from t) from t")
require.NoError(t, err)
fields = rs.Fields()
require.Len(t, fields, 1)
require.Equal(t, "(c) > all (select c from t)", fields[0].Column.Name.L)
require.Equal(t, "(c) > all (select c from t)", fields[0].ColumnAsName.L)
require.NoError(t, rs.Close())
tk.MustExec("begin")
tk.MustExec("insert t values(1,1)")
rs, err = tk.Exec("select c d, d c from t")
require.NoError(t, err)
fields = rs.Fields()
require.Len(t, fields, 2)
require.Equal(t, "c", fields[0].Column.Name.L)
require.Equal(t, "d", fields[0].ColumnAsName.L)
require.Equal(t, "d", fields[1].Column.Name.L)
require.Equal(t, "c", fields[1].ColumnAsName.L)
require.NoError(t, rs.Close())
// Test case for query a column of a table.
// In this case, all attributes have values.
rs, err = tk.Exec("select c as a from t as t2")
require.NoError(t, err)
fields = rs.Fields()
require.Equal(t, "c", fields[0].Column.Name.L)
require.Equal(t, "a", fields[0].ColumnAsName.L)
require.Equal(t, "t", fields[0].Table.Name.L)
require.Equal(t, "t2", fields[0].TableAsName.L)
require.Equal(t, "test", fields[0].DBName.L)
require.Nil(t, rs.Close())
// Test case for query a expression which only using constant inputs.
// In this case, the table, org_table and database attributes will all be empty.
rs, err = tk.Exec("select hour(1) as a from t as t2")
require.NoError(t, err)
fields = rs.Fields()
require.Equal(t, "a", fields[0].Column.Name.L)
require.Equal(t, "a", fields[0].ColumnAsName.L)
require.Equal(t, "", fields[0].Table.Name.L)
require.Equal(t, "", fields[0].TableAsName.L)
require.Equal(t, "", fields[0].DBName.L)
require.Nil(t, rs.Close())
// Test case for query a column wrapped with parentheses and unary plus.
// In this case, the column name should be its original name.
rs, err = tk.Exec("select (c), (+c), +(c), +(+(c)), ++c from t")
require.NoError(t, err)
fields = rs.Fields()
for i := 0; i < 5; i++ {
require.Equal(t, "c", fields[i].Column.Name.L)
require.Equal(t, "c", fields[i].ColumnAsName.L)
}
require.Nil(t, rs.Close())
// Test issue https://github.com/pingcap/tidb/issues/9639 .
// Both window function and expression appear in final result field.
tk.MustExec("set @@tidb_enable_window_function = 1")
rs, err = tk.Exec("select 1+1, row_number() over() num from t")
require.NoError(t, err)
fields = rs.Fields()
require.Equal(t, "1+1", fields[0].Column.Name.L)
require.Equal(t, "1+1", fields[0].ColumnAsName.L)
require.Equal(t, "num", fields[1].Column.Name.L)
require.Equal(t, "num", fields[1].ColumnAsName.L)
require.Nil(t, rs.Close())
tk.MustExec("set @@tidb_enable_window_function = 0")
rs, err = tk.Exec("select if(1,c,c) from t;")
require.NoError(t, err)
fields = rs.Fields()
require.Equal(t, "if(1,c,c)", fields[0].Column.Name.L)
// It's a compatibility issue. Should be empty instead.
require.Equal(t, "if(1,c,c)", fields[0].ColumnAsName.L)
require.Nil(t, rs.Close())
}
func TestSelectVar(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (d int)")
tk.MustExec("insert into t values(1), (2), (1)")
// This behavior is different from MySQL.
result := tk.MustQuery("select @a, @a := d+1 from t")
result.Check(testkit.Rows("<nil> 2", "2 3", "3 2"))
// Test for PR #10658.
tk.MustExec("select SQL_BIG_RESULT d from t group by d")
tk.MustExec("select SQL_SMALL_RESULT d from t group by d")
tk.MustExec("select SQL_BUFFER_RESULT d from t group by d")
}
func TestHistoryRead(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists history_read")
tk.MustExec("create table history_read (a int)")
tk.MustExec("insert history_read values (1)")
// For mocktikv, safe point is not initialized, we manually insert it for snapshot to use.
safePointName := "tikv_gc_safe_point"
safePointValue := "20060102-15:04:05 -0700"
safePointComment := "All versions after safe point can be accessed. (DO NOT EDIT)"
updateSafePoint := fmt.Sprintf(`INSERT INTO mysql.tidb VALUES ('%[1]s', '%[2]s', '%[3]s')
ON DUPLICATE KEY
UPDATE variable_value = '%[2]s', comment = '%[3]s'`, safePointName, safePointValue, safePointComment)
tk.MustExec(updateSafePoint)
// Set snapshot to a time before save point will fail.
_, err := tk.Exec("set @@tidb_snapshot = '2006-01-01 15:04:05.999999'")
require.True(t, terror.ErrorEqual(err, variable.ErrSnapshotTooOld), "err %v", err)
// SnapshotTS Is not updated if check failed.
require.Equal(t, uint64(0), tk.Session().GetSessionVars().SnapshotTS)
// Setting snapshot to a time in the future will fail. (One day before the 2038 problem)
_, err = tk.Exec("set @@tidb_snapshot = '2038-01-18 03:14:07'")
require.Regexp(t, "cannot set read timestamp to a future time", err)
// SnapshotTS Is not updated if check failed.
require.Equal(t, uint64(0), tk.Session().GetSessionVars().SnapshotTS)
curVer1, _ := store.CurrentVersion(kv.GlobalTxnScope)
time.Sleep(time.Millisecond)
snapshotTime := time.Now()
time.Sleep(time.Millisecond)
curVer2, _ := store.CurrentVersion(kv.GlobalTxnScope)
tk.MustExec("insert history_read values (2)")
tk.MustQuery("select * from history_read").Check(testkit.Rows("1", "2"))
tk.MustExec("set @@tidb_snapshot = '" + snapshotTime.Format("2006-01-02 15:04:05.999999") + "'")
ctx := tk.Session().(sessionctx.Context)
snapshotTS := ctx.GetSessionVars().SnapshotTS
require.Greater(t, snapshotTS, curVer1.Ver)
require.Less(t, snapshotTS, curVer2.Ver)
tk.MustQuery("select * from history_read").Check(testkit.Rows("1"))
tk.MustExecToErr("insert history_read values (2)")
tk.MustExecToErr("update history_read set a = 3 where a = 1")
tk.MustExecToErr("delete from history_read where a = 1")
tk.MustExec("set @@tidb_snapshot = ''")
tk.MustQuery("select * from history_read").Check(testkit.Rows("1", "2"))
tk.MustExec("insert history_read values (3)")
tk.MustExec("update history_read set a = 4 where a = 3")
tk.MustExec("delete from history_read where a = 1")
time.Sleep(time.Millisecond)
snapshotTime = time.Now()
time.Sleep(time.Millisecond)
tk.MustExec("alter table history_read add column b int")
tk.MustExec("insert history_read values (8, 8), (9, 9)")
tk.MustQuery("select * from history_read order by a").Check(testkit.Rows("2 <nil>", "4 <nil>", "8 8", "9 9"))
tk.MustExec("set @@tidb_snapshot = '" + snapshotTime.Format("2006-01-02 15:04:05.999999") + "'")
tk.MustQuery("select * from history_read order by a").Check(testkit.Rows("2", "4"))
tsoStr := strconv.FormatUint(oracle.GoTimeToTS(snapshotTime), 10)
tk.MustExec("set @@tidb_snapshot = '" + tsoStr + "'")
tk.MustQuery("select * from history_read order by a").Check(testkit.Rows("2", "4"))
tk.MustExec("set @@tidb_snapshot = ''")
tk.MustQuery("select * from history_read order by a").Check(testkit.Rows("2 <nil>", "4 <nil>", "8 8", "9 9"))
}
func TestHistoryReadInTxn(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
// For mocktikv, safe point is not initialized, we manually insert it for snapshot to use.
safePointName := "tikv_gc_safe_point"
safePointValue := "20060102-15:04:05 -0700"
safePointComment := "All versions after safe point can be accessed. (DO NOT EDIT)"
updateSafePoint := fmt.Sprintf(`INSERT INTO mysql.tidb VALUES ('%[1]s', '%[2]s', '%[3]s')
ON DUPLICATE KEY
UPDATE variable_value = '%[2]s', comment = '%[3]s'`, safePointName, safePointValue, safePointComment)
tk.MustExec(updateSafePoint)
tk.MustExec("drop table if exists his_t0, his_t1")
tk.MustExec("create table his_t0(id int primary key, v int)")
tk.MustExec("insert into his_t0 values(1, 10)")
time.Sleep(time.Millisecond)
tk.MustExec("set @a=now(6)")
time.Sleep(time.Millisecond)
tk.MustExec("create table his_t1(id int primary key, v int)")
tk.MustExec("update his_t0 set v=v+1")
time.Sleep(time.Millisecond)
tk.MustExec("set tidb_snapshot=now(6)")
ts2 := tk.Session().GetSessionVars().SnapshotTS
tk.MustExec("set tidb_snapshot=''")
time.Sleep(time.Millisecond)
tk.MustExec("update his_t0 set v=v+1")
tk.MustExec("insert into his_t1 values(10, 100)")
init := func(isolation string, setSnapshotBeforeTxn bool) {
if isolation == "none" {
tk.MustExec("set @@tidb_snapshot=@a")
return
}
if setSnapshotBeforeTxn {
tk.MustExec("set @@tidb_snapshot=@a")
}
if isolation == "optimistic" {
tk.MustExec("begin optimistic")
} else {
tk.MustExec(fmt.Sprintf("set @@tx_isolation='%s'", isolation))
tk.MustExec("begin pessimistic")
}
if !setSnapshotBeforeTxn {
tk.MustExec("set @@tidb_snapshot=@a")
}
}
for _, isolation := range []string{
"none", // not start an explicit txn
"optimistic",
"REPEATABLE-READ",
"READ-COMMITTED",
} {
for _, setSnapshotBeforeTxn := range []bool{false, true} {
t.Run(fmt.Sprintf("[%s] setSnapshotBeforeTxn[%v]", isolation, setSnapshotBeforeTxn), func(t *testing.T) {
tk.MustExec("rollback")
tk.MustExec("set @@tidb_snapshot=''")
init(isolation, setSnapshotBeforeTxn)
// When tidb_snapshot is set, should use the snapshot info schema
tk.MustQuery("show tables like 'his_%'").Check(testkit.Rows("his_t0"))
// When tidb_snapshot is set, select should use select ts
tk.MustQuery("select * from his_t0").Check(testkit.Rows("1 10"))
tk.MustQuery("select * from his_t0 where id=1").Check(testkit.Rows("1 10"))
// When tidb_snapshot is set, write statements should not be allowed
if isolation != "none" && isolation != "optimistic" {
notAllowedSQLs := []string{
"insert into his_t0 values(5, 1)",
"delete from his_t0 where id=1",
"update his_t0 set v=v+1",
"select * from his_t0 for update",
"select * from his_t0 where id=1 for update",
"create table his_t2(id int)",
}
for _, sql := range notAllowedSQLs {
err := tk.ExecToErr(sql)
require.Errorf(t, err, "can not execute write statement when 'tidb_snapshot' is set")
}
}
// After `ExecRestrictedSQL` with a specified snapshot and use current session, the original snapshot ts should not be reset
// See issue: https://github.com/pingcap/tidb/issues/34529
exec := tk.Session().GetRestrictedSQLExecutor()
ctx := kv.WithInternalSourceType(context.Background(), kv.InternalTxnOthers)
rows, _, err := exec.ExecRestrictedSQL(ctx, []sqlexec.OptionFuncAlias{sqlexec.ExecOptionWithSnapshot(ts2), sqlexec.ExecOptionUseCurSession}, "select * from his_t0 where id=1")
require.NoError(t, err)
require.Equal(t, 1, len(rows))
require.Equal(t, int64(1), rows[0].GetInt64(0))
require.Equal(t, int64(11), rows[0].GetInt64(1))
tk.MustQuery("select * from his_t0 where id=1").Check(testkit.Rows("1 10"))
tk.MustQuery("show tables like 'his_%'").Check(testkit.Rows("his_t0"))
// CLEAR
tk.MustExec("set @@tidb_snapshot=''")
// When tidb_snapshot is not set, should use the transaction's info schema
tk.MustQuery("show tables like 'his_%'").Check(testkit.Rows("his_t0", "his_t1"))
// When tidb_snapshot is not set, select should use the transaction's ts
tk.MustQuery("select * from his_t0").Check(testkit.Rows("1 12"))
tk.MustQuery("select * from his_t0 where id=1").Check(testkit.Rows("1 12"))
tk.MustQuery("select * from his_t1").Check(testkit.Rows("10 100"))
tk.MustQuery("select * from his_t1 where id=10").Check(testkit.Rows("10 100"))
// When tidb_snapshot is not set, select ... for update should not be effected
tk.MustQuery("select * from his_t0 for update").Check(testkit.Rows("1 12"))
tk.MustQuery("select * from his_t0 where id=1 for update").Check(testkit.Rows("1 12"))
tk.MustQuery("select * from his_t1 for update").Check(testkit.Rows("10 100"))
tk.MustQuery("select * from his_t1 where id=10 for update").Check(testkit.Rows("10 100"))
tk.MustExec("rollback")
})
}
}
}
func TestCurrentTimestampValueSelection(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t,t1")
tk.MustExec("create table t (id int, t0 timestamp null default current_timestamp, t1 timestamp(1) null default current_timestamp(1), t2 timestamp(2) null default current_timestamp(2) on update current_timestamp(2))")
tk.MustExec("insert into t (id) values (1)")
rs := tk.MustQuery("select t0, t1, t2 from t where id = 1")
t0 := rs.Rows()[0][0].(string)
t1 := rs.Rows()[0][1].(string)
t2 := rs.Rows()[0][2].(string)
require.Equal(t, 1, len(strings.Split(t0, ".")))
require.Equal(t, 1, len(strings.Split(t1, ".")[1]))
require.Equal(t, 2, len(strings.Split(t2, ".")[1]))
tk.MustQuery("select id from t where t0 = ?", t0).Check(testkit.Rows("1"))
tk.MustQuery("select id from t where t1 = ?", t1).Check(testkit.Rows("1"))
tk.MustQuery("select id from t where t2 = ?", t2).Check(testkit.Rows("1"))
time.Sleep(time.Second)
tk.MustExec("update t set t0 = now() where id = 1")
rs = tk.MustQuery("select t2 from t where id = 1")
newT2 := rs.Rows()[0][0].(string)
require.True(t, newT2 != t2)
tk.MustExec("create table t1 (id int, a timestamp, b timestamp(2), c timestamp(3))")
tk.MustExec("insert into t1 (id, a, b, c) values (1, current_timestamp(2), current_timestamp, current_timestamp(3))")
rs = tk.MustQuery("select a, b, c from t1 where id = 1")
a := rs.Rows()[0][0].(string)
b := rs.Rows()[0][1].(string)
d := rs.Rows()[0][2].(string)
require.Equal(t, 1, len(strings.Split(a, ".")))
require.Equal(t, "00", strings.Split(b, ".")[1])
require.Equal(t, 3, len(strings.Split(d, ".")[1]))
}
func TestAdmin(t *testing.T) {
var cluster testutils.Cluster
store := testkit.CreateMockStore(t, mockstore.WithClusterInspector(func(c testutils.Cluster) {
mockstore.BootstrapWithSingleStore(c)
cluster = c
}))
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk2 := testkit.NewTestKit(t, store)
tk2.MustExec("use test")
tk.MustExec("drop table if exists admin_test")
tk.MustExec("create table admin_test (c1 int, c2 int, c3 int default 1, index (c1))")
tk.MustExec("insert admin_test (c1) values (1),(2),(NULL)")
ctx := context.Background()
// cancel DDL jobs test
r, err := tk.Exec("admin cancel ddl jobs 1")
require.NoError(t, err)
req := r.NewChunk(nil)
err = r.Next(ctx, req)
require.NoError(t, err)
row := req.GetRow(0)
require.Equal(t, 2, row.Len())
require.Equal(t, "1", row.GetString(0))
require.Regexp(t, ".*DDL Job:1 not found", row.GetString(1))
// show ddl test;
r, err = tk.Exec("admin show ddl")
require.NoError(t, err)
req = r.NewChunk(nil)
err = r.Next(ctx, req)
require.NoError(t, err)
row = req.GetRow(0)
require.Equal(t, 6, row.Len())
tk = testkit.NewTestKit(t, store)
tk.MustExec("begin")
sess := tk.Session()
ddlInfo, err := ddl.GetDDLInfo(sess)
require.NoError(t, err)
require.Equal(t, ddlInfo.SchemaVer, row.GetInt64(0))
// TODO: Pass this test.
// rowOwnerInfos := strings.Split(row.Data[1].GetString(), ",")
// ownerInfos := strings.Split(ddlInfo.Owner.String(), ",")
// c.Assert(rowOwnerInfos[0], Equals, ownerInfos[0])
serverInfo, err := infosync.GetServerInfoByID(ctx, row.GetString(1))
require.NoError(t, err)
require.Equal(t, serverInfo.IP+":"+strconv.FormatUint(uint64(serverInfo.Port), 10), row.GetString(2))
require.Equal(t, "", row.GetString(3))
req = r.NewChunk(nil)
err = r.Next(ctx, req)
require.NoError(t, err)
require.Zero(t, req.NumRows())
tk.MustExec("rollback")
// show DDL jobs test
r, err = tk.Exec("admin show ddl jobs")
require.NoError(t, err)
req = r.NewChunk(nil)
err = r.Next(ctx, req)
require.NoError(t, err)
row = req.GetRow(0)
require.Equal(t, 13, row.Len())
txn, err := store.Begin()
require.NoError(t, err)
historyJobs, err := ddl.GetLastNHistoryDDLJobs(meta.NewMutator(txn), ddl.DefNumHistoryJobs)
require.Greater(t, len(historyJobs), 1)
require.Greater(t, len(row.GetString(1)), 0)
require.NoError(t, err)
require.Equal(t, historyJobs[0].ID, row.GetInt64(0))
require.NoError(t, err)
r, err = tk.Exec("admin show ddl jobs 20")
require.NoError(t, err)
req = r.NewChunk(nil)
err = r.Next(ctx, req)
require.NoError(t, err)
row = req.GetRow(0)
require.Equal(t, 13, row.Len())
require.Equal(t, historyJobs[0].ID, row.GetInt64(0))
require.NoError(t, err)
// show DDL job queries test
tk.MustExec("use test")
tk.MustExec("drop table if exists admin_test2")
tk.MustExec("create table admin_test2 (c1 int, c2 int, c3 int default 1, index (c1))")
result := tk.MustQuery(`admin show ddl job queries 1, 1, 1`)
result.Check(testkit.Rows())
result = tk.MustQuery(`admin show ddl job queries 1, 2, 3, 4`)
result.Check(testkit.Rows())
historyJobs, err = ddl.GetLastNHistoryDDLJobs(meta.NewMutator(txn), ddl.DefNumHistoryJobs)
result = tk.MustQuery(fmt.Sprintf("admin show ddl job queries %d", historyJobs[0].ID))
result.Check(testkit.Rows(historyJobs[0].Query))
require.NoError(t, err)
// show DDL job queries with range test
tk.MustExec("use test")
tk.MustExec("drop table if exists admin_test2")
tk.MustExec("create table admin_test2 (c1 int, c2 int, c3 int default 1, index (c1))")
tk.MustExec("drop table if exists admin_test3")
tk.MustExec("create table admin_test3 (c1 int, c2 int, c3 int default 1, index (c1))")
tk.MustExec("drop table if exists admin_test4")
tk.MustExec("create table admin_test4 (c1 int, c2 int, c3 int default 1, index (c1))")
tk.MustExec("drop table if exists admin_test5")
tk.MustExec("create table admin_test5 (c1 int, c2 int, c3 int default 1, index (c1))")
tk.MustExec("drop table if exists admin_test6")
tk.MustExec("create table admin_test6 (c1 int, c2 int, c3 int default 1, index (c1))")
tk.MustExec("drop table if exists admin_test7")
tk.MustExec("create table admin_test7 (c1 int, c2 int, c3 int default 1, index (c1))")
tk.MustExec("drop table if exists admin_test8")
tk.MustExec("create table admin_test8 (c1 int, c2 int, c3 int default 1, index (c1))")
historyJobs, err = ddl.GetLastNHistoryDDLJobs(meta.NewMutator(txn), ddl.DefNumHistoryJobs)
result = tk.MustQuery(`admin show ddl job queries limit 3`)
result.Check(testkit.Rows(fmt.Sprintf("%d %s", historyJobs[0].ID, historyJobs[0].Query), fmt.Sprintf("%d %s", historyJobs[1].ID, historyJobs[1].Query), fmt.Sprintf("%d %s", historyJobs[2].ID, historyJobs[2].Query)))
result = tk.MustQuery(`admin show ddl job queries limit 3, 2`)
result.Check(testkit.Rows(fmt.Sprintf("%d %s", historyJobs[3].ID, historyJobs[3].Query), fmt.Sprintf("%d %s", historyJobs[4].ID, historyJobs[4].Query)))
result = tk.MustQuery(`admin show ddl job queries limit 3 offset 2`)
result.Check(testkit.Rows(fmt.Sprintf("%d %s", historyJobs[2].ID, historyJobs[2].Query), fmt.Sprintf("%d %s", historyJobs[3].ID, historyJobs[3].Query), fmt.Sprintf("%d %s", historyJobs[4].ID, historyJobs[4].Query)))
require.NoError(t, err)
// check situations when `admin show ddl job 20` happens at the same time with new DDLs being executed
var wg sync.WaitGroup
wg.Add(2)
flag := true
go func() {
defer wg.Done()
for i := 0; i < 10; i++ {
tk.MustExec("drop table if exists admin_test9")
tk.MustExec("create table admin_test9 (c1 int, c2 int, c3 int default 1, index (c1))")
}
}()
go func() {
// check that the result set has no duplication
defer wg.Done()
for i := 0; i < 10; i++ {
result := tk2.MustQuery(`admin show ddl job queries 20`)
rows := result.Rows()
rowIDs := make(map[string]struct{})
for _, row := range rows {
rowID := fmt.Sprintf("%v", row[0])
if _, ok := rowIDs[rowID]; ok {
flag = false
return
}
rowIDs[rowID] = struct{}{}
}
}
}()
wg.Wait()
require.True(t, flag)
// check situations when `admin show ddl job queries limit 3 offset 2` happens at the same time with new DDLs being executed
var wg2 sync.WaitGroup
wg2.Add(2)
flag = true
go func() {
defer wg2.Done()
for i := 0; i < 10; i++ {
tk.MustExec("drop table if exists admin_test9")
tk.MustExec("create table admin_test9 (c1 int, c2 int, c3 int default 1, index (c1))")
}
}()
go func() {
// check that the result set has no duplication
defer wg2.Done()
for i := 0; i < 10; i++ {
result := tk2.MustQuery(`admin show ddl job queries limit 3 offset 2`)
rows := result.Rows()
rowIDs := make(map[string]struct{})
for _, row := range rows {
rowID := fmt.Sprintf("%v", row[0])
if _, ok := rowIDs[rowID]; ok {
flag = false
return
}
rowIDs[rowID] = struct{}{}
}
}
}()
wg2.Wait()
require.True(t, flag)
// check table test
tk.MustExec("create table admin_test1 (c1 int, c2 int default 1, index (c1))")
tk.MustExec("insert admin_test1 (c1) values (21),(22)")
r, err = tk.Exec("admin check table admin_test, admin_test1")
require.NoError(t, err)
require.Nil(t, r)
// error table name
require.Error(t, tk.ExecToErr("admin check table admin_test_error"))
// different index values
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
require.NotNil(t, is)
tb, err := is.TableByName(context.Background(), pmodel.NewCIStr("test"), pmodel.NewCIStr("admin_test"))
require.NoError(t, err)
require.Len(t, tb.Indices(), 1)
_, err = tb.Indices()[0].Create(mock.NewContext().GetTableCtx(), txn, types.MakeDatums(int64(10)), kv.IntHandle(1), nil)
require.NoError(t, err)
err = txn.Commit(context.Background())
require.NoError(t, err)
errAdmin := tk.ExecToErr("admin check table admin_test")
require.Error(t, errAdmin)
if config.CheckTableBeforeDrop {
tk.MustGetErrMsg("drop table admin_test", errAdmin.Error())
// Drop inconsistency index.
tk.MustExec("alter table admin_test drop index c1")
tk.MustExec("admin check table admin_test")
}
// checksum table test
tk.MustExec("create table checksum_with_index (id int, count int, PRIMARY KEY(id), KEY(count))")
tk.MustExec("create table checksum_without_index (id int, count int, PRIMARY KEY(id))")
r, err = tk.Exec("admin checksum table checksum_with_index, checksum_without_index")
require.NoError(t, err)
res := tk.ResultSetToResult(r, "admin checksum table")
// Mocktikv returns 1 for every table/index scan, then we will xor the checksums of a table.
// For "checksum_with_index", we have two checksums, so the result will be 1^1 = 0.
// For "checksum_without_index", we only have one checksum, so the result will be 1.
res.Sort().Check(testkit.Rows("test checksum_with_index 0 2 2", "test checksum_without_index 1 1 1"))
tk.MustExec("drop table if exists t1;")
tk.MustExec("CREATE TABLE t1 (c2 BOOL, PRIMARY KEY (c2));")
tk.MustExec("INSERT INTO t1 SET c2 = '0';")
tk.MustExec("ALTER TABLE t1 ADD COLUMN c3 DATETIME NULL DEFAULT '2668-02-03 17:19:31';")
tk.MustExec("ALTER TABLE t1 ADD INDEX idx2 (c3);")
tk.MustExec("ALTER TABLE t1 ADD COLUMN c4 bit(10) default 127;")
tk.MustExec("ALTER TABLE t1 ADD INDEX idx3 (c4);")
tk.MustExec("admin check table t1;")
// Test admin show ddl jobs table name after table has been droped.
tk.MustExec("drop table if exists t1;")
re := tk.MustQuery("admin show ddl jobs 1")
rows := re.Rows()
require.Len(t, rows, 1)
require.Equal(t, "t1", rows[0][2])
// Test for reverse scan get history ddl jobs when ddl history jobs queue has multiple regions.
txn, err = store.Begin()
require.NoError(t, err)
historyJobs, err = ddl.GetLastNHistoryDDLJobs(meta.NewMutator(txn), 20)
require.NoError(t, err)
// Split region for history ddl job queues.
m := meta.NewMutator(txn)
startKey := meta.DDLJobHistoryKey(m, 0)
endKey := meta.DDLJobHistoryKey(m, historyJobs[0].ID)
cluster.SplitKeys(startKey, endKey, int(historyJobs[0].ID/5))
historyJobs2, err := ddl.GetLastNHistoryDDLJobs(meta.NewMutator(txn), 20)
require.NoError(t, err)
require.Equal(t, historyJobs2, historyJobs)
}
func TestMaxOneRow(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec(`use test`)
tk.MustExec(`drop table if exists t1`)
tk.MustExec(`drop table if exists t2`)
tk.MustExec(`create table t1(a double, b double);`)
tk.MustExec(`create table t2(a double, b double);`)
tk.MustExec(`insert into t1 values(1, 1), (2, 2), (3, 3);`)
tk.MustExec(`insert into t2 values(0, 0);`)
tk.MustExec(`set @@tidb_init_chunk_size=1;`)
rs, err := tk.Exec(`select (select t1.a from t1 where t1.a > t2.a) as a from t2;`)
require.NoError(t, err)
err = rs.Next(context.TODO(), rs.NewChunk(nil))
require.Error(t, err)
require.Equal(t, "[executor:1242]Subquery returns more than 1 row", err.Error())
require.NoError(t, rs.Close())
}
func TestIsFastPlan(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t(id int primary key, a int)")
cases := []struct {
sql string
isFastPlan bool
}{
{"select a from t where id=1", true},
{"select a+id from t where id=1", true},
{"select 1", true},
{"select @@autocommit", true},
{"set @@autocommit=1", true},
{"set @a=1", true},
{"select * from t where a=1", false},
{"select * from t", false},
}
for _, ca := range cases {
if strings.HasPrefix(ca.sql, "select") {
tk.MustQuery(ca.sql)
} else {
tk.MustExec(ca.sql)
}
info := tk.Session().ShowProcess()
require.NotNil(t, info)
p, ok := info.Plan.(base.Plan)
require.True(t, ok)
ok = executor.IsFastPlan(p)
require.Equal(t, ca.isFastPlan, ok)
}
}
func TestGlobalMemoryControl2(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(t)
tk0 := testkit.NewTestKit(t, store)
tk0.MustExec("set global tidb_mem_oom_action = 'cancel'")
tk0.MustExec("set global tidb_server_memory_limit = 1 << 30")
tk0.MustExec("set global tidb_server_memory_limit_sess_min_size = 128")
sm := &testkit.MockSessionManager{
PS: []*util.ProcessInfo{tk0.Session().ShowProcess()},
}
dom.ServerMemoryLimitHandle().SetSessionManager(sm)
go dom.ServerMemoryLimitHandle().Run()
tk0.MustExec("use test")
tk0.MustExec("create table t(a int)")
tk0.MustExec("insert into t select 1")
for i := 1; i <= 8; i++ {
tk0.MustExec("insert into t select * from t") // 256 Lines
}
var test []int
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
time.Sleep(100 * time.Millisecond) // Make sure the sql is running.
test = make([]int, 128<<20) // Keep 1GB HeapInuse
wg.Done()
}()
sql := "select * from t t1 join t t2 join t t3 on t1.a=t2.a and t1.a=t3.a order by t1.a;" // Need 500MB
require.True(t, exeerrors.ErrMemoryExceedForInstance.Equal(tk0.QueryToErr(sql)))
require.Equal(t, tk0.Session().GetSessionVars().DiskTracker.MaxConsumed(), int64(0))
wg.Wait()
test[0] = 0
runtime.GC()
}
func TestSignalCheckpointForSort(t *testing.T) {
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/pkg/executor/sortexec/SignalCheckpointForSort", `return(true)`))
defer func() {
require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/pkg/executor/sortexec/SignalCheckpointForSort"))
}()
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/pkg/util/chunk/SignalCheckpointForSort", `return(true)`))
defer func() {
require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/pkg/util/chunk/SignalCheckpointForSort"))
}()
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
defer tk.MustExec("set global tidb_mem_oom_action = DEFAULT")
tk.MustExec("set global tidb_mem_oom_action='CANCEL'")
tk.MustExec("set tidb_mem_quota_query = 100000000")
tk.MustExec("use test")
tk.MustExec("create table t(a int)")
for i := 0; i < 20; i++ {
tk.MustExec(fmt.Sprintf("insert into t values(%d)", i))
}
tk.Session().GetSessionVars().ConnectionID = 123456
err := tk.QueryToErr("select * from t order by a")
require.True(t, exeerrors.ErrMemoryExceedForQuery.Equal(err))
}
func TestSessionRootTrackerDetach(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
defer tk.MustExec("set global tidb_mem_oom_action = DEFAULT")
tk.MustExec("set global tidb_mem_oom_action='CANCEL'")
tk.MustExec("use test")
tk.MustExec("create table t(a int, b int, index idx(a))")
tk.MustExec("create table t1(a int, c int, index idx(a))")
tk.MustExec("set tidb_mem_quota_query=10")
err := tk.ExecToErr("select /*+hash_join(t1)*/ t.a, t1.a from t use index(idx), t1 use index(idx) where t.a = t1.a")
fmt.Println(err.Error())
require.True(t, exeerrors.ErrMemoryExceedForQuery.Equal(err))
tk.MustExec("set tidb_mem_quota_query=1000")
rs, err := tk.Exec("select /*+hash_join(t1)*/ t.a, t1.a from t use index(idx), t1 use index(idx) where t.a = t1.a")
require.NoError(t, err)
require.NotNil(t, tk.Session().GetSessionVars().MemTracker.GetFallbackForTest(false))
err = rs.Close()
require.NoError(t, err)
require.Nil(t, tk.Session().GetSessionVars().MemTracker.GetFallbackForTest(false))
}
func TestProcessInfoOfSubQuery(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk2 := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t (i int, j int);")
var wg sync.WaitGroup
wg.Add(1)
go func() {
tk.MustQuery("select 1, (select sleep(count(1) + 2) from t);")
wg.Done()
}()
time.Sleep(time.Second)
tk2.MustQuery("select 1 from information_schema.processlist where TxnStart != '' and info like 'select%sleep% from t%'").Check(testkit.Rows("1"))
wg.Wait()
}
func TestIssues49377(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table employee (employee_id int, name varchar(20), dept_id int)")
tk.MustExec("insert into employee values (1, 'Furina', 1), (2, 'Klee', 1), (3, 'Eula', 1), (4, 'Diluc', 2), (5, 'Tartaglia', 2)")
tk.MustQuery("select 1,1,1 union all ( " +
"(select * from employee where dept_id = 1) " +
"union all " +
"(select * from employee where dept_id = 1 order by employee_id) " +
"order by 1 limit 1 " +
");").Sort().Check(testkit.Rows("1 1 1", "1 Furina 1"))
tk.MustQuery("select 1,1,1 union all ( " +
"(select * from employee where dept_id = 1) " +
"union all " +
"(select * from employee where dept_id = 1 order by employee_id) " +
"order by 1" +
");").Sort().Check(testkit.Rows("1 1 1", "1 Furina 1", "1 Furina 1", "2 Klee 1", "2 Klee 1", "3 Eula 1", "3 Eula 1"))
tk.MustQuery("select * from employee where dept_id = 1 " +
"union all " +
"(select * from employee where dept_id = 1 order by employee_id) " +
"union all" +
"(" +
"select * from employee where dept_id = 1 " +
"union all " +
"(select * from employee where dept_id = 1 order by employee_id) " +
"limit 1" +
");").Sort().Check(testkit.Rows("1 Furina 1", "1 Furina 1", "1 Furina 1", "2 Klee 1", "2 Klee 1", "3 Eula 1", "3 Eula 1"))
}
func TestIssues40463(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test;")
tk.MustExec("CREATE TABLE `4f380f26-9af6-4df8-959d-ad6296eff914` (`f7a9a4be-3728-449b-a5ea-df9b957eec67` enum('bkdv0','9rqy','lw','neud','ym','4nbv','9a7','bpkfo','xtfl','59','6vjj') NOT NULL DEFAULT 'neud', `43ca0135-1650-429b-8887-9eabcae2a234` set('8','5x47','xc','o31','lnz','gs5s','6yam','1','20ea','i','e') NOT NULL DEFAULT 'e', PRIMARY KEY (`f7a9a4be-3728-449b-a5ea-df9b957eec67`,`43ca0135-1650-429b-8887-9eabcae2a234`) /*T![clustered_index] CLUSTERED */) ENGINE=InnoDB DEFAULT CHARSET=ascii COLLATE=ascii_bin;")
tk.MustExec("INSERT INTO `4f380f26-9af6-4df8-959d-ad6296eff914` VALUES ('bkdv0','gs5s'),('lw','20ea'),('neud','8'),('ym','o31'),('4nbv','o31'),('xtfl','e');")
tk.MustExec("CREATE TABLE `ba35a09f-76f4-40aa-9b48-13154a24bdd2` (`9b2a7138-14a3-4e8f-b29a-720392aad22c` set('zgn','if8yo','e','k7','bav','xj6','lkag','m5','as','ia','l3') DEFAULT 'zgn,if8yo,e,k7,ia,l3',`a60d6b5c-08bd-4a6d-b951-716162d004a5` set('6li6','05jlu','w','l','m','e9r','5q','d0ol','i6ajr','csf','d32') DEFAULT '6li6,05jlu,w,l,m,d0ol,i6ajr,csf,d32',`fb753d37-6252-4bd3-9bd1-0059640e7861` year(4) DEFAULT '2065', UNIQUE KEY `51816c39-27df-4bbe-a0e7-d6b6f54be2a2` (`fb753d37-6252-4bd3-9bd1-0059640e7861`), KEY `b0dfda0a-ffed-4c5b-9a72-4113bc1cbc8e` (`9b2a7138-14a3-4e8f-b29a-720392aad22c`,`fb753d37-6252-4bd3-9bd1-0059640e7861`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin /*T! SHARD_ROW_ID_BITS=5 */;")
tk.MustExec("insert into `ba35a09f-76f4-40aa-9b48-13154a24bdd2` values ('if8yo', '6li6,05jlu,w,l,m,d0ol,i6ajr,csf,d32', 2065);")
tk.MustExec("CREATE TABLE `07ccc74e-14c3-4685-bb41-c78a069b1a6d` (`8a93bdc5-2214-4f96-b5a7-1ba4c0d396ae` bigint(20) NOT NULL DEFAULT '-4604789462044748682',`30b19ecf-679f-4ca3-813f-d3c3b8f7da7e` date NOT NULL DEFAULT '5030-11-23',`1c52eaf2-1ebb-4486-9410-dfd00c7c835c` decimal(7,5) DEFAULT '-81.91307',`4b09dfdc-e688-41cb-9ffa-d03071a43077` float DEFAULT '1.7989023',PRIMARY KEY (`30b19ecf-679f-4ca3-813f-d3c3b8f7da7e`,`8a93bdc5-2214-4f96-b5a7-1ba4c0d396ae`) /*T![clustered_index] CLUSTERED */,KEY `ae7a7637-ca52-443b-8a3f-69694f730cc4` (`8a93bdc5-2214-4f96-b5a7-1ba4c0d396ae`),KEY `42640042-8a17-4145-9510-5bb419f83ed9` (`8a93bdc5-2214-4f96-b5a7-1ba4c0d396ae`),KEY `839f4f5a-83f3-449b-a7dd-c7d2974d351a` (`30b19ecf-679f-4ca3-813f-d3c3b8f7da7e`),KEY `c474cde1-6fe4-45df-9067-b4e479f84149` (`8a93bdc5-2214-4f96-b5a7-1ba4c0d396ae`),KEY `f834d0a9-709e-4ca8-925d-73f48322b70d` (`8a93bdc5-2214-4f96-b5a7-1ba4c0d396ae`)) ENGINE=InnoDB DEFAULT CHARSET=gbk COLLATE=gbk_chinese_ci;")
tk.MustExec("set sql_mode=``;")
tk.MustExec("INSERT INTO `07ccc74e-14c3-4685-bb41-c78a069b1a6d` VALUES (616295989348159438,'0000-00-00',1.00000,1.7989023),(2215857492573998768,'1970-02-02',0.00000,1.7989023),(2215857492573998768,'1983-05-13',0.00000,1.7989023),(-2840083604831267906,'1984-01-30',1.00000,1.7989023),(599388718360890339,'1986-09-09',1.00000,1.7989023),(3506764933630033073,'1987-11-22',1.00000,1.7989023),(3506764933630033073,'2002-02-26',1.00000,1.7989023),(3506764933630033073,'2003-05-14',1.00000,1.7989023),(3506764933630033073,'2007-05-16',1.00000,1.7989023),(3506764933630033073,'2017-02-20',1.00000,1.7989023),(3506764933630033073,'2017-08-06',1.00000,1.7989023),(2215857492573998768,'2019-02-18',1.00000,1.7989023),(3506764933630033073,'2020-08-11',1.00000,1.7989023),(3506764933630033073,'2028-06-07',1.00000,1.7989023),(3506764933630033073,'2036-08-16',1.00000,1.7989023);")
tk.MustQuery("select /*+ use_index_merge( `4f380f26-9af6-4df8-959d-ad6296eff914` ) */ /*+ stream_agg() */ approx_percentile( `4f380f26-9af6-4df8-959d-ad6296eff914`.`f7a9a4be-3728-449b-a5ea-df9b957eec67` , 77 ) as r0 , `4f380f26-9af6-4df8-959d-ad6296eff914`.`f7a9a4be-3728-449b-a5ea-df9b957eec67` as r1 from `4f380f26-9af6-4df8-959d-ad6296eff914` where not( IsNull( `4f380f26-9af6-4df8-959d-ad6296eff914`.`f7a9a4be-3728-449b-a5ea-df9b957eec67` ) ) and not( `4f380f26-9af6-4df8-959d-ad6296eff914`.`f7a9a4be-3728-449b-a5ea-df9b957eec67` in ( select `8a93bdc5-2214-4f96-b5a7-1ba4c0d396ae` from `07ccc74e-14c3-4685-bb41-c78a069b1a6d` where `4f380f26-9af6-4df8-959d-ad6296eff914`.`f7a9a4be-3728-449b-a5ea-df9b957eec67` in ( select `a60d6b5c-08bd-4a6d-b951-716162d004a5` from `ba35a09f-76f4-40aa-9b48-13154a24bdd2` where not( `4f380f26-9af6-4df8-959d-ad6296eff914`.`f7a9a4be-3728-449b-a5ea-df9b957eec67` between 'bpkfo' and '59' ) and not( `4f380f26-9af6-4df8-959d-ad6296eff914`.`f7a9a4be-3728-449b-a5ea-df9b957eec67` in ( select `fb753d37-6252-4bd3-9bd1-0059640e7861` from `ba35a09f-76f4-40aa-9b48-13154a24bdd2` where IsNull( `4f380f26-9af6-4df8-959d-ad6296eff914`.`f7a9a4be-3728-449b-a5ea-df9b957eec67` ) or not( `4f380f26-9af6-4df8-959d-ad6296eff914`.`43ca0135-1650-429b-8887-9eabcae2a234` in ( select `8a93bdc5-2214-4f96-b5a7-1ba4c0d396ae` from `07ccc74e-14c3-4685-bb41-c78a069b1a6d` where IsNull( `4f380f26-9af6-4df8-959d-ad6296eff914`.`43ca0135-1650-429b-8887-9eabcae2a234` ) and not( `4f380f26-9af6-4df8-959d-ad6296eff914`.`f7a9a4be-3728-449b-a5ea-df9b957eec67` between 'neud' and 'bpkfo' ) ) ) ) ) ) ) ) group by `4f380f26-9af6-4df8-959d-ad6296eff914`.`f7a9a4be-3728-449b-a5ea-df9b957eec67`;")
}
func TestIssue38756(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t (c1 int)")
tk.MustExec("insert into t values (1), (2), (3)")
tk.MustQuery("SELECT SQRT(1) FROM t").Check(testkit.Rows("1", "1", "1"))
tk.MustQuery("(SELECT DISTINCT SQRT(1) FROM t)").Check(testkit.Rows("1"))
tk.MustQuery("SELECT DISTINCT cast(1 as double) FROM t").Check(testkit.Rows("1"))
}
func TestIssue50043(t *testing.T) {
testIssue50043WithInitSQL(t, "")
}
func TestIssue50043WithPipelinedDML(t *testing.T) {
testIssue50043WithInitSQL(t, "set @@tidb_dml_type=bulk")
}
func testIssue50043WithInitSQL(t *testing.T, initSQL string) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec(initSQL)
// Test simplified case by update.
tk.MustExec("use test")
tk.MustExec("create table t (c1 boolean ,c2 decimal ( 37 , 17 ), unique key idx1 (c1 ,c2),unique key idx2 ( c1 ));")
tk.MustExec("insert into t values (0,NULL);")
tk.MustExec("alter table t alter column c2 drop default;")
tk.MustExec("update t set c2 = 5 where c1 = 0;")
tk.MustQuery("select * from t order by c1,c2").Check(testkit.Rows("0 5.00000000000000000"))
// Test simplified case by insert on duplicate key update.
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (c1 boolean ,c2 decimal ( 37 , 17 ), unique key idx1 (c1 ,c2));")
tk.MustExec("alter table t alter column c2 drop default;")
tk.MustExec("alter table t add unique key idx4 ( c1 );")
tk.MustExec("insert into t values (0, NULL), (1, 1);")
tk.MustExec("insert into t values (0, 2) ,(1, 3) on duplicate key update c2 = 5;")
tk.MustQuery("show warnings").Check(testkit.Rows())
tk.MustQuery("select * from t order by c1,c2").Check(testkit.Rows("0 5.00000000000000000", "1 5.00000000000000000"))
// Test Issue 50043.
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (c1 boolean ,c2 decimal ( 37 , 17 ), unique key idx1 (c1 ,c2));")
tk.MustExec("alter table t alter column c2 drop default;")
tk.MustExec("alter table t add unique key idx4 ( c1 );")
tk.MustExec("insert into t values (0, NULL), (1, 1);")
tk.MustExec("insert ignore into t values (0, 2) ,(1, 3) on duplicate key update c2 = 5, c1 = 0")
tk.MustQuery("select * from t order by c1,c2").Check(testkit.Rows("0 5.00000000000000000", "1 1.00000000000000000"))
}
func TestIssue51324(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t (id int key, a int, b enum('a', 'b'))")
tk.MustGetErrMsg("insert into t values ()", "[table:1364]Field 'id' doesn't have a default value")
tk.MustExec("insert into t set id = 1")
tk.MustExec("insert into t set id = 2, a = NULL, b = NULL")
tk.MustExec("insert into t set id = 3, a = DEFAULT, b = DEFAULT")
tk.MustQuery("select * from t order by id").Check(testkit.Rows("1 <nil> <nil>", "2 <nil> <nil>", "3 <nil> <nil>"))
tk.MustExec("alter table t alter column a drop default")
tk.MustExec("alter table t alter column b drop default")
tk.MustGetErrMsg("insert into t set id = 4;", "[table:1364]Field 'a' doesn't have a default value")
tk.MustExec("insert into t set id = 5, a = NULL, b = NULL;")
tk.MustGetErrMsg("insert into t set id = 6, a = DEFAULT, b = DEFAULT;", "[table:1364]Field 'a' doesn't have a default value")
tk.MustQuery("select * from t order by id").Check(testkit.Rows("1 <nil> <nil>", "2 <nil> <nil>", "3 <nil> <nil>", "5 <nil> <nil>"))
tk.MustExec("insert ignore into t set id = 4;")
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1364 Field 'a' doesn't have a default value"))
tk.MustExec("insert ignore into t set id = 6, a = DEFAULT, b = DEFAULT;")
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1364 Field 'a' doesn't have a default value"))
tk.MustQuery("select * from t order by id").Check(testkit.Rows("1 <nil> <nil>", "2 <nil> <nil>", "3 <nil> <nil>", "4 <nil> <nil>", "5 <nil> <nil>", "6 <nil> <nil>"))
tk.MustExec("update t set id = id + 10")
tk.MustQuery("show warnings").Check(testkit.Rows())
tk.MustQuery("select * from t order by id").Check(testkit.Rows("11 <nil> <nil>", "12 <nil> <nil>", "13 <nil> <nil>", "14 <nil> <nil>", "15 <nil> <nil>", "16 <nil> <nil>"))
// Test not null case.
tk.MustExec("drop table t")
tk.MustExec("create table t (id int key, a int not null, b enum('a', 'b') not null)")
tk.MustGetErrMsg("insert into t values ()", "[table:1364]Field 'id' doesn't have a default value")
tk.MustGetErrMsg("insert into t set id = 1", "[table:1364]Field 'a' doesn't have a default value")
tk.MustGetErrMsg("insert into t set id = 2, a = NULL, b = NULL", "[table:1048]Column 'a' cannot be null")
tk.MustGetErrMsg("insert into t set id = 2, a = 2, b = NULL", "[table:1048]Column 'b' cannot be null")
tk.MustGetErrMsg("insert into t set id = 3, a = DEFAULT, b = DEFAULT", "[table:1364]Field 'a' doesn't have a default value")
tk.MustExec("alter table t alter column a drop default")
tk.MustExec("alter table t alter column b drop default")
tk.MustExec("insert ignore into t set id = 4;")
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1364 Field 'a' doesn't have a default value"))
tk.MustExec("insert ignore into t set id = 5, a = NULL, b = NULL;")
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'a' cannot be null", "Warning 1048 Column 'b' cannot be null"))
tk.MustExec("insert ignore into t set id = 6, a = 6, b = NULL;")
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1048 Column 'b' cannot be null"))
tk.MustExec("insert ignore into t set id = 7, a = DEFAULT, b = DEFAULT;")
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1364 Field 'a' doesn't have a default value"))
tk.MustQuery("select * from t order by id").Check(testkit.Rows("4 0 a", "5 0 ", "6 6 ", "7 0 a"))
// Test add column with OriginDefaultValue case.
tk.MustExec("drop table t")
tk.MustExec("create table t (id int, unique key idx (id))")
tk.MustExec("insert into t values (1)")
tk.MustExec("alter table t add column a int default 1")
tk.MustExec("alter table t add column b int default null")
tk.MustExec("alter table t add column c int not null")
tk.MustExec("alter table t add column d int not null default 1")
tk.MustExec("insert ignore into t (id) values (2)")
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1364 Field 'c' doesn't have a default value"))
tk.MustExec("insert ignore into t (id) values (1),(2) on duplicate key update id = id+10")
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1364 Field 'c' doesn't have a default value"))
tk.MustExec("alter table t alter column a drop default")
tk.MustExec("alter table t alter column b drop default")
tk.MustExec("alter table t alter column c drop default")
tk.MustExec("alter table t alter column d drop default")
tk.MustExec("insert ignore into t (id) values (3)")
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1364 Field 'a' doesn't have a default value", "Warning 1364 Field 'b' doesn't have a default value", "Warning 1364 Field 'c' doesn't have a default value", "Warning 1364 Field 'd' doesn't have a default value"))
tk.MustExec("insert ignore into t (id) values (11),(12),(3) on duplicate key update id = id+10")
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1364 Field 'a' doesn't have a default value", "Warning 1364 Field 'b' doesn't have a default value", "Warning 1364 Field 'c' doesn't have a default value", "Warning 1364 Field 'd' doesn't have a default value"))
tk.MustQuery("select * from t order by id").Check(testkit.Rows("13 <nil> <nil> 0 0", "21 1 <nil> 0 1", "22 1 <nil> 0 1"))
}
func TestDecimalDivPrecisionIncrement(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t (a decimal(3,0), b decimal(3,0))")
tk.MustExec("insert into t values (8, 7), (9, 7)")
tk.MustQuery("select a/b from t").Check(testkit.Rows("1.1429", "1.2857"))
tk.MustExec("set div_precision_increment = 7")
tk.MustQuery("select a/b from t").Check(testkit.Rows("1.1428571", "1.2857143"))
tk.MustExec("set div_precision_increment = 30")
tk.MustQuery("select a/b from t").Check(testkit.Rows("1.142857142857142857142857142857", "1.285714285714285714285714285714"))
tk.MustExec("set div_precision_increment = 4")
tk.MustQuery("select avg(a) from t").Check(testkit.Rows("8.5000"))
tk.MustExec("set div_precision_increment = 4")
tk.MustQuery("select avg(a/b) from t").Check(testkit.Rows("1.21428571"))
tk.MustExec("set div_precision_increment = 10")
tk.MustQuery("select avg(a/b) from t").Check(testkit.Rows("1.21428571428571428550"))
}
func TestIssue48756(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("CREATE TABLE t (id INT, a VARBINARY(20), b BIGINT)")
tk.MustExec(`INSERT INTO t VALUES(1, _binary '2012-05-19 09:06:07', 20120519090607),
(1, _binary '2012-05-19 09:06:07', 20120519090607),
(2, _binary '12012-05-19 09:06:07', 120120519090607),
(2, _binary '12012-05-19 09:06:07', 120120519090607)`)
tk.MustQuery("SELECT SUBTIME(BIT_OR(b), '1 1:1:1.000002') FROM t GROUP BY id").Sort().Check(testkit.Rows(
"2012-05-18 08:05:05.999998",
"<nil>",
))
tk.MustQuery("show warnings").Check(testkit.Rows(
"Warning 1292 Incorrect time value: '120120519090607'",
))
}
func TestIssue50308(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t(a timestamp);")
tk.MustExec("insert ignore into t values(cast('2099-01-01' as date));")
tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning 1292 Incorrect timestamp value: '2099-01-01' for column 'a' at row 1"))
tk.MustQuery("select * from t;").Check(testkit.Rows("0000-00-00 00:00:00"))
tk.MustExec("delete from t")
tk.MustExec("insert into t values('2000-01-01');")
tk.MustGetErrMsg("update t set a=cast('2099-01-01' as date)", "[types:1292]Incorrect timestamp value: '2099-01-01'")
tk.MustExec("update ignore t set a=cast('2099-01-01' as date);")
tk.MustQuery("show warnings").Check(testkit.RowsWithSep("|", "Warning 1292 Incorrect timestamp value: '2099-01-01'"))
tk.MustQuery("select * from t;").Check(testkit.Rows("0000-00-00 00:00:00"))
}
func TestQueryWithKill(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test;")
tk.MustExec("drop table if exists tkq;")
tk.MustExec("create table tkq (a int key, b int, index idx_b(b));")
tk.MustExec("insert into tkq values (1,1);")
var wg sync.WaitGroup
ch := make(chan context.CancelFunc, 1024)
testDuration := time.Second * 10
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test;")
start := time.Now()
for {
ctx, cancel := context.WithCancel(context.Background())
ch <- cancel
rs, err := tk.ExecWithContext(ctx, "select a from tkq where b = 1;")
if err == nil {
require.NotNil(t, rs)
rows, err := session.ResultSetToStringSlice(ctx, tk.Session(), rs)
if err == nil {
require.Equal(t, 1, len(rows))
require.Equal(t, 1, len(rows[0]))
require.Equal(t, "1", fmt.Sprintf("%v", rows[0][0]))
}
}
if err != nil {
require.Equal(t, context.Canceled, err)
}
if rs != nil {
rs.Close()
}
if time.Since(start) > testDuration {
return
}
}
}()
}
wg.Add(1)
go func() {
defer wg.Done()
for {
select {
case cancel := <-ch:
// mock for random kill query
if len(ch) < 5 {
time.Sleep(time.Duration(rand.Intn(1000)) * time.Nanosecond)
}
cancel()
case <-time.After(time.Second):
return
}
}
}()
wg.Wait()
}