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 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();

View File

@ -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);
}
}
/**

View File

@ -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;

View File

@ -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;

View File

@ -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();
}
}