spuerx před 9 roky
rodič
revize
13fcd8c336

+ 0 - 49
src/main/java/org/elasticsearch/dsl/ElasticDslBuilder.java

@@ -1,49 +0,0 @@
-package org.elasticsearch.dsl;
-
-import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
-import com.google.common.collect.ImmutableList;
-import org.elasticsearch.dsl.exception.ElasticSql2DslException;
-import org.elasticsearch.dsl.parser.*;
-import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
-
-import java.util.List;
-import java.util.function.Consumer;
-
-public class ElasticDslBuilder {
-
-    private SQLQueryExpr queryExpr;
-
-    public ElasticDslBuilder(SQLQueryExpr queryExpr) {
-        this.queryExpr = queryExpr;
-    }
-
-    private List<ElasticSqlParser> buildSqlParserChain() {
-        //SQL解析器的顺序不能改变
-        return ImmutableList.of(
-                //解析SQL指定的索引和文档类型
-                new QueryFromParser(),
-                //解析SQL查询指定的where条件
-                new QueryWhereConditionParser(),
-                //解析SQL排序条件
-                new QueryOrderConditionParser(),
-                //解析SQL查询指定的字段
-                new QuerySelectFieldListParser(),
-                //解析SQL的分页条数
-                new QueryLimitSizeParser()
-        );
-    }
-
-    public ElasticDslContext build() {
-        final ElasticDslContext dslContext = new ElasticDslContext(queryExpr);
-        if (queryExpr.getSubQuery().getQuery() instanceof ElasticSqlSelectQueryBlock) {
-            buildSqlParserChain().stream().forEach(new Consumer<ElasticSqlParser>() {
-                @Override
-                public void accept(ElasticSqlParser sqlParser) {
-                    sqlParser.parse(dslContext);
-                }
-            });
-            return dslContext;
-        }
-        throw new ElasticSql2DslException("[syntax error] ElasticSql only support Select Sql, but get: " + queryExpr.getSubQuery().getQuery().getClass());
-    }
-}

+ 13 - 139
src/main/java/org/elasticsearch/dsl/ElasticDslContext.java

@@ -1,161 +1,35 @@
 package org.elasticsearch.dsl;
 
 import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.lang.StringUtils;
-import org.elasticsearch.ElasticMockClient;
-import org.elasticsearch.action.search.SearchRequestBuilder;
-import org.elasticsearch.client.Client;
-import org.elasticsearch.index.query.BoolFilterBuilder;
-import org.elasticsearch.index.query.FilterBuilders;
-import org.elasticsearch.index.query.QueryBuilders;
-import org.elasticsearch.search.sort.SortBuilder;
-import org.elasticsearch.utils.GsonHelper;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.function.Consumer;
 
 public class ElasticDslContext {
-    /*取数开始位置*/
-    private int from = 0;
-    /*取数大小*/
-    private int size = 15;
-    /*查询索引*/
-    private String index;
-    /*查询文档类*/
-    private String type;
-    /*查询索引别名*/
-    private String queryAs;
-    /*查询字段列表*/
-    private List<String> queryFieldList;
-    /*SQL的where条件*/
-    private transient BoolFilterBuilder filterBuilder;
-    /*SQL的order by条件*/
-    private transient List<SortBuilder> sortBuilderList;
     /*SQL*/
-    private transient SQLQueryExpr queryExpr;
+    private SQLQueryExpr queryExpr;
+    /*SQL Args*/
+    private Object[] sqlArgs;
+    /*Result*/
+    private ElasticSqlParseResult parseResult;
 
-    public ElasticDslContext(SQLQueryExpr queryExpr) {
+    public ElasticDslContext(SQLQueryExpr queryExpr, Object[] sqlArgs) {
         this.queryExpr = queryExpr;
+        this.sqlArgs = sqlArgs;
+        parseResult = new ElasticSqlParseResult();
     }
 
-    public void addSort(SortBuilder sortBuilder) {
-        if (sortBuilder != null) {
-            if (sortBuilderList == null) {
-                sortBuilderList = new LinkedList<SortBuilder>();
-            }
-            sortBuilderList.add(sortBuilder);
-        }
-    }
-
-    public BoolFilterBuilder boolFilter() {
-        if (filterBuilder == null) {
-            filterBuilder = FilterBuilders.boolFilter();
-        }
-        return filterBuilder;
-    }
-
-    public List<String> getQueryFieldList() {
-        return queryFieldList;
-    }
-
-    public void setQueryFieldList(List<String> queryFieldList) {
-        this.queryFieldList = queryFieldList;
-    }
-
-    public String getIndex() {
-        return index;
-    }
-
-    public void setIndex(String index) {
-        this.index = index;
-    }
-
-    public String getType() {
-        return type;
-    }
-
-    public void setType(String type) {
-        this.type = type;
-    }
-
-    public int getFrom() {
-        return from;
-    }
-
-    public void setFrom(int from) {
-        this.from = from;
-    }
-
-    public int getSize() {
-        return size;
-    }
-
-    public void setSize(int size) {
-        this.size = size;
-    }
-
-    public String getQueryAs() {
-        return queryAs;
-    }
-
-    public void setQueryAs(String queryAs) {
-        this.queryAs = queryAs;
+    public Object[] getSqlArgs() {
+        return sqlArgs;
     }
 
     public SQLQueryExpr getQueryExpr() {
         return queryExpr;
     }
 
-    public String toDsl(Client client) {
-        return toRequest(client).toString();
-    }
-
-    public String toDsl() {
-        return toDsl(ElasticMockClient.get());
-    }
-
-    public SearchRequestBuilder toRequest(Client client) {
-        final SearchRequestBuilder requestBuilder = new SearchRequestBuilder(client);
-
-        if (size > 100) {
-            requestBuilder.setFrom(from).setSize(100);
-        } else {
-            requestBuilder.setFrom(from).setSize(size);
-        }
-
-        if (StringUtils.isNotBlank(index)) {
-            requestBuilder.setIndices(index);
-        }
-
-        if (StringUtils.isNotBlank(type)) {
-            requestBuilder.setTypes(type);
-        }
-
-        if (filterBuilder != null && filterBuilder.hasClauses()) {
-            requestBuilder.setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), filterBuilder));
-        } else {
-            requestBuilder.setQuery(QueryBuilders.matchAllQuery());
-        }
-
-        if (CollectionUtils.isNotEmpty(sortBuilderList)) {
-            sortBuilderList.stream().forEach(new Consumer<SortBuilder>() {
-                @Override
-                public void accept(SortBuilder sortBuilder) {
-                    requestBuilder.addSort(sortBuilder);
-                }
-            });
-        }
-
-        if (CollectionUtils.isNotEmpty(queryFieldList)) {
-            requestBuilder.setFetchSource(queryFieldList.toArray(new String[queryFieldList.size()]), null);
-        }
-        return requestBuilder;
+    public ElasticSqlParseResult getParseResult() {
+        return parseResult;
     }
 
     @Override
     public String toString() {
-        return GsonHelper.gson.toJson(this) + "\n" + "[DSL]: \n" + toDsl();
+        return parseResult.toDsl();
     }
 }

+ 98 - 0
src/main/java/org/elasticsearch/dsl/ElasticSql2DslParser.java

