diff --git a/core/src/main/java/org/opensearch/sql/calcite/utils/UserDefinedFunctionUtils.java b/core/src/main/java/org/opensearch/sql/calcite/utils/UserDefinedFunctionUtils.java index aac002f1943..dd4fc1a3611 100644 --- a/core/src/main/java/org/opensearch/sql/calcite/utils/UserDefinedFunctionUtils.java +++ b/core/src/main/java/org/opensearch/sql/calcite/utils/UserDefinedFunctionUtils.java @@ -220,6 +220,47 @@ public UDFOperandMetadata getOperandMetadata() { }; } + /** + * Adapt a static math function (e.g., Math.expm1, Math.rint) to a UserDefinedFunctionBuilder. + * This method generates a Calcite-compatible UDF by boxing the operand, converting it to a + * double, and then calling the corresponding method in {@link Math}. + * + *

It assumes the math method has the signature: {@code double method(double)}. This utility is + * specifically designed for single-operand Math methods. + * + * @param methodName the name of the static method in {@link Math} to be invoked + * @param returnTypeInference the return type inference of the UDF + * @param nullPolicy the null policy of the UDF + * @param operandMetadata type checker + * @return an adapted ImplementorUDF with the math method, which is a UserDefinedFunctionBuilder + */ + public static ImplementorUDF adaptMathFunctionToUDF( + String methodName, + SqlReturnTypeInference returnTypeInference, + NullPolicy nullPolicy, + UDFOperandMetadata operandMetadata) { + + NotNullImplementor implementor = + (translator, call, translatedOperands) -> { + Expression operand = translatedOperands.get(0); + operand = Expressions.box(operand); + operand = Expressions.call(operand, "doubleValue"); + return Expressions.call(Math.class, methodName, operand); + }; + + return new ImplementorUDF(implementor, nullPolicy) { + @Override + public SqlReturnTypeInference getReturnTypeInference() { + return returnTypeInference; + } + + @Override + public UDFOperandMetadata getOperandMetadata() { + return operandMetadata; + } + }; + } + public static List prependFunctionProperties( List operands, RexToLixTranslator translator) { List operandsWithProperties = new ArrayList<>(operands); diff --git a/core/src/main/java/org/opensearch/sql/expression/function/PPLBuiltinOperators.java b/core/src/main/java/org/opensearch/sql/expression/function/PPLBuiltinOperators.java index 6c2d0af8eba..d40acebd429 100644 --- a/core/src/main/java/org/opensearch/sql/expression/function/PPLBuiltinOperators.java +++ b/core/src/main/java/org/opensearch/sql/expression/function/PPLBuiltinOperators.java @@ -7,6 +7,7 @@ import static org.opensearch.sql.calcite.utils.UserDefinedFunctionUtils.adaptExprMethodToUDF; import static org.opensearch.sql.calcite.utils.UserDefinedFunctionUtils.adaptExprMethodWithPropertiesToUDF; +import static org.opensearch.sql.calcite.utils.UserDefinedFunctionUtils.adaptMathFunctionToUDF; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -104,6 +105,26 @@ public class PPLBuiltinOperators extends ReflectiveSqlOperatorTable { public static final SqlOperator SHA2 = CryptographicFunction.sha2().toUDF("SHA2"); public static final SqlOperator CIDRMATCH = new CidrMatchFunction().toUDF("CIDRMATCH"); + public static final SqlOperator COSH = + adaptMathFunctionToUDF( + "cosh", ReturnTypes.DOUBLE_FORCE_NULLABLE, NullPolicy.ANY, PPLOperandTypes.NUMERIC) + .toUDF("COSH"); + + public static final SqlOperator SINH = + adaptMathFunctionToUDF( + "sinh", ReturnTypes.DOUBLE_FORCE_NULLABLE, NullPolicy.ANY, PPLOperandTypes.NUMERIC) + .toUDF("SINH"); + + public static final SqlOperator RINT = + adaptMathFunctionToUDF( + "rint", ReturnTypes.DOUBLE_FORCE_NULLABLE, NullPolicy.ANY, PPLOperandTypes.NUMERIC) + .toUDF("RINT"); + + public static final SqlOperator EXPM1 = + adaptMathFunctionToUDF( + "expm1", ReturnTypes.DOUBLE_FORCE_NULLABLE, NullPolicy.ANY, PPLOperandTypes.NUMERIC) + .toUDF("EXPM1"); + // IP comparing functions public static final SqlOperator NOT_EQUALS_IP = CompareIpFunction.notEquals().toUDF("NOT_EQUALS_IP"); diff --git a/core/src/main/java/org/opensearch/sql/expression/function/PPLFuncImpTable.java b/core/src/main/java/org/opensearch/sql/expression/function/PPLFuncImpTable.java index dc4f195d6be..87679ca5e19 100644 --- a/core/src/main/java/org/opensearch/sql/expression/function/PPLFuncImpTable.java +++ b/core/src/main/java/org/opensearch/sql/expression/function/PPLFuncImpTable.java @@ -18,6 +18,7 @@ import static org.opensearch.sql.expression.function.BuiltinFunctionName.ACOS; import static org.opensearch.sql.expression.function.BuiltinFunctionName.ADD; import static org.opensearch.sql.expression.function.BuiltinFunctionName.ADDDATE; +import static org.opensearch.sql.expression.function.BuiltinFunctionName.ADDFUNCTION; import static org.opensearch.sql.expression.function.BuiltinFunctionName.ADDTIME; import static org.opensearch.sql.expression.function.BuiltinFunctionName.AND; import static org.opensearch.sql.expression.function.BuiltinFunctionName.ARRAY; @@ -37,6 +38,7 @@ import static org.opensearch.sql.expression.function.BuiltinFunctionName.CONV; import static org.opensearch.sql.expression.function.BuiltinFunctionName.CONVERT_TZ; import static org.opensearch.sql.expression.function.BuiltinFunctionName.COS; +import static org.opensearch.sql.expression.function.BuiltinFunctionName.COSH; import static org.opensearch.sql.expression.function.BuiltinFunctionName.COT; import static org.opensearch.sql.expression.function.BuiltinFunctionName.COUNT; import static org.opensearch.sql.expression.function.BuiltinFunctionName.CRC32; @@ -61,11 +63,13 @@ import static org.opensearch.sql.expression.function.BuiltinFunctionName.DAY_OF_YEAR; import static org.opensearch.sql.expression.function.BuiltinFunctionName.DEGREES; import static org.opensearch.sql.expression.function.BuiltinFunctionName.DIVIDE; +import static org.opensearch.sql.expression.function.BuiltinFunctionName.DIVIDEFUNCTION; import static org.opensearch.sql.expression.function.BuiltinFunctionName.E; import static org.opensearch.sql.expression.function.BuiltinFunctionName.EARLIEST; import static org.opensearch.sql.expression.function.BuiltinFunctionName.EQUAL; import static org.opensearch.sql.expression.function.BuiltinFunctionName.EXISTS; import static org.opensearch.sql.expression.function.BuiltinFunctionName.EXP; +import static org.opensearch.sql.expression.function.BuiltinFunctionName.EXPM1; import static org.opensearch.sql.expression.function.BuiltinFunctionName.EXTRACT; import static org.opensearch.sql.expression.function.BuiltinFunctionName.FILTER; import static org.opensearch.sql.expression.function.BuiltinFunctionName.FLOOR; @@ -137,6 +141,7 @@ import static org.opensearch.sql.expression.function.BuiltinFunctionName.MONTHNAME; import static org.opensearch.sql.expression.function.BuiltinFunctionName.MONTH_OF_YEAR; import static org.opensearch.sql.expression.function.BuiltinFunctionName.MULTIPLY; +import static org.opensearch.sql.expression.function.BuiltinFunctionName.MULTIPLYFUNCTION; import static org.opensearch.sql.expression.function.BuiltinFunctionName.MULTI_MATCH; import static org.opensearch.sql.expression.function.BuiltinFunctionName.NOT; import static org.opensearch.sql.expression.function.BuiltinFunctionName.NOTEQUAL; @@ -159,6 +164,7 @@ import static org.opensearch.sql.expression.function.BuiltinFunctionName.REPLACE; import static org.opensearch.sql.expression.function.BuiltinFunctionName.REVERSE; import static org.opensearch.sql.expression.function.BuiltinFunctionName.RIGHT; +import static org.opensearch.sql.expression.function.BuiltinFunctionName.RINT; import static org.opensearch.sql.expression.function.BuiltinFunctionName.ROUND; import static org.opensearch.sql.expression.function.BuiltinFunctionName.RTRIM; import static org.opensearch.sql.expression.function.BuiltinFunctionName.SECOND; @@ -167,8 +173,10 @@ import static org.opensearch.sql.expression.function.BuiltinFunctionName.SHA1; import static org.opensearch.sql.expression.function.BuiltinFunctionName.SHA2; import static org.opensearch.sql.expression.function.BuiltinFunctionName.SIGN; +import static org.opensearch.sql.expression.function.BuiltinFunctionName.SIGNUM; import static org.opensearch.sql.expression.function.BuiltinFunctionName.SIMPLE_QUERY_STRING; import static org.opensearch.sql.expression.function.BuiltinFunctionName.SIN; +import static org.opensearch.sql.expression.function.BuiltinFunctionName.SINH; import static org.opensearch.sql.expression.function.BuiltinFunctionName.SPAN; import static org.opensearch.sql.expression.function.BuiltinFunctionName.SQRT; import static org.opensearch.sql.expression.function.BuiltinFunctionName.STDDEV_POP; @@ -180,6 +188,7 @@ import static org.opensearch.sql.expression.function.BuiltinFunctionName.SUBSTRING; import static org.opensearch.sql.expression.function.BuiltinFunctionName.SUBTIME; import static org.opensearch.sql.expression.function.BuiltinFunctionName.SUBTRACT; +import static org.opensearch.sql.expression.function.BuiltinFunctionName.SUBTRACTFUNCTION; import static org.opensearch.sql.expression.function.BuiltinFunctionName.SUM; import static org.opensearch.sql.expression.function.BuiltinFunctionName.SYSDATE; import static org.opensearch.sql.expression.function.BuiltinFunctionName.TAKE; @@ -668,8 +677,11 @@ void populate() { registerOperator(OR, SqlStdOperatorTable.OR); registerOperator(NOT, SqlStdOperatorTable.NOT); registerOperator(ADD, SqlStdOperatorTable.PLUS); + registerOperator(ADDFUNCTION, SqlStdOperatorTable.PLUS); registerOperator(SUBTRACT, SqlStdOperatorTable.MINUS); + registerOperator(SUBTRACTFUNCTION, SqlStdOperatorTable.MINUS); registerOperator(MULTIPLY, SqlStdOperatorTable.MULTIPLY); + registerOperator(MULTIPLYFUNCTION, SqlStdOperatorTable.MULTIPLY); registerOperator(TRUNCATE, SqlStdOperatorTable.TRUNCATE); registerOperator(ASCII, SqlStdOperatorTable.ASCII); registerOperator(LENGTH, SqlStdOperatorTable.CHAR_LENGTH); @@ -699,6 +711,7 @@ void populate() { registerOperator(RAND, SqlStdOperatorTable.RAND); registerOperator(ROUND, SqlStdOperatorTable.ROUND); registerOperator(SIGN, SqlStdOperatorTable.SIGN); + registerOperator(SIGNUM, SqlStdOperatorTable.SIGN); registerOperator(SIN, SqlStdOperatorTable.SIN); registerOperator(CBRT, SqlStdOperatorTable.CBRT); registerOperator(IS_NOT_NULL, SqlStdOperatorTable.IS_NOT_NULL); @@ -725,6 +738,10 @@ void populate() { registerOperator(INTERNAL_REGEXP_REPLACE_3, SqlLibraryOperators.REGEXP_REPLACE_3); // Register PPL UDF operator + registerOperator(COSH, PPLBuiltinOperators.COSH); + registerOperator(SINH, PPLBuiltinOperators.SINH); + registerOperator(EXPM1, PPLBuiltinOperators.EXPM1); + registerOperator(RINT, PPLBuiltinOperators.RINT); registerOperator(SPAN, PPLBuiltinOperators.SPAN); registerOperator(E, PPLBuiltinOperators.E); registerOperator(CONV, PPLBuiltinOperators.CONV); @@ -733,6 +750,7 @@ void populate() { registerOperator(MODULUSFUNCTION, PPLBuiltinOperators.MOD); registerOperator(CRC32, PPLBuiltinOperators.CRC32); registerOperator(DIVIDE, PPLBuiltinOperators.DIVIDE); + registerOperator(DIVIDEFUNCTION, PPLBuiltinOperators.DIVIDE); registerOperator(SHA2, PPLBuiltinOperators.SHA2); registerOperator(CIDRMATCH, PPLBuiltinOperators.CIDRMATCH); registerOperator(INTERNAL_GROK, PPLBuiltinOperators.GROK); diff --git a/docs/user/ppl/functions/math.rst b/docs/user/ppl/functions/math.rst index 65f544461b1..2944f3fb8dc 100644 --- a/docs/user/ppl/functions/math.rst +++ b/docs/user/ppl/functions/math.rst @@ -15,7 +15,7 @@ ABS Description >>>>>>>>>>> -Usage: abs(x) calculate the abs x. +Usage: abs(x) calculates the abs x. Argument type: INTEGER/LONG/FLOAT/DOUBLE @@ -32,13 +32,113 @@ Example:: +---------+ +ADD +--- + +Description +>>>>>>>>>>> + +Usage: add(x, y) calculates x plus y. + +Argument type: INTEGER/LONG/FLOAT/DOUBLE, INTEGER/LONG/FLOAT/DOUBLE + +Return type: Wider number between x and y + +Synonyms: Addition Symbol (+) + +Example:: + + os> source=people | eval `ADD(2, 1)` = ADD(2, 1) | fields `ADD(2, 1)` + fetched rows / total rows = 1/1 + +-----------+ + | ADD(2, 1) | + |-----------| + | 3 | + +-----------+ + + +SUBTRACT +-------- + +Description +>>>>>>>>>>> + +Usage: subtract(x, y) calculates x minus y. + +Argument type: INTEGER/LONG/FLOAT/DOUBLE, INTEGER/LONG/FLOAT/DOUBLE + +Return type: Wider number between x and y + +Synonyms: Subtraction Symbol (-) + +Example:: + + os> source=people | eval `SUBTRACT(2, 1)` = SUBTRACT(2, 1) | fields `SUBTRACT(2, 1)` + fetched rows / total rows = 1/1 + +----------------+ + | SUBTRACT(2, 1) | + |----------------| + | 1 | + +----------------+ + + +MULTIPLY +-------- + +Description +>>>>>>>>>>> + +Usage: multiply(x, y) calculates the multiplication of x and y. + +Argument type: INTEGER/LONG/FLOAT/DOUBLE, INTEGER/LONG/FLOAT/DOUBLE + +Return type: Wider number between x and y. If y equals to 0, then returns NULL. + +Synonyms: Multiplication Symbol (\*) + +Example:: + + os> source=people | eval `MULTIPLY(2, 1)` = MULTIPLY(2, 1) | fields `MULTIPLY(2, 1)` + fetched rows / total rows = 1/1 + +----------------+ + | MULTIPLY(2, 1) | + |----------------| + | 2 | + +----------------+ + + +DIVIDE +------ + +Description +>>>>>>>>>>> + +Usage: divide(x, y) calculates x divided by y. + +Argument type: INTEGER/LONG/FLOAT/DOUBLE, INTEGER/LONG/FLOAT/DOUBLE + +Return type: Wider number between x and y + +Synonyms: Division Symbol (/) + +Example:: + + os> source=people | eval `DIVIDE(2, 1)` = DIVIDE(2, 1) | fields `DIVIDE(2, 1)` + fetched rows / total rows = 1/1 + +--------------+ + | DIVIDE(2, 1) | + |--------------| + | 2 | + +--------------+ + + ACOS ---- Description >>>>>>>>>>> -Usage: acos(x) calculate the arc cosine of x. Returns NULL if x is not in the range -1 to 1. +Usage: acos(x) calculates the arc cosine of x. Returns NULL if x is not in the range -1 to 1. Argument type: INTEGER/LONG/FLOAT/DOUBLE @@ -109,7 +209,7 @@ Description Usage: atan2(y, x) calculates the arc tangent of y / x, except that the signs of both arguments are used to determine the quadrant of the result. -Argument type: INTEGER/LONG/FLOAT/DOUBLE +Argument type: INTEGER/LONG/FLOAT/DOUBLE, INTEGER/LONG/FLOAT/DOUBLE Return type: DOUBLE @@ -194,7 +294,7 @@ COS Description >>>>>>>>>>> -Usage: cos(x) calculate the cosine of x, where x is given in radians. +Usage: cos(x) calculates the cosine of x, where x is given in radians. Argument type: INTEGER/LONG/FLOAT/DOUBLE @@ -211,13 +311,36 @@ Example:: +--------+ +COSH +---- + +Description +>>>>>>>>>>> + +Usage: cosh(x) calculates the hyperbolic cosine of x, defined as (((e^x) + (e^(-x))) / 2). + +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type: DOUBLE + +Example:: + + os> source=people | eval `COSH(2)` = COSH(2) | fields `COSH(2)` + fetched rows / total rows = 1/1 + +--------------------+ + | COSH(2) | + |--------------------| + | 3.7621956910836314 | + +--------------------+ + + COT --- Description >>>>>>>>>>> -Usage: cot(x) calculate the cotangent of x. Returns out-of-range error if x equals to 0. +Usage: cot(x) calculates the cotangent of x. Returns out-of-range error if x equals to 0. Argument type: INTEGER/LONG/FLOAT/DOUBLE @@ -324,6 +447,29 @@ Example:: +------------------+ +EXPM1 +----- + +Description +>>>>>>>>>>> + +Usage: expm1(NUMBER T) returns the exponential of T, minus 1. + +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type: DOUBLE + +Example:: + + os> source=people | eval `EXPM1(1)` = EXPM1(1) | fields `EXPM1(1)` + fetched rows / total rows = 1/1 + +-------------------+ + | EXPM1(1) | + |-------------------| + | 1.718281828459045 | + +-------------------+ + + FLOOR ----- @@ -471,7 +617,7 @@ Description Usage: MOD(n, m) calculates the remainder of the number n divided by m. -Argument type: INTEGER/LONG/FLOAT/DOUBLE +Argument type: INTEGER/LONG/FLOAT/DOUBLE, INTEGER/LONG/FLOAT/DOUBLE Return type: Wider type between types of n and m if m is nonzero value. If m equals to 0, then returns NULL. @@ -486,6 +632,29 @@ Example:: +-----------+-------------+ +MODULUS +------- + +Description +>>>>>>>>>>> + +Usage: MODULUS(n, m) calculates the remainder of the number n divided by m. + +Argument type: INTEGER/LONG/FLOAT/DOUBLE, INTEGER/LONG/FLOAT/DOUBLE + +Return type: Wider type between types of n and m if m is nonzero value. If m equals to 0, then returns NULL. + +Example:: + + os> source=people | eval `MODULUS(3, 2)` = MODULUS(3, 2), `MODULUS(3.1, 2)` = MODULUS(3.1, 2) | fields `MODULUS(3, 2)`, `MODULUS(3.1, 2)` + fetched rows / total rows = 1/1 + +---------------+-----------------+ + | MODULUS(3, 2) | MODULUS(3.1, 2) | + |---------------+-----------------| + | 1 | 1.1 | + +---------------+-----------------+ + + PI -- @@ -515,7 +684,7 @@ Description Usage: POW(x, y) calculates the value of x raised to the power of y. Bad inputs return NULL result. -Argument type: INTEGER/LONG/FLOAT/DOUBLE +Argument type: INTEGER/LONG/FLOAT/DOUBLE, INTEGER/LONG/FLOAT/DOUBLE Return type: DOUBLE @@ -540,7 +709,7 @@ Description Usage: POWER(x, y) calculates the value of x raised to the power of y. Bad inputs return NULL result. -Argument type: INTEGER/LONG/FLOAT/DOUBLE +Argument type: INTEGER/LONG/FLOAT/DOUBLE, INTEGER/LONG/FLOAT/DOUBLE Return type: DOUBLE @@ -652,13 +821,38 @@ Example:: +---------+---------+------------+ +SIGNUM +------ + +Description +>>>>>>>>>>> + +Usage: Returns the sign of the argument as -1, 0, or 1, depending on whether the number is negative, zero, or positive + +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type: INTEGER + +Synonyms: `SIGN` + +Example:: + + os> source=people | eval `SIGNUM(1)` = SIGNUM(1), `SIGNUM(0)` = SIGNUM(0), `SIGNUM(-1.1)` = SIGNUM(-1.1) | fields `SIGNUM(1)`, `SIGNUM(0)`, `SIGNUM(-1.1)` + fetched rows / total rows = 1/1 + +-----------+-----------+--------------+ + | SIGNUM(1) | SIGNUM(0) | SIGNUM(-1.1) | + |-----------+-----------+--------------| + | 1 | 0 | -1 | + +-----------+-----------+--------------+ + + SIN --- Description >>>>>>>>>>> -Usage: sin(x) calculate the sine of x, where x is given in radians. +Usage: sin(x) calculates the sine of x, where x is given in radians. Argument type: INTEGER/LONG/FLOAT/DOUBLE @@ -675,6 +869,29 @@ Example:: +--------+ +SINH +---- + +Description +>>>>>>>>>>> + +Usage: sinh(x) calculates the hyperbolic sine of x, defined as (((e^x) - (e^(-x))) / 2). + +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type: DOUBLE + +Example:: + + os> source=people | eval `SINH(2)` = SINH(2) | fields `SINH(2)` + fetched rows / total rows = 1/1 + +-------------------+ + | SINH(2) | + |-------------------| + | 3.626860407847019 | + +-------------------+ + + SQRT ---- @@ -725,3 +942,26 @@ Example:: | 2.0 | 2.1 | -3.0 | | 2.0 | 2.1 | -3.0 | +---------+-------------+-----------+ + + +RINT +---- + +Description +>>>>>>>>>>> + +Usage: rint(NUMBER T) returns T rounded to the closest whole integer number. + +Argument type: INTEGER/LONG/FLOAT/DOUBLE + +Return type: DOUBLE + +Example:: + + os> source=people | eval `RINT(1.7)` = RINT(1.7) | fields `RINT(1.7)` + fetched rows / total rows = 1/1 + +-----------+ + | RINT(1.7) | + |-----------| + | 2.0 | + +-----------+ \ No newline at end of file diff --git a/integ-test/src/test/java/org/opensearch/sql/ppl/MathematicalFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/ppl/MathematicalFunctionIT.java index 3b5f819061c..f53049fb5c3 100644 --- a/integ-test/src/test/java/org/opensearch/sql/ppl/MathematicalFunctionIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/ppl/MathematicalFunctionIT.java @@ -36,6 +36,38 @@ public void testAbs() throws IOException { verifyDataRows(result, rows(32), rows(36), rows(28), rows(33), rows(36), rows(39), rows(34)); } + @Test + public void testAddFunction() throws IOException { + JSONObject result = + executeQuery( + String.format("source=%s | where age = add(31, 1) | fields age", TEST_INDEX_BANK)); + verifyDataRows(result, rows(32)); + } + + @Test + public void testSubtractFunction() throws IOException { + JSONObject result = + executeQuery( + String.format("source=%s | where age = subtract(33, 1) | fields age", TEST_INDEX_BANK)); + verifyDataRows(result, rows(32)); + } + + @Test + public void testMultiplyFunction() throws IOException { + JSONObject result = + executeQuery( + String.format("source=%s | where age = multiply(16, 2) | fields age", TEST_INDEX_BANK)); + verifyDataRows(result, rows(32)); + } + + @Test + public void testDivideFunction() throws IOException { + JSONObject result = + executeQuery( + String.format("source=%s | where divide(age, 2) = 16 | fields age", TEST_INDEX_BANK)); + verifyDataRows(result, rows(32), rows(33)); + } + @Test public void testCeil() throws IOException { JSONObject result = @@ -93,6 +125,22 @@ public void testExp() throws IOException { rows(Math.exp(34))); } + @Test + public void testExpm1() throws IOException { + JSONObject result = + executeQuery(String.format("source=%s | eval f = expm1(age) | fields f", TEST_INDEX_BANK)); + verifySchema(result, schema("f", null, "double")); + verifyDataRows( + result, + rows(Math.expm1(32)), + rows(Math.expm1(36)), + rows(Math.expm1(28)), + rows(Math.expm1(33)), + rows(Math.expm1(36)), + rows(Math.expm1(39)), + rows(Math.expm1(34))); + } + @Test public void testFloor() throws IOException { JSONObject result = @@ -222,6 +270,15 @@ public void testMod() throws IOException { verifyDataRows(result, rows(2), rows(6), rows(8), rows(3), rows(6), rows(9), rows(4)); } + @Test + public void testModulus() throws IOException { + JSONObject result = + executeQuery( + String.format("source=%s | eval f = modulus(age, 10) | fields f", TEST_INDEX_BANK)); + verifySchema(result, schema("f", null, "int")); + verifyDataRows(result, rows(2), rows(6), rows(8), rows(3), rows(6), rows(9), rows(4)); + } + @Test public void testPow() throws IOException { JSONObject pow = @@ -282,6 +339,14 @@ public void testSign() throws IOException { verifyDataRows(result, rows(1), rows(1), rows(1), rows(1), rows(1), rows(1), rows(1)); } + @Test + public void testSignum() throws IOException { + JSONObject result = + executeQuery(String.format("source=%s | eval f = signum(age) | fields f", TEST_INDEX_BANK)); + verifySchema(result, schema("f", null, "int")); + verifyDataRows(result, rows(1), rows(1), rows(1), rows(1), rows(1), rows(1), rows(1)); + } + @Test public void testSqrt() throws IOException { JSONObject result = @@ -426,6 +491,14 @@ public void testCos() throws IOException { verifySome(result.getJSONArray("datarows"), rows(Math.cos(1.57))); } + @Test + public void testCosh() throws IOException { + JSONObject result = + executeQuery(String.format("source=%s | eval f = cosh(1.5) | fields f", TEST_INDEX_BANK)); + verifySchema(result, schema("f", null, "double")); + verifySome(result.getJSONArray("datarows"), rows(Math.cosh(1.5))); + } + @Test public void testCot() throws IOException { JSONObject result = @@ -458,4 +531,20 @@ public void testSin() throws IOException { verifySchema(result, schema("f", null, "double")); verifySome(result.getJSONArray("datarows"), rows(Math.sin(1.57))); } + + @Test + public void testSinh() throws IOException { + JSONObject result = + executeQuery(String.format("source=%s | eval f = sinh(1.5) | fields f", TEST_INDEX_BANK)); + verifySchema(result, schema("f", null, "double")); + verifySome(result.getJSONArray("datarows"), rows(Math.sinh(1.5))); + } + + @Test + public void testRint() throws IOException { + JSONObject result = + executeQuery(String.format("source=%s | eval f = rint(1.7) | fields f", TEST_INDEX_BANK)); + verifySchema(result, schema("f", null, "double")); + verifySome(result.getJSONArray("datarows"), rows(Math.rint(1.7))); + } } diff --git a/ppl/src/main/antlr/OpenSearchPPLLexer.g4 b/ppl/src/main/antlr/OpenSearchPPLLexer.g4 index c6b8809b9ab..312c34aa713 100644 --- a/ppl/src/main/antlr/OpenSearchPPLLexer.g4 +++ b/ppl/src/main/antlr/OpenSearchPPLLexer.g4 @@ -261,6 +261,10 @@ NTH: 'NTH'; NTILE: 'NTILE'; // BASIC FUNCTIONS +PLUS_FUCTION: 'ADD'; +MINUS_FUCTION: 'SUBTRACT'; +STAR_FUNCTION: 'MULTIPLY'; +DIVIDE_FUNCTION: 'DIVIDE'; ABS: 'ABS'; CBRT: 'CBRT'; CEIL: 'CEIL'; @@ -269,12 +273,14 @@ CONV: 'CONV'; CRC32: 'CRC32'; E: 'E'; EXP: 'EXP'; +EXPM1: 'EXPM1'; FLOOR: 'FLOOR'; LN: 'LN'; LOG: 'LOG'; LOG10: 'LOG10'; LOG2: 'LOG2'; MOD: 'MOD'; +MODULUS: 'MODULUS'; PI: 'PI'; POSITION: 'POSITION'; POW: 'POW'; @@ -284,6 +290,8 @@ ROUND: 'ROUND'; SIGN: 'SIGN'; SQRT: 'SQRT'; TRUNCATE: 'TRUNCATE'; +RINT: 'RINT'; +SIGNUM: 'SIGNUM'; // TRIGONOMETRIC FUNCTIONS ACOS: 'ACOS'; @@ -291,10 +299,12 @@ ASIN: 'ASIN'; ATAN: 'ATAN'; ATAN2: 'ATAN2'; COS: 'COS'; +COSH: 'COSH'; COT: 'COT'; DEGREES: 'DEGREES'; RADIANS: 'RADIANS'; SIN: 'SIN'; +SINH: 'SINH'; TAN: 'TAN'; // CRYPTOGRAPHIC FUNCTIONS diff --git a/ppl/src/main/antlr/OpenSearchPPLParser.g4 b/ppl/src/main/antlr/OpenSearchPPLParser.g4 index dcc71c1d061..018456f59d4 100644 --- a/ppl/src/main/antlr/OpenSearchPPLParser.g4 +++ b/ppl/src/main/antlr/OpenSearchPPLParser.g4 @@ -698,6 +698,10 @@ relevanceArgValue mathematicalFunctionName : ABS + | PLUS_FUCTION + | MINUS_FUCTION + | STAR_FUNCTION + | DIVIDE_FUNCTION | CBRT | CEIL | CEILING @@ -705,12 +709,14 @@ mathematicalFunctionName | CRC32 | E | EXP + | EXPM1 | FLOOR | LN | LOG | LOG10 | LOG2 | MOD + | MODULUS | PI | POW | POWER @@ -719,6 +725,8 @@ mathematicalFunctionName | SIGN | SQRT | TRUNCATE + | RINT + | SIGNUM | trigonometricFunctionName ; @@ -743,10 +751,12 @@ trigonometricFunctionName | ATAN | ATAN2 | COS + | COSH | COT | DEGREES | RADIANS | SIN + | SINH | TAN ;