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


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/UnCorrelatedApplyAggregateFilter.java:
##########
@@ -117,7 +117,8 @@ public List<Rule> buildRules() {
                 
PlanUtils.filterOrSelf(ImmutableSet.copyOf(unCorrelatedPredicate), 
filter.child()));
         return new LogicalApply<>(apply.getCorrelationSlot(), 
apply.getSubqueryType(), apply.isNot(),
                 apply.getCompareExpr(), apply.getTypeCoercionExpr(),
-                ExpressionUtils.optionalAnd(correlatedPredicate), 
apply.getMarkJoinSlotReference(),
+                
ExpressionUtils.mergeCorrelationFilter(apply.getCorrelationFilter(), 
correlatedPredicate),

Review Comment:
   [P1] Do not split aggregate groups for non-equality correlations
   
   For `L.x=2` and `R={(r1=1,g=0),(r1=2,g=0)}`, `EXISTS (SELECT g FROM R WHERE 
r1 <= L.x GROUP BY g HAVING count(*) = L.x)` is true: both rows form one `g=0` 
group with count 2. This rule adds `r1` to the group keys while pulling up `r1 
<= x`; after this merge preserves the earlier HAVING, the right side instead 
has two count-1 groups, so neither satisfies `count_slot = x` and EXISTS 
becomes false. `getUnCorrelatedExprs` accepts this inequality and EXISTS has no 
rejection or later re-aggregation. Please preserve the correlation below the 
aggregate, or reject non-equality cases where the added inner expression is not 
functionally fixed, and add this count-based oracle.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java:
##########
@@ -227,6 +227,27 @@ public static Optional<Expression> 
optionalAnd(Collection<Expression> collection
         return optionalAnd(ImmutableList.copyOf(collection));
     }
 
+    /**
+     * Merge newly extracted correlated predicates into an existing 
correlation filter of an
+     * apply. the same apply can be rewritten multiple times (e.g. two nested 
correlated
+     * filters), and each rule application pulls a new correlated predicate 
into the apply.
+     * the existing correlation filter must be kept and AND-ed with the new 
predicates,
+     * otherwise the previously extracted predicates are silently dropped and 
never appear in
+     * the final join condition.
+     *
+     * @param existingCorrelationFilter the correlation filter accumulated on 
the apply
+     * @param correlatedPredicates the newly extracted correlated predicates
+     * @return the merged correlation filter
+     */
+    public static Optional<Expression> mergeCorrelationFilter(
+            Optional<Expression> existingCorrelationFilter, List<Expression> 
correlatedPredicates) {
+        List<Expression> allCorrelatedPredicates = new ArrayList<>();
+        existingCorrelationFilter.ifPresent(filter -> 
allCorrelatedPredicates.addAll(
+                ExpressionUtils.extractConjunction(filter)));
+        allCorrelatedPredicates.addAll(correlatedPredicates);

Review Comment:
   [P2] Preserve the WHERE/HAVING evaluation boundary for sensitive predicates
   
   When an EXISTS subquery has a correlated HAVING above a correlated WHERE, 
this merge moves both predicates into the post-aggregate join domain. For 
example, with `L={(5)}` and `R={(2,0)}`, `WHERE r1 > l.x GROUP BY r1,r2 HAVING 
assert_true(r2 = l.x, 'boom')` should produce no group and no error. After 
decorrelation the right side first creates the `(2,0)` group, and the NLJ 
evaluates `assert_true(0 = 5, 'boom')` on that candidate even though the 
original WHERE removed the row. `AssertTrue` is a `NoneMovableFunction`, so 
this changes observable semantics; reordering the conjuncts is insufficient 
because each NLJ expression is evaluated over the candidate block before 
masking. Please preserve the original stage for sensitive HAVING predicates (or 
reject this shape) and add the empty-after-WHERE oracle.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Rewriter.java:
##########
@@ -467,6 +467,15 @@ public class Rewriter extends AbstractBatchJobExecutor {
                     ),
                     // query rewrite support window, so add this rule here
                     custom(RuleType.AGG_SCALAR_SUBQUERY_TO_WINDOW_FUNCTION, 
AggScalarSubQueryToWindowFunction::new),
+                    // the analyzer may create redundant passthrough projects 
around the aggregate
+                    // (e.g. the group-by normalization projects of `GROUP 
BY`), which block
+                    // UnCorrelatedApplyAggregateFilter /
+                    // PullUpCorrelatedFilterUnderApplyAggregateProject
+                    // (they need Apply(Aggregate(Filter)) to pull up the 
correlated predicate under
+                    // the aggregate). eliminate them before unnesting so that 
the correlated predicate
+                    // under the aggregate is extracted into the apply's 
correlationFilter instead of
+                    // being silently dropped after apply-to-join.
+                    custom(RuleType.ELIMINATE_UNNECESSARY_PROJECT, 
EliminateUnnecessaryProject::new),

Review Comment:
   [P2] Do not make this correctness fix disableable
   
   `CustomRewriteJob` skips this pass when `disable_nereids_rules` contains 
`ELIMINATE_UNNECESSARY_PROJECT`, which is an accepted non-privilege RuleType. 
The analyzer project then remains in the new `qt_sql22` shape; as the comment 
above notes, it blocks extraction of `r.r1 = l.x`, and apply-to-join silently 
loses that predicate, returning TRUE where the oracle expects FALSE. Please 
make the required wrapper handling part of the correlated-apply correctness 
rewrite rather than a separately disableable generic cleanup, and add the same 
oracle with this rule disabled.



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