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 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,22 +159,33 @@ 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;
|
||||||
for (Root<?> root : roots) {
|
if (subQuery == null || subQuery.getCorrelatedJoins() == null) {
|
||||||
if (root.getJoins() != null) {
|
q.assertRoot();
|
||||||
for (Join<?, ?> join : root.getJoins()) {
|
for (Root<?> root : roots) {
|
||||||
filter = and(factory, ((ExpressionImpl<?>)join)
|
if (root.getJoins() != null) {
|
||||||
.toKernelExpression(factory, model, q), filter);
|
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) {
|
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();
|
||||||
|
|
|
@ -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,32 +116,37 @@ 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.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;
|
org.apache.openjpa.kernel.exps.Expression join = null;
|
||||||
if (bind) {
|
if (_correlatedPath == null) {
|
||||||
Value var = factory.newBoundVariable(c.getAlias(this), meta.getDescribedType());
|
if (subquery != null) {
|
||||||
join = factory.bindVariable(var, path);
|
corrJoins = subquery.getCorrelatedJoins();
|
||||||
c.registerVariable(this, var, path);
|
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) {
|
if (getJoins() != null) {
|
||||||
for (Join<?, ?> join1 : getJoins()) {
|
for (Join<?, ?> join1 : getJoins()) {
|
||||||
|
@ -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,34 +271,40 @@ 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.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;
|
org.apache.openjpa.kernel.exps.Expression join = null;
|
||||||
if (bind) {
|
PathImpl<?,?> corrJoin = getCorrelatedJoin(this);
|
||||||
Value var = factory.newBoundVariable(c.getAlias(this), meta.getDescribedType());
|
PathImpl<?,?> corrRoot = getCorrelatedRoot(subquery);
|
||||||
join = factory.bindVariable(var, path);
|
|
||||||
c.registerVariable(this, var, path);
|
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) {
|
if (getJoins() != null) {
|
||||||
for (Join<?, ?> join1 : getJoins()) {
|
for (Join<?, ?> join1 : getJoins()) {
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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() {
|
||||||
RootImpl<?> root = (RootImpl<?>)getRoot();
|
if (_delegate.getRoots() == null && _corrJoins != null) {
|
||||||
PathImpl<?, ?> correlatedRoot = root.getCorrelatedParent();
|
FromImpl<?,?> corrJoin = (FromImpl<?,?>) _corrJoins.get(0);
|
||||||
if (correlatedRoot != null && root.getJoins() != null) {
|
if (corrJoin.getJoins() != null) {
|
||||||
Join<?,?> join = root.getJoins().iterator().next();
|
FromImpl<?,?> join = (FromImpl<?,?>)corrJoin.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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
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