You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by an...@apache.org on 2010/01/20 21:55:49 UTC

svn commit: r901376 - in /cayenne/main/trunk: docs/doc/src/main/resources/ framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/query/

Author: andrey
Date: Wed Jan 20 20:55:48 2010
New Revision: 901376

URL: http://svn.apache.org/viewvc?rev=901376&view=rev
Log:
CAY-1368 Left Join and Prefetches do not work together

Modified:
    cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DbEntity.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/query/SelectQueryTest.java

Modified: cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt?rev=901376&r1=901375&r2=901376&view=diff
==============================================================================
--- cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt (original)
+++ cayenne/main/trunk/docs/doc/src/main/resources/RELEASE-NOTES.txt Wed Jan 20 20:55:48 2010
@@ -56,6 +56,7 @@
 CAY-1355 Warning if rename Embeddable.
 CAY-1361 SelectQuery.aliasPathSplits does nothing
 CAY-1365 "= NULL" being used instead of "IS NULL" on an EJBQL expression..
+CAY-1368 Left Join and Prefetches do not work together
 
 ----------------------------------
 Release: 3.0 RC 1

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DbEntity.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DbEntity.java?rev=901376&r1=901375&r2=901376&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DbEntity.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/DbEntity.java Wed Jan 20 20:55:48 2010
@@ -22,6 +22,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
@@ -643,6 +644,11 @@
             transformed.setOperand(0, converted);
             return transformed;
         }
