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); +}