You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2019/04/11 08:38:55 UTC

[cayenne] branch master updated (0e9145d -> 5ac4bdf)

This is an automated email from the ASF dual-hosted git repository.

ntimofeev pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git.


    from 0e9145d  Postgres build fixed, disallow it's failure
     new e6649cb  CAY-2553 Wrong disjoint prefetch query qualifier
     new 5ac4bdf  Merge PR #370

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 RELEASE-NOTES.txt                                  |   1 +
 .../main/java/org/apache/cayenne/map/DbEntity.java | 131 +++--------------
 .../apache/cayenne/exp/TranslateExpressionIT.java  | 159 +++++++++++++++++++++
 .../java/org/apache/cayenne/map/DbEntityIT.java    |   6 +-
 4 files changed, 179 insertions(+), 118 deletions(-)
 create mode 100644 cayenne-server/src/test/java/org/apache/cayenne/exp/TranslateExpressionIT.java


[cayenne] 02/02: Merge PR #370

Posted by nt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git

commit 5ac4bdf8f98a8b20b924dbb2eb49e5ac7dd069ad
Merge: 0e9145d e6649cb
Author: Nikita Timofeev <st...@gmail.com>
AuthorDate: Thu Apr 11 11:38:49 2019 +0300

    Merge PR #370

 RELEASE-NOTES.txt                                  |   1 +
 .../main/java/org/apache/cayenne/map/DbEntity.java | 131 +++--------------
 .../apache/cayenne/exp/TranslateExpressionIT.java  | 159 +++++++++++++++++++++
 .../java/org/apache/cayenne/map/DbEntityIT.java    |   6 +-
 4 files changed, 179 insertions(+), 118 deletions(-)

diff --cc RELEASE-NOTES.txt
index df5df34,d920ec2..64abe28
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@@ -32,19 -31,18 +32,20 @@@ Bug Fixes
  
  CAY-2332 Property API: unable to use eq() and in() methods for toMany relationships
  CAY-2509 Result of resolving lazily faulted relationships can be out-of-date
 -CAY-2530 DB Import and Class Generation from Project is performed for removed datamaps
 -CAY-2531 Importing same schema after Import Revert clears all entities in datamap
 +CAY-2530 Modeler: DB Import and Class Generation from Project is performed for removed datamaps
 +CAY-2531 Modeler: Importing same schema after Import Revert clears all entities in datamap
  CAY-2533 Modeler: Exception on validating ObjRelationship without db path
 -CAY-2535 Imposible to import stored proceedure apart from db tables
 -CAY-2537 Generate DB Schema: Schema Generation Complete popup window is hidden
 +CAY-2535 Modeler: Impossible to import stored procedure apart from db tables
 +CAY-2537 Modeler: Schema Generation Complete popup window is hidden
  CAY-2544 Possible name clash of ivar and property name in generated class
  CAY-2547 CayenneDataObject serialization issue
+ CAY-2553 Wrong disjoint prefetch query qualifier
 +CAY-2559 Modeler: Warning dialog shows wrong information after changing target entity in dbRelationship
 +CAY-2561 Modeler: cgen type combobox doesn't set templates
  
  ----------------------------------
 -Release: 4.1.M3
 -Date:
 +Release: 4.1.B1
 +Date: March 7, 2019
  ----------------------------------
  Changes/New Features:
  


[cayenne] 01/02: CAY-2553 Wrong disjoint prefetch query qualifier

Posted by nt...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git

commit e6649cbf1d2bc250f1176f8767932f881fae0ea8
Author: Arseni Bulatski <an...@gmail.com>
AuthorDate: Wed Mar 13 15:56:44 2019 +0300

    CAY-2553 Wrong disjoint prefetch query qualifier
---
 RELEASE-NOTES.txt                                  |   1 +
 .../main/java/org/apache/cayenne/map/DbEntity.java | 131 +++--------------
 .../apache/cayenne/exp/TranslateExpressionIT.java  | 159 +++++++++++++++++++++
 .../java/org/apache/cayenne/map/DbEntityIT.java    |   6 +-
 4 files changed, 179 insertions(+), 118 deletions(-)

diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 27ebf74..d920ec2 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -38,6 +38,7 @@ CAY-2535 Imposible to import stored proceedure apart from db tables
 CAY-2537 Generate DB Schema: Schema Generation Complete popup window is hidden
 CAY-2544 Possible name clash of ivar and property name in generated class
 CAY-2547 CayenneDataObject serialization issue
+CAY-2553 Wrong disjoint prefetch query qualifier
 
 ----------------------------------
 Release: 4.1.M3
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/DbEntity.java b/cayenne-server/src/main/java/org/apache/cayenne/map/DbEntity.java
index 0626655..d92a7d4 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/DbEntity.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/DbEntity.java
@@ -19,6 +19,16 @@
 
 package org.apache.cayenne.map;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.function.Function;
+
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.ObjectId;
 import org.apache.cayenne.configuration.ConfigurationNode;
@@ -37,18 +47,6 @@ import org.apache.cayenne.util.CayenneMapEntry;
 import org.apache.cayenne.util.Util;
 import org.apache.cayenne.util.XMLEncoder;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.function.Function;
-
 /**
  * A DbEntity is a mapping descriptor that defines a structure of a database
  * table.
@@ -675,114 +673,17 @@ public class DbEntity extends Entity implements ConfigurationNode, DbEntityListe
         }
 
         String translatePath(String path) {
-
-            // algorithm to determine the translated path:
-            // 0. If relationship has at least one to-many component, travel all
-            // the way
-            // back, and then all the way forward
-            // 1. If relationship path equals to input, travel one step back,
-            // and then one
-            // step forward.
-            // 2. If input completely includes relationship path, use input's
-            // remaining
-            // tail.
-            // 3. If relationship path and input have none or some leading
-            // components in
-            // common,
-            // (a) strip common leading part;
-            // (b) reverse the remaining relationship part;
-            // (c) append remaining input to the reversed remaining
-            // relationship.
-
-            // case (0)
-            if (toMany) {
-                PathComponentIterator pathIt = createPathIterator(path);
-                Iterator<CayenneMapEntry> relationshipIt = resolvePathComponents(relationshipPath);
-
-                // for inserts from the both ends use LinkedList
-                LinkedList<String> finalPath = new LinkedList<>();
-
-                // append remainder of the relationship, reversing it
-                while (relationshipIt.hasNext()) {
-                    DbRelationship nextDBR = (DbRelationship) relationshipIt.next();
-                    prependReversedPath(finalPath, nextDBR);
-                }
-
-                while (pathIt.hasNext()) {
-                    // components may be attributes or relationships
-                    PathComponent<Attribute, Relationship> component = pathIt.next();
-                    appendPath(finalPath, component);
-                }
-
-                return Util.join(finalPath, Entity.PATH_SEPARATOR);
-            }
-            // case (1)
-            if (path.equals(relationshipPath)) {
-
-                LinkedList<String> finalPath = new LinkedList<>();
-                PathComponentIterator pathIt = createPathIterator(path);
-
-                // just do one step back and one step forward to create correct
-                // joins...
-                // find last rel...
-                DbRelationship lastDBR = null;
-
-                while (pathIt.hasNext()) {
-                    // relationship path components must be DbRelationships
-                    lastDBR = (DbRelationship) pathIt.next().getRelationship();
-                }
-
-                if (lastDBR != null) {
-                    prependReversedPath(finalPath, lastDBR);
-                    appendPath(finalPath, lastDBR);
-                }
-
-                return Util.join(finalPath, Entity.PATH_SEPARATOR);
-            }
-
-            // case (2)
-            String relationshipPathWithDot = relationshipPath + Entity.PATH_SEPARATOR;
-            if (path.startsWith(relationshipPathWithDot)) {
-                return path.substring(relationshipPathWithDot.length());
-            }
-
-            // case (3)
-            PathComponentIterator pathIt = createPathIterator(path);
-            Iterator<CayenneMapEntry> relationshipIt = resolvePathComponents(relationshipPath);
-
-            // for inserts from the both ends use LinkedList
             LinkedList<String> finalPath = new LinkedList<>();
-            while (relationshipIt.hasNext() && pathIt.hasNext()) {
+            PathComponentIterator pathIt = createPathIterator(relationshipPath);
+            while (pathIt.hasNext()) {
                 // relationship path components must be DbRelationships
-                DbRelationship nextDBR = (DbRelationship) relationshipIt.next();
-
-                // expression components may be attributes or relationships
-                PathComponent<Attribute, Relationship> component = pathIt.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, component);
-                    break;
+                DbRelationship lastDBR = (DbRelationship) pathIt.next().getRelationship();
+                if(lastDBR != null) {
+                    prependReversedPath(finalPath, lastDBR);
                 }
-
-                break;
-            }
-
-            // append remainder of the relationship, reversing it
-            while (relationshipIt.hasNext()) {
-                DbRelationship nextDBR = (DbRelationship) relationshipIt.next();
-                prependReversedPath(finalPath, nextDBR);
-            }
-
-            while (pathIt.hasNext()) {
-                // components may be attributes or relationships
-                PathComponent<Attribute, Relationship> component = pathIt.next();
-                appendPath(finalPath, component);
             }
 
+            finalPath.add(path);
             return Util.join(finalPath, Entity.PATH_SEPARATOR);
         }
 
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/TranslateExpressionIT.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/TranslateExpressionIT.java
new file mode 100644
index 0000000..2be3e36
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/TranslateExpressionIT.java
@@ -0,0 +1,159 @@
+/*****************************************************************
+ *   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.exp;
+
+import java.util.List;
+
+import org.apache.cayenne.access.DataContext;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.map.ObjEntity;
+import org.apache.cayenne.query.ObjectSelect;
+import org.apache.cayenne.test.jdbc.DBHelper;
+import org.apache.cayenne.test.jdbc.TableHelper;
+import org.apache.cayenne.testdo.testmap.Artist;
+import org.apache.cayenne.testdo.testmap.Gallery;
+import org.apache.cayenne.testdo.testmap.Painting;
+import org.apache.cayenne.unit.di.server.CayenneProjects;
+import org.apache.cayenne.unit.di.server.ServerCase;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
+public class TranslateExpressionIT extends ServerCase {
+
+    @Inject
+    private DataContext context;
+
+    @Inject
+    private DBHelper dbHelper;
+
+    @Before
+    public void createArtistsDataSet() throws Exception {
+        TableHelper tArtist = new TableHelper(dbHelper, "ARTIST");
+        tArtist.setColumns("ARTIST_ID", "ARTIST_NAME", "DATE_OF_BIRTH");
+
+        long dateBase = System.currentTimeMillis();
+        for (int i = 1; i <= 20; i++) {
+            tArtist.insert(i, "artist" + i, new java.sql.Date(dateBase + 10000 * i));
+        }
+
+        TableHelper tGallery = new TableHelper(dbHelper, "GALLERY");
+        tGallery.setColumns("GALLERY_ID", "GALLERY_NAME");
+        tGallery.insert(1, "tate modern");
+
+        TableHelper tPaintings = new TableHelper(dbHelper, "PAINTING");
+        tPaintings.setColumns("PAINTING_ID", "PAINTING_TITLE", "ARTIST_ID", "GALLERY_ID");
+        for (int i = 1; i <= 20; i++) {
+            tPaintings.insert(i, "painting" + i, i % 5 + 1, 1);
+        }
+    }
+
+    @Test
+    public void testPrefetchWithTranslatedExp() {
+        List<Painting> result = ObjectSelect.query(Painting.class)
+                .where(Painting.TO_ARTIST
+                        .dot(Artist.PAINTING_ARRAY)
+                        .dot(Painting.PAINTING_TITLE).like("painting7"))
+                .and(Painting.PAINTING_TITLE.like("painting2"))
+                .prefetch(Painting.TO_ARTIST.disjoint())
+                .select(context);
+        assertEquals(1, result.size());
+        assertEquals("artist3", result.get(0).getToArtist().getArtistName());
+    }
+
+    @Test
+    public void testPrefetchWithTheSamePrefetchAndQualifier() {
+        List<Painting> result = ObjectSelect.query(Painting.class)
+                .where(Painting.TO_GALLERY
+                        .dot(Gallery.PAINTING_ARRAY)
+                        .dot(Painting.PAINTING_TITLE)
+                        .eq("painting1"))
+                .and(Painting.PAINTING_TITLE.like("painting2"))
+                .prefetch(Painting.TO_GALLERY.disjoint())
+                .prefetch(Painting.TO_GALLERY.dot(Gallery.PAINTING_ARRAY).disjoint())
+                .select(context);
+        assertEquals(1, result.size());
+        assertEquals("painting2", result.get(0).getPaintingTitle());
+    }
+
+    @Test
+    public void testTranslateExpression() {
+        ObjEntity entity = context.getEntityResolver().getObjEntity("Painting");
+        Expression expression = ExpressionFactory.pathExp("toArtist.paintingArray");
+        Expression translatedExpression = entity
+                .translateToRelatedEntity(expression, "toArtist");
+        assertEquals(ExpressionFactory
+                .dbPathExp("paintingArray.toArtist.paintingArray"),
+                translatedExpression);
+    }
+
+    @Test
+    public void testRelationshipPathEqualsToInput() {
+        ObjEntity entity = context.getEntityResolver().getObjEntity("Painting");
+        Expression expression = ExpressionFactory.pathExp("toArtist");
+        Expression translatedExpression = entity
+                .translateToRelatedEntity(expression, "toArtist");
+        assertEquals(ExpressionFactory.dbPathExp("paintingArray.toArtist"),
+                translatedExpression);
+    }
+
+    @Test
+    public void testRelationshipNoneLeadingParts() {
+        ObjEntity entity = context.getEntityResolver().getObjEntity("Painting");
+        Expression expression = ExpressionFactory.pathExp("toGallery");
+        Expression translatedExpression = entity
+                .translateToRelatedEntity(expression, "toArtist");
+        assertEquals(ExpressionFactory.dbPathExp("paintingArray.toGallery"),
+                translatedExpression);
+    }
+
+    @Test
+    public void testRelationshipSomeLeadingParts() {
+        ObjEntity entity = context.getEntityResolver().getObjEntity("Painting");
+        Expression expression = ExpressionFactory.pathExp("toGallery");
+        Expression translatedExpression = entity
+                .translateToRelatedEntity(expression, "toArtist.paintingArray.toGallery");
+        assertEquals(ExpressionFactory.dbPathExp("paintingArray.toArtist.paintingArray.toGallery"),
+                translatedExpression);
+    }
+
+    @Test
+    public void testCompQualifier() {
+        ObjEntity entity = context.getEntityResolver().getObjEntity("Painting");
+        Expression expression = ExpressionFactory.pathExp("toArtist.artistExhibitArray.toExhibit");
+        Expression translatedExpression = entity
+                .translateToRelatedEntity(expression, "toGallery");
+        assertEquals(ExpressionFactory.dbPathExp("paintingArray.toArtist.artistExhibitArray.toExhibit"),
+                translatedExpression);
+    }
+
+    @Test
+    public void testCompQualifierAndPref() {
+        ObjEntity entity = context.getEntityResolver().getObjEntity("Artist");
+        Expression expression = ExpressionFactory.pathExp("paintingArray.toGallery");
+        Expression translatedExpression = entity
+                .translateToRelatedEntity(expression, "artistExhibitArray.toExhibit");
+        assertEquals(ExpressionFactory.dbPathExp("artistExhibitArray.toArtist.paintingArray.toGallery"),
+                translatedExpression);
+    }
+}
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/map/DbEntityIT.java b/cayenne-server/src/test/java/org/apache/cayenne/map/DbEntityIT.java
index c0a886f..8523593 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/map/DbEntityIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/map/DbEntityIT.java
@@ -19,6 +19,8 @@
 
 package org.apache.cayenne.map;
 
+import java.util.Collection;
+
 import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.exp.Expression;
@@ -29,8 +31,6 @@ import org.apache.cayenne.unit.di.server.UseServerRuntime;
 import org.apache.cayenne.util.Util;
 import org.junit.Test;
 
-import java.util.Collection;
-
 import static org.junit.Assert.*;
 
 @UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
@@ -270,6 +270,6 @@ public class DbEntityIT extends ServerCase {
         Expression e1 = ExpressionFactory.exp("db:toArtist.ARTIST_NAME = 'aa'");
         Expression translated = paintingE.translateToRelatedEntity(e1, "toArtist");
 
-        assertEquals("failure: " + translated, ExpressionFactory.exp("db:ARTIST_NAME = 'aa'"), translated);
+        assertEquals("failure: " + translated, ExpressionFactory.exp("db:paintingArray.toArtist.ARTIST_NAME = 'aa'"), translated);
     }
 }