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


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/AddProjectForVolatileExpression.java:
##########
@@ -269,6 +271,85 @@ public <T extends Expression> Optional<Pair<List<T>, 
LogicalProject<Plan>>> rewr
         return Optional.of(Pair.of(newTargetsBuilder.build(), new 
LogicalProject<>(projects, plan.child(0))));
     }
 
+    private Optional<JoinRewriteResult> 
rewriteJoinExpressions(LogicalJoin<Plan, Plan> join,
+            Collection<Expression> targets) {
+        Map<Expression, Integer> volatileExpressionCounter = 
Maps.newLinkedHashMap();
+        Map<Expression, Set<Slot>> volatileExpressionSlots = 
Maps.newLinkedHashMap();
+        for (Expression target : targets) {
+            target.foreach(e -> {
+                Expression expr = (Expression) e;
+                if (expr.isVolatile()) {
+                    volatileExpressionCounter.merge(expr, 1, Integer::sum);
+                    Set<Slot> inputSlots = expr.getInputSlots();
+                    volatileExpressionSlots
+                            .computeIfAbsent(expr, ignored -> 
Sets.newLinkedHashSet())
+                            .addAll(inputSlots.isEmpty() ? 
target.getInputSlots() : inputSlots);
+                }
+            });
+        }
+
+        ImmutableList.Builder<NamedExpression> leftAliases = 
ImmutableList.builder();
+        ImmutableList.Builder<NamedExpression> rightAliases = 
ImmutableList.builder();
+        Map<Expression, Slot> replaceMap = Maps.newHashMap();
+        Set<Slot> leftOutputSet = join.left().getOutputSet();
+        Set<Slot> rightOutputSet = join.right().getOutputSet();
+        for (Entry<Expression, Integer> entry : 
volatileExpressionCounter.entrySet()) {
+            if (entry.getValue() <= 1) {
+                continue;

Review Comment:
   This guard still lets an empty-slot volatile expression be projected into 
one child when the containing join conjunct references both sides. For example, 
after BETWEEN expansion, `t1.id + rand() between t2.id and t2.id + 1` 
contributes the same `rand()` node twice; `volatileInputSlots` is empty, while 
`inputSlots` collected from the containing targets includes both left and right 
slots. The current guard does not skip that case, then the side selection below 
falls through to `leftAliases`, so `rand()` is evaluated once per left row and 
reused for every matching right row. The original ON predicate evaluates it per 
joined pair, so with one left row matching two right rows the original can keep 
one pair and reject the other, while the rewritten plan can only keep both or 
neither. Please also skip slot-free volatile expressions when the collected 
containing `inputSlots` are not fully covered by either child, or otherwise 
keep them in the join without child projection. This is distinc
 t from the existing direct ON-pushdown comments because it is introduced by 
the new repeated-volatile materialization path after the volatile expression 
has been selected for aliasing.



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