From 0c7ff7fcb6533f48156345aac1f1be186a2a4f12 Mon Sep 17 00:00:00 2001 From: tiancaiamao Date: Tue, 20 Jul 2021 15:34:06 +0800 Subject: [PATCH 1/2] planner/core: fix a panic when select for update on join partition table with normal table --- planner/core/integration_test.go | 10 ++++++++++ planner/core/planbuilder.go | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/planner/core/integration_test.go b/planner/core/integration_test.go index 642233ea04f16..beaa960ee999b 100644 --- a/planner/core/integration_test.go +++ b/planner/core/integration_test.go @@ -3970,3 +3970,13 @@ func (s *testIntegrationSerialSuite) TestSelectIgnoreTemporaryTableInView(c *C) tk.MustQuery("select * from v5").Check(testkit.Rows("1 2", "3 4")) } + +func (s *testIntegrationSerialSuite) TestIssue26250(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("create table tp (id int primary key) partition by range (id) (partition p0 values less than (100));") + tk.MustExec("create table tn (id int primary key);") + tk.MustExec("insert into tp values(1),(2);") + tk.MustExec("insert into tn values(1),(2);") + tk.MustQuery("select * from tp,tn where tp.id=tn.id and tn.id=1 for update;").Check(testkit.Rows("1 1")) +} diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 3e39d12bd58fb..a58e20f2ada73 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -1234,6 +1234,10 @@ func (b *PlanBuilder) buildSelectLock(src LogicalPlan, lock *ast.SelectLockInfo) func addExtraPIDColumnToDataSource(p LogicalPlan, info *extraPIDInfo) error { switch raw := p.(type) { case *DataSource: + // Fix issue 26250, do not add extra pid column to normal table. + if raw.tableInfo.GetPartitionInfo() == nil { + return nil + } raw.addExtraPIDColumn(info) return nil default: From 370d4ce9b9144c5a13f3c65c4930508047f37d2f Mon Sep 17 00:00:00 2001 From: tiancaiamao Date: Tue, 20 Jul 2021 17:11:31 +0800 Subject: [PATCH 2/2] executor: fix table id to partition id mapping in select lock executor --- executor/executor.go | 5 +++-- executor/partition_table_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/executor/executor.go b/executor/executor.go index 3b01cc6199b47..76b334c5e860e 100644 --- a/executor/executor.go +++ b/executor/executor.go @@ -929,8 +929,9 @@ func (e *SelectLockExec) Next(ctx context.Context, req *chunk.Chunk) error { if len(e.partitionedTable) > 0 { // Replace the table ID with partition ID. // The partition ID is returned as an extra column from the table reader. - offset := e.tblID2PIDColumnIndex[id] - physicalID = row.GetInt64(offset) + if offset, ok := e.tblID2PIDColumnIndex[id]; ok { + physicalID = row.GetInt64(offset) + } } for _, col := range cols { diff --git a/executor/partition_table_test.go b/executor/partition_table_test.go index 116d796c74e80..92d999108ae4a 100644 --- a/executor/partition_table_test.go +++ b/executor/partition_table_test.go @@ -3056,3 +3056,35 @@ func (s *partitionTableSuite) TestIssue25528(c *C) { tk.MustExec("INSERT INTO issue25528 (`c1`, `c2`, `c3`, `c4`) VALUES (1, 1, 1, 1) , (3, 3, 3, 3) , (2, 2, 2, 2) , (4, 4, 4, 4);") tk.MustQuery("select * from issue25528 where c1 in (3, 4) order by c2 for update;").Check(testkit.Rows("3 3 3 3", "4 4 4 4")) } + +func (s *partitionTableSuite) TestIssue26251(c *C) { + tk1 := testkit.NewTestKit(c, s.store) + tk1.MustExec("use test") + tk1.MustExec("create table tp (id int primary key) partition by range (id) (partition p0 values less than (100));") + tk1.MustExec("create table tn (id int primary key);") + tk1.MustExec("insert into tp values(1),(2);") + tk1.MustExec("insert into tn values(1),(2);") + + tk2 := testkit.NewTestKit(c, s.store) + tk2.MustExec("use test") + + tk1.MustExec("begin pessimistic") + tk1.MustQuery("select * from tp,tn where tp.id=tn.id and tn.id<=1 for update;").Check(testkit.Rows("1 1")) + + ch := make(chan struct{}, 1) + tk2.MustExec("begin pessimistic") + go func() { + // This query should block. + tk2.MustQuery("select * from tn where id=1 for update;").Check(testkit.Rows("1")) + ch <- struct{}{} + }() + + select { + case <-time.After(100 * time.Millisecond): + // Expected, query blocked, not finish within 100ms. + tk1.MustExec("rollback") + case <-ch: + // Unexpected, test fail. + c.Fail() + } +}