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:
Fay Wang 2009-06-24 06:02:17 +00:00
parent 636bd5f213
commit e57f032626
7 changed files with 288 additions and 94 deletions

View File

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

View File

@ -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) {

View File

@ -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) {

View File

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

View File

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

View File

@ -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() {

View File

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