| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- package org.elasticsearch.dsl.parser.syntax;
- import com.alibaba.druid.sql.ast.SQLExpr;
- import com.alibaba.druid.sql.ast.expr.*;
- import com.google.common.collect.ArrayListMultimap;
- import com.google.common.collect.ListMultimap;
- import com.google.common.collect.Lists;
- import org.apache.commons.collections.CollectionUtils;
- import org.elasticsearch.dsl.bean.AtomFilter;
- import org.elasticsearch.dsl.bean.ElasticDslContext;
- import org.elasticsearch.dsl.bean.ElasticSqlQueryField;
- import org.elasticsearch.dsl.bean.SQLCondition;
- import org.elasticsearch.dsl.enums.QueryFieldType;
- import org.elasticsearch.dsl.enums.SQLBoolOperator;
- import org.elasticsearch.dsl.enums.SQLConditionOperator;
- import org.elasticsearch.dsl.enums.SQLConditionType;
- import org.elasticsearch.dsl.exception.ElasticSql2DslException;
- import org.elasticsearch.dsl.parser.QueryParser;
- import org.elasticsearch.dsl.parser.helper.ElasticSqlArgTransferHelper;
- import org.elasticsearch.dsl.parser.listener.ParseActionListener;
- 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;
- 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();
- if (queryBlock.getWhere() != null) {
- SQLCondition whereCondition = parseFilterCondition(dslContext, queryBlock.getWhere());
- SQLBoolOperator operator = whereCondition.getOperator();
- if(SQLConditionType.Atom == whereCondition.getSQLConditionType()) {
- operator = SQLBoolOperator.AND;
- }
- BoolFilterBuilder boolFilter = mergeAtomFilter(whereCondition.getFilterList(), operator);
- dslContext.getParseResult().setWhereCondition(boolFilter);
- }
- }
- 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) {
- SQLBoolOperator operator = SQLBinaryOperator.BooleanAnd == binaryOperator ? SQLBoolOperator.AND : SQLBoolOperator.OR;
- SQLCondition leftCondition = parseFilterCondition(dslContext, sqlBinOpExpr.getLeft());
- SQLCondition rightCondition = parseFilterCondition(dslContext, sqlBinOpExpr.getRight());
- List<AtomFilter> curFilterList = Lists.newArrayList();
- combineFilterBuilder(curFilterList, leftCondition, operator);
- combineFilterBuilder(curFilterList, rightCondition, operator);
- return new SQLCondition(curFilterList, operator);
- }
- }
- return new SQLCondition(parseAtomFilterCondition(dslContext, sqlExpr), SQLConditionType.Atom);
- }
- private void combineFilterBuilder(List<AtomFilter> combiner, SQLCondition SQLCondition, SQLBoolOperator binOperator) {
- if (SQLConditionType.Atom == SQLCondition.getSQLConditionType() || SQLCondition.getOperator() == binOperator) {
- combiner.addAll(SQLCondition.getFilterList());
- }
- else {
- BoolFilterBuilder subBoolFilter = mergeAtomFilter(SQLCondition.getFilterList(), binOperator);
- combiner.add(new AtomFilter(subBoolFilter));
- }
- }
- private BoolFilterBuilder mergeAtomFilter(List<AtomFilter> atomFilterList, SQLBoolOperator operator) {
- BoolFilterBuilder subBoolFilter = FilterBuilders.boolFilter();
- ListMultimap<String, FilterBuilder> listMultiMap = ArrayListMultimap.create();
- for (AtomFilter atomFilter : atomFilterList) {
- if(Boolean.FALSE == atomFilter.getNestedFilter()) {
- if (operator == SQLBoolOperator.AND) {
- subBoolFilter.must(atomFilter.getFilter());
- }
- if (operator == SQLBoolOperator.OR) {
- subBoolFilter.should(atomFilter.getFilter());
- }
- }
- else {
- String nestedDocPrefix = atomFilter.getNestedFilterPathContext();
- listMultiMap.put(nestedDocPrefix, atomFilter.getFilter());
- }
- }
- for (String nestedDocPrefix : listMultiMap.keySet()) {
- List<FilterBuilder> nestedFilterList = listMultiMap.get(nestedDocPrefix);
- if(nestedFilterList.size() == 1) {
- if (operator == SQLBoolOperator.AND) {
- subBoolFilter.must(FilterBuilders.nestedFilter(nestedDocPrefix, nestedFilterList.get(0)));
- }
- if (operator == SQLBoolOperator.OR) {
- subBoolFilter.should(FilterBuilders.nestedFilter(nestedDocPrefix, nestedFilterList.get(0)));
- }
- continue;
- }
- BoolFilterBuilder boolNestedFilter = FilterBuilders.boolFilter();
- for (FilterBuilder nestedFilterItem : nestedFilterList) {
- if (operator == SQLBoolOperator.AND) {
- boolNestedFilter.must(nestedFilterItem);
- }
- if (operator == SQLBoolOperator.OR) {
- boolNestedFilter.should(nestedFilterItem);
- }
- }
- if (operator == SQLBoolOperator.AND) {
- subBoolFilter.must(FilterBuilders.nestedFilter(nestedDocPrefix, boolNestedFilter));
- }
- if (operator == SQLBoolOperator.OR) {
- subBoolFilter.should(FilterBuilders.nestedFilter(nestedDocPrefix, boolNestedFilter));
- }
- }
- return subBoolFilter;
- }
- private AtomFilter parseAtomFilterCondition(ElasticDslContext dslContext, SQLExpr sqlExpr) {
- if (sqlExpr instanceof SQLBinaryOpExpr) {
- SQLBinaryOpExpr sqlBinOpExpr = (SQLBinaryOpExpr) sqlExpr;
- final SQLBinaryOperator binaryOperator = sqlBinOpExpr.getOperator();
- if (isValidBinOperator(binaryOperator)) {
- //EQ NEQ
- if (SQLBinaryOperator.Equality == binaryOperator || SQLBinaryOperator.LessThanOrGreater == binaryOperator || SQLBinaryOperator.NotEqual == binaryOperator) {
- Object targetVal = ElasticSqlArgTransferHelper.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 = ElasticSqlArgTransferHelper.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) {
- SQLInListExpr inListExpr = (SQLInListExpr) sqlExpr;
- if (CollectionUtils.isEmpty(inListExpr.getTargetList())) {
- throw new ElasticSql2DslException("[syntax error] In list expr target list cannot be blank");
- }
- Object[] targetInList = ElasticSqlArgTransferHelper.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 = ElasticSqlArgTransferHelper.transferSqlArg(betweenExpr.getBeginExpr(), dslContext.getSqlArgs());
- Object to = ElasticSqlArgTransferHelper.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 AtomFilter parseCondition(SQLExpr leftQueryFieldExpr, SQLConditionOperator operator, Object[] rightParamValues, String queryAs, ConditionFilterBuilder filterBuilder) {
- QueryFieldParser queryFieldParser = new QueryFieldParser();
- ElasticSqlQueryField queryField = queryFieldParser.parseConditionQueryField(leftQueryFieldExpr, queryAs);
- AtomFilter atomFilter = null;
- if (queryField.getQueryFieldType() == QueryFieldType.RootDocField || queryField.getQueryFieldType() == QueryFieldType.InnerDocField) {
- FilterBuilder originalFilter = filterBuilder.buildFilter(queryField.getQueryFieldFullName(), operator, rightParamValues);
- atomFilter = new AtomFilter(originalFilter);
- }
- if (queryField.getQueryFieldType() == QueryFieldType.NestedDocField) {
- FilterBuilder originalFilter = filterBuilder.buildFilter(queryField.getQueryFieldFullName(), operator, rightParamValues);
- atomFilter = new AtomFilter(originalFilter, queryField.getNestedDocContextPath());
- }
- if (atomFilter == null) {
- throw new ElasticSql2DslException(String.format("[syntax error] where condition field can not support type[%s]", queryField.getQueryFieldType()));
- }
- onAtomConditionParse(queryField, rightParamValues, operator);
- return atomFilter;
- }
- private void onAtomConditionParse(ElasticSqlQueryField 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);
- }
- public 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.Is
- || binaryOperator == SQLBinaryOperator.IsNot;
- }
- }
|