spuerx 9 лет назад
Родитель
Сommit
9adfa31251

+ 19 - 76
src/main/java/org/elasticsearch/dsl/ElasticDslBuilder.java

@@ -1,15 +1,10 @@
 package org.elasticsearch.dsl;
 
-import com.alibaba.druid.sql.ast.SQLExpr;
-import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
-import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
-import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
 import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
-import com.google.common.collect.Lists;
+import com.google.common.collect.ImmutableList;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
-import org.elasticsearch.index.query.BoolFilterBuilder;
+import org.elasticsearch.dsl.parser.*;
 import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
-import org.elasticsearch.utils.StringUtils;
 
 import java.util.List;
 
@@ -21,78 +16,26 @@ public class ElasticDslBuilder {
         this.queryExpr = queryExpr;
     }
 
-    public ElasticDslContext build() {
-        ElasticDslContext dslContext = new ElasticDslContext();
-        if (queryExpr.getSubQuery().getQuery() instanceof ElasticSqlSelectQueryBlock) {
-            ElasticSqlSelectQueryBlock queryBlock = (ElasticSqlSelectQueryBlock) queryExpr.getSubQuery().getQuery();
-            //解析SQL指定索引别名
-            parseQueryAs(dslContext, queryBlock);
-            //解析SQL查询条件
-            parseFilterCondition(dslContext.boolFilter(), queryBlock.getWhere());
-            //解析查询阶段
-            parseSelectFieldList(dslContext, queryBlock);
-        }
-        return dslContext;
-    }
-
-    private void parseFilterCondition(BoolFilterBuilder filterBuilder, SQLExpr sqlExpr) {
-        System.out.println(sqlExpr.getClass());
-        if (sqlExpr == null) {
-            return;
-        }
-
-        //throw new ElasticSql2DslException("[syntax error] Where condition not support type: " + sqlExpr.getClass());
-
-        if (sqlExpr instanceof SQLBinaryOpExpr) {
-            SQLBinaryOpExpr sqlBinOpExpr = (SQLBinaryOpExpr) sqlExpr;
-        }
-    }
-
-    private void parseQueryAs(ElasticDslContext dslContext, ElasticSqlSelectQueryBlock queryBlock) {
-        dslContext.setQueryAs(queryBlock.getFrom().getAlias());
-    }
+    //SQL解析器的顺序不能改变
+    private static final List<ElasticSqlParser> sqlParseProcessors = ImmutableList.of(
+            //解析SQL指定的索引和文档类型
+            QueryIndexParser::parseQueryIndicesAndTypes,
+            //解析SQL查询索引别名
+            QueryAsAliasParser::parseQueryAsAlias,
+            //解析SQL查询指定的where条件
+            FilterConditionParser::parseFilterCondition,
+            //解析SQL查询指定的字段
+            SelectFieldListParser::parseSelectFieldList
 
-    private void parseSelectFieldList(ElasticDslContext dslContext, ElasticSqlSelectQueryBlock queryBlock) {
-        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;
-            }
+    public ElasticDslContext build() {
+        ElasticDslContext dslContext = new ElasticDslContext(queryExpr);
+        if (queryExpr.getSubQuery().getQuery() instanceof ElasticSqlSelectQueryBlock) {
+            sqlParseProcessors.stream().forEach(sqlParser -> sqlParser.parse(dslContext));
+            return dslContext;
         }
-
-        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);
+        throw new ElasticSql2DslException("[syntax error] ElasticSql only support Select Sql, but get: " + queryExpr.getSubQuery().getQuery().getClass());
     }
 
 }

+ 15 - 4
src/main/java/org/elasticsearch/dsl/ElasticDslContext.java

@@ -1,5 +1,6 @@
 package org.elasticsearch.dsl;
 
+import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
 import org.apache.commons.collections.CollectionUtils;
 import org.elasticsearch.ElasticMockClient;
 import org.elasticsearch.action.search.SearchRequestBuilder;
@@ -23,12 +24,18 @@ public class ElasticDslContext {
     private List<String> types;
     /*查询索引别名*/
     private String queryAs;
-    /*SQL的where条件*/
-    private BoolFilterBuilder filterBuilder;
-    /*SQL的order by条件*/
-    private List<SortBuilder> sortBuilderList;
     /*查询字段列表*/
     private List<String> queryFieldList;
+    /*SQL的where条件*/
+    private transient BoolFilterBuilder filterBuilder;
+    /*SQL的order by条件*/
+    private transient List<SortBuilder> sortBuilderList;
+    /*SQL*/
+    private transient SQLQueryExpr queryExpr;
+
+    public ElasticDslContext(SQLQueryExpr queryExpr) {
+        this.queryExpr = queryExpr;
+    }
 
     public void addSort(SortBuilder sortBuilder) {
         if (sortBuilder != null) {
@@ -94,6 +101,10 @@ public class ElasticDslContext {
         this.queryAs = queryAs;
     }
 
+    public SQLQueryExpr getQueryExpr() {
+        return queryExpr;
+    }
+
     public String toDsl() {
         SearchRequestBuilder requestBuilder = new SearchRequestBuilder(ElasticMockClient.get());
 

+ 2 - 2
src/main/java/org/elasticsearch/dsl/ElasticSql2DslParser.java

@@ -36,11 +36,11 @@ public class ElasticSql2DslParser {
 
     private void check(ElasticSqlExprParser sqlExprParser, SQLExpr sqlQueryExpr) {
         if (sqlExprParser.getLexer().token() != Token.EOF) {
-            throw new ElasticSql2DslException("Sql last token is not EOF");
+            throw new ElasticSql2DslException("[syntax error] Sql last token is not EOF");
         }
 
         if (!(sqlQueryExpr instanceof SQLQueryExpr)) {
-            throw new ElasticSql2DslException("Sql is not select sql");
+            throw new ElasticSql2DslException("[syntax error] Sql is not select sql");
         }
     }
 

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

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

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

@@ -0,0 +1,64 @@
+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;
+    }
+
+}

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

@@ -0,0 +1,11 @@
+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());
+    }
+}

+ 23 - 0
src/main/java/org/elasticsearch/dsl/parser/QueryIndexParser.java

@@ -0,0 +1,23 @@
+package org.elasticsearch.dsl.parser;
+
+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 QueryIndexParser {
+    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.setIndices(ImmutableList.of(tableSource.getExpr().toString()));
+        } else {
+            throw new ElasticSql2DslException("[syntax error] From table source could be [SQLExprTableSource],but get: " + queryBlock.getFrom().getClass());
+        }
+    }
+}

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

@@ -0,0 +1,57 @@
+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);
+    }
+}

+ 3 - 1
src/test/java/org/elasticsearch/SqlParserTest.java

@@ -49,7 +49,9 @@ public class SqlParserTest extends TestCase {
         //String sql = "select * from book b where price+1 < 2"; //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
+
+        String sql = "select * from book bk where a + 1 > b"; //SQLBetweenExpr
 
         ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser(sql);
         ElasticDslContext dslContext = sql2DslParser.parse();