| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- 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.ElasticSqlIdentifier;
- import org.elasticsearch.dsl.ElasticSqlParseUtil;
- import org.elasticsearch.dsl.ParseActionListener;
- import org.elasticsearch.dsl.enums.SQLConditionOperator;
- 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;
- import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
- 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();
- BoolFilterBuilder whereCondition = FilterBuilders.boolFilter();
- if (queryBlock.getWhere() != null) {
- SqlCondition sqlCondition = parseFilterCondition(dslContext, queryBlock.getWhere());
- if (!sqlCondition.isAndOr()) {
- whereCondition.must(sqlCondition.getFilterList().get(0));
- } else {
- for (FilterBuilder filter : sqlCondition.getFilterList()) {
- if (sqlCondition.getOperator() == SQLBinaryOperator.BooleanAnd) {
- whereCondition.must(filter);
- }
- if (sqlCondition.getOperator() == SQLBinaryOperator.BooleanOr) {
- whereCondition.should(filter);
- }
- }
- }
- }
- dslContext.getParseResult().setWhereCondition(whereCondition);
- }
- private SqlCondition parseFilterCondition(ElasticDslContext dslContext, SQLExpr sqlExpr) {
- if (sqlExpr instanceof SQLBinaryOpExpr) {
- SQLBinaryOpExpr sqlBinOpExpr = (SQLBinaryOpExpr) sqlExpr;
- SQLBinaryOperator binaryOperator = sqlBinOpExpr.getOperator();
- if (SQLBinaryOperator.BooleanAnd == binaryOperator || SQLBinaryOperator.BooleanOr == binaryOperator) {
- final SqlCondition leftCondition = parseFilterCondition(dslContext, sqlBinOpExpr.getLeft());
- final SqlCondition rightCondition = parseFilterCondition(dslContext, sqlBinOpExpr.getRight());
- List<FilterBuilder> curFilterList = Lists.newArrayList();
- if (!leftCondition.isAndOr() || leftCondition.operator == binaryOperator) {
- curFilterList.addAll(leftCondition.getFilterList());
- } else {
- final BoolFilterBuilder subBoolFilter = FilterBuilders.boolFilter();
- leftCondition.getFilterList().stream().forEach(new Consumer<FilterBuilder>() {
- @Override
- public void accept(FilterBuilder filter) {
- if (leftCondition.getOperator() == SQLBinaryOperator.BooleanAnd) {
- subBoolFilter.must(filter);
- }
- if (leftCondition.getOperator() == SQLBinaryOperator.BooleanOr) {
- subBoolFilter.should(filter);
- }
- }
- });
- curFilterList.add(subBoolFilter);
- }
- if (!rightCondition.isAndOr() || rightCondition.operator == binaryOperator) {
- curFilterList.addAll(rightCondition.getFilterList());
- } else {
- final BoolFilterBuilder subBoolFilter = FilterBuilders.boolFilter();
- rightCondition.getFilterList().stream().forEach(new Consumer<FilterBuilder>() {
- @Override
- public void accept(FilterBuilder filter) {
- if (rightCondition.getOperator() == SQLBinaryOperator.BooleanAnd) {
- subBoolFilter.must(filter);
- }
- if (rightCondition.getOperator() == SQLBinaryOperator.BooleanOr) {
- subBoolFilter.should(filter);
- }
- }
- });
- curFilterList.add(subBoolFilter);
- }
- return new SqlCondition(curFilterList, binaryOperator);
- }
- }
- return new SqlCondition(parseAtomFilterCondition(dslContext, sqlExpr));
- }
- private FilterBuilder parseAtomFilterCondition(ElasticDslContext dslContext, SQLExpr sqlExpr) {
- if (sqlExpr instanceof SQLBinaryOpExpr) {
- SQLBinaryOpExpr sqlBinOpExpr = (SQLBinaryOpExpr) sqlExpr;
- final SQLBinaryOperator binaryOperator = sqlBinOpExpr.getOperator();
- if (ElasticSqlParseUtil.isValidBinOperator(binaryOperator)) {
- //EQ NEQ
- if (SQLBinaryOperator.Equality == binaryOperator || SQLBinaryOperator.LessThanOrGreater == binaryOperator || SQLBinaryOperator.NotEqual == binaryOperator) {
- Object targetVal = ElasticSqlParseUtil.transferSqlArg(sqlBinOpExpr.getRight(), dslContext.getSqlArgs());
- SQLConditionOperator operator = SQLBinaryOperator.Equality == binaryOperator ? SQLConditionOperator.Equality : SQLConditionOperator.NotEqual;
- return parseCondition(sqlBinOpExpr.getLeft(), operator, new Object[]{targetVal}, dslContext.getParseResult().getQueryAs(), new ConditionFilterBuilder() {
- @Override
- public FilterBuilder buildFilter(String leftIdfName, SQLConditionOperator operator, Object[] rightParamValues) {
- FilterBuilder eqFilter = FilterBuilders.termFilter(leftIdfName, rightParamValues[0]);
- if (SQLConditionOperator.Equality == operator) {
- return eqFilter;
- } else {
- return FilterBuilders.notFilter(eqFilter);
- }
- }
- });
- }
- //GT GTE LT LTE
- if (SQLBinaryOperator.GreaterThan == binaryOperator || SQLBinaryOperator.GreaterThanOrEqual == binaryOperator
- || SQLBinaryOperator.LessThan == binaryOperator || SQLBinaryOperator.LessThanOrEqual == binaryOperator) {
- SQLConditionOperator operator = null;
- if (SQLBinaryOperator.GreaterThan == binaryOperator) {
- operator = SQLConditionOperator.GreaterThan;
- } else if (SQLBinaryOperator.GreaterThanOrEqual == binaryOperator) {
- operator = SQLConditionOperator.GreaterThanOrEqual;
- } else if (SQLBinaryOperator.LessThan == binaryOperator) {
- operator = SQLConditionOperator.LessThan;
- } else if (SQLBinaryOperator.LessThanOrEqual == binaryOperator) {
- operator = SQLConditionOperator.LessThanOrEqual;
- }
- Object targetVal = ElasticSqlParseUtil.transferSqlArg(sqlBinOpExpr.getRight(), dslContext.getSqlArgs());
- return parseCondition(sqlBinOpExpr.getLeft(), operator, new Object[]{targetVal}, dslContext.getParseResult().getQueryAs(), new ConditionFilterBuilder() {
- @Override
- public FilterBuilder buildFilter(String leftIdfName, SQLConditionOperator operator, Object[] rightParamValues) {
- FilterBuilder rangeFilter = null;
- if (SQLConditionOperator.GreaterThan == operator) {
- rangeFilter = FilterBuilders.rangeFilter(leftIdfName).gt(rightParamValues[0]);
- } else if (SQLConditionOperator.GreaterThanOrEqual == operator) {
- rangeFilter = FilterBuilders.rangeFilter(leftIdfName).gte(rightParamValues[0]);
- } else if (SQLConditionOperator.LessThan == operator) {
- rangeFilter = FilterBuilders.rangeFilter(leftIdfName).lt(rightParamValues[0]);
- } else if (SQLConditionOperator.LessThanOrEqual == operator) {
- rangeFilter = FilterBuilders.rangeFilter(leftIdfName).lte(rightParamValues[0]);
- }
- 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");
- }
- SQLConditionOperator operator = SQLBinaryOperator.Is == binaryOperator ? SQLConditionOperator.IsNull : SQLConditionOperator.IsNotNull;
- return parseCondition(sqlBinOpExpr.getLeft(), operator, null, dslContext.getParseResult().getQueryAs(), new ConditionFilterBuilder() {
- @Override
- public FilterBuilder buildFilter(String leftIdfName, SQLConditionOperator operator, Object[] rightParamValues) {
- FilterBuilder missingFilter = FilterBuilders.missingFilter(leftIdfName);
- if (SQLConditionOperator.IsNotNull == operator) {
- return FilterBuilders.notFilter(missingFilter);
- }
- return missingFilter;
- }
- });
- }
- }
- } else if (sqlExpr instanceof SQLInListExpr) {
- final 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(), dslContext.getSqlArgs());
- SQLConditionOperator operator = inListExpr.isNot() ? SQLConditionOperator.NotIn : SQLConditionOperator.In;
- return parseCondition(inListExpr.getExpr(), operator, targetInList, dslContext.getParseResult().getQueryAs(), new ConditionFilterBuilder() {
- @Override
- public FilterBuilder buildFilter(String leftIdfName, SQLConditionOperator operator, Object[] rightParamValues) {
- if (SQLConditionOperator.NotIn == operator) {
- return FilterBuilders.notFilter(FilterBuilders.inFilter(leftIdfName, rightParamValues));
- } else {
- return FilterBuilders.inFilter(leftIdfName, rightParamValues);
- }
- }
- });
- } else if (sqlExpr instanceof SQLBetweenExpr) {
- SQLBetweenExpr betweenExpr = (SQLBetweenExpr) sqlExpr;
- Object from = ElasticSqlParseUtil.transferSqlArg(betweenExpr.getBeginExpr(), dslContext.getSqlArgs());
- 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(), SQLConditionOperator.BetweenAnd, new Object[]{from, to}, dslContext.getParseResult().getQueryAs(), new ConditionFilterBuilder() {
- @Override
- public FilterBuilder buildFilter(String leftIdfName, SQLConditionOperator operator, Object[] rightParamValues) {
- return FilterBuilders.rangeFilter(leftIdfName).gte(rightParamValues[0]).lte(rightParamValues[1]);
- }
- });
- }
- throw new ElasticSql2DslException("[syntax error] Can not support syntax type: " + sqlExpr.toString());
- }
- private FilterBuilder parseCondition(SQLExpr leftIdentifierExpr, SQLConditionOperator operator, Object[] rightParamValues, String queryAs, final ConditionFilterBuilder filterBuilder) {
- final List<FilterBuilder> conditionCollector = Lists.newLinkedList();
- final Object[] pRightParamValues = rightParamValues;
- final SQLConditionOperator pOperator = operator;
- ElasticSqlIdentifier sqlIdentifier = ElasticSqlIdentifierHelper.parseSqlIdentifier(leftIdentifierExpr, queryAs, new ElasticSqlIdentifierHelper.ElasticSqlSinglePropertyFunc() {
- @Override
- public void parse(String propertyName) {
- FilterBuilder originalFilter = filterBuilder.buildFilter(propertyName, pOperator, pRightParamValues);
- conditionCollector.add(originalFilter);
- }
- }, new ElasticSqlIdentifierHelper.ElasticSqlPathPropertyFunc() {
- @Override
- public void parse(String propertyPath, String propertyName) {
- FilterBuilder originalFilter = filterBuilder.buildFilter(propertyName, pOperator, pRightParamValues);
- FilterBuilder nestFilter = FilterBuilders.nestedFilter(propertyPath, originalFilter);
- conditionCollector.add(nestFilter);
- }
- });
- if (CollectionUtils.isNotEmpty(conditionCollector)) {
- onAtomConditionParse(sqlIdentifier, rightParamValues, operator);
- return conditionCollector.get(0);
- }
- return null;
- }
- private void onAtomConditionParse(ElasticSqlIdentifier paramName, Object[] paramValues, SQLConditionOperator operator) {
- try {
- parseActionListener.onAtomConditionParse(paramName, paramValues, operator);
- } catch (Exception ex) {
- try {
- parseActionListener.onFailure(ex);
- } catch (Exception exp) {
- //ignore;
- }
- }
- }
- @FunctionalInterface
- private interface ConditionFilterBuilder {
- FilterBuilder buildFilter(String leftIdfName, SQLConditionOperator operator, Object[] rightParamValues);
- }
- private class SqlCondition {
- //是否AND/OR运算
- private boolean isAndOr = false;
- //运算符
- private SQLBinaryOperator operator;
- //条件集合
- private List<FilterBuilder> filterList;
- public SqlCondition(FilterBuilder atomFilter) {
- filterList = Lists.newArrayList(atomFilter);
- isAndOr = false;
- }
- public SqlCondition(List<FilterBuilder> filterList, SQLBinaryOperator operator) {
- this.filterList = filterList;
- isAndOr = true;
- this.operator = operator;
- }
- public boolean isAndOr() {
- return isAndOr;
- }
- public SQLBinaryOperator getOperator() {
- return operator;
- }
- public List<FilterBuilder> getFilterList() {
- return filterList;
- }
- }
- }
|