Skip to content

Commit

Permalink
Improved testing and error handling on constraint index creation on o…
Browse files Browse the repository at this point in the history
…rphaned indexes
  • Loading branch information
tinwelint committed Apr 27, 2017
1 parent aa45e7d commit 55d7b9e
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 24 deletions.
Expand Up @@ -532,8 +532,8 @@ public UniquenessConstraint uniquePropertyConstraintCreate( KernelStatement stat
} }
return constraint; return constraint;
} }
catch ( ConstraintVerificationFailedKernelException | DropIndexFailureException | TransactionFailureException catch ( ConstraintVerificationFailedKernelException | DropIndexFailureException | TransactionFailureException |
e ) AlreadyConstrainedException e )
{ {
throw new CreateConstraintFailureException( constraint, e ); throw new CreateConstraintFailureException( constraint, e );
} }
Expand Down
Expand Up @@ -24,18 +24,20 @@


import org.neo4j.kernel.api.KernelAPI; import org.neo4j.kernel.api.KernelAPI;
import org.neo4j.kernel.api.KernelTransaction; import org.neo4j.kernel.api.KernelTransaction;
import org.neo4j.kernel.api.ReadOperations;
import org.neo4j.kernel.api.Statement; import org.neo4j.kernel.api.Statement;
import org.neo4j.kernel.api.StatementTokenNameLookup;
import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint;
import org.neo4j.kernel.api.exceptions.TransactionFailureException; import org.neo4j.kernel.api.exceptions.TransactionFailureException;
import org.neo4j.kernel.api.exceptions.index.IndexEntryConflictException; import org.neo4j.kernel.api.exceptions.index.IndexEntryConflictException;
import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException;
import org.neo4j.kernel.api.exceptions.index.IndexPopulationFailedKernelException; import org.neo4j.kernel.api.exceptions.index.IndexPopulationFailedKernelException;
import org.neo4j.kernel.api.exceptions.schema.AlreadyConstrainedException;
import org.neo4j.kernel.api.exceptions.schema.ConstraintVerificationFailedKernelException; import org.neo4j.kernel.api.exceptions.schema.ConstraintVerificationFailedKernelException;
import org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException; import org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException;
import org.neo4j.kernel.api.exceptions.schema.DropIndexFailureException; import org.neo4j.kernel.api.exceptions.schema.DropIndexFailureException;
import org.neo4j.kernel.api.exceptions.schema.SchemaRuleNotFoundException; import org.neo4j.kernel.api.exceptions.schema.SchemaRuleNotFoundException;
import org.neo4j.kernel.api.exceptions.schema.UniquenessConstraintVerificationFailedKernelException; import org.neo4j.kernel.api.exceptions.schema.UniquenessConstraintVerificationFailedKernelException;
import org.neo4j.kernel.api.exceptions.schema.SchemaKernelException.OperationContext;
import org.neo4j.kernel.api.index.IndexDescriptor; import org.neo4j.kernel.api.index.IndexDescriptor;
import org.neo4j.kernel.api.index.PropertyAccessor; import org.neo4j.kernel.api.index.PropertyAccessor;
import org.neo4j.kernel.impl.api.KernelStatement; import org.neo4j.kernel.impl.api.KernelStatement;
Expand Down Expand Up @@ -89,9 +91,9 @@ public ConstraintIndexCreator( Supplier<KernelAPI> kernelSupplier, IndexingServi
public long createUniquenessConstraintIndex( KernelStatement state, SchemaReadOperations schema, public long createUniquenessConstraintIndex( KernelStatement state, SchemaReadOperations schema,
int labelId, int propertyKeyId ) int labelId, int propertyKeyId )
throws ConstraintVerificationFailedKernelException, TransactionFailureException, throws ConstraintVerificationFailedKernelException, TransactionFailureException,
CreateConstraintFailureException, DropIndexFailureException CreateConstraintFailureException, DropIndexFailureException, AlreadyConstrainedException
{ {
IndexDescriptor descriptor = getOrCreateConstraintIndex( state, labelId, propertyKeyId ); IndexDescriptor descriptor = getOrCreateConstraintIndex( state, schema, labelId, propertyKeyId );
UniquenessConstraint constraint = new UniquenessConstraint( labelId, propertyKeyId ); UniquenessConstraint constraint = new UniquenessConstraint( labelId, propertyKeyId );


boolean success = false; boolean success = false;
Expand Down Expand Up @@ -211,11 +213,10 @@ private void awaitIndexPopulation( UniquenessConstraint constraint, long indexId
} }
} }


