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
;