001package io.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  @Override
032  public SqlLimitResponse limit(SqlLimitRequest request) {
033
034    String dbSql = request.getDbSql();
035
036    StringBuilder sb = new StringBuilder(60 + dbSql.length());
037
038    int firstRow = request.getFirstRow();
039
040    int lastRow = request.getMaxRows();
041    if (lastRow > 0) {
042      lastRow += firstRow;
043    }
044
045    sb.append("select * from ( ");
046
047    sb.append("select ");
048    if (request.isDistinct()) {
049      sb.append("distinct ");
050    }
051
052    sb.append(ROW_NUMBER_OVER);
053    sb.append(request.getDbOrderBy());
054    sb.append(ROW_NUMBER_AS);
055
056    sb.append(dbSql);
057
058    sb.append(" ) ");
059    sb.append(rowNumberWindowAlias);
060    sb.append(" where ");
061    if (firstRow > 0) {
062      sb.append(" rn > ").append(firstRow);
063      if (lastRow > 0) {
064        sb.append(" and ");
065      }
066    }
067    if (lastRow > 0) {
068      sb.append(" rn <= ").append(lastRow);
069    }
070
071    String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
072
073    return new SqlLimitResponse(sql, true);
074  }
075}