mirror of
https://github.com/apache/openjpa.git
synced 2025-03-06 16:39:11 +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.AbstractManagedType;
|
||||||
import org.apache.openjpa.persistence.meta.Members;
|
import org.apache.openjpa.persistence.meta.Members;
|
||||||
import org.apache.openjpa.persistence.meta.MetamodelImpl;
|
import org.apache.openjpa.persistence.meta.MetamodelImpl;
|
||||||
import org.apache.openjpa.persistence.meta.Types;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts expressions of a CriteriaQuery to kernel Expression.
|
* Converts expressions of a CriteriaQuery to kernel Expression.
|
||||||
@ -53,6 +52,7 @@ 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());
|
||||||
|
|
||||||
evalAccessPaths(exps, factory, q);
|
evalAccessPaths(exps, factory, q);
|
||||||
//exps.alias = null; // String
|
//exps.alias = null; // String
|
||||||
@ -181,10 +181,7 @@ public class CriteriaExpressionBuilder {
|
|||||||
.toKernelExpression(factory, model, q), filter);
|
.toKernelExpression(factory, model, q), filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (((RootImpl<?>)root).getCorrelatedParent() != null) {
|
((RootImpl)root).addToContext(factory, model, q);
|
||||||
filter = and(factory, ((RootImpl<?>)root)
|
|
||||||
.toKernelExpression(factory, model, q), filter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (where != null) {
|
if (where != null) {
|
||||||
filter = and(factory, where.toKernelExpression
|
filter = and(factory, where.toKernelExpression
|
||||||
|
@ -20,16 +20,14 @@ package org.apache.openjpa.persistence.criteria;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.persistence.Parameter;
|
import javax.persistence.criteria.AbstractQuery;
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
import javax.persistence.criteria.Expression;
|
import javax.persistence.criteria.Expression;
|
||||||
import javax.persistence.criteria.Order;
|
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.ExpressionFactory;
|
||||||
import org.apache.openjpa.kernel.exps.QueryExpressions;
|
import org.apache.openjpa.kernel.exps.QueryExpressions;
|
||||||
import org.apache.openjpa.kernel.exps.Value;
|
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.MetamodelImpl;
|
||||||
import org.apache.openjpa.persistence.meta.Types;
|
import org.apache.openjpa.persistence.meta.Types;
|
||||||
|
|
||||||
@ -73,7 +70,7 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
|
|||||||
private PredicateImpl _having;
|
private PredicateImpl _having;
|
||||||
private List<Subquery<?>> _subqueries;
|
private List<Subquery<?>> _subqueries;
|
||||||
private Boolean _distinct;
|
private Boolean _distinct;
|
||||||
private SubqueryImpl<?> _context;
|
private SubqueryImpl<?> _delegator;
|
||||||
|
|
||||||
// AliasContext
|
// AliasContext
|
||||||
private int aliasCount = 0;
|
private int aliasCount = 0;
|
||||||
@ -83,25 +80,38 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
|
|||||||
new HashMap<Selection<?>, Value>();
|
new HashMap<Selection<?>, Value>();
|
||||||
private Map<Selection<?>,Value> _values =
|
private Map<Selection<?>,Value> _values =
|
||||||
new HashMap<Selection<?>, Value>();
|
new HashMap<Selection<?>, Value>();
|
||||||
private Map<Selection<?>,String> _aliases =
|
private Map<Selection<?>,String> _aliases = null;
|
||||||
new HashMap<Selection<?>, String>();
|
|
||||||
|
// SubqueryContext
|
||||||
|
//private Stack<Context> _contexts = null;
|
||||||
|
|
||||||
public CriteriaQueryImpl(MetamodelImpl model) {
|
public CriteriaQueryImpl(MetamodelImpl model) {
|
||||||
this._model = model;
|
this._model = model;
|
||||||
|
_aliases = new HashMap<Selection<?>, String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContext(SubqueryImpl<?> context) {
|
public CriteriaQueryImpl(MetamodelImpl model, SubqueryImpl<?> delegator) {
|
||||||
_context = context;
|
this._model = model;
|
||||||
|
_delegator = delegator;
|
||||||
|
_aliases = getAliases();
|
||||||
}
|
}
|
||||||
|
|
||||||
public SubqueryImpl<?> getContext() {
|
public void setDelegator(SubqueryImpl<?> delegator) {
|
||||||
return _context;
|
_delegator = delegator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubqueryImpl<?> getDelegator() {
|
||||||
|
return _delegator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MetamodelImpl getMetamodel() {
|
public MetamodelImpl getMetamodel() {
|
||||||
return _model;
|
return _model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//public Stack<Context> getContexts() {
|
||||||
|
// return _contexts;
|
||||||
|
//}
|
||||||
|
|
||||||
public CriteriaQuery distinct(boolean distinct) {
|
public CriteriaQuery distinct(boolean distinct) {
|
||||||
_distinct = distinct;
|
_distinct = distinct;
|
||||||
return this;
|
return this;
|
||||||
@ -319,6 +329,9 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
|
|||||||
* receiver with the help of the given {@link ExpressionFactory}.
|
* receiver with the help of the given {@link ExpressionFactory}.
|
||||||
*/
|
*/
|
||||||
QueryExpressions getQueryExpressions(ExpressionFactory factory) {
|
QueryExpressions getQueryExpressions(ExpressionFactory factory) {
|
||||||
|
//_contexts = new Stack<Context>();
|
||||||
|
//Context context = new Context(null, null, null);
|
||||||
|
// _contexts.push(context);
|
||||||
return new CriteriaExpressionBuilder()
|
return new CriteriaExpressionBuilder()
|
||||||
.getQueryExpressions(factory, this);
|
.getQueryExpressions(factory, this);
|
||||||
}
|
}
|
||||||
@ -328,6 +341,30 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
|
|||||||
throw new IllegalStateException("no root is set");
|
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
|
// AliasContext management
|
||||||
//
|
//
|
||||||
@ -390,6 +427,8 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
|
|||||||
_variables.put(node, var);
|
_variables.put(node, var);
|
||||||
_values.put(node, path);
|
_values.put(node, path);
|
||||||
_aliases.put(node, alias);
|
_aliases.put(node, alias);
|
||||||
|
//_contexts.peek().addSchema(alias, var.getMetaData());
|
||||||
|
//_contexts.peek().addVariable(alias, var);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRegistered(Selection<?> selection) {
|
public boolean isRegistered(Selection<?> selection) {
|
||||||
|
@ -29,7 +29,6 @@ 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.SetJoin;
|
import javax.persistence.criteria.SetJoin;
|
||||||
import javax.persistence.metamodel.Attribute;
|
|
||||||
import javax.persistence.metamodel.CollectionAttribute;
|
import javax.persistence.metamodel.CollectionAttribute;
|
||||||
import javax.persistence.metamodel.ListAttribute;
|
import javax.persistence.metamodel.ListAttribute;
|
||||||
import javax.persistence.metamodel.MapAttribute;
|
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.AbstractManagedType;
|
||||||
import org.apache.openjpa.persistence.meta.Members;
|
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,
|
* 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) {
|
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) {
|
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) {
|
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) {
|
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>
|
public static class SingularJoin<Z,X> extends FromImpl<Z,X>
|
||||||
implements Join<Z,X>{
|
implements Join<Z,X>{
|
||||||
private final JoinType joinType;
|
private final JoinType joinType;
|
||||||
|
private boolean allowNull = false;
|
||||||
|
|
||||||
public SingularJoin(FromImpl<?,Z> from,
|
public SingularJoin(FromImpl<?,Z> from,
|
||||||
Members.SingularAttributeImpl<? super Z, X> member, JoinType jt) {
|
Members.SingularAttributeImpl<? super Z, X> member, JoinType jt) {
|
||||||
super(from, member, member.getJavaType());
|
super(from, member, member.getJavaType());
|
||||||
joinType = jt;
|
joinType = jt;
|
||||||
|
allowNull = joinType != JoinType.INNER;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JoinType getJoinType() {
|
public JoinType getJoinType() {
|
||||||
@ -85,16 +87,26 @@ 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 = _member.fmd.getDeclaredTypeMetaData();
|
||||||
|
org.apache.openjpa.kernel.exps.Path path = null;
|
||||||
|
SubqueryImpl<?> subquery = c.getDelegator();
|
||||||
|
PathImpl<?,?> parent = getInnermostParentPath();
|
||||||
if (c.isRegistered(this))
|
if (c.isRegistered(this))
|
||||||
return c.getValue(this);
|
return c.getValue(this);
|
||||||
boolean allowNull = joinType != JoinType.INNER;
|
else if (parent.inSubquery(subquery)) {
|
||||||
ClassMetaData meta = _member.fmd.getDeclaredTypeMetaData();
|
org.apache.openjpa.kernel.exps.Subquery subQ =
|
||||||
org.apache.openjpa.kernel.exps.Path path =
|
subquery.getSubQ();
|
||||||
|
path = factory.newPath(subQ);
|
||||||
|
path.setMetaData(subQ.getMetaData());
|
||||||
|
//path.setSchemaAlias(c.getAlias(this));
|
||||||
|
} else {
|
||||||
|
path =
|
||||||
(org.apache.openjpa.kernel.exps.Path)
|
(org.apache.openjpa.kernel.exps.Path)
|
||||||
_parent.toValue(factory, model, c);
|
_parent.toValue(factory, model, c);
|
||||||
path.get(_member.fmd, allowNull);
|
path.get(_member.fmd, allowNull);
|
||||||
path.setMetaData(meta);
|
path.setMetaData(meta);
|
||||||
path.setImplicitType(meta.getDescribedType());
|
path.setImplicitType(meta.getDescribedType());
|
||||||
|
}
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +116,23 @@ public abstract class Joins {
|
|||||||
CriteriaQueryImpl c) {
|
CriteriaQueryImpl c) {
|
||||||
ClassMetaData meta = _member.fmd.getDeclaredTypeMetaData();
|
ClassMetaData meta = _member.fmd.getDeclaredTypeMetaData();
|
||||||
org.apache.openjpa.kernel.exps.Path path = null;
|
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);
|
Value var = c.getVariable(_parent);
|
||||||
path = factory.newPath(var);
|
path = factory.newPath(var);
|
||||||
path.setMetaData(meta);
|
path.setMetaData(meta);
|
||||||
@ -112,12 +140,13 @@ public abstract class Joins {
|
|||||||
} else
|
} else
|
||||||
path =
|
path =
|
||||||
(org.apache.openjpa.kernel.exps.Path)toValue(factory, model, c);
|
(org.apache.openjpa.kernel.exps.Path)toValue(factory, model, c);
|
||||||
|
org.apache.openjpa.kernel.exps.Expression join = null;
|
||||||
|
if (bind) {
|
||||||
Value var = factory.newBoundVariable(c.getAlias(this),
|
Value var = factory.newBoundVariable(c.getAlias(this),
|
||||||
meta.getDescribedType());
|
meta.getDescribedType());
|
||||||
org.apache.openjpa.kernel.exps.Expression join = factory
|
join = factory.bindVariable(var, path);
|
||||||
.bindVariable(var, path);
|
|
||||||
c.registerVariable(this, var, path);
|
c.registerVariable(this, var, path);
|
||||||
org.apache.openjpa.kernel.exps.Expression filter = null;
|
}
|
||||||
if (getJoins() != null) {
|
if (getJoins() != null) {
|
||||||
for (Join<?, ?> join1 : getJoins()) {
|
for (Join<?, ?> join1 : getJoins()) {
|
||||||
filter = CriteriaExpressionBuilder.and(factory,
|
filter = CriteriaExpressionBuilder.and(factory,
|
||||||
@ -125,7 +154,22 @@ public abstract class Joins {
|
|||||||
toKernelExpression(factory, model, c), filter);
|
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>
|
public static abstract class AbstractCollection<Z,C,E> extends FromImpl<Z,E>
|
||||||
implements PluralJoin<Z, C, E> {
|
implements PluralJoin<Z, C, E> {
|
||||||
final JoinType joinType;
|
final JoinType joinType;
|
||||||
|
boolean allowNull = false;
|
||||||
|
|
||||||
public AbstractCollection(FromImpl<?,Z> from,
|
public AbstractCollection(FromImpl<?,Z> from,
|
||||||
Members.PluralAttributeImpl<? super Z, C, E> member, JoinType jt) {
|
Members.PluralAttributeImpl<? super Z, C, E> member, JoinType jt) {
|
||||||
super(from, member, member.getBindableJavaType());
|
super(from, member, member.getBindableJavaType());
|
||||||
joinType = jt;
|
joinType = jt;
|
||||||
|
allowNull = joinType != JoinType.INNER;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JoinType getJoinType() {
|
public JoinType getJoinType() {
|
||||||
@ -168,19 +214,32 @@ public abstract class Joins {
|
|||||||
return (PluralAttribute<? super Z, C, E>) _member.getType();
|
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).
|
* Convert this path to a kernel path (value).
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
|
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
|
||||||
CriteriaQueryImpl c) {
|
CriteriaQueryImpl c) {
|
||||||
boolean allowNull = joinType != JoinType.INNER;
|
ClassMetaData meta = getMemberClassMetaData();
|
||||||
ClassMetaData meta = _member.fmd.getElement()
|
|
||||||
.getDeclaredTypeMetaData();
|
|
||||||
org.apache.openjpa.kernel.exps.Path path = null;
|
org.apache.openjpa.kernel.exps.Path path = null;
|
||||||
|
SubqueryImpl<?> subquery = c.getDelegator();
|
||||||
|
PathImpl<?,?> parent = getInnermostParentPath();
|
||||||
|
|
||||||
if (c.isRegistered(this)) {
|
if (c.isRegistered(this)) {
|
||||||
Value var = c.getVariable(this);
|
Value var = c.getVariable(this);
|
||||||
path = factory.newPath(var);
|
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 {
|
} else {
|
||||||
path = (org.apache.openjpa.kernel.exps.Path)
|
path = (org.apache.openjpa.kernel.exps.Path)
|
||||||
_parent.toValue(factory, model, c);
|
_parent.toValue(factory, model, c);
|
||||||
@ -197,12 +256,25 @@ public abstract class Joins {
|
|||||||
public org.apache.openjpa.kernel.exps.Expression toKernelExpression(
|
public org.apache.openjpa.kernel.exps.Expression toKernelExpression(
|
||||||
ExpressionFactory factory, MetamodelImpl model,
|
ExpressionFactory factory, MetamodelImpl model,
|
||||||
CriteriaQueryImpl c) {
|
CriteriaQueryImpl c) {
|
||||||
ClassMetaData meta = _member.fmd.isElementCollection()
|
ClassMetaData meta = getMemberClassMetaData();
|
||||||
? _member.fmd.getEmbeddedMetaData()
|
|
||||||
: _member.fmd.getElement().getDeclaredTypeMetaData();
|
|
||||||
|
|
||||||
org.apache.openjpa.kernel.exps.Path path = null;
|
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);
|
Value var = c.getVariable(_parent);
|
||||||
path = factory.newPath(var);
|
path = factory.newPath(var);
|
||||||
path.setMetaData(meta);
|
path.setMetaData(meta);
|
||||||
@ -211,12 +283,13 @@ public abstract class Joins {
|
|||||||
path = (org.apache.openjpa.kernel.exps.Path)
|
path = (org.apache.openjpa.kernel.exps.Path)
|
||||||
toValue(factory, model, c);
|
toValue(factory, model, c);
|
||||||
|
|
||||||
|
org.apache.openjpa.kernel.exps.Expression join = null;
|
||||||
|
if (bind) {
|
||||||
Value var = factory.newBoundVariable(c.getAlias(this),
|
Value var = factory.newBoundVariable(c.getAlias(this),
|
||||||
meta.getDescribedType());
|
meta.getDescribedType());
|
||||||
org.apache.openjpa.kernel.exps.Expression join =
|
join = factory.bindVariable(var, path);
|
||||||
factory.bindVariable(var, path);
|
|
||||||
c.registerVariable(this, var, path);
|
c.registerVariable(this, var, path);
|
||||||
org.apache.openjpa.kernel.exps.Expression filter = null;
|
}
|
||||||
if (getJoins() != null) {
|
if (getJoins() != null) {
|
||||||
for (Join<?, ?> join1 : getJoins()) {
|
for (Join<?, ?> join1 : getJoins()) {
|
||||||
filter = CriteriaExpressionBuilder.and(factory,
|
filter = CriteriaExpressionBuilder.and(factory,
|
||||||
@ -224,7 +297,21 @@ public abstract class Joins {
|
|||||||
toKernelExpression(factory, model, c), filter);
|
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.Join;
|
||||||
import javax.persistence.criteria.JoinType;
|
import javax.persistence.criteria.JoinType;
|
||||||
import javax.persistence.criteria.Path;
|
import javax.persistence.criteria.Path;
|
||||||
import javax.persistence.metamodel.Attribute;
|
|
||||||
import javax.persistence.metamodel.Bindable;
|
import javax.persistence.metamodel.Bindable;
|
||||||
import javax.persistence.metamodel.ManagedType;
|
import javax.persistence.metamodel.ManagedType;
|
||||||
import javax.persistence.metamodel.MapAttribute;
|
import javax.persistence.metamodel.MapAttribute;
|
||||||
@ -58,6 +57,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. 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
|
||||||
@ -121,6 +121,13 @@ public class PathImpl<Z,X> extends ExpressionImpl<X> implements Path<X> {
|
|||||||
parent._member);
|
parent._member);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCorrelatedParent(PathImpl<?,?> correlatedParent) {
|
||||||
|
_correlatedParent = correlatedParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PathImpl<?,?> getCorrelatedParent() {
|
||||||
|
return _correlatedParent;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert this path to a kernel path.
|
* 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))
|
if (q.isRegistered(this))
|
||||||
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.getContext();
|
SubqueryImpl<?> subquery = q.getDelegator();
|
||||||
PathImpl<?,?> parent = getInnermostParentPath();
|
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();
|
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());
|
||||||
boolean allowNull = false;
|
//path.setSchemaAlias(q.getAlias(_parent));
|
||||||
path.get(_member.fmd, allowNull);
|
traversePath(_parent, path, _member.fmd);
|
||||||
} else if (_parent != null) {
|
} 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)
|
path = (org.apache.openjpa.kernel.exps.Path)
|
||||||
_parent.toValue(factory, model, q);
|
_parent.toValue(factory, model, q);
|
||||||
}
|
|
||||||
boolean allowNull = _parent instanceof Join
|
|
||||||
&& ((Join<?,?>)_parent).getJoinType() != JoinType.INNER;
|
|
||||||
path.get(_member.fmd, allowNull);
|
path.get(_member.fmd, allowNull);
|
||||||
} else {
|
} else if (_parent == null) {
|
||||||
path = factory.newPath();
|
path = factory.newPath();
|
||||||
path.setMetaData(model.repos.getCachedMetaData(getJavaType()));
|
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);
|
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
|
* Return the path corresponding to the referenced
|
||||||
* single-valued attribute.
|
* single-valued attribute.
|
||||||
|
@ -22,7 +22,7 @@ package org.apache.openjpa.persistence.criteria;
|
|||||||
import javax.persistence.criteria.Root;
|
import javax.persistence.criteria.Root;
|
||||||
import javax.persistence.metamodel.EntityType;
|
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.ExpressionFactory;
|
||||||
import org.apache.openjpa.kernel.exps.Path;
|
import org.apache.openjpa.kernel.exps.Path;
|
||||||
import org.apache.openjpa.kernel.exps.Subquery;
|
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> {
|
public class RootImpl<X> extends FromImpl<X,X> implements Root<X> {
|
||||||
private final Types.Entity<X> _entity;
|
private final Types.Entity<X> _entity;
|
||||||
private RootImpl<X> _correlatedParent;
|
|
||||||
|
|
||||||
public RootImpl(Types.Entity<X> type) {
|
public RootImpl(Types.Entity<X> type) {
|
||||||
super(type);
|
super(type);
|
||||||
@ -50,12 +49,18 @@ public class RootImpl<X> extends FromImpl<X,X> implements Root<X> {
|
|||||||
return _entity;
|
return _entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCorrelatedParent(RootImpl<X> correlatedParent) {
|
public void addToContext(ExpressionFactory factory, MetamodelImpl model,
|
||||||
_correlatedParent = correlatedParent;
|
CriteriaQueryImpl q) {
|
||||||
}
|
String alias = q.getAlias(this);
|
||||||
|
Value var = factory.newBoundVariable(alias,
|
||||||
public RootImpl<X> getCorrelatedParent() {
|
AbstractExpressionBuilder.TYPE_OBJECT);
|
||||||
return _correlatedParent;
|
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
|
@Override
|
||||||
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
|
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
|
||||||
CriteriaQueryImpl c) {
|
CriteriaQueryImpl c) {
|
||||||
SubqueryImpl<?> subquery = c.getContext();
|
SubqueryImpl<?> subquery = c.getDelegator();
|
||||||
Path var = null;
|
Path var = null;
|
||||||
if (inSubquery(subquery)) {
|
if (inSubquery(subquery)) {
|
||||||
Subquery subQ = subquery.getSubQ();
|
Subquery subQ = subquery.getSubQ();
|
||||||
@ -86,12 +91,7 @@ public class RootImpl<X> extends FromImpl<X,X> implements Root<X> {
|
|||||||
Value path = toValue(factory, model, c);
|
Value path = toValue(factory, model, c);
|
||||||
Value var = factory.newBoundVariable(c.getAlias(this),
|
Value var = factory.newBoundVariable(c.getAlias(this),
|
||||||
_entity.meta.getDescribedType());
|
_entity.meta.getDescribedType());
|
||||||
Expression exp = factory.bindVariable(var, path);
|
return factory.bindVariable(var, path);
|
||||||
|
|
||||||
if (_correlatedParent == null)
|
|
||||||
return exp;
|
|
||||||
Value path1 = _correlatedParent.toValue(factory, model, c);
|
|
||||||
return factory.equal(path1, path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
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.exps.Value;
|
||||||
import org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder;
|
import org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder;
|
||||||
import org.apache.openjpa.meta.ClassMetaData;
|
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.AbstractManagedType;
|
||||||
import org.apache.openjpa.persistence.meta.MetamodelImpl;
|
import org.apache.openjpa.persistence.meta.MetamodelImpl;
|
||||||
import org.apache.openjpa.persistence.meta.Types;
|
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.
|
* @param <T> the type selected by this subquery.
|
||||||
*/
|
*/
|
||||||
public class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
|
public class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
|
||||||
private final CriteriaQueryImpl _parent;
|
private final AbstractQuery _parent;
|
||||||
private final CriteriaQueryImpl _delegate;
|
private final CriteriaQueryImpl _delegate;
|
||||||
|
private final MetamodelImpl _model;
|
||||||
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;
|
||||||
|
|
||||||
public SubqueryImpl(Class<T> cls, CriteriaQueryImpl parent) {
|
public SubqueryImpl(Class<T> cls, AbstractQuery parent) {
|
||||||
super(cls);
|
super(cls);
|
||||||
_parent = parent;
|
_parent = parent;
|
||||||
_delegate = new CriteriaQueryImpl(parent.getMetamodel());
|
if (parent instanceof CriteriaQueryImpl)
|
||||||
_delegate.setContext(this);
|
_model = ((CriteriaQueryImpl)parent).getMetamodel();
|
||||||
|
else if (parent instanceof SubqueryImpl)
|
||||||
|
_model = ((SubqueryImpl)parent).getMetamodel();
|
||||||
|
else
|
||||||
|
_model = null;
|
||||||
|
|
||||||
|
_delegate = new CriteriaQueryImpl(_model, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractQuery getParent() {
|
public AbstractQuery getParent() {
|
||||||
return _parent;
|
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) {
|
public Subquery<T> select(Expression<T> expression) {
|
||||||
_select = expression;
|
_select = expression;
|
||||||
_delegate.select(expression);
|
_delegate.select(expression);
|
||||||
@ -201,15 +226,41 @@ public class SubqueryImpl<T> extends ExpressionImpl<T> implements Subquery<T> {
|
|||||||
final boolean subclasses = true;
|
final boolean subclasses = true;
|
||||||
CriteriaExpressionBuilder queryEval = new CriteriaExpressionBuilder();
|
CriteriaExpressionBuilder queryEval = new CriteriaExpressionBuilder();
|
||||||
String alias = q.getAlias(this);
|
String alias = q.getAlias(this);
|
||||||
ClassMetaData candidate =
|
ClassMetaData candidate = getCandidate();
|
||||||
((AbstractManagedType<?>)getRoot().getModel()).meta;
|
|
||||||
_subq = factory.newSubquery(candidate, subclasses, alias);
|
_subq = factory.newSubquery(candidate, subclasses, alias);
|
||||||
_subq.setMetaData(candidate);
|
_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,
|
QueryExpressions subexp = queryEval.getQueryExpressions(factory,
|
||||||
_delegate);
|
_delegate);
|
||||||
_subq.setQueryExpressions(subexp);
|
_subq.setQueryExpressions(subexp);
|
||||||
if (subexp.projections.length > 0)
|
if (subexp.projections.length > 0)
|
||||||
JPQLExpressionBuilder.checkEmbeddable(subexp.projections[0], null);
|
JPQLExpressionBuilder.checkEmbeddable(subexp.projections[0], null);
|
||||||
|
//contexts.pop();
|
||||||
return _subq;
|
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