From 06fe7fec6912b3246451339d63919d8f53198542 Mon Sep 17 00:00:00 2001 From: Arenatlx <314806019@qq.com> Date: Mon, 5 Jun 2023 19:15:40 +0800 Subject: [PATCH 1/3] This is an automated cherry-pick of #44414 Signed-off-by: ti-chi-bot --- executor/builder.go | 6 + executor/test/partitiontest/partition_test.go | 505 ++++++++++++++++++ 2 files changed, 511 insertions(+) create mode 100644 executor/test/partitiontest/partition_test.go diff --git a/executor/builder.go b/executor/builder.go index a99d1428fa48a..77e474aa63ecb 100644 --- a/executor/builder.go +++ b/executor/builder.go @@ -4172,6 +4172,9 @@ func (builder *dataReaderBuilder) buildTableReaderForIndexJoin(ctx context.Conte locateKey[keyColOffsets[i]] = data } p, err := pt.GetPartitionByRow(e.ctx, locateKey) + if table.ErrNoPartitionForGivenValue.Equal(err) { + continue + } if err != nil { return nil, err } @@ -4216,6 +4219,9 @@ func (builder *dataReaderBuilder) buildTableReaderForIndexJoin(ctx context.Conte locateKey[keyColOffsets[i]] = data } p, err := pt.GetPartitionByRow(e.ctx, locateKey) + if table.ErrNoPartitionForGivenValue.Equal(err) { + continue + } if err != nil { return nil, err } diff --git a/executor/test/partitiontest/partition_test.go b/executor/test/partitiontest/partition_test.go new file mode 100644 index 0000000000000..d9614cd808ec3 --- /dev/null +++ b/executor/test/partitiontest/partition_test.go @@ -0,0 +1,505 @@ +// Copyright 2023 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 partitiontest + +import ( + "fmt" + "testing" + + "github.com/pingcap/failpoint" + "github.com/pingcap/tidb/testkit" + "github.com/stretchr/testify/require" +) + +func TestPartitionedTableReplace(t *testing.T) { + failpoint.Enable("github.com/pingcap/tidb/planner/core/forceDynamicPrune", `return(true)`) + defer failpoint.Disable("github.com/pingcap/tidb/planner/core/forceDynamicPrune") + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + testSQL := `drop table if exists replace_test; + create table replace_test (id int PRIMARY KEY AUTO_INCREMENT, c1 int, c2 int, c3 int default 1) + partition by range (id) ( + PARTITION p0 VALUES LESS THAN (3), + PARTITION p1 VALUES LESS THAN (5), + PARTITION p2 VALUES LESS THAN (7), + PARTITION p3 VALUES LESS THAN (9));` + tk.MustExec(testSQL) + testSQL = `replace replace_test (c1) values (1),(2),(NULL);` + tk.MustExec(testSQL) + require.Equal(t, tk.Session().LastMessage(), "Records: 3 Duplicates: 0 Warnings: 0") + + errReplaceSQL := `replace replace_test (c1) values ();` + tk.MustExec("begin") + err := tk.ExecToErr(errReplaceSQL) + require.Error(t, err) + tk.MustExec("rollback") + + errReplaceSQL = `replace replace_test (c1, c2) values (1,2),(1);` + tk.MustExec("begin") + err = tk.ExecToErr(errReplaceSQL) + require.Error(t, err) + tk.MustExec("rollback") + + errReplaceSQL = `replace replace_test (xxx) values (3);` + tk.MustExec("begin") + err = tk.ExecToErr(errReplaceSQL) + require.Error(t, err) + tk.MustExec("rollback") + + errReplaceSQL = `replace replace_test_xxx (c1) values ();` + tk.MustExec("begin") + err = tk.ExecToErr(errReplaceSQL) + require.Error(t, err) + tk.MustExec("rollback") + + replaceSetSQL := `replace replace_test set c1 = 3;` + tk.MustExec(replaceSetSQL) + require.Empty(t, tk.Session().LastMessage()) + + errReplaceSetSQL := `replace replace_test set c1 = 4, c1 = 5;` + tk.MustExec("begin") + err = tk.ExecToErr(errReplaceSetSQL) + require.Error(t, err) + tk.MustExec("rollback") + + errReplaceSetSQL = `replace replace_test set xxx = 6;` + tk.MustExec("begin") + err = tk.ExecToErr(errReplaceSetSQL) + require.Error(t, err) + tk.MustExec("rollback") + + tk.MustExec(`drop table if exists replace_test_1`) + tk.MustExec(`create table replace_test_1 (id int, c1 int) partition by range (id) ( + PARTITION p0 VALUES LESS THAN (4), + PARTITION p1 VALUES LESS THAN (6), + PARTITION p2 VALUES LESS THAN (8), + PARTITION p3 VALUES LESS THAN (10), + PARTITION p4 VALUES LESS THAN (100))`) + tk.MustExec(`replace replace_test_1 select id, c1 from replace_test;`) + require.Equal(t, tk.Session().LastMessage(), "Records: 4 Duplicates: 0 Warnings: 0") + + tk.MustExec(`drop table if exists replace_test_2`) + tk.MustExec(`create table replace_test_2 (id int, c1 int) partition by range (id) ( + PARTITION p0 VALUES LESS THAN (10), + PARTITION p1 VALUES LESS THAN (50), + PARTITION p2 VALUES LESS THAN (100), + PARTITION p3 VALUES LESS THAN (300))`) + tk.MustExec(`replace replace_test_1 select id, c1 from replace_test union select id * 10, c1 * 10 from replace_test;`) + require.Equal(t, tk.Session().LastMessage(), "Records: 8 Duplicates: 0 Warnings: 0") + + errReplaceSelectSQL := `replace replace_test_1 select c1 from replace_test;` + tk.MustExec("begin") + err = tk.ExecToErr(errReplaceSelectSQL) + require.Error(t, err) + tk.MustExec("rollback") + + tk.MustExec(`drop table if exists replace_test_3`) + replaceUniqueIndexSQL := `create table replace_test_3 (c1 int, c2 int, UNIQUE INDEX (c2)) partition by range (c2) ( + PARTITION p0 VALUES LESS THAN (4), + PARTITION p1 VALUES LESS THAN (7), + PARTITION p2 VALUES LESS THAN (11))` + tk.MustExec(replaceUniqueIndexSQL) + replaceUniqueIndexSQL = `replace into replace_test_3 set c2=8;` + tk.MustExec(replaceUniqueIndexSQL) + replaceUniqueIndexSQL = `replace into replace_test_3 set c2=8;` + tk.MustExec(replaceUniqueIndexSQL) + require.Equal(t, int64(1), int64(tk.Session().AffectedRows())) + require.Empty(t, tk.Session().LastMessage()) + replaceUniqueIndexSQL = `replace into replace_test_3 set c1=8, c2=8;` + tk.MustExec(replaceUniqueIndexSQL) + require.Equal(t, int64(2), int64(tk.Session().AffectedRows())) + require.Empty(t, tk.Session().LastMessage()) + + replaceUniqueIndexSQL = `replace into replace_test_3 set c2=NULL;` + tk.MustExec(replaceUniqueIndexSQL) + replaceUniqueIndexSQL = `replace into replace_test_3 set c2=NULL;` + tk.MustExec(replaceUniqueIndexSQL) + require.Equal(t, int64(1), int64(tk.Session().AffectedRows())) + require.Empty(t, tk.Session().LastMessage()) + + replaceUniqueIndexSQL = `create table replace_test_4 (c1 int, c2 int, c3 int, UNIQUE INDEX (c1, c2)) partition by range (c1) ( + PARTITION p0 VALUES LESS THAN (4), + PARTITION p1 VALUES LESS THAN (7), + PARTITION p2 VALUES LESS THAN (11));` + tk.MustExec(`drop table if exists replace_test_4`) + tk.MustExec(replaceUniqueIndexSQL) + replaceUniqueIndexSQL = `replace into replace_test_4 set c2=NULL;` + tk.MustExec(replaceUniqueIndexSQL) + replaceUniqueIndexSQL = `replace into replace_test_4 set c2=NULL;` + tk.MustExec(replaceUniqueIndexSQL) + require.Equal(t, int64(1), int64(tk.Session().AffectedRows())) + + replacePrimaryKeySQL := `create table replace_test_5 (c1 int, c2 int, c3 int, PRIMARY KEY (c1, c2)) partition by range (c2) ( + PARTITION p0 VALUES LESS THAN (4), + PARTITION p1 VALUES LESS THAN (7), + PARTITION p2 VALUES LESS THAN (11));` + tk.MustExec(replacePrimaryKeySQL) + replacePrimaryKeySQL = `replace into replace_test_5 set c1=1, c2=2;` + tk.MustExec(replacePrimaryKeySQL) + replacePrimaryKeySQL = `replace into replace_test_5 set c1=1, c2=2;` + tk.MustExec(replacePrimaryKeySQL) + require.Equal(t, int64(1), int64(tk.Session().AffectedRows())) + + issue989SQL := `CREATE TABLE tIssue989 (a int, b int, KEY(a), UNIQUE KEY(b)) partition by range (b) ( + PARTITION p1 VALUES LESS THAN (100), + PARTITION p2 VALUES LESS THAN (200))` + tk.MustExec(issue989SQL) + issue989SQL = `insert into tIssue989 (a, b) values (1, 2);` + tk.MustExec(issue989SQL) + issue989SQL = `replace into tIssue989(a, b) values (111, 2);` + tk.MustExec(issue989SQL) + r := tk.MustQuery("select * from tIssue989;") + r.Check(testkit.Rows("111 2")) +} + +func TestHashPartitionedTableReplace(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@session.tidb_enable_table_partition = '1';") + tk.MustExec("drop table if exists replace_test;") + testSQL := `create table replace_test (id int PRIMARY KEY AUTO_INCREMENT, c1 int, c2 int, c3 int default 1) + partition by hash(id) partitions 4;` + tk.MustExec(testSQL) + + testSQL = `replace replace_test (c1) values (1),(2),(NULL);` + tk.MustExec(testSQL) + + errReplaceSQL := `replace replace_test (c1) values ();` + tk.MustExec("begin") + err := tk.ExecToErr(errReplaceSQL) + require.Error(t, err) + tk.MustExec("rollback") + + errReplaceSQL = `replace replace_test (c1, c2) values (1,2),(1);` + tk.MustExec("begin") + err = tk.ExecToErr(errReplaceSQL) + require.Error(t, err) + tk.MustExec("rollback") + + errReplaceSQL = `replace replace_test (xxx) values (3);` + tk.MustExec("begin") + err = tk.ExecToErr(errReplaceSQL) + require.Error(t, err) + tk.MustExec("rollback") + + errReplaceSQL = `replace replace_test_xxx (c1) values ();` + tk.MustExec("begin") + err = tk.ExecToErr(errReplaceSQL) + require.Error(t, err) + tk.MustExec("rollback") + + errReplaceSetSQL := `replace replace_test set c1 = 4, c1 = 5;` + tk.MustExec("begin") + err = tk.ExecToErr(errReplaceSetSQL) + require.Error(t, err) + tk.MustExec("rollback") + + errReplaceSetSQL = `replace replace_test set xxx = 6;` + tk.MustExec("begin") + err = tk.ExecToErr(errReplaceSetSQL) + require.Error(t, err) + tk.MustExec("rollback") + + tk.MustExec(`replace replace_test set c1 = 3;`) + tk.MustExec(`replace replace_test set c1 = 4;`) + tk.MustExec(`replace replace_test set c1 = 5;`) + tk.MustExec(`replace replace_test set c1 = 6;`) + tk.MustExec(`replace replace_test set c1 = 7;`) + + tk.MustExec(`drop table if exists replace_test_1`) + tk.MustExec(`create table replace_test_1 (id int, c1 int) partition by hash(id) partitions 5;`) + tk.MustExec(`replace replace_test_1 select id, c1 from replace_test;`) + + tk.MustExec(`drop table if exists replace_test_2`) + tk.MustExec(`create table replace_test_2 (id int, c1 int) partition by hash(id) partitions 6;`) + + tk.MustExec(`replace replace_test_1 select id, c1 from replace_test union select id * 10, c1 * 10 from replace_test;`) + + errReplaceSelectSQL := `replace replace_test_1 select c1 from replace_test;` + tk.MustExec("begin") + err = tk.ExecToErr(errReplaceSelectSQL) + require.Error(t, err) + tk.MustExec("rollback") + + tk.MustExec(`drop table if exists replace_test_3`) + replaceUniqueIndexSQL := `create table replace_test_3 (c1 int, c2 int, UNIQUE INDEX (c2)) partition by hash(c2) partitions 7;` + tk.MustExec(replaceUniqueIndexSQL) + + tk.MustExec(`replace into replace_test_3 set c2=8;`) + tk.MustExec(`replace into replace_test_3 set c2=8;`) + require.Equal(t, int64(1), int64(tk.Session().AffectedRows())) + tk.MustExec(`replace into replace_test_3 set c1=8, c2=8;`) + require.Equal(t, int64(2), int64(tk.Session().AffectedRows())) + + tk.MustExec(`replace into replace_test_3 set c2=NULL;`) + tk.MustExec(`replace into replace_test_3 set c2=NULL;`) + require.Equal(t, int64(1), int64(tk.Session().AffectedRows())) + + for i := 0; i < 100; i++ { + sql := fmt.Sprintf("replace into replace_test_3 set c2=%d;", i) + tk.MustExec(sql) + } + result := tk.MustQuery("select count(*) from replace_test_3") + result.Check(testkit.Rows("102")) + + replaceUniqueIndexSQL = `create table replace_test_4 (c1 int, c2 int, c3 int, UNIQUE INDEX (c1, c2)) partition by hash(c1) partitions 8;` + tk.MustExec(`drop table if exists replace_test_4`) + tk.MustExec(replaceUniqueIndexSQL) + replaceUniqueIndexSQL = `replace into replace_test_4 set c2=NULL;` + tk.MustExec(replaceUniqueIndexSQL) + replaceUniqueIndexSQL = `replace into replace_test_4 set c2=NULL;` + tk.MustExec(replaceUniqueIndexSQL) + require.Equal(t, int64(1), int64(tk.Session().AffectedRows())) + + replacePrimaryKeySQL := `create table replace_test_5 (c1 int, c2 int, c3 int, PRIMARY KEY (c1, c2)) partition by hash (c2) partitions 9;` + tk.MustExec(replacePrimaryKeySQL) + replacePrimaryKeySQL = `replace into replace_test_5 set c1=1, c2=2;` + tk.MustExec(replacePrimaryKeySQL) + replacePrimaryKeySQL = `replace into replace_test_5 set c1=1, c2=2;` + tk.MustExec(replacePrimaryKeySQL) + require.Equal(t, int64(1), int64(tk.Session().AffectedRows())) + + issue989SQL := `CREATE TABLE tIssue989 (a int, b int, KEY(a), UNIQUE KEY(b)) partition by hash (b) partitions 10;` + tk.MustExec(issue989SQL) + issue989SQL = `insert into tIssue989 (a, b) values (1, 2);` + tk.MustExec(issue989SQL) + issue989SQL = `replace into tIssue989(a, b) values (111, 2);` + tk.MustExec(issue989SQL) + r := tk.MustQuery("select * from tIssue989;") + r.Check(testkit.Rows("111 2")) +} + +func TestPartitionedTableUpdate(t *testing.T) { + failpoint.Enable("github.com/pingcap/tidb/planner/core/forceDynamicPrune", `return(true)`) + defer failpoint.Disable("github.com/pingcap/tidb/planner/core/forceDynamicPrune") + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec(`create table t (id int not null default 1, name varchar(255)) + PARTITION BY RANGE ( id ) ( + PARTITION p0 VALUES LESS THAN (6), + PARTITION p1 VALUES LESS THAN (11), + PARTITION p2 VALUES LESS THAN (16), + PARTITION p3 VALUES LESS THAN (21))`) + + tk.MustExec(`insert INTO t VALUES (1, "hello");`) + tk.CheckExecResult(1, 0) + tk.MustExec(`insert INTO t VALUES (7, "hello");`) + tk.CheckExecResult(1, 0) + + // update non partition column + tk.MustExec(`UPDATE t SET name = "abc" where id > 0;`) + tk.CheckExecResult(2, 0) + require.Equal(t, tk.Session().LastMessage(), "Rows matched: 2 Changed: 2 Warnings: 0") + r := tk.MustQuery(`SELECT * from t order by id limit 2;`) + r.Check(testkit.Rows("1 abc", "7 abc")) + + // update partition column + tk.MustExec(`update t set id = id + 1`) + tk.CheckExecResult(2, 0) + require.Equal(t, tk.Session().LastMessage(), "Rows matched: 2 Changed: 2 Warnings: 0") + r = tk.MustQuery(`SELECT * from t order by id limit 2;`) + r.Check(testkit.Rows("2 abc", "8 abc")) + + // update partition column, old and new record locates on different partitions + tk.MustExec(`update t set id = 20 where id = 8`) + tk.CheckExecResult(1, 0) + require.Equal(t, tk.Session().LastMessage(), "Rows matched: 1 Changed: 1 Warnings: 0") + r = tk.MustQuery(`SELECT * from t order by id limit 2;`) + r.Check(testkit.Rows("2 abc", "20 abc")) + + // table option is auto-increment + tk.MustExec("drop table if exists t;") + tk.MustExec(`create table t (id int not null auto_increment, name varchar(255), primary key(id)) + PARTITION BY RANGE ( id ) ( + PARTITION p0 VALUES LESS THAN (6), + PARTITION p1 VALUES LESS THAN (11), + PARTITION p2 VALUES LESS THAN (16), + PARTITION p3 VALUES LESS THAN (21))`) + + tk.MustExec("insert into t(name) values ('aa')") + tk.MustExec("update t set id = 8 where name = 'aa'") + require.Equal(t, tk.Session().LastMessage(), "Rows matched: 1 Changed: 1 Warnings: 0") + tk.MustExec("insert into t(name) values ('bb')") + r = tk.MustQuery("select * from t;") + r.Check(testkit.Rows("8 aa", "9 bb")) + + err := tk.ExecToErr("update t set id = null where name = 'aa'") + require.EqualError(t, err, "[table:1048]Column 'id' cannot be null") + + // Test that in a transaction, when a constraint failed in an update statement, the record is not inserted. + tk.MustExec("drop table if exists t;") + tk.MustExec(`create table t (id int, name int unique) + PARTITION BY RANGE ( name ) ( + PARTITION p0 VALUES LESS THAN (6), + PARTITION p1 VALUES LESS THAN (11), + PARTITION p2 VALUES LESS THAN (16), + PARTITION p3 VALUES LESS THAN (21))`) + tk.MustExec("insert t values (1, 1), (2, 2);") + err = tk.ExecToErr("update t set name = 1 where id = 2") + require.Error(t, err) + tk.MustQuery("select * from t").Check(testkit.Rows("1 1", "2 2")) + + // test update ignore for pimary key + tk.MustExec("drop table if exists t;") + tk.MustExec(`create table t(a bigint, primary key (a)) + PARTITION BY RANGE (a) ( + PARTITION p0 VALUES LESS THAN (6), + PARTITION p1 VALUES LESS THAN (11))`) + tk.MustExec("insert into t values (5)") + tk.MustExec("insert into t values (7)") + err = tk.ExecToErr("update ignore t set a = 5 where a = 7;") + require.NoError(t, err) + require.Equal(t, tk.Session().LastMessage(), "Rows matched: 1 Changed: 0 Warnings: 1") + r = tk.MustQuery("SHOW WARNINGS;") + r.Check(testkit.Rows("Warning 1062 Duplicate entry '5' for key 't.PRIMARY'")) + tk.MustQuery("select * from t order by a").Check(testkit.Rows("5", "7")) + + // test update ignore for truncate as warning + err = tk.ExecToErr("update ignore t set a = 1 where a = (select '2a')") + require.NoError(t, err) + r = tk.MustQuery("SHOW WARNINGS;") + r.Check(testkit.Rows("Warning 1292 Truncated incorrect DOUBLE value: '2a'", "Warning 1292 Truncated incorrect DOUBLE value: '2a'")) + + // test update ignore for unique key + tk.MustExec("drop table if exists t;") + tk.MustExec(`create table t(a bigint, unique key I_uniq (a)) + PARTITION BY RANGE (a) ( + PARTITION p0 VALUES LESS THAN (6), + PARTITION p1 VALUES LESS THAN (11))`) + tk.MustExec("insert into t values (5)") + tk.MustExec("insert into t values (7)") + err = tk.ExecToErr("update ignore t set a = 5 where a = 7;") + require.NoError(t, err) + require.Equal(t, tk.Session().LastMessage(), "Rows matched: 1 Changed: 0 Warnings: 1") + r = tk.MustQuery("SHOW WARNINGS;") + r.Check(testkit.Rows("Warning 1062 Duplicate entry '5' for key 't.I_uniq'")) + tk.MustQuery("select * from t order by a").Check(testkit.Rows("5", "7")) +} + +func TestPartitionedTableDelete(t *testing.T) { + failpoint.Enable("github.com/pingcap/tidb/planner/core/forceDynamicPrune", `return(true)`) + defer failpoint.Disable("github.com/pingcap/tidb/planner/core/forceDynamicPrune") + createTable := `CREATE TABLE test.t (id int not null default 1, name varchar(255), index(id)) + PARTITION BY RANGE ( id ) ( + PARTITION p0 VALUES LESS THAN (6), + PARTITION p1 VALUES LESS THAN (11), + PARTITION p2 VALUES LESS THAN (16), + PARTITION p3 VALUES LESS THAN (21))` + + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec(createTable) + for i := 1; i < 21; i++ { + tk.MustExec(fmt.Sprintf(`insert into t values (%d, "hello")`, i)) + } + + tk.MustExec(`delete from t where id = 2 limit 1;`) + tk.CheckExecResult(1, 0) + + // Test delete with false condition + tk.MustExec(`delete from t where 0;`) + tk.CheckExecResult(0, 0) + + tk.MustExec("insert into t values (2, 'abc')") + tk.MustExec(`delete from t where t.id = 2 limit 1`) + tk.CheckExecResult(1, 0) + + // Test delete ignore + tk.MustExec("insert into t values (2, 'abc')") + err := tk.ExecToErr("delete from t where id = (select '2a')") + require.Error(t, err) + err = tk.ExecToErr("delete ignore from t where id = (select '2a')") + require.NoError(t, err) + tk.CheckExecResult(1, 0) + r := tk.MustQuery("SHOW WARNINGS;") + r.Check(testkit.Rows("Warning 1292 Truncated incorrect DOUBLE value: '2a'", "Warning 1292 Truncated incorrect DOUBLE value: '2a'")) + + // Test delete without using index, involve multiple partitions. + tk.MustExec("delete from t ignore index(id) where id >= 13 and id <= 17") + tk.CheckExecResult(5, 0) + + tk.MustExec("admin check table t") + tk.MustExec(`delete from t;`) + tk.CheckExecResult(14, 0) + + // Fix that partitioned table should not use PointGetPlan. + tk.MustExec(`create table t1 (c1 bigint, c2 bigint, c3 bigint, primary key(c1)) partition by range (c1) (partition p0 values less than (3440))`) + tk.MustExec("insert into t1 values (379, 379, 379)") + tk.MustExec("delete from t1 where c1 = 379") + tk.CheckExecResult(1, 0) + tk.MustExec(`drop table t1;`) +} + +func TestPartitionOnMissing(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("create schema OnMissing") + tk.MustExec("use OnMissing") + tk.MustExec(`set global tidb_partition_prune_mode='dynamic'`) + tk.MustExec(`set session tidb_partition_prune_mode='dynamic'`) + + tk.MustExec(`CREATE TABLE tt1 ( + id INT NOT NULL, + listid INT, + name varchar(10), + primary key (listid) clustered + ) + PARTITION BY LIST (listid) ( + PARTITION p1 VALUES IN (1), + PARTITION p2 VALUES IN (2), + PARTITION p3 VALUES IN (3), + PARTITION p4 VALUES IN (4) + )`) + + tk.MustExec(`CREATE TABLE tt2 ( + id INT NOT NULL, + listid INT + )`) + + tk.MustExec(`create index idx_listid on tt1(id,listid)`) + tk.MustExec(`create index idx_listid on tt2(listid)`) + + tk.MustExec(`insert into tt1 values(1,1,1)`) + tk.MustExec(`insert into tt1 values(2,2,2)`) + tk.MustExec(`insert into tt1 values(3,3,3)`) + tk.MustExec(`insert into tt1 values(4,4,4)`) + tk.MustExec(`insert into tt2 values(1,1)`) + tk.MustExec(`insert into tt2 values(2,2)`) + tk.MustExec(`insert into tt2 values(3,3)`) + tk.MustExec(`insert into tt2 values(4,4)`) + tk.MustExec(`insert into tt2 values(5,5)`) + + tk.MustExec(`analyze table tt1`) + tk.MustExec(`analyze table tt2`) + + tk.MustQuery(`select /*+ inl_join(tt1)*/ count(*) from tt2 + left join tt1 on tt1.listid=tt2.listid and tt1.id=tt2.id`).Check(testkit.Rows("5")) + tk.MustQuery(`select /*+ inl_join(tt1)*/ count(*) from tt2 + left join tt1 on tt1.listid=tt2.listid`).Check(testkit.Rows("5")) + tk.MustQuery(`explain format = 'brief' select /*+ inl_join(tt1)*/ count(*) from tt2 + left join tt1 on tt1.listid=tt2.listid`).Check(testkit.Rows(""+ + "StreamAgg 1.00 root funcs:count(1)->Column#7", + "└─IndexJoin 5.00 root left outer join, inner:TableReader, outer key:onmissing.tt2.listid, inner key:onmissing.tt1.listid, equal cond:eq(onmissing.tt2.listid, onmissing.tt1.listid)", + " ├─IndexReader(Build) 5.00 root index:IndexFullScan", + " │ └─IndexFullScan 5.00 cop[tikv] table:tt2, index:idx_listid(listid) keep order:false", + " └─TableReader(Probe) 4.00 root partition:all data:TableRangeScan", + " └─TableRangeScan 4.00 cop[tikv] table:tt1 range: decided by [onmissing.tt2.listid], keep order:false")) +} From bdc3332171f4bfe85ceb7dabc133a29c30104813 Mon Sep 17 00:00:00 2001 From: AilinKid <314806019@qq.com> Date: Mon, 5 Jun 2023 19:25:41 +0800 Subject: [PATCH 2/3] make fmt Signed-off-by: AilinKid <314806019@qq.com> --- executor/partition_table_test.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/executor/partition_table_test.go b/executor/partition_table_test.go index e398733be62ca..16d5e30ee9eb0 100644 --- a/executor/partition_table_test.go +++ b/executor/partition_table_test.go @@ -3923,7 +3923,8 @@ func TestPartitionOnMissing(t *testing.T) { tk.MustExec(`CREATE TABLE tt1 ( id INT NOT NULL, listid INT, - name varchar(10) + name varchar(10), + primary key (listid) clustered ) PARTITION BY LIST (listid) ( PARTITION p1 VALUES IN (1), @@ -3955,4 +3956,14 @@ func TestPartitionOnMissing(t *testing.T) { tk.MustQuery(`select /*+ inl_join(tt1)*/ count(*) from tt2 left join tt1 on tt1.listid=tt2.listid and tt1.id=tt2.id`).Check(testkit.Rows("5")) + tk.MustQuery(`select /*+ inl_join(tt1)*/ count(*) from tt2 + left join tt1 on tt1.listid=tt2.listid`).Check(testkit.Rows("5")) + tk.MustQuery(`explain format = 'brief' select /*+ inl_join(tt1)*/ count(*) from tt2 + left join tt1 on tt1.listid=tt2.listid`).Check(testkit.Rows(""+ + "StreamAgg 1.00 root funcs:count(1)->Column#7", + "└─IndexJoin 5.00 root left outer join, inner:TableReader, outer key:onmissing.tt2.listid, inner key:onmissing.tt1.listid, equal cond:eq(onmissing.tt2.listid, onmissing.tt1.listid)", + " ├─IndexReader(Build) 5.00 root index:IndexFullScan", + " │ └─IndexFullScan 5.00 cop[tikv] table:tt2, index:idx_listid(listid) keep order:false", + " └─TableReader(Probe) 4.00 root partition:all data:TableRangeScan", + " └─TableRangeScan 4.00 cop[tikv] table:tt1 range: decided by [onmissing.tt2.listid], keep order:false")) } From 130d636603d9cb8eed1f72e7564781ff39da0386 Mon Sep 17 00:00:00 2001 From: Arenatlx Date: Mon, 5 Jun 2023 19:26:40 +0800 Subject: [PATCH 3/3] Delete partition_test.go --- executor/test/partitiontest/partition_test.go | 505 ------------------ 1 file changed, 505 deletions(-) delete mode 100644 executor/test/partitiontest/partition_test.go diff --git a/executor/test/partitiontest/partition_test.go b/executor/test/partitiontest/partition_test.go deleted file mode 100644 index d9614cd808ec3..0000000000000 --- a/executor/test/partitiontest/partition_test.go +++ /dev/null @@ -1,505 +0,0 @@ -// Copyright 2023 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 partitiontest - -import ( - "fmt" - "testing" - - "github.com/pingcap/failpoint" - "github.com/pingcap/tidb/testkit" - "github.com/stretchr/testify/require" -) - -func TestPartitionedTableReplace(t *testing.T) { - failpoint.Enable("github.com/pingcap/tidb/planner/core/forceDynamicPrune", `return(true)`) - defer failpoint.Disable("github.com/pingcap/tidb/planner/core/forceDynamicPrune") - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - testSQL := `drop table if exists replace_test; - create table replace_test (id int PRIMARY KEY AUTO_INCREMENT, c1 int, c2 int, c3 int default 1) - partition by range (id) ( - PARTITION p0 VALUES LESS THAN (3), - PARTITION p1 VALUES LESS THAN (5), - PARTITION p2 VALUES LESS THAN (7), - PARTITION p3 VALUES LESS THAN (9));` - tk.MustExec(testSQL) - testSQL = `replace replace_test (c1) values (1),(2),(NULL);` - tk.MustExec(testSQL) - require.Equal(t, tk.Session().LastMessage(), "Records: 3 Duplicates: 0 Warnings: 0") - - errReplaceSQL := `replace replace_test (c1) values ();` - tk.MustExec("begin") - err := tk.ExecToErr(errReplaceSQL) - require.Error(t, err) - tk.MustExec("rollback") - - errReplaceSQL = `replace replace_test (c1, c2) values (1,2),(1);` - tk.MustExec("begin") - err = tk.ExecToErr(errReplaceSQL) - require.Error(t, err) - tk.MustExec("rollback") - - errReplaceSQL = `replace replace_test (xxx) values (3);` - tk.MustExec("begin") - err = tk.ExecToErr(errReplaceSQL) - require.Error(t, err) - tk.MustExec("rollback") - - errReplaceSQL = `replace replace_test_xxx (c1) values ();` - tk.MustExec("begin") - err = tk.ExecToErr(errReplaceSQL) - require.Error(t, err) - tk.MustExec("rollback") - - replaceSetSQL := `replace replace_test set c1 = 3;` - tk.MustExec(replaceSetSQL) - require.Empty(t, tk.Session().LastMessage()) - - errReplaceSetSQL := `replace replace_test set c1 = 4, c1 = 5;` - tk.MustExec("begin") - err = tk.ExecToErr(errReplaceSetSQL) - require.Error(t, err) - tk.MustExec("rollback") - - errReplaceSetSQL = `replace replace_test set xxx = 6;` - tk.MustExec("begin") - err = tk.ExecToErr(errReplaceSetSQL) - require.Error(t, err) - tk.MustExec("rollback") - - tk.MustExec(`drop table if exists replace_test_1`) - tk.MustExec(`create table replace_test_1 (id int, c1 int) partition by range (id) ( - PARTITION p0 VALUES LESS THAN (4), - PARTITION p1 VALUES LESS THAN (6), - PARTITION p2 VALUES LESS THAN (8), - PARTITION p3 VALUES LESS THAN (10), - PARTITION p4 VALUES LESS THAN (100))`) - tk.MustExec(`replace replace_test_1 select id, c1 from replace_test;`) - require.Equal(t, tk.Session().LastMessage(), "Records: 4 Duplicates: 0 Warnings: 0") - - tk.MustExec(`drop table if exists replace_test_2`) - tk.MustExec(`create table replace_test_2 (id int, c1 int) partition by range (id) ( - PARTITION p0 VALUES LESS THAN (10), - PARTITION p1 VALUES LESS THAN (50), - PARTITION p2 VALUES LESS THAN (100), - PARTITION p3 VALUES LESS THAN (300))`) - tk.MustExec(`replace replace_test_1 select id, c1 from replace_test union select id * 10, c1 * 10 from replace_test;`) - require.Equal(t, tk.Session().LastMessage(), "Records: 8 Duplicates: 0 Warnings: 0") - - errReplaceSelectSQL := `replace replace_test_1 select c1 from replace_test;` - tk.MustExec("begin") - err = tk.ExecToErr(errReplaceSelectSQL) - require.Error(t, err) - tk.MustExec("rollback") - - tk.MustExec(`drop table if exists replace_test_3`) - replaceUniqueIndexSQL := `create table replace_test_3 (c1 int, c2 int, UNIQUE INDEX (c2)) partition by range (c2) ( - PARTITION p0 VALUES LESS THAN (4), - PARTITION p1 VALUES LESS THAN (7), - PARTITION p2 VALUES LESS THAN (11))` - tk.MustExec(replaceUniqueIndexSQL) - replaceUniqueIndexSQL = `replace into replace_test_3 set c2=8;` - tk.MustExec(replaceUniqueIndexSQL) - replaceUniqueIndexSQL = `replace into replace_test_3 set c2=8;` - tk.MustExec(replaceUniqueIndexSQL) - require.Equal(t, int64(1), int64(tk.Session().AffectedRows())) - require.Empty(t, tk.Session().LastMessage()) - replaceUniqueIndexSQL = `replace into replace_test_3 set c1=8, c2=8;` - tk.MustExec(replaceUniqueIndexSQL) - require.Equal(t, int64(2), int64(tk.Session().AffectedRows())) - require.Empty(t, tk.Session().LastMessage()) - - replaceUniqueIndexSQL = `replace into replace_test_3 set c2=NULL;` - tk.MustExec(replaceUniqueIndexSQL) - replaceUniqueIndexSQL = `replace into replace_test_3 set c2=NULL;` - tk.MustExec(replaceUniqueIndexSQL) - require.Equal(t, int64(1), int64(tk.Session().AffectedRows())) - require.Empty(t, tk.Session().LastMessage()) - - replaceUniqueIndexSQL = `create table replace_test_4 (c1 int, c2 int, c3 int, UNIQUE INDEX (c1, c2)) partition by range (c1) ( - PARTITION p0 VALUES LESS THAN (4), - PARTITION p1 VALUES LESS THAN (7), - PARTITION p2 VALUES LESS THAN (11));` - tk.MustExec(`drop table if exists replace_test_4`) - tk.MustExec(replaceUniqueIndexSQL) - replaceUniqueIndexSQL = `replace into replace_test_4 set c2=NULL;` - tk.MustExec(replaceUniqueIndexSQL) - replaceUniqueIndexSQL = `replace into replace_test_4 set c2=NULL;` - tk.MustExec(replaceUniqueIndexSQL) - require.Equal(t, int64(1), int64(tk.Session().AffectedRows())) - - replacePrimaryKeySQL := `create table replace_test_5 (c1 int, c2 int, c3 int, PRIMARY KEY (c1, c2)) partition by range (c2) ( - PARTITION p0 VALUES LESS THAN (4), - PARTITION p1 VALUES LESS THAN (7), - PARTITION p2 VALUES LESS THAN (11));` - tk.MustExec(replacePrimaryKeySQL) - replacePrimaryKeySQL = `replace into replace_test_5 set c1=1, c2=2;` - tk.MustExec(replacePrimaryKeySQL) - replacePrimaryKeySQL = `replace into replace_test_5 set c1=1, c2=2;` - tk.MustExec(replacePrimaryKeySQL) - require.Equal(t, int64(1), int64(tk.Session().AffectedRows())) - - issue989SQL := `CREATE TABLE tIssue989 (a int, b int, KEY(a), UNIQUE KEY(b)) partition by range (b) ( - PARTITION p1 VALUES LESS THAN (100), - PARTITION p2 VALUES LESS THAN (200))` - tk.MustExec(issue989SQL) - issue989SQL = `insert into tIssue989 (a, b) values (1, 2);` - tk.MustExec(issue989SQL) - issue989SQL = `replace into tIssue989(a, b) values (111, 2);` - tk.MustExec(issue989SQL) - r := tk.MustQuery("select * from tIssue989;") - r.Check(testkit.Rows("111 2")) -} - -func TestHashPartitionedTableReplace(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustExec("set @@session.tidb_enable_table_partition = '1';") - tk.MustExec("drop table if exists replace_test;") - testSQL := `create table replace_test (id int PRIMARY KEY AUTO_INCREMENT, c1 int, c2 int, c3 int default 1) - partition by hash(id) partitions 4;` - tk.MustExec(testSQL) - - testSQL = `replace replace_test (c1) values (1),(2),(NULL);` - tk.MustExec(testSQL) - - errReplaceSQL := `replace replace_test (c1) values ();` - tk.MustExec("begin") - err := tk.ExecToErr(errReplaceSQL) - require.Error(t, err) - tk.MustExec("rollback") - - errReplaceSQL = `replace replace_test (c1, c2) values (1,2),(1);` - tk.MustExec("begin") - err = tk.ExecToErr(errReplaceSQL) - require.Error(t, err) - tk.MustExec("rollback") - - errReplaceSQL = `replace replace_test (xxx) values (3);` - tk.MustExec("begin") - err = tk.ExecToErr(errReplaceSQL) - require.Error(t, err) - tk.MustExec("rollback") - - errReplaceSQL = `replace replace_test_xxx (c1) values ();` - tk.MustExec("begin") - err = tk.ExecToErr(errReplaceSQL) - require.Error(t, err) - tk.MustExec("rollback") - - errReplaceSetSQL := `replace replace_test set c1 = 4, c1 = 5;` - tk.MustExec("begin") - err = tk.ExecToErr(errReplaceSetSQL) - require.Error(t, err) - tk.MustExec("rollback") - - errReplaceSetSQL = `replace replace_test set xxx = 6;` - tk.MustExec("begin") - err = tk.ExecToErr(errReplaceSetSQL) - require.Error(t, err) - tk.MustExec("rollback") - - tk.MustExec(`replace replace_test set c1 = 3;`) - tk.MustExec(`replace replace_test set c1 = 4;`) - tk.MustExec(`replace replace_test set c1 = 5;`) - tk.MustExec(`replace replace_test set c1 = 6;`) - tk.MustExec(`replace replace_test set c1 = 7;`) - - tk.MustExec(`drop table if exists replace_test_1`) - tk.MustExec(`create table replace_test_1 (id int, c1 int) partition by hash(id) partitions 5;`) - tk.MustExec(`replace replace_test_1 select id, c1 from replace_test;`) - - tk.MustExec(`drop table if exists replace_test_2`) - tk.MustExec(`create table replace_test_2 (id int, c1 int) partition by hash(id) partitions 6;`) - - tk.MustExec(`replace replace_test_1 select id, c1 from replace_test union select id * 10, c1 * 10 from replace_test;`) - - errReplaceSelectSQL := `replace replace_test_1 select c1 from replace_test;` - tk.MustExec("begin") - err = tk.ExecToErr(errReplaceSelectSQL) - require.Error(t, err) - tk.MustExec("rollback") - - tk.MustExec(`drop table if exists replace_test_3`) - replaceUniqueIndexSQL := `create table replace_test_3 (c1 int, c2 int, UNIQUE INDEX (c2)) partition by hash(c2) partitions 7;` - tk.MustExec(replaceUniqueIndexSQL) - - tk.MustExec(`replace into replace_test_3 set c2=8;`) - tk.MustExec(`replace into replace_test_3 set c2=8;`) - require.Equal(t, int64(1), int64(tk.Session().AffectedRows())) - tk.MustExec(`replace into replace_test_3 set c1=8, c2=8;`) - require.Equal(t, int64(2), int64(tk.Session().AffectedRows())) - - tk.MustExec(`replace into replace_test_3 set c2=NULL;`) - tk.MustExec(`replace into replace_test_3 set c2=NULL;`) - require.Equal(t, int64(1), int64(tk.Session().AffectedRows())) - - for i := 0; i < 100; i++ { - sql := fmt.Sprintf("replace into replace_test_3 set c2=%d;", i) - tk.MustExec(sql) - } - result := tk.MustQuery("select count(*) from replace_test_3") - result.Check(testkit.Rows("102")) - - replaceUniqueIndexSQL = `create table replace_test_4 (c1 int, c2 int, c3 int, UNIQUE INDEX (c1, c2)) partition by hash(c1) partitions 8;` - tk.MustExec(`drop table if exists replace_test_4`) - tk.MustExec(replaceUniqueIndexSQL) - replaceUniqueIndexSQL = `replace into replace_test_4 set c2=NULL;` - tk.MustExec(replaceUniqueIndexSQL) - replaceUniqueIndexSQL = `replace into replace_test_4 set c2=NULL;` - tk.MustExec(replaceUniqueIndexSQL) - require.Equal(t, int64(1), int64(tk.Session().AffectedRows())) - - replacePrimaryKeySQL := `create table replace_test_5 (c1 int, c2 int, c3 int, PRIMARY KEY (c1, c2)) partition by hash (c2) partitions 9;` - tk.MustExec(replacePrimaryKeySQL) - replacePrimaryKeySQL = `replace into replace_test_5 set c1=1, c2=2;` - tk.MustExec(replacePrimaryKeySQL) - replacePrimaryKeySQL = `replace into replace_test_5 set c1=1, c2=2;` - tk.MustExec(replacePrimaryKeySQL) - require.Equal(t, int64(1), int64(tk.Session().AffectedRows())) - - issue989SQL := `CREATE TABLE tIssue989 (a int, b int, KEY(a), UNIQUE KEY(b)) partition by hash (b) partitions 10;` - tk.MustExec(issue989SQL) - issue989SQL = `insert into tIssue989 (a, b) values (1, 2);` - tk.MustExec(issue989SQL) - issue989SQL = `replace into tIssue989(a, b) values (111, 2);` - tk.MustExec(issue989SQL) - r := tk.MustQuery("select * from tIssue989;") - r.Check(testkit.Rows("111 2")) -} - -func TestPartitionedTableUpdate(t *testing.T) { - failpoint.Enable("github.com/pingcap/tidb/planner/core/forceDynamicPrune", `return(true)`) - defer failpoint.Disable("github.com/pingcap/tidb/planner/core/forceDynamicPrune") - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec(`create table t (id int not null default 1, name varchar(255)) - PARTITION BY RANGE ( id ) ( - PARTITION p0 VALUES LESS THAN (6), - PARTITION p1 VALUES LESS THAN (11), - PARTITION p2 VALUES LESS THAN (16), - PARTITION p3 VALUES LESS THAN (21))`) - - tk.MustExec(`insert INTO t VALUES (1, "hello");`) - tk.CheckExecResult(1, 0) - tk.MustExec(`insert INTO t VALUES (7, "hello");`) - tk.CheckExecResult(1, 0) - - // update non partition column - tk.MustExec(`UPDATE t SET name = "abc" where id > 0;`) - tk.CheckExecResult(2, 0) - require.Equal(t, tk.Session().LastMessage(), "Rows matched: 2 Changed: 2 Warnings: 0") - r := tk.MustQuery(`SELECT * from t order by id limit 2;`) - r.Check(testkit.Rows("1 abc", "7 abc")) - - // update partition column - tk.MustExec(`update t set id = id + 1`) - tk.CheckExecResult(2, 0) - require.Equal(t, tk.Session().LastMessage(), "Rows matched: 2 Changed: 2 Warnings: 0") - r = tk.MustQuery(`SELECT * from t order by id limit 2;`) - r.Check(testkit.Rows("2 abc", "8 abc")) - - // update partition column, old and new record locates on different partitions - tk.MustExec(`update t set id = 20 where id = 8`) - tk.CheckExecResult(1, 0) - require.Equal(t, tk.Session().LastMessage(), "Rows matched: 1 Changed: 1 Warnings: 0") - r = tk.MustQuery(`SELECT * from t order by id limit 2;`) - r.Check(testkit.Rows("2 abc", "20 abc")) - - // table option is auto-increment - tk.MustExec("drop table if exists t;") - tk.MustExec(`create table t (id int not null auto_increment, name varchar(255), primary key(id)) - PARTITION BY RANGE ( id ) ( - PARTITION p0 VALUES LESS THAN (6), - PARTITION p1 VALUES LESS THAN (11), - PARTITION p2 VALUES LESS THAN (16), - PARTITION p3 VALUES LESS THAN (21))`) - - tk.MustExec("insert into t(name) values ('aa')") - tk.MustExec("update t set id = 8 where name = 'aa'") - require.Equal(t, tk.Session().LastMessage(), "Rows matched: 1 Changed: 1 Warnings: 0") - tk.MustExec("insert into t(name) values ('bb')") - r = tk.MustQuery("select * from t;") - r.Check(testkit.Rows("8 aa", "9 bb")) - - err := tk.ExecToErr("update t set id = null where name = 'aa'") - require.EqualError(t, err, "[table:1048]Column 'id' cannot be null") - - // Test that in a transaction, when a constraint failed in an update statement, the record is not inserted. - tk.MustExec("drop table if exists t;") - tk.MustExec(`create table t (id int, name int unique) - PARTITION BY RANGE ( name ) ( - PARTITION p0 VALUES LESS THAN (6), - PARTITION p1 VALUES LESS THAN (11), - PARTITION p2 VALUES LESS THAN (16), - PARTITION p3 VALUES LESS THAN (21))`) - tk.MustExec("insert t values (1, 1), (2, 2);") - err = tk.ExecToErr("update t set name = 1 where id = 2") - require.Error(t, err) - tk.MustQuery("select * from t").Check(testkit.Rows("1 1", "2 2")) - - // test update ignore for pimary key - tk.MustExec("drop table if exists t;") - tk.MustExec(`create table t(a bigint, primary key (a)) - PARTITION BY RANGE (a) ( - PARTITION p0 VALUES LESS THAN (6), - PARTITION p1 VALUES LESS THAN (11))`) - tk.MustExec("insert into t values (5)") - tk.MustExec("insert into t values (7)") - err = tk.ExecToErr("update ignore t set a = 5 where a = 7;") - require.NoError(t, err) - require.Equal(t, tk.Session().LastMessage(), "Rows matched: 1 Changed: 0 Warnings: 1") - r = tk.MustQuery("SHOW WARNINGS;") - r.Check(testkit.Rows("Warning 1062 Duplicate entry '5' for key 't.PRIMARY'")) - tk.MustQuery("select * from t order by a").Check(testkit.Rows("5", "7")) - - // test update ignore for truncate as warning - err = tk.ExecToErr("update ignore t set a = 1 where a = (select '2a')") - require.NoError(t, err) - r = tk.MustQuery("SHOW WARNINGS;") - r.Check(testkit.Rows("Warning 1292 Truncated incorrect DOUBLE value: '2a'", "Warning 1292 Truncated incorrect DOUBLE value: '2a'")) - - // test update ignore for unique key - tk.MustExec("drop table if exists t;") - tk.MustExec(`create table t(a bigint, unique key I_uniq (a)) - PARTITION BY RANGE (a) ( - PARTITION p0 VALUES LESS THAN (6), - PARTITION p1 VALUES LESS THAN (11))`) - tk.MustExec("insert into t values (5)") - tk.MustExec("insert into t values (7)") - err = tk.ExecToErr("update ignore t set a = 5 where a = 7;") - require.NoError(t, err) - require.Equal(t, tk.Session().LastMessage(), "Rows matched: 1 Changed: 0 Warnings: 1") - r = tk.MustQuery("SHOW WARNINGS;") - r.Check(testkit.Rows("Warning 1062 Duplicate entry '5' for key 't.I_uniq'")) - tk.MustQuery("select * from t order by a").Check(testkit.Rows("5", "7")) -} - -func TestPartitionedTableDelete(t *testing.T) { - failpoint.Enable("github.com/pingcap/tidb/planner/core/forceDynamicPrune", `return(true)`) - defer failpoint.Disable("github.com/pingcap/tidb/planner/core/forceDynamicPrune") - createTable := `CREATE TABLE test.t (id int not null default 1, name varchar(255), index(id)) - PARTITION BY RANGE ( id ) ( - PARTITION p0 VALUES LESS THAN (6), - PARTITION p1 VALUES LESS THAN (11), - PARTITION p2 VALUES LESS THAN (16), - PARTITION p3 VALUES LESS THAN (21))` - - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec(createTable) - for i := 1; i < 21; i++ { - tk.MustExec(fmt.Sprintf(`insert into t values (%d, "hello")`, i)) - } - - tk.MustExec(`delete from t where id = 2 limit 1;`) - tk.CheckExecResult(1, 0) - - // Test delete with false condition - tk.MustExec(`delete from t where 0;`) - tk.CheckExecResult(0, 0) - - tk.MustExec("insert into t values (2, 'abc')") - tk.MustExec(`delete from t where t.id = 2 limit 1`) - tk.CheckExecResult(1, 0) - - // Test delete ignore - tk.MustExec("insert into t values (2, 'abc')") - err := tk.ExecToErr("delete from t where id = (select '2a')") - require.Error(t, err) - err = tk.ExecToErr("delete ignore from t where id = (select '2a')") - require.NoError(t, err) - tk.CheckExecResult(1, 0) - r := tk.MustQuery("SHOW WARNINGS;") - r.Check(testkit.Rows("Warning 1292 Truncated incorrect DOUBLE value: '2a'", "Warning 1292 Truncated incorrect DOUBLE value: '2a'")) - - // Test delete without using index, involve multiple partitions. - tk.MustExec("delete from t ignore index(id) where id >= 13 and id <= 17") - tk.CheckExecResult(5, 0) - - tk.MustExec("admin check table t") - tk.MustExec(`delete from t;`) - tk.CheckExecResult(14, 0) - - // Fix that partitioned table should not use PointGetPlan. - tk.MustExec(`create table t1 (c1 bigint, c2 bigint, c3 bigint, primary key(c1)) partition by range (c1) (partition p0 values less than (3440))`) - tk.MustExec("insert into t1 values (379, 379, 379)") - tk.MustExec("delete from t1 where c1 = 379") - tk.CheckExecResult(1, 0) - tk.MustExec(`drop table t1;`) -} - -func TestPartitionOnMissing(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - tk.MustExec("create schema OnMissing") - tk.MustExec("use OnMissing") - tk.MustExec(`set global tidb_partition_prune_mode='dynamic'`) - tk.MustExec(`set session tidb_partition_prune_mode='dynamic'`) - - tk.MustExec(`CREATE TABLE tt1 ( - id INT NOT NULL, - listid INT, - name varchar(10), - primary key (listid) clustered - ) - PARTITION BY LIST (listid) ( - PARTITION p1 VALUES IN (1), - PARTITION p2 VALUES IN (2), - PARTITION p3 VALUES IN (3), - PARTITION p4 VALUES IN (4) - )`) - - tk.MustExec(`CREATE TABLE tt2 ( - id INT NOT NULL, - listid INT - )`) - - tk.MustExec(`create index idx_listid on tt1(id,listid)`) - tk.MustExec(`create index idx_listid on tt2(listid)`) - - tk.MustExec(`insert into tt1 values(1,1,1)`) - tk.MustExec(`insert into tt1 values(2,2,2)`) - tk.MustExec(`insert into tt1 values(3,3,3)`) - tk.MustExec(`insert into tt1 values(4,4,4)`) - tk.MustExec(`insert into tt2 values(1,1)`) - tk.MustExec(`insert into tt2 values(2,2)`) - tk.MustExec(`insert into tt2 values(3,3)`) - tk.MustExec(`insert into tt2 values(4,4)`) - tk.MustExec(`insert into tt2 values(5,5)`) - - tk.MustExec(`analyze table tt1`) - tk.MustExec(`analyze table tt2`) - - tk.MustQuery(`select /*+ inl_join(tt1)*/ count(*) from tt2 - left join tt1 on tt1.listid=tt2.listid and tt1.id=tt2.id`).Check(testkit.Rows("5")) - tk.MustQuery(`select /*+ inl_join(tt1)*/ count(*) from tt2 - left join tt1 on tt1.listid=tt2.listid`).Check(testkit.Rows("5")) - tk.MustQuery(`explain format = 'brief' select /*+ inl_join(tt1)*/ count(*) from tt2 - left join tt1 on tt1.listid=tt2.listid`).Check(testkit.Rows(""+ - "StreamAgg 1.00 root funcs:count(1)->Column#7", - "└─IndexJoin 5.00 root left outer join, inner:TableReader, outer key:onmissing.tt2.listid, inner key:onmissing.tt1.listid, equal cond:eq(onmissing.tt2.listid, onmissing.tt1.listid)", - " ├─IndexReader(Build) 5.00 root index:IndexFullScan", - " │ └─IndexFullScan 5.00 cop[tikv] table:tt2, index:idx_listid(listid) keep order:false", - " └─TableReader(Probe) 4.00 root partition:all data:TableRangeScan", - " └─TableRangeScan 4.00 cop[tikv] table:tt1 range: decided by [onmissing.tt2.listid], keep order:false")) -}