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 {
|
throws SQLException {
|
||||||
Select sel = _sql.newSelect();
|
Select sel = _sql.newSelect();
|
||||||
if (!select(sel, mapping, subs, sm, null, fetch,
|
if (!select(sel, mapping, subs, sm, null, fetch,
|
||||||
JDBCFetchConfiguration.EAGER_JOIN, true))
|
JDBCFetchConfiguration.EAGER_JOIN, true, false))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
sel.wherePrimaryKey(sm.getObjectId(), mapping, this);
|
sel.wherePrimaryKey(sm.getObjectId(), mapping, this);
|
||||||
|
@ -463,8 +463,8 @@ public class JDBCStoreManager
|
||||||
//### object that only creates a real select when actually used?
|
//### object that only creates a real select when actually used?
|
||||||
|
|
||||||
Select sel = _sql.newSelect();
|
Select sel = _sql.newSelect();
|
||||||
if (select(sel, mapping, sel.SUBS_EXACT, sm, fields, jfetch,
|
if (select(sel, mapping, Select.SUBS_EXACT, sm, fields, jfetch,
|
||||||
EagerFetchModes.EAGER_JOIN, true)) {
|
EagerFetchModes.EAGER_JOIN, true, false)) {
|
||||||
sel.wherePrimaryKey(sm.getObjectId(), mapping, this);
|
sel.wherePrimaryKey(sm.getObjectId(), mapping, this);
|
||||||
res = sel.execute(this, jfetch, lockLevel);
|
res = sel.execute(this, jfetch, lockLevel);
|
||||||
try {
|
try {
|
||||||
|
@ -854,18 +854,20 @@ public class JDBCStoreManager
|
||||||
* @param eager eager fetch mode to use
|
* @param eager eager fetch mode to use
|
||||||
* @param ident whether to select primary key columns as distinct
|
* @param ident whether to select primary key columns as distinct
|
||||||
* identifiers
|
* identifiers
|
||||||
|
* @param outer whether we're outer-joining to this type
|
||||||
* @return true if the select is required, false otherwise
|
* @return true if the select is required, false otherwise
|
||||||
*/
|
*/
|
||||||
public boolean select(Select sel, ClassMapping mapping, int subs,
|
public boolean select(Select sel, ClassMapping mapping, int subs,
|
||||||
OpenJPAStateManager sm, BitSet fields, JDBCFetchConfiguration fetch,
|
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
|
// add class conditions so that they're cloned for any batched selects
|
||||||
boolean joinedSupers = false;
|
boolean joinedSupers = false;
|
||||||
if ((sm == null || sm.getPCState() == PCState.TRANSIENT)
|
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);
|
loadSubclasses(mapping);
|
||||||
|
Joins joins = (outer) ? sel.newOuterJoins() : null;
|
||||||
joinedSupers = mapping.getDiscriminator().addClassConditions(sel,
|
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
|
// create all our eager selects so that those fields are reserved
|
||||||
|
@ -889,7 +891,7 @@ public class JDBCStoreManager
|
||||||
fetch.traverseJDBC(eagerToMany), eager);
|
fetch.traverseJDBC(eagerToMany), eager);
|
||||||
|
|
||||||
// optionally select subclass mappings
|
// 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);
|
selectSubclassMappings(sel, mapping, sm, fetch);
|
||||||
if (sm != null)
|
if (sm != null)
|
||||||
sel.setDistinct(false);
|
sel.setDistinct(false);
|
||||||
|
|
|
@ -126,20 +126,29 @@ public abstract class InValueDiscriminatorStrategy
|
||||||
if (subs.length == 0 && base.getJoinablePCSuperclassMapping() == null)
|
if (subs.length == 0 && base.getJoinablePCSuperclassMapping() == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// if not selecting subclasses, limit to just the given class
|
|
||||||
Column col = disc.getColumns()[0];
|
Column col = disc.getColumns()[0];
|
||||||
SQLBuffer sql = new SQLBuffer(sel.getConfiguration().
|
SQLBuffer sql = new SQLBuffer(sel.getConfiguration().
|
||||||
getDBDictionaryInstance());
|
getDBDictionaryInstance());
|
||||||
sql.append(sel.getColumnAlias(col, joins));
|
boolean outer = joins != null && joins.isOuter();
|
||||||
if (!subclasses || subs.length == 0)
|
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),
|
return sql.append(" = ").appendValue(getDiscriminatorValue(base),
|
||||||
col);
|
col);
|
||||||
|
|
||||||
|
if (outer)
|
||||||
|
sql.append(" IS ").appendValue(null).append(" OR ").append(alias);
|
||||||
sql.append(" IN (");
|
sql.append(" IN (");
|
||||||
sql.appendValue(getDiscriminatorValue(base), col);
|
sql.appendValue(getDiscriminatorValue(base), col);
|
||||||
for (int i = 0; i < subs.length; i++)
|
for (int i = 0; i < subs.length; i++)
|
||||||
sql.append(", ").appendValue(getDiscriminatorValue(subs[i]), col);
|
sql.append(", ").appendValue(getDiscriminatorValue(subs[i]), col);
|
||||||
sql.append(")");
|
sql.append(")");
|
||||||
|
if (outer)
|
||||||
|
sql.append(")");
|
||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -810,6 +810,10 @@ public abstract class AbstractResult
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isOuter() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public Joins crossJoin(Table localTable, Table foreignTable) {
|
public Joins crossJoin(Table localTable, Table foreignTable) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,11 @@ public interface Joins {
|
||||||
*/
|
*/
|
||||||
public boolean isEmpty();
|
public boolean isEmpty();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this joins path results in outer joins.
|
||||||
|
*/
|
||||||
|
public boolean isOuter();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a cross join on the given tables.
|
* Perform a cross join on the given tables.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -810,6 +810,10 @@ public class LogicalUnion
|
||||||
return sel.newJoins();
|
return sel.newJoins();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Joins newOuterJoins() {
|
||||||
|
return sel.newOuterJoins();
|
||||||
|
}
|
||||||
|
|
||||||
public void append(SQLBuffer buf, Joins joins) {
|
public void append(SQLBuffer buf, Joins joins) {
|
||||||
sel.append(buf, joins);
|
sel.append(buf, joins);
|
||||||
}
|
}
|
||||||
|
|
|
@ -652,6 +652,11 @@ public interface Select
|
||||||
*/
|
*/
|
||||||
public Joins newJoins();
|
public Joins newJoins();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new instance to use for outer joining.
|
||||||
|
*/
|
||||||
|
public Joins newOuterJoins();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append the given joins to the given buffer.
|
* 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
|
// delegate to store manager to select in same order it loads result
|
||||||
((JDBCStoreManager) store).select(wrapper, mapping, subclasses, null,
|
((JDBCStoreManager) store).select(wrapper, mapping, subclasses, null,
|
||||||
null, fetch, eager, ident);
|
null, fetch, eager, ident, (_flags & OUTER) != 0);
|
||||||
|
|
||||||
// reset
|
// reset
|
||||||
if (hasJoins)
|
if (hasJoins)
|
||||||
|
@ -1626,6 +1626,10 @@ public class SelectImpl
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Joins newOuterJoins() {
|
||||||
|
return ((PathJoins) newJoins()).setOuter(true);
|
||||||
|
}
|
||||||
|
|
||||||
public void append(SQLBuffer buf, Joins joins) {
|
public void append(SQLBuffer buf, Joins joins) {
|
||||||
if (joins == null || joins.isEmpty())
|
if (joins == null || joins.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
@ -1744,10 +1748,9 @@ public class SelectImpl
|
||||||
return joins;
|
return joins;
|
||||||
|
|
||||||
// record that this is an outer join set, even if it's empty
|
// record that this is an outer join set, even if it's empty
|
||||||
PathJoins pj = (PathJoins) joins;
|
PathJoins pj = ((PathJoins) joins).setOuter(true);
|
||||||
pj.setOuter(true);
|
if (pj.isEmpty())
|
||||||
if (joins.isEmpty())
|
return pj;
|
||||||
return joins;
|
|
||||||
|
|
||||||
Join join;
|
Join join;
|
||||||
Join rec;
|
Join rec;
|
||||||
|
@ -1928,7 +1931,8 @@ public class SelectImpl
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOuter(boolean outer) {
|
public PathJoins setOuter(boolean outer) {
|
||||||
|
return new SelectJoins(this).setOuter(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDirty() {
|
public boolean isDirty() {
|
||||||
|
@ -1994,14 +1998,12 @@ public class SelectImpl
|
||||||
* Represents a SQL string selected with null id.
|
* Represents a SQL string selected with null id.
|
||||||
*/
|
*/
|
||||||
private static class NullId {
|
private static class NullId {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a placeholder SQL string.
|
* Represents a placeholder SQL string.
|
||||||
*/
|
*/
|
||||||
private static class Placeholder {
|
private static class Placeholder {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2269,7 +2271,8 @@ public class SelectImpl
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOuter(boolean outer) {
|
public PathJoins setOuter(boolean outer) {
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDirty() {
|
public boolean isDirty() {
|
||||||
|
@ -2345,7 +2348,8 @@ public class SelectImpl
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOuter(boolean outer) {
|
public PathJoins setOuter(boolean outer) {
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDirty() {
|
public boolean isDirty() {
|
||||||
|
@ -2452,8 +2456,9 @@ public class SelectImpl
|
||||||
return _outer;
|
return _outer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOuter(boolean outer) {
|
public PathJoins setOuter(boolean outer) {
|
||||||
_outer = outer;
|
_outer = outer;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDirty() {
|
public boolean isDirty() {
|
||||||
|
@ -2796,15 +2801,10 @@ public class SelectImpl
|
||||||
interface PathJoins
|
interface PathJoins
|
||||||
extends Joins {
|
extends Joins {
|
||||||
|
|
||||||
/**
|
|
||||||
* Return whether this join set ended with an outer join.
|
|
||||||
*/
|
|
||||||
public boolean isOuter();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark this as an outer joins set.
|
* 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.
|
* Return true if this instance has a path, any joins, or a variable.
|
||||||
|
|
Loading…
Reference in New Issue