001package com.avaje.ebean.config.dbplatform;
002
003/**
004 * Use top and row_number() function to limit sql results.
005 */
006public class MsSqlServer2005SqlLimiter implements SqlLimiter {
007
008  final String rowNumberWindowAlias;
009
010  /**
011   * Specify the name of the rowNumberWindowAlias.
012   */
013  public MsSqlServer2005SqlLimiter(String rowNumberWindowAlias) {
014    this.rowNumberWindowAlias = rowNumberWindowAlias;
015  }
016
017  public MsSqlServer2005SqlLimiter() {
018    this("as limitresult");
019  }
020
021  public SqlLimitResponse limit(SqlLimitRequest request) {
022
023    StringBuilder sb = new StringBuilder(500);
024
025    int firstRow = request.getFirstRow();
026
027    int lastRow = request.getMaxRows();
028    if (lastRow > 0) {
029      lastRow = lastRow + firstRow;
030    }
031
032    if (firstRow < 1) {
033      // just use top n
034      sb.append(" select ");
035      if (request.isDistinct()) {
036        sb.append("distinct ");
037      }
038      sb.append(" top ").append(lastRow).append(" ");
039      sb.append(request.getDbSql());
040      return new SqlLimitResponse(sb.toString(), false);
041    }
042
043    /*
044     * SELECT * FROM (SELECT TOP 20 ROW_NUMBER() OVER (ORDER BY ...) AS rn, ...)
045     * AS limitresult WHERE rn >= 11 AND rn <= 20
046     */
047
048    sb.append("select * ").append(NEW_LINE).append("from ( ");
049
050    sb.append("select ");
051    if (request.isDistinct()) {
052      sb.append("distinct ");
053    }
054    sb.append("top ").append(lastRow);
055    sb.append(" row_number() over (order by ");
056    sb.append(request.getDbOrderBy());
057    sb.append(") as rn, ");
058    sb.append(request.getDbSql());
059
060    sb.append(NEW_LINE).append(") ");
061    sb.append(rowNumberWindowAlias);
062    sb.append(" where ");
063    if (firstRow > 0) {
064      sb.append(" rn > ").append(firstRow);
065      if (lastRow > 0) {
066        sb.append(" and ");
067      }
068    }
069    if (lastRow > 0) {
070      sb.append(" rn <= ").append(lastRow);
071    }
072
073    String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
074
075    return new SqlLimitResponse(sql, true);
076  }
077
078}