#566 - Refactor internals - Initial tidy on OrmQueryDetail and OrmQueryDetailProperties - internals for fetch paths etc

This commit is contained in:
Robin Bygrave committed 2016-02-17 13:59:48 +13:00
1 parent 2fcaab44c6
commit 5c6d6608ef
12 files changed
+397 -145

No files matched your search

@@ -110,7 +110,7 @@ public class ProfileOrigin {
Collection<Props> pathProperties = pathProps.getPathProps();
for (Props props : pathProperties) {
if (!props.isEmpty()) {
detail.addFetch(props.getPath(), props.getPropertiesAsString(), null);
detail.fetch(props.getPath(), props.getPropertiesAsString(), null);
}
}
@@ -1252,7 +1252,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo, SpiBeanType<T> {
OrmQueryDetail detail = query.getDetail();
for (int i = 0; i < propertiesMany.length; i++) {
if (detail.includes(propertiesMany[i].getName())) {
if (detail.includesPath(propertiesMany[i].getName())) {
return propertiesMany[i];
}
}
@@ -353,7 +353,7 @@ public class CQueryBuilder {
// transfer PathProperties into OrmQueryDetail
for (String path : pathProps.getPaths()) {
detail.getChunk(path, true).setDefaultProperties(null, pathProps.get(path));
detail.fetch(path, pathProps.get(path));
}
// check if @Id property included in RawSql
@@ -140,7 +140,7 @@ public class SqlTreeBuilder {
boolean includeJoins = (alias == null) ? false : alias.isIncludeJoins();
return new SqlTree(summary.toString(), rootNode, selectSql, fromSql, inheritanceWhereSql, encryptedProps,
manyProperty, queryDetail.getIncludes(), includeJoins);
manyProperty, queryDetail.getFetchPaths(), includeJoins);
}
private String buildSelectClause() {
@@ -183,7 +183,7 @@ public class SqlTreeBuilder {
rootNode = buildSelectChain(null, null, desc, null);
if (!rawSql) {
alias.addJoin(queryDetail.getIncludes(), desc);
alias.addJoin(queryDetail.getFetchPaths(), desc);
alias.addJoin(predicates.getPredicateIncludes(), desc);
alias.addManyWhereJoins(manyWhereJoins.getPropertyNames());
@@ -471,7 +471,7 @@ public class SqlTreeBuilder {
return false;
}
if (queryDetail.includes(propName)) {
if (queryDetail.includesPath(propName)) {
if (manyProperty != null) {
// only one many associated allowed to be included in fetch
@@ -498,7 +498,7 @@ public class SqlTreeBuilder {
*/
private boolean isIncludeBean(String prefix) {
if (queryDetail.includes(prefix)) {
if (queryDetail.includesPath(prefix)) {
// explicitly included
summary.append(", ").append(prefix);
String[] splitNames = SplitName.split(prefix);
@@ -1008,7 +1008,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
}
public DefaultOrmQuery<T> fetch(String property, String columns, FetchConfig config) {
detail.addFetch(property, columns, config);
detail.fetch(property, columns, config);
return this;
}
@@ -13,12 +13,12 @@ import javax.persistence.PersistenceException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
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.
@@ -46,8 +46,6 @@ public class OrmQueryDetail implements Serializable {
*/
private LinkedHashMap<String, OrmQueryProperties> fetchPaths = new LinkedHashMap<String, OrmQueryProperties>(8);
private LinkedHashSet<String> includes = new LinkedHashSet<String>(8);
/**
* Return a deep copy of the OrmQueryDetail.
*/
@@ -57,7 +55,6 @@ public class OrmQueryDetail implements Serializable {
for (Map.Entry<String, OrmQueryProperties> entry : fetchPaths.entrySet()) {
copy.fetchPaths.put(entry.getKey(), entry.getValue().copy());
}
copy.includes = new LinkedHashSet<String>(includes);
return copy;
}
@@ -170,7 +167,7 @@ public class OrmQueryDetail implements Serializable {
* set the properties to include on the base / root entity.
*/
public void select(String columns) {
baseProps = new OrmQueryProperties(null, columns);
baseProps = new OrmQueryProperties(null, columns, null);
}
public boolean containsProperty(String property) {
@@ -215,7 +212,6 @@ public class OrmQueryDetail implements Serializable {
for (int i = 0; i < matchingPaths.size(); i++) {
String path = matchingPaths.get(i);
includes.remove(path);
OrmQueryProperties secQuery = fetchPaths.remove(path);
if (secQuery != null) {
props.add(secQuery);
@@ -228,7 +224,6 @@ public class OrmQueryDetail implements Serializable {
// remove join to secondary query from the main query
// and add to this secondary query
pass2It.remove();
includes.remove(pass2Prop.getPath());
secQuery.add(pass2Prop);
}
}
@@ -257,29 +252,24 @@ public class OrmQueryDetail implements Serializable {
OrmQueryProperties tunedRoot = tunedDetail.getChunk(null, false);
if (tunedRoot != null) {
tuned = true;
baseProps.setTunedProperties(tunedRoot);
baseProps = tunedRoot;
for (OrmQueryProperties tunedChunk : tunedDetail.fetchPaths.values()) {
OrmQueryProperties chunk = getChunk(tunedChunk.getPath(), false);
if (chunk != null) {
// set the properties to select
chunk.setTunedProperties(tunedChunk);
} else {
// add a missing join
putFetchPath(tunedChunk.copy());
}
fetch(tunedChunk.copy());
}
}
return tuned;
}
/**
* Matches a join() method of the query.
* Add or replace the fetch detail.
*/
public void putFetchPath(OrmQueryProperties chunk) {
protected void fetch(OrmQueryProperties chunk) {
String path = chunk.getPath();
fetchPaths.put(path, chunk);
includes.add(path);
if (path == null) {
baseProps = chunk;
} else {
fetchPaths.put(path, chunk);
}
}
/**
@@ -289,7 +279,6 @@ public class OrmQueryDetail implements Serializable {
* </p>
*/
public void clear() {
includes.clear();
fetchPaths.clear();
}
@@ -299,11 +288,16 @@ public class OrmQueryDetail implements Serializable {
* @param path the property to join
* @param partialProps the properties on the join property to include
*/
public void addFetch(String path, String partialProps, FetchConfig fetchConfig) {
public void fetch(String path, String partialProps, FetchConfig fetchConfig) {
OrmQueryProperties chunk = getChunk(path, true);
chunk.setProperties(partialProps);
chunk.setFetchConfig(fetchConfig);
fetch(new OrmQueryProperties(path, partialProps, fetchConfig));
}
/**
* Add for raw sql etc when the properties are already parsed into a set.
*/
public void fetch(String path, LinkedHashSet<String> properties) {
fetch(new OrmQueryProperties(path, properties));
}
public void sortFetchPaths(BeanDescriptor<?> d) {
@@ -438,15 +432,14 @@ public class OrmQueryDetail implements Serializable {
public void setDefaultSelectClause(BeanDescriptor<?> desc) {
if (desc.hasDefaultSelectClause() && !hasSelectClause()) {
baseProps.setDefaultProperties(desc.getDefaultSelectClause(), desc.getDefaultSelectClauseSet());
baseProps = new OrmQueryProperties(null, desc.getDefaultSelectClause());
}
for (OrmQueryProperties joinProps : fetchPaths.values()) {
if (!joinProps.hasSelectClause()) {
BeanDescriptor<?> assocDesc = desc.getBeanDescriptor(joinProps.getPath());
if (assocDesc.hasDefaultSelectClause()) {
// use the default select clause
joinProps.setDefaultProperties(assocDesc.getDefaultSelectClause(), assocDesc.getDefaultSelectClauseSet());
fetch(joinProps.getPath(), assocDesc.getDefaultSelectClause(), joinProps.getFetchConfig());
}
}
}
@@ -489,7 +482,7 @@ public class OrmQueryDetail implements Serializable {
OrmQueryProperties props = fetchPaths.get(path);
if (create && props == null) {
props = new OrmQueryProperties(path);
putFetchPath(props);
fetch(props);
return props;
} else {
@@ -498,9 +491,9 @@ public class OrmQueryDetail implements Serializable {
}
/**
* Return true if the property is included.
* Return true if the fetch path is included.
*/
public boolean includes(String path) {
public boolean includesPath(String path) {
OrmQueryProperties chunk = fetchPaths.get(path);
@@ -509,9 +502,9 @@ public class OrmQueryDetail implements Serializable {
}
/**
* Return the property includes for this detail.
* Return the fetch paths for this detail.
*/
public HashSet<String> getIncludes() {
return includes;
public Set<String> getFetchPaths() {
return fetchPaths.keySet();
}
}
@@ -64,8 +64,7 @@ public class OrmQueryDetailParser {
private void process() {
if (isFetch()) {
OrmQueryProperties props = readFindFetch();
detail.putFetchPath(props);
detail.fetch(readFindFetch());
} else if (parser.isMatch("where")) {
readWhere();
@@ -157,7 +156,7 @@ public class OrmQueryDetailParser {
private void readSelect() {
String path = null;
String props = parser.nextWord();
if (props != null && props.startsWith("(")) {
if (props.startsWith("(")) {
props = props.substring(1, props.length() - 1);
OrmQueryProperties base = new OrmQueryProperties(path, props);
detail.setBase(base);
@@ -28,11 +28,11 @@ public class OrmQueryProperties implements Serializable {
private static final long serialVersionUID = -8785582703966455658L;
private String parentPath;
private String path;
private final String parentPath;
private final String path;
private String rawProperties;
private String trimmedProperties;
private final String rawProperties;
private final String trimmedProperties;
/**
* NB: -1 means no +query, 0 means use the default batch size.
@@ -55,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 LinkedHashSet<String> included;
private final LinkedHashSet<String> included;
/**
* Included bean joins.
@@ -83,25 +83,110 @@ public class OrmQueryProperties implements Serializable {
private SpiExpressionList filterMany;
/**
* Construct with a given path (null == root path).
* Construct for root so path (and parentPath) are null.
*/
public OrmQueryProperties() {
this((String)null);
}
/**
* Construct with a given path.
*/
public OrmQueryProperties(String path) {
this.path = path;
this.parentPath = SplitName.parent(path);
this.rawProperties = null;
this.trimmedProperties = null;
this.included = null;
}
public OrmQueryProperties(String path, String rawProperties) {
this(path, rawProperties, null);
}
public OrmQueryProperties(String path, String rawProperties, FetchConfig fetchConfig) {
OrmQueryPropertiesParser.Response response = OrmQueryPropertiesParser.parse(rawProperties);
this.path = path;
this.parentPath = SplitName.parent(path);
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;
if (fetchConfig != null) {
this.fetchConfig = fetchConfig;
lazyFetchBatch = fetchConfig.getLazyBatchSize();
queryFetchBatch = fetchConfig.getQueryBatchSize();
queryFetchAll = fetchConfig.isQueryAll();
}
}
public OrmQueryProperties(String path, LinkedHashSet<String> parsedProperties) {
if (parsedProperties == null) {
throw new IllegalArgumentException("parsedProperties is null");
}
this.path = path;
this.parentPath = SplitName.parent(path);
// for rawSql parsedProperties can be empty (when only fetching Id property)
this.included = parsedProperties;
this.rawProperties = join(parsedProperties);
this.trimmedProperties = rawProperties;
this.lazyFetchBatch = -1;
this.queryFetchBatch = -1;
this.cache = false;
this.readOnly = false;
this.queryFetchAll = false;
}
/**
* Construct for root so path (and parentPath) are null.
* Join the set of properties into a comma delimited string.
*/
public OrmQueryProperties() {
private String join(LinkedHashSet<String> parsedProperties) {
StringBuilder sb = new StringBuilder(50);
boolean first = true;
for (String property : parsedProperties) {
if (first) {
first = false;
} else {
sb.append(",");
}
sb.append(property);
}
return sb.toString();
}
/**
* Used by query language parser.
* Copy constructor.
*/
public OrmQueryProperties(String path, String properties) {
this(path);
setProperties(properties);
private OrmQueryProperties(OrmQueryProperties source) {
this.parentPath = source.parentPath;
this.path = source.path;
this.rawProperties = source.rawProperties;
this.trimmedProperties = source.trimmedProperties;
this.cache = source.cache;
this.readOnly = source.readOnly;
this.queryFetchAll = source.queryFetchAll;
this.queryFetchBatch = source.queryFetchBatch;
this.lazyFetchBatch = source.lazyFetchBatch;
this.filterMany = source.filterMany;
this.included = (source.included == null) ? null : new LinkedHashSet<String>(source.included);
if (includedBeanJoin != null) {
this.includedBeanJoin = new HashSet<String>(source.includedBeanJoin);
}
}
/**
* Creates a copy of the OrmQueryProperties.
*/
public OrmQueryProperties copy() {
return new OrmQueryProperties(this);
}
/**
@@ -115,41 +200,10 @@ public class OrmQueryProperties implements Serializable {
orderBy.add(orderProp);
}
/**
* Set the Fetch configuration options for this path.
*/
public void setFetchConfig(FetchConfig fetchConfig) {
if (fetchConfig != null) {
this.fetchConfig = fetchConfig;
lazyFetchBatch = fetchConfig.getLazyBatchSize();
queryFetchBatch = fetchConfig.getQueryBatchSize();
queryFetchAll = fetchConfig.isQueryAll();
}
}
public FetchConfig getFetchConfig() {
return fetchConfig;
}
/**
* Set the comma delimited properties to fetch for this path.
* <p>
* This can include the +query and +lazy type hints.
* </p>
*/
public void setProperties(String rawProperties) {
OrmQueryPropertiesParser.Response response = OrmQueryPropertiesParser.parse(rawProperties);
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;
}
/**
* Return the expressions used to filter on this path. This should be a many path to use this
* method.
@@ -193,28 +247,6 @@ public class OrmQueryProperties implements Serializable {
this.filterMany = filterMany;
}
/**
* Set the properties from deployment default FetchTypes.
*/
public void setDefaultProperties(String properties, LinkedHashSet<String> included) {
this.rawProperties = properties;
this.trimmedProperties = properties;
this.included = included;
}
/**
* Set the properties from a matching AutoTune tuned properties.
*/
public void setTunedProperties(OrmQueryProperties tunedProperties) {
if (tunedProperties.hasProperties()) {
this.rawProperties = tunedProperties.rawProperties;
this.trimmedProperties = tunedProperties.trimmedProperties;
this.included = tunedProperties.included;
this.queryFetchBatch = Math.max(queryFetchBatch, tunedProperties.queryFetchBatch);
this.lazyFetchBatch = Math.max(lazyFetchBatch, tunedProperties.lazyFetchBatch);
}
}
/**
* Define the select and joins for this query.
*/
@@ -249,30 +281,6 @@ public class OrmQueryProperties implements Serializable {
}
}
/**
* Creates a copy of the OrmQueryProperties.
*/
public OrmQueryProperties copy() {
OrmQueryProperties copy = new OrmQueryProperties();
copy.parentPath = parentPath;
copy.path = path;
copy.rawProperties = rawProperties;
copy.trimmedProperties = trimmedProperties;
copy.cache = cache;
copy.readOnly = readOnly;
copy.queryFetchAll = queryFetchAll;
copy.queryFetchBatch = queryFetchBatch;
copy.lazyFetchBatch = lazyFetchBatch;
copy.filterMany = filterMany;
if (included != null) {
copy.included = new LinkedHashSet<String>(included);
}
if (includedBeanJoin != null) {
copy.includedBeanJoin = new HashSet<String>(includedBeanJoin);
}
return copy;
}
public boolean hasSelectClause() {
if ("*".equals(trimmedProperties)) {
// explicitly selected all properties