Skip to content

Commit

Permalink
ReadOperations.indexQuery now return resource iterator
Browse files Browse the repository at this point in the history
To provide the possibility to close underlying index iterator
without having to exhaust it.
  • Loading branch information
burqen committed Nov 22, 2017
1 parent 564f935 commit cfccb14
Show file tree
Hide file tree
Showing 15 changed files with 310 additions and 79 deletions.
Expand Up @@ -24,12 +24,13 @@

import org.neo4j.graphdb.Resource;
import org.neo4j.graphdb.ResourceIterator;
import org.neo4j.graphdb.ResourceUtils;

public abstract class ResourceClosingIterator<T, V> implements ResourceIterator<V>
{
public static <R> ResourceIterator<R> newResourceIterator( Resource resource, Iterator<R> iterator )
public static <R> ResourceIterator<R> newResourceIterator( Iterator<R> iterator, Resource... resources )
{
return new ResourceClosingIterator<R,R>( resource, iterator )
return new ResourceClosingIterator<R,R>( iterator, resources )
{
@Override
public R map( R elem )
Expand All @@ -39,20 +40,23 @@ public R map( R elem )
};
}

private Resource resource;
private Resource[] resources;
private final Iterator<T> iterator;

ResourceClosingIterator( Resource resource, Iterator<T> iterator )
ResourceClosingIterator( Iterator<T> iterator, Resource... resources )
{
this.resource = resource;
this.resources = resources;
this.iterator = iterator;
}

@Override
public void close()
{
resource.close();
resource = Resource.EMPTY;
if ( resources != null )
{
ResourceUtils.closeAll( resources );
resources = null;
}
}

@Override
Expand Down
Expand Up @@ -374,12 +374,12 @@ ResourceIterator<Relationship> doExpand( Path path, BranchState state )
{
final Node node = path.endNode();
ResourceIterator<Relationship> resourceIterator = asResourceIterator( node.getRelationships().iterator() );
return newResourceIterator( resourceIterator, new FilteringIterator<>( resourceIterator, rel ->
return newResourceIterator( new FilteringIterator<>( resourceIterator, rel ->
{
Exclusion exclude = exclusion.get( rel.getType().name() );
exclude = (exclude == null) ? defaultExclusion : exclude;
return exclude.accept( node, rel );
} ) );
} ), resourceIterator );
}

@Override
Expand Down Expand Up @@ -588,7 +588,7 @@ void buildString( StringBuilder result )
ResourceIterator<Relationship> doExpand( final Path path, BranchState state )
{
ResourceIterator<Relationship> resourceIterator = expander.doExpand( path, state );
return newResourceIterator( resourceIterator, new FilteringIterator<>( resourceIterator, item ->
return newResourceIterator( new FilteringIterator<>( resourceIterator, item ->
{
Path extendedPath = ExtendedPath.extend( path, item );
for ( Filter filter : filters )
Expand All @@ -599,7 +599,7 @@ ResourceIterator<Relationship> doExpand( final Path path, BranchState state )
}
}
return true;
} ) );
} ), resourceIterator );
}

@Override
Expand Down
Expand Up @@ -27,8 +27,10 @@

import org.neo4j.collection.primitive.PrimitiveIntIterator;
import org.neo4j.collection.primitive.PrimitiveLongIterator;
import org.neo4j.collection.primitive.PrimitiveLongResourceIterator;
import org.neo4j.cursor.Cursor;
import org.neo4j.graphdb.Direction;
import org.neo4j.internal.kernel.api.IndexQuery;
import org.neo4j.kernel.api.exceptions.EntityNotFoundException;
import org.neo4j.kernel.api.exceptions.LabelNotFoundKernelException;
import org.neo4j.kernel.api.exceptions.ProcedureException;
Expand All @@ -44,7 +46,6 @@
import org.neo4j.kernel.api.proc.ProcedureSignature;
import org.neo4j.kernel.api.proc.QualifiedName;
import org.neo4j.kernel.api.proc.UserFunctionSignature;
import org.neo4j.internal.kernel.api.IndexQuery;
import org.neo4j.kernel.api.schema.LabelSchemaDescriptor;
import org.neo4j.kernel.api.schema.SchemaDescriptor;
import org.neo4j.kernel.api.schema.constaints.ConstraintDescriptor;
Expand Down Expand Up @@ -126,7 +127,7 @@ public interface ReadOperations
* @return ids of the matching nodes
* @throws org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException if no such index is found.
*/
PrimitiveLongIterator indexQuery( IndexDescriptor index, IndexQuery... predicates )
PrimitiveLongResourceIterator indexQuery( IndexDescriptor index, IndexQuery... predicates )
throws IndexNotFoundKernelException, IndexNotApplicableKernelException;

