Author: fancy
Date: Tue May 26 00:05:36 2009
New Revision: 778540
URL: http://svn.apache.org/viewvc?rev=778540&view=rev
Log:
OPENJPA-1098 JPA2 Query support for subselect_identification_variable
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
openjpa/trunk/openjpa-kernel/src/main/jjtree/org/apache/openjpa/kernel/jpql/JPQL.jjt
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/query/TestSubquery.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=778540&r1=778539&r2=778540&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
Tue May 26 00:05:36 2009
@@ -244,7 +244,10 @@
}
if (n.id == JJTPATH) {
Path path = getPath(n);
- ClassMetaData cmd = getFieldType(path.last());
+ FieldMetaData fmd = path.last();
+ ClassMetaData cmd = getFieldType(fmd);
+ if (cmd == null && fmd.isElementCollection())
+ cmd = fmd.getDefiningMetaData();
if (cmd != null) {
return cmd;
}
@@ -591,7 +594,15 @@
Path subpath = factory.newPath(ctx().subquery);
subpath.setMetaData(ctx().subquery.getMetaData());
+ // subquery may have KEY range over a variable
+ // that is not defined.
+ JPQLNode key = root().findChildByID(JJTKEY, true);
+ if (key != null && firstChild(key).text.equals(alias.text)) {
+ Value var = getVariable(alias.text, false);
+ exp = and(exp, factory.bindVariable(var, path));
+ }
exp = and(exp, factory.equal(path, subpath));
+ return exp;
}
return addJoin(path, alias, exp);
@@ -661,6 +672,15 @@
Path subpath = factory.newPath(ctx().subquery);
subpath.setMetaData(ctx().subquery.getMetaData());
+ if (alias != null && !isSeendVariable(alias)) {
+ // subquery may have KEY range over a variable
+ // that is not defined.
+ JPQLNode key = root().findChildByID(JJTKEY, true);
+ if (key != null && firstChild(key).text.equals(alias)) {
+ Value var = getVariable(alias, false);
+ exp = and(exp, factory.bindVariable(var, path));
+ }
+ }
return and(exp, factory.equal(path, subpath));
} else {
// we have an alias: bind it as a variable
@@ -1682,7 +1702,7 @@
// resolve the first element against the aliases map ...
// i.e., the path "SELECT x.id FROM SomeClass x where x.id > 10"
// will need to have "x" in the alias map in order to resolve
- Path path;
+ Path path = null;
final String name = firstChild(node).text;
final Value val = getVariable(name, false);
Modified:
openjpa/trunk/openjpa-kernel/src/main/jjtree/org/apache/openjpa/kernel/jpql/JPQL.jjt
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/jjtree/org/apache/openjpa/kernel/jpql/JPQL.jjt?rev=778540&r1=778539&r2=778540&view=diff
==============================================================================
---
openjpa/trunk/openjpa-kernel/src/main/jjtree/org/apache/openjpa/kernel/jpql/JPQL.jjt
(original)
+++
openjpa/trunk/openjpa-kernel/src/main/jjtree/org/apache/openjpa/kernel/jpql/JPQL.jjt
Tue May 26 00:05:36 2009
@@ -402,10 +402,16 @@
( LOOKAHEAD(1) <COMMA> subquery_from_item() )*
}
+
+void subselect_identification_variable_declaration(): { }
+{
+ from_item() (LOOKAHEAD(inner_join()) inner_join() |
LOOKAHEAD(outer_join()) outer_join())*
+}
+
void subquery_from_item() : { }
{
LOOKAHEAD(collection_member_declaration()) collection_member_declaration()
- | LOOKAHEAD(identification_variable_declaration())
identification_variable_declaration()
+ | LOOKAHEAD(subselect_identification_variable_declaration())
subselect_identification_variable_declaration()
}
void inner_join() #INNERJOIN : { }
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=778540&r1=778539&r2=778540&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
Tue May 26 00:05:36 2009
@@ -755,7 +755,7 @@
// test range variable over element collection
String[] query = {
"select e from Employee e, in (e.nickNames) n " +
- " where n like '%1'",
+ " where n like '%1'",
};
for (int i = 0; i < query.length; i++) {
es = em.createQuery(query[i]).getResultList();
@@ -1154,24 +1154,24 @@
public void queryEntityA_Coll_String() {
EntityManager em = emf.createEntityManager();
String[] query = {
- "select e from " +
- " EntityA_Coll_String a " +
- " , in (a.nickNames) e order by a.id",
- "select e from " +
- " EntityA_Coll_String a " +
- " , in (a.nickNames) e order by a.id",
- "select e from " +
- " EntityA_Coll_String a " +
- " , in (a.nickNames) e order by e",
- "select a from " +
- " EntityA_Coll_String a " +
- " WHERE a.nickNames IS EMPTY order by a",
- "select a from " +
- " EntityA_Coll_String a " +
- " WHERE exists (select n from EntityA_Coll_String a, " +
- " in (a.nickNames) n where n like '%1') " +
- " order by a",
- };
+ "select e from " +
+ " EntityA_Coll_String a " +
+ " , in (a.nickNames) e order by a.id",
+ "select e from " +
+ " EntityA_Coll_String a " +
+ " , in (a.nickNames) e order by a.id",
+ "select e from " +
+ " EntityA_Coll_String a " +
+ " , in (a.nickNames) e order by e",
+ "select a from " +
+ " EntityA_Coll_String a " +
+ " WHERE a.nickNames IS EMPTY order by a",
+ "select a from " +
+ " EntityA_Coll_String a " +
+ " WHERE exists (select n from EntityA_Coll_String a, " +
+ " in (a.nickNames) n where n like '%1') " +
+ " order by a",
+ };
List rs = null;
for (int i = 0; i < query.length; i++) {
rs = em.createQuery(query[i]).getResultList();
@@ -1574,14 +1574,13 @@
"select a.embed.embed from EntityA_Embed_Embed a",
"select a.embed as e from EntityA_Embed_Embed a ORDER BY e",
};
- 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) ",
- };
+ 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();
@@ -1660,8 +1659,8 @@
" order by e.intVal3",
"select e, e.intVal1, e.embed.intVal2 from " +
" EntityA_Coll_Embed_Embed a " +
- " , in (a.embeds) e WHERE e.intVal1 <= SOME (select e2." +
- "intVal2 " +
+ " , in (a.embeds) e WHERE e.intVal1 <= SOME " +
+ " (select e2.intVal2 " +
" from EntityA_Coll_Embed_Embed a1, in (a1.embeds) e2) " +
" order by e.intVal3",
"select e, e.intVal1, e.embed.intVal2 from " +
@@ -1685,8 +1684,8 @@
" order by e.intVal3",
"select e, e.intVal1, e.embed.intVal2 from " +
" EntityA_Coll_Embed_Embed a " +
- " , in (a.embeds) e WHERE e.intVal1 <= SOME (select e." +
- "intVal2 " +
+ " , in (a.embeds) e WHERE e.intVal1 <= SOME " +
+ " (select e.intVal2 " +
" from EntityA_Coll_Embed_Embed a, in (a.embeds) e) " +
" order by e.intVal3",
"select e, e.intVal1, e.embed.intVal2 from " +
@@ -1710,8 +1709,8 @@
" order by e.intVal3",
"select e, e.intVal1, e.embed.intVal2 from " +
" EntityA_Coll_Embed_Embed a " +
- " , in (a.embeds) e WHERE e.intVal1 <= SOME (select e2." +
- "intVal2 " +
+ " , in (a.embeds) e WHERE e.intVal1 <= SOME " +
+ " (select e2.intVal2 " +
" from in(a.embeds) e2) " +
" order by e.intVal3",
"select e, e.intVal1, e.embed.intVal2 from " +
@@ -2347,24 +2346,28 @@
" where ?1 = any " +
" (select KEY(e) from Item1 i, in(i.images) e) " +
" order by i",
- "select i from Item2 i" +
- " where ?1 = any " +
- " (select KEY(e) from Item2 i, in(i.images) e) " +
- " order by i",
- "select i from Item3 i" +
- " where ?1 = any " +
- " (select KEY(e) from Item3 i, in(i.images) e) " +
- " order by i",
"select i from Item1 i" +
" where exists " +
" (select e from Item1 i, in(i.images) e" +
" where ?1 = KEY(e)) " +
" order by i",
+ };
+ String[] query2 = {
+ "select i from Item2 i" +
+ " where ?1 = any " +
+ " (select KEY(e) from Item2 i, in(i.images) e) " +
+ " order by i",
"select i from Item2 i" +
" where exists " +
" (select e from Item2 i, in(i.images) e" +
" where ?1 = KEY(e)) " +
" order by i",
+ };
+ String[] query3 = {
+ "select i from Item3 i" +
+ " where ?1 = any " +
+ " (select KEY(e) from Item3 i, in(i.images) e) " +
+ " order by i",
"select i from Item3 i" +
" where exists " +
" (select e from Item3 i, in(i.images) e" +
@@ -2374,25 +2377,26 @@
for (int i = 0; i < query.length; i++) {
Query q = em.createQuery(query[i]);
- switch (i) {
- case 0:
- case 3:
- q.setParameter(1, imageKey1);
- is1 = q.getResultList();
- assertItem1(is1.get(0));
- break;
- case 1:
- case 4:
- q.setParameter(1, imageKey2);
- is2 = q.getResultList();
- assertItem2(is2.get(0));
- break;
- case 2:
- case 5:
- q.setParameter(1, imageKey3);
- is3 = q.getResultList();
- assertItem3(is3.get(0));
- break;
+ q.setParameter(1, imageKey1);
+ is1 = q.getResultList();
+ for (Item1 item : is1){
+ assertItem1(item);
+ }
+ }
+ for (int i = 0; i < query2.length; i++) {
+ Query q = em.createQuery(query2[i]);
+ q.setParameter(1, imageKey2);
+ is2 = q.getResultList();
+ for (Item2 item : is2){
+ assertItem2(item);
+ }
+ }
+ for (int i = 0; i < query3.length; i++) {
+ Query q = em.createQuery(query3[i]);
+ q.setParameter(1, imageKey3);
+ is3 = q.getResultList();
+ for (Item3 item : is3){
+ assertItem3(item);
}
}
em.close();
@@ -2415,7 +2419,7 @@
tran.commit();
em.clear();
- // test KEY(e) appeared in subquery
+ // test KEY(e) in subquery
Division d1 = (Division) ((Company1) cs1.get(0)).getOrganization().
keySet().toArray()[0];
Division d2 = (Division) ((Company2) cs2.get(0)).getOrganization().
@@ -2428,40 +2432,47 @@
" (select KEY(d) from Company1 c, in(c.organization) d" +
" where d.id = 1)" +
" order by c ",
+ "select c from Company1 c where exists" +
+ " (select d from in(c.organization) d" +
+ " where KEY(d) = ?1)" +
+ " order by c ",
+ "select c from Company1 c where exists" +
+ " (select d from c.organization d" +
+ " where KEY(d) = ?1)" +
+ " order by c ",
+ };
+ for (int i = 0; i < query.length; i++) {
+ Query q = em.createQuery(query[i]);
+ q.setParameter(1, d1);
+ cs1 = q.getResultList();
+ for (Company1 c : cs1){
+ assertCompany1(c);
+ }
+ }
+
+ String[] query2 = {
"select c from Company2 c" +
" where ?1 = " +
" (select KEY(d) from Company2 c, in(c.organization) d" +
" where d.id = 3)" +
" order by c ",
- "select c from Company1 c where exists" +
+ "select c from Company2 c where exists" +
" (select d from in(c.organization) d" +
" where KEY(d) = ?1)" +
" order by c ",
"select c from Company2 c where exists" +
- " (select d from in(c.organization) d" +
+ " (select d from c.organization d" +
" where KEY(d) = ?1)" +
" order by c ",
};
- for (int i = 0; i < query.length; i++) {
- Query q = em.createQuery(query[i]);
- switch (i) {
- case 0:
- case 1:
- case 3:
- q.setParameter(1, d1);
- cs1 = q.getResultList();
- if (cs1.size() > 0)
- assertCompany1(cs1.get(0));
- break;
- case 2:
- case 4:
- q.setParameter(1, d2);
- cs2 = q.getResultList();
- if (cs2.size() > 0)
- assertCompany2(cs2.get(0));
- break;
- }
+ for (int i = 0; i < query2.length; i++) {
+ Query q = em.createQuery(query2[i]);
+ q.setParameter(1, d2);
+ cs2 = q.getResultList();
+ for (Company2 c : cs2){
+ assertCompany2(c);
+ }
}
em.close();
}
Modified:
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestSubquery.java
URL:
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestSubquery.java?rev=778540&r1=778539&r2=778540&view=diff
==============================================================================
---
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestSubquery.java
(original)
+++
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/TestSubquery.java
Tue May 26 00:05:36 2009
@@ -39,6 +39,14 @@
}
static String[] querys = new String[] {
+ "select c from Customer c where EXISTS" +
+ " (select o from in(c.orders) o)" ,
+ "select c from Customer c where EXISTS" +
+ " (select o from c.orders o)" ,
+ "select c from Customer c where NOT EXISTS" +
+ " (select o from in (c.orders) o)" ,
+ "select c from Customer c where NOT EXISTS" +
+ " (select o from c.orders o)" ,
"select o1.oid from Order o1 where o1.oid in " +
" (select distinct o.oid from OrderItem i, Order o" +
" where i.quantity > 10 and o.amount > 1000 and i.lid = o.oid)" ,
@@ -86,8 +94,8 @@
// "select o from Order o where o.amount > (select count(o) from Order o)",
// "select o from Order o where o.amount > (select count(o2) from
// Order o2)",
- // "select c from Customer c left join c.orders p where not exists"
- // + " (select o2 from c.orders o2 where o2 = o",
+ // "select c from Customer c left join c.orders o where not exists"
+ // + " (select o2 from c.orders o2 where o2 = o)",
};
static String[] querys_jpa20 = new String[] {