Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions src/main/java/org/nlpcn/es4sql/parse/CastParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package org.nlpcn.es4sql.parse;

import com.alibaba.druid.sql.ast.expr.SQLCastExpr;
import com.google.common.base.Joiner;
import org.nlpcn.es4sql.SQLFunctions;
import org.nlpcn.es4sql.Util;
import org.nlpcn.es4sql.exception.SqlParseException;

import java.util.ArrayList;
import java.util.List;

/**
* Created by leonlu on 2017/9/21.
*/
public class CastParser {

private enum DataType {
INT, LONG, FLOAT, DOUBLE, STRING, DATETIME
}

private SQLCastExpr castExpr;
private String alias;
private String tableAlias;

public CastParser(SQLCastExpr castExpr, String alias, String tableAlias) {
this.castExpr = castExpr;
this.alias = alias;
this.tableAlias = tableAlias;
}

public String parse(boolean isReturn) throws SqlParseException {
List<String> result = new ArrayList<>();

String dataType = castExpr.getDataType().getName().toUpperCase();
String fileName = String.format("doc['%s'].value",Util.expr2Object(castExpr.getExpr()));
String name = "field_"+SQLFunctions.random();

try {
if (DataType.valueOf(dataType) == DataType.INT) {
result.add(String.format("def %s = Double.parseDouble(%s.toString()).intValue()", name, fileName));
} else if (DataType.valueOf(dataType) == DataType.LONG) {
result.add(String.format("def %s = Double.parseDouble(%s.toString()).longValue()", name, fileName));
} else if (DataType.valueOf(dataType) == DataType.FLOAT) {
result.add(String.format("def %s = Double.parseDouble(%s.toString()).floatValue()", name, fileName));
} else if (DataType.valueOf(dataType) == DataType.DOUBLE) {
result.add(String.format("def %s = Double.parseDouble(%s.toString()).doubleValue()", name, fileName));
} else if (DataType.valueOf(dataType) == DataType.STRING) {
result.add(String.format("def %s = %s.toString()",name, fileName));
} else if (DataType.valueOf(dataType) == DataType.DATETIME) {
result.add(String.format("def %s = new Date(Double.parseDouble(%s.toString()).longValue())", name, fileName));
} else {
throw new SqlParseException("not support cast to data type:" + dataType);
}
if(isReturn) {
result.add("return " + name);
}

return Joiner.on("; ").join(result);
} catch (Exception ex) {
throw new SqlParseException(String.format("field cast to type: %s failed. error:%s",dataType, ex.getMessage()));
}
}
}
13 changes: 13 additions & 0 deletions src/main/java/org/nlpcn/es4sql/parse/FieldMaker.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ public static Field makeField(SQLExpr expr, String alias, String tableAlias) thr
methodParameters.add(new KVValue(alias));
methodParameters.add(new KVValue(scriptCode));
return new MethodField("script", methodParameters, null, alias);
}else if (expr instanceof SQLCastExpr) {
SQLCastExpr castExpr = (SQLCastExpr) expr;
if (alias == null) {
alias = "cast_" + castExpr.getExpr().toString();
}
String scriptCode = new CastParser(castExpr, alias, tableAlias).parse(true);
List<KVValue> methodParameters = new ArrayList<>();
methodParameters.add(new KVValue(alias));
methodParameters.add(new KVValue(scriptCode));
return new MethodField("script", methodParameters, null, alias);
} else {
throw new SqlParseException("unknown field name : " + expr);
}
Expand Down Expand Up @@ -251,6 +261,9 @@ public static MethodField makeMethodField(String name, List<SQLExpr> arguments,
} else if (object instanceof SQLCaseExpr) {
String scriptCode = new CaseWhenParser((SQLCaseExpr) object, alias, tableAlias).parse();
paramers.add(new KVValue("script",new SQLCharExpr(scriptCode)));
} else if(object instanceof SQLCastExpr) {
String scriptCode = new CastParser((SQLCastExpr) object, alias, tableAlias).parse(false);
paramers.add(new KVValue("script",new SQLCharExpr(scriptCode)));
} else {
paramers.add(new KVValue(Util.removeTableAilasFromField(object, tableAlias)));
}
Expand Down
125 changes: 125 additions & 0 deletions src/test/java/org/nlpcn/es4sql/SqlParserTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,131 @@ public void caseWhenTestWithouhtElseExpr() throws SqlParseException {

}

@Test
public void castToIntTest() throws Exception {
String query = "select cast(age as int) from "+ TestsConstants.TEST_INDEX + "/account limit 10";
SQLExpr sqlExpr = queryToExpr(query);
Select select = parser.parseSelect((SQLQueryExpr) sqlExpr);
Field castField = select.getFields().get(0);
Assert.assertTrue(castField instanceof MethodField);

MethodField methodField = (MethodField) castField;
Assert.assertEquals("script",castField.getName());

String alias = (String) methodField.getParams().get(0).value;
String scriptCode = (String) methodField.getParams().get(1).value;
Assert.assertEquals("cast_age",alias);
Assert.assertTrue(scriptCode.contains("doc['age'].value"));
Assert.assertTrue(scriptCode.contains("Double.parseDouble(doc['age'].value.toString()).intValue()"));
}

