OPENJPA-1143: correlation join support

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@788604 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Fay Wang 2009-06-26 06:34:34 +00:00
parent 3f15ecde4d
commit 291f314242
5 changed files with 270 additions and 122 deletions

View File

@ -49,8 +49,7 @@ import org.apache.openjpa.persistence.meta.MetamodelImpl;
*/ */
public class CriteriaExpressionBuilder { public class CriteriaExpressionBuilder {
public QueryExpressions getQueryExpressions(ExpressionFactory factory, public QueryExpressions getQueryExpressions(ExpressionFactory factory, CriteriaQueryImpl<?> q) {
CriteriaQueryImpl q) {
QueryExpressions exps = new QueryExpressions(); QueryExpressions exps = new QueryExpressions();
//exps.setContexts(q.getContexts()); //exps.setContexts(q.getContexts());
@ -76,8 +75,7 @@ public class CriteriaExpressionBuilder {
return exps; return exps;
} }
protected void evalAccessPaths(QueryExpressions exps, protected void evalAccessPaths(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl<?> q) {
ExpressionFactory factory, CriteriaQueryImpl q) {
Set<ClassMetaData> metas = new HashSet<ClassMetaData>(); Set<ClassMetaData> metas = new HashSet<ClassMetaData>();
Set<Root<?>> roots = q.getRoots(); Set<Root<?>> roots = q.getRoots();
if (roots != null) { if (roots != null) {
@ -88,17 +86,14 @@ public class CriteriaExpressionBuilder {
for (Join<?,?> join : root.getJoins()) { for (Join<?,?> join : root.getJoins()) {
Class<?> cls = join.getAttribute().getJavaType(); Class<?> cls = join.getAttribute().getJavaType();
if (join.getAttribute().isAssociation()) { if (join.getAttribute().isAssociation()) {
ClassMetaData meta = metamodel.repos. ClassMetaData meta = metamodel.repos.getMetaData(cls, null, true);
getMetaData(cls, null, true); PersistenceType type = metamodel.getPersistenceType(meta);
PersistenceType type = metamodel. if (type == PersistenceType.ENTITY || type == PersistenceType.EMBEDDABLE)
getPersistenceType(meta);
if (type == PersistenceType.ENTITY ||
type == PersistenceType.EMBEDDABLE)
metas.add(meta); metas.add(meta);
} }
} }
if (root.getFetches() != null) { if (root.getFetches() != null) {
for (Fetch fetch : root.getFetches()) { for (Fetch<?,?> fetch : root.getFetches()) {
metas.add(metamodel.repos.getMetaData( metas.add(metamodel.repos.getMetaData(
fetch.getAttribute().getJavaType(), fetch.getAttribute().getJavaType(),
null, false)); null, false));
@ -110,8 +105,7 @@ public class CriteriaExpressionBuilder {
exps.accessPath = metas.toArray(new ClassMetaData[metas.size()]); exps.accessPath = metas.toArray(new ClassMetaData[metas.size()]);
} }
protected void evalOrdering(QueryExpressions exps, protected void evalOrdering(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl<?> q) {
ExpressionFactory factory, CriteriaQueryImpl q) {
List<Order> orders = q.getOrderList(); List<Order> orders = q.getOrderList();
MetamodelImpl model = q.getMetamodel(); MetamodelImpl model = q.getMetamodel();
if (orders == null) if (orders == null)
@ -124,7 +118,7 @@ public class CriteriaExpressionBuilder {
for (int i = 0; i < ordercount; i++) { for (int i = 0; i < ordercount; i++) {
OrderImpl order = (OrderImpl)orders.get(i); OrderImpl order = (OrderImpl)orders.get(i);
//Expression<? extends Comparable> expr = order.getExpression(); //Expression<? extends Comparable> expr = order.getExpression();
Expression expr = order.getExpression5(); Expression<?> expr = order.getExpression5();
exps.ordering[i] = Expressions.toValue( exps.ordering[i] = Expressions.toValue(
(ExpressionImpl<?>)expr, factory, model, q); (ExpressionImpl<?>)expr, factory, model, q);
@ -134,8 +128,7 @@ public class CriteriaExpressionBuilder {
} }
} }
protected void evalGrouping(QueryExpressions exps, protected void evalGrouping(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl<?> q) {
ExpressionFactory factory, CriteriaQueryImpl q) {
// exps.grouping = null; // Value[] // exps.grouping = null; // Value[]
// exps.groupingClauses = null; // String[] // exps.groupingClauses = null; // String[]
List<Expression<?>> groups = q.getGroupList(); List<Expression<?>> groups = q.getGroupList();
@ -155,8 +148,7 @@ public class CriteriaExpressionBuilder {
: having.toKernelExpression(factory, model, q); : having.toKernelExpression(factory, model, q);
} }
protected void evalDistinct(QueryExpressions exps, protected void evalDistinct(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl<?> q) {
ExpressionFactory factory, CriteriaQueryImpl q) {
Boolean distinct = q.getDistinct(); Boolean distinct = q.getDistinct();
if (distinct == null) { if (distinct == null) {
exps.distinct = QueryExpressions.DISTINCT_FALSE; exps.distinct = QueryExpressions.DISTINCT_FALSE;
@ -167,13 +159,14 @@ public class CriteriaExpressionBuilder {
//exps.distinct &= ~QueryExpressions.DISTINCT_AUTO; //exps.distinct &= ~QueryExpressions.DISTINCT_AUTO;
} }
protected void evalFilter(QueryExpressions exps, ExpressionFactory factory, protected void evalFilter(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl<?> q) {
CriteriaQueryImpl q) {
Set<Root<?>> roots = q.getRoots(); Set<Root<?>> roots = q.getRoots();
MetamodelImpl model = q.getMetamodel(); MetamodelImpl model = q.getMetamodel();
PredicateImpl where = q.getRestriction(); PredicateImpl where = q.getRestriction();
q.assertRoot(); SubqueryImpl<?> subQuery = q.getDelegator();
org.apache.openjpa.kernel.exps.Expression filter = null; org.apache.openjpa.kernel.exps.Expression filter = null;
if (subQuery == null || subQuery.getCorrelatedJoins() == null) {
q.assertRoot();
for (Root<?> root : roots) { for (Root<?> root : roots) {
if (root.getJoins() != null) { if (root.getJoins() != null) {
for (Join<?, ?> join : root.getJoins()) { for (Join<?, ?> join : root.getJoins()) {
@ -181,8 +174,18 @@ public class CriteriaExpressionBuilder {
.toKernelExpression(factory, model, q), filter); .toKernelExpression(factory, model, q), filter);
} }
} }
((RootImpl)root).addToContext(factory, model, q); ((RootImpl<?>)root).addToContext(factory, model, q);
} }
}
if (subQuery != null) {
List<Join<?,?>> 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);
}
}
if (where != null) { if (where != null) {
filter = and(factory, where.toKernelExpression filter = and(factory, where.toKernelExpression
(factory, model, q), filter); (factory, model, q), filter);
@ -192,8 +195,7 @@ public class CriteriaExpressionBuilder {
exps.filter = filter; exps.filter = filter;
} }
protected void evalProjections(QueryExpressions exps, protected void evalProjections(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl<?> q) {
ExpressionFactory factory, CriteriaQueryImpl q) {
List<Selection<?>> selections = q.getSelectionList(); List<Selection<?>> selections = q.getSelectionList();
MetamodelImpl model = q.getMetamodel(); MetamodelImpl model = q.getMetamodel();
// TODO: fill in projection clauses // TODO: fill in projection clauses
@ -212,8 +214,8 @@ public class CriteriaExpressionBuilder {
} }
private void getProjections(QueryExpressions exps, private void getProjections(QueryExpressions exps,
List<Selection<?>> selections, List projections, List aliases, List<Selection<?>> selections, List projections, List<String> aliases,
ExpressionFactory factory, CriteriaQueryImpl q, MetamodelImpl model) { ExpressionFactory factory, CriteriaQueryImpl<?> q, MetamodelImpl model) {
for (Selection<?> s : selections) { for (Selection<?> s : selections) {
List<Selection<?>> sels = ((SelectionImpl)s).getSelections(); List<Selection<?>> sels = ((SelectionImpl)s).getSelections();
if (sels == null) { if (sels == null) {
@ -229,14 +231,20 @@ public class CriteriaExpressionBuilder {
} }
} }
protected boolean isDefaultProjection(List<Selection<?>> selections, protected boolean isDefaultProjection(List<Selection<?>> selections, CriteriaQueryImpl<?> q) {
CriteriaQueryImpl q) { if (selections == null)
return selections == null return true;
|| (selections.size() == 1 && selections.get(0) == q.getRoot()); 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, protected void evalFetchJoin(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl<?> q) {
ExpressionFactory factory, CriteriaQueryImpl q) {
List<String> iPaths = new ArrayList<String>(); List<String> iPaths = new ArrayList<String>();
List<String> oPaths = new ArrayList<String>(); List<String> oPaths = new ArrayList<String>();
Set<Root<?>> roots = q.getRoots(); Set<Root<?>> roots = q.getRoots();

View File

@ -18,6 +18,7 @@
*/ */
package org.apache.openjpa.persistence.criteria; package org.apache.openjpa.persistence.criteria;
import javax.persistence.criteria.AbstractQuery;
import javax.persistence.criteria.CollectionJoin; import javax.persistence.criteria.CollectionJoin;
import javax.persistence.criteria.Expression; import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Join; import javax.persistence.criteria.Join;
@ -73,6 +74,10 @@ public abstract class Joins {
return (FromImpl<?, Z>) _parent; return (FromImpl<?, Z>) _parent;
} }
public Member<? extends Z, X> getMember() {
return (Member<? extends Z, X>) _member;
}
/** /**
* Return the metamodel attribute corresponding to the join. * Return the metamodel attribute corresponding to the join.
* @return metamodel attribute type corresponding to the join * @return metamodel attribute type corresponding to the join
@ -111,33 +116,38 @@ public abstract class Joins {
SubqueryImpl<?> subquery = c.getDelegator(); SubqueryImpl<?> subquery = c.getDelegator();
PathImpl<?,?> parent = getInnermostParentPath(); PathImpl<?,?> parent = getInnermostParentPath();
org.apache.openjpa.kernel.exps.Expression filter = null; org.apache.openjpa.kernel.exps.Expression filter = null;
PathImpl<?,?> correlatedParent = null; PathImpl<?,?> correlatedParentPath = null;
boolean bind = true; boolean bind = true;
if (parent.inSubquery(subquery)) { java.util.List<Join<?,?>> corrJoins = null;
org.apache.openjpa.kernel.exps.Expression join = null;
if (_correlatedPath == null) {
if (subquery != null) {
corrJoins = subquery.getCorrelatedJoins();
org.apache.openjpa.kernel.exps.Subquery subQ = subquery.getSubQ(); org.apache.openjpa.kernel.exps.Subquery subQ = subquery.getSubQ();
path = factory.newPath(subQ); path = factory.newPath(subQ);
correlatedParent = _parent.getCorrelatedParent(); if ((corrJoins != null && corrJoins.contains(_parent)) ||
if (correlatedParent == null) { (corrJoins == null && parent.inSubquery(subquery))) {
correlatedParentPath = _parent.getCorrelatedPath();
bind = false;
} else {
path.setMetaData(subQ.getMetaData()); path.setMetaData(subQ.getMetaData());
path.get(_member.fmd, allowNull); path.get(_member.fmd, allowNull);
//path.setSchemaAlias(c.getAlias(_parent)); //path.setSchemaAlias(c.getAlias(_parent));
} else {
bind = false;
} }
} else if (c.isRegistered(_parent)) { } else if (c.isRegistered(_parent)) {
Value var = c.getVariable(_parent); Value var = c.getVariable(_parent);
path = factory.newPath(var); path = factory.newPath(var);
path.setMetaData(meta); path.setMetaData(meta);
path.get(_member.fmd, false); path.get(_member.fmd, false);
} else { } else
path = (org.apache.openjpa.kernel.exps.Path)toValue(factory, model, c); path = (org.apache.openjpa.kernel.exps.Path)toValue(factory, model, c);
}
org.apache.openjpa.kernel.exps.Expression join = null;
if (bind) { if (bind) {
Value var = factory.newBoundVariable(c.getAlias(this), meta.getDescribedType()); Value var = factory.newBoundVariable(c.getAlias(this), meta.getDescribedType());
join = factory.bindVariable(var, path); join = factory.bindVariable(var, path);
c.registerVariable(this, var, path); c.registerVariable(this, var, path);
} }
}
if (getJoins() != null) { if (getJoins() != null) {
for (Join<?, ?> join1 : getJoins()) { for (Join<?, ?> join1 : getJoins()) {
filter = CriteriaExpressionBuilder.and(factory, filter = CriteriaExpressionBuilder.and(factory,
@ -146,11 +156,16 @@ public abstract class Joins {
} }
org.apache.openjpa.kernel.exps.Expression expr = CriteriaExpressionBuilder.and(factory, join, filter); org.apache.openjpa.kernel.exps.Expression expr = CriteriaExpressionBuilder.and(factory, join, filter);
if (correlatedParent == null) { if (correlatedParentPath == null) {
return expr; return expr;
} else { } else {
org.apache.openjpa.kernel.exps.Path parentPath = (org.apache.openjpa.kernel.exps.Path) org.apache.openjpa.kernel.exps.Path parentPath = null;
correlatedParent.toValue(factory, model, c); 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.get(_member.fmd, allowNull);
//parentPath.setSchemaAlias(c.getAlias(correlatedParent)); //parentPath.setSchemaAlias(c.getAlias(correlatedParent));
path.setMetaData(meta); path.setMetaData(meta);
@ -159,6 +174,18 @@ public abstract class Joins {
return CriteriaExpressionBuilder.and(factory, expr, filter); 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 @@ public abstract class Joins {
@Override @Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model, public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQueryImpl<?> c) { CriteriaQueryImpl<?> c) {
ClassMetaData meta = getMemberClassMetaData();
org.apache.openjpa.kernel.exps.Path path = null; org.apache.openjpa.kernel.exps.Path path = null;
SubqueryImpl<?> subquery = c.getDelegator(); SubqueryImpl<?> subquery = c.getDelegator();
PathImpl<?,?> parent = getInnermostParentPath(); PathImpl<?,?> parent = getInnermostParentPath();
@ -245,35 +271,41 @@ public abstract class Joins {
ClassMetaData meta = getMemberClassMetaData(); ClassMetaData meta = getMemberClassMetaData();
org.apache.openjpa.kernel.exps.Path path = null; org.apache.openjpa.kernel.exps.Path path = null;
SubqueryImpl<?> subquery = c.getDelegator(); SubqueryImpl<?> subquery = c.getDelegator();
PathImpl<?,?> parent = getInnermostParentPath();
org.apache.openjpa.kernel.exps.Expression filter = null; org.apache.openjpa.kernel.exps.Expression filter = null;
PathImpl correlatedParent = null; java.util.List<Join<?,?>> corrJoins = null;
boolean bind = true; boolean bind = true;
if (parent.inSubquery(subquery)) { org.apache.openjpa.kernel.exps.Expression join = null;
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(); org.apache.openjpa.kernel.exps.Subquery subQ = subquery.getSubQ();
path = factory.newPath(subQ); path = factory.newPath(subQ);
correlatedParent = _parent.getCorrelatedParent(); if (corrJoin != null || corrRoot != null) {
if (correlatedParent == null) { correlatedParentPath = _parent.getCorrelatedPath();
bind = false;
} else {
path.setMetaData(subQ.getMetaData()); path.setMetaData(subQ.getMetaData());
path.get(_member.fmd, allowNull); path.get(_member.fmd, allowNull);
//path.setSchemaAlias(c.getAlias(_parent)); //path.setSchemaAlias(c.getAlias(_parent));
} else {
bind = false;
} }
} else if (c.isRegistered(_parent)) { } else if (c.isRegistered(_parent)) {
Value var = c.getVariable(_parent); Value var = c.getVariable(_parent);
path = factory.newPath(var); path = factory.newPath(var);
path.setMetaData(meta); path.setMetaData(meta);
path.get(_member.fmd, false); path.get(_member.fmd, false);
} else { } else
path = (org.apache.openjpa.kernel.exps.Path)toValue(factory, model, c); path = (org.apache.openjpa.kernel.exps.Path)toValue(factory, model, c);
}
org.apache.openjpa.kernel.exps.Expression join = null;
if (bind) { if (bind) {
Value var = factory.newBoundVariable(c.getAlias(this), meta.getDescribedType()); Value var = factory.newBoundVariable(c.getAlias(this), meta.getDescribedType());
join = factory.bindVariable(var, path); join = factory.bindVariable(var, path);
c.registerVariable(this, var, path); c.registerVariable(this, var, path);
} }
}
if (getJoins() != null) { if (getJoins() != null) {
for (Join<?, ?> join1 : getJoins()) { for (Join<?, ?> join1 : getJoins()) {
filter = CriteriaExpressionBuilder.and(factory, filter = CriteriaExpressionBuilder.and(factory,
@ -281,19 +313,36 @@ public abstract class Joins {
} }
} }
org.apache.openjpa.kernel.exps.Expression expr = CriteriaExpressionBuilder.and(factory, join, filter); org.apache.openjpa.kernel.exps.Expression expr = CriteriaExpressionBuilder.and(factory, join, filter);
if (correlatedParent == null) { if (correlatedParentPath == null) {
return expr; return expr;
} else { } else {
org.apache.openjpa.kernel.exps.Path parentPath = (org.apache.openjpa.kernel.exps.Path) org.apache.openjpa.kernel.exps.Path parentPath = null;
correlatedParent.toValue(factory, model, c); 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.get(_member.fmd, allowNull);
//parentPath.setSchemaAlias(c.getAlias(correlatedParent)); //parentPath.setSchemaAlias(c.getAlias(correlatedParentPath));
path.setMetaData(meta); path.setMetaData(meta);
//filter = bindVariableForKeyPath(path, alias, filter); //filter = bindVariableForKeyPath(path, alias, filter);
filter = factory.equal(parentPath, path); filter = factory.equal(parentPath, path);
return CriteriaExpressionBuilder.and(factory, expr, filter); 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);
}
} }
/** /**

View File

@ -56,7 +56,7 @@ public class PathImpl<Z,X> extends ExpressionImpl<X> implements Path<X> {
protected final PathImpl<?,Z> _parent; protected final PathImpl<?,Z> _parent;
protected final Members.Member<? super Z,?> _member; protected final Members.Member<? super Z,?> _member;
private boolean isEmbedded = false; private boolean isEmbedded = false;
private PathImpl<?,?> _correlatedParent; protected PathImpl<?,?> _correlatedPath;
/** /**
* Protected. use by root path which neither represent a member nor has a * Protected. use by root path which neither represent a member nor has a
@ -119,12 +119,11 @@ public class PathImpl<Z,X> extends ExpressionImpl<X> implements Path<X> {
parent._member); parent._member);
} }
public void setCorrelatedParent(PathImpl<?,?> correlatedParent) { public void setCorrelatedPath(PathImpl<?,?> correlatedPath) {
_correlatedParent = correlatedParent; _correlatedPath = correlatedPath;
} }
public PathImpl<?,?> getCorrelatedPath() {
public PathImpl<?,?> getCorrelatedParent() { return _correlatedPath;
return _correlatedParent;
} }
/** /**
@ -137,15 +136,15 @@ public class PathImpl<Z,X> extends ExpressionImpl<X> implements Path<X> {
return q.getValue(this); return q.getValue(this);
org.apache.openjpa.kernel.exps.Path path = null; org.apache.openjpa.kernel.exps.Path path = null;
SubqueryImpl<?> subquery = q.getDelegator(); SubqueryImpl<?> subquery = q.getDelegator();
PathImpl<?,?> parent = getInnermostParentPath();
boolean allowNull = _parent == null ? false : _parent instanceof Join boolean allowNull = _parent == null ? false : _parent instanceof Join
&& ((Join<?,?>)_parent).getJoinType() != JoinType.INNER; && ((Join<?,?>)_parent).getJoinType() != JoinType.INNER;
PathImpl<?,?> corrJoin = getCorrelatedJoin(this);
PathImpl<?,?> corrRoot = getCorrelatedRoot(subquery);
if (_parent != null && q.isRegistered(_parent)) { if (_parent != null && q.isRegistered(_parent)) {
path = factory.newPath(q.getVariable(_parent)); path = factory.newPath(q.getVariable(_parent));
//path.setSchemaAlias(q.getAlias(_parent)); //path.setSchemaAlias(q.getAlias(_parent));
path.get(_member.fmd, allowNull); 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(); org.apache.openjpa.kernel.exps.Subquery subQ = subquery.getSubQ();
path = factory.newPath(subQ); path = factory.newPath(subQ);
path.setMetaData(subQ.getMetaData()); path.setMetaData(subQ.getMetaData());
@ -166,11 +165,29 @@ public class PathImpl<Z,X> extends ExpressionImpl<X> implements Path<X> {
return path; 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. * Affirms if this receiver occurs in the roots of the given subquery.
*/ */
public boolean inSubquery(SubqueryImpl<?> 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) { protected void traversePath(PathImpl<?,?> parent, org.apache.openjpa.kernel.exps.Path path, FieldMetaData fmd) {
@ -178,7 +195,7 @@ public class PathImpl<Z,X> extends ExpressionImpl<X> implements Path<X> {
&& ((Join<?,?>)parent).getJoinType() != JoinType.INNER; && ((Join<?,?>)parent).getJoinType() != JoinType.INNER;
FieldMetaData fmd1 = parent._member == null ? null : parent._member.fmd; FieldMetaData fmd1 = parent._member == null ? null : parent._member.fmd;
PathImpl<?,?> parent1 = parent._parent; PathImpl<?,?> parent1 = parent._parent;
if (parent1 == null || parent1.getCorrelatedParent() != null) { if (parent1 == null || parent1.getCorrelatedPath() != null) {
if (fmd != null) if (fmd != null)
path.get(fmd, allowNull); path.get(fmd, allowNull);
return; return;

View File

@ -50,7 +50,7 @@ public class RootImpl<X> extends FromImpl<X,X> implements Root<X> {
} }
public void addToContext(ExpressionFactory factory, MetamodelImpl model, public void addToContext(ExpressionFactory factory, MetamodelImpl model,
CriteriaQueryImpl q) { CriteriaQueryImpl<?> q) {
String alias = q.getAlias(this); String alias = q.getAlias(this);
Value var = factory.newBoundVariable(alias, Value var = factory.newBoundVariable(alias,
AbstractExpressionBuilder.TYPE_OBJECT); AbstractExpressionBuilder.TYPE_OBJECT);
@ -71,11 +71,13 @@ public class RootImpl<X> extends FromImpl<X,X> implements Root<X> {
CriteriaQueryImpl<?> c) { CriteriaQueryImpl<?> c) {
SubqueryImpl<?> subquery = c.getDelegator(); SubqueryImpl<?> subquery = c.getDelegator();
Path var = null; Path var = null;
//String alias = c.getAlias(this);
if (inSubquery(subquery)) { if (inSubquery(subquery)) {
Subquery subQ = subquery.getSubQ(); Subquery subQ = subquery.getSubQ();
var = factory.newPath(subQ); var = factory.newPath(subQ);
} else { } else {
var = factory.newPath(); var = factory.newPath();
//var.setSchemaAlias(alias);
} }
var.setMetaData(_entity.meta); var.setMetaData(_entity.meta);
return var; return var;

View File

@ -18,6 +18,7 @@
*/ */
package org.apache.openjpa.persistence.criteria; package org.apache.openjpa.persistence.criteria;
import java.util.ArrayList;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -26,6 +27,7 @@ import javax.persistence.criteria.AbstractQuery;
import javax.persistence.criteria.CollectionJoin; import javax.persistence.criteria.CollectionJoin;
import javax.persistence.criteria.Expression; import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Join; import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.ListJoin; import javax.persistence.criteria.ListJoin;
import javax.persistence.criteria.MapJoin; import javax.persistence.criteria.MapJoin;
import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Predicate;
@ -62,6 +64,7 @@ public class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
private java.util.Set<Join<?,?>> _joins; private java.util.Set<Join<?,?>> _joins;
private Expression<T> _select; private Expression<T> _select;
private org.apache.openjpa.kernel.exps.Subquery _subq; private org.apache.openjpa.kernel.exps.Subquery _subq;
private List<Join<?,?>> _corrJoins = null;
public SubqueryImpl(Class<T> cls, AbstractQuery<?> parent) { public SubqueryImpl(Class<T> cls, AbstractQuery<?> parent) {
super(cls); super(cls);
@ -176,7 +179,7 @@ public class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
public <Y> Root<Y> correlate(Root<Y> root) { public <Y> Root<Y> correlate(Root<Y> root) {
Types.Entity<Y> entity = (Types.Entity<Y>)root.getModel(); Types.Entity<Y> entity = (Types.Entity<Y>)root.getModel();
RootImpl<Y> corrRoot = new RootImpl<Y>(entity); RootImpl<Y> corrRoot = new RootImpl<Y>(entity);
corrRoot.setCorrelatedParent((RootImpl<Y>)root); corrRoot.setCorrelatedPath((RootImpl<Y>)root);
Set<Root<?>> roots = getRoots(); Set<Root<?>> roots = getRoots();
if (roots == null) { if (roots == null) {
roots = new LinkedHashSet<Root<?>>(); roots = new LinkedHashSet<Root<?>>();
@ -186,9 +189,54 @@ public class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
return corrRoot; return corrRoot;
} }
public List<Join<?,?>> getCorrelatedJoins() {
return _corrJoins;
}
public <X,Y> Join<X,Y> correlate(Join<X,Y> join) { public <X,Y> Join<X,Y> correlate(Join<X,Y> join) {
_delegate.from(join.getModel().getBindableJavaType()); Join corrJoin = clone(join);
return join; ((PathImpl<?,?>)corrJoin).setCorrelatedPath((PathImpl<?,?>)join);
if (_corrJoins == null)
_corrJoins = new ArrayList<Join<?,?>>();
_corrJoins.add(corrJoin);
return corrJoin;
}
private Join<?,?> clone(Join<?,?> join) {
List<Members.SingularAttributeImpl<?,?>> members =
new ArrayList<Members.SingularAttributeImpl<?,?>>();
List<JoinType> jts = new ArrayList<JoinType>();
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.SingularAttributeImpl<?,?>> members,
List<JoinType> 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 <X,Y> CollectionJoin<X,Y> correlate(CollectionJoin<X,Y> join) { public <X,Y> CollectionJoin<X,Y> correlate(CollectionJoin<X,Y> join) {
_delegate.from(join.getModel().getBindableJavaType()); _delegate.from(join.getModel().getBindableJavaType());
@ -225,7 +273,7 @@ public class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
public Value toValue(ExpressionFactory factory, MetamodelImpl model, public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQueryImpl<?> q) { CriteriaQueryImpl<?> q) {
final boolean subclasses = true; final boolean subclasses = true;
CriteriaExpressionBuilder queryEval = new CriteriaExpressionBuilder(); CriteriaExpressionBuilder exprBuilder = new CriteriaExpressionBuilder();
String alias = q.getAlias(this); String alias = q.getAlias(this);
ClassMetaData candidate = getCandidate(); ClassMetaData candidate = getCandidate();
_subq = factory.newSubquery(candidate, subclasses, alias); _subq = factory.newSubquery(candidate, subclasses, alias);
@ -235,7 +283,7 @@ public class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
//Context context = new Context(null, _subq, contexts.peek()); //Context context = new Context(null, _subq, contexts.peek());
//contexts.push(context); //contexts.push(context);
//_delegate.setContexts(contexts); //_delegate.setContexts(contexts);
QueryExpressions subexp = queryEval.getQueryExpressions(factory, QueryExpressions subexp = exprBuilder.getQueryExpressions(factory,
_delegate); _delegate);
_subq.setQueryExpressions(subexp); _subq.setQueryExpressions(subexp);
if (subexp.projections.length > 0) if (subexp.projections.length > 0)
@ -248,18 +296,42 @@ public class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
// correlated parent, the candidate of the subquery // correlated parent, the candidate of the subquery
// should be the class metadata of the collection element // should be the class metadata of the collection element
private ClassMetaData getCandidate() { 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(); RootImpl<?> root = (RootImpl<?>)getRoot();
PathImpl<?, ?> correlatedRoot = root.getCorrelatedParent(); RootImpl<?> corrRoot = (RootImpl<?>)root.getCorrelatedPath();
if (correlatedRoot != null && root.getJoins() != null) { if (corrRoot != null && root.getJoins() != null) {
Join<?,?> join = root.getJoins().iterator().next(); FromImpl<?,?> join = (FromImpl<?,?>) root.getJoins().iterator().next();
FieldMetaData fmd = ((Members.Member<?, ?>)join.getAttribute()).fmd; return getInnermostCandidate(join);
if (join.getAttribute().isCollection()) {
return fmd.isElementCollection() ? fmd.getEmbeddedMetaData(): fmd.getElement().getDeclaredTypeMetaData();
} else {
return fmd.getDeclaredTypeMetaData();
}
} }
return ((AbstractManagedType<?>)root.getModel()).meta; 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();
}
} }