diff --git a/core/trino-main/src/main/java/io/trino/operator/scalar/MathFunctions.java b/core/trino-main/src/main/java/io/trino/operator/scalar/MathFunctions.java index 05b8470f16a2..8f9108629c4f 100644 --- a/core/trino-main/src/main/java/io/trino/operator/scalar/MathFunctions.java +++ b/core/trino-main/src/main/java/io/trino/operator/scalar/MathFunctions.java @@ -837,6 +837,13 @@ public static double round(@SqlType(StandardTypes.DOUBLE) double num, @SqlType(S if (rescaledRound != Long.MAX_VALUE) { return sign * (rescaledRound / factor); } + if (Double.isInfinite(rescaled)) { + // num has max 17 precisions, so to make round actually do something, decimals must be smaller than 17. + // then factor must be smaller than 10^17 + // then in order for rescaled to be greater than Double.MAX_VALUE, num must be greater than 1.8E291 with many trailing zeros + // in which case, rounding is no op anyway + return num; + } return sign * DoubleMath.roundToBigInteger(rescaled, RoundingMode.HALF_UP).doubleValue() / factor; } @@ -858,6 +865,11 @@ public static long roundReal(@SqlType(StandardTypes.REAL) long num, @SqlType(Sta if (rescaledRound != Long.MAX_VALUE) { result = sign * (rescaledRound / factor); } + else if (Double.isInfinite(rescaled)) { + // numInFloat is max at 3.4028235e+38f, to make rescale greater than Double.MAX_VALUE, decimals must be greater than 270 + // but numInFloat has max 8 precision, so rounding is no op + return num; + } else { result = sign * (DoubleMath.roundToBigInteger(rescaled, RoundingMode.HALF_UP).doubleValue() / factor); } diff --git a/core/trino-main/src/test/java/io/trino/operator/scalar/TestMathFunctions.java b/core/trino-main/src/test/java/io/trino/operator/scalar/TestMathFunctions.java index b1164e0c5cd5..1ed81c813daf 100644 --- a/core/trino-main/src/test/java/io/trino/operator/scalar/TestMathFunctions.java +++ b/core/trino-main/src/test/java/io/trino/operator/scalar/TestMathFunctions.java @@ -1658,6 +1658,13 @@ public void testRound() assertThat(assertions.function("round", "DOUBLE '3000.1234567890123456789'", "16")) .isEqualTo(3000.1234567890124); + // 1.8E292*10^16 is infinity. + assertThat(assertions.function("round", "DOUBLE '1.8E292'", "16")) + .isEqualTo(1.8E292); + + assertThat(assertions.function("round", "DOUBLE '-1.8E292'", "16")) + .isEqualTo(-1.8E292); + assertThat(assertions.function("round", "TINYINT '3'", "TINYINT '1'")) .isEqualTo((byte) 3); @@ -1702,6 +1709,13 @@ public void testRound() assertThat(assertions.function("round", "REAL '3000.1234567890123456789'", "16")) .isEqualTo(3000.1235f); + // 3.4028235e+38 * 10 ^ 271 is infinity + assertThat(assertions.function("round", "REAL '3.4028235e+38'", "271")) + .isEqualTo(3.4028235e+38f); + + assertThat(assertions.function("round", "REAL '-3.4028235e+38'", "271")) + .isEqualTo(-3.4028235e+38f); + assertThat(assertions.function("round", "3", "1")) .isEqualTo(3);