Skip to content

Commit

Permalink
Add IndexCapability and CapableIndexReference
Browse files Browse the repository at this point in the history
First step toward providing index backed ORDER BY in cypher.
IndexCapability answer the questions:
 - Can I get the actual property values from this index?
 - What ordering of index query results does this index naturally provide?

IndexCapability describe the functional capabilities of a given index.
Each schema index rule stored in schema store will have it's own
capabilities depending on index type (unique, general), index description
(label, properties) and index provider.

Right now IndexCapability is decided by the SchemaIndexProvider
backing the given index.

IndexCapability can not change for a given index during its lifetime.
  • Loading branch information
burqen committed Nov 16, 2017
1 parent ab31efb commit e257c37
Show file tree
Hide file tree
Showing 41 changed files with 602 additions and 104 deletions.
@@ -0,0 +1,41 @@
package org.neo4j.internal.kernel.api;

import org.neo4j.values.storable.ValueGroup;

public interface CapableIndexReference extends IndexReference, IndexCapability
{
CapableIndexReference NO_INDEX = new CapableIndexReference()
{
IndexReference noIndexReference = IndexReference.NO_INDEX;

@Override
public IndexOrderCapability[] order( ValueGroup... valueGroups )
{
return new IndexOrderCapability[0];
}

@Override
public IndexValueCapability value( ValueGroup... valueGroups )
{
return IndexValueCapability.NO;
}

@Override
public boolean isUnique()
{
return noIndexReference.isUnique();
}

@Override
public int label()
{
return noIndexReference.label();
}

@Override
public int[] properties()
{
return noIndexReference.properties();
}
};
}
@@ -0,0 +1,74 @@
/*
* Copyright (c) 2002-2017 "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;

import org.neo4j.values.storable.ValueGroup;

/**
* Capabilities of an index.
* Capabilities of an index can not change during the indexes lifetimes.
* Caching of IndexCapability is allowed.
* It does NOT describe the capabilities of the index at some given moment. For example it does not describe
* index state. Rather it describe the functionality that index provide given that it is available.
*/
public interface IndexCapability
{
/**
* What possible orderings is this index capable to provide for a query on given combination of {@link ValueGroup}.
* Ordering of ValueGroup correspond to ordering of related {@link IndexReference#properties()}.
*
* @param valueGroups Ordered array of {@link ValueGroup ValueGroups} for which index should be queried. Note that valueGroup
* must correspond to related {@link IndexReference#properties()}. A {@code null} value in the array
* ({@code new ValueGroup[]{null}}) is interpreted as a wildcard for any {@link ValueGroup}. Note that this is not the same as
* {@code order(null)} which is undefined.
* @return {@link IndexOrderCapability} array containing all possible orderings for provided value groups or empty array if no explicit
* ordering is possible or if length of {@code valueGroups} and {@link IndexReference#properties()} differ.
*/
IndexOrderCapability[] order( ValueGroup... valueGroups );

/**
* Is the index capable of providing values for a query on given combination of {@link ValueGroup}.
* Ordering of ValueGroup correspond to ordering of {@code properties} in related {@link IndexReference}.
*
* @param valueGroups Ordered array of {@link ValueGroup ValueGroups} for which index should be queried. Note that valueGroup
* must correspond to related {@link IndexReference#properties()}. A {@code null} value in the array
* ({@code new ValueGroup[]{null}}) is interpreted as a wildcard for any {@link ValueGroup}. Note that this is not the same as
* {@code order(null)} which is undefined.
* @return {@link IndexValueCapability#YES} if index is capable of providing values for query on provided array of value groups,
* {@link IndexValueCapability#NO} if not or {@link IndexValueCapability#MAYBE} for some results. If length of
* {@code valueGroups} and {@link IndexReference#properties()} differ {@link IndexValueCapability#NO} is returned.
*/
IndexValueCapability value( ValueGroup... valueGroups );

IndexCapability NO_CAPABILITY = new IndexCapability()
{
@Override
public IndexOrderCapability[] order( ValueGroup... valueGroups )
{
return new IndexOrderCapability[0];
}

@Override
public IndexValueCapability value( ValueGroup... valueGroups )
{
return IndexValueCapability.NO;
}
};
}
@@ -0,0 +1,25 @@
/*
* Copyright (c) 2002-2017 "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;

public enum IndexOrderCapability
{
ASCENDING, DESCENDING
}
@@ -0,0 +1,25 @@
/*
* Copyright (c) 2002-2017 "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;

public enum IndexValueCapability
{
YES, NO, MAYBE
}
Expand Up @@ -31,5 +31,5 @@ public interface SchemaRead
* @param properties the index properties
* @return the IndexReference, or {@link IndexReference#NO_INDEX} if such an index does not exist.
*/
IndexReference index( int label, int... properties );
CapableIndexReference index( int label, int... properties );
}
Expand Up @@ -300,9 +300,9 @@ public void shouldGetNoIndex() throws Exception
int badLabel = token.nodeLabel( "BAD_LABEL" );
int badProp = token.propertyKey( "badProp" );

