seawinde commented on code in PR #67172:
URL: https://github.com/apache/doris/pull/67172#discussion_r3885197928
##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/AbstractMaterializedViewRule.java:
##########
@@ -471,6 +470,49 @@ protected List<Plan> doRewrite(StructInfo queryStructInfo,
CascadesContext casca
return rewriteResults;
}
+ Plan buildPartitionCompensationPlan(Plan rewrittenPlan, Plan
baseTablePlan, Plan queryPlan) {
+ Plan queryGlobalLimit = queryPlan.<Plan>collectFirst(
+ node -> isGlobalLimitOrTopN((Plan) node)).orElse(null);
+ if (queryGlobalLimit == null) {
+ return buildCompensationUnion(queryPlan,
Lists.newArrayList(rewrittenPlan, baseTablePlan));
+ }
+ Plan rewrittenGlobalLimit = rewrittenPlan.<Plan>collectFirst(
+ node -> isSameGlobalLimitOrTopN((Plan) node,
queryGlobalLimit)).orElse(null);
+ Plan baseTableGlobalLimit = baseTablePlan.<Plan>collectFirst(
+ node -> isSameGlobalLimitOrTopN((Plan) node,
queryGlobalLimit)).orElse(null);
+ if (rewrittenGlobalLimit == null || baseTableGlobalLimit == null
+ || getOffset(rewrittenGlobalLimit) !=
getOffset(queryGlobalLimit)) {
+ return null;
+ }
+ Plan compensationUnion =
buildCompensationUnion(queryGlobalLimit.child(0), Lists.newArrayList(
+ rewrittenGlobalLimit.child(0), baseTableGlobalLimit.child(0)));
+ return queryPlan.rewriteDownShortCircuit(plan -> plan ==
queryGlobalLimit
+ ? queryGlobalLimit.withChildren(compensationUnion) : plan);
+ }
+
+ private boolean isGlobalLimitOrTopN(Plan plan) {
+ return plan instanceof LogicalTopN
+ || plan instanceof LogicalLimit && ((LogicalLimit<?>)
plan).getPhase() == LimitPhase.GLOBAL;
+ }
+
+ private boolean isSameGlobalLimitOrTopN(Plan plan, Plan queryGlobalLimit) {
+ return plan.getType() == queryGlobalLimit.getType() &&
isGlobalLimitOrTopN(plan);
+ }
Review Comment:
已完成最终修复。现在 query、rewritten、base-table 三棵 plan 都会收集全部 Global
Limit/TopN,要求各自恰好一个且类型、offset 一致;多个、缺失或不匹配时直接放弃 partition compensation
rewrite。相关边界单测已补齐(包括 multiple/mixed/unexpected global operators)。
##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/AbstractMaterializedViewRule.java:
##########
@@ -471,6 +470,49 @@ protected List<Plan> doRewrite(StructInfo queryStructInfo,
CascadesContext casca
return rewriteResults;
}
+ Plan buildPartitionCompensationPlan(Plan rewrittenPlan, Plan
baseTablePlan, Plan queryPlan) {
+ Plan queryGlobalLimit = queryPlan.<Plan>collectFirst(
+ node -> isGlobalLimitOrTopN((Plan) node)).orElse(null);
+ if (queryGlobalLimit == null) {
+ return buildCompensationUnion(queryPlan,
Lists.newArrayList(rewrittenPlan, baseTablePlan));
+ }
+ Plan rewrittenGlobalLimit = rewrittenPlan.<Plan>collectFirst(
+ node -> isSameGlobalLimitOrTopN((Plan) node,
queryGlobalLimit)).orElse(null);
+ Plan baseTableGlobalLimit = baseTablePlan.<Plan>collectFirst(
+ node -> isSameGlobalLimitOrTopN((Plan) node,
queryGlobalLimit)).orElse(null);
+ if (rewrittenGlobalLimit == null || baseTableGlobalLimit == null
+ || getOffset(rewrittenGlobalLimit) !=
getOffset(queryGlobalLimit)) {
+ return null;
Review Comment:
已完成最终修复并补充注释。支持前提现在明确为:每棵 plan 唯一 Global Limit/TopN、算子类型一致、offset
一致,且该算子必须是根节点;前提不满足时返回 null,保守跳过 rewrite。外层 Project 场景另有单测和回归覆盖。
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]