From 3ea6c5ca0838e38558dbb3add462df400643600a Mon Sep 17 00:00:00 2001 From: "opensearch-trigger-bot[bot]" <98922864+opensearch-trigger-bot[bot]@users.noreply.github.com> Date: Fri, 17 Mar 2023 09:47:51 -0700 Subject: [PATCH] Added SIGNUM function to V2 engine (#1429) (#1442) * Added SIGNUM function to V2 engine (#241) * Added SIGNUM function to V2 engine, updated documentation, added unit/IT tests Signed-off-by: Matthew Wells * fixed merge mistake Signed-off-by: Matthew Wells * fixed merging error Signed-off-by: Matthew Wells --------- Signed-off-by: Matthew Wells (cherry picked from commit 6496692da55a74603eb04cce1a6821836bed4406) Co-authored-by: Matthew Wells --- .../org/opensearch/sql/expression/DSL.java | 5 ++ .../function/BuiltinFunctionName.java | 1 + .../arthmetic/MathematicalFunction.java | 13 ++++ .../arthmetic/MathematicalFunctionTest.java | 78 +++++++++++++++++++ docs/user/dql/functions.rst | 18 ++++- .../sql/sql/MathematicalFunctionIT.java | 13 +++- sql/src/main/antlr/OpenSearchSQLParser.g4 | 2 +- 7 files changed, 124 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/opensearch/sql/expression/DSL.java b/core/src/main/java/org/opensearch/sql/expression/DSL.java index b4f7b6a574..55471baa0f 100644 --- a/core/src/main/java/org/opensearch/sql/expression/DSL.java +++ b/core/src/main/java/org/opensearch/sql/expression/DSL.java @@ -262,8 +262,13 @@ public static FunctionExpression sign(Expression... expressions) { return compile(FunctionProperties.None, BuiltinFunctionName.SIGN, expressions); } + public static FunctionExpression signum(Expression... expressions) { + return compile(FunctionProperties.None, BuiltinFunctionName.SIGNUM, expressions); + } + public static FunctionExpression sinh(Expression... expressions) { return compile(FunctionProperties.None, BuiltinFunctionName.SINH, expressions); + } public static FunctionExpression sqrt(Expression... expressions) { diff --git a/core/src/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java b/core/src/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java index ea6cee91f9..371192149b 100644 --- a/core/src/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java +++ b/core/src/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java @@ -41,6 +41,7 @@ public enum BuiltinFunctionName { RINT(FunctionName.of("rint")), ROUND(FunctionName.of("round")), SIGN(FunctionName.of("sign")), + SIGNUM(FunctionName.of("signum")), SINH(FunctionName.of("sinh")), SQRT(FunctionName.of("sqrt")), CBRT(FunctionName.of("cbrt")), diff --git a/core/src/main/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunction.java b/core/src/main/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunction.java index 929839be4d..c186cec0a3 100644 --- a/core/src/main/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunction.java +++ b/core/src/main/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunction.java @@ -71,6 +71,7 @@ public static void register(BuiltinFunctionRepository repository) { repository.register(rint()); repository.register(round()); repository.register(sign()); + repository.register(signum()); repository.register(sinh()); repository.register(sqrt()); repository.register(truncate()); @@ -444,6 +445,18 @@ private static DefaultFunctionResolver sign() { v -> new ExprIntegerValue(Math.signum(v.doubleValue())), INTEGER); } + /** + * Definition of signum(x) function. + * Returns the sign of the argument as -1.0, 0, or 1.0 + * depending on whether x is negative, zero, or positive + * The supported signature is + * BYTE/SHORT/INTEGER/LONG/FLOAT/DOUBLE -> INTEGER + */ + private static DefaultFunctionResolver signum() { + return baseMathFunction(BuiltinFunctionName.SIGNUM.getName(), + v -> new ExprIntegerValue(Math.signum(v.doubleValue())), INTEGER); + } + /** * Definition of sinh(x) function. * Returns the hyperbolix sine of x, defined as (((e^x) - (e^(-x))) / 2) diff --git a/core/src/test/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunctionTest.java b/core/src/test/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunctionTest.java index 80b4aa7e6e..7099475b64 100644 --- a/core/src/test/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunctionTest.java +++ b/core/src/test/java/org/opensearch/sql/expression/operator/arthmetic/MathematicalFunctionTest.java @@ -1729,6 +1729,84 @@ public void sign_missing_value() { assertTrue(sign.valueOf(valueEnv()).isMissing()); } + /** + * Test signum with byte value. + */ + @ParameterizedTest(name = "signum({0})") + @ValueSource(bytes = {2, 0, -2}) + public void signum_bytes_value(Byte value) { + FunctionExpression signum = DSL.signum(DSL.literal(value)); + assertThat( + signum.valueOf(valueEnv()), + allOf(hasType(INTEGER), hasValue((int) Math.signum(value)))); + assertEquals(String.format("signum(%s)", value), signum.toString()); + } + + /** + * Test signum with short value. + */ + @ParameterizedTest(name = "signum({0})") + @ValueSource(shorts = {2, 0, -2}) + public void signum_short_value(Short value) { + FunctionExpression signum = DSL.signum(DSL.literal(value)); + assertThat( + signum.valueOf(valueEnv()), + allOf(hasType(INTEGER), hasValue((int) Math.signum(value)))); + assertEquals(String.format("signum(%s)", value), signum.toString()); + } + + /** + * Test signum with integer value. + */ + @ParameterizedTest(name = "signum({0})") + @ValueSource(ints = {2, 0, -2}) + public void signum_int_value(Integer value) { + FunctionExpression signum = DSL.signum(DSL.literal(value)); + assertThat( + signum.valueOf(valueEnv()), + allOf(hasType(INTEGER), hasValue((int) Math.signum(value)))); + assertEquals(String.format("signum(%s)", value), signum.toString()); + } + + /** + * Test signum with long value. + */ + @ParameterizedTest(name = "signum({0})") + @ValueSource(longs = {2L, 0L, -2L}) + public void signum_long_value(Long value) { + FunctionExpression signum = DSL.signum(DSL.literal(value)); + assertThat( + signum.valueOf(valueEnv()), + allOf(hasType(INTEGER), hasValue((int) Math.signum(value)))); + assertEquals(String.format("signum(%s)", value), signum.toString()); + } + + /** + * Test signum with float value. + */ + @ParameterizedTest(name = "signum({0})") + @ValueSource(floats = {2F, 0F, -2F}) + public void signum_float_value(Float value) { + FunctionExpression signum = DSL.signum(DSL.literal(value)); + assertThat( + signum.valueOf(valueEnv()), + allOf(hasType(INTEGER), hasValue((int) Math.signum(value)))); + assertEquals(String.format("signum(%s)", value), signum.toString()); + } + + /** + * Test signum with double value. + */ + @ParameterizedTest(name = "signum({0})") + @ValueSource(doubles = {2, 0, -2}) + public void signum_double_value(Double value) { + FunctionExpression signum = DSL.signum(DSL.literal(value)); + assertThat( + signum.valueOf(valueEnv()), + allOf(hasType(INTEGER), hasValue((int) Math.signum(value)))); + assertEquals(String.format("signum(%s)", value), signum.toString()); + } + /** * Test sinh with byte value. */ diff --git a/docs/user/dql/functions.rst b/docs/user/dql/functions.rst index 065ac23d37..ef79e56bc2 100644 --- a/docs/user/dql/functions.rst +++ b/docs/user/dql/functions.rst @@ -840,9 +840,23 @@ SIGNUM Description >>>>>>>>>>> -Specifications: +Usage: Returns the sign of the argument as -1, 0, or 1, depending on whether the number is negative, zero, or positive + +Argument type: BYTE/SHORT/INTEGER/LONG/FLOAT/DOUBLE + +Return type: INTEGER + +Synonyms: `SIGN`_ -1. SIGNUM(NUMBER T) -> T +Example:: + + os> SELECT SIGNUM(1), SIGNUM(0), SIGNUM(-1.1) + fetched rows / total rows = 1/1 + +-------------+-------------+----------------+ + | SIGNUM(1) | SIGNUM(0) | SIGNUM(-1.1) | + |-------------+-------------+----------------| + | 1 | 0 | -1 | + +-------------+-------------+----------------+ SIN diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/MathematicalFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/MathematicalFunctionIT.java index b4fcf8e4f9..c1aedc459f 100644 --- a/integ-test/src/test/java/org/opensearch/sql/sql/MathematicalFunctionIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/sql/MathematicalFunctionIT.java @@ -152,9 +152,6 @@ public void testRound() throws IOException { verifyDataRows(result, rows(-4.0)); } - /** - * Test sign function with double value. - */ @Test public void testSign() throws IOException { JSONObject result = executeQuery("select sign(1.1)"); @@ -167,6 +164,16 @@ public void testSign() throws IOException { } @Test + public void testSignum() throws IOException { + JSONObject result = executeQuery("select signum(1.1)"); + verifySchema(result, schema("signum(1.1)", null, "integer")); + verifyDataRows(result, rows(1)); + + result = executeQuery("select signum(-1.1)"); + verifySchema(result, schema("signum(-1.1)", null, "integer")); + verifyDataRows(result, rows(-1)); + } + public void testSinh() throws IOException { JSONObject result = executeQuery("select sinh(1)"); verifySchema(result, schema("sinh(1)", null, "double")); diff --git a/sql/src/main/antlr/OpenSearchSQLParser.g4 b/sql/src/main/antlr/OpenSearchSQLParser.g4 index 5741e491ed..743dfadb82 100644 --- a/sql/src/main/antlr/OpenSearchSQLParser.g4 +++ b/sql/src/main/antlr/OpenSearchSQLParser.g4 @@ -451,7 +451,7 @@ aggregationFunctionName mathematicalFunctionName : ABS | CBRT | CEIL | CEILING | CONV | CRC32 | E | EXP | EXPM1 | FLOOR | LN | LOG | LOG10 | LOG2 | MOD | PI | POW | POWER - | RAND | RINT | ROUND | SIGN | SQRT | TRUNCATE + | RAND | RINT | ROUND | SIGN | SIGNUM | SQRT | TRUNCATE | trigonometricFunctionName | arithmeticFunctionName ;