Merge branch 'dev' of https://phabricator.tomicevic.com/diffusion/MG/memgraph into dev
This commit is contained in:
commit
32bdc4fd5e
@ -283,8 +283,9 @@ public:
|
||||
void abort();
|
||||
};
|
||||
|
||||
class VertexIterator : public Sized<8, 8>,
|
||||
public IteratorBase<const VertexAccessor>
|
||||
class VertexIterator
|
||||
: public Sized<8, 8>,
|
||||
public iter::Composable<const VertexAccessor, VertexIterator>
|
||||
{
|
||||
public:
|
||||
template <class T>
|
||||
@ -296,14 +297,15 @@ public:
|
||||
VertexIterator &operator=(const VertexIterator &other) = delete;
|
||||
VertexIterator &operator=(VertexIterator &&other) = delete;
|
||||
|
||||
Option<const VertexAccessor> next() final;
|
||||
Option<const VertexAccessor> next();
|
||||
|
||||
Count count() final;
|
||||
Count count();
|
||||
};
|
||||
|
||||
// TODO: Find reasons of such great size ant try to decrease it.
|
||||
class VertexAccessIterator : public Sized<560, 8>,
|
||||
public IteratorBase<const VertexAccessor>
|
||||
class VertexAccessIterator
|
||||
: public Sized<560, 8>,
|
||||
public iter::Composable<const VertexAccessor, VertexAccessIterator>
|
||||
{
|
||||
public:
|
||||
template <class T>
|
||||
@ -315,14 +317,15 @@ public:
|
||||
VertexAccessIterator &operator=(const VertexAccessIterator &other) = delete;
|
||||
VertexAccessIterator &operator=(VertexAccessIterator &&other) = delete;
|
||||
|
||||
Option<const VertexAccessor> next() final;
|
||||
Option<const VertexAccessor> next();
|
||||
|
||||
Count count() final;
|
||||
Count count();
|
||||
};
|
||||
|
||||
// TODO: Find reasons of such great size ant try to decrease it.
|
||||
class EdgeAccessIterator : public Sized<560, 8>,
|
||||
public IteratorBase<const EdgeAccessor>
|
||||
class EdgeAccessIterator
|
||||
: public Sized<560, 8>,
|
||||
public iter::Composable<const EdgeAccessor, EdgeAccessIterator>
|
||||
{
|
||||
public:
|
||||
template <class T>
|
||||
@ -334,13 +337,14 @@ public:
|
||||
EdgeAccessIterator &operator=(const EdgeAccessIterator &other) = delete;
|
||||
EdgeAccessIterator &operator=(EdgeAccessIterator &&other) = delete;
|
||||
|
||||
Option<const EdgeAccessor> next() final;
|
||||
Option<const EdgeAccessor> next();
|
||||
|
||||
Count count() final;
|
||||
Count count();
|
||||
};
|
||||
|
||||
class OutEdgesIterator : public Sized<48, 8>,
|
||||
public IteratorBase<const EdgeAccessor>
|
||||
class OutEdgesIterator
|
||||
: public Sized<48, 8>,
|
||||
public iter::Composable<const EdgeAccessor, OutEdgesIterator>
|
||||
{
|
||||
public:
|
||||
template <class T>
|
||||
@ -352,13 +356,14 @@ public:
|
||||
OutEdgesIterator &operator=(const OutEdgesIterator &other) = delete;
|
||||
OutEdgesIterator &operator=(OutEdgesIterator &&other) = delete;
|
||||
|
||||
Option<const EdgeAccessor> next() final;
|
||||
Option<const EdgeAccessor> next();
|
||||
|
||||
Count count() final;
|
||||
Count count();
|
||||
};
|
||||
|
||||
class InEdgesIterator : public Sized<64, 8>,
|
||||
public IteratorBase<const EdgeAccessor>
|
||||
class InEdgesIterator
|
||||
: public Sized<64, 8>,
|
||||
public iter::Composable<const EdgeAccessor, InEdgesIterator>
|
||||
{
|
||||
public:
|
||||
template <class T>
|
||||
@ -370,12 +375,13 @@ public:
|
||||
InEdgesIterator &operator=(const InEdgesIterator &other) = delete;
|
||||
InEdgesIterator &operator=(InEdgesIterator &&other) = delete;
|
||||
|
||||
Option<const EdgeAccessor> next() final;
|
||||
Option<const EdgeAccessor> next();
|
||||
|
||||
Count count() final;
|
||||
Count count();
|
||||
};
|
||||
|
||||
class EdgeIterator : public Sized<8, 8>, public IteratorBase<const EdgeAccessor>
|
||||
class EdgeIterator : public Sized<8, 8>,
|
||||
public iter::Composable<const EdgeAccessor, EdgeIterator>
|
||||
{
|
||||
public:
|
||||
template <class T>
|
||||
@ -387,9 +393,9 @@ public:
|
||||
EdgeIterator &operator=(const EdgeIterator &other) = delete;
|
||||
EdgeIterator &operator=(EdgeIterator &&other) = delete;
|
||||
|
||||
Option<const EdgeAccessor> next() final;
|
||||
Option<const EdgeAccessor> next();
|
||||
|
||||
Count count() final;
|
||||
Count count();
|
||||
|
||||
EdgeIterator &operator->() { return *this; }
|
||||
};
|
||||
|
@ -177,14 +177,12 @@ TRANSFORM_REF(EdgePropertyKey,
|
||||
::EdgePropertyFamily::PropertyType::PropertyFamilyKey);
|
||||
|
||||
// ITERATORS
|
||||
TRANSFORM_REF_SIZED(VertexIterator,
|
||||
std::unique_ptr<IteratorBase<const ::VertexAccessor>>);
|
||||
TRANSFORM_REF_SIZED(EdgeIterator,
|
||||
std::unique_ptr<IteratorBase<const ::EdgeAccessor>>);
|
||||
TRANSFORM_REF_SIZED(VertexAccessIterator, vertex_access_iterator_t);
|
||||
TRANSFORM_REF_SIZED(EdgeAccessIterator, edge_access_iterator_t);
|
||||
TRANSFORM_REF_SIZED(OutEdgesIterator, out_edge_iterator_t);
|
||||
TRANSFORM_REF_SIZED(InEdgesIterator, in_edge_iterator_t);
|
||||
TRANSFORM_REF(VertexIterator, ::iter::Virtual<const ::VertexAccessor>);
|
||||
TRANSFORM_REF(EdgeIterator, ::iter::Virtual<const ::EdgeAccessor>);
|
||||
TRANSFORM_REF(VertexAccessIterator, vertex_access_iterator_t);
|
||||
TRANSFORM_REF(EdgeAccessIterator, edge_access_iterator_t);
|
||||
TRANSFORM_REF(OutEdgesIterator, out_edge_iterator_t);
|
||||
TRANSFORM_REF(InEdgesIterator, in_edge_iterator_t);
|
||||
|
||||
template <class T>
|
||||
TRANSFORM_REF_TEMPLATED(VertexIndex<T>, VertexIndexBase<T>);
|
||||
@ -212,22 +210,18 @@ TRANSFORM_VALUE(EdgePropertyKey,
|
||||
TRANSFORM_VALUE(VertexPropertyKey,
|
||||
::VertexPropertyFamily::PropertyType::PropertyFamilyKey);
|
||||
TRANSFORM_VALUE_ONE(VertexAccessIterator, vertex_access_iterator_t);
|
||||
// MOVE_CONSTRUCTOR_FORCED(VertexAccessIterator, vertex_access_iterator_t);
|
||||
MOVE_CONSTRUCTOR_FORCED(VertexAccessIterator, vertex_access_iterator_t);
|
||||
TRANSFORM_VALUE_ONE(EdgeAccessIterator, edge_access_iterator_t);
|
||||
// MOVE_CONSTRUCTOR_FORCED(EdgeAccessIterator, edge_access_iterator_t);
|
||||
MOVE_CONSTRUCTOR_FORCED(EdgeAccessIterator, edge_access_iterator_t);
|
||||
TRANSFORM_VALUE_ONE(OutEdgesIterator, out_edge_iterator_t);
|
||||
// MOVE_CONSTRUCTOR_FORCED(OutEdgesIterator, out_edge_iterator_t);
|
||||
MOVE_CONSTRUCTOR_FORCED(OutEdgesIterator, out_edge_iterator_t);
|
||||
TRANSFORM_VALUE_ONE(InEdgesIterator, in_edge_iterator_t);
|
||||
// MOVE_CONSTRUCTOR_FORCED(InEdgesIterator, in_edge_iterator_t);
|
||||
TRANSFORM_VALUE_ONE(VertexIterator,
|
||||
std::unique_ptr<IteratorBase<const ::VertexAccessor>>);
|
||||
// MOVE_CONSTRUCTOR_FORCED(VertexIterator,
|
||||
// std::unique_ptr<IteratorBase<const
|
||||
// ::VertexAccessor>>);
|
||||
TRANSFORM_VALUE_ONE(EdgeIterator,
|
||||
std::unique_ptr<IteratorBase<const ::EdgeAccessor>>);
|
||||
// MOVE_CONSTRUCTOR_FORCED(EdgeIterator,
|
||||
// std::unique_ptr<IteratorBase<const ::EdgeAccessor>>);
|
||||
MOVE_CONSTRUCTOR_FORCED(InEdgesIterator, in_edge_iterator_t);
|
||||
TRANSFORM_VALUE_ONE(VertexIterator, ::iter::Virtual<const ::VertexAccessor>);
|
||||
MOVE_CONSTRUCTOR_FORCED(VertexIterator,
|
||||
::iter::Virtual<const ::VertexAccessor>);
|
||||
TRANSFORM_VALUE_ONE(EdgeIterator, ::iter::Virtual<const ::EdgeAccessor>);
|
||||
MOVE_CONSTRUCTOR_FORCED(EdgeIterator, ::iter::Virtual<const ::EdgeAccessor>);
|
||||
|
||||
template <class T>
|
||||
TRANSFORM_VALUE_ONE_RAW(
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <utility>
|
||||
#include "utils/crtp.hpp"
|
||||
|
||||
// TODO: reimplement this
|
||||
template <class T>
|
||||
class List
|
||||
{
|
||||
@ -186,19 +187,23 @@ private:
|
||||
private:
|
||||
void find_and_disconnect()
|
||||
{
|
||||
auto it = It(list);
|
||||
Node *bef = nullptr;
|
||||
auto now = load(list->head);
|
||||
auto next = load(curr->next);
|
||||
while (it.valid()) {
|
||||
if (it.curr == curr) {
|
||||
if (it.disconnect()) {
|
||||
while (now != nullptr) {
|
||||
if (now == curr) {
|
||||
prev = bef;
|
||||
if (disconnect()) {
|
||||
return;
|
||||
}
|
||||
it.reset();
|
||||
} else if (it.curr == next) { // Comparison with next is
|
||||
// optimization for early return.
|
||||
bef = nullptr;
|
||||
now = load(list->head);
|
||||
} else if (now == next) { // Comparison with next is
|
||||
// optimization for early return.
|
||||
return;
|
||||
} else {
|
||||
it++;
|
||||
bef = now;
|
||||
now = load(now->next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,18 @@ auto load_queries(Db &db)
|
||||
return t.commit();
|
||||
};
|
||||
|
||||
auto create_labeled_and_named_node_v2 = [&db](const properties_t &args) {
|
||||
DbAccessor t(db);
|
||||
auto prop_key = t.vertex_property_key("name", args[0]->flags);
|
||||
auto &label = t.label_find_or_create("OTHER");
|
||||
|
||||
auto vertex_accessor = t.vertex_insert();
|
||||
vertex_accessor.set(prop_key, args[0]);
|
||||
vertex_accessor.add_label(label);
|
||||
// cout_properties(vertex_accessor.properties());
|
||||
return t.commit();
|
||||
};
|
||||
|
||||
auto create_account = [&db](const properties_t &args) {
|
||||
DbAccessor t(db);
|
||||
auto prop_id = t.vertex_property_key("id", args[0]->flags);
|
||||
@ -400,6 +412,7 @@ auto load_queries(Db &db)
|
||||
queries[15648836733456301916u] = create_edge_v2;
|
||||
queries[10597108978382323595u] = create_account;
|
||||
queries[5397556489557792025u] = create_labeled_and_named_node;
|
||||
queries[16090682663946456821u] = create_labeled_and_named_node_v2;
|
||||
queries[7939106225150551899u] = create_edge;
|
||||
queries[6579425155585886196u] = create_edge;
|
||||
queries[11198568396549106428u] = find_node_by_internal_id;
|
||||
@ -412,8 +425,8 @@ auto load_queries(Db &db)
|
||||
queries[14897166600223619735u] = match_edge_all_delete;
|
||||
queries[16888549834923624215u] = match_edge_type_delete;
|
||||
queries[11675960684124428508u] = match_id_type_return;
|
||||
queries[1554436524951961398u] = match_name_type_return;
|
||||
queries[8537338362659537296u] = match_name_type_return_cross;
|
||||
queries[15698881472054193835u] = match_name_type_return;
|
||||
queries[12595102442911913761u] = match_name_type_return_cross;
|
||||
queries[8918221081398321263u] = match_label_type_return;
|
||||
|
||||
return queries;
|
||||
|
@ -24,7 +24,7 @@ public:
|
||||
|
||||
// Returns iterator which returns valid records in range.
|
||||
// ordered==None => doesn't guarantee any order of submitting records.
|
||||
std::unique_ptr<IteratorBase<const typename TG::accessor_t>>
|
||||
iter::Virtual<const typename TG::accessor_t>
|
||||
for_range(DbAccessor &t, Border<K> from = Border<K>(),
|
||||
Border<K> to = Border<K>()) final;
|
||||
|
||||
|
@ -22,7 +22,7 @@ public:
|
||||
|
||||
// Returns iterator which returns valid records in range.
|
||||
// ordered==None => doesn't guarantee any order of submitting records.
|
||||
std::unique_ptr<IteratorBase<const typename T::accessor_t>>
|
||||
iter::Virtual<const typename T::accessor_t>
|
||||
for_range(DbAccessor &t, Border<K> from = Border<K>(),
|
||||
Border<K> to = Border<K>()) final;
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
// #include "storage/indexes/index_record.hpp"
|
||||
#include "storage/garbage/delete_sensitive.hpp"
|
||||
#include "utils/border.hpp"
|
||||
#include "utils/iterator/iterator_base.hpp"
|
||||
#include "utils/iterator/virtual_iter.hpp"
|
||||
#include "utils/order.hpp"
|
||||
|
||||
template <class TG, class K>
|
||||
@ -50,7 +50,7 @@ public:
|
||||
// order==Descending => guarantees order of returned records will be from
|
||||
// largest to smallest.
|
||||
// Range must be from<=to
|
||||
virtual std::unique_ptr<IteratorBase<const typename TG::accessor_t>>
|
||||
virtual iter::Virtual<const typename TG::accessor_t>
|
||||
for_range(DbAccessor &, Border<K> from = Border<K>(),
|
||||
Border<K> to = Border<K>()) = 0;
|
||||
|
||||
|
146
include/utils/iterator/composable.hpp
Normal file
146
include/utils/iterator/composable.hpp
Normal file
@ -0,0 +1,146 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/crtp.hpp"
|
||||
#include "utils/iterator/count.hpp"
|
||||
#include "utils/option.hpp"
|
||||
|
||||
// class EdgeType;
|
||||
|
||||
namespace iter
|
||||
{
|
||||
template <class I, class OP>
|
||||
auto make_map(I &&iter, OP &&op);
|
||||
|
||||
template <class I, class OP>
|
||||
auto make_filter(I &&iter, OP &&op);
|
||||
|
||||
template <class I, class C>
|
||||
void for_all(I &&iter, C &&consumer);
|
||||
|
||||
template <class I, class OP>
|
||||
auto make_flat_map(I &&iter, OP &&op);
|
||||
|
||||
template <class I, class OP>
|
||||
auto make_inspect(I &&iter, OP &&op);
|
||||
|
||||
template <class I, class OP>
|
||||
auto make_limited_map(I &&iter, OP &&op);
|
||||
|
||||
template <class I, class OP>
|
||||
auto make_virtual(I &&iter);
|
||||
|
||||
// Class for creating easy composable iterators fo querying.
|
||||
// Derived - type of derived class
|
||||
// T - return type
|
||||
template <class T, class Derived>
|
||||
class Composable : public Crtp<Derived>
|
||||
{
|
||||
// Moves self
|
||||
Derived &&move() { return std::move(this->derived()); }
|
||||
public:
|
||||
auto virtualize() { return iter::make_virtual(move()); }
|
||||
|
||||
template <class OP>
|
||||
auto map(OP &&op)
|
||||
{
|
||||
return iter::make_map<Derived, OP>(move(), std::move(op));
|
||||
}
|
||||
|
||||
template <class OP>
|
||||
auto filter(OP &&op)
|
||||
{
|
||||
return iter::make_filter<Derived, OP>(move(), std::move(op));
|
||||
}
|
||||
|
||||
// Replaces every item with item taken from n if it exists.
|
||||
template <class R>
|
||||
auto replace(Option<R> &n)
|
||||
{
|
||||
return iter::make_limited_map<Derived>(
|
||||
move(), [&](auto v) mutable { return std::move(n); });
|
||||
}
|
||||
|
||||
// Maps with call to method to() and filters with call to fill.
|
||||
auto to()
|
||||
{
|
||||
return map([](auto er) { return er.to(); }).fill();
|
||||
}
|
||||
|
||||
// Maps with call to method from() and filters with call to fill.
|
||||
auto from()
|
||||
{
|
||||
return map([](auto er) { return er.from(); }).fill();
|
||||
}
|
||||
|
||||
// Combines out iterators into one iterator.
|
||||
auto out()
|
||||
{
|
||||
return iter::make_flat_map<Derived>(
|
||||
move(), [](auto vr) { return vr.out().fill(); });
|
||||
}
|
||||
|
||||
// Filters with label on from vertex.
|
||||
template <class LABEL>
|
||||
auto from_label(LABEL const &label)
|
||||
{
|
||||
return filter([&](auto &ra) {
|
||||
auto va = ra.from();
|
||||
return va.fill() && va.has_label(label);
|
||||
});
|
||||
}
|
||||
|
||||
// Filters with property under given key
|
||||
template <class KEY, class PROP>
|
||||
auto has_property(KEY &key, PROP const &prop)
|
||||
{
|
||||
return filter([&](auto &va) { return va.at(key) == prop; });
|
||||
}
|
||||
|
||||
// Copy-s all pasing value to t before they are returned.
|
||||
// auto clone_to(Option<T> &t)
|
||||
// {
|
||||
// return iter::make_inspect<decltype(std::move(*this))>(
|
||||
// std::move(*this), [&](auto &v) { t = Option<T>(v); });
|
||||
// }
|
||||
|
||||
// Copy-s pasing value to t before they are returned.
|
||||
auto clone_to(Option<const T> &t)
|
||||
{
|
||||
return iter::make_inspect<Derived>(
|
||||
move(), [&](auto &v) mutable { t = Option<const T>(v); });
|
||||
}
|
||||
|
||||
// Filters with call to method fill()
|
||||
auto fill()
|
||||
{
|
||||
return filter([](auto &ra) { return ra.fill(); });
|
||||
}
|
||||
|
||||
// Filters with type
|
||||
template <class TYPE>
|
||||
auto type(TYPE const &type)
|
||||
{
|
||||
return filter([&](auto &ra) { return ra.edge_type() == type; });
|
||||
}
|
||||
|
||||
// Filters with label.
|
||||
template <class LABEL>
|
||||
auto label(LABEL const &label)
|
||||
{
|
||||
return filter([&](auto &va) { return va.has_label(label); });
|
||||
}
|
||||
|
||||
// Filters out vertices which are connected.
|
||||
auto isolated()
|
||||
{
|
||||
return filter([&](auto &ra) { return ra.isolated(); });
|
||||
}
|
||||
|
||||
// For all items calls OP.
|
||||
template <class OP>
|
||||
void for_all(OP &&op)
|
||||
{
|
||||
iter::for_all(move(), std::move(op));
|
||||
}
|
||||
};
|
||||
}
|
@ -12,11 +12,7 @@ public:
|
||||
|
||||
Count(size_t min, size_t max) : min(min), max(max) {}
|
||||
|
||||
Count &min_zero()
|
||||
{
|
||||
min = 0;
|
||||
return *this;
|
||||
}
|
||||
Count min_zero() const { return Count(0, max); }
|
||||
|
||||
size_t avg() const { return ((max - min) >> 1) + min; }
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/iterator/composable.hpp"
|
||||
#include "utils/iterator/iterator_base.hpp"
|
||||
#include "utils/option.hpp"
|
||||
|
||||
namespace iter
|
||||
{
|
||||
@ -12,7 +12,7 @@ namespace iter
|
||||
// I - iterator type
|
||||
// OP - type of filter function. OP: T& -> bool
|
||||
template <class T, class I, class OP>
|
||||
class Filter : public IteratorBase<T>
|
||||
class Filter : public IteratorBase<T>, public Composable<T, Filter<T, I, OP>>
|
||||
{
|
||||
|
||||
public:
|
||||
|
@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/iterator/composable.hpp"
|
||||
#include "utils/iterator/iterator_base.hpp"
|
||||
|
||||
namespace iter
|
||||
{
|
||||
|
||||
@ -12,7 +15,8 @@ namespace iter
|
||||
// J - iterator type returned from OP
|
||||
// OP - type of mapper function
|
||||
template <class T, class I, class J, class OP>
|
||||
class FlatMap : public IteratorBase<T>
|
||||
class FlatMap : public IteratorBase<T>,
|
||||
public Composable<T, FlatMap<T, I, J, OP>>
|
||||
{
|
||||
|
||||
public:
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/iterator/composable.hpp"
|
||||
#include "utils/iterator/iterator_base.hpp"
|
||||
#include "utils/option.hpp"
|
||||
|
||||
namespace iter
|
||||
{
|
||||
@ -13,7 +13,7 @@ namespace iter
|
||||
// I - iterator type
|
||||
// OP - type of inspector function. OP: T&->void
|
||||
template <class T, class I, class OP>
|
||||
class Inspect : public IteratorBase<T>
|
||||
class Inspect : public IteratorBase<T>, public Composable<T, Inspect<T, I, OP>>
|
||||
{
|
||||
|
||||
public:
|
||||
|
@ -12,3 +12,4 @@
|
||||
#include "utils/iterator/limited_map.hpp"
|
||||
#include "utils/iterator/map.hpp"
|
||||
#include "utils/iterator/range_iterator.hpp"
|
||||
#include "utils/iterator/virtual_iter.hpp"
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/iterator/composable.hpp"
|
||||
#include "utils/iterator/iterator_base.hpp"
|
||||
#include "utils/option.hpp"
|
||||
|
||||
namespace iter
|
||||
{
|
||||
@ -11,7 +11,8 @@ namespace iter
|
||||
// I - iterator type gotten from accessor
|
||||
// A - accessor type
|
||||
template <class T, class I, class A>
|
||||
class IteratorAccessor : public IteratorBase<T>
|
||||
class IteratorAccessor : public IteratorBase<T>,
|
||||
public Composable<T, IteratorAccessor<T, I, A>>
|
||||
{
|
||||
public:
|
||||
IteratorAccessor() = delete;
|
||||
|
@ -3,29 +3,6 @@
|
||||
#include "utils/iterator/count.hpp"
|
||||
#include "utils/option.hpp"
|
||||
|
||||
class EdgeType;
|
||||
|
||||
namespace iter
|
||||
{
|
||||
template <class I, class OP>
|
||||
auto make_map(I &&iter, OP &&op);
|
||||
|
||||
template <class I, class OP>
|
||||
auto make_filter(I &&iter, OP &&op);
|
||||
|
||||
template <class I, class C>
|
||||
void for_all(I &&iter, C &&consumer);
|
||||
|
||||
template <class I, class OP>
|
||||
auto make_flat_map(I &&iter, OP &&op);
|
||||
|
||||
template <class I, class OP>
|
||||
auto make_inspect(I &&iter, OP &&op);
|
||||
|
||||
template <class I, class OP>
|
||||
auto make_limited_map(I &&iter, OP &&op);
|
||||
}
|
||||
|
||||
// Base iterator for next() kind iterator.
|
||||
// T - type of return value
|
||||
template <class T>
|
||||
@ -36,110 +13,5 @@ public:
|
||||
|
||||
virtual Option<T> next() = 0;
|
||||
|
||||
virtual Count count() { return Count(0, ~((size_t)0)); }
|
||||
|
||||
template <class OP>
|
||||
auto map(OP &&op)
|
||||
{
|
||||
return iter::make_map<decltype(std::move(*this)), OP>(std::move(*this),
|
||||
std::move(op));
|
||||
}
|
||||
|
||||
template <class OP>
|
||||
auto filter(OP &&op)
|
||||
{
|
||||
return iter::make_filter<decltype(std::move(*this)), OP>(
|
||||
std::move(*this), std::move(op));
|
||||
}
|
||||
|
||||
// Replaces every item with item taken from n if it exists.
|
||||
template <class R>
|
||||
auto replace(Option<R> &n)
|
||||
{
|
||||
return iter::make_limited_map<decltype(std::move(*this))>(
|
||||
std::move(*this), [&](auto v) mutable { return std::move(n); });
|
||||
}
|
||||
|
||||
// Maps with call to method to() and filters with call to fill.
|
||||
auto to()
|
||||
{
|
||||
return map([](auto er) { return er.to(); }).fill();
|
||||
}
|
||||
|
||||
// Maps with call to method from() and filters with call to fill.
|
||||
auto from()
|
||||
{
|
||||
return map([](auto er) { return er.from(); }).fill();
|
||||
}
|
||||
|
||||
// Combines out iterators into one iterator.
|
||||
auto out()
|
||||
{
|
||||
return iter::make_flat_map<decltype(std::move(*this))>(
|
||||
std::move(*this), [](auto vr) { return vr.out().fill(); });
|
||||
}
|
||||
|
||||
// Filters with label on from vertex.
|
||||
template <class LABEL>
|
||||
auto from_label(LABEL const &label)
|
||||
{
|
||||
return filter([&](auto &ra) {
|
||||
auto va = ra.from();
|
||||
return va.fill() && va.has_label(label);
|
||||
});
|
||||
}
|
||||
|
||||
// Filters with property under given key
|
||||
template <class KEY, class PROP>
|
||||
auto has_property(KEY &key, PROP const &prop)
|
||||
{
|
||||
return filter([&](auto &va) { return va.at(key) == prop; });
|
||||
}
|
||||
|
||||
// Copy-s all pasing value to t before they are returned.
|
||||
// auto clone_to(Option<T> &t)
|
||||
// {
|
||||
// return iter::make_inspect<decltype(std::move(*this))>(
|
||||
// std::move(*this), [&](auto &v) { t = Option<T>(v); });
|
||||
// }
|
||||
|
||||
// Copy-s pasing value to t before they are returned.
|
||||
auto clone_to(Option<const T> &t)
|
||||
{
|
||||
return iter::make_inspect<decltype(std::move(*this))>(
|
||||
std::move(*this), [&](auto &v) mutable { t = Option<const T>(v); });
|
||||
}
|
||||
|
||||
// Filters with call to method fill()
|
||||
auto fill()
|
||||
{
|
||||
return filter([](auto &ra) { return ra.fill(); });
|
||||
}
|
||||
|
||||
// Filters with type
|
||||
template <class TYPE>
|
||||
auto type(TYPE const &type)
|
||||
{
|
||||
return filter([&](auto &ra) { return ra.edge_type() == type; });
|
||||
}
|
||||
|
||||
// Filters with label.
|
||||
template <class LABEL>
|
||||
auto label(LABEL const &label)
|
||||
{
|
||||
return filter([&](auto &va) { return va.has_label(label); });
|
||||
}
|
||||
|
||||
// Filters out vertices which are connected.
|
||||
auto isolated()
|
||||
{
|
||||
return filter([&](auto &ra) { return ra.isolated(); });
|
||||
}
|
||||
|
||||
// For all items calls OP.
|
||||
template <class OP>
|
||||
void for_all(OP &&op)
|
||||
{
|
||||
iter::for_all(std::move(*this), std::move(op));
|
||||
}
|
||||
virtual Count count() = 0;
|
||||
};
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/iterator/composable.hpp"
|
||||
#include "utils/iterator/iterator_base.hpp"
|
||||
|
||||
namespace iter
|
||||
@ -8,7 +9,8 @@ namespace iter
|
||||
// T - type of return value
|
||||
// F - type of wraped lambda
|
||||
template <class T, class F>
|
||||
class LambdaIterator : public IteratorBase<T>
|
||||
class LambdaIterator : public IteratorBase<T>,
|
||||
public Composable<T, LambdaIterator<T, F>>
|
||||
{
|
||||
public:
|
||||
LambdaIterator(F &&f, size_t count) : func(std::move(f)), _count(count) {}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/iterator/composable.hpp"
|
||||
#include "utils/iterator/iterator_base.hpp"
|
||||
#include "utils/option.hpp"
|
||||
|
||||
namespace iter
|
||||
{
|
||||
@ -12,7 +12,8 @@ namespace iter
|
||||
// I - iterator type
|
||||
// OP - type of mapper function. OP: V -> Option<T>
|
||||
template <class T, class I, class OP>
|
||||
class LimitedMap : public IteratorBase<T>
|
||||
class LimitedMap : public IteratorBase<T>,
|
||||
public Composable<T, LimitedMap<T, I, OP>>
|
||||
{
|
||||
|
||||
public:
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/iterator/composable.hpp"
|
||||
#include "utils/iterator/iterator_base.hpp"
|
||||
#include "utils/option.hpp"
|
||||
|
||||
namespace iter
|
||||
{
|
||||
@ -12,7 +12,7 @@ namespace iter
|
||||
// I - iterator type
|
||||
// OP - type of mapper function
|
||||
template <class T, class I, class OP>
|
||||
class Map : public IteratorBase<T>
|
||||
class Map : public IteratorBase<T>, public Composable<T, Map<T, I, OP>>
|
||||
{
|
||||
|
||||
public:
|
||||
|
48
include/utils/iterator/virtual_iter.hpp
Normal file
48
include/utils/iterator/virtual_iter.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/iterator/composable.hpp"
|
||||
#include "utils/iterator/iterator_base.hpp"
|
||||
|
||||
namespace iter
|
||||
{
|
||||
|
||||
// Class which wraps iterator and hides it's type. It actualy does this by
|
||||
// dynamicly allocating iterator on heap.
|
||||
// T - type of return value
|
||||
template <class T>
|
||||
class Virtual : public Composable<T, Virtual<T>>
|
||||
{
|
||||
|
||||
public:
|
||||
Virtual() = delete;
|
||||
|
||||
// Virtual operation is designed to be used in chained calls which operate
|
||||
// on a
|
||||
// iterator. Virtual will in that usecase receive other iterator by value
|
||||
// and
|
||||
// std::move is a optimization for it.
|
||||
|
||||
template <class I>
|
||||
Virtual(I &&iter) : it(std::make_unique<I>(std::move(iter)))
|
||||
{
|
||||
}
|
||||
|
||||
Virtual(Virtual &&m) : it(std::move(m.it)) {}
|
||||
|
||||
~Virtual() {}
|
||||
|
||||
Option<T> next() { return it.get()->next(); }
|
||||
|
||||
Count count() { return it.get()->count(); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<IteratorBase<T>> it;
|
||||
};
|
||||
|
||||
template <class I>
|
||||
auto make_virtual(I &&iter)
|
||||
{
|
||||
// Compiler cant deduce type T. decltype is here to help with it.
|
||||
return Virtual<decltype(iter.next().take())>(std::move(iter));
|
||||
}
|
||||
}
|
@ -17,8 +17,12 @@ public:
|
||||
{
|
||||
// use a slow, more complex rnd generator to initialize a fast one
|
||||
// make sure to call this before requesting any random numbers!
|
||||
std::random_device rd;
|
||||
std::mt19937_64 gen(rd());
|
||||
|
||||
// NOTE: Valgird complanis to next instruction
|
||||
// std::random_device rd;
|
||||
// std::mt19937_64 gen(rd());
|
||||
std::mt19937_64 gen(time(0));
|
||||
|
||||
std::uniform_int_distribution<unsigned long long> dist;
|
||||
|
||||
// the number generated by MT can be full of zeros and xorshift
|
||||
|
@ -432,24 +432,24 @@ bool operator!=(const EdgeAccessor &a, const EdgeAccessor &b)
|
||||
}
|
||||
|
||||
// ************************* VertexIterator
|
||||
DESTRUCTOR(VertexIterator, unique_ptr);
|
||||
DESTRUCTOR(VertexIterator, Virtual);
|
||||
|
||||
Option<const VertexAccessor> VertexIterator::next()
|
||||
{
|
||||
return HALF_CALL(get()->next()).map<const VertexAccessor>();
|
||||
return HALF_CALL(next()).map<const VertexAccessor>();
|
||||
}
|
||||
|
||||
Count VertexIterator::count() { return HALF_CALL(get()->count()); }
|
||||
Count VertexIterator::count() { return HALF_CALL(count()); }
|
||||
|
||||
// ************************* EdgeIterator
|
||||
DESTRUCTOR(EdgeIterator, unique_ptr);
|
||||
DESTRUCTOR(EdgeIterator, Virtual);
|
||||
|
||||
Option<const EdgeAccessor> EdgeIterator::next()
|
||||
{
|
||||
return HALF_CALL(get()->next()).map<const EdgeAccessor>();
|
||||
return HALF_CALL(next()).map<const EdgeAccessor>();
|
||||
}
|
||||
|
||||
Count EdgeIterator::count() { return HALF_CALL(get()->count()); }
|
||||
Count EdgeIterator::count() { return HALF_CALL(count()); }
|
||||
|
||||
// ************************* OutEdgesIterator
|
||||
DESTRUCTOR(OutEdgesIterator, out_edge_iterator_t);
|
||||
|
@ -22,7 +22,6 @@ Cleaning::Cleaning(ConcurrentMap<std::string, Db> &dbs) : dbms(dbs)
|
||||
for (auto &db : dbs.access()) {
|
||||
logger.info("Cleaning database \"{}\"", db.first);
|
||||
DbTransaction t(db.second);
|
||||
|
||||
try {
|
||||
logger.info("Cleaning edges");
|
||||
t.clean_edge_section();
|
||||
@ -34,7 +33,6 @@ Cleaning::Cleaning(ConcurrentMap<std::string, Db> &dbs) : dbms(dbs)
|
||||
db.first);
|
||||
logger.error("{}", e.what());
|
||||
}
|
||||
|
||||
t.trans.commit();
|
||||
}
|
||||
last_clean = now;
|
||||
|
@ -32,12 +32,11 @@ bool NonUniqueUnorderedIndex<T, K>::insert(IndexRecord<T, K> &&value)
|
||||
}
|
||||
|
||||
template <class T, class K>
|
||||
std::unique_ptr<IteratorBase<const typename T::accessor_t>>
|
||||
iter::Virtual<const typename T::accessor_t>
|
||||
NonUniqueUnorderedIndex<T, K>::for_range(DbAccessor &t, Border<K> from,
|
||||
Border<K> to)
|
||||
{
|
||||
return std::make_unique<decltype(
|
||||
for_range_exact(t, std::move(from), std::move(to)))>(
|
||||
return iter::make_virtual(
|
||||
for_range_exact(t, std::move(from), std::move(to)));
|
||||
}
|
||||
|
||||
|
@ -39,11 +39,10 @@ bool UniqueOrderedIndex<T, K>::insert(IndexRecord<T, K> &&value)
|
||||
}
|
||||
|
||||
template <class T, class K>
|
||||
std::unique_ptr<IteratorBase<const typename T::accessor_t>>
|
||||
iter::Virtual<const typename T::accessor_t>
|
||||
UniqueOrderedIndex<T, K>::for_range(DbAccessor &t, Border<K> from, Border<K> to)
|
||||
{
|
||||
return std::make_unique<decltype(
|
||||
for_range_exact(t, std::move(from), std::move(to)))>(
|
||||
return iter::make_virtual(
|
||||
for_range_exact(t, std::move(from), std::move(to)));
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,7 @@
|
||||
#include "storage/label/label.hpp"
|
||||
|
||||
Label::Label(const char *name)
|
||||
: name(std::string(name)),
|
||||
index_v(std::unique_ptr<label_index_t>(new label_index_t()))
|
||||
: name(std::string(name)), index_v(std::make_unique<label_index_t>())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -68,6 +68,14 @@ target_link_libraries(integration_queries ${fmt_static_lib})
|
||||
add_test(NAME integration_queries COMMAND integration_queries)
|
||||
set_property(TARGET integration_queries PROPERTY CXX_STANDARD 14)
|
||||
|
||||
# test cleaning methods
|
||||
add_executable(cleaning integration/cleaning.cpp)
|
||||
target_link_libraries(cleaning memgraph)
|
||||
target_link_libraries(cleaning Threads::Threads)
|
||||
target_link_libraries(cleaning ${fmt_static_lib})
|
||||
add_test(NAME cleaning COMMAND cleaning)
|
||||
set_property(TARGET cleaning PROPERTY CXX_STANDARD 14)
|
||||
|
||||
# test query engine
|
||||
add_executable(integration_query_engine integration/query_engine.cpp)
|
||||
target_link_libraries(integration_query_engine Threads::Threads)
|
||||
|
96
tests/integration/cleaning.cpp
Normal file
96
tests/integration/cleaning.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
#include "query_engine/hardcode/queries.hpp"
|
||||
|
||||
#include "barrier/barrier.cpp"
|
||||
|
||||
#include "logging/default.hpp"
|
||||
#include "logging/streams/stdout.hpp"
|
||||
#include "query_engine/query_stripper.hpp"
|
||||
#include "utils/sysinfo/memory.hpp"
|
||||
|
||||
template <class S, class Q>
|
||||
void run(size_t n, std::string &query, S &stripper, Q &qf)
|
||||
{
|
||||
auto stripped = stripper.strip(query);
|
||||
std::cout << "Running query [" << stripped.hash << "] for " << n << " time."
|
||||
<< std::endl;
|
||||
for (int i = 0; i < n; i++) {
|
||||
assert(qf[stripped.hash](stripped.arguments));
|
||||
}
|
||||
}
|
||||
|
||||
void clean_vertex(Db &db)
|
||||
{
|
||||
DbTransaction t(db);
|
||||
t.clean_vertex_section();
|
||||
t.trans.commit();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
logging::init_async();
|
||||
logging::log->pipe(std::make_unique<Stdout>());
|
||||
|
||||
size_t cvl_n = 1000;
|
||||
|
||||
Db db;
|
||||
|
||||
auto query_functions = load_queries(barrier::trans(db));
|
||||
|
||||
auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL);
|
||||
|
||||
std::string create_vertex_label =
|
||||
"CREATE (n:LABEL {name: \"cleaner_test\"}) RETURN n";
|
||||
std::string create_vertex_other =
|
||||
"CREATE (n:OTHER {name: \"cleaner_test\"}) RETURN n";
|
||||
std::string delete_label_vertices = "MATCH (n:LABEL) DELETE n";
|
||||
std::string delete_all_vertices = "MATCH (n) DELETE n";
|
||||
|
||||
// ******************************* TEST 1 ********************************//
|
||||
// add vertices a
|
||||
// clean vertices
|
||||
// delete vertices a
|
||||
// clean vertices
|
||||
run(cvl_n, create_vertex_label, stripper, query_functions);
|
||||
assert(db.graph.vertices.access().size() == cvl_n);
|
||||
|
||||
clean_vertex(db);
|
||||
assert(db.graph.vertices.access().size() == cvl_n);
|
||||
|
||||
run(1, delete_label_vertices, stripper, query_functions);
|
||||
assert(db.graph.vertices.access().size() == cvl_n);
|
||||
|
||||
clean_vertex(db);
|
||||
assert(db.graph.vertices.access().size() == 0);
|
||||
|
||||
// ******************************* TEST 2 ********************************//
|
||||
// add vertices a
|
||||
// add vertices b
|
||||
// clean vertices
|
||||
// delete vertices a
|
||||
// clean vertices
|
||||
// delete vertices all
|
||||
run(cvl_n, create_vertex_label, stripper, query_functions);
|
||||
assert(db.graph.vertices.access().size() == cvl_n);
|
||||
|
||||
run(cvl_n, create_vertex_other, stripper, query_functions);
|
||||
assert(db.graph.vertices.access().size() == cvl_n * 2);
|
||||
|
||||
clean_vertex(db);
|
||||
assert(db.graph.vertices.access().size() == cvl_n * 2);
|
||||
|
||||
run(1, delete_label_vertices, stripper, query_functions);
|
||||
assert(db.graph.vertices.access().size() == cvl_n * 2);
|
||||
|
||||
clean_vertex(db);
|
||||
assert(db.graph.vertices.access().size() == cvl_n);
|
||||
|
||||
run(1, delete_all_vertices, stripper, query_functions);
|
||||
assert(db.graph.vertices.access().size() == cvl_n);
|
||||
|
||||
clean_vertex(db);
|
||||
assert(db.graph.vertices.access().size() == 0);
|
||||
|
||||
// TODO: more tests
|
||||
|
||||
return 0;
|
||||
}
|
@ -2,9 +2,9 @@
|
||||
|
||||
#include "barrier/barrier.cpp"
|
||||
|
||||
#include "communication/bolt/v1/serialization/bolt_serializer.hpp"
|
||||
#include "database/db.hpp"
|
||||
#include "query_engine/query_stripper.hpp"
|
||||
#include "communication/bolt/v1/serialization/bolt_serializer.hpp"
|
||||
// #include "storage/edges.cpp"
|
||||
// #include "storage/edges.hpp"
|
||||
// #include "storage/vertices.cpp"
|
||||
@ -24,6 +24,7 @@ int main(void)
|
||||
"CREATE (n:LABEL {name: \"TEST1\"}) RETURN n",
|
||||
"CREATE (n:LABEL {name: \"TEST2\"}) RETURN n",
|
||||
"CREATE (n:LABEL {name: \"TEST3\"}) RETURN n",
|
||||
"CREATE (n:OTHER {name: \"TEST4\"}) RETURN n"
|
||||
"CREATE (n:ACCOUNT {id: 2322, name: \"TEST\", country: \"Croatia\", "
|
||||
"created_at: 2352352}) RETURN n",
|
||||
"MATCH (n {id: 0}) RETURN n", "MATCH (n {id: 1}) RETURN n",
|
||||
@ -35,10 +36,21 @@ int main(void)
|
||||
"MATCH (n: {id: 0}) SET n.name = \"TEST100\" RETURN n",
|
||||
"MATCH (n: {id: 1}) SET n.name = \"TEST101\" RETURN n",
|
||||
"MATCH (n: {id: 0}) SET n.name = \"TEST102\" RETURN n",
|
||||
"MATCH (n:LABEL) RETURN n"};
|
||||
"MATCH (n:LABEL) RETURN n", "MATCH (n1), (n2) WHERE ID(n1)=0 AND "
|
||||
"ID(n2)=1 CREATE (n1)<-[r:IS {age: "
|
||||
"25,weight: 70}]-(n2) RETURN r",
|
||||
"MATCH (n) RETURN n", "MATCH (n:LABEL) RETURN n", "MATCH (n) DELETE n ",
|
||||
"MATCH (n:LABEL) DELETE n", "MATCH (n) WHERE ID(n) = 0 DELETE n",
|
||||
"MATCH ()-[r]-() WHERE ID(r) = 0 DELETE r", "MATCH ()-[r]-() DELETE r",
|
||||
"MATCH ()-[r:TYPE]-() DELETE r",
|
||||
"MATCH (n)-[:TYPE]->(m) WHERE ID(n) = 0 RETURN m",
|
||||
"MATCH (n)-[:TYPE]->(m) WHERE n.name = \"kruno\" RETURN m",
|
||||
"MATCH (n)-[:TYPE]->(m) WHERE n.name = \"kruno\" RETURN n,m",
|
||||
"MATCH (n:LABEL)-[:TYPE]->(m) RETURN n"};
|
||||
|
||||
for (auto &query : queries) {
|
||||
auto stripped = stripper.strip(query);
|
||||
std::cout << "Query hash: " << stripped.hash << std::endl;
|
||||
auto result = query_functions[stripped.hash](stripped.arguments);
|
||||
permanent_assert(result == true,
|
||||
"Result retured from query function is not true");
|
||||
|
Loading…
Reference in New Issue
Block a user