@Override public void delete() { KernelTransaction transaction = safeAcquireTransaction(); try { boolean deleted = transaction.dataWrite().nodeDelete( getId() ); if ( !deleted ) { throw new NotFoundException( "Unable to delete Node[" + nodeId + "] since it has already been deleted." ); } } catch ( InvalidTransactionTypeKernelException e ) { throw new ConstraintViolationException( e.getMessage(), e ); } catch ( AutoIndexingKernelException e ) { throw new IllegalStateException( "Auto indexing encountered a failure while deleting the node: " + e.getMessage(), e ); } }
@Test public void shouldNotFindDeletedNodeInRangeSearch() throws Exception { // Given boolean needsValues = indexProvidesStringValues(); int label = token.nodeLabel( "Node" ); int prop = token.propertyKey( "prop" ); IndexReference index = schemaRead.index( label, prop ); try ( org.neo4j.internal.kernel.api.Transaction tx = beginTransaction(); NodeValueIndexCursor node = cursors.allocateNodeValueIndexCursor() ) { // when tx.dataWrite().nodeDelete( strOne ); tx.dataWrite().nodeDelete( strThree1 ); tx.dataWrite().nodeDelete( strThree2 ); tx.dataWrite().nodeDelete( strThree3 ); tx.dataRead().nodeIndexSeek( index, node, IndexOrder.NONE, needsValues, IndexQuery.range( prop, "one", true, "three", true ) ); // then assertFalse( node.next() ); } }
@Test public void shouldNotRemoveNodeThatDoesNotExist() throws Exception { long node = 0; try ( Transaction tx = beginTransaction() ) { assertFalse( tx.dataWrite().nodeDelete( node ) ); tx.failure(); } try ( Transaction tx = beginTransaction() ) { assertFalse( tx.dataWrite().nodeDelete( node ) ); tx.success(); } // should not crash }
@Test public void shouldHandleMultipleNodeDeletions() throws Exception { long nodeId; try ( Transaction tx = beginTransaction() ) { nodeId = tx.dataWrite().nodeCreate(); tx.success(); } try ( Transaction tx = beginTransaction() ) { assertTrue( tx.dataWrite().nodeDelete( nodeId ) ); assertFalse( tx.dataWrite().nodeDelete( nodeId ) ); tx.success(); } }
@Test public void shouldAllowRemoveAndAddConflictingDataInOneTransaction_DeleteNode() throws Exception { // given long node = constrainedNode( "Label1", "key1", "value1" ); Transaction transaction = newTransaction( AnonymousContext.writeToken() ); // when transaction.dataWrite().nodeDelete( node ); createLabeledNode( transaction, "Label1", "key1", "value1" ); commit(); }
@Test public void shouldAllowRemoveAndAddConflictingDataInOneTransaction_DeleteNode() throws Exception { // given long node = createNodeWithLabelAndProps( label, aValues ); // when newTransaction(); transaction.dataWrite().nodeDelete( node ); long newNode = createLabeledNode( label ); setProperties( newNode, aValues ); // then does not fail commit(); }
@Test public void shouldNotSeeNodeThatWasDeletedInTransaction() throws Exception { long nodeID = createNode(); try ( Transaction ignore = graphDatabaseAPI.beginTx() ) { KernelTransaction ktx = ktx(); ktx.dataWrite().nodeDelete( nodeID ); try ( NodeValueIndexCursor cursor = seek( ktx ) ) { assertFalse( cursor.next() ); } } }
@Test public void shouldRemoveNode() throws Exception { long node = createNode(); try ( Transaction tx = beginTransaction() ) { tx.dataWrite().nodeDelete( node ); tx.success(); } try ( org.neo4j.graphdb.Transaction ignore = graphDb.beginTx() ) { try { graphDb.getNodeById( node ); fail( "Did not remove node" ); } catch ( NotFoundException e ) { // expected } } }
@Ignore public void shouldNotFindDeletedNodeInConjunctionLabelScan() throws Exception { // Given Node node = createNode( "label1", "label2" ); try ( org.neo4j.internal.kernel.api.Transaction tx = beginTransaction(); NodeLabelIndexCursor cursor = tx.cursors().allocateNodeLabelIndexCursor() ) { // when tx.dataWrite().nodeDelete( node.node ); tx.dataRead().nodeLabelIntersectionScan( cursor, node.labels ); // then assertFalse( cursor.next() ); } }
@Test public void shouldNotFindDeletedNodeInLabelScan() throws Exception { // Given Node node = createNode( "label" ); try ( org.neo4j.internal.kernel.api.Transaction tx = beginTransaction(); NodeLabelIndexCursor cursor = tx.cursors().allocateNodeLabelIndexCursor() ) { // when tx.dataWrite().nodeDelete( node.node ); tx.dataRead().nodeLabelScan( node.labels[0], cursor ); // then assertFalse( cursor.next() ); } }
@Ignore public void shouldNotFindDeletedNodeInDisjunctionLabelScan() throws Exception { // Given Node node = createNode( "label1", "label2" ); try ( org.neo4j.internal.kernel.api.Transaction tx = beginTransaction(); NodeLabelIndexCursor cursor = tx.cursors().allocateNodeLabelIndexCursor() ) { // when tx.dataWrite().nodeDelete( node.node ); tx.dataRead().nodeLabelUnionScan( cursor, node.labels ); // then assertFalse( cursor.next() ); } }
@Test public void shouldNotSeeDeletedNode() throws Exception { // Given long node; try ( Transaction tx = beginTransaction() ) { node = tx.dataWrite().nodeCreate(); tx.success(); } // Then try ( Transaction tx = beginTransaction() ) { tx.dataWrite().nodeDelete( node ); assertFalse( tx.dataRead().nodeExists( node ) ); } }
@Test public void shouldNotCountRemovedNodesFromTxState() throws Exception { // Given Node node1 = createNode( "label" ); Node node2 = createNode( "label" ); try ( org.neo4j.internal.kernel.api.Transaction tx = beginTransaction() ) { // when tx.dataWrite().nodeDelete( node2.node ); long countTxState = tx.dataRead().countsForNode( node1.labels[0] ); long countNoTxState = tx.dataRead().countsForNodeWithoutTxState( node1.labels[0] ); // then assertEquals( 1, countTxState ); assertEquals( 2, countNoTxState ); } }
@Test public void shouldNotFindDeletedNodeInIndexSeek() throws Exception { // Given boolean needsValues = false; int label = token.nodeLabel( "Node" ); int prop = token.propertyKey( "prop" ); IndexReference index = schemaRead.index( label, prop ); try ( org.neo4j.internal.kernel.api.Transaction tx = beginTransaction(); NodeValueIndexCursor node = cursors.allocateNodeValueIndexCursor() ) { // when tx.dataWrite().nodeDelete( strOne ); tx.dataRead().nodeIndexSeek( index, node, IndexOrder.NONE, needsValues, IndexQuery.exact( prop, "one" ) ); // then assertFalse( node.next() ); } }
@Test public void shouldNotFindDeletedNodeInIndexScan() throws Exception { // Given boolean needsValues = indexProvidesAllValues(); int label = token.nodeLabel( "Node" ); int prop = token.propertyKey( "prop" ); IndexReference index = schemaRead.index( label, prop ); IndexValueCapability wildcardCapability = index.valueCapability( ValueCategory.UNKNOWN ); try ( org.neo4j.internal.kernel.api.Transaction tx = beginTransaction(); NodeValueIndexCursor node = cursors.allocateNodeValueIndexCursor() ) { MutableLongSet uniqueIds = new LongHashSet(); // when tx.dataRead().nodeIndexScan( index, node, IndexOrder.NONE, needsValues ); assertThat( node.numberOfProperties(), equalTo( 1 ) ); assertFoundNodesAndValue( node, TOTAL_NODE_COUNT, uniqueIds, wildcardCapability, needsValues ); // then tx.dataWrite().nodeDelete( strOne ); tx.dataRead().nodeIndexScan( index, node, IndexOrder.NONE, needsValues ); assertFoundNodesAndValue( node, TOTAL_NODE_COUNT - 1, uniqueIds, wildcardCapability, needsValues ); } }
@Test public void shouldNotFindDeletedNodeInPrefixSearch() throws Exception { // Given boolean needsValues = indexProvidesStringValues(); int label = token.nodeLabel( "Node" ); int prop = token.propertyKey( "prop" ); IndexReference index = schemaRead.index( label, prop ); try ( org.neo4j.internal.kernel.api.Transaction tx = beginTransaction(); NodeValueIndexCursor node = cursors.allocateNodeValueIndexCursor() ) { // when tx.dataWrite().nodeDelete( strOne ); tx.dataRead().nodeIndexSeek( index, node, IndexOrder.NONE, needsValues, IndexQuery.stringPrefix( prop, stringValue( "on" )) ); // then assertFalse( node.next() ); } }
@Test public void shouldDetectNodeDeletedInTransaction() throws Exception { // GIVEN long deletedInTx, unaffected, addedInTx, addedAndRemovedInTx; try ( Transaction tx = beginTransaction() ) { deletedInTx = tx.dataWrite().nodeCreate(); unaffected = tx.dataWrite().nodeCreate(); tx.success(); } try ( Transaction tx = beginTransaction() ) { // WHEN addedInTx = tx.dataWrite().nodeCreate(); addedAndRemovedInTx = tx.dataWrite().nodeCreate(); tx.dataWrite().nodeDelete( deletedInTx ); tx.dataWrite().nodeDelete( addedAndRemovedInTx ); // THEN assertFalse( tx.dataRead().nodeDeletedInTransaction( addedInTx ) ); assertFalse( tx.dataRead().nodeDeletedInTransaction( unaffected ) ); assertTrue( tx.dataRead().nodeDeletedInTransaction( addedAndRemovedInTx ) ); assertTrue( tx.dataRead().nodeDeletedInTransaction( deletedInTx ) ); } }
@Test public void shouldNotFindDeletedNodeInCompositeIndex() throws Exception { // Given boolean needsValues = false; int label = token.nodeLabel( "Person" ); int firstName = token.propertyKey( "firstname" ); int surname = token.propertyKey( "surname" ); IndexReference index = schemaRead.index( label, firstName, surname ); try ( org.neo4j.internal.kernel.api.Transaction tx = beginTransaction(); NodeValueIndexCursor node = cursors.allocateNodeValueIndexCursor() ) { // when tx.dataWrite().nodeDelete( jackDalton ); tx.dataRead().nodeIndexSeek( index, node, IndexOrder.NONE, needsValues, IndexQuery.exact( firstName, "Jack" ), IndexQuery.exact( surname, "Dalton" ) ); // then assertFalse( node.next() ); } }
@Test public void shouldDiscoverDeletedNodeInTransaction() throws Exception { long nodeId; try ( Transaction tx = beginTransaction() ) { nodeId = tx.dataWrite().nodeCreate(); tx.success(); } try ( Transaction tx = beginTransaction() ) { assertTrue( tx.dataWrite().nodeDelete( nodeId ) ); try ( NodeCursor node = tx.cursors().allocateNodeCursor() ) { tx.dataRead().singleNode( nodeId, node ); assertFalse( node.next() ); } tx.success(); } }
@After public void clean() throws Exception { if ( transaction != null ) { transaction.close(); } newTransaction(); transaction.schemaWrite() .constraintDrop( ConstraintDescriptorFactory.uniqueForLabel( label, propertyIds() ) ); commit(); try ( Transaction tx = kernel.beginTransaction( Transaction.Type.implicit, LoginContext.AUTH_DISABLED ); NodeCursor node = tx.cursors().allocateNodeCursor() ) { tx.dataRead().allNodesScan( node ); while ( node.next() ) { tx.dataWrite().nodeDelete( node.nodeReference() ); } tx.success(); } }