[#6197] Emulate LIMIT .. WITH TIES using RANK()

This commit is contained in:
lukaseder 2017-05-10 13:07:57 +02:00
parent a2ee0b82a1
commit 6831cb305d
4 changed files with 40 additions and 10 deletions

View File

@ -51,6 +51,7 @@ import static org.jooq.SQLDialect.MYSQL;
// ...
import static org.jooq.SQLDialect.POSTGRES;
import static org.jooq.SQLDialect.POSTGRES_9_5;
// ...
import static org.jooq.SQLDialect.SQLITE;
// ...
// ...
@ -641,10 +642,9 @@ public interface SelectQuery<R extends Record> extends Select<R>, ConditionProvi
void addLimit(Param<Integer> offset, Param<Integer> numberOfRows);
/**
* Specify the <code>TOP n WITH TIES</code> or
* <code>FETCH NEXT n WITH TIES</code> clause.
* Add the <code>WITH TIES</code> clause to a <code>LIMIT</code> clause.
*/
@Support({})
@Support({ CUBRID, FIREBIRD_3_0, POSTGRES })
void setWithTies(boolean withTies);
/**

View File

@ -34,6 +34,15 @@
*/
package org.jooq;
import static org.jooq.SQLDialect.CUBRID;
// ...
import static org.jooq.SQLDialect.FIREBIRD_3_0;
// ...
// ...
// ...
import static org.jooq.SQLDialect.POSTGRES;
// ...
// ...
// ...
// ...
@ -81,6 +90,9 @@ package org.jooq;
*/
public interface SelectWithTiesAfterOffsetStep<R extends Record> extends SelectForUpdateStep<R> {
@Support({})
/**
* Add the <code>WITH TIES</code> clause to a <code>LIMIT</code> clause.
*/
@Support({ CUBRID, FIREBIRD_3_0, POSTGRES })
SelectForUpdateStep<R> withTies();
}

View File

@ -34,6 +34,15 @@
*/
package org.jooq;
import static org.jooq.SQLDialect.CUBRID;
// ...
import static org.jooq.SQLDialect.FIREBIRD_3_0;
// ...
// ...
// ...
import static org.jooq.SQLDialect.POSTGRES;
// ...
// ...
// ...
// ...
@ -81,6 +90,9 @@ package org.jooq;
*/
public interface SelectWithTiesStep<R extends Record> extends SelectOffsetStep<R> {
@Support({})
/**
* Add the <code>WITH TIES</code> clause to a <code>LIMIT</code> clause.
*/
@Support({ CUBRID, FIREBIRD_3_0, POSTGRES })
SelectOffsetStep<R> withTies();
}

View File

@ -814,15 +814,21 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
if (wrapQueryExpressionBodyInDerivedTable)
c.qualify(false);
// [#2580] When DISTINCT is applied, we mustn't use ROW_NUMBER() OVER(),
// [#2580] FETCH NEXT n ROWS ONLY emulation:
// -----------------------------------------
// When DISTINCT is applied, we mustn't use ROW_NUMBER() OVER(),
// which changes the DISTINCT semantics. Instead, use DENSE_RANK() OVER(),
// ordering by the SELECT's ORDER BY clause AND all the expressions from
// the projection
// [#6197] TODO: What about the combination of DISTINCT and WITH TIES?
c.visit(distinct
? DSL.denseRank().over(orderBy(getNonEmptyOrderByForDistinct(c.configuration())))
: getLimit().withTies()
//
// [#6197] FETCH NEXT n ROWS WITH TIES emulation:
// ----------------------------------------------
// DISTINCT seems irrelevant here (to be proven)
c.visit(getLimit().withTies()
? DSL.rank().over(orderBy(getNonEmptyOrderBy(c.configuration())))
: distinct
? DSL.denseRank().over(orderBy(getNonEmptyOrderByForDistinct(c.configuration())))
: DSL.rowNumber().over(orderBy(getNonEmptyOrderBy(c.configuration())))
);