From d6edb688d32a087cf2ae2576026f8e40675210f9 Mon Sep 17 00:00:00 2001 From: Ti Chi Robot Date: Thu, 18 Jul 2024 00:04:30 +0800 Subject: [PATCH] planner: fix invalid pointer caused by a recursive CTE query (#54450) (#54676) close pingcap/tidb#54449 --- pkg/executor/cte_test.go | 50 ++++++++++++++++++++++++++++++ pkg/planner/core/find_best_task.go | 2 +- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/pkg/executor/cte_test.go b/pkg/executor/cte_test.go index 1738220235774..410ca652b5ace 100644 --- a/pkg/executor/cte_test.go +++ b/pkg/executor/cte_test.go @@ -604,3 +604,53 @@ func TestCTEIterationMemTracker(t *testing.T) { }() tk.MustQuery(fmt.Sprintf("explain analyze with recursive cte1 as (select c1 from t1 union all select c1 + 1 c1 from cte1 where c1 < %d) select * from cte1", maxIter)) } + +func TestCTETableInvaildTask(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("CREATE TABLE p ( groupid bigint(20) DEFAULT NULL, KEY k1 (groupid));") + tk.MustExec(`CREATE TABLE g (groupid bigint(20) DEFAULT NULL,parentid bigint(20) NOT NULL,KEY k1 (parentid),KEY k2 (groupid,parentid));`) + tk.MustExec(`set tidb_opt_enable_hash_join=off;`) + tk.MustQuery(`explain WITH RECURSIVE w(gid) AS ( + SELECT + groupId + FROM + p + UNION + SELECT + g.groupId + FROM + g + JOIN w ON g.parentId = w.gid +) +SELECT + 1 +FROM + g +WHERE + g.groupId IN ( + SELECT + gid + FROM + w + );`).Check(testkit.Rows( + "Projection_54 9990.00 root 1->Column#17", + "└─IndexJoin_59 9990.00 root inner join, inner:IndexReader_58, outer key:test.p.groupid, inner key:test.g.groupid, equal cond:eq(test.p.groupid, test.g.groupid)", + " ├─HashAgg_75(Build) 12800.00 root group by:test.p.groupid, funcs:firstrow(test.p.groupid)->test.p.groupid", + " │ └─Selection_72 12800.00 root not(isnull(test.p.groupid))", + " │ └─CTEFullScan_73 16000.00 root CTE:w data:CTE_0", + " └─IndexReader_58(Probe) 9990.00 root index:Selection_57", + " └─Selection_57 9990.00 cop[tikv] not(isnull(test.g.groupid))", + " └─IndexRangeScan_56 10000.00 cop[tikv] table:g, index:k2(groupid, parentid) range: decided by [eq(test.g.groupid, test.p.groupid)], keep order:false, stats:pseudo", + "CTE_0 16000.00 root Recursive CTE", + "├─IndexReader_24(Seed Part) 10000.00 root index:IndexFullScan_23", + "│ └─IndexFullScan_23 10000.00 cop[tikv] table:p, index:k1(groupid) keep order:false, stats:pseudo", + "└─IndexHashJoin_34(Recursive Part) 10000.00 root inner join, inner:IndexLookUp_31, outer key:test.p.groupid, inner key:test.g.parentid, equal cond:eq(test.p.groupid, test.g.parentid)", + " ├─Selection_51(Build) 8000.00 root not(isnull(test.p.groupid))", + " │ └─CTETable_52 10000.00 root Scan on CTE_0", + " └─IndexLookUp_31(Probe) 10000.00 root ", + " ├─IndexRangeScan_29(Build) 10000.00 cop[tikv] table:g, index:k1(parentid) range: decided by [eq(test.g.parentid, test.p.groupid)], keep order:false, stats:pseudo", + " └─TableRowIDScan_30(Probe) 10000.00 cop[tikv] table:g keep order:false, stats:pseudo")) + tk.MustQuery(`show warnings`).Check(testkit.Rows()) +} diff --git a/pkg/planner/core/find_best_task.go b/pkg/planner/core/find_best_task.go index 2036eea945021..e851828c910d7 100644 --- a/pkg/planner/core/find_best_task.go +++ b/pkg/planner/core/find_best_task.go @@ -2616,7 +2616,7 @@ func (p *LogicalCTE) findBestTask(prop *property.PhysicalProperty, counter *Plan func (p *LogicalCTETable) findBestTask(prop *property.PhysicalProperty, _ *PlanCounterTp, _ *physicalOptimizeOp) (t task, cntPlan int64, err error) { if !prop.IsSortItemEmpty() { - return nil, 1, nil + return invalidTask, 0, nil } pcteTable := PhysicalCTETable{IDForStorage: p.idForStorage}.Init(p.SCtx(), p.StatsInfo())