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

Commit 13afbe5

Browse files
authored
Support mathematical functions ceil/ceiling, exp, floor, ln, log (#540)
* Support ceil/ceiling, exact, exp, floor, ln, log functions * Added integ test cases * Set the registration of function name to be case insensitive * Function signature changed consistent with mysql * Function signature changed consistent with mysql * Function signature changed consistent with mysql * Added comparison test cases * changed matcher to closeto * added closeTo matcher * Extracted method to compile functions in DSL * update
1 parent 4b139c4 commit 13afbe5

File tree

19 files changed

+1388
-333
lines changed

19 files changed

+1388
-333
lines changed

core/src/main/java/com/amazon/opendistroforelasticsearch/sql/expression/DSL.java

Lines changed: 63 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
import com.amazon.opendistroforelasticsearch.sql.data.model.ExprValueUtils;
2020
import com.amazon.opendistroforelasticsearch.sql.data.type.ExprType;
2121
import com.amazon.opendistroforelasticsearch.sql.expression.aggregation.Aggregator;
22-
import com.amazon.opendistroforelasticsearch.sql.expression.env.Environment;
2322
import com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionName;
2423
import com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionRepository;
24+
import com.amazon.opendistroforelasticsearch.sql.expression.function.FunctionName;
2525
import java.util.Arrays;
2626
import lombok.RequiredArgsConstructor;
2727

@@ -62,102 +62,124 @@ public static ReferenceExpression ref(String ref, ExprType type) {
6262
}
6363

6464
public FunctionExpression abs(Expression... expressions) {
65-
return (FunctionExpression)
66-
repository.compile(BuiltinFunctionName.ABS.getName(), Arrays.asList(expressions));
65+
return function(BuiltinFunctionName.ABS, expressions);
66+
}
67+
68+
public FunctionExpression ceil(Expression... expressions) {
69+
return function(BuiltinFunctionName.CEIL, expressions);
70+
}
71+
72+
public FunctionExpression ceiling(Expression... expressions) {
73+
return function(BuiltinFunctionName.CEILING, expressions);
74+
}
75+
76+
public FunctionExpression exp(Expression... expressions) {
77+
return function(BuiltinFunctionName.EXP, expressions);
78+
}
79+
80+
public FunctionExpression floor(Expression... expressions) {
81+
return function(BuiltinFunctionName.FLOOR, expressions);
82+
}
83+
84+
public FunctionExpression ln(Expression... expressions) {
85+
return function(BuiltinFunctionName.LN, expressions);
86+
}
87+
88+
public FunctionExpression log(Expression... expressions) {
89+
return function(BuiltinFunctionName.LOG, expressions);
90+
}
91+
92+
public FunctionExpression log10(Expression... expressions) {
93+
return function(BuiltinFunctionName.LOG10, expressions);
94+
}
95+
96+
public FunctionExpression log2(Expression... expressions) {
97+
return function(BuiltinFunctionName.LOG2, expressions);
6798
}
6899

69100
public FunctionExpression add(Expression... expressions) {
70-
return (FunctionExpression)
71-
repository.compile(BuiltinFunctionName.ADD.getName(), Arrays.asList(expressions));
101+
return function(BuiltinFunctionName.ADD, expressions);
72102
}
73103

74104
public FunctionExpression subtract(Expression... expressions) {
75-
return (FunctionExpression)
76-
repository.compile(BuiltinFunctionName.SUBTRACT.getName(), Arrays.asList(expressions));
105+
return function(BuiltinFunctionName.SUBTRACT, expressions);
77106
}
78107

79108
public FunctionExpression multiply(Expression... expressions) {
80-
return (FunctionExpression)
81-
repository.compile(BuiltinFunctionName.MULTIPLY.getName(), Arrays.asList(expressions));
109+
return function(BuiltinFunctionName.MULTIPLY, expressions);
82110
}
83111

84112
public FunctionExpression divide(Expression... expressions) {
85-
return (FunctionExpression)
86-
repository.compile(BuiltinFunctionName.DIVIDE.getName(), Arrays.asList(expressions));
113+
return function(BuiltinFunctionName.DIVIDE, expressions);
87114
}
88115

89116
public FunctionExpression module(Expression... expressions) {
90-
return (FunctionExpression)
91-
repository.compile(BuiltinFunctionName.MODULES.getName(), Arrays.asList(expressions));
117+
return function(BuiltinFunctionName.MODULES, expressions);
92118
}
93119

94120
public FunctionExpression and(Expression... expressions) {
95-
return (FunctionExpression)
96-
repository.compile(BuiltinFunctionName.AND.getName(), Arrays.asList(expressions));
121+
return function(BuiltinFunctionName.AND, expressions);
97122
}
98123

99124
public FunctionExpression or(Expression... expressions) {
100-
return (FunctionExpression)
101-
repository.compile(BuiltinFunctionName.OR.getName(), Arrays.asList(expressions));
125+
return function(BuiltinFunctionName.OR, expressions);
102126
}
103127

104128
public FunctionExpression xor(Expression... expressions) {
105-
return (FunctionExpression)
106-
repository.compile(BuiltinFunctionName.XOR.getName(), Arrays.asList(expressions));
129+
return function(BuiltinFunctionName.XOR, expressions);
107130
}
108131

109132
public FunctionExpression not(Expression... expressions) {
110-
return (FunctionExpression)
111-
repository.compile(BuiltinFunctionName.NOT.getName(), Arrays.asList(expressions));
133+
return function(BuiltinFunctionName.NOT, expressions);
112134
}
113135

114136
public FunctionExpression equal(Expression... expressions) {
115-
return (FunctionExpression)
116-
repository.compile(BuiltinFunctionName.EQUAL.getName(), Arrays.asList(expressions));
137+
return function(BuiltinFunctionName.EQUAL, expressions);
117138
}
118139

119140
public FunctionExpression notequal(Expression... expressions) {
120-
return (FunctionExpression)
121-
repository.compile(BuiltinFunctionName.NOTEQUAL.getName(), Arrays.asList(expressions));
141+
return function(BuiltinFunctionName.NOTEQUAL, expressions);
122142
}
123143

124144
public FunctionExpression less(Expression... expressions) {
125-
return (FunctionExpression)
126-
repository.compile(BuiltinFunctionName.LESS.getName(), Arrays.asList(expressions));
145+
return function(BuiltinFunctionName.LESS, expressions);
127146
}
128147

129148
public FunctionExpression lte(Expression... expressions) {
130-
return (FunctionExpression)
131-
repository.compile(BuiltinFunctionName.LTE.getName(), Arrays.asList(expressions));
149+
return function(BuiltinFunctionName.LTE, expressions);
132150
}
133151

134152
public FunctionExpression greater(Expression... expressions) {
135-
return (FunctionExpression)
136-
repository.compile(BuiltinFunctionName.GREATER.getName(), Arrays.asList(expressions));
153+
return function(BuiltinFunctionName.GREATER, expressions);
137154
}
138155

139156
public FunctionExpression gte(Expression... expressions) {
140-
return (FunctionExpression)
141-
repository.compile(BuiltinFunctionName.GTE.getName(), Arrays.asList(expressions));
157+
return function(BuiltinFunctionName.GTE, expressions);
142158
}
143159

144160
public FunctionExpression like(Expression... expressions) {
145-
return (FunctionExpression)
146-
repository.compile(BuiltinFunctionName.LIKE.getName(), Arrays.asList(expressions));
161+
return function(BuiltinFunctionName.LIKE, expressions);
147162
}
148163

149164
public Aggregator avg(Expression... expressions) {
150-
return (Aggregator)
151-
repository.compile(BuiltinFunctionName.AVG.getName(), Arrays.asList(expressions));
165+
return aggregate(BuiltinFunctionName.AVG, expressions);
152166
}
153167

154168
public Aggregator sum(Expression... expressions) {
155-
return (Aggregator)
156-
repository.compile(BuiltinFunctionName.SUM.getName(), Arrays.asList(expressions));
169+
return aggregate(BuiltinFunctionName.SUM, expressions);
157170
}
158171

159172
public Aggregator count(Expression... expressions) {
160-
return (Aggregator)
161-
repository.compile(BuiltinFunctionName.COUNT.getName(), Arrays.asList(expressions));
173+
return aggregate(BuiltinFunctionName.COUNT, expressions);
174+
}
175+
176+
private FunctionExpression function(BuiltinFunctionName functionName, Expression... expressions) {
177+
return (FunctionExpression) repository.compile(
178+
functionName.getName(), Arrays.asList(expressions));
179+
}
180+
181+
private Aggregator aggregate(BuiltinFunctionName functionName, Expression... expressions) {
182+
return (Aggregator) repository.compile(
183+
functionName.getName(), Arrays.asList(expressions));
162184
}
163185
}

