Allow null discriminator values when adding class conditions on outer joins.

git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@443447 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
A. Abram White 2006-09-14 19:36:09 +00:00
parent fcd072a2c5
commit a5d552f940
7 changed files with 56 additions and 27 deletions

View File

@ -367,7 +367,7 @@ public class JDBCStoreManager
throws SQLException {
Select sel = _sql.newSelect();
if (!select(sel, mapping, subs, sm, null, fetch,
JDBCFetchConfiguration.EAGER_JOIN, true))
JDBCFetchConfiguration.EAGER_JOIN, true, false))
return null;
sel.wherePrimaryKey(sm.getObjectId(), mapping, this);
@ -463,8 +463,8 @@ public class JDBCStoreManager
//### object that only creates a real select when actually used?
Select sel = _sql.newSelect();
if (select(sel, mapping, sel.SUBS_EXACT, sm, fields, jfetch,
EagerFetchModes.EAGER_JOIN, true)) {
if (select(sel, mapping, Select.SUBS_EXACT, sm, fields, jfetch,
EagerFetchModes.EAGER_JOIN, true, false)) {
sel.wherePrimaryKey(sm.getObjectId(), mapping, this);
res = sel.execute(this, jfetch, lockLevel);
try {
@ -854,18 +854,20 @@ public class JDBCStoreManager
* @param eager eager fetch mode to use
* @param ident whether to select primary key columns as distinct
* identifiers
* @param outer whether we're outer-joining to this type
* @return true if the select is required, false otherwise
*/
public boolean select(Select sel, ClassMapping mapping, int subs,
OpenJPAStateManager sm, BitSet fields, JDBCFetchConfiguration fetch,
int eager, boolean ident) {
int eager, boolean ident, boolean outer) {
// add class conditions so that they're cloned for any batched selects
boolean joinedSupers = false;
if ((sm == null || sm.getPCState() == PCState.TRANSIENT)
&& (subs == sel.SUBS_JOINABLE || subs == sel.SUBS_NONE)) {
&& (subs == Select.SUBS_JOINABLE || subs == Select.SUBS_NONE)) {
loadSubclasses(mapping);
Joins joins = (outer) ? sel.newOuterJoins() : null;
joinedSupers = mapping.getDiscriminator().addClassConditions(sel,
subs == sel.SUBS_JOINABLE, null);
subs == Select.SUBS_JOINABLE, joins);
}
// create all our eager selects so that those fields are reserved
@ -889,7 +891,7 @@ public class JDBCStoreManager
fetch.traverseJDBC(eagerToMany), eager);
// optionally select subclass mappings
if (subs == sel.SUBS_JOINABLE || subs == sel.SUBS_ANY_JOINABLE)
if (subs == Select.SUBS_JOINABLE || subs == Select.SUBS_ANY_JOINABLE)
selectSubclassMappings(sel, mapping, sm, fetch);
if (sm != null)
sel.setDistinct(false);

View File

@ -126,20 +126,29 @@ public abstract class InValueDiscriminatorStrategy
if (subs.length == 0 && base.getJoinablePCSuperclassMapping() == null)
return null;
// if not selecting subclasses, limit to just the given class
Column col = disc.getColumns()[0];
SQLBuffer sql = new SQLBuffer(sel.getConfiguration().
getDBDictionaryInstance());
sql.append(sel.getColumnAlias(col, joins));
if (!subclasses || subs.length == 0)
boolean outer = joins != null && joins.isOuter();
if (outer)
sql.append("(");
String alias = sel.getColumnAlias(col, joins);
sql.append(alias);
// if not selecting subclasses, limit to just the given class
if (!outer && (!subclasses || subs.length == 0))
return sql.append(" = ").appendValue(getDiscriminatorValue(base),
col);
if (outer)
sql.append(" IS ").appendValue(null).append(" OR ").append(alias);
sql.append(" IN (");
sql.appendValue(getDiscriminatorValue(base), col);
for (int i = 0; i < subs.length; i++)
sql.append(", ").appendValue(getDiscriminatorValue(subs[i]), col);
sql.append(")");
if (outer)
sql.append(")");
return sql;
}
}

View File

@ -810,6 +810,10 @@ public abstract class AbstractResult
return true;
}
public boolean isOuter() {
return false;
}
public Joins crossJoin(Table localTable, Table foreignTable) {
return this;
}

View File

@ -31,6 +31,11 @@ public interface Joins {
*/
public boolean isEmpty();
/**
* Whether this joins path results in outer joins.
*/
public boolean isOuter();
/**
* Perform a cross join on the given tables.
*/

View File

@ -810,6 +810,10 @@ public class LogicalUnion
return sel.newJoins();
}
public Joins newOuterJoins() {
return sel.newOuterJoins();
}
public void append(SQLBuffer buf, Joins joins) {
sel.append(buf, joins);
}

View File

@ -652,6 +652,11 @@ public interface Select
*/
public Joins newJoins();
/**
* Return a new instance to use for outer joining.
*/
public Joins newOuterJoins();
/**
* Append the given joins to the given buffer.
*/

View File

@ -759,7 +759,7 @@ public class SelectImpl
// delegate to store manager to select in same order it loads result
((JDBCStoreManager) store).select(wrapper, mapping, subclasses, null,
null, fetch, eager, ident);
null, fetch, eager, ident, (_flags & OUTER) != 0);
// reset
if (hasJoins)
@ -1626,6 +1626,10 @@ public class SelectImpl
return this;
}
public Joins newOuterJoins() {
return ((PathJoins) newJoins()).setOuter(true);
}
public void append(SQLBuffer buf, Joins joins) {
if (joins == null || joins.isEmpty())
return;
@ -1744,10 +1748,9 @@ public class SelectImpl
return joins;
// record that this is an outer join set, even if it's empty
PathJoins pj = (PathJoins) joins;
pj.setOuter(true);
if (joins.isEmpty())
return joins;
PathJoins pj = ((PathJoins) joins).setOuter(true);
if (pj.isEmpty())
return pj;
Join join;
Join rec;
@ -1928,7 +1931,8 @@ public class SelectImpl
return false;
}
public void setOuter(boolean outer) {
public PathJoins setOuter(boolean outer) {
return new SelectJoins(this).setOuter(true);
}
public boolean isDirty() {
@ -1994,14 +1998,12 @@ public class SelectImpl
* Represents a SQL string selected with null id.
*/
private static class NullId {
}
/**
* Represents a placeholder SQL string.
*/
private static class Placeholder {
}
/**
@ -2269,7 +2271,8 @@ public class SelectImpl
return false;
}
public void setOuter(boolean outer) {
public PathJoins setOuter(boolean outer) {
return this;
}
public boolean isDirty() {
@ -2345,7 +2348,8 @@ public class SelectImpl
return false;
}
public void setOuter(boolean outer) {
public PathJoins setOuter(boolean outer) {
return this;
}
public boolean isDirty() {
@ -2452,8 +2456,9 @@ public class SelectImpl
return _outer;
}
public void setOuter(boolean outer) {
public PathJoins setOuter(boolean outer) {
_outer = outer;
return this;
}
public boolean isDirty() {
@ -2796,15 +2801,10 @@ public class SelectImpl
interface PathJoins
extends Joins {
/**
* Return whether this join set ended with an outer join.
*/
public boolean isOuter();
/**
* Mark this as an outer joins set.
*/
public void setOuter(boolean outer);
public PathJoins setOuter(boolean outer);
/**
* Return true if this instance has a path, any joins, or a variable.