Index: extensions/modeshape-connector-store-jpa/src/main/java/org/modeshape/connector/store/jpa/model/simple/LargeValueEntity.java =================================================================== --- extensions/modeshape-connector-store-jpa/src/main/java/org/modeshape/connector/store/jpa/model/simple/LargeValueEntity.java (revision 1726) +++ extensions/modeshape-connector-store-jpa/src/main/java/org/modeshape/connector/store/jpa/model/simple/LargeValueEntity.java (working copy) @@ -50,9 +50,10 @@ import org.modeshape.graph.property.PropertyType; @Entity @Table( name = "MODE_SIMPLE_LARGE_VALUES" ) @NamedQueries( { - @NamedQuery( name = "LargeValueEntity.selectUnused", query = "select values.hash from NodeEntity node join node.largeValues values" ), + @NamedQuery( name = "LargeValueEntity.selectUnused", query = "select largeValue.hash from LargeValueEntity largeValue where largeValue.hash not in (select values.hash from NodeEntity node join node.largeValues values)" ), @NamedQuery( name = "LargeValueEntity.deleteAllUnused", query = "delete LargeValueEntity value where value.hash not in (select values.hash from NodeEntity node join node.largeValues values)" ), - @NamedQuery( name = "LargeValueEntity.deleteIn", query = "delete LargeValueEntity value where value.hash in (:inValues)" )} ) + @NamedQuery( name = "LargeValueEntity.deleteIn", query = "delete LargeValueEntity value where value.hash in (:inValues)" ) + } ) public class LargeValueEntity { @Id @@ -213,7 +214,8 @@ public class LargeValueEntity { int fromIndex = 0; do { int toIndex = Math.min(fromIndex + 20, endIndex); - Query query = manager.createQuery("LargeValueEntity.deleteIn"); + Query query = manager.createNamedQuery("LargeValueEntity.deleteIn"); + System.out.println(hashes.subList(fromIndex, toIndex)); query.setParameter("inValues", hashes.subList(fromIndex, toIndex)); query.executeUpdate(); result += toIndex - fromIndex; Index: modeshape-jcr/src/test/java/org/modeshape/jcr/ModeShapeTckTest.java =================================================================== --- modeshape-jcr/src/test/java/org/modeshape/jcr/ModeShapeTckTest.java (revision 1726) +++ modeshape-jcr/src/test/java/org/modeshape/jcr/ModeShapeTckTest.java (working copy) @@ -3,6 +3,8 @@ package org.modeshape.jcr; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNull.notNullValue; import static org.junit.Assert.assertThat; +import java.io.ByteArrayInputStream; +import java.util.Calendar; import java.util.Collections; import javax.jcr.AccessDeniedException; import javax.jcr.Credentials; @@ -11,6 +13,7 @@ import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.PathNotFoundException; import javax.jcr.Property; +import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.SimpleCredentials; import javax.jcr.nodetype.ConstraintViolationException; @@ -720,4 +723,43 @@ public class ModeShapeTckTest extends AbstractJCRTest { } } + + public void testShouldAllowDeletingNodesWhenLargePropertyIsPresent() throws Exception { + // q.v. MODE-693 + session = helper.getReadWriteSession(); + + Node root = session.getRootNode(); + + final int SIZE = 2048; + byte[] largeArray = new byte[SIZE]; + for (int i = 0; i < SIZE; i++) { + largeArray[i] = (byte)'x'; + } + + Node projectNode = root.addNode("mode693", "nt:unstructured"); + + Node fileNode = projectNode.addNode("fileNode", "nt:file"); + Node contentNode = fileNode.addNode("jcr:content", "nt:resource"); + contentNode.setProperty("jcr:data", new ByteArrayInputStream(largeArray)); + contentNode.setProperty("jcr:lastModified", Calendar.getInstance()); + contentNode.setProperty("jcr:mimeType", "application/octet-stream"); + + Node otherNode = projectNode.addNode("otherNode", "nt:unstructured"); + session.save(); + + String pathToNode = projectNode.getName() + "/" + otherNode.getName(); + + if (!root.hasNode(pathToNode)) { + throw new RepositoryException("Cannot delete node at path=" + pathToNode + " since no node exists at this path"); + } + Node nodeToDelete = root.getNode(pathToNode); + nodeToDelete.remove(); + session.save(); + + // Make sure that only one node was deleted + assertThat(root.hasNode(projectNode.getName()), is(true)); + assertThat(projectNode.hasNode(fileNode.getName()), is(true)); + assertThat(fileNode.hasNode(contentNode.getName()), is(true)); + assertThat(root.hasNode(pathToNode), is(false)); + } }