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
This commit is contained in:
parent
9acdc632e9
commit
141d9b3bb8
@ -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 &(); }
|
||||
};
|
||||
|
@ -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_,
|
||||
|
@ -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));
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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++;
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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"));
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
40
tests/unit/skiplist_suffix.cpp
Normal file
40
tests/unit/skiplist_suffix.cpp
Normal file
@ -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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user