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: reopen CTE in apply only when correlate (#38214) #45066

Merged
merged 1 commit into from
Jun 30, 2023
Merged
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
20 changes: 20 additions & 0 deletions cmd/explaintest/r/cte.result
Original file line number Diff line number Diff line change
Expand Up @@ -805,3 +805,23 @@ a b
0 4
1 5
1 4
CREATE TABLE `t_cqmg3b` (
`wkey` int(11) DEFAULT NULL,
`pkey` int(11) NOT NULL,
`c_anpf_c` int(11) DEFAULT NULL,
`c_b_fp_c` text DEFAULT NULL,
`c_ndccfb` int(11) DEFAULT NULL,
`c_8rswc` int(11) DEFAULT NULL,
PRIMARY KEY (`pkey`) /*T![clustered_index] CLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
INSERT INTO `t_cqmg3b` VALUES (102,556000,NULL,'vbwxgc',NULL,NULL),(102,557000,NULL,'bfblud',NULL,NULL),(102,558000,NULL,'c6drnb',NULL,NULL),(102,559000,NULL,'fo_ezc',NULL,NULL),(102,560000,NULL,'btdes',NULL,NULL),(102,561000,NULL,'gy6zc',NULL,NULL),(102,562000,NULL,'9cyx9c',NULL,NULL),(102,563000,NULL,NULL,NULL,NULL),(103,564000,NULL,NULL,NULL,NULL),(103,565000,NULL,NULL,NULL,NULL),(103,566000,NULL,NULL,NULL,NULL),(103,567000,NULL,NULL,NULL,NULL),(103,568000,NULL,NULL,NULL,NULL),(103,569000,NULL,NULL,NULL,NULL),(103,570000,NULL,NULL,NULL,NULL),(105,578000,NULL,'fmicvd',NULL,NULL),(105,579000,NULL,'_tflkc',NULL,NULL),(105,580000,NULL,'xhovz',NULL,NULL),(105,581000,NULL,'n5bak',NULL,NULL),(105,582000,NULL,'gszus',NULL,NULL),(105,583000,NULL,'ewvydd',NULL,NULL),(105,584000,NULL,'fbzr0d',NULL,NULL),(107,590000,NULL,'8kgdf',NULL,NULL),(107,591000,NULL,'28v4bc',NULL,NULL),(107,592000,NULL,'evujpb',NULL,NULL),(107,593000,NULL,'8nkbzd',NULL,NULL),(107,594000,NULL,NULL,NULL,NULL),(109,599000,NULL,'1zswm',NULL,NULL),(109,600000,NULL,'gxlzrc',NULL,NULL),(109,601000,NULL,'xmedjc',NULL,NULL),(110,602000,NULL,'jwym6',NULL,NULL),(110,603000,NULL,NULL,NULL,NULL),(110,604000,NULL,'pcckxd',NULL,NULL),(111,605000,NULL,'lhvvp',NULL,NULL),(111,606000,NULL,'5eyidd',NULL,NULL),(111,607000,NULL,'l8azic',NULL,NULL),(111,608000,NULL,'_lmxx',NULL,NULL),(112,609000,NULL,'cstovb',NULL,NULL),(112,610000,NULL,'9bcdjc',NULL,NULL),(112,611000,NULL,'7zofhc',NULL,NULL),(112,612000,NULL,'pe2a3',NULL,NULL),(112,613000,NULL,'xtoet',NULL,NULL),(112,614000,NULL,'unvnj',NULL,NULL),(112,615000,NULL,'fj4v1b',NULL,NULL);
CREATE TABLE `t_dnmxh` (
`wkey` int(11) DEFAULT NULL,
`pkey` int(11) NOT NULL,
`c_xhsndb` double DEFAULT NULL,
PRIMARY KEY (`pkey`) /*T![clustered_index] CLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
INSERT INTO `t_dnmxh` VALUES (104,571000,NULL),(104,572000,44.37),(104,573000,59.91),(104,574000,91.5),(104,575000,9.53),(104,576000,92.4),(104,577000,47.96),(106,585000,NULL),(106,586000,NULL),(106,587000,NULL),(106,588000,NULL),(106,589000,NULL),(108,595000,13.35),(108,596000,13.51),(108,597000,47.51),(108,598000,NULL),(113,616000,24.73),(113,617000,NULL),(113,618000,92.6),(113,619000,NULL),(113,620000,91.65),(113,621000,100.46),(113,622000,31.3),(113,623000,63.81);
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';
count(1)
24
19 changes: 19 additions & 0 deletions cmd/explaintest/t/cte.test
Original file line number Diff line number Diff line change
Expand Up @@ -314,3 +314,22 @@ 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;
# case
CREATE TABLE `t_cqmg3b` (
`wkey` int(11) DEFAULT NULL,
`pkey` int(11) NOT NULL,
`c_anpf_c` int(11) DEFAULT NULL,
`c_b_fp_c` text DEFAULT NULL,
`c_ndccfb` int(11) DEFAULT NULL,
`c_8rswc` int(11) DEFAULT NULL,
PRIMARY KEY (`pkey`) /*T![clustered_index] CLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
INSERT INTO `t_cqmg3b` VALUES (102,556000,NULL,'vbwxgc',NULL,NULL),(102,557000,NULL,'bfblud',NULL,NULL),(102,558000,NULL,'c6drnb',NULL,NULL),(102,559000,NULL,'fo_ezc',NULL,NULL),(102,560000,NULL,'btdes',NULL,NULL),(102,561000,NULL,'gy6zc',NULL,NULL),(102,562000,NULL,'9cyx9c',NULL,NULL),(102,563000,NULL,NULL,NULL,NULL),(103,564000,NULL,NULL,NULL,NULL),(103,565000,NULL,NULL,NULL,NULL),(103,566000,NULL,NULL,NULL,NULL),(103,567000,NULL,NULL,NULL,NULL),(103,568000,NULL,NULL,NULL,NULL),(103,569000,NULL,NULL,NULL,NULL),(103,570000,NULL,NULL,NULL,NULL),(105,578000,NULL,'fmicvd',NULL,NULL),(105,579000,NULL,'_tflkc',NULL,NULL),(105,580000,NULL,'xhovz',NULL,NULL),(105,581000,NULL,'n5bak',NULL,NULL),(105,582000,NULL,'gszus',NULL,NULL),(105,583000,NULL,'ewvydd',NULL,NULL),(105,584000,NULL,'fbzr0d',NULL,NULL),(107,590000,NULL,'8kgdf',NULL,NULL),(107,591000,NULL,'28v4bc',NULL,NULL),(107,592000,NULL,'evujpb',NULL,NULL),(107,593000,NULL,'8nkbzd',NULL,NULL),(107,594000,NULL,NULL,NULL,NULL),(109,599000,NULL,'1zswm',NULL,NULL),(109,600000,NULL,'gxlzrc',NULL,NULL),(109,601000,NULL,'xmedjc',NULL,NULL),(110,602000,NULL,'jwym6',NULL,NULL),(110,603000,NULL,NULL,NULL,NULL),(110,604000,NULL,'pcckxd',NULL,NULL),(111,605000,NULL,'lhvvp',NULL,NULL),(111,606000,NULL,'5eyidd',NULL,NULL),(111,607000,NULL,'l8azic',NULL,NULL),(111,608000,NULL,'_lmxx',NULL,NULL),(112,609000,NULL,'cstovb',NULL,NULL),(112,610000,NULL,'9bcdjc',NULL,NULL),(112,611000,NULL,'7zofhc',NULL,NULL),(112,612000,NULL,'pe2a3',NULL,NULL),(112,613000,NULL,'xtoet',NULL,NULL),(112,614000,NULL,'unvnj',NULL,NULL),(112,615000,NULL,'fj4v1b',NULL,NULL);
CREATE TABLE `t_dnmxh` (
`wkey` int(11) DEFAULT NULL,
`pkey` int(11) NOT NULL,
`c_xhsndb` double DEFAULT NULL,
PRIMARY KEY (`pkey`) /*T![clustered_index] CLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
INSERT INTO `t_dnmxh` VALUES (104,571000,NULL),(104,572000,44.37),(104,573000,59.91),(104,574000,91.5),(104,575000,9.53),(104,576000,92.4),(104,577000,47.96),(106,585000,NULL),(106,586000,NULL),(106,587000,NULL),(106,588000,NULL),(106,589000,NULL),(108,595000,13.35),(108,596000,13.51),(108,597000,47.51),(108,598000,NULL),(113,616000,24.73),(113,617000,NULL),(113,618000,92.6),(113,619000,NULL),(113,620000,91.65),(113,621000,100.46),(113,622000,31.3),(113,623000,63.81);
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';
18 changes: 10 additions & 8 deletions planner/core/logical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -4881,12 +4881,12 @@ func (b *PlanBuilder) buildProjUponView(ctx context.Context, dbName model.CIStr,
// every row from outerPlan and the whole innerPlan.
func (b *PlanBuilder) buildApplyWithJoinType(outerPlan, innerPlan LogicalPlan, tp JoinType) LogicalPlan {
b.optFlag = b.optFlag | flagPredicatePushDown | flagBuildKeyInfo | flagDecorrelate
setIsInApplyForCTE(innerPlan)
ap := LogicalApply{LogicalJoin: LogicalJoin{JoinType: tp}}.Init(b.ctx, b.getSelectOffset())
ap.SetChildren(outerPlan, innerPlan)
ap.names = make([]*types.FieldName, outerPlan.Schema().Len()+innerPlan.Schema().Len())
copy(ap.names, outerPlan.OutputNames())
ap.SetSchema(expression.MergeSchema(outerPlan.Schema(), innerPlan.Schema()))
setIsInApplyForCTE(innerPlan, ap.Schema())
// Note that, tp can only be LeftOuterJoin or InnerJoin, so we don't consider other outer joins.
if tp == LeftOuterJoin {
b.optFlag = b.optFlag | flagEliminateOuterJoin
Expand All @@ -4907,27 +4907,29 @@ func (b *PlanBuilder) buildSemiApply(outerPlan, innerPlan LogicalPlan, condition
return nil, err
}

setIsInApplyForCTE(innerPlan)
setIsInApplyForCTE(innerPlan, join.Schema())
ap := &LogicalApply{LogicalJoin: *join}
ap.tp = plancodec.TypeApply
ap.self = ap
return ap, nil
}

// setIsInApplyForCTE indicates CTE is the in inner side of Apply,
// setIsInApplyForCTE indicates CTE is the in inner side of Apply and correlate.
// the storage of cte needs to be reset for each outer row.
// It's better to handle this in CTEExec.Close(), but cte storage is closed when SQL is finished.
func setIsInApplyForCTE(p LogicalPlan) {
func setIsInApplyForCTE(p LogicalPlan, apSchema *expression.Schema) {
switch x := p.(type) {
case *LogicalCTE:
x.cte.IsInApply = true
setIsInApplyForCTE(x.cte.seedPartLogicalPlan)
if len(extractCorColumnsBySchema4LogicalPlan(p, apSchema)) > 0 {
x.cte.IsInApply = true
}
setIsInApplyForCTE(x.cte.seedPartLogicalPlan, apSchema)
if x.cte.recursivePartLogicalPlan != nil {
setIsInApplyForCTE(x.cte.recursivePartLogicalPlan)
setIsInApplyForCTE(x.cte.recursivePartLogicalPlan, apSchema)
}
default:
for _, child := range p.Children() {
setIsInApplyForCTE(child)
setIsInApplyForCTE(child, apSchema)
}
}
}
Expand Down