Forráskód Böngészése

add order condition parser

spuerx 9 éve
szülő
commit
b23f4dc26e

+ 6 - 0
pom.xml

@@ -63,6 +63,12 @@
             <version>3.2.1</version>
         </dependency>
 
+        <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+            <version>2.6</version>
+        </dependency>
+
 
 
         <dependency>

+ 5 - 5
src/main/java/org/elasticsearch/dsl/ElasticDslBuilder.java

@@ -19,13 +19,13 @@ public class ElasticDslBuilder {
     //SQL解析器的顺序不能改变
     private static final List<ElasticSqlParser> sqlParseProcessors = ImmutableList.of(
             //解析SQL指定的索引和文档类型
-            QueryIndexParser::parseQueryIndicesAndTypes,
-            //解析SQL查询索引别名
-            QueryAsAliasParser::parseQueryAsAlias,
+            QueryFromParser::parseQueryIndicesAndTypes,
             //解析SQL查询指定的where条件
-            FilterConditionParser::parseFilterCondition,
+            QueryWhereConditionParser::parseFilterCondition,
+            //解析SQL排序条件
+            QueryOrderConditionParser::parseOrderCondition,
             //解析SQL查询指定的字段
-            SelectFieldListParser::parseSelectFieldList
+            QuerySelectFieldListParser::parseSelectFieldList
 
     );
 

+ 1 - 1
src/main/java/org/elasticsearch/dsl/ElasticDslContext.java

@@ -123,7 +123,7 @@ public class ElasticDslContext {
         }
 
         if (filterBuilder != null && filterBuilder.hasClauses()) {
-            requestBuilder.setQuery(QueryBuilders.filteredQuery(null, filterBuilder));
+            requestBuilder.setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), filterBuilder));
         } else {
             requestBuilder.setQuery(QueryBuilders.matchAllQuery());
         }

+ 3 - 1
src/main/java/org/elasticsearch/dsl/ElasticSql2DslParser.java

@@ -1,9 +1,11 @@
-package org.elasticsearch.dsl;
+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;
 

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

@@ -0,0 +1,50 @@
+package org.elasticsearch.dsl.parser;
+
+import com.alibaba.druid.sql.ast.SQLExpr;
+import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
+import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
+import org.elasticsearch.dsl.exception.ElasticSql2DslException;
+import org.elasticsearch.utils.StringUtils;
+
+public class ElasticSqlIdfParser {
+
+    public static void parseSqlIdentifier(SQLExpr idfSqlExpr, String queryAsAlias, ElasticSqlTopIdfFunc topIdfFunc, ElasticSqlNestIdfFunc nestIdfFunc) {
+        if (idfSqlExpr instanceof SQLIdentifierExpr) {
+            topIdfFunc.parse(((SQLIdentifierExpr) idfSqlExpr).getName());
+        }
+        if (idfSqlExpr instanceof SQLPropertyExpr) {
+            SQLPropertyExpr propertyExpr = (SQLPropertyExpr) idfSqlExpr;
+
+            if (propertyExpr.getOwner() instanceof SQLPropertyExpr) {
+                SQLPropertyExpr ownerPropertyExpr = (SQLPropertyExpr) propertyExpr.getOwner();
+                if (!(ownerPropertyExpr.getOwner() instanceof SQLIdentifierExpr)) {
+                    throw new ElasticSql2DslException("[syntax error] Select field ref level should <= 3");
+                }
+                SQLIdentifierExpr superOwnerIdfExpr = (SQLIdentifierExpr) ownerPropertyExpr.getOwner();
+                if (StringUtils.isNotBlank(queryAsAlias) && queryAsAlias.equalsIgnoreCase(superOwnerIdfExpr.getName())) {
+                    nestIdfFunc.parse(ownerPropertyExpr.getName(), propertyExpr.getName());
+                } else {
+                    throw new ElasticSql2DslException("[syntax error] Select field qualifier not support: " + superOwnerIdfExpr.getName());
+                }
+            } else if (propertyExpr.getOwner() instanceof SQLIdentifierExpr) {
+                SQLIdentifierExpr ownerIdfExpr = (SQLIdentifierExpr) propertyExpr.getOwner();
+                if (StringUtils.isNotBlank(queryAsAlias) && queryAsAlias.equalsIgnoreCase(ownerIdfExpr.getName())) {
+                    topIdfFunc.parse(propertyExpr.getName());
+                } else {
+                    nestIdfFunc.parse(ownerIdfExpr.getName(), propertyExpr.getName());
+                }
+            }
+        }
+    }
+
+    @FunctionalInterface
+    public interface ElasticSqlTopIdfFunc {
+        void parse(String idfName);
+    }
+
+    @FunctionalInterface
+    public interface ElasticSqlNestIdfFunc {
+        void parse(String nestPath, String idfName);
+    }
+
+}

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

@@ -0,0 +1,65 @@
+package org.elasticsearch.dsl.parser;
+
+import com.alibaba.druid.sql.ast.SQLExpr;
+import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
+import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
+import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
+import com.alibaba.druid.sql.ast.expr.SQLNumberExpr;
+import com.google.common.collect.Lists;
+import org.elasticsearch.dsl.exception.ElasticSql2DslException;
+
+import java.util.List;
+
+public class ElasticSqlParseUtil {
+    public static Object[] transferSqlArgs(List<SQLExpr> exprList) {
+        SQLExpr firstArg = exprList.get(0);
+        if (firstArg instanceof SQLIntegerExpr) {
+            return toObjectArray(Lists.transform(exprList, argItem -> {
+                return ((SQLIntegerExpr) argItem).getNumber().longValue();
+            }));
+        }
+        if (firstArg instanceof SQLNumberExpr) {
+            return toObjectArray(Lists.transform(exprList, argItem -> {
+                return ((SQLNumberExpr) argItem).getNumber().doubleValue();
+            }));
+        }
+        if (firstArg instanceof SQLCharExpr) {
+            return toObjectArray(Lists.transform(exprList, argItem -> {
+                return ((SQLCharExpr) argItem).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();
+        }
+        throw new ElasticSql2DslException("[syntax error] Can not support arg type: " + expr.getClass());
+    }
+
+    private static <T> Object[] toObjectArray(List<T> list) {
+        return list.toArray(new Object[list.size()]);
+    }
+
+    public static boolean isValidBinOperator(SQLBinaryOperator binaryOperator) {
+        return binaryOperator == SQLBinaryOperator.BooleanAnd
+                || binaryOperator == SQLBinaryOperator.Equality
+                || binaryOperator == SQLBinaryOperator.NotEqual
+                || binaryOperator == SQLBinaryOperator.LessThanOrGreater
+                || binaryOperator == SQLBinaryOperator.BooleanOr
+                || binaryOperator == SQLBinaryOperator.GreaterThan
+                || binaryOperator == SQLBinaryOperator.GreaterThanOrEqual
+                || binaryOperator == SQLBinaryOperator.LessThan
+                || binaryOperator == SQLBinaryOperator.LessThanOrEqual
+                || binaryOperator == SQLBinaryOperator.LessThanOrGreater
+                || binaryOperator == SQLBinaryOperator.Is
+                || binaryOperator == SQLBinaryOperator.IsNot;
+    }
+}

+ 0 - 64
src/main/java/org/elasticsearch/dsl/parser/FilterConditionParser.java

@@ -1,64 +0,0 @@
-package org.elasticsearch.dsl.parser;
-
-import com.alibaba.druid.sql.ast.SQLExpr;
-import com.alibaba.druid.sql.ast.expr.*;
-import org.elasticsearch.dsl.ElasticDslContext;
-import org.elasticsearch.dsl.exception.ElasticSql2DslException;
-import org.elasticsearch.index.query.BoolFilterBuilder;
-import org.elasticsearch.index.query.FilterBuilders;
-import org.elasticsearch.index.query.TermsFilterBuilder;
-import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
-
-public class FilterConditionParser {
-    public static void parseFilterCondition(ElasticDslContext dslContext) {
-        ElasticSqlSelectQueryBlock queryBlock = (ElasticSqlSelectQueryBlock) dslContext.getQueryExpr().getSubQuery().getQuery();
-        parseFilterCondition(dslContext.boolFilter(), queryBlock.getWhere());
-
-    }
-
-    private static void parseFilterCondition(BoolFilterBuilder filterBuilder, SQLExpr sqlExpr) {
-        if (sqlExpr instanceof SQLBinaryOpExpr) {
-            SQLBinaryOpExpr sqlBinOpExpr = (SQLBinaryOpExpr) sqlExpr;
-            SQLBinaryOperator binaryOperator = sqlBinOpExpr.getOperator();
-
-            if (isValidBinOperator(binaryOperator)) {
-
-            }
-        } else if (sqlExpr instanceof SQLInListExpr) {
-            SQLInListExpr inListExpr = (SQLInListExpr) sqlExpr;
-
-            if (inListExpr.getExpr() instanceof SQLIdentifierExpr) {
-                TermsFilterBuilder inFilter = FilterBuilders.inFilter(
-                        ((SQLIdentifierExpr) inListExpr.getExpr()).getName(),
-                        inListExpr.getTargetList().toArray(new Object[inListExpr.getTargetList().size()])
-                );
-                if (inListExpr.isNot()) {
-                    filterBuilder.mustNot(inFilter);
-                } else {
-                    filterBuilder.must(inFilter);
-                }
-            }
-
-            if (inListExpr.getExpr() instanceof SQLPropertyExpr) {
-
-            }
-        } else {
-            throw new ElasticSql2DslException("[syntax error] Can not support Op type: " + sqlExpr.getClass());
-        }
-    }
-
-    private static boolean isValidBinOperator(SQLBinaryOperator binaryOperator) {
-        return binaryOperator == SQLBinaryOperator.BooleanAnd
-                || binaryOperator == SQLBinaryOperator.Equality
-                || binaryOperator == SQLBinaryOperator.NotEqual
-                || binaryOperator == SQLBinaryOperator.BooleanOr
-                || binaryOperator == SQLBinaryOperator.GreaterThan
-                || binaryOperator == SQLBinaryOperator.GreaterThanOrEqual
-                || binaryOperator == SQLBinaryOperator.LessThan
-                || binaryOperator == SQLBinaryOperator.LessThanOrEqual
-                || binaryOperator == SQLBinaryOperator.LessThanOrGreater
-                || binaryOperator == SQLBinaryOperator.Is
-                || binaryOperator == SQLBinaryOperator.IsNot;
-    }
-
-}

+ 0 - 11
src/main/java/org/elasticsearch/dsl/parser/QueryAsAliasParser.java

@@ -1,11 +0,0 @@
-package org.elasticsearch.dsl.parser;
-
-import org.elasticsearch.dsl.ElasticDslContext;
-import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
-
-public class QueryAsAliasParser {
-    public static void parseQueryAsAlias(ElasticDslContext dslContext) {
-        ElasticSqlSelectQueryBlock queryBlock = (ElasticSqlSelectQueryBlock) dslContext.getQueryExpr().getSubQuery().getQuery();
-        dslContext.setQueryAs(queryBlock.getFrom().getAlias());
-    }
-}

+ 3 - 6
src/main/java/org/elasticsearch/dsl/parser/QueryIndexParser.java

@@ -6,18 +6,15 @@ import org.elasticsearch.dsl.ElasticDslContext;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
 
-public class QueryIndexParser {
+public class QueryFromParser {
     public static void parseQueryIndicesAndTypes(ElasticDslContext dslContext) {
         ElasticSqlSelectQueryBlock queryBlock = (ElasticSqlSelectQueryBlock) dslContext.getQueryExpr().getSubQuery().getQuery();
         if (queryBlock.getFrom() instanceof SQLExprTableSource) {
             SQLExprTableSource tableSource = (SQLExprTableSource) queryBlock.getFrom();
-
-//            System.out.println(tableSource.getAlias());
-//            System.out.println(tableSource.getExpr().getClass());
-
+            dslContext.setQueryAs(tableSource.getAlias());
             dslContext.setIndices(ImmutableList.of(tableSource.getExpr().toString()));
         } else {
-            throw new ElasticSql2DslException("[syntax error] From table source could be [SQLExprTableSource],but get: " + queryBlock.getFrom().getClass());
+            throw new ElasticSql2DslException("[syntax error] From table source should be [SQLExprTableSource],but get: " + queryBlock.getFrom().getClass());
         }
     }
 }

+ 165 - 0
src/main/java/org/elasticsearch/dsl/parser/QueryOrderConditionParser.java

@@ -0,0 +1,165 @@
+package org.elasticsearch.dsl.parser;
+
+import com.alibaba.druid.sql.ast.SQLExpr;
+import com.alibaba.druid.sql.ast.SQLOrderBy;
+import com.alibaba.druid.sql.ast.SQLOrderingSpecification;
+import com.alibaba.druid.sql.ast.expr.*;
+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.exception.ElasticSql2DslException;
+import org.elasticsearch.search.sort.FieldSortBuilder;
+import org.elasticsearch.search.sort.SortBuilder;
+import org.elasticsearch.search.sort.SortBuilders;
+import org.elasticsearch.search.sort.SortOrder;
+import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
+
+import java.util.List;
+
+public class QueryOrderConditionParser {
+    public static void parseOrderCondition(ElasticDslContext dslContext) {
+        ElasticSqlSelectQueryBlock queryBlock = (ElasticSqlSelectQueryBlock) dslContext.getQueryExpr().getSubQuery().getQuery();
+        SQLOrderBy sqlOrderBy = queryBlock.getOrderBy();
+        if (sqlOrderBy != null && CollectionUtils.isNotEmpty(sqlOrderBy.getItems())) {
+            sqlOrderBy.getItems().stream().forEach(orderByItem -> {
+                SortBuilder orderBy = parseOrderCondition(orderByItem, dslContext.getQueryAs());
+                if (orderBy != null) {
+                    dslContext.addSort(orderBy);
+                }
+            });
+        }
+    }
+
+    private static SortBuilder parseOrderCondition(SQLSelectOrderByItem orderByItem, String queryAs) {
+        if (orderByItem.getExpr() instanceof SQLPropertyExpr || orderByItem.getExpr() instanceof SQLIdentifierExpr) {
+            return parseCondition(orderByItem.getExpr(), queryAs, idfName -> {
+                if (SQLOrderingSpecification.ASC == orderByItem.getType()) {
+                    return SortBuilders.fieldSort(idfName).order(SortOrder.ASC);
+                } else {
+                    return SortBuilders.fieldSort(idfName).order(SortOrder.DESC);
+                }
+            });
+        }
+        if (orderByItem.getExpr() instanceof SQLMethodInvokeExpr) {
+            SQLMethodInvokeExpr methodInvokeExpr = (SQLMethodInvokeExpr) orderByItem.getExpr();
+            checkNvlMethod(methodInvokeExpr);
+
+            Object valueArg = ElasticSqlParseUtil.transferSqlArg(methodInvokeExpr.getParameters().get(1));
+            return parseCondition(methodInvokeExpr.getParameters().get(0), queryAs, idfName -> {
+                FieldSortBuilder fieldSortBuilder = null;
+                if (SQLOrderingSpecification.ASC == orderByItem.getType()) {
+                    fieldSortBuilder = SortBuilders.fieldSort(idfName).order(SortOrder.ASC).missing(valueArg);
+                } else {
+                    fieldSortBuilder = SortBuilders.fieldSort(idfName).order(SortOrder.DESC).missing(valueArg);
+                }
+                if (methodInvokeExpr.getParameters().size() == 3) {
+                    SQLExpr sortModArg = methodInvokeExpr.getParameters().get(2);
+                    String sortModeText = ((SQLCharExpr) sortModArg).getText();
+                    fieldSortBuilder.sortMode(SortOption.get(sortModeText).mode());
+                }
+                return fieldSortBuilder;
+            });
+        }
+        throw new ElasticSql2DslException("[syntax error] ElasticSql cannot support sort type: " + orderByItem.getExpr().getClass());
+    }
+
+    private static void checkNvlMethod(SQLMethodInvokeExpr nvlInvokeExpr) {
+        if (!"nvl".equalsIgnoreCase(nvlInvokeExpr.getMethodName())) {
+            throw new ElasticSql2DslException("[syntax error] ElasticSql sort condition only support nvl method invoke");
+        }
+
+        if (CollectionUtils.isEmpty(nvlInvokeExpr.getParameters()) || nvlInvokeExpr.getParameters().size() > 3) {
+            throw new ElasticSql2DslException(String.format("[syntax error] There is no %s args method named nvl",
+                    nvlInvokeExpr.getParameters() != null ? nvlInvokeExpr.getParameters().size() : 0));
+        }
+
+        SQLExpr fieldArg = nvlInvokeExpr.getParameters().get(0);
+        SQLExpr valueArg = nvlInvokeExpr.getParameters().get(1);
+
+        if (!(fieldArg instanceof SQLPropertyExpr) && !(fieldArg instanceof SQLIdentifierExpr)) {
+            throw new ElasticSql2DslException("[syntax error] The first arg of nvl method should be field param name");
+        }
+
+        if (!(valueArg instanceof SQLCharExpr) && !(valueArg instanceof SQLIntegerExpr) && !(valueArg instanceof SQLNumberExpr)) {
+            throw new ElasticSql2DslException("[syntax error] The second arg of nvl method should be number or string");
+        }
+
+        if (nvlInvokeExpr.getParameters().size() == 3) {
+            SQLExpr sortModArg = nvlInvokeExpr.getParameters().get(2);
+            if (!(sortModArg instanceof SQLCharExpr)) {
+                throw new ElasticSql2DslException("[syntax error] The third arg of nvl method should be string");
+            }
+            String sortModeText = ((SQLCharExpr) sortModArg).getText();
+            if (!SortOption.AVG.mode().equalsIgnoreCase(sortModeText) && !SortOption.MIN.mode().equalsIgnoreCase(sortModeText)
+                    && !SortOption.MAX.mode().equalsIgnoreCase(sortModeText) && !SortOption.SUM.mode().equalsIgnoreCase(sortModeText)) {
+                throw new ElasticSql2DslException("[syntax error] The third arg of nvl method should be one of the string[min,max,avg,sum]");
+            }
+        }
+    }
+
+    private static SortBuilder parseCondition(SQLExpr sqlExpr, String queryAs, ConditionSortBuilder sortBuilder) {
+        List<SortBuilder> tmpSortList = Lists.newLinkedList();
+        ElasticSqlIdfParser.parseSqlIdentifier(sqlExpr, queryAs, idfName -> {
+            FieldSortBuilder originalSort = sortBuilder.buildSort(idfName);
+            tmpSortList.add(originalSort);
+        }, (nestPath, idfName) -> {
+            FieldSortBuilder originalSort = sortBuilder.buildSort(idfName);
+            originalSort.setNestedPath(nestPath);
+            tmpSortList.add(originalSort);
+        });
+        if (CollectionUtils.isNotEmpty(tmpSortList)) {
+            return tmpSortList.get(0);
+        }
+        return null;
+    }
+
+    @FunctionalInterface
+    private interface ConditionSortBuilder {
+        FieldSortBuilder buildSort(String idfName);
+    }
+
+    public enum SortOption {
+        SUM {
+            @Override
+            public String mode() {
+                return "sum";
+            }
+        },
+        MIN {
+            @Override
+            public String mode() {
+                return "min";
+            }
+        },
+        MAX {
+            @Override
+            public String mode() {
+                return "max";
+            }
+        },
+        AVG {
+            @Override
+            public String mode() {
+                return "avg";
+            }
+        };
+
+        public abstract String mode();
+
+        @Override
+        public String toString() {
+            return mode();
+        }
+
+        public static SortOption get(String mode) {
+            SortOption op = null;
+            for (SortOption option : SortOption.values()) {
+                if (option.mode().equalsIgnoreCase(mode)) {
+                    op = option;
+                }
+            }
+            return op;
+        }
+    }
+}

+ 30 - 0
src/main/java/org/elasticsearch/dsl/parser/QuerySelectFieldListParser.java

@@ -0,0 +1,30 @@
+package org.elasticsearch.dsl.parser;
+
+import com.google.common.collect.Lists;
+import org.elasticsearch.dsl.ElasticDslContext;
+import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
+
+import java.util.List;
+
+public class QuerySelectFieldListParser {
+    public static final String SQL_FIELD_MATCH_ALL = "*";
+
+    public static void parseSelectFieldList(ElasticDslContext dslContext) {
+        ElasticSqlSelectQueryBlock queryBlock = (ElasticSqlSelectQueryBlock) dslContext.getQueryExpr().getSubQuery().getQuery();
+
+        List<String> selectFields = Lists.newLinkedList();
+        queryBlock.getSelectList().stream().forEach(
+                selectField -> ElasticSqlIdfParser.parseSqlIdentifier(selectField.getExpr(), dslContext.getQueryAs(),
+                        idfName -> {
+                            if (!SQL_FIELD_MATCH_ALL.equals(idfName)) {
+                                selectFields.add(idfName);
+                            }
+                        },
+                        (nestPath, idfName) -> {
+                            selectFields.add(String.format("%s.%s", nestPath, idfName));
+                        }
+                )
+        );
+        dslContext.setQueryFieldList(selectFields);
+    }
+}

+ 143 - 0
src/main/java/org/elasticsearch/dsl/parser/QueryWhereConditionParser.java

@@ -0,0 +1,143 @@
+package org.elasticsearch.dsl.parser;
+
+import com.alibaba.druid.sql.ast.SQLExpr;
+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.exception.ElasticSql2DslException;
+import org.elasticsearch.index.query.FilterBuilder;
+import org.elasticsearch.index.query.FilterBuilders;
+import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
+
+import java.util.List;
+
+public class QueryWhereConditionParser {
+    public static void parseFilterCondition(ElasticDslContext dslContext) {
+        ElasticSqlSelectQueryBlock queryBlock = (ElasticSqlSelectQueryBlock) dslContext.getQueryExpr().getSubQuery().getQuery();
+        if (queryBlock.getWhere() != null) {
+            FilterBuilder sqlWhereFilter = parseFilterCondition(dslContext, queryBlock.getWhere());
+            dslContext.boolFilter().must(sqlWhereFilter);
+        }
+    }
+
+    private static FilterBuilder parseFilterCondition(ElasticDslContext dslContext, SQLExpr sqlExpr) {
+        if (sqlExpr instanceof SQLBinaryOpExpr) {
+            SQLBinaryOpExpr sqlBinOpExpr = (SQLBinaryOpExpr) sqlExpr;
+            SQLBinaryOperator binaryOperator = sqlBinOpExpr.getOperator();
+
+            if (ElasticSqlParseUtil.isValidBinOperator(binaryOperator)) {
+                //AND OR
+                if (SQLBinaryOperator.BooleanAnd == binaryOperator || SQLBinaryOperator.BooleanOr == binaryOperator) {
+                    FilterBuilder leftFilter = parseFilterCondition(dslContext, sqlBinOpExpr.getLeft());
+                    FilterBuilder rightFilter = parseFilterCondition(dslContext, sqlBinOpExpr.getRight());
+                    if (SQLBinaryOperator.BooleanAnd == binaryOperator) {
+                        return FilterBuilders.boolFilter().must(leftFilter).must(rightFilter);
+                    } else {
+                        return FilterBuilders.boolFilter().should(leftFilter).should(rightFilter);
+                    }
+                }
+
+                //以下是二元运算,左边必须是变量
+                if (!(sqlBinOpExpr.getLeft() instanceof SQLPropertyExpr || sqlBinOpExpr.getLeft() instanceof SQLIdentifierExpr)) {
+                    throw new ElasticSql2DslException("[syntax error] Equality expr left part should be a param name");
+                }
+
+                //EQ NEQ
+                if (SQLBinaryOperator.Equality == binaryOperator || SQLBinaryOperator.LessThanOrGreater == binaryOperator || SQLBinaryOperator.NotEqual == binaryOperator) {
+                    Object targetVal = ElasticSqlParseUtil.transferSqlArg(sqlBinOpExpr.getRight());
+                    return parseCondition(sqlBinOpExpr.getLeft(), dslContext.getQueryAs(), idfName -> {
+                        FilterBuilder eqFilter = FilterBuilders.termFilter(idfName, targetVal);
+                        if (SQLBinaryOperator.Equality == binaryOperator) {
+                            return eqFilter;
+                        } else {
+                            return FilterBuilders.notFilter(eqFilter);
+                        }
+                    });
+                }
+
+                //GT GTE LT LTE
+                if (SQLBinaryOperator.GreaterThan == binaryOperator || SQLBinaryOperator.GreaterThanOrEqual == binaryOperator
+                        || SQLBinaryOperator.LessThan == binaryOperator || SQLBinaryOperator.LessThanOrEqual == binaryOperator) {
+                    Object targetVal = ElasticSqlParseUtil.transferSqlArg(sqlBinOpExpr.getRight());
+                    return parseCondition(sqlBinOpExpr.getLeft(), dslContext.getQueryAs(), idfName -> {
+                        FilterBuilder rangeFilter = null;
+                        if (SQLBinaryOperator.GreaterThan == binaryOperator) {
+                            rangeFilter = FilterBuilders.rangeFilter(idfName).gt(targetVal);
+                        } else if (SQLBinaryOperator.GreaterThanOrEqual == binaryOperator) {
+                            rangeFilter = FilterBuilders.rangeFilter(idfName).gte(targetVal);
+                        } else if (SQLBinaryOperator.LessThan == binaryOperator) {
+                            rangeFilter = FilterBuilders.rangeFilter(idfName).lt(targetVal);
+                        } else if (SQLBinaryOperator.LessThanOrEqual == binaryOperator) {
+                            rangeFilter = FilterBuilders.rangeFilter(idfName).lte(targetVal);
+                        }
+                        return rangeFilter;
+                    });
+                }
+
+                //IS / IS NOT
+                if (SQLBinaryOperator.Is == binaryOperator || SQLBinaryOperator.IsNot == binaryOperator) {
+                    if (!(sqlBinOpExpr.getRight() instanceof SQLNullExpr)) {
+                        throw new ElasticSql2DslException("[syntax error] Is/IsNot expr right part should be null");
+                    }
+                    return parseCondition(sqlBinOpExpr.getLeft(), dslContext.getQueryAs(), idfName -> {
+                        FilterBuilder missingFilter = FilterBuilders.missingFilter(idfName);
+                        if (SQLBinaryOperator.IsNot == binaryOperator) {
+                            return FilterBuilders.notFilter(missingFilter);
+                        }
+                        return missingFilter;
+                    });
+                }
+            }
+        } else if (sqlExpr instanceof SQLInListExpr) {
+            SQLInListExpr inListExpr = (SQLInListExpr) sqlExpr;
+            if (CollectionUtils.isEmpty(inListExpr.getTargetList())) {
+                throw new ElasticSql2DslException("[syntax error] In list expr target list cannot be blank");
+            }
+            Object[] targetInList = ElasticSqlParseUtil.transferSqlArgs(inListExpr.getTargetList());
+            return parseCondition(inListExpr.getExpr(), dslContext.getQueryAs(), idfName -> {
+                if (inListExpr.isNot()) {
+                    return FilterBuilders.notFilter(FilterBuilders.inFilter(idfName, targetInList));
+                } else {
+                    return FilterBuilders.inFilter(idfName, targetInList);
+                }
+            });
+        } else if (sqlExpr instanceof SQLBetweenExpr) {
+            SQLBetweenExpr betweenExpr = (SQLBetweenExpr) sqlExpr;
+            if ((!(betweenExpr.getBeginExpr() instanceof SQLIntegerExpr) && !(betweenExpr.getBeginExpr() instanceof SQLNumberExpr))
+                    || (!(betweenExpr.getEndExpr() instanceof SQLIntegerExpr) && !(betweenExpr.getEndExpr() instanceof SQLNumberExpr))) {
+                throw new ElasticSql2DslException(String.format("[syntax error] Can not support between arg type : begin >%s end> %s",
+                        betweenExpr.getBeginExpr().getClass(), betweenExpr.getEndExpr().getClass()));
+            }
+
+            Object from = ElasticSqlParseUtil.transferSqlArg(betweenExpr.getBeginExpr());
+            Object to = ElasticSqlParseUtil.transferSqlArg(betweenExpr.getEndExpr());
+
+            return parseCondition(betweenExpr.getTestExpr(), dslContext.getQueryAs(), idfName -> {
+                return FilterBuilders.rangeFilter(idfName).gte(from).lte(to);
+            });
+        }
+        throw new ElasticSql2DslException("[syntax error] Can not support Op type: " + sqlExpr.getClass());
+    }
+
+    private static FilterBuilder parseCondition(SQLExpr sqlExpr, String queryAs, ConditionFilterBuilder filterBuilder) {
+        List<FilterBuilder> tmpFilterList = Lists.newLinkedList();
+        ElasticSqlIdfParser.parseSqlIdentifier(sqlExpr, queryAs, idfName -> {
+            FilterBuilder originalFilter = filterBuilder.buildFilter(idfName);
+            tmpFilterList.add(originalFilter);
+        }, (nestPath, idfName) -> {
+            FilterBuilder originalFilter = filterBuilder.buildFilter(idfName);
+            FilterBuilder nestFilter = FilterBuilders.nestedFilter(nestPath, originalFilter);
+            tmpFilterList.add(nestFilter);
+        });
+        if (CollectionUtils.isNotEmpty(tmpFilterList)) {
+            return tmpFilterList.get(0);
+        }
+        return null;
+    }
+
+    @FunctionalInterface
+    private interface ConditionFilterBuilder {
+        FilterBuilder buildFilter(String idfName);
+    }
+}

+ 0 - 57
src/main/java/org/elasticsearch/dsl/parser/SelectFieldListParser.java

@@ -1,57 +0,0 @@
-package org.elasticsearch.dsl.parser;
-
-import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
-import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
-import com.google.common.collect.Lists;
-import org.elasticsearch.dsl.ElasticDslContext;
-import org.elasticsearch.dsl.exception.ElasticSql2DslException;
-import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
-import org.elasticsearch.utils.StringUtils;
-
-import java.util.List;
-
-public class SelectFieldListParser {
-    public static void parseSelectFieldList(ElasticDslContext dslContext) {
-        ElasticSqlSelectQueryBlock queryBlock = (ElasticSqlSelectQueryBlock) dslContext.getQueryExpr().getSubQuery().getQuery();
-        List<String> selectFields = Lists.newLinkedList();
-        String queryAsAlias = dslContext.getQueryAs();
-
-        if (queryBlock.getSelectList().size() == 1 && (queryBlock.getSelectList().get(0).getExpr() instanceof SQLIdentifierExpr)) {
-            SQLIdentifierExpr idfExpr = (SQLIdentifierExpr) queryBlock.getSelectList().get(0).getExpr();
-            if ("*".equalsIgnoreCase(idfExpr.getName())) {
-                return;
-            }
-        }
-
-        queryBlock.getSelectList().stream().forEach(selectFieldItem -> {
-            if (selectFieldItem.getExpr() instanceof SQLIdentifierExpr) {
-                SQLIdentifierExpr idfExpr = (SQLIdentifierExpr) selectFieldItem.getExpr();
-                selectFields.add(idfExpr.getName());
-            }
-            if (selectFieldItem.getExpr() instanceof SQLPropertyExpr) {
-                SQLPropertyExpr propertyExpr = (SQLPropertyExpr) selectFieldItem.getExpr();
-
-                if (propertyExpr.getOwner() instanceof SQLPropertyExpr) {
-                    SQLPropertyExpr ownerPropertyExpr = (SQLPropertyExpr) propertyExpr.getOwner();
-                    if (!(ownerPropertyExpr.getOwner() instanceof SQLIdentifierExpr)) {
-                        throw new ElasticSql2DslException("[syntax error] Select field ref level could <= 3");
-                    }
-                    SQLIdentifierExpr superOwnerIdfExpr = (SQLIdentifierExpr) ownerPropertyExpr.getOwner();
-                    if (StringUtils.isNotBlank(queryAsAlias) && queryAsAlias.equalsIgnoreCase(superOwnerIdfExpr.getName())) {
-                        selectFields.add(String.format("%s.%s", ownerPropertyExpr.getName(), propertyExpr.getName()));
-                    } else {
-                        throw new ElasticSql2DslException("[syntax error] Select field qualifier not support: " + superOwnerIdfExpr.getName());
-                    }
-                } else if (propertyExpr.getOwner() instanceof SQLIdentifierExpr) {
-                    SQLIdentifierExpr ownerIdfExpr = (SQLIdentifierExpr) propertyExpr.getOwner();
-                    if (StringUtils.isNotBlank(queryAsAlias) && queryAsAlias.equalsIgnoreCase(ownerIdfExpr.getName())) {
-                        selectFields.add(propertyExpr.getName());
-                    } else {
-                        selectFields.add(String.format("%s.%s", ownerIdfExpr.getName(), propertyExpr.getName()));
-                    }
-                }
-            }
-        });
-        dslContext.setQueryFieldList(selectFields);
-    }
-}

+ 67 - 9
src/test/java/org/elasticsearch/SqlParserTest.java

@@ -3,14 +3,14 @@ package org.elasticsearch;
 import junit.framework.TestCase;
 import org.apache.commons.collections.CollectionUtils;
 import org.elasticsearch.dsl.ElasticDslContext;
-import org.elasticsearch.dsl.ElasticSql2DslParser;
+import org.elasticsearch.dsl.parser.ElasticSql2DslParser;
 import org.junit.Assert;
 
 
 public class SqlParserTest extends TestCase {
 
     public void testParseSelectFieldWithQueryAs() {
-        String sql = "select b.id,bookCategory,b.bookStatus,clazz.sortNo,b.clazz.cid from book b where 1 = 1";
+        String sql = "select b.id,bookCategory,b.bookStatus,clazz.sortNo,b.clazz.cid from book b where c = 1";
         ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser(sql);
         ElasticDslContext dslContext = sql2DslParser.parse();
 
@@ -23,7 +23,7 @@ public class SqlParserTest extends TestCase {
     }
 
     public void testParseSelectFieldWithoutQueryAs() {
-        String sql = "select b.id,bookCategory,b.bookStatus,clazz.sortNo,clazz.cid from book where 1 = 1";
+        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();
 
@@ -35,8 +35,8 @@ public class SqlParserTest extends TestCase {
         Assert.assertEquals(dslContext.getQueryFieldList().get(4), "clazz.cid");
     }
 
-    public void testParseSelectFieldMatchAll() {
-        String sql = "select * from book where 1 = 1";
+    public void testParseSelectFieldMatchAll_01() {
+        String sql = "select * from book where c = 1";
         ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser(sql);
         ElasticDslContext dslContext = sql2DslParser.parse();
 
@@ -44,14 +44,72 @@ public class SqlParserTest extends TestCase {
         Assert.assertTrue(CollectionUtils.isEmpty(dslContext.getQueryFieldList()));
     }
 
+    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()));
+    }
+
+    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)));
+    }
+
+    public void testParseInFilterCondition_01() {
+        String sql = "select * from book bk where bk.status in ('ONLINE','DONE') and productCategory='802'";
+
+        ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser(sql);
+        ElasticDslContext dslContext = sql2DslParser.parse();
+        System.out.println(dslContext.toString());
+    }
+
+    public void testParseEqFilterCondition_01() {
+        //String sql = "select * from book bk where (bk.price = 10.2 or bk.category not in ('AV', 'H')) and bk.status in ('ONLINE', 'DONE')";
+
+        String sql = "select p.id,p.productCategory,p.displayName from product_v9 p "
+                + "where p.productCategory in ('901','902') and p.userGroupArray in ('NEW_USER', 'DEFAULT') and salesArea not in(2,3,4) "
+                + " and p.productStatus in ('ONLINE', 'PAUSE', 'TEMPORARY_FULL', 'PREVIEW')"
+                + " and p.sourceType = '9' and (p.productType='LOAN_REQUEST' or (p.price > 100 and p.price <= 200))"
+                + " and p.price between 1 and 1000";
+
+
+        ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser(sql);
+        ElasticDslContext dslContext = sql2DslParser.parse();
+        System.out.println(dslContext.toString());
+    }
+
     public void testParseFilterCondition() {
-        //String sql = "select * from book b where 1 = 1 and b.status='ONLINE'"; //SQLBinaryOpExpr
-        //String sql = "select * from book b where price+1 < 2"; //SQLBinaryOpExpr
+        //String sql = "select * from book b where b.status='ONLINE'"; //SQLBinaryOpExpr
         //String sql = "select * from book b where c in (1,2,3)";    //SQLInListExpr
         //String sql = "select * from book b where c not in (1,2,3)"; //SQLInListExpr
-        //String sql = "select * from book b where c between 1 and 3"; //SQLBetweenExpr
+        String sql = "select * from book b where c between 1 and 3"; //SQLBetweenExpr
+
+        ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser(sql);
+        ElasticDslContext dslContext = sql2DslParser.parse();
+
+        System.out.println(dslContext.toString());
+    }
+
+    public void testParseIsNullFilter() {
+        String sql = "select * from book b where b.cls is not null"; //SQLBetweenExpr
+
+        ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser(sql);
+        ElasticDslContext dslContext = sql2DslParser.parse();
+
+        System.out.println(dslContext.toString());
+    }
 
-        String sql = "select * from book bk where a + 1 > b"; //SQLBetweenExpr
+    public void testParseOrderCondition() {
+        String sql = "select * from book b where b.status = 'ONLINE' order by nvl(b.sortNo,-1) asc";
+        //String sql = "select * from book b where b.status = 'ONLINE' order by b.sortNo asc,b.bbs desc";
 
         ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser(sql);
         ElasticDslContext dslContext = sql2DslParser.parse();