package jef.database.jsqlparser.visitor; import java.util.ArrayDeque; import java.util.Deque; import java.util.Iterator; import java.util.List; import jef.database.dialect.DatabaseDialect; import jef.database.jsqlparser.statement.select.Distinct; import jef.database.jsqlparser.statement.select.PlainSelect; import jef.database.jsqlparser.statement.select.SelectExpressionItem; import jef.database.jsqlparser.statement.select.Union; import jef.database.meta.Feature; /** * 将语句转换为COUNT语句 * * @author jiyi * */ public class ToCountDeParser extends DeParserAdapter { protected final Deque<Object> visitPath = new ArrayDeque<Object>(); private DatabaseDialect profile; public ToCountDeParser(DatabaseDialect profile) { this.profile = profile; } @Override public void visit(Union union) { if (!visitPath.isEmpty()) {// 仅对顶层的PlainSelect操作 super.visit(union); return; } visitPath.push(union); sb.append("select count(*) as t__cnt from ("); for (Iterator<PlainSelect> iter = union.getPlainSelects().iterator(); iter.hasNext();) { sb.append("("); PlainSelect plainSelect = iter.next(); plainSelect.accept(this); sb.append(")"); if (iter.hasNext()) { sb.append(" UNION "); } } // 去除原来语句中的order和limit // if (union.getOrderBy() != null) { // union.getOrderBy().accept(this); // } // if (union.getLimit() != null) { // deparseLimit(union.getLimit()); // } sb.append(')'); visitPath.pop(); } @Override public void visit(PlainSelect plainSelect) { if (!visitPath.isEmpty()) {// 仅对顶层的PlainSelect操作 super.visit(plainSelect); return; } visitPath.push(plainSelect); sb.append("select "); rewriteSelectItem(sb, plainSelect, profile); writeFromAndWhere(plainSelect); writeGroupByAndHaving(plainSelect); // writeOrderAndLimit(plainSelect); visitPath.pop(); } public static void rewriteSelectItem(StringBuilder sb, PlainSelect plainSelect, DatabaseDialect profile) { sb.append("count("); Distinct dis = plainSelect.getDistinct(); if (dis == null) { sb.append('*'); } else { rewriteDistinctCount(sb, dis, plainSelect.getSelectItems(), profile); } sb.append(")"); } /* * 从"count("后面的部分开始写起 */ private static void rewriteDistinctCount(StringBuilder sb, Distinct dis, List<SelectItem> items, DatabaseDialect profile) { sb.append(dis.toString()).append(' '); String concatStart = "concat("; String concat = ","; String concatEnd = ")"; if (profile.has(Feature.SUPPORT_CONCAT)) { concatStart = ""; concat = "||"; concatEnd = ""; } else if (profile.has(Feature.CONCAT_IS_ADD)) { concatStart = ""; concat = "+"; concatEnd = ""; } int n = 0; if (items.size() > 1) { sb.append(concatStart); } for (SelectItem v : items) { if (n > 0) sb.append(concat); if (v.isAllColumns()) { sb.append(v.toString()); } else { SelectExpressionItem item = v.getAsSelectExpression(); item.getExpression().appendTo(sb); } n++; } if (items.size() > 1) { sb.append(concatEnd); } } }