mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#566 - Refactor internals - Initial tidy on OrmQueryDetail and OrmQueryDetailProperties
This commit is contained in:
@@ -92,7 +92,7 @@ public class PathProperties {
|
||||
/**
|
||||
* Get the properties for a given path.
|
||||
*/
|
||||
public Set<String> get(String path) {
|
||||
public LinkedHashSet<String> get(String path) {
|
||||
Props props = pathMap.get(path);
|
||||
return props == null ? null : props.getProperties();
|
||||
}
|
||||
@@ -109,7 +109,7 @@ public class PathProperties {
|
||||
/**
|
||||
* Set the properties for a given path.
|
||||
*/
|
||||
public void put(String path, Set<String> properties) {
|
||||
public void put(String path, LinkedHashSet<String> properties) {
|
||||
pathMap.put(path, new Props(this, null, path, properties));
|
||||
}
|
||||
|
||||
@@ -160,9 +160,9 @@ public class PathProperties {
|
||||
private final String parentPath;
|
||||
private final String path;
|
||||
|
||||
private final Set<String> propSet;
|
||||
private final LinkedHashSet<String> propSet;
|
||||
|
||||
private Props(PathProperties owner, String parentPath, String path, Set<String> propSet) {
|
||||
private Props(PathProperties owner, String parentPath, String path, LinkedHashSet<String> propSet) {
|
||||
this.owner = owner;
|
||||
this.path = path;
|
||||
this.parentPath = parentPath;
|
||||
@@ -195,7 +195,7 @@ public class PathProperties {
|
||||
/**
|
||||
* Return the properties for this property set.
|
||||
*/
|
||||
public Set<String> getProperties() {
|
||||
public LinkedHashSet<String> getProperties() {
|
||||
return propSet;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.avaje.ebeaninternal.api;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Used to build HashQueryPlan instances.
|
||||
*/
|
||||
@@ -33,6 +35,21 @@ public class HashQueryPlanBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the set with order being important.
|
||||
*/
|
||||
public HashQueryPlanBuilder addOrdered(Set<?> set) {
|
||||
if (set == null) {
|
||||
add(false);
|
||||
} else {
|
||||
add(true);
|
||||
for (Object o : set) {
|
||||
add(o);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an integer to the hash calculation.
|
||||
*/
|
||||
|
||||
@@ -1038,7 +1038,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return findId(query, t);
|
||||
}
|
||||
|
||||
private <T> SpiOrmQueryRequest<T> createQueryRequest(Type type, Query<T> query, Transaction t) {
|
||||
<T> SpiOrmQueryRequest<T> createQueryRequest(Type type, Query<T> query, Transaction t) {
|
||||
|
||||
SpiQuery<T> spiQuery = (SpiQuery<T>) query;
|
||||
spiQuery.setType(type);
|
||||
|
||||
@@ -73,9 +73,9 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
@@ -347,7 +347,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo, SpiBeanType<T> {
|
||||
private final BeanDescriptorJsonHelp<T> jsonHelp;
|
||||
|
||||
private final String defaultSelectClause;
|
||||
private final Set<String> defaultSelectClauseSet;
|
||||
private final LinkedHashSet<String> defaultSelectClauseSet;
|
||||
|
||||
private SpiEbeanServer ebeanServer;
|
||||
|
||||
@@ -856,7 +856,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo, SpiBeanType<T> {
|
||||
/**
|
||||
* Return the default select clause already parsed into an ordered Set.
|
||||
*/
|
||||
public Set<String> getDefaultSelectClauseSet() {
|
||||
public LinkedHashSet<String> getDefaultSelectClauseSet() {
|
||||
return defaultSelectClauseSet;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Describes Beans including their deployment information.
|
||||
@@ -763,7 +762,7 @@ public class DeployBeanDescriptor<T> {
|
||||
/**
|
||||
* Parse the include separating by comma or semicolon.
|
||||
*/
|
||||
public Set<String> parseDefaultSelectClause(String rawList) {
|
||||
public LinkedHashSet<String> parseDefaultSelectClause(String rawList) {
|
||||
|
||||
if (rawList == null) {
|
||||
return null;
|
||||
@@ -780,7 +779,7 @@ public class DeployBeanDescriptor<T> {
|
||||
set.add(temp);
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableSet(set);
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Utility to help isSame methods.
|
||||
*/
|
||||
@@ -19,6 +22,26 @@ public class Same {
|
||||
return v1 == null ? v2 == null : v1.equals(v2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if both collections are the same by value and order is taken into account.
|
||||
*/
|
||||
public static boolean sameByValue(Collection<?> v1, Collection<?> v2) {
|
||||
if (v1 == null) {
|
||||
return v2 == null;
|
||||
}
|
||||
if (v2 == null || v1.size() != v2.size()) {
|
||||
return false;
|
||||
}
|
||||
Iterator<?> thisIt = v1.iterator();
|
||||
Iterator<?> thatIt = v2.iterator();
|
||||
while (thisIt.hasNext() && thatIt.hasNext()) {
|
||||
if (!thisIt.next().equals(thatIt.next())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Null safe check by sameByValue or sameByNull based on byValue.
|
||||
*/
|
||||
|
||||
@@ -25,7 +25,6 @@ import com.avaje.ebeaninternal.server.querydefn.OrmQueryLimitRequest;
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Generates the SQL SELECT statements taking into account the physical
|
||||
@@ -354,8 +353,7 @@ public class CQueryBuilder {
|
||||
|
||||
// transfer PathProperties into OrmQueryDetail
|
||||
for (String path : pathProps.getPaths()) {
|
||||
Set<String> props = pathProps.get(path);
|
||||
detail.getChunk(path, true).setDefaultProperties(null, props);
|
||||
detail.getChunk(path, true).setDefaultProperties(null, pathProps.get(path));
|
||||
}
|
||||
|
||||
// check if @Id property included in RawSql
|
||||
|
||||
@@ -7,6 +7,7 @@ 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 org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.io.Serializable;
|
||||
@@ -18,7 +19,6 @@ import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Represents the internal structure of an Object Relational query.
|
||||
@@ -38,6 +38,7 @@ public class OrmQueryDetail implements Serializable {
|
||||
/**
|
||||
* Root level properties.
|
||||
*/
|
||||
@NotNull
|
||||
private OrmQueryProperties baseProps = new OrmQueryProperties();
|
||||
|
||||
/**
|
||||
@@ -60,17 +61,17 @@ public class OrmQueryDetail implements Serializable {
|
||||
return copy;
|
||||
}
|
||||
|
||||
public int queryPlanHash() {
|
||||
HashQueryPlanBuilder builder = new HashQueryPlanBuilder();
|
||||
queryPlanHash(builder);
|
||||
return builder.getPlanHash();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the hash for the query plan.
|
||||
*/
|
||||
public void queryPlanHash(HashQueryPlanBuilder builder) {
|
||||
if (baseProps == null) {
|
||||
builder.add(false);
|
||||
} else {
|
||||
builder.add(true);
|
||||
baseProps.queryPlanHash(builder);
|
||||
}
|
||||
|
||||
baseProps.queryPlanHash(builder);
|
||||
if (fetchPaths != null) {
|
||||
for (OrmQueryProperties p : fetchPaths.values()) {
|
||||
p.queryPlanHash(builder);
|
||||
@@ -79,11 +80,10 @@ public class OrmQueryDetail implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if equal in terms of autoTune (select and fetch).
|
||||
* Return true if the details are the same for query plan purposes.
|
||||
*/
|
||||
public boolean isAutoTuneEqual(OrmQueryDetail otherDetail) {
|
||||
|
||||
if (!isSame(baseProps, otherDetail.baseProps)) {
|
||||
public boolean isSameByPlan(OrmQueryDetail otherDetail) {
|
||||
if (!isSameByPlan(baseProps, otherDetail.baseProps)) {
|
||||
return false;
|
||||
}
|
||||
if (fetchPaths == null) {
|
||||
@@ -92,10 +92,16 @@ public class OrmQueryDetail implements Serializable {
|
||||
if (fetchPaths.size() != otherDetail.fetchPaths.size()) {
|
||||
return false;
|
||||
}
|
||||
Set<Map.Entry<String, OrmQueryProperties>> entries = fetchPaths.entrySet();
|
||||
for (Map.Entry<String, OrmQueryProperties> entry : entries) {
|
||||
OrmQueryProperties chunk = otherDetail.getChunk(entry.getKey(), false);
|
||||
if (!isSame(entry.getValue(), chunk)) {
|
||||
// check with ordering being important
|
||||
Iterator<Map.Entry<String, OrmQueryProperties>> thisIt = fetchPaths.entrySet().iterator();
|
||||
Iterator<Map.Entry<String, OrmQueryProperties>> thatIt = otherDetail.fetchPaths.entrySet().iterator();
|
||||
while (thisIt.hasNext() && thatIt.hasNext()) {
|
||||
Map.Entry<String, OrmQueryProperties> thisEntry = thisIt.next();
|
||||
Map.Entry<String, OrmQueryProperties> thatEntry = thatIt.next();
|
||||
if (!thisEntry.getKey().equals(thatEntry.getKey())) {
|
||||
return false;
|
||||
}
|
||||
if (!thisEntry.getValue().isSameByPlan(thatEntry.getValue())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -103,21 +109,54 @@ public class OrmQueryDetail implements Serializable {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isSame(OrmQueryProperties p1, OrmQueryProperties p2) {
|
||||
if (p1 == null) {
|
||||
return p2 == null;
|
||||
/**
|
||||
* Return true if equal in terms of autoTune (select and fetch without property ordering).
|
||||
*/
|
||||
public boolean isAutoTuneEqual(OrmQueryDetail otherDetail) {
|
||||
|
||||
if (!isSameByAutoTune(baseProps, otherDetail.baseProps)) {
|
||||
return false;
|
||||
}
|
||||
return p1.isSame(p2);
|
||||
if (fetchPaths == null) {
|
||||
return otherDetail.fetchPaths == null;
|
||||
}
|
||||
if (fetchPaths.size() != otherDetail.fetchPaths.size()) {
|
||||
return false;
|
||||
}
|
||||
// check without regard to ordering
|
||||
for (Map.Entry<String, OrmQueryProperties> entry : fetchPaths.entrySet()) {
|
||||
OrmQueryProperties chunk = otherDetail.getChunk(entry.getKey(), false);
|
||||
if (!isSameByAutoTune(entry.getValue(), chunk)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isSameByAutoTune(OrmQueryProperties p1, OrmQueryProperties p2) {
|
||||
return p1 == null ? p2 == null : p1.isSameByAutoTune(p2);
|
||||
}
|
||||
|
||||
private boolean isSameByPlan(OrmQueryProperties p1, OrmQueryProperties p2) {
|
||||
return p1 == null ? p2 == null : p1.isSameByPlan(p2);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return asString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the detail in string form.
|
||||
*/
|
||||
public String asString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (baseProps != null) {
|
||||
sb.append("select ").append(baseProps);
|
||||
if (!baseProps.isEmpty()) {
|
||||
baseProps.append("select ", sb);
|
||||
}
|
||||
if (fetchPaths != null) {
|
||||
for (OrmQueryProperties join : fetchPaths.values()) {
|
||||
sb.append(" fetch ").append(join);
|
||||
join.append(" fetch ", sb);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
@@ -135,7 +174,7 @@ public class OrmQueryDetail implements Serializable {
|
||||
}
|
||||
|
||||
public boolean containsProperty(String property) {
|
||||
return baseProps == null || baseProps.isIncluded(property);
|
||||
return baseProps.isIncluded(property);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -399,9 +438,6 @@ public class OrmQueryDetail implements Serializable {
|
||||
public void setDefaultSelectClause(BeanDescriptor<?> desc) {
|
||||
|
||||
if (desc.hasDefaultSelectClause() && !hasSelectClause()) {
|
||||
if (baseProps == null) {
|
||||
baseProps = new OrmQueryProperties();
|
||||
}
|
||||
baseProps.setDefaultProperties(desc.getDefaultSelectClause(), desc.getDefaultSelectClauseSet());
|
||||
}
|
||||
|
||||
@@ -417,14 +453,14 @@ public class OrmQueryDetail implements Serializable {
|
||||
}
|
||||
|
||||
public boolean hasSelectClause() {
|
||||
return (baseProps != null && baseProps.hasSelectClause());
|
||||
return (baseProps.hasSelectClause());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the query detail has neither select properties specified or any joins defined.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return fetchPaths.isEmpty() && (baseProps == null || !baseProps.hasProperties());
|
||||
return fetchPaths.isEmpty() && (!baseProps.hasProperties());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,6 +29,8 @@ public class OrmQueryDetailParser {
|
||||
|
||||
public OrmQueryDetail parse() throws PersistenceException {
|
||||
|
||||
if (parser.isEmpty()) return detail;
|
||||
|
||||
parser.nextWord();
|
||||
processInitial();
|
||||
return detail;
|
||||
@@ -155,7 +157,7 @@ public class OrmQueryDetailParser {
|
||||
private void readSelect() {
|
||||
String path = null;
|
||||
String props = parser.nextWord();
|
||||
if (props.startsWith("(")) {
|
||||
if (props != null && props.startsWith("(")) {
|
||||
props = props.substring(1, props.length() - 1);
|
||||
OrmQueryProperties base = new OrmQueryProperties(path, props);
|
||||
detail.setBase(base);
|
||||
|
||||
@@ -10,13 +10,12 @@ import com.avaje.ebeaninternal.api.SpiExpressionFactory;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionList;
|
||||
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.server.expression.FilterExpressionList;
|
||||
import com.avaje.ebeaninternal.server.expression.Same;
|
||||
import com.avaje.ebeaninternal.server.query.SplitName;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
@@ -32,8 +31,7 @@ public class OrmQueryProperties implements Serializable {
|
||||
private String parentPath;
|
||||
private String path;
|
||||
|
||||
private String properties;
|
||||
|
||||
private String rawProperties;
|
||||
private String trimmedProperties;
|
||||
|
||||
/**
|
||||
@@ -57,7 +55,7 @@ public class OrmQueryProperties implements Serializable {
|
||||
* Note this SHOULD be a LinkedHashSet to preserve order of the properties. This is to make using
|
||||
* SqlSelect easier with predictable property/column ordering.
|
||||
*/
|
||||
private Set<String> included;
|
||||
private LinkedHashSet<String> included;
|
||||
|
||||
/**
|
||||
* Included bean joins.
|
||||
@@ -92,8 +90,10 @@ public class OrmQueryProperties implements Serializable {
|
||||
this.parentPath = SplitName.parent(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct for root so path (and parentPath) are null.
|
||||
*/
|
||||
public OrmQueryProperties() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,25 +137,17 @@ public class OrmQueryProperties implements Serializable {
|
||||
* This can include the +query and +lazy type hints.
|
||||
* </p>
|
||||
*/
|
||||
public void setProperties(String properties) {
|
||||
this.properties = properties;
|
||||
this.trimmedProperties = properties;
|
||||
parseProperties();
|
||||
public void setProperties(String rawProperties) {
|
||||
|
||||
if (!isAllProperties()) {
|
||||
Set<String> parsed = parseIncluded(trimmedProperties);
|
||||
if (parsed.contains("*")) {
|
||||
this.included = null;
|
||||
} else {
|
||||
this.included = parsed;
|
||||
}
|
||||
} else {
|
||||
this.included = null;
|
||||
}
|
||||
}
|
||||
OrmQueryPropertiesParser.Response response = OrmQueryPropertiesParser.parse(rawProperties);
|
||||
|
||||
private boolean isAllProperties() {
|
||||
return (trimmedProperties == null) || (trimmedProperties.length() == 0) || "*".equals(trimmedProperties);
|
||||
this.rawProperties = rawProperties;
|
||||
this.trimmedProperties = response.properties;
|
||||
this.included = response.included;
|
||||
this.lazyFetchBatch = response.lazyFetchBatch;
|
||||
this.queryFetchBatch = response.queryFetchBatch;
|
||||
this.cache = response.cache;
|
||||
this.readOnly = response.readOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -204,8 +196,8 @@ public class OrmQueryProperties implements Serializable {
|
||||
/**
|
||||
* Set the properties from deployment default FetchTypes.
|
||||
*/
|
||||
public void setDefaultProperties(String properties, Set<String> included) {
|
||||
this.properties = properties;
|
||||
public void setDefaultProperties(String properties, LinkedHashSet<String> included) {
|
||||
this.rawProperties = properties;
|
||||
this.trimmedProperties = properties;
|
||||
this.included = included;
|
||||
}
|
||||
@@ -215,7 +207,7 @@ public class OrmQueryProperties implements Serializable {
|
||||
*/
|
||||
public void setTunedProperties(OrmQueryProperties tunedProperties) {
|
||||
if (tunedProperties.hasProperties()) {
|
||||
this.properties = tunedProperties.properties;
|
||||
this.rawProperties = tunedProperties.rawProperties;
|
||||
this.trimmedProperties = tunedProperties.trimmedProperties;
|
||||
this.included = tunedProperties.included;
|
||||
this.queryFetchBatch = Math.max(queryFetchBatch, tunedProperties.queryFetchBatch);
|
||||
@@ -264,7 +256,7 @@ public class OrmQueryProperties implements Serializable {
|
||||
OrmQueryProperties copy = new OrmQueryProperties();
|
||||
copy.parentPath = parentPath;
|
||||
copy.path = path;
|
||||
copy.properties = properties;
|
||||
copy.rawProperties = rawProperties;
|
||||
copy.trimmedProperties = trimmedProperties;
|
||||
copy.cache = cache;
|
||||
copy.readOnly = readOnly;
|
||||
@@ -273,7 +265,7 @@ public class OrmQueryProperties implements Serializable {
|
||||
copy.lazyFetchBatch = lazyFetchBatch;
|
||||
copy.filterMany = filterMany;
|
||||
if (included != null) {
|
||||
copy.included = new HashSet<String>(included);
|
||||
copy.included = new LinkedHashSet<String>(included);
|
||||
}
|
||||
if (includedBeanJoin != null) {
|
||||
copy.includedBeanJoin = new HashSet<String>(includedBeanJoin);
|
||||
@@ -290,17 +282,28 @@ public class OrmQueryProperties implements Serializable {
|
||||
return included != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the properties and configuration are empty.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return rawProperties == null || rawProperties.isEmpty();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String s = "";
|
||||
StringBuilder sb = new StringBuilder(40);
|
||||
append("", sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String append(String prefix, StringBuilder sb) {
|
||||
sb.append(prefix);
|
||||
if (path != null) {
|
||||
s += path + " ";
|
||||
sb.append(path).append(" ");
|
||||
}
|
||||
if (properties != null) {
|
||||
s += "(" + properties + ") ";
|
||||
} else if (included != null) {
|
||||
s += "(" + included + ") ";
|
||||
if (!isEmpty()) {
|
||||
sb.append("(").append(rawProperties).append(") ");
|
||||
}
|
||||
return s;
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean isChild(OrmQueryProperties possibleChild) {
|
||||
@@ -318,35 +321,22 @@ public class OrmQueryProperties implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the query plan hash.
|
||||
* Return the raw properties.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void queryPlanHash(HashQueryPlanBuilder builder) {
|
||||
|
||||
builder.add(path);
|
||||
if (properties != null) {
|
||||
builder.add(properties);
|
||||
} else {
|
||||
builder.add(included);
|
||||
}
|
||||
builder.add(filterMany != null);
|
||||
if (filterMany != null) {
|
||||
filterMany.queryPlanHash(builder);
|
||||
}
|
||||
builder.add(lazyFetchBatch);
|
||||
builder.add(queryFetchBatch);
|
||||
builder.add(queryFetchAll);
|
||||
}
|
||||
|
||||
public String getProperties() {
|
||||
return properties;
|
||||
return rawProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this has properties.
|
||||
* Return true if this has properties. Returning false means this part of the
|
||||
* path is a partial object.
|
||||
*/
|
||||
public boolean hasProperties() {
|
||||
return properties != null || included != null;
|
||||
return included != null;
|
||||
}
|
||||
|
||||
public boolean allProperties() {
|
||||
return included == null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -370,10 +360,6 @@ public class OrmQueryProperties implements Serializable {
|
||||
includedBeanJoin.add(propertyName);
|
||||
}
|
||||
|
||||
public boolean allProperties() {
|
||||
return included == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This excludes the bean joined properties.
|
||||
* <p>
|
||||
@@ -386,7 +372,7 @@ public class OrmQueryProperties implements Serializable {
|
||||
return included;
|
||||
}
|
||||
|
||||
LinkedHashSet<String> temp = new LinkedHashSet<String>(secondaryQueryJoins.size() + included.size());
|
||||
LinkedHashSet<String> temp = new LinkedHashSet<String>(2 * (secondaryQueryJoins.size() + included.size()));
|
||||
temp.addAll(included);
|
||||
temp.addAll(secondaryQueryJoins);
|
||||
return temp;
|
||||
@@ -400,30 +386,10 @@ public class OrmQueryProperties implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the properties including the bean joins. This is the set that will be used by
|
||||
* EntityBeanIntercept to determine if a property needs to be lazy loaded.
|
||||
* Return the property set.
|
||||
*/
|
||||
public Set<String> getAllIncludedProperties() {
|
||||
|
||||
if (included == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (includedBeanJoin == null && secondaryQueryJoins == null) {
|
||||
return new LinkedHashSet<String>(included);
|
||||
}
|
||||
|
||||
LinkedHashSet<String> s = new LinkedHashSet<String>(2 * (included.size() + 5));
|
||||
if (included != null) {
|
||||
s.addAll(included);
|
||||
}
|
||||
if (includedBeanJoin != null) {
|
||||
s.addAll(includedBeanJoin);
|
||||
}
|
||||
if (secondaryQueryJoins != null) {
|
||||
s.addAll(secondaryQueryJoins);
|
||||
}
|
||||
return s;
|
||||
protected Set<String> getIncluded() {
|
||||
return included;
|
||||
}
|
||||
|
||||
public boolean isIncluded(String propName) {
|
||||
@@ -480,96 +446,47 @@ public class OrmQueryProperties implements Serializable {
|
||||
return path;
|
||||
}
|
||||
|
||||
private void parseProperties() {
|
||||
if (trimmedProperties == null) {
|
||||
return;
|
||||
}
|
||||
int pos = trimmedProperties.indexOf("+readonly");
|
||||
if (pos > -1) {
|
||||
trimmedProperties = StringHelper.replaceString(trimmedProperties, "+readonly", "");
|
||||
this.readOnly = true;
|
||||
}
|
||||
pos = trimmedProperties.indexOf("+cache");
|
||||
if (pos > -1) {
|
||||
trimmedProperties = StringHelper.replaceString(trimmedProperties, "+cache", "");
|
||||
this.cache = true;
|
||||
}
|
||||
pos = trimmedProperties.indexOf("+query");
|
||||
if (pos > -1) {
|
||||
queryFetchBatch = parseBatchHint(pos, "+query");
|
||||
}
|
||||
pos = trimmedProperties.indexOf("+lazy");
|
||||
if (pos > -1) {
|
||||
lazyFetchBatch = parseBatchHint(pos, "+lazy");
|
||||
}
|
||||
|
||||
trimmedProperties = trimmedProperties.trim();
|
||||
while (trimmedProperties.startsWith(",")) {
|
||||
trimmedProperties = trimmedProperties.substring(1).trim();
|
||||
}
|
||||
}
|
||||
|
||||
private int parseBatchHint(int pos, String option) {
|
||||
|
||||
int startPos = pos + option.length();
|
||||
|
||||
int endPos = findEndPos(startPos, trimmedProperties);
|
||||
if (endPos == -1) {
|
||||
trimmedProperties = StringHelper.replaceString(trimmedProperties, option, "");
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
|
||||
String batchParam = trimmedProperties.substring(startPos + 1, endPos);
|
||||
|
||||
if (endPos + 1 >= trimmedProperties.length()) {
|
||||
trimmedProperties = trimmedProperties.substring(0, pos);
|
||||
} else {
|
||||
trimmedProperties = trimmedProperties.substring(0, pos) + trimmedProperties.substring(endPos + 1);
|
||||
}
|
||||
return Integer.parseInt(batchParam);
|
||||
}
|
||||
}
|
||||
|
||||
private int findEndPos(int pos, String props) {
|
||||
|
||||
if (pos < props.length()) {
|
||||
if (props.charAt(pos) == '(') {
|
||||
int endPara = props.indexOf(')', pos + 1);
|
||||
if (endPara == -1) {
|
||||
String m = "Error could not find ')' in " + props + " after position " + pos;
|
||||
throw new RuntimeException(m);
|
||||
}
|
||||
return endPara;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the include separating by comma or semicolon.
|
||||
* Return true if the properties are the same for autoTune purposes.
|
||||
*/
|
||||
private static Set<String> parseIncluded(String rawList) {
|
||||
|
||||
String[] res = rawList.split(",");
|
||||
|
||||
LinkedHashSet<String> set = new LinkedHashSet<String>(res.length + 3);
|
||||
|
||||
String temp;
|
||||
for (int i = 0; i < res.length; i++) {
|
||||
temp = res[i].trim();
|
||||
if (temp.length() > 0) {
|
||||
set.add(temp);
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.unmodifiableSet(set);
|
||||
}
|
||||
|
||||
public boolean isSame(OrmQueryProperties p2) {
|
||||
public boolean isSameByAutoTune(OrmQueryProperties p2) {
|
||||
if (included == null) {
|
||||
return p2.included == null;
|
||||
}
|
||||
return included.equals(p2.included);
|
||||
}
|
||||
|
||||
/**
|
||||
* Properties are the same for query plan purposes.
|
||||
*/
|
||||
public boolean isSameByPlan(OrmQueryProperties p2) {
|
||||
|
||||
if (!Same.sameByValue(secondaryQueryJoins, p2.secondaryQueryJoins)) return false;
|
||||
if (!Same.sameByValue(included, p2.included)) return false;
|
||||
if (!Same.sameByNull(filterMany, p2.filterMany)) return false;
|
||||
if (filterMany != null && !filterMany.isSameByPlan(p2.filterMany)) return false;
|
||||
|
||||
return lazyFetchBatch == p2.lazyFetchBatch
|
||||
&& queryFetchBatch == p2.queryFetchBatch
|
||||
&& queryFetchAll == p2.queryFetchAll;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the query plan hash.
|
||||
*/
|
||||
public void queryPlanHash(HashQueryPlanBuilder builder) {
|
||||
|
||||
builder.add(path);
|
||||
builder.addOrdered(included);
|
||||
builder.add(secondaryQueryJoins);
|
||||
|
||||
builder.add(filterMany != null);
|
||||
if (filterMany != null) {
|
||||
filterMany.queryPlanHash(builder);
|
||||
}
|
||||
builder.add(lazyFetchBatch);
|
||||
builder.add(queryFetchBatch);
|
||||
builder.add(queryFetchAll);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
package com.avaje.ebeaninternal.server.querydefn;
|
||||
|
||||
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
/**
|
||||
* Parses the path properties string.
|
||||
*/
|
||||
public class OrmQueryPropertiesParser {
|
||||
|
||||
private static Response EMPTY = new Response();
|
||||
|
||||
/**
|
||||
* Immutable response of the parsed properties and options.
|
||||
*/
|
||||
public static class Response {
|
||||
|
||||
final boolean readOnly;
|
||||
final boolean cache;
|
||||
final int queryFetchBatch;
|
||||
final int lazyFetchBatch;
|
||||
final String properties;
|
||||
final LinkedHashSet<String> included;
|
||||
|
||||
public Response(boolean readOnly, boolean cache, int queryFetchBatch, int lazyFetchBatch, String properties, LinkedHashSet<String> included) {
|
||||
this.readOnly = readOnly;
|
||||
this.cache = cache;
|
||||
this.queryFetchBatch = queryFetchBatch;
|
||||
this.lazyFetchBatch = lazyFetchBatch;
|
||||
this.properties = properties;
|
||||
this.included = included;
|
||||
}
|
||||
|
||||
public Response() {
|
||||
this.readOnly = false;
|
||||
this.cache = false;
|
||||
this.queryFetchBatch = -1;
|
||||
this.lazyFetchBatch = -1;
|
||||
this.properties = "";
|
||||
this.included = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the path properties string returning the parsed properties and options.
|
||||
* In general it is comma delimited with some special strings like +lazy(20).
|
||||
*/
|
||||
public static Response parse(String rawProperties) {
|
||||
return new OrmQueryPropertiesParser(rawProperties).parse();
|
||||
}
|
||||
|
||||
private String inputProperties;
|
||||
|
||||
private String outputProperties = "";
|
||||
private boolean allProperties;
|
||||
private boolean readOnly;
|
||||
private boolean cache;
|
||||
private int queryFetchBatch = -1;
|
||||
private int lazyFetchBatch = -1;
|
||||
|
||||
private OrmQueryPropertiesParser(String inputProperties) {
|
||||
this.inputProperties = inputProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the raw string properties input.
|
||||
*/
|
||||
private Response parse() {
|
||||
|
||||
if (inputProperties == null || inputProperties.isEmpty()) {
|
||||
return EMPTY;
|
||||
}
|
||||
int pos = inputProperties.indexOf("+readonly");
|
||||
if (pos > -1) {
|
||||
inputProperties = StringHelper.replaceString(inputProperties, "+readonly", "");
|
||||
readOnly = true;
|
||||
}
|
||||
pos = inputProperties.indexOf("+cache");
|
||||
if (pos > -1) {
|
||||
inputProperties = StringHelper.replaceString(inputProperties, "+cache", "");
|
||||
cache = true;
|
||||
}
|
||||
pos = inputProperties.indexOf("+query");
|
||||
if (pos > -1) {
|
||||
queryFetchBatch = parseBatchHint(pos, "+query");
|
||||
}
|
||||
pos = inputProperties.indexOf("+lazy");
|
||||
if (pos > -1) {
|
||||
lazyFetchBatch = parseBatchHint(pos, "+lazy");
|
||||
}
|
||||
|
||||
LinkedHashSet<String> included = parseIncluded();
|
||||
String properties = (allProperties) ? "*" : outputProperties;
|
||||
return new Response(readOnly, cache, queryFetchBatch, lazyFetchBatch, properties, included);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the include separating by comma or semicolon.
|
||||
*/
|
||||
private LinkedHashSet<String> parseIncluded() {
|
||||
|
||||
inputProperties = inputProperties.trim();
|
||||
if (inputProperties.isEmpty()) {
|
||||
// default properties
|
||||
return null;
|
||||
}
|
||||
if (inputProperties.equals("*")) {
|
||||
// explicit all properties
|
||||
allProperties = true;
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] res = inputProperties.split(",");
|
||||
|
||||
StringBuilder sb = new StringBuilder(70);
|
||||
LinkedHashSet<String> propertySet = new LinkedHashSet<String>(res.length * 2);
|
||||
|
||||
int count = 0;
|
||||
String temp;
|
||||
for (int i = 0; i < res.length; i++) {
|
||||
temp = res[i].trim();
|
||||
if (temp.length() > 0) {
|
||||
if (count > 0) {
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append(temp);
|
||||
propertySet.add(temp);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (propertySet.isEmpty()) {
|
||||
// default properties
|
||||
return null;
|
||||
}
|
||||
|
||||
if (propertySet.contains("*")) {
|
||||
// explicit all properties
|
||||
allProperties = true;
|
||||
return null;
|
||||
}
|
||||
|
||||
// partial properties
|
||||
outputProperties = sb.toString();
|
||||
return propertySet;
|
||||
}
|
||||
|
||||
private int parseBatchHint( int pos, String option) {
|
||||
|
||||
int startPos = pos + option.length();
|
||||
int endPos = findEndPos(startPos, inputProperties);
|
||||
if (endPos == -1) {
|
||||
inputProperties = StringHelper.replaceString(inputProperties, option, "");
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
|
||||
String batchParam = inputProperties.substring(startPos + 1, endPos);
|
||||
|
||||
if (endPos + 1 >= inputProperties.length()) {
|
||||
inputProperties = inputProperties.substring(0, pos);
|
||||
} else {
|
||||
inputProperties = inputProperties.substring(0, pos) + inputProperties.substring(endPos + 1);
|
||||
}
|
||||
return Integer.parseInt(batchParam);
|
||||
}
|
||||
}
|
||||
|
||||
private int findEndPos(int pos, String props) {
|
||||
|
||||
if (pos < props.length()) {
|
||||
if (props.charAt(pos) == '(') {
|
||||
int endPara = props.indexOf(')', pos + 1);
|
||||
if (endPara == -1) {
|
||||
throw new RuntimeException("Error could not find ')' in " + props + " after position " + pos);
|
||||
}
|
||||
return endPara;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,10 @@ public class SimpleTextParser {
|
||||
this.eof = oql.length();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return oql.isEmpty();
|
||||
}
|
||||
|
||||
public int getPos() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.FetchConfig;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.server.querydefn.DefaultOrmQuery;
|
||||
import com.avaje.ebeaninternal.server.querydefn.OrmQueryDetail;
|
||||
import com.avaje.tests.model.basic.Order;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
|
||||
public class DefaultServer_createOrmQueryRequestTest extends BaseTestCase {
|
||||
|
||||
static DefaultServer defaultServer = (DefaultServer)Ebean.getDefaultServer();
|
||||
|
||||
Query<Order> query() {
|
||||
return defaultServer.find(Order.class);
|
||||
}
|
||||
|
||||
OrmQueryRequest<Order> queryRequest(Query<Order> query) {
|
||||
return (OrmQueryRequest<Order>)defaultServer.createQueryRequest(SpiQuery.Type.LIST, query, null);
|
||||
}
|
||||
|
||||
OrmQueryDetail detail(Query<Order> query) {
|
||||
return queryRequest(query).getQuery().getDetail();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_empty_then_same() {
|
||||
|
||||
assertSame(detail(query()), detail(query()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void select_all_then_same() {
|
||||
|
||||
assertSame(detail(query().select("*")), detail(query().select("*")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_propertiesInOrder_then_same() {
|
||||
|
||||
assertSame(detail(query().select("id,name")), detail(query().select("id,name")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_propertiesInDifferentOrder_then_different() {
|
||||
|
||||
assertDifferent(detail(query().select("id,name")), detail(query().select("name, id")));
|
||||
|
||||
// but same from autotune perspective
|
||||
assertThat(detail(query().select("id,name")).isAutoTuneEqual(detail(query().select("name, id")))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_additional_fetch_then_different() {
|
||||
|
||||
assertDifferent(detail(query().select("id,name")), detail(query().select("id,name").fetch("details")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_same_fetch_then_same() {
|
||||
|
||||
assertSame(detail(query().select("id,name").fetch("details")), detail(query().select("id,name").fetch("details")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_fetch_order_different_then_different() {
|
||||
|
||||
assertDifferent(detail(query().select("id,name").fetch("details").fetch("customer")),
|
||||
detail(query().select("id,name").fetch("customer").fetch("details")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_extra_queryFetchToMany_then_same() {
|
||||
|
||||
assertDifferent(detail(query().select("id,name").fetch("customer")),
|
||||
detail(query().select("id,name").fetch("customer").fetch("details", new FetchConfig().query())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_extra_queryToOne_fetch_then_different() {
|
||||
|
||||
// with the fetch of customer the foreign key must be added to the root query
|
||||
assertDifferent(detail(query().select("id,name")),
|
||||
detail(query().select("id,name").fetch("customer",new FetchConfig().query())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_additional_fetch_V2_then_different() {
|
||||
|
||||
assertDifferent(detail(query().select("id,name")), detail(query().select("id,name").fetch("customer","id")));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void when_fetchConfig_then_differentPlan() throws Exception {
|
||||
|
||||
DefaultOrmQuery<Order> query1 = (DefaultOrmQuery<Order>)Ebean.find(Order.class)
|
||||
.select("status, shipDate")
|
||||
.fetch("details", "orderQty, unitPrice", new FetchConfig().query())
|
||||
.fetch("details.product", "sku, name");
|
||||
|
||||
|
||||
DefaultOrmQuery<Order> query2 = (DefaultOrmQuery<Order>)Ebean.find(Order.class)
|
||||
.select("status, shipDate")
|
||||
.fetch("details", "orderQty, unitPrice")
|
||||
.fetch("details.product", "sku, name");
|
||||
|
||||
assertDifferent(detail(query1), detail(query2));
|
||||
}
|
||||
|
||||
private void assertSame(OrmQueryDetail detail1, OrmQueryDetail detail2) {
|
||||
assertThat(detail1.isSameByPlan(detail2)).isTrue();
|
||||
assertThat(detail1.queryPlanHash()).isEqualTo(detail2.queryPlanHash());
|
||||
}
|
||||
|
||||
private void assertDifferent(OrmQueryDetail detail1, OrmQueryDetail detail2) {
|
||||
assertThat(detail1.isSameByPlan(detail2)).isFalse();
|
||||
assertThat(detail1.queryPlanHash()).isNotEqualTo(detail2.queryPlanHash());
|
||||
}
|
||||
}
|
||||
@@ -40,24 +40,6 @@ public class DefaultOrmQueryTest {
|
||||
assertThat(q1.queryBindHash()).isEqualTo(q2.queryBindHash());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void when_FetchConfig_then_differentPlan() throws Exception {
|
||||
|
||||
DefaultOrmQuery<?> query1 = (DefaultOrmQuery<?>)Ebean.find(Order.class)
|
||||
.select("status, shipDate")
|
||||
.fetch("details", "orderQty, unitPrice", new FetchConfig().query())
|
||||
.fetch("details.product", "sku, name");
|
||||
|
||||
|
||||
DefaultOrmQuery<?> query2 = (DefaultOrmQuery<?>)Ebean.find(Order.class)
|
||||
.select("status, shipDate")
|
||||
.fetch("details", "orderQty, unitPrice")
|
||||
.fetch("details.product", "sku, name");
|
||||
|
||||
assertThat(query1.createQueryPlanKey()).isNotEqualTo(query2.createQueryPlanKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_diffFirstMaxRows_then_differentPlan() throws Exception {
|
||||
|
||||
|
||||
+35
-38
@@ -5,114 +5,111 @@ import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
|
||||
public class OrmQueryDetailParserTest extends BaseTestCase {
|
||||
|
||||
OrmQueryDetail parse(String query) {
|
||||
return new OrmQueryDetailParser(query).parse();
|
||||
}
|
||||
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void parse_when_nullString() throws Exception {
|
||||
parse(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parse_when_emptyString() throws Exception {
|
||||
assertTrue(parse("").isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseBasic() throws Exception {
|
||||
|
||||
OrmQueryDetail detail = parse("select (id,name)");
|
||||
|
||||
OrmQueryDetail other = new OrmQueryDetail();
|
||||
other.select("id,name");
|
||||
|
||||
OrmQueryProperties root = other.getChunk(null, false);
|
||||
OrmQueryProperties root = detail.getChunk(null, false);
|
||||
assertNull(root.getPath());
|
||||
assertThat(root.getAllIncludedProperties()).contains("id", "name");
|
||||
|
||||
OrmQueryDetailParser p = new OrmQueryDetailParser("select (id,name)");
|
||||
OrmQueryDetail detail = p.parse();
|
||||
|
||||
root = detail.getChunk(null, false);
|
||||
assertNull(root.getPath());
|
||||
assertThat(root.getAllIncludedProperties()).contains("id", "name");
|
||||
assertThat(root.getIncluded()).containsExactly("id", "name");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseEmptySelect() throws Exception {
|
||||
|
||||
OrmQueryDetailParser p = new OrmQueryDetailParser("select fetch customer (email)");
|
||||
OrmQueryDetail detail = p.parse();
|
||||
OrmQueryDetail detail = parse("select fetch customer (email)");
|
||||
|
||||
OrmQueryProperties root = detail.getChunk(null, false);
|
||||
assertNull(root.getPath());
|
||||
assertThat(root.getAllIncludedProperties()).isNull();
|
||||
assertThat(root.getIncluded()).isNull();
|
||||
|
||||
OrmQueryProperties chunk = detail.getChunk("customer", false);
|
||||
assertThat(chunk.getPath()).isEqualTo("customer");
|
||||
assertThat(chunk.getAllIncludedProperties()).contains("email");
|
||||
assertThat(chunk.getIncluded()).contains("email");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseSelectFetch() throws Exception {
|
||||
|
||||
OrmQueryDetailParser p = new OrmQueryDetailParser("select (id,name) fetch customer (email)");
|
||||
OrmQueryDetail detail = p.parse();
|
||||
OrmQueryDetail detail = parse("select (id,name) fetch customer (email)");
|
||||
|
||||
OrmQueryProperties root = detail.getChunk(null, false);
|
||||
assertNull(root.getPath());
|
||||
assertThat(root.getAllIncludedProperties()).contains("id", "name");
|
||||
assertThat(root.getIncluded()).contains("id", "name");
|
||||
|
||||
OrmQueryProperties chunk = detail.getChunk("customer", false);
|
||||
assertThat(chunk.getPath()).isEqualTo("customer");
|
||||
assertThat(chunk.getAllIncludedProperties()).contains("email");
|
||||
assertThat(chunk.getIncluded()).contains("email");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseSelectFetchMore() throws Exception {
|
||||
|
||||
OrmQueryDetailParser p = new OrmQueryDetailParser("select (id,name) fetch customer (email) fetch details.product (sku,description)");
|
||||
OrmQueryDetail detail = p.parse();
|
||||
OrmQueryDetail detail = parse("select (id,name) fetch customer (email) fetch details.product (sku,description)");
|
||||
|
||||
OrmQueryProperties root = detail.getChunk(null, false);
|
||||
assertNull(root.getPath());
|
||||
assertThat(root.getAllIncludedProperties()).contains("id", "name");
|
||||
assertThat(root.getIncluded()).contains("id", "name");
|
||||
|
||||
OrmQueryProperties chunk = detail.getChunk("customer", false);
|
||||
assertThat(chunk.getPath()).isEqualTo("customer");
|
||||
assertThat(chunk.getAllIncludedProperties()).contains("email");
|
||||
assertThat(chunk.getIncluded()).contains("email");
|
||||
|
||||
chunk = detail.getChunk("details.product", false);
|
||||
assertThat(chunk.getPath()).isEqualTo("details.product");
|
||||
assertThat(chunk.getAllIncludedProperties()).contains("sku","description");
|
||||
assertThat(chunk.getIncluded()).contains("sku","description");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseWithPlusQuery() throws Exception {
|
||||
|
||||
OrmQueryDetailParser p = new OrmQueryDetailParser("select (id,name) fetch customer (+query,id,name,email)");
|
||||
OrmQueryDetail detail = p.parse();
|
||||
OrmQueryDetail detail = parse("select (id,name) fetch customer (+query,id,name,email)");
|
||||
|
||||
OrmQueryProperties root = detail.getChunk(null, false);
|
||||
assertNull(root.getPath());
|
||||
assertThat(root.getAllIncludedProperties()).contains("id", "name");
|
||||
assertThat(root.getIncluded()).contains("id", "name");
|
||||
|
||||
OrmQueryProperties chunk = detail.getChunk("customer", false);
|
||||
assertThat(chunk.getPath()).isEqualTo("customer");
|
||||
assertThat(chunk.getAllIncludedProperties()).contains("id", "name", "email");
|
||||
assertThat(chunk.getIncluded()).contains("id", "name", "email");
|
||||
assertThat(chunk.isQueryFetch()).isTrue();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTuneApply() {
|
||||
|
||||
OrmQueryDetailParser p = new OrmQueryDetailParser("select (status) fetch customer (email)");
|
||||
OrmQueryDetail detail = p.parse();
|
||||
|
||||
OrmQueryDetailParser p2 = new OrmQueryDetailParser("select (id,name) fetch customer (+query,id,name,email)");
|
||||
OrmQueryDetail tune = p2.parse();
|
||||
|
||||
OrmQueryDetail detail = parse("select (status) fetch customer (email)");
|
||||
OrmQueryDetail tune = parse("select (id,name) fetch customer (+query,id,name,email)");
|
||||
|
||||
detail.tuneFetchProperties(tune);
|
||||
|
||||
OrmQueryProperties root = detail.getChunk(null, false);
|
||||
assertNull(root.getPath());
|
||||
assertThat(root.getAllIncludedProperties()).contains("id", "name");
|
||||
assertThat(root.getIncluded()).contains("id", "name");
|
||||
|
||||
OrmQueryProperties chunk = detail.getChunk("customer", false);
|
||||
assertThat(chunk.getPath()).isEqualTo("customer");
|
||||
assertThat(chunk.getAllIncludedProperties()).contains("id", "name", "email");
|
||||
assertThat(chunk.getIncluded()).contains("id", "name", "email");
|
||||
assertThat(chunk.isQueryFetch()).isTrue();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,20 +2,70 @@ package com.avaje.ebeaninternal.server.querydefn;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class OrmQueryDetailTest {
|
||||
|
||||
OrmQueryDetail parse(String query) {
|
||||
return new OrmQueryDetailParser(query).parse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_isAutoTuneEqual() {
|
||||
public void isAutoTuneEqual_when_fetchOrderIsDifferent_then_stillEqual() {
|
||||
|
||||
OrmQueryDetailParser parser1 = new OrmQueryDetailParser("select (id,name) fetch customer (name) fetch details (code)");
|
||||
OrmQueryDetail detail1 = parser1.parse();
|
||||
|
||||
OrmQueryDetailParser parser2 = new OrmQueryDetailParser("select (id,name) fetch details (code) fetch customer (name)");
|
||||
OrmQueryDetail detail2 = parser2.parse();
|
||||
OrmQueryDetail detail1 = parse("select (id,name) fetch customer (name) fetch details (code)");
|
||||
OrmQueryDetail detail2 = parse("select (id,name) fetch details (code) fetch customer (name)");
|
||||
|
||||
assertTrue(detail1.isAutoTuneEqual(detail2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAutoTuneEqual_when_different_select() {
|
||||
|
||||
OrmQueryDetail detail1 = parse("select (id,name) fetch customer (name) fetch details (code)");
|
||||
OrmQueryDetail detail2 = parse("select (id) fetch details (code) fetch customer (name)");
|
||||
|
||||
assertFalse(detail1.isAutoTuneEqual(detail2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAutoTuneEqual_when_different_selectInFetch() {
|
||||
|
||||
OrmQueryDetail detail1 = parse("select (id,name) fetch customer (name) fetch details (code)");
|
||||
OrmQueryDetail detail2 = parse("select (id,name) fetch customer (id,name) fetch details (code)");
|
||||
|
||||
assertFalse(detail1.isAutoTuneEqual(detail2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAutoTuneEqual_when_different_additionalFetch() {
|
||||
|
||||
OrmQueryDetail detail1 = parse("select (id,name) fetch customer (name) fetch details (code)");
|
||||
OrmQueryDetail detail2 = parse("select (id,name) fetch customer (name) fetch details (code) fetch customer.contacts");
|
||||
|
||||
assertFalse(detail1.isAutoTuneEqual(detail2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void select_whenMultiple() throws Exception {
|
||||
|
||||
OrmQueryDetail other = new OrmQueryDetail();
|
||||
other.select("id,name");
|
||||
|
||||
OrmQueryProperties root = other.getChunk(null, false);
|
||||
assertNull(root.getPath());
|
||||
assertThat(root.getIncluded()).containsExactly("id", "name");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void select_whenOne() throws Exception {
|
||||
|
||||
OrmQueryDetail other = new OrmQueryDetail();
|
||||
other.select("name");
|
||||
|
||||
OrmQueryProperties root = other.getChunk(null, false);
|
||||
assertNull(root.getPath());
|
||||
assertThat(root.getIncluded()).containsExactly("name");
|
||||
}
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
package com.avaje.ebeaninternal.server.querydefn;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class OrmQueryPropertiesParserTest {
|
||||
|
||||
@Test
|
||||
public void when_null() {
|
||||
|
||||
OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse(null);
|
||||
assertAllDefaults(res);
|
||||
assertThat(res.properties).isEqualTo("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_empty() throws Exception {
|
||||
|
||||
OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("");
|
||||
assertAllDefaults(res);
|
||||
assertThat(res.properties).isEqualTo("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_hasStar() throws Exception {
|
||||
|
||||
OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("*");
|
||||
assertAllDefaults(res);
|
||||
assertThat(res.properties).isEqualTo("*");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_hasCache() throws Exception {
|
||||
|
||||
OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("+cache");
|
||||
assertThat(res.cache).isTrue();
|
||||
assertThat(res.included).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_hasCache_first() throws Exception {
|
||||
|
||||
OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("+cache,id");
|
||||
assertThat(res.cache).isTrue();
|
||||
assertThat(res.included).containsExactly("id");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_hasCache_last() throws Exception {
|
||||
|
||||
OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("name,+cache");
|
||||
assertThat(res.cache).isTrue();
|
||||
assertThat(res.included).containsExactly("name");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_hasCache_middle() throws Exception {
|
||||
|
||||
OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("name,+cache, id");
|
||||
assertThat(res.cache).isTrue();
|
||||
assertThat(res.included).containsExactly("name", "id");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_hasReadOnly() throws Exception {
|
||||
|
||||
OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("+readonly");
|
||||
assertThat(res.readOnly).isTrue();
|
||||
assertThat(res.included).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_hasLazy() throws Exception {
|
||||
|
||||
OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("+lazy");
|
||||
assertThat(res.lazyFetchBatch).isEqualTo(0);
|
||||
assertThat(res.included).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_hasLazyValue() throws Exception {
|
||||
|
||||
OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("+lazy(20)");
|
||||
assertThat(res.lazyFetchBatch).isEqualTo(20);
|
||||
assertThat(res.included).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_hasLazyValue_last() throws Exception {
|
||||
|
||||
OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("name,+lazy(20)");
|
||||
assertThat(res.lazyFetchBatch).isEqualTo(20);
|
||||
assertThat(res.included).containsExactly("name");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_hasLazyValue_first() throws Exception {
|
||||
|
||||
OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("+lazy(20),id,name");
|
||||
assertThat(res.lazyFetchBatch).isEqualTo(20);
|
||||
assertThat(res.included).containsExactly("id", "name");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_allProperties() throws Exception {
|
||||
|
||||
OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("+query(4),+lazy(5)");
|
||||
assertThat(res.lazyFetchBatch).isEqualTo(5);
|
||||
assertThat(res.included).isNull();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void when_everything_set() throws Exception {
|
||||
|
||||
OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("id, name +readonly +lazy(20) +query(30) +cache");
|
||||
assertThat(res.lazyFetchBatch).isEqualTo(20);
|
||||
assertThat(res.queryFetchBatch).isEqualTo(30);
|
||||
assertThat(res.readOnly).isTrue();
|
||||
assertThat(res.cache).isTrue();
|
||||
assertThat(res.included).containsExactly("id", "name");
|
||||
}
|
||||
|
||||
private void assertAllDefaults(OrmQueryPropertiesParser.Response res) {
|
||||
assertThat(res.cache).isFalse();
|
||||
assertThat(res.readOnly).isFalse();
|
||||
assertThat(res.lazyFetchBatch).isEqualTo(-1);
|
||||
assertThat(res.queryFetchBatch).isEqualTo(-1);
|
||||
assertThat(res.included).isNull();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.avaje.ebeaninternal.server.querydefn;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class OrmQueryPropertiesTest {
|
||||
|
||||
String append(String prefix, OrmQueryProperties p1) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
p1.append(prefix, sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void append_when_empty() {
|
||||
|
||||
OrmQueryProperties p1 = new OrmQueryProperties();
|
||||
assertThat(append("select ",p1)).isEqualTo("select ");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void append_when_someProperties() {
|
||||
|
||||
OrmQueryProperties p1 = new OrmQueryProperties(null, "id,name");
|
||||
assertThat(append("select ",p1)).isEqualTo("select (id,name) ");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void append_when_somePropertiesWithOptions() {
|
||||
|
||||
OrmQueryProperties p1 = new OrmQueryProperties(null, "id,name +cache");
|
||||
assertThat(append("select ",p1)).isEqualTo("select (id,name +cache) ");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void append_when_path_and_emptyProperties() {
|
||||
|
||||
OrmQueryProperties p1 = new OrmQueryProperties("customer", "");
|
||||
assertThat(append("fetch ",p1)).isEqualTo("fetch customer ");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void append_when_path_and_somePropertiesWithOptions() {
|
||||
|
||||
OrmQueryProperties p1 = new OrmQueryProperties("customer", "id,name +cache");
|
||||
assertThat(append("fetch ",p1)).isEqualTo("fetch customer (id,name +cache) ");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,15 +1,14 @@
|
||||
package com.avaje.ebeaninternal.server.querydefn;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebeaninternal.server.expression.DefaultExpressionFactory;
|
||||
import com.avaje.tests.model.basic.Order;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class TestQueryLanguage extends BaseTestCase {
|
||||
|
||||
@@ -19,7 +18,7 @@ public class TestQueryLanguage extends BaseTestCase {
|
||||
DefaultOrmQuery<Order> q = check("find order join customer (id, name)");
|
||||
OrmQueryDetail detail = q.getDetail();
|
||||
OrmQueryProperties chunk = detail.getChunk("customer", false);
|
||||
Set<String> props = chunk.getAllIncludedProperties();
|
||||
Set<String> props = chunk.getIncluded();
|
||||
|
||||
Assert.assertTrue(props.contains("id"));
|
||||
Assert.assertTrue(props.contains("name"));
|
||||
@@ -27,7 +26,7 @@ public class TestQueryLanguage extends BaseTestCase {
|
||||
q = check("find order join customer(id, name)");
|
||||
detail = q.getDetail();
|
||||
chunk = detail.getChunk("customer", false);
|
||||
props = chunk.getAllIncludedProperties();
|
||||
props = chunk.getIncluded();
|
||||
|
||||
Assert.assertTrue(props.contains("id"));
|
||||
Assert.assertTrue(props.contains("name"));
|
||||
@@ -37,7 +36,7 @@ public class TestQueryLanguage extends BaseTestCase {
|
||||
q = check("find order join customer(+cache +readonly, id, name)");
|
||||
detail = q.getDetail();
|
||||
chunk = detail.getChunk("customer", false);
|
||||
props = chunk.getAllIncludedProperties();
|
||||
props = chunk.getIncluded();
|
||||
Assert.assertTrue(props.contains("id"));
|
||||
Assert.assertTrue(props.contains("name"));
|
||||
Assert.assertTrue(chunk.isCache());
|
||||
@@ -46,7 +45,7 @@ public class TestQueryLanguage extends BaseTestCase {
|
||||
q = check("find order join customer(+cache +readonly,id,name)");
|
||||
detail = q.getDetail();
|
||||
chunk = detail.getChunk("customer", false);
|
||||
props = chunk.getAllIncludedProperties();
|
||||
props = chunk.getIncluded();
|
||||
Assert.assertTrue(props.contains("id"));
|
||||
Assert.assertTrue(props.contains("name"));
|
||||
Assert.assertTrue(chunk.isCache());
|
||||
@@ -55,14 +54,14 @@ public class TestQueryLanguage extends BaseTestCase {
|
||||
q = check("find order(id,status) join customer(+cache +readonly,id,name)");
|
||||
detail = q.getDetail();
|
||||
chunk = detail.getChunk("customer", false);
|
||||
props = chunk.getAllIncludedProperties();
|
||||
props = chunk.getIncluded();
|
||||
Assert.assertTrue(props.contains("id"));
|
||||
Assert.assertTrue(props.contains("name"));
|
||||
Assert.assertTrue(chunk.isCache());
|
||||
Assert.assertTrue(chunk.isReadOnly());
|
||||
|
||||
chunk = detail.getChunk(null, false);
|
||||
props = chunk.getAllIncludedProperties();
|
||||
props = chunk.getIncluded();
|
||||
Assert.assertTrue(props.contains("id"));
|
||||
Assert.assertTrue(props.contains("status"));
|
||||
Assert.assertFalse(props.contains("orderDate"));
|
||||
@@ -70,7 +69,7 @@ public class TestQueryLanguage extends BaseTestCase {
|
||||
q = check("find order(id,status) join customer(+cache +readonly,id,name) where id > :minId order by status");
|
||||
detail = q.getDetail();
|
||||
chunk = detail.getChunk("customer", false);
|
||||
props = chunk.getAllIncludedProperties();
|
||||
props = chunk.getIncluded();
|
||||
Assert.assertTrue(props.contains("id"));
|
||||
Assert.assertTrue(props.contains("name"));
|
||||
Assert.assertTrue(chunk.isCache());
|
||||
|
||||
@@ -101,7 +101,7 @@ public class TunedQueryInfoTest extends BaseTestCase {
|
||||
@NotNull
|
||||
private TunedQueryInfo createTunedQueryInfo(OrmQueryDetail tunedDetail) {
|
||||
Origin origin = new Origin();
|
||||
origin.setDetail(tunedDetail.toString());
|
||||
origin.setDetail(tunedDetail.asString());
|
||||
return new TunedQueryInfo(origin);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,37 +1,40 @@
|
||||
package com.avaje.tests.query;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.server.querydefn.OrmQueryDetail;
|
||||
import com.avaje.tests.model.basic.Order;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class TestQueryParsing extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
String oq = "find order join customer join customer.contacts join details (+query(4),+lazy(5))";
|
||||
String oq = "find order join customer (id, name) join customer.contacts join details (+query(4),+lazy(5))";
|
||||
Query<Order> q = Ebean.createQuery(Order.class, oq);
|
||||
checkQuery(q);
|
||||
|
||||
String oq1 = "find order join customer join customer.contacts join details ( +query(4), +lazy(5) )";
|
||||
String oq1 = "find order join customer (id, name) join customer.contacts join details ( +query(4), +lazy(5) )";
|
||||
SpiQuery<?> q1 = (SpiQuery<?>) Ebean.createQuery(Order.class, oq1);
|
||||
checkQuery(q1);
|
||||
|
||||
String oq2 = "find order join customer join customer.contacts join details ( +query(4), +lazy(5) , *)";
|
||||
String oq2 = "find order join customer (id, name) join customer.contacts join details ( +query(4), +lazy(5) , *)";
|
||||
SpiQuery<?> q2 = (SpiQuery<?>) Ebean.createQuery(Order.class, oq2);
|
||||
checkQuery(q2);
|
||||
|
||||
String oq3 = "find order join customer join customer.contacts join details (+query(4),+lazy(5),*)";
|
||||
String oq3 = "find order join customer (id, name) join customer.contacts join details (+query(4),+lazy(5),*)";
|
||||
SpiQuery<?> q3 = (SpiQuery<?>) Ebean.createQuery(Order.class, oq3);
|
||||
checkQuery(q3);
|
||||
|
||||
String oq4 = "find order join customer join customer.contacts join details (+query(4) +lazy(5) *)";
|
||||
String oq4 = "find order join customer (id, name) join customer.contacts join details (+query(4) +lazy(5) *)";
|
||||
SpiQuery<?> q4 = (SpiQuery<?>) Ebean.createQuery(Order.class, oq4);
|
||||
checkQuery(q4);
|
||||
|
||||
@@ -41,23 +44,25 @@ public class TestQueryParsing extends BaseTestCase {
|
||||
|
||||
SpiQuery<?> sq = (SpiQuery<?>) q;
|
||||
OrmQueryDetail detail = sq.getDetail();
|
||||
assertTrue(detail.getChunk(null, false).allProperties());
|
||||
|
||||
Assert.assertNotNull(detail.getChunk("customer", false));
|
||||
Assert.assertFalse(detail.getChunk("customer", false).isQueryFetch());
|
||||
Assert.assertFalse(detail.getChunk("customer", false).isLazyFetch());
|
||||
assertNotNull(detail.getChunk("customer", false));
|
||||
assertFalse(detail.getChunk("customer", false).isQueryFetch());
|
||||
assertFalse(detail.getChunk("customer", false).isLazyFetch());
|
||||
assertFalse(detail.getChunk("customer", false).allProperties());
|
||||
assertEquals("id, name",detail.getChunk("customer", false).getProperties());
|
||||
|
||||
Assert.assertNotNull(detail.getChunk("customer.contacts", false));
|
||||
Assert.assertFalse(detail.getChunk("customer.contacts", false).isQueryFetch());
|
||||
Assert.assertFalse(detail.getChunk("customer.contacts", false).isLazyFetch());
|
||||
assertNotNull(detail.getChunk("customer.contacts", false));
|
||||
assertFalse(detail.getChunk("customer.contacts", false).isQueryFetch());
|
||||
assertFalse(detail.getChunk("customer.contacts", false).isLazyFetch());
|
||||
assertTrue(detail.getChunk("customer.contacts", false).allProperties());
|
||||
|
||||
Assert.assertNotNull(detail.getChunk("details", false));
|
||||
Assert.assertTrue(detail.getChunk("details", false).isQueryFetch());
|
||||
Assert.assertTrue(detail.getChunk("details", false).isLazyFetch());
|
||||
|
||||
Assert.assertEquals(4, detail.getChunk("details", false).getQueryFetchBatch());
|
||||
Assert.assertEquals(5, detail.getChunk("details", false).getLazyFetchBatch());
|
||||
|
||||
Assert.assertTrue(detail.getChunk("details", false).allProperties());
|
||||
assertNotNull(detail.getChunk("details", false));
|
||||
assertTrue(detail.getChunk("details", false).isQueryFetch());
|
||||
assertTrue(detail.getChunk("details", false).isLazyFetch());
|
||||
assertEquals(4, detail.getChunk("details", false).getQueryFetchBatch());
|
||||
assertEquals(5, detail.getChunk("details", false).getLazyFetchBatch());
|
||||
assertTrue(detail.getChunk("details", false).allProperties());
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user