#274 - Predicate using a foreign key column sometimes adds an extra join

This commit is contained in:
rbygrave
2015-04-11 18:53:17 +12:00
parent bede89fe13
commit db57404e18
3 changed files with 46 additions and 34 deletions
@@ -60,12 +60,12 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
private final ConcurrentHashMap<HashQueryPlan, CQueryPlan> queryPlanCache = new ConcurrentHashMap<HashQueryPlan, CQueryPlan>();
private final ConcurrentHashMap<String, ElPropertyValue> elGetCache = new ConcurrentHashMap<String, ElPropertyValue>();
private final ConcurrentHashMap<String, ElPropertyValue> elCache = new ConcurrentHashMap<String, ElPropertyValue>();
private final ConcurrentHashMap<String, ElPropertyDeploy> elDeployCache = new ConcurrentHashMap<String, ElPropertyDeploy>();
private final ConcurrentHashMap<String, ElComparator<T>> comparatorCache = new ConcurrentHashMap<String, ElComparator<T>>();
private final ConcurrentHashMap<String, BeanFkeyProperty> fkeyMap = new ConcurrentHashMap<String, BeanFkeyProperty>();
public enum EntityType {
ORM, EMBEDDED, SQL
}
@@ -630,7 +630,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
* foreign keys don't require an extra join.
*/
public void add(BeanFkeyProperty fkey) {
fkeyMap.put(fkey.getName(), fkey);
elDeployCache.put(fkey.getName(), fkey);
}
public void initialiseFkeys() {
@@ -1379,7 +1379,15 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
* Get an Expression language Value object.
*/
public ElPropertyValue getElGetValue(String propName) {
return getElPropertyValue(propName, false);
ElPropertyValue elGetValue = elCache.get(propName);
if (elGetValue != null) {
return elGetValue;
}
elGetValue = buildElGetValue(propName, null, false);
if (elGetValue != null) {
elCache.put(propName, elGetValue);
}
return elGetValue;
}
/**
@@ -1389,36 +1397,30 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
* </p>
*/
public ElPropertyDeploy getElPropertyDeploy(String propName) {
ElPropertyDeploy fk = fkeyMap.get(propName);
if (fk != null) {
return fk;
ElPropertyDeploy elProp = elDeployCache.get(propName);
if (elProp != null) {
return elProp;
}
return getElPropertyValue(propName, true);
}
private ElPropertyValue getElPropertyValue(String propName, boolean propertyDeploy) {
ElPropertyValue elGetValue = elGetCache.get(propName);
if (elGetValue == null) {
// need to build it potentially navigating the BeanDescriptors
elGetValue = buildElGetValue(propName, null, propertyDeploy);
if (elGetValue == null) {
return null;
}
if (elGetValue instanceof BeanFkeyProperty) {
fkeyMap.put(propName, (BeanFkeyProperty) elGetValue);
} else {
elGetCache.put(propName, elGetValue);
}
if (!propName.contains(".")) {
// No period means simple property and no need to look for
// foreign key properties (in order to avoid an extra join)
elProp = getElGetValue(propName);
} else {
elProp = buildElGetValue(propName, null, true);
}
return elGetValue;
if (elProp != null) {
elDeployCache.put(propName, elProp);
}
return elProp;
}
protected ElPropertyValue buildElGetValue(String propName, ElPropertyChainBuilder chain, boolean propertyDeploy) {
if (propertyDeploy && chain != null) {
BeanFkeyProperty fk = fkeyMap.get(propName);
if (fk != null) {
return fk.create(chain.getExpression(), chain.isContainsMany());
ElPropertyDeploy fk = elDeployCache.get(propName);
if (fk != null && fk instanceof BeanFkeyProperty) {
// propertyDeploy chain for foreign key column
return ((BeanFkeyProperty)fk).create(chain.getExpression(), chain.isContainsMany());
}
}
@@ -31,6 +31,10 @@ public final class BeanFkeyProperty implements ElPropertyValue {
this.placeHolder = calcPlaceHolder(prefix, dbColumn);
}
public String toString() {
return "prefix:"+prefix+" name:"+name+" dbColumn:"+dbColumn+" ph:"+placeHolder;
}
public int getDeployOrder() {
return deployOrder;
}
@@ -8,6 +8,8 @@ import com.avaje.ebeaninternal.server.lib.util.StringHelper;
import com.avaje.ebeaninternal.server.query.SplitName;
import com.avaje.ebeaninternal.server.type.ScalarType;
import java.util.Arrays;
/**
* A ElGetValue based on a chain of properties.
@@ -41,9 +43,9 @@ public class ElPropertyChain implements ElPropertyValue {
private final ScalarType<?> scalarType;
private final ElPropertyValue lastElPropertyValue;
public ElPropertyChain(boolean containsMany, boolean embedded, String expression, ElPropertyValue[] chain) {
this.containsMany = containsMany;
this.chain = chain;
this.expression = expression;
@@ -51,19 +53,19 @@ public class ElPropertyChain implements ElPropertyValue {
if (dotPos > -1){
this.name = expression.substring(dotPos+1);
if (embedded){
int embPos = expression.lastIndexOf('.',dotPos-1);
int embPos = expression.lastIndexOf('.',dotPos-1);
this.prefix = embPos == -1 ? null : expression.substring(0, embPos);
} else {
this.prefix = expression.substring(0, dotPos);
}
} else {
this.prefix = null;
this.name = expression;
}
}
this.assocId = chain[chain.length-1].isAssocId();
this.last = chain.length-1;
this.lastBeanProperty = chain[chain.length-1].getBeanProperty();
if (lastBeanProperty != null){
@@ -77,6 +79,10 @@ public class ElPropertyChain implements ElPropertyValue {
this.placeHolderEncrypted = getElPlaceHolder(prefix, lastElPropertyValue, true);
}
public String toString() {
return "expr:"+expression+" chain:"+ Arrays.toString(chain);
}
private String getElPlaceHolder(String prefix, ElPropertyValue lastElPropertyValue, boolean encrypted) {
if (prefix == null){
return lastElPropertyValue.getElPlaceholder(encrypted);