예제 #1
0
        private void CollectAndSortNodeIds(long nodeId, Transaction transaction, NodeCursor nodes)
        {
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final org.eclipse.collections.api.set.primitive.MutableLongSet nodeIdSet = new org.eclipse.collections.impl.set.mutable.primitive.LongHashSet();
            MutableLongSet nodeIdSet = new LongHashSet();

            nodeIdSet.add(nodeId);

            [email protected] read = transaction.DataRead();
            read.SingleNode(nodeId, nodes);
            if (!nodes.Next())
            {
                this._sortedNodeIds = _empty;
                return;
            }
            using (RelationshipSelectionCursor rels = RelationshipSelections.allCursor(transaction.Cursors(), nodes, null))
            {
                while (rels.Next())
                {
                    if (_firstRelId == NO_SUCH_RELATIONSHIP)
                    {
                        _firstRelId = rels.RelationshipReference();
                    }

                    nodeIdSet.add(rels.SourceNodeReference());
                    nodeIdSet.add(rels.TargetNodeReference());
                }
            }

            this._sortedNodeIds = nodeIdSet.toSortedArray();
        }
예제 #2
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: void lockAllNodesAndConsumeRelationships(long nodeId, final org.neo4j.internal.kernel.api.Transaction transaction, org.neo4j.internal.kernel.api.NodeCursor nodes) throws org.neo4j.internal.kernel.api.exceptions.KernelException
//JAVA TO C# CONVERTER WARNING: 'final' parameters are ignored unless the option to convert to C# 7.2 'in' parameters is selected:
        internal virtual void LockAllNodesAndConsumeRelationships(long nodeId, Transaction transaction, NodeCursor nodes)
        {
            bool retry;

            do
            {
                retry       = false;
                _firstRelId = NO_SUCH_RELATIONSHIP;

                // lock all the nodes involved by following the node id ordering
                CollectAndSortNodeIds(nodeId, transaction, nodes);
                LockAllNodes(_sortedNodeIds);

                // perform the action on each relationship, we will retry if the the relationship iterator contains
                // new relationships
                [email protected] read = transaction.DataRead();
                read.SingleNode(nodeId, nodes);
                //if the node is not there, someone else probably deleted it, just ignore
                if (nodes.Next())
                {
                    using (RelationshipSelectionCursor rels = RelationshipSelections.allCursor(transaction.Cursors(), nodes, null))
                    {
                        bool first = true;
                        while (rels.Next() && !retry)
                        {
                            retry = PerformAction(rels.RelationshipReference(), first);
                            first = false;
                        }
                    }
                }
            } while (retry);
        }
예제 #3
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldComputeDegreeWithoutType() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldComputeDegreeWithoutType()
        {
            // GIVEN
            long node;

            using (Transaction tx = Transaction())
            {
                Write write = tx.DataWrite();
                node = write.NodeCreate();
                write.RelationshipCreate(node, tx.TokenWrite().relationshipTypeGetOrCreateForName("R1"), write.NodeCreate());
                write.RelationshipCreate(node, tx.TokenWrite().relationshipTypeGetOrCreateForName("R2"), write.NodeCreate());
                write.RelationshipCreate(write.NodeCreate(), tx.TokenWrite().relationshipTypeGetOrCreateForName("R3"), node);
                write.RelationshipCreate(node, tx.TokenWrite().relationshipTypeGetOrCreateForName("R4"), node);

                tx.Success();
            }

            using (Transaction tx = Transaction())
            {
                Read          read    = tx.DataRead();
                CursorFactory cursors = tx.Cursors();
                using (NodeCursor nodes = cursors.AllocateNodeCursor())
                {
                    assertThat(CompiledExpandUtils.NodeGetDegreeIfDense(read, node, nodes, cursors, OUTGOING), equalTo(3));
                    assertThat(CompiledExpandUtils.NodeGetDegreeIfDense(read, node, nodes, cursors, INCOMING), equalTo(2));
                    assertThat(CompiledExpandUtils.NodeGetDegreeIfDense(read, node, nodes, cursors, BOTH), equalTo(4));
                }
            }
        }
