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 2017/02/24 07:17:06 UTC

cayenne git commit: CAY-2242 Fix from Matt Watson for multiple insertion case.

Repository: cayenne
Updated Branches:
  refs/heads/master 0c3e3b68c -> 91eb2c0ae


CAY-2242 Fix from Matt Watson for multiple insertion case.


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/91eb2c0a
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/91eb2c0a
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/91eb2c0a

Branch: refs/heads/master
Commit: 91eb2c0aede06162de39ab27f73ccc467b14fc6e
Parents: 0c3e3b6
Author: Nikita Timofeev <st...@gmail.com>
Authored: Fri Feb 24 09:56:29 2017 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Fri Feb 24 09:56:29 2017 +0300

----------------------------------------------------------------------
 .../access/DataDomainFlattenedBucket.java       | 67 +++++++++++++-------
 .../cayenne/access/VerticalInheritanceIT.java   | 27 ++++++++
 2 files changed, 71 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/91eb2c0a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainFlattenedBucket.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainFlattenedBucket.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainFlattenedBucket.java
index b88a341..900174e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainFlattenedBucket.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainFlattenedBucket.java
@@ -108,29 +108,53 @@ class DataDomainFlattenedBucket {
             List<FlattenedArcKey> flattenedArcKeys = entry.getValue();
 
             DataNode node = parent.getDomain().lookupDataNode(dbEntity.getDataMap());
+
+            // TODO: O(N) lookup
+            InsertBatchQuery existingQuery = findInsertBatchQuery(queries, dbEntity);
             InsertBatchQuery newQuery = new InsertBatchQuery(dbEntity, 50);
-            boolean newQueryAdded = false;
 
-            // Here can be options with multiple arcs:
-            //  1. they can go as different columns in a single row
-            //  2. they can go as different rows in one batch
-            //  3. mix of both
+            // merge the snapshots of the FAKs by ObjectId for all ToOne relationships in case we have multiple Arcs per Object
+            Map<ObjectId, Map<String, Object>> toOneSnapshots = new HashMap<>();
+
+            // gather the list of the ToMany snapshots (these will actually be their own insert rows)
+            List<Map<String, Object>> toManySnapshots = new ArrayList<>();
+
             for (FlattenedArcKey flattenedArcKey : flattenedArcKeys) {
-                Map<String, Object> snapshot = flattenedArcKey.buildJoinSnapshotForInsert(node);
-                ObjectId objectId = null;
+                Map<String, Object> joinSnapshot = flattenedArcKey.buildJoinSnapshotForInsert(node);
+
+                if (flattenedArcKey.relationship.isToMany()) {
+                    toManySnapshots.add(joinSnapshot);
+                } else {
+                    ObjectId objectId = flattenedArcKey.id1.getSourceId();
+
+                    Map<String, Object> snapshot = toOneSnapshots.get(objectId);
+
+                    if (snapshot == null) {
+                        toOneSnapshots.put(objectId, joinSnapshot);
+                    } else {
+                        // merge joinSnapshot data with existing snapshot
+                        for (Map.Entry<String, Object> dbValue : joinSnapshot.entrySet()) {
+                            snapshot.put(dbValue.getKey(), dbValue.getValue());
+                        }
+                    }
+                }
+            }
+
+            // apply the merged ToOne snapshots information and possibly merge it with an existing BatchQueryRow
+            for (Map.Entry<ObjectId, Map<String, Object>> flattenedSnapshot : toOneSnapshots.entrySet()) {
+                ObjectId objectId = flattenedSnapshot.getKey();
+                Map<String, Object> snapshot = flattenedSnapshot.getValue();
 
-                // TODO: O(N) lookup
-                InsertBatchQuery existingQuery = findInsertBatchQuery(queries, dbEntity);
                 if (existingQuery != null) {
+
                     // TODO: O(N) lookup
-                    BatchQueryRow existingRow = findRowForObjectId(existingQuery.getRows(), flattenedArcKey.id1.getSourceId());
+                    BatchQueryRow existingRow = findRowForObjectId(existingQuery.getRows(), objectId);
                     // todo: do we need to worry about flattenedArcKey.id2 ?
 
                     if (existingRow != null) {
-                        objectId = existingRow.getObjectId();
                         List<DbAttribute> existingQueryDbAttributes = existingQuery.getDbAttributes();
 
-                        for (int i = 0; i < existingQueryDbAttributes.size(); i++) {
+                        for(int i=0; i < existingQueryDbAttributes.size(); i++) {
                             Object value = existingRow.getValue(i);
                             if (value != null) {
                                 snapshot.put(existingQueryDbAttributes.get(i).getName(), value);
@@ -140,21 +164,18 @@ class DataDomainFlattenedBucket {
                 }
 
                 newQuery.add(snapshot, objectId);
+            }
 
-                if (existingQuery != null) {
-                    // replace inside arc loop, so next arc know about it
-                    queries.remove(existingQuery);
-                    queries.add(newQuery);
-                    newQueryAdded = true;
-                    // start clean query for the next arc
-                    newQuery = new InsertBatchQuery(dbEntity, 50);
-                }
+            // apply the ToMany snapshots as new BatchQueryRows
+            for(Map<String, Object> toManySnapshot : toManySnapshots) {
+                newQuery.add(toManySnapshot);
             }
 
-            if(!newQueryAdded) {
-                // if not replaced existing query already
-                queries.add(newQuery);
+            if (existingQuery != null) {
+                queries.remove(existingQuery);
             }
+
+            queries.add(newQuery);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/91eb2c0a/cayenne-server/src/test/java/org/apache/cayenne/access/VerticalInheritanceIT.java
----------------------------------------------------------------------
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 1f2d512..147e468 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
@@ -619,4 +619,31 @@ public class VerticalInheritanceIT extends ServerCase {
 		assertEquals(other2, impl2.getOther2());
 	}
 
+	@Test
+	public void testInsertTwoObjectsWithMultipleAttributeAndMultipleRelationship() {
+		IvOther other1 = context.newObject(IvOther.class);
+		other1.setName("other1");
+
+		IvOther other2 = context.newObject(IvOther.class);
+		other2.setName("other2");
+
+		IvImpl impl1 = context.newObject(IvImpl.class);
+		impl1.setName("Impl 1");
+		impl1.setAttr1("attr1");
+		impl1.setAttr2("attr2");
+		impl1.setOther1(other1);
+		impl1.setOther2(other2);
+
+		IvImpl impl2 = context.newObject(IvImpl.class);
+		impl2.setName("Impl 2");
+		impl2.setAttr1("attr1");
+		impl2.setAttr2("attr2");
+		impl2.setOther1(other1);
+		impl2.setOther2(other2);
+
+		context.commitChanges();
+
+		assertEquals(2, ObjectSelect.query(IvImpl.class).selectCount(context));
+	}
+
 }