github-actions[bot] commented on code in PR #65393:
URL: https://github.com/apache/doris/pull/65393#discussion_r3664570705


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/PartitionIncrementMaintainer.java:
##########
@@ -444,6 +451,20 @@ public Void visitLogicalWindow(LogicalWindow<? extends 
Plan> window, PartitionIn
             return super.visitLogicalWindow(window, context);
         }
 
+        @Override
+        public Void visitLogicalPartitionTopN(LogicalPartitionTopN<? extends 
Plan> partitionTopN,
+                PartitionIncrementCheckContext context) {
+            if (!planOutputContainsPartitionColumnToCheck(partitionTopN, 
context)) {

Review Comment:
   [P1] Keep global Limit/TopN out of partition-local maintenance
   
   A reachable rewritten plan is:
   ```
   Limit(1)
     Window(row_number() OVER (PARTITION BY p ORDER BY x))
       PartitionTopN(keys=[p], hasGlobalLimit=true, limit=1)
         Scan(p, x)
   ```
   `PushDownLimit`/`PushDownTopNThroughWindow` leave the global operator above 
the Window and set `hasGlobalLimit=true` on the inserted node. This visitor 
only checks `keys=[p]`, so the PR now classifies the plan as PCT-capable; 
previously the unsupported PartitionTopN stopped it. If only source partition A 
is refreshed, the global limit is evaluated on A's restricted input while a 
previously selected row in MV partition B is not removed, so the MV can contain 
rows beyond the global result. Please reject `hasGlobalLimit=true` unless the 
global operation is proven partition-local, and add a refresh test where the 
global winner moves between MV partitions.



##########
regression-test/suites/nereids_rules_p0/mv/increment_create/cross_join_range_date_increment_create.groovy:
##########
@@ -336,12 +336,12 @@ suite("cross_join_range_date_increment_create", 
"increment_create") {
 
     def sql_all_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7, 
mv_sql_8, mv_sql_9, mv_sql_10, mv_sql_11, mv_sql_12,
                         mv_sql_13, mv_sql_14, mv_sql_15, mv_sql_16, mv_sql_17, 
mv_sql_18]
-    def sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, mv_sql_7]
+    def sql_increment_list = [mv_sql_1, mv_sql_3, mv_sql_4, mv_sql_6, 
mv_sql_7, mv_sql_13]

Review Comment:
   [P2] Make the newly accepted refresh change the query result
   
   `list_judgement` keeps the base tables between SQL cases and calls the same 
`primary_tb_change` insert each time. By the time the newly accepted 
`mv_sql_13` runs, that exact row has already been inserted by five earlier 
accepted cases; this query groups every referenced key before evaluating its 
windows, so one more duplicate produces the same source result. The right-table 
pass repeats a grouped-away row too. This comparison can therefore pass without 
exercising whether the newly supported nested-window refresh maintains a 
result-changing update. Please reset/isolate state per case or use a fresh 
group key, assert that the source result changed, then refresh and compare; the 
other moved classification lists need the same treatment.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/PartitionIncrementMaintainer.java:
##########
@@ -476,25 +498,46 @@ private boolean checkWindowPartition(Expression 
expression, PartitionIncrementCh
                     expression.collectToList(expressionTreeNode -> 
expressionTreeNode instanceof WindowExpression);
             for (Object windowExpressionObj : windowExpressions) {
                 WindowExpression windowExpression = (WindowExpression) 
windowExpressionObj;
-                List<Expression> partitionKeys = 
windowExpression.getPartitionKeys();
-                Set<Column> originalPartitionbyExprSet = new HashSet<>();
-                partitionKeys.forEach(groupExpr -> {
-                    if (groupExpr instanceof SlotReference && 
groupExpr.isColumnFromTable()) {
-                        originalPartitionbyExprSet.add(((SlotReference) 
groupExpr).getOriginalColumn().get());
-                    }
-                });
-                Set<SlotReference> contextPartitionColumnSet = 
getPartitionColumnsToCheck(context);
-                if (contextPartitionColumnSet.isEmpty()) {
-                    return false;
-                }
-                if (contextPartitionColumnSet.stream().noneMatch(
-                        partition -> 
originalPartitionbyExprSet.contains(partition.getOriginalColumn().get()))) {
+                if 
(!checkPartitionKeysContainPartitionToCheck(windowExpression.getPartitionKeys(),
 context)) {
                     return false;
                 }
             }
             return true;
         }
 
+        private boolean 
checkPartitionKeysContainPartitionToCheck(List<Expression> partitionKeys,
+                PartitionIncrementCheckContext context) {
+            // Match partition keys by slot identity (exprId) instead of the 
bare catalog Column,
+            // because Column.equals compares column attributes but not the 
owning table: an unrelated
+            // input column with the same definition (e.g. l.p vs r.p) would 
otherwise be accepted as
+            // the tracked partition key. The context already carries every 
slot equal to the MV
+            // partition column via join equal-set propagation, so a 
slot-level containment check keeps
+            // genuinely unrelated partition keys (no equality to the tracked 
column) rejected.
+            Set<SlotReference> partitionKeySlotSet = new HashSet<>();
+            partitionKeys.forEach(partitionKey -> {
+                if (partitionKey instanceof SlotReference && 
partitionKey.isColumnFromTable()) {
+                    partitionKeySlotSet.add((SlotReference) partitionKey);
+                }
+            });
+            Set<SlotReference> contextPartitionColumnSet = 
getPartitionColumnsToCheck(context);
+            if (contextPartitionColumnSet.isEmpty()) {
+                return false;
+            }
+            return 
contextPartitionColumnSet.stream().anyMatch(partitionKeySlotSet::contains);

Review Comment:
   [P2] Resolve proven equal slots before comparing ExprIds
   
   A reduced safe plan is:
   ```
   Project(l.p#1, w#5)
     Window(w OVER (PARTITION BY r.p#3))
       InnerJoin(l.p#1 = r.p#3)
         Scan l
         Scan r
   ```
   `visitLogicalWindow` calls this helper before descending into the join, so 
the context still contains only `l.p#1`; `visitLogicalJoin` would add `r.p#3` 
later. Exact containment therefore rejects this partition-local window. The 
same regression occurs for a forwarding `p#1 AS p_alias#2`, whose equality is 
already recorded by `LogicalProject.computeEqualSet` but whose ExprId differs. 
This is the inverse of the existing unrelated-same-schema thread: here equality 
is proven. Please expand lineage/equality classes from the child logical 
properties before matching, while retaining distinct scan identities, and add 
positive alias and inner-join-equality cases.



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