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