diff --git a/README.md b/README.md index 85e7334ec..1d326bf5c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## Querydsl -Querydsl is a framework which enables the construction of type-safe SQL-like queries for multiple backends including JPA, JDO and SQL in Java. +Querydsl is a framework which enables the construction of type-safe SQL-like queries for multiple backends including JPA, MongoDB and SQL in Java. Instead of writing queries as inline strings or externalizing them into XML files they are constructed via a fluent API. diff --git a/querydsl-apt/pom.xml b/querydsl-apt/pom.xml index 5c00fae78..5649492af 100644 --- a/querydsl-apt/pom.xml +++ b/querydsl-apt/pom.xml @@ -5,7 +5,7 @@ com.mysema.querydsl querydsl-root - 3.3.2.BUILD-SNAPSHOT + 3.3.3.BUILD-SNAPSHOT ../querydsl-root/pom.xml diff --git a/querydsl-apt/src/main/java/com/mysema/query/apt/jpa/JPAConfiguration.java b/querydsl-apt/src/main/java/com/mysema/query/apt/jpa/JPAConfiguration.java index 5404d5dc0..2604890eb 100644 --- a/querydsl-apt/src/main/java/com/mysema/query/apt/jpa/JPAConfiguration.java +++ b/querydsl-apt/src/main/java/com/mysema/query/apt/jpa/JPAConfiguration.java @@ -24,6 +24,7 @@ import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; +import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Types; import javax.persistence.Access; @@ -133,12 +134,22 @@ public class JPAConfiguration extends DefaultConfiguration { } mirror = TypeUtils.getAnnotationMirrorOfType(element, OneToMany.class); + if (mirror == null) { + mirror = TypeUtils.getAnnotationMirrorOfType(element, ManyToMany.class); + } if (mirror != null) { TypeMirror typeArg = TypeUtils.getAnnotationValueAsTypeMirror(mirror, "targetEntity"); TypeMirror erasure = types.erasure(element.asType()); TypeElement typeElement = (TypeElement) types.asElement(erasure); if (typeElement != null && typeArg != null) { - return types.getDeclaredType(typeElement, typeArg); + if (typeElement.getTypeParameters().size() == 1) { + return types.getDeclaredType(typeElement, typeArg); + } else if (typeElement.getTypeParameters().size() == 2) { + if (element.asType() instanceof DeclaredType) { + TypeMirror first = ((DeclaredType)element.asType()).getTypeArguments().get(0); + return types.getDeclaredType(typeElement, first, typeArg); + } + } } } diff --git a/querydsl-apt/src/test/java/com/mysema/query/apt/GenericExporterTest.java b/querydsl-apt/src/test/java/com/mysema/query/apt/GenericExporterTest.java index 7c68296d4..5cb062013 100644 --- a/querydsl-apt/src/test/java/com/mysema/query/apt/GenericExporterTest.java +++ b/querydsl-apt/src/test/java/com/mysema/query/apt/GenericExporterTest.java @@ -93,6 +93,9 @@ public class GenericExporterTest extends AbstractProcessorTest { expected.add("QGeneric4Test_HidaBezGruppe.java"); expected.add("QInterfaceType2Test_UserImpl.java"); expected.add("QOrderTest_Order.java"); + expected.add("QManagedEmailTest_ManagedEmails.java"); + expected.add("QGeneric12Test_ChannelRole.java"); + expected.add("QManyToManyTest_Person.java"); execute(expected, "GenericExporterTest2", "HibernateAnnotationProcessor"); } diff --git a/querydsl-apt/src/test/java/com/mysema/query/domain/Generic12Test.java b/querydsl-apt/src/test/java/com/mysema/query/domain/Generic12Test.java index 1263919e6..d2b1e59e7 100644 --- a/querydsl-apt/src/test/java/com/mysema/query/domain/Generic12Test.java +++ b/querydsl-apt/src/test/java/com/mysema/query/domain/Generic12Test.java @@ -1,6 +1,6 @@ package com.mysema.query.domain; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; import java.util.List; @@ -15,7 +15,7 @@ import org.junit.Test; import com.google.common.collect.Lists; public class Generic12Test { - + @Entity @Inheritance @DiscriminatorColumn(name = "CONTEXT") @@ -58,10 +58,10 @@ public class Generic12Test { public static class SubjectRole extends Role { // missing type param, should be Role // some constructors } - + @Test public void test() { - assertEquals(QGeneric12Test_ChannelPermission.class, + assertEquals(QGeneric12Test_Permission.class, QGeneric12Test_ChannelRole.channelRole.permissions.get(0).getClass()); assertEquals(QGeneric12Test_Permission.class, QGeneric12Test_SubjectRole.subjectRole.permissions.get(0).getClass()); diff --git a/querydsl-apt/src/test/java/com/mysema/query/domain/ManagedEmailTest.java b/querydsl-apt/src/test/java/com/mysema/query/domain/ManagedEmailTest.java new file mode 100644 index 000000000..09541eaef --- /dev/null +++ b/querydsl-apt/src/test/java/com/mysema/query/domain/ManagedEmailTest.java @@ -0,0 +1,41 @@ +package com.mysema.query.domain; + +import static org.junit.Assert.assertEquals; + +import java.util.Map; + +import javax.persistence.Entity; +import javax.persistence.MapKey; +import javax.persistence.OneToMany; + +import org.junit.Test; + +public class ManagedEmailTest { + + public interface ManagedEmail { + + } + + public enum EmailType { WORK, HOME } + + @Entity + public static class ManagedEmailImpl implements ManagedEmail { + + } + + @Entity + public static class ManagedEmails { + + @OneToMany(targetEntity = ManagedEmailImpl.class) + @MapKey(name = "emailType") + private Map emails; + + } + + @Test + public void test() { + assertEquals(EmailType.class, QManagedEmailTest_ManagedEmails.managedEmails.emails.getKeyType()); + assertEquals(ManagedEmailImpl.class, QManagedEmailTest_ManagedEmails.managedEmails.emails.getValueType()); + } + +} diff --git a/querydsl-apt/src/test/java/com/mysema/query/domain/ManyToManyTest.java b/querydsl-apt/src/test/java/com/mysema/query/domain/ManyToManyTest.java new file mode 100644 index 000000000..49753dfe2 --- /dev/null +++ b/querydsl-apt/src/test/java/com/mysema/query/domain/ManyToManyTest.java @@ -0,0 +1,35 @@ +package com.mysema.query.domain; + +import static org.junit.Assert.assertEquals; + +import java.util.Set; + +import javax.persistence.Entity; +import javax.persistence.ManyToMany; + +import org.junit.Test; + +public class ManyToManyTest { + + public interface PhoneNumber { + + } + + @Entity + public static class PhoneNumberImpl { + + } + + @Entity + public static class Person { + + @ManyToMany(targetEntity=PhoneNumberImpl.class) + Set phones; + } + + @Test + public void test() { + assertEquals(PhoneNumberImpl.class, QManyToManyTest_Person.person.phones.getElementType()); + } + +} diff --git a/querydsl-codegen/pom.xml b/querydsl-codegen/pom.xml index 1cf9dae59..6da6fb496 100644 --- a/querydsl-codegen/pom.xml +++ b/querydsl-codegen/pom.xml @@ -5,7 +5,7 @@ com.mysema.querydsl querydsl-root - 3.3.2.BUILD-SNAPSHOT + 3.3.3.BUILD-SNAPSHOT ../querydsl-root/pom.xml diff --git a/querydsl-codegen/src/main/java/com/mysema/query/codegen/EntitySerializer.java b/querydsl-codegen/src/main/java/com/mysema/query/codegen/EntitySerializer.java index 9b1599e71..09bdaee3a 100644 --- a/querydsl-codegen/src/main/java/com/mysema/query/codegen/EntitySerializer.java +++ b/querydsl-codegen/src/main/java/com/mysema/query/codegen/EntitySerializer.java @@ -13,67 +13,25 @@ */ package com.mysema.query.codegen; -import static com.mysema.codegen.Symbols.ASSIGN; -import static com.mysema.codegen.Symbols.COMMA; -import static com.mysema.codegen.Symbols.DOT; -import static com.mysema.codegen.Symbols.EMPTY; -import static com.mysema.codegen.Symbols.NEW; -import static com.mysema.codegen.Symbols.QUOTE; -import static com.mysema.codegen.Symbols.RETURN; -import static com.mysema.codegen.Symbols.SEMICOLON; -import static com.mysema.codegen.Symbols.STAR; -import static com.mysema.codegen.Symbols.SUPER; -import static com.mysema.codegen.Symbols.THIS; -import static com.mysema.codegen.Symbols.UNCHECKED; - -import java.io.IOException; -import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import javax.annotation.Generated; -import javax.inject.Inject; -import javax.inject.Named; - import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.mysema.codegen.CodeWriter; -import com.mysema.codegen.model.ClassType; -import com.mysema.codegen.model.Constructor; -import com.mysema.codegen.model.Parameter; -import com.mysema.codegen.model.SimpleType; -import com.mysema.codegen.model.Type; -import com.mysema.codegen.model.TypeCategory; -import com.mysema.codegen.model.TypeExtends; -import com.mysema.codegen.model.Types; -import com.mysema.query.types.ConstructorExpression; -import com.mysema.query.types.Expression; -import com.mysema.query.types.Path; -import com.mysema.query.types.PathMetadata; -import com.mysema.query.types.PathMetadataFactory; +import com.mysema.codegen.model.*; +import com.mysema.query.types.*; import com.mysema.query.types.expr.ComparableExpression; import com.mysema.query.types.expr.SimpleExpression; -import com.mysema.query.types.path.ArrayPath; -import com.mysema.query.types.path.BooleanPath; -import com.mysema.query.types.path.CollectionPath; -import com.mysema.query.types.path.ComparablePath; -import com.mysema.query.types.path.DatePath; -import com.mysema.query.types.path.DateTimePath; -import com.mysema.query.types.path.EntityPathBase; -import com.mysema.query.types.path.EnumPath; -import com.mysema.query.types.path.ListPath; -import com.mysema.query.types.path.MapPath; -import com.mysema.query.types.path.NumberPath; -import com.mysema.query.types.path.PathInits; -import com.mysema.query.types.path.SetPath; -import com.mysema.query.types.path.SimplePath; -import com.mysema.query.types.path.StringPath; -import com.mysema.query.types.path.TimePath; +import com.mysema.query.types.path.*; + +import javax.annotation.Generated; +import javax.inject.Inject; +import javax.inject.Named; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.util.*; + +import static com.mysema.codegen.Symbols.*; /** * EntitySerializer is a {@link Serializer} implementation for entity types @@ -371,6 +329,7 @@ public class EntitySerializer implements Serializer { protected void introFactoryMethods(CodeWriter writer, final EntityType model) throws IOException { String localName = writer.getRawName(model); String genericName = writer.getGenericName(true, model); + Set sizes = Sets.newHashSet(); for (Constructor c : model.getConstructors()) { // begin @@ -378,12 +337,21 @@ public class EntitySerializer implements Serializer { writer.suppressWarnings(UNCHECKED); } Type returnType = new ClassType(ConstructorExpression.class, model); + final boolean asExpr = sizes.add(c.getParameters().size()); writer.beginStaticMethod(returnType, "create", c.getParameters(), new Function() { @Override public Parameter apply(Parameter p) { - return new Parameter(p.getName(), typeMappings.getExprType( - p.getType(), model, false, false, true)); + Type type; + if (!asExpr) { + type = typeMappings.getExprType( + p.getType(), model, false, false, true); + } else if (p.getType().isFinal()) { + type = new ClassType(Expression.class, p.getType()); + } else { + type = new ClassType(Expression.class, new TypeExtends(p.getType())); + } + return new Parameter(p.getName(), type); } }); diff --git a/querydsl-codegen/src/main/java/com/mysema/query/codegen/ProjectionSerializer.java b/querydsl-codegen/src/main/java/com/mysema/query/codegen/ProjectionSerializer.java index ecadc65f9..8a7fa9f8e 100644 --- a/querydsl-codegen/src/main/java/com/mysema/query/codegen/ProjectionSerializer.java +++ b/querydsl-codegen/src/main/java/com/mysema/query/codegen/ProjectionSerializer.java @@ -13,21 +13,18 @@ */ package com.mysema.query.codegen; -import java.io.IOException; +import com.google.common.base.Function; +import com.google.common.collect.Sets; +import com.mysema.codegen.CodeWriter; +import com.mysema.codegen.model.*; +import com.mysema.query.types.ConstructorExpression; +import com.mysema.query.types.Expression; +import com.mysema.query.types.expr.NumberExpression; import javax.annotation.Generated; import javax.inject.Inject; - -import com.google.common.base.Function; -import com.mysema.codegen.CodeWriter; -import com.mysema.codegen.model.ClassType; -import com.mysema.codegen.model.Constructor; -import com.mysema.codegen.model.Parameter; -import com.mysema.codegen.model.Type; -import com.mysema.codegen.model.TypeCategory; -import com.mysema.codegen.model.Types; -import com.mysema.query.types.ConstructorExpression; -import com.mysema.query.types.expr.NumberExpression; +import java.io.IOException; +import java.util.Set; /** * ProjectionSerializer is a {@link Serializer} implementation for projection types @@ -60,7 +57,7 @@ public final class ProjectionSerializer implements Serializer{ // imports writer.imports(NumberExpression.class.getPackage()); - writer.imports(ConstructorExpression.class, Generated.class); + writer.imports(Expression.class, ConstructorExpression.class, Generated.class); // javadoc writer.javadoc(queryType + " is a Querydsl Projection type for " + simpleName); @@ -85,14 +82,24 @@ public final class ProjectionSerializer implements Serializer{ intro(model, writer); String localName = writer.getRawName(model); + Set sizes = Sets.newHashSet(); for (Constructor c : model.getConstructors()) { + final boolean asExpr = sizes.add(c.getParameters().size()); // begin writer.beginConstructor(c.getParameters(), new Function() { @Override public Parameter apply(Parameter p) { - return new Parameter(p.getName(), typeMappings.getExprType(p.getType(), - model, false, false, true)); + Type type; + if (!asExpr) { + type = typeMappings.getExprType(p.getType(), + model, false, false, true); + } else if (p.getType().isFinal()) { + type = new ClassType(Expression.class, p.getType()); + } else { + type = new ClassType(Expression.class, new TypeExtends(p.getType())); + } + return new Parameter(p.getName(), type); } }); diff --git a/querydsl-codegen/src/main/java/com/mysema/query/codegen/Property.java b/querydsl-codegen/src/main/java/com/mysema/query/codegen/Property.java index 9dff65a09..ee4ec7c30 100644 --- a/querydsl-codegen/src/main/java/com/mysema/query/codegen/Property.java +++ b/querydsl-codegen/src/main/java/com/mysema/query/codegen/Property.java @@ -75,7 +75,12 @@ public final class Property implements Comparable { @Override public int compareTo(Property o) { - return name.compareToIgnoreCase(o.getName()); + int rv = name.compareToIgnoreCase(o.getName()); + if (rv == 0) { + return name.compareTo(o.getName()); + } else { + return rv; + } } public Property createCopy(EntityType targetModel) { diff --git a/querydsl-codegen/src/test/java/com/mysema/query/codegen/ProjectionSerializerTest.java b/querydsl-codegen/src/test/java/com/mysema/query/codegen/ProjectionSerializerTest.java index 569955f09..b30990ce8 100644 --- a/querydsl-codegen/src/test/java/com/mysema/query/codegen/ProjectionSerializerTest.java +++ b/querydsl-codegen/src/test/java/com/mysema/query/codegen/ProjectionSerializerTest.java @@ -13,22 +13,16 @@ */ package com.mysema.query.codegen; -import static org.junit.Assert.*; +import com.mysema.codegen.JavaWriter; +import com.mysema.codegen.model.*; +import org.junit.Test; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import java.util.Arrays; -import org.junit.Test; - -import com.mysema.codegen.JavaWriter; -import com.mysema.codegen.model.Constructor; -import com.mysema.codegen.model.Parameter; -import com.mysema.codegen.model.SimpleType; -import com.mysema.codegen.model.Type; -import com.mysema.codegen.model.TypeCategory; -import com.mysema.codegen.model.Types; +import static org.junit.Assert.assertTrue; public class ProjectionSerializerTest { @@ -47,9 +41,9 @@ public class ProjectionSerializerTest { Writer writer = new StringWriter(); ProjectionSerializer serializer = new ProjectionSerializer(new JavaTypeMappings()); serializer.serialize(type, SimpleSerializerConfig.DEFAULT, new JavaWriter(writer)); - assertTrue(writer.toString().contains("StringExpression firstName")); - assertTrue(writer.toString().contains("StringExpression lastName")); - assertTrue(writer.toString().contains("NumberExpression age")); + assertTrue(writer.toString().contains("Expression firstName")); + assertTrue(writer.toString().contains("Expression lastName")); + assertTrue(writer.toString().contains("Expression age")); } } diff --git a/querydsl-collections/README.md b/querydsl-collections/README.md index 53fcf9678..f12e0192e 100644 --- a/querydsl-collections/README.md +++ b/querydsl-collections/README.md @@ -1,4 +1,4 @@ -# Querydsl Collections # +## Querydsl Collections The Collections module provides integration with Java Collections and Beans. diff --git a/querydsl-collections/pom.xml b/querydsl-collections/pom.xml index 3137b7566..f752ca1b4 100644 --- a/querydsl-collections/pom.xml +++ b/querydsl-collections/pom.xml @@ -5,7 +5,7 @@ com.mysema.querydsl querydsl-root - 3.3.2.BUILD-SNAPSHOT + 3.3.3.BUILD-SNAPSHOT ../querydsl-root/pom.xml diff --git a/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryFunctions.java b/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryFunctions.java index fd595004c..7282196f4 100644 --- a/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryFunctions.java +++ b/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryFunctions.java @@ -25,6 +25,7 @@ import java.util.Set; import javax.annotation.Nullable; +import com.google.common.base.Objects; import com.mysema.query.types.Expression; import com.mysema.query.types.Operator; import com.mysema.query.types.Ops; @@ -79,8 +80,22 @@ public final class CollQueryFunctions { private static final List nullList = Arrays.asList((Object)null); + public static boolean equals(Object o1, Object o2) { + return Objects.equal(o1, o2); + } + + public static > int compareTo(T c1, T c2) { + if (c1 == null) { + return c2 == null ? 0 : -1; + } else if (c2 == null) { + return 1; + } else { + return c1.compareTo(c2); + } + } + public static > boolean between(A a, A b, A c) { - return a.compareTo(b) >= 0 && a.compareTo(c) <= 0; + return compareTo(a, b) >= 0 && compareTo(a, c) <= 0; } public static double cot(double x) { diff --git a/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryMixin.java b/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryMixin.java index b0f8a7497..f52026f0e 100644 --- a/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryMixin.java +++ b/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryMixin.java @@ -1,6 +1,6 @@ /* * Copyright 2011, Mysema Ltd - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -24,13 +24,13 @@ import com.mysema.query.types.template.BooleanTemplate; /** * CollQueryMixin extends {@link QueryMixin} to provide normalization logic specific to this module - * + * * @author tiwe * * @param */ public class CollQueryMixin extends QueryMixin { - + private static final Predicate ANY = BooleanTemplate.create("any"); public CollQueryMixin() {} @@ -42,22 +42,22 @@ public class CollQueryMixin extends QueryMixin { public CollQueryMixin(T self, QueryMetadata metadata) { super(self, metadata); } - + @Override protected Predicate normalize(Predicate predicate, boolean where) { predicate = (Predicate)ExpressionUtils.extract(predicate); - if (predicate != null) { + if (predicate != null) { Context context = new Context(); Predicate transformed = (Predicate) predicate.accept(CollectionAnyVisitor.DEFAULT, context); for (int i = 0; i < context.paths.size(); i++) { - innerJoin( - (Path)context.paths.get(i).getMetadata().getParent(), + leftJoin( + (Path)context.paths.get(i).getMetadata().getParent(), (Path)context.replacements.get(i)); on(ANY); } - return transformed; + return transformed; } else { return predicate; } } -} +} diff --git a/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryTemplates.java b/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryTemplates.java index 2ae2bde78..c3315761b 100644 --- a/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryTemplates.java +++ b/querydsl-collections/src/main/java/com/mysema/query/collections/CollQueryTemplates.java @@ -29,16 +29,16 @@ public class CollQueryTemplates extends JavaTemplates { protected CollQueryTemplates() { String functions = CollQueryFunctions.class.getName(); - add(Ops.EQ, "{0}.equals({1})"); - add(Ops.NE, "!{0}.equals({1})"); + add(Ops.EQ, functions + ".equals({0}, {1})"); + add(Ops.NE, "!" + functions + ".equals({0}, {1})"); add(Ops.INSTANCE_OF, "{1}.isInstance({0})"); // Comparable - add(Ops.GT, "{0}.compareTo({1}) > 0"); - add(Ops.LT, "{0}.compareTo({1}) < 0"); - add(Ops.GOE, "{0}.compareTo({1}) >= 0"); - add(Ops.LOE, "{0}.compareTo({1}) <= 0"); - add(Ops.BETWEEN, functions + ".between({0},{1},{2})"); + add(Ops.GT, functions + ".compareTo({0}, {1}) > 0"); + add(Ops.LT, functions + ".compareTo({0}, {1}) < 0"); + add(Ops.GOE, functions + ".compareTo({0}, {1}) >= 0"); + add(Ops.LOE, functions + ".compareTo({0}, {1}) <= 0"); + add(Ops.BETWEEN, functions + ".between({0}, {1}, {2})"); add(Ops.STRING_CAST, "String.valueOf({0})"); // Number diff --git a/querydsl-collections/src/test/java/com/mysema/query/collections/Document.java b/querydsl-collections/src/test/java/com/mysema/query/collections/Document.java new file mode 100644 index 000000000..fc92b8dd9 --- /dev/null +++ b/querydsl-collections/src/test/java/com/mysema/query/collections/Document.java @@ -0,0 +1,31 @@ +package com.mysema.query.collections; + +import java.util.ArrayList; +import java.util.List; + +import com.mysema.query.annotations.QueryEntity; + +@QueryEntity +public class Document { + + private Long id; + + private List meshThesaurusTerms = new ArrayList(); + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public List getMeshThesaurusTerms() { + return meshThesaurusTerms; + } + + public void setMeshThesaurusTerms(List meshThesaurusTerms) { + this.meshThesaurusTerms = meshThesaurusTerms; + } + +} \ No newline at end of file diff --git a/querydsl-collections/src/test/java/com/mysema/query/collections/DocumentTest.java b/querydsl-collections/src/test/java/com/mysema/query/collections/DocumentTest.java new file mode 100644 index 000000000..cd85280c6 --- /dev/null +++ b/querydsl-collections/src/test/java/com/mysema/query/collections/DocumentTest.java @@ -0,0 +1,61 @@ +package com.mysema.query.collections; + +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.mysema.query.types.Predicate; + +public class DocumentTest { + + private Document doc1, doc2, doc3; + + private QDocument qDoc = QDocument.document; + + @Before + public void setUp() { + doc1 = new Document(); + doc1.setId(1L); + doc1.getMeshThesaurusTerms().add("x"); + + doc2 = new Document(); + doc2.setId(2L); + + doc3 = new Document(); + doc3.setId(3L); + } + + @Test + public void test1() { + Predicate crit = qDoc.id.eq(3L); + List expResult = CollQueryFactory.from(qDoc, doc1, doc2, doc3).where(crit).list(qDoc); + assertTrue(expResult.contains(doc3)); //ok + } + + @Test + public void test2() { + Predicate crit = qDoc.meshThesaurusTerms.any().eq("x"); + List expResult = CollQueryFactory.from(qDoc, doc1, doc2, doc3).where(crit).list(qDoc); + assertTrue(expResult.contains(doc1)); //ok + } + + @Test + public void test3() { + Predicate crit = qDoc.meshThesaurusTerms.any().eq("x").or(qDoc.id.eq(3L)); + List expResult = CollQueryFactory.from(qDoc, doc1, doc2, doc3).where(crit).list(qDoc); + assertTrue(expResult.contains(doc1)); + assertTrue(expResult.contains(doc3)); //fails, expResult contains only doc1, but should contain doc1 and doc3! + } + + @Test + public void test4() { + Predicate crit = qDoc.id.eq(3L).or(qDoc.meshThesaurusTerms.any().eq("x")); + List expResult = CollQueryFactory.from(qDoc, doc1, doc2, doc3).where(crit).list(qDoc); + assertTrue(expResult.contains(doc1)); + assertTrue(expResult.contains(doc3)); //fails, expResult contains only doc1, but should contain doc1 and doc3! + } + +} diff --git a/querydsl-core/pom.xml b/querydsl-core/pom.xml index 01dedc0c5..5dcc15370 100644 --- a/querydsl-core/pom.xml +++ b/querydsl-core/pom.xml @@ -5,7 +5,7 @@ com.mysema.querydsl querydsl-root - 3.3.2.BUILD-SNAPSHOT + 3.3.3.BUILD-SNAPSHOT ../querydsl-root/pom.xml diff --git a/querydsl-core/src/main/java/com/mysema/query/support/ReplaceVisitor.java b/querydsl-core/src/main/java/com/mysema/query/support/ReplaceVisitor.java new file mode 100644 index 000000000..82ea2e915 --- /dev/null +++ b/querydsl-core/src/main/java/com/mysema/query/support/ReplaceVisitor.java @@ -0,0 +1,161 @@ +/* + * Copyright 2014, Mysema Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.mysema.query.support; + +import com.google.common.collect.ImmutableList; +import com.mysema.query.*; +import com.mysema.query.types.*; +import com.mysema.query.types.template.BooleanTemplate; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; + +/** + * ReplaceVisitor is a deep visitor that can be customized to replace segments of + * expression trees + */ +public class ReplaceVisitor implements Visitor, Void> { + + @Override + public Expression visit(Constant expr, @Nullable Void context) { + return expr; + } + + @Override + public Expression visit(FactoryExpression expr, @Nullable Void context) { + List> args = visit(expr.getArgs()); + if (args.equals(expr.getArgs())) { + return expr; + } else { + return FactoryExpressionUtils.wrap(expr, args); + } + } + + @Override + public Expression visit(Operation expr, @Nullable Void context) { + ImmutableList> args = visit(expr.getArgs()); + if (args.equals(expr.getArgs())) { + return expr; + } else if (expr instanceof Predicate) { + return new PredicateOperation((Operator)expr.getOperator(), args); + } else { + return new OperationImpl(expr.getType(), expr.getOperator(), args); + } + } + + @Override + public Expression visit(ParamExpression expr, @Nullable Void context) { + return expr; + } + + @Override + public Expression visit(Path expr, @Nullable Void context) { + if (expr.getMetadata().isRoot()) { + return expr; + } else { + PathMetadata metadata = expr.getMetadata(); + Path parent = (Path)metadata.getParent().accept(this, null); + if (parent.equals(metadata.getParent())) { + return expr; + } else { + metadata = new PathMetadata(parent, metadata.getElement(), + metadata.getPathType()); + return new PathImpl(expr.getType(), metadata); + } + } + } + + @Override + public Expression visit(SubQueryExpression expr, @Nullable Void context) { + QueryMetadata md = new DefaultQueryMetadata(); + md.setDistinct(expr.getMetadata().isDistinct()); + md.setModifiers(expr.getMetadata().getModifiers()); + md.setUnique(expr.getMetadata().isUnique()); + for (QueryFlag flag : expr.getMetadata().getFlags()) { + md.addFlag(new QueryFlag(flag.getPosition(), flag.getFlag().accept(this, null))); + } + for (Expression e : expr.getMetadata().getGroupBy()) { + md.addGroupBy(e.accept(this, null)); + } + Predicate having = expr.getMetadata().getHaving(); + if (having != null) { + md.addHaving((Predicate)having.accept(this, null)); + } + for (JoinExpression je : expr.getMetadata().getJoins()) { + md.addJoin(je.getType(), je.getTarget().accept(this, null)); + if (je.getCondition() != null) { + md.addJoinCondition((Predicate)je.getCondition().accept(this, null)); + } + for (JoinFlag jf : je.getFlags()) { + md.addJoinFlag(new JoinFlag(jf.getFlag().accept(this, null), jf.getPosition())); + } + } + for (OrderSpecifier os : expr.getMetadata().getOrderBy()) { + OrderSpecifier os2 = new OrderSpecifier(os.getOrder(), os.getTarget().accept(this, + null)); + switch (os.getNullHandling()) { + case NullsFirst: os2 = os2.nullsFirst(); break; + case NullsLast: os2 = os2.nullsLast(); break; + } + md.addOrderBy(os2); + } + for (Map.Entry, Object> entry : expr.getMetadata().getParams() + .entrySet()) { + md.setParam((ParamExpression)entry.getKey().accept(this, null), entry.getValue()); + } + for (Expression e : expr.getMetadata().getProjection()) { + md.addProjection(e.accept(this, null)); + } + Predicate where = expr.getMetadata().getWhere(); + if (where != null) { + md.addWhere((Predicate)where.accept(this, null)); + } + if (expr.getMetadata().equals(md)) { + return expr; + } else { + return new SubQueryExpressionImpl(expr.getType(), md); + } + } + + @Override + public Expression visit(TemplateExpression expr, @Nullable Void context) { + ImmutableList.Builder builder = ImmutableList.builder(); + for (Object arg : expr.getArgs()) { + if (arg instanceof Expression) { + builder.add(((Expression)arg).accept(this, null)); + } else { + builder.add(arg); + } + } + ImmutableList args = builder.build(); + if (args.equals(expr.getArgs())) { + return expr; + } else { + if (expr instanceof Predicate) { + return BooleanTemplate.create(expr.getTemplate(), args); + } else { + return new TemplateExpressionImpl(expr.getType(), expr.getTemplate(), args); + } + } + } + + private ImmutableList> visit(List> args) { + ImmutableList.Builder> builder = ImmutableList.builder(); + for (Expression arg : args) { + builder.add(arg.accept(this, null)); + } + return builder.build(); + } +} diff --git a/querydsl-core/src/main/java/com/mysema/query/types/expr/CaseBuilder.java b/querydsl-core/src/main/java/com/mysema/query/types/expr/CaseBuilder.java index 9467b6049..cdf4a19fd 100644 --- a/querydsl-core/src/main/java/com/mysema/query/types/expr/CaseBuilder.java +++ b/querydsl-core/src/main/java/com/mysema/query/types/expr/CaseBuilder.java @@ -13,18 +13,17 @@ */ package com.mysema.query.types.expr; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.Nullable; - import com.mysema.query.types.ConstantImpl; import com.mysema.query.types.Expression; import com.mysema.query.types.NullExpression; import com.mysema.query.types.Ops; +import javax.annotation.Nullable; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.List; + /** * CaseBuilder enables the construction of typesafe case-when-then-else * constructs : @@ -164,8 +163,28 @@ public final class CaseBuilder { this.when = b; } - @SuppressWarnings("unchecked") public Cases> then(Expression expr) { + if (expr instanceof BooleanExpression) { + return (Cases) then((BooleanExpression) expr); + } else if (expr instanceof StringExpression) { + return (Cases) then((StringExpression) expr); + } else if (expr instanceof NumberExpression) { + return then((NumberExpression) expr); + } else if (expr instanceof DateExpression) { + return then((DateExpression) expr); + } else if (expr instanceof DateTimeExpression) { + return then((DateTimeExpression) expr); + } else if (expr instanceof TimeExpression) { + return then((TimeExpression) expr); + } else if (expr instanceof ComparableExpression) { + return then((ComparableExpression) expr); + } else { + return thenSimple(expr); + } + } + + @SuppressWarnings("unchecked") + private Cases> thenSimple(Expression expr) { return new Cases>((Class)expr.getType()) { @Override protected SimpleExpression createResult(Class type, Expression last) { @@ -176,12 +195,12 @@ public final class CaseBuilder { } public Cases> then(A constant) { - return then(ConstantImpl.create(constant)); + return thenSimple(ConstantImpl.create(constant)); } // Boolean - public Cases then(BooleanExpression expr) { + public Cases then(BooleanExpression expr) { return thenBoolean(expr); } @@ -200,6 +219,26 @@ public final class CaseBuilder { return thenBoolean(ConstantImpl.create(b)); } + // Comparable + + public Cases> then(ComparableExpression expr) { + return thenComparable(expr); + } + + private Cases> thenComparable(Expression expr) { + return new Cases>((Class)expr.getType()) { + @Override + protected ComparableExpression createResult(Class type, Expression last) { + return ComparableOperation.create(type, Ops.CASE, last); + } + + }.addCase(when, expr); + } + + public Cases> then(A arg) { + return thenComparable(ConstantImpl.create(arg)); + } + // Date public Cases> then(DateExpression expr) { @@ -216,7 +255,7 @@ public final class CaseBuilder { }.addCase(when, expr); } - public Cases> thenDate(java.sql.Date date) { + public Cases> then(java.sql.Date date) { return thenDate(ConstantImpl.create(date)); } @@ -236,11 +275,11 @@ public final class CaseBuilder { }.addCase(when, expr); } - public Cases> thenDateTime(Timestamp ts) { + public Cases> then(Timestamp ts) { return thenDateTime(ConstantImpl.create(ts)); } - public Cases> thenDateTime(java.util.Date date) { + public Cases> then(java.util.Date date) { return thenDateTime(ConstantImpl.create(date)); } diff --git a/querydsl-core/src/test/java/com/mysema/query/support/ReplaceVisitorTest.java b/querydsl-core/src/test/java/com/mysema/query/support/ReplaceVisitorTest.java new file mode 100644 index 000000000..1574b40f1 --- /dev/null +++ b/querydsl-core/src/test/java/com/mysema/query/support/ReplaceVisitorTest.java @@ -0,0 +1,40 @@ +package com.mysema.query.support; + +import com.mysema.query.types.*; +import com.mysema.query.types.path.StringPath; +import org.junit.Test; + +import javax.annotation.Nullable; + +import static org.junit.Assert.assertEquals; + +public class ReplaceVisitorTest { + + private static final ReplaceVisitor visitor = new ReplaceVisitor() { + public Expression visit(Path expr, @Nullable Void context) { + if (expr.getMetadata().isRoot()) { + return new PathImpl(expr.getType(), expr.getMetadata().getName() + "_"); + } else { + return super.visit(expr, context); + } + } + }; + + @Test + public void Operation() { + Expression str = new StringPath(new PathImpl(Object.class, "customer"), "name"); + Expression str2 = new StringPath("str"); + Expression concat = Expressions.stringOperation(Ops.CONCAT, str, str2); + assertEquals("customer.name + str", concat.toString()); + assertEquals("customer_.name + str_", concat.accept(visitor, null).toString()); + } + + @Test + public void TemplateExpression() { + Expression str = new StringPath(new PathImpl(Object.class, "customer"), "name"); + Expression str2 = new StringPath("str"); + Expression concat = Expressions.stringTemplate("{0} + {1}", str, str2); + assertEquals("customer.name + str", concat.toString()); + assertEquals("customer_.name + str_", concat.accept(visitor, null).toString()); + } +} diff --git a/querydsl-docs/src/main/docbook/en-US/Querydsl_Reference.xml b/querydsl-docs/src/main/docbook/en-US/Querydsl_Reference.xml index 8cc281bdf..0ba79e343 100644 --- a/querydsl-docs/src/main/docbook/en-US/Querydsl_Reference.xml +++ b/querydsl-docs/src/main/docbook/en-US/Querydsl_Reference.xml @@ -1,6 +1,6 @@ + ]> diff --git a/querydsl-docs/src/main/docbook/en-US/content/tutorials/jpa.xml b/querydsl-docs/src/main/docbook/en-US/content/tutorials/jpa.xml index fbd0c37f0..5a07af0a0 100644 --- a/querydsl-docs/src/main/docbook/en-US/content/tutorials/jpa.xml +++ b/querydsl-docs/src/main/docbook/en-US/content/tutorials/jpa.xml @@ -501,7 +501,7 @@ QCustomer customer = QCustomer.customer; // delete all customers new JPADeleteClause(entityManager, customer).execute(); // delete all customers with a level less than 3 -new JPAeDeleteClause(entityManager, customer).where(customer.level.lt(3)).execute(); +new JPADeleteClause(entityManager, customer).where(customer.level.lt(3)).execute(); ]]> The second parameter of the JPADeleteClause constructor is the entity to diff --git a/querydsl-hibernate-search/pom.xml b/querydsl-hibernate-search/pom.xml index de390a96e..a43f84b62 100644 --- a/querydsl-hibernate-search/pom.xml +++ b/querydsl-hibernate-search/pom.xml @@ -5,7 +5,7 @@ com.mysema.querydsl querydsl-root - 3.3.2.BUILD-SNAPSHOT + 3.3.3.BUILD-SNAPSHOT ../querydsl-root/pom.xml diff --git a/querydsl-jdo/README.md b/querydsl-jdo/README.md index 6ba61d3c7..a79dbd243 100644 --- a/querydsl-jdo/README.md +++ b/querydsl-jdo/README.md @@ -1,4 +1,4 @@ -# Querydsl JDO # +## Querydsl JDO The JDO module provides integration with the JDO API. diff --git a/querydsl-jdo/pom.xml b/querydsl-jdo/pom.xml index b0818f819..43dcaea0e 100644 --- a/querydsl-jdo/pom.xml +++ b/querydsl-jdo/pom.xml @@ -5,7 +5,7 @@ com.mysema.querydsl querydsl-root - 3.3.2.BUILD-SNAPSHOT + 3.3.3.BUILD-SNAPSHOT ../querydsl-root/pom.xml diff --git a/querydsl-jdo/src/test/java/com/mysema/query/jdo/BasicsTest.java b/querydsl-jdo/src/test/java/com/mysema/query/jdo/BasicsTest.java index b155af620..ba3893579 100644 --- a/querydsl-jdo/src/test/java/com/mysema/query/jdo/BasicsTest.java +++ b/querydsl-jdo/src/test/java/com/mysema/query/jdo/BasicsTest.java @@ -14,12 +14,14 @@ package com.mysema.query.jdo; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import java.io.IOException; import javax.jdo.PersistenceManager; import javax.jdo.Transaction; +import com.mysema.query.types.Projections; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; @@ -98,6 +100,11 @@ public class BasicsTest extends AbstractJDOTest { query().from(product).singleResult(new Expression[]{product}); } + @Test + public void FactoryExpression_In_GroupBy() { + Expression productBean = Projections.bean(Product.class, product.name, product.description); + assertFalse(query().from(product).groupBy(productBean).list(productBean).isEmpty()); + } @Test(expected=NonUniqueResultException.class) public void Unique_Result_Throws_Exception_On_Multiple_Results() { diff --git a/querydsl-jpa-codegen/pom.xml b/querydsl-jpa-codegen/pom.xml index 57f602365..b2f744c36 100644 --- a/querydsl-jpa-codegen/pom.xml +++ b/querydsl-jpa-codegen/pom.xml @@ -5,7 +5,7 @@ com.mysema.querydsl querydsl-root - 3.3.2.BUILD-SNAPSHOT + 3.3.3.BUILD-SNAPSHOT ../querydsl-root/pom.xml diff --git a/querydsl-jpa/README.md b/querydsl-jpa/README.md index aca6e7bd2..edbd3c388 100644 --- a/querydsl-jpa/README.md +++ b/querydsl-jpa/README.md @@ -1,4 +1,4 @@ -# Querydsl JPA # +## Querydsl JPA The JPA module provides integration with the JPA 2 persistence API. diff --git a/querydsl-jpa/pom.xml b/querydsl-jpa/pom.xml index 75ac80569..8006c0f09 100644 --- a/querydsl-jpa/pom.xml +++ b/querydsl-jpa/pom.xml @@ -5,7 +5,7 @@ com.mysema.querydsl querydsl-root - 3.3.2.BUILD-SNAPSHOT + 3.3.3.BUILD-SNAPSHOT ../querydsl-root/pom.xml diff --git a/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPAQueryMixin.java b/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPAQueryMixin.java index a4b07b0e2..1123b3db8 100644 --- a/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPAQueryMixin.java +++ b/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPAQueryMixin.java @@ -13,11 +13,6 @@ */ package com.mysema.query.jpa; -import java.util.Map; -import java.util.Set; - -import javax.persistence.Entity; - import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.mysema.query.JoinFlag; @@ -25,19 +20,14 @@ import com.mysema.query.QueryMetadata; import com.mysema.query.support.Context; import com.mysema.query.support.ListAccessVisitor; import com.mysema.query.support.QueryMixin; -import com.mysema.query.types.CollectionExpression; -import com.mysema.query.types.ConstantImpl; -import com.mysema.query.types.EntityPath; -import com.mysema.query.types.Expression; -import com.mysema.query.types.ExpressionUtils; -import com.mysema.query.types.OperationImpl; -import com.mysema.query.types.Path; -import com.mysema.query.types.PathImpl; -import com.mysema.query.types.PathMetadata; -import com.mysema.query.types.PathType; -import com.mysema.query.types.Predicate; +import com.mysema.query.support.ReplaceVisitor; +import com.mysema.query.types.*; import com.mysema.query.types.path.CollectionPathBase; +import javax.persistence.Entity; +import java.util.Map; +import java.util.Set; + /** * JPAQueryMixin extends {@link QueryMixin} to support JPQL join construction * @@ -51,6 +41,8 @@ public class JPAQueryMixin extends QueryMixin { private final Map, Path> aliases = Maps.newHashMap(); + private ReplaceVisitor replaceVisitor; + public static final JoinFlag FETCH = new JoinFlag("fetch "); public static final JoinFlag FETCH_ALL_PROPERTIES = new JoinFlag(" fetch all properties"); @@ -130,16 +122,32 @@ public class JPAQueryMixin extends QueryMixin { } } + private Path convertPathForOrder(Path path) { + PathMetadata metadata = path.getMetadata(); + // at least three levels + if (metadata.getParent() != null && !metadata.getParent().getMetadata().isRoot()) { + Path shortened = shorten(metadata.getParent()); + return new PathImpl(path.getType(), + new PathMetadata(shortened, metadata.getElement(), metadata.getPathType())); + } else { + return path; + } + } + @Override public Expression convert(Expression expr, boolean forOrder) { - if (forOrder && expr instanceof Path) { - Path path = (Path)expr; - PathMetadata metadata = path.getMetadata(); - // at least three levels - if (metadata.getParent() != null && !metadata.getParent().getMetadata().isRoot()) { - Path shortened = shorten(metadata.getParent()); - expr = new PathImpl(expr.getType(), - new PathMetadata(shortened, metadata.getElement(), metadata.getPathType())); + if (forOrder) { + if (expr instanceof Path) { + expr = convertPathForOrder((Path)expr); + } else { + if (replaceVisitor == null) { + replaceVisitor = new ReplaceVisitor() { + public Expression visit(Path expr, Void context) { + return convertPathForOrder(expr); + } + }; + } + expr = (Expression)expr.accept(replaceVisitor, null); } } return Conversions.convert(super.convert(expr, forOrder)); diff --git a/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPQLSerializer.java b/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPQLSerializer.java index e90433d43..0d2cc5790 100644 --- a/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPQLSerializer.java +++ b/querydsl-jpa/src/main/java/com/mysema/query/jpa/JPQLSerializer.java @@ -331,18 +331,6 @@ public class JPQLSerializer extends SerializerBase { return null; } - @Override - public Void visit(FactoryExpression expr, Void context) { - if (!inProjection) { - append("("); - super.visit(expr, context); - append(")"); - } else { - super.visit(expr, context); - } - return null; - } - @Override @SuppressWarnings("unchecked") protected void visitOperation(Class type, Operator operator, List> args) { diff --git a/querydsl-jpa/src/test/java/com/mysema/query/AbstractJPATest.java b/querydsl-jpa/src/test/java/com/mysema/query/AbstractJPATest.java index 736c1e79c..38a3bed03 100644 --- a/querydsl-jpa/src/test/java/com/mysema/query/AbstractJPATest.java +++ b/querydsl-jpa/src/test/java/com/mysema/query/AbstractJPATest.java @@ -1139,6 +1139,12 @@ public abstract class AbstractJPATest { assertEquals(2l, query().from(cat).where(where).count()); } + @Test + public void FactoryExpression_In_GroupBy() { + Expression catBean = Projections.bean(Cat.class, cat.id, cat.name); + assertFalse(query().from(cat).groupBy(catBean).list(catBean).isEmpty()); + } + @Test @Ignore public void Size() { diff --git a/querydsl-jpa/src/test/java/com/mysema/query/jpa/JPAQueryMixinTest.java b/querydsl-jpa/src/test/java/com/mysema/query/jpa/JPAQueryMixinTest.java index 47c67365d..86833a382 100644 --- a/querydsl-jpa/src/test/java/com/mysema/query/jpa/JPAQueryMixinTest.java +++ b/querydsl-jpa/src/test/java/com/mysema/query/jpa/JPAQueryMixinTest.java @@ -1,11 +1,5 @@ package com.mysema.query.jpa; -import static org.junit.Assert.assertEquals; - -import java.util.Arrays; - -import org.junit.Test; - import com.mysema.query.JoinExpression; import com.mysema.query.JoinType; import com.mysema.query.QueryMetadata; @@ -15,6 +9,11 @@ import com.mysema.query.jpa.domain4.QBookVersion; import com.mysema.query.types.PathMetadataFactory; import com.mysema.query.types.Predicate; import com.mysema.query.types.path.StringPath; +import org.junit.Test; + +import java.util.Arrays; + +import static org.junit.Assert.assertEquals; public class JPAQueryMixinTest { @@ -41,6 +40,22 @@ public class JPAQueryMixinTest { md.getOrderBy()); } + @Test + public void OrderBy_Operation() { + QCat cat = QCat.cat; + QCat cat_mate = new QCat("cat_mate"); + mixin.from(cat); + mixin.orderBy(cat.mate.name.lower().asc()); + + QueryMetadata md = mixin.getMetadata(); + assertEquals(Arrays.asList( + new JoinExpression(JoinType.DEFAULT, cat), + new JoinExpression(JoinType.LEFTJOIN, cat.mate.as(cat_mate))), + md.getJoins()); + assertEquals(Arrays.asList(cat_mate.name.lower().asc()), + md.getOrderBy()); + } + @Test public void OrderBy_Long() { QCat cat = QCat.cat; diff --git a/querydsl-lucene3/README.md b/querydsl-lucene3/README.md index 0c33f3ae5..1aca60249 100644 --- a/querydsl-lucene3/README.md +++ b/querydsl-lucene3/README.md @@ -1,6 +1,6 @@ -# Querydsl Lucene # +## Querydsl Lucene 3 -The Lucene module provides integration with the Lucene indexing library. +The Lucene module provides integration with the Lucene 3 indexing library. **Maven integration** @@ -8,7 +8,7 @@ The Lucene module provides integration with the Lucene indexing library. com.mysema.querydsl - querydsl-lucene + querydsl-lucene3 ${querydsl.version} @@ -16,7 +16,7 @@ The Lucene module provides integration with the Lucene indexing library. org.slf4j slf4j-log4j12 1.6.1 - + **Creating the query types** @@ -55,4 +55,4 @@ which is transformed into the following Lucene query : +year:[1800 TO 2000] +title:huckle* -For more information on the Querydsl Lucene module visit the reference documentation http://www.querydsl.com/static/querydsl/latest/reference/html/ch02s04.html \ No newline at end of file +For more information on the Querydsl Lucene module visit the reference documentation http://www.querydsl.com/static/querydsl/latest/reference/html/ch02s04.html diff --git a/querydsl-lucene3/pom.xml b/querydsl-lucene3/pom.xml index 21631f9de..d02d67736 100644 --- a/querydsl-lucene3/pom.xml +++ b/querydsl-lucene3/pom.xml @@ -5,13 +5,13 @@ com.mysema.querydsl querydsl-root - 3.3.2.BUILD-SNAPSHOT + 3.3.3.BUILD-SNAPSHOT ../querydsl-root/pom.xml com.mysema.querydsl querydsl-lucene3 - Querydsl - Lucene support + Querydsl - Lucene 3 support Lucene support for Querydsl jar diff --git a/querydsl-lucene4/README.md b/querydsl-lucene4/README.md index 0c33f3ae5..0250337fa 100644 --- a/querydsl-lucene4/README.md +++ b/querydsl-lucene4/README.md @@ -1,6 +1,6 @@ -# Querydsl Lucene # +## Querydsl Lucene 4 -The Lucene module provides integration with the Lucene indexing library. +The Lucene module provides integration with the Lucene 4 indexing library. **Maven integration** @@ -8,7 +8,7 @@ The Lucene module provides integration with the Lucene indexing library. com.mysema.querydsl - querydsl-lucene + querydsl-lucene4 ${querydsl.version} diff --git a/querydsl-lucene4/pom.xml b/querydsl-lucene4/pom.xml index 4cca5fde5..a932e8b17 100644 --- a/querydsl-lucene4/pom.xml +++ b/querydsl-lucene4/pom.xml @@ -5,13 +5,13 @@ com.mysema.querydsl querydsl-root - 3.3.2.BUILD-SNAPSHOT + 3.3.3.BUILD-SNAPSHOT ../querydsl-root/pom.xml com.mysema.querydsl querydsl-lucene4 - Querydsl - Lucene support + Querydsl - Lucene 4 support Lucene support for Querydsl jar diff --git a/querydsl-maven-plugin/pom.xml b/querydsl-maven-plugin/pom.xml index 189414c96..bf3d3be61 100644 --- a/querydsl-maven-plugin/pom.xml +++ b/querydsl-maven-plugin/pom.xml @@ -5,7 +5,7 @@ com.mysema.querydsl querydsl-root - 3.3.2.BUILD-SNAPSHOT + 3.3.3.BUILD-SNAPSHOT ../querydsl-root/pom.xml diff --git a/querydsl-maven-plugin/src/main/java/com/mysema/query/maven/AbstractMetaDataExportMojo.java b/querydsl-maven-plugin/src/main/java/com/mysema/query/maven/AbstractMetaDataExportMojo.java index 940082c7a..f1a3c5ee6 100644 --- a/querydsl-maven-plugin/src/main/java/com/mysema/query/maven/AbstractMetaDataExportMojo.java +++ b/querydsl-maven-plugin/src/main/java/com/mysema/query/maven/AbstractMetaDataExportMojo.java @@ -17,6 +17,7 @@ import java.io.File; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; +import java.util.Comparator; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; @@ -248,6 +249,13 @@ public class AbstractMetaDataExportMojo extends AbstractMojo{ */ private boolean exportForeignKeys; + /** + * override default column order (default: alphabetical) + * + * @parameter + */ + private String columnComparatorClass; + /** * java import added to generated query classes: * com.bar for package (without .* notation) @@ -370,6 +378,14 @@ public class AbstractMetaDataExportMojo extends AbstractMojo{ configuration.registerNumeric(mapping.size, mapping.digits, Class.forName(mapping.javaType)); } } + if (columnComparatorClass != null) { + try { + exporter.setColumnComparatorClass( (Class) Class.forName(this.columnComparatorClass).asSubclass(Comparator.class)); + } catch (ClassNotFoundException e) { + getLog().error(e); + throw new MojoExecutionException(e.getMessage(), e); + } + } exporter.setConfiguration(configuration); diff --git a/querydsl-mongodb/README.md b/querydsl-mongodb/README.md index 726f16a1c..6625c74d6 100644 --- a/querydsl-mongodb/README.md +++ b/querydsl-mongodb/README.md @@ -1,4 +1,4 @@ -# Querydsl Mongodb # +## Querydsl Mongodb The Mongodb module provides integration with the Mongodb API. diff --git a/querydsl-mongodb/pom.xml b/querydsl-mongodb/pom.xml index 196745e79..273698fe7 100644 --- a/querydsl-mongodb/pom.xml +++ b/querydsl-mongodb/pom.xml @@ -5,7 +5,7 @@ com.mysema.querydsl querydsl-root - 3.3.2.BUILD-SNAPSHOT + 3.3.3.BUILD-SNAPSHOT ../querydsl-root/pom.xml diff --git a/querydsl-mongodb/src/test/java/com/mysema/query/mongodb/MongodbQueryTest.java b/querydsl-mongodb/src/test/java/com/mysema/query/mongodb/MongodbQueryTest.java index d8ba35ada..ee4218132 100644 --- a/querydsl-mongodb/src/test/java/com/mysema/query/mongodb/MongodbQueryTest.java +++ b/querydsl-mongodb/src/test/java/com/mysema/query/mongodb/MongodbQueryTest.java @@ -28,6 +28,7 @@ import java.util.Date; import java.util.Iterator; import java.util.List; +import com.mysema.query.mongodb.domain.*; import org.bson.types.ObjectId; import org.junit.Before; import org.junit.Test; @@ -41,15 +42,10 @@ import com.mongodb.MongoException; import com.mongodb.ReadPreference; import com.mysema.query.NonUniqueResultException; import com.mysema.query.SearchResults; -import com.mysema.query.mongodb.domain.Address; -import com.mysema.query.mongodb.domain.City; -import com.mysema.query.mongodb.domain.Item; -import com.mysema.query.mongodb.domain.MapEntity; import com.mysema.query.mongodb.domain.QAddress; import com.mysema.query.mongodb.domain.QItem; import com.mysema.query.mongodb.domain.QMapEntity; import com.mysema.query.mongodb.domain.QUser; -import com.mysema.query.mongodb.domain.User; import com.mysema.query.mongodb.domain.User.Gender; import com.mysema.query.mongodb.morphia.MorphiaQuery; import com.mysema.query.types.EntityPath; @@ -70,6 +66,7 @@ public class MongodbQueryTest { private final QItem item = QItem.item; private final QAddress address = QAddress.address; private final QMapEntity mapEntity = QMapEntity.mapEntity; + private final QDates dates = QDates.dates; List users = Lists.newArrayList(); User u1, u2, u3, u4; @@ -77,7 +74,7 @@ public class MongodbQueryTest { public MongodbQueryTest() throws UnknownHostException, MongoException { mongo = new Mongo(); - morphia = new Morphia().map(User.class).map(Item.class).map(MapEntity.class); + morphia = new Morphia().map(User.class).map(Item.class).map(MapEntity.class).map(Dates.class); ds = morphia.createDatastore(mongo, dbname); } @@ -209,6 +206,19 @@ public class MongodbQueryTest { assertEquals(0, query().where(user.addresses.any().street.eq("akatu")).count()); } + @Test + public void Dates() { + Date start = new Date(); + ds.delete(ds.createQuery(Dates.class)); + Dates d = new Dates(); + d.setDate(new Date()); + ds.save(d); + Date end = new Date(); + + assertEquals(d, query(dates).where(dates.date.between(start, end)).singleResult()); + assertEquals(0, query(dates).where(dates.date.between(new Date(0), start)).count()); + } + @Test public void ElemMatch() { // { "addresses" : { "$elemMatch" : { "street" : "Aakatu1"}}} diff --git a/querydsl-mongodb/src/test/java/com/mysema/query/mongodb/MongodbSerializerTest.java b/querydsl-mongodb/src/test/java/com/mysema/query/mongodb/MongodbSerializerTest.java index 48f0eb7f1..80e79f809 100644 --- a/querydsl-mongodb/src/test/java/com/mysema/query/mongodb/MongodbSerializerTest.java +++ b/querydsl-mongodb/src/test/java/com/mysema/query/mongodb/MongodbSerializerTest.java @@ -131,6 +131,12 @@ public class MongodbSerializerTest { assertQuery(title.ne("A"), dbo("title", dbo("$ne", "A"))); } + @Test + public void Between() { + System.err.println(dbo("year", dbo("$gte", 1).append("$lte", 10))); + assertQuery(year.between(1, 10), dbo("year", dbo("$gte", 1).append("$lte", 10))); + } + @Test public void LessAndGreaterAndBetween() { assertQuery(title.lt("A"), dbo("title", dbo("$lt", "A"))); diff --git a/querydsl-mongodb/src/test/java/com/mysema/query/mongodb/domain/Dates.java b/querydsl-mongodb/src/test/java/com/mysema/query/mongodb/domain/Dates.java new file mode 100644 index 000000000..307580db1 --- /dev/null +++ b/querydsl-mongodb/src/test/java/com/mysema/query/mongodb/domain/Dates.java @@ -0,0 +1,31 @@ +package com.mysema.query.mongodb.domain; + +import org.bson.types.ObjectId; +import org.mongodb.morphia.annotations.Entity; +import org.mongodb.morphia.annotations.Id; + +import java.util.Date; + +@Entity +public class Dates { + + private @Id ObjectId id; + + private Date date; + + public ObjectId getId() { + return id; + } + + public void setId(ObjectId id) { + this.id = id; + } + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } +} diff --git a/querydsl-root/pom.xml b/querydsl-root/pom.xml index 768afd0e8..3e3f220d3 100644 --- a/querydsl-root/pom.xml +++ b/querydsl-root/pom.xml @@ -1,531 +1,531 @@ - - - 4.0.0 - com.mysema.querydsl - querydsl-root - 3.3.2.BUILD-SNAPSHOT - Querydsl - parent project for Querydsl modules - http://www.querydsl.com - - - com.mysema.home - mysema-source - 0.3.1 - - - pom - - 2007 - - - false - UTF-8 - - - 10.10.1.1 - 2.3.1 - 1.3.174 - 9.1-901.jdbc4 - 11.1.0.7.0 - 5.1.18 - 1.3.1 - 8.4.0 - 3.7.2 - 13.10.00.35 - - 13.0.1 - 0.6.1 - 0.2.4 - 2.2.2 - 1.3.2 - 1.6.1 - - - - - junit - junit - 4.8.1 - test - - - javax.servlet - servlet-api - - - - - - org.easymock - easymock - 3.0 - test - - - cglib - cglib-nodep - - - - - - - - - org.slf4j - slf4j-api - ${slf4j.version} - - - org.slf4j - slf4j-log4j12 - ${slf4j.version} - provided - - - - - - Mysema Ltd - http://www.mysema.com - - - - scm:git:git@github.com:mysema/querydsl.git - scm:git:git@github.com:mysema/querydsl.git - git@github.com:mysema/querydsl.git - - - - - tiwe - Timo Westkämper - timo.westkamper@mysema.com - Mysema Ltd - - Project Manager - Architect - - - - sasa - Samppa Saarela - samppa.saarela@mysema.com - Mysema Ltd - - Developer - - - - vema - Vesa Marttila - vesa.marttila@mysema.com - Mysema Ltd - - Developer - - - - laim - Lassi Immonen - lassi.immonen@mysema.com - Mysema Ltd - - Developer - - - - - - - Apache License, Version 2.0 - LICENSE.txt - - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 2.4 - - - com.mysema.maven - apt-maven-plugin - 1.0.9 - - - org.apache.maven.plugins - maven-surefire-plugin - 2.16 - - - com.springsource.bundlor - com.springsource.bundlor.maven - 1.0.0.RELEASE - - - bundlor - - bundlor - - - - - true - - - - - - - - maven-assembly-plugin - - - ../querydsl-root/src/main/assembly.xml - - ../querydsl-root/target/dist - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9.1 - - ${project.build.directory}/dist/apidocs - ${project.build.directory}/dist/apidocs - - - Core - com.mysema.query:com.mysema.query.alias:com.mysema.query.annotations:com.mysema.query.codegen:com.mysema.query.dml:com.mysema.query.functions:com.mysema.query.serialization:com.mysema.query.support:com.mysema.query.types* - - - APT - com.mysema.query.apt* - - - Collections - com.mysema.query.collections* - - - JPA - com.mysema.query.jpa* - - - JDO - com.mysema.query.jdo* - - - SQL - com.mysema.query.sql* - - - Lucene - com.mysema.query.lucene - - - Hibernate Search - com.mysema.query.search - - - Mongodb - com.mysema.query.mongodb* - - - - - - com.mysema.maven - maven-version-plugin - 0.1.0 - - - org.apache.maven.plugins - maven-pmd-plugin - 2.3 - - 1.6 - true - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.6 - 1.6 - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - package - - jar - - - - - - org.apache.maven.plugins - maven-jar-plugin - 2.4 - - true - - - - org.apache.maven.plugins - maven-surefire-plugin - - -Xms256m -Xmx512m -XX:MaxPermSize=512m - com.mysema.testutil.ExternalDB - - - - org.apache.maven.surefire - surefire-junit47 - 2.16 - - - - - - - - - source - http://source.mysema.com/maven2/releases - - - jboss - https://repository.jboss.org/nexus/content/groups/public-jboss - - - jboss2 - https://repository.jboss.org/nexus/content/repositories/releases - - - EclipseLink Repo - http://download.eclipse.org/rt/eclipselink/maven.repo/ - - - jahia - http://maven.jahia.org/maven2 - - - datanucleus - http://www.datanucleus.org/downloads/maven2 - - - morphia_repo - http://morphia.googlecode.com/svn/mavenrepo/ - - - CUBRID - http://maven.cubrid.org - - - Sonatype snapshots - https://oss.sonatype.org/content/repositories/snapshots - - true - - - false - - - - com.springsource.repository.bundles.release - http://repository.springsource.com/maven/bundles/release - - - spring roo repository - http://spring-roo-repository.springsource.org/release - - - - - - datanucleus - http://www.datanucleus.org/downloads/maven2 - - - com.springsource.repository.bundles.release - http://repository.springsource.com/maven/bundles/release - - - com.springsource.repository.bundles.external - http://repository.springsource.com/maven/bundles/external - - - - - - all - true - - ../querydsl-core - ../querydsl-codegen - ../querydsl-apt - ../querydsl-collections - ../querydsl-sql - ../querydsl-sql-codegen - ../querydsl-maven-plugin - ../querydsl-jpa - ../querydsl-jpa-codegen - ../querydsl-jdo - - - ../querydsl-lucene3 - ../querydsl-lucene4 - ../querydsl-hibernate-search - - - ../querydsl-mongodb - - - ../querydsl-scala - - - - - hibernate-search - - ../querydsl-core - ../querydsl-codegen - ../querydsl-lucene3 - ../querydsl-hibernate-search - - - - - jpa - - ../querydsl-core - ../querydsl-codegen - ../querydsl-apt - ../querydsl-sql - ../querydsl-sql-codegen - ../querydsl-maven-plugin - ../querydsl-jpa - ../querydsl-jpa-codegen - - - - - jdo - - ../querydsl-core - ../querydsl-codegen - ../querydsl-apt - ../querydsl-sql - ../querydsl-sql-codegen - ../querydsl-maven-plugin - ../querydsl-jdo - - - - - lucene - - ../querydsl-core - ../querydsl-codegen - ../querydsl-apt - ../querydsl-lucene3 - ../querydsl-lucene4 - - - - - mongodb - - ../querydsl-core - ../querydsl-codegen - ../querydsl-apt - ../querydsl-mongodb - - - - - sql - - ../querydsl-core - ../querydsl-codegen - ../querydsl-sql - ../querydsl-sql-codegen - ../querydsl-maven-plugin - - - - - collections - - ../querydsl-core - ../querydsl-codegen - ../querydsl-apt - ../querydsl-collections - - - - - jenkins - - - - org.apache.maven.plugins - maven-surefire-plugin - - com.mysema.testutil.DummyInterface - - **/*$* - **/MSSQLSuiteTest.java - **/TeradataSuiteTest.java - - - - - - - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9.1 - - true - - - - org.codehaus.mojo - junit-report-maven-plugin - devel - - true - - - - org.apache.maven.plugins - maven-jxr-plugin - 2.3 - - true - - - - - + + + 4.0.0 + com.mysema.querydsl + querydsl-root + 3.3.3.BUILD-SNAPSHOT + Querydsl + parent project for Querydsl modules + http://www.querydsl.com + + + com.mysema.home + mysema-source + 0.3.1 + + + pom + + 2007 + + + false + UTF-8 + + + 10.10.1.1 + 2.3.1 + 1.3.174 + 9.1-901.jdbc4 + 11.1.0.7.0 + 5.1.18 + 1.3.1 + 8.4.0 + 3.7.2 + 13.10.00.35 + + 13.0.1 + 0.6.2 + 0.2.4 + 2.2.2 + 1.3.2 + 1.6.1 + + + + + junit + junit + 4.8.1 + test + + + javax.servlet + servlet-api + + + + + + org.easymock + easymock + 3.0 + test + + + cglib + cglib-nodep + + + + + + + + + org.slf4j + slf4j-api + ${slf4j.version} + + + org.slf4j + slf4j-log4j12 + ${slf4j.version} + provided + + + + + + Mysema Ltd + http://www.mysema.com + + + + scm:git:git@github.com:mysema/querydsl.git + scm:git:git@github.com:mysema/querydsl.git + git@github.com:mysema/querydsl.git + + + + + tiwe + Timo Westkämper + timo.westkamper@mysema.com + Mysema Ltd + + Project Manager + Architect + + + + sasa + Samppa Saarela + samppa.saarela@mysema.com + Mysema Ltd + + Developer + + + + vema + Vesa Marttila + vesa.marttila@mysema.com + Mysema Ltd + + Developer + + + + laim + Lassi Immonen + lassi.immonen@mysema.com + Mysema Ltd + + Developer + + + + + + + Apache License, Version 2.0 + LICENSE.txt + + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.4 + + + com.mysema.maven + apt-maven-plugin + 1.0.9 + + + org.apache.maven.plugins + maven-surefire-plugin + 2.16 + + + com.springsource.bundlor + com.springsource.bundlor.maven + 1.0.0.RELEASE + + + bundlor + + bundlor + + + + + true + + + + + + + + maven-assembly-plugin + + + ../querydsl-root/src/main/assembly.xml + + ../querydsl-root/target/dist + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + ${project.build.directory}/dist/apidocs + ${project.build.directory}/dist/apidocs + + + Core + com.mysema.query:com.mysema.query.alias:com.mysema.query.annotations:com.mysema.query.codegen:com.mysema.query.dml:com.mysema.query.functions:com.mysema.query.serialization:com.mysema.query.support:com.mysema.query.types* + + + APT + com.mysema.query.apt* + + + Collections + com.mysema.query.collections* + + + JPA + com.mysema.query.jpa* + + + JDO + com.mysema.query.jdo* + + + SQL + com.mysema.query.sql* + + + Lucene + com.mysema.query.lucene + + + Hibernate Search + com.mysema.query.search + + + Mongodb + com.mysema.query.mongodb* + + + + + + com.mysema.maven + maven-version-plugin + 0.1.0 + + + org.apache.maven.plugins + maven-pmd-plugin + 2.3 + + 1.6 + true + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.6 + 1.6 + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + package + + jar + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + true + + + + org.apache.maven.plugins + maven-surefire-plugin + + -Xms256m -Xmx512m -XX:MaxPermSize=512m + com.mysema.testutil.ExternalDB + + + + org.apache.maven.surefire + surefire-junit47 + 2.16 + + + + + + + + + source + http://source.mysema.com/maven2/releases + + + jboss + https://repository.jboss.org/nexus/content/groups/public-jboss + + + jboss2 + https://repository.jboss.org/nexus/content/repositories/releases + + + EclipseLink Repo + http://download.eclipse.org/rt/eclipselink/maven.repo/ + + + jahia + http://maven.jahia.org/maven2 + + + datanucleus + http://www.datanucleus.org/downloads/maven2 + + + morphia_repo + http://morphia.googlecode.com/svn/mavenrepo/ + + + CUBRID + http://maven.cubrid.org + + + Sonatype snapshots + https://oss.sonatype.org/content/repositories/snapshots + + true + + + false + + + + com.springsource.repository.bundles.release + http://repository.springsource.com/maven/bundles/release + + + spring roo repository + http://spring-roo-repository.springsource.org/release + + + + + + datanucleus + http://www.datanucleus.org/downloads/maven2 + + + com.springsource.repository.bundles.release + http://repository.springsource.com/maven/bundles/release + + + com.springsource.repository.bundles.external + http://repository.springsource.com/maven/bundles/external + + + + + + all + true + + ../querydsl-core + ../querydsl-codegen + ../querydsl-apt + ../querydsl-collections + ../querydsl-sql + ../querydsl-sql-codegen + ../querydsl-maven-plugin + ../querydsl-jpa + ../querydsl-jpa-codegen + ../querydsl-jdo + + + ../querydsl-lucene3 + ../querydsl-lucene4 + ../querydsl-hibernate-search + + + ../querydsl-mongodb + + + ../querydsl-scala + + + + + hibernate-search + + ../querydsl-core + ../querydsl-codegen + ../querydsl-lucene3 + ../querydsl-hibernate-search + + + + + jpa + + ../querydsl-core + ../querydsl-codegen + ../querydsl-apt + ../querydsl-sql + ../querydsl-sql-codegen + ../querydsl-maven-plugin + ../querydsl-jpa + ../querydsl-jpa-codegen + + + + + jdo + + ../querydsl-core + ../querydsl-codegen + ../querydsl-apt + ../querydsl-sql + ../querydsl-sql-codegen + ../querydsl-maven-plugin + ../querydsl-jdo + + + + + lucene + + ../querydsl-core + ../querydsl-codegen + ../querydsl-apt + ../querydsl-lucene3 + ../querydsl-lucene4 + + + + + mongodb + + ../querydsl-core + ../querydsl-codegen + ../querydsl-apt + ../querydsl-mongodb + + + + + sql + + ../querydsl-core + ../querydsl-codegen + ../querydsl-sql + ../querydsl-sql-codegen + ../querydsl-maven-plugin + + + + + collections + + ../querydsl-core + ../querydsl-codegen + ../querydsl-apt + ../querydsl-collections + + + + + jenkins + + + + org.apache.maven.plugins + maven-surefire-plugin + + com.mysema.testutil.DummyInterface + + **/*$* + **/MSSQLSuiteTest.java + **/TeradataSuiteTest.java + + + + + + + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + true + + + + org.codehaus.mojo + junit-report-maven-plugin + devel + + true + + + + org.apache.maven.plugins + maven-jxr-plugin + 2.3 + + true + + + + + diff --git a/querydsl-scala/pom.xml b/querydsl-scala/pom.xml index b625b12fc..e91fb9483 100644 --- a/querydsl-scala/pom.xml +++ b/querydsl-scala/pom.xml @@ -5,7 +5,7 @@ com.mysema.querydsl querydsl-root - 3.3.2.BUILD-SNAPSHOT + 3.3.3.BUILD-SNAPSHOT ../querydsl-root/pom.xml diff --git a/querydsl-sql-codegen/pom.xml b/querydsl-sql-codegen/pom.xml index 78fb2eddc..68a9e3bd1 100644 --- a/querydsl-sql-codegen/pom.xml +++ b/querydsl-sql-codegen/pom.xml @@ -5,7 +5,7 @@ com.mysema.querydsl querydsl-root - 3.3.2.BUILD-SNAPSHOT + 3.3.3.BUILD-SNAPSHOT ../querydsl-root/pom.xml diff --git a/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/ant/AntMetaDataExporter.java b/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/ant/AntMetaDataExporter.java index 07ec52d9e..570e862fe 100644 --- a/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/ant/AntMetaDataExporter.java +++ b/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/ant/AntMetaDataExporter.java @@ -17,6 +17,7 @@ import java.io.File; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; +import java.util.Comparator; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; @@ -182,6 +183,11 @@ public class AntMetaDataExporter extends Task { * */ private boolean beanPrintSupertype; + + /** + * override default column order (default: alphabetical) + */ + private String columnComparatorClass; /** * java import added to generated query classes: @@ -192,7 +198,8 @@ public class AntMetaDataExporter extends Task { private String[] imports; - @Override + @Override + @SuppressWarnings({ "unchecked", "rawtypes" }) public void execute() { Connection dbConn = null; File targetPackagePath = new File(targetSourceFolder); @@ -256,6 +263,9 @@ public class AntMetaDataExporter extends Task { if (sourceEncoding != null) { exporter.setSourceEncoding(sourceEncoding); } + if (columnComparatorClass != null) { + exporter.setColumnComparatorClass((Class) Class.forName(this.columnComparatorClass).asSubclass(Comparator.class)); + } exporter.export(dbConn.getMetaData()); diff --git a/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/AbstractNamingStrategy.java b/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/AbstractNamingStrategy.java index 16cab15d9..5fd955f24 100644 --- a/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/AbstractNamingStrategy.java +++ b/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/AbstractNamingStrategy.java @@ -1,6 +1,6 @@ /* * Copyright 2011, Mysema Ltd - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -18,22 +18,22 @@ import com.mysema.util.JavaSyntaxUtils; /** * AbstractNamingStrategy is an abstract base class for NamingStrategy implementations - * + * * @author tiwe * */ public abstract class AbstractNamingStrategy implements NamingStrategy { - + protected String foreignKeysClassName = "ForeignKeys"; - + protected String foreignKeysVariable = "fk"; - + protected String primaryKeysClassName = "PrimaryKeys"; - + protected String primaryKeysVariable = "pk"; - + protected String reservedSuffix = "_col"; - + @Override public String appendSchema(String packageName, String schemaName) { String suffix = schemaName.toLowerCase(); @@ -42,7 +42,7 @@ public abstract class AbstractNamingStrategy implements NamingStrategy { } return packageName + "." + suffix; } - + protected String escape(EntityType entityType, String name) { int suffix = 0; while (true) { @@ -52,9 +52,9 @@ public abstract class AbstractNamingStrategy implements NamingStrategy { } else { return candidate; } - } + } } - + @Override public String getForeignKeysClassName() { return foreignKeysClassName; @@ -74,7 +74,34 @@ public abstract class AbstractNamingStrategy implements NamingStrategy { public String getPrimaryKeysVariable(EntityType entityType) { return primaryKeysVariable; } - + + @Override + public String normalizeColumnName(String columnName) { + if (columnName != null) { + return columnName.replaceAll("\r", "").replaceAll("\n", " "); + } else { + return null; + } + } + + @Override + public String normalizeTableName(String tableName) { + if (tableName != null) { + return tableName.replaceAll("\r", "").replaceAll("\n", " "); + } else { + return null; + } + } + + @Override + public String normalizeSchemaName(String schemaName) { + if (schemaName != null) { + return schemaName.replaceAll("\r", "").replaceAll("\n", " "); + } else { + return null; + } + } + public void setForeignKeysClassName(String foreignKeysClassName) { this.foreignKeysClassName = foreignKeysClassName; } diff --git a/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/DefaultNamingStrategy.java b/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/DefaultNamingStrategy.java index af36c1b29..5c9b9cb09 100644 --- a/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/DefaultNamingStrategy.java +++ b/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/DefaultNamingStrategy.java @@ -93,21 +93,6 @@ public class DefaultNamingStrategy extends AbstractNamingStrategy { return getPropertyName(pkName, entityType); } - @Override - public String normalizeColumnName(String columnName) { - return columnName.replaceAll("\r", "").replaceAll("\n", " "); - } - - @Override - public String normalizeTableName(String tableName) { - return tableName.replaceAll("\r", "").replaceAll("\n", " "); - } - - @Override - public String normalizeSchemaName(String schemaName) { - return schemaName.replaceAll("\r", "").replaceAll("\n", " "); - } - protected String normalizePropertyName(String name) { return Naming.normalize(name, reservedSuffix); } diff --git a/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/KeyDataFactory.java b/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/KeyDataFactory.java index 1f28c08bf..31d23b13b 100644 --- a/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/KeyDataFactory.java +++ b/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/KeyDataFactory.java @@ -73,10 +73,10 @@ public class KeyDataFactory { try{ while (foreignKeys.next()) { String name = foreignKeys.getString(FK_NAME); - String parentColumnName = foreignKeys.getString(FK_PARENT_COLUMN_NAME); - String foreignSchemaName = foreignKeys.getString(FK_FOREIGN_SCHEMA_NAME); - String foreignTableName = foreignKeys.getString(FK_FOREIGN_TABLE_NAME); - String foreignColumn = foreignKeys.getString(FK_FOREIGN_COLUMN_NAME); + String parentColumnName = namingStrategy.normalizeColumnName(foreignKeys.getString(FK_PARENT_COLUMN_NAME)); + String foreignSchemaName = namingStrategy.normalizeSchemaName(foreignKeys.getString(FK_FOREIGN_SCHEMA_NAME)); + String foreignTableName = namingStrategy.normalizeTableName(foreignKeys.getString(FK_FOREIGN_TABLE_NAME)); + String foreignColumn = namingStrategy.normalizeColumnName(foreignKeys.getString(FK_FOREIGN_COLUMN_NAME)); if (name == null || name.isEmpty()) { name = tableName + "_" + foreignTableName + "_IFK"; } @@ -102,10 +102,10 @@ public class KeyDataFactory { try{ while (foreignKeys.next()) { String name = foreignKeys.getString(FK_NAME); - String parentSchemaName = foreignKeys.getString(FK_PARENT_SCHEMA_NAME); - String parentTableName = foreignKeys.getString(FK_PARENT_TABLE_NAME); - String parentColumnName = foreignKeys.getString(FK_PARENT_COLUMN_NAME); - String foreignColumn = foreignKeys.getString(FK_FOREIGN_COLUMN_NAME); + String parentSchemaName = namingStrategy.normalizeSchemaName(foreignKeys.getString(FK_PARENT_SCHEMA_NAME)); + String parentTableName = namingStrategy.normalizeTableName(foreignKeys.getString(FK_PARENT_TABLE_NAME)); + String parentColumnName = namingStrategy.normalizeColumnName(foreignKeys.getString(FK_PARENT_COLUMN_NAME)); + String foreignColumn = namingStrategy.normalizeColumnName(foreignKeys.getString(FK_FOREIGN_COLUMN_NAME)); if (name == null || name.isEmpty()) { name = tableName + "_" + parentTableName + "_FK"; } diff --git a/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/MetaDataExporter.java b/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/MetaDataExporter.java index ab2e9af1b..12f6a810e 100644 --- a/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/MetaDataExporter.java +++ b/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/MetaDataExporter.java @@ -23,6 +23,7 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -251,6 +252,7 @@ public class MetaDataExporter { int columnType = columns.getInt("DATA_TYPE"); Number columnSize = (Number) columns.getObject("COLUMN_SIZE"); Number columnDigits = (Number) columns.getObject("DECIMAL_DIGITS"); + int columnIndex = columns.getInt("ORDINAL_POSITION"); int nullable = columns.getInt("NULLABLE"); String propertyName = namingStrategy.getPropertyName(normalizedColumnName, classModel); @@ -269,7 +271,7 @@ public class MetaDataExporter { } Type typeModel = new ClassType(fieldType, clazz); Property property = createProperty(classModel, normalizedColumnName, propertyName, typeModel); - ColumnMetadata column = ColumnMetadata.named(normalizedColumnName).ofType(columnType); + ColumnMetadata column = ColumnMetadata.named(normalizedColumnName).ofType(columnType).withIndex(columnIndex); if (nullable == DatabaseMetaData.columnNoNulls) { column = column.notNull(); } @@ -539,6 +541,13 @@ public class MetaDataExporter { module.bind(SQLCodegenModule.INNER_CLASSES_FOR_KEYS, innerClassesForKeys); } + /** + * @param columnComparator + */ + public void setColumnComparatorClass(Class> columnComparatorClass) { + module.bind(SQLCodegenModule.COLUMN_COMPARATOR, columnComparatorClass); + } + /** * @param serializerClass */ diff --git a/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/MetaDataSerializer.java b/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/MetaDataSerializer.java index 2e248cb3c..c31db6835 100644 --- a/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/MetaDataSerializer.java +++ b/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/MetaDataSerializer.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.lang.annotation.Annotation; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -28,6 +29,7 @@ import java.util.Set; import javax.inject.Inject; import javax.inject.Named; +import com.google.common.collect.Lists; import com.mysema.codegen.CodeWriter; import com.mysema.codegen.model.ClassType; import com.mysema.codegen.model.Parameter; @@ -35,7 +37,6 @@ import com.mysema.codegen.model.SimpleType; import com.mysema.codegen.model.Type; import com.mysema.codegen.model.TypeCategory; import com.mysema.codegen.model.Types; -import com.mysema.query.codegen.CodegenModule; import com.mysema.query.codegen.EntitySerializer; import com.mysema.query.codegen.EntityType; import com.mysema.query.codegen.Property; @@ -64,6 +65,8 @@ public class MetaDataSerializer extends EntitySerializer { private final boolean innerClassesForKeys; private final Set imports; + + private final Comparator columnComparator; /** * Create a new MetaDataSerializer instance @@ -77,11 +80,13 @@ public class MetaDataSerializer extends EntitySerializer { TypeMappings typeMappings, NamingStrategy namingStrategy, @Named(SQLCodegenModule.INNER_CLASSES_FOR_KEYS) boolean innerClassesForKeys, - @Named(SQLCodegenModule.IMPORTS) Set imports) { + @Named(SQLCodegenModule.IMPORTS) Set imports, + @Named(SQLCodegenModule.COLUMN_COMPARATOR) Comparator columnComparator) { super(typeMappings,Collections.emptyList()); this.namingStrategy = namingStrategy; this.innerClassesForKeys = innerClassesForKeys; this.imports = new HashSet(imports); + this.columnComparator = columnComparator; } @Override @@ -203,12 +208,17 @@ public class MetaDataSerializer extends EntitySerializer { @Override protected void outro(EntityType model, CodeWriter writer) throws IOException { writer.beginPublicMethod(Types.VOID,"addMetadata"); - for (Property property : model.getProperties()) { + List properties = Lists.newArrayList(model.getProperties()); + if (columnComparator != null) { + Collections.sort(properties, columnComparator); + } + for (Property property : properties) { String name = property.getEscapedName(); ColumnMetadata metadata = (ColumnMetadata) property.getData().get("COLUMN"); StringBuilder columnMeta = new StringBuilder(); columnMeta.append("ColumnMetadata"); columnMeta.append(".named(\"" + metadata.getName() + "\")"); + columnMeta.append(".withIndex(" + metadata.getIndex() + ")"); columnMeta.append(".ofType(" + metadata.getJdbcType() + ")"); if (metadata.hasSize()) { columnMeta.append(".withSize(" + metadata.getSize() + ")"); diff --git a/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/OrdinalPositionComparator.java b/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/OrdinalPositionComparator.java new file mode 100644 index 000000000..5bc9079bb --- /dev/null +++ b/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/OrdinalPositionComparator.java @@ -0,0 +1,28 @@ +package com.mysema.query.sql.codegen; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.Map; + +import com.mysema.query.codegen.Property; +import com.mysema.query.sql.ColumnMetadata; + +public class OrdinalPositionComparator implements Comparator { + + public OrdinalPositionComparator() { + super(); + } + + @Override + public int compare(Property property1, Property property2) { + Integer comparison = null; + for (Property property : Arrays.asList(property1, property2)) { + Map data = property.getData(); + ColumnMetadata columnMetadata = (ColumnMetadata) data.get("COLUMN"); + int index = columnMetadata.getIndex(); + comparison = comparison == null ? index : comparison - index; + } + return comparison; + } + +} diff --git a/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/OriginalNamingStrategy.java b/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/OriginalNamingStrategy.java index 172895ec7..dab998c5b 100644 --- a/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/OriginalNamingStrategy.java +++ b/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/OriginalNamingStrategy.java @@ -58,21 +58,6 @@ public class OriginalNamingStrategy extends AbstractNamingStrategy { return getPropertyName(primaryKeyName); } - @Override - public String normalizeColumnName(String columnName) { - return columnName.replaceAll("\r", "").replaceAll("\n", " "); - } - - @Override - public String normalizeTableName(String tableName) { - return tableName.replaceAll("\r", "").replaceAll("\n", " "); - } - - @Override - public String normalizeSchemaName(String schemaName) { - return schemaName.replaceAll("\r", "").replaceAll("\n", " "); - } - private String getPropertyName(String name) { return Naming.normalize(name, reservedSuffix); } diff --git a/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/SQLCodegenModule.java b/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/SQLCodegenModule.java index cf3c2f2e0..7574e6bc4 100644 --- a/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/SQLCodegenModule.java +++ b/querydsl-sql-codegen/src/main/java/com/mysema/query/sql/codegen/SQLCodegenModule.java @@ -42,6 +42,8 @@ public class SQLCodegenModule extends CodegenModule{ public static final String SCHEMA_TO_PACKAGE = "schemaToPackage"; + public static final String COLUMN_COMPARATOR = "columnComparator"; + @Override protected void configure() { super.configure(); @@ -57,6 +59,7 @@ public class SQLCodegenModule extends CodegenModule{ bind(PACKAGE_NAME, "com.example"); bind(BEAN_SERIALIZER, (Class)null); bind(SCHEMA_TO_PACKAGE, false); + bind(COLUMN_COMPARATOR, null); } public String getPrefix() { diff --git a/querydsl-sql-codegen/src/test/java/com/mysema/query/sql/codegen/MetaDataExporterTest.java b/querydsl-sql-codegen/src/test/java/com/mysema/query/sql/codegen/MetaDataExporterTest.java index 793300cb1..4d8212675 100644 --- a/querydsl-sql-codegen/src/test/java/com/mysema/query/sql/codegen/MetaDataExporterTest.java +++ b/querydsl-sql-codegen/src/test/java/com/mysema/query/sql/codegen/MetaDataExporterTest.java @@ -115,6 +115,12 @@ public class MetaDataExporterTest { // multi key stmt.execute("create table multikey(id INT, id2 VARCHAR, id3 INT, CONSTRAINT pk_multikey PRIMARY KEY (id, id2, id3) )"); + // M_PRODUCT_BOM_ID + stmt.execute("create table product(id int, " + + "m_product_bom_id int, " + + "m_productbom_id int, " + + "constraint product_bom foreign key (m_productbom_id) references product(id))"); + }finally{ stmt.close(); } @@ -146,14 +152,14 @@ public class MetaDataExporterTest { @Test public void NormalSettings_Repetition() throws SQLException { - test("Q", "", "", "", defaultNaming, "target/1", false, false); + test("Q", "", "", "", defaultNaming, "target/1", false, false, false); File file = new File("target/1/test/QEmployee.java"); long lastModified = file.lastModified(); assertTrue(file.exists()); clean = false; - test("Q", "", "", "", defaultNaming, "target/1", false, false); + test("Q", "", "", "", defaultNaming, "target/1", false, false, false); assertEquals(lastModified, file.lastModified()); } @@ -173,14 +179,15 @@ public class MetaDataExporterTest { for (boolean exportColumns : trueAndFalse) { for (String beanPackage : Arrays.asList("test2", null)) { for (Serializer beanSerializer : BEAN_SERIALIZERS) { + for (boolean withOriginalPositioning : trueAndFalse) { counter++; this.beanPackageName = beanPackage; this.schemaToPackage = schemaToPackage; this.exportColumns = exportColumns; this.beanSerializer = beanSerializer; test(namePrefix, nameSuffix, beanPrefix, beanSuffix, - ns, "target/multiple_"+counter, withBeans, withInnerClasses); - }}}}}}}}}}} + ns, "target/multiple_"+counter, withBeans, withInnerClasses, withOriginalPositioning); + }}}}}}}}}}}} } @Test @@ -284,7 +291,7 @@ public class MetaDataExporterTest { private void test(String namePrefix, String nameSuffix, String beanPrefix, String beanSuffix, NamingStrategy namingStrategy, String target, boolean withBeans, - boolean withInnerClasses) throws SQLException{ + boolean withInnerClasses, boolean withOrdinalPositioning) throws SQLException{ File targetDir = new File(target); if (clean) { try { @@ -312,6 +319,9 @@ public class MetaDataExporterTest { if (withBeans) { exporter.setBeanSerializer(beanSerializer); } + if (withOrdinalPositioning) { + exporter.setColumnComparatorClass(OrdinalPositionComparator.class); + } exporter.export(connection.getMetaData()); JavaCompiler compiler = new SimpleCompiler(); diff --git a/querydsl-sql/README.md b/querydsl-sql/README.md index 2f4b38bb0..ddb7938ec 100644 --- a/querydsl-sql/README.md +++ b/querydsl-sql/README.md @@ -1,4 +1,4 @@ -# Querydsl SQL # +## Querydsl SQL The SQL module provides integration with the JDBC API. diff --git a/querydsl-sql/pom.xml b/querydsl-sql/pom.xml index 4fea1efb9..60facda97 100644 --- a/querydsl-sql/pom.xml +++ b/querydsl-sql/pom.xml @@ -5,7 +5,7 @@ com.mysema.querydsl querydsl-root - 3.3.2.BUILD-SNAPSHOT + 3.3.3.BUILD-SNAPSHOT ../querydsl-root/pom.xml @@ -27,7 +27,7 @@ 1.6 - javax.validation + javax.validation validation-api 1.0.0.GA diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/CUBRIDTemplates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/CUBRIDTemplates.java index 968fc5628..b1daa48df 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/CUBRIDTemplates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/CUBRIDTemplates.java @@ -52,6 +52,7 @@ public class CUBRIDTemplates extends SQLTemplates { setParameterMetadataAvailable(false); setNullsFirst(null); setNullsLast(null); + setDefaultValues("\ndefault values"); add(Ops.DateTimeOps.DAY_OF_YEAR, "dayofyear({0})"); add(Ops.DateTimeOps.DAY_OF_WEEK, "dayofweek({0})"); diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/ColumnMetadata.java b/querydsl-sql/src/main/java/com/mysema/query/sql/ColumnMetadata.java index 304ecf07c..490708f9d 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/ColumnMetadata.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/ColumnMetadata.java @@ -61,12 +61,14 @@ public final class ColumnMetadata implements Serializable { * if the name is null */ public static ColumnMetadata named(String name) { - return new ColumnMetadata(name, null, true, UNDEFINED, UNDEFINED); + return new ColumnMetadata(null, name, null, true, UNDEFINED, UNDEFINED); } private static final int UNDEFINED = -1; private final String name; + + private final Integer index; private final Integer jdbcType; @@ -76,8 +78,9 @@ public final class ColumnMetadata implements Serializable { private final int decimalDigits; - private ColumnMetadata(String name, Integer jdbcType, boolean nullable, int size, + private ColumnMetadata(Integer index, String name, Integer jdbcType, boolean nullable, int size, int decimalDigits) { + this.index = index; this.name = name; this.jdbcType = jdbcType; this.nullable = nullable; @@ -88,6 +91,14 @@ public final class ColumnMetadata implements Serializable { public String getName() { return name; } + + public int getIndex() { + return index; + } + + public ColumnMetadata withIndex(int index) { + return new ColumnMetadata(index, name, jdbcType, nullable, size, decimalDigits); + } public int getJdbcType() { return jdbcType; @@ -98,7 +109,7 @@ public final class ColumnMetadata implements Serializable { } public ColumnMetadata ofType(int jdbcType) { - return new ColumnMetadata(name, jdbcType, nullable, size, decimalDigits); + return new ColumnMetadata(index, name, jdbcType, nullable, size, decimalDigits); } public boolean isNullable() { @@ -106,7 +117,7 @@ public final class ColumnMetadata implements Serializable { } public ColumnMetadata notNull() { - return new ColumnMetadata(name, jdbcType, false, size, decimalDigits); + return new ColumnMetadata(index, name, jdbcType, false, size, decimalDigits); } /** @@ -123,7 +134,7 @@ public final class ColumnMetadata implements Serializable { } public ColumnMetadata withSize(int size) { - return new ColumnMetadata(name, jdbcType, nullable, size, decimalDigits); + return new ColumnMetadata(index, name, jdbcType, nullable, size, decimalDigits); } /** @@ -140,7 +151,7 @@ public final class ColumnMetadata implements Serializable { } public ColumnMetadata withDigits(int decimalDigits) { - return new ColumnMetadata(name, jdbcType, nullable, size, decimalDigits); + return new ColumnMetadata(index, name, jdbcType, nullable, size, decimalDigits); } @Override 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 5cbb73862..513aa0b3e 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 @@ -54,6 +54,7 @@ public class DerbyTemplates extends SQLTemplates { addClass2TypeMappings("smallint", Byte.class); setAutoIncrement(" generated always as identity"); setFunctionJoinsWrapped(true); + setDefaultValues("\nvalues (default)"); add(Ops.CONCAT, "varchar({0} || {1})"); add(Ops.DateTimeOps.DAY_OF_MONTH, "day({0})"); diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/HSQLDBTemplates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/HSQLDBTemplates.java index 1540cf12b..c164e75f0 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/HSQLDBTemplates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/HSQLDBTemplates.java @@ -44,6 +44,7 @@ public class HSQLDBTemplates extends SQLTemplates { super("\"", escape, quote); setLimitRequired(true); setAutoIncrement(" identity"); + setDefaultValues("\ndefault values"); add(Ops.TRIM, "trim(both from {0})"); add(Ops.NEGATE, "{0} * -1", 7); diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/PostgresTemplates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/PostgresTemplates.java index efbc677ef..de1821315 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/PostgresTemplates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/PostgresTemplates.java @@ -47,6 +47,7 @@ public class PostgresTemplates extends SQLTemplates { setDummyTable(null); setCountDistinctMultipleColumns(true); setCountViaAnalytics(true); + setDefaultValues("\ndefault values"); // type mappings addClass2TypeMappings("numeric(3,0)", Byte.class); diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/RelationalPathBase.java b/querydsl-sql/src/main/java/com/mysema/query/sql/RelationalPathBase.java index a53b8c0d4..c514039ce 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/RelationalPathBase.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/RelationalPathBase.java @@ -47,9 +47,7 @@ public class RelationalPathBase extends BeanPath implements RelationalPath @Nullable private PrimaryKey primaryKey; - private final List> columns = Lists.newArrayList(); - - private final Map, ColumnMetadata> columnMetadata = Maps.newHashMap(); + private final Map, ColumnMetadata> columnMetadata = Maps.newLinkedHashMap(); private final List> foreignKeys = Lists.newArrayList(); @@ -143,20 +141,19 @@ public class RelationalPathBase extends BeanPath implements RelationalPath } public Path[] all() { - Path[] all = new Path[columns.size()]; - columns.toArray(all); + Path[] all = new Path[columnMetadata.size()]; + columnMetadata.keySet().toArray(all); return all; } @Override protected

