From 141d9b3bb8bff2152d72a22563dc87b2831bebe5 Mon Sep 17 00:00:00 2001
From: Dominik Gleich <dominik.gleich@memgraph.io>
Date: Wed, 7 Jun 2017 09:49:51 +0200
Subject: [PATCH] Rework of index api. Remove implicit default value of
 current_state in graph_db_accessor.

Reviewers: buda, florijan

Reviewed By: buda, florijan

Subscribers: mislav.bradac, pullbot

Differential Revision: https://phabricator.memgraph.io/D392
---
 src/data_structures/concurrent/skiplist.hpp   |  18 ++-
 src/database/graph_db_accessor.hpp            |  40 +++++--
 .../{index_utils.hpp => index_common.hpp}     |  59 +++++++++-
 src/database/indexes/key_index.hpp            |  26 +++--
 src/database/indexes/label_property_index.hpp |  68 +++++++++---
 src/durability/snapshooter.cpp                |   4 +-
 tests/integration/hardcoded_query/clique.hpp  |   4 +-
 .../hardcoded_query/delete_all.cpp            |   2 +-
 .../hardcoded_query/match_garment.cpp         |   2 +-
 .../match_garment_default_outfit.cpp          |   4 +-
 ...match_garment_set_label_general_return.hpp |   2 +-
 .../hardcoded_query/match_profile.cpp         |   2 +-
 .../match_profile_garment_score.cpp           |   2 +-
 .../match_profile_garment_set_score.cpp       |   4 +-
 .../match_profile_garment_update_score.cpp    |   2 +-
 tests/unit/database_key_index.cpp             |  14 +--
 tests/unit/database_label_property_index.cpp  |  12 +-
 tests/unit/graph_db_accessor.cpp              | 103 +++++++++---------
 tests/unit/graph_db_accessor_index_api.cpp    |  59 +++++++---
 .../unit/query_plan_accumulate_aggregate.cpp  |   4 +-
 tests/unit/query_plan_bag_semantics.cpp       |  14 +--
 .../query_plan_create_set_remove_delete.cpp   |  88 +++++++--------
 tests/unit/query_plan_match_filter_return.cpp |  10 +-
 tests/unit/record_edge_vertex_accessor.cpp    |  14 +--
 tests/unit/skiplist_suffix.cpp                |  40 +++++++
 25 files changed, 398 insertions(+), 199 deletions(-)
 rename src/database/indexes/{index_utils.hpp => index_common.hpp} (76%)
 create mode 100644 tests/unit/skiplist_suffix.cpp

