Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Commit

Permalink
Support mathematical functions: conv, crc32, mod, pow/power, round, s…
Browse files Browse the repository at this point in the history
…ign, sqrt, truncate (#577)

* supported conv, crc32, mod, pow/power, round, sign, sqrt, truncate functions

* update

* added test cases

* update

* added integ test cases

* update

* address comments

* updated java doc, change the behavior of divided by 0, updated sql function doc

* update

* update

* remove test cases that returns null value in doctest

* added instruction in null value result
  • Loading branch information
chloe-zh authored Jul 20, 2020
1 parent 0b57d93 commit 9d72867
Show file tree
Hide file tree
Showing 17 changed files with 1,796 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ public FunctionExpression ceiling(Expression... expressions) {
return function(BuiltinFunctionName.CEILING, expressions);
}

public FunctionExpression conv(Expression... expressions) {
return function(BuiltinFunctionName.CONV, expressions);
}

public FunctionExpression crc32(Expression... expressions) {
return function(BuiltinFunctionName.CRC32, expressions);
}

public FunctionExpression exp(Expression... expressions) {
return function(BuiltinFunctionName.EXP, expressions);
}
Expand All @@ -97,6 +105,34 @@ public FunctionExpression log2(Expression... expressions) {
return function(BuiltinFunctionName.LOG2, expressions);
}

public FunctionExpression mod(Expression... expressions) {
return function(BuiltinFunctionName.MOD, expressions);
}

public FunctionExpression pow(Expression... expressions) {
return function(BuiltinFunctionName.POW, expressions);
}

public FunctionExpression power(Expression... expressions) {
return function(BuiltinFunctionName.POWER, expressions);
}

public FunctionExpression round(Expression... expressions) {
return function(BuiltinFunctionName.ROUND, expressions);
}

public FunctionExpression sign(Expression... expressions) {
return function(BuiltinFunctionName.SIGN, expressions);
}

public FunctionExpression sqrt(Expression... expressions) {
return function(BuiltinFunctionName.SQRT, expressions);
}

public FunctionExpression truncate(Expression... expressions) {
return function(BuiltinFunctionName.TRUNCATE, expressions);
}

public FunctionExpression add(Expression... expressions) {
return function(BuiltinFunctionName.ADD, expressions);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,21 @@ public enum BuiltinFunctionName {
ABS(FunctionName.of("abs")),
CEIL(FunctionName.of("ceil")),
CEILING(FunctionName.of("ceiling")),
CONV(FunctionName.of("conv")),
CRC32(FunctionName.of("crc32")),
EXP(FunctionName.of("exp")),
FLOOR(FunctionName.of("floor")),
LN(FunctionName.of("ln")),
LOG(FunctionName.of("log")),
LOG10(FunctionName.of("log10")),
LOG2(FunctionName.of("log2")),
MOD(FunctionName.of("mod")),
POW(FunctionName.of("pow")),
POWER(FunctionName.of("power")),
ROUND(FunctionName.of("round")),
SIGN(FunctionName.of("sign")),
SQRT(FunctionName.of("sqrt")),
TRUNCATE(FunctionName.of("truncate")),

/**
* Text Functions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,60 @@

@UtilityClass
public class OperatorUtils {
/**
* Construct {@link FunctionBuilder} which call function with three arguments produced by
* observers.In general, if any operand evaluates to a MISSING value, the enclosing operator
* will return MISSING; if none of operands evaluates to a MISSING value but there is an
* operand evaluates to a NULL value, the enclosing operator will return NULL.
*
* @param functionName function name
* @param function {@link BiFunction}
* @param observer1 extract the value of type T from the first argument
* @param observer2 extract the value of type U from the first argument
* @param observer3 extract the value of type V from the first argument
* @param returnType return type
* @param <T> the type of the first argument to the function
* @param <U> the type of the second argument to the function
* @param <V> the type of the third argument to the function
* @param <R> the type of the result of the function
* @return {@link FunctionBuilder}
*/
public static <T, U, V, R> FunctionBuilder tripleArgFunc(
FunctionName functionName,
TriFunction<T, U, V, R> function,
Function<ExprValue, T> observer1,
Function<ExprValue, U> observer2,
Function<ExprValue, V> observer3,
ExprCoreType returnType) {
return arguments -> new FunctionExpression(functionName, arguments) {
@Override
public ExprValue valueOf(Environment<Expression, ExprValue> valueEnv) {
ExprValue arg1 = arguments.get(0).valueOf(valueEnv);
ExprValue arg2 = arguments.get(1).valueOf(valueEnv);
ExprValue arg3 = arguments.get(2).valueOf(valueEnv);
if (arg1.isMissing() || arg2.isMissing() || arg3.isMissing()) {
return ExprValueUtils.missingValue();
} else if (arg1.isNull() || arg2.isNull() || arg3.isNull()) {
return ExprValueUtils.nullValue();
} else {
return ExprValueUtils.fromObjectValue(
function.apply(observer1.apply(arg1), observer2.apply(arg2), observer3.apply(arg3)));
}
}

@Override
public ExprType type() {
return returnType;
}

@Override
public String toString() {
return String.format("%s(%s, %s, %s)", functionName, arguments.get(0).toString(), arguments
.get(1).toString(), arguments.get(2).toString());
}
};
}

/**
* Construct {@link FunctionBuilder} which call function with arguments produced by observer.
*
Expand Down Expand Up @@ -222,4 +276,8 @@ public String toString() {
*/
public static final BiPredicate<ExprValue, ExprValue> COMPARE_WITH_NULL_OR_MISSING =
(left, right) -> left.isMissing() || right.isMissing() || left.isNull() || right.isNull();

public interface TriFunction<T, U, V, R> {
R apply(T t, U u, V v);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,10 @@ private static FunctionResolver divide() {
return new FunctionResolver(
BuiltinFunctionName.DIVIDE.getName(),
scalarFunction(BuiltinFunctionName.DIVIDE.getName(),
(v1, v2) -> v1 / v2,
(v1, v2) -> v1 / v2,
(v1, v2) -> v1 / v2,
(v1, v2) -> v1 / v2)
(v1, v2) -> v2 == 0 ? null : v1 / v2,
(v1, v2) -> v2 == 0 ? null : v1 / v2,
(v1, v2) -> v2 == 0 ? null : v1 / v2,
(v1, v2) -> v2 == 0 ? null : v1 / v2)
);
}

Expand All @@ -106,10 +106,10 @@ private static FunctionResolver modules() {
return new FunctionResolver(
BuiltinFunctionName.MODULES.getName(),
scalarFunction(BuiltinFunctionName.MODULES.getName(),
(v1, v2) -> v1 % v2,
(v1, v2) -> v1 % v2,
(v1, v2) -> v1 % v2,
(v1, v2) -> v1 % v2)
(v1, v2) -> v2 == 0 ? null : v1 % v2,
(v1, v2) -> v2 == 0 ? null : v1 % v2,
(v1, v2) -> v2 == 0 ? null : v1 % v2,
(v1, v2) -> v2 == 0 ? null : v1 % v2)
);
}

Expand Down
Loading

0 comments on commit 9d72867

Please sign in to comment.