diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java index 5835cf4319fb..93203afe3c3b 100644 --- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java +++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java @@ -653,9 +653,9 @@ Builder populate() { map.put(SAFE_ADD, new SafeArithmeticImplementor(BuiltInMethod.SAFE_ADD.method)); - map.put(SAFE_DIVIDE, - new SafeArithmeticImplementor(BuiltInMethod.SAFE_DIVIDE.method)); - map.put(SAFE_MULTIPLY, + map.put(SAFE_DIVIDE, + new SafeArithmeticImplementor(BuiltInMethod.SAFE_DIVIDE.method)); + map.put(SAFE_MULTIPLY, new SafeArithmeticImplementor(BuiltInMethod.SAFE_MULTIPLY.method)); map.put(SAFE_NEGATE, new SafeArithmeticImplementor(BuiltInMethod.SAFE_MULTIPLY.method)); diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java index 76d1ad6d872d..42492d97e72d 100644 --- a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java +++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java @@ -1733,11 +1733,11 @@ private static RelDataType deriveTypeMapFromEntries(SqlOperatorBinding opBinding SqlFunctionCategory.NUMERIC); /** The "SAFE_DIVIDE(numeric1, numeric2)" function; equivalent to the {@code /} operator but - * returns null if an error occurs, such as division by zero. */ + * returns null if an error occurs, such as overflow or division by zero. */ @LibraryOperator(libraries = {BIG_QUERY}) public static final SqlFunction SAFE_DIVIDE = SqlBasicFunction.create("SAFE_DIVIDE", - ReturnTypes.DOUBLE_IF_INTEGER.orElse(ReturnTypes.QUOTIENT_FORCE_NULLABLE), + ReturnTypes.DOUBLE_IF_INTEGERS.orElse(ReturnTypes.QUOTIENT_FORCE_NULLABLE), OperandTypes.NUMERIC_NUMERIC, SqlFunctionCategory.NUMERIC); diff --git a/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java b/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java index 06c420ba5b80..2f9a46d55569 100644 --- a/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java +++ b/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java @@ -827,10 +827,10 @@ public static SqlCall stripSeparator(SqlCall call) { DECIMAL_QUOTIENT.andThen(SqlTypeTransforms.TO_NULLABLE); /** - * Type-inference stratey whereby the result type of a call is + * Type-inference strategy whereby the result type of a call is * {@link #DOUBLE} if both operands are integer types. */ - public static final SqlReturnTypeInference DOUBLE_IF_INTEGER = opBinding -> { + public static final SqlReturnTypeInference DOUBLE_IF_INTEGERS = opBinding -> { RelDataTypeFactory typeFactory = opBinding.getTypeFactory(); SqlTypeName type1 = opBinding.getOperandType(0).getSqlTypeName(); SqlTypeName type2 = opBinding.getOperandType(1).getSqlTypeName(); diff --git a/site/_docs/reference.md b/site/_docs/reference.md index 26bde910c0a8..6cc2f03aa532 100644 --- a/site/_docs/reference.md +++ b/site/_docs/reference.md @@ -2800,7 +2800,7 @@ BigQuery's type system uses confusingly different names for types and functions: | b o | RTRIM(string) | Returns *string* with all blanks removed from the end | b | SAFE_ADD(numeric1, numeric2) | Returns *numeric1* + *numeric2*, or NULL on overflow | b | SAFE_CAST(value AS type) | Converts *value* to *type*, returning NULL if conversion fails -| b | SAFE_DIVIDE(numeric1, numeric2) | Returns *numeric1* / *numeric2*, or NULL on overflow or if *numeric2* is zero +| b | SAFE_DIVIDE(numeric1, numeric2) | Returns *numeric1* / *numeric2*, or NULL on overflow or if *numeric2* is zero | b | SAFE_MULTIPLY(numeric1, numeric2) | Returns *numeric1* * *numeric2*, or NULL on overflow | b | SAFE_NEGATE(numeric) | Returns *numeric* * -1, or NULL on overflow | b | SAFE_OFFSET(index) | Similar to `OFFSET` except null is returned if *index* is out of bounds diff --git a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java index 889df779ee37..5352779c1681 100644 --- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java +++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java @@ -7408,76 +7408,76 @@ private static void checkIf(SqlOperatorFixture f) { @Test void testSafeAddFunc() { final SqlOperatorFixture f0 = fixture().setFor(SqlLibraryOperators.SAFE_ADD); f0.checkFails("^safe_add(2, 3)^", - "No match found for function signature " - + "SAFE_ADD\\(, \\)", false); + "No match found for function signature " + + "SAFE_ADD\\(, \\)", false); final SqlOperatorFixture f = f0.withLibrary(SqlLibrary.BIG_QUERY); // Basic test for each of the 9 2-permutations of BIGINT, DECIMAL, and FLOAT f.checkScalar("safe_add(cast(20 as bigint), cast(20 as bigint))", - "40", "BIGINT"); + "40", "BIGINT"); f.checkScalar("safe_add(cast(20 as bigint), cast(1.2345 as decimal(5,4)))", - "21.2345", "DECIMAL(19, 4)"); + "21.2345", "DECIMAL(19, 4)"); f.checkScalar("safe_add(cast(1.2345 as decimal(5,4)), cast(20 as bigint))", - "21.2345", "DECIMAL(19, 4)"); - f.checkScalar("safe_add(cast(1.2345 as decimal(5,4)), " - + "cast(2.0 as decimal(2, 1)))", "3.2345", "DECIMAL(6, 4)"); + "21.2345", "DECIMAL(19, 4)"); + f.checkScalar("safe_add(cast(1.2345 as decimal(5,4)), cast(2.0 as decimal(2, 1)))", + "3.2345", "DECIMAL(6, 4)"); f.checkScalar("safe_add(cast(3 as double), cast(3 as bigint))", - "6.0", "DOUBLE"); + "6.0", "DOUBLE"); f.checkScalar("safe_add(cast(3 as bigint), cast(3 as double))", - "6.0", "DOUBLE"); + "6.0", "DOUBLE"); f.checkScalar("safe_add(cast(3 as double), cast(1.2345 as decimal(5, 4)))", - "4.2345", "DOUBLE"); + "4.2345", "DOUBLE"); f.checkScalar("safe_add(cast(1.2345 as decimal(5, 4)), cast(3 as double))", - "4.2345", "DOUBLE"); + "4.2345", "DOUBLE"); f.checkScalar("safe_add(cast(3 as double), cast(3 as double))", - "6.0", "DOUBLE"); + "6.0", "DOUBLE"); // Tests for + and - Infinity f.checkScalar("safe_add(cast('Infinity' as double), cast(3 as double))", - "Infinity", "DOUBLE"); + "Infinity", "DOUBLE"); f.checkScalar("safe_add(cast('-Infinity' as double), cast(3 as double))", - "-Infinity", "DOUBLE"); + "-Infinity", "DOUBLE"); f.checkScalar("safe_add(cast('-Infinity' as double), " - + "cast('Infinity' as double))", "NaN", "DOUBLE"); + + "cast('Infinity' as double))", "NaN", "DOUBLE"); // Tests for NaN f.checkScalar("safe_add(cast('NaN' as double), cast(3 as bigint))", - "NaN", "DOUBLE"); + "NaN", "DOUBLE"); f.checkScalar("safe_add(cast('NaN' as double), cast(1.23 as decimal(3, 2)))", - "NaN", "DOUBLE"); + "NaN", "DOUBLE"); f.checkScalar("safe_add(cast('NaN' as double), cast('Infinity' as double))", - "NaN", "DOUBLE"); + "NaN", "DOUBLE"); f.checkScalar("safe_add(cast(3 as bigint), cast('NaN' as double))", - "NaN", "DOUBLE"); + "NaN", "DOUBLE"); f.checkScalar("safe_add(cast(1.23 as decimal(3, 2)), cast('NaN' as double))", - "NaN", "DOUBLE"); + "NaN", "DOUBLE"); // Overflow test for each pairing f.checkNull("safe_add(cast(20 as bigint), " - + "cast(9223372036854775807 as bigint))"); + + "cast(9223372036854775807 as bigint))"); f.checkNull("safe_add(cast(-20 as bigint), " - + "cast(-9223372036854775807 as bigint))"); + + "cast(-9223372036854775807 as bigint))"); f.checkNull("safe_add(9, cast(9.999999999999999999e75 as DECIMAL(38, 19)))"); f.checkNull("safe_add(-9, cast(-9.999999999999999999e75 as DECIMAL(38, 19)))"); f.checkNull("safe_add(cast(9.999999999999999999e75 as DECIMAL(38, 19)), 9)"); f.checkNull("safe_add(cast(-9.999999999999999999e75 as DECIMAL(38, 19)), -9)"); f.checkNull("safe_add(cast(9.9e75 as DECIMAL(76, 0)), " - + "cast(9.9e75 as DECIMAL(76, 0)))"); + + "cast(9.9e75 as DECIMAL(76, 0)))"); f.checkNull("safe_add(cast(-9.9e75 as DECIMAL(76, 0)), " - + "cast(-9.9e75 as DECIMAL(76, 0)))"); + + "cast(-9.9e75 as DECIMAL(76, 0)))"); f.checkNull("safe_add(cast(1.7976931348623157e308 as double), " - + "cast(9.9e7 as decimal(76, 0)))"); + + "cast(9.9e7 as decimal(76, 0)))"); f.checkNull("safe_add(cast(-1.7976931348623157e308 as double), " - + "cast(-9.9e7 as decimal(76, 0)))"); + + "cast(-9.9e7 as decimal(76, 0)))"); f.checkNull("safe_add(cast(9.9e7 as decimal(76, 0)), " - + "cast(1.7976931348623157e308 as double))"); + + "cast(1.7976931348623157e308 as double))"); f.checkNull("safe_add(cast(-9.9e7 as decimal(76, 0)), " - + "cast(-1.7976931348623157e308 as double))"); + + "cast(-1.7976931348623157e308 as double))"); f.checkNull("safe_add(cast(1.7976931348623157e308 as double), cast(3 as bigint))"); f.checkNull("safe_add(cast(-1.7976931348623157e308 as double), " - + "cast(-3 as bigint))"); + + "cast(-3 as bigint))"); f.checkNull("safe_add(cast(3 as bigint), cast(1.7976931348623157e308 as double))"); f.checkNull("safe_add(cast(-3 as bigint), " - + "cast(-1.7976931348623157e308 as double))"); + + "cast(-1.7976931348623157e308 as double))"); f.checkNull("safe_add(cast(3 as double), cast(1.7976931348623157e308 as double))"); f.checkNull("safe_add(cast(-3 as double), " - + "cast(-1.7976931348623157e308 as double))"); + + "cast(-1.7976931348623157e308 as double))"); // Check that null argument retuns null f.checkNull("safe_add(cast(null as double), cast(3 as bigint))"); f.checkNull("safe_add(cast(3 as double), cast(null as bigint))"); @@ -7486,8 +7486,8 @@ private static void checkIf(SqlOperatorFixture f) { @Test void testSafeDivideFunc() { final SqlOperatorFixture f0 = fixture().setFor(SqlLibraryOperators.SAFE_DIVIDE); f0.checkFails("^safe_divide(2, 3)^", - "No match found for function signature " - + "SAFE_DIVIDE\\(, \\)", false); + "No match found for function signature " + + "SAFE_DIVIDE\\(, \\)", false); final SqlOperatorFixture f = f0.withLibrary(SqlLibrary.BIG_QUERY); // Basic test for each of the 9 2-permutations of BIGINT, DECIMAL, and FLOAT f.checkScalar("safe_divide(cast(2 as bigint), cast(4 as bigint))", @@ -7633,8 +7633,8 @@ private static void checkIf(SqlOperatorFixture f) { @Test void testSafeNegateFunc() { final SqlOperatorFixture f0 = fixture().setFor(SqlLibraryOperators.SAFE_NEGATE); f0.checkFails("^safe_negate(2)^", - "No match found for function signature " - + "SAFE_NEGATE\\(\\)", false); + "No match found for function signature " + + "SAFE_NEGATE\\(\\)", false); final SqlOperatorFixture f = f0.withLibrary(SqlLibrary.BIG_QUERY); f.checkScalar("safe_negate(cast(20 as bigint))", "-20", "BIGINT"); @@ -7668,79 +7668,79 @@ private static void checkIf(SqlOperatorFixture f) { @Test void testSafeSubtractFunc() { final SqlOperatorFixture f0 = fixture().setFor(SqlLibraryOperators.SAFE_SUBTRACT); f0.checkFails("^safe_subtract(2, 3)^", - "No match found for function signature " - + "SAFE_SUBTRACT\\(, \\)", false); + "No match found for function signature " + + "SAFE_SUBTRACT\\(, \\)", false); final SqlOperatorFixture f = f0.withLibrary(SqlLibrary.BIG_QUERY); // Basic test for each of the 9 2-permutations of BIGINT, DECIMAL, and FLOAT f.checkScalar("safe_subtract(cast(20 as bigint), cast(20 as bigint))", - "0", "BIGINT"); + "0", "BIGINT"); f.checkScalar("safe_subtract(cast(20 as bigint), cast(-1.2345 as decimal(5,4)))", - "21.2345", "DECIMAL(19, 4)"); + "21.2345", "DECIMAL(19, 4)"); f.checkScalar("safe_subtract(cast(1.2345 as decimal(5,4)), cast(-20 as bigint))", - "21.2345", "DECIMAL(19, 4)"); + "21.2345", "DECIMAL(19, 4)"); f.checkScalar("safe_subtract(cast(1.23 as decimal(3,2)), " - + "cast(-2.0 as decimal(2, 1)))", "3.23", "DECIMAL(4, 2)"); + + "cast(-2.0 as decimal(2, 1)))", "3.23", "DECIMAL(4, 2)"); f.checkScalar("safe_subtract(cast(3 as double), cast(-3 as bigint))", - "6.0", "DOUBLE"); + "6.0", "DOUBLE"); f.checkScalar("safe_subtract(cast(3 as bigint), cast(-3 as double))", - "6.0", "DOUBLE"); + "6.0", "DOUBLE"); f.checkScalar("safe_subtract(cast(3 as double), cast(-1.2345 as decimal(5, 4)))", - "4.2345", "DOUBLE"); + "4.2345", "DOUBLE"); f.checkScalar("safe_subtract(cast(1.2345 as decimal(5, 4)), cast(-3 as double))", - "4.2345", "DOUBLE"); + "4.2345", "DOUBLE"); f.checkScalar("safe_subtract(cast(3 as double), cast(3 as double))", - "0.0", "DOUBLE"); + "0.0", "DOUBLE"); // Tests for + and - Infinity f.checkScalar("safe_subtract(cast('Infinity' as double), cast(3 as double))", - "Infinity", "DOUBLE"); + "Infinity", "DOUBLE"); f.checkScalar("safe_subtract(cast('-Infinity' as double), cast(3 as double))", - "-Infinity", "DOUBLE"); + "-Infinity", "DOUBLE"); f.checkScalar("safe_subtract(cast('Infinity' as double), " - + "cast('Infinity' as double))", "NaN", "DOUBLE"); + + "cast('Infinity' as double))", "NaN", "DOUBLE"); // Tests for NaN f.checkScalar("safe_subtract(cast('NaN' as double), cast(3 as bigint))", - "NaN", "DOUBLE"); + "NaN", "DOUBLE"); f.checkScalar("safe_subtract(cast('NaN' as double), cast(1.23 as decimal(3, 2)))", - "NaN", "DOUBLE"); + "NaN", "DOUBLE"); f.checkScalar("safe_subtract(cast('NaN' as double), cast('Infinity' as double))", - "NaN", "DOUBLE"); + "NaN", "DOUBLE"); f.checkScalar("safe_subtract(cast(3 as bigint), cast('NaN' as double))", - "NaN", "DOUBLE"); + "NaN", "DOUBLE"); f.checkScalar("safe_subtract(cast(1.23 as decimal(3, 2)), cast('NaN' as double))", - "NaN", "DOUBLE"); + "NaN", "DOUBLE"); // Overflow test for each pairing f.checkNull("safe_subtract(cast(20 as bigint), " - + "cast(-9223372036854775807 as bigint))"); + + "cast(-9223372036854775807 as bigint))"); f.checkNull("safe_subtract(cast(-20 as bigint), " - + "cast(9223372036854775807 as bigint))"); + + "cast(9223372036854775807 as bigint))"); f.checkNull("safe_subtract(9, cast(-9.999999999999999999e75 as DECIMAL(38, 19)))"); f.checkNull("safe_subtract(-9, cast(9.999999999999999999e75 as DECIMAL(38, 19)))"); f.checkNull("safe_subtract(cast(-9.999999999999999999e75 as DECIMAL(38, 19)), 9)"); f.checkNull("safe_subtract(cast(9.999999999999999999e75 as DECIMAL(38, 19)), -9)"); f.checkNull("safe_subtract(cast(-9.9e75 as DECIMAL(76, 0)), " - + "cast(9.9e75 as DECIMAL(76, 0)))"); + + "cast(9.9e75 as DECIMAL(76, 0)))"); f.checkNull("safe_subtract(cast(9.9e75 as DECIMAL(76, 0)), " - + "cast(-9.9e75 as DECIMAL(76, 0)))"); + + "cast(-9.9e75 as DECIMAL(76, 0)))"); f.checkNull("safe_subtract(cast(1.7976931348623157e308 as double), " - + "cast(-9.9e7 as decimal(76, 0)))"); + + "cast(-9.9e7 as decimal(76, 0)))"); f.checkNull("safe_subtract(cast(-1.7976931348623157e308 as double), " - + "cast(9.9e7 as decimal(76, 0)))"); + + "cast(9.9e7 as decimal(76, 0)))"); f.checkNull("safe_subtract(cast(9.9e7 as decimal(76, 0)), " - + "cast(-1.7976931348623157e308 as double))"); + + "cast(-1.7976931348623157e308 as double))"); f.checkNull("safe_subtract(cast(-9.9e7 as decimal(76, 0)), " - + "cast(1.7976931348623157e308 as double))"); + + "cast(1.7976931348623157e308 as double))"); f.checkNull("safe_subtract(cast(1.7976931348623157e308 as double), " - + "cast(-3 as bigint))"); + + "cast(-3 as bigint))"); f.checkNull("safe_subtract(cast(-1.7976931348623157e308 as double), " - + "cast(3 as bigint))"); + + "cast(3 as bigint))"); f.checkNull("safe_subtract(cast(3 as bigint), " - + "cast(-1.7976931348623157e308 as double))"); + + "cast(-1.7976931348623157e308 as double))"); f.checkNull("safe_subtract(cast(-3 as bigint), " - + "cast(1.7976931348623157e308 as double))"); + + "cast(1.7976931348623157e308 as double))"); f.checkNull("safe_subtract(cast(3 as double), " - + "cast(-1.7976931348623157e308 as double))"); + + "cast(-1.7976931348623157e308 as double))"); f.checkNull("safe_subtract(cast(-3 as double), " - + "cast(1.7976931348623157e308 as double))"); + + "cast(1.7976931348623157e308 as double))"); // Check that null argument retuns null f.checkNull("safe_subtract(cast(null as double), cast(3 as bigint))"); f.checkNull("safe_subtract(cast(3 as double), cast(null as bigint))");