#1633 - ENH: Add bind parameter expansion for raw() expressions

This commit is contained in:
rob bygrave
2019-02-07 23:29:42 +13:00
parent efce6b57e1
commit ea60e42a4d
5 changed files with 212 additions and 11 deletions
@@ -529,7 +529,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
*/
@Override
public Expression raw(String raw, Object value) {
return new RawExpression(raw, new Object[]{value});
return RawExpressionBuilder.buildSingle(raw, value);
}
/**
@@ -541,7 +541,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
*/
@Override
public Expression raw(String raw, Object[] values) {
return new RawExpression(raw, values);
return RawExpressionBuilder.build(raw, values);
}
/**
@@ -12,9 +12,9 @@ import java.util.Collection;
class RawExpression extends NonPrepareExpression {
private final String sql;
final String sql;
private final Object[] values;
final Object[] values;
RawExpression(String sql, Object[] values) {
this.sql = sql;
@@ -0,0 +1,86 @@
package io.ebeaninternal.server.expression;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
class RawExpressionBuilder {
private static final String BP_1 = "?1";
private static final String[] BP = {BP_1, "?2", "?3", "?4", "?5", "?6", "?7", "?8",
"?9", "?10", "?11", "?12", "?13", "?14", "?15", "?16", "?17", "?18", "?19", "?20"};
/**
* Build RawExpression taking into account parameter expansion.
*/
static RawExpression buildSingle(String raw, Object value) {
if (isExpand(value, raw, BP_1)) {
Collection val = (Collection) value;
raw = raw.replace(BP_1, expand(val));
return new RawExpression(raw, val.toArray());
}
return new RawExpression(raw, new Object[]{value});
}
/**
* Build RawExpression for multiple bind values taking into account parameter expansion.
*/
static RawExpression build(String raw, Object[] values) {
for (int i = 0; i < values.length; i++) {
if (isExpand(values[i], raw, match(i))) {
return new RawExpressionBuilder(raw, values).build();
}
}
return new RawExpression(raw, values);
}
/**
* Return true if this value is a collection that should be expanded.
*/
private static boolean isExpand(Object value, String raw, String bindMatch) {
return value instanceof Collection && raw.contains(bindMatch);
}
private static String match(int i) {
if (i < 20) {
return BP[i];
}
return "?" + (i + 1);
}
private static String expand(Collection values) {
StringBuilder sqlExpand = new StringBuilder(values.size() * 2);
for (int i = 0; i < values.size(); i++) {
if (i > 0) {
sqlExpand.append(",");
}
sqlExpand.append("?");
}
return sqlExpand.toString();
}
private final String expanded;
private final List<Object> params = new ArrayList<>();
private RawExpressionBuilder(String raw, Object[] values) {
for (int i = 0; i < values.length; i++) {
String match = match(i);
if (!isExpand(values[i], raw, match)) {
params.add(values[i]);
} else {
Collection val = (Collection) values[i];
params.addAll(val);
raw = raw.replace(match, expand(val));
}
}
this.expanded = raw;
}
private RawExpression build() {
return new RawExpression(expanded, params.toArray());
}
}