@@ -0,0 +1,98 @@
+package org.elasticsearch.dsl;
+
+import com.alibaba.druid.sql.ast.SQLExpr;
+import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
+import com.alibaba.druid.sql.parser.ParserException;
+import com.alibaba.druid.sql.parser.Token;
+import com.google.common.collect.ImmutableList;
+import org.elasticsearch.dsl.exception.ElasticSql2DslException;
+import org.elasticsearch.dsl.parser.*;
+import org.elasticsearch.sql.ElasticSqlExprParser;
+import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
+
+import java.lang.reflect.Array;
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Consumer;
+
+public class ElasticSql2DslParser {
+
+    /**
+     * 执行sql到dsl转换
+     *
+     * @param sql 待解析sql
+     * @return 解析结果
+     * @throws ElasticSql2DslException 当解析出现语法错误时抛出
+     */
+    public ElasticSqlParseResult parse(String sql) throws ElasticSql2DslException {
+        return parse(sql, null);
+    }
+
+
+    /**
+     * 执行sql到dsl转换
+     *
+     * @param sql     待解析sql
+     * @param sqlArgs sql动态参数
+     * @return 解析结果
+     * @throws ElasticSql2DslException 当解析出现语法错误时抛出
+     */
+    public ElasticSqlParseResult parse(String sql, Object[] sqlArgs) throws ElasticSql2DslException {
+        SQLQueryExpr queryExpr = null;
+        try {
+            ElasticSqlExprParser elasticSqlExprParser = new ElasticSqlExprParser(sql);
+            SQLExpr sqlQueryExpr = elasticSqlExprParser.expr();
+            check(elasticSqlExprParser, sqlQueryExpr, sqlArgs);
+            queryExpr = (SQLQueryExpr) sqlQueryExpr;
+        } catch (ParserException ex) {
+            throw new ElasticSql2DslException(ex);
+        }
+
+        final ElasticDslContext elasticDslContext = new ElasticDslContext(queryExpr, sqlArgs);
+        if (queryExpr.getSubQuery().getQuery() instanceof ElasticSqlSelectQueryBlock) {
+            buildSqlParserChain().stream().forEach(new Consumer<QueryParser>() {
+                @Override
+                public void accept(QueryParser sqlParser) {
+                    sqlParser.parse(elasticDslContext);
+                }
+            });
+        } else {
+            throw new ElasticSql2DslException("[syntax error] ElasticSql only support Select Sql");
+        }
+        return elasticDslContext.getParseResult();
+    }
+
+    private void check(ElasticSqlExprParser sqlExprParser, SQLExpr sqlQueryExpr, Object[] sqlArgs) {
+        if (sqlExprParser.getLexer().token() != Token.EOF) {
+            throw new ElasticSql2DslException("[syntax error] Sql last token is not EOF");
+        }
+
+        if (!(sqlQueryExpr instanceof SQLQueryExpr)) {
+            throw new ElasticSql2DslException("[syntax error] Sql is not select sql");
+        }
+
+        if (sqlArgs != null && sqlArgs.length > 0) {
+            for (Object arg : sqlArgs) {
+                if (arg instanceof Array || arg instanceof Collection) {
+                    throw new ElasticSql2DslException("[syntax error] Sql arg cannot support collection type");
+                }
+            }
+        }
+    }
+
+    private List<QueryParser> buildSqlParserChain() {
+        //SQL解析器的顺序不能改变
+        return ImmutableList.of(
+                //解析SQL指定的索引和文档类型
+                new QueryFromParser(),
+                //解析SQL查询指定的where条件
+                new QueryWhereConditionParser(),
+                //解析SQL排序条件
+                new QueryOrderConditionParser(),
+                //解析SQL查询指定的字段
+                new QuerySelectFieldListParser(),
+                //解析SQL的分页条数
+                new QueryLimitSizeParser()
+        );
+    }
+}

+ 149 - 0
src/main/java/org/elasticsearch/dsl/ElasticSqlParseResult.java

