Skip to content

Commit

Permalink
Address Oliver's comments
Browse files Browse the repository at this point in the history
  • Loading branch information
tanclary committed Sep 6, 2023
1 parent 526d63a commit 4804912
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion site/_docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
136 changes: 68 additions & 68 deletions testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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\\(<NUMERIC>, <NUMERIC>\\)", false);
"No match found for function signature "
+ "SAFE_ADD\\(<NUMERIC>, <NUMERIC>\\)", 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))");
Expand All @@ -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\\(<NUMERIC>, <NUMERIC>\\)", false);
"No match found for function signature "
+ "SAFE_DIVIDE\\(<NUMERIC>, <NUMERIC>\\)", 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))",
Expand Down Expand Up @@ -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\\(<NUMERIC>\\)", false);
"No match found for function signature "
+ "SAFE_NEGATE\\(<NUMERIC>\\)", false);
final SqlOperatorFixture f = f0.withLibrary(SqlLibrary.BIG_QUERY);
f.checkScalar("safe_negate(cast(20 as bigint))", "-20",
"BIGINT");
Expand Down Expand Up @@ -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\\(<NUMERIC>, <NUMERIC>\\)", false);
"No match found for function signature "
+ "SAFE_SUBTRACT\\(<NUMERIC>, <NUMERIC>\\)", 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))");
Expand Down

0 comments on commit 4804912

Please sign in to comment.