seawinde commented on code in PR #67172:
URL: https://github.com/apache/doris/pull/67172#discussion_r3885199212


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/AbstractMaterializedViewRule.java:
##########
@@ -471,6 +470,58 @@ protected List<Plan> doRewrite(StructInfo queryStructInfo, 
CascadesContext casca
         return rewriteResults;
     }
 
+    // Partition compensation only supports one global limit/topN in each 
plan. When this invariant
+    // is not met, return null so the caller skips the rewrite instead of 
changing query semantics.
+    Plan buildPartitionCompensationPlan(Plan rewrittenPlan, Plan 
baseTablePlan, Plan queryPlan) {
+        List<Plan> queryGlobalLimits = queryPlan.collectToList(node -> 
isGlobalLimitOrTopN((Plan) node));
+        List<Plan> rewrittenGlobalLimits = rewrittenPlan.collectToList(
+                node -> isGlobalLimitOrTopN((Plan) node));
+        List<Plan> baseTableGlobalLimits = baseTablePlan.collectToList(
+                node -> isGlobalLimitOrTopN((Plan) node));
+        if (queryGlobalLimits.isEmpty()) {
+            return rewrittenGlobalLimits.isEmpty() && 
baseTableGlobalLimits.isEmpty()
+                    ? buildCompensationUnion(queryPlan, 
Lists.newArrayList(rewrittenPlan, baseTablePlan)) : null;
+        }
+        if (queryGlobalLimits.size() != 1
+                || rewrittenGlobalLimits.size() != 1 || 
baseTableGlobalLimits.size() != 1) {
+            return null;
+        }
+        Plan queryGlobalLimit = queryGlobalLimits.get(0);
+        Plan rewrittenGlobalLimit = rewrittenGlobalLimits.get(0);
+        Plan baseTableGlobalLimit = baseTableGlobalLimits.get(0);
+        // Rewriting can change the limit value and order-key expressions, but 
preserves the outer
+        // operator kind. The offset must still match because it cannot be 
safely adjusted after UNION.
+        if (rewrittenGlobalLimit.getType() != queryGlobalLimit.getType()
+                || baseTableGlobalLimit.getType() != queryGlobalLimit.getType()
+                || getOffset(rewrittenGlobalLimit) != 
getOffset(queryGlobalLimit)
+                || getOffset(baseTableGlobalLimit) != 
getOffset(queryGlobalLimit)) {
+            return null;
+        }
+        Plan compensationUnion = 
buildCompensationUnion(queryGlobalLimit.child(0), Lists.newArrayList(

Review Comment:
   已按该 P1 建议修复,提交 d891c1f2309。partition compensation 现在要求三棵 plan 的唯一 Global 
Limit/TopN 都位于根节点;query、MV、base 任一存在外层 Project 或其他非根形态时直接放弃 rewrite,避免 UNION 按 
ordinal 合并不同语义的表达式。新增回归 partition_compensation_project_mv,验证 stale partition 下 
MV 不被选择、无 VUNION,且 rewrite 开关前后结果一致。提交 90f81c138d3。



-- 
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]

Reply via email to