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/11/19 13:36:34 UTC
[cayenne] 02/02: CAY-2723 Phantom update of a to-dependent-pk relationship
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 cd8f404f6227e4b49b19503d5491152bdc521043
Author: Nikita Timofeev <st...@gmail.com>
AuthorDate: Fri Nov 19 16:36:13 2021 +0300
CAY-2723 Phantom update of a to-dependent-pk relationship
---
.../cayenne/access/flush/DbRowOpFactory.java | 4 ++
.../cayenne/access/flush/operation/Qualifier.java | 2 +-
.../java/org/apache/cayenne/access/CAY2723IT.java | 58 ++++++++++++++++++++++
3 files changed, 63 insertions(+), 1 deletion(-)
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/flush/DbRowOpFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/access/flush/DbRowOpFactory.java
index 28fa93d..accf329 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/flush/DbRowOpFactory.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/flush/DbRowOpFactory.java
@@ -94,6 +94,10 @@ class DbRowOpFactory {
}
private DbRowOp createRow(DbEntity entity, ObjectId id, DbRowOpType type) {
+ // skip phantom nodes, this could be a created and immediately deleted relationship
+ if(store.getNode(id) == null && !id.getEntityName().startsWith("db:")) {
+ return null;
+ }
switch (type) {
case INSERT:
return new InsertDbRowOp(object, entity, id);
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/flush/operation/Qualifier.java b/cayenne-server/src/main/java/org/apache/cayenne/access/flush/operation/Qualifier.java
index 5f17172..0589e0a 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/flush/operation/Qualifier.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/flush/operation/Qualifier.java
@@ -50,7 +50,7 @@ public class Qualifier {
public Map<String, Object> getSnapshot() {
Map<String, Object> idSnapshot = row.getChangeId().getIdSnapshot();
if(additionalQualifier == null || additionalQualifier.isEmpty()) {
- return idSnapshot;
+ return new HashMap<>(idSnapshot);
}
Map<String, Object> qualifier = new HashMap<>(additionalQualifier.size() + idSnapshot.size());
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/CAY2723IT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/CAY2723IT.java
new file mode 100644
index 0000000..b337792
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/CAY2723IT.java
@@ -0,0 +1,58 @@
+/*****************************************************************
+ * 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
+ *
+ * https://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.access;
+
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.testdo.testmap.Painting;
+import org.apache.cayenne.testdo.testmap.PaintingInfo;
+import org.apache.cayenne.unit.di.DataChannelInterceptor;
+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.Test;
+
+import static org.junit.Assert.assertEquals;
+
+@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
+public class CAY2723IT extends ServerCase {
+ @Inject
+ private DataContext context;
+
+ @Inject
+ private DataChannelInterceptor queryInterceptor;
+
+ @Test
+ public void phantomToDepPKUpdate() {
+ Painting painting = context.newObject(Painting.class);
+ painting.setPaintingTitle("test_p_123");
+
+ PaintingInfo paintingInfo = context.newObject(PaintingInfo.class);
+ paintingInfo.setTextReview("test_a_123");
+
+ painting.setToPaintingInfo(paintingInfo);
+ painting.setToPaintingInfo(null);
+
+ context.deleteObject(paintingInfo);
+
+ // here should be only single insert of the painting object, but there will be 3 queries in total
+ // (2 for the PK generation + insert)
+ int queryCounter = queryInterceptor.runWithQueryCounter(() -> context.commitChanges());
+ assertEquals(3, queryCounter);
+ }
+}