Merged issue679 branch because of foreseen conflicts.

- conflicting getRealParameters moved to ConstructorUtils.

Merge branch 'master' of github.com:mysema/querydsl into issue679

Conflicts:
	querydsl-core/src/main/java/com/mysema/query/types/ConstructorExpression.java
This commit is contained in:
Ruben Dijkstra 2014-04-10 21:12:15 +02:00
commit ce2c062b44
80 changed files with 1547 additions and 825 deletions

View File

@ -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.

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-root</artifactId>
<version>3.3.2.BUILD-SNAPSHOT</version>
<version>3.3.3.BUILD-SNAPSHOT</version>
<relativePath>../querydsl-root/pom.xml</relativePath>
</parent>

View File

@ -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);
}
}
}
}

View File

@ -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");
}

View File

@ -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<SubjectPermission>
// 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());

View File

@ -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<EmailType, ManagedEmail> emails;
}
@Test
public void test() {
assertEquals(EmailType.class, QManagedEmailTest_ManagedEmails.managedEmails.emails.getKeyType());
assertEquals(ManagedEmailImpl.class, QManagedEmailTest_ManagedEmails.managedEmails.emails.getValueType());
}
}

View File

@ -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<PhoneNumber> phones;
}
@Test
public void test() {
assertEquals(PhoneNumberImpl.class, QManyToManyTest_Person.person.phones.getElementType());
}
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-root</artifactId>
<version>3.3.2.BUILD-SNAPSHOT</version>
<version>3.3.3.BUILD-SNAPSHOT</version>
<relativePath>../querydsl-root/pom.xml</relativePath>
</parent>

View File

@ -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<Integer> 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<Parameter, Parameter>() {
@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);
}
});

View File

@ -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<Integer> sizes = Sets.newHashSet();
for (Constructor c : model.getConstructors()) {
final boolean asExpr = sizes.add(c.getParameters().size());
// begin
writer.beginConstructor(c.getParameters(), new Function<Parameter,Parameter>() {
@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);
}
});

View File

@ -75,7 +75,12 @@ public final class Property implements Comparable<Property> {
@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) {

View File

@ -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<Integer> age"));
assertTrue(writer.toString().contains("Expression<String> firstName"));
assertTrue(writer.toString().contains("Expression<String> lastName"));
assertTrue(writer.toString().contains("Expression<Integer> age"));
}
}

View File

@ -1,4 +1,4 @@
# Querydsl Collections #
## Querydsl Collections
The Collections module provides integration with Java Collections and Beans.

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-root</artifactId>
<version>3.3.2.BUILD-SNAPSHOT</version>
<version>3.3.3.BUILD-SNAPSHOT</version>
<relativePath>../querydsl-root/pom.xml</relativePath>
</parent>

View File

@ -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<Object> nullList = Arrays.<Object>asList((Object)null);
public static boolean equals(Object o1, Object o2) {
return Objects.equal(o1, o2);
}
public static <T extends Comparable<? super T>> 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 <A extends Comparable<? super A>> 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) {

View File

@ -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 <T>
*/
public class CollQueryMixin<T> extends QueryMixin<T> {
private static final Predicate ANY = BooleanTemplate.create("any");
public CollQueryMixin() {}
@ -42,22 +42,22 @@ public class CollQueryMixin<T> extends QueryMixin<T> {
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;
}
}
}
}

View File

@ -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

View File

@ -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<String> meshThesaurusTerms = new ArrayList<String>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public List<String> getMeshThesaurusTerms() {
return meshThesaurusTerms;
}
public void setMeshThesaurusTerms(List<String> meshThesaurusTerms) {
this.meshThesaurusTerms = meshThesaurusTerms;
}
}

View File

@ -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<Document> 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<Document> 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<Document> 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<Document> 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!
}
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-root</artifactId>
<version>3.3.2.BUILD-SNAPSHOT</version>
<version>3.3.3.BUILD-SNAPSHOT</version>
<relativePath>../querydsl-root/pom.xml</relativePath>
</parent>

View File