+        
+        private PathComponentIterator createPathIterator(String path) {
+            return new PathComponentIterator(DbEntity.this, path, 
+                    new HashMap<String, String>()); //TODO: do we need aliases here?
+        }
 
         String translatePath(String path) {
 
@@ -661,7 +667,7 @@
 
             // case (0)
             if (toMany) {
-                Iterator<CayenneMapEntry> pathIt = resolvePathComponents(path);
+                PathComponentIterator pathIt = createPathIterator(path);
                 Iterator<CayenneMapEntry> relationshipIt = resolvePathComponents(relationshipPath);
 
                 // for inserts from the both ends use LinkedList
@@ -675,8 +681,8 @@
 
                 while (pathIt.hasNext()) {
                     // components may be attributes or relationships
-                    CayenneMapEntry next = pathIt.next();
-                    appendPath(finalPath, next);
+                    PathComponent<Attribute, Relationship> component = pathIt.next();
+                    appendPath(finalPath, component);
                 }
 
                 return convertToPath(finalPath);
@@ -685,15 +691,15 @@
             if (path.equals(relationshipPath)) {
 
                 LinkedList<String> finalPath = new LinkedList<String>();
-                Iterator<CayenneMapEntry> it = resolvePathComponents(path);
+                PathComponentIterator pathIt = createPathIterator(path);
 
                 // just do one step back and one step forward to create correct joins...
                 // find last rel...
                 DbRelationship lastDBR = null;
 
-                while (it.hasNext()) {
+                while (pathIt.hasNext()) {
                     // relationship path components must be DbRelationships
-                    lastDBR = (DbRelationship) it.next();
+                    lastDBR = (DbRelationship) pathIt.next().getRelationship();
                 }
 
                 if (lastDBR != null) {
@@ -711,7 +717,7 @@
             }
 
             // case (3)
-            Iterator<CayenneMapEntry> pathIt = resolvePathComponents(path);
+            PathComponentIterator pathIt = createPathIterator(path);
             Iterator<CayenneMapEntry> relationshipIt = resolvePathComponents(relationshipPath);
 
             // for inserts from the both ends use LinkedList
@@ -722,14 +728,14 @@
                 DbRelationship nextDBR = (DbRelationship) relationshipIt.next();
 
                 // expression components may be attributes or relationships
-                CayenneMapEntry next = pathIt.next();
+                PathComponent<Attribute, Relationship> component = pathIt.next();
 
-                if (nextDBR != next) {
+                if (nextDBR != component.getRelationship()) {
                     // found split point
                     // consume the last iteration components,
                     // then break out to finish the iterators independently
                     prependReversedPath(finalPath, nextDBR);
-                    appendPath(finalPath, next);
+                    appendPath(finalPath, component);
                     break;
                 }
 
@@ -744,8 +750,8 @@
 
             while (pathIt.hasNext()) {
                 // components may be attributes or relationships
-                CayenneMapEntry next = pathIt.next();
-                appendPath(finalPath, next);
+                PathComponent<Attribute, Relationship> component = pathIt.next();
+                appendPath(finalPath, component);
             }
 
             return convertToPath(finalPath);
@@ -787,5 +793,18 @@
                 CayenneMapEntry pathComponent) {
             finalPath.addLast(pathComponent.getName());
         }
+        
+        private void appendPath(
+                LinkedList<String> finalPath,
+                PathComponent<Attribute, Relationship> pathComponent) {
+            String name = (pathComponent.getAttribute() != null ? 
+                pathComponent.getAttribute() :
+                pathComponent.getRelationship()).getName();
+            if (pathComponent.getJoinType() == JoinType.LEFT_OUTER) {
+                name += OUTER_JOIN_INDICATOR;
+            }
+            
+            finalPath.addLast(name);
+        }
     }
 }

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java?rev=901376&r1=901375&r2=901376&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/map/ObjEntity.java Wed Jan 20 20:55:48 2010
@@ -23,6 +23,7 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -1086,36 +1087,43 @@
 
         DBPathConverter transformer = new DBPathConverter();
 
-        String dbPath = transformer.toDbPath(resolvePathComponents(relationshipPath));
+        String dbPath = transformer.toDbPath(createPathIterator(relationshipPath));
         Expression dbClone = expression.transform(transformer);
 
         return getDbEntity().translateToRelatedEntity(dbClone, dbPath);
     }
+    
+    private PathComponentIterator createPathIterator(String path) {
+        return new PathComponentIterator(ObjEntity.this, path, 
+                new HashMap<String, String>()); //TODO: do we need aliases here?
+    }
 
     final class DBPathConverter implements Transformer {
 
         // TODO: make it a public method - resolveDBPathComponents or something...
         // seems generally useful
-        String toDbPath(Iterator<CayenneMapEntry> objectPathComponents) {
+        
+        String toDbPath(PathComponentIterator objectPathComponents) {
             StringBuilder buf = new StringBuilder();
             while (objectPathComponents.hasNext()) {
-                Object component = objectPathComponents.next();
+                PathComponent<Attribute, Relationship> component = objectPathComponents.next();
 
                 Iterator<?> dbSubpath;
 
-                if (component instanceof ObjRelationship) {
-                    dbSubpath = ((ObjRelationship) component)
-                            .getDbRelationships()
-                            .iterator();
+                if (component.getAttribute() != null) {
+                    dbSubpath = ((ObjAttribute) component.getAttribute()).getDbPathIterator();
                 }
-                else if (component instanceof ObjAttribute) {
-                    dbSubpath = ((ObjAttribute) component).getDbPathIterator();
+                else if (component.getRelationship() != null) {
+                    dbSubpath = ((ObjRelationship) component.getRelationship())
+                        .getDbRelationships()
+                        .iterator();
                 }
                 else {
                     throw new CayenneRuntimeException("Unknown path component: "
                             + component);
                 }
 
+                boolean firstComponent = true;
                 while (dbSubpath.hasNext()) {
                     CayenneMapEntry subComponent = (CayenneMapEntry) dbSubpath.next();
                     if (buf.length() > 0) {
@@ -1123,6 +1131,10 @@
                     }
 
                     buf.append(subComponent.getName());
+                    if (firstComponent && component.getJoinType() == JoinType.LEFT_OUTER) {
+                        buf.append(OUTER_JOIN_INDICATOR);
+                    }
+                    firstComponent = false;
                 }
             }
 
@@ -1143,7 +1155,7 @@
 
             // convert obj_path to db_path
 
-            String converted = toDbPath(resolvePathComponents(expression));
+            String converted = toDbPath(createPathIterator((String) expression.getOperand(0)));
             Expression exp = ExpressionFactory.expressionOfType(Expression.DB_PATH);
             exp.setOperand(0, converted);
             return exp;

Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/query/SelectQueryTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/query/SelectQueryTest.java?rev=901376&r1=901375&r2=901376&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/query/SelectQueryTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/query/SelectQueryTest.java Wed Jan 20 20:55:48 2010
@@ -538,4 +538,18 @@
             }
         }
     }
+    
+    public void testLeftJoinAndPrefetchToMany() {
+        SelectQuery query = new SelectQuery(Artist.class, 
+            ExpressionFactory.matchExp("paintingArray+.toGallery", null));
+        query.addPrefetch("artistExhibitArray");
+        createDataContext().performQuery(query);
+    }
+    
+    public void testLeftJoinAndPrefetchToOne() {
+        SelectQuery query = new SelectQuery(Painting.class, 
+            ExpressionFactory.matchExp("toArtist+.artistName", null));
+        query.addPrefetch("toGallery");
+        createDataContext().performQuery(query);
+    }
 }