Skip to content

Commit

Permalink
[CALCITE-6224] Add LOG2 function (enabled in MySQL, Spark library)
Browse files Browse the repository at this point in the history
Co-authored-by: Tanner Clary <[email protected]>
close apache#3707
  • Loading branch information
caicancai authored and tanclary committed Feb 29, 2024
1 parent 2558c13 commit c546d4a
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@
import static org.apache.calcite.sql.fun.SqlLibraryOperators.LEFT;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.LEVENSHTEIN;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.LOG;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.LOG2;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.LOGICAL_AND;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.LOGICAL_OR;
import static org.apache.calcite.sql.fun.SqlLibraryOperators.LPAD;
Expand Down Expand Up @@ -637,6 +638,7 @@ Builder populate() {
defineMethod(EXP, BuiltInMethod.EXP.method, NullPolicy.STRICT);
defineMethod(POWER, BuiltInMethod.POWER.method, NullPolicy.STRICT);
defineMethod(ABS, BuiltInMethod.ABS.method, NullPolicy.STRICT);
defineMethod(LOG2, BuiltInMethod.LOG2.method, NullPolicy.STRICT);

map.put(LN, new LogImplementor());
map.put(LOG, new LogImplementor());
Expand Down
13 changes: 12 additions & 1 deletion core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
Original file line number Diff line number Diff line change
Expand Up @@ -2764,7 +2764,7 @@ public static double power(BigDecimal b0, BigDecimal b1) {
}


// LN, LOG, LOG10
// LN, LOG, LOG10, LOG2

/** SQL {@code LOG(number, number2)} function applied to double values. */
public static double log(double d0, double d1) {
Expand All @@ -2788,6 +2788,17 @@ public static double log(BigDecimal d0, BigDecimal d1) {
return Math.log(d0.doubleValue()) / Math.log(d1.doubleValue());
}

/** SQL {@code LOG2(number)} function applied to double values. */
public static @Nullable Double log2(double number) {
return (number <= 0) ? null : log(number, 2);
}

/** SQL {@code LOG2(number)} function applied to
* BigDecimal values. */
public static @Nullable Double log2(BigDecimal number) {
return log2(number.doubleValue());
}

// MOD

/** SQL <code>MOD</code> operator applied to byte values. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2149,6 +2149,14 @@ private static RelDataType deriveTypeMapFromEntries(SqlOperatorBinding opBinding
OperandTypes.NUMERIC_OPTIONAL_NUMERIC,
SqlFunctionCategory.NUMERIC);

/** The "LOG2(numeric)" function. Returns the base 2 logarithm of numeric. */
@LibraryOperator(libraries = {MYSQL, SPARK})
public static final SqlFunction LOG2 =
SqlBasicFunction.create("LOG2",
ReturnTypes.DOUBLE_FORCE_NULLABLE,
OperandTypes.NUMERIC,
SqlFunctionCategory.NUMERIC);

@LibraryOperator(libraries = {BIG_QUERY, SPARK})
public static final SqlFunction POW =
SqlStdOperatorTable.POWER.withName("POW");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,13 @@ public static SqlCall stripSeparator(SqlCall call) {
public static final SqlReturnTypeInference DOUBLE_NULLABLE =
DOUBLE.andThen(SqlTypeTransforms.TO_NULLABLE);

/**
* Type-inference strategy whereby the result type of a call is a nullable
* Double.
*/
public static final SqlReturnTypeInference DOUBLE_FORCE_NULLABLE =
DOUBLE.andThen(SqlTypeTransforms.FORCE_NULLABLE);

/**
* Type-inference strategy whereby the result type of a call is a Char.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,7 @@ public enum BuiltInMethod {
SAFE_MULTIPLY(SqlFunctions.class, "safeMultiply", double.class, double.class),
SAFE_SUBTRACT(SqlFunctions.class, "safeSubtract", double.class, double.class),
LOG(SqlFunctions.class, "log", long.class, long.class),
LOG2(SqlFunctions.class, "log2", long.class),
SEC(SqlFunctions.class, "sec", double.class),
SECH(SqlFunctions.class, "sech", double.class),
SIGN(SqlFunctions.class, "sign", long.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 @@ -2783,6 +2783,7 @@ In the following:
| b f s | LENGTH(string) | Equivalent to `CHAR_LENGTH(string)`
| h s | LEVENSHTEIN(string1, string2) | Returns the Levenshtein distance between *string1* and *string2*
| b | LOG(numeric1 [, numeric2 ]) | Returns the logarithm of *numeric1* to base *numeric2*, or base e if *numeric2* is not present
| m s | LOG2(numeric) | Returns the base 2 logarithm of *numeric*
| b o s | LPAD(string, length [, pattern ]) | Returns a string or bytes value that consists of *string* prepended to *length* with *pattern*
| b | TO_BASE32(string) | Converts the *string* to base-32 encoded form and returns an encoded string
| b | FROM_BASE32(string) | Returns the decoded result of a base-32 *string* as a string
Expand Down
37 changes: 37 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 @@ -6243,6 +6243,43 @@ void checkRegexpExtract(SqlOperatorFixture f0, FunctionAlias functionAlias) {
f.checkNull("log(10, cast(null as real))");
}

/** Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-6224">[CALCITE-6224]
* Add LOG2 function (enabled in MYSQL, Spark library)</a>. */
@Test void testLog2Func() {
final SqlOperatorFixture f0 = fixture();
f0.checkFails("^log2(4)^",
"No match found for function signature LOG2\\(<NUMERIC>\\)", false);
f0.setFor(SqlLibraryOperators.LOG2);
final Consumer<SqlOperatorFixture> consumer = f -> {
f.checkScalarApprox("log2(2)", "DOUBLE",
isWithin(1.0, 0.000001));
f.checkScalarApprox("log2(4)", "DOUBLE",
isWithin(2.0, 0.000001));
f.checkScalarApprox("log2(65536)", "DOUBLE",
isWithin(16.0, 0.000001));
f.checkScalarApprox("log2(2.0/3)", "DOUBLE",
isWithin(-0.5849625007211561, 0.000001));
f.checkScalarApprox("log2(4.0/3)", "DOUBLE",
isWithin(0.4150374992788435, 0.000001));
f.checkScalarApprox("log2(0.5)", "DOUBLE",
isWithin(-1.0, 0.000001));
f.checkScalarApprox("log2(cast(10e8 as double))", "DOUBLE",
isWithin(29.897352853986263, 0.000001));
f.checkScalarApprox("log2(cast(10e8 as float))", "DOUBLE",
isWithin(29.897352853986263, 0.000001));
f.checkScalarApprox("log2(1e+52)", "DOUBLE",
isWithin(172.74026093414284, 0.000001));
f.checkNull("log2(0)");
f.checkNull("log2(-2)");
f.checkNull("log2(+0.0)");
f.checkNull("log2(-0.0)");
f.checkNull("log2(null)");
f.checkNull("log2(cast(null as real))");
};
f0.forEachLibrary(list(SqlLibrary.MYSQL, SqlLibrary.SPARK), consumer);
}

@Test void testRandFunc() {
final SqlOperatorFixture f = fixture();
f.setFor(SqlStdOperatorTable.RAND, VmName.EXPAND);
Expand Down

0 comments on commit c546d4a

Please sign in to comment.