Files
tidb/planner/core/integration_test.go

8332 lines
353 KiB
Go

// Copyright 2019 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 core_test
import (
"bytes"
"fmt"
"regexp"
"strconv"
"strings"
"testing"
"time"
"github.com/pingcap/errors"
"github.com/pingcap/failpoint"
"github.com/pingcap/tidb/config"
"github.com/pingcap/tidb/domain"
"github.com/pingcap/tidb/errno"
"github.com/pingcap/tidb/expression"
"github.com/pingcap/tidb/infoschema"
"github.com/pingcap/tidb/parser/auth"
"github.com/pingcap/tidb/parser/model"
"github.com/pingcap/tidb/parser/mysql"
"github.com/pingcap/tidb/parser/terror"
"github.com/pingcap/tidb/planner/core"
"github.com/pingcap/tidb/session"
"github.com/pingcap/tidb/sessionctx/stmtctx"
"github.com/pingcap/tidb/sessionctx/variable"
"github.com/pingcap/tidb/statistics/handle"
"github.com/pingcap/tidb/table"
"github.com/pingcap/tidb/testkit"
"github.com/pingcap/tidb/testkit/testdata"
"github.com/pingcap/tidb/util"
"github.com/stretchr/testify/require"
)
func TestShowSubquery(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 varchar(10), b int, c int)")
tk.MustQuery("show columns from t where true").Check(testkit.Rows(
"a varchar(10) YES <nil> ",
"b int(11) YES <nil> ",
"c int(11) YES <nil> ",
))
tk.MustQuery("show columns from t where field = 'b'").Check(testkit.Rows(
"b int(11) YES <nil> ",
))
tk.MustQuery("show columns from t where field in (select 'b')").Check(testkit.Rows(
"b int(11) YES <nil> ",
))
tk.MustQuery("show columns from t where field in (select 'b') and true").Check(testkit.Rows(
"b int(11) YES <nil> ",
))
tk.MustQuery("show columns from t where field in (select 'b') and false").Check(testkit.Rows())
tk.MustExec("insert into t values('c', 0, 0)")
tk.MustQuery("show columns from t where field < all (select a from t)").Sort().Check(testkit.Rows(
"a varchar(10) YES <nil> ",
"b int(11) YES <nil> ",
))
tk.MustExec("insert into t values('b', 0, 0)")
tk.MustQuery("show columns from t where field < all (select a from t)").Check(testkit.Rows(
"a varchar(10) YES <nil> ",
))
}
func TestJoinOperatorRightAssociative(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, b int)")
tk.MustExec("insert into t values(1,10),(2,20)")
// make sure this join won't rewrite as left-associative join like (t0 join t1) join t2 when explicit parent existed.
// mysql will detect the t0.a is out of it's join parent scope and errors like ERROR 1054 (42S22): Unknown column 't0.a' in 'on clause'
err := tk.ExecToErr("select t1.* from t t0 cross join (t t1 join t t2 on 100=t0.a);")
require.Error(t, err)
require.EqualError(t, err, "[planner:1054]Unknown column 't0.a' in 'on clause'")
}
func TestPpdWithSetVar(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(c1 int, c2 varchar(255))")
tk.MustExec("insert into t values(1,'a'),(2,'d'),(3,'c')")
tk.MustQuery("select t01.c1,t01.c2,t01.c3 from (select t1.*,@c3:=@c3+1 as c3 from (select t.*,@c3:=0 from t order by t.c1)t1)t01 where t01.c3=1 and t01.c2='d'").Check(testkit.Rows())
tk.MustQuery("select t01.c1,t01.c2,t01.c3 from (select t1.*,@c3:=@c3+1 as c3 from (select t.*,@c3:=0 from t order by t.c1)t1)t01 where t01.c3=2 and t01.c2='d'").Check(testkit.Rows("2 d 2"))
}
func TestBitColErrorMessage(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists bit_col_t")
tk.MustExec("create table bit_col_t (a bit(64))")
tk.MustExec("drop table bit_col_t")
tk.MustExec("create table bit_col_t (a bit(1))")
tk.MustExec("drop table bit_col_t")
tk.MustGetErrCode("create table bit_col_t (a bit(0))", mysql.ErrInvalidFieldSize)
tk.MustGetErrCode("create table bit_col_t (a bit(65))", mysql.ErrTooBigDisplaywidth)
}
func TestAggPushDownLeftJoin(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 customer")
tk.MustExec("create table customer (C_CUSTKEY bigint(20) NOT NULL, C_NAME varchar(25) NOT NULL, " +
"C_ADDRESS varchar(25) NOT NULL, PRIMARY KEY (`C_CUSTKEY`) /*T![clustered_index] CLUSTERED */)")
tk.MustExec("drop table if exists orders")
tk.MustExec("create table orders (O_ORDERKEY bigint(20) NOT NULL, O_CUSTKEY bigint(20) NOT NULL, " +
"O_TOTALPRICE decimal(15,2) NOT NULL, PRIMARY KEY (`O_ORDERKEY`) /*T![clustered_index] CLUSTERED */)")
tk.MustExec("insert into customer values (6, \"xiao zhang\", \"address1\");")
tk.MustExec("set @@tidb_opt_agg_push_down=1;")
tk.MustQuery("select c_custkey, count(o_orderkey) as c_count from customer left outer join orders " +
"on c_custkey = o_custkey group by c_custkey").Check(testkit.Rows("6 0"))
tk.MustQuery("explain format='brief' select c_custkey, count(o_orderkey) as c_count from customer left outer join orders " +
"on c_custkey = o_custkey group by c_custkey").Check(testkit.Rows(
"Projection 10000.00 root test.customer.c_custkey, Column#7",
"└─Projection 10000.00 root if(isnull(Column#8), 0, 1)->Column#7, test.customer.c_custkey",
" └─HashJoin 10000.00 root left outer join, equal:[eq(test.customer.c_custkey, test.orders.o_custkey)]",
" ├─HashAgg(Build) 8000.00 root group by:test.orders.o_custkey, funcs:count(Column#9)->Column#8, funcs:firstrow(test.orders.o_custkey)->test.orders.o_custkey",
" │ └─TableReader 8000.00 root data:HashAgg",
" │ └─HashAgg 8000.00 cop[tikv] group by:test.orders.o_custkey, funcs:count(test.orders.o_orderkey)->Column#9",
" │ └─TableFullScan 10000.00 cop[tikv] table:orders keep order:false, stats:pseudo",
" └─TableReader(Probe) 10000.00 root data:TableFullScan",
" └─TableFullScan 10000.00 cop[tikv] table:customer keep order:false, stats:pseudo"))
tk.MustQuery("select c_custkey, count(o_orderkey) as c_count from orders right outer join customer " +
"on c_custkey = o_custkey group by c_custkey").Check(testkit.Rows("6 0"))
tk.MustQuery("explain format='brief' select c_custkey, count(o_orderkey) as c_count from orders right outer join customer " +
"on c_custkey = o_custkey group by c_custkey").Check(testkit.Rows(
"Projection 10000.00 root test.customer.c_custkey, Column#7",
"└─Projection 10000.00 root if(isnull(Column#8), 0, 1)->Column#7, test.customer.c_custkey",
" └─HashJoin 10000.00 root right outer join, equal:[eq(test.orders.o_custkey, test.customer.c_custkey)]",
" ├─HashAgg(Build) 8000.00 root group by:test.orders.o_custkey, funcs:count(Column#9)->Column#8, funcs:firstrow(test.orders.o_custkey)->test.orders.o_custkey",
" │ └─TableReader 8000.00 root data:HashAgg",
" │ └─HashAgg 8000.00 cop[tikv] group by:test.orders.o_custkey, funcs:count(test.orders.o_orderkey)->Column#9",
" │ └─TableFullScan 10000.00 cop[tikv] table:orders keep order:false, stats:pseudo",
" └─TableReader(Probe) 10000.00 root data:TableFullScan",
" └─TableFullScan 10000.00 cop[tikv] table:customer keep order:false, stats:pseudo"))
}
func TestPushLimitDownIndexLookUpReader(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("set tidb_cost_model_version=2")
tk.MustExec("set @@session.tidb_executor_concurrency = 4;")
tk.MustExec("set @@session.tidb_hash_join_concurrency = 5;")
tk.MustExec("set @@session.tidb_distsql_scan_concurrency = 15;")
tk.MustExec("use test")
tk.MustExec("drop table if exists tbl")
tk.MustExec("create table tbl(a int, b int, c int, key idx_b_c(b,c))")
tk.MustExec("insert into tbl values(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5)")
tk.MustExec("analyze table tbl")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestAggColumnPrune(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)")
tk.MustExec("insert into t values(1),(2)")
var input []string
var output []struct {
SQL string
Res []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Res...))
}
}
func TestIsFromUnixtimeNullRejective(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 bigint, b bigint);`)
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestIssue22298(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, b int);`)
tk.MustGetErrMsg(`select * from t where 0 and c = 10;`, "[planner:1054]Unknown column 'c' in 'where clause'")
}
func TestIssue24571(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec(`create view v as select 1 as b;`)
tk.MustExec(`create table t (a int);`)
tk.MustExec(`update v, t set a=2;`)
tk.MustGetErrCode(`update v, t set b=2;`, mysql.ErrNonUpdatableTable)
tk.MustExec("create database db1")
tk.MustExec("use db1")
tk.MustExec("update test.t, (select 1 as a) as t set test.t.a=1;")
// bug in MySQL: ERROR 1288 (HY000): The target table t of the UPDATE is not updatable
tk.MustExec("update (select 1 as a) as t, test.t set test.t.a=1;")
}
func TestBuildUpdateListResolver(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
// For issue https://github.com/pingcap/tidb/issues/24567
tk.MustExec("drop table if exists t")
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t(a int)")
tk.MustExec("create table t1(b int)")
tk.MustGetErrCode("update (select 1 as a) as t set a=1", mysql.ErrNonUpdatableTable)
tk.MustGetErrCode("update (select 1 as a) as t, t1 set a=1", mysql.ErrNonUpdatableTable)
tk.MustExec("drop table if exists t")
tk.MustExec("drop table if exists t1")
// For issue https://github.com/pingcap/tidb/issues/30031
tk.MustExec("create table t(a int default -1, c int as (a+10) stored)")
tk.MustExec("insert into t(a) values(1)")
tk.MustExec("update test.t, (select 1 as b) as t set test.t.a=default")
tk.MustQuery("select * from t").Check(testkit.Rows("-1 9"))
tk.MustExec("drop table if exists t")
}
func TestIssue22828(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 t (c int);`)
tk.MustGetErrMsg(`select group_concat((select concat(c,group_concat(c)) FROM t where xxx=xxx)) FROM t;`, "[planner:1054]Unknown column 'xxx' in 'where clause'")
}
func TestIssue35623(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 view if exists v1;`)
tk.MustExec(`CREATE TABLE t1(c0 INT UNIQUE);`)
tk.MustExec("CREATE definer='root'@'localhost' VIEW v1(c0) AS SELECT 1 FROM t1;")
err := tk.ExecToErr("SELECT v1.c0 FROM v1 WHERE (true)LIKE(v1.c0);")
require.NoError(t, err)
err = tk.ExecToErr("SELECT v2.c0 FROM (select 1 as c0 from t1) v2 WHERE (v2.c0)like(True);")
require.NoError(t, err)
}
func TestIssue37971(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec(`drop table if exists t3;`)
tk.MustExec(`CREATE TABLE t3(c0 INT, primary key(c0));`)
err := tk.ExecToErr("SELECT v2.c0 FROM (select 1 as c0 from t3) v2 WHERE (v2.c0)like(True);")
require.NoError(t, err)
}
func TestJoinNotNullFlag(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1(x int not null)")
tk.MustExec("create table t2(x int)")
tk.MustExec("insert into t2 values (1)")
tk.MustQuery("select IFNULL((select t1.x from t1 where t1.x = t2.x), 'xxx') as col1 from t2").Check(testkit.Rows("xxx"))
tk.MustQuery("select ifnull(t1.x, 'xxx') from t2 left join t1 using(x)").Check(testkit.Rows("xxx"))
tk.MustQuery("select ifnull(t1.x, 'xxx') from t2 natural left join t1").Check(testkit.Rows("xxx"))
}
func TestAntiJoinConstProp(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1(a int not null, b int not null)")
tk.MustExec("insert into t1 values (1,1)")
tk.MustExec("create table t2(a int not null, b int not null)")
tk.MustExec("insert into t2 values (2,2)")
tk.MustQuery("select * from t1 where t1.a not in (select a from t2 where t2.a = t1.a and t2.a > 1)").Check(testkit.Rows(
"1 1",
))
tk.MustQuery("select * from t1 where t1.a not in (select a from t2 where t2.b = t1.b and t2.a > 1)").Check(testkit.Rows(
"1 1",
))
tk.MustQuery("select * from t1 where t1.a not in (select a from t2 where t2.b = t1.b and t2.b > 1)").Check(testkit.Rows(
"1 1",
))
tk.MustQuery("select q.a in (select count(*) from t1 s where not exists (select 1 from t1 p where q.a > 1 and p.a = s.a)) from t1 q").Check(testkit.Rows(
"1",
))
tk.MustQuery("select q.a in (select not exists (select 1 from t1 p where q.a > 1 and p.a = s.a) from t1 s) from t1 q").Check(testkit.Rows(
"1",
))
tk.MustExec("drop table t1, t2")
tk.MustExec("create table t1(a int not null, b int)")
tk.MustExec("insert into t1 values (1,null)")
tk.MustExec("create table t2(a int not null, b int)")
tk.MustExec("insert into t2 values (2,2)")
tk.MustQuery("select * from t1 where t1.a not in (select a from t2 where t2.b > t1.b)").Check(testkit.Rows(
"1 <nil>",
))
tk.MustQuery("select * from t1 where t1.a not in (select a from t2 where t1.a = 2)").Check(testkit.Rows(
"1 <nil>",
))
}
func TestSimplifyOuterJoinWithCast(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("set tidb_cost_model_version=2")
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int not null, b datetime default null)")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestNoneAccessPathsFoundByIsolationRead(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.MustExec("select * from t")
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'")
// Don't filter mysql.SystemDB by isolation read.
tk.MustQuery("explain format = 'brief' select * from mysql.stats_meta").Check(testkit.Rows(
"TableReader 10000.00 root data:TableFullScan",
"└─TableFullScan 10000.00 cop[tikv] table:stats_meta keep order:false, stats:pseudo"))
_, err := tk.Exec("select * from t")
require.EqualError(t, err, "[planner:1815]Internal : No access path for table 't' is found with 'tidb_isolation_read_engines' = 'tiflash', valid values can be 'tikv'. Please check tiflash replica or ensure the query is readonly.")
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash, tikv'")
tk.MustExec("select * from t")
defer config.RestoreFunc()()
config.UpdateGlobal(func(conf *config.Config) {
conf.IsolationRead.Engines = []string{"tiflash"}
})
// Change instance config doesn't affect isolation read.
tk.MustExec("select * from t")
}
func TestSelPushDownTiFlash(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, b varchar(20))")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'")
tk.MustExec("set @@session.tidb_allow_mpp = 0")
tk.MustExec("set tidb_cost_model_version=2")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestVerboseExplain(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(`set tidb_opt_limit_push_down_threshold=0`)
tk.MustExec("drop table if exists t1, t2, t3")
tk.MustExec("create table t1(a int, b int)")
tk.MustExec("create table t2(a int, b int)")
tk.MustExec("create table t3(a int, b int, index c(b))")
tk.MustExec("insert into t1 values(1,2)")
tk.MustExec("insert into t1 values(3,4)")
tk.MustExec("insert into t1 values(5,6)")
tk.MustExec("insert into t2 values(1,2)")
tk.MustExec("insert into t2 values(3,4)")
tk.MustExec("insert into t2 values(5,6)")
tk.MustExec("insert into t3 values(1,2)")
tk.MustExec("insert into t3 values(3,4)")
tk.MustExec("insert into t3 values(5,6)")
tk.MustExec("analyze table t1")
tk.MustExec("analyze table t2")
tk.MustExec("analyze table t3")
// Default RPC encoding may cause statistics explain result differ and then the test unstable.
tk.MustExec("set @@tidb_enable_chunk_rpc = on")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t1" || tblInfo.Name.L == "t2" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestPushDownToTiFlashWithKeepOrder(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, b varchar(20))")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set tidb_cost_model_version=2")
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'")
tk.MustExec("set @@session.tidb_allow_mpp = 0")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestPushDownToTiFlashWithKeepOrderInFastMode(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, b varchar(20))")
tk.MustExec("set @@session.tiflash_fastscan=ON")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set tidb_cost_model_version=2")
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'")
tk.MustExec("set @@session.tidb_allow_mpp = 0")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestMPPJoin(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 d1_t")
tk.MustExec("create table d1_t(d1_k int, value int)")
tk.MustExec("insert into d1_t values(1,2),(2,3)")
tk.MustExec("analyze table d1_t")
tk.MustExec("drop table if exists d2_t")
tk.MustExec("create table d2_t(d2_k decimal(10,2), value int)")
tk.MustExec("insert into d2_t values(10.11,2),(10.12,3)")
tk.MustExec("analyze table d2_t")
tk.MustExec("drop table if exists d3_t")
tk.MustExec("create table d3_t(d3_k date, value int)")
tk.MustExec("insert into d3_t values(date'2010-01-01',2),(date'2010-01-02',3)")
tk.MustExec("analyze table d3_t")
tk.MustExec("drop table if exists fact_t")
tk.MustExec("create table fact_t(d1_k int, d2_k decimal(10,2), d3_k date, col1 int, col2 int, col3 int)")
tk.MustExec("insert into fact_t values(1,10.11,date'2010-01-01',1,2,3),(1,10.11,date'2010-01-02',1,2,3),(1,10.12,date'2010-01-01',1,2,3),(1,10.12,date'2010-01-02',1,2,3)")
tk.MustExec("insert into fact_t values(2,10.11,date'2010-01-01',1,2,3),(2,10.11,date'2010-01-02',1,2,3),(2,10.12,date'2010-01-01',1,2,3),(2,10.12,date'2010-01-02',1,2,3)")
tk.MustExec("analyze table fact_t")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "fact_t" || tblInfo.Name.L == "d1_t" || tblInfo.Name.L == "d2_t" || tblInfo.Name.L == "d3_t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'")
tk.MustExec("set @@session.tidb_allow_mpp = 1")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestMPPLeftSemiJoin(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
// test table
tk.MustExec("use test")
tk.MustExec("create table test.t(a int not null, b int null);")
tk.MustExec("set tidb_allow_mpp=1; set tidb_enforce_mpp=1;")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
var input []string
var output []struct {
SQL string
Plan []string
Warn []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
})
if strings.HasPrefix(tt, "set") || strings.HasPrefix(tt, "UPDATE") {
tk.MustExec(tt)
continue
}
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()))
}
}
func TestMPPOuterJoinBuildSideForBroadcastJoin(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 a")
tk.MustExec("create table a(id int, value int)")
tk.MustExec("insert into a values(1,2),(2,3)")
tk.MustExec("analyze table a")
tk.MustExec("drop table if exists b")
tk.MustExec("create table b(id int, value int)")
tk.MustExec("insert into b values(1,2),(2,3),(3,4)")
tk.MustExec("analyze table b")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "a" || tblInfo.Name.L == "b" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'")
tk.MustExec("set @@session.tidb_opt_mpp_outer_join_fixed_build_side = 0")
tk.MustExec("set @@session.tidb_broadcast_join_threshold_size = 10000")
tk.MustExec("set @@session.tidb_broadcast_join_threshold_count = 10000")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestMPPOuterJoinBuildSideForShuffleJoinWithFixedBuildSide(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 a")
tk.MustExec("create table a(id int, value int)")
tk.MustExec("insert into a values(1,2),(2,3)")
tk.MustExec("analyze table a")
tk.MustExec("drop table if exists b")
tk.MustExec("create table b(id int, value int)")
tk.MustExec("insert into b values(1,2),(2,3),(3,4)")
tk.MustExec("analyze table b")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "a" || tblInfo.Name.L == "b" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'")
tk.MustExec("set @@session.tidb_opt_mpp_outer_join_fixed_build_side = 1")
tk.MustExec("set @@session.tidb_broadcast_join_threshold_size = 0")
tk.MustExec("set @@session.tidb_broadcast_join_threshold_count = 0")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestMPPOuterJoinBuildSideForShuffleJoin(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 a")
tk.MustExec("create table a(id int, value int)")
tk.MustExec("insert into a values(1,2),(2,3)")
tk.MustExec("analyze table a")
tk.MustExec("drop table if exists b")
tk.MustExec("create table b(id int, value int)")
tk.MustExec("insert into b values(1,2),(2,3),(3,4)")
tk.MustExec("analyze table b")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "a" || tblInfo.Name.L == "b" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'")
tk.MustExec("set @@session.tidb_opt_mpp_outer_join_fixed_build_side = 0")
tk.MustExec("set @@session.tidb_broadcast_join_threshold_size = 0")
tk.MustExec("set @@session.tidb_broadcast_join_threshold_count = 0")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestMPPShuffledJoin(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 d1_t")
tk.MustExec("create table d1_t(d1_k int, value int)")
tk.MustExec("insert into d1_t values(1,2),(2,3)")
tk.MustExec("insert into d1_t values(1,2),(2,3)")
tk.MustExec("analyze table d1_t")
tk.MustExec("drop table if exists d2_t")
tk.MustExec("create table d2_t(d2_k decimal(10,2), value int)")
tk.MustExec("insert into d2_t values(10.11,2),(10.12,3)")
tk.MustExec("insert into d2_t values(10.11,2),(10.12,3)")
tk.MustExec("analyze table d2_t")
tk.MustExec("drop table if exists d3_t")
tk.MustExec("create table d3_t(d3_k date, value int)")
tk.MustExec("insert into d3_t values(date'2010-01-01',2),(date'2010-01-02',3)")
tk.MustExec("insert into d3_t values(date'2010-01-01',2),(date'2010-01-02',3)")
tk.MustExec("analyze table d3_t")
tk.MustExec("drop table if exists fact_t")
tk.MustExec("create table fact_t(d1_k int, d2_k decimal(10,2), d3_k date, col1 int, col2 int, col3 int)")
tk.MustExec("insert into fact_t values(1,10.11,date'2010-01-01',1,2,3),(1,10.11,date'2010-01-02',1,2,3),(1,10.12,date'2010-01-01',1,2,3),(1,10.12,date'2010-01-02',1,2,3)")
tk.MustExec("insert into fact_t values(2,10.11,date'2010-01-01',1,2,3),(2,10.11,date'2010-01-02',1,2,3),(2,10.12,date'2010-01-01',1,2,3),(2,10.12,date'2010-01-02',1,2,3)")
tk.MustExec("insert into fact_t values(2,10.11,date'2010-01-01',1,2,3),(2,10.11,date'2010-01-02',1,2,3),(2,10.12,date'2010-01-01',1,2,3),(2,10.12,date'2010-01-02',1,2,3)")
tk.MustExec("insert into fact_t values(2,10.11,date'2010-01-01',1,2,3),(2,10.11,date'2010-01-02',1,2,3),(2,10.12,date'2010-01-01',1,2,3),(2,10.12,date'2010-01-02',1,2,3)")
tk.MustExec("analyze table fact_t")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "fact_t" || tblInfo.Name.L == "d1_t" || tblInfo.Name.L == "d2_t" || tblInfo.Name.L == "d3_t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'")
tk.MustExec("set @@session.tidb_allow_mpp = 1")
tk.MustExec("set @@session.tidb_broadcast_join_threshold_size = 1")
tk.MustExec("set @@session.tidb_broadcast_join_threshold_count = 1")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestMPPJoinWithCanNotFoundColumnInSchemaColumnsError(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 t1")
tk.MustExec("create table t1(id int, v1 decimal(20,2), v2 decimal(20,2))")
tk.MustExec("create table t2(id int, v1 decimal(10,2), v2 decimal(10,2))")
tk.MustExec("create table t3(id int, v1 decimal(10,2), v2 decimal(10,2))")
tk.MustExec("insert into t1 values(1,1,1),(2,2,2)")
tk.MustExec("insert into t2 values(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),(6,6,6),(7,7,7),(8,8,8)")
tk.MustExec("insert into t3 values(1,1,1)")
tk.MustExec("analyze table t1")
tk.MustExec("analyze table t2")
tk.MustExec("analyze table t3")
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t1" || tblInfo.Name.L == "t2" || tblInfo.Name.L == "t3" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'")
tk.MustExec("set @@session.tidb_enforce_mpp = 1")
tk.MustExec("set @@session.tidb_broadcast_join_threshold_size = 0")
tk.MustExec("set @@session.tidb_broadcast_join_threshold_count = 0")
tk.MustExec("set @@session.tidb_opt_mpp_outer_join_fixed_build_side = 0")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestJoinNotSupportedByTiFlash(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists table_1")
tk.MustExec("create table table_1(id int not null, bit_col bit(2) not null, datetime_col datetime not null)")
tk.MustExec("insert into table_1 values(1,b'1','2020-01-01 00:00:00'),(2,b'0','2020-01-01 00:00:00')")
tk.MustExec("analyze table table_1")
tk.MustExec("insert into mysql.expr_pushdown_blacklist values('dayofmonth', 'tiflash', '');")
tk.MustExec("admin reload expr_pushdown_blacklist;")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "table_1" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'")
tk.MustExec("set @@session.tidb_allow_mpp = 1")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
tk.MustExec("set @@session.tidb_broadcast_join_threshold_size = 1")
tk.MustExec("set @@session.tidb_broadcast_join_threshold_count = 1")
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestMPPWithHashExchangeUnderNewCollation(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists table_1")
tk.MustExec("create table table_1(id int not null, value char(10)) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;")
tk.MustExec("insert into table_1 values(1,'1'),(2,'2')")
tk.MustExec("drop table if exists table_2")
tk.MustExec("create table table_2(id int not null, value char(10)) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;")
tk.MustExec("insert into table_2 values(1,'1'),(2,'2')")
tk.MustExec("analyze table table_1")
tk.MustExec("analyze table table_2")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "table_1" || tblInfo.Name.L == "table_2" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'")
tk.MustExec("set @@session.tidb_allow_mpp = 1")
tk.MustExec("set @@session.tidb_broadcast_join_threshold_count = 0")
tk.MustExec("set @@session.tidb_broadcast_join_threshold_size = 0")
tk.MustExec("set @@session.tidb_hash_exchange_with_new_collation = 1")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestMPPWithBroadcastExchangeUnderNewCollation(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists table_1")
tk.MustExec("create table table_1(id int not null, value char(10))")
tk.MustExec("insert into table_1 values(1,'1'),(2,'2')")
tk.MustExec("analyze table table_1")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "table_1" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'")
tk.MustExec("set @@session.tidb_allow_mpp = 1")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestPartitionTableDynamicModeUnderNewCollation(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("create database test_new_collation")
tk.MustExec("use test_new_collation")
tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'")
// hash + range partition
tk.MustExec(`CREATE TABLE thash (a int, c varchar(20) charset utf8mb4 collate utf8mb4_general_ci, key(a)) partition by hash(a) partitions 4`)
tk.MustExec(`CREATE TABLE trange (a int, c varchar(20) charset utf8mb4 collate utf8mb4_general_ci, key(a)) partition by range(a) (
partition p0 values less than (10),
partition p1 values less than (20),
partition p2 values less than (30),
partition p3 values less than (40))`)
tk.MustExec(`insert into thash values (1, 'a'), (1, 'A'), (11, 'a'), (11, 'A'), (21, 'a'), (21, 'A'), (31, 'a'), (31, 'A')`)
tk.MustExec(`insert into trange values (1, 'a'), (1, 'A'), (11, 'a'), (11, 'A'), (21, 'a'), (21, 'A'), (31, 'a'), (31, 'A')`)
tk.MustQuery(`select * from thash use index(a) where a in (1, 11, 31) and c='a'`).Sort().Check(testkit.Rows("1 A", "1 a", "11 A", "11 a", "31 A", "31 a"))
tk.MustQuery(`select * from thash ignore index(a) where a in (1, 11, 31) and c='a'`).Sort().Check(testkit.Rows("1 A", "1 a", "11 A", "11 a", "31 A", "31 a"))
tk.MustQuery(`select * from trange use index(a) where a in (1, 11, 31) and c='a'`).Sort().Check(testkit.Rows("1 A", "1 a", "11 A", "11 a", "31 A", "31 a"))
tk.MustQuery(`select * from trange ignore index(a) where a in (1, 11, 31) and c='a'`).Sort().Check(testkit.Rows("1 A", "1 a", "11 A", "11 a", "31 A", "31 a"))
// range partition and partitioned by utf8mb4_general_ci
tk.MustExec(`create table strrange(a varchar(10) charset utf8mb4 collate utf8mb4_general_ci, b int) partition by range columns(a) (
partition p0 values less than ('a'),
partition p1 values less than ('k'),
partition p2 values less than ('z'))`)
tk.MustExec("insert into strrange values ('a', 1), ('A', 1), ('y', 1), ('Y', 1), ('q', 1)")
tk.MustQuery("select * from strrange where a in ('a', 'y')").Sort().Check(testkit.Rows("A 1", "Y 1", "a 1", "y 1"))
// list partition and partitioned by utf8mb4_general_ci
tk.MustExec(`create table strlist(a varchar(10) charset utf8mb4 collate utf8mb4_general_ci, b int) partition by list columns (a) (
partition p0 values in ('a', 'b'),
partition p1 values in ('c', 'd'),
partition p2 values in ('e', 'f'))`)
tk.MustExec("insert into strlist values ('a', 1), ('A', 1), ('d', 1), ('D', 1), ('e', 1)")
tk.MustQuery(`select * from strlist where a='a'`).Sort().Check(testkit.Rows("A 1", "a 1"))
tk.MustQuery(`select * from strlist where a in ('D', 'e')`).Sort().Check(testkit.Rows("D 1", "d 1", "e 1"))
}
func TestMPPAvgRewrite(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists table_1")
tk.MustExec("create table table_1(id int not null, value decimal(10,2))")
tk.MustExec("insert into table_1 values(1,1),(2,2)")
tk.MustExec("analyze table table_1")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "table_1" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'")
tk.MustExec("set @@session.tidb_allow_mpp = 1")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestAggPushDownEngine(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 primary key, b varchar(20))")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'")
tk.MustQuery("explain format = 'brief' select approx_count_distinct(a) from t").Check(testkit.Rows(
"StreamAgg 1.00 root funcs:approx_count_distinct(Column#5)->Column#3",
"└─TableReader 1.00 root data:StreamAgg",
" └─StreamAgg 1.00 batchCop[tiflash] funcs:approx_count_distinct(test.t.a)->Column#5",
" └─TableFullScan 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo"))
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tikv'")
tk.MustQuery("explain format = 'brief' select approx_count_distinct(a) from t").Check(testkit.Rows(
"HashAgg 1.00 root funcs:approx_count_distinct(test.t.a)->Column#3",
"└─TableReader 10000.00 root data:TableFullScan",
" └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"))
}
func TestIssue15110(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists crm_rd_150m")
tk.MustExec(`CREATE TABLE crm_rd_150m (
product varchar(256) DEFAULT NULL,
uks varchar(16) DEFAULT NULL,
brand varchar(256) DEFAULT NULL,
cin varchar(16) DEFAULT NULL,
created_date timestamp NULL DEFAULT NULL,
quantity int(11) DEFAULT NULL,
amount decimal(11,0) DEFAULT NULL,
pl_date timestamp NULL DEFAULT NULL,
customer_first_date timestamp NULL DEFAULT NULL,
recent_date timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;`)
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "crm_rd_150m" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'")
tk.MustExec("explain format = 'brief' SELECT count(*) FROM crm_rd_150m dataset_48 WHERE (CASE WHEN (month(dataset_48.customer_first_date)) <= 30 THEN '新客' ELSE NULL END) IS NOT NULL;")
}
func TestReadFromStorageHint(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, tt, ttt")
tk.MustExec("set session tidb_allow_mpp=OFF")
tk.MustExec("create table t(a int, b int, index ia(a))")
tk.MustExec("create table tt(a int, b int, primary key(a))")
tk.MustExec("create table ttt(a int, primary key (a desc))")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
var input []string
var output []struct {
SQL string
Plan []string
Warn []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()))
}
}
func TestKeepOrderHint(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, t1, th")
tk.MustExec("drop view if exists v, v1")
tk.MustExec("create table t(a int, b int, primary key(a));")
tk.MustExec("create table t1(a int, b int, index idx_a(a));")
tk.MustExec("create table th (a int, key(a)) partition by hash(a) partitions 4;")
tk.MustExec("create definer='root'@'localhost' view v as select * from t1 where a<10 order by a limit 1;")
tk.MustExec("create definer='root'@'localhost' view v1 as select * from t where a<10 order by a limit 1;")
// If the optimizer can not generate the keep order plan, it will report error
err := tk.ExecToErr("explain select /*+ keep_order(t1, idx_a) */ * from t1 where a<10 limit 1;")
require.EqualError(t, err, "[planner:1815]Internal : Can't find a proper physical plan for this query")
err = tk.ExecToErr("explain select /*+ keep_order(t, primary) */ * from t where a<10 limit 1;")
require.EqualError(t, err, "[planner:1815]Internal : Can't find a proper physical plan for this query")
// The partition table can not keep order
tk.MustExec("analyze table th;")
err = tk.ExecToErr("select a from th where a<1 order by a limit 1;")
require.NoError(t, err)
err = tk.ExecToErr("select /*+ keep_order(th, a) */ a from th where a<1 order by a limit 1;")
require.EqualError(t, err, "[planner:1815]Internal : Can't find a proper physical plan for this query")
var input []string
var output []struct {
SQL string
Plan []string
Warn []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()))
}
}
func TestKeepOrderHintWithBinding(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 t1")
tk.MustExec("create table t1(a int, b int, index idx_a(a));")
// create binding for keep_order hint
tk.MustExec("select * from t1 where a<10 order by a limit 1;")
tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("0"))
tk.MustExec("create global binding for select * from t1 where a<10 order by a limit 1 using select /*+ keep_order(t1, idx_a) */ * from t1 where a<10 order by a limit 1;")
tk.MustExec("select * from t1 where a<10 order by a limit 1;")
tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1"))
res := tk.MustQuery("show global bindings").Rows()
require.Equal(t, res[0][0], "select * from `test` . `t1` where `a` < ? order by `a` limit ?")
require.Equal(t, res[0][1], "SELECT /*+ keep_order(`t1` `idx_a`)*/ * FROM `test`.`t1` WHERE `a` < 10 ORDER BY `a` LIMIT 1")
tk.MustExec("drop global binding for select * from t1 where a<10 order by a limit 1;")
tk.MustExec("select * from t1 where a<10 order by a limit 1;")
tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("0"))
res = tk.MustQuery("show global bindings").Rows()
require.Equal(t, len(res), 0)
// create binding for no_keep_order hint
tk.MustExec("create global binding for select * from t1 where a<10 order by a limit 1 using select /*+ no_keep_order(t1, idx_a) */ * from t1 where a<10 order by a limit 1;")
tk.MustExec("select * from t1 where a<10 order by a limit 1;")
tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1"))
res = tk.MustQuery("show global bindings").Rows()
require.Equal(t, res[0][0], "select * from `test` . `t1` where `a` < ? order by `a` limit ?")
require.Equal(t, res[0][1], "SELECT /*+ no_keep_order(`t1` `idx_a`)*/ * FROM `test`.`t1` WHERE `a` < 10 ORDER BY `a` LIMIT 1")
tk.MustExec("drop global binding for select * from t1 where a<10 order by a limit 1;")
tk.MustExec("select * from t1 where a<10 order by a limit 1;")
tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("0"))
res = tk.MustQuery("show global bindings").Rows()
require.Equal(t, len(res), 0)
}
func TestViewHint(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 view if exists v, v1, v2")
tk.MustExec("drop table if exists t, t1, t2")
tk.MustExec("create table t(a int, b int);")
tk.MustExec("create table t1(a int, b int);")
tk.MustExec("create table t2(a int, b int);")
tk.MustExec("create definer='root'@'localhost' view v as select t.a, t.b from t join (select count(*) as a from t1 join t2 on t1.b=t2.b group by t2.a) tt on t.a = tt.a;")
tk.MustExec("create definer='root'@'localhost' view v1 as select t.a, t.b from t join (select count(*) as a from t1 join v on t1.b=v.b group by v.a) tt on t.a = tt.a;")
tk.MustExec("create definer='root'@'localhost' view v2 as select t.a, t.b from t join (select count(*) as a from t1 join v1 on t1.b=v1.b group by v1.a) tt on t.a = tt.a;")
var input []string
var output []struct {
SQL string
Plan []string
Warn []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()))
}
}
func TestViewHintScope(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 view if exists v, v1, v2, v3, v4")
tk.MustExec("drop table if exists t, t1, t2, t3, t4")
tk.MustExec("create table t(a int, b int);")
tk.MustExec("create table t1(a int, b int);")
tk.MustExec("create table t2(a int, b int);")
tk.MustExec("create table t3(a int, b int)")
tk.MustExec("create table t4(a int, b int, index idx_a(a), index idx_b(b))")
tk.MustExec("create definer='root'@'localhost' view v as select t.a, t.b from t join (select count(*) as a from t1 join t2 join t3 where t1.b=t2.b and t2.a = t3.a group by t2.a) tt on t.a = tt.a;")
tk.MustExec("create definer='root'@'localhost' view v1 as select t.a, t.b from t join (select count(*) as a from t1 join v on t1.b=v.b group by v.a) tt on t.a = tt.a;")
tk.MustExec("create definer='root'@'localhost' view v2 as select t.a, t.b from t join (select count(*) as a from t1 join v1 on t1.b=v1.b group by v1.a) tt on t.a = tt.a;")
tk.MustExec("create definer='root'@'localhost' view v3 as select /*+ merge_join(t) */ t.a, t.b from t join (select /*+ stream_agg() */ count(*) as a from t1 join v1 on t1.b=v1.b group by v1.a) tt on t.a = tt.a;")
tk.MustExec("create definer='root'@'localhost' view v4 as select * from t4 where a > 2 and b > 3;")
var input []string
var output []struct {
SQL string
Plan []string
Warn []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()))
}
}
func TestViewHintWithBinding(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 view if exists v, v1")
tk.MustExec("drop table if exists t, t1, t2, t3")
tk.MustExec("create table t(a int, b int);")
tk.MustExec("create table t1(a int, b int);")
tk.MustExec("create table t2(a int, b int);")
tk.MustExec("create table t3(a int, b int)")
tk.MustExec("create definer='root'@'localhost' view v as select t.a, t.b from t join (select count(*) as a from t1 join t2 join t3 where t1.b=t2.b and t2.a = t3.a group by t2.a) tt on t.a = tt.a;")
tk.MustExec("create definer='root'@'localhost' view v1 as select t.a, t.b from t join (select count(*) as a from t1 join v on t1.b=v.b group by v.a) tt on t.a = tt.a;")
tk.MustExec("create definer='root'@'localhost' view v2 as select t.a, t.b from t join (select count(*) as a from t1 join v1 on t1.b=v1.b group by v1.a) tt on t.a = tt.a;")
tk.MustExec("select * from v2")
tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("0"))
tk.MustExec("create global binding for select * from v2 using select /*+ qb_name(qb_v_2, v2.v1@sel_2 .v@sel_2 .@sel_2), merge_join(t1@qb_v_2), stream_agg(@qb_v_2), qb_name(qb_v_1, v2. v1@sel_2 .v@sel_2 .@sel_1), merge_join(t@qb_v_1) */ * from v2;")
tk.MustExec("select * from v2")
tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1"))
res := tk.MustQuery("show global bindings").Rows()
require.Equal(t, res[0][0], "select * from `test` . `v2`")
require.Equal(t, res[0][1], "SELECT /*+ qb_name(`qb_v_2` , `v2`. `v1`@`sel_2`. `v`@`sel_2`. ``@`sel_2`) merge_join(`t1`@`qb_v_2`) stream_agg(@`qb_v_2`) qb_name(`qb_v_1` , `v2`. `v1`@`sel_2`. `v`@`sel_2`. ``@`sel_1`) merge_join(`t`@`qb_v_1`)*/ * FROM `test`.`v2`")
tk.MustExec("drop global binding for select * from v2")
tk.MustExec("select * from v2")
tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("0"))
res = tk.MustQuery("show global bindings").Rows()
require.Equal(t, len(res), 0)
}
func TestAllViewHintType(t *testing.T) {
store := testkit.CreateMockStore(t, withMockTiFlash(2))
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("set tidb_cost_model_version=2")
tk.MustExec("set @@session.tidb_allow_mpp=ON")
tk.MustExec("set @@session.tidb_isolation_read_engines='tiflash, tikv'")
tk.MustExec("drop view if exists v, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12")
tk.MustExec("drop table if exists t, t1, t2, t4, t3, t5")
tk.MustExec("create table t(a int not null, b int, index idx_a(a));")
tk.MustExec("create table t1(a int not null, b int, index idx_a(a));")
tk.MustExec("create table t2(a int, b int, index idx_a(a));")
tk.MustExec("create table t3(a int, b int, index idx_a(a));")
tk.MustExec("create table t4(a int, b int, index idx_a(a));")
tk.MustExec("create table t5(a int, b int, index idx_a(a), index idx_b(b));")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("create definer='root'@'localhost' view v as select t.a, t.b from t join t1 on t.a = t1.a;")
tk.MustExec("create definer='root'@'localhost' view v1 as select t2.a, t2.b from t2 join t3 join v where t2.b = t3.b and t3.a = v.a;")
tk.MustExec("create definer='root'@'localhost' view v2 as select t.a, t.b from t join (select count(*) as a from t1 join v1 on t1.b=v1.b group by v1.a) tt on t.a = tt.a;")
tk.MustExec("create definer='root'@'localhost' view v3 as select * from t5 where a > 1 and b < 2;")
tk.MustExec("create definer='root'@'localhost' view v4 as select * from t5 where a > 1 or b < 2;")
tk.MustExec("create definer='root'@'localhost' view v5 as SELECT * FROM t WHERE EXISTS (SELECT 1 FROM t1 WHERE t1.b = t.b);")
tk.MustExec("create definer='root'@'localhost' view v6 as select * from t1 where t1.a < (select sum(t2.a) from t2 where t2.b = t1.b);")
tk.MustExec("create definer='root'@'localhost' view v7 as WITH CTE AS (SELECT * FROM t WHERE t.a < 60) SELECT * FROM CTE WHERE CTE.a <18 union select * from cte where cte.b > 1;")
tk.MustExec("create definer='root'@'localhost' view v8 as WITH CTE1 AS (SELECT b FROM t1), CTE2 AS (WITH CTE3 AS (SELECT a FROM t2), CTE4 AS (SELECT a FROM t3) SELECT CTE3.a FROM CTE3, CTE4) SELECT b FROM CTE1, CTE2 union select * from CTE1;")
tk.MustExec("create definer='root'@'localhost' view v9 as select sum(a) from t;")
tk.MustExec("create definer='root'@'localhost' view v10 as SELECT * FROM t WHERE a > 10 ORDER BY b LIMIT 1;")
tk.MustExec("create definer='root'@'localhost' view v11 as select a, sum(b) from t group by a")
tk.MustExec("create definer='root'@'localhost' view v12 as select t.a, t.b from t join t t1 on t.a = t1.a;")
var input []string
var output []struct {
SQL string
Plan []string
Warn []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()))
}
}
func TestReadFromStorageHintAndIsolationRead(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, tt, ttt")
tk.MustExec("create table t(a int, b int, index ia(a))")
tk.MustExec("set @@session.tidb_isolation_read_engines=\"tikv\"")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
var input []string
var output []struct {
SQL string
Plan []string
Warn []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
tk.Session().GetSessionVars().StmtCtx.SetWarnings(nil)
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()))
}
}
func TestIsolationReadTiFlashNotChoosePointGet(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, b int, primary key (a))")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
tk.MustExec("set @@session.tidb_isolation_read_engines=\"tiflash\"")
var input []string
var output []struct {
SQL string
Result []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Result = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Result...))
}
}
func TestIsolationReadTiFlashUseIndexHint(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, index idx(a));")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
tk.MustExec("set @@session.tidb_isolation_read_engines=\"tiflash\"")
var input []string
var output []struct {
SQL string
Plan []string
Warn []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()))
}
}
func TestIsolationReadDoNotFilterSystemDB(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("set @@tidb_isolation_read_engines = \"tiflash\"")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestPartitionTableStats(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
{
tk.MustExec(`set @@tidb_partition_prune_mode='` + string(variable.Static) + `'`)
tk.MustExec("use test")
tk.MustExec(`set tidb_opt_limit_push_down_threshold=0`)
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int, b int)partition by range columns(a)(partition p0 values less than (10), partition p1 values less than(20), partition p2 values less than(30));")
tk.MustExec("insert into t values(21, 1), (22, 2), (23, 3), (24, 4), (15, 5)")
tk.MustExec("analyze table t")
var input []string
var output []struct {
SQL string
Result []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Result = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Result...))
}
}
}
func TestPartitionPruningForInExpr(t *testing.T) {
failpoint.Enable("github.com/pingcap/tidb/planner/core/forceDynamicPrune", `return(true)`)
defer failpoint.Disable("github.com/pingcap/tidb/planner/core/forceDynamicPrune")
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(11) not null, b int) partition by range (a) (partition p0 values less than (4), partition p1 values less than(10), partition p2 values less than maxvalue);")
tk.MustExec("insert into t values (1, 1),(10, 10),(11, 11)")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestPartitionPruningWithDateType(t *testing.T) {
failpoint.Enable("github.com/pingcap/tidb/planner/core/forceDynamicPrune", `return(true)`)
defer failpoint.Disable("github.com/pingcap/tidb/planner/core/forceDynamicPrune")
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 datetime) partition by range columns (a) (partition p1 values less than ('20000101'), partition p2 values less than ('2000-10-01'));")
tk.MustExec("insert into t values ('20000201'), ('19000101');")
// cannot get the statistical information immediately
// tk.MustQuery(`SELECT PARTITION_NAME,TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME = 't';`).Check(testkit.Rows("p1 1", "p2 1"))
str := tk.MustQuery(`desc select * from t where a < '2000-01-01';`).Rows()[0][3].(string)
require.True(t, strings.Contains(str, "partition:p1"))
}
func TestPartitionPruningForEQ(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 datetime, b int) partition by range(weekday(a)) (partition p0 values less than(10), partition p1 values less than (100))")
is := tk.Session().GetInfoSchema().(infoschema.InfoSchema)
tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
require.NoError(t, err)
pt := tbl.(table.PartitionedTable)
query, err := expression.ParseSimpleExprWithTableInfo(tk.Session(), "a = '2020-01-01 00:00:00'", tbl.Meta())
require.NoError(t, err)
dbName := model.NewCIStr(tk.Session().GetSessionVars().CurrentDB)
columns, names, err := expression.ColumnInfos2ColumnsAndNames(tk.Session(), dbName, tbl.Meta().Name, tbl.Meta().Cols(), tbl.Meta())
require.NoError(t, err)
// Even the partition is not monotonous, EQ condition should be prune!
// select * from t where a = '2020-01-01 00:00:00'
res, err := core.PartitionPruning(tk.Session(), pt, []expression.Expression{query}, nil, columns, names)
require.NoError(t, err)
require.Len(t, res, 1)
require.Equal(t, 0, res[0])
}
func TestErrNoDB(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("create user test")
_, err := tk.Exec("grant select on test1111 to test@'%'")
require.Equal(t, core.ErrNoDB, errors.Cause(err))
_, err = tk.Exec("grant select on * to test@'%'")
require.Equal(t, core.ErrNoDB, errors.Cause(err))
_, err = tk.Exec("revoke select on * from test@'%'")
require.Equal(t, core.ErrNoDB, errors.Cause(err))
tk.MustExec("use test")
tk.MustExec("create table test1111 (id int)")
tk.MustExec("grant select on test1111 to test@'%'")
}
func TestMaxMinEliminate(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("set tidb_cost_model_version=2")
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int primary key)")
tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn
tk.MustExec("create table cluster_index_t(a int, b int, c int, primary key (a, b));")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestINLJHintSmallTable(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1(a int not null, b int, key(a))")
tk.MustExec("insert into t1 values(1,1),(2,2)")
tk.MustExec("create table t2(a int not null, b int, key(a))")
tk.MustExec("insert into t2 values(1,1),(2,2),(3,3),(4,4),(5,5)")
tk.MustExec("analyze table t1, t2")
tk.MustExec("explain format = 'brief' select /*+ TIDB_INLJ(t1) */ * from t1 join t2 on t1.a = t2.a")
}
func TestIndexJoinUniqueCompositeIndex(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("set tidb_cost_model_version=2")
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2")
tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeIntOnly
tk.MustExec("create table t1(a int not null, c int not null)")
tk.MustExec("create table t2(a int not null, b int not null, c int not null, primary key(a,b))")
tk.MustExec("insert into t1 values(1,1)")
tk.MustExec("insert into t2 values(1,1,1),(1,2,1)")
tk.MustExec("analyze table t1,t2")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestIndexMerge(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, b int, c int, unique index(a), unique index(b), primary key(c))")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestIndexMergeHint4CNF(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(id int primary key, a int, b int, c int, key(a), key(b), key(c))")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestInvisibleIndex(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
// Optimizer cannot see invisible indexes.
tk.MustExec("create table t(a int, b int, unique index i_a (a) invisible, unique index i_b(b))")
tk.MustExec("insert into t values (1,2)")
// For issue 26217, can't use invisible index after admin check table.
tk.MustExec("admin check table t")
// Optimizer cannot use invisible indexes.
tk.MustQuery("select a from t order by a").Check(testkit.Rows("1"))
require.False(t, tk.MustUseIndex("select a from t order by a", "i_a"))
tk.MustQuery("select a from t where a > 0").Check(testkit.Rows("1"))
require.False(t, tk.MustUseIndex("select a from t where a > 1", "i_a"))
// If use invisible indexes in index hint and sql hint, throw an error.
errStr := "[planner:1176]Key 'i_a' doesn't exist in table 't'"
tk.MustGetErrMsg("select * from t use index(i_a)", errStr)
tk.MustGetErrMsg("select * from t force index(i_a)", errStr)
tk.MustGetErrMsg("select * from t ignore index(i_a)", errStr)
tk.MustQuery("select /*+ USE_INDEX(t, i_a) */ * from t")
require.Len(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings(), 1)
require.EqualError(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings()[0].Err, errStr)
tk.MustQuery("select /*+ IGNORE_INDEX(t, i_a), USE_INDEX(t, i_b) */ a from t order by a")
require.Len(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings(), 1)
require.EqualError(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings()[0].Err, errStr)
tk.MustQuery("select /*+ FORCE_INDEX(t, i_a), USE_INDEX(t, i_b) */ a from t order by a")
require.Len(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings(), 1)
require.EqualError(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings()[0].Err, errStr)
// For issue 15519
inapplicableErrStr := "[planner:1815]force_index(test.aaa) is inapplicable, check whether the table(test.aaa) exists"
tk.MustQuery("select /*+ FORCE_INDEX(aaa) */ * from t")
require.Len(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings(), 1)
require.EqualError(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings()[0].Err, inapplicableErrStr)
tk.MustExec("admin check table t")
tk.MustExec("admin check index t i_a")
}
// for issue #14822 and #38258
func TestIndexJoinTableRange(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1(a int, b int, primary key (a), key idx_t1_b (b))")
tk.MustExec("create table t2(a int, b int, primary key (a), key idx_t1_b (b))")
tk.MustExec("create table t3(a int, b int, c int)")
tk.MustExec("create table t4(a int, b int, c int, primary key (a, b) clustered)")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestTopNByConstFunc(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustQuery("select max(t.col) from (select 'a' as col union all select '' as col) as t").Check(testkit.Rows(
"a",
))
}
func TestSubqueryWithTopN(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("set tidb_cost_model_version=2")
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int, b int)")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestIndexHintWarning(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1(a int, b int, c int, key a(a), key b(b))")
tk.MustExec("create table t2(a int, b int, c int, key a(a), key b(b))")
var input []string
var output []struct {
SQL string
Warnings []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
tk.MustQuery(tt)
warns := tk.Session().GetSessionVars().StmtCtx.GetWarnings()
output[i].Warnings = make([]string, len(warns))
for j := range warns {
output[i].Warnings[j] = warns[j].Err.Error()
}
})
tk.MustQuery(tt)
warns := tk.Session().GetSessionVars().StmtCtx.GetWarnings()
require.Len(t, warns, len(output[i].Warnings))
for j := range warns {
require.Equal(t, stmtctx.WarnLevelWarning, warns[j].Level)
require.EqualError(t, warns[j].Err, output[i].Warnings[j])
}
}
//Test view with index hint should result error
tk.MustExec("drop table if exists t1")
tk.MustExec("drop view if exists v1")
tk.MustExec("CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT, INDEX (c2))")
tk.MustExec("INSERT INTO t1 VALUES (1,1), (2,2), (3,3)")
tk.MustExec("CREATE VIEW v1 AS SELECT c1, c2 FROM t1")
err := tk.ExecToErr("SELECT * FROM v1 USE INDEX (PRIMARY) WHERE c1=2")
require.True(t, terror.ErrorEqual(err, core.ErrKeyDoesNotExist))
}
func TestIssue32672(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)")
for _, agg := range []string{"stream", "hash"} {
rs := tk.MustQuery(fmt.Sprintf("explain format='verbose' select /*+ %v_agg() */ count(*) from t", agg)).Rows()
// cols: id, estRows, estCost, ...
operator := rs[0][0].(string)
cost, err := strconv.ParseFloat(rs[0][2].(string), 64)
require.NoError(t, err)
require.True(t, strings.Contains(strings.ToLower(operator), agg))
require.True(t, cost > 0)
}
}
func TestIssue15546(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t, pt, vt")
tk.MustExec("create table t(a int, b int)")
tk.MustExec("insert into t values(1, 1)")
tk.MustExec("create table pt(a int primary key, b int) partition by range(a) (" +
"PARTITION `p0` VALUES LESS THAN (10), PARTITION `p1` VALUES LESS THAN (20), PARTITION `p2` VALUES LESS THAN (30))")
tk.MustExec("insert into pt values(1, 1), (11, 11), (21, 21)")
tk.MustExec("create definer='root'@'localhost' view vt(a, b) as select a, b from t")
tk.MustQuery("select * from pt, vt where pt.a = vt.a").Check(testkit.Rows("1 1 1 1"))
}
func TestApproxCountDistinctInPartitionTable(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(11), b int) partition by range (a) (partition p0 values less than (3), partition p1 values less than maxvalue);")
tk.MustExec("insert into t values(1, 1), (2, 1), (3, 1), (4, 2), (4, 2)")
tk.MustExec("set session tidb_opt_agg_push_down=1")
tk.MustExec(`set @@tidb_partition_prune_mode='` + string(variable.Static) + `'`)
tk.MustQuery("explain format = 'brief' select approx_count_distinct(a), b from t group by b order by b desc").Check(testkit.Rows("Sort 16000.00 root test.t.b:desc",
"└─HashAgg 16000.00 root group by:test.t.b, funcs:approx_count_distinct(Column#5)->Column#4, funcs:firstrow(Column#6)->test.t.b",
" └─PartitionUnion 16000.00 root ",
" ├─HashAgg 8000.00 root group by:test.t.b, funcs:approx_count_distinct(test.t.a)->Column#5, funcs:firstrow(test.t.b)->Column#6, funcs:firstrow(test.t.b)->test.t.b",
" │ └─TableReader 10000.00 root data:TableFullScan",
" │ └─TableFullScan 10000.00 cop[tikv] table:t, partition:p0 keep order:false, stats:pseudo",
" └─HashAgg 8000.00 root group by:test.t.b, funcs:approx_count_distinct(test.t.a)->Column#5, funcs:firstrow(test.t.b)->Column#6, funcs:firstrow(test.t.b)->test.t.b",
" └─TableReader 10000.00 root data:TableFullScan",
" └─TableFullScan 10000.00 cop[tikv] table:t, partition:p1 keep order:false, stats:pseudo"))
tk.MustQuery("select approx_count_distinct(a), b from t group by b order by b desc").Check(testkit.Rows("1 2", "3 1"))
}
func TestApproxPercentile(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, b int)")
tk.MustExec("insert into t values(1, 1), (2, 1), (3, 2), (4, 2), (5, 2)")
var input []string
var output []struct {
SQL string
Plan []string
Res []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain " + tt).Rows())
output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery("explain " + tt).Check(testkit.Rows(output[i].Plan...))
tk.MustQuery(tt).Check(testkit.Rows(output[i].Res...))
}
}
func TestIssue17813(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists hash_partition_overflow")
tk.MustExec("create table hash_partition_overflow (c0 bigint unsigned) partition by hash(c0) partitions 3")
tk.MustExec("insert into hash_partition_overflow values (9223372036854775808)")
tk.MustQuery("select * from hash_partition_overflow where c0 = 9223372036854775808").Check(testkit.Rows("9223372036854775808"))
tk.MustQuery("select * from hash_partition_overflow where c0 in (1, 9223372036854775808)").Check(testkit.Rows("9223372036854775808"))
}
func TestHintWithRequiredProperty(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("set tidb_cost_model_version=2")
tk.MustExec("set @@session.tidb_executor_concurrency = 4;")
tk.MustExec("set @@session.tidb_hash_join_concurrency = 5;")
tk.MustExec("set @@session.tidb_distsql_scan_concurrency = 15;")
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int primary key, b int, c int, key b(b))")
var input []string
var output []struct {
SQL string
Plan []string
Warnings []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings()
output[i].Warnings = make([]string, len(warnings))
for j, warning := range warnings {
output[i].Warnings[j] = warning.Err.Error()
}
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings()
require.Len(t, warnings, len(output[i].Warnings))
for j, warning := range warnings {
require.EqualError(t, warning.Err, output[i].Warnings[j])
}
}
}
func TestIssue15813(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t0, t1")
tk.MustExec("create table t0(c0 int primary key)")
tk.MustExec("create table t1(c0 int primary key)")
tk.MustExec("CREATE INDEX i0 ON t0(c0)")
tk.MustExec("CREATE INDEX i0 ON t1(c0)")
tk.MustQuery("select /*+ MERGE_JOIN(t0, t1) */ * from t0, t1 where t0.c0 = t1.c0").Check(testkit.Rows())
}
func TestIssue31261(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec(`use test`)
tk.MustExec(`drop table if exists PK_MULTI_COL_5177`)
tk.MustExec(` CREATE TABLE PK_MULTI_COL_5177 (
COL1 binary(10) NOT NULL,
COL2 varbinary(10) NOT NULL,
COL3 smallint(45) NOT NULL,
PRIMARY KEY (COL1(5),COL2,COL3),
UNIQUE KEY UIDXM (COL1(5),COL2),
UNIQUE KEY UIDX (COL2),
KEY IDX3 (COL3),
KEY IDXM (COL3,COL2))`)
tk.MustExec(`insert into PK_MULTI_COL_5177(col1, col2, col3) values(0x00000000000000000000, 0x002B200DF5BA03E59F82, 1)`)
require.Len(t, tk.MustQuery(`select col1, col2 from PK_MULTI_COL_5177 where col1 = 0x00000000000000000000 and col2 in (0x002B200DF5BA03E59F82, 0x002B200DF5BA03E59F82, 0x002B200DF5BA03E59F82)`).Rows(), 1)
require.Len(t, tk.MustQuery(`select col1, col2 from PK_MULTI_COL_5177 where col1 = 0x00000000000000000000 and col2 = 0x002B200DF5BA03E59F82`).Rows(), 1)
}
func TestFullGroupByOrderBy(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, b int)")
tk.MustQuery("select count(a) as b from t group by a order by b").Check(testkit.Rows())
err := tk.ExecToErr("select count(a) as cnt from t group by a order by b")
require.True(t, terror.ErrorEqual(err, core.ErrFieldNotInGroupBy))
}
func TestHintWithoutTableWarning(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1(a int, b int, c int, key a(a))")
tk.MustExec("create table t2(a int, b int, c int, key a(a))")
var input []string
var output []struct {
SQL string
Warnings []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
tk.MustQuery(tt)
warns := tk.Session().GetSessionVars().StmtCtx.GetWarnings()
output[i].Warnings = make([]string, len(warns))
for j := range warns {
output[i].Warnings[j] = warns[j].Err.Error()
}
})
tk.MustQuery(tt)
warns := tk.Session().GetSessionVars().StmtCtx.GetWarnings()
require.Len(t, warns, len(output[i].Warnings))
for j := range warns {
require.Equal(t, stmtctx.WarnLevelWarning, warns[j].Level)
require.EqualError(t, warns[j].Err, output[i].Warnings[j])
}
}
}
func TestIssue15858(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.MustExec("select * from t t1, (select a from t order by a+1) t2 where t1.a = t2.a")
}
func TestIssue15846(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t0, t1")
tk.MustExec("CREATE TABLE t0(t0 INT UNIQUE);")
tk.MustExec("CREATE TABLE t1(c0 FLOAT);")
tk.MustExec("INSERT INTO t1(c0) VALUES (0);")
tk.MustExec("INSERT INTO t0(t0) VALUES (NULL), (NULL);")
tk.MustQuery("SELECT t1.c0 FROM t1 LEFT JOIN t0 ON 1;").Check(testkit.Rows("0", "0"))
tk.MustExec("drop table if exists t0, t1")
tk.MustExec("CREATE TABLE t0(t0 INT);")
tk.MustExec("CREATE TABLE t1(c0 FLOAT);")
tk.MustExec("INSERT INTO t1(c0) VALUES (0);")
tk.MustExec("INSERT INTO t0(t0) VALUES (NULL), (NULL);")
tk.MustQuery("SELECT t1.c0 FROM t1 LEFT JOIN t0 ON 1;").Check(testkit.Rows("0", "0"))
tk.MustExec("drop table if exists t0, t1")
tk.MustExec("CREATE TABLE t0(t0 INT);")
tk.MustExec("CREATE TABLE t1(c0 FLOAT);")
tk.MustExec("create unique index idx on t0(t0);")
tk.MustExec("INSERT INTO t1(c0) VALUES (0);")
tk.MustExec("INSERT INTO t0(t0) VALUES (NULL), (NULL);")
tk.MustQuery("SELECT t1.c0 FROM t1 LEFT JOIN t0 ON 1;").Check(testkit.Rows("0", "0"))
}
func TestFloorUnixTimestampPruning(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists floor_unix_timestamp")
tk.MustExec(`create table floor_unix_timestamp (ts timestamp(3))
partition by range (floor(unix_timestamp(ts))) (
partition p0 values less than (unix_timestamp('2020-04-05 00:00:00')),
partition p1 values less than (unix_timestamp('2020-04-12 00:00:00')),
partition p2 values less than (unix_timestamp('2020-04-15 00:00:00')))`)
tk.MustExec("insert into floor_unix_timestamp values ('2020-04-04 00:00:00')")
tk.MustExec("insert into floor_unix_timestamp values ('2020-04-04 23:59:59.999')")
tk.MustExec("insert into floor_unix_timestamp values ('2020-04-05 00:00:00')")
tk.MustExec("insert into floor_unix_timestamp values ('2020-04-05 00:00:00.001')")
tk.MustExec("insert into floor_unix_timestamp values ('2020-04-12 01:02:03.456')")
tk.MustExec("insert into floor_unix_timestamp values ('2020-04-14 00:00:42')")
tk.MustQuery("select count(*) from floor_unix_timestamp where '2020-04-05 00:00:00.001' = ts").Check(testkit.Rows("1"))
tk.MustQuery("select * from floor_unix_timestamp where ts > '2020-04-05 00:00:00' order by ts").Check(testkit.Rows("2020-04-05 00:00:00.001", "2020-04-12 01:02:03.456", "2020-04-14 00:00:42.000"))
tk.MustQuery("select count(*) from floor_unix_timestamp where ts <= '2020-04-05 23:00:00'").Check(testkit.Rows("4"))
tk.MustQuery("select * from floor_unix_timestamp partition(p1, p2) where ts > '2020-04-14 00:00:00'").Check(testkit.Rows("2020-04-14 00:00:42.000"))
}
func TestIssue16290And16292(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, b int, primary key(a));")
tk.MustExec("insert into t values(1, 1);")
for i := 0; i <= 1; i++ {
tk.MustExec(fmt.Sprintf("set session tidb_opt_agg_push_down = %v", i))
tk.MustQuery("select avg(a) from (select * from t ta union all select * from t tb) t;").Check(testkit.Rows("1.0000"))
tk.MustQuery("select avg(b) from (select * from t ta union all select * from t tb) t;").Check(testkit.Rows("1.0000"))
tk.MustQuery("select count(distinct a) from (select * from t ta union all select * from t tb) t;").Check(testkit.Rows("1"))
tk.MustQuery("select count(distinct b) from (select * from t ta union all select * from t tb) t;").Check(testkit.Rows("1"))
}
}
func TestTableDualWithRequiredProperty(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2;")
tk.MustExec("create table t1 (a int, b int) partition by range(a) " +
"(partition p0 values less than(10), partition p1 values less than MAXVALUE)")
tk.MustExec("create table t2 (a int, b int)")
tk.MustExec("select /*+ MERGE_JOIN(t1, t2) */ * from t1 partition (p0), t2 where t1.a > 100 and t1.a = t2.a")
}
func TestIndexJoinInnerIndexNDV(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 t1, t2")
tk.MustExec("create table t1(a int not null, b int not null, c int not null)")
tk.MustExec("create table t2(a int not null, b int not null, c int not null, index idx1(a,b), index idx2(c))")
tk.MustExec("insert into t1 values(1,1,1),(1,1,1),(1,1,1)")
tk.MustExec("insert into t2 values(1,1,1),(1,1,2),(1,1,3)")
tk.MustExec("analyze table t1, t2")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestIssue16837(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,b int,c int,d int,e int,unique key idx_ab(a,b),unique key(c),unique key(d))")
tk.MustQuery("explain format = 'brief' select /*+ use_index_merge(t,c,idx_ab) */ * from t where a = 1 or (e = 1 and c = 1)").Check(testkit.Rows(
"IndexMerge 0.01 root type: union",
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_ab(a, b) range:[1,1], keep order:false, stats:pseudo",
"├─IndexRangeScan(Build) 1.00 cop[tikv] table:t, index:c(c) range:[1,1], keep order:false, stats:pseudo",
"└─Selection(Probe) 0.01 cop[tikv] or(eq(test.t.a, 1), and(eq(test.t.e, 1), eq(test.t.c, 1)))",
" └─TableRowIDScan 11.00 cop[tikv] table:t keep order:false, stats:pseudo"))
tk.MustQuery("show warnings").Check(testkit.Rows())
tk.MustExec("insert into t values (2, 1, 1, 1, 2)")
tk.MustQuery("select /*+ use_index_merge(t,c,idx_ab) */ * from t where a = 1 or (e = 1 and c = 1)").Check(testkit.Rows())
}
func TestIndexMergeSerial(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, b int, unique key(a), unique key(b))")
tk.MustExec("insert into t value (1, 5), (2, 4), (3, 3), (4, 2), (5, 1)")
tk.MustExec("insert into t value (6, 0), (7, -1), (8, -2), (9, -3), (10, -4)")
tk.MustExec("analyze table t")
var input []string
var output []struct {
SQL string
Plan []string
Warnings []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
output[i].Warnings = testdata.ConvertRowsToStrings(tk.MustQuery("show warnings").Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
tk.MustQuery("show warnings").Check(testkit.Rows(output[i].Warnings...))
}
}
func TestIndexMergePartialScansClusteredIndex(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, b int, c int, primary key (a, b) clustered, key idx_c(c));")
tk.MustExec("insert into t values (1, 1, 1), (10, 10, 10), (100, 100, 100);")
const queryTemplate = "select /*+ use_index_merge(t) */ %s from t where %s order by a, b;"
projections := [][]string{{"a"}, {"b"}, {"c"}, {"a", "b"}, {"b", "c"}, {"c", "a"}, {"b", "a", "c"}}
cases := []struct {
condition string
expected []string
}{
{
// 3 table scans
"a < 2 or a < 10 or a > 11", []string{"1", "100"},
},
{
// 3 index scans
"c < 10 or c < 11 or c > 50", []string{"1", "10", "100"},
},
{
// 1 table scan + 1 index scan
"a < 2 or c > 10000", []string{"1"},
},
{
// 2 table scans + 1 index scan
"a < 2 or a > 88 or c > 10000", []string{"1", "100"},
},
{
// 2 table scans + 2 index scans
"a < 2 or (a >= 10 and b >= 10) or c > 100 or c < 1", []string{"1", "10", "100"},
},
{
// 3 table scans + 2 index scans
"a < 2 or (a >= 10 and b >= 10) or (a >= 20 and b < 10) or c > 100 or c < 1", []string{"1", "10", "100"},
},
}
for _, p := range projections {
for _, ca := range cases {
query := fmt.Sprintf(queryTemplate, strings.Join(p, ","), ca.condition)
tk.HasPlan(query, "IndexMerge")
expected := make([]string, 0, len(ca.expected))
for _, datum := range ca.expected {
row := strings.Repeat(datum+" ", len(p))
expected = append(expected, row[:len(row)-1])
}
tk.MustQuery(query).Check(testkit.Rows(expected...))
}
}
}
func TestIndexMergePartialScansTiDBRowID(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, b int, c int, unique key (a, b), key idx_c(c));")
tk.MustExec("insert into t values (1, 1, 1), (10, 10, 10), (100, 100, 100);")
const queryTemplate = "select /*+ use_index_merge(t) */ %s from t where %s order by a;"
projections := [][]string{{"a"}, {"b"}, {"c"}, {"a", "b"}, {"b", "c"}, {"c", "a"}, {"b", "a", "c"}}
cases := []struct {
condition string
expected []string
}{
{
// 3 index scans
"c < 10 or c < 11 or c > 50", []string{"1", "10", "100"},
},
{
// 2 index scans
"c < 10 or a < 2", []string{"1"},
},
{
// 1 table scan + 1 index scan
"_tidb_rowid < 2 or c > 10000", []string{"1"},
},
{
// 2 table scans + 1 index scan
"_tidb_rowid < 2 or _tidb_rowid < 10 or c > 11", []string{"1", "10", "100"},
},
{
// 1 table scans + 3 index scans
"_tidb_rowid < 2 or (a >= 10 and b >= 10) or c > 100 or c < 1", []string{"1", "10", "100"},
},
{
// 1 table scans + 4 index scans
"_tidb_rowid < 2 or (a >= 10 and b >= 10) or (a >= 20 and b < 10) or c > 100 or c < 1", []string{"1", "10", "100"},
},
}
for _, p := range projections {
for _, ca := range cases {
query := fmt.Sprintf(queryTemplate, strings.Join(p, ","), ca.condition)
tk.HasPlan(query, "IndexMerge")
expected := make([]string, 0, len(ca.expected))
for _, datum := range ca.expected {
row := strings.Repeat(datum+" ", len(p))
expected = append(expected, row[:len(row)-1])
}
tk.MustQuery(query).Check(testkit.Rows(expected...))
}
}
}
func TestIndexMergePartialScansPKIsHandle(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, b int, c int, primary key (a), unique key (b), key idx_c(c));")
tk.MustExec("insert into t values (1, 1, 1), (10, 10, 10), (100, 100, 100);")
const queryTemplate = "select /*+ use_index_merge(t) */ %s from t where %s order by b;"
projections := [][]string{{"a"}, {"b"}, {"c"}, {"a", "b"}, {"b", "c"}, {"c", "a"}, {"b", "a", "c"}}
cases := []struct {
condition string
expected []string
}{
{
// 3 index scans
"b < 10 or c < 11 or c > 50", []string{"1", "10", "100"},
},
{
// 1 table scan + 1 index scan
"a < 2 or c > 10000", []string{"1"},
},
{
// 2 table scans + 1 index scan
"a < 2 or a < 10 or b > 11", []string{"1", "100"},
},
{
// 1 table scans + 3 index scans
"a < 2 or b >= 10 or c > 100 or c < 1", []string{"1", "10", "100"},
},
{
// 3 table scans + 2 index scans
"a < 2 or a >= 10 or a >= 20 or c > 100 or b < 1", []string{"1", "10", "100"},
},
}
for _, p := range projections {
for _, ca := range cases {
query := fmt.Sprintf(queryTemplate, strings.Join(p, ","), ca.condition)
tk.HasPlan(query, "IndexMerge")
expected := make([]string, 0, len(ca.expected))
for _, datum := range ca.expected {
row := strings.Repeat(datum+" ", len(p))
expected = append(expected, row[:len(row)-1])
}
tk.MustQuery(query).Check(testkit.Rows(expected...))
}
}
}
func TestIssue23919(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test;")
// Test for the minimal reproducible case.
tk.MustExec("drop table if exists t;")
tk.MustExec("create table t (a int, b int, index(a), index(b)) partition by hash (a) partitions 2;")
tk.MustExec("insert into t values (1, 5);")
tk.MustQuery("select /*+ use_index_merge( t ) */ * from t where a in (3) or b in (5) order by a;").
Check(testkit.Rows("1 5"))
// Test for the original case.
tk.MustExec("drop table if exists t;")
tk.MustExec(`CREATE TABLE t (
col_5 text NOT NULL,
col_6 tinyint(3) unsigned DEFAULT NULL,
col_7 float DEFAULT '4779.165058537128',
col_8 smallint(6) NOT NULL DEFAULT '-24790',
col_9 date DEFAULT '2031-01-15',
col_37 int(11) DEFAULT '1350204687',
PRIMARY KEY (col_5(6),col_8) /*T![clustered_index] NONCLUSTERED */,
UNIQUE KEY idx_6 (col_9,col_7,col_8),
KEY idx_8 (col_8,col_6,col_5(6),col_9,col_7),
KEY idx_9 (col_9,col_7,col_8)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
PARTITION BY RANGE ( col_8 ) (
PARTITION p0 VALUES LESS THAN (-17650),
PARTITION p1 VALUES LESS THAN (-13033),
PARTITION p2 VALUES LESS THAN (2521),
PARTITION p3 VALUES LESS THAN (7510)
);`)
tk.MustExec("insert into t values ('', NULL, 6304.0146, -24790, '2031-01-15', 1350204687);")
tk.MustQuery("select var_samp(col_7) aggCol from (select /*+ use_index_merge( t ) */ * from t where " +
"t.col_9 in ( '2002-06-22' ) or t.col_5 in ( 'PkfzI' ) or t.col_8 in ( -24874 ) and t.col_6 > null and " +
"t.col_5 > 'r' and t.col_9 in ( '1979-09-04' ) and t.col_7 < 8143.667552769195 or " +
"t.col_5 in ( 'iZhfEjRWci' , 'T' , '' ) or t.col_9 <> '1976-09-11' and t.col_7 = 8796.436181615773 and " +
"t.col_8 = 7372 order by col_5,col_8 ) ordered_tbl group by col_6;").Check(testkit.Rows("<nil>"))
}
func TestIssue16407(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,b char(100),key(a),key(b(10)))")
tk.MustQuery("explain format = 'brief' select /*+ use_index_merge(t) */ * from t where a=10 or b='x'").Check(testkit.Rows(
"IndexMerge 0.04 root type: union",
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:a(a) range:[10,10], keep order:false, stats:pseudo",
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:b(b) range:[\"x\",\"x\"], keep order:false, stats:pseudo",
"└─Selection(Probe) 0.04 cop[tikv] or(eq(test.t.a, 10), eq(test.t.b, \"x\"))",
" └─TableRowIDScan 19.99 cop[tikv] table:t keep order:false, stats:pseudo"))
tk.MustQuery("show warnings").Check(testkit.Rows())
tk.MustExec("insert into t values (1, 'xx')")
tk.MustQuery("select /*+ use_index_merge(t) */ * from t where a=10 or b='x'").Check(testkit.Rows())
}
func TestStreamAggProp(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)")
tk.MustExec("insert into t values(1),(1),(2)")
var input []string
var output []struct {
SQL string
Plan []string
Res []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows())
output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...))
tk.MustQuery(tt).Check(testkit.Rows(output[i].Res...))
}
}
func TestOptimizeHintOnPartitionTable(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, b int, c varchar(20),
primary key(a), key(b), key(c)
) partition by range columns(a) (
partition p0 values less than(6),
partition p1 values less than(11),
partition p2 values less than(16));`)
tk.MustExec(`insert into t values (1,1,"1"), (2,2,"2"), (8,8,"8"), (11,11,"11"), (15,15,"15")`)
tk.MustExec("set @@tidb_enable_index_merge = off")
defer func() {
tk.MustExec("set @@tidb_enable_index_merge = on")
}()
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec(`set @@tidb_partition_prune_mode='` + string(variable.Static) + `'`)
var input []string
var output []struct {
SQL string
Plan []string
Warn []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows())
output[i].Warn = testdata.ConvertRowsToStrings(tk.MustQuery("show warnings").Rows())
})
tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...))
tk.MustQuery("show warnings").Check(testkit.Rows(output[i].Warn...))
}
}
func TestNotReadOnlySQLOnTiFlash(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, b varchar(20))")
tk.MustExec(`set @@tidb_isolation_read_engines = "tiflash"`)
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
err := tk.ExecToErr("select * from t for update")
require.EqualError(t, err, `[planner:1815]Internal : No access path for table 't' is found with 'tidb_isolation_read_engines' = 'tiflash', valid values can be 'tiflash, tikv'. Please check tiflash replica or ensure the query is readonly.`)
err = tk.ExecToErr("insert into t select * from t")
require.EqualError(t, err, `[planner:1815]Internal : No access path for table 't' is found with 'tidb_isolation_read_engines' = 'tiflash', valid values can be 'tiflash, tikv'. Please check tiflash replica or ensure the query is readonly.`)
tk.MustExec("prepare stmt_insert from 'insert into t select * from t where t.a = ?'")
tk.MustExec("set @a=1")
err = tk.ExecToErr("execute stmt_insert using @a")
require.EqualError(t, err, `[planner:1815]Internal : No access path for table 't' is found with 'tidb_isolation_read_engines' = 'tiflash', valid values can be 'tiflash, tikv'. Please check tiflash replica or ensure the query is readonly.`)
}
func TestSelectLimit(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)")
tk.MustExec("insert into t values(1),(1),(2)")
// normal test
tk.MustExec("set @@session.sql_select_limit=1")
result := tk.MustQuery("select * from t order by a")
require.Len(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings(), 0)
result.Check(testkit.Rows("1"))
result = tk.MustQuery("select * from t order by a limit 2")
result.Check(testkit.Rows("1", "1"))
tk.MustExec("set @@session.sql_select_limit=default")
result = tk.MustQuery("select * from t order by a")
result.Check(testkit.Rows("1", "1", "2"))
// test for subquery
tk.MustExec("set @@session.sql_select_limit=1")
result = tk.MustQuery("select * from (select * from t) s order by a")
result.Check(testkit.Rows("1"))
result = tk.MustQuery("select * from (select * from t limit 2) s order by a") // limit write in subquery, has no effect.
result.Check(testkit.Rows("1"))
result = tk.MustQuery("select (select * from t limit 1) s") // limit write in subquery, has no effect.
result.Check(testkit.Rows("1"))
result = tk.MustQuery("select * from t where t.a in (select * from t) limit 3") // select_limit will not effect subquery
result.Sort().Check(testkit.Rows("1", "1", "2"))
result = tk.MustQuery("select * from (select * from t) s limit 3") // select_limit will not effect subquery
result.Sort().Check(testkit.Rows("1", "1", "2"))
// test for union
result = tk.MustQuery("select * from t union all select * from t limit 2") // limit outside subquery
result.Check(testkit.Rows("1", "1"))
result = tk.MustQuery("select * from t union all (select * from t limit 2)") // limit inside subquery
result.Check(testkit.Rows("1"))
// test for prepare & execute
tk.MustExec("prepare s1 from 'select * from t where a = ?'")
tk.MustExec("set @a = 1")
result = tk.MustQuery("execute s1 using @a")
result.Check(testkit.Rows("1"))
tk.MustExec("set @@session.sql_select_limit=default")
result = tk.MustQuery("execute s1 using @a")
result.Check(testkit.Rows("1", "1"))
tk.MustExec("set @@session.sql_select_limit=1")
tk.MustExec("prepare s2 from 'select * from t where a = ? limit 3'")
result = tk.MustQuery("execute s2 using @a") // if prepare stmt has limit, select_limit takes no effect.
result.Check(testkit.Rows("1", "1"))
// test for create view
tk.MustExec("set @@session.sql_select_limit=1")
tk.MustExec("create definer='root'@'localhost' view s as select * from t") // select limit should not effect create view
result = tk.MustQuery("select * from s")
result.Check(testkit.Rows("1"))
tk.MustExec("set @@session.sql_select_limit=default")
result = tk.MustQuery("select * from s")
result.Sort().Check(testkit.Rows("1", "1", "2"))
// test for DML
tk.MustExec("set @@session.sql_select_limit=1")
tk.MustExec("create table b (a int)")
tk.MustExec("insert into b select * from t") // all values are inserted
result = tk.MustQuery("select * from b limit 3")
result.Sort().Check(testkit.Rows("1", "1", "2"))
tk.MustExec("update b set a = 2 where a = 1") // all values are updated
result = tk.MustQuery("select * from b limit 3")
result.Check(testkit.Rows("2", "2", "2"))
result = tk.MustQuery("select * from b")
result.Check(testkit.Rows("2"))
tk.MustExec("delete from b where a = 2") // all values are deleted
result = tk.MustQuery("select * from b")
result.Check(testkit.Rows())
}
func TestHintParserWarnings(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, b int, key(a), key(b));")
tk.MustExec("select /*+ use_index_merge() */ * from t where a = 1 or b = 1;")
rows := tk.MustQuery("show warnings;").Rows()
require.Len(t, rows, 1)
}
func TestIssue16935(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("CREATE TABLE t0(c0 INT);")
tk.MustExec("INSERT INTO t0(c0) VALUES (1), (1), (1), (1), (1), (1);")
tk.MustExec("CREATE definer='root'@'localhost' VIEW v0(c0) AS SELECT NULL FROM t0;")
tk.MustQuery("SELECT * FROM t0 LEFT JOIN v0 ON TRUE WHERE v0.c0 IS NULL;")
}
func TestAccessPathOnClusterIndex(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t1 (a int, b varchar(20), c decimal(40,10), d int, primary key(a,b), key(c))")
tk.MustExec(`insert into t1 values (1,"111",1.1,11), (2,"222",2.2,12), (3,"333",3.3,13)`)
tk.MustExec("analyze table t1")
var input []string
var output []struct {
SQL string
Plan []string
Res []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format='brief' " + tt).Rows())
output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows())
})
tk.MustQuery("explain format='brief' " + tt).Check(testkit.Rows(output[i].Plan...))
tk.MustQuery(tt).Sort().Check(testkit.Rows(output[i].Res...))
}
}
func TestClusterIndexUniqueDoubleRead(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("create database cluster_idx_unique_double_read;")
tk.MustExec("use cluster_idx_unique_double_read;")
defer tk.MustExec("drop database cluster_idx_unique_double_read;")
tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (a varchar(64), b varchar(64), uk int, v int, primary key(a, b), unique key uuk(uk));")
tk.MustExec("insert t values ('a', 'a1', 1, 11), ('b', 'b1', 2, 22), ('c', 'c1', 3, 33);")
tk.MustQuery("select * from t use index (uuk);").Check(testkit.Rows("a a1 1 11", "b b1 2 22", "c c1 3 33"))
}
func TestIndexJoinOnClusteredIndex(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.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t (a int, b varchar(20), c decimal(40,10), d int, primary key(a,b), key(c))")
tk.MustExec(`insert into t values (1,"111",1.1,11), (2,"222",2.2,12), (3,"333",3.3,13)`)
tk.MustExec("analyze table t")
var input []string
var output []struct {
SQL string
Plan []string
Res []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows())
output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery("explain format = 'brief'" + tt).Check(testkit.Rows(output[i].Plan...))
tk.MustQuery(tt).Check(testkit.Rows(output[i].Res...))
}
}
func TestIssue18984(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t, t2")
tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn
tk.MustExec("create table t(a int, b int, c int, primary key(a, b))")
tk.MustExec("create table t2(a int, b int, c int, d int, primary key(a,b), index idx(c))")
tk.MustExec("insert into t values(1,1,1), (2,2,2), (3,3,3)")
tk.MustExec("insert into t2 values(1,2,3,4), (2,4,3,5), (1,3,1,1)")
tk.MustQuery("select /*+ INL_MERGE_JOIN(t) */ * from t right outer join t2 on t.a=t2.c").Check(testkit.Rows(
"1 1 1 1 3 1 1",
"3 3 3 1 2 3 4",
"3 3 3 2 4 3 5"))
tk.MustQuery("select /*+ INL_MERGE_JOIN(t2) */ * from t left outer join t2 on t.a=t2.c").Check(testkit.Rows(
"1 1 1 1 3 1 1",
"2 2 2 <nil> <nil> <nil> <nil>",
"3 3 3 1 2 3 4",
"3 3 3 2 4 3 5"))
}
func TestTimeToSecPushDownToTiFlash(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 time(4))")
tk.MustExec("insert into t values('700:10:10.123456')")
tk.MustExec("insert into t values('20:20:20')")
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
rows := [][]interface{}{
{"TableReader_9", "10000.00", "root", " data:ExchangeSender_8"},
{"└─ExchangeSender_8", "10000.00", "mpp[tiflash]", " ExchangeType: PassThrough"},
{" └─Projection_4", "10000.00", "mpp[tiflash]", " time_to_sec(test.t.a)->Column#3"},
{" └─TableFullScan_7", "10000.00", "mpp[tiflash]", "table:t", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain select time_to_sec(a) from t;").Check(rows)
}
func TestRightShiftPushDownToTiFlash(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, b int)")
tk.MustExec("insert into t values(2147483647, 32)")
tk.MustExec("insert into t values(12, 2)")
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
rows := [][]interface{}{
{"TableReader_9", "root", "data:ExchangeSender_8"},
{"└─ExchangeSender_8", "mpp[tiflash]", "ExchangeType: PassThrough"},
{" └─Projection_4", "mpp[tiflash]", "rightshift(test.t.a, test.t.b)->Column#4"},
{" └─TableFullScan_7", "mpp[tiflash]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain select a >> b from t;").CheckAt([]int{0, 2, 4}, rows)
}
func TestBitColumnPushDown(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("set tidb_cost_model_version=1")
tk.MustExec("create table t1(a bit(8), b int)")
tk.MustExec("create table t2(a bit(8), b int)")
tk.MustExec("insert into t1 values ('1', 1), ('2', 2), ('3', 3), ('4', 4), ('1', 1), ('2', 2), ('3', 3), ('4', 4)")
tk.MustExec("insert into t2 values ('1', 1), ('2', 2), ('3', 3), ('4', 4), ('1', 1), ('2', 2), ('3', 3), ('4', 4)")
sql := "select b from t1 where t1.b > (select min(t2.b) from t2 where t2.a < t1.a)"
tk.MustQuery(sql).Sort().Check(testkit.Rows("2", "2", "3", "3", "4", "4"))
rows := [][]interface{}{
{"Projection_15", "root", "test.t1.b"},
{"└─Apply_17", "root", "CARTESIAN inner join, other cond:gt(test.t1.b, Column#7)"},
{" ├─TableReader_20(Build)", "root", "data:Selection_19"},
{" │ └─Selection_19", "cop[tikv]", "not(isnull(test.t1.b))"},
{" │ └─TableFullScan_18", "cop[tikv]", "keep order:false, stats:pseudo"},
{" └─Selection_21(Probe)", "root", "not(isnull(Column#7))"},
{" └─StreamAgg_23", "root", "funcs:min(test.t2.b)->Column#7"},
{" └─TopN_24", "root", "test.t2.b, offset:0, count:1"},
{" └─TableReader_32", "root", "data:TopN_31"},
{" └─TopN_31", "cop[tikv]", "test.t2.b, offset:0, count:1"},
{" └─Selection_30", "cop[tikv]", "lt(test.t2.a, test.t1.a), not(isnull(test.t2.b))"},
{" └─TableFullScan_29", "cop[tikv]", "keep order:false, stats:pseudo"},
}
tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows)
tk.MustExec("insert t1 values ('A', 1);")
sql = "select a from t1 where ascii(a)=65"
tk.MustQuery(sql).Check(testkit.Rows("A"))
rows = [][]interface{}{
{"TableReader_7", "root", "data:Selection_6"},
{"└─Selection_6", "cop[tikv]", "eq(ascii(cast(test.t1.a, var_string(1))), 65)"},
{" └─TableFullScan_5", "cop[tikv]", "keep order:false, stats:pseudo"},
}
tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = `eq(concat(cast(test.t1.a, var_string(1)), "A"), "AA")`
sql = "select a from t1 where concat(a, 'A')='AA'"
tk.MustQuery(sql).Check(testkit.Rows("A"))
tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = `eq(cast(test.t1.a, binary(1)), "A")`
sql = "select a from t1 where binary a='A'"
tk.MustQuery(sql).Check(testkit.Rows("A"))
tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = `eq(cast(test.t1.a, var_string(1)), "A")`
sql = "select a from t1 where cast(a as char)='A'"
tk.MustQuery(sql).Check(testkit.Rows("A"))
tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows)
tk.MustExec("insert into mysql.expr_pushdown_blacklist values('bit', 'tikv','');")
tk.MustExec("admin reload expr_pushdown_blacklist;")
rows = [][]interface{}{
{"Selection_5", "root", `eq(cast(test.t1.a, var_string(1)), "A")`},
{"└─TableReader_7", "root", "data:TableFullScan_6"},
{" └─TableFullScan_6", "cop[tikv]", "keep order:false, stats:pseudo"},
}
sql = "select a from t1 where cast(a as char)='A'"
tk.MustQuery(sql).Check(testkit.Rows("A"))
tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows)
tk.MustExec("delete from mysql.expr_pushdown_blacklist where name='bit'")
tk.MustExec("admin reload expr_pushdown_blacklist;")
sql = "select a from t1 where ascii(a)=65"
tk.MustQuery(sql).Check(testkit.Rows("A"))
rows = [][]interface{}{
{"TableReader_7", "root", "data:Selection_6"},
{"└─Selection_6", "cop[tikv]", "eq(ascii(cast(test.t1.a, var_string(1))), 65)"},
{" └─TableFullScan_5", "cop[tikv]", "keep order:false, stats:pseudo"},
}
tk.MustQuery(fmt.Sprintf("explain analyze %s", sql)).CheckAt([]int{0, 3, 6}, rows)
// test collation
tk.MustExec("update mysql.tidb set VARIABLE_VALUE='True' where VARIABLE_NAME='new_collation_enabled'")
tk.MustQuery("SELECT VARIABLE_VALUE FROM mysql.tidb WHERE VARIABLE_NAME='new_collation_enabled';").Check(
testkit.Rows("True"))
tk.MustExec("create table t3 (a bit(8));")
tk.MustExec("insert into t3 values (65)")
tk.MustExec("SET NAMES utf8mb4 COLLATE utf8mb4_bin")
tk.MustQuery("select a from t3 where cast(a as char) = 'a'").Check(testkit.Rows())
tk.MustExec("SET NAMES utf8mb4 COLLATE utf8mb4_general_ci")
tk.MustQuery("select a from t3 where cast(a as char) = 'a'").Check(testkit.Rows("A"))
}
func TestSysdatePushDown(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t(id int signed, id2 int unsigned, c varchar(11), d datetime, b double, e bit(10))")
tk.MustExec("insert into t(id, id2, c, d) values (-1, 1, 'abc', '2021-12-12')")
rows := [][]interface{}{
{"TableReader_7", "root", "data:Selection_6"},
{"└─Selection_6", "cop[tikv]", "gt(test.t.d, sysdate())"},
{" └─TableFullScan_5", "cop[tikv]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where d > sysdate()").
CheckAt([]int{0, 3, 6}, rows)
// assert sysdate isn't now after set global tidb_sysdate_is_now in the same session
tk.MustExec("set global tidb_sysdate_is_now='1'")
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where d > sysdate()").
CheckAt([]int{0, 3, 6}, rows)
// assert sysdate is now after set global tidb_sysdate_is_now in the new session
tk = testkit.NewTestKit(t, store)
tk.MustExec("use test")
now := time.Now()
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/expression/injectNow", fmt.Sprintf(`return(%d)`, now.Unix())))
rows[1][2] = fmt.Sprintf("gt(test.t.d, %v)", now.Format("2006-01-02 15:04:05"))
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where d > sysdate()").
CheckAt([]int{0, 3, 6}, rows)
failpoint.Disable("github.com/pingcap/tidb/expression/injectNow")
// assert sysdate isn't now after set session tidb_sysdate_is_now false in the same session
tk.MustExec("set tidb_sysdate_is_now='0'")
rows[1][2] = "gt(test.t.d, sysdate())"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where d > sysdate()").
CheckAt([]int{0, 3, 6}, rows)
}
func TestTimeScalarFunctionPushDownResult(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(col1 datetime, col2 datetime, y int(8), m int(8), d int(8)) CHARSET=utf8 COLLATE=utf8_general_ci;")
tk.MustExec("insert into t values ('2022-03-24 01:02:03.040506', '9999-12-31 23:59:59', 9999, 12, 31);")
testcases := []struct {
sql string
function string
}{
{
sql: "select col1, hour(col1) from t where hour(col1)=hour('2022-03-24 01:02:03.040506');",
function: "hour",
},
{
sql: "select col1, month(col1) from t where month(col1)=month('2022-03-24 01:02:03.040506');",
function: "month",
},
{
sql: "select col1, minute(col1) from t where minute(col1)=minute('2022-03-24 01:02:03.040506');",
function: "minute",
},
{
function: "second",
sql: "select col1, second(col1) from t where second(col1)=second('2022-03-24 01:02:03.040506');",
},
{
function: "microsecond",
sql: "select col1, microsecond(col1) from t where microsecond(col1)=microsecond('2022-03-24 01:02:03.040506');",
},
{
function: "dayName",
sql: "select col1, dayName(col1) from t where dayName(col1)=dayName('2022-03-24 01:02:03.040506');",
},
{
function: "dayOfMonth",
sql: "select col1, dayOfMonth(col1) from t where dayOfMonth(col1)=dayOfMonth('2022-03-24 01:02:03.040506');",
},
{
function: "dayOfWeek",
sql: "select col1, dayOfWeek(col1) from t where dayOfWeek(col1)=dayOfWeek('2022-03-24 01:02:03.040506');",
},
{
function: "dayOfYear",
sql: "select col1, dayOfYear(col1) from t where dayOfYear(col1)=dayOfYear('2022-03-24 01:02:03.040506');",
},
{
function: "Date",
sql: "select col1, Date(col1) from t where Date(col1)=Date('2022-03-24 01:02:03.040506');",
},
{
function: "Week",
sql: "select col1, Week(col1) from t where Week(col1)=Week('2022-03-24 01:02:03.040506');",
},
{
function: "time_to_sec",
sql: "select col1, time_to_sec (col1) from t where time_to_sec(col1)=time_to_sec('2022-03-24 01:02:03.040506');",
},
{
function: "DateDiff",
sql: "select col1, DateDiff(col1, col2) from t where DateDiff(col1, col2)=DateDiff('2022-03-24 01:02:03.040506', '9999-12-31 23:59:59');",
},
{
function: "MonthName",
sql: "select col1, MonthName(col1) from t where MonthName(col1)=MonthName('2022-03-24 01:02:03.040506');",
},
{
function: "MakeDate",
sql: "select col1, MakeDate(9999, 31) from t where MakeDate(y, d)=MakeDate(9999, 31);",
},
{
function: "MakeTime",
sql: "select col1, MakeTime(12, 12, 31) from t where MakeTime(m, m, d)=MakeTime(12, 12, 31);",
},
}
tk.MustExec("delete from mysql.expr_pushdown_blacklist where name != 'date_add'")
tk.MustExec("admin reload expr_pushdown_blacklist;")
for _, testcase := range testcases {
r1 := tk.MustQuery(testcase.sql).Rows()
tk.MustExec(fmt.Sprintf("insert into mysql.expr_pushdown_blacklist(name) values('%s');", testcase.function))
tk.MustExec("admin reload expr_pushdown_blacklist;")
r2 := tk.MustQuery(testcase.sql).Rows()
require.EqualValues(t, r2, r1, testcase.sql)
}
tk.MustExec("delete from mysql.expr_pushdown_blacklist where name != 'date_add'")
tk.MustExec("admin reload expr_pushdown_blacklist;")
}
func TestNumberFunctionPushDown(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t(a int signed, b int unsigned,c double)")
tk.MustExec("insert into t values (-1,61,4.4)")
testcases := []struct {
sql string
function string
}{
{
sql: "select a, mod(a,2) from t where mod(-1,2)=mod(a,2);",
function: "mod",
},
{
sql: "select b, mod(b,2) from t where mod(61,2)=mod(b,2);",
function: "mod",
},
{
sql: "select b,unhex(b) from t where unhex(61) = unhex(b)",
function: "unhex",
},
{
sql: "select b, oct(b) from t where oct(61) = oct(b)",
function: "oct",
},
{
sql: "select c, sin(c) from t where sin(4.4) = sin(c)",
function: "sin",
},
{
sql: "select c, asin(c) from t where asin(4.4) = asin(c)",
function: "asin",
},
{
sql: "select c, cos(c) from t where cos(4.4) = cos(c)",
function: "cos",
},
{
sql: "select c, acos(c) from t where acos(4.4) = acos(c)",
function: "acos",
},
{
sql: "select b,atan(b) from t where atan(61)=atan(b)",
function: "atan",
},
{
sql: "select b, atan2(b, c) from t where atan2(61,4.4)=atan2(b,c)",
function: "atan2",
},
{
sql: "select b,cot(b) from t where cot(61)=cot(b)",
function: "cot",
},
{
sql: "select c from t where pi() < c",
function: "pi",
},
}
for _, testcase := range testcases {
tk.MustExec("delete from mysql.expr_pushdown_blacklist where name != 'date_add'")
tk.MustExec("admin reload expr_pushdown_blacklist;")
r1 := tk.MustQuery(testcase.sql).Rows()
tk.MustExec(fmt.Sprintf("insert into mysql.expr_pushdown_blacklist(name) values('%s');", testcase.function))
tk.MustExec("admin reload expr_pushdown_blacklist;")
r2 := tk.MustQuery(testcase.sql).Rows()
require.EqualValues(t, r2, r1, testcase.sql)
}
}
func TestScalarFunctionPushDown(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t(id int signed, id2 int unsigned, c varchar(11), d datetime, b double, e bit(10))")
tk.MustExec("insert into t(id, id2, c, d) values (-1, 1, '{\"a\":1}', '2021-12-12')")
rows := [][]interface{}{
{"TableReader_7", "root", "data:Selection_6"},
{"└─Selection_6", "cop[tikv]", "right(test.t.c, 1)"},
{" └─TableFullScan_5", "cop[tikv]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where right(c,1);").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "mod(test.t.id, test.t.id)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where mod(id, id);").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "mod(test.t.id, test.t.id2)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where mod(id, id2);").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "mod(test.t.id2, test.t.id)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where mod(id2, id);").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "mod(test.t.id2, test.t.id2)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where mod(id2, id2);").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "sin(cast(test.t.id, double BINARY))"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where sin(id);").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "asin(cast(test.t.id, double BINARY))"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where asin(id);").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "cos(cast(test.t.id, double BINARY))"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where cos(id);").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "acos(cast(test.t.id, double BINARY))"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where acos(id);").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "atan(cast(test.t.id, double BINARY))"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where atan(id);").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "atan2(cast(test.t.id, double BINARY), cast(test.t.id, double BINARY))"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where atan2(id,id);").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "hour(cast(test.t.d, time))"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where hour(d);").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "hour(cast(test.t.d, time))"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where hour(d);").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "minute(cast(test.t.d, time))"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where minute(d);").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "second(cast(test.t.d, time))"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where second(d);").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "month(test.t.d)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where month(d);").
CheckAt([]int{0, 3, 6}, rows)
//rows[1][2] = "dayname(test.t.d)"
//tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where dayname(d);").
// CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "dayofmonth(test.t.d)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where dayofmonth(d);").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "from_days(test.t.id)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where from_days(id);").
CheckAt([]int{0, 3, 6}, rows)
//rows[1][2] = "last_day(test.t.d)"
//tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where last_day(d);").
// CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "gt(4, test.t.id)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where pi() > id;").
CheckAt([]int{0, 3, 6}, rows)
//rows[1][2] = "truncate(test.t.id, 0)"
//tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where truncate(id,0)").
// CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "round(test.t.b)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where round(b)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "date(test.t.d)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where date(d)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "week(test.t.d)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where week(d)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "datediff(test.t.d, test.t.d)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where datediff(d,d)").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "gt(test.t.d, sysdate())"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where d > sysdate()").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "ascii(cast(test.t.e, var_string(2)))"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where ascii(e);").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "eq(json_valid(test.t.c), 1)"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where json_valid(c)=1;").
CheckAt([]int{0, 3, 6}, rows)
rows[1][2] = "json_contains(cast(test.t.c, json BINARY), cast(\"1\", json BINARY))"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where json_contains(c, '1');").
CheckAt([]int{0, 3, 6}, rows)
}
func TestDistinctScalarFunctionPushDown(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 not null, b int not null, c int not null, primary key (a,c)) partition by range (c) (partition p0 values less than (5), partition p1 values less than (10))")
tk.MustExec("insert into t values(1,1,1),(2,2,2),(3,1,3),(7,1,7),(8,2,8),(9,2,9)")
tk.MustQuery("select count(distinct b+1) as col from t").Check(testkit.Rows(
"2",
))
}
func TestReverseUTF8PushDownToTiFlash(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 varchar(256))")
tk.MustExec("insert into t values('pingcap')")
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
rows := [][]interface{}{
{"TableReader_9", "root", "data:ExchangeSender_8"},
{"└─ExchangeSender_8", "mpp[tiflash]", "ExchangeType: PassThrough"},
{" └─Projection_4", "mpp[tiflash]", "reverse(test.t.a)->Column#3"},
{" └─TableFullScan_7", "mpp[tiflash]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain select reverse(a) from t;").CheckAt([]int{0, 2, 4}, rows)
}
func TestReversePushDownToTiFlash(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 binary(32))")
tk.MustExec("insert into t values('pingcap')")
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
rows := [][]interface{}{
{"TableReader_9", "root", "data:ExchangeSender_8"},
{"└─ExchangeSender_8", "mpp[tiflash]", "ExchangeType: PassThrough"},
{" └─Projection_4", "mpp[tiflash]", "reverse(test.t.a)->Column#3"},
{" └─TableFullScan_7", "mpp[tiflash]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain select reverse(a) from t;").CheckAt([]int{0, 2, 4}, rows)
}
func TestSpacePushDownToTiFlash(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)")
tk.MustExec("insert into t values(5)")
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
rows := [][]interface{}{
{"TableReader_9", "root", "data:ExchangeSender_8"},
{"└─ExchangeSender_8", "mpp[tiflash]", "ExchangeType: PassThrough"},
{" └─Projection_4", "mpp[tiflash]", "space(test.t.a)->Column#3"},
{" └─TableFullScan_7", "mpp[tiflash]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain select space(a) from t;").CheckAt([]int{0, 2, 4}, rows)
}
func TestExplainAnalyzePointGet(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, b varchar(20))")
tk.MustExec("insert into t values (1,1)")
res := tk.MustQuery("explain analyze select * from t where a=1;")
checkExplain := func(rpc string) {
resBuff := bytes.NewBufferString("")
for _, row := range res.Rows() {
_, _ = fmt.Fprintf(resBuff, "%s\n", row)
}
explain := resBuff.String()
require.Containsf(t, explain, rpc+":{num_rpc:", "%s", explain)
require.Containsf(t, explain, "total_time:", "%s", explain)
}
checkExplain("Get")
res = tk.MustQuery("explain analyze select * from t where a in (1,2,3);")
checkExplain("BatchGet")
}
func TestExplainAnalyzeDML(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, b int, unique index (a));")
tk.MustExec("insert into t values (1,1)")
res := tk.MustQuery("explain analyze select * from t where a=1;")
checkExplain := func(rpc string) {
resBuff := bytes.NewBufferString("")
for _, row := range res.Rows() {
_, _ = fmt.Fprintf(resBuff, "%s\n", row)
}
explain := resBuff.String()
require.Containsf(t, explain, rpc+":{num_rpc:", "%s", explain)
require.Containsf(t, explain, "total_time:", "%s", explain)
}
checkExplain("Get")
res = tk.MustQuery("explain analyze insert ignore into t values (1,1),(2,2),(3,3),(4,4);")
checkExplain("BatchGet")
}
func TestExplainAnalyzeDML2(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
cases := []struct {
prepare string
sql string
planRegexp string
}{
// Test for alloc auto ID.
{
sql: "insert into t () values ()",
planRegexp: ".*prepare.*total.*, auto_id_allocator.*alloc_cnt: 1, Get.*num_rpc.*total_time.*commit_txn.*prewrite.*get_commit_ts.*commit.*write_keys.*, insert.*",
},
// Test for rebase ID.
{
sql: "insert into t (a) values (99000000000)",
planRegexp: ".*prepare.*total.*, auto_id_allocator.*rebase_cnt: 1, Get.*num_rpc.*total_time.*commit_txn.*prewrite.*get_commit_ts.*commit.*write_keys.*, insert.*",
},
// Test for alloc auto ID and rebase ID.
{
sql: "insert into t (a) values (null), (99000000000)",
planRegexp: ".*prepare.*total.*, auto_id_allocator.*alloc_cnt: 1, rebase_cnt: 1, Get.*num_rpc.*total_time.*commit_txn.*prewrite.*get_commit_ts.*commit.*write_keys.*, insert.*",
},
// Test for insert ignore.
{
sql: "insert ignore into t values (null,1), (2, 2), (99000000000, 3), (100000000000, 4)",
planRegexp: ".*prepare.*total.*, auto_id_allocator.*alloc_cnt: 1, rebase_cnt: 2, Get.*num_rpc.*total_time.*commit_txn.*count: 3, prewrite.*get_commit_ts.*commit.*write_keys.*, check_insert.*",
},
// Test for insert on duplicate.
{
sql: "insert into t values (null,null), (1,1),(2,2) on duplicate key update a = a + 100000000000",
planRegexp: ".*prepare.*total.*, auto_id_allocator.*alloc_cnt: 1, rebase_cnt: 1, Get.*num_rpc.*total_time.*commit_txn.*count: 2, prewrite.*get_commit_ts.*commit.*write_keys.*, check_insert.*",
},
// Test for replace with alloc ID.
{
sql: "replace into t () values ()",
planRegexp: ".*auto_id_allocator.*alloc_cnt: 1, Get.*num_rpc.*total_time.*commit_txn.*prewrite.*get_commit_ts.*commit.*write_keys.*",
},
// Test for replace with alloc ID and rebase ID.
{
sql: "replace into t (a) values (null), (99000000000)",
planRegexp: ".*auto_id_allocator.*alloc_cnt: 1, rebase_cnt: 1, Get.*num_rpc.*total_time.*commit_txn.*prewrite.*get_commit_ts.*commit.*write_keys.*",
},
// Test for update with rebase ID.
{
prepare: "insert into t values (1,1),(2,2)",
sql: "update t set a=a*100000000000",
planRegexp: ".*auto_id_allocator.*rebase_cnt: 2, Get.*num_rpc.*total_time.*commit_txn.*prewrite.*get_commit_ts.*commit.*write_keys.*",
},
}
for _, ca := range cases {
for i := 0; i < 3; i++ {
tk.MustExec("drop table if exists t")
switch i {
case 0:
tk.MustExec("create table t (a bigint auto_increment, b int, primary key (a));")
case 1:
tk.MustExec("create table t (a bigint unsigned auto_increment, b int, primary key (a));")
case 2:
if strings.Contains(ca.sql, "on duplicate key") {
continue
}
tk.MustExec("create table t (a bigint primary key auto_random(5), b int);")
tk.MustExec("set @@allow_auto_random_explicit_insert=1;")
default:
panic("should never happen")
}
if ca.prepare != "" {
tk.MustExec(ca.prepare)
}
res := tk.MustQuery("explain analyze " + ca.sql)
resBuff := bytes.NewBufferString("")
for _, row := range res.Rows() {
_, _ = fmt.Fprintf(resBuff, "%s\t", row)
}
explain := resBuff.String()
require.Regexpf(t, ca.planRegexp, explain, "idx: %v,sql: %v", i, ca.sql)
}
}
// Test for table without auto id.
for _, ca := range cases {
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (a bigint, b int);")
tk.MustExec("insert into t () values ()")
if ca.prepare != "" {
tk.MustExec(ca.prepare)
}
res := tk.MustQuery("explain analyze " + ca.sql)
resBuff := bytes.NewBufferString("")
for _, row := range res.Rows() {
_, _ = fmt.Fprintf(resBuff, "%s\t", row)
}
explain := resBuff.String()
require.NotContainsf(t, explain, "auto_id_allocator", "sql: %v, explain: %v", ca.sql, explain)
}
}
func TestPartitionExplain(t *testing.T) {
failpoint.Enable("github.com/pingcap/tidb/planner/core/forceDynamicPrune", `return(true)`)
defer failpoint.Disable("github.com/pingcap/tidb/planner/core/forceDynamicPrune")
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec(`create table pt (id int, c int, key i_id(id), key i_c(c)) partition by range (c) (
partition p0 values less than (4),
partition p1 values less than (7),
partition p2 values less than (10))`)
tk.MustExec("set @@tidb_enable_index_merge = 1;")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain " + tt).Rows())
})
tk.MustQuery("explain " + tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestPartialBatchPointGet(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 int, c_str varchar(40), primary key(c_int, c_str))")
tk.MustExec("insert into t values (3, 'bose')")
tk.MustQuery("select * from t where c_int in (3)").Check(testkit.Rows(
"3 bose",
))
tk.MustQuery("select * from t where c_int in (3) or c_str in ('yalow') and c_int in (1, 2)").Check(testkit.Rows(
"3 bose",
))
}
func TestIssue19926(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists ta;")
tk.MustExec("drop table if exists tb;")
tk.MustExec("drop table if exists tc;")
tk.MustExec("drop view if exists v;")
tk.MustExec("CREATE TABLE `ta` (\n `id` varchar(36) NOT NULL ,\n `status` varchar(1) NOT NULL \n);")
tk.MustExec("CREATE TABLE `tb` (\n `id` varchar(36) NOT NULL ,\n `status` varchar(1) NOT NULL \n);")
tk.MustExec("CREATE TABLE `tc` (\n `id` varchar(36) NOT NULL ,\n `status` varchar(1) NOT NULL \n);")
tk.MustExec("insert into ta values('1','1');")
tk.MustExec("insert into tb values('1','1');")
tk.MustExec("insert into tc values('1','1');")
tk.MustExec("create definer='root'@'localhost' view v as\nselect \nconcat(`ta`.`status`,`tb`.`status`) AS `status`, \n`ta`.`id` AS `id` from (`ta` join `tb`) \nwhere (`ta`.`id` = `tb`.`id`);")
tk.MustQuery("SELECT tc.status,v.id FROM tc, v WHERE tc.id = v.id AND v.status = '11';").Check(testkit.Rows("1 1"))
}
func TestDeleteUsingJoin(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1(a int primary key, b int)")
tk.MustExec("create table t2(a int primary key, b int)")
tk.MustExec("insert into t1 values(1,1),(2,2)")
tk.MustExec("insert into t2 values(2,2)")
tk.MustExec("delete t1.* from t1 join t2 using (a)")
tk.MustQuery("select * from t1").Check(testkit.Rows("1 1"))
tk.MustQuery("select * from t2").Check(testkit.Rows("2 2"))
}
func Test19942(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.Session().GetSessionVars().EnableClusteredIndex = variable.ClusteredIndexDefModeOn
tk.MustExec("CREATE TABLE test.`t` (" +
" `a` int(11) NOT NULL," +
" `b` varchar(10) COLLATE utf8_general_ci NOT NULL," +
" `c` varchar(50) COLLATE utf8_general_ci NOT NULL," +
" `d` char(10) NOT NULL," +
" PRIMARY KEY (`c`)," +
" UNIQUE KEY `a_uniq` (`a`)," +
" UNIQUE KEY `b_uniq` (`b`)," +
" UNIQUE KEY `d_uniq` (`d`)," +
" KEY `a_idx` (`a`)," +
" KEY `b_idx` (`b`)," +
" KEY `d_idx` (`d`)" +
") ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;")
tk.MustExec("INSERT INTO test.t (a, b, c, d) VALUES (1, '1', '0', '1');")
tk.MustExec("INSERT INTO test.t (a, b, c, d) VALUES (2, ' 2', ' 0', ' 2');")
tk.MustExec("INSERT INTO test.t (a, b, c, d) VALUES (3, ' 3 ', ' 3 ', ' 3 ');")
tk.MustExec("INSERT INTO test.t (a, b, c, d) VALUES (4, 'a', 'a ', 'a');")
tk.MustExec("INSERT INTO test.t (a, b, c, d) VALUES (5, ' A ', ' A ', ' A ');")
tk.MustExec("INSERT INTO test.t (a, b, c, d) VALUES (6, ' E', 'é ', ' E');")
mkr := func() [][]interface{} {
return testkit.RowsWithSep("|",
"3| 3 | 3 | 3",
"2| 2 0| 2",
"5| A | A | A",
"1|1|0|1",
"4|a|a |a",
"6| E|é | E")
}
tk.MustQuery("SELECT * FROM `test`.`t` FORCE INDEX(`a_uniq`);").Check(mkr())
tk.MustQuery("SELECT * FROM `test`.`t` FORCE INDEX(`b_uniq`);").Check(mkr())
tk.MustQuery("SELECT * FROM `test`.`t` FORCE INDEX(`d_uniq`);").Check(mkr())
tk.MustQuery("SELECT * FROM `test`.`t` FORCE INDEX(`a_idx`);").Check(mkr())
tk.MustQuery("SELECT * FROM `test`.`t` FORCE INDEX(`b_idx`);").Check(mkr())
tk.MustQuery("SELECT * FROM `test`.`t` FORCE INDEX(`d_idx`);").Check(mkr())
tk.MustExec("admin check table t")
}
func TestPartitionUnionWithPPruningColumn(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` (\n `fid` bigint(36) NOT NULL,\n `oty` varchar(30) DEFAULT NULL,\n `oid` int(11) DEFAULT NULL,\n `pid` bigint(20) DEFAULT NULL,\n `bid` int(11) DEFAULT NULL,\n `r5` varchar(240) DEFAULT '',\n PRIMARY KEY (`fid`)\n)PARTITION BY HASH( `fid` ) PARTITIONS 4;")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (59, 'm', 441, 1, 2143, 'LE1264_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (135, 'm', 1121, 1, 2423, 'LE2008_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (139, 'm', 1125, 1, 2432, 'LE2005_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (143, 'm', 1129, 1, 2438, 'LE2006_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (147, 'm', 1133, 1, 2446, 'LE2014_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (167, 'm', 1178, 1, 2512, 'LE2055_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (171, 'm', 1321, 1, 2542, 'LE1006_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (179, 'm', 1466, 1, 2648, 'LE2171_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (187, 'm', 1567, 1, 2690, 'LE1293_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (57, 'm', 341, 1, 2102, 'LE1001_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (137, 'm', 1123, 1, 2427, 'LE2003_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (145, 'm', 1131, 1, 2442, 'LE2048_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (138, 'm', 1124, 1, 2429, 'LE2004_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (142, 'm', 1128, 1, 2436, 'LE2049_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (174, 'm', 1381, 1, 2602, 'LE2170_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (28, 'm', 81, 1, 2023, 'LE1009_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (60, 'm', 442, 1, 2145, 'LE1263_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (136, 'm', 1122, 1, 2425, 'LE2002_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (140, 'm', 1126, 1, 2434, 'LE2001_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (168, 'm', 1179, 1, 2514, 'LE2052_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (196, 'm', 3380, 1, 2890, 'LE1300_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (208, 'm', 3861, 1, 3150, 'LE1323_r5');")
tk.MustExec("INSERT INTO t (fid, oty, oid, pid, bid, r5) VALUES (432, 'm', 4060, 1, 3290, 'LE1327_r5');")
tk.MustQuery("SELECT DISTINCT t.bid, t.r5 FROM t left join t parent on parent.oid = t.pid WHERE t.oty = 'm';").Sort().Check(
testkit.Rows("2023 LE1009_r5",
"2102 LE1001_r5",
"2143 LE1264_r5",
"2145 LE1263_r5",
"2423 LE2008_r5",
"2425 LE2002_r5",
"2427 LE2003_r5",
"2429 LE2004_r5",
"2432 LE2005_r5",
"2434 LE2001_r5",
"2436 LE2049_r5",
"2438 LE2006_r5",
"2442 LE2048_r5",
"2446 LE2014_r5",
"2512 LE2055_r5",
"2514 LE2052_r5",
"2542 LE1006_r5",
"2602 LE2170_r5",
"2648 LE2171_r5",
"2690 LE1293_r5",
"2890 LE1300_r5",
"3150 LE1323_r5",
"3290 LE1327_r5"))
}
func TestIssue20139(t *testing.T) {
failpoint.Enable("github.com/pingcap/tidb/planner/core/forceDynamicPrune", `return(true)`)
defer failpoint.Disable("github.com/pingcap/tidb/planner/core/forceDynamicPrune")
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 (id int, c int) partition by range (id) (partition p0 values less than (4), partition p1 values less than (7))")
tk.MustExec("insert into t values(3, 3), (5, 5)")
plan := tk.MustQuery("explain format = 'brief' select * from t where c = 1 and id = c")
plan.Check(testkit.Rows(
"TableReader 0.01 root partition:p0 data:Selection",
"└─Selection 0.01 cop[tikv] eq(test.t.c, 1), eq(test.t.id, 1)",
" └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo",
))
tk.MustExec("drop table t")
}
func TestIssue14481(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 default null, b int default null, c int default null)")
plan := tk.MustQuery("explain format = 'brief' select * from t where a = 1 and a = 2")
plan.Check(testkit.Rows("TableDual 0.00 root rows:0"))
tk.MustExec("drop table t")
}
func TestIssue20710(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("drop table if exists s;")
tk.MustExec("create table t(a int, b int)")
tk.MustExec("create table s(a int, b int, index(a))")
tk.MustExec("insert into t values(1,1),(1,2),(2,2)")
tk.MustExec("insert into s values(1,1),(2,2),(2,1)")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestQueryBlockTableAliasInHint(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
require.True(t, tk.HasPlan("select /*+ HASH_JOIN(@sel_1 t2) */ * FROM (select 1) t1 NATURAL LEFT JOIN (select 2) t2", "HashJoin"))
tk.MustQuery("select /*+ HASH_JOIN(@sel_1 t2) */ * FROM (select 1) t1 NATURAL LEFT JOIN (select 2) t2").Check(testkit.Rows(
"1 2",
))
require.Len(t, tk.Session().GetSessionVars().StmtCtx.GetWarnings(), 0)
}
func TestIssue10448(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(pk int(11) primary key)")
tk.MustExec("insert into t values(1),(2),(3)")
tk.MustQuery("select a from (select pk as a from t) t1 where a = 18446744073709551615").Check(testkit.Rows())
}
func TestMultiUpdateOnPrimaryKey(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 not null primary key)")
tk.MustExec("insert into t values (1)")
tk.MustGetErrMsg(`UPDATE t m, t n SET m.a = m.a + 10, n.a = n.a + 10`,
`[planner:1706]Primary key/partition key update is not allowed since the table is updated both as 'm' and 'n'.`)
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (a varchar(10) not null primary key)")
tk.MustExec("insert into t values ('abc')")
tk.MustGetErrMsg(`UPDATE t m, t n SET m.a = 'def', n.a = 'xyz'`,
`[planner:1706]Primary key/partition key update is not allowed since the table is updated both as 'm' and 'n'.`)
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (a int, b int, primary key (a, b))")
tk.MustExec("insert into t values (1, 2)")
tk.MustGetErrMsg(`UPDATE t m, t n SET m.a = m.a + 10, n.b = n.b + 10`,
`[planner:1706]Primary key/partition key update is not allowed since the table is updated both as 'm' and 'n'.`)
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (a int primary key, b int)")
tk.MustExec("insert into t values (1, 2)")
tk.MustGetErrMsg(`UPDATE t m, t n SET m.a = m.a + 10, n.a = n.a + 10`,
`[planner:1706]Primary key/partition key update is not allowed since the table is updated both as 'm' and 'n'.`)
tk.MustExec(`UPDATE t m, t n SET m.b = m.b + 10, n.b = n.b + 10`)
tk.MustQuery("SELECT * FROM t").Check(testkit.Rows("1 12"))
tk.MustGetErrMsg(`UPDATE t m, t n SET m.a = m.a + 1, n.b = n.b + 10`,
`[planner:1706]Primary key/partition key update is not allowed since the table is updated both as 'm' and 'n'.`)
tk.MustGetErrMsg(`UPDATE t m, t n, t q SET m.a = m.a + 1, n.b = n.b + 10, q.b = q.b - 10`,
`[planner:1706]Primary key/partition key update is not allowed since the table is updated both as 'm' and 'n'.`)
tk.MustGetErrMsg(`UPDATE t m, t n, t q SET m.b = m.b + 1, n.a = n.a + 10, q.b = q.b - 10`,
`[planner:1706]Primary key/partition key update is not allowed since the table is updated both as 'm' and 'n'.`)
tk.MustGetErrMsg(`UPDATE t m, t n, t q SET m.b = m.b + 1, n.b = n.b + 10, q.a = q.a - 10`,
`[planner:1706]Primary key/partition key update is not allowed since the table is updated both as 'm' and 'q'.`)
tk.MustGetErrMsg(`UPDATE t q, t n, t m SET m.b = m.b + 1, n.b = n.b + 10, q.a = q.a - 10`,
`[planner:1706]Primary key/partition key update is not allowed since the table is updated both as 'q' and 'n'.`)
tk.MustExec("update t m, t n set m.a = n.a+10 where m.a=n.a")
tk.MustQuery("select * from t").Check(testkit.Rows("11 12"))
}
func TestOrderByHavingNotInSelect(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists ttest")
tk.MustExec("create table ttest (v1 int, v2 int)")
tk.MustExec("insert into ttest values(1, 2), (4,6), (1, 7)")
tk.MustGetErrMsg("select v1 from ttest order by count(v2)",
"[planner:3029]Expression #1 of ORDER BY contains aggregate function and applies to the result of a non-aggregated query")
tk.MustGetErrMsg("select v1 from ttest having count(v2)",
"[planner:8123]In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column 'v1'; this is incompatible with sql_mode=only_full_group_by")
tk.MustGetErrMsg("select v2, v1 from (select * from ttest) t1 join (select 1, 2) t2 group by v1",
"[planner:1055]Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.t1.v2' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by")
tk.MustGetErrMsg("select v2, v1 from (select t1.v1, t2.v2 from ttest t1 join ttest t2) t3 join (select 1, 2) t2 group by v1",
"[planner:1055]Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'test.t3.v2' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by")
}
func TestUpdateSetDefault(t *testing.T) {
store := testkit.CreateMockStore(t)
// #20598
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table tt (x int, z int as (x+10) stored)")
tk.MustExec("insert into tt(x) values (1)")
tk.MustExec("update tt set x=2, z = default")
tk.MustExec("update tt set x=2, z = default(z)")
tk.MustQuery("select * from tt").Check(testkit.Rows("2 12"))
tk.MustGetErrMsg("update tt set x=2, z = default(x)",
"[planner:3105]The value specified for generated column 'z' in table 'tt' is not allowed.")
tk.MustGetErrMsg("update tt set z = 123",
"[planner:3105]The value specified for generated column 'z' in table 'tt' is not allowed.")
tk.MustGetErrMsg("update tt as ss set z = 123",
"[planner:3105]The value specified for generated column 'z' in table 'tt' is not allowed.")
tk.MustGetErrMsg("update tt as ss set x = 3, z = 13",
"[planner:3105]The value specified for generated column 'z' in table 'tt' is not allowed.")
tk.MustGetErrMsg("update tt as s1, tt as s2 set s1.z = default, s2.z = 456",
"[planner:3105]The value specified for generated column 'z' in table 'tt' is not allowed.")
}
func TestExtendedStatsSwitch(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 not null, b int not null, key(a), key(b))")
tk.MustExec("insert into t values(1,1),(2,2),(3,3),(4,4),(5,5),(6,6)")
tk.MustExec("set session tidb_enable_extended_stats = off")
tk.MustGetErrMsg("alter table t add stats_extended s1 correlation(a,b)",
"Extended statistics feature is not generally available now, and tidb_enable_extended_stats is OFF")
tk.MustGetErrMsg("alter table t drop stats_extended s1",
"Extended statistics feature is not generally available now, and tidb_enable_extended_stats is OFF")
tk.MustGetErrMsg("admin reload stats_extended",
"Extended statistics feature is not generally available now, and tidb_enable_extended_stats is OFF")
tk.MustExec("set session tidb_enable_extended_stats = on")
tk.MustExec("alter table t add stats_extended s1 correlation(a,b)")
tk.MustQuery("select stats, status from mysql.stats_extended where name = 's1'").Check(testkit.Rows(
"<nil> 0",
))
tk.MustExec("set session tidb_enable_extended_stats = off")
// Analyze should not collect extended stats.
tk.MustExec("analyze table t")
tk.MustQuery("select stats, status from mysql.stats_extended where name = 's1'").Check(testkit.Rows(
"<nil> 0",
))
tk.MustExec("set session tidb_enable_extended_stats = on")
// Analyze would collect extended stats.
tk.MustExec("analyze table t")
tk.MustQuery("select stats, status from mysql.stats_extended where name = 's1'").Check(testkit.Rows(
"1.000000 1",
))
// Estimated index scan count is 4 using extended stats.
tk.MustQuery("explain format = 'brief' select * from t use index(b) where a > 3 order by b limit 1").Check(testkit.Rows(
"Limit 1.00 root offset:0, count:1",
"└─Projection 1.00 root test.t.a, test.t.b",
" └─IndexLookUp 1.00 root ",
" ├─IndexFullScan(Build) 4.00 cop[tikv] table:t, index:b(b) keep order:true",
" └─Selection(Probe) 1.00 cop[tikv] gt(test.t.a, 3)",
" └─TableRowIDScan 4.00 cop[tikv] table:t keep order:false",
))
tk.MustExec("set session tidb_enable_extended_stats = off")
// Estimated index scan count is 2 using independent assumption.
tk.MustQuery("explain format = 'brief' select * from t use index(b) where a > 3 order by b limit 1").Check(testkit.Rows(
"Limit 1.00 root offset:0, count:1",
"└─Projection 1.00 root test.t.a, test.t.b",
" └─IndexLookUp 1.00 root ",
" ├─IndexFullScan(Build) 2.00 cop[tikv] table:t, index:b(b) keep order:true",
" └─Selection(Probe) 1.00 cop[tikv] gt(test.t.a, 3)",
" └─TableRowIDScan 2.00 cop[tikv] table:t keep order:false",
))
}
func TestOrderByNotInSelectDistinct(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
// #12442
tk.MustExec("drop table if exists ttest")
tk.MustExec("create table ttest (v1 int, v2 int)")
tk.MustExec("insert into ttest values(1, 2), (4,6), (1, 7)")
tk.MustGetErrMsg("select distinct v1 from ttest order by v2",
"[planner:3065]Expression #1 of ORDER BY clause is not in SELECT list, references column 'test.ttest.v2' which is not in SELECT list; this is incompatible with DISTINCT")
tk.MustGetErrMsg("select distinct v1+1 from ttest order by v1",
"[planner:3065]Expression #1 of ORDER BY clause is not in SELECT list, references column 'test.ttest.v1' which is not in SELECT list; this is incompatible with DISTINCT")
tk.MustGetErrMsg("select distinct v1+1 from ttest order by 1+v1",
"[planner:3065]Expression #1 of ORDER BY clause is not in SELECT list, references column 'test.ttest.v1' which is not in SELECT list; this is incompatible with DISTINCT")
tk.MustGetErrMsg("select distinct v1+1 from ttest order by v1+2",
"[planner:3065]Expression #1 of ORDER BY clause is not in SELECT list, references column 'test.ttest.v1' which is not in SELECT list; this is incompatible with DISTINCT")
tk.MustGetErrMsg("select distinct count(v1) from ttest group by v2 order by sum(v1)",
"[planner:3066]Expression #1 of ORDER BY clause is not in SELECT list, contains aggregate function; this is incompatible with DISTINCT")
tk.MustGetErrMsg("select distinct sum(v1)+1 from ttest group by v2 order by sum(v1)",
"[planner:3066]Expression #1 of ORDER BY clause is not in SELECT list, contains aggregate function; this is incompatible with DISTINCT")
// Expressions in ORDER BY whole match some fields in DISTINCT.
tk.MustQuery("select distinct v1+1 from ttest order by v1+1").Check(testkit.Rows("2", "5"))
tk.MustQuery("select distinct count(v1) from ttest order by count(v1)").Check(testkit.Rows("3"))
tk.MustQuery("select distinct count(v1) from ttest group by v2 order by count(v1)").Check(testkit.Rows("1"))
tk.MustQuery("select distinct sum(v1) from ttest group by v2 order by sum(v1)").Check(testkit.Rows("1", "4"))
tk.MustQuery("select distinct v1, v2 from ttest order by 1, 2").Check(testkit.Rows("1 2", "1 7", "4 6"))
tk.MustQuery("select distinct v1, v2 from ttest order by 2, 1").Check(testkit.Rows("1 2", "4 6", "1 7"))
// Referenced columns of expressions in ORDER BY whole match some fields in DISTINCT,
// both original expression and alias can be referenced.
tk.MustQuery("select distinct v1 from ttest order by v1+1").Check(testkit.Rows("1", "4"))
tk.MustQuery("select distinct v1, v2 from ttest order by v1+1, v2").Check(testkit.Rows("1 2", "1 7", "4 6"))
tk.MustQuery("select distinct v1+1 as z, v2 from ttest order by v1+1, z+v2").Check(testkit.Rows("2 2", "2 7", "5 6"))
tk.MustQuery("select distinct sum(v1) as z from ttest group by v2 order by z+1").Check(testkit.Rows("1", "4"))
tk.MustQuery("select distinct sum(v1)+1 from ttest group by v2 order by sum(v1)+1").Check(testkit.Rows("2", "5"))
tk.MustQuery("select distinct v1 as z from ttest order by v1+z").Check(testkit.Rows("1", "4"))
}
func TestInvalidNamedWindowSpec(t *testing.T) {
store := testkit.CreateMockStore(t)
// #12356
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("DROP TABLE IF EXISTS temptest")
tk.MustExec("create table temptest (val int, val1 int)")
tk.MustQuery("SELECT val FROM temptest WINDOW w AS (ORDER BY val RANGE 1 PRECEDING)").Check(testkit.Rows())
tk.MustGetErrMsg("SELECT val FROM temptest WINDOW w AS (ORDER BY val, val1 RANGE 1 PRECEDING)",
"[planner:3587]Window 'w' with RANGE N PRECEDING/FOLLOWING frame requires exactly one ORDER BY expression, of numeric or temporal type")
tk.MustGetErrMsg("select val1, avg(val1) as a from temptest group by val1 window w as (order by a)",
"[planner:1054]Unknown column 'a' in 'window order by'")
tk.MustGetErrMsg("select val1, avg(val1) as a from temptest group by val1 window w as (partition by a)",
"[planner:1054]Unknown column 'a' in 'window partition by'")
}
func TestCorrelatedAggregate(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
// #18350
tk.MustExec("DROP TABLE IF EXISTS tab, tab2")
tk.MustExec("CREATE TABLE tab(i INT)")
tk.MustExec("CREATE TABLE tab2(j INT)")
tk.MustExec("insert into tab values(1),(2),(3)")
tk.MustExec("insert into tab2 values(1),(2),(3),(15)")
tk.MustQuery(`SELECT m.i,
(SELECT COUNT(n.j)
FROM tab2 WHERE j=15) AS o
FROM tab m, tab2 n GROUP BY 1 order by m.i`).Check(testkit.Rows("1 4", "2 4", "3 4"))
tk.MustQuery(`SELECT
(SELECT COUNT(n.j)
FROM tab2 WHERE j=15) AS o
FROM tab m, tab2 n order by m.i`).Check(testkit.Rows("12"))
// #17748
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1 (a int, b int)")
tk.MustExec("create table t2 (m int, n int)")
tk.MustExec("insert into t1 values (2,2), (2,2), (3,3), (3,3), (3,3), (4,4)")
tk.MustExec("insert into t2 values (1,11), (2,22), (3,32), (4,44), (4,44)")
tk.MustExec("set @@sql_mode='TRADITIONAL'")
tk.MustQuery(`select count(*) c, a,
( select group_concat(count(a)) from t2 where m = a )
from t1 group by a order by a`).
Check(testkit.Rows("2 2 2", "3 3 3", "1 4 1,1"))
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (a int, b int)")
tk.MustExec("insert into t values (1,1),(2,1),(2,2),(3,1),(3,2),(3,3)")
// Sub-queries in SELECT fields
// from SELECT fields
tk.MustQuery("select (select count(a)) from t").Check(testkit.Rows("6"))
tk.MustQuery("select (select (select (select count(a)))) from t").Check(testkit.Rows("6"))
tk.MustQuery("select (select (select count(n.a)) from t m order by count(m.b)) from t n").Check(testkit.Rows("6"))
// from WHERE
tk.MustQuery("select (select count(n.a) from t where count(n.a)=3) from t n").Check(testkit.Rows("<nil>"))
tk.MustQuery("select (select count(a) from t where count(distinct n.a)=3) from t n").Check(testkit.Rows("6"))
// from HAVING
tk.MustQuery("select (select count(n.a) from t having count(n.a)=6 limit 1) from t n").Check(testkit.Rows("6"))
tk.MustQuery("select (select count(n.a) from t having count(distinct n.b)=3 limit 1) from t n").Check(testkit.Rows("6"))
tk.MustQuery("select (select sum(distinct n.a) from t having count(distinct n.b)=3 limit 1) from t n").Check(testkit.Rows("6"))
tk.MustQuery("select (select sum(distinct n.a) from t having count(distinct n.b)=6 limit 1) from t n").Check(testkit.Rows("<nil>"))
// from ORDER BY
tk.MustQuery("select (select count(n.a) from t order by count(n.b) limit 1) from t n").Check(testkit.Rows("6"))
tk.MustQuery("select (select count(distinct n.b) from t order by count(n.b) limit 1) from t n").Check(testkit.Rows("3"))
// from TableRefsClause
tk.MustQuery("select (select cnt from (select count(a) cnt) s) from t").Check(testkit.Rows("6"))
tk.MustQuery("select (select count(cnt) from (select count(a) cnt) s) from t").Check(testkit.Rows("1"))
// from sub-query inside aggregate
tk.MustQuery("select (select sum((select count(a)))) from t").Check(testkit.Rows("6"))
tk.MustQuery("select (select sum((select count(a))+sum(a))) from t").Check(testkit.Rows("20"))
// from GROUP BY
tk.MustQuery("select (select count(a) from t group by count(n.a)) from t n").Check(testkit.Rows("6"))
tk.MustQuery("select (select count(distinct a) from t group by count(n.a)) from t n").Check(testkit.Rows("3"))
// Sub-queries in HAVING
tk.MustQuery("select sum(a) from t having (select count(a)) = 0").Check(testkit.Rows())
tk.MustQuery("select sum(a) from t having (select count(a)) > 0").Check(testkit.Rows("14"))
// Sub-queries in ORDER BY
tk.MustQuery("select count(a) from t group by b order by (select count(a))").Check(testkit.Rows("1", "2", "3"))
tk.MustQuery("select count(a) from t group by b order by (select -count(a))").Check(testkit.Rows("3", "2", "1"))
// Nested aggregate (correlated aggregate inside aggregate)
tk.MustQuery("select (select sum(count(a))) from t").Check(testkit.Rows("6"))
tk.MustQuery("select (select sum(sum(a))) from t").Check(testkit.Rows("14"))
// Combining aggregates
tk.MustQuery("select count(a), (select count(a)) from t").Check(testkit.Rows("6 6"))
tk.MustQuery("select sum(distinct b), count(a), (select count(a)), (select cnt from (select sum(distinct b) as cnt) n) from t").
Check(testkit.Rows("6 6 6 6"))
}
func TestCorrelatedColumnAggFuncPushDown(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, b int);")
tk.MustExec("insert into t values (1,1);")
tk.MustQuery("select (select count(n.a + a) from t) from t n;").Check(testkit.Rows(
"1",
))
}
// Test for issue https://github.com/pingcap/tidb/issues/21607.
func TestConditionColPruneInPhysicalUnionScan(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, b int);")
tk.MustExec("begin;")
tk.MustExec("insert into t values (1, 2);")
tk.MustQuery("select count(*) from t where b = 1 and b in (3);").
Check(testkit.Rows("0"))
tk.MustExec("drop table t;")
tk.MustExec("create table t (a int, b int as (a + 1), c int as (b + 1));")
tk.MustExec("begin;")
tk.MustExec("insert into t (a) values (1);")
tk.MustQuery("select count(*) from t where b = 1 and b in (3);").
Check(testkit.Rows("0"))
tk.MustQuery("select count(*) from t where c = 1 and c in (3);").
Check(testkit.Rows("0"))
}
func TestInvalidHint(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists tt")
tk.MustExec("create table tt(a int, key(a));")
var input []string
var output []struct {
SQL string
Plan []string
Warnings []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
warning := "show warnings;"
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
output[i].Warnings = testdata.ConvertRowsToStrings(tk.MustQuery(warning).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
}
// Test for issue https://github.com/pingcap/tidb/issues/18320
func TestNonaggregateColumnWithSingleValueInOnlyFullGroupByMode(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, b int, c int)")
tk.MustExec("insert into t values (1, 2, 3), (4, 5, 6), (7, 8, 9)")
tk.MustQuery("select a, count(b) from t where a = 1").Check(testkit.Rows("1 1"))
tk.MustQuery("select a, count(b) from t where a = 10").Check(testkit.Rows("<nil> 0"))
tk.MustQuery("select a, c, sum(b) from t where a = 1 group by c").Check(testkit.Rows("1 3 2"))
tk.MustGetErrMsg("select a from t where a = 1 order by count(b)", "[planner:3029]Expression #1 of ORDER BY contains aggregate function and applies to the result of a non-aggregated query")
tk.MustQuery("select a from t where a = 1 having count(b) > 0").Check(testkit.Rows("1"))
}
func TestConvertRangeToPoint(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("create table t0 (a int, b int, index(a, b))")
tk.MustExec("insert into t0 values (1, 1)")
tk.MustExec("insert into t0 values (2, 2)")
tk.MustExec("insert into t0 values (2, 2)")
tk.MustExec("insert into t0 values (2, 2)")
tk.MustExec("insert into t0 values (2, 2)")
tk.MustExec("insert into t0 values (2, 2)")
tk.MustExec("insert into t0 values (3, 3)")
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t1 (a int, b int, c int, index(a, b, c))")
tk.MustExec("drop table if exists t2")
tk.MustExec("create table t2 (a float, b float, index(a, b))")
tk.MustExec("drop table if exists t3")
tk.MustExec("create table t3 (a char(10), b char(10), c char(10), index(a, b, c))")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestIssue22040(t *testing.T) {
store := testkit.CreateMockStore(t)
// #22040
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, primary key(a,b))")
// valid case
tk.MustExec("select * from t where (a,b) in ((1,2),(1,2))")
// invalid case, column count doesn't match
{
err := tk.ExecToErr("select * from t where (a,b) in (1,2)")
require.IsType(t, expression.ErrOperandColumns, errors.Cause(err))
}
{
err := tk.ExecToErr("select * from t where (a,b) in ((1,2),1)")
require.IsType(t, expression.ErrOperandColumns, errors.Cause(err))
}
}
func TestIssue22105(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 t1 (
key1 int(11) NOT NULL,
key2 int(11) NOT NULL,
key3 int(11) NOT NULL,
key4 int(11) NOT NULL,
key5 int(11) DEFAULT NULL,
key6 int(11) DEFAULT NULL,
key7 int(11) NOT NULL,
key8 int(11) NOT NULL,
KEY i1 (key1),
KEY i2 (key2),
KEY i3 (key3),
KEY i4 (key4),
KEY i5 (key5),
KEY i6 (key6)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin`)
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestIssue22071(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t (a int);")
tk.MustExec("insert into t values(1),(2),(5)")
tk.MustQuery("select n in (1,2) from (select a in (1,2) as n from t) g;").Sort().Check(testkit.Rows("0", "1", "1"))
tk.MustQuery("select n in (1,n) from (select a in (1,2) as n from t) g;").Check(testkit.Rows("1", "1", "1"))
}
func TestCreateViewIsolationRead(t *testing.T) {
store := testkit.CreateMockStore(t)
se, err := session.CreateSession4Test(store)
require.NoError(t, err)
require.NoError(t, se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil))
tk := testkit.NewTestKit(t, store)
tk.SetSession(se)
tk.MustExec("use test;")
tk.MustExec("drop table if exists t;")
tk.MustExec("create table t(a int, b int);")
tk.MustExec("set session tidb_isolation_read_engines='tiflash,tidb';")
// No error for CreateView.
tk.MustExec("create view v0 (a, avg_b) as select a, avg(b) from t group by a;")
tk.MustGetErrMsg("select * from v0;", "[planner:1815]Internal : No access path for table 't' is found with 'tidb_isolation_read_engines' = 'tiflash,tidb', valid values can be 'tikv'.")
tk.MustExec("set session tidb_isolation_read_engines='tikv,tiflash,tidb';")
tk.MustQuery("select * from v0;").Check(testkit.Rows())
}
func TestIssue22199(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1(i int primary key, j int, index idx_j(j))")
tk.MustExec("create table t2(i int primary key, j int, index idx_j(j))")
tk.MustGetErrMsg("select t1.*, (select t2.* from t1) from t1", "[planner:1051]Unknown table 't2'")
}
func TestIssue22892(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("set @@tidb_partition_prune_mode='static'")
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t1(a int) partition by hash (a) partitions 5;")
tk.MustExec("insert into t1 values (0);")
tk.MustQuery("select * from t1 where a not between 1 and 2;").Check(testkit.Rows("0"))
tk.MustExec("set @@tidb_partition_prune_mode='dynamic'")
tk.MustExec("drop table if exists t2")
tk.MustExec("create table t2(a int) partition by hash (a) partitions 5;")
tk.MustExec("insert into t2 values (0);")
tk.MustQuery("select * from t2 where a not between 1 and 2;").Check(testkit.Rows("0"))
}
func TestIssue26719(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec(`create table tx (a int) partition by range (a) (partition p0 values less than (10), partition p1 values less than (20))`)
tk.MustExec(`insert into tx values (1)`)
tk.MustExec("set @@tidb_partition_prune_mode='dynamic'")
tk.MustExec(`begin`)
tk.MustExec(`delete from tx where a in (1)`)
tk.MustQuery(`select * from tx PARTITION(p0)`).Check(testkit.Rows())
tk.MustQuery(`select * from tx`).Check(testkit.Rows())
tk.MustExec(`rollback`)
}
func TestIssue32428(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table `t1` (`a` enum('aa') DEFAULT NULL, KEY `k` (`a`))")
tk.MustExec("insert into t1 values('aa')")
tk.MustExec("insert into t1 values(null)")
tk.MustQuery("select a from t1 where a<=>'aa'").Check(testkit.Rows("aa"))
tk.MustQuery("select a from t1 where a<=>null").Check(testkit.Rows("<nil>"))
tk.MustExec(`CREATE TABLE IDT_MULTI15860STROBJSTROBJ (
COL1 enum('aa') DEFAULT NULL,
COL2 int(41) DEFAULT NULL,
COL3 year(4) DEFAULT NULL,
KEY U_M_COL4 (COL1,COL2),
KEY U_M_COL5 (COL3,COL2))`)
tk.MustExec(`insert into IDT_MULTI15860STROBJSTROBJ values("aa", 1013610488, 1982)`)
tk.MustQuery(`SELECT * FROM IDT_MULTI15860STROBJSTROBJ t1 RIGHT JOIN IDT_MULTI15860STROBJSTROBJ t2 ON t1.col1 <=> t2.col1 where t1.col1 is null and t2.col1 = "aa"`).Check(testkit.Rows()) // empty result
tk.MustExec(`prepare stmt from "SELECT * FROM IDT_MULTI15860STROBJSTROBJ t1 RIGHT JOIN IDT_MULTI15860STROBJSTROBJ t2 ON t1.col1 <=> t2.col1 where t1.col1 is null and t2.col1 = ?"`)
tk.MustExec(`set @a="aa"`)
tk.MustQuery(`execute stmt using @a`).Check(testkit.Rows()) // empty result
}
func TestPushDownProjectionForTiKV(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, b real, i int, id int, value decimal(6,3), name char(128), d decimal(6,3), s char(128), t datetime, c bigint as ((a+1)) virtual, e real as ((b+a)))")
tk.MustExec("analyze table t")
tk.MustExec("set session tidb_opt_projection_push_down=1")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestPushDownProjectionForTiFlashCoprocessor(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, b real, i int, id int, value decimal(6,3), name char(128), d decimal(6,3), s char(128), t datetime, c bigint as ((a+1)) virtual, e real as ((b+a)))")
tk.MustExec("analyze table t")
tk.MustExec("set session tidb_opt_projection_push_down=1")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestPushDownProjectionForTiFlash(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 (id int, value decimal(6,3), name char(128))")
tk.MustExec("analyze table t")
tk.MustExec("set session tidb_allow_mpp=OFF")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestPushDownSelectionForMPP(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 (id int, value decimal(6,3), name char(128))")
tk.MustExec("analyze table t")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;")
tk.MustExec("set @@tidb_isolation_read_engines='tiflash,tidb';")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestPushDownProjectionForMPP(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 (id int, value decimal(6,3), name char(128))")
tk.MustExec("analyze table t")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestReorderSimplifiedOuterJoins(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 t1,t2,t3")
tk.MustExec("create table t1 (pk char(32) primary key nonclustered, col1 char(32), col2 varchar(40), col3 char(32), key (col1), key (col3), key (col2,col3), key (col1,col3))")
tk.MustExec("create table t2 (pk char(32) primary key nonclustered, col1 varchar(100))")
tk.MustExec("create table t3 (pk char(32) primary key nonclustered, keycol varchar(100), pad1 tinyint(1) default null, pad2 varchar(40), key (keycol,pad1,pad2))")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
}
// Apply operator may got panic because empty Projection is eliminated.
func TestIssue23887(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, b int);")
tk.MustExec("insert into t values(1, 2), (3, 4);")
var input []string
var output []struct {
SQL string
Plan []string
Res []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows())
output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows())
})
tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...))
tk.MustQuery(tt).Sort().Check(testkit.Rows(output[i].Res...))
}
tk.MustExec("drop table if exists t1;")
tk.MustExec("create table t1 (c1 int primary key, c2 int, c3 int, index c2 (c2));")
tk.MustQuery("select count(1) from (select count(1) from (select * from t1 where c3 = 100) k) k2;").Check(testkit.Rows("1"))
}
func TestDeleteStmt(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t(a int)")
tk.MustExec("delete t from t;")
tk.MustExec("delete t from test.t as t;")
tk.MustGetErrCode("delete test.t from test.t as t;", mysql.ErrUnknownTable)
tk.MustExec("delete test.t from t;")
tk.MustExec("create database db1")
tk.MustExec("use db1")
tk.MustExec("create table t(a int)")
tk.MustGetErrCode("delete test.t from t;", mysql.ErrUnknownTable)
}
func TestIndexMergeConstantTrue(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, b int not null, key(b))")
tk.MustExec("delete /*+ use_index_merge(t) */ FROM t WHERE a=1 OR (b < SOME (SELECT /*+ use_index_merge(t)*/ b FROM t WHERE a<2 OR b<2))")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int not null, b int not null, key(a), key(b))")
tk.MustExec("delete /*+ use_index_merge(t) */ FROM t WHERE a=1 OR (b < SOME (SELECT /*+ use_index_merge(t)*/ b FROM t WHERE a<2 OR b<2))")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int primary key, b int not null, c int, key(a), key(b,c))")
tk.MustExec("delete /*+ use_index_merge(t) */ FROM t WHERE a=1 OR (a<2 and b<2)")
}
func TestPushDownAggForMPP(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 (id int, value decimal(6,3))")
tk.MustExec("analyze table t")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec(" set @@tidb_allow_mpp=1; set @@tidb_broadcast_join_threshold_count = 1; set @@tidb_broadcast_join_threshold_size=1;")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestMppUnionAll(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("drop table if exists t1")
tk.MustExec("create table t (a int not null, b int, c varchar(20))")
tk.MustExec("create table t1 (a int, b int not null, c double)")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" || tblInfo.Name.L == "t1" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestMppJoinDecimal(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("drop table if exists tt")
tk.MustExec("create table t (c1 decimal(8, 5), c2 decimal(9, 5), c3 decimal(9, 4) NOT NULL, c4 decimal(8, 4) NOT NULL, c5 decimal(40, 20))")
tk.MustExec("create table tt (pk int(11) NOT NULL AUTO_INCREMENT primary key,col_varchar_64 varchar(64),col_char_64_not_null char(64) NOT null, col_decimal_30_10_key decimal(30,10), col_tinyint tinyint, col_varchar_key varchar(1), key col_decimal_30_10_key (col_decimal_30_10_key), key col_varchar_key(col_varchar_key));")
tk.MustExec("analyze table t")
tk.MustExec("analyze table tt")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" || tblInfo.Name.L == "tt" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set @@tidb_allow_mpp=1;")
tk.MustExec("set @@session.tidb_broadcast_join_threshold_size = 1")
tk.MustExec("set @@session.tidb_broadcast_join_threshold_count = 1")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestMppJoinExchangeColumnPrune(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("drop table if exists tt")
tk.MustExec("create table t (c1 int, c2 int, c3 int NOT NULL, c4 int NOT NULL, c5 int)")
tk.MustExec("create table tt (b1 int)")
tk.MustExec("analyze table t")
tk.MustExec("analyze table tt")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" || tblInfo.Name.L == "tt" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set @@tidb_allow_mpp=1;")
tk.MustExec("set @@session.tidb_broadcast_join_threshold_size = 1")
tk.MustExec("set @@session.tidb_broadcast_join_threshold_count = 1")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestMppFineGrainedJoinAndAgg(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("drop table if exists tt")
tk.MustExec("create table t (c1 int, c2 int, c3 int NOT NULL, c4 int NOT NULL, c5 int)")
tk.MustExec("create table tt (b1 int)")
tk.MustExec("analyze table t")
tk.MustExec("analyze table tt")
instances := []string{
"tiflash,127.0.0.1:3933,127.0.0.1:7777,,",
"tikv,127.0.0.1:11080,127.0.0.1:10080,,",
}
fpName := "github.com/pingcap/tidb/infoschema/mockStoreServerInfo"
fpExpr := `return("` + strings.Join(instances, ";") + `")`
require.NoError(t, failpoint.Enable(fpName, fpExpr))
defer func() { require.NoError(t, failpoint.Disable(fpName)) }()
fpName2 := "github.com/pingcap/tidb/planner/core/mockTiFlashStreamCountUsingMinLogicalCores"
require.NoError(t, failpoint.Enable(fpName2, `return("8")`))
defer func() { require.NoError(t, failpoint.Disable(fpName2)) }()
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" || tblInfo.Name.L == "tt" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set @@tidb_allow_mpp=1;")
tk.MustExec("set @@session.tidb_broadcast_join_threshold_size = 1")
tk.MustExec("set @@session.tidb_broadcast_join_threshold_count = 1")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestMppAggTopNWithJoin(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 (id int, value decimal(6,3))")
tk.MustExec("analyze table t")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec(" set @@tidb_allow_mpp=1;")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestLimitIndexLookUpKeepOrder(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, b int, c int, d int, index idx(a,b,c));")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestDecorrelateInnerJoinInSubquery(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 not null, b int not null)")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestDecorrelateLimitInSubquery(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists test")
tk.MustExec("create table test(id int, value int)")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(c int)")
tk.MustExec("insert t values(10), (8), (7), (9), (11)")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestIndexMergeTableFilter(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, b int, c int, d int, key(a), key(b));")
tk.MustExec("insert into t values(10,1,1,10)")
tk.MustQuery("explain format = 'brief' select /*+ use_index_merge(t) */ * from t where a=10 or (b=10 and c=10)").Check(testkit.Rows(
"IndexMerge 0.02 root type: union",
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:a(a) range:[10,10], keep order:false, stats:pseudo",
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:b(b) range:[10,10], keep order:false, stats:pseudo",
"└─Selection(Probe) 0.02 cop[tikv] or(eq(test.t.a, 10), and(eq(test.t.b, 10), eq(test.t.c, 10)))",
" └─TableRowIDScan 19.99 cop[tikv] table:t keep order:false, stats:pseudo",
))
tk.MustQuery("select /*+ use_index_merge(t) */ * from t where a=10 or (b=10 and c=10)").Check(testkit.Rows(
"10 1 1 10",
))
tk.MustQuery("explain format = 'brief' select /*+ use_index_merge(t) */ * from t where (a=10 and d=10) or (b=10 and c=10)").Check(testkit.Rows(
"IndexMerge 0.00 root type: union",
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:a(a) range:[10,10], keep order:false, stats:pseudo",
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:b(b) range:[10,10], keep order:false, stats:pseudo",
"└─Selection(Probe) 0.00 cop[tikv] or(and(eq(test.t.a, 10), eq(test.t.d, 10)), and(eq(test.t.b, 10), eq(test.t.c, 10)))",
" └─TableRowIDScan 19.99 cop[tikv] table:t keep order:false, stats:pseudo",
))
tk.MustQuery("select /*+ use_index_merge(t) */ * from t where (a=10 and d=10) or (b=10 and c=10)").Check(testkit.Rows(
"10 1 1 10",
))
}
func TestIssue22850(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(11))")
tk.MustQuery("SELECT @v:=(SELECT 1 FROM t1 t2 LEFT JOIN t1 ON t1.a GROUP BY t1.a) FROM t1").Check(testkit.Rows()) // work fine
}
func TestJoinSchemaChange(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1(a int(11))")
tk.MustExec("create table t2(a decimal(40,20) unsigned, b decimal(40,20))")
tk.MustQuery("select count(*) as x from t1 group by a having x not in (select a from t2 where x = t2.b)").Check(testkit.Rows())
}
// #22949: test HexLiteral Used in GetVar expr
func TestGetVarExprWithHexLiteral(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test;")
tk.MustExec("drop table if exists t1_no_idx;")
tk.MustExec("create table t1_no_idx(id int, col_bit bit(16));")
tk.MustExec("insert into t1_no_idx values(1, 0x3135);")
tk.MustExec("insert into t1_no_idx values(2, 0x0f);")
tk.MustExec("prepare stmt from 'select id from t1_no_idx where col_bit = ?';")
tk.MustExec("set @a = 0x3135;")
tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("1"))
tk.MustExec("set @a = 0x0F;")
tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("2"))
// same test, but use IN expr
tk.MustExec("prepare stmt from 'select id from t1_no_idx where col_bit in (?)';")
tk.MustExec("set @a = 0x3135;")
tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("1"))
tk.MustExec("set @a = 0x0F;")
tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("2"))
// same test, but use table with index on col_bit
tk.MustExec("drop table if exists t2_idx;")
tk.MustExec("create table t2_idx(id int, col_bit bit(16), key(col_bit));")
tk.MustExec("insert into t2_idx values(1, 0x3135);")
tk.MustExec("insert into t2_idx values(2, 0x0f);")
tk.MustExec("prepare stmt from 'select id from t2_idx where col_bit = ?';")
tk.MustExec("set @a = 0x3135;")
tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("1"))
tk.MustExec("set @a = 0x0F;")
tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("2"))
// same test, but use IN expr
tk.MustExec("prepare stmt from 'select id from t2_idx where col_bit in (?)';")
tk.MustExec("set @a = 0x3135;")
tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("1"))
tk.MustExec("set @a = 0x0F;")
tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("2"))
// test col varchar with GetVar
tk.MustExec("drop table if exists t_varchar;")
tk.MustExec("create table t_varchar(id int, col_varchar varchar(100), key(col_varchar));")
tk.MustExec("insert into t_varchar values(1, '15');")
tk.MustExec("prepare stmt from 'select id from t_varchar where col_varchar = ?';")
tk.MustExec("set @a = 0x3135;")
tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("1"))
}
// test BitLiteral used with GetVar
func TestGetVarExprWithBitLiteral(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test;")
tk.MustExec("drop table if exists t1_no_idx;")
tk.MustExec("create table t1_no_idx(id int, col_bit bit(16));")
tk.MustExec("insert into t1_no_idx values(1, 0x3135);")
tk.MustExec("insert into t1_no_idx values(2, 0x0f);")
tk.MustExec("prepare stmt from 'select id from t1_no_idx where col_bit = ?';")
// 0b11000100110101 is 0x3135
tk.MustExec("set @a = 0b11000100110101;")
tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("1"))
// same test, but use IN expr
tk.MustExec("prepare stmt from 'select id from t1_no_idx where col_bit in (?)';")
tk.MustExec("set @a = 0b11000100110101;")
tk.MustQuery("execute stmt using @a;").Check(testkit.Rows("1"))
}
func TestIndexMergeClusterIndex(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 (c1 float, c2 int, c3 int, primary key (c1) /*T![clustered_index] CLUSTERED */, key idx_1 (c2), key idx_2 (c3))")
tk.MustExec("insert into t values(1.0,1,2),(2.0,2,1),(3.0,1,1),(4.0,2,2)")
tk.MustQuery("select /*+ use_index_merge(t) */ c3 from t where c3 = 1 or c2 = 1").Sort().Check(testkit.Rows(
"1",
"1",
"2",
))
tk.MustExec("drop table t")
tk.MustExec("create table t (a int, b int, c int, primary key (a,b) /*T![clustered_index] CLUSTERED */, key idx_c(c))")
tk.MustExec("insert into t values (0,1,2)")
tk.MustQuery("select /*+ use_index_merge(t) */ c from t where c > 10 or a < 1").Check(testkit.Rows(
"2",
))
}
func TestMultiColMaxOneRow(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1,t2")
tk.MustExec("create table t1(a int)")
tk.MustExec("create table t2(a int, b int, c int, primary key(a,b) nonclustered)")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows())
})
tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestIssue23736(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t0, t1")
tk.MustExec("create table t0(a int, b int, c int as (a + b) virtual, unique index (c) invisible);")
tk.MustExec("create table t1(a int, b int, c int as (a + b) virtual);")
tk.MustExec("insert into t0(a, b) values (12, -1), (8, 7);")
tk.MustExec("insert into t1(a, b) values (12, -1), (8, 7);")
tk.MustQuery("select /*+ stream_agg() */ count(1) from t0 where c > 10 and b < 2;").Check(testkit.Rows("1"))
tk.MustQuery("select /*+ stream_agg() */ count(1) from t1 where c > 10 and b < 2;").Check(testkit.Rows("1"))
tk.MustExec("delete from t0")
tk.MustExec("insert into t0(a, b) values (5, 1);")
tk.MustQuery("select /*+ nth_plan(3) */ count(1) from t0 where c > 10 and b < 2;").Check(testkit.Rows("0"))
// Should not use invisible index
require.False(t, tk.MustUseIndex("select /*+ stream_agg() */ count(1) from t0 where c > 10 and b < 2", "c"))
}
// https://github.com/pingcap/tidb/issues/23802
func TestPanicWhileQueryTableWithIsNull(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists NT_HP27193")
tk.MustExec("CREATE TABLE `NT_HP27193` ( `COL1` int(20) DEFAULT NULL, `COL2` varchar(20) DEFAULT NULL, `COL4` datetime DEFAULT NULL, `COL3` bigint(20) DEFAULT NULL, `COL5` float DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin PARTITION BY HASH ( `COL1`%`COL3` ) PARTITIONS 10;")
rs, err := tk.Exec("select col1 from NT_HP27193 where col1 is null;")
require.NoError(t, err)
rs.Close()
tk.MustExec("INSERT INTO NT_HP27193 (COL2, COL4, COL3, COL5) VALUES ('m', '2020-05-04 13:15:27', 8, 2602)")
rs, err = tk.Exec("select col1 from NT_HP27193 where col1 is null;")
require.NoError(t, err)
rs.Close()
tk.MustExec("drop table if exists NT_HP27193")
}
func TestIssue23846(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 varbinary(10),UNIQUE KEY(a))")
tk.MustExec("insert into t values(0x00A4EEF4FA55D6706ED5)")
tk.MustQuery("select count(*) from t where a=0x00A4EEF4FA55D6706ED5").Check(testkit.Rows("1"))
tk.MustQuery("select * from t where a=0x00A4EEF4FA55D6706ED5").Check(testkit.Rows("\x00\xa4\xee\xf4\xfaU\xd6pn\xd5")) // not empty
}
func TestIssue23839(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists BB")
tk.MustExec("CREATE TABLE `BB` (\n" +
" `col_int` int(11) DEFAULT NULL,\n" +
" `col_varchar_10` varchar(10) DEFAULT NULL,\n" +
" `pk` int(11) NOT NULL AUTO_INCREMENT,\n" +
" `col_int_not_null` int(11) NOT NULL,\n" +
" `col_decimal` decimal(10,0) DEFAULT NULL,\n" +
" `col_datetime` datetime DEFAULT NULL,\n" +
" `col_decimal_not_null` decimal(10,0) NOT NULL,\n" +
" `col_datetime_not_null` datetime NOT NULL,\n" +
" `col_varchar_10_not_null` varchar(10) NOT NULL,\n" +
" PRIMARY KEY (`pk`) /*T![clustered_index] CLUSTERED */\n" +
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin AUTO_INCREMENT=2000001")
tk.Exec("explain SELECT OUTR . col2 AS X FROM (SELECT INNR . col1 as col1, SUM( INNR . col2 ) as col2 FROM (SELECT INNR . `col_int_not_null` + 1 as col1, INNR . `pk` as col2 FROM BB AS INNR) AS INNR GROUP BY col1) AS OUTR2 INNER JOIN (SELECT INNR . col1 as col1, MAX( INNR . col2 ) as col2 FROM (SELECT INNR . `col_int_not_null` + 1 as col1, INNR . `pk` as col2 FROM BB AS INNR) AS INNR GROUP BY col1) AS OUTR ON OUTR2.col1 = OUTR.col1 GROUP BY OUTR . col1, OUTR2 . col1 HAVING X <> 'b'")
}
// https://github.com/pingcap/tidb/issues/24095
func TestIssue24095(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 (id int, value decimal(10,5));")
tk.MustExec("desc format = 'brief' select count(*) from t join (select t.id, t.value v1 from t join t t1 on t.id = t1.id order by t.value limit 1) v on v.id = t.id and v.v1 = t.value;")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows())
})
tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestIssue24281(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists member, agent, deposit, view_member_agents")
tk.MustExec("create table member(login varchar(50) NOT NULL, agent_login varchar(100) DEFAULT NULL, PRIMARY KEY(login))")
tk.MustExec("create table agent(login varchar(50) NOT NULL, data varchar(100) DEFAULT NULL, share_login varchar(50) NOT NULL, PRIMARY KEY(login))")
tk.MustExec("create table deposit(id varchar(50) NOT NULL, member_login varchar(50) NOT NULL, transfer_amount int NOT NULL, PRIMARY KEY(id), KEY midx(member_login, transfer_amount))")
tk.MustExec("create definer='root'@'localhost' view view_member_agents (member, share_login) as select m.login as member, a.share_login AS share_login from member as m join agent as a on m.agent_login = a.login")
tk.MustExec(" select s.member_login as v1, SUM(s.transfer_amount) AS v2 " +
"FROM deposit AS s " +
"JOIN view_member_agents AS v ON s.member_login = v.member " +
"WHERE 1 = 1 AND v.share_login = 'somevalue' " +
"GROUP BY s.member_login " +
"UNION select 1 as v1, 2 as v2")
}
func TestIssue25799(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2")
tk.MustExec(`create table t1 (a float default null, b smallint(6) DEFAULT NULL)`)
tk.MustExec(`insert into t1 values (1, 1)`)
tk.MustExec(`create table t2 (a float default null, b tinyint(4) DEFAULT NULL, key b (b))`)
tk.MustExec(`insert into t2 values (null, 1)`)
tk.HasPlan(`select /*+ TIDB_INLJ(t2@sel_2) */ t1.a, t1.b from t1 where t1.a not in (select t2.a from t2 where t1.b=t2.b)`, `IndexJoin`)
tk.MustQuery(`select /*+ TIDB_INLJ(t2@sel_2) */ t1.a, t1.b from t1 where t1.a not in (select t2.a from t2 where t1.b=t2.b)`).Check(testkit.Rows())
}
func TestLimitWindowColPrune(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)")
tk.MustExec("insert into t values(1)")
tk.MustQuery("select count(a) f1, row_number() over (order by count(a)) as f2 from t limit 1").Check(testkit.Rows("1 1"))
}
func TestIncrementalAnalyzeStatsVer2(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, b int, index idx_b(b))")
tk.MustExec("insert into t values(1,1),(2,2),(3,3)")
tk.MustExec("set @@session.tidb_analyze_version = 2")
tk.MustExec("analyze table t")
is := tk.Session().GetInfoSchema().(infoschema.InfoSchema)
tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
require.NoError(t, err)
tblID := tbl.Meta().ID
rows := tk.MustQuery(fmt.Sprintf("select distinct_count from mysql.stats_histograms where table_id = %d and is_index = 1", tblID)).Rows()
require.Len(t, rows, 1)
require.Equal(t, "3", rows[0][0])
tk.MustExec("insert into t values(4,4),(5,5),(6,6)")
tk.MustExec("analyze incremental table t index idx_b")
warns := tk.Session().GetSessionVars().StmtCtx.GetWarnings()
require.Len(t, warns, 3)
require.EqualError(t, warns[0].Err, "The version 2 would collect all statistics not only the selected indexes")
require.EqualError(t, warns[1].Err, "The version 2 stats would ignore the INCREMENTAL keyword and do full sampling")
require.EqualError(t, warns[2].Err, "Analyze use auto adjusted sample rate 1.000000 for table test.t")
rows = tk.MustQuery(fmt.Sprintf("select distinct_count from mysql.stats_histograms where table_id = %d and is_index = 1", tblID)).Rows()
require.Len(t, rows, 1)
require.Equal(t, "6", rows[0][0])
}
func TestConflictReadFromStorage(t *testing.T) {
failpoint.Enable("github.com/pingcap/tidb/planner/core/forceDynamicPrune", `return(true)`)
defer failpoint.Disable("github.com/pingcap/tidb/planner/core/forceDynamicPrune")
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, c varchar(20),
primary key(a), key(b), key(c)
) partition by range columns(a) (
partition p0 values less than(6),
partition p1 values less than(11),
partition p2 values less than(16));`)
tk.MustExec(`insert into t values (1,1,"1"), (2,2,"2"), (8,8,"8"), (11,11,"11"), (15,15,"15")`)
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustQuery(`explain select /*+ read_from_storage(tikv[t partition(p0)], tiflash[t partition(p1, p2)]) */ * from t`)
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1815 Storage hints are conflict, you can only specify one storage type of table test.t"))
tk.MustQuery(`explain select /*+ read_from_storage(tikv[t], tiflash[t]) */ * from t`)
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1815 Storage hints are conflict, you can only specify one storage type of table test.t"))
}
// TestSequenceAsDataSource is used to test https://github.com/pingcap/tidb/issues/24383.
func TestSequenceAsDataSource(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 sequence if exists s1, s2")
tk.MustExec("create sequence s1")
tk.MustExec("create sequence s2")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows())
})
tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestIssue27167(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("set names utf8mb4")
tk.MustExec("use test")
tk.MustExec("drop table if exists all_types")
tk.MustExec("CREATE TABLE `all_types` (" +
"`id` int(11) NOT NULL," +
"`d_tinyint` tinyint(4) DEFAULT NULL," +
"`d_smallint` smallint(6) DEFAULT NULL," +
"`d_int` int(11) DEFAULT NULL," +
"`d_bigint` bigint(20) DEFAULT NULL," +
"`d_float` float DEFAULT NULL," +
"`d_double` double DEFAULT NULL," +
"`d_decimal` decimal(10,2) DEFAULT NULL," +
"`d_bit` bit(10) DEFAULT NULL," +
"`d_binary` binary(10) DEFAULT NULL," +
"`d_date` date DEFAULT NULL," +
"`d_datetime` datetime DEFAULT NULL," +
"`d_timestamp` timestamp NULL DEFAULT NULL," +
"`d_varchar` varchar(20) NULL default NULL," +
"PRIMARY KEY (`id`));",
)
tk.MustQuery("select @@collation_connection;").Check(testkit.Rows("utf8mb4_bin"))
tk.MustExec(`insert into all_types values(0, 0, 1, 2, 3, 1.5, 2.2, 10.23, 12, 'xy', '2021-12-12', '2021-12-12 12:00:00', '2021-12-12 12:00:00', '123');`)
tk.MustQuery("select collation(c) from (select d_date c from all_types union select d_int c from all_types) t").Check(testkit.Rows("utf8mb4_bin", "utf8mb4_bin"))
tk.MustQuery("select collation(c) from (select d_date c from all_types union select d_int collate binary c from all_types) t").Check(testkit.Rows("binary", "binary"))
tk.MustQuery("select collation(c) from (select d_date c from all_types union select d_float c from all_types) t").Check(testkit.Rows("utf8mb4_bin", "utf8mb4_bin"))
// timestamp also OK
tk.MustQuery("select collation(c) from (select d_timestamp c from all_types union select d_float c from all_types) t").Check(testkit.Rows("utf8mb4_bin", "utf8mb4_bin"))
}
func TestIssue25300(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec(`create table t (a char(65) collate utf8_unicode_ci, b text collate utf8_general_ci not null);`)
tk.MustExec(`insert into t values ('a', 'A');`)
tk.MustExec(`insert into t values ('b', 'B');`)
tk.MustGetErrCode(`(select a from t) union ( select b from t);`, mysql.ErrCantAggregateNcollations)
tk.MustGetErrCode(`(select 'a' collate utf8mb4_unicode_ci) union (select 'b' collate utf8mb4_general_ci);`, mysql.ErrCantAggregateNcollations)
tk.MustGetErrCode(`(select a from t) union ( select b from t) union all select 'a';`, mysql.ErrCantAggregateNcollations)
tk.MustGetErrCode(`(select a from t) union ( select b from t) union select 'a';`, mysql.ErrCantAggregateNcollations)
tk.MustGetErrCode(`(select a from t) union ( select b from t) union select 'a' except select 'd';`, mysql.ErrCantAggregateNcollations)
}
func TestMergeContinuousSelections(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists ts")
tk.MustExec("create table ts (col_char_64 char(64), col_varchar_64_not_null varchar(64) not null, col_varchar_key varchar(1), id int primary key, col_varchar_64 varchar(64),col_char_64_not_null char(64) not null);")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "ts" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec(" set @@tidb_allow_mpp=1;")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestSelectIgnoreTemporaryTableInView(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "localhost", CurrentUser: true, AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890"))
tk.MustExec("create table t1 (a int, b int)")
tk.MustExec("create table t2 (c int, d int)")
tk.MustExec("create view v1 as select * from t1 order by a")
tk.MustExec("create view v2 as select * from ((select * from t1) union (select * from t2)) as tt order by a, b")
tk.MustExec("create view v3 as select * from v1 order by a")
tk.MustExec("create view v4 as select * from t1, t2 where t1.a = t2.c order by a, b")
tk.MustExec("create view v5 as select * from (select * from t1) as t1 order by a")
tk.MustExec("insert into t1 values (1, 2), (3, 4)")
tk.MustExec("insert into t2 values (3, 5), (6, 7)")
tk.MustExec("create temporary table t1 (a int, b int)")
tk.MustExec("create temporary table t2 (c int, d int)")
tk.MustQuery("select * from t1").Check(testkit.Rows())
tk.MustQuery("select * from t2").Check(testkit.Rows())
tk.MustQuery("select * from v1").Check(testkit.Rows("1 2", "3 4"))
tk.MustQuery("select * from v2").Check(testkit.Rows("1 2", "3 4", "3 5", "6 7"))
tk.MustQuery("select * from v3").Check(testkit.Rows("1 2", "3 4"))
tk.MustQuery("select * from v4").Check(testkit.Rows("3 4 3 5"))
tk.MustQuery("select * from v5").Check(testkit.Rows("1 2", "3 4"))
}
// TestIsMatchProp is used to test https://github.com/pingcap/tidb/issues/26017.
func TestIsMatchProp(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1(a int, b int, c int, d int, index idx_a_b_c(a, b, c))")
tk.MustExec("create table t2(a int, b int, c int, d int, index idx_a_b_c_d(a, b, c, d))")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows())
})
tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestIssue26250(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table tp (id int primary key) partition by range (id) (partition p0 values less than (100));")
tk.MustExec("create table tn (id int primary key);")
tk.MustExec("insert into tp values(1),(2);")
tk.MustExec("insert into tn values(1),(2);")
tk.MustQuery("select * from tp,tn where tp.id=tn.id and tn.id=1 for update;").Check(testkit.Rows("1 1"))
}
func TestCorrelationAdjustment4Limit(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 (pk int primary key auto_increment, year int, c varchar(256), index idx_year(year))")
insertWithYear := func(n, year int) {
for i := 0; i < n; i++ {
tk.MustExec(fmt.Sprintf("insert into t (year, c) values (%v, space(256))", year))
}
}
insertWithYear(10, 2000)
insertWithYear(10, 2001)
insertWithYear(10, 2002)
tk.MustExec("analyze table t")
// case 1
tk.MustExec("set @@tidb_opt_enable_correlation_adjustment = false")
// the estRow for TableFullScan is under-estimated since we have to scan through 2000 and 2001 to access 2002,
// but the formula(LimitNum / Selectivity) based on uniform-assumption cannot consider this factor.
tk.MustQuery("explain format=brief select * from t use index(primary) where year=2002 limit 1").Check(testkit.Rows(
"Limit 1.00 root offset:0, count:1",
"└─TableReader 1.00 root data:Limit",
" └─Limit 1.00 cop[tikv] offset:0, count:1",
" └─Selection 1.00 cop[tikv] eq(test.t.year, 2002)",
" └─TableFullScan 3.00 cop[tikv] table:t keep order:false"))
// case 2: after enabling correlation adjustment, this factor can be considered.
tk.MustExec("set @@tidb_opt_enable_correlation_adjustment = true")
tk.MustQuery("explain format=brief select * from t use index(primary) where year=2002 limit 1").Check(testkit.Rows(
"Limit 1.00 root offset:0, count:1",
"└─TableReader 1.00 root data:Limit",
" └─Limit 1.00 cop[tikv] offset:0, count:1",
" └─Selection 1.00 cop[tikv] eq(test.t.year, 2002)",
" └─TableFullScan 21.00 cop[tikv] table:t keep order:false"))
tk.MustExec("truncate table t")
for y := 2000; y <= 2050; y++ {
insertWithYear(2, y)
}
tk.MustExec("analyze table t")
// case 3: correlation adjustment is only allowed to update the upper-bound, so estRow = max(1/selectivity, adjustedCount);
// 1/sel = 1/(1/NDV) is around 50, adjustedCount is 1 since the first row can meet the requirement `year=2000`;
// in this case the estRow is over-estimated, but it's safer that can avoid to convert IndexScan to TableScan incorrectly in some cases.
tk.MustQuery("explain format=brief select * from t use index(primary) where year=2000 limit 1").Check(testkit.Rows(
"Limit 1.00 root offset:0, count:1",
"└─TableReader 1.00 root data:Limit",
" └─Limit 1.00 cop[tikv] offset:0, count:1",
" └─Selection 1.00 cop[tikv] eq(test.t.year, 2000)",
" └─TableFullScan 51.00 cop[tikv] table:t keep order:false"))
}
func TestCTESelfJoin(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2, t3")
tk.MustExec("create table t1(t1a int, t1b int, t1c int)")
tk.MustExec("create table t2(t2a int, t2b int, t2c int)")
tk.MustExec("create table t3(t3a int, t3b int, t3c int)")
tk.MustExec(`
with inv as
(select t1a , t3a, sum(t2c)
from t1, t2, t3
where t2a = t1a
and t2b = t3b
and t3c = 1998
group by t1a, t3a)
select inv1.t1a, inv2.t3a
from inv inv1, inv inv2
where inv1.t1a = inv2.t1a
and inv1.t3a = 4
and inv2.t3a = 4+1`)
}
// https://github.com/pingcap/tidb/issues/26214
func TestIssue26214(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(11) default null, `b` int(11) default null, `c` int(11) default null, key `expression_index` ((case when `a` < 0 then 1 else 2 end)))")
_, err := tk.Exec("select * from t where case when a < 0 then 1 else 2 end <= 1 order by 4;")
require.True(t, core.ErrUnknownColumn.Equal(err))
}
func TestCreateViewWithWindowFunc(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t6;")
tk.MustExec("CREATE TABLE t6(t TIME, ts TIMESTAMP);")
tk.MustExec("INSERT INTO t6 VALUES ('12:30', '2016-07-05 08:30:42');")
tk.MustExec("drop view if exists v;")
tk.MustExec("CREATE definer='root'@'localhost' VIEW v AS SELECT COUNT(*) OVER w0, COUNT(*) OVER w from t6 WINDOW w0 AS (), w AS (w0 ORDER BY t);")
rows := tk.MustQuery("select * from v;")
rows.Check(testkit.Rows("1 1"))
}
func TestIssue29834(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists IDT_MC21814;")
tk.MustExec("CREATE TABLE `IDT_MC21814` (`COL1` year(4) DEFAULT NULL,`COL2` year(4) DEFAULT NULL,KEY `U_M_COL` (`COL1`,`COL2`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;")
tk.MustExec("insert into IDT_MC21814 values(1901, 2119), (2155, 2000);")
tk.MustQuery("SELECT/*+ INL_JOIN(t1, t2), nth_plan(1) */ t2.* FROM IDT_MC21814 t1 LEFT JOIN IDT_MC21814 t2 ON t1.col1 = t2.col1 WHERE t2.col2 BETWEEN 2593 AND 1971 AND t1.col1 IN (2155, 1901, 1967);").Check(testkit.Rows())
tk.MustQuery("SELECT/*+ INL_JOIN(t1, t2), nth_plan(2) */ t2.* FROM IDT_MC21814 t1 LEFT JOIN IDT_MC21814 t2 ON t1.col1 = t2.col1 WHERE t2.col2 BETWEEN 2593 AND 1971 AND t1.col1 IN (2155, 1901, 1967);").Check(testkit.Rows())
// Only can generate one index join plan. Because the index join inner child can not be tableDual.
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 The parameter of nth_plan() is out of range"))
}
func TestIssue29221(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("set tidb_enable_index_merge=on;")
tk.MustExec("drop table if exists t;")
tk.MustExec("create table t(a int, b int, index idx_a(a), index idx_b(b));")
tk.MustExec("set @@session.sql_select_limit=3;")
tk.MustQuery("explain format = 'brief' select * from t where a = 1 or b = 1;").Check(testkit.Rows(
"Limit 3.00 root offset:0, count:3",
"└─IndexMerge 3.00 root type: union",
" ├─IndexRangeScan(Build) 1.50 cop[tikv] table:t, index:idx_a(a) range:[1,1], keep order:false, stats:pseudo",
" ├─IndexRangeScan(Build) 1.50 cop[tikv] table:t, index:idx_b(b) range:[1,1], keep order:false, stats:pseudo",
" └─TableRowIDScan(Probe) 3.00 cop[tikv] table:t keep order:false, stats:pseudo"))
tk.MustQuery("explain format = 'brief' select /*+ use_index_merge(t) */ * from t where a = 1 or b = 1;").Check(testkit.Rows(
"Limit 3.00 root offset:0, count:3",
"└─IndexMerge 3.00 root type: union",
" ├─IndexRangeScan(Build) 1.50 cop[tikv] table:t, index:idx_a(a) range:[1,1], keep order:false, stats:pseudo",
" ├─IndexRangeScan(Build) 1.50 cop[tikv] table:t, index:idx_b(b) range:[1,1], keep order:false, stats:pseudo",
" └─TableRowIDScan(Probe) 3.00 cop[tikv] table:t keep order:false, stats:pseudo"))
tk.MustExec("set @@session.sql_select_limit=18446744073709551615;")
tk.MustQuery("explain format = 'brief' select * from t where a = 1 or b = 1;").Check(testkit.Rows(
"IndexMerge 19.99 root type: union",
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_a(a) range:[1,1], keep order:false, stats:pseudo",
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_b(b) range:[1,1], keep order:false, stats:pseudo",
"└─TableRowIDScan(Probe) 19.99 cop[tikv] table:t keep order:false, stats:pseudo"))
tk.MustQuery("explain format = 'brief' select * from t where a = 1 or b = 1 limit 3;").Check(testkit.Rows(
"Limit 3.00 root offset:0, count:3",
"└─IndexMerge 3.00 root type: union",
" ├─IndexRangeScan(Build) 1.50 cop[tikv] table:t, index:idx_a(a) range:[1,1], keep order:false, stats:pseudo",
" ├─IndexRangeScan(Build) 1.50 cop[tikv] table:t, index:idx_b(b) range:[1,1], keep order:false, stats:pseudo",
" └─TableRowIDScan(Probe) 3.00 cop[tikv] table:t keep order:false, stats:pseudo"))
tk.MustQuery("explain format = 'brief' select /*+ use_index_merge(t) */ * from t where a = 1 or b = 1;").Check(testkit.Rows(
"IndexMerge 19.99 root type: union",
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_a(a) range:[1,1], keep order:false, stats:pseudo",
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t, index:idx_b(b) range:[1,1], keep order:false, stats:pseudo",
"└─TableRowIDScan(Probe) 19.99 cop[tikv] table:t keep order:false, stats:pseudo"))
tk.MustQuery("explain format = 'brief' select /*+ use_index_merge(t) */ * from t where a = 1 or b = 1 limit 3;").Check(testkit.Rows(
"Limit 3.00 root offset:0, count:3",
"└─IndexMerge 3.00 root type: union",
" ├─IndexRangeScan(Build) 1.50 cop[tikv] table:t, index:idx_a(a) range:[1,1], keep order:false, stats:pseudo",
" ├─IndexRangeScan(Build) 1.50 cop[tikv] table:t, index:idx_b(b) range:[1,1], keep order:false, stats:pseudo",
" └─TableRowIDScan(Probe) 3.00 cop[tikv] table:t keep order:false, stats:pseudo"))
}
func TestLimitPushDown(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)`)
tk.MustExec(`insert into t values (1)`)
tk.MustExec(`analyze table t`)
tk.MustExec(`set tidb_opt_limit_push_down_threshold=0`)
tk.MustQuery(`explain format=brief select a from t order by a desc limit 10`).Check(testkit.Rows(
`TopN 1.00 root test.t.a:desc, offset:0, count:10`,
`└─TableReader 1.00 root data:TableFullScan`,
` └─TableFullScan 1.00 cop[tikv] table:t keep order:false`))
tk.MustExec(`set tidb_opt_limit_push_down_threshold=10`)
tk.MustQuery(`explain format=brief select a from t order by a desc limit 10`).Check(testkit.Rows(
`TopN 1.00 root test.t.a:desc, offset:0, count:10`,
`└─TableReader 1.00 root data:TopN`,
` └─TopN 1.00 cop[tikv] test.t.a:desc, offset:0, count:10`,
` └─TableFullScan 1.00 cop[tikv] table:t keep order:false`))
tk.MustQuery(`explain format=brief select a from t order by a desc limit 11`).Check(testkit.Rows(
`TopN 1.00 root test.t.a:desc, offset:0, count:11`,
`└─TableReader 1.00 root data:TableFullScan`,
` └─TableFullScan 1.00 cop[tikv] table:t keep order:false`))
tk.MustQuery(`explain format=brief select /*+ limit_to_cop() */ a from t order by a desc limit 11`).Check(testkit.Rows(
`TopN 1.00 root test.t.a:desc, offset:0, count:11`,
`└─TableReader 1.00 root data:TopN`,
` └─TopN 1.00 cop[tikv] test.t.a:desc, offset:0, count:11`,
` └─TableFullScan 1.00 cop[tikv] table:t keep order:false`))
}
func TestIssue26559(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t(a timestamp, b datetime);")
tk.MustExec("insert into t values('2020-07-29 09:07:01', '2020-07-27 16:57:36');")
tk.MustQuery("select greatest(a, b) from t union select null;").Sort().Check(testkit.Rows("2020-07-29 09:07:01", "<nil>"))
}
func TestIssue29503(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
defer config.RestoreFunc()()
config.UpdateGlobal(func(conf *config.Config) {
conf.Status.RecordQPSbyDB = true
})
tk.MustExec("use test")
tk.MustExec("drop table if exists t;")
tk.MustExec("create table t(a int);")
require.NoError(t, tk.ExecToErr("create binding for select 1 using select 1;"))
require.NoError(t, tk.ExecToErr("create binding for select a from t using select a from t;"))
res := tk.MustQuery("show session bindings;")
require.Len(t, res.Rows(), 2)
}
func TestHeuristicIndexSelection(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 t1, t2")
tk.MustExec("create table t1(a int, b int, c int, d int, e int, f int, g int, primary key (a), unique key c_d_e (c, d, e), unique key f (f), unique key f_g (f, g), key g (g))")
tk.MustExec("create table t2(a int, b int, c int, d int, unique index idx_a (a), unique index idx_b_c (b, c), unique index idx_b_c_a_d (b, c, a, d))")
tk.MustExec("create table t3(a bigint, b varchar(255), c bigint, primary key(a, b) clustered)")
tk.MustExec("create table t4(a bigint, b varchar(255), c bigint, primary key(a, b) nonclustered)")
// Default RPC encoding may cause statistics explain result differ and then the test unstable.
tk.MustExec("set @@tidb_enable_chunk_rpc = on")
var input []string
var output []struct {
SQL string
Plan []string
Warnings []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'verbose' " + tt).Rows())
output[i].Warnings = testdata.ConvertRowsToStrings(tk.MustQuery("show warnings").Rows())
})
tk.MustQuery("explain format = 'verbose' " + tt).Check(testkit.Rows(output[i].Plan...))
tk.MustQuery("show warnings").Check(testkit.Rows(output[i].Warnings...))
}
}
func TestOutputSkylinePruningInfo(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, b int, c int, d int, e int, f int, g int, primary key (a), unique key c_d_e (c, d, e), unique key f (f), unique key f_g (f, g), key g (g))")
// Default RPC encoding may cause statistics explain result differ and then the test unstable.
tk.MustExec("set @@tidb_enable_chunk_rpc = on")
var input []string
var output []struct {
SQL string
Plan []string
Warnings []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'verbose' " + tt).Rows())
output[i].Warnings = testdata.ConvertRowsToStrings(tk.MustQuery("show warnings").Rows())
})
tk.MustQuery("explain format = 'verbose' " + tt).Check(testkit.Rows(output[i].Plan...))
tk.MustQuery("show warnings").Check(testkit.Rows(output[i].Warnings...))
}
}
func TestPreferRangeScanForUnsignedIntHandle(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 unsigned primary key, b int, c int, index idx_b(b))")
tk.MustExec("insert into t values (1,2,3), (4,5,6), (7,8,9), (10,11,12), (13,14,15)")
do, _ := session.GetDomain(store)
require.Nil(t, do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll))
tk.MustExec("analyze table t")
// Default RPC encoding may cause statistics explain result differ and then the test unstable.
tk.MustExec("set @@tidb_enable_chunk_rpc = on")
var input []string
var output []struct {
SQL string
Plan []string
Warnings []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
})
if strings.HasPrefix(tt, "set") {
tk.MustExec(tt)
continue
}
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
output[i].Warnings = testdata.ConvertRowsToStrings(tk.MustQuery("show warnings").Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
tk.MustQuery("show warnings").Check(testkit.Rows(output[i].Warnings...))
}
}
func TestIssue27083(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, b int, c int, index idx_b(b))")
tk.MustExec("insert into t values (1,2,3), (4,5,6), (7,8,9), (10, 11, 12), (13,14,15), (16, 17, 18)")
do, _ := session.GetDomain(store)
require.Nil(t, do.StatsHandle().DumpStatsDeltaToKV(handle.DumpAll))
tk.MustExec("analyze table t")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows())
})
tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestIssues27130(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("set tidb_cost_model_version=2")
tk.MustExec("create table t1( a enum('y','b','Abc','null'),b enum('y','b','Abc','null'),key(a));")
tk.MustQuery(`explain format=brief select * from t1 where a like "A%"`).Check(testkit.Rows(
"TableReader 8000.00 root data:Selection",
"└─Selection 8000.00 cop[tikv] like(test.t1.a, \"A%\", 92)",
" └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
))
tk.MustQuery(`explain format=brief select * from t1 where b like "A%"`).Check(testkit.Rows(
"TableReader 8000.00 root data:Selection",
"└─Selection 8000.00 cop[tikv] like(test.t1.b, \"A%\", 92)",
" └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
))
tk.MustExec("drop table if exists t2")
tk.MustExec("create table t2( a enum('y','b','Abc','null'),b enum('y','b','Abc','null'),key(a, b));")
tk.MustQuery(`explain format=brief select * from t2 where a like "A%"`).Check(testkit.Rows(
"IndexReader 8000.00 root index:Selection",
"└─Selection 8000.00 cop[tikv] like(test.t2.a, \"A%\", 92)",
" └─IndexFullScan 10000.00 cop[tikv] table:t2, index:a(a, b) keep order:false, stats:pseudo",
))
tk.MustQuery(`explain format=brief select * from t2 where a like "A%" and b like "A%"`).Check(testkit.Rows(
"IndexReader 8000.00 root index:Selection",
"└─Selection 8000.00 cop[tikv] like(test.t2.a, \"A%\", 92), like(test.t2.b, \"A%\", 92)",
" └─IndexFullScan 10000.00 cop[tikv] table:t2, index:a(a, b) keep order:false, stats:pseudo",
))
tk.MustExec("drop table if exists t3")
tk.MustExec("create table t3( a int,b enum('y','b','Abc','null'), c enum('y','b','Abc','null'),key(a, b, c));")
tk.MustQuery(`explain format=brief select * from t3 where a = 1 and b like "A%"`).Check(testkit.Rows(
"IndexReader 8.00 root index:Selection",
"└─Selection 8.00 cop[tikv] like(test.t3.b, \"A%\", 92)",
" └─IndexRangeScan 10.00 cop[tikv] table:t3, index:a(a, b, c) range:[1,1], keep order:false, stats:pseudo",
))
}
func TestIssue27242(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists UK_MU16407")
tk.MustExec("CREATE TABLE UK_MU16407 (COL3 timestamp NULL DEFAULT NULL, UNIQUE KEY U3(COL3));")
defer tk.MustExec("DROP TABLE UK_MU16407")
tk.MustExec(`insert into UK_MU16407 values("1985-08-31 18:03:27");`)
tk.MustExec(`SELECT COL3 FROM UK_MU16407 WHERE COL3>_utf8mb4'2039-1-19 3:14:40';`)
}
func verifyTimestampOutOfRange(tk *testkit.TestKit) {
tk.MustQuery(`select * from t28424 where t != "2038-1-19 3:14:08"`).Sort().Check(testkit.Rows("1970-01-01 00:00:01]\n[2038-01-19 03:14:07"))
tk.MustQuery(`select * from t28424 where t < "2038-1-19 3:14:08"`).Sort().Check(testkit.Rows("1970-01-01 00:00:01]\n[2038-01-19 03:14:07"))
tk.MustQuery(`select * from t28424 where t <= "2038-1-19 3:14:08"`).Sort().Check(testkit.Rows("1970-01-01 00:00:01]\n[2038-01-19 03:14:07"))
tk.MustQuery(`select * from t28424 where t >= "2038-1-19 3:14:08"`).Check(testkit.Rows())
tk.MustQuery(`select * from t28424 where t > "2038-1-19 3:14:08"`).Check(testkit.Rows())
tk.MustQuery(`select * from t28424 where t != "1970-1-1 0:0:0"`).Sort().Check(testkit.Rows("1970-01-01 00:00:01]\n[2038-01-19 03:14:07"))
tk.MustQuery(`select * from t28424 where t < "1970-1-1 0:0:0"`).Check(testkit.Rows())
tk.MustQuery(`select * from t28424 where t <= "1970-1-1 0:0:0"`).Check(testkit.Rows())
tk.MustQuery(`select * from t28424 where t >= "1970-1-1 0:0:0"`).Sort().Check(testkit.Rows("1970-01-01 00:00:01]\n[2038-01-19 03:14:07"))
tk.MustQuery(`select * from t28424 where t > "1970-1-1 0:0:0"`).Sort().Check(testkit.Rows("1970-01-01 00:00:01]\n[2038-01-19 03:14:07"))
}
func TestIssue28424(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t28424, dt28242")
tk.MustExec(`set time_zone='+00:00'`)
tk.MustExec(`drop table if exists t28424,dt28424`)
tk.MustExec(`create table t28424 (t timestamp)`)
defer tk.MustExec("DROP TABLE t28424")
tk.MustExec(`insert into t28424 values ("2038-01-19 03:14:07"), ("1970-01-01 00:00:01")`)
verifyTimestampOutOfRange(tk)
tk.MustExec(`alter table t28424 add unique index (t)`)
verifyTimestampOutOfRange(tk)
tk.MustExec(`create table dt28424 (dt datetime)`)
defer tk.MustExec("DROP TABLE dt28424")
tk.MustExec(`insert into dt28424 values ("2038-01-19 03:14:07"), ("1970-01-01 00:00:01")`)
tk.MustExec(`insert into dt28424 values ("1969-12-31 23:59:59"), ("1970-01-01 00:00:00"), ("2038-03-19 03:14:08")`)
tk.MustQuery(`select * from t28424 right join dt28424 on t28424.t = dt28424.dt`).Sort().Check(testkit.Rows(
"1970-01-01 00:00:01 1970-01-01 00:00:01]\n" +
"[2038-01-19 03:14:07 2038-01-19 03:14:07]\n" +
"[<nil> 1969-12-31 23:59:59]\n" +
"[<nil> 1970-01-01 00:00:00]\n" +
"[<nil> 2038-03-19 03:14:08"))
}
func TestTemporaryTableForCte(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create temporary table tmp1(a int, b int, c int);")
tk.MustExec("insert into tmp1 values (1,1,1),(2,2,2),(3,3,3),(4,4,4);")
rows := tk.MustQuery("with cte1 as (with cte2 as (select * from tmp1) select * from cte2) select * from cte1 left join tmp1 on cte1.c=tmp1.c;")
rows.Check(testkit.Rows("1 1 1 1 1 1", "2 2 2 2 2 2", "3 3 3 3 3 3", "4 4 4 4 4 4"))
rows = tk.MustQuery("with cte1 as (with cte2 as (select * from tmp1) select * from cte2) select * from cte1 t1 left join cte1 t2 on t1.c=t2.c;")
rows.Check(testkit.Rows("1 1 1 1 1 1", "2 2 2 2 2 2", "3 3 3 3 3 3", "4 4 4 4 4 4"))
rows = tk.MustQuery("WITH RECURSIVE cte(a) AS (SELECT 1 UNION SELECT a+1 FROM tmp1 WHERE a < 5) SELECT * FROM cte order by a;")
rows.Check(testkit.Rows("1", "2", "3", "4", "5"))
}
func TestGroupBySetVar(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(c1 int);")
tk.MustExec("insert into t1 values(1), (2), (3), (4), (5), (6);")
rows := tk.MustQuery("select floor(dt.rn/2) rownum, count(c1) from (select @rownum := @rownum + 1 rn, c1 from (select @rownum := -1) drn, t1) dt group by floor(dt.rn/2) order by rownum;")
rows.Check(testkit.Rows("0 2", "1 2", "2 2"))
tk.MustExec("create table ta(a int, b int);")
tk.MustExec("set sql_mode='';")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
res := tk.MustQuery("explain format = 'brief' " + tt)
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(res.Rows())
})
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestPushDownGroupConcatToTiFlash(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists ts")
tk.MustExec("create table ts (col_0 char(64), col_1 varchar(64) not null, col_2 varchar(1), id int primary key);")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "ts" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set @@tidb_isolation_read_engines='tiflash,tidb'; set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;")
var input []string
var output []struct {
SQL string
Plan []string
Warning []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
comment := fmt.Sprintf("case:%v sql:%s", i, tt)
warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings()
testdata.OnRecord(func() {
if len(warnings) > 0 {
output[i].Warning = make([]string, len(warnings))
for j, warning := range warnings {
output[i].Warning[j] = warning.Err.Error()
}
}
})
if len(output[i].Warning) == 0 {
require.Len(t, warnings, 0, comment)
} else {
require.Len(t, warnings, len(output[i].Warning), comment)
for j, warning := range warnings {
require.Equal(t, stmtctx.WarnLevelWarning, warning.Level, comment)
require.EqualError(t, warning.Err, output[i].Warning[j], comment)
}
}
}
}
func TestIssue27797(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
origin := tk.MustQuery("SELECT @@session.tidb_partition_prune_mode")
originStr := origin.Rows()[0][0].(string)
defer func() {
tk.MustExec("set @@session.tidb_partition_prune_mode = '" + originStr + "'")
}()
tk.MustExec("set @@session.tidb_partition_prune_mode = 'static'")
tk.MustExec("use test")
tk.MustExec("drop table if exists t27797")
tk.MustExec("create table t27797(a int, b int, c int, d int) " +
"partition by range columns(d) (" +
"partition p0 values less than (20)," +
"partition p1 values less than(40)," +
"partition p2 values less than(60));")
tk.MustExec("insert into t27797 values(1,1,1,1), (2,2,2,2), (22,22,22,22), (44,44,44,44);")
tk.MustExec("set sql_mode='';")
result := tk.MustQuery("select count(*) from (select a, b from t27797 where d > 1 and d < 60 and b > 0 group by b, c) tt;")
result.Check(testkit.Rows("3"))
tk.MustExec("drop table if exists IDT_HP24172")
tk.MustExec("CREATE TABLE `IDT_HP24172` ( " +
"`COL1` mediumint(16) DEFAULT NULL, " +
"`COL2` varchar(20) DEFAULT NULL, " +
"`COL4` datetime DEFAULT NULL, " +
"`COL3` bigint(20) DEFAULT NULL, " +
"`COL5` float DEFAULT NULL, " +
"KEY `UM_COL` (`COL1`,`COL3`) " +
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin " +
"PARTITION BY HASH( `COL1`+`COL3` ) " +
"PARTITIONS 8;")
tk.MustExec("insert into IDT_HP24172(col1) values(8388607);")
result = tk.MustQuery("select col2 from IDT_HP24172 where col1 = 8388607 and col1 in (select col1 from IDT_HP24172);")
result.Check(testkit.Rows("<nil>"))
}
func TestIssue27949(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t27949")
tk.MustExec("create table t27949 (a int, b int, key(b))")
tk.MustQuery("explain format = 'brief' select * from t27949 where b=1").Check(testkit.Rows("IndexLookUp 10.00 root ",
"├─IndexRangeScan(Build) 10.00 cop[tikv] table:t27949, index:b(b) range:[1,1], keep order:false, stats:pseudo",
"└─TableRowIDScan(Probe) 10.00 cop[tikv] table:t27949 keep order:false, stats:pseudo"))
tk.MustExec("create global binding for select * from t27949 where b=1 using select * from t27949 ignore index(b) where b=1")
tk.MustQuery("explain format = 'brief' select * from t27949 where b=1").Check(testkit.Rows("TableReader 10.00 root data:Selection",
"└─Selection 10.00 cop[tikv] eq(test.t27949.b, 1)",
" └─TableFullScan 10000.00 cop[tikv] table:t27949 keep order:false, stats:pseudo"))
tk.MustExec("set @@sql_select_limit=100")
tk.MustQuery("explain format = 'brief' select * from t27949 where b=1").Check(testkit.Rows("Limit 10.00 root offset:0, count:100",
"└─TableReader 10.00 root data:Limit",
" └─Limit 10.00 cop[tikv] offset:0, count:100",
" └─Selection 10.00 cop[tikv] eq(test.t27949.b, 1)",
" └─TableFullScan 10000.00 cop[tikv] table:t27949 keep order:false, stats:pseudo"))
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int, index idx_a(a));")
tk.MustExec("create binding for select * from t using select * from t use index(idx_a);")
tk.MustExec("select * from t;")
tk.MustQuery("select @@last_plan_from_binding;").Check(testkit.Rows("1"))
tk.MustExec("prepare stmt from 'select * from t';")
tk.MustExec("execute stmt;")
tk.MustQuery("select @@last_plan_from_binding;").Check(testkit.Rows("1"))
}
func TestIssue28154(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
defer func() {
tk.MustExec("drop table if exists t")
}()
tk.MustExec("create table t(a TEXT)")
tk.MustExec("insert into t values('abc')")
result := tk.MustQuery("select * from t where from_base64('')")
result.Check(testkit.Rows())
_, err := tk.Exec("update t set a = 'def' where from_base64('')")
require.EqualError(t, err, "[types:1292]Truncated incorrect DOUBLE value: ''")
result = tk.MustQuery("select * from t where from_base64('invalidbase64')")
result.Check(testkit.Rows())
tk.MustExec("update t set a = 'hig' where from_base64('invalidbase64')")
result = tk.MustQuery("select * from t where from_base64('test')")
result.Check(testkit.Rows())
_, err = tk.Exec("update t set a = 'xyz' where from_base64('test')")
require.Error(t, err)
require.Regexp(t, "\\[types:1292\\]Truncated incorrect DOUBLE value.*", err.Error())
result = tk.MustQuery("select * from t")
result.Check(testkit.Rows("abc"))
}
func TestRejectSortForMPP(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 (id int, value decimal(6,3), name char(128))")
tk.MustExec("analyze table t")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;")
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
res := tk.MustQuery(tt)
res.Check(testkit.Rows(output[i].Plan...))
}
}
func TestRegardNULLAsPoint(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists tpk")
tk.MustExec(`create table tuk (a int, b int, c int, unique key (a, b, c))`)
tk.MustExec(`create table tik (a int, b int, c int, key (a, b, c))`)
for _, va := range []string{"NULL", "1"} {
for _, vb := range []string{"NULL", "1"} {
for _, vc := range []string{"NULL", "1"} {
tk.MustExec(fmt.Sprintf(`insert into tuk values (%v, %v, %v)`, va, vb, vc))
tk.MustExec(fmt.Sprintf(`insert into tik values (%v, %v, %v)`, va, vb, vc))
if va == "1" && vb == "1" && vc == "1" {
continue
}
// duplicated NULL rows
tk.MustExec(fmt.Sprintf(`insert into tuk values (%v, %v, %v)`, va, vb, vc))
tk.MustExec(fmt.Sprintf(`insert into tik values (%v, %v, %v)`, va, vb, vc))
}
}
}
var input []string
var output []struct {
SQL string
PlanEnabled []string
PlanDisabled []string
Result []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
tk.MustExec(`set @@session.tidb_regard_null_as_point=true`)
output[i].PlanEnabled = testdata.ConvertRowsToStrings(tk.MustQuery("explain " + tt).Rows())
output[i].Result = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
tk.MustExec(`set @@session.tidb_regard_null_as_point=false`)
output[i].PlanDisabled = testdata.ConvertRowsToStrings(tk.MustQuery("explain " + tt).Rows())
})
tk.MustExec(`set @@session.tidb_regard_null_as_point=true`)
tk.MustQuery("explain " + tt).Check(testkit.Rows(output[i].PlanEnabled...))
tk.MustQuery(tt).Check(testkit.Rows(output[i].Result...))
tk.MustExec(`set @@session.tidb_regard_null_as_point=false`)
tk.MustQuery("explain " + tt).Check(testkit.Rows(output[i].PlanDisabled...))
tk.MustQuery(tt).Check(testkit.Rows(output[i].Result...))
}
}
func TestIssues29711(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists tbl_29711")
tk.MustExec("CREATE TABLE `tbl_29711` (" +
"`col_250` text COLLATE utf8_unicode_ci NOT NULL," +
"`col_251` enum('Alice','Bob','Charlie','David') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'Charlie'," +
"PRIMARY KEY (`col_251`,`col_250`(1)) NONCLUSTERED);")
tk.MustQuery("explain format=brief " +
"select col_250,col_251 from tbl_29711 where col_251 between 'Bob' and 'David' order by col_250,col_251 limit 6;").
Check(testkit.Rows(
"TopN 6.00 root test.tbl_29711.col_250, test.tbl_29711.col_251, offset:0, count:6",
"└─IndexLookUp 6.00 root ",
" ├─IndexRangeScan(Build) 30.00 cop[tikv] table:tbl_29711, index:PRIMARY(col_251, col_250) range:[\"Bob\",\"Bob\"], [\"Charlie\",\"Charlie\"], [\"David\",\"David\"], keep order:false, stats:pseudo",
" └─TopN(Probe) 6.00 cop[tikv] test.tbl_29711.col_250, test.tbl_29711.col_251, offset:0, count:6",
" └─TableRowIDScan 30.00 cop[tikv] table:tbl_29711 keep order:false, stats:pseudo",
))
tk.MustExec("drop table if exists t29711")
tk.MustExec("CREATE TABLE `t29711` (" +
"`a` varchar(10) DEFAULT NULL," +
"`b` int(11) DEFAULT NULL," +
"`c` int(11) DEFAULT NULL," +
"KEY `ia` (`a`(2)))")
tk.MustQuery("explain format=brief select * from t29711 use index (ia) order by a limit 10;").
Check(testkit.Rows(
"TopN 10.00 root test.t29711.a, offset:0, count:10",
"└─IndexLookUp 10.00 root ",
" ├─IndexFullScan(Build) 10000.00 cop[tikv] table:t29711, index:ia(a) keep order:false, stats:pseudo",
" └─TopN(Probe) 10.00 cop[tikv] test.t29711.a, offset:0, count:10",
" └─TableRowIDScan 10000.00 cop[tikv] table:t29711 keep order:false, stats:pseudo",
))
}
func TestIssue27313(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 varchar(100), b int, c int, index idx1(a(2), b), index idx2(a))")
tk.MustExec("explain format = 'verbose' select * from t where a = 'abcdefghijk' and b > 4")
// no warning indicates that idx2 is not pruned by idx1.
tk.MustQuery("show warnings").Check(testkit.Rows())
}
func TestIssue30094(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec(`drop table if exists t30094;`)
tk.MustExec(`create table t30094(a varchar(10));`)
tk.MustQuery(`explain format = 'brief' select * from t30094 where cast(a as float) and cast(a as char);`).Check(testkit.Rows(
"TableReader 8000.00 root data:Selection",
"└─Selection 8000.00 cop[tikv] cast(test.t30094.a, float BINARY), cast(test.t30094.a, var_string(5))",
" └─TableFullScan 10000.00 cop[tikv] table:t30094 keep order:false, stats:pseudo",
))
tk.MustQuery(`explain format = 'brief' select * from t30094 where concat(a,'1') = _binary 0xe59388e59388e59388 collate binary and concat(a,'1') = _binary 0xe598bfe598bfe598bf collate binary;`).Check(testkit.Rows(
"TableReader 8000.00 root data:Selection",
"└─Selection 8000.00 cop[tikv] eq(concat(test.t30094.a, \"1\"), \"0xe59388e59388e59388\"), eq(concat(test.t30094.a, \"1\"), \"0xe598bfe598bfe598bf\")",
" └─TableFullScan 10000.00 cop[tikv] table:t30094 keep order:false, stats:pseudo",
))
}
func TestIssue30200(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(c1 varchar(100), c2 varchar(100), key(c1), key(c2), c3 varchar(100));")
tk.MustExec("insert into t1 values('ab', '10', '10');")
tk.MustExec("drop table if exists tt1;")
tk.MustExec("create table tt1(c1 varchar(100), c2 varchar(100), c3 varchar(100), c4 varchar(100), key idx_0(c1), key idx_1(c2, c3));")
tk.MustExec("insert into tt1 values('ab', '10', '10', '10');")
tk.MustExec("drop table if exists tt2;")
tk.MustExec("create table tt2 (c1 int , pk int, primary key( pk ) , unique key( c1));")
tk.MustExec("insert into tt2 values(-3896405, -1), (-2, 1), (-1, -2);")
tk.MustExec("drop table if exists tt3;")
tk.MustExec("create table tt3(c1 int, c2 int, c3 int as (c1 + c2), key(c1), key(c2), key(c3));")
tk.MustExec("insert into tt3(c1, c2) values(1, 1);")
oriIndexMergeSwitcher := tk.MustQuery("select @@tidb_enable_index_merge;").Rows()[0][0].(string)
tk.MustExec("set tidb_enable_index_merge = on;")
defer func() {
tk.MustExec(fmt.Sprintf("set tidb_enable_index_merge = %s;", oriIndexMergeSwitcher))
}()
var input []string
var output []struct {
SQL string
Plan []string
Res []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format=brief " + tt).Rows())
output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery("explain format=brief " + tt).Check(testkit.Rows(output[i].Plan...))
tk.MustQuery(tt).Check(testkit.Rows(output[i].Res...))
}
}
func TestIssue29705(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
origin := tk.MustQuery("SELECT @@session.tidb_partition_prune_mode")
originStr := origin.Rows()[0][0].(string)
defer func() {
tk.MustExec("set @@session.tidb_partition_prune_mode = '" + originStr + "'")
}()
tk.MustExec("set @@session.tidb_partition_prune_mode = 'static'")
tk.MustExec("use test")
tk.MustExec("drop table if exists t;")
tk.MustExec("create table t(id int) partition by hash(id) partitions 4;")
tk.MustExec("insert into t values(1);")
result := tk.MustQuery("SELECT COUNT(1) FROM ( SELECT COUNT(1) FROM t b GROUP BY id) a;")
result.Check(testkit.Rows("1"))
}
func TestIssue30271(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 char(10), b char(10), c char(10), index (a, b, c)) collate utf8mb4_bin;")
tk.MustExec("insert into t values ('b', 'a', '1'), ('b', 'A', '2'), ('c', 'a', '3');")
tk.MustExec("set names utf8mb4 collate utf8mb4_general_ci;")
tk.MustQuery("select * from t where (a>'a' and b='a') or (b = 'A' and a < 'd') order by a,c;").Check(testkit.Rows("b a 1", "b A 2", "c a 3"))
}
func TestIssue30804(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1(a int, b int)")
tk.MustExec("create table t2(a int, b int)")
// minimal reproduction of https://github.com/pingcap/tidb/issues/30804
tk.MustExec("select avg(0) over w from t1 window w as (order by (select 1))")
// named window cannot be used in subquery
err := tk.ExecToErr("select avg(0) over w from t1 where b > (select sum(t2.a) over w from t2) window w as (partition by t1.b)")
require.True(t, core.ErrWindowNoSuchWindow.Equal(err))
tk.MustExec("select avg(0) over w1 from t1 where b > (select sum(t2.a) over w2 from t2 window w2 as (partition by t2.b)) window w1 as (partition by t1.b)")
}
func TestIndexMergeWarning(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(c1 int, c2 int)")
tk.MustExec("select /*+ use_index_merge(t1) */ * from t1 where c1 < 1 or c2 < 1")
warningMsg := "Warning 1105 IndexMerge is inapplicable or disabled. No available filter or available index."
tk.MustQuery("show warnings").Check(testkit.Rows(warningMsg))
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t1(c1 int, c2 int, key(c1), key(c2))")
tk.MustExec("select /*+ use_index_merge(t1), no_index_merge() */ * from t1 where c1 < 1 or c2 < 1")
warningMsg = "Warning 1105 IndexMerge is inapplicable or disabled. Got no_index_merge hint or tidb_enable_index_merge is off."
tk.MustQuery("show warnings").Check(testkit.Rows(warningMsg))
tk.MustExec("drop table if exists t1")
tk.MustExec("create temporary table t1(c1 int, c2 int, key(c1), key(c2))")
tk.MustExec("select /*+ use_index_merge(t1) */ * from t1 where c1 < 1 or c2 < 1")
warningMsg = "Warning 1105 IndexMerge is inapplicable or disabled. Cannot use IndexMerge on temporary table."
tk.MustQuery("show warnings").Check(testkit.Rows(warningMsg))
}
func TestIndexMergeWithCorrelatedColumns(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 t1, t2;")
tk.MustExec("create table t1(c1 int, c2 int, c3 int, primary key(c1), key(c2));")
tk.MustExec("insert into t1 values(1, 1, 1);")
tk.MustExec("insert into t1 values(2, 2, 2);")
tk.MustExec("create table t2(c1 int, c2 int, c3 int);")
tk.MustExec("insert into t2 values(1, 1, 1);")
tk.MustExec("insert into t2 values(2, 2, 2);")
tk.MustExec("drop table if exists tt1, tt2;")
tk.MustExec("create table tt1 (c_int int, c_str varchar(40), c_datetime datetime, c_decimal decimal(12, 6), primary key(c_int), key(c_int), key(c_str), unique key(c_decimal), key(c_datetime));")
tk.MustExec("create table tt2 like tt1 ;")
tk.MustExec(`insert into tt1 (c_int, c_str, c_datetime, c_decimal) values (6, 'sharp payne', '2020-06-07 10:40:39', 6.117000) ,
(7, 'objective kare', '2020-02-05 18:47:26', 1.053000) ,
(8, 'thirsty pasteur', '2020-01-02 13:06:56', 2.506000) ,
(9, 'blissful wilbur', '2020-06-04 11:34:04', 9.144000) ,
(10, 'reverent mclean', '2020-02-12 07:36:26', 7.751000) ;`)
tk.MustExec(`insert into tt2 (c_int, c_str, c_datetime, c_decimal) values (6, 'beautiful joliot', '2020-01-16 01:44:37', 5.627000) ,
(7, 'hopeful blackburn', '2020-05-23 21:44:20', 7.890000) ,
(8, 'ecstatic davinci', '2020-02-01 12:27:17', 5.648000) ,
(9, 'hopeful lewin', '2020-05-05 05:58:25', 7.288000) ,
(10, 'sharp jennings', '2020-01-28 04:35:03', 9.758000) ;`)
var input []string
var output []struct {
SQL string
Plan []string
Res []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format=brief " + tt).Rows())
output[i].Res = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery("explain format=brief " + tt).Check(testkit.Rows(output[i].Plan...))
tk.MustQuery(tt).Check(testkit.Rows(output[i].Res...))
}
}
func TestIssue20510(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("CREATE TABLE t1 (a int PRIMARY KEY, b int)")
tk.MustExec("CREATE TABLE t2 (a int PRIMARY KEY, b int)")
tk.MustExec("INSERT INTO t1 VALUES (1,1), (2,1), (3,1), (4,2)")
tk.MustExec("INSERT INTO t2 VALUES (1,2), (2,2)")
tk.MustQuery("explain format=brief SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.a WHERE not(0+(t1.a=30 and t2.b=1));").Check(testkit.Rows(
"Selection 8000.00 root not(plus(0, and(eq(test.t1.a, 30), eq(test.t2.b, 1))))",
"└─MergeJoin 10000.00 root left outer join, left key:test.t1.a, right key:test.t2.a",
" ├─TableReader(Build) 8000.00 root data:Selection",
" │ └─Selection 8000.00 cop[tikv] not(istrue_with_null(plus(0, and(eq(test.t2.a, 30), eq(test.t2.b, 1)))))",
" │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
" └─TableReader(Probe) 10000.00 root data:TableFullScan",
" └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:true, stats:pseudo"))
tk.MustQuery("SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.a WHERE not(0+(t1.a=30 and t2.b=1));").Check(testkit.Rows(
"1 1 1 2",
"2 1 2 2",
"3 1 <nil> <nil>",
"4 2 <nil> <nil>",
))
}
func TestIssue31035(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(c1 longtext, c2 decimal(37, 4), unique key(c1(10)), unique key(c2));")
tk.MustExec("insert into t1 values('眐', -962541614831459.7458);")
tk.MustQuery("select * from t1 order by c2 + 10;").Check(testkit.Rows("眐 -962541614831459.7458"))
}
// TestDNFCondSelectivityWithConst test selectivity calculation with DNF conditions with one is const.
// Close https://github.com/pingcap/tidb/issues/31096
func TestDNFCondSelectivityWithConst(t *testing.T) {
store := testkit.CreateMockStore(t)
testKit := testkit.NewTestKit(t, store)
testKit.MustExec("use test")
testKit.MustExec("drop table if exists t1")
testKit.MustExec("create table t1(a int, b int, c int);")
testKit.MustExec("insert into t1 value(10,10,10)")
for i := 0; i < 7; i++ {
testKit.MustExec("insert into t1 select * from t1")
}
testKit.MustExec("insert into t1 value(1,1,1)")
testKit.MustExec("analyze table t1")
testKit.MustQuery("explain format = 'brief' select * from t1 where a=1 or b=1;").Check(testkit.Rows(
"TableReader 1.99 root data:Selection",
"└─Selection 1.99 cop[tikv] or(eq(test.t1.a, 1), eq(test.t1.b, 1))",
" └─TableFullScan 129.00 cop[tikv] table:t1 keep order:false"))
testKit.MustQuery("explain format = 'brief' select * from t1 where 0=1 or a=1 or b=1;").Check(testkit.Rows(
"TableReader 1.99 root data:Selection",
"└─Selection 1.99 cop[tikv] or(0, or(eq(test.t1.a, 1), eq(test.t1.b, 1)))",
" └─TableFullScan 129.00 cop[tikv] table:t1 keep order:false"))
testKit.MustQuery("explain format = 'brief' select * from t1 where null or a=1 or b=1;").Check(testkit.Rows(
"TableReader 1.99 root data:Selection",
"└─Selection 1.99 cop[tikv] or(0, or(eq(test.t1.a, 1), eq(test.t1.b, 1)))",
" └─TableFullScan 129.00 cop[tikv] table:t1 keep order:false"))
testKit.MustQuery("explain format = 'brief' select * from t1 where a=1 or false or b=1;").Check(testkit.Rows(
"TableReader 1.99 root data:Selection",
"└─Selection 1.99 cop[tikv] or(eq(test.t1.a, 1), or(0, eq(test.t1.b, 1)))",
" └─TableFullScan 129.00 cop[tikv] table:t1 keep order:false"))
testKit.MustQuery("explain format = 'brief' select * from t1 where a=1 or b=1 or \"false\";").Check(testkit.Rows(
"TableReader 1.99 root data:Selection",
"└─Selection 1.99 cop[tikv] or(eq(test.t1.a, 1), or(eq(test.t1.b, 1), 0))",
" └─TableFullScan 129.00 cop[tikv] table:t1 keep order:false"))
testKit.MustQuery("explain format = 'brief' select * from t1 where 1=1 or a=1 or b=1;").Check(testkit.Rows(
"TableReader 129.00 root data:Selection",
"└─Selection 129.00 cop[tikv] or(1, or(eq(test.t1.a, 1), eq(test.t1.b, 1)))",
" └─TableFullScan 129.00 cop[tikv] table:t1 keep order:false"))
testKit.MustQuery("explain format = 'brief' select * from t1 where a=1 or b=1 or 1=1;").Check(testkit.Rows(
"TableReader 129.00 root data:Selection",
"└─Selection 129.00 cop[tikv] or(eq(test.t1.a, 1), or(eq(test.t1.b, 1), 1))",
" └─TableFullScan 129.00 cop[tikv] table:t1 keep order:false"))
testKit.MustExec("drop table if exists t1")
}
func TestIssue31202(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t31202(a int primary key, b int);")
tbl, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t31202", L: "t31202"})
require.NoError(t, err)
// Set the hacked TiFlash replica for explain tests.
tbl.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true}
tk.MustQuery("explain format = 'brief' select * from t31202;").Check(testkit.Rows(
"TableReader 10000.00 root data:ExchangeSender",
"└─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough",
" └─TableFullScan 10000.00 mpp[tiflash] table:t31202 keep order:false, stats:pseudo"))
tk.MustQuery("explain format = 'brief' select * from t31202 use index (primary);").Check(testkit.Rows(
"TableReader 10000.00 root data:TableFullScan",
"└─TableFullScan 10000.00 cop[tikv] table:t31202 keep order:false, stats:pseudo"))
tk.MustExec("drop table if exists t31202")
}
func TestNaturalJoinUpdateSameTable(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("create database natural_join_update")
defer tk.MustExec("drop database natural_join_update")
tk.MustExec("use natural_join_update")
tk.MustExec("create table t1(a int, b int)")
tk.MustExec("insert into t1 values (1,1),(2,2)")
tk.MustExec("update t1 as a natural join t1 b SET a.a = 2, b.b = 3")
tk.MustQuery("select * from t1").Sort().Check(testkit.Rows("2 3", "2 3"))
tk.MustExec("drop table t1")
tk.MustExec("create table t1 (a int primary key, b int)")
tk.MustExec("insert into t1 values (1,1),(2,2)")
tk.MustGetErrCode(`update t1 as a natural join t1 b SET a.a = 2, b.b = 3`, mysql.ErrMultiUpdateKeyConflict)
tk.MustExec("drop table t1")
tk.MustExec("create table t1 (a int, b int) partition by hash (a) partitions 3")
tk.MustExec("insert into t1 values (1,1),(2,2)")
tk.MustGetErrCode(`update t1 as a natural join t1 b SET a.a = 2, b.b = 3`, mysql.ErrMultiUpdateKeyConflict)
tk.MustExec("drop table t1")
tk.MustExec("create table t1 (A int, b int) partition by hash (b) partitions 3")
tk.MustExec("insert into t1 values (1,1),(2,2)")
tk.MustGetErrCode(`update t1 as a natural join t1 B SET a.A = 2, b.b = 3`, mysql.ErrMultiUpdateKeyConflict)
_, err := tk.Exec(`update t1 as a natural join t1 B SET a.A = 2, b.b = 3`)
require.Error(t, err)
require.Regexp(t, ".planner:1706.Primary key/partition key update is not allowed since the table is updated both as 'a' and 'B'.", err.Error())
tk.MustExec("drop table t1")
tk.MustExec("create table t1 (A int, b int) partition by RANGE COLUMNS (b) (partition `pNeg` values less than (0),partition `pPos` values less than MAXVALUE)")
tk.MustExec("insert into t1 values (1,1),(2,2)")
tk.MustGetErrCode(`update t1 as a natural join t1 B SET a.A = 2, b.b = 3`, mysql.ErrMultiUpdateKeyConflict)
tk.MustExec("drop table t1")
}
func TestAggPushToCopForCachedTable(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(`create table t32157(
process_code varchar(8) NOT NULL,
ctrl_class varchar(2) NOT NULL,
ctrl_type varchar(1) NOT NULL,
oper_no varchar(12) DEFAULT NULL,
modify_date datetime DEFAULT NULL,
d_c_flag varchar(2) NOT NULL,
PRIMARY KEY (process_code,ctrl_class,d_c_flag) NONCLUSTERED);`)
tk.MustExec("insert into t32157 values ('GDEP0071', '05', '1', '10000', '2016-06-29 00:00:00', 'C')")
tk.MustExec("insert into t32157 values ('GDEP0071', '05', '0', '0000', '2016-06-01 00:00:00', 'D')")
tk.MustExec("alter table t32157 cache")
tk.MustQuery("explain format = 'brief' select /*+AGG_TO_COP()*/ count(*) from t32157 ignore index(primary) where process_code = 'GDEP0071'").Check(testkit.Rows(
"StreamAgg 1.00 root funcs:count(1)->Column#8]\n" +
"[└─UnionScan 10.00 root eq(test.t32157.process_code, \"GDEP0071\")]\n" +
"[ └─TableReader 10.00 root data:Selection]\n" +
"[ └─Selection 10.00 cop[tikv] eq(test.t32157.process_code, \"GDEP0071\")]\n" +
"[ └─TableFullScan 10000.00 cop[tikv] table:t32157 keep order:false, stats:pseudo"))
var readFromCacheNoPanic bool
for i := 0; i < 10; i++ {
tk.MustQuery("select /*+AGG_TO_COP()*/ count(*) from t32157 ignore index(primary) where process_code = 'GDEP0071'").Check(testkit.Rows("2"))
if tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache {
readFromCacheNoPanic = true
break
}
}
require.True(t, readFromCacheNoPanic)
tk.MustExec("drop table if exists t31202")
}
func TestIssue31240(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t31240(a int, b int);")
tk.MustExec("set @@tidb_allow_mpp = 0")
tk.MustExec("set tidb_cost_model_version=2")
tbl, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t31240", L: "t31240"})
require.NoError(t, err)
// Set the hacked TiFlash replica for explain tests.
tbl.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true}
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
})
if strings.HasPrefix(tt, "set") {
tk.MustExec(tt)
continue
}
testdata.OnRecord(func() {
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
tk.MustExec("drop table if exists t31240")
}
func TestIssue32632(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("CREATE TABLE `partsupp` (" +
" `PS_PARTKEY` bigint(20) NOT NULL," +
"`PS_SUPPKEY` bigint(20) NOT NULL," +
"`PS_AVAILQTY` bigint(20) NOT NULL," +
"`PS_SUPPLYCOST` decimal(15,2) NOT NULL," +
"`PS_COMMENT` varchar(199) NOT NULL," +
"PRIMARY KEY (`PS_PARTKEY`,`PS_SUPPKEY`) /*T![clustered_index] NONCLUSTERED */)")
tk.MustExec("CREATE TABLE `supplier` (" +
"`S_SUPPKEY` bigint(20) NOT NULL," +
"`S_NAME` char(25) NOT NULL," +
"`S_ADDRESS` varchar(40) NOT NULL," +
"`S_NATIONKEY` bigint(20) NOT NULL," +
"`S_PHONE` char(15) NOT NULL," +
"`S_ACCTBAL` decimal(15,2) NOT NULL," +
"`S_COMMENT` varchar(101) NOT NULL," +
"PRIMARY KEY (`S_SUPPKEY`) /*T![clustered_index] CLUSTERED */)")
tk.MustExec("analyze table partsupp;")
tk.MustExec("analyze table supplier;")
tk.MustExec("set @@tidb_enforce_mpp = 1")
tbl1, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "partsupp", L: "partsupp"})
require.NoError(t, err)
tbl2, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "supplier", L: "supplier"})
require.NoError(t, err)
// Set the hacked TiFlash replica for explain tests.
tbl1.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true}
tbl2.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true}
h := dom.StatsHandle()
statsTbl1 := h.GetTableStats(tbl1.Meta())
statsTbl1.Count = 800000
statsTbl2 := h.GetTableStats(tbl2.Meta())
statsTbl2.Count = 10000
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
tk.MustExec("drop table if exists partsupp")
tk.MustExec("drop table if exists supplier")
}
func TestTiFlashPartitionTableScan(t *testing.T) {
failpoint.Enable("github.com/pingcap/tidb/planner/core/forceDynamicPrune", `return(true)`)
defer failpoint.Disable("github.com/pingcap/tidb/planner/core/forceDynamicPrune")
store, dom := testkit.CreateMockStoreAndDomain(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("set tidb_cost_model_version=1")
tk.MustExec("set @@tidb_partition_prune_mode = 'dynamic'")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'")
tk.MustExec("set @@tidb_enforce_mpp = on")
tk.MustExec("set @@tidb_allow_batch_cop = 2")
tk.MustExec("drop table if exists rp_t;")
tk.MustExec("drop table if exists hp_t;")
tk.MustExec("create table rp_t(a int) partition by RANGE (a) (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("create table hp_t(a int) partition by hash(a) partitions 4;")
tbl1, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "rp_t", L: "rp_t"})
require.NoError(t, err)
tbl2, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "hp_t", L: "hp_t"})
require.NoError(t, err)
// Set the hacked TiFlash replica for explain tests.
tbl1.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true}
tbl2.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true}
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
tk.MustExec("drop table rp_t;")
tk.MustExec("drop table hp_t;")
}
func TestTiFlashFineGrainedShuffle(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("set tidb_cost_model_version=2")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'")
tk.MustExec("set @@tidb_enforce_mpp = on")
tk.MustExec("drop table if exists t1;")
tk.MustExec("create table t1(c1 int, c2 int)")
tbl1, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t1", L: "t1"})
require.NoError(t, err)
// Set the hacked TiFlash replica for explain tests.
tbl1.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true}
var input []string
var output []struct {
SQL string
Plan []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
})
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
}
}
func TestTiFlashFineGrainedShuffleWithMaxTiFlashThreads(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'")
tk.MustExec("set @@tidb_enforce_mpp = on")
tk.MustExec("drop table if exists t1;")
tk.MustExec("create table t1(c1 int, c2 int)")
tbl1, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t1", L: "t1"})
require.NoError(t, err)
// Set the hacked TiFlash replica for explain tests.
tbl1.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true}
sql := "explain select row_number() over w1 from t1 window w1 as (partition by c1);"
getStreamCountFromExplain := func(rows [][]interface{}) (res []uint64) {
re := regexp.MustCompile("stream_count: ([0-9]+)")
for _, row := range rows {
buf := bytes.NewBufferString("")
_, _ = fmt.Fprintf(buf, "%s\n", row)
if matched := re.FindStringSubmatch(buf.String()); matched != nil {
require.Equal(t, len(matched), 2)
c, err := strconv.ParseUint(matched[1], 10, 64)
require.NoError(t, err)
res = append(res, c)
}
}
return res
}
// tiflash_fine_grained_shuffle_stream_count should be same with tidb_max_tiflash_threads.
tk.MustExec("set @@tiflash_fine_grained_shuffle_stream_count = 0")
tk.MustExec("set @@tidb_max_tiflash_threads = 10")
rows := tk.MustQuery(sql).Rows()
streamCount := getStreamCountFromExplain(rows)
// require.Equal(t, len(streamCount), 1)
require.Equal(t, uint64(10), streamCount[0])
// tiflash_fine_grained_shuffle_stream_count should be default value when tidb_max_tiflash_threads is -1.
tk.MustExec("set @@tiflash_fine_grained_shuffle_stream_count = 0")
tk.MustExec("set @@tidb_max_tiflash_threads = -1")
rows = tk.MustQuery(sql).Rows()
streamCount = getStreamCountFromExplain(rows)
// require.Equal(t, len(streamCount), 1)
require.Equal(t, uint64(variable.DefStreamCountWhenMaxThreadsNotSet), streamCount[0])
// tiflash_fine_grained_shuffle_stream_count should be default value when tidb_max_tiflash_threads is 0.
tk.MustExec("set @@tiflash_fine_grained_shuffle_stream_count = 0")
tk.MustExec("set @@tidb_max_tiflash_threads = 0")
rows = tk.MustQuery(sql).Rows()
streamCount = getStreamCountFromExplain(rows)
// require.Equal(t, len(streamCount), 1)
require.Equal(t, uint64(variable.DefStreamCountWhenMaxThreadsNotSet), streamCount[0])
// Disabled when tiflash_fine_grained_shuffle_stream_count is -1.
tk.MustExec("set @@tiflash_fine_grained_shuffle_stream_count = -1")
tk.MustExec("set @@tidb_max_tiflash_threads = 10")
rows = tk.MustQuery(sql).Rows()
streamCount = getStreamCountFromExplain(rows)
require.Equal(t, len(streamCount), 0)
// Test when tiflash_fine_grained_shuffle_stream_count is greater than 0.
tk.MustExec("set @@tiflash_fine_grained_shuffle_stream_count = 16")
tk.MustExec("set @@tidb_max_tiflash_threads = 10")
rows = tk.MustQuery(sql).Rows()
streamCount = getStreamCountFromExplain(rows)
// require.Equal(t, len(streamCount), 1)
require.Equal(t, uint64(16), streamCount[0])
}
func TestIssue33175(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t (id bigint(45) unsigned not null, c varchar(20), primary key(id));")
tk.MustExec("insert into t values (9734095886065816707, 'a'), (10353107668348738101, 'b'), (0, 'c');")
tk.MustExec("begin")
tk.MustExec("insert into t values (33, 'd');")
tk.MustQuery("select max(id) from t;").Check(testkit.Rows("10353107668348738101"))
tk.MustExec("rollback")
tk.MustExec("alter table t cache")
for {
tk.MustQuery("select max(id) from t;").Check(testkit.Rows("10353107668348738101"))
if tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache {
break
}
}
// // With subquery, like the original issue case.
for {
tk.MustQuery("select * from t where id > (select max(id) from t where t.id > 0);").Check(testkit.Rows())
if tk.Session().GetSessionVars().StmtCtx.ReadFromTableCache {
break
}
}
// Test order by desc / asc.
tk.MustQuery("select id from t order by id desc;").Check(testkit.Rows(
"10353107668348738101",
"9734095886065816707",
"0"))
tk.MustQuery("select id from t order by id asc;").Check(testkit.Rows(
"0",
"9734095886065816707",
"10353107668348738101"))
tk.MustExec("alter table t nocache")
tk.MustExec("drop table t")
// Cover more code that use union scan
// TableReader/IndexReader/IndexLookup
for idx, q := range []string{
"create temporary table t (id bigint unsigned, c int default null, index(id))",
"create temporary table t (id bigint unsigned primary key)",
} {
tk.MustExec(q)
tk.MustExec("insert into t(id) values (1), (3), (9734095886065816707), (9734095886065816708)")
tk.MustQuery("select min(id) from t").Check(testkit.Rows("1"))
tk.MustQuery("select max(id) from t").Check(testkit.Rows("9734095886065816708"))
tk.MustQuery("select id from t order by id asc").Check(testkit.Rows(
"1", "3", "9734095886065816707", "9734095886065816708"))
tk.MustQuery("select id from t order by id desc").Check(testkit.Rows(
"9734095886065816708", "9734095886065816707", "3", "1"))
if idx == 0 {
tk.MustQuery("select * from t order by id asc").Check(testkit.Rows(
"1 <nil>",
"3 <nil>",
"9734095886065816707 <nil>",
"9734095886065816708 <nil>"))
tk.MustQuery("select * from t order by id desc").Check(testkit.Rows(
"9734095886065816708 <nil>",
"9734095886065816707 <nil>",
"3 <nil>",
"1 <nil>"))
}
tk.MustExec("drop table t")
}
// More and more test
tk.MustExec("create global temporary table `tmp1` (id bigint unsigned primary key) on commit delete rows;")
tk.MustExec("begin")
tk.MustExec("insert into tmp1 values (0),(1),(2),(65536),(9734095886065816707),(9734095886065816708);")
tk.MustQuery("select * from tmp1 where id <= 65534 or (id > 65535 and id < 9734095886065816700) or id >= 9734095886065816707 order by id desc;").Check(testkit.Rows(
"9734095886065816708", "9734095886065816707", "65536", "2", "1", "0"))
tk.MustQuery("select * from tmp1 where id <= 65534 or (id > 65535 and id < 9734095886065816700) or id >= 9734095886065816707 order by id asc;").Check(testkit.Rows(
"0", "1", "2", "65536", "9734095886065816707", "9734095886065816708"))
tk.MustExec("create global temporary table `tmp2` (id bigint primary key) on commit delete rows;")
tk.MustExec("begin")
tk.MustExec("insert into tmp2 values(-2),(-1),(0),(1),(2);")
tk.MustQuery("select * from tmp2 where id <= -1 or id > 0 order by id desc;").Check(testkit.Rows("2", "1", "-1", "-2"))
tk.MustQuery("select * from tmp2 where id <= -1 or id > 0 order by id asc;").Check(testkit.Rows("-2", "-1", "1", "2"))
}
func TestIssue33042(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t1(id int primary key, col1 int)")
tk.MustExec("create table t2(id int primary key, col1 int)")
tk.MustQuery("explain format='brief' SELECT /*+ merge_join(t1, t2)*/ * FROM (t1 LEFT JOIN t2 ON t1.col1=t2.id) order by t2.id;").Check(
testkit.Rows(
"Sort 12500.00 root test.t2.id",
"└─MergeJoin 12500.00 root left outer join, left key:test.t1.col1, right key:test.t2.id",
" ├─TableReader(Build) 10000.00 root data:TableFullScan",
" │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:true, stats:pseudo",
" └─Sort(Probe) 10000.00 root test.t1.col1",
" └─TableReader 10000.00 root data:TableFullScan",
" └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
),
)
}
func TestIssue29663(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 int, b int)")
tk.MustExec("create table t2 (c int, d int)")
tk.MustExec("insert into t1 values(1, 1), (1,2),(2,1),(2,2)")
tk.MustExec("insert into t2 values(1, 3), (1,4),(2,5),(2,6)")
tk.MustQuery("explain select one.a from t1 one order by (select two.d from t2 two where two.c = one.b)").Check(testkit.Rows(
"Projection_16 10000.00 root test.t1.a",
"└─Sort_17 10000.00 root test.t2.d",
" └─Apply_20 10000.00 root CARTESIAN left outer join",
" ├─TableReader_22(Build) 10000.00 root data:TableFullScan_21",
" │ └─TableFullScan_21 10000.00 cop[tikv] table:one keep order:false, stats:pseudo",
" └─MaxOneRow_23(Probe) 10000.00 root ",
" └─TableReader_26 20000.00 root data:Selection_25",
" └─Selection_25 20000.00 cop[tikv] eq(test.t2.c, test.t1.b)",
" └─TableFullScan_24 20000000.00 cop[tikv] table:two keep order:false, stats:pseudo"))
}
func TestIssue31609(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustQuery("explain select rank() over (partition by table_name) from information_schema.tables").Check(testkit.Rows(
"Projection_7 10000.00 root Column#27",
"└─Shuffle_11 10000.00 root execution info: concurrency:5, data sources:[MemTableScan_9]",
" └─Window_8 10000.00 root rank()->Column#27 over(partition by Column#3)",
" └─Sort_10 10000.00 root Column#3",
" └─MemTableScan_9 10000.00 root table:TABLES ",
))
}
func TestDecimalOverflow(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 deci (a decimal(65,30),b decimal(65,0))")
tk.MustExec("insert into deci values (1234567890.123456789012345678901234567890,987654321098765432109876543210987654321098765432109876543210)")
tk.MustQuery("select a from deci union ALL select b from deci;").Sort().Check(testkit.Rows("1234567890.123456789012345678901234567890", "99999999999999999999999999999999999.999999999999999999999999999999"))
}
func TestIssue35083(t *testing.T) {
defer func() {
variable.SetSysVar(variable.TiDBOptProjectionPushDown, variable.BoolToOnOff(config.GetGlobalConfig().Performance.ProjectionPushDown))
}()
defer config.RestoreFunc()()
config.UpdateGlobal(func(conf *config.Config) {
conf.Performance.ProjectionPushDown = true
})
variable.SetSysVar(variable.TiDBOptProjectionPushDown, variable.BoolToOnOff(config.GetGlobalConfig().Performance.ProjectionPushDown))
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t1 (a varchar(100), b int)")
tk.MustQuery("select @@tidb_opt_projection_push_down").Check(testkit.Rows("1"))
tk.MustQuery("explain format = 'brief' select cast(a as datetime) from t1").Check(testkit.Rows(
"TableReader 10000.00 root data:Projection",
"└─Projection 10000.00 cop[tikv] cast(test.t1.a, datetime BINARY)->Column#4",
" └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"))
}
func TestIssue25813(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t(a json);")
tk.MustExec("insert into t values('{\"id\": \"ish\"}');")
tk.MustQuery("select t2.a from t t1 left join t t2 on t1.a=t2.a where t2.a->'$.id'='ish';").Check(testkit.Rows("{\"id\": \"ish\"}"))
tk.MustQuery("explain format = 'brief' select * from t t1 left join t t2 on t1.a=t2.a where t2.a->'$.id'='ish';").Check(testkit.Rows(
"Selection 8000.00 root eq(json_extract(test.t.a, \"$.id\"), cast(\"ish\", json BINARY))",
"└─HashJoin 10000.00 root left outer join, equal:[eq(test.t.a, test.t.a)]",
" ├─TableReader(Build) 8000.00 root data:Selection",
" │ └─Selection 8000.00 cop[tikv] not(isnull(cast(test.t.a, var_string(4294967295))))",
" │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
" └─TableReader(Probe) 10000.00 root data:TableFullScan",
" └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"))
}
func TestRepeatPushDownToTiFlash(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, b int)")
tk.MustExec("insert into t values(2147483647, 2)")
tk.MustExec("insert into t values(12, 2)")
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
rows := [][]interface{}{
{"TableReader_9", "root", "data:ExchangeSender_8"},
{"└─ExchangeSender_8", "mpp[tiflash]", "ExchangeType: PassThrough"},
{" └─Projection_4", "mpp[tiflash]", "repeat(cast(test.t.a, var_string(20)), test.t.b)->Column#4"},
{" └─TableFullScan_7", "mpp[tiflash]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain select repeat(a,b) from t;").CheckAt([]int{0, 2, 4}, rows)
}
func TestIssue36194(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(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)")
// create virtual tiflash replica.
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
tk.MustQuery("explain format = 'brief' select /*+ read_from_storage(tiflash[t]) */ * from t where a + 1 > 20 limit 100;;").Check(testkit.Rows(
"Limit 100.00 root offset:0, count:100",
"└─TableReader 100.00 root data:ExchangeSender",
" └─ExchangeSender 100.00 mpp[tiflash] ExchangeType: PassThrough",
" └─Limit 100.00 mpp[tiflash] offset:0, count:100",
" └─Selection 100.00 mpp[tiflash] gt(plus(test.t.a, 1), 20)",
" └─TableFullScan 125.00 mpp[tiflash] table:t keep order:false, stats:pseudo"))
}
func TestGetFormatPushDownToTiFlash(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t(location varchar(10));")
tk.MustExec("insert into t values('USA'), ('JIS'), ('ISO'), ('EUR'), ('INTERNAL')")
tk.MustExec("set @@tidb_enforce_mpp=1;")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash';")
tbl, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t", L: "t"})
require.NoError(t, err)
// Set the hacked TiFlash replica for explain tests.
tbl.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true}
tk.MustQuery("explain format = 'brief' select GET_FORMAT(DATE, location) from t;").Check(testkit.Rows(
"TableReader 10000.00 root data:ExchangeSender",
"└─ExchangeSender 10000.00 mpp[tiflash] ExchangeType: PassThrough",
" └─Projection 10000.00 mpp[tiflash] get_format(DATE, test.t.location)->Column#3",
" └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo"))
}
func TestAggWithJsonPushDownToTiFlash(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 json);")
tk.MustExec("insert into t values(null);")
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'")
// Create virtual tiflash replica info.
dom := domain.GetDomain(tk.Session())
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
rows := [][]interface{}{
{"HashAgg_6", "root", "funcs:avg(Column#4)->Column#3"},
{"└─Projection_19", "root", "cast(test.t.a, double BINARY)->Column#4"},
{" └─TableReader_12", "root", "data:TableFullScan_11"},
{" └─TableFullScan_11", "cop[tiflash]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain select avg(a) from t;").CheckAt([]int{0, 2, 4}, rows)
rows = [][]interface{}{
{"HashAgg_6", "root", "funcs:sum(Column#4)->Column#3"},
{"└─Projection_19", "root", "cast(test.t.a, double BINARY)->Column#4"},
{" └─TableReader_12", "root", "data:TableFullScan_11"},
{" └─TableFullScan_11", "cop[tiflash]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain select sum(a) from t;").CheckAt([]int{0, 2, 4}, rows)
rows = [][]interface{}{
{"HashAgg_6", "root", "funcs:group_concat(Column#4 separator \",\")->Column#3"},
{"└─Projection_13", "root", "cast(test.t.a, var_string(4294967295))->Column#4"},
{" └─TableReader_10", "root", "data:TableFullScan_9"},
{" └─TableFullScan_9", "cop[tiflash]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain select /*+ hash_agg() */ group_concat(a) from t;").CheckAt([]int{0, 2, 4}, rows)
}
func TestLeftShiftPushDownToTiFlash(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(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)")
tk.MustExec("insert into t values(2147483647, 32)")
tk.MustExec("insert into t values(12, 2)")
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'")
// Create virtual tiflash replica info.
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
rows := [][]interface{}{
{"TableReader_9", "root", "data:ExchangeSender_8"},
{"└─ExchangeSender_8", "mpp[tiflash]", "ExchangeType: PassThrough"},
{" └─Projection_4", "mpp[tiflash]", "leftshift(test.t.a, test.t.b)->Column#4"},
{" └─TableFullScan_7", "mpp[tiflash]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain select a << b from t;").CheckAt([]int{0, 2, 4}, rows)
}
func TestIssue36609(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil))
tk.MustExec("use test")
tk.MustExec("create table t1(a int, b int, c int, d int, index ia(a), index ib(b), index ic(c), index id(d))")
tk.MustExec("create table t2(a int, b int, c int, d int, index ia(a), index ib(b), index ic(c), index id(d))")
tk.MustExec("create table t3(a int, b int, c int, d int, index ia(a), index ib(b), index ic(c), index id(d))")
tk.MustExec("create table t4(a int, b int, c int, d int, index ia(a), index ib(b), index ic(c), index id(d))")
tk.MustExec("create table t5(a int, b int, c int, d int, index ia(a), index ib(b), index ic(c), index id(d))")
tk.MustQuery("select * from t3 straight_join t4 on t3.a = t4.b straight_join t2 on t3.d = t2.c straight_join t1 on t1.a = t2.b straight_join t5 on t4.c = t5.d where t2.b < 100 and t4.a = 10;")
tk.MustQuery("select * from information_schema.statements_summary;")
}
func TestHexIntOrStrPushDownToTiFlash(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(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 varchar(10));")
tk.MustExec("insert into t values(1, 'tiflash');")
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'")
tbl, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t", L: "t"})
require.NoError(t, err)
// Set the hacked TiFlash replica for explain tests.
tbl.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true}
rows := [][]interface{}{
{"TableReader_9", "root", "data:ExchangeSender_8"},
{"└─ExchangeSender_8", "mpp[tiflash]", "ExchangeType: PassThrough"},
{" └─Projection_4", "mpp[tiflash]", "hex(test.t.a)->Column#4"},
{" └─TableFullScan_7", "mpp[tiflash]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain select hex(a) from t;").CheckAt([]int{0, 2, 4}, rows)
rows = [][]interface{}{
{"TableReader_9", "root", "data:ExchangeSender_8"},
{"└─ExchangeSender_8", "mpp[tiflash]", "ExchangeType: PassThrough"},
{" └─Projection_4", "mpp[tiflash]", "hex(test.t.b)->Column#4"},
{" └─TableFullScan_7", "mpp[tiflash]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain select hex(b) from t;").CheckAt([]int{0, 2, 4}, rows)
}
func TestBinPushDownToTiFlash(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int);")
tk.MustExec("insert into t values(1);")
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'")
tbl, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t", L: "t"})
require.NoError(t, err)
// Set the hacked TiFlash replica for explain tests.
tbl.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true}
rows := [][]interface{}{
{"TableReader_9", "root", "data:ExchangeSender_8"},
{"└─ExchangeSender_8", "mpp[tiflash]", "ExchangeType: PassThrough"},
{" └─Projection_4", "mpp[tiflash]", "bin(test.t.a)->Column#3"},
{" └─TableFullScan_7", "mpp[tiflash]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain select bin(a) from t;").CheckAt([]int{0, 2, 4}, rows)
}
func TestEltPushDownToTiFlash(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(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 varchar(20))")
tk.MustExec("insert into t values(2147483647, '32')")
tk.MustExec("insert into t values(12, 'abc')")
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'")
// Create virtual tiflash replica info.
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
rows := [][]interface{}{
{"TableReader_9", "root", "data:ExchangeSender_8"},
{"└─ExchangeSender_8", "mpp[tiflash]", "ExchangeType: PassThrough"},
{" └─Projection_4", "mpp[tiflash]", "elt(test.t.a, test.t.b)->Column#4"},
{" └─TableFullScan_7", "mpp[tiflash]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain select elt(a, b) from t;").CheckAt([]int{0, 2, 4}, rows)
}
func TestRegexpInstrPushDownToTiFlash(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists test.t;")
tk.MustExec("create table test.t (expr varchar(30), pattern varchar(30), pos int, occur int, ret_op int, match_type varchar(30));")
tk.MustExec("insert into test.t values ('123', '12.', 1, 1, 0, ''), ('aBb', 'bb', 1, 1, 0, 'i'), ('ab\nabc', '^abc$', 1, 1, 0, 'm');")
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'")
// Create virtual tiflash replica info.
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
rows := [][]interface{}{
{"TableReader_9", "root", "data:ExchangeSender_8"},
{"└─ExchangeSender_8", "mpp[tiflash]", "ExchangeType: PassThrough"},
{" └─Projection_4", "mpp[tiflash]", "regexp_instr(test.t.expr, test.t.pattern, 1, 1, 0, test.t.match_type)->Column#8"},
{" └─TableFullScan_7", "mpp[tiflash]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain select regexp_instr(expr, pattern, 1, 1, 0, match_type) as res from test.t;").CheckAt([]int{0, 2, 4}, rows)
}
func TestRegexpSubstrPushDownToTiFlash(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists test.t;")
tk.MustExec("create table test.t (expr varchar(30), pattern varchar(30), pos int, occur int, match_type varchar(30));")
tk.MustExec("insert into test.t values ('123', '12.', 1, 1, ''), ('aBb', 'bb', 1, 1, 'i'), ('ab\nabc', '^abc$', 1, 1, 'm');")
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'")
// Create virtual tiflash replica info.
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
rows := [][]interface{}{
{"TableReader_9", "root", "data:ExchangeSender_8"},
{"└─ExchangeSender_8", "mpp[tiflash]", "ExchangeType: PassThrough"},
{" └─Projection_4", "mpp[tiflash]", "regexp_substr(test.t.expr, test.t.pattern, 1, 1, test.t.match_type)->Column#7"},
{" └─TableFullScan_7", "mpp[tiflash]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain select regexp_substr(expr, pattern, 1, 1, match_type) as res from test.t;").CheckAt([]int{0, 2, 4}, rows)
}
func TestRegexpReplacePushDownToTiFlash(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists test.t;")
tk.MustExec("create table test.t (expr varchar(30), pattern varchar(30), repl varchar(30), pos int, occur int, match_type varchar(30));")
tk.MustExec("insert into test.t values ('123', '12.', '233', 1, 1, ''), ('aBb', 'bb', 'bc', 1, 1, 'i'), ('ab\nabc', '^abc$', 'd', 1, 1, 'm');")
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'")
// Create virtual tiflash replica info.
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
rows := [][]interface{}{
{"TableReader_9", "root", "data:ExchangeSender_8"},
{"└─ExchangeSender_8", "mpp[tiflash]", "ExchangeType: PassThrough"},
{" └─Projection_4", "mpp[tiflash]", "regexp_replace(test.t.expr, test.t.pattern, test.t.repl, 1, 1, test.t.match_type)->Column#8"},
{" └─TableFullScan_7", "mpp[tiflash]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain select regexp_replace(expr, pattern, repl, 1, 1, match_type) as res from test.t;").CheckAt([]int{0, 2, 4}, rows)
}
func TestCastTimeAsDurationToTiFlash(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a date, b datetime(4))")
tk.MustExec("insert into t values('2021-10-26', '2021-10-26')")
tk.MustExec("insert into t values('2021-10-26', '2021-10-26 11:11:11')")
tk.MustExec("insert into t values('2021-10-26', '2021-10-26 11:11:11.111111')")
tk.MustExec("insert into t values('2021-10-26', '2021-10-26 11:11:11.123456')")
tk.MustExec("insert into t values('2021-10-26', '2021-10-26 11:11:11.999999')")
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'")
// Create virtual tiflash replica info.
is := dom.InfoSchema()
db, exists := is.SchemaByName(model.NewCIStr("test"))
require.True(t, exists)
for _, tblInfo := range db.Tables {
if tblInfo.Name.L == "t" {
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
Count: 1,
Available: true,
}
}
}
rows := [][]interface{}{
{"TableReader_9", "root", "data:ExchangeSender_8"},
{"└─ExchangeSender_8", "mpp[tiflash]", "ExchangeType: PassThrough"},
{" └─Projection_4", "mpp[tiflash]", "cast(test.t.a, time BINARY)->Column#4, cast(test.t.b, time BINARY)->Column#5"},
{" └─TableFullScan_7", "mpp[tiflash]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain select cast(a as time), cast(b as time) from t;").CheckAt([]int{0, 2, 4}, rows)
}
func TestUnhexPushDownToTiFlash(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(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 varchar(20));")
tk.MustExec("insert into t values(6162, '7469666C617368');")
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1;")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'")
tbl, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t", L: "t"})
require.NoError(t, err)
// Set the hacked TiFlash replica for explain tests.
tbl.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true}
rows := [][]interface{}{
{"TableReader_9", "root", "data:ExchangeSender_8"},
{"└─ExchangeSender_8", "mpp[tiflash]", "ExchangeType: PassThrough"},
{" └─Projection_4", "mpp[tiflash]", "unhex(cast(test.t.a, var_string(20)))->Column#4"},
{" └─TableFullScan_7", "mpp[tiflash]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain select unhex(a) from t;").CheckAt([]int{0, 2, 4}, rows)
rows = [][]interface{}{
{"TableReader_9", "root", "data:ExchangeSender_8"},
{"└─ExchangeSender_8", "mpp[tiflash]", "ExchangeType: PassThrough"},
{" └─Projection_4", "mpp[tiflash]", "unhex(test.t.b)->Column#4"},
{" └─TableFullScan_7", "mpp[tiflash]", "keep order:false, stats:pseudo"},
}
tk.MustQuery("explain select unhex(b) from t;").CheckAt([]int{0, 2, 4}, rows)
}
func TestPartitionTableFallBackStatic(t *testing.T) {
store, _ := testkit.CreateMockStoreAndDomain(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("set @@tidb_partition_prune_mode='static'")
tk.MustExec("CREATE TABLE t (a int) PARTITION BY RANGE (a) (PARTITION p0 VALUES LESS THAN (6),PARTITION p1 VALUES LESS THAN (11));")
tk.MustExec("insert into t values (1),(2),(3),(4),(7),(8),(9),(10)")
tk.MustExec("analyze table t")
// use static plan in static mode
rows := [][]interface{}{
{"PartitionUnion", "", ""},
{"├─TableReader", "", "data:TableFullScan"},
{"│ └─TableFullScan", "table:t, partition:p0", "keep order:false"},
{"└─TableReader", "", "data:TableFullScan"},
{" └─TableFullScan", "table:t, partition:p1", "keep order:false"},
}
tk.MustQuery("explain format='brief' select * from t").CheckAt([]int{0, 3, 4}, rows)
tk.MustExec("CREATE TABLE t2 (a int) PARTITION BY RANGE (a) (PARTITION p0 VALUES LESS THAN (6),PARTITION p1 VALUES LESS THAN (11));")
tk.MustExec("insert into t2 values (1),(2),(3),(4),(7),(8),(9),(10)")
tk.MustExec("analyze table t2")
tk.MustExec("set @@tidb_partition_prune_mode='dynamic'")
// use static plan in dynamic mode due to having not global stats
tk.MustQuery("explain format='brief' select * from t").CheckAt([]int{0, 3, 4}, rows)
tk.MustExec("analyze table t")
// use dynamic plan in dynamic mode with global stats
rows = [][]interface{}{
{"TableReader", "partition:all", "data:TableFullScan"},
{"└─TableFullScan", "table:t", "keep order:false"},
}
tk.MustQuery("explain format='brief' select * from t").CheckAt([]int{0, 3, 4}, rows)
rows = [][]interface{}{
{"Union", "", ""},
{"├─PartitionUnion", "", ""},
{"│ ├─TableReader", "", "data:TableFullScan"},
{"│ │ └─TableFullScan", "table:t, partition:p0", "keep order:false"},
{"│ └─TableReader", "", "data:TableFullScan"},
{"│ └─TableFullScan", "table:t, partition:p1", "keep order:false"},
{"└─PartitionUnion", "", ""},
{" ├─TableReader", "", "data:TableFullScan"},
{" │ └─TableFullScan", "table:t2, partition:p0", "keep order:false"},
{" └─TableReader", "", "data:TableFullScan"},
{" └─TableFullScan", "table:t2, partition:p1", "keep order:false"},
}
// use static plan in dynamic mode due to t2 has no global stats
tk.MustQuery("explain format='brief' select * from t union all select * from t2;").CheckAt([]int{0, 3, 4}, rows)
}
func TestEnableTiFlashReadForWriteStmt(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(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)")
tk.MustExec("insert into t values(1, 2)")
tk.MustExec("drop table if exists t2")
tk.MustExec("create table t2(a int)")
tk.MustExec("set @@tidb_allow_mpp=1; set @@tidb_enforce_mpp=1")
tk.MustExec("set @@tidb_isolation_read_engines = 'tiflash'")
tk.MustExec("set @@tidb_enable_tiflash_read_for_write_stmt = ON")
tbl, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t", L: "t"})
require.NoError(t, err)
// Set the hacked TiFlash replica for explain tests.
tbl.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true}
tbl2, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t2", L: "t2"})
require.NoError(t, err)
// Set the hacked TiFlash replica for explain tests.
tbl2.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true}
checkMpp := func(r [][]interface{}) {
check := false
for i := range r {
if r[i][2] == "mpp[tiflash]" {
check = true
break
}
}
require.Equal(t, check, true)
}
// Insert into ... select
rs := tk.MustQuery("explain insert into t2 select a+b from t").Rows()
checkMpp(rs)
rs = tk.MustQuery("explain insert into t2 select t.a from t2 join t on t2.a = t.a").Rows()
checkMpp(rs)
// Replace into ... select
rs = tk.MustQuery("explain replace into t2 select a+b from t").Rows()
checkMpp(rs)
// CTE
rs = tk.MustQuery("explain update t set a=a+1 where b in (select a from t2 where t.a > t2.a)").Rows()
checkMpp(rs)
}
func TestPointGetWithSelectLock(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t(a int, b int, primary key(a, b));")
tk.MustExec("create table t1(c int unique, d int);")
tbl, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t", L: "t"})
require.NoError(t, err)
// Set the hacked TiFlash replica for explain tests.
tbl.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true}
tbl1, err := dom.InfoSchema().TableByName(model.CIStr{O: "test", L: "test"}, model.CIStr{O: "t1", L: "t1"})
require.NoError(t, err)
// Set the hacked TiFlash replica for explain tests.
tbl1.Meta().TiFlashReplica = &model.TiFlashReplicaInfo{Count: 1, Available: true}
sqls := []string{
"explain select a, b from t where (a = 1 and b = 2) or (a =2 and b = 1) for update;",
"explain select a, b from t where a = 1 and b = 2 for update;",
"explain select c, d from t1 where c = 1 for update;",
"explain select c, d from t1 where c = 1 and d = 1 for update;",
"explain select c, d from t1 where (c = 1 or c = 2 )and d = 1 for update;",
"explain select c, d from t1 where c in (1,2,3,4) for update;",
}
tk.MustExec("set @@tidb_enable_tiflash_read_for_write_stmt = on;")
tk.MustExec("set @@tidb_isolation_read_engines='tidb,tiflash';")
tk.MustExec("begin;")
// assert point get / batch point get can't work with tiflash in interaction txn
for _, sql := range sqls {
err = tk.ExecToErr(sql)
require.Error(t, err)
}
// assert point get / batch point get can work with tikv in interaction txn
tk.MustExec("set @@tidb_isolation_read_engines='tidb,tikv,tiflash';")
for _, sql := range sqls {
tk.MustQuery(sql)
}
tk.MustExec("commit")
// assert point get / batch point get can work with tiflash in auto commit
tk.MustExec("set @@tidb_isolation_read_engines='tidb,tiflash';")
for _, sql := range sqls {
tk.MustQuery(sql)
}
}
func TestTableRangeFallback(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1 (a int primary key, b int)")
tk.MustExec("create table t2 (c int)")
tk.MustQuery("explain format='brief' select * from t1 where a in (10, 20, 30, 40, 50) and b > 1").Check(testkit.Rows(
"Selection 1.67 root gt(test.t1.b, 1)",
"└─Batch_Point_Get 5.00 root table:t1 handle:[10 20 30 40 50], keep order:false, desc:false"))
tk.MustQuery("explain format='brief' select * from t1 join t2 on t1.b = t2.c where t1.a in (10, 20, 30, 40, 50)").Check(testkit.Rows(
"HashJoin 6.24 root inner join, equal:[eq(test.t1.b, test.t2.c)]",
"├─Selection(Build) 5.00 root not(isnull(test.t1.b))",
"│ └─Batch_Point_Get 5.00 root table:t1 handle:[10 20 30 40 50], keep order:false, desc:false",
"└─TableReader(Probe) 9990.00 root data:Selection",
" └─Selection 9990.00 cop[tikv] not(isnull(test.t2.c))",
" └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"))
tk.MustExec("set @@tidb_opt_range_max_size=10")
tk.MustQuery("explain format='brief' select * from t1 where a in (10, 20, 30, 40, 50) and b > 1").Check(testkit.Rows(
"TableReader 8000.00 root data:Selection",
"└─Selection 8000.00 cop[tikv] gt(test.t1.b, 1), in(test.t1.a, 10, 20, 30, 40, 50)",
" └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"))
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 Memory capacity of 10 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen"))
tk.MustQuery("explain format='brief' select * from t1 join t2 on t1.b = t2.c where t1.a in (10, 20, 30, 40, 50)").Check(testkit.Rows(
"HashJoin 10000.00 root inner join, equal:[eq(test.t1.b, test.t2.c)]",
"├─TableReader(Build) 8000.00 root data:Selection",
"│ └─Selection 8000.00 cop[tikv] not(isnull(test.t2.c))",
"│ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
"└─TableReader(Probe) 8000.00 root data:Selection",
" └─Selection 8000.00 cop[tikv] in(test.t1.a, 10, 20, 30, 40, 50), not(isnull(test.t1.b))",
" └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"))
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 Memory capacity of 10 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen"))
}
func TestIndexRangeFallback(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1 (a varchar(10), b varchar(10), c varchar(10), index idx_a_b(a(2), b(2)))")
tk.MustExec("create table t2 (d varchar(10))")
tk.MustExec("create table t3 (pk int primary key, a int, key(a))")
tk.MustExec("create table t4 (a int, b int, c int, index idx_a_b(a, b))")
// Simple index range fallback case.
tk.MustExec("set @@tidb_opt_range_max_size=0")
tk.MustQuery("explain format='brief' select * from t1 where a in ('aaa', 'bbb', 'ccc') and b in ('ddd', 'eee', 'fff')").Check(testkit.Rows(
"IndexLookUp 0.90 root ",
"├─IndexRangeScan(Build) 0.90 cop[tikv] table:t1, index:idx_a_b(a, b) range:[\"aa\" \"dd\",\"aa\" \"dd\"], [\"aa\" \"ee\",\"aa\" \"ee\"], [\"aa\" \"ff\",\"aa\" \"ff\"], [\"bb\" \"dd\",\"bb\" \"dd\"], [\"bb\" \"ee\",\"bb\" \"ee\"], [\"bb\" \"ff\",\"bb\" \"ff\"], [\"cc\" \"dd\",\"cc\" \"dd\"], [\"cc\" \"ee\",\"cc\" \"ee\"], [\"cc\" \"ff\",\"cc\" \"ff\"], keep order:false, stats:pseudo",
"└─Selection(Probe) 0.90 cop[tikv] in(test.t1.a, \"aaa\", \"bbb\", \"ccc\"), in(test.t1.b, \"ddd\", \"eee\", \"fff\")",
" └─TableRowIDScan 0.90 cop[tikv] table:t1 keep order:false, stats:pseudo"))
tk.MustExec("set @@tidb_opt_range_max_size=1000")
tk.MustQuery("explain format='brief' select * from t1 where a in ('aaa', 'bbb', 'ccc') and b in ('ddd', 'eee', 'fff')").Check(testkit.Rows(
"IndexLookUp 0.09 root ",
"├─IndexRangeScan(Build) 30.00 cop[tikv] table:t1, index:idx_a_b(a, b) range:[\"aa\",\"aa\"], [\"bb\",\"bb\"], [\"cc\",\"cc\"], keep order:false, stats:pseudo",
"└─Selection(Probe) 0.09 cop[tikv] in(test.t1.a, \"aaa\", \"bbb\", \"ccc\"), in(test.t1.b, \"ddd\", \"eee\", \"fff\")",
" └─TableRowIDScan 30.00 cop[tikv] table:t1 keep order:false, stats:pseudo"))
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 Memory capacity of 1000 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen"))
// Index range fallback under join.
tk.MustExec("set @@tidb_opt_range_max_size=0")
tk.MustQuery("explain format='brief' select * from t1 join t2 on t1.c = t2.d where a in ('aaa', 'bbb', 'ccc') and b in ('ddd', 'eee', 'fff')").Check(testkit.Rows(
"HashJoin 1.12 root inner join, equal:[eq(test.t1.c, test.t2.d)]",
"├─IndexLookUp(Build) 0.90 root ",
"│ ├─IndexRangeScan(Build) 0.90 cop[tikv] table:t1, index:idx_a_b(a, b) range:[\"aa\" \"dd\",\"aa\" \"dd\"], [\"aa\" \"ee\",\"aa\" \"ee\"], [\"aa\" \"ff\",\"aa\" \"ff\"], [\"bb\" \"dd\",\"bb\" \"dd\"], [\"bb\" \"ee\",\"bb\" \"ee\"], [\"bb\" \"ff\",\"bb\" \"ff\"], [\"cc\" \"dd\",\"cc\" \"dd\"], [\"cc\" \"ee\",\"cc\" \"ee\"], [\"cc\" \"ff\",\"cc\" \"ff\"], keep order:false, stats:pseudo",
"│ └─Selection(Probe) 0.90 cop[tikv] in(test.t1.a, \"aaa\", \"bbb\", \"ccc\"), in(test.t1.b, \"ddd\", \"eee\", \"fff\"), not(isnull(test.t1.c))",
"│ └─TableRowIDScan 0.90 cop[tikv] table:t1 keep order:false, stats:pseudo",
"└─TableReader(Probe) 9990.00 root data:Selection",
" └─Selection 9990.00 cop[tikv] not(isnull(test.t2.d))",
" └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"))
tk.MustExec("set @@tidb_opt_range_max_size=1000")
tk.MustQuery("explain format='brief' select * from t1 join t2 on t1.c = t2.d where a in ('aaa', 'bbb', 'ccc') and b in ('ddd', 'eee', 'fff')").Check(testkit.Rows(
"HashJoin 0.11 root inner join, equal:[eq(test.t1.c, test.t2.d)]",
"├─IndexLookUp(Build) 0.09 root ",
"│ ├─IndexRangeScan(Build) 30.00 cop[tikv] table:t1, index:idx_a_b(a, b) range:[\"aa\",\"aa\"], [\"bb\",\"bb\"], [\"cc\",\"cc\"], keep order:false, stats:pseudo",
"│ └─Selection(Probe) 0.09 cop[tikv] in(test.t1.a, \"aaa\", \"bbb\", \"ccc\"), in(test.t1.b, \"ddd\", \"eee\", \"fff\"), not(isnull(test.t1.c))",
"│ └─TableRowIDScan 30.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
"└─TableReader(Probe) 9990.00 root data:Selection",
" └─Selection 9990.00 cop[tikv] not(isnull(test.t2.d))",
" └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"))
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 Memory capacity of 1000 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen"))
// Index range fallback in index column + pk column schema.
tk.MustExec("set @@tidb_opt_range_max_size=0")
tk.MustQuery("explain format='brief' select /*+ use_index(t3, a) */ * from t3 where a in (1, 3, 5) and pk in (2, 4, 6)").Check(testkit.Rows(
"IndexReader 0.90 root index:IndexRangeScan",
"└─IndexRangeScan 0.90 cop[tikv] table:t3, index:a(a) range:[1 2,1 2], [1 4,1 4], [1 6,1 6], [3 2,3 2], [3 4,3 4], [3 6,3 6], [5 2,5 2], [5 4,5 4], [5 6,5 6], keep order:false, stats:pseudo"))
tk.MustExec("set @@tidb_opt_range_max_size=1000")
tk.MustQuery("explain format='brief' select /*+ use_index(t3, a) */ * from t3 where a in (1, 3, 5) and pk in (2, 4, 6)").Check(testkit.Rows(
"IndexReader 0.01 root index:Selection",
"└─Selection 0.01 cop[tikv] in(test.t3.pk, 2, 4, 6)",
" └─IndexRangeScan 30.00 cop[tikv] table:t3, index:a(a) range:[1,1], [3,3], [5,5], keep order:false, stats:pseudo"))
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 Memory capacity of 1000 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen"))
// Index range fallback for idx_col1 in (?, ?, ?) and idx_col2 = ? conditions. Prevent SplitCorColAccessCondFromFilters
// adding idx_col2 = ? back to access conditions.
tk.MustExec("set @@tidb_opt_range_max_size=0")
tk.MustQuery("explain format='brief' select /*+ use_index(t4, idx_a_b) */ * from t4 where a in (1, 3, 5) and b = 2").Check(testkit.Rows(
"IndexLookUp 0.30 root ",
"├─IndexRangeScan(Build) 0.30 cop[tikv] table:t4, index:idx_a_b(a, b) range:[1 2,1 2], [3 2,3 2], [5 2,5 2], keep order:false, stats:pseudo",
"└─TableRowIDScan(Probe) 0.30 cop[tikv] table:t4 keep order:false, stats:pseudo"))
tk.MustExec("set @@tidb_opt_range_max_size=1000")
tk.MustQuery("explain format='brief' select /*+ use_index(t4, idx_a_b) */ * from t4 where a in (1, 3, 5) and b = 2").Check(testkit.Rows(
"IndexLookUp 0.03 root ",
"├─Selection(Build) 0.03 cop[tikv] eq(test.t4.b, 2)",
"│ └─IndexRangeScan 30.00 cop[tikv] table:t4, index:idx_a_b(a, b) range:[1,1], [3,3], [5,5], keep order:false, stats:pseudo",
"└─TableRowIDScan(Probe) 0.03 cop[tikv] table:t4 keep order:false, stats:pseudo"))
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 Memory capacity of 1000 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen"))
}
func TestPlanCacheForTableRangeFallback(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("set @@tidb_enable_prepared_plan_cache=1")
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (a int primary key, b int)")
tk.MustExec("set @@tidb_opt_range_max_size=10")
tk.MustExec("prepare stmt from 'select * from t where a in (?, ?, ?, ?, ?) and b > 1'")
tk.MustExec("set @a=10, @b=20, @c=30, @d=40, @e=50")
tk.MustExec("execute stmt using @a, @b, @c, @d, @e")
tk.MustQuery("show warnings").Sort().Check(testkit.Rows("Warning 1105 Memory capacity of 10 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen",
"Warning 1105 skip plan-cache: in-list is too long"))
tk.MustExec("execute stmt using @a, @b, @c, @d, @e")
// The plan with range fallback is not cached.
tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0"))
}
func TestPlanCacheForIndexRangeFallback(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec(`set @@tidb_enable_prepared_plan_cache=1`)
tk.MustExec("set @@tidb_enable_collect_execution_info=0") // In this way `explain for connection id` doesn't display execution info.
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t (a varchar(10), b varchar(10), c varchar(10), index idx_a_b(a, b))")
tk.MustExec("set @@tidb_opt_range_max_size=1330") // 1330 is the memory usage of ["aa","aa"], ["bb","bb"], ["cc","cc"], ["dd","dd"], ["ee","ee"].
rows := tk.MustQuery("explain format='brief' select * from t where a in ('aa', 'bb', 'cc', 'dd', 'ee')").Rows()
require.True(t, strings.Contains(rows[1][0].(string), "IndexRangeScan"))
require.True(t, strings.Contains(rows[1][4].(string), "range:[\"aa\",\"aa\"], [\"bb\",\"bb\"], [\"cc\",\"cc\"], [\"dd\",\"dd\"], [\"ee\",\"ee\"]"))
rows = tk.MustQuery("explain format='brief' select * from t where a in ('aaaaaaaaaa', 'bbbbbbbbbb', 'cccccccccc', 'dddddddddd', 'eeeeeeeeee')").Rows()
// 1330 is not enough for ["aaaaaaaaaa","aaaaaaaaaa"], ["bbbbbbbbbb","bbbbbbbbbb"], ["cccccccccc","cccccccccc"], ["dddddddddd","dddddddddd"], ["eeeeeeeeee","eeeeeeeeee"].
// So it falls back to table full scan.
require.True(t, strings.Contains(rows[2][0].(string), "TableFullScan"))
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 Memory capacity of 1330 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen"))
// Test rebuilding ranges for the cached plan doesn't have memory limit.
tk.MustExec("prepare stmt1 from 'select * from t where a in (?, ?, ?, ?, ?)'")
tk.MustExec("set @a='aa', @b='bb', @c='cc', @d='dd', @e='ee'")
tk.MustExec("execute stmt1 using @a, @b, @c, @d, @e")
tk.MustQuery("show warnings").Check(testkit.Rows()) // Range fallback doesn't happen and the plan can be put into cache.
tk.MustExec("set @a='aaaaaaaaaa', @b='bbbbbbbbbb', @c='cccccccccc', @d='dddddddddd', @e='eeeeeeeeee'")
tk.MustExec("execute stmt1 using @a, @b, @c, @d, @e")
tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1"))
tk.MustExec("execute stmt1 using @a, @b, @c, @d, @e")
tkProcess := tk.Session().ShowProcess()
ps := []*util.ProcessInfo{tkProcess}
tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps})
rows = tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Rows()
// We don't limit range mem usage when rebuilding ranges for the cached plan.
// So ["aaaaaaaaaa","aaaaaaaaaa"], ["bbbbbbbbbb","bbbbbbbbbb"], ["cccccccccc","cccccccccc"], ["dddddddddd","dddddddddd"], ["eeeeeeeeee","eeeeeeeeee"] can still be built even if its mem usage exceeds 1330.
require.True(t, strings.Contains(rows[2][0].(string), "IndexRangeScan"))
require.True(t, strings.Contains(rows[2][4].(string), "range:[\"aaaaaaaaaa\",\"aaaaaaaaaa\"], [\"bbbbbbbbbb\",\"bbbbbbbbbb\"], [\"cccccccccc\",\"cccccccccc\"], [\"dddddddddd\",\"dddddddddd\"], [\"eeeeeeeeee\",\"eeeeeeeeee\"]"))
// Test the plan with range fallback would not be put into cache.
tk.MustExec("prepare stmt2 from 'select * from t where a in (?, ?, ?, ?, ?) and b in (?, ?, ?, ?, ?)'")
tk.MustExec("set @a='aa', @b='bb', @c='cc', @d='dd', @e='ee', @f='ff', @g='gg', @h='hh', @i='ii', @j='jj'")
tk.MustExec("execute stmt2 using @a, @b, @c, @d, @e, @f, @g, @h, @i, @j")
tk.MustQuery("show warnings").Sort().Check(testkit.Rows("Warning 1105 Memory capacity of 1330 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen",
"Warning 1105 skip plan-cache: in-list is too long"))
tk.MustExec("execute stmt2 using @a, @b, @c, @d, @e, @f, @g, @h, @i, @j")
tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0"))
}
func TestCorColRangeWithRangeMaxSize(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2, t3")
tk.MustExec("create table t1(a int)")
tk.MustExec("create table t2 (a int, b int, c int, index idx_a_b(a, b))")
tk.MustExec("create table t3(a int primary key)")
tk.MustExec("insert into t1 values (2), (4), (6)")
tk.MustExec("insert into t2 (a, b) values (1, 2), (3, 2), (5, 2)")
tk.MustExec("insert into t3 values (2), (4)")
tk.MustExec("insert into mysql.opt_rule_blacklist value(\"decorrelate\")")
tk.MustExec("admin reload opt_rule_blacklist")
defer func() {
tk.MustExec("delete from mysql.opt_rule_blacklist where name = \"decorrelate\"")
tk.MustExec("admin reload opt_rule_blacklist")
}()
// Correlated column in index range.
tk.MustExec("set @@tidb_opt_range_max_size=1000")
rows := tk.MustQuery("explain format='brief' select * from t1 where exists (select * from t2 where t2.a in (1, 3, 5) and b >= 2 and t2.b = t1.a)").Rows()
// 1000 is not enough for [1 2,1 +inf], [3 2,3 +inf], [5 2,5 +inf]. So b >= 2 is not used to build ranges.
require.True(t, strings.Contains(rows[4][0].(string), "Selection"))
require.True(t, strings.Contains(rows[4][4].(string), "ge(test.t2.b, 2)"))
// 1000 is not enough for [1 ?,1 ?], [3 ?,3 ?], [5 ?,5 ?] but we don't restrict range mem usage when appending col = cor_col
// conditions to access conditions in SplitCorColAccessCondFromFilters.
require.True(t, strings.Contains(rows[5][0].(string), "IndexRangeScan"))
require.True(t, strings.Contains(rows[5][4].(string), "range: decided by [in(test.t2.a, 1, 3, 5) eq(test.t2.b, test.t1.a)]"))
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 Memory capacity of 1000 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen"))
// We need to rebuild index ranges each time the value of correlated column test.t1.a changes. We don't restrict range
// mem usage when rebuilding index ranges, otherwise range fallback would happen when rebuilding index ranges, causing
// to wrong query results.
tk.MustQuery("select * from t1 where exists (select * from t2 where t2.a in (1, 3, 5) and b >= 2 and t2.b = t1.a)").Check(testkit.Rows("2"))
// Correlated column in table range.
tk.MustExec("set @@tidb_opt_range_max_size=1")
rows = tk.MustQuery("explain format='brief' select * from t1 where exists (select * from t3 where t3.a = t1.a)").Rows()
// 1 is not enough for [?,?] but we don't restrict range mem usage when adding col = cor_col to access conditions.
require.True(t, strings.Contains(rows[4][0].(string), "TableRangeScan"))
require.True(t, strings.Contains(rows[4][4].(string), "range: decided by [eq(test.t3.a, test.t1.a)]"))
tk.MustQuery("show warnings").Check(testkit.Rows())
// We need to rebuild table ranges each time the value of correlated column test.t1.a changes. We don't restrict range
// mem usage when rebuilding table ranges, otherwise range fallback would happen when rebuilding table ranges, causing
// to wrong query results.
tk.MustQuery("select * from t1 where exists (select * from t3 where t3.a = t1.a)").Check(testkit.Rows("2", "4"))
}
func TestIssue37760(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.MustExec("insert into t values (2), (4), (6)")
tk.MustExec("set @@tidb_opt_range_max_size=1")
tk.MustQuery("select * from t where a").Check(testkit.Rows("2", "4", "6"))
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 Memory capacity of 1 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen"))
}
// TestExplainAnalyzeDMLCommit covers the issue #37373.
func TestExplainAnalyzeDMLCommit(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 (c1 int key, c2 int);")
tk.MustExec("insert into t values (1, 1)")
err := failpoint.Enable("github.com/pingcap/tidb/session/mockSleepBeforeTxnCommit", "return(500)")
require.NoError(t, err)
defer func() {
_ = failpoint.Disable("github.com/pingcap/tidb/session/mockSleepBeforeTxnCommit")
}()
// The commit is paused by the failpoint, after the fix the explain statement
// execution should proceed after the commit finishes.
_, err = tk.Exec("explain analyze delete from t;")
require.NoError(t, err)
tk.MustQuery("select * from t").Check(testkit.Rows())
}
func TestIndexJoinRangeFallback(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1(a int, b int, c varchar(10), d varchar(10), index idx_a_b_c_d(a, b, c(2), d(2)))")
tk.MustExec("create table t2(e int, f int, g varchar(10), h varchar(10))")
var input []string
var output []struct {
SQL string
Plan []string
Warn []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
setStmt := strings.HasPrefix(tt, "set")
testdata.OnRecord(func() {
output[i].SQL = tt
if !setStmt {
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())
}
})
if setStmt {
tk.MustExec(tt)
} else {
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()))
}
}
}
func TestPlanCacheForIndexJoinRangeFallback(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec(`set @@tidb_enable_prepared_plan_cache=1`)
tk.MustExec("set @@tidb_enable_collect_execution_info=0")
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2")
tk.MustExec("create table t1(a int, b varchar(10), c varchar(10), index idx_a_b(a, b))")
tk.MustExec("create table t2(d int)")
tk.MustExec("set @@tidb_opt_range_max_size=1275")
// 1275 is enough for [? a,? a], [? b,? b], [? c,? c] but is not enough for [? aaaaaa,? aaaaaa], [? bbbbbb,? bbbbbb], [? cccccc,? cccccc].
rows := tk.MustQuery("explain format='brief' select /*+ inl_join(t1) */ * from t1 join t2 on t1.a = t2.d where t1.b in ('a', 'b', 'c')").Rows()
require.True(t, strings.Contains(rows[6][4].(string), "range: decided by [eq(test.t1.a, test.t2.d) in(test.t1.b, a, b, c)]"))
tk.MustQuery("show warnings").Check(testkit.Rows())
rows = tk.MustQuery("explain format='brief' select /*+ inl_join(t1) */ * from t1 join t2 on t1.a = t2.d where t1.b in ('aaaaaa', 'bbbbbb', 'cccccc');").Rows()
require.True(t, strings.Contains(rows[6][4].(string), "range: decided by [eq(test.t1.a, test.t2.d)]"))
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 Memory capacity of 1275 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen"))
tk.MustExec("prepare stmt1 from 'select /*+ inl_join(t1) */ * from t1 join t2 on t1.a = t2.d where t1.b in (?, ?, ?)'")
tk.MustExec("set @a='a', @b='b', @c='c'")
tk.MustExec("execute stmt1 using @a, @b, @c")
tk.MustQuery("show warnings").Check(testkit.Rows())
tk.MustExec("set @a='aaaaaa', @b='bbbbbb', @c='cccccc'")
tk.MustExec("execute stmt1 using @a, @b, @c")
tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("1"))
tk.MustExec("execute stmt1 using @a, @b, @c")
tkProcess := tk.Session().ShowProcess()
ps := []*util.ProcessInfo{tkProcess}
tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps})
rows = tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Rows()
// We don't limit range mem usage when rebuilding index join ranges for the cached plan. So [? aaaaaa,? aaaaaa], [? bbbbbb,? bbbbbb], [? cccccc,? cccccc] can be built.
require.True(t, strings.Contains(rows[6][4].(string), "range: decided by [eq(test.t1.a, test.t2.d) in(test.t1.b, aaaaaa, bbbbbb, cccccc)]"))
// Test the plan with range fallback would not be put into cache.
tk.MustExec("prepare stmt2 from 'select /*+ inl_join(t1) */ * from t1 join t2 on t1.a = t2.d where t1.b in (?, ?, ?, ?, ?)'")
tk.MustExec("set @a='a', @b='b', @c='c', @d='d', @e='e'")
tk.MustExec("execute stmt2 using @a, @b, @c, @d, @e")
tk.MustQuery("show warnings").Sort().Check(testkit.Rows("Warning 1105 Memory capacity of 1275 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen",
"Warning 1105 skip plan-cache: in-list is too long"))
tk.MustExec("execute stmt2 using @a, @b, @c, @d, @e")
tk.MustQuery("select @@last_plan_from_cache").Check(testkit.Rows("0"))
}
// https://github.com/pingcap/tidb/issues/38295.
func TestIssue38295(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("CREATE TABLE t0(c0 BLOB(298) , c1 BLOB(182) , c2 NUMERIC);")
tk.MustExec("CREATE VIEW v0(c0) AS SELECT t0.c1 FROM t0;")
tk.MustExec("INSERT INTO t0 VALUES (-1, 'a', '2046549365');")
tk.MustExec("CREATE INDEX i0 ON t0(c2);")
tk.MustGetErrCode("SELECT t0.c1, t0.c2 FROM t0 GROUP BY MOD(t0.c0, DEFAULT(t0.c2));", errno.ErrFieldNotInGroupBy)
tk.MustExec("UPDATE t0 SET c2=1413;")
}
func TestOuterJoinEliminationForIssue18216(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2;")
tk.MustExec("create table t1 (a int, c int);")
tk.MustExec("insert into t1 values (1, 1), (1, 2), (2, 3), (2, 4);")
tk.MustExec("create table t2 (a int, c int);")
tk.MustExec("insert into t2 values (1, 1), (1, 2), (2, 3), (2, 4);")
// The output might be unstable.
tk.MustExec("select group_concat(c order by (select group_concat(c order by a) from t2 where a=t1.a)) from t1; ")
tk.MustQuery("select group_concat(c order by (select group_concat(c order by c) from t2 where a=t1.a), c desc) from t1;").Check(testkit.Rows("2,1,4,3"))
}
func TestNullConditionForPrefixIndex(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec(`CREATE TABLE t1 (
id char(1) DEFAULT NULL,
c1 varchar(255) DEFAULT NULL,
c2 text DEFAULT NULL,
KEY idx1 (c1),
KEY idx2 (c1,c2(5))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin`)
tk.MustExec("set tidb_cost_model_version=2")
tk.MustExec("create table t2(a int, b varchar(10), index idx(b(5)))")
tk.MustExec("create table t3(a int, b varchar(10), c int, primary key (a, b(5)) clustered)")
tk.MustExec("set tidb_opt_prefix_index_single_scan = 1")
tk.MustExec("insert into t1 values ('a', '0xfff', '111111'), ('b', '0xfff', '22 '), ('c', '0xfff', ''), ('d', '0xfff', null)")
tk.MustExec("insert into t2 values (1, 'aaaaaa'), (2, 'bb '), (3, ''), (4, null)")
tk.MustExec("insert into t3 values (1, 'aaaaaa', 2), (1, 'bb ', 3), (1, '', 4)")
var input []string
var output []struct {
SQL string
Plan []string
Result []string
}
integrationSuiteData := core.GetIntegrationSuiteData()
integrationSuiteData.LoadTestCases(t, &input, &output)
for i, tt := range input {
testdata.OnRecord(func() {
output[i].SQL = tt
output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format='brief' " + tt).Rows())
output[i].Result = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Sort().Rows())
})
tk.MustQuery("explain format='brief' " + tt).Check(testkit.Rows(output[i].Plan...))
tk.MustQuery(tt).Sort().Check(testkit.Rows(output[i].Result...))
}
// test plan cache
tk.MustExec(`set tidb_enable_prepared_plan_cache=1`)
tk.MustExec("set @@tidb_enable_collect_execution_info=0")
tk.MustExec("prepare stmt from 'select count(1) from t1 where c1 = ? and c2 is not null'")
tk.MustExec("set @a = '0xfff'")
tk.MustQuery("execute stmt using @a").Check(testkit.Rows("3"))
tk.MustQuery("execute stmt using @a").Check(testkit.Rows("3"))
tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1"))
tk.MustQuery("execute stmt using @a").Check(testkit.Rows("3"))
tkProcess := tk.Session().ShowProcess()
ps := []*util.ProcessInfo{tkProcess}
tk.Session().SetSessionManager(&testkit.MockSessionManager{PS: ps})
tk.MustQuery(fmt.Sprintf("explain for connection %d", tkProcess.ID)).Check(testkit.Rows(
"StreamAgg_18 1.00 root funcs:count(Column#7)->Column#5",
"└─IndexReader_19 1.00 root index:StreamAgg_9",
" └─StreamAgg_9 1.00 cop[tikv] funcs:count(1)->Column#7",
" └─IndexRangeScan_17 99.90 cop[tikv] table:t1, index:idx2(c1, c2) range:[\"0xfff\" -inf,\"0xfff\" +inf], keep order:false, stats:pseudo"))
}
func TestAutoIncrementCheckWithCheckConstraint(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec(`CREATE TABLE t (
id INTEGER NOT NULL AUTO_INCREMENT,
CHECK (id IN (0, 1)),
KEY idx_autoinc_id (id)
)`)
}
// https://github.com/pingcap/tidb/issues/36888.
func TestIssue36888(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("CREATE TABLE t0(c0 INT);")
tk.MustExec("CREATE TABLE t1(c0 INT);")
tk.MustExec("INSERT INTO t0 VALUES (NULL);")
tk.MustQuery("SELECT t0.c0 FROM t0 LEFT JOIN t1 ON t0.c0>=t1.c0 WHERE (CONCAT_WS(t0.c0, t1.c0) IS NULL);").Check(testkit.Rows("<nil>"))
}
// https://github.com/pingcap/tidb/issues/40285.
func TestIssue40285(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("CREATE TABLE t(col1 enum('p5', '9a33x') NOT NULL DEFAULT 'p5',col2 tinyblob DEFAULT NULL) ENGINE = InnoDB DEFAULT CHARSET = latin1 COLLATE = latin1_bin;")
tk.MustQuery("(select last_value(col1) over () as r0 from t) union all (select col2 as r0 from t);")
}