Author: aadamchik
Date: Mon Apr 16 18:10:03 2012
New Revision: 1326721
URL: http://svn.apache.org/viewvc?rev=1326721&view=rev
Log:
CAY-1681 Third prefetch kind - DISJOINT_BY_ID
CAY-1681-v5.patch by Andrei Veprev ... seems complete to me
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolver.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/PrefetchTreeNode.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextDisjointByIdPrefetchTest.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/query/PrefetchTreeNodeTest.java
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolver.java
URL:
http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolver.java?rev=1326721&r1=1326720&r2=1326721&view=diff
==============================================================================
---
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolver.java
(original)
+++
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolver.java
Mon Apr 16 18:10:03 2012
@@ -187,9 +187,11 @@ class HierarchicalObjectResolver {
query.orQualifier(allJoinsQualifier);
}
- // TODO: need to pass the remaining tree to make joint prefetches
work
- // but not sure is it a good idea to do it in that way
- query.setPrefetchTree(node);
+ // need to pass the remaining tree to make joint prefetches work
+ PrefetchTreeNode jointSubtree = node.cloneJointSubtree();
+ if (jointSubtree.hasChildren()) {
+ query.setPrefetchTree(jointSubtree);
+ }
query.setFetchingDataRows(true);
if (relationship.isSourceIndependentFromTargetChange()) {
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/PrefetchTreeNode.java
URL:
http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/PrefetchTreeNode.java?rev=1326721&r1=1326720&r2=1326721&view=diff
==============================================================================
---
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/PrefetchTreeNode.java
(original)
+++
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/PrefetchTreeNode.java
Mon Apr 16 18:10:03 2012
@@ -33,7 +33,7 @@ import org.apache.cayenne.util.XMLSerial
/**
* Defines a node in a prefetch tree.
- *
+ *
* @since 1.2
*/
public class PrefetchTreeNode implements Serializable, XMLSerializable {
@@ -164,6 +164,34 @@ public class PrefetchTreeNode implements
}
/**
+ * Returns a clone of subtree that includes all joint children
+ * starting from this node itself and till the first occurrence of
non-joint node
+ *
+ * @since 3.1
+ */
+ public PrefetchTreeNode cloneJointSubtree() {
+ return cloneJointSubtree(null);
+ }
+
+ private PrefetchTreeNode cloneJointSubtree(PrefetchTreeNode parent) {
+ PrefetchTreeNode cloned = new PrefetchTreeNode(parent, getName());
+ if (parent != null) {
+ cloned.setSemantics(getSemantics());
+ cloned.setPhantom(isPhantom());
+ }
+
+ if (children != null) {
+ for (PrefetchTreeNode child : children) {
+ if (child.isJointPrefetch()) {
+ cloned.addChild(child.cloneJointSubtree(cloned));
+ }
+ }
+ }
+
+ return cloned;
+ }
+
+ /**
* Traverses the tree depth-first, invoking callback methods of the
processor when
* passing through the nodes.
*/
@@ -220,7 +248,7 @@ public class PrefetchTreeNode implements
/**
* Adds a "path" with specified semantics to this prefetch node. All yet
non-existent
* nodes in the created path will be marked as phantom.
- *
+ *
* @return the last segment in the created path.
*/
public PrefetchTreeNode addPath(String path) {
@@ -375,11 +403,11 @@ public class PrefetchTreeNode implements
public String getEntityName() {
return entityName;
}
-
+
public void setEntityName(String entityName) {
this.entityName = entityName;
}
-
+
// **** custom serialization that supports serializing subtrees...
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextDisjointByIdPrefetchTest.java
URL:
http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextDisjointByIdPrefetchTest.java?rev=1326721&r1=1326720&r2=1326721&view=diff
==============================================================================
---
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextDisjointByIdPrefetchTest.java
(original)
+++
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/access/DataContextDisjointByIdPrefetchTest.java
Mon Apr 16 18:10:03 2012
@@ -18,6 +18,8 @@ import org.apache.cayenne.unit.di.server
import org.apache.cayenne.unit.di.server.UseServerRuntime;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import static org.apache.cayenne.exp.ExpressionFactory.matchExp;
@@ -96,9 +98,9 @@ public class DataContextDisjointByIdPref
private void createBagWithTwoBoxesAndPlentyOfBallsDataSet() throws
Exception {
tBag.insert(1, null);
- tBox.insert(1, 1, null);
+ tBox.insert(1, 1, "big");
tBoxInfo.insert(1, 1, "red");
- tBox.insert(2, 1, null);
+ tBox.insert(2, 1, "small");
tBoxInfo.insert(2, 2, "green");
tThing.insert(1, 10, 10);
@@ -210,6 +212,7 @@ public class DataContextDisjointByIdPref
BoxInfo info = (BoxInfo)
b1.readPropertyDirectly(Box.BOX_INFO_PROPERTY);
assertNotNull(info);
assertEquals("red", info.getColor());
+ assertEquals(PersistenceState.COMMITTED,
info.getPersistenceState());
}
});
}
@@ -227,10 +230,17 @@ public class DataContextDisjointByIdPref
public void execute() {
assertFalse(result.isEmpty());
Bag b1 = result.get(0);
- List<?> toMany = (List<?>)
b1.readPropertyDirectly(Bag.BALLS_PROPERTY);
- assertNotNull(toMany);
- assertFalse(((ValueHolder) toMany).isFault());
- assertEquals(6, toMany.size());
+ List<Ball> balls = (List<Ball>)
b1.readPropertyDirectly(Bag.BALLS_PROPERTY);
+ assertNotNull(balls);
+ assertFalse(((ValueHolder) balls).isFault());
+ assertEquals(6, balls.size());
+
+ List<Integer> volumes = new ArrayList<Integer>();
+ for (Ball b : balls) {
+ assertEquals(PersistenceState.COMMITTED,
b.getPersistenceState());
+ volumes.add(b.getThingVolume());
+ }
+ assertEquals(Arrays.asList(10, 20, 30, 40, 20, 40), volumes);
}
});
}
@@ -248,10 +258,17 @@ public class DataContextDisjointByIdPref
public void execute() {
assertFalse(result.isEmpty());
Bag b1 = result.get(0);
- List<?> toMany = (List<?>)
b1.readPropertyDirectly(Bag.THINGS_PROPERTY);
- assertNotNull(toMany);
- assertFalse(((ValueHolder) toMany).isFault());
- assertEquals(6, toMany.size());
+ List<Thing> things = (List<Thing>)
b1.readPropertyDirectly(Bag.THINGS_PROPERTY);
+ assertNotNull(things);
+ assertFalse(((ValueHolder) things).isFault());
+ assertEquals(6, things.size());
+
+ List<Integer> volumes = new ArrayList<Integer>();
+ for (Thing t : things) {
+ assertEquals(PersistenceState.COMMITTED,
t.getPersistenceState());
+ volumes.add(t.getVolume());
+ }
+ assertEquals(Arrays.asList(10, 20, 20, 30, 40, 40), volumes);
}
});
}
@@ -284,10 +301,17 @@ public class DataContextDisjointByIdPref
public void execute() {
assertFalse(result.isEmpty());
Box b1 = result.get(0);
- List<?> toMany = (List<?>)
b1.readPropertyDirectly(Box.THINGS_PROPERTY);
- assertNotNull(toMany);
- assertFalse(((ValueHolder) toMany).isFault());
- assertEquals(2, toMany.size());
+ List<Thing> things = (List<Thing>)
b1.readPropertyDirectly(Box.THINGS_PROPERTY);
+ assertNotNull(things);
+ assertFalse(((ValueHolder) things).isFault());
+ assertEquals(2, things.size());
+
+ List<Integer> volumes = new ArrayList<Integer>();
+ for (Thing t : things) {
+ assertEquals(PersistenceState.COMMITTED,
t.getPersistenceState());
+ volumes.add(t.getVolume());
+ }
+ assertEquals(Arrays.asList(10, 20), volumes);
}
});
}
@@ -314,6 +338,8 @@ public class DataContextDisjointByIdPref
Ball ball = balls.get(0);
Thing thing = (Thing)
ball.readPropertyDirectly(Ball.THING_PROPERTY);
assertNotNull(thing);
+ assertEquals(PersistenceState.COMMITTED,
thing.getPersistenceState());
+ assertEquals(Integer.valueOf(10), thing.getVolume());
}
});
}
@@ -338,11 +364,25 @@ public class DataContextDisjointByIdPref
assertFalse(((ValueHolder) boxes).isFault());
assertEquals(2, boxes.size());
+ List<String> names = new ArrayList<String>();
+ for (Box box : boxes) {
+ assertEquals(PersistenceState.COMMITTED,
box.getPersistenceState());
+ names.add(box.getName());
+ }
+ assertTrue(names.contains("big"));
+ assertTrue(names.contains("small"));
+
Box box = boxes.get(0);
List<Ball> balls = (List<Ball>)
box.readPropertyDirectly(Box.BALLS_PROPERTY);
assertNotNull(balls);
assertFalse(((ValueHolder) balls).isFault());
assertEquals(2, balls.size());
+ List<Integer> volumes = new ArrayList<Integer>();
+ for (Ball ball : balls) {
+ assertEquals(PersistenceState.COMMITTED,
ball.getPersistenceState());
+ volumes.add(ball.getThingVolume());
+ }
+ assertEquals(Arrays.asList(10, 20), volumes);
}
});
}
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/query/PrefetchTreeNodeTest.java
URL:
http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/query/PrefetchTreeNodeTest.java?rev=1326721&r1=1326720&r2=1326721&view=diff
==============================================================================
---
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/query/PrefetchTreeNodeTest.java
(original)
+++
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/query/PrefetchTreeNodeTest.java
Mon Apr 16 18:10:03 2012
@@ -140,4 +140,34 @@ public class PrefetchTreeNodeTest extend
assertSame(nc2, nc3.getParent());
assertEquals("xyz", nc3.getName());
}
+
+ public void testCloneJointSubtree() throws Exception {
+ PrefetchTreeNode root = new PrefetchTreeNode(null, "root");
+ root.setPhantom(false);
+ PrefetchTreeNode joint1 = root.addPath("joint1");
+ joint1.setPhantom(false);
+ joint1.setSemantics(PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS);
+ PrefetchTreeNode joint2 = root.addPath("joint2");
+ joint2.setPhantom(false);
+ joint2.setSemantics(PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS);
+ PrefetchTreeNode disjoint = joint1.addPath("disjoint1");
+ disjoint.setPhantom(false);
+ disjoint.setSemantics(PrefetchTreeNode.DISJOINT_PREFETCH_SEMANTICS);
+
+ PrefetchTreeNode cloned = root.cloneJointSubtree();
+ assertEquals("root", cloned.getName());
+
+ assertEquals(2, cloned.getChildren().size());
+
+ PrefetchTreeNode joint1Clone = cloned.getChild("joint1");
+ assertNotNull(joint1Clone);
+ assertEquals("joint1", joint1.getPath());
+ assertEquals(0, joint1Clone.getChildren().size());
+
+ PrefetchTreeNode joint2Clone = cloned.getChild("joint2");
+ assertNotNull(joint2Clone);
+ assertEquals("joint2", joint2.getPath());
+ assertEquals(0, joint2Clone.getChildren().size());
+
+ }
}