mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-24 08:25:50 +00:00
#566 - Refactor internals - SpiExpression, add prepareExpression() to merge queryAutoTuneHash() and queryPlanHash() - sameByPlan() & sameByBind()
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
package com.avaje.ebeaninternal.api;
|
||||
|
||||
/**
|
||||
* Key used for caching query plans for ORM and RawSql queries.
|
||||
*/
|
||||
public interface CQueryPlanKey {
|
||||
|
||||
/**
|
||||
* Used by read audit such that we can log read audit entries without the full sql
|
||||
* (which would make the read audit logs verbose).
|
||||
*/
|
||||
String getPartialKey();
|
||||
|
||||
}
|
||||
@@ -5,32 +5,18 @@ package com.avaje.ebeaninternal.api;
|
||||
*/
|
||||
public class HashQuery {
|
||||
|
||||
private final HashQueryPlan planHash;
|
||||
private final CQueryPlanKey planHash;
|
||||
|
||||
private final int bindHash;
|
||||
|
||||
/**
|
||||
* Create the HashQuery.
|
||||
*/
|
||||
public HashQuery(HashQueryPlan planHash, int bindHash) {
|
||||
public HashQuery(CQueryPlanKey planHash, int bindHash) {
|
||||
this.planHash = planHash;
|
||||
this.bindHash = bindHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the query plan hash.
|
||||
*/
|
||||
public HashQueryPlan getPlanHash() {
|
||||
return planHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bind values hash.
|
||||
*/
|
||||
public int getBindHash() {
|
||||
return bindHash;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int hc = 31 * planHash.hashCode();
|
||||
hc = 31 * hc + bindHash;
|
||||
|
||||
@@ -9,14 +9,12 @@ public class HashQueryPlanBuilder {
|
||||
|
||||
private int bindCount;
|
||||
|
||||
private String rawSql;
|
||||
|
||||
public HashQueryPlanBuilder() {
|
||||
this.planHash = 92821;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return planHash+":"+bindCount+(rawSql != null ? ":r" : "");
|
||||
return planHash+":"+bindCount;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,19 +56,24 @@ public class HashQueryPlanBuilder {
|
||||
bindCount += extraBindCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add raw sql to the hash.
|
||||
*/
|
||||
public void addRawSql(String rawSql) {
|
||||
this.rawSql = rawSql;
|
||||
public void bindIfNotNull(Object someValue) {
|
||||
if (someValue != null) {
|
||||
bindCount++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and return the calculated HashQueryPlan.
|
||||
*/
|
||||
public HashQueryPlan build() {
|
||||
return new HashQueryPlan(rawSql, planHash, bindCount);
|
||||
public String build() {
|
||||
return planHash+"_"+bindCount;
|
||||
}
|
||||
|
||||
|
||||
public int getPlanHash() {
|
||||
return planHash;
|
||||
}
|
||||
|
||||
public int getBindCount() {
|
||||
return bindCount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,16 @@ public interface SpiExpression extends Expression {
|
||||
*/
|
||||
int queryBindHash();
|
||||
|
||||
/**
|
||||
* Return true if the expression is the same without taking into account bind values.
|
||||
*/
|
||||
boolean isSameByPlan(SpiExpression other);
|
||||
|
||||
/**
|
||||
* Return true if the expression is the same with respect to bind values.
|
||||
*/
|
||||
boolean isSameByBind(SpiExpression other);
|
||||
|
||||
/**
|
||||
* Add some sql to the query.
|
||||
* <p>
|
||||
@@ -65,4 +75,10 @@ public interface SpiExpression extends Expression {
|
||||
* Validate all the properties/paths associated with this expression.
|
||||
*/
|
||||
void validate(SpiExpressionValidation validation);
|
||||
|
||||
/**
|
||||
* Return a copy of the expression for use in the query plan key.
|
||||
*/
|
||||
SpiExpression copyForPlanKey();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
package com.avaje.ebeaninternal.api;
|
||||
|
||||
import com.avaje.ebean.ExpressionFactory;
|
||||
import com.avaje.ebean.ExpressionList;
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Internal extension of ExpressionList.
|
||||
*/
|
||||
public interface SpiExpressionList<T> extends ExpressionList<T> {
|
||||
public interface SpiExpressionList<T> extends ExpressionList<T>, SpiExpression {
|
||||
|
||||
/**
|
||||
* Return the underlying list of expressions.
|
||||
@@ -22,57 +19,9 @@ public interface SpiExpressionList<T> extends ExpressionList<T> {
|
||||
*/
|
||||
SpiExpressionList<?> trimPath(int prefixTrim);
|
||||
|
||||
/**
|
||||
* Restore the ExpressionFactory after deserialisation.
|
||||
*/
|
||||
void setExpressionFactory(ExpressionFactory expr);
|
||||
|
||||
/**
|
||||
* Process "Many" properties populating ManyWhereJoins.
|
||||
* <p>
|
||||
* Predicates on Many properties require an extra independent join clause.
|
||||
* </p>
|
||||
*/
|
||||
void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoins);
|
||||
|
||||
/**
|
||||
* Return true if this list is empty.
|
||||
*/
|
||||
boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Concatenate the expression sql into a String.
|
||||
* <p>
|
||||
* The list of expressions are evaluated in order building a sql statement
|
||||
* with bind parameters.
|
||||
* </p>
|
||||
*/
|
||||
String buildSql(SpiExpressionRequest request);
|
||||
|
||||
/**
|
||||
* Combine the expression bind values into a list.
|
||||
* <p>
|
||||
* Expressions are evaluated in order and all the resulting bind values are
|
||||
* returned as a List.
|
||||
* </p>
|
||||
*
|
||||
* @return the list of all the bind values in order.
|
||||
*/
|
||||
List<Object> buildBindValues(SpiExpressionRequest request);
|
||||
|
||||
/**
|
||||
* Prepare the expressions contained in the list. For example, compile sub-query expressions etc.
|
||||
*/
|
||||
void prepareExpression(BeanQueryRequest<?> request);
|
||||
|
||||
/**
|
||||
* Calculate a hash based on the expressions but excluding the actual bind
|
||||
* values.
|
||||
*/
|
||||
void queryPlanHash(HashQueryPlanBuilder builder);
|
||||
|
||||
/**
|
||||
* Validate all the properties/paths used in this expression list.
|
||||
*/
|
||||
void validate(SpiExpressionValidation validation);
|
||||
}
|
||||
|
||||
@@ -467,17 +467,13 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Identifies queries that are the same bar the bind variables.
|
||||
* Prepare the query which prepares sub-query expressions and calculates
|
||||
* and returns the query plan key.
|
||||
* <p>
|
||||
* This is used AFTER AutoTune has potentially tuned the query. This is
|
||||
* used to identify and reused query plans (the final SQL string and
|
||||
* associated SqlTree object).
|
||||
* </p>
|
||||
* <p>
|
||||
* Excludes the actual bind values (as they don't effect the query plan).
|
||||
* The query plan excludes actual bind values (as they don't effect the query plan).
|
||||
* </p>
|
||||
*/
|
||||
HashQueryPlan queryPlanHash(BeanQueryRequest<?> request);
|
||||
CQueryPlanKey prepare(BeanQueryRequest<?> request);
|
||||
|
||||
/**
|
||||
* Calculate a hash based on the bind values used in the query.
|
||||
|
||||
@@ -1110,7 +1110,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
|
||||
// the query hash after any tuning
|
||||
request.calculateQueryPlanHash();
|
||||
request.prepareQuery();
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.*;
|
||||
import com.avaje.ebean.PersistenceContextScope;
|
||||
import com.avaje.ebean.QueryEachConsumer;
|
||||
import com.avaje.ebean.QueryEachWhileConsumer;
|
||||
import com.avaje.ebean.QueryIterator;
|
||||
import com.avaje.ebean.RawSql;
|
||||
import com.avaje.ebean.Version;
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.bean.PersistenceContext;
|
||||
@@ -16,8 +13,8 @@ import com.avaje.ebean.event.BeanFindController;
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebeaninternal.api.BeanIdList;
|
||||
import com.avaje.ebeaninternal.api.HashQuery;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlan;
|
||||
import com.avaje.ebeaninternal.api.LoadContext;
|
||||
import com.avaje.ebeaninternal.api.CQueryPlanKey;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery.Type;
|
||||
@@ -32,6 +29,13 @@ import com.avaje.ebeaninternal.server.query.CQueryPlan;
|
||||
import com.avaje.ebeaninternal.server.query.CancelableQuery;
|
||||
import com.avaje.ebeaninternal.server.transaction.DefaultPersistenceContext;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Wraps the objects involved in executing a Query.
|
||||
*/
|
||||
@@ -55,7 +59,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
|
||||
private HashQuery cacheKey;
|
||||
|
||||
private HashQueryPlan queryPlanHash;
|
||||
private CQueryPlanKey queryPlanKey;
|
||||
|
||||
/**
|
||||
* Create the InternalQueryRequest.
|
||||
@@ -126,10 +130,10 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the query plan hash AFTER any potential AutoTune tuning.
|
||||
* Prepare the query and calculate the query plan key.
|
||||
*/
|
||||
public void calculateQueryPlanHash() {
|
||||
this.queryPlanHash = query.queryPlanHash(this);
|
||||
public void prepareQuery() {
|
||||
this.queryPlanKey = query.prepare(this);
|
||||
}
|
||||
|
||||
public boolean isRawSql() {
|
||||
@@ -355,7 +359,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
* query plan for this query exists.
|
||||
*/
|
||||
public CQueryPlan getQueryPlan() {
|
||||
return beanDescriptor.getQueryPlan(queryPlanHash);
|
||||
return beanDescriptor.getQueryPlan(queryPlanKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -366,15 +370,15 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
* with just the bind variables changing.
|
||||
* </p>
|
||||
*/
|
||||
public HashQueryPlan getQueryPlanHash() {
|
||||
return queryPlanHash;
|
||||
public CQueryPlanKey getQueryPlanKey() {
|
||||
return queryPlanKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put the QueryPlan into the cache.
|
||||
*/
|
||||
public void putQueryPlan(CQueryPlan queryPlan) {
|
||||
beanDescriptor.putQueryPlan(queryPlanHash, queryPlan);
|
||||
beanDescriptor.putQueryPlan(queryPlanKey, queryPlan);
|
||||
}
|
||||
|
||||
public boolean isUseBeanCache() {
|
||||
@@ -401,7 +405,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
for (T bean : actualDetails) {
|
||||
ids.add(beanDescriptor.getIdForJson(bean));
|
||||
}
|
||||
beanDescriptor.readAuditMany(queryPlanHash.getPartialKey(), "l2-query-cache", ids);
|
||||
beanDescriptor.readAuditMany(queryPlanKey.getPartialKey(), "l2-query-cache", ids);
|
||||
}
|
||||
|
||||
return cached;
|
||||
|
||||
@@ -29,7 +29,7 @@ import com.avaje.ebean.event.readaudit.ReadEvent;
|
||||
import com.avaje.ebean.meta.MetaBeanInfo;
|
||||
import com.avaje.ebean.meta.MetaQueryPlanStatistic;
|
||||
import com.avaje.ebean.plugin.SpiBeanType;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlan;
|
||||
import com.avaje.ebeaninternal.api.CQueryPlanKey;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.api.SpiTransaction;
|
||||
@@ -87,7 +87,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo, SpiBeanType<T> {
|
||||
|
||||
private final ConcurrentHashMap<Integer, SpiUpdatePlan> updatePlanCache = new ConcurrentHashMap<Integer, SpiUpdatePlan>();
|
||||
|
||||
private final ConcurrentHashMap<HashQueryPlan, CQueryPlan> queryPlanCache = new ConcurrentHashMap<HashQueryPlan, CQueryPlan>();
|
||||
private final ConcurrentHashMap<CQueryPlanKey, CQueryPlan> queryPlanCache = new ConcurrentHashMap<CQueryPlanKey, CQueryPlan>();
|
||||
|
||||
private final ConcurrentHashMap<String, ElPropertyValue> elCache = new ConcurrentHashMap<String, ElPropertyValue>();
|
||||
|
||||
@@ -1163,11 +1163,11 @@ public class BeanDescriptor<T> implements MetaBeanInfo, SpiBeanType<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public CQueryPlan getQueryPlan(HashQueryPlan key) {
|
||||
public CQueryPlan getQueryPlan(CQueryPlanKey key) {
|
||||
return queryPlanCache.get(key);
|
||||
}
|
||||
|
||||
public void putQueryPlan(HashQueryPlan key, CQueryPlan plan) {
|
||||
public void putQueryPlan(CQueryPlanKey key, CQueryPlan plan) {
|
||||
queryPlanCache.put(key, plan);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import com.avaje.ebean.SqlUpdate;
|
||||
import com.avaje.ebeaninternal.api.BindParams;
|
||||
import com.avaje.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
import com.avaje.ebeaninternal.server.expression.IdInExpression;
|
||||
import com.avaje.ebeaninternal.util.DefaultExpressionRequest;
|
||||
import com.avaje.ebeaninternal.server.expression.DefaultExpressionRequest;
|
||||
|
||||
public class IntersectionRow {
|
||||
|
||||
|
||||
@@ -63,6 +63,32 @@ public final class TableJoin {
|
||||
return hc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return queryHash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
TableJoin that = (TableJoin) o;
|
||||
|
||||
if (!table.equals(that.table)) return false;
|
||||
if (type != that.type) return false;
|
||||
if (columns.length != that.columns.length) return false;
|
||||
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
if (!columns[i].equals(that.columns[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return a hash value for adding to a query plan.
|
||||
*/
|
||||
|
||||
@@ -8,76 +8,97 @@ import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoinColumn;
|
||||
*/
|
||||
public class TableJoinColumn {
|
||||
|
||||
/**
|
||||
* The local database column name.
|
||||
*/
|
||||
private final String localDbColumn;
|
||||
/**
|
||||
* The local database column name.
|
||||
*/
|
||||
private final String localDbColumn;
|
||||
|
||||
/**
|
||||
* The foreign database column name.
|
||||
*/
|
||||
private final String foreignDbColumn;
|
||||
/**
|
||||
* The foreign database column name.
|
||||
*/
|
||||
private final String foreignDbColumn;
|
||||
|
||||
private final boolean insertable;
|
||||
|
||||
private final boolean updateable;
|
||||
private final boolean insertable;
|
||||
|
||||
/**
|
||||
* Hash for including in a query plan
|
||||
*/
|
||||
private final int queryHash;
|
||||
private final boolean updateable;
|
||||
|
||||
/**
|
||||
* Create the pair.
|
||||
*/
|
||||
public TableJoinColumn(DeployTableJoinColumn deploy) {
|
||||
this.localDbColumn = InternString.intern(deploy.getLocalDbColumn());
|
||||
this.foreignDbColumn = InternString.intern(deploy.getForeignDbColumn());
|
||||
this.insertable = deploy.isInsertable();
|
||||
this.updateable = deploy.isUpdateable();
|
||||
this.queryHash = hashOf(localDbColumn) * 31 + hashOf(foreignDbColumn);
|
||||
}
|
||||
/**
|
||||
* Hash for including in a query plan
|
||||
*/
|
||||
private final int queryHash;
|
||||
|
||||
private int hashOf(String value) {
|
||||
return (value == null) ? 0 : value.hashCode();
|
||||
}
|
||||
/**
|
||||
* Create the pair.
|
||||
*/
|
||||
public TableJoinColumn(DeployTableJoinColumn deploy) {
|
||||
this.localDbColumn = InternString.intern(deploy.getLocalDbColumn());
|
||||
this.foreignDbColumn = InternString.intern(deploy.getForeignDbColumn());
|
||||
this.insertable = deploy.isInsertable();
|
||||
this.updateable = deploy.isUpdateable();
|
||||
this.queryHash = hash();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return localDbColumn+" = "+foreignDbColumn;
|
||||
}
|
||||
int hash() {
|
||||
int result = localDbColumn != null ? localDbColumn.hashCode() : 0;
|
||||
result = 31 * result + (foreignDbColumn != null ? foreignDbColumn.hashCode() : 0);
|
||||
result = 31 * result + (insertable ? 1 : 0);
|
||||
result = 31 * result + (updateable ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a hash for including in a query plan.
|
||||
*/
|
||||
public int queryHash() {
|
||||
return queryHash;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return queryHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the foreign database column name.
|
||||
*/
|
||||
public String getForeignDbColumn() {
|
||||
return foreignDbColumn;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
/**
|
||||
* Return the local database column name.
|
||||
*/
|
||||
public String getLocalDbColumn() {
|
||||
return localDbColumn;
|
||||
}
|
||||
TableJoinColumn that = (TableJoinColumn) o;
|
||||
if (insertable != that.insertable) return false;
|
||||
if (updateable != that.updateable) return false;
|
||||
if (!localDbColumn.equals(that.localDbColumn)) return false;
|
||||
return foreignDbColumn.equals(that.foreignDbColumn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this column should be insertable.
|
||||
*/
|
||||
public boolean isInsertable() {
|
||||
return insertable;
|
||||
}
|
||||
public String toString() {
|
||||
return localDbColumn + " = " + foreignDbColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this column should be updateable.
|
||||
*/
|
||||
public boolean isUpdateable() {
|
||||
return updateable;
|
||||
}
|
||||
/**
|
||||
* Return a hash for including in a query plan.
|
||||
*/
|
||||
public int queryHash() {
|
||||
return queryHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the foreign database column name.
|
||||
*/
|
||||
public String getForeignDbColumn() {
|
||||
return foreignDbColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the local database column name.
|
||||
*/
|
||||
public String getLocalDbColumn() {
|
||||
return localDbColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this column should be insertable.
|
||||
*/
|
||||
public boolean isInsertable() {
|
||||
return insertable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this column should be updateable.
|
||||
*/
|
||||
public boolean isUpdateable() {
|
||||
return updateable;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,19 +22,20 @@ public abstract class AbstractExpression implements SpiExpression {
|
||||
this.propName = propName;
|
||||
}
|
||||
|
||||
public String getPropertyName() {
|
||||
return propName;
|
||||
@Override
|
||||
public SpiExpression copyForPlanKey() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
|
||||
|
||||
String propertyName = getPropertyName();
|
||||
if (propertyName != null) {
|
||||
ElPropertyDeploy elProp = desc.getElPropertyDeploy(propertyName);
|
||||
if (propName != null) {
|
||||
ElPropertyDeploy elProp = desc.getElPropertyDeploy(propName);
|
||||
if (elProp != null) {
|
||||
if (elProp.containsFormulaWithJoin()) {
|
||||
// for findRowCount query select clause
|
||||
manyWhereJoin.addFormulaWithJoin(propertyName);
|
||||
manyWhereJoin.addFormulaWithJoin(propName);
|
||||
}
|
||||
if (elProp.containsMany()) {
|
||||
// for findRowCount we join to a many property
|
||||
@@ -51,12 +52,11 @@ public abstract class AbstractExpression implements SpiExpression {
|
||||
|
||||
@Override
|
||||
public void validate(SpiExpressionValidation validation) {
|
||||
validation.validate(getPropertyName());
|
||||
validation.validate(propName);
|
||||
}
|
||||
|
||||
protected ElPropertyValue getElProp(SpiExpressionRequest request) {
|
||||
protected final ElPropertyValue getElProp(SpiExpressionRequest request) {
|
||||
|
||||
String propertyName = getPropertyName();
|
||||
return request.getBeanDescriptor().getElGetValue(propertyName);
|
||||
return request.getBeanDescriptor().getElGetValue(propName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,13 @@ package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.ManyWhereJoins;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionValidation;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.el.ElPropertyDeploy;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
@@ -102,7 +104,7 @@ class AllEqualsExpression extends NonPrepareExpression {
|
||||
Object value = entry.getValue();
|
||||
String propName = entry.getKey();
|
||||
builder.add(propName).add(value == null ? 0 : 1);
|
||||
builder.bind(value == null ? 0 : 1);
|
||||
builder.bindIfNotNull(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,4 +118,48 @@ class AllEqualsExpression extends NonPrepareExpression {
|
||||
|
||||
return hc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
if (!(other instanceof AllEqualsExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AllEqualsExpression that = (AllEqualsExpression) other;
|
||||
return isSameByValue(that, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
if (!(other instanceof AllEqualsExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AllEqualsExpression that = (AllEqualsExpression) other;
|
||||
return isSameByValue(that, true);
|
||||
}
|
||||
|
||||
private boolean isSameByValue(AllEqualsExpression that, boolean byValue) {
|
||||
|
||||
if (propMap.size() != that.propMap.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Iterator<Entry<String, Object>> thisIt = propMap.entrySet().iterator();
|
||||
Iterator<Entry<String, Object>> thatIt = that.propMap.entrySet().iterator();
|
||||
|
||||
while (thisIt.hasNext() && thatIt.hasNext()) {
|
||||
Entry<String, Object> thisNext = thisIt.next();
|
||||
Entry<String, Object> thatNext = thatIt.next();
|
||||
|
||||
if (!thisNext.getKey().equals(thatNext.getKey())) {
|
||||
return false;
|
||||
}
|
||||
if (!Same.sameBy(byValue, thisNext.getValue(), thatNext.getValue())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
|
||||
|
||||
class BetweenExpression extends AbstractExpression {
|
||||
|
||||
private static final long serialVersionUID = 2078918165221454910L;
|
||||
@@ -30,7 +29,7 @@ class BetweenExpression extends AbstractExpression {
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
|
||||
request.append(getPropertyName()).append(BETWEEN).append(" ? and ? ");
|
||||
request.append(propName).append(BETWEEN).append(" ? and ? ");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -45,4 +44,21 @@ class BetweenExpression extends AbstractExpression {
|
||||
hc = hc * 31 + valueHigh.hashCode();
|
||||
return hc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
if (!(other instanceof BetweenExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BetweenExpression that = (BetweenExpression) other;
|
||||
return this.propName.equals(that.propName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
BetweenExpression that = (BetweenExpression) other;
|
||||
return valueLow.equals(that.valueLow)
|
||||
&& valueHigh.equals(that.valueHigh);
|
||||
}
|
||||
}
|
||||
|
||||
+19
@@ -2,6 +2,7 @@ package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.ManyWhereJoins;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionValidation;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
@@ -50,6 +51,7 @@ class BetweenPropertyExpression extends NonPrepareExpression {
|
||||
validation.validate(highProperty);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
request.addBindValue(value);
|
||||
}
|
||||
@@ -70,4 +72,21 @@ class BetweenPropertyExpression extends NonPrepareExpression {
|
||||
public int queryBindHash() {
|
||||
return value.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
if (!(other instanceof BetweenPropertyExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BetweenPropertyExpression that = (BetweenPropertyExpression) other;
|
||||
return lowProperty.equals(that.lowProperty)
|
||||
&& highProperty.equals(that.highProperty);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
BetweenPropertyExpression that = (BetweenPropertyExpression) other;
|
||||
return value.equals(that.value);
|
||||
}
|
||||
}
|
||||
|
||||
+21
-5
@@ -1,7 +1,7 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
|
||||
@@ -16,6 +16,7 @@ class CaseInsensitiveEqualExpression extends AbstractExpression {
|
||||
this.value = value.toLowerCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
|
||||
ElPropertyValue prop = getElProp(request);
|
||||
@@ -28,14 +29,13 @@ class CaseInsensitiveEqualExpression extends AbstractExpression {
|
||||
request.addBindValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
|
||||
String propertyName = getPropertyName();
|
||||
String pname = propertyName;
|
||||
|
||||
String pname = propName;
|
||||
ElPropertyValue prop = getElProp(request);
|
||||
if (prop != null && prop.isDbEncrypted()) {
|
||||
pname = prop.getBeanProperty().getDecryptProperty(propertyName);
|
||||
pname = prop.getBeanProperty().getDecryptProperty(propName);
|
||||
}
|
||||
|
||||
request.append("lower(").append(pname).append(") =? ");
|
||||
@@ -51,4 +51,20 @@ class CaseInsensitiveEqualExpression extends AbstractExpression {
|
||||
public int queryBindHash() {
|
||||
return value.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
if (!(other instanceof CaseInsensitiveEqualExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CaseInsensitiveEqualExpression that = (CaseInsensitiveEqualExpression) other;
|
||||
return this.propName.equals(that.propName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
CaseInsensitiveEqualExpression that = (CaseInsensitiveEqualExpression) other;
|
||||
return value.equals(that.value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +86,19 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio
|
||||
this.likeType = likeType;
|
||||
}
|
||||
|
||||
DefaultExampleExpression(ArrayList<SpiExpression> source) {
|
||||
this.entity = null;
|
||||
this.list = new ArrayList<SpiExpression>(source.size());
|
||||
for (SpiExpression expression : source) {
|
||||
list.add(expression.copyForPlanKey());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpression copyForPlanKey() {
|
||||
return new DefaultExampleExpression(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins whereManyJoins) {
|
||||
if (list != null) {
|
||||
@@ -201,6 +214,38 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio
|
||||
return hc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
if (!(other instanceof DefaultExampleExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DefaultExampleExpression that = (DefaultExampleExpression) other;
|
||||
if (this.list.size() != that.list.size()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (!list.get(i).isSameByPlan(that.list.get(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
DefaultExampleExpression that = (DefaultExampleExpression) other;
|
||||
if (this.list.size() != that.list.size()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (!list.get(i).isSameByBind(that.list.get(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the List of expressions.
|
||||
*/
|
||||
|
||||
+49
-19
@@ -1,4 +1,4 @@
|
||||
package com.avaje.ebeaninternal.util;
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
@@ -56,6 +56,10 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
this.listAndJoin = " and ";
|
||||
}
|
||||
|
||||
private DefaultExpressionList() {
|
||||
this(null, null, null, new ArrayList<SpiExpression>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpressionList<?> trimPath(int prefixTrim) {
|
||||
throw new RuntimeException("Only allowed on FilterExpressionList");
|
||||
@@ -65,17 +69,6 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ExpressionFactory.
|
||||
* <p>
|
||||
* After deserialisation so that it can be further modified.
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
public void setExpressionFactory(ExpressionFactory expr) {
|
||||
this.expr = expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a copy of the expression list.
|
||||
* <p>
|
||||
@@ -88,6 +81,14 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return copy;
|
||||
}
|
||||
|
||||
public DefaultExpressionList<T> copyForPlanKey() {
|
||||
DefaultExpressionList<T> copy = new DefaultExpressionList<T>();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
copy.list.add(list.get(i).copyForPlanKey());
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if one of the expressions is related to a Many property.
|
||||
*/
|
||||
@@ -325,7 +326,7 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildSql(SpiExpressionRequest request) {
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
|
||||
request.append(listAndStart);
|
||||
for (int i = 0, size = list.size(); i < size; i++) {
|
||||
@@ -336,17 +337,13 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
expression.addSql(request);
|
||||
}
|
||||
request.append(listAndEnd);
|
||||
return request.getSql();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> buildBindValues(SpiExpressionRequest request) {
|
||||
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
for (int i = 0, size = list.size(); i < size; i++) {
|
||||
SpiExpression expression = list.get(i);
|
||||
expression.addBindValues(request);
|
||||
list.get(i).addBindValues(request);
|
||||
}
|
||||
return request.getBindValues();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -371,6 +368,7 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
/**
|
||||
* Calculate a hash based on the expressions.
|
||||
*/
|
||||
@Override
|
||||
public int queryBindHash() {
|
||||
int hash = DefaultExpressionList.class.getName().hashCode();
|
||||
for (int i = 0, size = list.size(); i < size; i++) {
|
||||
@@ -379,6 +377,38 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
if (!(other instanceof DefaultExpressionList)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DefaultExpressionList<?> that = (DefaultExpressionList<?>)other;
|
||||
if (list.size() != that.list.size()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0, size = list.size(); i < size; i++) {
|
||||
if (!list.get(i).isSameByPlan(that.list.get(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
DefaultExpressionList<?> that = (DefaultExpressionList<?>)other;
|
||||
if (list.size() != that.list.size()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0, size = list.size(); i < size; i++) {
|
||||
if (!list.get(i).isSameByBind(that.list.get(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Path exists - for the given path in a JSON document.
|
||||
*/
|
||||
+14
-3
@@ -1,4 +1,4 @@
|
||||
package com.avaje.ebeaninternal.util;
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
@@ -40,7 +40,7 @@ public class DefaultExpressionRequest implements SpiExpressionRequest {
|
||||
this.binder = binder;
|
||||
this.expressionList = expressionList;
|
||||
// immediately build the list of bind values (callback style)
|
||||
expressionList.buildBindValues(this);
|
||||
expressionList.addBindValues(this);
|
||||
}
|
||||
|
||||
public DefaultExpressionRequest(BeanDescriptor<?> beanDescriptor) {
|
||||
@@ -55,7 +55,8 @@ public class DefaultExpressionRequest implements SpiExpressionRequest {
|
||||
* Build sql for the underlying expression list.
|
||||
*/
|
||||
public String buildSql() {
|
||||
return expressionList.buildSql(this);
|
||||
expressionList.addSql(this);
|
||||
return sql.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,10 +72,12 @@ public class DefaultExpressionRequest implements SpiExpressionRequest {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonExpressionHandler getJsonHandler() {
|
||||
return binder.getJsonExpressionHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parseDeploy(String logicalProp) {
|
||||
|
||||
String s = deployParser.getDeployWord(logicalProp);
|
||||
@@ -94,14 +97,17 @@ public class DefaultExpressionRequest implements SpiExpressionRequest {
|
||||
/**
|
||||
* Increments the parameter index and returns that value.
|
||||
*/
|
||||
@Override
|
||||
public int nextParameter() {
|
||||
return ++paramIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanDescriptor<?> getBeanDescriptor() {
|
||||
return beanDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiOrmQueryRequest<?> getQueryRequest() {
|
||||
return queryRequest;
|
||||
}
|
||||
@@ -109,16 +115,19 @@ public class DefaultExpressionRequest implements SpiExpressionRequest {
|
||||
/**
|
||||
* Append text the underlying sql expression.
|
||||
*/
|
||||
@Override
|
||||
public SpiExpressionRequest append(String sqlExpression) {
|
||||
sql.append(sqlExpression);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindEncryptKey(Object bindValue) {
|
||||
bindValues.add(bindValue);
|
||||
bindLog("****");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValue(Object bindValue) {
|
||||
bindValues.add(bindValue);
|
||||
bindLog(bindValue);
|
||||
@@ -137,10 +146,12 @@ public class DefaultExpressionRequest implements SpiExpressionRequest {
|
||||
return bindLog == null ? "" : bindLog.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSql() {
|
||||
return sql.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> getBindValues() {
|
||||
return bindValues;
|
||||
}
|
||||
@@ -17,19 +17,26 @@ public class ExistsExpression implements SpiExpression {
|
||||
|
||||
private static final long serialVersionUID = 666990277309851644L;
|
||||
|
||||
private final boolean not;
|
||||
protected final boolean not;
|
||||
|
||||
private final SpiQuery<?> subQuery;
|
||||
protected final SpiQuery<?> subQuery;
|
||||
|
||||
private List<Object> bindParams;
|
||||
protected List<Object> bindParams;
|
||||
|
||||
private String sql;
|
||||
protected String sql;
|
||||
|
||||
public ExistsExpression(SpiQuery<?> subQuery, boolean not) {
|
||||
this.subQuery = subQuery;
|
||||
this.not = not;
|
||||
}
|
||||
|
||||
ExistsExpression(boolean not, String sql , List<Object> bindParams) {
|
||||
this.not = not;
|
||||
this.sql = sql;
|
||||
this.bindParams = bindParams;
|
||||
this.subQuery = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareExpression(BeanQueryRequest<?> request) {
|
||||
|
||||
@@ -38,10 +45,15 @@ public class ExistsExpression implements SpiExpression {
|
||||
this.sql = subQuery.getGeneratedSql().replace('\n', ' ');
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpression copyForPlanKey() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile/build the sub query.
|
||||
*/
|
||||
private CQuery<?> compileSubQuery(BeanQueryRequest<?> queryRequest) {
|
||||
protected CQuery<?> compileSubQuery(BeanQueryRequest<?> queryRequest) {
|
||||
SpiEbeanServer ebeanServer = (SpiEbeanServer) queryRequest.getEbeanServer();
|
||||
return ebeanServer.compileQuery(subQuery, queryRequest.getTransaction());
|
||||
}
|
||||
@@ -76,6 +88,32 @@ public class ExistsExpression implements SpiExpression {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
if (!(other instanceof ExistsExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ExistsExpression that = (ExistsExpression) other;
|
||||
return this.sql.equals(that.sql)
|
||||
&& this.not == that.not
|
||||
&& this.bindParams.size() == that.bindParams.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
ExistsExpression that = (ExistsExpression) other;
|
||||
if (this.bindParams.size() != that.bindParams.size()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < bindParams.size(); i++) {
|
||||
if (!bindParams.get(i).equals(that.bindParams.get(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins whereManyJoins) {
|
||||
// Nothing to do for exists expression
|
||||
|
||||
+1
-2
@@ -1,8 +1,7 @@
|
||||
package com.avaje.ebeaninternal.util;
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebean.*;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionList;
|
||||
import com.avaje.ebeaninternal.server.expression.FilterExprPath;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.util.List;
|
||||
@@ -6,7 +6,6 @@ import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionValidation;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.util.DefaultExpressionRequest;
|
||||
|
||||
/**
|
||||
* Slightly redundant as Query.setId() ultimately also does the same job.
|
||||
@@ -69,4 +68,14 @@ class IdExpression extends NonPrepareExpression implements SpiExpression {
|
||||
return value.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
return other instanceof IdExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
IdExpression that = (IdExpression) other;
|
||||
return value.equals(that.value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@ package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.ManyWhereJoins;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionValidation;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
|
||||
import com.avaje.ebeaninternal.util.DefaultExpressionRequest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -86,4 +86,27 @@ public class IdInExpression extends NonPrepareExpression {
|
||||
return idList.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
if (!(other instanceof IdInExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
IdInExpression that = (IdInExpression) other;
|
||||
return this.idList.size() == that.idList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
IdInExpression that = (IdInExpression) other;
|
||||
if (this.idList.size() != that.idList.size()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < idList.size(); i++) {
|
||||
if (!idList.get(i).equals(that.idList.get(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
|
||||
@@ -61,20 +61,18 @@ class InExpression extends AbstractExpression {
|
||||
return;
|
||||
}
|
||||
|
||||
String propertyName = getPropertyName();
|
||||
|
||||
ElPropertyValue prop = getElProp(request);
|
||||
if (prop != null && !prop.isAssocId()) {
|
||||
prop = null;
|
||||
}
|
||||
|
||||
if (prop != null) {
|
||||
request.append(prop.getAssocIdInExpr(propertyName));
|
||||
request.append(prop.getAssocIdInExpr(propName));
|
||||
String inClause = prop.getAssocIdInValueExpr(values.length);
|
||||
request.append(inClause);
|
||||
|
||||
} else {
|
||||
request.append(propertyName);
|
||||
request.append(propName);
|
||||
if (not) {
|
||||
request.append(" not");
|
||||
}
|
||||
@@ -105,4 +103,29 @@ class InExpression extends AbstractExpression {
|
||||
return hc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
if (!(other instanceof InExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
InExpression that = (InExpression) other;
|
||||
return propName.equals(that.propName)
|
||||
&& not == that.not
|
||||
&& values.length == that.values.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
InExpression that = (InExpression) other;
|
||||
if (this.values.length != that.values.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (!values[i].equals(that.values[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.server.query.CQuery;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* In expression using a sub query.
|
||||
*/
|
||||
@@ -24,12 +25,20 @@ class InQueryExpression extends AbstractExpression {
|
||||
|
||||
private String sql;
|
||||
|
||||
public InQueryExpression(String propertyName, SpiQuery<?> subQuery, boolean not) {
|
||||
InQueryExpression(String propertyName, SpiQuery<?> subQuery, boolean not) {
|
||||
super(propertyName);
|
||||
this.subQuery = subQuery;
|
||||
this.not = not;
|
||||
}
|
||||
|
||||
InQueryExpression(String propertyName, boolean not, String sql, List<Object> bindParams) {
|
||||
super(propertyName);
|
||||
this.subQuery = null;
|
||||
this.not = not;
|
||||
this.sql = sql;
|
||||
this.bindParams = bindParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareExpression(BeanQueryRequest<?> request) {
|
||||
|
||||
@@ -61,7 +70,7 @@ class InQueryExpression extends AbstractExpression {
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
|
||||
request.append(" (").append(getPropertyName()).append(")");
|
||||
request.append(" (").append(propName).append(")");
|
||||
if (not) {
|
||||
request.append(" not");
|
||||
}
|
||||
@@ -77,4 +86,31 @@ class InQueryExpression extends AbstractExpression {
|
||||
request.addBindValue(bindParams.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
if (!(other instanceof InQueryExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
InQueryExpression that = (InQueryExpression) other;
|
||||
return propName.equals(that.propName)
|
||||
&& sql.equals(that.sql)
|
||||
&& not == that.not
|
||||
&& bindParams.size() == that.bindParams.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
InQueryExpression that = (InQueryExpression) other;
|
||||
if (this.bindParams.size() != that.bindParams.size()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < bindParams.size(); i++) {
|
||||
if (!bindParams.get(i).equals(that.bindParams.get(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
|
||||
/**
|
||||
@@ -60,6 +60,8 @@ class JsonPathExpression extends AbstractExpression {
|
||||
@Override
|
||||
public void queryPlanHash(HashQueryPlanBuilder builder) {
|
||||
builder.add(JsonPathExpression.class).add(propName).add(path).add(operator);
|
||||
builder.bindIfNotNull(value);
|
||||
builder.bindIfNotNull(upperValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,6 +71,27 @@ class JsonPathExpression extends AbstractExpression {
|
||||
return hc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
if (!(other instanceof JsonPathExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JsonPathExpression that = (JsonPathExpression) other;
|
||||
return propName.equals(that.propName)
|
||||
&& operator == that.operator
|
||||
&& Same.sameByValue(path, that.path)
|
||||
&& Same.sameByNull(value, that.value)
|
||||
&& Same.sameByNull(upperValue, that.upperValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
JsonPathExpression that = (JsonPathExpression) other;
|
||||
if (value != null ? !value.equals(that.value) : that.value != null) return false;
|
||||
return upperValue != null ? upperValue.equals(that.upperValue) : that.upperValue == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionValidation;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.util.DefaultExpressionList;
|
||||
|
||||
/**
|
||||
* Junction implementation.
|
||||
@@ -35,6 +34,14 @@ abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, Expr
|
||||
Conjunction(com.avaje.ebean.Query<T> query, ExpressionList<T> parent) {
|
||||
super(false, AND, query, parent);
|
||||
}
|
||||
|
||||
Conjunction(DefaultExpressionList<T> expressionList) {
|
||||
super(false, AND, expressionList);
|
||||
}
|
||||
@Override
|
||||
public SpiExpression copyForPlanKey() {
|
||||
return new Conjunction<T>(exprList.copyForPlanKey());
|
||||
}
|
||||
}
|
||||
|
||||
static class Disjunction<T> extends JunctionExpression<T> {
|
||||
@@ -44,9 +51,18 @@ abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, Expr
|
||||
Disjunction(com.avaje.ebean.Query<T> query, ExpressionList<T> parent) {
|
||||
super(true, OR, query, parent);
|
||||
}
|
||||
|
||||
Disjunction(DefaultExpressionList<T> expressionList) {
|
||||
super(true, OR, expressionList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpression copyForPlanKey() {
|
||||
return new Disjunction<T>(exprList.copyForPlanKey());
|
||||
}
|
||||
}
|
||||
|
||||
private final DefaultExpressionList<T> exprList;
|
||||
protected final DefaultExpressionList<T> exprList;
|
||||
|
||||
private final String joinType;
|
||||
|
||||
@@ -61,6 +77,15 @@ abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, Expr
|
||||
this.exprList = new DefaultExpressionList<T>(query, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct for copyForPlanKey.
|
||||
*/
|
||||
JunctionExpression(boolean disjunction, String joinType, DefaultExpressionList<T> exprList) {
|
||||
this.disjunction = disjunction;
|
||||
this.joinType = joinType;
|
||||
this.exprList = exprList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
|
||||
|
||||
@@ -163,6 +188,25 @@ abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, Expr
|
||||
return hc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
|
||||
if (!(other instanceof JunctionExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JunctionExpression that = (JunctionExpression) other;
|
||||
return joinType.equals(that.joinType)
|
||||
&& exprList.isSameByPlan(that.exprList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
JunctionExpression that = (JunctionExpression) other;
|
||||
return joinType.equals(that.joinType)
|
||||
&& exprList.isSameByBind(that.exprList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> endJunction() {
|
||||
return exprList.endJunction();
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
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.server.el.ElPropertyValue;
|
||||
|
||||
@@ -22,6 +23,7 @@ class LikeExpression extends AbstractExpression {
|
||||
this.val = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
|
||||
ElPropertyValue prop = getElProp(request);
|
||||
@@ -35,14 +37,13 @@ class LikeExpression extends AbstractExpression {
|
||||
request.addBindValue(bindValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
|
||||
String propertyName = getPropertyName();
|
||||
String pname = propertyName;
|
||||
|
||||
String pname = propName;
|
||||
ElPropertyValue prop = getElProp(request);
|
||||
if (prop != null && prop.isDbEncrypted()) {
|
||||
pname = prop.getBeanProperty().getDecryptProperty(propertyName);
|
||||
pname = prop.getBeanProperty().getDecryptProperty(propName);
|
||||
}
|
||||
if (caseInsensitive) {
|
||||
request.append("lower(").append(pname).append(")");
|
||||
@@ -71,6 +72,24 @@ class LikeExpression extends AbstractExpression {
|
||||
return val.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
if (!(other instanceof LikeExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LikeExpression that = (LikeExpression) other;
|
||||
return this.propName.equals(that.propName)
|
||||
&& this.caseInsensitive == that.caseInsensitive
|
||||
&& this.type == that.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
LikeExpression that = (LikeExpression) other;
|
||||
return val.equals(that.val);
|
||||
}
|
||||
|
||||
private static String getValue(String value, boolean caseInsensitive, LikeType type) {
|
||||
if (caseInsensitive) {
|
||||
value = value.toLowerCase();
|
||||
|
||||
@@ -26,6 +26,12 @@ abstract class LogicExpression implements SpiExpression {
|
||||
And(Expression expOne, Expression expTwo) {
|
||||
super(AND, expOne, expTwo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpression copyForPlanKey() {
|
||||
return new And(expOne.copyForPlanKey(), expTwo.copyForPlanKey());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class Or extends LogicExpression {
|
||||
@@ -35,11 +41,16 @@ abstract class LogicExpression implements SpiExpression {
|
||||
Or(Expression expOne, Expression expTwo) {
|
||||
super(OR, expOne, expTwo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpression copyForPlanKey() {
|
||||
return new Or(expOne.copyForPlanKey(), expTwo.copyForPlanKey());
|
||||
}
|
||||
}
|
||||
|
||||
private final SpiExpression expOne;
|
||||
protected final SpiExpression expOne;
|
||||
|
||||
private final SpiExpression expTwo;
|
||||
protected final SpiExpression expTwo;
|
||||
|
||||
private final String joinType;
|
||||
|
||||
@@ -49,6 +60,7 @@ abstract class LogicExpression implements SpiExpression {
|
||||
this.expTwo = (SpiExpression) expTwo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
|
||||
expOne.containsMany(desc, manyWhereJoin);
|
||||
expTwo.containsMany(desc, manyWhereJoin);
|
||||
@@ -60,11 +72,13 @@ abstract class LogicExpression implements SpiExpression {
|
||||
expTwo.validate(validation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
expOne.addBindValues(request);
|
||||
expTwo.addBindValues(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
|
||||
request.append("(");
|
||||
@@ -83,16 +97,38 @@ abstract class LogicExpression implements SpiExpression {
|
||||
/**
|
||||
* Based on the joinType plus the two expressions.
|
||||
*/
|
||||
@Override
|
||||
public void queryPlanHash(HashQueryPlanBuilder builder) {
|
||||
builder.add(LogicExpression.class).add(joinType);
|
||||
expOne.queryPlanHash(builder);
|
||||
expTwo.queryPlanHash(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int queryBindHash() {
|
||||
int hc = expOne.queryBindHash();
|
||||
hc = hc * 31 + expTwo.queryBindHash();
|
||||
return hc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
|
||||
if (!(other instanceof LogicExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LogicExpression that = (LogicExpression) other;
|
||||
return this.joinType.equals(that.joinType)
|
||||
&& this.expOne.isSameByPlan(that.expOne)
|
||||
&& this.expTwo.isSameByPlan(that.expTwo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
LogicExpression that = (LogicExpression) other;
|
||||
return this.expOne.isSameByBind(that.expOne)
|
||||
&& this.expTwo.isSameByBind(that.expTwo);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,4 +12,9 @@ abstract class NonPrepareExpression implements SpiExpression {
|
||||
public void prepareExpression(BeanQueryRequest<?> request) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpression copyForPlanKey() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,11 @@ class NoopExpression implements SpiExpression {
|
||||
|
||||
protected static final NoopExpression INSTANCE = new NoopExpression();
|
||||
|
||||
@Override
|
||||
public SpiExpression copyForPlanKey() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins whereManyJoins) {
|
||||
// nothing to do
|
||||
@@ -50,4 +55,14 @@ class NoopExpression implements SpiExpression {
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
return other instanceof NoopExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@ final class NotExpression implements SpiExpression {
|
||||
|
||||
private static final long serialVersionUID = 5648926732402355781L;
|
||||
|
||||
private static final String NOT = "not (";
|
||||
private static final String NOT_START = "not (";
|
||||
private static final String NOT_END = ") ";
|
||||
|
||||
private final SpiExpression exp;
|
||||
|
||||
@@ -21,6 +22,12 @@ final class NotExpression implements SpiExpression {
|
||||
this.exp = (SpiExpression) exp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpression copyForPlanKey() {
|
||||
return new NotExpression(exp.copyForPlanKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
|
||||
exp.containsMany(desc, manyWhereJoin);
|
||||
}
|
||||
@@ -30,14 +37,16 @@ final class NotExpression implements SpiExpression {
|
||||
exp.validate(validation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
exp.addBindValues(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
request.append(NOT);
|
||||
request.append(NOT_START);
|
||||
exp.addSql(request);
|
||||
request.append(") ");
|
||||
request.append(NOT_END);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -54,8 +63,23 @@ final class NotExpression implements SpiExpression {
|
||||
exp.queryPlanHash(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int queryBindHash() {
|
||||
return exp.queryBindHash();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
if (!(other instanceof NotExpression)) {
|
||||
return false;
|
||||
}
|
||||
NotExpression that = (NotExpression) other;
|
||||
return exp.isSameByPlan(that.exp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
NotExpression that = (NotExpression) other;
|
||||
return exp.isSameByBind(that.exp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
|
||||
@@ -28,7 +28,7 @@ class NullExpression extends AbstractExpression {
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
|
||||
String propertyName = getPropertyName();
|
||||
String propertyName = propName;
|
||||
|
||||
String nullExpr = notNull ? " is not null " : " is null ";
|
||||
|
||||
@@ -41,6 +41,23 @@ class NullExpression extends AbstractExpression {
|
||||
request.append(propertyName).append(nullExpr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
if (!(other instanceof NullExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NullExpression that = (NullExpression) other;
|
||||
return this.propName.equals(that.propName)
|
||||
&& this.notNull == that.notNull;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
// no bind values so always true
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Based on notNull flag and the propertyName.
|
||||
*/
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.ManyWhereJoins;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionValidation;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
@@ -55,4 +56,31 @@ class RawExpression extends NonPrepareExpression {
|
||||
public int queryBindHash() {
|
||||
return sql.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
if (!(other instanceof RawExpression)) {
|
||||
return false;
|
||||
}
|
||||
RawExpression that = (RawExpression) other;
|
||||
return sql.equals(that.sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
if (!(other instanceof RawExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RawExpression that = (RawExpression) other;
|
||||
if (values.length != that.values.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (!Same.sameByValue(values[i], that.values[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
/**
|
||||
* Utility to help isSame methods.
|
||||
*/
|
||||
public class Same {
|
||||
|
||||
/**
|
||||
* Return true if both values are null or both an not null.
|
||||
*/
|
||||
public static boolean sameByNull(Object v1, Object v2) {
|
||||
return v1 == null ? v2 == null : v2 != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Null safe equals check.
|
||||
*/
|
||||
public static boolean sameByValue(Object v1, Object v2) {
|
||||
return v1 == null ? v2 == null : v1.equals(v2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Null safe check by sameByValue or sameByNull based on byValue.
|
||||
*/
|
||||
public static boolean sameBy(boolean byValue, Object value, Object value1) {
|
||||
|
||||
if (byValue) {
|
||||
return sameByValue(value, value1);
|
||||
} else {
|
||||
return sameByNull(value, value1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
|
||||
@@ -20,17 +20,25 @@ public class SimpleExpression extends AbstractExpression {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public final String getPropName() {
|
||||
return propName;
|
||||
}
|
||||
|
||||
public boolean isOpEquals() {
|
||||
return Op.EQ.equals(type);
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
|
||||
ElPropertyValue prop = getElProp(request);
|
||||
if (prop != null) {
|
||||
if (prop.isAssocId()) {
|
||||
Object[] ids = prop.getAssocOneIdValues((EntityBean)value);
|
||||
Object[] ids = prop.getAssocOneIdValues((EntityBean) value);
|
||||
if (ids != null) {
|
||||
for (int i = 0; i < ids.length; i++) {
|
||||
request.addBindValue(ids[i]);
|
||||
@@ -54,12 +62,10 @@ public class SimpleExpression extends AbstractExpression {
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
|
||||
String propertyName = getPropertyName();
|
||||
|
||||
ElPropertyValue prop = getElProp(request);
|
||||
if (prop != null) {
|
||||
if (prop.isAssocId()) {
|
||||
request.append(prop.getAssocOneIdExpr(propertyName, type.bind()));
|
||||
request.append(prop.getAssocOneIdExpr(propName, type.bind()));
|
||||
return;
|
||||
}
|
||||
if (prop.isDbEncrypted()) {
|
||||
@@ -68,7 +74,7 @@ public class SimpleExpression extends AbstractExpression {
|
||||
return;
|
||||
}
|
||||
}
|
||||
request.append(propertyName).append(type.bind());
|
||||
request.append(propName).append(type.bind());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,8 +91,20 @@ public class SimpleExpression extends AbstractExpression {
|
||||
return value.hashCode();
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
if (!(other instanceof SimpleExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SimpleExpression that = (SimpleExpression) other;
|
||||
return this.propName.equals(that.propName)
|
||||
&& this.type == that.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
SimpleExpression that = (SimpleExpression) other;
|
||||
return value.equals(that.value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
package com.avaje.ebeaninternal.server.query;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.avaje.ebean.bean.ObjectGraphNode;
|
||||
import com.avaje.ebean.config.dbplatform.SqlLimitResponse;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlan;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.CQueryPlanKey;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
@@ -18,6 +13,10 @@ import com.avaje.ebeaninternal.server.type.RsetDataReader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Represents a query for a given SQL statement.
|
||||
* <p>
|
||||
@@ -45,7 +44,7 @@ public class CQueryPlan {
|
||||
|
||||
private final boolean autoTuned;
|
||||
|
||||
private final HashQueryPlan hash;
|
||||
private final CQueryPlanKey planKey;
|
||||
|
||||
private final boolean rawSql;
|
||||
|
||||
@@ -79,7 +78,7 @@ public class CQueryPlan {
|
||||
this.server = request.getServer();
|
||||
this.beanType = request.getBeanDescriptor().getBeanType();
|
||||
this.stats = new CQueryPlanStats(this, server.isCollectQueryOrigins());
|
||||
this.hash = request.getQueryPlanHash();
|
||||
this.planKey = request.getQueryPlanKey();
|
||||
this.autoTuned = request.getQuery().isAutoTuned();
|
||||
if (sqlRes != null) {
|
||||
this.sql = sqlRes.getSql();
|
||||
@@ -103,7 +102,7 @@ public class CQueryPlan {
|
||||
this.server = request.getServer();
|
||||
this.beanType = request.getBeanDescriptor().getBeanType();
|
||||
this.stats = new CQueryPlanStats(this, server.isCollectQueryOrigins());
|
||||
this.hash = buildHash(sql, rawSql, rowNumberIncluded, logWhereSql);
|
||||
this.planKey = buildPlanKey(sql, rawSql, rowNumberIncluded, logWhereSql);
|
||||
this.autoTuned = false;
|
||||
this.sql = sql;
|
||||
this.sqlTree = sqlTree;
|
||||
@@ -114,15 +113,13 @@ public class CQueryPlan {
|
||||
}
|
||||
|
||||
|
||||
private HashQueryPlan buildHash(String sql, boolean rawSql, boolean rowNumberIncluded, String logWhereSql) {
|
||||
HashQueryPlanBuilder builder = new HashQueryPlanBuilder();
|
||||
builder.add(sql).add(rawSql).add(rowNumberIncluded).add(logWhereSql);
|
||||
builder.addRawSql(sql);
|
||||
return builder.build();
|
||||
private CQueryPlanKey buildPlanKey(String sql, boolean rawSql, boolean rowNumberIncluded, String logWhereSql) {
|
||||
|
||||
return new RawSqlQueryPlanKey(sql, rawSql, rowNumberIncluded, logWhereSql);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return beanType + " hash:" + hash;
|
||||
return beanType + " hash:" + planKey;
|
||||
}
|
||||
|
||||
public Class<?> getBeanType() {
|
||||
@@ -147,8 +144,8 @@ public class CQueryPlan {
|
||||
return autoTuned;
|
||||
}
|
||||
|
||||
public HashQueryPlan getHash() {
|
||||
return hash;
|
||||
public CQueryPlanKey getPlanKey() {
|
||||
return planKey;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,7 +161,7 @@ public class CQueryPlan {
|
||||
|
||||
private String calcAuditQueryKey() {
|
||||
// rawSql needs to include the MD5 hash of the sql
|
||||
return rawSql ? hash.getPartialKey() + "_" + getSqlMd5Hash() : hash.getPartialKey();
|
||||
return rawSql ? planKey.getPartialKey() + "_" + getSqlMd5Hash() : planKey.getPartialKey();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -233,7 +233,7 @@ public final class CQueryPlanStats {
|
||||
|
||||
@Override
|
||||
public String getQueryPlanHash() {
|
||||
return queryPlan.getHash().toString();
|
||||
return queryPlan.getPlanKey().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -13,7 +13,7 @@ import com.avaje.ebeaninternal.server.persist.Binder;
|
||||
import com.avaje.ebeaninternal.server.querydefn.OrmQueryProperties;
|
||||
import com.avaje.ebeaninternal.server.type.DataBind;
|
||||
import com.avaje.ebeaninternal.server.util.BindParamsParser;
|
||||
import com.avaje.ebeaninternal.util.DefaultExpressionRequest;
|
||||
import com.avaje.ebeaninternal.server.expression.DefaultExpressionRequest;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.avaje.ebeaninternal.server.query;
|
||||
|
||||
import com.avaje.ebeaninternal.api.CQueryPlanKey;
|
||||
|
||||
/**
|
||||
* QueryPlanKey for RawSql queries.
|
||||
*/
|
||||
public class RawSqlQueryPlanKey implements CQueryPlanKey {
|
||||
|
||||
private final String sql;
|
||||
private final boolean rawSql;
|
||||
private final boolean rowNumberIncluded;
|
||||
private final String logWhereSql;
|
||||
|
||||
public RawSqlQueryPlanKey(String sql, boolean rawSql, boolean rowNumberIncluded, String logWhereSql) {
|
||||
this.sql = sql;
|
||||
this.rawSql = rawSql;
|
||||
this.rowNumberIncluded = rowNumberIncluded;
|
||||
this.logWhereSql = logWhereSql;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getPartialKey() + ":r";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return as a partial key. For rawSql hash the sql is part of the key and as such
|
||||
* needs to be included in order to have a complete key. Typically the MD5 of the sql
|
||||
* can be used as a short form proxy for the actual sql.
|
||||
*/
|
||||
public String getPartialKey() {
|
||||
return hashCode() + "_0";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
RawSqlQueryPlanKey that = (RawSqlQueryPlanKey) o;
|
||||
|
||||
if (rawSql != that.rawSql) return false;
|
||||
if (rowNumberIncluded != that.rowNumberIncluded) return false;
|
||||
if (!sql.equals(that.sql)) return false;
|
||||
return logWhereSql != null ? logWhereSql.equals(that.logWhereSql) : that.logWhereSql == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = sql.hashCode();
|
||||
result = 31 * result + (rawSql ? 1 : 0);
|
||||
result = 31 * result + (rowNumberIncluded ? 1 : 0);
|
||||
result = 31 * result + logWhereSql.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -13,9 +13,8 @@ import com.avaje.ebean.plugin.SpiBeanType;
|
||||
import com.avaje.ebean.text.PathProperties;
|
||||
import com.avaje.ebeaninternal.api.BindParams;
|
||||
import com.avaje.ebeaninternal.api.HashQuery;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlan;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.ManyWhereJoins;
|
||||
import com.avaje.ebeaninternal.api.CQueryPlanKey;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionList;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionValidation;
|
||||
@@ -28,7 +27,7 @@ import com.avaje.ebeaninternal.server.deploy.DeployNamedQuery;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoin;
|
||||
import com.avaje.ebeaninternal.server.expression.SimpleExpression;
|
||||
import com.avaje.ebeaninternal.server.query.CancelableQuery;
|
||||
import com.avaje.ebeaninternal.util.DefaultExpressionList;
|
||||
import com.avaje.ebeaninternal.server.expression.DefaultExpressionList;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.sql.Timestamp;
|
||||
@@ -234,7 +233,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
/**
|
||||
* Hash of final query after AutoTune tuning.
|
||||
*/
|
||||
private HashQueryPlan queryPlanHash;
|
||||
private CQueryPlanKey queryPlanKey;
|
||||
|
||||
private transient PersistenceContext persistenceContext;
|
||||
|
||||
@@ -493,7 +492,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
if (se instanceof SimpleExpression) {
|
||||
SimpleExpression e = (SimpleExpression) se;
|
||||
if (e.isOpEquals()) {
|
||||
return new NaturalKeyBindParam(e.getPropertyName(), e.getValue());
|
||||
return new NaturalKeyBindParam(e.getPropName(), e.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -759,55 +758,34 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
/**
|
||||
* Calculate the query hash for either AutoTune query tuning or Query Plan caching.
|
||||
*/
|
||||
HashQueryPlan calculateQueryPlanHash() {
|
||||
|
||||
// exclude bind values and things unrelated to the sql being generated
|
||||
HashQueryPlanBuilder builder = new HashQueryPlanBuilder();
|
||||
|
||||
builder.add((type == null ? 0 : type.ordinal() + 1));
|
||||
builder.add(autoTuned).add(distinct).add(sqlDistinct).add(query);
|
||||
builder.add(firstRow).add(maxRows).add(orderBy).add(forUpdate);
|
||||
builder.add(rawWhereClause).add(additionalWhere).add(additionalHaving);
|
||||
builder.add(mapKey);
|
||||
builder.add(disableLazyLoading);
|
||||
builder.add(id != null);
|
||||
builder.add(temporalMode);
|
||||
builder.add(rawSql == null ? 0 : rawSql.queryHash());
|
||||
builder.add(includeTableJoin != null ? includeTableJoin.queryHash() : 0);
|
||||
builder.add(rootTableAlias);
|
||||
|
||||
if (detail != null) {
|
||||
detail.queryPlanHash(builder);
|
||||
}
|
||||
if (bindParams != null) {
|
||||
bindParams.buildQueryPlanHash(builder);
|
||||
}
|
||||
CQueryPlanKey createQueryPlanKey() {
|
||||
|
||||
DefaultExpressionList<T> where = null;
|
||||
DefaultExpressionList<T> having = null;
|
||||
if (whereExpressions != null) {
|
||||
whereExpressions.queryPlanHash(builder);
|
||||
where = whereExpressions.copyForPlanKey();
|
||||
}
|
||||
if (havingExpressions != null) {
|
||||
havingExpressions.queryPlanHash(builder);
|
||||
having = havingExpressions.copyForPlanKey();
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
queryPlanKey = new OrmQueryPlanKey(includeTableJoin, type, detail, maxRows, firstRow,
|
||||
disableLazyLoading, rawWhereClause, orderBy, query, additionalWhere, additionalHaving,
|
||||
distinct, sqlDistinct, mapKey, id, bindParams, where, having,
|
||||
temporalMode, forUpdate, rootTableAlias, rawSql);
|
||||
|
||||
return queryPlanKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate a hash that should be unique for the generated SQL across a given bean type.
|
||||
* <p>
|
||||
* This can used to enable the caching and reuse of a 'query plan'.
|
||||
* </p>
|
||||
* <p>
|
||||
* This is calculated AFTER AutoTune query tuning has occurred.
|
||||
* </p>
|
||||
* Prepare the query which prepares any expressions (sub-query expressions etc) and calculates the query plan key.
|
||||
*/
|
||||
public HashQueryPlan queryPlanHash(BeanQueryRequest<?> request) {
|
||||
public CQueryPlanKey prepare(BeanQueryRequest<?> request) {
|
||||
|
||||
prepareExpressions(request);
|
||||
|
||||
queryPlanHash = calculateQueryPlanHash();
|
||||
return queryPlanHash;
|
||||
queryPlanKey = createQueryPlanKey();
|
||||
return queryPlanKey;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -852,7 +830,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
// so queryPlanHash is calculated well before this method is called
|
||||
int hc = queryBindHash();
|
||||
|
||||
return new HashQuery(queryPlanHash, hc);
|
||||
return new HashQuery(queryPlanKey, hc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
package com.avaje.ebeaninternal.server.querydefn;
|
||||
|
||||
import com.avaje.ebean.OrderBy;
|
||||
import com.avaje.ebean.RawSql;
|
||||
import com.avaje.ebeaninternal.api.BindParams;
|
||||
import com.avaje.ebeaninternal.api.CQueryPlanKey;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoin;
|
||||
|
||||
/**
|
||||
* Query plan key for ORM queries.
|
||||
*/
|
||||
public class OrmQueryPlanKey implements CQueryPlanKey {
|
||||
|
||||
private final TableJoin includeTableJoin;
|
||||
private final String orderByAsSting;
|
||||
private final OrmQueryDetail detail;
|
||||
private final BindParams bindParams;
|
||||
private final SpiExpression whereExpressions;
|
||||
private final SpiExpression havingExpressions;
|
||||
private final RawSql rawSql;
|
||||
private final boolean hasIdValue;
|
||||
|
||||
private final SpiQuery.Type type;
|
||||
private final int maxRows;
|
||||
private final int firstRow;
|
||||
private final boolean disableLazyLoading;
|
||||
private final String rawWhereClause;
|
||||
private final String query;
|
||||
private final String additionalWhere;
|
||||
private final String additionalHaving;
|
||||
private final boolean distinct;
|
||||
private final boolean sqlDistinct;
|
||||
private final String mapKey;
|
||||
private final SpiQuery.TemporalMode temporalMode;
|
||||
private final boolean forUpdate;
|
||||
private final String rootTableAlias;
|
||||
|
||||
private final int planHash;
|
||||
private final int bindCount;
|
||||
|
||||
public OrmQueryPlanKey(TableJoin includeTableJoin, SpiQuery.Type type, OrmQueryDetail detail, int maxRows, int firstRow, boolean disableLazyLoading, String rawWhereClause, OrderBy<?> orderBy, String query, String additionalWhere, String additionalHaving, boolean distinct, boolean sqlDistinct, String mapKey, Object id, BindParams bindParams, SpiExpression whereExpressions, SpiExpression havingExpressions, SpiQuery.TemporalMode temporalMode, boolean forUpdate, String rootTableAlias, RawSql rawSql) {
|
||||
|
||||
this.includeTableJoin = includeTableJoin;
|
||||
this.type = type;
|
||||
this.detail = detail;
|
||||
this.maxRows = maxRows;
|
||||
this.firstRow = firstRow;
|
||||
this.disableLazyLoading = disableLazyLoading;
|
||||
this.rawWhereClause = rawWhereClause;
|
||||
this.orderByAsSting = (orderBy == null) ? null : orderBy.toStringFormat();
|
||||
this.query = query;
|
||||
this.additionalWhere = additionalWhere;
|
||||
this.additionalHaving = additionalHaving;
|
||||
this.distinct = distinct;
|
||||
this.sqlDistinct = sqlDistinct;
|
||||
this.mapKey = mapKey;
|
||||
this.hasIdValue = (id != null);
|
||||
this.bindParams = bindParams;
|
||||
this.whereExpressions = whereExpressions;
|
||||
this.havingExpressions = havingExpressions;
|
||||
this.temporalMode = temporalMode;
|
||||
this.forUpdate = forUpdate;
|
||||
this.rootTableAlias = rootTableAlias;
|
||||
this.rawSql = rawSql;
|
||||
|
||||
// exclude bind values and things unrelated to the sql being generated
|
||||
HashQueryPlanBuilder builder = new HashQueryPlanBuilder();
|
||||
|
||||
builder.add((type == null ? 0 : type.ordinal() + 1));
|
||||
builder.add(distinct).add(sqlDistinct).add(query);
|
||||
builder.add(firstRow).add(maxRows);
|
||||
builder.add(orderBy).add(forUpdate);
|
||||
builder.add(rawWhereClause).add(additionalWhere).add(additionalHaving);
|
||||
builder.add(mapKey);
|
||||
builder.add(disableLazyLoading);
|
||||
builder.add(hasIdValue);
|
||||
builder.add(temporalMode);
|
||||
builder.add(rawSql == null ? 0 : rawSql.queryHash());
|
||||
builder.add(includeTableJoin != null ? includeTableJoin.queryHash() : 0);
|
||||
builder.add(rootTableAlias);
|
||||
|
||||
if (detail != null) {
|
||||
detail.queryPlanHash(builder);
|
||||
}
|
||||
if (bindParams != null) {
|
||||
bindParams.buildQueryPlanHash(builder);
|
||||
}
|
||||
if (whereExpressions != null) {
|
||||
whereExpressions.queryPlanHash(builder);
|
||||
}
|
||||
if (havingExpressions != null) {
|
||||
havingExpressions.queryPlanHash(builder);
|
||||
}
|
||||
|
||||
this.planHash = builder.getPlanHash();
|
||||
this.bindCount = builder.getBindCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPartialKey() {
|
||||
return planHash + "_" + bindCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return planHash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
OrmQueryPlanKey that = (OrmQueryPlanKey) o;
|
||||
|
||||
if (planHash != that.planHash) return false;
|
||||
if (bindCount != that.bindCount) return false;
|
||||
|
||||
if (maxRows != that.maxRows) return false;
|
||||
if (firstRow != that.firstRow) return false;
|
||||
if (disableLazyLoading != that.disableLazyLoading) return false;
|
||||
|
||||
if (distinct != that.distinct) return false;
|
||||
if (sqlDistinct != that.sqlDistinct) return false;
|
||||
if (forUpdate != that.forUpdate) return false;
|
||||
if (hasIdValue != that.hasIdValue) return false;
|
||||
if (type != that.type) return false;
|
||||
if (temporalMode != that.temporalMode) return false;
|
||||
if (includeTableJoin != null ? !includeTableJoin.equals(that.includeTableJoin) : that.includeTableJoin != null) return false;
|
||||
if (orderByAsSting != null ? !orderByAsSting.equals(that.orderByAsSting) : that.orderByAsSting != null) return false;
|
||||
|
||||
if (whereExpressions != null ? !whereExpressions.isSameByPlan(that.whereExpressions) : that.whereExpressions != null) return false;
|
||||
if (havingExpressions != null ? !havingExpressions.isSameByPlan(that.havingExpressions) : that.havingExpressions != null) return false;
|
||||
|
||||
// if (detail != null ? !detail.equals(that.detail) : that.detail != null) return false;
|
||||
// if (bindParams != null ? !bindParams.equals(that.bindParams) : that.bindParams != null) return false;
|
||||
// if (rawSql != null ? !rawSql.equals(that.rawSql) : that.rawSql != null) return false;
|
||||
|
||||
if (rawWhereClause != null ? !rawWhereClause.equals(that.rawWhereClause) : that.rawWhereClause != null) return false;
|
||||
if (query != null ? !query.equals(that.query) : that.query != null) return false;
|
||||
if (additionalWhere != null ? !additionalWhere.equals(that.additionalWhere) : that.additionalWhere != null) return false;
|
||||
if (additionalHaving != null ? !additionalHaving.equals(that.additionalHaving) : that.additionalHaving != null) return false;
|
||||
if (mapKey != null ? !mapKey.equals(that.mapKey) : that.mapKey != null) return false;
|
||||
return rootTableAlias != null ? rootTableAlias.equals(that.rootTableAlias) : that.rootTableAlias == null;
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.server.expression.FilterExprPath;
|
||||
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
|
||||
import com.avaje.ebeaninternal.server.query.SplitName;
|
||||
import com.avaje.ebeaninternal.util.FilterExpressionList;
|
||||
import com.avaje.ebeaninternal.server.expression.FilterExpressionList;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import org.avaje.agentloader.AgentLoader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -29,4 +30,16 @@ public class BaseTestCase {
|
||||
SpiEbeanServer spi = (SpiEbeanServer)Ebean.getDefaultServer();
|
||||
return spi.getDatabasePlatform().getName().equals("h2");
|
||||
}
|
||||
|
||||
protected <T> BeanDescriptor<T> getBeanDescriptor(Class<T> cls) {
|
||||
return spiEbeanServer().getBeanDescriptor(cls);
|
||||
}
|
||||
|
||||
protected SpiEbeanServer spiEbeanServer() {
|
||||
return (SpiEbeanServer) Ebean.getDefaultServer();
|
||||
}
|
||||
|
||||
protected EbeanServer server() {
|
||||
return Ebean.getDefaultServer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoinColumn;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TableJoinColumnTest {
|
||||
|
||||
TableJoinColumn col(String localDbColumn, String foreignDbColumn, boolean insertable, boolean updateable) {
|
||||
DeployTableJoinColumn column = new DeployTableJoinColumn(localDbColumn, foreignDbColumn, insertable, updateable);
|
||||
return new TableJoinColumn(column);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_same() {
|
||||
assertSame(col("a", "b", true, true), col("a", "b", true, true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffFirstCol() {
|
||||
assertDifferent(col("a", "b", true, true), col("c", "b", true, true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffSecondCol() {
|
||||
assertDifferent(col("a", "b", true, true), col("a", "c", true, true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffInsertable() {
|
||||
assertDifferent(col("a", "b", true, true), col("a", "b", false, true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffUpdateable() {
|
||||
assertDifferent(col("a", "b", true, true), col("a", "b", true, false));
|
||||
}
|
||||
|
||||
private void assertDifferent(TableJoinColumn col, TableJoinColumn col2) {
|
||||
assertThat(col).isNotEqualTo(col2);
|
||||
assertThat(col.hashCode()).isNotEqualTo(col2.hashCode());
|
||||
}
|
||||
|
||||
private void assertSame(TableJoinColumn col, TableJoinColumn col2) {
|
||||
assertThat(col).isEqualTo(col2);
|
||||
assertThat(col.hashCode()).isEqualTo(col2.hashCode());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoinColumn;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TableJoinTest {
|
||||
|
||||
DeployTableJoinColumn col(String localDbColumn, String foreignDbColumn, boolean insertable, boolean updateable) {
|
||||
return new DeployTableJoinColumn(localDbColumn, foreignDbColumn, insertable, updateable);
|
||||
}
|
||||
|
||||
TableJoin table(String tableName, String col1, String col2) {
|
||||
DeployTableJoin deploy = new DeployTableJoin();
|
||||
deploy.setTable(tableName);
|
||||
deploy.addJoinColumn(col(col1, col2, true, true));
|
||||
return new TableJoin(deploy);
|
||||
}
|
||||
|
||||
TableJoin table(String tableName, String col1, String col2, String col3, String col4) {
|
||||
DeployTableJoin deploy = new DeployTableJoin();
|
||||
deploy.setTable(tableName);
|
||||
deploy.addJoinColumn(col(col1, col2, true, true));
|
||||
deploy.addJoinColumn(col(col3, col4, true, true));
|
||||
return new TableJoin(deploy);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_same() {
|
||||
assertSame(table("myTable", "a", "b"), table("myTable", "a", "b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffTable() {
|
||||
assertDifferent(table("myTable", "a", "b"), table("diffTable", "a", "b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffColumn() {
|
||||
assertDifferent(table("myTable", "a", "b"), table("myTable", "c", "b"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_moreColumns() {
|
||||
assertDifferent(table("myTable", "a", "b"), table("myTable", "a", "b", "c", "d"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_lessColumns() {
|
||||
assertDifferent(table("myTable", "a", "b", "c", "d"), table("myTable", "a", "b"));
|
||||
}
|
||||
|
||||
void assertSame(TableJoin join1, TableJoin join2) {
|
||||
assertThat(join1).isEqualTo(join1);
|
||||
assertThat(join1.hashCode()).isEqualTo(join1.hashCode());
|
||||
}
|
||||
|
||||
|
||||
void assertDifferent(TableJoin join1, TableJoin join2) {
|
||||
assertThat(join1).isNotEqualTo(join2);
|
||||
assertThat(join1.hashCode()).isNotEqualTo(join2.hashCode());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
|
||||
public class AllEqualsExpressionTest {
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_same() {
|
||||
|
||||
assertThat(exp("a", 10).isSameByPlan(exp("a", 10))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_sameMultiple() {
|
||||
|
||||
assertThat(exp("a", 10, "b", "23").isSameByBind(exp("a", 10, "b", "23"))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffBindValue() {
|
||||
|
||||
assertThat(exp("a", 10).isSameByPlan(exp("a", 20))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_multiple() {
|
||||
|
||||
assertThat(exp("a", 10, "b", 20, "c", 30).isSameByPlan(exp("a", 10, "b", 20, "c", 30))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_less() {
|
||||
|
||||
assertThat(exp("a", 10, "b", 20, "c", 30).isSameByPlan(exp("a", 10, "b", 20))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_more() {
|
||||
|
||||
assertThat(exp("a", 10, "b", 20).isSameByPlan(exp("a", 10, "b", 20, "c", 30))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffProperty_diff() {
|
||||
|
||||
assertThat(exp("a", 10).isSameByPlan(exp("b", 10))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffType_diff() {
|
||||
|
||||
assertThat(exp("a", 10).isSameByPlan(new NoopExpression())).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffBindByNull_last() {
|
||||
|
||||
assertThat(exp("a", 10).isSameByPlan(exp("a", null))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffBindByNull_first() {
|
||||
|
||||
assertThat(exp("a", null).isSameByPlan(exp("a", 10))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_differentExpressionType() {
|
||||
|
||||
assertThat(exp("a", null).isSameByPlan(new NoopExpression())).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffBindByNull_last() {
|
||||
|
||||
assertThat(exp("a", 10).isSameByBind(exp("a", null))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffBindByNull_first() {
|
||||
|
||||
assertThat(exp("a", null).isSameByBind(exp("a", 10))).isFalse();
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
private AllEqualsExpression exp(Map<String, Object> propMap) {
|
||||
return new AllEqualsExpression(propMap);
|
||||
}
|
||||
|
||||
AllEqualsExpression exp(String key0, Object val1) {
|
||||
LinkedHashMap<String,Object> map = new LinkedHashMap<String,Object>();
|
||||
map.put(key0, val1);
|
||||
return exp(map);
|
||||
}
|
||||
|
||||
|
||||
AllEqualsExpression exp(String key0, Object val1, String key2, Object val2) {
|
||||
LinkedHashMap<String,Object> map = new LinkedHashMap<String,Object>();
|
||||
map.put(key0, val1);
|
||||
map.put(key2, val2);
|
||||
return exp(map);
|
||||
}
|
||||
|
||||
AllEqualsExpression exp(String key0, Object val1, String key2, Object val2, String key3, Object val3) {
|
||||
LinkedHashMap<String,Object> map = new LinkedHashMap<String,Object>();
|
||||
map.put(key0, val1);
|
||||
map.put(key2, val2);
|
||||
map.put(key3, val3);
|
||||
return exp(map);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.tests.model.basic.Order;
|
||||
|
||||
public abstract class BaseExpressionTest extends BaseTestCase {
|
||||
|
||||
protected DefaultExpressionRequest newExpressionRequest() {
|
||||
BeanDescriptor<Order> desc = getBeanDescriptor(Order.class);
|
||||
return new DefaultExpressionRequest(desc);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
|
||||
public class BetweenExpressionTest extends BaseExpressionTest {
|
||||
|
||||
@Test
|
||||
public void addSql() throws Exception {
|
||||
|
||||
DefaultExpressionRequest expReq = newExpressionRequest();
|
||||
|
||||
BetweenExpression exp = new BetweenExpression("startDate", 1, 2);
|
||||
exp.addSql(expReq);
|
||||
|
||||
assertThat(expReq.getSql()).isEqualTo("startDate between ? and ? ");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyForPlanKey_isSameInstance() throws Exception {
|
||||
|
||||
BetweenExpression exp = new BetweenExpression("startDate", 1, 2);
|
||||
SpiExpression other = exp.copyForPlanKey();
|
||||
|
||||
assertThat(exp).isSameAs(other);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_properties_match() throws Exception {
|
||||
|
||||
BetweenExpression exp0 = new BetweenExpression("startDate", 1, 2);
|
||||
BetweenExpression exp1 = new BetweenExpression("startDate", 3, 4);
|
||||
|
||||
assertThat(exp0.isSameByPlan(exp1)).isTrue();
|
||||
assertThat(exp1.isSameByPlan(exp0)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_properties_do_not_match() throws Exception {
|
||||
|
||||
BetweenExpression exp0 = new BetweenExpression("startDate", 1, 2);
|
||||
BetweenExpression exp1 = new BetweenExpression("endDate", 1, 2);
|
||||
|
||||
assertThat(exp0.isSameByPlan(exp1)).isFalse();
|
||||
assertThat(exp1.isSameByPlan(exp0)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_values_do_not_match() throws Exception {
|
||||
|
||||
BetweenExpression exp0 = new BetweenExpression("startDate", 1, 2);
|
||||
BetweenExpression exp1 = new BetweenExpression("startDate", 1, 3);
|
||||
|
||||
assertThat(exp0.isSameByBind(exp1)).isFalse();
|
||||
assertThat(exp1.isSameByBind(exp0)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_values_match() throws Exception {
|
||||
|
||||
BetweenExpression exp0 = new BetweenExpression("startDate", 1, 2);
|
||||
BetweenExpression exp1 = new BetweenExpression("startDate", 1, 2);
|
||||
|
||||
assertThat(exp0.isSameByBind(exp1)).isTrue();
|
||||
assertThat(exp1.isSameByBind(exp0)).isTrue();
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
|
||||
public class BetweenPropertyExpressionTest {
|
||||
|
||||
@NotNull
|
||||
private BetweenPropertyExpression exp(String lowProperty, String highProperty, Object value) {
|
||||
return new BetweenPropertyExpression(lowProperty, highProperty, value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_same() {
|
||||
assertThat(exp("a", "b", 10).isSameByPlan(exp("a", "b", 10))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffValue() {
|
||||
assertThat(exp("a", "b", 10).isSameByPlan(exp("a", "b", 20))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffProperty() {
|
||||
assertThat(exp("a", "b", 10).isSameByPlan(exp("a", "c", 10))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffExpressionType() {
|
||||
assertThat(exp("a", "b", 10).isSameByPlan(new NoopExpression())).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_same() {
|
||||
assertThat(exp("a", "b", 10).isSameByBind(exp("a", "b", 10))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diff() {
|
||||
assertThat(exp("a", "b", 10).isSameByBind(exp("a", "b", 20))).isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
|
||||
public class CaseInsensitiveEqualExpressionTest {
|
||||
|
||||
CaseInsensitiveEqualExpression exp(String propName, String value) {
|
||||
return new CaseInsensitiveEqualExpression(propName, value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_same() {
|
||||
|
||||
assertThat(exp("a", "10").isSameByPlan(exp("a", "10"))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffBind_same() {
|
||||
|
||||
assertThat(exp("a", "10").isSameByPlan(exp("a", "20"))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffProperty_diff() {
|
||||
|
||||
assertThat(exp("a", "10").isSameByPlan(exp("b", "10"))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffType_diff() {
|
||||
|
||||
assertThat(exp("a", "10").isSameByPlan(new NoopExpression())).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_sameBindValues() {
|
||||
|
||||
assertThat(exp("a", "10").isSameByBind(exp("b", "10"))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffBindValues() {
|
||||
|
||||
assertThat(exp("a", "10").isSameByBind(exp("b", "20"))).isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
+63
-15
@@ -1,13 +1,11 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.LikeType;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
@@ -22,42 +20,68 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class DefaultExampleExpressionTest extends BaseTestCase {
|
||||
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
SpiEbeanServer server = (SpiEbeanServer)Ebean.getDefaultServer();
|
||||
BeanDescriptor<Customer> desc = server.getBeanDescriptor(Customer.class);
|
||||
|
||||
SpiQuery<Customer> query = (SpiQuery<Customer>)server.find(Customer.class);
|
||||
|
||||
Customer customer() {
|
||||
Address address = new Address();
|
||||
address.setCity("billingAddress.city");
|
||||
|
||||
Customer customer = new Customer();
|
||||
customer.setName("name");
|
||||
customer.setBillingAddress(address);
|
||||
return customer;
|
||||
}
|
||||
|
||||
DefaultExampleExpression exp() {
|
||||
Customer customer = customer();
|
||||
return new DefaultExampleExpression((EntityBean)customer, false, LikeType.EQUAL_TO);
|
||||
}
|
||||
|
||||
DefaultExampleExpression expr = new DefaultExampleExpression((EntityBean)customer, false, LikeType.EQUAL_TO);
|
||||
DefaultExampleExpression expExtra() {
|
||||
Customer customer = customer();
|
||||
customer.setSmallnote("smallNote");
|
||||
return new DefaultExampleExpression((EntityBean)customer, false, LikeType.EQUAL_TO);
|
||||
}
|
||||
|
||||
DefaultExampleExpression expDiffName() {
|
||||
Customer customer = customer();
|
||||
customer.setName("otherName");
|
||||
return new DefaultExampleExpression((EntityBean)customer, false, LikeType.EQUAL_TO);
|
||||
}
|
||||
|
||||
BeanQueryRequest<?> request = create(query, desc);
|
||||
BeanDescriptor<Customer> customerBeanDescriptor() {
|
||||
return getBeanDescriptor(Customer.class);
|
||||
}
|
||||
|
||||
DefaultExampleExpression prepare(DefaultExampleExpression expr) {
|
||||
|
||||
SpiQuery<Customer> query = (SpiQuery<Customer>)spiEbeanServer().find(Customer.class);
|
||||
BeanQueryRequest<?> request = create(query, customerBeanDescriptor());
|
||||
expr.prepareExpression(request);
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
DefaultExampleExpression expr = exp();
|
||||
|
||||
prepare(expr);
|
||||
|
||||
HashQueryPlanBuilder builder = new HashQueryPlanBuilder();
|
||||
expr.queryPlanHash(builder);
|
||||
|
||||
TDSpiExpressionRequest req = new TDSpiExpressionRequest(desc);
|
||||
TDSpiExpressionRequest req = new TDSpiExpressionRequest(customerBeanDescriptor());
|
||||
expr.addBindValues(req);
|
||||
|
||||
assertThat(req.bindValues).contains("name", "billingAddress.city");
|
||||
|
||||
address.setCity("Auckland");
|
||||
Customer customer = customer();
|
||||
customer.setName("Rob");
|
||||
customer.getBillingAddress().setCity("Auckland");
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
Query<Customer> query1 = server.find(Customer.class)
|
||||
Query<Customer> query1 = server().find(Customer.class)
|
||||
.where().exampleLike(customer)
|
||||
.query();
|
||||
|
||||
@@ -72,4 +96,28 @@ public class DefaultExampleExpressionTest extends BaseTestCase {
|
||||
return new OrmQueryRequest<T>(null, null, query, desc, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_whenSame() {
|
||||
|
||||
assertThat(prepare(exp()).isSameByPlan(prepare(exp()))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffBindValue_stillSame() {
|
||||
|
||||
assertThat(prepare(exp()).isSameByPlan(prepare(expDiffName()))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_extraExpression_then_different() {
|
||||
|
||||
assertThat(prepare(exp()).isSameByPlan(prepare(expExtra()))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_lessExpression_then_different() {
|
||||
|
||||
assertThat(prepare(expExtra()).isSameByPlan(prepare(exp()))).isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebean.ExpressionList;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
|
||||
public class DefaultExpressionListTest {
|
||||
|
||||
|
||||
DefaultExpressionList exp() {
|
||||
|
||||
return new DefaultExpressionList<Object>(null, new DefaultExpressionFactory(true), null);
|
||||
}
|
||||
|
||||
DefaultExpressionList spi(ExpressionList list) {
|
||||
return (DefaultExpressionList)list;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_same() {
|
||||
|
||||
assertThat(spi(exp().eq("a", 10).eq("b", 20))
|
||||
.isSameByPlan(spi(exp().eq("a", 10).eq("b", 20)))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffExpressionType() {
|
||||
|
||||
assertThat(spi(exp().eq("a", 10).eq("b", 20))
|
||||
.isSameByPlan(new NoopExpression())).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_less() {
|
||||
|
||||
assertThat(spi(exp().eq("a", 10).eq("b", 20))
|
||||
.isSameByPlan(spi(exp().eq("a", 10)))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_lessEmptyLast() {
|
||||
|
||||
assertThat(spi(exp().eq("a", 10).eq("b", 20))
|
||||
.isSameByPlan(spi(exp()))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_lessEmptyFirst() {
|
||||
|
||||
assertThat(spi(exp())
|
||||
.isSameByPlan(spi(exp().eq("a", 10)))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_more() {
|
||||
|
||||
assertThat(spi(exp().eq("a", 10).eq("b", 20))
|
||||
.isSameByPlan(spi(exp().eq("a", 10).eq("b", 20).eq("c", 30)))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffProperties() {
|
||||
|
||||
assertThat(spi(exp().eq("a", 10).eq("b", 20))
|
||||
.isSameByPlan(spi(exp().eq("c", 10).eq("b", 20)))).isFalse();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_same() {
|
||||
|
||||
assertThat(spi(exp().eq("a", 10).eq("b", 20))
|
||||
.isSameByBind(spi(exp().eq("a", 10).eq("b", 20)))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffValues() {
|
||||
|
||||
assertThat(spi(exp().eq("a", 10).eq("b", 20))
|
||||
.isSameByBind(spi(exp().eq("a", 10).eq("b", 30)))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_less() {
|
||||
|
||||
assertThat(spi(exp().eq("a", 10))
|
||||
.isSameByBind(spi(exp().eq("a", 10).eq("b", 20)))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_more() {
|
||||
|
||||
assertThat(spi(exp().eq("a", 10))
|
||||
.isSameByBind(spi(exp().eq("a", 10).eq("b", 20)))).isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
|
||||
public class ExistsExpressionTest {
|
||||
|
||||
|
||||
@NotNull
|
||||
private ExistsExpression exp(boolean not, String sql, Object... bindValues) {
|
||||
return new ExistsExpression(not, sql, Arrays.asList(bindValues));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_same() {
|
||||
|
||||
assertThat(exp(true,"a", 10).isSameByPlan(exp(true,"a", 10))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffBind_same() {
|
||||
|
||||
assertThat(exp(true,"a", 10).isSameByPlan(exp(true,"a", 20))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffNot() {
|
||||
|
||||
assertThat(exp(true,"a", 10).isSameByPlan(exp(false,"a", 10))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffSql() {
|
||||
|
||||
assertThat(exp(true,"a", 10).isSameByPlan(exp(true,"b", 10))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_sameBindValues() {
|
||||
|
||||
assertThat(exp(true,"a", 10).isSameByBind(exp(true,"a", 10))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_sameMultipleBindValues() {
|
||||
|
||||
assertThat(exp(true,"a", 10, "ABC", 20).isSameByBind(exp(true,"a", 10, "ABC", 20))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffMultipleBindValues() {
|
||||
|
||||
assertThat(exp(true,"a", 10, "ABC", 20).isSameByBind(exp(true,"a", 10, "ABC", 21))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffMultipleBindValuesByOrder() {
|
||||
|
||||
assertThat(exp(true,"a", 10, "ABC", 20).isSameByBind(exp(true,"a", 10, 20, "ABC"))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffBindValues() {
|
||||
|
||||
assertThat(exp(true,"a", 10).isSameByBind(exp(true,"a", 20))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_lessBindValues() {
|
||||
|
||||
assertThat(exp(true,"a", 10, 20).isSameByBind(exp(true,"a", 20))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_moreBindValues() {
|
||||
|
||||
assertThat(exp(true,"a", 10).isSameByBind(exp(true,"a", 10, 20))).isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
|
||||
public class IdExpressionTest {
|
||||
|
||||
|
||||
@NotNull
|
||||
private IdExpression exp(Object value) {
|
||||
return new IdExpression(value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_same() {
|
||||
|
||||
assertThat(exp(10).isSameByPlan(exp(10))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffBind_same() {
|
||||
|
||||
assertThat(exp(10).isSameByPlan(exp(20))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_sameBindValues() {
|
||||
|
||||
assertThat(exp(10).isSameByBind(exp(10))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffBindValues() {
|
||||
|
||||
assertThat(exp(10).isSameByBind(exp(20))).isFalse();
|
||||
assertThat(exp(10).isSameByBind(exp("junk"))).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
|
||||
public class IdInExpressionTest {
|
||||
|
||||
|
||||
@NotNull
|
||||
private IdInExpression exp(Object... values) {
|
||||
return new IdInExpression(Arrays.asList(values));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_same() {
|
||||
|
||||
assertThat(exp(10).isSameByPlan(exp(10))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffBind_same() {
|
||||
|
||||
assertThat(exp(10).isSameByPlan(exp(20))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffBindCount() {
|
||||
|
||||
assertThat(exp(10).isSameByPlan(exp(10, 20))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_sameBindValues() {
|
||||
|
||||
assertThat(exp(10).isSameByBind(exp(10))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_mulitpleSameBindValues() {
|
||||
|
||||
assertThat(exp(10,"ABC", 20).isSameByBind(exp(10, "ABC", 20))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffBindValues() {
|
||||
|
||||
assertThat(exp(10).isSameByBind(exp("junk"))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_lessBindValues() {
|
||||
|
||||
assertThat(exp(10,"ABC", 20).isSameByBind(exp(10, "ABC"))).isFalse();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_moreBindValues() {
|
||||
|
||||
assertThat(exp(10,"ABC").isSameByBind(exp(10, "ABC", 30))).isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +1,16 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
|
||||
public class InExpressionTest {
|
||||
|
||||
@@ -87,4 +91,70 @@ public class InExpressionTest {
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private InExpression exp(String propName, boolean not, Object... values) {
|
||||
return new InExpression(propName, Arrays.asList(values), not);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_same() {
|
||||
|
||||
assertThat(exp("a", false, 10).isSameByPlan(exp("a", false, 10))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffPropertyName() {
|
||||
|
||||
assertThat(exp("a", false, 10).isSameByPlan(exp("b", false, 10))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffNot() {
|
||||
|
||||
assertThat(exp("a", false, 10).isSameByPlan(exp("a", true, 10))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffBind_same() {
|
||||
|
||||
assertThat(exp("a", false, 10).isSameByPlan(exp("a", false, 10, 20))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffBindCount() {
|
||||
|
||||
assertThat(exp("a", false, 10).isSameByPlan(exp("a", false, 10, 20))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_sameBindValues() {
|
||||
|
||||
assertThat(exp("a", false, 10).isSameByBind(exp("a", false, 10))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_sameMultipleBindValues() {
|
||||
|
||||
assertThat(exp("a", false, 10, "ABC", 20).isSameByBind(exp("a", false, 10, "ABC", 20))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffBindValues() {
|
||||
|
||||
assertThat(exp("a", false, 10).isSameByBind(exp("a", false, "foo"))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_lessBindValues() {
|
||||
|
||||
assertThat(exp("a", false, 10, "ABC", 20).isSameByBind(exp("a", false, 10, "ABC"))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_moreBindValues() {
|
||||
|
||||
assertThat(exp("a", false, 10, "ABC").isSameByBind(exp("a", false, 10, "ABC", 30))).isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
|
||||
public class InQueryExpressionTest {
|
||||
|
||||
|
||||
@NotNull
|
||||
private InQueryExpression exp(String propertyName, boolean not, String sql, Object... bindValues) {
|
||||
return new InQueryExpression(propertyName, not, sql, Arrays.asList(bindValues));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_same() {
|
||||
|
||||
assertThat(exp("name",true,"sql", 10).isSameByPlan(exp("name",true,"sql", 10))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffBind_same() {
|
||||
|
||||
assertThat(exp("name",true,"sql", 10).isSameByPlan(exp("name",true,"sql", 20))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffNPropertyName() {
|
||||
|
||||
assertThat(exp("name",true,"sql", 10).isSameByPlan(exp("nameDiff",true,"sql", 10))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffNot() {
|
||||
|
||||
assertThat(exp("name",true,"sql", 10).isSameByPlan(exp("name",false,"sql", 10))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffSql() {
|
||||
|
||||
assertThat(exp("name",true,"sql", 10).isSameByPlan(exp("name",true,"sqlDiff", 10))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_sameBindValues() {
|
||||
|
||||
assertThat(exp("name",true,"sql", 10).isSameByBind(exp("name",true,"sql", 10))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_sameMultipleBindValues() {
|
||||
|
||||
assertThat(exp("name",true,"sql", 10, "ABC", 20).isSameByBind(exp("name",true,"sql", 10, "ABC", 20))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffMultipleBindValues() {
|
||||
|
||||
assertThat(exp("name",true,"sql", 10, "ABC", 20).isSameByBind(exp("name",true,"sql", 10, "ABC", 21))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffMultipleBindValuesByOrder() {
|
||||
|
||||
assertThat(exp("name",true,"sql", 10, "ABC", 20).isSameByBind(exp("name",true,"sql", 10, 20, "ABC"))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffBindValues() {
|
||||
|
||||
assertThat(exp("name",true,"sql", 10).isSameByBind(exp("name",true,"sql", 20))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_lessBindValues() {
|
||||
|
||||
assertThat(exp("name",true,"sql", 10, 20).isSameByBind(exp("name",true,"sql", 20))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_moreBindValues() {
|
||||
|
||||
assertThat(exp("name",true,"sql", 10).isSameByBind(exp("name",true,"sql", 10, 20))).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
|
||||
public class JsonPathExpressionTest {
|
||||
|
||||
@NotNull
|
||||
private JsonPathExpression exp(String propertyName, String path, Op operator, Object value) {
|
||||
return new JsonPathExpression(propertyName, path, operator, value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_same() {
|
||||
|
||||
assertThat(exp("a", "path", Op.EQ, 10).isSameByPlan(exp("a", "path", Op.EQ, 10))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffBind_same() {
|
||||
|
||||
assertThat(exp("a", "path", Op.EQ, 10).isSameByPlan(exp("a", "path", Op.EQ, 20))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffPath() {
|
||||
|
||||
assertThat(exp("a", "path", Op.EQ, 10).isSameByPlan(exp("a", "pathDiff", Op.EQ, 10))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffProperty_diff() {
|
||||
|
||||
assertThat(exp("a", "path", Op.EQ, 10).isSameByPlan(exp("b", "path", Op.EQ, 10))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffOperator_diff() {
|
||||
|
||||
assertThat(exp("a", "path", Op.EQ, 10).isSameByPlan(exp("a", "path", Op.LT, 10))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffType_diff() {
|
||||
|
||||
assertThat(exp("a", "path", Op.EQ, 10).isSameByPlan(new NoopExpression())).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_sameBindValues() {
|
||||
|
||||
assertThat(exp("a", "path", Op.EQ, 10).isSameByBind(exp("a", "path", Op.LT, 10))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_sameNullBindValues() {
|
||||
|
||||
assertThat(exp("a", "path", Op.EQ, null).isSameByBind(exp("a", "path", Op.LT, null))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffBindValues() {
|
||||
|
||||
assertThat(exp("a", "path", Op.EQ, 10).isSameByBind(exp("a", "path", Op.EQ, "junk"))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffFirstNullBindValues() {
|
||||
|
||||
assertThat(exp("a", "path", Op.EQ, null).isSameByBind(exp("a", "path", Op.LT, 10))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffLastNullBindValues() {
|
||||
|
||||
assertThat(exp("a", "path", Op.EQ, 10).isSameByBind(exp("a", "path", Op.LT, null))).isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebean.Expr;
|
||||
import com.avaje.ebean.Expression;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
|
||||
public class JunctionExpressionTest {
|
||||
|
||||
Expression eq(String propName, int value) {
|
||||
return Expr.eq(propName, value);
|
||||
}
|
||||
|
||||
|
||||
DefaultExpressionList<?> exp(Expression... expressions) {
|
||||
|
||||
DefaultExpressionList<Object> list = new DefaultExpressionList<Object>(null, new DefaultExpressionFactory(true), null);
|
||||
for (Expression ex : expressions) {
|
||||
list.add(ex);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
<T> JunctionExpression and(DefaultExpressionList<T> list) {
|
||||
return new JunctionExpression.Conjunction<T>(list);
|
||||
}
|
||||
|
||||
<T> JunctionExpression or(DefaultExpressionList<T> list) {
|
||||
return new JunctionExpression.Disjunction<T>(list);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_same() {
|
||||
|
||||
assertThat(and(exp(eq("a", 10), eq("b", 10)))
|
||||
.isSameByPlan(and(exp(eq("a", 10), eq("b", 10))))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyForPlanKey_isSameByPlan_when_same() {
|
||||
|
||||
assertThat(and(exp(eq("a", 10), eq("b", 10)).copyForPlanKey())
|
||||
.isSameByPlan(and(exp(eq("a", 10), eq("b", 10))))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyForPlanKey_isSameByPlan_when_diff() {
|
||||
|
||||
assertThat(and(exp(eq("a", 10), eq("b", 10)).copyForPlanKey())
|
||||
.isSameByPlan(and(exp(eq("a", 10), eq("c", 10))))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffType() {
|
||||
|
||||
assertThat(and(exp(eq("a", 10), eq("b", 10)))
|
||||
.isSameByPlan(or(exp(eq("a", 10), eq("b", 10))))).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebean.LikeType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
|
||||
public class LikeExpressionTest extends BaseExpressionTest {
|
||||
|
||||
|
||||
@NotNull
|
||||
private LikeExpression exp(String propertyName, String value, boolean caseInsensitive, LikeType type) {
|
||||
return new LikeExpression(propertyName, value, caseInsensitive, type);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_same() {
|
||||
|
||||
assertThat(exp("a", "rob", true, LikeType.STARTS_WITH)
|
||||
.isSameByPlan(exp("a", "rob", true, LikeType.STARTS_WITH))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffBind_then_stillSame() {
|
||||
|
||||
assertThat(exp("a", "rob", true, LikeType.STARTS_WITH)
|
||||
.isSameByPlan(exp("a", "bor", true, LikeType.STARTS_WITH))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffCaseInsensitive() {
|
||||
|
||||
assertThat(exp("a", "rob", true, LikeType.STARTS_WITH)
|
||||
.isSameByPlan(exp("a", "rob", false, LikeType.STARTS_WITH))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffLikeType() {
|
||||
|
||||
assertThat(exp("a", "rob", true, LikeType.STARTS_WITH)
|
||||
.isSameByPlan(exp("a", "rob", true, LikeType.ENDS_WITH))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffProperty() {
|
||||
|
||||
assertThat(exp("a", "rob", true, LikeType.STARTS_WITH)
|
||||
.isSameByPlan(exp("b", "rob", true, LikeType.STARTS_WITH))).isFalse();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_sameBindValues() {
|
||||
|
||||
assertThat(exp("a", "rob", true, LikeType.STARTS_WITH)
|
||||
.isSameByBind(exp("a", "rob", true, LikeType.STARTS_WITH))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffBindValues() {
|
||||
|
||||
assertThat(exp("a", "rob", true, LikeType.STARTS_WITH)
|
||||
.isSameByBind(exp("a", "bor", true, LikeType.STARTS_WITH))).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebean.Expr;
|
||||
import com.avaje.ebean.Expression;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class LogicExpressionTest extends BaseExpressionTest {
|
||||
|
||||
Expression eq(String propName, int value) {
|
||||
return Expr.eq(propName, value);
|
||||
}
|
||||
|
||||
LogicExpression and(Expression a, Expression b) {
|
||||
return new LogicExpression.And(a, b);
|
||||
}
|
||||
|
||||
LogicExpression or(Expression a, Expression b) {
|
||||
return new LogicExpression.Or(a, b);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_same() {
|
||||
|
||||
assertThat(and(eq("a", 10), eq("b", 10))
|
||||
.isSameByPlan(and(eq("a", 10), eq("b", 10)))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffBind_then_stillSame() {
|
||||
|
||||
assertThat(and(eq("a", 10), eq("b", 10))
|
||||
.isSameByPlan(and(eq("a", 20), eq("b", 20)))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffExp1_then_diff() {
|
||||
|
||||
assertThat(and(eq("a", 10), eq("b", 10))
|
||||
.isSameByPlan(and(eq("c", 10), eq("b", 10)))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffExp2_then_diff() {
|
||||
|
||||
assertThat(and(eq("a", 10), eq("b", 10))
|
||||
.isSameByPlan(and(eq("a", 10), eq("c", 10)))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffType_then_diff() {
|
||||
|
||||
assertThat(or(eq("a", 10), eq("b", 10))
|
||||
.isSameByPlan(and(eq("a", 10), eq("c", 10)))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffExpressionType() {
|
||||
|
||||
assertThat(or(eq("a", 10), eq("b", 10))
|
||||
.isSameByPlan(new NoopExpression())).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_sameBindValues() {
|
||||
|
||||
assertThat(and(eq("a", 10), eq("b", 10))
|
||||
.isSameByBind(and(eq("a", 10), eq("c", 10)))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffBindValues() {
|
||||
|
||||
assertThat(and(eq("a", 10), eq("b", 10))
|
||||
.isSameByBind(and(eq("a", 10), eq("c", 20)))).isFalse();
|
||||
}
|
||||
}
|
||||
+27
-1
@@ -8,7 +8,8 @@ import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class NoopExpressionQueryTest extends BaseTestCase {
|
||||
|
||||
public class NoopExpressionTest extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
@@ -39,4 +40,29 @@ public class NoopExpressionQueryTest extends BaseTestCase {
|
||||
|
||||
assertThat(generatedSql).contains("select t0.id c0 from o_customer t0 where t0.name is null and 1=1 and t0.status is not null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_same() {
|
||||
|
||||
assertThat(new NoopExpression().isSameByPlan(new NoopExpression())).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffExpressionType() {
|
||||
|
||||
assertThat(new NoopExpression().isSameByPlan(null)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_same() {
|
||||
|
||||
assertThat(new NoopExpression().isSameByBind(new NoopExpression())).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffExpressionType() {
|
||||
|
||||
assertThat(new NoopExpression().isSameByBind(null)).isTrue();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
|
||||
import com.avaje.ebean.Expression;
|
||||
import org.junit.Test;
|
||||
|
||||
import static com.avaje.ebean.Expr.eq;
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
|
||||
public class NotExpressionTest {
|
||||
|
||||
|
||||
NotExpression not(Expression expression) {
|
||||
return new NotExpression(expression);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_same() {
|
||||
|
||||
assertThat(not(eq("a", 10))
|
||||
.isSameByPlan(not(eq("a", 10)))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_sameByPlan() {
|
||||
|
||||
assertThat(not(eq("a", 10))
|
||||
.isSameByPlan(not(eq("a", 20)))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_different() {
|
||||
|
||||
assertThat(not(eq("a", 10))
|
||||
.isSameByPlan(not(eq("b", 10)))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_differentExpressionType() {
|
||||
|
||||
assertThat(not(eq("a", 10))
|
||||
.isSameByPlan(new NoopExpression())).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_same() {
|
||||
|
||||
assertThat(not(eq("a", 10))
|
||||
.isSameByBind(not(eq("b", 10)))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_different() {
|
||||
|
||||
assertThat(not(eq("a", 10))
|
||||
.isSameByBind(not(eq("a", 20)))).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class NullExpressionTest extends BaseExpressionTest {
|
||||
|
||||
NullExpression nullExp(String propertyName, boolean notNull) {
|
||||
return new NullExpression(propertyName, notNull);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addSql_when_notNull() throws Exception {
|
||||
|
||||
DefaultExpressionRequest expReq = newExpressionRequest();
|
||||
|
||||
nullExp("id", true).addSql(expReq);
|
||||
|
||||
assertThat(expReq.getSql()).isEqualTo("id is not null ");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addSql_when_null() throws Exception {
|
||||
|
||||
DefaultExpressionRequest expReq = newExpressionRequest();
|
||||
|
||||
nullExp("id", false).addSql(expReq);
|
||||
|
||||
assertThat(expReq.getSql()).isEqualTo("id is null ");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addSql_when_notNull_and_assocOne() throws Exception {
|
||||
|
||||
DefaultExpressionRequest expReq = newExpressionRequest();
|
||||
|
||||
nullExp("customer", true).addSql(expReq);
|
||||
|
||||
assertThat(expReq.getSql()).isEqualTo("customer.id is not null ");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addSql_when_null_and_assocOne() throws Exception {
|
||||
|
||||
DefaultExpressionRequest expReq = newExpressionRequest();
|
||||
|
||||
nullExp("customer", false).addSql(expReq);
|
||||
|
||||
assertThat(expReq.getSql()).isEqualTo("customer.id is null ");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyForPlanKey_isSameInstance() throws Exception {
|
||||
|
||||
NullExpression exp = nullExp("customer.name", false);
|
||||
SpiExpression other = exp.copyForPlanKey();
|
||||
|
||||
assertThat(exp).isSameAs(other);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_true() throws Exception {
|
||||
|
||||
assertThat(nullExp("customer.name", false)
|
||||
.isSameByBind(nullExp("customer.name", false))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_true() throws Exception {
|
||||
|
||||
assertThat(nullExp("customer.name", false)
|
||||
.isSameByPlan(nullExp("customer.name", false))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_false_when_notNullDiff() throws Exception {
|
||||
|
||||
assertThat(new NullExpression("customer.name", false)
|
||||
.isSameByPlan(new NullExpression("customer.name", true))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_false_when_propertyNameDiff() throws Exception {
|
||||
|
||||
assertThat(new NullExpression("customer.startDate", true)
|
||||
.isSameByPlan(new NullExpression("customer.name", true))).isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
|
||||
public class RawExpressionTest {
|
||||
|
||||
@NotNull
|
||||
private RawExpression exp(String sql, Object... values) {
|
||||
return new RawExpression(sql, values);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_same() {
|
||||
assertThat(exp("a", 10).isSameByPlan(exp("a", 10))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffBindValues() {
|
||||
assertThat(exp("a", 10).isSameByPlan(exp("a", 20))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffSql() {
|
||||
assertThat(exp("a", 10).isSameByPlan(exp("b", 10))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_same() {
|
||||
assertThat(exp("a", 10).isSameByBind(exp("a", 10))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffBindValues() {
|
||||
assertThat(exp("a", 10).isSameByBind(exp("a", 20))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_moreBindValues() {
|
||||
assertThat(exp("a", 10).isSameByBind(exp("a", 10, 20))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_lessBindValues() {
|
||||
assertThat(exp("a", 10, 20).isSameByBind(exp("a", 10))).isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
public class SameTest {
|
||||
|
||||
@Test
|
||||
public void sameByNull() throws Exception {
|
||||
|
||||
assertThat(Same.sameByNull("a", "a")).isTrue();
|
||||
assertThat(Same.sameByNull("a", "b")).isTrue();
|
||||
assertThat(Same.sameByNull(null, null)).isTrue();
|
||||
assertThat(Same.sameByNull("a", null)).isFalse();
|
||||
assertThat(Same.sameByNull(null, "a")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sameByValue() throws Exception {
|
||||
|
||||
assertThat(Same.sameByValue("a", "a")).isTrue();
|
||||
assertThat(Same.sameByValue("a", "b")).isFalse();
|
||||
assertThat(Same.sameByValue(null, null)).isTrue();
|
||||
assertThat(Same.sameByValue("a", null)).isFalse();
|
||||
assertThat(Same.sameByValue(null, "a")).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class SimpleExpressionTest extends BaseExpressionTest {
|
||||
|
||||
@NotNull
|
||||
private SimpleExpression exp(String propertyName, Op operator, Object value) {
|
||||
return new SimpleExpression(propertyName, operator, value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_same() {
|
||||
|
||||
assertThat(exp("a", Op.EQ, 10).isSameByPlan(exp("a", Op.EQ, 10))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffBind_same() {
|
||||
|
||||
assertThat(exp("a", Op.EQ, 10).isSameByPlan(exp("a", Op.EQ, 20))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffProperty_diff() {
|
||||
|
||||
assertThat(exp("a", Op.EQ, 10).isSameByPlan(exp("b", Op.EQ, 10))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffOperator_diff() {
|
||||
|
||||
assertThat(exp("a", Op.EQ, 10).isSameByPlan(exp("a", Op.LT, 10))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByPlan_when_diffType_diff() {
|
||||
|
||||
assertThat(exp("a", Op.EQ, 10).isSameByPlan(new NoopExpression())).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_sameBindValues() {
|
||||
|
||||
assertThat(exp("a", Op.EQ, 10).isSameByBind(exp("a", Op.LT, 10))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameByBind_when_diffBindValues() {
|
||||
|
||||
assertThat(exp("a", Op.EQ, 10).isSameByBind(exp("a", Op.EQ, "junk"))).isFalse();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.avaje.ebeaninternal.server.query;
|
||||
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class RawSqlQueryPlanKeyTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void test_equals_same_instance() {
|
||||
|
||||
RawSqlQueryPlanKey key = key("select foo", true, true, "");
|
||||
assertThat(key).isEqualTo(key);
|
||||
assertThat(key.hashCode()).isEqualTo(key.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_equals_diff_instance() {
|
||||
|
||||
assertThat(key("select foo", true, true, "")).isEqualTo(key("select foo", true, true, ""));
|
||||
assertThat(key("select foo", true, true, "").hashCode()).isEqualTo(key("select foo", true, true, "").hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_notEquals_diff_sql() {
|
||||
|
||||
assertThat(key("select foo", true, true, "")).isNotEqualTo(key("select bar", true, true, ""));
|
||||
assertThat(key("select foo", true, true, "").hashCode()).isNotEqualTo(key("select bar", true, true, "").hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_notEquals_diff_rawSqlFlag() {
|
||||
|
||||
assertThat(key("select foo", true, true, "")).isNotEqualTo(key("select foo", false, true, ""));
|
||||
assertThat(key("select foo", true, true, "").hashCode()).isNotEqualTo(key("select foo", false, true, "").hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_notEquals_diff_rowNumberIncluded() {
|
||||
|
||||
assertThat(key("select foo", true, true, "")).isNotEqualTo(key("select foo", true, false, ""));
|
||||
assertThat(key("select foo", true, true, "").hashCode()).isNotEqualTo(key("select foo", true, false, "").hashCode());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void test_notEquals_diff_logWhereSql() {
|
||||
|
||||
assertThat(key("select foo", true, true, "")).isNotEqualTo(key("select foo", true, true, "a"));
|
||||
assertThat(key("select foo", true, true, "").hashCode()).isNotEqualTo(key("select foo", true, true, "a").hashCode());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private RawSqlQueryPlanKey key(String sql, boolean rawSql, boolean rowNumberIncluded, String logWhereSql) {
|
||||
return new RawSqlQueryPlanKey(sql, rawSql, rowNumberIncluded, logWhereSql);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,7 +16,7 @@ public class DefaultOrmQueryTest {
|
||||
DefaultOrmQuery<Order> q1 = (DefaultOrmQuery<Order>)Ebean.find(Order.class).where().in("name", "a","b","c").query();
|
||||
DefaultOrmQuery<Order> q2 = (DefaultOrmQuery<Order>)Ebean.find(Order.class).where().in("id", 2,2,3).query();
|
||||
|
||||
assertThat(q1.calculateQueryPlanHash()).isNotEqualTo(q2.calculateQueryPlanHash());
|
||||
assertThat(q1.createQueryPlanKey()).isNotEqualTo(q2.createQueryPlanKey());
|
||||
assertThat(q1.queryBindHash()).isNotEqualTo(q2.queryBindHash());
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public class DefaultOrmQueryTest {
|
||||
DefaultOrmQuery<Order> q1 = (DefaultOrmQuery<Order>)Ebean.find(Order.class).where().in("id", 1,2,3).query();
|
||||
DefaultOrmQuery<Order> q2 = (DefaultOrmQuery<Order>)Ebean.find(Order.class).where().in("id", 2,2,3).query();
|
||||
|
||||
assertThat(q1.calculateQueryPlanHash()).isEqualTo(q2.calculateQueryPlanHash());
|
||||
assertThat(q1.createQueryPlanKey()).isEqualTo(q2.createQueryPlanKey());
|
||||
assertThat(q1.queryBindHash()).isNotEqualTo(q2.queryBindHash());
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ public class DefaultOrmQueryTest {
|
||||
DefaultOrmQuery<Order> q1 = (DefaultOrmQuery<Order>)Ebean.find(Order.class).where().in("id", 1,2,3).query();
|
||||
DefaultOrmQuery<Order> q2 = (DefaultOrmQuery<Order>)Ebean.find(Order.class).where().in("id", 1,2,3).query();
|
||||
|
||||
assertThat(q1.calculateQueryPlanHash()).isEqualTo(q2.calculateQueryPlanHash());
|
||||
assertThat(q1.createQueryPlanKey()).isEqualTo(q2.createQueryPlanKey());
|
||||
assertThat(q1.queryBindHash()).isEqualTo(q2.queryBindHash());
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ public class DefaultOrmQueryTest {
|
||||
.fetch("details", "orderQty, unitPrice")
|
||||
.fetch("details.product", "sku, name");
|
||||
|
||||
assertThat(query1.calculateQueryPlanHash()).isNotEqualTo(query2.calculateQueryPlanHash());
|
||||
assertThat(query1.createQueryPlanKey()).isNotEqualTo(query2.createQueryPlanKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -69,7 +69,7 @@ public class DefaultOrmQueryTest {
|
||||
.setFirstRow(1)
|
||||
.setMaxRows(0);
|
||||
|
||||
assertThat(query1.calculateQueryPlanHash()).isNotEqualTo(query2.calculateQueryPlanHash());
|
||||
assertThat(query1.createQueryPlanKey()).isNotEqualTo(query2.createQueryPlanKey());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,432 @@
|
||||
package com.avaje.ebeaninternal.server.querydefn;
|
||||
|
||||
|
||||
import com.avaje.ebean.OrderBy;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionList;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoin;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoinColumn;
|
||||
import com.avaje.ebeaninternal.server.expression.BaseExpressionTest;
|
||||
import com.avaje.tests.model.basic.Customer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class OrmQueryPlanKeyTest extends BaseExpressionTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void equals_when_defaults() {
|
||||
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
|
||||
assertSame(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffTableJoinNull() {
|
||||
|
||||
TableJoin tableJoin = tableJoin("id", "customer_id");
|
||||
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(tableJoin, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffTableJoin() {
|
||||
|
||||
TableJoin tableJoin1 = tableJoin("id", "customer_id");
|
||||
TableJoin tableJoin2 = tableJoin("id", "other_customer_id");
|
||||
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(tableJoin1, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(tableJoin2, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_sameTableJoin() {
|
||||
|
||||
TableJoin tableJoin1 = tableJoin("id", "customer_id");
|
||||
TableJoin tableJoin2 = tableJoin("id", "customer_id");
|
||||
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(tableJoin1, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(tableJoin2, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
|
||||
assertSame(key1, key2);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private TableJoin tableJoin(String col1, String col2) {
|
||||
DeployTableJoin deploy = new DeployTableJoin();
|
||||
deploy.setTable("myTable");
|
||||
deploy.addJoinColumn(new DeployTableJoinColumn(col1, col2));
|
||||
return new TableJoin(deploy);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffQueryType() {
|
||||
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.LIST, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_firstRowsDifferent() {
|
||||
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 10, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_maxRowsDifferent() {
|
||||
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 10, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_firstRowsMaxRowsSame() {
|
||||
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 10, 20, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 10, 20, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
|
||||
assertSame(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffDisableLazyLoading() {
|
||||
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, true, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffRawWhereNull() {
|
||||
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, "rawWhere", null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffRawWhere() {
|
||||
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, "rawWhere", null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, "rawDiff", null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffOrderByNull() {
|
||||
|
||||
OrderBy<Object> o1 = new OrderBy<Object>("id");
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, o1, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_orderBySame() {
|
||||
|
||||
OrderBy<Object> o1 = new OrderBy<Object>("id, name");
|
||||
OrderBy<Object> o2 = new OrderBy<Object>("id, name");
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, o1, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, o2, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
|
||||
assertSame(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffQueryNull() {
|
||||
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, "query", null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void equals_when_diffQuery() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, "query", null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, "queryDiff", null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_querySame() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, "query", null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, "query", null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertSame(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffAddWhereNull() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, "addWhere", null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffAddWhere() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, "addWhere", null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, "diff", null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_sameAddWhere() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, "addWhere", null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, "addWhere", null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertSame(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffAddHavingNull() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, "addHaving", false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffAddHaving() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, "addHaving", false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, "diff", false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_sameAddHaving() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, "addHaving", false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, "addHaving", false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertSame(key1, key2);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void equals_when_diffDistinct() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, true, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_sameDistinct() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, true, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, true, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertSame(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffSqlDistinct() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, true, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_sameSqlDistinct() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, true, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, true, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertSame(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffMapKeyNull() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, "mapKey", null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffMapKey() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, "mapKey", null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, "diff", null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_sameMapKey() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, "mapKey", null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, "mapKey", null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertSame(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffIdNull() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, 42, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_idBothGiven() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, 42, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, 23, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertSame(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffTemporalMode() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.DRAFT, false, null, null);
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffForUpdate() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, true, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffRootAliasNull() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, "rootAlias", null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffRootAlias() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, "rootAlias", null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, "diff", null);
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_sameRootAlias() {
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, "rootAlias", null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, "rootAlias", null);
|
||||
assertSame(key1, key2);
|
||||
}
|
||||
|
||||
SpiExpressionList<Customer> list_id_eq_42() {
|
||||
return (SpiExpressionList<Customer>) server().find(Customer.class)
|
||||
.where().eq("id", 42);
|
||||
}
|
||||
|
||||
SpiExpressionList<Customer> list_id_eq_43() {
|
||||
return (SpiExpressionList<Customer>) server().find(Customer.class)
|
||||
.where().eq("id", 43);
|
||||
}
|
||||
|
||||
SpiExpressionList<Customer> list_id_eq_42_and_name_eq_rob() {
|
||||
return (SpiExpressionList<Customer>) server().find(Customer.class)
|
||||
.where().eq("id", 43).eq("name", "rob");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void equals_when_sameWhere() {
|
||||
|
||||
|
||||
SpiExpressionList<Customer> list1 = list_id_eq_42();
|
||||
SpiExpressionList<Customer> list2 = list_id_eq_43();
|
||||
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, list1, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, list2, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertSame(key1, key2);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void equals_when_diffWhere() {
|
||||
|
||||
SpiExpressionList<Customer> where1 = list_id_eq_42();
|
||||
SpiExpressionList<Customer> where2 = list_id_eq_42_and_name_eq_rob();
|
||||
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, where1, null, SpiQuery.TemporalMode.DRAFT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, where2, null, SpiQuery.TemporalMode.DRAFT, false, null, null);
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffWhereNullLast() {
|
||||
|
||||
SpiExpressionList<Customer> list1 = list_id_eq_42();
|
||||
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, list1, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffWhereNullFirst() {
|
||||
|
||||
SpiExpressionList<Customer> list1 = list_id_eq_42();
|
||||
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, list1, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffHaving() {
|
||||
|
||||
SpiExpression having1 = list_id_eq_42().copyForPlanKey();
|
||||
SpiExpression having2 = list_id_eq_42_and_name_eq_rob().copyForPlanKey();
|
||||
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, having1, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, having2, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertDifferent(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_sameHaving() {
|
||||
|
||||
SpiExpression having1 = list_id_eq_42().copyForPlanKey();
|
||||
SpiExpression having2 = list_id_eq_42().copyForPlanKey();
|
||||
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, having1, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, having2, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertSame(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_havingNullLast() {
|
||||
|
||||
SpiExpression having1 = list_id_eq_42().copyForPlanKey();
|
||||
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, having1, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertSame(key1, key2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_havingNullFirst() {
|
||||
|
||||
SpiExpression having1 = list_id_eq_42().copyForPlanKey();
|
||||
|
||||
OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, having1, SpiQuery.TemporalMode.CURRENT, false, null, null);
|
||||
assertSame(key1, key2);
|
||||
}
|
||||
|
||||
private void assertDifferent(OrmQueryPlanKey key1, OrmQueryPlanKey key2) {
|
||||
assertThat(key1).isNotEqualTo(key2);
|
||||
assertThat(key1.hashCode()).isNotEqualTo(key2.hashCode());
|
||||
}
|
||||
|
||||
private void assertSame(OrmQueryPlanKey key1, OrmQueryPlanKey key2) {
|
||||
assertThat(key1).isEqualTo(key2);
|
||||
assertThat(key1.hashCode()).isEqualTo(key2.hashCode());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user