@Test
public void castToLongTest() throws Exception {
String query = "select cast(insert_time as long) from "+ TestsConstants.TEST_INDEX + " limit 10";
SQLExpr sqlExpr = queryToExpr(query);
Select select = parser.parseSelect((SQLQueryExpr) sqlExpr);
Field castField = select.getFields().get(0);
Assert.assertTrue(castField instanceof MethodField);

MethodField methodField = (MethodField) castField;
Assert.assertEquals("script",castField.getName());

String alias = (String) methodField.getParams().get(0).value;
String scriptCode = (String) methodField.getParams().get(1).value;
Assert.assertEquals("cast_insert_time",alias);
Assert.assertTrue(scriptCode.contains("doc['insert_time'].value"));
Assert.assertTrue(scriptCode.contains("Double.parseDouble(doc['insert_time'].value.toString()).longValue()"));
}

@Test
public void castToFloatTest() throws Exception {
String query = "select cast(age as float) from "+ TestsConstants.TEST_INDEX + " limit 10";
SQLExpr sqlExpr = queryToExpr(query);
Select select = parser.parseSelect((SQLQueryExpr) sqlExpr);
Field castField = select.getFields().get(0);
Assert.assertTrue(castField instanceof MethodField);

MethodField methodField = (MethodField) castField;
Assert.assertEquals("script",castField.getName());

String alias = (String) methodField.getParams().get(0).value;
String scriptCode = (String) methodField.getParams().get(1).value;
Assert.assertEquals("cast_age",alias);
Assert.assertTrue(scriptCode.contains("doc['age'].value"));
Assert.assertTrue(scriptCode.contains("Double.parseDouble(doc['age'].value.toString()).floatValue()"));
}

@Test
public void castToDoubleTest() throws Exception {
String query = "select cast(age as double) from "+ TestsConstants.TEST_INDEX + "/account limit 10";
SQLExpr sqlExpr = queryToExpr(query);
Select select = parser.parseSelect((SQLQueryExpr) sqlExpr);
Field castField = select.getFields().get(0);
Assert.assertTrue(castField instanceof MethodField);

MethodField methodField = (MethodField) castField;
Assert.assertEquals("script",castField.getName());

String alias = (String) methodField.getParams().get(0).value;
String scriptCode = (String) methodField.getParams().get(1).value;
Assert.assertEquals("cast_age",alias);
Assert.assertTrue(scriptCode.contains("doc['age'].value"));
Assert.assertTrue(scriptCode.contains("Double.parseDouble(doc['age'].value.toString()).doubleValue()"));
}

@Test
public void castToStringTest() throws Exception {
String query = "select cast(age as string) from "+ TestsConstants.TEST_INDEX + "/account limit 10";
SQLExpr sqlExpr = queryToExpr(query);
Select select = parser.parseSelect((SQLQueryExpr) sqlExpr);
Field castField = select.getFields().get(0);
Assert.assertTrue(castField instanceof MethodField);

MethodField methodField = (MethodField) castField;
Assert.assertEquals("script",castField.getName());

String alias = (String) methodField.getParams().get(0).value;
String scriptCode = (String) methodField.getParams().get(1).value;
Assert.assertEquals("cast_age",alias);
Assert.assertTrue(scriptCode.contains("doc['age'].value.toString()"));
}

@Test
public void castToDateTimeTest() throws Exception {
String query = "select cast(age as datetime) from "+ TestsConstants.TEST_INDEX + "/account limit 10";
SQLExpr sqlExpr = queryToExpr(query);
Select select = parser.parseSelect((SQLQueryExpr) sqlExpr);
Field castField = select.getFields().get(0);
Assert.assertTrue(castField instanceof MethodField);

MethodField methodField = (MethodField) castField;
Assert.assertEquals("script",castField.getName());

String alias = (String) methodField.getParams().get(0).value;
String scriptCode = (String) methodField.getParams().get(1).value;
Assert.assertEquals("cast_age",alias);
Assert.assertTrue(scriptCode.contains("doc['age'].value"));
Assert.assertTrue(scriptCode.contains("new Date(Double.parseDouble(doc['age'].value.toString()).longValue())"));
}

@Test
public void castToDoubleThenDivideTest() throws Exception {
String query = "select cast(age as double)/2 from "+ TestsConstants.TEST_INDEX + "/account limit 10";
SQLExpr sqlExpr = queryToExpr(query);
Select select = parser.parseSelect((SQLQueryExpr) sqlExpr);
Field castField = select.getFields().get(0);
Assert.assertTrue(castField instanceof MethodField);

MethodField methodField = (MethodField) castField;
Assert.assertEquals("script",castField.getName());

String alias = (String) methodField.getParams().get(0).value;
String scriptCode = (String) methodField.getParams().get(1).value;
Assert.assertTrue(scriptCode.contains("doc['age'].value"));
Assert.assertTrue(scriptCode.contains("Double.parseDouble(doc['age'].value.toString()).doubleValue()"));
Assert.assertTrue(scriptCode.contains("/ 2"));
}


@Test
public void multiSelectMinusOperationCheckIndices() throws SqlParseException {
Expand Down