diff --git a/src/main/java/com/avaje/ebean/DRawSqlParser.java b/src/main/java/com/avaje/ebean/DRawSqlParser.java
index 4353403d7..33622f356 100644
--- a/src/main/java/com/avaje/ebean/DRawSqlParser.java
+++ b/src/main/java/com/avaje/ebean/DRawSqlParser.java
@@ -71,7 +71,7 @@ class DRawSqlParser {
preFrom = trimSelectKeyword(preFrom);
- return new Sql(sql.hashCode(), preFrom, preWhere, whereExprAnd, preHaving, havingExprAnd, orderByPrefix, orderBySql, (distinctPos > -1));
+ return new Sql(sql, preFrom, preWhere, whereExprAnd, preHaving, havingExprAnd, orderByPrefix, orderBySql, (distinctPos > -1));
}
/**
diff --git a/src/main/java/com/avaje/ebean/FetchConfig.java b/src/main/java/com/avaje/ebean/FetchConfig.java
index b885ce3ff..bf2904531 100644
--- a/src/main/java/com/avaje/ebean/FetchConfig.java
+++ b/src/main/java/com/avaje/ebean/FetchConfig.java
@@ -249,4 +249,22 @@ public class FetchConfig implements Serializable {
return queryAll;
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ FetchConfig that = (FetchConfig) o;
+ if (lazyBatchSize != that.lazyBatchSize) return false;
+ if (queryBatchSize != that.queryBatchSize) return false;
+ return queryAll == that.queryAll;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = lazyBatchSize;
+ result = 92821 * result + queryBatchSize;
+ result = 92821 * result + (queryAll ? 1 : 0);
+ return result;
+ }
}
diff --git a/src/main/java/com/avaje/ebean/RawSql.java b/src/main/java/com/avaje/ebean/RawSql.java
index 51760d84f..048532af9 100644
--- a/src/main/java/com/avaje/ebean/RawSql.java
+++ b/src/main/java/com/avaje/ebean/RawSql.java
@@ -206,6 +206,14 @@ public final class RawSql implements Serializable {
return sql;
}
+ /**
+ * Return the key;
+ */
+ public Key getKey() {
+ boolean parsed = sql != null && sql.parsed;
+ String unParsedSql = (sql == null) ? "" : sql.unparsedSql;
+ return new Key(parsed, unParsedSql, columnMapping);
+ }
/**
* Return the resultSet if this is a ResultSet based RawSql.
@@ -221,16 +229,6 @@ public final class RawSql implements Serializable {
return columnMapping;
}
- /**
- * Return the hash for this query.
- */
- public int queryHash() {
- if (resultSet != null) {
- return 31 * columnMapping.queryHash();
- }
- return 31 * sql.queryHash() + columnMapping.queryHash();
- }
-
/**
* Represents the sql part of the query. For parsed RawSql the sql is broken
* up so that Ebean can insert extra WHERE and HAVING expressions into the
@@ -260,13 +258,10 @@ public final class RawSql implements Serializable {
private final boolean distinct;
- private final int queryHashCode;
-
/**
* Construct for unparsed SQL.
*/
protected Sql(String unparsedSql) {
- this.queryHashCode = unparsedSql.hashCode();
this.parsed = false;
this.unparsedSql = unparsedSql;
this.preFrom = null;
@@ -282,12 +277,11 @@ public final class RawSql implements Serializable {
/**
* Construct for parsed SQL.
*/
- protected Sql(int queryHashCode, String preFrom, String preWhere, boolean andWhereExpr,
+ protected Sql(String unparsedSql, String preFrom, String preWhere, boolean andWhereExpr,
String preHaving, boolean andHavingExpr, String orderByPrefix, String orderBy, boolean distinct) {
- this.queryHashCode = queryHashCode;
+ this.unparsedSql = unparsedSql;
this.parsed = true;
- this.unparsedSql = null;
this.preFrom = preFrom;
this.preHaving = preHaving;
this.preWhere = preWhere;
@@ -298,13 +292,6 @@ public final class RawSql implements Serializable {
this.distinct = distinct;
}
- /**
- * Return a hash for this query.
- */
- public int queryHash() {
- return queryHashCode;
- }
-
public String toString() {
if (!parsed) {
return "unparsed[" + unparsedSql + "]";
@@ -406,13 +393,10 @@ public final class RawSql implements Serializable {
private final boolean immutable;
- private final int queryHashCode;
-
/**
* Construct from parsed sql where the columns have been identified.
*/
protected ColumnMapping(List
- * This is so the LoadBeanContext or LoadManyContext use the
- * defined query for +query and +lazy execution.
- *
diff --git a/src/main/java/com/avaje/ebeaninternal/api/SpiExpression.java b/src/main/java/com/avaje/ebeaninternal/api/SpiExpression.java
index 28cdf61c5..bacd508de 100644
--- a/src/main/java/com/avaje/ebeaninternal/api/SpiExpression.java
+++ b/src/main/java/com/avaje/ebeaninternal/api/SpiExpression.java
@@ -17,32 +17,36 @@ public interface SpiExpression extends Expression {
*
* That is, if the hash changes then the query will be considered different
* from an AutoTune perspective and get different tuning.
*
- * This is used where queries are the same except for the bind values, in which
- * case the query execution plan can be reused.
- *
@@ -61,7 +65,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.
*/
@@ -71,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();
+
}
diff --git a/src/main/java/com/avaje/ebeaninternal/api/SpiExpressionList.java b/src/main/java/com/avaje/ebeaninternal/api/SpiExpressionList.java
index 1cacf0a45..de075203c 100644
--- a/src/main/java/com/avaje/ebeaninternal/api/SpiExpressionList.java
+++ b/src/main/java/com/avaje/ebeaninternal/api/SpiExpressionList.java
@@ -1,17 +1,13 @@
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.
*/
-public interface SpiExpressionList
- * Predicates on Many properties require an extra independent join clause.
- *
- * The list of expressions are evaluated in order building a sql statement
- * with bind parameters.
- *
- * Expressions are evaluated in order and all the resulting bind values are
- * returned as a List.
- *
- * After deserialisation so that it can be further modified. - *
- */ - @Override - public void setExpressionFactory(ExpressionFactory expr) { - this.expr = expr; - } - /** * Return a copy of the expression list. *
@@ -88,6 +81,14 @@ public class DefaultExpressionList
- * The parts of the secondary queries are removed and used
- * by LoadBeanContext/LoadManyContext to build the appropriate
- * queries.
- *
@@ -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();
}
/**
diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryPlanStats.java b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryPlanStats.java
index 31636a05e..6196867ac 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryPlanStats.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryPlanStats.java
@@ -233,7 +233,7 @@ public final class CQueryPlanStats {
@Override
public String getQueryPlanHash() {
- return queryPlan.getHash().toString();
+ return queryPlan.getPlanKey().toString();
}
@Override
diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryPredicates.java b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryPredicates.java
index e3570defb..c42ec239f 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryPredicates.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryPredicates.java
@@ -1,16 +1,6 @@
package com.avaje.ebeaninternal.server.query;
-import java.sql.SQLException;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
import com.avaje.ebean.RawSql;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import com.avaje.ebeaninternal.api.BindParams;
import com.avaje.ebeaninternal.api.BindParams.OrderedList;
import com.avaje.ebeaninternal.api.SpiExpressionList;
@@ -23,7 +13,15 @@ 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;
+
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
/**
* Compile Query Predicates.
@@ -465,7 +463,7 @@ public class CQueryPredicates {
/**
* Return the bind values for the where expression.
*/
- public ArrayList
- * This can used to enable the caching and reuse of a 'query plan'.
- *
- * This is calculated AFTER AutoTune query tuning has occurred.
- *
@@ -45,9 +42,7 @@ public class OrmQueryDetail implements Serializable {
/**
* Contains the fetch/lazy/query joins and their properties.
*/
- private LinkedHashMap
- * This can include the +query and +lazy type hints.
- *
@@ -399,7 +357,7 @@ public class OrmQueryProperties implements Serializable {
return included;
}
- LinkedHashSet