/**
Expand Down
Expand Up @@ -28,13 +28,16 @@
import org.neo4j.collection.primitive.PrimitiveIntIterator;
import org.neo4j.collection.primitive.PrimitiveIntSet;
import org.neo4j.collection.primitive.PrimitiveLongIterator;
import org.neo4j.collection.primitive.PrimitiveLongResourceIterator;
import org.neo4j.cursor.Cursor;
import org.neo4j.helpers.collection.CastingIterator;
import org.neo4j.helpers.collection.Iterators;
import org.neo4j.internal.kernel.api.IndexQuery;
import org.neo4j.internal.kernel.api.IndexQuery.ExactPredicate;
import org.neo4j.internal.kernel.api.exceptions.KernelException;
import org.neo4j.kernel.api.StatementConstants;
import org.neo4j.kernel.api.exceptions.EntityNotFoundException;
import org.neo4j.kernel.api.exceptions.InvalidTransactionTypeKernelException;
import org.neo4j.internal.kernel.api.exceptions.KernelException;
import org.neo4j.kernel.api.exceptions.explicitindex.AutoIndexingKernelException;
import org.neo4j.kernel.api.exceptions.index.IndexEntryConflictException;
import org.neo4j.kernel.api.exceptions.index.IndexNotApplicableKernelException;
Expand All @@ -49,8 +52,6 @@
import org.neo4j.kernel.api.exceptions.schema.RepeatedPropertyInCompositeSchemaException;
import org.neo4j.kernel.api.exceptions.schema.UnableToValidateConstraintException;
import org.neo4j.kernel.api.exceptions.schema.UniquePropertyValueValidationException;
import org.neo4j.internal.kernel.api.IndexQuery;
import org.neo4j.internal.kernel.api.IndexQuery.ExactPredicate;
import org.neo4j.kernel.api.schema.LabelSchemaDescriptor;
import org.neo4j.kernel.api.schema.RelationTypeSchemaDescriptor;
import org.neo4j.kernel.api.schema.SchemaDescriptor;
Expand Down Expand Up @@ -357,7 +358,7 @@ public PrimitiveLongIterator nodesGetForLabel( KernelStatement state, int labelI
}

@Override
public PrimitiveLongIterator indexQuery( KernelStatement statement, IndexDescriptor index,
public PrimitiveLongResourceIterator indexQuery( KernelStatement statement, IndexDescriptor index,
IndexQuery[] predicates )
throws IndexNotFoundKernelException, IndexNotApplicableKernelException
{
Expand Down
Expand Up @@ -25,9 +25,9 @@
import org.neo4j.collection.primitive.PrimitiveLongCollections;
import org.neo4j.collection.primitive.PrimitiveLongIterator;
import org.neo4j.cursor.Cursor;
import org.neo4j.internal.kernel.api.IndexQuery;
import org.neo4j.kernel.api.exceptions.EntityNotFoundException;
import org.neo4j.kernel.api.index.PropertyAccessor;
import org.neo4j.internal.kernel.api.IndexQuery;
import org.neo4j.kernel.impl.api.operations.EntityOperations;
import org.neo4j.storageengine.api.NodeItem;
import org.neo4j.values.storable.Value;
Expand Down
Expand Up @@ -30,8 +30,11 @@
import org.neo4j.collection.primitive.PrimitiveIntIterator;
import org.neo4j.collection.primitive.PrimitiveLongCollections;
import org.neo4j.collection.primitive.PrimitiveLongIterator;
import org.neo4j.collection.primitive.PrimitiveLongResourceIterator;
import org.neo4j.cursor.Cursor;
import org.neo4j.graphdb.Direction;
import org.neo4j.internal.kernel.api.IndexQuery;
import org.neo4j.internal.kernel.api.exceptions.KernelException;
import org.neo4j.io.pagecache.tracing.cursor.PageCursorTracer;
import org.neo4j.kernel.api.DataWriteOperations;
import org.neo4j.kernel.api.ExecutionStatisticsOperations;
Expand All @@ -45,7 +48,6 @@
import org.neo4j.kernel.api.TokenWriteOperations;
import org.neo4j.kernel.api.exceptions.EntityNotFoundException;
import org.neo4j.kernel.api.exceptions.InvalidTransactionTypeKernelException;
import org.neo4j.internal.kernel.api.exceptions.KernelException;
import org.neo4j.kernel.api.exceptions.LabelNotFoundKernelException;
import org.neo4j.kernel.api.exceptions.ProcedureException;
import org.neo4j.kernel.api.exceptions.PropertyKeyIdNotFoundKernelException;
Expand Down Expand Up @@ -74,7 +76,6 @@
import org.neo4j.kernel.api.proc.QualifiedName;
import org.neo4j.kernel.api.proc.UserFunctionSignature;
import org.neo4j.kernel.api.query.ExecutingQuery;
import org.neo4j.internal.kernel.api.IndexQuery;
import org.neo4j.kernel.api.schema.LabelSchemaDescriptor;
import org.neo4j.kernel.api.schema.RelationTypeSchemaDescriptor;
import org.neo4j.kernel.api.schema.SchemaDescriptor;
Expand Down Expand Up @@ -225,7 +226,7 @@ public PrimitiveLongIterator nodesGetForLabel( int labelId )
}

@Override
public PrimitiveLongIterator indexQuery( IndexDescriptor index, IndexQuery... predicates )
public PrimitiveLongResourceIterator indexQuery( IndexDescriptor index, IndexQuery... predicates )
throws IndexNotFoundKernelException, IndexNotApplicableKernelException
{
statement.assertOpen();
Expand Down
Expand Up @@ -28,10 +28,12 @@
import org.neo4j.collection.primitive.PrimitiveIntIterator;
import org.neo4j.collection.primitive.PrimitiveIntSet;
import org.neo4j.collection.primitive.PrimitiveIntStack;
import org.neo4j.collection.primitive.PrimitiveLongCollections;
import org.neo4j.collection.primitive.PrimitiveLongIterator;
import org.neo4j.collection.primitive.PrimitiveLongResourceIterator;
import org.neo4j.cursor.Cursor;
import org.neo4j.graphdb.NotFoundException;
import org.neo4j.internal.kernel.api.IndexQuery;
import org.neo4j.kernel.api.DataWriteOperations;
import org.neo4j.kernel.api.ExplicitIndex;
import org.neo4j.kernel.api.ExplicitIndexHits;
Expand Down Expand Up @@ -59,7 +61,6 @@
import org.neo4j.kernel.api.index.InternalIndexState;
import org.neo4j.kernel.api.index.SchemaIndexProvider;
import org.neo4j.kernel.api.properties.PropertyKeyIdIterator;
import org.neo4j.internal.kernel.api.IndexQuery;
import org.neo4j.kernel.api.schema.LabelSchemaDescriptor;
import org.neo4j.kernel.api.schema.RelationTypeSchemaDescriptor;
import org.neo4j.kernel.api.schema.SchemaDescriptor;
Expand Down Expand Up @@ -845,51 +846,57 @@ public long nodeGetFromUniqueIndexSeek(
}

@Override
public PrimitiveLongIterator indexQuery( KernelStatement state, IndexDescriptor index, IndexQuery... predicates )
public PrimitiveLongResourceIterator indexQuery( KernelStatement state, IndexDescriptor index, IndexQuery... predicates )
throws IndexNotFoundKernelException, IndexNotApplicableKernelException
{
StorageStatement storeStatement = state.getStoreStatement();
IndexReader reader = storeStatement.getIndexReader( index );
PrimitiveLongIterator committed = reader.query( predicates );
PrimitiveLongResourceIterator committed = reader.query( predicates );
PrimitiveLongIterator exactMatches = reader.hasFullNumberPrecision( predicates )
? committed : LookupFilter.exactIndexMatches( this, state, committed, predicates );

PrimitiveLongIterator result;
IndexQuery firstPredicate = predicates[0];
switch ( firstPredicate.type() )
{
case exact:
IndexQuery.ExactPredicate[] exactPreds = assertOnlyExactPredicates( predicates );
return filterIndexStateChangesForSeek( state, exactMatches, index, IndexQuery.asValueTuple( exactPreds ) );
result = filterIndexStateChangesForSeek( state, exactMatches, index, IndexQuery.asValueTuple( exactPreds ) );
break;

case stringSuffix:
case stringContains:
case exists:
return filterIndexStateChangesForScan( state, exactMatches, index );
result = filterIndexStateChangesForScan( state, exactMatches, index );
break;

case rangeNumeric:
{
assertSinglePredicate( predicates );
IndexQuery.NumberRangePredicate numPred = (IndexQuery.NumberRangePredicate) firstPredicate;
return filterIndexStateChangesForRangeSeekByNumber( state, index, numPred.from(),
result = filterIndexStateChangesForRangeSeekByNumber( state, index, numPred.from(),
numPred.fromInclusive(), numPred.to(), numPred.toInclusive(), exactMatches );
}
break;

case rangeString:
{
assertSinglePredicate( predicates );
IndexQuery.StringRangePredicate strPred = (IndexQuery.StringRangePredicate) firstPredicate;
return filterIndexStateChangesForRangeSeekByString(
result = filterIndexStateChangesForRangeSeekByString(
state, index, strPred.from(), strPred.fromInclusive(), strPred.to(),
strPred.toInclusive(), committed );
break;
}
case stringPrefix:
{
assertSinglePredicate( predicates );
IndexQuery.StringPrefixPredicate strPred = (IndexQuery.StringPrefixPredicate) firstPredicate;
return filterIndexStateChangesForRangeSeekByPrefix( state, index, strPred.prefix(), committed );
result = filterIndexStateChangesForRangeSeekByPrefix( state, index, strPred.prefix(), committed );
break;
}
default:
throw new UnsupportedOperationException( "Query not supported: " + Arrays.toString( predicates ) );
}
return PrimitiveLongCollections.resourceIterator( result, committed );
}

private IndexQuery.ExactPredicate[] assertOnlyExactPredicates( IndexQuery[] predicates )
Expand Down
Expand Up @@ -23,13 +23,14 @@
import org.neo4j.collection.primitive.PrimitiveIntIterator;
import org.neo4j.collection.primitive.PrimitiveIntSet;
import org.neo4j.collection.primitive.PrimitiveLongIterator;
import org.neo4j.collection.primitive.PrimitiveLongResourceIterator;
import org.neo4j.cursor.Cursor;
import org.neo4j.internal.kernel.api.IndexQuery;
import org.neo4j.kernel.api.StatementConstants;
import org.neo4j.kernel.api.exceptions.EntityNotFoundException;
import org.neo4j.kernel.api.exceptions.index.IndexNotApplicableKernelException;
import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException;
import org.neo4j.kernel.api.exceptions.schema.IndexBrokenKernelException;
import org.neo4j.internal.kernel.api.IndexQuery;
import org.neo4j.kernel.api.schema.index.IndexDescriptor;
import org.neo4j.kernel.impl.api.KernelStatement;
import org.neo4j.kernel.impl.api.RelationshipVisitor;
Expand All @@ -56,7 +57,7 @@ public interface EntityReadOperations
* @return ids of the matching nodes
* @throws IndexNotFoundKernelException if no such index is found.
*/
PrimitiveLongIterator indexQuery( KernelStatement statement, IndexDescriptor index, IndexQuery... predicates )
PrimitiveLongResourceIterator indexQuery( KernelStatement statement, IndexDescriptor index, IndexQuery... predicates )
throws IndexNotFoundKernelException, IndexNotApplicableKernelException;

