[#2580] Bad SQL rendered when combining DISTINCT with LIMIT .. OFFSET in

DB2, SQL Server
This commit is contained in:
lukaseder 2013-09-24 22:31:46 +02:00
parent 27035bb515
commit 5bb189f477
3 changed files with 50 additions and 1 deletions

View File

@ -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())) {

View File

@ -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();

View File

@ -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 (")