OPENJPA-1024: support case expression in subquery

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@764779 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Fay Wang 2009-04-14 13:53:41 +00:00
parent 171fe56aa2
commit 0398c0e7dd
5 changed files with 128 additions and 6 deletions

View File

@ -28,6 +28,7 @@ import org.apache.openjpa.jdbc.sql.SQLBuffer;
import org.apache.openjpa.jdbc.sql.Select;
import org.apache.openjpa.kernel.Filters;
import org.apache.openjpa.kernel.exps.ExpressionVisitor;
import org.apache.openjpa.kernel.exps.Value;
import org.apache.openjpa.meta.ClassMetaData;
/**
@ -42,6 +43,8 @@ public class GeneralCaseExpression
private final Val _val;
private ClassMetaData _meta = null;
private Class _cast = null;
private Value other = null;
private ExpState otherState = null;
/**
* Constructor.
@ -158,7 +161,7 @@ public class GeneralCaseExpression
}
private SQLBuffer newSQLBuffer(Select sel, ExpContext ctx, ExpState state) {
calculateValue(sel, ctx, state, null, null);
calculateValue(sel, ctx, state, (Val)other, otherState);
SQLBuffer buf = new SQLBuffer(ctx.store.getDBDictionary());
appendTo(sel, ctx, state, buf, 0);
return buf;
@ -190,5 +193,20 @@ public class GeneralCaseExpression
public void setMetaData(ClassMetaData meta) {
_meta = meta;
}
public void setOtherPath(Value other) {
this.other = other;
}
public Value getOtherPath() {
return other;
}
public void setOtherState(ExpState otherState) {
this.otherState = otherState;
}
public ExpState getOtherState() {
return otherState;
}
}

View File

@ -29,6 +29,7 @@ import org.apache.openjpa.jdbc.sql.SQLBuffer;
import org.apache.openjpa.jdbc.sql.Select;
import org.apache.openjpa.kernel.Filters;
import org.apache.openjpa.kernel.exps.ExpressionVisitor;
import org.apache.openjpa.kernel.exps.Value;
import org.apache.openjpa.meta.ClassMetaData;
/**
@ -44,6 +45,8 @@ public class SimpleCaseExpression
private final Val _val;
private ClassMetaData _meta = null;
private Class _cast = null;
private Value other = null;
private ExpState otherState = null;
/**
* Constructor.
@ -192,7 +195,7 @@ public class SimpleCaseExpression
}
private SQLBuffer newSQLBuffer(Select sel, ExpContext ctx, ExpState state) {
calculateValue(sel, ctx, state, null, null);
calculateValue(sel, ctx, state, (Val)other, otherState);
SQLBuffer buf = new SQLBuffer(ctx.store.getDBDictionary());
appendTo(sel, ctx, state, buf, 0);
return buf;
@ -224,5 +227,20 @@ public class SimpleCaseExpression
public void setMetaData(ClassMetaData meta) {
_meta = meta;
}
public void setOtherPath(Value other) {
this.other = other;
}
public Value getOtherPath() {
return other;
}
public void setOtherState(ExpState otherState) {
this.otherState = otherState;
}
public ExpState getOtherState() {
return otherState;
}
}

View File

@ -30,6 +30,7 @@ import org.apache.openjpa.kernel.Filters;
import org.apache.openjpa.kernel.exps.ExpressionVisitor;
import org.apache.openjpa.kernel.exps.QueryExpressions;
import org.apache.openjpa.kernel.exps.Subquery;
import org.apache.openjpa.kernel.exps.Value;
import org.apache.openjpa.meta.ClassMetaData;
/**
@ -149,6 +150,16 @@ class SubQ
public void calculateValue(Select sel, ExpContext ctx, ExpState state,
Val other, ExpState otherState) {
Value[] projs = _exps.projections;
for (int i = 0; i < projs.length; i++) {
if (projs[i] instanceof GeneralCaseExpression) {
((GeneralCaseExpression)projs[i]).setOtherPath(other);
((GeneralCaseExpression)projs[i]).setOtherState(otherState);
} else if (projs[i] instanceof SimpleCaseExpression) {
((SimpleCaseExpression)projs[i]).setOtherPath(other);
((SimpleCaseExpression)projs[i]).setOtherState(otherState);
}
}
}
public int length(Select sel, ExpContext ctx, ExpState state) {

View File

@ -157,6 +157,35 @@ public class TestJPQLScalarExpressions extends AbstractTestCase {
result = (Object[]) rs.get(rs.size()-1);
assertEquals(result[1], 1);
startTx(em);
String update = "update CompUser c set c.creditRating = " +
" CASE c.age WHEN 35 THEN " +
"org.apache.openjpa.persistence.common.apps.CompUser$CreditRating.POOR" +
" WHEN 11 THEN " +
"org.apache.openjpa.persistence.common.apps.CompUser$CreditRating.GOOD" +
" ELSE " +
"org.apache.openjpa.persistence.common.apps.CompUser$CreditRating.EXCELLENT" +
" END ";
int updateCount = em.createQuery(update).executeUpdate();
assertEquals("the result is not 6", 6, updateCount);
/*
//Derby fails but DB2 worksh
String update2 = "update CompUser c set c.creditRating = " +
" (select " +
" CASE c1.age WHEN 10 THEN " +
"org.apache.openjpa.persistence.common.apps.CompUser$CreditRating.POOR" +
" WHEN 19 THEN " +
"org.apache.openjpa.persistence.common.apps.CompUser$CreditRating.GOOD " +
" ELSE " +
"org.apache.openjpa.persistence.common.apps.CompUser$CreditRating.EXCELLENT " +
" END " +
" from CompUser c1" +
" where c.userid = c1.userid)";
updateCount = em.createQuery(update2).executeUpdate();
assertEquals("the result is not 6", 6, updateCount);
*/
endTx(em);
endEm(em);
}
@ -231,9 +260,28 @@ public class TestJPQLScalarExpressions extends AbstractTestCase {
" ELSE " +
"org.apache.openjpa.persistence.common.apps.CompUser$CreditRating.EXCELLENT " +
" END ";
result = em.createQuery(update2).executeUpdate();
assertEquals("the result is not 6", 6, result);
int updateCount = em.createQuery(update2).executeUpdate();
assertEquals("the result is not 6", 6, updateCount);
String query4 = "select e.name, e.creditRating from CompUser e " +
"where e.creditRating = " +
"(select " +
"CASE WHEN e1.age = 11 THEN " +
"org.apache.openjpa.persistence.common.apps.CompUser$CreditRating.POOR" +
" WHEN e1.age = 35 THEN " +
"org.apache.openjpa.persistence.common.apps.CompUser$CreditRating.GOOD" +
" ELSE " +
"org.apache.openjpa.persistence.common.apps.CompUser$CreditRating.EXCELLENT" +
" END " +
"from CompUser e1" +
" where e.userid = e1.userid) ORDER BY e.age";
List rs4 = em.createQuery(query4).getResultList();
Object[] result4 = (Object[]) rs4.get(0);
assertEquals("the name is not Ugo", "Ugo", result4[0]);
assertEquals("the credit rating is not 'EXCELLENT'", "EXCELLENT",
((org.apache.openjpa.persistence.common.apps.CompUser.CreditRating)
result4[1]).name());
String update3 = "update CompUser c set c.creditRating = " +
" CASE c.age WHEN 35 THEN " +
"org.apache.openjpa.persistence.common.apps.CompUser$CreditRating.POOR" +
@ -245,7 +293,23 @@ public class TestJPQLScalarExpressions extends AbstractTestCase {
result = em.createQuery(update3).executeUpdate();
assertEquals("the result is not 6", 6, result);
endTx(em);
// Derby fails but DB2 works
/*
String update4 = "update CompUser c set c.creditRating = " +
" (select " +
" CASE c1.age WHEN 10 THEN " +
"org.apache.openjpa.persistence.common.apps.CompUser$CreditRating.POOR" +
" WHEN 19 THEN " +
"org.apache.openjpa.persistence.common.apps.CompUser$CreditRating.GOOD" +
" ELSE " +
"org.apache.openjpa.persistence.common.apps.CompUser$CreditRating.EXCELLENT" +
" END " +
" from CompUser c1" +
" where c.userid = c1.userid)";
updateCount = em.createQuery(update4).executeUpdate();
assertEquals("the result is not 6", 6, updateCount);
*/
endTx(em);
endEm(em);
}

View File

@ -115,6 +115,17 @@ public class TestSubquery
"select o.oid from Order o where o.customer.name in" +
" (select CONCAT(o.customer.name, 'XX') from Order o" +
" where o.amount > 10)",
"select c from Customer c where c.creditRating =" +
" (select " +
" CASE WHEN o2.amount > 10 THEN " +
"org.apache.openjpa.persistence.query.Customer$CreditRating.POOR" +
" WHEN o2.amount = 10 THEN " +
"org.apache.openjpa.persistence.query.Customer$CreditRating.GOOD " +
" ELSE " +
"org.apache.openjpa.persistence.query.Customer$CreditRating.EXCELLENT " +
" END " +
" from Order o2" +
" where c.cid.id = o2.customer.cid.id)",
};
static String[] updates = new String[] {