Skip to content

Commit

Permalink
[CALCITE-6066] Add HYPOT function (enabled in Spark library)
Browse files Browse the repository at this point in the history
  • Loading branch information
herunkang2018 committed Nov 2, 2023
1 parent c5f3b8d commit b4e7cf4
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public enum NullPolicy {
/** Returns null if and only if all of the arguments are null;
* If all of the arguments are false return false otherwise true. */
ALL,
/** Returns null if and only if one of the arguments are null. */
/** Returns null if and only if at least one of the arguments is null. */
STRICT,
/** Returns null if one of the arguments is null, and possibly other times. */
SEMI_STRICT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@
import static org.apache.calcite.sql.fun.SqlLibraryOperators.FROM_BASE64;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.FROM_HEX;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.GETBIT;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.HYPOT;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.ILIKE;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.IS_INF;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.IS_NAN;
Expand Down Expand Up @@ -657,6 +658,7 @@ Builder populate() {
defineMethod(CSCH, BuiltInMethod.CSCH.method, NullPolicy.STRICT);
defineMethod(DEGREES, BuiltInMethod.DEGREES.method, NullPolicy.STRICT);
defineMethod(FACTORIAL, BuiltInMethod.FACTORIAL.method, NullPolicy.STRICT);
defineMethod(HYPOT, BuiltInMethod.HYPOT.method, NullPolicy.STRICT);
defineMethod(IS_INF, BuiltInMethod.IS_INF.method, NullPolicy.STRICT);
defineMethod(IS_NAN, BuiltInMethod.IS_NAN.method, NullPolicy.STRICT);
defineMethod(POW, BuiltInMethod.POWER.method, NullPolicy.STRICT);
Expand Down
10 changes: 10 additions & 0 deletions core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
Original file line number Diff line number Diff line change
Expand Up @@ -3114,6 +3114,16 @@ public static double degrees(double b0) {
return CombinatoricsUtils.factorial(b0);
}

/** SQL <code>HYPOT</code> operator applied to BigDecimal values. */
public static double hypot(BigDecimal a, BigDecimal b) {
return hypot(a.doubleValue(), b.doubleValue());
}

/** SQL <code>HYPOT</code> operator applied to double values. */
public static double hypot(double a, double b) {
return Math.hypot(a, b);
}

/** SQL <code>IS_INF</code> operator applied to BigDecimal values. */
public static boolean isInf(BigDecimal b0) {
return Double.isInfinite(b0.doubleValue());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2046,6 +2046,15 @@ private static RelDataType deriveTypeMapFromEntries(SqlOperatorBinding opBinding
OperandTypes.INTEGER,
SqlFunctionCategory.NUMERIC);

/** The {@code HYPOT(numeric1, numeric2)} function; returns
* sqrt(numeric1^2 + numeric2^2) without intermediate overflow or underflow. */
@LibraryOperator(libraries = {SPARK})
public static final SqlFunction HYPOT =
SqlBasicFunction.create("HYPOT",
ReturnTypes.DOUBLE_NULLABLE,
OperandTypes.NUMERIC_NUMERIC,
SqlFunctionCategory.NUMERIC);

@LibraryOperator(libraries = {BIG_QUERY, MYSQL, POSTGRESQL})
public static final SqlFunction MD5 =
SqlBasicFunction.create("MD5",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,7 @@ public enum BuiltInMethod {
TAN(SqlFunctions.class, "tan", double.class),
TANH(SqlFunctions.class, "tanh", long.class),
SINH(SqlFunctions.class, "sinh", long.class),
HYPOT(SqlFunctions.class, "hypot", double.class, double.class),
TRUNCATE(SqlFunctions.class, "truncate", String.class, int.class),
TRUNCATE_OR_PAD(SqlFunctions.class, "truncateOrPad", String.class, int.class),
TRIM(SqlFunctions.class, "trim", boolean.class, boolean.class, String.class,
Expand Down
1 change: 1 addition & 0 deletions site/_docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -2740,6 +2740,7 @@ BigQuery's type system uses confusingly different names for types and functions:
| b | FORMAT_TIMESTAMP(string timestamp) | Formats *timestamp* according to the specified format *string*
| s | GETBIT(value, position) | Equivalent to `BIT_GET(value, position)`
| b o | GREATEST(expr [, expr ]*) | Returns the greatest of the expressions
| s | HYPOT(numeric1, numeric2) | Returns sqrt(*numeric1*^2 + *numeric2*^2) without intermediate overflow or underflow
| b h s | IF(condition, value1, value2) | Returns *value1* if *condition* is TRUE, *value2* otherwise
| b | IFNULL(value1, value2) | Equivalent to `NVL(value1, value2)`
| p | string1 ILIKE string2 [ ESCAPE string3 ] | Whether *string1* matches pattern *string2*, ignoring case (similar to `LIKE`)
Expand Down
28 changes: 28 additions & 0 deletions testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -7659,6 +7659,34 @@ private static void checkIf(SqlOperatorFixture f) {
f.checkNull("pow(cast(null as integer), 2)");
}

@Test void testHypotFunc() {
final SqlOperatorFixture f0 = fixture().setFor(SqlLibraryOperators.HYPOT);
f0.checkFails("^hypot(3, 4)^",
"No match found for function signature HYPOT\\(<NUMERIC>, <NUMERIC>\\)",
false);
final SqlOperatorFixture f = f0.withLibrary(SqlLibrary.SPARK);
f.checkScalarApprox("hypot(3, 4)", "DOUBLE NOT NULL",
isWithin(5.0000d, 0.0001d));
f.checkScalarApprox("hypot(3.0, cast(4 as bigint))", "DOUBLE NOT NULL",
isWithin(5.0000d, 0.0001d));
f.checkScalarApprox("hypot(cast(-2 as bigint), cast(-4 as bigint))",
"DOUBLE NOT NULL",
isWithin(4.4721d, 0.0001d));
f.checkScalarApprox("hypot(cast(3.0 as double), cast(4.0 as double))",
"DOUBLE NOT NULL",
isWithin(5.0000d, 0.0001d));
f.checkScalarApprox("hypot(-2.5, cast(-4.5 as double))", "DOUBLE NOT NULL",
isWithin(5.1478d, 0.0001d));
f.checkScalarApprox("hypot(-2.5, -4.5)", "DOUBLE NOT NULL",
isWithin(5.1478d, 0.0001d));
f.checkType("hypot(cast(null as bigint), 1)", "DOUBLE");
f.checkNull("hypot(cast(null as bigint), 1)");
f.checkNull("hypot(1, cast(null as bigint))");
f.checkNull("hypot(cast(null as bigint), cast(null as bigint))");
f.checkNull("hypot(cast(null as double), cast(null as double))");
f.checkNull("hypot(cast(null as decimal), cast(null as decimal))");
}

@Test void testInfinity() {
final SqlOperatorFixture f = fixture();
f.checkScalar("cast('Infinity' as double)", "Infinity",
Expand Down

0 comments on commit b4e7cf4

Please sign in to comment.