private List<Long> asList( NodeValueIndexCursor cursor ) { List<Long> list = new ArrayList<>(); while ( cursor.next() ) { list.add( cursor.nodeReference() ); } return list; }
@Test public void shouldHandleNullInIndexSeek() throws KernelException { // GIVEN Read read = mock( Read.class ); IndexReference index = mock( IndexReference.class ); when( index.properties() ).thenReturn( new int[]{42} ); // WHEN NodeValueIndexCursor cursor = CompiledIndexUtils.indexSeek( mock( Read.class ), mock( CursorFactory.class ), index, null ); // THEN verify( read, never() ).nodeIndexSeek( any(), any(), any(), anyBoolean() ); assertFalse( cursor.next() ); } }
private void assertFoundNodesAndNoValue( NodeValueIndexCursor node, int nodes, MutableLongSet uniqueIds ) { uniqueIds.clear(); for ( int i = 0; i < nodes; i++ ) { assertTrue( "at least " + nodes + " nodes, was " + uniqueIds.size(), node.next() ); long nodeReference = node.nodeReference(); assertTrue( "all nodes are unique", uniqueIds.add( nodeReference ) ); // We can't quite assert !node.hasValue() because even tho pure SpatialIndexReader is guaranteed to not return any values, // where null could be used, the generic native index, especially when having composite keys including spatial values it's // more of a gray area and some keys may be spatial, some not and therefore a proper Value[] will be extracted // potentially containing some NO_VALUE values. } assertFalse( "no more than " + nodes + " nodes", node.next() ); }
private void assertResultsInOrder( List<Pair<Long,Value>> expected, NodeValueIndexCursor cursor ) { Comparator<Pair<Long,Value>> comparator = indexOrder == IndexOrder.ASCENDING ? ( a, b ) -> Values.COMPARATOR.compare( a.other(), b.other() ) : ( a, b ) -> Values.COMPARATOR.compare( b.other(), a.other() ); expected.sort( comparator ); Iterator<Pair<Long,Value>> expectedRows = expected.iterator(); while ( cursor.next() && expectedRows.hasNext() ) { Pair<Long, Value> expectedRow = expectedRows.next(); assertThat( cursor.nodeReference(), equalTo( expectedRow.first() ) ); for ( int i = 0; i < cursor.numberOfProperties(); i++ ) { Value value = cursor.propertyValue( i ); assertThat( value, equalTo( expectedRow.other() ) ); } } assertFalse( expectedRows.hasNext() ); assertFalse( cursor.next() ); }
@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 shouldNotSeeNodeThatHasItsLabelRemovedInTransaction() throws Exception { long nodeID = createNode(); try ( Transaction ignore = graphDatabaseAPI.beginTx() ) { KernelTransaction ktx = ktx(); ktx.dataWrite().nodeRemoveLabel( nodeID, LABEL_ID ); try ( NodeValueIndexCursor cursor = seek( ktx ) ) { assertFalse( cursor.next() ); } } }
@Test public void shouldNotSeeNodeThatHasAPropertyRemovedInTransaction() throws Exception { long nodeID = createNode(); try ( Transaction ignore = graphDatabaseAPI.beginTx() ) { KernelTransaction ktx = ktx(); ktx.dataWrite().nodeRemoveProperty( nodeID, index.schema().getPropertyIds()[0] ); try ( NodeValueIndexCursor cursor = seek( ktx ) ) { assertFalse( cursor.next() ); } } }
@Test public void shouldNotFindDNodeWithRemovedLabelInIndexSeek() 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().nodeRemoveLabel( strOne, label ); tx.dataRead().nodeIndexSeek( index, node, IndexOrder.NONE, needsValues, IndexQuery.exact( prop, "one" ) ); // then assertFalse( node.next() ); } }
@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 shouldNotFindUpdatedNodeInIndexSeek() 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().nodeSetProperty( strOne, prop, stringValue( "ett" ) ); tx.dataRead().nodeIndexSeek( index, node, IndexOrder.NONE, needsValues, IndexQuery.exact( prop, "one" ) ); // then assertFalse( node.next() ); } }
@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 shouldNotFindNodeWithRemovedLabelInPrefixSearch() 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().nodeRemoveLabel( strOne, label ); tx.dataRead().nodeIndexSeek( index, node, IndexOrder.NONE, needsValues, IndexQuery.stringPrefix( prop, stringValue( "on" )) ); // then assertFalse( node.next() ); } }
@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 shouldNotFindNodeWithRemovedLabelInCompositeIndex() 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().nodeRemoveLabel( joeDalton, label ); tx.dataRead().nodeIndexSeek( index, node, IndexOrder.NONE, needsValues, IndexQuery.exact( firstName, "Joe" ), IndexQuery.exact( surname, "Dalton" ) ); // then assertFalse( node.next() ); } }
@Test public void shouldNotFindUpdatedNodeInPrefixSearch() 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().nodeSetProperty( strOne, prop, stringValue( "ett" ) ); tx.dataRead().nodeIndexSeek( index, node, IndexOrder.NONE, needsValues, IndexQuery.stringPrefix( prop, stringValue( "on" )) ); // then assertFalse( node.next() ); } }
@Test public void shouldFindUpdatedNodeInIndexSeek() 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().nodeSetProperty( strOne, prop, stringValue( "ett" ) ); tx.dataRead().nodeIndexSeek( index, node, IndexOrder.NONE, needsValues, IndexQuery.exact( prop, "ett" ) ); // then assertTrue( node.next() ); assertEquals( strOne, node.nodeReference() ); } }
@Test public void shouldFindSwappedNodeInIndexSeek() 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().nodeRemoveLabel( strOne, label ); tx.dataWrite().nodeAddLabel( strOneNoLabel, label ); tx.dataRead().nodeIndexSeek( index, node, IndexOrder.NONE, needsValues, IndexQuery.exact( prop, "one" ) ); // then assertTrue( node.next() ); assertEquals( strOneNoLabel, node.nodeReference() ); } }
@Test public void shouldFindUpdatedNodeInPrefixSearch() 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().nodeSetProperty( strOne, prop, stringValue( "ett" ) ); tx.dataRead().nodeIndexSeek( index, node, IndexOrder.NONE, needsValues, IndexQuery.stringPrefix( prop, stringValue( "et" ) ) ); // then assertTrue( node.next() ); assertEquals( strOne, node.nodeReference() ); } }
@Test public void shouldFindSwappedNodeInPrefixSearch() 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().nodeRemoveLabel( strOne, label ); tx.dataWrite().nodeAddLabel( strOneNoLabel, label ); tx.dataRead().nodeIndexSeek( index, node, IndexOrder.NONE, needsValues, IndexQuery.stringPrefix( prop, stringValue( "on" )) ); // then assertTrue( node.next() ); assertEquals( strOneNoLabel, node.nodeReference() ); } }
@Test public void shouldNotFindUpdatedNodeInRangeSearch() 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().nodeSetProperty( strOne, prop, stringValue( "ett" ) ); tx.dataWrite().nodeSetProperty( strThree1, prop, stringValue( "tre" ) ); tx.dataWrite().nodeSetProperty( strThree2, prop, stringValue( "tre" ) ); tx.dataWrite().nodeSetProperty( strThree3, prop, stringValue( "tre" ) ); tx.dataRead().nodeIndexSeek( index, node, IndexOrder.NONE, needsValues, IndexQuery.range( prop, "one", true, "three", true ) ); // then assertFalse( node.next() ); } }