Skip to content

Commit

Permalink
Built-in-procedures should use in-use when possible
Browse files Browse the repository at this point in the history
The built-in procedures for listing labels and relationship types should only
list those that are currently in-use.
  • Loading branch information
pontusmelke authored and jakewins committed Jan 23, 2016
1 parent e188bb6 commit 609cc75
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 49 deletions.
Expand Up @@ -56,7 +56,7 @@ class CallProcedureAcceptanceTest extends ExecutionEngineFunSuite {
result.toList shouldBe empty 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 // Given
createLabeledNode("A") createLabeledNode("A")
execute("MATCH (a:A) REMOVE a:A") execute("MATCH (a:A) REMOVE a:A")
Expand All @@ -65,11 +65,10 @@ class CallProcedureAcceptanceTest extends ExecutionEngineFunSuite {
val result = execute("CALL sys.db.labels") val result = execute("CALL sys.db.labels")


// Then // Then
result.toList should equal( result shouldBe empty
List(Map("label" -> "A")))
} }


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 // Given
createLabeledNode("A") createLabeledNode("A")
execute("MATCH (a) DETACH DELETE a") execute("MATCH (a) DETACH DELETE a")
Expand All @@ -78,8 +77,7 @@ class CallProcedureAcceptanceTest extends ExecutionEngineFunSuite {
val result = execute("CALL sys.db.labels") val result = execute("CALL sys.db.labels")


// Then // Then
result.toList should equal( result shouldBe empty
List(Map("label" -> "A")))
} }


test("should be able to find types from built-in-procedure") { test("should be able to find types from built-in-procedure") {
Expand All @@ -94,9 +92,9 @@ class CallProcedureAcceptanceTest extends ExecutionEngineFunSuite {
// Then // Then
result.toList should equal( result.toList should equal(
List( List(
Map("relationshipTypes" -> "A"), Map("relationshipType" -> "A"),
Map("relationshipTypes" -> "B"), Map("relationshipType" -> "B"),
Map("relationshipTypes" -> "C"))) Map("relationshipType" -> "C")))
} }


test("sys.db.relationshipType work on an empty database") { test("sys.db.relationshipType work on an empty database") {
Expand All @@ -105,10 +103,10 @@ class CallProcedureAcceptanceTest extends ExecutionEngineFunSuite {
val result = execute("CALL sys.db.relationshipTypes") val result = execute("CALL sys.db.relationshipTypes")


// Then // 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
// Given // Given
relate(createNode(), createNode(), "A") relate(createNode(), createNode(), "A")
Expand All @@ -120,11 +118,7 @@ class CallProcedureAcceptanceTest extends ExecutionEngineFunSuite {
val result = execute("CALL sys.db.relationshipTypes") val result = execute("CALL sys.db.relationshipTypes")


// Then // Then
result.toList should equal( result shouldBe empty
List(
Map("relationshipTypes" -> "A"),
Map("relationshipTypes" -> "B"),
Map("relationshipTypes" -> "C")))
} }


test("should be able to find propertyKeys from built-in-procedure") { test("should be able to find propertyKeys from built-in-procedure") {
Expand All @@ -137,9 +131,9 @@ class CallProcedureAcceptanceTest extends ExecutionEngineFunSuite {
// Then // Then
result.toList should equal( result.toList should equal(
List( List(
Map("propertyKeys" -> "A"), Map("propertyKey" -> "A"),
Map("propertyKeys" -> "B"), Map("propertyKey" -> "B"),
Map("propertyKeys" -> "C"))) Map("propertyKey" -> "C")))
} }


test("sys.db.propertyKeys works on an empty database") { test("sys.db.propertyKeys works on an empty database") {
Expand All @@ -163,25 +157,26 @@ class CallProcedureAcceptanceTest extends ExecutionEngineFunSuite {
// Then // Then
result.toList should equal( result.toList should equal(
List( List(
Map("propertyKeys" -> "A"), Map("propertyKey" -> "A"),
Map("propertyKeys" -> "B"), Map("propertyKey" -> "B"),
Map("propertyKeys" -> "R"))) Map("propertyKey" -> "R")))
} }


test("removing all nodes and relationship does not remove properties from the store") { test("removing all nodes and relationship does not remove properties from the store") {
// Given // Given
relate(createNode("A" -> 1), createNode("B" -> 1), "R" ->1) relate(createNode("A" -> 1), createNode("B" -> 1), "R" ->1)
execute("MATCH (a) DETACH DELETE a") execute("MATCH (a) DETACH DELETE a")
println(execute("MATCH (a) RETURN count(a)").toList)


// When // When
val result = execute("CALL sys.db.propertyKeys") val result = execute("CALL sys.db.propertyKeys")


// Then // Then
result.toList should equal( result.toList should equal(
List( List(
Map("propertyKeys" -> "A"), Map("propertyKey" -> "A"),
Map("propertyKeys" -> "B"), Map("propertyKey" -> "B"),
Map("propertyKeys" -> "R"))) Map("propertyKey" -> "R")))
} }


test("should be able to call procedure with explicit arguments") { test("should be able to call procedure with explicit arguments") {
Expand Down Expand Up @@ -263,8 +258,6 @@ class CallProcedureAcceptanceTest extends ExecutionEngineFunSuite {
an [InvalidArgumentException] shouldBe thrownBy(execute("CALL my.first.proc('ten', 10, 42)")) an [InvalidArgumentException] shouldBe thrownBy(execute("CALL my.first.proc('ten', 10, 42)"))
} }




test("should fail if implicit argument is missing") { test("should fail if implicit argument is missing") {
// Given // Given
register(Neo4jTypes.NTString, Neo4jTypes.NTNumber) register(Neo4jTypes.NTString, Neo4jTypes.NTNumber)
Expand Down
Expand Up @@ -28,6 +28,8 @@
import org.neo4j.collection.primitive.PrimitiveLongIterator; import org.neo4j.collection.primitive.PrimitiveLongIterator;
import org.neo4j.cursor.Cursor; import org.neo4j.cursor.Cursor;
import org.neo4j.graphdb.Direction; 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.NodePropertyConstraint;
import org.neo4j.kernel.api.constraints.PropertyConstraint; import org.neo4j.kernel.api.constraints.PropertyConstraint;
import org.neo4j.kernel.api.constraints.RelationshipPropertyConstraint; import org.neo4j.kernel.api.constraints.RelationshipPropertyConstraint;
Expand Down Expand Up @@ -96,6 +98,7 @@ public interface ReadOperations
/** Returns the relationship types currently stored in the database */ /** Returns the relationship types currently stored in the database */
Iterator<Token> relationshipTypesGetAllTokens(); Iterator<Token> relationshipTypesGetAllTokens();



int labelCount(); int labelCount();


int propertyKeyCount(); int propertyKeyCount();
Expand Down Expand Up @@ -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. */ /** For read procedures, this key will be available in the invocation context as a means to access the current read statement. */
Procedure.Key<ReadOperations> readStatement = Procedure.Key.key("statementContext.read", ReadOperations.class ); Procedure.Key<ReadOperations> readOperations = Procedure.Key.key("statementContext.read", ReadOperations.class );

/** For managed procedures, this gives access to the current statement. */
Procedure.Key<Statement> statement = Procedure.Key.key("statement", Statement.class );


/** Fetch a procedure given its signature. */ /** Fetch a procedure given its signature. */
ProcedureSignature procedureGet( ProcedureSignature.ProcedureName name ) throws ProcedureException; ProcedureSignature procedureGet( ProcedureSignature.ProcedureName name ) throws ProcedureException;
Expand Down
Expand Up @@ -20,16 +20,17 @@
package org.neo4j.kernel.builtinprocs; package org.neo4j.kernel.builtinprocs;


import org.neo4j.collection.RawIterator; import org.neo4j.collection.RawIterator;
import org.neo4j.graphdb.Label;
import org.neo4j.kernel.api.exceptions.ProcedureException; import org.neo4j.kernel.api.exceptions.ProcedureException;
import org.neo4j.kernel.api.proc.Neo4jTypes; import org.neo4j.kernel.api.proc.Neo4jTypes;
import org.neo4j.kernel.api.proc.Procedure; import org.neo4j.kernel.api.proc.Procedure;
import org.neo4j.kernel.api.proc.ProcedureSignature.ProcedureName; 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.asRawIterator;
import static org.neo4j.helpers.collection.Iterables.map; 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 public class ListLabelsProcedure extends Procedure.BasicProcedure
{ {
Expand All @@ -41,7 +42,7 @@ public ListLabelsProcedure( ProcedureName name )
@Override @Override
public RawIterator<Object[], ProcedureException> apply( Context ctx, Object[] input ) throws ProcedureException public RawIterator<Object[], ProcedureException> apply( Context ctx, Object[] input ) throws ProcedureException
{ {
RawIterator<Token,ProcedureException> tokens = asRawIterator( ctx.get( readStatement ).labelsGetAllTokens() ); RawIterator<Label,ProcedureException> labels = asRawIterator( TokenAccess.LABELS.inUse( ctx.get( statement ) ) );
return map( ( token ) -> new Object[]{ token.name() }, tokens ); return map( ( l) -> new Object[]{l.name()}, labels );
} }
} }
Expand Up @@ -24,24 +24,24 @@
import org.neo4j.kernel.api.proc.Neo4jTypes; import org.neo4j.kernel.api.proc.Neo4jTypes;
import org.neo4j.kernel.api.proc.Procedure; import org.neo4j.kernel.api.proc.Procedure;
import org.neo4j.kernel.api.proc.ProcedureSignature; 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.asRawIterator;
import static org.neo4j.helpers.collection.Iterables.map; 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 class ListPropertyKeysProcedure extends Procedure.BasicProcedure
{ {
public ListPropertyKeysProcedure( ProcedureSignature.ProcedureName name ) public ListPropertyKeysProcedure( ProcedureSignature.ProcedureName name )
{ {
super( procedureSignature( name ).out( name.name(), Neo4jTypes.NTString ).build() ); super( procedureSignature( name ).out( "propertyKey", Neo4jTypes.NTString ).build() );
} }


@Override @Override
public RawIterator<Object[], ProcedureException> apply( Context ctx, Object[] input ) throws ProcedureException public RawIterator<Object[], ProcedureException> apply( Context ctx, Object[] input ) throws ProcedureException
{ {
RawIterator<Token,ProcedureException> tokens = asRawIterator( ctx.get( readStatement ).propertyKeyGetAllTokens() ); RawIterator<String,ProcedureException> labels = asRawIterator( TokenAccess.PROPERTY_KEYS.inUse( ctx.get( statement ) ) );
return map( ( token ) -> new Object[]{ token.name() }, tokens ); return map( ( key) -> new Object[]{key}, labels );
} }
} }
Expand Up @@ -20,28 +20,30 @@
package org.neo4j.kernel.builtinprocs; package org.neo4j.kernel.builtinprocs;


import org.neo4j.collection.RawIterator; import org.neo4j.collection.RawIterator;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.kernel.api.exceptions.ProcedureException; import org.neo4j.kernel.api.exceptions.ProcedureException;
import org.neo4j.kernel.api.proc.Neo4jTypes; import org.neo4j.kernel.api.proc.Neo4jTypes;
import org.neo4j.kernel.api.proc.Procedure; import org.neo4j.kernel.api.proc.Procedure;
import org.neo4j.kernel.api.proc.ProcedureSignature; 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.asRawIterator;
import static org.neo4j.helpers.collection.Iterables.map; 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 class ListRelationshipTypesProcedure extends Procedure.BasicProcedure
{ {
public ListRelationshipTypesProcedure( ProcedureSignature.ProcedureName name ) public ListRelationshipTypesProcedure( ProcedureSignature.ProcedureName name )
{ {
super( procedureSignature( name ).out( name.name(), Neo4jTypes.NTString ).build()); super( procedureSignature( name ).out( "relationshipType", Neo4jTypes.NTString ).build());
} }


@Override @Override
public RawIterator<Object[], ProcedureException> apply( Context ctx, Object[] input ) throws ProcedureException public RawIterator<Object[], ProcedureException> apply( Context ctx, Object[] input ) throws ProcedureException
{ {
RawIterator<Token,ProcedureException> tokens = asRawIterator( ctx.get( readStatement ).relationshipTypesGetAllTokens() ); RawIterator<RelationshipType,ProcedureException> types =
return map( ( token ) -> new Object[]{ token.name() }, tokens ); asRawIterator( TokenAccess.RELATIONSHIP_TYPES.inUse( ctx.get( statement ) ) );
return map( ( l) -> new Object[]{l.name()}, types );
} }
} }
Expand Up @@ -29,6 +29,9 @@
import org.neo4j.collection.primitive.PrimitiveLongIterator; import org.neo4j.collection.primitive.PrimitiveLongIterator;
import org.neo4j.cursor.Cursor; import org.neo4j.cursor.Cursor;
import org.neo4j.graphdb.Direction; 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.DataWriteOperations;
import org.neo4j.kernel.api.LegacyIndexHits; import org.neo4j.kernel.api.LegacyIndexHits;
import org.neo4j.kernel.api.ReadOperations; import org.neo4j.kernel.api.ReadOperations;
Expand Down Expand Up @@ -671,7 +674,8 @@ public RawIterator<Object[], ProcedureException> procedureCallRead( ProcedureNam
{ {
statement.assertOpen(); statement.assertOpen();
Procedure.BasicContext ctx = new Procedure.BasicContext(); 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 ); return procedures.call( ctx, name, input );
} }


Expand Down
Expand Up @@ -43,8 +43,11 @@ public class BuiltinProceduresIT extends KernelIntegrationTest
public void listAllLabels() throws Throwable public void listAllLabels() throws Throwable
{ {
// Given // Given

DataWriteOperations ops = dataWriteOperationsInNewTransaction(); DataWriteOperations ops = dataWriteOperationsInNewTransaction();
ops.labelGetOrCreateForName( "MyLabel" ); long nodeId = ops.nodeCreate();
int labelId = ops.labelGetOrCreateForName( "MyLabel" );
ops.nodeAddLabel( nodeId, labelId );
commit(); commit();


// When // When
Expand Down Expand Up @@ -74,7 +77,8 @@ public void listRelationshipTypes() throws Throwable
{ {
// Given // Given
DataWriteOperations ops = dataWriteOperationsInNewTransaction(); DataWriteOperations ops = dataWriteOperationsInNewTransaction();
ops.relationshipTypeGetOrCreateForName( "MyRelType" ); int relType = ops.relationshipTypeGetOrCreateForName( "MyRelType" );
ops.relationshipCreate( relType, ops.nodeCreate(), ops.nodeCreate() );
commit(); commit();


// When // When
Expand Down
Expand Up @@ -92,7 +92,7 @@ public void registeredProcedureShouldGetReadOperations() throws Throwable
@Override @Override
public RawIterator<Object[], ProcedureException> apply( Context ctx, Object[] input ) throws ProcedureException public RawIterator<Object[], ProcedureException> apply( Context ctx, Object[] input ) throws ProcedureException
{ {
return RawIterator.<Object[], ProcedureException>of( new Object[]{ ctx.get( ReadOperations.readStatement ) } ); return RawIterator.<Object[], ProcedureException>of( new Object[]{ ctx.get( ReadOperations.readOperations ) } );
} }
} ); } );


Expand Down

0 comments on commit 609cc75

Please sign in to comment.