OPENJPA-1013: parameter support for Criteria Query

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@775997 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Fay Wang 2009-05-18 15:56:35 +00:00
parent 7b581bf651
commit 76764564b1
8 changed files with 284 additions and 135 deletions

View File

@ -55,17 +55,17 @@ public abstract class AbstractExpressionBuilder {
protected static final int EX_UNSUPPORTED = 2;
// common implicit type settings
protected static final Class<Object> TYPE_OBJECT = Object.class;
protected static final Class<String> TYPE_STRING = String.class;
protected static final Class<Character> TYPE_CHAR_OBJ = Character.class;
protected static final Class<Number> TYPE_NUMBER = Number.class;
protected static final Class<Collection> TYPE_COLLECTION = Collection.class;
protected static final Class<Map> TYPE_MAP = Map.class;
public static final Class<Object> TYPE_OBJECT = Object.class;
public static final Class<String> TYPE_STRING = String.class;
public static final Class<Character> TYPE_CHAR_OBJ = Character.class;
public static final Class<Number> TYPE_NUMBER = Number.class;
public static final Class<Collection> TYPE_COLLECTION = Collection.class;
public static final Class<Map> TYPE_MAP = Map.class;
// contains types for setImplicitTypes
protected static final int CONTAINS_TYPE_ELEMENT = 1;
protected static final int CONTAINS_TYPE_KEY = 2;
protected static final int CONTAINS_TYPE_VALUE = 3;
public static final int CONTAINS_TYPE_ELEMENT = 1;
public static final int CONTAINS_TYPE_KEY = 2;
public static final int CONTAINS_TYPE_VALUE = 3;
private static final Localizer _loc = Localizer.forPackage
(AbstractExpressionBuilder.class);
@ -366,7 +366,7 @@ public abstract class AbstractExpressionBuilder {
/**
* Perform conversions to make values compatible.
*/
private void convertTypes(Value val1, Value val2) {
public static void convertTypes(Value val1, Value val2) {
Class<?> t1 = val1.getType();
Class<?> t2 = val2.getType();
@ -415,7 +415,7 @@ public abstract class AbstractExpressionBuilder {
/**
* Perform conversions to make values compatible.
*/
private void convertTypesQuotedNumbers(Value val1, Value val2) {
public static void convertTypesQuotedNumbers(Value val1, Value val2) {
Class<?> t1 = val1.getType();
Class<?> t2 = val2.getType();
@ -457,7 +457,7 @@ public abstract class AbstractExpressionBuilder {
/**
* Return true if given class can be used as a number.
*/
private static boolean isNumeric(Class<?> type) {
public static boolean isNumeric(Class<?> type) {
type = Filters.wrap(type);
return Number.class.isAssignableFrom(type)
|| type == Character.TYPE || type == TYPE_CHAR_OBJ;

View File

@ -413,33 +413,32 @@ public class TestTypesafeCriteria extends SQLListenerTestCase {
assertEquivalence(q, jpql);
}
@AllowFailure
public void testParameters1() {
String jpql = "SELECT c FROM Customer c Where c.status = :stat";
CriteriaQuery q = cb.create();
Root<Customer> c = q.from(Customer.class);
Parameter<Integer> param = cb.parameter(Integer.class);
Parameter<Integer> param = cb.parameter(Integer.class, "stat");
q.select(c).where(cb.equal(c.get(Customer_.status), param));
assertEquivalence(q, jpql, new String[]{"stat"}, new Object[] {1});
}
@AllowFailure
public void testParameters2() {
String jpql = "SELECT c FROM Customer c Where c.status = :stat AND c.name = :name";
String jpql = "SELECT c FROM Customer c Where c.status = :stat AND " +
"c.name = :name";
CriteriaQuery q = cb.create();
Root<Customer> c = q.from(Customer.class);
Parameter<Integer> param1 = cb.parameter(Integer.class, "stat");
Parameter<String> param2 = cb.parameter(String.class, "name");
q.select(c).where(cb.equal(c.get(Customer_.status), param1),
cb.equal(c.get(Customer_.name), param2));
q.select(c).where(cb.and(cb.equal(c.get(Customer_.status), param1),
cb.equal(c.get(Customer_.name), param2)));
assertEquivalence(q, jpql, new String[] { "stat", "name" }, new Object[] { 1, "test" });
assertEquivalence(q, jpql, new String[] { "stat", "name" },
new Object[] { 1, "test" });
}
@AllowFailure
public void testParameters3() {
String jpql = "SELECT c FROM Customer c Where c.status = :1";
String jpql = "SELECT c FROM Customer c Where c.status = ?1";
CriteriaQuery q = cb.create();
Root<Customer> c = q.from(Customer.class);
Parameter<Integer> param = cb.parameter(Integer.class);
@ -447,31 +446,31 @@ public class TestTypesafeCriteria extends SQLListenerTestCase {
assertEquivalence(q, jpql, new Object[] { 1 });
}
@AllowFailure
public void testParameters4() {
String jpql = "SELECT c FROM Customer c Where c.status = :1 AND c.name = :2";
String jpql = "SELECT c FROM Customer c Where c.status = ?1 AND " +
"c.name = ?2";
CriteriaQuery q = cb.create();
Root<Customer> c = q.from(Customer.class);
Parameter<Integer> param1 = cb.parameter(Integer.class);
Parameter<Integer> param2 = cb.parameter(Integer.class);
q.select(c).where(cb.equal(c.get(Customer_.status), param1),
cb.equal(c.get(Customer_.name), param2));
q.select(c).where(cb.and(cb.equal(c.get(Customer_.status), param1),
cb.equal(c.get(Customer_.name), param2)));
assertEquivalence(q, jpql, new Object[] { 1, "test" });
}
// collection-valued input parameter
// do not support collection-valued input parameter
@AllowFailure
public void testParameters5() {
String jpql = "SELECT c FROM Customer c Where c.status IN (:coll)";
CriteriaQuery q = cb.create();
Root<Customer> c = q.from(Customer.class);
Parameter<List> param1 = cb.parameter(List.class);
q.select(c).where(cb.equal(c.get(Customer_.status), param1));
//q.select(c).where(cb.in(c.get(Customer_.status)).value(params1));
List vals = new ArrayList();
vals.add(1);
vals.add(2);
assertEquivalence(q, jpql, new String[] {"coll"}, new Object[] {vals});
//assertEquivalence(q, jpql, new String[] {"coll"}, new Object[] {vals});
}
@AllowFailure

View File

@ -34,10 +34,14 @@ import javax.persistence.criteria.Selection;
import javax.persistence.criteria.Subquery;
import javax.persistence.metamodel.Entity;
import org.apache.commons.collections.map.LinkedMap;
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.QueryExpressions;
import org.apache.openjpa.kernel.exps.Value;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.persistence.meta.MetamodelImpl;
import org.apache.openjpa.persistence.meta.Types;
@ -57,6 +61,7 @@ public class CriteriaQueryImpl implements CriteriaQuery {
private List<Expression<?>> _groups;
private PredicateImpl _having;
private Boolean _distinct;
private LinkedMap _parameterTypes;
public CriteriaQueryImpl(MetamodelImpl model) {
this._model = model;
@ -164,6 +169,14 @@ public class CriteriaQueryImpl implements CriteriaQuery {
return null;
}
public LinkedMap getParameterTypes() {
return _parameterTypes;
}
public void setParameterTypes(LinkedMap parameterTypes) {
_parameterTypes = parameterTypes;
}
/**
* Populate kernel expressions.
*/
@ -184,11 +197,11 @@ public class CriteriaQueryImpl implements CriteriaQuery {
// exps.fetchInnerPaths = null; // String[]
// exps.fetchPaths = null; // String[]
exps.filter = _where == null ? factory.emptyExpression()
: _where.toKernelExpression(factory, _model);
: _where.toKernelExpression(factory, _model, this);
evalGrouping(exps, factory);
exps.having = _having == null ? factory.emptyExpression()
: _having.toKernelExpression(factory, _model);
: _having.toKernelExpression(factory, _model, this);
evalOrdering(exps, factory);
// exps.operation = QueryOperations.OP_SELECT;
@ -199,6 +212,8 @@ public class CriteriaQueryImpl implements CriteriaQuery {
exps.projections = toValues(factory, getSelectionList());
// exps.range = null; // Value[]
// exps.resultClass = null; // Class
if (_parameterTypes != null)
exps.parameterTypes = _parameterTypes;
return exps;
}
@ -214,7 +229,7 @@ public class CriteriaQueryImpl implements CriteriaQuery {
OrderImpl order = (OrderImpl)_orders.get(i);
//Expression<? extends Comparable> expr = order.getExpression();
//exps.ordering[i] = Expressions.toValue(
// (ExpressionImpl<?>)expr, factory, _model);
// (ExpressionImpl<?>)expr, factory, _model, this);
//exps.orderingClauses[i] = assemble(firstChild);
//exps.orderingAliases[i] = firstChild.text;
@ -231,7 +246,7 @@ public class CriteriaQueryImpl implements CriteriaQuery {
for (int i = 0; i < groupByCount; i++) {
Expression<?> groupBy = _groups.get(i);
exps.grouping[i] = Expressions.toValue(
(ExpressionImpl<?>)groupBy, factory, _model);;
(ExpressionImpl<?>)groupBy, factory, _model, this);;
}
}
@ -244,9 +259,68 @@ public class CriteriaQueryImpl implements CriteriaQuery {
Value[] result = new Value[sels.size()];
int i = 0;
for (Selection<?> s : sels) {
result[i++] = ((ExpressionImpl<?>)s).toValue(factory, _model);
result[i++] = ((ExpressionImpl<?>)s).toValue(factory, _model,
this);
}
return result;
}
void setImplicitTypes(Value val1, Value val2, Class<?> expected) {
Class<?> c1 = val1.getType();
Class<?> c2 = val2.getType();
boolean o1 = c1 == AbstractExpressionBuilder.TYPE_OBJECT;
boolean o2 = c2 == AbstractExpressionBuilder.TYPE_OBJECT;
if (o1 && !o2) {
val1.setImplicitType(c2);
if (val1.getMetaData() == null && !val1.isXPath())
val1.setMetaData(val2.getMetaData());
} else if (!o1 && o2) {
val2.setImplicitType(c1);
if (val2.getMetaData() == null && !val1.isXPath())
val2.setMetaData(val1.getMetaData());
} else if (o1 && o2 && expected != null) {
// we never expect a pc type, so don't bother with metadata
val1.setImplicitType(expected);
val2.setImplicitType(expected);
} else if (AbstractExpressionBuilder.isNumeric(val1.getType())
!= AbstractExpressionBuilder.isNumeric(val2.getType())) {
AbstractExpressionBuilder.convertTypes(val1, val2);
}
// as well as setting the types for conversions, we also need to
// ensure that any parameters are declared with the correct type,
// since the JPA spec expects that these will be validated
org.apache.openjpa.kernel.exps.Parameter param =
val1 instanceof org.apache.openjpa.kernel.exps.Parameter ?
(org.apache.openjpa.kernel.exps.Parameter) val1
: val2 instanceof org.apache.openjpa.kernel.exps.Parameter ?
(org.apache.openjpa.kernel.exps.Parameter) val2 : null;
Path path = val1 instanceof Path ? (Path) val1
: val2 instanceof Path ? (Path) val2 : null;
// we only check for parameter-to-path comparisons
if (param == null || path == null || _parameterTypes == null)
return;
FieldMetaData fmd = path.last();
if (fmd == null)
return;
//TODO:
//if (expected == null)
// checkEmbeddable(path);
Class<?> type = path.getType();
if (type == null)
return;
Object paramKey = param.getParameterKey();
if (paramKey == null)
return;
// make sure we have already declared the parameter
if (_parameterTypes.containsKey(paramKey))
_parameterTypes.put(paramKey, type);
}
}

View File

@ -21,6 +21,7 @@ package org.apache.openjpa.persistence.criteria;
import java.util.Collection;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.QueryBuilder.In;
@ -39,12 +40,14 @@ import org.apache.openjpa.persistence.meta.MetamodelImpl;
public abstract class ExpressionImpl<X> extends SelectionImpl<X>
implements Expression<X> {
Value toValue(ExpressionFactory factory, MetamodelImpl model) {
Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
throw new AbstractMethodError(this.getClass().getName());
}
org.apache.openjpa.kernel.exps.Expression toKernelExpression(
ExpressionFactory factory, MetamodelImpl model) {
ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
throw new AbstractMethodError(this.getClass().getName());
}

View File

@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.QueryBuilder;
@ -38,8 +39,8 @@ import org.apache.openjpa.persistence.meta.MetamodelImpl;
public class Expressions {
static Value toValue(ExpressionImpl<?> e, ExpressionFactory factory,
MetamodelImpl model) {
Value v = e.toValue(factory, model);
MetamodelImpl model, CriteriaQuery q) {
Value v = e.toValue(factory, model, q);
return v;
}
@ -107,8 +108,9 @@ public class Expressions {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
return factory.abs(Expressions.toValue(e, factory, model));
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
return factory.abs(Expressions.toValue(e, factory, model, q));
}
}
@ -125,8 +127,9 @@ public class Expressions {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
Value v = factory.count(Expressions.toValue(e, factory, model));
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
Value v = factory.count(Expressions.toValue(e, factory, model, q));
return _distinct ? factory.distinct(v) : v;
}
}
@ -137,8 +140,9 @@ public class Expressions {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
return factory.avg(Expressions.toValue(e, factory, model));
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
return factory.avg(Expressions.toValue(e, factory, model, q));
}
}
@ -148,8 +152,9 @@ public class Expressions {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
return factory.sqrt(Expressions.toValue(e, factory, model));
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
return factory.sqrt(Expressions.toValue(e, factory, model, q));
}
}
@ -159,8 +164,9 @@ public class Expressions {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
return factory.max(Expressions.toValue(e, factory, model));
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
return factory.max(Expressions.toValue(e, factory, model, q));
}
}
@ -170,8 +176,9 @@ public class Expressions {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
return factory.min(Expressions.toValue(e, factory, model));
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
return factory.min(Expressions.toValue(e, factory, model, q));
}
}
@ -185,8 +192,9 @@ public class Expressions {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
return factory.size(Expressions.toValue(e, factory, model));
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
return factory.size(Expressions.toValue(e, factory, model, q));
}
}
@ -197,8 +205,9 @@ public class Expressions {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
return factory.cast(Expressions.toValue(e, factory, model), b);
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
return factory.cast(Expressions.toValue(e, factory, model, q), b);
}
}
public static class Concat extends BinarayFunctionalExpression<String> {
@ -215,10 +224,11 @@ public class Expressions {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
return factory.concat(
Expressions.toValue(e1, factory, model),
Expressions.toValue(e2, factory, model));
Expressions.toValue(e1, factory, model, q),
Expressions.toValue(e2, factory, model, q));
}
}
@ -246,11 +256,12 @@ public class Expressions {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
return JPQLExpressionBuilder.convertSubstringArguments(factory,
Expressions.toValue(e, factory, model),
from == null ? null : from.toValue(factory, model),
len == null ? null : len.toValue(factory, model));
Expressions.toValue(e, factory, model, q),
from == null ? null : from.toValue(factory, model, q),
len == null ? null : len.toValue(factory, model, q));
}
}
@ -286,7 +297,8 @@ public class Expressions {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
Boolean spec = null;
if (ts != null) {
switch (ts) {
@ -296,8 +308,8 @@ public class Expressions {
}
}
return factory.trim(
Expressions.toValue(e1, factory, model),
Expressions.toValue(e2, factory, model), spec);
Expressions.toValue(e1, factory, model, q),
Expressions.toValue(e2, factory, model, q), spec);
}
}
@ -324,12 +336,13 @@ public class Expressions {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
return (e2 == null)
? factory.sum(Expressions.toValue(e1, factory, model))
? factory.sum(Expressions.toValue(e1, factory, model, q))
: factory.add(
Expressions.toValue(e1, factory, model),
Expressions.toValue(e2, factory, model));
Expressions.toValue(e1, factory, model, q),
Expressions.toValue(e2, factory, model, q));
}
}
@ -349,10 +362,11 @@ public class Expressions {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
return factory.multiply(
Expressions.toValue(e1, factory, model),
Expressions.toValue(e2, factory, model));
Expressions.toValue(e1, factory, model, q),
Expressions.toValue(e2, factory, model, q));
}
}
@ -372,10 +386,11 @@ public class Expressions {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
return factory.subtract(
Expressions.toValue(e1, factory, model),
Expressions.toValue(e2, factory, model));
Expressions.toValue(e1, factory, model, q),
Expressions.toValue(e2, factory, model, q));
}
}
@ -396,10 +411,11 @@ public class Expressions {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
return factory.divide(
Expressions.toValue(e1, factory, model),
Expressions.toValue(e2, factory, model));
Expressions.toValue(e1, factory, model, q),
Expressions.toValue(e2, factory, model, q));
}
}
@ -417,10 +433,11 @@ public class Expressions {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
return factory.mod(
Expressions.toValue(e1, factory, model),
Expressions.toValue(e2, factory, model));
Expressions.toValue(e1, factory, model, q),
Expressions.toValue(e2, factory, model, q));
}
}
@ -430,7 +447,8 @@ public class Expressions {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
return factory.getCurrentDate();
}
}
@ -441,7 +459,8 @@ public class Expressions {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
return factory.getCurrentTime();
}
}
@ -453,7 +472,8 @@ public class Expressions {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
return factory.getCurrentTimestamp();
}
}
@ -475,21 +495,21 @@ public class Expressions {
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(
ExpressionFactory factory, MetamodelImpl model) {
ExpressionFactory factory, MetamodelImpl model, CriteriaQuery q) {
boolean isTypeExpr = false;
Value val1 = Expressions.toValue(e1, factory, model);
Value val2 = Expressions.toValue(e2, factory, model);
Value val1 = Expressions.toValue(e1, factory, model, q);
Value val2 = Expressions.toValue(e2, factory, model, q);
if (e1 instanceof PathImpl) {
PathImpl path = (PathImpl)e1;
isTypeExpr = path.isTypeExpr();
if (isTypeExpr) {
((Constant)e2).setTypeLit(isTypeExpr);
val2 = Expressions.toValue(e2, factory, model);
val2 = Expressions.toValue(e2, factory, model, q);
Class clzz = (Class)((Literal)val2).getValue();
val2.setMetaData(((Types.Managed)model.type(clzz)).meta);
}
}
((CriteriaQueryImpl)q).setImplicitTypes(val1, val2, null);
if (!negate)
return factory.equal(val1, val2);
else
@ -508,10 +528,10 @@ public class Expressions {
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(
ExpressionFactory factory, MetamodelImpl model) {
ExpressionFactory factory, MetamodelImpl model, CriteriaQuery q) {
return factory.greaterThan(
Expressions.toValue(e1, factory, model),
Expressions.toValue(e2, factory, model));
Expressions.toValue(e1, factory, model, q),
Expressions.toValue(e2, factory, model, q));
}
}
@ -526,10 +546,10 @@ public class Expressions {
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(
ExpressionFactory factory, MetamodelImpl model) {
ExpressionFactory factory, MetamodelImpl model, CriteriaQuery q) {
return factory.greaterThanEqual(
Expressions.toValue(e1, factory, model),
Expressions.toValue(e2, factory, model));
Expressions.toValue(e1, factory, model, q),
Expressions.toValue(e2, factory, model, q));
}
}
@ -545,10 +565,10 @@ public class Expressions {
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(
ExpressionFactory factory, MetamodelImpl model) {
ExpressionFactory factory, MetamodelImpl model, CriteriaQuery q) {
return factory.lessThan(
Expressions.toValue(e1, factory, model),
Expressions.toValue(e2, factory, model));
Expressions.toValue(e1, factory, model, q),
Expressions.toValue(e2, factory, model, q));
}
}
@ -563,10 +583,10 @@ public class Expressions {
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(
ExpressionFactory factory, MetamodelImpl model) {
ExpressionFactory factory, MetamodelImpl model, CriteriaQuery q) {
return factory.lessThanEqual(
Expressions.toValue(e1, factory, model),
Expressions.toValue(e2, factory, model));
Expressions.toValue(e1, factory, model, q),
Expressions.toValue(e2, factory, model, q));
}
}
@ -601,7 +621,8 @@ public class Expressions {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
if (!typeLit)
return factory.newLiteral(arg, 1);
else
@ -625,13 +646,14 @@ public class Expressions {
@Override
public org.apache.openjpa.kernel.exps.Expression toKernelExpression(
ExpressionFactory factory, MetamodelImpl model) {
ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
if (!negate)
return factory.isEmpty(
Expressions.toValue(collection, factory, model));
Expressions.toValue(collection, factory, model, q));
else
return factory.isNotEmpty(
Expressions.toValue(collection, factory, model));
Expressions.toValue(collection, factory, model, q));
}
}
@ -661,10 +683,11 @@ public class Expressions {
@Override
public org.apache.openjpa.kernel.exps.Expression toKernelExpression(
ExpressionFactory factory, MetamodelImpl model) {
ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
return factory.contains(
Expressions.toValue(collection, factory, model),
Expressions.toValue(element, factory, model));
Expressions.toValue(collection, factory, model, q),
Expressions.toValue(element, factory, model, q));
}
}
@ -704,11 +727,12 @@ public class Expressions {
@Override
public org.apache.openjpa.kernel.exps.Expression toKernelExpression(
ExpressionFactory factory, MetamodelImpl model) {
ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
return factory.matches(
Expressions.toValue(str, factory, model),
Expressions.toValue(pattern, factory, model), "_", "%",
Expressions.toValue(escapeChar, factory, model).toString());
Expressions.toValue(str, factory, model, q),
Expressions.toValue(pattern, factory, model, q), "_", "%",
Expressions.toValue(escapeChar, factory, model, q).toString());
}
}
@ -737,12 +761,13 @@ public class Expressions {
@Override
public org.apache.openjpa.kernel.exps.Value toValue(
ExpressionFactory factory, MetamodelImpl model) {
ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
Value[] vs = new Value[values.size()];
int i = 0;
for (Expression<?> e : values)
vs[i++] = Expressions.toValue((ExpressionImpl<?>)e,
factory, model);
factory, model, q);
return factory.coalesceExpression(vs);
}
}
@ -756,9 +781,9 @@ public class Expressions {
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(
ExpressionFactory factory, MetamodelImpl model) {
ExpressionFactory factory, MetamodelImpl model, CriteriaQuery q) {
return factory.equal(
Expressions.toValue(e, factory, model),
Expressions.toValue(e, factory, model, q),
factory.getNull());
}
}
@ -772,9 +797,9 @@ public class Expressions {
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(
ExpressionFactory factory, MetamodelImpl model) {
ExpressionFactory factory, MetamodelImpl model, CriteriaQuery q) {
return factory.notEqual(
Expressions.toValue(e, factory, model),
Expressions.toValue(e, factory, model, q),
factory.getNull());
}
}
@ -804,11 +829,11 @@ public class Expressions {
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(
ExpressionFactory factory, MetamodelImpl model) {
ExpressionFactory factory, MetamodelImpl model, CriteriaQuery q) {
IsNotNull notNull = new Expressions.IsNotNull(e);
return factory.and(
super.toKernelExpression(factory, model),
notNull.toKernelExpression(factory, model));
super.toKernelExpression(factory, model, q),
notNull.toKernelExpression(factory, model, q));
}
}
@ -857,21 +882,22 @@ public class Expressions {
@Override
public org.apache.openjpa.kernel.exps.Value toValue(
ExpressionFactory factory, MetamodelImpl model) {
ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
int size = whens.size();
org.apache.openjpa.kernel.exps.Expression[] exps =
new org.apache.openjpa.kernel.exps.Expression[size];
for (int i = 0; i < size; i++) {
org.apache.openjpa.kernel.exps.Expression expr =
((Expressions.BinaryLogicalExpression)whens.get(i)).
toKernelExpression(factory, model);
toKernelExpression(factory, model, q);
Value action = Expressions.toValue(
(ExpressionImpl<?>)thens.get(i), factory, model);
(ExpressionImpl<?>)thens.get(i), factory, model, q);
exps[i] = factory.whenCondition(expr, action);
}
Value other = Expressions.toValue(
(ExpressionImpl<?>)otherwise, factory, model);
(ExpressionImpl<?>)otherwise, factory, model, q);
return factory.generalCaseExpression(exps, other);
}
}
@ -929,9 +955,10 @@ public class Expressions {
@Override
public org.apache.openjpa.kernel.exps.Value toValue(
ExpressionFactory factory, MetamodelImpl model) {
ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
Value caseOperandExpr = Expressions.toValue(
(ExpressionImpl<?>)caseOperand, factory, model);
(ExpressionImpl<?>)caseOperand, factory, model, q);
int size = whens.size();
org.apache.openjpa.kernel.exps.Expression[] exps =
new org.apache.openjpa.kernel.exps.Expression[size];
@ -940,12 +967,12 @@ public class Expressions {
//TODO: Boolean literal, String literal
val = factory.newLiteral(whens.get(i), Literal.TYPE_NUMBER);
Value action = Expressions.toValue(
(ExpressionImpl<?>)thens.get(i), factory, model);
(ExpressionImpl<?>)thens.get(i), factory, model, q);
exps[i] = factory.whenScalar(val, action);
}
Value other = Expressions.toValue(
(ExpressionImpl<?>)otherwise, factory, model);
(ExpressionImpl<?>)otherwise, factory, model, q);
return factory.simpleCaseExpression(caseOperandExpr, exps, other);
}
}

