added tests for case statements

This commit is contained in:
Timo Westkämper 2009-11-11 11:50:47 +00:00
parent 96adcb6020
commit 6d24ea7c10
15 changed files with 193 additions and 124 deletions

View File

@ -47,7 +47,7 @@
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.2.1.ga</version>
<version>3.4.0.GA</version>
<scope>test</scope>
</dependency>
</dependencies>

View File

@ -63,7 +63,7 @@ public class ColQueryTemplates extends JavaTemplates {
// TEMPORARY FIXES
add(Ops.DIV, "((double){0}) / ((double){1})");
add(Ops.DIV, "(double)({0}/{1})");
}
public static boolean like(String str, String like){

View File

@ -94,11 +94,11 @@ public class EvaluatorFactory {
};
} catch (CompileException e) {
throw new RuntimeException(e.getMessage(), e);
throw new RuntimeException(e.getMessage() + " with source " + javaSource, e);
} catch (ParseException e) {
throw new RuntimeException(e.getMessage(), e);
throw new RuntimeException(e.getMessage() + " with source " + javaSource, e);
} catch (ScanException e) {
throw new RuntimeException(e.getMessage(), e);
throw new RuntimeException(e.getMessage() + " with source " + javaSource, e);
}
}

View File

@ -71,6 +71,11 @@ public class JavaTemplates extends Templates {
add(Ops.DateTimeOps.SECOND, "{0}.getSecond()");
add(Ops.DateTimeOps.WEEK, "{0}.getWeek()");
add(Ops.DateTimeOps.YEAR, "{0}.getYear()");
// case
add(Ops.CASE, "({0})");
add(Ops.CASE_WHEN, "({0}) ? ({1}) : ({2})");
add(Ops.CASE_ELSE, "{0}");
// Math
try {

View File

@ -3,7 +3,6 @@ package com.mysema.query.types;
import java.util.ArrayList;
import java.util.List;
import com.mysema.query.types.custom.CSimple;
import com.mysema.query.types.expr.EBoolean;
import com.mysema.query.types.expr.Expr;
import com.mysema.query.types.operation.OSimple;
@ -15,9 +14,21 @@ import com.mysema.query.types.operation.Ops;
*/
public class CaseBuilder {
private class CaseElement<A> {
final EBoolean condition;
final Expr<A> target;
public CaseElement(EBoolean condition, Expr<A> target){
this.condition = condition;
this.target = target;
}
}
public class Cases<A> {
private final List<Expr<?>> exprs = new ArrayList<Expr<?>>();
private final List<CaseElement<A>> cases = new ArrayList<CaseElement<A>>();
private final Class<A> type;
@ -26,26 +37,29 @@ public class CaseBuilder {
}
Cases<A> addCase(EBoolean condition, Expr<A> expr) {
exprs.add(OSimple.create(type, Ops.CASE_WHEN, condition, expr));
cases.add(0, new CaseElement<A>(condition, expr));
return this;
}
private Expr<A> createChain(List<Expr<?>> exprs) {
StringBuilder builder = new StringBuilder(exprs.size() * 4);
for (int i = 0; i < exprs.size(); i++){
if (i > 0) builder.append(" ");
builder.append("{").append(i).append("}");
}
return new CSimple<A>(type, exprs, templateFactory.create(builder.toString()));
}
public Expr<A> otherwise(A constant) {
return otherwise(Expr.create(constant));
}
public Expr<A> otherwise(Expr<A> expr) {
exprs.add(OSimple.create(type, Ops.CASE_ELSE, expr));
return OSimple.create(type, Ops.CASE, createChain(exprs));
cases.add(0, new CaseElement<A>(null, expr));
Expr<A> last = null;
for (CaseElement<A> element : cases){
if (last == null){
last = OSimple.create(type, Ops.CASE_ELSE,
element.target);
}else{
last = OSimple.create(type, Ops.CASE_WHEN,
element.condition,
element.target,
last);
}
}
return OSimple.create(type, Ops.CASE, last);
}
public CaseWhen<A> when(EBoolean b) {
@ -66,7 +80,7 @@ public class CaseBuilder {
}
public Cases<A> then(A constant) {
return cases.addCase(b, Expr.create(constant));
return then(Expr.create(constant));
}
public Cases<A> then(Expr<A> expr) {
@ -76,26 +90,22 @@ public class CaseBuilder {
public class Initial {
private final EBoolean b;
private final EBoolean when;
public Initial(EBoolean b) {
this.b = b;
this.when = b;
}
@SuppressWarnings("unchecked")
public <A> Cases<A> then(A constant) {
return new Cases<A>((Class) constant.getClass()).addCase(b, Expr.create(constant));
return then(Expr.create(constant));
}
@SuppressWarnings("unchecked")
public <A> Cases<A> then(Expr<A> expr) {
return new Cases<A>((Class)expr.getType()).addCase(b, expr);
return new Cases<A>((Class)expr.getType()).addCase(when, expr);
}
}
private static final TemplateFactory templateFactory = new TemplateFactory();
public Initial when(EBoolean b) {
return new Initial(b);
}

View File

@ -165,7 +165,7 @@ public class Templates {
// case
add(Ops.CASE, "case {0} end");
add(Ops.CASE_WHEN, "when {0} then {1}");
add(Ops.CASE_WHEN, "when {0} then {1} {2}");
add(Ops.CASE_ELSE, "else {0}");
// subquery

View File

@ -21,6 +21,47 @@ public abstract class EComparable<D extends Comparable> extends EComparableBase<
public EComparable(Class<? extends D> type) {
super(type);
}
/**
* Create a <code>from &lt; this &lt; to</code> expression
*
* @param from
* @param to
* @return
*/
public final EBoolean between(D from, D to) {
return OBoolean.create(Ops.BETWEEN, this, ExprConst.create(from), ExprConst.create(to));
}
/**
* Create a <code>first &lt; this &lt; second</code> expression
*
* @param from
* @param to
* @return
*/
public final EBoolean between(Expr<D> from, Expr<D> to) {
return OBoolean.create(Ops.BETWEEN, this, from, to);
}
/**
* @param from
* @param to
* @return
*/
public final EBoolean notBetween(D from, D to) {
return between(from, to).not();
}
/**
* @param from
* @param to
* @return
*/
public final EBoolean notBetween(Expr<D> from, Expr<D> to) {
return between(from, to).not();
}
/**
* Create a <code>this &gt; right</code> expression

View File

@ -7,7 +7,6 @@ package com.mysema.query.types.expr;
import com.mysema.query.types.Order;
import com.mysema.query.types.OrderSpecifier;
import com.mysema.query.types.operation.OBoolean;
import com.mysema.query.types.operation.ONumber;
import com.mysema.query.types.operation.OString;
import com.mysema.query.types.operation.Ops;
@ -44,30 +43,7 @@ public abstract class EComparableBase<D extends Comparable> extends Expr<D> {
}
return asc;
}
/**
* Create a <code>first &lt; this &lt; second</code> expression
*
* @param first
* @param second
* @return
*/
public final EBoolean between(D first, D second) {
return OBoolean.create(Ops.BETWEEN, this, ExprConst.create(first), ExprConst.create(second));
}
/**
* Create a <code>first &lt; this &lt; second</code> expression
*
* @param first
* @param second
* @return
*/
public final EBoolean between(Expr<D> first, Expr<D> second) {
return OBoolean.create(Ops.BETWEEN, this, first, second);
}
/**
* Create a cast expression to the given numeric type
*
@ -91,24 +67,6 @@ public abstract class EComparableBase<D extends Comparable> extends Expr<D> {
return desc;
}
/**
* @param first
* @param second
* @return
*/
public final EBoolean notBetween(D first, D second) {
return between(first, second).not();
}
/**
* @param first
* @param second
* @return
*/
public final EBoolean notBetween(Expr<D> first, Expr<D> second) {
return between(first, second).not();
}
/**
* Get a cast to String expression
*

View File

@ -328,7 +328,49 @@ public abstract class ENumber<D extends Number & Comparable<?>> extends ECompara
public final <A extends Number & Comparable<?>> EBoolean gt(A right) {
return gt(ENumber.create(cast(right)));
}
/**
* Create a <code>from &lt; this &lt; to</code> expression
*
* @param <A>
* @param from
* @param to
* @return
*/
public final <A extends Number & Comparable<?>> EBoolean between(A from, A to) {
return OBoolean.create(Ops.BETWEEN, this, ExprConst.create(from), ExprConst.create(to));
}
/**
* Create a <code>from &lt; this &lt; to</code> expression
*
* @param <A>
* @param from
* @param to
* @return
*/
public final <A extends Number & Comparable<?>> EBoolean between(Expr<A> from, Expr<A> to) {
return OBoolean.create(Ops.BETWEEN, this, from, to);
}
/**
* @param from
* @param to
* @return
*/
public final <A extends Number & Comparable<?>> EBoolean notBetween(A from, A to) {
return between(from, to).not();
}
/**
* @param from
* @param to
* @return
*/
public final <A extends Number & Comparable<?>> EBoolean notBetween(Expr<A> from, Expr<A> to) {
return between(from, to).not();
}
/**
* Create a <code>this &gt; right</code> expression
*

View File

@ -9,6 +9,8 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import com.mysema.query.types.CaseBuilder;
import com.mysema.query.types.expr.Constant;
import com.mysema.query.types.expr.ECollection;
import com.mysema.query.types.expr.EDate;
import com.mysema.query.types.expr.EDateTime;
@ -28,12 +30,12 @@ import com.mysema.query.types.expr.Expr;
*/
public class Projections {
// private final Module module;
private final Module module;
private final Target target;
public Projections(Module module, Target target) {
// this.module = module;
this.module = module;
this.target = target;
}
@ -79,6 +81,14 @@ public class Projections {
}
<A extends Number & Comparable<A>> Collection<ENumber<?>> numeric(ENumber<A> expr, ENumber<A> other, A knownValue){
HashSet<ENumber<?>> rv = new HashSet<ENumber<?>>();
rv.addAll(numeric(expr, other));
rv.addAll(numeric(expr, ENumber.create(knownValue)));
return rv;
}
@SuppressWarnings("unchecked")
private <A extends Number & Comparable<A>> Collection<ENumber<?>> numeric(ENumber<A> expr, ENumber<?> other){
HashSet<ENumber<?>> rv = new HashSet<ENumber<?>>();
rv.add(expr.abs());
rv.add(expr.add(other));
@ -87,10 +97,14 @@ public class Projections {
rv.add(expr.sqrt());
rv.add(expr.subtract(other));
// CaseBuilder cases = new CaseBuilder();
// rv.add(ENumber.create(1).add(cases
// .when(expr.gt(0)).then(1)
// .otherwise(0)));
if (!(other instanceof Constant || module == Module.JDOQL)){
CaseBuilder cases = new CaseBuilder();
rv.add(ENumber.create(1).add(cases
.when(expr.gt(10)).then(expr)
.when(expr.between(0, 10)).then((ENumber)other)
.otherwise((ENumber)other)));
}
return rv;
}
@ -117,6 +131,7 @@ public class Projections {
return rv;
}
@SuppressWarnings("unchecked")
Collection<Expr<String>> stringProjections(EString expr, EString other){
HashSet<Expr<String>> rv = new HashSet<Expr<String>>();
rv.add(expr.append("Hello"));
@ -135,11 +150,12 @@ public class Projections {
rv.add(expr.substring(1));
rv.add(expr.substring(0, 1));
// CaseBuilder cases = new CaseBuilder();
// rv.add(cases.when(expr.eq("A")).then("a")
// .when(expr.eq("B")).then("b")
// .when(expr.eq("C")).then("c")
// .otherwise("x"));
if (!(other instanceof Constant || module == Module.JDOQL)){
CaseBuilder cases = new CaseBuilder();
rv.add(cases.when(expr.eq("A")).then(other)
.when(expr.eq("B")).then(expr)
.otherwise(other));
}
rv.add(expr.trim());

View File

@ -66,7 +66,9 @@ public abstract class StandardTest {
System.err.println();
}catch(Throwable t){
t.printStackTrace();
errors.add(pr + " failed : " + t.getMessage());
errors.add(pr + " failed : \n" +
t.getClass().getName() + " : " +
t.getMessage() + "\n");
}
}
}
@ -85,7 +87,9 @@ public abstract class StandardTest {
}
}catch(Throwable t){
t.printStackTrace();
errors.add(f + " failed : " + t.getMessage());
errors.add(f + " failed : \n" +
t.getClass().getName() + " : " +
t.getMessage() +"\n");
}
}
}

View File

@ -41,7 +41,12 @@ public class CaseBuilderTest {
"when customer.annualSpending > 2000 then Silver " +
"else Bronze " +
"end", cases.toString());
String rv = c.getAnnualSpending() > 10000 ? "Premier" :
c.getAnnualSpending() > 5000 ? "Gold" :
c.getAnnualSpending() > 2000 ? "Silver" :
"Bronze";
}
}

View File

@ -14,40 +14,36 @@
<description>Hibernate / HQL support for querydsl</description>
<packaging>jar</packaging>
<properties>
<hibernate.version>3.2.1.ga</hibernate.version>
</properties>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.6.ga</version>
<scope>provided</scope>
<!-- license : LGPL v2.1 -->
<exclusions>
<exclusion>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
</exclusion>
<exclusion>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.2.1.ga</version>
<scope>provided</scope>
</dependency>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.4.0.GA</version>
<exclusions>
<exclusion>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
</exclusion>
<exclusion>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
</exclusion>
</exclusions>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.2.1.ga</version>
<version>3.4.0.ga</version>
<scope>provided</scope>
</dependency>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>3.1.0.GA</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>

View File

@ -20,11 +20,4 @@ public class SubQueryTest extends AbstractQueryTest{
toString("exists (select cat from Cat cat where cat.weight < :a1)", sub().from(cat).where(cat.weight.lt(1)).unique(cat).exists());
}
// @Test
// public void stateful(){
// HQLSubQuery sub = sub();
// sub.from(cat);
// assertEquals("select cat from cat", sub.toString());
// }
}

View File

@ -133,7 +133,6 @@ public class JDOQLQueryStandardTest extends AbstractJDOTest {
standardTest.numericCasts(product.price, otherProduct.price, 200.0);
standardTest.numericTests(product.amount, otherProduct.amount, 2);
standardTest.stringTests(product.name, otherProduct.name, productName);
// timeTests too slow and causes OutOfMemoryError
standardTest.timeTests(product.timeField, otherProduct.timeField, time);
standardTest.report();