spuerx %!s(int64=9) %!d(string=hai) anos
pai
achega
8cef9bd3a0
Modificáronse 48 ficheiros con 585 adicións e 199 borrados
  1. 1 1
      src/main/java/org/elasticsearch/dsl/helper/ElasticSqlDateParseHelper.java
  2. 32 11
      src/main/java/org/elasticsearch/dsl/helper/ElasticSqlMethodInvokeHelper.java
  3. 6 22
      src/main/java/org/elasticsearch/dsl/parser/query/method/fulltext/FullTextAtomQueryParser.java
  4. 10 1
      src/main/java/org/elasticsearch/dsl/parser/query/method/fulltext/MatchAtomQueryParser.java
  5. 10 1
      src/main/java/org/elasticsearch/dsl/parser/query/method/fulltext/MultiMatchAtomQueryParser.java
  6. 10 1
      src/main/java/org/elasticsearch/dsl/parser/query/method/fulltext/QueryStringAtomQueryParser.java
  7. 8 0
      src/main/java/org/elasticsearch/dsl/parser/query/method/fulltext/SimpleQueryStringAtomQueryParser.java
  8. 53 0
      src/main/java/org/elasticsearch/dsl/parser/query/method/script/ScriptAtomQueryParser.java
  9. 10 1
      src/main/java/org/elasticsearch/dsl/parser/query/method/term/FuzzyAtomQueryParser.java
  10. 9 0
      src/main/java/org/elasticsearch/dsl/parser/query/method/term/PrefixAtomQueryParser.java
  11. 9 1
      src/main/java/org/elasticsearch/dsl/parser/query/method/term/RegexpAtomQueryParser.java
  12. 10 1
      src/main/java/org/elasticsearch/dsl/parser/query/method/term/TermAtomQueryParser.java
  13. 9 33
      src/main/java/org/elasticsearch/dsl/parser/query/method/term/TermLevelAtomQueryParser.java
  14. 9 1
      src/main/java/org/elasticsearch/dsl/parser/query/method/term/TermsAtomQueryParser.java
  15. 10 1
      src/main/java/org/elasticsearch/dsl/parser/query/method/term/WildcardAtomQueryParser.java
  16. 6 0
      src/main/java/org/elasticsearch/dsl/parser/sql/AbstractQueryConditionParser.java
  17. 2 2
      src/main/java/org/elasticsearch/dsl/parser/sql/QueryGroupByParser.java
  18. 1 1
      src/main/java/org/elasticsearch/dsl/parser/sql/QueryOrderConditionParser.java
  19. 1 1
      src/main/java/org/elasticsearch/jdbc/AbstractConnection.java
  20. 1 1
      src/main/java/org/elasticsearch/jdbc/AbstractDataSource.java
  21. 1 1
      src/main/java/org/elasticsearch/jdbc/AbstractDriverBasedDataSource.java
  22. 1 1
      src/main/java/org/elasticsearch/jdbc/AbstractFeatureNotSupportedConnection.java
  23. 1 1
      src/main/java/org/elasticsearch/jdbc/AbstractFeatureNotSupportedPreparedStatement.java
  24. 1 1
      src/main/java/org/elasticsearch/jdbc/AbstractFeatureNotSupportedResultSet.java
  25. 1 1
      src/main/java/org/elasticsearch/jdbc/AbstractFeatureNotSupportedStatement.java
  26. 5 6
      src/main/java/org/elasticsearch/jdbc/AbstractResultSet.java
  27. 1 1
      src/main/java/org/elasticsearch/jdbc/AbstractStatement.java
  28. 1 1
      src/main/java/org/elasticsearch/jdbc/ConnectionProxy.java
  29. 1 1
      src/main/java/org/elasticsearch/jdbc/DriverManagerDataSource.java
  30. 1 1
      src/main/java/org/elasticsearch/jdbc/ElasticConnection.java
  31. 2 2
      src/main/java/org/elasticsearch/jdbc/ElasticDatabaseMetaData.java
  32. 4 4
      src/main/java/org/elasticsearch/jdbc/ElasticDriver.java
  33. 1 1
      src/main/java/org/elasticsearch/jdbc/ElasticPreparedStatement.java
  34. 1 1
      src/main/java/org/elasticsearch/jdbc/ElasticResultSet.java
  35. 1 1
      src/main/java/org/elasticsearch/jdbc/ElasticResultSetMetaData.java
  36. 2 2
      src/main/java/org/elasticsearch/jdbc/ElasticSingleConnectionDataSource.java
  37. 23 37
      src/main/java/org/elasticsearch/jdbc/ElasticStatement.java
  38. 1 1
      src/main/java/org/elasticsearch/jdbc/SmartDataSource.java
  39. 1 1
      src/main/java/org/elasticsearch/jdbc/search/ElasticClientProvider.java
  40. 1 1
      src/main/java/org/elasticsearch/jdbc/search/ElasticClientProxy.java
  41. 1 1
      src/main/java/org/elasticsearch/jdbc/search/ElasticClientProxyProviderImpl.java
  42. 2 2
      src/main/java/org/elasticsearch/jdbc/search/JdbcSearchActionExecutor.java
  43. 15 16
      src/main/java/org/elasticsearch/jdbc/search/JdbcSearchResponse.java
  44. 182 0
      src/main/java/org/elasticsearch/jdbc/es/JdbcSearchResponseExtractor.java
  45. 21 24
      src/main/java/org/elasticsearch/jdbc/search/JdbcSearchResponseResolver.java
  46. 55 7
      src/test/java/org/elasticsearch/jdbc/ElasticDriverTest.java
  47. 48 0
      src/test/java/org/elasticsearch/jdbc/bean/ProductAggResult.java
  48. 3 3
      src/test/java/org/elasticsearch/query/SqlParserWhereConditionTest.java

+ 1 - 1
src/main/java/org/elasticsearch/dsl/helper/ElasticSqlDateParseHelper.java

