github-actions[bot] commented on code in PR #64622:
URL: https://github.com/apache/doris/pull/64622#discussion_r3432086592
##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/SearchSignatureForRound.java:
##########
@@ -18,26 +18,84 @@
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 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).
+ *
+ * For float/double inputs the result type defaults to double, which is
correct except
+ * when a non-negative integer-literal scale is given: the rounded double
cannot land on a
+ * clean N-decimal value (e.g. round(23900/293, 2) stores 81.56999999999999488…
+ * in IEEE-754 and renders as "81.56999999999999").
+ * In that case, for DOUBLE input we route the call through the existing
decimal
+ * signature, which both gives the user the value they asked for and matches
MySQL's
+ * behavior. FLOAT input is left on the original DOUBLE path: float promotes to
+ * decimal(14, 7) which can only hold 7 integer digits —- values |f| >= 1e7
would
+ * overflow during the cast.
*/
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()
+ && isNonNegativeIntegerLiteralAtMost(arguments.get(1),
+ DOUBLE_DECIMAL_RESULT_MAX_SCALE)) {
Review Comment:
This decimal route still changes valid DOUBLE inputs that cannot be
represented by `DECIMALV3(30,15)`. The analyzed expression for a column is
effectively:
```text
Project(round(d, 2))
Scan(d: DOUBLE)
```
After this branch selects the decimal signature, type coercion inserts:
```text
Project(round(CAST(d AS DECIMALV3(30,15)), 2))
Scan(d: DOUBLE)
```
`DECIMALV3(30,15)` only has 15 integer digits, and the BE
float/double-to-decimal cast marks overflow/NaN/Inf as NULL in non-strict mode
or returns `ARITHMETIC_OVERFLOW` in strict mode. So rows such as `d = 1e20`, `d
= -1e20`, `d = inf`, or `d = nan` used to flow through the DOUBLE round
implementation, but now become NULL or fail before the round function runs.
This is distinct from the earlier scale > 15 issue: even with the scale cap,
the first argument is still not guaranteed cast-preserving. Please keep the
DOUBLE path for values the chosen decimal type cannot represent, or use a
decimal conversion/result strategy that preserves the accepted DOUBLE domain
instead of silently nulling/erroring valid inputs.
--
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]