mirror of https://github.com/apache/openjpa.git
OPENJPA-2099: Reuse internal select by parameter rebinding
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1229690 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
6289157f9c
commit
2846f873c2
|
@ -39,10 +39,10 @@ import org.apache.openjpa.jdbc.sql.Joins;
|
||||||
import org.apache.openjpa.jdbc.sql.Result;
|
import org.apache.openjpa.jdbc.sql.Result;
|
||||||
import org.apache.openjpa.jdbc.sql.Select;
|
import org.apache.openjpa.jdbc.sql.Select;
|
||||||
import org.apache.openjpa.jdbc.sql.SelectExecutor;
|
import org.apache.openjpa.jdbc.sql.SelectExecutor;
|
||||||
|
import org.apache.openjpa.jdbc.sql.SelectImpl;
|
||||||
import org.apache.openjpa.jdbc.sql.Union;
|
import org.apache.openjpa.jdbc.sql.Union;
|
||||||
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
import org.apache.openjpa.kernel.OpenJPAStateManager;
|
||||||
import org.apache.openjpa.kernel.StateManagerImpl;
|
import org.apache.openjpa.kernel.StateManagerImpl;
|
||||||
import org.apache.openjpa.lib.util.Localizer;
|
|
||||||
import org.apache.openjpa.meta.ClassMetaData;
|
import org.apache.openjpa.meta.ClassMetaData;
|
||||||
import org.apache.openjpa.meta.JavaTypes;
|
import org.apache.openjpa.meta.JavaTypes;
|
||||||
import org.apache.openjpa.util.ChangeTracker;
|
import org.apache.openjpa.util.ChangeTracker;
|
||||||
|
@ -60,9 +60,11 @@ import org.apache.openjpa.util.Proxy;
|
||||||
*
|
*
|
||||||
* @author Abe White
|
* @author Abe White
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("serial")
|
||||||
public abstract class StoreCollectionFieldStrategy
|
public abstract class StoreCollectionFieldStrategy
|
||||||
extends ContainerFieldStrategy {
|
extends ContainerFieldStrategy {
|
||||||
|
protected SelectExecutor _executor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the foreign key used to join to the owning field for the given
|
* Return the foreign key used to join to the owning field for the given
|
||||||
* element mapping from {@link #getIndependentElementMappings} (or null).
|
* element mapping from {@link #getIndependentElementMappings} (or null).
|
||||||
|
@ -94,8 +96,7 @@ public abstract class StoreCollectionFieldStrategy
|
||||||
*
|
*
|
||||||
* @see FieldMapping#joinRelation
|
* @see FieldMapping#joinRelation
|
||||||
*/
|
*/
|
||||||
protected abstract Joins joinElementRelation(Joins joins,
|
protected abstract Joins joinElementRelation(Joins joins, ClassMapping elem);
|
||||||
ClassMapping elem);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Join to the owning field table for the given element mapping from
|
* Join to the owning field table for the given element mapping from
|
||||||
|
@ -112,9 +113,9 @@ public abstract class StoreCollectionFieldStrategy
|
||||||
* Convert the field value to a collection. Handles collections and
|
* Convert the field value to a collection. Handles collections and
|
||||||
* arrays by default.
|
* arrays by default.
|
||||||
*/
|
*/
|
||||||
protected Collection toCollection(Object val) {
|
protected Collection<?> toCollection(Object val) {
|
||||||
if (field.getTypeCode() == JavaTypes.COLLECTION)
|
if (field.getTypeCode() == JavaTypes.COLLECTION)
|
||||||
return (Collection) val;
|
return (Collection<?>) val;
|
||||||
return JavaTypes.toList(val, field.getElement().getType(), false);
|
return JavaTypes.toList(val, field.getElement().getType(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +160,7 @@ public abstract class StoreCollectionFieldStrategy
|
||||||
final ClassMapping[] elems = getIndependentElementMappings(true);
|
final ClassMapping[] elems = getIndependentElementMappings(true);
|
||||||
Union union = (Union) sel;
|
Union union = (Union) sel;
|
||||||
if (fetch.getSubclassFetchMode(field.getElementMapping().
|
if (fetch.getSubclassFetchMode(field.getElementMapping().
|
||||||
getTypeMapping()) != fetch.EAGER_JOIN)
|
getTypeMapping()) != JDBCFetchConfiguration.EAGER_JOIN)
|
||||||
union.abortUnion();
|
union.abortUnion();
|
||||||
union.select(new Union.Selector() {
|
union.select(new Union.Selector() {
|
||||||
public void select(Select sel, int idx) {
|
public void select(Select sel, int idx) {
|
||||||
|
@ -180,8 +181,7 @@ public abstract class StoreCollectionFieldStrategy
|
||||||
if (fetch.hasFetchInnerJoin(field.getFullName(false)))
|
if (fetch.hasFetchInnerJoin(field.getFullName(false)))
|
||||||
outer = false;
|
outer = false;
|
||||||
selectEager(sel, getDefaultElementMapping(true), sm, store, fetch,
|
selectEager(sel, getDefaultElementMapping(true), sm, store, fetch,
|
||||||
JDBCFetchConfiguration.EAGER_JOIN, false,
|
JDBCFetchConfiguration.EAGER_JOIN, false, outer);
|
||||||
outer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEagerSelectToMany() {
|
public boolean isEagerSelectToMany() {
|
||||||
|
@ -194,7 +194,7 @@ public abstract class StoreCollectionFieldStrategy
|
||||||
private void selectEager(Select sel, ClassMapping elem,
|
private void selectEager(Select sel, ClassMapping elem,
|
||||||
OpenJPAStateManager sm, JDBCStore store, JDBCFetchConfiguration fetch,
|
OpenJPAStateManager sm, JDBCStore store, JDBCFetchConfiguration fetch,
|
||||||
int eagerMode, boolean selectOid, boolean outer) {
|
int eagerMode, boolean selectOid, boolean outer) {
|
||||||
// force distinct if there was a to-many join to avoid dups, but
|
// force distinct if there was a to-many join to avoid duplicates, but
|
||||||
// if this is a parallel select don't make distinct based on the
|
// if this is a parallel select don't make distinct based on the
|
||||||
// eager joins alone if the original wasn't distinct
|
// eager joins alone if the original wasn't distinct
|
||||||
if (eagerMode == JDBCFetchConfiguration.EAGER_PARALLEL) {
|
if (eagerMode == JDBCFetchConfiguration.EAGER_PARALLEL) {
|
||||||
|
@ -214,8 +214,7 @@ public abstract class StoreCollectionFieldStrategy
|
||||||
joins = join(joins, elem);
|
joins = join(joins, elem);
|
||||||
|
|
||||||
// order, ref cols
|
// order, ref cols
|
||||||
if (field.getOrderColumn() != null || field.getOrders().length > 0
|
if (field.getOrderColumn() != null || field.getOrders().length > 0 || !selectOid) {
|
||||||
|| !selectOid) {
|
|
||||||
if (outer)
|
if (outer)
|
||||||
joins = sel.outer(joins);
|
joins = sel.outer(joins);
|
||||||
if (!selectOid) {
|
if (!selectOid) {
|
||||||
|
@ -360,14 +359,11 @@ public abstract class StoreCollectionFieldStrategy
|
||||||
// get the StateManager of this toMany value
|
// get the StateManager of this toMany value
|
||||||
// and find the value of the inverse mappedBy field (Customer)
|
// and find the value of the inverse mappedBy field (Customer)
|
||||||
// for this toMacdny field
|
// for this toMacdny field
|
||||||
PersistenceCapable pc = (PersistenceCapable)
|
PersistenceCapable pc = (PersistenceCapable)((Collection) coll).iterator().next();
|
||||||
((Collection) coll).iterator().next();
|
OpenJPAStateManager sm1 = (OpenJPAStateManager) pc.pcGetStateManager();
|
||||||
OpenJPAStateManager sm1 = (OpenJPAStateManager) pc.
|
|
||||||
pcGetStateManager();
|
|
||||||
|
|
||||||
ClassMapping clm = ((ClassMapping) sm1.getMetaData());
|
ClassMapping clm = ((ClassMapping) sm1.getMetaData());
|
||||||
FieldMapping fm = (FieldMapping) clm.getField(
|
FieldMapping fm = (FieldMapping) clm.getField(mappedByFieldMapping.getName());
|
||||||
mappedByFieldMapping.getName());
|
|
||||||
if (fm == mappedByFieldMapping)
|
if (fm == mappedByFieldMapping)
|
||||||
res.setMappedByValue(sm1.fetchObject(fm.getIndex()));
|
res.setMappedByValue(sm1.fetchObject(fm.getIndex()));
|
||||||
} else {
|
} else {
|
||||||
|
@ -513,8 +509,7 @@ public abstract class StoreCollectionFieldStrategy
|
||||||
Result res = sel.execute(store, fetch);
|
Result res = sel.execute(store, fetch);
|
||||||
try {
|
try {
|
||||||
res.next();
|
res.next();
|
||||||
coll.getChangeTracker().setNextSequence
|
coll.getChangeTracker().setNextSequence(res.getInt(field) + 1);
|
||||||
(res.getInt(field) + 1);
|
|
||||||
} finally {
|
} finally {
|
||||||
res.close();
|
res.close();
|
||||||
}
|
}
|
||||||
|
@ -522,17 +517,20 @@ public abstract class StoreCollectionFieldStrategy
|
||||||
sm.storeObjectField(field.getIndex(), coll);
|
sm.storeObjectField(field.getIndex(), coll);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// select data for this state manager
|
||||||
// select data for this sm
|
|
||||||
final ClassMapping[] elems = getIndependentElementMappings(true);
|
final ClassMapping[] elems = getIndependentElementMappings(true);
|
||||||
final Joins[] resJoins = new Joins[Math.max(1, elems.length)];
|
final Joins[] resJoins = new Joins[Math.max(1, elems.length)];
|
||||||
Union union = store.getSQLFactory().newUnion
|
Union union;
|
||||||
(Math.max(1, elems.length));
|
if (_executor == null) {
|
||||||
|
union = store.getSQLFactory().newUnion(Math.max(1, elems.length));
|
||||||
|
_executor = union;
|
||||||
|
} else {
|
||||||
|
union = (Union)_executor;
|
||||||
|
}
|
||||||
union.select(new Union.Selector() {
|
union.select(new Union.Selector() {
|
||||||
public void select(Select sel, int idx) {
|
public void select(Select sel, int idx) {
|
||||||
ClassMapping elem = (elems.length == 0) ? null : elems[idx];
|
ClassMapping elem = (elems.length == 0) ? null : elems[idx];
|
||||||
resJoins[idx] = selectAll(sel, elem, sm, store, fetch,
|
resJoins[idx] = selectAll(sel, elem, sm, store, fetch, JDBCFetchConfiguration.EAGER_PARALLEL);
|
||||||
JDBCFetchConfiguration.EAGER_PARALLEL);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -555,8 +553,7 @@ public abstract class StoreCollectionFieldStrategy
|
||||||
if (ct != null && field.getOrderColumn() != null)
|
if (ct != null && field.getOrderColumn() != null)
|
||||||
seq = res.getInt(field.getOrderColumn());
|
seq = res.getInt(field.getOrderColumn());
|
||||||
setMappedBy(sm.getObjectId(), sm, coll, res);
|
setMappedBy(sm.getObjectId(), sm, coll, res);
|
||||||
add(store, coll, loadElement(sm, store, fetch, res,
|
add(store, coll, loadElement(sm, store, fetch, res, resJoins[res.indexOf()]));
|
||||||
resJoins[res.indexOf()]));
|
|
||||||
}
|
}
|
||||||
if (ct != null && field.getOrderColumn() != null)
|
if (ct != null && field.getOrderColumn() != null)
|
||||||
ct.setNextSequence(seq + 1);
|
ct.setNextSequence(seq + 1);
|
||||||
|
@ -565,11 +562,12 @@ public abstract class StoreCollectionFieldStrategy
|
||||||
}
|
}
|
||||||
|
|
||||||
// set into sm
|
// set into sm
|
||||||
if (field.getTypeCode() == JavaTypes.ARRAY)
|
if (field.getTypeCode() == JavaTypes.ARRAY) {
|
||||||
sm.storeObject(field.getIndex(), JavaTypes.toArray
|
sm.storeObject(field.getIndex(), JavaTypes.toArray
|
||||||
((Collection) coll, field.getElement().getType()));
|
((Collection) coll, field.getElement().getType()));
|
||||||
else
|
} else {
|
||||||
sm.storeObject(field.getIndex(), coll);
|
sm.storeObject(field.getIndex(), coll);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -581,13 +579,17 @@ public abstract class StoreCollectionFieldStrategy
|
||||||
ForeignKey fk = getJoinForeignKey(elem);
|
ForeignKey fk = getJoinForeignKey(elem);
|
||||||
Object oid = getObjectIdForJoin(fk, sm);
|
Object oid = getObjectIdForJoin(fk, sm);
|
||||||
sel.whereForeignKey(fk, oid, field.getDefiningMapping(), store);
|
sel.whereForeignKey(fk, oid, field.getDefiningMapping(), store);
|
||||||
|
Joins joins;
|
||||||
// order first, then select so that if the projection introduces
|
if (!sel.isReadOnly()) {
|
||||||
// additional ordering, it will be after our required ordering
|
// order first, then select so that if the projection introduces
|
||||||
field.orderLocal(sel, elem, null);
|
// additional ordering, it will be after our required ordering
|
||||||
Joins joins = joinElementRelation(sel.newJoins(), elem);
|
field.orderLocal(sel, elem, null);
|
||||||
field.orderRelation(sel, elem, joins);
|
joins = joinElementRelation(sel.newJoins(), elem);
|
||||||
selectElement(sel, elem, store, fetch, eagerMode, joins);
|
field.orderRelation(sel, elem, joins);
|
||||||
|
selectElement(sel, elem, store, fetch, eagerMode, joins);
|
||||||
|
} else {
|
||||||
|
joins = joinElementRelation(sel.newJoins(), elem);
|
||||||
|
}
|
||||||
return joins;
|
return joins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -624,4 +626,8 @@ public abstract class StoreCollectionFieldStrategy
|
||||||
}
|
}
|
||||||
return oid;
|
return oid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return getClass().getSimpleName() + '[' + field.getName() + ']';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ public abstract class AbstractResult
|
||||||
|
|
||||||
private static final Joins JOINS = new NoOpJoins();
|
private static final Joins JOINS = new NoOpJoins();
|
||||||
|
|
||||||
private Map _eager = null;
|
private Map<Object,Object> _eager = null;
|
||||||
private ClassMapping _base = null;
|
private ClassMapping _base = null;
|
||||||
private int _index = 0;
|
private int _index = 0;
|
||||||
private boolean _gotEager = false;
|
private boolean _gotEager = false;
|
||||||
|
@ -86,14 +86,14 @@ public abstract class AbstractResult
|
||||||
private Object _mappedByValue = null;
|
private Object _mappedByValue = null;
|
||||||
|
|
||||||
public Object getEager(FieldMapping key) {
|
public Object getEager(FieldMapping key) {
|
||||||
Map map = getEagerMap(true);
|
Map<Object,Object> map = getEagerMap(true);
|
||||||
return (map == null) ? null : map.get(key);
|
return (map == null) ? null : map.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putEager(FieldMapping key, Object res) {
|
public void putEager(FieldMapping key, Object res) {
|
||||||
Map map = getEagerMap(false);
|
Map<Object,Object> map = getEagerMap(false);
|
||||||
if (map == null) {
|
if (map == null) {
|
||||||
map = new HashMap();
|
map = new HashMap<Object,Object>();
|
||||||
setEagerMap(map);
|
setEagerMap(map);
|
||||||
}
|
}
|
||||||
map.put(key, res);
|
map.put(key, res);
|
||||||
|
@ -104,7 +104,7 @@ public abstract class AbstractResult
|
||||||
*
|
*
|
||||||
* @param client whether the client is accessing eager information
|
* @param client whether the client is accessing eager information
|
||||||
*/
|
*/
|
||||||
protected Map getEagerMap(boolean client) {
|
protected Map<Object,Object> getEagerMap(boolean client) {
|
||||||
if (client)
|
if (client)
|
||||||
_gotEager = true;
|
_gotEager = true;
|
||||||
return _eager;
|
return _eager;
|
||||||
|
@ -113,7 +113,7 @@ public abstract class AbstractResult
|
||||||
/**
|
/**
|
||||||
* Raw eager information.
|
* Raw eager information.
|
||||||
*/
|
*/
|
||||||
protected void setEagerMap(Map eager) {
|
protected void setEagerMap(Map<Object,Object> eager) {
|
||||||
_eager = eager;
|
_eager = eager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,11 +129,9 @@ public abstract class AbstractResult
|
||||||
/**
|
/**
|
||||||
* Close all results in eager map.
|
* Close all results in eager map.
|
||||||
*/
|
*/
|
||||||
protected void closeEagerMap(Map eager) {
|
protected void closeEagerMap(Map<Object,Object> eager) {
|
||||||
if (eager != null) {
|
if (eager != null) {
|
||||||
Object res;
|
for (Object res : eager.values()) {
|
||||||
for (Iterator itr = eager.values().iterator(); itr.hasNext();) {
|
|
||||||
res = itr.next();
|
|
||||||
if (res != this && res instanceof Closeable)
|
if (res != this && res instanceof Closeable)
|
||||||
try {
|
try {
|
||||||
((Closeable) res).close();
|
((Closeable) res).close();
|
||||||
|
@ -891,9 +889,6 @@ public abstract class AbstractResult
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void appendTo(SQLBuffer buf) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public Joins setCorrelatedVariable(String var) {
|
public Joins setCorrelatedVariable(String var) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -904,5 +899,10 @@ public abstract class AbstractResult
|
||||||
|
|
||||||
public void moveJoinsToParent() {
|
public void moveJoinsToParent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StringBuilder path() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,9 +39,9 @@ class JoinSet {
|
||||||
// efficient representation with O(1) lookup, add, remove operations for
|
// efficient representation with O(1) lookup, add, remove operations for
|
||||||
// typical sets of joins, and it means we'd have to create a graph anyway
|
// typical sets of joins, and it means we'd have to create a graph anyway
|
||||||
// when joinIterator() is called
|
// when joinIterator() is called
|
||||||
private final List _graph = new ArrayList();
|
private final List<Node> _graph = new ArrayList<Node>();
|
||||||
private int _size = 0;
|
private int _size = 0;
|
||||||
private List _sorted = null;
|
private List<Join> _sorted = null;
|
||||||
|
|
||||||
public JoinSet() {
|
public JoinSet() {
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ class JoinSet {
|
||||||
if (copy._graph.get(i) == null)
|
if (copy._graph.get(i) == null)
|
||||||
_graph.add(null);
|
_graph.add(null);
|
||||||
else
|
else
|
||||||
_graph.add(((Node) copy._graph.get(i)).clone());
|
_graph.add((Node) copy._graph.get(i).clone());
|
||||||
}
|
}
|
||||||
_size = copy._size;
|
_size = copy._size;
|
||||||
_sorted = copy._sorted;
|
_sorted = copy._sorted;
|
||||||
|
@ -95,23 +95,22 @@ class JoinSet {
|
||||||
/**
|
/**
|
||||||
* Iterator over joins that prepares them for SQL translation.
|
* Iterator over joins that prepares them for SQL translation.
|
||||||
*/
|
*/
|
||||||
public Iterator joinIterator() {
|
public Iterator<Join> joinIterator() {
|
||||||
if (_size < 2)
|
if (_size < 2)
|
||||||
return iterator();
|
return iterator();
|
||||||
if (_sorted != null)
|
if (_sorted != null)
|
||||||
return _sorted.iterator();
|
return _sorted.iterator();
|
||||||
|
|
||||||
List sorted = new ArrayList(_size);
|
List<Join> sorted = new ArrayList<Join>(_size);
|
||||||
LinkedList queue = new LinkedList();
|
LinkedList<Node> queue = new LinkedList<Node>();
|
||||||
BitSet seen = new BitSet(_graph.size() * _graph.size()
|
BitSet seen = new BitSet(_graph.size() * _graph.size() + _graph.size());
|
||||||
+ _graph.size());
|
|
||||||
|
|
||||||
// traverse graph
|
// traverse graph
|
||||||
Node n;
|
Node n;
|
||||||
int idx, sidx;
|
int idx, sidx;
|
||||||
for (int i = 0; i < _graph.size(); i++) {
|
for (int i = 0; i < _graph.size(); i++) {
|
||||||
// seed queue with next set of disconnected joins
|
// seed queue with next set of disconnected joins
|
||||||
for (n = (Node) _graph.get(i); n != null; n = n.next) {
|
for (n = _graph.get(i); n != null; n = n.next) {
|
||||||
sidx = getSeenIndex(n.join);
|
sidx = getSeenIndex(n.join);
|
||||||
if (!seen.get(sidx)) {
|
if (!seen.get(sidx)) {
|
||||||
seen.set(sidx);
|
seen.set(sidx);
|
||||||
|
@ -183,8 +182,8 @@ class JoinSet {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
boolean added = false;
|
boolean added = false;
|
||||||
for (Iterator itr = js.iterator(); itr.hasNext();)
|
for (Iterator<Join> itr = js.iterator(); itr.hasNext();)
|
||||||
added = add((Join) itr.next()) || added;
|
added = add(itr.next()) || added;
|
||||||
return added;
|
return added;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,8 +217,8 @@ class JoinSet {
|
||||||
_size++;
|
_size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator iterator() {
|
public Iterator<Join> iterator() {
|
||||||
return new Iterator() {
|
return new Iterator<Join>() {
|
||||||
private Node _next = null;
|
private Node _next = null;
|
||||||
private int _idx = -1;
|
private int _idx = -1;
|
||||||
|
|
||||||
|
@ -237,7 +236,7 @@ class JoinSet {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object next() {
|
public Join next() {
|
||||||
if (!hasNext())
|
if (!hasNext())
|
||||||
throw new NoSuchElementException();
|
throw new NoSuchElementException();
|
||||||
Join j = _next.join;
|
Join j = _next.join;
|
||||||
|
@ -289,16 +288,16 @@ class JoinSet {
|
||||||
|
|
||||||
public boolean removeAll(JoinSet js) {
|
public boolean removeAll(JoinSet js) {
|
||||||
boolean remd = false;
|
boolean remd = false;
|
||||||
for (Iterator itr = js.iterator(); itr.hasNext();)
|
for (Iterator<Join> itr = js.iterator(); itr.hasNext();)
|
||||||
remd = remove((Join) itr.next()) || remd;
|
remd = remove(itr.next()) || remd;
|
||||||
return remd;
|
return remd;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean retainAll(JoinSet js) {
|
public boolean retainAll(JoinSet js) {
|
||||||
boolean remd = false;
|
boolean remd = false;
|
||||||
Join join;
|
Join join;
|
||||||
for (Iterator itr = iterator(); itr.hasNext();) {
|
for (Iterator<Join> itr = iterator(); itr.hasNext();) {
|
||||||
join = (Join) itr.next();
|
join = itr.next();
|
||||||
if (!js.contains(join))
|
if (!js.contains(join))
|
||||||
remd = remove(join);
|
remd = remove(join);
|
||||||
}
|
}
|
||||||
|
@ -318,8 +317,8 @@ class JoinSet {
|
||||||
public boolean containsAll(JoinSet js) {
|
public boolean containsAll(JoinSet js) {
|
||||||
if (js._size > _size || js._graph.size() > _graph.size())
|
if (js._size > _size || js._graph.size() > _graph.size())
|
||||||
return false;
|
return false;
|
||||||
for (Iterator itr = js.iterator(); itr.hasNext();)
|
for (Iterator<Join> itr = js.iterator(); itr.hasNext();)
|
||||||
if (!contains((Join) itr.next()))
|
if (!contains(itr.next()))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -347,7 +346,7 @@ class JoinSet {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder buf = new StringBuilder();
|
StringBuilder buf = new StringBuilder();
|
||||||
buf.append("[");
|
buf.append("[");
|
||||||
for (Iterator itr = iterator(); itr.hasNext();) {
|
for (Iterator<Join> itr = iterator(); itr.hasNext();) {
|
||||||
buf.append("<").append(itr.next()).append(">");
|
buf.append("<").append(itr.next()).append(">");
|
||||||
if (itr.hasNext())
|
if (itr.hasNext())
|
||||||
buf.append(", ");
|
buf.append(", ");
|
||||||
|
|
|
@ -102,4 +102,10 @@ public interface Joins {
|
||||||
* Move joins that belong to subquery's parent
|
* Move joins that belong to subquery's parent
|
||||||
*/
|
*/
|
||||||
public void moveJoinsToParent();
|
public void moveJoinsToParent();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current path as a mutable string.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public StringBuilder path();
|
||||||
}
|
}
|
||||||
|
|
|
@ -915,6 +915,10 @@ public class LogicalUnion
|
||||||
public DBDictionary getDictionary() {
|
public DBDictionary getDictionary() {
|
||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isReadOnly() {
|
||||||
|
return sel.isReadOnly();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -584,4 +584,25 @@ public final class SQLBuffer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binds the given value to a parameter representing the given column.
|
||||||
|
* The column must be bound before this call.
|
||||||
|
* @param o a parameter value
|
||||||
|
* @param col a column to which the value is to be bound
|
||||||
|
* @return this same buffer
|
||||||
|
* @exception IllegalArgumentException is no parameter represents the given column
|
||||||
|
*/
|
||||||
|
public SQLBuffer bind(Object o, Column col) {
|
||||||
|
boolean bound = false;
|
||||||
|
for (int i = 0; i < _params.size(); i++) {
|
||||||
|
BindParameter param = _params.get(i);
|
||||||
|
if (param.getColumn() == col) {
|
||||||
|
param.setValue(o);
|
||||||
|
bound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!bound)
|
||||||
|
throw new IllegalArgumentException("Column " + col + " does not exist to bind " + o);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -751,22 +751,42 @@ public interface Select
|
||||||
/**
|
/**
|
||||||
* Set joined table metadatas for polymorphic queries
|
* Set joined table metadatas for polymorphic queries
|
||||||
*/
|
*/
|
||||||
public void setJoinedTableClassMeta(List meta);
|
public void setJoinedTableClassMeta(List<ClassMapping> meta);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get joined table metadatas for polymorphic queries
|
* get joined table metadatas for polymorphic queries
|
||||||
*/
|
*/
|
||||||
public List getJoinedTableClassMeta();
|
public List<ClassMapping> getJoinedTableClassMeta();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set joined table metadatas excluded for polymorphic queries
|
* Set joined table metadatas excluded for polymorphic queries
|
||||||
*/
|
*/
|
||||||
public void setExcludedJoinedTableClassMeta(List meta);
|
public void setExcludedJoinedTableClassMeta(List<ClassMapping> meta);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get joined table metadatas excluded for polymorphic queries
|
* get joined table metadatas excluded for polymorphic queries
|
||||||
*/
|
*/
|
||||||
public List getExcludedJoinedTableClassMeta();
|
public List<ClassMapping> getExcludedJoinedTableClassMeta();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the database dictionary used by this select to form the target SQL
|
||||||
|
* statement.
|
||||||
|
*
|
||||||
|
* @return the immutable database dictionary.
|
||||||
|
*/
|
||||||
public DBDictionary getDictionary() ;
|
public DBDictionary getDictionary() ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Affirms if this select is structurally immutable.
|
||||||
|
* A select becomes immutable upon {@link #execute(JDBCStore, JDBCFetchConfiguration) execution}.
|
||||||
|
* There is no explicit way to turn a select into read-only status.
|
||||||
|
* <br>
|
||||||
|
* The immutable contract does not prevent {@link SQLBuffer#bind(Object, Column) binding}
|
||||||
|
* new values to {@link BindParameter parameters}.
|
||||||
|
*
|
||||||
|
* @return false on construction, true after execution.
|
||||||
|
*
|
||||||
|
* @since 2.2.0
|
||||||
|
*/
|
||||||
|
boolean isReadOnly();
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,6 @@ import java.util.Stack;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import org.apache.commons.collections.iterators.EmptyIterator;
|
import org.apache.commons.collections.iterators.EmptyIterator;
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
|
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
|
||||||
import org.apache.openjpa.jdbc.kernel.EagerFetchModes;
|
import org.apache.openjpa.jdbc.kernel.EagerFetchModes;
|
||||||
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
|
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
|
||||||
|
@ -117,15 +116,15 @@ public class SelectImpl
|
||||||
// field of type Address:
|
// field of type Address:
|
||||||
// 'address.street' should map to a different table alias than
|
// 'address.street' should map to a different table alias than
|
||||||
// 'parent.address.street' for the purposes of comparisons
|
// 'parent.address.street' for the purposes of comparisons
|
||||||
private Map _aliases = null;
|
private Map<Object,Integer> _aliases = null;
|
||||||
|
|
||||||
// map of indexes to table aliases like 'TABLENAME t0'
|
// map of indexes to table aliases like 'TABLENAME t0'
|
||||||
private SortedMap _tables = null;
|
private SortedMap<Integer,String> _tables = null;
|
||||||
|
|
||||||
// combined list of selected ids and map of each id to its alias
|
// combined list of selected ids and map of each id to its alias
|
||||||
protected final Selects _selects = newSelects();
|
protected final Selects _selects = newSelects();
|
||||||
private List _ordered = null;
|
private List<Object> _ordered = null;
|
||||||
private List _grouped = null;
|
private List<Object> _grouped = null;
|
||||||
|
|
||||||
// flags
|
// flags
|
||||||
private int _flags = 0;
|
private int _flags = 0;
|
||||||
|
@ -147,15 +146,15 @@ public class SelectImpl
|
||||||
// joins to add to the end of our where clause, and joins to prepend to
|
// joins to add to the end of our where clause, and joins to prepend to
|
||||||
// all selects (see select(classmapping) method)
|
// all selects (see select(classmapping) method)
|
||||||
private SelectJoins _joins = null;
|
private SelectJoins _joins = null;
|
||||||
private Stack _preJoins = null;
|
private Stack<PathJoins> _preJoins = null;
|
||||||
|
|
||||||
// map of joins+keys to eager selects and global set of eager keys; the
|
// map of joins+keys to eager selects and global set of eager keys; the
|
||||||
// same key can't be used more than once
|
// same key can't be used more than once
|
||||||
private Map _eager = null;
|
private Map<Object,SelectExecutor> _eager = null;
|
||||||
private Set _eagerKeys = null;
|
private Set<FieldMapping> _eagerKeys = null;
|
||||||
|
|
||||||
// subselect support
|
// subselect support
|
||||||
private List<SelectImpl> _subsels = null;
|
private List<Select> _subsels = null;
|
||||||
private SelectImpl _parent = null;
|
private SelectImpl _parent = null;
|
||||||
private String _subPath = null;
|
private String _subPath = null;
|
||||||
private boolean _hasSub = false;
|
private boolean _hasSub = false;
|
||||||
|
@ -170,8 +169,10 @@ public class SelectImpl
|
||||||
// A path navigation is begin with this schema alias
|
// A path navigation is begin with this schema alias
|
||||||
private String _schemaAlias = null;
|
private String _schemaAlias = null;
|
||||||
private ClassMapping _tpcMeta = null;
|
private ClassMapping _tpcMeta = null;
|
||||||
private List _joinedTables = null;
|
private List<ClassMapping> _joinedTables = null;
|
||||||
private List _exJoinedTables = null;
|
private List<ClassMapping> _exJoinedTables = null;
|
||||||
|
|
||||||
|
private boolean _readOnly = false;
|
||||||
|
|
||||||
public ClassMapping getTablePerClassMeta() {
|
public ClassMapping getTablePerClassMeta() {
|
||||||
return _tpcMeta;
|
return _tpcMeta;
|
||||||
|
@ -180,19 +181,19 @@ public class SelectImpl
|
||||||
_tpcMeta = meta;
|
_tpcMeta = meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setJoinedTableClassMeta(List meta) {
|
public void setJoinedTableClassMeta(List<ClassMapping> meta) {
|
||||||
_joinedTables = meta;
|
_joinedTables = meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List getJoinedTableClassMeta() {
|
public List<ClassMapping> getJoinedTableClassMeta() {
|
||||||
return _joinedTables;
|
return _joinedTables;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setExcludedJoinedTableClassMeta(List meta) {
|
public void setExcludedJoinedTableClassMeta(List<ClassMapping> meta) {
|
||||||
_exJoinedTables = meta;
|
_exJoinedTables = meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List getExcludedJoinedTableClassMeta() {
|
public List<ClassMapping> getExcludedJoinedTableClassMeta() {
|
||||||
return _exJoinedTables;
|
return _exJoinedTables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,10 +342,8 @@ public class SelectImpl
|
||||||
public boolean hasMultipleSelects() {
|
public boolean hasMultipleSelects() {
|
||||||
if (_eager == null)
|
if (_eager == null)
|
||||||
return false;
|
return false;
|
||||||
Map.Entry entry;
|
for (Iterator<Map.Entry<Object,SelectExecutor>> itr = _eager.entrySet().iterator(); itr.hasNext();) {
|
||||||
for (Iterator itr = _eager.entrySet().iterator(); itr.hasNext();) {
|
if (itr.next().getValue() != this)
|
||||||
entry = (Map.Entry) itr.next();
|
|
||||||
if (entry.getValue() != this)
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -429,9 +428,13 @@ public class SelectImpl
|
||||||
try { conn.close(); } catch (SQLException se2) {}
|
try { conn.close(); } catch (SQLException se2) {}
|
||||||
throw se;
|
throw se;
|
||||||
}
|
}
|
||||||
return getEagerResult(conn, stmnt, rs, store, fetch, forUpdate, sql);
|
try {
|
||||||
|
return getEagerResult(conn, stmnt, rs, store, fetch, forUpdate, sql);
|
||||||
|
} finally {
|
||||||
|
makeReadOnly();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute our eager selects, adding the results under the same keys
|
* Execute our eager selects, adding the results under the same keys
|
||||||
* to the given result.
|
* to the given result.
|
||||||
|
@ -443,11 +446,9 @@ public class SelectImpl
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// execute eager selects
|
// execute eager selects
|
||||||
Map.Entry entry;
|
|
||||||
Result eres;
|
Result eres;
|
||||||
Map eager;
|
Map<Object,Object> eager;
|
||||||
for (Iterator itr = sel._eager.entrySet().iterator(); itr.hasNext();) {
|
for (Map.Entry<Object,SelectExecutor> entry : sel._eager.entrySet()) {
|
||||||
entry = (Map.Entry) itr.next();
|
|
||||||
|
|
||||||
// simulated batched selects for inner/outer joins; for separate
|
// simulated batched selects for inner/outer joins; for separate
|
||||||
// selects, don't pass on lock level, because they're probably
|
// selects, don't pass on lock level, because they're probably
|
||||||
|
@ -455,12 +456,11 @@ public class SelectImpl
|
||||||
if (entry.getValue() == sel)
|
if (entry.getValue() == sel)
|
||||||
eres = res;
|
eres = res;
|
||||||
else
|
else
|
||||||
eres = ((SelectExecutor) entry.getValue()).execute(store,
|
eres = entry.getValue().execute(store, fetch);
|
||||||
fetch);
|
|
||||||
|
|
||||||
eager = res.getEagerMap(false);
|
eager = res.getEagerMap(false);
|
||||||
if (eager == null) {
|
if (eager == null) {
|
||||||
eager = new HashMap();
|
eager = new HashMap<Object,Object>();
|
||||||
res.setEagerMap(eager);
|
res.setEagerMap(eager);
|
||||||
}
|
}
|
||||||
eager.put(entry.getKey(), eres);
|
eager.put(entry.getKey(), eres);
|
||||||
|
@ -547,8 +547,10 @@ public class SelectImpl
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List getSubselects() {
|
public List<Select> getSubselects() {
|
||||||
return (_subsels == null) ? Collections.EMPTY_LIST : _subsels;
|
if (_subsels == null)
|
||||||
|
return Collections.emptyList();
|
||||||
|
return _subsels;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Select getParent() {
|
public Select getParent() {
|
||||||
|
@ -579,7 +581,7 @@ public class SelectImpl
|
||||||
_parent = (SelectImpl) parent;
|
_parent = (SelectImpl) parent;
|
||||||
if (_parent != null) {
|
if (_parent != null) {
|
||||||
if (_parent._subsels == null)
|
if (_parent._subsels == null)
|
||||||
_parent._subsels = new ArrayList(2);
|
_parent._subsels = new ArrayList<Select>(2);
|
||||||
_parent._subsels.add(this);
|
_parent._subsels.add(this);
|
||||||
if (_parent._joinSyntax == JoinSyntaxes.SYNTAX_SQL92)
|
if (_parent._joinSyntax == JoinSyntaxes.SYNTAX_SQL92)
|
||||||
_joinSyntax = JoinSyntaxes.SYNTAX_TRADITIONAL;
|
_joinSyntax = JoinSyntaxes.SYNTAX_TRADITIONAL;
|
||||||
|
@ -596,7 +598,7 @@ public class SelectImpl
|
||||||
return _hasSub;
|
return _hasSub;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map getAliases() {
|
public Map<Object,Integer> getAliases() {
|
||||||
return _aliases;
|
return _aliases;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -604,7 +606,7 @@ public class SelectImpl
|
||||||
_aliases.remove(key);
|
_aliases.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map getTables() {
|
public Map<Integer,String> getTables() {
|
||||||
return _tables;
|
return _tables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,19 +643,21 @@ public class SelectImpl
|
||||||
return getTableIndex(table, pj, false) != -1;
|
return getTableIndex(table, pj, false) != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getTableAliases() {
|
public Collection<String> getTableAliases() {
|
||||||
return (_tables == null) ? Collections.EMPTY_SET : _tables.values();
|
if (_tables == null)
|
||||||
|
return Collections.emptySet();
|
||||||
|
return _tables.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List getSelects() {
|
public List<Object> getSelects() {
|
||||||
return Collections.unmodifiableList(_selects);
|
return Collections.unmodifiableList(_selects);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List getSelectAliases() {
|
public List<Object> getSelectAliases() {
|
||||||
return _selects.getAliases(false, _outer != null);
|
return _selects.getAliases(false, _outer != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List getIdentifierAliases() {
|
public List<Object> getIdentifierAliases() {
|
||||||
return _selects.getAliases(true, _outer != null);
|
return _selects.getAliases(true, _outer != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -679,8 +683,8 @@ public class SelectImpl
|
||||||
|
|
||||||
// join set iterator allows concurrent modification
|
// join set iterator allows concurrent modification
|
||||||
Join j;
|
Join j;
|
||||||
for (Iterator itr = _joins.joins().iterator(); itr.hasNext();) {
|
for (Iterator<Join> itr = _joins.joins().iterator(); itr.hasNext();) {
|
||||||
j = (Join) itr.next();
|
j = itr.next();
|
||||||
if (j.getRelationTarget() != null) {
|
if (j.getRelationTarget() != null) {
|
||||||
j.getRelationTarget().getDiscriminator().addClassConditions
|
j.getRelationTarget().getDiscriminator().addClassConditions
|
||||||
(this, j.getSubclasses() == SUBS_JOINABLE,
|
(this, j.getSubclasses() == SUBS_JOINABLE,
|
||||||
|
@ -694,7 +698,7 @@ public class SelectImpl
|
||||||
return _joins;
|
return _joins;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator getJoinIterator() {
|
public Iterator<Join> getJoinIterator() {
|
||||||
if (_joins == null || _joins.isEmpty())
|
if (_joins == null || _joins.isEmpty())
|
||||||
return EmptyIterator.INSTANCE;
|
return EmptyIterator.INSTANCE;
|
||||||
return _joins.joins().joinIterator();
|
return _joins.joins().joinIterator();
|
||||||
|
@ -742,9 +746,9 @@ public class SelectImpl
|
||||||
public String getColumnAlias(Column col, Object path) {
|
public String getColumnAlias(Column col, Object path) {
|
||||||
Table table = col.getTable();
|
Table table = col.getTable();
|
||||||
String tableAlias = null;
|
String tableAlias = null;
|
||||||
Iterator itr = getJoinIterator();
|
Iterator<Join> itr = getJoinIterator();
|
||||||
while (itr.hasNext()) {
|
while (itr.hasNext()) {
|
||||||
Join join = (Join) itr.next();
|
Join join = itr.next();
|
||||||
if (join != null) {
|
if (join != null) {
|
||||||
if (join.getTable1() == table)
|
if (join.getTable1() == table)
|
||||||
tableAlias = join.getAlias1();
|
tableAlias = join.getAlias1();
|
||||||
|
@ -951,6 +955,7 @@ public class SelectImpl
|
||||||
void select(Select wrapper, ClassMapping mapping, int subclasses,
|
void select(Select wrapper, ClassMapping mapping, int subclasses,
|
||||||
JDBCStore store, JDBCFetchConfiguration fetch, int eager,
|
JDBCStore store, JDBCFetchConfiguration fetch, int eager,
|
||||||
Joins joins, boolean ident) {
|
Joins joins, boolean ident) {
|
||||||
|
assertMutable();
|
||||||
// note that this is one case where we don't want to use the result
|
// note that this is one case where we don't want to use the result
|
||||||
// of getJoins(); just use the given joins, which will either be clean
|
// of getJoins(); just use the given joins, which will either be clean
|
||||||
// or the result of previous pre-joins. this way we don't push extra
|
// or the result of previous pre-joins. this way we don't push extra
|
||||||
|
@ -967,7 +972,7 @@ public class SelectImpl
|
||||||
boolean hasJoins = pj != null && pj.isDirty();
|
boolean hasJoins = pj != null && pj.isDirty();
|
||||||
if (hasJoins) {
|
if (hasJoins) {
|
||||||
if (_preJoins == null)
|
if (_preJoins == null)
|
||||||
_preJoins = new Stack();
|
_preJoins = new Stack<PathJoins>();
|
||||||
_preJoins.push(pj);
|
_preJoins.push(pj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1098,6 +1103,7 @@ public class SelectImpl
|
||||||
*/
|
*/
|
||||||
private boolean columnOperation(Column col, boolean sel, Boolean asc,
|
private boolean columnOperation(Column col, boolean sel, Boolean asc,
|
||||||
PathJoins pj, boolean aliasOrder) {
|
PathJoins pj, boolean aliasOrder) {
|
||||||
|
assertMutable();
|
||||||
String as = null;
|
String as = null;
|
||||||
if (asc != null && (aliasOrder || (_flags & RECORD_ORDERED) != 0)) {
|
if (asc != null && (aliasOrder || (_flags & RECORD_ORDERED) != 0)) {
|
||||||
Object id;
|
Object id;
|
||||||
|
@ -1107,7 +1113,7 @@ public class SelectImpl
|
||||||
id = getColumnAlias(col, pj);
|
id = getColumnAlias(col, pj);
|
||||||
if ((_flags & RECORD_ORDERED) != 0) {
|
if ((_flags & RECORD_ORDERED) != 0) {
|
||||||
if (_ordered == null)
|
if (_ordered == null)
|
||||||
_ordered = new ArrayList(5);
|
_ordered = new ArrayList<Object>(5);
|
||||||
_ordered.add(id);
|
_ordered.add(id);
|
||||||
}
|
}
|
||||||
if (aliasOrder) {
|
if (aliasOrder) {
|
||||||
|
@ -1224,6 +1230,7 @@ public class SelectImpl
|
||||||
*/
|
*/
|
||||||
private boolean orderBy(Object sql, boolean asc, Joins joins, boolean sel,
|
private boolean orderBy(Object sql, boolean asc, Joins joins, boolean sel,
|
||||||
boolean aliasOrder, Value selAs) {
|
boolean aliasOrder, Value selAs) {
|
||||||
|
assertMutable();
|
||||||
Object order = sql;
|
Object order = sql;
|
||||||
if (aliasOrder) {
|
if (aliasOrder) {
|
||||||
order = toOrderAlias(_orders++);
|
order = toOrderAlias(_orders++);
|
||||||
|
@ -1231,7 +1238,7 @@ public class SelectImpl
|
||||||
}
|
}
|
||||||
if ((_flags & RECORD_ORDERED) != 0) {
|
if ((_flags & RECORD_ORDERED) != 0) {
|
||||||
if (_ordered == null)
|
if (_ordered == null)
|
||||||
_ordered = new ArrayList(5);
|
_ordered = new ArrayList<Object>(5);
|
||||||
_ordered.add(selAs == null ? sql : selAs);
|
_ordered.add(selAs == null ? sql : selAs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1284,10 +1291,10 @@ public class SelectImpl
|
||||||
* Return the indexes in the select list of all items we're ordering
|
* Return the indexes in the select list of all items we're ordering
|
||||||
* by, or null if none. For use with unions.
|
* by, or null if none. For use with unions.
|
||||||
*/
|
*/
|
||||||
List getOrderedIndexes() {
|
List<Integer> getOrderedIndexes() {
|
||||||
if (_ordered == null)
|
if (_ordered == null)
|
||||||
return null;
|
return null;
|
||||||
List idxs = new ArrayList(_ordered.size());
|
List<Integer> idxs = new ArrayList<Integer>(_ordered.size());
|
||||||
for (int i = 0; i < _ordered.size(); i++)
|
for (int i = 0; i < _ordered.size(); i++)
|
||||||
idxs.add(_selects.indexOf(_ordered.get(i)));
|
idxs.add(_selects.indexOf(_ordered.get(i)));
|
||||||
return idxs;
|
return idxs;
|
||||||
|
@ -1376,15 +1383,16 @@ public class SelectImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SQLBuffer buf = new SQLBuffer(_dict);
|
SQLBuffer buf = isReadOnly() ? _where : new SQLBuffer(_dict);
|
||||||
Object[] params = getBindParameter(oid, mapping, toCols, fromCols, pj, store);
|
Object[] params = getBindParameter(oid, mapping, toCols, fromCols, pj, store);
|
||||||
bindParameter(buf, params, fromCols, pj);
|
bindParameter(buf, params, fromCols, pj);
|
||||||
|
|
||||||
if (constCols != null && constCols.length > 0) {
|
if (constCols != null && constCols.length > 0) {
|
||||||
bindParameter(buf, vals, constCols, pj);
|
bindParameter(buf, vals, constCols, pj);
|
||||||
}
|
}
|
||||||
|
if (buf != _where) {
|
||||||
where(buf, pj);
|
where(buf, pj);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1423,16 +1431,26 @@ public class SelectImpl
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binds the parameters to the given SQL buffer.
|
* Binds the parameters to the given SQL buffer.
|
||||||
* @param buf
|
* @param buf a sql buffer
|
||||||
* @param params
|
* @param params the parameter values to bind
|
||||||
* @param fromCols
|
* @param fromCols the corresponding columns to which the parameters bind. Same size of the values.
|
||||||
* @param pj
|
* @param pj the joins, if any, for the columns
|
||||||
*/
|
*/
|
||||||
void bindParameter(SQLBuffer buf, Object[] params, Column[] fromCols, PathJoins pj) {
|
void bindParameter(SQLBuffer buf, Object[] params, Column[] fromCols, PathJoins pj) {
|
||||||
|
if (isReadOnly()) {
|
||||||
|
for (int i = 0; i < params.length; i++) {
|
||||||
|
buf.bind(params[i], fromCols[i]);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (int i = 0; i < params.length; i++) {
|
for (int i = 0; i < params.length; i++) {
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
buf.append(" AND ");
|
buf.append(" AND ");
|
||||||
buf.append(getColumnAlias(fromCols[i], pj));
|
buf.append(getColumnAlias(fromCols[i], pj));
|
||||||
|
// WARNING: Potential bug hides here
|
||||||
|
// A parameter value appearing as null and non-null in two binding operation
|
||||||
|
// will expose this bug. Requires more structure to BindParameter to accept
|
||||||
|
// an opcode.
|
||||||
buf.append(params[i] == null ? " IS " : " = ");
|
buf.append(params[i] == null ? " IS " : " = ");
|
||||||
buf.appendValue(params[i], fromCols[i]);
|
buf.appendValue(params[i], fromCols[i]);
|
||||||
}
|
}
|
||||||
|
@ -1551,7 +1569,7 @@ public class SelectImpl
|
||||||
if (_grouped == null || !_grouped.contains(sql)) {
|
if (_grouped == null || !_grouped.contains(sql)) {
|
||||||
if (_grouping == null) {
|
if (_grouping == null) {
|
||||||
_grouping = new SQLBuffer(_dict);
|
_grouping = new SQLBuffer(_dict);
|
||||||
_grouped = new ArrayList();
|
_grouped = new ArrayList<Object>();
|
||||||
} else
|
} else
|
||||||
_grouping.append(", ");
|
_grouping.append(", ");
|
||||||
|
|
||||||
|
@ -1590,7 +1608,7 @@ public class SelectImpl
|
||||||
private boolean isGrouping() {
|
private boolean isGrouping() {
|
||||||
return (_flags & GROUPING) != 0;
|
return (_flags & GROUPING) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the joins to use for column aliases, etc.
|
* Return the joins to use for column aliases, etc.
|
||||||
*
|
*
|
||||||
|
@ -1602,7 +1620,7 @@ public class SelectImpl
|
||||||
boolean pre = (pj == null || !pj.isDirty())
|
boolean pre = (pj == null || !pj.isDirty())
|
||||||
&& _preJoins != null && !_preJoins.isEmpty();
|
&& _preJoins != null && !_preJoins.isEmpty();
|
||||||
if (pre)
|
if (pre)
|
||||||
pj = (PathJoins) _preJoins.peek();
|
pj = (PathJoins)_preJoins.peek();
|
||||||
|
|
||||||
if (pj == null || !pj.isDirty())
|
if (pj == null || !pj.isDirty())
|
||||||
pj = _joins;
|
pj = _joins;
|
||||||
|
@ -1641,9 +1659,9 @@ public class SelectImpl
|
||||||
sel._joinSyntax = _joinSyntax;
|
sel._joinSyntax = _joinSyntax;
|
||||||
sel._schemaAlias = _schemaAlias;
|
sel._schemaAlias = _schemaAlias;
|
||||||
if (_aliases != null)
|
if (_aliases != null)
|
||||||
sel._aliases = new HashMap(_aliases);
|
sel._aliases = new HashMap<Object,Integer>(_aliases);
|
||||||
if (_tables != null)
|
if (_tables != null)
|
||||||
sel._tables = new TreeMap(_tables);
|
sel._tables = new TreeMap<Integer,String>(_tables);
|
||||||
if (_joins != null)
|
if (_joins != null)
|
||||||
sel._joins = _joins.clone(sel);
|
sel._joins = _joins.clone(sel);
|
||||||
if (_where != null)
|
if (_where != null)
|
||||||
|
@ -1653,7 +1671,7 @@ public class SelectImpl
|
||||||
sel._from._outer = sel;
|
sel._from._outer = sel;
|
||||||
}
|
}
|
||||||
if (_subsels != null) {
|
if (_subsels != null) {
|
||||||
sel._subsels = new ArrayList(_subsels.size());
|
sel._subsels = new ArrayList<Select>(_subsels.size());
|
||||||
SelectImpl sub, selSub;
|
SelectImpl sub, selSub;
|
||||||
for (int j = 0; j < _subsels.size(); j++) {
|
for (int j = 0; j < _subsels.size(); j++) {
|
||||||
sub = (SelectImpl) _subsels.get(j);
|
sub = (SelectImpl) _subsels.get(j);
|
||||||
|
@ -1717,7 +1735,7 @@ public class SelectImpl
|
||||||
|
|
||||||
// global set of eager keys
|
// global set of eager keys
|
||||||
if (_eagerKeys == null)
|
if (_eagerKeys == null)
|
||||||
_eagerKeys = new HashSet();
|
_eagerKeys = new HashSet<FieldMapping>();
|
||||||
_eagerKeys.add(key);
|
_eagerKeys.add(key);
|
||||||
|
|
||||||
SelectExecutor sel;
|
SelectExecutor sel;
|
||||||
|
@ -1737,7 +1755,7 @@ public class SelectImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_eager == null)
|
if (_eager == null)
|
||||||
_eager = new HashMap();
|
_eager = new HashMap<Object,SelectExecutor>();
|
||||||
_eager.put(toEagerKey(key, getJoins(null, false)), sel);
|
_eager.put(toEagerKey(key, getJoins(null, false)), sel);
|
||||||
return sel;
|
return sel;
|
||||||
}
|
}
|
||||||
|
@ -1750,9 +1768,8 @@ public class SelectImpl
|
||||||
sel._flags &= ~NONAUTO_DISTINCT;
|
sel._flags &= ~NONAUTO_DISTINCT;
|
||||||
sel._eagerKeys = _eagerKeys;
|
sel._eagerKeys = _eagerKeys;
|
||||||
if (_preJoins != null && !_preJoins.isEmpty()) {
|
if (_preJoins != null && !_preJoins.isEmpty()) {
|
||||||
sel._preJoins = new Stack();
|
sel._preJoins = new Stack<PathJoins>();
|
||||||
sel._preJoins.push(((SelectJoins) _preJoins.peek()).
|
sel._preJoins.push(((SelectJoins) _preJoins.peek()).clone(sel));
|
||||||
clone(sel));
|
|
||||||
}
|
}
|
||||||
return sel;
|
return sel;
|
||||||
}
|
}
|
||||||
|
@ -1760,7 +1777,7 @@ public class SelectImpl
|
||||||
/**
|
/**
|
||||||
* Return view of eager selects. May be null.
|
* Return view of eager selects. May be null.
|
||||||
*/
|
*/
|
||||||
public Map getEagerMap() {
|
public Map<Object,SelectExecutor> getEagerMap() {
|
||||||
return _eager;
|
return _eager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1809,9 +1826,9 @@ public class SelectImpl
|
||||||
if (!buf.isEmpty())
|
if (!buf.isEmpty())
|
||||||
buf.append(" AND ");
|
buf.append(" AND ");
|
||||||
Join join = null;
|
Join join = null;
|
||||||
for (Iterator itr = ((PathJoins) joins).joins().joinIterator();
|
for (Iterator<Join> itr = ((PathJoins) joins).joins().joinIterator();
|
||||||
itr.hasNext();) {
|
itr.hasNext();) {
|
||||||
join = (Join) itr.next();
|
join = itr.next();
|
||||||
switch (_joinSyntax) {
|
switch (_joinSyntax) {
|
||||||
case JoinSyntaxes.SYNTAX_TRADITIONAL:
|
case JoinSyntaxes.SYNTAX_TRADITIONAL:
|
||||||
buf.append(_dict.toTraditionalJoin(join));
|
buf.append(_dict.toTraditionalJoin(join));
|
||||||
|
@ -1936,8 +1953,8 @@ public class SelectImpl
|
||||||
Join join;
|
Join join;
|
||||||
Join rec;
|
Join rec;
|
||||||
boolean hasJoins = _joins != null && _joins.joins() != null;
|
boolean hasJoins = _joins != null && _joins.joins() != null;
|
||||||
for (Iterator itr = pj.joins().iterator(); itr.hasNext();) {
|
for (Iterator<Join> itr = pj.joins().iterator(); itr.hasNext();) {
|
||||||
join = (Join) itr.next();
|
join = itr.next();
|
||||||
if (join.getType() == Join.TYPE_INNER) {
|
if (join.getType() == Join.TYPE_INNER) {
|
||||||
if (!hasJoins)
|
if (!hasJoins)
|
||||||
join.setType(Join.TYPE_OUTER);
|
join.setType(Join.TYPE_OUTER);
|
||||||
|
@ -1969,8 +1986,8 @@ public class SelectImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
Join join;
|
Join join;
|
||||||
for (Iterator itr = pj.joins().iterator(); itr.hasNext();) {
|
for (Iterator<Join> itr = pj.joins().iterator(); itr.hasNext();) {
|
||||||
join = (Join) itr.next();
|
join = itr.next();
|
||||||
if (join.getType() == Join.TYPE_INNER) {
|
if (join.getType() == Join.TYPE_INNER) {
|
||||||
if (join.getForeignKey() != null
|
if (join.getForeignKey() != null
|
||||||
&& !_dict.canOuterJoin(_joinSyntax, join.getForeignKey())) {
|
&& !_dict.canOuterJoin(_joinSyntax, join.getForeignKey())) {
|
||||||
|
@ -1999,7 +2016,7 @@ public class SelectImpl
|
||||||
Integer i = null;
|
Integer i = null;
|
||||||
Object key = table.getFullIdentifier().getName();
|
Object key = table.getFullIdentifier().getName();
|
||||||
if (pj != null && pj.path() != null)
|
if (pj != null && pj.path() != null)
|
||||||
key = new Key(pj.getPathStr(), key);
|
key = new Key(pj.path().toString(), key);
|
||||||
|
|
||||||
if (_ctx != null && (_parent != null || _subsels != null || _hasSub)) {
|
if (_ctx != null && (_parent != null || _subsels != null || _hasSub)) {
|
||||||
i = findAliasForQuery(table, pj, key, create);
|
i = findAliasForQuery(table, pj, key, create);
|
||||||
|
@ -2067,11 +2084,11 @@ public class SelectImpl
|
||||||
(corrVar == null || (thisCtx != null && ctx() == thisCtx)));
|
(corrVar == null || (thisCtx != null && ctx() == thisCtx)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the alias for the key starting lookup in this instance only.
|
||||||
|
*/
|
||||||
private Integer getAlias(Table table, Object key) {
|
private Integer getAlias(Table table, Object key) {
|
||||||
Integer alias = null;
|
return _aliases == null ? null : _aliases.get(key);
|
||||||
if (_aliases != null)
|
|
||||||
alias = (Integer) _aliases.get(key);
|
|
||||||
return alias;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int createAlias(Table table, Object key) {
|
private int createAlias(Table table, Object key) {
|
||||||
|
@ -2080,21 +2097,16 @@ public class SelectImpl
|
||||||
return i.intValue();
|
return i.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the alias for the key starting lookup in this instance and searching the parents
|
||||||
|
* as well if necessary.
|
||||||
|
*/
|
||||||
private Integer findAlias(Table table, Object key) {
|
private Integer findAlias(Table table, Object key) {
|
||||||
Integer alias = null;
|
Integer alias = getAlias(table, key);
|
||||||
if (_aliases != null) {
|
if (alias != null) {
|
||||||
alias = (Integer) _aliases.get(key);
|
return alias;
|
||||||
if (alias != null) {
|
|
||||||
return alias;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (_parent != null) {
|
return (_parent != null) ? _parent.findAlias(table, key) : null;
|
||||||
alias = _parent.findAlias(table, key);
|
|
||||||
if (alias != null) {
|
|
||||||
return alias;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return alias;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2102,13 +2114,13 @@ public class SelectImpl
|
||||||
*/
|
*/
|
||||||
private void recordTableAlias(Table table, Object key, Integer alias) {
|
private void recordTableAlias(Table table, Object key, Integer alias) {
|
||||||
if (_aliases == null)
|
if (_aliases == null)
|
||||||
_aliases = new HashMap();
|
_aliases = new HashMap<Object,Integer>();
|
||||||
_aliases.put(key, alias);
|
_aliases.put(key, alias);
|
||||||
|
|
||||||
String tableString = _dict.getFullName(table, false) + " "
|
String tableString = _dict.getFullName(table, false) + " "
|
||||||
+ toAlias(alias.intValue());
|
+ toAlias(alias.intValue());
|
||||||
if (_tables == null)
|
if (_tables == null)
|
||||||
_tables = new TreeMap();
|
_tables = new TreeMap<Integer,String>();
|
||||||
_tables.put(alias, tableString);
|
_tables.put(alias, tableString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2122,9 +2134,9 @@ public class SelectImpl
|
||||||
int aliases = (fromParent || _parent == null) ? 0 : _parent.aliasSize(false, this);
|
int aliases = (fromParent || _parent == null) ? 0 : _parent.aliasSize(false, this);
|
||||||
aliases += (_aliases == null) ? 0 : _aliases.size();
|
aliases += (_aliases == null) ? 0 : _aliases.size();
|
||||||
if (_subsels != null) {
|
if (_subsels != null) {
|
||||||
for (SelectImpl sub : _subsels) {
|
for (Select sub : _subsels) {
|
||||||
if (sub != fromSub)
|
if (sub != fromSub)
|
||||||
aliases += sub.aliasSize(true, null);
|
aliases += ((SelectImpl)sub).aliasSize(true, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return aliases;
|
return aliases;
|
||||||
|
@ -2264,10 +2276,6 @@ public class SelectImpl
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return _path + "|" + _key;
|
return _path + "|" + _key;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object getKey() {
|
|
||||||
return _key;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2278,11 +2286,11 @@ public class SelectImpl
|
||||||
implements PathJoins {
|
implements PathJoins {
|
||||||
|
|
||||||
private SelectImpl _sel = null;
|
private SelectImpl _sel = null;
|
||||||
private Map<Column, Object> cachedColumnAlias_ = null;
|
private Map<Column, Object> _cachedColumnAlias = null;
|
||||||
|
|
||||||
// position in selected columns list where we expect the next load
|
// position in selected columns list where we expect the next load
|
||||||
private int _pos = 0;
|
private int _pos = 0;
|
||||||
private Stack _preJoins = null;
|
private Stack<Joins> _preJoins = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
|
@ -2291,7 +2299,7 @@ public class SelectImpl
|
||||||
DBDictionary dict) {
|
DBDictionary dict) {
|
||||||
super(conn, stmnt, rs, dict);
|
super(conn, stmnt, rs, dict);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select for this result.
|
* Select for this result.
|
||||||
*/
|
*/
|
||||||
|
@ -2311,29 +2319,28 @@ public class SelectImpl
|
||||||
// eager results
|
// eager results
|
||||||
if (_sel._eager == null || !_sel._eagerKeys.contains(key))
|
if (_sel._eager == null || !_sel._eagerKeys.contains(key))
|
||||||
return null;
|
return null;
|
||||||
Map map = SelectResult.this.getEagerMap(true);
|
Map<Object,Object> map = SelectResult.this.getEagerMap(true);
|
||||||
if (map == null)
|
if (map == null)
|
||||||
return null;
|
return null;
|
||||||
return map.get(_sel.toEagerKey(key, getJoins(null)));
|
return map.get(SelectImpl.toEagerKey(key, getJoins(null)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putEager(FieldMapping key, Object res) {
|
public void putEager(FieldMapping key, Object res) {
|
||||||
Map map = SelectResult.this.getEagerMap(true);
|
Map<Object,Object> map = SelectResult.this.getEagerMap(true);
|
||||||
if (map == null) {
|
if (map == null) {
|
||||||
map = new HashMap();
|
map = new HashMap<Object,Object>();
|
||||||
setEagerMap(map);
|
setEagerMap(map);
|
||||||
}
|
}
|
||||||
map.put(_sel.toEagerKey(key, getJoins(null)), res);
|
map.put(SelectImpl.toEagerKey(key, getJoins(null)), res);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object load(ClassMapping mapping, JDBCStore store,
|
public Object load(ClassMapping mapping, JDBCStore store,
|
||||||
JDBCFetchConfiguration fetch, Joins joins)
|
JDBCFetchConfiguration fetch, Joins joins)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
boolean hasJoins = joins != null
|
boolean hasJoins = joins != null && ((PathJoins) joins).path() != null;
|
||||||
&& ((PathJoins) joins).path() != null;
|
|
||||||
if (hasJoins) {
|
if (hasJoins) {
|
||||||
if (_preJoins == null)
|
if (_preJoins == null)
|
||||||
_preJoins = new Stack();
|
_preJoins = new Stack<Joins>();
|
||||||
_preJoins.push(joins);
|
_preJoins.push(joins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2362,9 +2369,9 @@ public class SelectImpl
|
||||||
if (pj != null && pj.path() != null) {
|
if (pj != null && pj.path() != null) {
|
||||||
Object columnAlias = getColumnAlias((Column) obj, pj);
|
Object columnAlias = getColumnAlias((Column) obj, pj);
|
||||||
if (joins == null) {
|
if (joins == null) {
|
||||||
if (cachedColumnAlias_ == null)
|
if (_cachedColumnAlias == null)
|
||||||
cachedColumnAlias_ = new HashMap<Column, Object>();
|
_cachedColumnAlias = new HashMap<Column, Object>();
|
||||||
cachedColumnAlias_.put((Column) obj, columnAlias);
|
_cachedColumnAlias.put((Column) obj, columnAlias);
|
||||||
}
|
}
|
||||||
return columnAlias != null && _sel._selects.contains(columnAlias);
|
return columnAlias != null && _sel._selects.contains(columnAlias);
|
||||||
}
|
}
|
||||||
|
@ -2416,8 +2423,8 @@ public class SelectImpl
|
||||||
if (pj != null && pj.path() != null) {
|
if (pj != null && pj.path() != null) {
|
||||||
Column col = (Column) obj;
|
Column col = (Column) obj;
|
||||||
pk = (col.isPrimaryKey()) ? Boolean.TRUE : Boolean.FALSE;
|
pk = (col.isPrimaryKey()) ? Boolean.TRUE : Boolean.FALSE;
|
||||||
if (joins == null && cachedColumnAlias_ != null) {
|
if (joins == null && _cachedColumnAlias != null) {
|
||||||
obj = cachedColumnAlias_.get(col);
|
obj = _cachedColumnAlias.get(col);
|
||||||
if (obj == null)
|
if (obj == null)
|
||||||
obj = getColumnAlias(col, pj);
|
obj = getColumnAlias(col, pj);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2468,6 +2475,8 @@ public class SelectImpl
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the joins to use to find column data.
|
* Return the joins to use to find column data.
|
||||||
|
* If the given join is non-null and has a path then it is returned.
|
||||||
|
* Otherwise, returns the {@link #getPreJoins() pre joins}.
|
||||||
*/
|
*/
|
||||||
private PathJoins getJoins(Joins joins) {
|
private PathJoins getJoins(Joins joins) {
|
||||||
PathJoins pj = (PathJoins) joins;
|
PathJoins pj = (PathJoins) joins;
|
||||||
|
@ -2477,7 +2486,7 @@ public class SelectImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the pre joins for the result, or null if none. Note that
|
* Return the pre joins for this result, or null if none. Note that
|
||||||
* we have to take the Select's pre joins into account too, since
|
* we have to take the Select's pre joins into account too, since
|
||||||
* batched selects can have additional pre joins on the stack even
|
* batched selects can have additional pre joins on the stack even
|
||||||
* on execution.
|
* on execution.
|
||||||
|
@ -2497,15 +2506,14 @@ public class SelectImpl
|
||||||
private String getColumnAlias(Column col, PathJoins pj) {
|
private String getColumnAlias(Column col, PathJoins pj) {
|
||||||
String alias;
|
String alias;
|
||||||
if (_sel._from != null) {
|
if (_sel._from != null) {
|
||||||
alias = _sel.toAlias(_sel._from.getTableIndex
|
alias = SelectImpl.toAlias(_sel._from.getTableIndex(col.getTable(), pj, false));
|
||||||
(col.getTable(), pj, false));
|
|
||||||
if (alias == null)
|
if (alias == null)
|
||||||
return null;
|
return null;
|
||||||
if (_sel._dict.requiresAliasForSubselect)
|
if (_sel._dict.requiresAliasForSubselect)
|
||||||
return FROM_SELECT_ALIAS + "." + alias + "_" + col;
|
return FROM_SELECT_ALIAS + "." + alias + "_" + col;
|
||||||
return alias + "_" + col;
|
return alias + "_" + col;
|
||||||
}
|
}
|
||||||
alias = _sel.toAlias(_sel.getTableIndex(col.getTable(), pj, false));
|
alias = SelectImpl.toAlias(_sel.getTableIndex(col.getTable(), pj, false));
|
||||||
return (alias == null) ? null : alias + "." + col;
|
return (alias == null) ? null : alias + "." + col;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2611,7 +2619,6 @@ public class SelectImpl
|
||||||
protected String correlatedVar = null;
|
protected String correlatedVar = null;
|
||||||
protected Context context = null;
|
protected Context context = null;
|
||||||
protected Context lastContext = null;
|
protected Context lastContext = null;
|
||||||
protected String pathStr = null;
|
|
||||||
|
|
||||||
public Select getSelect() {
|
public Select getSelect() {
|
||||||
return null;
|
return null;
|
||||||
|
@ -2649,10 +2656,6 @@ public class SelectImpl
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getVariable() {
|
|
||||||
return var;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Joins setCorrelatedVariable(String var) {
|
public Joins setCorrelatedVariable(String var) {
|
||||||
this.correlatedVar = var;
|
this.correlatedVar = var;
|
||||||
return this;
|
return this;
|
||||||
|
@ -2716,20 +2719,12 @@ public class SelectImpl
|
||||||
path = new StringBuilder(str);
|
path = new StringBuilder(str);
|
||||||
else
|
else
|
||||||
path.append('.').append(str);
|
path.append('.').append(str);
|
||||||
pathStr = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPathStr() {
|
|
||||||
if (pathStr == null) {
|
|
||||||
pathStr = path.toString();
|
|
||||||
}
|
|
||||||
return pathStr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "PathJoinsImpl<" + hashCode() + ">: "
|
return "PathJoinsImpl<" + hashCode() + ">: " + String.valueOf(path);
|
||||||
+ String.valueOf(path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void moveJoinsToParent() {
|
public void moveJoinsToParent() {
|
||||||
|
@ -2937,25 +2932,24 @@ public class SelectImpl
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object aliases[] = _sel._aliases.values().toArray();
|
Integer aliases[] = _sel._aliases.values().toArray(new Integer[_sel._aliases.size()]);
|
||||||
boolean found1 = false;
|
boolean found1 = false;
|
||||||
boolean found2 = false;
|
boolean found2 = false;
|
||||||
|
|
||||||
for (int i = 0; i < aliases.length; i++) {
|
for (int i = 0; i < aliases.length; i++) {
|
||||||
int alias = ((Integer)aliases[i]).intValue();
|
int alias = aliases[i].intValue();
|
||||||
if (alias == j.getIndex1())
|
if (alias == j.getIndex1())
|
||||||
found1 = true;
|
found1 = true;
|
||||||
if (alias == j.getIndex2())
|
if (alias == j.getIndex2())
|
||||||
found2 = true;
|
found2 = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found1 && found2)
|
if (found1 && found2) {
|
||||||
return;
|
return;
|
||||||
else if (!found1 && !found2) {
|
} else if (!found1 && !found2) {
|
||||||
j.setIsNotMyJoin();
|
j.setIsNotMyJoin();
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
j.setCorrelated();
|
j.setCorrelated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2965,8 +2959,8 @@ public class SelectImpl
|
||||||
return;
|
return;
|
||||||
Join j = null;
|
Join j = null;
|
||||||
List<Join> removed = new ArrayList<Join>(5);
|
List<Join> removed = new ArrayList<Join>(5);
|
||||||
for (Iterator itr = _joins.iterator(); itr.hasNext();) {
|
for (Iterator<Join> itr = _joins.iterator(); itr.hasNext();) {
|
||||||
j = (Join) itr.next();
|
j = itr.next();
|
||||||
if (j.isNotMyJoin()) {
|
if (j.isNotMyJoin()) {
|
||||||
addJoinsToParent(_sel._parent, j);
|
addJoinsToParent(_sel._parent, j);
|
||||||
removed.add(j);
|
removed.add(j);
|
||||||
|
@ -3035,12 +3029,12 @@ public class SelectImpl
|
||||||
* the alias of each selected id.
|
* the alias of each selected id.
|
||||||
*/
|
*/
|
||||||
protected static class Selects
|
protected static class Selects
|
||||||
extends AbstractList {
|
extends AbstractList<Object> {
|
||||||
|
|
||||||
protected List _ids = null;
|
protected List<Object> _ids = null;
|
||||||
protected List _idents = null;
|
protected List<Object> _idents = null;
|
||||||
protected Map _aliases = null;
|
protected Map<Object,Object> _aliases = null;
|
||||||
protected Map _selectAs = null;
|
protected Map<Object,String> _selectAs = null;
|
||||||
protected DBDictionary _dict = null;
|
protected DBDictionary _dict = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3048,22 +3042,22 @@ public class SelectImpl
|
||||||
*/
|
*/
|
||||||
public void addAll(Selects sels) {
|
public void addAll(Selects sels) {
|
||||||
if (_ids == null && sels._ids != null)
|
if (_ids == null && sels._ids != null)
|
||||||
_ids = new ArrayList(sels._ids);
|
_ids = new ArrayList<Object>(sels._ids);
|
||||||
else if (sels._ids != null)
|
else if (sels._ids != null)
|
||||||
_ids.addAll(sels._ids);
|
_ids.addAll(sels._ids);
|
||||||
|
|
||||||
if (_idents == null && sels._idents != null)
|
if (_idents == null && sels._idents != null)
|
||||||
_idents = new ArrayList(sels._idents);
|
_idents = new ArrayList<Object>(sels._idents);
|
||||||
else if (sels._idents != null)
|
else if (sels._idents != null)
|
||||||
_idents.addAll(sels._idents);
|
_idents.addAll(sels._idents);
|
||||||
|
|
||||||
if (_aliases == null && sels._aliases != null)
|
if (_aliases == null && sels._aliases != null)
|
||||||
_aliases = new HashMap(sels._aliases);
|
_aliases = new HashMap<Object,Object>(sels._aliases);
|
||||||
else if (sels._aliases != null)
|
else if (sels._aliases != null)
|
||||||
_aliases.putAll(sels._aliases);
|
_aliases.putAll(sels._aliases);
|
||||||
|
|
||||||
if (_selectAs == null && sels._selectAs != null)
|
if (_selectAs == null && sels._selectAs != null)
|
||||||
_selectAs = new HashMap(sels._selectAs);
|
_selectAs = new HashMap<Object,String>(sels._selectAs);
|
||||||
else if (sels._selectAs != null)
|
else if (sels._selectAs != null)
|
||||||
_selectAs.putAll(sels._selectAs);
|
_selectAs.putAll(sels._selectAs);
|
||||||
}
|
}
|
||||||
|
@ -3080,8 +3074,8 @@ public class SelectImpl
|
||||||
*/
|
*/
|
||||||
public int setAlias(Object id, Object alias, boolean ident) {
|
public int setAlias(Object id, Object alias, boolean ident) {
|
||||||
if (_ids == null) {
|
if (_ids == null) {
|
||||||
_ids = new ArrayList();
|
_ids = new ArrayList<Object>();
|
||||||
_aliases = new HashMap();
|
_aliases = new HashMap<Object,Object>();
|
||||||
}
|
}
|
||||||
|
|
||||||
int idx;
|
int idx;
|
||||||
|
@ -3093,7 +3087,7 @@ public class SelectImpl
|
||||||
|
|
||||||
if (ident) {
|
if (ident) {
|
||||||
if (_idents == null)
|
if (_idents == null)
|
||||||
_idents = new ArrayList(3);
|
_idents = new ArrayList<Object>(3);
|
||||||
_idents.add(id);
|
_idents.add(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3136,11 +3130,11 @@ public class SelectImpl
|
||||||
* A list representation of the aliases, in select order, with
|
* A list representation of the aliases, in select order, with
|
||||||
* AS aliases present.
|
* AS aliases present.
|
||||||
*/
|
*/
|
||||||
public List getAliases(final boolean ident, final boolean inner) {
|
public List<Object> getAliases(final boolean ident, final boolean inner) {
|
||||||
if (_ids == null)
|
if (_ids == null)
|
||||||
return Collections.EMPTY_LIST;
|
return Collections.emptyList();
|
||||||
|
|
||||||
return new AbstractList() {
|
return new AbstractList<Object>() {
|
||||||
public int size() {
|
public int size() {
|
||||||
return (ident && _idents != null) ? _idents.size()
|
return (ident && _idents != null) ? _idents.size()
|
||||||
: _ids.size();
|
: _ids.size();
|
||||||
|
@ -3181,7 +3175,7 @@ public class SelectImpl
|
||||||
*/
|
*/
|
||||||
public void setSelectAs(Object id, String as) {
|
public void setSelectAs(Object id, String as) {
|
||||||
if (_selectAs == null)
|
if (_selectAs == null)
|
||||||
_selectAs = new HashMap((int) (5 * 1.33 + 1));
|
_selectAs = new HashMap<Object,String>((int) (5 * 1.33 + 1));
|
||||||
_selectAs.put(id, as);
|
_selectAs.put(id, as);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3193,7 +3187,7 @@ public class SelectImpl
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Object id;
|
Object id;
|
||||||
for (Iterator itr = _ids.iterator(); itr.hasNext();) {
|
for (Iterator<Object> itr = _ids.iterator(); itr.hasNext();) {
|
||||||
id = itr.next();
|
id = itr.next();
|
||||||
if (id instanceof Placeholder) {
|
if (id instanceof Placeholder) {
|
||||||
itr.remove();
|
itr.remove();
|
||||||
|
@ -3242,6 +3236,30 @@ public class SelectImpl
|
||||||
|
|
||||||
public void moveJoinsToParent() {
|
public void moveJoinsToParent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Affirms if this instance is (structurally) immutable.
|
||||||
|
*/
|
||||||
|
public boolean isReadOnly() {
|
||||||
|
return _readOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks this instance immutable.
|
||||||
|
*/
|
||||||
|
private void makeReadOnly() {
|
||||||
|
_readOnly = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raises illegal state exception if this instance is immutable.
|
||||||
|
*/
|
||||||
|
public void assertMutable() {
|
||||||
|
if (_readOnly) {
|
||||||
|
throw new IllegalStateException("Select@" + Integer.toHexString(System.identityHashCode(this)) +
|
||||||
|
" is read-only");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3283,11 +3301,8 @@ interface PathJoins
|
||||||
public void nullJoins();
|
public void nullJoins();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The select owner of this join
|
* Gets the select who owns this join.
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public Select getSelect();
|
public Select getSelect();
|
||||||
|
|
||||||
public String getPathStr();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue