tanclary commented on code in PR #3234:
URL: https://github.com/apache/calcite/pull/3234#discussion_r1254726840
##########
babel/src/test/resources/sql/big-query.iq:
##########
@@ -600,6 +600,44 @@ FROM t;
!ok
!}
+#####################################################################
+# SAFE_MULTIPLY
+#
+# SAFE_MULTIPLY(value1, value2)
+#
+# Equivalent to the mulitply operator (*), but returns NULL if
overflow/underflow occurs.
+SELECT SAFE_MULTIPLY(5, 4) as result;
++--------+
+| result |
++--------+
+| 20 |
++--------+
+(1 row)
+
+!ok
+
+#Overflow occurs if result is greater than 2^63 - 1
+SELECT SAFE_MULTIPLY(9223372036854775807, 2) as overflow_result;
++-----------------+
+| overflow_result |
++-----------------+
+| |
++-----------------+
+(1 row)
+
+!ok
+
+#Underflow occurs if result is less than -2^63
+SELECT SAFE_MULTIPLY(-9223372036854775806, 3) as underflow_result;
++------------------+
+| underflow_result |
++------------------+
+| |
++------------------+
+(1 row)
+
+!ok
+
Review Comment:
Done.
##########
core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java:
##########
@@ -1524,6 +1524,91 @@ public static int multiply(int b0, int b1) {
throw notArithmetic("*", b0, b1);
}
+ /** SQL <code>SAFE_MULTIPLY</code> function applied to long values. */
+ public static @Nullable Long safeMultiply(long b0, long b1) {
+ try {
+ return Math.multiplyExact(b0, b1);
+ } catch (ArithmeticException e) {
+ return null;
+ }
+ }
+
+ /** SQL <code>SAFE_MULTIPLY</code> function applied to long and BigDecimal
values. */
+ public static @Nullable BigDecimal safeMultiply(long b0, BigDecimal b1) {
+ BigDecimal ans = BigDecimal.valueOf(b0).multiply(b1);
+ return safeDecimal(ans) ? ans : null;
+ }
+
+ /** SQL <code>SAFE_MULTIPLY</code> function applied to BigDecimal and long
values. */
+ public static @Nullable BigDecimal safeMultiply(BigDecimal b0, long b1) {
+ BigDecimal ans = b0.multiply(BigDecimal.valueOf(b1));
+ return safeDecimal(ans) ? ans : null;
+ }
+
+ /** SQL <code>SAFE_MULTIPLY</code> function applied to BigDecimal values. */
+ public static @Nullable BigDecimal safeMultiply(BigDecimal b0, BigDecimal
b1) {
+ BigDecimal ans = b0.multiply(b1);
+ return safeDecimal(ans) ? ans : null;
+ }
+
+ /** SQL <code>SAFE_MULTIPLY</code> function applied to double and long
values. */
+ public static @Nullable Double safeMultiply(double b0, long b1) {
+ double ans = b0 * b1;
+ boolean isInfinite = Double.isInfinite(b0);
+ return safeDecimal(ans) || isInfinite ? ans : null;
+ }
+
+ /** SQL <code>SAFE_MULTIPLY</code> function applied to long and double
values. */
+ public static @Nullable Double safeMultiply(long b0, double b1) {
+ double ans = b0 * b1;
+ boolean isInfinite = Double.isInfinite(b1);
+ return safeDecimal(ans) || isInfinite ? ans : null;
+ }
+
+ /** SQL <code>SAFE_MULTIPLY</code> function applied to double and BigDecimal
values. */
+ public static @Nullable Double safeMultiply(double b0, BigDecimal b1) {
+ double ans = b0 * b1.doubleValue();
+ boolean isInfinite = Double.isInfinite(b0);
+ return safeDecimal(ans) || isInfinite ? ans : null;
+ }
+
+ /** SQL <code>SAFE_MULTIPLY</code> function applied to BigDecimal and double
values. */
+ public static @Nullable Double safeMultiply(BigDecimal b0, double b1) {
+ double ans = b0.doubleValue() * b1;
+ boolean isInfinite = Double.isInfinite(b1);
+ return safeDecimal(ans) || isInfinite ? ans : null;
+ }
+
+ /** SQL <code>SAFE_MULTIPLY</code> function applied to double values. */
+ public static @Nullable Double safeMultiply(double b0, double b1) {
+ double ans = b0 * b1;
+ boolean isInfinite = Double.isInfinite(b0) || Double.isInfinite(b1);
+ return safeDecimal(ans) || isInfinite ? ans : null;
+ }
+
+ /** Helper for the safe arithmetic functions to determine
+ * overflow for a BigDecimal value. According to BigQuery, BigDecimal
+ * overflow occurs if the precision is greater than 76 or the precision
+ * is greater than 38. */
+ private static boolean safeDecimal(BigDecimal b) {
+ return b.scale() <= 38 && b.precision() <= 76;
+ }
+
+ /** Helper for the safe arithmetic functions to determine
+ * overflow for a double. */
+ private static boolean safeDecimal(double d) {
Review Comment:
Good call. Done.
--
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]