core/src/main/java/com/amazon/opendistroforelasticsearch/sql/expression/config/ExpressionConfig.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import com.amazon.opendistroforelasticsearch.sql.expression.aggregation.AggregatorFunction;
2020
import com.amazon.opendistroforelasticsearch.sql.expression.function.BuiltinFunctionRepository;
2121
import com.amazon.opendistroforelasticsearch.sql.expression.operator.arthmetic.ArithmeticFunction;
22-
import com.amazon.opendistroforelasticsearch.sql.expression.operator.arthmetic.UnaryFunction;
22+
import com.amazon.opendistroforelasticsearch.sql.expression.operator.arthmetic.MathematicalFunction;
2323
import com.amazon.opendistroforelasticsearch.sql.expression.operator.predicate.BinaryPredicateOperator;
2424
import com.amazon.opendistroforelasticsearch.sql.expression.operator.predicate.UnaryPredicateOperator;
2525
import java.util.HashMap;
@@ -40,7 +40,7 @@ public BuiltinFunctionRepository functionRepository() {
4040
new BuiltinFunctionRepository(new HashMap<>());
4141
ArithmeticFunction.register(builtinFunctionRepository);
4242
BinaryPredicateOperator.register(builtinFunctionRepository);
43-
UnaryFunction.register(builtinFunctionRepository);
43+
MathematicalFunction.register(builtinFunctionRepository);
4444
UnaryPredicateOperator.register(builtinFunctionRepository);
4545
AggregatorFunction.register(builtinFunctionRepository);
4646
return builtinFunctionRepository;

core/src/main/java/com/amazon/opendistroforelasticsearch/sql/expression/function/BuiltinFunctionName.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,22 @@
1212
@Getter
1313
@RequiredArgsConstructor
1414
public enum BuiltinFunctionName {
15+
/**
16+
* Mathematical Functions.
17+
*/
1518
ABS(FunctionName.of("abs")),
19+
CEIL(FunctionName.of("ceil")),
20+
CEILING(FunctionName.of("ceiling")),
21+
EXP(FunctionName.of("exp")),
22+
FLOOR(FunctionName.of("floor")),
23+
LN(FunctionName.of("ln")),
24+
LOG(FunctionName.of("log")),
25+
LOG10(FunctionName.of("log10")),
26+
LOG2(FunctionName.of("log2")),
27+
28+
/**
29+
* Text Functions.
30+
*/
1631
TOSTRING(FunctionName.of("tostring")),
1732

1833
/**

core/src/main/java/com/amazon/opendistroforelasticsearch/sql/expression/function/FunctionName.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public class FunctionName {
2929
private final String functionName;
3030

3131
public static FunctionName of(String functionName) {
32-
return new FunctionName(functionName);
32+
return new FunctionName(functionName.toLowerCase());
3333
}
3434

3535
@Override

core/src/main/java/com/amazon/opendistroforelasticsearch/sql/expression/operator/OperatorUtils.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,57 @@ public String toString() {
104104
};
105105
}
106106

107+
/**
108+
* Construct {@link FunctionBuilder} which call function with arguments produced by observer1 and
109+
* observer2 In general, if any operand evaluates to a MISSING value, the enclosing operator will
110+
* return MISSING; if none of operands evaluates to a MISSING value but there is an operand
111+
* evaluates to a NULL value, the enclosing operator will return NULL.
112+
*
113+
* @param functionName function name
114+
* @param function {@link BiFunction}
115+
* @param observer1 extract the value of type T from the first argument
116+
* @param observer2 extract the value of type U from the second argument
117+
* @param returnType return type
118+
* @param <T> the type of the first argument to the function
119+
* @param <U> the type of the second argument to the function
120+
* @param <R> the type of the result of the function
121+
* @return {@link FunctionBuilder}
122+
*/
123+
public static <T, U, R> FunctionBuilder doubleArgFunc(
124+
FunctionName functionName,
125+
BiFunction<T, U, R> function,
126+
Function<ExprValue, T> observer1,
127+
Function<ExprValue, U> observer2,
128+
ExprType returnType) {
129+
return arguments ->
130+
new FunctionExpression(functionName, arguments) {
131+
@Override
132+
public ExprValue valueOf(Environment<Expression, ExprValue> env) {
133+
ExprValue arg1 = arguments.get(0).valueOf(env);
134+
ExprValue arg2 = arguments.get(1).valueOf(env);
135+
if (arg1.isMissing() || arg2.isMissing()) {
136+
return ExprValueUtils.missingValue();
137+
} else if (arg1.isNull() || arg2.isNull()) {
138+
return ExprValueUtils.nullValue();
139+
} else {
140+
return ExprValueUtils.fromObjectValue(
141+
function.apply(observer1.apply(arg1), observer2.apply(arg2)));
142+
}
143+
}
144+
145+
@Override
146+
public ExprType type() {
147+
return returnType;
148+
}
149+
150+
@Override
151+
public String toString() {
152+
return String.format("%s(%s, %s)", functionName, arguments.get(0).toString(), arguments
153+
.get(1).toString());
154+
}
155+
};
156+
}
157+
107158
/**
108159
* Construct {@link FunctionBuilder} which call function with arguments produced by observer In
109160
* general, if any operand evaluates to a MISSING value, the enclosing operator will return

0 commit comments

Comments
 (0)