From 83107e02df9ab4a0a15b6a040ac70a11de28a14c Mon Sep 17 00:00:00 2001 From: cip999 Date: Sun, 22 Aug 2021 16:36:32 +0200 Subject: [PATCH] Implemented "greatest" and "least" functions in old engine --- .../sql/legacy/SQLFunctionsIT.java | 4 +- .../sql/legacy/utils/SQLFunctions.java | 84 +++++++++++-------- 2 files changed, 51 insertions(+), 37 deletions(-) diff --git a/integ-test/src/test/java/com/amazon/opendistroforelasticsearch/sql/legacy/SQLFunctionsIT.java b/integ-test/src/test/java/com/amazon/opendistroforelasticsearch/sql/legacy/SQLFunctionsIT.java index aab2c20d5..37a447dbb 100644 --- a/integ-test/src/test/java/com/amazon/opendistroforelasticsearch/sql/legacy/SQLFunctionsIT.java +++ b/integ-test/src/test/java/com/amazon/opendistroforelasticsearch/sql/legacy/SQLFunctionsIT.java @@ -884,13 +884,13 @@ public void literalMultiField() throws Exception { public void greatestWithAliasAndStrings() throws Exception { JSONObject response = executeJdbcRequest("SELECT greatest(firstname, lastname) AS max " + - "FROM " + TEST_INDEX_ACCOUNT + " LIMIT 3"); + "FROM " + TEST_INDEX_ACCOUNT + " LIMIT 3"); verifyDataRows(response, rows("duke"), rows("hattie"), rows("nanette")); - } + } private SearchHits query(String query) throws IOException { final String rsp = executeQueryWithStringOutput(query); diff --git a/legacy/src/main/java/com/amazon/opendistroforelasticsearch/sql/legacy/utils/SQLFunctions.java b/legacy/src/main/java/com/amazon/opendistroforelasticsearch/sql/legacy/utils/SQLFunctions.java index 752f7252f..e036f160f 100644 --- a/legacy/src/main/java/com/amazon/opendistroforelasticsearch/sql/legacy/utils/SQLFunctions.java +++ b/legacy/src/main/java/com/amazon/opendistroforelasticsearch/sql/legacy/utils/SQLFunctions.java @@ -606,51 +606,52 @@ private Tuple binaryOpertator(String methodName, String operator private Tuple greatest(SQLExpr a, SQLExpr b) { String name = nextId("greatest"); - String name_a = extractName(a); - String name_b = extractName(b); - - String value_a = getPropertyOrStringValue(a); - String value_b = getPropertyOrStringValue(b); - - String nameString_a = nextId("string_a"); - String nameString_b = nextId("string_b"); - - return new Tuple<>(name, - scriptDeclare(a) + scriptDeclare(b) - + "def " + name + ";" - + String.format("if (%s instanceof Number) ", name_a) - + String.format("{%s = (%s >= %s ? %s : %s);} ", name, name_a, name_b, name_a, name_b) - + "else {" - + def(nameString_a, convertToString(value_a)) + ";" - + def(nameString_b, convertToString(value_b)) + ";" - + String.format("%s = (%s.compareTo(%s) >= 0 ? %s : %s);}", - name, nameString_a, nameString_b, value_a, value_b) - + name + " = " + name); + return comparisonFunctionTemplate(a, b, name, ">"); } private Tuple least(SQLExpr a, SQLExpr b) { String name = nextId("least"); - String name_a = extractName(a); - String name_b = extractName(b); + return comparisonFunctionTemplate(a, b, name, "<"); + } - String value_a = getPropertyOrStringValue(a); - String value_b = getPropertyOrStringValue(b); + private Tuple comparisonFunctionTemplate(SQLExpr a, SQLExpr b, + String name, String comparisonOperator) { + String value_a = (a instanceof SQLTextLiteralExpr + ? getPropertyOrStringValue(a) : getPropertyOrValue(a)); + String value_b = (b instanceof SQLTextLiteralExpr + ? getPropertyOrStringValue(b) : getPropertyOrValue(b)); String nameString_a = nextId("string_a"); String nameString_b = nextId("string_b"); - return new Tuple<>(name, - scriptDeclare(a) + scriptDeclare(b) - + "def " + name + ";" - + String.format("if (%s instanceof Number) ", name_a) - + String.format("{%s = (%s <= %s ? %s : %s);} ", name, name_a, name_b, name_a, name_b) - + "else {" - + def(nameString_a, convertToString(value_a)) + ";" - + def(nameString_b, convertToString(value_b)) + ";" - + String.format("%s = (%s.compareTo(%s) <= 0 ? %s : %s);}", - name, nameString_a, nameString_b, value_a, value_b) - + name + " = " + name); + String numberComparison = String.format("%s = (%s %s %s ? %s : %s);", + name, value_a, comparisonOperator, value_b, value_a, value_b); + String stringOrDateComparison = def(nameString_a, convertToString(value_a)) + ";" + + def(nameString_b, convertToString(value_b)) + ";" + + String.format("%s = (%s.compareTo(%s) %s 0 ? %s : %s);", + name, nameString_a, nameString_b, comparisonOperator, value_a, value_b); + + String definition = "def " + name + ";" + + String.format("if (%s) {%s = %s;} ", checkIfNull(a), name, value_b) + + String.format("else if (%s) {%s = %s;} ", checkIfNull(b), name, value_a) + + "else {"; + + if (isProperty(a) && isProperty(b)) { + definition += String.format("if (%s instanceof Number) {", value_a) + + numberComparison + + "} else {" + + stringOrDateComparison + + "} "; + } else if (a instanceof SQLNumericLiteralExpr || b instanceof SQLNumericLiteralExpr) { + definition += numberComparison; + } else { + definition += stringOrDateComparison; + } + + definition += String.format("} %s = %s", name, name); + + return new Tuple<>(name, definition); } private static boolean isProperty(SQLExpr expr) { @@ -661,6 +662,8 @@ private static boolean isProperty(SQLExpr expr) { private static String getPropertyOrValue(SQLExpr expr) { if (isProperty(expr)) { return doc(expr) + ".value"; + } else if (expr instanceof SQLNullExpr) { + return "null"; } else { return exprString(expr); } @@ -724,6 +727,17 @@ private static String convertType(SQLExpr script) { } + private static String checkIfNull(SQLExpr expr) { + if (isProperty(expr)) { + return doc(expr) + ".size() == 0 || " + getPropertyOrValue(expr) + " == null"; + } else if (expr instanceof SQLNullExpr) { + return "0 == 0"; + } + else { + return "0 == 1"; + } + } + private static String convertToString(String name) { return String.format("(%s instanceof String ? (String) %s : %s.toString())", name, name, name);