Skip to content

Commit 30498cc

Browse files
authored
planner, CTE: Fix default inline CTE which contains agg or window function and refactor inline CTE strategy (#48436)
close #47711
1 parent ac6bc7a commit 30498cc

13 files changed

+209
-148
lines changed

cmd/explaintest/r/cte.result

-12
Original file line numberDiff line numberDiff line change
@@ -790,15 +790,3 @@ with cte1 as (select 1), cte2 as (select 2) select * from cte1 union (with cte2
790790
1
791791
1
792792
3
793-
explain with cte1 as (select 1), cte2 as (select 2) select * from cte1 union (with cte2 as (select 3) select * from cte2 union all select * from cte2);
794-
id estRows task access object operator info
795-
HashAgg_24 3.00 root group by:Column#9, funcs:firstrow(Column#9)->Column#9
796-
└─Union_25 3.00 root
797-
├─Projection_26 1.00 root 1->Column#9
798-
│ └─TableDual_27 1.00 root rows:1
799-
└─Union_29 2.00 root
800-
├─CTEFullScan_31 1.00 root CTE:cte2 data:CTE_2
801-
└─CTEFullScan_33 1.00 root CTE:cte2 data:CTE_2
802-
CTE_2 1.00 root Non-Recursive CTE
803-
└─Projection_22(Seed Part) 1.00 root 3->Column#5
804-
└─TableDual_23 1.00 root rows:1

cmd/explaintest/r/explain_cte.result

-27
Original file line numberDiff line numberDiff line change
@@ -167,33 +167,6 @@ CTE_0 8001.00 root Recursive CTE, limit(offset:0, count:0)
167167
│ └─TableFullScan_17 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo
168168
└─Projection_21(Recursive Part) 10000.00 root cast(plus(test.t1.c1, 1), int(11))->test.t1.c1
169169
└─CTETable_22 10000.00 root Scan on CTE_0
170-
explain with recursive cte1(c1) as (select c1 from t1 union select c1 from t2 limit 1) select * from cte1;
171-
id estRows task access object operator info
172-
CTEFullScan_34 1.00 root CTE:cte1 data:CTE_0
173-
CTE_0 1.00 root Non-Recursive CTE
174-
└─Limit_20(Seed Part) 1.00 root offset:0, count:1
175-
└─HashAgg_21 1.00 root group by:Column#11, funcs:firstrow(Column#11)->Column#11
176-
└─Union_22 20000.00 root
177-
├─TableReader_25 10000.00 root data:TableFullScan_24
178-
│ └─TableFullScan_24 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo
179-
└─IndexReader_32 10000.00 root index:IndexFullScan_31
180-
└─IndexFullScan_31 10000.00 cop[tikv] table:t2, index:c1(c1) keep order:false, stats:pseudo
181-
explain with recursive cte1(c1) as (select c1 from t1 union select c1 from t2 limit 100 offset 100) select * from cte1;
182-
id estRows task access object operator info
183-
CTEFullScan_34 100.00 root CTE:cte1 data:CTE_0
184-
CTE_0 100.00 root Non-Recursive CTE
185-
└─Limit_20(Seed Part) 100.00 root offset:100, count:100
186-
└─HashAgg_21 200.00 root group by:Column#11, funcs:firstrow(Column#11)->Column#11
187-
└─Union_22 20000.00 root
188-
├─TableReader_25 10000.00 root data:TableFullScan_24
189-
│ └─TableFullScan_24 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo
190-
└─IndexReader_32 10000.00 root index:IndexFullScan_31
191-
└─IndexFullScan_31 10000.00 cop[tikv] table:t2, index:c1(c1) keep order:false, stats:pseudo
192-
explain with recursive cte1(c1) as (select c1 from t1 union select c1 from t2 limit 0 offset 0) select * from cte1;
193-
id estRows task access object operator info
194-
CTEFullScan_18 0.00 root CTE:cte1 data:CTE_0
195-
CTE_0 0.00 root Non-Recursive CTE
196-
└─TableDual_16(Seed Part) 0.00 root rows:0
197170
CREATE TABLE `customer` (
198171
`c_customer_sk` int(11) NOT NULL,
199172
`c_customer_id` char(16) NOT NULL,

cmd/explaintest/t/cte.test

-1
Original file line numberDiff line numberDiff line change
@@ -336,4 +336,3 @@ INSERT INTO `t_dnmxh` VALUES (104,571000,NULL),(104,572000,44.37),(104,573000,59
336336
WITH cte_0 AS (select distinct ref_0.wkey as c0, ref_0.pkey as c1, ref_0.c_xhsndb as c2 from t_dnmxh as ref_0 where (1 <= ( select ref_1.pkey not in ( select ref_5.wkey as c0 from t_dnmxh as ref_5 where (ref_5.wkey < ( select ref_6.pkey as c0 from t_cqmg3b as ref_6 where 88 between 96 and 76)) ) as c0 from (t_cqmg3b as ref_1 left outer join t_dnmxh as ref_2 on (ref_1.wkey = ref_2.wkey )) where ref_0.c_xhsndb is NULL union select 33 <= 91 as c0 from t_cqmg3b as ref_8 ))), cte_1 AS (select ref_9.wkey as c0, ref_9.pkey as c1, ref_9.c_anpf_c as c2, ref_9.c_b_fp_c as c3, ref_9.c_ndccfb as c4, ref_9.c_8rswc as c5 from t_cqmg3b as ref_9) select count(1) from cte_0 as ref_10 where case when 56 < 50 then case when 100 in ( select distinct ref_11.c4 as c0 from cte_1 as ref_11 where (ref_11.c4 > ( select ref_13.pkey as c0 from t_dnmxh as ref_13 where (ref_13.wkey > ( select distinct ref_11.c1 as c0 from cte_0 as ref_14)) )) or (1 = 1)) then null else null end else '7mxv6' end not like 'ki4%vc';
337337
#case
338338
with cte1 as (select 1), cte2 as (select 2) select * from cte1 union (with cte2 as (select 3) select * from cte2 union all select * from cte2) order by 1;
339-
explain with cte1 as (select 1), cte2 as (select 2) select * from cte1 union (with cte2 as (select 3) select * from cte2 union all select * from cte2);

cmd/explaintest/t/explain_cte.test

-5
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,6 @@ explain with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 c1 fro
3939
explain with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 c1 from cte1 limit 1) select * from cte1 dt1 join cte1 dt2 on dt1.c1 = dt2.c1;
4040
explain with recursive cte1(c1) as (select c1 from t1 union select c1 + 1 c1 from cte1 limit 0 offset 0) select * from cte1 dt1 join cte1 dt2 on dt1.c1 = dt2.c1;
4141

42-
# non-recursive limit
43-
explain with recursive cte1(c1) as (select c1 from t1 union select c1 from t2 limit 1) select * from cte1;
44-
explain with recursive cte1(c1) as (select c1 from t1 union select c1 from t2 limit 100 offset 100) select * from cte1;
45-
explain with recursive cte1(c1) as (select c1 from t1 union select c1 from t2 limit 0 offset 0) select * from cte1;
46-
4742
# TPC-DS Q11
4843
CREATE TABLE `customer` (
4944
`c_customer_sk` int(11) NOT NULL,

planner/core/casetest/physical_plan_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -1432,6 +1432,8 @@ func TestSingleConsumerCTE(t *testing.T) {
14321432
tk.MustExec("use test")
14331433
tk.MustExec("drop table if exists t;")
14341434
tk.MustExec("CREATE TABLE `t` (`a` int(11));")
1435+
tk.MustExec("create table t1 (c1 int primary key, c2 int, index c2 (c2));")
1436+
tk.MustExec("create table t2 (c1 int unique, c2 int);")
14351437
tk.MustExec("insert into t values (1), (5), (10), (15), (20), (30), (50);")
14361438

14371439
var (

planner/core/casetest/testdata/flat_plan_suite_out.json

+5-70
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@
212212
{
213213
"Depth": 2,
214214
"Label": 0,
215-
"IsRoot": true,
216-
"StoreType": 2,
215+
"IsRoot": false,
216+
"StoreType": 0,
217217
"ReqType": 0,
218218
"IsPhysicalPlan": true,
219219
"TextTreeIndent": "│ │ ",
@@ -232,80 +232,15 @@
232232
{
233233
"Depth": 2,
234234
"Label": 0,
235-
"IsRoot": true,
236-
"StoreType": 2,
235+
"IsRoot": false,
236+
"StoreType": 0,
237237
"ReqType": 0,
238238
"IsPhysicalPlan": true,
239239
"TextTreeIndent": "",
240240
"IsLastChild": true
241241
}
242242
],
243-
"CTEs": [
244-
[
245-
{
246-
"Depth": 0,
247-
"Label": 0,
248-
"IsRoot": true,
249-
"StoreType": 2,
250-
"ReqType": 0,
251-
"IsPhysicalPlan": true,
252-
"TextTreeIndent": "",
253-
"IsLastChild": true
254-
},
255-
{
256-
"Depth": 1,
257-
"Label": 3,
258-
"IsRoot": true,
259-
"StoreType": 2,
260-
"ReqType": 0,
261-
"IsPhysicalPlan": true,
262-
"TextTreeIndent": "",
263-
"IsLastChild": true
264-
},
265-
{
266-
"Depth": 2,
267-
"Label": 0,
268-
"IsRoot": false,
269-
"StoreType": 0,
270-
"ReqType": 0,
271-
"IsPhysicalPlan": true,
272-
"TextTreeIndent": "",
273-
"IsLastChild": true
274-
}
275-
],
276-
[
277-
{
278-
"Depth": 0,
279-
"Label": 0,
280-
"IsRoot": true,
281-
"StoreType": 2,
282-
"ReqType": 0,
283-
"IsPhysicalPlan": true,
284-
"TextTreeIndent": "",
285-
"IsLastChild": true
286-
},
287-
{
288-
"Depth": 1,
289-
"Label": 3,
290-
"IsRoot": true,
291-
"StoreType": 2,
292-
"ReqType": 0,
293-
"IsPhysicalPlan": true,
294-
"TextTreeIndent": "",
295-
"IsLastChild": true
296-
},
297-
{
298-
"Depth": 2,
299-
"Label": 0,
300-
"IsRoot": false,
301-
"StoreType": 0,
302-
"ReqType": 0,
303-
"IsPhysicalPlan": true,
304-
"TextTreeIndent": "",
305-
"IsLastChild": true
306-
}
307-
]
308-
]
243+
"CTEs": null
309244
},
310245
{
311246
"SQL": "WITH RECURSIVE cte (n) AS( SELECT 1 UNION ALL SELECT n + 1 FROM cte WHERE n < 5)SELECT * FROM cte;",

planner/core/casetest/testdata/integration_suite_out.json

+10-13
Original file line numberDiff line numberDiff line change
@@ -6593,24 +6593,21 @@
65936593
{
65946594
"SQL": "explain format = 'brief' select /*+ qb_name(qb_v8, v8), merge(@qb_v8) */ * from v8;",
65956595
"Plan": [
6596-
"HashAgg 16000.00 root group by:Column#21, funcs:firstrow(Column#21)->Column#21",
6596+
"HashAgg 16000.00 root group by:Column#41, funcs:firstrow(Column#41)->Column#41",
65976597
"└─Union 1000000010000.00 root ",
65986598
" ├─HashJoin 1000000000000.00 root CARTESIAN inner join",
65996599
" │ ├─TableReader(Build) 10000.00 root data:TableFullScan",
66006600
" │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
6601-
" │ └─CTEFullScan(Probe) 100000000.00 root CTE:cte2 data:CTE_1",
6601+
" │ └─Projection(Probe) 100000000.00 root 1->Column#55",
6602+
" │ └─HashJoin 100000000.00 root CARTESIAN inner join",
6603+
" │ ├─Projection(Build) 10000.00 root 1->Column#54",
6604+
" │ │ └─IndexReader 10000.00 root index:IndexFullScan",
6605+
" │ │ └─IndexFullScan 10000.00 cop[tikv] table:t3, index:idx_a(a) keep order:false, stats:pseudo",
6606+
" │ └─Projection(Probe) 10000.00 root 1->Column#53",
6607+
" │ └─IndexReader 10000.00 root index:IndexFullScan",
6608+
" │ └─IndexFullScan 10000.00 cop[tikv] table:t2, index:idx_a(a) keep order:false, stats:pseudo",
66026609
" └─TableReader 10000.00 root data:TableFullScan",
6603-
" └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
6604-
"CTE_1 100000000.00 root Non-Recursive CTE",
6605-
"└─HashJoin(Seed Part) 100000000.00 root CARTESIAN inner join",
6606-
" ├─CTEFullScan(Build) 10000.00 root CTE:cte4 data:CTE_3",
6607-
" └─CTEFullScan(Probe) 10000.00 root CTE:cte3 data:CTE_2",
6608-
"CTE_3 10000.00 root Non-Recursive CTE",
6609-
"└─IndexReader(Seed Part) 10000.00 root index:IndexFullScan",
6610-
" └─IndexFullScan 10000.00 cop[tikv] table:t3, index:idx_a(a) keep order:false, stats:pseudo",
6611-
"CTE_2 10000.00 root Non-Recursive CTE",
6612-
"└─IndexReader(Seed Part) 10000.00 root index:IndexFullScan",
6613-
" └─IndexFullScan 10000.00 cop[tikv] table:t2, index:idx_a(a) keep order:false, stats:pseudo"
6610+
" └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
66146611
],
66156612
"Warn": null
66166613
},

planner/core/casetest/testdata/plan_suite_in.json

+8-1
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,10 @@
796796
{
797797
"name": "TestSingleConsumerCTE",
798798
"cases": [
799+
"with recursive cte1(c1) as (select c1 from t1 union select c1 from t2 limit 1) select * from cte1; -- non-recursive limit, inline cte1",
800+
"with recursive cte1(c1) as (select c1 from t1 union select c1 from t2 limit 100 offset 100) select * from cte1; -- non-recursive limit, inline cte1",
801+
"with recursive cte1(c1) as (select c1 from t1 union select c1 from t2 limit 0 offset 0) select * from cte1; -- non-recursive limit, inline cte1",
802+
"with cte1 as (select 1), cte2 as (select 2) select * from cte1 union (with cte2 as (select 3) select * from cte2 union all select * from cte2) -- inline cte1, not inline cte2",
799803
"with base1 as (WITH RECURSIVE cte(a) AS (with tmp as (select 1 as a) SELECT a from tmp UNION SELECT a+1 FROM cte) SELECT * FROM cte) select * from base1; -- issue #43318",
800804
"with cte as (select 1) select * from cte; -- inline cte",
801805
"with cte1 as (select 1), cte2 as (select 2) select * from cte1 union select * from cte2; -- inline cte1, cte2",
@@ -810,7 +814,10 @@
810814
"set tidb_opt_force_inline_cte=1; -- enable force inline CTE",
811815
"with cte as (select 1) select * from cte union select * from cte; -- force inline cte while multi-consumer",
812816
"set tidb_opt_force_inline_cte=0; -- disable force inline CTE",
813-
"with cte as (select 1) select /*+ MERGE() */ * from cte union select * from cte; -- firstly inline cte, secondly cannot be inlined"
817+
"with cte as (select 1) select /*+ MERGE() */ * from cte union select * from cte; -- firstly inline cte, secondly cannot be inlined",
818+
"with a as (select 8 as id from dual),maxa as (select max(id) as max_id from a),b as (with recursive temp as (select 1 as lvl from dual union all select lvl+1 from temp, maxa where lvl < max_id)select * from temp) select * from b; -- issue #47711, maxa cannot be inlined because it contains agg and in the recursive part of cte temp",
819+
"with a as (select count(*) from t1), b as (select 2 as bb from a), c as (with recursive tmp as (select 1 as res from t1 union all select res+1 from tmp,b where res+1 < bb) select * from tmp) select * from c; -- inline a, cannot be inline b because b indirectly contains agg and in the recursive part of cte tmp",
820+
"with a as (select count(*) from t1), b as (select 2 as bb from a), c as (with recursive tmp as (select bb as res from b union all select res+1 from tmp where res +1 < 10) select * from tmp) select * from c; -- inline a, b, cannot be inline tmp, c"
814821
]
815822
},
816823
{

0 commit comments

Comments
 (0)