@@ -0,0 +1,149 @@
+package org.elasticsearch.dsl;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
+import org.elasticsearch.ElasticMockClient;
+import org.elasticsearch.action.search.SearchRequestBuilder;
+import org.elasticsearch.client.Client;
+import org.elasticsearch.index.query.BoolFilterBuilder;
+import org.elasticsearch.index.query.FilterBuilders;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.search.sort.SortBuilder;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.function.Consumer;
+
+public class ElasticSqlParseResult {
+    /*取数开始位置*/
+    private int from = 0;
+    /*取数大小*/
+    private int size = 15;
+    /*查询索引*/
+    private String index;
+    /*查询文档类*/
+    private String type;
+    /*查询索引别名*/
+    private String queryAs;
+    /*查询字段列表*/
+    private List<String> queryFieldList;
+    /*SQL的where条件*/
+    private transient BoolFilterBuilder filterBuilder;
+    /*SQL的order by条件*/
+    private transient List<SortBuilder> sortBuilderList;
+
+    public void addSort(SortBuilder sortBuilder) {
+        if (sortBuilder != null) {
+            if (sortBuilderList == null) {
+                sortBuilderList = new LinkedList<SortBuilder>();
+            }
+            sortBuilderList.add(sortBuilder);
+        }
+    }
+
+    public BoolFilterBuilder boolFilter() {
+        if (filterBuilder == null) {
+            filterBuilder = FilterBuilders.boolFilter();
+        }
+        return filterBuilder;
+    }
+
+    public List<String> getQueryFieldList() {
+        return queryFieldList;
+    }
+
+    public void setQueryFieldList(List<String> queryFieldList) {
+        this.queryFieldList = queryFieldList;
+    }
+
+    public String getIndex() {
+        return index;
+    }
+
+    public void setIndex(String index) {
+        this.index = index;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public int getFrom() {
+        return from;
+    }
+
+    public void setFrom(int from) {
+        this.from = from;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    public void setSize(int size) {
+        this.size = size;
+    }
+
+    public String getQueryAs() {
+        return queryAs;
+    }
+
+    public void setQueryAs(String queryAs) {
+        this.queryAs = queryAs;
+    }
+
+    public SearchRequestBuilder toRequest(Client client) {
+        final SearchRequestBuilder requestBuilder = new SearchRequestBuilder(client);
+
+        if (size > 100) {
+            requestBuilder.setFrom(from).setSize(100);
+        } else {
+            requestBuilder.setFrom(from).setSize(size);
+        }
+
+        if (StringUtils.isNotBlank(index)) {
+            requestBuilder.setIndices(index);
+        }
+
+        if (StringUtils.isNotBlank(type)) {
+            requestBuilder.setTypes(type);
+        }
+
+        if (filterBuilder != null && filterBuilder.hasClauses()) {
+            requestBuilder.setQuery(QueryBuilders.filteredQuery(null, filterBuilder));
+        } else {
+            requestBuilder.setQuery(QueryBuilders.matchAllQuery());
+        }
+
+        if (CollectionUtils.isNotEmpty(sortBuilderList)) {
+            sortBuilderList.stream().forEach(new Consumer<SortBuilder>() {
+                @Override
+                public void accept(SortBuilder sortBuilder) {
+                    requestBuilder.addSort(sortBuilder);
+                }
+            });
+        }
+
+        if (CollectionUtils.isNotEmpty(queryFieldList)) {
+            requestBuilder.setFetchSource(queryFieldList.toArray(new String[queryFieldList.size()]), null);
+        }
+        return requestBuilder;
+    }
+
+    public String toDsl(Client client) {
+        return toRequest(client).toString();
+    }
+
+    public String toDsl() {
+        return toDsl(ElasticMockClient.get());
+    }
+
+    @Override
+    public String toString() {
+        return toDsl();
+    }
+}

+ 75 - 0
src/main/java/org/elasticsearch/dsl/ElasticSqlParseUtil.java

@@ -0,0 +1,75 @@
+package org.elasticsearch.dsl;
+
+import com.alibaba.druid.sql.ast.SQLExpr;
+import com.alibaba.druid.sql.ast.expr.*;
+import org.elasticsearch.dsl.exception.ElasticSql2DslException;
+import org.elasticsearch.dsl.parser.helper.ElasticSqlDateParseHelper;
+
+import java.util.List;
+
+public class ElasticSqlParseUtil {
+
+    public static Object[] transferSqlArgs(List<SQLExpr> exprList, Object[] sqlArgs) {
+        Object[] values = new Object[exprList.size()];
+        for (int idx = 0; idx < exprList.size(); idx++) {
+            values[idx] = transferSqlArg(exprList.get(idx), sqlArgs);
+        }
+        return values;
+    }
+
+    public static Object transferSqlArg(SQLExpr expr, Object[] sqlArgs) {
+        if (expr instanceof SQLVariantRefExpr) {
+            SQLVariantRefExpr varRefExpr = (SQLVariantRefExpr) expr;
+            if (sqlArgs == null || sqlArgs.length == 0) {
+                throw new ElasticSql2DslException("[syntax error] Sql args cannot be blank");
+            }
+            if (varRefExpr.getIndex() >= sqlArgs.length) {
+                throw new ElasticSql2DslException("[syntax error] Sql args out of index: " + varRefExpr.getIndex());
+            }
+            //解析date类型
+            if (ElasticSqlDateParseHelper.isDateArgObjectValue(sqlArgs[varRefExpr.getIndex()])) {
+                return ElasticSqlDateParseHelper.formatDefaultEsDateObjectValue(sqlArgs[varRefExpr.getIndex()]);
+            }
+            return sqlArgs[varRefExpr.getIndex()];
+        }
+        if (expr instanceof SQLIntegerExpr) {
+            return ((SQLIntegerExpr) expr).getNumber().longValue();
+        }
+        if (expr instanceof SQLNumberExpr) {
+            return ((SQLNumberExpr) expr).getNumber().doubleValue();
+        }
+        if (expr instanceof SQLCharExpr) {
+            Object textObject = ((SQLCharExpr) expr).getValue();
+            //解析date类型
+            if (textObject instanceof String && ElasticSqlDateParseHelper.isDateArgStringValue((String) textObject)) {
+                return ElasticSqlDateParseHelper.formatDefaultEsDateStringValue((String) textObject);
+            }
+            return textObject;
+        }
+        if (expr instanceof SQLMethodInvokeExpr) {
+            SQLMethodInvokeExpr methodExpr = (SQLMethodInvokeExpr) expr;
+
+            //解析date函数
+            if (ElasticSqlDateParseHelper.isDateMethod(methodExpr)) {
+                ElasticSqlDateParseHelper.checkDateMethod(methodExpr);
+                String patternArg = (String) ElasticSqlParseUtil.transferSqlArg(methodExpr.getParameters().get(0), sqlArgs);
+                String timeValArg = (String) ElasticSqlParseUtil.transferSqlArg(methodExpr.getParameters().get(1), sqlArgs);
+                return ElasticSqlDateParseHelper.formatDefaultEsDate(patternArg, timeValArg);
+            }
+        }
+        throw new ElasticSql2DslException("[syntax error] Can not support arg type: " + expr.toString());
+    }
+
+    public static boolean isValidBinOperator(SQLBinaryOperator binaryOperator) {
+        return binaryOperator == SQLBinaryOperator.Equality
+                || binaryOperator == SQLBinaryOperator.NotEqual
+                || binaryOperator == SQLBinaryOperator.LessThanOrGreater
+                || binaryOperator == SQLBinaryOperator.GreaterThan
+                || binaryOperator == SQLBinaryOperator.GreaterThanOrEqual
+                || binaryOperator == SQLBinaryOperator.LessThan
+                || binaryOperator == SQLBinaryOperator.LessThanOrEqual
+                || binaryOperator == SQLBinaryOperator.LessThanOrGreater
+                || binaryOperator == SQLBinaryOperator.Is
+                || binaryOperator == SQLBinaryOperator.IsNot;
+    }
+}

+ 6 - 0
src/main/java/org/elasticsearch/dsl/exception/ElasticSql2DslException.java

@@ -1,7 +1,13 @@
 package org.elasticsearch.dsl.exception;
 
+import com.alibaba.druid.sql.parser.ParserException;
+
 public class ElasticSql2DslException extends RuntimeException {
     public ElasticSql2DslException(String message) {
         super(message);
     }
+
+    public ElasticSql2DslException(ParserException ex) {
+        super(ex);
+    }
 }

+ 0 - 49
src/main/java/org/elasticsearch/dsl/parser/ElasticSql2DslParser.java

@@ -1,49 +0,0 @@
-package org.elasticsearch.dsl.parser;
-
-import com.alibaba.druid.sql.ast.SQLExpr;
-import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
-import com.alibaba.druid.sql.parser.Token;
-import org.elasticsearch.common.lang3.StringUtils;
-import org.elasticsearch.dsl.ElasticDslBuilder;
-import org.elasticsearch.dsl.ElasticDslContext;
-import org.elasticsearch.dsl.exception.ElasticSql2DslException;
-import org.elasticsearch.sql.ElasticSqlExprParser;
-
-public class ElasticSql2DslParser {
-
-    private String sql;
-
-    public ElasticSql2DslParser(String sql) {
-        if (StringUtils.isBlank(sql)) {
-            throw new IllegalArgumentException("constructor args [sql] cannot be blank!");
-        }
-        this.sql = sql;
-    }
-
-    /**
-     * 执行sql到dsl转换
-     *
-     * @return 解析后dsl上下文
-     * @throws ElasticSql2DslException 当解析出现语法错误时抛出
-     */
-    public ElasticDslContext parse() {
-        ElasticSqlExprParser elasticSqlExprParser = new ElasticSqlExprParser(sql);
-        SQLExpr sqlQueryExpr = elasticSqlExprParser.expr();
-
-        check(elasticSqlExprParser, sqlQueryExpr);
-
-        ElasticDslBuilder dslBuilder = new ElasticDslBuilder((SQLQueryExpr) sqlQueryExpr);
-        return dslBuilder.build();
-    }
-
-    private void check(ElasticSqlExprParser sqlExprParser, SQLExpr sqlQueryExpr) {
-        if (sqlExprParser.getLexer().token() != Token.EOF) {
-            throw new ElasticSql2DslException("[syntax error] Sql last token is not EOF");
-        }
-
-        if (!(sqlQueryExpr instanceof SQLQueryExpr)) {
-            throw new ElasticSql2DslException("[syntax error] Sql is not select sql");
-        }
-    }
-
-}

+ 0 - 112
src/main/java/org/elasticsearch/dsl/parser/ElasticSqlParseUtil.java

@@ -1,112 +0,0 @@
-package org.elasticsearch.dsl.parser;
-
-import com.alibaba.druid.sql.ast.SQLExpr;
-import com.alibaba.druid.sql.ast.expr.*;
-import com.google.common.base.Function;
-import com.google.common.collect.Lists;
-import org.apache.commons.collections.CollectionUtils;
-import org.elasticsearch.dsl.exception.ElasticSql2DslException;
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.List;
-import java.util.TimeZone;
-
-public class ElasticSqlParseUtil {
-    public static Object[] transferSqlArgs(List<SQLExpr> exprList) {
-        SQLExpr firstArg = exprList.get(0);
-        if (firstArg instanceof SQLIntegerExpr) {
-            return toObjectArray(Lists.transform(exprList, new Function<SQLExpr, Object>() {
-                @Override
-                public Object apply(SQLExpr sqlExpr) {
-                    return ((SQLIntegerExpr) sqlExpr).getNumber().longValue();
-                }
-            }));
-        }
-        if (firstArg instanceof SQLNumberExpr) {
-            return toObjectArray(Lists.transform(exprList, new Function<SQLExpr, Object>() {
-                @Override
-                public Object apply(SQLExpr sqlExpr) {
-                    return ((SQLNumberExpr) sqlExpr).getNumber().doubleValue();
-                }
-            }));
-        }
-        if (firstArg instanceof SQLCharExpr) {
-            return toObjectArray(Lists.transform(exprList, new Function<SQLExpr, Object>() {
-                @Override
-                public Object apply(SQLExpr sqlExpr) {
-                    return ((SQLCharExpr) sqlExpr).getValue();
-                }
-            }));
-        }
-        throw new ElasticSql2DslException("[syntax error] Can not support arg type: " + firstArg.getClass());
-    }
-
-    public static Object transferSqlArg(SQLExpr expr) {
-        if (expr instanceof SQLIntegerExpr) {
-            return ((SQLIntegerExpr) expr).getNumber().longValue();
-        }
-        if (expr instanceof SQLNumberExpr) {
-            return ((SQLNumberExpr) expr).getNumber().doubleValue();
-        }
-        if (expr instanceof SQLCharExpr) {
-            return ((SQLCharExpr) expr).getValue();
-        }
-        if (expr instanceof SQLMethodInvokeExpr) {
-            SQLMethodInvokeExpr dateMethodExpr = (SQLMethodInvokeExpr) expr;
-            checkDateMethod(dateMethodExpr);
-            final String patternArg = (String) ElasticSqlParseUtil.transferSqlArg(dateMethodExpr.getParameters().get(0));
-            final String timeValArg = (String) ElasticSqlParseUtil.transferSqlArg(dateMethodExpr.getParameters().get(1));
-            try {
-                SimpleDateFormat dateFormat = new SimpleDateFormat(patternArg);
-                Date date = dateFormat.parse(timeValArg);
-
-                dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
-                return dateFormat.format(date);
-            } catch (ParseException pex) {
-                throw new ElasticSql2DslException("[syntax error] Parse time arg error: " + expr.toString());
-            }
-        }
-        throw new ElasticSql2DslException("[syntax error] Can not support arg type: " + expr.toString());
-    }
-
-    private static void checkDateMethod(SQLMethodInvokeExpr dateInvokeExpr) {
-        if (!"date".equalsIgnoreCase(dateInvokeExpr.getMethodName())) {
-            throw new ElasticSql2DslException("[syntax error] ElasticSql not support method:" + dateInvokeExpr.getMethodName());
-        }
-
-        if (CollectionUtils.isEmpty(dateInvokeExpr.getParameters()) || dateInvokeExpr.getParameters().size() != 2) {
-            throw new ElasticSql2DslException(String.format("[syntax error] There is no %s args method named nvl",
-                    dateInvokeExpr.getParameters() != null ? dateInvokeExpr.getParameters().size() : 0));
-        }
-
-        SQLExpr patternArg = dateInvokeExpr.getParameters().get(0);
-        SQLExpr timeValArg = dateInvokeExpr.getParameters().get(1);
-
-        if (!(patternArg instanceof SQLCharExpr)) {
-            throw new ElasticSql2DslException("[syntax error] The first arg of date method should be a time pattern");
-        }
-
-        if (!(timeValArg instanceof SQLCharExpr)) {
-            throw new ElasticSql2DslException("[syntax error] The second arg of date method should be a string of time");
-        }
-    }
-
-    private static <T> Object[] toObjectArray(List<T> list) {
-        return list.toArray(new Object[list.size()]);
-    }
-
-    public static boolean isValidBinOperator(SQLBinaryOperator binaryOperator) {
-        return binaryOperator == SQLBinaryOperator.Equality
-                || binaryOperator == SQLBinaryOperator.NotEqual
-                || binaryOperator == SQLBinaryOperator.LessThanOrGreater
-                || binaryOperator == SQLBinaryOperator.GreaterThan
-                || binaryOperator == SQLBinaryOperator.GreaterThanOrEqual
-                || binaryOperator == SQLBinaryOperator.LessThan
-                || binaryOperator == SQLBinaryOperator.LessThanOrEqual
-                || binaryOperator == SQLBinaryOperator.LessThanOrGreater
-                || binaryOperator == SQLBinaryOperator.Is
-                || binaryOperator == SQLBinaryOperator.IsNot;
-    }
-}

+ 5 - 6
src/main/java/org/elasticsearch/dsl/parser/QueryFromParser.java

@@ -3,21 +3,20 @@ package org.elasticsearch.dsl.parser;
 import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
 import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
 import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
-import com.google.common.collect.ImmutableList;
 import org.elasticsearch.dsl.ElasticDslContext;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
 
-public class QueryFromParser implements ElasticSqlParser {
+public class QueryFromParser implements QueryParser {
     @Override
     public void parse(ElasticDslContext dslContext) {
         ElasticSqlSelectQueryBlock queryBlock = (ElasticSqlSelectQueryBlock) dslContext.getQueryExpr().getSubQuery().getQuery();
         if (queryBlock.getFrom() instanceof SQLExprTableSource) {
             SQLExprTableSource tableSource = (SQLExprTableSource) queryBlock.getFrom();
-            dslContext.setQueryAs(tableSource.getAlias());
+            dslContext.getParseResult().setQueryAs(tableSource.getAlias());
 
             if (tableSource.getExpr() instanceof SQLIdentifierExpr) {
-                dslContext.setIndex(((SQLIdentifierExpr) tableSource.getExpr()).getName());
+                dslContext.getParseResult().setIndex(((SQLIdentifierExpr) tableSource.getExpr()).getName());
                 return;
             }
             if (tableSource.getExpr() instanceof SQLPropertyExpr) {
@@ -26,8 +25,8 @@ public class QueryFromParser implements ElasticSqlParser {
                 if (!(idxExpr.getOwner() instanceof SQLIdentifierExpr)) {
                     throw new ElasticSql2DslException("[syntax error] From table should like [index].[type]");
                 }
-                dslContext.setIndex(((SQLIdentifierExpr) idxExpr.getOwner()).getName());
-                dslContext.setType(idxExpr.getName());
+                dslContext.getParseResult().setIndex(((SQLIdentifierExpr) idxExpr.getOwner()).getName());
+                dslContext.getParseResult().setType(idxExpr.getName());
                 return;
             }
         }

+ 5 - 5
src/main/java/org/elasticsearch/dsl/parser/QueryLimitSizeParser.java

@@ -5,7 +5,7 @@ import org.elasticsearch.dsl.ElasticDslContext;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
 
-public class QueryLimitSizeParser implements ElasticSqlParser {
+public class QueryLimitSizeParser implements QueryParser {
     @Override
     public void parse(ElasticDslContext dslContext) {
         ElasticSqlSelectQueryBlock queryBlock = (ElasticSqlSelectQueryBlock) dslContext.getQueryExpr().getSubQuery().getQuery();
@@ -13,15 +13,15 @@ public class QueryLimitSizeParser implements ElasticSqlParser {
             if (!(queryBlock.getLimit().getOffset() instanceof SQLIntegerExpr)) {
                 throw new ElasticSql2DslException("[syntax error] Sql limit expr offset should be a non-negative number");
             }
-            dslContext.setFrom(((SQLIntegerExpr) queryBlock.getLimit().getOffset()).getNumber().intValue());
+            dslContext.getParseResult().setFrom(((SQLIntegerExpr) queryBlock.getLimit().getOffset()).getNumber().intValue());
 
             if (!(queryBlock.getLimit().getRowCount() instanceof SQLIntegerExpr)) {
                 throw new ElasticSql2DslException("[syntax error] Sql limit expr row count should be a non-negative number");
             }
-            dslContext.setSize(((SQLIntegerExpr) queryBlock.getLimit().getRowCount()).getNumber().intValue());
+            dslContext.getParseResult().setSize(((SQLIntegerExpr) queryBlock.getLimit().getRowCount()).getNumber().intValue());
         } else {
-            dslContext.setFrom(0);
-            dslContext.setSize(15);
+            dslContext.getParseResult().setFrom(0);
+            dslContext.getParseResult().setSize(15);
         }
     }
 }

+ 9 - 7
src/main/java/org/elasticsearch/dsl/parser/QueryOrderConditionParser.java

@@ -8,7 +8,9 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
 import com.google.common.collect.Lists;
 import org.apache.commons.collections.CollectionUtils;
 import org.elasticsearch.dsl.ElasticDslContext;
+import org.elasticsearch.dsl.ElasticSqlParseUtil;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
+import org.elasticsearch.dsl.parser.helper.ElasticSqlIdentifierHelper;
 import org.elasticsearch.search.sort.FieldSortBuilder;
 import org.elasticsearch.search.sort.SortBuilder;
 import org.elasticsearch.search.sort.SortBuilders;
@@ -17,22 +19,22 @@ import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
 
 import java.util.List;
 
-public class QueryOrderConditionParser implements ElasticSqlParser {
+public class QueryOrderConditionParser implements QueryParser {
     @Override
     public void parse(ElasticDslContext dslContext) {
         ElasticSqlSelectQueryBlock queryBlock = (ElasticSqlSelectQueryBlock) dslContext.getQueryExpr().getSubQuery().getQuery();
         SQLOrderBy sqlOrderBy = queryBlock.getOrderBy();
         if (sqlOrderBy != null && CollectionUtils.isNotEmpty(sqlOrderBy.getItems())) {
             for (SQLSelectOrderByItem orderByItem : sqlOrderBy.getItems()) {
-                SortBuilder orderBy = parseOrderCondition(orderByItem, dslContext.getQueryAs());
+                SortBuilder orderBy = parseOrderCondition(orderByItem, dslContext.getParseResult().getQueryAs(), dslContext.getSqlArgs());
                 if (orderBy != null) {
-                    dslContext.addSort(orderBy);
+                    dslContext.getParseResult().addSort(orderBy);
                 }
             }
         }
     }
 
-    private SortBuilder parseOrderCondition(final SQLSelectOrderByItem orderByItem, String queryAs) {
+    private SortBuilder parseOrderCondition(final SQLSelectOrderByItem orderByItem, String queryAs, Object[] sqlArgs) {
         if (orderByItem.getExpr() instanceof SQLPropertyExpr || orderByItem.getExpr() instanceof SQLIdentifierExpr) {
             return parseCondition(orderByItem.getExpr(), queryAs, new ConditionSortBuilder() {
                 @Override
@@ -49,7 +51,7 @@ public class QueryOrderConditionParser implements ElasticSqlParser {
             final SQLMethodInvokeExpr methodInvokeExpr = (SQLMethodInvokeExpr) orderByItem.getExpr();
             checkNvlMethod(methodInvokeExpr);
 
-            final Object valueArg = ElasticSqlParseUtil.transferSqlArg(methodInvokeExpr.getParameters().get(1));
+            final Object valueArg = ElasticSqlParseUtil.transferSqlArg(methodInvokeExpr.getParameters().get(1), sqlArgs);
             return parseCondition(methodInvokeExpr.getParameters().get(0), queryAs, new ConditionSortBuilder() {
                 @Override
                 public FieldSortBuilder buildSort(String idfName) {
@@ -107,13 +109,13 @@ public class QueryOrderConditionParser implements ElasticSqlParser {
 
     private SortBuilder parseCondition(SQLExpr sqlExpr, String queryAs, final ConditionSortBuilder sortBuilder) {
         final List<SortBuilder> tmpSortList = Lists.newLinkedList();
-        ElasticSqlIdfParser.parseSqlIdentifier(sqlExpr, queryAs, new ElasticSqlIdfParser.ElasticSqlTopIdfFunc() {
+        ElasticSqlIdentifierHelper.parseSqlIdentifier(sqlExpr, queryAs, new ElasticSqlIdentifierHelper.ElasticSqlTopIdfFunc() {
             @Override
             public void parse(String idfName) {
                 FieldSortBuilder originalSort = sortBuilder.buildSort(idfName);
                 tmpSortList.add(originalSort);
             }
-        }, new ElasticSqlIdfParser.ElasticSqlNestIdfFunc() {
+        }, new ElasticSqlIdentifierHelper.ElasticSqlNestIdfFunc() {
             @Override
             public void parse(String nestPath, String idfName) {
                 FieldSortBuilder originalSort = sortBuilder.buildSort(idfName);

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

@@ -3,6 +3,6 @@ package org.elasticsearch.dsl.parser;
 import org.elasticsearch.dsl.ElasticDslContext;
 
 @FunctionalInterface
-public interface ElasticSqlParser {
+public interface QueryParser {
     void parse(ElasticDslContext dslContext);
 }

+ 5 - 4
src/main/java/org/elasticsearch/dsl/parser/QuerySelectFieldListParser.java

@@ -3,11 +3,12 @@ package org.elasticsearch.dsl.parser;
 import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
 import com.google.common.collect.Lists;
 import org.elasticsearch.dsl.ElasticDslContext;
+import org.elasticsearch.dsl.parser.helper.ElasticSqlIdentifierHelper;
 import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
 
 import java.util.List;
 
-public class QuerySelectFieldListParser implements ElasticSqlParser {
+public class QuerySelectFieldListParser implements QueryParser {
 
     public static final String SQL_FIELD_MATCH_ALL = "*";
 
@@ -17,20 +18,20 @@ public class QuerySelectFieldListParser implements ElasticSqlParser {
 
         final List<String> selectFields = Lists.newLinkedList();
         for (SQLSelectItem selectField : queryBlock.getSelectList()) {
-            ElasticSqlIdfParser.parseSqlIdentifier(selectField.getExpr(), dslContext.getQueryAs(), new ElasticSqlIdfParser.ElasticSqlTopIdfFunc() {
+            ElasticSqlIdentifierHelper.parseSqlIdentifier(selectField.getExpr(), dslContext.getParseResult().getQueryAs(), new ElasticSqlIdentifierHelper.ElasticSqlTopIdfFunc() {
                 @Override
                 public void parse(String idfName) {
                     if (!SQL_FIELD_MATCH_ALL.equals(idfName)) {
                         selectFields.add(idfName);
                     }
                 }
-            }, new ElasticSqlIdfParser.ElasticSqlNestIdfFunc() {
+            }, new ElasticSqlIdentifierHelper.ElasticSqlNestIdfFunc() {
                 @Override
                 public void parse(String nestPath, String idfName) {
                     selectFields.add(String.format("%s.%s", nestPath, idfName));
                 }
             });
         }
-        dslContext.setQueryFieldList(selectFields);
+        dslContext.getParseResult().setQueryFieldList(selectFields);
     }
 }

+ 18 - 16
src/main/java/org/elasticsearch/dsl/parser/QueryWhereConditionParser.java

@@ -5,7 +5,9 @@ import com.alibaba.druid.sql.ast.expr.*;
 import com.google.common.collect.Lists;
 import org.apache.commons.collections.CollectionUtils;
 import org.elasticsearch.dsl.ElasticDslContext;
+import org.elasticsearch.dsl.ElasticSqlParseUtil;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
+import org.elasticsearch.dsl.parser.helper.ElasticSqlIdentifierHelper;
 import org.elasticsearch.index.query.BoolFilterBuilder;
 import org.elasticsearch.index.query.FilterBuilder;
 import org.elasticsearch.index.query.FilterBuilders;
@@ -14,21 +16,21 @@ import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
 import java.util.List;
 import java.util.function.Consumer;
 
-public class QueryWhereConditionParser implements ElasticSqlParser {
+public class QueryWhereConditionParser implements QueryParser {
     @Override
     public void parse(ElasticDslContext dslContext) {
         ElasticSqlSelectQueryBlock queryBlock = (ElasticSqlSelectQueryBlock) dslContext.getQueryExpr().getSubQuery().getQuery();
         if (queryBlock.getWhere() != null) {
             SqlCondition sqlCondition = parseFilterCondition(dslContext, queryBlock.getWhere());
             if (!sqlCondition.isAndOr()) {
-                dslContext.boolFilter().must(sqlCondition.getFilterList().get(0));
+                dslContext.getParseResult().boolFilter().must(sqlCondition.getFilterList().get(0));
             } else {
                 for (FilterBuilder filter : sqlCondition.getFilterList()) {
                     if (sqlCondition.getOperator() == SQLBinaryOperator.BooleanAnd) {
-                        dslContext.boolFilter().must(filter);
+                        dslContext.getParseResult().boolFilter().must(filter);
                     }
                     if (sqlCondition.getOperator() == SQLBinaryOperator.BooleanOr) {
-                        dslContext.boolFilter().should(filter);
+                        dslContext.getParseResult().boolFilter().should(filter);
                     }
                 }
             }
@@ -99,8 +101,8 @@ public class QueryWhereConditionParser implements ElasticSqlParser {
 
                 //EQ NEQ
                 if (SQLBinaryOperator.Equality == binaryOperator || SQLBinaryOperator.LessThanOrGreater == binaryOperator || SQLBinaryOperator.NotEqual == binaryOperator) {
-                    final Object targetVal = ElasticSqlParseUtil.transferSqlArg(sqlBinOpExpr.getRight());
-                    return parseCondition(sqlBinOpExpr.getLeft(), dslContext.getQueryAs(), new ConditionFilterBuilder() {
+                    final Object targetVal = ElasticSqlParseUtil.transferSqlArg(sqlBinOpExpr.getRight(), dslContext.getSqlArgs());
+                    return parseCondition(sqlBinOpExpr.getLeft(), dslContext.getParseResult().getQueryAs(), new ConditionFilterBuilder() {
                         @Override
                         public FilterBuilder buildFilter(String idfName) {
                             FilterBuilder eqFilter = FilterBuilders.termFilter(idfName, targetVal);
@@ -116,8 +118,8 @@ public class QueryWhereConditionParser implements ElasticSqlParser {
                 //GT GTE LT LTE
                 if (SQLBinaryOperator.GreaterThan == binaryOperator || SQLBinaryOperator.GreaterThanOrEqual == binaryOperator
                         || SQLBinaryOperator.LessThan == binaryOperator || SQLBinaryOperator.LessThanOrEqual == binaryOperator) {
-                    final Object targetVal = ElasticSqlParseUtil.transferSqlArg(sqlBinOpExpr.getRight());
-                    return parseCondition(sqlBinOpExpr.getLeft(), dslContext.getQueryAs(), new ConditionFilterBuilder() {
+                    final Object targetVal = ElasticSqlParseUtil.transferSqlArg(sqlBinOpExpr.getRight(), dslContext.getSqlArgs());
+                    return parseCondition(sqlBinOpExpr.getLeft(), dslContext.getParseResult().getQueryAs(), new ConditionFilterBuilder() {
                         @Override
                         public FilterBuilder buildFilter(String idfName) {
                             FilterBuilder rangeFilter = null;
@@ -140,7 +142,7 @@ public class QueryWhereConditionParser implements ElasticSqlParser {
                     if (!(sqlBinOpExpr.getRight() instanceof SQLNullExpr)) {
                         throw new ElasticSql2DslException("[syntax error] Is/IsNot expr right part should be null");
                     }
-                    return parseCondition(sqlBinOpExpr.getLeft(), dslContext.getQueryAs(), new ConditionFilterBuilder() {
+                    return parseCondition(sqlBinOpExpr.getLeft(), dslContext.getParseResult().getQueryAs(), new ConditionFilterBuilder() {
                         @Override
                         public FilterBuilder buildFilter(String idfName) {
                             FilterBuilder missingFilter = FilterBuilders.missingFilter(idfName);
@@ -157,8 +159,8 @@ public class QueryWhereConditionParser implements ElasticSqlParser {
             if (CollectionUtils.isEmpty(inListExpr.getTargetList())) {
                 throw new ElasticSql2DslException("[syntax error] In list expr target list cannot be blank");
             }
-            final Object[] targetInList = ElasticSqlParseUtil.transferSqlArgs(inListExpr.getTargetList());
-            return parseCondition(inListExpr.getExpr(), dslContext.getQueryAs(), new ConditionFilterBuilder() {
+            final Object[] targetInList = ElasticSqlParseUtil.transferSqlArgs(inListExpr.getTargetList(), dslContext.getSqlArgs());
+            return parseCondition(inListExpr.getExpr(), dslContext.getParseResult().getQueryAs(), new ConditionFilterBuilder() {
                 @Override
                 public FilterBuilder buildFilter(String idfName) {
                     if (inListExpr.isNot()) {
@@ -171,14 +173,14 @@ public class QueryWhereConditionParser implements ElasticSqlParser {
         } else if (sqlExpr instanceof SQLBetweenExpr) {
             SQLBetweenExpr betweenExpr = (SQLBetweenExpr) sqlExpr;
 
-            final Object from = ElasticSqlParseUtil.transferSqlArg(betweenExpr.getBeginExpr());
-            final Object to = ElasticSqlParseUtil.transferSqlArg(betweenExpr.getEndExpr());
+            final Object from = ElasticSqlParseUtil.transferSqlArg(betweenExpr.getBeginExpr(), dslContext.getSqlArgs());
+            final Object to = ElasticSqlParseUtil.transferSqlArg(betweenExpr.getEndExpr(), dslContext.getSqlArgs());
 
             if (from == null || to == null) {
                 throw new ElasticSql2DslException("[syntax error] Between Expr only support one of [number,date] arg type");
             }
 
-            return parseCondition(betweenExpr.getTestExpr(), dslContext.getQueryAs(), new ConditionFilterBuilder() {
+            return parseCondition(betweenExpr.getTestExpr(), dslContext.getParseResult().getQueryAs(), new ConditionFilterBuilder() {
                 @Override
                 public FilterBuilder buildFilter(String idfName) {
                     return FilterBuilders.rangeFilter(idfName).gte(from).lte(to);
@@ -190,13 +192,13 @@ public class QueryWhereConditionParser implements ElasticSqlParser {
 
     private FilterBuilder parseCondition(SQLExpr sqlExpr, String queryAs, final ConditionFilterBuilder filterBuilder) {
         final List<FilterBuilder> tmpFilterList = Lists.newLinkedList();
-        ElasticSqlIdfParser.parseSqlIdentifier(sqlExpr, queryAs, new ElasticSqlIdfParser.ElasticSqlTopIdfFunc() {
+        ElasticSqlIdentifierHelper.parseSqlIdentifier(sqlExpr, queryAs, new ElasticSqlIdentifierHelper.ElasticSqlTopIdfFunc() {
             @Override
             public void parse(String idfName) {
                 FilterBuilder originalFilter = filterBuilder.buildFilter(idfName);
                 tmpFilterList.add(originalFilter);
             }
-        }, new ElasticSqlIdfParser.ElasticSqlNestIdfFunc() {
+        }, new ElasticSqlIdentifierHelper.ElasticSqlNestIdfFunc() {
             @Override
             public void parse(String nestPath, String idfName) {
                 FilterBuilder originalFilter = filterBuilder.buildFilter(idfName);

+ 134 - 0
src/main/java/org/elasticsearch/dsl/parser/helper/ElasticSqlDateParseHelper.java

@@ -0,0 +1,134 @@
+package org.elasticsearch.dsl.parser.helper;
+
+import com.alibaba.druid.sql.ast.SQLExpr;
+import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
+import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
+import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
+import org.apache.commons.collections.CollectionUtils;
+import org.elasticsearch.dsl.exception.ElasticSql2DslException;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.regex.Pattern;
+
+public class ElasticSqlDateParseHelper {
+    public static final String DEFAULT_ES_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
+
+    public static final Pattern SQL_DATE_REGEX_PATTERN_01 = Pattern.compile("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}");
+    public static final Pattern SQL_DATE_REGEX_PATTERN_02 = Pattern.compile("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}");
+    public static final Pattern SQL_DATE_REGEX_PATTERN_03 = Pattern.compile("\\d{4}-\\d{2}-\\d{2}");
+
+    private enum SqlDateRegex {
+        DATE_REGEX_01 {
+            @Override
+            Pattern getPattern() {
+                return SQL_DATE_REGEX_PATTERN_01;
+            }
+
+            @Override
+            String getPatternString() {
+                return "yyyy-MM-dd HH:mm:ss";
+            }
+        },
+        DATE_REGEX_02 {
+            @Override
+            Pattern getPattern() {
+                return SQL_DATE_REGEX_PATTERN_02;
+            }
+
+            @Override
+            String getPatternString() {
+                return "yyyy-MM-dd HH:mm";
+            }
+        },
+        DATE_REGEX_03 {
+            @Override
+            Pattern getPattern() {
+                return SQL_DATE_REGEX_PATTERN_03;
+            }
+
+            @Override
+            String getPatternString() {
+                return "yyyy-MM-dd";
+            }
+
+        };
+
+        abstract Pattern getPattern();
+
+        abstract String getPatternString();
+    }
+
+    public static boolean isDateMethod(SQLMethodInvokeExpr dateMethodExpr) {
+        return "date".equalsIgnoreCase(dateMethodExpr.getMethodName());
+    }
+
+    public static boolean isDateArgStringValue(String date) {
+        return SqlDateRegex.DATE_REGEX_01.getPattern().matcher(date).matches()
+                || SqlDateRegex.DATE_REGEX_02.getPattern().matcher(date).matches()
+                || SqlDateRegex.DATE_REGEX_03.getPattern().matcher(date).matches();
+    }
+
+    public static boolean isDateArgObjectValue(Object date) {
+        if (date instanceof Date) {
+            return true;
+        }
+        return false;
+    }
+
+    public static String formatDefaultEsDateStringValue(String date) {
+        if (SqlDateRegex.DATE_REGEX_01.getPattern().matcher(date).matches()) {
+            return formatDefaultEsDate(SqlDateRegex.DATE_REGEX_01.getPatternString(), date);
+        }
+        if (SqlDateRegex.DATE_REGEX_02.getPattern().matcher(date).matches()) {
+            return formatDefaultEsDate(SqlDateRegex.DATE_REGEX_02.getPatternString(), date);
+        }
+        if (SqlDateRegex.DATE_REGEX_03.getPattern().matcher(date).matches()) {
+            return formatDefaultEsDate(SqlDateRegex.DATE_REGEX_03.getPatternString(), date);
+        }
+        throw new ElasticSql2DslException("[syntax error] ElasticSql cannot support such date type: " + date);
+    }
+
+    public static String formatDefaultEsDateObjectValue(Object date) {
+        if (date instanceof Date) {
+            SimpleDateFormat dateFormat = new SimpleDateFormat(DEFAULT_ES_DATE_FORMAT);
+            return dateFormat.format(date);
+        }
+        throw new ElasticSql2DslException("[syntax error] ElasticSql cannot support such date type: " + date.getClass());
+    }
+
+    public static String formatDefaultEsDate(String patternArg, String timeValArg) {
+        try {
+            SimpleDateFormat dateFormat = new SimpleDateFormat(patternArg);
+            Date date = dateFormat.parse(timeValArg);
+
+            dateFormat = new SimpleDateFormat(DEFAULT_ES_DATE_FORMAT);
+            return dateFormat.format(date);
+        } catch (ParseException pex) {
+            throw new ElasticSql2DslException("[syntax error] Parse time arg error: " + timeValArg);
+        }
+    }
+
+    public static void checkDateMethod(SQLMethodInvokeExpr dateInvokeExpr) {
+        if (!"date".equalsIgnoreCase(dateInvokeExpr.getMethodName())) {
+            throw new ElasticSql2DslException("[syntax error] ElasticSql not support method:" + dateInvokeExpr.getMethodName());
+        }
+
+        if (CollectionUtils.isEmpty(dateInvokeExpr.getParameters()) || dateInvokeExpr.getParameters().size() != 2) {
+            throw new ElasticSql2DslException(String.format("[syntax error] There is no %s args method named nvl",
+                    dateInvokeExpr.getParameters() != null ? dateInvokeExpr.getParameters().size() : 0));
+        }
+
+        SQLExpr patternArg = dateInvokeExpr.getParameters().get(0);
+        SQLExpr timeValArg = dateInvokeExpr.getParameters().get(1);
+
+        if (!(patternArg instanceof SQLCharExpr) && !(patternArg instanceof SQLVariantRefExpr)) {
+            throw new ElasticSql2DslException("[syntax error] The first arg of date method should be a time pattern");
+        }
+
+        if (!(timeValArg instanceof SQLCharExpr) && !(timeValArg instanceof SQLVariantRefExpr)) {
+            throw new ElasticSql2DslException("[syntax error] The second arg of date method should be a string of time");
+        }
+    }
+}

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

@@ -1,4 +1,4 @@
-package org.elasticsearch.dsl.parser;
+package org.elasticsearch.dsl.parser.helper;
 
 import com.alibaba.druid.sql.ast.SQLExpr;
 import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
@@ -6,7 +6,7 @@ import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 import org.elasticsearch.utils.StringUtils;
 
-public class ElasticSqlIdfParser {
+public class ElasticSqlIdentifierHelper {
 
     public static void parseSqlIdentifier(SQLExpr idfSqlExpr, String queryAsAlias, ElasticSqlTopIdfFunc topIdfFunc, ElasticSqlNestIdfFunc nestIdfFunc) {
         if (idfSqlExpr instanceof SQLIdentifierExpr) {

+ 10 - 84
src/test/java/org/elasticsearch/SqlParserTest.java

@@ -1,9 +1,7 @@
 package org.elasticsearch;
 
-import org.apache.commons.collections.CollectionUtils;
-import org.elasticsearch.dsl.ElasticDslContext;
-import org.elasticsearch.dsl.parser.ElasticSql2DslParser;
-import org.junit.Assert;
+import org.elasticsearch.dsl.ElasticSql2DslParser;
+import org.elasticsearch.dsl.ElasticSqlParseResult;
 import org.junit.Test;
 
 
@@ -11,85 +9,13 @@ public class SqlParserTest {
 
     @Test
     public void testParseSelectFieldWithQueryAs() {
-        String sql = "select b.id,bookCategory,b.bookStatus,clazz.sortNo,b.clazz.cid from book b where b.type = 'AV'";
-        ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser(sql);
-        ElasticDslContext dslContext = sql2DslParser.parse();
-
-        System.out.println(dslContext.toString());
-        Assert.assertEquals(dslContext.getQueryFieldList().get(0), "id");
-        Assert.assertEquals(dslContext.getQueryFieldList().get(1), "bookCategory");
-        Assert.assertEquals(dslContext.getQueryFieldList().get(2), "bookStatus");
-        Assert.assertEquals(dslContext.getQueryFieldList().get(3), "clazz.sortNo");
-        Assert.assertEquals(dslContext.getQueryFieldList().get(4), "clazz.cid");
-    }
-
-    @Test
-    public void testParseSelectFieldWithoutQueryAs() {
-        String sql = "select b.id,bookCategory,b.bookStatus,clazz.sortNo,clazz.cid from book where c = 1";
-        ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser(sql);
-        ElasticDslContext dslContext = sql2DslParser.parse();
-
-        System.out.println(dslContext.toString());
-        Assert.assertEquals(dslContext.getQueryFieldList().get(0), "b.id");
-        Assert.assertEquals(dslContext.getQueryFieldList().get(1), "bookCategory");
-        Assert.assertEquals(dslContext.getQueryFieldList().get(2), "b.bookStatus");
-        Assert.assertEquals(dslContext.getQueryFieldList().get(3), "clazz.sortNo");
-        Assert.assertEquals(dslContext.getQueryFieldList().get(4), "clazz.cid");
-    }
-
-    @Test
-    public void testParseSelectFieldMatchAll_01() {
-        String sql = "select * from lib.av as b where c = 1 and updated_at > date('yyyy-MM-dd', '2016-10-22')";
-        ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser(sql);
-        ElasticDslContext dslContext = sql2DslParser.parse();
-
-        System.out.println(dslContext.toString());
-        Assert.assertTrue(CollectionUtils.isEmpty(dslContext.getQueryFieldList()));
-    }
-
-    @Test
-    public void testParseSelectFieldMatchAll_02() {
-        String sql = "select b.* from book b";
-        ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser(sql);
-        ElasticDslContext dslContext = sql2DslParser.parse();
-
-        System.out.println(dslContext.toString());
-        Assert.assertTrue(CollectionUtils.isEmpty(dslContext.getQueryFieldList()));
-    }
-
-    @Test
-    public void testParseSelectFieldMatchAll_03() {
-        String sql = "select b.n.* from book b";
-        ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser(sql);
-        ElasticDslContext dslContext = sql2DslParser.parse();
-
-        System.out.println(dslContext.toString());
-        Assert.assertTrue(dslContext.getQueryFieldList().size() == 1);
-        Assert.assertTrue("n.*".equals(dslContext.getQueryFieldList().get(0)));
-    }
-
-    @Test
-    public void testParseInFilterCondition_01() {
-        String sql = "select * from book bk where bk.status in ('SALES') and category='b'"
-                + " and (bk.bookType in ('AV') or salesArea = '4')"
-                + " and requestType=2";
-
-        ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser(sql);
-        ElasticDslContext dslContext = sql2DslParser.parse();
-        System.out.println(dslContext.toString());
-    }
-
-    @Test
-    public void testParseNestCondition() {
-        String sql = "select id,bookStatus,updatedAt,bookClassifications from book.basic dd where"
-                + " bookCategory = '802'"
-                + " and bookClassifications.classificationId > 0"
-                + " order by id desc,nvl(bookClassifications.sortNo, 999, 'min') asc";
-
-        ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser(sql);
-        ElasticDslContext dslContext = sql2DslParser.parse();
-
-        System.out.println(dslContext.toString());
+        String sql = "select id,productStatus from index.trx_order where "
+                + " productCategory in ('801', '802') "
+                + " and (updatedAt > date('yyyy-MM-dd hh:mm', ?) or updatedAt < '2017-01-01') "
+                + " and price > ?";
+
+        ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser();
+        ElasticSqlParseResult parseResult = sql2DslParser.parse(sql, new Object[]{"2016-12-30 14:58", 100.12});
+        System.out.println(parseResult.toDsl());
     }
-    
 }