[#8593] DB2 ranking functions require an ORDER BY clause

This commit is contained in:
lukaseder 2019-05-02 13:39:10 +02:00
parent a7a0a02d3c
commit cad39d4e62
3 changed files with 44 additions and 27 deletions

View File

@ -426,16 +426,20 @@ class Function<T> extends AbstractField<T> implements
return;
Boolean ranking = false;
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:
@ -457,7 +461,9 @@ class Function<T> extends AbstractField<T> implements
.sql(' ');
previousRanking = (Boolean) ctx.data(DATA_RANKING_FUNCTION, ranking);
previousRowNumber = (Boolean) ctx.data(DATA_ROWNUMBER_FUNCTION, rowNumber);
ctx.visit(window);
@ -466,10 +472,12 @@ class Function<T> extends AbstractField<T> implements
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")

View File

@ -454,10 +454,12 @@ 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.

View File

@ -40,6 +40,7 @@ package org.jooq.impl;
import static java.lang.Boolean.TRUE;
// ...
import static org.jooq.SQLDialect.CUBRID;
// ...
import static org.jooq.SQLDialect.H2;
// ...
import static org.jooq.SQLDialect.MYSQL;
@ -79,6 +80,7 @@ import org.jooq.Context;
import org.jooq.Field;
import org.jooq.Keyword;
import org.jooq.OrderField;
// ...
import org.jooq.SQLDialect;
import org.jooq.WindowSpecificationExcludeStep;
import org.jooq.WindowSpecificationFinalStep;
@ -101,9 +103,14 @@ final class WindowSpecificationImpl extends AbstractQueryPart implements
/**
* Generated UID
*/
private static final long serialVersionUID = 2996016924769376361L;
private static final EnumSet<SQLDialect> OMIT_PARTITION_BY_ONE = EnumSet.of(CUBRID, MYSQL, SQLITE);
private static final EnumSet<SQLDialect> REQUIRES_ORDER_BY_IN_RANKING = EnumSet.of(H2);
private static final long serialVersionUID = 2996016924769376361L;
private static final EnumSet<SQLDialect> OMIT_PARTITION_BY_ONE = EnumSet.of(CUBRID, MYSQL, SQLITE);
private static final EnumSet<SQLDialect> REQUIRES_ORDER_BY_IN_RANKING = EnumSet.of(H2);
private final WindowDefinitionImpl windowDefinition;
private final QueryPartList<Field<?>> partitionBy;
@ -163,17 +170,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(' ')