Author: faywang
Date: Wed Jun 24 06:02:17 2009
New Revision: 787916

URL: http://svn.apache.org/viewvc?rev=787916&view=rev
Log:
OPENJPA-1143: subquery support

Modified:
    
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpressionBuilder.java
    
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java
    
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/FromImpl.java
    
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Joins.java
    
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/PathImpl.java
    
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/RootImpl.java
    
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SubqueryImpl.java

Modified: 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpressionBuilder.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpressionBuilder.java?rev=787916&r1=787915&r2=787916&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpressionBuilder.java
 (original)
+++ 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpressionBuilder.java
 Wed Jun 24 06:02:17 2009
@@ -40,7 +40,6 @@
 import org.apache.openjpa.persistence.meta.AbstractManagedType;
 import org.apache.openjpa.persistence.meta.Members;
 import org.apache.openjpa.persistence.meta.MetamodelImpl;
-import org.apache.openjpa.persistence.meta.Types;
 
 /**
  * Converts expressions of a CriteriaQuery to kernel Expression.
@@ -53,6 +52,7 @@
     public QueryExpressions getQueryExpressions(ExpressionFactory factory, 
         CriteriaQueryImpl q) {
         QueryExpressions exps = new QueryExpressions();
+        //exps.setContexts(q.getContexts());
 
         evalAccessPaths(exps, factory, q);
         //exps.alias = null;      // String   
@@ -181,10 +181,7 @@
                         .toKernelExpression(factory, model, q), filter);
                 }
             }
-            if (((RootImpl<?>)root).getCorrelatedParent() != null) {
-                filter = and(factory, ((RootImpl<?>)root)
-                    .toKernelExpression(factory, model, q), filter);
-            }
+            ((RootImpl)root).addToContext(factory, model, q);
         }
         if (where != null) {
             filter = and(factory, where.toKernelExpression

Modified: 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java?rev=787916&r1=787915&r2=787916&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java
 (original)
+++ 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java
 Wed Jun 24 06:02:17 2009
@@ -20,16 +20,14 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import javax.persistence.Parameter;
+import javax.persistence.criteria.AbstractQuery;
 import javax.persistence.criteria.CriteriaQuery;
 import javax.persistence.criteria.Expression;
 import javax.persistence.criteria.Order;
@@ -45,7 +43,6 @@
 import org.apache.openjpa.kernel.exps.ExpressionFactory;
 import org.apache.openjpa.kernel.exps.QueryExpressions;
 import org.apache.openjpa.kernel.exps.Value;
-import org.apache.openjpa.persistence.QueryImpl;
 import org.apache.openjpa.persistence.meta.MetamodelImpl;
 import org.apache.openjpa.persistence.meta.Types;
 
@@ -73,7 +70,7 @@
     private PredicateImpl       _having;
     private List<Subquery<?>>   _subqueries;
     private Boolean             _distinct;
-    private SubqueryImpl<?>     _context;
+    private SubqueryImpl<?>     _delegator;
     
     // AliasContext
     private int aliasCount = 0;
@@ -83,25 +80,38 @@
         new HashMap<Selection<?>, Value>();
     private Map<Selection<?>,Value> _values = 
         new HashMap<Selection<?>, Value>();
-    private Map<Selection<?>,String> _aliases = 
-        new HashMap<Selection<?>, String>();
+    private Map<Selection<?>,String> _aliases = null;
+
+    // SubqueryContext
+    //private Stack<Context> _contexts = null;
     
     public CriteriaQueryImpl(MetamodelImpl model) {
         this._model = model;
+        _aliases = new HashMap<Selection<?>, String>(); 
     }
     
-    public void setContext(SubqueryImpl<?> context) {
-        _context = context;
+    public CriteriaQueryImpl(MetamodelImpl model, SubqueryImpl<?> delegator) {
+        this._model = model;
+        _delegator = delegator;
+        _aliases = getAliases();
+    }
+
+    public void setDelegator(SubqueryImpl<?> delegator) {
+        _delegator = delegator;
     }
     
-    public SubqueryImpl<?> getContext() {
-        return _context;
+    public SubqueryImpl<?> getDelegator() {
+        return _delegator;
     }
     
     public MetamodelImpl getMetamodel() {
         return _model;
     }
     
+    //public Stack<Context> getContexts() {
+    //    return _contexts;
+    //}
+    
     public CriteriaQuery distinct(boolean distinct) {
         _distinct = distinct;
         return this;
@@ -319,8 +329,11 @@
      * receiver with the help of the given {...@link ExpressionFactory}.
      */
     QueryExpressions getQueryExpressions(ExpressionFactory factory) {
+        //_contexts = new Stack<Context>();
+        //Context context = new Context(null, null, null);
+        //    _contexts.push(context);
         return new CriteriaExpressionBuilder()
-              .getQueryExpressions(factory, this);
+             .getQueryExpressions(factory, this);
     }    
     
     public void assertRoot() {
@@ -329,6 +342,30 @@
     }
     
     //
