yujun777 commented on code in PR #68861:
URL: https://github.com/apache/doris/pull/68861#discussion_r4270461209


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/AbstractMaterializedViewAggregateRule.java:
##########
@@ -588,6 +610,16 @@ private boolean isGroupByEquals(Pair<Plan, 
LogicalAggregate<Plan>> queryTopPlanA
         LogicalAggregate<Plan> queryAggregate = queryTopPlanAndAggPair.value();
         LogicalAggregate<Plan> viewAggregate = viewTopPlanAndAggPair.value();
 
+        // If the query is a scalar aggregate but the view groups by extra 
dimensions, the dimensions
+        // removed by the uniform function dependency below only guarantee at 
most one group, not that a
+        // group exists. Eliminating the aggregate into a bare project would 
lose the single row a scalar
+        // aggregate must always emit when the filter matches zero rows. Keep 
the aggregate by rejecting
+        // this fast path and falling back to the roll up rewrite.
+        if (queryAggregate.getGroupByExpressions().isEmpty()
+                && !viewAggregate.getGroupByExpressions().isEmpty()) {

Review Comment:
   Confirmed, and it is this PR that makes the case reachable. Reproduced with 
`set enable_sql_cache=false`
   (the session default is on, which is why my first pass over these queries 
showed no difference): on this
   branch `select count(*) from base where k = 9999 having count(*) > 0` against
   `select k, count(*) cnt from base group by k having count(*) > 0` returned a 
row of `0` with the rewrite
   on, while the same query with `enable_materialized_view_rewrite=false` 
returned no row. A build without
   the guard of this PR returns no row for every one of the combinations below, 
so the guard is what lets
   the query reach the roll up.
   
   The predicate is lost in the compensation, not in `aggregateRewriteByView`: 
the view's own residual
   `cnt > 0`, mapped back onto query slots, is the query's `count(*) > 0`, so
   `Predicates.compensatePredicates` dropped it as exactly covered by the view 
(and
   `removePredicatesImpliedByViewResidual` would have dropped it as implied as 
well), both of which run
   before `rejectUnsafeResidualCompensation` gets to look at it. The rewritten 
plan then had no filter
   above the rolled up aggregate, and `SUM0` over the empty row set is `0`, 
which is a row.
   
   Fixed in `Predicates`: a candidate which constrains an aggregate or a window 
output is no longer pruned
   as redundant because the view states the same condition. The view enforced 
it over the value the view
   aggregated, while the query needs it over the value its own aggregate 
produces from the view rows, and
   the roll up changes that value. Such a predicate now stays in the 
compensation, where the existing
   `rejectUnsafeResidualCompensation` check sees it and refuses the rewrite.
   
   Validation, with `enable_sql_cache=false`, comparing rewrite on against
   `enable_materialized_view_rewrite=false` for `k in {1, 9999}` and `having 
count(*) > {0, 5, 19, 20, 21,
   100000}`: all 12 answers are identical, including the reported one. A view 
which has a `HAVING` above
   its aggregate is now refused for these queries the same way it already is 
for every other query against
   it, so the coverage cost is limited to a scalar query repeating an aggregate 
mv's own `HAVING`.
   
   Regression: `agg_scalar_empty_input` now creates `scalar_agg_having_mv`
   (`select k, count(*) as cnt from ... group by k having count(*) > 0`) and 
asserts
   `async_mv_rewrite_fail` / `mv_rewrite_fail` for both the matched and the 
empty-input query, together with
   the rewrite-off / rewrite-on result pairs which pin the empty result. The 
case where the mv has no
   `HAVING` of its own and the query `HAVING` stays above the roll up (`having 
count(*) > 100000`) still
   picks the mv and is unchanged.
   



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