Merge pull request #859 from querydsl/i853

Improve limit/offset handling
This commit is contained in:
Timo Westkämper 2014-07-19 15:50:22 +03:00
commit d2d484611d
2 changed files with 34 additions and 15 deletions

View File

@ -13,9 +13,11 @@
*/
package com.mysema.query.sql;
import com.mysema.query.QueryFlag;
import com.mysema.query.QueryFlag.Position;
import com.mysema.query.QueryMetadata;
import com.mysema.query.QueryModifiers;
import com.mysema.query.support.Expressions;
/**
* SQLServer2012Templates is an SQL dialect for Microsoft SQL Server 2012 and later
@ -25,6 +27,8 @@ import com.mysema.query.QueryModifiers;
*/
public class SQLServer2012Templates extends SQLServerTemplates {
private String topTemplate = "top {0s} ";
private String limitOffsetTemplate = "\noffset {1} rows fetch next {0} rows only";
private String offsetTemplate = "\noffset {0} rows";
@ -52,7 +56,22 @@ public class SQLServer2012Templates extends SQLServerTemplates {
@Override
public void serialize(QueryMetadata metadata, boolean forCountRow, SQLSerializer context) {
context.serializeForQuery(metadata, forCountRow);
if (!forCountRow && metadata.getModifiers().isRestricting() && metadata.getOrderBy().isEmpty()
&& !metadata.getJoins().isEmpty()) {
QueryModifiers mod = metadata.getModifiers();
// use top if order by is empty
if (mod.getOffset() == null) {
// select top ...
metadata = metadata.clone();
metadata.addFlag(new QueryFlag(QueryFlag.Position.AFTER_SELECT,
Expressions.template(Integer.class, topTemplate, mod.getLimit())));
context.serializeForQuery(metadata, forCountRow);
} else {
throw new IllegalStateException("offset not supported without order by");
}
} else {
context.serializeForQuery(metadata, forCountRow);
}
if (!metadata.getFlags().isEmpty()) {
context.serialize(Position.END, metadata.getFlags());
@ -61,13 +80,15 @@ public class SQLServer2012Templates extends SQLServerTemplates {
@Override
protected void serializeModifiers(QueryMetadata metadata, SQLSerializer context) {
QueryModifiers mod = metadata.getModifiers();
if (mod.getLimit() == null) {
context.handle(offsetTemplate, mod.getOffset());
} else if (mod.getOffset() == null) {
context.handle(limitOffsetTemplate, mod.getLimit(), 0);
} else {
context.handle(limitOffsetTemplate, mod.getLimit(), mod.getOffset());
if (!metadata.getOrderBy().isEmpty()) {
QueryModifiers mod = metadata.getModifiers();
if (mod.getLimit() == null) {
context.handle(offsetTemplate, mod.getOffset());
} else if (mod.getOffset() == null) {
context.handle(limitOffsetTemplate, mod.getLimit(), 0);
} else {
context.handle(limitOffsetTemplate, mod.getLimit(), mod.getOffset());
}
}
}

View File

@ -13,10 +13,6 @@
*/
package com.mysema.query.sql;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import com.mysema.query.types.ConstantImpl;
import com.mysema.query.types.Operation;
import com.mysema.query.types.OperationImpl;
@ -24,6 +20,8 @@ import com.mysema.query.types.Path;
import com.mysema.query.types.expr.NumberExpression;
import com.mysema.query.types.path.SimplePath;
import com.mysema.query.types.template.NumberTemplate;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class SQLServer2012TemplatesTest extends AbstractSQLTemplatesTest {
@ -64,14 +62,14 @@ public class SQLServer2012TemplatesTest extends AbstractSQLTemplatesTest {
public void Limit() {
query.from(survey1).limit(5);
query.getMetadata().addProjection(survey1.id);
assertEquals("select survey1.ID from SURVEY survey1 offset ? rows fetch next ? rows only", query.toString());
assertEquals("select top 5 survey1.ID from SURVEY survey1", query.toString());
}
@Test
public void Modifiers() {
query.from(survey1).limit(5).offset(3);
query.from(survey1).limit(5).offset(3).orderBy(survey1.id.asc());
query.getMetadata().addProjection(survey1.id);
assertEquals("select survey1.ID from SURVEY survey1 offset ? rows fetch next ? rows only", query.toString());
assertEquals("select survey1.ID from SURVEY survey1 order by survey1.ID asc offset ? rows fetch next ? rows only", query.toString());
}
@Test