+    // SubqueryContext
+    //
+    //public void setContexts(Stack<Context> contexts) {
+    //    _contexts = contexts;
+    //}
+    
+    public CriteriaQueryImpl getInnermostParent() {
+        if (_delegator == null)
+            return this;
+        AbstractQuery parent = _delegator.getParent();
+        if (parent instanceof CriteriaQueryImpl) 
+            return (CriteriaQueryImpl)parent;
+        // parent is a SubqueryImpl    
+        return ((SubqueryImpl)parent).getDelegate().getInnermostParent();
+    }
+    
+    public Map<Selection<?>,String> getAliases() {
+        CriteriaQueryImpl c = getInnermostParent();
+        if (c._aliases == null)
+            c._aliases = new HashMap<Selection<?>, String>();
+        return c._aliases;
+    }
+    
+    //
     // AliasContext management
     //
     
@@ -390,6 +427,8 @@
         _variables.put(node, var);
         _values.put(node, path);
         _aliases.put(node, alias);
+        //_contexts.peek().addSchema(alias, var.getMetaData());
+        //_contexts.peek().addVariable(alias, var);
     }
     
     public boolean isRegistered(Selection<?> selection) {

Modified: 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/FromImpl.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/FromImpl.java?rev=787916&r1=787915&r2=787916&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/FromImpl.java
 (original)
+++ 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/FromImpl.java
 Wed Jun 24 06:02:17 2009
@@ -29,7 +29,6 @@
 import javax.persistence.criteria.ListJoin;
 import javax.persistence.criteria.MapJoin;
 import javax.persistence.criteria.SetJoin;
-import javax.persistence.metamodel.Attribute;
 import javax.persistence.metamodel.CollectionAttribute;
 import javax.persistence.metamodel.ListAttribute;
 import javax.persistence.metamodel.MapAttribute;
@@ -39,7 +38,6 @@
 
 import org.apache.openjpa.persistence.meta.AbstractManagedType;
 import org.apache.openjpa.persistence.meta.Members;
-import org.apache.openjpa.persistence.meta.Types;
 
 /**
  * Represents a bound type, usually an entity that appears in the from clause, 
@@ -174,7 +172,7 @@
 
 
     public <W,Y> CollectionJoin<W, Y> joinCollection(String attr) {
-        return (CollectionJoin<W,Y>)join(attr, JoinType.INNER);
+        return (CollectionJoin<W,Y>)join(type.getCollection(attr), 
JoinType.INNER);
     }
 
     public <W,Y> CollectionJoin<W, Y> joinCollection(String attr, JoinType jt) 
{
@@ -182,7 +180,7 @@
     }
 
     public <W,Y> ListJoin<W, Y> joinList(String attr) {
-        return (ListJoin<W,Y>)join(attr, JoinType.INNER);
+        return (ListJoin<W,Y>)join(type.getList(attr), JoinType.INNER);
     }
 
     public <W,Y> ListJoin<W,Y> joinList(String attr, JoinType jt) {

Modified: 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Joins.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Joins.java?rev=787916&r1=787915&r2=787916&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Joins.java
 (original)
+++ 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Joins.java
 Wed Jun 24 06:02:17 2009
@@ -58,11 +58,13 @@
     public static class SingularJoin<Z,X> extends FromImpl<Z,X> 
         implements Join<Z,X>{
         private final JoinType joinType;
+        private boolean allowNull = false;
         
         public SingularJoin(FromImpl<?,Z> from, 
             Members.SingularAttributeImpl<? super Z, X> member, JoinType jt) {
             super(from, member, member.getJavaType());
             joinType = jt;
+            allowNull = joinType != JoinType.INNER;
         }
         
         public JoinType getJoinType() {
@@ -85,16 +87,26 @@
         @Override
         public Value toValue(ExpressionFactory factory, MetamodelImpl model, 
             CriteriaQueryImpl c) {
+            ClassMetaData meta = _member.fmd.getDeclaredTypeMetaData();
+            org.apache.openjpa.kernel.exps.Path path = null;
+            SubqueryImpl<?> subquery = c.getDelegator();
+            PathImpl<?,?> parent = getInnermostParentPath();
             if (c.isRegistered(this))
                 return c.getValue(this);
-            boolean allowNull = joinType != JoinType.INNER;
-            ClassMetaData meta = _member.fmd.getDeclaredTypeMetaData();
-            org.apache.openjpa.kernel.exps.Path path = 
-                (org.apache.openjpa.kernel.exps.Path)
-                _parent.toValue(factory, model, c);
-            path.get(_member.fmd, allowNull);
-            path.setMetaData(meta);
-            path.setImplicitType(meta.getDescribedType());
+            else if (parent.inSubquery(subquery)) {
+                org.apache.openjpa.kernel.exps.Subquery subQ = 
+                    subquery.getSubQ();
+                path = factory.newPath(subQ);
+                path.setMetaData(subQ.getMetaData());
+                //path.setSchemaAlias(c.getAlias(this));
+            } else {
+                path = 
+                    (org.apache.openjpa.kernel.exps.Path)
+                    _parent.toValue(factory, model, c);
+                path.get(_member.fmd, allowNull);
+                path.setMetaData(meta);
+                path.setImplicitType(meta.getDescribedType());
+            }
             return path;
         }
         
@@ -104,7 +116,23 @@
             CriteriaQueryImpl c) {
             ClassMetaData meta = _member.fmd.getDeclaredTypeMetaData();
             org.apache.openjpa.kernel.exps.Path path = null;
-            if (c.isRegistered(_parent)) {
+            SubqueryImpl<?> subquery = c.getDelegator();
+            PathImpl<?,?> parent = getInnermostParentPath();
+            org.apache.openjpa.kernel.exps.Expression filter = null;
+            PathImpl correlatedParent = null;
+            boolean bind = true;
+            if (parent.inSubquery(subquery)) {
+                org.apache.openjpa.kernel.exps.Subquery subQ = 
+                    subquery.getSubQ();
+                path = factory.newPath(subQ);
+                correlatedParent = _parent.getCorrelatedParent();
+                if (correlatedParent == null) {
+                    path.setMetaData(subQ.getMetaData());
+                    path.get(_member.fmd, allowNull);
+                    //path.setSchemaAlias(c.getAlias(_parent));
+                } else 
+                    bind = false;
+            } else if (c.isRegistered(_parent)) {
                Value var = c.getVariable(_parent);
                path = factory.newPath(var);
                path.setMetaData(meta);
@@ -112,12 +140,13 @@
             } else
                path = 
                 (org.apache.openjpa.kernel.exps.Path)toValue(factory, model, 
c);
-            Value var = factory.newBoundVariable(c.getAlias(this), 
-                meta.getDescribedType());
-            org.apache.openjpa.kernel.exps.Expression join = factory
-                .bindVariable(var, path);
-            c.registerVariable(this, var, path);
-            org.apache.openjpa.kernel.exps.Expression filter = null;
+            org.apache.openjpa.kernel.exps.Expression join = null;
+            if (bind) {
+                Value var = factory.newBoundVariable(c.getAlias(this), 
+                    meta.getDescribedType());
+                join = factory.bindVariable(var, path);
+                c.registerVariable(this, var, path);
+            }
             if (getJoins() != null) {
                 for (Join<?, ?> join1 : getJoins()) {
                     filter = CriteriaExpressionBuilder.and(factory, 
@@ -125,7 +154,22 @@
                         toKernelExpression(factory, model, c), filter);
                 }
             }
-            return CriteriaExpressionBuilder.and(factory, join, filter);
+            org.apache.openjpa.kernel.exps.Expression expr = 
+                CriteriaExpressionBuilder.and(factory, join, filter);
+            
+            if (correlatedParent == null)
+                return expr;
+            else {
+                org.apache.openjpa.kernel.exps.Path parentPath =
+                    (org.apache.openjpa.kernel.exps.Path)
+                    correlatedParent.toValue(factory, model, c);
+                parentPath.get(_member.fmd, allowNull);
+                //parentPath.setSchemaAlias(c.getAlias(correlatedParent));
+                path.setMetaData(meta);
+                //filter = bindVariableForKeyPath(path, alias, filter);
+                filter = factory.equal(parentPath, path);
+                return CriteriaExpressionBuilder.and(factory, expr, filter);
+            }
         }
     }
     
@@ -140,11 +184,13 @@
     public static abstract class AbstractCollection<Z,C,E> extends 
FromImpl<Z,E> 
         implements PluralJoin<Z, C, E> {
         final JoinType joinType;
+        boolean allowNull = false;
         
         public AbstractCollection(FromImpl<?,Z> from, 
             Members.PluralAttributeImpl<? super Z, C, E> member, JoinType jt) {
             super(from, member, member.getBindableJavaType());
             joinType = jt;
+            allowNull = joinType != JoinType.INNER;
         }
         
         public JoinType getJoinType() {
@@ -167,6 +213,12 @@
         public PluralAttribute<? super Z, C, E> getModel() {
             return (PluralAttribute<? super Z, C, E>) _member.getType();
         }
+        
+        public ClassMetaData getMemberClassMetaData() {
+            return _member.fmd.isElementCollection() 
+                ? _member.fmd.getEmbeddedMetaData()
+                : _member.fmd.getElement().getDeclaredTypeMetaData();
+        }
 
         /**
          * Convert this path to a kernel path (value).
@@ -174,13 +226,20 @@
         @Override
         public Value toValue(ExpressionFactory factory, MetamodelImpl model,
             CriteriaQueryImpl c) {
-            boolean allowNull = joinType != JoinType.INNER;
-            ClassMetaData meta = _member.fmd.getElement()
-                .getDeclaredTypeMetaData();
+            ClassMetaData meta = getMemberClassMetaData(); 
             org.apache.openjpa.kernel.exps.Path path = null;
+            SubqueryImpl<?> subquery = c.getDelegator();
+            PathImpl<?,?> parent = getInnermostParentPath();
+            
             if (c.isRegistered(this)) {
                 Value var = c.getVariable(this);
                 path = factory.newPath(var);
+            } else if (parent.inSubquery(subquery)) {
+                org.apache.openjpa.kernel.exps.Subquery subQ = 
+                    subquery.getSubQ();
+                path = factory.newPath(subQ);
+                path.setMetaData(subQ.getMetaData());
+                //path.setSchemaAlias(c.getAlias(this));
             } else {
                 path = (org.apache.openjpa.kernel.exps.Path)
                     _parent.toValue(factory, model, c);
@@ -197,12 +256,25 @@
         public org.apache.openjpa.kernel.exps.Expression toKernelExpression(
             ExpressionFactory factory, MetamodelImpl model, 
             CriteriaQueryImpl c) {
-            ClassMetaData meta = _member.fmd.isElementCollection() 
-                ? _member.fmd.getEmbeddedMetaData()
-                : _member.fmd.getElement().getDeclaredTypeMetaData();
-                
+            ClassMetaData meta = getMemberClassMetaData(); 
             org.apache.openjpa.kernel.exps.Path path = null;
-            if (c.isRegistered(_parent)) {
+            SubqueryImpl<?> subquery = c.getDelegator();
+            PathImpl<?,?> parent = getInnermostParentPath();
+            org.apache.openjpa.kernel.exps.Expression filter = null;
+            PathImpl correlatedParent = null;
+            boolean bind = true;
+            if (parent.inSubquery(subquery)) {
+                org.apache.openjpa.kernel.exps.Subquery subQ = 
+                    subquery.getSubQ();
+                path = factory.newPath(subQ);
+                correlatedParent = _parent.getCorrelatedParent();
+                if (correlatedParent == null) {
+                    path.setMetaData(subQ.getMetaData());
+                    path.get(_member.fmd, allowNull);
+                    //path.setSchemaAlias(c.getAlias(_parent));
+                } else
+                    bind = false;
+            } else if (c.isRegistered(_parent)) {
                 Value var = c.getVariable(_parent);
                 path = factory.newPath(var);
                 path.setMetaData(meta);
@@ -210,13 +282,14 @@
             } else           
                 path = (org.apache.openjpa.kernel.exps.Path)
                     toValue(factory, model, c);
-            
-            Value var = factory.newBoundVariable(c.getAlias(this), 
-                meta.getDescribedType());
-            org.apache.openjpa.kernel.exps.Expression join = 
-                factory.bindVariable(var, path);
-            c.registerVariable(this, var, path);
-            org.apache.openjpa.kernel.exps.Expression filter = null;
+        
+            org.apache.openjpa.kernel.exps.Expression join = null;
+            if (bind) {
+                Value var = factory.newBoundVariable(c.getAlias(this), 
+                        meta.getDescribedType());
+                join = factory.bindVariable(var, path);
+                c.registerVariable(this, var, path);
+            }
             if (getJoins() != null) {
                 for (Join<?, ?> join1 : getJoins()) {
                     filter = CriteriaExpressionBuilder.and(factory, 
@@ -224,8 +297,22 @@
                         toKernelExpression(factory, model, c), filter);
                 }
             }
-            return CriteriaExpressionBuilder.and(factory, join, filter);
-       }
+            org.apache.openjpa.kernel.exps.Expression expr = 
+                CriteriaExpressionBuilder.and(factory, join, filter);
+            if (correlatedParent == null)
+                return expr;
+            else {
+                org.apache.openjpa.kernel.exps.Path parentPath =
+                    (org.apache.openjpa.kernel.exps.Path)
+                    correlatedParent.toValue(factory, model, c);
+                parentPath.get(_member.fmd, allowNull);
+                //parentPath.setSchemaAlias(c.getAlias(correlatedParent));
+                path.setMetaData(meta);
+                //filter = bindVariableForKeyPath(path, alias, filter);
+                filter = factory.equal(parentPath, path);
+                return CriteriaExpressionBuilder.and(factory, expr, filter);
+            }
+        }
     }
     
     /**

Modified: 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/PathImpl.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/PathImpl.java?rev=787916&r1=787915&r2=787916&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/PathImpl.java
 (original)
+++ 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/PathImpl.java
 Wed Jun 24 06:02:17 2009
@@ -23,7 +23,6 @@
 import javax.persistence.criteria.Join;
 import javax.persistence.criteria.JoinType;
 import javax.persistence.criteria.Path;
-import javax.persistence.metamodel.Attribute;
 import javax.persistence.metamodel.Bindable;
 import javax.persistence.metamodel.ManagedType;
 import javax.persistence.metamodel.MapAttribute;
@@ -58,7 +57,8 @@
     protected final PathImpl<?,Z> _parent;
     protected final Members.Member<? super Z,?> _member;
     private boolean isEmbedded = false;
-    
+    private PathImpl<?,?> _correlatedParent;
+
     /**
      * Protected. use by root path which neither represent a member nor has a
      * parent. 
@@ -121,6 +121,13 @@
             parent._member); 
     }
     
+    public void setCorrelatedParent(PathImpl<?,?> correlatedParent) {
+        _correlatedParent = correlatedParent;
+    }
+    
+    public PathImpl<?,?> getCorrelatedParent() {
+        return _correlatedParent;
+    }
     
     /**
      * Convert this path to a kernel path.
@@ -131,27 +138,26 @@
         if (q.isRegistered(this))
             return q.getValue(this);
         org.apache.openjpa.kernel.exps.Path path = null;
-        SubqueryImpl<?> subquery = q.getContext();
+        SubqueryImpl<?> subquery = q.getDelegator();
         PathImpl<?,?> parent = getInnermostParentPath();
-        if (parent.inSubquery(subquery)) {
+        boolean allowNull = _parent == null ? false : _parent instanceof Join 
+            && ((Join<?,?>)_parent).getJoinType() != JoinType.INNER;
+        
+        if (_parent != null && q.isRegistered(_parent)) {
+            path = factory.newPath(q.getVariable(_parent));
+            //path.setSchemaAlias(q.getAlias(_parent));
+            path.get(_member.fmd, allowNull);
+        } else if (parent.inSubquery(subquery)) {
             org.apache.openjpa.kernel.exps.Subquery subQ = subquery.getSubQ();
             path = factory.newPath(subQ);
             path.setMetaData(subQ.getMetaData());
-            boolean allowNull = false;
+            //path.setSchemaAlias(q.getAlias(_parent));
+            traversePath(_parent, path, _member.fmd);
+        } else if (_parent != null) {
+            path = (org.apache.openjpa.kernel.exps.Path)
+            _parent.toValue(factory, model, q);
             path.get(_member.fmd, allowNull);
-        } else if (_parent != null) { 
-            if (q.isRegistered(_parent)) {
-                path = factory.newPath(q.getVariable(_parent));
-                ClassMetaData meta = _member.fmd.getDeclaredTypeMetaData();
-                path.setMetaData(meta);
-            } else {
-                path = (org.apache.openjpa.kernel.exps.Path)
-                     _parent.toValue(factory, model, q);
-            }
-            boolean allowNull = _parent instanceof Join 
-                    && ((Join<?,?>)_parent).getJoinType() != JoinType.INNER;
-            path.get(_member.fmd, allowNull);
-        } else {
+        } else if (_parent == null) {
             path = factory.newPath();
             path.setMetaData(model.repos.getCachedMetaData(getJavaType()));
         }
@@ -171,6 +177,22 @@
         return subquery != null && subquery.getRoots().contains(this);
     }
     
+    protected void traversePath(PathImpl<?,?> parent,
+            org.apache.openjpa.kernel.exps.Path path, FieldMetaData fmd) {
+        boolean allowNull = parent == null ? false : parent instanceof Join 
+            && ((Join<?,?>)parent).getJoinType() != JoinType.INNER;
+        FieldMetaData fmd1 = parent._member == null ? null : 
parent._member.fmd;
+        PathImpl<?,?> parent1 = parent._parent;
+        if (parent1 == null || parent1.getCorrelatedParent() != null) {
+            if (fmd != null) 
+                path.get(fmd, allowNull);
+            return;
+        }
+        traversePath(parent1, path, fmd1);
+        if (fmd != null) 
+            path.get(fmd, allowNull);
+    }
+    
     /**
      *  Return the path corresponding to the referenced 
      *  single-valued attribute.

Modified: 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/RootImpl.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/RootImpl.java?rev=787916&r1=787915&r2=787916&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/RootImpl.java
 (original)
+++ 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/RootImpl.java
 Wed Jun 24 06:02:17 2009
@@ -22,7 +22,7 @@
 import javax.persistence.criteria.Root;
 import javax.persistence.metamodel.EntityType;
 
-import org.apache.openjpa.kernel.exps.Expression;
+import org.apache.openjpa.kernel.exps.AbstractExpressionBuilder;
 import org.apache.openjpa.kernel.exps.ExpressionFactory;
 import org.apache.openjpa.kernel.exps.Path;
 import org.apache.openjpa.kernel.exps.Subquery;
@@ -39,7 +39,6 @@
  */
 public class RootImpl<X> extends FromImpl<X,X> implements Root<X> {
     private final Types.Entity<X> _entity;
-    private RootImpl<X> _correlatedParent;
         
     public RootImpl(Types.Entity<X> type) {
         super(type);
@@ -50,12 +49,18 @@
         return _entity;
     }
     
-    public void setCorrelatedParent(RootImpl<X> correlatedParent) {
-        _correlatedParent = correlatedParent;
-    }
-    
-    public RootImpl<X> getCorrelatedParent() {
-        return _correlatedParent;
+    public void  addToContext(ExpressionFactory factory, MetamodelImpl model, 
+        CriteriaQueryImpl q) {
+        String alias = q.getAlias(this);
+        Value var = factory.newBoundVariable(alias, 
+            AbstractExpressionBuilder.TYPE_OBJECT);
+        var.setMetaData(_entity.meta);
+        //TODO:
+        //Context currContext = (Context)q.getContexts().peek();
+        //currContext.addSchema(alias, _entity.meta); 
+        //currContext.addVariable(alias, var);
+        //if (currContext.schemaAlias == null)
+        //    currContext.schemaAlias = alias;
     }
     
     /**
@@ -64,7 +69,7 @@
     @Override
     public Value toValue(ExpressionFactory factory, MetamodelImpl model, 
         CriteriaQueryImpl c) {
-        SubqueryImpl<?> subquery = c.getContext();
+        SubqueryImpl<?> subquery = c.getDelegator();
         Path var = null;
         if (inSubquery(subquery)) {
             Subquery subQ = subquery.getSubQ();
@@ -85,13 +90,8 @@
         ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl c) {
         Value path = toValue(factory, model, c);
         Value var = factory.newBoundVariable(c.getAlias(this), 
-            _entity.meta.getDescribedType());
-        Expression exp = factory.bindVariable(var, path);
-        
-        if (_correlatedParent == null) 
-            return exp;
-        Value path1 = _correlatedParent.toValue(factory, model, c);
-        return factory.equal(path1, path);
+             _entity.meta.getDescribedType());
+        return factory.bindVariable(var, path);
     }
     
     public String toString() {

Modified: 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SubqueryImpl.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SubqueryImpl.java?rev=787916&r1=787915&r2=787916&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SubqueryImpl.java
 (original)
+++ 
openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SubqueryImpl.java
 Wed Jun 24 06:02:17 2009
@@ -39,6 +39,7 @@
 import org.apache.openjpa.kernel.exps.Value;
 import org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder;
 import org.apache.openjpa.meta.ClassMetaData;
+import org.apache.openjpa.meta.JavaTypes;
 import org.apache.openjpa.persistence.meta.AbstractManagedType;
 import org.apache.openjpa.persistence.meta.MetamodelImpl;
 import org.apache.openjpa.persistence.meta.Types;
@@ -53,23 +54,47 @@
  * @param <T> the type selected by this subquery.
  */
 public class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
-    private final CriteriaQueryImpl _parent;
+    private final AbstractQuery _parent;
     private final CriteriaQueryImpl _delegate;
+    private final MetamodelImpl  _model;
     private java.util.Set<Join<?,?>> _joins;
     private Expression<T> _select;
     private org.apache.openjpa.kernel.exps.Subquery _subq;
     
-    public SubqueryImpl(Class<T> cls, CriteriaQueryImpl parent) {
+    public SubqueryImpl(Class<T> cls, AbstractQuery parent) {
         super(cls);
         _parent = parent;
-        _delegate = new CriteriaQueryImpl(parent.getMetamodel());
-        _delegate.setContext(this);
+        if (parent instanceof CriteriaQueryImpl) 
+            _model = ((CriteriaQueryImpl)parent).getMetamodel();
+        else if (parent instanceof SubqueryImpl) 
+            _model = ((SubqueryImpl)parent).getMetamodel();
+        else 
+            _model = null;
+        
+        _delegate = new CriteriaQueryImpl(_model, this);
     }
     
     public AbstractQuery getParent() {
         return _parent;
     }
     
+    public CriteriaQueryImpl getDelegate() {
+        return _delegate;
+    }
+    
+    public MetamodelImpl getMetamodel() {
+        return _model;
+    }
+    
+    //public Stack<Context> getContexts() {
+    //    return getInnermostParent().getContexts();
+    //}
+    
+    public CriteriaQueryImpl getInnermostParent() {
+        return (CriteriaQueryImpl)(((_parent instanceof CriteriaQueryImpl)) ? 
+            _parent : ((SubqueryImpl)_parent).getInnermostParent());
+    }
+
     public Subquery<T> select(Expression<T> expression) {
         _select = expression;
         _delegate.select(expression);
@@ -201,15 +226,41 @@
         final boolean subclasses = true;
         CriteriaExpressionBuilder queryEval = new CriteriaExpressionBuilder();
         String alias = q.getAlias(this);
-        ClassMetaData candidate =  
-            ((AbstractManagedType<?>)getRoot().getModel()).meta;
+        ClassMetaData candidate = getCandidate(); 
         _subq = factory.newSubquery(candidate, subclasses, alias);
         _subq.setMetaData(candidate);
+        //TODO:
+        //Stack<Context> contexts = getContexts();
+        //Context context = new Context(null, _subq, contexts.peek());
+        //contexts.push(context);
+        //_delegate.setContexts(contexts);
         QueryExpressions subexp = queryEval.getQueryExpressions(factory, 
                 _delegate);
         _subq.setQueryExpressions(subexp);
         if (subexp.projections.length > 0)
             JPQLExpressionBuilder.checkEmbeddable(subexp.projections[0], null);
+        //contexts.pop();
         return _subq;
     }
+    
+    // if we are in a subquery against a collection from a 
+    // correlated parent, the candidate of the subquery
+    // should be the class metadata of the collection element 
+    private ClassMetaData getCandidate() {
+        RootImpl<?> root = (RootImpl<?>)getRoot();
+        RootImpl<?> correlatedRoot = (RootImpl<?>)root.getCorrelatedParent();
+        if (correlatedRoot != null && root.getJoins() != null) {
+            FromImpl join = (FromImpl) root.getJoins().iterator().next();
+            if (join._member.fmd.getDeclaredTypeCode() == 
+                JavaTypes.COLLECTION || 
+                join._member.fmd.getDeclaredTypeCode() == 
+                JavaTypes.MAP)
+            return join._member.fmd.isElementCollection()
+                ? join._member.fmd.getEmbeddedMetaData()
+                : join._member.fmd.getElement().getDeclaredTypeMetaData();
+            return join._member.fmd.getDeclaredTypeMetaData();
+        }
+        return ((AbstractManagedType<?>)root.getModel()).meta;
+    }
+    
 }


Reply via email to