> P add(P path) { - columns.add(path); return path; } @Override public List> getColumns() { - return columns; + return Lists.newArrayList(this.columnMetadata.keySet()); } @Override 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 122b66fb0..e13315ef1 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 @@ -537,11 +537,15 @@ public class SQLSerializer extends SerializerBase { } } - // values - append(templates.getValues()); - append("("); - handle(COMMA, values); - append(")"); + if (!values.isEmpty()) { + // values + append(templates.getValues()); + append("("); + handle(COMMA, values); + append(")"); + } else { + append(templates.getDefaultValues()); + } } } 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 a1f31f650..b7cc5dbf2 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 @@ -53,6 +53,7 @@ public class SQLServerTemplates extends SQLTemplates { setDummyTable(""); setNullsFirst(null); setNullsLast(null); + setDefaultValues("\ndefault values"); // String add(Ops.CONCAT, "{0} + {1}", 13); 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 ede19e38d..e73db54e8 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 @@ -176,6 +176,8 @@ public class SQLTemplates extends Templates { private String values = "\nvalues "; + private String defaultValues = "\nvalues ()"; + private String where = "\nwhere "; private String with = "with "; @@ -584,6 +586,10 @@ public class SQLTemplates extends Templates { return values; } + public final String getDefaultValues() { + return defaultValues; + } + public final String getWhere() { return where; } @@ -946,6 +952,10 @@ public class SQLTemplates extends Templates { this.values = values; } + protected void setDefaultValues(String defaultValues) { + this.defaultValues = defaultValues; + } + protected void setWhere(String where) { this.where = where; } diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLiteTemplates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLiteTemplates.java index a69ff9d63..6c390ba38 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/SQLiteTemplates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/SQLiteTemplates.java @@ -50,6 +50,7 @@ public class SQLiteTemplates extends SQLTemplates { setLimitRequired(true); setNullsFirst(null); setNullsLast(null); + setDefaultValues("\ndefault values"); add(Ops.MOD, "{0} % {1}"); add(Ops.INDEX_OF, "charindex({1},{0},1)-1"); diff --git a/querydsl-sql/src/main/java/com/mysema/query/sql/TeradataTemplates.java b/querydsl-sql/src/main/java/com/mysema/query/sql/TeradataTemplates.java index e97cdd7eb..17217e9fe 100644 --- a/querydsl-sql/src/main/java/com/mysema/query/sql/TeradataTemplates.java +++ b/querydsl-sql/src/main/java/com/mysema/query/sql/TeradataTemplates.java @@ -57,6 +57,7 @@ public class TeradataTemplates extends SQLTemplates { setNullsLast(null); setDummyTable(null); setCountViaAnalytics(true); + setDefaultValues("\ndefault values"); addClass2TypeMappings("byteint", Byte.class); addClass2TypeMappings("double precision", Double.class); diff --git a/querydsl-sql/src/test/java/com/mysema/query/InsertBase.java b/querydsl-sql/src/test/java/com/mysema/query/InsertBase.java index d7f7dc923..0c64ddc16 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/InsertBase.java +++ b/querydsl-sql/src/test/java/com/mysema/query/InsertBase.java @@ -28,6 +28,9 @@ import static org.junit.Assert.assertTrue; import java.sql.ResultSet; import java.sql.SQLException; +import com.mysema.query.sql.domain.QDateTest; +import org.joda.time.DateTime; +import org.joda.time.LocalDate; import org.junit.After; import org.junit.Before; import org.junit.Ignore; @@ -53,6 +56,8 @@ public class InsertBase extends AbstractBaseTest { private void reset() throws SQLException{ delete(survey).execute(); insert(survey).values(1, "Hello World", "Hello").execute(); + + delete(QDateTest.qDateTest).execute(); } @Before @@ -65,6 +70,30 @@ public class InsertBase extends AbstractBaseTest { reset(); } + @Test + public void Insert_Dates() { + QDateTest dateTest = QDateTest.qDateTest; + LocalDate localDate = new LocalDate(1978, 1, 2); + + Path localDateProperty = new PathImpl(LocalDate.class, "DATE_TEST"); + Path dateTimeProperty = new PathImpl(DateTime.class, "DATE_TEST"); + SQLInsertClause insert = insert(dateTest); + insert.set(localDateProperty, localDate); + insert.execute(); + + Tuple result = query().from(dateTest).singleResult( + dateTest.dateTest.year(), + dateTest.dateTest.month(), + dateTest.dateTest.dayOfMonth(), + dateTimeProperty); + assertEquals(Integer.valueOf(1978), result.get(0, Integer.class)); + assertEquals(Integer.valueOf(1), result.get(1, Integer.class)); + assertEquals(Integer.valueOf(2), result.get(2, Integer.class)); + + DateTime dateTime = result.get(dateTimeProperty); + assertEquals(dateTime, localDate.toDateTimeAtStartOfDay()); + } + @Test public void Complex1() { // related to #584795 @@ -137,6 +166,12 @@ public class InsertBase extends AbstractBaseTest { .values(4, null, null).execute()); } + @Test + @ExcludeIn({HSQLDB, DERBY}) + public void Insert_Without_Values() { + assertEquals(1, insert(survey).execute()); + } + @Test @ExcludeIn(ORACLE) public void Insert_Nulls_In_Batch() { diff --git a/querydsl-sql/src/test/java/com/mysema/query/SelectBase.java b/querydsl-sql/src/test/java/com/mysema/query/SelectBase.java index 31e463c3d..947663e22 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/SelectBase.java +++ b/querydsl-sql/src/test/java/com/mysema/query/SelectBase.java @@ -50,6 +50,13 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import com.mysema.query.types.*; +import com.google.common.collect.Maps; +import junit.framework.Assert; +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.joda.time.LocalDateTime; +import org.joda.time.LocalTime; import org.junit.Ignore; import org.junit.Test; @@ -70,19 +77,6 @@ import com.mysema.query.sql.domain.QEmployee; import com.mysema.query.sql.domain.QEmployeeNoPK; import com.mysema.query.sql.domain.QIdName; import com.mysema.query.support.Expressions; -import com.mysema.query.types.ArrayConstructorExpression; -import com.mysema.query.types.Concatenation; -import com.mysema.query.types.ConstantImpl; -import com.mysema.query.types.ConstructorExpression; -import com.mysema.query.types.Expression; -import com.mysema.query.types.MappingProjection; -import com.mysema.query.types.ParamNotSetException; -import com.mysema.query.types.Path; -import com.mysema.query.types.PathImpl; -import com.mysema.query.types.Predicate; -import com.mysema.query.types.QBean; -import com.mysema.query.types.QTuple; -import com.mysema.query.types.SubQueryExpression; import com.mysema.query.types.expr.BooleanExpression; import com.mysema.query.types.expr.Coalesce; import com.mysema.query.types.expr.DateExpression; @@ -370,6 +364,56 @@ public class SelectBase extends AbstractBaseTest { } } + @Test + @IncludeIn({H2, SQLSERVER, MYSQL, ORACLE, SQLITE, TERADATA}) // TODO fix postgres + public void Dates() { + long ts = ((long)Math.floor(System.currentTimeMillis() / 1000)) * 1000; + long tsDate = new org.joda.time.LocalDate(ts).toDateMidnight().getMillis(); + long tsTime = new org.joda.time.LocalTime(ts).getMillisOfDay(); + + List data = Lists.newArrayList(); + data.add(new java.util.Date(ts)); + data.add(new java.util.Date(tsDate)); + data.add(new java.util.Date(tsTime)); + data.add(new java.sql.Timestamp(ts)); + data.add(new java.sql.Timestamp(tsDate)); + data.add(new java.sql.Date(110, 0, 1)); + data.add(new java.sql.Date(tsDate)); + data.add(new java.sql.Time(0, 0, 0)); + data.add(new java.sql.Time(12, 30, 0)); + data.add(new java.sql.Time(23, 59, 59)); + //data.add(new java.sql.Time(tsTime)); + data.add(new DateTime(ts)); + data.add(new DateTime(tsDate)); + data.add(new DateTime(tsTime)); + data.add(new LocalDateTime(ts)); + data.add(new LocalDateTime(tsDate)); + data.add(new LocalDateTime(2014, 3, 30, 2, 0)); + data.add(new LocalDate(2010, 1, 1)); + data.add(new LocalDate(ts)); + data.add(new LocalDate(tsDate)); + data.add(new LocalTime(0, 0, 0)); + data.add(new LocalTime(12, 30, 0)); + data.add(new LocalTime(23, 59, 59)); + data.add(new LocalTime(ts)); + data.add(new LocalTime(tsTime)); + + Map failures = Maps.newIdentityHashMap(); + for (Object dt : data) { + Object dt2 = query().singleResult(new ConstantImpl(dt)); + if (!dt.equals(dt2)) { + failures.put(dt, dt2); + } + } + if (!failures.isEmpty()) { + for (Map.Entry entry : failures.entrySet()) { + System.out.println(entry.getKey().getClass().getName() + + ": " + entry.getKey() + " != " + entry.getValue()); + } + Assert.fail("Failed with " + failures); + } + } + @Test @ExcludeIn({SQLITE}) public void Date_Add() { @@ -508,6 +552,12 @@ public class SelectBase extends AbstractBaseTest { assertTrue(query().from(employee).where(employee.firstname.eq("Barbara")).exists()); } + @Test + public void FactoryExpression_In_GroupBy() { + Expression empBean = Projections.bean(Employee.class, employee.id, employee.superiorId); + assertFalse(query().from(employee).groupBy(empBean).list(empBean).isEmpty()); + } + @Test @ExcludeIn({H2, SQLITE, DERBY, CUBRID, MYSQL}) public void Full_Join() 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 7247d831e..43950edf2 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 @@ -21,6 +21,8 @@ import java.sql.Time; import java.sql.Timestamp; import java.util.regex.Pattern; +import com.mysema.query.support.Expressions; +import com.mysema.query.types.path.NumberPath; import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.joda.time.LocalTime; @@ -102,5 +104,13 @@ public class SQLTemplatesTest { } + @Test + public void Numeric_Operations() { + NumberPath intPath = Expressions.numberPath(Integer.class, "intPath"); + NumberPath intPath2 = Expressions.numberPath(Integer.class, "intPath2"); + SQLSerializer serializer = new SQLSerializer(new Configuration(SQLTemplates.DEFAULT)); + serializer.handle(intPath.subtract(intPath2.add(2))); + assertEquals("intPath - (intPath2 + ?)", serializer.toString()); + } } diff --git a/querydsl-sql/src/test/java/com/mysema/query/sql/domain/QDateTest.java b/querydsl-sql/src/test/java/com/mysema/query/sql/domain/QDateTest.java new file mode 100644 index 000000000..c87832d2f --- /dev/null +++ b/querydsl-sql/src/test/java/com/mysema/query/sql/domain/QDateTest.java @@ -0,0 +1,33 @@ +package com.mysema.query.sql.domain; + +import com.mysema.query.sql.ColumnMetadata; +import com.mysema.query.sql.RelationalPathBase; +import com.mysema.query.types.PathMetadata; +import com.mysema.query.types.PathMetadataFactory; +import com.mysema.query.types.path.DatePath; + +import java.sql.Date; + +public class QDateTest extends RelationalPathBase { + + private static final long serialVersionUID = 1394463749655231079L; + + public static final QDateTest qDateTest = new QDateTest("DATE_TEST"); + + public final DatePath dateTest = createDate("dateTest", java.sql.Date.class); + + public QDateTest(String path) { + super(QDateTest.class, PathMetadataFactory.forVariable(path), "PUBLIC", "DATE_TEST"); + addMetadata(); + } + + public QDateTest(PathMetadata metadata) { + super(QDateTest.class, metadata, "PUBLIC", "DATE_TEST"); + addMetadata(); + } + + protected void addMetadata() { + addMetadata(dateTest, ColumnMetadata.named("DATE_TEST")); + } + +} diff --git a/querydsl-sql/src/test/java/com/mysema/query/types/LocalDateTimeTest.java b/querydsl-sql/src/test/java/com/mysema/query/sql/types/LocalDateTimeTest.java similarity index 96% rename from querydsl-sql/src/test/java/com/mysema/query/types/LocalDateTimeTest.java rename to querydsl-sql/src/test/java/com/mysema/query/sql/types/LocalDateTimeTest.java index 930681f30..4bdafc1d8 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/types/LocalDateTimeTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/sql/types/LocalDateTimeTest.java @@ -1,4 +1,4 @@ -package com.mysema.query.types; +package com.mysema.query.sql.types; import java.sql.PreparedStatement; import java.sql.SQLException; diff --git a/querydsl-sql/src/test/java/com/mysema/query/types/LocaleTypeTest.java b/querydsl-sql/src/test/java/com/mysema/query/sql/types/LocaleTypeTest.java similarity index 94% rename from querydsl-sql/src/test/java/com/mysema/query/types/LocaleTypeTest.java rename to querydsl-sql/src/test/java/com/mysema/query/sql/types/LocaleTypeTest.java index 2cb47ef5e..dfedc5d93 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/types/LocaleTypeTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/sql/types/LocaleTypeTest.java @@ -1,4 +1,4 @@ -package com.mysema.query.types; +package com.mysema.query.sql.types; import static org.junit.Assert.assertEquals; diff --git a/querydsl-sql/src/test/java/com/mysema/query/types/TypeTest.java b/querydsl-sql/src/test/java/com/mysema/query/sql/types/TypeTest.java similarity index 99% rename from querydsl-sql/src/test/java/com/mysema/query/types/TypeTest.java rename to querydsl-sql/src/test/java/com/mysema/query/sql/types/TypeTest.java index cb868782d..90e9e0e07 100644 --- a/querydsl-sql/src/test/java/com/mysema/query/types/TypeTest.java +++ b/querydsl-sql/src/test/java/com/mysema/query/sql/types/TypeTest.java @@ -11,7 +11,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.mysema.query.types; +package com.mysema.query.sql.types; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull;