From 609cc75a6bcb1c4eb960be4df9ed9dadfa927453 Mon Sep 17 00:00:00 2001 From: Pontus Melke Date: Tue, 19 Jan 2016 13:21:36 +0100 Subject: [PATCH] Built-in-procedures should use `in-use` when possible The built-in procedures for listing labels and relationship types should only list those that are currently in-use. --- .../CallProcedureAcceptanceTest.scala | 47 ++++++++----------- .../org/neo4j/kernel/api/ReadOperations.java | 8 +++- .../builtinprocs/ListLabelsProcedure.java | 11 +++-- .../ListPropertyKeysProcedure.java | 12 ++--- .../ListRelationshipTypesProcedure.java | 14 +++--- .../kernel/impl/api/OperationsFacade.java | 6 ++- .../integrationtest/BuiltinProceduresIT.java | 8 +++- .../integrationtest/ProceduresKernelIT.java | 2 +- 8 files changed, 59 insertions(+), 49 deletions(-) diff --git a/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/CallProcedureAcceptanceTest.scala b/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/CallProcedureAcceptanceTest.scala index 885fd143ac1fd..de9034272051a 100644 --- a/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/CallProcedureAcceptanceTest.scala +++ b/community/cypher/acceptance/src/test/scala/org/neo4j/internal/cypher/acceptance/CallProcedureAcceptanceTest.scala @@ -56,7 +56,7 @@ class CallProcedureAcceptanceTest extends ExecutionEngineFunSuite { result.toList shouldBe empty } - test("removing labels from nodes does not remove labels from label store") { + test("sys.db.labels should be empty when all labels are removed") { // Given createLabeledNode("A") execute("MATCH (a:A) REMOVE a:A") @@ -65,11 +65,10 @@ class CallProcedureAcceptanceTest extends ExecutionEngineFunSuite { val result = execute("CALL sys.db.labels") // Then - result.toList should equal( - List(Map("label" -> "A"))) + result shouldBe empty } - test("removing all the nodes does not remove labels from label store") { + test("sys.db.labels should be empty when all nodes are removed") { // Given createLabeledNode("A") execute("MATCH (a) DETACH DELETE a") @@ -78,8 +77,7 @@ class CallProcedureAcceptanceTest extends ExecutionEngineFunSuite { val result = execute("CALL sys.db.labels") // Then - result.toList should equal( - List(Map("label" -> "A"))) + result shouldBe empty } test("should be able to find types from built-in-procedure") { @@ -94,9 +92,9 @@ class CallProcedureAcceptanceTest extends ExecutionEngineFunSuite { // Then result.toList should equal( List( - Map("relationshipTypes" -> "A"), - Map("relationshipTypes" -> "B"), - Map("relationshipTypes" -> "C"))) + Map("relationshipType" -> "A"), + Map("relationshipType" -> "B"), + Map("relationshipType" -> "C"))) } test("sys.db.relationshipType work on an empty database") { @@ -105,10 +103,10 @@ class CallProcedureAcceptanceTest extends ExecutionEngineFunSuite { val result = execute("CALL sys.db.relationshipTypes") // Then - result.toList shouldBe empty + result shouldBe empty } - test("removing all the relationships does not remove relationship types from the store") { + test("sys.db.relationshipTypes should be empty when all relationships are removed") { // Given // Given relate(createNode(), createNode(), "A") @@ -120,11 +118,7 @@ class CallProcedureAcceptanceTest extends ExecutionEngineFunSuite { val result = execute("CALL sys.db.relationshipTypes") // Then - result.toList should equal( - List( - Map("relationshipTypes" -> "A"), - Map("relationshipTypes" -> "B"), - Map("relationshipTypes" -> "C"))) + result shouldBe empty } test("should be able to find propertyKeys from built-in-procedure") { @@ -137,9 +131,9 @@ class CallProcedureAcceptanceTest extends ExecutionEngineFunSuite { // Then result.toList should equal( List( - Map("propertyKeys" -> "A"), - Map("propertyKeys" -> "B"), - Map("propertyKeys" -> "C"))) + Map("propertyKey" -> "A"), + Map("propertyKey" -> "B"), + Map("propertyKey" -> "C"))) } test("sys.db.propertyKeys works on an empty database") { @@ -163,15 +157,16 @@ class CallProcedureAcceptanceTest extends ExecutionEngineFunSuite { // Then result.toList should equal( List( - Map("propertyKeys" -> "A"), - Map("propertyKeys" -> "B"), - Map("propertyKeys" -> "R"))) + Map("propertyKey" -> "A"), + Map("propertyKey" -> "B"), + Map("propertyKey" -> "R"))) } test("removing all nodes and relationship does not remove properties from the store") { // Given relate(createNode("A" -> 1), createNode("B" -> 1), "R" ->1) execute("MATCH (a) DETACH DELETE a") + println(execute("MATCH (a) RETURN count(a)").toList) // When val result = execute("CALL sys.db.propertyKeys") @@ -179,9 +174,9 @@ class CallProcedureAcceptanceTest extends ExecutionEngineFunSuite { // Then result.toList should equal( List( - Map("propertyKeys" -> "A"), - Map("propertyKeys" -> "B"), - Map("propertyKeys" -> "R"))) + Map("propertyKey" -> "A"), + Map("propertyKey" -> "B"), + Map("propertyKey" -> "R"))) } test("should be able to call procedure with explicit arguments") { @@ -263,8 +258,6 @@ class CallProcedureAcceptanceTest extends ExecutionEngineFunSuite { an [InvalidArgumentException] shouldBe thrownBy(execute("CALL my.first.proc('ten', 10, 42)")) } - - test("should fail if implicit argument is missing") { // Given register(Neo4jTypes.NTString, Neo4jTypes.NTNumber) diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/ReadOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/api/ReadOperations.java index 50e59414bd561..16dbb13528d3a 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/ReadOperations.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/api/ReadOperations.java @@ -28,6 +28,8 @@ import org.neo4j.collection.primitive.PrimitiveLongIterator; import org.neo4j.cursor.Cursor; import org.neo4j.graphdb.Direction; +import org.neo4j.graphdb.Label; +import org.neo4j.graphdb.RelationshipType; import org.neo4j.kernel.api.constraints.NodePropertyConstraint; import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.RelationshipPropertyConstraint; @@ -96,6 +98,7 @@ public interface ReadOperations /** Returns the relationship types currently stored in the database */ Iterator relationshipTypesGetAllTokens(); + int labelCount(); int propertyKeyCount(); @@ -552,7 +555,10 @@ DoubleLongRegister indexSample( IndexDescriptor index, DoubleLongRegister target //=========================================== /** For read procedures, this key will be available in the invocation context as a means to access the current read statement. */ - Procedure.Key readStatement = Procedure.Key.key("statementContext.read", ReadOperations.class ); + Procedure.Key readOperations = Procedure.Key.key("statementContext.read", ReadOperations.class ); + + /** For managed procedures, this gives access to the current statement. */ + Procedure.Key statement = Procedure.Key.key("statement", Statement.class ); /** Fetch a procedure given its signature. */ ProcedureSignature procedureGet( ProcedureSignature.ProcedureName name ) throws ProcedureException; diff --git a/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/ListLabelsProcedure.java b/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/ListLabelsProcedure.java index fbddc33096ed1..ac4f791a9cf1d 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/ListLabelsProcedure.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/ListLabelsProcedure.java @@ -20,16 +20,17 @@ package org.neo4j.kernel.builtinprocs; import org.neo4j.collection.RawIterator; +import org.neo4j.graphdb.Label; import org.neo4j.kernel.api.exceptions.ProcedureException; import org.neo4j.kernel.api.proc.Neo4jTypes; import org.neo4j.kernel.api.proc.Procedure; import org.neo4j.kernel.api.proc.ProcedureSignature.ProcedureName; -import org.neo4j.storageengine.api.Token; +import org.neo4j.kernel.impl.api.TokenAccess; -import static org.neo4j.kernel.api.ReadOperations.readStatement; -import static org.neo4j.kernel.api.proc.ProcedureSignature.procedureSignature; import static org.neo4j.helpers.collection.Iterables.asRawIterator; import static org.neo4j.helpers.collection.Iterables.map; +import static org.neo4j.kernel.api.ReadOperations.statement; +import static org.neo4j.kernel.api.proc.ProcedureSignature.procedureSignature; public class ListLabelsProcedure extends Procedure.BasicProcedure { @@ -41,7 +42,7 @@ public ListLabelsProcedure( ProcedureName name ) @Override public RawIterator apply( Context ctx, Object[] input ) throws ProcedureException { - RawIterator tokens = asRawIterator( ctx.get( readStatement ).labelsGetAllTokens() ); - return map( ( token ) -> new Object[]{ token.name() }, tokens ); + RawIterator labels = asRawIterator( TokenAccess.LABELS.inUse( ctx.get( statement ) ) ); + return map( ( l) -> new Object[]{l.name()}, labels ); } } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/ListPropertyKeysProcedure.java b/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/ListPropertyKeysProcedure.java index c666bf266db90..b83a0a33deece 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/ListPropertyKeysProcedure.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/ListPropertyKeysProcedure.java @@ -24,24 +24,24 @@ import org.neo4j.kernel.api.proc.Neo4jTypes; import org.neo4j.kernel.api.proc.Procedure; import org.neo4j.kernel.api.proc.ProcedureSignature; -import org.neo4j.storageengine.api.Token; +import org.neo4j.kernel.impl.api.TokenAccess; -import static org.neo4j.kernel.api.ReadOperations.readStatement; -import static org.neo4j.kernel.api.proc.ProcedureSignature.procedureSignature; import static org.neo4j.helpers.collection.Iterables.asRawIterator; import static org.neo4j.helpers.collection.Iterables.map; +import static org.neo4j.kernel.api.ReadOperations.statement; +import static org.neo4j.kernel.api.proc.ProcedureSignature.procedureSignature; public class ListPropertyKeysProcedure extends Procedure.BasicProcedure { public ListPropertyKeysProcedure( ProcedureSignature.ProcedureName name ) { - super( procedureSignature( name ).out( name.name(), Neo4jTypes.NTString ).build() ); + super( procedureSignature( name ).out( "propertyKey", Neo4jTypes.NTString ).build() ); } @Override public RawIterator apply( Context ctx, Object[] input ) throws ProcedureException { - RawIterator tokens = asRawIterator( ctx.get( readStatement ).propertyKeyGetAllTokens() ); - return map( ( token ) -> new Object[]{ token.name() }, tokens ); + RawIterator labels = asRawIterator( TokenAccess.PROPERTY_KEYS.inUse( ctx.get( statement ) ) ); + return map( ( key) -> new Object[]{key}, labels ); } } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/ListRelationshipTypesProcedure.java b/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/ListRelationshipTypesProcedure.java index f3ffc18f5662a..abc2b3329a65b 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/ListRelationshipTypesProcedure.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/builtinprocs/ListRelationshipTypesProcedure.java @@ -20,28 +20,30 @@ package org.neo4j.kernel.builtinprocs; import org.neo4j.collection.RawIterator; +import org.neo4j.graphdb.RelationshipType; import org.neo4j.kernel.api.exceptions.ProcedureException; import org.neo4j.kernel.api.proc.Neo4jTypes; import org.neo4j.kernel.api.proc.Procedure; import org.neo4j.kernel.api.proc.ProcedureSignature; -import org.neo4j.storageengine.api.Token; +import org.neo4j.kernel.impl.api.TokenAccess; -import static org.neo4j.kernel.api.ReadOperations.readStatement; -import static org.neo4j.kernel.api.proc.ProcedureSignature.procedureSignature; import static org.neo4j.helpers.collection.Iterables.asRawIterator; import static org.neo4j.helpers.collection.Iterables.map; +import static org.neo4j.kernel.api.ReadOperations.statement; +import static org.neo4j.kernel.api.proc.ProcedureSignature.procedureSignature; public class ListRelationshipTypesProcedure extends Procedure.BasicProcedure { public ListRelationshipTypesProcedure( ProcedureSignature.ProcedureName name ) { - super( procedureSignature( name ).out( name.name(), Neo4jTypes.NTString ).build()); + super( procedureSignature( name ).out( "relationshipType", Neo4jTypes.NTString ).build()); } @Override public RawIterator apply( Context ctx, Object[] input ) throws ProcedureException { - RawIterator tokens = asRawIterator( ctx.get( readStatement ).relationshipTypesGetAllTokens() ); - return map( ( token ) -> new Object[]{ token.name() }, tokens ); + RawIterator types = + asRawIterator( TokenAccess.RELATIONSHIP_TYPES.inUse( ctx.get( statement ) ) ); + return map( ( l) -> new Object[]{l.name()}, types ); } } 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 79860c9a3be76..f38e3508c2d5e 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 @@ -29,6 +29,9 @@ import org.neo4j.collection.primitive.PrimitiveLongIterator; import org.neo4j.cursor.Cursor; import org.neo4j.graphdb.Direction; +import org.neo4j.graphdb.Label; +import org.neo4j.graphdb.RelationshipType; +import org.neo4j.graphdb.ResourceIterator; import org.neo4j.kernel.api.DataWriteOperations; import org.neo4j.kernel.api.LegacyIndexHits; import org.neo4j.kernel.api.ReadOperations; @@ -671,7 +674,8 @@ public RawIterator procedureCallRead( ProcedureNam { statement.assertOpen(); Procedure.BasicContext ctx = new Procedure.BasicContext(); - ctx.put( ReadOperations.readStatement, this ); + ctx.put( ReadOperations.readOperations, this ); + ctx.put( ReadOperations.statement, statement ); return procedures.call( ctx, name, input ); } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/BuiltinProceduresIT.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/BuiltinProceduresIT.java index 542df4df731c6..aa495546b1b1e 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/BuiltinProceduresIT.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/BuiltinProceduresIT.java @@ -43,8 +43,11 @@ public class BuiltinProceduresIT extends KernelIntegrationTest public void listAllLabels() throws Throwable { // Given + DataWriteOperations ops = dataWriteOperationsInNewTransaction(); - ops.labelGetOrCreateForName( "MyLabel" ); + long nodeId = ops.nodeCreate(); + int labelId = ops.labelGetOrCreateForName( "MyLabel" ); + ops.nodeAddLabel( nodeId, labelId ); commit(); // When @@ -74,7 +77,8 @@ public void listRelationshipTypes() throws Throwable { // Given DataWriteOperations ops = dataWriteOperationsInNewTransaction(); - ops.relationshipTypeGetOrCreateForName( "MyRelType" ); + int relType = ops.relationshipTypeGetOrCreateForName( "MyRelType" ); + ops.relationshipCreate( relType, ops.nodeCreate(), ops.nodeCreate() ); commit(); // When diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/ProceduresKernelIT.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/ProceduresKernelIT.java index 735857374c932..785d9d66b149e 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/ProceduresKernelIT.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/integrationtest/ProceduresKernelIT.java @@ -92,7 +92,7 @@ public void registeredProcedureShouldGetReadOperations() throws Throwable @Override public RawIterator apply( Context ctx, Object[] input ) throws ProcedureException { - return RawIterator.of( new Object[]{ ctx.get( ReadOperations.readStatement ) } ); + return RawIterator.of( new Object[]{ ctx.get( ReadOperations.readOperations ) } ); } } );