QueryWhereConditionParser.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. package org.elasticsearch.dsl.parser;
  2. import com.alibaba.druid.sql.ast.SQLExpr;
  3. import com.alibaba.druid.sql.ast.expr.*;
  4. import com.google.common.collect.Lists;
  5. import org.apache.commons.collections.CollectionUtils;
  6. import org.elasticsearch.dsl.ElasticDslContext;
  7. import org.elasticsearch.dsl.ElasticSqlParseUtil;
  8. import org.elasticsearch.dsl.exception.ElasticSql2DslException;
  9. import org.elasticsearch.dsl.parser.helper.ElasticSqlIdentifierHelper;
  10. import org.elasticsearch.index.query.BoolFilterBuilder;
  11. import org.elasticsearch.index.query.FilterBuilder;
  12. import org.elasticsearch.index.query.FilterBuilders;
  13. import org.elasticsearch.sql.ElasticSqlSelectQueryBlock;
  14. import java.util.List;
  15. import java.util.function.Consumer;
  16. public class QueryWhereConditionParser implements QueryParser {
  17. @Override
  18. public void parse(ElasticDslContext dslContext) {
  19. ElasticSqlSelectQueryBlock queryBlock = (ElasticSqlSelectQueryBlock) dslContext.getQueryExpr().getSubQuery().getQuery();
  20. BoolFilterBuilder whereCondition = FilterBuilders.boolFilter();
  21. if (queryBlock.getWhere() != null) {
  22. SqlCondition sqlCondition = parseFilterCondition(dslContext, queryBlock.getWhere());
  23. if (!sqlCondition.isAndOr()) {
  24. whereCondition.must(sqlCondition.getFilterList().get(0));
  25. } else {
  26. for (FilterBuilder filter : sqlCondition.getFilterList()) {
  27. if (sqlCondition.getOperator() == SQLBinaryOperator.BooleanAnd) {
  28. whereCondition.must(filter);
  29. }
  30. if (sqlCondition.getOperator() == SQLBinaryOperator.BooleanOr) {
  31. whereCondition.should(filter);
  32. }
  33. }
  34. }
  35. }
  36. dslContext.getParseResult().setWhereCondition(whereCondition);
  37. }
  38. private SqlCondition parseFilterCondition(ElasticDslContext dslContext, SQLExpr sqlExpr) {
  39. if (sqlExpr instanceof SQLBinaryOpExpr) {
  40. SQLBinaryOpExpr sqlBinOpExpr = (SQLBinaryOpExpr) sqlExpr;
  41. SQLBinaryOperator binaryOperator = sqlBinOpExpr.getOperator();
  42. if (SQLBinaryOperator.BooleanAnd == binaryOperator || SQLBinaryOperator.BooleanOr == binaryOperator) {
  43. final SqlCondition leftCondition = parseFilterCondition(dslContext, sqlBinOpExpr.getLeft());
  44. final SqlCondition rightCondition = parseFilterCondition(dslContext, sqlBinOpExpr.getRight());
  45. List<FilterBuilder> curFilterList = Lists.newArrayList();
  46. if (!leftCondition.isAndOr() || leftCondition.operator == binaryOperator) {
  47. curFilterList.addAll(leftCondition.getFilterList());
  48. } else {
  49. final BoolFilterBuilder subBoolFilter = FilterBuilders.boolFilter();
  50. leftCondition.getFilterList().stream().forEach(new Consumer<FilterBuilder>() {
  51. @Override
  52. public void accept(FilterBuilder filter) {
  53. if (leftCondition.getOperator() == SQLBinaryOperator.BooleanAnd) {
  54. subBoolFilter.must(filter);
  55. }
  56. if (leftCondition.getOperator() == SQLBinaryOperator.BooleanOr) {
  57. subBoolFilter.should(filter);
  58. }
  59. }
  60. });
  61. curFilterList.add(subBoolFilter);
  62. }
  63. if (!rightCondition.isAndOr() || rightCondition.operator == binaryOperator) {
  64. curFilterList.addAll(rightCondition.getFilterList());
  65. } else {
  66. final BoolFilterBuilder subBoolFilter = FilterBuilders.boolFilter();
  67. rightCondition.getFilterList().stream().forEach(new Consumer<FilterBuilder>() {
  68. @Override
  69. public void accept(FilterBuilder filter) {
  70. if (rightCondition.getOperator() == SQLBinaryOperator.BooleanAnd) {
  71. subBoolFilter.must(filter);
  72. }
  73. if (rightCondition.getOperator() == SQLBinaryOperator.BooleanOr) {
  74. subBoolFilter.should(filter);
  75. }
  76. }
  77. });
  78. curFilterList.add(subBoolFilter);
  79. }
  80. return new SqlCondition(curFilterList, binaryOperator);
  81. }
  82. }
  83. return new SqlCondition(parseAtomFilterCondition(dslContext, sqlExpr));
  84. }
  85. private FilterBuilder parseAtomFilterCondition(ElasticDslContext dslContext, SQLExpr sqlExpr) {
  86. if (sqlExpr instanceof SQLBinaryOpExpr) {
  87. SQLBinaryOpExpr sqlBinOpExpr = (SQLBinaryOpExpr) sqlExpr;
  88. final SQLBinaryOperator binaryOperator = sqlBinOpExpr.getOperator();
  89. if (ElasticSqlParseUtil.isValidBinOperator(binaryOperator)) {
  90. //EQ NEQ
  91. if (SQLBinaryOperator.Equality == binaryOperator || SQLBinaryOperator.LessThanOrGreater == binaryOperator || SQLBinaryOperator.NotEqual == binaryOperator) {
  92. final Object targetVal = ElasticSqlParseUtil.transferSqlArg(sqlBinOpExpr.getRight(), dslContext.getSqlArgs());
  93. return parseCondition(sqlBinOpExpr.getLeft(), dslContext.getParseResult().getQueryAs(), new ConditionFilterBuilder() {
  94. @Override
  95. public FilterBuilder buildFilter(String idfName) {
  96. FilterBuilder eqFilter = FilterBuilders.termFilter(idfName, targetVal);
  97. if (SQLBinaryOperator.Equality == binaryOperator) {
  98. return eqFilter;
  99. } else {
  100. return FilterBuilders.notFilter(eqFilter);
  101. }
  102. }
  103. });
  104. }
  105. //GT GTE LT LTE
  106. if (SQLBinaryOperator.GreaterThan == binaryOperator || SQLBinaryOperator.GreaterThanOrEqual == binaryOperator
  107. || SQLBinaryOperator.LessThan == binaryOperator || SQLBinaryOperator.LessThanOrEqual == binaryOperator) {
  108. final Object targetVal = ElasticSqlParseUtil.transferSqlArg(sqlBinOpExpr.getRight(), dslContext.getSqlArgs());
  109. return parseCondition(sqlBinOpExpr.getLeft(), dslContext.getParseResult().getQueryAs(), new ConditionFilterBuilder() {
  110. @Override
  111. public FilterBuilder buildFilter(String idfName) {
  112. FilterBuilder rangeFilter = null;
  113. if (SQLBinaryOperator.GreaterThan == binaryOperator) {
  114. rangeFilter = FilterBuilders.rangeFilter(idfName).gt(targetVal);
  115. } else if (SQLBinaryOperator.GreaterThanOrEqual == binaryOperator) {
  116. rangeFilter = FilterBuilders.rangeFilter(idfName).gte(targetVal);
  117. } else if (SQLBinaryOperator.LessThan == binaryOperator) {
  118. rangeFilter = FilterBuilders.rangeFilter(idfName).lt(targetVal);
  119. } else if (SQLBinaryOperator.LessThanOrEqual == binaryOperator) {
  120. rangeFilter = FilterBuilders.rangeFilter(idfName).lte(targetVal);
  121. }
  122. return rangeFilter;
  123. }
  124. });
  125. }
  126. //IS / IS NOT
  127. if (SQLBinaryOperator.Is == binaryOperator || SQLBinaryOperator.IsNot == binaryOperator) {
  128. if (!(sqlBinOpExpr.getRight() instanceof SQLNullExpr)) {
  129. throw new ElasticSql2DslException("[syntax error] Is/IsNot expr right part should be null");
  130. }
  131. return parseCondition(sqlBinOpExpr.getLeft(), dslContext.getParseResult().getQueryAs(), new ConditionFilterBuilder() {
  132. @Override
  133. public FilterBuilder buildFilter(String idfName) {
  134. FilterBuilder missingFilter = FilterBuilders.missingFilter(idfName);
  135. if (SQLBinaryOperator.IsNot == binaryOperator) {
  136. return FilterBuilders.notFilter(missingFilter);
  137. }
  138. return missingFilter;
  139. }
  140. });
  141. }
  142. }
  143. } else if (sqlExpr instanceof SQLInListExpr) {
  144. final SQLInListExpr inListExpr = (SQLInListExpr) sqlExpr;
  145. if (CollectionUtils.isEmpty(inListExpr.getTargetList())) {
  146. throw new ElasticSql2DslException("[syntax error] In list expr target list cannot be blank");
  147. }
  148. final Object[] targetInList = ElasticSqlParseUtil.transferSqlArgs(inListExpr.getTargetList(), dslContext.getSqlArgs());
  149. return parseCondition(inListExpr.getExpr(), dslContext.getParseResult().getQueryAs(), new ConditionFilterBuilder() {
  150. @Override
  151. public FilterBuilder buildFilter(String idfName) {
  152. if (inListExpr.isNot()) {
  153. return FilterBuilders.notFilter(FilterBuilders.inFilter(idfName, targetInList));
  154. } else {
  155. return FilterBuilders.inFilter(idfName, targetInList);
  156. }
  157. }
  158. });
  159. } else if (sqlExpr instanceof SQLBetweenExpr) {
  160. SQLBetweenExpr betweenExpr = (SQLBetweenExpr) sqlExpr;
  161. final Object from = ElasticSqlParseUtil.transferSqlArg(betweenExpr.getBeginExpr(), dslContext.getSqlArgs());
  162. final Object to = ElasticSqlParseUtil.transferSqlArg(betweenExpr.getEndExpr(), dslContext.getSqlArgs());
  163. if (from == null || to == null) {
  164. throw new ElasticSql2DslException("[syntax error] Between Expr only support one of [number,date] arg type");
  165. }
  166. return parseCondition(betweenExpr.getTestExpr(), dslContext.getParseResult().getQueryAs(), new ConditionFilterBuilder() {
  167. @Override
  168. public FilterBuilder buildFilter(String idfName) {
  169. return FilterBuilders.rangeFilter(idfName).gte(from).lte(to);
  170. }
  171. });
  172. }
  173. throw new ElasticSql2DslException("[syntax error] Can not support syntax type: " + sqlExpr.toString());
  174. }
  175. private FilterBuilder parseCondition(SQLExpr sqlExpr, String queryAs, final ConditionFilterBuilder filterBuilder) {
  176. final List<FilterBuilder> tmpFilterList = Lists.newLinkedList();
  177. ElasticSqlIdentifierHelper.parseSqlIdentifier(sqlExpr, queryAs, new ElasticSqlIdentifierHelper.ElasticSqlSinglePropertyFunc() {
  178. @Override
  179. public void parse(String propertyName) {
  180. FilterBuilder originalFilter = filterBuilder.buildFilter(propertyName);
  181. tmpFilterList.add(originalFilter);
  182. }
  183. }, new ElasticSqlIdentifierHelper.ElasticSqlPathPropertyFunc() {
  184. @Override
  185. public void parse(String propertyPath, String propertyName) {
  186. FilterBuilder originalFilter = filterBuilder.buildFilter(propertyName);
  187. FilterBuilder nestFilter = FilterBuilders.nestedFilter(propertyPath, originalFilter);
  188. tmpFilterList.add(nestFilter);
  189. }
  190. });
  191. if (CollectionUtils.isNotEmpty(tmpFilterList)) {
  192. return tmpFilterList.get(0);
  193. }
  194. return null;
  195. }
  196. private abstract class ConditionFilterBuilder {
  197. public abstract FilterBuilder buildFilter(String idfName);
  198. }
  199. private class SqlCondition {
  200. //是否AND/OR运算
  201. private boolean isAndOr = false;
  202. //运算符
  203. private SQLBinaryOperator operator;
  204. //条件集合
  205. private List<FilterBuilder> filterList;
  206. public SqlCondition(FilterBuilder atomFilter) {
  207. filterList = Lists.newArrayList(atomFilter);
  208. isAndOr = false;
  209. }
  210. public SqlCondition(List<FilterBuilder> filterList, SQLBinaryOperator operator) {
  211. this.filterList = filterList;
  212. isAndOr = true;
  213. this.operator = operator;
  214. }
  215. public boolean isAndOr() {
  216. return isAndOr;
  217. }
  218. public SQLBinaryOperator getOperator() {
  219. return operator;
  220. }
  221. public List<FilterBuilder> getFilterList() {
  222. return filterList;
  223. }
  224. }
  225. }