You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by fa...@apache.org on 2008/04/09 20:09:49 UTC
svn commit: r646455 - in /openjpa:
branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/
branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/
branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/k...
Author: fancy
Date: Wed Apr 9 11:09:42 2008
New Revision: 646455
URL: http://svn.apache.org/viewvc?rev=646455&view=rev
Log:
OPENJPA-547 INNER JOIN FETCH query incorrectly generates LEFT join SQL
Modified:
openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java
openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java
openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java
openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java
openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java
openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java
openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java
openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java
openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java
openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java
openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
Modified: openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java (original)
+++ openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java Wed Apr 9 11:09:42 2008
@@ -260,4 +260,38 @@
throw translate(re);
}
}
+
+ public Set getFetchInnerJoins() {
+ try {
+ return getJDBCDelegate().getFetchInnerJoins();
+ } catch (RuntimeException re) {
+ throw translate(re);
+ }
+ }
+
+ public boolean hasFetchInnerJoin(String field) {
+ try {
+ return getJDBCDelegate().hasFetchInnerJoin(field);
+ } catch (RuntimeException re) {
+ throw translate(re);
+ }
+ }
+
+ public JDBCFetchConfiguration addFetchInnerJoin(String field) {
+ try {
+ getJDBCDelegate().addFetchInnerJoin(field);
+ return this;
+ } catch (RuntimeException re) {
+ throw translate(re);
+ }
+ }
+
+ public JDBCFetchConfiguration addFetchInnerJoins(Collection fields) {
+ try {
+ getJDBCDelegate().addFetchInnerJoins(fields);
+ return this;
+ } catch (RuntimeException re) {
+ throw translate(re);
+ }
+ }
}
Modified: openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java (original)
+++ openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java Wed Apr 9 11:09:42 2008
@@ -207,4 +207,38 @@
* Convenience method to cast traversal to store-specific type.
*/
public JDBCFetchConfiguration traverseJDBC(FieldMetaData fm);
+
+ /**
+ * Returns the names of the inner fetch joins that this component will use
+ * when loading objects. Defaults to the empty set. This set is not
+ * thread safe.
+ *
+ * @since 1.1
+ */
+ public Set getFetchInnerJoins();
+
+ /**
+ * Return true if the given fully-qualified inner fetch join has been added.
+ *
+ * @since 1.1
+ */
+ public boolean hasFetchInnerJoin(String field);
+
+ /**
+ * Adds <code>field</code> to the set of fully-qualified field names to
+ * eagerly join when loading objects. Each class can have at most
+ * one to-many eagerly joined fields.
+ *
+ * @since 1.1
+ */
+ public JDBCFetchConfiguration addFetchInnerJoin(String field);
+
+ /**
+ * Adds <code>fields</code> to the set of fully-qualified field names to
+ * eagerly join when loading objects. Each class can have at most
+ * one to-many eagerly joined fields.
+ *
+ * @since 1.1
+ */
+ public JDBCFetchConfiguration addFetchInnerJoins(Collection fields);
}
Modified: openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java (original)
+++ openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java Wed Apr 9 11:09:42 2008
@@ -69,6 +69,7 @@
public int size = 0;
public int syntax = 0;
public Set joins = null;
+ public Set fetchInnerJoins = null;
public int isolationLevel = -1;
}
@@ -344,5 +345,38 @@
if (!(conf instanceof JDBCConfiguration))
return null;
return (JDBCConfiguration) conf;
+ }
+
+ public Set getFetchInnerJoins() {
+ return (_state.fetchInnerJoins == null) ? Collections.EMPTY_SET
+ : _state.fetchInnerJoins;
+ }
+
+ public boolean hasFetchInnerJoin(String field) {
+ return _state.fetchInnerJoins != null &&
+ _state.fetchInnerJoins.contains(field);
+ }
+
+ public JDBCFetchConfiguration addFetchInnerJoin(String join) {
+ if (StringUtils.isEmpty(join))
+ throw new UserException(_loc.get("null-join"));
+
+ lock();
+ try {
+ if (_state.fetchInnerJoins == null)
+ _state.fetchInnerJoins = new HashSet();
+ _state.fetchInnerJoins.add(join);
+ } finally {
+ unlock();
+ }
+ return this;
+ }
+
+ public JDBCFetchConfiguration addFetchInnerJoins(Collection joins) {
+ if (joins == null || joins.isEmpty())
+ return this;
+ for (Iterator itr = joins.iterator(); itr.hasNext();)
+ addFetchInnerJoin((String) itr.next());
+ return this;
}
}
Modified: openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java (original)
+++ openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java Wed Apr 9 11:09:42 2008
@@ -150,6 +150,8 @@
fetch.addFields(Arrays.asList(exps[0].fetchPaths));
fetch.addJoins(Arrays.asList(exps[0].fetchPaths));
}
+ if (exps[0].fetchInnerPaths != null)
+ fetch.addFetchInnerJoins(Arrays.asList(exps[0].fetchInnerPaths));
int eager = calculateEagerMode(exps[0], range.start, range.end);
int subclassMode = fetch.getSubclassFetchMode((ClassMapping) base);
@@ -600,6 +602,8 @@
fetch.addFields(Arrays.asList(exps[0].fetchPaths));
fetch.addJoins(Arrays.asList(exps[0].fetchPaths));
}
+ if (exps[0].fetchInnerPaths != null)
+ fetch.addFetchInnerJoins(Arrays.asList(exps[0].fetchInnerPaths));
int eager = calculateEagerMode(exps[0], range.start, range.end);
eager = Math.min(eager, JDBCFetchConfiguration.EAGER_JOIN);
Modified: openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java (original)
+++ openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java Wed Apr 9 11:09:42 2008
@@ -409,9 +409,11 @@
// clone it for a to-many eager select can result in a clone that
// produces invalid SQL
ClassMapping cls = field.getIndependentTypeMappings()[0];
+ boolean forceInner = fetch.hasFetchInnerJoin(field.getFullName(false)) ?
+ true : false;
sel.select(cls, field.getSelectSubclasses(), store, fetch,
JDBCFetchConfiguration.EAGER_JOIN,
- eagerJoin(sel.newJoins(), cls, false));
+ eagerJoin(sel.newJoins(), cls, forceInner));
}
/**
Modified: openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java (original)
+++ openjpa/branches/1.0.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java Wed Apr 9 11:09:42 2008
@@ -24,7 +24,6 @@
import java.util.HashMap;
import java.util.Map;
-import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCStore;
import org.apache.openjpa.jdbc.meta.ClassMapping;
@@ -168,10 +167,13 @@
// we limit further eager fetches to joins, because after this point
// the select has been modified such that parallel clones may produce
// invalid sql
+ boolean outer = field.getNullValue() != FieldMapping.NULL_EXCEPTION;
+ // force inner join for inner join fetch
+ if (fetch.hasFetchInnerJoin(field.getFullName(false)))
+ outer = false;
selectEager(sel, getDefaultElementMapping(true), sm, store, fetch,
JDBCFetchConfiguration.EAGER_JOIN, false,
- field.getNullValue()
- != FieldMapping.NULL_EXCEPTION);
+ outer);
}
public boolean isEagerSelectToMany() {
Modified: openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java (original)
+++ openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java Wed Apr 9 11:09:42 2008
@@ -63,6 +63,7 @@
public int operation = QueryOperations.OP_SELECT;
public ClassMetaData[] accessPath = StoreQuery.EMPTY_METAS;
public String[] fetchPaths = StoreQuery.EMPTY_STRINGS;
+ public String[] fetchInnerPaths = StoreQuery.EMPTY_STRINGS;
public Value[] range = EMPTY_VALUES;
private Boolean _aggregate = null;
Modified: openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java (original)
+++ openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java Wed Apr 9 11:09:42 2008
@@ -440,6 +440,7 @@
// handle JOIN FETCH
Set joins = null;
+ Set innerJoins = null;
JPQLNode[] outers = root().findChildrenByID(JJTOUTERFETCHJOIN);
for (int i = 0; outers != null && i < outers.length; i++)
@@ -447,13 +448,20 @@
add(getPath(onlyChild(outers[i])).last().getFullName(false));
JPQLNode[] inners = root().findChildrenByID(JJTINNERFETCHJOIN);
- for (int i = 0; inners != null && i < inners.length; i++)
- (joins == null ? joins = new TreeSet() : joins).
- add(getPath(onlyChild(inners[i])).last().getFullName(false));
+ for (int i = 0; inners != null && i < inners.length; i++) {
+ String path = getPath(onlyChild(inners[i])).last()
+ .getFullName(false);
+ (joins == null ? joins = new TreeSet() : joins).add(path);
+ (innerJoins == null ? innerJoins = new TreeSet() : innerJoins).
+ add(path);
+ }
if (joins != null)
exps.fetchPaths = (String[]) joins.
toArray(new String[joins.size()]);
+ if (innerJoins != null)
+ exps.fetchInnerPaths = (String[]) innerJoins.
+ toArray(new String[innerJoins.size()]);
return filter;
}
@@ -494,7 +502,7 @@
else if (node.id == JJTINNERJOIN)
exp = addJoin(node, true, exp);
else if (node.id == JJTINNERFETCHJOIN)
- exp = addJoin(node, true, exp);
+ ; // we handle inner fetch joins in the evalFetchJoins() method
else if (node.id == JJTOUTERFETCHJOIN)
; // we handle outer fetch joins in the evalFetchJoins() method
else
Modified: openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java (original)
+++ openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java Wed Apr 9 11:09:42 2008
@@ -260,4 +260,38 @@
throw translate(re);
}
}
+
+ public Set getFetchInnerJoins() {
+ try {
+ return getJDBCDelegate().getFetchInnerJoins();
+ } catch (RuntimeException re) {
+ throw translate(re);
+ }
+ }
+
+ public boolean hasFetchInnerJoin(String field) {
+ try {
+ return getJDBCDelegate().hasFetchInnerJoin(field);
+ } catch (RuntimeException re) {
+ throw translate(re);
+ }
+ }
+
+ public JDBCFetchConfiguration addFetchInnerJoin(String field) {
+ try {
+ getJDBCDelegate().addFetchInnerJoin(field);
+ return this;
+ } catch (RuntimeException re) {
+ throw translate(re);
+ }
+ }
+
+ public JDBCFetchConfiguration addFetchInnerJoins(Collection fields) {
+ try {
+ getJDBCDelegate().addFetchInnerJoins(fields);
+ return this;
+ } catch (RuntimeException re) {
+ throw translate(re);
+ }
+ }
}
Modified: openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java (original)
+++ openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java Wed Apr 9 11:09:42 2008
@@ -207,4 +207,38 @@
* Convenience method to cast traversal to store-specific type.
*/
public JDBCFetchConfiguration traverseJDBC(FieldMetaData fm);
+
+ /**
+ * Returns the names of the inner fetch joins that this component will use
+ * when loading objects. Defaults to the empty set. This set is not
+ * thread safe.
+ *
+ * @since 1.0.3
+ */
+ public Set getFetchInnerJoins();
+
+ /**
+ * Return true if the given fully-qualified inner fetch join has been added.
+ *
+ * @since 1.0.3
+ */
+ public boolean hasFetchInnerJoin(String field);
+
+ /**
+ * Adds <code>field</code> to the set of fully-qualified field names to
+ * eagerly join when loading objects. Each class can have at most
+ * one to-many eagerly joined fields.
+ *
+ * @since 1.0.3
+ */
+ public JDBCFetchConfiguration addFetchInnerJoin(String field);
+
+ /**
+ * Adds <code>fields</code> to the set of fully-qualified field names to
+ * eagerly join when loading objects. Each class can have at most
+ * one to-many eagerly joined fields.
+ *
+ * @since 1.0.3
+ */
+ public JDBCFetchConfiguration addFetchInnerJoins(Collection fields);
}
Modified: openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java (original)
+++ openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java Wed Apr 9 11:09:42 2008
@@ -69,6 +69,7 @@
public int size = 0;
public int syntax = 0;
public Set joins = null;
+ public Set fetchInnerJoins = null;
public int isolationLevel = -1;
}
@@ -344,5 +345,38 @@
if (!(conf instanceof JDBCConfiguration))
return null;
return (JDBCConfiguration) conf;
+ }
+
+ public Set getFetchInnerJoins() {
+ return (_state.fetchInnerJoins == null) ? Collections.EMPTY_SET
+ : _state.fetchInnerJoins;
+ }
+
+ public boolean hasFetchInnerJoin(String field) {
+ return _state.fetchInnerJoins != null &&
+ _state.fetchInnerJoins.contains(field);
+ }
+
+ public JDBCFetchConfiguration addFetchInnerJoin(String join) {
+ if (StringUtils.isEmpty(join))
+ throw new UserException(_loc.get("null-join"));
+
+ lock();
+ try {
+ if (_state.fetchInnerJoins == null)
+ _state.fetchInnerJoins = new HashSet();
+ _state.fetchInnerJoins.add(join);
+ } finally {
+ unlock();
+ }
+ return this;
+ }
+
+ public JDBCFetchConfiguration addFetchInnerJoins(Collection joins) {
+ if (joins == null || joins.isEmpty())
+ return this;
+ for (Iterator itr = joins.iterator(); itr.hasNext();)
+ addFetchInnerJoin((String) itr.next());
+ return this;
}
}
Modified: openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java (original)
+++ openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java Wed Apr 9 11:09:42 2008
@@ -148,6 +148,8 @@
fetch.addFields(Arrays.asList(exps[0].fetchPaths));
fetch.addJoins(Arrays.asList(exps[0].fetchPaths));
}
+ if (exps[0].fetchInnerPaths != null)
+ fetch.addFetchInnerJoins(Arrays.asList(exps[0].fetchInnerPaths));
int eager = calculateEagerMode(exps[0], range.start, range.end);
int subclassMode = fetch.getSubclassFetchMode((ClassMapping) base);
@@ -599,6 +601,8 @@
fetch.addFields(Arrays.asList(exps[0].fetchPaths));
fetch.addJoins(Arrays.asList(exps[0].fetchPaths));
}
+ if (exps[0].fetchInnerPaths != null)
+ fetch.addFetchInnerJoins(Arrays.asList(exps[0].fetchInnerPaths));
int eager = calculateEagerMode(exps[0], range.start, range.end);
eager = Math.min(eager, JDBCFetchConfiguration.EAGER_JOIN);
Modified: openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java (original)
+++ openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java Wed Apr 9 11:09:42 2008
@@ -409,9 +409,11 @@
// clone it for a to-many eager select can result in a clone that
// produces invalid SQL
ClassMapping cls = field.getIndependentTypeMappings()[0];
+ boolean forceInner = fetch.hasFetchInnerJoin(field.getFullName(false)) ?
+ true : false;
sel.select(cls, field.getSelectSubclasses(), store, fetch,
JDBCFetchConfiguration.EAGER_JOIN,
- eagerJoin(sel.newJoins(), cls, false));
+ eagerJoin(sel.newJoins(), cls, forceInner));
}
/**
Modified: openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java (original)
+++ openjpa/branches/1.1.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java Wed Apr 9 11:09:42 2008
@@ -24,7 +24,6 @@
import java.util.HashMap;
import java.util.Map;
-import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCStore;
import org.apache.openjpa.jdbc.meta.ClassMapping;
@@ -168,10 +167,13 @@
// we limit further eager fetches to joins, because after this point
// the select has been modified such that parallel clones may produce
// invalid sql
+ boolean outer = field.getNullValue() != FieldMapping.NULL_EXCEPTION;
+ // force inner join for inner join fetch
+ if (fetch.hasFetchInnerJoin(field.getFullName(false)))
+ outer = false;
selectEager(sel, getDefaultElementMapping(true), sm, store, fetch,
JDBCFetchConfiguration.EAGER_JOIN, false,
- field.getNullValue()
- != FieldMapping.NULL_EXCEPTION);
+ outer);
}
public boolean isEagerSelectToMany() {
Modified: openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java (original)
+++ openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java Wed Apr 9 11:09:42 2008
@@ -65,6 +65,7 @@
public int operation = QueryOperations.OP_SELECT;
public ClassMetaData[] accessPath = StoreQuery.EMPTY_METAS;
public String[] fetchPaths = StoreQuery.EMPTY_STRINGS;
+ public String[] fetchInnerPaths = StoreQuery.EMPTY_STRINGS;
public Value[] range = EMPTY_VALUES;
private Boolean _aggregate = null;
Modified: openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java (original)
+++ openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java Wed Apr 9 11:09:42 2008
@@ -452,6 +452,7 @@
// handle JOIN FETCH
Set joins = null;
+ Set innerJoins = null;
JPQLNode[] outers = root().findChildrenByID(JJTOUTERFETCHJOIN);
for (int i = 0; outers != null && i < outers.length; i++)
@@ -459,13 +460,20 @@
add(getPath(onlyChild(outers[i])).last().getFullName(false));
JPQLNode[] inners = root().findChildrenByID(JJTINNERFETCHJOIN);
- for (int i = 0; inners != null && i < inners.length; i++)
- (joins == null ? joins = new TreeSet() : joins).
- add(getPath(onlyChild(inners[i])).last().getFullName(false));
+ for (int i = 0; inners != null && i < inners.length; i++) {
+ String path = getPath(onlyChild(inners[i])).last()
+ .getFullName(false);
+ (joins == null ? joins = new TreeSet() : joins).add(path);
+ (innerJoins == null ? innerJoins = new TreeSet() : innerJoins).
+ add(path);
+ }
if (joins != null)
exps.fetchPaths = (String[]) joins.
toArray(new String[joins.size()]);
+ if (innerJoins != null)
+ exps.fetchInnerPaths = (String[]) innerJoins.
+ toArray(new String[innerJoins.size()]);
return filter;
}
@@ -506,7 +514,7 @@
else if (node.id == JJTINNERJOIN)
exp = addJoin(node, true, exp);
else if (node.id == JJTINNERFETCHJOIN)
- exp = addJoin(node, true, exp);
+ ; // we handle inner fetch joins in the evalFetchJoins() method
else if (node.id == JJTOUTERFETCHJOIN)
; // we handle outer fetch joins in the evalFetchJoins() method
else
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/DelegatingJDBCFetchConfiguration.java Wed Apr 9 11:09:42 2008
@@ -260,4 +260,38 @@
throw translate(re);
}
}
+
+ public Set getFetchInnerJoins() {
+ try {
+ return getJDBCDelegate().getFetchInnerJoins();
+ } catch (RuntimeException re) {
+ throw translate(re);
+ }
+ }
+
+ public boolean hasFetchInnerJoin(String field) {
+ try {
+ return getJDBCDelegate().hasFetchInnerJoin(field);
+ } catch (RuntimeException re) {
+ throw translate(re);
+ }
+ }
+
+ public JDBCFetchConfiguration addFetchInnerJoin(String field) {
+ try {
+ getJDBCDelegate().addFetchInnerJoin(field);
+ return this;
+ } catch (RuntimeException re) {
+ throw translate(re);
+ }
+ }
+
+ public JDBCFetchConfiguration addFetchInnerJoins(Collection fields) {
+ try {
+ getJDBCDelegate().addFetchInnerJoins(fields);
+ return this;
+ } catch (RuntimeException re) {
+ throw translate(re);
+ }
+ }
}
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfiguration.java Wed Apr 9 11:09:42 2008
@@ -207,4 +207,38 @@
* Convenience method to cast traversal to store-specific type.
*/
public JDBCFetchConfiguration traverseJDBC(FieldMetaData fm);
+
+ /**
+ * Returns the names of the inner fetch joins that this component will use
+ * when loading objects. Defaults to the empty set. This set is not
+ * thread safe.
+ *
+ * @since 1.0.3
+ */
+ public Set getFetchInnerJoins();
+
+ /**
+ * Return true if the given fully-qualified inner fetch join has been added.
+ *
+ * @since 1.0.3
+ */
+ public boolean hasFetchInnerJoin(String field);
+
+ /**
+ * Adds <code>field</code> to the set of fully-qualified field names to
+ * eagerly join when loading objects. Each class can have at most
+ * one to-many eagerly joined fields.
+ *
+ * @since 1.0.3
+ */
+ public JDBCFetchConfiguration addFetchInnerJoin(String field);
+
+ /**
+ * Adds <code>fields</code> to the set of fully-qualified field names to
+ * eagerly join when loading objects. Each class can have at most
+ * one to-many eagerly joined fields.
+ *
+ * @since 1.0.3
+ */
+ public JDBCFetchConfiguration addFetchInnerJoins(Collection fields);
}
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCFetchConfigurationImpl.java Wed Apr 9 11:09:42 2008
@@ -69,6 +69,7 @@
public int size = 0;
public int syntax = 0;
public Set joins = null;
+ public Set fetchInnerJoins = null;
public int isolationLevel = -1;
}
@@ -344,5 +345,38 @@
if (!(conf instanceof JDBCConfiguration))
return null;
return (JDBCConfiguration) conf;
+ }
+
+ public Set getFetchInnerJoins() {
+ return (_state.fetchInnerJoins == null) ? Collections.EMPTY_SET
+ : _state.fetchInnerJoins;
+ }
+
+ public boolean hasFetchInnerJoin(String field) {
+ return _state.fetchInnerJoins != null &&
+ _state.fetchInnerJoins.contains(field);
+ }
+
+ public JDBCFetchConfiguration addFetchInnerJoin(String join) {
+ if (StringUtils.isEmpty(join))
+ throw new UserException(_loc.get("null-join"));
+
+ lock();
+ try {
+ if (_state.fetchInnerJoins == null)
+ _state.fetchInnerJoins = new HashSet();
+ _state.fetchInnerJoins.add(join);
+ } finally {
+ unlock();
+ }
+ return this;
+ }
+
+ public JDBCFetchConfiguration addFetchInnerJoins(Collection joins) {
+ if (joins == null || joins.isEmpty())
+ return this;
+ for (Iterator itr = joins.iterator(); itr.hasNext();)
+ addFetchInnerJoin((String) itr.next());
+ return this;
}
}
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java Wed Apr 9 11:09:42 2008
@@ -148,6 +148,8 @@
fetch.addFields(Arrays.asList(exps[0].fetchPaths));
fetch.addJoins(Arrays.asList(exps[0].fetchPaths));
}
+ if (exps[0].fetchInnerPaths != null)
+ fetch.addFetchInnerJoins(Arrays.asList(exps[0].fetchInnerPaths));
int eager = calculateEagerMode(exps[0], range.start, range.end);
int subclassMode = fetch.getSubclassFetchMode((ClassMapping) base);
@@ -599,6 +601,8 @@
fetch.addFields(Arrays.asList(exps[0].fetchPaths));
fetch.addJoins(Arrays.asList(exps[0].fetchPaths));
}
+ if (exps[0].fetchInnerPaths != null)
+ fetch.addFetchInnerJoins(Arrays.asList(exps[0].fetchInnerPaths));
int eager = calculateEagerMode(exps[0], range.start, range.end);
eager = Math.min(eager, JDBCFetchConfiguration.EAGER_JOIN);
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java Wed Apr 9 11:09:42 2008
@@ -409,9 +409,11 @@
// clone it for a to-many eager select can result in a clone that
// produces invalid SQL
ClassMapping cls = field.getIndependentTypeMappings()[0];
+ boolean forceInner = fetch.hasFetchInnerJoin(field.getFullName(false)) ?
+ true : false;
sel.select(cls, field.getSelectSubclasses(), store, fetch,
JDBCFetchConfiguration.EAGER_JOIN,
- eagerJoin(sel.newJoins(), cls, false));
+ eagerJoin(sel.newJoins(), cls, forceInner));
}
/**
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java Wed Apr 9 11:09:42 2008
@@ -24,7 +24,6 @@
import java.util.HashMap;
import java.util.Map;
-import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCStore;
import org.apache.openjpa.jdbc.meta.ClassMapping;
@@ -168,10 +167,13 @@
// we limit further eager fetches to joins, because after this point
// the select has been modified such that parallel clones may produce
// invalid sql
+ boolean outer = field.getNullValue() != FieldMapping.NULL_EXCEPTION;
+ // force inner join for inner join fetch
+ if (fetch.hasFetchInnerJoin(field.getFullName(false)))
+ outer = false;
selectEager(sel, getDefaultElementMapping(true), sm, store, fetch,
JDBCFetchConfiguration.EAGER_JOIN, false,
- field.getNullValue()
- != FieldMapping.NULL_EXCEPTION);
+ outer);
}
public boolean isEagerSelectToMany() {
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/QueryExpressions.java Wed Apr 9 11:09:42 2008
@@ -65,6 +65,7 @@
public int operation = QueryOperations.OP_SELECT;
public ClassMetaData[] accessPath = StoreQuery.EMPTY_METAS;
public String[] fetchPaths = StoreQuery.EMPTY_STRINGS;
+ public String[] fetchInnerPaths = StoreQuery.EMPTY_STRINGS;
public Value[] range = EMPTY_VALUES;
private Boolean _aggregate = null;
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java?rev=646455&r1=646454&r2=646455&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java Wed Apr 9 11:09:42 2008
@@ -452,6 +452,7 @@
// handle JOIN FETCH
Set joins = null;
+ Set innerJoins = null;
JPQLNode[] outers = root().findChildrenByID(JJTOUTERFETCHJOIN);
for (int i = 0; outers != null && i < outers.length; i++)
@@ -459,13 +460,20 @@
add(getPath(onlyChild(outers[i])).last().getFullName(false));
JPQLNode[] inners = root().findChildrenByID(JJTINNERFETCHJOIN);
- for (int i = 0; inners != null && i < inners.length; i++)
- (joins == null ? joins = new TreeSet() : joins).
- add(getPath(onlyChild(inners[i])).last().getFullName(false));
+ for (int i = 0; inners != null && i < inners.length; i++) {
+ String path = getPath(onlyChild(inners[i])).last()
+ .getFullName(false);
+ (joins == null ? joins = new TreeSet() : joins).add(path);
+ (innerJoins == null ? innerJoins = new TreeSet() : innerJoins).
+ add(path);
+ }
if (joins != null)
exps.fetchPaths = (String[]) joins.
toArray(new String[joins.size()]);
+ if (innerJoins != null)
+ exps.fetchInnerPaths = (String[]) innerJoins.
+ toArray(new String[innerJoins.size()]);
return filter;
}
@@ -506,7 +514,7 @@
else if (node.id == JJTINNERJOIN)
exp = addJoin(node, true, exp);
else if (node.id == JJTINNERFETCHJOIN)
- exp = addJoin(node, true, exp);
+ ; // we handle inner fetch joins in the evalFetchJoins() method
else if (node.id == JJTOUTERFETCHJOIN)
; // we handle outer fetch joins in the evalFetchJoins() method
else