public IndexEntryConflictException( long existingNodeId, long addedNodeId, Value... propertyValue ) { this( existingNodeId, addedNodeId, ValueTuple.of( propertyValue ) ); }
private ValueTuple values( Object... values ) { return ValueTuple.of( values ); }
public static ValueTuple asValueTuple( IndexQuery.ExactPredicate... query ) { Value[] values = new Value[query.length]; for ( int i = 0; i < query.length; i++ ) { values[i] = query[i].value(); } return ValueTuple.of( values ); }
void checkConflict( Value[] values ) throws IndexEntryConflictException { if ( conflict ) { conflict = false; throw new IndexEntryConflictException( existingNodeId, addedNodeId, ValueTuple.of( values ) ); } } }
@Override public void process( IndexEntryUpdate<?> update ) throws IndexEntryConflictException { actual.process( update ); if ( update.updateMode() != REMOVED ) { touchedTuples.add( ValueTuple.of( update.values() ) ); } }
private ValueTuple tuple( Object... objs ) { Value[] values = new Value[objs.length]; for ( int i = 0; i < values.length; i++ ) { values[i] = Values.of( objs[i] ); } return ValueTuple.of( values ); }
private TreeMap<ValueTuple,LongDiffSets> sortedAddedNodesDiffSets( long... added ) { TreeMap<ValueTuple,LongDiffSets> map = new TreeMap<>( ValueTuple.COMPARATOR ); for ( long node : added ) { map.put( ValueTuple.of( stringValue( "value" + node ) ), addedNodes( node ) ); } return map; }
TxStateBuilder withRemoved( long id, Object... value ) { final ValueTuple valueTuple = ValueTuple.of( (Object[]) value ); final MutableLongDiffSetsImpl changes = updates.computeIfAbsent( valueTuple, ignore -> new MutableLongDiffSetsImpl( OnHeapCollectionsFactory.INSTANCE ) ); changes.remove( id ); return this; }
@Override public void checkForDuplicate( Value[] values, long nodeId ) throws IndexEntryConflictException { final ValueTuple key = ValueTuple.of( values ); if ( valueNodeIdMap.containsKey( key ) ) { throw new IndexEntryConflictException( valueNodeIdMap.get( key ), nodeId, key ); } valueNodeIdMap.put( key, nodeId ); }
TxStateBuilder withAdded( long id, Object... value ) { final ValueTuple valueTuple = ValueTuple.of( (Object[]) value ); final MutableLongDiffSetsImpl changes = updates.computeIfAbsent( valueTuple, ignore -> new MutableLongDiffSetsImpl( OnHeapCollectionsFactory.INSTANCE ) ); changes.add( id ); return this; }
@Test public void shouldMakeCompositeEntryConflicts() { LabelSchemaDescriptor schema = SchemaDescriptorFactory.forLabel( labelId, 2, 3, 4 ); ValueTuple values = ValueTuple.of( true, "hi", new long[]{6L, 4L} ); IndexEntryConflictException e = new IndexEntryConflictException( 0L, 1L, values ); assertThat( e.evidenceMessage( SchemaUtil.idTokenNameLookup, schema ), equalTo( "Both Node(0) and Node(1) have the label `label[1]` " + "and properties `property[2]` = true, `property[3]` = 'hi', `property[4]` = [6, 4]" ) ); } }
@Test void shouldSeekOnAnEmptyTxState() { // GIVEN final ReadableTransactionState state = Mockito.mock( ReadableTransactionState.class ); // WHEN AddedAndRemoved changes = indexUpdatesForSeek( state, compositeIndex, ValueTuple.of( "43value1", "43value2" ) ); // THEN assertTrue( changes.isEmpty() ); }
@Test public void checkNumericMultiplePropertiesDuplicates() throws Exception { Number duplicatedNumberA = 0.33d; Number duplicatedNumberB = 2; Value propertyA = Values.doubleValue( duplicatedNumberA.doubleValue() ); Value propertyB = Values.intValue( duplicatedNumberB.intValue() ); expectedException.expect( IndexEntryConflictException.class ); expectedException.expectMessage( format( "Both node 3 and node 4 share the property value %s", ValueTuple.of( propertyA, propertyB ) ) ); checkStrategy.checkForDuplicate( new Value[]{propertyA, propertyB}, 3 ); checkStrategy.checkForDuplicate( new Value[]{propertyA, propertyB}, 4 ); }
@Test public void getOrCreateIndexUpdatesForSeek_useCollectionsFactory() { final MutableLongDiffSets diffSets = state.getOrCreateIndexUpdatesForSeek( new HashMap<>(), ValueTuple.of( stringValue( "test" ) ) ); diffSets.add( 1 ); diffSets.remove( 2 ); verify( collectionsFactory, times( 2 ) ).newLongSet(); verifyNoMoreInteractions( collectionsFactory ); }
@Test public void checkStringSinglePropertyDuplicates() throws Exception { String duplicatedString = "duplicate"; Value propertyValue = Values.stringValue( duplicatedString ); expectedException.expect( IndexEntryConflictException.class ); expectedException.expectMessage( format( "Both node 1 and node 2 share the property value %s", ValueTuple.of( propertyValue ) ) ); checkStrategy.checkForDuplicate( propertyValue, 1 ); checkStrategy.checkForDuplicate( propertyValue, 2 ); }
@Test public void checkNumericSinglePropertyDuplicates() throws Exception { double duplicatedNumber = 0.33d; Value property = Values.doubleValue( duplicatedNumber ); expectedException.expect( IndexEntryConflictException.class ); expectedException.expectMessage( format( "Both node 3 and node 4 share the property value %s", ValueTuple.of( property ) ) ); checkStrategy.checkForDuplicate( property, 3 ); checkStrategy.checkForDuplicate( property, 4 ); }
void onPropertyRemove( NodeCursor node, PropertyCursor propertyCursor, int propertyKeyId, Value value ) { assert noSchemaChangedInTx(); Iterator<? extends IndexDescriptor> indexes = storageReader.indexesGetRelatedToProperty( propertyKeyId ); NodeSchemaMatcher.onMatchingSchema( indexes, node, propertyCursor, propertyKeyId, ( index, propertyKeyIds ) -> { Value[] values = getValueTuple( node, propertyCursor, propertyKeyId, value, index.schema().getPropertyIds() ); read.txState().indexDoUpdateEntry( index.schema(), node.nodeReference(), ValueTuple.of( values ), null ); } ); }
@Test public void checkStringMultiplePropertiesDuplicates() throws Exception { String duplicateA = "duplicateA"; String duplicateB = "duplicateB"; Value propertyA = Values.stringValue( duplicateA ); Value propertyB = Values.stringValue( duplicateB ); expectedException.expect( IndexEntryConflictException.class ); expectedException.expectMessage( format( "Both node 1 and node 2 share the property value %s", ValueTuple.of( duplicateA, duplicateB ) ) ); checkStrategy.checkForDuplicate( new Value[]{propertyA, propertyB}, 1 ); checkStrategy.checkForDuplicate( new Value[]{propertyA, propertyB}, 2 ); }
void onPropertyAdd( NodeCursor node, PropertyCursor propertyCursor, int propertyKeyId, Value value ) { assert noSchemaChangedInTx(); Iterator<? extends IndexDescriptor> indexes = storageReader.indexesGetRelatedToProperty( propertyKeyId ); NodeSchemaMatcher.onMatchingSchema( indexes, node, propertyCursor, propertyKeyId, ( index, propertyKeyIds ) -> { Value[] values = getValueTuple( node, propertyCursor, propertyKeyId, value, index.schema().getPropertyIds() ); indexProviders.validateBeforeCommit( index.schema(), values ); read.txState().indexDoUpdateEntry( index.schema(), node.nodeReference(), null, ValueTuple.of( values ) ); } ); }
@Test void shouldSeekWhenThereAreNewNumberNodes() { // GIVEN ReadableTransactionState state = new TxStateBuilder() .withAdded( 42L, 42001.0, 42002.0 ) .withAdded( 43L, 43001.0, 43002.0 ) .build(); // WHEN AddedAndRemoved changes = indexUpdatesForSeek( state, compositeIndex, ValueTuple.of( 43001.0, 43002.0 ) ); // THEN assertContains( changes.getAdded(), 43L ); }