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

Commit

Permalink
Support CASE statement in one more grammer (#262)
Browse files Browse the repository at this point in the history
* Reassign condition expressions of the items in case express

* Added UT and IT

* Fixed the JDBC formatter for the case statement

* Added IT to test JDBC formatter for the case when statement

* Updated the release notes
  • Loading branch information
chloe-zh authored Nov 4, 2019
1 parent 5d59a18 commit 842c215
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 10 deletions.
7 changes: 6 additions & 1 deletion opendistro-elasticsearch-sql.release-notes
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
* Feature [#258](https://github.com/opendistro-for-elasticsearch/sql/issues/185): Elasticsearch 7.3.2 compatibility
* Feature [#201](https://github.com/opendistro-for-elasticsearch/sql/pull/201): Improve query verification by adding semantic analyzer

* Enhancement [#262](https://github.com/opendistro-for-elasticsearch/sql/pull/262): Support CASE statement in one more grammer
* Enhancement [#253](https://github.com/opendistro-for-elasticsearch/sql/pull/253): Support Cast function
* Enhancement [#260](https://github.com/opendistro-for-elasticsearch/sql/pull/260): Support string operators: ASCII, RTRIM, LTRIM, LOCATE, LENGTH, REPLACE
* Enhancement [#254](https://github.com/opendistro-for-elasticsearch/sql/issues/254): Support SELECT <number_literal>
* Enhancement [#251](https://github.com/opendistro-for-elasticsearch/sql/pull/251): Support number operators: POWER, ATAN2, COT, SIGN/SIGNUM
* Enhancement [#215](https://github.com/opendistro-for-elasticsearch/sql/issues215): Support ordinal in GROUP/ORDER BY clause
Expand All @@ -19,6 +22,7 @@
* Enhancement [#82](https://github.com/opendistro-for-elasticsearch/sql/issues/82): Pre-verification before actual execution of query
* Enhancement [#75](https://github.com/opendistro-for-elasticsearch/sql/issues/75): Support order by on SQL functions like SUM etc

* BugFix [#265](https://github.com/opendistro-for-elasticsearch/sql/pull/265): Fix the LOG function that delivered inaccurate result
* BugFix [#233](https://github.com/opendistro-for-elasticsearch/sql/issues/233): Function names are case-sensitive
* BugFix [#191](https://github.com/opendistro-for-elasticsearch/sql/issues/191): Fix new syntax check for LEFT JOIN on nested field and metadata field
* BugFix [#188](https://github.com/opendistro-for-elasticsearch/sql/issues/188): Having doesn't working on nested field
Expand All @@ -34,9 +38,10 @@
* BugFix [#121](https://github.com/opendistro-for-elasticsearch/sql/issues/121): Dot/period at start of index name fails to parse
* BugFix [#111](https://github.com/opendistro-for-elasticsearch/sql/issues/111): JDBC format of aggregation query with date_format adds unnecessary column bug

## 2019-10-15, Version 1.2.1 (Current)
## 2019-10-15, Version 1.2.1

### Notable changes

* Feature [#202](https://github.com/opendistro-for-elasticsearch/sql/issues/202): Elasticsearch 7.2.1 compatibility

## 2019-07-23, Version 1.2.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

package com.amazon.opendistroforelasticsearch.sql.executor.format;

import com.alibaba.druid.sql.ast.expr.SQLCaseExpr;
import com.alibaba.druid.sql.ast.expr.SQLCastExpr;
import com.amazon.opendistroforelasticsearch.sql.domain.Field;
import com.amazon.opendistroforelasticsearch.sql.domain.JoinSelect;
Expand Down Expand Up @@ -326,6 +327,8 @@ private Schema.Type fetchMethodReturnType(Field field) {
if (field.getExpression() instanceof SQLCastExpr) {
return SQLFunctions.getCastFunctionReturnType(
((SQLCastExpr) field.getExpression()).getDataType().getName());
} else if (field.getExpression() instanceof SQLCaseExpr) {
return Schema.Type.TEXT;
}
return SQLFunctions.getScriptFunctionReturnType(
((ScriptMethodField) field).getFunctionName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package com.amazon.opendistroforelasticsearch.sql.parser;

import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
import com.alibaba.druid.sql.ast.expr.SQLCaseExpr;
import com.alibaba.druid.sql.ast.expr.SQLNullExpr;
import com.amazon.opendistroforelasticsearch.sql.domain.Condition;
Expand Down Expand Up @@ -45,6 +47,16 @@ public CaseWhenParser(SQLCaseExpr caseExpr, String alias, String tableAlias) {
public String parse() throws SqlParseException {
List<String> result = new ArrayList<>();

if (caseExpr.getValueExpr() != null) {
for (SQLCaseExpr.Item item : caseExpr.getItems()) {
SQLExpr left = caseExpr.getValueExpr();
SQLExpr right = item.getConditionExpr();
SQLBinaryOpExpr conditionExpr = new SQLBinaryOpExpr(left, SQLBinaryOperator.Equality, right);
item.setConditionExpr(conditionExpr);
}
caseExpr.setValueExpr(null);
}

for (SQLCaseExpr.Item item : caseExpr.getItems()) {
SQLExpr conditionExpr = item.getConditionExpr();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,10 @@ public void parseWhere(SQLExpr expr, Where where) throws SqlParseException {

if (expr instanceof SQLBinaryOpExpr) {
SQLBinaryOpExpr bExpr = (SQLBinaryOpExpr) expr;
if (explanSpecialCondWithBothSidesAreLiterals(bExpr, where)) {
if (explainSpecialCondWithBothSidesAreLiterals(bExpr, where)) {
return;
}
if (explanSpecialCondWithBothSidesAreProperty(bExpr, where)) {
if (explainSpecialCondWithBothSidesAreProperty(bExpr, where)) {
return;
}
}
Expand All @@ -118,7 +118,7 @@ public void parseWhere(SQLExpr expr, Where where) throws SqlParseException {
parseWhere(((SQLNotExpr) expr).getExpr(), where);
negateWhere(where);
} else {
explanCond("AND", expr, where);
explainCond("AND", expr, where);
}
}

Expand All @@ -135,7 +135,7 @@ private void negateWhere(Where where) throws SqlParseException {
}

//some where conditions eg. 1=1 or 3>2 or 'a'='b'
private boolean explanSpecialCondWithBothSidesAreLiterals(SQLBinaryOpExpr bExpr, Where where)
private boolean explainSpecialCondWithBothSidesAreLiterals(SQLBinaryOpExpr bExpr, Where where)
throws SqlParseException {
if ((bExpr.getLeft() instanceof SQLNumericLiteralExpr || bExpr.getLeft() instanceof SQLCharExpr)
&& (bExpr.getRight() instanceof SQLNumericLiteralExpr || bExpr.getRight() instanceof SQLCharExpr)
Expand All @@ -150,14 +150,14 @@ private boolean explanSpecialCondWithBothSidesAreLiterals(SQLBinaryOpExpr bExpr,
+ " " + operator + " " + Util.expr2Object(bExpr.getRight(), "'"))
);

explanCond("AND", sqlMethodInvokeExpr, where);
explainCond("AND", sqlMethodInvokeExpr, where);
return true;
}
return false;
}

//some where conditions eg. field1=field2 or field1>field2
private boolean explanSpecialCondWithBothSidesAreProperty(SQLBinaryOpExpr bExpr, Where where)
private boolean explainSpecialCondWithBothSidesAreProperty(SQLBinaryOpExpr bExpr, Where where)
throws SqlParseException {
//join is not support
if ((bExpr.getLeft() instanceof SQLPropertyExpr || bExpr.getLeft() instanceof SQLIdentifierExpr)
Expand Down Expand Up @@ -185,7 +185,7 @@ private boolean explanSpecialCondWithBothSidesAreProperty(SQLBinaryOpExpr bExpr,
sqlMethodInvokeExpr.addParameter(new SQLCharExpr(
"doc['" + leftProperty + "'].value " + operator + " doc['" + rightProperty + "'].value"));

explanCond("AND", sqlMethodInvokeExpr, where);
explainCond("AND", sqlMethodInvokeExpr, where);
return true;
}
return false;
Expand Down Expand Up @@ -226,11 +226,11 @@ private void routeCond(SQLBinaryOpExpr bExpr, SQLExpr sub, Where where) throws S
parseWhere(((SQLNotExpr) sub).getExpr(), subWhere);
negateWhere(subWhere);
} else {
explanCond(bExpr.getOperator().name, sub, where);
explainCond(bExpr.getOperator().name, sub, where);
}
}

private void explanCond(String opear, SQLExpr expr, Where where) throws SqlParseException {
private void explainCond(String opear, SQLExpr expr, Where where) throws SqlParseException {
if (expr instanceof SQLBinaryOpExpr) {
SQLBinaryOpExpr soExpr = (SQLBinaryOpExpr) expr;
boolean methodAsOpear = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1740,6 +1740,32 @@ public void backticksQuotedAliasInJDBCResponseTest() {
assertTrue(response.contains("\"alias\": \"name\""));
}

@Test
public void caseWhenSwitchTest() throws IOException {
JSONObject response = executeQuery("SELECT CASE age " +
"WHEN '30' THEN '1' " +
"WHEN '40' THEN '2' " +
"ELSE '0' END AS cases FROM " + TEST_INDEX_ACCOUNT + " WHERE age IS NOT NULL");
JSONObject hit = getHits(response).getJSONObject(0);
String age = hit.query("/_source/age").toString();
String cases = age.equals("30") ? "1" : age.equals("40") ? "2" : "0";

assertThat(cases, equalTo(hit.query("/fields/cases/0")));
}

@Test
public void caseWhenJdbcResponseTest() {
String response = executeQuery("SELECT CASE age " +
"WHEN '30' THEN 'age is 30' " +
"WHEN '40' THEN 'age is 40' " +
"ELSE 'NA' END AS cases FROM " + TEST_INDEX_ACCOUNT + " WHERE age is not null", "jdbc");
assertTrue(
response.contains("age is 30") ||
response.contains("age is 40") ||
response.contains("NA")
);
}

private String getScrollId(JSONObject response) {
return response.getString("_scroll_id");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@
import com.amazon.opendistroforelasticsearch.sql.parser.SqlParser;
import com.amazon.opendistroforelasticsearch.sql.query.maker.QueryMaker;
import com.amazon.opendistroforelasticsearch.sql.query.multi.MultiQuerySelect;
import com.amazon.opendistroforelasticsearch.sql.util.CheckScriptContents;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder.ScriptField;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
Expand Down Expand Up @@ -1116,6 +1118,22 @@ public void caseWhenTestWithouhtElseExpr() throws SqlParseException {

}

@Test
public void caseWhenSwitchTest() {
String query = "SELECT CASE weather "
+ "WHEN 'Sunny' THEN '0' "
+ "WHEN 'Rainy' THEN '1' "
+ "ELSE 'NA' END AS case "
+ "FROM t";
ScriptField scriptField = CheckScriptContents.getScriptFieldFromQuery(query);
Assert.assertTrue(
CheckScriptContents.scriptContainsString(
scriptField,
"doc['weather'].value=='Sunny'"
)
);
}

@Test
public void castToIntTest() throws Exception {
String query = "select cast(age as int) from "+ TestsConstants.TEST_INDEX_ACCOUNT + "/account limit 10";
Expand Down

0 comments on commit 842c215

Please sign in to comment.