package jef.database.dialect.handler; import javax.persistence.PersistenceException; import jef.database.DbUtils; import jef.database.jdbc.statement.ResultSetLaterProcess; import jef.database.jsqlparser.parser.ParseException; import jef.database.jsqlparser.statement.select.OrderBy; import jef.database.jsqlparser.statement.select.PlainSelect; import jef.database.jsqlparser.statement.select.Select; import jef.database.jsqlparser.statement.select.SubSelect; import jef.database.jsqlparser.statement.select.Top; import jef.database.jsqlparser.statement.select.Union; import jef.database.wrapper.clause.BindSql; import org.apache.commons.lang.StringUtils; public class SQL2000LimitHandlerSlowImpl implements LimitHandler { public BindSql toPageSQL(String sql, int[] offsetLimit) { int offset=offsetLimit[0]; if(offset==0){//没有offset可以简化处理 int indexDistinct=StringUtils.indexOfIgnoreCase(sql, "select distinct"); int index=StringUtils.indexOfIgnoreCase(sql, "select"); return new BindSql(new StringBuilder( sql.length() + 8 ) .append(sql).insert(index + (indexDistinct == index ? 15 : 6), " top " + offsetLimit[1] ).toString()); } return processToPageSQL(sql,offsetLimit); } protected BindSql processToPageSQL(String sql, int[] offsetLimit) { try { Select select = DbUtils.parseNativeSelect(sql); if(select.getSelectBody() instanceof PlainSelect){ return toPage(offsetLimit,(PlainSelect)select.getSelectBody(),sql); }else{ return toPage(offsetLimit,(Union)select.getSelectBody(),sql); } } catch (ParseException e) { throw new PersistenceException(e); } } private BindSql toPage(int[] offsetLimit, Union union,String raw) { OrderBy order=union.getOrderBy(); if(order==null){ order=union.getLastPlainSelect().getOrderBy(); if(order!=null){ //解析器问题,会把属于整个union的排序条件当做是属于最后一个查询的 union.getLastPlainSelect().setOrderBy(null); union.setOrderBy(order); }else{ throw new UnsupportedOperationException("Select must have order to page"); } } StringBuilder sb=new StringBuilder(raw.length()+40); sb.append("select top "); sb.append(offsetLimit[0]+offsetLimit[1]).append(" * from"); SubSelect s=new SubSelect(); union.setOrderBy(null); s.setSelectBody(union); s.setAlias("__ef_tmp1"); s.appendTo(sb); sb.append('\n'); order.appendTo(sb); // sb.append(") __ef_tmp2\n"); // order.reverseAppendTo(sb,"__ef_tmp2",null); return new BindSql(sb.toString()).setReverseResult(new ResultSetLaterProcess(offsetLimit[0])); } private BindSql toPage(int[] offsetLimit, PlainSelect selectBody,String raw) { OrderBy order=selectBody.getOrderBy(); if(order==null){ throw new UnsupportedOperationException("Select must have order to page"); } selectBody.setTop(new Top(offsetLimit[0]+offsetLimit[1])); StringBuilder sb=new StringBuilder(raw.length()+30); // sb.append("select top ").append(offsetLimit[1]).append(" * from ("); selectBody.appendTo(sb); // sb.append(") __ef_t"); // order.reverseAppendTo(sb,"__ef_t",selectBody.getSelectItems()); return new BindSql(sb.toString()).setReverseResult(new ResultSetLaterProcess(offsetLimit[0])); } @Override public BindSql toPageSQL(String sql, int[] offsetLimit, boolean isUnion) { return toPageSQL(sql, offsetLimit); } }