QueryWhereConditionParser.java 15 KB

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