From 16df2e309d7f99d0797d8ab61bb9ff08afe0a4ae Mon Sep 17 00:00:00 2001 From: lukaseder Date: Thu, 14 Mar 2019 10:14:37 +0100 Subject: [PATCH] [#8414] Don't emulate empty ORDER BY clause in H2's ROW_NUMBER() function --- .../src/main/java/org/jooq/impl/Function.java | 23 +++++++++++++++---- jOOQ/src/main/java/org/jooq/impl/Tools.java | 5 ++++ .../jooq/impl/WindowSpecificationImpl.java | 12 ++++++++++ 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/Function.java b/jOOQ/src/main/java/org/jooq/impl/Function.java index 535f38a9b4..441466b5cb 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Function.java +++ b/jOOQ/src/main/java/org/jooq/impl/Function.java @@ -89,6 +89,7 @@ import static org.jooq.impl.Term.MODE; import static org.jooq.impl.Term.PRODUCT; import static org.jooq.impl.Term.ROW_NUMBER; import static org.jooq.impl.Tools.BooleanDataKey.DATA_RANKING_FUNCTION; +import static org.jooq.impl.Tools.BooleanDataKey.DATA_ROWNUMBER_FUNCTION; import static org.jooq.impl.Tools.DataKey.DATA_WINDOW_DEFINITIONS; import java.math.BigDecimal; @@ -424,10 +425,17 @@ class Function extends AbstractField implements return; Boolean ranking = false; - Boolean previous = null; + Boolean rowNumber = false; + Boolean previousRanking = null; + Boolean previousRowNumber = null; if (term != null) { switch (term) { + case ROW_NUMBER: + rowNumber = true; + ranking = true; + break; + case CUME_DIST: case DENSE_RANK: case FIRST_VALUE: @@ -438,7 +446,6 @@ class Function extends AbstractField implements case NTILE: case PERCENT_RANK: case RANK: - case ROW_NUMBER: ranking = true; break; } @@ -448,14 +455,20 @@ class Function extends AbstractField implements .visit(K_OVER) .sql(' '); - previous = (Boolean) ctx.data(DATA_RANKING_FUNCTION, ranking); + previousRanking = (Boolean) ctx.data(DATA_RANKING_FUNCTION, ranking); + previousRowNumber = (Boolean) ctx.data(DATA_ROWNUMBER_FUNCTION, rowNumber); ctx.visit(window); - if (TRUE.equals(previous)) - ctx.data(DATA_RANKING_FUNCTION, previous); + if (TRUE.equals(previousRanking)) + ctx.data(DATA_RANKING_FUNCTION, previousRanking); else ctx.data().remove(DATA_RANKING_FUNCTION); + + if (TRUE.equals(previousRowNumber)) + ctx.data(DATA_ROWNUMBER_FUNCTION, previousRowNumber); + else + ctx.data().remove(DATA_ROWNUMBER_FUNCTION); } @SuppressWarnings("unchecked") diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index a36979c68d..a7c4222434 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -452,6 +452,11 @@ final class Tools { */ DATA_EMULATE_BULK_INSERT_RETURNING, + /** + * [#8414] We're currently generating the window specification of a row_number function. + */ + DATA_ROWNUMBER_FUNCTION, + /** * [#1535] We're currently generating the window specification of a ranking function. */ diff --git a/jOOQ/src/main/java/org/jooq/impl/WindowSpecificationImpl.java b/jOOQ/src/main/java/org/jooq/impl/WindowSpecificationImpl.java index 90800108cb..ea746f9c07 100644 --- a/jOOQ/src/main/java/org/jooq/impl/WindowSpecificationImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/WindowSpecificationImpl.java @@ -62,6 +62,7 @@ import static org.jooq.impl.Keywords.K_PRECEDING; import static org.jooq.impl.Keywords.K_UNBOUNDED_FOLLOWING; import static org.jooq.impl.Keywords.K_UNBOUNDED_PRECEDING; import static org.jooq.impl.Tools.BooleanDataKey.DATA_RANKING_FUNCTION; +import static org.jooq.impl.Tools.BooleanDataKey.DATA_ROWNUMBER_FUNCTION; import static org.jooq.impl.WindowSpecificationImpl.Exclude.CURRENT_ROW; import static org.jooq.impl.WindowSpecificationImpl.Exclude.GROUP; import static org.jooq.impl.WindowSpecificationImpl.Exclude.NO_OTHERS; @@ -162,6 +163,17 @@ final class WindowSpecificationImpl extends AbstractQueryPart implements glue = " "; } + else if (TRUE.equals(ctx.data(DATA_ROWNUMBER_FUNCTION)) && REQUIRES_ORDER_BY_IN_RANKING.contains(ctx.family())) { + + // [#8414] H2 requires ORDER BY in all other ranking functions than ROW_NUMBER() + if (ctx.family() != H2) { + ctx.sql(glue) + .visit(K_ORDER_BY).sql(' ') + .visit(field(select(one()))); + + glue = " "; + } + } else if (TRUE.equals(ctx.data(DATA_RANKING_FUNCTION)) && REQUIRES_ORDER_BY_IN_RANKING.contains(ctx.family())) { ctx.sql(glue) .visit(K_ORDER_BY).sql(' ')