Skip to content

Commit

Permalink
Move logic to create cursors to static method
Browse files Browse the repository at this point in the history
Move all logic to create the appropriate cursor given denseness,
direction and types to a central place instead of redoing the same
stuff everywhere.
  • Loading branch information
pontusmelke committed Feb 1, 2018
1 parent 4d125ce commit e966ec1
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 184 deletions.
Expand Up @@ -24,11 +24,8 @@
import org.neo4j.internal.kernel.api.NodeCursor; import org.neo4j.internal.kernel.api.NodeCursor;
import org.neo4j.internal.kernel.api.PropertyCursor; import org.neo4j.internal.kernel.api.PropertyCursor;
import org.neo4j.internal.kernel.api.Read; import org.neo4j.internal.kernel.api.Read;
import org.neo4j.internal.kernel.api.RelationshipGroupCursor;
import org.neo4j.internal.kernel.api.RelationshipTraversalCursor;
import org.neo4j.internal.kernel.api.helpers.RelationshipDenseSelectionCursor;
import org.neo4j.internal.kernel.api.helpers.RelationshipSelectionCursor; import org.neo4j.internal.kernel.api.helpers.RelationshipSelectionCursor;
import org.neo4j.internal.kernel.api.helpers.RelationshipSparseSelectionCursor; import org.neo4j.internal.kernel.api.helpers.RelationshipSelections;
import org.neo4j.kernel.api.StatementConstants; import org.neo4j.kernel.api.StatementConstants;
import org.neo4j.kernel.api.exceptions.EntityNotFoundException; import org.neo4j.kernel.api.exceptions.EntityNotFoundException;
import org.neo4j.storageengine.api.EntityType; import org.neo4j.storageengine.api.EntityType;
Expand Down Expand Up @@ -102,59 +99,14 @@ public static boolean nodeHasLabel( Read read, NodeCursor nodeCursor, long node,
} }


public static RelationshipSelectionCursor nodeGetRelationships( Read read, CursorFactory cursors, NodeCursor node, public static RelationshipSelectionCursor nodeGetRelationships( Read read, CursorFactory cursors, NodeCursor node,
long nodeId, long nodeId, Direction direction, int[] types )
Direction direction, int[] relTypes )
{ {
read.singleNode( nodeId, node ); read.singleNode( nodeId, node );
if ( !node.next() ) if ( !node.next() )
{ {
return RelationshipSelectionCursor.EMPTY; return RelationshipSelectionCursor.EMPTY;
} }
if ( node.isDense() ) return RelationshipSelections.selectionCursor( cursors, node, direction, types );
{
RelationshipGroupCursor groupCursor = cursors.allocateRelationshipGroupCursor();
node.relationships( groupCursor );
RelationshipTraversalCursor traversalCursor = cursors.allocateRelationshipTraversalCursor();
RelationshipDenseSelectionCursor selectionCursor =
new RelationshipDenseSelectionCursor();
switch ( direction )
{
case OUTGOING:
selectionCursor.outgoing( groupCursor, traversalCursor, relTypes );
break;
case INCOMING:
selectionCursor.incoming( groupCursor, traversalCursor, relTypes );
break;
case BOTH:
selectionCursor.all( groupCursor, traversalCursor, relTypes );
break;
default:
throw new IllegalStateException( "Code style is awesome" );
}
return selectionCursor;
}
else
{
RelationshipTraversalCursor traversalCursor = cursors.allocateRelationshipTraversalCursor();
node.allRelationships( traversalCursor );
RelationshipSparseSelectionCursor selectionCursor =
new RelationshipSparseSelectionCursor();
switch ( direction )
{
case OUTGOING:
selectionCursor.outgoing( traversalCursor, relTypes );
break;
case INCOMING:
selectionCursor.incoming( traversalCursor, relTypes );
break;
case BOTH:
selectionCursor.all( traversalCursor, relTypes );
break;
default:
throw new IllegalStateException( "Code style is awesome" );
}
return selectionCursor;
}
} }