@ -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<Expression<?>, Void> {
@Override
public Expression<?> visit(Constant<?> expr, @Nullable Void context) {
return expr;
}
@Override
public Expression<?> visit(FactoryExpression<?> expr, @Nullable Void context) {
List<Expression<?>> 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<Expression<?>> 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<ParamExpression<?>, 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<Expression<?>> visit(List<Expression<?>> args) {
ImmutableList.Builder<Expression<?>> builder = ImmutableList.builder();
for (Expression<?> arg : args) {
builder.add(arg.accept(this, null));
}
return builder.build();
}
}

View File

@ -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 <A> Cases<A, SimpleExpression<A>> then(Expression<A> 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 <A> Cases<A, SimpleExpression<A>> thenSimple(Expression<A> expr) {
return new Cases<A, SimpleExpression<A>>((Class)expr.getType()) {
@Override
protected SimpleExpression<A> createResult(Class<A> type, Expression<A> last) {
@ -176,12 +195,12 @@ public final class CaseBuilder {
}
public <A> Cases<A, SimpleExpression<A>> then(A constant) {
return then(ConstantImpl.create(constant));
return thenSimple(ConstantImpl.create(constant));
}
// Boolean
public Cases<Boolean,BooleanExpression> then(BooleanExpression expr) {
public Cases<Boolean, BooleanExpression> then(BooleanExpression expr) {
return thenBoolean(expr);
}
@ -200,6 +219,26 @@ public final class CaseBuilder {
return thenBoolean(ConstantImpl.create(b));
}
// Comparable
public <T extends Comparable> Cases<T, ComparableExpression<T>> then(ComparableExpression<T> expr) {
return thenComparable(expr);
}
private <T extends Comparable> Cases<T, ComparableExpression<T>> thenComparable(Expression<T> expr) {
return new Cases<T, ComparableExpression<T>>((Class)expr.getType()) {
@Override
protected ComparableExpression<T> createResult(Class<T> type, Expression<T> last) {
return ComparableOperation.create(type, Ops.CASE, last);
}
}.addCase(when, expr);
}
public <A extends Comparable> Cases<A, ComparableExpression<A>> then(A arg) {
return thenComparable(ConstantImpl.create(arg));
}
// Date
public <T extends Comparable> Cases<T, DateExpression<T>> then(DateExpression<T> expr) {
@ -216,7 +255,7 @@ public final class CaseBuilder {
}.addCase(when, expr);
}
public Cases<java.sql.Date, DateExpression<java.sql.Date>> thenDate(java.sql.Date date) {
public Cases<java.sql.Date, DateExpression<java.sql.Date>> then(java.sql.Date date) {
return thenDate(ConstantImpl.create(date));
}
@ -236,11 +275,11 @@ public final class CaseBuilder {
}.addCase(when, expr);
}
public Cases<Timestamp, DateTimeExpression<Timestamp>> thenDateTime(Timestamp ts) {
public Cases<Timestamp, DateTimeExpression<Timestamp>> then(Timestamp ts) {
return thenDateTime(ConstantImpl.create(ts));
}
public Cases<java.util.Date, DateTimeExpression<java.util.Date>> thenDateTime(java.util.Date date) {
public Cases<java.util.Date, DateTimeExpression<java.util.Date>> then(java.util.Date date) {
return thenDateTime(ConstantImpl.create(date));
}

View File

@ -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<String> str = new StringPath(new PathImpl(Object.class, "customer"), "name");
Expression<String> str2 = new StringPath("str");
Expression<String> 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<String> str = new StringPath(new PathImpl(Object.class, "customer"), "name");
Expression<String> str2 = new StringPath("str");
Expression<String> concat = Expressions.stringTemplate("{0} + {1}", str, str2);
assertEquals("customer.name + str", concat.toString());
assertEquals("customer_.name + str_", concat.accept(visitor, null).toString());
}
}

View File

@ -1,6 +1,6 @@
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY versionNumber "3.3.1">
<!ENTITY versionNumber "3.3.2">
<!ENTITY copyrightYear "2007-2014">
<!ENTITY copyrightHolder "Mysema Ltd.">
]>

View File

@ -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();
]]></programlisting>
<para>The second parameter of the JPADeleteClause constructor is the entity to

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-root</artifactId>
<version>3.3.2.BUILD-SNAPSHOT</version>
<version>3.3.3.BUILD-SNAPSHOT</version>
<relativePath>../querydsl-root/pom.xml</relativePath>
</parent>

View File

@ -1,4 +1,4 @@
# Querydsl JDO #
## Querydsl JDO
The JDO module provides integration with the JDO API.

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-root</artifactId>
<version>3.3.2.BUILD-SNAPSHOT</version>
<version>3.3.3.BUILD-SNAPSHOT</version>
<relativePath>../querydsl-root/pom.xml</relativePath>
</parent>

View File

@ -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<Product> 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() {

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-root</artifactId>
<version>3.3.2.BUILD-SNAPSHOT</version>
<version>3.3.3.BUILD-SNAPSHOT</version>
<relativePath>../querydsl-root/pom.xml</relativePath>
</parent>

View File

@ -1,4 +1,4 @@
# Querydsl JPA #
## Querydsl JPA
The JPA module provides integration with the JPA 2 persistence API.

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-root</artifactId>
<version>3.3.2.BUILD-SNAPSHOT</version>
<version>3.3.3.BUILD-SNAPSHOT</version>
<relativePath>../querydsl-root/pom.xml</relativePath>
</parent>

View File

@ -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<T> extends QueryMixin<T> {
private final Map<Expression<?>, 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<T> extends QueryMixin<T> {
}
}
private <T> Path<T> convertPathForOrder(Path<T> 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<T>(path.getType(),
new PathMetadata(shortened, metadata.getElement(), metadata.getPathType()));
} else {
return path;
}
}
@Override
public <RT> Expression<RT> convert(Expression<RT> 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<RT>(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<RT>)expr.accept(replaceVisitor, null);
}
}
return Conversions.convert(super.convert(expr, forOrder));

View File

@ -331,18 +331,6 @@ public class JPQLSerializer extends SerializerBase<JPQLSerializer> {
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<? extends Expression<?>> args) {

View File

@ -1139,6 +1139,12 @@ public abstract class AbstractJPATest {
assertEquals(2l, query().from(cat).where(where).count());
}
@Test
public void FactoryExpression_In_GroupBy() {
Expression<Cat> catBean = Projections.bean(Cat.class, cat.id, cat.name);
assertFalse(query().from(cat).groupBy(catBean).list(catBean).isEmpty());
}
@Test
@Ignore
public void Size() {

View File

@ -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;

View File

@ -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.
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-lucene</artifactId>
<artifactId>querydsl-lucene3</artifactId>
<version>${querydsl.version}</version>
</dependency>
@ -16,7 +16,7 @@ The Lucene module provides integration with the Lucene indexing library.
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.1</version>
</dependency>
</dependency>
**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
For more information on the Querydsl Lucene module visit the reference documentation http://www.querydsl.com/static/querydsl/latest/reference/html/ch02s04.html

View File

@ -5,13 +5,13 @@
<parent>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-root</artifactId>
<version>3.3.2.BUILD-SNAPSHOT</version>
<version>3.3.3.BUILD-SNAPSHOT</version>
<relativePath>../querydsl-root/pom.xml</relativePath>
</parent>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-lucene3</artifactId>
<name>Querydsl - Lucene support</name>
<name>Querydsl - Lucene 3 support</name>
<description>Lucene support for Querydsl</description>
<packaging>jar</packaging>

View File

@ -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.
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-lucene</artifactId>
<artifactId>querydsl-lucene4</artifactId>
<version>${querydsl.version}</version>
</dependency>

View File

@ -5,13 +5,13 @@
<parent>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-root</artifactId>
<version>3.3.2.BUILD-SNAPSHOT</version>
<version>3.3.3.BUILD-SNAPSHOT</version>
<relativePath>../querydsl-root/pom.xml</relativePath>
</parent>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-lucene4</artifactId>
<name>Querydsl - Lucene support</name>
<name>Querydsl - Lucene 4 support</name>
<description>Lucene support for Querydsl</description>
<packaging>jar</packaging>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-root</artifactId>
<version>3.3.2.BUILD-SNAPSHOT</version>
<version>3.3.3.BUILD-SNAPSHOT</version>
<relativePath>../querydsl-root/pom.xml</relativePath>
</parent>

View File

@ -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);

View File

@ -1,4 +1,4 @@
# Querydsl Mongodb #
## Querydsl Mongodb
The Mongodb module provides integration with the Mongodb API.

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-root</artifactId>
<version>3.3.2.BUILD-SNAPSHOT</version>
<version>3.3.3.BUILD-SNAPSHOT</version>
<relativePath>../querydsl-root/pom.xml</relativePath>
</parent>

View File

@ -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<User> 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"}}}

View File

@ -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")));

View File

@ -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;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-root</artifactId>
<version>3.3.2.BUILD-SNAPSHOT</version>
<version>3.3.3.BUILD-SNAPSHOT</version>
<relativePath>../querydsl-root/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-root</artifactId>
<version>3.3.2.BUILD-SNAPSHOT</version>
<version>3.3.3.BUILD-SNAPSHOT</version>
<relativePath>../querydsl-root/pom.xml</relativePath>
</parent>

View File

@ -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());

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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";
}

View File

@ -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<? extends Comparator<Property>> columnComparatorClass) {
module.bind(SQLCodegenModule.COLUMN_COMPARATOR, columnComparatorClass);
}
/**
* @param serializerClass
*/

