diff --git a/community/consistency-check/src/main/java/org/neo4j/consistency/checking/full/PropertyAndNodeIndexedCheck.java b/community/consistency-check/src/main/java/org/neo4j/consistency/checking/full/PropertyAndNodeIndexedCheck.java index f6328c29855e6..b68bda1dd31c9 100644 --- a/community/consistency-check/src/main/java/org/neo4j/consistency/checking/full/PropertyAndNodeIndexedCheck.java +++ b/community/consistency-check/src/main/java/org/neo4j/consistency/checking/full/PropertyAndNodeIndexedCheck.java @@ -81,8 +81,7 @@ public void check( NodeRecord record, } /** - * Matches indexes to a node. This implementation mirrors NodeSchemaMatcher.onMatchingSchema(...), but as all - * accessor methods are different, a shared implementation was hard to achieve. + * Matches indexes to a node. */ private void matchIndexesToNode( NodeRecord record, diff --git a/community/consistency-check/src/test/java/org/neo4j/consistency/checking/GraphStoreFixture.java b/community/consistency-check/src/test/java/org/neo4j/consistency/checking/GraphStoreFixture.java index 82f84d6039f3d..9e87886b4b1e8 100644 --- a/community/consistency-check/src/test/java/org/neo4j/consistency/checking/GraphStoreFixture.java +++ b/community/consistency-check/src/test/java/org/neo4j/consistency/checking/GraphStoreFixture.java @@ -43,7 +43,7 @@ import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.pagecache.PageCache; import org.neo4j.io.pagecache.tracing.cursor.context.EmptyVersionContextSupplier; -import org.neo4j.kernel.api.ReadOperations; +import org.neo4j.kernel.api.StatementConstants; import org.neo4j.kernel.api.direct.DirectStoreAccess; import org.neo4j.internal.kernel.api.exceptions.TransactionFailureException; import org.neo4j.kernel.api.labelscan.LabelScanStore; @@ -51,8 +51,8 @@ import org.neo4j.kernel.extension.KernelExtensions; import org.neo4j.kernel.impl.api.TransactionRepresentationCommitProcess; import org.neo4j.kernel.impl.api.TransactionToApply; -import org.neo4j.kernel.impl.api.index.IndexStoreView; import org.neo4j.kernel.impl.api.index.IndexProviderMap; +import org.neo4j.kernel.impl.api.index.IndexStoreView; import org.neo4j.kernel.impl.api.scan.FullLabelStream; import org.neo4j.kernel.impl.factory.DatabaseInfo; import org.neo4j.kernel.impl.index.labelscan.NativeLabelScanStore; @@ -423,7 +423,7 @@ public void delete( PropertyRecord before, PropertyRecord property ) private void updateCounts( NodeRecord node, int delta ) { - writer.incrementNodeCount( ReadOperations.ANY_LABEL, delta ); + writer.incrementNodeCount( StatementConstants.ANY_LABEL, delta ); for ( long label : NodeLabelsField.parseLabelsField( node ).get( nodes ) ) { writer.incrementNodeCount( (int)label, delta ); diff --git a/community/consistency-check/src/test/java/org/neo4j/consistency/checking/full/FullCheckIntegrationTest.java b/community/consistency-check/src/test/java/org/neo4j/consistency/checking/full/FullCheckIntegrationTest.java index 2f4fc1ca20ff2..ca7b6d0e2eb3d 100644 --- a/community/consistency-check/src/test/java/org/neo4j/consistency/checking/full/FullCheckIntegrationTest.java +++ b/community/consistency-check/src/test/java/org/neo4j/consistency/checking/full/FullCheckIntegrationTest.java @@ -133,8 +133,8 @@ import static org.neo4j.graphdb.RelationshipType.withName; import static org.neo4j.helpers.collection.Iterables.asIterable; import static org.neo4j.helpers.collection.MapUtil.stringMap; -import static org.neo4j.kernel.api.ReadOperations.ANY_LABEL; -import static org.neo4j.kernel.api.ReadOperations.ANY_RELATIONSHIP_TYPE; +import static org.neo4j.kernel.api.StatementConstants.ANY_LABEL; +import static org.neo4j.kernel.api.StatementConstants.ANY_RELATIONSHIP_TYPE; import static org.neo4j.kernel.api.labelscan.NodeLabelUpdate.labelChanges; import static org.neo4j.kernel.api.schema.index.SchemaIndexDescriptorFactory.forLabel; import static org.neo4j.kernel.api.schema.index.SchemaIndexDescriptorFactory.uniqueForLabel; diff --git a/community/cypher/interpreted-runtime/src/test/scala/org/neo4j/cypher/internal/runtime/interpreted/TransactionBoundQueryContextTest.scala b/community/cypher/interpreted-runtime/src/test/scala/org/neo4j/cypher/internal/runtime/interpreted/TransactionBoundQueryContextTest.scala index 6ec2cf9e3b883..f95a1deff7971 100644 --- a/community/cypher/interpreted-runtime/src/test/scala/org/neo4j/cypher/internal/runtime/interpreted/TransactionBoundQueryContextTest.scala +++ b/community/cypher/interpreted-runtime/src/test/scala/org/neo4j/cypher/internal/runtime/interpreted/TransactionBoundQueryContextTest.scala @@ -43,10 +43,8 @@ import org.neo4j.kernel.api.security.AnonymousContext import org.neo4j.kernel.impl.api.{ClockContext, KernelStatement, KernelTransactionImplementation, StatementOperationParts} import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge import org.neo4j.kernel.impl.coreapi.{InternalTransaction, PropertyContainerLocker} -import org.neo4j.kernel.impl.factory.CanWrite import org.neo4j.kernel.impl.locking.LockTracer import org.neo4j.kernel.impl.newapi.DefaultCursors -import org.neo4j.kernel.impl.proc.Procedures import org.neo4j.kernel.impl.query.clientconnection.ClientConnectionInfo import org.neo4j.kernel.impl.query.{Neo4jTransactionalContext, Neo4jTransactionalContextFactory} import org.neo4j.storageengine.api.StorageStatement @@ -73,8 +71,7 @@ class TransactionBoundQueryContextTest extends CypherFunSuite { when(kernelTransaction.securityContext()).thenReturn(AUTH_DISABLED) val storeStatement = mock[StorageStatement] val operations = mock[StatementOperationParts](RETURNS_DEEP_STUBS) - statement = new KernelStatement(kernelTransaction, null, storeStatement, new Procedures(), new CanWrite(), - LockTracer.NONE, operations, new ClockContext(), EmptyVersionContextSupplier.EMPTY) + statement = new KernelStatement(kernelTransaction, null, storeStatement, LockTracer.NONE, operations, new ClockContext(), EmptyVersionContextSupplier.EMPTY) statement.initialize(null, PageCursorTracerSupplier.NULL.get()) statement.acquire() } diff --git a/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/Read.java b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/Read.java index 85a90bd253db7..e859201351f94 100644 --- a/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/Read.java +++ b/community/kernel-api/src/main/java/org/neo4j/internal/kernel/api/Read.java @@ -216,6 +216,20 @@ long nodeUniqueIndexSeek( IndexReference index, IndexQuery.ExactPredicate... pre */ long countsForRelationshipWithoutTxState( int startLabelId, int typeId, int endLabelId ); + /** + * Count of the total number of nodes in the database including changes in the current transaction. + * + * @return the total number of nodes in the database + */ + long nodesGetCount( ); + + /** + * Count of the total number of relationships in the database including changes in the current transaction. + * + * @return the total number of relationships in the database + */ + long relationshipsGetCount( ); + /** * @param reference * a reference from {@link RelationshipDataAccessor#relationshipReference()}. diff --git a/community/kernel-api/src/test/java/org/neo4j/internal/kernel/api/helpers/StubRead.java b/community/kernel-api/src/test/java/org/neo4j/internal/kernel/api/helpers/StubRead.java index b231f9c15ff85..66ff7da6c4c5a 100644 --- a/community/kernel-api/src/test/java/org/neo4j/internal/kernel/api/helpers/StubRead.java +++ b/community/kernel-api/src/test/java/org/neo4j/internal/kernel/api/helpers/StubRead.java @@ -127,6 +127,18 @@ public long countsForRelationshipWithoutTxState( int startLabelId, int typeId, i throw new UnsupportedOperationException(); } + @Override + public long nodesGetCount() + { + throw new UnsupportedOperationException(); + } + + @Override + public long relationshipsGetCount() + { + throw new UnsupportedOperationException(); + } + @Override public void singleRelationship( long reference, RelationshipScanCursor cursor ) { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/NeoStoreDataSource.java b/community/kernel/src/main/java/org/neo4j/kernel/NeoStoreDataSource.java index 085839eaae0d6..e78096239757d 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/NeoStoreDataSource.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/NeoStoreDataSource.java @@ -48,8 +48,6 @@ import org.neo4j.kernel.configuration.Config; import org.neo4j.kernel.extension.dependency.AllByPrioritySelectionStrategy; import org.neo4j.kernel.impl.api.CommitProcessFactory; -import org.neo4j.kernel.impl.api.ConstraintEnforcingEntityOperations; -import org.neo4j.kernel.impl.api.DataIntegrityValidatingStatementOperations; import org.neo4j.kernel.impl.api.DatabaseSchemaState; import org.neo4j.kernel.impl.api.ExplicitIndexProviderLookup; import org.neo4j.kernel.impl.api.KernelImpl; @@ -57,12 +55,9 @@ import org.neo4j.kernel.impl.api.KernelTransactionTimeoutMonitor; import org.neo4j.kernel.impl.api.KernelTransactions; import org.neo4j.kernel.impl.api.KernelTransactionsSnapshot; -import org.neo4j.kernel.impl.api.LockingStatementOperations; import org.neo4j.kernel.impl.api.SchemaState; -import org.neo4j.kernel.impl.api.SchemaStateConcern; import org.neo4j.kernel.impl.api.SchemaWriteGuard; import org.neo4j.kernel.impl.api.StackingQueryRegistrationOperations; -import org.neo4j.kernel.impl.api.StateHandlingStatementOperations; import org.neo4j.kernel.impl.api.StatementOperationParts; import org.neo4j.kernel.impl.api.TransactionCommitProcess; import org.neo4j.kernel.impl.api.TransactionHooks; @@ -680,9 +675,9 @@ private NeoStoreKernelModule buildKernel( LogFiles logFiles, TransactionAppender indexConfigStore, kernelProvider, explicitIndexProviderLookup ); StatementOperationParts statementOperationParts = dependencies.satisfyDependency( - buildStatementOperations( storeLayer, autoIndexing, - constraintIndexCreator, databaseSchemaState, explicitIndexStore, cpuClockRef, - heapAllocationRef, indexingService ) ); + buildStatementOperations( + cpuClockRef, + heapAllocationRef ) ); TransactionHooks hooks = new TransactionHooks(); @@ -864,44 +859,13 @@ public DependencyResolver getDependencyResolver() return dependencies; } - private StatementOperationParts buildStatementOperations( StoreReadLayer storeReadLayer, AutoIndexing autoIndexing, - ConstraintIndexCreator constraintIndexCreator, DatabaseSchemaState databaseSchemaState, - ExplicitIndexStore explicitIndexStore, AtomicReference cpuClockRef, - AtomicReference heapAllocationRef, - IndexingService indexingService ) + private StatementOperationParts buildStatementOperations( AtomicReference cpuClockRef, + AtomicReference heapAllocationRef ) { - // The passed in StoreReadLayer is the bottom most layer: Read-access to committed data. - // To it we add: - // + Transaction state handling - StateHandlingStatementOperations stateHandlingContext = new StateHandlingStatementOperations( storeReadLayer, - autoIndexing, constraintIndexCreator, explicitIndexStore, indexingService ); - QueryRegistrationOperations queryRegistrationOperations = new StackingQueryRegistrationOperations( clock, cpuClockRef, heapAllocationRef ); - StatementOperationParts parts = new StatementOperationParts( stateHandlingContext, stateHandlingContext, - stateHandlingContext, stateHandlingContext, stateHandlingContext, stateHandlingContext, - new SchemaStateConcern( databaseSchemaState ), null, stateHandlingContext, stateHandlingContext, - stateHandlingContext, queryRegistrationOperations ); - // + Constraints - ConstraintEnforcingEntityOperations constraintEnforcingEntityOperations = - new ConstraintEnforcingEntityOperations( constraintSemantics, parts.entityWriteOperations(), - parts.entityReadOperations(), - parts.schemaWriteOperations(), parts.schemaReadOperations() ); - // + Data integrity - DataIntegrityValidatingStatementOperations dataIntegrityContext = - new DataIntegrityValidatingStatementOperations( - parts.keyWriteOperations(), parts.schemaReadOperations(), constraintEnforcingEntityOperations ); - parts = parts.override( null, dataIntegrityContext, constraintEnforcingEntityOperations, - constraintEnforcingEntityOperations, null, dataIntegrityContext, null, null, null, null, null, null ); - // + Locking - LockingStatementOperations lockingContext = new LockingStatementOperations( parts.entityReadOperations(), - parts.entityWriteOperations(), parts.schemaReadOperations(), parts.schemaWriteOperations(), - parts.schemaStateOperations() ); - parts = parts.override( null, null, null, lockingContext, lockingContext, lockingContext, lockingContext, - lockingContext, null, null, null, null ); - - return parts; + return new StatementOperationParts( queryRegistrationOperations ); } @Override diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/DataWriteOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/api/DataWriteOperations.java deleted file mode 100644 index 04ef05e68f8ed..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/DataWriteOperations.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.api; - -import org.neo4j.internal.kernel.api.ExplicitIndexWrite; -import org.neo4j.internal.kernel.api.exceptions.EntityNotFoundException; -import org.neo4j.internal.kernel.api.exceptions.InvalidTransactionTypeKernelException; -import org.neo4j.internal.kernel.api.exceptions.KernelException; -import org.neo4j.internal.kernel.api.exceptions.explicitindex.AutoIndexingKernelException; -import org.neo4j.internal.kernel.api.exceptions.explicitindex.ExplicitIndexNotFoundKernelException; -import org.neo4j.internal.kernel.api.exceptions.schema.ConstraintValidationException; -import org.neo4j.values.storable.Value; - -public interface DataWriteOperations extends ExplicitIndexWrite -{ - //=========================================== - //== DATA OPERATIONS ======================== - //=========================================== - - long nodeCreate(); - - void nodeDelete( long nodeId ) - throws EntityNotFoundException, InvalidTransactionTypeKernelException, AutoIndexingKernelException; - - int nodeDetachDelete( long nodeId ) - throws KernelException; - - long relationshipCreate( int relationshipTypeId, long startNodeId, long endNodeId ) - throws EntityNotFoundException; - - void relationshipDelete( long relationshipId ) - throws EntityNotFoundException, InvalidTransactionTypeKernelException, AutoIndexingKernelException; - - /** - * Labels a node with the label corresponding to the given label id. - * If the node already had that label nothing will happen. Label ids are retrieved from - * {@link org.neo4j.kernel.impl.api.operations.KeyWriteOperations#labelGetOrCreateForName(org.neo4j.kernel.api.Statement, String)} - * or {@link - * org.neo4j.kernel.impl.api.operations.KeyReadOperations#labelGetForName(org.neo4j.kernel.api.Statement, String)}. - */ - boolean nodeAddLabel( long nodeId, int labelId ) - throws EntityNotFoundException, ConstraintValidationException; - - /** - * Removes a label with the corresponding id from a node. - * If the node doesn't have that label nothing will happen. Label id are retrieved from - * {@link org.neo4j.kernel.impl.api.operations.KeyWriteOperations#labelGetOrCreateForName(org.neo4j.kernel.api.Statement,String)} - * or {@link - * org.neo4j.kernel.impl.api.operations.KeyReadOperations#labelGetForName(org.neo4j.kernel.api.Statement, String)}. - */ - boolean nodeRemoveLabel( long nodeId, int labelId ) throws EntityNotFoundException; - - Value nodeSetProperty( long nodeId, int propertyKeyId, Value value ) - throws EntityNotFoundException, AutoIndexingKernelException, - InvalidTransactionTypeKernelException, ConstraintValidationException; - - Value relationshipSetProperty( long relationshipId, int propertyKeyId, Value value ) - throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException; - - Value graphSetProperty( int propertyKeyId, Value value ); - - /** - * Remove a node's property given the node's id and the property key id and return the value to which - * it was set or null if it was not set on the node - */ - Value nodeRemoveProperty( long nodeId, int propertyKeyId ) - throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException; - - Value relationshipRemoveProperty( long relationshipId, int propertyKeyId ) - throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException; - - Value graphRemoveProperty( int propertyKeyId ); - - //=========================================== - //== EXPLICIT INDEX OPERATIONS ================ - //=========================================== - - String nodeExplicitIndexSetConfiguration( String indexName, String key, String value ) - throws ExplicitIndexNotFoundKernelException; - - String relationshipExplicitIndexSetConfiguration( String indexName, String key, String value ) - throws ExplicitIndexNotFoundKernelException; - - String nodeExplicitIndexRemoveConfiguration( String indexName, String key ) - throws ExplicitIndexNotFoundKernelException; - - String relationshipExplicitIndexRemoveConfiguration( String indexName, String key ) - throws ExplicitIndexNotFoundKernelException; - - @Override - void nodeAddToExplicitIndex( String indexName, long node, String key, Object value ) - throws ExplicitIndexNotFoundKernelException; - - @Override - void relationshipAddToExplicitIndex( String indexName, long relationship, String key, Object value ) - throws EntityNotFoundException, ExplicitIndexNotFoundKernelException; - - @Override - void relationshipRemoveFromExplicitIndex( String indexName, long relationship, String key, Object value ) - throws ExplicitIndexNotFoundKernelException; - - @Override - void relationshipRemoveFromExplicitIndex( String indexName, long relationship, String key ) - throws ExplicitIndexNotFoundKernelException; - - @Override - void relationshipRemoveFromExplicitIndex( String indexName, long relationship ) - throws ExplicitIndexNotFoundKernelException; - - void nodeExplicitIndexDrop( String indexName ) throws ExplicitIndexNotFoundKernelException; - - void relationshipExplicitIndexDrop( String indexName ) throws ExplicitIndexNotFoundKernelException; -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/KeyReadTokenNameLookup.java b/community/kernel/src/main/java/org/neo4j/kernel/api/KeyReadTokenNameLookup.java deleted file mode 100644 index f17716f76e0ae..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/KeyReadTokenNameLookup.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.api; - -import org.neo4j.internal.kernel.api.TokenNameLookup; -import org.neo4j.internal.kernel.api.exceptions.LabelNotFoundKernelException; -import org.neo4j.internal.kernel.api.exceptions.PropertyKeyIdNotFoundKernelException; -import org.neo4j.kernel.api.exceptions.RelationshipTypeIdNotFoundKernelException; -import org.neo4j.kernel.impl.api.operations.KeyReadOperations; - -/** - * Instances allow looking up ids back to their names. - */ -public final class KeyReadTokenNameLookup implements TokenNameLookup -{ - private final KeyReadOperations read; - - public KeyReadTokenNameLookup( KeyReadOperations read ) - { - this.read = read; - } - - /** - * Returns the label name for the given label id. In case of downstream failure, returns label[id]. - */ - @Override - public String labelGetName( int labelId ) - { - try - { - return read.labelGetName( null, labelId ); - } - catch ( LabelNotFoundKernelException e ) - { - return "[" + labelId + "]"; - } - } - - @Override - public String relationshipTypeGetName( int relTypeId ) - { - try - { - return read.relationshipTypeGetName( null, relTypeId ); - } - catch ( RelationshipTypeIdNotFoundKernelException e ) - { - return "[" + relTypeId + "]"; - } - } - - /** - * Returns the name of a property given its property key id. In case of downstream failure, returns property[id]. - */ - @Override - public String propertyKeyGetName( int propertyKeyId ) - { - try - { - return read.propertyKeyGetName( null, propertyKeyId ); - } - catch ( PropertyKeyIdNotFoundKernelException e ) - { - return "[" + propertyKeyId + "]"; - } - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/ReadOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/api/ReadOperations.java deleted file mode 100644 index 527cb8573e309..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/ReadOperations.java +++ /dev/null @@ -1,513 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.api; - -import java.util.Iterator; -import java.util.Map; -import java.util.Set; -import java.util.function.Function; - -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.internal.kernel.api.InternalIndexState; -import org.neo4j.internal.kernel.api.exceptions.EntityNotFoundException; -import org.neo4j.internal.kernel.api.exceptions.LabelNotFoundKernelException; -import org.neo4j.internal.kernel.api.exceptions.ProcedureException; -import org.neo4j.internal.kernel.api.exceptions.PropertyKeyIdNotFoundKernelException; -import org.neo4j.internal.kernel.api.exceptions.explicitindex.ExplicitIndexNotFoundKernelException; -import org.neo4j.internal.kernel.api.procs.ProcedureHandle; -import org.neo4j.internal.kernel.api.procs.ProcedureSignature; -import org.neo4j.internal.kernel.api.procs.QualifiedName; -import org.neo4j.internal.kernel.api.procs.UserFunctionHandle; -import org.neo4j.internal.kernel.api.procs.UserFunctionSignature; -import org.neo4j.internal.kernel.api.schema.SchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.constraints.ConstraintDescriptor; -import org.neo4j.kernel.api.exceptions.RelationshipTypeIdNotFoundKernelException; -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.kernel.api.exceptions.schema.SchemaRuleNotFoundException; -import org.neo4j.kernel.api.index.IndexProvider; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.impl.api.RelationshipVisitor; -import org.neo4j.kernel.impl.api.operations.KeyReadOperations; -import org.neo4j.kernel.impl.api.store.RelationshipIterator; -import org.neo4j.register.Register.DoubleLongRegister; -import org.neo4j.storageengine.api.NodeItem; -import org.neo4j.storageengine.api.PropertyItem; -import org.neo4j.storageengine.api.RelationshipItem; -import org.neo4j.storageengine.api.Token; -import org.neo4j.storageengine.api.lock.ResourceType; -import org.neo4j.storageengine.api.schema.PopulationProgress; -import org.neo4j.values.storable.Value; - -/** - * Defines all types of read operations that can be done. - */ -public interface ReadOperations -{ - int ANY_LABEL = -1; - int ANY_RELATIONSHIP_TYPE = -1; - - //=========================================== - //== TOKEN OPERATIONS ======================= - //=========================================== - - /** Returns a label id for a label name. If the label doesn't exist, {@link KeyReadOperations#NO_SUCH_LABEL} - * will be returned. */ - int labelGetForName( String labelName ); - - /** Returns the label name for the given label id. */ - String labelGetName( int labelId ) throws LabelNotFoundKernelException; - - /** Returns the labels currently stored in the database * */ - Iterator labelsGetAllTokens(); - /** - * Returns a property key id for the given property key. If the property key doesn't exist, - * {@link StatementConstants#NO_SUCH_PROPERTY_KEY} will be returned. - */ - int propertyKeyGetForName( String propertyKeyName ); - - /** Returns the name of a property given its property key id */ - String propertyKeyGetName( int propertyKeyId ) throws PropertyKeyIdNotFoundKernelException; - - /** Returns the property keys currently stored in the database */ - Iterator propertyKeyGetAllTokens(); - - int relationshipTypeGetForName( String relationshipTypeName ); - - String relationshipTypeGetName( int relationshipTypeId ) throws RelationshipTypeIdNotFoundKernelException; - - /** Returns the relationship types currently stored in the database */ - Iterator relationshipTypesGetAllTokens(); - - int labelCount(); - - int propertyKeyCount(); - - int relationshipTypeCount(); - - //=========================================== - //== DATA OPERATIONS ======================== - //=========================================== - - /** - * @param labelId the label id of the label that returned nodes are guaranteed to have - * @return ids of all nodes that have the given label - */ - PrimitiveLongResourceIterator nodesGetForLabel( int labelId ); - - /** - * Queries the given index with the given index query. - * - * @param index the index to query against. - * @param predicates array of the {@link IndexQuery} predicates to query for. - * @return ids of the matching nodes - * @throws org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException if no such index is found. - */ - PrimitiveLongResourceIterator indexQuery( SchemaIndexDescriptor index, IndexQuery... predicates ) - throws IndexNotFoundKernelException, IndexNotApplicableKernelException; - - /** - * @return an iterator over all nodes in the database. - */ - PrimitiveLongIterator nodesGetAll(); - - /** - * @return an iterator over all relationships in the database. - */ - PrimitiveLongIterator relationshipsGetAll(); - - RelationshipIterator nodeGetRelationships( long nodeId, Direction direction, int[] relTypes ) - throws EntityNotFoundException; - - RelationshipIterator nodeGetRelationships( long nodeId, Direction direction ) throws EntityNotFoundException; - - /** - * Returns node id of unique node found in the given unique index for value or - * {@link StatementConstants#NO_SUCH_NODE} if the index does not contain a - * matching node. - *

- * If a node is found, a READ lock for the index entry will be held. If no node - * is found (if {@link StatementConstants#NO_SUCH_NODE} was returned), a WRITE - * lock for the index entry will be held. This is to facilitate unique creation - * of nodes, to build get-or-create semantics on top of this method. - * - * @throws org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException if no such index found. - */ - long nodeGetFromUniqueIndexSeek( SchemaIndexDescriptor index, IndexQuery.ExactPredicate... predicates ) throws IndexNotFoundKernelException, - IndexBrokenKernelException, IndexNotApplicableKernelException; - - long nodesCountIndexed( SchemaIndexDescriptor index, long nodeId, Value value ) - throws IndexNotFoundKernelException, IndexBrokenKernelException; - - boolean nodeExists( long nodeId ); - - /** - * Checks if a node is labeled with a certain label or not. Returns - * {@code true} if the node is labeled with the label, otherwise {@code false.} - */ - boolean nodeHasLabel( long nodeId, int labelId ) throws EntityNotFoundException; - - int nodeGetDegree( long nodeId, Direction direction, int relType ) throws EntityNotFoundException; - - int nodeGetDegree( long nodeId, Direction direction ) throws EntityNotFoundException; - - boolean nodeIsDense( long nodeId ) throws EntityNotFoundException; - - /** - * Returns all labels set on node with id {@code nodeId}. - * If the node has no labels an empty {@link Iterable} will be returned. - */ - PrimitiveIntIterator nodeGetLabels( long nodeId ) throws EntityNotFoundException; - - PrimitiveIntIterator nodeGetPropertyKeys( long nodeId ) throws EntityNotFoundException; - - PrimitiveIntIterator relationshipGetPropertyKeys( long relationshipId ) throws EntityNotFoundException; - - PrimitiveIntIterator graphGetPropertyKeys(); - - PrimitiveIntIterator nodeGetRelationshipTypes( long nodeId ) throws EntityNotFoundException; - - boolean nodeHasProperty( long nodeId, int propertyKeyId ) throws EntityNotFoundException; - - Value nodeGetProperty( long nodeId, int propertyKeyId ) throws EntityNotFoundException; - - boolean relationshipHasProperty( long relationshipId, int propertyKeyId ) throws EntityNotFoundException; - - Value relationshipGetProperty( long relationshipId, int propertyKeyId ) throws EntityNotFoundException; - - boolean graphHasProperty( int propertyKeyId ); - - Value graphGetProperty( int propertyKeyId ); - - void relationshipVisit( long relId, RelationshipVisitor visitor ) - throws EntityNotFoundException, EXCEPTION; - - long nodesGetCount(); - - long relationshipsGetCount(); - - //=========================================== - //== CURSOR ACCESS OPERATIONS =============== - //=========================================== - - Cursor nodeCursorById( long nodeId ) throws EntityNotFoundException; - - Cursor relationshipCursorById( long relId ) throws EntityNotFoundException; - - Cursor nodeGetProperties( NodeItem node ); - - Cursor relationshipGetProperties( RelationshipItem relationship ); - - //=========================================== - //== SCHEMA OPERATIONS ====================== - //=========================================== - - /** - * Returns the index rule for the given SchemaDescriptor. - */ - SchemaIndexDescriptor indexGetForSchema( SchemaDescriptor descriptor ) - throws SchemaRuleNotFoundException; - - /** Get all indexes for a label. */ - Iterator indexesGetForLabel( int labelId ); - - /** Returns all indexes. */ - Iterator indexesGetAll(); - - /** Retrieve the state of an index. */ - InternalIndexState indexGetState( SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException; - - /** Retrieve provider descriptor for an index. */ - IndexProvider.Descriptor indexGetProviderDescriptor( SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException; - - /** Retrieve the population progress of an index. */ - PopulationProgress indexGetPopulationProgress( SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException; - - /** Get the index size. */ - long indexSize( SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException; - - /** Calculate the index unique values percentage (range: {@code 0.0} exclusive to {@code 1.0} inclusive). */ - double indexUniqueValuesSelectivity( SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException; - - /** Returns the failure description of a failed index. */ - String indexGetFailure( SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException; - - /** - * Get all constraints applicable to label and propertyKey. - */ - Iterator constraintsGetForSchema( SchemaDescriptor descriptor ); - - /** - * Get all constraints applicable to label. - */ - Iterator constraintsGetForLabel( int labelId ); - - /** - * Get all constraints applicable to relationship type. - */ - Iterator constraintsGetForRelationshipType( int typeId ); - - /** - * Get all constraints. - */ - Iterator constraintsGetAll(); - - /** - * Get the owning constraint for a constraint index. Returns null if the index does not have an owning constraint. - */ - Long indexGetOwningUniquenessConstraintId( SchemaIndexDescriptor index ); - - V schemaStateGetOrCreate( K key, Function creator ); - - V schemaStateGet( K key ); - - void schemaStateFlush(); - - //=========================================== - //== LOCKING OPERATIONS ===================== - //=========================================== - - void acquireExclusive( ResourceType type, long... ids ); - - void acquireShared( ResourceType type, long... ids ); - - void releaseExclusive( ResourceType type, long... ids ); - - void releaseShared( ResourceType type, long... ids ); - - //=========================================== - //== EXPLICIT INDEX OPERATIONS ================ - //=========================================== - - /** - * @param indexName name of node index to check for existence. - * @param customConfiguration if {@code null} the configuration of existing won't be matched, otherwise it will - * be matched and a mismatch will throw {@link IllegalArgumentException}. - * @return whether or not node explicit index with name {@code indexName} exists. - * @throws IllegalArgumentException on index existence with provided mismatching {@code customConfiguration}. - */ - boolean nodeExplicitIndexExists( String indexName, Map customConfiguration ); - - /** - * @param indexName name of relationship index to check for existence. - * @param customConfiguration if {@code null} the configuration of existing won't be matched, otherwise it will - * be matched and a mismatch will throw {@link IllegalArgumentException}. - * @return whether or not relationship explicit index with name {@code indexName} exists. - * @throws IllegalArgumentException on index existence with provided mismatching {@code customConfiguration}. - */ - boolean relationshipExplicitIndexExists( String indexName, Map customConfiguration ); - - Map nodeExplicitIndexGetConfiguration( String indexName ) - throws ExplicitIndexNotFoundKernelException; - - Map relationshipExplicitIndexGetConfiguration( String indexName ) - throws ExplicitIndexNotFoundKernelException; - - ExplicitIndexHits nodeExplicitIndexGet( String indexName, String key, Object value ) - throws ExplicitIndexNotFoundKernelException; - - ExplicitIndexHits nodeExplicitIndexQuery( String indexName, String key, Object queryOrQueryObject ) - throws ExplicitIndexNotFoundKernelException; - - ExplicitIndexHits nodeExplicitIndexQuery( String indexName, Object queryOrQueryObject ) - throws ExplicitIndexNotFoundKernelException; - - /** - * @param startNode -1 if ignored. - * @param endNode -1 if ignored. - */ - ExplicitIndexHits relationshipExplicitIndexGet( String name, String key, Object valueOrNull, long startNode, - long endNode ) throws ExplicitIndexNotFoundKernelException; - - /** - * @param startNode -1 if ignored. - * @param endNode -1 if ignored. - */ - ExplicitIndexHits relationshipExplicitIndexQuery( String indexName, String key, Object queryOrQueryObject, - long startNode, long endNode ) - throws ExplicitIndexNotFoundKernelException; - - /** - * @param startNode -1 if ignored. - * @param endNode -1 if ignored. - */ - ExplicitIndexHits relationshipExplicitIndexQuery( String indexName, Object queryOrQueryObject, - long startNode, long endNode ) - throws ExplicitIndexNotFoundKernelException; - - String[] nodeExplicitIndexesGetAll(); - - String[] relationshipExplicitIndexesGetAll(); - - //=========================================== - //== COUNTS OPERATIONS ====================== - //=========================================== - - /** - * The number of nodes in the graph, including anything changed in the transaction state. - * - * If the label parameter is {@link #ANY_LABEL}, this method returns the total number of nodes in the graph, i.e. - * {@code MATCH (n) RETURN count(n)}. - * - * If the label parameter is set to any other value, this method returns the number of nodes that has that label, - * i.e. {@code MATCH (n:LBL) RETURN count(n)}. - * - * @param labelId the label to get the count for, or {@link #ANY_LABEL} to get the total number of nodes. - * @return the number of matching nodes in the graph. - */ - long countsForNode( int labelId ); - - /** - * The number of nodes in the graph, without taking into account anything in the transaction state. - * - * If the label parameter is {@link #ANY_LABEL}, this method returns the total number of nodes in the graph, i.e. - * {@code MATCH (n) RETURN count(n)}. - * - * If the label parameter is set to any other value, this method returns the number of nodes that has that label, - * i.e. {@code MATCH (n:LBL) RETURN count(n)}. - * - * @param labelId the label to get the count for, or {@link #ANY_LABEL} to get the total number of nodes. - * @return the number of matching nodes in the graph. - */ - long countsForNodeWithoutTxState( int labelId ); - - /** - * The number of relationships in the graph, including anything changed in the transaction state. - * - * Returns the number of relationships in the graph that matches the specified pattern, - * {@code (:startLabelId)-[:typeId]->(:endLabelId)}, like so: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
{@code startLabelId}{@code typeId} {@code endLabelId} Pattern
{@link #ANY_LABEL} {@link #ANY_RELATIONSHIP_TYPE} {@link #ANY_LABEL}{@code MATCH} {@code ()-[r]->()} {@code RETURN count(r)}
{@link #ANY_LABEL} {@code REL} {@link #ANY_LABEL}{@code MATCH} {@code ()-[r:REL]->()} {@code RETURN count(r)}
{@code LHS} {@link #ANY_RELATIONSHIP_TYPE} {@link #ANY_LABEL}{@code MATCH} {@code (:LHS)-[r]->()} {@code RETURN count(r)}
{@link #ANY_LABEL} {@link #ANY_RELATIONSHIP_TYPE} {@code RHS}{@code MATCH} {@code ()-[r]->(:RHS)} {@code RETURN count(r)}
{@code LHS} {@code REL} {@link #ANY_LABEL}{@code MATCH} {@code (:LHS)-[r:REL]->()} {@code RETURN count(r)}
{@link #ANY_LABEL} {@code REL} {@code RHS}{@code MATCH} {@code ()-[r:REL]->(:RHS)} {@code RETURN count(r)}
- * - * @param startLabelId the label of the start node of relationships to get the count for, or {@link #ANY_LABEL}. - * @param typeId the type of relationships to get a count for, or {@link #ANY_RELATIONSHIP_TYPE}. - * @param endLabelId the label of the end node of relationships to get the count for, or {@link #ANY_LABEL}. - * @return the number of matching relationships in the graph. - */ - long countsForRelationship( int startLabelId, int typeId, int endLabelId ); - - /** - * The number of relationships in the graph, without taking into account anything in the transaction state. - * - * Returns the number of relationships in the graph that matches the specified pattern, - * {@code (:startLabelId)-[:typeId]->(:endLabelId)}, like so: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
{@code startLabelId}{@code typeId} {@code endLabelId} Pattern
{@link #ANY_LABEL} {@link #ANY_RELATIONSHIP_TYPE} {@link #ANY_LABEL}{@code MATCH} {@code ()-[r]->()} {@code RETURN count(r)}
{@link #ANY_LABEL} {@code REL} {@link #ANY_LABEL}{@code MATCH} {@code ()-[r:REL]->()} {@code RETURN count(r)}
{@code LHS} {@link #ANY_RELATIONSHIP_TYPE} {@link #ANY_LABEL}{@code MATCH} {@code (:LHS)-[r]->()} {@code RETURN count(r)}
{@link #ANY_LABEL} {@link #ANY_RELATIONSHIP_TYPE} {@code RHS}{@code MATCH} {@code ()-[r]->(:RHS)} {@code RETURN count(r)}
{@code LHS} {@code REL} {@link #ANY_LABEL}{@code MATCH} {@code (:LHS)-[r:REL]->()} {@code RETURN count(r)}
{@link #ANY_LABEL} {@code REL} {@code RHS}{@code MATCH} {@code ()-[r:REL]->(:RHS)} {@code RETURN count(r)}
- * - * @param startLabelId the label of the start node of relationships to get the count for, or {@link #ANY_LABEL}. - * @param typeId the type of relationships to get a count for, or {@link #ANY_RELATIONSHIP_TYPE}. - * @param endLabelId the label of the end node of relationships to get the count for, or {@link #ANY_LABEL}. - * @return the number of matching relationships in the graph. - */ - long countsForRelationshipWithoutTxState( int startLabelId, int typeId, int endLabelId ); - - DoubleLongRegister indexUpdatesAndSize( SchemaIndexDescriptor index, DoubleLongRegister target ) - throws IndexNotFoundKernelException; - - DoubleLongRegister indexSample( SchemaIndexDescriptor index, DoubleLongRegister target ) - throws IndexNotFoundKernelException; - - //=========================================== - //== PROCEDURE OPERATIONS =================== - //=========================================== - - /** Fetch a procedure given its signature. */ - ProcedureHandle procedureGet( QualifiedName name ) throws ProcedureException; - - /** Fetch a function given its signature, or empty if no such function exists*/ - UserFunctionHandle functionGet( QualifiedName name ); - - /** Fetch an aggregation function given its signature, or empty if no such function exists*/ - UserFunctionHandle aggregationFunctionGet( QualifiedName name ); - - /** Fetch all registered procedures */ - Set functionsGetAll(); - - /** Fetch all registered procedures */ - Set proceduresGetAll(); -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/SilentTokenNameLookup.java b/community/kernel/src/main/java/org/neo4j/kernel/api/SilentTokenNameLookup.java index cc0d7d1748e86..d1c9968e330cd 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/SilentTokenNameLookup.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/api/SilentTokenNameLookup.java @@ -28,7 +28,6 @@ /** * Instances allow looking up ids back to their names. * - * NOTE: this class will replace StatementTokenNameLookup. */ public final class SilentTokenNameLookup implements TokenNameLookup { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/Statement.java b/community/kernel/src/main/java/org/neo4j/kernel/api/Statement.java index 3670cb7228743..acc2f52f4b286 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/Statement.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/api/Statement.java @@ -20,7 +20,6 @@ package org.neo4j.kernel.api; import org.neo4j.graphdb.Resource; -import org.neo4j.internal.kernel.api.exceptions.InvalidTransactionTypeKernelException; /** * A statement which is a smaller coherent unit of work inside a {@link KernelTransaction}. @@ -29,18 +28,6 @@ */ public interface Statement extends Resource, ResourceManager { - /** - * @return interface exposing all read operations. - */ - ReadOperations readOperations(); - - /** - * @return interface exposing all write operations about data such as nodes, relationships and properties. - * @throws InvalidTransactionTypeKernelException if type of this transaction have already been decided - * and it's of a different type.. - */ - DataWriteOperations dataWriteOperations() throws InvalidTransactionTypeKernelException; - /** * @return interface exposing operations for associating metadata with this statement */ diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/StatementConstants.java b/community/kernel/src/main/java/org/neo4j/kernel/api/StatementConstants.java index 729536b019e25..31b779f10229b 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/StatementConstants.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/api/StatementConstants.java @@ -26,6 +26,8 @@ public final class StatementConstants public static final int NO_SUCH_PROPERTY_KEY = -1; public static final long NO_SUCH_NODE = -1; public static final long NO_SUCH_RELATIONSHIP = -1; + public static final int ANY_LABEL = -1; + public static final int ANY_RELATIONSHIP_TYPE = -1; private StatementConstants() { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/StatementTokenNameLookup.java b/community/kernel/src/main/java/org/neo4j/kernel/api/StatementTokenNameLookup.java deleted file mode 100644 index 730b5e116c613..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/StatementTokenNameLookup.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.api; - -import org.neo4j.internal.kernel.api.TokenNameLookup; -import org.neo4j.internal.kernel.api.exceptions.LabelNotFoundKernelException; -import org.neo4j.internal.kernel.api.exceptions.PropertyKeyIdNotFoundKernelException; -import org.neo4j.kernel.api.exceptions.RelationshipTypeIdNotFoundKernelException; - -/** - * Instances allow looking up ids back to their names. - * - * Deprecated: will be replaced by SilentTokenNameLookup - */ -@Deprecated -public final class StatementTokenNameLookup implements TokenNameLookup -{ - private final ReadOperations statement; - - public StatementTokenNameLookup( ReadOperations statement ) - { - this.statement = statement; - } - - /** - * Returns the label name for the given label id. In case of downstream failure, returns label[id]. - */ - @Override - public String labelGetName( int labelId ) - { - try - { - return statement.labelGetName( labelId ); - } - catch ( LabelNotFoundKernelException e ) - { - return "[" + labelId + "]"; - } - } - - @Override - public String relationshipTypeGetName( int relTypeId ) - { - try - { - return statement.relationshipTypeGetName( relTypeId ); - } - catch ( RelationshipTypeIdNotFoundKernelException e ) - { - return "[" + relTypeId + "]"; - } - } - - /** - * Returns the name of a property given its property key id. In case of downstream failure, returns property[id]. - */ - @Override - public String propertyKeyGetName( int propertyKeyId ) - { - try - { - return statement.propertyKeyGetName( propertyKeyId ); - } - catch ( PropertyKeyIdNotFoundKernelException e ) - { - return "[" + propertyKeyId + "]"; - } - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/schema/SchemaDescriptorFactory.java b/community/kernel/src/main/java/org/neo4j/kernel/api/schema/SchemaDescriptorFactory.java index 2277210245b7d..06c9464a95ded 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/schema/SchemaDescriptorFactory.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/api/schema/SchemaDescriptorFactory.java @@ -19,7 +19,7 @@ */ package org.neo4j.kernel.api.schema; -import org.neo4j.kernel.impl.api.operations.KeyReadOperations; +import org.neo4j.kernel.api.StatementConstants; public class SchemaDescriptorFactory { @@ -45,7 +45,7 @@ private static void validatePropertyIds( int[] propertyIds ) { for ( int propertyId : propertyIds ) { - if ( KeyReadOperations.NO_SUCH_PROPERTY_KEY == propertyId ) + if ( StatementConstants.NO_SUCH_PROPERTY_KEY == propertyId ) { throw new IllegalArgumentException( "Index schema descriptor can't be created for non existent property." ); @@ -55,7 +55,7 @@ private static void validatePropertyIds( int[] propertyIds ) private static void validateRelationshipTypeLabelId( int relType ) { - if ( KeyReadOperations.NO_SUCH_RELATIONSHIP_TYPE == relType ) + if ( StatementConstants.NO_SUCH_RELATIONSHIP_TYPE == relType ) { throw new IllegalArgumentException( "Index schema descriptor can't be created for non existent relationship type." ); @@ -64,7 +64,7 @@ private static void validateRelationshipTypeLabelId( int relType ) private static void validateLabelId( int labelId ) { - if ( KeyReadOperations.NO_SUCH_LABEL == labelId ) + if ( StatementConstants.NO_SUCH_LABEL == labelId ) { throw new IllegalArgumentException( "Index schema descriptor can't be created for non existent label." ); } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/api/txstate/TransactionCountingStateVisitor.java b/community/kernel/src/main/java/org/neo4j/kernel/api/txstate/TransactionCountingStateVisitor.java index 4f92ae8e534f8..5f5816de0d12c 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/api/txstate/TransactionCountingStateVisitor.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/api/txstate/TransactionCountingStateVisitor.java @@ -34,8 +34,8 @@ import org.neo4j.storageengine.api.txstate.ReadableTransactionState; import org.neo4j.storageengine.api.txstate.TxStateVisitor; -import static org.neo4j.kernel.api.ReadOperations.ANY_LABEL; -import static org.neo4j.kernel.api.ReadOperations.ANY_RELATIONSHIP_TYPE; +import static org.neo4j.kernel.api.StatementConstants.ANY_LABEL; +import static org.neo4j.kernel.api.StatementConstants.ANY_RELATIONSHIP_TYPE; public class TransactionCountingStateVisitor extends TxStateVisitor.Delegator { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/ConstraintEnforcingEntityOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/ConstraintEnforcingEntityOperations.java deleted file mode 100644 index fff22cecf5de3..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/ConstraintEnforcingEntityOperations.java +++ /dev/null @@ -1,667 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api; - -import org.apache.commons.lang3.ArrayUtils; - -import java.util.Iterator; - -import org.neo4j.collection.primitive.PrimitiveIntCollections; -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.EntityNotFoundException; -import org.neo4j.internal.kernel.api.exceptions.InvalidTransactionTypeKernelException; -import org.neo4j.internal.kernel.api.exceptions.KernelException; -import org.neo4j.internal.kernel.api.exceptions.explicitindex.AutoIndexingKernelException; -import org.neo4j.internal.kernel.api.exceptions.schema.ConstraintValidationException; -import org.neo4j.internal.kernel.api.schema.LabelSchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.RelationTypeSchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.SchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.constraints.ConstraintDescriptor; -import org.neo4j.kernel.api.StatementConstants; -import org.neo4j.kernel.api.exceptions.index.IndexEntryConflictException; -import org.neo4j.kernel.api.exceptions.index.IndexNotApplicableKernelException; -import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; -import org.neo4j.kernel.api.exceptions.schema.AlreadyConstrainedException; -import org.neo4j.kernel.api.exceptions.schema.AlreadyIndexedException; -import org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException; -import org.neo4j.kernel.api.exceptions.schema.DropConstraintFailureException; -import org.neo4j.kernel.api.exceptions.schema.DropIndexFailureException; -import org.neo4j.kernel.api.exceptions.schema.IndexBrokenKernelException; -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.kernel.api.schema.constaints.IndexBackedConstraintDescriptor; -import org.neo4j.kernel.api.schema.constaints.NodeExistenceConstraintDescriptor; -import org.neo4j.kernel.api.schema.constaints.NodeKeyConstraintDescriptor; -import org.neo4j.kernel.api.schema.constaints.RelExistenceConstraintDescriptor; -import org.neo4j.kernel.api.schema.constaints.UniquenessConstraintDescriptor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.impl.api.operations.EntityOperations; -import org.neo4j.kernel.impl.api.operations.EntityReadOperations; -import org.neo4j.kernel.impl.api.operations.EntityWriteOperations; -import org.neo4j.kernel.impl.api.operations.SchemaReadOperations; -import org.neo4j.kernel.impl.api.operations.SchemaWriteOperations; -import org.neo4j.kernel.impl.api.schema.NodeSchemaMatcher; -import org.neo4j.kernel.impl.api.store.NodeLoadingIterator; -import org.neo4j.kernel.impl.constraints.ConstraintSemantics; -import org.neo4j.kernel.impl.locking.LockTracer; -import org.neo4j.kernel.impl.locking.Locks; -import org.neo4j.kernel.impl.locking.ResourceTypes; -import org.neo4j.storageengine.api.Direction; -import org.neo4j.storageengine.api.NodeItem; -import org.neo4j.storageengine.api.PropertyItem; -import org.neo4j.storageengine.api.RelationshipItem; -import org.neo4j.values.storable.Value; -import org.neo4j.values.storable.Values; - -import static java.lang.String.format; -import static org.neo4j.internal.kernel.api.exceptions.schema.ConstraintValidationException.Phase.VALIDATION; -import static org.neo4j.internal.kernel.api.schema.SchemaDescriptorPredicates.hasProperty; -import static org.neo4j.kernel.api.StatementConstants.NO_SUCH_NODE; -import static org.neo4j.kernel.api.StatementConstants.NO_SUCH_PROPERTY_KEY; -import static org.neo4j.kernel.impl.locking.ResourceTypes.INDEX_ENTRY; -import static org.neo4j.kernel.impl.locking.ResourceTypes.indexEntryResourceId; - -public class ConstraintEnforcingEntityOperations implements EntityOperations, SchemaWriteOperations -{ - private final EntityWriteOperations entityWriteOperations; - private final EntityReadOperations entityReadOperations; - private final SchemaWriteOperations schemaWriteOperations; - private final SchemaReadOperations schemaReadOperations; - private final ConstraintSemantics constraintSemantics; - private final NodeSchemaMatcher nodeSchemaMatcher; - - public ConstraintEnforcingEntityOperations( - ConstraintSemantics constraintSemantics, EntityWriteOperations entityWriteOperations, - EntityReadOperations entityReadOperations, - SchemaWriteOperations schemaWriteOperations, - SchemaReadOperations schemaReadOperations ) - { - this.constraintSemantics = constraintSemantics; - this.entityWriteOperations = entityWriteOperations; - this.entityReadOperations = entityReadOperations; - this.schemaWriteOperations = schemaWriteOperations; - this.schemaReadOperations = schemaReadOperations; - nodeSchemaMatcher = new NodeSchemaMatcher( entityReadOperations ); - } - - @Override - public boolean nodeAddLabel( KernelStatement state, long nodeId, int labelId ) - throws EntityNotFoundException, ConstraintValidationException - { - try ( Cursor cursor = nodeCursorById( state, nodeId ) ) - { - NodeItem node = cursor.get(); - if ( !node.hasLabel( labelId ) ) - { - // no need to verify if the node already had the label - Iterator constraints = schemaReadOperations.constraintsGetForLabel( state, labelId ); - while ( constraints.hasNext() ) - { - ConstraintDescriptor constraint = constraints.next(); - if ( constraint.enforcesUniqueness() ) - { - IndexBackedConstraintDescriptor uniqueConstraint = (IndexBackedConstraintDescriptor) constraint; - ExactPredicate[] propertyValues = getAllPropertyValues( state, uniqueConstraint.schema(), node ); - if ( propertyValues != null ) - { - validateNoExistingNodeWithExactValues( state, uniqueConstraint, propertyValues, node.id() ); - } - } - } - } - } - return entityWriteOperations.nodeAddLabel( state, nodeId, labelId ); - } - - @Override - public Value nodeSetProperty( KernelStatement state, long nodeId, int propertyKeyId, Value value ) - throws EntityNotFoundException, AutoIndexingKernelException, - InvalidTransactionTypeKernelException, ConstraintValidationException - { - try ( Cursor cursor = nodeCursorById( state, nodeId ) ) - { - NodeItem node = cursor.get(); - state.locks().optimistic().acquireShared( state.lockTracer(), ResourceTypes.LABEL, - PrimitiveIntCollections.asLongArray( node.labels() ) ); - Iterator constraints = - getConstraintsInvolvingProperty( state, propertyKeyId ); - Iterator uniquenessConstraints = - new CastingIterator<>( constraints, IndexBackedConstraintDescriptor.class ); - - nodeSchemaMatcher.onMatchingSchema( state, uniquenessConstraints, node, propertyKeyId, - ( constraint, propertyIds ) -> - { - if ( propertyIds.contains( propertyKeyId ) ) - { - Value previousValue = nodeGetProperty( state, node, propertyKeyId ); - if ( value.equals( previousValue ) ) - { - // since we are changing to the same value, there is no need to check - return; - } - } - validateNoExistingNodeWithExactValues( state, constraint, - getAllPropertyValues( state, constraint.schema(), node, propertyKeyId, value ), - node.id() ); - } ); - } - - return entityWriteOperations.nodeSetProperty( state, nodeId, propertyKeyId, value ); - } - - private Iterator getConstraintsInvolvingProperty( KernelStatement state, int propertyId ) - { - Iterator allConstraints = schemaReadOperations.constraintsGetAll( state ); - - return Iterators.filter( hasProperty( propertyId ), allConstraints ); - } - - private ExactPredicate[] getAllPropertyValues( KernelStatement state, SchemaDescriptor schema, NodeItem node ) - { - return getAllPropertyValues( state, schema, node, StatementConstants.NO_SUCH_PROPERTY_KEY, Values.NO_VALUE ); - } - - /** - * Fetch the property values for all properties in schema for a given node. Return these as an exact predicate - * array. - * - * The changedProperty is used to override the store/txState value of the property. This is used when we intend - * to change a property, and that to verify that the post-change values do not validate some constraint. - */ - private ExactPredicate[] getAllPropertyValues( KernelStatement state, SchemaDescriptor schema, NodeItem node, - int changedPropertyKeyId, Value changedValue ) - { - int[] schemaPropertyIds = schema.getPropertyIds(); - ExactPredicate[] values = new ExactPredicate[schemaPropertyIds.length]; - - int nMatched = 0; - Cursor nodePropertyCursor = nodeGetProperties( state, node ); - while ( nodePropertyCursor.next() ) - { - PropertyItem property = nodePropertyCursor.get(); - - int nodePropertyId = property.propertyKeyId(); - int k = ArrayUtils.indexOf( schemaPropertyIds, nodePropertyId ); - if ( k >= 0 ) - { - if ( nodePropertyId != changedPropertyKeyId ) - { - values[k] = IndexQuery.exact( nodePropertyId, property.value() ); - } - nMatched++; - } - } - - if ( changedPropertyKeyId != NO_SUCH_PROPERTY_KEY ) - { - int k = ArrayUtils.indexOf( schemaPropertyIds, changedPropertyKeyId ); - if ( k >= 0 ) - { - values[k] = IndexQuery.exact( changedPropertyKeyId, changedValue ); - nMatched++; - } - } - if ( nMatched < values.length ) - { - return null; - } - return values; - } - - private void validateNoExistingNodeWithExactValues( - KernelStatement state, - IndexBackedConstraintDescriptor constraint, - ExactPredicate[] propertyValues, - long modifiedNode - ) throws ConstraintValidationException - { - try - { - SchemaIndexDescriptor index = constraint.ownedIndexDescriptor(); - assertIndexOnline( state, index ); - - int labelId = index.schema().keyId(); - state.locks().optimistic().acquireExclusive( - state.lockTracer(), - INDEX_ENTRY, - indexEntryResourceId( labelId, propertyValues ) - ); - - long existing = entityReadOperations.nodeGetFromUniqueIndexSeek( state, index, propertyValues ); - if ( existing != NO_SUCH_NODE && existing != modifiedNode ) - { - throw new UniquePropertyValueValidationException( constraint, VALIDATION, - new IndexEntryConflictException( existing, NO_SUCH_NODE, IndexQuery.asValueTuple( propertyValues ) ) ); - } - } - catch ( IndexNotFoundKernelException | IndexBrokenKernelException | IndexNotApplicableKernelException e ) - { - throw new UnableToValidateConstraintException( constraint, e ); - } - } - - private void assertIndexOnline( KernelStatement state, SchemaIndexDescriptor schemaIndexDescriptor ) - throws IndexNotFoundKernelException, IndexBrokenKernelException - { - switch ( schemaReadOperations.indexGetState( state, schemaIndexDescriptor ) ) - { - case ONLINE: - return; - default: - throw new IndexBrokenKernelException( schemaReadOperations.indexGetFailure( state, - schemaIndexDescriptor ) ); - } - } - - // Simply delegate the rest of the invocations - - @Override - public void nodeDelete( KernelStatement state, long nodeId ) - throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException - { - entityWriteOperations.nodeDelete( state, nodeId ); - } - - @Override - public int nodeDetachDelete( KernelStatement state, long nodeId ) throws KernelException - { - return entityWriteOperations.nodeDetachDelete( state, nodeId ); - } - - @Override - public long relationshipCreate( KernelStatement statement, - int relationshipTypeId, - long startNodeId, - long endNodeId ) - throws EntityNotFoundException - { - return entityWriteOperations.relationshipCreate( statement, relationshipTypeId, startNodeId, endNodeId ); - } - - @Override - public void relationshipDelete( KernelStatement state, long relationshipId ) - throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException - { - entityWriteOperations.relationshipDelete( state, relationshipId ); - } - - @Override - public boolean nodeRemoveLabel( KernelStatement state, long nodeId, int labelId ) throws EntityNotFoundException - { - return entityWriteOperations.nodeRemoveLabel( state, nodeId, labelId ); - } - - @Override - public Value relationshipSetProperty( KernelStatement state, long relationshipId, int propertyKeyId, Value value ) - throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException - { - return entityWriteOperations.relationshipSetProperty( state, relationshipId, propertyKeyId, value ); - } - - @Override - public Value graphSetProperty( KernelStatement state, int propertyKeyId, Value value ) - { - return entityWriteOperations.graphSetProperty( state, propertyKeyId, value ); - } - - @Override - public Value nodeRemoveProperty( KernelStatement state, long nodeId, int propertyKeyId ) - throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException - { - return entityWriteOperations.nodeRemoveProperty( state, nodeId, propertyKeyId ); - } - - @Override - public Value relationshipRemoveProperty( KernelStatement state, - long relationshipId, - int propertyKeyId ) throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException - { - return entityWriteOperations.relationshipRemoveProperty( state, relationshipId, propertyKeyId ); - } - - @Override - public Value graphRemoveProperty( KernelStatement state, int propertyKeyId ) - { - return entityWriteOperations.graphRemoveProperty( state, propertyKeyId ); - } - - @Override - public PrimitiveLongResourceIterator nodesGetForLabel( KernelStatement state, int labelId ) - { - return entityReadOperations.nodesGetForLabel( state, labelId ); - } - - @Override - public PrimitiveLongResourceIterator indexQuery( KernelStatement statement, SchemaIndexDescriptor index, - IndexQuery[] predicates ) - throws IndexNotFoundKernelException, IndexNotApplicableKernelException - { - return entityReadOperations.indexQuery( statement, index, predicates ); - } - - @Override - public long nodeGetFromUniqueIndexSeek( - KernelStatement state, - SchemaIndexDescriptor index, - ExactPredicate... predicates ) - throws IndexNotFoundKernelException, IndexBrokenKernelException, IndexNotApplicableKernelException - { - assertIndexOnline( state, index ); - assertPredicatesMatchSchema( index.schema(), predicates ); - int labelId = index.schema().keyId(); - - // If we find the node - hold a shared lock. If we don't find a node - hold an exclusive lock. - // If locks are deferred than both shared and exclusive locks will be taken only at commit time. - Locks.Client locks = state.locks().optimistic(); - LockTracer lockTracer = state.lockTracer(); - long indexEntryId = indexEntryResourceId( labelId, predicates ); - - locks.acquireShared( lockTracer, INDEX_ENTRY, indexEntryId ); - - long nodeId = entityReadOperations.nodeGetFromUniqueIndexSeek( state, index, predicates ); - if ( NO_SUCH_NODE == nodeId ) - { - locks.releaseShared( INDEX_ENTRY, indexEntryId ); - locks.acquireExclusive( lockTracer, INDEX_ENTRY, indexEntryId ); - - nodeId = entityReadOperations.nodeGetFromUniqueIndexSeek( state, index, predicates ); - if ( NO_SUCH_NODE != nodeId ) // we found it under the exclusive lock - { - // downgrade to a shared lock - locks.acquireShared( lockTracer, INDEX_ENTRY, indexEntryId ); - locks.releaseExclusive( INDEX_ENTRY, indexEntryId ); - } - } - return nodeId; - } - - private void assertPredicatesMatchSchema( SchemaDescriptor schema, ExactPredicate[] predicates ) - throws IndexNotApplicableKernelException - { - int[] propertyIds = schema.getPropertyIds(); - if ( propertyIds.length != predicates.length ) - { - throw new IndexNotApplicableKernelException( - format( "The index specifies %d properties, but only %d lookup predicates were given.", - propertyIds.length, predicates.length ) ); - } - for ( int i = 0; i < predicates.length; i++ ) - { - if ( predicates[i].propertyKeyId() != propertyIds[i] ) - { - throw new IndexNotApplicableKernelException( - format( "The index has the property id %d in position %d, but the lookup property id was %d.", - propertyIds[i], i, predicates[i].propertyKeyId() ) ); - } - } - } - - @Override - public long nodesCountIndexed( KernelStatement statement, SchemaIndexDescriptor index, long nodeId, Value value ) - throws IndexNotFoundKernelException, IndexBrokenKernelException - { - return entityReadOperations.nodesCountIndexed( statement, index, nodeId, value ); - } - - @Override - public boolean graphHasProperty( KernelStatement state, int propertyKeyId ) - { - return entityReadOperations.graphHasProperty( state, propertyKeyId ); - } - - @Override - public Value graphGetProperty( KernelStatement state, int propertyKeyId ) - { - return entityReadOperations.graphGetProperty( state, propertyKeyId ); - } - - @Override - public PrimitiveIntIterator graphGetPropertyKeys( KernelStatement state ) - { - return entityReadOperations.graphGetPropertyKeys( state ); - } - - @Override - public long nodeCreate( KernelStatement statement ) - { - return entityWriteOperations.nodeCreate( statement ); - } - - @Override - public PrimitiveLongIterator nodesGetAll( KernelStatement state ) - { - return entityReadOperations.nodesGetAll( state ); - } - - @Override - public PrimitiveLongIterator relationshipsGetAll( KernelStatement state ) - { - return entityReadOperations.relationshipsGetAll( state ); - } - - @Override - public void relationshipVisit( KernelStatement statement, - long relId, RelationshipVisitor visitor ) - throws EntityNotFoundException, EXCEPTION - { - entityReadOperations.relationshipVisit( statement, relId, visitor ); - } - - @Override - public Cursor nodeCursorById( KernelStatement statement, long nodeId ) throws EntityNotFoundException - { - return entityReadOperations.nodeCursorById( statement, nodeId ); - } - - @Override - public Cursor relationshipCursorById( KernelStatement statement, long relId ) throws EntityNotFoundException - { - return entityReadOperations.relationshipCursorById( statement, relId ); - } - - @Override - public Cursor relationshipCursorGetAll( KernelStatement statement ) - { - return entityReadOperations.relationshipCursorGetAll( statement ); - } - - @Override - public Cursor nodeGetProperties( KernelStatement statement, NodeItem node ) - { - return entityReadOperations.nodeGetProperties( statement, node ); - } - - @Override - public Value nodeGetProperty( KernelStatement statement, NodeItem node, int propertyKeyId ) - { - return entityReadOperations.nodeGetProperty( statement, node, propertyKeyId ); - } - - @Override - public boolean nodeHasProperty( KernelStatement statement, NodeItem node, int propertyKeyId ) - { - return entityReadOperations.nodeHasProperty( statement, node, propertyKeyId ); - } - - @Override - public PrimitiveIntSet nodeGetPropertyKeys( KernelStatement statement, NodeItem node ) - { - return entityReadOperations.nodeGetPropertyKeys( statement, node ); - } - - @Override - public Cursor relationshipGetProperties( KernelStatement statement, RelationshipItem relationship ) - { - return entityReadOperations.relationshipGetProperties( statement, relationship ); - } - - @Override - public Value relationshipGetProperty( KernelStatement statement, RelationshipItem relationship, int propertyKeyId ) - { - return entityReadOperations.relationshipGetProperty( statement, relationship, propertyKeyId ); - } - - @Override - public boolean relationshipHasProperty( KernelStatement statement, RelationshipItem relationship, - int propertyKeyId ) - { - return entityReadOperations.relationshipHasProperty( statement, relationship, propertyKeyId ); - } - - @Override - public PrimitiveIntSet relationshipGetPropertyKeys( KernelStatement statement, - RelationshipItem relationship ) - { - return entityReadOperations.relationshipGetPropertyKeys( statement, relationship ); - } - - @Override - public Cursor nodeGetRelationships( KernelStatement statement, NodeItem node, - Direction direction ) - { - return entityReadOperations.nodeGetRelationships( statement, node, direction ); - } - - @Override - public Cursor nodeGetRelationships( KernelStatement statement, NodeItem node, Direction direction, - int[] relTypes ) - { - return entityReadOperations.nodeGetRelationships( statement, node, direction, relTypes ); - } - - @Override - public SchemaIndexDescriptor indexCreate( KernelStatement state, SchemaDescriptor descriptor ) - throws AlreadyIndexedException, AlreadyConstrainedException, RepeatedPropertyInCompositeSchemaException - { - return schemaWriteOperations.indexCreate( state, descriptor ); - } - - @Override - public void indexDrop( KernelStatement state, SchemaIndexDescriptor descriptor ) throws DropIndexFailureException - { - schemaWriteOperations.indexDrop( state, descriptor ); - } - - @Override - public void uniqueIndexDrop( KernelStatement state, SchemaIndexDescriptor descriptor ) throws DropIndexFailureException - { - schemaWriteOperations.uniqueIndexDrop( state, descriptor ); - } - - @Override - public NodeKeyConstraintDescriptor nodeKeyConstraintCreate( KernelStatement state, LabelSchemaDescriptor descriptor ) - throws AlreadyConstrainedException, CreateConstraintFailureException, AlreadyIndexedException, - RepeatedPropertyInCompositeSchemaException - { - Iterator> nodes = new NodeLoadingIterator( nodesGetForLabel( state, descriptor.getLabelId() ), - id -> nodeCursorById( state, id ) ); - constraintSemantics.validateNodeKeyConstraint( nodes, descriptor, - ( node, propertyKey ) -> entityReadOperations.nodeHasProperty( state, node, propertyKey ) ); - return schemaWriteOperations.nodeKeyConstraintCreate( state, descriptor ); - } - - @Override - public UniquenessConstraintDescriptor uniquePropertyConstraintCreate( KernelStatement state, SchemaDescriptor descriptor ) - throws AlreadyConstrainedException, CreateConstraintFailureException, AlreadyIndexedException, - RepeatedPropertyInCompositeSchemaException - { - return schemaWriteOperations.uniquePropertyConstraintCreate( state, descriptor ); - } - - @Override - public NodeExistenceConstraintDescriptor nodePropertyExistenceConstraintCreate( - KernelStatement state, - LabelSchemaDescriptor descriptor - ) throws AlreadyConstrainedException, CreateConstraintFailureException, RepeatedPropertyInCompositeSchemaException - { - Iterator> nodes = new NodeLoadingIterator( nodesGetForLabel( state, descriptor.getLabelId() ), - id -> nodeCursorById( state, id ) ); - constraintSemantics.validateNodePropertyExistenceConstraint( nodes, descriptor, - ( node, propertyKey ) -> entityReadOperations.nodeHasProperty( state, node, propertyKey ) ); - return schemaWriteOperations.nodePropertyExistenceConstraintCreate( state, descriptor ); - } - - @Override - public RelExistenceConstraintDescriptor relationshipPropertyExistenceConstraintCreate( - KernelStatement state, - RelationTypeSchemaDescriptor descriptor - ) throws AlreadyConstrainedException, CreateConstraintFailureException, RepeatedPropertyInCompositeSchemaException - { - try ( Cursor cursor = relationshipCursorGetAll( state ) ) - { - constraintSemantics.validateRelationshipPropertyExistenceConstraint( cursor, descriptor, - ( relationship, propertyKey ) -> entityReadOperations - .relationshipHasProperty( state, relationship, propertyKey ) ); - } - return schemaWriteOperations.relationshipPropertyExistenceConstraintCreate( state, descriptor ); - } - - @Override - public void constraintDrop( KernelStatement state, ConstraintDescriptor constraint ) - throws DropConstraintFailureException - { - schemaWriteOperations.constraintDrop( state, constraint ); - } - - @Override - public long nodesGetCount( KernelStatement statement ) - { - return entityReadOperations.nodesGetCount( statement ); - } - - @Override - public long relationshipsGetCount( KernelStatement statement ) - { - return entityReadOperations.relationshipsGetCount( statement ); - } - - @Override - public boolean nodeExists( KernelStatement statement, long id ) - { - return entityReadOperations.nodeExists( statement, id ); - } - - @Override - public PrimitiveIntSet relationshipTypes( KernelStatement statement, NodeItem nodeItem ) - { - return entityReadOperations.relationshipTypes( statement, nodeItem ); - } - - @Override - public int degree( KernelStatement statement, NodeItem nodeItem, Direction direction ) - { - return entityReadOperations.degree( statement, nodeItem, direction ); - } - - @Override - public int degree( KernelStatement statement, NodeItem nodeItem, Direction direction, int relType ) - { - return entityReadOperations.degree( statement, nodeItem, direction, relType ); - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/CountsRecordState.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/CountsRecordState.java index 92dca9efe595c..accc2117faf38 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/CountsRecordState.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/CountsRecordState.java @@ -33,8 +33,8 @@ import org.neo4j.storageengine.api.StorageCommand; import static java.util.Objects.requireNonNull; -import static org.neo4j.kernel.api.ReadOperations.ANY_LABEL; -import static org.neo4j.kernel.api.ReadOperations.ANY_RELATIONSHIP_TYPE; +import static org.neo4j.kernel.api.StatementConstants.ANY_LABEL; +import static org.neo4j.kernel.api.StatementConstants.ANY_RELATIONSHIP_TYPE; import static org.neo4j.kernel.impl.store.counts.keys.CountsKeyFactory.indexSampleKey; import static org.neo4j.kernel.impl.store.counts.keys.CountsKeyFactory.indexStatisticsKey; import static org.neo4j.kernel.impl.store.counts.keys.CountsKeyFactory.nodeKey; diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/DataIntegrityValidatingStatementOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/DataIntegrityValidatingStatementOperations.java deleted file mode 100644 index 331be509c2d21..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/DataIntegrityValidatingStatementOperations.java +++ /dev/null @@ -1,294 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api; - -import java.util.Arrays; - -import org.neo4j.internal.kernel.api.schema.LabelSchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.RelationTypeSchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.SchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.constraints.ConstraintDescriptor; -import org.neo4j.kernel.api.Statement; -import org.neo4j.kernel.api.StatementTokenNameLookup; -import org.neo4j.kernel.api.exceptions.schema.AlreadyConstrainedException; -import org.neo4j.kernel.api.exceptions.schema.AlreadyIndexedException; -import org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException; -import org.neo4j.kernel.api.exceptions.schema.DropConstraintFailureException; -import org.neo4j.kernel.api.exceptions.schema.DropIndexFailureException; -import org.neo4j.internal.kernel.api.exceptions.schema.IllegalTokenNameException; -import org.neo4j.kernel.api.exceptions.schema.IndexBelongsToConstraintException; -import org.neo4j.kernel.api.exceptions.schema.NoSuchConstraintException; -import org.neo4j.kernel.api.exceptions.schema.NoSuchIndexException; -import org.neo4j.kernel.api.exceptions.schema.RepeatedPropertyInCompositeSchemaException; -import org.neo4j.internal.kernel.api.exceptions.schema.SchemaKernelException.OperationContext; -import org.neo4j.internal.kernel.api.exceptions.schema.TooManyLabelsException; -import org.neo4j.kernel.api.schema.constaints.ConstraintDescriptorFactory; -import org.neo4j.kernel.api.schema.constaints.NodeExistenceConstraintDescriptor; -import org.neo4j.kernel.api.schema.constaints.NodeKeyConstraintDescriptor; -import org.neo4j.kernel.api.schema.constaints.RelExistenceConstraintDescriptor; -import org.neo4j.kernel.api.schema.constaints.UniquenessConstraintDescriptor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.impl.api.operations.KeyWriteOperations; -import org.neo4j.kernel.impl.api.operations.SchemaReadOperations; -import org.neo4j.kernel.impl.api.operations.SchemaWriteOperations; - -import static org.neo4j.internal.kernel.api.exceptions.schema.SchemaKernelException.OperationContext.CONSTRAINT_CREATION; -import static org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor.Type.UNIQUE; - -public class DataIntegrityValidatingStatementOperations implements - KeyWriteOperations, - SchemaWriteOperations -{ - private final KeyWriteOperations keyWriteDelegate; - private final SchemaReadOperations schemaReadDelegate; - private final SchemaWriteOperations schemaWriteDelegate; - - public DataIntegrityValidatingStatementOperations( - KeyWriteOperations keyWriteDelegate, - SchemaReadOperations schemaReadDelegate, - SchemaWriteOperations schemaWriteDelegate ) - { - this.keyWriteDelegate = keyWriteDelegate; - this.schemaReadDelegate = schemaReadDelegate; - this.schemaWriteDelegate = schemaWriteDelegate; - } - - @Override - public int propertyKeyGetOrCreateForName( Statement state, String propertyKey ) - throws IllegalTokenNameException - { - // KISS - but refactor into a general purpose constraint checker later on - return keyWriteDelegate.propertyKeyGetOrCreateForName( state, checkValidTokenName( propertyKey ) ); - } - - @Override - public int relationshipTypeGetOrCreateForName( Statement state, String relationshipTypeName ) - throws IllegalTokenNameException - { - return keyWriteDelegate.relationshipTypeGetOrCreateForName( state, checkValidTokenName( relationshipTypeName ) ); - } - - @Override - public int labelGetOrCreateForName( Statement state, String label ) - throws IllegalTokenNameException, TooManyLabelsException - { - // KISS - but refactor into a general purpose constraint checker later on - return keyWriteDelegate.labelGetOrCreateForName( state, checkValidTokenName( label ) ); - } - - @Override - public void labelCreateForName( KernelStatement state, String labelName, int id ) - throws IllegalTokenNameException, TooManyLabelsException - { - keyWriteDelegate.labelCreateForName( state, labelName, id ); - } - - @Override - public void propertyKeyCreateForName( KernelStatement state, String propertyKeyName, int id ) throws IllegalTokenNameException - { - keyWriteDelegate.propertyKeyCreateForName( state, propertyKeyName, id ); - } - - @Override - public void relationshipTypeCreateForName( KernelStatement state, String relationshipTypeName, int id ) throws IllegalTokenNameException - { - keyWriteDelegate.relationshipTypeCreateForName( state, relationshipTypeName, id ); - } - - @Override - public SchemaIndexDescriptor indexCreate( KernelStatement state, SchemaDescriptor descriptor ) - throws AlreadyIndexedException, AlreadyConstrainedException, RepeatedPropertyInCompositeSchemaException - { - assertValidDescriptor( descriptor, OperationContext.INDEX_CREATION ); - assertIndexDoesNotExist( state, OperationContext.INDEX_CREATION, descriptor ); - return schemaWriteDelegate.indexCreate( state, descriptor ); - } - - @Override - public void indexDrop( KernelStatement state, SchemaIndexDescriptor index ) throws DropIndexFailureException - { - try - { - SchemaIndexDescriptor existingIndex = - schemaReadDelegate.indexGetForSchema( state, index.schema() ); - - if ( existingIndex == null ) - { - throw new NoSuchIndexException( index.schema() ); - } - - if ( existingIndex.type() == UNIQUE ) - { - if ( schemaReadDelegate.indexGetOwningUniquenessConstraintId( state, existingIndex ) != null ) - { - throw new IndexBelongsToConstraintException( index.schema() ); - } - } - } - catch ( IndexBelongsToConstraintException | NoSuchIndexException e ) - { - throw new DropIndexFailureException( index.schema(), e ); - } - schemaWriteDelegate.indexDrop( state, index ); - } - - @Override - public void uniqueIndexDrop( KernelStatement state, SchemaIndexDescriptor index ) throws DropIndexFailureException - { - schemaWriteDelegate.uniqueIndexDrop( state, index ); - } - - @Override - public NodeKeyConstraintDescriptor nodeKeyConstraintCreate( - KernelStatement state, LabelSchemaDescriptor descriptor ) - throws AlreadyConstrainedException, CreateConstraintFailureException, AlreadyIndexedException, - RepeatedPropertyInCompositeSchemaException - { - assertValidDescriptor( descriptor, OperationContext.CONSTRAINT_CREATION ); - ConstraintDescriptor constraint = ConstraintDescriptorFactory.nodeKeyForSchema( descriptor ); - assertConstraintDoesNotExist( state, constraint ); - - // It is not allowed to create node key constraints on indexed label/property pairs - assertIndexDoesNotExist( state, OperationContext.CONSTRAINT_CREATION, descriptor ); - - return schemaWriteDelegate.nodeKeyConstraintCreate( state, descriptor ); - } - - @Override - public UniquenessConstraintDescriptor uniquePropertyConstraintCreate( - KernelStatement state, SchemaDescriptor descriptor ) - throws AlreadyConstrainedException, CreateConstraintFailureException, AlreadyIndexedException, - RepeatedPropertyInCompositeSchemaException - { - assertValidDescriptor( descriptor, OperationContext.CONSTRAINT_CREATION ); - ConstraintDescriptor constraint = ConstraintDescriptorFactory.uniqueForSchema( descriptor ); - assertConstraintDoesNotExist( state, constraint ); - - // It is not allowed to create uniqueness constraints on indexed label/property pairs - assertIndexDoesNotExist( state, OperationContext.CONSTRAINT_CREATION, descriptor ); - - return schemaWriteDelegate.uniquePropertyConstraintCreate( state, descriptor ); - } - - @Override - public NodeExistenceConstraintDescriptor nodePropertyExistenceConstraintCreate( KernelStatement state, - LabelSchemaDescriptor descriptor ) throws AlreadyConstrainedException, CreateConstraintFailureException, - RepeatedPropertyInCompositeSchemaException - { - assertValidDescriptor( descriptor, OperationContext.CONSTRAINT_CREATION ); - ConstraintDescriptor constraint = ConstraintDescriptorFactory.existsForSchema( descriptor ); - assertConstraintDoesNotExist( state, constraint ); - return schemaWriteDelegate.nodePropertyExistenceConstraintCreate( state, descriptor ); - } - - @Override - public RelExistenceConstraintDescriptor relationshipPropertyExistenceConstraintCreate( KernelStatement state, - RelationTypeSchemaDescriptor descriptor ) - throws AlreadyConstrainedException, CreateConstraintFailureException, - RepeatedPropertyInCompositeSchemaException - { - assertValidDescriptor( descriptor, OperationContext.CONSTRAINT_CREATION ); - ConstraintDescriptor constraint = ConstraintDescriptorFactory.existsForSchema( descriptor ); - assertConstraintDoesNotExist( state, constraint ); - return schemaWriteDelegate.relationshipPropertyExistenceConstraintCreate( state, descriptor ); - } - - @Override - public void constraintDrop( KernelStatement state, ConstraintDescriptor descriptor ) throws DropConstraintFailureException - { - try - { - assertConstraintExists( state, descriptor ); - } - catch ( NoSuchConstraintException e ) - { - throw new DropConstraintFailureException( descriptor , e ); - } - schemaWriteDelegate.constraintDrop( state, descriptor ); - } - - private void assertIndexDoesNotExist( KernelStatement state, OperationContext context, - SchemaDescriptor descriptor ) - throws AlreadyIndexedException, AlreadyConstrainedException - { - SchemaIndexDescriptor existingIndex = schemaReadDelegate.indexGetForSchema( state, descriptor ); - if ( existingIndex != null ) - { - // OK so we found a matching constraint index. We check whether or not it has an owner - // because this may have been a left-over constraint index from a previously failed - // constraint creation, due to crash or similar, hence the missing owner. - if ( existingIndex.type() == UNIQUE ) - { - if ( context != CONSTRAINT_CREATION || constraintIndexHasOwner( state, existingIndex ) ) - { - throw new AlreadyConstrainedException( ConstraintDescriptorFactory.uniqueForSchema( descriptor ), - context, new StatementTokenNameLookup( state.readOperations() ) ); - } - } - else - { - throw new AlreadyIndexedException( descriptor, context ); - } - } - } - - private boolean constraintIndexHasOwner( KernelStatement state, SchemaIndexDescriptor descriptor ) - { - return schemaReadDelegate.indexGetOwningUniquenessConstraintId( state, descriptor ) != null; - } - - private String checkValidTokenName( String name ) throws IllegalTokenNameException - { - if ( name == null || name.isEmpty() ) - { - throw new IllegalTokenNameException( name ); - } - return name; - } - - private void assertConstraintDoesNotExist( KernelStatement state, ConstraintDescriptor constraint ) - throws AlreadyConstrainedException - { - if ( schemaReadDelegate.constraintExists( state, constraint ) ) - { - throw new AlreadyConstrainedException( constraint, OperationContext.CONSTRAINT_CREATION, - new StatementTokenNameLookup( state.readOperations() ) ); - } - } - - private void assertConstraintExists( KernelStatement state, ConstraintDescriptor constraint ) - throws NoSuchConstraintException - { - if ( !schemaReadDelegate.constraintExists( state, constraint ) ) - { - throw new NoSuchConstraintException( constraint ); - } - } - - private void assertValidDescriptor( SchemaDescriptor descriptor, OperationContext context ) - throws RepeatedPropertyInCompositeSchemaException - { - int numUnique = Arrays.stream( descriptor.getPropertyIds() ).distinct().toArray().length; - if ( numUnique != descriptor.getPropertyIds().length ) - { - throw new RepeatedPropertyInCompositeSchemaException( descriptor, context ); - } - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelImpl.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelImpl.java index 7146ac74fc2e1..7d7524611a0d8 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelImpl.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelImpl.java @@ -56,15 +56,6 @@ * * Please refer to the {@link KernelTransaction} javadoc for details. * - * The architecture of the kernel is based around a layered design, where one layer performs some task, and potentially - * delegates down to a lower layer. For instance, writing to the database will pass through - * {@link LockingStatementOperations}, which will grab locks and delegate to {@link StateHandlingStatementOperations} - * which will store the change in the transaction state, to be applied later if the transaction is committed. - * - * A read will, similarly, pass through {@link LockingStatementOperations}. It then reaches - * {@link StateHandlingStatementOperations}, which includes any changes that exist in the current transaction, and then - * finally {@link org.neo4j.storageengine.api.StoreReadLayer} will read the current committed state from - * the stores or caches. */ public class KernelImpl extends LifecycleAdapter implements InwardKernel { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelStatement.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelStatement.java index efe4a9bbe0400..bef2093d38a7f 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelStatement.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelStatement.java @@ -31,25 +31,20 @@ import org.neo4j.graphdb.NotInTransactionException; import org.neo4j.graphdb.TransactionTerminatedException; -import org.neo4j.internal.kernel.api.exceptions.InvalidTransactionTypeKernelException; import org.neo4j.internal.kernel.api.security.AccessMode; import org.neo4j.io.pagecache.tracing.cursor.PageCursorTracer; import org.neo4j.io.pagecache.tracing.cursor.context.VersionContext; import org.neo4j.io.pagecache.tracing.cursor.context.VersionContextSupplier; import org.neo4j.kernel.api.AssertOpen; -import org.neo4j.kernel.api.DataWriteOperations; import org.neo4j.kernel.api.QueryRegistryOperations; -import org.neo4j.kernel.api.ReadOperations; import org.neo4j.kernel.api.Statement; import org.neo4j.kernel.api.exceptions.Status; import org.neo4j.kernel.api.query.ExecutingQuery; 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.factory.AccessCapability; import org.neo4j.kernel.impl.locking.LockTracer; import org.neo4j.kernel.impl.locking.StatementLocks; -import org.neo4j.kernel.impl.proc.Procedures; import org.neo4j.storageengine.api.StorageStatement; import static java.lang.String.format; @@ -84,7 +79,6 @@ public class KernelStatement extends CloseableResourceManager implements TxState private final TxStateHolder txStateHolder; private final StorageStatement storeStatement; - private final AccessCapability accessCapability; private final KernelTransactionImplementation transaction; private final OperationsFacade facade; private StatementLocks statementLocks; @@ -97,20 +91,17 @@ public class KernelStatement extends CloseableResourceManager implements TxState private final VersionContextSupplier versionContextSupplier; public KernelStatement( KernelTransactionImplementation transaction, - TxStateHolder txStateHolder, - StorageStatement storeStatement, - Procedures procedures, - AccessCapability accessCapability, - LockTracer systemLockTracer, - StatementOperationParts statementOperations, - ClockContext clockContext, - VersionContextSupplier versionContextSupplier ) + TxStateHolder txStateHolder, + StorageStatement storeStatement, + LockTracer systemLockTracer, + StatementOperationParts statementOperations, + ClockContext clockContext, + VersionContextSupplier versionContextSupplier ) { this.transaction = transaction; this.txStateHolder = txStateHolder; this.storeStatement = storeStatement; - this.accessCapability = accessCapability; - this.facade = new OperationsFacade( transaction, this, procedures, statementOperations ); + this.facade = new OperationsFacade( this, statementOperations ); this.executingQueryList = ExecutingQueryList.EMPTY; this.systemLockTracer = systemLockTracer; this.statementOpenCloseCalls = RECORD_STATEMENTS_TRACES ? new ArrayDeque<>() : EMPTY_STATEMENT_HISTORY; @@ -118,24 +109,6 @@ public KernelStatement( KernelTransactionImplementation transaction, this.versionContextSupplier = versionContextSupplier; } - @Override - public ReadOperations readOperations() - { - assertAllows( AccessMode::allowsReads, "Read" ); - return facade; - } - - @Override - public DataWriteOperations dataWriteOperations() - throws InvalidTransactionTypeKernelException - { - accessCapability.assertCanWrite(); - - assertAllows( AccessMode::allowsWrites, "Write" ); - transaction.upgradeToDataWrites(); - return facade; - } - @Override public QueryRegistryOperations queryRegistration() { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelTransactionImplementation.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelTransactionImplementation.java index d2e8721b64474..9a9a4bba8ced8 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelTransactionImplementation.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/KernelTransactionImplementation.java @@ -214,7 +214,7 @@ public KernelTransactionImplementation( StatementOperationParts statementOperati this.versionContextSupplier = versionContextSupplier; this.storageStatement = storeLayer.newStatement(); this.currentStatement = new KernelStatement( this, this, storageStatement, - procedures, accessCapability, lockTracer, statementOperations, this.clocks, + lockTracer, statementOperations, this.clocks, versionContextSupplier ); this.accessCapability = accessCapability; this.statistics = new Statistics( this, cpuClockRef, heapAllocationRef ); diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/LockingStatementOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/LockingStatementOperations.java deleted file mode 100644 index 4dc585df03704..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/LockingStatementOperations.java +++ /dev/null @@ -1,550 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api; - -import org.apache.commons.lang3.mutable.MutableInt; - -import java.util.Iterator; -import java.util.function.Function; - -import org.neo4j.helpers.collection.Iterators; -import org.neo4j.internal.kernel.api.InternalIndexState; -import org.neo4j.internal.kernel.api.exceptions.EntityNotFoundException; -import org.neo4j.internal.kernel.api.exceptions.InvalidTransactionTypeKernelException; -import org.neo4j.internal.kernel.api.exceptions.KernelException; -import org.neo4j.internal.kernel.api.exceptions.explicitindex.AutoIndexingKernelException; -import org.neo4j.internal.kernel.api.exceptions.schema.ConstraintValidationException; -import org.neo4j.internal.kernel.api.schema.LabelSchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.RelationTypeSchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.SchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.constraints.ConstraintDescriptor; -import org.neo4j.kernel.api.Statement; -import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; -import org.neo4j.kernel.api.exceptions.schema.AlreadyConstrainedException; -import org.neo4j.kernel.api.exceptions.schema.AlreadyIndexedException; -import org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException; -import org.neo4j.kernel.api.exceptions.schema.DropConstraintFailureException; -import org.neo4j.kernel.api.exceptions.schema.DropIndexFailureException; -import org.neo4j.kernel.api.exceptions.schema.RepeatedPropertyInCompositeSchemaException; -import org.neo4j.kernel.api.exceptions.schema.SchemaRuleNotFoundException; -import org.neo4j.kernel.api.index.IndexProvider; -import org.neo4j.kernel.api.schema.constaints.NodeExistenceConstraintDescriptor; -import org.neo4j.kernel.api.schema.constaints.NodeKeyConstraintDescriptor; -import org.neo4j.kernel.api.schema.constaints.RelExistenceConstraintDescriptor; -import org.neo4j.kernel.api.schema.constaints.UniquenessConstraintDescriptor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.impl.api.operations.EntityReadOperations; -import org.neo4j.kernel.impl.api.operations.EntityWriteOperations; -import org.neo4j.kernel.impl.api.operations.LockOperations; -import org.neo4j.kernel.impl.api.operations.SchemaReadOperations; -import org.neo4j.kernel.impl.api.operations.SchemaStateOperations; -import org.neo4j.kernel.impl.api.operations.SchemaWriteOperations; -import org.neo4j.kernel.impl.locking.ResourceTypes; -import org.neo4j.storageengine.api.lock.ResourceType; -import org.neo4j.storageengine.api.schema.PopulationProgress; -import org.neo4j.values.storable.Value; - -import static java.lang.Math.max; -import static java.lang.Math.min; - -public class LockingStatementOperations implements - EntityWriteOperations, - SchemaReadOperations, - SchemaWriteOperations, - SchemaStateOperations, - LockOperations -{ - private final EntityReadOperations entityReadDelegate; - private final EntityWriteOperations entityWriteDelegate; - private final SchemaReadOperations schemaReadDelegate; - private final SchemaWriteOperations schemaWriteDelegate; - private final SchemaStateOperations schemaStateDelegate; - - public LockingStatementOperations( - EntityReadOperations entityReadDelegate, - EntityWriteOperations entityWriteDelegate, - SchemaReadOperations schemaReadDelegate, - SchemaWriteOperations schemaWriteDelegate, - SchemaStateOperations schemaStateDelegate ) - { - this.entityReadDelegate = entityReadDelegate; - this.entityWriteDelegate = entityWriteDelegate; - this.schemaReadDelegate = schemaReadDelegate; - this.schemaWriteDelegate = schemaWriteDelegate; - this.schemaStateDelegate = schemaStateDelegate; - } - - @Override - public boolean nodeAddLabel( KernelStatement state, long nodeId, int labelId ) - throws ConstraintValidationException, EntityNotFoundException - { - sharedLabelLock( state, labelId ); - - acquireExclusiveNodeLock( state, nodeId ); - state.assertOpen(); - - return entityWriteDelegate.nodeAddLabel( state, nodeId, labelId ); - } - - @Override - public boolean nodeRemoveLabel( KernelStatement state, long nodeId, int labelId ) throws EntityNotFoundException - { - acquireExclusiveNodeLock( state, nodeId ); - state.assertOpen(); - return entityWriteDelegate.nodeRemoveLabel( state, nodeId, labelId ); - } - - @Override - public SchemaIndexDescriptor indexCreate( KernelStatement state, SchemaDescriptor descriptor ) - throws AlreadyIndexedException, AlreadyConstrainedException, RepeatedPropertyInCompositeSchemaException - { - exclusiveLabelLock( state, descriptor.keyId() ); - state.assertOpen(); - return schemaWriteDelegate.indexCreate( state, descriptor ); - } - - @Override - public void indexDrop( KernelStatement state, SchemaIndexDescriptor descriptor ) throws DropIndexFailureException - { - exclusiveLabelLock( state, descriptor.schema().keyId() ); - state.assertOpen(); - schemaWriteDelegate.indexDrop( state, descriptor ); - } - - @Override - public void uniqueIndexDrop( KernelStatement state, SchemaIndexDescriptor descriptor ) throws DropIndexFailureException - { - exclusiveLabelLock( state, descriptor.schema().keyId() ); - state.assertOpen(); - schemaWriteDelegate.uniqueIndexDrop( state, descriptor ); - } - - @Override - public V schemaStateGetOrCreate( KernelStatement state, K key, Function creator ) - { - state.assertOpen(); - return schemaStateDelegate.schemaStateGetOrCreate( state, key, creator ); - } - - @Override - public V schemaStateGet( KernelStatement state, K key ) - { - state.assertOpen(); - return schemaStateDelegate.schemaStateGet( state, key ); - } - - @Override - public void schemaStateFlush( KernelStatement state ) - { - state.assertOpen(); - schemaStateDelegate.schemaStateFlush( state ); - } - - @Override - public Iterator indexesGetForLabel( KernelStatement state, int labelId ) - { - sharedLabelLock( state, labelId ); - state.assertOpen(); - return schemaReadDelegate.indexesGetForLabel( state, labelId ); - } - - @Override - public SchemaIndexDescriptor indexGetForSchema( KernelStatement state, SchemaDescriptor descriptor ) - { - sharedLabelLock( state, descriptor.keyId() ); - state.assertOpen(); - return schemaReadDelegate.indexGetForSchema( state, descriptor ); - } - - @Override - public Iterator indexesGetAll( KernelStatement state ) - { - state.assertOpen(); - return Iterators.map( indexDescriptor -> - { - sharedLabelLock( state, indexDescriptor.schema().keyId() ); - return indexDescriptor; - }, schemaReadDelegate.indexesGetAll( state ) ); - } - - @Override - public InternalIndexState indexGetState( KernelStatement state, SchemaIndexDescriptor descriptor ) - throws IndexNotFoundKernelException - { - sharedLabelLock( state, descriptor.schema().keyId() ); - state.assertOpen(); - return schemaReadDelegate.indexGetState( state, descriptor ); - } - - @Override - public IndexProvider.Descriptor indexGetProviderDescriptor( KernelStatement state, SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException - { - sharedLabelLock( state, descriptor.schema().keyId() ); - state.assertOpen(); - return schemaReadDelegate.indexGetProviderDescriptor( state, descriptor ); - } - - @Override - public PopulationProgress indexGetPopulationProgress( KernelStatement state, SchemaIndexDescriptor descriptor ) - throws IndexNotFoundKernelException - { - sharedLabelLock( state, descriptor.schema().keyId() ); - state.assertOpen(); - return schemaReadDelegate.indexGetPopulationProgress( state, descriptor ); - } - - @Override - public long indexSize( KernelStatement state, SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException - { - sharedLabelLock( state, descriptor.schema().keyId() ); - state.assertOpen(); - return schemaReadDelegate.indexSize( state, descriptor ); - } - - @Override - public double indexUniqueValuesPercentage( KernelStatement state, - SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException - { - sharedLabelLock( state, descriptor.schema().keyId() ); - state.assertOpen(); - return schemaReadDelegate.indexUniqueValuesPercentage( state, descriptor ); - } - - @Override - public Long indexGetOwningUniquenessConstraintId( KernelStatement state, SchemaIndexDescriptor index ) - { - sharedLabelLock( state, index.schema().keyId() ); - state.assertOpen(); - return schemaReadDelegate.indexGetOwningUniquenessConstraintId( state, index ); - } - - @Override - public long indexGetCommittedId( KernelStatement state, SchemaIndexDescriptor index ) - throws SchemaRuleNotFoundException - { - sharedLabelLock( state, index.schema().keyId() ); - state.assertOpen(); - return schemaReadDelegate.indexGetCommittedId( state, index ); - } - - @Override - public void nodeDelete( KernelStatement state, long nodeId ) - throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException - { - acquireExclusiveNodeLock( state, nodeId ); - state.assertOpen(); - entityWriteDelegate.nodeDelete( state, nodeId ); - } - - @Override - public int nodeDetachDelete( final KernelStatement state, final long nodeId ) throws KernelException - { - final MutableInt count = new MutableInt(); - TwoPhaseNodeForRelationshipLocking locking = new TwoPhaseNodeForRelationshipLocking( entityReadDelegate, - relId -> - { - state.assertOpen(); - try - { - entityWriteDelegate.relationshipDelete( state, relId ); - count.increment(); - } - catch ( EntityNotFoundException e ) - { - // it doesn't matter... - } - } ); - - locking.lockAllNodesAndConsumeRelationships( nodeId, state ); - state.assertOpen(); - entityWriteDelegate.nodeDetachDelete( state, nodeId ); - return count.intValue(); - } - - @Override - public long nodeCreate( KernelStatement statement ) - { - return entityWriteDelegate.nodeCreate( statement ); - } - - @Override - public long relationshipCreate( KernelStatement state, - int relationshipTypeId, - long startNodeId, - long endNodeId ) - throws EntityNotFoundException - { - sharedRelationshipTypeLock( state, relationshipTypeId ); - lockRelationshipNodes( state, startNodeId, endNodeId ); - return entityWriteDelegate.relationshipCreate( state, relationshipTypeId, startNodeId, endNodeId ); - } - - @Override - public void relationshipDelete( final KernelStatement state, long relationshipId ) - throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException - { - entityReadDelegate.relationshipVisit( state, relationshipId, - ( relId, type, startNode, endNode ) -> lockRelationshipNodes( state, startNode, endNode ) ); - acquireExclusiveRelationshipLock( state, relationshipId ); - state.assertOpen(); - entityWriteDelegate.relationshipDelete(state, relationshipId); - } - - private void lockRelationshipNodes( KernelStatement state, long startNodeId, long endNodeId ) - { - // Order the locks to lower the risk of deadlocks with other threads creating/deleting rels concurrently - acquireExclusiveNodeLock( state, min( startNodeId, endNodeId ) ); - if ( startNodeId != endNodeId ) - { - acquireExclusiveNodeLock( state, max( startNodeId, endNodeId ) ); - } - } - - @Override - public NodeKeyConstraintDescriptor nodeKeyConstraintCreate( KernelStatement state, LabelSchemaDescriptor descriptor ) - throws CreateConstraintFailureException, AlreadyConstrainedException, AlreadyIndexedException, - RepeatedPropertyInCompositeSchemaException - { - exclusiveLabelLock( state, descriptor.getLabelId() ); - state.assertOpen(); - return schemaWriteDelegate.nodeKeyConstraintCreate( state, descriptor ); - } - - @Override - public UniquenessConstraintDescriptor uniquePropertyConstraintCreate( KernelStatement state, SchemaDescriptor descriptor ) - throws CreateConstraintFailureException, AlreadyConstrainedException, AlreadyIndexedException, - RepeatedPropertyInCompositeSchemaException - { - exclusiveLabelLock( state, descriptor.keyId() ); - state.assertOpen(); - return schemaWriteDelegate.uniquePropertyConstraintCreate( state, descriptor ); - } - - @Override - public NodeExistenceConstraintDescriptor nodePropertyExistenceConstraintCreate( KernelStatement state, - LabelSchemaDescriptor descriptor ) throws AlreadyConstrainedException, CreateConstraintFailureException, - RepeatedPropertyInCompositeSchemaException - { - exclusiveLabelLock( state, descriptor.getLabelId() ); - state.assertOpen(); - return schemaWriteDelegate.nodePropertyExistenceConstraintCreate( state, descriptor ); - } - - @Override - public RelExistenceConstraintDescriptor relationshipPropertyExistenceConstraintCreate( KernelStatement state, - RelationTypeSchemaDescriptor descriptor ) - throws AlreadyConstrainedException, CreateConstraintFailureException, - RepeatedPropertyInCompositeSchemaException - { - exclusiveRelationshipTypeLock( state, descriptor.getRelTypeId() ); - state.assertOpen(); - return schemaWriteDelegate.relationshipPropertyExistenceConstraintCreate( state, descriptor ); - } - - @Override - public Iterator constraintsGetForSchema( KernelStatement state, SchemaDescriptor descriptor ) - { - sharedOptimisticLock( state, descriptor.keyType(), descriptor.keyId() ); - state.assertOpen(); - return schemaReadDelegate.constraintsGetForSchema( state, descriptor ); - } - - @Override - public boolean constraintExists( KernelStatement state, ConstraintDescriptor descriptor ) - { - SchemaDescriptor schema = descriptor.schema(); - sharedOptimisticLock( state, schema.keyType(), schema.keyId() ); - state.assertOpen(); - return schemaReadDelegate.constraintExists( state, descriptor ); - } - - @Override - public Iterator constraintsGetForLabel( KernelStatement state, int labelId ) - { - sharedLabelLock( state, labelId ); - state.assertOpen(); - return schemaReadDelegate.constraintsGetForLabel( state, labelId ); - } - - @Override - public Iterator constraintsGetForRelationshipType( KernelStatement state, - int typeId ) - { - sharedRelationshipTypeLock( state, typeId ); - state.assertOpen(); - return schemaReadDelegate.constraintsGetForRelationshipType( state, typeId ); - } - - @Override - public Iterator constraintsGetAll( KernelStatement state ) - { - state.assertOpen(); - return Iterators.map( constraintDescriptor -> - { - SchemaDescriptor schema = constraintDescriptor.schema(); - acquireShared( state, schema.keyType(), schema.keyId() ); - return constraintDescriptor; - }, schemaReadDelegate.constraintsGetAll( state ) ); - } - - @Override - public void constraintDrop( KernelStatement state, ConstraintDescriptor constraint ) - throws DropConstraintFailureException - { - SchemaDescriptor schema = constraint.schema(); - exclusiveOptimisticLock( state, schema.keyType(), schema.keyId() ); - state.assertOpen(); - schemaWriteDelegate.constraintDrop( state, constraint ); - } - - @Override - public Value nodeSetProperty( KernelStatement state, long nodeId, int propertyKeyId, Value value ) - throws ConstraintValidationException, EntityNotFoundException, AutoIndexingKernelException, - InvalidTransactionTypeKernelException - { - acquireExclusiveNodeLock( state, nodeId ); - state.assertOpen(); - return entityWriteDelegate.nodeSetProperty( state, nodeId, propertyKeyId, value ); - } - - @Override - public Value nodeRemoveProperty( KernelStatement state, long nodeId, int propertyKeyId ) - throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException - { - acquireExclusiveNodeLock( state, nodeId ); - state.assertOpen(); - return entityWriteDelegate.nodeRemoveProperty( state, nodeId, propertyKeyId ); - } - - @Override - public Value relationshipSetProperty( KernelStatement state, long relationshipId, int propertyKeyId, Value value ) - throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException - { - acquireExclusiveRelationshipLock( state, relationshipId ); - state.assertOpen(); - return entityWriteDelegate.relationshipSetProperty( state, relationshipId, propertyKeyId, value ); - } - - @Override - public Value relationshipRemoveProperty( KernelStatement state, long relationshipId, int propertyKeyId ) - throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException - { - acquireExclusiveRelationshipLock( state, relationshipId ); - state.assertOpen(); - return entityWriteDelegate.relationshipRemoveProperty( state, relationshipId, propertyKeyId ); - } - - @Override - public Value graphSetProperty( KernelStatement state, int propertyKeyId, Value value ) - { - state.locks().optimistic().acquireExclusive( state.lockTracer(), ResourceTypes.GRAPH_PROPS, ResourceTypes.graphPropertyResource() ); - state.assertOpen(); - return entityWriteDelegate.graphSetProperty( state, propertyKeyId, value ); - } - - @Override - public Value graphRemoveProperty( KernelStatement state, int propertyKeyId ) - { - state.locks().optimistic().acquireExclusive( state.lockTracer(), ResourceTypes.GRAPH_PROPS, ResourceTypes.graphPropertyResource() ); - state.assertOpen(); - return entityWriteDelegate.graphRemoveProperty( state, propertyKeyId ); - } - - @Override - public void acquireExclusive( KernelStatement state, ResourceType resourceType, long... ids ) - { - state.locks().pessimistic().acquireExclusive( state.lockTracer(), resourceType, ids ); - state.assertOpen(); - } - - @Override - public void acquireShared( KernelStatement state, ResourceType resourceType, long... ids ) - { - state.locks().pessimistic().acquireShared( state.lockTracer(), resourceType, ids ); - state.assertOpen(); - } - - @Override - public void releaseExclusive( KernelStatement state, ResourceType type, long... ids ) - { - state.locks().pessimistic().releaseExclusive( type, ids ); - state.assertOpen(); - } - - @Override - public void releaseShared( KernelStatement state, ResourceType type, long... ids ) - { - state.locks().pessimistic().releaseShared( type, ids ); - state.assertOpen(); - } - - @Override - public String indexGetFailure( Statement state, SchemaIndexDescriptor descriptor ) - throws IndexNotFoundKernelException - { - return schemaReadDelegate.indexGetFailure( state, descriptor ); - } - - private void acquireExclusiveNodeLock( KernelStatement state, long nodeId ) - { - if ( !state.hasTxStateWithChanges() || !state.txState().nodeIsAddedInThisTx( nodeId ) ) - { - exclusiveOptimisticLock( state, ResourceTypes.NODE, nodeId ); - } - } - - private void acquireExclusiveRelationshipLock( KernelStatement state, long relationshipId ) - { - if ( !state.hasTxStateWithChanges() || !state.txState().relationshipIsAddedInThisTx( relationshipId ) ) - { - exclusiveOptimisticLock( state, ResourceTypes.RELATIONSHIP, relationshipId ); - } - } - - private void exclusiveLabelLock( KernelStatement state, long labelId ) - { - exclusiveOptimisticLock( state, ResourceTypes.LABEL, labelId ); - } - - private void sharedLabelLock( KernelStatement state, long labelId ) - { - sharedOptimisticLock( state, ResourceTypes.LABEL, labelId ); - } - - private void exclusiveRelationshipTypeLock( KernelStatement state, long typeId ) - { - exclusiveOptimisticLock( state, ResourceTypes.RELATIONSHIP_TYPE, typeId ); - } - - private void sharedRelationshipTypeLock( KernelStatement state, long typeId ) - { - sharedOptimisticLock( state, ResourceTypes.RELATIONSHIP_TYPE, typeId ); - } - - private void sharedOptimisticLock( KernelStatement statement, ResourceType resource, long resourceId ) - { - statement.locks().optimistic().acquireShared( statement.lockTracer(), resource, resourceId ); - } - - private void exclusiveOptimisticLock( KernelStatement statement, ResourceType resource, long resourceId ) - { - statement.locks().optimistic().acquireExclusive( statement.lockTracer(), resource, resourceId ); - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/LookupFilter.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/LookupFilter.java index 8c8ffdb014ca4..e191fa8362a4a 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/LookupFilter.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/LookupFilter.java @@ -24,13 +24,9 @@ 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.internal.kernel.api.IndexQuery; import org.neo4j.internal.kernel.api.exceptions.EntityNotFoundException; import org.neo4j.kernel.api.index.PropertyAccessor; -import org.neo4j.kernel.impl.api.operations.EntityOperations; -import org.neo4j.storageengine.api.NodeItem; import org.neo4j.values.storable.Value; import org.neo4j.values.storable.ValueGroup; import org.neo4j.values.storable.Values; @@ -94,57 +90,6 @@ public static PrimitiveLongIterator exactIndexMatches( PropertyAccessor accessor return indexedNodeIds; } - /** - * This filter is added on top of index results for schema index implementations that will have - * potential false positive hits due to value coersion to double values. - * The given {@code indexedNodeIds} will be wrapped in a filter double-checking with the actual - * node property values iff the {@link IndexQuery} predicates query for numbers, i.e. where this - * coersion problem may be possible. - * - * used in "normal" operation - */ - public static PrimitiveLongResourceIterator exactIndexMatches( EntityOperations operations, KernelStatement state, - PrimitiveLongResourceIterator indexedNodeIds, IndexQuery... predicates ) - { - if ( !indexedNodeIds.hasNext() ) - { - return indexedNodeIds; - } - - IndexQuery[] filteredPredicates = - Arrays.stream( predicates ) - .filter( LookupFilter::isNumericOrGeometricPredicate ) - .toArray( IndexQuery[]::new ); - - if ( filteredPredicates.length > 0 ) - { - LongPredicate combinedPredicate = nodeId -> - { - try ( Cursor node = operations.nodeCursorById( state, nodeId ) ) - { - NodeItem nodeItem = node.get(); - for ( IndexQuery predicate : filteredPredicates ) - { - int propertyKeyId = predicate.propertyKeyId(); - Value value = operations.nodeGetProperty( state, nodeItem, propertyKeyId ); - if ( !predicate.acceptsValue( value ) ) - { - return false; - } - } - return true; - } - catch ( EntityNotFoundException ignored ) - { - return false; // The node has been deleted but was still reported from the index. We hope that this - // is some transient problem and just ignore this index entry. - } - }; - return PrimitiveLongCollections.filter( indexedNodeIds, combinedPredicate ); - } - return indexedNodeIds; - } - private static boolean isNumericOrGeometricPredicate( IndexQuery predicate ) { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/OperationsFacade.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/OperationsFacade.java index 1c229b5094d60..a81f7f5bddd72 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/OperationsFacade.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/OperationsFacade.java @@ -19,1128 +19,32 @@ */ package org.neo4j.kernel.impl.api; -import java.util.Iterator; import java.util.Map; -import java.util.Set; -import java.util.function.Function; import java.util.stream.Stream; -import org.neo4j.collection.primitive.PrimitiveIntIterator; -import org.neo4j.collection.primitive.PrimitiveLongIterator; -import org.neo4j.collection.primitive.PrimitiveLongResourceCollections; -import org.neo4j.collection.primitive.PrimitiveLongResourceIterator; -import org.neo4j.cursor.Cursor; -import org.neo4j.graphdb.Direction; -import org.neo4j.helpers.collection.Iterators; -import org.neo4j.internal.kernel.api.IndexQuery; -import org.neo4j.internal.kernel.api.InternalIndexState; -import org.neo4j.internal.kernel.api.exceptions.EntityNotFoundException; -import org.neo4j.internal.kernel.api.exceptions.InvalidTransactionTypeKernelException; -import org.neo4j.internal.kernel.api.exceptions.KernelException; -import org.neo4j.internal.kernel.api.exceptions.LabelNotFoundKernelException; -import org.neo4j.internal.kernel.api.exceptions.ProcedureException; -import org.neo4j.internal.kernel.api.exceptions.PropertyKeyIdNotFoundKernelException; -import org.neo4j.internal.kernel.api.exceptions.explicitindex.AutoIndexingKernelException; -import org.neo4j.internal.kernel.api.exceptions.explicitindex.ExplicitIndexNotFoundKernelException; -import org.neo4j.internal.kernel.api.exceptions.schema.ConstraintValidationException; -import org.neo4j.internal.kernel.api.procs.ProcedureHandle; -import org.neo4j.internal.kernel.api.procs.ProcedureSignature; -import org.neo4j.internal.kernel.api.procs.QualifiedName; -import org.neo4j.internal.kernel.api.procs.UserFunctionHandle; -import org.neo4j.internal.kernel.api.procs.UserFunctionSignature; -import org.neo4j.internal.kernel.api.schema.SchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.constraints.ConstraintDescriptor; -import org.neo4j.internal.kernel.api.security.AccessMode; -import org.neo4j.kernel.api.DataWriteOperations; -import org.neo4j.kernel.api.ExplicitIndexHits; -import org.neo4j.kernel.api.KernelTransaction; import org.neo4j.kernel.api.QueryRegistryOperations; -import org.neo4j.kernel.api.ReadOperations; -import org.neo4j.kernel.api.StatementConstants; -import org.neo4j.kernel.api.exceptions.RelationshipTypeIdNotFoundKernelException; -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.kernel.api.exceptions.schema.SchemaRuleNotFoundException; -import org.neo4j.kernel.api.index.IndexProvider; import org.neo4j.kernel.api.query.ExecutingQuery; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.impl.api.operations.CountsOperations; -import org.neo4j.kernel.impl.api.operations.EntityReadOperations; -import org.neo4j.kernel.impl.api.operations.EntityWriteOperations; -import org.neo4j.kernel.impl.api.operations.ExplicitIndexReadOperations; -import org.neo4j.kernel.impl.api.operations.ExplicitIndexWriteOperations; -import org.neo4j.kernel.impl.api.operations.KeyReadOperations; -import org.neo4j.kernel.impl.api.operations.LockOperations; import org.neo4j.kernel.impl.api.operations.QueryRegistrationOperations; -import org.neo4j.kernel.impl.api.operations.SchemaReadOperations; -import org.neo4j.kernel.impl.api.operations.SchemaStateOperations; -import org.neo4j.kernel.impl.api.store.CursorRelationshipIterator; -import org.neo4j.kernel.impl.api.store.RelationshipIterator; -import org.neo4j.kernel.impl.proc.Procedures; import org.neo4j.kernel.impl.query.clientconnection.ClientConnectionInfo; -import org.neo4j.register.Register.DoubleLongRegister; -import org.neo4j.storageengine.api.NodeItem; -import org.neo4j.storageengine.api.PropertyItem; -import org.neo4j.storageengine.api.RelationshipItem; -import org.neo4j.storageengine.api.Token; -import org.neo4j.storageengine.api.lock.ResourceType; -import org.neo4j.storageengine.api.schema.PopulationProgress; -import org.neo4j.storageengine.api.schema.SchemaRule; -import org.neo4j.values.storable.Value; -import org.neo4j.values.storable.Values; import org.neo4j.values.virtual.MapValue; -import static org.neo4j.collection.primitive.PrimitiveIntCollections.deduplicate; - -public class OperationsFacade - implements ReadOperations, DataWriteOperations, - QueryRegistryOperations +public class OperationsFacade implements QueryRegistryOperations { - private final KernelTransaction tx; private final KernelStatement statement; - private final Procedures procedures; private StatementOperationParts operations; - OperationsFacade( KernelTransaction tx, KernelStatement statement, - Procedures procedures, StatementOperationParts operationParts ) + OperationsFacade( KernelStatement statement, + StatementOperationParts operationParts ) { - this.tx = tx; this.statement = statement; - this.procedures = procedures; this.operations = operationParts; } - final KeyReadOperations tokenRead() - { - return operations.keyReadOperations(); - } - - final EntityReadOperations dataRead() - { - return operations.entityReadOperations(); - } - - final EntityWriteOperations dataWrite() - { - return operations.entityWriteOperations(); - } - - final ExplicitIndexWriteOperations explicitIndexWrite() - { - return operations.explicitIndexWriteOperations(); - } - - final ExplicitIndexReadOperations explicitIndexRead() - { - return operations.explicitIndexReadOperations(); - } - - final SchemaReadOperations schemaRead() - { - return operations.schemaReadOperations(); - } - final QueryRegistrationOperations queryRegistrationOperations() { return operations.queryRegistrationOperations(); } - final SchemaStateOperations schemaState() - { - return operations.schemaStateOperations(); - } - - final LockOperations locking() - { - return operations.locking(); - } - - final CountsOperations counting() - { - return operations.counting(); - } - - // - - @Override - public PrimitiveLongIterator nodesGetAll() - { - statement.assertOpen(); - return dataRead().nodesGetAll( statement ); - } - - @Override - public PrimitiveLongIterator relationshipsGetAll() - { - statement.assertOpen(); - return dataRead().relationshipsGetAll( statement ); - } - - @Override - public PrimitiveLongResourceIterator nodesGetForLabel( int labelId ) - { - statement.assertOpen(); - if ( labelId == StatementConstants.NO_SUCH_LABEL ) - { - return PrimitiveLongResourceCollections.emptyIterator(); - } - return dataRead().nodesGetForLabel( statement, labelId ); - } - - @Override - public PrimitiveLongResourceIterator indexQuery( SchemaIndexDescriptor index, IndexQuery... predicates ) - throws IndexNotFoundKernelException, IndexNotApplicableKernelException - { - statement.assertOpen(); - return dataRead().indexQuery( statement, index, predicates ); - } - - @Override - public long nodeGetFromUniqueIndexSeek( SchemaIndexDescriptor index, IndexQuery.ExactPredicate... predicates ) - throws IndexNotFoundKernelException, IndexBrokenKernelException, IndexNotApplicableKernelException - { - statement.assertOpen(); - return dataRead().nodeGetFromUniqueIndexSeek( statement, index, predicates ); - } - - @Override - public boolean nodeExists( long nodeId ) - { - statement.assertOpen(); - return dataRead().nodeExists( statement, nodeId ); - } - - @Override - public boolean nodeHasLabel( long nodeId, int labelId ) throws EntityNotFoundException - { - statement.assertOpen(); - - if ( labelId == StatementConstants.NO_SUCH_LABEL ) - { - return false; - } - - try ( Cursor node = dataRead().nodeCursorById( statement, nodeId ) ) - { - return node.get().hasLabel( labelId ); - } - } - - @Override - public PrimitiveIntIterator nodeGetLabels( long nodeId ) throws EntityNotFoundException - { - statement.assertOpen(); - try ( Cursor node = dataRead().nodeCursorById( statement, nodeId ) ) - { - return node.get().labels().iterator(); - } - } - - @Override - public boolean nodeHasProperty( long nodeId, int propertyKeyId ) throws EntityNotFoundException - { - statement.assertOpen(); - if ( propertyKeyId == StatementConstants.NO_SUCH_PROPERTY_KEY ) - { - return false; - } - try ( Cursor node = dataRead().nodeCursorById( statement, nodeId ) ) - { - return dataRead().nodeHasProperty( statement, node.get(), propertyKeyId ); - } - } - - @Override - public Value nodeGetProperty( long nodeId, int propertyKeyId ) throws EntityNotFoundException - { - statement.assertOpen(); - if ( propertyKeyId == StatementConstants.NO_SUCH_PROPERTY_KEY ) - { - return Values.NO_VALUE; - } - try ( Cursor node = dataRead().nodeCursorById( statement, nodeId ) ) - { - return dataRead().nodeGetProperty( statement, node.get(), propertyKeyId ); - } - } - - @Override - public RelationshipIterator nodeGetRelationships( long nodeId, Direction direction, int[] relTypes ) - throws EntityNotFoundException - { - statement.assertOpen(); - try ( Cursor node = dataRead().nodeCursorById( statement, nodeId ) ) - { - return new CursorRelationshipIterator( dataRead() - .nodeGetRelationships( statement, node.get(), direction( direction ), deduplicate( relTypes ) ) ); - } - } - - private org.neo4j.storageengine.api.Direction direction( Direction direction ) - { - switch ( direction ) - { - case OUTGOING: return org.neo4j.storageengine.api.Direction.OUTGOING; - case INCOMING: return org.neo4j.storageengine.api.Direction.INCOMING; - case BOTH: return org.neo4j.storageengine.api.Direction.BOTH; - default: throw new IllegalArgumentException( direction.name() ); - } - } - - @Override - public RelationshipIterator nodeGetRelationships( long nodeId, Direction direction ) - throws EntityNotFoundException - { - statement.assertOpen(); - try ( Cursor node = dataRead().nodeCursorById( statement, nodeId ) ) - { - return new CursorRelationshipIterator( - dataRead().nodeGetRelationships( statement, node.get(), direction( direction ) ) ); - } - } - - @Override - public int nodeGetDegree( long nodeId, Direction direction, int relType ) throws EntityNotFoundException - { - statement.assertOpen(); - try ( Cursor node = dataRead().nodeCursorById( statement, nodeId ) ) - { - return dataRead().degree( statement, node.get(), direction( direction ), relType ); - } - } - - @Override - public int nodeGetDegree( long nodeId, Direction direction ) throws EntityNotFoundException - { - statement.assertOpen(); - try ( Cursor node = dataRead().nodeCursorById( statement, nodeId ) ) - { - return dataRead().degree( statement, node.get(), direction( direction ) ); - } - } - - @Override - public boolean nodeIsDense( long nodeId ) throws EntityNotFoundException - { - statement.assertOpen(); - try ( Cursor node = dataRead().nodeCursorById( statement, nodeId ) ) - { - return node.get().isDense(); - } - } - - @Override - public PrimitiveIntIterator nodeGetRelationshipTypes( long nodeId ) throws EntityNotFoundException - { - statement.assertOpen(); - try ( Cursor node = dataRead().nodeCursorById( statement, nodeId ) ) - { - return dataRead().relationshipTypes( statement,node.get() ).iterator(); - } - } - - @Override - public boolean relationshipHasProperty( long relationshipId, int propertyKeyId ) throws EntityNotFoundException - { - statement.assertOpen(); - if ( propertyKeyId == StatementConstants.NO_SUCH_PROPERTY_KEY ) - { - return false; - } - try ( Cursor relationship = dataRead().relationshipCursorById( statement, relationshipId ) ) - { - return dataRead().relationshipHasProperty( statement, relationship.get(), propertyKeyId ); - } - } - - @Override - public Value relationshipGetProperty( long relationshipId, int propertyKeyId ) throws EntityNotFoundException - { - statement.assertOpen(); - if ( propertyKeyId == StatementConstants.NO_SUCH_PROPERTY_KEY ) - { - return Values.NO_VALUE; - } - try ( Cursor relationship = dataRead().relationshipCursorById( statement, relationshipId ) ) - { - return dataRead().relationshipGetProperty( statement, relationship.get(), propertyKeyId ); - } - } - - @Override - public boolean graphHasProperty( int propertyKeyId ) - { - statement.assertOpen(); - return propertyKeyId != StatementConstants.NO_SUCH_PROPERTY_KEY && - dataRead().graphHasProperty( statement, propertyKeyId ); - } - - @Override - public Value graphGetProperty( int propertyKeyId ) - { - statement.assertOpen(); - if ( propertyKeyId == StatementConstants.NO_SUCH_PROPERTY_KEY ) - { - return Values.NO_VALUE; - } - return dataRead().graphGetProperty( statement, propertyKeyId ); - } - - @Override - public PrimitiveIntIterator nodeGetPropertyKeys( long nodeId ) throws EntityNotFoundException - { - statement.assertOpen(); - try ( Cursor node = dataRead().nodeCursorById( statement, nodeId ) ) - { - return dataRead().nodeGetPropertyKeys( statement, node.get() ).iterator(); - } - } - - @Override - public PrimitiveIntIterator relationshipGetPropertyKeys( long relationshipId ) throws EntityNotFoundException - { - statement.assertOpen(); - try ( Cursor relationship = dataRead().relationshipCursorById( statement, relationshipId ) ) - { - return dataRead().relationshipGetPropertyKeys( statement, relationship.get() ).iterator(); - } - } - - @Override - public PrimitiveIntIterator graphGetPropertyKeys() - { - statement.assertOpen(); - return dataRead().graphGetPropertyKeys( statement ); - } - - @Override - public void relationshipVisit( long relId, - RelationshipVisitor visitor ) throws EntityNotFoundException, EXCEPTION - { - statement.assertOpen(); - dataRead().relationshipVisit( statement, relId, visitor ); - } - - @Override - public long nodesGetCount() - { - statement.assertOpen(); - return dataRead().nodesGetCount( statement ); - } - - @Override - public long relationshipsGetCount() - { - statement.assertOpen(); - return dataRead().relationshipsGetCount( statement ); - } - - @Override - public ProcedureHandle procedureGet( QualifiedName name ) throws ProcedureException - { - statement.assertOpen(); - return procedures.procedure( name ); - } - - @Override - public UserFunctionHandle functionGet( QualifiedName name ) - { - statement.assertOpen(); - return procedures.function( name ); - } - - @Override - public UserFunctionHandle aggregationFunctionGet( QualifiedName name ) - { - statement.assertOpen(); - return procedures.aggregationFunction( name ); - } - - @Override - public Set functionsGetAll() - { - statement.assertOpen(); - return procedures.getAllFunctions(); - } - - @Override - public Set proceduresGetAll() - { - statement.assertOpen(); - return procedures.getAllProcedures(); - } - - @Override - public long nodesCountIndexed( SchemaIndexDescriptor index, long nodeId, Value value ) - throws IndexNotFoundKernelException, IndexBrokenKernelException - { - statement.assertOpen(); - return dataRead().nodesCountIndexed( statement, index, nodeId, value ); - } - // - - // - @Override - public Cursor nodeCursorById( long nodeId ) throws EntityNotFoundException - { - statement.assertOpen(); - return dataRead().nodeCursorById( statement, nodeId ); - } - - @Override - public Cursor relationshipCursorById( long relId ) throws EntityNotFoundException - { - statement.assertOpen(); - return dataRead().relationshipCursorById( statement, relId ); - } - - @Override - public Cursor nodeGetProperties( NodeItem node ) - { - statement.assertOpen(); - return dataRead().nodeGetProperties( statement, node ); - } - - @Override - public Cursor relationshipGetProperties( RelationshipItem relationship ) - { - statement.assertOpen(); - return dataRead().relationshipGetProperties( statement, relationship ); - } - - // - - // - @Override - public SchemaIndexDescriptor indexGetForSchema( SchemaDescriptor descriptor ) - throws SchemaRuleNotFoundException - { - statement.assertOpen(); - SchemaIndexDescriptor schemaIndexDescriptor = schemaRead().indexGetForSchema( statement, descriptor ); - if ( schemaIndexDescriptor == null ) - { - throw new SchemaRuleNotFoundException( SchemaRule.Kind.INDEX_RULE, descriptor ); - } - return schemaIndexDescriptor; - } - - @Override - public Iterator indexesGetForLabel( int labelId ) - { - statement.assertOpen(); - return schemaRead().indexesGetForLabel( statement, labelId ); - } - - @Override - public Iterator indexesGetAll() - { - statement.assertOpen(); - return schemaRead().indexesGetAll( statement ); - } - - @Override - public Long indexGetOwningUniquenessConstraintId( SchemaIndexDescriptor index ) - { - statement.assertOpen(); - return schemaRead().indexGetOwningUniquenessConstraintId( statement, index ); - } - - @Override - public InternalIndexState indexGetState( SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException - { - statement.assertOpen(); - return schemaRead().indexGetState( statement, descriptor ); - } - - @Override - public IndexProvider.Descriptor indexGetProviderDescriptor( SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException - { - statement.assertOpen(); - return schemaRead().indexGetProviderDescriptor( statement, descriptor ); - } - - @Override - public PopulationProgress indexGetPopulationProgress( SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException - { - statement.assertOpen(); - return schemaRead().indexGetPopulationProgress( statement, descriptor ); - } - - @Override - public long indexSize( SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException - { - statement.assertOpen(); - return schemaRead().indexSize( statement, descriptor ); - } - - @Override - public double indexUniqueValuesSelectivity( SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException - { - statement.assertOpen(); - return schemaRead().indexUniqueValuesPercentage( statement, descriptor ); - } - - @Override - public String indexGetFailure( SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException - { - statement.assertOpen(); - return schemaRead().indexGetFailure( statement, descriptor ); - } - - @Override - public Iterator constraintsGetForSchema( SchemaDescriptor descriptor ) - { - statement.assertOpen(); - return schemaRead().constraintsGetForSchema( statement, descriptor ); - } - - @Override - public Iterator constraintsGetForLabel( int labelId ) - { - statement.assertOpen(); - return schemaRead().constraintsGetForLabel( statement, labelId ); - } - - @Override - public Iterator constraintsGetForRelationshipType( int typeId ) - { - statement.assertOpen(); - return schemaRead().constraintsGetForRelationshipType( statement, typeId ); - } - - @Override - public Iterator constraintsGetAll() - { - statement.assertOpen(); - return schemaRead().constraintsGetAll( statement ); - } - // - - // - @Override - public int labelGetForName( String labelName ) - { - statement.assertOpen(); - return tokenRead().labelGetForName( statement, labelName ); - } - - @Override - public String labelGetName( int labelId ) throws LabelNotFoundKernelException - { - statement.assertOpen(); - return tokenRead().labelGetName( statement, labelId ); - } - - @Override - public int propertyKeyGetForName( String propertyKeyName ) - { - statement.assertOpen(); - return tokenRead().propertyKeyGetForName( statement, propertyKeyName ); - } - - @Override - public String propertyKeyGetName( int propertyKeyId ) throws PropertyKeyIdNotFoundKernelException - { - statement.assertOpen(); - return tokenRead().propertyKeyGetName( statement, propertyKeyId ); - } - - @Override - public Iterator propertyKeyGetAllTokens() - { - statement.assertOpen(); - AccessMode mode = tx.securityContext().mode(); - return Iterators.stream( tokenRead().propertyKeyGetAllTokens( statement ) ). - filter( propKey -> mode.allowsPropertyReads( propKey.id() ) ).iterator(); - } - - @Override - public Iterator labelsGetAllTokens() - { - statement.assertOpen(); - return tokenRead().labelsGetAllTokens( statement ); - } - - @Override - public Iterator relationshipTypesGetAllTokens() - { - statement.assertOpen(); - return tokenRead().relationshipTypesGetAllTokens( statement ); - } - - @Override - public int relationshipTypeGetForName( String relationshipTypeName ) - { - statement.assertOpen(); - return tokenRead().relationshipTypeGetForName( statement, relationshipTypeName ); - } - - @Override - public String relationshipTypeGetName( int relationshipTypeId ) throws RelationshipTypeIdNotFoundKernelException - { - statement.assertOpen(); - return tokenRead().relationshipTypeGetName( statement, relationshipTypeId ); - } - - @Override - public int labelCount() - { - statement.assertOpen(); - return tokenRead().labelCount( statement ); - } - - @Override - public int propertyKeyCount() - { - statement.assertOpen(); - return tokenRead().propertyKeyCount( statement ); - } - - @Override - public int relationshipTypeCount() - { - statement.assertOpen(); - return tokenRead().relationshipTypeCount( statement ); - } - - // - - // - @Override - public V schemaStateGetOrCreate( K key, Function creator ) - { - return schemaState().schemaStateGetOrCreate( statement, key, creator ); - } - - @Override - public V schemaStateGet( K key ) - { - return schemaState().schemaStateGet( statement, key ); - } - - @Override - public void schemaStateFlush() - { - schemaState().schemaStateFlush( statement ); - } - // - - // - @Override - public long nodeCreate() - { - statement.assertOpen(); - return dataWrite().nodeCreate( statement ); - } - - @Override - public void nodeDelete( long nodeId ) - throws EntityNotFoundException, InvalidTransactionTypeKernelException, AutoIndexingKernelException - { - statement.assertOpen(); - dataWrite().nodeDelete( statement, nodeId ); - } - - @Override - public int nodeDetachDelete( long nodeId ) throws KernelException - { - statement.assertOpen(); - return dataWrite().nodeDetachDelete( statement, nodeId ); - } - - @Override - public long relationshipCreate( int relationshipTypeId, long startNodeId, long endNodeId ) - throws EntityNotFoundException - { - statement.assertOpen(); - return dataWrite().relationshipCreate( statement, relationshipTypeId, startNodeId, endNodeId ); - } - - @Override - public void relationshipDelete( long relationshipId ) - throws EntityNotFoundException, InvalidTransactionTypeKernelException, AutoIndexingKernelException - { - statement.assertOpen(); - dataWrite().relationshipDelete( statement, relationshipId ); - } - - @Override - public boolean nodeAddLabel( long nodeId, int labelId ) - throws EntityNotFoundException, ConstraintValidationException - { - statement.assertOpen(); - return dataWrite().nodeAddLabel( statement, nodeId, labelId ); - } - - @Override - public boolean nodeRemoveLabel( long nodeId, int labelId ) throws EntityNotFoundException - { - statement.assertOpen(); - return dataWrite().nodeRemoveLabel( statement, nodeId, labelId ); - } - - @Override - public Value nodeSetProperty( long nodeId, int propertyKeyId, Value value ) - throws EntityNotFoundException, AutoIndexingKernelException, - InvalidTransactionTypeKernelException, ConstraintValidationException - { - statement.assertOpen(); - return dataWrite().nodeSetProperty( statement, nodeId, propertyKeyId, value ); - } - - @Override - public Value relationshipSetProperty( long relationshipId, int propertyKeyId, Value value ) - throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException - { - statement.assertOpen(); - return dataWrite().relationshipSetProperty( statement, relationshipId, propertyKeyId, value ); - } - - @Override - public Value graphSetProperty( int propertyKeyId, Value value ) - { - statement.assertOpen(); - return dataWrite().graphSetProperty( statement, propertyKeyId, value ); - } - - @Override - public Value nodeRemoveProperty( long nodeId, int propertyKeyId ) - throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException - { - statement.assertOpen(); - return dataWrite().nodeRemoveProperty( statement, nodeId, propertyKeyId ); - } - - @Override - public Value relationshipRemoveProperty( long relationshipId, int propertyKeyId ) - throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException - { - statement.assertOpen(); - return dataWrite().relationshipRemoveProperty( statement, relationshipId, propertyKeyId ); - } - - @Override - public Value graphRemoveProperty( int propertyKeyId ) - { - statement.assertOpen(); - return dataWrite().graphRemoveProperty( statement, propertyKeyId ); - } - - // - // - @Override - public void acquireExclusive( ResourceType type, long... ids ) - { - statement.assertOpen(); - locking().acquireExclusive( statement, type, ids ); - } - - @Override - public void acquireShared( ResourceType type, long... ids ) - { - statement.assertOpen(); - locking().acquireShared( statement, type, ids ); - } - - @Override - public void releaseExclusive( ResourceType type, long... ids ) - { - statement.assertOpen(); - locking().releaseExclusive( statement, type, ids ); - } - - @Override - public void releaseShared( ResourceType type, long... ids ) - { - statement.assertOpen(); - locking().releaseShared( statement, type, ids ); - } - // - - // - @Override - public boolean nodeExplicitIndexExists( String indexName, Map customConfiguration ) - { - statement.assertOpen(); - return explicitIndexRead().nodeExplicitIndexExists( statement, indexName, customConfiguration ); - } - - @Override - public boolean relationshipExplicitIndexExists( String indexName, Map customConfiguration ) - { - statement.assertOpen(); - return explicitIndexRead().relationshipExplicitIndexExists( statement, indexName, customConfiguration ); - } - - @Override - public ExplicitIndexHits nodeExplicitIndexGet( String indexName, String key, Object value ) - throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - return explicitIndexRead().nodeExplicitIndexGet( statement, indexName, key, value ); - } - - @Override - public ExplicitIndexHits nodeExplicitIndexQuery( String indexName, String key, Object queryOrQueryObject ) - throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - return explicitIndexRead().nodeExplicitIndexQuery( statement, indexName, key, queryOrQueryObject ); - } - - @Override - public ExplicitIndexHits nodeExplicitIndexQuery( String indexName, Object queryOrQueryObject ) - throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - return explicitIndexRead().nodeExplicitIndexQuery( statement, indexName, queryOrQueryObject ); - } - - @Override - public ExplicitIndexHits relationshipExplicitIndexGet( String indexName, String key, Object value, - long startNode, long endNode ) throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - return explicitIndexRead().relationshipExplicitIndexGet( statement, indexName, key, value, startNode, endNode ); - } - - @Override - public ExplicitIndexHits relationshipExplicitIndexQuery( String indexName, String key, Object queryOrQueryObject, - long startNode, long endNode ) throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - return explicitIndexRead().relationshipExplicitIndexQuery( statement, indexName, key, queryOrQueryObject, - startNode, endNode ); - } - - @Override - public ExplicitIndexHits relationshipExplicitIndexQuery( String indexName, Object queryOrQueryObject, - long startNode, long endNode ) throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - return explicitIndexRead().relationshipExplicitIndexQuery( statement, indexName, queryOrQueryObject, - startNode, endNode ); - } - - @Override - public void nodeExplicitIndexCreateLazily( String indexName, Map customConfig ) - { - statement.assertOpen(); - explicitIndexWrite().nodeExplicitIndexCreateLazily( statement, indexName, customConfig ); - } - - @Override - public void nodeExplicitIndexCreate( String indexName, Map customConfig ) - { - statement.assertOpen(); - - explicitIndexWrite().nodeExplicitIndexCreate( statement, indexName, customConfig ); - } - - @Override - public void relationshipExplicitIndexCreateLazily( String indexName, Map customConfig ) - { - statement.assertOpen(); - explicitIndexWrite().relationshipExplicitIndexCreateLazily( statement, indexName, customConfig ); - } - - @Override - public void relationshipExplicitIndexCreate( String indexName, Map customConfig ) - { - statement.assertOpen(); - - explicitIndexWrite().relationshipExplicitIndexCreate( statement, indexName, customConfig ); - } - - @Override - public void nodeAddToExplicitIndex( String indexName, long node, String key, Object value ) - throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - explicitIndexWrite().nodeAddToExplicitIndex( statement, indexName, node, key, value ); - } - - @Override - public void nodeRemoveFromExplicitIndex( String indexName, long node, String key, Object value ) - throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - explicitIndexWrite().nodeRemoveFromExplicitIndex( statement, indexName, node, key, value ); - } - - @Override - public void nodeRemoveFromExplicitIndex( String indexName, long node, String key ) - throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - explicitIndexWrite().nodeRemoveFromExplicitIndex( statement, indexName, node, key ); - } - - @Override - public void nodeRemoveFromExplicitIndex( String indexName, long node ) throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - explicitIndexWrite().nodeRemoveFromExplicitIndex( statement, indexName, node ); - } - - @Override - public void relationshipAddToExplicitIndex( String indexName, long relationship, String key, Object value ) - throws EntityNotFoundException, ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - explicitIndexWrite().relationshipAddToExplicitIndex( statement, indexName, relationship, key, value ); - } - - @Override - public void relationshipRemoveFromExplicitIndex( String indexName, long relationship, String key, Object value ) - throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - explicitIndexWrite().relationshipRemoveFromExplicitIndex( statement, indexName, relationship, key, value ); - } - - @Override - public void relationshipRemoveFromExplicitIndex( String indexName, long relationship, String key ) - throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - explicitIndexWrite().relationshipRemoveFromExplicitIndex( statement, indexName, relationship, key ); - } - - @Override - public void relationshipRemoveFromExplicitIndex( String indexName, long relationship ) - throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - explicitIndexWrite().relationshipRemoveFromExplicitIndex( statement, indexName, relationship ); - } - - @Override - public void nodeExplicitIndexDrop( String indexName ) throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - explicitIndexWrite().nodeExplicitIndexDrop( statement, indexName ); - } - - @Override - public void relationshipExplicitIndexDrop( String indexName ) throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - explicitIndexWrite().relationshipExplicitIndexDrop( statement, indexName ); - } - - @Override - public Map nodeExplicitIndexGetConfiguration( String indexName ) - throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - return explicitIndexRead().nodeExplicitIndexGetConfiguration( statement, indexName ); - } - - @Override - public Map relationshipExplicitIndexGetConfiguration( String indexName ) - throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - return explicitIndexRead().relationshipExplicitIndexGetConfiguration( statement, indexName ); - } - - @Override - public String nodeExplicitIndexSetConfiguration( String indexName, String key, String value ) - throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - return explicitIndexWrite().nodeExplicitIndexSetConfiguration( statement, indexName, key, value ); - } - - @Override - public String relationshipExplicitIndexSetConfiguration( String indexName, String key, String value ) - throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - return explicitIndexWrite().relationshipExplicitIndexSetConfiguration( statement, indexName, key, value ); - } - - @Override - public String nodeExplicitIndexRemoveConfiguration( String indexName, String key ) - throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - return explicitIndexWrite().nodeExplicitIndexRemoveConfiguration( statement, indexName, key ); - } - - @Override - public String relationshipExplicitIndexRemoveConfiguration( String indexName, String key ) - throws ExplicitIndexNotFoundKernelException - { - statement.assertOpen(); - return explicitIndexWrite().relationshipExplicitIndexRemoveConfiguration( statement, indexName, key ); - } - - @Override - public String[] nodeExplicitIndexesGetAll() - { - statement.assertOpen(); - return explicitIndexRead().nodeExplicitIndexesGetAll( statement ); - } - - @Override - public String[] relationshipExplicitIndexesGetAll() - { - statement.assertOpen(); - return explicitIndexRead().relationshipExplicitIndexesGetAll( statement ); - } - // - - // - - @Override - public long countsForNode( int labelId ) - { - statement.assertOpen(); - return counting().countsForNode( statement, labelId ); - } - - @Override - public long countsForNodeWithoutTxState( int labelId ) - { - statement.assertOpen(); - return counting().countsForNodeWithoutTxState( statement, labelId ); - } - - @Override - public long countsForRelationship( int startLabelId, int typeId, int endLabelId ) - { - statement.assertOpen(); - return counting().countsForRelationship( statement, startLabelId, typeId, endLabelId ); - } - - @Override - public long countsForRelationshipWithoutTxState( int startLabelId, int typeId, int endLabelId ) - { - statement.assertOpen(); - return counting().countsForRelationshipWithoutTxState( statement, startLabelId, typeId, endLabelId ); - } - - @Override - public DoubleLongRegister indexUpdatesAndSize( SchemaIndexDescriptor index, DoubleLongRegister target ) - throws IndexNotFoundKernelException - { - statement.assertOpen(); - return counting().indexUpdatesAndSize( statement, index, target ); - } - - @Override - public DoubleLongRegister indexSample( SchemaIndexDescriptor index, DoubleLongRegister target ) - throws IndexNotFoundKernelException - { - statement.assertOpen(); - return counting().indexSample( statement, index, target ); - } - - // - // query monitoring @Override diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/SchemaStateConcern.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/SchemaStateConcern.java deleted file mode 100644 index 872c5903e0408..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/SchemaStateConcern.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api; - -import java.util.function.Function; - -import org.neo4j.kernel.impl.api.operations.SchemaStateOperations; - -public class SchemaStateConcern implements SchemaStateOperations -{ - private final SchemaState schemaState; - - public SchemaStateConcern( SchemaState schemaState ) - { - this.schemaState = schemaState; - } - - @Override - public V schemaStateGetOrCreate( KernelStatement state, K key, Function creator ) - { - return schemaState.getOrCreate( key, creator ); - } - - @Override - public V schemaStateGet( KernelStatement state, K key ) - { - return schemaState.get( key ); - } - - @Override - public void schemaStateFlush( KernelStatement state ) - { - schemaState.clear(); - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/StateHandlingStatementOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/StateHandlingStatementOperations.java deleted file mode 100644 index 2087fc95a2de9..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/StateHandlingStatementOperations.java +++ /dev/null @@ -1,1787 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api; - -import java.util.Arrays; -import java.util.Iterator; -import java.util.Map; - -import org.neo4j.collection.primitive.Primitive; -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.graphdb.NotFoundException; -import org.neo4j.internal.kernel.api.IndexQuery; -import org.neo4j.internal.kernel.api.InternalIndexState; -import org.neo4j.internal.kernel.api.exceptions.EntityNotFoundException; -import org.neo4j.internal.kernel.api.exceptions.InvalidTransactionTypeKernelException; -import org.neo4j.internal.kernel.api.exceptions.LabelNotFoundKernelException; -import org.neo4j.internal.kernel.api.exceptions.PropertyKeyIdNotFoundKernelException; -import org.neo4j.internal.kernel.api.exceptions.explicitindex.AutoIndexingKernelException; -import org.neo4j.internal.kernel.api.exceptions.explicitindex.ExplicitIndexNotFoundKernelException; -import org.neo4j.internal.kernel.api.exceptions.schema.ConstraintValidationException; -import org.neo4j.internal.kernel.api.exceptions.schema.TooManyLabelsException; -import org.neo4j.internal.kernel.api.schema.LabelSchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.RelationTypeSchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.SchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.SchemaUtil; -import org.neo4j.internal.kernel.api.schema.constraints.ConstraintDescriptor; -import org.neo4j.kernel.api.DataWriteOperations; -import org.neo4j.kernel.api.ExplicitIndex; -import org.neo4j.kernel.api.ExplicitIndexHits; -import org.neo4j.kernel.api.Statement; -import org.neo4j.kernel.api.exceptions.RelationshipTypeIdNotFoundKernelException; -import org.neo4j.internal.kernel.api.exceptions.TransactionFailureException; -import org.neo4j.kernel.api.exceptions.index.IndexNotApplicableKernelException; -import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; -import org.neo4j.kernel.api.exceptions.schema.AlreadyConstrainedException; -import org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException; -import org.neo4j.kernel.api.exceptions.schema.SchemaRuleNotFoundException; -import org.neo4j.kernel.api.exceptions.schema.UniquePropertyValueValidationException; -import org.neo4j.kernel.api.explicitindex.AutoIndexing; -import org.neo4j.kernel.api.index.IndexProvider; -import org.neo4j.kernel.api.properties.PropertyKeyIdIterator; -import org.neo4j.kernel.api.schema.constaints.ConstraintDescriptorFactory; -import org.neo4j.kernel.api.schema.constaints.IndexBackedConstraintDescriptor; -import org.neo4j.kernel.api.schema.constaints.NodeExistenceConstraintDescriptor; -import org.neo4j.kernel.api.schema.constaints.NodeKeyConstraintDescriptor; -import org.neo4j.kernel.api.schema.constaints.RelExistenceConstraintDescriptor; -import org.neo4j.kernel.api.schema.constaints.UniquenessConstraintDescriptor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptorFactory; -import org.neo4j.kernel.api.txstate.TransactionCountingStateVisitor; -import org.neo4j.kernel.api.txstate.TransactionState; -import org.neo4j.kernel.impl.api.index.IndexingService; -import org.neo4j.kernel.impl.api.operations.CountsOperations; -import org.neo4j.kernel.impl.api.operations.EntityOperations; -import org.neo4j.kernel.impl.api.operations.ExplicitIndexReadOperations; -import org.neo4j.kernel.impl.api.operations.ExplicitIndexWriteOperations; -import org.neo4j.kernel.impl.api.operations.KeyReadOperations; -import org.neo4j.kernel.impl.api.operations.KeyWriteOperations; -import org.neo4j.kernel.impl.api.operations.SchemaReadOperations; -import org.neo4j.kernel.impl.api.operations.SchemaWriteOperations; -import org.neo4j.kernel.impl.api.state.ConstraintIndexCreator; -import org.neo4j.kernel.impl.api.state.IndexTxStateUpdater; -import org.neo4j.kernel.impl.api.store.RelationshipIterator; -import org.neo4j.kernel.impl.index.ExplicitIndexStore; -import org.neo4j.kernel.impl.index.IndexEntityType; -import org.neo4j.register.Register.DoubleLongRegister; -import org.neo4j.storageengine.api.Direction; -import org.neo4j.storageengine.api.EntityType; -import org.neo4j.storageengine.api.NodeItem; -import org.neo4j.storageengine.api.PropertyItem; -import org.neo4j.storageengine.api.RelationshipItem; -import org.neo4j.storageengine.api.StorageProperty; -import org.neo4j.storageengine.api.StorageStatement; -import org.neo4j.storageengine.api.StoreReadLayer; -import org.neo4j.storageengine.api.Token; -import org.neo4j.storageengine.api.schema.IndexReader; -import org.neo4j.storageengine.api.schema.PopulationProgress; -import org.neo4j.storageengine.api.txstate.NodeState; -import org.neo4j.storageengine.api.txstate.PrimitiveLongReadableDiffSets; -import org.neo4j.storageengine.api.txstate.ReadableDiffSets; -import org.neo4j.values.storable.Value; -import org.neo4j.values.storable.ValueGroup; -import org.neo4j.values.storable.ValueTuple; -import org.neo4j.values.storable.Values; - -import static java.lang.String.format; -import static org.neo4j.collection.primitive.PrimitiveIntCollections.filter; -import static org.neo4j.collection.primitive.PrimitiveLongCollections.resourceIterator; -import static org.neo4j.collection.primitive.PrimitiveLongCollections.single; -import static org.neo4j.function.Predicates.any; -import static org.neo4j.helpers.collection.Iterators.filter; -import static org.neo4j.helpers.collection.Iterators.iterator; -import static org.neo4j.helpers.collection.Iterators.singleOrNull; -import static org.neo4j.kernel.api.StatementConstants.NO_SUCH_NODE; -import static org.neo4j.kernel.impl.api.state.IndexTxStateUpdater.LabelChangeType.ADDED_LABEL; -import static org.neo4j.kernel.impl.api.state.IndexTxStateUpdater.LabelChangeType.REMOVED_LABEL; -import static org.neo4j.kernel.impl.util.Cursors.count; -import static org.neo4j.kernel.impl.util.Cursors.empty; -import static org.neo4j.register.Registers.newDoubleLongRegister; -import static org.neo4j.storageengine.api.txstate.TxStateVisitor.EMPTY; - -public class StateHandlingStatementOperations implements - KeyReadOperations, - KeyWriteOperations, - EntityOperations, - SchemaReadOperations, - SchemaWriteOperations, - CountsOperations, ExplicitIndexReadOperations, ExplicitIndexWriteOperations -{ - private final StoreReadLayer storeLayer; - private final AutoIndexing autoIndexing; - private final ConstraintIndexCreator constraintIndexCreator; - private final ExplicitIndexStore explicitIndexStore; - private final IndexTxStateUpdater indexTxStateUpdater; - - public StateHandlingStatementOperations( - StoreReadLayer storeLayer, AutoIndexing propertyTrackers, - ConstraintIndexCreator constraintIndexCreator, - ExplicitIndexStore explicitIndexStore, - IndexingService indexingService ) - { - this.storeLayer = storeLayer; - this.autoIndexing = propertyTrackers; - this.constraintIndexCreator = constraintIndexCreator; - this.explicitIndexStore = explicitIndexStore; - this.indexTxStateUpdater = new IndexTxStateUpdater( storeLayer, this, indexingService ); - } - - // - - @Override - public Cursor nodeCursorById( KernelStatement statement, long nodeId ) throws EntityNotFoundException - { - Cursor node = nodeCursor( statement, nodeId ); - if ( !node.next() ) - { - node.close(); - throw new EntityNotFoundException( EntityType.NODE, nodeId ); - } - return node; - } - - private Cursor nodeCursor( KernelStatement statement, long nodeId ) - { - Cursor cursor = statement.getStoreStatement().acquireSingleNodeCursor( nodeId ); - if ( statement.hasTxStateWithChanges() ) - { - return statement.txState().augmentSingleNodeCursor( cursor, nodeId ); - } - return cursor; - } - - @Override - public Cursor relationshipCursorById( KernelStatement statement, long relationshipId ) - throws EntityNotFoundException - { - Cursor relationship = relationshipCursor( statement, relationshipId ); - if ( !relationship.next() ) - { - relationship.close(); - throw new EntityNotFoundException( EntityType.RELATIONSHIP, relationshipId ); - } - return relationship; - } - - private Cursor relationshipCursor( KernelStatement statement, long relationshipId ) - { - Cursor cursor = - statement.getStoreStatement().acquireSingleRelationshipCursor( relationshipId ); - if ( statement.hasTxStateWithChanges() ) - { - return statement.txState().augmentSingleRelationshipCursor( cursor, relationshipId ); - } - return cursor; - } - - @Override - public Cursor relationshipCursorGetAll( KernelStatement statement ) - { - Cursor cursor = statement.getStoreStatement().relationshipsGetAllCursor(); - if ( statement.hasTxStateWithChanges() ) - { - return statement.txState().augmentRelationshipsGetAllCursor( cursor ); - } - return cursor; - } - - @Override - public Cursor nodeGetRelationships( KernelStatement statement, NodeItem node, - Direction direction ) - { - Cursor cursor; - if ( statement.hasTxStateWithChanges() && statement.txState().nodeIsAddedInThisTx( node.id() ) ) - { - cursor = empty(); - } - else - { - cursor = storeLayer.nodeGetRelationships( statement.getStoreStatement(), node, direction ); - } - if ( !statement.hasTxStateWithChanges() ) - { - return cursor; - } - NodeState nodeState = statement.txState().getNodeState( node.id() ); - return statement.txState().augmentNodeRelationshipCursor( cursor, nodeState, direction ); - } - - @Override - public Cursor nodeGetRelationships( KernelStatement statement, NodeItem node, Direction direction, - int[] relTypes ) - { - Cursor cursor; - if ( statement.hasTxStateWithChanges() && statement.txState().nodeIsAddedInThisTx( node.id() ) ) - { - cursor = empty(); - } - else - { - cursor = storeLayer.nodeGetRelationships( statement.getStoreStatement(), node, direction, any( relTypes ) ); - } - if ( !statement.hasTxStateWithChanges() ) - { - return cursor; - } - NodeState nodeState = statement.txState().getNodeState( node.id() ); - return statement.txState().augmentNodeRelationshipCursor( cursor, nodeState, direction, relTypes ); - } - - @Override - public Cursor nodeGetProperties( KernelStatement statement, NodeItem node ) - { - Cursor cursor; - if ( statement.hasTxStateWithChanges() && statement.txState().nodeIsAddedInThisTx( node.id() ) ) - { - cursor = empty(); - } - else - { - cursor = storeLayer.nodeGetProperties( statement.getStoreStatement(), node, statement ); - } - - return statement.hasTxStateWithChanges() - ? statement.txState().augmentPropertyCursor( cursor, statement.txState().getNodeState( node.id() ) ) - : cursor; - } - - @Override - public PrimitiveIntSet nodeGetPropertyKeys( KernelStatement statement, NodeItem node ) - { - final PrimitiveIntSet keys = Primitive.intSet(); - try ( Cursor properties = nodeGetProperties( statement, node ) ) - { - while ( properties.next() ) - { - keys.add( properties.get().propertyKeyId() ); - } - } - - return keys; - } - - @Override - public Value nodeGetProperty( KernelStatement statement, NodeItem node, int propertyKeyId ) - { - try ( Cursor cursor = nodeGetPropertyCursor( statement, node, propertyKeyId ) ) - { - if ( cursor.next() ) - { - return cursor.get().value(); - } - } - catch ( NotFoundException e ) - { - return Values.NO_VALUE; - } - - return Values.NO_VALUE; - } - - @Override - public boolean nodeHasProperty( KernelStatement statement, NodeItem node, int propertyKeyId ) - { - try ( Cursor cursor = nodeGetPropertyCursor( statement, node, propertyKeyId ) ) - { - return cursor.next(); - } - } - - private Cursor nodeGetPropertyCursor( KernelStatement statement, NodeItem node, int propertyKeyId ) - { - - Cursor cursor; - if ( statement.hasTxStateWithChanges() && statement.txState().nodeIsAddedInThisTx( node.id() ) ) - { - cursor = empty(); - } - else - { - cursor = storeLayer.nodeGetProperty( statement.getStoreStatement(), node, propertyKeyId, statement ); - } - - return statement.hasTxStateWithChanges() - ? statement.txState().augmentSinglePropertyCursor( - cursor, statement.txState().getNodeState( node.id() ), propertyKeyId ) - : cursor; - } - - @Override - public Cursor relationshipGetProperties( KernelStatement statement, RelationshipItem relationship ) - { - Cursor cursor; - if ( statement.hasTxStateWithChanges() && statement.txState().relationshipIsAddedInThisTx( relationship.id() ) ) - { - cursor = empty(); - } - else - { - cursor = storeLayer.relationshipGetProperties( statement.getStoreStatement(), relationship, statement ); - } - - return statement.hasTxStateWithChanges() - ? statement.txState() - .augmentPropertyCursor( cursor, statement.txState().getRelationshipState( relationship.id() ) ) - : cursor; - } - - @Override - public PrimitiveIntSet relationshipGetPropertyKeys( KernelStatement statement, - RelationshipItem relationship ) - { - final PrimitiveIntSet keys = Primitive.intSet(); - try ( Cursor properties = relationshipGetProperties( statement, relationship ) ) - { - while ( properties.next() ) - { - keys.add( properties.get().propertyKeyId() ); - } - } - - return keys; - } - - @Override - public Value relationshipGetProperty( KernelStatement statement, RelationshipItem relationship, int propertyKeyId ) - { - try ( Cursor cursor = relationshipGetPropertyCursor( statement, relationship, propertyKeyId ) ) - { - if ( cursor.next() ) - { - return cursor.get().value(); - } - } - catch ( NotFoundException e ) - { - return Values.NO_VALUE; - } - - return Values.NO_VALUE; - } - - @Override - public boolean relationshipHasProperty( KernelStatement statement, RelationshipItem relationship, int propertyKeyId ) - { - try ( Cursor cursor = relationshipGetPropertyCursor( statement, relationship, propertyKeyId ) ) - { - return cursor.next(); - } - } - - private Cursor relationshipGetPropertyCursor( KernelStatement statement, - RelationshipItem relationship, int propertyKeyId ) - { - Cursor cursor; - if ( statement.hasTxStateWithChanges() && statement.txState().relationshipIsAddedInThisTx( relationship.id() ) ) - { - cursor = empty(); - } - else - { - cursor = storeLayer - .relationshipGetProperty( statement.getStoreStatement(), relationship, propertyKeyId, statement ); - } - - return statement.hasTxStateWithChanges() - ? statement.txState().augmentSinglePropertyCursor( cursor, statement.txState() - .getRelationshipState( relationship.id() ), propertyKeyId ) - : cursor; - } - - // - - @Override - public long nodeCreate( KernelStatement state ) - { - long nodeId = state.getStoreStatement().reserveNode(); - state.txState().nodeDoCreate(nodeId); - return nodeId; - } - - @Override - public void nodeDelete( KernelStatement state, long nodeId ) - throws AutoIndexingKernelException, EntityNotFoundException, InvalidTransactionTypeKernelException - { - autoIndexing.nodes().entityRemoved( state.dataWriteOperations(), nodeId ); - try ( Cursor cursor = nodeCursorById( state, nodeId ) ) - { - state.txState().nodeDoDelete( cursor.get().id() ); - } - } - - @Override - public int nodeDetachDelete( KernelStatement state, long nodeId ) - throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException - { - nodeDelete( state, nodeId ); - return 0; - } - - @Override - public long relationshipCreate( KernelStatement state, - int relationshipTypeId, - long startNodeId, - long endNodeId ) - throws EntityNotFoundException - { - try ( Cursor startNode = nodeCursorById( state, startNodeId ) ) - { - try ( Cursor endNode = nodeCursorById( state, endNodeId ) ) - { - long id = state.getStoreStatement().reserveRelationship(); - state.txState().relationshipDoCreate( id, relationshipTypeId, startNode.get().id(), endNode.get().id() ); - return id; - } - } - } - - @Override - public void relationshipDelete( final KernelStatement state, long relationshipId ) - throws EntityNotFoundException, InvalidTransactionTypeKernelException, AutoIndexingKernelException - { - try ( Cursor cursor = relationshipCursorById( state, relationshipId ) ) - { - RelationshipItem relationship = cursor.get(); - - autoIndexing.relationships().entityRemoved( state.dataWriteOperations(), relationshipId ); - final TransactionState txState = state.txState(); - if ( txState.relationshipIsAddedInThisTx( relationship.id() ) ) - { - txState.relationshipDoDeleteAddedInThisTx( relationship.id() ); - } - else - { - txState.relationshipDoDelete( relationship.id(), relationship.type(), relationship.startNode(), - relationship.endNode() ); - } - } - } - - @Override - public PrimitiveLongIterator nodesGetAll( KernelStatement state ) - { - PrimitiveLongIterator iterator = storeLayer.nodesGetAll(); - return state.hasTxStateWithChanges() ? state.txState().augmentNodesGetAll( iterator ) : iterator; - } - - @Override - public RelationshipIterator relationshipsGetAll( KernelStatement state ) - { - RelationshipIterator iterator = storeLayer.relationshipsGetAll(); - return state.hasTxStateWithChanges() ? state.txState().augmentRelationshipsGetAll( iterator ) : iterator; - } - - @Override - public boolean nodeAddLabel( KernelStatement state, long nodeId, int labelId ) throws EntityNotFoundException - { - try ( Cursor cursor = nodeCursorById( state, nodeId ) ) - { - NodeItem node = cursor.get(); - if ( node.hasLabel( labelId ) ) - { - // Label is already in state or in store, no-op - return false; - } - - state.txState().nodeDoAddLabel( labelId, node.id() ); - - indexTxStateUpdater.onLabelChange( state, labelId, node, ADDED_LABEL ); - - return true; - } - } - - @Override - public boolean nodeRemoveLabel( KernelStatement state, long nodeId, int labelId ) throws EntityNotFoundException - { - try ( Cursor cursor = nodeCursorById( state, nodeId ) ) - { - NodeItem node = cursor.get(); - if ( !node.hasLabel( labelId ) ) - { - // Label does not exist in state or in store, no-op - return false; - } - - state.txState().nodeDoRemoveLabel( labelId, node.id() ); - - indexTxStateUpdater.onLabelChange( state, labelId, node, REMOVED_LABEL ); - - return true; - } - } - - @Override - public PrimitiveLongResourceIterator nodesGetForLabel( KernelStatement state, int labelId ) - { - PrimitiveLongResourceIterator committed = storeLayer.nodesGetForLabel( state.getStoreStatement(), labelId ); - if ( state.hasTxStateWithChanges() ) - { - PrimitiveLongResourceIterator wLabelChanges = state.txState().nodesWithLabelChanged( labelId ).augment( committed ); - return state.txState().addedAndRemovedNodes().augmentWithRemovals( wLabelChanges ); - } - - return committed; - } - - @Override - public long nodesGetCount( KernelStatement state ) - { - long base = storeLayer.nodesGetCount(); - return state.hasTxStateWithChanges() ? base + state.txState().addedAndRemovedNodes().delta() : base; - } - - @Override - public long relationshipsGetCount( KernelStatement state ) - { - long base = storeLayer.relationshipsGetCount(); - return state.hasTxStateWithChanges() ? base + state.txState().addedAndRemovedRelationships().delta() : base; - } - - @Override - public SchemaIndexDescriptor indexCreate( KernelStatement state, SchemaDescriptor descriptor ) - { - SchemaIndexDescriptor schemaIndexDescriptor = SchemaIndexDescriptorFactory.forSchema( descriptor ); - state.txState().indexRuleDoAdd( schemaIndexDescriptor ); - return schemaIndexDescriptor; - } - - @Override - public void indexDrop( KernelStatement state, SchemaIndexDescriptor descriptor ) - { - state.txState().indexDoDrop( descriptor ); - } - - @Override - public void uniqueIndexDrop( KernelStatement state, SchemaIndexDescriptor descriptor ) - { - state.txState().indexDoDrop( descriptor ); - } - - private void indexBackedConstraintCreate( KernelStatement state, IndexBackedConstraintDescriptor constraint ) - throws CreateConstraintFailureException - { - LabelSchemaDescriptor descriptor = constraint.schema(); - try - { - if ( state.hasTxStateWithChanges() && - state.txState().indexDoUnRemove( constraint.ownedIndexDescriptor() ) ) // ..., DROP, *CREATE* - { // creation is undoing a drop - if ( !state.txState().constraintDoUnRemove( constraint ) ) // CREATE, ..., DROP, *CREATE* - { // ... the drop we are undoing did itself undo a prior create... - state.txState().constraintDoAdd( - constraint, state.txState().indexCreatedForConstraint( constraint ) ); - } - } - else // *CREATE* - { // create from scratch - Iterator it = storeLayer.constraintsGetForSchema( descriptor ); - while ( it.hasNext() ) - { - if ( it.next().equals( constraint ) ) - { - return; - } - } - long indexId = constraintIndexCreator.createUniquenessConstraintIndex( state, this, descriptor ); - if ( !constraintExists( state, constraint ) ) - { - // This looks weird, but since we release the label lock while awaiting population of the index - // backing this constraint there can be someone else getting ahead of us, creating this exact constraint - // before we do, so now getting out here under the lock we must check again and if it exists - // we must at this point consider this an idempotent operation because we verified earlier - // that it didn't exist and went on to create it. - state.txState().constraintDoAdd( constraint, indexId ); - } - } - } - catch ( UniquePropertyValueValidationException | TransactionFailureException | AlreadyConstrainedException e ) - { - throw new CreateConstraintFailureException( constraint, e ); - } - } - - @Override - public NodeKeyConstraintDescriptor nodeKeyConstraintCreate( KernelStatement state, - LabelSchemaDescriptor descriptor ) - throws CreateConstraintFailureException - { - NodeKeyConstraintDescriptor constraint = ConstraintDescriptorFactory.nodeKeyForSchema( descriptor ); - indexBackedConstraintCreate( state, constraint ); - return constraint; - } - - @Override - public UniquenessConstraintDescriptor uniquePropertyConstraintCreate( KernelStatement state, SchemaDescriptor descriptor ) - throws CreateConstraintFailureException - { - UniquenessConstraintDescriptor constraint = ConstraintDescriptorFactory.uniqueForSchema( descriptor ); - indexBackedConstraintCreate( state, constraint ); - return constraint; - } - - @Override - public NodeExistenceConstraintDescriptor nodePropertyExistenceConstraintCreate( - KernelStatement state, - LabelSchemaDescriptor descriptor - ) - { - NodeExistenceConstraintDescriptor constraint = ConstraintDescriptorFactory.existsForSchema( descriptor ); - state.txState().constraintDoAdd( constraint ); - return constraint; - } - - @Override - public RelExistenceConstraintDescriptor relationshipPropertyExistenceConstraintCreate( - KernelStatement state, - RelationTypeSchemaDescriptor descriptor - ) - { - RelExistenceConstraintDescriptor constraint = ConstraintDescriptorFactory.existsForSchema( descriptor ); - state.txState().constraintDoAdd( constraint ); - return constraint; - } - - @Override - public Iterator constraintsGetForSchema( KernelStatement state, SchemaDescriptor descriptor ) - { - Iterator constraints = storeLayer.constraintsGetForSchema( descriptor ); - if ( state.hasTxStateWithChanges() ) - { - return state.txState().constraintsChangesForSchema( descriptor ).apply( constraints ); - } - return constraints; - } - - @Override - public boolean constraintExists( KernelStatement state, ConstraintDescriptor descriptor ) - { - boolean inStore = storeLayer.constraintExists( descriptor ); - if ( state.hasTxStateWithChanges() ) - { - ReadableDiffSets diffSet = - state.txState().constraintsChangesForSchema( descriptor.schema() ); - return diffSet.isAdded( descriptor ) || (inStore && !diffSet.isRemoved( descriptor )); - } - return inStore; - } - - @Override - public Iterator constraintsGetForLabel( KernelStatement state, int labelId ) - { - Iterator constraints = storeLayer.constraintsGetForLabel( labelId ); - if ( state.hasTxStateWithChanges() ) - { - return state.txState().constraintsChangesForLabel( labelId ).apply( constraints ); - } - return constraints; - } - - @Override - public Iterator constraintsGetForRelationshipType( KernelStatement state, - int typeId ) - { - Iterator constraints = storeLayer.constraintsGetForRelationshipType( typeId ); - if ( state.hasTxStateWithChanges() ) - { - return state.txState().constraintsChangesForRelationshipType( typeId ).apply( constraints ); - } - return constraints; - } - - @Override - public Iterator constraintsGetAll( KernelStatement state ) - { - Iterator constraints = storeLayer.constraintsGetAll(); - if ( state.hasTxStateWithChanges() ) - { - return state.txState().constraintsChanges().apply( constraints ); - } - return constraints; - } - - @Override - public void constraintDrop( KernelStatement state, ConstraintDescriptor constraint ) - { - state.txState().constraintDoDrop( constraint ); - } - - @Override - public SchemaIndexDescriptor indexGetForSchema( KernelStatement state, SchemaDescriptor descriptor ) - { - SchemaIndexDescriptor schemaIndexDescriptor = storeLayer.indexGetForSchema( descriptor ); - Iterator rules = iterator( schemaIndexDescriptor ); - if ( state.hasTxStateWithChanges() ) - { - rules = filter( - SchemaDescriptor.equalTo( descriptor ), - state.txState().indexDiffSetsByLabel( descriptor.keyId() ).apply( rules ) ); - } - return singleOrNull( rules ); - } - - @Override - public InternalIndexState indexGetState( KernelStatement state, SchemaIndexDescriptor descriptor ) - throws IndexNotFoundKernelException - { - // If index is in our state, then return populating - if ( state.hasTxStateWithChanges() ) - { - if ( checkIndexState( descriptor, - state.txState().indexDiffSetsByLabel( descriptor.schema().keyId() ) ) ) - { - return InternalIndexState.POPULATING; - } - } - - return storeLayer.indexGetState( descriptor ); - } - - @Override - public IndexProvider.Descriptor indexGetProviderDescriptor( KernelStatement state, SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException - { - if ( state.hasTxStateWithChanges() ) - { - if ( checkIndexState( descriptor, - state.txState().indexDiffSetsByLabel( descriptor.schema().keyId() ) ) ) - { - return IndexProvider.UNDECIDED; - } - } - return storeLayer.indexGetProviderDescriptor( descriptor ); - } - - @Override - public PopulationProgress indexGetPopulationProgress( KernelStatement state, SchemaIndexDescriptor descriptor ) throws - IndexNotFoundKernelException - { - // If index is in our state, then return 0% - if ( state.hasTxStateWithChanges() ) - { - if ( checkIndexState( descriptor, - state.txState().indexDiffSetsByLabel( descriptor.schema().keyId() ) ) ) - { - return PopulationProgress.NONE; - } - } - - return storeLayer.indexGetPopulationProgress( descriptor.schema() ); - } - - private boolean checkIndexState( SchemaIndexDescriptor index, ReadableDiffSets diffSet ) - throws IndexNotFoundKernelException - { - if ( diffSet.isAdded( index ) ) - { - return true; - } - if ( diffSet.isRemoved( index ) ) - { - throw new IndexNotFoundKernelException( format( "Index on %s has been dropped in this transaction.", - index.userDescription( SchemaUtil.idTokenNameLookup ) ) ); - } - return false; - } - - @Override - public Iterator indexesGetForLabel( KernelStatement state, int labelId ) - { - if ( state.hasTxStateWithChanges() ) - { - return state.txState().indexDiffSetsByLabel( labelId ) - .apply( storeLayer.indexesGetForLabel( labelId ) ); - } - return storeLayer.indexesGetForLabel( labelId ); - } - - @Override - public Iterator indexesGetAll( KernelStatement state ) - { - if ( state.hasTxStateWithChanges() ) - { - return state.txState().indexChanges().apply( storeLayer.indexesGetAll() ); - } - - return storeLayer.indexesGetAll(); - } - - @Override - public long nodeGetFromUniqueIndexSeek( - KernelStatement state, SchemaIndexDescriptor index, IndexQuery.ExactPredicate... query ) - throws IndexNotFoundKernelException, IndexNotApplicableKernelException - { - try ( IndexReader reader = state.getStoreStatement().getFreshIndexReader( index ) ) - { - /* Here we have an intricate scenario where we need to return the PrimitiveLongIterator - * since subsequent filtering will happen outside, but at the same time have the ability to - * close the IndexReader when done iterating over the lookup result. This is because we get - * a fresh reader that isn't associated with the current transaction and hence will not be - * automatically closed. */ - PrimitiveLongResourceIterator committed = reader.query( query ); - PrimitiveLongResourceIterator exactMatches = reader.hasFullValuePrecision( query ) - ? committed : LookupFilter.exactIndexMatches( this, state, committed, query ); - PrimitiveLongResourceIterator changesFiltered = - filterIndexStateChangesForSeek( state, exactMatches, index, IndexQuery.asValueTuple( query ) ); - return single( resourceIterator( changesFiltered, committed ), NO_SUCH_NODE ); - } - } - - @Override - public PrimitiveLongResourceIterator indexQuery( KernelStatement state, SchemaIndexDescriptor index, IndexQuery... predicates ) - throws IndexNotFoundKernelException, IndexNotApplicableKernelException - { - StorageStatement storeStatement = state.getStoreStatement(); - IndexReader reader = storeStatement.getIndexReader( index ); - PrimitiveLongResourceIterator committed = reader.query( predicates ); - PrimitiveLongResourceIterator exactMatches = reader.hasFullValuePrecision( predicates ) - ? committed : LookupFilter.exactIndexMatches( this, state, committed, predicates ); - - IndexQuery firstPredicate = predicates[0]; - switch ( firstPredicate.type() ) - { - case exact: - IndexQuery.ExactPredicate[] exactPreds = assertOnlyExactPredicates( predicates ); - return filterIndexStateChangesForSeek( state, exactMatches, index, IndexQuery.asValueTuple( exactPreds ) ); - - case stringSuffix: - case stringContains: - case exists: - return filterIndexStateChangesForScan( state, exactMatches, index ); - - case range: - assertSinglePredicate( predicates ); - IndexQuery.RangePredicate rangePred = (IndexQuery.RangePredicate) firstPredicate; - return filterIndexStateChangesForRangeSeek( state, index, rangePred.valueGroup(), - rangePred.fromValue(), rangePred.fromInclusive(), - rangePred.toValue(), rangePred.toInclusive(), - exactMatches ); - - case stringPrefix: - { - assertSinglePredicate( predicates ); - IndexQuery.StringPrefixPredicate strPred = (IndexQuery.StringPrefixPredicate) firstPredicate; - return filterIndexStateChangesForRangeSeekByPrefix( state, index, strPred.prefix(), committed ); - } - default: - throw new UnsupportedOperationException( "Query not supported: " + Arrays.toString( predicates ) ); - } - } - - public static IndexQuery.ExactPredicate[] assertOnlyExactPredicates( IndexQuery[] predicates ) - { - IndexQuery.ExactPredicate[] exactPredicates; - if ( predicates.getClass() == IndexQuery.ExactPredicate[].class ) - { - exactPredicates = (IndexQuery.ExactPredicate[]) predicates; - } - else - { - exactPredicates = new IndexQuery.ExactPredicate[predicates.length]; - for ( int i = 0; i < predicates.length; i++ ) - { - if ( predicates[i] instanceof IndexQuery.ExactPredicate ) - { - exactPredicates[i] = (IndexQuery.ExactPredicate) predicates[i]; - } - else - { - // TODO: what to throw? - throw new UnsupportedOperationException( "Query not supported: " + Arrays.toString( predicates ) ); - } - } - } - return exactPredicates; - } - - private void assertSinglePredicate( IndexQuery[] predicates ) - { - if ( predicates.length != 1 ) - { - // TODO: what to throw? - throw new UnsupportedOperationException( "Query not supported: " + Arrays.toString( predicates ) ); - } - } - - @Override - public long nodesCountIndexed( KernelStatement statement, SchemaIndexDescriptor index, long nodeId, Value value ) - throws IndexNotFoundKernelException - { - IndexReader reader = statement.getStoreStatement().getIndexReader( index ); - return reader.countIndexedNodes( nodeId, value ); - } - - private PrimitiveLongResourceIterator filterIndexStateChangesForScan( - KernelStatement state, PrimitiveLongResourceIterator nodeIds, SchemaIndexDescriptor index ) - { - if ( state.hasTxStateWithChanges() ) - { - PrimitiveLongReadableDiffSets labelPropertyChanges = - state.txState().indexUpdatesForScan( index ); - ReadableDiffSets nodes = state.txState().addedAndRemovedNodes(); - - // Apply to actual index lookup - return nodes.augmentWithRemovals( labelPropertyChanges.augment( nodeIds ) ); - } - return nodeIds; - } - - private PrimitiveLongResourceIterator filterIndexStateChangesForSeek( - KernelStatement state, PrimitiveLongResourceIterator nodeIds, SchemaIndexDescriptor index, - ValueTuple propertyValues ) - { - if ( state.hasTxStateWithChanges() ) - { - PrimitiveLongReadableDiffSets labelPropertyChanges = - state.txState().indexUpdatesForSeek( index, propertyValues ); - ReadableDiffSets nodes = state.txState().addedAndRemovedNodes(); - - // Apply to actual index lookup - return nodes.augmentWithRemovals( labelPropertyChanges.augment( nodeIds ) ); - } - return nodeIds; - } - - private PrimitiveLongResourceIterator filterIndexStateChangesForRangeSeek( KernelStatement state, - SchemaIndexDescriptor index, ValueGroup valueGroup, - Value lower, boolean includeLower, - Value upper, boolean includeUpper, - PrimitiveLongResourceIterator nodeIds ) - { - if ( state.hasTxStateWithChanges() ) - { - TransactionState txState = state.txState(); - PrimitiveLongReadableDiffSets labelPropertyChangesForString = txState.indexUpdatesForRangeSeek( - index, valueGroup, lower, includeLower, upper, includeUpper ); - ReadableDiffSets nodes = txState.addedAndRemovedNodes(); - - // Apply to actual index lookup - return nodes.augmentWithRemovals( labelPropertyChangesForString.augment( nodeIds ) ); - } - return nodeIds; - } - - private PrimitiveLongResourceIterator filterIndexStateChangesForRangeSeekByPrefix( KernelStatement state, - SchemaIndexDescriptor index, - String prefix, - PrimitiveLongResourceIterator nodeIds ) - { - if ( state.hasTxStateWithChanges() ) - { - TransactionState txState = state.txState(); - PrimitiveLongReadableDiffSets labelPropertyChangesForPrefix = - txState.indexUpdatesForRangeSeekByPrefix( index, prefix ); - ReadableDiffSets nodes = txState.addedAndRemovedNodes(); - - // Apply to actual index lookup - return nodes.augmentWithRemovals( labelPropertyChangesForPrefix.augment( nodeIds ) ); - } - return nodeIds; - } - - @Override - public Value nodeSetProperty( KernelStatement state, long nodeId, int propertyKeyId, Value value ) - throws EntityNotFoundException, InvalidTransactionTypeKernelException, AutoIndexingKernelException - { - DataWriteOperations ops = state.dataWriteOperations(); - try ( Cursor cursor = nodeCursorById( state, nodeId ) ) - { - NodeItem node = cursor.get(); - Value existingValue = Values.NO_VALUE; - try ( Cursor properties = nodeGetPropertyCursor( state, node, propertyKeyId ) ) - { - if ( !properties.next() ) - { - autoIndexing.nodes().propertyAdded( ops, nodeId, propertyKeyId, value ); - } - else - { - existingValue = properties.get().value(); - autoIndexing.nodes().propertyChanged( ops, nodeId, propertyKeyId, existingValue, value ); - } - } - - if ( existingValue == Values.NO_VALUE ) - { - state.txState().nodeDoAddProperty( node.id(), propertyKeyId, value ); - indexTxStateUpdater.onPropertyAdd( state, node, propertyKeyId, value ); - return Values.NO_VALUE; - } - else - { - if ( propertyHasChanged( value, existingValue ) ) - { - state.txState().nodeDoChangeProperty( node.id(), propertyKeyId, existingValue, value ); - indexTxStateUpdater.onPropertyChange( state, node, propertyKeyId, existingValue, value ); - } - return existingValue; - } - } - } - - @Override - public Value relationshipSetProperty( KernelStatement state, long relationshipId, int propertyKeyId, Value value ) - throws EntityNotFoundException, InvalidTransactionTypeKernelException, AutoIndexingKernelException - { - DataWriteOperations ops = state.dataWriteOperations(); - try ( Cursor cursor = relationshipCursorById( state, relationshipId ) ) - { - RelationshipItem relationship = cursor.get(); - Value existingValue = Values.NO_VALUE; - try ( Cursor properties = relationshipGetPropertyCursor( state, relationship, propertyKeyId ) ) - { - if ( !properties.next() ) - { - autoIndexing.relationships().propertyAdded( ops, relationshipId, propertyKeyId, value ); - } - else - { - existingValue = properties.get().value(); - autoIndexing.relationships().propertyChanged( - ops, relationshipId, propertyKeyId, existingValue, value ); - } - } - if ( propertyHasChanged( value, existingValue ) ) - { - state.txState().relationshipDoReplaceProperty( - relationship.id(), propertyKeyId, existingValue, value ); - } - return existingValue; - } - } - - @Override - public Value graphSetProperty( KernelStatement state, int propertyKeyId, Value value ) - { - Value existingValue = graphGetProperty( state, propertyKeyId ); - - if ( !value.equals( existingValue ) ) - { - state.txState().graphDoReplaceProperty( propertyKeyId, existingValue, value ); - } - - return existingValue; - } - - @Override - public Value nodeRemoveProperty( KernelStatement state, long nodeId, int propertyKeyId ) - throws EntityNotFoundException, InvalidTransactionTypeKernelException, AutoIndexingKernelException - { - DataWriteOperations ops = state.dataWriteOperations(); - try ( Cursor cursor = nodeCursorById( state, nodeId ) ) - { - NodeItem node = cursor.get(); - Value existingValue = Values.NO_VALUE; - try ( Cursor properties = nodeGetPropertyCursor( state, node, propertyKeyId ) ) - { - if ( properties.next() ) - { - existingValue = properties.get().value(); - - autoIndexing.nodes().propertyRemoved( ops, nodeId, propertyKeyId ); - state.txState().nodeDoRemoveProperty( node.id(), propertyKeyId ); - - indexTxStateUpdater.onPropertyRemove( state, node, propertyKeyId, existingValue ); - } - } - return existingValue; - } - } - - @Override - public Value relationshipRemoveProperty( KernelStatement state, long relationshipId, int propertyKeyId ) - throws EntityNotFoundException, InvalidTransactionTypeKernelException, AutoIndexingKernelException - { - DataWriteOperations ops = state.dataWriteOperations(); - try ( Cursor cursor = relationshipCursorById( state, relationshipId ) ) - { - RelationshipItem relationship = cursor.get(); - Value existingValue = Values.NO_VALUE; - try ( Cursor properties = relationshipGetPropertyCursor( state, relationship, - propertyKeyId ) ) - { - if ( properties.next() ) - { - existingValue = properties.get().value(); - - autoIndexing.relationships().propertyRemoved( ops, relationshipId, propertyKeyId ); - state.txState().relationshipDoRemoveProperty( relationship.id(), propertyKeyId ); - } - } - return existingValue; - } - } - - @Override - public Value graphRemoveProperty( KernelStatement state, int propertyKeyId ) - { - Value existingValue = graphGetProperty( state, propertyKeyId ); - if ( existingValue != Values.NO_VALUE ) - { - state.txState().graphDoRemoveProperty( propertyKeyId ); - } - return existingValue; - } - - @Override - public PrimitiveIntIterator graphGetPropertyKeys( KernelStatement state ) - { - if ( state.hasTxStateWithChanges() ) - { - return new PropertyKeyIdIterator( graphGetAllProperties( state ) ); - } - - return storeLayer.graphGetPropertyKeys(); - } - - @Override - public boolean graphHasProperty( KernelStatement state, int propertyKeyId ) - { - return graphGetProperty( state, propertyKeyId ) != Values.NO_VALUE; - } - - @Override - public Value graphGetProperty( KernelStatement state, int propertyKeyId ) - { - Iterator properties = graphGetAllProperties( state ); - while ( properties.hasNext() ) - { - StorageProperty property = properties.next(); - if ( property.propertyKeyId() == propertyKeyId ) - { - return property.value(); - } - } - return Values.NO_VALUE; - } - - private Iterator graphGetAllProperties( KernelStatement state ) - { - if ( state.hasTxStateWithChanges() ) - { - return state.txState().augmentGraphProperties( storeLayer.graphGetAllProperties() ); - } - - return storeLayer.graphGetAllProperties(); - } - - @Override - public long countsForNode( final KernelStatement statement, int labelId ) - { - long count = countsForNodeWithoutTxState( statement, labelId ); - if ( statement.hasTxStateWithChanges() ) - { - CountsRecordState counts = new CountsRecordState(); - try - { - statement.txState().accept( new TransactionCountingStateVisitor( EMPTY, storeLayer, - statement.getStoreStatement(), statement.txState(), counts ) ); - if ( counts.hasChanges() ) - { - count += counts.nodeCount( labelId, newDoubleLongRegister() ).readSecond(); - } - } - catch ( ConstraintValidationException | CreateConstraintFailureException e ) - { - throw new IllegalArgumentException( "Unexpected error: " + e.getMessage() ); - } - } - return count; - } - - @Override - public long countsForNodeWithoutTxState( final KernelStatement statement, int labelId ) - { - return storeLayer.countsForNode( labelId ); - } - - @Override - public long countsForRelationship( KernelStatement statement, int startLabelId, int typeId, int endLabelId ) - { - long count = countsForRelationshipWithoutTxState( statement, startLabelId, typeId, endLabelId ); - if ( statement.hasTxStateWithChanges() ) - { - CountsRecordState counts = new CountsRecordState(); - try - { - statement.txState().accept( new TransactionCountingStateVisitor( EMPTY, storeLayer, - statement.getStoreStatement(), statement.txState(), counts ) ); - if ( counts.hasChanges() ) - { - count += counts.relationshipCount( startLabelId, typeId, endLabelId, newDoubleLongRegister() ) - .readSecond(); - } - } - catch ( ConstraintValidationException | CreateConstraintFailureException e ) - { - throw new IllegalArgumentException( "Unexpected error: " + e.getMessage() ); - } - } - return count; - } - - @Override - public long countsForRelationshipWithoutTxState( KernelStatement statement, int startLabelId, int typeId, - int endLabelId ) - { - return storeLayer.countsForRelationship( startLabelId, typeId, endLabelId ); - } - - @Override - public long indexSize( KernelStatement statement, SchemaIndexDescriptor descriptor ) - throws IndexNotFoundKernelException - { - return storeLayer.indexSize( descriptor.schema() ); - } - - @Override - public double indexUniqueValuesPercentage( KernelStatement statement, SchemaIndexDescriptor descriptor ) - throws IndexNotFoundKernelException - { - return storeLayer.indexUniqueValuesPercentage( descriptor.schema() ); - } - - @Override - public DoubleLongRegister indexUpdatesAndSize( KernelStatement statement, SchemaIndexDescriptor index, - DoubleLongRegister target ) throws IndexNotFoundKernelException - { - return storeLayer.indexUpdatesAndSize( index.schema(), target ); - } - - @Override - public DoubleLongRegister indexSample( KernelStatement statement, SchemaIndexDescriptor index, DoubleLongRegister target ) - throws IndexNotFoundKernelException - { - return storeLayer.indexSample( index.schema(), target ); - } - - // - // Methods that delegate directly to storage - // - - @Override - public Long indexGetOwningUniquenessConstraintId( KernelStatement state, SchemaIndexDescriptor index ) - { - return storeLayer.indexGetOwningUniquenessConstraintId( index ); - } - - @Override - public long indexGetCommittedId( KernelStatement state, SchemaIndexDescriptor index ) - throws SchemaRuleNotFoundException - { - return storeLayer.indexGetCommittedId( index ); - } - - @Override - public String indexGetFailure( Statement state, SchemaIndexDescriptor descriptor ) - throws IndexNotFoundKernelException - { - return storeLayer.indexGetFailure( descriptor.schema() ); - } - - @Override - public int labelGetForName( Statement state, String labelName ) - { - return storeLayer.labelGetForName( labelName ); - } - - @Override - public String labelGetName( Statement state, int labelId ) throws LabelNotFoundKernelException - { - return storeLayer.labelGetName( labelId ); - } - - @Override - public int propertyKeyGetForName( Statement state, String propertyKeyName ) - { - return storeLayer.propertyKeyGetForName( propertyKeyName ); - } - - @Override - public String propertyKeyGetName( Statement state, int propertyKeyId ) throws PropertyKeyIdNotFoundKernelException - { - return storeLayer.propertyKeyGetName( propertyKeyId ); - } - - @Override - public Iterator propertyKeyGetAllTokens( Statement state ) - { - return storeLayer.propertyKeyGetAllTokens(); - } - - @Override - public Iterator labelsGetAllTokens( Statement state ) - { - return storeLayer.labelsGetAllTokens(); - } - - @Override - public Iterator relationshipTypesGetAllTokens( Statement state ) - { - return storeLayer.relationshipTypeGetAllTokens(); - } - - @Override - public int relationshipTypeGetForName( Statement state, String relationshipTypeName ) - { - return storeLayer.relationshipTypeGetForName( relationshipTypeName ); - } - - @Override - public String relationshipTypeGetName( Statement state, int relationshipTypeId ) throws - RelationshipTypeIdNotFoundKernelException - { - return storeLayer.relationshipTypeGetName( relationshipTypeId ); - } - - @Override - public int labelGetOrCreateForName( Statement state, String labelName ) throws TooManyLabelsException - { - return storeLayer.labelGetOrCreateForName( labelName ); - } - - @Override - public int propertyKeyGetOrCreateForName( Statement state, String propertyKeyName ) - { - return storeLayer.propertyKeyGetOrCreateForName( propertyKeyName ); - } - - @Override - public int relationshipTypeGetOrCreateForName( Statement state, String relationshipTypeName ) - { - return storeLayer.relationshipTypeGetOrCreateForName( relationshipTypeName ); - } - - @Override - public void labelCreateForName( KernelStatement state, String labelName, - int id ) - { - state.txState().labelDoCreateForName( labelName, id ); - } - - @Override - public void propertyKeyCreateForName( KernelStatement state, - String propertyKeyName, - int id ) - { - state.txState().propertyKeyDoCreateForName( propertyKeyName, id ); - - } - - @Override - public void relationshipTypeCreateForName( KernelStatement state, - String relationshipTypeName, - int id ) - { - state.txState().relationshipTypeDoCreateForName( relationshipTypeName, id ); - } - - @Override - public int labelCount( KernelStatement statement ) - { - return storeLayer.labelCount(); - } - - @Override - public int propertyKeyCount( KernelStatement statement ) - { - return storeLayer.propertyKeyCount(); - } - - @Override - public int relationshipTypeCount( KernelStatement statement ) - { - return storeLayer.relationshipTypeCount(); - } - - @Override - public void relationshipVisit( KernelStatement statement, - long relId, RelationshipVisitor visitor ) throws EntityNotFoundException, EXCEPTION - { - if ( statement.hasTxStateWithChanges() ) - { - if ( statement.txState().relationshipVisit( relId, visitor ) ) - { - return; - } - } - storeLayer.relationshipVisit( relId, visitor ); - } - - // - @Override - public boolean nodeExplicitIndexExists( KernelStatement statement, String indexName, Map customConfiguration ) - { - return statement.explicitIndexTxState().checkIndexExistence( IndexEntityType.Node, indexName, customConfiguration ); - } - - @Override - public boolean relationshipExplicitIndexExists( KernelStatement statement, String indexName, Map customConfiguration ) - { - return statement.explicitIndexTxState().checkIndexExistence( IndexEntityType.Relationship, indexName, customConfiguration ); - } - - @Override - public ExplicitIndexHits nodeExplicitIndexGet( KernelStatement statement, String indexName, String key, Object value ) - throws ExplicitIndexNotFoundKernelException - { - return statement.explicitIndexTxState().nodeChanges( indexName ).get( key, value ); - } - - @Override - public ExplicitIndexHits nodeExplicitIndexQuery( KernelStatement statement, String indexName, String key, - Object queryOrQueryObject ) throws ExplicitIndexNotFoundKernelException - { - return statement.explicitIndexTxState().nodeChanges( indexName ).query( key, queryOrQueryObject ); - } - - @Override - public ExplicitIndexHits nodeExplicitIndexQuery( KernelStatement statement, - String indexName, - Object queryOrQueryObject ) - throws ExplicitIndexNotFoundKernelException - { - return statement.explicitIndexTxState().nodeChanges( indexName ).query( queryOrQueryObject ); - } - - @Override - public ExplicitIndexHits relationshipExplicitIndexGet( KernelStatement statement, String indexName, String key, - Object value, long startNode, long endNode ) throws ExplicitIndexNotFoundKernelException - { - ExplicitIndex index = statement.explicitIndexTxState().relationshipChanges( indexName ); - if ( startNode != -1 || endNode != -1 ) - { - return index.get( key, value, startNode, endNode ); - } - return index.get( key, value ); - } - - @Override - public ExplicitIndexHits relationshipExplicitIndexQuery( KernelStatement statement, String indexName, String key, - Object queryOrQueryObject, long startNode, long endNode ) throws ExplicitIndexNotFoundKernelException - { - ExplicitIndex index = statement.explicitIndexTxState().relationshipChanges( indexName ); - if ( startNode != -1 || endNode != -1 ) - { - return index.query( key, queryOrQueryObject, startNode, endNode ); - } - return index.query( key, queryOrQueryObject ); - } - - @Override - public ExplicitIndexHits relationshipExplicitIndexQuery( KernelStatement statement, String indexName, - Object queryOrQueryObject, long startNode, long endNode ) throws ExplicitIndexNotFoundKernelException - { - ExplicitIndex index = statement.explicitIndexTxState().relationshipChanges( indexName ); - if ( startNode != -1 || endNode != -1 ) - { - return index.query( queryOrQueryObject, startNode, endNode ); - } - return index.query( queryOrQueryObject ); - } - - @Override - public void nodeExplicitIndexCreateLazily( KernelStatement statement, String indexName, - Map customConfig ) - { - explicitIndexStore.getOrCreateNodeIndexConfig( indexName, customConfig ); - } - - @Override - public void nodeExplicitIndexCreate( KernelStatement statement, String indexName, Map customConfig ) - { - statement.explicitIndexTxState().createIndex( IndexEntityType.Node, indexName, customConfig ); - } - - @Override - public void relationshipExplicitIndexCreateLazily( KernelStatement statement, String indexName, - Map customConfig ) - { - explicitIndexStore.getOrCreateRelationshipIndexConfig( indexName, customConfig ); - } - - @Override - public void relationshipExplicitIndexCreate( KernelStatement statement, - String indexName, - Map customConfig ) - { - statement.explicitIndexTxState().createIndex( IndexEntityType.Relationship, indexName, customConfig ); - } - - @Override - public void nodeAddToExplicitIndex( KernelStatement statement, String indexName, long node, String key, Object value ) - throws ExplicitIndexNotFoundKernelException - { - statement.explicitIndexTxState().nodeChanges( indexName ).addNode( node, key, value ); - } - - @Override - public void nodeRemoveFromExplicitIndex( KernelStatement statement, String indexName, long node, String key, - Object value ) throws ExplicitIndexNotFoundKernelException - { - statement.explicitIndexTxState().nodeChanges( indexName ).remove( node, key, value ); - } - - @Override - public void nodeRemoveFromExplicitIndex( KernelStatement statement, String indexName, long node, String key ) - throws ExplicitIndexNotFoundKernelException - { - statement.explicitIndexTxState().nodeChanges( indexName ).remove( node, key ); - } - - @Override - public void nodeRemoveFromExplicitIndex( KernelStatement statement, String indexName, long node ) - throws ExplicitIndexNotFoundKernelException - { - statement.explicitIndexTxState().nodeChanges( indexName ).remove( node ); - } - - @Override - public void relationshipAddToExplicitIndex( final KernelStatement statement, final String indexName, - final long relationship, final String key, final Object value ) - throws EntityNotFoundException, ExplicitIndexNotFoundKernelException - { - relationshipVisit( statement, relationship, - ( relId, type, startNode, endNode ) -> statement.explicitIndexTxState().relationshipChanges( indexName ).addRelationship( - relationship, key, value, startNode, endNode ) ); - } - - @Override - public void relationshipRemoveFromExplicitIndex( final KernelStatement statement, - final String indexName, - long relationship, - final String key, - final Object value ) throws ExplicitIndexNotFoundKernelException - { - try - { - relationshipVisit( statement, relationship, ( relId, type, startNode, endNode ) -> - statement.explicitIndexTxState().relationshipChanges( indexName ).removeRelationship( - relId, key, value, startNode, endNode ) ); - } - catch ( EntityNotFoundException e ) - { // Apparently this is OK - } - } - - @Override - public void relationshipRemoveFromExplicitIndex( final KernelStatement statement, - final String indexName, - long relationship, - final String key ) throws ExplicitIndexNotFoundKernelException - { - try - { - relationshipVisit( statement, relationship, ( relId, type, startNode, endNode ) -> - statement.explicitIndexTxState().relationshipChanges( indexName ).removeRelationship( - relId, key, startNode, endNode ) ); - } - catch ( EntityNotFoundException e ) - { // Apparently this is OK - } - } - - @Override - public void relationshipRemoveFromExplicitIndex( final KernelStatement statement, - final String indexName, - long relationship ) - throws ExplicitIndexNotFoundKernelException - { - try - { - relationshipVisit( statement, relationship, ( relId, type, startNode, endNode ) -> - statement.explicitIndexTxState().relationshipChanges( indexName ).removeRelationship( - relId, startNode, endNode ) ); - } - catch ( EntityNotFoundException e ) - { - // This is a special case which is still OK. This method is called lazily where deleted relationships - // that still are referenced by an explicit index will be added for removal in this transaction. - // Ideally we'd want to include start/end node too, but we can't since the relationship doesn't exist. - // So we do the "normal" remove call on the explicit index transaction changes. The downside is that - // Some queries on this transaction state that include start/end nodes might produce invalid results. - statement.explicitIndexTxState().relationshipChanges( indexName ).remove( relationship ); - } - } - - @Override - public void nodeExplicitIndexDrop( KernelStatement statement, - String indexName ) throws ExplicitIndexNotFoundKernelException - { - statement.explicitIndexTxState().nodeChanges( indexName ).drop(); - statement.explicitIndexTxState().deleteIndex( IndexEntityType.Node, indexName ); - } - - @Override - public void relationshipExplicitIndexDrop( KernelStatement statement, String indexName ) - throws ExplicitIndexNotFoundKernelException - { - statement.explicitIndexTxState().relationshipChanges( indexName ).drop(); - statement.explicitIndexTxState().deleteIndex( IndexEntityType.Relationship, indexName ); - } - - @Override - public String nodeExplicitIndexSetConfiguration( KernelStatement statement, - String indexName, - String key, - String value ) - throws ExplicitIndexNotFoundKernelException - { - return explicitIndexStore.setNodeIndexConfiguration( indexName, key, value ); - } - - @Override - public String relationshipExplicitIndexSetConfiguration( KernelStatement statement, String indexName, String key, - String value ) throws ExplicitIndexNotFoundKernelException - { - return explicitIndexStore.setRelationshipIndexConfiguration( indexName, key, value ); - } - - @Override - public String nodeExplicitIndexRemoveConfiguration( KernelStatement statement, String indexName, String key ) - throws ExplicitIndexNotFoundKernelException - { - return explicitIndexStore.removeNodeIndexConfiguration( indexName, key ); - } - - @Override - public String relationshipExplicitIndexRemoveConfiguration( KernelStatement statement, String indexName, String key ) - throws ExplicitIndexNotFoundKernelException - { - return explicitIndexStore.removeRelationshipIndexConfiguration( indexName, key ); - } - - @Override - public Map nodeExplicitIndexGetConfiguration( KernelStatement statement, String indexName ) - throws ExplicitIndexNotFoundKernelException - { - return explicitIndexStore.getNodeIndexConfiguration( indexName ); - } - - @Override - public Map relationshipExplicitIndexGetConfiguration( KernelStatement statement, String indexName ) - throws ExplicitIndexNotFoundKernelException - { - return explicitIndexStore.getRelationshipIndexConfiguration( indexName ); - } - - @Override - public String[] nodeExplicitIndexesGetAll( KernelStatement statement ) - { - return explicitIndexStore.getAllNodeIndexNames(); - } - - @Override - public String[] relationshipExplicitIndexesGetAll( KernelStatement statement ) - { - return explicitIndexStore.getAllRelationshipIndexNames(); - } - // - - @Override - public boolean nodeExists( KernelStatement statement, long id ) - { - if ( statement.hasTxStateWithChanges() ) - { - TransactionState txState = statement.txState(); - if ( txState.nodeIsDeletedInThisTx( id ) ) - { - return false; - } - else if ( txState.nodeIsAddedInThisTx( id ) ) - { - return true; - } - } - return storeLayer.nodeExists( id ); - } - - @Override - public PrimitiveIntSet relationshipTypes( KernelStatement statement, NodeItem node ) - { - if ( statement.hasTxStateWithChanges() && statement.txState().nodeIsAddedInThisTx( node.id() ) ) - { - return statement.txState().getNodeState( node.id() ).relationshipTypes(); - } - - // Read types in the current transaction - PrimitiveIntSet types = statement.hasTxStateWithChanges() - ? statement.txState().getNodeState( node.id() ).relationshipTypes() - : Primitive.intSet(); - - // Augment with types stored on disk, minus any types where all rels of that type are deleted - // in current tx. - types.addAll( filter( storeLayer.relationshipTypes( statement.getStoreStatement(), node ).iterator(), - current -> !types.contains( current ) && degree( statement, node, Direction.BOTH, current ) > 0 ) ); - - return types; - } - - @Override - public int degree( KernelStatement statement, NodeItem node, Direction direction ) - { - int degree = statement.hasTxStateWithChanges() && statement.txState().nodeIsAddedInThisTx( node.id() ) - ? 0 - : computeDegree( statement, node, direction, null ); - - return statement.hasTxStateWithChanges() - ? statement.txState().getNodeState( node.id() ).augmentDegree( direction, degree ) - : degree; - } - - @Override - public int degree( KernelStatement statement, NodeItem node, Direction direction, int relType ) - { - int degree = statement.hasTxStateWithChanges() && statement.txState().nodeIsAddedInThisTx( node.id() ) - ? 0 - : computeDegree( statement, node, direction, relType ); - - return statement.hasTxStateWithChanges() - ? statement.txState().getNodeState( node.id() ).augmentDegree( direction, degree, relType ) - : degree; - } - - private int computeDegree( KernelStatement statement, NodeItem node, Direction direction, Integer relType ) - { - StorageStatement storeStatement = statement.getStoreStatement(); - if ( node.isDense() ) - { - return storeLayer.degreeRelationshipsInGroup( storeStatement, node.id(), node.nextGroupId(), - direction, relType ); - } - else - { - return count( relType == null - ? storeLayer.nodeGetRelationships( storeStatement, node, direction ) - : storeLayer.nodeGetRelationships( storeStatement, node, direction, t -> t == relType ) ); - } - } - - private boolean propertyHasChanged( Value lhs, Value rhs ) - { - //It is not enough to check equality here since by our equality semantics `int == tofloat(int)` is `true` - //so by only checking for equality users cannot change type of property without also "changing" the value. - //Hence the extra type check here. - return lhs.getClass() != rhs.getClass() || !lhs.equals( rhs ); - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/StatementOperationParts.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/StatementOperationParts.java index 6de7cf8afe889..f97e8910afb92 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/StatementOperationParts.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/StatementOperationParts.java @@ -19,149 +19,27 @@ */ package org.neo4j.kernel.impl.api; -import org.neo4j.kernel.impl.api.operations.CountsOperations; -import org.neo4j.kernel.impl.api.operations.EntityReadOperations; -import org.neo4j.kernel.impl.api.operations.EntityWriteOperations; -import org.neo4j.kernel.impl.api.operations.ExplicitIndexReadOperations; -import org.neo4j.kernel.impl.api.operations.ExplicitIndexWriteOperations; -import org.neo4j.kernel.impl.api.operations.KeyReadOperations; -import org.neo4j.kernel.impl.api.operations.KeyWriteOperations; -import org.neo4j.kernel.impl.api.operations.LockOperations; import org.neo4j.kernel.impl.api.operations.QueryRegistrationOperations; -import org.neo4j.kernel.impl.api.operations.SchemaReadOperations; -import org.neo4j.kernel.impl.api.operations.SchemaStateOperations; -import org.neo4j.kernel.impl.api.operations.SchemaWriteOperations; public class StatementOperationParts { - private final KeyReadOperations keyReadOperations; - private final KeyWriteOperations keyWriteOperations; - private final EntityReadOperations entityReadOperations; - private final EntityWriteOperations entityWriteOperations; - private final SchemaReadOperations schemaReadOperations; - private final SchemaWriteOperations schemaWriteOperations; - private final SchemaStateOperations schemaStateOperations; - private final LockOperations lockingStatementOperations; - private final CountsOperations countsStatementOperations; - private final ExplicitIndexReadOperations explicitIndexReadOperations; - private final ExplicitIndexWriteOperations explicitIndexWriteOperations; private final QueryRegistrationOperations queryRegistrationOperations; public StatementOperationParts( - KeyReadOperations keyReadOperations, - KeyWriteOperations keyWriteOperations, - EntityReadOperations entityReadOperations, - EntityWriteOperations entityWriteOperations, - SchemaReadOperations schemaReadOperations, - SchemaWriteOperations schemaWriteOperations, - SchemaStateOperations schemaStateOperations, - LockOperations lockingStatementOperations, - CountsOperations countsStatementOperations, - ExplicitIndexReadOperations explicitIndexReadOperations, - ExplicitIndexWriteOperations explicitIndexWriteOperations, QueryRegistrationOperations queryRegistrationOperations ) { - this.keyReadOperations = keyReadOperations; - this.keyWriteOperations = keyWriteOperations; - this.entityReadOperations = entityReadOperations; - this.entityWriteOperations = entityWriteOperations; - this.schemaReadOperations = schemaReadOperations; - this.schemaWriteOperations = schemaWriteOperations; - this.schemaStateOperations = schemaStateOperations; - this.lockingStatementOperations = lockingStatementOperations; - this.countsStatementOperations = countsStatementOperations; - this.explicitIndexReadOperations = explicitIndexReadOperations; - this.explicitIndexWriteOperations = explicitIndexWriteOperations; this.queryRegistrationOperations = queryRegistrationOperations; } - public KeyReadOperations keyReadOperations() - { - return checkNotNull( keyReadOperations, KeyReadOperations.class ); - } - - public KeyWriteOperations keyWriteOperations() - { - return checkNotNull( keyWriteOperations, KeyWriteOperations.class ); - } - - public EntityReadOperations entityReadOperations() - { - return checkNotNull( entityReadOperations, EntityReadOperations.class ); - } - - public EntityWriteOperations entityWriteOperations() - { - return checkNotNull( entityWriteOperations, EntityWriteOperations.class ); - } - - public SchemaReadOperations schemaReadOperations() - { - return checkNotNull( schemaReadOperations, SchemaReadOperations.class ); - } - - public SchemaWriteOperations schemaWriteOperations() - { - return checkNotNull( schemaWriteOperations, SchemaWriteOperations.class ); - } - - public SchemaStateOperations schemaStateOperations() - { - return checkNotNull( schemaStateOperations, SchemaStateOperations.class ); - } - - public LockOperations locking() - { - return checkNotNull( lockingStatementOperations, LockOperations.class ); - } - - public ExplicitIndexReadOperations explicitIndexReadOperations() - { - return checkNotNull( explicitIndexReadOperations, ExplicitIndexReadOperations.class ); - } - - public ExplicitIndexWriteOperations explicitIndexWriteOperations() - { - return checkNotNull( explicitIndexWriteOperations, ExplicitIndexWriteOperations.class ); - } - - public CountsOperations counting() - { - return checkNotNull( countsStatementOperations, CountsOperations.class ); - } - public QueryRegistrationOperations queryRegistrationOperations() { return checkNotNull( queryRegistrationOperations, QueryRegistrationOperations.class ); } - public StatementOperationParts override( - KeyReadOperations keyReadOperations, - KeyWriteOperations keyWriteOperations, - EntityReadOperations entityReadOperations, - EntityWriteOperations entityWriteOperations, - SchemaReadOperations schemaReadOperations, - SchemaWriteOperations schemaWriteOperations, - SchemaStateOperations schemaStateOperations, - LockOperations lockingStatementOperations, - CountsOperations countsStatementOperations, - ExplicitIndexReadOperations explicitIndexReadOperations, - ExplicitIndexWriteOperations explicitIndexWriteOperations, - QueryRegistrationOperations queryRegistrationOperations ) + public StatementOperationParts override( QueryRegistrationOperations queryRegistrationOperations ) { return new StatementOperationParts( - eitherOr( keyReadOperations, this.keyReadOperations, KeyReadOperations.class ), - eitherOr( keyWriteOperations, this.keyWriteOperations, KeyWriteOperations.class ), - eitherOr( entityReadOperations, this.entityReadOperations, EntityReadOperations.class ), - eitherOr( entityWriteOperations, this.entityWriteOperations, EntityWriteOperations.class ), - eitherOr( schemaReadOperations, this.schemaReadOperations, SchemaReadOperations.class ), - eitherOr( schemaWriteOperations, this.schemaWriteOperations, SchemaWriteOperations.class ), - eitherOr( schemaStateOperations, this.schemaStateOperations, SchemaStateOperations.class ), - eitherOr( lockingStatementOperations, this.lockingStatementOperations, LockOperations.class ), - eitherOr( countsStatementOperations, this.countsStatementOperations, CountsOperations.class ), - eitherOr( explicitIndexReadOperations, this.explicitIndexReadOperations, ExplicitIndexReadOperations.class ), - eitherOr( explicitIndexWriteOperations, this.explicitIndexWriteOperations, ExplicitIndexWriteOperations.class ), - eitherOr( queryRegistrationOperations, this.queryRegistrationOperations, QueryRegistrationOperations.class ) ); + eitherOr( queryRegistrationOperations, this.queryRegistrationOperations, QueryRegistrationOperations.class ) ); } private T checkNotNull( T object, Class cls ) diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/TokenAccess.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/TokenAccess.java index e4d4dc544eb3d..b51b074580939 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/TokenAccess.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/TokenAccess.java @@ -33,7 +33,7 @@ import org.neo4j.kernel.api.Statement; import static org.neo4j.graphdb.Label.label; -import static org.neo4j.kernel.api.ReadOperations.ANY_LABEL; +import static org.neo4j.kernel.api.StatementConstants.ANY_LABEL; public abstract class TokenAccess { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/TwoPhaseNodeForRelationshipLocking.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/TwoPhaseNodeForRelationshipLocking.java deleted file mode 100644 index daed1090713e4..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/TwoPhaseNodeForRelationshipLocking.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api; - -import java.util.Arrays; - -import org.neo4j.collection.primitive.Primitive; -import org.neo4j.collection.primitive.PrimitiveArrays; -import org.neo4j.collection.primitive.PrimitiveLongSet; -import org.neo4j.cursor.Cursor; -import org.neo4j.function.ThrowingConsumer; -import org.neo4j.internal.kernel.api.exceptions.EntityNotFoundException; -import org.neo4j.internal.kernel.api.exceptions.KernelException; -import org.neo4j.kernel.impl.api.operations.EntityReadOperations; -import org.neo4j.kernel.impl.locking.ResourceTypes; -import org.neo4j.storageengine.api.Direction; -import org.neo4j.storageengine.api.NodeItem; -import org.neo4j.storageengine.api.RelationshipItem; - -import static org.neo4j.kernel.api.StatementConstants.NO_SUCH_RELATIONSHIP; - -class TwoPhaseNodeForRelationshipLocking -{ - private final EntityReadOperations ops; - private final ThrowingConsumer relIdAction; - - private long firstRelId; - private long[] sortedNodeIds; - - TwoPhaseNodeForRelationshipLocking( EntityReadOperations entityReadOperations, - ThrowingConsumer relIdAction ) - { - this.ops = entityReadOperations; - this.relIdAction = relIdAction; - } - - void lockAllNodesAndConsumeRelationships( long nodeId, final KernelStatement state ) throws KernelException - { - boolean retry; - do - { - retry = false; - firstRelId = NO_SUCH_RELATIONSHIP; - - // lock all the nodes involved by following the node id ordering - collectAndSortNodeIds( nodeId, state ); - - lockAllNodes( state, sortedNodeIds ); - - // perform the action on each relationship, we will retry if the the relationship iterator contains new relationships - try ( Cursor node = ops.nodeCursorById( state, nodeId ) ) - { - try ( Cursor relationships = ops.nodeGetRelationships( state, node.get(), Direction.BOTH ) ) - { - boolean first = true; - while ( relationships.next() && !retry ) - { - retry = performAction( state, relationships.get(), first ); - first = false; - } - } - } - } - while ( retry ); - } - - private void collectAndSortNodeIds( long nodeId, KernelStatement state ) throws EntityNotFoundException - { - PrimitiveLongSet nodeIdSet = Primitive.longSet(); - nodeIdSet.add( nodeId ); - - try ( Cursor node = ops.nodeCursorById( state, nodeId ) ) - { - try ( Cursor rels = ops.nodeGetRelationships( state, node.get(), Direction.BOTH ) ) - { - while ( rels.next() ) - { - RelationshipItem rel = rels.get(); - if ( firstRelId == NO_SUCH_RELATIONSHIP ) - { - firstRelId = rel.id(); - } - - nodeIdSet.add( rel.startNode() ); - nodeIdSet.add( rel.endNode() ); - } - } - } - - long[] nodeIds = PrimitiveArrays.of( nodeIdSet ); - Arrays.sort( nodeIds ); - this.sortedNodeIds = nodeIds; - } - - private void lockAllNodes( KernelStatement state, long[] nodeIds ) - { - state.locks().optimistic().acquireExclusive( state.lockTracer(), ResourceTypes.NODE, nodeIds ); - } - - private void unlockAllNodes( KernelStatement state, long[] nodeIds ) - { - for ( long nodeId : nodeIds ) - { - state.locks().optimistic().releaseExclusive( ResourceTypes.NODE, nodeId ); - } - } - - private boolean performAction( KernelStatement state, RelationshipItem rel, boolean first ) throws KernelException - { - if ( first ) - { - if ( rel.id() != firstRelId ) - { - // if the first relationship is not the same someone added some new rels, so we need to - // lock them all again - unlockAllNodes( state, sortedNodeIds ); - sortedNodeIds = null; - return true; - } - } - - relIdAction.accept( rel.id() ); - return false; - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/CountsOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/CountsOperations.java deleted file mode 100644 index 7bd390a4ed877..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/CountsOperations.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.operations; - -import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.impl.api.KernelStatement; -import org.neo4j.register.Register.DoubleLongRegister; - -public interface CountsOperations -{ - /** @see org.neo4j.kernel.api.ReadOperations#countsForNode(int) */ - long countsForNode( KernelStatement statement, int labelId ); - - /** @see org.neo4j.kernel.api.ReadOperations#countsForNodeWithoutTxState(int) */ - long countsForNodeWithoutTxState( KernelStatement statement, int labelId ); - - /** @see org.neo4j.kernel.api.ReadOperations#countsForRelationship(int, int, int) */ - long countsForRelationship( KernelStatement statement, int startLabelId, int typeId, int endLabelId ); - - /** @see org.neo4j.kernel.api.ReadOperations#countsForRelationshipWithoutTxState(int, int, int) */ - long countsForRelationshipWithoutTxState( KernelStatement statement, int startLabelId, int typeId, int endLabelId ); - - DoubleLongRegister indexUpdatesAndSize( KernelStatement statement, SchemaIndexDescriptor index, - DoubleLongRegister target ) throws IndexNotFoundKernelException; - - DoubleLongRegister indexSample( KernelStatement statement, SchemaIndexDescriptor index, DoubleLongRegister target ) - throws IndexNotFoundKernelException; -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/EntityOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/EntityOperations.java deleted file mode 100644 index c6cfd72763508..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/EntityOperations.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.operations; - -public interface EntityOperations extends EntityReadOperations, EntityWriteOperations -{ -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/EntityReadOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/EntityReadOperations.java deleted file mode 100644 index cf6c9e8fb2eab..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/EntityReadOperations.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.operations; - -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.internal.kernel.api.exceptions.EntityNotFoundException; -import org.neo4j.kernel.api.StatementConstants; -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.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.impl.api.KernelStatement; -import org.neo4j.kernel.impl.api.RelationshipVisitor; -import org.neo4j.storageengine.api.Direction; -import org.neo4j.storageengine.api.NodeItem; -import org.neo4j.storageengine.api.PropertyItem; -import org.neo4j.storageengine.api.RelationshipItem; -import org.neo4j.values.storable.Value; - -public interface EntityReadOperations -{ - /** - * @param labelId the label id of the label that returned nodes are guaranteed to have - * @return ids of all nodes that have the given label - */ - PrimitiveLongResourceIterator nodesGetForLabel( KernelStatement state, int labelId ); - - /** - * Queries the given index with the given index query. - * - * @param statement the KernelStatement to use. - * @param index the index to query against. - * @param predicates the {@link IndexQuery} predicates to query for. - * @return ids of the matching nodes - * @throws IndexNotFoundKernelException if no such index is found. - */ - PrimitiveLongResourceIterator indexQuery( KernelStatement statement, SchemaIndexDescriptor index, IndexQuery... predicates ) - throws IndexNotFoundKernelException, IndexNotApplicableKernelException; - - /** - * Returns the id of the matched node, or {@link StatementConstants#NO_SUCH_NODE} if no node was found. - * - * @throws IndexNotFoundKernelException if no such index found. - * @throws IndexBrokenKernelException if we found an index that was corrupt or otherwise in a failed state. - */ - long nodeGetFromUniqueIndexSeek( KernelStatement state, SchemaIndexDescriptor index, IndexQuery.ExactPredicate... predicates ) - throws IndexNotFoundKernelException, IndexBrokenKernelException, IndexNotApplicableKernelException; - - long nodesCountIndexed( KernelStatement statement, SchemaIndexDescriptor index, long nodeId, Value value ) - throws IndexNotFoundKernelException, IndexBrokenKernelException; - - boolean graphHasProperty( KernelStatement state, int propertyKeyId ); - - Value graphGetProperty( KernelStatement state, int propertyKeyId ); - - /** - * Return all property keys associated with a relationship. - */ - PrimitiveIntIterator graphGetPropertyKeys( KernelStatement state ); - - PrimitiveLongIterator nodesGetAll( KernelStatement state ); - - PrimitiveLongIterator relationshipsGetAll( KernelStatement state ); - - void relationshipVisit( KernelStatement statement, long relId, - RelationshipVisitor visitor ) throws EntityNotFoundException, EXCEPTION; - - Cursor nodeCursorById( KernelStatement statement, long nodeId ) throws EntityNotFoundException; - - Cursor relationshipCursorById( KernelStatement statement, long relId ) - throws EntityNotFoundException; - - Cursor relationshipCursorGetAll( KernelStatement statement ); - - Cursor nodeGetRelationships( KernelStatement statement, NodeItem node, Direction direction ); - - Cursor nodeGetRelationships( KernelStatement statement, NodeItem node, Direction direction, - int[] relTypes ); - - Cursor nodeGetProperties( KernelStatement statement, NodeItem node ); - - Value nodeGetProperty( KernelStatement statement, NodeItem node, int propertyKeyId ); - - boolean nodeHasProperty( KernelStatement statement, NodeItem node, int propertyKeyId ); - - PrimitiveIntSet nodeGetPropertyKeys( KernelStatement statement, NodeItem node ); - - Cursor relationshipGetProperties( KernelStatement statement, RelationshipItem relationship ); - - Value relationshipGetProperty( KernelStatement statement, RelationshipItem relationship, int propertyKeyId ); - - boolean relationshipHasProperty( KernelStatement statement, RelationshipItem relationship, int propertyKeyId ); - - PrimitiveIntSet relationshipGetPropertyKeys( KernelStatement statement, RelationshipItem relationship ); - - long nodesGetCount( KernelStatement statement ); - - long relationshipsGetCount( KernelStatement statement ); - - boolean nodeExists( KernelStatement statement, long id ); - - /** - * Returns the set of types for relationships attached to this node. - * - * @param statement the current kernel statement - * @param nodeItem the node - * @return the set of types for relationships attached to this node. - * @throws IllegalStateException if no current node is selected - */ - PrimitiveIntSet relationshipTypes( KernelStatement statement, NodeItem nodeItem ); - - /** - * Returns degree, e.g. number of relationships for this node. - * - * @param statement the current kernel statement - * @param nodeItem the node - * @param direction {@link Direction} filter when counting relationships, e.g. only - * {@link Direction#OUTGOING outgoing} or {@link Direction#INCOMING incoming}. - * @return degree of relationships in the given direction. - */ - int degree( KernelStatement statement, NodeItem nodeItem, Direction direction ); - - /** - * Returns degree, e.g. number of relationships for this node. - * - * @param statement the current kernel statement - * @param nodeItem the node - * @param direction {@link Direction} filter on when counting relationships, e.g. only - * {@link Direction#OUTGOING outgoing} or {@link Direction#INCOMING incoming}. - * @param relType relationship type id to filter when counting relationships. - * @return degree of relationships in the given direction and relationship type. - */ - int degree( KernelStatement statement, NodeItem nodeItem, Direction direction, int relType ); -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/EntityWriteOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/EntityWriteOperations.java deleted file mode 100644 index b2fdd55d841c1..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/EntityWriteOperations.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.operations; - -import org.neo4j.internal.kernel.api.exceptions.EntityNotFoundException; -import org.neo4j.internal.kernel.api.exceptions.InvalidTransactionTypeKernelException; -import org.neo4j.internal.kernel.api.exceptions.KernelException; -import org.neo4j.internal.kernel.api.exceptions.explicitindex.AutoIndexingKernelException; -import org.neo4j.internal.kernel.api.exceptions.schema.ConstraintValidationException; -import org.neo4j.kernel.impl.api.KernelStatement; -import org.neo4j.values.storable.Value; - -public interface EntityWriteOperations -{ - // Currently, of course, most relevant operations here are still in the old core API implementation. - - long relationshipCreate( KernelStatement statement, - int relationshipTypeId, - long startNodeId, - long endNodeId ) throws EntityNotFoundException; - - long nodeCreate( KernelStatement statement ); - - void nodeDelete( KernelStatement state, long nodeId ) - throws EntityNotFoundException, InvalidTransactionTypeKernelException, AutoIndexingKernelException; - - void relationshipDelete( KernelStatement state, long relationshipId ) - throws EntityNotFoundException, InvalidTransactionTypeKernelException, AutoIndexingKernelException; - - int nodeDetachDelete( KernelStatement state, long nodeId ) throws KernelException; - - /** - * Labels a node with the label corresponding to the given label id. - * If the node already had that label nothing will happen. Label ids - * are retrieved from {@link KeyWriteOperations#labelGetOrCreateForName(org.neo4j.kernel.api.Statement, String)} - * or {@link - * KeyReadOperations#labelGetForName(org.neo4j.kernel.api.Statement, String)}. - */ - boolean nodeAddLabel( KernelStatement state, long nodeId, int labelId ) - throws EntityNotFoundException, ConstraintValidationException; - - /** - * Removes a label with the corresponding id from a node. - * If the node doesn't have that label nothing will happen. Label ids - * are retrieved from {@link KeyWriteOperations#labelGetOrCreateForName(org.neo4j.kernel.api.Statement, String)} - * or {@link - * KeyReadOperations#labelGetForName(org.neo4j.kernel.api.Statement, String)}. - */ - boolean nodeRemoveLabel( KernelStatement state, long nodeId, int labelId ) throws EntityNotFoundException; - - Value nodeSetProperty( KernelStatement state, long nodeId, int propertyKeyId, Value value ) - throws EntityNotFoundException, AutoIndexingKernelException, - InvalidTransactionTypeKernelException, ConstraintValidationException; - - Value relationshipSetProperty( KernelStatement state, long relationshipId, int propertyKeyId, Value value ) - throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException; - - Value graphSetProperty( KernelStatement state, int propertyKeyId, Value value ); - - /** - * Remove a node's property given the node's id and the property key id and return the value to which - * it was set or null if it was not set on the node - */ - Value nodeRemoveProperty( KernelStatement state, long nodeId, int propertyKeyId ) - throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException; - - Value relationshipRemoveProperty( KernelStatement state, long relationshipId, int propertyKeyId ) - throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException; - - Value graphRemoveProperty( KernelStatement state, int propertyKeyId ); -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/ExplicitIndexReadOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/ExplicitIndexReadOperations.java deleted file mode 100644 index 6c74f323110e6..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/ExplicitIndexReadOperations.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.operations; - -import java.util.Map; - -import org.neo4j.internal.kernel.api.exceptions.explicitindex.ExplicitIndexNotFoundKernelException; -import org.neo4j.kernel.api.ExplicitIndexHits; -import org.neo4j.kernel.impl.api.KernelStatement; - -public interface ExplicitIndexReadOperations -{ - /** - * @param statement {@link KernelStatement} to use for state. - * @param indexName name of node index to check for existence. - * @param customConfiguration if {@code null} the configuration of existing won't be matched, otherwise it will - * be matched and a mismatch will throw {@link IllegalArgumentException}. - * @return whether or not node explicit index with name {@code indexName} exists. - * @throws IllegalArgumentException on index existence with provided mismatching {@code customConfiguration}. - */ - boolean nodeExplicitIndexExists( KernelStatement statement, String indexName, Map customConfiguration ); - - /** - * @param statement {@link KernelStatement} to use for state. - * @param indexName name of relationship index to check for existence. - * @param customConfiguration if {@code null} the configuration of existing won't be matched, otherwise it will - * be matched and a mismatch will throw {@link IllegalArgumentException}. - * @return whether or not relationship explicit index with name {@code indexName} exists. - * @throws IllegalArgumentException on index existence with provided mismatching {@code customConfiguration}. - */ - boolean relationshipExplicitIndexExists( KernelStatement statement, String indexName, Map customConfiguration ); - - Map nodeExplicitIndexGetConfiguration( KernelStatement statement, String indexName ) - throws ExplicitIndexNotFoundKernelException; - - Map relationshipExplicitIndexGetConfiguration( KernelStatement statement, String indexName ) - throws ExplicitIndexNotFoundKernelException; - - ExplicitIndexHits nodeExplicitIndexGet( KernelStatement statement, String indexName, String key, Object value ) - throws ExplicitIndexNotFoundKernelException; - - ExplicitIndexHits nodeExplicitIndexQuery( KernelStatement statement, String indexName, String key, - Object queryOrQueryObject ) throws ExplicitIndexNotFoundKernelException; - - ExplicitIndexHits nodeExplicitIndexQuery( KernelStatement statement, String indexName, Object queryOrQueryObject ) - throws ExplicitIndexNotFoundKernelException; - - ExplicitIndexHits relationshipExplicitIndexGet( KernelStatement statement, String indexName, String key, Object value, - long startNode, long endNode ) throws ExplicitIndexNotFoundKernelException; - - ExplicitIndexHits relationshipExplicitIndexQuery( KernelStatement statement, String indexName, String key, - Object queryOrQueryObject, long startNode, long endNode ) throws ExplicitIndexNotFoundKernelException; - - ExplicitIndexHits relationshipExplicitIndexQuery( KernelStatement statement, String indexName, - Object queryOrQueryObject, long startNode, long endNode ) - throws ExplicitIndexNotFoundKernelException; - - String[] nodeExplicitIndexesGetAll( KernelStatement statement ); - - String[] relationshipExplicitIndexesGetAll( KernelStatement statement ); -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/ExplicitIndexWriteOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/ExplicitIndexWriteOperations.java deleted file mode 100644 index 565a8268cd929..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/ExplicitIndexWriteOperations.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.operations; - -import java.util.Map; - -import org.neo4j.internal.kernel.api.exceptions.EntityNotFoundException; -import org.neo4j.internal.kernel.api.exceptions.explicitindex.ExplicitIndexNotFoundKernelException; -import org.neo4j.kernel.impl.api.KernelStatement; - -public interface ExplicitIndexWriteOperations -{ - void nodeExplicitIndexCreateLazily( KernelStatement statement, String indexName, Map customConfig ); - - void nodeExplicitIndexCreate( KernelStatement statement, String indexName, Map customConfig ); - - void relationshipExplicitIndexCreateLazily( KernelStatement statement, String indexName, - Map customConfig ); - - void relationshipExplicitIndexCreate( KernelStatement statement, String indexName, - Map customConfig ); - - String nodeExplicitIndexSetConfiguration( KernelStatement statement, String indexName, String key, String value ) - throws ExplicitIndexNotFoundKernelException; - - String relationshipExplicitIndexSetConfiguration( KernelStatement statement, String indexName, String key, - String value ) throws ExplicitIndexNotFoundKernelException; - - String nodeExplicitIndexRemoveConfiguration( KernelStatement statement, String indexName, String key ) - throws ExplicitIndexNotFoundKernelException; - - String relationshipExplicitIndexRemoveConfiguration( KernelStatement statement, String indexName, String key ) - throws ExplicitIndexNotFoundKernelException; - - void nodeAddToExplicitIndex( KernelStatement statement, String indexName, long node, String key, Object value ) - throws ExplicitIndexNotFoundKernelException; - - void nodeRemoveFromExplicitIndex( KernelStatement statement, String indexName, long node, String key, Object value ) - throws ExplicitIndexNotFoundKernelException; - - void nodeRemoveFromExplicitIndex( KernelStatement statement, String indexName, long node, String key ) - throws ExplicitIndexNotFoundKernelException; - - void nodeRemoveFromExplicitIndex( KernelStatement statement, String indexName, long node ) - throws ExplicitIndexNotFoundKernelException; - - void relationshipAddToExplicitIndex( KernelStatement statement, String indexName, long relationship, String key, - Object value ) throws EntityNotFoundException, ExplicitIndexNotFoundKernelException; - - void relationshipRemoveFromExplicitIndex( KernelStatement statement, String indexName, long relationship, String key, - Object value ) throws ExplicitIndexNotFoundKernelException; - - void relationshipRemoveFromExplicitIndex( KernelStatement statement, String indexName, long relationship, String key ) - throws ExplicitIndexNotFoundKernelException; - - void relationshipRemoveFromExplicitIndex( KernelStatement statement, String indexName, long relationship ) - throws ExplicitIndexNotFoundKernelException; - - void nodeExplicitIndexDrop( KernelStatement statement, String indexName ) throws ExplicitIndexNotFoundKernelException; - - void relationshipExplicitIndexDrop( KernelStatement statement, String indexName ) throws - ExplicitIndexNotFoundKernelException; -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/KeyReadOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/KeyReadOperations.java deleted file mode 100644 index 21bc5e60c2ec0..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/KeyReadOperations.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.operations; - -import java.util.Iterator; - -import org.neo4j.internal.kernel.api.exceptions.LabelNotFoundKernelException; -import org.neo4j.internal.kernel.api.exceptions.PropertyKeyIdNotFoundKernelException; -import org.neo4j.kernel.api.Statement; -import org.neo4j.kernel.api.StatementConstants; -import org.neo4j.kernel.api.exceptions.RelationshipTypeIdNotFoundKernelException; -import org.neo4j.kernel.impl.api.KernelStatement; -import org.neo4j.storageengine.api.Token; - -public interface KeyReadOperations -{ - int NO_SUCH_LABEL = StatementConstants.NO_SUCH_LABEL; - int NO_SUCH_PROPERTY_KEY = StatementConstants.NO_SUCH_PROPERTY_KEY; - int NO_SUCH_RELATIONSHIP_TYPE = StatementConstants.NO_SUCH_RELATIONSHIP_TYPE; - - /** Returns a label id for a label name. If the label doesn't exist, {@link #NO_SUCH_LABEL} will be returned. */ - int labelGetForName( Statement state, String labelName ); - - /** Returns the label name for the given label id. */ - String labelGetName( Statement state, int labelId ) throws LabelNotFoundKernelException; - - /** - * Returns a property key id for the given property key. If the property key doesn't exist, - * {@link #NO_SUCH_PROPERTY_KEY} will be returned. - */ - int propertyKeyGetForName( Statement state, String propertyKeyName ); - - /** Returns the name of a property given its property key id */ - String propertyKeyGetName( Statement state, int propertyKeyId ) throws PropertyKeyIdNotFoundKernelException; - - /** Returns the property keys currently stored in the database */ - Iterator propertyKeyGetAllTokens( Statement state ); - - /** Returns the labels currently stored in the database **/ - Iterator labelsGetAllTokens( Statement state ); - - /** Returns the relationship types currently stored in the database */ - Iterator relationshipTypesGetAllTokens( Statement state ); - - int relationshipTypeGetForName( Statement state, String relationshipTypeName ); - - String relationshipTypeGetName( Statement state, int relationshipTypeId ) - throws RelationshipTypeIdNotFoundKernelException; - - int labelCount( KernelStatement statement ); - - int propertyKeyCount( KernelStatement statement ); - - int relationshipTypeCount( KernelStatement statement ); -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/KeyWriteOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/KeyWriteOperations.java deleted file mode 100644 index 681ee3af963f7..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/KeyWriteOperations.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.operations; - -import org.neo4j.kernel.api.Statement; -import org.neo4j.internal.kernel.api.exceptions.schema.IllegalTokenNameException; -import org.neo4j.internal.kernel.api.exceptions.schema.TooManyLabelsException; -import org.neo4j.kernel.impl.api.KernelStatement; - -public interface KeyWriteOperations -{ - /** - * Returns a label id for a label name. If the label doesn't exist prior to - * this call it gets created. - */ - int labelGetOrCreateForName( Statement state, String labelName ) - throws IllegalTokenNameException, TooManyLabelsException; - - /** - * Returns a property key id for a property key. If the key doesn't exist prior to - * this call it gets created. - */ - int propertyKeyGetOrCreateForName( Statement state, String propertyKeyName ) throws IllegalTokenNameException; - - int relationshipTypeGetOrCreateForName( Statement state, String relationshipTypeName ) - throws IllegalTokenNameException; - - /** - * Returns a label id for a label name. If the label doesn't exist prior to - * this call it gets created. - */ - void labelCreateForName( KernelStatement state, String labelName, - int id ) throws IllegalTokenNameException, TooManyLabelsException; - - /** - * Returns a property key id for a property key. If the key doesn't exist prior to - * this call it gets created. - */ - void propertyKeyCreateForName( KernelStatement state, String propertyKeyName, int id ) - throws IllegalTokenNameException; - - void relationshipTypeCreateForName( KernelStatement state, String relationshipTypeName, int id ) - throws IllegalTokenNameException; -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/LockOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/LockOperations.java deleted file mode 100644 index 37ed83419b843..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/LockOperations.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.operations; - -import org.neo4j.kernel.impl.api.KernelStatement; -import org.neo4j.storageengine.api.lock.ResourceType; - -public interface LockOperations -{ - void acquireExclusive( KernelStatement state, ResourceType resourceType, long... ids ); - void acquireShared( KernelStatement state, ResourceType resourceType, long... ids ); - - void releaseExclusive( KernelStatement statement, ResourceType type, long... ids ); - void releaseShared( KernelStatement statement, ResourceType type, long... ids ); -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/SchemaReadOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/SchemaReadOperations.java deleted file mode 100644 index 6eb39638c2c66..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/SchemaReadOperations.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.operations; - -import java.util.Iterator; - -import org.neo4j.internal.kernel.api.InternalIndexState; -import org.neo4j.internal.kernel.api.schema.SchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.constraints.ConstraintDescriptor; -import org.neo4j.kernel.api.Statement; -import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; -import org.neo4j.kernel.api.exceptions.schema.SchemaRuleNotFoundException; -import org.neo4j.kernel.api.index.IndexProvider; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.impl.api.KernelStatement; -import org.neo4j.storageengine.api.schema.PopulationProgress; - -public interface SchemaReadOperations -{ - /** - * Returns the descriptor for the given labelId and propertyKey. - */ - SchemaIndexDescriptor indexGetForSchema( KernelStatement state, SchemaDescriptor descriptor ); - - /** - * Get all indexes for a label. - */ - Iterator indexesGetForLabel( KernelStatement state, int labelId ); - - /** - * Returns all indexes. - */ - Iterator indexesGetAll( KernelStatement state ); - - /** - * Retrieve the state of an index. - */ - InternalIndexState indexGetState( KernelStatement state, SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException; - - /** - * Retrieve the index provider descriptor for an index. - */ - IndexProvider.Descriptor indexGetProviderDescriptor( KernelStatement state, SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException; - - /** - * Retrieve the population progress of an index. - */ - PopulationProgress indexGetPopulationProgress( KernelStatement state, SchemaIndexDescriptor descriptor ) throws - IndexNotFoundKernelException; - - /** - * Get the index size. - **/ - long indexSize( KernelStatement state, SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException; - - /** - * Calculate the index unique values percentage. - **/ - double indexUniqueValuesPercentage( KernelStatement state, SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException; - - /** - * Returns the failure description of a failed index. - */ - String indexGetFailure( Statement state, SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException; - - /** - * Get all constraints applicable to label and propertyKeys. - */ - Iterator constraintsGetForSchema( KernelStatement state, SchemaDescriptor descriptor ); - - /** - * Returns true if a constraint exists that matches the given {@link ConstraintDescriptor}. - */ - boolean constraintExists( KernelStatement state, ConstraintDescriptor descriptor ); - - /** - * Get all constraints applicable to label. - */ - Iterator constraintsGetForLabel( KernelStatement state, int labelId ); - - /** - * Get all constraints applicable to relationship type. - */ - Iterator constraintsGetForRelationshipType( KernelStatement state, int typeId ); - - /** - * Get all constraints. - */ - Iterator constraintsGetAll( KernelStatement state ); - - /** - * Get the owning constraint for a constraint index. Returns null if the index does not have an owning constraint. - */ - Long indexGetOwningUniquenessConstraintId( KernelStatement state, SchemaIndexDescriptor index ); - - /** - * Get the index id (the id or the schema rule record) for a committed index - * - throws exception for indexes that aren't committed. - */ - long indexGetCommittedId( KernelStatement state, SchemaIndexDescriptor index ) throws SchemaRuleNotFoundException; -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/SchemaStateOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/SchemaStateOperations.java deleted file mode 100644 index b389bcb3f5aac..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/SchemaStateOperations.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.operations; - -import java.util.function.Function; - -import org.neo4j.kernel.impl.api.KernelStatement; - -public interface SchemaStateOperations -{ - /** - * The schema state is flushed when ever the schema is updated. If you build objects - * the rely on the current state of the schema, use this to make sure you don't use - * outdated schema information. - * - * Additionally, schema state entries are evicted using an LRU policy. The size - * of the LRU cache is determined by GraphDatabaseSettings.query_cache_size - * - * NOTE: This currently is solely used by Cypher and might or might not be turned into - * a more generic facility in the future - */ - V schemaStateGetOrCreate( KernelStatement state, K key, Function creator ); - - /** - * Return schema state associated with provided key - * @param state statement - * @param key state key - * @return state associated with key - */ - V schemaStateGet( KernelStatement state, K key ); - - /** - * Flush the schema state. - */ - void schemaStateFlush( KernelStatement state ); -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/SchemaWriteOperations.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/SchemaWriteOperations.java deleted file mode 100644 index 43d19cd421854..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/operations/SchemaWriteOperations.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.operations; - -import org.neo4j.internal.kernel.api.schema.LabelSchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.RelationTypeSchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.SchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.constraints.ConstraintDescriptor; -import org.neo4j.kernel.api.exceptions.schema.AlreadyConstrainedException; -import org.neo4j.kernel.api.exceptions.schema.AlreadyIndexedException; -import org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException; -import org.neo4j.kernel.api.exceptions.schema.DropConstraintFailureException; -import org.neo4j.kernel.api.exceptions.schema.DropIndexFailureException; -import org.neo4j.kernel.api.exceptions.schema.RepeatedPropertyInCompositeSchemaException; -import org.neo4j.kernel.api.schema.constaints.NodeExistenceConstraintDescriptor; -import org.neo4j.kernel.api.schema.constaints.NodeKeyConstraintDescriptor; -import org.neo4j.kernel.api.schema.constaints.RelExistenceConstraintDescriptor; -import org.neo4j.kernel.api.schema.constaints.UniquenessConstraintDescriptor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.impl.api.KernelStatement; - -public interface SchemaWriteOperations -{ - /** - * Creates an index, indexing properties with the given {@code propertyKeyId} for nodes with the given - * {@code labelId}. - */ - SchemaIndexDescriptor indexCreate( KernelStatement state, SchemaDescriptor descriptor ) - throws AlreadyIndexedException, AlreadyConstrainedException, RepeatedPropertyInCompositeSchemaException; - - /** Drops a {@link SchemaIndexDescriptor} from the database */ - void indexDrop( KernelStatement state, SchemaIndexDescriptor descriptor ) throws DropIndexFailureException; - - /** - * This should not be used, it is exposed to allow an external job to clean up constraint indexes. - * That external job should become an internal job, at which point this operation should go away. - */ - void uniqueIndexDrop( KernelStatement state, SchemaIndexDescriptor descriptor ) throws DropIndexFailureException; - - NodeKeyConstraintDescriptor nodeKeyConstraintCreate( KernelStatement state, LabelSchemaDescriptor descriptor ) - throws AlreadyConstrainedException, CreateConstraintFailureException, AlreadyIndexedException, - RepeatedPropertyInCompositeSchemaException; - - UniquenessConstraintDescriptor uniquePropertyConstraintCreate( KernelStatement state, SchemaDescriptor descriptor ) - throws AlreadyConstrainedException, CreateConstraintFailureException, AlreadyIndexedException, - RepeatedPropertyInCompositeSchemaException; - - NodeExistenceConstraintDescriptor nodePropertyExistenceConstraintCreate( KernelStatement state, - LabelSchemaDescriptor descriptor ) throws AlreadyConstrainedException, CreateConstraintFailureException, - RepeatedPropertyInCompositeSchemaException; - - RelExistenceConstraintDescriptor relationshipPropertyExistenceConstraintCreate( KernelStatement state, - RelationTypeSchemaDescriptor descriptor ) - throws AlreadyConstrainedException, CreateConstraintFailureException, - RepeatedPropertyInCompositeSchemaException; - - void constraintDrop( KernelStatement state, ConstraintDescriptor constraint ) throws DropConstraintFailureException; -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/schema/NodeSchemaMatcher.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/schema/NodeSchemaMatcher.java deleted file mode 100644 index 59d55791d4095..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/schema/NodeSchemaMatcher.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.schema; - -import java.util.Iterator; - -import org.neo4j.collection.primitive.Primitive; -import org.neo4j.collection.primitive.PrimitiveIntSet; -import org.neo4j.function.ThrowingBiConsumer; -import org.neo4j.internal.kernel.api.schema.SchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.SchemaDescriptorSupplier; -import org.neo4j.kernel.impl.api.KernelStatement; -import org.neo4j.kernel.impl.api.operations.EntityReadOperations; -import org.neo4j.storageengine.api.NodeItem; - -/** - * This class holds functionality to match LabelSchemaDescriptors to nodes - */ -public class NodeSchemaMatcher -{ - private final EntityReadOperations readOps; - - public NodeSchemaMatcher( EntityReadOperations readOps ) - { - this.readOps = readOps; - } - - /** - * Iterate over some schema suppliers, and invoke a callback for every supplier that matches the node. To match the - * node N the supplier must supply a LabelSchemaDescriptor D, such that N has the label of D, and values for all - * the properties of D. - * - * To avoid unnecessary store lookups, this implementation only gets propertyKeyIds for the node if some - * descriptor has a valid label. - * - * @param the type to match. Must implement SchemaDescriptorSupplier - * @param The type of exception that can be thrown when taking the action - * @param state The current statement - * @param schemaSuppliers The suppliers to match - * @param node The node - * @param specialPropertyId This property id will always count as a match for the descriptor, regardless of - * whether the node has this property or not - * @param callback The action to take on match - * @throws EXCEPTION This exception is propagated from the action - */ - public void onMatchingSchema( - KernelStatement state, - Iterator schemaSuppliers, - NodeItem node, - int specialPropertyId, - ThrowingBiConsumer callback - ) throws EXCEPTION - { - PrimitiveIntSet nodePropertyIds = null; - while ( schemaSuppliers.hasNext() ) - { - SUPPLIER schemaSupplier = schemaSuppliers.next(); - SchemaDescriptor schema = schemaSupplier.schema(); - if ( node.labels().contains( schema.keyId() ) ) - { - if ( nodePropertyIds == null ) - { - nodePropertyIds = Primitive.intSet(); - nodePropertyIds.addAll( readOps.nodeGetPropertyKeys( state, node ).iterator() ); - } - - if ( nodeHasSchemaProperties( nodePropertyIds, schema.getPropertyIds(), specialPropertyId ) ) - { - callback.accept( schemaSupplier, nodePropertyIds ); - } - } - } - } - - public static boolean nodeHasSchemaProperties( - PrimitiveIntSet nodeProperties, int[] indexPropertyIds, int changedPropertyId ) - { - for ( int indexPropertyId : indexPropertyIds ) - { - if ( indexPropertyId != changedPropertyId && !nodeProperties.contains( indexPropertyId ) ) - { - return false; - } - } - return true; - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/ConstraintIndexCreator.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/ConstraintIndexCreator.java index fb7626b1fc1e4..46ca15a2445a5 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/ConstraintIndexCreator.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/ConstraintIndexCreator.java @@ -28,22 +28,19 @@ import org.neo4j.internal.kernel.api.Session; import org.neo4j.internal.kernel.api.TokenRead; import org.neo4j.internal.kernel.api.Transaction; +import org.neo4j.internal.kernel.api.exceptions.TransactionFailureException; import org.neo4j.internal.kernel.api.exceptions.schema.SchemaKernelException; import org.neo4j.internal.kernel.api.exceptions.schema.SchemaKernelException.OperationContext; -import org.neo4j.internal.kernel.api.schema.LabelSchemaDescriptor; import org.neo4j.internal.kernel.api.schema.SchemaDescriptor; import org.neo4j.kernel.api.KernelTransaction; import org.neo4j.kernel.api.SilentTokenNameLookup; import org.neo4j.kernel.api.Statement; -import org.neo4j.kernel.api.StatementTokenNameLookup; -import org.neo4j.internal.kernel.api.exceptions.TransactionFailureException; import org.neo4j.kernel.api.exceptions.index.IndexEntryConflictException; import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; import org.neo4j.kernel.api.exceptions.index.IndexPopulationFailedKernelException; import org.neo4j.kernel.api.exceptions.schema.AlreadyConstrainedException; import org.neo4j.kernel.api.exceptions.schema.AlreadyIndexedException; import org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException; -import org.neo4j.kernel.api.exceptions.schema.SchemaRuleNotFoundException; import org.neo4j.kernel.api.exceptions.schema.UniquePropertyValueValidationException; import org.neo4j.kernel.api.index.PropertyAccessor; import org.neo4j.kernel.api.schema.constaints.ConstraintDescriptorFactory; @@ -51,11 +48,9 @@ import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor.Type; import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptorFactory; -import org.neo4j.kernel.impl.api.KernelStatement; import org.neo4j.kernel.impl.api.KernelTransactionImplementation; import org.neo4j.kernel.impl.api.index.IndexProxy; import org.neo4j.kernel.impl.api.index.IndexingService; -import org.neo4j.kernel.impl.api.operations.SchemaReadOperations; import org.neo4j.kernel.impl.api.store.DefaultCapableIndexReference; import org.neo4j.kernel.impl.locking.Locks.Client; @@ -79,89 +74,6 @@ public ConstraintIndexCreator( Supplier kernelSupplier, IndexingService this.propertyAccessor = propertyAccessor; } - @Deprecated - public long createUniquenessConstraintIndex( - KernelStatement state, SchemaReadOperations schemaOps, LabelSchemaDescriptor descriptor - ) throws TransactionFailureException, CreateConstraintFailureException, UniquePropertyValueValidationException, - AlreadyConstrainedException - { - UniquenessConstraintDescriptor constraint = ConstraintDescriptorFactory.uniqueForSchema( descriptor ); - SchemaIndexDescriptor index; - try - { - index = getOrCreateUniquenessConstraintIndex( state, schemaOps, descriptor ); - } - catch ( AlreadyConstrainedException e ) - { - throw e; - } - catch ( SchemaKernelException e ) - { - throw new CreateConstraintFailureException( constraint, e ); - } - - boolean success = false; - boolean reacquiredLabelLock = false; - Client locks = state.locks().pessimistic(); - try - { - long indexId = schemaOps.indexGetCommittedId( state, index ); - IndexProxy proxy = indexingService.getIndexProxy( indexId ); - - // Release the LABEL WRITE lock during index population. - // At this point the integrity of the constraint to be created was checked - // while holding the lock and the index rule backing the soon-to-be-created constraint - // has been created. Now it's just the population left, which can take a long time - releaseLabelLock( locks, descriptor.getLabelId() ); - - awaitConstrainIndexPopulation( constraint, proxy ); - - // Index population was successful, but at this point we don't know if the uniqueness constraint holds. - // Acquire LABEL WRITE lock and verify the constraints here in this user transaction - // and if everything checks out then it will be held until after the constraint has been - // created and activated. - acquireLabelLock( state, locks, descriptor.getLabelId() ); - reacquiredLabelLock = true; - - indexingService.getIndexProxy( indexId ).verifyDeferredConstraints( propertyAccessor ); - success = true; - return indexId; - } - catch ( SchemaRuleNotFoundException e ) - { - throw new IllegalStateException( - String.format( "Index (%s) that we just created does not exist.", descriptor ), e ); - } - catch ( IndexNotFoundKernelException e ) - { - throw new TransactionFailureException( - String.format( "Index (%s) that we just created does not exist.", descriptor ), e ); - } - catch ( IndexEntryConflictException e ) - { - throw new UniquePropertyValueValidationException( constraint, VERIFICATION, e ); - } - catch ( InterruptedException | IOException e ) - { - throw new CreateConstraintFailureException( constraint, e ); - } - finally - { - if ( !success ) - { - if ( !reacquiredLabelLock ) - { - acquireLabelLock( state, locks, descriptor.getLabelId() ); - } - - if ( indexStillExists( schemaOps, state, descriptor, index ) ) - { - dropUniquenessConstraintIndex( index ); - } - } - } - } - /** * You MUST hold a label write lock before you call this method. * However the label write lock is temporarily released while populating the index backing the constraint. @@ -264,13 +176,6 @@ public long createUniquenessConstraintIndex( KernelTransactionImplementation tra } } - private boolean indexStillExists( SchemaReadOperations schemaOps, KernelStatement state, - SchemaDescriptor descriptor, SchemaIndexDescriptor index ) - { - SchemaIndexDescriptor existingIndex = schemaOps.indexGetForSchema( state, descriptor ); - return existingIndex != null && existingIndex.equals( index ); - } - private boolean indexStillExists( SchemaRead schemaRead, SchemaDescriptor descriptor, CapableIndexReference index ) { @@ -278,11 +183,6 @@ private boolean indexStillExists( SchemaRead schemaRead, SchemaDescriptor descri return existingIndex != CapableIndexReference.NO_INDEX && existingIndex.equals( index ); } - private void acquireLabelLock( KernelStatement state, Client locks, int labelId ) - { - locks.acquireExclusive( state.lockTracer(), LABEL, labelId ); - } - private void acquireLabelLock( KernelTransactionImplementation state, Client locks, int labelId ) { locks.acquireExclusive( state.lockTracer(), LABEL, labelId ); @@ -342,32 +242,6 @@ private void awaitConstrainIndexPopulation( UniquenessConstraintDescriptor const } } - private SchemaIndexDescriptor getOrCreateUniquenessConstraintIndex( KernelStatement state, SchemaReadOperations schemaOps, - LabelSchemaDescriptor schema ) throws SchemaKernelException - { - SchemaIndexDescriptor descriptor = schemaOps.indexGetForSchema( state, schema ); - if ( descriptor != null ) - { - if ( descriptor.type() == Type.UNIQUE ) - { - // OK so we found a matching constraint index. We check whether or not it has an owner - // because this may have been a left-over constraint index from a previously failed - // constraint creation, due to crash or similar, hence the missing owner. - if ( schemaOps.indexGetOwningUniquenessConstraintId( state, descriptor ) == null ) - { - return descriptor; - } - throw new AlreadyConstrainedException( - ConstraintDescriptorFactory.uniqueForSchema( schema ), - OperationContext.CONSTRAINT_CREATION, - new StatementTokenNameLookup( state.readOperations() ) ); - } - // There's already an index for this schema descriptor, which isn't of the type we're after. - throw new AlreadyIndexedException( schema, CONSTRAINT_CREATION ); - } - return createConstraintIndex( schema ); - } - private CapableIndexReference getOrCreateUniquenessConstraintIndex( SchemaRead schemaRead, TokenRead tokenRead, SchemaDescriptor schema ) throws SchemaKernelException, IndexNotFoundKernelException diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/IndexTxStateUpdater.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/IndexTxStateUpdater.java deleted file mode 100644 index f1ad5615f8c0e..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/state/IndexTxStateUpdater.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.state; - -import org.apache.commons.lang3.ArrayUtils; - -import java.util.Iterator; - -import org.neo4j.collection.primitive.Primitive; -import org.neo4j.collection.primitive.PrimitiveIntSet; -import org.neo4j.cursor.Cursor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.impl.api.KernelStatement; -import org.neo4j.kernel.impl.api.index.IndexingService; -import org.neo4j.kernel.impl.api.operations.EntityReadOperations; -import org.neo4j.kernel.impl.api.schema.NodeSchemaMatcher; -import org.neo4j.storageengine.api.NodeItem; -import org.neo4j.storageengine.api.PropertyItem; -import org.neo4j.storageengine.api.StoreReadLayer; -import org.neo4j.values.storable.Value; -import org.neo4j.values.storable.ValueTuple; -import org.neo4j.values.storable.Values; - -import static org.neo4j.kernel.api.StatementConstants.NO_SUCH_PROPERTY_KEY; - -public class IndexTxStateUpdater -{ - private final StoreReadLayer storeReadLayer; - private final EntityReadOperations readOps; - private final NodeSchemaMatcher nodeIndexMatcher; - private final IndexingService indexingService; - - // We can use the StoreReadLayer directly instead of the SchemaReadOps, because we know that in transactions - // where this class is needed we will never have index changes. - public IndexTxStateUpdater( StoreReadLayer storeReadLayer, EntityReadOperations readOps, IndexingService indexingService ) - { - this.storeReadLayer = storeReadLayer; - this.readOps = readOps; - this.nodeIndexMatcher = new NodeSchemaMatcher( readOps ); - this.indexingService = indexingService; - } - - // LABEL CHANGES - - public enum LabelChangeType - { - ADDED_LABEL, - REMOVED_LABEL - } - - public void onLabelChange( KernelStatement state, int labelId, NodeItem node, LabelChangeType changeType ) - { - assert noSchemaChangedInTx( state ); - PrimitiveIntSet nodePropertyIds = Primitive.intSet(); - nodePropertyIds.addAll( readOps.nodeGetPropertyKeys( state, node ).iterator() ); - - Iterator indexes = storeReadLayer.indexesGetForLabel( labelId ); - - while ( indexes.hasNext() ) - { - SchemaIndexDescriptor index = indexes.next(); - int[] indexPropertyIds = index.schema().getPropertyIds(); - if ( nodeHasIndexProperties( nodePropertyIds, indexPropertyIds ) ) - { - Value[] values = getValueTuple( state, node, indexPropertyIds ); - if ( changeType == LabelChangeType.ADDED_LABEL ) - { - indexingService.validateBeforeCommit( index.schema(), values ); - state.txState().indexDoUpdateEntry( index.schema(), node.id(), null, ValueTuple.of( values ) ); - } - else - { - state.txState().indexDoUpdateEntry( index.schema(), node.id(), ValueTuple.of( values ), null ); - } - } - } - } - - private boolean noSchemaChangedInTx( KernelStatement state ) - { - return !(state.txState().hasChanges() && !state.txState().hasDataChanges()); - } - - // PROPERTY CHANGES - - public void onPropertyAdd( KernelStatement state, NodeItem node, int propertyKeyId, Value value ) - { - assert noSchemaChangedInTx( state ); - Iterator indexes = - storeReadLayer.indexesGetRelatedToProperty( propertyKeyId ); - nodeIndexMatcher.onMatchingSchema( state, indexes, node, propertyKeyId, - ( index, propertyKeyIds ) -> - { - Value[] values = getValueTuple( state, node, propertyKeyId, value, index.schema().getPropertyIds() ); - indexingService.validateBeforeCommit( index.schema(), values ); - state.txState().indexDoUpdateEntry( index.schema(), node.id(), null, ValueTuple.of( values ) ); - } ); - } - - public void onPropertyRemove( KernelStatement state, NodeItem node, int propertyKeyId, Value value ) - { - assert noSchemaChangedInTx( state ); - Iterator indexes = - storeReadLayer.indexesGetRelatedToProperty( propertyKeyId ); - nodeIndexMatcher.onMatchingSchema( state, indexes, node, propertyKeyId, - ( index, propertyKeyIds ) -> - { - Value[] values = getValueTuple( state, node, propertyKeyId, value, index.schema().getPropertyIds() ); - state.txState().indexDoUpdateEntry( index.schema(), node.id(), ValueTuple.of( values ), null ); - }); - } - - public void onPropertyChange( KernelStatement state, NodeItem node, int propertyKeyId, Value beforeValue, Value afterValue ) - { - assert noSchemaChangedInTx( state ); - Iterator indexes = storeReadLayer.indexesGetRelatedToProperty( propertyKeyId ); - nodeIndexMatcher.onMatchingSchema( state, indexes, node, propertyKeyId, - ( index, propertyKeyIds ) -> - { - int[] indexPropertyIds = index.schema().getPropertyIds(); - - Value[] valuesBefore = new Value[indexPropertyIds.length]; - Value[] valuesAfter = new Value[indexPropertyIds.length]; - for ( int i = 0; i < indexPropertyIds.length; i++ ) - { - int indexPropertyId = indexPropertyIds[i]; - if ( indexPropertyId == propertyKeyId ) - { - valuesBefore[i] = beforeValue; - valuesAfter[i] = afterValue; - } - else - { - Value value = readOps.nodeGetProperty( state, node, indexPropertyId ); - valuesBefore[i] = value; - valuesAfter[i] = value; - } - } - indexingService.validateBeforeCommit( index.schema(), valuesAfter ); - state.txState().indexDoUpdateEntry( index.schema(), node.id(), - ValueTuple.of( valuesBefore ), ValueTuple.of( valuesAfter ) ); - }); - } - - // HELPERS - - private Value[] getValueTuple( KernelStatement state, NodeItem node, - int[] indexPropertyIds ) - { - return getValueTuple( state, node, NO_SUCH_PROPERTY_KEY, Values.NO_VALUE, indexPropertyIds ); - } - - private Value[] getValueTuple( KernelStatement state, NodeItem node, - int changedPropertyKeyId, Value changedValue, int[] indexPropertyIds ) - { - Value[] values = new Value[indexPropertyIds.length]; - Cursor propertyCursor = readOps.nodeGetProperties( state, node ); - while ( propertyCursor.next() ) - { - PropertyItem property = propertyCursor.get(); - int k = ArrayUtils.indexOf( indexPropertyIds, property.propertyKeyId() ); - if ( k >= 0 ) - { - values[k] = indexPropertyIds[k] == changedPropertyKeyId - ? changedValue : property.value(); - } - } - - if ( changedPropertyKeyId != NO_SUCH_PROPERTY_KEY ) - { - int k = ArrayUtils.indexOf( indexPropertyIds, changedPropertyKeyId ); - if ( k >= 0 ) - { - values[k] = changedValue; - } - } - - return values; - } - - private static boolean nodeHasIndexProperties( PrimitiveIntSet nodeProperties, int[] indexPropertyIds ) - { - for ( int indexPropertyId : indexPropertyIds ) - { - if ( !nodeProperties.contains( indexPropertyId ) ) - { - return false; - } - } - return true; - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/store/StorageLayer.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/store/StorageLayer.java index 06f3915354345..3def71c7d836a 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/api/store/StorageLayer.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/api/store/StorageLayer.java @@ -40,7 +40,7 @@ import org.neo4j.internal.kernel.api.schema.SchemaDescriptor; import org.neo4j.internal.kernel.api.schema.constraints.ConstraintDescriptor; import org.neo4j.kernel.api.AssertOpen; -import org.neo4j.kernel.api.ReadOperations; +import org.neo4j.kernel.api.StatementConstants; import org.neo4j.kernel.api.exceptions.RelationshipTypeIdNotFoundKernelException; import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; import org.neo4j.kernel.api.exceptions.schema.SchemaRuleNotFoundException; @@ -488,7 +488,7 @@ public long countsForNode( int labelId ) @Override public long countsForRelationship( int startLabelId, int typeId, int endLabelId ) { - if ( !(startLabelId == ReadOperations.ANY_LABEL || endLabelId == ReadOperations.ANY_LABEL) ) + if ( !(startLabelId == StatementConstants.ANY_LABEL || endLabelId == StatementConstants.ANY_LABEL) ) { throw new UnsupportedOperationException( "not implemented" ); } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/PropertyNameUtils.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/PropertyNameUtils.java index 2da82e01181bd..5791f826935cd 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/PropertyNameUtils.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/coreapi/schema/PropertyNameUtils.java @@ -29,7 +29,6 @@ import org.neo4j.internal.kernel.api.exceptions.PropertyKeyIdNotFoundKernelException; import org.neo4j.internal.kernel.api.exceptions.schema.IllegalTokenNameException; import org.neo4j.internal.kernel.api.schema.LabelSchemaDescriptor; -import org.neo4j.kernel.api.ReadOperations; public class PropertyNameUtils { @@ -37,18 +36,6 @@ private PropertyNameUtils() { } - public static String[] getPropertyKeys( ReadOperations readOperations, LabelSchemaDescriptor descriptor ) - throws PropertyKeyIdNotFoundKernelException - { - int[] propertyKeyIds = descriptor.getPropertyIds(); - String[] propertyKeys = new String[propertyKeyIds.length]; - for ( int i = 0; i < propertyKeyIds.length; i++ ) - { - propertyKeys[i] = readOperations.propertyKeyGetName( propertyKeyIds[i] ); - } - return propertyKeys; - } - public static String[] getPropertyKeys( TokenRead tokenRead, int...properties ) throws PropertyKeyIdNotFoundKernelException { @@ -71,17 +58,6 @@ public static String[] getPropertyKeys( TokenNameLookup tokenNameLookup, LabelSc return propertyKeys; } - public static String[] getPropertyKeys( ReadOperations readOperations, int[] propertyIds ) - throws PropertyKeyIdNotFoundKernelException - { - String[] propertyKeys = new String[propertyIds.length]; - for ( int i = 0; i < propertyIds.length; i++ ) - { - propertyKeys[i] = readOperations.propertyKeyGetName( propertyIds[i] ); - } - return propertyKeys; - } - public static String[] getPropertyKeys( TokenNameLookup tokenNameLookup, int[] propertyIds ) { String[] propertyKeys = new String[propertyIds.length]; @@ -92,16 +68,6 @@ public static String[] getPropertyKeys( TokenNameLookup tokenNameLookup, int[] p return propertyKeys; } - public static int[] getPropertyIds( ReadOperations statement, String[] propertyKeys ) - { - int[] propertyKeyIds = new int[propertyKeys.length]; - for ( int i = 0; i < propertyKeys.length; i++ ) - { - propertyKeyIds[i] = statement.propertyKeyGetForName( propertyKeys[i] ); - } - return propertyKeyIds; - } - public static int[] getPropertyIds( TokenRead tokenRead, String[] propertyKeys ) { int[] propertyKeyIds = new int[propertyKeys.length]; @@ -112,11 +78,6 @@ public static int[] getPropertyIds( TokenRead tokenRead, String[] propertyKeys ) return propertyKeyIds; } - public static int[] getPropertyIds( ReadOperations statement, Iterable propertyKeys ) - { - return Iterables.stream( propertyKeys ).mapToInt( statement::propertyKeyGetForName ).toArray(); - } - public static int[] getPropertyIds( TokenRead tokenRead, Iterable propertyKeys ) { return Iterables.stream( propertyKeys ).mapToInt( tokenRead::propertyKey ).toArray(); diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/newapi/AllStoreHolder.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/newapi/AllStoreHolder.java index 69f7780cc9c45..a160698cc9b72 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/newapi/AllStoreHolder.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/newapi/AllStoreHolder.java @@ -488,6 +488,20 @@ public long nodesCountIndexed( IndexReference index, long nodeId, Value value ) return reader.countIndexedNodes( nodeId, value ); } + @Override + public long nodesGetCount( ) + { + long base = storeReadLayer.nodesGetCount(); + return ktx.hasTxStateWithChanges() ? base + ktx.txState().addedAndRemovedNodes().delta() : base; + } + + @Override + public long relationshipsGetCount( ) + { + long base = storeReadLayer.relationshipsGetCount(); + return ktx.hasTxStateWithChanges() ? base + ktx.txState().addedAndRemovedRelationships().delta() : base; + } + @Override public Register.DoubleLongRegister indexUpdatesAndSize( IndexReference index, Register.DoubleLongRegister target ) throws IndexNotFoundKernelException diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/newapi/DefaultNodeValueIndexCursor.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/newapi/DefaultNodeValueIndexCursor.java index 2d52ef06cafdb..4875fd63a9653 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/newapi/DefaultNodeValueIndexCursor.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/newapi/DefaultNodeValueIndexCursor.java @@ -40,7 +40,6 @@ import static org.neo4j.collection.primitive.PrimitiveLongCollections.asSet; import static org.neo4j.collection.primitive.PrimitiveLongCollections.emptyIterator; import static org.neo4j.collection.primitive.PrimitiveLongCollections.emptySet; -import static org.neo4j.kernel.impl.api.StateHandlingStatementOperations.assertOnlyExactPredicates; import static org.neo4j.kernel.impl.store.record.AbstractBaseRecord.NO_ID; final class DefaultNodeValueIndexCursor extends IndexCursor @@ -297,6 +296,32 @@ private PrimitiveLongSet removed( TransactionState txState, PrimitiveLongReadabl return longSet; } + private static IndexQuery.ExactPredicate[] assertOnlyExactPredicates( IndexQuery[] predicates ) + { + IndexQuery.ExactPredicate[] exactPredicates; + if ( predicates.getClass() == IndexQuery.ExactPredicate[].class ) + { + exactPredicates = (IndexQuery.ExactPredicate[]) predicates; + } + else + { + exactPredicates = new IndexQuery.ExactPredicate[predicates.length]; + for ( int i = 0; i < predicates.length; i++ ) + { + if ( predicates[i] instanceof IndexQuery.ExactPredicate ) + { + exactPredicates[i] = (IndexQuery.ExactPredicate) predicates[i]; + } + else + { + // TODO: what to throw? + throw new UnsupportedOperationException( "Query not supported: " + Arrays.toString( predicates ) ); + } + } + } + return exactPredicates; + } + public void release() { // nothing to do diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/IdPrettyPrinter.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/IdPrettyPrinter.java index ccbef381441b1..56e24f31c6fc9 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/IdPrettyPrinter.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/IdPrettyPrinter.java @@ -19,8 +19,8 @@ */ package org.neo4j.kernel.impl.util; +import org.neo4j.internal.kernel.api.Read; import org.neo4j.internal.kernel.api.TokenRead; -import org.neo4j.kernel.api.ReadOperations; public class IdPrettyPrinter { @@ -30,7 +30,7 @@ private IdPrettyPrinter() public static String label( int id ) { - return id == ReadOperations.ANY_LABEL ? "" : (":label=" + id); + return id == Read.ANY_LABEL ? "" : (":label=" + id); } public static String propertyKey( int id ) diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/dbstructure/GraphDbStructureGuide.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/dbstructure/GraphDbStructureGuide.java index f7c483e18083f..43afa8643f1be 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/util/dbstructure/GraphDbStructureGuide.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/util/dbstructure/GraphDbStructureGuide.java @@ -21,30 +21,38 @@ import java.util.Iterator; +import javax.xml.validation.SchemaFactory; + import org.neo4j.graphdb.DependencyResolver; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Label; import org.neo4j.graphdb.RelationshipType; import org.neo4j.graphdb.Transaction; import org.neo4j.helpers.collection.Visitable; +import org.neo4j.internal.kernel.api.IndexReference; +import org.neo4j.internal.kernel.api.Read; +import org.neo4j.internal.kernel.api.SchemaRead; import org.neo4j.internal.kernel.api.TokenNameLookup; +import org.neo4j.internal.kernel.api.TokenRead; import org.neo4j.internal.kernel.api.exceptions.KernelException; import org.neo4j.internal.kernel.api.schema.constraints.ConstraintDescriptor; -import org.neo4j.kernel.api.ReadOperations; -import org.neo4j.kernel.api.Statement; -import org.neo4j.kernel.api.StatementTokenNameLookup; +import org.neo4j.kernel.api.KernelTransaction; +import org.neo4j.kernel.api.SilentTokenNameLookup; import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; +import org.neo4j.kernel.api.schema.LabelSchemaDescriptor; +import org.neo4j.kernel.api.schema.SchemaDescriptorFactory; import org.neo4j.kernel.api.schema.constaints.NodeExistenceConstraintDescriptor; import org.neo4j.kernel.api.schema.constaints.RelExistenceConstraintDescriptor; import org.neo4j.kernel.api.schema.constaints.UniquenessConstraintDescriptor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; +import org.neo4j.kernel.impl.api.store.DefaultIndexReference; import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge; import org.neo4j.kernel.internal.GraphDatabaseAPI; import static java.lang.String.format; import static org.neo4j.helpers.collection.Iterators.loop; -import static org.neo4j.kernel.api.ReadOperations.ANY_LABEL; -import static org.neo4j.kernel.api.ReadOperations.ANY_RELATIONSHIP_TYPE; +import static org.neo4j.internal.kernel.api.IndexReference.sortByType; +import static org.neo4j.kernel.api.StatementConstants.ANY_LABEL; +import static org.neo4j.kernel.api.StatementConstants.ANY_RELATIONSHIP_TYPE; public class GraphDbStructureGuide implements Visitable { @@ -65,23 +73,19 @@ public void accept( DbStructureVisitor visitor ) { try ( Transaction tx = db.beginTx() ) { - try ( Statement statement = bridge.get() ) - { - showStructure( statement, visitor ); - } + showStructure( bridge.getKernelTransactionBoundToThisThread( true ), visitor ); tx.success(); } } - private void showStructure( Statement statement, DbStructureVisitor visitor ) + private void showStructure( KernelTransaction ktx, DbStructureVisitor visitor ) { - ReadOperations read = statement.readOperations(); try { - showTokens( visitor, read ); - showSchema( visitor, read ); - showStatistics( visitor, read ); + showTokens( visitor, ktx ); + showSchema( visitor, ktx ); + showStatistics( visitor, ktx ); } catch ( KernelException e ) { @@ -90,63 +94,65 @@ private void showStructure( Statement statement, DbStructureVisitor visitor ) } } - private void showTokens( DbStructureVisitor visitor, ReadOperations read ) + private void showTokens( DbStructureVisitor visitor, KernelTransaction ktx ) { - showLabels( read, visitor ); - showPropertyKeys( read, visitor ); - showRelTypes( read, visitor ); + showLabels( ktx, visitor ); + showPropertyKeys( ktx, visitor ); + showRelTypes( ktx, visitor ); } - private void showLabels( ReadOperations read, DbStructureVisitor visitor ) + private void showLabels( KernelTransaction ktx, DbStructureVisitor visitor ) { for ( Label label : db.getAllLabels() ) { - int labelId = read.labelGetForName( label.name() ); + int labelId = ktx.tokenRead().nodeLabel( label.name() ); visitor.visitLabel( labelId, label.name() ); } } - private void showPropertyKeys( ReadOperations read, DbStructureVisitor visitor ) + private void showPropertyKeys( KernelTransaction ktx, DbStructureVisitor visitor ) { for ( String propertyKeyName : db.getAllPropertyKeys() ) { - int propertyKeyId = read.propertyKeyGetForName( propertyKeyName ); + int propertyKeyId = ktx.tokenRead().propertyKey( propertyKeyName ); visitor.visitPropertyKey( propertyKeyId, propertyKeyName ); } } - private void showRelTypes( ReadOperations read, DbStructureVisitor visitor ) + private void showRelTypes( KernelTransaction ktx, DbStructureVisitor visitor ) { for ( RelationshipType relType : db.getAllRelationshipTypes() ) { - int relTypeId = read.relationshipTypeGetForName( relType.name() ); + int relTypeId = ktx.tokenRead().relationshipType( relType.name() ); visitor.visitRelationshipType( relTypeId, relType.name() ); } } - private void showSchema( DbStructureVisitor visitor, ReadOperations read ) throws IndexNotFoundKernelException + private void showSchema( DbStructureVisitor visitor, KernelTransaction ktx ) throws IndexNotFoundKernelException { - TokenNameLookup nameLookup = new StatementTokenNameLookup( read ); + TokenNameLookup nameLookup = new SilentTokenNameLookup( ktx.tokenRead() ); - showIndices( visitor, read, nameLookup ); - showUniqueConstraints( visitor, read, nameLookup ); + showIndices( visitor, ktx, nameLookup ); + showUniqueConstraints( visitor, ktx, nameLookup ); } - private void showIndices( DbStructureVisitor visitor, ReadOperations read, TokenNameLookup nameLookup ) + private void showIndices( DbStructureVisitor visitor, KernelTransaction ktx, TokenNameLookup nameLookup ) throws IndexNotFoundKernelException { - for ( SchemaIndexDescriptor descriptor : loop( SchemaIndexDescriptor.sortByType( read.indexesGetAll() ) ) ) + SchemaRead schemaRead = ktx.schemaRead(); + for ( IndexReference reference : loop( sortByType( schemaRead.indexesGetAll() ) ) ) { - String userDescription = descriptor.schema().userDescription( nameLookup ); - double uniqueValuesPercentage = read.indexUniqueValuesSelectivity( descriptor ); - long size = read.indexSize( descriptor ); - visitor.visitIndex( descriptor, userDescription, uniqueValuesPercentage, size ); + String userDescription = SchemaDescriptorFactory.forLabel( reference.label(), reference.properties() ) + .userDescription( nameLookup ); + double uniqueValuesPercentage = schemaRead.indexUniqueValuesSelectivity( reference ); + long size = schemaRead.indexSize( reference ); + visitor.visitIndex( DefaultIndexReference.toDescriptor( reference ), userDescription, uniqueValuesPercentage, size ); } } - private void showUniqueConstraints( DbStructureVisitor visitor, ReadOperations read, TokenNameLookup nameLookup ) + private void showUniqueConstraints( DbStructureVisitor visitor, KernelTransaction ktx, TokenNameLookup nameLookup ) { - Iterator constraints = read.constraintsGetAll(); + Iterator constraints = ktx.schemaRead().constraintsGetAll(); while ( constraints.hasNext() ) { ConstraintDescriptor constraint = constraints.next(); @@ -174,78 +180,80 @@ else if ( constraint instanceof RelExistenceConstraintDescriptor ) } } - private void showStatistics( DbStructureVisitor visitor, ReadOperations read ) + private void showStatistics( DbStructureVisitor visitor, KernelTransaction ktx ) { - showNodeCounts( read, visitor ); - showRelCounts( read, visitor ); + showNodeCounts( ktx, visitor ); + showRelCounts( ktx, visitor ); } - private void showNodeCounts( ReadOperations read, DbStructureVisitor visitor ) + private void showNodeCounts( KernelTransaction ktx, DbStructureVisitor visitor ) { + Read read = ktx.dataRead(); visitor.visitAllNodesCount( read.countsForNode( ANY_LABEL ) ); for ( Label label : db.getAllLabels() ) { - int labelId = read.labelGetForName( label.name() ); + int labelId = ktx.tokenRead().nodeLabel( label.name() ); visitor.visitNodeCount( labelId, label.name(), read.countsForNode( labelId ) ); } } - private void showRelCounts( ReadOperations read, DbStructureVisitor visitor ) + private void showRelCounts( KernelTransaction ktx, DbStructureVisitor visitor ) { // all wildcards - noSide( read, visitor, WILDCARD_REL_TYPE, ANY_RELATIONSHIP_TYPE ); + noSide( ktx, visitor, WILDCARD_REL_TYPE, ANY_RELATIONSHIP_TYPE ); + TokenRead tokenRead = ktx.tokenRead(); // one label only for ( Label label : db.getAllLabels() ) { - int labelId = read.labelGetForName( label.name() ); + int labelId = tokenRead.nodeLabel( label.name() ); - leftSide( read, visitor, label, labelId, WILDCARD_REL_TYPE, ANY_RELATIONSHIP_TYPE ); - rightSide( read, visitor, label, labelId, WILDCARD_REL_TYPE, ANY_RELATIONSHIP_TYPE ); + leftSide( ktx, visitor, label, labelId, WILDCARD_REL_TYPE, ANY_RELATIONSHIP_TYPE ); + rightSide( ktx, visitor, label, labelId, WILDCARD_REL_TYPE, ANY_RELATIONSHIP_TYPE ); } // fixed rel type for ( RelationshipType relType : db.getAllRelationshipTypes() ) { - int relTypeId = read.relationshipTypeGetForName( relType.name() ); - noSide( read, visitor, relType, relTypeId ); + int relTypeId = tokenRead.relationshipType( relType.name() ); + noSide( ktx, visitor, relType, relTypeId ); for ( Label label : db.getAllLabels() ) { - int labelId = read.labelGetForName( label.name() ); + int labelId = tokenRead.nodeLabel( label.name() ); // wildcard on right - leftSide( read, visitor, label, labelId, relType, relTypeId ); + leftSide( ktx, visitor, label, labelId, relType, relTypeId ); // wildcard on left - rightSide( read, visitor, label, labelId, relType, relTypeId ); + rightSide( ktx, visitor, label, labelId, relType, relTypeId ); } } } - private void noSide( ReadOperations read, DbStructureVisitor visitor, RelationshipType relType, int relTypeId ) + private void noSide( KernelTransaction ktx, DbStructureVisitor visitor, RelationshipType relType, int relTypeId ) { String userDescription = format("MATCH ()-[%s]->() RETURN count(*)", colon( relType.name() )); - long amount = read.countsForRelationship( ANY_LABEL, relTypeId, ANY_LABEL ); + long amount = ktx.dataRead().countsForRelationship( ANY_LABEL, relTypeId, ANY_LABEL ); visitor.visitRelCount( ANY_LABEL, relTypeId, ANY_LABEL, userDescription, amount ); } - private void leftSide( ReadOperations read, DbStructureVisitor visitor, Label label, int labelId, + private void leftSide( KernelTransaction ktx, DbStructureVisitor visitor, Label label, int labelId, RelationshipType relType, int relTypeId ) { String userDescription = format( "MATCH (%s)-[%s]->() RETURN count(*)", colon( label.name() ), colon( relType.name() ) ); - long amount = read.countsForRelationship( labelId, relTypeId, ANY_LABEL ); + long amount = ktx.dataRead().countsForRelationship( labelId, relTypeId, ANY_LABEL ); visitor.visitRelCount( labelId, relTypeId, ANY_LABEL, userDescription, amount ); } - private void rightSide( ReadOperations read, DbStructureVisitor visitor, Label label, int labelId, + private void rightSide( KernelTransaction ktx, DbStructureVisitor visitor, Label label, int labelId, RelationshipType relType, int relTypeId ) { String userDescription = format( "MATCH ()-[%s]->(%s) RETURN count(*)", colon( relType.name() ), colon( label.name() ) ); - long amount = read.countsForRelationship( ANY_LABEL, relTypeId, labelId ); + long amount = ktx.dataRead().countsForRelationship( ANY_LABEL, relTypeId, labelId ); visitor.visitRelCount( ANY_LABEL, relTypeId, labelId, userDescription, amount ); } diff --git a/community/kernel/src/main/java/org/neo4j/unsafe/impl/batchimport/NodeCountsProcessor.java b/community/kernel/src/main/java/org/neo4j/unsafe/impl/batchimport/NodeCountsProcessor.java index 6aac23e405f08..b94ed5b0e196a 100644 --- a/community/kernel/src/main/java/org/neo4j/unsafe/impl/batchimport/NodeCountsProcessor.java +++ b/community/kernel/src/main/java/org/neo4j/unsafe/impl/batchimport/NodeCountsProcessor.java @@ -19,7 +19,7 @@ */ package org.neo4j.unsafe.impl.batchimport; -import org.neo4j.kernel.api.ReadOperations; +import org.neo4j.kernel.api.StatementConstants; import org.neo4j.kernel.impl.api.CountsAccessor; import org.neo4j.kernel.impl.store.NodeLabelsField; import org.neo4j.kernel.impl.store.NodeStore; @@ -76,7 +76,7 @@ public void done() { for ( int i = 0; i < labelCounts.length; i++ ) { - counts.incrementNodeCount( i == anyLabel ? ReadOperations.ANY_LABEL : i, labelCounts[i] ); + counts.incrementNodeCount( i == anyLabel ? StatementConstants.ANY_LABEL : i, labelCounts[i] ); } } } diff --git a/community/kernel/src/main/java/org/neo4j/unsafe/impl/batchimport/RelationshipCountsProcessor.java b/community/kernel/src/main/java/org/neo4j/unsafe/impl/batchimport/RelationshipCountsProcessor.java index a7d0231ce3c0e..0d6c0025d59dc 100644 --- a/community/kernel/src/main/java/org/neo4j/unsafe/impl/batchimport/RelationshipCountsProcessor.java +++ b/community/kernel/src/main/java/org/neo4j/unsafe/impl/batchimport/RelationshipCountsProcessor.java @@ -19,7 +19,7 @@ */ package org.neo4j.unsafe.impl.batchimport; -import org.neo4j.kernel.api.ReadOperations; +import org.neo4j.kernel.api.StatementConstants; import org.neo4j.kernel.impl.api.CountsAccessor; import org.neo4j.kernel.impl.store.record.RelationshipRecord; import org.neo4j.unsafe.impl.batchimport.cache.LongArray; @@ -103,10 +103,10 @@ public void done() { for ( int wildcardType = 0; wildcardType <= anyRelationshipType; wildcardType++ ) { - int type = wildcardType == anyRelationshipType ? ReadOperations.ANY_RELATIONSHIP_TYPE : wildcardType; + int type = wildcardType == anyRelationshipType ? StatementConstants.ANY_RELATIONSHIP_TYPE : wildcardType; long count = wildcardCounts.get( wildcardType ); countsUpdater.incrementRelationshipCount( - ReadOperations.ANY_LABEL, type, ReadOperations.ANY_LABEL, count ); + StatementConstants.ANY_LABEL, type, StatementConstants.ANY_LABEL, count ); } for ( int labelId = 0; labelId < anyLabel; labelId++ ) @@ -116,10 +116,10 @@ public void done() long startCount = labelsCounts.get( arrayIndex( labelId, typeId, START ) ); long endCount = labelsCounts.get( arrayIndex( labelId, typeId, END ) ); - int type = typeId == anyRelationshipType ? ReadOperations.ANY_RELATIONSHIP_TYPE : typeId; + int type = typeId == anyRelationshipType ? StatementConstants.ANY_RELATIONSHIP_TYPE : typeId; - countsUpdater.incrementRelationshipCount( labelId, type, ReadOperations.ANY_LABEL, startCount ); - countsUpdater.incrementRelationshipCount( ReadOperations.ANY_LABEL, type, labelId, endCount ); + countsUpdater.incrementRelationshipCount( labelId, type, StatementConstants.ANY_LABEL, startCount ); + countsUpdater.incrementRelationshipCount( StatementConstants.ANY_LABEL, type, labelId, endCount ); } } } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/api/index/CompositeIndexAccessorCompatibility.java b/community/kernel/src/test/java/org/neo4j/kernel/api/index/CompositeIndexAccessorCompatibility.java index a9a76ec23f3bb..d4b9a183e1913 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/api/index/CompositeIndexAccessorCompatibility.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/api/index/CompositeIndexAccessorCompatibility.java @@ -162,7 +162,7 @@ public void closingAnOnlineIndexUpdaterMustNotThrowEvenIfItHasBeenFedConflicting // we cannot have them go around and throw exceptions, because that could potentially break // recovery. // Conflicting data can happen because of faulty data coercion. These faults are resolved by - // the exact-match filtering we do on index seeks in StateHandlingStatementOperations. + // the exact-match filtering we do on index seeks. updateAndCommit( asList( add( 1L, descriptor.schema(), "a", "a" ), diff --git a/community/kernel/src/test/java/org/neo4j/kernel/api/index/SimpleIndexAccessorCompatibility.java b/community/kernel/src/test/java/org/neo4j/kernel/api/index/SimpleIndexAccessorCompatibility.java index e155da29d22d3..745de104562af 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/api/index/SimpleIndexAccessorCompatibility.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/api/index/SimpleIndexAccessorCompatibility.java @@ -207,7 +207,7 @@ public void closingAnOnlineIndexUpdaterMustNotThrowEvenIfItHasBeenFedConflicting // we cannot have them go around and throw exceptions, because that could potentially break // recovery. // Conflicting data can happen because of faulty data coercion. These faults are resolved by - // the exact-match filtering we do on index seeks in StateHandlingStatementOperations. + // the exact-match filtering we do on index seeks. updateAndCommit( asList( add( 1L, descriptor.schema(), "a" ), @@ -415,7 +415,7 @@ public void closingAnOnlineIndexUpdaterMustNotThrowEvenIfItHasBeenFedConflicting // we cannot have them go around and throw exceptions, because that could potentially break // recovery. // Conflicting data can happen because of faulty data coercion. These faults are resolved by - // the exact-match filtering we do on index seeks in StateHandlingStatementOperations. + // the exact-match filtering we do on index seeks. updateAndCommit( asList( add( 1L, descriptor.schema(), "a" ), diff --git a/community/kernel/src/test/java/org/neo4j/kernel/builtinprocs/ResampleOutdatedIndexesProcedureTest.java b/community/kernel/src/test/java/org/neo4j/kernel/builtinprocs/ResampleOutdatedIndexesProcedureTest.java index 81578a9679932..bb55d66e687a6 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/builtinprocs/ResampleOutdatedIndexesProcedureTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/builtinprocs/ResampleOutdatedIndexesProcedureTest.java @@ -30,7 +30,7 @@ public class ResampleOutdatedIndexesProcedureTest { private final IndexingService indexingService = mock( IndexingService.class ); - private final IndexProcedures procedure = new IndexProcedures( new StubKernelTransaction( null ), indexingService ); + private final IndexProcedures procedure = new IndexProcedures( new StubKernelTransaction( ), indexingService ); @Test public void shouldTriggerResampling() diff --git a/community/kernel/src/test/java/org/neo4j/kernel/builtinprocs/StubKernelTransaction.java b/community/kernel/src/test/java/org/neo4j/kernel/builtinprocs/StubKernelTransaction.java index 620e65c04381e..05ccf17bf135e 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/builtinprocs/StubKernelTransaction.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/builtinprocs/StubKernelTransaction.java @@ -39,24 +39,21 @@ import org.neo4j.internal.kernel.api.Write; import org.neo4j.internal.kernel.api.security.SecurityContext; import org.neo4j.kernel.api.KernelTransaction; -import org.neo4j.kernel.api.ReadOperations; import org.neo4j.kernel.api.Statement; import org.neo4j.kernel.api.exceptions.Status; import org.neo4j.kernel.impl.api.ClockContext; public class StubKernelTransaction implements KernelTransaction { - private final ReadOperations readOperations; - StubKernelTransaction( ReadOperations readOperations ) + StubKernelTransaction( ) { - this.readOperations = readOperations; } @Override public Statement acquireStatement() { - return new StubStatement( readOperations ); + return new StubStatement( ); } @Override diff --git a/community/kernel/src/test/java/org/neo4j/kernel/builtinprocs/StubStatement.java b/community/kernel/src/test/java/org/neo4j/kernel/builtinprocs/StubStatement.java index a360e6837e802..8709bddc61ae3 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/builtinprocs/StubStatement.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/builtinprocs/StubStatement.java @@ -19,20 +19,12 @@ */ package org.neo4j.kernel.builtinprocs; -import org.neo4j.kernel.api.DataWriteOperations; import org.neo4j.kernel.api.QueryRegistryOperations; -import org.neo4j.kernel.api.ReadOperations; import org.neo4j.kernel.api.Statement; import org.neo4j.kernel.api.StubResourceManager; public class StubStatement extends StubResourceManager implements Statement { - private final ReadOperations readOperations; - - StubStatement( ReadOperations readOperations ) - { - this.readOperations = readOperations; - } @Override public void close() @@ -40,18 +32,6 @@ public void close() throw new UnsupportedOperationException( "not implemented" ); } - @Override - public ReadOperations readOperations() - { - return readOperations; - } - - @Override - public DataWriteOperations dataWriteOperations() - { - throw new UnsupportedOperationException( "not implemented" ); - } - @Override public QueryRegistryOperations queryRegistration() { diff --git a/community/kernel/src/test/java/org/neo4j/kernel/counts/CompositeCountsTest.java b/community/kernel/src/test/java/org/neo4j/kernel/counts/CompositeCountsTest.java index ca169c3bf181a..2100319237146 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/counts/CompositeCountsTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/counts/CompositeCountsTest.java @@ -32,8 +32,8 @@ import org.neo4j.graphdb.Transaction; import org.neo4j.internal.kernel.api.TokenRead; import org.neo4j.kernel.api.KernelTransaction; -import org.neo4j.kernel.api.ReadOperations; import org.neo4j.kernel.api.Statement; +import org.neo4j.kernel.api.StatementConstants; import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge; import org.neo4j.kernel.impl.newapi.Read; import org.neo4j.test.rule.DatabaseRule; @@ -405,7 +405,7 @@ private long countsForRelationship( Label start, RelationshipType type, Label en // start if ( start == null ) { - startId = ReadOperations.ANY_LABEL; + startId = StatementConstants.ANY_LABEL; } else { diff --git a/community/kernel/src/test/java/org/neo4j/kernel/counts/LabelCountsTest.java b/community/kernel/src/test/java/org/neo4j/kernel/counts/LabelCountsTest.java index 61ec8a3214f22..c766c04b0c1f6 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/counts/LabelCountsTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/counts/LabelCountsTest.java @@ -32,7 +32,7 @@ import org.neo4j.internal.kernel.api.Read; import org.neo4j.internal.kernel.api.TokenRead; import org.neo4j.kernel.api.KernelTransaction; -import org.neo4j.kernel.api.ReadOperations; +import org.neo4j.kernel.api.StatementConstants; import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge; import org.neo4j.test.rule.DatabaseRule; import org.neo4j.test.rule.ImpermanentDatabaseRule; @@ -221,7 +221,7 @@ private long countsForNode( Label label ) int labelId; if ( label == null ) { - labelId = ReadOperations.ANY_LABEL; + labelId = StatementConstants.ANY_LABEL; } else { diff --git a/community/kernel/src/test/java/org/neo4j/kernel/counts/NodeCountsTest.java b/community/kernel/src/test/java/org/neo4j/kernel/counts/NodeCountsTest.java index 919e6be9e5e2d..6c0de073a29c0 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/counts/NodeCountsTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/counts/NodeCountsTest.java @@ -30,7 +30,7 @@ import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Transaction; import org.neo4j.kernel.api.KernelTransaction; -import org.neo4j.kernel.api.ReadOperations; +import org.neo4j.kernel.api.StatementConstants; import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge; import org.neo4j.test.Barrier; import org.neo4j.test.NamedFunction; @@ -212,6 +212,6 @@ private long numberOfNodes() private long countsForNode() { - return kernelTransactionSupplier.get().dataRead().countsForNode( ReadOperations.ANY_LABEL ); + return kernelTransactionSupplier.get().dataRead().countsForNode( StatementConstants.ANY_LABEL ); } } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/AutoIndexOperationsTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/AutoIndexOperationsTest.java deleted file mode 100644 index 7dabe5a9f324b..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/AutoIndexOperationsTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api; - -import org.junit.Before; -import org.junit.Test; - -import org.neo4j.kernel.api.DataWriteOperations; -import org.neo4j.kernel.api.explicitindex.AutoIndexOperations; -import org.neo4j.kernel.impl.api.explicitindex.InternalAutoIndexOperations; -import org.neo4j.kernel.impl.core.PropertyKeyTokenHolder; -import org.neo4j.kernel.impl.core.TokenNotFoundException; -import org.neo4j.storageengine.api.Token; -import org.neo4j.values.storable.Values; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; -import static org.neo4j.kernel.impl.api.explicitindex.InternalAutoIndexing.NODE_AUTO_INDEX; - -public class AutoIndexOperationsTest -{ - private final DataWriteOperations ops = mock(DataWriteOperations.class); - private final PropertyKeyTokenHolder tokens = mock( PropertyKeyTokenHolder.class ); - private final AutoIndexOperations index = new InternalAutoIndexOperations( tokens, InternalAutoIndexOperations.EntityType.NODE ); - - private final int nonIndexedProperty = 1337; - private final String nonIndexedPropertyName = "foo"; - private final int indexedProperty = 1338; - private final int indexedProperty2 = 1339; - private final String indexedPropertyName = "bar"; - private final String indexedPropertyName2 = "baz"; - - @Before - public void setup() throws TokenNotFoundException - { - when(tokens.getTokenById( nonIndexedProperty )).thenReturn( new Token( nonIndexedPropertyName, nonIndexedProperty ) ); - when(tokens.getTokenById( indexedProperty )).thenReturn( new Token( indexedPropertyName, indexedProperty ) ); - when(tokens.getTokenById( indexedProperty2 )).thenReturn( new Token( indexedPropertyName, indexedProperty2 ) ); - index.enabled( true ); - } - - @Test - public void shouldNotRemoveFromIndexForNonAutoIndexedProperty() throws Exception - { - // Given - index.startAutoIndexingProperty( indexedPropertyName ); - - // When - index.propertyRemoved( ops, 11, nonIndexedProperty ); - - // Then - verifyZeroInteractions( ops ); - } - - @Test - public void shouldRemoveSpecificValueFromIndexForAutoIndexedProperty() throws Exception - { - // Given - long nodeId = 11; - int value1 = 1; - int value2 = 2; - index.startAutoIndexingProperty( indexedPropertyName ); - index.startAutoIndexingProperty( indexedPropertyName2 ); - index.propertyAdded( ops, nodeId, indexedProperty, Values.of( value1 ) ); - index.propertyAdded( ops, nodeId, indexedProperty2, Values.of( value2 ) ); - - // When - reset( ops ); - index.propertyRemoved( ops, nodeId, indexedProperty ); - - // Then - verify( ops ).nodeRemoveFromExplicitIndex( NODE_AUTO_INDEX, nodeId, indexedPropertyName ); - } - - @Test - public void shouldNotAddToIndexForNonAutoIndexedProperty() throws Exception - { - // Given - index.startAutoIndexingProperty( indexedPropertyName ); - - // When - index.propertyAdded( ops, 11, nonIndexedProperty, Values.of( "Hello!" ) ); - - // Then - verifyZeroInteractions( ops ); - } - - @Test - public void shouldNotAddOrRemoveFromIndexForNonAutoIndexedProperty() throws Exception - { - // Given - index.startAutoIndexingProperty( indexedPropertyName ); - - // When - index.propertyChanged( ops, 11, nonIndexedProperty, Values.of( "Goodbye!" ), Values.of( "Hello!" ) ); - - // Then - verifyZeroInteractions( ops ); - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/CountsStoreTransactionApplierTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/CountsStoreTransactionApplierTest.java index 3a3a1188b2e10..50cc94032e0cd 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/CountsStoreTransactionApplierTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/CountsStoreTransactionApplierTest.java @@ -23,7 +23,7 @@ import java.util.Optional; -import org.neo4j.kernel.api.ReadOperations; +import org.neo4j.kernel.api.StatementConstants; import org.neo4j.kernel.impl.store.counts.CountsTracker; import org.neo4j.kernel.impl.transaction.command.Command; import org.neo4j.storageengine.api.TransactionApplicationMode; @@ -49,10 +49,10 @@ public void shouldNotifyCacheAccessOnHowManyUpdatesOnCountsWeHadSoFar() throws E // WHEN try ( TransactionApplier txApplier = applier.startTx( new TransactionToApply( null, 2L ) ) ) { - txApplier.visitNodeCountsCommand( new Command.NodeCountsCommand( ReadOperations.ANY_LABEL, 1 ) ); + txApplier.visitNodeCountsCommand( new Command.NodeCountsCommand( StatementConstants.ANY_LABEL, 1 ) ); } // THEN - verify( updater, times( 1 ) ).incrementNodeCount( ReadOperations.ANY_LABEL, 1 ); + verify( updater, times( 1 ) ).incrementNodeCount( StatementConstants.ANY_LABEL, 1 ); } } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/DataIntegrityValidatingStatementOperationsTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/DataIntegrityValidatingStatementOperationsTest.java deleted file mode 100644 index cb3c803dc50e6..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/DataIntegrityValidatingStatementOperationsTest.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.stubbing.Answer; - -import java.util.Iterator; - -import org.neo4j.internal.kernel.api.schema.LabelSchemaDescriptor; -import org.neo4j.kernel.api.exceptions.schema.AlreadyConstrainedException; -import org.neo4j.kernel.api.exceptions.schema.AlreadyIndexedException; -import org.neo4j.kernel.api.exceptions.schema.DropIndexFailureException; -import org.neo4j.internal.kernel.api.exceptions.schema.IllegalTokenNameException; -import org.neo4j.kernel.api.exceptions.schema.IndexBelongsToConstraintException; -import org.neo4j.kernel.api.exceptions.schema.NoSuchIndexException; -import org.neo4j.kernel.api.exceptions.schema.RepeatedPropertyInCompositeSchemaException; -import org.neo4j.internal.kernel.api.exceptions.schema.SchemaKernelException; -import org.neo4j.kernel.api.schema.SchemaDescriptorFactory; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptorFactory; -import org.neo4j.kernel.impl.api.operations.KeyWriteOperations; -import org.neo4j.kernel.impl.api.operations.SchemaReadOperations; -import org.neo4j.kernel.impl.api.operations.SchemaWriteOperations; - -import static org.hamcrest.core.IsInstanceOf.instanceOf; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.helpers.collection.Iterators.iterator; - -public class DataIntegrityValidatingStatementOperationsTest -{ - @Rule - public ExpectedException exception = ExpectedException.none(); - - LabelSchemaDescriptor descriptor = SchemaDescriptorFactory.forLabel( 0, 7 ); - SchemaIndexDescriptor index = SchemaIndexDescriptorFactory.forLabel( 0, 7 ); - SchemaIndexDescriptor uniqueIndex = SchemaIndexDescriptorFactory.uniqueForLabel( 0, 7 ); - private SchemaReadOperations innerRead; - private SchemaWriteOperations innerWrite; - private KeyWriteOperations innerKeyWrite; - private DataIntegrityValidatingStatementOperations ops; - - @Before - public void setup() - { - innerKeyWrite = mock( KeyWriteOperations.class ); - innerRead = mock( SchemaReadOperations.class ); - innerWrite = mock( SchemaWriteOperations.class ); - ops = new DataIntegrityValidatingStatementOperations( innerKeyWrite, innerRead, innerWrite ); - } - - @Test - public void shouldDisallowReAddingIndex() throws Exception - { - // GIVEN - when( innerRead.indexGetForSchema( state, descriptor ) ).thenReturn( index ); - - // WHEN - try - { - ops.indexCreate( state, descriptor ); - fail( "Should have thrown exception." ); - } - catch ( AlreadyIndexedException e ) - { - // ok - } - - // THEN - verify( innerWrite, never() ).indexCreate( eq( state ), any() ); - } - - @Test - public void shouldDisallowAddingIndexWhenConstraintIndexExists() throws Exception - { - // GIVEN - when( innerRead.indexGetForSchema( state, descriptor ) ).thenReturn( uniqueIndex ); - - // WHEN - try - { - ops.indexCreate( state, descriptor ); - fail( "Should have thrown exception." ); - } - catch ( AlreadyConstrainedException e ) - { - // ok - } - - // THEN - verify( innerWrite, never() ).indexCreate( eq( state ), any() ); - } - - @Test - public void shouldDisallowDroppingIndexThatDoesNotExist() throws Exception - { - // GIVEN - when( innerRead.indexGetForSchema( state, descriptor ) ).thenReturn( null ); - - // WHEN - try - { - ops.indexDrop( state, index ); - fail( "Should have thrown exception." ); - } - catch ( DropIndexFailureException e ) - { - assertThat(e.getCause(), instanceOf( NoSuchIndexException.class) ); - } - - // THEN - verify( innerWrite, never() ).indexCreate( eq( state ), any() ); - } - - @Test - public void shouldDisallowDroppingIndexWhenConstraintIndexExists() throws Exception - { - // GIVEN - when( innerRead.indexGetForSchema( state, descriptor ) ).thenReturn( uniqueIndex ); - - // WHEN - try - { - ops.indexDrop( state, index ); - fail( "Should have thrown exception." ); - } - catch ( DropIndexFailureException e ) - { - assertThat(e.getCause(), instanceOf( IndexBelongsToConstraintException.class) ); - } - - // THEN - verify( innerWrite, never() ).indexCreate( eq( state ), any() ); - } - - @Test - public void shouldDisallowDroppingConstraintIndexThatDoesNotExists() throws Exception - { - // GIVEN - when( innerRead.indexGetForSchema( state, descriptor ) ).thenReturn( uniqueIndex ); - - // WHEN - try - { - ops.indexDrop( state, index ); - fail( "Should have thrown exception." ); - } - catch ( DropIndexFailureException e ) - { - assertThat(e.getCause(), instanceOf( IndexBelongsToConstraintException.class) ); - } - - // THEN - verify( innerWrite, never() ).indexCreate( eq( state ), any() ); - } - - @Test - public void shouldDisallowDroppingConstraintIndexThatIsReallyJustRegularIndex() throws Exception - { - // GIVEN - when( innerRead.indexGetForSchema( state, descriptor ) ).thenReturn( uniqueIndex ); - - // WHEN - try - { - ops.indexDrop( state, index ); - fail( "Should have thrown exception." ); - } - catch ( DropIndexFailureException e ) - { - assertThat(e.getCause(), instanceOf( IndexBelongsToConstraintException.class) ); - } - - // THEN - verify( innerWrite, never() ).indexCreate( eq( state ), any() ); - } - - @Test - public void shouldDisallowNullOrEmptyPropertyKey() - { - try - { - ops.propertyKeyGetOrCreateForName( state, null ); - fail( "Should not be able to create null property key" ); - } - catch ( IllegalTokenNameException e ) - { // good - } - - try - { - ops.propertyKeyGetOrCreateForName( state, "" ); - fail( "Should not be able to create empty property key" ); - } - catch ( IllegalTokenNameException e ) - { // good - } - } - - @Test - public void shouldDisallowNullOrEmptyLabelName() throws Exception - { - try - { - ops.labelGetOrCreateForName( state, null ); - fail( "Should not be able to create null label" ); - } - catch ( IllegalTokenNameException e ) - { // good - } - - try - { - ops.labelGetOrCreateForName( state, "" ); - fail( "Should not be able to create empty label" ); - } - catch ( IllegalTokenNameException e ) - { // good - } - } - - @Test( expected = SchemaKernelException.class ) - public void shouldFailInvalidLabelNames() throws Exception - { - ops.labelGetOrCreateForName( state, "" ); - } - - @Test( expected = SchemaKernelException.class ) - public void shouldFailOnNullLabel() throws Exception - { - ops.labelGetOrCreateForName( state, null ); - } - - @Test( expected = RepeatedPropertyInCompositeSchemaException.class ) - public void shouldFailIndexCreateOnRepeatedPropertyId() throws Exception - { - ops.indexCreate( state, SchemaDescriptorFactory.forLabel( 0, 1, 1 ) ); - } - - @Test( expected = RepeatedPropertyInCompositeSchemaException.class ) - public void shouldFailNodeExistenceCreateOnRepeatedPropertyId() throws Exception - { - ops.nodePropertyExistenceConstraintCreate( state, SchemaDescriptorFactory.forLabel( 0, 1, 1 ) ); - } - - @Test( expected = RepeatedPropertyInCompositeSchemaException.class ) - public void shouldFailRelExistenceCreateOnRepeatedPropertyId() throws Exception - { - ops.relationshipPropertyExistenceConstraintCreate( state, SchemaDescriptorFactory.forRelType( 0, 1, 1 ) ); - } - - @Test( expected = RepeatedPropertyInCompositeSchemaException.class ) - public void shouldFailUniquenessCreateOnRepeatedPropertyId() throws Exception - { - ops.uniquePropertyConstraintCreate( state, SchemaDescriptorFactory.forLabel( 0, 1, 1 ) ); - } - - @SafeVarargs - private static Answer> withIterator( final T... content ) - { - return invocationOnMock -> iterator( content ); - } - - private final KernelStatement state = StatementOperationsTestHelper.mockedState(); -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/DataStatementArgumentVerificationTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/DataStatementArgumentVerificationTest.java deleted file mode 100644 index e27b2ea851000..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/DataStatementArgumentVerificationTest.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api; - -import org.junit.Test; - -import org.neo4j.collection.primitive.PrimitiveLongIterator; -import org.neo4j.kernel.api.KernelTransaction; -import org.neo4j.kernel.api.ReadOperations; -import org.neo4j.kernel.api.StatementConstants; -import org.neo4j.kernel.impl.proc.Procedures; -import org.neo4j.values.storable.Value; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.neo4j.values.storable.Values.NO_VALUE; - -public class DataStatementArgumentVerificationTest -{ - @Test - public void shouldReturnNoPropertyFromNodeGetPropertyWithoutDelegatingForNoSuchPropertyKeyIdConstant() - throws Exception - { - // given - ReadOperations statement = stubStatement(); - - // when - Value value = statement.nodeGetProperty( 17, StatementConstants.NO_SUCH_PROPERTY_KEY ); - - // then - assertTrue( "should return NoProperty", value == NO_VALUE ); - } - - @Test - public void shouldReturnNoPropertyFromRelationshipGetPropertyWithoutDelegatingForNoSuchPropertyKeyIdConstant() - throws Exception - { - // given - ReadOperations statement = stubStatement(); - - // when - Value value = statement.relationshipGetProperty( 17, StatementConstants.NO_SUCH_PROPERTY_KEY ); - - // then - assertEquals( "should return NoProperty", value, NO_VALUE ); - } - - @Test - public void shouldReturnNoPropertyFromGraphGetPropertyWithoutDelegatingForNoSuchPropertyKeyIdConstant() - { - // given - ReadOperations statement = stubStatement(); - - // when - Object value = statement.graphGetProperty( StatementConstants.NO_SUCH_PROPERTY_KEY ); - - // then - assertEquals( "should return NoProperty", value, NO_VALUE ); - } - - @Test - public void shouldReturnEmptyIdIteratorFromNodesGetForLabelForNoSuchLabelConstant() - { - // given - ReadOperations statement = stubStatement(); - - // when - PrimitiveLongIterator nodes = statement.nodesGetForLabel( StatementConstants.NO_SUCH_LABEL ); - - // then - assertFalse( "should not contain any ids", nodes.hasNext() ); - } - - @Test - public void shouldAlwaysReturnFalseFromNodeHasLabelForNoSuchLabelConstant() throws Exception - { - // given - ReadOperations statement = stubStatement(); - - // when - boolean hasLabel = statement.nodeHasLabel( 17, StatementConstants.NO_SUCH_LABEL ); - - // then - assertFalse( "should not contain any ids", hasLabel ); - } - - private OperationsFacade stubStatement() - { - return new OperationsFacade( mock(KernelTransaction.class), mock( KernelStatement.class ), new Procedures(), - mock( StatementOperationParts.class ) ); - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelStatementTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelStatementTest.java index 1576fda454d72..df647cdff99af 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelStatementTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/KernelStatementTest.java @@ -21,19 +21,13 @@ import org.junit.Test; -import java.util.Optional; import java.util.concurrent.atomic.AtomicReference; import org.neo4j.graphdb.NotInTransactionException; -import org.neo4j.graphdb.TransactionTerminatedException; import org.neo4j.io.pagecache.tracing.cursor.context.EmptyVersionContextSupplier; -import org.neo4j.kernel.api.exceptions.Status; import org.neo4j.kernel.api.query.ExecutingQuery; import org.neo4j.kernel.api.txstate.TxStateHolder; -import org.neo4j.kernel.impl.factory.AccessCapability; -import org.neo4j.kernel.impl.factory.CanWrite; import org.neo4j.kernel.impl.locking.LockTracer; -import org.neo4j.kernel.impl.proc.Procedures; import org.neo4j.resources.CpuClock; import org.neo4j.resources.HeapAllocation; import org.neo4j.storageengine.api.StorageStatement; @@ -42,31 +36,16 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static org.neo4j.internal.kernel.api.security.SecurityContext.AUTH_DISABLED; public class KernelStatementTest { - @Test( expected = TransactionTerminatedException.class ) - public void shouldThrowTerminateExceptionWhenTransactionTerminated() - { - KernelTransactionImplementation transaction = mock( KernelTransactionImplementation.class ); - when( transaction.getReasonIfTerminated() ).thenReturn( Optional.of( Status.Transaction.Terminated ) ); - when( transaction.securityContext() ).thenReturn( AUTH_DISABLED ); - - KernelStatement statement = new KernelStatement( transaction, null, mock( StorageStatement.class ), null, new CanWrite(), - LockTracer.NONE, mock( StatementOperationParts.class ), new ClockContext(), EmptyVersionContextSupplier.EMPTY ); - statement.acquire(); - - statement.readOperations().nodeExists( 0 ); - } - @Test public void shouldReleaseStorageStatementWhenForceClosed() { // given StorageStatement storeStatement = mock( StorageStatement.class ); KernelStatement statement = new KernelStatement( mock( KernelTransactionImplementation.class ), - null, storeStatement, new Procedures(), new CanWrite(), LockTracer.NONE, + null, storeStatement, LockTracer.NONE, mock( StatementOperationParts.class ), new ClockContext(), EmptyVersionContextSupplier.EMPTY ); statement.acquire(); @@ -90,10 +69,8 @@ public void assertStatementIsNotOpenWhileAcquireIsNotInvoked() KernelTransactionImplementation transaction = mock( KernelTransactionImplementation.class ); TxStateHolder txStateHolder = mock( TxStateHolder.class ); StorageStatement storeStatement = mock( StorageStatement.class ); - AccessCapability accessCapability = mock( AccessCapability.class ); - Procedures procedures = mock( Procedures.class ); KernelStatement statement = new KernelStatement( transaction, txStateHolder, - storeStatement, procedures, accessCapability, LockTracer.NONE, mock( StatementOperationParts.class ), + storeStatement, LockTracer.NONE, mock( StatementOperationParts.class ), new ClockContext(), EmptyVersionContextSupplier.EMPTY ); statement.assertOpen(); @@ -105,8 +82,6 @@ public void reportQueryWaitingTimeToTransactionStatisticWhenFinishQueryExecution KernelTransactionImplementation transaction = mock( KernelTransactionImplementation.class ); TxStateHolder txStateHolder = mock( TxStateHolder.class ); StorageStatement storeStatement = mock( StorageStatement.class ); - AccessCapability accessCapability = mock( AccessCapability.class ); - Procedures procedures = mock( Procedures.class ); KernelTransactionImplementation.Statistics statistics = new KernelTransactionImplementation.Statistics( transaction, new AtomicReference<>( CpuClock.NOT_AVAILABLE ), new AtomicReference<>( HeapAllocation.NOT_AVAILABLE ) ); @@ -114,7 +89,7 @@ public void reportQueryWaitingTimeToTransactionStatisticWhenFinishQueryExecution when( transaction.executingQueries() ).thenReturn( ExecutingQueryList.EMPTY ); KernelStatement statement = new KernelStatement( transaction, txStateHolder, - storeStatement, procedures, accessCapability, LockTracer.NONE, mock( StatementOperationParts.class ), + storeStatement, LockTracer.NONE, mock( StatementOperationParts.class ), new ClockContext(), EmptyVersionContextSupplier.EMPTY ); statement.acquire(); diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/LockingStatementOperationsTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/LockingStatementOperationsTest.java deleted file mode 100644 index 4c813131261ea..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/LockingStatementOperationsTest.java +++ /dev/null @@ -1,521 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api; - -import org.junit.Test; -import org.mockito.InOrder; - -import java.util.Iterator; -import java.util.Optional; - -import org.neo4j.helpers.collection.Iterators; -import org.neo4j.internal.kernel.api.exceptions.EntityNotFoundException; -import org.neo4j.internal.kernel.api.exceptions.InvalidTransactionTypeKernelException; -import org.neo4j.internal.kernel.api.exceptions.KernelException; -import org.neo4j.internal.kernel.api.exceptions.explicitindex.AutoIndexingKernelException; -import org.neo4j.internal.kernel.api.schema.LabelSchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.constraints.ConstraintDescriptor; -import org.neo4j.io.pagecache.tracing.cursor.PageCursorTracer; -import org.neo4j.io.pagecache.tracing.cursor.context.EmptyVersionContextSupplier; -import org.neo4j.kernel.api.schema.SchemaDescriptorFactory; -import org.neo4j.kernel.api.schema.constaints.RelExistenceConstraintDescriptor; -import org.neo4j.kernel.api.schema.constaints.UniquenessConstraintDescriptor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptorFactory; -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.TwoPhaseNodeForRelationshipLockingTest.RelationshipData; -import org.neo4j.kernel.impl.api.operations.EntityReadOperations; -import org.neo4j.kernel.impl.api.operations.EntityWriteOperations; -import org.neo4j.kernel.impl.api.operations.SchemaReadOperations; -import org.neo4j.kernel.impl.api.operations.SchemaStateOperations; -import org.neo4j.kernel.impl.api.operations.SchemaWriteOperations; -import org.neo4j.kernel.impl.api.state.TxState; -import org.neo4j.kernel.impl.factory.CanWrite; -import org.neo4j.kernel.impl.locking.LockTracer; -import org.neo4j.kernel.impl.locking.Locks; -import org.neo4j.kernel.impl.locking.ResourceTypes; -import org.neo4j.kernel.impl.locking.SimpleStatementLocks; -import org.neo4j.kernel.impl.proc.Procedures; -import org.neo4j.storageengine.api.StorageStatement; -import org.neo4j.values.storable.Value; -import org.neo4j.values.storable.Values; - -import static java.util.Collections.emptyIterator; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.empty; -import static org.junit.Assert.assertSame; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.when; -import static org.neo4j.helpers.collection.Iterators.asList; -import static org.neo4j.kernel.api.schema.constaints.ConstraintDescriptorFactory.existsForRelType; -import static org.neo4j.kernel.api.schema.constaints.ConstraintDescriptorFactory.uniqueForLabel; -import static org.neo4j.kernel.api.schema.constaints.ConstraintDescriptorFactory.uniqueForSchema; -import static org.neo4j.kernel.impl.api.TwoPhaseNodeForRelationshipLockingTest.returnRelationships; - -public class LockingStatementOperationsTest -{ - private final LockingStatementOperations lockingOps; - private final EntityReadOperations entityReadOps; - private final EntityWriteOperations entityWriteOps; - private final SchemaReadOperations schemaReadOps; - private final SchemaWriteOperations schemaWriteOps; - private final Locks.Client locks = mock( Locks.Client.class ); - private final InOrder order; - private final KernelTransactionImplementation transaction = mock( KernelTransactionImplementation.class ); - private final TxState txState = new TxState(); - private final KernelStatement state = new KernelStatement( transaction, new SimpleTxStateHolder( txState ), - mock( StorageStatement.class ), new Procedures(), new CanWrite(), LockTracer.NONE, null, - new ClockContext(), EmptyVersionContextSupplier.EMPTY ); - private final SchemaStateOperations schemaStateOps; - - private final LabelSchemaDescriptor descriptor = SchemaDescriptorFactory.forLabel( 123, 456 ); - - public LockingStatementOperationsTest() - { - when( transaction.getReasonIfTerminated() ).thenReturn( Optional.empty() ); - entityReadOps = mock( EntityReadOperations.class ); - entityWriteOps = mock( EntityWriteOperations.class ); - schemaReadOps = mock( SchemaReadOperations.class ); - schemaWriteOps = mock( SchemaWriteOperations.class ); - schemaStateOps = mock( SchemaStateOperations.class ); - order = inOrder( locks, entityWriteOps, schemaReadOps, schemaWriteOps, schemaStateOps ); - lockingOps = new LockingStatementOperations( - entityReadOps, entityWriteOps, schemaReadOps, schemaWriteOps, schemaStateOps - ); - state.initialize( new SimpleStatementLocks( locks ), PageCursorTracer.NULL ); - state.acquire(); - } - - @Test - public void shouldAcquireEntityWriteLockBeforeAddingLabelToNode() throws Exception - { - // when - lockingOps.nodeAddLabel( state, 123, 456 ); - - // then - order.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, 123 ); - order.verify( entityWriteOps ).nodeAddLabel( state, 123, 456 ); - } - - @Test - public void shouldNotAcquireEntityWriteLockBeforeAddingLabelToJustCreatedNode() throws Exception - { - // when - txState.nodeDoCreate( 123 ); - lockingOps.nodeAddLabel( state, 123, 456 ); - - // then - order.verify( locks, never() ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, 123 ); - order.verify( entityWriteOps ).nodeAddLabel( state, 123, 456 ); - } - - @Test - public void shouldAcquireSchemaReadLockBeforeAddingLabelToNode() throws Exception - { - // when - int labelId = 456; - lockingOps.nodeAddLabel( state, 123, labelId ); - - // then - order.verify( locks ).acquireShared( LockTracer.NONE, ResourceTypes.LABEL, labelId ); - order.verify( entityWriteOps ).nodeAddLabel( state, 123, labelId ); - } - - @Test - public void shouldAcquireEntityWriteLockBeforeSettingPropertyOnNode() throws Exception - { - // given - int propertyKeyId = 8; - Value value = Values.of( 9 ); - - // when - lockingOps.nodeSetProperty( state, 123, propertyKeyId, value ); - - // then - order.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, 123 ); - order.verify( entityWriteOps ).nodeSetProperty( state, 123, propertyKeyId, value ); - } - - @Test - public void shouldNotAcquireEntityWriteLockBeforeSettingPropertyOnJustCreatedNode() throws Exception - { - // given - txState.nodeDoCreate( 123 ); - int propertyKeyId = 8; - Value value = Values.of( 9 ); - - // when - lockingOps.nodeSetProperty( state, 123, propertyKeyId, value ); - - // then - order.verify( locks, never() ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, 123 ); - order.verify( entityWriteOps ).nodeSetProperty( state, 123, propertyKeyId, value ); - } - - @Test - public void shouldAcquireEntityWriteLockBeforeDeletingNode() - throws EntityNotFoundException, AutoIndexingKernelException, InvalidTransactionTypeKernelException - { - // WHEN - lockingOps.nodeDelete( state, 123 ); - - //THEN - order.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, 123 ); - order.verify( entityWriteOps ).nodeDelete( state, 123 ); - } - - @Test - public void shouldNotAcquireEntityWriteLockBeforeDeletingJustCreatedNode() throws Exception - { - // WHEN - txState.nodeDoCreate( 123 ); - lockingOps.nodeDelete( state, 123 ); - - //THEN - order.verify( locks, never() ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, 123 ); - order.verify( entityWriteOps ).nodeDelete( state, 123 ); - } - - @Test - public void shouldAcquireSchemaWriteLockBeforeAddingIndexRule() throws Exception - { - // given - LabelSchemaDescriptor descriptor = SchemaDescriptorFactory.forLabel( 123, 456 ); - SchemaIndexDescriptor index = SchemaIndexDescriptorFactory.forLabel( 123, 456 ); - when( schemaWriteOps.indexCreate( state, descriptor ) ).thenReturn( index ); - - // when - SchemaIndexDescriptor result = lockingOps.indexCreate( state, descriptor ); - - // then - assertSame( index, result ); - order.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.LABEL, descriptor.getLabelId() ); - order.verify( schemaWriteOps ).indexCreate( state, descriptor ); - } - - @Test - public void shouldAcquireSchemaWriteLockBeforeRemovingIndexRule() throws Exception - { - // given - SchemaIndexDescriptor index = SchemaIndexDescriptorFactory.forLabel( 0, 0 ); - - // when - lockingOps.indexDrop( state, index ); - - // then - order.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.LABEL, index.schema().keyId() ); - order.verify( schemaWriteOps ).indexDrop( state, index ); - } - - @Test - public void acquireReadLockBeforeGettingIndexRules() - { - // given - int labelId = 1; - SchemaIndexDescriptor labelDescriptor = SchemaIndexDescriptorFactory.forLabel( labelId, 2, 3 ); - - Iterator rules = Iterators.iterator( labelDescriptor ); - when( schemaReadOps.indexesGetAll( state ) ).thenReturn( rules ); - - // when - Iterator result = lockingOps.indexesGetAll( state ); - Iterators.count( result ); - - // then - order.verify( schemaReadOps ).indexesGetAll( state ); - order.verify( locks ).acquireShared( LockTracer.NONE, ResourceTypes.LABEL, labelId ); - } - - @Test - public void shouldAcquireSchemaWriteLockBeforeCreatingUniquenessConstraint() throws Exception - { - // given - UniquenessConstraintDescriptor constraint = uniqueForSchema( descriptor ); - when( schemaWriteOps.uniquePropertyConstraintCreate( state, descriptor ) ).thenReturn( constraint ); - - // when - UniquenessConstraintDescriptor result = lockingOps.uniquePropertyConstraintCreate( state, descriptor ); - - // then - assertSame( constraint, result ); - order.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.LABEL, descriptor.getLabelId() ); - order.verify( schemaWriteOps ).uniquePropertyConstraintCreate( state, descriptor ); - } - - @Test - public void shouldAcquireSchemaWriteLockBeforeDroppingConstraint() throws Exception - { - // given - UniquenessConstraintDescriptor constraint = uniqueForSchema( descriptor ); - - // when - lockingOps.constraintDrop( state, constraint ); - - // then - order.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.LABEL, descriptor.getLabelId() ); - order.verify( schemaWriteOps ).constraintDrop( state, constraint ); - } - - @Test - public void shouldAcquireSchemaReadLockBeforeGettingConstraintsByLabelAndProperty() - { - // given - when( schemaReadOps.constraintsGetForSchema( state, descriptor ) ).thenReturn( emptyIterator() ); - - // when - Iterator result = lockingOps.constraintsGetForSchema( state, descriptor ); - - // then - assertThat( asList( result ), empty() ); - order.verify( locks ).acquireShared( LockTracer.NONE, ResourceTypes.LABEL, descriptor.getLabelId() ); - order.verify( schemaReadOps ).constraintsGetForSchema( state, descriptor ); - } - - @Test - public void shouldAcquireSchemaReadLockBeforeGettingConstraintsByLabel() - { - // given - int labelId = 123; - when( schemaReadOps.constraintsGetForLabel( state, labelId ) ).thenReturn( emptyIterator() ); - - // when - Iterator result = lockingOps.constraintsGetForLabel( state, labelId ); - - // then - assertThat( asList( result ), empty() ); - order.verify( locks ).acquireShared( LockTracer.NONE, ResourceTypes.LABEL, labelId ); - order.verify( schemaReadOps ).constraintsGetForLabel( state, labelId ); - } - - @Test - public void shouldAcquireSchemaReadLockBeforeGettingAllConstraints() - { - // given - int labelId = 1; - int relTypeId = 2; - UniquenessConstraintDescriptor uniquenessConstraint = uniqueForLabel( labelId, 2, 3, 3 ); - RelExistenceConstraintDescriptor existenceConstraint = existsForRelType( relTypeId, 3, 4, 5 ); - - when( schemaReadOps.constraintsGetAll( state ) ) - .thenReturn( Iterators.iterator( uniquenessConstraint, existenceConstraint ) ); - - // when - Iterator result = lockingOps.constraintsGetAll( state ); - Iterators.count( result ); - - // then - assertThat( asList( result ), empty() ); - order.verify( schemaReadOps ).constraintsGetAll( state ); - order.verify( locks ).acquireShared( LockTracer.NONE, ResourceTypes.LABEL, labelId ); - order.verify( locks ).acquireShared( LockTracer.NONE, ResourceTypes.RELATIONSHIP_TYPE, relTypeId ); - } - - @Test - public void shouldAcquireEntityWriteLockCreatingRelationship() throws Exception - { - // when - lockingOps.relationshipCreate( state, 1, 2, 3 ); - - // then - order.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, 2 ); - order.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, 3 ); - order.verify( entityWriteOps ).relationshipCreate( state, 1, 2, 3 ); - } - - @Test - public void shouldAcquireNodeLocksWhenCreatingRelationshipInOrderOfAscendingId() throws Exception - { - // GIVEN - long lowId = 3; - long highId = 5; - - { - // WHEN - lockingOps.relationshipCreate( state, 0, lowId, highId ); - - // THEN - InOrder lockingOrder = inOrder( locks ); - lockingOrder.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, lowId ); - lockingOrder.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, highId ); - lockingOrder.verifyNoMoreInteractions(); - reset( locks ); - } - - { - // WHEN - lockingOps.relationshipCreate( state, 0, highId, lowId ); - - // THEN - InOrder lockingOrder = inOrder( locks ); - lockingOrder.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, lowId ); - lockingOrder.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, highId ); - lockingOrder.verifyNoMoreInteractions(); - } - } - - @SuppressWarnings( "unchecked" ) - @Test - public void shouldAcquireNodeLocksWhenDeletingRelationshipInOrderOfAscendingId() throws Exception - { - // GIVEN - final long relationshipId = 10; - final long lowId = 3; - final long highId = 5; - - { - // and GIVEN - doAnswer( invocation -> - { - RelationshipVisitor visitor = invocation.getArgument( 2 ); - visitor.visit( relationshipId, 0, lowId, highId ); - return null; - } ).when( entityReadOps ).relationshipVisit( any( KernelStatement.class ), anyLong(), - any( RelationshipVisitor.class ) ); - - // WHEN - lockingOps.relationshipDelete( state, relationshipId ); - - // THEN - InOrder lockingOrder = inOrder( locks ); - lockingOrder.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, lowId ); - lockingOrder.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, highId ); - lockingOrder.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.RELATIONSHIP, relationshipId ); - lockingOrder.verifyNoMoreInteractions(); - reset( locks ); - } - - { - // and GIVEN - doAnswer( invocation -> - { - RelationshipVisitor visitor = invocation.getArgument( 2 ); - visitor.visit( relationshipId, 0, highId, lowId ); - return null; - } ).when( entityReadOps ).relationshipVisit( any( KernelStatement.class ), anyLong(), - any( RelationshipVisitor.class ) ); - - // WHEN - lockingOps.relationshipDelete( state, relationshipId ); - - // THEN - InOrder lockingOrder = inOrder( locks ); - lockingOrder.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, lowId ); - lockingOrder.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, highId ); - lockingOrder.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.RELATIONSHIP, relationshipId ); - lockingOrder.verifyNoMoreInteractions(); - } - } - - @Test - public void shouldAcquireEntityWriteLockBeforeSettingPropertyOnRelationship() throws Exception - { - // given - int propertyKeyId = 8; - Value value = Values.of( 9 ); - - // when - lockingOps.relationshipSetProperty( state, 123, propertyKeyId, value ); - - // then - order.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.RELATIONSHIP, 123 ); - order.verify( entityWriteOps ).relationshipSetProperty( state, 123, propertyKeyId, value ); - } - - @Test - public void shouldNotAcquireEntityWriteLockBeforeSettingPropertyOnJustCreatedRelationship() throws Exception - { - // given - txState.relationshipDoCreate( 123, 1, 2, 3 ); - int propertyKeyId = 8; - Value value = Values.of( 9 ); - - // when - lockingOps.relationshipSetProperty( state, 123, propertyKeyId, value ); - - // then - order.verify( locks, never() ).acquireExclusive( LockTracer.NONE, ResourceTypes.RELATIONSHIP, 123 ); - order.verify( entityWriteOps ).relationshipSetProperty( state, 123, propertyKeyId, value ); - } - - @Test - public void detachDeleteNodeWithoutRelationshipsExclusivelyLockNode() throws KernelException - { - long nodeId = 1L; - returnRelationships( entityReadOps, state, nodeId, false ); - - lockingOps.nodeDetachDelete( state, nodeId ); - - order.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, nodeId ); - order.verify( locks, never() ).releaseExclusive( ResourceTypes.NODE, nodeId ); - order.verify( entityWriteOps ).nodeDetachDelete( state, nodeId ); - } - - @Test - public void detachDeleteNodeExclusivelyLockNodes() throws KernelException - { - long nodeId = 1L; - RelationshipData relationship = new RelationshipData( 1, nodeId, 2L ); - returnRelationships( entityReadOps, state, nodeId, false, relationship ); - - lockingOps.nodeDetachDelete( state, nodeId ); - - order.verify( locks ).acquireExclusive( - LockTracer.NONE, ResourceTypes.NODE, relationship.startNodeId, relationship.endNodeId ); - order.verify( locks, never() ).releaseExclusive( ResourceTypes.NODE, relationship.startNodeId ); - order.verify( locks, never() ).releaseExclusive( ResourceTypes.NODE, relationship.endNodeId ); - order.verify( entityWriteOps ).nodeDetachDelete( state, nodeId ); - } - - private static class SimpleTxStateHolder implements TxStateHolder - { - private final TxState txState; - - private SimpleTxStateHolder( TxState txState ) - { - this.txState = txState; - } - - @Override - public TransactionState txState() - { - return txState; - } - - @Override - public ExplicitIndexTransactionState explicitIndexTxState() - { - return null; - } - - @Override - public boolean hasTxStateWithChanges() - { - return txState.hasChanges(); - } - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/OperationsFacadeTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/OperationsFacadeTest.java deleted file mode 100644 index 1712603f81f1e..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/OperationsFacadeTest.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import org.neo4j.graphdb.Label; -import org.neo4j.graphdb.Transaction; -import org.neo4j.internal.kernel.api.schema.LabelSchemaDescriptor; -import org.neo4j.kernel.api.ReadOperations; -import org.neo4j.kernel.api.Statement; -import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; -import org.neo4j.kernel.api.exceptions.schema.SchemaRuleNotFoundException; -import org.neo4j.kernel.api.index.IndexProvider; -import org.neo4j.kernel.api.schema.SchemaDescriptorFactory; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptorFactory; -import org.neo4j.test.rule.DatabaseRule; -import org.neo4j.test.rule.ImpermanentDatabaseRule; - -import static org.hamcrest.CoreMatchers.allOf; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; - -public class OperationsFacadeTest -{ - @Rule - public DatabaseRule db = new ImpermanentDatabaseRule(); - - private final Label LABEL1 = Label.label( "Label1" ); - private final String PROP1 = "Prop1"; - private int labelId; - private int propertyId; - - @Before - public void setup() - { - try ( Transaction tx = db.beginTx() ) - { - db.createNode( LABEL1 ).setProperty( PROP1, 1 ); - tx.success(); - } - - try ( Transaction tx = db.beginTx(); - Statement statement = db.statement() ) - { - ReadOperations readOperations = statement.readOperations(); - labelId = readOperations.labelGetForName( LABEL1.name() ); - propertyId = readOperations.propertyKeyGetForName( PROP1 ); - tx.success(); - } - } - - @Test - public void testThrowExceptionWhenIndexNotFound() - { - try ( Transaction ignored = db.beginTx(); - Statement statement = db.statement() ) - { - ReadOperations readOperations = statement.readOperations(); - try - { - LabelSchemaDescriptor descriptor = SchemaDescriptorFactory.forLabel( 1, 2 ); - readOperations.indexGetForSchema( descriptor ); - fail( "Should have failed" ); - } - catch ( SchemaRuleNotFoundException e ) - { - assertThat( e.getMessage(), containsString( "No index was found for :label[1](property[2])" ) ); - } - } - } - - @Test - public void indexGetProviderDescriptorMustReturnUndecidedIfIndexCreatedInTransaction() throws Exception - { - try ( Transaction tx = db.beginTx(); - Statement statement = db.statement() ) - { - db.schema().indexFor( LABEL1 ).on( PROP1 ).create(); - ReadOperations readOperations = statement.readOperations(); - SchemaIndexDescriptor schemaIndexDescriptor = SchemaIndexDescriptorFactory.forLabel( labelId, propertyId ); - IndexProvider.Descriptor providerDescriptor = readOperations.indexGetProviderDescriptor( - schemaIndexDescriptor ); - assertThat( providerDescriptor, is( IndexProvider.UNDECIDED ) ); - tx.success(); - } - } - - @Test - public void indexGetProviderDescriptorMustThrowIfIndexDoesNotExist() - { - try ( Transaction tx = db.beginTx(); - Statement statement = db.statement() ) - { - ReadOperations readOperations = statement.readOperations(); - SchemaIndexDescriptor schemaIndexDescriptor = SchemaIndexDescriptorFactory.forLabel( labelId, propertyId ); - - try - { - readOperations.indexGetProviderDescriptor( schemaIndexDescriptor ); - fail( "Should have failed" ); - } - catch ( IndexNotFoundKernelException e ) - { - // good - assertThat( e.getMessage(), allOf( - containsString( "No index" ), - containsString( ":label[" + labelId + "](property[" + propertyId + "])" ) ) ); - } - tx.success(); - } - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/StatementLifecycleTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/StatementLifecycleTest.java index edcc46aa1b3db..6763b29e1c373 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/StatementLifecycleTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/StatementLifecycleTest.java @@ -22,9 +22,7 @@ import org.junit.Test; import org.neo4j.io.pagecache.tracing.cursor.context.EmptyVersionContextSupplier; -import org.neo4j.kernel.impl.factory.CanWrite; import org.neo4j.kernel.impl.locking.LockTracer; -import org.neo4j.kernel.impl.proc.Procedures; import org.neo4j.storageengine.api.StorageStatement; import static org.mockito.Mockito.mock; @@ -79,7 +77,7 @@ public void shouldReleaseStoreStatementWhenForceClosingStatements() private KernelStatement getKernelStatement( KernelTransactionImplementation transaction, StorageStatement storageStatement ) { - return new KernelStatement( transaction, null, storageStatement, new Procedures(), new CanWrite(), + return new KernelStatement( transaction, null, storageStatement, LockTracer.NONE, mock( StatementOperationParts.class ), new ClockContext(), EmptyVersionContextSupplier.EMPTY ); } } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/StatementOperationsTestHelper.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/StatementOperationsTestHelper.java index fa31bcf0d6fff..7278194334e0c 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/StatementOperationsTestHelper.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/StatementOperationsTestHelper.java @@ -19,80 +19,16 @@ */ package org.neo4j.kernel.impl.api; -import org.neo4j.internal.kernel.api.IndexQuery; -import org.neo4j.kernel.api.ReadOperations; -import org.neo4j.kernel.api.exceptions.index.IndexNotApplicableKernelException; -import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; -import org.neo4j.kernel.api.txstate.TransactionState; -import org.neo4j.kernel.impl.api.operations.CountsOperations; -import org.neo4j.kernel.impl.api.operations.EntityReadOperations; -import org.neo4j.kernel.impl.api.operations.EntityWriteOperations; -import org.neo4j.kernel.impl.api.operations.ExplicitIndexReadOperations; -import org.neo4j.kernel.impl.api.operations.ExplicitIndexWriteOperations; -import org.neo4j.kernel.impl.api.operations.KeyReadOperations; -import org.neo4j.kernel.impl.api.operations.KeyWriteOperations; -import org.neo4j.kernel.impl.api.operations.LockOperations; import org.neo4j.kernel.impl.api.operations.QueryRegistrationOperations; -import org.neo4j.kernel.impl.api.operations.SchemaReadOperations; -import org.neo4j.kernel.impl.api.operations.SchemaStateOperations; -import org.neo4j.kernel.impl.api.operations.SchemaWriteOperations; -import org.neo4j.kernel.impl.locking.Locks; -import org.neo4j.kernel.impl.locking.SimpleStatementLocks; -import org.neo4j.storageengine.api.StorageStatement; -import org.neo4j.storageengine.api.schema.IndexReader; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.neo4j.collection.primitive.PrimitiveLongResourceCollections.emptyIterator; public abstract class StatementOperationsTestHelper { public static StatementOperationParts mockedParts() { return new StatementOperationParts( - mock( KeyReadOperations.class ), - mock( KeyWriteOperations.class ), - mock( EntityReadOperations.class ), - mock( EntityWriteOperations.class ), - mock( SchemaReadOperations.class ), - mock( SchemaWriteOperations.class ), - mock( SchemaStateOperations.class ), - mock( LockOperations.class ), - mock( CountsOperations.class ), - mock( ExplicitIndexReadOperations.class ), - mock( ExplicitIndexWriteOperations.class ), - mock( QueryRegistrationOperations.class ) ); - } - - public static KernelStatement mockedState() - { - return mockedState( mock( TransactionState.class ) ); - } - - public static KernelStatement mockedState( final TransactionState txState ) - { - KernelStatement state = mock( KernelStatement.class ); - Locks.Client locks = mock( Locks.Client.class ); - try - { - IndexReader indexReader = mock( IndexReader.class ); - when( indexReader.query( isA( IndexQuery.ExactPredicate.class ) ) ) - .thenReturn( emptyIterator() ); - StorageStatement storageStatement = mock( StorageStatement.class ); - when( storageStatement.getIndexReader( any() ) ).thenReturn( indexReader ); - when( state.getStoreStatement() ).thenReturn( storageStatement ); - } - catch ( IndexNotFoundKernelException | IndexNotApplicableKernelException e ) - { - throw new Error( e ); - } - when( state.txState() ).thenReturn( txState ); - when( state.hasTxStateWithChanges() ).thenAnswer( invocation -> txState.hasChanges() ); - when( state.locks() ).thenReturn( new SimpleStatementLocks( locks ) ); - when( state.readOperations() ).thenReturn( mock( ReadOperations.class ) ); - return state; + mock( QueryRegistrationOperations.class ) ); } private StatementOperationsTestHelper() diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/TwoPhaseNodeForRelationshipLockingTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/TwoPhaseNodeForRelationshipLockingTest.java deleted file mode 100644 index 3b0ea1d404ff6..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/TwoPhaseNodeForRelationshipLockingTest.java +++ /dev/null @@ -1,255 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api; - -import org.junit.Test; -import org.mockito.InOrder; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -import java.util.HashSet; -import java.util.NoSuchElementException; -import java.util.Set; - -import org.neo4j.cursor.Cursor; -import org.neo4j.function.ThrowingConsumer; -import org.neo4j.internal.kernel.api.exceptions.EntityNotFoundException; -import org.neo4j.internal.kernel.api.exceptions.KernelException; -import org.neo4j.kernel.impl.api.operations.EntityReadOperations; -import org.neo4j.kernel.impl.locking.LockTracer; -import org.neo4j.kernel.impl.locking.Locks; -import org.neo4j.kernel.impl.locking.ResourceTypes; -import org.neo4j.kernel.impl.locking.SimpleStatementLocks; -import org.neo4j.storageengine.api.Direction; -import org.neo4j.storageengine.api.EntityType; -import org.neo4j.storageengine.api.NodeItem; -import org.neo4j.storageengine.api.RelationshipItem; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; -import static org.neo4j.helpers.collection.Iterators.set; - -public class TwoPhaseNodeForRelationshipLockingTest -{ - private final EntityReadOperations ops = mock( EntityReadOperations.class ); - private final KernelStatement state = mock( KernelStatement.class ); - private final Locks.Client locks = mock( Locks.Client.class ); - private final long nodeId = 42L; - - { - when( state.locks() ).thenReturn( new SimpleStatementLocks( locks ) ); - when( state.lockTracer() ).thenReturn( LockTracer.NONE ); - } - - @Test - public void shouldLockNodesInOrderAndConsumeTheRelationships() throws Throwable - { - // given - Collector collector = new Collector(); - TwoPhaseNodeForRelationshipLocking locking = new TwoPhaseNodeForRelationshipLocking( ops, collector ); - - returnRelationships( - ops, state, nodeId, false, - new RelationshipData( 21L, nodeId, 43L ), - new RelationshipData( 22L, 40L, nodeId ), - new RelationshipData( 23L, nodeId, 41L ), - new RelationshipData( 2L, nodeId, 3L ), - new RelationshipData( 3L, 49L, nodeId ), - new RelationshipData( 50L, nodeId, 41L ) ); - - InOrder inOrder = inOrder( locks ); - - // when - locking.lockAllNodesAndConsumeRelationships( nodeId, state ); - - // then - inOrder.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, 3L, 40L, 41L, nodeId, 43L, 49L ); - assertEquals( set( 21L, 22L, 23L, 2L, 3L, 50L ), collector.set ); - } - - @Test - public void shouldLockNodesInOrderAndConsumeTheRelationshipsAndRetryIfTheNewRelationshipsAreCreated() - throws Throwable - { - // given - Collector collector = new Collector(); - TwoPhaseNodeForRelationshipLocking locking = new TwoPhaseNodeForRelationshipLocking( ops, collector ); - - RelationshipData relationship1 = new RelationshipData( 21L, nodeId, 43L ); - RelationshipData relationship2 = new RelationshipData( 22L, 40L, nodeId ); - RelationshipData relationship3 = new RelationshipData( 23L, nodeId, 41L ); - returnRelationships( ops, state, nodeId, true, relationship1, relationship2, relationship3 ); - - InOrder inOrder = inOrder( locks ); - - // when - locking.lockAllNodesAndConsumeRelationships( nodeId, state ); - - // then - inOrder.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, 40L, 41L, nodeId ); - - inOrder.verify( locks ).releaseExclusive( ResourceTypes.NODE, 40L ); - inOrder.verify( locks ).releaseExclusive( ResourceTypes.NODE, 41L ); - inOrder.verify( locks ).releaseExclusive( ResourceTypes.NODE, nodeId ); - - inOrder.verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, 40L, 41L, nodeId, 43L ); - assertEquals( set( 21L, 22L, 23L ), collector.set ); - } - - @Test - public void lockNodeWithoutRelationships() throws Exception - { - Collector collector = new Collector(); - TwoPhaseNodeForRelationshipLocking locking = new TwoPhaseNodeForRelationshipLocking( ops, collector ); - returnRelationships( ops, state, nodeId, false ); - - locking.lockAllNodesAndConsumeRelationships( nodeId, state ); - - verify( locks ).acquireExclusive( LockTracer.NONE, ResourceTypes.NODE, nodeId ); - verifyNoMoreInteractions( locks ); - } - - public static class RelationshipData - { - public final long relId; - public final long startNodeId; - public final long endNodeId; - - RelationshipData( long relId, long startNodeId, long endNodeId ) - { - this.relId = relId; - this.startNodeId = startNodeId; - this.endNodeId = endNodeId; - } - - RelationshipItem asRelationshipItem() - { - RelationshipItem rel = mock( RelationshipItem.class ); - when( rel.id() ).thenReturn( relId ); - when( rel.startNode() ).thenReturn( startNodeId ); - when( rel.endNode() ).thenReturn( endNodeId ); - return rel; - } - } - - static void returnRelationships( EntityReadOperations ops, KernelStatement state, long nodeId, - final boolean skipFirst, final RelationshipData... relIds ) throws EntityNotFoundException - { - NodeItem nodeItem = mock( NodeItem.class ); - when( ops.nodeGetRelationships( state, nodeItem, Direction.BOTH ) ) - .thenAnswer( new Answer>() - { - private boolean first = skipFirst; - - @Override - public Cursor answer( InvocationOnMock invocation ) - { - try - { - return new Cursor() - { - private int i = first ? 1 : 0; - private RelationshipData relationshipData; - - @Override - public boolean next() - { - boolean next = i < relIds.length; - relationshipData = next ? relIds[i++] : null; - return next; - } - - @Override - public RelationshipItem get() - { - if ( relationshipData == null ) - { - throw new NoSuchElementException(); - } - - return relationshipData.asRelationshipItem(); - } - - @Override - public void close() - { - } - }; - } - finally - { - first = false; - } - } - } ); - - when( ops.nodeCursorById( state, nodeId ) ).thenAnswer( invocationOnMock -> - { - Cursor cursor = new Cursor() - { - private int i; - - @Override - public boolean next() - { - return i++ == 0; - } - - @Override - public NodeItem get() - { - if ( i != 1 ) - { - throw new NoSuchElementException(); - } - return nodeItem; - } - - @Override - public void close() - { - - } - }; - if ( !cursor.next() ) - { - throw new EntityNotFoundException( EntityType.NODE, nodeId ); - } - return cursor; - } ); - } - - private static class Collector implements ThrowingConsumer - { - public final Set set = new HashSet<>(); - - @Override - public void accept( Long input ) - { - assertNotNull( input ); - set.add( input ); - } - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/constraints/ConstraintIndexCreatorTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/constraints/ConstraintIndexCreatorTest.java index ef47f47c05cb1..96cc687c3d503 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/constraints/ConstraintIndexCreatorTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/constraints/ConstraintIndexCreatorTest.java @@ -108,7 +108,6 @@ public void shouldCreateIndexInAnotherTransaction() throws Exception // then assertEquals( INDEX_ID, indexId ); - verifyNoMoreInteractions( indexCreationContext.schemaWriteOperations() ); verify( schemaRead ).indexGetCommittedId( indexReference ); verify( schemaRead ).index( LABEL_ID, PROPERTY_KEY_ID ); verifyNoMoreInteractions( schemaRead ); @@ -288,7 +287,6 @@ public void shouldFailOnExistingOwnedConstraintIndex() throws Exception // then assertEquals( "There should have been no need to acquire a statement to create the constraint index", 0, kernel.transactions.size() ); - verifyNoMoreInteractions( indexCreationContext.schemaWriteOperations() ); verify( schemaRead ).index( LABEL_ID, PROPERTY_KEY_ID ); verify( schemaRead ).indexGetOwningUniquenessConstraintId( indexReference ); verifyNoMoreInteractions( schemaRead ); diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/operations/ConstraintEnforcingEntityOperationsTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/operations/ConstraintEnforcingEntityOperationsTest.java deleted file mode 100644 index 5bdef8ce037c7..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/operations/ConstraintEnforcingEntityOperationsTest.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.operations; - -import org.junit.Before; -import org.junit.Test; - -import org.neo4j.collection.primitive.PrimitiveIntCollections; -import org.neo4j.cursor.Cursor; -import org.neo4j.internal.kernel.api.IndexQuery; -import org.neo4j.internal.kernel.api.InternalIndexState; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptorFactory; -import org.neo4j.kernel.impl.api.ConstraintEnforcingEntityOperations; -import org.neo4j.kernel.impl.api.KernelStatement; -import org.neo4j.kernel.impl.api.state.StubCursors; -import org.neo4j.kernel.impl.constraints.StandardConstraintSemantics; -import org.neo4j.kernel.impl.locking.LockTracer; -import org.neo4j.kernel.impl.locking.Locks; -import org.neo4j.kernel.impl.locking.ResourceTypes; -import org.neo4j.kernel.impl.locking.SimpleStatementLocks; -import org.neo4j.storageengine.api.NodeItem; -import org.neo4j.values.storable.Value; -import org.neo4j.values.storable.Values; - -import static java.util.Collections.emptyIterator; -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; -import static org.neo4j.internal.kernel.api.IndexQuery.exact; -import static org.neo4j.kernel.api.StatementConstants.NO_SUCH_NODE; -import static org.neo4j.kernel.impl.locking.ResourceTypes.INDEX_ENTRY; -import static org.neo4j.kernel.impl.locking.ResourceTypes.indexEntryResourceId; - -public class ConstraintEnforcingEntityOperationsTest -{ - private final int labelId = 1; - private final int propertyKeyId = 2; - private final Value value = Values.of( "value" ); - private final long resourceId = indexEntryResourceId( labelId, exact( propertyKeyId, value ) ); - private final SchemaIndexDescriptor index = SchemaIndexDescriptorFactory.uniqueForLabel( labelId, propertyKeyId ); - private final IndexQuery.ExactPredicate withValue = IndexQuery.exact( propertyKeyId, value ); - private EntityReadOperations readOps; - private KernelStatement state; - private Locks.Client locks; - private ConstraintEnforcingEntityOperations ops; - private SchemaReadOperations schemaReadOps; - private EntityWriteOperations entityWriteOperations; - - @Before - public void given_ConstraintEnforcingEntityOperations_with_OnlineIndex() throws Exception - { - this.readOps = mock( EntityReadOperations.class ); - schemaReadOps = mock( SchemaReadOperations.class ); - entityWriteOperations = mock( EntityWriteOperations.class ); - SchemaWriteOperations schemaWriteOps = mock( SchemaWriteOperations.class ); - this.state = mock( KernelStatement.class ); - when( schemaReadOps.indexGetState( state, index ) ).thenReturn( InternalIndexState.ONLINE ); - this.locks = mock( Locks.Client.class ); - when( state.locks() ).thenReturn( new SimpleStatementLocks( locks ) ); - when( state.lockTracer() ).thenReturn( LockTracer.NONE ); - - this.ops = new ConstraintEnforcingEntityOperations( new StandardConstraintSemantics(), entityWriteOperations, readOps, - schemaWriteOps, schemaReadOps ); - } - - @Test - public void shouldHoldIndexReadLockIfNodeIsExists() throws Exception - { - // given - long expectedNodeId = 15; - when( readOps.nodeGetFromUniqueIndexSeek( state, index, withValue ) ).thenReturn( expectedNodeId ); - - // when - long nodeId = ops.nodeGetFromUniqueIndexSeek( state, index, withValue ); - - // then - assertEquals( expectedNodeId, nodeId ); - verify( locks).acquireShared( - LockTracer.NONE, - INDEX_ENTRY, resourceId ); - verifyNoMoreInteractions( locks ); - } - - @Test - public void acquireAllLabelsSharedLocksBeforeSettingPropertyOnNode() throws Exception - { - Cursor nodeCursor = - StubCursors.asNodeCursor( 123, PrimitiveIntCollections.asSet( new int[]{1, 5, 7} ) ); - nodeCursor.next(); - when( readOps.nodeCursorById( state, 123 ) ).thenReturn( nodeCursor ); - when( schemaReadOps.constraintsGetAll( state ) ).thenReturn( emptyIterator() ); - int propertyKeyId = 8; - Value value = Values.of( 9 ); - - ops.nodeSetProperty( state, 123, propertyKeyId, value ); - - verify( locks ).acquireShared( LockTracer.NONE, ResourceTypes.LABEL, 1, 5, 7 ); - verify( entityWriteOperations ).nodeSetProperty( state, 123, propertyKeyId, value ); - } - - @Test - public void shouldHoldIndexWriteLockIfNodeDoesNotExist() throws Exception - { - // given - when( readOps.nodeGetFromUniqueIndexSeek( state, index, withValue ) ).thenReturn( NO_SUCH_NODE ); - - // when - long nodeId = ops.nodeGetFromUniqueIndexSeek( state, index, withValue ); - - // then - assertEquals( NO_SUCH_NODE, nodeId ); - verify( locks ).acquireShared( - LockTracer.NONE, - INDEX_ENTRY, resourceId ); - verify( locks ).acquireExclusive( - LockTracer.NONE, - INDEX_ENTRY, resourceId ); - verify( locks ).releaseShared( INDEX_ENTRY, resourceId ); - verifyNoMoreInteractions( locks ); - } - - @Test - public void shouldHoldIndexReadLockIfNodeIsConcurrentlyCreated() throws Exception - { - // given - long expectedNodeId = 15; - when( readOps.nodeGetFromUniqueIndexSeek( state, index, withValue ) ) - .thenReturn( NO_SUCH_NODE ) - .thenReturn( expectedNodeId ); - - // when - long nodeId = ops.nodeGetFromUniqueIndexSeek( state, index, withValue ); - - // then - assertEquals( expectedNodeId, nodeId ); - verify( locks, times(2) ).acquireShared( - LockTracer.NONE, - INDEX_ENTRY, resourceId ); - verify( locks ).acquireExclusive( - LockTracer.NONE, - INDEX_ENTRY, resourceId ); - verify( locks ).releaseShared( INDEX_ENTRY, resourceId ); - verify( locks ).releaseExclusive( INDEX_ENTRY, resourceId ); - verifyNoMoreInteractions( locks ); - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/schema/NodeSchemaMatcherTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/schema/NodeSchemaMatcherTest.java deleted file mode 100644 index 0264787be496f..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/schema/NodeSchemaMatcherTest.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.schema; - -import org.junit.Before; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.neo4j.collection.primitive.Primitive; -import org.neo4j.collection.primitive.PrimitiveIntCollections; -import org.neo4j.collection.primitive.PrimitiveIntSet; -import org.neo4j.cursor.Cursor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.impl.api.KernelStatement; -import org.neo4j.kernel.impl.api.operations.EntityReadOperations; -import org.neo4j.kernel.impl.api.state.StubCursors; -import org.neo4j.storageengine.api.NodeItem; -import org.neo4j.values.storable.Values; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.equalTo; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.neo4j.helpers.collection.Iterators.iterator; -import static org.neo4j.kernel.api.schema.index.SchemaIndexDescriptorFactory.forLabel; - -public class NodeSchemaMatcherTest -{ - - private static final int labelId1 = 10; - private static final int labelId2 = 11; - private static final int nonExistentLabelId = 12; - private static final int propId1 = 20; - private static final int propId2 = 21; - private static final int unIndexedPropId = 22; - private static final int nonExistentPropId = 23; - private static final int specialPropId = 24; - - KernelStatement state; - NodeItem node; - - SchemaIndexDescriptor index1 = forLabel( labelId1, propId1 ); - SchemaIndexDescriptor index1_2 = forLabel( labelId1, propId1, propId2 ); - SchemaIndexDescriptor indexWithMissingProperty = forLabel( labelId1, propId1, nonExistentPropId ); - SchemaIndexDescriptor indexWithMissingLabel = forLabel( nonExistentLabelId, propId1, propId2 ); - SchemaIndexDescriptor indexOnSpecialProperty = forLabel( labelId1, propId1, specialPropId ); - - private NodeSchemaMatcher nodeSchemaMatcher; - - @Before - public void setup() - { - state = mock( KernelStatement.class ); - - PrimitiveIntSet labels = Primitive.intSet(); - labels.add( labelId1 ); - - Cursor nodeItemCursor = StubCursors.asNodeCursor( 0, labels ); - nodeItemCursor.next(); - node = nodeItemCursor.get(); - - PrimitiveIntSet defaultPropertyIds = PrimitiveIntCollections.asSet( new int[]{ propId1, propId2, - unIndexedPropId} ); - EntityReadOperations readOps = mock( EntityReadOperations.class ); - when( readOps.nodeGetPropertyKeys( state, node ) ).thenReturn( defaultPropertyIds ); - when( readOps.nodeGetProperty( state, node, propId1 ) ).thenReturn( Values.of( "hi1" ) ); - when( readOps.nodeGetProperty( state, node, propId2 ) ).thenReturn( Values.of( "hi2" ) ); - when( readOps.nodeGetProperty( state, node, unIndexedPropId ) ).thenReturn( Values.of( "hi3" ) ); - - nodeSchemaMatcher = new NodeSchemaMatcher( readOps ); - } - - @Test - public void shouldMatchOnSingleProperty() - { - // when - final List matched = new ArrayList<>(); - nodeSchemaMatcher.onMatchingSchema( - state, iterator( index1 ), node, unIndexedPropId, ( schema, props ) -> matched.add( schema ) ); - - // then - assertThat( matched, contains( index1 ) ); - } - - @Test - public void shouldMatchOnTwoProperties() - { - // when - final List matched = new ArrayList<>(); - nodeSchemaMatcher.onMatchingSchema( - state, iterator( index1_2 ), node, unIndexedPropId, ( schema, props ) -> matched.add( schema ) ); - - // then - assertThat( matched, contains( index1_2 ) ); - } - - @Test - public void shouldNotMatchIfNodeIsMissingProperty() - { - // when - final List matched = new ArrayList<>(); - nodeSchemaMatcher.onMatchingSchema( state, iterator( indexWithMissingProperty ), node, unIndexedPropId, - ( schema, props ) -> matched.add( schema ) ); - - // then - assertThat( matched, empty() ); - } - - @Test - public void shouldNotMatchIfNodeIsMissingLabel() - { - // when - final List matched = new ArrayList<>(); - nodeSchemaMatcher.onMatchingSchema( state, iterator( indexWithMissingLabel ), node, unIndexedPropId, - ( schema, props ) -> matched.add( schema ) ); - - // then - assertThat( matched, empty() ); - } - - @Test - public void shouldMatchOnSpecialProperty() - { - // when - final List matched = new ArrayList<>(); - nodeSchemaMatcher.onMatchingSchema( state, iterator( indexOnSpecialProperty ), node, specialPropId, - ( schema, props ) -> matched.add( schema ) ); - - // then - assertThat( matched, contains( indexOnSpecialProperty ) ); - } - - @Test - public void shouldMatchSeveralTimes() - { - // given - List indexes = Arrays.asList( index1, index1, index1_2, index1_2 ); - - // when - final List matched = new ArrayList<>(); - nodeSchemaMatcher.onMatchingSchema( - state, indexes.iterator(), node, unIndexedPropId, ( schema, props ) -> matched.add( schema ) ); - - // then - assertThat( matched, equalTo( indexes ) ); - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/IndexQueryTransactionStateTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/IndexQueryTransactionStateTest.java deleted file mode 100644 index 866d5330522b3..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/IndexQueryTransactionStateTest.java +++ /dev/null @@ -1,370 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.state; - -import org.junit.Before; -import org.junit.Test; - -import java.util.Collections; -import java.util.List; - -import org.neo4j.collection.primitive.PrimitiveLongCollections; -import org.neo4j.collection.primitive.PrimitiveLongIterator; -import org.neo4j.collection.primitive.PrimitiveLongResourceIterator; -import org.neo4j.graphdb.Resource; -import org.neo4j.internal.kernel.api.IndexQuery; -import org.neo4j.internal.kernel.api.InternalIndexState; -import org.neo4j.internal.kernel.api.schema.SchemaDescriptor; -import org.neo4j.kernel.api.AssertOpen; -import org.neo4j.kernel.api.properties.PropertyKeyValue; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptorFactory; -import org.neo4j.kernel.api.txstate.TransactionState; -import org.neo4j.kernel.configuration.Config; -import org.neo4j.kernel.impl.api.ConstraintEnforcingEntityOperations; -import org.neo4j.kernel.impl.api.KernelStatement; -import org.neo4j.kernel.impl.api.StateHandlingStatementOperations; -import org.neo4j.kernel.impl.api.StatementOperationsTestHelper; -import org.neo4j.kernel.impl.api.explicitindex.InternalAutoIndexing; -import org.neo4j.kernel.impl.api.index.IndexProxy; -import org.neo4j.kernel.impl.api.index.IndexingService; -import org.neo4j.kernel.impl.api.operations.EntityOperations; -import org.neo4j.kernel.impl.constraints.StandardConstraintSemantics; -import org.neo4j.kernel.impl.index.ExplicitIndexStore; -import org.neo4j.kernel.impl.storageengine.impl.recordstorage.StoreStatement; -import org.neo4j.storageengine.api.NodeItem; -import org.neo4j.storageengine.api.StoreReadLayer; -import org.neo4j.storageengine.api.schema.IndexReader; -import org.neo4j.values.storable.Value; -import org.neo4j.values.storable.Values; - -import static java.util.Arrays.asList; -import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.neo4j.helpers.collection.Iterators.asSet; -import static org.neo4j.kernel.api.StatementConstants.NO_SUCH_NODE; -import static org.neo4j.kernel.impl.api.state.StubCursors.asNodeCursor; -import static org.neo4j.kernel.impl.api.state.StubCursors.asPropertyCursor; -import static org.neo4j.kernel.impl.api.state.StubCursors.labels; -import static org.neo4j.test.mockito.answer.Neo4jMockitoAnswers.answerAsIteratorFrom; -import static org.neo4j.test.mockito.answer.Neo4jMockitoAnswers.answerAsPrimitiveLongIteratorFrom; - -public class IndexQueryTransactionStateTest -{ - private int labelId = 2; - private int propertyKeyId = 3; - private Value value = Values.of( "My Value" ); - private SchemaIndexDescriptor schemaIndexDescriptor = SchemaIndexDescriptorFactory.forLabel( labelId, propertyKeyId ); - private List indexes = Collections.singletonList( schemaIndexDescriptor ); - private IndexQuery.ExactPredicate withValue = IndexQuery.exact( propertyKeyId, value ); - - private StoreReadLayer store; - private StoreStatement statement; - private EntityOperations txContext; - private KernelStatement state; - private IndexReader indexReader; - - @Before - public void before() throws Exception - { - TransactionState txState = new TxState(); - state = StatementOperationsTestHelper.mockedState( txState ); - - store = mock( StoreReadLayer.class ); - when( store.indexGetState( schemaIndexDescriptor ) ).thenReturn( InternalIndexState.ONLINE ); - when( store.indexesGetForLabel( labelId ) ).then( answerAsIteratorFrom( indexes ) ); - when( store.indexesGetAll() ).then( answerAsIteratorFrom( indexes ) ); - when( store.indexesGetRelatedToProperty( propertyKeyId ) ).then( answerAsIteratorFrom( indexes ) ); - when( store.constraintsGetForLabel( labelId ) ).thenReturn( Collections.emptyIterator() ); - when( store.indexGetForSchema( schemaIndexDescriptor.schema() ) ).thenReturn( schemaIndexDescriptor ); - - statement = mock( StoreStatement.class ); - when( state.getStoreStatement() ).thenReturn( statement ); - indexReader = mock( IndexReader.class ); - when( statement.getIndexReader( schemaIndexDescriptor ) ).thenReturn( indexReader ); - when( statement.getFreshIndexReader( schemaIndexDescriptor ) ).thenReturn( indexReader ); - - IndexingService indexingService = mock( IndexingService.class ); - when( indexingService.getIndexProxy( any( SchemaDescriptor.class ) ) ).thenReturn( mock( IndexProxy.class ) ); - - StateHandlingStatementOperations stateHandlingOperations = new StateHandlingStatementOperations( - store, - new InternalAutoIndexing( Config.defaults(), null ), - mock( ConstraintIndexCreator.class ), - mock( ExplicitIndexStore.class ), - indexingService ); - txContext = new ConstraintEnforcingEntityOperations( new StandardConstraintSemantics(), stateHandlingOperations, - stateHandlingOperations, stateHandlingOperations, stateHandlingOperations ); - } - - @Test - public void shouldExcludeRemovedNodesFromIndexQuery() throws Exception - { - // Given - long nodeId = 2L; - when( indexReader.query( withValue ) ).then( answerAsPrimitiveLongIteratorFrom( asList( 1L, nodeId, 3L ) ) ); - - when( statement.acquireSingleNodeCursor( nodeId ) ).thenReturn( asNodeCursor( nodeId ) ); - - txContext.nodeDelete( state, nodeId ); - - // When - PrimitiveLongIterator result = txContext.indexQuery( state, schemaIndexDescriptor, withValue ); - - // Then - assertThat( PrimitiveLongCollections.toSet( result ), equalTo( asSet( 1L, 3L ) ) ); - } - - @Test - public void shouldExcludeRemovedNodeFromUniqueIndexQuery() throws Exception - { - // Given - long nodeId = 1L; - when( indexReader.query( withValue ) ).thenReturn( asPrimitiveResourceIterator( nodeId ) ); - - when( statement.acquireSingleNodeCursor( nodeId ) ).thenReturn( asNodeCursor( nodeId ) ); - - txContext.nodeDelete( state, nodeId ); - - // When - long result = txContext.nodeGetFromUniqueIndexSeek( state, schemaIndexDescriptor, withValue ); - - // Then - assertNoSuchNode( result ); - } - - @Test - public void shouldExcludeChangedNodesWithMissingLabelFromIndexQuery() throws Exception - { - // Given - when( indexReader.query( withValue ) ).then( answerAsPrimitiveLongIteratorFrom( asList( 2L, 3L ) ) ); - - state.txState().nodeDoAddProperty( 1L, propertyKeyId, Values.of( 10 ) ); - - // When - PrimitiveLongIterator result = txContext.indexQuery( state, schemaIndexDescriptor, withValue ); - - // Then - assertThat( PrimitiveLongCollections.toSet( result ), equalTo( asSet( 2L, 3L ) ) ); - } - - @Test - public void shouldExcludeChangedNodeWithMissingLabelFromUniqueIndexQuery() throws Exception - { - // Given - when( indexReader.query( withValue ) ).thenReturn( asPrimitiveResourceIterator() ); - state.txState().nodeDoAddProperty( 1L, propertyKeyId, Values.of( 10 ) ); - - // When - long result = txContext.nodeGetFromUniqueIndexSeek( state, schemaIndexDescriptor, withValue ); - - // Then - assertNoSuchNode( result ); - } - - @Test - public void shouldIncludeCreatedNodesWithCorrectLabelAndProperty() throws Exception - { - // Given - when( indexReader.query( withValue ) ).then( answerAsPrimitiveLongIteratorFrom( asList( 2L, 3L ) ) ); - - long nodeId = 1L; - state.txState().nodeDoAddProperty( nodeId, propertyKeyId, value ); - when( statement.acquireSingleNodeCursor( nodeId ) ).thenReturn( asNodeCursor( nodeId, 40L ) ); - mockStoreProperty(); - - when( store.indexesGetForLabel( labelId ) ).thenReturn( indexes.iterator() ); - txContext.nodeAddLabel( state, nodeId, labelId ); - - // When - PrimitiveLongIterator result = txContext.indexQuery( state, schemaIndexDescriptor, withValue ); - - // Then - assertThat( PrimitiveLongCollections.toSet( result ), equalTo( asSet( nodeId, 2L, 3L ) ) ); - } - - @Test - public void shouldIncludeUniqueCreatedNodeWithCorrectLabelAndProperty() throws Exception - { - // Given - when( indexReader.query( withValue ) ).thenReturn( asPrimitiveResourceIterator() ); - - long nodeId = 1L; - state.txState().nodeDoAddProperty( nodeId, propertyKeyId, value ); - - when( statement.acquireSingleNodeCursor( nodeId ) ).thenReturn( asNodeCursor( nodeId, 40L ) ); - mockStoreProperty(); - - when( store.indexesGetForLabel( labelId ) ).thenReturn( indexes.iterator() ); - txContext.nodeAddLabel( state, nodeId, labelId ); - - // When - long result = txContext.nodeGetFromUniqueIndexSeek( state, schemaIndexDescriptor, withValue ); - - // Then - assertThat( result, equalTo( nodeId ) ); - } - - @Test - public void shouldIncludeExistingNodesWithCorrectPropertyAfterAddingLabel() throws Exception - { - // Given - when( indexReader.query( withValue ) ).then( answerAsPrimitiveLongIteratorFrom( asList( 2L, 3L ) ) ); - - long nodeId = 1L; - - when( statement.acquireSingleNodeCursor( nodeId ) ).thenReturn( asNodeCursor( nodeId, 40L ) ); - mockStoreProperty(); - - when( store.indexesGetForLabel( labelId ) ).thenReturn( indexes.iterator() ); - txContext.nodeAddLabel( state, nodeId, labelId ); - - // When - PrimitiveLongIterator result = txContext.indexQuery( state, schemaIndexDescriptor, withValue ); - - // Then - assertThat( PrimitiveLongCollections.toSet( result ), equalTo( asSet( nodeId, 2L, 3L ) ) ); - } - - @Test - public void shouldIncludeExistingUniqueNodeWithCorrectPropertyAfterAddingLabel() throws Exception - { - // Given - when( indexReader.query( withValue ) ).thenReturn( asPrimitiveResourceIterator() ); - - long nodeId = 2L; - - when( statement.acquireSingleNodeCursor( nodeId ) ).thenReturn( asNodeCursor( nodeId, 40L ) ); - mockStoreProperty(); - - when( store.indexesGetForLabel( labelId ) ).thenReturn( indexes.iterator() ); - txContext.nodeAddLabel( state, nodeId, labelId ); - - // When - long result = txContext.nodeGetFromUniqueIndexSeek( state, schemaIndexDescriptor, withValue ); - - // Then - assertThat( result, equalTo( nodeId ) ); - } - - @Test - public void shouldExcludeExistingNodesWithCorrectPropertyAfterRemovingLabel() throws Exception - { - // Given - long nodeId = 1L; - when( indexReader.query( withValue ) ).then( answerAsPrimitiveLongIteratorFrom( asList( nodeId, 2L, 3L ) ) ); - - when( statement.acquireSingleNodeCursor( nodeId ) ) - .thenReturn( asNodeCursor( nodeId, 40L, labels( labelId ) ) ); - mockStoreProperty(); - - txContext.nodeRemoveLabel( state, nodeId, labelId ); - - // When - PrimitiveLongIterator result = txContext.indexQuery( state, schemaIndexDescriptor, withValue ); - - // Then - assertThat( PrimitiveLongCollections.toSet( result ), equalTo( asSet( 2L, 3L ) ) ); - } - - @Test - public void shouldExcludeExistingUniqueNodeWithCorrectPropertyAfterRemovingLabel() throws Exception - { - // Given - long nodeId = 1L; - when( indexReader.query( withValue ) ).thenReturn( asPrimitiveResourceIterator( nodeId ) ); - - when( statement.acquireSingleNodeCursor( nodeId ) ) - .thenReturn( asNodeCursor( nodeId, 40L, labels( labelId ) ) ); - mockStoreProperty(); - - txContext.nodeRemoveLabel( state, nodeId, labelId ); - - // When - long result = txContext.nodeGetFromUniqueIndexSeek( state, schemaIndexDescriptor, withValue ); - - // Then - assertNoSuchNode( result ); - } - - @Test - public void shouldExcludeNodesWithRemovedProperty() throws Exception - { - // Given - when( indexReader.query( withValue ) ).then( answerAsPrimitiveLongIteratorFrom( asList( 2L, 3L ) ) ); - - long nodeId = 1L; - state.txState().nodeDoAddProperty( nodeId, propertyKeyId, Values.of( 10 ) ); - - when( statement.acquireSingleNodeCursor( nodeId ) ) - .thenReturn( asNodeCursor( nodeId, labels( labelId ) ) ); - - txContext.nodeAddLabel( state, nodeId, labelId ); - - // When - PrimitiveLongIterator result = txContext.indexQuery( state, schemaIndexDescriptor, withValue ); - - // Then - assertThat( PrimitiveLongCollections.toSet( result ), equalTo( asSet( 2L, 3L ) ) ); - } - - @Test - public void shouldExcludeUniqueNodeWithRemovedProperty() throws Exception - { - // Given - long nodeId = 1L; - when( indexReader.query( withValue ) ).thenReturn( asPrimitiveResourceIterator( nodeId ) ); - - when( statement.acquireSingleNodeCursor( nodeId ) ) - .thenReturn( asNodeCursor( nodeId, 40, labels( labelId ) ) ); - mockStoreProperty(); - - txContext.nodeRemoveProperty( state, nodeId, propertyKeyId ); - - // When - long result = txContext.nodeGetFromUniqueIndexSeek( state, schemaIndexDescriptor, withValue ); - - // Then - assertNoSuchNode( result ); - } - - private void mockStoreProperty() - { - when( store.nodeGetProperties( eq( statement ), any( NodeItem.class ), any( AssertOpen.class ) ) ) - .thenReturn( asPropertyCursor( new PropertyKeyValue( propertyKeyId, value ) ) ); - when( store.nodeGetProperty( eq( statement ), any( NodeItem.class ), eq( propertyKeyId ), - any( AssertOpen.class ) ) ) - .thenReturn( asPropertyCursor( new PropertyKeyValue( propertyKeyId, value ) ) ); - } - - private void assertNoSuchNode( long node ) - { - assertThat( node, equalTo( NO_SUCH_NODE ) ); - } - - private static PrimitiveLongResourceIterator asPrimitiveResourceIterator( long... values ) - { - return PrimitiveLongCollections.resourceIterator( PrimitiveLongCollections.iterator( values ), Resource.EMPTY ); - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/IndexTxStateUpdaterTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/IndexTxStateUpdaterTest.java deleted file mode 100644 index 539f39d6e777a..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/IndexTxStateUpdaterTest.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.state; - -import org.junit.Before; -import org.junit.Test; - -import java.util.Arrays; -import java.util.List; - -import org.neo4j.collection.primitive.Primitive; -import org.neo4j.collection.primitive.PrimitiveIntCollections; -import org.neo4j.collection.primitive.PrimitiveIntSet; -import org.neo4j.cursor.Cursor; -import org.neo4j.internal.kernel.api.schema.SchemaDescriptor; -import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; -import org.neo4j.kernel.api.properties.PropertyKeyValue; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptorFactory; -import org.neo4j.kernel.api.txstate.TransactionState; -import org.neo4j.kernel.impl.api.KernelStatement; -import org.neo4j.kernel.impl.api.index.IndexProxy; -import org.neo4j.kernel.impl.api.index.IndexingService; -import org.neo4j.kernel.impl.api.operations.EntityReadOperations; -import org.neo4j.storageengine.api.NodeItem; -import org.neo4j.storageengine.api.StoreReadLayer; -import org.neo4j.values.storable.ValueTuple; -import org.neo4j.values.storable.Values; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.helpers.collection.Iterators.filter; -import static org.neo4j.internal.kernel.api.schema.SchemaDescriptorPredicates.hasLabel; -import static org.neo4j.internal.kernel.api.schema.SchemaDescriptorPredicates.hasProperty; -import static org.neo4j.kernel.impl.api.state.IndexTxStateUpdater.LabelChangeType.ADDED_LABEL; -import static org.neo4j.kernel.impl.api.state.IndexTxStateUpdater.LabelChangeType.REMOVED_LABEL; - -public class IndexTxStateUpdaterTest -{ - private static final int labelId1 = 10; - private static final int labelId2 = 11; - private static final int unIndexedLabelId = 12; - private static final int propId1 = 20; - private static final int propId2 = 21; - private static final int propId3 = 22; - private static final int newPropId = 23; - private static final int unIndexedPropId = 24; - - private KernelStatement state; - private TransactionState txState; - private IndexTxStateUpdater indexTxUpdater; - private NodeItem node; - - private SchemaIndexDescriptor indexOn1_1 = SchemaIndexDescriptorFactory.forLabel( labelId1, propId1 ); - private SchemaIndexDescriptor indexOn2_new = SchemaIndexDescriptorFactory.forLabel( labelId2, newPropId ); - private SchemaIndexDescriptor uniqueOn1_2 = SchemaIndexDescriptorFactory.uniqueForLabel( labelId1, propId2 ); - private SchemaIndexDescriptor indexOn1_1_new = SchemaIndexDescriptorFactory.forLabel( labelId1, propId1, newPropId ); - private SchemaIndexDescriptor uniqueOn2_2_3 = SchemaIndexDescriptorFactory - .uniqueForLabel( labelId2, propId2, propId3 ); - private List indexes = - Arrays.asList( indexOn1_1, indexOn2_new, uniqueOn1_2, indexOn1_1_new, uniqueOn2_2_3 ); - - @Before - public void setup() throws IndexNotFoundKernelException - { - state = mock( KernelStatement.class ); - txState = mock( TransactionState.class ); - when( state.txState() ).thenReturn( txState ); - - StoreReadLayer storeReadLayer = mock( StoreReadLayer.class ); - when( storeReadLayer.indexesGetAll() ).thenAnswer( x -> indexes.iterator() ); - when( storeReadLayer.indexesGetForLabel(anyInt() ) ) - .thenAnswer( x -> - { - Integer argument = x.getArgument( 0 ); - return filter( hasLabel( argument ), indexes.iterator() ); - } ); - - when( storeReadLayer.indexesGetRelatedToProperty( anyInt() ) ) - .thenAnswer( x -> - { - Integer argument = x.getArgument( 0 ); - return filter( hasProperty( argument ), indexes.iterator() ); - } ); - - PrimitiveIntSet labels = Primitive.intSet(); - labels.add( labelId1 ); - labels.add( labelId2 ); - - Cursor nodeItemCursor = StubCursors.asNodeCursor( 0, labels ); - nodeItemCursor.next(); - node = nodeItemCursor.get(); - - PrimitiveIntSet defaultPropertyIds = PrimitiveIntCollections.asSet( new int[]{ propId1, propId2, propId3 } ); - EntityReadOperations readOps = mock( EntityReadOperations.class ); - when( readOps.nodeGetPropertyKeys( state, node ) ).thenReturn( defaultPropertyIds ); - when( readOps.nodeGetProperties( state, node ) ).thenAnswer( p -> StubCursors.asPropertyCursor( - new PropertyKeyValue( propId1, Values.of( "hi1" ) ), - new PropertyKeyValue( propId2, Values.of( "hi2" ) ), - new PropertyKeyValue( propId3, Values.of( "hi3" ) ) ) ); - when( readOps.nodeGetProperty( state, node, propId1 ) ).thenReturn( Values.of( "hi1" ) ); - when( readOps.nodeGetProperty( state, node, propId2 ) ).thenReturn( Values.of( "hi2" ) ); - when( readOps.nodeGetProperty( state, node, propId3 ) ).thenReturn( Values.of( "hi3" ) ); - - IndexingService indexingService = mock( IndexingService.class ); - when( indexingService.getIndexProxy( any( SchemaDescriptor.class ) ) ).thenReturn( mock( IndexProxy.class ) ); - - indexTxUpdater = new IndexTxStateUpdater( storeReadLayer, readOps, indexingService ); - - } - - // LABELS - - @Test - public void shouldNotUpdateIndexesOnChangedIrrelevantLabel() - { - // WHEN - indexTxUpdater.onLabelChange( state, unIndexedLabelId, node, ADDED_LABEL ); - indexTxUpdater.onLabelChange( state, unIndexedLabelId, node, REMOVED_LABEL ); - - // THEN - verify( txState, never() ).indexDoUpdateEntry( any(), anyInt(), any(), any() ); - } - - @Test - public void shouldUpdateIndexesOnAddedLabel() - { - // WHEN - indexTxUpdater.onLabelChange( state, labelId1, node, ADDED_LABEL ); - - // THEN - verifyIndexUpdate( indexOn1_1.schema(), node.id(), null, values( "hi1" ) ); - verifyIndexUpdate( uniqueOn1_2.schema(), node.id(), null, values( "hi2" ) ); - verify( txState, times( 2 ) ).indexDoUpdateEntry( any(), anyLong(), isNull(), any() ); - } - - @Test - public void shouldUpdateIndexesOnRemovedLabel() - { - // WHEN - indexTxUpdater.onLabelChange( state, labelId2, node, REMOVED_LABEL ); - - // THEN - verifyIndexUpdate( uniqueOn2_2_3.schema(), node.id(), values( "hi2", "hi3" ), null ); - verify( txState, times( 1 ) ).indexDoUpdateEntry( any(), anyLong(), any(), isNull() ); - } - - // PROPERTIES - - @Test - public void shouldNotUpdateIndexesOnChangedIrrelevantProperty() - { - // WHEN - indexTxUpdater.onPropertyAdd( state, node, unIndexedPropId, Values.of( "whAt" ) ); - indexTxUpdater.onPropertyRemove( state, node, unIndexedPropId, Values.of( "whAt" ) ); - indexTxUpdater.onPropertyChange( state, node, unIndexedPropId, Values.of( "whAt" ), Values.of( "whAt2" ) ); - - // THEN - verify( txState, never() ).indexDoUpdateEntry( any(), anyInt(), any(), any() ); - } - - @Test - public void shouldUpdateIndexesOnAddedProperty() - { - // WHEN - indexTxUpdater.onPropertyAdd( state, node, newPropId, Values.of( "newHi" ) ); - - // THEN - verifyIndexUpdate( indexOn2_new.schema(), node.id(), null, values( "newHi" ) ); - verifyIndexUpdate( indexOn1_1_new.schema(), node.id(), null, values( "hi1", "newHi" ) ); - verify( txState, times( 2 ) ).indexDoUpdateEntry( any(), anyLong(), isNull(), any() ); - } - - @Test - public void shouldUpdateIndexesOnRemovedProperty() - { - // WHEN - indexTxUpdater.onPropertyRemove( state, node, propId2, Values.of( "hi2" ) ); - - // THEN - verifyIndexUpdate( uniqueOn1_2.schema(), node.id(), values( "hi2" ), null ); - verifyIndexUpdate( uniqueOn2_2_3.schema(), node.id(), values( "hi2", "hi3" ), null ); - verify( txState, times( 2 ) ).indexDoUpdateEntry( any(), anyLong(), any(), isNull() ); - } - - @Test - public void shouldUpdateIndexesOnChangesProperty() - { - // WHEN - indexTxUpdater.onPropertyChange( state, node, propId2, Values.of( "hi2" ), Values.of( "new2" ) ); - - // THEN - verifyIndexUpdate( uniqueOn1_2.schema(), node.id(), values( "hi2" ), values( "new2" ) ); - verifyIndexUpdate( uniqueOn2_2_3.schema(), node.id(), values( "hi2", "hi3" ), values( "new2", "hi3" ) ); - verify( txState, times( 2 ) ).indexDoUpdateEntry( any(), anyLong(), any(), any() ); - } - - private ValueTuple values( Object... values ) - { - return ValueTuple.of( values ); - } - - private void verifyIndexUpdate( - SchemaDescriptor schema, long nodeId, ValueTuple before, ValueTuple after ) - { - verify( txState ).indexDoUpdateEntry( eq( schema ), eq( nodeId), eq( before ), eq( after ) ); - } - -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/LabelTransactionStateTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/LabelTransactionStateTest.java deleted file mode 100644 index 71fef8609c7ea..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/LabelTransactionStateTest.java +++ /dev/null @@ -1,384 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.state; - -import org.junit.Before; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.neo4j.collection.primitive.PrimitiveIntCollections; -import org.neo4j.collection.primitive.PrimitiveLongCollections; -import org.neo4j.internal.kernel.api.exceptions.EntityNotFoundException; -import org.neo4j.kernel.api.AssertOpen; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptorFactory; -import org.neo4j.kernel.api.txstate.TransactionState; -import org.neo4j.kernel.impl.api.KernelStatement; -import org.neo4j.kernel.impl.api.StateHandlingStatementOperations; -import org.neo4j.kernel.impl.api.StatementOperationsTestHelper; -import org.neo4j.kernel.impl.api.explicitindex.InternalAutoIndexing; -import org.neo4j.kernel.impl.api.index.IndexingService; -import org.neo4j.kernel.impl.index.ExplicitIndexStore; -import org.neo4j.kernel.impl.storageengine.impl.recordstorage.StoreStatement; -import org.neo4j.storageengine.api.NodeItem; -import org.neo4j.storageengine.api.StoreReadLayer; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.neo4j.helpers.collection.Iterators.asSet; -import static org.neo4j.kernel.impl.api.state.StubCursors.asNodeCursor; -import static org.neo4j.kernel.impl.api.state.StubCursors.asPropertyCursor; -import static org.neo4j.test.mockito.answer.Neo4jMockitoAnswers.answerAsIteratorFrom; -import static org.neo4j.test.mockito.answer.Neo4jMockitoAnswers.answerAsPrimitiveLongIteratorFrom; - -public class LabelTransactionStateTest -{ - @Before - public void before() - { - store = mock( StoreReadLayer.class ); - when( store.indexesGetForLabel( anyInt() ) ).then( answerAsIteratorFrom( Collections.emptyList() ) ); - when( store.indexesGetAll() ).then( answerAsIteratorFrom( Collections.emptyList() ) ); - - txState = new TxState(); - state = StatementOperationsTestHelper.mockedState( txState ); - txContext = new StateHandlingStatementOperations( store, mock( InternalAutoIndexing.class ), - mock( ConstraintIndexCreator.class ), mock( ExplicitIndexStore.class ), mock( IndexingService.class ) ); - - storeStatement = mock( StoreStatement.class ); - when( state.getStoreStatement() ).thenReturn( storeStatement ); - } - - @Test - public void addOnlyLabelShouldBeVisibleInTx() throws Exception - { - // GIVEN - commitNoLabels(); - - // WHEN - txContext.nodeAddLabel( state, nodeId, labelId1 ); - - // THEN - assertLabels( labelId1 ); - } - - @Test - public void addAdditionalLabelShouldBeReflectedWithinTx() throws Exception - { - // GIVEN - commitLabels( labelId1 ); - - // WHEN - txContext.nodeAddLabel( state, nodeId, labelId2 ); - - // THEN - assertLabels( labelId1, labelId2 ); - } - - @Test - public void addAlreadyExistingLabelShouldBeReflectedWithinTx() throws Exception - { - // GIVEN - commitLabels( labelId1 ); - - // WHEN - txContext.nodeAddLabel( state, nodeId, labelId1 ); - - // THEN - assertLabels( labelId1 ); - } - - @Test - public void removeCommittedLabelShouldBeReflectedWithinTx() throws Exception - { - // GIVEN - commitLabels( labelId1, labelId2 ); - - // WHEN - txContext.nodeRemoveLabel( state, nodeId, labelId1 ); - - // THEN - assertLabels( labelId2 ); - } - - @Test - public void removeAddedLabelInTxShouldBeReflectedWithinTx() throws Exception - { - // GIVEN - commitLabels( labelId1 ); - - // WHEN - txContext.nodeAddLabel( state, nodeId, labelId2 ); - txContext.nodeRemoveLabel( state, nodeId, labelId2 ); - - // THEN - assertLabels( labelId1 ); - } - - @Test - public void addRemovedLabelInTxShouldBeReflectedWithinTx() throws Exception - { - // GIVEN - commitLabels( labelId1 ); - - // WHEN - txContext.nodeRemoveLabel( state, nodeId, labelId1 ); - txContext.nodeAddLabel( state, nodeId, labelId1 ); - - // THEN - assertLabels( labelId1 ); - } - - @Test - public void addedLabelsShouldBeReflectedWhenGettingNodesForLabel() throws Exception - { - // GIVEN - commitLabels( - labels( 0, 1, 2 ), - labels( 1, 2, 3 ), - labels( 2, 1, 3 ) ); - - // WHEN - List indexes = Collections.singletonList( SchemaIndexDescriptorFactory.forLabel( 2, 2 ) ); - when( store.indexesGetForLabel( 2 ) ).thenReturn( indexes.iterator() ); - txContext.nodeAddLabel( state, 2, 2 ); - - // THEN - assertEquals( asSet( 0L, 1L, 2L ), PrimitiveLongCollections.toSet( txContext.nodesGetForLabel( state, 2 ) ) ); - } - - @Test - public void removedLabelsShouldBeReflectedWhenGettingNodesForLabel() throws Exception - { - // GIVEN - commitLabels( - labels( 0, 1, 2 ), - labels( 1, 2, 3 ), - labels( 2, 1, 3 ) ); - - // WHEN - txContext.nodeRemoveLabel( state, 1, 2 ); - - // THEN - assertEquals( asSet( 0L ), PrimitiveLongCollections.toSet( txContext.nodesGetForLabel( state, 2 ) ) ); - } - - @Test - public void addingNewLabelToNodeShouldRespondTrue() throws Exception - { - // GIVEN - commitNoLabels(); - - // WHEN - boolean added = txContext.nodeAddLabel( state, nodeId, labelId1 ); - - // THEN - assertTrue( "Should have been added now", added ); - } - - @Test - public void addingExistingLabelToNodeShouldRespondFalse() throws Exception - { - // GIVEN - commitLabels( labelId1 ); - - // WHEN - boolean added = txContext.nodeAddLabel( state, nodeId, labelId1 ); - - // THEN - assertFalse( "Shouldn't have been added now", added ); - } - - @Test - public void removingExistingLabelFromNodeShouldRespondTrue() throws Exception - { - // GIVEN - commitLabels( labelId1 ); - - // WHEN - boolean removed = txContext.nodeRemoveLabel( state, nodeId, labelId1 ); - - // THEN - assertTrue( "Should have been removed now", removed ); - } - - @Test - public void removingNonExistentLabelFromNodeShouldRespondFalse() throws Exception - { - // GIVEN - commitNoLabels(); - - // WHEN - txContext.nodeAddLabel( state, nodeId, labelId1 ); - - // THEN - assertLabels( labelId1 ); - } - - @Test - public void should_return_true_when_adding_new_label() throws Exception - { - // GIVEN - when( storeStatement.acquireSingleNodeCursor( 1337 ) ).thenReturn( asNodeCursor( 1337 ) ); - when( store.nodeGetProperties( eq( storeStatement ), any( NodeItem.class ), any( AssertOpen.class ) ) ) - .thenReturn( asPropertyCursor() ); - - // WHEN - boolean added = txContext.nodeAddLabel( state, 1337, 12 ); - - // THEN - assertTrue( "Label should have been added", added ); - } - - @Test - public void should_return_false_when_adding_existing_label() throws Exception - { - // GIVEN - when( storeStatement.acquireSingleNodeCursor( 1337 ) ).thenReturn( asNodeCursor( 1337, - StubCursors.labels( 12 ) ) ); - when( store.nodeGetProperties( eq( storeStatement ), any( NodeItem.class ), any( AssertOpen.class ) ) ) - .thenReturn( asPropertyCursor() ); - - // WHEN - boolean added = txContext.nodeAddLabel( state, 1337, 12 ); - - // THEN - assertFalse( "Label should have been added", added ); - } - - @Test - public void should_return_true_when_removing_existing_label() throws Exception - { - // GIVEN - when( storeStatement.acquireSingleNodeCursor( 1337 ) ).thenReturn( asNodeCursor( 1337, - StubCursors.labels( 12 ) ) ); - when( store.nodeGetProperties( eq( storeStatement ), any( NodeItem.class ), any( AssertOpen.class ) ) ) - .thenReturn( asPropertyCursor() ); - - // WHEN - boolean added = txContext.nodeRemoveLabel( state, 1337, 12 ); - - // THEN - assertTrue( "Label should have been removed", added ); - } - - @Test - public void should_return_true_when_removing_non_existant_label() throws Exception - { - // GIVEN - when( storeStatement.acquireSingleNodeCursor( 1337 ) ).thenReturn( asNodeCursor( 1337 ) ); - - // WHEN - boolean removed = txContext.nodeRemoveLabel( state, 1337, 12 ); - - // THEN - assertFalse( "Label should have been removed", removed ); - } - - // exists - - private final int labelId1 = 10; - private final int labelId2 = 12; - private final long nodeId = 20; - - private StoreReadLayer store; - private TransactionState txState; - private StateHandlingStatementOperations txContext; - - private KernelStatement state; - private StoreStatement storeStatement; - - private static class Labels - { - private final long nodeId; - private final int[] labelIds; - - Labels( long nodeId, int... labelIds ) - { - this.nodeId = nodeId; - this.labelIds = labelIds; - } - } - - private static Labels labels( long nodeId, int... labelIds ) - { - return new Labels( nodeId, labelIds ); - } - - private void commitLabels( Labels... labels ) - { - Map> allLabels = new HashMap<>(); - for ( Labels nodeLabels : labels ) - { - when( storeStatement.acquireSingleNodeCursor( nodeLabels.nodeId ) ) - .thenReturn( asNodeCursor( nodeLabels.nodeId, StubCursors.labels( nodeLabels.labelIds ) ) ); - when( store.nodeGetProperties( eq( storeStatement ), any( NodeItem.class ), any( AssertOpen.class ) ) ) - .thenReturn( asPropertyCursor() ); - - for ( int label : nodeLabels.labelIds ) - { - Collection nodes = allLabels.computeIfAbsent( label, k -> new ArrayList<>() ); - nodes.add( nodeLabels.nodeId ); - } - } - - for ( Map.Entry> entry : allLabels.entrySet() ) - { - when( store.nodesGetForLabel( state.getStoreStatement(), entry.getKey() ) ) - .then( answerAsPrimitiveLongIteratorFrom( entry.getValue() ) ); - } - } - - private void commitNoLabels() - { - commitLabels( new int[0] ); - } - - private void commitLabels( int... labels ) - { - commitLabels( labels( nodeId, labels ) ); - } - - private void assertLabels( int... labels ) throws EntityNotFoundException - { - txContext.nodeCursorById( state, nodeId ) - .forAll( node -> assertEquals( PrimitiveIntCollections.asSet( labels ), node.labels() ) ); - - txContext.nodeCursorById( state, nodeId ).forAll( node -> - { - for ( int label : labels ) - { - assertTrue( "Expected labels not found on node", node.hasLabel( label ) ); - } - } ); - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/SchemaTransactionStateTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/SchemaTransactionStateTest.java deleted file mode 100644 index bc2d61547b5b9..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/SchemaTransactionStateTest.java +++ /dev/null @@ -1,310 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.state; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.stubbing.Answer; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import org.neo4j.helpers.collection.Iterators; -import org.neo4j.internal.kernel.api.InternalIndexState; -import org.neo4j.internal.kernel.api.schema.LabelSchemaDescriptor; -import org.neo4j.kernel.api.schema.SchemaDescriptorFactory; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptorFactory; -import org.neo4j.kernel.api.txstate.TransactionState; -import org.neo4j.kernel.impl.api.KernelStatement; -import org.neo4j.kernel.impl.api.StateHandlingStatementOperations; -import org.neo4j.kernel.impl.api.StatementOperationsTestHelper; -import org.neo4j.kernel.impl.api.explicitindex.InternalAutoIndexing; -import org.neo4j.kernel.impl.api.index.IndexingService; -import org.neo4j.kernel.impl.index.ExplicitIndexStore; -import org.neo4j.kernel.impl.storageengine.impl.recordstorage.StoreStatement; -import org.neo4j.storageengine.api.StoreReadLayer; - -import static java.util.Collections.emptySet; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; -import static org.neo4j.helpers.collection.Iterables.option; -import static org.neo4j.helpers.collection.Iterators.asSet; - -public class SchemaTransactionStateTest -{ - private static SchemaIndexDescriptor indexCreate( StateHandlingStatementOperations txContext, KernelStatement state, - int labelId, int propertyKey ) - { - return txContext.indexCreate( state, SchemaDescriptorFactory.forLabel( labelId, propertyKey ) ); - } - - private static SchemaIndexDescriptor indexGetForLabelAndPropertyKey( - StateHandlingStatementOperations txContext, KernelStatement state, int labelId, int propertyKey ) - { - LabelSchemaDescriptor schemaDescriptor = SchemaDescriptorFactory.forLabel( labelId, propertyKey ); - return txContext.indexGetForSchema( state, schemaDescriptor ); - } - - private static SchemaIndexDescriptor indexGetForLabelAndPropertyKey( StoreReadLayer store, int labelId, - int propertyKey ) - { - return store.indexGetForSchema( SchemaDescriptorFactory.forLabel( labelId, propertyKey ) ); - } - - @Test - public void addedRuleShouldBeVisibleInTx() - { - // GIVEN - commitNoLabels(); - - // WHEN - SchemaIndexDescriptor index = indexCreate( txContext, state, labelId1, key1 ); - - // THEN - assertEquals( asSet( index ), Iterators.asSet( txContext.indexesGetForLabel( state, labelId1 ) ) ); - verify( store ).indexesGetForLabel( labelId1 ); - - assertEquals( asSet( index ), Iterators.asSet( txContext.indexesGetAll( state ) ) ); - verify( store ).indexesGetAll(); - - verifyNoMoreInteractions( store ); - } - - @Test - public void addedRulesShouldBeVisibleInTx() - { - // GIVEN - commitNoLabels(); - - // WHEN - SchemaIndexDescriptor rule1 = indexCreate( txContext, state, labelId1, key1 ); - SchemaIndexDescriptor rule2 = indexCreate( txContext, state, labelId2, key2 ); - - // THEN - assertEquals( asSet( rule1 ), Iterators.asSet( txContext.indexesGetForLabel( state, labelId1 ) ) ); - verify( store ).indexesGetForLabel( labelId1 ); - - assertEquals( asSet( rule2 ), Iterators.asSet( txContext.indexesGetForLabel( state, labelId2 ) ) ); - verify( store ).indexesGetForLabel( labelId2 ); - - assertEquals( asSet( rule1, rule2 ), Iterators.asSet( txContext.indexesGetAll( state ) ) ); - verify( store ).indexesGetAll(); - - verifyNoMoreInteractions( store ); - } - - @Test - public void addedAdditionalRuleShouldBeVisibleInTx() - { - // GIVEN - commitNoLabels(); - - // WHEN - SchemaIndexDescriptor rule1 = indexCreate( txContext, state, labelId1, key1 ); - SchemaIndexDescriptor rule2 = indexCreate( txContext, state, labelId1, key2 ); - - // THEN - assertEquals( asSet( rule1, rule2 ), Iterators.asSet( txContext.indexesGetForLabel( state, labelId1 ) ) ); - } - - @Test - public void creatingAnIndexShouldBePopulatingStateWithinTX() throws Exception - { - // GIVEN - commitLabels( labelId1 ); - SchemaIndexDescriptor rule = indexCreate( txContext, state, labelId1, key1 ); - - // THEN - assertEquals( InternalIndexState.POPULATING, txContext.indexGetState( state, rule ) ); - } - - @Test - public void shouldReturnNonExistentRuleAddedInTransaction() - { - // GIVEN - // -- non-existent rule added in the transaction - indexCreate( txContext, state, labelId1, key1 ); - - // WHEN - SchemaIndexDescriptor index = indexGetForLabelAndPropertyKey( txContext, state, labelId1, key1 ); - Iterator labelRules = txContext.indexesGetForLabel( state, labelId1 ); - - // THEN - SchemaIndexDescriptor expectedRule = SchemaIndexDescriptorFactory.forLabel( labelId1, key1 ); - assertEquals( expectedRule, index ); - assertEquals( asSet( expectedRule ), asSet( labelRules ) ); - } - - @Test - public void shouldReturnNonExistentRuleAddedInTransactionFromLookup() - { - // GIVEN - // -- the store already have an index on the label and a different property - SchemaIndexDescriptor existingRule1 = SchemaIndexDescriptorFactory.forLabel( labelId1, key1 ); - when( indexGetForLabelAndPropertyKey( store, labelId1, key1 ) ).thenReturn( existingRule1 ); - // -- the store already have an index on a different label with the same property - SchemaIndexDescriptor existingRule2 = SchemaIndexDescriptorFactory.forLabel( labelId2, key2 ); - when( indexGetForLabelAndPropertyKey( store, labelId2, key2 ) ).thenReturn( existingRule2 ); - // -- a non-existent index has been added in the transaction - indexCreate( txContext, state, labelId1, key2 ); - - // WHEN - SchemaIndexDescriptor index = indexGetForLabelAndPropertyKey( txContext, state, labelId1, key2 ); - - // THEN - assertEquals( SchemaIndexDescriptorFactory.forLabel( labelId1, key2 ), index ); - } - - @Test - public void shouldNotReturnRulesAddedInTransactionWithDifferentLabelOrPropertyFromLookup() - { - // GIVEN - // -- the store already have an index on the label and a different property - SchemaIndexDescriptor existingIndex1 = SchemaIndexDescriptorFactory.forLabel( labelId1, key1 ); - when( indexGetForLabelAndPropertyKey( store,labelId1, key1) ).thenReturn( existingIndex1 ); - // -- the store already have an index on a different label with the same property - SchemaIndexDescriptor existingIndex2 = SchemaIndexDescriptorFactory.forLabel( labelId2, key2 ); - when( indexGetForLabelAndPropertyKey( store, labelId2, key2 ) ).thenReturn( existingIndex2 ); - // -- a non-existent rule has been added in the transaction - indexCreate( txContext, state, labelId1, key2 ); - - // WHEN - SchemaIndexDescriptor lookupRule1 = indexGetForLabelAndPropertyKey( txContext, state, labelId1, key1 ); - SchemaIndexDescriptor lookupRule2 = indexGetForLabelAndPropertyKey( txContext, state, labelId2, key2 ); - - // THEN - assertEquals( existingIndex1, lookupRule1 ); - assertEquals( existingIndex2, lookupRule2 ); - } - - @Test - public void shouldNotReturnExistentRuleDroppedInTransaction() - { - // GIVEN - // -- a rule that exists in the store - SchemaIndexDescriptor index = SchemaIndexDescriptorFactory.forLabel( labelId1, key1 ); - when( store.indexesGetForLabel( labelId1 ) ).thenReturn( option( index ).iterator() ); - // -- that same rule dropped in the transaction - txContext.indexDrop( state, index ); - - // WHEN - assertNull( indexGetForLabelAndPropertyKey( txContext, state, labelId1, key1 ) ); - Iterator rulesByLabel = txContext.indexesGetForLabel( state, labelId1 ); - - // THEN - assertEquals( emptySet(), asSet( rulesByLabel ) ); - } - - // exists - - private final int labelId1 = 10; - private final int labelId2 = 12; - private final int key1 = 45; - private final int key2 = 46; - private final long nodeId = 20; - - private StoreReadLayer store; - private TransactionState txState; - private StateHandlingStatementOperations txContext; - private KernelStatement state; - private StoreStatement storeStatement; - - @Before - public void before() - { - txState = new TxState(); - state = StatementOperationsTestHelper.mockedState( txState ); - - store = mock( StoreReadLayer.class ); - when( store.indexesGetForLabel( labelId1 ) ).then( asAnswer( Collections.emptyList() ) ); - when( store.indexesGetForLabel( labelId2 ) ).then( asAnswer( Collections.emptyList() ) ); - when( store.indexesGetAll() ).then( asAnswer( Collections.emptyList() ) ); - - txContext = new StateHandlingStatementOperations( store, mock( InternalAutoIndexing.class ), - mock( ConstraintIndexCreator.class ), mock( ExplicitIndexStore.class ), mock( IndexingService.class ) ); - - storeStatement = mock(StoreStatement.class); - when( state.getStoreStatement() ).thenReturn( storeStatement ); - } - - private static Answer> asAnswer( final Iterable values ) - { - return invocation -> values.iterator(); - } - - private static class Labels - { - private final long nodeId; - private final int[] labelIds; - - Labels( long nodeId, int... labelIds ) - { - this.nodeId = nodeId; - this.labelIds = labelIds; - } - } - - private static Labels labels( long nodeId, int... labelIds ) - { - return new Labels( nodeId, labelIds ); - } - - private void commitLabels( Labels... labels ) - { - Map> allLabels = new HashMap<>(); - for ( Labels nodeLabels : labels ) - { - when( storeStatement.acquireSingleNodeCursor( nodeLabels.nodeId ) ).thenReturn( - StubCursors.asNodeCursor( nodeLabels.nodeId, StubCursors.labels( nodeLabels.labelIds ) ) ); - - for ( int label : nodeLabels.labelIds ) - { - - Collection nodes = allLabels.computeIfAbsent( label, k -> new ArrayList<>() ); - nodes.add( nodeLabels.nodeId ); - } - } - - for ( Map.Entry> entry : allLabels.entrySet() ) - { - when( store.nodesGetForLabel( state.getStoreStatement(), entry.getKey() ) ) - .then( asAnswer( entry.getValue() ) ); - } - } - - private void commitNoLabels() - { - commitLabels( new int[0] ); - } - - private void commitLabels( int... labels ) - { - commitLabels( labels( nodeId, labels ) ); - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/StateHandlingStatementOperationsTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/StateHandlingStatementOperationsTest.java deleted file mode 100644 index 952cfa8157d71..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/StateHandlingStatementOperationsTest.java +++ /dev/null @@ -1,654 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.state; - -import org.junit.Test; - -import java.util.Collections; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.neo4j.collection.primitive.PrimitiveLongCollections; -import org.neo4j.collection.primitive.PrimitiveLongIterator; -import org.neo4j.collection.primitive.PrimitiveLongResourceCollections; -import org.neo4j.cursor.Cursor; -import org.neo4j.helpers.collection.Iterables; -import org.neo4j.internal.kernel.api.IndexQuery; -import org.neo4j.internal.kernel.api.IndexQuery.RangePredicate; -import org.neo4j.internal.kernel.api.schema.LabelSchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.constraints.ConstraintDescriptor; -import org.neo4j.kernel.api.AssertOpen; -import org.neo4j.kernel.api.DataWriteOperations; -import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; -import org.neo4j.kernel.api.explicitindex.AutoIndexOperations; -import org.neo4j.kernel.api.explicitindex.AutoIndexing; -import org.neo4j.kernel.api.properties.PropertyKeyValue; -import org.neo4j.kernel.api.schema.SchemaDescriptorFactory; -import org.neo4j.kernel.api.schema.constaints.ConstraintDescriptorFactory; -import org.neo4j.kernel.api.schema.constaints.UniquenessConstraintDescriptor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptorFactory; -import org.neo4j.kernel.api.txstate.TransactionState; -import org.neo4j.kernel.impl.api.KernelStatement; -import org.neo4j.kernel.impl.api.StateHandlingStatementOperations; -import org.neo4j.kernel.impl.api.explicitindex.InternalAutoIndexing; -import org.neo4j.kernel.impl.api.index.IndexingService; -import org.neo4j.kernel.impl.index.ExplicitIndexStore; -import org.neo4j.kernel.impl.storageengine.impl.recordstorage.StoreStatement; -import org.neo4j.kernel.impl.util.collection.OnHeapCollectionsFactory; -import org.neo4j.kernel.impl.util.diffsets.DiffSets; -import org.neo4j.kernel.impl.util.diffsets.PrimitiveLongDiffSets; -import org.neo4j.storageengine.api.NodeItem; -import org.neo4j.storageengine.api.PropertyItem; -import org.neo4j.storageengine.api.RelationshipItem; -import org.neo4j.storageengine.api.StorageStatement; -import org.neo4j.storageengine.api.StoreReadLayer; -import org.neo4j.storageengine.api.schema.IndexReader; -import org.neo4j.values.storable.NumberValue; -import org.neo4j.values.storable.Value; -import org.neo4j.values.storable.ValueGroup; -import org.neo4j.values.storable.ValueTuple; -import org.neo4j.values.storable.Values; - -import static java.util.Collections.emptyIterator; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.ArgumentMatchers.isNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; -import static org.neo4j.collection.primitive.PrimitiveLongCollections.setOf; -import static org.neo4j.helpers.collection.Iterators.asIterable; -import static org.neo4j.helpers.collection.Iterators.asSet; -import static org.neo4j.helpers.collection.Iterators.iterator; -import static org.neo4j.kernel.impl.api.StatementOperationsTestHelper.mockedState; -import static org.neo4j.kernel.impl.api.state.StubCursors.asNodeCursor; -import static org.neo4j.kernel.impl.api.state.StubCursors.asPropertyCursor; -import static org.neo4j.values.storable.Values.stringValue; - -public class StateHandlingStatementOperationsTest -{ - // Note: Most of the behavior of this class is tested in separate classes, - // based on the category of state being - // tested. This contains general tests or things that are common to all - // types of state. - - StoreReadLayer inner = mock( StoreReadLayer.class ); - - private final LabelSchemaDescriptor descriptor = SchemaDescriptorFactory.forLabel( 10, 66 ); - private final SchemaIndexDescriptor index = SchemaIndexDescriptorFactory.forLabel( 1, 2 ); - - @Test - public void shouldNeverDelegateWrites() throws Exception - { - KernelStatement state = mockedState(); - - when( state.txState() ).thenReturn( new TxState() ); - StoreStatement storeStatement = mock( StoreStatement.class ); - when( state.getStoreStatement() ).thenReturn( storeStatement ); - when( inner.indexesGetForLabel( 0 ) ).thenReturn( iterator( SchemaIndexDescriptorFactory.forLabel( 0, 0 ) ) ); - when( storeStatement.acquireSingleNodeCursor( anyLong() ) ).thenReturn( asNodeCursor( 0 ) ); - when( inner.nodeGetProperties( eq( storeStatement ), any( NodeItem.class ), any( AssertOpen.class ) ) ). - thenReturn( asPropertyCursor() ); - - StateHandlingStatementOperations ctx = newTxStateOps( inner ); - - // When - LabelSchemaDescriptor descriptor = SchemaDescriptorFactory.forLabel( 0, 0 ); - ctx.indexCreate( state, descriptor ); - ctx.nodeAddLabel( state, 0, 0 ); - ctx.indexDrop( state, SchemaIndexDescriptorFactory.forSchema( descriptor ) ); - ctx.nodeRemoveLabel( state, 0, 0 ); - - // one for add and one for remove - verify( storeStatement, times( 2 ) ).acquireSingleNodeCursor( 0 ); - verifyNoMoreInteractions( storeStatement ); - } - - @Test - public void shouldNotAddConstraintAlreadyExistsInTheStore() throws Exception - { - // given - UniquenessConstraintDescriptor constraint = ConstraintDescriptorFactory.uniqueForSchema( descriptor ); - TransactionState txState = mock( TransactionState.class ); - when( txState.nodesWithLabelChanged( anyInt() ) ).thenReturn( new DiffSets<>() ); - when( txState.hasChanges() ).thenReturn( true ); - KernelStatement state = mockedState( txState ); - when( inner.constraintsGetForSchema( any() ) ).thenReturn( iterator( constraint ) ); - StateHandlingStatementOperations context = newTxStateOps( inner ); - - // when - context.uniquePropertyConstraintCreate( state, descriptor ); - - // then - verify( txState ).indexDoUnRemove( eq( constraint.ownedIndexDescriptor() ) ); - } - - @Test - public void shouldGetConstraintsByLabelAndProperty() throws Exception - { - // given - ConstraintDescriptor constraint = ConstraintDescriptorFactory.uniqueForSchema( descriptor ); - TransactionState txState = new TxState(); - KernelStatement state = mockedState( txState ); - when( inner.constraintsGetForSchema( constraint.schema() ) ) - .thenAnswer( invocation -> emptyIterator() ); - StateHandlingStatementOperations context = newTxStateOps( inner ); - context.uniquePropertyConstraintCreate( state, descriptor ); - - // when - Set result = Iterables.asSet( - asIterable( context.constraintsGetForSchema( state, constraint.schema() ) ) ); - - // then - assertEquals( asSet( constraint ), result ); - } - - @Test - public void shouldGetConstraintsByLabel() throws Exception - { - // given - UniquenessConstraintDescriptor constraint1 = ConstraintDescriptorFactory.uniqueForLabel( 2, 3 ); - UniquenessConstraintDescriptor constraint2 = ConstraintDescriptorFactory.uniqueForLabel( 4, 5 ); - - TransactionState txState = new TxState(); - KernelStatement state = mockedState( txState ); - when( inner.constraintsGetForSchema( constraint1.schema() ) ) - .thenAnswer( invocation -> emptyIterator() ); - when( inner.constraintsGetForSchema( constraint2.schema() ) ) - .thenAnswer( invocation -> emptyIterator() ); - when( inner.constraintsGetForLabel( 1 ) ) - .thenAnswer( invocation -> emptyIterator() ); - when( inner.constraintsGetForLabel( 2 ) ) - .thenAnswer( invocation -> iterator( constraint1 ) ); - StateHandlingStatementOperations context = newTxStateOps( inner ); - context.uniquePropertyConstraintCreate( state, constraint1.ownedIndexDescriptor().schema() ); - context.uniquePropertyConstraintCreate( state, constraint2.ownedIndexDescriptor().schema() ); - - // when - Set result = Iterables.asSet( asIterable( context.constraintsGetForLabel( state, 2 ) ) ); - - // then - assertEquals( asSet( constraint1 ), result ); - } - - @Test - public void shouldGetAllConstraints() throws Exception - { - // given - UniquenessConstraintDescriptor constraint1 = ConstraintDescriptorFactory.uniqueForLabel( 2, 3 ); - UniquenessConstraintDescriptor constraint2 = ConstraintDescriptorFactory.uniqueForLabel( 4, 5 ); - - TransactionState txState = new TxState(); - KernelStatement state = mockedState( txState ); - when( inner.constraintsGetForSchema( constraint1.schema() ) ) - .thenAnswer( invocation -> emptyIterator() ); - when( inner.constraintsGetForSchema( constraint2.schema() ) ) - .thenAnswer( invocation -> emptyIterator() ); - when( inner.constraintsGetAll() ) - .thenAnswer( invocation -> iterator( constraint2 ) ); - StateHandlingStatementOperations context = newTxStateOps( inner ); - context.uniquePropertyConstraintCreate( state, constraint1.schema() ); - context.uniquePropertyConstraintCreate( state, constraint2.schema() ); - - // when - Set result = Iterables.asSet( asIterable( context.constraintsGetAll( state ) ) ); - - // then - assertEquals( asSet( constraint1, constraint2 ), result ); - } - - @Test - public void shouldConsiderTransactionStateDuringIndexScanWithIndexQuery() throws Exception - { - // Given - TransactionState txState = mock( TransactionState.class ); - KernelStatement statement = mock( KernelStatement.class ); - when( statement.hasTxStateWithChanges() ).thenReturn( true ); - when( statement.txState() ).thenReturn( txState ); - when( txState.indexUpdatesForScan( index ) ).thenReturn( createDiffSets() ); - when( txState.addedAndRemovedNodes() ).thenReturn( - new DiffSets<>( Collections.singleton( 45L ), Collections.singleton( 46L ) ) - ); - - StoreReadLayer storeReadLayer = mock( StoreReadLayer.class ); - IndexReader indexReader = addMockedIndexReader( statement ); - IndexQuery query = IndexQuery.exists( index.schema().getPropertyId() ); - when( indexReader.query( query ) ).thenReturn( - PrimitiveLongCollections.resourceIterator( PrimitiveLongCollections.iterator( 43L, 44L, 46L ), null ) - ); - - StateHandlingStatementOperations context = newTxStateOps( storeReadLayer ); - - // When - PrimitiveLongIterator results = context.indexQuery( statement, index, query ); - - // Then - assertEquals( asSet( 42L, 43L ), PrimitiveLongCollections.toSet( results ) ); - } - - @Test - public void shouldConsiderTransactionStateDuringIndexSeekWithIndexQuery() throws Exception - { - // Given - TransactionState txState = mock( TransactionState.class ); - KernelStatement statement = mock( KernelStatement.class ); - when( statement.hasTxStateWithChanges() ).thenReturn( true ); - when( statement.txState() ).thenReturn( txState ); - when( txState.indexUpdatesForSeek( index, ValueTuple.of( "value" ) ) ).thenReturn( createDiffSets() ); - when( txState.addedAndRemovedNodes() ).thenReturn( - new DiffSets<>( Collections.singleton( 45L ), Collections.singleton( 46L ) ) - ); - - StoreReadLayer storeReadLayer = mock( StoreReadLayer.class ); - IndexReader indexReader = addMockedIndexReader( statement ); - IndexQuery.ExactPredicate query = IndexQuery.exact( index.schema().getPropertyId(), "value" ); - when( indexReader.query( query ) ).thenReturn( - PrimitiveLongCollections.resourceIterator( PrimitiveLongCollections.iterator( 43L, 44L, 46L ), null ) ); - - StateHandlingStatementOperations context = newTxStateOps( storeReadLayer ); - - // When - PrimitiveLongIterator results = context.indexQuery( statement, index, query ); - - // Then - assertEquals( asSet( 42L, 43L ), PrimitiveLongCollections.toSet( results ) ); - } - - @Test - public void shouldConsiderTransactionStateDuringIndexRangeSeekByPrefixWithIndexQuery() throws Exception - { - // Given - TransactionState txState = mock( TransactionState.class ); - KernelStatement statement = mock( KernelStatement.class ); - when( statement.hasTxStateWithChanges() ).thenReturn( true ); - when( statement.txState() ).thenReturn( txState ); - when( txState.indexUpdatesForRangeSeekByPrefix( index, "prefix" ) ).thenReturn( createDiffSets() - ); - when( txState.addedAndRemovedNodes() ).thenReturn( - new DiffSets<>( Collections.singleton( 45L ), Collections.singleton( 46L ) ) - ); - - StoreReadLayer storeReadLayer = mock( StoreReadLayer.class ); - IndexReader indexReader = addMockedIndexReader( statement ); - IndexQuery.StringPrefixPredicate indexQuery = IndexQuery.stringPrefix( index.schema().getPropertyId(), "prefix" ); - when( indexReader.query( indexQuery ) ).thenReturn( - PrimitiveLongCollections.resourceIterator( PrimitiveLongCollections.iterator( 43L, 44L, 46L ), null ) ); - - StateHandlingStatementOperations context = newTxStateOps( storeReadLayer ); - - // When - PrimitiveLongIterator results = context.indexQuery( statement, index, indexQuery ); - - // Then - assertEquals( asSet( 42L, 43L ), PrimitiveLongCollections.toSet( results ) ); - } - - @Test - public void shouldConsiderTransactionStateDuringIndexRangeSeekByContainsWithIndexQuery() throws Exception - { - // Given - TransactionState txState = mock( TransactionState.class ); - KernelStatement statement = mock( KernelStatement.class ); - when( statement.hasTxStateWithChanges() ).thenReturn( true ); - when( statement.txState() ).thenReturn( txState ); - when( txState.indexUpdatesForScan( index ) ).thenReturn( createDiffSets() - ); - when( txState.addedAndRemovedNodes() ).thenReturn( - new DiffSets<>( Collections.singleton( 45L ), Collections.singleton( 46L ) ) - ); - - StoreReadLayer storeReadLayer = mock( StoreReadLayer.class ); - IndexReader indexReader = addMockedIndexReader( statement ); - IndexQuery.StringContainsPredicate indexQuery = IndexQuery.stringContains( index.schema().getPropertyId(), "contains" ); - when( indexReader.query( indexQuery ) ).thenReturn( - PrimitiveLongCollections.resourceIterator( PrimitiveLongCollections.iterator( 43L, 44L, 46L ), null ) ); - - StateHandlingStatementOperations context = newTxStateOps( storeReadLayer ); - - // When - PrimitiveLongIterator results = context.indexQuery( statement, index, indexQuery ); - - // Then - assertEquals( asSet( 42L, 43L ), PrimitiveLongCollections.toSet( results ) ); - } - - @Test - public void shouldConsiderTransactionStateDuringIndexRangeSeekBySuffixWithIndexQuery() throws Exception - { - // Given - TransactionState txState = mock( TransactionState.class ); - KernelStatement statement = mock( KernelStatement.class ); - when( statement.hasTxStateWithChanges() ).thenReturn( true ); - when( statement.txState() ).thenReturn( txState ); - when( txState.indexUpdatesForScan( index ) ).thenReturn( createDiffSets() - ); - when( txState.addedAndRemovedNodes() ).thenReturn( - new DiffSets<>( Collections.singleton( 45L ), Collections.singleton( 46L ) ) - ); - - StoreReadLayer storeReadLayer = mock( StoreReadLayer.class ); - IndexReader indexReader = addMockedIndexReader( statement ); - IndexQuery.StringSuffixPredicate indexQuery = IndexQuery.stringSuffix( index.schema().getPropertyId(), "suffix" ); - when( indexReader.query( indexQuery ) ).thenReturn( - PrimitiveLongCollections.resourceIterator( PrimitiveLongCollections.iterator( 43L, 44L, 46L ), null ) ); - - StateHandlingStatementOperations context = newTxStateOps( storeReadLayer ); - - // When - PrimitiveLongIterator results = context.indexQuery( statement, index, indexQuery ); - - // Then - assertEquals( asSet( 42L, 43L ), PrimitiveLongCollections.toSet( results ) ); - } - - @SuppressWarnings( "unchecked" ) - @Test - public void shouldConsiderTransactionStateDuringIndexBetweenRangeSeekByNumberWithIndexQuery() throws Exception - { - // Given - final int propertyKey = 2; - final int inRange = 15; - NumberValue lower = Values.numberValue( 10 ); - NumberValue upper = Values.numberValue( 20 ); - - TransactionState txState = mock( TransactionState.class ); - KernelStatement statement = mock( KernelStatement.class ); - when( statement.hasTxStateWithChanges() ).thenReturn( true ); - when( statement.txState() ).thenReturn( txState ); - StorageStatement storageStatement = mock( StorageStatement.class ); - when( statement.getStoreStatement() ).thenReturn( storageStatement ); - when( txState.indexUpdatesForRangeSeek( index, ValueGroup.NUMBER, lower, true, upper, false ) ) - .thenReturn( createDiffSets() ); - when( txState.addedAndRemovedNodes() ).thenReturn( - new DiffSets<>( Collections.singleton( 45L ), Collections.singleton( 46L ) ) - ); - StoreReadLayer storeReadLayer = mock( StoreReadLayer.class ); - when( txState.augmentSingleNodeCursor( any( Cursor.class ), anyLong() ) ).thenAnswer( invocationOnMock -> - { - long nodeId = invocationOnMock.getArgument( 1 ); - when( txState.augmentSinglePropertyCursor( any( Cursor.class ), isNull(), - eq( propertyKey ) ) ) - .thenReturn( asPropertyCursor( new PropertyKeyValue( propertyKey, Values.of( inRange ) ) ) ); - return asNodeCursor( nodeId, nodeId + 20000 ); - } ); - - IndexReader indexReader = addMockedIndexReader( storageStatement ); - RangePredicate indexQuery = - IndexQuery.range( index.schema().getPropertyId(), lower.asObject(), true, upper.asObject(), false ); - when( indexReader.query( indexQuery ) ).thenReturn( - PrimitiveLongCollections.resourceIterator( PrimitiveLongCollections.iterator( 43L, 44L, 46L ), null ) - ); - when( storageStatement.acquireSingleNodeCursor( anyLong() ) ).thenAnswer( invocationOnMock -> - { - long nodeId = invocationOnMock.getArgument( 0 ); - when( storeReadLayer.nodeGetProperty( eq( storageStatement ), any( NodeItem.class ), eq( propertyKey ), - any( AssertOpen.class ) ) ) - .thenReturn( asPropertyCursor( new PropertyKeyValue( propertyKey, Values.of( inRange ) ) ) ); - return asNodeCursor( nodeId, nodeId + 20000 ); - } ); - - StateHandlingStatementOperations context = newTxStateOps( storeReadLayer ); - - // When - PrimitiveLongIterator results = context.indexQuery( statement, index, indexQuery ); - - // Then - assertEquals( asSet( 42L, 43L ), PrimitiveLongCollections.toSet( results ) ); - } - - @Test - public void shouldConsiderTransactionStateDuringIndexBetweenRangeSeekByStringWithIndexQuery() throws Exception - { - // Given - TransactionState txState = mock( TransactionState.class ); - KernelStatement statement = mock( KernelStatement.class ); - when( statement.hasTxStateWithChanges() ).thenReturn( true ); - when( statement.txState() ).thenReturn( txState ); - when( txState.indexUpdatesForRangeSeek( index, ValueGroup.TEXT, stringValue( "Anne" ), true, stringValue( "Bill" ), false ) ) - .thenReturn( createDiffSets() ); - when( txState.addedAndRemovedNodes() ).thenReturn( - new DiffSets<>( Collections.singleton( 45L ), Collections.singleton( 46L ) ) - ); - - StoreReadLayer storeReadLayer = mock( StoreReadLayer.class ); - IndexReader indexReader = addMockedIndexReader( statement ); - RangePredicate rangePredicate = - IndexQuery.range( index.schema().getPropertyId(), "Anne", true, "Bill", false ); - when( indexReader.query( rangePredicate ) ).thenReturn( - PrimitiveLongCollections.resourceIterator( PrimitiveLongCollections.iterator( 43L, 44L, 46L ), null ) ); - - StateHandlingStatementOperations context = newTxStateOps( storeReadLayer ); - - // When - PrimitiveLongIterator results = context.indexQuery( - statement, index, rangePredicate ); - - // Then - assertEquals( asSet( 42L, 43L ), PrimitiveLongCollections.toSet( results ) ); - } - - @Test - public void indexQueryClosesIndexReader() throws Exception - { - KernelStatement kernelStatement = mock( KernelStatement.class ); - StoreStatement storeStatement = mock( StoreStatement.class ); - IndexReader indexReader = mock( IndexReader.class ); - - when( indexReader.query( any() ) ).thenReturn( PrimitiveLongResourceCollections.emptyIterator() ); - when( storeStatement.getFreshIndexReader( any() ) ).thenReturn( indexReader ); - when( kernelStatement.getStoreStatement() ).thenReturn( storeStatement ); - - StateHandlingStatementOperations operations = newTxStateOps( mock( StoreReadLayer.class ) ); - - operations.nodeGetFromUniqueIndexSeek( - kernelStatement, - SchemaIndexDescriptorFactory.uniqueForLabel( 1, 1 ), - IndexQuery.exact( 1, "foo" ) ); - - verify( indexReader ).close(); - } - - @Test - public void shouldNotRecordNodeSetPropertyOnSameValue() throws Exception - { - // GIVEN - int propertyKeyId = 5; - long nodeId = 0; - Value value = Values.of( "The value" ); - KernelStatement kernelStatement = mock( KernelStatement.class ); - StoreStatement storeStatement = mock( StoreStatement.class ); - DataWriteOperations dataWriteOperations = mock( DataWriteOperations.class ); - Cursor ourNode = nodeCursorWithProperty( propertyKeyId ); - when( storeStatement.acquireSingleNodeCursor( nodeId ) ).thenReturn( ourNode ); - when( kernelStatement.getStoreStatement() ).thenReturn( storeStatement ); - when( kernelStatement.dataWriteOperations() ).thenReturn( dataWriteOperations ); - InternalAutoIndexing autoIndexing = mock( InternalAutoIndexing.class ); - AutoIndexOperations autoIndexOps = mock( AutoIndexOperations.class ); - when( autoIndexing.nodes() ).thenReturn( autoIndexOps ); - when( autoIndexing.relationships() ).thenReturn( AutoIndexOperations.UNSUPPORTED ); - StoreReadLayer storeReadLayer = mock( StoreReadLayer.class ); - Cursor propertyItemCursor = propertyCursor( propertyKeyId, value ); - when( storeReadLayer.nodeGetProperty( eq( storeStatement ), any( NodeItem.class ), - eq( propertyKeyId ), any( AssertOpen.class ) ) ).thenReturn( propertyItemCursor ); - StateHandlingStatementOperations operations = newTxStateOps( storeReadLayer, autoIndexing ); - - // WHEN - Value newValue = Values.of( "The value" ); - operations.nodeSetProperty( kernelStatement, nodeId, propertyKeyId, newValue ); - - // THEN - assertFalse( kernelStatement.hasTxStateWithChanges() ); - // although auto-indexing should still be notified - verify( autoIndexOps ).propertyChanged( - any( DataWriteOperations.class ), eq( nodeId ), - eq( propertyKeyId ), eq( value ), eq( newValue ) ); - } - - @Test - public void shouldNotRecordRelationshipSetPropertyOnSameValue() throws Exception - { - // GIVEN - int propertyKeyId = 5; - long relationshipId = 0; - Value value = Values.of( "The value" ); - KernelStatement kernelStatement = mock( KernelStatement.class ); - StoreStatement storeStatement = mock( StoreStatement.class ); - DataWriteOperations dataWriteOperations = mock( DataWriteOperations.class ); - Cursor ourRelationship = relationshipCursorWithProperty( propertyKeyId ); - when( storeStatement.acquireSingleRelationshipCursor( relationshipId ) ).thenReturn( ourRelationship ); - when( kernelStatement.getStoreStatement() ).thenReturn( storeStatement ); - when( kernelStatement.dataWriteOperations() ).thenReturn( dataWriteOperations ); - InternalAutoIndexing autoIndexing = mock( InternalAutoIndexing.class ); - AutoIndexOperations autoIndexOps = mock( AutoIndexOperations.class ); - when( autoIndexing.nodes() ).thenReturn( AutoIndexOperations.UNSUPPORTED ); - when( autoIndexing.relationships() ).thenReturn( autoIndexOps ); - StoreReadLayer storeReadLayer = mock( StoreReadLayer.class ); - Cursor propertyItemCursor = propertyCursor( propertyKeyId, value ); - when( storeReadLayer.relationshipGetProperty( eq( storeStatement ), any( RelationshipItem.class ), - eq( propertyKeyId ), any( AssertOpen.class ) ) ).thenReturn( propertyItemCursor ); - StateHandlingStatementOperations operations = newTxStateOps( storeReadLayer, autoIndexing ); - - // WHEN - Value newValue = Values.of( "The value" ); - operations.relationshipSetProperty( kernelStatement, relationshipId, propertyKeyId, newValue ); - - // THEN - assertFalse( kernelStatement.hasTxStateWithChanges() ); - // although auto-indexing should still be notified - verify( autoIndexOps ).propertyChanged( - eq( dataWriteOperations ), eq( relationshipId ), - eq( propertyKeyId ), eq( newValue ), eq( newValue ) ); - } - - @Test - public void shouldNotRecordGraphSetPropertyOnSameValue() - { - // GIVEN - int propertyKeyId = 5; - Value value = Values.of( "The value" ); - KernelStatement kernelStatement = mock( KernelStatement.class ); - StoreStatement storeStatement = mock( StoreStatement.class ); - when( kernelStatement.getStoreStatement() ).thenReturn( storeStatement ); - when( inner.graphGetAllProperties() ).thenReturn( iterator( new PropertyKeyValue( propertyKeyId, value ) ) ); - StateHandlingStatementOperations operations = newTxStateOps( inner ); - - // WHEN - Value newValue = Values.of( "The value" ); - operations.graphSetProperty( kernelStatement, propertyKeyId, newValue ); - - // THEN - assertFalse( kernelStatement.hasTxStateWithChanges() ); - } - - @Test - public void shouldNotDecorateNumberQuerResultsWIthLookupFilterIfIndexHasFullNumberPrecision() throws Exception - { - // given - int propertyKeyId = 5; - long nodeId = 567; - AtomicBoolean nodeCursorCalled = new AtomicBoolean(); - KernelStatement kernelStatement = mock( KernelStatement.class ); - StoreStatement storeStatement = mock( StoreStatement.class ); - when( storeStatement.acquireSingleNodeCursor( nodeId ) ).thenAnswer( invocation -> - { - nodeCursorCalled.set( true ); - return null; - } ); - when( kernelStatement.getStoreStatement() ).thenReturn( storeStatement ); - IndexReader indexReader = mock( IndexReader.class ); - when( indexReader.hasFullValuePrecision( any() ) ).thenReturn( true ); - when( indexReader.query( any() ) ) - .thenAnswer( invocation -> PrimitiveLongResourceCollections.iterator( null, nodeId ) ); - when( storeStatement.getFreshIndexReader( any() ) ).thenReturn( indexReader ); - when( storeStatement.getIndexReader( any() ) ).thenReturn( indexReader ); - - StateHandlingStatementOperations operations = newTxStateOps( inner ); - - // when - operations.nodeGetFromUniqueIndexSeek( kernelStatement, index, IndexQuery.exact( propertyKeyId, 12345L ) ); - operations.indexQuery( kernelStatement, index, IndexQuery.exact( propertyKeyId, 12345L ) ); - operations.indexQuery( kernelStatement, index, - IndexQuery.range( propertyKeyId, Long.MIN_VALUE, true, Long.MAX_VALUE, false ) ); - - // then - assertFalse( nodeCursorCalled.get() ); - } - - private Cursor nodeCursorWithProperty( long propertyKeyId ) - { - NodeItem item = mock( NodeItem.class ); - when( item.nextPropertyId()).thenReturn( propertyKeyId ); - return StubCursors.cursor( item ); - } - - private Cursor relationshipCursorWithProperty( long propertyKeyId ) - { - RelationshipItem item = mock( RelationshipItem.class ); - when( item.nextPropertyId() ).thenReturn( propertyKeyId ); - return StubCursors.cursor( item ); - } - - private Cursor propertyCursor( long propertyKeyId, Value value ) - { - PropertyItem propertyItem = mock( PropertyItem.class ); - when( propertyItem.propertyKeyId() ).thenReturn( (int) propertyKeyId ); - when( propertyItem.value() ).thenReturn( value ); - return StubCursors.cursor( propertyItem ); - } - - private StateHandlingStatementOperations newTxStateOps( StoreReadLayer delegate ) - { - return newTxStateOps( delegate, mock( InternalAutoIndexing.class ) ); - } - - private StateHandlingStatementOperations newTxStateOps( StoreReadLayer delegate, AutoIndexing autoIndexing ) - { - return new StateHandlingStatementOperations( delegate, - autoIndexing, mock( ConstraintIndexCreator.class ), - mock( ExplicitIndexStore.class ), mock( IndexingService.class ) ); - } - - private IndexReader addMockedIndexReader( KernelStatement kernelStatement ) throws IndexNotFoundKernelException - { - StorageStatement storageStatement = mock( StorageStatement.class ); - when( kernelStatement.getStoreStatement() ).thenReturn( storageStatement ); - return addMockedIndexReader( storageStatement ); - } - - private IndexReader addMockedIndexReader( StorageStatement storeStatement ) - throws IndexNotFoundKernelException - { - IndexReader indexReader = mock( IndexReader.class ); - when( storeStatement.getIndexReader( any( SchemaIndexDescriptor.class ) ) ).thenReturn( indexReader ); - return indexReader; - } - - private static PrimitiveLongDiffSets createDiffSets() - { - return new PrimitiveLongDiffSets( setOf( 42L ), setOf( 44L ), OnHeapCollectionsFactory.INSTANCE ); - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/StateOperationsAutoIndexingTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/StateOperationsAutoIndexingTest.java deleted file mode 100644 index 6772bd515e57f..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/state/StateOperationsAutoIndexingTest.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api.state; - -import org.junit.Before; -import org.junit.Test; - -import org.neo4j.collection.primitive.PrimitiveIntCollections; -import org.neo4j.internal.kernel.api.exceptions.InvalidTransactionTypeKernelException; -import org.neo4j.kernel.api.AssertOpen; -import org.neo4j.kernel.api.DataWriteOperations; -import org.neo4j.kernel.api.explicitindex.AutoIndexing; -import org.neo4j.kernel.impl.api.KernelStatement; -import org.neo4j.kernel.impl.api.StateHandlingStatementOperations; -import org.neo4j.kernel.impl.api.explicitindex.InternalAutoIndexOperations; -import org.neo4j.kernel.impl.api.explicitindex.InternalAutoIndexing; -import org.neo4j.kernel.impl.api.index.IndexingService; -import org.neo4j.kernel.impl.index.ExplicitIndexStore; -import org.neo4j.storageengine.api.NodeItem; -import org.neo4j.storageengine.api.PropertyItem; -import org.neo4j.storageengine.api.RelationshipItem; -import org.neo4j.storageengine.api.StorageStatement; -import org.neo4j.storageengine.api.StoreReadLayer; -import org.neo4j.values.storable.Value; -import org.neo4j.values.storable.Values; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.RETURNS_MOCKS; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.kernel.impl.api.state.StubCursors.cursor; -import static org.neo4j.kernel.impl.util.Cursors.empty; - -public class StateOperationsAutoIndexingTest -{ - // TODO: This level of mocking is a massive smell, we're violating law of demeter like nobody's business - private final InternalAutoIndexOperations nodeOps = mock( InternalAutoIndexOperations.class ); - private final InternalAutoIndexOperations relOps = mock( InternalAutoIndexOperations.class ); - private final AutoIndexing idx = mock( InternalAutoIndexing.class ); - private final StorageStatement storeStmt = mock( StorageStatement.class ); - private final DataWriteOperations writeOps = mock(DataWriteOperations.class); - private final KernelStatement stmt = mock( KernelStatement.class, RETURNS_MOCKS ); - private final StoreReadLayer storeLayer = mock( StoreReadLayer.class, RETURNS_MOCKS ); - private final StateHandlingStatementOperations context = new StateHandlingStatementOperations( - storeLayer, idx, mock(ConstraintIndexCreator.class), mock(ExplicitIndexStore.class), mock( IndexingService.class ) ); - - @Before - public void setup() throws InvalidTransactionTypeKernelException - { - when( idx.nodes() ).thenReturn( nodeOps ); - when( idx.relationships() ).thenReturn( relOps ); - when( stmt.getStoreStatement() ).thenReturn( storeStmt ); - when( stmt.dataWriteOperations() ).thenReturn( writeOps ); - } - - @Test - public void shouldSignalNodeRemovedToAutoIndex() throws Exception - { - // Given - when( storeStmt.acquireSingleNodeCursor( 1337 ) ).thenReturn( cursor( mock( NodeItem.class )) ); - - // When - context.nodeDelete( stmt, 1337 ); - - // Then - verify( nodeOps ).entityRemoved( writeOps, 1337 ); - } - - @Test - public void shouldSignalRelationshipRemovedToAutoIndex() throws Exception - { - // Given - when( storeStmt.acquireSingleRelationshipCursor( 1337 ) ).thenReturn( cursor( mock( RelationshipItem.class )) ); - - // When - context.relationshipDelete( stmt, 1337 ); - - // Then - verify( relOps ).entityRemoved( writeOps, 1337 ); - } - - @Test - public void shouldSignalNodePropertyAddedToAutoIndex() throws Exception - { - // Given - int propertyKeyId = 1; - Value value = Values.of( "Hello!" ); - - NodeItem node = mock( NodeItem.class ); - when( node.labels() ).thenReturn( PrimitiveIntCollections.emptySet() ); - when( storeStmt.acquireSingleNodeCursor( 1337 ) ).thenReturn( cursor( node ) ); - when( storeLayer.nodeGetProperty( eq( storeStmt ), any( NodeItem.class ), eq( propertyKeyId ), - any( AssertOpen.class ) ) ) - .thenReturn( cursor() ); - - // When - context.nodeSetProperty( stmt, 1337, propertyKeyId, value ); - - // Then - verify( nodeOps ).propertyAdded( writeOps, 1337, propertyKeyId, value ); - } - - @Test - public void shouldSignalRelationshipPropertyAddedToAutoIndex() throws Exception - { - // Given - int propertyKeyId = 1; - Value value = Values.of( "Hello!" ); - - RelationshipItem relationship = mock( RelationshipItem.class ); - when( storeStmt.acquireSingleRelationshipCursor( 1337 ) ).thenReturn( cursor( relationship ) ); - when( storeLayer.relationshipGetProperty( storeStmt, relationship, propertyKeyId, AssertOpen.ALWAYS_OPEN ) ) - .thenReturn( empty() ); - - // When - context.relationshipSetProperty( stmt, 1337, propertyKeyId, value ); - - // Then - verify( relOps ).propertyAdded( writeOps, 1337, propertyKeyId, value ); - } - - @Test - public void shouldSignalNodePropertyChangedToAutoIndex() throws Exception - { - // Given - int propertyKeyId = 1; - Value value = Values.of( "Hello!" ); - PropertyItem existingProperty = mock( PropertyItem.class ); - - when(existingProperty.propertyKeyId()).thenReturn( propertyKeyId ); - when(existingProperty.value()).thenReturn( Values.of( "Goodbye!" ) ); - - NodeItem node = mock( NodeItem.class ); - when( node.labels() ).thenReturn( PrimitiveIntCollections.emptySet() ); - when( storeStmt.acquireSingleNodeCursor( 1337 ) ).thenReturn( cursor( node ) ); - when( storeLayer.nodeGetProperty( eq( storeStmt ), any( NodeItem.class ), eq( propertyKeyId ), - any( AssertOpen.class ) ) ) - .thenReturn( cursor( existingProperty ) ); - - // When - context.nodeSetProperty( stmt, 1337, propertyKeyId, value ); - - // Then - verify( nodeOps ).propertyChanged( eq(writeOps), eq(1337L), - eq( propertyKeyId ), any( Value.class ), eq( value ) ); - } - - @Test - public void shouldSignalRelationshipPropertyChangedToAutoIndex() throws Exception - { - // Given - int propertyKeyId = 1; - Value value = Values.of( "Hello!" ); - PropertyItem existingProperty = mock( PropertyItem.class ); - - when(existingProperty.propertyKeyId()).thenReturn( propertyKeyId ); - when(existingProperty.value()).thenReturn( Values.of( "Goodbye!" ) ); - - RelationshipItem relationship = mock( RelationshipItem.class ); - when( storeStmt.acquireSingleRelationshipCursor( 1337 ) ).thenReturn( cursor( relationship ) ); - when( storeLayer.relationshipGetProperty( storeStmt, relationship, propertyKeyId, stmt ) ) - .thenReturn( cursor( existingProperty ) ); - - // When - context.relationshipSetProperty( stmt, 1337, propertyKeyId, value ); - - // Then - verify( relOps ).propertyChanged( eq( writeOps ), eq( 1337L ), - eq( propertyKeyId ), any( Value.class ), eq( value ) ); - } - - @Test - public void shouldSignalNodePropertyRemovedToAutoIndex() throws Exception - { - // Given - PropertyItem existingProperty = mock( PropertyItem.class ); - when( existingProperty.propertyKeyId() ).thenReturn( 1 ); - when( existingProperty.value() ).thenReturn( Values.of( "Goodbye!" ) ); - int propertyKeyId = existingProperty.propertyKeyId(); - - NodeItem node = mock( NodeItem.class ); - when( storeLayer.nodeGetProperty( eq( storeStmt ), any( NodeItem.class ), eq( propertyKeyId ), - any( AssertOpen.class ) ) ) - .thenReturn( cursor( existingProperty ) ); - when( node.labels() ).thenReturn( PrimitiveIntCollections.emptySet() ); - when( storeStmt.acquireSingleNodeCursor( 1337 ) ).thenReturn( cursor( node ) ); - - // When - context.nodeRemoveProperty( stmt, 1337, propertyKeyId ); - - // Then - verify( nodeOps ).propertyRemoved( writeOps, 1337L, propertyKeyId ); - } - - @Test - public void shouldSignalRelationshipPropertyRemovedToAutoIndex() throws Exception - { - // Given - PropertyItem existingProperty = mock( PropertyItem.class ); - - int propertyKeyId = 1; - when( existingProperty.propertyKeyId() ).thenReturn( propertyKeyId ); - when( existingProperty.value() ).thenReturn( Values.of( "Goodbye!" ) ); - - RelationshipItem relationship = mock( RelationshipItem.class ); - when( storeStmt.acquireSingleRelationshipCursor( 1337 ) ).thenReturn( cursor( relationship ) ); - when( storeLayer.relationshipGetProperty( storeStmt, relationship, propertyKeyId, stmt ) ) - .thenReturn( cursor( existingProperty ) ); - - // When - context.relationshipRemoveProperty( stmt, 1337, existingProperty.propertyKeyId() ); - - // Then - verify( relOps ).propertyRemoved( writeOps, 1337L, existingProperty.propertyKeyId() ); - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/store/StorageLayerTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/store/StorageLayerTest.java index ab085e1cb898b..b11412433bbb8 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/api/store/StorageLayerTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/api/store/StorageLayerTest.java @@ -35,9 +35,7 @@ import org.neo4j.kernel.impl.api.ClockContext; import org.neo4j.kernel.impl.api.KernelStatement; import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge; -import org.neo4j.kernel.impl.factory.CanWrite; import org.neo4j.kernel.impl.locking.LockTracer; -import org.neo4j.kernel.impl.proc.Procedures; import org.neo4j.kernel.internal.GraphDatabaseAPI; import org.neo4j.storageengine.api.StorageEngine; import org.neo4j.storageengine.api.StoreReadLayer; @@ -68,7 +66,7 @@ public void before() db = (GraphDatabaseAPI) createGraphDatabase(); DependencyResolver resolver = db.getDependencyResolver(); this.disk = resolver.resolveDependency( StorageEngine.class ).storeReadLayer(); - this.state = new KernelStatement( null, null, disk.newStatement(), new Procedures(), new CanWrite(), + this.state = new KernelStatement( null, null, disk.newStatement(), LockTracer.NONE, null, new ClockContext(), EmptyVersionContextSupplier.EMPTY ); } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/factory/GraphDatabaseFacadeTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/factory/GraphDatabaseFacadeTest.java index 3a32c2e4f53ca..b71514eac682c 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/factory/GraphDatabaseFacadeTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/factory/GraphDatabaseFacadeTest.java @@ -32,7 +32,6 @@ import org.neo4j.graphdb.factory.GraphDatabaseSettings; 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.configuration.Config; import org.neo4j.kernel.guard.Guard; @@ -53,7 +52,6 @@ public class GraphDatabaseFacadeTest private final GraphDatabaseFacade.SPI spi = Mockito.mock( GraphDatabaseFacade.SPI.class, RETURNS_DEEP_STUBS ); private final GraphDatabaseFacade graphDatabaseFacade = new GraphDatabaseFacade(); private GraphDatabaseQueryService queryService; - private ReadOperations readOperations; @Rule public final ExpectedException expectedException = ExpectedException.none(); @@ -65,7 +63,6 @@ public void setUp() DependencyResolver resolver = mock( DependencyResolver.class ); EditionModule editionModule = mock( EditionModule.class ); Statement statement = mock( Statement.class, RETURNS_DEEP_STUBS ); - readOperations = mock( ReadOperations.class ); ThreadToStatementContextBridge contextBridge = mock( ThreadToStatementContextBridge.class ); when( spi.queryService() ).thenReturn( queryService ); @@ -76,7 +73,6 @@ public void setUp() when( contextBridge.get() ).thenReturn( statement ); Config config = Config.defaults(); when( resolver.resolveDependency( Config.class ) ).thenReturn( config ); - when( statement.readOperations() ).thenReturn( readOperations ); graphDatabaseFacade.init( editionModule, spi, guard, contextBridge, config, mock( RelationshipTypeTokenHolder.class ) ); } diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/newapi/MockStore.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/newapi/MockStore.java index 2d83d9cc2bcd9..134dbe75116cd 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/newapi/MockStore.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/newapi/MockStore.java @@ -232,7 +232,6 @@ public long countsForNodeWithoutTxState( int labelId ) public long countsForRelationship( int startLabelId, int typeId, int endLabelId ) { throw new UnsupportedOperationException(); - } @Override @@ -241,6 +240,18 @@ public long countsForRelationshipWithoutTxState( int startLabelId, int typeId, i throw new UnsupportedOperationException(); } + @Override + public long nodesGetCount() + { + throw new UnsupportedOperationException(); + } + + @Override + public long relationshipsGetCount() + { + throw new UnsupportedOperationException(); + } + @Override public boolean relationshipExists( long reference ) { diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/recovery/KernelRecoveryTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/recovery/KernelRecoveryTest.java index 07f971a80c3d2..62ca5cafd5aac 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/recovery/KernelRecoveryTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/recovery/KernelRecoveryTest.java @@ -30,7 +30,7 @@ import org.neo4j.graphdb.mockfs.EphemeralFileSystemAbstraction; import org.neo4j.graphdb.mockfs.UncloseableDelegatingFileSystemAbstraction; import org.neo4j.io.fs.FileSystemAbstraction; -import org.neo4j.kernel.api.ReadOperations; +import org.neo4j.kernel.api.StatementConstants; import org.neo4j.kernel.impl.transaction.command.Command.NodeCommand; import org.neo4j.kernel.impl.transaction.command.Command.NodeCountsCommand; import org.neo4j.kernel.impl.transaction.log.LogPosition; @@ -75,11 +75,11 @@ public void shouldHandleWritesProperlyAfterRecovery() throws Exception assertThat( logEntries( crashedFs, logFile ), containsExactly( // Tx before recovery startEntry( -1, -1 ), commandEntry( node1, NodeCommand.class ), - commandEntry( ReadOperations.ANY_LABEL, NodeCountsCommand.class ), commitEntry( 2 ), + commandEntry( StatementConstants.ANY_LABEL, NodeCountsCommand.class ), commitEntry( 2 ), // Tx after recovery startEntry( -1, -1 ), commandEntry( node2, NodeCommand.class ), - commandEntry( ReadOperations.ANY_LABEL, NodeCountsCommand.class ), commitEntry( 3 ), + commandEntry( StatementConstants.ANY_LABEL, NodeCountsCommand.class ), commitEntry( 3 ), // checkpoint checkPoint( new LogPosition( 0, 250 ) ) ) ); diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/GraphDbStructureGuideTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/GraphDbStructureGuideTest.java index 35e120b819002..f93bdf2864e27 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/GraphDbStructureGuideTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/util/dbstructure/GraphDbStructureGuideTest.java @@ -46,8 +46,8 @@ import static org.mockito.Mockito.verify; import static org.neo4j.graphdb.Label.label; import static org.neo4j.graphdb.RelationshipType.withName; -import static org.neo4j.kernel.api.ReadOperations.ANY_LABEL; -import static org.neo4j.kernel.api.ReadOperations.ANY_RELATIONSHIP_TYPE; +import static org.neo4j.kernel.api.StatementConstants.ANY_LABEL; +import static org.neo4j.kernel.api.StatementConstants.ANY_RELATIONSHIP_TYPE; import static org.neo4j.kernel.impl.api.store.DefaultIndexReference.toDescriptor; public class GraphDbStructureGuideTest diff --git a/community/kernel/src/test/java/org/neo4j/unsafe/impl/batchimport/input/csv/CsvInputBatchImportIT.java b/community/kernel/src/test/java/org/neo4j/unsafe/impl/batchimport/input/csv/CsvInputBatchImportIT.java index 6875fb8ff6283..c66f8b44380a3 100644 --- a/community/kernel/src/test/java/org/neo4j/unsafe/impl/batchimport/input/csv/CsvInputBatchImportIT.java +++ b/community/kernel/src/test/java/org/neo4j/unsafe/impl/batchimport/input/csv/CsvInputBatchImportIT.java @@ -49,8 +49,8 @@ import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; -import java.util.function.Function; import java.util.function.Consumer; +import java.util.function.Function; import java.util.function.Supplier; import org.neo4j.graphdb.GraphDatabaseService; @@ -59,7 +59,7 @@ import org.neo4j.graphdb.Relationship; import org.neo4j.graphdb.Transaction; import org.neo4j.helpers.collection.Pair; -import org.neo4j.kernel.api.ReadOperations; +import org.neo4j.kernel.api.StatementConstants; import org.neo4j.kernel.configuration.Config; import org.neo4j.kernel.impl.logging.NullLogService; import org.neo4j.kernel.impl.storageengine.impl.recordstorage.RecordStorageEngine; @@ -77,21 +77,19 @@ import org.neo4j.unsafe.impl.batchimport.BatchImporter; import org.neo4j.unsafe.impl.batchimport.Configuration; import org.neo4j.unsafe.impl.batchimport.ParallelBatchImporter; -import org.neo4j.unsafe.impl.batchimport.input.InputEntity; import org.neo4j.unsafe.impl.batchimport.input.Collector; import org.neo4j.unsafe.impl.batchimport.input.Group; import org.neo4j.unsafe.impl.batchimport.input.Input; +import org.neo4j.unsafe.impl.batchimport.input.InputEntity; import org.neo4j.values.storable.CoordinateReferenceSystem; import org.neo4j.values.storable.PointValue; -import static org.hamcrest.Matchers.greaterThanOrEqualTo; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThat; - import static java.lang.String.format; import static java.lang.System.currentTimeMillis; import static java.nio.charset.Charset.defaultCharset; - +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; import static org.neo4j.graphdb.factory.GraphDatabaseSettings.db_timezone; import static org.neo4j.helpers.collection.Iterators.asSet; import static org.neo4j.kernel.impl.util.AutoCreatingHashMap.nested; @@ -391,7 +389,7 @@ private void verifyImportedData( List nodeData, NeoStores neoStores = ((GraphDatabaseAPI)db).getDependencyResolver().resolveDependency( RecordStorageEngine.class ).testAccessNeoStores(); Function labelTranslationTable = - translationTable( neoStores.getLabelTokenStore(), ReadOperations.ANY_LABEL ); + translationTable( neoStores.getLabelTokenStore(), StatementConstants.ANY_LABEL ); for ( Pair count : allNodeCounts( labelTranslationTable, expectedNodeCounts ) ) { assertEquals( "Label count mismatch for label " + count.first(), @@ -402,7 +400,7 @@ private void verifyImportedData( List nodeData, } Function relationshipTypeTranslationTable = - translationTable( neoStores.getRelationshipTypeTokenStore(), ReadOperations.ANY_RELATIONSHIP_TYPE ); + translationTable( neoStores.getRelationshipTypeTokenStore(), StatementConstants.ANY_RELATIONSHIP_TYPE ); for ( Pair count : allRelationshipCounts( labelTranslationTable, relationshipTypeTranslationTable, expectedRelationshipCounts ) ) { diff --git a/community/lucene-index/src/test/java/org/neo4j/kernel/api/impl/schema/DefaultSchemaIndexConfigTest.java b/community/lucene-index/src/test/java/org/neo4j/kernel/api/impl/schema/DefaultSchemaIndexConfigTest.java index 3f746e6a997fb..df27d975776ef 100644 --- a/community/lucene-index/src/test/java/org/neo4j/kernel/api/impl/schema/DefaultSchemaIndexConfigTest.java +++ b/community/lucene-index/src/test/java/org/neo4j/kernel/api/impl/schema/DefaultSchemaIndexConfigTest.java @@ -27,11 +27,11 @@ import org.neo4j.graphdb.Transaction; import org.neo4j.graphdb.factory.GraphDatabaseBuilder; import org.neo4j.graphdb.factory.GraphDatabaseSettings; -import org.neo4j.kernel.api.ReadOperations; -import org.neo4j.kernel.api.Statement; +import org.neo4j.internal.kernel.api.CapableIndexReference; +import org.neo4j.internal.kernel.api.TokenRead; +import org.neo4j.kernel.api.KernelTransaction; import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; import org.neo4j.kernel.api.index.IndexProvider; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptorFactory; import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge; import org.neo4j.kernel.internal.GraphDatabaseAPI; import org.neo4j.test.TestGraphDatabaseFactory; @@ -103,14 +103,18 @@ public void shouldUseConfiguredIndexProviderNative20() throws IndexNotFoundKerne private void assertIndexProvider( GraphDatabaseService db, IndexProvider.Descriptor expected ) throws IndexNotFoundKernelException { GraphDatabaseAPI graphDatabaseAPI = (GraphDatabaseAPI) db; - try ( Transaction tx = graphDatabaseAPI.beginTx(); - Statement statement = graphDatabaseAPI.getDependencyResolver().resolveDependency( ThreadToStatementContextBridge.class ).get() ) + try ( Transaction tx = graphDatabaseAPI.beginTx() ) { - ReadOperations readOperations = statement.readOperations(); - int labelId = readOperations.labelGetForName( LABEL.name() ); - int propertyId = readOperations.propertyKeyGetForName( KEY ); - IndexProvider.Descriptor descriptor = readOperations.indexGetProviderDescriptor( SchemaIndexDescriptorFactory.forLabel( labelId, propertyId ) ); - assertEquals( "expected IndexProvider.Descriptor", expected, descriptor ); + KernelTransaction ktx = graphDatabaseAPI.getDependencyResolver() + .resolveDependency( ThreadToStatementContextBridge.class ) + .getKernelTransactionBoundToThisThread( true ); + TokenRead tokenRead = ktx.tokenRead(); + int labelId = tokenRead.nodeLabel( LABEL.name() ); + int propertyId = tokenRead.propertyKey( KEY ); + CapableIndexReference index = ktx.schemaRead().index( labelId, propertyId ); + + assertEquals( "expected IndexProvider.Descriptor", expected, + new IndexProvider.Descriptor( index.providerKey(), index.providerVersion() ) ); tx.success(); } } diff --git a/community/lucene-index/src/test/java/org/neo4j/kernel/impl/api/OperationsFacadeSchemaIndexIteratorTest.java b/community/lucene-index/src/test/java/org/neo4j/kernel/impl/api/OperationsFacadeSchemaIndexIteratorTest.java deleted file mode 100644 index 0a579c6e71200..0000000000000 --- a/community/lucene-index/src/test/java/org/neo4j/kernel/impl/api/OperationsFacadeSchemaIndexIteratorTest.java +++ /dev/null @@ -1,766 +0,0 @@ -/* - * 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 . - */ -package org.neo4j.kernel.impl.api; - -import org.junit.Assume; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.RuleChain; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import org.neo4j.collection.primitive.PrimitiveLongCollections; -import org.neo4j.collection.primitive.PrimitiveLongIterator; -import org.neo4j.graphdb.Label; -import org.neo4j.graphdb.Node; -import org.neo4j.graphdb.Transaction; -import org.neo4j.internal.kernel.api.IndexQuery; -import org.neo4j.kernel.api.ReadOperations; -import org.neo4j.kernel.api.Statement; -import org.neo4j.kernel.api.exceptions.index.IndexNotApplicableKernelException; -import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptorFactory; -import org.neo4j.test.rule.DatabaseRule; -import org.neo4j.test.rule.EmbeddedDatabaseRule; -import org.neo4j.test.rule.RandomRule; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder; -import static org.junit.Assert.assertThat; - -/** - * Does test having multiple iterators open on the same index - *

    - *
  • Exhaust variations:
  • - *
      - *
    • Exhaust iterators one by one
    • - *
    • Nesting
    • - *
    • Interleaved
    • - *
    - *
  • Happy case for schema index iterators on static db for:
  • - *
      - *
    • Single property number index
    • - *
    • Single property string index
    • - *
    • Composite property number index
    • - *
    • Composite property string index
    • - *
    - *
  • For index queries:
  • - *
      - *
    • {@link IndexQuery#exists(int)}
    • - *
    • {@link IndexQuery#exact(int, Object)}
    • - *
    • {@link IndexQuery#range(int, Number, boolean, Number, boolean)}
    • - *
    • {@link IndexQuery#range(int, String, boolean, String, boolean)}
    • - *
    - *
- * Does NOT test - *
    - *
  • Single property unique number index
  • - *
  • Single property unique string index
  • - *
  • Composite property mixed index
  • - *
  • {@link IndexQuery#stringPrefix(int, String)}
  • - *
  • {@link IndexQuery#stringSuffix(int, String)}
  • - *
  • {@link IndexQuery#stringContains(int, String)}
  • - *
  • Composite property node key index (due to it being enterprise feature)
  • - *
  • Label index iterators
  • - *
  • Concurrency
  • - *
  • Locking
  • - *
  • Cluster
  • - *
  • Index creation
  • - *
- * Code navigation: - */ -@RunWith( Parameterized.class ) -public class OperationsFacadeSchemaIndexIteratorTest -{ - private interface IndexCoordinatorFactory - { - IndexCoordinator create( Label indexLabel, String numberProp1, String numberProp2, String stringProp1, String stringProp2 ); - } - - private final DatabaseRule db = new EmbeddedDatabaseRule(); - - private static final RandomRule rnd = new RandomRule(); - @Rule - public RuleChain ruleChain = RuleChain.outerRule( rnd ).around( db ); - - private static final Label indexLabel = Label.label( "IndexLabel" ); - - private static final String numberProp1 = "numberProp1"; - private static final String numberProp2 = "numberProp2"; - private static final String stringProp1 = "stringProp1"; - private static final String stringProp2 = "stringProp2"; - - @Parameterized.Parameters( name = "{0}" ) - public static Collection params() - { - return Arrays.asList( - new Object[]{"Single number non unique", (IndexCoordinatorFactory) NumberIndexCoordinator::new}, - new Object[]{"Single string non unique", (IndexCoordinatorFactory) StringIndexCoordinator::new}, - new Object[]{"Composite number non unique", (IndexCoordinatorFactory) NumberCompositeIndexCoordinator::new}, - new Object[]{"Composite string non unique", (IndexCoordinatorFactory) StringCompositeIndexCoordinator::new} - ); - } - - @Parameterized.Parameter( 0 ) - public String name; - - @Parameterized.Parameter( 1 ) - public IndexCoordinatorFactory indexCoordinatorFactory; - - private IndexCoordinator indexCoordinator; - - @Before - public void setupDb() - { - indexCoordinator = indexCoordinatorFactory.create( indexLabel, numberProp1, numberProp2, stringProp1, stringProp2 ); - indexCoordinator.init( db ); - indexCoordinator.createIndex( db ); - } - - @Test - public void multipleIteratorsNotNestedExists() throws Exception - { - - try ( Transaction tx = db.beginTx(); - Statement statement = db.statement() ) - { - // when - ReadOperations readOperations = statement.readOperations(); - PrimitiveLongIterator iter1 = indexCoordinator.queryExists( readOperations ); - List actual1 = PrimitiveLongCollections.asList( iter1 ); - - PrimitiveLongIterator iter2 = indexCoordinator.queryExists( readOperations ); - List actual2 = PrimitiveLongCollections.asList( iter2 ); - - // then - indexCoordinator.assertExistsResult( actual1 ); - indexCoordinator.assertExistsResult( actual2 ); - tx.success(); - } - } - - @Test - public void multipleIteratorsNotNestedExact() throws Exception - { - try ( Transaction tx = db.beginTx(); - Statement statement = db.statement() ) - { - // when - ReadOperations readOperations = statement.readOperations(); - PrimitiveLongIterator iter1 = indexCoordinator.queryExact( readOperations ); - List actual1 = PrimitiveLongCollections.asList( iter1 ); - - PrimitiveLongIterator iter2 = indexCoordinator.queryExact( readOperations ); - List actual2 = PrimitiveLongCollections.asList( iter2 ); - - // then - indexCoordinator.assertExactResult( actual1 ); - indexCoordinator.assertExactResult( actual2 ); - tx.success(); - } - } - - @Test - public void multipleIteratorsNotNestedRange() throws IndexNotApplicableKernelException, IndexNotFoundKernelException - { - Assume.assumeTrue( indexCoordinator.supportRangeQuery() ); - try ( Transaction tx = db.beginTx(); - Statement statement = db.statement() ) - { - // when - ReadOperations readOperations = statement.readOperations(); - PrimitiveLongIterator iter1 = indexCoordinator.queryRange( readOperations ); - List actual1 = PrimitiveLongCollections.asList( iter1 ); - - PrimitiveLongIterator iter2 = indexCoordinator.queryRange( readOperations ); - List actual2 = PrimitiveLongCollections.asList( iter2 ); - - // then - indexCoordinator.assertRangeResult( actual1 ); - indexCoordinator.assertRangeResult( actual2 ); - tx.success(); - } - } - - @Test - public void multipleIteratorsNestedInnerNewExists() throws Exception - { - try ( Transaction tx = db.beginTx(); - Statement statement = db.statement() ) - { - // when - ReadOperations readOperations = statement.readOperations(); - PrimitiveLongIterator iter1 = indexCoordinator.queryExists( readOperations ); - List actual1 = new ArrayList<>(); - while ( iter1.hasNext() ) - { - actual1.add( iter1.next() ); - PrimitiveLongIterator iter2 = indexCoordinator.queryExists( readOperations ); - List actual2 = PrimitiveLongCollections.asList( iter2 ); - indexCoordinator.assertExistsResult( actual2 ); - } - // then - indexCoordinator.assertExistsResult( actual1 ); - tx.success(); - } - } - - @Test - public void multipleIteratorsNestedInnerNewExact() throws Exception - { - try ( Transaction tx = db.beginTx(); - Statement statement = db.statement() ) - { - // when - ReadOperations readOperations = statement.readOperations(); - PrimitiveLongIterator iter1 = indexCoordinator.queryExact( readOperations ); - List actual1 = new ArrayList<>(); - while ( iter1.hasNext() ) - { - actual1.add( iter1.next() ); - PrimitiveLongIterator iter2 = indexCoordinator.queryExact( readOperations ); - List actual2 = PrimitiveLongCollections.asList( iter2 ); - indexCoordinator.assertExactResult( actual2 ); - } - // then - indexCoordinator.assertExactResult( actual1 ); - tx.success(); - } - } - - @Test - public void multipleIteratorsNestedInnerNewRange() throws Exception - { - Assume.assumeTrue( indexCoordinator.supportRangeQuery() ); - try ( Transaction tx = db.beginTx(); - Statement statement = db.statement() ) - { - // when - ReadOperations readOperations = statement.readOperations(); - PrimitiveLongIterator iter1 = indexCoordinator.queryRange( readOperations ); - List actual1 = new ArrayList<>(); - while ( iter1.hasNext() ) - { - actual1.add( iter1.next() ); - PrimitiveLongIterator iter2 = indexCoordinator.queryRange( readOperations ); - List actual2 = PrimitiveLongCollections.asList( iter2 ); - indexCoordinator.assertRangeResult( actual2 ); - } - // then - indexCoordinator.assertRangeResult( actual1 ); - tx.success(); - } - } - - @Test - public void multipleIteratorsNestedInterleavedExists() throws Exception - { - try ( Transaction tx = db.beginTx(); - Statement statement = db.statement() ) - { - // when - ReadOperations readOperations = statement.readOperations(); - PrimitiveLongIterator iter1 = indexCoordinator.queryExists( readOperations ); - List actual1 = new ArrayList<>(); - PrimitiveLongIterator iter2 = indexCoordinator.queryExists( readOperations ); - List actual2 = new ArrayList<>(); - - // Interleave - exhaustInterleaved( iter1, actual1, iter2, actual2 ); - - // then - indexCoordinator.assertExistsResult( actual1 ); - indexCoordinator.assertExistsResult( actual2 ); - tx.success(); - } - } - - @Test - public void multipleIteratorsNestedInterleavedExact() throws Exception - { - try ( Transaction tx = db.beginTx(); - Statement statement = db.statement() ) - { - // when - ReadOperations readOperations = statement.readOperations(); - PrimitiveLongIterator iter1 = indexCoordinator.queryExact( readOperations ); - List actual1 = new ArrayList<>(); - PrimitiveLongIterator iter2 = indexCoordinator.queryExact( readOperations ); - List actual2 = new ArrayList<>(); - - // Interleave - exhaustInterleaved( iter1, actual1, iter2, actual2 ); - - // then - indexCoordinator.assertExactResult( actual1 ); - indexCoordinator.assertExactResult( actual2 ); - tx.success(); - } - } - - @Test - public void multipleIteratorsNestedInterleavedRange() throws Exception - { - Assume.assumeTrue( indexCoordinator.supportRangeQuery() ); - try ( Transaction tx = db.beginTx(); - Statement statement = db.statement() ) - { - // when - ReadOperations readOperations = statement.readOperations(); - PrimitiveLongIterator iter1 = indexCoordinator.queryRange( readOperations ); - List actual1 = new ArrayList<>(); - PrimitiveLongIterator iter2 = indexCoordinator.queryRange( readOperations ); - List actual2 = new ArrayList<>(); - - // Interleave - exhaustInterleaved( iter1, actual1, iter2, actual2 ); - - // then - indexCoordinator.assertRangeResult( actual1 ); - indexCoordinator.assertRangeResult( actual2 ); - tx.success(); - } - } - - private void exhaustInterleaved( PrimitiveLongIterator source1, List target1, PrimitiveLongIterator source2, List target2 ) - { - while ( source1.hasNext() && source2.hasNext() ) - { - if ( rnd.nextBoolean() ) - { - target1.add( source1.next() ); - } - else - { - target2.add( source2.next() ); - } - } - - // Empty the rest - while ( source1.hasNext() ) - { - target1.add( source1.next() ); - } - while ( source2.hasNext() ) - { - target2.add( source2.next() ); - } - } - - private static class StringCompositeIndexCoordinator extends IndexCoordinator - { - StringCompositeIndexCoordinator( Label indexLabel, String numberProp1, String numberProp2, String stringProp1, String stringProp2 ) - { - super( indexLabel, numberProp1, numberProp2, stringProp1, stringProp2 ); - } - - @Override - protected SchemaIndexDescriptor extractIndexDescriptor() - { - return SchemaIndexDescriptorFactory.forLabel( indexedLabelId, stringPropId1, stringPropId2 ); - } - - @Override - boolean supportRangeQuery() - { - return false; - } - - @Override - PrimitiveLongIterator queryRange( ReadOperations readOperations ) - { - throw new UnsupportedOperationException(); - } - - @Override - PrimitiveLongIterator queryExists( ReadOperations readOperations ) - throws IndexNotApplicableKernelException, IndexNotFoundKernelException - { - return readOperations.indexQuery( schemaIndexDescriptor, - IndexQuery.exists( stringPropId1 ), - IndexQuery.exists( stringPropId2 ) ); - } - - @Override - PrimitiveLongIterator queryExact( ReadOperations readOperations ) - throws IndexNotApplicableKernelException, IndexNotFoundKernelException - { - return readOperations.indexQuery( schemaIndexDescriptor, - IndexQuery.exact( stringPropId1, stringProp1Values[0] ), - IndexQuery.exact( stringPropId2, stringProp2Values[0] ) ); - } - - @Override - void assertRangeResult( List result ) - { - throw new UnsupportedOperationException(); - } - - @Override - void assertExactResult( List actual ) - { - List expected = new ArrayList<>(); - expected.add( 0L ); - assertSameContent( actual, expected ); - } - - @Override - void doCreateIndex( DatabaseRule db ) - { - db.schema().indexFor( indexLabel ).on( stringProp1 ).on( stringProp2 ).create(); - } - } - - private static class NumberCompositeIndexCoordinator extends IndexCoordinator - { - NumberCompositeIndexCoordinator( Label indexLabel, String numberProp1, String numberProp2, String stringProp1, String stringProp2 ) - { - super( indexLabel, numberProp1, numberProp2, stringProp1, stringProp2 ); - } - - @Override - protected SchemaIndexDescriptor extractIndexDescriptor() - { - return SchemaIndexDescriptorFactory.forLabel( indexedLabelId, numberPropId1, numberPropId2 ); - } - - @Override - boolean supportRangeQuery() - { - return false; - } - - @Override - PrimitiveLongIterator queryRange( ReadOperations readOperations ) - { - throw new UnsupportedOperationException(); - } - - @Override - PrimitiveLongIterator queryExists( ReadOperations readOperations ) - throws IndexNotApplicableKernelException, IndexNotFoundKernelException - { - return readOperations.indexQuery( schemaIndexDescriptor, - IndexQuery.exists( numberPropId1 ), - IndexQuery.exists( numberPropId2 ) ); - } - - @Override - PrimitiveLongIterator queryExact( ReadOperations readOperations ) - throws IndexNotApplicableKernelException, IndexNotFoundKernelException - { - return readOperations.indexQuery( schemaIndexDescriptor, - IndexQuery.exact( numberPropId1, numberProp1Values[0] ), - IndexQuery.exact( numberPropId2, numberProp2Values[0] ) ); - } - - @Override - void assertRangeResult( List actual ) - { - throw new UnsupportedOperationException(); - } - - @Override - void assertExactResult( List actual ) - { - List expected = new ArrayList<>(); - expected.add( 0L ); - assertSameContent( actual, expected ); - } - - @Override - void doCreateIndex( DatabaseRule db ) - { - db.schema().indexFor( indexLabel ).on( numberProp1 ).on( numberProp2 ).create(); - } - } - - private static class StringIndexCoordinator extends IndexCoordinator - { - StringIndexCoordinator( Label indexLabel, String numberProp1, String numberProp2, String stringProp1, String stringProp2 ) - { - super( indexLabel, numberProp1, numberProp2, stringProp1, stringProp2 ); - } - - @Override - protected SchemaIndexDescriptor extractIndexDescriptor() - { - return SchemaIndexDescriptorFactory.forLabel( indexedLabelId, stringPropId1 ); - } - - @Override - boolean supportRangeQuery() - { - return true; - } - - @Override - PrimitiveLongIterator queryRange( ReadOperations readOperations ) - throws IndexNotApplicableKernelException, IndexNotFoundKernelException - { - // query for half the range - return readOperations.indexQuery( schemaIndexDescriptor, - IndexQuery.range( numberPropId1, stringProp1Values[0], true, stringProp1Values[numberOfNodes / 2], false ) ); - } - - @Override - PrimitiveLongIterator queryExists( ReadOperations readOperations ) - throws IndexNotApplicableKernelException, IndexNotFoundKernelException - { - return readOperations.indexQuery( schemaIndexDescriptor, IndexQuery.exists( stringPropId1 ) ); - } - - @Override - PrimitiveLongIterator queryExact( ReadOperations readOperations ) - throws IndexNotApplicableKernelException, IndexNotFoundKernelException - { - return readOperations.indexQuery( schemaIndexDescriptor, IndexQuery.exact( stringPropId1, stringProp1Values[0] ) ); - } - - @Override - void assertRangeResult( List actual ) - { - List expected = new ArrayList<>(); - for ( long i = 0; i < numberOfNodes / 2; i++ ) - { - expected.add( i ); - } - assertSameContent( actual, expected ); - } - - @Override - void assertExactResult( List actual ) - { - List expected = new ArrayList<>(); - expected.add( 0L ); - assertSameContent( actual, expected ); - } - - @Override - void doCreateIndex( DatabaseRule db ) - { - db.schema().indexFor( indexLabel ).on( stringProp1 ).create(); - } - } - - private static class NumberIndexCoordinator extends IndexCoordinator - { - NumberIndexCoordinator( Label indexLabel, String numberProp1, String numberProp2, String stringProp1, String stringProp2 ) - { - super( indexLabel, numberProp1, numberProp2, stringProp1, stringProp2 ); - } - - @Override - protected SchemaIndexDescriptor extractIndexDescriptor() - { - return SchemaIndexDescriptorFactory.forLabel( indexedLabelId, numberPropId1 ); - } - - @Override - boolean supportRangeQuery() - { - return true; - } - - @Override - PrimitiveLongIterator queryRange( ReadOperations readOperations ) - throws IndexNotApplicableKernelException, IndexNotFoundKernelException - { - // query for half the range - return readOperations.indexQuery( schemaIndexDescriptor, - IndexQuery.range( numberPropId1, numberProp1Values[0], true, numberProp1Values[numberOfNodes / 2], false ) ); - } - - @Override - PrimitiveLongIterator queryExists( ReadOperations readOperations ) - throws IndexNotApplicableKernelException, IndexNotFoundKernelException - { - return readOperations.indexQuery( schemaIndexDescriptor, IndexQuery.exists( numberPropId1 ) ); - } - - @Override - PrimitiveLongIterator queryExact( ReadOperations readOperations ) - throws IndexNotApplicableKernelException, IndexNotFoundKernelException - { - return readOperations.indexQuery( schemaIndexDescriptor, IndexQuery.exact( numberPropId1, numberProp1Values[0] ) ); - } - - @Override - void assertRangeResult( List actual ) - { - List expected = new ArrayList<>(); - for ( long i = 0; i < numberOfNodes / 2; i++ ) - { - expected.add( i ); - } - assertSameContent( actual, expected ); - } - - @Override - void assertExactResult( List actual ) - { - List expected = new ArrayList<>(); - expected.add( 0L ); - assertSameContent( actual, expected ); - } - - @Override - void doCreateIndex( DatabaseRule db ) - { - db.schema().indexFor( indexLabel ).on( numberProp1 ).create(); - } - } - - private abstract static class IndexCoordinator - { - final int numberOfNodes = 100; - - final Label indexLabel; - final String numberProp1; - final String numberProp2; - final String stringProp1; - final String stringProp2; - - Number[] numberProp1Values; - Number[] numberProp2Values; - String[] stringProp1Values; - String[] stringProp2Values; - - int indexedLabelId; - int numberPropId1; - int numberPropId2; - int stringPropId1; - int stringPropId2; - SchemaIndexDescriptor schemaIndexDescriptor; - - IndexCoordinator( Label indexLabel, String numberProp1, String numberProp2, String stringProp1, String stringProp2 ) - { - this.indexLabel = indexLabel; - this.numberProp1 = numberProp1; - this.numberProp2 = numberProp2; - this.stringProp1 = stringProp1; - this.stringProp2 = stringProp2; - - this.numberProp1Values = new Number[numberOfNodes]; - this.numberProp2Values = new Number[numberOfNodes]; - this.stringProp1Values = new String[numberOfNodes]; - this.stringProp2Values = new String[numberOfNodes]; - - // EXISTING DATA: - // 100 nodes with properties: - // numberProp1: 0-99 - // numberProp2: 0-99 - // stringProp1: "string-0"-"string-99" - // stringProp2: "string-0"-"string-99" - for ( int i = 0; i < numberOfNodes; i++ ) - { - numberProp1Values[i] = i; - numberProp2Values[i] = i; - stringProp1Values[i] = "string-" + String.format( "%02d", i ); - stringProp2Values[i] = "string-" + String.format( "%02d", i ); - } - } - - void init( DatabaseRule db ) - { - try ( Transaction tx = db.beginTx() ) - { - for ( int i = 0; i < numberOfNodes; i++ ) - { - Node node = db.createNode( indexLabel ); - node.setProperty( numberProp1, numberProp1Values[i] ); - node.setProperty( numberProp2, numberProp2Values[i] ); - node.setProperty( stringProp1, stringProp1Values[i] ); - node.setProperty( stringProp2, stringProp2Values[i] ); - } - tx.success(); - } - - try ( Transaction tx = db.beginTx(); - Statement statement = db.statement() ) - { - ReadOperations readOp = statement.readOperations(); - indexedLabelId = readOp.labelGetForName( indexLabel.name() ); - numberPropId1 = readOp.propertyKeyGetForName( numberProp1 ); - numberPropId2 = readOp.propertyKeyGetForName( numberProp2 ); - stringPropId1 = readOp.propertyKeyGetForName( stringProp1 ); - stringPropId2 = readOp.propertyKeyGetForName( stringProp2 ); - tx.success(); - } - schemaIndexDescriptor = extractIndexDescriptor(); - } - - protected abstract SchemaIndexDescriptor extractIndexDescriptor(); - - void createIndex( DatabaseRule db ) - { - try ( Transaction tx = db.beginTx() ) - { - doCreateIndex( db ); - tx.success(); - } - try ( Transaction tx = db.beginTx() ) - { - db.schema().awaitIndexesOnline( 1, TimeUnit.MINUTES ); - tx.success(); - } - } - - abstract boolean supportRangeQuery(); - - abstract PrimitiveLongIterator queryRange( ReadOperations readOperations ) - throws IndexNotApplicableKernelException, IndexNotFoundKernelException; - - abstract PrimitiveLongIterator queryExists( ReadOperations readOperations ) - throws IndexNotApplicableKernelException, IndexNotFoundKernelException; - - abstract PrimitiveLongIterator queryExact( ReadOperations readOperations ) - throws IndexNotApplicableKernelException, IndexNotFoundKernelException; - - abstract void assertRangeResult( List result ); - - void assertExistsResult( List actual ) - { - List expected = new ArrayList<>(); - for ( long i = 0; i < numberOfNodes; i++ ) - { - expected.add( i ); - } - assertSameContent( actual, expected ); - } - - void assertSameContent( List actual, List expected ) - { - assertThat( actual, is( containsInAnyOrder( expected.toArray() ) ) ); - } - - abstract void assertExactResult( List result ); - - abstract void doCreateIndex( DatabaseRule db ); - } -} diff --git a/community/neo4j/src/test/java/org/neo4j/kernel/impl/index/schema/NativeStringIndexingIT.java b/community/neo4j/src/test/java/org/neo4j/kernel/impl/index/schema/NativeStringIndexingIT.java index 2bf2cefab73c9..76ce05d7a7d3a 100644 --- a/community/neo4j/src/test/java/org/neo4j/kernel/impl/index/schema/NativeStringIndexingIT.java +++ b/community/neo4j/src/test/java/org/neo4j/kernel/impl/index/schema/NativeStringIndexingIT.java @@ -31,11 +31,16 @@ import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Transaction; import org.neo4j.graphdb.schema.IndexCreator; +import org.neo4j.internal.kernel.api.IndexOrder; import org.neo4j.internal.kernel.api.IndexQuery; +import org.neo4j.internal.kernel.api.NodeValueIndexCursor; +import org.neo4j.internal.kernel.api.exceptions.KernelException; +import org.neo4j.kernel.api.KernelTransaction; import org.neo4j.kernel.api.Statement; import org.neo4j.kernel.api.exceptions.index.IndexNotApplicableKernelException; import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptorFactory; +import org.neo4j.kernel.impl.api.store.DefaultIndexReference; import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge; import org.neo4j.test.TestLabels; import org.neo4j.test.rule.DatabaseRule; @@ -45,7 +50,9 @@ import static java.util.concurrent.TimeUnit.SECONDS; import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.neo4j.test.Randoms.CSA_LETTERS_AND_DIGITS; @@ -123,7 +130,7 @@ public void shouldFailBeforeCommitOnSizesLargerThanLimit() } @Test - public void shouldHandleCompositeSizesCloseToTheLimit() throws IndexNotApplicableKernelException, IndexNotFoundKernelException + public void shouldHandleCompositeSizesCloseToTheLimit() throws KernelException { // given createIndex( KEY, KEY2 ); @@ -143,17 +150,21 @@ public void shouldHandleCompositeSizesCloseToTheLimit() throws IndexNotApplicabl try ( Transaction tx = db.beginTx() ) { - try ( Statement statement = db.getDependencyResolver().resolveDependency( ThreadToStatementContextBridge.class ).get() ) + KernelTransaction ktx = + db.getDependencyResolver().resolveDependency( ThreadToStatementContextBridge.class ) + .getKernelTransactionBoundToThisThread( true ); + int labelId = ktx.tokenRead().nodeLabel( LABEL.name() ); + int propertyKeyId1 = ktx.tokenRead().propertyKey( KEY ); + int propertyKeyId2 = ktx.tokenRead().propertyKey( KEY2 ); + try ( NodeValueIndexCursor cursor = ktx.cursors().allocateNodeValueIndexCursor() ) { - int labelId = statement.readOperations().labelGetForName( LABEL.name() ); - int propertyKeyId1 = statement.readOperations().propertyKeyGetForName( KEY ); - int propertyKeyId2 = statement.readOperations().propertyKeyGetForName( KEY2 ); - try ( PrimitiveLongResourceIterator result = statement.readOperations().indexQuery( - SchemaIndexDescriptorFactory.forLabel( labelId, propertyKeyId1, propertyKeyId2 ), IndexQuery.exact( propertyKeyId1, string1 ), - IndexQuery.exact( propertyKeyId2, string2 ) ) ) - { - assertEquals( node.getId(), PrimitiveLongCollections.single( result, -1 ) ); - } + ktx.dataRead().nodeIndexSeek( DefaultIndexReference.general( labelId, propertyKeyId1, propertyKeyId2 ), + cursor, IndexOrder.NONE, + IndexQuery.exact( propertyKeyId1, string1 ), + IndexQuery.exact( propertyKeyId2, string2 ) ); + assertTrue( cursor.next() ); + assertEquals( node.getId(), cursor.nodeReference() ); + assertFalse( cursor.next() ); } tx.success(); } diff --git a/community/neo4j/src/test/java/org/neo4j/locking/QueryExecutionLocksIT.java b/community/neo4j/src/test/java/org/neo4j/locking/QueryExecutionLocksIT.java index 50e8158c5a94f..55f834fedf11c 100644 --- a/community/neo4j/src/test/java/org/neo4j/locking/QueryExecutionLocksIT.java +++ b/community/neo4j/src/test/java/org/neo4j/locking/QueryExecutionLocksIT.java @@ -27,19 +27,10 @@ import java.util.Arrays; import java.util.Collections; import java.util.EventListener; -import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.Optional; -import java.util.Set; import java.util.concurrent.TimeUnit; -import java.util.function.Function; -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.graphdb.Label; import org.neo4j.graphdb.Lock; import org.neo4j.graphdb.Node; @@ -49,8 +40,6 @@ import org.neo4j.internal.kernel.api.ExecutionStatistics; import org.neo4j.internal.kernel.api.ExplicitIndexRead; import org.neo4j.internal.kernel.api.ExplicitIndexWrite; -import org.neo4j.internal.kernel.api.IndexQuery; -import org.neo4j.internal.kernel.api.InternalIndexState; import org.neo4j.internal.kernel.api.Locks; import org.neo4j.internal.kernel.api.NodeCursor; import org.neo4j.internal.kernel.api.Procedures; @@ -62,42 +51,19 @@ import org.neo4j.internal.kernel.api.TokenRead; import org.neo4j.internal.kernel.api.TokenWrite; import org.neo4j.internal.kernel.api.Write; -import org.neo4j.internal.kernel.api.exceptions.EntityNotFoundException; import org.neo4j.internal.kernel.api.exceptions.InvalidTransactionTypeKernelException; -import org.neo4j.internal.kernel.api.exceptions.LabelNotFoundKernelException; -import org.neo4j.internal.kernel.api.exceptions.ProcedureException; -import org.neo4j.internal.kernel.api.exceptions.PropertyKeyIdNotFoundKernelException; -import org.neo4j.internal.kernel.api.exceptions.explicitindex.ExplicitIndexNotFoundKernelException; -import org.neo4j.internal.kernel.api.procs.ProcedureHandle; -import org.neo4j.internal.kernel.api.procs.ProcedureSignature; -import org.neo4j.internal.kernel.api.procs.QualifiedName; -import org.neo4j.internal.kernel.api.procs.UserFunctionHandle; -import org.neo4j.internal.kernel.api.procs.UserFunctionSignature; -import org.neo4j.internal.kernel.api.schema.SchemaDescriptor; -import org.neo4j.internal.kernel.api.schema.constraints.ConstraintDescriptor; +import org.neo4j.internal.kernel.api.exceptions.TransactionFailureException; import org.neo4j.internal.kernel.api.security.LoginContext; import org.neo4j.internal.kernel.api.security.SecurityContext; import org.neo4j.kernel.GraphDatabaseQueryService; -import org.neo4j.kernel.api.ExplicitIndexHits; import org.neo4j.kernel.api.KernelTransaction; -import org.neo4j.kernel.api.ReadOperations; import org.neo4j.kernel.api.ResourceTracker; import org.neo4j.kernel.api.Statement; import org.neo4j.kernel.api.dbms.DbmsOperations; -import org.neo4j.kernel.api.exceptions.RelationshipTypeIdNotFoundKernelException; import org.neo4j.kernel.api.exceptions.Status; -import org.neo4j.internal.kernel.api.exceptions.TransactionFailureException; -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.kernel.api.exceptions.schema.SchemaRuleNotFoundException; -import org.neo4j.kernel.api.index.IndexProvider; import org.neo4j.kernel.api.query.ExecutingQuery; -import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; import org.neo4j.kernel.api.txstate.TxStateHolder; import org.neo4j.kernel.impl.api.ClockContext; -import org.neo4j.kernel.impl.api.RelationshipVisitor; -import org.neo4j.kernel.impl.api.store.RelationshipIterator; import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge; import org.neo4j.kernel.impl.coreapi.InternalTransaction; import org.neo4j.kernel.impl.coreapi.PropertyContainerLocker; @@ -109,15 +75,8 @@ import org.neo4j.kernel.impl.query.TransactionalContextFactory; import org.neo4j.kernel.impl.query.clientconnection.ClientConnectionInfo; import org.neo4j.kernel.impl.query.statistic.StatisticProvider; -import org.neo4j.register.Register; -import org.neo4j.storageengine.api.NodeItem; -import org.neo4j.storageengine.api.PropertyItem; -import org.neo4j.storageengine.api.RelationshipItem; -import org.neo4j.storageengine.api.Token; import org.neo4j.storageengine.api.lock.ResourceType; -import org.neo4j.storageengine.api.schema.PopulationProgress; import org.neo4j.test.rule.EmbeddedDatabaseRule; -import org.neo4j.values.storable.Value; import static java.util.Arrays.asList; import static org.hamcrest.Matchers.empty; @@ -251,7 +210,6 @@ private static class TransactionalContextWrapper implements TransactionalContext private final TransactionalContext delegate; private final List recordedLocks; private final LockOperationListener[] listeners; - private LockRecordingReadOperationsWrapper recordingReadOperationsWrapper; private RecordingLocks recordingLocks; private TransactionalContextWrapper( TransactionalContext delegate, LockOperationListener... listeners ) @@ -544,577 +502,6 @@ public void releaseSharedLabelLock( long... ids ) } } - private static class LockRecordingReadOperationsWrapper implements ReadOperations - { - private final List listeners; - private final List lockOperationRecords; - private final ReadOperations readOperations; - - LockRecordingReadOperationsWrapper( ReadOperations readOperations, List recordedLocks, List listeners ) - { - this.listeners = listeners; - this.readOperations = readOperations; - this.lockOperationRecords = recordedLocks; - } - - @Override - public int labelGetForName( String labelName ) - { - return readOperations.labelGetForName( labelName ); - } - - @Override - public String labelGetName( int labelId ) throws LabelNotFoundKernelException - { - return readOperations.labelGetName( labelId ); - } - - @Override - public Iterator labelsGetAllTokens() - { - return readOperations.labelsGetAllTokens(); - } - - @Override - public int propertyKeyGetForName( String propertyKeyName ) - { - return readOperations.propertyKeyGetForName( propertyKeyName ); - } - - @Override - public String propertyKeyGetName( int propertyKeyId ) throws PropertyKeyIdNotFoundKernelException - { - return readOperations.propertyKeyGetName( propertyKeyId ); - } - - @Override - public Iterator propertyKeyGetAllTokens() - { - return readOperations.propertyKeyGetAllTokens(); - } - - @Override - public int relationshipTypeGetForName( String relationshipTypeName ) - { - return readOperations.relationshipTypeGetForName( relationshipTypeName ); - } - - @Override - public String relationshipTypeGetName( int relationshipTypeId ) throws RelationshipTypeIdNotFoundKernelException - { - return readOperations.relationshipTypeGetName( relationshipTypeId ); - } - - @Override - public Iterator relationshipTypesGetAllTokens() - { - return readOperations.relationshipTypesGetAllTokens(); - } - - @Override - public int labelCount() - { - return readOperations.labelCount(); - } - - @Override - public int propertyKeyCount() - { - return readOperations.propertyKeyCount(); - } - - @Override - public int relationshipTypeCount() - { - return readOperations.relationshipTypeCount(); - } - - @Override - public PrimitiveLongResourceIterator nodesGetForLabel( int labelId ) - { - return readOperations.nodesGetForLabel( labelId ); - } - - @Override - public PrimitiveLongResourceIterator indexQuery( SchemaIndexDescriptor index, IndexQuery... predicates ) - throws IndexNotFoundKernelException, IndexNotApplicableKernelException - { - return readOperations.indexQuery( index, predicates ); - } - - @Override - public PrimitiveLongIterator nodesGetAll() - { - return readOperations.nodesGetAll(); - } - - @Override - public PrimitiveLongIterator relationshipsGetAll() - { - return readOperations.relationshipsGetAll(); - } - - @Override - public RelationshipIterator nodeGetRelationships( long nodeId, Direction direction, int[] relTypes ) - throws EntityNotFoundException - { - return readOperations.nodeGetRelationships( nodeId, direction, relTypes ); - } - - @Override - public RelationshipIterator nodeGetRelationships( long nodeId, Direction direction ) - throws EntityNotFoundException - { - return readOperations.nodeGetRelationships( nodeId, direction ); - } - - @Override - public long nodeGetFromUniqueIndexSeek( SchemaIndexDescriptor index, IndexQuery.ExactPredicate... predicates ) - throws IndexNotFoundKernelException, IndexBrokenKernelException, IndexNotApplicableKernelException - { - return readOperations.nodeGetFromUniqueIndexSeek( index, predicates ); - } - - @Override - public long nodesCountIndexed( SchemaIndexDescriptor index, long nodeId, Value value ) - throws IndexNotFoundKernelException, IndexBrokenKernelException - { - return readOperations.nodesCountIndexed( index, nodeId, value ); - } - - @Override - public boolean nodeExists( long nodeId ) - { - return readOperations.nodeExists( nodeId ); - } - - @Override - public boolean nodeHasLabel( long nodeId, int labelId ) throws EntityNotFoundException - { - return readOperations.nodeHasLabel( nodeId, labelId ); - } - - @Override - public int nodeGetDegree( long nodeId, Direction direction, int relType ) throws EntityNotFoundException - { - return readOperations.nodeGetDegree( nodeId, direction, relType ); - } - - @Override - public int nodeGetDegree( long nodeId, Direction direction ) throws EntityNotFoundException - { - return readOperations.nodeGetDegree( nodeId, direction ); - } - - @Override - public boolean nodeIsDense( long nodeId ) throws EntityNotFoundException - { - return readOperations.nodeIsDense( nodeId ); - } - - @Override - public PrimitiveIntIterator nodeGetLabels( long nodeId ) throws EntityNotFoundException - { - return readOperations.nodeGetLabels( nodeId ); - } - - @Override - public PrimitiveIntIterator nodeGetPropertyKeys( long nodeId ) throws EntityNotFoundException - { - return readOperations.nodeGetPropertyKeys( nodeId ); - } - - @Override - public PrimitiveIntIterator relationshipGetPropertyKeys( long relationshipId ) throws EntityNotFoundException - { - return readOperations.relationshipGetPropertyKeys( relationshipId ); - } - - @Override - public PrimitiveIntIterator graphGetPropertyKeys() - { - return readOperations.graphGetPropertyKeys(); - } - - @Override - public PrimitiveIntIterator nodeGetRelationshipTypes( long nodeId ) throws EntityNotFoundException - { - return readOperations.nodeGetRelationshipTypes( nodeId ); - } - - @Override - public boolean nodeHasProperty( long nodeId, int propertyKeyId ) throws EntityNotFoundException - { - return readOperations.nodeHasProperty( nodeId, propertyKeyId ); - } - - @Override - public Value nodeGetProperty( long nodeId, int propertyKeyId ) throws EntityNotFoundException - { - return readOperations.nodeGetProperty( nodeId, propertyKeyId ); - } - - @Override - public boolean relationshipHasProperty( long relationshipId, int propertyKeyId ) throws EntityNotFoundException - { - return readOperations.relationshipHasProperty( relationshipId, propertyKeyId ); - } - - @Override - public Value relationshipGetProperty( long relationshipId, int propertyKeyId ) throws EntityNotFoundException - { - return readOperations.relationshipGetProperty( relationshipId, propertyKeyId ); - } - - @Override - public boolean graphHasProperty( int propertyKeyId ) - { - return readOperations.graphHasProperty( propertyKeyId ); - } - - @Override - public Value graphGetProperty( int propertyKeyId ) - { - return readOperations.graphGetProperty( propertyKeyId ); - } - - @Override - public void relationshipVisit( long relId, - RelationshipVisitor visitor ) throws EntityNotFoundException, EXCEPTION - { - readOperations.relationshipVisit( relId, visitor ); - } - - @Override - public long nodesGetCount() - { - return readOperations.nodesGetCount(); - } - - @Override - public long relationshipsGetCount() - { - return readOperations.relationshipsGetCount(); - } - - @Override - public Cursor nodeCursorById( long nodeId ) throws EntityNotFoundException - { - return readOperations.nodeCursorById( nodeId ); - } - - @Override - public Cursor relationshipCursorById( long relId ) throws EntityNotFoundException - { - return readOperations.relationshipCursorById( relId ); - } - - @Override - public Cursor nodeGetProperties( NodeItem node ) - { - return readOperations.nodeGetProperties( node ); - } - - @Override - public Cursor relationshipGetProperties( RelationshipItem relationship ) - { - return readOperations.relationshipGetProperties( relationship ); - } - - @Override - public SchemaIndexDescriptor indexGetForSchema( SchemaDescriptor descriptor ) throws SchemaRuleNotFoundException - { - return readOperations.indexGetForSchema( descriptor ); - } - - @Override - public Iterator indexesGetForLabel( int labelId ) - { - return readOperations.indexesGetForLabel( labelId ); - } - - @Override - public Iterator indexesGetAll() - { - return readOperations.indexesGetAll(); - } - - @Override - public InternalIndexState indexGetState( SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException - { - return readOperations.indexGetState( descriptor ); - } - - @Override - public IndexProvider.Descriptor indexGetProviderDescriptor( SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException - { - return readOperations.indexGetProviderDescriptor( descriptor ); - } - - @Override - public PopulationProgress indexGetPopulationProgress( SchemaIndexDescriptor descriptor ) - throws IndexNotFoundKernelException - { - return readOperations.indexGetPopulationProgress( descriptor ); - } - - @Override - public long indexSize( SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException - { - return readOperations.indexSize( descriptor ); - } - - @Override - public double indexUniqueValuesSelectivity( SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException - { - return readOperations.indexUniqueValuesSelectivity( descriptor ); - } - - @Override - public String indexGetFailure( SchemaIndexDescriptor descriptor ) throws IndexNotFoundKernelException - { - return readOperations.indexGetFailure( descriptor ); - } - - @Override - public Iterator constraintsGetForSchema( SchemaDescriptor descriptor ) - { - return readOperations.constraintsGetForSchema( descriptor ); - } - - @Override - public Iterator constraintsGetForLabel( int labelId ) - { - return readOperations.constraintsGetForLabel( labelId ); - } - - @Override - public Iterator constraintsGetForRelationshipType( int typeId ) - { - return readOperations.constraintsGetForRelationshipType( typeId ); - } - - @Override - public Iterator constraintsGetAll() - { - return readOperations.constraintsGetAll(); - } - - @Override - public Long indexGetOwningUniquenessConstraintId( SchemaIndexDescriptor index ) - { - return readOperations.indexGetOwningUniquenessConstraintId( index ); - } - - @Override - public V schemaStateGetOrCreate( K key, Function creator ) - { - return readOperations.schemaStateGetOrCreate( key, creator ); - } - - @Override - public V schemaStateGet( K key ) - { - return readOperations.schemaStateGet( key ); - } - - @Override - public void schemaStateFlush() - { - readOperations.schemaStateFlush(); - } - - @Override - public void acquireExclusive( ResourceType type, long... ids ) - { - for ( LockOperationListener listener : listeners ) - { - listener.lockAcquired( true, type, ids ); - } - lockOperationRecords.add( new LockOperationRecord( true, true, type, ids ) ); - readOperations.acquireExclusive( type, ids ); - } - - @Override - public void acquireShared( ResourceType type, long... ids ) - { - for ( LockOperationListener listener : listeners ) - { - listener.lockAcquired( false, type, ids ); - } - lockOperationRecords.add( new LockOperationRecord( false, true, type, ids ) ); - readOperations.acquireShared( type, ids ); - } - - @Override - public void releaseExclusive( ResourceType type, long... ids ) - { - lockOperationRecords.add( new LockOperationRecord( true, false, type, ids ) ); - readOperations.releaseExclusive( type, ids ); - } - - @Override - public void releaseShared( ResourceType type, long... ids ) - { - lockOperationRecords.add( new LockOperationRecord( false, false, type, ids ) ); - readOperations.releaseShared( type, ids ); - } - - @Override - public boolean nodeExplicitIndexExists( String indexName, Map customConfiguration ) - { - return readOperations.nodeExplicitIndexExists( indexName, customConfiguration ); - } - - @Override - public boolean relationshipExplicitIndexExists( String indexName, Map customConfiguration ) - { - return readOperations.relationshipExplicitIndexExists( indexName, customConfiguration ); - } - - @Override - public Map nodeExplicitIndexGetConfiguration( String indexName ) - throws ExplicitIndexNotFoundKernelException - { - return readOperations.nodeExplicitIndexGetConfiguration( indexName ); - } - - @Override - public Map relationshipExplicitIndexGetConfiguration( String indexName ) - throws ExplicitIndexNotFoundKernelException - { - return readOperations.relationshipExplicitIndexGetConfiguration( indexName ); - } - - @Override - public ExplicitIndexHits nodeExplicitIndexGet( String indexName, String key, Object value ) - throws ExplicitIndexNotFoundKernelException - { - return readOperations.nodeExplicitIndexGet( indexName, key, value ); - } - - @Override - public ExplicitIndexHits nodeExplicitIndexQuery( String indexName, String key, Object queryOrQueryObject ) - throws ExplicitIndexNotFoundKernelException - { - return readOperations.nodeExplicitIndexQuery( indexName, key, queryOrQueryObject ); - } - - @Override - public ExplicitIndexHits nodeExplicitIndexQuery( String indexName, Object queryOrQueryObject ) - throws ExplicitIndexNotFoundKernelException - { - return readOperations.nodeExplicitIndexQuery( indexName, queryOrQueryObject ); - } - - @Override - public ExplicitIndexHits relationshipExplicitIndexGet( String name, String key, Object valueOrNull, long startNode, - long endNode ) throws ExplicitIndexNotFoundKernelException - { - return readOperations.relationshipExplicitIndexGet( name, key, valueOrNull, startNode, endNode ); - } - - @Override - public ExplicitIndexHits relationshipExplicitIndexQuery( String indexName, String key, Object queryOrQueryObject, - long startNode, long endNode ) throws ExplicitIndexNotFoundKernelException - { - return readOperations - .relationshipExplicitIndexQuery( indexName, key, queryOrQueryObject, startNode, endNode ); - } - - @Override - public ExplicitIndexHits relationshipExplicitIndexQuery( String indexName, Object queryOrQueryObject, - long startNode, long endNode ) throws ExplicitIndexNotFoundKernelException - { - return readOperations.relationshipExplicitIndexQuery( indexName, queryOrQueryObject, startNode, endNode ); - } - - @Override - public String[] nodeExplicitIndexesGetAll() - { - return readOperations.nodeExplicitIndexesGetAll(); - } - - @Override - public String[] relationshipExplicitIndexesGetAll() - { - return readOperations.relationshipExplicitIndexesGetAll(); - } - - @Override - public long countsForNode( int labelId ) - { - return readOperations.countsForNode( labelId ); - } - - @Override - public long countsForNodeWithoutTxState( int labelId ) - { - return readOperations.countsForNodeWithoutTxState( labelId ); - } - - @Override - public long countsForRelationship( int startLabelId, int typeId, int endLabelId ) - { - return readOperations.countsForRelationship( startLabelId, typeId, endLabelId ); - } - - @Override - public long countsForRelationshipWithoutTxState( int startLabelId, int typeId, int endLabelId ) - { - return readOperations.countsForRelationshipWithoutTxState( startLabelId, typeId, endLabelId ); - } - - @Override - public Register.DoubleLongRegister indexUpdatesAndSize( SchemaIndexDescriptor index, - Register.DoubleLongRegister target ) throws IndexNotFoundKernelException - { - return readOperations.indexUpdatesAndSize( index, target ); - } - - @Override - public Register.DoubleLongRegister indexSample( SchemaIndexDescriptor index, Register.DoubleLongRegister target ) - throws IndexNotFoundKernelException - { - return readOperations.indexSample( index, target ); - } - - @Override - public ProcedureHandle procedureGet( QualifiedName name ) throws ProcedureException - { - return readOperations.procedureGet( name ); - } - - @Override - public UserFunctionHandle functionGet( QualifiedName name ) - { - return readOperations.functionGet( name ); - } - - @Override - public UserFunctionHandle aggregationFunctionGet( QualifiedName name ) - { - return readOperations.aggregationFunctionGet( name ); - } - - @Override - public Set functionsGetAll() - { - return readOperations.functionsGetAll(); - } - - @Override - public Set proceduresGetAll() - { - return readOperations.proceduresGetAll(); - } - - List getLockOperationRecords() - { - return lockOperationRecords; - } - } - private static class LockOperationListener implements EventListener { void lockAcquired( boolean exclusive, ResourceType resourceType, long... ids ) diff --git a/community/server/src/test/java/org/neo4j/server/rest/domain/GraphDbHelper.java b/community/server/src/test/java/org/neo4j/server/rest/domain/GraphDbHelper.java index eee6a608f5049..877e3090e4b99 100644 --- a/community/server/src/test/java/org/neo4j/server/rest/domain/GraphDbHelper.java +++ b/community/server/src/test/java/org/neo4j/server/rest/domain/GraphDbHelper.java @@ -68,7 +68,7 @@ public int getNumberOfNodes() try ( Session session = kernel.beginSession( AnonymousContext.read() ); org.neo4j.internal.kernel.api.Transaction tx = session.beginTransaction( org.neo4j.internal.kernel.api.Transaction.Type.implicit ) ) { - return Math.toIntExact( tx.dataRead().countsForNode( Read.ANY_LABEL ) ); + return Math.toIntExact( tx.dataRead().nodesGetCount() ); } catch ( TransactionFailureException e ) { @@ -82,7 +82,7 @@ public int getNumberOfRelationships() try ( Session session = kernel.beginSession( AnonymousContext.read() ); org.neo4j.internal.kernel.api.Transaction tx = session.beginTransaction( org.neo4j.internal.kernel.api.Transaction.Type.implicit ) ) { - return Math.toIntExact( tx.dataRead().countsForRelationship( Read.ANY_LABEL, Read.ANY_RELATIONSHIP_TYPE, Read.ANY_LABEL ) ); + return Math.toIntExact( tx.dataRead().relationshipsGetCount() ); } catch ( TransactionFailureException e ) { diff --git a/community/shell/src/main/java/org/neo4j/shell/kernel/GraphDatabaseShellServer.java b/community/shell/src/main/java/org/neo4j/shell/kernel/GraphDatabaseShellServer.java index dbf2a1254fe72..25ad118e62c5a 100644 --- a/community/shell/src/main/java/org/neo4j/shell/kernel/GraphDatabaseShellServer.java +++ b/community/shell/src/main/java/org/neo4j/shell/kernel/GraphDatabaseShellServer.java @@ -28,8 +28,8 @@ import org.neo4j.graphdb.factory.GraphDatabaseBuilder; import org.neo4j.graphdb.factory.GraphDatabaseFactory; import org.neo4j.graphdb.factory.GraphDatabaseSettings; +import org.neo4j.internal.kernel.api.TokenRead; import org.neo4j.kernel.api.KernelTransaction; -import org.neo4j.kernel.api.Statement; import org.neo4j.kernel.api.exceptions.Status; import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge; import org.neo4j.kernel.internal.GraphDatabaseAPI; @@ -133,9 +133,9 @@ public void registerTopLevelTransactionInProgress( Serializable clientId ) } } - public Statement getStatement() + public TokenRead getTokenRead() { - return getThreadToStatementContextBridge().get(); + return getThreadToStatementContextBridge().getKernelTransactionBoundToThisThread( true ).tokenRead(); } private ThreadToStatementContextBridge getThreadToStatementContextBridge() diff --git a/community/shell/src/main/java/org/neo4j/shell/kernel/apps/Schema.java b/community/shell/src/main/java/org/neo4j/shell/kernel/apps/Schema.java index 8b69cf5eed414..ddfe18296ebd5 100644 --- a/community/shell/src/main/java/org/neo4j/shell/kernel/apps/Schema.java +++ b/community/shell/src/main/java/org/neo4j/shell/kernel/apps/Schema.java @@ -29,7 +29,7 @@ import org.neo4j.graphdb.schema.ConstraintType; import org.neo4j.graphdb.schema.IndexDefinition; import org.neo4j.graphdb.schema.Schema.IndexState; -import org.neo4j.kernel.api.Statement; +import org.neo4j.internal.kernel.api.TokenRead; import org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException; import org.neo4j.kernel.api.schema.SchemaDescriptorFactory; import org.neo4j.kernel.impl.api.index.IndexingService; @@ -182,11 +182,10 @@ private void sampleIndexes( Label[] labels, String property, boolean sampleAll, int labelKey; int propertyKey; - try ( Statement statement = getServer().getStatement() ) - { - labelKey = statement.readOperations().labelGetForName( labels[0].name() ); - propertyKey = statement.readOperations().propertyKeyGetForName( property ); - } + + TokenRead tokenRead = getServer().getTokenRead(); + labelKey = tokenRead.nodeLabel( labels[0].name() ); + propertyKey = tokenRead.propertyKey( property ); if ( labelKey == -1 ) { diff --git a/enterprise/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/UniqueConstraintVerificationAcceptanceTest.scala b/enterprise/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/UniqueConstraintVerificationAcceptanceTest.scala deleted file mode 100644 index 9541374b25d95..0000000000000 --- a/enterprise/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/UniqueConstraintVerificationAcceptanceTest.scala +++ /dev/null @@ -1,154 +0,0 @@ -/* - * 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 Affero 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package org.neo4j.internal.cypher.acceptance - -import java.time.{LocalDate, LocalDateTime} - -import org.neo4j.cypher.internal.compiler.v3_4.helpers.ListSupport -import org.neo4j.cypher.{CypherExecutionException, ExecutionEngineFunSuite, QueryStatisticsTestSupport} -import org.neo4j.graphdb.ConstraintViolationException -import org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException -import org.neo4j.kernel.api.schema.SchemaDescriptorFactory -import org.neo4j.kernel.impl.api.OperationsFacade - -import scala.collection.JavaConverters._ - -class UniqueConstraintVerificationAcceptanceTest - extends ExecutionEngineFunSuite with QueryStatisticsTestSupport with ListSupport { - - test("should_add_constraint_with_no_existing_data") { - //GIVEN - - //WHEN - execute("create constraint on (node:Label) assert node.propertyKey is unique") - - //THEN - graph.inTx { - context: OperationsFacade => - val prop = context.propertyKeyGetForName("propertyKey") - val label = context.labelGetForName("Label") - - val constraints = context.constraintsGetForSchema(SchemaDescriptorFactory.forLabel(label, prop)).asScala - - constraints should have size 1 - } - } - - test("should_add_constraint_when_existing_data_is_unique") { - // GIVEN - execute("create (a:Person{name:\"Alistair\"}), (b:Person{name:\"Stefan\"})") - - // WHEN - execute("create constraint on (n:Person) assert n.name is unique") - - // THEN - graph.inTx { - context: OperationsFacade => - val prop = context.propertyKeyGetForName("name") - val label = context.labelGetForName("Person") - - val constraints = context.constraintsGetForSchema(SchemaDescriptorFactory.forLabel(label, prop)).asScala - - constraints should have size 1 - } - } - - test("should_add_constraint_using_recreated_unique_data") { - // GIVEN - execute("create (a:Person{name:\"Alistair\"}), (b:Person{name:\"Stefan\"})") - execute("match (n:Person) delete n") - execute("create (a:Person{name:\"Alistair\"}), (b:Person{name:\"Stefan\"})") - - // WHEN - execute("create constraint on (n:Person) assert n.name is unique") - - // THEN - graph.inTx { - context: OperationsFacade => - val prop = context.propertyKeyGetForName("name") - val label = context.labelGetForName("Person") - - val constraints = context.constraintsGetForSchema(SchemaDescriptorFactory.forLabel(label, prop)).asScala - - constraints should have size 1 - } - } - - test("should_drop_constraint") { - //GIVEN - execute("create constraint on (node:Label) assert node.propertyKey is unique") - - //WHEN - execute("drop constraint on (node:Label) assert node.propertyKey is unique") - - //THEN - graph.inTx { - context: OperationsFacade => - val prop = context.propertyKeyGetForName("propertyKey") - val label = context.labelGetForName("Label") - - val constraints = context.constraintsGetForSchema(SchemaDescriptorFactory.forLabel(label, prop)).asScala - - constraints shouldBe empty - } - } - - test("should_fail_to_add_constraint_when_existing_data_conflicts") { - // GIVEN - execute("create (a:Person{id:1}), (b:Person{id:1})") - - // WHEN - try - { - execute("create constraint on (n:Person) assert n.id is unique") - - fail("expected exception") - } - // THEN - catch - { - case ex: CypherExecutionException => - assert(ex.getCause.isInstanceOf[CreateConstraintFailureException]) - } - - graph.inTx { - context: OperationsFacade => - val prop = context.propertyKeyGetForName("id") - val label = context.labelGetForName("Person") - - val constraints = context.constraintsGetForSchema(SchemaDescriptorFactory.forLabel(label, prop)).asScala - - constraints shouldBe empty - } - } - - test("Should handle temporal with unique constraint") { - // When - graph.execute("CREATE CONSTRAINT ON (n:User) ASSERT (n.birthday) IS UNIQUE") - - // Then - createLabeledNode(Map("birthday" -> LocalDate.of(1991, 10, 18)), "User") - createLabeledNode(Map("birthday" -> LocalDateTime.of(1991, 10, 18, 0, 0, 0, 0)), "User") - createLabeledNode(Map("birthday" -> "1991-10-18"), "User") - a[ConstraintViolationException] should be thrownBy { - createLabeledNode(Map("birthday" -> LocalDate.of(1991, 10, 18)), "User") - } - } -} diff --git a/enterprise/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiled_runtime/v3_4/codegen/ir/BuildProbeTableInstructionsTest.scala b/enterprise/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiled_runtime/v3_4/codegen/ir/BuildProbeTableInstructionsTest.scala index 0dbff1095df93..38c738a25e90e 100644 --- a/enterprise/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiled_runtime/v3_4/codegen/ir/BuildProbeTableInstructionsTest.scala +++ b/enterprise/cypher/cypher/src/test/scala/org/neo4j/cypher/internal/compiled_runtime/v3_4/codegen/ir/BuildProbeTableInstructionsTest.scala @@ -39,7 +39,6 @@ import org.neo4j.cypher.internal.util.v3_4.test_helpers.CypherFunSuite import org.neo4j.graphdb.Node import org.neo4j.internal.kernel.api._ import org.neo4j.internal.kernel.api.helpers.StubNodeCursor -import org.neo4j.kernel.api.ReadOperations import org.neo4j.kernel.impl.core.{EmbeddedProxySPI, NodeProxy} import org.neo4j.values.AnyValue import org.neo4j.values.storable._ @@ -57,7 +56,6 @@ class BuildProbeTableInstructionsTest extends CypherFunSuite with CodeGenSugar { private val entityAccessor = mock[EmbeddedProxySPI] private val queryContext = mock[QueryContext] private val transactionalContext = mock[TransactionalContextWrapper] - private val readOps = mock[ReadOperations] private val dataRead = mock[Read] private val cursors = mock[CursorFactory] private def nodeCursor = { @@ -78,9 +76,7 @@ class BuildProbeTableInstructionsTest extends CypherFunSuite with CodeGenSugar { when(transactionalContext.dataRead).thenReturn(dataRead) when(transactionalContext.cursors).thenReturn(cursors) when(queryContext.entityAccessor).thenReturn(entityAccessor) - when(readOps.nodesGetAll()).then(new Answer[PrimitiveLongIterator] { - def answer(invocation: InvocationOnMock) = allNodeIdsIterator() - }) + override protected def beforeEach() = allNodeIds.clear() diff --git a/tools/src/main/java/org/neo4j/tools/dump/DumpCountsStore.java b/tools/src/main/java/org/neo4j/tools/dump/DumpCountsStore.java index c2a4b05b1c7a2..df75b97f8499a 100644 --- a/tools/src/main/java/org/neo4j/tools/dump/DumpCountsStore.java +++ b/tools/src/main/java/org/neo4j/tools/dump/DumpCountsStore.java @@ -32,7 +32,7 @@ import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.pagecache.PageCache; import org.neo4j.io.pagecache.tracing.cursor.context.EmptyVersionContextSupplier; -import org.neo4j.kernel.api.ReadOperations; +import org.neo4j.kernel.api.StatementConstants; import org.neo4j.kernel.api.schema.index.SchemaIndexDescriptor; import org.neo4j.kernel.configuration.Config; import org.neo4j.kernel.impl.api.CountsVisitor; @@ -187,7 +187,7 @@ public boolean visitUnknownKey( ReadableBuffer key, ReadableBuffer value ) private String label( int id ) { - if ( id == ReadOperations.ANY_LABEL ) + if ( id == StatementConstants.ANY_LABEL ) { return ""; } @@ -210,7 +210,7 @@ private String propertyKeys( int[] ids ) private String relationshipType( int id ) { - if ( id == ReadOperations.ANY_RELATIONSHIP_TYPE ) + if ( id == StatementConstants.ANY_RELATIONSHIP_TYPE ) { return ""; }