package jef.database.dialect.handler;
import jef.database.wrapper.clause.BindSql;
import com.alibaba.druid.sql.ast.SQLOrderBy;
import com.alibaba.druid.sql.ast.SQLOver;
import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
import com.alibaba.druid.sql.ast.statement.SQLUnionQuery;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;
import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerOutputVisitor;
public class SQL2005LimitHandler extends SQL2000LimitHandler {
private SQLOrderBy defaultOrder;
public SQL2005LimitHandler() {
super();
defaultOrder = new SQLOrderBy();
SQLSelectOrderByItem oe = new SQLSelectOrderByItem();
oe.setExpr(new SQLIdentifierExpr("CURRENT_TIMESTAMP"));
defaultOrder.getItems().add(oe);
}
@Override
protected BindSql toPage(int[] offsetLimit, SQLServerSelectQueryBlock selectBody, SQLSelect select, String raw) {
SQLOrderBy order = select.getOrderBy();
if (order == null) {
order = defaultOrder;
} else {
select.setOrderBy(null);
}
SQLAggregateExpr arg=new SQLAggregateExpr("row_number");
SQLOver over=new SQLOver();
over.setOrderBy(order);
arg.setOver(over);
selectBody.getSelectList().add(0, new SQLSelectItem(arg, "__rn"));
StringBuilder sb = new StringBuilder("SELECT _tmp1.* FROM (");
SQLServerOutputVisitor visitor=new SQLServerOutputVisitor(sb);
visitor.setPrettyFormat(false);
select.accept(visitor);
sb.append(") _tmp1 WHERE __rn between ");
sb.append(offsetLimit[0] + 1).append(" and ").append(offsetLimit[0] + offsetLimit[1]);
return new BindSql(sb.toString());
}
@Override
protected BindSql toPage(int[] offsetLimit, SQLUnionQuery union, SQLSelect select, String raw) {
SQLOrderBy order = super.removeOrder(union);
if(order==null){
order = defaultOrder;
}
// order可以直接移出
StringBuilder sb = new StringBuilder();
SQLServerOutputVisitor visitor=new SQLServerOutputVisitor(sb);
visitor.setPrettyFormat(false);
sb.append("SELECT _tmp2.* FROM ( \nSELECT row_number() OVER (");
order.accept(visitor);
sb.append(") AS __rn, _tmp1.* FROM (");
union.accept(visitor);
sb.append(") _tmp1) _tmp2 WHERE __rn BETWEEN ");
sb.append(offsetLimit[0] + 1).append(" and ").append(offsetLimit[0] + offsetLimit[1]);
return new BindSql(sb.toString());
}
}