mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Initial add of SpiNamedParam
This commit is contained in:
@@ -192,6 +192,11 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
ExampleExpression exampleLike(Object example, boolean caseInsensitive, LikeType likeType);
|
||||
|
||||
/**
|
||||
* Create the query by Example expression specifying more options.
|
||||
*/
|
||||
Expression like(LikeType likeType, String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Like - property like value where the value contains the SQL wild card
|
||||
* characters % (percentage) and _ (underscore).
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.avaje.ebeaninternal.api;
|
||||
|
||||
public interface SpiNamedParam {
|
||||
|
||||
Object getValue();
|
||||
}
|
||||
@@ -296,6 +296,8 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
void setLoadDescription(String loadMode, String loadDescription);
|
||||
|
||||
SpiNamedParam createNamedParameter(String parameterName);
|
||||
|
||||
/**
|
||||
* Return the joins required to support predicates on the many properties.
|
||||
*/
|
||||
|
||||
@@ -251,6 +251,12 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
return new DefaultExampleExpression(checkEntityBean(example), caseInsensitive, likeType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression like(LikeType likeType, String propertyName, Object value) {
|
||||
|
||||
return new LikeExpression(propertyName, value, true, LikeType.RAW);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like - property like value where the value contains the SQL wild card
|
||||
* characters % (percentage) and _ (underscore).
|
||||
|
||||
@@ -4,28 +4,43 @@ import com.avaje.ebean.LikeType;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.api.SpiNamedParam;
|
||||
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
class LikeExpression extends AbstractExpression {
|
||||
|
||||
private final String val;
|
||||
private final Object value;
|
||||
|
||||
private final boolean caseInsensitive;
|
||||
|
||||
private final LikeType type;
|
||||
|
||||
LikeExpression(String propertyName, String value, boolean caseInsensitive, LikeType type) {
|
||||
LikeExpression(String propertyName, Object value, boolean caseInsensitive, LikeType type) {
|
||||
super(propertyName);
|
||||
this.caseInsensitive = caseInsensitive;
|
||||
this.type = type;
|
||||
this.val = value;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bind value taking into account named parameters.
|
||||
*/
|
||||
private Object value() {
|
||||
if (value instanceof SpiNamedParam) {
|
||||
return ((SpiNamedParam)value).getValue();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private String val() {
|
||||
return value().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDocQuery(DocQueryContext context) throws IOException {
|
||||
context.writeLike(propName, val, type, caseInsensitive);
|
||||
context.writeLike(propName, val(), type, caseInsensitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -38,7 +53,7 @@ class LikeExpression extends AbstractExpression {
|
||||
request.addBindEncryptKey(encryptKey);
|
||||
}
|
||||
|
||||
String bindValue = getValue(val, caseInsensitive, type);
|
||||
String bindValue = getValue(val(), caseInsensitive, type);
|
||||
request.addBindValue(bindValue);
|
||||
}
|
||||
|
||||
@@ -74,7 +89,7 @@ class LikeExpression extends AbstractExpression {
|
||||
|
||||
@Override
|
||||
public int queryBindHash() {
|
||||
return val.hashCode();
|
||||
return val().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -92,7 +107,7 @@ class LikeExpression extends AbstractExpression {
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
LikeExpression that = (LikeExpression) other;
|
||||
return val.equals(that.val);
|
||||
return val().equals(that.val());
|
||||
}
|
||||
|
||||
private static String getValue(String value, boolean caseInsensitive, LikeType type) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.avaje.ebean.plugin.ExpressionPath;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.api.SpiNamedParam;
|
||||
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -13,18 +14,28 @@ public class SimpleExpression extends AbstractExpression {
|
||||
|
||||
private final Op type;
|
||||
|
||||
private final Object value;
|
||||
private final Object val;
|
||||
|
||||
public SimpleExpression(String propertyName, Op type, Object value) {
|
||||
super(propertyName);
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
this.val = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bind value taking into account named parameters.
|
||||
*/
|
||||
private Object value() {
|
||||
if (val instanceof SpiNamedParam) {
|
||||
return ((SpiNamedParam)val).getValue();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdEqualTo(String idName) {
|
||||
if (type == Op.EQ && idName.equals(propName)) {
|
||||
return value;
|
||||
return value();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -37,13 +48,13 @@ public class SimpleExpression extends AbstractExpression {
|
||||
ExpressionPath prop = context.getExpressionPath(propName);
|
||||
if (prop != null && prop.isAssocId()) {
|
||||
String idName = prop.getAssocIdExpression(propName, "");
|
||||
Object[] ids = prop.getAssocIdValues((EntityBean) value);
|
||||
Object[] ids = prop.getAssocIdValues((EntityBean) value());
|
||||
if (ids == null || ids.length != 1) {
|
||||
throw new IllegalArgumentException("Expecting 1 Id value for " + idName + " but got " + ids);
|
||||
}
|
||||
context.writeSimple(type, idName, ids[0]);
|
||||
} else {
|
||||
context.writeSimple(type, propName, value);
|
||||
context.writeSimple(type, propName, value());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +67,7 @@ public class SimpleExpression extends AbstractExpression {
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
return value();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,7 +76,7 @@ public class SimpleExpression extends AbstractExpression {
|
||||
ElPropertyValue prop = getElProp(request);
|
||||
if (prop != null) {
|
||||
if (prop.isAssocId()) {
|
||||
Object[] ids = prop.getAssocIdValues((EntityBean) value);
|
||||
Object[] ids = prop.getAssocIdValues((EntityBean) value());
|
||||
if (ids != null) {
|
||||
for (int i = 0; i < ids.length; i++) {
|
||||
request.addBindValue(ids[i]);
|
||||
@@ -83,7 +94,7 @@ public class SimpleExpression extends AbstractExpression {
|
||||
// prop.getBeanProperty().getScalarType();
|
||||
}
|
||||
|
||||
request.addBindValue(value);
|
||||
request.addBindValue(value());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -115,7 +126,7 @@ public class SimpleExpression extends AbstractExpression {
|
||||
|
||||
@Override
|
||||
public int queryBindHash() {
|
||||
return value.hashCode();
|
||||
return value().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -132,6 +143,6 @@ public class SimpleExpression extends AbstractExpression {
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
SimpleExpression that = (SimpleExpression) other;
|
||||
return value.equals(that.value);
|
||||
return value().equals(that.value());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package com.avaje.ebeaninternal.server.grammer;
|
||||
|
||||
import com.avaje.ebean.Expression;
|
||||
import com.avaje.ebean.ExpressionList;
|
||||
import com.avaje.ebean.LikeType;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.server.grammer.antlr.EQLBaseListener;
|
||||
import com.avaje.ebeaninternal.server.grammer.antlr.EQLLexer;
|
||||
import com.avaje.ebeaninternal.server.grammer.antlr.EQLParser;
|
||||
@@ -14,7 +17,7 @@ class EqlAdapter<T> extends EQLBaseListener {
|
||||
|
||||
private static final OperatorMapping operatorMapping = new OperatorMapping();
|
||||
|
||||
private final Query<T> query;
|
||||
private final SpiQuery<T> query;
|
||||
|
||||
private final EqlAdapterHelper helper;
|
||||
|
||||
@@ -25,7 +28,7 @@ class EqlAdapter<T> extends EQLBaseListener {
|
||||
private boolean textMode;
|
||||
|
||||
public EqlAdapter(Query<T> query) {
|
||||
this.query = query;
|
||||
this.query = (SpiQuery<T>)query;
|
||||
this.helper = new EqlAdapterHelper(this);
|
||||
}
|
||||
|
||||
@@ -60,8 +63,7 @@ class EqlAdapter<T> extends EQLBaseListener {
|
||||
/**
|
||||
* Push the expression list onto the appropriate stack.
|
||||
*/
|
||||
private void pushExprList(ExpressionList<T> list, String type) {
|
||||
System.out.println("Push " + type + ">> ");
|
||||
private void pushExprList(ExpressionList<T> list) {
|
||||
if (textMode) {
|
||||
textStack.push(list);
|
||||
} else {
|
||||
@@ -72,8 +74,7 @@ class EqlAdapter<T> extends EQLBaseListener {
|
||||
/**
|
||||
* End a list of expressions added by 'OR'.
|
||||
*/
|
||||
private void popJunction(String type) {
|
||||
System.out.println("Pop " + type + " >> ");
|
||||
private void popJunction() {
|
||||
if (textMode) {
|
||||
textStack.pop();
|
||||
} else {
|
||||
@@ -145,7 +146,7 @@ class EqlAdapter<T> extends EQLBaseListener {
|
||||
String operator = ctx.getChild(1).getText();
|
||||
EqlOperator op = operatorMapping.get(operator);
|
||||
if (op == null) {
|
||||
throw new IllegalStateException("No operator found for " + op);
|
||||
throw new IllegalStateException("No operator found for " + operator);
|
||||
}
|
||||
|
||||
// RHS is Path, Literal or Named input parameter
|
||||
@@ -158,43 +159,50 @@ class EqlAdapter<T> extends EQLBaseListener {
|
||||
public void enterConditional_term(EQLParser.Conditional_termContext ctx) {
|
||||
int childCount = ctx.getChildCount();
|
||||
if (childCount > 1) {
|
||||
pushExprList(peekExprList().and(), "Conjunction");
|
||||
pushExprList(peekExprList().and());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitConditional_term(EQLParser.Conditional_termContext ctx) {
|
||||
if (ctx.getChildCount() > 1) {
|
||||
popJunction("Conjunction");
|
||||
popJunction();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterConditional_expression(EQLParser.Conditional_expressionContext ctx) {
|
||||
if (ctx.getChildCount() > 1) {
|
||||
pushExprList(peekExprList().or(), "Disjunction");
|
||||
pushExprList(peekExprList().or());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitConditional_expression(EQLParser.Conditional_expressionContext ctx) {
|
||||
if (ctx.getChildCount() > 1) {
|
||||
popJunction("Disjunction");
|
||||
popJunction();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterConditional_factor(EQLParser.Conditional_factorContext ctx) {
|
||||
if (ctx.getChildCount() > 1) {
|
||||
pushExprList(peekExprList().not(), "Not");
|
||||
pushExprList(peekExprList().not());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitConditional_factor(EQLParser.Conditional_factorContext ctx) {
|
||||
if (ctx.getChildCount() > 1) {
|
||||
popJunction("Not");
|
||||
popJunction();
|
||||
}
|
||||
}
|
||||
|
||||
public Object namedParam(String parameterName) {
|
||||
return query.createNamedParameter(parameterName);
|
||||
}
|
||||
|
||||
public Expression like(LikeType likeType, String property, Object bindValue) {
|
||||
return query.getExpressionFactory().like(likeType, property, bindValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.avaje.ebeaninternal.server.grammer;
|
||||
|
||||
import com.avaje.ebean.ExpressionList;
|
||||
import com.avaje.ebean.LikeType;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@@ -65,16 +66,16 @@ class EqlAdapterHelper {
|
||||
peekExprList().le(path, bind(value));
|
||||
break;
|
||||
case LIKE:
|
||||
peekExprList().like(path, bindString(value));
|
||||
addLike(LikeType.RAW, path, bind(value));
|
||||
break;
|
||||
case CONTAINS:
|
||||
peekExprList().contains(path, bindString(value));
|
||||
addLike(LikeType.CONTAINS, path, bind(value));
|
||||
break;
|
||||
case STARTS_WITH:
|
||||
peekExprList().startsWith(path, bindString(value));
|
||||
addLike(LikeType.STARTS_WITH, path, bind(value));
|
||||
break;
|
||||
case ENDS_WITH:
|
||||
peekExprList().endsWith(path, bindString(value));
|
||||
addLike(LikeType.ENDS_WITH, path, bind(value));
|
||||
break;
|
||||
case ILIKE:
|
||||
peekExprList().ilike(path, bindString(value));
|
||||
@@ -94,6 +95,10 @@ class EqlAdapterHelper {
|
||||
|
||||
}
|
||||
|
||||
private void addLike(LikeType likeType, String path, Object bindValue) {
|
||||
peekExprList().add(owner.like(likeType, path, bindValue));
|
||||
}
|
||||
|
||||
private String bindString(String value) {
|
||||
ValueType valueType = getValueType(value);
|
||||
switch (valueType) {
|
||||
@@ -120,7 +125,7 @@ class EqlAdapterHelper {
|
||||
case BOOL: return Boolean.parseBoolean(value);
|
||||
case NUMBER: return new BigDecimal(value);
|
||||
case STRING: return unquote(value);
|
||||
case NAMED_PARAM: return new NamedParameter(value.substring(1));
|
||||
case NAMED_PARAM: return owner.namedParam(value.substring(1));
|
||||
default:
|
||||
throw new IllegalArgumentException("Unhandled valueType "+valueType);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import com.avaje.ebeaninternal.api.ManyWhereJoins;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionList;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionValidation;
|
||||
import com.avaje.ebeaninternal.api.SpiNamedParam;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.api.SpiQuerySecondary;
|
||||
import com.avaje.ebeaninternal.server.autotune.ProfilingListener;
|
||||
@@ -28,6 +29,7 @@ import com.avaje.ebeaninternal.server.query.CancelableQuery;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -135,6 +137,8 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
*/
|
||||
private Object id;
|
||||
|
||||
private Map<String,ONamedParam> namedParams;
|
||||
|
||||
/**
|
||||
* Bind parameters when using the query language.
|
||||
*/
|
||||
@@ -1138,6 +1142,15 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
*/
|
||||
@Override
|
||||
public DefaultOrmQuery<T> setParameter(String name, Object value) {
|
||||
|
||||
if (namedParams != null) {
|
||||
ONamedParam param = namedParams.get(name);
|
||||
if (param != null) {
|
||||
param.setValue(value);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
if (bindParams == null) {
|
||||
bindParams = new BindParams();
|
||||
}
|
||||
@@ -1375,6 +1388,20 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
this.generatedSql = generatedSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiNamedParam createNamedParameter(String name) {
|
||||
if (namedParams == null) {
|
||||
namedParams = new HashMap<String, ONamedParam>();
|
||||
}
|
||||
|
||||
ONamedParam param = namedParams.get(name);
|
||||
if (param == null) {
|
||||
param = new ONamedParam(name);
|
||||
namedParams.put(name, param);
|
||||
}
|
||||
return param;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultFetchBuffer(int fetchSize) {
|
||||
if (bufferFetchSizeHint == 0) {
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.avaje.ebeaninternal.server.querydefn;
|
||||
|
||||
import com.avaje.ebeaninternal.api.SpiNamedParam;
|
||||
|
||||
public class ONamedParam implements SpiNamedParam {
|
||||
|
||||
private final String name;
|
||||
|
||||
private Object value;
|
||||
|
||||
public ONamedParam(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setValue(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user