mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
212 lines
4.9 KiB
Java
212 lines
4.9 KiB
Java
package io.ebeaninternal.server.querydefn;
|
|
|
|
import io.ebeaninternal.api.HashQueryPlanBuilder;
|
|
import io.ebeaninternal.server.deploy.DeployParser;
|
|
import io.ebeaninternal.server.persist.Binder;
|
|
import io.ebeaninternal.server.type.DataBind;
|
|
|
|
import java.sql.SQLException;
|
|
import java.util.LinkedHashMap;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
/**
|
|
* Set properties for a UpdateQuery.
|
|
*/
|
|
public class OrmUpdateProperties {
|
|
|
|
private static final NullValue NULL_VALUE = new NullValue();
|
|
|
|
private static final NoneValue NONE_VALUE = new NoneValue();
|
|
|
|
/**
|
|
* Bind value used in the set clause for update query.
|
|
* It may/may not have bind values etc.
|
|
*/
|
|
public static abstract class Value {
|
|
|
|
public void bind(Binder binder, DataBind dataBind) throws SQLException {
|
|
// default to no bind values
|
|
}
|
|
|
|
public String bindClause() {
|
|
return "";
|
|
}
|
|
|
|
public int getBindCount() {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set property to null.
|
|
*/
|
|
private static class NullValue extends Value {
|
|
@Override
|
|
public String bindClause() {
|
|
return "=null";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set property to a simple value.
|
|
*/
|
|
private static class SimpleValue extends Value {
|
|
|
|
final Object value;
|
|
|
|
SimpleValue(Object value) {
|
|
this.value = value;
|
|
}
|
|
|
|
@Override
|
|
public int getBindCount() {
|
|
return 1;
|
|
}
|
|
|
|
@Override
|
|
public String bindClause() {
|
|
return "=?";
|
|
}
|
|
|
|
@Override
|
|
public void bind(Binder binder, DataBind dataBind) throws SQLException {
|
|
binder.bindObject(dataBind, value);
|
|
dataBind.append(value).append(",");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set using an expression with no bind value.
|
|
*/
|
|
private static class NoneValue extends Value {
|
|
@Override
|
|
public String bindClause() {
|
|
return "";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set using an expression with many bind values.
|
|
*/
|
|
private static class RawArrayValue extends Value {
|
|
|
|
final Object[] bindValues;
|
|
|
|
RawArrayValue(Object[] bindValues) {
|
|
this.bindValues = bindValues;
|
|
}
|
|
|
|
@Override
|
|
public int getBindCount() {
|
|
return bindValues.length;
|
|
}
|
|
|
|
@Override
|
|
public void bind(Binder binder, DataBind dataBind) throws SQLException {
|
|
for (Object val : bindValues) {
|
|
binder.bindObject(dataBind, val);
|
|
dataBind.append(val).append(",");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The set properties/expressions and their bind values.
|
|
*/
|
|
private LinkedHashMap<String, Value> values = new LinkedHashMap<>();
|
|
|
|
/**
|
|
* Normal set property.
|
|
*/
|
|
public void set(String propertyName, Object value) {
|
|
if (value == null) {
|
|
values.put(propertyName, NULL_VALUE);
|
|
|
|
} else {
|
|
values.put(propertyName, new SimpleValue(value));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set a raw expression with no bind values.
|
|
*/
|
|
public void setRaw(String propertyName) {
|
|
values.put(propertyName, NONE_VALUE);
|
|
}
|
|
|
|
/**
|
|
* Set a raw expression with many bind values.
|
|
*/
|
|
void setRaw(String propertyExpression, Object... vals) {
|
|
if (vals.length == 0) {
|
|
setRaw(propertyExpression);
|
|
} else {
|
|
values.put(propertyExpression, new RawArrayValue(vals));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return true if this update has the same logical set clause.
|
|
*/
|
|
public boolean isSameByPlan(OrmUpdateProperties that) {
|
|
return that.values.size() == values.size()
|
|
&& logicalSetClause().equals(that.logicalSetClause());
|
|
}
|
|
|
|
/**
|
|
* Build the hash for the query plan caching.
|
|
*/
|
|
void buildQueryPlanHash(HashQueryPlanBuilder builder) {
|
|
builder.add(OrmUpdateProperties.class);
|
|
Set<Map.Entry<String, Value>> entries = values.entrySet();
|
|
for (Map.Entry<String, Value> entry : entries) {
|
|
builder.add(entry.getKey());
|
|
builder.bind(entry.getValue().getBindCount());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Bind all the bind values for the update set clause.
|
|
*/
|
|
public void bind(Binder binder, DataBind dataBind) throws SQLException {
|
|
for (Value bindValue : values.values()) {
|
|
bindValue.bind(binder, dataBind);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build the actual set clause converting logical property names to db columns etc.
|
|
*/
|
|
public String buildSetClause(DeployParser deployParser) {
|
|
|
|
int setCount = 0;
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
for (Map.Entry<String, Value> entry : values.entrySet()) {
|
|
String property = entry.getKey();
|
|
if (setCount++ > 0) {
|
|
sb.append(", ");
|
|
}
|
|
// translate to db columns and remove table alias placeholders
|
|
sb.append(deployParser.parse(property).replace("${}", ""));
|
|
sb.append(entry.getValue().bindClause());
|
|
}
|
|
return sb.toString();
|
|
}
|
|
|
|
/**
|
|
* Return a logical set clause to use for isSameByPlan() use.
|
|
*/
|
|
private String logicalSetClause() {
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
for (Map.Entry<String, Value> entry : values.entrySet()) {
|
|
sb.append(", ");
|
|
sb.append(entry.getKey()).append(entry.getValue().bindClause());
|
|
}
|
|
return sb.toString();
|
|
}
|
|
|
|
}
|