Return-Path: Delivered-To: apmail-openjpa-commits-archive@www.apache.org Received: (qmail 5506 invoked from network); 26 Jun 2009 06:34:52 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 26 Jun 2009 06:34:52 -0000 Received: (qmail 15059 invoked by uid 500); 26 Jun 2009 06:35:03 -0000 Delivered-To: apmail-openjpa-commits-archive@openjpa.apache.org Received: (qmail 15027 invoked by uid 500); 26 Jun 2009 06:35:03 -0000 Mailing-List: contact commits-help@openjpa.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@openjpa.apache.org Delivered-To: mailing list commits@openjpa.apache.org Received: (qmail 15007 invoked by uid 99); 26 Jun 2009 06:35:03 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 26 Jun 2009 06:35:02 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 26 Jun 2009 06:34:57 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 509DD23888D0; Fri, 26 Jun 2009 06:34:35 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r788604 - in /openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria: CriteriaExpressionBuilder.java Joins.java PathImpl.java RootImpl.java SubqueryImpl.java Date: Fri, 26 Jun 2009 06:34:35 -0000 To: commits@openjpa.apache.org From: faywang@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090626063435.509DD23888D0@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: faywang Date: Fri Jun 26 06:34:34 2009 New Revision: 788604 URL: http://svn.apache.org/viewvc?rev=788604&view=rev Log: OPENJPA-1143: correlation join 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/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=788604&r1=788603&r2=788604&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 Fri Jun 26 06:34:34 2009 @@ -49,8 +49,7 @@ */ public class CriteriaExpressionBuilder { - public QueryExpressions getQueryExpressions(ExpressionFactory factory, - CriteriaQueryImpl q) { + public QueryExpressions getQueryExpressions(ExpressionFactory factory, CriteriaQueryImpl q) { QueryExpressions exps = new QueryExpressions(); //exps.setContexts(q.getContexts()); @@ -76,8 +75,7 @@ return exps; } - protected void evalAccessPaths(QueryExpressions exps, - ExpressionFactory factory, CriteriaQueryImpl q) { + protected void evalAccessPaths(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl q) { Set metas = new HashSet(); Set> roots = q.getRoots(); if (roots != null) { @@ -88,17 +86,14 @@ for (Join join : root.getJoins()) { Class cls = join.getAttribute().getJavaType(); if (join.getAttribute().isAssociation()) { - ClassMetaData meta = metamodel.repos. - getMetaData(cls, null, true); - PersistenceType type = metamodel. - getPersistenceType(meta); - if (type == PersistenceType.ENTITY || - type == PersistenceType.EMBEDDABLE) + ClassMetaData meta = metamodel.repos.getMetaData(cls, null, true); + PersistenceType type = metamodel.getPersistenceType(meta); + if (type == PersistenceType.ENTITY || type == PersistenceType.EMBEDDABLE) metas.add(meta); } } if (root.getFetches() != null) { - for (Fetch fetch : root.getFetches()) { + for (Fetch fetch : root.getFetches()) { metas.add(metamodel.repos.getMetaData( fetch.getAttribute().getJavaType(), null, false)); @@ -110,8 +105,7 @@ exps.accessPath = metas.toArray(new ClassMetaData[metas.size()]); } - protected void evalOrdering(QueryExpressions exps, - ExpressionFactory factory, CriteriaQueryImpl q) { + protected void evalOrdering(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl q) { List orders = q.getOrderList(); MetamodelImpl model = q.getMetamodel(); if (orders == null) @@ -124,7 +118,7 @@ for (int i = 0; i < ordercount; i++) { OrderImpl order = (OrderImpl)orders.get(i); //Expression expr = order.getExpression(); - Expression expr = order.getExpression5(); + Expression expr = order.getExpression5(); exps.ordering[i] = Expressions.toValue( (ExpressionImpl)expr, factory, model, q); @@ -134,8 +128,7 @@ } } - protected void evalGrouping(QueryExpressions exps, - ExpressionFactory factory, CriteriaQueryImpl q) { + protected void evalGrouping(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl q) { // exps.grouping = null; // Value[] // exps.groupingClauses = null; // String[] List> groups = q.getGroupList(); @@ -155,8 +148,7 @@ : having.toKernelExpression(factory, model, q); } - protected void evalDistinct(QueryExpressions exps, - ExpressionFactory factory, CriteriaQueryImpl q) { + protected void evalDistinct(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl q) { Boolean distinct = q.getDistinct(); if (distinct == null) { exps.distinct = QueryExpressions.DISTINCT_FALSE; @@ -167,22 +159,33 @@ //exps.distinct &= ~QueryExpressions.DISTINCT_AUTO; } - protected void evalFilter(QueryExpressions exps, ExpressionFactory factory, - CriteriaQueryImpl q) { + protected void evalFilter(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl q) { Set> roots = q.getRoots(); MetamodelImpl model = q.getMetamodel(); PredicateImpl where = q.getRestriction(); - q.assertRoot(); + SubqueryImpl subQuery = q.getDelegator(); org.apache.openjpa.kernel.exps.Expression filter = null; - for (Root root : roots) { - if (root.getJoins() != null) { - for (Join join : root.getJoins()) { - filter = and(factory, ((ExpressionImpl)join) - .toKernelExpression(factory, model, q), filter); + if (subQuery == null || subQuery.getCorrelatedJoins() == null) { + q.assertRoot(); + for (Root root : roots) { + if (root.getJoins() != null) { + for (Join join : root.getJoins()) { + filter = and(factory, ((ExpressionImpl)join) + .toKernelExpression(factory, model, q), filter); + } } + ((RootImpl)root).addToContext(factory, model, q); + } + } + if (subQuery != null) { + List> corrJoins = subQuery.getCorrelatedJoins(); + if (corrJoins != null) { + for (int i = 0; i < corrJoins.size(); i++) + filter = and(factory, ((ExpressionImpl)corrJoins.get(i)) + .toKernelExpression(factory, model, q), filter); } - ((RootImpl)root).addToContext(factory, model, q); } + if (where != null) { filter = and(factory, where.toKernelExpression (factory, model, q), filter); @@ -192,8 +195,7 @@ exps.filter = filter; } - protected void evalProjections(QueryExpressions exps, - ExpressionFactory factory, CriteriaQueryImpl q) { + protected void evalProjections(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl q) { List> selections = q.getSelectionList(); MetamodelImpl model = q.getMetamodel(); // TODO: fill in projection clauses @@ -212,8 +214,8 @@ } private void getProjections(QueryExpressions exps, - List> selections, List projections, List aliases, - ExpressionFactory factory, CriteriaQueryImpl q, MetamodelImpl model) { + List> selections, List projections, List aliases, + ExpressionFactory factory, CriteriaQueryImpl q, MetamodelImpl model) { for (Selection s : selections) { List> sels = ((SelectionImpl)s).getSelections(); if (sels == null) { @@ -229,14 +231,20 @@ } } - protected boolean isDefaultProjection(List> selections, - CriteriaQueryImpl q) { - return selections == null - || (selections.size() == 1 && selections.get(0) == q.getRoot()); + protected boolean isDefaultProjection(List> selections, CriteriaQueryImpl q) { + if (selections == null) + return true; + if (selections.size() != 1) + return false; + Selection sel = selections.get(0); + if (q.getRoots() != null && sel == q.getRoot()) + return true; + if ((sel instanceof PathImpl) && ((PathImpl)sel)._correlatedPath != null) + return true; + return false; } - protected void evalFetchJoin(QueryExpressions exps, - ExpressionFactory factory, CriteriaQueryImpl q) { + protected void evalFetchJoin(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl q) { List iPaths = new ArrayList(); List oPaths = new ArrayList(); Set> roots = q.getRoots(); 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=788604&r1=788603&r2=788604&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 Fri Jun 26 06:34:34 2009 @@ -18,6 +18,7 @@ */ package org.apache.openjpa.persistence.criteria; +import javax.persistence.criteria.AbstractQuery; import javax.persistence.criteria.CollectionJoin; import javax.persistence.criteria.Expression; import javax.persistence.criteria.Join; @@ -73,6 +74,10 @@ return (FromImpl) _parent; } + public Member getMember() { + return (Member) _member; + } + /** * Return the metamodel attribute corresponding to the join. * @return metamodel attribute type corresponding to the join @@ -111,32 +116,37 @@ SubqueryImpl subquery = c.getDelegator(); PathImpl parent = getInnermostParentPath(); org.apache.openjpa.kernel.exps.Expression filter = null; - PathImpl correlatedParent = null; + PathImpl correlatedParentPath = 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); - path.get(_member.fmd, false); - } else { - path = (org.apache.openjpa.kernel.exps.Path)toValue(factory, model, c); - } + java.util.List> corrJoins = 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 (_correlatedPath == null) { + if (subquery != null) { + corrJoins = subquery.getCorrelatedJoins(); + org.apache.openjpa.kernel.exps.Subquery subQ = subquery.getSubQ(); + path = factory.newPath(subQ); + if ((corrJoins != null && corrJoins.contains(_parent)) || + (corrJoins == null && parent.inSubquery(subquery))) { + correlatedParentPath = _parent.getCorrelatedPath(); + bind = false; + } else { + path.setMetaData(subQ.getMetaData()); + path.get(_member.fmd, allowNull); + //path.setSchemaAlias(c.getAlias(_parent)); + } + } else if (c.isRegistered(_parent)) { + Value var = c.getVariable(_parent); + path = factory.newPath(var); + path.setMetaData(meta); + path.get(_member.fmd, false); + } else + path = (org.apache.openjpa.kernel.exps.Path)toValue(factory, model, c); + + 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()) { @@ -146,11 +156,16 @@ } org.apache.openjpa.kernel.exps.Expression expr = CriteriaExpressionBuilder.and(factory, join, filter); - if (correlatedParent == null) { + if (correlatedParentPath == null) { return expr; } else { - org.apache.openjpa.kernel.exps.Path parentPath = (org.apache.openjpa.kernel.exps.Path) - correlatedParent.toValue(factory, model, c); + org.apache.openjpa.kernel.exps.Path parentPath = null; + if (corrJoins != null && corrJoins.contains(_parent)) { + Value var = getVariableForCorrPath(subquery, correlatedParentPath); + parentPath = factory.newPath(var); + } else + parentPath = (org.apache.openjpa.kernel.exps.Path) + correlatedParentPath.toValue(factory, model, c); parentPath.get(_member.fmd, allowNull); //parentPath.setSchemaAlias(c.getAlias(correlatedParent)); path.setMetaData(meta); @@ -159,6 +174,18 @@ return CriteriaExpressionBuilder.and(factory, expr, filter); } } + + private Value getVariableForCorrPath(SubqueryImpl subquery, PathImpl path) { + AbstractQuery parent = subquery.getParent(); + if (parent instanceof CriteriaQueryImpl) { + return ((CriteriaQueryImpl)parent).getVariable(path); + } + Value var = ((SubqueryImpl)parent).getDelegate().getVariable(path); + if (var != null) + return var; + return getVariableForCorrPath((SubqueryImpl)parent, path); + } + } /** @@ -214,7 +241,6 @@ @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl c) { - ClassMetaData meta = getMemberClassMetaData(); org.apache.openjpa.kernel.exps.Path path = null; SubqueryImpl subquery = c.getDelegator(); PathImpl parent = getInnermostParentPath(); @@ -245,34 +271,40 @@ ClassMetaData meta = getMemberClassMetaData(); org.apache.openjpa.kernel.exps.Path path = null; SubqueryImpl subquery = c.getDelegator(); - PathImpl parent = getInnermostParentPath(); org.apache.openjpa.kernel.exps.Expression filter = null; - PathImpl correlatedParent = null; + java.util.List> corrJoins = 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); - path.get(_member.fmd, false); - } else { - path = (org.apache.openjpa.kernel.exps.Path)toValue(factory, model, c); - } 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); + PathImpl corrJoin = getCorrelatedJoin(this); + PathImpl corrRoot = getCorrelatedRoot(subquery); + + PathImpl correlatedParentPath = null; + if (_correlatedPath == null) { + if (subquery != null) { + corrJoins = subquery.getCorrelatedJoins(); + org.apache.openjpa.kernel.exps.Subquery subQ = subquery.getSubQ(); + path = factory.newPath(subQ); + if (corrJoin != null || corrRoot != null) { + correlatedParentPath = _parent.getCorrelatedPath(); + bind = false; + } else { + path.setMetaData(subQ.getMetaData()); + path.get(_member.fmd, allowNull); + //path.setSchemaAlias(c.getAlias(_parent)); + } + } else if (c.isRegistered(_parent)) { + Value var = c.getVariable(_parent); + path = factory.newPath(var); + path.setMetaData(meta); + path.get(_member.fmd, false); + } else + path = (org.apache.openjpa.kernel.exps.Path)toValue(factory, model, c); + + 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()) { @@ -281,19 +313,36 @@ } } org.apache.openjpa.kernel.exps.Expression expr = CriteriaExpressionBuilder.and(factory, join, filter); - if (correlatedParent == null) { + if (correlatedParentPath == null) { return expr; } else { - org.apache.openjpa.kernel.exps.Path parentPath = (org.apache.openjpa.kernel.exps.Path) - correlatedParent.toValue(factory, model, c); + org.apache.openjpa.kernel.exps.Path parentPath = null; + if (corrJoins != null && corrJoins.contains(_parent)) { + Value var = getVariableForCorrPath(subquery, correlatedParentPath); + parentPath = factory.newPath(var); + } else + parentPath = (org.apache.openjpa.kernel.exps.Path) + correlatedParentPath.toValue(factory, model, c); + parentPath.get(_member.fmd, allowNull); - //parentPath.setSchemaAlias(c.getAlias(correlatedParent)); + //parentPath.setSchemaAlias(c.getAlias(correlatedParentPath)); path.setMetaData(meta); //filter = bindVariableForKeyPath(path, alias, filter); filter = factory.equal(parentPath, path); return CriteriaExpressionBuilder.and(factory, expr, filter); } } + + private Value getVariableForCorrPath(SubqueryImpl subquery, PathImpl path) { + AbstractQuery parent = subquery.getParent(); + if (parent instanceof CriteriaQueryImpl) { + return ((CriteriaQueryImpl)parent).getVariable(path); + } + Value var = ((SubqueryImpl)parent).getDelegate().getVariable(path); + if (var != null) + return var; + return getVariableForCorrPath((SubqueryImpl)parent, path); + } } /** 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=788604&r1=788603&r2=788604&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 Fri Jun 26 06:34:34 2009 @@ -56,8 +56,8 @@ protected final PathImpl _parent; protected final Members.Member _member; private boolean isEmbedded = false; - private PathImpl _correlatedParent; - + protected PathImpl _correlatedPath; + /** * Protected. use by root path which neither represent a member nor has a * parent. @@ -119,12 +119,11 @@ parent._member); } - public void setCorrelatedParent(PathImpl correlatedParent) { - _correlatedParent = correlatedParent; + public void setCorrelatedPath(PathImpl correlatedPath) { + _correlatedPath = correlatedPath; } - - public PathImpl getCorrelatedParent() { - return _correlatedParent; + public PathImpl getCorrelatedPath() { + return _correlatedPath; } /** @@ -137,15 +136,15 @@ return q.getValue(this); org.apache.openjpa.kernel.exps.Path path = null; SubqueryImpl subquery = q.getDelegator(); - PathImpl parent = getInnermostParentPath(); boolean allowNull = _parent == null ? false : _parent instanceof Join && ((Join)_parent).getJoinType() != JoinType.INNER; - + PathImpl corrJoin = getCorrelatedJoin(this); + PathImpl corrRoot = getCorrelatedRoot(subquery); 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)) { + } else if (corrJoin != null || corrRoot != null) { org.apache.openjpa.kernel.exps.Subquery subQ = subquery.getSubQ(); path = factory.newPath(subQ); path.setMetaData(subQ.getMetaData()); @@ -166,11 +165,29 @@ return path; } + public PathImpl getCorrelatedRoot(SubqueryImpl subquery) { + if (subquery == null) + return null; + PathImpl root = getInnermostParentPath(); + if (subquery.getRoots() != null && subquery.getRoots().contains(this)) + return root; + return null; + } + + + public PathImpl getCorrelatedJoin(PathImpl path) { + if (path._correlatedPath != null) + return path._correlatedPath; + if (path._parent == null) + return null; + return getCorrelatedJoin(path._parent); + } + /** * Affirms if this receiver occurs in the roots of the given subquery. */ public boolean inSubquery(SubqueryImpl subquery) { - return subquery != null && subquery.getRoots().contains(this); + return subquery != null && (subquery.getRoots() == null ? false : subquery.getRoots().contains(this)); } protected void traversePath(PathImpl parent, org.apache.openjpa.kernel.exps.Path path, FieldMetaData fmd) { @@ -178,7 +195,7 @@ && ((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 (parent1 == null || parent1.getCorrelatedPath() != null) { if (fmd != null) path.get(fmd, allowNull); return; 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=788604&r1=788603&r2=788604&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 Fri Jun 26 06:34:34 2009 @@ -50,7 +50,7 @@ } public void addToContext(ExpressionFactory factory, MetamodelImpl model, - CriteriaQueryImpl q) { + CriteriaQueryImpl q) { String alias = q.getAlias(this); Value var = factory.newBoundVariable(alias, AbstractExpressionBuilder.TYPE_OBJECT); @@ -71,11 +71,13 @@ CriteriaQueryImpl c) { SubqueryImpl subquery = c.getDelegator(); Path var = null; + //String alias = c.getAlias(this); if (inSubquery(subquery)) { Subquery subQ = subquery.getSubQ(); var = factory.newPath(subQ); } else { var = factory.newPath(); + //var.setSchemaAlias(alias); } var.setMetaData(_entity.meta); return var; 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=788604&r1=788603&r2=788604&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 Fri Jun 26 06:34:34 2009 @@ -18,6 +18,7 @@ */ package org.apache.openjpa.persistence.criteria; +import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -26,6 +27,7 @@ import javax.persistence.criteria.CollectionJoin; import javax.persistence.criteria.Expression; import javax.persistence.criteria.Join; +import javax.persistence.criteria.JoinType; import javax.persistence.criteria.ListJoin; import javax.persistence.criteria.MapJoin; import javax.persistence.criteria.Predicate; @@ -62,6 +64,7 @@ private java.util.Set> _joins; private Expression _select; private org.apache.openjpa.kernel.exps.Subquery _subq; + private List> _corrJoins = null; public SubqueryImpl(Class cls, AbstractQuery parent) { super(cls); @@ -176,7 +179,7 @@ public Root correlate(Root root) { Types.Entity entity = (Types.Entity)root.getModel(); RootImpl corrRoot = new RootImpl(entity); - corrRoot.setCorrelatedParent((RootImpl)root); + corrRoot.setCorrelatedPath((RootImpl)root); Set> roots = getRoots(); if (roots == null) { roots = new LinkedHashSet>(); @@ -186,9 +189,54 @@ return corrRoot; } + public List> getCorrelatedJoins() { + return _corrJoins; + } + public Join correlate(Join join) { - _delegate.from(join.getModel().getBindableJavaType()); - return join; + Join corrJoin = clone(join); + ((PathImpl)corrJoin).setCorrelatedPath((PathImpl)join); + if (_corrJoins == null) + _corrJoins = new ArrayList>(); + _corrJoins.add(corrJoin); + return corrJoin; + } + + private Join clone(Join join) { + List> members = + new ArrayList>(); + List jts = new ArrayList(); + FromImpl root = getMembers(join, members, jts); + Members.SingularAttributeImpl member = members.get(0); + JoinType jt = jts.get(0); + Join join1 = makeJoin(root, member, jt); + for (int i = 1; i < members.size(); i++) { + join1 = makeJoin((FromImpl)join1, members.get(i), jts.get(i)); + } + return join1; + } + + private Join makeJoin(FromImpl parent, Members.SingularAttributeImpl member, JoinType jt) { + return new Joins.SingularJoin(parent, member, jt); + } + + private FromImpl getMembers(Join join, List> members, + List jts) { + PathImpl parent = (PathImpl)join.getParentPath(); + Members.SingularAttributeImpl member = + (Members.SingularAttributeImpl)((Joins.SingularJoin)join).getMember(); + JoinType jt = join.getJoinType(); + FromImpl root = null; + if (parent instanceof RootImpl) { + members.add(member); + jts.add(jt); + return (FromImpl)parent; + } else { + root = getMembers((Join)parent, members, jts); + } + members.add(member); + jts.add(jt); + return root; } public CollectionJoin correlate(CollectionJoin join) { _delegate.from(join.getModel().getBindableJavaType()); @@ -225,7 +273,7 @@ public Value toValue(ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl q) { final boolean subclasses = true; - CriteriaExpressionBuilder queryEval = new CriteriaExpressionBuilder(); + CriteriaExpressionBuilder exprBuilder = new CriteriaExpressionBuilder(); String alias = q.getAlias(this); ClassMetaData candidate = getCandidate(); _subq = factory.newSubquery(candidate, subclasses, alias); @@ -235,7 +283,7 @@ //Context context = new Context(null, _subq, contexts.peek()); //contexts.push(context); //_delegate.setContexts(contexts); - QueryExpressions subexp = queryEval.getQueryExpressions(factory, + QueryExpressions subexp = exprBuilder.getQueryExpressions(factory, _delegate); _subq.setQueryExpressions(subexp); if (subexp.projections.length > 0) @@ -248,18 +296,42 @@ // correlated parent, the candidate of the subquery // should be the class metadata of the collection element private ClassMetaData getCandidate() { + if (_delegate.getRoots() == null && _corrJoins != null) { + FromImpl corrJoin = (FromImpl) _corrJoins.get(0); + if (corrJoin.getJoins() != null) { + FromImpl join = (FromImpl)corrJoin.getJoins().iterator().next(); + return getInnermostCandidate(join); + } + } + RootImpl root = (RootImpl)getRoot(); - PathImpl correlatedRoot = root.getCorrelatedParent(); - if (correlatedRoot != null && root.getJoins() != null) { - Join join = root.getJoins().iterator().next(); - FieldMetaData fmd = ((Members.Member)join.getAttribute()).fmd; - if (join.getAttribute().isCollection()) { - return fmd.isElementCollection() ? fmd.getEmbeddedMetaData(): fmd.getElement().getDeclaredTypeMetaData(); - } else { - return fmd.getDeclaredTypeMetaData(); - } + RootImpl corrRoot = (RootImpl)root.getCorrelatedPath(); + if (corrRoot != null && root.getJoins() != null) { + FromImpl join = (FromImpl) root.getJoins().iterator().next(); + return getInnermostCandidate(join); } + return ((AbstractManagedType)root.getModel()).meta; } + private ClassMetaData getInnermostCandidate(FromImpl from) { + if (from.getJoins() != null) { + from = (FromImpl) from.getJoins().iterator().next(); + return getInnermostCandidate(from); + } + return getCandidate(from); + } + + + private ClassMetaData getCandidate(FromImpl from) { + if (from._member.fmd.getDeclaredTypeCode() == + JavaTypes.COLLECTION || + from._member.fmd.getDeclaredTypeCode() == + JavaTypes.MAP) + return from._member.fmd.isElementCollection() + ? from._member.fmd.getEmbeddedMetaData() + : from._member.fmd.getElement().getDeclaredTypeMetaData(); + return from._member.fmd.getDeclaredTypeMetaData(); + + } }