Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

planner: preprocessor add CTE recursive check when handleTableName (#34133) #34413

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions bindinfo/handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -863,8 +863,7 @@ func GenerateBindSQL(ctx context.Context, stmtNode ast.StmtNode, planHint string
withIdx := strings.Index(bindSQL, "WITH")
restoreCtx := format.NewRestoreCtx(format.RestoreStringSingleQuotes|format.RestoreSpacesAroundBinaryOperation|format.RestoreStringWithoutCharset|format.RestoreNameBackQuotes, &withSb)
restoreCtx.DefaultDB = defaultDB
err := n.With.Restore(restoreCtx)
if err != nil {
if err := n.With.Restore(restoreCtx); err != nil {
logutil.BgLogger().Debug("[sql-bind] restore SQL failed", zap.Error(err))
return ""
}
Expand Down
190 changes: 190 additions & 0 deletions cmd/explaintest/r/cte.result
Original file line number Diff line number Diff line change
Expand Up @@ -607,3 +607,193 @@ c1 c1 c1
1 1 1
2 2 2
3 3 3
// Test CTE as inner side of Apply
drop table if exists t1, t2;
create table t1(c1 int, c2 int);
insert into t1 values(2, 1);
insert into t1 values(2, 2);
create table t2(c1 int, c2 int);
insert into t2 values(1, 1);
insert into t2 values(3, 2);
explain select * from t1 where c1 > all(with cte1 as (select c1 from t2 where t2.c2 = t1.c2) select c1 from cte1);
id estRows task access object operator info
Projection_18 10000.00 root test.t1.c1, test.t1.c2
└─Apply_20 10000.00 root CARTESIAN inner join, other cond:or(and(gt(test.t1.c1, Column#8), if(ne(Column#9, 0), NULL, 1)), or(eq(Column#10, 0), if(isnull(test.t1.c1), NULL, 0)))
├─TableReader_22(Build) 10000.00 root data:TableFullScan_21
│ └─TableFullScan_21 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo
└─HashAgg_23(Probe) 1.00 root funcs:max(Column#13)->Column#8, funcs:sum(Column#14)->Column#9, funcs:count(1)->Column#10
└─Projection_27 10.00 root test.t2.c1, cast(isnull(test.t2.c1), decimal(20,0) BINARY)->Column#14
└─CTEFullScan_25 10.00 root CTE:cte1 data:CTE_0
CTE_0 10.00 root Non-Recursive CTE
└─Projection_13(Seed Part) 10.00 root test.t2.c1
└─TableReader_16 10.00 root data:Selection_15
└─Selection_15 10.00 cop[tikv] eq(test.t2.c2, test.t1.c2)
└─TableFullScan_14 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo
select * from t1 where c1 > all(with cte1 as (select c1 from t2 where t2.c2 = t1.c2) select c1 from cte1);
c1 c2
2 1
// Test semi apply.
insert into t1 values(2, 3);
explain select * from t1 where exists(with cte1 as (select c1 from t2 where t2.c2 = t1.c2) select c1 from cte1);
id estRows task access object operator info
Apply_17 10000.00 root CARTESIAN semi join
├─TableReader_19(Build) 10000.00 root data:TableFullScan_18
│ └─TableFullScan_18 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo
└─CTEFullScan_20(Probe) 10.00 root CTE:cte1 data:CTE_0
CTE_0 10.00 root Non-Recursive CTE
└─Projection_11(Seed Part) 10.00 root test.t2.c1
└─TableReader_14 10.00 root data:Selection_13
└─Selection_13 10.00 cop[tikv] eq(test.t2.c2, test.t1.c2)
└─TableFullScan_12 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo
select * from t1 where exists(with cte1 as (select c1 from t2 where t2.c2 = t1.c2) select c1 from cte1);
c1 c2
2 1
2 2
// Same as above, but test recursive cte.
explain select * from t1 where c1 > all(with recursive cte1 as (select c1 from t2 where t2.c2 = t1.c2 union all select c1+1 as c1 from cte1 limit 1) select c1 from cte1);
id estRows task access object operator info
Projection_26 10000.00 root test.t1.c1, test.t1.c2
└─Apply_28 10000.00 root CARTESIAN inner join, other cond:or(and(gt(test.t1.c1, Column#14), if(ne(Column#15, 0), NULL, 1)), or(eq(Column#16, 0), if(isnull(test.t1.c1), NULL, 0)))
├─TableReader_30(Build) 10000.00 root data:TableFullScan_29
│ └─TableFullScan_29 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo
└─HashAgg_31(Probe) 1.00 root funcs:max(Column#19)->Column#14, funcs:sum(Column#20)->Column#15, funcs:count(1)->Column#16
└─Projection_35 20.00 root test.t2.c1, cast(isnull(test.t2.c1), decimal(20,0) BINARY)->Column#20
└─CTEFullScan_33 20.00 root CTE:cte1 data:CTE_0
CTE_0 20.00 root Recursive CTE, limit(offset:0, count:1)
├─Projection_19(Seed Part) 10.00 root test.t2.c1
│ └─TableReader_22 10.00 root data:Selection_21
│ └─Selection_21 10.00 cop[tikv] eq(test.t2.c2, test.t1.c2)
│ └─TableFullScan_20 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo
└─Projection_23(Recursive Part) 10.00 root cast(plus(test.t2.c1, 1), int(11))->test.t2.c1
└─CTETable_24 10.00 root Scan on CTE_0
select * from t1 where c1 > all(with recursive cte1 as (select c1 from t2 where t2.c2 = t1.c2 union all select c1+1 as c1 from cte1 limit 1) select c1 from cte1);
c1 c2
2 1
2 3
explain select * from t1 where exists(with recursive cte1 as (select c1 from t2 where t2.c2 = t1.c2 union all select c1+1 as c1 from cte1 limit 10) select c1 from cte1);
id estRows task access object operator info
Apply_25 10000.00 root CARTESIAN semi join
├─TableReader_27(Build) 10000.00 root data:TableFullScan_26
│ └─TableFullScan_26 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo
└─CTEFullScan_28(Probe) 20.00 root CTE:cte1 data:CTE_0
CTE_0 20.00 root Recursive CTE, limit(offset:0, count:10)
├─Projection_17(Seed Part) 10.00 root test.t2.c1
│ └─TableReader_20 10.00 root data:Selection_19
│ └─Selection_19 10.00 cop[tikv] eq(test.t2.c2, test.t1.c2)
│ └─TableFullScan_18 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo
└─Projection_21(Recursive Part) 10.00 root cast(plus(test.t2.c1, 1), int(11))->test.t2.c1
└─CTETable_22 10.00 root Scan on CTE_0
select * from t1 where exists(with recursive cte1 as (select c1 from t2 where t2.c2 = t1.c2 union all select c1+1 as c1 from cte1 limit 10) select c1 from cte1);
c1 c2
2 1
2 2
// Test correlated col is in recursive part.
explain select * from t1 where c1 > all(with recursive cte1 as (select c1, c2 from t2 union all select c1+1 as c1, c2+1 as c2 from cte1 where cte1.c2=t1.c2) select c1 from cte1);
id estRows task access object operator info
Projection_24 10000.00 root test.t1.c1, test.t1.c2
└─Apply_26 10000.00 root CARTESIAN inner join, other cond:or(and(gt(test.t1.c1, Column#18), if(ne(Column#19, 0), NULL, 1)), or(eq(Column#20, 0), if(isnull(test.t1.c1), NULL, 0)))
├─TableReader_28(Build) 10000.00 root data:TableFullScan_27
│ └─TableFullScan_27 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo
└─HashAgg_29(Probe) 1.00 root funcs:max(Column#23)->Column#18, funcs:sum(Column#24)->Column#19, funcs:count(1)->Column#20
└─Projection_33 18000.00 root test.t2.c1, cast(isnull(test.t2.c1), decimal(20,0) BINARY)->Column#24
└─CTEFullScan_31 18000.00 root CTE:cte1 data:CTE_0
CTE_0 18000.00 root Recursive CTE
├─TableReader_19(Seed Part) 10000.00 root data:TableFullScan_18
│ └─TableFullScan_18 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo
└─Projection_20(Recursive Part) 8000.00 root cast(plus(test.t2.c1, 1), int(11))->test.t2.c1, cast(plus(test.t2.c2, 1), int(11))->test.t2.c2
└─Selection_21 8000.00 root eq(test.t2.c2, test.t1.c2)
└─CTETable_22 10000.00 root Scan on CTE_0
select * from t1 where c1 > all(with recursive cte1 as (select c1, c2 from t2 union all select c1+1 as c1, c2+1 as c2 from cte1 where cte1.c2=t1.c2) select c1 from cte1);
c1 c2
explain select * from t1 where exists(with recursive cte1 as (select c1, c2 from t2 union all select c1+1 as c1, c2+1 as c2 from cte1 where cte1.c2=t1.c2) select c1 from cte1);
id estRows task access object operator info
Apply_23 10000.00 root CARTESIAN semi join
├─TableReader_25(Build) 10000.00 root data:TableFullScan_24
│ └─TableFullScan_24 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo
└─CTEFullScan_26(Probe) 18000.00 root CTE:cte1 data:CTE_0
CTE_0 18000.00 root Recursive CTE
├─TableReader_17(Seed Part) 10000.00 root data:TableFullScan_16
│ └─TableFullScan_16 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo
└─Projection_18(Recursive Part) 8000.00 root cast(plus(test.t2.c1, 1), int(11))->test.t2.c1, cast(plus(test.t2.c2, 1), int(11))->test.t2.c2
└─Selection_19 8000.00 root eq(test.t2.c2, test.t1.c2)
└─CTETable_20 10000.00 root Scan on CTE_0
select * from t1 where exists(with recursive cte1 as (select c1, c2 from t2 union all select c1+1 as c1, c2+1 as c2 from cte1 where cte1.c2=t1.c2) select c1 from cte1);
c1 c2
2 1
2 2
2 3
use test;
drop table if exists t1, t2;
drop view if exists v1;
create table t1 (a int);
insert into t1 values (0), (1), (2), (3), (4);
create table t2 (a int);
insert into t2 values (1), (2), (3), (4), (5);
drop view if exists v1,v2;
create view v1 as with t1 as (select a from t2 where t2.a=3 union select t2.a+1 from t1,t2 where t1.a=t2.a) select * from t1 order by a desc;
create view v2 as with recursive t1 as ( select a from t2 where t2.a=3 union select t2.a+1 from t1,t2 where t1.a=t2.a) select * from t1 order by a desc;
create database if not exists test1;
use test1;
select * from test.v1;
a
5
4
3
2
select * from test.v2;
a
6
5
4
3
use test;
drop table if exists t ,t1, t2;
create table t(a int);
insert into t values (0);
create table t1 (b int);
insert into t1 values (0);
create table t2 (c int);
insert into t2 values (0);
drop view if exists v1;
create view v1 as with t1 as (with t11 as (select * from t) select * from t1, t2) select * from t1;
use test1;
select * from test.v1;
b c
0 0
use test;
drop table if exists t11111;
create table t11111 (d int);
insert into t11111 values (123), (223), (323);
drop view if exists v1;
create view v1 as WITH t123 AS (WITH t11111 AS ( SELECT * FROM t1 ) SELECT ( WITH t2 AS ( SELECT ( WITH t23 AS ( SELECT * FROM t11111 ) SELECT * FROM t23 LIMIT 1 ) FROM t11111 ) SELECT * FROM t2 LIMIT 1 ) FROM t11111, t2 ) SELECT * FROM t11111;
use test1;
select * from test.v1;
d
123
223
323
use test;
drop table if exists t1;
create table t1 (a int);
insert into t1 values (1);
drop view if exists v1;
create view v1 as SELECT (WITH qn AS (SELECT 10*a as a FROM t1),qn2 AS (SELECT 3*a AS b FROM qn) SELECT * from qn2 LIMIT 1) FROM t1;
use test1;
select * from test.v1;
name_exp_1
30
use test;
drop table if exists t1,t2;
create table t1 (a int);
insert into t1 values (0), (1);
create table t2 (b int);
insert into t2 values (4), (5);
drop view if exists v1;
create view v1 as with t1 as (with t11 as (select * from t1) select * from t1, t2) select * from t1;
use test1;
select * from test.v1;
a b
0 5
0 4
1 5
1 4
88 changes: 88 additions & 0 deletions cmd/explaintest/t/cte.test
Original file line number Diff line number Diff line change
Expand Up @@ -226,3 +226,91 @@ create table tpk1(c1 int primary key);
insert into tpk1 values(1), (2), (3);
explain with cte1 as (select c1 from tpk) select /*+ merge_join(dt1, dt2) */ * from tpk1 dt1 inner join cte1 dt2 inner join cte1 dt3 on dt1.c1 = dt2.c1 and dt2.c1 = dt3.c1;
with cte1 as (select c1 from tpk) select /*+ merge_join(dt1, dt2) */ * from tpk1 dt1 inner join cte1 dt2 inner join cte1 dt3 on dt1.c1 = dt2.c1 and dt2.c1 = dt3.c1;
#case 34
--echo // Test CTE as inner side of Apply
drop table if exists t1, t2;
create table t1(c1 int, c2 int);
insert into t1 values(2, 1);
insert into t1 values(2, 2);
create table t2(c1 int, c2 int);
insert into t2 values(1, 1);
insert into t2 values(3, 2);
explain select * from t1 where c1 > all(with cte1 as (select c1 from t2 where t2.c2 = t1.c2) select c1 from cte1);
select * from t1 where c1 > all(with cte1 as (select c1 from t2 where t2.c2 = t1.c2) select c1 from cte1);

--echo // Test semi apply.
insert into t1 values(2, 3);
explain select * from t1 where exists(with cte1 as (select c1 from t2 where t2.c2 = t1.c2) select c1 from cte1);
select * from t1 where exists(with cte1 as (select c1 from t2 where t2.c2 = t1.c2) select c1 from cte1);

--echo // Same as above, but test recursive cte.
explain select * from t1 where c1 > all(with recursive cte1 as (select c1 from t2 where t2.c2 = t1.c2 union all select c1+1 as c1 from cte1 limit 1) select c1 from cte1);
select * from t1 where c1 > all(with recursive cte1 as (select c1 from t2 where t2.c2 = t1.c2 union all select c1+1 as c1 from cte1 limit 1) select c1 from cte1);

explain select * from t1 where exists(with recursive cte1 as (select c1 from t2 where t2.c2 = t1.c2 union all select c1+1 as c1 from cte1 limit 10) select c1 from cte1);
select * from t1 where exists(with recursive cte1 as (select c1 from t2 where t2.c2 = t1.c2 union all select c1+1 as c1 from cte1 limit 10) select c1 from cte1);

--echo // Test correlated col is in recursive part.
explain select * from t1 where c1 > all(with recursive cte1 as (select c1, c2 from t2 union all select c1+1 as c1, c2+1 as c2 from cte1 where cte1.c2=t1.c2) select c1 from cte1);
select * from t1 where c1 > all(with recursive cte1 as (select c1, c2 from t2 union all select c1+1 as c1, c2+1 as c2 from cte1 where cte1.c2=t1.c2) select c1 from cte1);

explain select * from t1 where exists(with recursive cte1 as (select c1, c2 from t2 union all select c1+1 as c1, c2+1 as c2 from cte1 where cte1.c2=t1.c2) select c1 from cte1);
select * from t1 where exists(with recursive cte1 as (select c1, c2 from t2 union all select c1+1 as c1, c2+1 as c2 from cte1 where cte1.c2=t1.c2) select c1 from cte1);
# Some cases to Test Create View With CTE and checkout Database
# With name is the same as the table name
use test;
drop table if exists t1, t2;
drop view if exists v1;
create table t1 (a int);
insert into t1 values (0), (1), (2), (3), (4);
create table t2 (a int);
insert into t2 values (1), (2), (3), (4), (5);
drop view if exists v1,v2;
create view v1 as with t1 as (select a from t2 where t2.a=3 union select t2.a+1 from t1,t2 where t1.a=t2.a) select * from t1 order by a desc;
create view v2 as with recursive t1 as ( select a from t2 where t2.a=3 union select t2.a+1 from t1,t2 where t1.a=t2.a) select * from t1 order by a desc;
create database if not exists test1;
use test1;
select * from test.v1;
select * from test.v2;
# case
use test;
drop table if exists t ,t1, t2;
create table t(a int);
insert into t values (0);
create table t1 (b int);
insert into t1 values (0);
create table t2 (c int);
insert into t2 values (0);
drop view if exists v1;
create view v1 as with t1 as (with t11 as (select * from t) select * from t1, t2) select * from t1;
use test1;
select * from test.v1;
# case
use test;
drop table if exists t11111;
create table t11111 (d int);
insert into t11111 values (123), (223), (323);
drop view if exists v1;
create view v1 as WITH t123 AS (WITH t11111 AS ( SELECT * FROM t1 ) SELECT ( WITH t2 AS ( SELECT ( WITH t23 AS ( SELECT * FROM t11111 ) SELECT * FROM t23 LIMIT 1 ) FROM t11111 ) SELECT * FROM t2 LIMIT 1 ) FROM t11111, t2 ) SELECT * FROM t11111;
use test1;
select * from test.v1;
# case
use test;
drop table if exists t1;
create table t1 (a int);
insert into t1 values (1);
drop view if exists v1;
create view v1 as SELECT (WITH qn AS (SELECT 10*a as a FROM t1),qn2 AS (SELECT 3*a AS b FROM qn) SELECT * from qn2 LIMIT 1) FROM t1;
use test1;
select * from test.v1;
# case
use test;
drop table if exists t1,t2;
create table t1 (a int);
insert into t1 values (0), (1);
create table t2 (b int);
insert into t2 values (4), (5);
drop view if exists v1;
create view v1 as with t1 as (with t11 as (select * from t1) select * from t1, t2) select * from t1;
use test1;
select * from test.v1;
Loading