You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by fa...@apache.org on 2009/05/19 00:23:04 UTC

svn commit: r776117 - in /openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/ openjpa-persistence-jdbc/...

Author: fancy
Date: Mon May 18 22:23:04 2009
New Revision: 776117

URL: http://svn.apache.org/viewvc?rev=776117&view=rev
Log:
OPENJPA-1094 JPA2 Query support KEY to appear in subquery

Modified:
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ContainsExpression.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/MapKey.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SubQ.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Variable.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Val.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java?rev=776117&r1=776116&r2=776117&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java Mon May 18 22:23:04 2009
@@ -21,6 +21,7 @@
 import org.apache.openjpa.jdbc.sql.SQLBuffer;
 import org.apache.openjpa.jdbc.sql.Select;
 import org.apache.openjpa.kernel.exps.ExpressionVisitor;
+import org.apache.openjpa.kernel.exps.Path;
 import org.apache.openjpa.kernel.exps.Value;
 
 /**
@@ -109,5 +110,9 @@
     public Value getSelectAs() {
         return _alias != null ? this : null;
     }
+
+    public Path getPath() {
+        return null;
+    }
 }
 

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ContainsExpression.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ContainsExpression.java?rev=776117&r1=776116&r2=776117&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ContainsExpression.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ContainsExpression.java Mon May 18 22:23:04 2009
@@ -42,7 +42,7 @@
         Val val1 = getValue1();
         if (contains != null && val1 instanceof PCPath) {
             PCPath sql = (PCPath) val1;
-            String path = sql.getPath();
+            String path = sql.getPCPathString();
 
             // update the count for this path
             Integer count = (Integer) contains.get(path);

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/MapKey.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/MapKey.java?rev=776117&r1=776116&r2=776117&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/MapKey.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/MapKey.java Mon May 18 22:23:04 2009
@@ -124,4 +124,11 @@
     public void setMetaData(ClassMetaData meta) {
         _meta = meta;        
     }
+
+    public Object toDataStoreValue(Select sel, ExpContext ctx, ExpState state, 
+        Object val) {
+        KeyExpState estate = (KeyExpState) state;
+        return _key.toDataStoreValue(sel, ctx, 
+            estate.key, val);
+    }
 }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java?rev=776117&r1=776116&r2=776117&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java Mon May 18 22:23:04 2009
@@ -218,7 +218,7 @@
         return xpath.toString();
     }
     
-    public String getPath() {
+    public String getPCPathString() {
         if (_actions == null)
             return (_varName == null) ? "" : _varName + ".";
 
@@ -293,10 +293,14 @@
                 case JavaTypes.COLLECTION:
                     ValueMapping elem = pstate.field.getElementMapping();
                     if (pstate.field.isElementCollection() &&
-                        pstate.field.getElement().isEmbedded())
-                        return ((HandlerCollectionTableFieldStrategy)
-                            pstate.field.getStrategy()).getElementColumns(
-                            elem.getTypeMapping());
+                        pstate.field.getElement().isEmbedded()) {
+                        Strategy strategy = pstate.field.getStrategy();
+                        if (strategy instanceof
+                            HandlerCollectionTableFieldStrategy)
+                            return ((HandlerCollectionTableFieldStrategy)
+                                strategy).getElementColumns(
+                                elem.getTypeMapping());
+                    }
                     if (pstate.joinedRel && elem.getTypeCode() == JavaTypes.PC)
                         return elem.getTypeMapping().getPrimaryKeyColumns();
                     if (elem.getColumns().length > 0)

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SubQ.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SubQ.java?rev=776117&r1=776116&r2=776117&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SubQ.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/SubQ.java Mon May 18 22:23:04 2009
@@ -69,7 +69,7 @@
     }
 
     public Class getType() {
-        if (_exps != null) {
+        if (_exps != null && _type == null) {
             if (_exps.projections.length == 0)
                 return _candidate.getDescribedType();
             if (_exps.projections.length == 1)

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Variable.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Variable.java?rev=776117&r1=776116&r2=776117&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Variable.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Variable.java Mon May 18 22:23:04 2009
@@ -24,6 +24,7 @@
 import org.apache.openjpa.jdbc.sql.SQLBuffer;
 import org.apache.openjpa.jdbc.sql.Select;
 import org.apache.openjpa.kernel.exps.ExpressionVisitor;
+import org.apache.openjpa.kernel.exps.Path;
 import org.apache.openjpa.meta.ClassMetaData;
 
 /**
@@ -75,6 +76,10 @@
         return _path;
     }
 
+    public Path getPath() {
+        return _path;
+    }
+
     /**
      * Set the path this variable is aliased to.
      */

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Val.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Val.java?rev=776117&r1=776116&r2=776117&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Val.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Val.java Mon May 18 22:23:04 2009
@@ -131,4 +131,8 @@
     public Value getSelectAs() {
         return _alias != null ? this : null;
     }
+
+    public Path getPath() {
+        return null;
+    }
 }

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java?rev=776117&r1=776116&r2=776117&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java Mon May 18 22:23:04 2009
@@ -88,4 +88,6 @@
      * Return 'this' concrete class if alias is set, otherwise null
      */
     public Value getSelectAs();
+
+    public Path getPath();
 }

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=776117&r1=776116&r2=776117&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 Mon May 18 22:23:04 2009
@@ -651,7 +651,13 @@
             // clause, since we might be in a subquery against a collection
             if (isPath(left)) {
                 Path path = getPath(left);
-                setCandidate(getFieldType(path.last()), alias);
+                FieldMetaData fmd = path.last();
+                ClassMetaData candidate = getFieldType(fmd);
+
+                if (candidate == null && fmd.isElementCollection())
+                    candidate = fmd.getDefiningMetaData();
+
+                setCandidate(candidate, alias);
 
                 Path subpath = factory.newPath(ctx().subquery);
                 subpath.setMetaData(ctx().subquery.getMetaData());
@@ -1491,6 +1497,14 @@
     private Value validateMapPath(JPQLNode node, JPQLNode id) {
         Path path = (Path) getValue(id);
         FieldMetaData fld = path.last();
+
+        if (fld == null && ctx().subquery != null) {
+            Value var = getVariable(id.text, false);
+            if (var != null) {
+                path = factory.newPath(var);
+                fld = path.last();
+            }
+        }
         
         if (fld != null) {            
             // validate the field is of type java.util.Map
@@ -1503,7 +1517,11 @@
                 throw parseException(EX_USER, "bad-qualified-identifier",
                     new Object[]{ id.text, oper}, null);
             }
-        }         
+        }
+        else
+            throw parseException(EX_USER, "unknown-type",
+                new Object[]{ id.text}, null);
+            
         return path;
     }
 
@@ -1517,7 +1535,9 @@
         FieldMetaData fld = path.last();
         path = (Path) factory.getKey(path);
         ClassMetaData meta = fld.getKey().getTypeMetaData();
-        if (inWhereClause && meta != null)
+        if (inWhereClause && meta != null &&
+            fld.isElementCollection() &&
+            fld.getElement().getEmbeddedMetaData() != null)
             // check basic type
             throw parseException(EX_USER, "bad-general-identifier",
                 new Object[]{ id.text, "KEY" }, null);

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=776117&r1=776116&r2=776117&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 Mon May 18 22:23:04 2009
@@ -746,6 +746,18 @@
             assertEmployee(e);
         }
         tran.commit();
+        em.clear();
+        // test range variable over element collection
+        String[] query = {
+            "select e from Employee e, in (e.nickNames) n " +
+            " where n like '%1'",  
+        };
+        for (int i = 0; i < query.length; i++) {
+            es = em.createQuery(query[i]).getResultList();
+            for (Employee e : es){
+                assertEmployee(e);
+            }
+        }
         em.close();
     }
 
@@ -2145,6 +2157,25 @@
         }
         
         tran.commit();
+
+        String query[] = {
+            "select d from Department1 d join d.empMap e " +
+                " where KEY(e) > 1 order by d",
+            "select d from Department1 d join d.empMap e" +
+                " where d.deptId = KEY(e) order by d",
+            "select d from Department1 d " +
+                " where d.deptId < ANY " +
+                " (select KEY(e) from in(d.empMap) e) " +
+                " order by d",
+            "select d from Department1 d " +
+                " where d.deptId < SOME " +
+                " (select KEY(e) from Department1 d1, in(d1.empMap) e) " +
+                " order by d",
+        };
+        for (int i = 0; i < query.length; i++) {
+            ds1 = em.createQuery(query[i]).getResultList();
+            assertDepartment1(ds1.get(0));
+        }
         em.close();
     }
 
@@ -2290,6 +2321,66 @@
         }
 
         tran.commit();
+
+        String imageKey1 = (String) is1.get(0).getImages().
+            keySet().toArray()[0];
+        String imageKey2 = (String) is2.get(0).getImages().
+            keySet().toArray()[0];
+        String imageKey3 = (String) is3.get(0).getImages().
+            keySet().toArray()[0];
+        String[] query = {
+            "select i from Item1 i" +
+                " 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",
+            "select i from Item2 i" +
+                " where exists " +
+                " (select e from Item2 i, in(i.images) e" +
+                "   where ?1 = KEY(e)) " +
+                " order by i",
+            "select i from Item3 i" +
+                " where exists " +
+                " (select e from Item3 i, in(i.images) e" +
+                "   where ?1 = KEY(e)) " +
+                " order by i",
+        };
+
+        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;
+            }
+        }
         em.close();
     }
 
@@ -2308,6 +2399,56 @@
             assertCompany2(c);
         }
         tran.commit();
+
+        em.clear();
+        // test KEY(e) appeared in subquery
+        Division d1 = (Division) ((Company1) cs1.get(0)).getOrganization().
+            keySet().toArray()[0];
+        Division d2 = (Division) ((Company2) cs2.get(0)).getOrganization().
+            keySet().toArray()[0];
+        String[] query = {
+            "select c from Company1 c, in(c.organization) d " +
+                " where KEY(d) = ?1",
+            "select c from Company1 c " +
+                " where ?1 = " +
+                " (select KEY(d) from Company1 c, in(c.organization) d" +
+                "   where d.id = 1)" +
+                " order by c ",  
+            "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 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" +
+                "  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;
+            }            
+        }
         em.close();
     }