mirror of
https://github.com/apache/openjpa.git
synced 2025-03-06 08:29:08 +00:00
OPENJPA-1143: subquery support
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@787916 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
636bd5f213
commit
e57f032626
@ -40,7 +40,6 @@ import org.apache.openjpa.meta.ClassMetaData;
|
||||
import org.apache.openjpa.persistence.meta.AbstractManagedType;
|
||||
import org.apache.openjpa.persistence.meta.Members;
|
||||
import org.apache.openjpa.persistence.meta.MetamodelImpl;
|
||||
import org.apache.openjpa.persistence.meta.Types;
|
||||
|
||||
/**
|
||||
* Converts expressions of a CriteriaQuery to kernel Expression.
|
||||
@ -53,6 +52,7 @@ public class CriteriaExpressionBuilder {
|
||||
public QueryExpressions getQueryExpressions(ExpressionFactory factory,
|
||||
CriteriaQueryImpl q) {
|
||||
QueryExpressions exps = new QueryExpressions();
|
||||
//exps.setContexts(q.getContexts());
|
||||
|
||||
evalAccessPaths(exps, factory, q);
|
||||
//exps.alias = null; // String
|
||||
@ -181,10 +181,7 @@ public class CriteriaExpressionBuilder {
|
||||
.toKernelExpression(factory, model, q), filter);
|
||||
}
|
||||
}
|
||||
if (((RootImpl<?>)root).getCorrelatedParent() != null) {
|
||||
filter = and(factory, ((RootImpl<?>)root)
|
||||
.toKernelExpression(factory, model, q), filter);
|
||||
}
|
||||
((RootImpl)root).addToContext(factory, model, q);
|
||||
}
|
||||
if (where != null) {
|
||||
filter = and(factory, where.toKernelExpression
|
||||
|
@ -20,16 +20,14 @@ package org.apache.openjpa.persistence.criteria;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Parameter;
|
||||
import javax.persistence.criteria.AbstractQuery;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Expression;
|
||||
import javax.persistence.criteria.Order;
|
||||
@ -45,7 +43,6 @@ import org.apache.openjpa.kernel.StoreQuery;
|
||||
import org.apache.openjpa.kernel.exps.ExpressionFactory;
|
||||
import org.apache.openjpa.kernel.exps.QueryExpressions;
|
||||
import org.apache.openjpa.kernel.exps.Value;
|
||||
import org.apache.openjpa.persistence.QueryImpl;
|
||||
import org.apache.openjpa.persistence.meta.MetamodelImpl;
|
||||
import org.apache.openjpa.persistence.meta.Types;
|
||||
|
||||
@ -73,7 +70,7 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
|
||||
private PredicateImpl _having;
|
||||
private List<Subquery<?>> _subqueries;
|
||||
private Boolean _distinct;
|
||||
private SubqueryImpl<?> _context;
|
||||
private SubqueryImpl<?> _delegator;
|
||||
|
||||
// AliasContext
|
||||
private int aliasCount = 0;
|
||||
@ -83,25 +80,38 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
|
||||
new HashMap<Selection<?>, Value>();
|
||||
private Map<Selection<?>,Value> _values =
|
||||
new HashMap<Selection<?>, Value>();
|
||||
private Map<Selection<?>,String> _aliases =
|
||||
new HashMap<Selection<?>, String>();
|
||||
private Map<Selection<?>,String> _aliases = null;
|
||||
|
||||
// SubqueryContext
|
||||
//private Stack<Context> _contexts = null;
|
||||
|
||||
public CriteriaQueryImpl(MetamodelImpl model) {
|
||||
this._model = model;
|
||||
_aliases = new HashMap<Selection<?>, String>();
|
||||
}
|
||||
|
||||
public void setContext(SubqueryImpl<?> context) {
|
||||
_context = context;
|
||||
public CriteriaQueryImpl(MetamodelImpl model, SubqueryImpl<?> delegator) {
|
||||
this._model = model;
|
||||
_delegator = delegator;
|
||||
_aliases = getAliases();
|
||||
}
|
||||
|
||||
public void setDelegator(SubqueryImpl<?> delegator) {
|
||||
_delegator = delegator;
|
||||
}
|
||||
|
||||
public SubqueryImpl<?> getContext() {
|
||||
return _context;
|
||||
public SubqueryImpl<?> getDelegator() {
|
||||
return _delegator;
|
||||
}
|
||||
|
||||
public MetamodelImpl getMetamodel() {
|
||||
return _model;
|
||||
}
|
||||
|
||||
//public Stack<Context> getContexts() {
|
||||
// return _contexts;
|
||||
//}
|
||||
|
||||
public CriteriaQuery distinct(boolean distinct) {
|
||||
_distinct = distinct;
|
||||
return this;
|
||||
@ -319,8 +329,11 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
|
||||
* receiver with the help of the given {@link ExpressionFactory}.
|
||||
*/
|
||||
QueryExpressions getQueryExpressions(ExpressionFactory factory) {
|
||||
//_contexts = new Stack<Context>();
|
||||
//Context context = new Context(null, null, null);
|
||||
// _contexts.push(context);
|
||||
return new CriteriaExpressionBuilder()
|
||||
.getQueryExpressions(factory, this);
|
||||
.getQueryExpressions(factory, this);
|
||||
}
|
||||
|
||||
public void assertRoot() {
|
||||
@ -328,6 +341,30 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
|
||||
throw new IllegalStateException("no root is set");
|
||||
}
|
||||
|
||||
//
|
||||
// SubqueryContext
|
||||
//
|
||||
//public void setContexts(Stack<Context> contexts) {
|
||||
// _contexts = contexts;
|
||||
//}
|
||||
|
||||
public CriteriaQueryImpl getInnermostParent() {
|
||||
if (_delegator == null)
|
||||
return this;
|
||||
AbstractQuery parent = _delegator.getParent();
|
||||
if (parent instanceof CriteriaQueryImpl)
|
||||
return (CriteriaQueryImpl)parent;
|
||||
// parent is a SubqueryImpl
|
||||
return ((SubqueryImpl)parent).getDelegate().getInnermostParent();
|
||||
}
|
||||
|
||||
public Map<Selection<?>,String> getAliases() {
|
||||
CriteriaQueryImpl c = getInnermostParent();
|
||||
if (c._aliases == null)
|
||||
c._aliases = new HashMap<Selection<?>, String>();
|
||||
return c._aliases;
|
||||
}
|
||||
|
||||
//
|
||||
// AliasContext management
|
||||
//
|
||||
@ -390,6 +427,8 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
|
||||
_variables.put(node, var);
|
||||
_values.put(node, path);
|
||||
_aliases.put(node, alias);
|
||||
//_contexts.peek().addSchema(alias, var.getMetaData());
|
||||
//_contexts.peek().addVariable(alias, var);
|
||||
}
|
||||
|
||||
public boolean isRegistered(Selection<?> selection) {
|
||||
|
@ -29,7 +29,6 @@ import javax.persistence.criteria.JoinType;
|
||||
import javax.persistence.criteria.ListJoin;
|
||||
import javax.persistence.criteria.MapJoin;
|
||||
import javax.persistence.criteria.SetJoin;
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import javax.persistence.metamodel.CollectionAttribute;
|
||||
import javax.persistence.metamodel.ListAttribute;
|
||||
import javax.persistence.metamodel.MapAttribute;
|
||||
@ -39,7 +38,6 @@ import javax.persistence.metamodel.SingularAttribute;
|
||||
|
||||
import org.apache.openjpa.persistence.meta.AbstractManagedType;
|
||||
import org.apache.openjpa.persistence.meta.Members;
|
||||
import org.apache.openjpa.persistence.meta.Types;
|
||||
|
||||
/**
|
||||
* Represents a bound type, usually an entity that appears in the from clause,
|
||||
@ -174,7 +172,7 @@ public class FromImpl<Z,X> extends PathImpl<Z,X> implements From<Z,X> {
|
||||
|
||||
|
||||
public <W,Y> CollectionJoin<W, Y> joinCollection(String attr) {
|
||||
return (CollectionJoin<W,Y>)join(attr, JoinType.INNER);
|
||||
return (CollectionJoin<W,Y>)join(type.getCollection(attr), JoinType.INNER);
|
||||
}
|
||||
|
||||
public <W,Y> CollectionJoin<W, Y> joinCollection(String attr, JoinType jt) {
|
||||
@ -182,7 +180,7 @@ public class FromImpl<Z,X> extends PathImpl<Z,X> implements From<Z,X> {
|
||||
}
|
||||
|
||||
public <W,Y> ListJoin<W, Y> joinList(String attr) {
|
||||
return (ListJoin<W,Y>)join(attr, JoinType.INNER);
|
||||
return (ListJoin<W,Y>)join(type.getList(attr), JoinType.INNER);
|
||||
}
|
||||
|
||||
public <W,Y> ListJoin<W,Y> joinList(String attr, JoinType jt) {
|
||||
|
@ -58,11 +58,13 @@ public abstract class Joins {
|
||||
public static class SingularJoin<Z,X> extends FromImpl<Z,X>
|
||||
implements Join<Z,X>{
|
||||
private final JoinType joinType;
|
||||
private boolean allowNull = false;
|
||||
|
||||
public SingularJoin(FromImpl<?,Z> from,
|
||||
Members.SingularAttributeImpl<? super Z, X> member, JoinType jt) {
|
||||
super(from, member, member.getJavaType());
|
||||
joinType = jt;
|
||||
allowNull = joinType != JoinType.INNER;
|
||||
}
|
||||
|
||||
public JoinType getJoinType() {
|
||||
@ -85,16 +87,26 @@ public abstract class Joins {
|
||||
@Override
|
||||
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
|
||||
CriteriaQueryImpl c) {
|
||||
ClassMetaData meta = _member.fmd.getDeclaredTypeMetaData();
|
||||
org.apache.openjpa.kernel.exps.Path path = null;
|
||||
SubqueryImpl<?> subquery = c.getDelegator();
|
||||
PathImpl<?,?> parent = getInnermostParentPath();
|
||||
if (c.isRegistered(this))
|
||||
return c.getValue(this);
|
||||
boolean allowNull = joinType != JoinType.INNER;
|
||||
ClassMetaData meta = _member.fmd.getDeclaredTypeMetaData();
|
||||
org.apache.openjpa.kernel.exps.Path path =
|
||||
(org.apache.openjpa.kernel.exps.Path)
|
||||
_parent.toValue(factory, model, c);
|
||||
path.get(_member.fmd, allowNull);
|
||||
path.setMetaData(meta);
|
||||
path.setImplicitType(meta.getDescribedType());
|
||||
else if (parent.inSubquery(subquery)) {
|
||||
org.apache.openjpa.kernel.exps.Subquery subQ =
|
||||
subquery.getSubQ();
|
||||
path = factory.newPath(subQ);
|
||||
path.setMetaData(subQ.getMetaData());
|
||||
//path.setSchemaAlias(c.getAlias(this));
|
||||
} else {
|
||||
path =
|
||||
(org.apache.openjpa.kernel.exps.Path)
|
||||
_parent.toValue(factory, model, c);
|
||||
path.get(_member.fmd, allowNull);
|
||||
path.setMetaData(meta);
|
||||
path.setImplicitType(meta.getDescribedType());
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
@ -104,7 +116,23 @@ public abstract class Joins {
|
||||
CriteriaQueryImpl c) {
|
||||
ClassMetaData meta = _member.fmd.getDeclaredTypeMetaData();
|
||||
org.apache.openjpa.kernel.exps.Path path = null;
|
||||
if (c.isRegistered(_parent)) {
|
||||
SubqueryImpl<?> subquery = c.getDelegator();
|
||||
PathImpl<?,?> parent = getInnermostParentPath();
|
||||
org.apache.openjpa.kernel.exps.Expression filter = null;
|
||||
PathImpl correlatedParent = 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);
|
||||
@ -112,12 +140,13 @@ public abstract class Joins {
|
||||
} else
|
||||
path =
|
||||
(org.apache.openjpa.kernel.exps.Path)toValue(factory, model, c);
|
||||
Value var = factory.newBoundVariable(c.getAlias(this),
|
||||
meta.getDescribedType());
|
||||
org.apache.openjpa.kernel.exps.Expression join = factory
|
||||
.bindVariable(var, path);
|
||||
c.registerVariable(this, var, path);
|
||||
org.apache.openjpa.kernel.exps.Expression filter = 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 (getJoins() != null) {
|
||||
for (Join<?, ?> join1 : getJoins()) {
|
||||
filter = CriteriaExpressionBuilder.and(factory,
|
||||
@ -125,7 +154,22 @@ public abstract class Joins {
|
||||
toKernelExpression(factory, model, c), filter);
|
||||
}
|
||||
}
|
||||
return CriteriaExpressionBuilder.and(factory, join, filter);
|
||||
org.apache.openjpa.kernel.exps.Expression expr =
|
||||
CriteriaExpressionBuilder.and(factory, join, filter);
|
||||
|
||||
if (correlatedParent == null)
|
||||
return expr;
|
||||
else {
|
||||
org.apache.openjpa.kernel.exps.Path parentPath =
|
||||
(org.apache.openjpa.kernel.exps.Path)
|
||||
correlatedParent.toValue(factory, model, c);
|
||||
parentPath.get(_member.fmd, allowNull);
|
||||
//parentPath.setSchemaAlias(c.getAlias(correlatedParent));
|
||||
path.setMetaData(meta);
|
||||
//filter = bindVariableForKeyPath(path, alias, filter);
|
||||
filter = factory.equal(parentPath, path);
|
||||
return CriteriaExpressionBuilder.and(factory, expr, filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,11 +184,13 @@ public abstract class Joins {
|
||||
public static abstract class AbstractCollection<Z,C,E> extends FromImpl<Z,E>
|
||||
implements PluralJoin<Z, C, E> {
|
||||
final JoinType joinType;
|
||||
boolean allowNull = false;
|
||||
|
||||
public AbstractCollection(FromImpl<?,Z> from,
|
||||
Members.PluralAttributeImpl<? super Z, C, E> member, JoinType jt) {
|
||||
super(from, member, member.getBindableJavaType());
|
||||
joinType = jt;
|
||||
allowNull = joinType != JoinType.INNER;
|
||||
}
|
||||
|
||||
public JoinType getJoinType() {
|
||||
@ -167,6 +213,12 @@ public abstract class Joins {
|
||||
public PluralAttribute<? super Z, C, E> getModel() {
|
||||
return (PluralAttribute<? super Z, C, E>) _member.getType();
|
||||
}
|
||||
|
||||
public ClassMetaData getMemberClassMetaData() {
|
||||
return _member.fmd.isElementCollection()
|
||||
? _member.fmd.getEmbeddedMetaData()
|
||||
: _member.fmd.getElement().getDeclaredTypeMetaData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this path to a kernel path (value).
|
||||
@ -174,13 +226,20 @@ public abstract class Joins {
|
||||
@Override
|
||||
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
|
||||
CriteriaQueryImpl c) {
|
||||
boolean allowNull = joinType != JoinType.INNER;
|
||||
ClassMetaData meta = _member.fmd.getElement()
|
||||
.getDeclaredTypeMetaData();
|
||||
ClassMetaData meta = getMemberClassMetaData();
|
||||
org.apache.openjpa.kernel.exps.Path path = null;
|
||||
SubqueryImpl<?> subquery = c.getDelegator();
|
||||
PathImpl<?,?> parent = getInnermostParentPath();
|
||||
|
||||
if (c.isRegistered(this)) {
|
||||
Value var = c.getVariable(this);
|
||||
path = factory.newPath(var);
|
||||
} else if (parent.inSubquery(subquery)) {
|
||||
org.apache.openjpa.kernel.exps.Subquery subQ =
|
||||
subquery.getSubQ();
|
||||
path = factory.newPath(subQ);
|
||||
path.setMetaData(subQ.getMetaData());
|
||||
//path.setSchemaAlias(c.getAlias(this));
|
||||
} else {
|
||||
path = (org.apache.openjpa.kernel.exps.Path)
|
||||
_parent.toValue(factory, model, c);
|
||||
@ -197,12 +256,25 @@ public abstract class Joins {
|
||||
public org.apache.openjpa.kernel.exps.Expression toKernelExpression(
|
||||
ExpressionFactory factory, MetamodelImpl model,
|
||||
CriteriaQueryImpl c) {
|
||||
ClassMetaData meta = _member.fmd.isElementCollection()
|
||||
? _member.fmd.getEmbeddedMetaData()
|
||||
: _member.fmd.getElement().getDeclaredTypeMetaData();
|
||||
|
||||
ClassMetaData meta = getMemberClassMetaData();
|
||||
org.apache.openjpa.kernel.exps.Path path = null;
|
||||
if (c.isRegistered(_parent)) {
|
||||
SubqueryImpl<?> subquery = c.getDelegator();
|
||||
PathImpl<?,?> parent = getInnermostParentPath();
|
||||
org.apache.openjpa.kernel.exps.Expression filter = null;
|
||||
PathImpl correlatedParent = 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);
|
||||
@ -210,13 +282,14 @@ public abstract class Joins {
|
||||
} else
|
||||
path = (org.apache.openjpa.kernel.exps.Path)
|
||||
toValue(factory, model, c);
|
||||
|
||||
Value var = factory.newBoundVariable(c.getAlias(this),
|
||||
meta.getDescribedType());
|
||||
org.apache.openjpa.kernel.exps.Expression join =
|
||||
factory.bindVariable(var, path);
|
||||
c.registerVariable(this, var, path);
|
||||
org.apache.openjpa.kernel.exps.Expression filter = 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 (getJoins() != null) {
|
||||
for (Join<?, ?> join1 : getJoins()) {
|
||||
filter = CriteriaExpressionBuilder.and(factory,
|
||||
@ -224,8 +297,22 @@ public abstract class Joins {
|
||||
toKernelExpression(factory, model, c), filter);
|
||||
}
|
||||
}
|
||||
return CriteriaExpressionBuilder.and(factory, join, filter);
|
||||
}
|
||||
org.apache.openjpa.kernel.exps.Expression expr =
|
||||
CriteriaExpressionBuilder.and(factory, join, filter);
|
||||
if (correlatedParent == null)
|
||||
return expr;
|
||||
else {
|
||||
org.apache.openjpa.kernel.exps.Path parentPath =
|
||||
(org.apache.openjpa.kernel.exps.Path)
|
||||
correlatedParent.toValue(factory, model, c);
|
||||
parentPath.get(_member.fmd, allowNull);
|
||||
//parentPath.setSchemaAlias(c.getAlias(correlatedParent));
|
||||
path.setMetaData(meta);
|
||||
//filter = bindVariableForKeyPath(path, alias, filter);
|
||||
filter = factory.equal(parentPath, path);
|
||||
return CriteriaExpressionBuilder.and(factory, expr, filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -23,7 +23,6 @@ import javax.persistence.criteria.Expression;
|
||||
import javax.persistence.criteria.Join;
|
||||
import javax.persistence.criteria.JoinType;
|
||||
import javax.persistence.criteria.Path;
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
import javax.persistence.metamodel.Bindable;
|
||||
import javax.persistence.metamodel.ManagedType;
|
||||
import javax.persistence.metamodel.MapAttribute;
|
||||
@ -58,7 +57,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. use by root path which neither represent a member nor has a
|
||||
* parent.
|
||||
@ -121,6 +121,13 @@ public class PathImpl<Z,X> extends ExpressionImpl<X> implements Path<X> {
|
||||
parent._member);
|
||||
}
|
||||
|
||||
public void setCorrelatedParent(PathImpl<?,?> correlatedParent) {
|
||||
_correlatedParent = correlatedParent;
|
||||
}
|
||||
|
||||
public PathImpl<?,?> getCorrelatedParent() {
|
||||
return _correlatedParent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this path to a kernel path.
|
||||
@ -131,27 +138,26 @@ public class PathImpl<Z,X> extends ExpressionImpl<X> implements Path<X> {
|
||||
if (q.isRegistered(this))
|
||||
return q.getValue(this);
|
||||
org.apache.openjpa.kernel.exps.Path path = null;
|
||||
SubqueryImpl<?> subquery = q.getContext();
|
||||
SubqueryImpl<?> subquery = q.getDelegator();
|
||||
PathImpl<?,?> parent = getInnermostParentPath();
|
||||
if (parent.inSubquery(subquery)) {
|
||||
boolean allowNull = _parent == null ? false : _parent instanceof Join
|
||||
&& ((Join<?,?>)_parent).getJoinType() != JoinType.INNER;
|
||||
|
||||
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)) {
|
||||
org.apache.openjpa.kernel.exps.Subquery subQ = subquery.getSubQ();
|
||||
path = factory.newPath(subQ);
|
||||
path.setMetaData(subQ.getMetaData());
|
||||
boolean allowNull = false;
|
||||
//path.setSchemaAlias(q.getAlias(_parent));
|
||||
traversePath(_parent, path, _member.fmd);
|
||||
} else if (_parent != null) {
|
||||
path = (org.apache.openjpa.kernel.exps.Path)
|
||||
_parent.toValue(factory, model, q);
|
||||
path.get(_member.fmd, allowNull);
|
||||
} else if (_parent != null) {
|
||||
if (q.isRegistered(_parent)) {
|
||||
path = factory.newPath(q.getVariable(_parent));
|
||||
ClassMetaData meta = _member.fmd.getDeclaredTypeMetaData();
|
||||
path.setMetaData(meta);
|
||||
} else {
|
||||
path = (org.apache.openjpa.kernel.exps.Path)
|
||||
_parent.toValue(factory, model, q);
|
||||
}
|
||||
boolean allowNull = _parent instanceof Join
|
||||
&& ((Join<?,?>)_parent).getJoinType() != JoinType.INNER;
|
||||
path.get(_member.fmd, allowNull);
|
||||
} else {
|
||||
} else if (_parent == null) {
|
||||
path = factory.newPath();
|
||||
path.setMetaData(model.repos.getCachedMetaData(getJavaType()));
|
||||
}
|
||||
@ -171,6 +177,22 @@ public class PathImpl<Z,X> extends ExpressionImpl<X> implements Path<X> {
|
||||
return subquery != null && subquery.getRoots().contains(this);
|
||||
}
|
||||
|
||||
protected void traversePath(PathImpl<?,?> parent,
|
||||
org.apache.openjpa.kernel.exps.Path path, FieldMetaData fmd) {
|
||||
boolean allowNull = parent == null ? false : parent instanceof Join
|
||||
&& ((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 (fmd != null)
|
||||
path.get(fmd, allowNull);
|
||||
return;
|
||||
}
|
||||
traversePath(parent1, path, fmd1);
|
||||
if (fmd != null)
|
||||
path.get(fmd, allowNull);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the path corresponding to the referenced
|
||||
* single-valued attribute.
|
||||
|
@ -22,7 +22,7 @@ package org.apache.openjpa.persistence.criteria;
|
||||
import javax.persistence.criteria.Root;
|
||||
import javax.persistence.metamodel.EntityType;
|
||||
|
||||
import org.apache.openjpa.kernel.exps.Expression;
|
||||
import org.apache.openjpa.kernel.exps.AbstractExpressionBuilder;
|
||||
import org.apache.openjpa.kernel.exps.ExpressionFactory;
|
||||
import org.apache.openjpa.kernel.exps.Path;
|
||||
import org.apache.openjpa.kernel.exps.Subquery;
|
||||
@ -39,7 +39,6 @@ import org.apache.openjpa.persistence.meta.Types;
|
||||
*/
|
||||
public class RootImpl<X> extends FromImpl<X,X> implements Root<X> {
|
||||
private final Types.Entity<X> _entity;
|
||||
private RootImpl<X> _correlatedParent;
|
||||
|
||||
public RootImpl(Types.Entity<X> type) {
|
||||
super(type);
|
||||
@ -50,12 +49,18 @@ public class RootImpl<X> extends FromImpl<X,X> implements Root<X> {
|
||||
return _entity;
|
||||
}
|
||||
|
||||
public void setCorrelatedParent(RootImpl<X> correlatedParent) {
|
||||
_correlatedParent = correlatedParent;
|
||||
}
|
||||
|
||||
public RootImpl<X> getCorrelatedParent() {
|
||||
return _correlatedParent;
|
||||
public void addToContext(ExpressionFactory factory, MetamodelImpl model,
|
||||
CriteriaQueryImpl q) {
|
||||
String alias = q.getAlias(this);
|
||||
Value var = factory.newBoundVariable(alias,
|
||||
AbstractExpressionBuilder.TYPE_OBJECT);
|
||||
var.setMetaData(_entity.meta);
|
||||
//TODO:
|
||||
//Context currContext = (Context)q.getContexts().peek();
|
||||
//currContext.addSchema(alias, _entity.meta);
|
||||
//currContext.addVariable(alias, var);
|
||||
//if (currContext.schemaAlias == null)
|
||||
// currContext.schemaAlias = alias;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -64,7 +69,7 @@ public class RootImpl<X> extends FromImpl<X,X> implements Root<X> {
|
||||
@Override
|
||||
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
|
||||
CriteriaQueryImpl c) {
|
||||
SubqueryImpl<?> subquery = c.getContext();
|
||||
SubqueryImpl<?> subquery = c.getDelegator();
|
||||
Path var = null;
|
||||
if (inSubquery(subquery)) {
|
||||
Subquery subQ = subquery.getSubQ();
|
||||
@ -85,13 +90,8 @@ public class RootImpl<X> extends FromImpl<X,X> implements Root<X> {
|
||||
ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl c) {
|
||||
Value path = toValue(factory, model, c);
|
||||
Value var = factory.newBoundVariable(c.getAlias(this),
|
||||
_entity.meta.getDescribedType());
|
||||
Expression exp = factory.bindVariable(var, path);
|
||||
|
||||
if (_correlatedParent == null)
|
||||
return exp;
|
||||
Value path1 = _correlatedParent.toValue(factory, model, c);
|
||||
return factory.equal(path1, path);
|
||||
_entity.meta.getDescribedType());
|
||||
return factory.bindVariable(var, path);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
@ -39,6 +39,7 @@ import org.apache.openjpa.kernel.exps.QueryExpressions;
|
||||
import org.apache.openjpa.kernel.exps.Value;
|
||||
import org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder;
|
||||
import org.apache.openjpa.meta.ClassMetaData;
|
||||
import org.apache.openjpa.meta.JavaTypes;
|
||||
import org.apache.openjpa.persistence.meta.AbstractManagedType;
|
||||
import org.apache.openjpa.persistence.meta.MetamodelImpl;
|
||||
import org.apache.openjpa.persistence.meta.Types;
|
||||
@ -53,23 +54,47 @@ import org.apache.openjpa.persistence.meta.Types;
|
||||
* @param <T> the type selected by this subquery.
|
||||
*/
|
||||
public class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
|
||||
private final CriteriaQueryImpl _parent;
|
||||
private final AbstractQuery _parent;
|
||||
private final CriteriaQueryImpl _delegate;
|
||||
private final MetamodelImpl _model;
|
||||
private java.util.Set<Join<?,?>> _joins;
|
||||
private Expression<T> _select;
|
||||
private org.apache.openjpa.kernel.exps.Subquery _subq;
|
||||
|
||||
public SubqueryImpl(Class<T> cls, CriteriaQueryImpl parent) {
|
||||
public SubqueryImpl(Class<T> cls, AbstractQuery parent) {
|
||||
super(cls);
|
||||
_parent = parent;
|
||||
_delegate = new CriteriaQueryImpl(parent.getMetamodel());
|
||||
_delegate.setContext(this);
|
||||
if (parent instanceof CriteriaQueryImpl)
|
||||
_model = ((CriteriaQueryImpl)parent).getMetamodel();
|
||||
else if (parent instanceof SubqueryImpl)
|
||||
_model = ((SubqueryImpl)parent).getMetamodel();
|
||||
else
|
||||
_model = null;
|
||||
|
||||
_delegate = new CriteriaQueryImpl(_model, this);
|
||||
}
|
||||
|
||||
public AbstractQuery getParent() {
|
||||
return _parent;
|
||||
}
|
||||
|
||||
public CriteriaQueryImpl getDelegate() {
|
||||
return _delegate;
|
||||
}
|
||||
|
||||
public MetamodelImpl getMetamodel() {
|
||||
return _model;
|
||||
}
|
||||
|
||||
//public Stack<Context> getContexts() {
|
||||
// return getInnermostParent().getContexts();
|
||||
//}
|
||||
|
||||
public CriteriaQueryImpl getInnermostParent() {
|
||||
return (CriteriaQueryImpl)(((_parent instanceof CriteriaQueryImpl)) ?
|
||||
_parent : ((SubqueryImpl)_parent).getInnermostParent());
|
||||
}
|
||||
|
||||
public Subquery<T> select(Expression<T> expression) {
|
||||
_select = expression;
|
||||
_delegate.select(expression);
|
||||
@ -201,15 +226,41 @@ public class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
|
||||
final boolean subclasses = true;
|
||||
CriteriaExpressionBuilder queryEval = new CriteriaExpressionBuilder();
|
||||
String alias = q.getAlias(this);
|
||||
ClassMetaData candidate =
|
||||
((AbstractManagedType<?>)getRoot().getModel()).meta;
|
||||
ClassMetaData candidate = getCandidate();
|
||||
_subq = factory.newSubquery(candidate, subclasses, alias);
|
||||
_subq.setMetaData(candidate);
|
||||
//TODO:
|
||||
//Stack<Context> contexts = getContexts();
|
||||
//Context context = new Context(null, _subq, contexts.peek());
|
||||
//contexts.push(context);
|
||||
//_delegate.setContexts(contexts);
|
||||
QueryExpressions subexp = queryEval.getQueryExpressions(factory,
|
||||
_delegate);
|
||||
_subq.setQueryExpressions(subexp);
|
||||
if (subexp.projections.length > 0)
|
||||
JPQLExpressionBuilder.checkEmbeddable(subexp.projections[0], null);
|
||||
//contexts.pop();
|
||||
return _subq;
|
||||
}
|
||||
|
||||
// if we are in a subquery against a collection from a
|
||||
// correlated parent, the candidate of the subquery
|
||||
// should be the class metadata of the collection element
|
||||
private ClassMetaData getCandidate() {
|
||||
RootImpl<?> root = (RootImpl<?>)getRoot();
|
||||
RootImpl<?> correlatedRoot = (RootImpl<?>)root.getCorrelatedParent();
|
||||
if (correlatedRoot != null && root.getJoins() != null) {
|
||||
FromImpl join = (FromImpl) root.getJoins().iterator().next();
|
||||
if (join._member.fmd.getDeclaredTypeCode() ==
|
||||
JavaTypes.COLLECTION ||
|
||||
join._member.fmd.getDeclaredTypeCode() ==
|
||||
JavaTypes.MAP)
|
||||
return join._member.fmd.isElementCollection()
|
||||
? join._member.fmd.getEmbeddedMetaData()
|
||||
: join._member.fmd.getElement().getDeclaredTypeMetaData();
|
||||
return join._member.fmd.getDeclaredTypeMetaData();
|
||||
}
|
||||
return ((AbstractManagedType<?>)root.getModel()).meta;
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user