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


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/SearchSignatureForRound.java:
##########
@@ -18,26 +18,86 @@
 package org.apache.doris.nereids.trees.expressions.functions;
 
 import org.apache.doris.catalog.FunctionSignature;
+import org.apache.doris.nereids.CascadesContext;
+import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
+import org.apache.doris.nereids.rules.expression.rules.FoldConstantRuleOnFE;
+import org.apache.doris.nereids.trees.expressions.Cast;
 import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.literal.IntegerLikeLiteral;
 import org.apache.doris.nereids.types.DoubleType;
 import org.apache.doris.nereids.types.IntegerType;
+import org.apache.doris.nereids.types.coercion.Int32OrLessType;
+import org.apache.doris.qe.ConnectContext;
 
+import java.math.BigInteger;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
- * if argument 0 is float or double, we should return double signature for 
round like function.
+ * Signature search for round-like functions (round, round_bankers, ceil, 
floor, truncate).
  */
 public interface SearchSignatureForRound extends ExplicitlyCastableSignature {
+
+    int DOUBLE_DECIMAL_RESULT_MAX_SCALE = 15;
+
     @Override
     default FunctionSignature searchSignature(List<FunctionSignature> 
signatures) {
         List<Expression> arguments = getArguments();
         if (arguments.get(0).getDataType().isFloatLikeType()) {
             if (arguments.size() == 1) {
                 return 
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE);
             } else if (arguments.size() == 2) {
+                if (arguments.get(0).getDataType().isDoubleType()
+                        && isOptedIntoDecimalReroute()
+                        && isNonNegativeIntegerLiteralAtMost(arguments.get(1),
+                                DOUBLE_DECIMAL_RESULT_MAX_SCALE)) {
+                    return ExplicitlyCastableSignature.super.searchSignature(
+                            withoutFloatLikeReturnTypes(signatures));
+                }
                 return 
FunctionSignature.ret(DoubleType.INSTANCE).args(DoubleType.INSTANCE, 
IntegerType.INSTANCE);
             }
         }
         return ExplicitlyCastableSignature.super.searchSignature(signatures);
     }
+
+    static boolean isOptedIntoDecimalReroute() {
+        ConnectContext ctx = ConnectContext.get();
+        return ctx != null && 
ctx.getSessionVariable().roundDoubleReturnsDecimalForConstScale;
+    }
+
+    /**
+     * True iff scale folds to an integer literal whose value lies in the 
closed range
+     * [0, maxValue].
+     */
+    static boolean isNonNegativeIntegerLiteralAtMost(Expression scale, int 
maxValue) {
+        Expression folded = scale;
+        if (!folded.isLiteral() && !folded.isSlot()) {
+            ExpressionRewriteContext ctx = new 
ExpressionRewriteContext(CascadesContext.initTempContext());
+            folded = FoldConstantRuleOnFE.evaluate(folded, ctx);
+        }
+        Expression unwrapped = folded;
+        if (unwrapped instanceof Cast && unwrapped.child(0).isLiteral()
+                && unwrapped.child(0).getDataType() instanceof 
Int32OrLessType) {
+            unwrapped = unwrapped.child(0);
+        }
+        if (!(unwrapped instanceof IntegerLikeLiteral)) {
+            return false;
+        }
+        Number number = ((IntegerLikeLiteral) unwrapped).getNumber();
+        BigInteger value = (number instanceof BigInteger)
+                ? (BigInteger) number
+                : BigInteger.valueOf(number.longValue());
+        return value.signum() >= 0 && 
value.compareTo(BigInteger.valueOf(maxValue)) <= 0;
+    }

Review Comment:
   This now accepts in-range widened integer literals, but 
`ComputePrecisionForRound` still only derives the result scale from 
`Int32OrLessType` literals/casts. A reduced plan is:
   
   ```text
   Project(round(d, CAST(2 AS BIGINT)))
     Scan(d: DOUBLE)
   ```
   
   `isNonNegativeIntegerLiteralAtMost` folds the scale to `BigIntLiteral(2)` 
and selects the decimal overload. Later 
`ComputePrecisionForRound.computePrecision` folds the same scale, sees 
`BigIntType` rather than `Int32OrLessType`, and falls through to `scale = 
decimalV3Type.getScale()` (15). The expression is therefore typed as 
`DECIMALV3(30,15)` instead of scale 2, so rendering/metadata can become 
`81.570000000000000` rather than `81.57`. This is distinct from the existing 
overflow thread because the scale is inside `[0, 15]`. Please either keep this 
predicate aligned with `ComputePrecisionForRound` (only accept int32-or-less 
after folding/unwrapping) or teach `ComputePrecisionForRound` to use exact 
widened integer values in range, and add a BIGINT/LARGEINT scale <= 15 test.



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