/**
Expand Down
Expand Up @@ -29,6 +29,7 @@

import org.neo4j.collection.primitive.PrimitiveLongCollections;
import org.neo4j.collection.primitive.PrimitiveLongIterator;
import org.neo4j.collection.primitive.PrimitiveLongResourceIterator;
import org.neo4j.function.Suppliers;
import org.neo4j.function.ThrowingAction;
import org.neo4j.graphdb.ConstraintViolationException;
Expand All @@ -40,6 +41,7 @@
import org.neo4j.graphdb.QueryExecutionException;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.Resource;
import org.neo4j.graphdb.ResourceIterable;
import org.neo4j.graphdb.ResourceIterator;
import org.neo4j.graphdb.Result;
Expand All @@ -54,21 +56,21 @@
import org.neo4j.graphdb.traversal.TraversalDescription;
import org.neo4j.helpers.collection.PrefetchingResourceIterator;
import org.neo4j.helpers.collection.ResourceClosingIterator;
import org.neo4j.internal.kernel.api.IndexQuery;
import org.neo4j.internal.kernel.api.exceptions.KernelException;
import org.neo4j.kernel.GraphDatabaseQueryService;
import org.neo4j.kernel.api.KernelTransaction;
import org.neo4j.kernel.api.ReadOperations;
import org.neo4j.kernel.api.Statement;
import org.neo4j.kernel.api.exceptions.EntityNotFoundException;
import org.neo4j.kernel.api.exceptions.InvalidTransactionTypeKernelException;
import org.neo4j.internal.kernel.api.exceptions.KernelException;
import org.neo4j.kernel.api.exceptions.Status;
import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException;
import org.neo4j.kernel.api.exceptions.schema.ConstraintValidationException;
import org.neo4j.kernel.api.exceptions.schema.SchemaKernelException;
import org.neo4j.kernel.api.exceptions.schema.SchemaRuleNotFoundException;
import org.neo4j.kernel.api.explicitindex.AutoIndexing;
import org.neo4j.kernel.api.index.InternalIndexState;
import org.neo4j.internal.kernel.api.IndexQuery;
import org.neo4j.kernel.api.schema.SchemaDescriptorFactory;
import org.neo4j.kernel.api.schema.index.IndexDescriptor;
import org.neo4j.internal.kernel.api.security.SecurityContext;
Expand Down Expand Up @@ -633,7 +635,8 @@ private ResourceIterator<Node> nodesByLabelAndProperty( Label myLabel, String ke
{
// Ha! We found an index - let's use it to find matching nodes
IndexQuery.ExactPredicate query = IndexQuery.exact( descriptor.schema().getPropertyId(), value );
return map2nodes( readOps.indexQuery( descriptor, query ), statement );
PrimitiveLongResourceIterator indexResult = readOps.indexQuery( descriptor, query );
return map2nodes( indexResult, statement, indexResult );
}
}
catch ( KernelException e )
Expand Down Expand Up @@ -686,13 +689,13 @@ private ResourceIterator<Node> allNodesWithLabel( final Label myLabel )

final PrimitiveLongIterator nodeIds = statement.readOperations().nodesGetForLabel( labelId );
return ResourceClosingIterator
.newResourceIterator( statement, map( nodeId -> new NodeProxy( nodeActions, nodeId ), nodeIds ) );
.newResourceIterator( map( nodeId -> new NodeProxy( nodeActions, nodeId ), nodeIds ), statement );
}

private ResourceIterator<Node> map2nodes( PrimitiveLongIterator input, Statement statement )
private ResourceIterator<Node> map2nodes( PrimitiveLongIterator input, Resource... resources )
{
return ResourceClosingIterator
.newResourceIterator( statement, map( id -> new NodeProxy( nodeActions, id ), input ) );
.newResourceIterator( map( id -> new NodeProxy( nodeActions, id ), input ), resources );
}

@Override
Expand Down

0 comments on commit cfccb14

Please sign in to comment.