mirror of https://github.com/apache/openjpa.git
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:
parent
3f15ecde4d
commit
291f314242
|
@ -49,8 +49,7 @@ import org.apache.openjpa.persistence.meta.MetamodelImpl;
|
|||
*/
|
||||
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 @@ public class CriteriaExpressionBuilder {
|
|||
return exps;
|
||||
}
|
||||
|
||||
protected void evalAccessPaths(QueryExpressions exps,
|
||||
ExpressionFactory factory, CriteriaQueryImpl q) {
|
||||
protected void evalAccessPaths(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl<?> q) {
|
||||
Set<ClassMetaData> metas = new HashSet<ClassMetaData>();
|
||||
Set<Root<?>> roots = q.getRoots();
|
||||
if (roots != null) {
|
||||
|
@ -88,17 +86,14 @@ public class CriteriaExpressionBuilder {
|
|||
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 @@ public class CriteriaExpressionBuilder {
|
|||
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<Order> orders = q.getOrderList();
|
||||
MetamodelImpl model = q.getMetamodel();
|
||||
if (orders == null)
|
||||
|
@ -124,7 +118,7 @@ public class CriteriaExpressionBuilder {
|
|||
for (int i = 0; i < ordercount; i++) {
|
||||
OrderImpl order = (OrderImpl)orders.get(i);
|
||||
//Expression<? extends Comparable> 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 @@ public class CriteriaExpressionBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
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<Expression<?>> groups = q.getGroupList();
|
||||
|
@ -155,8 +148,7 @@ public class CriteriaExpressionBuilder {
|
|||
: 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 @@ public class CriteriaExpressionBuilder {
|
|||
//exps.distinct &= ~QueryExpressions.DISTINCT_AUTO;
|
||||
}
|
||||
|
||||
protected void evalFilter(QueryExpressions exps, ExpressionFactory factory,
|
||||
CriteriaQueryImpl q) {
|
||||
protected void evalFilter(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl<?> q) {
|
||||
Set<Root<?>> 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);
|
||||
}
|
||||
((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) {
|
||||
filter = and(factory, where.toKernelExpression
|
||||
(factory, model, q), filter);
|
||||
|
@ -192,8 +195,7 @@ public class CriteriaExpressionBuilder {
|
|||
exps.filter = filter;
|
||||
}
|
||||
|
||||
protected void evalProjections(QueryExpressions exps,
|
||||
ExpressionFactory factory, CriteriaQueryImpl q) {
|
||||
protected void evalProjections(QueryExpressions exps, ExpressionFactory factory, CriteriaQueryImpl<?> q) {
|
||||
List<Selection<?>> selections = q.getSelectionList();
|
||||
MetamodelImpl model = q.getMetamodel();
|
||||
// TODO: fill in projection clauses
|
||||
|
@ -212,8 +214,8 @@ public class CriteriaExpressionBuilder {
|
|||
}
|
||||
|
||||
private void getProjections(QueryExpressions exps,
|
||||
List<Selection<?>> selections, List projections, List aliases,
|
||||
ExpressionFactory factory, CriteriaQueryImpl q, MetamodelImpl model) {
|
||||
List<Selection<?>> selections, List projections, List<String> aliases,
|
||||
ExpressionFactory factory, CriteriaQueryImpl<?> q, MetamodelImpl model) {
|
||||
for (Selection<?> s : selections) {
|
||||
List<Selection<?>> sels = ((SelectionImpl)s).getSelections();
|
||||
if (sels == null) {
|
||||
|
@ -229,14 +231,20 @@ public class CriteriaExpressionBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
protected boolean isDefaultProjection(List<Selection<?>> selections,
|
||||
CriteriaQueryImpl q) {
|
||||
return selections == null
|
||||
|| (selections.size() == 1 && selections.get(0) == q.getRoot());
|
||||
protected boolean isDefaultProjection(List<Selection<?>> 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<String> iPaths = new ArrayList<String>();
|
||||
List<String> oPaths = new ArrayList<String>();
|
||||
Set<Root<?>> roots = q.getRoots();
|
||||
|
|
|
@ -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 @@ public abstract class Joins {
|
|||
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 metamodel attribute type corresponding to the join
|
||||
|
@ -111,32 +116,37 @@ public abstract class Joins {
|
|||
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<Join<?,?>> 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 @@ public abstract class Joins {
|
|||
}
|
||||
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 @@ public abstract class Joins {
|
|||
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
|
||||
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 @@ public abstract class Joins {
|
|||
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<Join<?,?>> 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 @@ public abstract class Joins {
|
|||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -56,8 +56,8 @@ public class PathImpl<Z,X> extends ExpressionImpl<X> implements Path<X> {
|
|||
protected final PathImpl<?,Z> _parent;
|
||||
protected final Members.Member<? super Z,?> _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 @@ public class PathImpl<Z,X> extends ExpressionImpl<X> implements Path<X> {
|
|||
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 @@ public class PathImpl<Z,X> extends ExpressionImpl<X> implements Path<X> {
|
|||
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 @@ public class PathImpl<Z,X> extends ExpressionImpl<X> implements Path<X> {
|
|||
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 @@ public class PathImpl<Z,X> extends ExpressionImpl<X> implements Path<X> {
|
|||
&& ((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;
|
||||
|
|
|
@ -50,7 +50,7 @@ public class RootImpl<X> extends FromImpl<X,X> implements Root<X> {
|
|||
}
|
||||
|
||||
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 @@ public class RootImpl<X> extends FromImpl<X,X> implements Root<X> {
|
|||
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;
|
||||
|
|
|
@ -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.AbstractQuery;
|
|||
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 @@ public class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
|
|||
private java.util.Set<Join<?,?>> _joins;
|
||||
private Expression<T> _select;
|
||||
private org.apache.openjpa.kernel.exps.Subquery _subq;
|
||||
private List<Join<?,?>> _corrJoins = null;
|
||||
|
||||
public SubqueryImpl(Class<T> cls, AbstractQuery<?> parent) {
|
||||
super(cls);
|
||||
|
@ -176,7 +179,7 @@ public class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
|
|||
public <Y> Root<Y> correlate(Root<Y> root) {
|
||||
Types.Entity<Y> entity = (Types.Entity<Y>)root.getModel();
|
||||
RootImpl<Y> corrRoot = new RootImpl<Y>(entity);
|
||||
corrRoot.setCorrelatedParent((RootImpl<Y>)root);
|
||||
corrRoot.setCorrelatedPath((RootImpl<Y>)root);
|
||||
Set<Root<?>> roots = getRoots();
|
||||
if (roots == null) {
|
||||
roots = new LinkedHashSet<Root<?>>();
|
||||
|
@ -186,9 +189,54 @@ public class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
|
|||
return corrRoot;
|
||||
}
|
||||
|
||||
public List<Join<?,?>> getCorrelatedJoins() {
|
||||
return _corrJoins;
|
||||
}
|
||||
|
||||
public <X,Y> Join<X,Y> correlate(Join<X,Y> join) {
|
||||
_delegate.from(join.getModel().getBindableJavaType());
|
||||
return join;
|
||||
Join corrJoin = clone(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) {
|
||||
_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,
|
||||
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 @@ public class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
|
|||
//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 @@ public class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
|
|||
// correlated parent, the candidate of the subquery
|
||||
// should be the class metadata of the collection element
|
||||
private ClassMetaData getCandidate() {
|
||||
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();
|
||||
}
|
||||
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<?> 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();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue