Skip to content

Commit

Permalink
planner: reopen CTE in apply only when correlate (#38214) (#45066)
Browse files Browse the repository at this point in the history
ref #38214
  • Loading branch information
winoros committed Jun 30, 2023
1 parent ae39052 commit 54a8c45
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 8 deletions.
20 changes: 20 additions & 0 deletions cmd/explaintest/r/cte.result
Original file line number Diff line number Diff line change
Expand Up @@ -800,3 +800,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

0 comments on commit 54a8c45

Please sign in to comment.