Author: fancy
Date: Thu May 14 21:08:27 2009
New Revision: 774928
URL: http://svn.apache.org/viewvc?rev=774928&view=rev
Log:
OPENJPA-1064 JPA2 Query no support for embeddable of element collection in
predicate and subquery
JPA2 spec (section 4.12) does not support comparisons over embeddable class.
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/access/TestExplicitAccess.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/TestMany2ManyMapEx10.java
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java?rev=774928&r1=774927&r2=774928&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
Thu May 14 21:08:27 2009
@@ -752,6 +752,22 @@
return assemble(node);
}
+ private void checkEmbeddable(Value val) {
+ Path path = val instanceof Path ? (Path) val : null;
+ if (path == null)
+ return;
+
+ FieldMetaData fmd = path.last();
+ if (fmd == null)
+ return;
+
+ ValueMetaData vm = fmd.isElementCollection() ? fmd.getElement()
+ : fmd.getValue();
+ if (vm.getEmbeddedMetaData() != null)
+ throw parseException(EX_USER, "bad-predicate",
+ new Object[]{ currentQuery() }, null);
+ }
+
/**
* Recursive helper method to evaluate the given node.
*/
@@ -956,12 +972,14 @@
factory.notEqual(val1, factory.getNull()));
case JJTISNULL: // x.field IS [NOT] NULL
+ val1 = getValue(onlyChild(node));
+ checkEmbeddable(val1);
if (not)
return factory.notEqual
- (getValue(onlyChild(node)), factory.getNull());
+ (val1, factory.getNull());
else
return factory.equal
- (getValue(onlyChild(node)), factory.getNull());
+ (val1, factory.getNull());
case JJTPATH:
return getPathOrConstant(node);
@@ -1159,6 +1177,7 @@
case JJTMEMBEROF:
val1 = getValue(left(node), VAR_PATH);
val2 = getValue(right(node), VAR_PATH);
+ checkEmbeddable(val2);
setImplicitContainsTypes(val2, val1, CONTAINS_TYPE_ELEMENT);
return evalNot(not, factory.contains(val2, val1));
@@ -1290,6 +1309,9 @@
if (fmd == null)
return;
+ if (expected == null)
+ checkEmbeddable(path);
+
Class<?> type = path.getType();
if (type == null)
return;
@@ -1333,6 +1355,8 @@
try {
QueryExpressions subexp = getQueryExpressions();
subq.setQueryExpressions(subexp);
+ if (subexp.projections.length > 0)
+ checkEmbeddable(subexp.projections[0]);
return subq;
} finally {
// remove the subquery parse context
Modified:
openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties?rev=774928&r1=774927&r2=774928&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/jpql/localizer.properties
Thu May 14 21:08:27 2009
@@ -77,4 +77,6 @@
referring to an association field of type java.util.Map.
bad-qualified-path: Attemp to navigate a basic type of Key("{0}").
bad-general-identifier: The identitier "{0}" in "{1}" operator is not valid \
- in conditional expression.
\ No newline at end of file
+ in conditional expression.
+bad-predicate: JPQL query does not support conditional expression over \
+ embeddable class. JPQL string: "{0}".
\ No newline at end of file
Modified:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/access/TestExplicitAccess.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/access/TestExplicitAccess.java?rev=774928&r1=774927&r2=774928&view=diff
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/access/TestExplicitAccess.java
(original)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/access/TestExplicitAccess.java
Thu May 14 21:08:27 2009
@@ -873,9 +873,8 @@
qry.getSingleResult();
fail("Query execution should have failed.");
} catch (Exception e) {
- assertExceptionMessage(e, ArgumentException.class,
- "No field named \"firstName\" in \"EmbedFieldAccess\"",
- "[fName, lName]");
+ // no support: conditional expressional expression over embeddable
+ assertException(e, ArgumentException.class);
}
em.close();
Modified:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java?rev=774928&r1=774927&r2=774928&view=diff
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java
(original)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java
Thu May 14 21:08:27 2009
@@ -32,6 +32,7 @@
import javax.persistence.Query;
+import org.apache.openjpa.persistence.ArgumentException;
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
public class TestEmbeddable extends SingleEMFTestCase {
@@ -1198,7 +1199,7 @@
" ORDER BY a.embed",
"select a.embed from " +
" EntityA_Embed_ToOne a WHERE exists " +
- " (select a from EntityA_Embed_ToOne a" +
+ " (select a from EntityA_Embed_ToOne a " +
" where a.embed.b IS NOT NULL) " +
" ORDER BY a.embed",
};
@@ -1236,8 +1237,6 @@
"select a.embed as e from " +
" EntityA_Embed_MappedToOne a ORDER BY e",
"select a.embed from " +
- " EntityA_Embed_MappedToOne a WHERE a.embed IS NOT NULL",
- "select a.embed from " +
" EntityA_Embed_MappedToOne a WHERE a.embed.bm IS NOT NULL",
"select a.embed from " +
" EntityA_Embed_MappedToOne a " +
@@ -1254,6 +1253,29 @@
assertTrue(((Embed_MappedToOne) obj).getMappedEntityB() != null);
em.clear();
}
+ String[] query2 = {
+ // embeddable in conditional expression should fail
+ "select a.embed from " +
+ " EntityA_Embed_MappedToOne a " +
+ " WHERE exists " +
+ " (select e from EntityA_Embed_MappedToOne a" +
+ " join a.embed e " +
+ " where e.bm IS NOT NULL)",
+ "select a.embed from " +
+ " EntityA_Embed_MappedToOne a " +
+ " WHERE exists " +
+ " (select a.embed from EntityA_Embed_MappedToOne a " +
+ " where a.embed.bm IS NOT NULL)",
+ };
+ for (int i = 0; i < query2.length; i++) {
+ List<Object[]> rs = null;
+ try {
+ rs = em.createQuery(query2[i]).getResultList();
+ } catch (ArgumentException e) {
+ // as expected
+ }
+ }
+
EntityTransaction tran = em.getTransaction();
tran.begin();
Query q = em.createQuery("select a from EntityA_Embed_MappedToOne a");
@@ -1352,10 +1374,10 @@
"select e from EntityA_Embed_ToMany a join a.embed e " +
" WHERE e.bs IS NOT EMPTY ORDER BY e",
"select a from EntityA_Embed_ToMany a " +
- " WHERE exists (select a.embed from EntityA_Embed_ToMany a" +
+ " WHERE exists (select a from EntityA_Embed_ToMany a" +
" where a.embed.bs IS NOT EMPTY) ORDER BY a",
"select a from EntityA_Embed_ToMany a " +
- " WHERE exists (select a.embed from EntityA_Embed_ToMany a" +
+ " WHERE exists (select a from EntityA_Embed_ToMany a" +
" where a.embed.bs IS NOT EMPTY) ORDER BY a",
};
List rs = null;
@@ -1401,26 +1423,26 @@
EntityManager em = emf.createEntityManager();
// test select embeddable
String query[] = {
-// "select a.embed from EntityA_Embed_Embed_ToMany a",
-// "select a.embed from EntityA_Embed_Embed_ToMany a" +
-// " where a.embed.embed.name1 like '%1' ",
-// "select a.embed.embed from EntityA_Embed_Embed_ToMany a",
+ "select a.embed from EntityA_Embed_Embed_ToMany a",
+ "select a.embed from EntityA_Embed_Embed_ToMany a" +
+ " where a.embed.embed.name1 like '%1' ",
+ "select a.embed.embed from EntityA_Embed_Embed_ToMany a",
"select b from EntityA_Embed_Embed_ToMany a join a.embed.embed.bs"
+
" b",
-// "select a.embed.embed from EntityA_Embed_Embed_ToMany a " +
-// " where a.embed.embed.name1 like '%1'",
-// "select e2 from EntityA_Embed_Embed_ToMany a " +
-// " left join a.embed e1 left join e1.embed e2",
-// "select e2 from EntityA_Embed_Embed_ToMany a " +
-// " join a.embed e1 join e1.embed e2",
-// "select a.embed as e from EntityA_Embed_Embed_ToMany a ORDER BY
e",
-// "select a.embed.embed as e from EntityA_Embed_Embed_ToMany a " +
-// " where a.embed.embed.name1 like '%1' ORDER BY e",
-// "select a.embed from EntityA_Embed_Embed_ToMany a " +
-// " where a.embed.embed.bs IS NOT EMPTY",
-// "select a.embed from EntityA_Embed_Embed_ToMany a " +
-// " where exists (select a.embed.embed.bs from " +
-// " EntityA_Embed_Embed_ToMany a)",
+ "select a.embed.embed from EntityA_Embed_Embed_ToMany a " +
+ " where a.embed.embed.name1 like '%1'",
+ "select e2 from EntityA_Embed_Embed_ToMany a " +
+ " left join a.embed e1 left join e1.embed e2",
+ "select e2 from EntityA_Embed_Embed_ToMany a " +
+ " join a.embed e1 join e1.embed e2",
+ "select a.embed as e from EntityA_Embed_Embed_ToMany a ORDER BY e",
+ "select a.embed.embed as e from EntityA_Embed_Embed_ToMany a " +
+ " where a.embed.embed.name1 like '%1' ORDER BY e",
+ "select a.embed from EntityA_Embed_Embed_ToMany a " +
+ " where a.embed.embed.bs IS NOT EMPTY",
+ "select a.embed from EntityA_Embed_Embed_ToMany a " +
+ " where exists (select a.embed.embed.bs from " +
+ " EntityA_Embed_Embed_ToMany a)",
"select b from EntityA_Embed_Embed_ToMany a join a.embed.embed.bs"
+
" b",
};
@@ -1432,23 +1454,23 @@
switch (i) {
case 0:
case 1:
-// case 7:
-// case 9:
-// case 10:
-// assertTrue(obj instanceof Embed_Embed_ToMany);
-// assertTrue(((Embed_Embed_ToMany)
obj).getEmbed().getEntityBs().
-// size() > 0);
-// break;
-// case 2:
-// case 4:
-// case 5:
-// case 6:
-// case 8:
-// assertTrue(obj instanceof Embed_ToMany);
-// assertTrue(((Embed_ToMany) obj).getEntityBs().size() > 0);
-// break;
-// case 3:
-// case 11:
+ case 7:
+ case 9:
+ case 10:
+ assertTrue(obj instanceof Embed_Embed_ToMany);
+ assertTrue(((Embed_Embed_ToMany) obj).getEmbed().getEntityBs().
+ size() > 0);
+ break;
+ case 2:
+ case 4:
+ case 5:
+ case 6:
+ case 8:
+ assertTrue(obj instanceof Embed_ToMany);
+ assertTrue(((Embed_ToMany) obj).getEntityBs().size() > 0);
+ break;
+ case 3:
+ case 11:
assertTrue(obj instanceof EntityB1);
break;
}
@@ -1528,13 +1550,15 @@
"select a.embed from EntityA_Embed_Embed a",
"select a.embed.embed from EntityA_Embed_Embed a",
"select a.embed as e from EntityA_Embed_Embed a ORDER BY e",
- "select a.embed from EntityA_Embed_Embed a WHERE a.embed.embed " +
- " IS NOT NULL",
- "select a.embed from EntityA_Embed_Embed a " +
- " WHERE exists " +
- " (select a.embed.embed from EntityA_Embed_Embed a" +
- " where a.embed IS NOT NULL) ",
};
+ String query2[] = {
+ "select a.embed from EntityA_Embed_Embed a WHERE a.embed.embed
" +
+ " IS NOT NULL",
+ "select a.embed from EntityA_Embed_Embed a " +
+ " WHERE exists " +
+ " (select a.embed.embed from EntityA_Embed_Embed a" +
+ " where a.embed IS NOT NULL) ",
+ };
List rs = null;
for (int i = 0; i < query.length; i++) {
rs = em.createQuery(query[i]).getResultList();
@@ -1542,8 +1566,6 @@
switch (i) {
case 0:
case 2:
- case 3:
- case 4:
assertTrue(rs.get(0) instanceof Embed_Embed);
break;
case 1:
@@ -1552,6 +1574,13 @@
}
em.clear();
}
+ for (int i = 0; i < query2.length; i++) {
+ try {
+ rs = em.createQuery(query2[i]).getResultList();
+ } catch(ArgumentException e) {
+ // as expected
+ }
+ }
EntityTransaction tran = em.getTransaction();
tran.begin();
Query q = em.createQuery("select a from EntityA_Embed_Embed a");
@@ -1697,10 +1726,10 @@
}
}
for (int i = 0; i < query3.length; i++) {
+ try {
rs = em.createQuery(query3[i]).setParameter(1,
obj).getResultList();
- if (rs.size() > 0) {
- obj = ((Object[]) rs.get(0))[0];
- assertTrue(obj instanceof Embed_Embed);
+ } catch(ArgumentException e) {
+ // as expected
}
}
@@ -1745,16 +1774,53 @@
" from EntityA_Embed_Coll_Embed a, in (a.embed.embeds) e " +
" where e.intVal2 = 105) " +
" order by e",
+ "select e, a from " +
+ " EntityA_Embed_Coll_Embed a " +
+ " , in (a.embed.embeds) e " +
+ " where e.intVal1 = SOME " +
+ " (select e2.intVal1 from " +
+ " EntityA_Embed_Coll_Embed a2 " +
+ " , in (a2.embed.embeds) e2) " +
+ " order by e",
+ };
+ String[] query2 = {
+ "select e, a from " +
+ " EntityA_Embed_Coll_Embed a " +
+ " , in (a.embed.embeds) e " +
+ " where e = ?1 order by e",
};
List<Object[]> rs = null;
+ EntityA_Embed_Coll_Embed ea = null;
+ Object obj = null;
for (int i = 0; i < query.length; i++) {
rs = em.createQuery(query[i]).getResultList();
assertTrue(rs.size() > 0);
- Object obj = ((Object[]) rs.get(0))[0];
+ obj = ((Object[]) rs.get(0))[0];
assertTrue(obj instanceof Embed);
- em.clear();
+ if (i == query.length-1)
+ ea = (EntityA_Embed_Coll_Embed) ((Object[]) rs.get(0))[1];
}
+ for (int i = 0; i < query2.length; i++) {
+ try {
+ rs = em.createQuery(query2[i]).
+ setParameter(1, (Embed) obj).
+ getResultList();
+ } catch (ArgumentException e) {
+ // expected exception
+ }
+ }
+ try {
+ rs = em.createQuery("select a from " +
+ " EntityA_Embed_Coll_Embed a " +
+ " where a.embed = ?1 order by e").
+ setParameter(1, ea.getEmbed()).
+ getResultList();
+ } catch (ArgumentException e) {
+ // expected exception
+ }
+ em.clear();
+
EntityTransaction tran = em.getTransaction();
tran.begin();
Query q = em.createQuery("select a from EntityA_Embed_Coll_Embed a");
Modified:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/TestMany2ManyMapEx10.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/TestMany2ManyMapEx10.java?rev=774928&r1=774927&r2=774928&view=diff
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/TestMany2ManyMapEx10.java
(original)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/maps/m2mmapex10/TestMany2ManyMapEx10.java
Thu May 14 21:08:27 2009
@@ -32,6 +32,7 @@
import junit.framework.Assert;
import org.apache.openjpa.kernel.QueryImpl;
+import org.apache.openjpa.persistence.ArgumentException;
import org.apache.openjpa.persistence.test.AllowFailure;
import org.apache.openjpa.persistence.test.SQLListenerTestCase;
@@ -87,13 +88,24 @@
public void queryQualifiedId(boolean inMemory) throws Exception {
EntityManager em = emf.createEntityManager();
+ EmployeePK ekey = empPKs.get(0);
String query = "select KEY(e) from PhoneNumber p, " +
- " in (p.emps) e where e.empPK = ?1";
- Query q = em.createQuery(query).setParameter(1, empPKs.get(0));
+ " in (p.emps) e where e.empPK.name = ?1 and e.empPK.bDay = ?2";
+ Query q = em.createQuery(query).setParameter(1, ekey.getName()).
+ setParameter(2, ekey.getBDay());
if (inMemory)
setCandidate(q, PhoneNumber.class);
List rs = q.getResultList();
EmployeePK d = (EmployeePK) rs.get(0);
+
+ query = "select KEY(e) from PhoneNumber p, " +
+ " in (p.emps) e where e.empPK = ?1";
+ try {
+ rs = em.createQuery(query).setParameter(1, ekey).getResultList();
+ } catch (Exception e) {
+ // as excepted: conditional expressional expression over embeddable
+ assertException(e, ArgumentException.class);
+ }
query = "select KEY(p) from Employee e, " +
" in (e.phones) p";
@@ -105,8 +117,9 @@
em.clear();
query = "select ENTRY(e) from PhoneNumber p, " +
- " in (p.emps) e where e.empPK = ?1";
- q = em.createQuery(query).setParameter(1, empPKs.get(0));
+ " in (p.emps) e where e.empPK.name = ?1 and e.empPK.bDay = ?2";
+ q = em.createQuery(query).setParameter(1, ekey.getName()).
+ setParameter(2, ekey.getBDay());
if (inMemory)
setCandidate(q, PhoneNumber.class);
rs = q.getResultList();