From 6831cb305dcbcb000f81f6d53922f43e50f39bd3 Mon Sep 17 00:00:00 2001 From: lukaseder Date: Wed, 10 May 2017 13:07:57 +0200 Subject: [PATCH] [#6197] Emulate LIMIT .. WITH TIES using RANK() --- jOOQ/src/main/java/org/jooq/SelectQuery.java | 6 +++--- .../org/jooq/SelectWithTiesAfterOffsetStep.java | 14 +++++++++++++- .../main/java/org/jooq/SelectWithTiesStep.java | 14 +++++++++++++- .../main/java/org/jooq/impl/SelectQueryImpl.java | 16 +++++++++++----- 4 files changed, 40 insertions(+), 10 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/SelectQuery.java b/jOOQ/src/main/java/org/jooq/SelectQuery.java index df4e90627f..8967410be1 100644 --- a/jOOQ/src/main/java/org/jooq/SelectQuery.java +++ b/jOOQ/src/main/java/org/jooq/SelectQuery.java @@ -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 extends Select, ConditionProvi void addLimit(Param offset, Param numberOfRows); /** - * Specify the TOP n WITH TIES or - * FETCH NEXT n WITH TIES clause. + * Add the WITH TIES clause to a LIMIT clause. */ - @Support({}) + @Support({ CUBRID, FIREBIRD_3_0, POSTGRES }) void setWithTies(boolean withTies); /** diff --git a/jOOQ/src/main/java/org/jooq/SelectWithTiesAfterOffsetStep.java b/jOOQ/src/main/java/org/jooq/SelectWithTiesAfterOffsetStep.java index 59398af659..7110f4dd2e 100644 --- a/jOOQ/src/main/java/org/jooq/SelectWithTiesAfterOffsetStep.java +++ b/jOOQ/src/main/java/org/jooq/SelectWithTiesAfterOffsetStep.java @@ -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 extends SelectForUpdateStep { - @Support({}) + /** + * Add the WITH TIES clause to a LIMIT clause. + */ + @Support({ CUBRID, FIREBIRD_3_0, POSTGRES }) SelectForUpdateStep withTies(); } diff --git a/jOOQ/src/main/java/org/jooq/SelectWithTiesStep.java b/jOOQ/src/main/java/org/jooq/SelectWithTiesStep.java index 46b4d569f5..fcecac8752 100644 --- a/jOOQ/src/main/java/org/jooq/SelectWithTiesStep.java +++ b/jOOQ/src/main/java/org/jooq/SelectWithTiesStep.java @@ -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 extends SelectOffsetStep { - @Support({}) + /** + * Add the WITH TIES clause to a LIMIT clause. + */ + @Support({ CUBRID, FIREBIRD_3_0, POSTGRES }) SelectOffsetStep withTies(); } diff --git a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java index 3feae378d3..eaf58f7fdb 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java @@ -814,15 +814,21 @@ final class SelectQueryImpl extends AbstractResultQuery 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()))) );