@Test
  public void shouldGetConstraintsByLabel() throws Exception {
    // given
    UniquenessConstraint constraint1 = new UniquenessConstraint(11, 66);
    UniquenessConstraint constraint2 = new UniquenessConstraint(11, 99);

    TxState txState =
        new TxStateImpl(
            mock(OldTxStateBridge.class), mock(PersistenceManager.class), mock(IdGeneration.class));
    KernelStatement state = mockedState(txState);
    when(inner.constraintsGetForLabelAndPropertyKey(10, 66))
        .thenAnswer(asAnswer(Collections.emptyList()));
    when(inner.constraintsGetForLabelAndPropertyKey(11, 99))
        .thenAnswer(asAnswer(Collections.emptyList()));
    when(inner.constraintsGetForLabel(10)).thenAnswer(asAnswer(Collections.emptyList()));
    when(inner.constraintsGetForLabel(11)).thenAnswer(asAnswer(asIterable(constraint1)));
    StateHandlingStatementOperations context = newTxStateOps(inner);
    context.uniquenessConstraintCreate(state, 10, 66);
    context.uniquenessConstraintCreate(state, 11, 99);

    // when
    Set<UniquenessConstraint> result = asSet(asIterable(context.constraintsGetForLabel(state, 11)));

    // then
    assertEquals(asSet(constraint1, constraint2), result);
  }
  @Override
  public Iterator<IndexDescriptor> uniqueIndexesGetAll(KernelStatement state) {
    if (state.hasTxStateWithChanges()) {
      return state.txState().constraintIndexChanges().apply(storeLayer.uniqueIndexesGetAll());
    }

    return storeLayer.uniqueIndexesGetAll();
  }
  @Override
  public Iterator<DefinedProperty> graphGetAllProperties(KernelStatement state) {
    if (state.hasTxStateWithChanges()) {
      return state.txState().augmentGraphProperties(storeLayer.graphGetAllProperties());
    }

    return storeLayer.graphGetAllProperties();
  }
  @Override
  public Iterator<IndexDescriptor> uniqueIndexesGetForLabel(KernelStatement state, int labelId) {
    if (state.hasTxStateWithChanges()) {
      return state
          .txState()
          .constraintIndexDiffSetsByLabel(labelId)
          .apply(storeLayer.uniqueIndexesGetForLabel(labelId));
    }

    return storeLayer.uniqueIndexesGetForLabel(labelId);
  }
  @Test
  public void correctlySaysNodeIsDeleted() throws Exception {
    // Given
    state.nodeDoDelete(1l);
    Node node = mock(Node.class);
    when(node.getId()).thenReturn(1l);
    when(ops.nodeGetAllProperties(1l)).thenReturn(IteratorUtil.<DefinedProperty>emptyIterator());
    when(ops.nodeGetLabels(1l)).thenReturn(PrimitiveIntCollections.emptyIterator());

    // When & Then
    assertThat(snapshot().isDeleted(node), equalTo(true));
  }
  @Override
  public PrimitiveLongIterator nodesGetForLabel(KernelStatement state, int labelId) {
    if (state.hasTxStateWithChanges()) {
      PrimitiveLongIterator wLabelChanges =
          state
              .txState()
              .nodesWithLabelChanged(labelId)
              .augment(storeLayer.nodesGetForLabel(state, labelId));
      return state.txState().addedAndRemovedNodes().augmentWithRemovals(wLabelChanges);
    }

    return storeLayer.nodesGetForLabel(state, labelId);
  }
 @Override
 public PrimitiveLongIterator nodeGetRelationships(
     KernelStatement state, long nodeId, Direction direction) throws EntityNotFoundException {
   if (state.hasTxStateWithChanges()) {
     ReadableTxState txState = state.txState();
     PrimitiveLongIterator stored;
     if (txState.nodeIsAddedInThisTx(nodeId)) {
       stored = PrimitiveLongCollections.emptyIterator();
     } else {
       stored = storeLayer.nodeListRelationships(nodeId, direction);
     }
     return txState.augmentRelationships(nodeId, direction, stored);
   }
   return storeLayer.nodeListRelationships(nodeId, direction);
 }
  @Test
  public void shouldListAddedLabels() throws Exception {
    // Given
    state.nodeDoAddLabel(2, 1l);
    when(ops.labelGetName(2)).thenReturn("theLabel");
    when(ops.nodeGetLabels(1l)).thenReturn(PrimitiveIntCollections.emptyIterator());

    // When
    Iterable<LabelEntry> labelEntries = snapshot().assignedLabels();

    // Then
    LabelEntry entry = single(labelEntries);
    assertThat(entry.label().name(), equalTo("theLabel"));
    assertThat(entry.node().getId(), equalTo(1l));
  }
  @Override
  public void relationshipDelete(final KernelStatement state, long relationshipId)
      throws EntityNotFoundException {
    assertRelationshipExists(state, relationshipId);

    // NOTE: We implicitly delegate to neoStoreTransaction via txState.legacyState here. This is
    // because that
    // call returns modified properties, which node manager uses to update legacy tx state. This
    // will be cleaned up
    // once we've removed legacy tx state.
    legacyPropertyTrackers.relationshipDelete(relationshipId);
    final TransactionState txState = state.txState();
    if (txState.relationshipIsAddedInThisTx(relationshipId)) {
      txState.relationshipDoDeleteAddedInThisTx(relationshipId);
    } else {
      try {
        storeLayer.relationshipVisit(
            relationshipId,
            new RelationshipVisitor<RuntimeException>() {
              @Override
              public void visit(long relId, int type, long startNode, long endNode) {
                txState.relationshipDoDelete(relId, type, startNode, endNode);
              }
            });
      } catch (EntityNotFoundException e) {
        // If it doesn't exist, it doesn't exist, and the user got what she wanted.
        return;
      }
    }
  }
 public AugmentWithLocalStateExpandCursor(
     StoreReadLayer store,
     ReadableTxState state,
     Cursor inputCursor,
     NeoRegister.Node.In nodeId,
     Register.Object.In<int[]> relTypes,
     Register.Object.In<Direction> expandDirection,
     NeoRegister.Relationship.Out relId,
     NeoRegister.RelType.Out relType,
     Register.Object.Out<Direction> direction,
     NeoRegister.Node.Out startNodeId,
     NeoRegister.Node.Out neighborNodeId) {
   this.txState = state;
   this.inputCursor = inputCursor;
   this.nodeId = nodeId;
   this.relTypes = relTypes;
   this.expandDirection = expandDirection;
   this.relId = relId;
   this.relType = relType;
   this.direction = direction;
   this.startNodeId = startNodeId;
   this.neighborNodeId = neighborNodeId;
   this.storeCursor =
       store.expand(
           storeInputCursor,
           nodeId,
           relTypes,
           expandDirection,
           relIdFromStore,
           relType,
           direction,
           startNodeId,
           neighborNodeId);
 }
  @Override
  public PrimitiveLongIterator graphGetPropertyKeys(KernelStatement state) {
    if (state.hasTxStateWithChanges()) {
      return new PropertyKeyIdIterator(graphGetAllProperties(state));
    }

    return storeLayer.graphGetPropertyKeys(state);
  }
 @Override
 public PrimitiveIntIterator nodeGetLabels(KernelStatement state, long nodeId)
     throws EntityNotFoundException {
   if (state.hasTxStateWithChanges()) {
     return nodeGetLabels(storeLayer, state.txState(), nodeId);
   }
   return storeLayer.nodeGetLabels(nodeId);
 }
  @Test
  public void showsRemovedRelationships() throws Exception {
    // Given
    state.relationshipDoDelete(1l, 1, 1l, 2l);
    state.relationshipDoDelete(2l, 1, 1l, 1l);

    when(ops.relationshipGetAllProperties(1l))
        .thenReturn(IteratorUtil.<DefinedProperty>emptyIterator());
    when(ops.relationshipGetAllProperties(2l))
        .thenReturn(asList(Property.stringProperty(1, "p")).iterator());
    when(ops.propertyKeyGetName(1)).thenReturn("key");

    // When & Then
    TxStateTransactionDataSnapshot snapshot = snapshot();
    assertThat(idList(snapshot.deletedRelationships()), equalTo(asList(1l, 2l)));
    assertThat(single(snapshot.removedRelationshipProperties()).key(), equalTo("key"));
  }
  @Test
  public void shouldListRemovedNodeProperties() throws Exception {
    // Given
    DefinedProperty prevProp = stringProperty(1, "prevValue");
    state.nodeDoRemoveProperty(1l, prevProp);
    when(ops.propertyKeyGetName(1)).thenReturn("theKey");
    when(ops.nodeGetProperty(1, 1)).thenReturn(prevProp);

    // When
    Iterable<PropertyEntry<Node>> propertyEntries = snapshot().removedNodeProperties();

    // Then
    PropertyEntry<Node> entry = single(propertyEntries);
    assertThat(entry.key(), equalTo("theKey"));
    assertThat(entry.previouslyCommitedValue(), equalTo((Object) "prevValue"));
    assertThat(entry.entity().getId(), equalTo(1l));
  }
  @Override
  public int nodeGetDegree(KernelStatement state, long nodeId, Direction direction)
      throws EntityNotFoundException {
    if (state.hasTxStateWithChanges()) {
      int degree = 0;
      if (state.txState().nodeIsDeletedInThisTx(nodeId)) {
        return 0;
      }

      if (!state.txState().nodeIsAddedInThisTx(nodeId)) {
        degree = storeLayer.nodeGetDegree(nodeId, direction);
      }
      return state.txState().augmentNodeDegree(nodeId, degree, direction);
    } else {
      return storeLayer.nodeGetDegree(nodeId, direction);
    }
  }
  @Override
  public PrimitiveLongIterator relationshipGetPropertyKeys(
      KernelStatement state, long relationshipId) throws EntityNotFoundException {
    if (state.hasTxStateWithChanges()) {
      return new PropertyKeyIdIterator(relationshipGetAllProperties(state, relationshipId));
    }

    return storeLayer.relationshipGetPropertyKeys(relationshipId);
  }
  @Override
  public Iterator<DefinedProperty> nodeGetAllProperties(KernelStatement state, long nodeId)
      throws EntityNotFoundException {
    if (state.hasTxStateWithChanges()) {
      if (state.txState().nodeIsAddedInThisTx(nodeId)) {
        return state.txState().addedAndChangedNodeProperties(nodeId);
      }
      if (state.txState().nodeIsDeletedInThisTx(nodeId)) {
        // TODO Throw IllegalStateException to conform with beans API. We may want to introduce
        // EntityDeletedException instead and use it instead of returning empty values in similar
        // places
        throw new IllegalStateException("Node " + nodeId + " has been deleted");
      }
      return state.txState().augmentNodeProperties(nodeId, storeLayer.nodeGetAllProperties(nodeId));
    }

    return storeLayer.nodeGetAllProperties(nodeId);
  }
 @Override
 public Iterator<UniquenessConstraint> constraintsGetForLabelAndPropertyKey(
     KernelStatement state, int labelId, int propertyKeyId) {
   return applyConstraintsDiff(
       state,
       storeLayer.constraintsGetForLabelAndPropertyKey(labelId, propertyKeyId),
       labelId,
       propertyKeyId);
 }
  @Test
  public void showsDeletedNodes() throws Exception {
    // Given
    state.nodeDoDelete(1l);
    state.nodeDoDelete(2l);
    when(ops.nodeGetAllProperties(1l)).thenReturn(IteratorUtil.<DefinedProperty>emptyIterator());
    when(ops.nodeGetAllProperties(2l))
        .thenReturn(asList(Property.stringProperty(1, "p")).iterator());
    when(ops.nodeGetLabels(1l)).thenReturn(PrimitiveIntCollections.emptyIterator());
    when(ops.nodeGetLabels(2l)).thenReturn(PrimitiveIntCollections.iterator(15));
    when(ops.propertyKeyGetName(1)).thenReturn("key");
    when(ops.labelGetName(15)).thenReturn("label");

    // When & Then
    TxStateTransactionDataSnapshot snapshot = snapshot();
    assertThat(idList(snapshot.deletedNodes()), equalTo(asList(1l, 2l)));
    assertThat(single(snapshot.removedLabels()).label().name(), equalTo("label"));
    assertThat(single(snapshot.removedNodeProperties()).key(), equalTo("key"));
  }
 @Override
 public long relationshipCreate(
     KernelStatement state, int relationshipTypeId, long startNodeId, long endNodeId)
     throws EntityNotFoundException {
   assertNodeExists(state, startNodeId);
   assertNodeExists(state, endNodeId);
   long id = storeLayer.reserveRelationship();
   state.txState().relationshipDoCreate(id, relationshipTypeId, startNodeId, endNodeId);
   return id;
 }
 @Override
 public long countsForNode(KernelStatement statement, int labelId) {
   long count = storeLayer.countsForNode(labelId);
   if (statement.hasTxState()) {
     if (labelId != ReadOperations.ANY_LABEL) {
       throw new UnsupportedOperationException("not implemented");
     }
     count += statement.txState().addedAndRemovedNodes().delta();
   }
   return count;
 }
  @Test
  public void shouldListAddedRelationshipProperties() throws Exception {
    // Given
    DefinedProperty prevProp = stringProperty(1, "prevValue");
    state.relationshipDoReplaceProperty(1l, prevProp, stringProperty(1, "newValue"));

    when(ops.propertyKeyGetName(1)).thenReturn("theKey");
    when(ops.relationshipGetProperty(1, 1)).thenReturn(prevProp);

    // When
    Iterable<PropertyEntry<Relationship>> propertyEntries =
        snapshot().assignedRelationshipProperties();

    // Then
    PropertyEntry<Relationship> entry = single(propertyEntries);
    assertThat(entry.key(), equalTo("theKey"));
    assertThat(entry.value(), equalTo((Object) "newValue"));
    assertThat(entry.previouslyCommitedValue(), equalTo((Object) "prevValue"));
    assertThat(entry.entity().getId(), equalTo(1l));
  }
 // <Legacy index>
 @Override
 public <EXCEPTION extends Exception> void relationshipVisit(
     KernelStatement statement, long relId, RelationshipVisitor<EXCEPTION> visitor)
     throws EntityNotFoundException, EXCEPTION {
   if (statement.hasTxStateWithChanges()) {
     if (statement.txState().relationshipVisit(relId, visitor)) {
       return;
     }
   }
   storeLayer.relationshipVisit(relId, visitor);
 }
 @Override
 public long nodeGetUniqueFromIndexLookup(
     KernelStatement state, IndexDescriptor index, Object value)
     throws IndexNotFoundKernelException, IndexBrokenKernelException {
   PrimitiveLongResourceIterator committed =
       storeLayer.nodeGetUniqueFromIndexLookup(state, index, value);
   PrimitiveLongIterator exactMatches = filterExactIndexMatches(state, index, value, committed);
   PrimitiveLongIterator changeFilteredMatches =
       filterIndexStateChanges(state, index, value, exactMatches);
   return single(resourceIterator(changeFilteredMatches, committed), NO_SUCH_NODE);
 }
 @Override
 public PrimitiveLongIterator nodesGetFromIndexLookup(
     KernelStatement state, IndexDescriptor index, final Object value)
     throws IndexNotFoundKernelException {
   PrimitiveLongResourceIterator committed =
       storeLayer.nodesGetFromIndexLookup(state, index, value);
   PrimitiveLongIterator exactMatches = filterExactIndexMatches(state, index, value, committed);
   PrimitiveLongIterator changeFilteredMatches =
       filterIndexStateChanges(state, index, value, exactMatches);
   return resourceIterator(changeFilteredMatches, committed);
 }
 public static PrimitiveIntIterator nodeGetLabels(
     StoreReadLayer storeLayer, ReadableTxState txState, long nodeId)
     throws EntityNotFoundException {
   if (txState.nodeIsDeletedInThisTx(nodeId)) {
     return PrimitiveIntCollections.emptyIterator();
   }
   if (txState.nodeIsAddedInThisTx(nodeId)) {
     return PrimitiveIntCollections.toPrimitiveIterator(
         txState.nodeStateLabelDiffSets(nodeId).getAdded().iterator());
   }
   return txState.nodeStateLabelDiffSets(nodeId).augment(storeLayer.nodeGetLabels(nodeId));
 }
  @Override
  public PrimitiveIntIterator nodeGetLabels(KernelStatement state, long nodeId)
      throws EntityNotFoundException {
    if (state.hasTxStateWithChanges()) {
      if (state.txState().nodeIsDeletedInThisTx(nodeId)) {
        return PrimitiveIntCollections.emptyIterator();
      }

      if (state.txState().nodeIsAddedInThisTx(nodeId)) {
        return PrimitiveIntCollections.toPrimitiveIterator(
            state.txState().nodeStateLabelDiffSets(nodeId).getAdded().iterator());
      }

      return state
          .txState()
          .nodeStateLabelDiffSets(nodeId)
          .augment(storeLayer.nodeGetLabels(nodeId));
    }

    return storeLayer.nodeGetLabels(nodeId);
  }
  @Test
  public void correctlySaysRelIsDeleted() throws Exception {
    // Given
    state.relationshipDoDelete(1l, 1, 1l, 2l);

    Relationship rel = mock(Relationship.class);
    when(rel.getId()).thenReturn(1l);
    when(ops.relationshipGetAllProperties(1l))
        .thenReturn(Collections.<DefinedProperty>emptyIterator());

    // When & Then
    assertThat(snapshot().isDeleted(rel), equalTo(true));
  }
  @Override
  public IndexDescriptor indexesGetForLabelAndPropertyKey(
      KernelStatement state, int labelId, int propertyKey) {
    IndexDescriptor indexDescriptor =
        storeLayer.indexesGetForLabelAndPropertyKey(labelId, propertyKey);

    Iterator<IndexDescriptor> rules = iterator(indexDescriptor);
    if (state.hasTxStateWithChanges()) {
      rules =
          filterByPropertyKeyId(
              state.txState().indexDiffSetsByLabel(labelId).apply(rules), propertyKey);
    }
    return singleOrNull(rules);
  }
  @Test
  public void shouldListRemovedLabels() throws Exception {
    // Given
    state.nodeDoRemoveLabel(2, 1l);
    when(ops.labelGetName(2)).thenReturn("theLabel");

    // When
    Iterable<LabelEntry> labelEntries = snapshot().removedLabels();

    // Then
    LabelEntry entry = single(labelEntries);
    assertThat(entry.label().name(), equalTo("theLabel"));
    assertThat(entry.node().getId(), equalTo(1l));
  }