diff --git a/bindinfo/bind_test.go b/bindinfo/bind_test.go index ca6b376654c62..6167b7bd600b6 100644 --- a/bindinfo/bind_test.go +++ b/bindinfo/bind_test.go @@ -20,11 +20,9 @@ import ( "flag" "fmt" "os" - "strings" "testing" . "github.com/pingcap/check" - "github.com/pingcap/failpoint" "github.com/pingcap/parser" "github.com/pingcap/parser/auth" "github.com/pingcap/parser/model" @@ -32,7 +30,6 @@ import ( "github.com/pingcap/tidb/bindinfo" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/domain" - "github.com/pingcap/tidb/errno" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta/autoid" "github.com/pingcap/tidb/session" @@ -58,7 +55,6 @@ func TestT(t *testing.T) { } var _ = Suite(&testSuite{}) -var _ = SerialSuites(&testSerialSuite{}) type testSuite struct { cluster testutils.Cluster @@ -152,44 +148,6 @@ func (s *testSuite) cleanBindingEnv(tk *testkit.TestKit) { s.domain.BindHandle().Clear() } -type testSerialSuite struct { - cluster testutils.Cluster - store kv.Storage - domain *domain.Domain -} - -func (s *testSerialSuite) SetUpSuite(c *C) { - flag.Lookup("mockTikv") - useMockTikv := *mockTikv - if useMockTikv { - store, err := mockstore.NewMockStore( - mockstore.WithClusterInspector(func(c testutils.Cluster) { - mockstore.BootstrapWithSingleStore(c) - s.cluster = c - }), - ) - c.Assert(err, IsNil) - s.store = store - session.SetSchemaLease(0) - session.DisableStats4Test() - } - bindinfo.Lease = 0 - d, err := session.BootstrapSession(s.store) - c.Assert(err, IsNil) - d.SetStatsUpdating(true) - s.domain = d -} - -func (s *testSerialSuite) TearDownSuite(c *C) { - s.domain.Close() - s.store.Close() -} - -func (s *testSerialSuite) cleanBindingEnv(tk *testkit.TestKit) { - tk.MustExec("delete from mysql.bind_info where source != 'builtin'") - s.domain.BindHandle().Clear() -} - func normalizeWithDefaultDB(c *C, sql, db string) (string, string) { testParser := parser.New() stmt, err := testParser.ParseOneStmt(sql, "", "") @@ -1150,80 +1108,3 @@ func (s *testSuite) TestGCBindRecord(c *C) { tk.MustQuery("show global bindings").Check(testkit.Rows()) tk.MustQuery("select status from mysql.bind_info where original_sql = 'select * from `test` . `t` where `a` = ?'").Check(testkit.Rows()) } - -func (s *testSerialSuite) TestOptimizeOnlyOnce(c *C) { - tk := testkit.NewTestKit(c, s.store) - s.cleanBindingEnv(tk) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(a int, b int, index idxa(a))") - tk.MustExec("create global binding for select * from t using select * from t use index(idxa)") - c.Assert(failpoint.Enable("github.com/pingcap/tidb/planner/checkOptimizeCountOne", "return"), IsNil) - tk.MustQuery("select * from t").Check(testkit.Rows()) - c.Assert(failpoint.Disable("github.com/pingcap/tidb/planner/checkOptimizeCountOne"), IsNil) -} - -func (s *testSerialSuite) TestIssue26377(c *C) { - tk := testkit.NewTestKit(c, s.store) - s.cleanBindingEnv(tk) - tk.MustExec("use test") - tk.MustExec("set tidb_enable_global_temporary_table = true") - tk.MustExec("drop table if exists t1,tmp1") - tk.MustExec("create table t1(a int(11))") - tk.MustExec("create global temporary table tmp1(a int(11), key idx_a(a)) on commit delete rows;") - tk.MustExec("create temporary table tmp2(a int(11), key idx_a(a));") - - queries := []string{ - "create global binding for with cte1 as (select a from tmp1) select * from cte1 using with cte1 as (select a from tmp1) select * from cte1", - "create global binding for select * from t1 inner join tmp1 on t1.a=tmp1.a using select * from t1 inner join tmp1 on t1.a=tmp1.a;", - "create global binding for select * from t1 where t1.a in (select a from tmp1) using select * from t1 where t1.a in (select a from tmp1 use index (idx_a));", - "create global binding for select a from t1 union select a from tmp1 using select a from t1 union select a from tmp1 use index (idx_a);", - "create global binding for select t1.a, (select a from tmp1 where tmp1.a=1) as t2 from t1 using select t1.a, (select a from tmp1 where tmp1.a=1) as t2 from t1;", - "create global binding for select * from (select * from tmp1) using select * from (select * from tmp1);", - "create global binding for select * from t1 where t1.a = (select a from tmp1) using select * from t1 where t1.a = (select a from tmp1)", - } - genLocalTemporarySQL := func(sql string) string { - return strings.Replace(sql, "tmp1", "tmp2", -1) - } - for _, query := range queries { - localSQL := genLocalTemporarySQL(query) - queries = append(queries, localSQL) - } - - for _, q := range queries { - tk.MustGetErrCode(q, errno.ErrOptOnTemporaryTable) - } -} - -func (s *testSerialSuite) TestIssue27422(c *C) { - tk := testkit.NewTestKit(c, s.store) - s.cleanBindingEnv(tk) - tk.MustExec("use test") - tk.MustExec("set tidb_enable_global_temporary_table = true") - tk.MustExec("drop table if exists t1,tmp1,tmp2") - tk.MustExec("create table t1(a int(11))") - tk.MustExec("create global temporary table tmp1(a int(11), key idx_a(a)) on commit delete rows;") - tk.MustExec("create temporary table tmp2(a int(11), key idx_a(a));") - - queries := []string{ - "create global binding for insert into t1 (select * from tmp1) using insert into t1 (select * from tmp1);", - "create global binding for update t1 inner join tmp1 on t1.a=tmp1.a set t1.a=1 using update t1 inner join tmp1 on t1.a=tmp1.a set t1.a=1", - "create global binding for update t1 set t1.a=(select a from tmp1) using update t1 set t1.a=(select a from tmp1)", - "create global binding for update t1 set t1.a=1 where t1.a = (select a from tmp1) using update t1 set t1.a=1 where t1.a = (select a from tmp1)", - "create global binding for with cte1 as (select a from tmp1) update t1 set t1.a=1 where t1.a in (select a from cte1) using with cte1 as (select a from tmp1) update t1 set t1.a=1 where t1.a in (select a from cte1)", - "create global binding for delete from t1 where t1.a in (select a from tmp1) using delete from t1 where t1.a in (select a from tmp1)", - "create global binding for delete from t1 where t1.a = (select a from tmp1) using delete from t1 where t1.a = (select a from tmp1)", - "create global binding for delete t1 from t1,tmp1 using delete t1 from t1,tmp1", - } - genLocalTemporarySQL := func(sql string) string { - return strings.Replace(sql, "tmp1", "tmp2", -1) - } - for _, query := range queries { - localSQL := genLocalTemporarySQL(query) - queries = append(queries, localSQL) - } - - for _, q := range queries { - tk.MustGetErrCode(q, errno.ErrOptOnTemporaryTable) - } -} diff --git a/bindinfo/handle_test.go b/bindinfo/handle_serial_test.go similarity index 100% rename from bindinfo/handle_test.go rename to bindinfo/handle_serial_test.go diff --git a/bindinfo/optimize_serial_test.go b/bindinfo/optimize_serial_test.go new file mode 100644 index 0000000000000..228a44ab93693 --- /dev/null +++ b/bindinfo/optimize_serial_test.go @@ -0,0 +1,39 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bindinfo_test + +import ( + "testing" + + "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" +) + +func TestOptimizeOnlyOnce(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, b int, index idxa(a))") + tk.MustExec("create global binding for select * from t using select * from t use index(idxa)") + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/planner/checkOptimizeCountOne", "return")) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/planner/checkOptimizeCountOne")) + }() + tk.MustQuery("select * from t").Check(testkit.Rows()) +} diff --git a/bindinfo/temptable_serial_test.go b/bindinfo/temptable_serial_test.go new file mode 100644 index 0000000000000..779e144012320 --- /dev/null +++ b/bindinfo/temptable_serial_test.go @@ -0,0 +1,94 @@ +// Copyright 2021 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bindinfo_test + +import ( + "strings" + "testing" + + "github.com/pingcap/tidb/errno" + "github.com/pingcap/tidb/testkit" +) + +// TestSelectBindingOnGlobalTempTableProhibited covers https://github.com/pingcap/tidb/issues/26377 +func TestSelectBindingOnGlobalTempTableProhibited(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set tidb_enable_global_temporary_table = true") + tk.MustExec("drop table if exists t1,tmp1") + tk.MustExec("create table t1(a int(11))") + tk.MustExec("create global temporary table tmp1(a int(11), key idx_a(a)) on commit delete rows;") + tk.MustExec("create temporary table tmp2(a int(11), key idx_a(a));") + + queries := []string{ + "create global binding for with cte1 as (select a from tmp1) select * from cte1 using with cte1 as (select a from tmp1) select * from cte1", + "create global binding for select * from t1 inner join tmp1 on t1.a=tmp1.a using select * from t1 inner join tmp1 on t1.a=tmp1.a;", + "create global binding for select * from t1 where t1.a in (select a from tmp1) using select * from t1 where t1.a in (select a from tmp1 use index (idx_a));", + "create global binding for select a from t1 union select a from tmp1 using select a from t1 union select a from tmp1 use index (idx_a);", + "create global binding for select t1.a, (select a from tmp1 where tmp1.a=1) as t2 from t1 using select t1.a, (select a from tmp1 where tmp1.a=1) as t2 from t1;", + "create global binding for select * from (select * from tmp1) using select * from (select * from tmp1);", + "create global binding for select * from t1 where t1.a = (select a from tmp1) using select * from t1 where t1.a = (select a from tmp1)", + } + genLocalTemporarySQL := func(sql string) string { + return strings.Replace(sql, "tmp1", "tmp2", -1) + } + for _, query := range queries { + localSQL := genLocalTemporarySQL(query) + queries = append(queries, localSQL) + } + + for _, q := range queries { + tk.MustGetErrCode(q, errno.ErrOptOnTemporaryTable) + } +} + +// TestDMLBindingOnGlobalTempTableProhibited covers https://github.com/pingcap/tidb/issues/27422 +func TestDMLBindingOnGlobalTempTableProhibited(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set tidb_enable_global_temporary_table = true") + tk.MustExec("drop table if exists t1,tmp1,tmp2") + tk.MustExec("create table t1(a int(11))") + tk.MustExec("create global temporary table tmp1(a int(11), key idx_a(a)) on commit delete rows;") + tk.MustExec("create temporary table tmp2(a int(11), key idx_a(a));") + + queries := []string{ + "create global binding for insert into t1 (select * from tmp1) using insert into t1 (select * from tmp1);", + "create global binding for update t1 inner join tmp1 on t1.a=tmp1.a set t1.a=1 using update t1 inner join tmp1 on t1.a=tmp1.a set t1.a=1", + "create global binding for update t1 set t1.a=(select a from tmp1) using update t1 set t1.a=(select a from tmp1)", + "create global binding for update t1 set t1.a=1 where t1.a = (select a from tmp1) using update t1 set t1.a=1 where t1.a = (select a from tmp1)", + "create global binding for with cte1 as (select a from tmp1) update t1 set t1.a=1 where t1.a in (select a from cte1) using with cte1 as (select a from tmp1) update t1 set t1.a=1 where t1.a in (select a from cte1)", + "create global binding for delete from t1 where t1.a in (select a from tmp1) using delete from t1 where t1.a in (select a from tmp1)", + "create global binding for delete from t1 where t1.a = (select a from tmp1) using delete from t1 where t1.a = (select a from tmp1)", + "create global binding for delete t1 from t1,tmp1 using delete t1 from t1,tmp1", + } + genLocalTemporarySQL := func(sql string) string { + return strings.Replace(sql, "tmp1", "tmp2", -1) + } + for _, query := range queries { + localSQL := genLocalTemporarySQL(query) + queries = append(queries, localSQL) + } + + for _, q := range queries { + tk.MustGetErrCode(q, errno.ErrOptOnTemporaryTable) + } +}