spuerx 9 年之前
父節點
當前提交
2c70b5ebbd

+ 16 - 24
src/main/java/org/elasticsearch/dsl/ElasticSql2DslParser.java

@@ -17,27 +17,19 @@ 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);
+        return parse(sql, null, new ParseActionListenerAdapter());
     }
 
+    public ElasticSqlParseResult parse(String sql, ParseActionListener parseActionListener) throws ElasticSql2DslException {
+        return parse(sql, null, parseActionListener);
+    }
 
-    /**
-     * 执行sql到dsl转换
-     *
-     * @param sql     待解析sql
-     * @param sqlArgs sql动态参数
-     * @return 解析结果
-     * @throws ElasticSql2DslException 当解析出现语法错误时抛出
-     */
     public ElasticSqlParseResult parse(String sql, Object[] sqlArgs) throws ElasticSql2DslException {
+        return parse(sql, sqlArgs, new ParseActionListenerAdapter());
+    }
+
+    public ElasticSqlParseResult parse(String sql, Object[] sqlArgs, ParseActionListener parseActionListener) throws ElasticSql2DslException {
         SQLQueryExpr queryExpr = null;
         try {
             ElasticSqlExprParser elasticSqlExprParser = new ElasticSqlExprParser(sql);
@@ -50,7 +42,7 @@ public class ElasticSql2DslParser {
 
         final ElasticDslContext elasticDslContext = new ElasticDslContext(queryExpr, sqlArgs);
         if (queryExpr.getSubQuery().getQuery() instanceof ElasticSqlSelectQueryBlock) {
-            buildSqlParserChain().stream().forEach(new Consumer<QueryParser>() {
+            buildSqlParserChain(parseActionListener).stream().forEach(new Consumer<QueryParser>() {
                 @Override
                 public void accept(QueryParser sqlParser) {
                     sqlParser.parse(elasticDslContext);
@@ -80,21 +72,21 @@ public class ElasticSql2DslParser {
         }
     }
 
-    private List<QueryParser> buildSqlParserChain() {
+    private List<QueryParser> buildSqlParserChain(ParseActionListener parseActionListener) {
         //SQL解析器的顺序不能改变
         return ImmutableList.of(
                 //解析SQL指定的索引和文档类型
-                new QueryFromParser(),
+                new QueryFromParser(parseActionListener),
                 //解析SQL查询指定的where条件
-                new QueryWhereConditionParser(),
+                new QueryWhereConditionParser(parseActionListener),
                 //解析SQL排序条件
-                new QueryOrderConditionParser(),
+                new QueryOrderConditionParser(parseActionListener),
                 //解析路由参数
-                new QueryRoutingValParser(),
+                new QueryRoutingValParser(parseActionListener),
                 //解析SQL查询指定的字段
-                new QuerySelectFieldListParser(),
+                new QuerySelectFieldListParser(parseActionListener),
                 //解析SQL的分页条数
-                new QueryLimitSizeParser()
+                new QueryLimitSizeParser(parseActionListener)
         );
     }
 }

+ 41 - 0
src/main/java/org/elasticsearch/dsl/ElasticSqlIdentifier.java

@@ -0,0 +1,41 @@
+package org.elasticsearch.dsl;
+
+public class ElasticSqlIdentifier {
+
+    private String pathName;
+    private String propertyName;
+    private IdentifierType identifierType;
+
+    public ElasticSqlIdentifier(String propertyName) {
+        this.propertyName = propertyName;
+        this.identifierType = IdentifierType.Property;
+    }
+
+    public ElasticSqlIdentifier(String pathName, String propertyName, IdentifierType identifierType) {
+        if (identifierType != IdentifierType.InnerDocProperty && identifierType != IdentifierType.NestedDocProperty && identifierType != IdentifierType.MatchAllField) {
+            throw new IllegalArgumentException("identifierType must one of [InnerDocProperty, NestedDocProperty]");
+        }
+        this.pathName = pathName;
+        this.propertyName = propertyName;
+        this.identifierType = identifierType;
+    }
+
+    public String getPathName() {
+        return pathName;
+    }
+
+    public String getPropertyName() {
+        return propertyName;
+    }
+
+    public IdentifierType getIdentifierType() {
+        return identifierType;
+    }
+
+    public static enum IdentifierType {
+        MatchAllField,
+        Property,
+        InnerDocProperty,
+        NestedDocProperty,
+    }
+}

+ 10 - 0
src/main/java/org/elasticsearch/dsl/ParseActionListener.java

@@ -0,0 +1,10 @@
+package org.elasticsearch.dsl;
+
+public interface ParseActionListener {
+
+    void onSqlSelectFieldParse(ElasticSqlIdentifier sqlIdentifier);
+
+    void onAtomConditionParse(ElasticSqlIdentifier sqlIdentifier, Object[] paramValues, SQLConditionOperator operator);
+
+    void onFailure(Throwable t);
+}

+ 19 - 0
src/main/java/org/elasticsearch/dsl/ParseActionListenerAdapter.java

@@ -0,0 +1,19 @@
+package org.elasticsearch.dsl;
+
+public class ParseActionListenerAdapter implements ParseActionListener {
+
+    @Override
+    public void onSqlSelectFieldParse(ElasticSqlIdentifier sqlIdentifier) {
+
+    }
+
+    @Override
+    public void onAtomConditionParse(ElasticSqlIdentifier sqlIdentifier, Object[] paramValues, SQLConditionOperator operator) {
+
+    }
+
+    @Override
+    public void onFailure(Throwable t) {
+
+    }
+}

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

@@ -1,8 +0,0 @@
-package org.elasticsearch.dsl;
-
-public enum SQLIdentifierType {
-    MatchAllField,
-    Property,
-    InnerDocProperty,
-    NestedDocProperty,
-}

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

@@ -4,10 +4,18 @@ 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 org.elasticsearch.dsl.ElasticDslContext;
+import org.elasticsearch.dsl.ParseActionListener;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
 
 public class QueryFromParser implements QueryParser {
+
+    private ParseActionListener parseActionListener;
+
+    public QueryFromParser(ParseActionListener parseActionListener) {
+        this.parseActionListener = parseActionListener;
+    }
+
     @Override
     public void parse(ElasticDslContext dslContext) {
         ElasticSqlSelectQueryBlock queryBlock = (ElasticSqlSelectQueryBlock) dslContext.getQueryExpr().getSubQuery().getQuery();

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

@@ -5,10 +5,18 @@ import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
 import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
 import org.elasticsearch.dsl.ElasticDslContext;
 import org.elasticsearch.dsl.ElasticSqlParseUtil;
+import org.elasticsearch.dsl.ParseActionListener;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
 
 public class QueryLimitSizeParser implements QueryParser {
+
+    private ParseActionListener parseActionListener;
+
+    public QueryLimitSizeParser(ParseActionListener parseActionListener) {
+        this.parseActionListener = parseActionListener;
+    }
+
     @Override
     public void parse(ElasticDslContext dslContext) {
         ElasticSqlSelectQueryBlock queryBlock = (ElasticSqlSelectQueryBlock) dslContext.getQueryExpr().getSubQuery().getQuery();

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

@@ -12,6 +12,7 @@ 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.ParseActionListener;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 import org.elasticsearch.dsl.parser.helper.ElasticSqlIdentifierHelper;
 import org.elasticsearch.dsl.parser.helper.ElasticSqlMethodInvokeHelper;
@@ -24,6 +25,13 @@ import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
 import java.util.List;
 
 public class QueryOrderConditionParser implements QueryParser {
+
+    private ParseActionListener parseActionListener;
+
+    public QueryOrderConditionParser(ParseActionListener parseActionListener) {
+        this.parseActionListener = parseActionListener;
+    }
+
     @Override
     public void parse(ElasticDslContext dslContext) {
         ElasticSqlSelectQueryBlock queryBlock = (ElasticSqlSelectQueryBlock) dslContext.getQueryExpr().getSubQuery().getQuery();

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

@@ -7,12 +7,20 @@ 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.ParseActionListener;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
 
 import java.util.List;
 
 public class QueryRoutingValParser implements QueryParser {
+
+    private ParseActionListener parseActionListener;
+
+    public QueryRoutingValParser(ParseActionListener parseActionListener) {
+        this.parseActionListener = parseActionListener;
+    }
+
     @Override
     public void parse(ElasticDslContext dslContext) {
         ElasticSqlSelectQueryBlock queryBlock = (ElasticSqlSelectQueryBlock) dslContext.getQueryExpr().getSubQuery().getQuery();

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

@@ -3,6 +3,8 @@ 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.ElasticSqlIdentifier;
+import org.elasticsearch.dsl.ParseActionListener;
 import org.elasticsearch.dsl.parser.helper.ElasticSqlIdentifierHelper;
 import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
 
@@ -12,13 +14,19 @@ public class QuerySelectFieldListParser implements QueryParser {
 
     public static final String SQL_FIELD_MATCH_ALL = "*";
 
+    private ParseActionListener parseActionListener;
+
+    public QuerySelectFieldListParser(ParseActionListener parseActionListener) {
+        this.parseActionListener = parseActionListener;
+    }
+
     @Override
     public void parse(ElasticDslContext dslContext) {
         ElasticSqlSelectQueryBlock queryBlock = (ElasticSqlSelectQueryBlock) dslContext.getQueryExpr().getSubQuery().getQuery();
 
         final List<String> selectFields = Lists.newLinkedList();
         for (SQLSelectItem selectField : queryBlock.getSelectList()) {
-            ElasticSqlIdentifierHelper.parseSqlIdentifier(selectField.getExpr(), dslContext.getParseResult().getQueryAs(), new ElasticSqlIdentifierHelper.ElasticSqlSinglePropertyFunc() {
+            ElasticSqlIdentifier sqlIdentifier = ElasticSqlIdentifierHelper.parseSqlIdentifier(selectField.getExpr(), dslContext.getParseResult().getQueryAs(), new ElasticSqlIdentifierHelper.ElasticSqlSinglePropertyFunc() {
                 @Override
                 public void parse(String propertyName) {
                     if (!SQL_FIELD_MATCH_ALL.equals(propertyName)) {
@@ -31,7 +39,20 @@ public class QuerySelectFieldListParser implements QueryParser {
                     selectFields.add(String.format("%s.%s", propertyPath, propertyName));
                 }
             });
+            onSqlSelectFieldParse(sqlIdentifier);
         }
         dslContext.getParseResult().setQueryFieldList(selectFields);
     }
+
+    private void onSqlSelectFieldParse(ElasticSqlIdentifier sqlIdentifier) {
+        try {
+            parseActionListener.onSqlSelectFieldParse(sqlIdentifier);
+        } catch (Exception ex) {
+            try {
+                parseActionListener.onFailure(ex);
+            } catch (Exception exp) {
+                //ignore;
+            }
+        }
+    }
 }

+ 23 - 11
src/main/java/org/elasticsearch/dsl/parser/QueryWhereConditionParser.java

@@ -4,10 +4,7 @@ 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.ElasticSqlParseUtil;
-import org.elasticsearch.dsl.SQLConditionOperator;
-import org.elasticsearch.dsl.SQLIdentifierType;
+import org.elasticsearch.dsl.*;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 import org.elasticsearch.dsl.parser.helper.ElasticSqlIdentifierHelper;
 import org.elasticsearch.index.query.BoolFilterBuilder;
@@ -19,6 +16,13 @@ import java.util.List;
 import java.util.function.Consumer;
 
 public class QueryWhereConditionParser implements QueryParser {
+
+    private ParseActionListener parseActionListener;
+
+    public QueryWhereConditionParser(ParseActionListener parseActionListener) {
+        this.parseActionListener = parseActionListener;
+    }
+
     @Override
     public void parse(ElasticDslContext dslContext) {
         ElasticSqlSelectQueryBlock queryBlock = (ElasticSqlSelectQueryBlock) dslContext.getQueryExpr().getSubQuery().getQuery();
@@ -209,7 +213,7 @@ public class QueryWhereConditionParser implements QueryParser {
         final List<FilterBuilder> conditionCollector = Lists.newLinkedList();
         final Object[] pRightParamValues = rightParamValues;
         final SQLConditionOperator pOperator = operator;
-        SQLIdentifierType idfType = ElasticSqlIdentifierHelper.parseSqlIdentifier(leftIdentifierExpr, queryAs, new ElasticSqlIdentifierHelper.ElasticSqlSinglePropertyFunc() {
+        ElasticSqlIdentifier sqlIdentifier = ElasticSqlIdentifierHelper.parseSqlIdentifier(leftIdentifierExpr, queryAs, new ElasticSqlIdentifierHelper.ElasticSqlSinglePropertyFunc() {
             @Override
             public void parse(String propertyName) {
                 FilterBuilder originalFilter = filterBuilder.buildFilter(propertyName, pOperator, pRightParamValues);
@@ -224,19 +228,27 @@ public class QueryWhereConditionParser implements QueryParser {
             }
         });
         if (CollectionUtils.isNotEmpty(conditionCollector)) {
-            //todo invoke listener
-            onAtomConditionParse("", rightParamValues, idfType, operator);
+            onAtomConditionParse(sqlIdentifier, rightParamValues, operator);
             return conditionCollector.get(0);
         }
         return null;
     }
 
-    public void onAtomConditionParse(String paramName, Object[] paramValues, SQLIdentifierType paramPropertyType, SQLConditionOperator operator) {
-
+    private void onAtomConditionParse(ElasticSqlIdentifier sqlIdentifier, Object[] paramValues, SQLConditionOperator operator) {
+        try {
+            parseActionListener.onAtomConditionParse(sqlIdentifier, paramValues, operator);
+        } catch (Exception ex) {
+            try {
+                parseActionListener.onFailure(ex);
+            } catch (Exception exp) {
+                //ignore;
+            }
+        }
     }
 
-    private abstract class ConditionFilterBuilder {
-        public abstract FilterBuilder buildFilter(String leftIdfName, SQLConditionOperator operator, Object[] rightParamValues);
+    @FunctionalInterface
+    private interface ConditionFilterBuilder {
+        FilterBuilder buildFilter(String leftIdfName, SQLConditionOperator operator, Object[] rightParamValues);
     }
 
     private class SqlCondition {

+ 20 - 8
src/main/java/org/elasticsearch/dsl/parser/helper/ElasticSqlIdentifierHelper.java

@@ -8,7 +8,7 @@ import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
 import com.google.common.collect.Lists;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
-import org.elasticsearch.dsl.SQLIdentifierType;
+import org.elasticsearch.dsl.ElasticSqlIdentifier;
 import org.elasticsearch.dsl.exception.ElasticSql2DslException;
 
 import java.util.List;
@@ -24,9 +24,11 @@ public class ElasticSqlIdentifierHelper {
      * @param pathPropertyFunc   内嵌类型处理逻辑(nested)
      * @return 标识符类型
      */
-    public static SQLIdentifierType parseSqlIdentifier(final SQLExpr propertyNameExpr, final String queryAsAlias,
-                                                       final ElasticSqlSinglePropertyFunc singlePropertyFunc,
-                                                       final ElasticSqlPathPropertyFunc pathPropertyFunc) {
+    public static ElasticSqlIdentifier parseSqlIdentifier(final SQLExpr propertyNameExpr, final String queryAsAlias,
+                                                          final ElasticSqlSinglePropertyFunc singlePropertyFunc,
+                                                          final ElasticSqlPathPropertyFunc pathPropertyFunc) {
+        final StringBuilder propertyPathBuilder = new StringBuilder();
+        final StringBuilder propertyNameBuilder = new StringBuilder();
         if (propertyNameExpr instanceof SQLMethodInvokeExpr) {
             //如果指定是inner doc类型
             SQLMethodInvokeExpr innerObjExpr = (SQLMethodInvokeExpr) propertyNameExpr;
@@ -41,10 +43,12 @@ public class ElasticSqlIdentifierHelper {
                 }, new ElasticSqlPathPropertyFunc() {
                     @Override
                     public void parse(String propertyPath, String propertyName) {
+                        propertyPathBuilder.append(propertyPath);
+                        propertyNameBuilder.append(propertyName);
                         singlePropertyFunc.parse(String.format("%s.%s", propertyPath, propertyName));
                     }
                 });
-                return SQLIdentifierType.InnerDocProperty;
+                return new ElasticSqlIdentifier(propertyPathBuilder.toString(), propertyNameBuilder.toString(), ElasticSqlIdentifier.IdentifierType.InnerDocProperty);
             }
 
             //如果执行是nested doc类型
@@ -59,10 +63,12 @@ public class ElasticSqlIdentifierHelper {
                 }, new ElasticSqlPathPropertyFunc() {
                     @Override
                     public void parse(String propertyPath, String propertyName) {
+                        propertyPathBuilder.append(propertyPath);
+                        propertyNameBuilder.append(propertyName);
                         pathPropertyFunc.parse(propertyPath, propertyName);
                     }
                 });
-                return SQLIdentifierType.NestedDocProperty;
+                return new ElasticSqlIdentifier(propertyPathBuilder.toString(), propertyNameBuilder.toString(), ElasticSqlIdentifier.IdentifierType.NestedDocProperty);
             }
 
             throw new ElasticSql2DslException("[syntax error] Sql identifier method only support nested_doc and inner_doc");
@@ -74,19 +80,25 @@ public class ElasticSqlIdentifierHelper {
             @Override
             public void parse(String propertyName) {
                 isInnerDocProperty.add(Boolean.FALSE);
+                propertyNameBuilder.append(propertyName);
                 singlePropertyFunc.parse(propertyName);
             }
         }, new ElasticSqlPathPropertyFunc() {
             @Override
             public void parse(String propertyPath, String propertyName) {
                 isInnerDocProperty.add(Boolean.TRUE);
+                propertyPathBuilder.append(propertyPath);
+                propertyNameBuilder.append(propertyName);
                 singlePropertyFunc.parse(String.format("%s.%s", propertyPath, propertyName));
             }
         });
         if (CollectionUtils.isNotEmpty(isInnerDocProperty)) {
-            return isInnerDocProperty.get(0) ? SQLIdentifierType.InnerDocProperty : SQLIdentifierType.Property;
+            if (isInnerDocProperty.get(0)) {
+                return new ElasticSqlIdentifier(propertyPathBuilder.toString(), propertyNameBuilder.toString(), ElasticSqlIdentifier.IdentifierType.InnerDocProperty);
+            }
+            return new ElasticSqlIdentifier(propertyNameBuilder.toString());
         }
-        return SQLIdentifierType.MatchAllField;
+        return new ElasticSqlIdentifier(propertyPathBuilder.toString(), propertyNameBuilder.toString(), ElasticSqlIdentifier.IdentifierType.MatchAllField);
     }
 
     private static void parseSqlIdf(final SQLExpr propertyNameExpr, final String queryAsAlias,

+ 24 - 2
src/test/java/org/elasticsearch/SqlParserLimitTest.java

@@ -1,7 +1,6 @@
 package org.elasticsearch;
 
-import org.elasticsearch.dsl.ElasticSql2DslParser;
-import org.elasticsearch.dsl.ElasticSqlParseResult;
+import org.elasticsearch.dsl.*;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -27,4 +26,27 @@ public class SqlParserLimitTest {
         Assert.assertEquals(parseResult.getSize(), 15);
     }
 
+    @Test
+    public void testParseLimitExprWithListener() {
+        String sql = "select id,productStatus from index.trx_order trx where trx.status = 'SUCCESS' limit 5,15";
+        ElasticSql2DslParser sql2DslParser = new ElasticSql2DslParser();
+        ElasticSqlParseResult parseResult = sql2DslParser.parse(sql, new ParseActionListenerAdapter() {
+            @Override
+            public void onAtomConditionParse(ElasticSqlIdentifier sqlIdentifier, Object[] paramValues, SQLConditionOperator operator) {
+                System.out.println(sqlIdentifier.getPathName());
+                System.out.println(sqlIdentifier.getPropertyName());
+                System.out.println(sqlIdentifier.getIdentifierType());
+            }
+
+            @Override
+            public void onSqlSelectFieldParse(ElasticSqlIdentifier sqlIdentifier) {
+                System.out.println(sqlIdentifier.getPropertyName());
+            }
+        });
+
+        Assert.assertEquals(parseResult.getFrom(), 5);
+        Assert.assertEquals(parseResult.getSize(), 15);
+    }
+
+
 }