예제 #4
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private static void singleRelationship(org.neo4j.internal.kernel.api.Read read, org.neo4j.internal.kernel.api.RelationshipScanCursor relationships, long relationship) throws org.neo4j.internal.kernel.api.exceptions.EntityNotFoundException
        private static void SingleRelationship(Read read, RelationshipScanCursor relationships, long relationship)
        {
            read.SingleRelationship(relationship, relationships);
            if (!relationships.Next())
            {
                throw new EntityNotFoundException(EntityType.NODE, relationship);
            }
        }
예제 #5
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private static void singleNode(org.neo4j.internal.kernel.api.Read read, org.neo4j.internal.kernel.api.NodeCursor nodeCursor, long node) throws org.neo4j.internal.kernel.api.exceptions.EntityNotFoundException
        private static void SingleNode(Read read, NodeCursor nodeCursor, long node)
        {
            read.SingleNode(node, nodeCursor);
            if (!nodeCursor.Next())
            {
                throw new EntityNotFoundException(EntityType.NODE, node);
            }
        }
예제 #6
0
        /// <summary>
        /// Checks if given node has a given label.
        /// </summary>
        /// <param name="read"> The current Read instance </param>
        /// <param name="nodeCursor"> The node cursor to use </param>
        /// <param name="node"> The id of the node </param>
        /// <param name="label"> The id of the label </param>
        /// <returns> {@code true} if the node has the label, otherwise {@code false} </returns>
        /// <exception cref="EntityNotFoundException"> if the node is not there. </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: public static boolean nodeHasLabel(org.neo4j.internal.kernel.api.Read read, org.neo4j.internal.kernel.api.NodeCursor nodeCursor, long node, int label) throws org.neo4j.internal.kernel.api.exceptions.EntityNotFoundException
        public static bool NodeHasLabel(Read read, NodeCursor nodeCursor, long node, int label)
        {
            if (label == StatementConstants.NO_SUCH_LABEL)
            {
                return(false);
            }
            SingleNode(read, nodeCursor, node);

            return(nodeCursor.HasLabel(label));
        }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldAllowReadsInWriteMode()
        public virtual void ShouldAllowReadsInWriteMode()
        {
            // Given
            KernelTransactionImplementation tx = newTransaction(AnonymousContext.write());

            // When
            Read reads = tx.DataRead();

            // Then
            assertNotNull(reads);
        }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldAllowReadsInFullMode()
        public virtual void ShouldAllowReadsInFullMode()
        {
            // Given
            KernelTransactionImplementation tx = newTransaction(AUTH_DISABLED);

            // When
            Read reads = tx.DataRead();

            // Then
            assertNotNull(reads);
        }
예제 #9
0
 private static int CalculateTotalDegreeIfDense(Read read, long node, NodeCursor nodeCursor, Direction direction, int[] relTypes, CursorFactory cursors)
 {
     read.SingleNode(node, nodeCursor);
     if (!nodeCursor.Next())
     {
         return(0);
     }
     if (!nodeCursor.Dense)
     {
         return(NOT_DENSE_DEGREE);
     }
     return(CalculateTotalDegree(nodeCursor, direction, relTypes, cursors));
 }
