public static IndexEntryUpdate<SchemaDescriptor> remove( long nodeId, SchemaDescriptor schema, Object... objects ) { return IndexEntryUpdate.remove( nodeId, schema, toValues( objects ) ); }
@Test public void removeShouldRetainValues() { IndexEntryUpdate<?> single = IndexEntryUpdate.remove( 0, SchemaDescriptorFactory.forLabel( 3, 4 ), singleValue ); IndexEntryUpdate<?> multi = IndexEntryUpdate .remove( 0, SchemaDescriptorFactory.forLabel( 3, 4, 5 ), multiValue ); assertThat( single, not( equalTo( multi ) ) ); assertThat( single.values(), equalTo( new Object[]{singleValue} ) ); assertThat( multi.values(), equalTo( multiValue ) ); }
@Test public void shouldGenerateUpdatesForLabelRemovalWithExistingProperties() { // When EntityUpdates updates = EntityUpdates.forEntity( nodeId ).withTokens( label ).withTokensAfter( empty ).build(); // Then assertThat( updates.forIndexKeys( indexes, propertyLoader( property1, property2, property3 ), EntityType.NODE ), containsInAnyOrder( IndexEntryUpdate.remove( nodeId, index1, property1.value() ), IndexEntryUpdate.remove( nodeId, index2, property2.value() ), IndexEntryUpdate.remove( nodeId, index3, property3.value() ), IndexEntryUpdate.remove( nodeId, index123, values123 ) ) ); }
@SuppressWarnings( "ConstantConditions" ) private <INDEX_KEY extends SchemaDescriptorSupplier> Iterable<IndexEntryUpdate<INDEX_KEY>> gatherUpdatesForPotentials( Iterable<INDEX_KEY> potentiallyRelevant ) { List<IndexEntryUpdate<INDEX_KEY>> indexUpdates = new ArrayList<>(); for ( INDEX_KEY indexKey : potentiallyRelevant ) { SchemaDescriptor schema = indexKey.schema(); boolean relevantBefore = relevantBefore( schema ); boolean relevantAfter = relevantAfter( schema ); int[] propertyIds = schema.getPropertyIds(); if ( relevantBefore && !relevantAfter ) { indexUpdates.add( IndexEntryUpdate.remove( entityId, indexKey, valuesBefore( propertyIds ) ) ); } else if ( !relevantBefore && relevantAfter ) { indexUpdates.add( IndexEntryUpdate.add( entityId, indexKey, valuesAfter( propertyIds ) ) ); } else if ( relevantBefore && relevantAfter ) { if ( valuesChanged( propertyIds, schema.propertySchemaType() ) ) { indexUpdates.add( IndexEntryUpdate.change( entityId, indexKey, valuesBefore( propertyIds ), valuesAfter( propertyIds ) ) ); } } } return indexUpdates; }
@Test public void shouldGenerateUpdateWhenSwitchingToUselessTokenForNonSchemaIndex() { // When EntityUpdates updates = EntityUpdates.forEntity( nodeId ).withTokens( label ).withTokensAfter( unusedLabelId ).build(); // Then assertThat( updates.forIndexKeys( singleton( nonSchemaIndex ), propertyLoader( property1, property2, property3 ), EntityType.NODE ), containsInAnyOrder( IndexEntryUpdate.remove( nodeId, nonSchemaIndex, values123 ) ) ); }
@Test public void shouldGenerateUpdateWhenRemovingLastTokenForNonSchemaIndex() { // When EntityUpdates updates = EntityUpdates.forEntity( nodeId ).withTokens( label ).withTokensAfter( empty ).build(); // Then assertThat( updates.forIndexKeys( singleton( nonSchemaIndex ), propertyLoader( property1, property2, property3 ), EntityType.NODE ), containsInAnyOrder( IndexEntryUpdate.remove( nodeId, nonSchemaIndex, values123 ) ) ); }
void add( IndexEntryUpdate<?> update ) { if ( update.getEntityId() == 2 ) { job.update( IndexEntryUpdate.remove( nodeToDelete, index, valueToDelete ) ); } added.put( update.getEntityId(), update.values()[0].asObjectCopy() ); }
@Test public void updatesShouldEqualRegardlessOfCreationMethod() { IndexEntryUpdate<?> singleAdd = IndexEntryUpdate.add( 0, SchemaDescriptorFactory.forLabel( 3, 4 ), singleValue ); Value[] singleAsArray = {singleValue}; IndexEntryUpdate<?> multiAdd = IndexEntryUpdate .add( 0, SchemaDescriptorFactory.forLabel( 3, 4 ), singleAsArray ); IndexEntryUpdate<?> singleRemove = IndexEntryUpdate .remove( 0, SchemaDescriptorFactory.forLabel( 3, 4 ), singleValue ); IndexEntryUpdate<?> multiRemove = IndexEntryUpdate .remove( 0, SchemaDescriptorFactory.forLabel( 3, 4 ), singleAsArray ); IndexEntryUpdate<?> singleChange = IndexEntryUpdate .change( 0, SchemaDescriptorFactory.forLabel( 3, 4 ), singleValue, singleValue ); IndexEntryUpdate<?> multiChange = IndexEntryUpdate .change( 0, SchemaDescriptorFactory.forLabel( 3, 4 ), singleAsArray, singleAsArray ); assertThat( singleAdd, equalTo( multiAdd ) ); assertThat( singleRemove, equalTo( multiRemove ) ); assertThat( singleChange, equalTo( multiChange ) ); }
@Test public void removeShouldThrowIfAskedForChanged() { IndexEntryUpdate<?> single = IndexEntryUpdate.remove( 0, SchemaDescriptorFactory.forLabel( 3, 4 ), singleValue ); thrown.expect( UnsupportedOperationException.class ); single.beforeValues(); }
@Test public void shouldGenerateUpdateForLabelRemovalWithExistingProperty() { // When EntityUpdates updates = EntityUpdates.forEntity( nodeId ).withTokens( label ).withTokensAfter( empty ).build(); // Then assertThat( updates.forIndexKeys( indexes, propertyLoader( property1 ), EntityType.NODE ), containsInAnyOrder( IndexEntryUpdate.remove( nodeId, index1, property1.value() ) ) ); }
@Test public void shouldGenerateUpdateWhenRemovingLastPropForNonSchemaIndex() { // When EntityUpdates updates = EntityUpdates.forEntity( nodeId ).withTokens( label ).withTokensAfter( label ) .removed( property2.propertyKeyId(), property2.value() ) .build(); // Then assertThat( updates.forIndexKeys( singleton( nonSchemaIndex ), propertyLoader( property2), EntityType.NODE ), containsInAnyOrder( IndexEntryUpdate.remove( nodeId, nonSchemaIndex, null, property2.value(), null ) ) ); }
@Test public void shouldIndexRemove() throws Exception { // given IndexEntryUpdate<IndexDescriptor>[] updates = someUpdatesSingleType(); processAll( updates ); for ( int i = 0; i < updates.length; i++ ) { // when IndexEntryUpdate<IndexDescriptor> update = updates[i]; IndexEntryUpdate<IndexDescriptor> remove = remove( update.getEntityId(), indexDescriptor, update.values() ); processAll( remove ); forceAndCloseAccessor(); // then verifyUpdates( Arrays.copyOfRange( updates, i + 1, updates.length ) ); setupAccessor(); } }
@Override public void process( IndexEntryUpdate<?> update ) throws IndexEntryConflictException { IndexUpdater to = select( update.values()[0].valueGroup() ); switch ( update.updateMode() ) { case ADDED: case REMOVED: to.process( update ); break; case CHANGED: IndexUpdater from = select( update.beforeValues()[0].valueGroup() ); // There are two cases: // - both before/after go into the same updater --> pass update into that updater if ( from == to ) { from.process( update ); } // - before go into one and after into the other --> REMOVED from one and ADDED into the other else { from.process( IndexEntryUpdate.remove( update.getEntityId(), update.indexKey(), update.beforeValues() ) ); to.process( IndexEntryUpdate.add( update.getEntityId(), update.indexKey(), update.values() ) ); } break; default: throw new IllegalArgumentException( "Unknown update mode" ); } }
@Override public void process( IndexEntryUpdate<?> update ) throws IndexEntryConflictException { IndexUpdater to = select( ((PointValue)update.values()[0]).getCoordinateReferenceSystem() ); switch ( update.updateMode() ) { case ADDED: case REMOVED: to.process( update ); break; case CHANGED: IndexUpdater from = select( ((PointValue) update.beforeValues()[0]).getCoordinateReferenceSystem() ); // There are two cases: // - both before/after go into the same updater --> pass update into that updater if ( from == to ) { from.process( update ); } // - before go into one and after into the other --> REMOVED from one and ADDED into the other else { from.process( IndexEntryUpdate.remove( update.getEntityId(), update.indexKey(), update.beforeValues() ) ); to.process( IndexEntryUpdate.add( update.getEntityId(), update.indexKey(), update.values() ) ); } break; default: throw new IllegalArgumentException( "Unknown update mode" ); } }
from.process( IndexEntryUpdate.remove( update.getEntityId(), update.indexKey(), update.beforeValues() ) ); to.process( IndexEntryUpdate.add( update.getEntityId(), update.indexKey(), update.values() ) );
@Test public void shouldContainFedNodeUpdate() throws Exception { OnlineIndexUpdates onlineIndexUpdates = new OnlineIndexUpdates( nodeStore, relationshipStore, indexingService, propertyPhysicalToLogicalConverter ); int nodeId = 0; NodeRecord inUse = getNode( nodeId, true ); Value propertyValue = Values.of( "hej" ); long propertyId = createNodeProperty( inUse, propertyValue, 1 ); NodeRecord notInUse = getNode( nodeId, false ); nodeStore.updateRecord( inUse ); Command.NodeCommand nodeCommand = new Command.NodeCommand( inUse, notInUse ); PropertyRecord propertyBlocks = new PropertyRecord( propertyId ); propertyBlocks.setNodeId( nodeId ); Command.PropertyCommand propertyCommand = new Command.PropertyCommand( recordAccess.getIfLoaded( propertyId ).forReadingData(), propertyBlocks ); StoreIndexDescriptor indexDescriptor = forSchema( multiToken( ENTITY_TOKENS, NODE, 1, 4, 6 ), EMPTY.getProviderDescriptor() ).withId( 0 ); indexingService.createIndexes( indexDescriptor ); indexingService.getIndexProxy( indexDescriptor.schema() ).awaitStoreScanCompleted(); onlineIndexUpdates.feed( LongObjectMaps.immutable.of( nodeId, singletonList( propertyCommand ) ), LongObjectMaps.immutable.empty(), LongObjectMaps.immutable.of( nodeId, nodeCommand ), LongObjectMaps.immutable.empty() ); assertTrue( onlineIndexUpdates.hasUpdates() ); Iterator<IndexEntryUpdate<SchemaDescriptor>> iterator = onlineIndexUpdates.iterator(); assertEquals( iterator.next(), IndexEntryUpdate.remove( nodeId, indexDescriptor, propertyValue, null, null ) ); assertFalse( iterator.hasNext() ); }
@Test public void shouldContainFedRelationshipUpdate() throws Exception { OnlineIndexUpdates onlineIndexUpdates = new OnlineIndexUpdates( nodeStore, relationshipStore, indexingService, propertyPhysicalToLogicalConverter ); long relId = 0; RelationshipRecord inUse = getRelationship( relId, true, ENTITY_TOKEN ); Value propertyValue = Values.of( "hej" ); long propertyId = createRelationshipProperty( inUse, propertyValue, 1 ); RelationshipRecord notInUse = getRelationship( relId, false, ENTITY_TOKEN ); relationshipStore.updateRecord( inUse ); Command.RelationshipCommand relationshipCommand = new Command.RelationshipCommand( inUse, notInUse ); PropertyRecord propertyBlocks = new PropertyRecord( propertyId ); propertyBlocks.setRelId( relId ); Command.PropertyCommand propertyCommand = new Command.PropertyCommand( recordAccess.getIfLoaded( propertyId ).forReadingData(), propertyBlocks ); StoreIndexDescriptor indexDescriptor = forSchema( multiToken( ENTITY_TOKENS, RELATIONSHIP, 1, 4, 6 ), EMPTY.getProviderDescriptor() ).withId( 0 ); indexingService.createIndexes( indexDescriptor ); indexingService.getIndexProxy( indexDescriptor.schema() ).awaitStoreScanCompleted(); onlineIndexUpdates.feed( LongObjectMaps.immutable.empty(), LongObjectMaps.immutable.of( relId, singletonList( propertyCommand ) ), LongObjectMaps.immutable.empty(), LongObjectMaps.immutable.of( relId, relationshipCommand ) ); assertTrue( onlineIndexUpdates.hasUpdates() ); Iterator<IndexEntryUpdate<SchemaDescriptor>> iterator = onlineIndexUpdates.iterator(); assertEquals( iterator.next(), IndexEntryUpdate.remove( relId, indexDescriptor, propertyValue, null, null ) ); assertFalse( iterator.hasNext() ); }
@Test public void mustDiscoverNodeInStoreMissingFromIndex() throws Exception { GraphDatabaseService db = createDatabase(); try ( Transaction tx = db.beginTx() ) { db.execute( format( NODE_CREATE, "nodes", array( "Label" ), array( "prop" ) ) ).close(); tx.success(); } StoreIndexDescriptor indexDescriptor; long nodeId; try ( Transaction tx = db.beginTx() ) { db.schema().awaitIndexesOnline( 1, TimeUnit.MINUTES ); indexDescriptor = getIndexDescriptor( first( db.schema().getIndexes() ) ); Node node = db.createNode( Label.label( "Label" ) ); node.setProperty( "prop", "value" ); nodeId = node.getId(); tx.success(); } IndexingService indexes = getIndexingService( db ); IndexProxy indexProxy = indexes.getIndexProxy( indexDescriptor.schema() ); try ( IndexUpdater updater = indexProxy.newUpdater( IndexUpdateMode.ONLINE ) ) { updater.process( IndexEntryUpdate.remove( nodeId, indexDescriptor, Values.stringValue( "value" ) ) ); } db.shutdown(); ConsistencyCheckService.Result result = checkConsistency(); assertFalse( result.isSuccessful() ); }
try ( IndexUpdater updater = indexProxy.newUpdater( IndexUpdateMode.ONLINE ) ) updater.process( IndexEntryUpdate.remove( relId, indexDescriptor, Values.stringValue( "value" ) ) );