package jef.database.dialect.handler; import java.util.Arrays; import javax.persistence.PersistenceException; import jef.database.DbUtils; import jef.database.jsqlparser.expression.Function; import jef.database.jsqlparser.parser.ParseException; import jef.database.jsqlparser.statement.select.OrderBy; import jef.database.jsqlparser.statement.select.OrderByElement; import jef.database.jsqlparser.statement.select.PlainSelect; import jef.database.jsqlparser.statement.select.Select; import jef.database.jsqlparser.statement.select.SelectExpressionItem; import jef.database.jsqlparser.statement.select.Union; import jef.database.query.SqlExpression; import jef.database.wrapper.clause.BindSql; public class SQL2005LimitHandlerSlowImpl extends SQL2000LimitHandlerSlowImpl { private OrderBy defaultOrder; public SQL2005LimitHandlerSlowImpl() { super(); defaultOrder = new OrderBy(); OrderByElement oe = new OrderByElement(); oe.setExpression(new Function("CURRENT_TIMESTAMP")); defaultOrder.setOrderByElements(Arrays.asList(oe)); } 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); } else { order = defaultOrder; } }else{ union.setOrderBy(null); } // order可以直接移出 StringBuilder sb = new StringBuilder(); sb.append("select _tmp.* from ( \nselect row_number() over ("); order.appendTo(sb); sb.append(") as __rn, _tmp1.* from ("); union.appendTo(sb); sb.append(") _tmp1) _tmp2 where __rn between "); sb.append(offsetLimit[0] + 1).append(" and ").append(offsetLimit[0] + offsetLimit[1]); return new BindSql(sb.toString()); } private BindSql toPage(int[] offsetLimit, PlainSelect selectBody, String raw) { OrderBy order = selectBody.getOrderBy(); if (order == null) { order = defaultOrder; } else { selectBody.setOrderBy(null); } StringBuilder sb1 = new StringBuilder("row_number() over ("); order.appendTo(sb1); sb1.append(")"); selectBody.getSelectItems().add(0, new SelectExpressionItem(new SqlExpression(sb1.toString()), "__rn")); StringBuilder sb = new StringBuilder("select _tmp1.* from ("); selectBody.appendTo(sb); sb.append(") _tmp1 where __rn between "); sb.append(offsetLimit[0] + 1).append(" and ").append(offsetLimit[0] + offsetLimit[1]); return new BindSql(sb.toString()); } }