public static RelationshipSelectionCursor nodeGetRelationships( Read read, CursorFactory cursors, NodeCursor node, public static RelationshipSelectionCursor nodeGetRelationships( Read read, CursorFactory cursors, NodeCursor node,
Expand Down
Expand Up @@ -34,14 +34,14 @@ import org.neo4j.cypher.internal.runtime.interpreted.commands.convert.DirectionC
import org.neo4j.cypher.internal.runtime.interpreted.commands.expressions.{OnlyDirectionExpander, TypeAndDirectionExpander} import org.neo4j.cypher.internal.runtime.interpreted.commands.expressions.{OnlyDirectionExpander, TypeAndDirectionExpander}
import org.neo4j.cypher.internal.util.v3_4.{EntityNotFoundException, FailedIndexException} import org.neo4j.cypher.internal.util.v3_4.{EntityNotFoundException, FailedIndexException}
import org.neo4j.cypher.internal.v3_4.expressions.SemanticDirection import org.neo4j.cypher.internal.v3_4.expressions.SemanticDirection
import org.neo4j.cypher.internal.v3_4.expressions.SemanticDirection.{BOTH, INCOMING, OUTGOING}
import org.neo4j.cypher.internal.v3_4.logical.plans.{QualifiedName, _} import org.neo4j.cypher.internal.v3_4.logical.plans.{QualifiedName, _}
import org.neo4j.graphalgo.impl.path.ShortestPath import org.neo4j.graphalgo.impl.path.ShortestPath
import org.neo4j.graphalgo.impl.path.ShortestPath.ShortestPathPredicate import org.neo4j.graphalgo.impl.path.ShortestPath.ShortestPathPredicate
import org.neo4j.graphdb._ import org.neo4j.graphdb._
import org.neo4j.graphdb.security.URLAccessValidationError import org.neo4j.graphdb.security.URLAccessValidationError
import org.neo4j.graphdb.traversal.{Evaluators, TraversalDescription, Uniqueness} import org.neo4j.graphdb.traversal.{Evaluators, TraversalDescription, Uniqueness}
import org.neo4j.internal.kernel.api._ import org.neo4j.internal.kernel.api._
import org.neo4j.internal.kernel.api.helpers.RelationshipSelections.selectionCursor
import org.neo4j.internal.kernel.api.helpers._ import org.neo4j.internal.kernel.api.helpers._
import org.neo4j.kernel.GraphDatabaseQueryService import org.neo4j.kernel.GraphDatabaseQueryService
import org.neo4j.kernel.api.exceptions.ProcedureException import org.neo4j.kernel.api.exceptions.ProcedureException
Expand Down Expand Up @@ -172,78 +172,40 @@ final class TransactionBoundQueryContext(val transactionalContext: Transactional
else tokenWrite.labelGetOrCreateForName(labelName) else tokenWrite.labelGetOrCreateForName(labelName)
} }


private def selectRelationships(nodeCursor: NodeCursor, dir: SemanticDirection, types: Option[Array[Int]]) = { def getRelationshipsForIds(node: Long, dir: SemanticDirection,
val cursors = transactionalContext.kernelTransaction.cursors() types: Option[Array[Int]]): Iterator[RelationshipValue] = {
val read = reads()
read.singleNode(node, nodeCursor)
if (!nodeCursor.next()) return Iterator.empty
val factory = new RelationshipFactory[RelationshipValue] { val factory = new RelationshipFactory[RelationshipValue] {
override def relationship(id: Long, startNodeId: Long, typeId: Int, override def relationship(id: Long, startNodeId: Long, typeId: Int,
endNodeId: Long): RelationshipValue = endNodeId: Long): RelationshipValue =
fromRelationshipProxy(entityAccessor.newRelationshipProxy(id, startNodeId, typeId, endNodeId)) fromRelationshipProxy(entityAccessor.newRelationshipProxy(id, startNodeId, typeId, endNodeId))
} }
if (nodeCursor.isDense) {
val groupCursor = cursors.allocateRelationshipGroupCursor()
nodeCursor.relationships(groupCursor)
val traversalCursor = cursors.allocateRelationshipTraversalCursor()
val denseSelectionIterator = new RelationshipDenseSelectionIterator[RelationshipValue](factory)
dir match {
case OUTGOING => denseSelectionIterator.outgoing(groupCursor, traversalCursor, types.orNull)
case INCOMING => denseSelectionIterator.incoming(groupCursor, traversalCursor, types.orNull)
case BOTH => denseSelectionIterator.all(groupCursor, traversalCursor, types.orNull)
}
denseSelectionIterator
} else {
val traversalCursor = cursors.allocateRelationshipTraversalCursor()
nodeCursor.allRelationships(traversalCursor)
val sparseSelectionIterator = new RelationshipSparseSelectionIterator[RelationshipValue](factory)
dir match {
case OUTGOING => sparseSelectionIterator.outgoing(traversalCursor, types.orNull)
case INCOMING => sparseSelectionIterator.incoming(traversalCursor, types.orNull)
case BOTH => sparseSelectionIterator.all(traversalCursor, types.orNull)
}
sparseSelectionIterator
}
}


private def selectRelationshipsPrimitive(nodeCursor: NodeCursor, dir: SemanticDirection, types: Option[Array[Int]]) = { val cursor = selectionCursor(transactionalContext.kernelTransaction.cursors(), nodeCursor,
val cursors = transactionalContext.kernelTransaction.cursors() toGraphDb(dir), types.orNull)
if (nodeCursor.isDense) { new CursorIterator[RelationshipValue] {
val groupCursor = cursors.allocateRelationshipGroupCursor()
nodeCursor.relationships(groupCursor)
val traversalCursor = cursors.allocateRelationshipTraversalCursor()
val denseSelectionCursor = new RelationshipDenseSelectionCursor()
dir match {
case OUTGOING => denseSelectionCursor.outgoing(groupCursor, traversalCursor, types.orNull)
case INCOMING => denseSelectionCursor.incoming(groupCursor, traversalCursor, types.orNull)
case BOTH => denseSelectionCursor.all(groupCursor, traversalCursor, types.orNull)
}
denseSelectionCursor
} else {
val traversalCursor = cursors.allocateRelationshipTraversalCursor()
nodeCursor.allRelationships(traversalCursor)
val sparseSelectionCursor = new RelationshipSparseSelectionCursor()
dir match {
case OUTGOING => sparseSelectionCursor.outgoing(traversalCursor, types.orNull)
case INCOMING => sparseSelectionCursor.incoming(traversalCursor, types.orNull)
case BOTH => sparseSelectionCursor.all(traversalCursor, types.orNull)
}
sparseSelectionCursor
}
}


def getRelationshipsForIds(node: Long, dir: SemanticDirection, override protected def close(): Unit = cursor.close()
types: Option[Array[Int]]): Iterator[RelationshipValue] = {
val read = reads()
read.singleNode(node, nodeCursor)
if (!nodeCursor.next()) return Iterator.empty


selectRelationships(nodeCursor, dir, types).asScala override protected def fetchNext(): RelationshipValue =
if (cursor.next())
fromRelationshipProxy(entityAccessor.newRelationshipProxy(cursor.relationshipReference(),
cursor.sourceNodeReference(),
cursor.`type`(),
cursor.targetNodeReference()))
else null
}
} }


override def getRelationshipsForIdsPrimitive(node: Long, dir: SemanticDirection, override def getRelationshipsForIdsPrimitive(node: Long, dir: SemanticDirection,
types: Option[Array[Int]]): RelationshipIterator = { types: Option[Array[Int]]): RelationshipIterator = {
val read = reads() val read = reads()
read.singleNode(node, nodeCursor) read.singleNode(node, nodeCursor)
if (!nodeCursor.next()) RelationshipIterator.EMPTY if (!nodeCursor.next()) RelationshipIterator.EMPTY
else new RelationshipCursorIterator(selectRelationshipsPrimitive(nodeCursor, dir, types)) else new RelationshipCursorIterator(
selectionCursor(transactionalContext.kernelTransaction.cursors(), nodeCursor, toGraphDb(dir), types.orNull))
} }


override def getRelationshipFor(relationshipId: Long, typeId: Int, startNodeId: Long, override def getRelationshipFor(relationshipId: Long, typeId: Int, startNodeId: Long,
Expand Down
@@ -0,0 +1,156 @@
/*
* Copyright (c) 2002-2018 "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 <http://www.gnu.org/licenses/>.
*/
package org.neo4j.internal.kernel.api.helpers;

import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.ResourceIterator;
import org.neo4j.internal.kernel.api.CursorFactory;
import org.neo4j.internal.kernel.api.NodeCursor;
import org.neo4j.internal.kernel.api.RelationshipGroupCursor;
import org.neo4j.internal.kernel.api.RelationshipTraversalCursor;

/**
* Utilities for dealing with RelationshipSelectionCursor and corresponding iterators.
*/
public final class RelationshipSelections
{
private RelationshipSelections()
{
throw new UnsupportedOperationException( "Do not instantiate" );
}

/**
* Returns a selection cursor given the provided node cursor, direction and relationship types.
*
* @param cursors A cursor factor used for allocating the needed cursors
* @param node A node cursor positioned at the current node.
* @param direction The direction of the the relationship.
* @param types The types of the relationship
* @return A cursor that allows traversing the relationship chain.
*/
public static RelationshipSelectionCursor selectionCursor( CursorFactory cursors, NodeCursor node,
Direction direction, int[] types )
{
if ( node.isDense() )
{
RelationshipDenseSelectionCursor selectionCursor = new RelationshipDenseSelectionCursor();
setupDense( selectionCursor, cursors, node, direction, types );
return selectionCursor;
}
else
{
RelationshipSparseSelectionCursor selectionCursor = new RelationshipSparseSelectionCursor();

setupSparse( selectionCursor, cursors, node, direction, types );
return selectionCursor;
}
}

/**
* Returns a resource iterator given the provided node cursor, direction and relationship types.
*
* @param cursors A cursor factor used for allocating the needed cursors
* @param node A node cursor positioned at the current node.
* @param direction The direction of the the relationship.
* @param types The types of the relationship
* @param factory factory for creating instance of generic type T
* @return An iterator that allows traversing the relationship chain.
*/
public static <T> ResourceIterator<T> selectionIterator( CursorFactory cursors, NodeCursor node,
Direction direction, int[] types, RelationshipFactory<T> factory )
{
if ( node.isDense() )
{
RelationshipDenseSelectionIterator<T> selectionIterator =
new RelationshipDenseSelectionIterator<>( factory );
setupDense( selectionIterator, cursors, node, direction, types );
return selectionIterator;
}
else
{
RelationshipSparseSelectionIterator<T> selectionIterator =
new RelationshipSparseSelectionIterator<>( factory );

setupSparse( selectionIterator, cursors, node, direction, types );
return selectionIterator;
}
}

private static void setupDense( RelationshipDenseSelection denseSelection, CursorFactory cursors, NodeCursor node,
Direction direction, int[] types )
{

RelationshipGroupCursor groupCursor = cursors.allocateRelationshipGroupCursor();
RelationshipTraversalCursor traversalCursor = cursors.allocateRelationshipTraversalCursor();
try
{
node.relationships( groupCursor );
switch ( direction )
{
case OUTGOING:
denseSelection.outgoing( groupCursor, traversalCursor, types );
break;
case INCOMING:
denseSelection.incoming( groupCursor, traversalCursor, types );
break;
case BOTH:
denseSelection.all( groupCursor, traversalCursor, types );
break;
default:
throw new IllegalStateException( "Unknown direction: " + direction );
}
}
catch ( Throwable t )
{
groupCursor.close();
traversalCursor.close();
throw t;
}
}

private static void setupSparse( RelationshipSparseSelection sparseSelection,
CursorFactory cursors, NodeCursor node, Direction direction, int[] types )
{
RelationshipTraversalCursor traversalCursor = cursors.allocateRelationshipTraversalCursor();
try
{
node.allRelationships( traversalCursor );
switch ( direction )
{
case OUTGOING:
sparseSelection.outgoing( traversalCursor, types );
break;
case INCOMING:
sparseSelection.incoming( traversalCursor, types );
break;
case BOTH:
sparseSelection.all( traversalCursor, types );
break;
default:
throw new IllegalStateException( "Unknown direction: " + direction );
}
}
catch ( Throwable t )
{
traversalCursor.close();
throw t;
}
}
}

0 comments on commit e966ec1

Please sign in to comment.