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 2021/03/11 12:00:57 UTC

[cayenne] branch master updated: CAY-2693 Abstract subentities do not have rows materialized correctly

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


The following commit(s) were added to refs/heads/master by this push:
     new 21cda93  CAY-2693 Abstract subentities do not have rows materialized correctly
21cda93 is described below

commit 21cda9370698e7223263c9269b5ce63f15bb3ffb
Author: Nikita Timofeev <st...@gmail.com>
AuthorDate: Thu Mar 11 15:00:23 2021 +0300

    CAY-2693 Abstract subentities do not have rows materialized correctly
---
 RELEASE-NOTES.txt                                  |  1 +
 .../apache/cayenne/map/EntityInheritanceTree.java  | 22 ++++----
 .../cayenne/map/EntityInheritanceTreeTest.java     | 62 +++++++++++++++++++++-
 3 files changed, 74 insertions(+), 11 deletions(-)

diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 8445176..e242a4b 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -29,6 +29,7 @@ CAY-2686 SQL translator incorrectly quotes fully qualified tables' names
 CAY-2687 Modeler Migrate Repeatedly Asks to Set Column Type for MySQL
 CAY-2690 dbimport skips length changes for BINARY and VARBINARY columns
 CAY-2691 MySQL driver 8.0.x stores LocalDateTime differently than 5.1.x
