From 9df99f02f5445379bca7a31ca665c977acb3f984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Westk=C3=A4mper?= Date: Fri, 18 Jul 2014 08:14:40 +0300 Subject: [PATCH] Improve limit/offset handling --- .../query/sql/SQLServer2012Templates.java | 37 +++++++++++++++---- .../query/sql/SQLServer2012TemplatesTest.java | 12 +++--- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLServer2012Templates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLServer2012Templates.java index bf371e96d..fd4e79827 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLServer2012Templates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLServer2012Templates.java @@ -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()); + } } } diff --git a/querydsl-sql/src/test/java/com/mysema/query/sql/SQLServer2012TemplatesTest.java b/querydsl-sql/src/test/java/com/mysema/query/sql/SQLServer2012TemplatesTest.java index dc3bc203c..0f938e3ba 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/sql/SQLServer2012TemplatesTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/sql/SQLServer2012TemplatesTest.java @@ -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