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[] {        


Reply via email to