#566 - Refactor internals - SpiExpression, add prepareExpression() to merge queryAutoTuneHash() and queryPlanHash() - initial

This commit is contained in:
Robin Bygrave
2016-02-13 20:13:16 +13:00
parent 0d456b2ad6
commit 769e4bb488
29 changed files with 239 additions and 239 deletions
@@ -17,32 +17,26 @@ public interface SpiExpression extends Expression {
* </p>
*/
void containsMany(BeanDescriptor<?> desc, ManyWhereJoins whereManyJoins);
/**
/**
* Prepare the expression. For example, compile sub-query expressions etc.
*/
void prepareExpression(BeanQueryRequest<?> request);
/**
* Calculate a hash value used to identify a query for AutoTune tuning.
* <p>
* That is, if the hash changes then the query will be considered different
* from an AutoTune perspective and get different tuning.
* </p>
*/
void queryAutoTuneHash(HashQueryPlanBuilder builder);
/**
* Calculate a hash value for the expression.
* This includes the expression type and property but should exclude
* the bind values.
* <p>
* This is used where queries are the same except for the bind values, in which
* case the query execution plan can be reused.
* </p>
*/
void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder);
void queryPlanHash(HashQueryPlanBuilder builder);
/**
* Return the hash value for the values that will be bound.
*/
int queryBindHash();
/**
* Add some sql to the query.
* <p>
@@ -61,7 +55,7 @@ public interface SpiExpression extends Expression {
/**
* Add the parameter values to be set against query. For each ? place holder
* there should be a corresponding value that is added to the bindList.
*
*
* @param request
* the associated request.
*/
@@ -1,13 +1,12 @@
package com.avaje.ebeaninternal.api;
import java.util.ArrayList;
import java.util.List;
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.
*/
@@ -59,13 +58,18 @@ public interface SpiExpressionList<T> extends ExpressionList<T> {
*
* @return the list of all the bind values in order.
*/
ArrayList<Object> buildBindValues(SpiExpressionRequest request);
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(BeanQueryRequest<?> request, HashQueryPlanBuilder builder);
void queryPlanHash(HashQueryPlanBuilder builder);
/**
* Validate all the properties/paths used in this expression list.
@@ -1,5 +1,6 @@
package com.avaje.ebeaninternal.server.expression;
import com.avaje.ebean.event.BeanQueryRequest;
import com.avaje.ebeaninternal.api.ManyWhereJoins;
import com.avaje.ebeaninternal.api.SpiExpression;
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
@@ -43,6 +44,11 @@ public abstract class AbstractExpression implements SpiExpression {
}
}
@Override
public void prepareExpression(BeanQueryRequest<?> request) {
// do nothing
}
@Override
public void validate(SpiExpressionValidation validation) {
validation.validate(getPropertyName());
@@ -1,18 +1,16 @@
package com.avaje.ebeaninternal.server.expression;
import java.util.Map;
import java.util.Map.Entry;
import com.avaje.ebean.event.BeanQueryRequest;
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;
class AllEqualsExpression implements SpiExpression {
import java.util.Map;
import java.util.Map.Entry;
class AllEqualsExpression extends NonPrepareExpression {
private static final long serialVersionUID = -8691773558205937025L;
@@ -26,6 +24,7 @@ class AllEqualsExpression implements SpiExpression {
return propName;
}
@Override
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
if (propMap != null) {
for (String propertyName : propMap.keySet()) {
@@ -44,6 +43,7 @@ class AllEqualsExpression implements SpiExpression {
}
}
@Override
public void addBindValues(SpiExpressionRequest request) {
if (propMap.isEmpty()) {
@@ -57,6 +57,7 @@ class AllEqualsExpression implements SpiExpression {
}
}
@Override
public void addSql(SpiExpressionRequest request) {
if (propMap.isEmpty()) {
@@ -92,7 +93,8 @@ class AllEqualsExpression implements SpiExpression {
* The null check is required due to the "is null" sql being generated.
* </p>
*/
public void queryAutoTuneHash(HashQueryPlanBuilder builder) {
@Override
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(AllEqualsExpression.class);
@@ -104,10 +106,7 @@ class AllEqualsExpression implements SpiExpression {
}
}
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
queryAutoTuneHash(builder);
}
@Override
public int queryBindHash() {
int hc = 31;
@@ -21,25 +21,25 @@ class BetweenExpression extends AbstractExpression {
this.valueHigh = valHigh;
}
@Override
public void addBindValues(SpiExpressionRequest request) {
request.addBindValue(valueLow);
request.addBindValue(valueHigh);
}
@Override
public void addSql(SpiExpressionRequest request) {
request.append(getPropertyName()).append(BETWEEN).append(" ? and ? ");
}
public void queryAutoTuneHash(HashQueryPlanBuilder builder) {
@Override
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(BetweenExpression.class).add(propName);
builder.bind(2);
}
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
queryAutoTuneHash(builder);
}
@Override
public int queryBindHash() {
int hc = valueLow.hashCode();
hc = hc * 31 + valueHigh.hashCode();
@@ -1,9 +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.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;
@@ -12,7 +10,7 @@ import com.avaje.ebeaninternal.server.el.ElPropertyDeploy;
/**
* Between expression where a value is between two properties.
*/
class BetweenPropertyExpression implements SpiExpression {
class BetweenPropertyExpression extends NonPrepareExpression {
private static final long serialVersionUID = 2078918165221454910L;
@@ -32,6 +30,7 @@ class BetweenPropertyExpression implements SpiExpression {
return propName;
}
@Override
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
ElPropertyDeploy elProp = desc.getElPropertyDeploy(name(lowProperty));
@@ -55,20 +54,19 @@ class BetweenPropertyExpression implements SpiExpression {
request.addBindValue(value);
}
@Override
public void addSql(SpiExpressionRequest request) {
request.append(" ? ").append(BETWEEN).append(name(lowProperty)).append(" and ").append(name(highProperty));
}
public void queryAutoTuneHash(HashQueryPlanBuilder builder) {
@Override
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(BetweenPropertyExpression.class).add(lowProperty).add(highProperty);
builder.bind(1);
}
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
queryAutoTuneHash(builder);
}
@Override
public int queryBindHash() {
return value.hashCode();
}
@@ -41,15 +41,13 @@ class CaseInsensitiveEqualExpression extends AbstractExpression {
request.append("lower(").append(pname).append(") =? ");
}
public void queryAutoTuneHash(HashQueryPlanBuilder builder) {
@Override
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(CaseInsensitiveEqualExpression.class).add(propName);
builder.bind(1);
}
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
queryAutoTuneHash(builder);
}
@Override
public int queryBindHash() {
return value.hashCode();
}
@@ -86,6 +86,7 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio
this.likeType = likeType;
}
@Override
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins whereManyJoins) {
if (list != null) {
for (int i = 0; i < list.size(); i++) {
@@ -94,31 +95,37 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio
}
}
@Override
public ExampleExpression includeZeros() {
includeZeros = true;
return this;
}
@Override
public ExampleExpression caseInsensitive() {
caseInsensitive = true;
return this;
}
@Override
public ExampleExpression useStartsWith() {
likeType = LikeType.STARTS_WITH;
return this;
}
@Override
public ExampleExpression useContains() {
likeType = LikeType.CONTAINS;
return this;
}
@Override
public ExampleExpression useEndsWith() {
likeType = LikeType.ENDS_WITH;
return this;
}
@Override
public ExampleExpression useEqualTo() {
likeType = LikeType.EQUAL_TO;
return this;
@@ -134,6 +141,7 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio
/**
* Adds bind values to the request.
*/
@Override
public void addBindValues(SpiExpressionRequest request) {
for (int i = 0; i < list.size(); i++) {
@@ -145,6 +153,7 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio
/**
* Generates and adds the sql to the request.
*/
@Override
public void addSql(SpiExpressionRequest request) {
if (!list.isEmpty()) {
@@ -162,34 +171,27 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio
}
}
/**
* Return a hash for AutoTune query identification.
*/
public void queryAutoTuneHash(HashQueryPlanBuilder builder) {
// we have not yet built the list of expressions
// so just based on the class name
builder.add(DefaultExampleExpression.class);
@Override
public void prepareExpression(BeanQueryRequest<?> request) {
list = buildExpressions(request);
}
/**
* Return a hash for query plan identification.
* Return a hash for AutoTune query identification.
*/
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
// this is always called once, and always called before
// addSql() and addBindValues() methods
list = buildExpressions(request);
@Override
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(DefaultExampleExpression.class);
for (int i = 0; i < list.size(); i++) {
list.get(i).queryPlanHash(request, builder);
list.get(i).queryPlanHash(builder);
}
}
/**
* Return a hash for the actual bind values used.
*/
@Override
public int queryBindHash() {
int hc = DefaultExampleExpression.class.getName().hashCode();
for (int i = 0; i < list.size(); i++) {
@@ -28,19 +28,17 @@ public class ExistsExpression implements SpiExpression {
this.not = not;
}
public void queryAutoTuneHash(HashQueryPlanBuilder builder) {
builder.add(ExistsExpression.class).add(not);
subQuery.queryAutoTuneHash(builder);
}
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
@Override
public void prepareExpression(BeanQueryRequest<?> request) {
// queryPlanHash executes prior to addSql() or addBindValues()
// ... so compiledQuery will exist
compiledSubQuery = compileSubQuery(request);
}
queryAutoTuneHash(builder);
@Override
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(ExistsExpression.class).add(not);
subQuery.queryAutoTuneHash(builder);
}
/**
@@ -52,10 +50,12 @@ public class ExistsExpression implements SpiExpression {
return ebeanServer.compileQuery(subQuery, queryRequest.getTransaction());
}
@Override
public int queryBindHash() {
return subQuery.queryBindHash();
}
@Override
public void addSql(SpiExpressionRequest request) {
String subSelect = compiledSubQuery.getGeneratedSql();
@@ -69,6 +69,7 @@ public class ExistsExpression implements SpiExpression {
request.append(") ");
}
@Override
public void addBindValues(SpiExpressionRequest request) {
List<Object> bindParams = compiledSubQuery.getPredicates().getWhereExprBindValues();
@@ -1,6 +1,5 @@
package com.avaje.ebeaninternal.server.expression;
import com.avaje.ebean.event.BeanQueryRequest;
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
import com.avaje.ebeaninternal.api.ManyWhereJoins;
import com.avaje.ebeaninternal.api.SpiExpression;
@@ -12,7 +11,7 @@ import com.avaje.ebeaninternal.util.DefaultExpressionRequest;
/**
* Slightly redundant as Query.setId() ultimately also does the same job.
*/
class IdExpression implements SpiExpression {
class IdExpression extends NonPrepareExpression implements SpiExpression {
private static final long serialVersionUID = -3065936341718489842L;
@@ -25,6 +24,7 @@ class IdExpression implements SpiExpression {
/**
* Always returns false.
*/
@Override
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
}
@@ -34,6 +34,7 @@ class IdExpression implements SpiExpression {
// always valid
}
@Override
public void addBindValues(SpiExpressionRequest request) {
// 'flatten' EmbeddedId and multiple Id cases
@@ -45,6 +46,7 @@ class IdExpression implements SpiExpression {
}
}
@Override
public void addSql(SpiExpressionRequest request) {
DefaultExpressionRequest r = (DefaultExpressionRequest) request;
@@ -56,15 +58,13 @@ class IdExpression implements SpiExpression {
/**
* No properties so this is just a unique static number.
*/
public void queryAutoTuneHash(HashQueryPlanBuilder builder) {
@Override
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(IdExpression.class);
builder.bind(1);
}
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
queryAutoTuneHash(builder);
}
@Override
public int queryBindHash() {
return value.hashCode();
}
@@ -1,21 +1,19 @@
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.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;
/**
* Slightly redundant as Query.setId() ultimately also does the same job.
*/
public class IdInExpression implements SpiExpression {
public class IdInExpression extends NonPrepareExpression {
private static final long serialVersionUID = 1L;
@@ -25,6 +23,7 @@ public class IdInExpression implements SpiExpression {
this.idList = idList;
}
@Override
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
}
@@ -33,6 +32,7 @@ public class IdInExpression implements SpiExpression {
// always valid
}
@Override
public void addBindValues(SpiExpressionRequest request) {
// Bind the Id values including EmbeddedId and multiple Id
@@ -60,6 +60,7 @@ public class IdInExpression implements SpiExpression {
request.append(inClause);
}
@Override
public void addSql(SpiExpressionRequest request) {
DefaultExpressionRequest r = (DefaultExpressionRequest) request;
@@ -74,15 +75,13 @@ public class IdInExpression implements SpiExpression {
/**
* Incorporates the number of Id values to bind.
*/
public void queryAutoTuneHash(HashQueryPlanBuilder builder) {
@Override
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(IdInExpression.class).add(idList.size());
builder.bind(idList.size());
}
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
queryAutoTuneHash(builder);
}
@Override
public int queryBindHash() {
return idList.hashCode();
}
@@ -28,6 +28,7 @@ class InExpression extends AbstractExpression {
this.not = not;
}
@Override
public void addBindValues(SpiExpressionRequest request) {
ElPropertyValue prop = getElProp(request);
@@ -51,6 +52,7 @@ class InExpression extends AbstractExpression {
}
}
@Override
public void addSql(SpiExpressionRequest request) {
if (values.length == 0) {
@@ -88,15 +90,13 @@ class InExpression extends AbstractExpression {
/**
* Based on the number of values in the in clause.
*/
public void queryAutoTuneHash(HashQueryPlanBuilder builder) {
@Override
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(InExpression.class).add(propName).add(values.length).add(not);
builder.bind(values.length);
}
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
queryAutoTuneHash(builder);
}
@Override
public int queryBindHash() {
int hc = 31;
for (int i = 0; i < values.length; i++) {
@@ -28,18 +28,15 @@ class InQueryExpression extends AbstractExpression {
this.not = not;
}
public void queryAutoTuneHash(HashQueryPlanBuilder builder) {
builder.add(InQueryExpression.class).add(propName).add(not);
subQuery.queryAutoTuneHash(builder);
@Override
public void prepareExpression(BeanQueryRequest<?> request) {
compiledSubQuery = compileSubQuery(request);
}
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
// queryPlanHash executes prior to addSql() or addBindValues()
// ... so compiledQuery will exist
compiledSubQuery = compileSubQuery(request);
queryAutoTuneHash(builder);
@Override
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(InQueryExpression.class).add(propName).add(not);
subQuery.queryAutoTuneHash(builder);
}
/**
@@ -51,10 +48,12 @@ class InQueryExpression extends AbstractExpression {
return ebeanServer.compileQuery(subQuery, queryRequest.getTransaction());
}
@Override
public int queryBindHash() {
return subQuery.queryBindHash();
}
@Override
public void addSql(SpiExpressionRequest request) {
String subSelect = compiledSubQuery.getGeneratedSql();
@@ -70,6 +69,7 @@ class InQueryExpression extends AbstractExpression {
request.append(") ");
}
@Override
public void addBindValues(SpiExpressionRequest request) {
List<Object> bindParams = compiledSubQuery.getPredicates().getWhereExprBindValues();
@@ -58,15 +58,10 @@ class JsonPathExpression extends AbstractExpression {
}
@Override
public void queryAutoTuneHash(HashQueryPlanBuilder builder) {
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(JsonPathExpression.class).add(propName).add(path).add(operator);
}
@Override
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
queryAutoTuneHash(builder);
}
@Override
public int queryBindHash() {
int hc = (value == null) ? 0 : value.hashCode();
@@ -131,24 +131,23 @@ abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, Expr
}
}
@Override
public void prepareExpression(BeanQueryRequest<?> request) {
List<SpiExpression> list = exprList.internalList();
for (int i = 0; i < list.size(); i++) {
list.get(i).prepareExpression(request);
}
}
/**
* Based on Junction type and all the expression contained.
*/
@Override
public void queryAutoTuneHash(HashQueryPlanBuilder builder) {
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(JunctionExpression.class).add(joinType);
List<SpiExpression> list = exprList.internalList();
for (int i = 0; i < list.size(); i++) {
list.get(i).queryAutoTuneHash(builder);
}
}
@Override
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
builder.add(JunctionExpression.class).add(joinType);
List<SpiExpression> list = exprList.internalList();
for (int i = 0; i < list.size(); i++) {
list.get(i).queryPlanHash(request, builder);
list.get(i).queryPlanHash(builder);
}
}
@@ -1,7 +1,6 @@
package com.avaje.ebeaninternal.server.expression;
import com.avaje.ebean.LikeType;
import com.avaje.ebean.event.BeanQueryRequest;
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
@@ -61,15 +60,13 @@ class LikeExpression extends AbstractExpression {
/**
* Based on caseInsensitive and the property name.
*/
public void queryAutoTuneHash(HashQueryPlanBuilder builder) {
@Override
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(LikeExpression.class).add(caseInsensitive).add(propName);
builder.bind(1);
}
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
queryAutoTuneHash(builder);
}
@Override
public int queryBindHash() {
return val.hashCode();
}
@@ -74,19 +74,19 @@ abstract class LogicExpression implements SpiExpression {
request.append(") ");
}
@Override
public void prepareExpression(BeanQueryRequest<?> request) {
expOne.prepareExpression(request);
expTwo.prepareExpression(request);
}
/**
* Based on the joinType plus the two expressions.
*/
public void queryAutoTuneHash(HashQueryPlanBuilder builder) {
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(LogicExpression.class).add(joinType);
expOne.queryAutoTuneHash(builder);
expTwo.queryAutoTuneHash(builder);
}
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
builder.add(LogicExpression.class).add(joinType);
expOne.queryPlanHash(request, builder);
expTwo.queryPlanHash(request, builder);
expOne.queryPlanHash(builder);
expTwo.queryPlanHash(builder);
}
public int queryBindHash() {
@@ -0,0 +1,15 @@
package com.avaje.ebeaninternal.server.expression;
import com.avaje.ebean.event.BeanQueryRequest;
import com.avaje.ebeaninternal.api.SpiExpression;
/**
* Base abstract expression that does nothing for prepareExpression().
*/
abstract class NonPrepareExpression implements SpiExpression {
@Override
public void prepareExpression(BeanQueryRequest<?> request) {
// do nothing
}
}
@@ -26,13 +26,13 @@ class NoopExpression implements SpiExpression {
}
@Override
public void queryAutoTuneHash(HashQueryPlanBuilder builder) {
builder.add(NoopExpression.class);
public void prepareExpression(BeanQueryRequest<?> request) {
// do nothing
}
@Override
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
queryAutoTuneHash(builder);
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(NoopExpression.class);
}
@Override
@@ -40,17 +40,18 @@ final class NotExpression implements SpiExpression {
request.append(") ");
}
@Override
public void prepareExpression(BeanQueryRequest<?> request) {
exp.prepareExpression(request);
}
/**
* Based on the expression.
*/
public void queryAutoTuneHash(HashQueryPlanBuilder builder) {
@Override
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(NotExpression.class);
exp.queryAutoTuneHash(builder);
}
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
builder.add(NotExpression.class);
exp.queryPlanHash(request, builder);
exp.queryPlanHash(builder);
}
public int queryBindHash() {
@@ -20,10 +20,12 @@ class NullExpression extends AbstractExpression {
this.notNull = notNull;
}
@Override
public void addBindValues(SpiExpressionRequest request) {
}
@Override
public void addSql(SpiExpressionRequest request) {
String propertyName = getPropertyName();
@@ -42,14 +44,12 @@ class NullExpression extends AbstractExpression {
/**
* Based on notNull flag and the propertyName.
*/
public void queryAutoTuneHash(HashQueryPlanBuilder builder) {
@Override
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(NullExpression.class).add(notNull).add(propName);
}
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
queryAutoTuneHash(builder);
}
@Override
public int queryBindHash() {
return (notNull ? 1 : 0);
}
@@ -1,14 +1,12 @@
package com.avaje.ebeaninternal.server.expression;
import com.avaje.ebean.event.BeanQueryRequest;
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;
class RawExpression implements SpiExpression {
class RawExpression extends NonPrepareExpression {
private static final long serialVersionUID = 7973903141340334606L;
@@ -21,6 +19,7 @@ class RawExpression implements SpiExpression {
this.values = values;
}
@Override
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
}
@@ -30,6 +29,7 @@ class RawExpression implements SpiExpression {
// always ignored
}
@Override
public void addBindValues(SpiExpressionRequest request) {
if (values != null) {
for (int i = 0; i < values.length; i++) {
@@ -38,6 +38,7 @@ class RawExpression implements SpiExpression {
}
}
@Override
public void addSql(SpiExpressionRequest request) {
request.append(sql);
}
@@ -45,14 +46,12 @@ class RawExpression implements SpiExpression {
/**
* Based on the sql.
*/
public void queryAutoTuneHash(HashQueryPlanBuilder builder) {
@Override
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(RawExpression.class).add(sql);
}
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
queryAutoTuneHash(builder);
}
@Override
public int queryBindHash() {
return sql.hashCode();
}
@@ -24,6 +24,7 @@ public class SimpleExpression extends AbstractExpression {
return Op.EQ.equals(type);
}
@Override
public void addBindValues(SpiExpressionRequest request) {
ElPropertyValue prop = getElProp(request);
@@ -50,6 +51,7 @@ public class SimpleExpression extends AbstractExpression {
request.addBindValue(value);
}
@Override
public void addSql(SpiExpressionRequest request) {
String propertyName = getPropertyName();
@@ -72,15 +74,13 @@ public class SimpleExpression extends AbstractExpression {
/**
* Based on the type and propertyName.
*/
public void queryAutoTuneHash(HashQueryPlanBuilder builder) {
@Override
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(SimpleExpression.class).add(propName).add(type.name());
builder.bind(1);
}
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
queryAutoTuneHash(builder);
}
@Override
public int queryBindHash() {
return value.hashCode();
}
@@ -759,7 +759,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
/**
* Calculate the query hash for either AutoTune query tuning or Query Plan caching.
*/
private HashQueryPlan calculateHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
private HashQueryPlan calculateHash(HashQueryPlanBuilder builder) {
// exclude bind values and things unrelated to the sql being generated
@@ -780,31 +780,17 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
builder.add(rootTableAlias);
if (detail != null) {
detail.queryPlanHash(request, builder);
detail.queryPlanHash(builder);
}
if (bindParams != null) {
bindParams.buildQueryPlanHash(builder);
}
if (request == null) {
// for AutoTune...
builder.add(true);
if (whereExpressions != null) {
whereExpressions.queryAutoTuneHash(builder);
}
if (havingExpressions != null) {
havingExpressions.queryAutoTuneHash(builder);
}
} else {
// for query plan...
builder.add(false);
if (whereExpressions != null) {
whereExpressions.queryPlanHash(request, builder);
}
if (havingExpressions != null) {
havingExpressions.queryPlanHash(request, builder);
}
if (whereExpressions != null) {
whereExpressions.queryPlanHash(builder);
}
if (havingExpressions != null) {
havingExpressions.queryPlanHash(builder);
}
return builder.build();
@@ -816,7 +802,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
*/
public HashQueryPlan queryAutoTuneHash(HashQueryPlanBuilder builder) {
return calculateHash(null, builder);
return calculateHash(builder);
}
/**
@@ -830,10 +816,25 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
*/
public HashQueryPlan queryPlanHash(BeanQueryRequest<?> request) {
queryPlanHash = calculateHash(request, null);
prepareExpressions(request);
queryPlanHash = calculateHash(null);
return queryPlanHash;
}
/**
* Prepare the expressions (compile sub-queries etc).
*/
private void prepareExpressions(BeanQueryRequest<?> request) {
if (whereExpressions != null) {
whereExpressions.prepareExpression(request);
}
if (havingExpressions != null) {
havingExpressions.prepareExpression(request);
}
}
/**
* Calculate a hash based on the bind values used in the query.
* <p>
@@ -1,5 +1,14 @@
package com.avaje.ebeaninternal.server.querydefn;
import com.avaje.ebean.FetchConfig;
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssoc;
import com.avaje.ebeaninternal.server.el.ElPropertyDeploy;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
import com.avaje.ebeaninternal.server.query.SplitName;
import javax.persistence.PersistenceException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
@@ -11,17 +20,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.PersistenceException;
import com.avaje.ebean.FetchConfig;
import com.avaje.ebean.event.BeanQueryRequest;
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssoc;
import com.avaje.ebeaninternal.server.el.ElPropertyDeploy;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
import com.avaje.ebeaninternal.server.query.SplitName;
/**
* Represents the internal structure of an Object Relational query.
* <p>
@@ -65,17 +63,17 @@ public class OrmQueryDetail implements Serializable {
/**
* Calculate the hash for the query plan.
*/
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
public void queryPlanHash(HashQueryPlanBuilder builder) {
if (baseProps == null) {
builder.add(false);
} else {
builder.add(true);
baseProps.queryPlanHash(request, builder);
baseProps.queryPlanHash(builder);
}
if (fetchPaths != null) {
for (OrmQueryProperties p : fetchPaths.values()) {
p.queryPlanHash(request, builder);
p.queryPlanHash(builder);
}
}
}
@@ -1,18 +1,9 @@
package com.avaje.ebeaninternal.server.querydefn;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import com.avaje.ebean.ExpressionFactory;
import com.avaje.ebean.FetchConfig;
import com.avaje.ebean.OrderBy;
import com.avaje.ebean.Query;
import com.avaje.ebean.event.BeanQueryRequest;
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
import com.avaje.ebeaninternal.api.SpiExpression;
import com.avaje.ebeaninternal.api.SpiExpressionFactory;
@@ -23,6 +14,14 @@ import com.avaje.ebeaninternal.server.lib.util.StringHelper;
import com.avaje.ebeaninternal.server.query.SplitName;
import com.avaje.ebeaninternal.util.FilterExpressionList;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/**
* Represents the Properties of an Object Relational query.
*/
@@ -334,7 +333,7 @@ public class OrmQueryProperties implements Serializable {
* Calculate the query plan hash.
*/
@SuppressWarnings("unchecked")
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(path);
if (properties != null) {
@@ -344,7 +343,7 @@ public class OrmQueryProperties implements Serializable {
}
builder.add(filterMany != null);
if (filterMany != null) {
filterMany.queryPlanHash(request, builder);
filterMany.queryPlanHash(builder);
}
builder.add(lazyFetchBatch);
builder.add(queryFetchBatch);
@@ -349,15 +349,10 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
return request.getBindValues();
}
/**
* Calculate a hash based on the expressions but excluding the actual bind
* values.
*/
public void queryAutoTuneHash(HashQueryPlanBuilder builder) {
builder.add(DefaultExpressionList.class);
@Override
public void prepareExpression(BeanQueryRequest<?> request) {
for (int i = 0, size = list.size(); i < size; i++) {
SpiExpression expression = list.get(i);
expression.queryAutoTuneHash(builder);
list.get(i).prepareExpression(request);
}
}
@@ -366,11 +361,10 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
* values.
*/
@Override
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(DefaultExpressionList.class);
for (int i = 0, size = list.size(); i < size; i++) {
SpiExpression expression = list.get(i);
expression.queryPlanHash(request, builder);
list.get(i).queryPlanHash(builder);
}
}
@@ -380,8 +374,7 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
public int queryBindHash() {
int hash = DefaultExpressionList.class.getName().hashCode();
for (int i = 0, size = list.size(); i < size; i++) {
SpiExpression expression = list.get(i);
hash = hash * 31 + expression.queryBindHash();
hash = hash * 31 + list.get(i).queryBindHash();
}
return hash;
}