QueryWhereConditionParser.java 13 KB

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