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


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/implementation/AggregateStrategies.java:
##########
@@ -809,6 +780,33 @@ private LogicalAggregate<? extends Plan> 
storageLayerAggregate(
         }
     }
 
+    private boolean isSupportedStorageLayerAggregateArgument(
+            AggregateFunction aggregateFunction, Expression argument) {
+        if (argument instanceof SlotReference) {
+            return true;
+        }
+        if (!isNullPreservingCastOverSlot(argument)) {

Review Comment:
   [P1] Reject nested casts that can still fail
   
   With strict casting this admitted plan is not equivalent:
   ```text
   LogicalAggregate(count(CAST(a AS ARRAY<INT>)))
     LogicalOlapScan(a ARRAY<STRING> NOT NULL; row ['bad'])
   ```
   `Cast.castNullable(false, ARRAY<STRING>, ARRAY<INT>)` returns false because 
it does not recurse, so this COUNT branch accepts the cast. Normal BE array 
casting propagates the nested string-to-int error (and TRY_CAST can produce a 
top-level NULL). After storage COUNT, OLAP/FileScannerV2 counts `a` and emits 
empty/default arrays, so the upper cast succeeds and returns the source count 
instead of the required error/zero. Please reject complex casts unless nested 
conversions are recursively proven null- and error-preserving, and cover 
direct/projected runtime paths.



##########
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/PhysicalStorageLayerAggregateTest.java:
##########
@@ -402,6 +438,122 @@ public void 
testCountOnIndexRejectsIsNullOnProjectedCountSlot() {
                 
.matches(logicalAggregate(logicalProject(logicalFilter(logicalOlapScan()))));
     }
 
+    @Test
+    public void testCastThatMayProduceNullDoesNotUseStorageLayerAggregate() {
+        LogicalOlapScan olapScan = PlanConstructor.newLogicalOlapScan(2, 
"cast_aggregate", 0);
+        Cast cast = new Cast(olapScan.getOutput().get(0), 
TinyIntType.INSTANCE);
+        TryCast tryCast = new TryCast(olapScan.getOutput().get(0), 
TinyIntType.INSTANCE);
+        Cast stringCast = new Cast(olapScan.getOutput().get(1), 
TinyIntType.INSTANCE);
+        TryCast stringTryCast = new TryCast(olapScan.getOutput().get(1), 
TinyIntType.INSTANCE);
+        List<AggregateFunction> castAggregates = ImmutableList.of(
+                new Count(cast), new Count(tryCast), new Min(cast), new 
Max(tryCast),
+                new Count(stringCast), new Count(stringTryCast));
+
+        for (AggregateFunction function : castAggregates) {
+            LogicalAggregate<LogicalOlapScan> aggregate = new 
LogicalAggregate<>(
+                    Collections.emptyList(), ImmutableList.of(new 
Alias(function, "aggregate")),
+                    true, Optional.empty(), olapScan);

Review Comment:
   [P2] Assert that the physical alternative is absent
   
   `applyImplementation` copies a transformed alternative into the memo without 
removing the original logical expression, and `matches(...)` searches both 
logical and physical alternatives. This assertion therefore succeeds even if 
the rule incorrectly adds `PhysicalStorageLayerAggregate`. The same issue 
occurs in the negative checks around current lines 516 and 534. Please use 
`nonMatch(physicalStorageLayerAggregate())` (as the file-scan negative case 
does), optionally retaining the logical-shape match as a separate assertion.



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