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


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PushDownTopNDistinctThroughJoin.java:
##########
@@ -197,6 +200,33 @@ private List<OrderKey> getPushedOrderKeys(Set<Slot> 
groupBySlots, Set<Slot> join
                 notFound = true;
             }
         }
-        return pushedOrderKeys.build();
+        List<OrderKey> pushedOrderKeyList = pushedOrderKeys.build();
+        if (pushedOrderKeyList.size() == orderKeys.size()
+                || isOrderKeyPrefixUniqueAfterDistinct(joinChild, 
pushedOrderKeyList)) {
+            return pushedOrderKeyList;
+        }
+        return ImmutableList.of();
+    }
+
+    /**
+     * A partial order-key prefix is safe for a hard limit only when it 
uniquely orders the rows produced by
+     * {@link PlanUtils#distinct(Plan)}. This is true when a leading part of 
the prefix either is already a
+     * non-null unique key, covers every child output, or functionally 
determines every remaining child output.
+     */
+    private boolean isOrderKeyPrefixUniqueAfterDistinct(Plan joinChild, 
List<OrderKey> orderKeyPrefix) {
+        if (orderKeyPrefix.isEmpty()) {
+            return false;
+        }
+        Set<Slot> childOutput = joinChild.getOutputSet();
+        Set<Slot> prefixSlots = new HashSet<>();
+        for (OrderKey orderKey : orderKeyPrefix) {
+            prefixSlots.add((Slot) orderKey.getExpr());
+        }
+        if (prefixSlots.containsAll(childOutput)) {
+            return true;
+        }
+        DataTrait childTrait = joinChild.getLogicalProperties().getTrait();
+        return childTrait.isUniqueAndNotNull(prefixSlots)
+                || childTrait.isDependent(prefixSlots, childOutput);

Review Comment:
   [P2] Preserve augmented FDs across trait pruning
   
   Ordered inner-limit normalization can leave this reachable child shape:
   
   ```text
   Project(a, c, g(b,c) AS d)
     TopN(order by b, inner limit > 1)
       Project(a, f(a) AS b, c)
         Scan
   ```
   
   This is produced from `Project -> Limit -> Sort -> Project`: the early 
project/limit pushdown and `LimitSortToTopN` form `Project -> TopN -> Project`, 
and no pre-target rule merges across that TopN. The lower project records `a -> 
b` and the upper records `{b,c} -> d`, so `{a,c}` determines the full output 
and is a safe prefix. But when the upper project drops `b`, 
`Plan.computeDataTrait` calls `removeNotContain({a,c,d})`; its 
`findValidFuncDeps` traversal cannot activate the separate `{b,c}` determinant 
after deriving `b`, and the rebuilt trait loses `{a,c} -> d`. This call 
therefore returns false and rejects the safe pushdown this PR intends to 
preserve. This differs from the earlier augmentation thread, where all 
intermediate FD nodes remained present. Please make FD pruning 
closure/augmentation-aware and cover both the direct prune and this `Project -> 
TopN -> Project` plan case.



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