[#2580] Bad SQL rendered when combining DISTINCT with LIMIT .. OFFSET in
DB2, SQL Server
This commit is contained in:
parent
27035bb515
commit
5bb189f477
@ -307,6 +307,32 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
||||
assertEquals(Integer.valueOf(3), result.getValue(1, TBook_ID()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLimitDistinct() throws Exception {
|
||||
assertEquals(asList(1, 2),
|
||||
create().selectDistinct(TBookToBookStore_BOOK_ID())
|
||||
.from(TBookToBookStore())
|
||||
.orderBy(TBookToBookStore_BOOK_ID())
|
||||
.limit(2)
|
||||
.fetch(TBookToBookStore_BOOK_ID()));
|
||||
|
||||
assertEquals(asList(2, 3),
|
||||
create().selectDistinct(TBookToBookStore_BOOK_ID())
|
||||
.from(TBookToBookStore())
|
||||
.orderBy(TBookToBookStore_BOOK_ID())
|
||||
.limit(2)
|
||||
.offset(1)
|
||||
.fetch(TBookToBookStore_BOOK_ID()));
|
||||
|
||||
assertSame(asList(2, 1),
|
||||
create().selectDistinct(TBook_LANGUAGE_ID(), TBook_AUTHOR_ID())
|
||||
.from(TBook())
|
||||
.orderBy(TBook_AUTHOR_ID().desc())
|
||||
.limit(2)
|
||||
.offset(1)
|
||||
.fetch(TBook_AUTHOR_ID()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLimitAliased() throws Exception {
|
||||
if (asList(ASE, SQLSERVER).contains(dialect().family())) {
|
||||
|
||||
@ -1804,6 +1804,11 @@ public abstract class jOOQAbstractTest<
|
||||
new OrderByTests(this).testLimit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLimitDistinct() throws Exception {
|
||||
new OrderByTests(this).testLimitDistinct();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLimitAliased() throws Exception {
|
||||
new OrderByTests(this).testLimitAliased();
|
||||
|
||||
@ -61,6 +61,7 @@ import static org.jooq.SQLDialect.SQLSERVER;
|
||||
import static org.jooq.SQLDialect.SQLSERVER2008;
|
||||
import static org.jooq.SQLDialect.SQLSERVER2012;
|
||||
import static org.jooq.conf.ParamType.INLINED;
|
||||
import static org.jooq.impl.DSL.denseRank;
|
||||
import static org.jooq.impl.DSL.inline;
|
||||
import static org.jooq.impl.DSL.name;
|
||||
import static org.jooq.impl.DSL.one;
|
||||
@ -68,6 +69,7 @@ import static org.jooq.impl.DSL.rowNumber;
|
||||
import static org.jooq.impl.Utils.DATA_ROW_VALUE_EXPRESSION_PREDICATE_SUBQUERY;
|
||||
import static org.jooq.impl.Utils.DATA_WRAP_DERIVED_TABLES_IN_PARENTHESES;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@ -381,7 +383,23 @@ class SelectQueryImpl<R extends Record> extends AbstractSelect<R> implements Sel
|
||||
// window function, calculating row numbers for the LIMIT .. OFFSET clause
|
||||
RenderContext local = new DefaultRenderContext(context);
|
||||
local.subquery(true);
|
||||
toSQLReference0(local, rowNumber().over().orderBy(getNonEmptyOrderBy()).as(rownumName));
|
||||
|
||||
// [#2580] 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
|
||||
if (distinct) {
|
||||
List<SortField<?>> order = new ArrayList<SortField<?>>();
|
||||
order.addAll(getNonEmptyOrderBy());
|
||||
|
||||
// TODO: Challenge this with lots of additional tests, improve readability
|
||||
for (Field<?> field : getSelect())
|
||||
order.add(field.asc());
|
||||
toSQLReference0(local, denseRank().over().orderBy(order).as(rownumName));
|
||||
}
|
||||
else {
|
||||
toSQLReference0(local, rowNumber().over().orderBy(getNonEmptyOrderBy()).as(rownumName));
|
||||
}
|
||||
String enclosed = local.render();
|
||||
|
||||
context.keyword("select * from (")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user