예제 #10
0
        public static RelationshipSelectionCursor ConnectingRelationships(Read read, CursorFactory cursors, NodeCursor nodeCursor, long fromNode, Direction direction, long toNode, int[] relTypes)
        {
            //Check from
            int fromDegree = CalculateTotalDegreeIfDense(read, fromNode, nodeCursor, direction, relTypes, cursors);

            if (fromDegree == 0)
            {
                return(Org.Neo4j.@internal.Kernel.Api.helpers.RelationshipSelectionCursor_EMPTY);
            }
            bool fromNodeIsDense = fromDegree != NOT_DENSE_DEGREE;

            //Check to
            read.SingleNode(toNode, nodeCursor);
            if (!nodeCursor.Next())
            {
                return(Org.Neo4j.@internal.Kernel.Api.helpers.RelationshipSelectionCursor_EMPTY);
            }
            bool toNodeIsDense = nodeCursor.Dense;

            //Both are dense, start with the one with the lesser degree
            if (fromNodeIsDense && toNodeIsDense)
            {
                //Note that we have already position the cursor at toNode
                int       toDegree = CalculateTotalDegree(nodeCursor, direction, relTypes, cursors);
                long      startNode;
                long      endNode;
                Direction relDirection;
                if (fromDegree < toDegree)
                {
                    startNode    = fromNode;
                    endNode      = toNode;
                    relDirection = direction;
                }
                else
                {
                    startNode    = toNode;
                    endNode      = fromNode;
                    relDirection = direction.reverse();
                }

                return(ConnectingRelationshipsIterator(CompiledCursorUtils.NodeGetRelationships(read, cursors, nodeCursor, startNode, relDirection, relTypes), endNode));
            }
            else if (fromNodeIsDense)
            {
                return(ConnectingRelationshipsIterator(CompiledCursorUtils.NodeGetRelationships(read, cursors, nodeCursor, toNode, direction.reverse(), relTypes), fromNode));
            }
            else
            {               //either only toNode is dense or none of them, just go with what we got
                return(ConnectingRelationshipsIterator(CompiledCursorUtils.NodeGetRelationships(read, cursors, nodeCursor, fromNode, direction, relTypes), toNode));
            }
        }
예제 #11
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldCallIndexSeek() throws org.neo4j.internal.kernel.api.exceptions.KernelException
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldCallIndexSeek()
        {
            // GIVEN
            Read           read  = mock(typeof(Read));
            IndexReference index = mock(typeof(IndexReference));

            when(index.Properties()).thenReturn(new int[] { 42 });

            // WHEN
            CompiledIndexUtils.IndexSeek(read, mock(typeof(CursorFactory)), index, "hello");

            // THEN
            verify(read, times(1)).nodeIndexSeek(any(), any(), any(), anyBoolean(), any());
        }
예제 #12
0
        internal static int NodeGetDegreeIfDense(Read read, long node, NodeCursor nodeCursor, CursorFactory cursors, Direction direction, int type)
        {
            read.SingleNode(node, nodeCursor);
            if (!nodeCursor.Next())
            {
                return(0);
            }
            if (!nodeCursor.Dense)
            {
                return(NOT_DENSE_DEGREE);
            }

            return(NodeGetDegree(nodeCursor, cursors, direction, type));
        }
예제 #13
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldHandleNullInIndexSeek() throws org.neo4j.internal.kernel.api.exceptions.KernelException
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldHandleNullInIndexSeek()
        {
            // GIVEN
            Read           read  = mock(typeof(Read));
            IndexReference index = mock(typeof(IndexReference));

            when(index.Properties()).thenReturn(new int[] { 42 });

            // WHEN
            NodeValueIndexCursor cursor = CompiledIndexUtils.IndexSeek(mock(typeof(Read)), mock(typeof(CursorFactory)), index, null);

            // THEN
            verify(read, never()).nodeIndexSeek(any(), any(), any(), anyBoolean());
            assertFalse(cursor.Next());
        }
예제 #14
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private static void lockNodeUsingUniqueIndexSeek(org.neo4j.kernel.internal.GraphDatabaseAPI database, org.neo4j.graphdb.Label label, String nameProperty) throws org.neo4j.internal.kernel.api.exceptions.KernelException
        private static void LockNodeUsingUniqueIndexSeek(GraphDatabaseAPI database, Label label, string nameProperty)
        {
            using (Transaction transaction = database.BeginTx())
            {
                ThreadToStatementContextBridge contextBridge = database.DependencyResolver.resolveDependency(typeof(ThreadToStatementContextBridge));
                KernelTransaction kernelTransaction          = contextBridge.GetKernelTransactionBoundToThisThread(true);
                TokenRead         tokenRead = kernelTransaction.TokenRead();
                Read dataRead = kernelTransaction.DataRead();

                int            labelId        = tokenRead.NodeLabel(label.Name());
                int            propertyId     = tokenRead.PropertyKey(nameProperty);
                IndexReference indexReference = kernelTransaction.SchemaRead().index(labelId, propertyId);
                dataRead.LockingNodeUniqueIndexSeek(indexReference, IndexQuery.ExactPredicate.exact(propertyId, "value"));
                transaction.Success();
            }
        }
예제 #15
0
        /// <summary>
        /// Fetches a given property from a node
        /// </summary>
        /// <param name="read"> The current Read instance </param>
        /// <param name="nodeCursor"> The node cursor to use </param>
        /// <param name="node"> The id of the node </param>
        /// <param name="propertyCursor"> The property cursor to use </param>
        /// <param name="prop"> The id of the property to find </param>
        /// <returns> The value of the given property </returns>
        /// <exception cref="EntityNotFoundException"> If the node cannot be find. </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: public static org.neo4j.values.storable.Value nodeGetProperty(org.neo4j.internal.kernel.api.Read read, org.neo4j.internal.kernel.api.NodeCursor nodeCursor, long node, org.neo4j.internal.kernel.api.PropertyCursor propertyCursor, int prop) throws org.neo4j.internal.kernel.api.exceptions.EntityNotFoundException
        public static Value NodeGetProperty(Read read, NodeCursor nodeCursor, long node, PropertyCursor propertyCursor, int prop)
        {
            if (prop == StatementConstants.NO_SUCH_PROPERTY_KEY)
            {
                return(Values.NO_VALUE);
            }
            SingleNode(read, nodeCursor, node);
            nodeCursor.Properties(propertyCursor);
            while (propertyCursor.Next())
            {
                if (propertyCursor.PropertyKey() == prop)
                {
                    return(propertyCursor.PropertyValue());
                }
            }

            return(Values.NO_VALUE);
        }
예제 #16
0
        /// <summary>
        /// Fetches a given property from a relationship
        /// </summary>
        /// <param name="read"> The current Read instance </param>
        /// <param name="relationship"> The node cursor to use </param>
        /// <param name="node"> The id of the node </param>
        /// <param name="propertyCursor"> The property cursor to use </param>
        /// <param name="prop"> The id of the property to find </param>
        /// <returns> The value of the given property </returns>
        /// <exception cref="EntityNotFoundException"> If the node cannot be find. </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: public static org.neo4j.values.storable.Value relationshipGetProperty(org.neo4j.internal.kernel.api.Read read, org.neo4j.internal.kernel.api.RelationshipScanCursor relationship, long node, org.neo4j.internal.kernel.api.PropertyCursor propertyCursor, int prop) throws org.neo4j.internal.kernel.api.exceptions.EntityNotFoundException
        public static Value RelationshipGetProperty(Read read, RelationshipScanCursor relationship, long node, PropertyCursor propertyCursor, int prop)
        {
            if (prop == StatementConstants.NO_SUCH_PROPERTY_KEY)
            {
                return(Values.NO_VALUE);
            }
            SingleRelationship(read, relationship, node);
            relationship.Properties(propertyCursor);
            while (propertyCursor.Next())
            {
                if (propertyCursor.PropertyKey() == prop)
                {
                    return(propertyCursor.PropertyValue());
                }
            }

            return(Values.NO_VALUE);
        }
예제 #17
0
        /// <param name="label"> the label to get the number of nodes of, or {@code null} to get the total number of nodes. </param>
        private long CountsForNode(Label label)
        {
            KernelTransaction transaction = _transactionSupplier.get();
            Read read = transaction.DataRead();
            int  labelId;

            if (label == null)
            {
                labelId = StatementConstants.ANY_LABEL;
            }
            else
            {
                if ([email protected]_Fields.NO_TOKEN == (labelId = transaction.TokenRead().nodeLabel(label.Name())))
                {
                    return(0);
                }
            }
            return(read.CountsForNode(labelId));
        }
예제 #18
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldComputeDegreeWithType() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldComputeDegreeWithType()
        {
            // GIVEN
            long node;
            int  @in, @out, loop;

            using (Transaction tx = Transaction())
            {
                Write write = tx.DataWrite();
                node = write.NodeCreate();
                TokenWrite tokenWrite = tx.TokenWrite();
                @out = tokenWrite.RelationshipTypeGetOrCreateForName("OUT");
                @in  = tokenWrite.RelationshipTypeGetOrCreateForName("IN");
                loop = tokenWrite.RelationshipTypeGetOrCreateForName("LOOP");
                write.RelationshipCreate(node, @out, write.NodeCreate());
                write.RelationshipCreate(node, @out, write.NodeCreate());
                write.RelationshipCreate(write.NodeCreate(), @in, node);
                write.RelationshipCreate(node, loop, node);

                tx.Success();
            }

            using (Transaction tx = Transaction())
            {
                Read          read    = tx.DataRead();
                CursorFactory cursors = tx.Cursors();
                using (NodeCursor nodes = cursors.AllocateNodeCursor())
                {
                    assertThat(nodeGetDegreeIfDense(read, node, nodes, cursors, OUTGOING, @out), equalTo(2));
                    assertThat(nodeGetDegreeIfDense(read, node, nodes, cursors, OUTGOING, @in), equalTo(0));
                    assertThat(nodeGetDegreeIfDense(read, node, nodes, cursors, OUTGOING, loop), equalTo(1));

                    assertThat(nodeGetDegreeIfDense(read, node, nodes, cursors, INCOMING, @out), equalTo(0));
                    assertThat(nodeGetDegreeIfDense(read, node, nodes, cursors, INCOMING, @in), equalTo(1));
                    assertThat(nodeGetDegreeIfDense(read, node, nodes, cursors, INCOMING, loop), equalTo(1));

                    assertThat(nodeGetDegreeIfDense(read, node, nodes, cursors, BOTH, @out), equalTo(2));
                    assertThat(nodeGetDegreeIfDense(read, node, nodes, cursors, BOTH, @in), equalTo(1));
                    assertThat(nodeGetDegreeIfDense(read, node, nodes, cursors, BOTH, loop), equalTo(1));
                }
            }
        }
예제 #19
0
        public static RelationshipSelectionCursor NodeGetRelationships(Read read, CursorFactory cursors, NodeCursor node, long nodeId, Direction direction, int[] types)
        {
            read.SingleNode(nodeId, node);
            if (!node.Next())
            {
                return(Org.Neo4j.@internal.Kernel.Api.helpers.RelationshipSelectionCursor_EMPTY);
            }
            switch (direction.innerEnumValue)
            {
            case Direction.InnerEnum.OUTGOING:
                return(RelationshipSelections.outgoingCursor(cursors, node, types));

            case Direction.InnerEnum.INCOMING:
                return(RelationshipSelections.incomingCursor(cursors, node, types));

            case Direction.InnerEnum.BOTH:
                return(RelationshipSelections.allCursor(cursors, node, types));

            default:
                throw new System.InvalidOperationException("Unknown direction " + direction);
            }
        }
예제 #20
0
 internal CursorPropertyAccessor(NodeCursor nodeCursor, PropertyCursor propertyCursor, Read read)
 {
     this._nodeCursor     = nodeCursor;
     this._propertyCursor = propertyCursor;
     this._read           = read;
 }
예제 #21
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldNotAllowConcurrentViolationOfConstraint() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldNotAllowConcurrentViolationOfConstraint()
        {
            // Given
            GraphDatabaseAPI graphDb = Db.GraphDatabaseAPI;

            System.Func <KernelTransaction> ktxSupplier = () => graphDb.DependencyResolver.resolveDependency(typeof(ThreadToStatementContextBridge)).getKernelTransactionBoundToThisThread(true);

            Label  label            = label("Foo");
            string propertyKey      = "bar";
            string conflictingValue = "baz";

            // a constraint
            using (Transaction tx = graphDb.BeginTx())
            {
                graphDb.Schema().constraintFor(label).assertPropertyIsUnique(propertyKey).create();
                tx.Success();
            }

            // When
            using (Transaction tx = graphDb.BeginTx())
            {
                KernelTransaction ktx         = ktxSupplier();
                int             labelId       = ktx.TokenRead().nodeLabel(label.Name());
                int             propertyKeyId = ktx.TokenRead().propertyKey(propertyKey);
                IndexDescriptor index         = TestIndexDescriptorFactory.uniqueForLabel(labelId, propertyKeyId);
                Read            read          = ktx.DataRead();
                using (NodeValueIndexCursor cursor = ktx.Cursors().allocateNodeValueIndexCursor())
                {
                    read.NodeIndexSeek(ktx.SchemaRead().index(labelId, propertyKeyId), cursor, IndexOrder.NONE, false, IndexQuery.exact(index.Schema().PropertyId, "The value is irrelevant, we just want to perform some sort of lookup against this " + "index"));
                }
                // then let another thread come in and create a node
                Threads.execute(Db =>
                {
                    using (Transaction transaction = Db.beginTx())
                    {
                        Db.createNode(label).setProperty(propertyKey, conflictingValue);
                        transaction.success();
                    }
                    return(null);
                }, graphDb).get();

                // before we create a node with the same property ourselves - using the same statement that we have
                // already used for lookup against that very same index
                long node = ktx.DataWrite().nodeCreate();
                ktx.DataWrite().nodeAddLabel(node, labelId);
                try
                {
                    ktx.DataWrite().nodeSetProperty(node, propertyKeyId, Values.of(conflictingValue));

                    fail("exception expected");
                }
                // Then
                catch (UniquePropertyValueValidationException e)
                {
                    assertEquals(ConstraintDescriptorFactory.uniqueForLabel(labelId, propertyKeyId), e.Constraint());
                    IndexEntryConflictException conflict = Iterators.single(e.Conflicts().GetEnumerator());
                    assertEquals(Values.stringValue(conflictingValue), conflict.SinglePropertyValue);
                }

                tx.Success();
            }
        }
예제 #22
0
 public override TxStateVisitor DecorateTxStateVisitor(StorageReader storageReader, Read read, CursorFactory cursorFactory, ReadableTransactionState state, TxStateVisitor visitor)
 {
     return(visitor);
 }
예제 #23
0
 public abstract TxStateVisitor DecorateTxStateVisitor(StorageReader storageReader, Read read, CursorFactory cursorFactory, ReadableTransactionState state, TxStateVisitor visitor);
예제 #24
0
 public static RelationshipSelectionCursor NodeGetRelationships(Read read, CursorFactory cursors, NodeCursor node, long nodeId, Direction direction)
 {
     return(NodeGetRelationships(read, cursors, node, nodeId, direction, null));
 }
예제 #25
0
 public override TxStateVisitor DecorateTxStateVisitor(StorageReader storageReader, Read read, CursorFactory cursorFactory, ReadableTransactionState txState, TxStateVisitor visitor)
 {
     if (!txState.HasDataChanges())
     {
         // If there are no data changes, there is no need to enforce constraints. Since there is no need to
         // enforce constraints, there is no need to build up the state required to be able to enforce constraints.
         // In fact, it might even be counter productive to build up that state, since if there are no data changes
         // there would be schema changes instead, and in that case we would throw away the schema-dependant state
         // we just built when the schema changing transaction commits.
         return(visitor);
     }
     return(getOrCreatePropertyExistenceEnforcerFrom(storageReader).decorate(visitor, read, cursorFactory));
 }