Fix for #37 - disjunction expression should not produce inner join - left outer join instead

This commit is contained in:
Rob Bygrave
2014-05-18 21:17:19 +12:00
parent 5b98d82f58
commit 08602afcff
45 changed files with 956 additions and 331 deletions
@@ -27,6 +27,7 @@ import com.avaje.ebeaninternal.server.el.ElPropertyChainBuilder;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
import com.avaje.ebeaninternal.server.query.SqlBeanLoad;
import com.avaje.ebeaninternal.server.query.SqlJoinType;
import com.avaje.ebeaninternal.server.reflect.BeanReflectGetter;
import com.avaje.ebeaninternal.server.reflect.BeanReflectSetter;
import com.avaje.ebeaninternal.server.text.json.ReadJsonContext;
@@ -509,14 +510,14 @@ public class BeanProperty implements ElPropertyValue {
* Add any extra joins required to support this property. Generally a no
* operation except for a OneToOne exported.
*/
public void appendFrom(DbSqlContext ctx, boolean forceOuterJoin) {
public void appendFrom(DbSqlContext ctx, SqlJoinType joinType) {
if (formula && sqlFormulaJoin != null) {
ctx.appendFormulaJoin(sqlFormulaJoin, forceOuterJoin);
ctx.appendFormulaJoin(sqlFormulaJoin, joinType);
} else if (secondaryTableJoin != null) {
String relativePrefix = ctx.getRelativePrefix(secondaryTableJoinPrefix);
secondaryTableJoin.addJoin(forceOuterJoin, relativePrefix, ctx);
secondaryTableJoin.addJoin(joinType, relativePrefix, ctx);
}
}
@@ -16,6 +16,7 @@ import com.avaje.ebeaninternal.server.deploy.id.ImportedIdSimple;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssoc;
import com.avaje.ebeaninternal.server.el.ElPropertyChainBuilder;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
import com.avaje.ebeaninternal.server.query.SqlJoinType;
/**
* Abstract base for properties mapped to an associated bean, list, set or map.
@@ -129,22 +130,15 @@ public abstract class BeanPropertyAssoc<T> extends BeanProperty {
/**
* Add table join with table alias based on prefix.
*/
public boolean addJoin(boolean forceOuterJoin, String prefix, DbSqlContext ctx) {
return tableJoin.addJoin(forceOuterJoin, prefix, ctx);
public SqlJoinType addJoin(SqlJoinType joinType, String prefix, DbSqlContext ctx) {
return tableJoin.addJoin(joinType, prefix, ctx);
}
/**
* Add table join with explicit table alias.
*/
public boolean addJoin(boolean forceOuterJoin, String a1, String a2, DbSqlContext ctx) {
return tableJoin.addJoin(forceOuterJoin, a1, a2, ctx);
}
/**
* Add table join with explicit table alias.
*/
public void addInnerJoin(String a1, String a2, DbSqlContext ctx) {
tableJoin.addInnerJoin(a1, a2, ctx);
public SqlJoinType addJoin(SqlJoinType joinType, String a1, String a2, DbSqlContext ctx) {
return tableJoin.addJoin(joinType, a1, a2, ctx);
}
/**
@@ -23,6 +23,7 @@ import com.avaje.ebeaninternal.server.el.ElPropertyChainBuilder;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
import com.avaje.ebeaninternal.server.query.SplitName;
import com.avaje.ebeaninternal.server.query.SqlBeanLoad;
import com.avaje.ebeaninternal.server.query.SqlJoinType;
import com.avaje.ebeaninternal.server.text.json.ReadJsonContext;
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
@@ -508,9 +509,9 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
}
@Override
public void appendFrom(DbSqlContext ctx, boolean forceOuterJoin) {
public void appendFrom(DbSqlContext ctx, SqlJoinType joinType) {
if (!isTransient) {
localHelp.appendFrom(ctx, forceOuterJoin);
localHelp.appendFrom(ctx, joinType);
}
}
@@ -587,7 +588,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
abstract void appendSelect(DbSqlContext ctx, boolean subQuery);
abstract void appendFrom(DbSqlContext ctx, boolean forceOuterJoin);
abstract void appendFrom(DbSqlContext ctx, SqlJoinType joinType);
}
@@ -633,7 +634,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
}
@Override
void appendFrom(DbSqlContext ctx, boolean forceOuterJoin) {
void appendFrom(DbSqlContext ctx, SqlJoinType joinType) {
}
@Override
@@ -729,11 +730,11 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
}
@Override
void appendFrom(DbSqlContext ctx, boolean forceOuterJoin) {
void appendFrom(DbSqlContext ctx, SqlJoinType joinType) {
if (targetInheritInfo != null) {
// add join to support the discriminator column
String relativePrefix = ctx.getRelativePrefix(name);
tableJoin.addJoin(forceOuterJoin, relativePrefix, ctx);
tableJoin.addJoin(joinType, relativePrefix, ctx);
}
}
@@ -822,10 +823,10 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
}
@Override
void appendFrom(DbSqlContext ctx, boolean forceOuterJoin) {
void appendFrom(DbSqlContext ctx, SqlJoinType joinType) {
String relativePrefix = ctx.getRelativePrefix(getName());
tableJoin.addJoin(forceOuterJoin, relativePrefix, ctx);
tableJoin.addJoin(joinType, relativePrefix, ctx);
}
}
@@ -1,5 +1,7 @@
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebeaninternal.server.query.SqlJoinType;
/**
* Used to provide context during sql construction.
*/
@@ -72,7 +74,7 @@ public interface DbSqlContext {
* Append a Sql Formula join. This converts the "${ta}" keyword to the current
* table alias.
*/
public void appendFormulaJoin(String sqlFormulaJoin, boolean forceOuterJoin);
public void appendFormulaJoin(String sqlFormulaJoin, SqlJoinType joinType);
/**
* Return the current content length.
@@ -10,6 +10,7 @@ import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoinColumn;
import com.avaje.ebeaninternal.server.query.SplitName;
import com.avaje.ebeaninternal.server.query.SqlBeanLoad;
import com.avaje.ebeaninternal.server.query.SqlJoinType;
/**
* Represents a join to another table.
@@ -32,9 +33,9 @@ public final class TableJoin {
private final String table;
/**
* The type of join. LEFT OUTER etc.
* The type of join as per deployment (cardinality and optionality).
*/
private final String type;
private final SqlJoinType type;
/**
* The persist cascade info.
@@ -60,7 +61,7 @@ public final class TableJoin {
this.importedPrimaryKey = deploy.isImportedPrimaryKey();
this.table = InternString.intern(deploy.getTable());
this.type = InternString.intern(deploy.getType());
this.type = deploy.getType();
this.cascadeInfo = deploy.getCascadeInfo();
this.inheritInfo = deploy.getInheritInfo();
@@ -149,7 +150,7 @@ public final class TableJoin {
/**
* Return the type of join. LEFT OUTER JOIN etc.
*/
public String getType() {
public SqlJoinType getType() {
return type;
}
@@ -157,32 +158,26 @@ public final class TableJoin {
* Return true if this join is a left outer join.
*/
public boolean isOuterJoin() {
return type.equals(LEFT_OUTER);
return type == SqlJoinType.OUTER;
}
public boolean addJoin(boolean forceOuterJoin, String prefix, DbSqlContext ctx) {
public SqlJoinType addJoin(SqlJoinType joinType, String prefix, DbSqlContext ctx) {
String[] names = SplitName.split(prefix);
String a1 = ctx.getTableAlias(names[0]);
String a2 = ctx.getTableAlias(prefix);
return addJoin(forceOuterJoin, a1, a2, ctx);
return addJoin(joinType, a1, a2, ctx);
}
public boolean addJoin(boolean forceOuterJoin, String a1, String a2, DbSqlContext ctx) {
public SqlJoinType addJoin(SqlJoinType joinType, String a1, String a2, DbSqlContext ctx) {
String inheritance = inheritInfo != null ? inheritInfo.getWhere() : null;
ctx.addJoin(forceOuterJoin?LEFT_OUTER:type, table, columns(), a1, a2, inheritance);
String joinLiteral = joinType.getLiteral(type);
ctx.addJoin(joinLiteral, table, columns(), a1, a2, inheritance);
return forceOuterJoin || LEFT_OUTER.equals(type);
}
/**
* Explicitly add a (non-outer) join.
*/
public void addInnerJoin(String a1, String a2, DbSqlContext ctx) {
String inheritance = inheritInfo != null ? inheritInfo.getWhere() : null;
ctx.addJoin(JOIN, table, columns(), a1, a2, inheritance);
return joinType.autoToOuter(type);
}
}
@@ -9,6 +9,7 @@ import com.avaje.ebeaninternal.server.deploy.BeanCascadeInfo;
import com.avaje.ebeaninternal.server.deploy.BeanTable;
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
import com.avaje.ebeaninternal.server.deploy.TableJoin;
import com.avaje.ebeaninternal.server.query.SqlJoinType;
/**
* Represents a join to another table during deployment phase.
@@ -32,7 +33,7 @@ public class DeployTableJoin {
/**
* The type of join. LEFT OUTER etc.
*/
private String type = TableJoin.JOIN;
private SqlJoinType type = SqlJoinType.INNER;
/**
* The list of properties mapped to this joined table.
@@ -162,7 +163,7 @@ public class DeployTableJoin {
/**
* Return the type of join. LEFT OUTER JOIN etc.
*/
public String getType() {
public SqlJoinType getType() {
return type;
}
@@ -170,7 +171,11 @@ public class DeployTableJoin {
* Return true if this join is a left outer join.
*/
public boolean isOuterJoin() {
return type.equals(TableJoin.LEFT_OUTER);
return type == SqlJoinType.OUTER;
}
private void setType(SqlJoinType type) {
this.type = type;
}
/**
@@ -179,13 +184,13 @@ public class DeployTableJoin {
public void setType(String joinType) {
joinType = joinType.toUpperCase();
if (joinType.equalsIgnoreCase(TableJoin.JOIN)) {
type = TableJoin.JOIN;
type = SqlJoinType.INNER;
} else if (joinType.indexOf("LEFT") > -1) {
type = TableJoin.LEFT_OUTER;
type = SqlJoinType.OUTER;
} else if (joinType.indexOf("OUTER") > -1) {
type = TableJoin.LEFT_OUTER;
type = SqlJoinType.OUTER;
} else if (joinType.indexOf("INNER") > -1) {
type = TableJoin.JOIN;
type = SqlJoinType.INNER;
} else {
throw new RuntimeException(Message.msg("join.type.unknown", joinType));
}