+CAY-2693 Abstract subentities do not have rows materialized correctly
 CAY-2694 Precision issues with reverse / forward engineering of time types on MySQL
 CAY-2695 Reverse engineering on SQLite fails due to feature not being supported
 CAY-2698 EventSubject.getSubject() is not thread safe
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/EntityInheritanceTree.java b/cayenne-server/src/main/java/org/apache/cayenne/map/EntityInheritanceTree.java
index 18f859b..0e7df3d 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/EntityInheritanceTree.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/EntityInheritanceTree.java
@@ -34,7 +34,8 @@ import java.util.Collections;
  */
 public class EntityInheritanceTree {
 
-    protected ObjEntity entity;
+    protected final ObjEntity entity;
+    protected EntityInheritanceTree parent;
     protected Collection<EntityInheritanceTree> subentities;
     protected Expression normalizedQualifier;
 
@@ -43,13 +44,12 @@ public class EntityInheritanceTree {
     }
 
     /**
-     * Returns a qualifier Expression that matches root entity of this tree and all its
-     * subentities.
+     * Returns a qualifier Expression that matches root entity of this tree and all its subentities.
      */
     public Expression qualifierForEntityAndSubclasses() {
         Expression qualifier = entity.getDeclaredQualifier();
 
-        if (qualifier == null) {
+        if (qualifier == null && parent == null) {
             // match all
             return null;
         }
@@ -58,13 +58,16 @@ public class EntityInheritanceTree {
             for (EntityInheritanceTree child : subentities) {
                 Expression childQualifier = child.qualifierForEntityAndSubclasses();
 
-                // if any child qualifier is null, just return null, since no filtering is
-                // possible
+                // if any child qualifier is null, just return null, since no filtering is possible
                 if (childQualifier == null) {
                     return null;
                 }
 
-                qualifier = qualifier.orExp(childQualifier);
+                if(qualifier == null) {
+                    qualifier = childQualifier;
+                } else {
+                    qualifier = qualifier.orExp(childQualifier);
+                }
             }
         }
 
@@ -93,7 +96,7 @@ public class EntityInheritanceTree {
         }
 
         // no qualifier ... matches all rows
-        return entity;
+        return parent == null ? entity : null;
     }
 
     /**
@@ -120,6 +123,7 @@ public class EntityInheritanceTree {
         }
 
         subentities.add(node);
+        node.parent = this;
     }
 
     public int getChildrenCount() {
@@ -127,7 +131,7 @@ public class EntityInheritanceTree {
     }
 
     public Collection<EntityInheritanceTree> getChildren() {
-        return (subentities != null) ? subentities : Collections.<EntityInheritanceTree>emptyList();
+        return (subentities != null) ? subentities : Collections.emptyList();
     }
 
     public ObjEntity getEntity() {
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/map/EntityInheritanceTreeTest.java b/cayenne-server/src/test/java/org/apache/cayenne/map/EntityInheritanceTreeTest.java
index 680d5ab..b18f4fa 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/map/EntityInheritanceTreeTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/map/EntityInheritanceTreeTest.java
@@ -24,6 +24,7 @@ import org.junit.Test;
 
 import java.util.Collections;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 
@@ -76,8 +77,7 @@ public class EntityInheritanceTreeTest {
         subEntity.setDeclaredQualifier(ExpressionFactory.matchDbExp("x", 1));
         dataMap.addObjEntity(subEntity);
 
-        // creating EntityInheritanceTree via EntityResolver to ensure the entities are
-        // indexed
+        // creating EntityInheritanceTree via EntityResolver to ensure the entities are indexed
         EntityResolver resolver = new EntityResolver(Collections.singleton(dataMap));
         EntityInheritanceTree t1 = resolver.getInheritanceTree("E1");
 
@@ -94,4 +94,62 @@ public class EntityInheritanceTreeTest {
         assertSame(entity, t1.entityMatchingRow(row12));
         assertNull(t1.entityMatchingRow(row13));
     }
+
+    @Test
+    public void testEntityMatchingRow_CAY_2693() {
+        DataMap dataMap = new DataMap("map");
+
+        DbEntity dbEntity = new DbEntity("a");
+        dbEntity.addAttribute(new DbAttribute("type"));
+        dataMap.addDbEntity(dbEntity);
+
+        ObjEntity entityA = new ObjEntity("A");
+        entityA.setAbstract(true);
+        entityA.setDbEntityName(dbEntity.getName());
+        dataMap.addObjEntity(entityA);
+
+        ObjEntity subEntityC = new ObjEntity("AC"); // name it AC so it would be sorted before B
+        subEntityC.setSuperEntityName("A");
+        subEntityC.setAbstract(true);
+        dataMap.addObjEntity(subEntityC);
+
+        ObjEntity subEntityB = new ObjEntity("B");
+        subEntityB.setSuperEntityName("A");
+        subEntityB.setDeclaredQualifier(ExpressionFactory.matchDbExp("type", 0));
+        dataMap.addObjEntity(subEntityB);
+
+        ObjEntity subEntityD = new ObjEntity("D");
+        subEntityD.setSuperEntityName("AC");
+        subEntityD.setDeclaredQualifier(ExpressionFactory.matchDbExp("type", 1));
+        dataMap.addObjEntity(subEntityD);
+
+        ObjEntity subEntityE = new ObjEntity("E");
+        subEntityE.setSuperEntityName("AC");
+        subEntityE.setDeclaredQualifier(ExpressionFactory.matchDbExp("type", 2));
+        dataMap.addObjEntity(subEntityE);
+
+        // creating EntityInheritanceTree via EntityResolver to ensure the entities are indexed
+        EntityResolver resolver = new EntityResolver(Collections.singleton(dataMap));
+        EntityInheritanceTree treeA = resolver.getInheritanceTree("A");
+        EntityInheritanceTree treeC = resolver.getInheritanceTree("AC");
+
+        DataRow row11 = new DataRow(5);
+        row11.put("type", 0);
+
+        DataRow row12 = new DataRow(5);
+        row12.put("type", 1);
+
+        DataRow row13 = new DataRow(5);
+        row13.put("type", 2);
+
+        assertSame(subEntityB, treeA.entityMatchingRow(row11));
+        assertSame(subEntityD, treeA.entityMatchingRow(row12));
+        assertSame(subEntityE, treeA.entityMatchingRow(row13));
+
+        assertSame(subEntityD, treeC.entityMatchingRow(row12));
+        assertSame(subEntityE, treeC.entityMatchingRow(row13));
+
+        assertNull(treeA.qualifierForEntityAndSubclasses());
+        assertEquals(ExpressionFactory.exp("(db:type = 1) or (db:type = 2)"), treeC.qualifierForEntityAndSubclasses());
+    }
 }