assertEquals( "bad label", IndexReference.NO_INDEX, schemaRead.index( badLabel, prop ) );
assertEquals( "bad prop", IndexReference.NO_INDEX, schemaRead.index( label, badProp ) );
assertEquals( "just bad", IndexReference.NO_INDEX, schemaRead.index( badLabel, badProp ) );
assertEquals( "bad label", CapableIndexReference.NO_INDEX, schemaRead.index( badLabel, prop ) );
assertEquals( "bad prop", CapableIndexReference.NO_INDEX, schemaRead.index( label, badProp ) );
assertEquals( "just bad", CapableIndexReference.NO_INDEX, schemaRead.index( badLabel, badProp ) );
}

private long nodeWithProp( GraphDatabaseService graphDb, Object value )
Expand Down
Expand Up @@ -25,6 +25,7 @@

import org.neo4j.graphdb.ResourceIterator;
import org.neo4j.helpers.collection.Iterators;
import org.neo4j.internal.kernel.api.IndexCapability;
import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.io.pagecache.PageCache;
import org.neo4j.kernel.api.schema.index.IndexDescriptor;
Expand Down Expand Up @@ -141,6 +142,12 @@ public InternalIndexState getInitialState( long indexId, IndexDescriptor descrip
return InternalIndexState.POPULATING;
}

@Override
public IndexCapability getCapability( IndexDescriptor indexDescriptor )
{
return IndexCapability.NO_CAPABILITY;
}

@Override
public StoreMigrationParticipant storeMigrationParticipant( FileSystemAbstraction fs,
PageCache pageCache )
Expand Down Expand Up @@ -208,6 +215,13 @@ public abstract IndexAccessor getOnlineAccessor( long indexId, IndexDescriptor d
*/
public abstract InternalIndexState getInitialState( long indexId, IndexDescriptor descriptor );

/**
* Return {@link IndexCapability} for this index provider for a given {@link IndexDescriptor}.
*
* @param indexDescriptor {@link IndexDescriptor} to get IndexCapability for.
*/
public abstract IndexCapability getCapability( IndexDescriptor indexDescriptor );

/**
* @return a description of this index provider
*/
Expand Down
Expand Up @@ -24,6 +24,7 @@
import java.util.concurrent.Future;

import org.neo4j.graphdb.ResourceIterator;
import org.neo4j.internal.kernel.api.IndexCapability;
import org.neo4j.kernel.api.exceptions.index.IndexActivationFailedKernelException;
import org.neo4j.kernel.api.exceptions.index.IndexEntryConflictException;
import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException;
Expand Down Expand Up @@ -66,6 +67,12 @@ public InternalIndexState getState()
return getDelegate().getState();
}

@Override
public IndexCapability getIndexCapability()
{
return getDelegate().getIndexCapability();
}

