From fd0c4afce2756e5e0fbf67fb7e0fd33e34845c19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Westk=C3=A4mper?= Date: Sun, 14 Mar 2010 21:20:51 +0000 Subject: [PATCH] stabilized Oracle and SQL Server paging updated version to 1.3.14 --- querydsl-apt/pom.xml | 2 +- querydsl-collections/pom.xml | 2 +- querydsl-core/pom.xml | 2 +- .../mysema/query/DefaultQueryMetadata.java | 12 + .../java/com/mysema/query/QueryMetadata.java | 49 +- .../mysema/query/types/expr/EConstructor.java | 16 +- .../test/java/com/mysema/query/Filters.java | 4 +- .../com/mysema/query/MatchingFilters.java | 11 +- querydsl-hql/pom.xml | 14 +- querydsl-jdoql/pom.xml | 2 +- querydsl-maven-plugin/pom.xml | 2 +- querydsl-root/pom.xml | 2 +- querydsl-sql/pom.xml | 2 +- .../com/mysema/query/sql/DerbyTemplates.java | 29 +- .../com/mysema/query/sql/OracleTemplates.java | 48 +- .../com/mysema/query/sql/SQLSerializer.java | 65 ++- .../mysema/query/sql/SQLServerTemplates.java | 59 +- .../com/mysema/query/sql/SQLTemplates.java | 503 ++++++++---------- .../query/sql/SerializationContext.java | 34 ++ .../query/sql/mssql/SQLServerGrammar.java | 6 + .../query/sql/oracle/OracleGrammar.java | 10 +- .../java/com/mysema/query/DeleteBaseTest.java | 2 +- .../java/com/mysema/query/SelectBaseTest.java | 89 ++-- .../java/com/mysema/query/UpdateBaseTest.java | 2 +- .../mysema/query/_derby/SelectDerbyTest.java | 20 + .../mysema/query/_mssql/SelectMSSQLTest.java | 2 +- .../query/_oracle/SelectOracleTest.java | 15 + .../mysema/query/sql/SQLTemplatesTest.java | 5 + 28 files changed, 578 insertions(+), 431 deletions(-) create mode 100644 querydsl-sql/src/main/java/com/mysema/query/sql/SerializationContext.java diff --git a/querydsl-apt/pom.xml b/querydsl-apt/pom.xml index 8c923ad0e..bbc1eefff 100644 --- a/querydsl-apt/pom.xml +++ b/querydsl-apt/pom.xml @@ -5,7 +5,7 @@ com.mysema.querydsl querydsl-root - 1.3.13-SNAPSHOT + 1.3.14 com.mysema.querydsl diff --git a/querydsl-collections/pom.xml b/querydsl-collections/pom.xml index 6578a8bf6..66ed5fe5f 100644 --- a/querydsl-collections/pom.xml +++ b/querydsl-collections/pom.xml @@ -5,7 +5,7 @@ com.mysema.querydsl querydsl-root - 1.3.13-SNAPSHOT + 1.3.14 com.mysema.querydsl diff --git a/querydsl-core/pom.xml b/querydsl-core/pom.xml index 882bbd736..ca0af87d6 100644 --- a/querydsl-core/pom.xml +++ b/querydsl-core/pom.xml @@ -5,7 +5,7 @@ com.mysema.querydsl querydsl-root - 1.3.13-SNAPSHOT + 1.3.14 com.mysema.querydsl diff --git a/querydsl-core/src/main/java/com/mysema/query/DefaultQueryMetadata.java b/querydsl-core/src/main/java/com/mysema/query/DefaultQueryMetadata.java index 9463a4336..1db65bef4 100644 --- a/querydsl-core/src/main/java/com/mysema/query/DefaultQueryMetadata.java +++ b/querydsl-core/src/main/java/com/mysema/query/DefaultQueryMetadata.java @@ -121,6 +121,18 @@ public class DefaultQueryMetadata implements QueryMetadata, Cloneable { } } + public void clearOrderBy(){ + orderBy.clear(); + } + + public void clearProjection(){ + projection.clear(); + } + + public void clearWhere(){ + where = new BooleanBuilder(); + } + @Override public QueryMetadata clone(){ try { diff --git a/querydsl-core/src/main/java/com/mysema/query/QueryMetadata.java b/querydsl-core/src/main/java/com/mysema/query/QueryMetadata.java index b861d268b..293a16da1 100644 --- a/querydsl-core/src/main/java/com/mysema/query/QueryMetadata.java +++ b/querydsl-core/src/main/java/com/mysema/query/QueryMetadata.java @@ -64,6 +64,26 @@ public interface QueryMetadata extends Serializable { */ void addWhere(EBoolean... o); + /** + * + */ + void clearOrderBy(); + + /** + * + */ + void clearProjection(); + + /** + * + */ + void clearWhere(); + + /** + * @return + */ + QueryMetadata clone(); + /** * @return */ @@ -79,29 +99,29 @@ public interface QueryMetadata extends Serializable { * @return */ List getJoins(); - + /** * @return */ @Nullable QueryModifiers getModifiers(); - + /** * @return */ List> getOrderBy(); - + /** * @return */ List> getProjection(); - + /** * @return */ @Nullable EBoolean getWhere(); - + /** * @return */ @@ -112,16 +132,21 @@ public interface QueryMetadata extends Serializable { */ boolean isUnique(); + /** + * + */ + void reset(); + /** * @param distinct */ void setDistinct(boolean distinct); - + /** * @param limit */ void setLimit(@Nullable Long limit); - + /** * @param restriction */ @@ -136,14 +161,4 @@ public interface QueryMetadata extends Serializable { * @param unique */ void setUnique(boolean unique); - - /** - * - */ - void reset(); - - /** - * @return - */ - QueryMetadata clone(); } \ No newline at end of file diff --git a/querydsl-core/src/main/java/com/mysema/query/types/expr/EConstructor.java b/querydsl-core/src/main/java/com/mysema/query/types/expr/EConstructor.java index 369c5870b..3a79d4ce4 100644 --- a/querydsl-core/src/main/java/com/mysema/query/types/expr/EConstructor.java +++ b/querydsl-core/src/main/java/com/mysema/query/types/expr/EConstructor.java @@ -25,18 +25,22 @@ import com.mysema.query.types.Visitor; public class EConstructor extends Expr { private static final long serialVersionUID = -602747921848073175L; + + private static Class normalize(Class clazz){ + if (clazz.isPrimitive()){ + return ClassUtils.primitiveToWrapper(clazz); + }else{ + return clazz; + } + } public static EConstructor create(Class type, Expr... args){ for (Constructor c : type.getConstructors()){ Class[] paramTypes = c.getParameterTypes(); if (paramTypes.length == args.length){ boolean found = true; - for (int i = 0; i < paramTypes.length; i++){ - Class paramType = paramTypes[i]; - if (paramType.isPrimitive()){ - paramType = ClassUtils.primitiveToWrapper(paramType); - } - if (!paramType.isAssignableFrom(args[i].getType())){ + for (int i = 0; i < paramTypes.length; i++){ + if (!normalize(paramTypes[i]).isAssignableFrom(args[i].getType())){ found = false; break; } diff --git a/querydsl-core/src/test/java/com/mysema/query/Filters.java b/querydsl-core/src/test/java/com/mysema/query/Filters.java index 9eb5169dd..4303088cc 100644 --- a/querydsl-core/src/test/java/com/mysema/query/Filters.java +++ b/querydsl-core/src/test/java/com/mysema/query/Filters.java @@ -242,7 +242,9 @@ public class Filters { rv.add(expr.like("%"+knownValue.substring(1))); rv.add(expr.like("%"+knownValue.substring(1,2)+"%")); - if (!target.equals(Target.DERBY) && !target.equals(Target.HSQLDB)){ + if (!target.equals(Target.DERBY) + && !target.equals(Target.HSQLDB) + && !target.equals(Target.SQLSERVER)){ rv.add(expr.matches(knownValue.substring(0,1)+".*")); rv.add(expr.matches(".*"+knownValue.substring(1))); rv.add(expr.matches(".*"+knownValue.substring(1,2)+".*")); diff --git a/querydsl-core/src/test/java/com/mysema/query/MatchingFilters.java b/querydsl-core/src/test/java/com/mysema/query/MatchingFilters.java index 16e209d15..85d6e86e3 100644 --- a/querydsl-core/src/test/java/com/mysema/query/MatchingFilters.java +++ b/querydsl-core/src/test/java/com/mysema/query/MatchingFilters.java @@ -75,7 +75,9 @@ public class MatchingFilters { if (!target.equals(Target.DERBY) && !module.equals(Module.JDOQL)){ rv.add(expr.dayOfWeek().eq(other.dayOfWeek ())); rv.add(expr.dayOfYear().eq(other.dayOfYear())); - rv.add(expr.week().eq(other.week())); + if (!target.equals(Target.SQLSERVER)){ + rv.add(expr.week().eq(other.week())); + } } rv.add(expr.month().eq(other.month())); @@ -103,7 +105,9 @@ public class MatchingFilters { if (!target.equals(Target.DERBY) && !module.equals(Module.JDOQL)){ rv.add(expr.dayOfWeek().eq(other.dayOfWeek ())); rv.add(expr.dayOfYear().eq(other.dayOfYear())); - rv.add(expr.week().eq(other.week())); + if (!target.equals(Target.SQLSERVER)){ + rv.add(expr.week().eq(other.week())); + } } rv.add(expr.month().eq(other.month())); @@ -212,7 +216,8 @@ public class MatchingFilters { rv.add(expr.lower().eq(other.lower())); - if (!module.equals(Module.SQL) || (!target.equals(Target.HSQLDB) && !target.equals(Target.DERBY))){ + if (!module.equals(Module.SQL) + || (!target.equals(Target.HSQLDB) && !target.equals(Target.DERBY) && !target.equals(Target.SQLSERVER))){ rv.add(expr.matches(other.substring(0,1).append(".*"))); rv.add(expr.matches(other.substring(0,1).append(".").append(other.substring(2)))); rv.add(expr.matches(other.substring(1).prepend(".*"))); diff --git a/querydsl-hql/pom.xml b/querydsl-hql/pom.xml index 2f808d21f..6d35b8d52 100644 --- a/querydsl-hql/pom.xml +++ b/querydsl-hql/pom.xml @@ -5,7 +5,7 @@ com.mysema.querydsl querydsl-root - 1.3.13-SNAPSHOT + 1.3.14 com.mysema.querydsl @@ -87,12 +87,12 @@ mysql-connector-java 5.1.6 test - - - net.sourceforge.jtds - jtds - 1.2.4 - test + + + net.sourceforge.jtds + jtds + 1.2.4 + test com.mysema.querydsl diff --git a/querydsl-jdoql/pom.xml b/querydsl-jdoql/pom.xml index 39a886f61..b63c38983 100644 --- a/querydsl-jdoql/pom.xml +++ b/querydsl-jdoql/pom.xml @@ -5,7 +5,7 @@ com.mysema.querydsl querydsl-root - 1.3.13-SNAPSHOT + 1.3.14 com.mysema.querydsl diff --git a/querydsl-maven-plugin/pom.xml b/querydsl-maven-plugin/pom.xml index 362dcbc8a..4f644d187 100644 --- a/querydsl-maven-plugin/pom.xml +++ b/querydsl-maven-plugin/pom.xml @@ -5,7 +5,7 @@ com.mysema.querydsl querydsl-root - 1.3.13-SNAPSHOT + 1.3.14 com.mysema.querydsl diff --git a/querydsl-root/pom.xml b/querydsl-root/pom.xml index c2f665d66..2206a6317 100644 --- a/querydsl-root/pom.xml +++ b/querydsl-root/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.mysema.querydsl querydsl-root - 1.3.13-SNAPSHOT + 1.3.14 Querydsl parent project for querydsl modules http://source.mysema.com/display/querydsl diff --git a/querydsl-sql/pom.xml b/querydsl-sql/pom.xml index 3645a271b..bb9ff3957 100644 --- a/querydsl-sql/pom.xml +++ b/querydsl-sql/pom.xml @@ -5,7 +5,7 @@ com.mysema.querydsl querydsl-root - 1.3.13-SNAPSHOT + 1.3.14 com.mysema.querydsl diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/DerbyTemplates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/DerbyTemplates.java index db68acc60..27bda10b4 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/DerbyTemplates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/DerbyTemplates.java @@ -5,6 +5,8 @@ */ package com.mysema.query.sql; +import com.mysema.query.QueryMetadata; +import com.mysema.query.QueryModifiers; import com.mysema.query.types.operation.Ops; /** @@ -14,6 +16,13 @@ import com.mysema.query.types.operation.Ops; * */ public class DerbyTemplates extends SQLTemplates { + + private String limitOffsetTemplate = "\noffset {1s} rows fetch next {0s} rows only"; + + private String limitTemplate = "\nfetch first {0s} rows only"; + + private String offsetTemplate = "\noffset {0s} rows"; + { addClass2TypeMappings("smallint", Byte.class); @@ -26,9 +35,21 @@ public class DerbyTemplates extends SQLTemplates { add(Ops.CASE_EQ_WHEN, "when {0} = {1} then {2} {3}"); add(Ops.CASE_EQ_ELSE, "else {0}"); - setLimitAndOffsetSymbols(false); - setLimitTemplate("fetch first {0s} rows only"); - setOffsetTemplate("offset {0s} rows"); - setLimitOffsetTemplate("offset {1s} rows fetch next {0s} rows only"); +// setLimitAndOffsetSymbols(false); +// setLimitTemplate("fetch first {0s} rows only"); +// setOffsetTemplate("offset {0s} rows"); +// setLimitOffsetTemplate("offset {1s} rows fetch next {0s} rows only"); } + + protected void serializeModifiers(QueryMetadata metadata, SerializationContext context) { + QueryModifiers mod = metadata.getModifiers(); + if (mod.getLimit() == null){ + context.handle(offsetTemplate, mod.getOffset()); + }else if (mod.getOffset() == null){ + context.handle(limitTemplate, mod.getLimit()); + }else{ + context.handle(limitOffsetTemplate, mod.getLimit(), mod.getOffset()); + } + } + } \ No newline at end of file diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/OracleTemplates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/OracleTemplates.java index 8048a4cbb..0b4afa4d9 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/OracleTemplates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/OracleTemplates.java @@ -7,6 +7,8 @@ package com.mysema.query.sql; import java.math.BigInteger; +import com.mysema.query.QueryMetadata; +import com.mysema.query.QueryModifiers; import com.mysema.query.types.operation.Ops; /** @@ -19,6 +21,12 @@ import com.mysema.query.types.operation.Ops; */ public class OracleTemplates extends SQLTemplates { + private String limitOffsetTemplate = "rn > {0s} and rn <= {1s}"; + + private String limitTemplate = "rn <= {0}"; + + private String offsetTemplate = "rn > {0}"; + public OracleTemplates(){ // type mappings addClass2TypeMappings("number(3,0)", Byte.class); @@ -54,10 +62,40 @@ public class OracleTemplates extends SQLTemplates { add(Ops.DateTimeOps.MINUTE, "to_number(to_char({0},'MI'))"); add(Ops.DateTimeOps.SECOND, "to_number(to_char({0},'SS'))"); - setLimitAndOffsetSymbols(false); - setRequiresWhereForPagingSymbols(true); - setLimitTemplate("rownum < {0}"); - setOffsetTemplate("rownum > {0}"); - setLimitOffsetTemplate("rownum between {0} and {2}"); +// setLimitAndOffsetSymbols(false); +// setRequiresWhereForPagingSymbols(true); +// setLimitTemplate("rownum < {0}"); +// setOffsetTemplate("rownum > {0}"); +// setLimitOffsetTemplate("rownum between {0} and {2}"); } + + @Override + public void serialize(QueryMetadata metadata, boolean forCountRow, SerializationContext context) { + if (!forCountRow && metadata.getModifiers().isRestricting()){ + QueryModifiers mod = metadata.getModifiers(); + + if (mod.getOffset() == null){ + context.append("select * from (\n "); + context.serialize(metadata, forCountRow); + context.handle("\n) where rownum <= {0}", mod.getLimit()); + }else{ + context.append("select * from (\n"); + context.append(" select a.*, rownum rn from (\n "); + context.serialize(metadata, forCountRow); + context.append("\n ) a) where "); + + if (mod.getLimit() == null){ + context.handle(offsetTemplate, mod.getOffset()); + }else if (mod.getOffset() == null){ + context.handle(limitTemplate, mod.getLimit()); + }else{ + context.handle(limitOffsetTemplate, mod.getOffset(), mod.getLimit() + mod.getOffset()); + } + } + + }else{ + context.serialize(metadata, forCountRow); + } + } + } \ No newline at end of file diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLSerializer.java b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLSerializer.java index 650d3da88..8fdfc64eb 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLSerializer.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLSerializer.java @@ -20,6 +20,7 @@ import com.mysema.query.QueryMetadata; import com.mysema.query.serialization.SerializerBase; import com.mysema.query.types.Order; import com.mysema.query.types.OrderSpecifier; +import com.mysema.query.types.custom.CSimple; import com.mysema.query.types.expr.Constant; import com.mysema.query.types.expr.EBoolean; import com.mysema.query.types.expr.EConstructor; @@ -39,7 +40,30 @@ import com.mysema.query.types.query.SubQuery; */ public class SQLSerializer extends SerializerBase { - // TODO : improved table and column serialization + private final SerializationContext context = new SerializationContext(){ + + @Override + public void serialize(QueryMetadata metadata, boolean forCountRow) { + SQLSerializer.this.serializeForQuery(metadata, forCountRow); + } + + @Override + public SerializationContext append(String str) { + SQLSerializer.this.append(str); + return this; + } + + @Override + public void handle(String template, Object... args) { + Expr[] exprs = new Expr[args.length]; + for (int i = 0; i < args.length; i++){ + exprs[i] = ExprConst.create(args[i]); + } + SQLSerializer.this.handle(CSimple.create(Object.class, template, exprs)); + + } + + }; private static final String COMMA = ", "; @@ -115,8 +139,12 @@ public class SQLSerializer extends SerializerBase { handle(je.getTarget()); } + public void serialize(QueryMetadata metadata, boolean forCountRow){ + templates.serialize(metadata, forCountRow, context); + } + @SuppressWarnings("unchecked") - public void serialize(QueryMetadata metadata, boolean forCountRow) { + private void serializeForQuery(QueryMetadata metadata, boolean forCountRow) { List> select = metadata.getProjection(); List joins = metadata.getJoins(); EBoolean where = metadata.getWhere(); @@ -155,13 +183,7 @@ public class SQLSerializer extends SerializerBase { append(templates.getSelect()); } else { append(templates.getSelectDistinct()); - } - if (metadata.getModifiers().isRestricting() && !forCountRow && !templates.isPagingAfterOrder()){ - Long limit = metadata.getModifiers().getLimit(); - Long offset = metadata.getModifiers().getOffset(); - serializeModifiers(where, limit, offset); - } - + } handle(COMMA, sqlSelect); } @@ -193,13 +215,6 @@ public class SQLSerializer extends SerializerBase { serializeOrderBy(orderBy); } - // limit & offset - if (metadata.getModifiers().isRestricting() && !forCountRow && templates.isPagingAfterOrder()){ - Long limit = metadata.getModifiers().getLimit(); - Long offset = metadata.getModifiers().getOffset(); - serializeModifiers(where, limit, offset); - } - } public void serializeForDelete(PEntity entity, EBoolean where) { @@ -267,24 +282,6 @@ public class SQLSerializer extends SerializerBase { } } - private void serializeModifiers(@Nullable EBoolean where, Long limit, Long offset) { - if (!templates.isLimitAndOffsetSymbols()){ - if (where == null && templates.isRequiresWhereForPagingSymbols()){ - append(templates.getWhere()); - }else if (templates.isPagingAfterOrder()){ - append(" "); - } - handle(templates.getLimitOffsetCondition(limit, offset)); - }else{ - if (limit != null) { - append(templates.getLimit()).append(String.valueOf(limit)); - } - if (offset != null) { - append(templates.getOffset()).append(String.valueOf(offset)); - } - } - } - private void serializeOrderBy(List> orderBy) { append(templates.getOrderBy()); boolean first = true; diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLServerTemplates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLServerTemplates.java index 52644b13a..acd97b9d1 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLServerTemplates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLServerTemplates.java @@ -5,7 +5,12 @@ */ package com.mysema.query.sql; +import com.mysema.query.QueryMetadata; +import com.mysema.query.QueryModifiers; +import com.mysema.query.sql.mssql.RowNumber; +import com.mysema.query.types.OrderSpecifier; import com.mysema.query.types.operation.Ops; +import com.mysema.query.types.path.PNumber; /** * SQLServerTemplates is an SQL dialect for Microsoft SQL Server @@ -15,8 +20,16 @@ import com.mysema.query.types.operation.Ops; * @author tiwe * */ -// NOTE : under construction public class SQLServerTemplates extends SQLTemplates{ + + private static final PNumber rowNumber = new PNumber(Long.class, "row_number"); + + private String limitOffsetTemplate = "row_number > {0} and row_number <= {1}"; + + private String limitTemplate = "row_number <= {0}"; + + private String offsetTemplate = "row_number > {0}"; + { addClass2TypeMappings("decimal", Double.class); @@ -44,10 +57,44 @@ public class SQLServerTemplates extends SQLTemplates{ add(Ops.DateTimeOps.SECOND, "datepart(second, {0})"); add(Ops.DateTimeOps.MILLISECOND, "datepart(millisecond, {0})"); - setLimitAndOffsetSymbols(false); - setPagingAfterOrder(false); - setLimitTemplate("top {0s} "); - setOffsetTemplate(""); // FIXME - setLimitOffsetTemplate("top {2s} "); // FIXME +// setLimitAndOffsetSymbols(false); +// setPagingAfterOrder(false); +// setLimitTemplate("top {0s} "); +// setOffsetTemplate(""); // FIXME +// setLimitOffsetTemplate("top {2s} "); // FIXME + } + + @Override + public void serialize(QueryMetadata metadata, boolean forCountRow, SerializationContext context) { + if (!forCountRow && metadata.getModifiers().isRestricting()){ + context.append("with inner_query as \n"); + context.append("(\n "); + + metadata = metadata.clone(); + RowNumber rn = new RowNumber(); + for (OrderSpecifier os : metadata.getOrderBy()){ + rn.orderBy(os); + } + metadata.addProjection(rn.as(rowNumber)); + metadata.clearOrderBy(); + context.serialize(metadata, forCountRow); + + context.append("\n)\n"); + context.append("select * \n"); + context.append("from inner_query\n"); + context.append("where "); + + QueryModifiers mod = metadata.getModifiers(); + if (mod.getLimit() == null){ + context.handle(offsetTemplate, mod.getOffset()); + }else if (mod.getOffset() == null){ + context.handle(limitTemplate, mod.getLimit()); + }else{ + context.handle(limitOffsetTemplate, mod.getOffset(), mod.getLimit() + mod.getOffset()); + } + + }else{ + context.serialize(metadata, forCountRow); + } } } diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLTemplates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLTemplates.java index 96300ebd7..96f68a9df 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLTemplates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLTemplates.java @@ -10,14 +10,11 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; -import javax.annotation.Nullable; - import com.mysema.query.JoinType; import com.mysema.query.QueryException; +import com.mysema.query.QueryMetadata; +import com.mysema.query.QueryModifiers; import com.mysema.query.types.Templates; -import com.mysema.query.types.custom.CSimple; -import com.mysema.query.types.expr.ENumberConst; -import com.mysema.query.types.expr.Expr; import com.mysema.query.types.operation.Ops; /** @@ -28,12 +25,12 @@ import com.mysema.query.types.operation.Ops; * @version $Id$ */ public class SQLTemplates extends Templates { - + public static final SQLTemplates DEFAULT = new SQLTemplates(); - private final Map, String> class2type = new HashMap, String>(); - private String asc = " asc"; + + private final Map, String> class2type = new HashMap, String>(); private String columnAlias = " "; @@ -41,14 +38,14 @@ public class SQLTemplates extends Templates { private String countStar = "count(*)"; - private String distinctCountStart = "count(distinct "; - - private String distinctCountEnd = ")"; - private String deleteFrom = "delete from "; private String desc = " desc"; + private String distinctCountEnd = ")"; + + private String distinctCountStart = "count(distinct "; + private String dummyTable = "dual"; private String from = "\nfrom "; @@ -59,26 +56,18 @@ public class SQLTemplates extends Templates { private String having = "\nhaving "; - private String insertInto = "insert into "; - private String innerJoin = "\ninner join "; + private String insertInto = "insert into "; + private String join = "\njoin "; private String leftJoin = "\nleft join "; - private String limit = "\nlimit "; + private String limitTemplate = "\nlimit {0}"; - private boolean limitAndOffsetSymbols = true; + private String offsetTemplate = "\noffset {0}"; - private String limitOffsetTemplate = ""; - - private String limitTemplate = ""; - - private String offset = "\noffset "; - - private String offsetTemplate = ""; - private String on = "\non "; private String orderBy = "\norder by "; @@ -97,10 +86,6 @@ public class SQLTemplates extends Templates { private String where = "\nwhere "; - private boolean requiresWhereForPagingSymbols = false; - - private boolean pagingAfterOrder = true; - protected SQLTemplates() { // boolean add(Ops.AND, "{0} and {1}", 36); @@ -148,17 +133,95 @@ public class SQLTemplates extends Templates { class2type.put(String.class, "varchar"); } - public final Map, String> getClass2Type() { - return class2type; - } - - public final void addClass2TypeMappings(String type, Class... classes) { + public void addClass2TypeMappings(String type, Class... classes) { for (Class cl : classes) { class2type.put(cl, type); } } - public final SQLTemplates newLineToSingleSpace() { + public String getAsc() { + return asc; + } + + public Map, String> getClass2Type() { + return class2type; + } + + public String getColumnAlias() { + return columnAlias; + } + + public String getCount() { + return count; + } + + public String getCountStar() { + return countStar; + } + + public String getDeleteFrom() { + return deleteFrom; + } + + public String getDesc() { + return desc; + } + + public String getDistinctCountEnd() { + return distinctCountEnd; + } + + public String getDistinctCountStart() { + return distinctCountStart; + } + + public String getDummyTable() { + return dummyTable; + } + + public String getFrom() { + return from; + } + + public String getFullJoin() { + return fullJoin; + } + + public String getGroupBy() { + return groupBy; + } + + public String getHaving() { + return having; + } + + public String getInnerJoin() { + return innerJoin; + } + + public String getInsertInto() { + return insertInto; + } + + public String getJoin() { + return join; + } + + public String getJoinSymbol(JoinType joinType){ + switch (joinType) { + case FULLJOIN: return fullJoin; + case INNERJOIN: return innerJoin; + case JOIN: return join; + case LEFTJOIN: return leftJoin; + } + return ", "; + } + + public boolean isSupportsAlias() { + return true; + } + + public SQLTemplates newLineToSingleSpace() { for (Field field : SQLTemplates.class.getDeclaredFields()) { try { if (field.getType().equals(String.class)) { @@ -170,305 +233,183 @@ public class SQLTemplates extends Templates { } return this; } - - public final Expr getLimitOffsetCondition(@Nullable Long limit, @Nullable Long offset) { - if (offset == null) { - return CSimple.create(Object.class, limitTemplate, ENumberConst.create(limit)); - } else if (limit == null) { - return CSimple.create(Object.class, offsetTemplate, ENumberConst.create(offset)); - } else { - return CSimple.create(Object.class, limitOffsetTemplate, - ENumberConst.create(limit), - ENumberConst.create(offset), - ENumberConst.create(limit + offset)); + + public void serialize(QueryMetadata metadata, boolean forCountRow, SerializationContext context) { + context.serialize(metadata, forCountRow); + + if (!forCountRow && metadata.getModifiers().isRestricting()){ + serializeModifiers(metadata, context); + } + } + + protected void serializeModifiers(QueryMetadata metadata, SerializationContext context) { + QueryModifiers mod = metadata.getModifiers(); + if (mod.getLimit() != null) { + context.handle(limitTemplate, mod.getLimit()); + } + if (mod.getOffset() != null) { + context.handle(offsetTemplate, mod.getOffset()); } } - public final String getAsc() { - return asc; - } - - public final void setAsc(String asc) { + public void setAsc(String asc) { this.asc = asc; } - public final String getColumnAlias() { - return columnAlias; - } - - public final void setColumnAlias(String columnAlias) { + public void setColumnAlias(String columnAlias) { this.columnAlias = columnAlias; } - public final String getCount() { - return count; - } - - public final void setCount(String count) { + public void setCount(String count) { this.count = count; } - public final String getCountStar() { - return countStar; - } - - public final void setCountStar(String countStar) { + public void setCountStar(String countStar) { this.countStar = countStar; } - public final String getDistinctCountStart() { - return distinctCountStart; - } - - public final void setDistinctCountStart(String distinctCountStart) { - this.distinctCountStart = distinctCountStart; - } - - public final String getDistinctCountEnd() { - return distinctCountEnd; - } - - public final void setDistinctCountEnd(String distinctCountEnd) { - this.distinctCountEnd = distinctCountEnd; - } - - public final String getDeleteFrom() { - return deleteFrom; - } - - public final void setDeleteFrom(String deleteFrom) { + public void setDeleteFrom(String deleteFrom) { this.deleteFrom = deleteFrom; } - public final String getDesc() { - return desc; - } - - public final void setDesc(String desc) { + public void setDesc(String desc) { this.desc = desc; } - public final String getDummyTable() { - return dummyTable; + public void setDistinctCountEnd(String distinctCountEnd) { + this.distinctCountEnd = distinctCountEnd; } - public final void setDummyTable(String dummyTable) { + public void setDistinctCountStart(String distinctCountStart) { + this.distinctCountStart = distinctCountStart; + } + + public void setDummyTable(String dummyTable) { this.dummyTable = dummyTable; } - public final String getFrom() { - return from; - } - - public final void setFrom(String from) { + public void setFrom(String from) { this.from = from; } - public final String getFullJoin() { - return fullJoin; - } - - public final void setFullJoin(String fullJoin) { + public void setFullJoin(String fullJoin) { this.fullJoin = fullJoin; } - public final String getGroupBy() { - return groupBy; - } - - public final void setGroupBy(String groupBy) { + public void setGroupBy(String groupBy) { this.groupBy = groupBy; } - public final String getHaving() { - return having; - } - - public final void setHaving(String having) { + public void setHaving(String having) { this.having = having; } - public final String getInnerJoin() { - return innerJoin; - } - - public final void setInnerJoin(String innerJoin) { + public void setInnerJoin(String innerJoin) { this.innerJoin = innerJoin; } - public final String getJoin() { - return join; - } - - public final void setJoin(String join) { - this.join = join; - } - - public final String getLeftJoin() { - return leftJoin; - } - - public final void setLeftJoin(String leftJoin) { - this.leftJoin = leftJoin; - } - - public final String getLimit() { - return limit; - } - - public final void setLimit(String limit) { - this.limit = limit; - } - - public final boolean isLimitAndOffsetSymbols() { - return limitAndOffsetSymbols; - } - - public final void setLimitAndOffsetSymbols(boolean limitAndOffsetSymbols) { - this.limitAndOffsetSymbols = limitAndOffsetSymbols; - } - - public final String getLimitOffsetTemplate() { - return limitOffsetTemplate; - } - - public final void setLimitOffsetTemplate(String limitOffsetTemplate) { - this.limitOffsetTemplate = limitOffsetTemplate; - } - - public final String getLimitTemplate() { - return limitTemplate; - } - - public final void setLimitTemplate(String limitTemplate) { - this.limitTemplate = limitTemplate; - } - - public final String getOffset() { - return offset; - } - - public final void setOffset(String offset) { - this.offset = offset; - } - - public final String getOffsetTemplate() { - return offsetTemplate; - } - - public final void setOffsetTemplate(String offsetTemplate) { - this.offsetTemplate = offsetTemplate; - } - - public final String getOn() { - return on; - } - - public final void setOn(String on) { - this.on = on; - } - - public final String getOrderBy() { - return orderBy; - } - - public final void setOrderBy(String orderBy) { - this.orderBy = orderBy; - } - - public final String getSelect() { - return select; - } - - public final void setSelect(String select) { - this.select = select; - } - - public final String getSelectDistinct() { - return selectDistinct; - } - - public final void setSelectDistinct(String selectDistinct) { - this.selectDistinct = selectDistinct; - } - - public final String getTableAlias() { - return tableAlias; - } - - public final void setTableAlias(String tableAlias) { - this.tableAlias = tableAlias; - } - - public final String getUnion() { - return union; - } - - public final void setUnion(String union) { - this.union = union; - } - - public final String getUpdate() { - return update; - } - - public final void setUpdate(String update) { - this.update = update; - } - - public final String getValues() { - return values; - } - - public final void setValues(String values) { - this.values = values; - } - - public final String getWhere() { - return where; - } - - public final void setWhere(String where) { - this.where = where; - } - - public final boolean isSupportsAlias() { - return true; - } - - public final String getInsertInto() { - return insertInto; - } - - public final void setInsertInto(String insertInto) { + public void setInsertInto(String insertInto) { this.insertInto = insertInto; } - public final String getJoinSymbol(JoinType joinType){ - switch (joinType) { - case FULLJOIN: return fullJoin; - case INNERJOIN: return innerJoin; - case JOIN: return join; - case LEFTJOIN: return leftJoin; - } - return ", "; + public void setJoin(String join) { + this.join = join; } - public final boolean isRequiresWhereForPagingSymbols() { - return requiresWhereForPagingSymbols; + public void setLeftJoin(String leftJoin) { + this.leftJoin = leftJoin; } - public final void setRequiresWhereForPagingSymbols( - boolean requiresWhereForPagingSymbols) { - this.requiresWhereForPagingSymbols = requiresWhereForPagingSymbols; + public void setOffsetTemplate(String offsetTemplate) { + this.offsetTemplate = offsetTemplate; } - public final boolean isPagingAfterOrder() { - return pagingAfterOrder; + public void setOn(String on) { + this.on = on; } - public final void setPagingAfterOrder(boolean pagingAfterOrder) { - this.pagingAfterOrder = pagingAfterOrder; + public void setOrderBy(String orderBy) { + this.orderBy = orderBy; } + public void setSelect(String select) { + this.select = select; + } + + public void setSelectDistinct(String selectDistinct) { + this.selectDistinct = selectDistinct; + } + + public void setTableAlias(String tableAlias) { + this.tableAlias = tableAlias; + } + + public void setUnion(String union) { + this.union = union; + } + + public void setUpdate(String update) { + this.update = update; + } + + public void setValues(String values) { + this.values = values; + } + + public void setWhere(String where) { + this.where = where; + } + + public Map, String> getClass2type() { + return class2type; + } + + public String getLeftJoin() { + return leftJoin; + } + + public String getLimitTemplate() { + return limitTemplate; + } + + public String getOffsetTemplate() { + return offsetTemplate; + } + + public String getOn() { + return on; + } + + public String getOrderBy() { + return orderBy; + } + + public String getSelect() { + return select; + } + + public String getSelectDistinct() { + return selectDistinct; + } + + public String getTableAlias() { + return tableAlias; + } + + public String getUnion() { + return union; + } + + public String getUpdate() { + return update; + } + + public String getValues() { + return values; + } + + public String getWhere() { + return where; + } + } diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/SerializationContext.java b/querydsl-sql/src/main/java/com/mysema/query/sql/SerializationContext.java new file mode 100644 index 000000000..a92f50081 --- /dev/null +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/SerializationContext.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2010 Mysema Ltd. + * All rights reserved. + * + */ +package com.mysema.query.sql; + + +import com.mysema.query.QueryMetadata; + +/** + * @author tiwe + * + */ +public interface SerializationContext { + + /** + * @param metadata + * @param forCountRow + */ + void serialize(QueryMetadata metadata, boolean forCountRow); + + /** + * @param str + */ + SerializationContext append(String str); + + /** + * @param string + * @param offset + */ + void handle(String template, Object... args); + +} diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/mssql/SQLServerGrammar.java b/querydsl-sql/src/main/java/com/mysema/query/sql/mssql/SQLServerGrammar.java index 6c27686dc..22e457ee4 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/mssql/SQLServerGrammar.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/mssql/SQLServerGrammar.java @@ -7,6 +7,12 @@ package com.mysema.query.sql.mssql; import com.mysema.query.types.path.PNumber; +/** + * Convenience functions and constants for SQL Server usage + * + * @author tiwe + * + */ public final class SQLServerGrammar { private SQLServerGrammar(){} diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/oracle/OracleGrammar.java b/querydsl-sql/src/main/java/com/mysema/query/sql/oracle/OracleGrammar.java index 9d06d4cb3..551f8d498 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/oracle/OracleGrammar.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/oracle/OracleGrammar.java @@ -14,7 +14,7 @@ import com.mysema.query.types.path.PDate; import com.mysema.query.types.path.PNumber; /** - * OracleGrammar provides Oracle specific extensions to the SqlGrammar + * Convenience functions and constants for Oracle DB usage * * @author tiwe * @version $Id$ @@ -22,17 +22,13 @@ import com.mysema.query.types.path.PNumber; public final class OracleGrammar { private OracleGrammar(){} - - // global columns - + public static final ENumber level = new PNumber(Integer.class, "level"); public static final ENumber rownum = new PNumber(Integer.class, "rownum"); - + public static final EDate sysdate = new PDate(Date.class, "sysdate"); - // custom functions - public static > SumOver sumOver(Expr expr) { return new SumOver(expr); } diff --git a/querydsl-sql/src/test/java/com/mysema/query/DeleteBaseTest.java b/querydsl-sql/src/test/java/com/mysema/query/DeleteBaseTest.java index a7a38d524..68cbda024 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/DeleteBaseTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/DeleteBaseTest.java @@ -25,7 +25,7 @@ public abstract class DeleteBaseTest extends AbstractBaseTest{ @Test @ExcludeIn(MYSQL) - public void delete() throws SQLException{ + public void test() throws SQLException{ try{ // TODO : FIXME long count = query().from(survey).count(); diff --git a/querydsl-sql/src/test/java/com/mysema/query/SelectBaseTest.java b/querydsl-sql/src/test/java/com/mysema/query/SelectBaseTest.java index 9f678d422..fabdbfa1b 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/SelectBaseTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/SelectBaseTest.java @@ -11,7 +11,11 @@ import static com.mysema.query.Constants.employee2; import static com.mysema.query.Constants.survey; import static com.mysema.query.Constants.survey2; import static com.mysema.query.Constants.time; -import static com.mysema.query.Target.*; +import static com.mysema.query.Target.DERBY; +import static com.mysema.query.Target.HSQLDB; +import static com.mysema.query.Target.MYSQL; +import static com.mysema.query.Target.ORACLE; +import static com.mysema.query.Target.SQLSERVER; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -41,7 +45,6 @@ import com.mysema.query.types.expr.Expr; import com.mysema.query.types.query.ObjectSubQuery; import com.mysema.query.types.query.SubQuery; import com.mysema.testutil.ExcludeIn; -import com.mysema.testutil.IncludeIn; import com.mysema.testutil.Label; public abstract class SelectBaseTest extends AbstractBaseTest{ @@ -147,67 +150,44 @@ public abstract class SelectBaseTest extends AbstractBaseTest{ @Test public void limitAndOffset() throws SQLException { // limit - query().from(employee).limit(4).list(employee.id); + query().from(employee) + .orderBy(employee.firstname.asc()) + .limit(4).list(employee.id); // limit and offset - query().from(employee).limit(4).offset(3).list(employee.id); + query().from(employee) + .orderBy(employee.firstname.asc()) + .limit(4).offset(3).list(employee.id); } - @Test - @ExcludeIn({HSQLDB,MYSQL}) - public void offsetOnly(){ - // offset - query().from(employee).offset(3).list(employee.id); - } - @Test @ExcludeIn({ORACLE,DERBY,SQLSERVER}) - public void limitAndOffset2() throws SQLException { + public void limitAndOffset2() throws SQLException { + // limit + expectedQuery = "select e.id from employee2 e limit ?"; + query().from(employee).limit(4).list(employee.id); + // limit offset - expectedQuery = "select e.id from employee2 e limit 4 offset 3"; + expectedQuery = "select e.id from employee2 e limit ? offset ?"; query().from(employee).limit(4).offset(3).list(employee.id); - // limit - expectedQuery = "select e.id from employee2 e limit 4"; - query().from(employee).limit(4).list(employee.id); - - // offset -// expectedQuery = "select employee.id from employee2 employee offset 3"; -// query().from(employee).offset(3).list(employee.id); - } - - @Test - @IncludeIn(DERBY) - public void limitAndOffsetInDerby() throws SQLException { - expectedQuery = "select e.id from employee2 e offset 3 rows fetch next 4 rows only"; - query().from(employee).limit(4).offset(3).list(employee.id); - - // limit - expectedQuery = "select e.id from employee2 e fetch first 4 rows only"; - query().from(employee).limit(4).list(employee.id); - - // offset - expectedQuery = "select e.id from employee2 e offset 3 rows"; - query().from(employee).offset(3).list(employee.id); - } @Test - @IncludeIn(ORACLE) - public void limitAndOffsetInOracle() throws SQLException { - String prefix = "select e.id from employee2 e "; - + public void limitAndOffsetAndOrder(){ // limit - expectedQuery = prefix + "where rownum < ?"; - query().from(employee).limit(4).list(employee.id); - - // offset - expectedQuery = prefix + "where rownum > ?"; - query().from(employee).offset(3).list(employee.id); - - // limit offset - expectedQuery = prefix + "where rownum between ? and ?"; - query().from(employee).limit(4).offset(3).list(employee.id); + List names1 = Arrays.asList("Barbara","Daisy","Helen","Jennifer"); + assertEquals(names1, query().from(employee) + .orderBy(employee.firstname.asc()) + .limit(4) + .list(employee.firstname)); + + // limit + offset + List names2 = Arrays.asList("Helen","Jennifer","Jim","Joe"); + assertEquals(names2, query().from(employee) + .orderBy(employee.firstname.asc()) + .limit(4).offset(2) + .list(employee.firstname)); } @SuppressWarnings("unchecked") @@ -231,6 +211,15 @@ public abstract class SelectBaseTest extends AbstractBaseTest{ } } + @Test + @ExcludeIn({HSQLDB,MYSQL}) + public void offsetOnly(){ + // offset + query().from(employee) + .orderBy(employee.firstname.asc()) + .offset(3).list(employee.id); + } + @Test public void projection() throws IOException{ CloseableIterator results = query().from(survey).iterate(survey.all()); diff --git a/querydsl-sql/src/test/java/com/mysema/query/UpdateBaseTest.java b/querydsl-sql/src/test/java/com/mysema/query/UpdateBaseTest.java index 823c38795..2ae0a0a0f 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/UpdateBaseTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/UpdateBaseTest.java @@ -20,7 +20,7 @@ public abstract class UpdateBaseTest extends AbstractBaseTest{ } @Test - public void testUpdate(){ + public void test(){ // original state long count = query().from(survey).count(); assertEquals(0, query().from(survey).where(survey.name.eq("S")).count()); diff --git a/querydsl-sql/src/test/java/com/mysema/query/_derby/SelectDerbyTest.java b/querydsl-sql/src/test/java/com/mysema/query/_derby/SelectDerbyTest.java index 4a6c618fe..202a18a32 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/_derby/SelectDerbyTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/_derby/SelectDerbyTest.java @@ -5,8 +5,13 @@ */ package com.mysema.query._derby; +import static com.mysema.query.Constants.employee; + +import java.sql.SQLException; + import org.junit.Before; import org.junit.BeforeClass; +import org.junit.Test; import org.junit.runner.RunWith; import com.mysema.query.Connections; @@ -30,4 +35,19 @@ public class SelectDerbyTest extends SelectBaseTest { dialect = new DerbyTemplates().newLineToSingleSpace(); } + @Test + public void limitAndOffsetInDerby() throws SQLException { + expectedQuery = "select e.id from employee2 e offset 3 rows fetch next 4 rows only"; + query().from(employee).limit(4).offset(3).list(employee.id); + + // limit + expectedQuery = "select e.id from employee2 e fetch first 4 rows only"; + query().from(employee).limit(4).list(employee.id); + + // offset + expectedQuery = "select e.id from employee2 e offset 3 rows"; + query().from(employee).offset(3).list(employee.id); + + } + } diff --git a/querydsl-sql/src/test/java/com/mysema/query/_mssql/SelectMSSQLTest.java b/querydsl-sql/src/test/java/com/mysema/query/_mssql/SelectMSSQLTest.java index 2c7840e4d..4ac63d613 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/_mssql/SelectMSSQLTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/_mssql/SelectMSSQLTest.java @@ -47,7 +47,7 @@ public class SelectMSSQLTest extends SelectBaseTest { } @Test - public void testPaging(){ + public void manualPaging(){ RowNumber rowNumber = rowNumber().orderBy(employee.lastname.asc()).as(rn); // TODO : create a short cut for wild card Expr all = CSimple.create(Object[].class, "*"); diff --git a/querydsl-sql/src/test/java/com/mysema/query/_oracle/SelectOracleTest.java b/querydsl-sql/src/test/java/com/mysema/query/_oracle/SelectOracleTest.java index 549905607..480fc5993 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/_oracle/SelectOracleTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/_oracle/SelectOracleTest.java @@ -44,6 +44,21 @@ public class SelectOracleTest extends SelectBaseTest { dialect = new OracleTemplates().newLineToSingleSpace(); } + @Test + public void limitAndOffsetInOracle() throws SQLException { + // limit + expectedQuery = "select * from ( select e.id from employee2 e ) where rownum <= ?"; + query().from(employee).limit(4).list(employee.id); + + // offset + expectedQuery = "select * from ( select a.*, rownum rn from ( select e.id from employee2 e ) a) where rn > ?"; + query().from(employee).offset(3).list(employee.id); + + // limit offset + expectedQuery = "select * from ( select a.*, rownum rn from ( select e.id from employee2 e ) a) where rn > 3 and rn <= 7"; + query().from(employee).limit(4).offset(3).list(employee.id); + } + @Test public void connectByPrior() throws SQLException{ diff --git a/querydsl-sql/src/test/java/com/mysema/query/sql/SQLTemplatesTest.java b/querydsl-sql/src/test/java/com/mysema/query/sql/SQLTemplatesTest.java index a8b4b6e0f..d985120b4 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/sql/SQLTemplatesTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/sql/SQLTemplatesTest.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) 2010 Mysema Ltd. + * All rights reserved. + * + */ package com.mysema.query.sql; import static org.junit.Assert.assertEquals;