View File

@ -18,7 +18,14 @@
*/
package org.apache.openjpa.persistence.criteria;
import java.util.Collection;
import javax.persistence.Parameter;
import javax.persistence.criteria.CriteriaQuery;
import org.apache.commons.collections.map.LinkedMap;
import org.apache.openjpa.kernel.exps.ExpressionFactory;
import org.apache.openjpa.kernel.exps.Value;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.persistence.meta.MetamodelImpl;
/**
* Parameter of a criteria query.
@ -48,4 +55,40 @@ public class ParameterImpl<T> extends ExpressionImpl<T> implements Parameter<T>{
return position;
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
boolean positional = false;
LinkedMap parameterTypes = ((CriteriaQueryImpl)q).getParameterTypes();
if (parameterTypes == null) {
parameterTypes = new LinkedMap(6);
((CriteriaQueryImpl)q).setParameterTypes(parameterTypes);
}
if (name == null) {
position = parameterTypes.size() + 1;
positional = true;
}
Object paramKey = name == null ? Integer.valueOf(position) : name;
if (!parameterTypes.containsKey(paramKey))
parameterTypes.put(paramKey, Object.class);
ClassMetaData meta = null;
Class clzz = getJavaType();
int index;
if (positional)
index = position - 1;
else
// otherwise the index is just the current size of the params
index = parameterTypes.indexOf(paramKey);
boolean isCollectionValued = Collection.class.isAssignableFrom(clzz);
org.apache.openjpa.kernel.exps.Parameter param = isCollectionValued
? factory.newCollectionValuedParameter(paramKey, Object.class)
: factory.newParameter(paramKey, Object.class);
param.setMetaData(meta);
param.setIndex(index);
return param;
}
}

View File

@ -19,6 +19,7 @@
package org.apache.openjpa.persistence.criteria;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Path;
import javax.persistence.metamodel.AbstractCollection;
@ -65,12 +66,13 @@ public class PathImpl<X> extends ExpressionImpl<X> implements Path<X> {
}
@Override
public Value toValue(ExpressionFactory factory, MetamodelImpl model) {
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
CriteriaQuery q) {
Value var = null;
if (_parent != null) {
org.apache.openjpa.kernel.exps.Path path =
(org.apache.openjpa.kernel.exps.Path)
_parent.toValue(factory, model);
_parent.toValue(factory, model, q);
path.get(member.fmd, false);
var = path;
} else {

View File

@ -21,6 +21,7 @@ package org.apache.openjpa.persistence.criteria;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
@ -80,18 +81,18 @@ public class PredicateImpl extends ExpressionImpl<Boolean>
@Override
org.apache.openjpa.kernel.exps.Expression toKernelExpression(
ExpressionFactory factory, MetamodelImpl model) {
ExpressionFactory factory, MetamodelImpl model, CriteriaQuery q) {
if (_exps == null || _exps.isEmpty())
return factory.emptyExpression();
if (_exps.size() == 1)
return ((ExpressionImpl<?>)_exps.get(0))
.toKernelExpression(factory, model);
.toKernelExpression(factory, model, q);
ExpressionImpl<?> e1 = (ExpressionImpl<?>)_exps.get(0);
ExpressionImpl<?> e2 = (ExpressionImpl<?>)_exps.get(1);
org.apache.openjpa.kernel.exps.Expression ke1 =
e1.toKernelExpression(factory, model);
e1.toKernelExpression(factory, model, q);
org.apache.openjpa.kernel.exps.Expression ke2 =
e2.toKernelExpression(factory, model);
e2.toKernelExpression(factory, model, q);
org.apache.openjpa.kernel.exps.Expression result =
_op == BooleanOperator.AND
? factory.and(ke1,ke2) : factory.or(ke1, ke2);
@ -99,8 +100,8 @@ public class PredicateImpl extends ExpressionImpl<Boolean>
for (int i = 2; i < _exps.size(); i++) {
ExpressionImpl<?> e = (ExpressionImpl<?>)_exps.get(i);
result = _op == BooleanOperator.AND
? factory.and(result, e.toKernelExpression(factory, model))
: factory.or(result, e.toKernelExpression(factory, model));
? factory.and(result, e.toKernelExpression(factory, model, q))
: factory.or(result, e.toKernelExpression(factory,model,q));
}
return _negated ? factory.not(result) : result;
}