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 cca99eae9 CAY-2868 Regression: DefaultDbRowOpSorter shouldn't sort update operations cca99eae9 is described below commit cca99eae99f290adb67c44fd9ae66565ff7ddfff Author: Nikita Timofeev <stari...@gmail.com> AuthorDate: Fri Aug 16 12:26:35 2024 +0300 CAY-2868 Regression: DefaultDbRowOpSorter shouldn't sort update operations --- RELEASE-NOTES.txt | 1 + .../flush/operation/DefaultDbRowOpSorter.java | 7 ++++--- .../access/flush/DefaultDbRowOpSorterTest.java | 24 ++++++++++++++++++++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 3a5031e99..19ed50585 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -126,3 +126,4 @@ CAY-2851 Replace Existing OneToOne From New Object CAY-2853 Incorrect deletion of entities from flattened attributes CAY-2854 Improve delete prevention detection of flattened attribute row CAY-2866 DefaultDataDomainFlushAction breaks on circular relationship update +CAY-2868 Regression: DefaultDbRowOpSorter shouldn't sort update operations diff --git a/cayenne/src/main/java/org/apache/cayenne/access/flush/operation/DefaultDbRowOpSorter.java b/cayenne/src/main/java/org/apache/cayenne/access/flush/operation/DefaultDbRowOpSorter.java index ed431719e..f02eb7eb8 100644 --- a/cayenne/src/main/java/org/apache/cayenne/access/flush/operation/DefaultDbRowOpSorter.java +++ b/cayenne/src/main/java/org/apache/cayenne/access/flush/operation/DefaultDbRowOpSorter.java @@ -64,7 +64,8 @@ public class DefaultDbRowOpSorter implements DbRowOpSorter { for (int i = 0; i < sortedDbRows.size(); i++) { DbRowOp row = sortedDbRows.get(i); if (row.getEntity() != lastEntity) { - if(lastEntity != null && sorter.isReflexive(lastEntity)) { + // we do not sort update operations + if(lastEntity != null && !(lastRow instanceof UpdateDbRowOp) && sorter.isReflexive(lastEntity)) { ObjEntity objEntity = resolver.getObjEntity(lastRow.getObject().getObjectId().getEntityName()); List<DbRowOp> reflexiveSublist = sortedDbRows.subList(start, idx); sorter.sortObjectsForEntity(objEntity, reflexiveSublist, lastRow instanceof DeleteDbRowOp); @@ -76,7 +77,7 @@ public class DefaultDbRowOpSorter implements DbRowOpSorter { idx++; } // sort last chunk - if(lastEntity != null && sorter.isReflexive(lastEntity)) { + if(lastEntity != null && !(lastRow instanceof UpdateDbRowOp) && sorter.isReflexive(lastEntity)) { ObjEntity objEntity = resolver.getObjEntity(lastRow.getObject().getObjectId().getEntityName()); List<DbRowOp> reflexiveSublist = sortedDbRows.subList(start, idx); sorter.sortObjectsForEntity(objEntity, reflexiveSublist, lastRow instanceof DeleteDbRowOp); @@ -116,7 +117,7 @@ public class DefaultDbRowOpSorter implements DbRowOpSorter { return result; } - // 2. sort by entity relations + // 2. sort by entity relations, we don't really need this for updates, but do it for the stable result result = entitySorter.getDbEntityComparator().compare(left.getEntity(), right.getEntity()); if(result != 0) { // invert result for delete diff --git a/cayenne/src/test/java/org/apache/cayenne/access/flush/DefaultDbRowOpSorterTest.java b/cayenne/src/test/java/org/apache/cayenne/access/flush/DefaultDbRowOpSorterTest.java index b4bd0217b..8fbb3ddd4 100644 --- a/cayenne/src/test/java/org/apache/cayenne/access/flush/DefaultDbRowOpSorterTest.java +++ b/cayenne/src/test/java/org/apache/cayenne/access/flush/DefaultDbRowOpSorterTest.java @@ -192,8 +192,32 @@ public class DefaultDbRowOpSorterTest { List<DbRowOp> sorted = sorter.sort(rows); assertEquals(expected, sorted); // no actual sorting is done + verify(entitySorter, times(3)).getDbEntityComparator(); verify(entitySorter) // should call entity sorter .sortObjectsForEntity(isNull(), any(List.class), eq(false)); + verifyNoMoreInteractions(entitySorter); + } + + @Test + public void sortReflexiveUpdates() { + ObjectId id1 = ObjectId.of("reflexive", "id", 1); + ObjectId id2 = ObjectId.of("reflexive", "id", 2); + ObjectId id3 = ObjectId.of("reflexive", "id", 3); + ObjectId id4 = ObjectId.of("reflexive", "id", 4); + + DbEntity reflexive = mockEntity("reflexive"); + DbRowOp op1 = new UpdateDbRowOp(mockObject(id1), reflexive, id1); + DbRowOp op2 = new UpdateDbRowOp(mockObject(id2), reflexive, id2); + DbRowOp op3 = new UpdateDbRowOp(mockObject(id3), reflexive, id3); + DbRowOp op4 = new UpdateDbRowOp(mockObject(id4), reflexive, id4); + + List<DbRowOp> rows = Arrays.asList(op1, op2, op3, op4); + List<DbRowOp> expected = Arrays.asList(op1, op2, op3, op4); + + List<DbRowOp> sorted = sorter.sort(rows); + assertEquals(expected, sorted); // no actual sorting is done + verify(entitySorter, times(3)).getDbEntityComparator(); + verifyNoMoreInteractions(entitySorter); // shouldn't call entity sorter } private Persistent mockObject(ObjectId id) {