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

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


The following commit(s) were added to refs/heads/STABLE-4.2 by this push:
     new 105a8e2bc CAY-2840 Vertical Inheritance: Missing subclass attributes 
with joint prefetch
105a8e2bc is described below

commit 105a8e2bc9b60a5b0db37191dc70a4a898d58120
Author: Jadon Hansell <130694311+jghans...@users.noreply.github.com>
AuthorDate: Mon Feb 5 22:58:28 2024 +0400

    CAY-2840 Vertical Inheritance: Missing subclass attributes with joint 
prefetch
    
    (cherry picked from commit 2358f52a9c7728751ddc5aea68f973a84f1c8f35)
---
 RELEASE-NOTES.txt                                  |  1 +
 .../select/DescriptorColumnExtractor.java          |  6 ++++-
 .../cayenne/access/VerticalInheritanceIT.java      | 30 ++++++++++++++++++++++
 .../testdo/inheritance_vertical/auto/_IvBase.java  | 25 ++++++++++++++++++
 .../testdo/inheritance_vertical/auto/_IvOther.java | 19 ++++++++++++++
 .../test/resources/inheritance-vertical.map.xml    |  9 +++++++
 6 files changed, 89 insertions(+), 1 deletion(-)

diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index ab27b4664..cf9643a37 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -20,6 +20,7 @@ CAY-2809 Cayenne Expression grammar doesn't allow custom 
function as an argument
 CAY-2810 Can't use custom operator expression with aggregate functions
 CAY-2813 Regression: Constants.CI_PROPERTY flag is no longer working for MySQL
 CAY-2815 Incorrect translation of aliased expression
