mirror of https://github.com/apache/openjpa.git
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:
parent
fcd072a2c5
commit
a5d552f940
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -810,6 +810,10 @@ public abstract class AbstractResult
|
|||
return true;
|
||||
}
|
||||
|
||||
public boolean isOuter() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Joins crossJoin(Table localTable, Table foreignTable) {
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue