You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2009/09/07 22:50:02 UTC

svn commit: r812273 - in /cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne: access/HierarchicalObjectResolverNode.java access/ResultScanParentAttachmentStrategy.java query/SelectQueryPrefetchRouterAction.java

Author: aadamchik
Date: Mon Sep  7 20:50:02 2009
New Revision: 812273

URL: http://svn.apache.org/viewvc?rev=812273&view=rev
Log:
CAY-1250 Prefetching doesn't work with prefetched subentity

adding ResultScanParentAttachmentStrategy

Added:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ResultScanParentAttachmentStrategy.java
Modified:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolverNode.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/SelectQueryPrefetchRouterAction.java

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolverNode.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolverNode.java?rev=812273&r1=812272&r2=812273&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolverNode.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolverNode.java Mon Sep  7 20:50:02 2009
@@ -40,10 +40,16 @@
         if (node.getParent() == null || node.getParent().isPhantom()) {
             this.parentAttachmentStrategy = new NoopParentAttachmentStrategy();
         }
-        else {
+        else if (node
+                .getIncoming()
+                .getRelationship()
+                .isSourceIndependentFromTargetChange()) {
             this.parentAttachmentStrategy = new JoinedIdParentAttachementStrategy(context
                     .getGraphManager(), node);
         }
+        else {
+            this.parentAttachmentStrategy = new ResultScanParentAttachmentStrategy(node);
+        }
     }
 
     @Override
@@ -58,7 +64,7 @@
         // here we can get the same object repeated multiple times in case of
         // many-to-many between prefetched and main entity... this is needed to
         // connect prefetched objects to the main objects. To avoid needlessly refreshing
-        // the same object multiple times, track which objectids area alrady loaded in
+        // the same object multiple times, track which objectids area already loaded in
         // this pass
         Map<ObjectId, Persistent> seen = new HashMap<ObjectId, Persistent>();
 

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ResultScanParentAttachmentStrategy.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ResultScanParentAttachmentStrategy.java?rev=812273&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ResultScanParentAttachmentStrategy.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/ResultScanParentAttachmentStrategy.java Mon Sep  7 20:50:02 2009
@@ -0,0 +1,135 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.access;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cayenne.DataRow;
+import org.apache.cayenne.Persistent;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.ObjRelationship;
+
+/**
+ * Locates parents by checking for the child PK in the parent DataRow under FK.
+ */
+class ResultScanParentAttachmentStrategy implements ParentAttachmentStrategy {
+
+    private PrefetchProcessorNode parentNode;
+    private DbJoin[] joins;
+    private PrefetchProcessorNode node;
+
+    // TODO: the ivar below makes this strategy STATEFUL and non-reusable. If we need a
+    // stateless version down the line, will need to move this to the
+    // PrefetchProcessorNode.
+    private Map<Object, List<Persistent>> partitionByChild;
+
+    ResultScanParentAttachmentStrategy(PrefetchProcessorNode node) {
+
+        if (node.getParent() == null) {
+            throw new IllegalArgumentException(
+                    "ResultScanParentAttachmentStrategy works only for non-root nodes");
+        }
+
+        this.node = node;
+        parentNode = (PrefetchProcessorNode) node.getParent();
+
+        ObjRelationship relationship = node.getIncoming().getRelationship();
+
+        List<DbRelationship> dbRelationships = relationship.getDbRelationships();
+        if (dbRelationships.size() > 1) {
+            throw new IllegalArgumentException(
+                    "ResultScanParentAttachmentStrategy does not work for flattened relationships");
+        }
+
+        joins = dbRelationships.get(0).getJoins().toArray(
+                new DbJoin[dbRelationships.get(0).getJoins().size()]);
+
+    }
+
+    public void linkToParent(DataRow row, Persistent object) {
+
+        if (partitionByChild == null) {
+            indexParents();
+        }
+
+        Object key;
+
+        if (joins.length > 1) {
+
+            List<Object> values = new ArrayList<Object>(joins.length);
+
+            for (int j = 0; j < joins.length; j++) {
+                values.add(row.get(joins[j].getTargetName()));
+            }
+
+            key = values;
+        }
+        else {
+            key = row.get(joins[0].getTargetName());
+        }
+
+        List<Persistent> parents = (List<Persistent>) partitionByChild.get(key);
+        if (parents != null) {
+            for (Persistent parent : parents) {
+                node.linkToParent(object, parent);
+            }
+        }
+    }
+
+    private void indexParents() {
+        partitionByChild = new HashMap<Object, List<Persistent>>();
+
+        List<Persistent> objects = parentNode.getObjects();
+        List<DataRow> rows = parentNode.getDataRows();
+        int size = objects.size();
+        for (int i = 0; i < size; i++) {
+
+            DataRow row = rows.get(i);
+
+            Object key;
+
+            if (joins.length > 1) {
+
+                List<Object> values = new ArrayList<Object>(joins.length);
+
+                for (int j = 0; j < joins.length; j++) {
+                    values.add(row.get(joins[j].getSourceName()));
+                }
+
+                key = values;
+            }
+            else {
+                key = row.get(joins[0].getSourceName());
+            }
+
+            List<Persistent> parents = partitionByChild.get(key);
+            if (parents == null) {
+                parents = new ArrayList<Persistent>();
+                partitionByChild.put(key, parents);
+            }
+
+            parents.add(objects.get(i));
+        }
+    }
+
+}

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/SelectQueryPrefetchRouterAction.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/SelectQueryPrefetchRouterAction.java?rev=812273&r1=812272&r2=812273&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/SelectQueryPrefetchRouterAction.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/query/SelectQueryPrefetchRouterAction.java Mon Sep  7 20:50:02 2009
@@ -105,9 +105,12 @@
                 queryQualifier,
                 prefetchPath));
 
-        // setup extra result columns to be able to relate result rows to the parent
-        // result objects.
-        prefetchQuery.addResultPath("db:" + relationship.getReverseDbRelationshipPath());
+        if (relationship.isSourceIndependentFromTargetChange()) {
+            // setup extra result columns to be able to relate result rows to the parent
+            // result objects.
+            prefetchQuery.addResultPath("db:"
+                    + relationship.getReverseDbRelationshipPath());
+        }
 
         // pass prefetch subtree to enable joint prefetches...
         prefetchQuery.setPrefetchTree(node);