View File

@ -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<String> imports;
private final Comparator<Property> 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<String> imports) {
@Named(SQLCodegenModule.IMPORTS) Set<String> imports,
@Named(SQLCodegenModule.COLUMN_COMPARATOR) Comparator<Property> columnComparator) {
super(typeMappings,Collections.<String>emptyList());
this.namingStrategy = namingStrategy;
this.innerClassesForKeys = innerClassesForKeys;
this.imports = new HashSet<String>(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<Property> 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() + ")");

View File

@ -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<Property> {
public OrdinalPositionComparator() {
super();
}
@Override
public int compare(Property property1, Property property2) {
Integer comparison = null;
for (Property property : Arrays.asList(property1, property2)) {
Map<Object, Object> data = property.getData();
ColumnMetadata columnMetadata = (ColumnMetadata) data.get("COLUMN");
int index = columnMetadata.getIndex();
comparison = comparison == null ? index : comparison - index;
}
return comparison;
}
}

View File

@ -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);
}

View File

@ -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() {

View File

@ -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();

View File

@ -1,4 +1,4 @@
# Querydsl SQL #
## Querydsl SQL
The SQL module provides integration with the JDBC API.

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-root</artifactId>
<version>3.3.2.BUILD-SNAPSHOT</version>
<version>3.3.3.BUILD-SNAPSHOT</version>
<relativePath>../querydsl-root/pom.xml</relativePath>
</parent>
@ -27,7 +27,7 @@
<version>1.6</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>

View File

@ -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})");

View File

@ -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

View File

@ -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})");

View File

@ -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);

View File

@ -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);

View File

@ -47,9 +47,7 @@ public class RelationalPathBase<T> extends BeanPath<T> implements RelationalPath
@Nullable
private PrimaryKey<T> primaryKey;
private final List<Path<?>> columns = Lists.newArrayList();
private final Map<Path<?>, ColumnMetadata> columnMetadata = Maps.newHashMap();
private final Map<Path<?>, ColumnMetadata> columnMetadata = Maps.newLinkedHashMap();
private final List<ForeignKey<?>> foreignKeys = Lists.newArrayList();
@ -143,20 +141,19 @@ public class RelationalPathBase<T> extends BeanPath<T> 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 extends Path<?>> P add(P path) {
columns.add(path);
return path;
}
@Override
public List<Path<?>> getColumns() {
return columns;
return Lists.newArrayList(this.columnMetadata.keySet());
}
@Override

View File

@ -537,11 +537,15 @@ public class SQLSerializer extends SerializerBase<SQLSerializer> {
}
}
// 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());
}
}
}

View File

@ -53,6 +53,7 @@ public class SQLServerTemplates extends SQLTemplates {
setDummyTable("");
setNullsFirst(null);
setNullsLast(null);
setDefaultValues("\ndefault values");
// String
add(Ops.CONCAT, "{0} + {1}", 13);

View File

@ -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;
}

View File

@ -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");

View File

@ -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);

View File

@ -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<LocalDate> localDateProperty = new PathImpl<LocalDate>(LocalDate.class, "DATE_TEST");
Path<DateTime> dateTimeProperty = new PathImpl<DateTime>(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() {

View File

@ -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<Object> 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<Object, Object> 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<Object, Object> 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<Employee> 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 {

View File

@ -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<Integer> intPath = Expressions.numberPath(Integer.class, "intPath");
NumberPath<Integer> 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());
}
}

View File

@ -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<QDateTest> {
private static final long serialVersionUID = 1394463749655231079L;
public static final QDateTest qDateTest = new QDateTest("DATE_TEST");
public final DatePath<Date> 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"));
}
}

View File

@ -1,4 +1,4 @@
package com.mysema.query.types;
package com.mysema.query.sql.types;
import java.sql.PreparedStatement;
import java.sql.SQLException;

View File

@ -1,4 +1,4 @@
package com.mysema.query.types;
package com.mysema.query.sql.types;
import static org.junit.Assert.assertEquals;

View File

@ -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;