3901 lines
153 KiB
Go
3901 lines
153 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,
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package core_test
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"strings"
|
|
|
|
. "github.com/pingcap/check"
|
|
"github.com/pingcap/errors"
|
|
"github.com/pingcap/parser/auth"
|
|
"github.com/pingcap/parser/model"
|
|
"github.com/pingcap/parser/mysql"
|
|
"github.com/pingcap/parser/terror"
|
|
"github.com/pingcap/tidb/config"
|
|
"github.com/pingcap/tidb/domain"
|
|
"github.com/pingcap/tidb/expression"
|
|
"github.com/pingcap/tidb/infoschema"
|
|
"github.com/pingcap/tidb/kv"
|
|
"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/table"
|
|
"github.com/pingcap/tidb/util/collate"
|
|
"github.com/pingcap/tidb/util/testkit"
|
|
"github.com/pingcap/tidb/util/testutil"
|
|
)
|
|
|
|
var _ = Suite(&testIntegrationSuite{})
|
|
var _ = SerialSuites(&testIntegrationSerialSuite{})
|
|
|
|
type testIntegrationSuite struct {
|
|
testData testutil.TestData
|
|
store kv.Storage
|
|
dom *domain.Domain
|
|
}
|
|
|
|
func (s *testIntegrationSuite) SetUpSuite(c *C) {
|
|
var err error
|
|
s.testData, err = testutil.LoadTestSuiteData("testdata", "integration_suite")
|
|
c.Assert(err, IsNil)
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TearDownSuite(c *C) {
|
|
c.Assert(s.testData.GenerateOutputIfNeeded(), IsNil)
|
|
}
|
|
|
|
func (s *testIntegrationSuite) SetUpTest(c *C) {
|
|
var err error
|
|
s.store, s.dom, err = newStoreWithBootstrap()
|
|
c.Assert(err, IsNil)
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TearDownTest(c *C) {
|
|
s.dom.Close()
|
|
err := s.store.Close()
|
|
c.Assert(err, IsNil)
|
|
}
|
|
|
|
type testIntegrationSerialSuite struct {
|
|
testData testutil.TestData
|
|
store kv.Storage
|
|
dom *domain.Domain
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) SetUpSuite(c *C) {
|
|
var err error
|
|
s.testData, err = testutil.LoadTestSuiteData("testdata", "integration_serial_suite")
|
|
c.Assert(err, IsNil)
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TearDownSuite(c *C) {
|
|
c.Assert(s.testData.GenerateOutputIfNeeded(), IsNil)
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) SetUpTest(c *C) {
|
|
var err error
|
|
s.store, s.dom, err = newStoreWithBootstrap()
|
|
c.Assert(err, IsNil)
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TearDownTest(c *C) {
|
|
s.dom.Close()
|
|
err := s.store.Close()
|
|
c.Assert(err, IsNil)
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestShowSubquery(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
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)").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 (s *testIntegrationSuite) TestPpdWithSetVar(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestBitColErrorMessage(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestPushLimitDownIndexLookUpReader(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestAggColumnPrune(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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),(2)")
|
|
|
|
var input []string
|
|
var output []struct {
|
|
SQL string
|
|
Res []string
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Res = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
tk.MustQuery(tt).Check(testkit.Rows(output[i].Res...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestIsFromUnixtimeNullRejective(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
tk.MustExec(`drop table if exists t;`)
|
|
tk.MustExec(`create table t(a bigint, b bigint);`)
|
|
s.runTestsWithTestData("TestIsFromUnixtimeNullRejective", tk, c)
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestIssue22298(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestIssue24571(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestIssue22828(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) runTestsWithTestData(caseName string, tk *testkit.TestKit, c *C) {
|
|
var input []string
|
|
var output []struct {
|
|
SQL string
|
|
Plan []string
|
|
}
|
|
s.testData.GetTestCasesByName(caseName, c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestJoinNotNullFlag(c *C) {
|
|
store, dom, err := newStoreWithBootstrap()
|
|
c.Assert(err, IsNil)
|
|
tk := testkit.NewTestKit(c, store)
|
|
defer func() {
|
|
dom.Close()
|
|
store.Close()
|
|
}()
|
|
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 (s *testIntegrationSuite) TestAntiJoinConstProp(c *C) {
|
|
store, dom, err := newStoreWithBootstrap()
|
|
c.Assert(err, IsNil)
|
|
tk := testkit.NewTestKit(c, store)
|
|
defer func() {
|
|
dom.Close()
|
|
store.Close()
|
|
}()
|
|
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 (s *testIntegrationSuite) TestSimplifyOuterJoinWithCast(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestNoneAccessPathsFoundByIsolationRead(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
|
|
tk.MustExec("use test")
|
|
tk.MustExec("drop table if exists t")
|
|
tk.MustExec("create table t(a int primary key)")
|
|
|
|
_, err := tk.Exec("select * from t")
|
|
c.Assert(err, IsNil)
|
|
|
|
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")
|
|
c.Assert(err, NotNil)
|
|
c.Assert(err.Error(), Equals, "[planner:1815]Internal : Can not find access path matching 'tidb_isolation_read_engines'(value: 'tiflash'). Available values are 'tikv'.")
|
|
|
|
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 (s *testIntegrationSerialSuite) TestSelPushDownTiFlash(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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")
|
|
|
|
var input []string
|
|
var output []struct {
|
|
SQL string
|
|
Plan []string
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestVerboseExplain(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
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")
|
|
|
|
// Create virtual tiflash replica info.
|
|
dom := domain.GetDomain(tk.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestPushDownToTiFlashWithKeepOrder(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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")
|
|
var input []string
|
|
var output []struct {
|
|
SQL string
|
|
Plan []string
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestMPPJoin(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestMPPOuterJoinBuildSideForBroadcastJoin(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestMPPOuterJoinBuildSideForShuffleJoinWithFixedBuildSide(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestMPPOuterJoinBuildSideForShuffleJoin(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestMPPShuffledJoin(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestJoinNotSupportedByTiFlash(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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")
|
|
|
|
// Create virtual tiflash replica info.
|
|
dom := domain.GetDomain(tk.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.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")
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
|
|
tk.MustExec("set @@session.tidb_allow_mpp = 0")
|
|
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'")
|
|
tk.MustExec("set @@session.tidb_allow_batch_cop = 1")
|
|
tk.MustExec("set @@session.tidb_opt_broadcast_join = 1")
|
|
// make cbo force choose broadcast join since sql hint does not work for semi/anti-semi join
|
|
tk.MustExec("set @@session.tidb_opt_cpu_factor=10000000;")
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestMPPWithHashExchangeUnderNewCollation(c *C) {
|
|
defer collate.SetNewCollationEnabledForTest(false)
|
|
tk := testkit.NewTestKit(c, s.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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
for _, tblInfo := range db.Tables {
|
|
if tblInfo.Name.L == "table_1" {
|
|
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
|
|
Count: 1,
|
|
Available: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
collate.SetNewCollationEnabledForTest(true)
|
|
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'")
|
|
tk.MustExec("set @@session.tidb_allow_mpp = 1")
|
|
tk.MustExec("set @@session.tidb_opt_broadcast_join = 0")
|
|
tk.MustExec("set @@session.tidb_broadcast_join_threshold_count = 0")
|
|
tk.MustExec("set @@session.tidb_broadcast_join_threshold_size = 0")
|
|
var input []string
|
|
var output []struct {
|
|
SQL string
|
|
Plan []string
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestMPPWithBroadcastExchangeUnderNewCollation(c *C) {
|
|
defer collate.SetNewCollationEnabledForTest(false)
|
|
tk := testkit.NewTestKit(c, s.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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
for _, tblInfo := range db.Tables {
|
|
if tblInfo.Name.L == "table_1" {
|
|
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
|
|
Count: 1,
|
|
Available: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
collate.SetNewCollationEnabledForTest(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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestPartitionTableDynamicModeUnderNewCollation(c *C) {
|
|
collate.SetNewCollationEnabledForTest(true)
|
|
defer collate.SetNewCollationEnabledForTest(false)
|
|
tk := testkit.NewTestKitWithInit(c, s.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(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 (s *testIntegrationSerialSuite) TestMPPAvgRewrite(c *C) {
|
|
defer collate.SetNewCollationEnabledForTest(false)
|
|
tk := testkit.NewTestKit(c, s.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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
for _, tblInfo := range db.Tables {
|
|
if tblInfo.Name.L == "table_1" {
|
|
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
|
|
Count: 1,
|
|
Available: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
collate.SetNewCollationEnabledForTest(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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestAggPushDownEngine(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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("desc select approx_count_distinct(a) from t").Check(testkit.Rows(
|
|
"HashAgg_11 1.00 root funcs:approx_count_distinct(Column#4)->Column#3",
|
|
"└─TableReader_12 1.00 root data:HashAgg_6",
|
|
" └─HashAgg_6 1.00 batchCop[tiflash] funcs:approx_count_distinct(test.t.a)->Column#4",
|
|
" └─TableFullScan_10 10000.00 batchCop[tiflash] table:t keep order:false, stats:pseudo"))
|
|
|
|
tk.MustExec("set @@session.tidb_isolation_read_engines = 'tikv'")
|
|
|
|
tk.MustQuery("desc select approx_count_distinct(a) from t").Check(testkit.Rows(
|
|
"HashAgg_5 1.00 root funcs:approx_count_distinct(test.t.a)->Column#3",
|
|
"└─TableReader_11 10000.00 root data:TableFullScan_10",
|
|
" └─TableFullScan_10 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"))
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestIssue15110(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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 (s *testIntegrationSerialSuite) TestReadFromStorageHint(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
|
|
tk.MustExec("use test")
|
|
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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
output[i].Warn = s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
c.Assert(s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings()), DeepEquals, output[i].Warn)
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestReadFromStorageHintAndIsolationRead(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
|
|
tk.MustExec("use test")
|
|
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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
tk.Se.GetSessionVars().StmtCtx.SetWarnings(nil)
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
output[i].Warn = s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
c.Assert(s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings()), DeepEquals, output[i].Warn)
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestIsolationReadTiFlashNotChoosePointGet(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Result = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
tk.MustQuery(tt).Check(testkit.Rows(output[i].Result...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestIsolationReadTiFlashUseIndexHint(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
output[i].Warn = s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
c.Assert(s.testData.ConvertSQLWarnToStrings(tk.Se.GetSessionVars().StmtCtx.GetWarnings()), DeepEquals, output[i].Warn)
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestIsolationReadDoNotFilterSystemDB(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
|
|
tk.MustExec("use test")
|
|
tk.MustExec("set @@tidb_isolation_read_engines = \"tiflash\"")
|
|
var input []string
|
|
var output []struct {
|
|
SQL string
|
|
Plan []string
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestPartitionTableStats(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
{
|
|
tk.MustExec(`set @@tidb_partition_prune_mode='` + string(variable.Static) + `'`)
|
|
tk.MustExec("use test")
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Result = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
tk.MustQuery(tt).Check(testkit.Rows(output[i].Result...))
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestPartitionPruningForInExpr(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestPartitionPruningWithDateType(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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)
|
|
c.Assert(strings.Contains(str, "partition:p1"), IsTrue)
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestPartitionPruningForEQ(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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.Se.GetInfoSchema().(infoschema.InfoSchema)
|
|
tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
|
|
c.Assert(err, IsNil)
|
|
pt := tbl.(table.PartitionedTable)
|
|
query, err := expression.ParseSimpleExprWithTableInfo(tk.Se, "a = '2020-01-01 00:00:00'", tbl.Meta())
|
|
c.Assert(err, IsNil)
|
|
dbName := model.NewCIStr(tk.Se.GetSessionVars().CurrentDB)
|
|
columns, names, err := expression.ColumnInfos2ColumnsAndNames(tk.Se, dbName, tbl.Meta().Name, tbl.Meta().Cols(), tbl.Meta())
|
|
c.Assert(err, IsNil)
|
|
// 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.Se, pt, []expression.Expression{query}, nil, columns, names)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(res, HasLen, 1)
|
|
c.Assert(res[0], Equals, 0)
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestErrNoDB(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("create user test")
|
|
_, err := tk.Exec("grant select on test1111 to test@'%'")
|
|
c.Assert(errors.Cause(err), Equals, core.ErrNoDB)
|
|
tk.MustExec("use test")
|
|
tk.MustExec("create table test1111 (id int)")
|
|
tk.MustExec("grant select on test1111 to test@'%'")
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestMaxMinEliminate(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
|
|
tk.MustExec("use test")
|
|
tk.MustExec("drop table if exists t")
|
|
tk.MustExec("create table t(a int primary key)")
|
|
tk.Se.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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestINLJHintSmallTable(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
tk.MustExec("drop table if exists t1, t2")
|
|
tk.MustExec("create table t1(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 (s *testIntegrationSuite) TestIndexJoinUniqueCompositeIndex(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
|
|
tk.MustExec("use test")
|
|
tk.MustExec("drop table if exists t1, t2")
|
|
tk.Se.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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestIndexMerge(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestIndexMergeHint4CNF(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestInvisibleIndex(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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)")
|
|
|
|
// Optimizer cannot use invisible indexes.
|
|
tk.MustQuery("select a from t order by a").Check(testkit.Rows("1"))
|
|
c.Check(tk.MustUseIndex("select a from t order by a", "i_a"), IsFalse)
|
|
tk.MustQuery("select a from t where a > 0").Check(testkit.Rows("1"))
|
|
c.Check(tk.MustUseIndex("select a from t where a > 1", "i_a"), IsFalse)
|
|
|
|
// 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")
|
|
c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings(), HasLen, 1)
|
|
c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings()[0].Err.Error(), Equals, errStr)
|
|
tk.MustQuery("select /*+ IGNORE_INDEX(t, i_a), USE_INDEX(t, i_b) */ a from t order by a")
|
|
c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings(), HasLen, 1)
|
|
c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings()[0].Err.Error(), Equals, errStr)
|
|
|
|
tk.MustExec("admin check table t")
|
|
tk.MustExec("admin check index t i_a")
|
|
}
|
|
|
|
// for issue #14822
|
|
func (s *testIntegrationSuite) TestIndexJoinTableRange(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
|
|
tk.MustExec("use test")
|
|
tk.MustExec("drop table if exists t1, t2")
|
|
tk.MustExec("create table t1(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))")
|
|
|
|
var input []string
|
|
var output []struct {
|
|
SQL string
|
|
Plan []string
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestTopNByConstFunc(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestSubqueryWithTopN(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestIndexHintWarning(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
tk.MustExec("drop table if exists t1, t2")
|
|
tk.MustExec("create table t1(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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
tk.MustQuery(tt)
|
|
warns := tk.Se.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.Se.GetSessionVars().StmtCtx.GetWarnings()
|
|
c.Assert(len(warns), Equals, len(output[i].Warnings))
|
|
for j := range warns {
|
|
c.Assert(warns[j].Level, Equals, stmtctx.WarnLevelWarning)
|
|
c.Assert(warns[j].Err.Error(), Equals, output[i].Warnings[j])
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestIssue15546(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestApproxCountDistinctInPartitionTable(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestApproxPercentile(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain " + tt).Rows())
|
|
output[i].Res = s.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 (s *testIntegrationSuite) TestIssue17813(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestHintWithRequiredProperty(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
warnings := tk.Se.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.Se.GetSessionVars().StmtCtx.GetWarnings()
|
|
c.Assert(len(warnings), Equals, len(output[i].Warnings))
|
|
for j, warning := range warnings {
|
|
c.Assert(output[i].Warnings[j], Equals, warning.Err.Error())
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestIssue15813(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestFullGroupByOrderBy(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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")
|
|
c.Assert(terror.ErrorEqual(err, core.ErrFieldNotInGroupBy), IsTrue)
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestHintWithoutTableWarning(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
tk.MustExec("drop table if exists t1, t2")
|
|
tk.MustExec("create table t1(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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
tk.MustQuery(tt)
|
|
warns := tk.Se.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.Se.GetSessionVars().StmtCtx.GetWarnings()
|
|
c.Assert(len(warns), Equals, len(output[i].Warnings))
|
|
for j := range warns {
|
|
c.Assert(warns[j].Level, Equals, stmtctx.WarnLevelWarning)
|
|
c.Assert(warns[j].Err.Error(), Equals, output[i].Warnings[j])
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestIssue15858(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestIssue15846(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestFloorUnixTimestampPruning(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestIssue16290And16292(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestTableDualWithRequiredProperty(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
tk.MustExec("drop table if exists t1, t2;")
|
|
tk.MustExec("create table t1 (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 (s *testIntegrationSuite) TestIndexJoinInnerIndexNDV(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
tk.MustExec("drop table if exists t1, t2")
|
|
tk.MustExec("create table t1(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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestIssue16837(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 ",
|
|
"├─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 (s *testIntegrationSerialSuite) TestIndexMerge(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
output[i].Warnings = s.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 (s *testIntegrationSerialSuite) TestIndexMergePartialScansClusteredIndex(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSerialSuite) TestIndexMergePartialScansTiDBRowID(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSerialSuite) TestIndexMergePartialScansPKIsHandle(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSerialSuite) TestIssue23919(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSerialSuite) TestIssue16407(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 ",
|
|
"├─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 (s *testIntegrationSuite) TestStreamAggProp(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows())
|
|
output[i].Res = s.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 (s *testIntegrationSuite) TestOptimizeHintOnPartitionTable(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows())
|
|
output[i].Warn = s.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 (s *testIntegrationSerialSuite) TestNotReadOnlySQLOnTiFlash(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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")
|
|
c.Assert(err, NotNil)
|
|
c.Assert(err.Error(), Equals, `[planner:1815]Internal : Can not find access path matching 'tidb_isolation_read_engines'(value: 'tiflash'). Available values are 'tiflash, tikv'.`)
|
|
|
|
err = tk.ExecToErr("insert into t select * from t")
|
|
c.Assert(err, NotNil)
|
|
c.Assert(err.Error(), Equals, `[planner:1815]Internal : Can not find access path matching 'tidb_isolation_read_engines'(value: 'tiflash'). Available values are 'tiflash, tikv'.`)
|
|
|
|
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")
|
|
c.Assert(err, NotNil)
|
|
c.Assert(err.Error(), Equals, `[planner:1815]Internal : Can not find access path matching 'tidb_isolation_read_engines'(value: 'tiflash'). Available values are 'tiflash, tikv'.`)
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestSelectLimit(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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)")
|
|
|
|
// normal test
|
|
tk.MustExec("set @@session.sql_select_limit=1")
|
|
result := tk.MustQuery("select * from t order by a")
|
|
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.Check(testkit.Rows("1", "1", "2"))
|
|
result = tk.MustQuery("select * from (select * from t) s limit 3") // select_limit will not effect subquery
|
|
result.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.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.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 (s *testIntegrationSuite) TestHintParserWarnings(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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()
|
|
c.Assert(len(rows), Equals, 1)
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestIssue16935(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestAccessPathOnClusterIndex(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
tk.Se.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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format='brief' " + tt).Rows())
|
|
output[i].Res = s.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 (s *testIntegrationSuite) TestClusterIndexUniqueDoubleRead(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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.Se.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 (s *testIntegrationSuite) TestIndexJoinOnClusteredIndex(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
tk.Se.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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows())
|
|
output[i].Res = s.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 (s *testIntegrationSerialSuite) TestIssue18984(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
tk.MustExec("drop table if exists t, t2")
|
|
tk.Se.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 (s *testIntegrationSuite) TestDistinctScalarFunctionPushDown(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSerialSuite) TestExplainAnalyzePointGet(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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()
|
|
c.Assert(strings.Contains(explain, rpc+":{num_rpc:"), IsTrue, Commentf("%s", explain))
|
|
c.Assert(strings.Contains(explain, "total_time:"), IsTrue, Commentf("%s", explain))
|
|
}
|
|
checkExplain("Get")
|
|
res = tk.MustQuery("explain analyze select * from t where a in (1,2,3);")
|
|
checkExplain("BatchGet")
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestExplainAnalyzeDML(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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()
|
|
c.Assert(strings.Contains(explain, rpc+":{num_rpc:"), IsTrue, Commentf("%s", explain))
|
|
c.Assert(strings.Contains(explain, "total_time:"), IsTrue, Commentf("%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 (s *testIntegrationSuite) TestPartitionExplain(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain " + tt).Rows())
|
|
})
|
|
tk.MustQuery("explain " + tt).Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestPartialBatchPointGet(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestIssue19926(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestDeleteUsingJoin(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
tk.MustExec("drop table if exists t1, t2")
|
|
tk.MustExec("create table t1(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 (s *testIntegrationSerialSuite) Test19942(c *C) {
|
|
collate.SetNewCollationEnabledForTest(true)
|
|
defer collate.SetNewCollationEnabledForTest(false)
|
|
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
tk.Se.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 testutil.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 (s *testIntegrationSuite) TestPartitionUnionWithPPruningColumn(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestIssue20139(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestIssue14481(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 8000.00 root rows:0"))
|
|
tk.MustExec("drop table t")
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestIssue20710(c *C) {
|
|
tk := testkit.NewTestKitWithInit(c, s.store)
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestQueryBlockTableAliasInHint(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
|
|
tk.MustExec("use test")
|
|
c.Assert(tk.HasPlan("select /*+ HASH_JOIN(@sel_1 t2) */ * FROM (select 1) t1 NATURAL LEFT JOIN (select 2) t2", "HashJoin"), IsTrue)
|
|
tk.MustQuery("select /*+ HASH_JOIN(@sel_1 t2) */ * FROM (select 1) t1 NATURAL LEFT JOIN (select 2) t2").Check(testkit.Rows(
|
|
"1 2",
|
|
))
|
|
c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings(), HasLen, 0)
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestIssue10448(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestMultiUpdateOnPrimaryKey(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestOrderByHavingNotInSelect(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestUpdateSetDefault(c *C) {
|
|
// #20598
|
|
tk := testkit.NewTestKit(c, s.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.MustQuery("select * from tt").Check(testkit.Rows("2 12"))
|
|
|
|
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 (s *testIntegrationSuite) TestExtendedStatsSwitch(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestOrderByNotInSelectDistinct(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestInvalidNamedWindowSpec(c *C) {
|
|
// #12356
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestCorrelatedAggregate(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestCorrelatedColumnAggFuncPushDown(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestConditionColPruneInPhysicalUnionScan(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestInvalidHint(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
warning := "show warnings;"
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
output[i].Warnings = s.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 (s *testIntegrationSuite) TestNonaggregateColumnWithSingleValueInOnlyFullGroupByMode(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestConvertRangeToPoint(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestIssue22040(c *C) {
|
|
// #22040
|
|
tk := testkit.NewTestKit(c, s.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)")
|
|
c.Assert(errors.Cause(err), FitsTypeOf, expression.ErrOperandColumns)
|
|
}
|
|
{
|
|
err := tk.ExecToErr("select * from t where (a,b) in ((1,2),1)")
|
|
c.Assert(errors.Cause(err), FitsTypeOf, expression.ErrOperandColumns)
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestIssue22105(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestIssue22071(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestCreateViewIsolationRead(c *C) {
|
|
se, err := session.CreateSession4Test(s.store)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(se.Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil), IsTrue)
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.Se = 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 : Can not find access path matching 'tidb_isolation_read_engines'(value: 'tiflash,tidb'). Available values are 'tikv'.")
|
|
tk.MustExec("set session tidb_isolation_read_engines='tikv,tiflash,tidb';")
|
|
tk.MustQuery("select * from v0;").Check(testkit.Rows())
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestIssue22199(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
tk.MustExec("drop table if exists t1, t2")
|
|
tk.MustExec("create table t1(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 (s *testIntegrationSuite) TestIssue22892(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSerialSuite) TestPushDownProjectionForTiFlash(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
tk.MustExec("drop table if exists t")
|
|
tk.MustExec("create table t (id int, value decimal(6,3))")
|
|
tk.MustExec("analyze table t")
|
|
tk.MustExec("set session tidb_allow_mpp=OFF")
|
|
|
|
// Create virtual tiflash replica info.
|
|
dom := domain.GetDomain(tk.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
for _, tblInfo := range db.Tables {
|
|
if tblInfo.Name.L == "t" {
|
|
tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{
|
|
Count: 1,
|
|
Available: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
tk.MustExec("set @@tidb_opt_broadcast_join=1;")
|
|
|
|
var input []string
|
|
var output []struct {
|
|
SQL string
|
|
Plan []string
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestPushDownProjectionForMPP(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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_opt_broadcast_join=0;")
|
|
|
|
var input []string
|
|
var output []struct {
|
|
SQL string
|
|
Plan []string
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestReorderSimplifiedOuterJoins(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
|
|
tk.MustExec("use test")
|
|
tk.MustExec("drop table if exists t1,t2,t3")
|
|
tk.MustExec("create table t1 (pk char(32) primary key, 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, col1 varchar(100))")
|
|
tk.MustExec("create table t3 (pk char(32) primary key, 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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.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 (s *testIntegrationSerialSuite) TestIssue23887(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows())
|
|
output[i].Res = s.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 (s *testIntegrationSerialSuite) TestDeleteStmt(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestIndexMergeConstantTrue(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSerialSuite) TestPushDownAggForMPP(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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_opt_broadcast_join=0; set @@tidb_broadcast_join_threshold_count = 1; set @@tidb_broadcast_join_threshold_size=1;")
|
|
|
|
var input []string
|
|
var output []struct {
|
|
SQL string
|
|
Plan []string
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestMppUnionAll(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestMppJoinDecimal(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestMppAggTopNWithJoin(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestLimitIndexLookUpKeepOrder(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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, index idx(a,b,c));")
|
|
|
|
var input []string
|
|
var output []struct {
|
|
SQL string
|
|
Plan []string
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestDecorrelateInnerJoinInSubquery(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
tk.MustQuery(tt).Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestIndexMergeTableFilter(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 ",
|
|
"├─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 ",
|
|
"├─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 (s *testIntegrationSuite) TestIssue22850(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestJoinSchemaChange(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
tk.MustExec("drop table if exists t1, t2")
|
|
tk.MustExec("create table t1(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 (s *testIntegrationSuite) TestGetVarExprWithHexLiteral(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestGetVarExprWithBitLiteral(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestIndexMergeClusterIndex(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestMultiColMaxOneRow(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
|
|
tk.MustExec("use test")
|
|
tk.MustExec("drop table if exists t1,t2")
|
|
tk.MustExec("create table t1(a int)")
|
|
tk.MustExec("create table t2(a int, b int, c int, primary key(a,b))")
|
|
|
|
var input []string
|
|
var output []struct {
|
|
SQL string
|
|
Plan []string
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows())
|
|
})
|
|
tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestIssue23736(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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
|
|
c.Assert(tk.MustUseIndex("select /*+ stream_agg() */ count(1) from t0 where c > 10 and b < 2", "c"), IsFalse)
|
|
}
|
|
|
|
// https://github.com/pingcap/tidb/issues/23802
|
|
func (s *testIntegrationSuite) TestPanicWhileQueryTableWithIsNull(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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;")
|
|
_, err := tk.Exec("select col1 from NT_HP27193 where col1 is null;")
|
|
c.Assert(err, IsNil)
|
|
tk.MustExec("INSERT INTO NT_HP27193 (COL2, COL4, COL3, COL5) VALUES ('m', '2020-05-04 13:15:27', 8, 2602)")
|
|
_, err = tk.Exec("select col1 from NT_HP27193 where col1 is null;")
|
|
c.Assert(err, IsNil)
|
|
tk.MustExec("drop table if exists NT_HP27193")
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestIssue23846(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestIssue23839(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestIssue24095(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test;")
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows())
|
|
})
|
|
tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestIssue24281(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestLimitWindowColPrune(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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 (s *testIntegrationSuite) TestIncrementalAnalyzeStatsVer2(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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.Se.GetInfoSchema().(infoschema.InfoSchema)
|
|
tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
|
|
c.Assert(err, IsNil)
|
|
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()
|
|
c.Assert(len(rows), Equals, 1)
|
|
c.Assert(rows[0][0], Equals, "3")
|
|
tk.MustExec("insert into t values(4,4),(5,5),(6,6)")
|
|
tk.MustExec("analyze incremental table t index idx_b")
|
|
c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings(), HasLen, 2)
|
|
c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings()[0].Err.Error(), Equals, "The version 2 would collect all statistics not only the selected indexes")
|
|
c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings()[1].Err.Error(), Equals, "The version 2 stats would ignore the INCREMENTAL keyword and do full sampling")
|
|
rows = tk.MustQuery(fmt.Sprintf("select distinct_count from mysql.stats_histograms where table_id = %d and is_index = 1", tblID)).Rows()
|
|
c.Assert(len(rows), Equals, 1)
|
|
c.Assert(rows[0][0], Equals, "6")
|
|
}
|
|
|
|
func (s *testIntegrationSuite) TestConflictReadFromStorage(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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 (s *testIntegrationSuite) TestSequenceAsDataSource(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
|
|
tk.MustExec("use test")
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + tt).Rows())
|
|
})
|
|
tk.MustQuery("explain format = 'brief' " + tt).Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|
|
|
|
func (s *testIntegrationSerialSuite) TestMergeContinuousSelections(c *C) {
|
|
tk := testkit.NewTestKit(c, s.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.Se)
|
|
is := dom.InfoSchema()
|
|
db, exists := is.SchemaByName(model.NewCIStr("test"))
|
|
c.Assert(exists, IsTrue)
|
|
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
|
|
}
|
|
s.testData.GetTestCases(c, &input, &output)
|
|
for i, tt := range input {
|
|
s.testData.OnRecord(func() {
|
|
output[i].SQL = tt
|
|
output[i].Plan = s.testData.ConvertRowsToStrings(tk.MustQuery(tt).Rows())
|
|
})
|
|
res := tk.MustQuery(tt)
|
|
res.Check(testkit.Rows(output[i].Plan...))
|
|
}
|
|
}
|