Skip to content

Commit a04a55c

Browse files
authored
planner, CTE, view: Fix default inline CTE which contains orderby/limit/distinct and inside of view | tidb-test=pr/2438 (#56609) (#56695)
close #56582, close #56603
1 parent 13e8409 commit a04a55c

File tree

11 files changed

+343
-39
lines changed

11 files changed

+343
-39
lines changed

pkg/planner/core/casetest/flatplan/testdata/flat_plan_suite_out.json

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@
212212
{
213213
"Depth": 2,
214214
"Label": 0,
215-
"IsRoot": false,
216-
"StoreType": 0,
215+
"IsRoot": true,
216+
"StoreType": 2,
217217
"ReqType": 0,
218218
"IsPhysicalPlan": true,
219219
"TextTreeIndent": "│ │ ",
@@ -232,15 +232,80 @@
232232
{
233233
"Depth": 2,
234234
"Label": 0,
235-
"IsRoot": false,
236-
"StoreType": 0,
235+
"IsRoot": true,
236+
"StoreType": 2,
237237
"ReqType": 0,
238238
"IsPhysicalPlan": true,
239239
"TextTreeIndent": "",
240240
"IsLastChild": true
241241
}
242242
],
243-
"CTEs": null
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+
]
244309
},
245310
{
246311
"SQL": "WITH RECURSIVE cte (n) AS( SELECT 1 UNION ALL SELECT n + 1 FROM cte WHERE n < 5)SELECT * FROM cte;",

pkg/planner/core/casetest/hint/testdata/integration_suite_out.json

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -796,18 +796,24 @@
796796
{
797797
"SQL": "explain format = 'brief' select /*+ qb_name(qb_v8, v8), merge(@qb_v8) */ * from v8;",
798798
"Plan": [
799-
"HashAgg 16000.00 root group by:Column#41, funcs:firstrow(Column#41)->Column#41",
799+
"HashAgg 16000.00 root group by:Column#21, funcs:firstrow(Column#21)->Column#21",
800800
"└─Union 1000000010000.00 root ",
801801
" ├─HashJoin 1000000000000.00 root CARTESIAN inner join",
802-
" │ ├─IndexReader(Build) 10000.00 root index:IndexFullScan",
803-
" │ │ └─IndexFullScan 10000.00 cop[tikv] table:t3, index:idx_a(a) keep order:false, stats:pseudo",
804-
" │ └─HashJoin(Probe) 100000000.00 root CARTESIAN inner join",
805-
" │ ├─IndexReader(Build) 10000.00 root index:IndexFullScan",
806-
" │ │ └─IndexFullScan 10000.00 cop[tikv] table:t2, index:idx_a(a) keep order:false, stats:pseudo",
807-
" │ └─TableReader(Probe) 10000.00 root data:TableFullScan",
808-
" │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
802+
" │ ├─TableReader(Build) 10000.00 root data:TableFullScan",
803+
" │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
804+
" │ └─CTEFullScan(Probe) 100000000.00 root CTE:cte2 data:CTE_1",
809805
" └─TableReader 10000.00 root data:TableFullScan",
810-
" └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
806+
" └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
807+
"CTE_1 100000000.00 root Non-Recursive CTE",
808+
"└─HashJoin(Seed Part) 100000000.00 root CARTESIAN inner join",
809+
" ├─CTEFullScan(Build) 10000.00 root CTE:cte4 data:CTE_3",
810+
" └─CTEFullScan(Probe) 10000.00 root CTE:cte3 data:CTE_2",
811+
"CTE_3 10000.00 root Non-Recursive CTE",
812+
"└─IndexReader(Seed Part) 10000.00 root index:IndexFullScan",
813+
" └─IndexFullScan 10000.00 cop[tikv] table:t3, index:idx_a(a) keep order:false, stats:pseudo",
814+
"CTE_2 10000.00 root Non-Recursive CTE",
815+
"└─IndexReader(Seed Part) 10000.00 root index:IndexFullScan",
816+
" └─IndexFullScan 10000.00 cop[tikv] table:t2, index:idx_a(a) keep order:false, stats:pseudo"
811817
],
812818
"Warn": null
813819
},

pkg/planner/core/casetest/physicalplantest/physical_plan_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1209,6 +1209,7 @@ func TestSingleConsumerCTE(t *testing.T) {
12091209
tk.MustExec("create table t1 (c1 int primary key, c2 int, index c2 (c2));")
12101210
tk.MustExec("create table t2 (c1 int unique, c2 int);")
12111211
tk.MustExec("insert into t values (1), (5), (10), (15), (20), (30), (50);")
1212+
tk.MustExec("create table test(a int);")
12121213

12131214
var (
12141215
input []string
@@ -1225,7 +1226,7 @@ func TestSingleConsumerCTE(t *testing.T) {
12251226
testdata.OnRecord(func() {
12261227
output[i].SQL = ts
12271228
})
1228-
if strings.HasPrefix(ts, "set") {
1229+
if strings.HasPrefix(ts, "set") || strings.HasPrefix(ts, "create") {
12291230
tk.MustExec(ts)
12301231
continue
12311232
}

pkg/planner/core/casetest/physicalplantest/testdata/plan_suite_in.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,18 @@
571571
"with cte as (select 1) select /*+ MERGE() */ * from cte union select * from cte; -- firstly inline cte, secondly cannot be inlined",
572572
"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",
573573
"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",
574-
"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"
574+
"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",
575+
"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",
576+
"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",
577+
"WITH RECURSIVE CTE (x) AS (SELECT 1 UNION ALL SELECT distinct a FROM test), CTE1 AS (SELECT x FROM CTE UNION ALL select CTE.x from CTE join CTE1 on CTE.x=CTE1.x) SELECT * FROM CTE1; -- CTE contain distinct and ref by CET1 recursive part cannot be inlined;",
578+
"create definer='root'@'localhost' view test_cte(a) as WITH RECURSIVE CTE (x) AS (SELECT 1 UNION ALL SELECT distinct a FROM test) , CTE1 AS (SELECT x FROM CTE UNION ALL select CTE.x from CTE join CTE1 on CTE.x=CTE1.x) SELECT * FROM CTE1;",
579+
"select * from test_cte; -- CTE (inside of view) cannot be inlined by default;",
580+
"create definer='root'@'localhost' view test_inline_cte(a) as with CTE (x) as (select distinct a from test) select * from CTE;",
581+
"select * from test_inline_cte; -- CTE (inside of view) cannot be inlined by default;",
582+
"create definer='root'@'localhost' view test_force_inline_cte(a) as with CTE (x) as (select /*+ merge() */ distinct a from test) select * from CTE;",
583+
"select * from test_force_inline_cte; -- CTE (inside of view) can be inlined by force;" ,
584+
"WITH RECURSIVE CTE (x) AS (SELECT a FROM test limit 1) , CTE1(x) AS (SELECT a FROM test UNION ALL select CTE.x from CTE join CTE1 on CTE.x=CTE1.x) SELECT * FROM CTE1; -- CTE contain limit and ref by CET1 recursive part cannot be inlined;",
585+
"WITH RECURSIVE CTE (x) AS (SELECT a FROM test order by a) , CTE1(x) AS (SELECT a FROM test UNION ALL select CTE.x from CTE join CTE1 on CTE.x=CTE1.x) SELECT * FROM CTE1; -- CTE contain order by and ref by CET1 recursive part cannot be inlined;"
575586
]
576587
},
577588
{

pkg/planner/core/casetest/physicalplantest/testdata/plan_suite_out.json

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3390,6 +3390,159 @@
33903390
" └─CTETable 1.00 root Scan on CTE_4"
33913391
],
33923392
"Warning": null
3393+
},
3394+
{
3395+
"SQL": "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",
3396+
"Plan": [
3397+
"CTEFullScan 1.80 root CTE:tmp data:CTE_4",
3398+
"CTE_4 1.80 root Recursive CTE",
3399+
"├─Projection(Seed Part) 1.00 root 2->Column#37",
3400+
"│ └─HashAgg 1.00 root funcs:count(Column#46)->Column#44",
3401+
"│ └─TableReader 1.00 root data:HashAgg",
3402+
"│ └─HashAgg 1.00 cop[tikv] funcs:count(1)->Column#46",
3403+
"│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
3404+
"└─Projection(Recursive Part) 0.80 root cast(plus(Column#38, 1), bigint(1) BINARY)->Column#40",
3405+
" └─Selection 0.80 root lt(plus(Column#38, 1), 10)",
3406+
" └─CTETable 1.00 root Scan on CTE_4"
3407+
],
3408+
"Warning": null
3409+
},
3410+
{
3411+
"SQL": "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",
3412+
"Plan": [
3413+
"CTEFullScan 1.80 root CTE:tmp data:CTE_4",
3414+
"CTE_4 1.80 root Recursive CTE",
3415+
"├─Projection(Seed Part) 1.00 root 2->Column#37",
3416+
"│ └─HashAgg 1.00 root funcs:count(Column#46)->Column#44",
3417+
"│ └─TableReader 1.00 root data:HashAgg",
3418+
"│ └─HashAgg 1.00 cop[tikv] funcs:count(1)->Column#46",
3419+
"│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
3420+
"└─Projection(Recursive Part) 0.80 root cast(plus(Column#38, 1), bigint(1) BINARY)->Column#40",
3421+
" └─Selection 0.80 root lt(plus(Column#38, 1), 10)",
3422+
" └─CTETable 1.00 root Scan on CTE_4"
3423+
],
3424+
"Warning": null
3425+
},
3426+
{
3427+
"SQL": "WITH RECURSIVE CTE (x) AS (SELECT 1 UNION ALL SELECT distinct a FROM test), CTE1 AS (SELECT x FROM CTE UNION ALL select CTE.x from CTE join CTE1 on CTE.x=CTE1.x) SELECT * FROM CTE1; -- CTE contain distinct and ref by CET1 recursive part cannot be inlined;",
3428+
"Plan": [
3429+
"CTEFullScan 14401.80 root CTE:cte1 data:CTE_1",
3430+
"CTE_1 14401.80 root Recursive CTE",
3431+
"├─CTEFullScan(Seed Part) 8001.00 root CTE:cte data:CTE_0",
3432+
"└─HashJoin(Recursive Part) 6400.80 root inner join, equal:[eq(Column#11, Column#12)]",
3433+
" ├─Selection(Build) 6400.80 root not(isnull(Column#12))",
3434+
" │ └─CTETable 8001.00 root Scan on CTE_1",
3435+
" └─Selection(Probe) 6400.80 root not(isnull(Column#11))",
3436+
" └─CTEFullScan 8001.00 root CTE:cte data:CTE_0",
3437+
"CTE_0 8001.00 root Non-Recursive CTE",
3438+
"└─Union(Seed Part) 8001.00 root ",
3439+
" ├─Projection 1.00 root 1->Column#7",
3440+
" │ └─TableDual 1.00 root rows:1",
3441+
" └─Projection 8000.00 root cast(test.test.a, bigint(11) BINARY)->Column#7",
3442+
" └─HashAgg 8000.00 root group by:test.test.a, funcs:firstrow(test.test.a)->test.test.a",
3443+
" └─TableReader 8000.00 root data:HashAgg",
3444+
" └─HashAgg 8000.00 cop[tikv] group by:test.test.a, ",
3445+
" └─TableFullScan 10000.00 cop[tikv] table:test keep order:false, stats:pseudo"
3446+
],
3447+
"Warning": null
3448+
},
3449+
{
3450+
"SQL": "create definer='root'@'localhost' view test_cte(a) as WITH RECURSIVE CTE (x) AS (SELECT 1 UNION ALL SELECT distinct a FROM test) , CTE1 AS (SELECT x FROM CTE UNION ALL select CTE.x from CTE join CTE1 on CTE.x=CTE1.x) SELECT * FROM CTE1;",
3451+
"Plan": null,
3452+
"Warning": null
3453+
},
3454+
{
3455+
"SQL": "select * from test_cte; -- CTE (inside of view) cannot be inlined by default;",
3456+
"Plan": [
3457+
"CTEFullScan 14401.80 root CTE:cte1 data:CTE_1",
3458+
"CTE_1 14401.80 root Recursive CTE",
3459+
"├─CTEFullScan(Seed Part) 8001.00 root CTE:cte data:CTE_0",
3460+
"└─HashJoin(Recursive Part) 6400.80 root inner join, equal:[eq(Column#11, Column#12)]",
3461+
" ├─Selection(Build) 6400.80 root not(isnull(Column#12))",
3462+
" │ └─CTETable 8001.00 root Scan on CTE_1",
3463+
" └─Selection(Probe) 6400.80 root not(isnull(Column#11))",
3464+
" └─CTEFullScan 8001.00 root CTE:cte data:CTE_0",
3465+
"CTE_0 8001.00 root Non-Recursive CTE",
3466+
"└─Union(Seed Part) 8001.00 root ",
3467+
" ├─Projection 1.00 root 1->Column#7",
3468+
" │ └─TableDual 1.00 root rows:1",
3469+
" └─Projection 8000.00 root cast(test.test.a, bigint(11) BINARY)->Column#7",
3470+
" └─HashAgg 8000.00 root group by:test.test.a, funcs:firstrow(test.test.a)->test.test.a",
3471+
" └─TableReader 8000.00 root data:HashAgg",
3472+
" └─HashAgg 8000.00 cop[tikv] group by:test.test.a, ",
3473+
" └─TableFullScan 10000.00 cop[tikv] table:test keep order:false, stats:pseudo"
3474+
],
3475+
"Warning": null
3476+
},
3477+
{
3478+
"SQL": "create definer='root'@'localhost' view test_inline_cte(a) as with CTE (x) as (select distinct a from test) select * from CTE;",
3479+
"Plan": null,
3480+
"Warning": null
3481+
},
3482+
{
3483+
"SQL": "select * from test_inline_cte; -- CTE (inside of view) cannot be inlined by default;",
3484+
"Plan": [
3485+
"CTEFullScan 8000.00 root CTE:cte data:CTE_0",
3486+
"CTE_0 8000.00 root Non-Recursive CTE",
3487+
"└─HashAgg(Seed Part) 8000.00 root group by:test.test.a, funcs:firstrow(test.test.a)->test.test.a",
3488+
" └─TableReader 8000.00 root data:HashAgg",
3489+
" └─HashAgg 8000.00 cop[tikv] group by:test.test.a, ",
3490+
" └─TableFullScan 10000.00 cop[tikv] table:test keep order:false, stats:pseudo"
3491+
],
3492+
"Warning": null
3493+
},
3494+
{
3495+
"SQL": "create definer='root'@'localhost' view test_force_inline_cte(a) as with CTE (x) as (select /*+ merge() */ distinct a from test) select * from CTE;",
3496+
"Plan": null,
3497+
"Warning": null
3498+
},
3499+
{
3500+
"SQL": "select * from test_force_inline_cte; -- CTE (inside of view) can be inlined by force;",
3501+
"Plan": [
3502+
"HashAgg 8000.00 root group by:test.test.a, funcs:firstrow(test.test.a)->test.test.a",
3503+
"└─TableReader 8000.00 root data:HashAgg",
3504+
" └─HashAgg 8000.00 cop[tikv] group by:test.test.a, ",
3505+
" └─TableFullScan 10000.00 cop[tikv] table:test keep order:false, stats:pseudo"
3506+
],
3507+
"Warning": null
3508+
},
3509+
{
3510+
"SQL": "WITH RECURSIVE CTE (x) AS (SELECT a FROM test limit 1) , CTE1(x) AS (SELECT a FROM test UNION ALL select CTE.x from CTE join CTE1 on CTE.x=CTE1.x) SELECT * FROM CTE1; -- CTE contain limit and ref by CET1 recursive part cannot be inlined;",
3511+
"Plan": [
3512+
"CTEFullScan 16400.00 root CTE:cte1 data:CTE_1",
3513+
"CTE_1 16400.00 root Recursive CTE",
3514+
"├─TableReader(Seed Part) 10000.00 root data:TableFullScan",
3515+
"│ └─TableFullScan 10000.00 cop[tikv] table:test keep order:false, stats:pseudo",
3516+
"└─HashJoin(Recursive Part) 6400.00 root inner join, equal:[eq(test.test.a, test.test.a)]",
3517+
" ├─Selection(Build) 0.80 root not(isnull(test.test.a))",
3518+
" │ └─CTEFullScan 1.00 root CTE:cte data:CTE_0",
3519+
" └─Selection(Probe) 8000.00 root not(isnull(test.test.a))",
3520+
" └─CTETable 10000.00 root Scan on CTE_1",
3521+
"CTE_0 1.00 root Non-Recursive CTE",
3522+
"└─Limit(Seed Part) 1.00 root offset:0, count:1",
3523+
" └─TableReader 1.00 root data:Limit",
3524+
" └─Limit 1.00 cop[tikv] offset:0, count:1",
3525+
" └─TableFullScan 1.00 cop[tikv] table:test keep order:false, stats:pseudo"
3526+
],
3527+
"Warning": null
3528+
},
3529+
{
3530+
"SQL": "WITH RECURSIVE CTE (x) AS (SELECT a FROM test order by a) , CTE1(x) AS (SELECT a FROM test UNION ALL select CTE.x from CTE join CTE1 on CTE.x=CTE1.x) SELECT * FROM CTE1; -- CTE contain order by and ref by CET1 recursive part cannot be inlined;",
3531+
"Plan": [
3532+
"CTEFullScan 20000.00 root CTE:cte1 data:CTE_1",
3533+
"CTE_1 20000.00 root Recursive CTE",
3534+
"├─TableReader(Seed Part) 10000.00 root data:TableFullScan",
3535+
"│ └─TableFullScan 10000.00 cop[tikv] table:test keep order:false, stats:pseudo",
3536+
"└─HashJoin(Recursive Part) 10000.00 root inner join, equal:[eq(test.test.a, test.test.a)]",
3537+
" ├─Selection(Build) 8000.00 root not(isnull(test.test.a))",
3538+
" │ └─CTEFullScan 10000.00 root CTE:cte data:CTE_0",
3539+
" └─Selection(Probe) 8000.00 root not(isnull(test.test.a))",
3540+
" └─CTETable 10000.00 root Scan on CTE_1",
3541+
"CTE_0 10000.00 root Non-Recursive CTE",
3542+
"└─TableReader(Seed Part) 10000.00 root data:TableFullScan",
3543+
" └─TableFullScan 10000.00 cop[tikv] table:test keep order:false, stats:pseudo"
3544+
],
3545+
"Warning": null
33933546
}
33943547
]
33953548
},

pkg/planner/core/casetest/planstats/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ go_test(
99
],
1010
data = glob(["testdata/**"]),
1111
flaky = True,
12-
shard_count = 5,
12+
shard_count = 6,
1313
deps = [
1414
"//pkg/config",
1515
"//pkg/domain",

0 commit comments

Comments
 (0)