Skip to content

Commit

Permalink
Support for reading constraints by schema
Browse files Browse the repository at this point in the history
  • Loading branch information
pontusmelke committed Jan 2, 2018
1 parent b3bf06e commit b8b5819
Show file tree
Hide file tree
Showing 8 changed files with 265 additions and 66 deletions.
Expand Up @@ -19,6 +19,11 @@
*/
package org.neo4j.internal.kernel.api;

import java.util.Iterator;

import org.neo4j.internal.kernel.api.schema.SchemaDescriptor;
import org.neo4j.internal.kernel.api.schema.constraints.ConstraintDescriptor;

/**
* Surface for getting schema information, such as fetching specific indexes or constraints.
*/
Expand All @@ -32,4 +37,25 @@ public interface SchemaRead
* @return the IndexReference, or {@link CapableIndexReference#NO_INDEX} if such an index does not exist.
*/
CapableIndexReference index( int label, int... properties );

/**
* Finds all constraints for the given schema
* @param descriptor The descriptor of the schema
* @return All constraints for the given schema
*/
Iterator<ConstraintDescriptor> constraintsGetForSchema( SchemaDescriptor descriptor );

/**
* Checks if a constraint exists
* @param descriptor The descriptor of the constraint to check.
* @return <tt>true</tt> if the constraint exists, otherwise <tt>false</tt>
*/
boolean constraintExists( ConstraintDescriptor descriptor );

/**
* Finds all constraints for the given label
* @param labelId The id of the label
* @return All constraints for the given label
*/
Iterator<ConstraintDescriptor> constraintsGetForLabel( int labelId );
}
@@ -0,0 +1,67 @@
/*
* 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.junit.Test;

import java.util.Iterator;

import org.neo4j.graphdb.Label;
import org.neo4j.internal.kernel.api.schema.LabelSchemaDescriptor;
import org.neo4j.internal.kernel.api.schema.constraints.ConstraintDescriptor;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

@SuppressWarnings( "Duplicates" )
public abstract class ConstraintTestBase<G extends KernelAPIWriteTestSupport> extends KernelAPIWriteTestBase<G>
{
protected abstract LabelSchemaDescriptor labelSchemaDescriptor( int labelId, int... propertyIds );

@Test
public void shouldFindConstraintsBySchema() throws Exception
{
// GIVEN
try ( org.neo4j.graphdb.Transaction tx = graphDb.beginTx() )
{
graphDb.schema().constraintFor( Label.label( "FOO" ) ).assertPropertyIsUnique( "prop" ).create();
tx.success();
}

try ( Transaction tx = session.beginTransaction() )
{
int label = tx.tokenWrite().labelGetOrCreateForName( "FOO" );
int prop = tx.tokenWrite().propertyKeyGetOrCreateForName( "prop" );
LabelSchemaDescriptor descriptor = labelSchemaDescriptor( label, prop );

//WHEN
Iterator<ConstraintDescriptor> constraints =
tx.schemaRead().constraintsGetForSchema( descriptor );

// THEN
ConstraintDescriptor next = constraints.next();
assertTrue( next.enforcesUniqueness() );
assertThat( next.schema(), equalTo( descriptor ) );
assertFalse( constraints.hasNext() );
}
}
}
Expand Up @@ -50,6 +50,7 @@
import org.neo4j.internal.kernel.api.security.SecurityContext;
import org.neo4j.io.pagecache.tracing.cursor.PageCursorTracer;
import org.neo4j.io.pagecache.tracing.cursor.PageCursorTracerSupplier;
import org.neo4j.kernel.api.AssertOpen;
import org.neo4j.kernel.api.KernelTransaction;
import org.neo4j.kernel.api.KeyReadTokenNameLookup;
import org.neo4j.kernel.api.exceptions.ConstraintViolationTransactionFailureException;
Expand Down Expand Up @@ -98,7 +99,7 @@
* as
* {@code TransitionalTxManagementKernelTransaction} is gone from {@code server}.
*/
public class KernelTransactionImplementation implements KernelTransaction, TxStateHolder
public class KernelTransactionImplementation implements KernelTransaction, TxStateHolder, AssertOpen
{
/*
* IMPORTANT:
Expand Down Expand Up @@ -201,8 +202,7 @@ public KernelTransactionImplementation( StatementOperationParts statementOperati
this.statistics = new Statistics( this, cpuClock, heapAllocation );
this.userMetaData = new HashMap<>();
AllStoreHolder allStoreHolder =
new AllStoreHolder( storageEngine, storageStatement, this, cursors, explicitIndexStore,
this::assertOpen );
new AllStoreHolder( storageEngine, storageStatement, this, cursors, explicitIndexStore );
this.operations =
new Operations(
allStoreHolder,
Expand Down Expand Up @@ -467,10 +467,9 @@ private void assertTransactionOpen()

public void assertOpen()
{
Optional<Status> terminationReason = getReasonIfTerminated();
if ( terminationReason.isPresent() )
if ( terminationReason != null )
{
throw new TransactionTerminatedException( terminationReason.get() );
throw new TransactionTerminatedException( terminationReason );
}
}

Expand Down
Expand Up @@ -20,6 +20,7 @@
package org.neo4j.kernel.impl.newapi;

import java.nio.ByteBuffer;
import java.util.Iterator;
import java.util.Map;

import org.neo4j.function.Suppliers;
Expand All @@ -31,8 +32,9 @@
import org.neo4j.internal.kernel.api.exceptions.LabelNotFoundKernelException;
import org.neo4j.internal.kernel.api.exceptions.PropertyKeyIdNotFoundKernelException;
import org.neo4j.internal.kernel.api.exceptions.explicitindex.ExplicitIndexNotFoundKernelException;
import org.neo4j.internal.kernel.api.schema.SchemaDescriptor;
import org.neo4j.internal.kernel.api.schema.constraints.ConstraintDescriptor;
import org.neo4j.io.pagecache.PageCursor;
import org.neo4j.kernel.api.AssertOpen;
import org.neo4j.kernel.api.ExplicitIndex;
import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException;
import org.neo4j.kernel.api.exceptions.schema.IllegalTokenNameException;
Expand All @@ -41,7 +43,7 @@
import org.neo4j.kernel.api.schema.index.IndexDescriptorFactory;
import org.neo4j.kernel.api.txstate.ExplicitIndexTransactionState;
import org.neo4j.kernel.api.txstate.TransactionState;
import org.neo4j.kernel.api.txstate.TxStateHolder;
import org.neo4j.kernel.impl.api.KernelTransactionImplementation;
import org.neo4j.kernel.impl.api.store.PropertyUtil;
import org.neo4j.kernel.impl.index.ExplicitIndexStore;
import org.neo4j.kernel.impl.store.RecordCursor;
Expand Down Expand Up @@ -74,15 +76,14 @@ public class AllStoreHolder extends Read implements Token

public AllStoreHolder( StorageEngine engine,
StorageStatement statement,
TxStateHolder txStateHolder,
KernelTransactionImplementation ktx,
Cursors cursors,
ExplicitIndexStore explicitIndexStore,
AssertOpen assertOpen )
ExplicitIndexStore explicitIndexStore)
{
super( cursors, txStateHolder, assertOpen );
super( cursors, ktx);
this.storeReadLayer = engine.storeReadLayer();
this.statement = statement; // use provided statement, to assert no leakage
this.explicitIndexes = Suppliers.lazySingleton( txStateHolder::explicitIndexTxState );
this.explicitIndexes = Suppliers.lazySingleton( ktx::explicitIndexTxState );

this.nodes = statement.nodes();
this.relationships = statement.relationships();
Expand All @@ -94,7 +95,7 @@ public AllStoreHolder( StorageEngine engine,
@Override
public boolean nodeExists( long id )
{
assertOpen.assertOpen();
ktx.assertOpen();

if ( hasTxStateWithChanges() )
{
Expand Down Expand Up @@ -154,7 +155,7 @@ ExplicitIndex explicitRelationshipIndex( String indexName ) throws ExplicitIndex
@Override
public CapableIndexReference index( int label, int... properties )
{
assertOpen.assertOpen();
ktx.assertOpen();
IndexDescriptor indexDescriptor = storeReadLayer.indexGetForSchema( new LabelSchemaDescriptor( label, properties ) );
if ( indexDescriptor == null )
{
Expand All @@ -172,6 +173,31 @@ public CapableIndexReference index( int label, int... properties )
}
}

@Override
public Iterator<ConstraintDescriptor> constraintsGetForSchema( SchemaDescriptor descriptor )
{
sharedOptimisticLock( descriptor.keyType(), descriptor.keyId() );
ktx.assertOpen();
Iterator<ConstraintDescriptor> constraints = storeReadLayer.constraintsGetForSchema( descriptor );
if ( ktx.hasTxStateWithChanges() )
{
return ktx.txState().constraintsChangesForSchema( descriptor ).apply( constraints );
}
return constraints;
}

@Override
public boolean constraintExists( ConstraintDescriptor descriptor )
{
return false;
}

@Override
public Iterator<ConstraintDescriptor> constraintsGetForLabel( int labelId )
{
return null;
}

@Override
public int labelGetOrCreateForName( String labelName ) throws KernelException
{
Expand Down

0 comments on commit b8b5819

Please sign in to comment.