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 2020/08/06 12:10:15 UTC

[cayenne] branch master updated (1ff6f1b -> 0e2fe3d)

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

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


    from 1ff6f1b  storing cgen settings
     new dfb4e03  CommitLog does not include FKs for deleted objects CAY-2670
     new 0e2fe3d  CommitLog does not include FKs for deleted objects CAY-2670

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 +
 .../cayenne/commitlog/DeletedDiffProcessor.java    | 35 ++++++++++++++--------
 .../cayenne/commitlog/CommitLogFilterIT.java       | 32 ++++++++++++++++++++
 .../cayenne/commitlog/db/AuditableChild1x.java     |  9 ++++++
 ...AuditableChild1.java => _AuditableChild1x.java} |  4 +--
 .../commitlog/unit/AuditableServerCase.java        |  4 +++
 .../src/test/resources/lifecycle-map.map.xml       | 15 ++++++++++
 7 files changed, 86 insertions(+), 14 deletions(-)
 create mode 100644 cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/db/AuditableChild1x.java
 copy cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/db/auto/{_AuditableChild1.java => _AuditableChild1x.java} (96%)


[cayenne] 02/02: CommitLog does not include FKs for deleted objects CAY-2670

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

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

commit 0e2fe3d164d568c872acfd61c512944b43e900a1
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Thu Aug 6 14:26:51 2020 +0300

    CommitLog does not include FKs for deleted objects CAY-2670
    
    ... release notes
---
 RELEASE-NOTES.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index e89c04a..72693b0 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -20,6 +20,7 @@ CAY-2662 Use custom interface for SQL tree processor instead of a Function<Node,
 CAY-2663 Support for custom SQL operators
 CAY-2664 Add methods to EntityProperty to allow direct usage of primary key values
 CAY-2668 Experimental graph-based db operations sorter
+CAY-2670 CommitLog does not include FKs for deleted objects with one-way relationships
 
 Bug Fixes:
 


[cayenne] 01/02: CommitLog does not include FKs for deleted objects CAY-2670

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

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

commit dfb4e03f61780db62c9700625f0c28ea46f51ef2
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Thu Aug 6 14:26:51 2020 +0300

    CommitLog does not include FKs for deleted objects CAY-2670
    
    ... reproduced and fixed
---
 .../cayenne/commitlog/DeletedDiffProcessor.java    |  35 ++++---
 .../cayenne/commitlog/CommitLogFilterIT.java       |  32 +++++++
 .../cayenne/commitlog/db/AuditableChild1x.java     |   9 ++
 .../commitlog/db/auto/_AuditableChild1x.java       | 106 +++++++++++++++++++++
 .../commitlog/unit/AuditableServerCase.java        |   4 +
 .../src/test/resources/lifecycle-map.map.xml       |  15 +++
 6 files changed, 189 insertions(+), 12 deletions(-)

diff --git a/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/DeletedDiffProcessor.java b/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/DeletedDiffProcessor.java
index a283ef5..deafacf 100644
--- a/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/DeletedDiffProcessor.java
+++ b/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/DeletedDiffProcessor.java
@@ -18,28 +18,25 @@
  ****************************************************************/
 package org.apache.cayenne.commitlog;
 
-import java.util.List;
-
 import org.apache.cayenne.DataChannel;
 import org.apache.cayenne.DataRow;
 import org.apache.cayenne.ObjectId;
 import org.apache.cayenne.QueryResponse;
-import org.apache.cayenne.graph.ArcId;
-import org.apache.cayenne.graph.GraphChangeHandler;
+import org.apache.cayenne.commitlog.meta.CommitLogEntity;
+import org.apache.cayenne.commitlog.meta.CommitLogEntityFactory;
 import org.apache.cayenne.commitlog.model.MutableChangeMap;
 import org.apache.cayenne.commitlog.model.MutableObjectChange;
 import org.apache.cayenne.commitlog.model.ObjectChangeType;
-import org.apache.cayenne.commitlog.meta.CommitLogEntity;
-import org.apache.cayenne.commitlog.meta.CommitLogEntityFactory;
+import org.apache.cayenne.graph.ArcId;
+import org.apache.cayenne.graph.GraphChangeHandler;
+import org.apache.cayenne.map.DbRelationship;
 import org.apache.cayenne.query.ObjectIdQuery;
-import org.apache.cayenne.reflect.AttributeProperty;
-import org.apache.cayenne.reflect.ClassDescriptor;
-import org.apache.cayenne.reflect.PropertyVisitor;
-import org.apache.cayenne.reflect.ToManyProperty;
-import org.apache.cayenne.reflect.ToOneProperty;
+import org.apache.cayenne.reflect.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.List;
+
 class DeletedDiffProcessor implements GraphChangeHandler {
 
 	private static final Logger LOGGER = LoggerFactory.getLogger(DeletedDiffProcessor.class);
@@ -102,7 +99,21 @@ class DeletedDiffProcessor implements GraphChangeHandler {
 
 			@Override
 			public boolean visitToOne(ToOneProperty property) {
-				// TODO record FK changes?
+                if (!entity.isIncluded(property.getName())) {
+                    return true;
+                }
+
+                // TODO: is there such a thing as "confidential" relationship that we need to hide?
+
+                DbRelationship dbRelationship = property.getRelationship().getDbRelationships().get(0);
+
+                ObjectId value = row.createTargetObjectId(
+                        property.getTargetDescriptor().getEntity().getName(),
+                        dbRelationship);
+
+                if (value != null) {
+                    objectChangeSet.toOneRelationshipDisconnected(property.getName(), value);
+                }
 				return true;
 			}
 
diff --git a/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/CommitLogFilterIT.java b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/CommitLogFilterIT.java
index 4ed21f3..f3a6302 100644
--- a/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/CommitLogFilterIT.java
+++ b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/CommitLogFilterIT.java
@@ -22,6 +22,7 @@ import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.ObjectId;
 import org.apache.cayenne.commitlog.db.Auditable1;
 import org.apache.cayenne.commitlog.db.AuditableChild1;
+import org.apache.cayenne.commitlog.db.AuditableChild1x;
 import org.apache.cayenne.commitlog.model.*;
 import org.apache.cayenne.commitlog.unit.AuditableServerCase;
 import org.apache.cayenne.configuration.server.ServerRuntimeBuilder;
@@ -186,6 +187,37 @@ public class CommitLogFilterIT extends AuditableServerCase {
     }
 
     @Test
+    public void testPostCommit_Delete_ToOne_OneWay() throws SQLException {
+        auditable1.insert(1, "xx");
+        auditableChild1x.insert(1, 1, "cc1");
+        auditableChild1x.insert(2, 1, "cc2");
+
+        AuditableChild1x ac1 = SelectById.query(AuditableChild1x.class, 2).selectOne(context);
+        context.deleteObject(ac1);
+        context.commitChanges();
+
+        ArgumentCaptor<ChangeMap> changeMap = ArgumentCaptor.forClass(ChangeMap.class);
+        verify(mockListener).onPostCommit(any(ObjectContext.class), changeMap.capture());
+
+        assertNotNull(changeMap.getValue());
+        assertEquals(1, changeMap.getValue().getUniqueChanges().size());
+
+        ObjectChange change = changeMap.getValue().getChanges().get(ObjectId.of("AuditableChild1x", AuditableChild1x.ID_PK_COLUMN, 2));
+        assertNotNull(change);
+        assertEquals(ObjectChangeType.DELETE, change.getType());
+
+        assertEquals(1, change.getAttributeChanges().size());
+        assertEquals("cc2", change.getAttributeChanges().get(AuditableChild1x.CHAR_PROPERTY1.getName()).getOldValue());
+        assertNull(change.getAttributeChanges().get(AuditableChild1x.CHAR_PROPERTY1.getName()).getNewValue());
+
+        assertTrue("No 1..N relationships in the entity", change.getToManyRelationshipChanges().isEmpty());
+        assertEquals("N..1 state was not captured", 1, change.getToOneRelationshipChanges().size());
+        assertEquals(ObjectId.of("Auditable1", Auditable1.ID_PK_COLUMN, 1),
+                change.getToOneRelationshipChanges().get(AuditableChild1x.PARENT.getName()).getOldValue());
+    }
+
+
+    @Test
     public void testPostCommit_UpdateToOne() throws SQLException {
         auditable1.insert(1, "xx");
         auditable1.insert(2, "yy");
diff --git a/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/db/AuditableChild1x.java b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/db/AuditableChild1x.java
new file mode 100644
index 0000000..7d8c4a6
--- /dev/null
+++ b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/db/AuditableChild1x.java
@@ -0,0 +1,9 @@
+package org.apache.cayenne.commitlog.db;
+
+import org.apache.cayenne.commitlog.db.auto._AuditableChild1x;
+
+public class AuditableChild1x extends _AuditableChild1x {
+
+    private static final long serialVersionUID = 1L; 
+
+}
diff --git a/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/db/auto/_AuditableChild1x.java b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/db/auto/_AuditableChild1x.java
new file mode 100644
index 0000000..6889a4b
--- /dev/null
+++ b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/db/auto/_AuditableChild1x.java
@@ -0,0 +1,106 @@
+package org.apache.cayenne.commitlog.db.auto;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.apache.cayenne.BaseDataObject;
+import org.apache.cayenne.commitlog.db.Auditable1;
+import org.apache.cayenne.exp.property.EntityProperty;
+import org.apache.cayenne.exp.property.PropertyFactory;
+import org.apache.cayenne.exp.property.StringProperty;
+
+/**
+ * Class _AuditableChild1x was generated by Cayenne.
+ * It is probably a good idea to avoid changing this class manually,
+ * since it may be overwritten next time code is regenerated.
+ * If you need to make any customizations, please use subclass.
+ */
+public abstract class _AuditableChild1x extends BaseDataObject {
+
+    private static final long serialVersionUID = 1L; 
+
+    public static final String ID_PK_COLUMN = "ID";
+
+    public static final StringProperty<String> CHAR_PROPERTY1 = PropertyFactory.createString("charProperty1", String.class);
+    public static final EntityProperty<Auditable1> PARENT = PropertyFactory.createEntity("parent", Auditable1.class);
+
+    protected String charProperty1;
+
+    protected Object parent;
+
+    public void setCharProperty1(String charProperty1) {
+        beforePropertyWrite("charProperty1", this.charProperty1, charProperty1);
+        this.charProperty1 = charProperty1;
+    }
+
+    public String getCharProperty1() {
+        beforePropertyRead("charProperty1");
+        return this.charProperty1;
+    }
+
+    public void setParent(Auditable1 parent) {
+        setToOneTarget("parent", parent, true);
+    }
+
+    public Auditable1 getParent() {
+        return (Auditable1)readProperty("parent");
+    }
+
+    @Override
+    public Object readPropertyDirectly(String propName) {
+        if(propName == null) {
+            throw new IllegalArgumentException();
+        }
+
+        switch(propName) {
+            case "charProperty1":
+                return this.charProperty1;
+            case "parent":
+                return this.parent;
+            default:
+                return super.readPropertyDirectly(propName);
+        }
+    }
+
+    @Override
+    public void writePropertyDirectly(String propName, Object val) {
+        if(propName == null) {
+            throw new IllegalArgumentException();
+        }
+
+        switch (propName) {
+            case "charProperty1":
+                this.charProperty1 = (String)val;
+                break;
+            case "parent":
+                this.parent = val;
+                break;
+            default:
+                super.writePropertyDirectly(propName, val);
+        }
+    }
+
+    private void writeObject(ObjectOutputStream out) throws IOException {
+        writeSerialized(out);
+    }
+
+    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+        readSerialized(in);
+    }
+
+    @Override
+    protected void writeState(ObjectOutputStream out) throws IOException {
+        super.writeState(out);
+        out.writeObject(this.charProperty1);
+        out.writeObject(this.parent);
+    }
+
+    @Override
+    protected void readState(ObjectInputStream in) throws IOException, ClassNotFoundException {
+        super.readState(in);
+        this.charProperty1 = (String)in.readObject();
+        this.parent = in.readObject();
+    }
+
+}
diff --git a/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/unit/AuditableServerCase.java b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/unit/AuditableServerCase.java
index 570a54f..67ee30d 100644
--- a/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/unit/AuditableServerCase.java
+++ b/cayenne-commitlog/src/test/java/org/apache/cayenne/commitlog/unit/AuditableServerCase.java
@@ -34,6 +34,7 @@ public abstract class AuditableServerCase {
 
 	protected TableHelper auditable1;
 	protected TableHelper auditableChild1;
+	protected TableHelper auditableChild1x;
 
 	protected TableHelper auditable2;
 	protected TableHelper auditableChild3;
@@ -55,6 +56,8 @@ public abstract class AuditableServerCase {
 
 		this.auditableChild1 = new TableHelper(dbHelper, "AUDITABLE_CHILD1").setColumns("ID", "AUDITABLE1_ID",
 				"CHAR_PROPERTY1");
+		this.auditableChild1x = new TableHelper(dbHelper, "AUDITABLE_CHILD1X").setColumns("ID", "AUDITABLE1_ID",
+				"CHAR_PROPERTY1");
 
 		this.auditable2 = new TableHelper(dbHelper, "AUDITABLE2").setColumns("ID", "CHAR_PROPERTY1", "CHAR_PROPERTY2");
 
@@ -66,6 +69,7 @@ public abstract class AuditableServerCase {
 				"AUDITABLE3_ID");
 
 		this.auditableChild1.deleteAll();
+		this.auditableChild1x.deleteAll();
 		this.auditable1.deleteAll();
 		this.auditableChild3.deleteAll();
 		this.auditable2.deleteAll();
diff --git a/cayenne-commitlog/src/test/resources/lifecycle-map.map.xml b/cayenne-commitlog/src/test/resources/lifecycle-map.map.xml
index ab173e0..fc3bb20 100644
--- a/cayenne-commitlog/src/test/resources/lifecycle-map.map.xml
+++ b/cayenne-commitlog/src/test/resources/lifecycle-map.map.xml
@@ -29,6 +29,11 @@
 		<db-attribute name="CHAR_PROPERTY1" type="VARCHAR" length="200"/>
 		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
 	</db-entity>
+	<db-entity name="AUDITABLE_CHILD1X">
+		<db-attribute name="AUDITABLE1_ID" type="INTEGER"/>
+		<db-attribute name="CHAR_PROPERTY1" type="VARCHAR" length="200"/>
+		<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+	</db-entity>
 	<db-entity name="AUDITABLE_CHILD3">
 		<db-attribute name="AUDITABLE2_ID" type="INTEGER"/>
 		<db-attribute name="CHAR_PROPERTY1" type="VARCHAR" length="200"/>
@@ -76,6 +81,9 @@
 	<obj-entity name="AuditableChild1" className="org.apache.cayenne.commitlog.db.AuditableChild1" dbEntityName="AUDITABLE_CHILD1">
 		<obj-attribute name="charProperty1" type="java.lang.String" db-attribute-path="CHAR_PROPERTY1"/>
 	</obj-entity>
+	<obj-entity name="AuditableChild1x" className="org.apache.cayenne.commitlog.db.AuditableChild1x" dbEntityName="AUDITABLE_CHILD1X">
+		<obj-attribute name="charProperty1" type="java.lang.String" db-attribute-path="CHAR_PROPERTY1"/>
+	</obj-entity>
 	<obj-entity name="AuditableChild3" className="org.apache.cayenne.commitlog.db.AuditableChild3" dbEntityName="AUDITABLE_CHILD3">
 		<obj-attribute name="charProperty1" type="java.lang.String" db-attribute-path="CHAR_PROPERTY1"/>
 		<obj-attribute name="charProperty2" type="java.lang.String" db-attribute-path="CHAR_PROPERTY2"/>
@@ -87,6 +95,9 @@
 	<db-relationship name="children1" source="AUDITABLE1" target="AUDITABLE_CHILD1" toMany="true">
 		<db-attribute-pair source="ID" target="AUDITABLE1_ID"/>
 	</db-relationship>
+	<db-relationship name="children1x" source="AUDITABLE1" target="AUDITABLE_CHILD1X" toMany="true">
+		<db-attribute-pair source="ID" target="AUDITABLE1_ID"/>
+	</db-relationship>
 	<db-relationship name="children" source="AUDITABLE2" target="AUDITABLE_CHILD3" toMany="true">
 		<db-attribute-pair source="ID" target="AUDITABLE2_ID"/>
 	</db-relationship>
@@ -99,6 +110,9 @@
 	<db-relationship name="parent" source="AUDITABLE_CHILD1" target="AUDITABLE1">
 		<db-attribute-pair source="AUDITABLE1_ID" target="ID"/>
 	</db-relationship>
+	<db-relationship name="parent" source="AUDITABLE_CHILD1X" target="AUDITABLE1">
+		<db-attribute-pair source="AUDITABLE1_ID" target="ID"/>
+	</db-relationship>
 	<db-relationship name="parent" source="AUDITABLE_CHILD3" target="AUDITABLE2">
 		<db-attribute-pair source="AUDITABLE2_ID" target="ID"/>
 	</db-relationship>
@@ -119,6 +133,7 @@
 	<obj-relationship name="auditable4s" source="Auditable3" target="Auditable4" deleteRule="Deny" db-relationship-path="auditable4s"/>
 	<obj-relationship name="auditable3" source="Auditable4" target="Auditable3" deleteRule="Nullify" db-relationship-path="auditable3"/>
 	<obj-relationship name="parent" source="AuditableChild1" target="Auditable1" deleteRule="Nullify" db-relationship-path="parent"/>
+	<obj-relationship name="parent" source="AuditableChild1x" target="Auditable1" deleteRule="Nullify" db-relationship-path="parent"/>
 	<obj-relationship name="parent" source="AuditableChild3" target="Auditable2" deleteRule="Nullify" db-relationship-path="parent"/>
 	<obj-relationship name="e4s" source="E3" target="E4" deleteRule="Deny" db-relationship-path="e34s.e4"/>
 	<obj-relationship name="e3s" source="E4" target="E3" deleteRule="Deny" db-relationship-path="e34s.e3"/>