SQLQuery.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. package com.primeton.dsp.datarelease.api.sql;
  2. import com.alibaba.druid.sql.SQLUtils;
  3. import com.google.common.base.Preconditions;
  4. import com.primeton.dsp.datarelease.api.model.Field;
  5. import com.primeton.dsp.datarelease.api.model.Table;
  6. import com.primeton.dsp.datarelease.api.model.WhereCause;
  7. import net.sf.jsqlparser.expression.Alias;
  8. import net.sf.jsqlparser.expression.BinaryExpression;
  9. import net.sf.jsqlparser.expression.DateValue;
  10. import net.sf.jsqlparser.expression.DoubleValue;
  11. import net.sf.jsqlparser.expression.Expression;
  12. import net.sf.jsqlparser.expression.LongValue;
  13. import net.sf.jsqlparser.expression.StringValue;
  14. import net.sf.jsqlparser.expression.TimestampValue;
  15. import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
  16. import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
  17. import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
  18. import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
  19. import net.sf.jsqlparser.expression.operators.relational.GreaterThan;
  20. import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
  21. import net.sf.jsqlparser.expression.operators.relational.InExpression;
  22. import net.sf.jsqlparser.expression.operators.relational.LikeExpression;
  23. import net.sf.jsqlparser.expression.operators.relational.MinorThan;
  24. import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
  25. import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList;
  26. import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
  27. import net.sf.jsqlparser.schema.Column;
  28. import net.sf.jsqlparser.statement.select.PlainSelect;
  29. import net.sf.jsqlparser.statement.select.Select;
  30. import net.sf.jsqlparser.statement.select.SelectExpressionItem;
  31. import net.sf.jsqlparser.statement.select.SelectItem;
  32. import net.sf.jsqlparser.util.SelectUtils;
  33. import org.apache.commons.lang.StringUtils;
  34. import java.util.ArrayList;
  35. import java.util.Collection;
  36. import java.util.List;
  37. /**
  38. *
  39. * 单表服务发布,SQL 生成预览
  40. *
  41. * <pre>
  42. *
  43. * Created by zhaopx.
  44. * User: zhaopx
  45. * Date: 2020/3/25
  46. * Time: 17:50
  47. *
  48. * </pre>
  49. *
  50. * @author zhaopx
  51. */
  52. public abstract class SQLQuery {
  53. /**
  54. * 输出 SQL
  55. *
  56. * @return 返回 sql str
  57. */
  58. public abstract String show(boolean format);
  59. public static class Builder {
  60. /**
  61. * 核心 Select
  62. */
  63. Select select;
  64. public Builder(Table table) {
  65. net.sf.jsqlparser.schema.Table t = new net.sf.jsqlparser.schema.Table(table.getTableName());
  66. t.setAlias(new Alias(table.getAlias(), false));
  67. Select select = null;
  68. // select x from t
  69. if(table.getFields().isEmpty()) {
  70. select = SelectUtils.buildSelectFromTable(t);
  71. } else {
  72. List<Field> fields = table.getFields();
  73. SelectItem[] items = new SelectItem[fields.size()];
  74. int i = 0;
  75. for (Field field : fields) {
  76. SelectExpressionItem item = new SelectExpressionItem(new Column(t, field.getFieldName()));
  77. item.setAlias(new Alias(field.getAlias(), true));
  78. items[i] = item;
  79. i++;
  80. }
  81. select = SelectUtils.buildSelectFromTableAndSelectItems(t, items);
  82. }
  83. this.select = select;
  84. }
  85. public Builder(Table table, WhereCause... conds) {
  86. this(table);
  87. // 处理条件
  88. where(conds);
  89. }
  90. /**
  91. * 设置 where 调用条件。调用 where 后就不应该再调用 join 了
  92. * @return
  93. */
  94. public Builder where(WhereCause... wheres) {
  95. if(wheres == null || wheres.length == 0) {
  96. // 没有可加的条件
  97. return this;
  98. }
  99. PlainSelect ps = (PlainSelect)select.getSelectBody();
  100. Expression where = ps.getWhere();
  101. net.sf.jsqlparser.schema.Table table = (net.sf.jsqlparser.schema.Table)ps.getFromItem();
  102. if(where == null && wheres.length == 1) {
  103. // 一个条件,就这样了。
  104. Expression expr = buildExpression(table, wheres[0]);
  105. ps.setWhere(expr);
  106. } else if(where == null){
  107. // where is null,wheres 第一个不加 and,后续都加 and。
  108. Expression firstExpr = buildExpression(table, wheres[0]);
  109. WhereCause[] whereCauses1toEnd = new WhereCause[wheres.length - 1];
  110. System.arraycopy(wheres, 1, whereCauses1toEnd, 0, whereCauses1toEnd.length);
  111. ps.setWhere(buildWhereCause(table, firstExpr, whereCauses1toEnd));
  112. } else {
  113. // where is not null,第一个条件就需要加 and
  114. ps.setWhere(buildWhereCause(table, where, wheres));
  115. }
  116. return this;
  117. }
  118. /**
  119. * 创建循环的 where 条件
  120. * @param wheres 一个或者多个 where
  121. * @return
  122. */
  123. private Expression buildWhereCause(net.sf.jsqlparser.schema.Table table, Expression last, WhereCause... wheres) {
  124. if(wheres.length == 1) {
  125. Expression expression = buildExpression(table, wheres[0]);
  126. BinaryExpression expr = null;
  127. if("or".equalsIgnoreCase(wheres[0].getCond())){
  128. expr = new OrExpression(last, expression);
  129. } else {
  130. expr = new AndExpression(last, expression);
  131. }
  132. return expr;
  133. }
  134. Expression addExpr = buildExpression(table, wheres[0]);
  135. BinaryExpression expr = null;
  136. if("or".equalsIgnoreCase(wheres[0].getCond())){
  137. expr = new OrExpression(last, addExpr);
  138. } else {
  139. expr = new AndExpression(last, addExpr);
  140. }
  141. WhereCause[] whereCauses1toEnd = new WhereCause[wheres.length - 1];
  142. System.arraycopy(wheres, 1, whereCauses1toEnd, 0, whereCauses1toEnd.length);
  143. // 递归处理每一个表达式
  144. return buildWhereCause(table, expr, whereCauses1toEnd);
  145. }
  146. /**
  147. * 根据 where 条件,把前台选择的条件转为 sql 支持的结构。
  148. * @param table 表名称
  149. * @param cause 条件
  150. * @return
  151. */
  152. private Expression buildExpression(net.sf.jsqlparser.schema.Table table, WhereCause cause) {
  153. String[] mutilValue = cause.getValue() != null ? cause.getValue().split(",") : new String[]{};
  154. if (mutilValue.length > 1) {
  155. // 多值的情况 select * from table where id in('a', 'b')
  156. // 多值的必须是 in 或者 notin 的情况,如果不是,强制改变语句为 in 的条件
  157. String opera = cause.getOpera();
  158. if(!"in".equalsIgnoreCase(opera) && !"notin".equalsIgnoreCase(opera)) {
  159. cause.setOpera("in");
  160. }
  161. // 多个值的情况
  162. return buildSingleValue(table, cause);
  163. }
  164. // 单值的条件
  165. return buildSingleValue(table, cause);
  166. }
  167. /**
  168. * 编译单值的条件
  169. * @param table
  170. * @param cause
  171. * @return
  172. */
  173. private Expression buildSingleValue(net.sf.jsqlparser.schema.Table table, WhereCause cause) {
  174. Expression valueExpr = null;
  175. if(StringUtils.isNotBlank(cause.getToFieldName())) {
  176. // 第二个表名称和表字段名都不为 null,则表达式的值为第二个表中的字段
  177. // a.AGE > a.AGE2
  178. valueExpr = new Column(table, cause.getToFieldName());
  179. } else if("INT".equalsIgnoreCase(cause.getType())) {
  180. // 表达式为常量,但是值为数值类型,SQL 中数值不加引号
  181. valueExpr = new LongValue(cause.getValue());
  182. } else if("DOUBLE".equalsIgnoreCase(cause.getType())) {
  183. // 表达式为常量,但是值为浮点类型,SQL 中数值不加引号
  184. valueExpr = new DoubleValue(cause.getValue());
  185. } else if("DATE".equalsIgnoreCase(cause.getType())) {
  186. // 表达式为常量,但是值为日期类型,SQL 中数值不加引号
  187. // 日期类型为:yyyy-[M]M-[d]d
  188. valueExpr = new DateValue(cause.getValue());
  189. } else if("DATETIME".equalsIgnoreCase(cause.getType())) {
  190. // 表达式为常量,但是值为日期类型,SQL 中数值不加引号
  191. // 日期类型为:yyyy-[M]M-[d]d HH:mm:ss
  192. valueExpr = new TimestampValue(cause.getValue());
  193. } else {
  194. // 表达式值为常量,字符串, NAME = 'X'
  195. valueExpr = new StringValue(cause.getValue());
  196. }
  197. if("=".equals(cause.getOpera())) {
  198. EqualsTo equals = new EqualsTo();
  199. equals.setLeftExpression(new Column(table, cause.getFieldName()));
  200. equals.setRightExpression(valueExpr);
  201. return equals;
  202. } else if(">".equals(cause.getOpera())) {
  203. GreaterThan greaterThan = new GreaterThan();
  204. greaterThan.setLeftExpression(new Column(table, cause.getFieldName()));
  205. greaterThan.setRightExpression(valueExpr);
  206. return greaterThan;
  207. } else if(">=".equals(cause.getOpera())) {
  208. GreaterThanEquals greaterThanEquals = new GreaterThanEquals();
  209. greaterThanEquals.setLeftExpression(new Column(table, cause.getFieldName()));
  210. greaterThanEquals.setRightExpression(valueExpr);
  211. return greaterThanEquals;
  212. } else if("<".equals(cause.getOpera())) {
  213. MinorThan minorThan = new MinorThan();
  214. minorThan.setLeftExpression(new Column(table, cause.getFieldName()));
  215. minorThan.setRightExpression(valueExpr);
  216. return minorThan;
  217. } else if("<=".equals(cause.getOpera())) {
  218. MinorThanEquals minorThanEquals = new MinorThanEquals();
  219. minorThanEquals.setLeftExpression(new Column(table, cause.getFieldName()));
  220. minorThanEquals.setRightExpression(valueExpr);
  221. return minorThanEquals;
  222. } else if("<>".equals(cause.getOpera()) || "!=".equals(cause.getOpera())) {
  223. NotEqualsTo notEqualsTo = new NotEqualsTo();
  224. notEqualsTo.setLeftExpression(new Column(table, cause.getFieldName()));
  225. notEqualsTo.setRightExpression(valueExpr);
  226. return notEqualsTo;
  227. } else if("in".equalsIgnoreCase(cause.getOpera())) {
  228. String[] mutilValue = cause.getValue().split(",");
  229. InExpression inExpression = new InExpression();
  230. inExpression.setLeftExpression(new Column(table, cause.getFieldName()));
  231. MultiExpressionList list = new MultiExpressionList();
  232. List<Expression> inVals = new ArrayList<>();
  233. for (String val : mutilValue) {
  234. inVals.add(new StringValue(val));
  235. }
  236. list.addExpressionList(new ExpressionList(inVals));
  237. inExpression.setRightItemsList(list);
  238. return inExpression;
  239. } else if("notin".equalsIgnoreCase(cause.getOpera())) {
  240. String[] mutilValue = cause.getValue().split(",");
  241. InExpression inExpression = new InExpression();
  242. inExpression.setLeftExpression(new Column(table, cause.getFieldName()));
  243. // not 否定条件
  244. inExpression.setNot(true);
  245. MultiExpressionList list = new MultiExpressionList();
  246. List<Expression> inVals = new ArrayList<>();
  247. for (String val : mutilValue) {
  248. inVals.add(new StringValue(val));
  249. }
  250. list.addExpressionList(new ExpressionList(inVals));
  251. inExpression.setRightItemsList(list);
  252. return inExpression;
  253. } else if("l".equalsIgnoreCase(cause.getOpera())) {
  254. Preconditions.checkNotNull(cause.getValue(), " like value must not be blank");
  255. // 如果自带 %,则说明需要匹配值的 %,用转义
  256. String likeValue = cause.getValue().replaceAll("%", "\\%");
  257. valueExpr = new StringValue("%"+likeValue+"%");
  258. LikeExpression likeExpression = new LikeExpression();
  259. likeExpression.setLeftExpression(new Column(table, cause.getFieldName()));
  260. likeExpression.setRightExpression(valueExpr);
  261. return likeExpression;
  262. }
  263. EqualsTo equals = new EqualsTo();
  264. equals.setLeftExpression(new Column(table, cause.getFieldName()));
  265. equals.setRightExpression(valueExpr);
  266. return equals;
  267. }
  268. /**
  269. * 设置 where 调用条件。调用 where 后就不应该再调用 join 了
  270. * @return
  271. */
  272. public Builder where(Collection<WhereCause> wheres) {
  273. where(wheres.toArray(new WhereCause[wheres.size()]));
  274. return this;
  275. }
  276. /**
  277. * 创建 SQL
  278. *
  279. * @return
  280. */
  281. public SQLQuery build() {
  282. return new SQLQuery() {
  283. @Override
  284. public String show(boolean format) {
  285. if(!format) {
  286. return select.toString();
  287. }
  288. String sql = select.toString();
  289. // 美化一下 SQL
  290. sql = SQLUtils.formatMySql(sql);
  291. return sql;
  292. }
  293. };
  294. }
  295. }
  296. public static void main(String[] args) {
  297. StringValue valueExpr = new StringValue("%王%");
  298. LikeExpression likeExpression = new LikeExpression();
  299. likeExpression.setLeftExpression(new Column("NAME"));
  300. likeExpression.setRightExpression(valueExpr);
  301. System.out.println(likeExpression.toString());
  302. }
  303. }