@@ -16,7 +16,7 @@ public class ElasticSqlDateParseHelper {
     public static final Pattern SQL_DATE_REGEX_PATTERN_03 = Pattern.compile("\\d{4}-\\d{2}-\\d{2}");
 
     public static boolean isDateMethod(SQLMethodInvokeExpr dateMethodExpr) {
-        return ElasticSqlMethodInvokeHelper.DATE_METHOD.equalsIgnoreCase(dateMethodExpr.getMethodName());
+        return ElasticSqlMethodInvokeHelper.isMethodOf(ElasticSqlMethodInvokeHelper.DATE_METHOD, dateMethodExpr.getMethodName());
     }
 
     public static boolean isDateArgStringValue(String date) {

+ 32 - 11
src/main/java/org/elasticsearch/dsl/helper/ElasticSqlMethodInvokeHelper.java

@@ -2,39 +2,60 @@ package org.elasticsearch.dsl.helper;
 
 import com.alibaba.druid.sql.ast.SQLExpr;
 import com.alibaba.druid.sql.ast.expr.*;
+import com.google.common.collect.ImmutableList;
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
 import org.elasticsearch.dsl.enums.SortOption;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 
-public class ElasticSqlMethodInvokeHelper {
+import java.util.List;
 
-    public static final String DATE_METHOD = "date";
-    public static final String NVL_METHOD = "nvl";
+public class ElasticSqlMethodInvokeHelper {
+    public static final List<String> DATE_METHOD = ImmutableList.of("date", "to_date", "toDate");
+    public static final List<String> NVL_METHOD = ImmutableList.of("nvl", "is_null", "isnull");
 
-    public static final String AGG_TERMS_METHOD = "terms";
-    public static final String AGG_RANGE_METHOD = "range";
-    public static final String AGG_RANGE_SEGMENT_METHOD = "segment";
+    public static final List<String> AGG_TERMS_METHOD = ImmutableList.of("terms", "terms_agg");
+    public static final List<String> AGG_RANGE_METHOD = ImmutableList.of("range", "range_agg");
+    public static final List<String> AGG_RANGE_SEGMENT_METHOD = ImmutableList.of("segment", "segment_agg");
 
     public static final String AGG_MIN_METHOD = "min";
     public static final String AGG_MAX_METHOD = "max";
     public static final String AGG_AVG_METHOD = "avg";
     public static final String AGG_SUM_METHOD = "sum";
 
+    public static Boolean isMethodOf(List<String> methodAlias, String method) {
+        if (CollectionUtils.isEmpty(methodAlias)) {
+            return Boolean.FALSE;
+        }
+        for (String alias : methodAlias) {
+            if (alias.equalsIgnoreCase(method)) {
+                return Boolean.TRUE;
+            }
+        }
+        return Boolean.FALSE;
+    }
+
+    public static Boolean isMethodOf(String methodAlias, String method) {
+        if (StringUtils.isBlank(methodAlias)) {
+            return Boolean.FALSE;
+        }
+        return methodAlias.equalsIgnoreCase(method);
+    }
 
     public static void checkTermsAggMethod(SQLMethodInvokeExpr aggInvokeExpr) {
-        if (!AGG_TERMS_METHOD.equalsIgnoreCase(aggInvokeExpr.getMethodName())) {
+        if (!isMethodOf(AGG_TERMS_METHOD, aggInvokeExpr.getMethodName())) {
             throw new ElasticSql2DslException("[syntax error] Sql not support method:" + aggInvokeExpr.getMethodName());
         }
     }
 
     public static void checkRangeAggMethod(SQLMethodInvokeExpr aggInvokeExpr) {
-        if (!AGG_RANGE_METHOD.equalsIgnoreCase(aggInvokeExpr.getMethodName())) {
+        if (!isMethodOf(AGG_RANGE_METHOD, aggInvokeExpr.getMethodName())) {
             throw new ElasticSql2DslException("[syntax error] Sql not support method:" + aggInvokeExpr.getMethodName());
         }
     }
 
     public static void checkRangeItemAggMethod(SQLMethodInvokeExpr aggInvokeExpr) {
-        if (!AGG_RANGE_SEGMENT_METHOD.equalsIgnoreCase(aggInvokeExpr.getMethodName())) {
+        if (!isMethodOf(AGG_RANGE_SEGMENT_METHOD, aggInvokeExpr.getMethodName())) {
             throw new ElasticSql2DslException("[syntax error] Sql not support method:" + aggInvokeExpr.getMethodName());
         }
     }
@@ -49,7 +70,7 @@ public class ElasticSqlMethodInvokeHelper {
     }
 
     public static void checkDateMethod(SQLMethodInvokeExpr dateInvokeExpr) {
-        if (!DATE_METHOD.equalsIgnoreCase(dateInvokeExpr.getMethodName())) {
+        if (!isMethodOf(DATE_METHOD, dateInvokeExpr.getMethodName())) {
             throw new ElasticSql2DslException("[syntax error] Sql not support method:" + dateInvokeExpr.getMethodName());
         }
 
@@ -71,7 +92,7 @@ public class ElasticSqlMethodInvokeHelper {
     }
 
     public static void checkNvlMethod(SQLMethodInvokeExpr nvlInvokeExpr) {
-        if (!NVL_METHOD.equalsIgnoreCase(nvlInvokeExpr.getMethodName())) {
+        if (!isMethodOf(NVL_METHOD, nvlInvokeExpr.getMethodName())) {
             throw new ElasticSql2DslException("[syntax error] Sql sort condition only support nvl method invoke");
         }
 

+ 6 - 22
src/main/java/org/elasticsearch/dsl/parser/query/method/fulltext/FullTextAtomQueryParser.java

@@ -14,25 +14,9 @@ public class FullTextAtomQueryParser {
         this.parseActionListener = parseActionListener;
     }
 
-    private static Boolean isMatchQuery(SQLMethodInvokeExpr methodQueryExpr) {
-        return "match".equalsIgnoreCase(methodQueryExpr.getMethodName());
-    }
-
-    private static Boolean isMatchPrefixQuery(SQLMethodInvokeExpr methodQueryExpr) {
-        return "multiMatch".equalsIgnoreCase(methodQueryExpr.getMethodName());
-    }
-
-    private static Boolean isQueryStringQuery(SQLMethodInvokeExpr methodQueryExpr) {
-        return "queryString".equalsIgnoreCase(methodQueryExpr.getMethodName());
-    }
-
-    private static Boolean isSimpleQueryStringQuery(SQLMethodInvokeExpr methodQueryExpr) {
-        return "simpleQueryString".equalsIgnoreCase(methodQueryExpr.getMethodName());
-    }
-
     public static Boolean isFulltextAtomQuery(SQLMethodInvokeExpr methodQueryExpr) {
-        return isMatchQuery(methodQueryExpr) || isMatchPrefixQuery(methodQueryExpr) ||
-                isQueryStringQuery(methodQueryExpr) || isSimpleQueryStringQuery(methodQueryExpr);
+        return MatchAtomQueryParser.isMatchQuery(methodQueryExpr) || MultiMatchAtomQueryParser.isMultiMatch(methodQueryExpr) ||
+                QueryStringAtomQueryParser.isQueryStringQuery(methodQueryExpr) || SimpleQueryStringAtomQueryParser.isSimpleQueryStringQuery(methodQueryExpr);
     }
 
     public AtomQuery parseFullTextAtomQuery(SQLMethodInvokeExpr methodQueryExpr, String queryAs, Object[] sqlArgs) {
@@ -41,19 +25,19 @@ public class FullTextAtomQueryParser {
     }
 
     private AbstractAtomMethodQueryParser getQueryParser(SQLMethodInvokeExpr methodQueryExpr) {
-        if (Boolean.TRUE == isMatchQuery(methodQueryExpr)) {
+        if (Boolean.TRUE == MatchAtomQueryParser.isMatchQuery(methodQueryExpr)) {
             return new MatchAtomQueryParser(parseActionListener);
         }
 
-        if (Boolean.TRUE == isMatchPrefixQuery(methodQueryExpr)) {
+        if (Boolean.TRUE == MultiMatchAtomQueryParser.isMultiMatch(methodQueryExpr)) {
             return new MultiMatchAtomQueryParser(parseActionListener);
         }
 
-        if (Boolean.TRUE == isQueryStringQuery(methodQueryExpr)) {
+        if (Boolean.TRUE == QueryStringAtomQueryParser.isQueryStringQuery(methodQueryExpr)) {
             return new QueryStringAtomQueryParser(parseActionListener);
         }
 
-        if (Boolean.TRUE == isSimpleQueryStringQuery(methodQueryExpr)) {
+        if (Boolean.TRUE == SimpleQueryStringAtomQueryParser.isSimpleQueryStringQuery(methodQueryExpr)) {
             return new SimpleQueryStringAtomQueryParser(parseActionListener);
         }
 

+ 10 - 1
src/main/java/org/elasticsearch/dsl/parser/query/method/fulltext/MatchAtomQueryParser.java

@@ -2,12 +2,14 @@ package org.elasticsearch.dsl.parser.query.method.fulltext;
 
 import com.alibaba.druid.sql.ast.SQLExpr;
 import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
+import com.google.common.collect.ImmutableList;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.elasticsearch.common.unit.Fuzziness;
 import org.elasticsearch.dsl.bean.AtomQuery;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 import org.elasticsearch.dsl.helper.ElasticSqlArgTransferHelper;
+import org.elasticsearch.dsl.helper.ElasticSqlMethodInvokeHelper;
 import org.elasticsearch.dsl.listener.ParseActionListener;
 import org.elasticsearch.dsl.parser.query.method.AbstractAtomMethodQueryParser;
 import org.elasticsearch.dsl.parser.query.method.IConditionMethodQueryBuilder;
@@ -15,17 +17,24 @@ import org.elasticsearch.index.query.MatchQueryBuilder;
 import org.elasticsearch.index.query.QueryBuilder;
 import org.elasticsearch.index.query.QueryBuilders;
 
+import java.util.List;
 import java.util.Map;
 
 public class MatchAtomQueryParser extends AbstractAtomMethodQueryParser {
 
+    private static final List<String> MATCH_METHOD = ImmutableList.of("match", "match_query", "matchQuery");
+
     public MatchAtomQueryParser(ParseActionListener parseActionListener) {
         super(parseActionListener);
     }
 
+    public static Boolean isMatchQuery(SQLMethodInvokeExpr methodQueryExpr) {
+        return ElasticSqlMethodInvokeHelper.isMethodOf(MATCH_METHOD, methodQueryExpr.getMethodName());
+    }
+
     @Override
     protected void checkQueryMethod(SQLMethodInvokeExpr methodQueryExpr, String queryAs, Object[] sqlArgs) {
-        if (Boolean.FALSE == "match".equalsIgnoreCase(methodQueryExpr.getMethodName())) {
+        if (Boolean.FALSE == isMatchQuery(methodQueryExpr)) {
             throw new ElasticSql2DslException(String.format("[syntax error] Expected match query method name is [match],but get [%s]", methodQueryExpr.getMethodName()));
         }
 

+ 10 - 1
src/main/java/org/elasticsearch/dsl/parser/query/method/fulltext/MultiMatchAtomQueryParser.java

@@ -2,29 +2,38 @@ package org.elasticsearch.dsl.parser.query.method.fulltext;
 
 import com.alibaba.druid.sql.ast.SQLExpr;
 import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
+import com.google.common.collect.ImmutableList;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.elasticsearch.common.unit.Fuzziness;
 import org.elasticsearch.dsl.bean.AtomQuery;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 import org.elasticsearch.dsl.helper.ElasticSqlArgTransferHelper;
+import org.elasticsearch.dsl.helper.ElasticSqlMethodInvokeHelper;
 import org.elasticsearch.dsl.listener.ParseActionListener;
 import org.elasticsearch.dsl.parser.query.method.AbstractAtomMethodQueryParser;
 import org.elasticsearch.index.query.MatchQueryBuilder;
 import org.elasticsearch.index.query.MultiMatchQueryBuilder;
 import org.elasticsearch.index.query.QueryBuilders;
 
+import java.util.List;
 import java.util.Map;
 
 public class MultiMatchAtomQueryParser extends AbstractAtomMethodQueryParser {
 
+    private static final List<String> MULTI_MATCH_METHOD = ImmutableList.of("multiMatch", "multi_match", "multi_match_query", "multiMatchQuery");
+
     public MultiMatchAtomQueryParser(ParseActionListener parseActionListener) {
         super(parseActionListener);
     }
 
+    public static Boolean isMultiMatch(SQLMethodInvokeExpr methodQueryExpr) {
+        return ElasticSqlMethodInvokeHelper.isMethodOf(MULTI_MATCH_METHOD, methodQueryExpr.getMethodName());
+    }
+
     @Override
     protected void checkQueryMethod(SQLMethodInvokeExpr methodQueryExpr, String queryAs, Object[] sqlArgs) {
-        if (Boolean.FALSE == "multiMatch".equalsIgnoreCase(methodQueryExpr.getMethodName())) {
+        if (Boolean.FALSE == isMultiMatch(methodQueryExpr)) {
             throw new ElasticSql2DslException(String.format("[syntax error] Expected multiMatch query method name is [multiMatch],but get [%s]", methodQueryExpr.getMethodName()));
         }
 

+ 10 - 1
src/main/java/org/elasticsearch/dsl/parser/query/method/fulltext/QueryStringAtomQueryParser.java

@@ -2,29 +2,38 @@ package org.elasticsearch.dsl.parser.query.method.fulltext;
 
 import com.alibaba.druid.sql.ast.SQLExpr;
 import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
+import com.google.common.collect.ImmutableList;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.elasticsearch.common.unit.Fuzziness;
 import org.elasticsearch.dsl.bean.AtomQuery;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 import org.elasticsearch.dsl.helper.ElasticSqlArgTransferHelper;
+import org.elasticsearch.dsl.helper.ElasticSqlMethodInvokeHelper;
 import org.elasticsearch.dsl.listener.ParseActionListener;
 import org.elasticsearch.dsl.parser.query.method.AbstractAtomMethodQueryParser;
 import org.elasticsearch.index.query.QueryBuilders;
 import org.elasticsearch.index.query.QueryStringQueryBuilder;
 
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 
 public class QueryStringAtomQueryParser extends AbstractAtomMethodQueryParser {
 
+    private static List<String> QUERY_STRING_METHOD = ImmutableList.of("queryString", "query_string");
+
     public QueryStringAtomQueryParser(ParseActionListener parseActionListener) {
         super(parseActionListener);
     }
 
+    public static Boolean isQueryStringQuery(SQLMethodInvokeExpr methodQueryExpr) {
+        return ElasticSqlMethodInvokeHelper.isMethodOf(QUERY_STRING_METHOD, methodQueryExpr.getMethodName());
+    }
+
     @Override
     protected void checkQueryMethod(SQLMethodInvokeExpr methodQueryExpr, String queryAs, Object[] sqlArgs) {
-        if (Boolean.FALSE == "queryString".equalsIgnoreCase(methodQueryExpr.getMethodName())) {
+        if (Boolean.FALSE == isQueryStringQuery(methodQueryExpr)) {
             throw new ElasticSql2DslException(String.format("[syntax error] Expected queryString query method name is [queryString],but get [%s]", methodQueryExpr.getMethodName()));
         }
 

+ 8 - 0
src/main/java/org/elasticsearch/dsl/parser/query/method/fulltext/SimpleQueryStringAtomQueryParser.java

@@ -2,12 +2,14 @@ package org.elasticsearch.dsl.parser.query.method.fulltext;
 
 import com.alibaba.druid.sql.ast.SQLExpr;
 import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.elasticsearch.dsl.bean.AtomQuery;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 import org.elasticsearch.dsl.helper.ElasticSqlArgTransferHelper;
+import org.elasticsearch.dsl.helper.ElasticSqlMethodInvokeHelper;
 import org.elasticsearch.dsl.listener.ParseActionListener;
 import org.elasticsearch.dsl.parser.query.method.AbstractAtomMethodQueryParser;
 import org.elasticsearch.index.query.QueryBuilders;
@@ -20,10 +22,16 @@ import java.util.Map;
 
 public class SimpleQueryStringAtomQueryParser extends AbstractAtomMethodQueryParser {
 
+    private static List<String> SIMPLE_QUERY_STRING_METHOD = ImmutableList.of("simpleQueryString", "simple_query_string");
+
     public SimpleQueryStringAtomQueryParser(ParseActionListener parseActionListener) {
         super(parseActionListener);
     }
 
+    public static Boolean isSimpleQueryStringQuery(SQLMethodInvokeExpr methodQueryExpr) {
+        return ElasticSqlMethodInvokeHelper.isMethodOf(SIMPLE_QUERY_STRING_METHOD, methodQueryExpr.getMethodName());
+    }
+
     @Override
     protected void checkQueryMethod(SQLMethodInvokeExpr methodQueryExpr, String queryAs, Object[] sqlArgs) {
         if (Boolean.FALSE == "simpleQueryString".equalsIgnoreCase(methodQueryExpr.getMethodName())) {

+ 53 - 0
src/main/java/org/elasticsearch/dsl/parser/query/method/script/ScriptAtomQueryParser.java

@@ -0,0 +1,53 @@
+package org.elasticsearch.dsl.parser.query.method.script;
+
+import com.alibaba.druid.sql.ast.SQLExpr;
+import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
+import com.google.common.collect.ImmutableList;
+import org.apache.commons.lang.StringUtils;
+import org.elasticsearch.dsl.bean.AtomQuery;
+import org.elasticsearch.dsl.exception.ElasticSql2DslException;
+import org.elasticsearch.dsl.helper.ElasticSqlArgTransferHelper;
+import org.elasticsearch.dsl.helper.ElasticSqlMethodInvokeHelper;
+import org.elasticsearch.dsl.listener.ParseActionListener;
+import org.elasticsearch.dsl.parser.query.method.AbstractAtomMethodQueryParser;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.script.Script;
+
+import java.util.List;
+
+public class ScriptAtomQueryParser extends AbstractAtomMethodQueryParser {
+
+    private static List<String> SCRIPT_METHOD = ImmutableList.of("script_query", "scriptQuery");
+
+    public ScriptAtomQueryParser(ParseActionListener parseActionListener) {
+        super(parseActionListener);
+    }
+
+    public static Boolean isScriptAtomQuery(SQLMethodInvokeExpr methodQueryExpr) {
+        return ElasticSqlMethodInvokeHelper.isMethodOf(SCRIPT_METHOD, methodQueryExpr.getMethodName());
+    }
+
+    @Override
+    protected void checkQueryMethod(SQLMethodInvokeExpr methodQueryExpr, String queryAs, Object[] sqlArgs) {
+        if (Boolean.FALSE == isScriptAtomQuery(methodQueryExpr)) {
+            throw new ElasticSql2DslException(String.format("[syntax error] Expected script query method name is [script],but get [%s]", methodQueryExpr.getMethodName()));
+        }
+
+        int paramCount = methodQueryExpr.getParameters().size();
+        if (paramCount != 1) {
+            throw new ElasticSql2DslException(String.format("[syntax error] There's no %s args method: fuzzy", paramCount));
+        }
+
+        SQLExpr scriptExpr = methodQueryExpr.getParameters().get(0);
+        String text = ElasticSqlArgTransferHelper.transferSqlArg(scriptExpr, sqlArgs, false).toString();
+        if (StringUtils.isEmpty(text)) {
+            throw new ElasticSql2DslException("[syntax error] script can not be blank!");
+        }
+    }
+
+    @Override
+    protected AtomQuery parseMethodQueryExpr(SQLMethodInvokeExpr methodQueryExpr, String queryAs, Object[] sqlArgs) {
+        String script = (String) ElasticSqlArgTransferHelper.transferSqlArg(methodQueryExpr.getParameters().get(0), sqlArgs, false);
+        return new AtomQuery(QueryBuilders.scriptQuery(new Script(script)));
+    }
+}

+ 10 - 1
src/main/java/org/elasticsearch/dsl/parser/query/method/term/FuzzyAtomQueryParser.java

@@ -2,12 +2,14 @@ package org.elasticsearch.dsl.parser.query.method.term;
 
 import com.alibaba.druid.sql.ast.SQLExpr;
 import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
+import com.google.common.collect.ImmutableList;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.elasticsearch.common.unit.Fuzziness;
 import org.elasticsearch.dsl.bean.AtomQuery;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 import org.elasticsearch.dsl.helper.ElasticSqlArgTransferHelper;
+import org.elasticsearch.dsl.helper.ElasticSqlMethodInvokeHelper;
 import org.elasticsearch.dsl.listener.ParseActionListener;
 import org.elasticsearch.dsl.parser.query.method.AbstractAtomMethodQueryParser;
 import org.elasticsearch.dsl.parser.query.method.IConditionMethodQueryBuilder;
@@ -15,17 +17,24 @@ import org.elasticsearch.index.query.FuzzyQueryBuilder;
 import org.elasticsearch.index.query.QueryBuilder;
 import org.elasticsearch.index.query.QueryBuilders;
 
+import java.util.List;
 import java.util.Map;
 
 public class FuzzyAtomQueryParser extends AbstractAtomMethodQueryParser {
 
+    private static List<String> FUZZY_QUERY_METHOD = ImmutableList.of("fuzzy", "fuzzy_query", "fuzzyQuery");
+
     public FuzzyAtomQueryParser(ParseActionListener parseActionListener) {
         super(parseActionListener);
     }
 
+    public static Boolean isFuzzyQuery(SQLMethodInvokeExpr methodQueryExpr) {
+        return ElasticSqlMethodInvokeHelper.isMethodOf(FUZZY_QUERY_METHOD, methodQueryExpr.getMethodName());
+    }
+
     @Override
     protected void checkQueryMethod(SQLMethodInvokeExpr methodQueryExpr, String queryAs, Object[] sqlArgs) {
-        if (Boolean.FALSE == "fuzzy".equalsIgnoreCase(methodQueryExpr.getMethodName())) {
+        if (Boolean.FALSE == isFuzzyQuery(methodQueryExpr)) {
             throw new ElasticSql2DslException(String.format("[syntax error] Expected fuzzy query method name is [fuzzy],but get [%s]", methodQueryExpr.getMethodName()));
         }
 

+ 9 - 0
src/main/java/org/elasticsearch/dsl/parser/query/method/term/PrefixAtomQueryParser.java

@@ -2,11 +2,13 @@ package org.elasticsearch.dsl.parser.query.method.term;
 
 import com.alibaba.druid.sql.ast.SQLExpr;
 import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
+import com.google.common.collect.ImmutableList;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.elasticsearch.dsl.bean.AtomQuery;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 import org.elasticsearch.dsl.helper.ElasticSqlArgTransferHelper;
+import org.elasticsearch.dsl.helper.ElasticSqlMethodInvokeHelper;
 import org.elasticsearch.dsl.listener.ParseActionListener;
 import org.elasticsearch.dsl.parser.query.method.AbstractAtomMethodQueryParser;
 import org.elasticsearch.dsl.parser.query.method.IConditionMethodQueryBuilder;
@@ -14,14 +16,21 @@ import org.elasticsearch.index.query.PrefixQueryBuilder;
 import org.elasticsearch.index.query.QueryBuilder;
 import org.elasticsearch.index.query.QueryBuilders;
 
+import java.util.List;
 import java.util.Map;
 
 public class PrefixAtomQueryParser extends AbstractAtomMethodQueryParser {
 
+    private static List<String> PREFIX_QUERY_METHOD = ImmutableList.of("prefix", "prefix_query", "prefixQuery");
+
     public PrefixAtomQueryParser(ParseActionListener parseActionListener) {
         super(parseActionListener);
     }
 
+    public static Boolean isPrefixQuery(SQLMethodInvokeExpr methodQueryExpr) {
+        return ElasticSqlMethodInvokeHelper.isMethodOf(PREFIX_QUERY_METHOD, methodQueryExpr.getMethodName());
+    }
+
     @Override
     protected void checkQueryMethod(SQLMethodInvokeExpr methodQueryExpr, String queryAs, Object[] sqlArgs) {
         if (Boolean.FALSE == "prefix".equalsIgnoreCase(methodQueryExpr.getMethodName())) {

+ 9 - 1
src/main/java/org/elasticsearch/dsl/parser/query/method/term/RegexpAtomQueryParser.java

@@ -2,12 +2,14 @@ package org.elasticsearch.dsl.parser.query.method.term;
 
 import com.alibaba.druid.sql.ast.SQLExpr;
 import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.elasticsearch.dsl.bean.AtomQuery;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 import org.elasticsearch.dsl.helper.ElasticSqlArgTransferHelper;
+import org.elasticsearch.dsl.helper.ElasticSqlMethodInvokeHelper;
 import org.elasticsearch.dsl.listener.ParseActionListener;
 import org.elasticsearch.dsl.parser.query.method.AbstractAtomMethodQueryParser;
 import org.elasticsearch.dsl.parser.query.method.IConditionMethodQueryBuilder;
@@ -21,13 +23,19 @@ import java.util.Map;
 
 public class RegexpAtomQueryParser extends AbstractAtomMethodQueryParser {
 
+    private static List<String> REGEXP_QUERY_METHOD = ImmutableList.of("regexp", "regexp_query", "regexpQuery");
+
     public RegexpAtomQueryParser(ParseActionListener parseActionListener) {
         super(parseActionListener);
     }
 
+    public static Boolean isRegexpQuery(SQLMethodInvokeExpr methodQueryExpr) {
+        return ElasticSqlMethodInvokeHelper.isMethodOf(REGEXP_QUERY_METHOD, methodQueryExpr.getMethodName());
+    }
+
     @Override
     protected void checkQueryMethod(SQLMethodInvokeExpr methodQueryExpr, String queryAs, Object[] sqlArgs) {
-        if (Boolean.FALSE == "regexp".equalsIgnoreCase(methodQueryExpr.getMethodName())) {
+        if (Boolean.FALSE == isRegexpQuery(methodQueryExpr)) {
             throw new ElasticSql2DslException(String.format("[syntax error] Expected regexp query method name is [regexp],but get [%s]", methodQueryExpr.getMethodName()));
         }
 

+ 10 - 1
src/main/java/org/elasticsearch/dsl/parser/query/method/term/TermAtomQueryParser.java

@@ -2,11 +2,13 @@ package org.elasticsearch.dsl.parser.query.method.term;
 
 import com.alibaba.druid.sql.ast.SQLExpr;
 import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
+import com.google.common.collect.ImmutableList;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.elasticsearch.dsl.bean.AtomQuery;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 import org.elasticsearch.dsl.helper.ElasticSqlArgTransferHelper;
+import org.elasticsearch.dsl.helper.ElasticSqlMethodInvokeHelper;
 import org.elasticsearch.dsl.listener.ParseActionListener;
 import org.elasticsearch.dsl.parser.query.method.AbstractAtomMethodQueryParser;
 import org.elasticsearch.dsl.parser.query.method.IConditionMethodQueryBuilder;
@@ -14,17 +16,24 @@ import org.elasticsearch.index.query.QueryBuilder;
 import org.elasticsearch.index.query.QueryBuilders;
 import org.elasticsearch.index.query.TermQueryBuilder;
 
+import java.util.List;
 import java.util.Map;
 
 public class TermAtomQueryParser extends AbstractAtomMethodQueryParser {
 
+    private static List<String> TERM_QUERY_METHOD = ImmutableList.of("term", "term_query", "termQuery");
+
     public TermAtomQueryParser(ParseActionListener parseActionListener) {
         super(parseActionListener);
     }
 
+    public static Boolean isTermQuery(SQLMethodInvokeExpr methodQueryExpr) {
+        return ElasticSqlMethodInvokeHelper.isMethodOf(TERM_QUERY_METHOD, methodQueryExpr.getMethodName());
+    }
+
     @Override
     protected void checkQueryMethod(SQLMethodInvokeExpr methodQueryExpr, String queryAs, Object[] sqlArgs) {
-        if (Boolean.FALSE == "term".equalsIgnoreCase(methodQueryExpr.getMethodName())) {
+        if (Boolean.FALSE == isTermQuery(methodQueryExpr)) {
             throw new ElasticSql2DslException(String.format("[syntax error] Expected term query method name is [term],but get [%s]", methodQueryExpr.getMethodName()));
         }
 

+ 9 - 33
src/main/java/org/elasticsearch/dsl/parser/query/method/term/TermLevelAtomQueryParser.java

@@ -14,34 +14,10 @@ public class TermLevelAtomQueryParser {
         this.parseActionListener = parseActionListener;
     }
 
-    private static Boolean isPrefixQuery(SQLMethodInvokeExpr methodQueryExpr) {
-        return "prefix".equalsIgnoreCase(methodQueryExpr.getMethodName());
-    }
-
-    private static Boolean isTermQuery(SQLMethodInvokeExpr methodQueryExpr) {
-        return "term".equalsIgnoreCase(methodQueryExpr.getMethodName());
-    }
-
-    private static Boolean isTermsQuery(SQLMethodInvokeExpr methodQueryExpr) {
-        return "terms".equalsIgnoreCase(methodQueryExpr.getMethodName());
-    }
-
-    private static Boolean isWildcardQuery(SQLMethodInvokeExpr methodQueryExpr) {
-        return "wildcard".equalsIgnoreCase(methodQueryExpr.getMethodName());
-    }
-
-    private static Boolean isRegexpQuery(SQLMethodInvokeExpr methodQueryExpr) {
-        return "regexp".equalsIgnoreCase(methodQueryExpr.getMethodName());
-    }
-
-    private static Boolean isFuzzyQuery(SQLMethodInvokeExpr methodQueryExpr) {
-        return "fuzzy".equalsIgnoreCase(methodQueryExpr.getMethodName());
-    }
-
     public static Boolean isTermLevelAtomQuery(SQLMethodInvokeExpr methodQueryExpr) {
-        return isPrefixQuery(methodQueryExpr) || isTermQuery(methodQueryExpr) ||
-                isTermsQuery(methodQueryExpr) || isWildcardQuery(methodQueryExpr) ||
-                isRegexpQuery(methodQueryExpr) || isFuzzyQuery(methodQueryExpr);
+        return PrefixAtomQueryParser.isPrefixQuery(methodQueryExpr) || TermAtomQueryParser.isTermQuery(methodQueryExpr) ||
+                TermsAtomQueryParser.isTermsQuery(methodQueryExpr) || WildcardAtomQueryParser.isWildcardQuery(methodQueryExpr) ||
+                RegexpAtomQueryParser.isRegexpQuery(methodQueryExpr) || FuzzyAtomQueryParser.isFuzzyQuery(methodQueryExpr);
     }
 
     public AtomQuery parseTermLevelAtomQuery(SQLMethodInvokeExpr methodQueryExpr, String queryAs, Object[] sqlArgs) {
@@ -50,22 +26,22 @@ public class TermLevelAtomQueryParser {
     }
 
     private AbstractAtomMethodQueryParser getQueryParser(SQLMethodInvokeExpr methodQueryExpr) {
-        if (Boolean.TRUE == isPrefixQuery(methodQueryExpr)) {
+        if (Boolean.TRUE == PrefixAtomQueryParser.isPrefixQuery(methodQueryExpr)) {
             return new PrefixAtomQueryParser(parseActionListener);
         }
-        if (Boolean.TRUE == isTermQuery(methodQueryExpr)) {
+        if (Boolean.TRUE == TermAtomQueryParser.isTermQuery(methodQueryExpr)) {
             return new TermAtomQueryParser(parseActionListener);
         }
-        if (Boolean.TRUE == isTermsQuery(methodQueryExpr)) {
+        if (Boolean.TRUE == TermsAtomQueryParser.isTermsQuery(methodQueryExpr)) {
             return new TermsAtomQueryParser(parseActionListener);
         }
-        if (Boolean.TRUE == isWildcardQuery(methodQueryExpr)) {
+        if (Boolean.TRUE == WildcardAtomQueryParser.isWildcardQuery(methodQueryExpr)) {
             return new WildcardAtomQueryParser(parseActionListener);
         }
-        if (Boolean.TRUE == isRegexpQuery(methodQueryExpr)) {
+        if (Boolean.TRUE == RegexpAtomQueryParser.isRegexpQuery(methodQueryExpr)) {
             return new RegexpAtomQueryParser(parseActionListener);
         }
-        if (Boolean.TRUE == isFuzzyQuery(methodQueryExpr)) {
+        if (Boolean.TRUE == FuzzyAtomQueryParser.isFuzzyQuery(methodQueryExpr)) {
             return new FuzzyAtomQueryParser(parseActionListener);
         }
         throw new ElasticSql2DslException(String.format("[syntax error] Can not support method query expr[%s] condition", methodQueryExpr.getMethodName()));

+ 9 - 1
src/main/java/org/elasticsearch/dsl/parser/query/method/term/TermsAtomQueryParser.java

@@ -2,12 +2,14 @@ package org.elasticsearch.dsl.parser.query.method.term;
 
 import com.alibaba.druid.sql.ast.SQLExpr;
 import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.elasticsearch.dsl.bean.AtomQuery;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 import org.elasticsearch.dsl.helper.ElasticSqlArgTransferHelper;
+import org.elasticsearch.dsl.helper.ElasticSqlMethodInvokeHelper;
 import org.elasticsearch.dsl.listener.ParseActionListener;
 import org.elasticsearch.dsl.parser.query.method.AbstractAtomMethodQueryParser;
 import org.elasticsearch.dsl.parser.query.method.IConditionMethodQueryBuilder;
@@ -20,13 +22,19 @@ import java.util.Map;
 
 public class TermsAtomQueryParser extends AbstractAtomMethodQueryParser {
 
+    private static List<String> TERMS_QUERY_METHOD = ImmutableList.of("terms", "terms_query", "termsQuery");
+
     public TermsAtomQueryParser(ParseActionListener parseActionListener) {
         super(parseActionListener);
     }
 
+    public static Boolean isTermsQuery(SQLMethodInvokeExpr methodQueryExpr) {
+        return ElasticSqlMethodInvokeHelper.isMethodOf(TERMS_QUERY_METHOD, methodQueryExpr.getMethodName());
+    }
+
     @Override
     protected void checkQueryMethod(SQLMethodInvokeExpr methodQueryExpr, String queryAs, Object[] sqlArgs) {
-        if (Boolean.FALSE == "terms".equalsIgnoreCase(methodQueryExpr.getMethodName())) {
+        if (Boolean.FALSE == isTermsQuery(methodQueryExpr)) {
             throw new ElasticSql2DslException(String.format("[syntax error] Expected terms query method name is [terms],but get [%s]", methodQueryExpr.getMethodName()));
         }
 

+ 10 - 1
src/main/java/org/elasticsearch/dsl/parser/query/method/term/WildcardAtomQueryParser.java

@@ -2,11 +2,13 @@ package org.elasticsearch.dsl.parser.query.method.term;
 
 import com.alibaba.druid.sql.ast.SQLExpr;
 import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
+import com.google.common.collect.ImmutableList;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.elasticsearch.dsl.bean.AtomQuery;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 import org.elasticsearch.dsl.helper.ElasticSqlArgTransferHelper;
+import org.elasticsearch.dsl.helper.ElasticSqlMethodInvokeHelper;
 import org.elasticsearch.dsl.listener.ParseActionListener;
 import org.elasticsearch.dsl.parser.query.method.AbstractAtomMethodQueryParser;
 import org.elasticsearch.dsl.parser.query.method.IConditionMethodQueryBuilder;
@@ -14,17 +16,24 @@ import org.elasticsearch.index.query.QueryBuilder;
 import org.elasticsearch.index.query.QueryBuilders;
 import org.elasticsearch.index.query.WildcardQueryBuilder;
 
+import java.util.List;
 import java.util.Map;
 
 public class WildcardAtomQueryParser extends AbstractAtomMethodQueryParser {
 
+    private static List<String> WILDCARD_QUERY_METHOD = ImmutableList.of("wildcard", "wildcard_query", "wildcardQuery");
+
     public WildcardAtomQueryParser(ParseActionListener parseActionListener) {
         super(parseActionListener);
     }
 
+    public static Boolean isWildcardQuery(SQLMethodInvokeExpr methodQueryExpr) {
+        return ElasticSqlMethodInvokeHelper.isMethodOf(WILDCARD_QUERY_METHOD, methodQueryExpr.getMethodName());
+    }
+
     @Override
     protected void checkQueryMethod(SQLMethodInvokeExpr methodQueryExpr, String queryAs, Object[] sqlArgs) {
-        if (Boolean.FALSE == "wildcard".equalsIgnoreCase(methodQueryExpr.getMethodName())) {
+        if (Boolean.FALSE == isWildcardQuery(methodQueryExpr)) {
             throw new ElasticSql2DslException(String.format("[syntax error] Expected wildcard query method name is [wildcard],but get [%s]", methodQueryExpr.getMethodName()));
         }
 

+ 6 - 0
src/main/java/org/elasticsearch/dsl/parser/sql/AbstractQueryConditionParser.java

@@ -16,6 +16,7 @@ import org.elasticsearch.dsl.parser.query.exact.BinaryAtomQueryParser;
 import org.elasticsearch.dsl.parser.query.exact.InListAtomQueryParser;
 import org.elasticsearch.dsl.parser.query.method.fulltext.FullTextAtomQueryParser;
 import org.elasticsearch.dsl.parser.query.method.term.TermLevelAtomQueryParser;
+import org.elasticsearch.dsl.parser.query.method.script.ScriptAtomQueryParser;
 import org.elasticsearch.index.query.BoolQueryBuilder;
 import org.elasticsearch.index.query.QueryBuilder;
 import org.elasticsearch.index.query.QueryBuilders;
@@ -79,6 +80,11 @@ public abstract class AbstractQueryConditionParser implements QueryParser {
         if (sqlConditionExpr instanceof SQLMethodInvokeExpr) {
             SQLMethodInvokeExpr methodQueryExpr = (SQLMethodInvokeExpr) sqlConditionExpr;
 
+            if(ScriptAtomQueryParser.isScriptAtomQuery(methodQueryExpr)) {
+                ScriptAtomQueryParser scriptAtomQueryParser = new ScriptAtomQueryParser(parseActionListener);
+                return scriptAtomQueryParser.parseAtomMethodQuery(methodQueryExpr, queryAs, sqlArgs);
+            }
+
             if (FullTextAtomQueryParser.isFulltextAtomQuery(methodQueryExpr)) {
                 FullTextAtomQueryParser fullTextAtomQueryParser = new FullTextAtomQueryParser(parseActionListener);
                 return fullTextAtomQueryParser.parseFullTextAtomQuery(methodQueryExpr, queryAs, sqlArgs);

+ 2 - 2
src/main/java/org/elasticsearch/dsl/parser/sql/QueryGroupByParser.java

@@ -63,7 +63,7 @@ public class QueryGroupByParser implements QueryParser {
                 SQLMethodInvokeExpr aggMethodExpr = (SQLMethodInvokeExpr) groupByItem;
 
                 //Terms Aggregation
-                if (ElasticSqlMethodInvokeHelper.AGG_TERMS_METHOD.equalsIgnoreCase(aggMethodExpr.getMethodName())) {
+                if (ElasticSqlMethodInvokeHelper.isMethodOf(ElasticSqlMethodInvokeHelper.AGG_TERMS_METHOD, aggMethodExpr.getMethodName())) {
                     ElasticSqlMethodInvokeHelper.checkTermsAggMethod(aggMethodExpr);
 
                     SQLExpr termsFieldExpr = aggMethodExpr.getParameters().get(0);
@@ -74,7 +74,7 @@ public class QueryGroupByParser implements QueryParser {
 
 
                 //Range Aggregation
-                if (ElasticSqlMethodInvokeHelper.AGG_RANGE_METHOD.equalsIgnoreCase(aggMethodExpr.getMethodName())) {
+                if (ElasticSqlMethodInvokeHelper.isMethodOf(ElasticSqlMethodInvokeHelper.AGG_RANGE_METHOD, aggMethodExpr.getMethodName())) {
                     ElasticSqlMethodInvokeHelper.checkRangeAggMethod(aggMethodExpr);
 
                     List<RangeSegment> rangeSegments = parseRangeSegments(aggMethodExpr, dslContext.getSqlArgs());

+ 1 - 1
src/main/java/org/elasticsearch/dsl/parser/sql/QueryOrderConditionParser.java

@@ -67,7 +67,7 @@ public class QueryOrderConditionParser implements QueryParser {
         if (orderByItem.getExpr() instanceof SQLMethodInvokeExpr) {
             SQLMethodInvokeExpr methodInvokeExpr = (SQLMethodInvokeExpr) orderByItem.getExpr();
             //nvl method
-            if (ElasticSqlMethodInvokeHelper.NVL_METHOD.equalsIgnoreCase(methodInvokeExpr.getMethodName())) {
+            if (ElasticSqlMethodInvokeHelper.isMethodOf(ElasticSqlMethodInvokeHelper.NVL_METHOD, methodInvokeExpr.getMethodName())) {
                 ElasticSqlMethodInvokeHelper.checkNvlMethod(methodInvokeExpr);
                 Object valueArg = ElasticSqlArgTransferHelper.transferSqlArg(methodInvokeExpr.getParameters().get(1), sqlArgs);
                 return parseCondition(methodInvokeExpr.getParameters().get(0), queryAs, new ConditionSortBuilder() {

+ 1 - 1
src/main/java/org/elasticsearch/jdbc/AbstractConnection.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc;
+package org.elasticsearch.jdbc.api;
 
 import java.sql.*;
 import java.util.Properties;

+ 1 - 1
src/main/java/org/elasticsearch/jdbc/AbstractDataSource.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc;
+package org.elasticsearch.jdbc.api;
 
 
 import javax.sql.DataSource;

+ 1 - 1
src/main/java/org/elasticsearch/jdbc/AbstractDriverBasedDataSource.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc;
+package org.elasticsearch.jdbc.api;
 
 import java.sql.Connection;
 import java.sql.SQLException;

+ 1 - 1
src/main/java/org/elasticsearch/jdbc/AbstractFeatureNotSupportedConnection.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc;
+package org.elasticsearch.jdbc.api;
 
 
 import java.sql.*;

+ 1 - 1
src/main/java/org/elasticsearch/jdbc/AbstractFeatureNotSupportedPreparedStatement.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc;
+package org.elasticsearch.jdbc.api;
 
 
 import java.io.InputStream;

+ 1 - 1
src/main/java/org/elasticsearch/jdbc/AbstractFeatureNotSupportedResultSet.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc;
+package org.elasticsearch.jdbc.api;
 
 
 import java.io.InputStream;

+ 1 - 1
src/main/java/org/elasticsearch/jdbc/AbstractFeatureNotSupportedStatement.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc;
+package org.elasticsearch.jdbc.api;
 
 
 import java.sql.*;

+ 5 - 6
src/main/java/org/elasticsearch/jdbc/AbstractResultSet.java

@@ -1,6 +1,5 @@
-package org.elasticsearch.jdbc;
+package org.elasticsearch.jdbc.api;
 
-import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.SQLWarning;
 import java.sql.Statement;
@@ -48,17 +47,17 @@ public abstract class AbstractResultSet extends AbstractFeatureNotSupportedResul
 
     @Override
     public int getFetchDirection() throws SQLException {
-        return ResultSet.FETCH_FORWARD;
+        return FETCH_FORWARD;
     }
 
     @Override
     public int getType() throws SQLException {
-        return ResultSet.TYPE_FORWARD_ONLY;
+        return TYPE_FORWARD_ONLY;
     }
 
     @Override
     public int getConcurrency() throws SQLException {
-        return ResultSet.CONCUR_READ_ONLY;
+        return CONCUR_READ_ONLY;
     }
 
     @Override
@@ -68,7 +67,7 @@ public abstract class AbstractResultSet extends AbstractFeatureNotSupportedResul
 
     @Override
     public int getHoldability() throws SQLException {
-        return ResultSet.CLOSE_CURSORS_AT_COMMIT;
+        return CLOSE_CURSORS_AT_COMMIT;
     }
 
     @Override

+ 1 - 1
src/main/java/org/elasticsearch/jdbc/AbstractStatement.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc;
+package org.elasticsearch.jdbc.api;
 
 import java.sql.ResultSet;
 import java.sql.SQLException;

+ 1 - 1
src/main/java/org/elasticsearch/jdbc/ConnectionProxy.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc;
+package org.elasticsearch.jdbc.api;
 
 import java.sql.Connection;
 

+ 1 - 1
src/main/java/org/elasticsearch/jdbc/DriverManagerDataSource.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc;
+package org.elasticsearch.jdbc.api;
 
 
 import java.sql.Connection;

+ 1 - 1
src/main/java/org/elasticsearch/jdbc/ElasticConnection.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc;
+package org.elasticsearch.jdbc.api;
 
 import org.elasticsearch.client.Client;
 

+ 2 - 2
src/main/java/org/elasticsearch/jdbc/ElasticDatabaseMetaData.java

@@ -1,10 +1,10 @@
-package org.elasticsearch.jdbc;
+package org.elasticsearch.jdbc.api;
 
 import java.sql.*;
 
 public class ElasticDatabaseMetaData implements DatabaseMetaData {
 
-    private static final String ELASTIC_DRIVER_NAME = "org.elasticsearch.jdbc.ElasticDriver";
+    private static final String ELASTIC_DRIVER_NAME = "org.elasticsearch.jdbc.api.ElasticDriver";
     private static final String ELASTIC_DRIVER_PRODUCT_VERSION = "2.4.4";
     private static final Integer ELASTIC_DRIVER_PRODUCT_MAJOR_VERSION = 2;
     private static final Integer ELASTIC_DRIVER_PRODUCT_MINOR_VERSION = 4;

+ 4 - 4
src/main/java/org/elasticsearch/jdbc/ElasticDriver.java

@@ -1,8 +1,8 @@
-package org.elasticsearch.jdbc;
+package org.elasticsearch.jdbc.api;
 
-import org.elasticsearch.jdbc.search.ElasticClientProvider;
-import org.elasticsearch.jdbc.search.ElasticClientProxy;
-import org.elasticsearch.jdbc.search.ElasticClientProxyProviderImpl;
+import org.elasticsearch.jdbc.es.ElasticClientProvider;
+import org.elasticsearch.jdbc.es.ElasticClientProxy;
+import org.elasticsearch.jdbc.es.ElasticClientProxyProviderImpl;
 
 import java.sql.*;
 import java.util.Properties;

+ 1 - 1
src/main/java/org/elasticsearch/jdbc/ElasticPreparedStatement.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc;
+package org.elasticsearch.jdbc.api;
 
 import com.google.common.base.Function;
 import com.google.common.collect.Lists;

+ 1 - 1
src/main/java/org/elasticsearch/jdbc/ElasticResultSet.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc;
+package org.elasticsearch.jdbc.api;
 
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;

+ 1 - 1
src/main/java/org/elasticsearch/jdbc/ElasticResultSetMetaData.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc;
+package org.elasticsearch.jdbc.api;
 
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;

+ 2 - 2
src/main/java/org/elasticsearch/jdbc/ElasticSingleConnectionDataSource.java

@@ -1,8 +1,8 @@
-package org.elasticsearch.jdbc;
+package org.elasticsearch.jdbc.api;
 
 
 import org.elasticsearch.client.Client;
-import org.elasticsearch.jdbc.search.ElasticClientProvider;
+import org.elasticsearch.jdbc.es.ElasticClientProvider;
 import org.elasticsearch.utils.Logger;
 
 import java.lang.reflect.InvocationHandler;

+ 23 - 37
src/main/java/org/elasticsearch/jdbc/ElasticStatement.java

@@ -1,27 +1,39 @@
-package org.elasticsearch.jdbc;
+package org.elasticsearch.jdbc.api;
 
-import com.google.common.collect.Lists;
 import org.elasticsearch.action.search.SearchRequestBuilder;
 import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.dsl.bean.ElasticSqlParseResult;
 import org.elasticsearch.dsl.parser.ElasticSql2DslParser;
-import org.elasticsearch.jdbc.search.JdbcSearchActionExecutor;
-import org.elasticsearch.jdbc.search.JdbcSearchResponse;
-import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.jdbc.es.JdbcSearchActionExecutor;
+import org.elasticsearch.jdbc.es.JdbcSearchResponseExtractor;
 
 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.util.List;
 
 public class ElasticStatement extends AbstractStatement {
     protected ElasticConnection connection;
+    protected ResultSet executeResult;
 
     public ElasticStatement(ElasticConnection connection) {
         this.connection = connection;
     }
 
-    protected ResultSet executeResult;
+    @Override
+    public ResultSet getResultSet() throws SQLException {
+        return executeResult;
+    }
+
+    @Override
+    public Connection getConnection() throws SQLException {
+        return connection;
+    }
+
+    @Override
+    public boolean execute(String sql) throws SQLException {
+        executeQuery(sql);
+        return true;
+    }
 
     @Override
     public ResultSet executeQuery(String sql) throws SQLException {
@@ -45,37 +57,11 @@ public class ElasticStatement extends AbstractStatement {
             searchResponse = JdbcSearchActionExecutor.get().syncExecuteWithException(searchRequest);
         }
         catch (Exception exp) {
-            throw new SQLException(String.format("[ElasticStatement] Failed to execute search request sql[%s]", sql), exp);
+            throw new SQLException(String.format("[ElasticStatement] Failed to execute es request sql[%s]", sql), exp);
         }
 
-        JdbcSearchResponse<String> jdbcSearchResponse = new JdbcSearchResponse<String>();
-        jdbcSearchResponse.setFailedShards(searchResponse.getFailedShards());
-        jdbcSearchResponse.setSuccessfulShards(searchResponse.getSuccessfulShards());
-        jdbcSearchResponse.setTookInMillis(searchResponse.getTookInMillis());
-        jdbcSearchResponse.setTotalShards(searchResponse.getTotalShards());
-        jdbcSearchResponse.setTotalHits(searchResponse.getHits().getTotalHits());
-
-        List<String> hits = Lists.newLinkedList();
-        for (SearchHit searchHit : searchResponse.getHits().getHits()) {
-            hits.add(searchHit.getSourceAsString());
-        }
-        jdbcSearchResponse.setDocList(hits);
-        return executeResult = new ElasticResultSet(this, jdbcSearchResponse.toJson());
-    }
-
-    @Override
-    public boolean execute(String sql) throws SQLException {
-        executeQuery(sql);
-        return true;
-    }
-
-    @Override
-    public ResultSet getResultSet() throws SQLException {
-        return executeResult;
-    }
-
-    @Override
-    public Connection getConnection() throws SQLException {
-        return connection;
+        JdbcSearchResponseExtractor responseExtractor = new JdbcSearchResponseExtractor();
+        String searchResponseGson = responseExtractor.extractSearchResponse(searchResponse);
+        return executeResult = new ElasticResultSet(this, searchResponseGson);
     }
 }

+ 1 - 1
src/main/java/org/elasticsearch/jdbc/SmartDataSource.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc;
+package org.elasticsearch.jdbc.api;
 
 
 import javax.sql.DataSource;

+ 1 - 1
src/main/java/org/elasticsearch/jdbc/search/ElasticClientProvider.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc.search;
+package org.elasticsearch.jdbc.es;
 
 import org.elasticsearch.client.Client;
 

+ 1 - 1
src/main/java/org/elasticsearch/jdbc/search/ElasticClientProxy.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc.search;
+package org.elasticsearch.jdbc.es;
 
 import org.elasticsearch.client.Client;
 

+ 1 - 1
src/main/java/org/elasticsearch/jdbc/search/ElasticClientProxyProviderImpl.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc.search;
+package org.elasticsearch.jdbc.es;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;

+ 2 - 2
src/main/java/org/elasticsearch/jdbc/search/JdbcSearchActionExecutor.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc.search;
+package org.elasticsearch.jdbc.es;
 
 import org.elasticsearch.action.*;
 import org.elasticsearch.utils.Logger;
@@ -47,7 +47,7 @@ public class JdbcSearchActionExecutor {
 
             @Override
             public void onFailure(Throwable throwable) {
-                Logger.error(this, "Execute search req error!", throwable);
+                Logger.error(this, "Execute es req error!", throwable);
             }
         };
     }

+ 15 - 16
src/main/java/org/elasticsearch/jdbc/search/JdbcSearchResponse.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc.search;
+package org.elasticsearch.jdbc.es;
 
 import com.google.gson.Gson;
 
@@ -9,22 +9,14 @@ public class JdbcSearchResponse<T> {
     private int failedShards;
     private int successfulShards;
     private long tookInMillis;
-    private long totalHits;
 
-    private List<T> docList;
+    private long totalCount;
+    private List<T> resultList;
 
     public int getTotalShards() {
         return totalShards;
     }
 
-    public long getTotalHits() {
-        return totalHits;
-    }
-
-    public void setTotalHits(long totalHits) {
-        this.totalHits = totalHits;
-    }
-
     public void setTotalShards(int totalShards) {
         this.totalShards = totalShards;
     }
@@ -53,12 +45,20 @@ public class JdbcSearchResponse<T> {
         this.tookInMillis = tookInMillis;
     }
 
-    public List<T> getDocList() {
-        return docList;
+    public List<T> getResultList() {
+        return resultList;
     }
 
-    public void setDocList(List<T> docList) {
-        this.docList = docList;
+    public void setResultList(List<T> resultList) {
+        this.resultList = resultList;
+    }
+
+    public long getTotalCount() {
+        return totalCount;
+    }
+
+    public void setTotalCount(long totalCount) {
+        this.totalCount = totalCount;
     }
 
     @Override
@@ -69,5 +69,4 @@ public class JdbcSearchResponse<T> {
     public String toJson() {
         return new Gson().toJson(this, JdbcSearchResponse.class);
     }
-
 }

+ 182 - 0
src/main/java/org/elasticsearch/jdbc/es/JdbcSearchResponseExtractor.java

@@ -0,0 +1,182 @@
+package org.elasticsearch.jdbc.es;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.gson.Gson;
+import org.apache.commons.collections.CollectionUtils;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.search.aggregations.Aggregation;
+import org.elasticsearch.search.aggregations.bucket.range.Range;
+import org.elasticsearch.search.aggregations.bucket.range.date.InternalDateRange;
+import org.elasticsearch.search.aggregations.bucket.terms.Terms;
+import org.elasticsearch.search.aggregations.metrics.avg.Avg;
+import org.elasticsearch.search.aggregations.metrics.max.Max;
+import org.elasticsearch.search.aggregations.metrics.min.Min;
+import org.elasticsearch.search.aggregations.metrics.sum.Sum;
+
+import java.util.List;
+import java.util.Map;
+
+public class JdbcSearchResponseExtractor {
+
+    private static final String AGG_RESULT_COUNT_FIELD = "_count";
+
+    public String extractSearchResponse(SearchResponse searchResponse) {
+        JdbcSearchResponse<String> jdbcSearchResponse = null;
+
+        if (Boolean.TRUE == isAggregationResponse(searchResponse)) {
+            jdbcSearchResponse = extractAggregationResult(searchResponse);
+        }
+        else {
+            jdbcSearchResponse = extractQueryResult(searchResponse);
+        }
+        setBasicResponseInfo(searchResponse, jdbcSearchResponse);
+
+        return jdbcSearchResponse.toJson();
+    }
+
+    private boolean isAggregationResponse(SearchResponse response) {
+        if (response.getAggregations() == null) {
+            return false;
+        }
+        List<Aggregation> aggList = response.getAggregations().asList();
+        return CollectionUtils.isNotEmpty(aggList);
+    }
+
+    private void setBasicResponseInfo(SearchResponse searchResponse, JdbcSearchResponse<String> jdbcResponse) {
+        jdbcResponse.setFailedShards(searchResponse.getFailedShards());
+        jdbcResponse.setSuccessfulShards(searchResponse.getSuccessfulShards());
+        jdbcResponse.setTookInMillis(searchResponse.getTookInMillis());
+        jdbcResponse.setTotalShards(searchResponse.getTotalShards());
+    }
+
+    private JdbcSearchResponse<String> extractAggregationResult(SearchResponse searchResponse) {
+        JdbcSearchResponse<String> jdbcSearchResponse = new JdbcSearchResponse<String>();
+        List<Aggregation> aggList = searchResponse.getAggregations().asList();
+
+        Gson defaultGson = new Gson();
+        List<String> resultList = Lists.newArrayList();
+        dfsParseAggregationResponse(aggList, Maps.newTreeMap(), resultList, searchResponse.getHits().getTotalHits(), defaultGson);
+
+        jdbcSearchResponse.setResultList(resultList);
+
+        long totalAggCount = resultList.size();
+        jdbcSearchResponse.setTotalCount(totalAggCount);
+
+        return jdbcSearchResponse;
+    }
+
+    private JdbcSearchResponse<String> extractQueryResult(SearchResponse searchResponse) {
+        JdbcSearchResponse<String> jdbcSearchResponse = new JdbcSearchResponse<String>();
+        jdbcSearchResponse.setTotalCount(searchResponse.getHits().getTotalHits());
+
+        if (searchResponse.getHits() != null && searchResponse.getHits().getHits() != null) {
+            List<String> hits = Lists.newLinkedList();
+            for (SearchHit searchHit : searchResponse.getHits().getHits()) {
+                hits.add(searchHit.getSourceAsString());
+            }
+            jdbcSearchResponse.setResultList(hits);
+        }
+        return jdbcSearchResponse;
+    }
+
+    private void dfsParseAggregationResponse(List<Aggregation> aggregations, Map<String, Object> resultObject,
+                                             List<String> resultList, Long preBucketCount, Gson gson) {
+        if (preBucketCount <= 0) {
+            return;
+        }
+        // if no stats agg, return count
+        if (CollectionUtils.isEmpty(aggregations)) {
+            resultObject.put(AGG_RESULT_COUNT_FIELD, preBucketCount);
+            resultList.add(gson.toJson(resultObject));
+            resultObject.remove(AGG_RESULT_COUNT_FIELD);
+            return;
+        }
+        // process stats agg
+        if (isStatsAgg(aggregations.get(0))) {
+            List<String> statsKeys = Lists.newArrayList();
+            for (Aggregation aggregation : aggregations) {
+                //stats aggregation
+                parseStatsAgg(aggregation, resultObject, statsKeys);
+            }
+
+            resultObject.put(AGG_RESULT_COUNT_FIELD, preBucketCount);
+            statsKeys.add(AGG_RESULT_COUNT_FIELD);
+
+            resultList.add(gson.toJson(resultObject));
+            for (String keyName : statsKeys) {
+                resultObject.remove(keyName);
+            }
+            return;
+        }
+        // process bucket agg
+        for (Aggregation aggregation : aggregations) {
+            //terms aggregation
+            if (aggregation instanceof Terms) {
+                Terms rootTerms = (Terms) aggregation;
+                for (Terms.Bucket bucket : rootTerms.getBuckets()) {
+                    resultObject.put(rootTerms.getName(), bucket.getKey());
+                    dfsParseAggregationResponse(bucket.getAggregations().asList(), resultObject, resultList, bucket.getDocCount(), gson);
+                    resultObject.remove(rootTerms.getName());
+                }
+            }
+            //range aggregation
+            if (aggregation instanceof Range) {
+                if (aggregation instanceof InternalDateRange) {
+                    InternalDateRange rootRange = (InternalDateRange) aggregation;
+                    for (InternalDateRange.Bucket bucket : rootRange.getBuckets()) {
+                        resultObject.put(rootRange.getName(), bucket.getKey());
+                        dfsParseAggregationResponse(bucket.getAggregations().asList(), resultObject, resultList, bucket.getDocCount(), gson);
+                        resultObject.remove(rootRange.getName());
+                    }
+                }
+                else {
+                    Range rootRange = (Range) aggregation;
+                    for (Range.Bucket bucket : rootRange.getBuckets()) {
+                        resultObject.put(rootRange.getName(), bucket.getKey());
+                        dfsParseAggregationResponse(bucket.getAggregations().asList(), resultObject, resultList, bucket.getDocCount(), gson);
+                        resultObject.remove(rootRange.getName());
+                    }
+                }
+            }
+        }
+    }
+
+    private void parseStatsAgg(Aggregation aggregation, Map<String, Object> resultObject, List<String> statsKeys) {
+        if (aggregation instanceof Min) {
+            Min stats = (Min) aggregation;
+            resultObject.put(stats.getName(), getDoubleVal(stats.getValue()));
+            statsKeys.add(stats.getName());
+        }
+
+        if (aggregation instanceof Max) {
+            Max stats = (Max) aggregation;
+            resultObject.put(stats.getName(), getDoubleVal(stats.getValue()));
+            statsKeys.add(stats.getName());
+        }
+
+        if (aggregation instanceof Sum) {
+            Sum stats = (Sum) aggregation;
+            resultObject.put(stats.getName(), getDoubleVal(stats.getValue()));
+            statsKeys.add(stats.getName());
+        }
+
+        if (aggregation instanceof Avg) {
+            Avg stats = (Avg) aggregation;
+            resultObject.put(stats.getName(), getDoubleVal(stats.getValue()));
+            statsKeys.add(stats.getName());
+        }
+    }
+
+    private boolean isStatsAgg(Aggregation aggregation) {
+        return aggregation instanceof Min
+                || aggregation instanceof Max
+                || aggregation instanceof Avg
+                || aggregation instanceof Sum;
+    }
+
+    private double getDoubleVal(Double d) {
+        return d.isNaN() || d.isInfinite() ? 0 : d;
+    }
+}

+ 21 - 24
src/main/java/org/elasticsearch/jdbc/search/JdbcSearchResponseResolver.java

@@ -1,4 +1,4 @@
-package org.elasticsearch.jdbc.search;
+package org.elasticsearch.jdbc.es;
 
 import com.google.common.base.Function;
 import com.google.common.collect.Lists;
@@ -37,21 +37,21 @@ public class JdbcSearchResponseResolver {
         return resolveSearchResponse(typeToken, defaultEsDateFormatGson);
     }
 
-    public <T> JdbcSearchResponse<T> resolveSearchResponse(Class<T> clazz, String dataPattern) throws ResolveSearchResponseException {
-        Gson dateFormatGson = new GsonBuilder().setDateFormat(dataPattern).create();
+    public <T> JdbcSearchResponse<T> resolveSearchResponse(Class<T> clazz, String datePattern) throws ResolveSearchResponseException {
+        Gson dateFormatGson = new GsonBuilder().setDateFormat(datePattern).create();
         return resolveSearchResponse(clazz, dateFormatGson);
     }
 
-    public <T> JdbcSearchResponse<T> resolveSearchResponse(TypeToken<T> typeToken, String dataPattern) throws ResolveSearchResponseException {
-        Gson dateFormatGson = new GsonBuilder().setDateFormat(dataPattern).create();
+    public <T> JdbcSearchResponse<T> resolveSearchResponse(TypeToken<T> typeToken, String datePattern) throws ResolveSearchResponseException {
+        Gson dateFormatGson = new GsonBuilder().setDateFormat(datePattern).create();
         return resolveSearchResponse(typeToken, dateFormatGson);
     }
 
     public <T> JdbcSearchResponse<T> resolveSearchResponse(Class<T> clazz, Gson gson) throws ResolveSearchResponseException {
         return resolveSearchResponse(new ResolveStrategy<T>() {
             @Override
-            public T resolve(String document) {
-                return gson.fromJson(document, clazz);
+            public T resolve(String resultItem) {
+                return gson.fromJson(resultItem, clazz);
             }
         });
     }
@@ -59,8 +59,8 @@ public class JdbcSearchResponseResolver {
     public <T> JdbcSearchResponse<T> resolveSearchResponse(TypeToken<T> typeToken, Gson gson) throws ResolveSearchResponseException {
         return resolveSearchResponse(new ResolveStrategy<T>() {
             @Override
-            public T resolve(String document) {
-                return gson.fromJson(document, typeToken.getType());
+            public T resolve(String resultItem) {
+                return gson.fromJson(resultItem, typeToken.getType());
             }
         });
     }
@@ -71,33 +71,30 @@ public class JdbcSearchResponseResolver {
         JdbcSearchResponse<T> retJdbcSearchResponse = new JdbcSearchResponse<T>();
         setBasicPropertyForResponse(retJdbcSearchResponse, searchRespStrGson);
 
-        // resolve query result set
-        List<T> docList = resolveDocumentList(searchRespStrGson.getDocList(), resolveStrategy);
-        retJdbcSearchResponse.setDocList(docList);
-
-        // todo resolve aggregation result set
+        List<T> resultList = resolveResultList(searchRespStrGson.getResultList(), resolveStrategy);
+        retJdbcSearchResponse.setResultList(resultList);
 
         return retJdbcSearchResponse;
     }
 
-    protected <T> List<T> resolveDocumentList(List<String> documentList, ResolveStrategy<T> resolveStrategy) {
-        if (CollectionUtils.isEmpty(documentList)) {
+    protected <T> List<T> resolveResultList(List<String> resultList, ResolveStrategy<T> resolveStrategy) {
+        if (CollectionUtils.isEmpty(resultList)) {
             return Collections.emptyList();
         }
 
-        List<T> resolvedDocList = null;
+        List<T> resolvedList = null;
         try {
-            resolvedDocList = Lists.transform(documentList, new Function<String, T>() {
+            resolvedList = Lists.transform(resultList, new Function<String, T>() {
                 @Override
-                public T apply(String doc) {
-                    return resolveStrategy.resolve(doc);
+                public T apply(String resultItem) {
+                    return resolveStrategy.resolve(resultItem);
                 }
             });
         }
         catch (Exception ex) {
-            throw new ResolveSearchResponseException("Failed to resolve doc gson");
+            throw new ResolveSearchResponseException("Failed to resolve gson from response");
         }
-        return resolvedDocList;
+        return resolvedList;
     }
 
     protected JdbcSearchResponse<String> parseSearchResponseGson(String searchRespGson) {
@@ -113,13 +110,13 @@ public class JdbcSearchResponseResolver {
 
     protected <T> void setBasicPropertyForResponse(JdbcSearchResponse<T> targetResponse, JdbcSearchResponse<String> sourceResponse) {
         targetResponse.setTotalShards(sourceResponse.getTotalShards());
-        targetResponse.setTotalHits(sourceResponse.getTotalHits());
+        targetResponse.setTotalCount(sourceResponse.getTotalCount());
         targetResponse.setTookInMillis(sourceResponse.getTookInMillis());
         targetResponse.setFailedShards(sourceResponse.getFailedShards());
         targetResponse.setSuccessfulShards(sourceResponse.getSuccessfulShards());
     }
 
     public interface ResolveStrategy<T> {
-        T resolve(String document);
+        T resolve(String resultItem);
     }
 }

+ 55 - 7
src/test/java/org/elasticsearch/jdbc/ElasticDriverTest.java

@@ -1,16 +1,19 @@
 package org.elasticsearch.jdbc;
 
 
+import org.elasticsearch.jdbc.api.ElasticConnection;
+import org.elasticsearch.jdbc.api.ElasticSingleConnectionDataSource;
 import org.elasticsearch.jdbc.bean.Product;
-import org.elasticsearch.jdbc.search.JdbcSearchResponse;
-import org.elasticsearch.jdbc.search.JdbcSearchResponseResolver;
+import org.elasticsearch.jdbc.bean.ProductAggResult;
+import org.elasticsearch.jdbc.es.JdbcSearchResponse;
+import org.elasticsearch.jdbc.es.JdbcSearchResponseResolver;
 import org.junit.Test;
 
 import java.sql.*;
 import java.util.Enumeration;
 
 public class ElasticDriverTest {
-    private static final String driver = "org.elasticsearch.jdbc.ElasticDriver";
+    private static final String driver = "org.elasticsearch.jdbc.api.ElasticDriver";
     private static final String url = "jdbc:elastic:192.168.0.109:9300/judge_cluster";
 
     @Test
@@ -55,7 +58,7 @@ public class ElasticDriverTest {
         JdbcSearchResponseResolver jdbcSearchResponseResolver = new JdbcSearchResponseResolver(responseGson);
         JdbcSearchResponse<Product> jdbcSearchResponse = jdbcSearchResponseResolver.resolveSearchResponse(Product.class);
 
-        for (Product product : jdbcSearchResponse.getDocList()) {
+        for (Product product : jdbcSearchResponse.getResultList()) {
             System.out.println(product.getProductName());
         }
     }
@@ -78,13 +81,13 @@ public class ElasticDriverTest {
         JdbcSearchResponseResolver jdbcSearchResponseResolver = new JdbcSearchResponseResolver(responseGson);
         JdbcSearchResponse<Product> jdbcSearchResponse = jdbcSearchResponseResolver.resolveSearchResponse(Product.class);
 
-        for (Product product : jdbcSearchResponse.getDocList()) {
+        for (Product product : jdbcSearchResponse.getResultList()) {
             System.out.println(product.getProductName());
         }
     }
 
     @Test
-    public void testPrefixQuery2() throws Exception {
+    public void testPrefixAndNestedQuery() throws Exception {
         ElasticSingleConnectionDataSource dataSource = new ElasticSingleConnectionDataSource(url, true);
         dataSource.setDriverClassName(driver);
 
@@ -98,8 +101,53 @@ public class ElasticDriverTest {
         JdbcSearchResponseResolver jdbcSearchResponseResolver = new JdbcSearchResponseResolver(responseGson);
         JdbcSearchResponse<Product> jdbcSearchResponse = jdbcSearchResponseResolver.resolveSearchResponse(Product.class);
 
-        for (Product product : jdbcSearchResponse.getDocList()) {
+        for (Product product : jdbcSearchResponse.getResultList()) {
             System.out.println(product.getProductName());
         }
     }
+
+    @Test
+    public void testGroupBy() throws Exception {
+        ElasticSingleConnectionDataSource dataSource = new ElasticSingleConnectionDataSource(url, true);
+        dataSource.setDriverClassName(driver);
+
+        Connection connection = dataSource.getConnection();
+        String sql = "select min(advicePrice),max(provider.providerLevel) from index.product group by terms(productCode)";
+
+        PreparedStatement preparedStatement = connection.prepareStatement(sql);
+        ResultSet resultSet = preparedStatement.executeQuery();
+
+        String responseGson = resultSet.getString(1);
+
+        JdbcSearchResponseResolver jdbcSearchResponseResolver = new JdbcSearchResponseResolver(responseGson);
+        JdbcSearchResponse<ProductAggResult> jdbcSearchResponse = jdbcSearchResponseResolver.resolveSearchResponse(ProductAggResult.class);
+
+        System.out.println("resp total count: " + jdbcSearchResponse.getTotalCount());
+        for (ProductAggResult aggItem : jdbcSearchResponse.getResultList()) {
+            System.out.println(String.format("code:%s, count:%s, minPrice:%s, providerLevel:%s",
+                    aggItem.getProductCode(), aggItem.getDocCount(), aggItem.getMinAdvicePrice(), aggItem.getProviderLevel()));
+        }
+    }
+
+
+    @Test
+    public void testScriptQuery() throws Exception {
+        ElasticSingleConnectionDataSource dataSource = new ElasticSingleConnectionDataSource(url, true);
+        dataSource.setDriverClassName(driver);
+
+        Connection connection = dataSource.getConnection();
+        String script = "if(doc[\"advicePrice\"].empty) return true; if(doc[\"minPrice\"].value/doc[\"advicePrice\"].value > 0.363) return true; else return false;";
+        String sql = String.format("select * from index.product where script_query('%s')", script);
+
+        PreparedStatement preparedStatement = connection.prepareStatement(sql);
+        ResultSet resultSet = preparedStatement.executeQuery();
+
+        String responseGson = resultSet.getString(1);
+        JdbcSearchResponseResolver jdbcSearchResponseResolver = new JdbcSearchResponseResolver(responseGson);
+        JdbcSearchResponse<Product> jdbcSearchResponse = jdbcSearchResponseResolver.resolveSearchResponse(Product.class);
+
+        for (Product product : jdbcSearchResponse.getResultList()) {
+            System.out.println(String.format("productName:%s, minPrice:%s, advicePrice:%s", product.getProductName(), product.getMinPrice(), product.getAdvicePrice()));
+        }
+    }
 }

+ 48 - 0
src/test/java/org/elasticsearch/jdbc/bean/ProductAggResult.java

@@ -0,0 +1,48 @@
+package org.elasticsearch.jdbc.bean;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.math.BigDecimal;
+
+public class ProductAggResult {
+    @SerializedName("_count")
+    private Long docCount;
+    @SerializedName("agg_productCode")
+    private String productCode;
+    @SerializedName("min_advicePrice")
+    private BigDecimal minAdvicePrice;
+    @SerializedName("max_provider.providerLevel")
+    private Long providerLevel;
+
+    public Long getDocCount() {
+        return docCount;
+    }
+
+    public void setDocCount(Long docCount) {
+        this.docCount = docCount;
+    }
+
+    public String getProductCode() {
+        return productCode;
+    }
+
+    public void setProductCode(String productCode) {
+        this.productCode = productCode;
+    }
+
+    public BigDecimal getMinAdvicePrice() {
+        return minAdvicePrice;
+    }
+
+    public void setMinAdvicePrice(BigDecimal minAdvicePrice) {
+        this.minAdvicePrice = minAdvicePrice;
+    }
+
+    public void setProviderLevel(Long providerLevel) {
+        this.providerLevel = providerLevel;
+    }
+
+    public Long getProviderLevel() {
+        return providerLevel;
+    }
+}

+ 3 - 3
src/test/java/org/elasticsearch/query/SqlParserWhereConditionTest.java

@@ -109,19 +109,19 @@ public class SqlParserWhereConditionTest {
         Assert.assertEquals(parseResult.getWhereCondition().toString(), targetFilter.toString());
         System.out.println(parseResult.toDsl());
 
-        sql = "select id,status from index.order t where t.lastUpdateTime > date('yyyy/MM/dd hh:mm:ss', '2017/01/25 13:32:59')";
+        sql = "select id,status from index.order t where t.lastUpdateTime > to_date('yyyy/MM/dd hh:mm:ss', '2017/01/25 13:32:59')";
         parseResult = sql2DslParser.parse(sql);
         targetFilter = QueryBuilders.boolQuery().must(QueryBuilders.rangeQuery("lastUpdateTime").gt("2017-01-25T13:32:59.000+0800"));
         Assert.assertEquals(parseResult.getWhereCondition().toString(), targetFilter.toString());
         System.out.println(parseResult.toDsl());
 
-        sql = "select id,status from index.order t where t.lastUpdateTime > date('yyyy/MM/dd hh-mm', '2017/01/25 13-32')";
+        sql = "select id,status from index.order t where t.lastUpdateTime > to_date('yyyy/MM/dd hh-mm', '2017/01/25 13-32')";
         parseResult = sql2DslParser.parse(sql);
         targetFilter = QueryBuilders.boolQuery().must(QueryBuilders.rangeQuery("lastUpdateTime").gt("2017-01-25T13:32:00.000+0800"));
         Assert.assertEquals(parseResult.getWhereCondition().toString(), targetFilter.toString());
         System.out.println(parseResult.toDsl());
 
-        sql = "select id,status from index.order t where t.lastUpdateTime between date('yyyy/MM/dd hh-mm', '2017/01/25 13-32') and '2018-10-25'";
+        sql = "select id,status from index.order t where t.lastUpdateTime between to_date('yyyy/MM/dd hh-mm', '2017/01/25 13-32') and '2018-10-25'";
         parseResult = sql2DslParser.parse(sql);
         targetFilter = QueryBuilders.boolQuery().must(
                 QueryBuilders.rangeQuery("lastUpdateTime")