public IndexDescriptor getOrCreateConstraintIndex( KernelStatement state, public IndexDescriptor getOrCreateConstraintIndex( KernelStatement state, SchemaReadOperations schema,
int labelId, int propertyKeyId ) int labelId, int propertyKeyId ) throws AlreadyConstrainedException
{ {
ReadOperations readOperations = state.readOperations(); for ( IndexDescriptor descriptor : loop( schema.uniqueIndexesGetForLabel( state, labelId ) ) )
for ( IndexDescriptor descriptor : loop( readOperations.uniqueIndexesGetForLabel( labelId ) ) )
{ {
if ( descriptor.getPropertyKeyId() == propertyKeyId ) if ( descriptor.getPropertyKeyId() == propertyKeyId )
{ {
Expand All @@ -224,10 +225,14 @@ public IndexDescriptor getOrCreateConstraintIndex( KernelStatement state,
// constraint creation, due to crash or similar, hence the missing owner. // constraint creation, due to crash or similar, hence the missing owner.
try try
{ {
if ( readOperations.indexGetOwningUniquenessConstraintId( descriptor ) == null ) if ( schema.indexGetOwningUniquenessConstraintId( state, descriptor ) == null )
{ {
return descriptor; return descriptor;
} }
throw new AlreadyConstrainedException(
new UniquenessConstraint( descriptor.getLabelId(), descriptor.getPropertyKeyId() ),
OperationContext.CONSTRAINT_CREATION,
new StatementTokenNameLookup( state.readOperations() ) );
} }
catch ( SchemaRuleNotFoundException e ) catch ( SchemaRuleNotFoundException e )
{ {
Expand Down
Expand Up @@ -24,6 +24,7 @@
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;


import org.neo4j.helpers.collection.Iterators;
import org.neo4j.kernel.api.KernelAPI; import org.neo4j.kernel.api.KernelAPI;
import org.neo4j.kernel.api.KernelTransaction; import org.neo4j.kernel.api.KernelTransaction;
import org.neo4j.kernel.api.Statement; import org.neo4j.kernel.api.Statement;
Expand All @@ -32,6 +33,7 @@
import org.neo4j.kernel.api.exceptions.Status; import org.neo4j.kernel.api.exceptions.Status;
import org.neo4j.kernel.api.exceptions.TransactionFailureException; import org.neo4j.kernel.api.exceptions.TransactionFailureException;
import org.neo4j.kernel.api.exceptions.index.IndexPopulationFailedKernelException; import org.neo4j.kernel.api.exceptions.index.IndexPopulationFailedKernelException;
import org.neo4j.kernel.api.exceptions.schema.AlreadyConstrainedException;
import org.neo4j.kernel.api.exceptions.schema.ConstraintVerificationFailedKernelException; import org.neo4j.kernel.api.exceptions.schema.ConstraintVerificationFailedKernelException;
import org.neo4j.kernel.api.index.IndexDescriptor; import org.neo4j.kernel.api.index.IndexDescriptor;
import org.neo4j.kernel.api.index.PreexistingIndexEntryConflictException; import org.neo4j.kernel.api.index.PreexistingIndexEntryConflictException;
Expand All @@ -56,6 +58,8 @@
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;

import static org.neo4j.helpers.collection.Iterators.iterator;
import static org.neo4j.kernel.impl.api.StatementOperationsTestHelper.mockedParts; import static org.neo4j.kernel.impl.api.StatementOperationsTestHelper.mockedParts;
import static org.neo4j.kernel.impl.api.StatementOperationsTestHelper.mockedState; import static org.neo4j.kernel.impl.api.StatementOperationsTestHelper.mockedState;
import static org.neo4j.kernel.impl.store.SchemaStorage.IndexRuleKind.CONSTRAINT; import static org.neo4j.kernel.impl.store.SchemaStorage.IndexRuleKind.CONSTRAINT;
Expand All @@ -69,7 +73,8 @@ public void shouldCreateIndexInAnotherTransaction() throws Exception
StatementOperationParts constraintCreationContext = mockedParts(); StatementOperationParts constraintCreationContext = mockedParts();
StatementOperationParts indexCreationContext = mockedParts(); StatementOperationParts indexCreationContext = mockedParts();


IndexDescriptor descriptor = new IndexDescriptor( 123, 456 ); int labelId = 123;
IndexDescriptor descriptor = new IndexDescriptor( labelId, 456 );
KernelStatement state = mockedState(); KernelStatement state = mockedState();


IndexingService indexingService = mock( IndexingService.class ); IndexingService indexingService = mock( IndexingService.class );
Expand All @@ -80,7 +85,8 @@ public void shouldCreateIndexInAnotherTransaction() throws Exception
IndexProxy indexProxy = mock( IndexProxy.class ); IndexProxy indexProxy = mock( IndexProxy.class );
when( indexingService.getIndexProxy( 2468L ) ).thenReturn( indexProxy ); when( indexingService.getIndexProxy( 2468L ) ).thenReturn( indexProxy );
PropertyAccessor propertyAccessor = mock( PropertyAccessor.class ); PropertyAccessor propertyAccessor = mock( PropertyAccessor.class );

when( constraintCreationContext.schemaReadOperations().uniqueIndexesGetForLabel( state, labelId ) )
.thenReturn( Iterators.emptyIterator() );
ConstraintIndexCreator creator = new ConstraintIndexCreator( () -> kernel, indexingService, propertyAccessor, false ); ConstraintIndexCreator creator = new ConstraintIndexCreator( () -> kernel, indexingService, propertyAccessor, false );


// when // when
Expand All @@ -92,6 +98,7 @@ public void shouldCreateIndexInAnotherTransaction() throws Exception
verify( kernel.statements.get( 0 ).txState() ).constraintIndexRuleDoAdd( descriptor ); verify( kernel.statements.get( 0 ).txState() ).constraintIndexRuleDoAdd( descriptor );
verifyNoMoreInteractions( indexCreationContext.schemaWriteOperations() ); verifyNoMoreInteractions( indexCreationContext.schemaWriteOperations() );
verify( constraintCreationContext.schemaReadOperations() ).indexGetCommittedId( state, descriptor, CONSTRAINT ); verify( constraintCreationContext.schemaReadOperations() ).indexGetCommittedId( state, descriptor, CONSTRAINT );
verify( constraintCreationContext.schemaReadOperations() ).uniqueIndexesGetForLabel( state, labelId );
verifyNoMoreInteractions( constraintCreationContext.schemaReadOperations() ); verifyNoMoreInteractions( constraintCreationContext.schemaReadOperations() );
verify( indexProxy ).awaitStoreScanCompleted(); verify( indexProxy ).awaitStoreScanCompleted();
} }
Expand All @@ -103,7 +110,8 @@ public void shouldDropIndexIfPopulationFails() throws Exception
StatementOperationParts constraintCreationContext = mockedParts(); StatementOperationParts constraintCreationContext = mockedParts();
KernelStatement state = mockedState(); KernelStatement state = mockedState();


IndexDescriptor descriptor = new IndexDescriptor( 123, 456 ); int labelId = 123;
IndexDescriptor descriptor = new IndexDescriptor( labelId, 456 );


IndexingService indexingService = mock( IndexingService.class ); IndexingService indexingService = mock( IndexingService.class );
StubKernel kernel = new StubKernel(); StubKernel kernel = new StubKernel();
Expand All @@ -116,13 +124,14 @@ public void shouldDropIndexIfPopulationFails() throws Exception
doThrow( new IndexPopulationFailedKernelException( descriptor, "some index", cause) ) doThrow( new IndexPopulationFailedKernelException( descriptor, "some index", cause) )
.when(indexProxy).awaitStoreScanCompleted(); .when(indexProxy).awaitStoreScanCompleted();
PropertyAccessor propertyAccessor = mock( PropertyAccessor.class ); PropertyAccessor propertyAccessor = mock( PropertyAccessor.class );

when( constraintCreationContext.schemaReadOperations().uniqueIndexesGetForLabel( state, labelId ) )
.thenReturn( Iterators.emptyIterator() );
ConstraintIndexCreator creator = new ConstraintIndexCreator( () -> kernel, indexingService, propertyAccessor, false ); ConstraintIndexCreator creator = new ConstraintIndexCreator( () -> kernel, indexingService, propertyAccessor, false );


// when // when
try try
{ {
creator.createUniquenessConstraintIndex( state, constraintCreationContext.schemaReadOperations(), 123, 456 ); creator.createUniquenessConstraintIndex( state, constraintCreationContext.schemaReadOperations(), labelId, 456 );


fail( "expected exception" ); fail( "expected exception" );
} }
Expand All @@ -134,12 +143,13 @@ public void shouldDropIndexIfPopulationFails() throws Exception
} }
assertEquals( 2, kernel.statements.size() ); assertEquals( 2, kernel.statements.size() );
TransactionState tx1 = kernel.statements.get( 0 ).txState(); TransactionState tx1 = kernel.statements.get( 0 ).txState();
verify( tx1 ).constraintIndexRuleDoAdd( new IndexDescriptor( 123, 456 ) ); verify( tx1 ).constraintIndexRuleDoAdd( new IndexDescriptor( labelId, 456 ) );
verifyNoMoreInteractions( tx1 ); verifyNoMoreInteractions( tx1 );
verify( constraintCreationContext.schemaReadOperations() ).indexGetCommittedId( state, descriptor, CONSTRAINT ); verify( constraintCreationContext.schemaReadOperations() ).indexGetCommittedId( state, descriptor, CONSTRAINT );
verify( constraintCreationContext.schemaReadOperations() ).uniqueIndexesGetForLabel( state, labelId );
verifyNoMoreInteractions( constraintCreationContext.schemaReadOperations() ); verifyNoMoreInteractions( constraintCreationContext.schemaReadOperations() );
TransactionState tx2 = kernel.statements.get( 1 ).txState(); TransactionState tx2 = kernel.statements.get( 1 ).txState();
verify( tx2 ).constraintIndexDoDrop( new IndexDescriptor( 123, 456 ) ); verify( tx2 ).constraintIndexDoDrop( new IndexDescriptor( labelId, 456 ) );
verifyNoMoreInteractions( tx2 ); verifyNoMoreInteractions( tx2 );
} }


Expand Down Expand Up @@ -171,7 +181,8 @@ public void shouldReleaseSchemaLockWhileAwaitingIndexPopulation() throws Excepti
StubKernel kernel = new StubKernel(); StubKernel kernel = new StubKernel();
IndexingService indexingService = mock( IndexingService.class ); IndexingService indexingService = mock( IndexingService.class );
StatementOperationParts constraintCreationContext = mockedParts(); StatementOperationParts constraintCreationContext = mockedParts();
IndexDescriptor descriptor = new IndexDescriptor( 123, 456 ); int labelId = 123;
IndexDescriptor descriptor = new IndexDescriptor( labelId, 456 );
PropertyAccessor propertyAccessor = mock( PropertyAccessor.class ); PropertyAccessor propertyAccessor = mock( PropertyAccessor.class );


KernelStatement state = mockedState(); KernelStatement state = mockedState();
Expand All @@ -180,17 +191,114 @@ public void shouldReleaseSchemaLockWhileAwaitingIndexPopulation() throws Excepti
.thenReturn( 2468L ); .thenReturn( 2468L );
IndexProxy indexProxy = mock( IndexProxy.class ); IndexProxy indexProxy = mock( IndexProxy.class );
when( indexingService.getIndexProxy( anyLong() ) ).thenReturn( indexProxy ); when( indexingService.getIndexProxy( anyLong() ) ).thenReturn( indexProxy );
when( constraintCreationContext.schemaReadOperations().uniqueIndexesGetForLabel( state, labelId ) )
.thenReturn( Iterators.emptyIterator() );


ConstraintIndexCreator creator = new ConstraintIndexCreator( () -> kernel, indexingService, propertyAccessor, true ); ConstraintIndexCreator creator = new ConstraintIndexCreator( () -> kernel, indexingService, propertyAccessor, true );


// when // when
creator.createUniquenessConstraintIndex( state, constraintCreationContext.schemaReadOperations(), 123, 456 ); creator.createUniquenessConstraintIndex( state, constraintCreationContext.schemaReadOperations(), labelId, 456 );


// then // then
verify( state.locks().pessimistic() ).releaseExclusive( ResourceTypes.SCHEMA, ResourceTypes.schemaResource() ); verify( state.locks().pessimistic() ).releaseExclusive( ResourceTypes.SCHEMA, ResourceTypes.schemaResource() );
verify( state.locks().pessimistic() ).acquireExclusive( ResourceTypes.SCHEMA, ResourceTypes.schemaResource() ); verify( state.locks().pessimistic() ).acquireExclusive( ResourceTypes.SCHEMA, ResourceTypes.schemaResource() );
} }


@Test
public void shouldReuseExistingOrphanedConstraintIndex() throws Exception
{
// given
StatementOperationParts constraintCreationContext = mockedParts();
StatementOperationParts indexCreationContext = mockedParts();

int labelId = 123;
int propertyKeyId = 456;
IndexDescriptor descriptor = new IndexDescriptor( labelId, propertyKeyId );
KernelStatement state = mockedState();

IndexingService indexingService = mock( IndexingService.class );
StubKernel kernel = new StubKernel();

long orphanedConstraintIndexId = 111;
when( constraintCreationContext.schemaReadOperations().indexGetCommittedId( state, descriptor, CONSTRAINT ) )
.thenReturn( orphanedConstraintIndexId );
IndexProxy indexProxy = mock( IndexProxy.class );
when( indexingService.getIndexProxy( orphanedConstraintIndexId ) ).thenReturn( indexProxy );
PropertyAccessor propertyAccessor = mock( PropertyAccessor.class );
when( constraintCreationContext.schemaReadOperations().uniqueIndexesGetForLabel( state, labelId ) )
.thenReturn( iterator( descriptor ) );
when( constraintCreationContext.schemaReadOperations().indexGetOwningUniquenessConstraintId(
state, descriptor ) ).thenReturn( null ); // which means it has no owner
ConstraintIndexCreator creator = new ConstraintIndexCreator( () -> kernel, indexingService, propertyAccessor, false );

// when
long indexId = creator.createUniquenessConstraintIndex( state, constraintCreationContext.schemaReadOperations(), 123, propertyKeyId );

// then
assertEquals( orphanedConstraintIndexId, indexId );
assertEquals( "There should have been no need to acquire a statement to create the constraint index", 0,
kernel.statements.size() );
verifyNoMoreInteractions( indexCreationContext.schemaWriteOperations() );
verify( constraintCreationContext.schemaReadOperations() ).indexGetCommittedId( state, descriptor, CONSTRAINT );
verify( constraintCreationContext.schemaReadOperations() ).uniqueIndexesGetForLabel( state, labelId );
verify( constraintCreationContext.schemaReadOperations() )
.indexGetOwningUniquenessConstraintId( state, descriptor );
verifyNoMoreInteractions( constraintCreationContext.schemaReadOperations() );
verify( indexProxy ).awaitStoreScanCompleted();
}

@Test
public void shouldFailOnExistingOwnedConstraintIndex() throws Exception
{
// given
StatementOperationParts constraintCreationContext = mockedParts();
StatementOperationParts indexCreationContext = mockedParts();

int labelId = 123;
int propertyKeyId = 456;
IndexDescriptor descriptor = new IndexDescriptor( labelId, propertyKeyId );
KernelStatement state = mockedState();

IndexingService indexingService = mock( IndexingService.class );
StubKernel kernel = new StubKernel();

long constraintIndexId = 111;
long constraintIndexOwnerId = 222;
when( constraintCreationContext.schemaReadOperations().indexGetCommittedId( state, descriptor, CONSTRAINT ) )
.thenReturn( constraintIndexId );
IndexProxy indexProxy = mock( IndexProxy.class );
when( indexingService.getIndexProxy( constraintIndexId ) ).thenReturn( indexProxy );
PropertyAccessor propertyAccessor = mock( PropertyAccessor.class );
when( constraintCreationContext.schemaReadOperations().uniqueIndexesGetForLabel( state, labelId ) )
.thenReturn( iterator( descriptor ) );
when( constraintCreationContext.schemaReadOperations().indexGetOwningUniquenessConstraintId(
state, descriptor ) ).thenReturn( constraintIndexOwnerId ); // which means there's an owner
when( state.readOperations().labelGetName( labelId ) ).thenReturn( "MyLabel" );
when( state.readOperations().propertyKeyGetName( propertyKeyId ) ).thenReturn( "MyKey" );
ConstraintIndexCreator creator = new ConstraintIndexCreator( () -> kernel, indexingService, propertyAccessor, false );

// when
try
{
creator.createUniquenessConstraintIndex( state, constraintCreationContext.schemaReadOperations(), 123,
propertyKeyId );
fail( "Should've failed" );
}
catch ( AlreadyConstrainedException e )
{
// THEN good
}

// then
assertEquals( "There should have been no need to acquire a statement to create the constraint index", 0,
kernel.statements.size() );
verifyNoMoreInteractions( indexCreationContext.schemaWriteOperations() );
verify( constraintCreationContext.schemaReadOperations() ).uniqueIndexesGetForLabel( state, labelId );
verify( constraintCreationContext.schemaReadOperations() )
.indexGetOwningUniquenessConstraintId( state, descriptor );
verifyNoMoreInteractions( constraintCreationContext.schemaReadOperations() );
}

private class StubKernel implements KernelAPI private class StubKernel implements KernelAPI
{ {
private final List<KernelStatement> statements = new ArrayList<>(); private final List<KernelStatement> statements = new ArrayList<>();
Expand Down
Expand Up @@ -32,6 +32,7 @@
import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Transaction; import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.mockfs.EphemeralFileSystemAbstraction; import org.neo4j.graphdb.mockfs.EphemeralFileSystemAbstraction;
import org.neo4j.graphdb.schema.IndexDefinition;
import org.neo4j.helpers.collection.Iterables; import org.neo4j.helpers.collection.Iterables;
import org.neo4j.kernel.impl.api.index.IndexingService; import org.neo4j.kernel.impl.api.index.IndexingService;
import org.neo4j.kernel.impl.storageengine.impl.recordstorage.RecordStorageEngine; import org.neo4j.kernel.impl.storageengine.impl.recordstorage.RecordStorageEngine;
Expand All @@ -44,16 +45,20 @@
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;


import static org.neo4j.helpers.collection.Iterables.single;

public class ConstraintRecoveryIT public class ConstraintRecoveryIT
{ {
private static final String KEY = "prop";
private static final Label LABEL = Label.label( "label1" );

@Rule @Rule
public EphemeralFileSystemRule fileSystemRule = new EphemeralFileSystemRule(); public EphemeralFileSystemRule fileSystemRule = new EphemeralFileSystemRule();


private static final Label LABEL = Label.label( "label1" );
private GraphDatabaseAPI db; private GraphDatabaseAPI db;


@Test @Test
public void shouldNotHaveAnIndexIfUniqueConstraintCreationOnRecoveryFails() throws IOException public void shouldHaveAvailableOrphanedConstraintIndexIfUniqueConstraintCreationFails() throws IOException
{ {
// given // given
final EphemeralFileSystemAbstraction fs = fileSystemRule.get(); final EphemeralFileSystemAbstraction fs = fileSystemRule.get();
Expand Down Expand Up @@ -87,15 +92,15 @@ public void indexPopulationScanComplete()
for ( int i = 0; i < 2; i++ ) for ( int i = 0; i < 2; i++ )
{ {
Node node1 = db.createNode( LABEL ); Node node1 = db.createNode( LABEL );
node1.setProperty( "prop", true ); node1.setProperty( KEY, true );
} }


tx.success(); tx.success();
} }


try ( Transaction tx = db.beginTx() ) try ( Transaction tx = db.beginTx() )
{ {
db.schema().constraintFor( LABEL ).assertPropertyIsUnique( "prop" ).create(); db.schema().constraintFor( LABEL ).assertPropertyIsUnique( KEY ).create();
fail("Should have failed with ConstraintViolationException"); fail("Should have failed with ConstraintViolationException");
tx.success(); tx.success();
} }
Expand Down Expand Up @@ -128,7 +133,9 @@ public void indexPopulationScanComplete()


try(Transaction tx = db.beginTx()) try(Transaction tx = db.beginTx())
{ {
assertEquals(0, Iterables.count(Iterables.asList( db.schema().getIndexes() ))); IndexDefinition orphanedConstraintIndex = single( db.schema().getIndexes() );
assertEquals( LABEL.name(), orphanedConstraintIndex.getLabel().name() );
assertEquals( KEY, single( orphanedConstraintIndex.getPropertyKeys() ) );
} }


db.shutdown(); db.shutdown();
Expand Down

0 comments on commit 55d7b9e

Please sign in to comment.