+CAY-2840 Vertical Inheritance: Missing subclass attributes with joint prefetch
 
 ----------------------------------
 Release: 4.2
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DescriptorColumnExtractor.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DescriptorColumnExtractor.java
index 1cb72ff1a..ad4ee573f 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DescriptorColumnExtractor.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/DescriptorColumnExtractor.java
@@ -128,7 +128,11 @@ class DescriptorColumnExtractor extends 
BaseColumnExtractor implements PropertyV
                 }
                 if (count > 1) {
                     // it was a flattened attribute, so need to keep full path 
info
-                    String dataRowKey = result.getAttributePaths().get(i) + 
"." + dbAttribute.getName();
+                    String attributePath = result.getAttributePaths().get(i);
+                    if (attributePath.startsWith(PREFETCH_PREFIX)) {
+                        attributePath = 
attributePath.substring(PREFETCH_PREFIX.length());
+                    }
+                    String dataRowKey = attributePath + "." + 
dbAttribute.getName();
                     resultNodeDescriptor.setDataRowKey(dataRowKey);
                     addEntityResultField(dataRowKey);
                 } else {
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/access/VerticalInheritanceIT.java
 
b/cayenne-server/src/test/java/org/apache/cayenne/access/VerticalInheritanceIT.java
index a0cf075f7..320f22051 100644
--- 
a/cayenne-server/src/test/java/org/apache/cayenne/access/VerticalInheritanceIT.java
+++ 
b/cayenne-server/src/test/java/org/apache/cayenne/access/VerticalInheritanceIT.java
@@ -682,6 +682,36 @@ public class VerticalInheritanceIT extends ServerCase {
                assertEquals(2, 
ObjectSelect.query(IvImpl.class).selectCount(context));
        }
 
+       /**
+        * @link https://issues.apache.org/jira/browse/CAY-2840
+        */
+       @Test
+       public void testJointPrefetchBelongsTo() throws SQLException {
+               TableHelper ivOtherTable = new TableHelper(dbHelper, 
"IV_OTHER");
+               ivOtherTable.setColumns("ID", "NAME", 
"BASE_ID").setColumnTypes(Types.INTEGER, Types.VARCHAR, Types.INTEGER);
+
+               TableHelper ivBaseTable = new TableHelper(dbHelper, "IV_BASE");
+               ivBaseTable.setColumns("ID", "NAME", 
"TYPE").setColumnTypes(Types.INTEGER, Types.VARCHAR, Types.CHAR);
+
+               TableHelper ivImplTable = new TableHelper(dbHelper, "IV_IMPL");
+               ivImplTable.setColumns("ID", 
"ATTR1").setColumnTypes(Types.INTEGER, Types.VARCHAR);
+
+               ivBaseTable.insert(1, "Impl 1", "I");
+               ivImplTable.insert(1, "attr1");
+               ivOtherTable.insert(1, "other1", 1);
+
+               IvOther other = 
ObjectSelect.query(IvOther.class).prefetch(IvOther.BASE.joint()).selectOne(context);
+               assertNotNull(other);
+               assertNotNull(other.getBase());
+               
assertTrue(IvImpl.class.isAssignableFrom(other.getBase().getClass()));
+
+               IvImpl impl = (IvImpl)other.getBase();
+               // Ensure that base attributes were prefetched correctly
+               assertEquals("Impl 1", impl.getName());
+               // Ensure that subclass attributes were prefetched correctly
+               assertEquals("attr1", impl.getAttr1());
+       }
+
        /**
         * @link https://issues.apache.org/jira/browse/CAY-2282
         */
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvBase.java
 
b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvBase.java
index 97c2e182f..dbc850c03 100644
--- 
a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvBase.java
+++ 
b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvBase.java
@@ -4,9 +4,12 @@ import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 
+import java.util.List;
 import org.apache.cayenne.BaseDataObject;
+import org.apache.cayenne.exp.property.ListProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.exp.property.StringProperty;
+import org.apache.cayenne.testdo.inheritance_vertical.IvOther;
 
 /**
  * Class _IvBase was generated by Cayenne.
@@ -22,10 +25,12 @@ public abstract class _IvBase extends BaseDataObject {
 
     public static final StringProperty<String> NAME = 
PropertyFactory.createString("name", String.class);
     public static final StringProperty<String> TYPE = 
PropertyFactory.createString("type", String.class);
+    public static final ListProperty<IvOther> OTHERS = 
PropertyFactory.createList("others", IvOther.class);
 
     protected String name;
     protected String type;
 
+    protected Object others;
 
     public void setName(String name) {
         beforePropertyWrite("name", this.name, name);
@@ -47,6 +52,19 @@ public abstract class _IvBase extends BaseDataObject {
         return this.type;
     }
 
+    public void addToOthers(IvOther obj) {
+        addToManyTarget("others", obj, true);
+    }
+
+    public void removeFromOthers(IvOther obj) {
+        removeToManyTarget("others", obj, true);
+    }
+
+    @SuppressWarnings("unchecked")
+    public List<IvOther> getOthers() {
+        return (List<IvOther>)readProperty("others");
+    }
+
     @Override
     public Object readPropertyDirectly(String propName) {
         if(propName == null) {
@@ -58,6 +76,8 @@ public abstract class _IvBase extends BaseDataObject {
                 return this.name;
             case "type":
                 return this.type;
+            case "others":
+                return this.others;
             default:
                 return super.readPropertyDirectly(propName);
         }
@@ -76,6 +96,9 @@ public abstract class _IvBase extends BaseDataObject {
             case "type":
                 this.type = (String)val;
                 break;
+            case "others":
+                this.others = val;
+                break;
             default:
                 super.writePropertyDirectly(propName, val);
         }
@@ -94,6 +117,7 @@ public abstract class _IvBase extends BaseDataObject {
         super.writeState(out);
         out.writeObject(this.name);
         out.writeObject(this.type);
+        out.writeObject(this.others);
     }
 
     @Override
@@ -101,6 +125,7 @@ public abstract class _IvBase extends BaseDataObject {
         super.readState(in);
         this.name = (String)in.readObject();
         this.type = (String)in.readObject();
+        this.others = in.readObject();
     }
 
 }
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvOther.java
 
b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvOther.java
index 075309868..1d681139d 100644
--- 
a/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvOther.java
+++ 
b/cayenne-server/src/test/java/org/apache/cayenne/testdo/inheritance_vertical/auto/_IvOther.java
@@ -6,9 +6,11 @@ import java.io.ObjectOutputStream;
 import java.util.List;
 
 import org.apache.cayenne.BaseDataObject;
+import org.apache.cayenne.exp.property.EntityProperty;
 import org.apache.cayenne.exp.property.ListProperty;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.exp.property.StringProperty;
+import org.apache.cayenne.testdo.inheritance_vertical.IvBase;
 import org.apache.cayenne.testdo.inheritance_vertical.IvImpl;
 import org.apache.cayenne.testdo.inheritance_vertical.IvImplWithLock;
 
@@ -25,11 +27,13 @@ public abstract class _IvOther extends BaseDataObject {
     public static final String ID_PK_COLUMN = "ID";
 
     public static final StringProperty<String> NAME = 
PropertyFactory.createString("name", String.class);
+    public static final EntityProperty<IvBase> BASE = 
PropertyFactory.createEntity("base", IvBase.class);
     public static final ListProperty<IvImpl> IMPLS = 
PropertyFactory.createList("impls", IvImpl.class);
     public static final ListProperty<IvImplWithLock> IMPLS_WITH_LOCK = 
PropertyFactory.createList("implsWithLock", IvImplWithLock.class);
 
     protected String name;
 
+    protected Object base;
     protected Object impls;
     protected Object implsWithLock;
 
@@ -43,6 +47,14 @@ public abstract class _IvOther extends BaseDataObject {
         return this.name;
     }
 
+    public void setBase(IvBase base) {
+        setToOneTarget("base", base, true);
+    }
+
+    public IvBase getBase() {
+        return (IvBase)readProperty("base");
+    }
+
     public void addToImpls(IvImpl obj) {
         addToManyTarget("impls", obj, true);
     }
@@ -78,6 +90,8 @@ public abstract class _IvOther extends BaseDataObject {
         switch(propName) {
             case "name":
                 return this.name;
+            case "base":
+                return this.base;
             case "impls":
                 return this.impls;
             case "implsWithLock":
@@ -97,6 +111,9 @@ public abstract class _IvOther extends BaseDataObject {
             case "name":
                 this.name = (String)val;
                 break;
+            case "base":
+                this.base = val;
+                break;
             case "impls":
                 this.impls = val;
                 break;
@@ -120,6 +137,7 @@ public abstract class _IvOther extends BaseDataObject {
     protected void writeState(ObjectOutputStream out) throws IOException {
         super.writeState(out);
         out.writeObject(this.name);
+        out.writeObject(this.base);
         out.writeObject(this.impls);
         out.writeObject(this.implsWithLock);
     }
@@ -128,6 +146,7 @@ public abstract class _IvOther extends BaseDataObject {
     protected void readState(ObjectInputStream in) throws IOException, 
ClassNotFoundException {
         super.readState(in);
         this.name = (String)in.readObject();
+        this.base = in.readObject();
         this.impls = in.readObject();
         this.implsWithLock = in.readObject();
     }
diff --git a/cayenne-server/src/test/resources/inheritance-vertical.map.xml 
b/cayenne-server/src/test/resources/inheritance-vertical.map.xml
index 9c2939727..4fa04258a 100644
--- a/cayenne-server/src/test/resources/inheritance-vertical.map.xml
+++ b/cayenne-server/src/test/resources/inheritance-vertical.map.xml
@@ -66,6 +66,7 @@
                <db-attribute name="OTHER1_ID" type="INTEGER" 
isMandatory="true"/>
        </db-entity>
        <db-entity name="IV_OTHER">
+               <db-attribute name="BASE_ID" type="INTEGER"/>
                <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" 
isMandatory="true"/>
                <db-attribute name="NAME" type="VARCHAR" length="100"/>
        </db-entity>
@@ -202,6 +203,9 @@
        <db-relationship name="impl" source="IV_BASE" target="IV_IMPL" 
toDependentPK="true">
                <db-attribute-pair source="ID" target="ID"/>
        </db-relationship>
+       <db-relationship name="others" source="IV_BASE" target="IV_OTHER" 
toMany="true">
+               <db-attribute-pair source="ID" target="BASE_ID"/>
+       </db-relationship>
        <db-relationship name="impl" source="IV_BASE_WITH_LOCK" 
target="IV_IMPL_WITH_LOCK" toDependentPK="true">
                <db-attribute-pair source="ID" target="ID"/>
        </db-relationship>
@@ -229,6 +233,9 @@
        <db-relationship name="other1" source="IV_IMPL_WITH_LOCK" 
target="IV_OTHER">
                <db-attribute-pair source="OTHER1_ID" target="ID"/>
        </db-relationship>
+       <db-relationship name="base" source="IV_OTHER" target="IV_BASE">
+               <db-attribute-pair source="BASE_ID" target="ID"/>
+       </db-relationship>
        <db-relationship name="impls" source="IV_OTHER" target="IV_IMPL" 
toMany="true">
                <db-attribute-pair source="ID" target="OTHER_ID"/>
        </db-relationship>
@@ -263,11 +270,13 @@
                <db-attribute-pair source="IV_ROOT_ID" target="ID"/>
        </db-relationship>
        <obj-relationship name="x" source="Iv2Sub1" target="Iv2X" 
deleteRule="Nullify" db-relationship-path="sub1.x"/>
+       <obj-relationship name="others" source="IvBase" target="IvOther" 
deleteRule="Deny" db-relationship-path="others"/>
        <obj-relationship name="children" source="IvConcrete" 
target="IvConcrete" deleteRule="Deny" db-relationship-path="children"/>
        <obj-relationship name="parent" source="IvConcrete" target="IvConcrete" 
deleteRule="Nullify" db-relationship-path="parent"/>
        <obj-relationship name="other1" source="IvImpl" target="IvOther" 
deleteRule="Nullify" db-relationship-path="impl.other1"/>
        <obj-relationship name="other2" source="IvImpl" target="IvOther" 
deleteRule="Nullify" db-relationship-path="impl.other2"/>
        <obj-relationship name="other1" source="IvImplWithLock" 
target="IvOther" deleteRule="Nullify" db-relationship-path="impl.other1"/>
+       <obj-relationship name="base" source="IvOther" target="IvBase" 
deleteRule="Nullify" db-relationship-path="base"/>
        <obj-relationship name="impls" source="IvOther" target="IvImpl" 
deleteRule="Deny" db-relationship-path="impls.base"/>
        <obj-relationship name="implsWithLock" source="IvOther" 
target="IvImplWithLock" deleteRule="Deny" db-relationship-path="impls.base"/>
        <obj-relationship name="ivRoot" source="IvSub3" target="IvRoot" 
deleteRule="Nullify" db-relationship-path="sub3.ivRoot1"/>

Reply via email to