morrySnow commented on code in PR #67878:
URL: https://github.com/apache/doris/pull/67878#discussion_r4034599975


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java:
##########
@@ -1205,9 +1205,63 @@ public static boolean isInjective(Expression expression) 
{
         return expression instanceof Slot;
     }
 
-    // if the input is unique, the output of agg is unique, too
+    private static boolean isInjectiveAggArgument(Expression expression) {
+        if (expression instanceof Slot) {
+            return true;
+        }
+        if (!(expression instanceof Cast)) {
+            return false;
+        }
+        Cast cast = (Cast) expression;
+        DataType source = cast.child().getDataType();
+        DataType target = cast.getDataType();
+        // Bounded character casts may truncate to the declared length. Treat 
every non-identity
+        // conversion to CHAR/VARCHAR conservatively, including 
analyzer-generated casts.
+        return (source.equals(target) || (!target.isCharType() && 
!target.isVarcharType()))
+                && !Cast.castNullable(false, source, target)
+                && isInjectiveTypeConversion(source, target)
+                && isInjectiveAggArgument(cast.child());
+    }
+
+    /**
+     * Whether an aggregate preserves uniqueness for a group containing 
exactly one row.
+     *
+     * <p>Checking the aggregate kind and its input slots is not sufficient. 
An aggregate argument
+     * may contain a non-injective expression, and the aggregate return type 
may also collapse
+     * distinct argument values. Prove injectivity through both the argument 
expression and the
+     * one-row argument-to-result type conversion.
+     */
     public static boolean isInjectiveAgg(Expression agg) {
-        return agg instanceof Sum || agg instanceof Avg || agg instanceof Max 
|| agg instanceof Min;
+        if (!(agg instanceof Sum || agg instanceof Avg || agg instanceof Max 
|| agg instanceof Min)) {
+            return false;
+        }
+        Expression argument = agg.child(0);
+        return isInjectiveAggArgument(argument)
+                && isInjectiveTypeConversion(argument.getDataType(), 
agg.getDataType());
+    }
+
+    /**
+     * Whether a type conversion preserves every source value. Data types 
provide the general
+     * proof; the floating-point cases below supplement it with the exact 
integer ranges of IEEE
+     * 754 binary32 and binary64.
+     */
+    private static boolean isInjectiveTypeConversion(DataType source, DataType 
target) {
+        if (source.isInjectiveCastTo(target)) {
+            return true;
+        }
+        if (source.isIntegralType()) {

Review Comment:
   decimalv2 is deperated



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