diff --git a/src/data_structures/concurrent/skiplist.hpp b/src/data_structures/concurrent/skiplist.hpp
index 02c4c06df..2c8220081 100644
--- a/src/data_structures/concurrent/skiplist.hpp
+++ b/src/data_structures/concurrent/skiplist.hpp
@@ -241,6 +241,16 @@ class SkipList : private Lockable<lock_t> {
     IteratorBase() = default;
     IteratorBase(const IteratorBase &) = default;
 
+    const T &operator*() const {
+      debug_assert(node != nullptr, "Node is nullptr.");
+      return node->value();
+    }
+
+    const T *operator->() const {
+      debug_assert(node != nullptr, "Node is nullptr.");
+      return &node->value();
+    }
+
     T &operator*() {
       debug_assert(node != nullptr, "Node is nullptr.");
       return node->value();
@@ -284,9 +294,13 @@ class SkipList : private Lockable<lock_t> {
     ConstIterator() = default;
     ConstIterator(const ConstIterator &) = default;
 
-    const T &operator*() { return IteratorBase<ConstIterator>::operator*(); }
+    const T &operator*() const {
+      return IteratorBase<ConstIterator>::operator*();
+    }
 
-    const T *operator->() { return IteratorBase<ConstIterator>::operator->(); }
+    const T *operator->() const {
+      return IteratorBase<ConstIterator>::operator->();
+    }
 
     operator const T &() { return IteratorBase<ConstIterator>::operator T &(); }
   };
diff --git a/src/database/graph_db_accessor.hpp b/src/database/graph_db_accessor.hpp
index 7190494db..979853b3e 100644
--- a/src/database/graph_db_accessor.hpp
+++ b/src/database/graph_db_accessor.hpp
@@ -91,7 +91,7 @@ class GraphDbAccessor {
    *    deletions performed in the current transaction+command are not
    *    ignored).
    */
-  auto vertices(bool current_state = false) {
+  auto vertices(bool current_state) {
     // wrap version lists into accessors, which will look for visible versions
     auto accessors =
         iter::imap([this](auto vlist) { return VertexAccessor(*vlist, *this); },
@@ -119,7 +119,7 @@ class GraphDbAccessor {
    *    ignored).
    * @return iterable collection
    */
-  auto vertices(const GraphDbTypes::Label &label, bool current_state = false) {
+  auto vertices(const GraphDbTypes::Label &label, bool current_state) {
     return iter::imap(
         [this, current_state](auto vlist) {
           return VertexAccessor(*vlist, *this);
@@ -139,8 +139,7 @@ class GraphDbAccessor {
    * @return iterable collection
    */
   auto vertices(const GraphDbTypes::Label &label,
-                const GraphDbTypes::Property &property,
-                bool current_state = false) {
+                const GraphDbTypes::Property &property, bool current_state) {
     debug_assert(db_.label_property_index_.IndexExists(
                      LabelPropertyIndex::Key(label, property)),
                  "Label+property index doesn't exist.");
@@ -151,6 +150,34 @@ class GraphDbAccessor {
                           *transaction_, current_state));
   }
 
+  /**
+   * Return VertexAccessors which contain the current label + property, and
+   * those properties are equal to this 'value' for the given transaction
+   * visibility.
+   * @param label - label for which to return VertexAccessors
+   * @param property - property for which to return VertexAccessors
+   * @param value - property value for which to return VertexAccessors
+   * @param current_state If true then the graph state for the
+   *    current transaction+command is returned (insertions, updates and
+   *    deletions performed in the current transaction+command are not
+   *    ignored).
+   * @return iterable collection
+   */
+  auto vertices(const GraphDbTypes::Label &label,
+                const GraphDbTypes::Property &property,
+                const PropertyValue &value, bool current_state) {
+    debug_assert(db_.label_property_index_.IndexExists(
+                     LabelPropertyIndex::Key(label, property)),
+                 "Label+property index doesn't exist.");
+    debug_assert(value.type() != PropertyValue::Type::Null,
+                 "Can't query index for propery value type null.");
+    return iter::imap([this, current_state](
+                          auto vlist) { return VertexAccessor(*vlist, *this); },
+                      db_.label_property_index_.GetVlists(
+                          LabelPropertyIndex::Key(label, property), value,
+                          *transaction_, current_state));
+  }
+
   /**
    * Creates a new Edge and returns an accessor to it.
    *
@@ -178,7 +205,7 @@ class GraphDbAccessor {
    *    deletions performed in the current transaction+command are not
    *    ignored).
    */
-  auto edges(bool current_state = false) {
+  auto edges(bool current_state) {
     // wrap version lists into accessors, which will look for visible versions
     auto accessors =
         iter::imap([this](auto vlist) { return EdgeAccessor(*vlist, *this); },
@@ -206,8 +233,7 @@ class GraphDbAccessor {
    *    ignored).
    * @return iterable collection
    */
-  auto edges(const GraphDbTypes::EdgeType &edge_type,
-             bool current_state = false) {
+  auto edges(const GraphDbTypes::EdgeType &edge_type, bool current_state) {
     return iter::imap([this, current_state](
                           auto vlist) { return EdgeAccessor(*vlist, *this); },
                       db_.edge_types_index_.GetVlists(edge_type, *transaction_,
diff --git a/src/database/indexes/index_utils.hpp b/src/database/indexes/index_common.hpp
similarity index 76%
rename from src/database/indexes/index_utils.hpp
rename to src/database/indexes/index_common.hpp
index 1b63e96d8..24a8d4549 100644
--- a/src/database/indexes/index_utils.hpp
+++ b/src/database/indexes/index_common.hpp
@@ -2,16 +2,61 @@
 
 #include "cppitertools/filter.hpp"
 #include "cppitertools/imap.hpp"
+#include "cppitertools/takewhile.hpp"
 
 #include "data_structures/concurrent/concurrent_map.hpp"
+#include "data_structures/concurrent/skiplist.hpp"
 #include "mvcc/version_list.hpp"
 #include "transactions/transaction.hpp"
 
 namespace IndexUtils {
+/**
+ * @brief - Wrap beginning iterator to iterable object. This provides us with
+ * begin and end iterator, and allows us to iterate from the iterator given in
+ * constructor till the end of the collection over which we are really
+ * iterating, i.e. it allows us to iterate over the suffix of some skiplist
+ * hence the name SkipListSuffix.
+ */
+template <class TIterator, class TValue>
+class SkipListSuffix {
+ public:
+  class Iterator {
+   public:
+    Iterator(TIterator current) : current_(current) {}
+
+    TValue &operator*() { return *current_; }
+
+    bool operator!=(Iterator other) const {
+      return this->current_ != other.current_;
+    }
+
+    Iterator &operator++() {
+      ++current_;
+      return *this;
+    }
+
+   private:
+    TIterator current_;
+  };
+
+  SkipListSuffix(const TIterator begin,
+                 typename SkipList<TValue>::Accessor &&accessor)
+      : begin_(begin), accessor_(std::move(accessor)) {}
+
+  Iterator begin() const { return Iterator(begin_); }
+  Iterator end() { return Iterator(accessor_.end()); }
+
+  TIterator begin_;
+  typename SkipList<TValue>::Accessor accessor_;
+};
 /**
  * @brief - Get all inserted vlists in TKey specific storage which
  * still return true for the 'exists' function.
- * @param index - index from which to get vlists
+ * @param skiplist_accessor - accessor used to get begin iterator, and that
+ * should be used to get end iterator as well.
+ * @param begin - starting iterator for vlist iteration.
+ * @param predicate - function which checks if TIndexEntry has a value that we
+ * are looking for
  * @param t - current transaction, which determines visibility.
  * @param exists - method which determines visibility of entry and version
  * (record) of the underlying objects (vertex/edge)
@@ -24,12 +69,18 @@ namespace IndexUtils {
  * @return iterable collection of distinct vlist records<TRecord> for which
  * exists function evaluates as true
  */
-template <class TIndexEntry, class TRecord>
+template <class TIterator, class TIndexEntry, class TRecord>
 static auto GetVlists(
-    SkipList<TIndexEntry> &index, const tx::Transaction &t,
+    typename SkipList<TIndexEntry>::Accessor &&skiplist_accessor,
+    TIterator begin,
+    const std::function<bool(const TIndexEntry &entry)> predicate,
+    const tx::Transaction &t,
     const std::function<bool(const TIndexEntry &, const TRecord *)> exists,
     bool current_state = false) {
   TIndexEntry *prev = nullptr;
+  auto range =
+      iter::takewhile(predicate, SkipListSuffix<TIterator, TIndexEntry>(
+                                     begin, std::move(skiplist_accessor)));
   auto filtered = iter::filter(
       [&t, exists, prev, current_state](TIndexEntry &entry) mutable {
         // Check if the current entry could offer new possible return value
@@ -57,7 +108,7 @@ static auto GetVlists(
         return (current_state && new_record) ? exists(entry, new_record)
                                              : exists(entry, old_record);
       },
-      index.access());
+      std::move(range));
   return iter::imap([](auto entry) { return entry.vlist_; },
                     std::move(filtered));
 }
diff --git a/src/database/indexes/key_index.hpp b/src/database/indexes/key_index.hpp
index f1bf00d44..5dabbd67c 100644
--- a/src/database/indexes/key_index.hpp
+++ b/src/database/indexes/key_index.hpp
@@ -3,7 +3,7 @@
 #include "data_structures/concurrent/concurrent_map.hpp"
 #include "database/graph_db.hpp"
 #include "database/graph_db_datatypes.hpp"
-#include "database/indexes/index_utils.hpp"
+#include "database/indexes/index_common.hpp"
 #include "mvcc/version_list.hpp"
 #include "storage/edge.hpp"
 #include "storage/vertex.hpp"
@@ -55,12 +55,14 @@ class KeyIndex {
    * @return iterable collection of vlists records<TRecord> with the requested
    * TKey.
    */
-  auto GetVlists(const TKey &key, tx::Transaction &t,
-                 bool current_state = false) {
-    return IndexUtils::GetVlists<IndexEntry, TRecord>(
-        *GetKeyStorage(key), t,
-        [this, key](const IndexEntry &, const TRecord *record) {
-          return Exists(key, record);
+  auto GetVlists(const TKey &key, tx::Transaction &t, bool current_state) {
+    auto access = GetKeyStorage(key)->access();
+    auto begin = access.begin();
+    return IndexUtils::GetVlists<typename SkipList<IndexEntry>::Iterator,
+                                 IndexEntry, TRecord>(
+        std::move(access), begin, [](const IndexEntry &) { return true; }, t,
+        [key](const IndexEntry &, const TRecord *record) {
+          return KeyIndex::Exists(key, record);
         },
         current_state);
   }
@@ -87,8 +89,8 @@ class KeyIndex {
    */
   void Refresh(const Id &id, tx::Engine &engine) {
     return IndexUtils::Refresh<TKey, IndexEntry, TRecord>(
-        indices_, id, engine, [this](const TKey &key, const IndexEntry &entry) {
-          return Exists(key, entry.record_);
+        indices_, id, engine, [](const TKey &key, const IndexEntry &entry) {
+          return KeyIndex::Exists(key, entry.record_);
         });
   }
 
@@ -157,7 +159,7 @@ class KeyIndex {
    * @param label - label to check for.
    * @return true if it contains, false otherwise.
    */
-  bool Exists(const GraphDbTypes::Label &label, const Vertex *const v) const {
+  static bool Exists(const GraphDbTypes::Label &label, const Vertex *const v) {
     debug_assert(v != nullptr, "Vertex is nullptr.");
     // We have to check for existance of label because the transaction
     // might not see the label, or the label was deleted and not yet
@@ -171,8 +173,8 @@ class KeyIndex {
    * @param edge_type - edge_type to check for.
    * @return true if it has that edge_type, false otherwise.
    */
-  bool Exists(const GraphDbTypes::EdgeType &edge_type,
-              const Edge *const e) const {
+  static bool Exists(const GraphDbTypes::EdgeType &edge_type,
+                     const Edge *const e) {
     debug_assert(e != nullptr, "Edge is nullptr.");
     // We have to check for equality of edge types because the transaction
     // might not see the edge type, or the edge type was deleted and not yet
diff --git a/src/database/indexes/label_property_index.hpp b/src/database/indexes/label_property_index.hpp
index a630a7b57..13db27666 100644
--- a/src/database/indexes/label_property_index.hpp
+++ b/src/database/indexes/label_property_index.hpp
@@ -3,7 +3,7 @@
 #include "data_structures/concurrent/concurrent_map.hpp"
 #include "database/graph_db.hpp"
 #include "database/graph_db_datatypes.hpp"
-#include "database/indexes/index_utils.hpp"
+#include "database/indexes/index_common.hpp"
 #include "mvcc/version_list.hpp"
 #include "storage/edge.hpp"
 #include "storage/vertex.hpp"
@@ -12,6 +12,11 @@
 
 /**
  * @brief Implements LabelPropertyIndex.
+ * Currently this provides implementation for:
+ *    acquiring all entries which contain the given label, and a given property
+ * sorted by the property value
+ *    acquiring all non-unique entries with the given label, and property, with
+ * exactly one property value
  */
 class LabelPropertyIndex {
  public:
@@ -159,13 +164,50 @@ class LabelPropertyIndex {
    * @return iterable collection of vlists of vertex records with the requested
    * key sorted ascendingly by the property value.
    */
-  auto GetVlists(const Key &key, const tx::Transaction &t,
-                 bool current_state = false) {
+  auto GetVlists(const Key &key, const tx::Transaction &t, bool current_state) {
     debug_assert(ready_for_use_.access().contains(key), "Index not yet ready.");
-    return IndexUtils::GetVlists<IndexEntry, Vertex>(
-        *GetKeyStorage(key), t,
-        [this, key](const IndexEntry &entry, const Vertex *const vertex) {
-          return Exists(key, entry.value_, vertex);
+    auto access = GetKeyStorage(key)->access();
+    auto begin = access.begin();
+    return IndexUtils::GetVlists<typename SkipList<IndexEntry>::Iterator,
+                                 IndexEntry, Vertex>(
+        std::move(access), begin, [](const IndexEntry &) { return true; }, t,
+        [key](const IndexEntry &entry, const Vertex *const vertex) {
+          return LabelPropertyIndex::Exists(key, entry.value_, vertex);
+        },
+        current_state);
+  }
+
+  /**
+   * @brief - Get all the inserted vlists in key specific storage which still
+   * have that label and property visible in this transaction with property
+   * value equal to 'value'.
+   * @param key - Label+Property to query.
+   * @param value - vlists with this value will be returned
+   * @param t - current transaction, which determines visibility.
+   * @param current_state If true then the graph state for the
+   *    current transaction+command is returned (insertions, updates and
+   *    deletions performed in the current transaction+command are not
+   *    ignored).
+   * @return iterable collection of vlists of vertex records with the requested
+   * key and value
+   */
+  auto GetVlists(const Key &key, const PropertyValue &value,
+                 const tx::Transaction &t, bool current_state) {
+    debug_assert(ready_for_use_.access().contains(key), "Index not yet ready.");
+    auto access = GetKeyStorage(key)->access();
+    auto start_iter =
+        access.find_or_larger<typename SkipList<IndexEntry>::Iterator,
+                              IndexEntry>(IndexEntry(value, nullptr, nullptr));
+    return IndexUtils::GetVlists<typename SkipList<IndexEntry>::Iterator,
+                                 IndexEntry, Vertex>(
+        std::move(access), start_iter,
+        [value](const IndexEntry &entry) {
+          return !IndexEntry::Cmp(value, entry.value_) &&
+                 !IndexEntry::Cmp(entry.value_, value);
+        },
+        t,
+        [key](const IndexEntry &entry, const Vertex *const vertex) {
+          return LabelPropertyIndex::Exists(key, entry.value_, vertex);
         },
         current_state);
   }
@@ -206,8 +248,8 @@ class LabelPropertyIndex {
    */
   void Refresh(const Id &id, tx::Engine &engine) {
     return IndexUtils::Refresh<Key, IndexEntry, Vertex>(
-        indices_, id, engine, [this](const Key &key, const IndexEntry &entry) {
-          return Exists(key, entry.value_, entry.record_);
+        indices_, id, engine, [](const Key &key, const IndexEntry &entry) {
+          return LabelPropertyIndex::Exists(key, entry.value_, entry.record_);
         });
   }
 
@@ -346,12 +388,12 @@ class LabelPropertyIndex {
   /**
    * @brief - Check if Vertex contains label and property with the given
    * value.
-   * @param key - label and parameter to check for.
-   * @param value - value of parameter to compare
+   * @param key - label and property to check for.
+   * @param value - value of property to compare
    * @return true if it contains, false otherwise.
    */
-  bool Exists(const Key &key, const PropertyValue &value,
-              const Vertex *const v) const {
+  static bool Exists(const Key &key, const PropertyValue &value,
+                     const Vertex *const v) {
     debug_assert(v != nullptr, "Vertex is nullptr.");
     // We have to check for existance of label because the transaction
     // might not see the label, or the label was deleted and not yet
diff --git a/src/durability/snapshooter.cpp b/src/durability/snapshooter.cpp
index 5fc089162..50faaf07b 100644
--- a/src/durability/snapshooter.cpp
+++ b/src/durability/snapshooter.cpp
@@ -32,11 +32,11 @@ bool Snapshooter::Encode(const fs::path &snapshot_file,
     int64_t vertex_num = 0, edge_num = 0;
 
     buffer.Open(snapshot_file);
-    for (const auto &vertex : db_accessor_.vertices()) {
+    for (const auto &vertex : db_accessor_.vertices(false)) {
       encoder.WriteVertex(vertex);
       vertex_num++;
     }
-    for (const auto &edge : db_accessor_.edges()) {
+    for (const auto &edge : db_accessor_.edges(false)) {
       encoder.WriteEdge(edge);
       edge_num++;
     }
diff --git a/tests/integration/hardcoded_query/clique.hpp b/tests/integration/hardcoded_query/clique.hpp
index 47792e322..80f0aa767 100644
--- a/tests/integration/hardcoded_query/clique.hpp
+++ b/tests/integration/hardcoded_query/clique.hpp
@@ -39,8 +39,8 @@ bool run_general_query(GraphDbAccessor &db_accessor, const Parameters &args,
   // TODO dgleich: this code is very inefficient as it first makes a copy
   // of all the vertices/edges, and filters aftwarwards. I warned about this
   // happening in code review!!!
-  auto vertices_iterator = db_accessor.vertices();
-  auto edge_iterator = db_accessor.edges();
+  auto vertices_iterator = db_accessor.vertices(false);
+  auto edge_iterator = db_accessor.edges(false);
   std::vector<VertexAccessor> vertices(vertices_iterator.begin(),
                                        vertices_iterator.end());
   std::vector<EdgeAccessor> edges(edge_iterator.begin(), edge_iterator.end());
diff --git a/tests/integration/hardcoded_query/delete_all.cpp b/tests/integration/hardcoded_query/delete_all.cpp
index 6c8f3aa32..9c3906374 100644
--- a/tests/integration/hardcoded_query/delete_all.cpp
+++ b/tests/integration/hardcoded_query/delete_all.cpp
@@ -17,7 +17,7 @@ class CPUPlan : public PlanInterface<Stream> {
  public:
   bool run(GraphDbAccessor &db_accessor, const Parameters &args,
            Stream &stream) {
-    for (auto v : db_accessor.vertices()) db_accessor.detach_remove_vertex(v);
+    for (auto v : db_accessor.vertices(false)) db_accessor.detach_remove_vertex(v);
     std::vector<std::string> headers;
     stream.Header(headers);
     return true;
diff --git a/tests/integration/hardcoded_query/match_garment.cpp b/tests/integration/hardcoded_query/match_garment.cpp
index 10d5e6a12..5d6ef44a2 100644
--- a/tests/integration/hardcoded_query/match_garment.cpp
+++ b/tests/integration/hardcoded_query/match_garment.cpp
@@ -20,7 +20,7 @@ class CPUPlan : public PlanInterface<Stream> {
            Stream &stream) {
     std::vector<std::string> headers{std::string("g")};
     stream.Header(headers);
-    for (auto vertex : db_accessor.vertices()) {
+    for (auto vertex : db_accessor.vertices(false)) {
       if (vertex.has_label(db_accessor.label("garment"))) {
         TypedValue prop = vertex.PropsAt(db_accessor.property("garment_id"));
         if (prop.type() == TypedValue::Type::Null) continue;
diff --git a/tests/integration/hardcoded_query/match_garment_default_outfit.cpp b/tests/integration/hardcoded_query/match_garment_default_outfit.cpp
index d85c836f8..df842f70a 100644
--- a/tests/integration/hardcoded_query/match_garment_default_outfit.cpp
+++ b/tests/integration/hardcoded_query/match_garment_default_outfit.cpp
@@ -22,7 +22,7 @@ class CPUPlan : public PlanInterface<Stream> {
     std::vector<std::string> headers{std::string("r")};
     stream.Header(headers);
     std::vector<VertexAccessor> g1_set, g2_set;
-    for (auto g1 : db_accessor.vertices()) {
+    for (auto g1 : db_accessor.vertices(false)) {
       if (g1.has_label(db_accessor.label("garment"))) {
         TypedValue prop = g1.PropsAt(db_accessor.property("garment_id"));
         if (prop.type() == TypedValue::Type::Null) continue;
@@ -32,7 +32,7 @@ class CPUPlan : public PlanInterface<Stream> {
         g1_set.push_back(g1);
       }
     }
-    for (auto g2 : db_accessor.vertices()) {
+    for (auto g2 : db_accessor.vertices(false)) {
       if (g2.has_label(db_accessor.label("garment"))) {
         auto prop = g2.PropsAt(db_accessor.property("garment_id"));
         if (prop.type() == PropertyValue::Type::Null) continue;
diff --git a/tests/integration/hardcoded_query/match_garment_set_label_general_return.hpp b/tests/integration/hardcoded_query/match_garment_set_label_general_return.hpp
index cf09e4a20..d18313c67 100644
--- a/tests/integration/hardcoded_query/match_garment_set_label_general_return.hpp
+++ b/tests/integration/hardcoded_query/match_garment_set_label_general_return.hpp
@@ -18,7 +18,7 @@ bool run_general_query(GraphDbAccessor &db_accessor, const Parameters &args,
                        Stream &stream, const std::string &general_label) {
   std::vector<std::string> headers{std::string("g")};
   stream.Header(headers);
-  for (auto vertex : db_accessor.vertices()) {
+  for (auto vertex : db_accessor.vertices(false)) {
     if (vertex.has_label(db_accessor.label("garment"))) {
       query::TypedValue prop =
           vertex.PropsAt(db_accessor.property("garment_id"));
diff --git a/tests/integration/hardcoded_query/match_profile.cpp b/tests/integration/hardcoded_query/match_profile.cpp
index 310423fde..e708800d9 100644
--- a/tests/integration/hardcoded_query/match_profile.cpp
+++ b/tests/integration/hardcoded_query/match_profile.cpp
@@ -20,7 +20,7 @@ class CPUPlan : public PlanInterface<Stream> {
            Stream &stream) {
     std::vector<std::string> headers{std::string("p")};
     stream.Header(headers);
-    for (auto vertex : db_accessor.vertices()) {
+    for (auto vertex : db_accessor.vertices(false)) {
       if (vertex.has_label(db_accessor.label("profile"))) {
         TypedValue prop = vertex.PropsAt(db_accessor.property("profile_id"));
         if (prop.type() == TypedValue::Type::Null) continue;
diff --git a/tests/integration/hardcoded_query/match_profile_garment_score.cpp b/tests/integration/hardcoded_query/match_profile_garment_score.cpp
index 58bbf225e..3f5faabd7 100644
--- a/tests/integration/hardcoded_query/match_profile_garment_score.cpp
+++ b/tests/integration/hardcoded_query/match_profile_garment_score.cpp
@@ -43,7 +43,7 @@ class CPUPlan : public PlanInterface<Stream> {
       if (cmp.type() != TypedValue::Type::Bool) return false;
       return cmp.Value<bool>();
     };
-    for (auto edge : db_accessor.edges()) {
+    for (auto edge : db_accessor.edges(false)) {
       auto from = edge.from();
       auto to = edge.to();
       if (edge.edge_type() != db_accessor.edge_type("score")) continue;
diff --git a/tests/integration/hardcoded_query/match_profile_garment_set_score.cpp b/tests/integration/hardcoded_query/match_profile_garment_set_score.cpp
index 168319544..221318081 100644
--- a/tests/integration/hardcoded_query/match_profile_garment_set_score.cpp
+++ b/tests/integration/hardcoded_query/match_profile_garment_set_score.cpp
@@ -22,7 +22,7 @@ class CPUPlan : public PlanInterface<Stream> {
     std::vector<std::string> headers{std::string("r")};
     stream.Header(headers);
     std::vector<VertexAccessor> g1_set, g2_set;
-    for (auto g1 : db_accessor.vertices()) {
+    for (auto g1 : db_accessor.vertices(false)) {
       if (g1.has_label(db_accessor.label("profile"))) {
         auto prop = TypedValue(g1.PropsAt(db_accessor.property("profile_id")));
         if (prop.type() == TypedValue::Type::Null) continue;
@@ -38,7 +38,7 @@ class CPUPlan : public PlanInterface<Stream> {
         g1_set.push_back(g1);
       }
     }
-    for (auto g2 : db_accessor.vertices()) {
+    for (auto g2 : db_accessor.vertices(false)) {
       if (g2.has_label(db_accessor.label("garment"))) {
         auto prop = TypedValue(g2.PropsAt(db_accessor.property("garment_id")));
         if (prop.type() == TypedValue::Type::Null) continue;
diff --git a/tests/integration/hardcoded_query/match_profile_garment_update_score.cpp b/tests/integration/hardcoded_query/match_profile_garment_update_score.cpp
index 56fc3ff15..291ee564f 100644
--- a/tests/integration/hardcoded_query/match_profile_garment_update_score.cpp
+++ b/tests/integration/hardcoded_query/match_profile_garment_update_score.cpp
@@ -42,7 +42,7 @@ class CPUPlan : public PlanInterface<Stream> {
       if (cmp.type() != TypedValue::Type::Bool) return false;
       return cmp.Value<bool>();
     };
-    for (auto edge : db_accessor.edges()) {
+    for (auto edge : db_accessor.edges(false)) {
       auto from = edge.from();
       auto to = edge.to();
       if (edge.edge_type() != db_accessor.edge_type("score")) continue;
diff --git a/tests/unit/database_key_index.cpp b/tests/unit/database_key_index.cpp
index b3b9d776d..f4e4c3103 100644
--- a/tests/unit/database_key_index.cpp
+++ b/tests/unit/database_key_index.cpp
@@ -39,8 +39,8 @@ TEST(LabelsIndex, UniqueInsert) {
 
 // Check if index filters duplicates.
 TEST(LabelsIndex, UniqueFilter) {
-  KeyIndex<GraphDbTypes::Label, Vertex> index;
   Dbms dbms;
+  KeyIndex<GraphDbTypes::Label, Vertex> index;
   auto dba = dbms.active();
   tx::Engine engine;
 
@@ -72,7 +72,7 @@ TEST(LabelsIndex, UniqueFilter) {
   sort(expected.begin(),
        expected.end());  // Entries will be sorted by vlist pointers.
   int cnt = 0;
-  for (auto vlist : index.GetVlists(label1, *t3)) {
+  for (auto vlist : index.GetVlists(label1, *t3, false)) {
     EXPECT_LT(cnt, expected.size());
     EXPECT_EQ(vlist, expected[cnt++]);
   }
@@ -123,7 +123,7 @@ TEST(LabelsIndexDb, AddGetZeroLabels) {
   auto dba = dbms.active();
   auto vertex = dba->insert_vertex();
   vertex.add_label(dba->label("test"));
-  auto collection = dba->vertices(dba->label("test"));
+  auto collection = dba->vertices(dba->label("test"), false);
   std::vector<VertexAccessor> collection_vector(collection.begin(),
                                                 collection.end());
   EXPECT_EQ(collection_vector.size(), (size_t)0);
@@ -150,9 +150,9 @@ TEST(LabelsIndexDb, AddGetRemoveLabel) {
   {
     auto dba = dbms.active();
 
-    auto filtered = dba->vertices(dba->label("test"));
+    auto filtered = dba->vertices(dba->label("test"), false);
     std::vector<VertexAccessor> collection(filtered.begin(), filtered.end());
-    auto vertices = dba->vertices();
+    auto vertices = dba->vertices(false);
 
     std::vector<VertexAccessor> expected_collection;
     for (auto vertex : vertices) {
@@ -179,9 +179,9 @@ TEST(LabelsIndexDb, AddGetRemoveLabel) {
   {
     auto dba = dbms.active();
 
-    auto filtered = dba->vertices(dba->label("test"));
+    auto filtered = dba->vertices(dba->label("test"), false);
     std::vector<VertexAccessor> collection(filtered.begin(), filtered.end());
-    auto vertices = dba->vertices();
+    auto vertices = dba->vertices(false);
 
     std::vector<VertexAccessor> expected_collection;
     for (auto vertex : vertices) {
diff --git a/tests/unit/database_label_property_index.cpp b/tests/unit/database_label_property_index.cpp
index 19e203b3b..d92e7166c 100644
--- a/tests/unit/database_label_property_index.cpp
+++ b/tests/unit/database_label_property_index.cpp
@@ -150,7 +150,7 @@ TEST_F(LabelPropertyIndexComplexTest, UniqueFilter) {
   EXPECT_EQ(index.Count(*key), 2);
 
   auto t3 = engine.begin();
-  auto iter = index.GetVlists(*key, *t3);
+  auto iter = index.GetVlists(*key, *t3, false);
   EXPECT_EQ(std::distance(iter.begin(), iter.end()), 1);
   t3->commit();
 }
@@ -159,11 +159,11 @@ TEST_F(LabelPropertyIndexComplexTest, UniqueFilter) {
 TEST_F(LabelPropertyIndexComplexTest, RemoveLabel) {
   index.UpdateOnLabelProperty(vlist, vertex);
 
-  auto iter1 = index.GetVlists(*key, *t);
+  auto iter1 = index.GetVlists(*key, *t, false);
   EXPECT_EQ(std::distance(iter1.begin(), iter1.end()), 1);
 
   vertex->labels_.clear();
-  auto iter2 = index.GetVlists(*key, *t);
+  auto iter2 = index.GetVlists(*key, *t, false);
   EXPECT_EQ(std::distance(iter2.begin(), iter2.end()), 0);
 }
 
@@ -171,11 +171,11 @@ TEST_F(LabelPropertyIndexComplexTest, RemoveLabel) {
 TEST_F(LabelPropertyIndexComplexTest, RemoveProperty) {
   index.UpdateOnLabelProperty(vlist, vertex);
 
-  auto iter1 = index.GetVlists(*key, *t);
+  auto iter1 = index.GetVlists(*key, *t, false);
   EXPECT_EQ(std::distance(iter1.begin(), iter1.end()), 1);
 
   vertex->properties_.clear();
-  auto iter2 = index.GetVlists(*key, *t);
+  auto iter2 = index.GetVlists(*key, *t, false);
   EXPECT_EQ(std::distance(iter2.begin(), iter2.end()), 0);
 }
 
@@ -187,7 +187,7 @@ TEST_F(LabelPropertyIndexComplexTest, Refresh) {
   vertex->labels_.clear();
   vertex->properties_.clear();
   index.Refresh(engine.count() + 1, engine);
-  auto iter = index.GetVlists(*key, *t);
+  auto iter = index.GetVlists(*key, *t, false);
   EXPECT_EQ(std::distance(iter.begin(), iter.end()), 0);
 }
 
diff --git a/tests/unit/graph_db_accessor.cpp b/tests/unit/graph_db_accessor.cpp
index 4f54ff117..5df3b6fa0 100644
--- a/tests/unit/graph_db_accessor.cpp
+++ b/tests/unit/graph_db_accessor.cpp
@@ -7,7 +7,6 @@
 #include "storage/edge_accessor.hpp"
 #include "storage/vertex_accessor.hpp"
 
-
 template <typename TIterable>
 auto Count(TIterable iterable) {
   return std::distance(iterable.begin(), iterable.end());
@@ -23,36 +22,36 @@ TEST(GraphDbAccessorTest, InsertVertex) {
   Dbms dbms;
   auto accessor = dbms.active();
 
-  EXPECT_EQ(Count(accessor->vertices()), 0);
+  EXPECT_EQ(Count(accessor->vertices(false)), 0);
 
   accessor->insert_vertex();
-  EXPECT_EQ(Count(accessor->vertices()), 0);
+  EXPECT_EQ(Count(accessor->vertices(false)), 0);
   EXPECT_EQ(Count(accessor->vertices(true)), 1);
   accessor->advance_command();
-  EXPECT_EQ(Count(accessor->vertices()), 1);
+  EXPECT_EQ(Count(accessor->vertices(false)), 1);
 
   accessor->insert_vertex();
-  EXPECT_EQ(Count(accessor->vertices()), 1);
+  EXPECT_EQ(Count(accessor->vertices(false)), 1);
   EXPECT_EQ(Count(accessor->vertices(true)), 2);
   accessor->advance_command();
-  EXPECT_EQ(Count(accessor->vertices()), 2);
+  EXPECT_EQ(Count(accessor->vertices(false)), 2);
 }
 
 TEST(GraphDbAccessorTest, RemoveVertexSameTransaction) {
   Dbms dbms;
   auto accessor = dbms.active();
 
-  EXPECT_EQ(Count(accessor->vertices()), 0);
+  EXPECT_EQ(Count(accessor->vertices(false)), 0);
 
   auto va1 = accessor->insert_vertex();
   accessor->advance_command();
-  EXPECT_EQ(Count(accessor->vertices()), 1);
+  EXPECT_EQ(Count(accessor->vertices(false)), 1);
 
   EXPECT_TRUE(accessor->remove_vertex(va1));
-  EXPECT_EQ(Count(accessor->vertices()), 1);
+  EXPECT_EQ(Count(accessor->vertices(false)), 1);
   EXPECT_EQ(Count(accessor->vertices(true)), 0);
   accessor->advance_command();
-  EXPECT_EQ(Count(accessor->vertices()), 0);
+  EXPECT_EQ(Count(accessor->vertices(false)), 0);
   EXPECT_EQ(Count(accessor->vertices(true)), 0);
 }
 
@@ -66,15 +65,15 @@ TEST(GraphDbAccessorTest, RemoveVertexDifferentTransaction) {
 
   // second transaction checks that it sees it, and deletes it
   auto accessor2 = dbms.active();
-  EXPECT_EQ(Count(accessor2->vertices()), 1);
+  EXPECT_EQ(Count(accessor2->vertices(false)), 1);
   EXPECT_EQ(Count(accessor2->vertices(true)), 1);
-  for (auto vertex_accessor : accessor2->vertices())
+  for (auto vertex_accessor : accessor2->vertices(false))
     accessor2->remove_vertex(vertex_accessor);
   accessor2->commit();
 
   // third transaction checks that it does not see the vertex
   auto accessor3 = dbms.active();
-  EXPECT_EQ(Count(accessor3->vertices()), 0);
+  EXPECT_EQ(Count(accessor3->vertices(false)), 0);
   EXPECT_EQ(Count(accessor3->vertices(true)), 0);
 }
 
@@ -92,10 +91,10 @@ TEST(GraphDbAccessorTest, InsertEdge) {
 
   // setup (v1) - [:likes] -> (v2)
   dba->insert_edge(va1, va2, dba->edge_type("likes"));
-  EXPECT_EQ(Count(dba->edges()), 0);
+  EXPECT_EQ(Count(dba->edges(false)), 0);
   EXPECT_EQ(Count(dba->edges(true)), 1);
   dba->advance_command();
-  EXPECT_EQ(Count(dba->edges()), 1);
+  EXPECT_EQ(Count(dba->edges(false)), 1);
   EXPECT_EQ(Count(dba->edges(true)), 1);
   EXPECT_EQ(va1.out().begin()->to(), va2);
   EXPECT_EQ(va2.in().begin()->from(), va1);
@@ -110,7 +109,7 @@ TEST(GraphDbAccessorTest, InsertEdge) {
   EXPECT_EQ(Count(dba->edges(false)), 1);
   EXPECT_EQ(Count(dba->edges(true)), 2);
   dba->advance_command();
-  EXPECT_EQ(Count(dba->edges()), 2);
+  EXPECT_EQ(Count(dba->edges(false)), 2);
   EXPECT_EQ(va3.out().begin()->to(), va2);
   EXPECT_EQ(va1.in_degree(), 0);
   EXPECT_EQ(va1.out_degree(), 1);
@@ -131,28 +130,28 @@ TEST(GraphDbAccessorTest, RemoveEdge) {
   dba->insert_edge(va1, va2, dba->edge_type("likes"));
   dba->insert_edge(va3, va2, dba->edge_type("hates"));
   dba->advance_command();
-  EXPECT_EQ(Count(dba->edges()), 2);
+  EXPECT_EQ(Count(dba->edges(false)), 2);
   EXPECT_EQ(Count(dba->edges(true)), 2);
 
   // remove all [:hates] edges
-  for (auto edge : dba->edges())
+  for (auto edge : dba->edges(false))
     if (edge.edge_type() == dba->edge_type("hates")) dba->remove_edge(edge);
-  EXPECT_EQ(Count(dba->edges()), 2);
+  EXPECT_EQ(Count(dba->edges(false)), 2);
   EXPECT_EQ(Count(dba->edges(true)), 1);
 
   // current state: (v1) - [:likes] -> (v2), (v3)
   dba->advance_command();
-  EXPECT_EQ(Count(dba->edges()), 1);
+  EXPECT_EQ(Count(dba->edges(false)), 1);
   EXPECT_EQ(Count(dba->edges(true)), 1);
-  EXPECT_EQ(Count(dba->vertices()), 3);
+  EXPECT_EQ(Count(dba->vertices(false)), 3);
   EXPECT_EQ(Count(dba->vertices(true)), 3);
-  for (auto edge : dba->edges()) {
+  for (auto edge : dba->edges(false)) {
     EXPECT_EQ(edge.edge_type(), dba->edge_type("likes"));
     auto v1 = edge.from();
     auto v2 = edge.to();
 
     // ensure correct connectivity for all the vertices
-    for (auto vertex : dba->vertices()) {
+    for (auto vertex : dba->vertices(false)) {
       if (vertex == v1) {
         EXPECT_EQ(vertex.in_degree(), 0);
         EXPECT_EQ(vertex.out_degree(), 1);
@@ -184,58 +183,58 @@ TEST(GraphDbAccessorTest, DetachRemoveVertex) {
   for (auto &vertex : vertices) vertex.Reconstruct();
 
   // ensure that plain remove does NOT work
-  EXPECT_EQ(Count(dba->vertices()), 4);
-  EXPECT_EQ(Count(dba->edges()), 3);
+  EXPECT_EQ(Count(dba->vertices(false)), 4);
+  EXPECT_EQ(Count(dba->edges(false)), 3);
   EXPECT_FALSE(dba->remove_vertex(vertices[0]));
   EXPECT_FALSE(dba->remove_vertex(vertices[1]));
   EXPECT_FALSE(dba->remove_vertex(vertices[2]));
-  EXPECT_EQ(Count(dba->vertices()), 4);
-  EXPECT_EQ(Count(dba->edges()), 3);
+  EXPECT_EQ(Count(dba->vertices(false)), 4);
+  EXPECT_EQ(Count(dba->edges(false)), 3);
 
   dba->detach_remove_vertex(vertices[2]);
-  EXPECT_EQ(Count(dba->vertices()), 4);
+  EXPECT_EQ(Count(dba->vertices(false)), 4);
   EXPECT_EQ(Count(dba->vertices(true)), 3);
-  EXPECT_EQ(Count(dba->edges()), 3);
+  EXPECT_EQ(Count(dba->edges(false)), 3);
   EXPECT_EQ(Count(dba->edges(true)), 1);
   dba->advance_command();
   for (auto &vertex : vertices) vertex.Reconstruct();
 
-  EXPECT_EQ(Count(dba->vertices()), 3);
-  EXPECT_EQ(Count(dba->edges()), 1);
+  EXPECT_EQ(Count(dba->vertices(false)), 3);
+  EXPECT_EQ(Count(dba->edges(false)), 1);
   EXPECT_TRUE(dba->remove_vertex(vertices[3]));
   EXPECT_EQ(Count(dba->vertices(true)), 2);
-  EXPECT_EQ(Count(dba->vertices()), 3);
+  EXPECT_EQ(Count(dba->vertices(false)), 3);
   dba->advance_command();
   for (auto &vertex : vertices) vertex.Reconstruct();
 
-  EXPECT_EQ(Count(dba->vertices()), 2);
-  EXPECT_EQ(Count(dba->edges()), 1);
-  for (auto va : dba->vertices()) EXPECT_FALSE(dba->remove_vertex(va));
+  EXPECT_EQ(Count(dba->vertices(false)), 2);
+  EXPECT_EQ(Count(dba->edges(false)), 1);
+  for (auto va : dba->vertices(false)) EXPECT_FALSE(dba->remove_vertex(va));
   dba->advance_command();
   for (auto &vertex : vertices) vertex.Reconstruct();
 
-  EXPECT_EQ(Count(dba->vertices()), 2);
-  EXPECT_EQ(Count(dba->edges()), 1);
-  for (auto va : dba->vertices()) {
+  EXPECT_EQ(Count(dba->vertices(false)), 2);
+  EXPECT_EQ(Count(dba->edges(false)), 1);
+  for (auto va : dba->vertices(false)) {
     EXPECT_FALSE(dba->remove_vertex(va));
     dba->detach_remove_vertex(va);
     break;
   }
   EXPECT_EQ(Count(dba->vertices(true)), 1);
-  EXPECT_EQ(Count(dba->vertices()), 2);
+  EXPECT_EQ(Count(dba->vertices(false)), 2);
   dba->advance_command();
   for (auto &vertex : vertices) vertex.Reconstruct();
 
-  EXPECT_EQ(Count(dba->vertices()), 1);
-  EXPECT_EQ(Count(dba->edges()), 0);
+  EXPECT_EQ(Count(dba->vertices(false)), 1);
+  EXPECT_EQ(Count(dba->edges(false)), 0);
 
   // remove the last vertex, it has no connections
   // so that should work
-  for (auto va : dba->vertices()) EXPECT_TRUE(dba->remove_vertex(va));
+  for (auto va : dba->vertices(false)) EXPECT_TRUE(dba->remove_vertex(va));
   dba->advance_command();
 
-  EXPECT_EQ(Count(dba->vertices()), 0);
-  EXPECT_EQ(Count(dba->edges()), 0);
+  EXPECT_EQ(Count(dba->vertices(false)), 0);
+  EXPECT_EQ(Count(dba->edges(false)), 0);
 }
 
 TEST(GraphDbAccessorTest, DetachRemoveVertexMultiple) {
@@ -258,30 +257,30 @@ TEST(GraphDbAccessorTest, DetachRemoveVertexMultiple) {
   dba->advance_command();
   for (auto &vertex : vertices) vertex.Reconstruct();
 
-  EXPECT_EQ(Count(dba->vertices()), N);
-  EXPECT_EQ(Count(dba->edges()), N * N);
+  EXPECT_EQ(Count(dba->vertices(false)), N);
+  EXPECT_EQ(Count(dba->edges(false)), N * N);
 
   // detach delete one edge
   dba->detach_remove_vertex(vertices[0]);
   dba->advance_command();
   for (auto &vertex : vertices) vertex.Reconstruct();
-  EXPECT_EQ(Count(dba->vertices()), N - 1);
-  EXPECT_EQ(Count(dba->edges()), (N - 1) * (N - 1));
+  EXPECT_EQ(Count(dba->vertices(false)), N - 1);
+  EXPECT_EQ(Count(dba->edges(false)), (N - 1) * (N - 1));
 
   // detach delete two neighboring edges
   dba->detach_remove_vertex(vertices[1]);
   dba->detach_remove_vertex(vertices[2]);
   dba->advance_command();
   for (auto &vertex : vertices) vertex.Reconstruct();
-  EXPECT_EQ(Count(dba->vertices()), N - 3);
-  EXPECT_EQ(Count(dba->edges()), (N - 3) * (N - 3));
+  EXPECT_EQ(Count(dba->vertices(false)), N - 3);
+  EXPECT_EQ(Count(dba->edges(false)), (N - 3) * (N - 3));
 
   // detach delete everything, buwahahahaha
   for (int l = 3; l < N; ++l) dba->detach_remove_vertex(vertices[l]);
   dba->advance_command();
   for (auto &vertex : vertices) vertex.Reconstruct();
-  EXPECT_EQ(Count(dba->vertices()), 0);
-  EXPECT_EQ(Count(dba->edges()), 0);
+  EXPECT_EQ(Count(dba->vertices(false)), 0);
+  EXPECT_EQ(Count(dba->edges(false)), 0);
 }
 
 TEST(GraphDbAccessorTest, Labels) {
diff --git a/tests/unit/graph_db_accessor_index_api.cpp b/tests/unit/graph_db_accessor_index_api.cpp
index 0fa6ac0e0..c225cf66f 100644
--- a/tests/unit/graph_db_accessor_index_api.cpp
+++ b/tests/unit/graph_db_accessor_index_api.cpp
@@ -142,6 +142,31 @@ TEST(GraphDbAccessor, BuildIndexDouble) {
   EXPECT_THROW(dba->BuildIndex(label, property), utils::BasicException);
 }
 
+// Inserts vertices with properties with integers and filters to get exact
+// vertices with an exact integer.
+TEST(GraphDbAccessor, FilterLabelPropertySpecificValue) {
+  Dbms dbms;
+  auto dba = dbms.active();
+  auto label = dba->label("lab1");
+  auto property = dba->property("prop1");
+  dba->BuildIndex(label, property);
+  dba->commit();
+
+  auto dba2 = dbms.active();
+  for (int i = 1; i <= 5; ++i) {
+    for (int j = 1; j <= i; ++j) {
+      auto vertex = dba2->insert_vertex();
+      vertex.add_label(label);
+      vertex.PropsSet(property, i);
+    }
+  }
+  dba2->commit();
+  auto dba3 = dbms.active();
+  for (int i = 1; i <= 5; ++i)
+    EXPECT_EQ(Count(dba3->vertices(label, property, PropertyValue(i), false)),
+              i);
+}
+
 // Inserts integers, double, lists, booleans into index and check if they are
 // sorted as they should be sorted.
 TEST(GraphDbAccessor, SortedLabelPropertyEntries) {
@@ -252,24 +277,24 @@ TEST(GraphDbAccessor, VisibilityAfterInsertion) {
   auto type2 = dba->edge_type("type2");
   dba->insert_edge(v1, v2, type1);
 
-  EXPECT_EQ(Count(dba->vertices(lab1)), 0);
+  EXPECT_EQ(Count(dba->vertices(lab1, false)), 0);
   EXPECT_EQ(Count(dba->vertices(lab1, true)), 1);
-  EXPECT_EQ(Count(dba->vertices(lab2)), 0);
+  EXPECT_EQ(Count(dba->vertices(lab2, false)), 0);
   EXPECT_EQ(Count(dba->vertices(lab2, true)), 0);
-  EXPECT_EQ(Count(dba->edges(type1)), 0);
+  EXPECT_EQ(Count(dba->edges(type1, false)), 0);
   EXPECT_EQ(Count(dba->edges(type1, true)), 1);
-  EXPECT_EQ(Count(dba->edges(type2)), 0);
+  EXPECT_EQ(Count(dba->edges(type2, false)), 0);
   EXPECT_EQ(Count(dba->edges(type2, true)), 0);
 
   dba->advance_command();
 
-  EXPECT_EQ(Count(dba->vertices(lab1)), 1);
+  EXPECT_EQ(Count(dba->vertices(lab1, false)), 1);
   EXPECT_EQ(Count(dba->vertices(lab1, true)), 1);
-  EXPECT_EQ(Count(dba->vertices(lab2)), 0);
+  EXPECT_EQ(Count(dba->vertices(lab2, false)), 0);
   EXPECT_EQ(Count(dba->vertices(lab2, true)), 0);
-  EXPECT_EQ(Count(dba->edges(type1)), 1);
+  EXPECT_EQ(Count(dba->edges(type1, false)), 1);
   EXPECT_EQ(Count(dba->edges(type1, true)), 1);
-  EXPECT_EQ(Count(dba->edges(type2)), 0);
+  EXPECT_EQ(Count(dba->edges(type2, false)), 0);
   EXPECT_EQ(Count(dba->edges(type2, true)), 0);
 }
 
@@ -281,32 +306,32 @@ TEST(GraphDbAccessor, VisibilityAfterDeletion) {
   dba->advance_command();
   auto type = dba->edge_type("type");
   for (int j = 0; j < 3; ++j) {
-    auto vertices_it = dba->vertices().begin();
+    auto vertices_it = dba->vertices(false).begin();
     dba->insert_edge(*vertices_it++, *vertices_it, type);
   }
   dba->advance_command();
 
-  EXPECT_EQ(Count(dba->vertices(lab)), 5);
+  EXPECT_EQ(Count(dba->vertices(lab, false)), 5);
   EXPECT_EQ(Count(dba->vertices(lab, true)), 5);
-  EXPECT_EQ(Count(dba->edges(type)), 3);
+  EXPECT_EQ(Count(dba->edges(type, false)), 3);
   EXPECT_EQ(Count(dba->edges(type, true)), 3);
 
   // delete two edges
-  auto edges_it = dba->edges().begin();
+  auto edges_it = dba->edges(false).begin();
   for (int k = 0; k < 2; ++k) dba->remove_edge(*edges_it++);
-  EXPECT_EQ(Count(dba->edges(type)), 3);
+  EXPECT_EQ(Count(dba->edges(type, false)), 3);
   EXPECT_EQ(Count(dba->edges(type, true)), 1);
   dba->advance_command();
-  EXPECT_EQ(Count(dba->edges(type)), 1);
+  EXPECT_EQ(Count(dba->edges(type, false)), 1);
   EXPECT_EQ(Count(dba->edges(type, true)), 1);
 
   // detach-delete 2 vertices
-  auto vertices_it = dba->vertices().begin();
+  auto vertices_it = dba->vertices(false).begin();
   for (int k = 0; k < 2; ++k) dba->detach_remove_vertex(*vertices_it++);
-  EXPECT_EQ(Count(dba->vertices(lab)), 5);
+  EXPECT_EQ(Count(dba->vertices(lab, false)), 5);
   EXPECT_EQ(Count(dba->vertices(lab, true)), 3);
   dba->advance_command();
-  EXPECT_EQ(Count(dba->vertices(lab)), 3);
+  EXPECT_EQ(Count(dba->vertices(lab, false)), 3);
   EXPECT_EQ(Count(dba->vertices(lab, true)), 3);
 }
 
diff --git a/tests/unit/query_plan_accumulate_aggregate.cpp b/tests/unit/query_plan_accumulate_aggregate.cpp
index a8f6b4837..c0c5ad49b 100644
--- a/tests/unit/query_plan_accumulate_aggregate.cpp
+++ b/tests/unit/query_plan_accumulate_aggregate.cpp
@@ -431,7 +431,7 @@ TEST(QueryPlan, AggregateCountEdgeCases) {
   EXPECT_EQ(0, count());
 
   // one vertex, property set
-  for (VertexAccessor va : dba->vertices()) va.PropsSet(prop, 42);
+  for (VertexAccessor va : dba->vertices(false)) va.PropsSet(prop, 42);
   dba->advance_command();
   EXPECT_EQ(1, count());
 
@@ -441,7 +441,7 @@ TEST(QueryPlan, AggregateCountEdgeCases) {
   EXPECT_EQ(1, count());
 
   // two vertices, both with property set
-  for (VertexAccessor va : dba->vertices()) va.PropsSet(prop, 42);
+  for (VertexAccessor va : dba->vertices(false)) va.PropsSet(prop, 42);
   dba->advance_command();
   EXPECT_EQ(2, count());
 }
diff --git a/tests/unit/query_plan_bag_semantics.cpp b/tests/unit/query_plan_bag_semantics.cpp
index 26d3b9217..873fa4631 100644
--- a/tests/unit/query_plan_bag_semantics.cpp
+++ b/tests/unit/query_plan_bag_semantics.cpp
@@ -101,7 +101,7 @@ TEST(QueryPlan, CreateLimit) {
 
   EXPECT_EQ(1, PullAll(skip, *dba, symbol_table));
   dba->advance_command();
-  EXPECT_EQ(3, CountIterable(dba->vertices()));
+  EXPECT_EQ(3, CountIterable(dba->vertices(false)));
 }
 
 TEST(QueryPlan, OrderBy) {
@@ -125,9 +125,9 @@ TEST(QueryPlan, OrderBy) {
   for (const auto &order_value_pair : orderable) {
     const auto &values = order_value_pair.second;
     // empty database
-    for (auto &vertex : dba->vertices()) dba->detach_remove_vertex(vertex);
+    for (auto &vertex : dba->vertices(false)) dba->detach_remove_vertex(vertex);
     dba->advance_command();
-    ASSERT_EQ(0, CountIterable(dba->vertices()));
+    ASSERT_EQ(0, CountIterable(dba->vertices(false)));
 
     // take some effort to shuffle the values
     // because we are testing that something not ordered gets ordered
@@ -243,16 +243,16 @@ TEST(QueryPlan, OrderByExceptions) {
 
   for (const auto &pair : exception_pairs) {
     // empty database
-    for (auto &vertex : dba->vertices()) dba->detach_remove_vertex(vertex);
+    for (auto &vertex : dba->vertices(false)) dba->detach_remove_vertex(vertex);
     dba->advance_command();
-    ASSERT_EQ(0, CountIterable(dba->vertices()));
+    ASSERT_EQ(0, CountIterable(dba->vertices(false)));
 
     // make two vertices, and set values
     dba->insert_vertex().PropsSet(prop, pair.first);
     dba->insert_vertex().PropsSet(prop, pair.second);
     dba->advance_command();
-    ASSERT_EQ(2, CountIterable(dba->vertices()));
-    for (const auto &va : dba->vertices())
+    ASSERT_EQ(2, CountIterable(dba->vertices(false)));
+    for (const auto &va : dba->vertices(false))
       ASSERT_NE(va.PropsAt(prop).type(), PropertyValue::Type::Null);
 
     // order by and expect an exception
diff --git a/tests/unit/query_plan_create_set_remove_delete.cpp b/tests/unit/query_plan_create_set_remove_delete.cpp
index c33bc1068..d217a9f56 100644
--- a/tests/unit/query_plan_create_set_remove_delete.cpp
+++ b/tests/unit/query_plan_create_set_remove_delete.cpp
@@ -43,7 +43,7 @@ TEST(QueryPlan, CreateNodeWithAttributes) {
 
   // count the number of vertices
   int vertex_count = 0;
-  for (VertexAccessor vertex : dba->vertices()) {
+  for (VertexAccessor vertex : dba->vertices(false)) {
     vertex_count++;
     EXPECT_EQ(vertex.labels().size(), 1);
     EXPECT_EQ(*vertex.labels().begin(), label);
@@ -94,7 +94,7 @@ TEST(QueryPlan, CreateReturn) {
   EXPECT_EQ(42, results[0][1].Value<int64_t>());
 
   dba->advance_command();
-  EXPECT_EQ(1, CountIterable(dba->vertices()));
+  EXPECT_EQ(1, CountIterable(dba->vertices(false)));
 }
 
 TEST(QueryPlan, CreateExpand) {
@@ -111,8 +111,8 @@ TEST(QueryPlan, CreateExpand) {
 
   auto test_create_path = [&](bool cycle, int expected_nodes_created,
                               int expected_edges_created) {
-    int before_v = CountIterable(dba->vertices());
-    int before_e = CountIterable(dba->edges());
+    int before_v = CountIterable(dba->vertices(false));
+    int before_e = CountIterable(dba->edges(false));
 
     // data for the first node
     auto n = NODE("n");
@@ -141,15 +141,15 @@ TEST(QueryPlan, CreateExpand) {
     PullAll(create_expand, *dba, symbol_table);
     dba->advance_command();
 
-    EXPECT_EQ(CountIterable(dba->vertices()) - before_v,
+    EXPECT_EQ(CountIterable(dba->vertices(false)) - before_v,
               expected_nodes_created);
-    EXPECT_EQ(CountIterable(dba->edges()) - before_e, expected_edges_created);
+    EXPECT_EQ(CountIterable(dba->edges(false)) - before_e, expected_edges_created);
   };
 
   test_create_path(false, 2, 1);
   test_create_path(true, 1, 1);
 
-  for (VertexAccessor vertex : dba->vertices()) {
+  for (VertexAccessor vertex : dba->vertices(false)) {
     EXPECT_EQ(vertex.labels().size(), 1);
     GraphDbTypes::Label label = vertex.labels()[0];
     if (label == label_node_1) {
@@ -163,7 +163,7 @@ TEST(QueryPlan, CreateExpand) {
       FAIL();
     }
 
-    for (EdgeAccessor edge : dba->edges()) {
+    for (EdgeAccessor edge : dba->edges(false)) {
       EXPECT_EQ(edge.edge_type(), edge_type);
       EXPECT_EQ(edge.PropsAt(property).Value<int64_t>(), 3);
     }
@@ -191,10 +191,10 @@ TEST(QueryPlan, MatchCreateNode) {
   // creation op
   auto create_node = std::make_shared<CreateNode>(m, n_scan_all.op_);
 
-  EXPECT_EQ(CountIterable(dba->vertices()), 3);
+  EXPECT_EQ(CountIterable(dba->vertices(false)), 3);
   PullAll(create_node, *dba, symbol_table);
   dba->advance_command();
-  EXPECT_EQ(CountIterable(dba->vertices()), 6);
+  EXPECT_EQ(CountIterable(dba->vertices(false)), 6);
 }
 
 TEST(QueryPlan, MatchCreateExpand) {
@@ -217,8 +217,8 @@ TEST(QueryPlan, MatchCreateExpand) {
 
   auto test_create_path = [&](bool cycle, int expected_nodes_created,
                               int expected_edges_created) {
-    int before_v = CountIterable(dba->vertices());
-    int before_e = CountIterable(dba->edges());
+    int before_v = CountIterable(dba->vertices(false));
+    int before_e = CountIterable(dba->edges(false));
 
     // data for the first node
     auto n_scan_all = MakeScanAll(storage, symbol_table, "n");
@@ -239,9 +239,9 @@ TEST(QueryPlan, MatchCreateExpand) {
     PullAll(create_expand, *dba, symbol_table);
     dba->advance_command();
 
-    EXPECT_EQ(CountIterable(dba->vertices()) - before_v,
+    EXPECT_EQ(CountIterable(dba->vertices(false)) - before_v,
               expected_nodes_created);
-    EXPECT_EQ(CountIterable(dba->edges()) - before_e, expected_edges_created);
+    EXPECT_EQ(CountIterable(dba->edges(false)) - before_e, expected_edges_created);
   };
 
   test_create_path(false, 3, 3);
@@ -261,8 +261,8 @@ TEST(QueryPlan, Delete) {
       dba->insert_edge(vertices[j], vertices[k], type);
 
   dba->advance_command();
-  EXPECT_EQ(4, CountIterable(dba->vertices()));
-  EXPECT_EQ(6, CountIterable(dba->edges()));
+  EXPECT_EQ(4, CountIterable(dba->vertices(false)));
+  EXPECT_EQ(6, CountIterable(dba->edges(false)));
 
   AstTreeStorage storage;
   SymbolTable symbol_table;
@@ -276,8 +276,8 @@ TEST(QueryPlan, Delete) {
         n.op_, std::vector<Expression *>{n_get}, false);
     EXPECT_THROW(PullAll(delete_op, *dba, symbol_table), QueryRuntimeException);
     dba->advance_command();
-    EXPECT_EQ(4, CountIterable(dba->vertices()));
-    EXPECT_EQ(6, CountIterable(dba->edges()));
+    EXPECT_EQ(4, CountIterable(dba->vertices(false)));
+    EXPECT_EQ(6, CountIterable(dba->edges(false)));
   }
 
   // detach delete a single vertex
@@ -290,8 +290,8 @@ TEST(QueryPlan, Delete) {
     Frame frame(symbol_table.max_position());
     delete_op->MakeCursor(*dba)->Pull(frame, symbol_table);
     dba->advance_command();
-    EXPECT_EQ(3, CountIterable(dba->vertices()));
-    EXPECT_EQ(3, CountIterable(dba->edges()));
+    EXPECT_EQ(3, CountIterable(dba->vertices(false)));
+    EXPECT_EQ(3, CountIterable(dba->edges(false)));
   }
 
   // delete all remaining edges
@@ -305,8 +305,8 @@ TEST(QueryPlan, Delete) {
         r_m.op_, std::vector<Expression *>{r_get}, false);
     PullAll(delete_op, *dba, symbol_table);
     dba->advance_command();
-    EXPECT_EQ(3, CountIterable(dba->vertices()));
-    EXPECT_EQ(0, CountIterable(dba->edges()));
+    EXPECT_EQ(3, CountIterable(dba->vertices(false)));
+    EXPECT_EQ(0, CountIterable(dba->edges(false)));
   }
 
   // delete all remaining vertices
@@ -318,8 +318,8 @@ TEST(QueryPlan, Delete) {
         n.op_, std::vector<Expression *>{n_get}, false);
     PullAll(delete_op, *dba, symbol_table);
     dba->advance_command();
-    EXPECT_EQ(0, CountIterable(dba->vertices()));
-    EXPECT_EQ(0, CountIterable(dba->edges()));
+    EXPECT_EQ(0, CountIterable(dba->vertices(false)));
+    EXPECT_EQ(0, CountIterable(dba->edges(false)));
   }
 }
 
@@ -343,8 +343,8 @@ TEST(QueryPlan, DeleteTwiceDeleteBlockingEdge) {
     auto v2 = dba->insert_vertex();
     dba->insert_edge(v1, v2, dba->edge_type("T"));
     dba->advance_command();
-    EXPECT_EQ(2, CountIterable(dba->vertices()));
-    EXPECT_EQ(1, CountIterable(dba->edges()));
+    EXPECT_EQ(2, CountIterable(dba->vertices(false)));
+    EXPECT_EQ(1, CountIterable(dba->edges(false)));
 
     AstTreeStorage storage;
     SymbolTable symbol_table;
@@ -365,8 +365,8 @@ TEST(QueryPlan, DeleteTwiceDeleteBlockingEdge) {
         r_m.op_, std::vector<Expression *>{n_get, r_get, m_get}, detach);
     EXPECT_EQ(2, PullAll(delete_op, *dba, symbol_table));
     dba->advance_command();
-    EXPECT_EQ(0, CountIterable(dba->vertices()));
-    EXPECT_EQ(0, CountIterable(dba->edges()));
+    EXPECT_EQ(0, CountIterable(dba->vertices(false)));
+    EXPECT_EQ(0, CountIterable(dba->edges(false)));
   };
 
   test_delete(true);
@@ -385,8 +385,8 @@ TEST(QueryPlan, DeleteReturn) {
   }
 
   dba->advance_command();
-  EXPECT_EQ(4, CountIterable(dba->vertices()));
-  EXPECT_EQ(0, CountIterable(dba->edges()));
+  EXPECT_EQ(4, CountIterable(dba->vertices(false)));
+  EXPECT_EQ(0, CountIterable(dba->edges(false)));
 
   AstTreeStorage storage;
   SymbolTable symbol_table;
@@ -408,7 +408,7 @@ TEST(QueryPlan, DeleteReturn) {
   auto results = CollectProduce(produce.get(), symbol_table, *dba);
   EXPECT_EQ(4, results.size());
   dba->advance_command();
-  EXPECT_EQ(0, CountIterable(dba->vertices()));
+  EXPECT_EQ(0, CountIterable(dba->vertices(false)));
 }
 
 TEST(QueryPlan, DeleteNull) {
@@ -490,8 +490,8 @@ TEST(QueryPlan, SetProperty) {
   EXPECT_EQ(2, PullAll(set_r_p, *dba, symbol_table));
   dba->advance_command();
 
-  EXPECT_EQ(CountIterable(dba->edges()), 2);
-  for (EdgeAccessor edge : dba->edges()) {
+  EXPECT_EQ(CountIterable(dba->edges(false)), 2);
+  for (EdgeAccessor edge : dba->edges(false)) {
     ASSERT_EQ(edge.PropsAt(prop1).type(), PropertyValue::Type::Int);
     EXPECT_EQ(edge.PropsAt(prop1).Value<int64_t>(), 42);
     VertexAccessor from = edge.from();
@@ -542,8 +542,8 @@ TEST(QueryPlan, SetProperties) {
     EXPECT_EQ(1, PullAll(set_m_to_r, *dba, symbol_table));
     dba->advance_command();
 
-    EXPECT_EQ(CountIterable(dba->edges()), 1);
-    for (EdgeAccessor edge : dba->edges()) {
+    EXPECT_EQ(CountIterable(dba->edges(false)), 1);
+    for (EdgeAccessor edge : dba->edges(false)) {
       VertexAccessor from = edge.from();
       EXPECT_EQ(from.Properties().size(), update ? 2 : 1);
       if (update) {
@@ -591,7 +591,7 @@ TEST(QueryPlan, SetLabels) {
       n.op_, n.sym_, std::vector<GraphDbTypes::Label>{label2, label3});
   EXPECT_EQ(2, PullAll(label_set, *dba, symbol_table));
 
-  for (VertexAccessor vertex : dba->vertices()) {
+  for (VertexAccessor vertex : dba->vertices(false)) {
     vertex.SwitchNew();
     EXPECT_EQ(3, vertex.labels().size());
     EXPECT_TRUE(vertex.has_label(label2));
@@ -640,8 +640,8 @@ TEST(QueryPlan, RemoveProperty) {
   EXPECT_EQ(2, PullAll(set_r_p, *dba, symbol_table));
   dba->advance_command();
 
-  EXPECT_EQ(CountIterable(dba->edges()), 2);
-  for (EdgeAccessor edge : dba->edges()) {
+  EXPECT_EQ(CountIterable(dba->edges(false)), 2);
+  for (EdgeAccessor edge : dba->edges(false)) {
     EXPECT_EQ(edge.PropsAt(prop1).type(), PropertyValue::Type::Null);
     VertexAccessor from = edge.from();
     VertexAccessor to = edge.to();
@@ -675,7 +675,7 @@ TEST(QueryPlan, RemoveLabels) {
       n.op_, n.sym_, std::vector<GraphDbTypes::Label>{label1, label2});
   EXPECT_EQ(2, PullAll(label_remove, *dba, symbol_table));
 
-  for (VertexAccessor vertex : dba->vertices()) {
+  for (VertexAccessor vertex : dba->vertices(false)) {
     vertex.SwitchNew();
     EXPECT_EQ(1, vertex.labels().size());
     EXPECT_FALSE(vertex.has_label(label1));
@@ -847,10 +847,10 @@ TEST(QueryPlan, MergeNoInput) {
   auto create = std::make_shared<CreateNode>(node, nullptr);
   auto merge = std::make_shared<plan::Merge>(nullptr, create, create);
 
-  EXPECT_EQ(0, CountIterable(dba->vertices()));
+  EXPECT_EQ(0, CountIterable(dba->vertices(false)));
   EXPECT_EQ(1, PullAll(merge, *dba, symbol_table));
   dba->advance_command();
-  EXPECT_EQ(1, CountIterable(dba->vertices()));
+  EXPECT_EQ(1, CountIterable(dba->vertices(false)));
 }
 
 TEST(QueryPlan, SetPropertyOnNull) {
@@ -881,7 +881,7 @@ TEST(QueryPlan, SetPropertiesOnNull) {
                                                    std::vector<Symbol>{n.sym_});
   auto set_op = std::make_shared<plan::SetProperties>(
       optional, n.sym_, n_ident, plan::SetProperties::Op::REPLACE);
-  EXPECT_EQ(0, CountIterable(dba->vertices()));
+  EXPECT_EQ(0, CountIterable(dba->vertices(false)));
   EXPECT_EQ(1, PullAll(set_op, *dba, symbol_table));
 }
 
@@ -899,7 +899,7 @@ TEST(QueryPlan, SetLabelsOnNull) {
                                                    std::vector<Symbol>{n.sym_});
   auto set_op = std::make_shared<plan::SetLabels>(
       optional, n.sym_, std::vector<GraphDbTypes::Label>{label});
-  EXPECT_EQ(0, CountIterable(dba->vertices()));
+  EXPECT_EQ(0, CountIterable(dba->vertices(false)));
   EXPECT_EQ(1, PullAll(set_op, *dba, symbol_table));
 }
 
@@ -931,6 +931,6 @@ TEST(QueryPlan, RemoveLabelsOnNull) {
                                                    std::vector<Symbol>{n.sym_});
   auto remove_op = std::make_shared<plan::RemoveLabels>(
       optional, n.sym_, std::vector<GraphDbTypes::Label>{label});
-  EXPECT_EQ(0, CountIterable(dba->vertices()));
+  EXPECT_EQ(0, CountIterable(dba->vertices(false)));
   EXPECT_EQ(1, PullAll(remove_op, *dba, symbol_table));
 }
diff --git a/tests/unit/query_plan_match_filter_return.cpp b/tests/unit/query_plan_match_filter_return.cpp
index 4e2d7181c..7aff0434c 100644
--- a/tests/unit/query_plan_match_filter_return.cpp
+++ b/tests/unit/query_plan_match_filter_return.cpp
@@ -387,8 +387,8 @@ TEST(QueryPlan, OptionalMatchThenExpandToMissingNode) {
   auto edge_type = dba->edge_type("edge_type");
   dba->insert_edge(v1, v2, edge_type);
   dba->advance_command();
-  EXPECT_EQ(2, CountIterable(dba->vertices()));
-  EXPECT_EQ(1, CountIterable(dba->edges()));
+  EXPECT_EQ(2, CountIterable(dba->vertices(false)));
+  EXPECT_EQ(1, CountIterable(dba->edges(false)));
   AstTreeStorage storage;
   SymbolTable symbol_table;
   // OPTIONAL MATCH (n :missing)
@@ -434,8 +434,8 @@ TEST(QueryPlan, OptionalMatchThenExpandToMissingEdge) {
   auto edge_type = dba->edge_type("edge_type");
   dba->insert_edge(v1, v2, edge_type);
   dba->advance_command();
-  EXPECT_EQ(2, CountIterable(dba->vertices()));
-  EXPECT_EQ(1, CountIterable(dba->edges()));
+  EXPECT_EQ(2, CountIterable(dba->vertices(false)));
+  EXPECT_EQ(1, CountIterable(dba->edges(false)));
   AstTreeStorage storage;
   SymbolTable symbol_table;
   // OPTIONAL MATCH (n :missing) -[r]- (m)
@@ -816,7 +816,7 @@ TEST(QueryPlan, ScanAllByLabel) {
   labeled_vertex.add_label(label);
   dba->insert_vertex();
   dba->advance_command();
-  EXPECT_EQ(2, CountIterable(dba->vertices()));
+  EXPECT_EQ(2, CountIterable(dba->vertices(false)));
   // MATCH (n :label)
   AstTreeStorage storage;
   SymbolTable symbol_table;
diff --git a/tests/unit/record_edge_vertex_accessor.cpp b/tests/unit/record_edge_vertex_accessor.cpp
index f470a3d1e..1349f3a89 100644
--- a/tests/unit/record_edge_vertex_accessor.cpp
+++ b/tests/unit/record_edge_vertex_accessor.cpp
@@ -92,7 +92,7 @@ TEST(RecordAccessor, SwitchOldAndSwitchNewMemberFunctionTest) {
   // test both Switches work on existing record
   {
     auto dba = dbms.active();
-    auto v1 = *dba->vertices().begin();
+    auto v1 = *dba->vertices(false).begin();
     v1.SwitchOld();
     v1.SwitchNew();
   }
@@ -101,11 +101,11 @@ TEST(RecordAccessor, SwitchOldAndSwitchNewMemberFunctionTest) {
   {
     auto dba = dbms.active();
     auto label = dba->label("label");
-    auto v1 = *dba->vertices().begin();
+    auto v1 = *dba->vertices(false).begin();
 
-    EXPECT_FALSE(v1.has_label(label)); // old record
-    v1.add_label(label); // modifying data does not switch to new
-    EXPECT_FALSE(v1.has_label(label)); // old record
+    EXPECT_FALSE(v1.has_label(label));  // old record
+    v1.add_label(label);                // modifying data does not switch to new
+    EXPECT_FALSE(v1.has_label(label));  // old record
     v1.SwitchNew();
     EXPECT_TRUE(v1.has_label(label));
     v1.SwitchOld();
@@ -128,13 +128,13 @@ TEST(RecordAccessor, Reconstruct) {
 
   // ensure we don't have label set
   auto dba = dbms.active();
-  auto v1 = *dba->vertices().begin();
+  auto v1 = *dba->vertices(false).begin();
   v1.SwitchNew();
   EXPECT_FALSE(v1.has_label(label));
 
   {
     // update the record through a different accessor
-    auto v1_other_accessor = *dba->vertices().begin();
+    auto v1_other_accessor = *dba->vertices(false).begin();
     v1_other_accessor.add_label(label);
     EXPECT_FALSE(v1.has_label(label));
     v1_other_accessor.SwitchNew();
diff --git a/tests/unit/skiplist_suffix.cpp b/tests/unit/skiplist_suffix.cpp
new file mode 100644
index 000000000..c6131ed20
--- /dev/null
+++ b/tests/unit/skiplist_suffix.cpp
@@ -0,0 +1,40 @@
+#include <algorithm>
+#include <iterator>
+#include <vector>
+
+#include "gtest/gtest.h"
+
+#include "data_structures/concurrent/skiplist.hpp"
+#include "database/indexes/index_common.hpp"
+
+template <class TIterable>
+int Count(TIterable &collection) {
+  int ret = 0;
+  for (__attribute__((unused)) auto it : collection) ret += 1;
+  return ret;
+}
+
+TEST(SkipListSuffix, EmptyRange) {
+  SkipList<int> V;
+  auto access = V.access();
+  auto r1 = IndexUtils::SkipListSuffix<typename SkipList<int>::Iterator, int>(
+      access.begin(), std::move(access));
+  EXPECT_EQ(Count(r1), 0);
+}
+
+TEST(SkipListSuffix, NonEmptyRange) {
+  SkipList<int> V;
+  auto access = V.access();
+  access.insert(1);
+  access.insert(5);
+  access.insert(3);
+  auto r1 = IndexUtils::SkipListSuffix<typename SkipList<int>::Iterator, int>(
+      access.begin(), std::move(access));
+  EXPECT_EQ(Count(r1), 3);
+  auto iter = r1.begin();
+  EXPECT_EQ(*iter, 1);
+  ++iter;
+  EXPECT_EQ(*iter, 3);
+  ++iter;
+  EXPECT_EQ(*iter, 5);
+}