mirror of https://github.com/apache/openjpa.git
OPENJPA-1195: Datastore function for in general usage as well as JPA 2.0. CriteriaQuery Parameter indexing during registration.
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@797257 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
001c9e4fd2
commit
7099c084fb
|
@ -18,6 +18,10 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.openjpa.jdbc.kernel.exps;
|
package org.apache.openjpa.jdbc.kernel.exps;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.openjpa.jdbc.sql.Joins;
|
import org.apache.openjpa.jdbc.sql.Joins;
|
||||||
import org.apache.openjpa.jdbc.sql.Result;
|
import org.apache.openjpa.jdbc.sql.Result;
|
||||||
import org.apache.openjpa.jdbc.sql.SQLBuffer;
|
import org.apache.openjpa.jdbc.sql.SQLBuffer;
|
||||||
|
@ -43,18 +47,21 @@ public class Args
|
||||||
* Constructor. Supply values being combined.
|
* Constructor. Supply values being combined.
|
||||||
*/
|
*/
|
||||||
public Args(Val val1, Val val2) {
|
public Args(Val val1, Val val2) {
|
||||||
int len1 = (val1 instanceof Args) ? ((Args) val1)._args.length : 1;
|
this(new Val[]{val1, val2});
|
||||||
int len2 = (val2 instanceof Args) ? ((Args) val2)._args.length : 1;
|
}
|
||||||
|
|
||||||
_args = new Val[len1 + len2];
|
public Args (Val... values) {
|
||||||
if (val1 instanceof Args)
|
List<Val> list = new ArrayList<Val>();
|
||||||
System.arraycopy(((Args) val1)._args, 0, _args, 0, len1);
|
if (values != null) {
|
||||||
else
|
for (Val v : values) {
|
||||||
_args[0] = val1;
|
if (v instanceof Args) {
|
||||||
if (val2 instanceof Args)
|
list.addAll(Arrays.asList(((Args)v)._args));
|
||||||
System.arraycopy(((Args) val2)._args, 0, _args, len1, len2);
|
} else {
|
||||||
else
|
list.add(v);
|
||||||
_args[len1] = val2;
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_args = list.toArray(new Val[list.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -166,6 +173,12 @@ public class Args
|
||||||
|
|
||||||
public void appendTo(Select sel, ExpContext ctx, ExpState state,
|
public void appendTo(Select sel, ExpContext ctx, ExpState state,
|
||||||
SQLBuffer sql, int index) {
|
SQLBuffer sql, int index) {
|
||||||
|
ArgsExpState astate = (ArgsExpState) state;
|
||||||
|
for (int i = 0; i < _args.length; i++) {
|
||||||
|
_args[i].appendTo(sel, ctx, astate.states[i], sql, index);
|
||||||
|
if (i < _args.length-1)
|
||||||
|
sql.append(", ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void appendIsEmpty(Select sel, ExpContext ctx, ExpState state,
|
public void appendIsEmpty(Select sel, ExpContext ctx, ExpState state,
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.apache.openjpa.jdbc.kernel.exps;
|
||||||
|
|
||||||
|
import org.apache.openjpa.kernel.exps.Arguments;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A unary operator that executes a datastore specific function with zero or more arguments.
|
||||||
|
*
|
||||||
|
* @author Pinaki Poddar
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class DatastoreFunction extends UnaryOp {
|
||||||
|
private final String _functionName;
|
||||||
|
|
||||||
|
public DatastoreFunction(String name, Class<?> resultType, Arguments args) {
|
||||||
|
super((Val)args);
|
||||||
|
_functionName = name;
|
||||||
|
setImplicitType(resultType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getOperator() {
|
||||||
|
return _functionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -297,6 +297,17 @@ public class JDBCExpressionFactory
|
||||||
public Arguments newArgumentList(Value v1, Value v2) {
|
public Arguments newArgumentList(Value v1, Value v2) {
|
||||||
return new Args((Val) v1, (Val) v2);
|
return new Args((Val) v1, (Val) v2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Arguments newArgumentList(Value... vs) {
|
||||||
|
if (vs == null)
|
||||||
|
return new Args(null);
|
||||||
|
Val[] vals = new Val[vs.length];
|
||||||
|
int i = 0;
|
||||||
|
for (Value v : vs) {
|
||||||
|
vals[i++] = (Val)v;
|
||||||
|
}
|
||||||
|
return new Args(vals);
|
||||||
|
}
|
||||||
|
|
||||||
public Value newUnboundVariable(String name, Class type) {
|
public Value newUnboundVariable(String name, Class type) {
|
||||||
return new Variable(name, type);
|
return new Variable(name, type);
|
||||||
|
@ -503,4 +514,8 @@ public class JDBCExpressionFactory
|
||||||
val2 = getLiteralRawString(val2);
|
val2 = getLiteralRawString(val2);
|
||||||
return new NullIfExpression((Val) val1, (Val) val2);
|
return new NullIfExpression((Val) val1, (Val) val2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Value newFunction(String functionName, Class<?> resultType, Value... args) {
|
||||||
|
return new DatastoreFunction(functionName, resultType, newArgumentList(args));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,24 +32,30 @@ class Args
|
||||||
extends Val
|
extends Val
|
||||||
implements Arguments {
|
implements Arguments {
|
||||||
|
|
||||||
private final List _args = new ArrayList(3);
|
private final List<Value> _args = new ArrayList<Value>(3);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor. Supply values being combined.
|
* Constructor. Supply values being combined.
|
||||||
*/
|
*/
|
||||||
public Args(Value val1, Value val2) {
|
public Args(Value val1, Value val2) {
|
||||||
if (val1 instanceof Args)
|
this(new Value[]{val1, val2});
|
||||||
_args.addAll(((Args) val1)._args);
|
}
|
||||||
else
|
|
||||||
_args.add(val1);
|
public Args(Value...values) {
|
||||||
if (val2 instanceof Args)
|
if (values == null) {
|
||||||
_args.addAll(((Args) val2)._args);
|
return;
|
||||||
else
|
}
|
||||||
_args.add(val2);
|
for (Value v : values) {
|
||||||
|
if (v instanceof Args) {
|
||||||
|
_args.addAll(((Args)v)._args);
|
||||||
|
} else {
|
||||||
|
_args.add(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Value[] getValues() {
|
public Value[] getValues() {
|
||||||
return (Value[]) _args.toArray(new Value[_args.size()]);
|
return _args.toArray(new Value[_args.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class getType() {
|
public Class getType() {
|
||||||
|
|
|
@ -269,6 +269,12 @@ public interface ExpressionFactory {
|
||||||
* of which may itself be an argument list.
|
* of which may itself be an argument list.
|
||||||
*/
|
*/
|
||||||
public Arguments newArgumentList(Value arg1, Value arg2);
|
public Arguments newArgumentList(Value arg1, Value arg2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a function argument list consisting of the given values, any
|
||||||
|
* of which may itself be an argument list.
|
||||||
|
*/
|
||||||
|
public Arguments newArgumentList(Value... values);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an unbound variable. This method will only be called once for
|
* Return an unbound variable. This method will only be called once for
|
||||||
|
@ -481,4 +487,9 @@ public interface ExpressionFactory {
|
||||||
* a {@link Number}, {@link String}, or {@link Boolean} instance.
|
* a {@link Number}, {@link String}, or {@link Boolean} instance.
|
||||||
*/
|
*/
|
||||||
public Literal newTypeLiteral(Object val, int parseType);
|
public Literal newTypeLiteral(Object val, int parseType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a value representing the given datastore function with the given arguments.
|
||||||
|
*/
|
||||||
|
public Value newFunction(String functionName, Class<?> resultType, Value... args);
|
||||||
}
|
}
|
||||||
|
|
|
@ -525,6 +525,10 @@ public class InMemoryExpressionFactory
|
||||||
public Arguments newArgumentList(Value val1, Value val2) {
|
public Arguments newArgumentList(Value val1, Value val2) {
|
||||||
return new Args(val1, val2);
|
return new Args(val1, val2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Arguments newArgumentList(Value... values) {
|
||||||
|
return new Args(values);
|
||||||
|
}
|
||||||
|
|
||||||
public Value newUnboundVariable(String name, Class type) {
|
public Value newUnboundVariable(String name, Class type) {
|
||||||
UnboundVariable var = new UnboundVariable(type);
|
UnboundVariable var = new UnboundVariable(type);
|
||||||
|
@ -788,4 +792,8 @@ public class InMemoryExpressionFactory
|
||||||
public Value nullIfExpression(Value val1, Value val2) {
|
public Value nullIfExpression(Value val1, Value val2) {
|
||||||
return new NullIf((Val) val1, (Val) val2);
|
return new NullIf((Val) val1, (Val) val2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Value newFunction(String functionName, Class<?> resultType, Value... args) {
|
||||||
|
throw new AbstractMethodError();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -328,6 +328,10 @@ public abstract class CriteriaTest extends TestCase {
|
||||||
assertFalse(auditor.getSQLs().isEmpty());
|
assertFalse(auditor.getSQLs().isEmpty());
|
||||||
return auditor.getSQLs();
|
return auditor.getSQLs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void executeAndCompareSQL(CriteriaQuery<?> q, String expectedSQL) {
|
||||||
|
executeAndCompareSQL(em.createQuery(q), expectedSQL);
|
||||||
|
}
|
||||||
|
|
||||||
String extractSQL(Exception e) {
|
String extractSQL(Exception e) {
|
||||||
Throwable t = e.getCause();
|
Throwable t = e.getCause();
|
||||||
|
|
|
@ -802,4 +802,58 @@ public class TestTypesafeCriteria extends CriteriaTest {
|
||||||
|
|
||||||
assertEquivalence(q, jpql);
|
assertEquivalence(q, jpql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 0-arg function works only if there is a other projection items to determine the table to select from.
|
||||||
|
*/
|
||||||
|
public void testFunctionWithNoArgument() {
|
||||||
|
String jpql = "SELECT c.balanceOwed FROM Customer c";
|
||||||
|
String sql = "SELECT CURRENT_USER(), t0.balanceOwed FROM CR_CUST t0";
|
||||||
|
|
||||||
|
CriteriaQuery<Tuple> q = cb.createTupleQuery();
|
||||||
|
Root<Customer> c = q.from(Customer.class);
|
||||||
|
q.multiselect(cb.function("CURRENT_USER", String.class, (Expression<?>[])null), c.get(Customer_.balanceOwed));
|
||||||
|
|
||||||
|
executeAndCompareSQL(q, sql);
|
||||||
|
// assertEquivalence(q, jpql);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFunctionWithOneArgument() {
|
||||||
|
String jpql = "SELECT MAX(c.balanceOwed) FROM Customer c";
|
||||||
|
|
||||||
|
CriteriaQuery<Tuple> q = cb.createTupleQuery();
|
||||||
|
Root<Customer> c = q.from(Customer.class);
|
||||||
|
q.multiselect(cb.function("MAX", Integer.class, c.get(Customer_.balanceOwed)));
|
||||||
|
|
||||||
|
assertEquivalence(q, jpql);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFunctionWithTwoArgument() {
|
||||||
|
String jpql = "SELECT MOD(c.balanceOwed,10) FROM Customer c";
|
||||||
|
|
||||||
|
CriteriaQuery<Tuple> q = cb.createTupleQuery();
|
||||||
|
Root<Customer> c = q.from(Customer.class);
|
||||||
|
q.multiselect(cb.function("MOD", Integer.class, c.get(Customer_.balanceOwed), cb.literal(10)));
|
||||||
|
|
||||||
|
assertEquivalence(q, jpql);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFunctionWithFunctionArgumentInOrderBy() {
|
||||||
|
String jpql = "SELECT MOD(c.balanceOwed,10) FROM Customer c WHERE LENGTH(c.name)>3 ORDER BY LENGTH(c.name)";
|
||||||
|
String sql = "SELECT MOD(t0.balanceOwed, ?), LENGTH(t0.name) FROM CR_CUST t0 WHERE (LENGTH(t0.name) > ?) " +
|
||||||
|
"ORDER BY LENGTH(t0.name) ASC";
|
||||||
|
|
||||||
|
CriteriaQuery<Tuple> q = cb.createTupleQuery();
|
||||||
|
Root<Customer> c = q.from(Customer.class);
|
||||||
|
Expression<Integer> nameLength = cb.function("LENGTH", Integer.class, c.get(Customer_.name));
|
||||||
|
q.multiselect(cb.function("MOD", Integer.class, c.get(Customer_.balanceOwed), cb.literal(10)));
|
||||||
|
q.where(cb.greaterThan(nameLength, 3));
|
||||||
|
q.orderBy(cb.asc(nameLength));
|
||||||
|
|
||||||
|
executeAndCompareSQL(q, sql);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,7 +246,7 @@ public class CriteriaBuilder implements QueryBuilder, ExpressionParser {
|
||||||
|
|
||||||
public <T> Expression<T> function(String name, Class<T> type,
|
public <T> Expression<T> function(String name, Class<T> type,
|
||||||
Expression<?>... args) {
|
Expression<?>... args) {
|
||||||
throw new AbstractMethodError();
|
return new Expressions.DatabaseFunction(name, type, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Predicate ge(Expression<? extends Number> x,
|
public Predicate ge(Expression<? extends Number> x,
|
||||||
|
|
|
@ -81,8 +81,7 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
|
||||||
private static String ALIAS_BASE = "autoAlias";
|
private static String ALIAS_BASE = "autoAlias";
|
||||||
|
|
||||||
// Auto-generated Parameter name
|
// Auto-generated Parameter name
|
||||||
private int autoParameterCount = 0;
|
private static String PARAM_BASE = "*autoParam";
|
||||||
private static String PARAM_BASE = "autoParam";
|
|
||||||
|
|
||||||
private Map<Selection<?>,Value> _variables = new HashMap<Selection<?>, Value>();
|
private Map<Selection<?>,Value> _variables = new HashMap<Selection<?>, Value>();
|
||||||
private Map<Selection<?>,Value> _values = new HashMap<Selection<?>, Value>();
|
private Map<Selection<?>,Value> _values = new HashMap<Selection<?>, Value>();
|
||||||
|
@ -194,9 +193,13 @@ public class CriteriaQueryImpl<T> implements CriteriaQuery<T>, AliasContext {
|
||||||
if (_paramTypes == null) {
|
if (_paramTypes == null) {
|
||||||
_paramTypes = new LinkedHashMap<ParameterExpression<?>, Class<?>>();
|
_paramTypes = new LinkedHashMap<ParameterExpression<?>, Class<?>>();
|
||||||
}
|
}
|
||||||
|
if (_paramTypes.containsKey(p)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p.setIndex(_paramTypes.size());
|
||||||
_paramTypes.put(p, p.getJavaType());
|
_paramTypes.put(p, p.getJavaType());
|
||||||
if (p.getName() == null)
|
if (p.getName() == null)
|
||||||
p.assignAutoName(PARAM_BASE + (++autoParameterCount));
|
p.assignAutoName(PARAM_BASE + p.getIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<ParameterExpression<?>> getParameters() {
|
public Set<ParameterExpression<?>> getParameters() {
|
||||||
|
|
|
@ -47,12 +47,12 @@ public class Expressions {
|
||||||
* Handles null expression.
|
* Handles null expression.
|
||||||
*/
|
*/
|
||||||
static Value toValue(ExpressionImpl<?> e, ExpressionFactory factory,
|
static Value toValue(ExpressionImpl<?> e, ExpressionFactory factory,
|
||||||
MetamodelImpl model, CriteriaQueryImpl q) {
|
MetamodelImpl model, CriteriaQueryImpl<?> q) {
|
||||||
return (e == null) ? factory.getNull() : e.toValue(factory, model, q);
|
return (e == null) ? factory.getNull() : e.toValue(factory, model, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setImplicitTypes(Value v1, Value v2, Class<?> expected,
|
static void setImplicitTypes(Value v1, Value v2, Class<?> expected,
|
||||||
CriteriaQueryImpl q) {
|
CriteriaQueryImpl<?> q) {
|
||||||
JPQLExpressionBuilder.setImplicitTypes(v1, v2, expected,
|
JPQLExpressionBuilder.setImplicitTypes(v1, v2, expected,
|
||||||
q.getMetamodel(), q.getParameterTypes(), q.toString());
|
q.getMetamodel(), q.getParameterTypes(), q.toString());
|
||||||
}
|
}
|
||||||
|
@ -96,8 +96,26 @@ public class Expressions {
|
||||||
e2 = (ExpressionImpl<?>)y;
|
e2 = (ExpressionImpl<?>)y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functional Expression applies a function on a list of input Expressions.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param <X> the type of the resultant expression
|
||||||
|
*/
|
||||||
|
public abstract static class FunctionalExpression<X> extends ExpressionImpl<X>{
|
||||||
|
protected final ExpressionImpl<?>[] args;
|
||||||
|
|
||||||
|
public FunctionalExpression(Class<X> t, Expression<?>... args) {
|
||||||
|
super(t);
|
||||||
|
int len = args == null ? 0 : args.length;
|
||||||
|
this.args = new ExpressionImpl<?>[len];
|
||||||
|
for (int i = 0; args != null && i < args.length; i++) {
|
||||||
|
this.args[i] = (ExpressionImpl<?>)args[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binary Logical Expression applies a binary function on a pair of
|
* Binary Logical Expression applies a binary function on a pair of
|
||||||
* input Expression to generate a Predicate.
|
* input Expression to generate a Predicate.
|
||||||
|
@ -216,6 +234,24 @@ public class Expressions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class DatabaseFunction<T> extends FunctionalExpression<T> {
|
||||||
|
private final String functionName;
|
||||||
|
private final Class<T> resultType;
|
||||||
|
public DatabaseFunction(String name, Class<T> resultType, Expression<?>... exps) {
|
||||||
|
super(resultType, exps);
|
||||||
|
functionName = name;
|
||||||
|
this.resultType = resultType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Value toValue(ExpressionFactory factory, MetamodelImpl model,
|
||||||
|
CriteriaQueryImpl<?> q) {
|
||||||
|
return factory.newFunction(functionName, getJavaType(),
|
||||||
|
new Expressions.ListArgument(resultType, args).toValue(factory, model, q));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class Type<X>
|
public static class Type<X>
|
||||||
extends UnaryFunctionalExpression<Class<? extends X>> {
|
extends UnaryFunctionalExpression<Class<? extends X>> {
|
||||||
public Type(PathImpl<?, X> path) {
|
public Type(PathImpl<?, X> path) {
|
||||||
|
@ -1345,5 +1381,31 @@ public class Expressions {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An expression that is composed of one or more expressions.
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
*/
|
||||||
|
public static class ListArgument<T> extends ExpressionImpl<T> {
|
||||||
|
private final ExpressionImpl<?>[] _args;
|
||||||
|
public ListArgument(Class<T> cls, ExpressionImpl<?>... args) {
|
||||||
|
super(cls);
|
||||||
|
_args = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public org.apache.openjpa.kernel.exps.Arguments toValue(
|
||||||
|
ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl<?> q) {
|
||||||
|
org.apache.openjpa.kernel.exps.Value[] kvs = new org.apache.openjpa.kernel.exps.Value[_args.length];
|
||||||
|
int i = 0;
|
||||||
|
for (ExpressionImpl<?> arg : _args) {
|
||||||
|
kvs[i++] = arg.toValue(factory, model, q);
|
||||||
|
}
|
||||||
|
org.apache.openjpa.kernel.exps.Arguments e = factory.newArgumentList(kvs);
|
||||||
|
e.setImplicitType(getJavaType());
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ public class ParameterExpressionImpl<T> extends ExpressionImpl<T>
|
||||||
implements ParameterExpression<T>, QueryParameter<T> {
|
implements ParameterExpression<T>, QueryParameter<T> {
|
||||||
|
|
||||||
private String _autoName = null;
|
private String _autoName = null;
|
||||||
|
private int _index = 0; // index of the parameter as seen by the kernel
|
||||||
private final ParameterImpl<T> _delegate;
|
private final ParameterImpl<T> _delegate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -127,6 +128,14 @@ public class ParameterExpressionImpl<T> extends ExpressionImpl<T>
|
||||||
public final boolean isPositional() {
|
public final boolean isPositional() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setIndex(int index) {
|
||||||
|
_index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndex() {
|
||||||
|
return _index;
|
||||||
|
}
|
||||||
|
|
||||||
public final boolean isValueAssignable(Object v) {
|
public final boolean isValueAssignable(Object v) {
|
||||||
return _delegate.isValueAssignable(v);
|
return _delegate.isValueAssignable(v);
|
||||||
|
@ -155,6 +164,7 @@ public class ParameterExpressionImpl<T> extends ExpressionImpl<T>
|
||||||
? factory.newCollectionValuedParameter(paramKey, clzz)
|
? factory.newCollectionValuedParameter(paramKey, clzz)
|
||||||
: factory.newParameter(paramKey, clzz);
|
: factory.newParameter(paramKey, clzz);
|
||||||
param.setMetaData(meta);
|
param.setMetaData(meta);
|
||||||
|
param.setIndex(_index);
|
||||||
|
|
||||||
return param;
|
return param;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue