diff --git a/community/consistency-check/src/main/java/org/neo4j/consistency/checking/SchemaRecordCheck.java b/community/consistency-check/src/main/java/org/neo4j/consistency/checking/SchemaRecordCheck.java index 0fd1885d094b6..01e6c9a42bbe0 100644 --- a/community/consistency-check/src/main/java/org/neo4j/consistency/checking/SchemaRecordCheck.java +++ b/community/consistency-check/src/main/java/org/neo4j/consistency/checking/SchemaRecordCheck.java @@ -27,7 +27,7 @@ import org.neo4j.consistency.store.RecordAccess; import org.neo4j.kernel.api.exceptions.schema.MalformedSchemaRuleException; import org.neo4j.kernel.impl.store.SchemaRuleAccess; -import org.neo4j.kernel.impl.store.UniquenessConstraintRule; +import org.neo4j.kernel.impl.store.UniquePropertyConstraintRule; import org.neo4j.kernel.impl.store.record.DynamicRecord; import org.neo4j.kernel.impl.store.record.IndexRule; import org.neo4j.kernel.impl.store.record.LabelTokenRecord; @@ -131,7 +131,7 @@ public void check( DynamicRecord record, checkIndexRule( (IndexRule) rule, engine, record, records ); break; case UNIQUENESS_CONSTRAINT: - checkUniquenessConstraintRule( (UniquenessConstraintRule) rule, engine, record, records ); + checkUniquenessConstraintRule( (UniquePropertyConstraintRule) rule, engine, record, records ); break; default: engine.report().unsupportedSchemaRuleKind( kind ); @@ -139,7 +139,7 @@ public void check( DynamicRecord record, } } - private void checkUniquenessConstraintRule( UniquenessConstraintRule rule, + private void checkUniquenessConstraintRule( UniquePropertyConstraintRule rule, CheckerEngine engine, DynamicRecord record, RecordAccess records ) { diff --git a/community/consistency-check/src/main/java/org/neo4j/consistency/checking/SchemaRuleContent.java b/community/consistency-check/src/main/java/org/neo4j/consistency/checking/SchemaRuleContent.java index f04592288022f..db94de191f713 100644 --- a/community/consistency-check/src/main/java/org/neo4j/consistency/checking/SchemaRuleContent.java +++ b/community/consistency-check/src/main/java/org/neo4j/consistency/checking/SchemaRuleContent.java @@ -19,7 +19,7 @@ */ package org.neo4j.consistency.checking; -import org.neo4j.kernel.impl.store.UniquenessConstraintRule; +import org.neo4j.kernel.impl.store.UniquePropertyConstraintRule; import org.neo4j.kernel.impl.store.record.IndexRule; import org.neo4j.kernel.impl.store.record.SchemaRule; @@ -63,8 +63,8 @@ public boolean equals( Object obj ) return indexRulesEquals( (IndexRule) this.schemaRule, (IndexRule) that.schemaRule ); case UNIQUENESS_CONSTRAINT: return this.schemaRule.getKind() == that.schemaRule.getKind() && uniquenessConstraintEquals( - (UniquenessConstraintRule) this.schemaRule, - (UniquenessConstraintRule) that.schemaRule ); + (UniquePropertyConstraintRule) this.schemaRule, + (UniquePropertyConstraintRule) that.schemaRule ); default: throw new IllegalArgumentException( "Invalid SchemaRule kind: " + schemaRule.getKind() ); } @@ -77,7 +77,7 @@ private static boolean indexRulesEquals( IndexRule lhs, IndexRule rhs ) return lhs.getPropertyKey() == rhs.getPropertyKey(); } - private static boolean uniquenessConstraintEquals( UniquenessConstraintRule lhs, UniquenessConstraintRule rhs ) + private static boolean uniquenessConstraintEquals( UniquePropertyConstraintRule lhs, UniquePropertyConstraintRule rhs ) { return lhs.getPropertyKey() == rhs.getPropertyKey(); } diff --git a/community/consistency-check/src/test/java/org/neo4j/consistency/checking/SchemaRecordCheckTest.java b/community/consistency-check/src/test/java/org/neo4j/consistency/checking/SchemaRecordCheckTest.java index 102c013a79b5a..40fad91dee85a 100644 --- a/community/consistency-check/src/test/java/org/neo4j/consistency/checking/SchemaRecordCheckTest.java +++ b/community/consistency-check/src/test/java/org/neo4j/consistency/checking/SchemaRecordCheckTest.java @@ -26,7 +26,7 @@ import org.neo4j.kernel.api.exceptions.schema.MalformedSchemaRuleException; import org.neo4j.kernel.api.index.SchemaIndexProvider; import org.neo4j.kernel.impl.store.SchemaStorage; -import org.neo4j.kernel.impl.store.UniquenessConstraintRule; +import org.neo4j.kernel.impl.store.UniquePropertyConstraintRule; import org.neo4j.kernel.impl.store.record.DynamicRecord; import org.neo4j.kernel.impl.store.record.IndexRule; import org.neo4j.kernel.impl.store.record.LabelTokenRecord; @@ -126,7 +126,8 @@ public void shouldReportInvalidPropertyReferenceFromUniquenessConstraintRule() t DynamicRecord record = inUse( dynamicRecord( schemaRuleId ) ); - UniquenessConstraintRule rule = UniquenessConstraintRule.uniquenessConstraintRule( schemaRuleId, labelId, propertyKeyId, indexRuleId ); + UniquePropertyConstraintRule rule = UniquePropertyConstraintRule + .uniquenessConstraintRule( schemaRuleId, labelId, propertyKeyId, indexRuleId ); when( checker().ruleAccess.loadSingleSchemaRule( schemaRuleId ) ).thenReturn( rule ); @@ -155,7 +156,8 @@ public void shouldReportUniquenessConstraintNotReferencingBack() throws Exceptio SchemaIndexProvider.Descriptor providerDescriptor = new SchemaIndexProvider.Descriptor( "in-memory", "1.0" ); IndexRule rule1 = IndexRule.constraintIndexRule( ruleId1, labelId, propertyKeyId, providerDescriptor, (long) ruleId2 ); - UniquenessConstraintRule rule2 = UniquenessConstraintRule.uniquenessConstraintRule( ruleId2, labelId, propertyKeyId, ruleId2 ); + UniquePropertyConstraintRule rule2 = UniquePropertyConstraintRule + .uniquenessConstraintRule( ruleId2, labelId, propertyKeyId, ruleId2 ); when( checker().ruleAccess.loadSingleSchemaRule( ruleId1 ) ).thenReturn( rule1 ); when( checker().ruleAccess.loadSingleSchemaRule( ruleId2 ) ).thenReturn( rule2 ); @@ -214,8 +216,10 @@ public void shouldReportTwoUniquenessConstraintsReferencingSameIndex() throws Ex DynamicRecord record1 = inUse( dynamicRecord( ruleId1 ) ); DynamicRecord record2 = inUse( dynamicRecord( ruleId2 ) ); - UniquenessConstraintRule rule1 = UniquenessConstraintRule.uniquenessConstraintRule( ruleId1, labelId, propertyKeyId, ruleId2 ); - UniquenessConstraintRule rule2 = UniquenessConstraintRule.uniquenessConstraintRule( ruleId2, labelId, propertyKeyId, ruleId2 ); + UniquePropertyConstraintRule rule1 = UniquePropertyConstraintRule + .uniquenessConstraintRule( ruleId1, labelId, propertyKeyId, ruleId2 ); + UniquePropertyConstraintRule rule2 = UniquePropertyConstraintRule + .uniquenessConstraintRule( ruleId2, labelId, propertyKeyId, ruleId2 ); when( checker().ruleAccess.loadSingleSchemaRule( ruleId1 ) ).thenReturn( rule1 ); when( checker().ruleAccess.loadSingleSchemaRule( ruleId2 ) ).thenReturn( rule2 ); @@ -241,7 +245,8 @@ public void shouldReportUnreferencedUniquenessConstraint() throws Exception DynamicRecord record = inUse( dynamicRecord( ruleId ) ); - UniquenessConstraintRule rule = UniquenessConstraintRule.uniquenessConstraintRule( ruleId, labelId, propertyKeyId, ruleId ); + UniquePropertyConstraintRule rule = UniquePropertyConstraintRule + .uniquenessConstraintRule( ruleId, labelId, propertyKeyId, ruleId ); when( checker().ruleAccess.loadSingleSchemaRule( ruleId ) ).thenReturn( rule ); @@ -271,8 +276,10 @@ public void shouldReportConstraintIndexNotReferencingBack() throws Exception SchemaIndexProvider.Descriptor providerDescriptor = new SchemaIndexProvider.Descriptor( "in-memory", "1.0" ); - IndexRule rule1 = IndexRule.constraintIndexRule( ruleId1, labelId, propertyKeyId, providerDescriptor, (long) ruleId1 ); - UniquenessConstraintRule rule2 = UniquenessConstraintRule.uniquenessConstraintRule( ruleId2, labelId, propertyKeyId, ruleId1 ); + IndexRule rule1 = IndexRule.constraintIndexRule( ruleId1, labelId, propertyKeyId, providerDescriptor, (long) + ruleId1 ); + UniquePropertyConstraintRule rule2 = UniquePropertyConstraintRule + .uniquenessConstraintRule( ruleId2, labelId, propertyKeyId, ruleId1 ); when( checker().ruleAccess.loadSingleSchemaRule( ruleId1 ) ).thenReturn( rule1 ); when( checker().ruleAccess.loadSingleSchemaRule( ruleId2 ) ).thenReturn( rule2 ); diff --git a/community/consistency-check/src/test/java/org/neo4j/consistency/checking/SchemaRuleContentTest.java b/community/consistency-check/src/test/java/org/neo4j/consistency/checking/SchemaRuleContentTest.java index 9e879360e1522..020d8f82b9fb4 100644 --- a/community/consistency-check/src/test/java/org/neo4j/consistency/checking/SchemaRuleContentTest.java +++ b/community/consistency-check/src/test/java/org/neo4j/consistency/checking/SchemaRuleContentTest.java @@ -26,7 +26,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; -import static org.neo4j.kernel.impl.store.UniquenessConstraintRule.uniquenessConstraintRule; +import static org.neo4j.kernel.impl.store.UniquePropertyConstraintRule.uniquenessConstraintRule; import static org.neo4j.kernel.impl.store.record.IndexRule.constraintIndexRule; import static org.neo4j.kernel.impl.store.record.IndexRule.indexRule; diff --git a/community/consistency-check/src/test/java/org/neo4j/consistency/checking/full/FullCheckIntegrationTest.java b/community/consistency-check/src/test/java/org/neo4j/consistency/checking/full/FullCheckIntegrationTest.java index 4a8986482a0d1..f48375be58b34 100644 --- a/community/consistency-check/src/test/java/org/neo4j/consistency/checking/full/FullCheckIntegrationTest.java +++ b/community/consistency-check/src/test/java/org/neo4j/consistency/checking/full/FullCheckIntegrationTest.java @@ -75,7 +75,7 @@ import org.neo4j.kernel.impl.store.RecordStore; import org.neo4j.kernel.impl.store.SchemaStorage; import org.neo4j.kernel.impl.store.StoreAccess; -import org.neo4j.kernel.impl.store.UniquenessConstraintRule; +import org.neo4j.kernel.impl.store.UniquePropertyConstraintRule; import org.neo4j.kernel.impl.store.record.DynamicRecord; import org.neo4j.kernel.impl.store.record.IndexRule; import org.neo4j.kernel.impl.store.record.LabelTokenRecord; @@ -856,7 +856,8 @@ protected void transactionData( GraphStoreFixture.TransactionDataBuilder tx, SchemaIndexProvider.Descriptor providerDescriptor = new SchemaIndexProvider.Descriptor( "lucene", "1.0" ); IndexRule rule1 = IndexRule.constraintIndexRule( ruleId1, labelId, propertyKeyId, providerDescriptor, (long) ruleId2 ); - UniquenessConstraintRule rule2 = UniquenessConstraintRule.uniquenessConstraintRule( ruleId2, labelId, propertyKeyId, ruleId2 ); + UniquePropertyConstraintRule rule2 = UniquePropertyConstraintRule + .uniquenessConstraintRule( ruleId2, labelId, propertyKeyId, ruleId2 ); Collection records1 = serializeRule( rule1, record1 ); diff --git a/community/cypher/cypher-compiler-2.3/src/main/scala/org/neo4j/cypher/internal/compiler/v2_3/spi/PlanContext.scala b/community/cypher/cypher-compiler-2.3/src/main/scala/org/neo4j/cypher/internal/compiler/v2_3/spi/PlanContext.scala index 55a18114fbccb..0a9f13dd537a2 100644 --- a/community/cypher/cypher-compiler-2.3/src/main/scala/org/neo4j/cypher/internal/compiler/v2_3/spi/PlanContext.scala +++ b/community/cypher/cypher-compiler-2.3/src/main/scala/org/neo4j/cypher/internal/compiler/v2_3/spi/PlanContext.scala @@ -19,7 +19,7 @@ */ package org.neo4j.cypher.internal.compiler.v2_3.spi -import org.neo4j.kernel.api.constraints.UniquenessConstraint +import org.neo4j.kernel.api.constraints.PropertyConstraint import org.neo4j.kernel.api.index.IndexDescriptor /** @@ -35,7 +35,7 @@ trait PlanContext extends TokenContext { def getUniqueIndexRule(labelName: String, propertyKey: String): Option[IndexDescriptor] - def getUniquenessConstraint(labelName: String, propertyKey: String): Option[UniquenessConstraint] + def getUniquenessConstraint(labelName: String, propertyKey: String): Option[PropertyConstraint] def checkNodeIndex(idxName: String) diff --git a/community/cypher/cypher-compiler-2.3/src/main/scala/org/neo4j/cypher/internal/compiler/v2_3/spi/QueryContext.scala b/community/cypher/cypher-compiler-2.3/src/main/scala/org/neo4j/cypher/internal/compiler/v2_3/spi/QueryContext.scala index a753810e66fa1..350251a1710eb 100644 --- a/community/cypher/cypher-compiler-2.3/src/main/scala/org/neo4j/cypher/internal/compiler/v2_3/spi/QueryContext.scala +++ b/community/cypher/cypher-compiler-2.3/src/main/scala/org/neo4j/cypher/internal/compiler/v2_3/spi/QueryContext.scala @@ -21,7 +21,7 @@ package org.neo4j.cypher.internal.compiler.v2_3.spi import org.neo4j.cypher.internal.compiler.v2_3.InternalQueryStatistics import org.neo4j.graphdb._ -import org.neo4j.kernel.api.constraints.UniquenessConstraint +import org.neo4j.kernel.api.constraints.{MandatoryPropertyConstraint, UniquenessConstraint} import org.neo4j.kernel.api.index.IndexDescriptor /* @@ -95,7 +95,7 @@ trait QueryContext extends TokenContext { def dropUniqueConstraint(labelId: Int, propertyKeyId: Int) - def createMandatoryConstraint(labelId: Int, propertyKeyId: Int): IdempotentResult[UniquenessConstraint]//TODO add MandatoryConstraint when doing kernel work + def createMandatoryConstraint(labelId: Int, propertyKeyId: Int): IdempotentResult[MandatoryPropertyConstraint] def dropMandatoryConstraint(labelId: Int, propertyKeyId: Int) diff --git a/community/cypher/cypher-compiler-2.3/src/test/scala/org/neo4j/cypher/internal/compiler/v2_3/executionplan/builders/StartPointChoosingBuilderTest.scala b/community/cypher/cypher-compiler-2.3/src/test/scala/org/neo4j/cypher/internal/compiler/v2_3/executionplan/builders/StartPointChoosingBuilderTest.scala index cc8eb97a3fb0b..c75c935d38ce5 100644 --- a/community/cypher/cypher-compiler-2.3/src/test/scala/org/neo4j/cypher/internal/compiler/v2_3/executionplan/builders/StartPointChoosingBuilderTest.scala +++ b/community/cypher/cypher-compiler-2.3/src/test/scala/org/neo4j/cypher/internal/compiler/v2_3/executionplan/builders/StartPointChoosingBuilderTest.scala @@ -33,7 +33,7 @@ import org.neo4j.cypher.internal.compiler.v2_3.pipes.FakePipe import org.neo4j.cypher.internal.compiler.v2_3.spi.PlanContext import org.neo4j.cypher.internal.compiler.v2_3.symbols._ import org.neo4j.graphdb.Direction -import org.neo4j.kernel.api.constraints.UniquenessConstraint +import org.neo4j.kernel.api.constraints.{UniquenessConstraint, PropertyConstraint} import org.neo4j.kernel.api.index.IndexDescriptor class StartPointChoosingBuilderTest extends BuilderTest { diff --git a/community/cypher/cypher-compiler-2.3/src/test/scala/org/neo4j/cypher/internal/compiler/v2_3/planner/LogicalPlanningTestSupport2.scala b/community/cypher/cypher-compiler-2.3/src/test/scala/org/neo4j/cypher/internal/compiler/v2_3/planner/LogicalPlanningTestSupport2.scala index 51acd2e6bad45..42fc03b95a073 100644 --- a/community/cypher/cypher-compiler-2.3/src/test/scala/org/neo4j/cypher/internal/compiler/v2_3/planner/LogicalPlanningTestSupport2.scala +++ b/community/cypher/cypher-compiler-2.3/src/test/scala/org/neo4j/cypher/internal/compiler/v2_3/planner/LogicalPlanningTestSupport2.scala @@ -36,7 +36,7 @@ import org.neo4j.cypher.internal.compiler.v2_3.spi.{GraphStatistics, PlanContext import org.neo4j.cypher.internal.compiler.v2_3.test_helpers.{CypherFunSuite, CypherTestSupport} import org.neo4j.cypher.internal.compiler.v2_3.tracing.rewriters.RewriterStepSequencer import org.neo4j.helpers.collection.Visitable -import org.neo4j.kernel.api.constraints.UniquenessConstraint +import org.neo4j.kernel.api.constraints.{UniquenessConstraint, PropertyConstraint} import org.neo4j.kernel.api.index.IndexDescriptor import org.neo4j.kernel.impl.util.dbstructure.DbStructureVisitor @@ -95,7 +95,7 @@ trait LogicalPlanningTestSupport2 extends CypherTestSupport with AstConstruction else None - def getUniquenessConstraint(labelName: String, propertyKey: String): Option[UniquenessConstraint] = { + def getUniquenessConstraint(labelName: String, propertyKey: String): Option[PropertyConstraint] = { if (config.uniqueIndexes((labelName, propertyKey))) Some(new UniquenessConstraint( semanticTable.resolvedLabelIds(labelName).id, diff --git a/community/cypher/cypher-compiler-2.3/src/test/scala/org/neo4j/cypher/internal/compiler/v2_3/spi/UpdateCountingQueryContextTest.scala b/community/cypher/cypher-compiler-2.3/src/test/scala/org/neo4j/cypher/internal/compiler/v2_3/spi/UpdateCountingQueryContextTest.scala index 442aef0546588..fc320bb237d25 100644 --- a/community/cypher/cypher-compiler-2.3/src/test/scala/org/neo4j/cypher/internal/compiler/v2_3/spi/UpdateCountingQueryContextTest.scala +++ b/community/cypher/cypher-compiler-2.3/src/test/scala/org/neo4j/cypher/internal/compiler/v2_3/spi/UpdateCountingQueryContextTest.scala @@ -26,7 +26,7 @@ import org.mockito.stubbing.Answer import org.neo4j.cypher.internal.compiler.v2_3.InternalQueryStatistics import org.neo4j.cypher.internal.compiler.v2_3.test_helpers.CypherFunSuite import org.neo4j.graphdb.{Node, Relationship} -import org.neo4j.kernel.api.constraints.UniquenessConstraint +import org.neo4j.kernel.api.constraints.{MandatoryPropertyConstraint, UniquenessConstraint} import org.neo4j.kernel.api.index.IndexDescriptor class UpdateCountingQueryContextTest extends CypherFunSuite { @@ -61,7 +61,7 @@ class UpdateCountingQueryContextTest extends CypherFunSuite { .thenReturn(IdempotentResult(mock[UniquenessConstraint])) when( inner.createMandatoryConstraint(anyInt(), anyInt()) ) - .thenReturn(IdempotentResult(mock[UniquenessConstraint])) + .thenReturn(IdempotentResult(mock[MandatoryPropertyConstraint])) when( inner.addIndexRule(anyInt(), anyInt()) ) .thenReturn(IdempotentResult(mock[IndexDescriptor])) diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_2/TransactionBoundPlanContext.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_2/TransactionBoundPlanContext.scala index 08a1aaae1b7f8..3b52244bdd875 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_2/TransactionBoundPlanContext.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_2/TransactionBoundPlanContext.scala @@ -61,8 +61,10 @@ class TransactionBoundPlanContext(someStatement: Statement, val gdb: GraphDataba val labelId = statement.readOperations().labelGetForName(labelName) val propertyKeyId = statement.readOperations().propertyKeyGetForName(propertyKey) - val matchingConstraints = statement.readOperations().constraintsGetForLabelAndPropertyKey(labelId, propertyKeyId) - if ( matchingConstraints.hasNext ) Some(matchingConstraints.next()) else None + import scala.collection.JavaConverters._ + statement.readOperations().constraintsGetForLabelAndPropertyKey(labelId, propertyKeyId).asScala.collectFirst { + case unique: UniquenessConstraint => unique + } } catch { case _: KernelException => None } diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_2/TransactionBoundQueryContext.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_2/TransactionBoundQueryContext.scala index c669c1cb31d91..413aed5417592 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_2/TransactionBoundQueryContext.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_2/TransactionBoundQueryContext.scala @@ -27,7 +27,6 @@ import org.neo4j.cypher.internal.compiler.v2_3.helpers.JavaConversionSupport._ import org.neo4j.graphdb.DynamicRelationshipType._ import org.neo4j.graphdb._ import org.neo4j.graphdb.factory.GraphDatabaseSettings -import org.neo4j.helpers.collection.IteratorUtil import org.neo4j.kernel.GraphDatabaseAPI import org.neo4j.kernel.api._ import org.neo4j.kernel.api.constraints.UniquenessConstraint @@ -281,12 +280,10 @@ final class TransactionBoundQueryContext(graph: GraphDatabaseAPI, statement.schemaWriteOperations().indexDrop(new IndexDescriptor(labelId, propertyKeyId)) def createUniqueConstraint(labelId: Int, propertyKeyId: Int): IdempotentResult[UniquenessConstraint] = try { - IdempotentResult(statement.schemaWriteOperations().uniquenessConstraintCreate(labelId, propertyKeyId)) + IdempotentResult(statement.schemaWriteOperations().uniquePropertyConstraintCreate(labelId, propertyKeyId)) } catch { - case _: AlreadyConstrainedException => - val readOperations: ReadOperations = statement.readOperations() - val uniquenessConstraints = readOperations.constraintsGetForLabelAndPropertyKey(labelId, propertyKeyId) - IdempotentResult(IteratorUtil.single(uniquenessConstraints), wasCreated = false) + case existing: AlreadyConstrainedException => + IdempotentResult(existing.constraint().asInstanceOf[UniquenessConstraint], wasCreated = false) } def dropUniqueConstraint(labelId: Int, propertyKeyId: Int) = diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_3/TransactionBoundPlanContext.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_3/TransactionBoundPlanContext.scala index 18ba27d4be89d..be6b2d6c22f43 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_3/TransactionBoundPlanContext.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_3/TransactionBoundPlanContext.scala @@ -24,7 +24,7 @@ import org.neo4j.cypher.internal.compiler.v2_3.spi._ import org.neo4j.graphdb.GraphDatabaseService import org.neo4j.kernel.GraphDatabaseAPI import org.neo4j.kernel.api.Statement -import org.neo4j.kernel.api.constraints.UniquenessConstraint +import org.neo4j.kernel.api.constraints.PropertyConstraint import org.neo4j.kernel.api.exceptions.KernelException import org.neo4j.kernel.api.exceptions.schema.SchemaRuleNotFoundException import org.neo4j.kernel.api.index.{IndexDescriptor, InternalIndexState} @@ -57,7 +57,7 @@ class TransactionBoundPlanContext(initialStatement: Statement, val gdb: GraphDat case _ => None } - def getUniquenessConstraint(labelName: String, propertyKey: String): Option[UniquenessConstraint] = try { + def getUniquenessConstraint(labelName: String, propertyKey: String): Option[PropertyConstraint] = try { val labelId = statement.readOperations().labelGetForName(labelName) val propertyKeyId = statement.readOperations().propertyKeyGetForName(propertyKey) diff --git a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_3/TransactionBoundQueryContext.scala b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_3/TransactionBoundQueryContext.scala index ed6a4270404c8..98c5715b9027a 100644 --- a/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_3/TransactionBoundQueryContext.scala +++ b/community/cypher/cypher/src/main/scala/org/neo4j/cypher/internal/spi/v2_3/TransactionBoundQueryContext.scala @@ -30,10 +30,9 @@ import org.neo4j.cypher.internal.compiler.v2_3.{EntityNotFoundException, FailedI import org.neo4j.graphdb.DynamicRelationshipType._ import org.neo4j.graphdb._ import org.neo4j.graphdb.factory.GraphDatabaseSettings -import org.neo4j.helpers.collection.IteratorUtil import org.neo4j.kernel.GraphDatabaseAPI import org.neo4j.kernel.api._ -import org.neo4j.kernel.api.constraints.UniquenessConstraint +import org.neo4j.kernel.api.constraints.{MandatoryPropertyConstraint, UniquenessConstraint} import org.neo4j.kernel.api.exceptions.schema.{AlreadyConstrainedException, AlreadyIndexedException} import org.neo4j.kernel.api.index.{IndexDescriptor, InternalIndexState} import org.neo4j.kernel.configuration.Config @@ -297,22 +296,24 @@ final class TransactionBoundQueryContext(graph: GraphDatabaseAPI, statement.schemaWriteOperations().indexDrop(new IndexDescriptor(labelId, propertyKeyId)) def createUniqueConstraint(labelId: Int, propertyKeyId: Int): IdempotentResult[UniquenessConstraint] = try { - IdempotentResult(statement.schemaWriteOperations().uniquenessConstraintCreate(labelId, propertyKeyId)) + IdempotentResult(statement.schemaWriteOperations().uniquePropertyConstraintCreate(labelId, propertyKeyId)) } catch { - case _: AlreadyConstrainedException => - val readOperations: ReadOperations = statement.readOperations() - val uniquenessConstraints = readOperations.constraintsGetForLabelAndPropertyKey(labelId, propertyKeyId) - IdempotentResult(IteratorUtil.single(uniquenessConstraints), wasCreated = false) + case existing: AlreadyConstrainedException => + IdempotentResult(existing.constraint().asInstanceOf[UniquenessConstraint], wasCreated = false) } def dropUniqueConstraint(labelId: Int, propertyKeyId: Int) = statement.schemaWriteOperations().constraintDrop(new UniquenessConstraint(labelId, propertyKeyId)) - //TODO implement - def createMandatoryConstraint(labelId: Int, propertyKeyId: Int): IdempotentResult[UniquenessConstraint] = ??? + def createMandatoryConstraint(labelId: Int, propertyKeyId: Int): IdempotentResult[MandatoryPropertyConstraint] = try { + IdempotentResult(statement.schemaWriteOperations().mandatoryPropertyConstraintCreate(labelId, propertyKeyId)) + } catch { + case existing: AlreadyConstrainedException => + IdempotentResult(existing.constraint().asInstanceOf[MandatoryPropertyConstraint], wasCreated = false) + } - //TODO implement - def dropMandatoryConstraint(labelId: Int, propertyKeyId: Int) = ??? + def dropMandatoryConstraint(labelId: Int, propertyKeyId: Int) = + statement.schemaWriteOperations().constraintDrop(new MandatoryPropertyConstraint(labelId, propertyKeyId)) override def hasLocalFileAccess: Boolean = graph match { case db: GraphDatabaseAPI => db.getDependencyResolver.resolveDependency(classOf[Config]).get(GraphDatabaseSettings.allow_file_urls) diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/ExecutionResultTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/ExecutionResultTest.scala index 7c41ad18390b6..45dfa78dd8e6d 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/ExecutionResultTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/ExecutionResultTest.scala @@ -132,8 +132,7 @@ class ExecutionResultTest extends ExecutionEngineFunSuite { assert(stats.uniqueConstraintsRemoved === 0) } - //TODO unignore when implemented spi - ignore("correct statistics for mandatory constraint added ") { + test("correct statistics for mandatory constraint added") { val result = execute("create constraint on (n:Person) assert n.name is not null") val stats = result.queryStatistics() @@ -141,8 +140,7 @@ class ExecutionResultTest extends ExecutionEngineFunSuite { assert(stats.mandatoryConstraintsRemoved === 0) } - //TODO unignore when implemented spi - ignore("correct statistics for mandatory constraint added twice") { + test("correct statistics for mandatory constraint added twice") { execute("create constraint on (n:Person) assert n.name is not null") val result = execute("create constraint on (n:Person) assert n.name is not null") val stats = result.queryStatistics() @@ -151,25 +149,12 @@ class ExecutionResultTest extends ExecutionEngineFunSuite { assert(stats.mandatoryConstraintsRemoved === 0) } - //TODO unignore when implemented spi - ignore("correct statistics for mandatory constraint dropped") { - execute("create constraint on (n:Person) assert n.name is not null") - val result = execute("drop constraint on (n:Person) assert n.name is not null") - val stats = result.queryStatistics() - - assert(stats.mandatoryConstraintsAdded === 0) - assert(stats.mandatoryConstraintsRemoved === 1) - } - - //TODO unignore when implemented spi - ignore("correct statistics for mandatory constraint dropped twice") { - execute("create constraint on (n:Person) assert n.name is not null") - execute("drop constraint on (n:Person) assert n.name is not null") - val result = execute("drop constraint on (n:Person) assert n.name is not null") - val stats = result.queryStatistics() - - assert(stats.mandatoryConstraintsAdded === 0) - assert(stats.mandatoryConstraintsRemoved === 0) - } + test("correct statistics for mandatory constraint dropped") { + execute("create constraint on (n:Person) assert n.name is not null") + val result = execute("drop constraint on (n:Person) assert n.name is not null") + val stats = result.queryStatistics() + assert(stats.mandatoryConstraintsAdded === 0) + assert(stats.mandatoryConstraintsRemoved === 1) + } } diff --git a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v2_3/LabelActionTest.scala b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v2_3/LabelActionTest.scala index 32f9b97921fc7..13ce60c6cae52 100644 --- a/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v2_3/LabelActionTest.scala +++ b/community/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiler/v2_3/LabelActionTest.scala @@ -24,8 +24,8 @@ import org.neo4j.cypher.internal.compiler.v2_3.commands.expressions.Literal import org.neo4j.cypher.internal.compiler.v2_3.commands.values.{KeyToken, TokenType} import org.neo4j.cypher.internal.compiler.v2_3.commands.{LabelAction, LabelSetOp} import org.neo4j.cypher.internal.compiler.v2_3.spi.{IdempotentResult, LockingQueryContext, QueryContext} -import org.neo4j.graphdb.{Relationship, Direction, Node} -import org.neo4j.kernel.api.constraints.UniquenessConstraint +import org.neo4j.graphdb.{Direction, Node, Relationship} +import org.neo4j.kernel.api.constraints.{MandatoryPropertyConstraint, UniquenessConstraint} import org.neo4j.kernel.api.index.IndexDescriptor class LabelActionTest extends GraphDatabaseFunSuite { @@ -141,7 +141,7 @@ class SnitchingQueryContext extends QueryContext { def dropUniqueConstraint(labelId: Int, propertyKeyId: Int) {???} - def createMandatoryConstraint(labelId: Int, propertyKeyId: Int): IdempotentResult[UniquenessConstraint] = ??? + def createMandatoryConstraint(labelId: Int, propertyKeyId: Int): IdempotentResult[MandatoryPropertyConstraint] = ??? def dropMandatoryConstraint(labelId: Int, propertyKeyId: Int) {???} diff --git a/community/cypher/docs/cypher-docs/src/test/scala/org/neo4j/cypher/docgen/ConstraintsTest.scala b/community/cypher/docs/cypher-docs/src/test/scala/org/neo4j/cypher/docgen/ConstraintsTest.scala index e83343d80f78b..7e0ebde3910e6 100644 --- a/community/cypher/docs/cypher-docs/src/test/scala/org/neo4j/cypher/docgen/ConstraintsTest.scala +++ b/community/cypher/docs/cypher-docs/src/test/scala/org/neo4j/cypher/docgen/ConstraintsTest.scala @@ -21,7 +21,7 @@ package org.neo4j.cypher.docgen import org.junit.Test import org.neo4j.cypher.CypherExecutionException -import org.neo4j.kernel.api.constraints.UniquenessConstraint +import org.neo4j.kernel.api.constraints.PropertyConstraint import scala.collection.JavaConverters._ @@ -103,7 +103,7 @@ class ConstraintsTest extends DocumentingTestBase with SoftReset { assert(getConstraintIterator(labelName, propName).size === 1) } - private def getConstraintIterator(labelName: String, propName: String): Iterator[UniquenessConstraint] = { + private def getConstraintIterator(labelName: String, propName: String): Iterator[PropertyConstraint] = { val statement = db.statement val prop = statement.readOperations().propertyKeyGetForName(propName) diff --git a/community/kernel/src/main/java/org/neo4j/graphdb/schema/ConstraintCreator.java b/community/kernel/src/main/java/org/neo4j/graphdb/schema/ConstraintCreator.java index 19c7eac230d55..22f0e7d743a0f 100644 --- a/community/kernel/src/main/java/org/neo4j/graphdb/schema/ConstraintCreator.java +++ b/community/kernel/src/main/java/org/neo4j/graphdb/schema/ConstraintCreator.java @@ -46,6 +46,14 @@ public interface ConstraintCreator */ ConstraintCreator assertPropertyIsUnique( String propertyKey ); + /** + * Imposes an existence constraint for the given property, such that any node with the given label must have a + * value set for the given property key. + * + * @return a {@link ConstraintCreator} instance to be used for further interaction. + */ + ConstraintCreator assertPropertyExists( String propertyKey ); + /** * Creates a constraint with the details specified by the other methods in this interface. * diff --git a/community/kernel/src/main/java/org/neo4j/graphdb/schema/ConstraintType.java b/community/kernel/src/main/java/org/neo4j/graphdb/schema/ConstraintType.java index 6fac723c50c72..884fabb20e58b 100644 --- a/community/kernel/src/main/java/org/neo4j/graphdb/schema/ConstraintType.java +++ b/community/kernel/src/main/java/org/neo4j/graphdb/schema/ConstraintType.java @@ -26,5 +26,6 @@ public enum ConstraintType { UNIQUENESS, + MANDATORY, ; } \ No newline at end of file diff --git a/community/kernel/src/main/java/org/neo4j/graphdb/schema/Schema.java b/community/kernel/src/main/java/org/neo4j/graphdb/schema/Schema.java index df9341a30811b..c1f34fde08690 100644 --- a/community/kernel/src/main/java/org/neo4j/graphdb/schema/Schema.java +++ b/community/kernel/src/main/java/org/neo4j/graphdb/schema/Schema.java @@ -40,7 +40,7 @@ public interface Schema * population of an index, to tell when it is done populating and is online serving * requests. */ - public static enum IndexState + enum IndexState { ONLINE, POPULATING, diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/SchemaRead.java b/community/kernel/src/main/java/org/neo4j/kernel/api/SchemaRead.java index 1db6286eeae34..1ac9a3fd87260 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/SchemaRead.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/api/SchemaRead.java @@ -21,7 +21,7 @@ import java.util.Iterator; -import org.neo4j.kernel.api.constraints.UniquenessConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; import org.neo4j.kernel.api.exceptions.schema.SchemaRuleNotFoundException; import org.neo4j.kernel.api.index.IndexDescriptor; @@ -63,22 +63,22 @@ IndexDescriptor uniqueIndexGetForLabelAndPropertyKey( int labelId, int propertyK /** * Get all constraints applicable to label and propertyKey. There are only {@link - * org.neo4j.kernel.api.constraints.UniquenessConstraint} + * PropertyConstraint} * for the time being. */ - Iterator constraintsGetForLabelAndPropertyKey( int labelId, int propertyKeyId ); + Iterator constraintsGetForLabelAndPropertyKey( int labelId, int propertyKeyId ); /** - * Get all constraints applicable to label. There are only {@link UniquenessConstraint} + * Get all constraints applicable to label. There are only {@link PropertyConstraint} * for the time being. */ - Iterator constraintsGetForLabel( int labelId ); + Iterator constraintsGetForLabel( int labelId ); /** - * Get all constraints. There are only {@link UniquenessConstraint} + * Get all constraints. There are only {@link PropertyConstraint} * for the time being. */ - Iterator constraintsGetAll(); + Iterator constraintsGetAll(); /** * Get the owning constraint for a constraint index. Returns null if the index does not have an owning constraint. diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/SchemaWrite.java b/community/kernel/src/main/java/org/neo4j/kernel/api/SchemaWrite.java index 82a4bf5609401..cbfcc76ceeae2 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/SchemaWrite.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/api/SchemaWrite.java @@ -19,6 +19,8 @@ */ package org.neo4j.kernel.api; +import org.neo4j.kernel.api.constraints.MandatoryPropertyConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.exceptions.schema.AddIndexFailureException; import org.neo4j.kernel.api.exceptions.schema.AlreadyConstrainedException; @@ -40,10 +42,13 @@ IndexDescriptor indexCreate( int labelId, int propertyKeyId ) /** Drops a {@link IndexDescriptor} from the database */ void indexDrop( IndexDescriptor descriptor ) throws DropIndexFailureException; - UniquenessConstraint uniquenessConstraintCreate( int labelId, int propertyKeyId ) + UniquenessConstraint uniquePropertyConstraintCreate( int labelId, int propertyKeyId ) throws CreateConstraintFailureException, AlreadyConstrainedException, AlreadyIndexedException; - void constraintDrop( UniquenessConstraint constraint ) throws DropConstraintFailureException; + MandatoryPropertyConstraint mandatoryPropertyConstraintCreate( int labelId, int propertyKeyId ) + throws CreateConstraintFailureException, AlreadyConstrainedException; + + void constraintDrop( PropertyConstraint constraint ) throws DropConstraintFailureException; /** * This should not be used, it is exposed to allow an external job to clean up constraint indexes. diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/constraints/MandatoryPropertyConstraint.java b/community/kernel/src/main/java/org/neo4j/kernel/api/constraints/MandatoryPropertyConstraint.java new file mode 100644 index 0000000000000..3cd88c322e55d --- /dev/null +++ b/community/kernel/src/main/java/org/neo4j/kernel/api/constraints/MandatoryPropertyConstraint.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2002-2015 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.neo4j.kernel.api.constraints; + +import org.neo4j.graphdb.schema.ConstraintType; + +public class MandatoryPropertyConstraint extends PropertyConstraint +{ + public MandatoryPropertyConstraint( int labelId, int propertyKeyId ) + { + super( labelId, propertyKeyId ); + } + + @Override + public void added( ChangeVisitor visitor ) + { + visitor.visitAddedMandatoryPropertyConstraint( this ); + } + + @Override + public void removed( ChangeVisitor visitor ) + { + visitor.visitRemovedMandatoryPropertyConstraint( this ); + } + + @Override + String constraintString() + { + return "NOT NULL"; + } + + @Override + public ConstraintType type() + { + return ConstraintType.MANDATORY; + } +} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/constraints/PropertyConstraint.java b/community/kernel/src/main/java/org/neo4j/kernel/api/constraints/PropertyConstraint.java new file mode 100644 index 0000000000000..6f4217339d8f3 --- /dev/null +++ b/community/kernel/src/main/java/org/neo4j/kernel/api/constraints/PropertyConstraint.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2002-2015 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.kernel.api.constraints; + +import org.neo4j.graphdb.schema.ConstraintType; +import org.neo4j.kernel.api.TokenNameLookup; + +public abstract class PropertyConstraint +{ + public interface ChangeVisitor + { + void visitAddedUniquePropertyConstraint( UniquenessConstraint constraint ); + + void visitRemovedUniquePropertyConstraint( UniquenessConstraint constraint ); + + void visitAddedMandatoryPropertyConstraint( MandatoryPropertyConstraint constraint ); + + void visitRemovedMandatoryPropertyConstraint( MandatoryPropertyConstraint constraint ); + } + + private final int labelId; + private final int propertyKeyId; + + public PropertyConstraint( int labelId, int propertyKeyId ) + { + this.labelId = labelId; + this.propertyKeyId = propertyKeyId; + } + + public abstract void added( ChangeVisitor visitor ); + + public abstract void removed( ChangeVisitor visitor ); + + @Override + public boolean equals( Object obj ) + { + if ( this == obj ) + { + return true; + } + if ( obj != null && getClass() == obj.getClass() ) + { + PropertyConstraint that = (PropertyConstraint) obj; + return this.equals( type(), that.labelId, that.propertyKeyId ); + } + return false; + } + + @Override + public int hashCode() + { + int result = labelId; + result = 31 * result + propertyKeyId; + return result; + } + + public int label() + { + return labelId; + } + + public int propertyKeyId() + { + return propertyKeyId; + } + + public boolean equals( ConstraintType type, int labelId, int propertyKeyId ) + { + return this.labelId == labelId && this.propertyKeyId == propertyKeyId && type() == type; + } + + @Override + public String toString() + { + return String.format( "CONSTRAINT ON ( n:label[%s] ) ASSERT n.property[%s] IS %s", + labelId, propertyKeyId, constraintString() ); + } + + public String userDescription( TokenNameLookup tokenNameLookup ) + { + String labelName = tokenNameLookup.labelGetName( labelId ); + String boundIdentifier = labelName.toLowerCase(); + return String.format( "CONSTRAINT ON ( %s:%s ) ASSERT %s.%s IS %s", boundIdentifier, labelName, + boundIdentifier, tokenNameLookup.propertyKeyGetName( propertyKeyId ), constraintString() ); + } + + abstract String constraintString(); + + public abstract ConstraintType type(); +} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/constraints/UniquenessConstraint.java b/community/kernel/src/main/java/org/neo4j/kernel/api/constraints/UniquenessConstraint.java index d484bfcc85ad4..4fde8bc5255c8 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/constraints/UniquenessConstraint.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/api/constraints/UniquenessConstraint.java @@ -17,72 +17,39 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package org.neo4j.kernel.api.constraints; -import org.neo4j.kernel.api.TokenNameLookup; +import org.neo4j.graphdb.schema.ConstraintType; -// TODO: When we add other types of constraints, we will either want to create a hierarchy, or... -// TODO: ...rename this to "Constraint" and add a "type" enum (or something like that). -public class UniquenessConstraint +public class UniquenessConstraint extends PropertyConstraint { - private final int labelId; - private final int propertyKeyId; - public UniquenessConstraint( int labelId, int propertyKeyId ) { - this.labelId = labelId; - this.propertyKeyId = propertyKeyId; + super( labelId, propertyKeyId ); } @Override - public boolean equals( Object obj ) + public void added( ChangeVisitor visitor ) { - if ( this == obj ) - { - return true; - } - if ( obj != null && getClass() == obj.getClass() ) - { - UniquenessConstraint that = (UniquenessConstraint) obj; - return this.equals( that.labelId, that.propertyKeyId ); - } - return false; + visitor.visitAddedUniquePropertyConstraint( this ); } @Override - public int hashCode() - { - int result = labelId; - result = 31 * result + propertyKeyId; - return result; - } - - public int label() - { - return labelId; - } - - public int propertyKeyId() - { - return propertyKeyId; - } - - public boolean equals( int labelId, int propertyKeyId ) + public void removed( ChangeVisitor visitor ) { - return this.labelId == labelId && this.propertyKeyId == propertyKeyId; + visitor.visitRemovedUniquePropertyConstraint( this ); } @Override - public String toString() + String constraintString() { - return String.format( "CONSTRAINT ON ( n:label[%s] ) ASSERT n.property[%s] IS UNIQUE", labelId, propertyKeyId ); + return "UNIQUE"; } - public String userDescription( TokenNameLookup tokenNameLookup ) + @Override + public ConstraintType type() { - String labelName = tokenNameLookup.labelGetName( labelId ); - String boundIdentifier = labelName.toLowerCase(); - return String.format( "CONSTRAINT ON ( %s:%s ) ASSERT %s.%s IS UNIQUE", boundIdentifier, labelName, - boundIdentifier, tokenNameLookup.propertyKeyGetName( propertyKeyId ) ); + return ConstraintType.UNIQUENESS; } } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/schema/AlreadyConstrainedException.java b/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/schema/AlreadyConstrainedException.java index f17b601881a92..624b1d0976d59 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/schema/AlreadyConstrainedException.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/schema/AlreadyConstrainedException.java @@ -20,7 +20,7 @@ package org.neo4j.kernel.api.exceptions.schema; import org.neo4j.kernel.api.TokenNameLookup; -import org.neo4j.kernel.api.constraints.UniquenessConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.exceptions.Status; import static java.lang.String.format; @@ -33,17 +33,22 @@ public class AlreadyConstrainedException extends SchemaKernelException private static final String INDEX_CONTEXT_FORMAT = "Label '%s' and property '%s' have a unique constraint defined on them, so an index is " + "already created that matches this."; - private final UniquenessConstraint constraint; + private final PropertyConstraint constraint; private final OperationContext context; - public AlreadyConstrainedException( UniquenessConstraint constraint, OperationContext context ) + public AlreadyConstrainedException( PropertyConstraint constraint, OperationContext context ) { super( Status.Schema.ConstraintAlreadyExists, constructUserMessage( context, null, constraint ) ); this.constraint = constraint; this.context = context; } - private static String constructUserMessage( OperationContext context, TokenNameLookup tokenNameLookup, UniquenessConstraint constraint ) + public PropertyConstraint constraint() + { + return constraint; + } + + private static String constructUserMessage( OperationContext context, TokenNameLookup tokenNameLookup, PropertyConstraint constraint ) { switch ( context ) { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/schema/ConstraintVerificationFailedKernelException.java b/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/schema/ConstraintVerificationFailedKernelException.java index d160a809e40d2..352b59e49a763 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/schema/ConstraintVerificationFailedKernelException.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/schema/ConstraintVerificationFailedKernelException.java @@ -23,7 +23,7 @@ import java.util.Set; import org.neo4j.kernel.api.TokenNameLookup; -import org.neo4j.kernel.api.constraints.UniquenessConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.exceptions.KernelException; import org.neo4j.kernel.api.exceptions.Status; import org.neo4j.kernel.api.index.IndexEntryConflictException; @@ -36,7 +36,7 @@ */ public class ConstraintVerificationFailedKernelException extends KernelException { - private final UniquenessConstraint constraint; + private final PropertyConstraint constraint; public static final class Evidence { @@ -71,14 +71,14 @@ public String toString() private final Set evidence; - public ConstraintVerificationFailedKernelException( UniquenessConstraint constraint, Set evidence ) + public ConstraintVerificationFailedKernelException( PropertyConstraint constraint, Set evidence ) { super( Status.Schema.ConstraintVerificationFailure, "Existing data does not satisfy %s.", constraint ); this.constraint = constraint; this.evidence = evidence; } - public ConstraintVerificationFailedKernelException( UniquenessConstraint constraint, Throwable failure ) + public ConstraintVerificationFailedKernelException( PropertyConstraint constraint, Throwable failure ) { super( Status.Schema.ConstraintVerificationFailure, failure, "Failed to verify constraint %s: %s", constraint, failure.getMessage() ); diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/schema/CreateConstraintFailureException.java b/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/schema/CreateConstraintFailureException.java index 6bcea1e3ffcdf..88f89ef01dc13 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/schema/CreateConstraintFailureException.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/schema/CreateConstraintFailureException.java @@ -19,23 +19,23 @@ */ package org.neo4j.kernel.api.exceptions.schema; -import org.neo4j.kernel.api.constraints.UniquenessConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.exceptions.KernelException; import org.neo4j.kernel.api.TokenNameLookup; import org.neo4j.kernel.api.exceptions.Status; public class CreateConstraintFailureException extends SchemaKernelException { - private final UniquenessConstraint constraint; + private final PropertyConstraint constraint; - public CreateConstraintFailureException( UniquenessConstraint constraint, Throwable cause ) + public CreateConstraintFailureException( PropertyConstraint constraint, Throwable cause ) { super( Status.Schema.ConstraintCreationFailure, cause, "Unable to create constraint %s: %s", constraint, cause.getMessage() ); this.constraint = constraint; } - public UniquenessConstraint constraint() + public PropertyConstraint constraint() { return constraint; } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/schema/DropConstraintFailureException.java b/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/schema/DropConstraintFailureException.java index 349b26c3d29aa..d725e94a7ef77 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/schema/DropConstraintFailureException.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/schema/DropConstraintFailureException.java @@ -20,21 +20,21 @@ package org.neo4j.kernel.api.exceptions.schema; import org.neo4j.kernel.api.TokenNameLookup; -import org.neo4j.kernel.api.constraints.UniquenessConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.exceptions.KernelException; import org.neo4j.kernel.api.exceptions.Status; public class DropConstraintFailureException extends SchemaKernelException { - private final UniquenessConstraint constraint; + private final PropertyConstraint constraint; - public DropConstraintFailureException( UniquenessConstraint constraint, Throwable cause ) + public DropConstraintFailureException( PropertyConstraint constraint, Throwable cause ) { super( Status.Schema.ConstraintDropFailure, cause, "Unable to drop constraint %s: %s", constraint, cause.getMessage() ); this.constraint = constraint; } - public UniquenessConstraint constraint() + public PropertyConstraint constraint() { return constraint; } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/schema/NoSuchConstraintException.java b/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/schema/NoSuchConstraintException.java index 493bab9e490e0..df3098ae961a5 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/schema/NoSuchConstraintException.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/api/exceptions/schema/NoSuchConstraintException.java @@ -20,17 +20,17 @@ package org.neo4j.kernel.api.exceptions.schema; import org.neo4j.kernel.api.TokenNameLookup; -import org.neo4j.kernel.api.constraints.UniquenessConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.exceptions.Status; import static java.lang.String.format; public class NoSuchConstraintException extends SchemaKernelException { - private final UniquenessConstraint constraint; + private final PropertyConstraint constraint; private final static String message = "No such constraint %s."; - public NoSuchConstraintException( UniquenessConstraint constraint ) + public NoSuchConstraintException( PropertyConstraint constraint ) { super( Status.Schema.NoSuchConstraint, format( message, constraint ) ); this.constraint = constraint; diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/txstate/ReadableTxState.java b/community/kernel/src/main/java/org/neo4j/kernel/api/txstate/ReadableTxState.java index 17671cb6b9cac..b986386fd3069 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/txstate/ReadableTxState.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/api/txstate/ReadableTxState.java @@ -24,6 +24,7 @@ import org.neo4j.collection.primitive.PrimitiveIntIterator; import org.neo4j.collection.primitive.PrimitiveLongIterator; import org.neo4j.graphdb.Direction; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.cursor.LabelCursor; import org.neo4j.kernel.api.cursor.NodeCursor; @@ -142,11 +143,11 @@ RelationshipIterator augmentRelationships( long nodeId, Direction direction, int Iterable constraintIndexesCreatedInTx(); - ReadableDiffSets constraintsChanges(); + ReadableDiffSets constraintsChanges(); - ReadableDiffSets constraintsChangesForLabel( int labelId ); + ReadableDiffSets constraintsChangesForLabel( int labelId ); - ReadableDiffSets constraintsChangesForLabelAndProperty( int labelId, int propertyKey ); + ReadableDiffSets constraintsChangesForLabelAndProperty( int labelId, int propertyKey ); Long indexCreatedForConstraint( UniquenessConstraint constraint ); diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/txstate/TransactionState.java b/community/kernel/src/main/java/org/neo4j/kernel/api/txstate/TransactionState.java index 9a5a015e8ad91..c03967dcdd362 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/txstate/TransactionState.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/api/txstate/TransactionState.java @@ -21,6 +21,8 @@ import java.util.Map; +import org.neo4j.kernel.api.constraints.MandatoryPropertyConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.index.IndexDescriptor; import org.neo4j.kernel.api.properties.DefinedProperty; @@ -85,9 +87,11 @@ void relationshipDoReplaceProperty( long relationshipId, void constraintDoAdd( UniquenessConstraint constraint, long indexId ); - void constraintDoDrop( UniquenessConstraint constraint ); + void constraintDoAdd( MandatoryPropertyConstraint constraint ); - boolean constraintDoUnRemove( UniquenessConstraint constraint ); + void constraintDoDrop( PropertyConstraint constraint ); + + boolean constraintDoUnRemove( PropertyConstraint constraint ); boolean constraintIndexDoUnRemove( IndexDescriptor index ); diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/txstate/TxStateVisitor.java b/community/kernel/src/main/java/org/neo4j/kernel/api/txstate/TxStateVisitor.java index ceb38093e7d6d..0884862a1a050 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/txstate/TxStateVisitor.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/api/txstate/TxStateVisitor.java @@ -23,6 +23,7 @@ import java.util.Map; import java.util.Set; +import org.neo4j.kernel.api.constraints.MandatoryPropertyConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.index.IndexDescriptor; import org.neo4j.kernel.api.properties.DefinedProperty; @@ -59,9 +60,13 @@ void visitGraphPropertyChanges( Iterator added, Iterator constraints = schemaReadOperations.constraintsGetForLabel( state, labelId ); + Iterator constraints = uniquePropertyConstraints( schemaReadOperations.constraintsGetForLabel( state, labelId ) ); while ( constraints.hasNext() ) { - UniquenessConstraint constraint = constraints.next(); + PropertyConstraint constraint = constraints.next(); int propertyKeyId = constraint.propertyKeyId(); Property property = entityReadOperations.nodeGetProperty( state, nodeId, propertyKeyId ); if ( property.isDefined() ) @@ -90,8 +93,8 @@ public Property nodeSetProperty( KernelStatement state, long nodeId, DefinedProp { int labelId = labelIds.next(); int propertyKeyId = property.propertyKeyId(); - Iterator constraintIterator = - schemaReadOperations.constraintsGetForLabelAndPropertyKey( state, labelId, propertyKeyId ); + Iterator constraintIterator = + uniquePropertyConstraints( schemaReadOperations.constraintsGetForLabelAndPropertyKey( state, labelId, propertyKeyId ) ); if ( constraintIterator.hasNext() ) { validateNoExistingNodeWithLabelAndProperty( state, labelId, property, nodeId ); @@ -136,6 +139,17 @@ private void assertIndexOnline( KernelStatement state, IndexDescriptor indexDesc throw new IndexBrokenKernelException( schemaReadOperations.indexGetFailure( state, indexDescriptor ) ); } } + private Iterator uniquePropertyConstraints( Iterator propertyConstraintIterator) + { + return new FilteringIterator<>( propertyConstraintIterator, new Predicate() + { + @Override + public boolean test( PropertyConstraint constraint ) + { + return constraint instanceof UniquenessConstraint; + } + } ); + } // Simply delegate the rest of the invocations diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/DataIntegrityValidatingStatementOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/DataIntegrityValidatingStatementOperations.java index 91ae37cc36371..c26e7e5f18d4f 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/DataIntegrityValidatingStatementOperations.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/DataIntegrityValidatingStatementOperations.java @@ -22,6 +22,8 @@ import java.util.Iterator; import org.neo4j.kernel.api.Statement; +import org.neo4j.kernel.api.constraints.MandatoryPropertyConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.exceptions.schema.AddIndexFailureException; import org.neo4j.kernel.api.exceptions.schema.AlreadyConstrainedException; @@ -132,24 +134,46 @@ public void uniqueIndexDrop( KernelStatement state, IndexDescriptor descriptor ) } @Override - public UniquenessConstraint uniquenessConstraintCreate( KernelStatement state, int labelId, int propertyKey ) + public UniquenessConstraint uniquePropertyConstraintCreate( KernelStatement state, int labelId, int propertyKey ) throws AlreadyConstrainedException, CreateConstraintFailureException, AlreadyIndexedException { - Iterator constraints = schemaReadDelegate.constraintsGetForLabelAndPropertyKey( + Iterator constraints = schemaReadDelegate.constraintsGetForLabelAndPropertyKey( state, labelId, propertyKey ); - if ( constraints.hasNext() ) + while ( constraints.hasNext() ) { - throw new AlreadyConstrainedException( constraints.next(), OperationContext.CONSTRAINT_CREATION ); + PropertyConstraint constraint = constraints.next(); + if ( constraint instanceof UniquenessConstraint ) + { + throw new AlreadyConstrainedException( constraint, OperationContext.CONSTRAINT_CREATION ); + } } // It is not allowed to create uniqueness constraints on indexed label/property pairs checkIndexExistence( state, OperationContext.CONSTRAINT_CREATION, labelId, propertyKey ); - return schemaWriteDelegate.uniquenessConstraintCreate( state, labelId, propertyKey ); + return schemaWriteDelegate.uniquePropertyConstraintCreate( state, labelId, propertyKey ); + } + + @Override + public MandatoryPropertyConstraint mandatoryPropertyConstraintCreate( KernelStatement state, int labelId, + int propertyKey ) throws AlreadyConstrainedException, CreateConstraintFailureException + { + Iterator constraints = schemaReadDelegate.constraintsGetForLabelAndPropertyKey( + state, labelId, propertyKey ); + while ( constraints.hasNext() ) + { + PropertyConstraint constraint = constraints.next(); + if ( constraint instanceof MandatoryPropertyConstraint ) + { + throw new AlreadyConstrainedException( constraint, OperationContext.CONSTRAINT_CREATION ); + } + } + + return schemaWriteDelegate.mandatoryPropertyConstraintCreate( state, labelId, propertyKey ); } @Override - public void constraintDrop( KernelStatement state, UniquenessConstraint constraint ) throws DropConstraintFailureException + public void constraintDrop( KernelStatement state, PropertyConstraint constraint ) throws DropConstraintFailureException { try { @@ -219,12 +243,12 @@ private void assertIndexExists( IndexDescriptor descriptor, Iterator constraints ) + private void assertConstraintExists( PropertyConstraint constraint, Iterator constraints ) throws NoSuchConstraintException { - for ( UniquenessConstraint existing : loop( constraints ) ) + for ( PropertyConstraint existing : loop( constraints ) ) { - if ( existing.equals( constraint.label(), constraint.propertyKeyId() ) ) + if ( existing.equals( constraint.type(), constraint.label(), constraint.propertyKeyId() ) ) { return; } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelTransactionImplementation.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelTransactionImplementation.java index ef873678d3f64..c0bac30391d68 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelTransactionImplementation.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelTransactionImplementation.java @@ -31,6 +31,7 @@ import org.neo4j.helpers.ThisShouldNotHappenError; import org.neo4j.kernel.api.KernelTransaction; import org.neo4j.kernel.api.Statement; +import org.neo4j.kernel.api.constraints.MandatoryPropertyConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.exceptions.EntityNotFoundException; import org.neo4j.kernel.api.exceptions.InvalidTransactionTypeKernelException; @@ -55,9 +56,10 @@ import org.neo4j.kernel.impl.index.IndexEntityType; import org.neo4j.kernel.impl.locking.LockGroup; import org.neo4j.kernel.impl.locking.Locks; +import org.neo4j.kernel.impl.store.MandatoryPropertyConstraintRule; import org.neo4j.kernel.impl.store.NeoStore; import org.neo4j.kernel.impl.store.SchemaStorage; -import org.neo4j.kernel.impl.store.UniquenessConstraintRule; +import org.neo4j.kernel.impl.store.UniquePropertyConstraintRule; import org.neo4j.kernel.impl.store.record.IndexRule; import org.neo4j.kernel.impl.transaction.TransactionHeaderInformationFactory; import org.neo4j.kernel.impl.transaction.TransactionMonitor; @@ -834,7 +836,7 @@ public void visitRemovedIndex( IndexDescriptor element, boolean isConstraintInde } @Override - public void visitAddedConstraint( UniquenessConstraint element ) + public void visitAddedUniquePropertyConstraint( UniquenessConstraint element ) { clearState = true; long constraintId = schemaStorage.newRuleId(); @@ -842,18 +844,18 @@ public void visitAddedConstraint( UniquenessConstraint element ) element.label(), element.propertyKeyId(), SchemaStorage.IndexRuleKind.CONSTRAINT ); - recordState.createSchemaRule( UniquenessConstraintRule.uniquenessConstraintRule( + recordState.createSchemaRule( UniquePropertyConstraintRule.uniquenessConstraintRule( constraintId, element.label(), element.propertyKeyId(), indexRule.getId() ) ); recordState.setConstraintIndexOwner( indexRule, constraintId ); } @Override - public void visitRemovedConstraint( UniquenessConstraint element ) + public void visitRemovedUniquePropertyConstraint( UniquenessConstraint element ) { try { clearState = true; - UniquenessConstraintRule rule = schemaStorage + UniquePropertyConstraintRule rule = schemaStorage .uniquenessConstraint( element.label(), element.propertyKeyId() ); recordState.dropSchemaRule( rule ); } @@ -868,6 +870,32 @@ public void visitRemovedConstraint( UniquenessConstraint element ) visitRemovedIndex( new IndexDescriptor( element.label(), element.propertyKeyId() ), true ); } + @Override + public void visitAddedMandatoryPropertyConstraint( MandatoryPropertyConstraint element ) + { + clearState = true; + recordState.createSchemaRule( MandatoryPropertyConstraintRule.mandatoryPropertyConstraintRule( + schemaStorage.newRuleId(), element.label(), element.propertyKeyId() ) ); + } + + @Override + public void visitRemovedMandatoryPropertyConstraint( MandatoryPropertyConstraint element ) + { + try + { + clearState = true; + recordState.dropSchemaRule( + schemaStorage.mandatoryPropertyConstraint( element.label(), element.propertyKeyId() ) ); + } + catch ( SchemaRuleNotFoundException e ) + { + throw new ThisShouldNotHappenError( + "Tobias Lindaaker", + "Constraint to be removed should exist, since its existence should " + + "have been validated earlier and the schema should have been locked." ); + } + } + @Override public void visitCreatedLabelToken( String name, int id ) { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/LockingStatementOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/LockingStatementOperations.java index 781da14d58035..6db003915f7ec 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/LockingStatementOperations.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/LockingStatementOperations.java @@ -23,6 +23,8 @@ import org.neo4j.function.Function; import org.neo4j.kernel.api.Statement; +import org.neo4j.kernel.api.constraints.MandatoryPropertyConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.exceptions.EntityNotFoundException; import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; @@ -274,36 +276,44 @@ public void visit( long relId, int type, long startNode, long endNode ) } @Override - public UniquenessConstraint uniquenessConstraintCreate( KernelStatement state, int labelId, int propertyKeyId ) + public UniquenessConstraint uniquePropertyConstraintCreate( KernelStatement state, int labelId, int propertyKeyId ) throws CreateConstraintFailureException, AlreadyConstrainedException, AlreadyIndexedException { state.locks().acquireExclusive( ResourceTypes.SCHEMA, schemaResource() ); - return schemaWriteDelegate.uniquenessConstraintCreate( state, labelId, propertyKeyId ); + return schemaWriteDelegate.uniquePropertyConstraintCreate( state, labelId, propertyKeyId ); } @Override - public Iterator constraintsGetForLabelAndPropertyKey( KernelStatement state, int labelId, int propertyKeyId ) + public MandatoryPropertyConstraint mandatoryPropertyConstraintCreate( KernelStatement state, int labelId, + int propertyKeyId ) throws AlreadyConstrainedException, CreateConstraintFailureException + { + state.locks().acquireExclusive( ResourceTypes.SCHEMA, schemaResource() ); + return schemaWriteDelegate.mandatoryPropertyConstraintCreate( state, labelId, propertyKeyId ); + } + + @Override + public Iterator constraintsGetForLabelAndPropertyKey( KernelStatement state, int labelId, int propertyKeyId ) { state.locks().acquireShared( ResourceTypes.SCHEMA, schemaResource() ); return schemaReadDelegate.constraintsGetForLabelAndPropertyKey( state, labelId, propertyKeyId ); } @Override - public Iterator constraintsGetForLabel( KernelStatement state, int labelId ) + public Iterator constraintsGetForLabel( KernelStatement state, int labelId ) { state.locks().acquireShared( ResourceTypes.SCHEMA, schemaResource() ); return schemaReadDelegate.constraintsGetForLabel( state, labelId ); } @Override - public Iterator constraintsGetAll( KernelStatement state ) + public Iterator constraintsGetAll( KernelStatement state ) { state.locks().acquireShared( ResourceTypes.SCHEMA, schemaResource() ); return schemaReadDelegate.constraintsGetAll( state ); } @Override - public void constraintDrop( KernelStatement state, UniquenessConstraint constraint ) + public void constraintDrop( KernelStatement state, PropertyConstraint constraint ) throws DropConstraintFailureException { state.locks().acquireExclusive( ResourceTypes.SCHEMA, schemaResource() ); diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/OperationsFacade.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/OperationsFacade.java index ff6887f6f734a..51d474c5cc777 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/OperationsFacade.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/OperationsFacade.java @@ -32,6 +32,8 @@ import org.neo4j.kernel.api.ReadOperations; import org.neo4j.kernel.api.SchemaWriteOperations; import org.neo4j.kernel.api.StatementConstants; +import org.neo4j.kernel.api.constraints.MandatoryPropertyConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.cursor.NodeCursor; import org.neo4j.kernel.api.cursor.RelationshipCursor; @@ -518,21 +520,21 @@ public String indexGetFailure( IndexDescriptor descriptor ) throws IndexNotFound } @Override - public Iterator constraintsGetForLabelAndPropertyKey( int labelId, int propertyKeyId ) + public Iterator constraintsGetForLabelAndPropertyKey( int labelId, int propertyKeyId ) { statement.assertOpen(); return schemaRead().constraintsGetForLabelAndPropertyKey( statement, labelId, propertyKeyId ); } @Override - public Iterator constraintsGetForLabel( int labelId ) + public Iterator constraintsGetForLabel( int labelId ) { statement.assertOpen(); return schemaRead().constraintsGetForLabel( statement, labelId ); } @Override - public Iterator constraintsGetAll() + public Iterator constraintsGetAll() { statement.assertOpen(); return schemaRead().constraintsGetAll( statement ); @@ -772,15 +774,23 @@ public void indexDrop( IndexDescriptor descriptor ) throws DropIndexFailureExcep } @Override - public UniquenessConstraint uniquenessConstraintCreate( int labelId, int propertyKeyId ) + public UniquenessConstraint uniquePropertyConstraintCreate( int labelId, int propertyKeyId ) throws CreateConstraintFailureException, AlreadyConstrainedException, AlreadyIndexedException { statement.assertOpen(); - return schemaWrite().uniquenessConstraintCreate( statement, labelId, propertyKeyId ); + return schemaWrite().uniquePropertyConstraintCreate( statement, labelId, propertyKeyId ); } @Override - public void constraintDrop( UniquenessConstraint constraint ) throws DropConstraintFailureException + public MandatoryPropertyConstraint mandatoryPropertyConstraintCreate( int labelId, int propertyKeyId ) + throws CreateConstraintFailureException, AlreadyConstrainedException + { + statement.assertOpen(); + return schemaWrite().mandatoryPropertyConstraintCreate( statement, labelId, propertyKeyId ); + } + + @Override + public void constraintDrop( PropertyConstraint constraint ) throws DropConstraintFailureException { statement.assertOpen(); schemaWrite().constraintDrop( statement, constraint ); diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/StateHandlingStatementOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/StateHandlingStatementOperations.java index e64e6484c4540..80befeeb8d53f 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/StateHandlingStatementOperations.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/StateHandlingStatementOperations.java @@ -30,10 +30,13 @@ import org.neo4j.collection.primitive.PrimitiveLongIterator; import org.neo4j.function.Predicate; import org.neo4j.graphdb.Direction; +import org.neo4j.graphdb.schema.ConstraintType; import org.neo4j.kernel.api.EntityType; import org.neo4j.kernel.api.LegacyIndex; import org.neo4j.kernel.api.LegacyIndexHits; import org.neo4j.kernel.api.Statement; +import org.neo4j.kernel.api.constraints.MandatoryPropertyConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.cursor.LabelCursor; import org.neo4j.kernel.api.cursor.NodeCursor; @@ -389,6 +392,7 @@ public PrimitiveLongIterator nodesGetAll( KernelStatement state ) } @Override + public RelationshipIterator relationshipsGetAll( KernelStatement state ) { return state.txState().augmentRelationshipsGetAll( storeLayer.relationshipsGetAll() ); @@ -465,7 +469,7 @@ public void uniqueIndexDrop( KernelStatement state, IndexDescriptor descriptor ) } @Override - public UniquenessConstraint uniquenessConstraintCreate( KernelStatement state, int labelId, int propertyKeyId ) + public UniquenessConstraint uniquePropertyConstraintCreate( KernelStatement state, int labelId, int propertyKeyId ) throws CreateConstraintFailureException { UniquenessConstraint constraint = new UniquenessConstraint( labelId, propertyKeyId ); @@ -482,10 +486,10 @@ public UniquenessConstraint uniquenessConstraintCreate( KernelStatement state, i } else // *CREATE* { // create from scratch - for ( Iterator it = storeLayer.constraintsGetForLabelAndPropertyKey( + for ( Iterator it = storeLayer.constraintsGetForLabelAndPropertyKey( labelId, propertyKeyId ); it.hasNext(); ) { - if ( it.next().equals( labelId, propertyKeyId ) ) + if ( it.next().equals( ConstraintType.UNIQUENESS, labelId, propertyKeyId ) ) { return constraint; } @@ -504,7 +508,17 @@ public UniquenessConstraint uniquenessConstraintCreate( KernelStatement state, i } @Override - public Iterator constraintsGetForLabelAndPropertyKey( KernelStatement state, + public MandatoryPropertyConstraint mandatoryPropertyConstraintCreate( KernelStatement state, int labelId, + int propertyKeyId ) throws CreateConstraintFailureException + { + MandatoryPropertyConstraint constraint = new MandatoryPropertyConstraint( labelId, propertyKeyId ); + state.txState().constraintDoAdd( constraint ); + // TODO: validate constraint for existing data + return constraint; + } + + @Override + public Iterator constraintsGetForLabelAndPropertyKey( KernelStatement state, int labelId, int propertyKeyId ) { return applyConstraintsDiff( state, storeLayer.constraintsGetForLabelAndPropertyKey( @@ -512,20 +526,21 @@ public Iterator constraintsGetForLabelAndPropertyKey( Kern } @Override - public Iterator constraintsGetForLabel( KernelStatement state, int labelId ) + public Iterator constraintsGetForLabel( KernelStatement state, int labelId ) { return applyConstraintsDiff( state, storeLayer.constraintsGetForLabel( labelId ), labelId ); } @Override - public Iterator constraintsGetAll( KernelStatement state ) + public Iterator constraintsGetAll( KernelStatement state ) { return applyConstraintsDiff( state, storeLayer.constraintsGetAll() ); } - private Iterator applyConstraintsDiff( KernelStatement state, - Iterator constraints, - int labelId, int propertyKeyId ) + + private Iterator applyConstraintsDiff( KernelStatement state, + Iterator constraints, + int labelId, int propertyKeyId ) { if ( state.hasTxStateWithChanges() ) { @@ -534,9 +549,9 @@ private Iterator applyConstraintsDiff( KernelStatement sta return constraints; } - private Iterator applyConstraintsDiff( KernelStatement state, - Iterator constraints, - int labelId ) + private Iterator applyConstraintsDiff( KernelStatement state, + Iterator constraints, + int labelId ) { if ( state.hasTxStateWithChanges() ) { @@ -545,8 +560,9 @@ private Iterator applyConstraintsDiff( KernelStatement sta return constraints; } - private Iterator applyConstraintsDiff( KernelStatement state, - Iterator constraints ) + + private Iterator applyConstraintsDiff( KernelStatement state, + Iterator constraints ) { if ( state.hasTxStateWithChanges() ) { @@ -556,7 +572,7 @@ private Iterator applyConstraintsDiff( KernelStatement sta } @Override - public void constraintDrop( KernelStatement state, UniquenessConstraint constraint ) + public void constraintDrop( KernelStatement state, PropertyConstraint constraint ) { state.txState().constraintDoDrop( constraint ); } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/SchemaReadOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/SchemaReadOperations.java index 63ce76c2dcf4b..fc967412bdd22 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/SchemaReadOperations.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/SchemaReadOperations.java @@ -22,7 +22,7 @@ import java.util.Iterator; import org.neo4j.kernel.api.Statement; -import org.neo4j.kernel.api.constraints.UniquenessConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; import org.neo4j.kernel.api.exceptions.schema.SchemaRuleNotFoundException; import org.neo4j.kernel.api.index.IndexDescriptor; @@ -78,22 +78,22 @@ public interface SchemaReadOperations String indexGetFailure( Statement state, IndexDescriptor descriptor ) throws IndexNotFoundKernelException; /** - * Get all constraints applicable to label and propertyKey. There are only {@link UniquenessConstraint} + * Get all constraints applicable to label and propertyKey. There are only {@link PropertyConstraint} * for the time being. */ - Iterator constraintsGetForLabelAndPropertyKey( KernelStatement state, int labelId, int propertyKeyId ); + Iterator constraintsGetForLabelAndPropertyKey( KernelStatement state, int labelId, int propertyKeyId ); /** - * Get all constraints applicable to label. There are only {@link UniquenessConstraint} + * Get all constraints applicable to label. There are only {@link PropertyConstraint} * for the time being. */ - Iterator constraintsGetForLabel( KernelStatement state, int labelId ); + Iterator constraintsGetForLabel( KernelStatement state, int labelId ); /** - * Get all constraints. There are only {@link UniquenessConstraint} + * Get all constraints. There are only {@link PropertyConstraint} * for the time being. */ - Iterator constraintsGetAll( KernelStatement state ); + Iterator constraintsGetAll( KernelStatement state ); /** * Get the owning constraint for a constraint index. Returns null if the index does not have an owning constraint. diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/SchemaWriteOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/SchemaWriteOperations.java index c486fbd18eb97..f6b83bd1725e8 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/SchemaWriteOperations.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/SchemaWriteOperations.java @@ -19,7 +19,8 @@ */ package org.neo4j.kernel.impl.api.operations; -import org.neo4j.kernel.impl.api.KernelStatement; +import org.neo4j.kernel.api.constraints.MandatoryPropertyConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.exceptions.schema.AddIndexFailureException; import org.neo4j.kernel.api.exceptions.schema.AlreadyConstrainedException; @@ -28,6 +29,7 @@ import org.neo4j.kernel.api.exceptions.schema.DropConstraintFailureException; import org.neo4j.kernel.api.exceptions.schema.DropIndexFailureException; import org.neo4j.kernel.api.index.IndexDescriptor; +import org.neo4j.kernel.impl.api.KernelStatement; public interface SchemaWriteOperations { @@ -47,8 +49,11 @@ IndexDescriptor indexCreate( KernelStatement state, int labelId, int propertyKey */ void uniqueIndexDrop( KernelStatement state, IndexDescriptor descriptor ) throws DropIndexFailureException; - UniquenessConstraint uniquenessConstraintCreate( KernelStatement state, int labelId, int propertyKeyId ) + UniquenessConstraint uniquePropertyConstraintCreate( KernelStatement state, int labelId, int propertyKeyId ) throws AlreadyConstrainedException, CreateConstraintFailureException, AlreadyIndexedException; - void constraintDrop( KernelStatement state, UniquenessConstraint constraint ) throws DropConstraintFailureException; + MandatoryPropertyConstraint mandatoryPropertyConstraintCreate( KernelStatement statement, int labelId, int propertyKeyId ) + throws AlreadyConstrainedException, CreateConstraintFailureException; + + void constraintDrop( KernelStatement state, PropertyConstraint constraint ) throws DropConstraintFailureException; } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/ConstraintIndexCreator.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/ConstraintIndexCreator.java index 43adc280dd42a..c7d256fc5b349 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/ConstraintIndexCreator.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/ConstraintIndexCreator.java @@ -23,6 +23,7 @@ import org.neo4j.kernel.api.KernelAPI; import org.neo4j.kernel.api.KernelTransaction; import org.neo4j.kernel.api.Statement; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.exceptions.TransactionFailureException; import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; @@ -60,7 +61,7 @@ public long createUniquenessConstraintIndex( KernelStatement state, SchemaReadOp CreateConstraintFailureException, DropIndexFailureException { IndexDescriptor descriptor = createConstraintIndex( labelId, propertyKeyId ); - UniquenessConstraint constraint = new UniquenessConstraint( labelId, propertyKeyId ); + PropertyConstraint constraint = new UniquenessConstraint( labelId, propertyKeyId ); boolean success = false; try @@ -109,7 +110,7 @@ public void dropUniquenessConstraintIndex( IndexDescriptor descriptor ) } } - private void awaitIndexPopulation( UniquenessConstraint constraint, long indexId ) + private void awaitIndexPopulation( PropertyConstraint constraint, long indexId ) throws InterruptedException, ConstraintVerificationFailedKernelException { try diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/LabelState.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/LabelState.java index 77089609b427a..90caac911b6a4 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/LabelState.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/LabelState.java @@ -19,7 +19,7 @@ */ package org.neo4j.kernel.impl.api.state; -import org.neo4j.kernel.api.constraints.UniquenessConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.index.IndexDescriptor; import org.neo4j.kernel.impl.util.diffsets.DiffSets; import org.neo4j.kernel.impl.util.diffsets.ReadableDiffSets; @@ -45,14 +45,14 @@ public abstract class LabelState public abstract ReadableDiffSets constraintIndexChanges(); - public abstract ReadableDiffSets constraintsChanges(); + public abstract ReadableDiffSets constraintsChanges(); public static class Mutable extends LabelState { private DiffSets nodeDiffSets; private DiffSets indexChanges; private DiffSets constraintIndexChanges; - private DiffSets constraintsChanges; + private DiffSets constraintsChanges; private final int labelId; private Mutable( int labelId ) @@ -111,12 +111,12 @@ public DiffSets getOrCreateConstraintIndexChanges() } @Override - public ReadableDiffSets constraintsChanges() + public ReadableDiffSets constraintsChanges() { return ReadableDiffSets.Empty.ifNull( constraintsChanges ); } - public DiffSets getOrCreateConstraintsChanges() + public DiffSets getOrCreateConstraintsChanges() { if ( constraintsChanges == null ) { @@ -162,7 +162,7 @@ public ReadableDiffSets constraintIndexChanges() } @Override - public ReadableDiffSets constraintsChanges() + public ReadableDiffSets constraintsChanges() { return ReadableDiffSets.Empty.instance(); } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/TxState.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/TxState.java index 40ebdd04d0c2a..858ab4a7e48ba 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/TxState.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/TxState.java @@ -34,6 +34,8 @@ import org.neo4j.function.Predicate; import org.neo4j.graphdb.Direction; import org.neo4j.helpers.collection.Iterables; +import org.neo4j.kernel.api.constraints.MandatoryPropertyConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.cursor.LabelCursor; import org.neo4j.kernel.api.cursor.NodeCursor; @@ -131,7 +133,7 @@ void setMap( TxState state, Map map ) private GraphState graphState; private DiffSets indexChanges; private DiffSets constraintIndexChanges; - private DiffSets constraintsChanges; + private DiffSets constraintsChanges; private PropertyChanges propertyChangesForNodes; @@ -359,22 +361,55 @@ protected void visitAddedRelationship( long relationshipId, int type, long start }; } - private static DiffSetsVisitor constraintsVisitor( final TxStateVisitor visitor ) + private static DiffSetsVisitor constraintsVisitor( final TxStateVisitor visitor ) { - return new DiffSetsVisitor() + return new ConstraintDiffSetsVisitor( visitor ); + } + + static class ConstraintDiffSetsVisitor implements PropertyConstraint.ChangeVisitor, DiffSetsVisitor + { + private final TxStateVisitor visitor; + + ConstraintDiffSetsVisitor( TxStateVisitor visitor ) { - @Override - public void visitAdded( UniquenessConstraint element ) - { - visitor.visitAddedConstraint( element ); - } + this.visitor = visitor; + } - @Override - public void visitRemoved( UniquenessConstraint element ) - { - visitor.visitRemovedConstraint( element ); - } - }; + @Override + public void visitAdded( PropertyConstraint element ) + { + element.added( this ); + } + + @Override + public void visitRemoved( PropertyConstraint element ) + { + element.removed( this ); + } + + @Override + public void visitAddedUniquePropertyConstraint( UniquenessConstraint constraint ) + { + visitor.visitAddedUniquePropertyConstraint( constraint ); + } + + @Override + public void visitRemovedUniquePropertyConstraint( UniquenessConstraint constraint ) + { + visitor.visitRemovedUniquePropertyConstraint( constraint ); + } + + @Override + public void visitAddedMandatoryPropertyConstraint( MandatoryPropertyConstraint constraint ) + { + visitor.visitAddedMandatoryPropertyConstraint( constraint ); + } + + @Override + public void visitRemovedMandatoryPropertyConstraint( MandatoryPropertyConstraint constraint ) + { + visitor.visitRemovedMandatoryPropertyConstraint( constraint ); + } } private static DiffSetsVisitor indexVisitor( final TxStateVisitor visitor, @@ -1048,14 +1083,22 @@ public void constraintDoAdd( UniquenessConstraint constraint, long indexId ) } @Override - public ReadableDiffSets constraintsChangesForLabelAndProperty( int labelId, + public void constraintDoAdd( MandatoryPropertyConstraint constraint ) + { + constraintsChangesDiffSets().add( constraint ); + getOrCreateLabelState( constraint.label() ).getOrCreateConstraintsChanges().add( constraint ); + hasChanges = true; + } + + @Override + public ReadableDiffSets constraintsChangesForLabelAndProperty( int labelId, final int propertyKey ) { return LABEL_STATE.get( this, labelId ).constraintsChanges().filterAdded( - new Predicate() + new Predicate() { @Override - public boolean test( UniquenessConstraint item ) + public boolean test( PropertyConstraint item ) { return item.propertyKeyId() == propertyKey; } @@ -1063,18 +1106,18 @@ public boolean test( UniquenessConstraint item ) } @Override - public ReadableDiffSets constraintsChangesForLabel( int labelId ) + public ReadableDiffSets constraintsChangesForLabel( int labelId ) { return LABEL_STATE.get( this, labelId ).constraintsChanges(); } @Override - public ReadableDiffSets constraintsChanges() + public ReadableDiffSets constraintsChanges() { return ReadableDiffSets.Empty.ifNull( constraintsChanges ); } - private DiffSets constraintsChangesDiffSets() + private DiffSets constraintsChangesDiffSets() { if ( constraintsChanges == null ) { @@ -1084,17 +1127,21 @@ private DiffSets constraintsChangesDiffSets() } @Override - public void constraintDoDrop( UniquenessConstraint constraint ) + public void constraintDoDrop( PropertyConstraint constraint ) { constraintsChangesDiffSets().remove( constraint ); - constraintIndexDoDrop( new IndexDescriptor( constraint.label(), constraint.propertyKeyId() ) ); + + if ( constraint instanceof UniquenessConstraint ) + { + constraintIndexDoDrop( new IndexDescriptor( constraint.label(), constraint.propertyKeyId() )); + } getOrCreateLabelState( constraint.label() ).getOrCreateConstraintsChanges().remove( constraint ); hasChanges = true; } @Override - public boolean constraintDoUnRemove( UniquenessConstraint constraint ) + public boolean constraintDoUnRemove( PropertyConstraint constraint ) { if ( constraintsChangesDiffSets().unRemove( constraint ) ) { @@ -1120,10 +1167,11 @@ public Iterable constraintIndexesCreatedInTx() { if ( createdConstraintIndexesByConstraint != null && !createdConstraintIndexesByConstraint.isEmpty() ) { - return map( new Function() + + return map( new Function() { @Override - public IndexDescriptor apply( UniquenessConstraint constraint ) + public IndexDescriptor apply( PropertyConstraint constraint ) { return new IndexDescriptor( constraint.label(), constraint.propertyKeyId() ); } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/store/CacheLayer.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/store/CacheLayer.java index d4e453c7463f9..b815da970f760 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/store/CacheLayer.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/store/CacheLayer.java @@ -45,7 +45,7 @@ import org.neo4j.function.Function; import org.neo4j.function.Predicate; import org.neo4j.graphdb.Direction; -import org.neo4j.kernel.api.constraints.UniquenessConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.cursor.NodeCursor; import org.neo4j.kernel.api.cursor.RelationshipCursor; import org.neo4j.kernel.api.exceptions.EntityNotFoundException; @@ -269,19 +269,19 @@ public Iterator graphGetAllProperties() } @Override - public Iterator constraintsGetForLabelAndPropertyKey( int labelId, int propertyKeyId ) + public Iterator constraintsGetForLabelAndPropertyKey( int labelId, int propertyKeyId ) { return schemaCache.constraintsForLabelAndProperty( labelId, propertyKeyId ); } @Override - public Iterator constraintsGetForLabel( int labelId ) + public Iterator constraintsGetForLabel( int labelId ) { return schemaCache.constraintsForLabel( labelId ); } @Override - public Iterator constraintsGetAll() + public Iterator constraintsGetAll() { return schemaCache.constraints(); } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/store/DiskLayer.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/store/DiskLayer.java index 87875914b344b..ebf4ff81ec717 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/store/DiskLayer.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/store/DiskLayer.java @@ -36,7 +36,7 @@ import org.neo4j.graphdb.TransactionFailureException; import org.neo4j.kernel.api.EntityType; import org.neo4j.kernel.api.ReadOperations; -import org.neo4j.kernel.api.constraints.UniquenessConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.cursor.LabelCursor; import org.neo4j.kernel.api.cursor.NodeCursor; import org.neo4j.kernel.api.cursor.PropertyCursor; @@ -69,11 +69,12 @@ import org.neo4j.kernel.impl.store.InvalidRecordException; import org.neo4j.kernel.impl.store.NeoStore; import org.neo4j.kernel.impl.store.NodeStore; +import org.neo4j.kernel.impl.store.PropertyConstraintRule; import org.neo4j.kernel.impl.store.RelationshipGroupStore; import org.neo4j.kernel.impl.store.RelationshipStore; import org.neo4j.kernel.impl.store.SchemaStorage; import org.neo4j.kernel.impl.store.UnderlyingStorageException; -import org.neo4j.kernel.impl.store.UniquenessConstraintRule; +import org.neo4j.kernel.impl.store.UniquePropertyConstraintRule; import org.neo4j.kernel.impl.store.record.IndexRule; import org.neo4j.kernel.impl.store.record.NodeRecord; import org.neo4j.kernel.impl.store.record.Record; @@ -96,17 +97,16 @@ */ public class DiskLayer implements StoreReadLayer { - private static final Function UNIQUENESS_CONSTRAINT_TO_RULE = - new Function() + private static final Function RULE_TO_CONSTRAINT = + new Function() { - @Override - public UniquenessConstraint apply( UniquenessConstraintRule rule ) + public PropertyConstraint apply( PropertyConstraintRule rule ) { // We can use propertyKeyId straight up here, without reading from the record, since we have // verified that it has that propertyKeyId in the predicate. And since we currently only support // uniqueness on single properties, there is nothing else to pass in to UniquenessConstraint. - return new UniquenessConstraint( rule.getLabel(), rule.getPropertyKey() ); + return rule.toConstraint(); } }; @@ -662,13 +662,13 @@ public String indexGetFailure( IndexDescriptor descriptor ) throws IndexNotFound } @Override - public Iterator constraintsGetForLabelAndPropertyKey( int labelId, final int propertyKeyId ) + public Iterator constraintsGetForLabelAndPropertyKey( int labelId, final int propertyKeyId ) { - return schemaStorage.schemaRules( UNIQUENESS_CONSTRAINT_TO_RULE, UniquenessConstraintRule.class, - labelId, new Predicate() + return schemaStorage.schemaRules( RULE_TO_CONSTRAINT, PropertyConstraintRule.class, + labelId, new Predicate() { @Override - public boolean test( UniquenessConstraintRule rule ) + public boolean test( PropertyConstraintRule rule ) { return rule.containsPropertyKeyId( propertyKeyId ); } @@ -676,17 +676,17 @@ public boolean test( UniquenessConstraintRule rule ) } @Override - public Iterator constraintsGetForLabel( int labelId ) + public Iterator constraintsGetForLabel( int labelId ) { - return schemaStorage.schemaRules( UNIQUENESS_CONSTRAINT_TO_RULE, UniquenessConstraintRule.class, - labelId, Predicates.alwaysTrue() ); + return schemaStorage.schemaRules( RULE_TO_CONSTRAINT, UniquePropertyConstraintRule.class, + labelId, Predicates.alwaysTrue() ); } @Override - public Iterator constraintsGetAll() + public Iterator constraintsGetAll() { - return schemaStorage.schemaRules( UNIQUENESS_CONSTRAINT_TO_RULE, SchemaRule.Kind.UNIQUENESS_CONSTRAINT, - Predicates.alwaysTrue() ); + return schemaStorage.schemaRules( RULE_TO_CONSTRAINT, SchemaRule.Kind.UNIQUENESS_CONSTRAINT, + Predicates.alwaysTrue() ); } @Override diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/store/SchemaCache.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/store/SchemaCache.java index bf71534f985e6..4ae56bcbff1e9 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/store/SchemaCache.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/store/SchemaCache.java @@ -29,15 +29,14 @@ import org.neo4j.function.Predicate; import org.neo4j.helpers.collection.Iterables; import org.neo4j.helpers.collection.NestingIterable; -import org.neo4j.kernel.api.constraints.UniquenessConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; import org.neo4j.kernel.api.index.IndexDescriptor; -import org.neo4j.kernel.impl.store.UniquenessConstraintRule; +import org.neo4j.kernel.impl.store.PropertyConstraintRule; import org.neo4j.kernel.impl.store.record.IndexRule; import org.neo4j.kernel.impl.store.record.SchemaRule; import static java.util.Collections.unmodifiableCollection; - import static org.neo4j.helpers.collection.Iterables.filter; /** @@ -54,7 +53,7 @@ public class SchemaCache private final Map> rulesByLabelMap = new HashMap<>(); private final Map rulesByIdMap = new HashMap<>(); - private final Collection constraints = new HashSet<>(); + private final Collection constraints = new HashSet<>(); private final Map> indexDescriptors = new HashMap<>(); public SchemaCache( Iterable initialRules ) @@ -100,29 +99,29 @@ public Collection schemaRulesForLabel( int label ) Collections.emptyList(); } - public Iterator constraints() + public Iterator constraints() { return constraints.iterator(); } - public Iterator constraintsForLabel( final int label ) + public Iterator constraintsForLabel( final int label ) { - return filter( new Predicate() + return filter( new Predicate() { @Override - public boolean test( UniquenessConstraint item ) + public boolean test( PropertyConstraint item ) { return item.label() == label; } }, constraints.iterator() ); } - public Iterator constraintsForLabelAndProperty( final int label, final int property ) + public Iterator constraintsForLabelAndProperty( final int label, final int property ) { - return filter( new Predicate() + return filter( new Predicate() { @Override - public boolean test( UniquenessConstraint item ) + public boolean test( PropertyConstraint item ) { return item.label() == label && item.propertyKeyId() == property; } @@ -136,9 +135,9 @@ public void addSchemaRule( SchemaRule rule ) // Note: If you start adding more unmarshalling of other types of things here, // make this into a more generic thing rather than adding more branch statement. - if( rule instanceof UniquenessConstraintRule ) + if( rule instanceof PropertyConstraintRule ) { - constraints.add( ruleToConstraint( (UniquenessConstraintRule) rule ) ); + constraints.add( ((PropertyConstraintRule) rule).toConstraint() ); } else if( rule instanceof IndexRule ) { @@ -212,9 +211,9 @@ public void removeSchemaRule( long id ) rulesByLabelMap.remove( labelId ); } - if( rule instanceof UniquenessConstraintRule ) + if( rule instanceof PropertyConstraintRule ) { - constraints.remove( ruleToConstraint( (UniquenessConstraintRule)rule ) ); + constraints.remove( ((PropertyConstraintRule) rule).toConstraint() ); } else if( rule instanceof IndexRule ) { @@ -245,11 +244,6 @@ public long indexId( IndexDescriptor index ) throws IndexNotFoundKernelException ); } - private UniquenessConstraint ruleToConstraint( UniquenessConstraintRule constraintRule ) - { - return new UniquenessConstraint( constraintRule.getLabel(), constraintRule.getPropertyKey() ); - } - public IndexDescriptor indexDescriptor( int labelId, int propertyKey ) { Map byLabel = indexDescriptors.get( labelId ); diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/store/StoreReadLayer.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/store/StoreReadLayer.java index e505b972c113d..55df0dc9253bf 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/store/StoreReadLayer.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/store/StoreReadLayer.java @@ -24,7 +24,7 @@ import org.neo4j.collection.primitive.PrimitiveIntIterator; import org.neo4j.collection.primitive.PrimitiveLongIterator; import org.neo4j.graphdb.Direction; -import org.neo4j.kernel.api.constraints.UniquenessConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.cursor.NodeCursor; import org.neo4j.kernel.api.cursor.RelationshipCursor; import org.neo4j.kernel.api.exceptions.EntityNotFoundException; @@ -122,12 +122,12 @@ Iterator relationshipGetAllProperties( StoreStatement statement Iterator graphGetAllProperties(); - Iterator constraintsGetForLabelAndPropertyKey( + Iterator constraintsGetForLabelAndPropertyKey( int labelId, int propertyKeyId ); - Iterator constraintsGetForLabel( int labelId ); + Iterator constraintsGetForLabel( int labelId ); - Iterator constraintsGetAll(); + Iterator constraintsGetAll(); PrimitiveLongResourceIterator nodeGetFromUniqueIndexSeek( KernelStatement state, IndexDescriptor index, Object value ) diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/BaseConstraintCreator.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/BaseConstraintCreator.java index 1e891df2bd636..712b2722e6541 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/BaseConstraintCreator.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/BaseConstraintCreator.java @@ -42,6 +42,12 @@ public ConstraintCreator assertPropertyIsUnique( String propertyKey ) return new PropertyUniqueConstraintCreator( actions, label, propertyKey ); } + @Override + public ConstraintCreator assertPropertyExists( String propertyKey ) + { + throw new UnsupportedOperationException( "not implemented" ); + } + @Override public ConstraintDefinition create() { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/PropertyUniqueConstraintDefinition.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/PropertyConstraintDefinition.java similarity index 75% rename from community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/PropertyUniqueConstraintDefinition.java rename to community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/PropertyConstraintDefinition.java index d6d46c0b51f94..0138a0d403940 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/PropertyUniqueConstraintDefinition.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/PropertyConstraintDefinition.java @@ -25,17 +25,20 @@ import static java.util.Collections.singletonList; -public class PropertyUniqueConstraintDefinition implements ConstraintDefinition +public class PropertyConstraintDefinition implements ConstraintDefinition { private final InternalSchemaActions actions; private final Label label; private final String propertyKey; + private final ConstraintType type; - public PropertyUniqueConstraintDefinition( InternalSchemaActions actions, Label label, String propertyKey ) + public PropertyConstraintDefinition( InternalSchemaActions actions, Label label, String propertyKey, + ConstraintType type ) { this.actions = actions; this.label = label; this.propertyKey = propertyKey; + this.type = type; } @Override @@ -63,7 +66,7 @@ public Label getLabel() public ConstraintType getConstraintType() { assertInUnterminatedTransaction(); - return ConstraintType.UNIQUENESS; + return type; } @Override @@ -85,8 +88,12 @@ public boolean equals( Object o ) return false; } - PropertyUniqueConstraintDefinition that = (PropertyUniqueConstraintDefinition) o; + PropertyConstraintDefinition that = (PropertyConstraintDefinition) o; + if ( type != that.type ) + { + return false; + } if ( !actions.equals( that.actions ) ) { return false; @@ -106,7 +113,7 @@ public boolean equals( Object o ) @Override public int hashCode() { - int result = actions.hashCode(); + int result = type.hashCode(); result = 31 * result + label.name().hashCode(); result = 31 * result + propertyKey.hashCode(); @@ -117,10 +124,23 @@ public int hashCode() public String toString() { // using label name as a good identifier name - return String.format( "%s.%s IS UNIQUE", label.name().toLowerCase(), propertyKey ); + return String.format( "%s.%s IS %s", label.name().toLowerCase(), propertyKey, constraintString() ); + } + + private String constraintString() + { + switch ( type ) + { + case UNIQUENESS: + return "UNIQUE"; + case MANDATORY: + return "NOT NULL"; + default: + throw new UnsupportedOperationException( "Unknown ConstraintType: " + type ); + } } - private final void assertInUnterminatedTransaction() + private void assertInUnterminatedTransaction() { actions.assertInUnterminatedTransaction(); } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/PropertyUniqueConstraintCreator.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/PropertyUniqueConstraintCreator.java index e782ea2f8852a..461af743fc990 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/PropertyUniqueConstraintCreator.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/PropertyUniqueConstraintCreator.java @@ -42,6 +42,12 @@ public final ConstraintCreator assertPropertyIsUnique( String propertyKey ) throw new UnsupportedOperationException( "You can only create one unique constraint at a time." ); } + @Override + public ConstraintCreator assertPropertyExists( String propertyKey ) + { + throw new UnsupportedOperationException( "You are already creating a unique constraint." ); + } + @Override public final ConstraintDefinition create() { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/SchemaImpl.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/SchemaImpl.java index 56682e4c8a688..781c7718a1585 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/SchemaImpl.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/SchemaImpl.java @@ -32,6 +32,7 @@ import org.neo4j.graphdb.NotFoundException; import org.neo4j.graphdb.schema.ConstraintCreator; import org.neo4j.graphdb.schema.ConstraintDefinition; +import org.neo4j.graphdb.schema.ConstraintType; import org.neo4j.graphdb.schema.IndexCreator; import org.neo4j.graphdb.schema.IndexDefinition; import org.neo4j.graphdb.schema.Schema; @@ -39,6 +40,7 @@ import org.neo4j.kernel.api.ReadOperations; import org.neo4j.kernel.api.Statement; import org.neo4j.kernel.api.StatementTokenNameLookup; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.exceptions.InvalidTransactionTypeKernelException; import org.neo4j.kernel.api.exceptions.KernelException; @@ -125,7 +127,7 @@ public Iterable getIndexes() private void addDefinitions( List definitions, final ReadOperations statement, Iterator indexes, final boolean constraintIndex ) { - addToCollection( map( new Function() + addToCollection( map( new Function() { @Override public IndexDefinition apply( IndexDescriptor rule ) @@ -287,7 +289,7 @@ public Iterable getConstraints() try ( Statement statement = statementContextSupplier.get() ) { - Iterator constraints = statement.readOperations().constraintsGetAll(); + Iterator constraints = statement.readOperations().constraintsGetAll(); return asConstraintDefinitions( statement.readOperations(), constraints ); } } @@ -304,26 +306,26 @@ public Iterable getConstraints( final Label label ) { return emptyList(); } - Iterator constraints = statement.readOperations().constraintsGetForLabel( labelId ); + Iterator constraints = statement.readOperations().constraintsGetForLabel( labelId ); return asConstraintDefinitions( statement.readOperations(), constraints ); } } private Iterable asConstraintDefinitions( - final ReadOperations readOperations, Iterator constraints ) + final ReadOperations readOperations, Iterator constraints ) { Iterator definitions = - map( new Function() + map( new Function() { @Override - public ConstraintDefinition apply( UniquenessConstraint constraint ) + public ConstraintDefinition apply( PropertyConstraint constraint ) { int labelId = constraint.label(); try { Label label = label( readOperations.labelGetName( labelId ) ); - return new PropertyUniqueConstraintDefinition( actions, label, - readOperations.propertyKeyGetName( constraint.propertyKeyId() ) ); + return new PropertyConstraintDefinition( actions, label, + readOperations.propertyKeyGetName( constraint.propertyKeyId() ), constraint.type() ); } catch ( PropertyKeyIdNotFoundKernelException e ) { @@ -428,8 +430,8 @@ public ConstraintDefinition createPropertyUniquenessConstraint( Label label, Str { int labelId = statement.schemaWriteOperations().labelGetOrCreateForName( label.name() ); int propertyKeyId = statement.schemaWriteOperations().propertyKeyGetOrCreateForName( propertyKey ); - statement.schemaWriteOperations().uniquenessConstraintCreate( labelId, propertyKeyId ); - return new PropertyUniqueConstraintDefinition( this, label, propertyKey ); + statement.schemaWriteOperations().uniquePropertyConstraintCreate( labelId, propertyKeyId ); + return new PropertyConstraintDefinition( this, label, propertyKey, ConstraintType.UNIQUENESS ); } catch ( AlreadyConstrainedException e ) { @@ -468,7 +470,7 @@ public void dropPropertyUniquenessConstraint( Label label, String propertyKey ) { int labelId = statement.schemaWriteOperations().labelGetOrCreateForName( label.name() ); int propertyKeyId = statement.schemaWriteOperations().propertyKeyGetOrCreateForName( propertyKey ); - UniquenessConstraint constraint = new UniquenessConstraint( labelId, propertyKeyId ); + PropertyConstraint constraint = new UniquenessConstraint( labelId, propertyKeyId ); statement.schemaWriteOperations().constraintDrop( constraint ); } catch ( IllegalTokenNameException | TooManyLabelsException | DropConstraintFailureException e ) diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/MandatoryPropertyConstraintRule.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/MandatoryPropertyConstraintRule.java new file mode 100644 index 0000000000000..1e9f5f988ea14 --- /dev/null +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/MandatoryPropertyConstraintRule.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2002-2015 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.neo4j.kernel.impl.store; + +import java.nio.ByteBuffer; + +import org.neo4j.kernel.api.constraints.MandatoryPropertyConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; + +public class MandatoryPropertyConstraintRule extends PropertyConstraintRule +{ + private final int propertyKeyId; + + /** We currently only support uniqueness constraints on a single property. */ + public static MandatoryPropertyConstraintRule mandatoryPropertyConstraintRule( long id, int labelId, int propertyKeyId ) + { + return new MandatoryPropertyConstraintRule( id, labelId, propertyKeyId ); + } + + public static MandatoryPropertyConstraintRule readMandatoryPropertyConstraintRule( long id, int labelId, ByteBuffer buffer ) + { + return new MandatoryPropertyConstraintRule( id, labelId, readPropertyKey( buffer ) ); + } + + private MandatoryPropertyConstraintRule( long id, int labelId, int propertyKeyId ) + { + super( id, labelId, Kind.MANDATORY_PROPERTY_CONSTRAINT ); + this.propertyKeyId = propertyKeyId; + } + + @Override + public int hashCode() + { + return super.hashCode() | propertyKeyId; + } + + @Override + public boolean equals( Object obj ) + { + return super.equals( obj ) && propertyKeyId == ((MandatoryPropertyConstraintRule) obj).propertyKeyId; + } + + @Override + protected String innerToString() + { + return ", propertyKey=" + propertyKeyId; + } + + @Override + public int length() + { + return super.length() + + 4; /* propertyKeyId */ + } + + @Override + public void serialize( ByteBuffer target ) + { + super.serialize( target ); + target.putInt( propertyKeyId ); + } + + private static int readPropertyKey( ByteBuffer buffer ) + { + return buffer.getInt(); + } + + public int getPropertyKey() + { + return propertyKeyId; + } + + @Override + public PropertyConstraint toConstraint() + { + return new MandatoryPropertyConstraint( getLabel(), getPropertyKey() ); + } + + @Override + public boolean containsPropertyKeyId( int propertyKeyId ) + { + return propertyKeyId == this.propertyKeyId; + } +} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/PropertyConstraintRule.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/PropertyConstraintRule.java new file mode 100644 index 0000000000000..521ac373d0f05 --- /dev/null +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/PropertyConstraintRule.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2002-2015 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.neo4j.kernel.impl.store; + +import org.neo4j.kernel.api.constraints.PropertyConstraint; +import org.neo4j.kernel.impl.store.record.AbstractSchemaRule; + +public abstract class PropertyConstraintRule extends AbstractSchemaRule +{ + PropertyConstraintRule( long id, int label, Kind kind ) + { + super( id, label, kind ); + } + + public abstract PropertyConstraint toConstraint(); + + public abstract boolean containsPropertyKeyId( int propertyKeyId ); +} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/SchemaStorage.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/SchemaStorage.java index 5a4f303abe824..3cc67a3b4ce0c 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/SchemaStorage.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/SchemaStorage.java @@ -139,12 +139,12 @@ public Iterator schemaRules( Function ruleConversion = (Function) conversion; return map( ruleConversion, filter( new Predicate() { - @SuppressWarnings("unchecked") + @SuppressWarnings( "unchecked" ) @Override public boolean test( SchemaRule rule ) { return rule.getLabel() == labelId && - rule.getKind().getRuleClass() == ruleType && + ruleType.isAssignableFrom( rule.getKind().getRuleClass() ) && predicate.test( (R) rule ); } }, loadAllSchemaRules() ) ); @@ -245,25 +245,35 @@ public long newRuleId() return schemaStore.nextId(); } - public UniquenessConstraintRule uniquenessConstraint( int labelId, final int propertyKeyId ) + public MandatoryPropertyConstraintRule mandatoryPropertyConstraint( int labelId, final int propertyKeyId ) throws SchemaRuleNotFoundException { - Iterator rules = schemaRules( - UniquenessConstraintRule.class, labelId, - new Predicate() - { - @Override - public boolean test( UniquenessConstraintRule item ) - { - return item.containsPropertyKeyId( propertyKeyId ); - } - } ); + return propertyConstraint( MandatoryPropertyConstraintRule.class, labelId, propertyKeyId ); + } + + public UniquePropertyConstraintRule uniquenessConstraint( int labelId, final int propertyKeyId ) + throws SchemaRuleNotFoundException + { + return propertyConstraint( UniquePropertyConstraintRule.class, labelId, propertyKeyId ); + } + + private Rule propertyConstraint( Class type, + final int labelId, final int propertyKeyId ) throws SchemaRuleNotFoundException + { + Iterator rules = schemaRules( type, labelId, new Predicate() + { + @Override + public boolean test( Rule item ) + { + return item.containsPropertyKeyId( propertyKeyId ); + } + } ); if ( !rules.hasNext() ) { throw new SchemaRuleNotFoundException( labelId, propertyKeyId, "not found" ); } - UniquenessConstraintRule rule = rules.next(); + Rule rule = rules.next(); if ( rules.hasNext() ) { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/UniquenessConstraintRule.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/UniquePropertyConstraintRule.java similarity index 77% rename from community/kernel/src/main/java/org/neo4j/kernel/impl/store/UniquenessConstraintRule.java rename to community/kernel/src/main/java/org/neo4j/kernel/impl/store/UniquePropertyConstraintRule.java index 0ac642f86d324..508891cdea87d 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/UniquenessConstraintRule.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/UniquePropertyConstraintRule.java @@ -22,28 +22,29 @@ import java.nio.ByteBuffer; import java.util.Arrays; -import org.neo4j.kernel.impl.store.record.AbstractSchemaRule; +import org.neo4j.kernel.api.constraints.PropertyConstraint; +import org.neo4j.kernel.api.constraints.UniquenessConstraint; import static org.neo4j.kernel.impl.util.IoPrimitiveUtils.safeCastLongToInt; -public class UniquenessConstraintRule extends AbstractSchemaRule +public class UniquePropertyConstraintRule extends PropertyConstraintRule { private final int[] propertyKeyIds; private final long ownedIndexRule; /** We currently only support uniqueness constraints on a single property. */ - public static UniquenessConstraintRule uniquenessConstraintRule( long id, int labelId, int propertyKeyId, - long ownedIndexRule ) + public static UniquePropertyConstraintRule uniquenessConstraintRule( long id, int labelId, int propertyKeyId, + long ownedIndexRule ) { - return new UniquenessConstraintRule( id, labelId, new int[] {propertyKeyId}, ownedIndexRule ); + return new UniquePropertyConstraintRule( id, labelId, new int[] {propertyKeyId}, ownedIndexRule ); } - public static UniquenessConstraintRule readUniquenessConstraintRule( long id, int labelId, ByteBuffer buffer ) + public static UniquePropertyConstraintRule readUniquenessConstraintRule( long id, int labelId, ByteBuffer buffer ) { - return new UniquenessConstraintRule( id, labelId, readPropertyKeys( buffer ), readOwnedIndexRule( buffer ) ); + return new UniquePropertyConstraintRule( id, labelId, readPropertyKeys( buffer ), readOwnedIndexRule( buffer ) ); } - private UniquenessConstraintRule( long id, int labelId, int[] propertyKeyIds, long ownedIndexRule ) + private UniquePropertyConstraintRule( long id, int labelId, int[] propertyKeyIds, long ownedIndexRule ) { super( id, labelId, Kind.UNIQUENESS_CONSTRAINT ); this.ownedIndexRule = ownedIndexRule; @@ -60,7 +61,7 @@ public int hashCode() @Override public boolean equals( Object obj ) { - return super.equals( obj ) && Arrays.equals( propertyKeyIds, ((UniquenessConstraintRule) obj).propertyKeyIds ); + return super.equals( obj ) && Arrays.equals( propertyKeyIds, ((UniquePropertyConstraintRule) obj).propertyKeyIds ); } @Override @@ -128,4 +129,10 @@ public long getOwnedIndex() { return ownedIndexRule; } + + @Override + public PropertyConstraint toConstraint() + { + return new UniquenessConstraint( getLabel(), getPropertyKey() ); + } } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/record/SchemaRule.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/record/SchemaRule.java index 90704ee41ae8f..acd811854ee9d 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/record/SchemaRule.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/record/SchemaRule.java @@ -22,7 +22,8 @@ import java.nio.ByteBuffer; import org.neo4j.kernel.api.exceptions.schema.MalformedSchemaRuleException; -import org.neo4j.kernel.impl.store.UniquenessConstraintRule; +import org.neo4j.kernel.impl.store.MandatoryPropertyConstraintRule; +import org.neo4j.kernel.impl.store.UniquePropertyConstraintRule; public interface SchemaRule extends RecordSerializable { @@ -41,7 +42,7 @@ public interface SchemaRule extends RecordSerializable */ Kind getKind(); - public static enum Kind + enum Kind { INDEX_RULE( 1, IndexRule.class ) { @@ -59,12 +60,20 @@ protected SchemaRule newRule( long id, int labelId, ByteBuffer buffer ) return IndexRule.readIndexRule( id, true, labelId, buffer ); } }, - UNIQUENESS_CONSTRAINT( 3, UniquenessConstraintRule.class ) + UNIQUENESS_CONSTRAINT( 3, UniquePropertyConstraintRule.class ) { @Override protected SchemaRule newRule( long id, int labelId, ByteBuffer buffer ) { - return UniquenessConstraintRule.readUniquenessConstraintRule( id, labelId, buffer ); + return UniquePropertyConstraintRule.readUniquenessConstraintRule( id, labelId, buffer ); + } + }, + MANDATORY_PROPERTY_CONSTRAINT( 4, MandatoryPropertyConstraintRule.class ) + { + @Override + protected SchemaRule newRule( long id, int labelId, ByteBuffer buffer ) + { + return MandatoryPropertyConstraintRule.readMandatoryPropertyConstraintRule( id, labelId, buffer ); } }; @@ -118,6 +127,7 @@ public static Kind kindForId( byte id ) throws MalformedSchemaRuleException case 1: return INDEX_RULE; case 2: return CONSTRAINT_INDEX_RULE; case 3: return UNIQUENESS_CONSTRAINT; + case 4: return MANDATORY_PROPERTY_CONSTRAINT; default: throw new MalformedSchemaRuleException( null, "Unknown kind id %d", id ); } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/NeoStoreTransactionApplier.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/NeoStoreTransactionApplier.java index 22360596a0a83..c997f72e5c3e6 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/NeoStoreTransactionApplier.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/NeoStoreTransactionApplier.java @@ -27,7 +27,7 @@ import org.neo4j.kernel.impl.store.NeoStore; import org.neo4j.kernel.impl.store.NodeStore; import org.neo4j.kernel.impl.store.SchemaStore; -import org.neo4j.kernel.impl.store.UniquenessConstraintRule; +import org.neo4j.kernel.impl.store.UniquePropertyConstraintRule; import org.neo4j.kernel.impl.store.record.DynamicRecord; import org.neo4j.kernel.impl.store.record.RelationshipRecord; @@ -144,7 +144,7 @@ public boolean visitSchemaRuleCommand( Command.SchemaRuleCommand command ) throw schemaStore.updateRecord( record ); } - if ( command.getSchemaRule() instanceof UniquenessConstraintRule ) + if ( command.getSchemaRule() instanceof UniquePropertyConstraintRule ) { switch ( command.getMode() ) { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/state/IntegrityValidator.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/state/IntegrityValidator.java index 5a63333e850ac..ebe1a2c3e4671 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/state/IntegrityValidator.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/state/IntegrityValidator.java @@ -26,7 +26,7 @@ import org.neo4j.kernel.api.exceptions.schema.ConstraintVerificationFailedKernelException; import org.neo4j.kernel.impl.api.index.IndexingService; import org.neo4j.kernel.impl.store.NeoStore; -import org.neo4j.kernel.impl.store.UniquenessConstraintRule; +import org.neo4j.kernel.impl.store.UniquePropertyConstraintRule; import org.neo4j.kernel.impl.store.record.NodeRecord; import org.neo4j.kernel.impl.store.record.Record; import org.neo4j.kernel.impl.store.record.SchemaRule; @@ -76,11 +76,11 @@ public void validateTransactionStartKnowledge( long lastCommittedTxWhenTransacti public void validateSchemaRule( SchemaRule schemaRule ) throws TransactionFailureException { - if ( schemaRule instanceof UniquenessConstraintRule ) + if ( schemaRule instanceof UniquePropertyConstraintRule ) { try { - indexes.validateIndex( ((UniquenessConstraintRule)schemaRule).getOwnedIndex() ); + indexes.validateIndex( ((UniquePropertyConstraintRule)schemaRule).getOwnedIndex() ); } catch ( ConstraintVerificationFailedKernelException e ) { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureArgumentFormatter.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureArgumentFormatter.java index 6f79346269d10..6ab0a9bdc6981 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureArgumentFormatter.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureArgumentFormatter.java @@ -25,6 +25,7 @@ import java.util.List; import org.neo4j.helpers.Strings; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.index.IndexDescriptor; @@ -85,9 +86,9 @@ else if ( arg instanceof IndexDescriptor ) int propertyKeyId = descriptor.getPropertyKeyId(); builder.append( format( "new IndexDescriptor( %s, %s )", labelId, propertyKeyId ) ); } - else if ( arg instanceof UniquenessConstraint ) + else if ( arg instanceof PropertyConstraint ) { - UniquenessConstraint constraint = (UniquenessConstraint) arg; + PropertyConstraint constraint = (PropertyConstraint) arg; int labelId = constraint.label(); int propertyKeyId = constraint.propertyKeyId(); builder.append( format( "new UniquenessConstraint( %s, %s )", labelId, propertyKeyId ) ); diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureCollector.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureCollector.java index 2552e1c8dd1eb..bea9bf19b216c 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureCollector.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureCollector.java @@ -22,7 +22,7 @@ import org.neo4j.function.Function; import org.neo4j.helpers.Pair; import org.neo4j.helpers.collection.Iterables; -import org.neo4j.kernel.api.constraints.UniquenessConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.index.IndexDescriptor; import java.util.*; @@ -36,7 +36,7 @@ public class DbStructureCollector implements DbStructureVisitor private final TokenMap relationshipTypes = new TokenMap( "relationship types" ); private final IndexDescriptorMap regularIndices = new IndexDescriptorMap( "regular" ); private final IndexDescriptorMap uniqueIndices = new IndexDescriptorMap( "unique" ); - private final Set uniquenessConstraint = new HashSet<>(); + private final Set uniquenessConstraint = new HashSet<>(); private final Map nodeCounts = new HashMap<>(); private final Map relCounts = new HashMap<>(); private long allNodesCount = -1l; @@ -78,10 +78,10 @@ public Iterator> knownUniqueIndices() @Override public Iterator> knownUniqueConstraints() { - return Iterables.map( new Function>() + return Iterables.map( new Function>() { @Override - public Pair apply( UniquenessConstraint uniquenessConstraint ) throws RuntimeException + public Pair apply( PropertyConstraint uniquenessConstraint ) throws RuntimeException { String label = labels.byIdOrFail( uniquenessConstraint.label() ); String propertyKey = propertyKeys.byIdOrFail( uniquenessConstraint.propertyKeyId() ); @@ -154,7 +154,7 @@ public void visitUniqueIndex( IndexDescriptor descriptor, String userDescription } @Override - public void visitUniqueConstraint( UniquenessConstraint constraint, String userDescription ) + public void visitUniqueConstraint( PropertyConstraint constraint, String userDescription ) { if ( !uniquenessConstraint.add( constraint ) ) { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureVisitor.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureVisitor.java index 81414ef38cc2f..9479d28f06814 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureVisitor.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureVisitor.java @@ -19,7 +19,7 @@ */ package org.neo4j.kernel.impl.util.dbstructure; -import org.neo4j.kernel.api.constraints.UniquenessConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.index.IndexDescriptor; public interface DbStructureVisitor @@ -30,7 +30,7 @@ public interface DbStructureVisitor void visitIndex( IndexDescriptor descriptor, String userDescription, double uniqueValuesPercentage, long size ); void visitUniqueIndex( IndexDescriptor descriptor, String userDescription, double uniqueValuesPercentage, long size ); - void visitUniqueConstraint( UniquenessConstraint constraint, String userDescription ); + void visitUniqueConstraint( PropertyConstraint constraint, String userDescription ); void visitAllNodesCount( long nodeCount ); void visitNodeCount( int labelId, String labelName, long nodeCount ); diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/dbstructure/GraphDbStructureGuide.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/dbstructure/GraphDbStructureGuide.java index ade26023e93be..80e16a1532ef8 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/dbstructure/GraphDbStructureGuide.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/dbstructure/GraphDbStructureGuide.java @@ -32,7 +32,7 @@ import org.neo4j.kernel.api.Statement; import org.neo4j.kernel.api.StatementTokenNameLookup; import org.neo4j.kernel.api.TokenNameLookup; -import org.neo4j.kernel.api.constraints.UniquenessConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.exceptions.KernelException; import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; import org.neo4j.kernel.api.index.IndexDescriptor; @@ -167,10 +167,10 @@ private void showUniqueIndices( DbStructureVisitor visitor, ReadOperations read, private void showUniqueConstraints( DbStructureVisitor visitor, ReadOperations read, TokenNameLookup nameLookup ) { - Iterator constraints = read.constraintsGetAll(); + Iterator constraints = read.constraintsGetAll(); while ( constraints.hasNext() ) { - UniquenessConstraint constraint = constraints.next(); + PropertyConstraint constraint = constraints.next(); String userDescription = constraint.userDescription( nameLookup ); visitor.visitUniqueConstraint( constraint, userDescription ); } diff --git a/community/kernel/src/main/java/org/neo4j/unsafe/batchinsert/BatchInserterImpl.java b/community/kernel/src/main/java/org/neo4j/unsafe/batchinsert/BatchInserterImpl.java index 8c19387b00518..c53a8bae3f4a5 100644 --- a/community/kernel/src/main/java/org/neo4j/unsafe/batchinsert/BatchInserterImpl.java +++ b/community/kernel/src/main/java/org/neo4j/unsafe/batchinsert/BatchInserterImpl.java @@ -40,6 +40,7 @@ import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.graphdb.schema.ConstraintCreator; import org.neo4j.graphdb.schema.ConstraintDefinition; +import org.neo4j.graphdb.schema.ConstraintType; import org.neo4j.graphdb.schema.IndexCreator; import org.neo4j.graphdb.schema.IndexDefinition; import org.neo4j.helpers.collection.IteratorUtil; @@ -55,6 +56,7 @@ import org.neo4j.kernel.IdGeneratorFactory; import org.neo4j.kernel.IdType; import org.neo4j.kernel.StoreLocker; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.exceptions.KernelException; import org.neo4j.kernel.api.exceptions.index.IndexCapacityExceededException; @@ -85,7 +87,7 @@ import org.neo4j.kernel.impl.coreapi.schema.IndexCreatorImpl; import org.neo4j.kernel.impl.coreapi.schema.IndexDefinitionImpl; import org.neo4j.kernel.impl.coreapi.schema.InternalSchemaActions; -import org.neo4j.kernel.impl.coreapi.schema.PropertyUniqueConstraintDefinition; +import org.neo4j.kernel.impl.coreapi.schema.PropertyConstraintDefinition; import org.neo4j.kernel.impl.index.IndexConfigStore; import org.neo4j.kernel.impl.locking.LockService; import org.neo4j.kernel.impl.locking.ReentrantLockService; @@ -104,7 +106,7 @@ import org.neo4j.kernel.impl.store.SchemaStore; import org.neo4j.kernel.impl.store.StoreFactory; import org.neo4j.kernel.impl.store.UnderlyingStorageException; -import org.neo4j.kernel.impl.store.UniquenessConstraintRule; +import org.neo4j.kernel.impl.store.UniquePropertyConstraintRule; import org.neo4j.kernel.impl.store.counts.CountsTracker; import org.neo4j.kernel.impl.store.id.IdGeneratorImpl; import org.neo4j.kernel.impl.store.record.DynamicRecord; @@ -138,7 +140,6 @@ import org.neo4j.logging.NullLog; import static java.lang.Boolean.parseBoolean; - import static org.neo4j.collection.primitive.PrimitiveLongCollections.map; import static org.neo4j.graphdb.DynamicLabel.label; import static org.neo4j.helpers.collection.IteratorUtil.first; @@ -418,7 +419,7 @@ private void checkSchemaCreationConstraints( int labelId, int propertyKeyId ) otherPropertyKeyId = ((IndexRule) rule).getPropertyKey(); break; case UNIQUENESS_CONSTRAINT: - otherPropertyKeyId = ((UniquenessConstraintRule) rule).getPropertyKey(); + otherPropertyKeyId = ((UniquePropertyConstraintRule) rule).getPropertyKey(); break; default: throw new IllegalStateException( "Case not handled."); @@ -589,7 +590,7 @@ public ConstraintCreator createDeferredConstraint( Label label ) return new BaseConstraintCreator( new BatchSchemaActions(), label ); } - private void createConstraintRule( UniquenessConstraint constraint ) + private void createConstraintRule( PropertyConstraint constraint ) { // TODO: Do not create duplicate index @@ -602,7 +603,8 @@ private void createConstraintRule( UniquenessConstraint constraint ) indexRuleId, constraint.label(), constraint.propertyKeyId(), this.schemaIndexProviders.getDefaultProvider().getProviderDescriptor(), constraintRuleId ); - UniquenessConstraintRule constraintRule = UniquenessConstraintRule.uniquenessConstraintRule( + UniquePropertyConstraintRule + constraintRule = UniquePropertyConstraintRule.uniquenessConstraintRule( constraintRuleId, constraint.label(), constraint.propertyKeyId(), indexRuleId ); for ( DynamicRecord record : schemaStore.allocateFrom( constraintRule ) ) @@ -1148,7 +1150,7 @@ public ConstraintDefinition createPropertyUniquenessConstraint( Label label, Str checkSchemaCreationConstraints( labelId, propertyKeyId ); createConstraintRule( new UniquenessConstraint( labelId, propertyKeyId ) ); - return new PropertyUniqueConstraintDefinition( this, label, propertyKey ); + return new PropertyConstraintDefinition( this, label, propertyKey, ConstraintType.UNIQUENESS ); } @Override diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelSchemaStateFlushingTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelSchemaStateFlushingTest.java index 3b839fb1b5416..a61ea403b28da 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelSchemaStateFlushingTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelSchemaStateFlushingTest.java @@ -30,7 +30,7 @@ import org.neo4j.kernel.api.KernelAPI; import org.neo4j.kernel.api.KernelTransaction; import org.neo4j.kernel.api.Statement; -import org.neo4j.kernel.api.constraints.UniquenessConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.exceptions.KernelException; import org.neo4j.kernel.api.exceptions.TransactionFailureException; import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; @@ -115,7 +115,7 @@ public void shouldInvalidateSchemaStateOnCreateConstraint() throws Exception public void shouldInvalidateSchemaStateOnDropConstraint() throws Exception { // given - UniquenessConstraint descriptor = createConstraint(); + PropertyConstraint descriptor = createConstraint(); commitToSchemaState( "test", "before" ); @@ -128,19 +128,19 @@ public void shouldInvalidateSchemaStateOnDropConstraint() throws Exception assertEquals( "after", after ); } - private UniquenessConstraint createConstraint() throws KernelException + private PropertyConstraint createConstraint() throws KernelException { try ( KernelTransaction transaction = kernel.newTransaction(); Statement statement = transaction.acquireStatement() ) { - UniquenessConstraint descriptor = statement.schemaWriteOperations().uniquenessConstraintCreate( 1, 1 ); + PropertyConstraint descriptor = statement.schemaWriteOperations().uniquePropertyConstraintCreate( 1, 1 ); transaction.success(); return descriptor; } } - private void dropConstraint( UniquenessConstraint descriptor ) throws KernelException + private void dropConstraint( PropertyConstraint descriptor ) throws KernelException { try ( KernelTransaction transaction = kernel.newTransaction(); Statement statement = transaction.acquireStatement() ) diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelTest.java index 0456a23fc79aa..ac37b8f8efcba 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelTest.java @@ -57,7 +57,7 @@ public void shouldNotAllowCreationOfConstraintsWhenInHA() throws Exception try { - statement.schemaWriteOperations().uniquenessConstraintCreate( 1, 1 ); + statement.schemaWriteOperations().uniquePropertyConstraintCreate( 1, 1 ); fail( "expected exception here" ); } catch ( InvalidTransactionTypeKernelException e ) diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/LockingStatementOperationsTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/LockingStatementOperationsTest.java index 9b5c069bcfd52..bd9ef3d792b49 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/LockingStatementOperationsTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/LockingStatementOperationsTest.java @@ -19,13 +19,14 @@ */ package org.neo4j.kernel.impl.api; -import java.util.Collections; -import java.util.Iterator; - import org.junit.Test; import org.mockito.InOrder; +import java.util.Collections; +import java.util.Iterator; + import org.neo4j.function.Function; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.exceptions.EntityNotFoundException; import org.neo4j.kernel.api.index.IndexDescriptor; @@ -43,7 +44,6 @@ import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; - import static org.neo4j.function.Functions.constant; import static org.neo4j.kernel.impl.locking.ResourceTypes.schemaResource; @@ -197,22 +197,22 @@ public void shouldAcquireSchemaWriteLockBeforeCreatingUniquenessConstraint() thr { // given UniquenessConstraint constraint = new UniquenessConstraint( 0, 0 ); - when( schemaWriteOps.uniquenessConstraintCreate( state, 123, 456 ) ).thenReturn( constraint ); + when( schemaWriteOps.uniquePropertyConstraintCreate( state, 123, 456 ) ).thenReturn( constraint ); // when - UniquenessConstraint result = lockingOps.uniquenessConstraintCreate( state, 123, 456 ); + PropertyConstraint result = lockingOps.uniquePropertyConstraintCreate( state, 123, 456 ); // then assertSame( constraint, result ); order.verify( locks ).acquireExclusive( ResourceTypes.SCHEMA, schemaResource() ); - order.verify( schemaWriteOps ).uniquenessConstraintCreate( state, 123, 456 ); + order.verify( schemaWriteOps ).uniquePropertyConstraintCreate( state, 123, 456 ); } @Test public void shouldAcquireSchemaWriteLockBeforeDroppingConstraint() throws Exception { // given - UniquenessConstraint constraint = new UniquenessConstraint( 1, 2 ); + PropertyConstraint constraint = new UniquenessConstraint( 1, 2 ); // when lockingOps.constraintDrop( state, constraint ); @@ -226,11 +226,11 @@ public void shouldAcquireSchemaWriteLockBeforeDroppingConstraint() throws Except public void shouldAcquireSchemaReadLockBeforeGettingConstraintsByLabelAndProperty() throws Exception { // given - Iterator constraints = Collections.emptyIterator(); + Iterator constraints = Collections.emptyIterator(); when( schemaReadOps.constraintsGetForLabelAndPropertyKey( state, 123, 456 ) ).thenReturn( constraints ); // when - Iterator result = lockingOps.constraintsGetForLabelAndPropertyKey( state, 123, 456 ); + Iterator result = lockingOps.constraintsGetForLabelAndPropertyKey( state, 123, 456 ); // then assertSame( constraints, result ); @@ -242,11 +242,11 @@ public void shouldAcquireSchemaReadLockBeforeGettingConstraintsByLabelAndPropert public void shouldAcquireSchemaReadLockBeforeGettingConstraintsByLabel() throws Exception { // given - Iterator constraints = Collections.emptyIterator(); + Iterator constraints = Collections.emptyIterator(); when( schemaReadOps.constraintsGetForLabel( state, 123 ) ).thenReturn( constraints ); // when - Iterator result = lockingOps.constraintsGetForLabel( state, 123 ); + Iterator result = lockingOps.constraintsGetForLabel( state, 123 ); // then assertSame( constraints, result ); @@ -258,11 +258,11 @@ public void shouldAcquireSchemaReadLockBeforeGettingConstraintsByLabel() throws public void shouldAcquireSchemaReadLockBeforeGettingAllConstraints() throws Exception { // given - Iterator constraints = Collections.emptyIterator(); + Iterator constraints = Collections.emptyIterator(); when( schemaReadOps.constraintsGetAll( state ) ).thenReturn( constraints ); // when - Iterator result = lockingOps.constraintsGetAll( state ); + Iterator result = lockingOps.constraintsGetAll( state ); // then assertSame( constraints, result ); diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/index/IndexIT.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/index/IndexIT.java index ab87e3c4d03c3..0dffc11f46171 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/index/IndexIT.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/index/IndexIT.java @@ -164,7 +164,7 @@ public void shouldFailToCreateIndexWhereAConstraintAlreadyExists() throws Except // given { SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); - statement.uniquenessConstraintCreate( labelId, propertyKey ); + statement.uniquePropertyConstraintCreate( labelId, propertyKey ); commit(); } @@ -191,8 +191,8 @@ public void shouldListConstraintIndexesInTheBeansAPI() throws Exception // given { SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); - statement.uniquenessConstraintCreate( statement.labelGetOrCreateForName( "Label1" ), - statement.propertyKeyGetOrCreateForName( "property1" ) ); + statement.uniquePropertyConstraintCreate( statement.labelGetOrCreateForName( "Label1" ), + statement.propertyKeyGetOrCreateForName( "property1" ) ); commit(); } @@ -232,7 +232,7 @@ public void shouldNotListConstraintIndexesAmongIndexes() throws Exception // given { SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); - statement.uniquenessConstraintCreate( labelId, propertyKey ); + statement.uniquePropertyConstraintCreate( labelId, propertyKey ); commit(); } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/ConstraintsCreationIT.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/ConstraintsCreationIT.java index b294b27064b70..7aa1483a81254 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/ConstraintsCreationIT.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/ConstraintsCreationIT.java @@ -19,14 +19,14 @@ */ package org.neo4j.kernel.impl.api.integrationtest; +import org.junit.Before; +import org.junit.Test; + import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import org.junit.Before; -import org.junit.Test; - import org.neo4j.function.Function; import org.neo4j.graphdb.ConstraintViolationException; import org.neo4j.graphdb.Node; @@ -35,6 +35,8 @@ import org.neo4j.graphdb.schema.Schema; import org.neo4j.kernel.api.ReadOperations; import org.neo4j.kernel.api.SchemaWriteOperations; +import org.neo4j.kernel.api.constraints.MandatoryPropertyConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.exceptions.KernelException; import org.neo4j.kernel.api.exceptions.TransactionFailureException; @@ -43,18 +45,16 @@ import org.neo4j.kernel.api.exceptions.schema.NoSuchConstraintException; import org.neo4j.kernel.api.index.IndexDescriptor; import org.neo4j.kernel.impl.store.SchemaStorage; -import org.neo4j.kernel.impl.store.UniquenessConstraintRule; +import org.neo4j.kernel.impl.store.UniquePropertyConstraintRule; import org.neo4j.kernel.impl.store.record.IndexRule; import static java.util.Collections.singletonList; - import static org.hamcrest.CoreMatchers.instanceOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; - import static org.neo4j.graphdb.DynamicLabel.label; import static org.neo4j.helpers.collection.IteratorUtil.asCollection; import static org.neo4j.helpers.collection.IteratorUtil.asList; @@ -65,15 +65,15 @@ public class ConstraintsCreationIT extends KernelIntegrationTest { @Test - public void shouldBeAbleToStoreAndRetrieveUniquenessConstraintRule() throws Exception + public void shouldBeAbleToStoreAndRetrieveUniquePropertyConstraintRule() throws Exception { // given - UniquenessConstraint constraint; + PropertyConstraint constraint; { SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); // when - constraint = statement.uniquenessConstraintCreate( labelId, propertyKeyId ); + constraint = statement.uniquePropertyConstraintCreate( labelId, propertyKeyId ); // then assertEquals( constraint, single( statement.constraintsGetForLabelAndPropertyKey( labelId,propertyKeyId ) ) ); @@ -82,11 +82,41 @@ public void shouldBeAbleToStoreAndRetrieveUniquenessConstraintRule() throws Exce // given commit(); } + { + ReadOperations statement = readOperationsInNewTransaction(); + + // when + Iterator constraints = statement + .constraintsGetForLabelAndPropertyKey( labelId, propertyKeyId ); + + // then + assertEquals( constraint, single( constraints ) ); + } + } + + @Test + public void shouldCreateAndRetrieveMandatoryPropertyConstraint() throws Exception + { + // given + PropertyConstraint constraint; { SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); // when - Iterator constraints = statement + constraint = statement.mandatoryPropertyConstraintCreate( labelId, propertyKeyId ); + + // then + assertEquals( constraint, single( statement.constraintsGetForLabelAndPropertyKey( labelId,propertyKeyId ) ) ); + assertEquals( constraint, single( statement.constraintsGetForLabel( labelId ) ) ); + + // given + commit(); + } + { + ReadOperations statement = readOperationsInNewTransaction(); + + // when + Iterator constraints = statement .constraintsGetForLabelAndPropertyKey( labelId, propertyKeyId ); // then @@ -95,59 +125,138 @@ public void shouldBeAbleToStoreAndRetrieveUniquenessConstraintRule() throws Exce } @Test - public void shouldNotPersistUniquenessConstraintsCreatedInAbortedTransaction() throws Exception + public void shouldNotPersistUniquePropertyConstraintsCreatedInAbortedTransaction() throws Exception { // given { SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); - statement.uniquenessConstraintCreate( labelId, propertyKeyId ); + statement.uniquePropertyConstraintCreate( labelId, propertyKeyId ); // when rollback(); } + { + ReadOperations statement = readOperationsInNewTransaction(); + + // then + Iterator constraints = statement.constraintsGetForLabelAndPropertyKey( labelId, propertyKeyId ); + assertFalse( "should not have any constraints", constraints.hasNext() ); + } + } + + @Test + public void shouldNotPersistMandatoryPropertyConstraintsCreatedInAbortedTransaction() throws Exception + { + // given { SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); + statement.mandatoryPropertyConstraintCreate( labelId, propertyKeyId ); + + // when + rollback(); + } + { + ReadOperations statement = readOperationsInNewTransaction(); + // then - Iterator constraints = statement.constraintsGetForLabelAndPropertyKey( labelId, propertyKeyId ); + Iterator constraints = statement.constraintsGetForLabelAndPropertyKey( labelId, propertyKeyId ); assertFalse( "should not have any constraints", constraints.hasNext() ); } } @Test - public void shouldNotStoreUniquenessConstraintThatIsRemovedInTheSameTransaction() throws Exception + public void shouldNotStoreUniquePropertyConstraintThatIsRemovedInTheSameTransaction() throws Exception { // given { SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); - UniquenessConstraint constraint = statement.uniquenessConstraintCreate( labelId, propertyKeyId ); + PropertyConstraint constraint = statement.uniquePropertyConstraintCreate( labelId, propertyKeyId ); // when statement.constraintDrop( constraint ); // then - assertFalse( "should not have any constraints", statement.constraintsGetForLabelAndPropertyKey( labelId, propertyKeyId ).hasNext() ); + assertFalse( "should not have any constraints", + statement.constraintsGetForLabelAndPropertyKey( labelId, propertyKeyId ).hasNext() ); // when commit(); } + { + ReadOperations statement = readOperationsInNewTransaction(); + + // then + assertFalse( "should not have any constraints", + statement.constraintsGetForLabelAndPropertyKey( labelId, propertyKeyId ).hasNext() ); + } + } + + @Test + public void shouldNotStoreMandatoryPropertyConstraintThatIsRemovedInTheSameTransaction() throws Exception + { + // given { SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); + PropertyConstraint constraint = statement.mandatoryPropertyConstraintCreate( labelId, propertyKeyId ); + + // when + statement.constraintDrop( constraint ); + + // then + assertFalse( "should not have any constraints", + statement.constraintsGetForLabelAndPropertyKey( labelId, propertyKeyId ).hasNext() ); + + // when + commit(); + } + { + ReadOperations statement = readOperationsInNewTransaction(); + + // then + assertFalse( "should not have any constraints", + statement.constraintsGetForLabelAndPropertyKey( labelId, propertyKeyId ).hasNext() ); + } + } + + @Test + public void shouldDropMandatoryPropertyConstraint() throws Exception + { + // given + PropertyConstraint constraint; + { + SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); + constraint = statement.mandatoryPropertyConstraintCreate( labelId, propertyKeyId ); + commit(); + } + + // when + { + SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); + statement.constraintDrop( constraint ); + commit(); + } + + // then + { + ReadOperations statement = readOperationsInNewTransaction(); + // then - assertFalse( "should not have any constraints", statement.constraintsGetForLabelAndPropertyKey( labelId, propertyKeyId ).hasNext() ); + assertFalse( "should not have any constraints", + statement.constraintsGetForLabelAndPropertyKey( labelId, propertyKeyId ).hasNext() ); } } @Test - public void shouldNotCreateUniquenessConstraintThatAlreadyExists() throws Exception + public void shouldNotCreateUniquePropertyConstraintThatAlreadyExists() throws Exception { // given { SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); - statement.uniquenessConstraintCreate( labelId, propertyKeyId ); + statement.uniquePropertyConstraintCreate( labelId, propertyKeyId ); commit(); } @@ -156,7 +265,7 @@ public void shouldNotCreateUniquenessConstraintThatAlreadyExists() throws Except { SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); - statement.uniquenessConstraintCreate( labelId, propertyKeyId ); + statement.uniquePropertyConstraintCreate( labelId, propertyKeyId ); fail( "Should not have validated" ); } @@ -168,13 +277,39 @@ public void shouldNotCreateUniquenessConstraintThatAlreadyExists() throws Except } @Test - public void shouldNotRemoveConstraintThatGetsReAdded() throws Exception + public void shouldNotCreateMandatoryPropertyConstraintThatAlreadyExists() throws Exception { // given - UniquenessConstraint constraint; { SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); - constraint = statement.uniquenessConstraintCreate( labelId, propertyKeyId ); + statement.mandatoryPropertyConstraintCreate( labelId, propertyKeyId ); + commit(); + } + + // when + try + { + SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); + + statement.mandatoryPropertyConstraintCreate( labelId, propertyKeyId ); + + fail( "Should not have validated" ); + } + // then + catch ( AlreadyConstrainedException e ) + { + // good + } + } + + @Test + public void shouldNotRemoveUniquePropertyConstraintThatGetsReAdded() throws Exception + { + // given + PropertyConstraint constraint; + { + SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); + constraint = statement.uniquePropertyConstraintCreate( labelId, propertyKeyId ); commit(); } SchemaStateCheck schemaState = new SchemaStateCheck().setUp(); @@ -183,75 +318,123 @@ public void shouldNotRemoveConstraintThatGetsReAdded() throws Exception // when statement.constraintDrop( constraint ); - statement.uniquenessConstraintCreate( labelId, propertyKeyId ); + statement.uniquePropertyConstraintCreate( labelId, propertyKeyId ); commit(); } { - SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); + ReadOperations statement = readOperationsInNewTransaction(); // then assertEquals( singletonList( constraint ), asCollection( statement.constraintsGetForLabelAndPropertyKey( labelId, propertyKeyId ) ) ); - schemaState.assertNotCleared(); + schemaState.assertNotCleared(statement); } } @Test - public void shouldClearSchemaStateWhenConstraintIsCreated() throws Exception + public void shouldNotRemoveMandatoryPropertyConstraintThatGetsReAdded() throws Exception { // given + PropertyConstraint constraint; + { + SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); + constraint = statement.mandatoryPropertyConstraintCreate( labelId, propertyKeyId ); + commit(); + } SchemaStateCheck schemaState = new SchemaStateCheck().setUp(); + { + SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); - SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); - - // when - statement.uniquenessConstraintCreate( labelId, propertyKeyId ); - commit(); + // when + statement.constraintDrop( constraint ); + statement.mandatoryPropertyConstraintCreate( labelId, propertyKeyId ); + commit(); + } + { + ReadOperations statement = readOperationsInNewTransaction(); - // then - schemaWriteOperationsInNewTransaction(); - schemaState.assertCleared(); + // then + assertEquals( singletonList( constraint ), asCollection( statement.constraintsGetForLabelAndPropertyKey( labelId, propertyKeyId ) ) ); + schemaState.assertNotCleared(statement); + } } @Test - public void shouldClearSchemaStateWhenConstraintIsDropped() throws Exception + public void shouldClearSchemaStateWhenConstraintIsCreated() throws Exception { - // given - UniquenessConstraint constraint; - SchemaStateCheck schemaState; + for ( int i = 0; i < 2; i++ ) { + // given + SchemaStateCheck schemaState = new SchemaStateCheck().setUp(); + SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); - constraint = statement.uniquenessConstraintCreate( labelId, propertyKeyId ); + + // when + if ( i == 0 ) + { + statement.uniquePropertyConstraintCreate( labelId, propertyKeyId ); + } + else + { + statement.mandatoryPropertyConstraintCreate( labelId, propertyKeyId ); + } commit(); - schemaState = new SchemaStateCheck().setUp(); + // then + schemaState.assertCleared(readOperationsInNewTransaction()); + rollback(); } + } + @Test + public void shouldClearSchemaStateWhenConstraintIsDropped() throws Exception + { + for ( int i = 0; i < 2; i++ ) { - SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); + // given + PropertyConstraint constraint; + SchemaStateCheck schemaState; + { + SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); + if ( i == 0 ) + { + constraint = statement.uniquePropertyConstraintCreate( labelId, propertyKeyId ); + } + else + { + constraint = statement.mandatoryPropertyConstraintCreate( labelId, propertyKeyId ); + } + commit(); + + schemaState = new SchemaStateCheck().setUp(); + } - // when - statement.constraintDrop( constraint ); - commit(); - } + { + SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); - // then - schemaWriteOperationsInNewTransaction(); - schemaState.assertCleared(); + // when + statement.constraintDrop( constraint ); + commit(); + } + + // then + schemaState.assertCleared( readOperationsInNewTransaction() ); + rollback(); + } } @Test - public void shouldCreateAnIndexToGoAlongWithAUniquenessConstraint() throws Exception + public void shouldCreateAnIndexToGoAlongWithAUniquePropertyConstraint() throws Exception { // when { SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); - statement.uniquenessConstraintCreate( labelId, propertyKeyId ); + statement.uniquePropertyConstraintCreate( labelId, propertyKeyId ); commit(); } // then { - SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); + ReadOperations statement = readOperationsInNewTransaction(); assertEquals( asSet( new IndexDescriptor( labelId, propertyKeyId ) ), asSet( statement.uniqueIndexesGetAll() ) ); } @@ -263,9 +446,9 @@ public void shouldDropCreatedConstraintIndexWhenRollingBackConstraintCreation() // given { SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); - statement.uniquenessConstraintCreate( labelId, propertyKeyId ); + statement.uniquePropertyConstraintCreate( labelId, propertyKeyId ); assertEquals( asSet( new IndexDescriptor( labelId, propertyKeyId ) ), - asSet( statement.uniqueIndexesGetAll() ) ); + asSet( statement.uniqueIndexesGetAll() ) ); } // when @@ -273,7 +456,7 @@ public void shouldDropCreatedConstraintIndexWhenRollingBackConstraintCreation() // then { - SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); + ReadOperations statement = readOperationsInNewTransaction(); assertEquals( emptySetOf( IndexDescriptor.class ), asSet( statement.uniqueIndexesGetAll() ) ); commit(); } @@ -283,11 +466,12 @@ public void shouldDropCreatedConstraintIndexWhenRollingBackConstraintCreation() public void shouldDropConstraintIndexWhenDroppingConstraint() throws Exception { // given - UniquenessConstraint constraint; + PropertyConstraint constraint; { SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); - constraint = statement.uniquenessConstraintCreate( labelId, propertyKeyId ); - assertEquals( asSet( new IndexDescriptor( labelId, propertyKeyId ) ), asSet( statement.uniqueIndexesGetAll() ) ); + constraint = statement.uniquePropertyConstraintCreate( labelId, propertyKeyId ); + assertEquals( asSet( new IndexDescriptor( labelId, propertyKeyId ) ), + asSet( statement.uniqueIndexesGetAll() ) ); commit(); } @@ -300,7 +484,7 @@ public void shouldDropConstraintIndexWhenDroppingConstraint() throws Exception // then { - SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); + ReadOperations statement = readOperationsInNewTransaction(); assertEquals( emptySetOf( IndexDescriptor.class ), asSet( statement.uniqueIndexesGetAll( ) ) ); commit(); } @@ -309,28 +493,116 @@ public void shouldDropConstraintIndexWhenDroppingConstraint() throws Exception @Test public void shouldNotDropConstraintThatDoesNotExist() throws Exception { - // when + for ( PropertyConstraint constraint : new PropertyConstraint[]{ + new UniquenessConstraint( labelId, propertyKeyId ), + new MandatoryPropertyConstraint( labelId, propertyKeyId ), + } ) { - SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); - - try + // when { - statement.constraintDrop( new UniquenessConstraint( labelId, propertyKeyId ) ); - fail( "Should not have dropped constraint" ); + SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); + + try + { + statement.constraintDrop( constraint ); + fail( "Should not have dropped constraint" ); + } + catch ( DropConstraintFailureException e ) + { + assertThat( e.getCause(), instanceOf( NoSuchConstraintException.class ) ); + } + commit(); } - catch ( DropConstraintFailureException e ) + + // then { - assertThat( e.getCause(), instanceOf( NoSuchConstraintException.class ) ); + ReadOperations statement = readOperationsInNewTransaction(); + assertEquals( emptySetOf( IndexDescriptor.class ), asSet( statement.uniqueIndexesGetAll() ) ); + commit(); } + } + } + + @Test + public void shouldNotDropMandatoryPropertyConstraintThatDoesNotExistWhenThereIsAUniquePropertyConstraint() + throws Exception + { + // given + PropertyConstraint constraint; + { + SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); + constraint = statement.uniquePropertyConstraintCreate( labelId, propertyKeyId ); commit(); } + // when + try + { + SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); + statement.constraintDrop( new MandatoryPropertyConstraint( constraint.label(), constraint.propertyKeyId() ) ); + + fail( "expected exception" ); + } + // then + catch ( DropConstraintFailureException e ) + { + assertThat( e.getCause(), instanceOf( NoSuchConstraintException.class ) ); + } + finally + { + rollback(); + } + // then + { + ReadOperations statement = readOperationsInNewTransaction(); + + Iterator constraints = statement + .constraintsGetForLabelAndPropertyKey( labelId, propertyKeyId ); + + assertEquals( constraint, single( constraints ) ); + } + } + + @Test + public void shouldNotDropUniquePropertyConstraintThatDoesNotExistWhenThereIsAMandatoryPropertyConstraint() + throws Exception + { + // given + PropertyConstraint constraint; { SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); - assertEquals( emptySetOf( IndexDescriptor.class ), asSet( statement.uniqueIndexesGetAll() ) ); + constraint = statement.mandatoryPropertyConstraintCreate( labelId, propertyKeyId ); commit(); } + + // when + try + { + SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); + statement.constraintDrop( new UniquenessConstraint( constraint.label(), constraint.propertyKeyId() ) ); + + fail( "expected exception" ); + } + // then + catch ( DropConstraintFailureException e ) + { + assertThat( e.getCause(), instanceOf( NoSuchConstraintException.class ) ); + } + finally + { + rollback(); + } + + // then + { + ReadOperations statement = readOperationsInNewTransaction(); + + Iterator constraints = statement + .constraintsGetForLabelAndPropertyKey( labelId, propertyKeyId ); + + assertEquals( constraint, single( constraints ) ); + } } @Test @@ -338,19 +610,19 @@ public void committedConstraintRuleShouldCrossReferenceTheCorrespondingIndexRule { // when SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); - statement.uniquenessConstraintCreate( labelId, propertyKeyId ); + statement.uniquePropertyConstraintCreate( labelId, propertyKeyId ); commit(); // then SchemaStorage schema = new SchemaStorage( neoStore().getSchemaStore() ); IndexRule indexRule = schema.indexRule( labelId, propertyKeyId ); - UniquenessConstraintRule constraintRule = schema.uniquenessConstraint( labelId, propertyKeyId ); + UniquePropertyConstraintRule constraintRule = schema.uniquenessConstraint( labelId, propertyKeyId ); assertEquals( constraintRule.getId(), indexRule.getOwningConstraint().longValue() ); assertEquals( indexRule.getId(), constraintRule.getOwnedIndex() ); } @Test - public void shouldNotLeaveAnyStateBehindAfterFailingToCreateConstraint() throws Exception + public void shouldNotLeaveAnyStateBehindAfterFailingToCreateUniquePropertyConstraint() throws Exception { // given try ( org.neo4j.graphdb.Transaction tx = db.beginTx() ) @@ -390,7 +662,7 @@ public void shouldNotLeaveAnyStateBehindAfterFailingToCreateConstraint() throws } @Test - public void shouldBeAbleToResolveConflictsAndRecreateConstraintAfterFailingToCreateConstraintDueToConflict() + public void shouldBeAbleToResolveConflictsAndRecreateConstraintAfterFailingToCreateUniquePropertyConstraintDueToConflict() throws Exception { // given @@ -459,7 +731,6 @@ public void createKeys() throws KernelException private class SchemaStateCheck implements Function { int invocationCount; - private ReadOperations readOperations; @Override public Integer apply( String s ) @@ -470,27 +741,27 @@ public Integer apply( String s ) public SchemaStateCheck setUp() throws TransactionFailureException { - this.readOperations = readOperationsInNewTransaction(); - checkState(); + ReadOperations readOperations = readOperationsInNewTransaction(); + checkState(readOperations); commit(); return this; } - public void assertCleared() + public void assertCleared(ReadOperations readOperations) { int count = invocationCount; - checkState(); + checkState( readOperations ); assertEquals( "schema state should have been cleared.", count + 1, invocationCount ); } - public void assertNotCleared() + public void assertNotCleared(ReadOperations readOperations) { int count = invocationCount; - checkState(); + checkState( readOperations ); assertEquals( "schema state should not have been cleared.", count, invocationCount ); } - private SchemaStateCheck checkState() + private SchemaStateCheck checkState( ReadOperations readOperations ) { assertEquals( Integer.valueOf( 7 ), readOperations.schemaStateGetOrCreate( "7", this ) ); return this; diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/NodeGetUniqueFromIndexSeekIT.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/NodeGetUniqueFromIndexSeekIT.java index dee3687f99993..ce37b2d6ba20a 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/NodeGetUniqueFromIndexSeekIT.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/NodeGetUniqueFromIndexSeekIT.java @@ -195,7 +195,7 @@ private long createNodeWithValue( String value ) throws KernelException private IndexDescriptor createUniquenessConstraint() throws Exception { SchemaWriteOperations schemaStatement = schemaWriteOperationsInNewTransaction(); - schemaStatement.uniquenessConstraintCreate( labelId, propertyKeyId ); + schemaStatement.uniquePropertyConstraintCreate( labelId, propertyKeyId ); IndexDescriptor result = schemaStatement.uniqueIndexGetForLabelAndPropertyKey( labelId, propertyKeyId ); commit(); return result; diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/UniquenessConstraintCreationIT.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/UniquenessConstraintCreationIT.java index d909e154355e4..b1636368a4129 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/UniquenessConstraintCreationIT.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/UniquenessConstraintCreationIT.java @@ -36,7 +36,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; - import static org.neo4j.helpers.collection.IteratorUtil.asSet; public class UniquenessConstraintCreationIT extends KernelIntegrationTest @@ -76,7 +75,7 @@ public void shouldAbortConstraintCreationWhenDuplicatesExist() throws Exception try { SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); - statement.uniquenessConstraintCreate( foo, name ); + statement.uniquePropertyConstraintCreate( foo, name ); fail( "expected exception" ); } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/UniquenessConstraintValidationIT.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/UniquenessConstraintValidationIT.java index ba7bdf603df94..dcbf4e43897bb 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/UniquenessConstraintValidationIT.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/UniquenessConstraintValidationIT.java @@ -328,7 +328,7 @@ private void createConstraint( String label, String propertyKey ) throws KernelE { SchemaWriteOperations statement = schemaWriteOperationsInNewTransaction(); - statement.uniquenessConstraintCreate( labelId, propertyKeyId ); + statement.uniquePropertyConstraintCreate( labelId, propertyKeyId ); commit(); } } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/IndexQueryTransactionStateTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/IndexQueryTransactionStateTest.java index 3d4a7c0ad0355..aa2a7052f8406 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/IndexQueryTransactionStateTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/IndexQueryTransactionStateTest.java @@ -30,6 +30,8 @@ import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.cursor.LabelCursor; import org.neo4j.kernel.api.cursor.PropertyCursor; +import org.neo4j.helpers.collection.IteratorUtil; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.index.IndexDescriptor; import org.neo4j.kernel.api.index.InternalIndexState; import org.neo4j.kernel.api.properties.Property; @@ -331,7 +333,7 @@ public void before() throws Exception when( store.indexesGetForLabel( labelId2 ) ).then( answerAsIteratorFrom( Collections .emptyList() ) ); when( store.indexesGetAll() ).then( answerAsIteratorFrom( Collections.emptyList() ) ); - when( store.constraintsGetForLabel( labelId ) ).thenReturn( Collections.emptyIterator() ); + when( store.constraintsGetForLabel( labelId ) ).thenReturn( Collections.emptyIterator() ); when( store.nodeExists( anyLong() ) ).thenReturn( true ); when( store.indexesGetForLabelAndPropertyKey( labelId, propertyKeyId ) ) .thenReturn( new IndexDescriptor( labelId, propertyKeyId ) ); diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/StateHandlingStatementOperationsTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/StateHandlingStatementOperationsTest.java index df31e05e9017a..0ae0ef6db3d47 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/StateHandlingStatementOperationsTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/StateHandlingStatementOperationsTest.java @@ -19,18 +19,19 @@ */ package org.neo4j.kernel.impl.api.state; -import java.util.Collections; -import java.util.Iterator; -import java.util.Set; - import org.junit.Test; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; +import java.util.Collections; +import java.util.Iterator; +import java.util.Set; + import org.neo4j.collection.primitive.PrimitiveLongCollections; import org.neo4j.collection.primitive.PrimitiveLongIterator; import org.neo4j.helpers.collection.IteratorUtil; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.cursor.LabelCursor; import org.neo4j.kernel.api.cursor.PropertyCursor; @@ -47,7 +48,6 @@ import org.neo4j.kernel.impl.util.diffsets.DiffSets; import static java.util.Arrays.asList; - import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; @@ -57,7 +57,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; - import static org.neo4j.helpers.collection.IteratorUtil.asIterable; import static org.neo4j.helpers.collection.IteratorUtil.asSet; import static org.neo4j.kernel.impl.api.StatementOperationsTestHelper.mockedState; @@ -107,7 +106,7 @@ public void shouldNeverDelegateWrites() throws Exception public void shouldNotAddConstraintAlreadyExistsInTheStore() throws Exception { // given - UniquenessConstraint constraint = new UniquenessConstraint( 10, 66 ); + PropertyConstraint constraint = new UniquenessConstraint( 10, 66 ); TransactionState txState = mock( TransactionState.class ); when( txState.nodesWithLabelChanged( anyInt() ) ).thenReturn( new DiffSets() ); KernelStatement state = mockedState( txState ); @@ -116,7 +115,7 @@ public void shouldNotAddConstraintAlreadyExistsInTheStore() throws Exception StateHandlingStatementOperations context = newTxStateOps( inner ); // when - context.uniquenessConstraintCreate( state, 10, 66 ); + context.uniquePropertyConstraintCreate( state, 10, 66 ); // then verify( txState ).constraintIndexDoUnRemove( any( IndexDescriptor.class ) ); @@ -126,16 +125,16 @@ public void shouldNotAddConstraintAlreadyExistsInTheStore() throws Exception public void shouldGetConstraintsByLabelAndProperty() throws Exception { // given - UniquenessConstraint constraint = new UniquenessConstraint( 10, 66 ); + PropertyConstraint constraint = new UniquenessConstraint( 10, 66 ); TransactionState txState = new TxState(); KernelStatement state = mockedState( txState ); when( inner.constraintsGetForLabelAndPropertyKey( 10, 66 ) ) .thenAnswer( asAnswer( Collections.emptyList() ) ); StateHandlingStatementOperations context = newTxStateOps( inner ); - context.uniquenessConstraintCreate( state, 10, 66 ); + context.uniquePropertyConstraintCreate( state, 10, 66 ); // when - Set result = asSet( + Set result = asSet( asIterable( context.constraintsGetForLabelAndPropertyKey( state, 10, 66 ) ) ); // then @@ -146,8 +145,8 @@ public void shouldGetConstraintsByLabelAndProperty() throws Exception public void shouldGetConstraintsByLabel() throws Exception { // given - UniquenessConstraint constraint1 = new UniquenessConstraint( 11, 66 ); - UniquenessConstraint constraint2 = new UniquenessConstraint( 11, 99 ); + PropertyConstraint constraint2 = new UniquenessConstraint( 11, 99 ); + PropertyConstraint constraint1 = new UniquenessConstraint( 11, 66 ); TransactionState txState = new TxState(); KernelStatement state = mockedState( txState ); @@ -160,11 +159,11 @@ public void shouldGetConstraintsByLabel() throws Exception when( inner.constraintsGetForLabel( 11 ) ) .thenAnswer( asAnswer( asIterable( constraint1 ) ) ); StateHandlingStatementOperations context = newTxStateOps( inner ); - context.uniquenessConstraintCreate( state, 10, 66 ); - context.uniquenessConstraintCreate( state, 11, 99 ); + context.uniquePropertyConstraintCreate( state, 10, 66 ); + context.uniquePropertyConstraintCreate( state, 11, 99 ); // when - Set result = asSet( asIterable( context.constraintsGetForLabel( state, 11 ) ) ); + Set result = asSet( asIterable( context.constraintsGetForLabel( state, 11 ) ) ); // then assertEquals( asSet( constraint1, constraint2 ), result ); @@ -174,8 +173,8 @@ public void shouldGetConstraintsByLabel() throws Exception public void shouldGetAllConstraints() throws Exception { // given - UniquenessConstraint constraint1 = new UniquenessConstraint( 10, 66 ); - UniquenessConstraint constraint2 = new UniquenessConstraint( 11, 99 ); + PropertyConstraint constraint1 = new UniquenessConstraint( 10, 66 ); + PropertyConstraint constraint2 = new UniquenessConstraint( 11, 99 ); TransactionState txState = new TxState(); KernelStatement state = mockedState( txState ); @@ -185,10 +184,10 @@ public void shouldGetAllConstraints() throws Exception .thenAnswer( asAnswer( Collections.emptyList() ) ); when( inner.constraintsGetAll() ).thenAnswer( asAnswer( asIterable( constraint2 ) ) ); StateHandlingStatementOperations context = newTxStateOps( inner ); - context.uniquenessConstraintCreate( state, 10, 66 ); + context.uniquePropertyConstraintCreate( state, 10, 66 ); // when - Set result = asSet( asIterable( context.constraintsGetAll( state ) ) ); + Set result = asSet( asIterable( context.constraintsGetAll( state ) ) ); // then assertEquals( asSet( constraint1, constraint2 ), result ); diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/TxStateTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/TxStateTest.java index 0c15e4c0737c0..bcb17a68025f3 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/TxStateTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/TxStateTest.java @@ -19,20 +19,22 @@ */ package org.neo4j.kernel.impl.api.state; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.RuleChain; +import org.junit.rules.TestRule; + import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.rules.TestRule; import org.neo4j.collection.primitive.PrimitiveLongIterator; import org.neo4j.graphdb.Direction; import org.neo4j.helpers.collection.IteratorUtil; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.index.IndexDescriptor; import org.neo4j.kernel.api.properties.DefinedProperty; @@ -313,7 +315,7 @@ public void shouldAddUniquenessConstraint() throws Exception state.constraintDoAdd( constraint, 7 ); // then - ReadableDiffSets diff = state.constraintsChangesForLabel( 1 ); + ReadableDiffSets diff = state.constraintsChangesForLabel( 1 ); assertEquals( Collections.singleton( constraint ), diff.getAdded() ); assertTrue( diff.getRemoved().isEmpty() ); diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/store/CacheLayerTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/store/CacheLayerTest.java index 0fa856ee67d89..1814188267943 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/store/CacheLayerTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/store/CacheLayerTest.java @@ -23,13 +23,13 @@ import java.util.Set; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.UniquenessConstraint; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; - import static org.neo4j.helpers.collection.IteratorUtil.asSet; public class CacheLayerTest @@ -42,7 +42,7 @@ public class CacheLayerTest public void shouldLoadAllConstraintsFromCache() throws Exception { // Given - Set constraints = asSet( new UniquenessConstraint( 0, 1 ) ); + Set constraints = asSet( (PropertyConstraint)new UniquenessConstraint( 0, 1 ) ); when(schemaCache.constraints()).thenReturn( constraints.iterator() ); // When & Then @@ -54,7 +54,7 @@ public void shouldLoadConstraintsByLabelFromCache() throws Exception { // Given int labelId = 0; - Set constraints = asSet( new UniquenessConstraint( labelId, 1 ) ); + Set constraints = asSet( (PropertyConstraint)new UniquenessConstraint( labelId, 1 ) ); when(schemaCache.constraintsForLabel(labelId)).thenReturn( constraints.iterator() ); // When & Then @@ -66,7 +66,7 @@ public void shouldLoadConstraintsByLabelAndPropertyFromCache() throws Exception { // Given int labelId = 0, propertyId = 1; - Set constraints = asSet( new UniquenessConstraint( labelId, propertyId ) ); + Set constraints = asSet( (PropertyConstraint)new UniquenessConstraint( labelId, propertyId ) ); when(schemaCache.constraintsForLabelAndProperty(labelId, propertyId)).thenReturn( constraints.iterator() ); // When & Then diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/store/SchemaCacheTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/store/SchemaCacheTest.java index cddcf514f9744..98d8464337e10 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/store/SchemaCacheTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/store/SchemaCacheTest.java @@ -19,10 +19,10 @@ */ package org.neo4j.kernel.impl.api.store; -import java.util.Collection; - import org.junit.Test; +import java.util.Collection; + import org.neo4j.helpers.collection.Iterables; import org.neo4j.helpers.collection.IteratorUtil; import org.neo4j.kernel.api.constraints.UniquenessConstraint; @@ -31,15 +31,13 @@ import org.neo4j.kernel.impl.store.record.SchemaRule; import static java.util.Arrays.asList; - import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; - import static org.neo4j.helpers.collection.IteratorUtil.asSet; import static org.neo4j.kernel.impl.api.index.TestSchemaIndexProviderDescriptor.PROVIDER_DESCRIPTOR; -import static org.neo4j.kernel.impl.store.UniquenessConstraintRule.uniquenessConstraintRule; +import static org.neo4j.kernel.impl.store.UniquePropertyConstraintRule.uniquenessConstraintRule; public class SchemaCacheTest { diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/NeoTransactionStoreApplierTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/NeoTransactionStoreApplierTest.java index 68a4818f73d99..fe764216df8fa 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/NeoTransactionStoreApplierTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/NeoTransactionStoreApplierTest.java @@ -51,7 +51,7 @@ import org.neo4j.kernel.impl.store.RelationshipStore; import org.neo4j.kernel.impl.store.RelationshipTypeTokenStore; import org.neo4j.kernel.impl.store.SchemaStore; -import org.neo4j.kernel.impl.store.UniquenessConstraintRule; +import org.neo4j.kernel.impl.store.UniquePropertyConstraintRule; import org.neo4j.kernel.impl.store.record.DynamicRecord; import org.neo4j.kernel.impl.store.record.IndexRule; import org.neo4j.kernel.impl.store.record.LabelTokenRecord; @@ -747,7 +747,8 @@ public void shouldApplyCreateUniquenessConstraintRuleSchemaRuleCommandToTheStore final DynamicRecord record = DynamicRecord.dynamicRecord( 21, true ); record.setCreated(); final Collection recordsAfter = Arrays.asList( record ); - final UniquenessConstraintRule rule = UniquenessConstraintRule.uniquenessConstraintRule( 0l, 1, 2, 3l ); + final UniquePropertyConstraintRule + rule = UniquePropertyConstraintRule.uniquenessConstraintRule( 0l, 1, 2, 3l ); final Command.SchemaRuleCommand command = new Command.SchemaRuleCommand().init( Collections.emptyList(), recordsAfter, rule ); @@ -770,7 +771,8 @@ public void shouldApplyCreateUniquenessConstraintRuleSchemaRuleCommandToTheStore final DynamicRecord record = DynamicRecord.dynamicRecord( 21, true ); record.setCreated(); final Collection recordsAfter = Arrays.asList( record ); - final UniquenessConstraintRule rule = UniquenessConstraintRule.uniquenessConstraintRule( 0l, 1, 2, 3l ); + final UniquePropertyConstraintRule + rule = UniquePropertyConstraintRule.uniquenessConstraintRule( 0l, 1, 2, 3l ); final Command.SchemaRuleCommand command = new Command.SchemaRuleCommand().init( Collections.emptyList(), recordsAfter, rule ); @@ -794,7 +796,8 @@ public void shouldApplyUpdateUniquenessConstraintRuleSchemaRuleCommandToTheStore final NeoCommandHandler applier = newApplier( false ); final DynamicRecord record = DynamicRecord.dynamicRecord( 21, true ); final Collection recordsAfter = Arrays.asList( record ); - final UniquenessConstraintRule rule = UniquenessConstraintRule.uniquenessConstraintRule( 0l, 1, 2, 3l ); + final UniquePropertyConstraintRule + rule = UniquePropertyConstraintRule.uniquenessConstraintRule( 0l, 1, 2, 3l ); final Command.SchemaRuleCommand command = new Command.SchemaRuleCommand().init( Collections.emptyList(), recordsAfter, rule ); @@ -816,7 +819,8 @@ public void shouldApplyUpdateUniquenessConstraintRuleSchemaRuleCommandToTheStore final NeoCommandHandler applier = newApplier( true ); final DynamicRecord record = DynamicRecord.dynamicRecord( 21, true ); final Collection recordsAfter = Arrays.asList( record ); - final UniquenessConstraintRule rule = UniquenessConstraintRule.uniquenessConstraintRule( 0l, 1, 2, 3l ); + final UniquePropertyConstraintRule + rule = UniquePropertyConstraintRule.uniquenessConstraintRule( 0l, 1, 2, 3l ); final Command.SchemaRuleCommand command = new Command.SchemaRuleCommand().init( Collections.emptyList(), recordsAfter, rule ); @@ -841,7 +845,8 @@ public void shouldApplyDeleteUniquenessConstraintRuleSchemaRuleCommandToTheStore final DynamicRecord record = DynamicRecord.dynamicRecord( 21, true ); record.setInUse( false ); final Collection recordsAfter = Arrays.asList( record ); - final UniquenessConstraintRule rule = UniquenessConstraintRule.uniquenessConstraintRule( 0l, 1, 2, 3l ); + final UniquePropertyConstraintRule + rule = UniquePropertyConstraintRule.uniquenessConstraintRule( 0l, 1, 2, 3l ); final Command.SchemaRuleCommand command = new Command.SchemaRuleCommand().init( Collections.emptyList(), recordsAfter, rule ); @@ -864,7 +869,8 @@ public void shouldApplyDeleteUniquenessConstraintRuleSchemaRuleCommandToTheStore final DynamicRecord record = DynamicRecord.dynamicRecord( 21, true ); record.setInUse( false ); final Collection recordsAfter = Arrays.asList( record ); - final UniquenessConstraintRule rule = UniquenessConstraintRule.uniquenessConstraintRule( 0l, 1, 2, 3l ); + final UniquePropertyConstraintRule + rule = UniquePropertyConstraintRule.uniquenessConstraintRule( 0l, 1, 2, 3l ); final Command.SchemaRuleCommand command = new Command.SchemaRuleCommand().init( Collections.emptyList(), recordsAfter, rule ); diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/IntegrityValidatorTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/IntegrityValidatorTest.java index fd85694f405c4..27b7d9f541ad5 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/IntegrityValidatorTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/IntegrityValidatorTest.java @@ -23,7 +23,7 @@ import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.when; -import static org.neo4j.kernel.impl.store.UniquenessConstraintRule.uniquenessConstraintRule; +import static org.neo4j.kernel.impl.store.UniquePropertyConstraintRule.uniquenessConstraintRule; import static org.powermock.api.mockito.PowerMockito.mock; import org.junit.Test; @@ -31,9 +31,8 @@ import org.neo4j.kernel.api.exceptions.schema.ConstraintVerificationFailedKernelException; import org.neo4j.kernel.impl.api.index.IndexingService; import org.neo4j.kernel.impl.store.NeoStore; -import org.neo4j.kernel.impl.store.UniquenessConstraintRule; +import org.neo4j.kernel.impl.store.UniquePropertyConstraintRule; import org.neo4j.kernel.impl.store.record.NodeRecord; -import org.neo4j.kernel.impl.transaction.state.IntegrityValidator; public class IntegrityValidatorTest { @@ -48,7 +47,7 @@ public void shouldValidateUniquenessIndexes() throws Exception doThrow( new ConstraintVerificationFailedKernelException( null, new RuntimeException() )) .when( indexes ).validateIndex( 2l ); - UniquenessConstraintRule record = uniquenessConstraintRule( 1l, 1, 1, 2l ); + UniquePropertyConstraintRule record = uniquenessConstraintRule( 1l, 1, 1, 2l ); // When try diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/NeoStoreTransactionTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/NeoStoreTransactionTest.java index b5e8e757cb96f..192638da9cbf3 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/NeoStoreTransactionTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/NeoStoreTransactionTest.java @@ -143,7 +143,7 @@ import static org.neo4j.kernel.api.index.SchemaIndexProvider.NO_INDEX_PROVIDER; import static org.neo4j.kernel.impl.api.TransactionApplicationMode.INTERNAL; import static org.neo4j.kernel.impl.api.index.TestSchemaIndexProviderDescriptor.PROVIDER_DESCRIPTOR; -import static org.neo4j.kernel.impl.store.UniquenessConstraintRule.uniquenessConstraintRule; +import static org.neo4j.kernel.impl.store.UniquePropertyConstraintRule.uniquenessConstraintRule; import static org.neo4j.kernel.impl.store.record.IndexRule.indexRule; import static org.neo4j.kernel.impl.transaction.log.TransactionIdStore.BASE_TX_ID; diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/SchemaRuleCommandTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/SchemaRuleCommandTest.java index 7cdae729b029f..baf1d73cee144 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/SchemaRuleCommandTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/SchemaRuleCommandTest.java @@ -55,7 +55,7 @@ import static org.neo4j.helpers.collection.IteratorUtil.first; import static org.neo4j.kernel.impl.api.index.TestSchemaIndexProviderDescriptor.PROVIDER_DESCRIPTOR; -import static org.neo4j.kernel.impl.store.UniquenessConstraintRule.uniquenessConstraintRule; +import static org.neo4j.kernel.impl.store.UniquePropertyConstraintRule.uniquenessConstraintRule; public class SchemaRuleCommandTest { diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/CineastsDbStructure.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/CineastsDbStructure.java index cb05228355047..c11905d9a1c80 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/CineastsDbStructure.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/CineastsDbStructure.java @@ -20,8 +20,6 @@ package org.neo4j.kernel.impl.util.dbstructure; import org.neo4j.helpers.collection.Visitable; -import org.neo4j.kernel.impl.util.dbstructure.DbStructureVisitor; - import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.index.IndexDescriptor; diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureArgumentFormatterTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureArgumentFormatterTest.java index 12dd68309319a..d7f8931e10eeb 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureArgumentFormatterTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureArgumentFormatterTest.java @@ -19,14 +19,14 @@ */ package org.neo4j.kernel.impl.util.dbstructure; -import java.io.IOException; - import org.junit.Test; +import java.io.IOException; + import org.neo4j.kernel.api.constraints.UniquenessConstraint; import org.neo4j.kernel.api.index.IndexDescriptor; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; public class DbStructureArgumentFormatterTest { diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureCollectorTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureCollectorTest.java index 1c84468387e4e..acd527a8c0dcc 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureCollectorTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureCollectorTest.java @@ -25,9 +25,7 @@ import org.neo4j.kernel.api.index.IndexDescriptor; import static java.util.Arrays.asList; - import static org.junit.Assert.assertEquals; - import static org.neo4j.helpers.Pair.of; import static org.neo4j.helpers.collection.Iterables.toList; diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureInvocationTracingAcceptanceTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureInvocationTracingAcceptanceTest.java index 63bd02d3dee8d..632d9fafe2b23 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureInvocationTracingAcceptanceTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/DbStructureInvocationTracingAcceptanceTest.java @@ -19,6 +19,8 @@ */ package org.neo4j.kernel.impl.util.dbstructure; +import org.junit.Test; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -41,8 +43,6 @@ import javax.tools.StandardLocation; import javax.tools.ToolProvider; -import org.junit.Test; - import org.neo4j.function.Function; import org.neo4j.helpers.collection.Visitable; import org.neo4j.kernel.api.constraints.UniquenessConstraint; @@ -52,7 +52,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; - import static org.neo4j.function.Functions.constant; public class DbStructureInvocationTracingAcceptanceTest diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/GraphDbStructureGuideTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/GraphDbStructureGuideTest.java index 1f405b7443cc7..dad44521e2d8d 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/GraphDbStructureGuideTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/GraphDbStructureGuideTest.java @@ -34,7 +34,7 @@ import org.neo4j.kernel.api.ReadOperations; import org.neo4j.kernel.api.SchemaWriteOperations; import org.neo4j.kernel.api.Statement; -import org.neo4j.kernel.api.constraints.UniquenessConstraint; +import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.exceptions.InvalidTransactionTypeKernelException; import org.neo4j.kernel.api.index.IndexDescriptor; import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge; @@ -129,7 +129,7 @@ public void visitsUniqueConstraintsAndIndices() throws Exception commitAndReOpen(); - UniquenessConstraint constraint = createUniqueConstraint( labelId, pkId ); + PropertyConstraint constraint = createUniqueConstraint( labelId, pkId ); IndexDescriptor descriptor = new IndexDescriptor( labelId, pkId ); // WHEN @@ -214,9 +214,9 @@ private IndexDescriptor createSchemaIndex( int labelId, int pkId ) throws Except return schemaWrite().indexCreate( labelId, pkId ); } - private UniquenessConstraint createUniqueConstraint( int labelId, int pkId ) throws Exception + private PropertyConstraint createUniqueConstraint( int labelId, int pkId ) throws Exception { - return schemaWrite().uniquenessConstraintCreate( labelId, pkId ); + return schemaWrite().uniquePropertyConstraintCreate( labelId, pkId ); } private int createLabeledNodes( String labelName, int amount ) throws Exception diff --git a/community/kernel/src/test/java/org/neo4j/unsafe/batchinsert/BatchInsertTest.java b/community/kernel/src/test/java/org/neo4j/unsafe/batchinsert/BatchInsertTest.java index dd3e0257d69db..be9c74fc5b271 100644 --- a/community/kernel/src/test/java/org/neo4j/unsafe/batchinsert/BatchInsertTest.java +++ b/community/kernel/src/test/java/org/neo4j/unsafe/batchinsert/BatchInsertTest.java @@ -82,7 +82,7 @@ import org.neo4j.kernel.impl.store.SchemaStore; import org.neo4j.kernel.impl.store.StoreFactory; import org.neo4j.kernel.impl.store.UnderlyingStorageException; -import org.neo4j.kernel.impl.store.UniquenessConstraintRule; +import org.neo4j.kernel.impl.store.UniquePropertyConstraintRule; import org.neo4j.kernel.impl.store.record.DynamicRecord; import org.neo4j.kernel.impl.store.record.IndexRule; import org.neo4j.kernel.impl.store.record.NodeRecord; @@ -910,15 +910,15 @@ public void shouldCreateConsistentUniquenessConstraint() throws Exception SchemaRule rule0 = storage.loadSingleSchemaRule( inUse.get( 0 ) ); SchemaRule rule1 = storage.loadSingleSchemaRule( inUse.get( 1 ) ); IndexRule indexRule; - UniquenessConstraintRule constraintRule; + UniquePropertyConstraintRule constraintRule; if ( rule0 instanceof IndexRule ) { indexRule = (IndexRule) rule0; - constraintRule = (UniquenessConstraintRule) rule1; + constraintRule = (UniquePropertyConstraintRule) rule1; } else { - constraintRule = (UniquenessConstraintRule) rule0; + constraintRule = (UniquePropertyConstraintRule) rule0; indexRule = (IndexRule) rule1; } assertEquals( "index should reference constraint", diff --git a/community/shell/src/test/java/org/neo4j/shell/TestApps.java b/community/shell/src/test/java/org/neo4j/shell/TestApps.java index 55a2ca935c38a..6fbbf3fdc342a 100644 --- a/community/shell/src/test/java/org/neo4j/shell/TestApps.java +++ b/community/shell/src/test/java/org/neo4j/shell/TestApps.java @@ -856,7 +856,7 @@ public void canListIndexesWhenNoOptionGiven() throws Exception } @Test - public void canListConstraints() throws Exception + public void canListUniquePropertyConstraints() throws Exception { // GIVEN Label label = label( "Person" ); @@ -869,7 +869,20 @@ public void canListConstraints() throws Exception } @Test - public void canListConstraintsByLabel() throws Exception + public void canListMandatoryPropertyConstraints() throws Exception + { + // GIVEN + Label label = label( "Person" ); + beginTx(); + db.schema().constraintFor( label ).assertPropertyExists( "name" ).create(); + finishTx(); + + // WHEN / THEN + executeCommand( "schema ls", "ON \\(person:Person\\) ASSERT person.name IS NOT NULL" ); + } + + @Test + public void canListUniquePropertyConstraintsByLabel() throws Exception { // GIVEN Label label1 = label( "Person" ); @@ -882,7 +895,20 @@ public void canListConstraintsByLabel() throws Exception } @Test - public void canListConstraintsByLabelAndProperty() throws Exception + public void canListMandatoryPropertyConstraintsByLabel() throws Exception + { + // GIVEN + Label label1 = label( "Person" ); + beginTx(); + db.schema().constraintFor( label1 ).assertPropertyExists( "name" ).create(); + finishTx(); + + // WHEN / THEN + executeCommand( "schema ls -l :Person", "ON \\(person:Person\\) ASSERT person.name IS NOT NULL" ); + } + + @Test + public void canListUniquePropertyConstraintsByLabelAndProperty() throws Exception { // GIVEN Label label1 = label( "Person" ); @@ -894,6 +920,19 @@ public void canListConstraintsByLabelAndProperty() throws Exception executeCommand( "schema ls -l :Person -p name", "ON \\(person:Person\\) ASSERT person.name IS UNIQUE" ); } + @Test + public void canListMandatoryPropertyConstraintsByLabelAndProperty() throws Exception + { + // GIVEN + Label label1 = label( "Person" ); + beginTx(); + db.schema().constraintFor( label1 ).assertPropertyExists( "name" ).create(); + finishTx(); + + // WHEN / THEN + executeCommand( "schema ls -l :Person -p name", "ON \\(person:Person\\) ASSERT person.name IS NOT NULL" ); + } + @Test public void failSampleWhenNoOptionGiven() throws Exception { diff --git a/enterprise/ha/src/test/java/org/neo4j/kernel/api/UniqueConstraintHaIT.java b/enterprise/ha/src/test/java/org/neo4j/kernel/api/UniqueConstraintHaIT.java index fbb3da5e5f45e..82087123c5928 100644 --- a/enterprise/ha/src/test/java/org/neo4j/kernel/api/UniqueConstraintHaIT.java +++ b/enterprise/ha/src/test/java/org/neo4j/kernel/api/UniqueConstraintHaIT.java @@ -32,7 +32,7 @@ import org.neo4j.kernel.ha.HaSettings; import org.neo4j.kernel.ha.HighlyAvailableGraphDatabase; import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge; -import org.neo4j.kernel.impl.coreapi.schema.PropertyUniqueConstraintDefinition; +import org.neo4j.kernel.impl.coreapi.schema.PropertyConstraintDefinition; import org.neo4j.test.ha.ClusterManager; import org.neo4j.test.ha.ClusterRule; @@ -216,9 +216,9 @@ public void newSlaveJoiningClusterShouldNotAcceptOperationsUntilConstraintIsOnli // Then try( Transaction ignored = slave.beginTx() ) { - assertThat(single( slave.schema().getConstraints() ), instanceOf(PropertyUniqueConstraintDefinition.class)); - PropertyUniqueConstraintDefinition constraint = - (PropertyUniqueConstraintDefinition)single(slave.schema().getConstraints()); + assertThat(single( slave.schema().getConstraints() ), instanceOf(PropertyConstraintDefinition.class)); + PropertyConstraintDefinition constraint = + (PropertyConstraintDefinition)single(slave.schema().getConstraints()); assertThat(single(constraint.getPropertyKeys()), equalTo("name")); assertThat(constraint.getLabel(), equalTo(label("User"))); }