diff --git a/querydsl-sql/src/main/java/com/querydsl/sql/SQLServer2005Templates.java b/querydsl-sql/src/main/java/com/querydsl/sql/SQLServer2005Templates.java index 7307c9f1d..24cbca1d5 100644 --- a/querydsl-sql/src/main/java/com/querydsl/sql/SQLServer2005Templates.java +++ b/querydsl-sql/src/main/java/com/querydsl/sql/SQLServer2005Templates.java @@ -91,6 +91,9 @@ public class SQLServer2005Templates extends SQLServerTemplates { for (OrderSpecifier os : metadata.getOrderBy()) { rn.orderBy(os); } + if (metadata.getOrderBy().isEmpty()) { + rn.orderBy(Expressions.currentTimestamp().asc()); + } FactoryExpression pr = Projections.appending(metadata.getProjection(), rn.as("rn")); metadata.setProjection(FactoryExpressionUtils.wrap(pr)); metadata.clearOrderBy(); diff --git a/querydsl-sql/src/main/java/com/querydsl/sql/SQLServer2012Templates.java b/querydsl-sql/src/main/java/com/querydsl/sql/SQLServer2012Templates.java index ced0e5745..fbb88d079 100644 --- a/querydsl-sql/src/main/java/com/querydsl/sql/SQLServer2012Templates.java +++ b/querydsl-sql/src/main/java/com/querydsl/sql/SQLServer2012Templates.java @@ -13,12 +13,15 @@ */ package com.querydsl.sql; +import java.util.Map; import java.util.Set; import com.querydsl.core.QueryFlag; import com.querydsl.core.QueryFlag.Position; import com.querydsl.core.QueryMetadata; import com.querydsl.core.QueryModifiers; +import com.querydsl.core.types.Expression; +import com.querydsl.core.types.Path; import com.querydsl.core.types.dsl.Expressions; /** @@ -67,20 +70,54 @@ public class SQLServer2012Templates extends SQLServerTemplates { public void serialize(QueryMetadata metadata, boolean forCountRow, SQLSerializer context) { if (!forCountRow && metadata.getModifiers().isRestricting() && metadata.getOrderBy().isEmpty() && !metadata.getJoins().isEmpty()) { + metadata = metadata.clone(); 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"); + // order by first column + metadata.addOrderBy(Expressions.ONE.asc()); } - } else { - context.serializeForQuery(metadata, forCountRow); } + context.serializeForQuery(metadata, forCountRow); + + if (!metadata.getFlags().isEmpty()) { + context.serialize(Position.END, metadata.getFlags()); + } + } + + @Override + public void serializeDelete(QueryMetadata metadata, RelationalPath entity, SQLSerializer context) { + // limit + QueryModifiers mod = metadata.getModifiers(); + if (mod.isRestricting()) { + metadata = metadata.clone(); + metadata.addFlag(new QueryFlag(QueryFlag.Position.AFTER_SELECT, + Expressions.template(Integer.class, topTemplate, mod.getLimit()))); + } + + context.serializeForDelete(metadata, entity); + + if (!metadata.getFlags().isEmpty()) { + context.serialize(Position.END, metadata.getFlags()); + } + } + + @Override + public void serializeUpdate(QueryMetadata metadata, RelationalPath entity, + Map, Expression> updates, SQLSerializer context) { + // limit + QueryModifiers mod = metadata.getModifiers(); + if (mod.isRestricting()) { + metadata = metadata.clone(); + metadata.addFlag(new QueryFlag(QueryFlag.Position.AFTER_SELECT, + Expressions.template(Integer.class, topTemplate, mod.getLimit()))); + } + + context.serializeForUpdate(metadata, entity, updates); if (!metadata.getFlags().isEmpty()) { context.serialize(Position.END, metadata.getFlags()); diff --git a/querydsl-sql/src/test/java/com/querydsl/sql/SQLServer2005TemplatesTest.java b/querydsl-sql/src/test/java/com/querydsl/sql/SQLServer2005TemplatesTest.java index 7d4a08f92..863c3cc42 100644 --- a/querydsl-sql/src/test/java/com/querydsl/sql/SQLServer2005TemplatesTest.java +++ b/querydsl-sql/src/test/java/com/querydsl/sql/SQLServer2005TemplatesTest.java @@ -67,12 +67,22 @@ public class SQLServer2005TemplatesTest extends AbstractSQLTemplatesTest { @Test public void modifiers() { query.from(survey1).limit(5).offset(3); + query.orderBy(survey1.id.asc()); query.getMetadata().setProjection(survey1.id); assertEquals("select * from (" + - " select survey1.ID, row_number() over () as rn from SURVEY survey1) a " + + " select survey1.ID, row_number() over (order by survey1.ID asc) as rn from SURVEY survey1) a " + "where rn > ? and rn <= ? order by rn", query.toString()); } + @Test + public void modifiers_noOrder() { + query.from(survey1).limit(5).offset(3); + query.getMetadata().setProjection(survey1.id); + assertEquals("select * from (" + + " select survey1.ID, row_number() over (order by current_timestamp asc) as rn from SURVEY survey1) a " + + "where rn > ? and rn <= ? order by rn", query.toString()); + } + @Test public void nextVal() { Operation nextval = ExpressionUtils.operation(String.class, SQLOps.NEXTVAL, ConstantImpl.create("myseq")); diff --git a/querydsl-sql/src/test/java/com/querydsl/sql/SQLServer2012TemplatesTest.java b/querydsl-sql/src/test/java/com/querydsl/sql/SQLServer2012TemplatesTest.java index 854013470..76f75e778 100644 --- a/querydsl-sql/src/test/java/com/querydsl/sql/SQLServer2012TemplatesTest.java +++ b/querydsl-sql/src/test/java/com/querydsl/sql/SQLServer2012TemplatesTest.java @@ -24,6 +24,8 @@ import com.querydsl.core.types.Operation; import com.querydsl.core.types.Path; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.core.types.dsl.NumberExpression; +import com.querydsl.sql.dml.SQLDeleteClause; +import com.querydsl.sql.dml.SQLUpdateClause; public class SQLServer2012TemplatesTest extends AbstractSQLTemplatesTest { @@ -67,6 +69,33 @@ public class SQLServer2012TemplatesTest extends AbstractSQLTemplatesTest { assertEquals("select top 5 survey1.ID from SURVEY survey1", query.toString()); } + @Test + public void limitOffset() { + query.from(survey1).limit(5).offset(5); + query.getMetadata().setProjection(survey1.id); + assertEquals("select survey1.ID from SURVEY survey1 " + + "order by 1 asc " + + "offset ? rows fetch next ? rows only", query.toString()); + } + + @Test + public void delete_limit() { + SQLDeleteClause clause = new SQLDeleteClause(null, createTemplates(), survey1); + clause.where(survey1.name.eq("Bob")); + clause.limit(5); + assertEquals("delete top 5 from SURVEY\n" + + "where SURVEY.NAME = ?", clause.toString()); + } + + @Test + public void update_limit() { + SQLUpdateClause clause = new SQLUpdateClause(null, createTemplates(), survey1); + clause.set(survey1.name, "Bob"); + clause.limit(5); + assertEquals("update top 5 SURVEY\n" + + "set NAME = ?", clause.toString()); + } + @Test public void modifiers() { query.from(survey1).limit(5).offset(3).orderBy(survey1.id.asc());