@Override
public IndexDescriptor getDescriptor()
{
Expand Down
Expand Up @@ -21,6 +21,7 @@

import java.util.concurrent.Future;

import org.neo4j.internal.kernel.api.IndexCapability;
import org.neo4j.kernel.api.index.IndexUpdater;
import org.neo4j.kernel.api.index.SchemaIndexProvider;
import org.neo4j.kernel.api.schema.LabelSchemaDescriptor;
Expand All @@ -34,14 +35,18 @@
public abstract class AbstractSwallowingIndexProxy implements IndexProxy
{
private final IndexDescriptor descriptor;
private final IndexCapability indexCapability;
private final SchemaIndexProvider.Descriptor providerDescriptor;
private final IndexPopulationFailure populationFailure;

public AbstractSwallowingIndexProxy( IndexDescriptor descriptor,
SchemaIndexProvider.Descriptor providerDescriptor, IndexPopulationFailure populationFailure )
AbstractSwallowingIndexProxy( IndexDescriptor descriptor,
SchemaIndexProvider.Descriptor providerDescriptor,
IndexCapability indexCapability,
IndexPopulationFailure populationFailure )
{
this.descriptor = descriptor;
this.providerDescriptor = providerDescriptor;
this.indexCapability = indexCapability;
this.populationFailure = populationFailure;
}

Expand Down Expand Up @@ -75,6 +80,12 @@ public void force()
{
}

@Override
public IndexCapability getIndexCapability()
{
return indexCapability;
}

@Override
public IndexDescriptor getDescriptor()
{
Expand Down
Expand Up @@ -24,6 +24,7 @@
import java.util.concurrent.Future;

import org.neo4j.graphdb.ResourceIterator;
import org.neo4j.internal.kernel.api.IndexCapability;
import org.neo4j.kernel.api.exceptions.index.IndexPopulationFailedKernelException;
import org.neo4j.kernel.api.index.IndexPopulator;
import org.neo4j.kernel.api.index.InternalIndexState;
Expand All @@ -42,15 +43,16 @@ public class FailedIndexProxy extends AbstractSwallowingIndexProxy
private final IndexCountsRemover indexCountsRemover;
private final Log log;

public FailedIndexProxy( IndexDescriptor descriptor,
SchemaIndexProvider.Descriptor providerDescriptor,
String indexUserDescription,
IndexPopulator populator,
IndexPopulationFailure populationFailure,
IndexCountsRemover indexCountsRemover,
LogProvider logProvider )
FailedIndexProxy( IndexDescriptor descriptor,
SchemaIndexProvider.Descriptor providerDescriptor,
IndexCapability indexCapability,
String indexUserDescription,
IndexPopulator populator,
IndexPopulationFailure populationFailure,
IndexCountsRemover indexCountsRemover,
LogProvider logProvider )
{
super( descriptor, providerDescriptor, populationFailure );
super( descriptor, providerDescriptor, indexCapability, populationFailure );
this.populator = populator;
this.indexUserDescription = indexUserDescription;
this.indexCountsRemover = indexCountsRemover;
Expand Down
Expand Up @@ -19,6 +19,7 @@
*/
package org.neo4j.kernel.impl.api.index;

import org.neo4j.internal.kernel.api.IndexCapability;
import org.neo4j.kernel.api.index.IndexPopulator;
import org.neo4j.kernel.api.index.SchemaIndexProvider;
import org.neo4j.kernel.api.schema.index.IndexDescriptor;
Expand All @@ -30,20 +31,23 @@ public class FailedPopulatingIndexProxyFactory implements FailedIndexProxyFactor
{
private final IndexDescriptor descriptor;
private final SchemaIndexProvider.Descriptor providerDescriptor;
private final IndexCapability indexCapability;
private final IndexPopulator populator;
private final String indexUserDescription;
private final IndexCountsRemover indexCountsRemover;
private final LogProvider logProvider;

FailedPopulatingIndexProxyFactory( IndexDescriptor descriptor,
SchemaIndexProvider.Descriptor providerDescriptor,
IndexCapability indexCapability,
IndexPopulator populator,
String indexUserDescription,
IndexCountsRemover indexCountsRemover,
LogProvider logProvider )
{
this.descriptor = descriptor;
this.providerDescriptor = providerDescriptor;
this.indexCapability = indexCapability;
this.populator = populator;
this.indexUserDescription = indexUserDescription;
this.indexCountsRemover = indexCountsRemover;
Expand All @@ -53,9 +57,7 @@ public class FailedPopulatingIndexProxyFactory implements FailedIndexProxyFactor
@Override
public IndexProxy create( Throwable failure )
{
return
new FailedIndexProxy(
descriptor, providerDescriptor,
indexUserDescription, populator, failure( failure ), indexCountsRemover, logProvider );
return new FailedIndexProxy( descriptor, providerDescriptor, indexCapability, indexUserDescription, populator, failure( failure ),
indexCountsRemover, logProvider );
}
}
Expand Up @@ -28,6 +28,7 @@
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.neo4j.graphdb.ResourceIterator;
import org.neo4j.internal.kernel.api.IndexCapability;
import org.neo4j.kernel.api.exceptions.index.ExceptionDuringFlipKernelException;
import org.neo4j.kernel.api.exceptions.index.FlipFailedKernelException;
import org.neo4j.kernel.api.exceptions.index.IndexActivationFailedKernelException;
Expand Down Expand Up @@ -254,6 +255,20 @@ public InternalIndexState getState()
}
}

@Override
public IndexCapability getIndexCapability()
{
lock.readLock().lock();
try
{
return delegate.getIndexCapability();
}
finally
{
lock.readLock().unlock();
}
}

@Override
public Future<Void> close() throws IOException
{
Expand Down

0 comments on commit e257c37

Please sign in to comment.