diff --git a/CMakeLists.txt b/CMakeLists.txt index a1086b0df..e41ecc27f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -407,6 +407,7 @@ set(memgraph_src_files ${src_dir}/utils/string/transform.cpp ${src_dir}/utils/string/join.cpp ${src_dir}/utils/string/file.cpp + ${src_dir}/utils/iterator/iterator_base.cpp ${src_dir}/query_engine/util.cpp ${src_dir}/communication/bolt/v1/bolt.cpp ${src_dir}/communication/bolt/v1/states.cpp diff --git a/include/barrier/barrier.hpp b/include/barrier/barrier.hpp index 748358c54..7c03e49c9 100644 --- a/include/barrier/barrier.hpp +++ b/include/barrier/barrier.hpp @@ -64,8 +64,8 @@ using label_ref_t = ReferenceWrapper<const Label>; // Original class should have Sized barrier class if it can't be Unsized. // Sized barrier classes should: // --Have same name as original class. -// --Inherit Sized class from common.hpp as private. Blueprint: -// class class_name: Sized<size_of_t,aligment_of_t> +// --Inherit Sized class from common.hpp as public. Blueprint: +// class class_name: public Sized<size_of_t,aligment_of_t> // --Sized template arguments must be hardcoded numbers equal to sizeof(T) and // alignof(T) where T is original class. // --It should have undefined public constructor which is specialized in .cpp @@ -83,7 +83,7 @@ using label_ref_t = ReferenceWrapper<const Label>; // --It should specify public methods which can be called on the original class. // // Blueprint: -// class class_name : private Sized<,> +// class class_name : public Sized<,> // { // public: // template <class T> @@ -281,7 +281,8 @@ public: void abort(); }; -class VertexIterator : private Sized<8, 8> +class VertexIterator : public Sized<8, 8>, + public IteratorBase<const VertexAccessor> { public: template <class T> @@ -293,11 +294,14 @@ public: VertexIterator &operator=(const VertexIterator &other) = delete; VertexIterator &operator=(VertexIterator &&other) = delete; - Option<const VertexAccessor> next(); + Option<const VertexAccessor> next() final; + + Count count() final; }; // TODO: Find reasons of such great size ant try to decrease it. -class VertexAccessIterator : private Sized<552, 8> +class VertexAccessIterator : public Sized<560, 8>, + public IteratorBase<const VertexAccessor> { public: template <class T> @@ -309,11 +313,14 @@ public: VertexAccessIterator &operator=(const VertexAccessIterator &other) = delete; VertexAccessIterator &operator=(VertexAccessIterator &&other) = delete; - Option<const VertexAccessor> next(); + Option<const VertexAccessor> next() final; + + Count count() final; }; // TODO: Find reasons of such great size ant try to decrease it. -class EdgeAccessIterator : private Sized<552, 8> +class EdgeAccessIterator : public Sized<560, 8>, + public IteratorBase<const EdgeAccessor> { public: template <class T> @@ -325,10 +332,13 @@ public: EdgeAccessIterator &operator=(const EdgeAccessIterator &other) = delete; EdgeAccessIterator &operator=(EdgeAccessIterator &&other) = delete; - Option<const EdgeAccessor> next(); + Option<const EdgeAccessor> next() final; + + Count count() final; }; -class OutEdgesIterator : private Sized<40, 8> +class OutEdgesIterator : public Sized<48, 8>, + public IteratorBase<const EdgeAccessor> { public: template <class T> @@ -340,10 +350,13 @@ public: OutEdgesIterator &operator=(const OutEdgesIterator &other) = delete; OutEdgesIterator &operator=(OutEdgesIterator &&other) = delete; - Option<const EdgeAccessor> next(); + Option<const EdgeAccessor> next() final; + + Count count() final; }; -class InEdgesIterator : private Sized<56, 8> +class InEdgesIterator : public Sized<64, 8>, + public IteratorBase<const EdgeAccessor> { public: template <class T> @@ -355,10 +368,12 @@ public: InEdgesIterator &operator=(const InEdgesIterator &other) = delete; InEdgesIterator &operator=(InEdgesIterator &&other) = delete; - Option<const EdgeAccessor> next(); + Option<const EdgeAccessor> next() final; + + Count count() final; }; -class EdgeIterator : private Sized<8, 8> +class EdgeIterator : public Sized<8, 8>, public IteratorBase<const EdgeAccessor> { public: template <class T> @@ -370,7 +385,9 @@ public: EdgeIterator &operator=(const EdgeIterator &other) = delete; EdgeIterator &operator=(EdgeIterator &&other) = delete; - Option<const EdgeAccessor> next(); + Option<const EdgeAccessor> next() final; + + Count count() final; }; class VertexPropertyKey : private Sized<8, 8> diff --git a/include/barrier/common.hpp b/include/barrier/common.hpp index 75b2bdbe6..1873988f7 100644 --- a/include/barrier/common.hpp +++ b/include/barrier/common.hpp @@ -121,6 +121,18 @@ protected: "Border class aligment mismatch"); } +public: + typename std::aligned_storage<size_B, alignment_B>::type &_data_ref() + { + return data; + } + + typename std::aligned_storage<size_B, alignment_B>::type const & + _data_ref_const() const + { + return data; + } + private: // Here is the aligned storage which imitates size and aligment of object of // original class from memgraph. diff --git a/include/barrier/trans.hpp b/include/barrier/trans.hpp index 2aa927d98..1e474903f 100644 --- a/include/barrier/trans.hpp +++ b/include/barrier/trans.hpp @@ -12,6 +12,8 @@ #include "storage/edge_x_vertex.hpp" #include "storage/label/label.hpp" +// This is the place for imports from memgraph .cpp + // **************************** HELPER DEFINES *******************************// // Creates 8 functions for transformation of refereces between types x and y. // Where x is a border type. @@ -26,6 +28,21 @@ y *trans(x *l) { return ptr_as<y>(l); } \ y const *trans(x const *l) { return ptr_as<y const>(l); } +// Creates 4 functions for transformation of refereces between types x and y. +// Where x is a sized border type. +// DANGEROUS +#define TRANSFORM_REF_SIZED(x, y) \ + y &trans(x &l) { return ref_as<y>(l._data_ref()); } \ + y const &trans(x const &l) \ + { \ + return ref_as<y const>(l._data_ref_const()); \ + } \ + y *trans(x *l) { return ptr_as<y>(&(l->_data_ref())); } \ + y const *trans(x const *l) \ + { \ + return ptr_as<y const>(&(l->_data_ref_const())); \ + } + // Creates 8 functions for transformation of refereces between types x and y. // Where both x and y are templates over T. Where x is a border type. // DANGEROUS @@ -158,14 +175,16 @@ TRANSFORM_REF(VertexPropertyKey, ::VertexPropertyFamily::PropertyType::PropertyFamilyKey); TRANSFORM_REF(EdgePropertyKey, ::EdgePropertyFamily::PropertyType::PropertyFamilyKey); -TRANSFORM_REF(VertexIterator, - std::unique_ptr<IteratorBase<const ::VertexAccessor>>); -TRANSFORM_REF(EdgeIterator, - std::unique_ptr<IteratorBase<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); + +// 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); template <class T> TRANSFORM_REF_TEMPLATED(VertexIndex<T>, VertexIndexBase<T>); @@ -193,21 +212,22 @@ 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); +// 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>>); +// 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(EdgeIterator, +// std::unique_ptr<IteratorBase<const ::EdgeAccessor>>); template <class T> TRANSFORM_VALUE_ONE_RAW( diff --git a/include/data_structures/concurrent/common.hpp b/include/data_structures/concurrent/common.hpp index 4ec9e7c16..35b1e3408 100644 --- a/include/data_structures/concurrent/common.hpp +++ b/include/data_structures/concurrent/common.hpp @@ -62,6 +62,8 @@ public: ~AccessorBase() {} + size_t size() { return accessor.size(); }; + list_it begin() { return accessor.begin(); } list_it_con begin() const { return accessor.cbegin(); } diff --git a/include/data_structures/concurrent/concurrent_list.hpp b/include/data_structures/concurrent/concurrent_list.hpp index 87d414f49..8f16a504b 100644 --- a/include/data_structures/concurrent/concurrent_list.hpp +++ b/include/data_structures/concurrent/concurrent_list.hpp @@ -281,6 +281,8 @@ public: ConstIterator cend() { return ConstIterator(); } + std::size_t size() { return count.load(std::memory_order_consume); } + private: std::atomic<std::size_t> count{0}; std::atomic<Node *> head{nullptr}; diff --git a/include/query_engine/hardcode/queries.hpp b/include/query_engine/hardcode/queries.hpp index 8d1a0c86b..191cca8de 100644 --- a/include/query_engine/hardcode/queries.hpp +++ b/include/query_engine/hardcode/queries.hpp @@ -4,6 +4,7 @@ #include <map> #include "barrier/barrier.hpp" +#include "utils/iterator/iterator_base.cpp" using namespace std; @@ -157,11 +158,8 @@ auto load_queries(Db &db) auto match_all_nodes = [&db](const properties_t &args) { DbAccessor t(db); - iter::for_all(t.vertex_access(), [&](auto vertex) { - if (vertex.fill()) { - cout << vertex.id() << endl; - } - }); + t.vertex_access().fill().for_all( + [&](auto vertex) { cout << vertex.id() << endl; }); return t.commit(); }; @@ -174,8 +172,8 @@ auto load_queries(Db &db) auto prop_key = t.vertex_property_key("name", Flags::String); cout << "VERTICES" << endl; - iter::for_all(label.index().for_range(t), - [&](auto a) { cout << a.at(prop_key) << endl; }); + label.index().for_range(t).for_all( + [&](auto a) { cout << a.at(prop_key) << endl; }); return t.commit(); }; @@ -184,11 +182,7 @@ auto load_queries(Db &db) auto match_all_delete = [&db](const properties_t &args) { DbAccessor t(db); - iter::for_all(t.vertex_access(), [&](auto a) { - if (a.fill()) { - a.remove(); - } - }); + t.vertex_access().fill().for_all([&](auto a) { a.remove(); }); return t.commit(); }; @@ -199,11 +193,7 @@ auto load_queries(Db &db) auto &label = t.label_find_or_create("LABEL"); - iter::for_all(label.index().for_range(t), [&](auto a) { - if (a.fill()) { - a.remove(); - } - }); + label.index().for_range(t).for_all([&](auto a) { a.remove(); }); return t.commit(); }; @@ -238,11 +228,7 @@ auto load_queries(Db &db) auto match_edge_all_delete = [&db](const properties_t &args) { DbAccessor t(db); - iter::for_all(t.edge_access(), [&](auto a) { - if (a.fill()) { - a.remove(); - } - }); + t.edge_access().fill().for_all([&](auto a) { a.remove(); }); return t.commit(); }; @@ -253,26 +239,46 @@ auto load_queries(Db &db) auto &type = t.type_find_or_create("TYPE"); - iter::for_all(type.index().for_range(t), [&](auto a) { - if (a.fill()) { - a.remove(); - } - }); + type.index().for_range(t).for_all([&](auto a) { a.remove(); }); return t.commit(); }; // MATCH (n)-[:TYPE]->(m) WHERE ID(n) = id RETURN m - auto match_type_id_return = [&db](const properties_t &args) { + auto match_id_type_return = [&db](const properties_t &args) { DbAccessor t(db); + auto &type = t.type_find_or_create("TYPE"); + auto ov = t.vertex_find(args[0]->as<Int64>().value); if (!option_fill(ov)) return t.commit(), false; auto v = ov.take(); - auto resoults = iter::make_f` + auto results = v.out().fill().type(type).to(); - return t.commit(); + // Example of Print resoult. + // results.for_all([&](auto va) { + // va is VertexAccessor + // PRINT + // }); + + return t.commit(); + }; + + // MATCH (n)-[:TYPE]->(m) WHERE n.name = "kruno" RETURN m + auto match_name_type_return = [&db](const properties_t &args) { + DbAccessor t(db); + + auto &type = t.type_find_or_create("TYPE"); + + auto it_type = type.index().for_range(t); + auto it_vertex = t.vertex_access(); + + // if(it_type.count().max>it_vertex.count().max){ + // + // } + + return t.commit(); }; // Blueprint: @@ -299,6 +305,7 @@ auto load_queries(Db &db) queries[6963549500479100885u] = match_edge_id_delete; queries[14897166600223619735u] = match_edge_all_delete; queries[16888549834923624215u] = match_edge_type_delete; + queries[11675960684124428508u] = match_id_type_return; return queries; } diff --git a/include/storage/model/edge_list.hpp b/include/storage/model/edge_list.hpp index ac53ab4db..cf139a4e5 100644 --- a/include/storage/model/edge_list.hpp +++ b/include/storage/model/edge_list.hpp @@ -27,6 +27,8 @@ public: void clear() { edges.clear(); } + std::size_t size() { return edges.size(); } + private: std::vector<EdgeRecord *> edges; }; diff --git a/include/storage/model/edge_map.hpp b/include/storage/model/edge_map.hpp index 5460e3e18..d1d9b0035 100644 --- a/include/storage/model/edge_map.hpp +++ b/include/storage/model/edge_map.hpp @@ -28,6 +28,8 @@ public: void clear() { edges.clear(); } + std::size_t size() { return edges.size(); } + private: RhHashMultiMap<VertexRecord *, EdgeRecord> edges; }; diff --git a/include/utils/iterator/count.hpp b/include/utils/iterator/count.hpp new file mode 100644 index 000000000..20016970f --- /dev/null +++ b/include/utils/iterator/count.hpp @@ -0,0 +1,21 @@ +#pragma once + +// Represents number of to be returned elements from iterator. Where acutal +// number is probably somwhere in [min,max]. +class Count +{ + +public: + Count(size_t exact) : min(exact), max(exact) {} + + Count(size_t min, size_t max) : min(min), max(max) {} + + Count &min_zero() + { + min = 0; + return *this; + } + + size_t min; + size_t max; +}; diff --git a/include/utils/iterator/filter.hpp b/include/utils/iterator/filter.hpp index fc908f19c..f0c430309 100644 --- a/include/utils/iterator/filter.hpp +++ b/include/utils/iterator/filter.hpp @@ -6,12 +6,11 @@ namespace iter { -// Class which filters values returned by I iterator into value of type T with -// OP -// function. +// Class which filters values T returned by I iterator if OP returns true for +// them. // T - type of return value // I - iterator type -// OP - type of mapper function +// OP - type of filter function. OP: T& -> bool template <class T, class I, class OP> class Filter : public IteratorBase<T> { @@ -25,30 +24,32 @@ public: // std::move is a optimization for it. Filter(I &&iter, OP &&op) : iter(std::move(iter)), op(std::move(op)) {} - Filter(Filter &&m) : iter(std::move(m.iter)), op(std::move(m.op)) {} - - ~Filter() final {} - + // Return values for which filter return true. Option<T> next() final { - auto item = iter.next(); - if (item.is_present()) { - return Option<T>(op(item.take())); - } else { - return Option<T>(); - } + auto item = Option<T>(); + do { + item = iter.next(); + if (!item.is_present()) { + return Option<T>(); + } + } while (!op(item.get())); + + return std::move(item); } + Count count() final { return iter.count().min_zero(); } + private: I iter; OP op; }; template <class I, class OP> -auto make_map(I &&iter, OP &&op) +auto make_filter(I &&iter, OP &&op) { // Compiler cant deduce type T. decltype is here to help with it. - return Filter<decltype(op(iter.next().take())), I, OP>(std::move(iter), - std::move(op)); + return Filter<decltype(iter.next().take()), I, OP>(std::move(iter), + std::move(op)); } } diff --git a/include/utils/iterator/iterator.hpp b/include/utils/iterator/iterator.hpp index 93e48a67d..fb9d41655 100644 --- a/include/utils/iterator/iterator.hpp +++ b/include/utils/iterator/iterator.hpp @@ -1,6 +1,8 @@ #pragma once #include "utils/iterator/accessor.hpp" +#include "utils/iterator/count.hpp" +#include "utils/iterator/filter.hpp" #include "utils/iterator/for_all.hpp" #include "utils/iterator/iterator_accessor.hpp" #include "utils/iterator/iterator_base.hpp" diff --git a/include/utils/iterator/iterator_accessor.hpp b/include/utils/iterator/iterator_accessor.hpp index 54ef77eda..2acd960d3 100644 --- a/include/utils/iterator/iterator_accessor.hpp +++ b/include/utils/iterator/iterator_accessor.hpp @@ -17,12 +17,13 @@ public: IteratorAccessor() = delete; IteratorAccessor(A &&acc) - : begin(std::move(acc.begin())), acc(std::forward<A>(acc)) + : begin(std::move(acc.begin())), acc(std::forward<A>(acc)), returned(0) { } IteratorAccessor(IteratorAccessor &&other) - : begin(std::move(other.begin)), acc(std::forward<A>(other.acc)) + : begin(std::move(other.begin)), acc(std::forward<A>(other.acc)), + returned(other.returned) { } @@ -37,15 +38,27 @@ public: if (begin != acc.end()) { auto ret = Option<T>(&(*(begin.operator->()))); begin++; + returned++; return ret; } else { return Option<T>(); } } + Count count() final + { + auto size = acc.size(); + if (size > returned) { + return Count(0); + } else { + return Count(size - returned); + } + } + private: I begin; A acc; + size_t returned; }; // TODO: Join to make functions into one diff --git a/include/utils/iterator/iterator_base.hpp b/include/utils/iterator/iterator_base.hpp index 68403c548..d6feb5813 100644 --- a/include/utils/iterator/iterator_base.hpp +++ b/include/utils/iterator/iterator_base.hpp @@ -1,7 +1,10 @@ #pragma once +#include "utils/iterator/count.hpp" #include "utils/option.hpp" +class EdgeType; + // Base iterator for next() kind iterator. // T - type of return value template <class T> @@ -11,4 +14,26 @@ public: virtual ~IteratorBase(){}; virtual Option<T> next() = 0; + + virtual Count count() { return Count(0, ~((size_t)0)); } + + template <class OP> + auto map(OP &&op); + + template <class OP> + auto filter(OP &&op); + + // Maps with call to method to() and filters with call to fill. + auto to(); + + // Filters with call to method fill() + auto fill(); + + // Filters with type + template <class TYPE> + auto type(TYPE const &type); + + // For all items calls OP. + template <class OP> + void for_all(OP &&op); }; diff --git a/include/utils/iterator/lambda_iterator.hpp b/include/utils/iterator/lambda_iterator.hpp index 67dbccfb6..cd130af31 100644 --- a/include/utils/iterator/lambda_iterator.hpp +++ b/include/utils/iterator/lambda_iterator.hpp @@ -11,26 +11,36 @@ template <class T, class F> class LambdaIterator : public IteratorBase<T> { public: - LambdaIterator(F &&f) : func(std::move(f)) {} + LambdaIterator(F &&f, size_t count) : func(std::move(f)), _count(count) {} - LambdaIterator(LambdaIterator &&other) : func(std::move(other.func)) {} + LambdaIterator(LambdaIterator &&other) + : func(std::move(other.func)), _count(other._count) + { + } ~LambdaIterator() final {} - Option<T> next() final { return func(); } + Option<T> next() final + { + _count = _count > 0 ? _count - 1 : 0; + return func(); + } + + Count count() final { return Count(_count); } private: F func; + size_t _count; }; // Wraps lambda which returns options as an iterator. template <class F> -auto make_iterator(F &&f) +auto make_iterator(F &&f, size_t count) { // Because function isn't receving or in any way using type T from // FunctionIterator compiler can't deduce it thats way there is decltype in // construction of FunctionIterator. Resoulting type of iter.next().take() // is T. - return LambdaIterator<decltype(f().take()), F>(std::move(f)); + return LambdaIterator<decltype(f().take()), F>(std::move(f), count); } } diff --git a/include/utils/iterator/map.hpp b/include/utils/iterator/map.hpp index ddbc45700..53cf52f46 100644 --- a/include/utils/iterator/map.hpp +++ b/include/utils/iterator/map.hpp @@ -37,6 +37,8 @@ public: } } + Count count() final { return iter.count(); } + private: I iter; OP op; diff --git a/include/utils/iterator/query.hpp b/include/utils/iterator/query.hpp new file mode 100644 index 000000000..b3fa64365 --- /dev/null +++ b/include/utils/iterator/query.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "storage/vertex_accessor.hpp" +#include "utils/iterator/iterator.hpp" +#include "utils/option.hpp" + +namespace query_help +{ + +template <class A> +bool fill(A &a) +{ + return a.fill(); +} +}; + +// Base iterator for next() kind iterator. +// Vertex::Accessor - type of return value +template <> +class IteratorBase<Vertex::Accessor> +{ +public: + virtual Option<Vertex::Accessor> next() = 0; + + auto fill() + { + return iter::make_filter(std::move(*this), query_help::fill); + } +}; diff --git a/src/barrier/barrier.cpp b/src/barrier/barrier.cpp index a2630d0a3..717e1fedf 100644 --- a/src/barrier/barrier.cpp +++ b/src/barrier/barrier.cpp @@ -437,6 +437,8 @@ Option<const VertexAccessor> VertexIterator::next() return HALF_CALL(get()->next()).map<const VertexAccessor>(); } +Count VertexIterator::count() { return HALF_CALL(get()->count()); } + // ************************* EdgeIterator DESTRUCTOR(EdgeIterator, unique_ptr); @@ -445,6 +447,8 @@ Option<const EdgeAccessor> EdgeIterator::next() return HALF_CALL(get()->next()).map<const EdgeAccessor>(); } +Count EdgeIterator::count() { return HALF_CALL(get()->count()); } + // ************************* OutEdgesIterator DESTRUCTOR(OutEdgesIterator, out_edge_iterator_t); @@ -453,6 +457,8 @@ Option<const EdgeAccessor> OutEdgesIterator::next() return HALF_CALL(next()).map<const EdgeAccessor>(); } +Count OutEdgesIterator::count() { return HALF_CALL(count()); } + // ************************* InEdgesIterator DESTRUCTOR(InEdgesIterator, in_edge_iterator_t); @@ -461,6 +467,8 @@ Option<const EdgeAccessor> InEdgesIterator::next() return HALF_CALL(next()).map<const EdgeAccessor>(); } +Count InEdgesIterator::count() { return HALF_CALL(count()); } + // ************************* VertexAccessIterator DESTRUCTOR(VertexAccessIterator, vertex_access_iterator_t); @@ -469,6 +477,8 @@ Option<const VertexAccessor> VertexAccessIterator::next() return HALF_CALL(next()).map<const VertexAccessor>(); } +Count VertexAccessIterator::count() { return HALF_CALL(count()); } + // ************************* EdgeAccessIterator DESTRUCTOR(EdgeAccessIterator, edge_access_iterator_t); @@ -477,6 +487,8 @@ Option<const EdgeAccessor> EdgeAccessIterator::next() return HALF_CALL(next()).map<const EdgeAccessor>(); } +Count EdgeAccessIterator::count() { return HALF_CALL(count()); } + // ************************* VertexPropertyKey DESTRUCTOR(VertexPropertyKey, PropertyFamilyKey); diff --git a/src/storage/indexes/impl/nonunique_unordered_index.cpp b/src/storage/indexes/impl/nonunique_unordered_index.cpp index d96f148ad..006ae702a 100644 --- a/src/storage/indexes/impl/nonunique_unordered_index.cpp +++ b/src/storage/indexes/impl/nonunique_unordered_index.cpp @@ -46,22 +46,26 @@ auto NonUniqueUnorderedIndex<T, K>::for_range_exact(DbAccessor &t_v, Border<K> from_v, Border<K> to_v) { - return iter::make_iterator([ - it = list.cbegin(), end = list.cend(), from = from_v, to = to_v, t = t_v - ]() mutable->auto { - while (it != end) { - const IndexRecord<T, K> &r = *it; - if (from < r.key && to > r.key && - r.is_valid(t.db_transaction.trans)) { - const typename T::accessor_t acc = r.access(t.db_transaction); + return iter::make_iterator( + [ + it = list.cbegin(), end = list.cend(), from = from_v, to = to_v, + t = t_v + ]() mutable->auto { + while (it != end) { + const IndexRecord<T, K> &r = *it; + if (from < r.key && to > r.key && + r.is_valid(t.db_transaction.trans)) { + const typename T::accessor_t acc = + r.access(t.db_transaction); + it++; + return make_option(std::move(acc)); + } it++; - return make_option(std::move(acc)); } - it++; - } - return Option<const typename T::accessor_t>(); - }); + return Option<const typename T::accessor_t>(); + }, + list.size()); } template <class T, class K> diff --git a/src/storage/indexes/impl/unique_ordered_index.cpp b/src/storage/indexes/impl/unique_ordered_index.cpp index a0de33592..dc2e6ec83 100644 --- a/src/storage/indexes/impl/unique_ordered_index.cpp +++ b/src/storage/indexes/impl/unique_ordered_index.cpp @@ -64,23 +64,28 @@ auto UniqueOrderedIndex<T, K>::for_range_exact(DbAccessor &t_v, } else { assert(this->order() != None); } + // TODO: determine size on fact of border size. + auto size = acc.size(); - return iter::make_iterator([ - it = std::move(begin), b_end = std::move(end), t = t_v, - hold_acc = std::move(acc) - ]() mutable->auto { - while (b_end >= it->key) { - const IndexRecord<T, K> &r = *it; - if (r.is_valid(t.db_transaction.trans)) { - const typename T::accessor_t acc = r.access(t.db_transaction); + return iter::make_iterator( + [ + it = std::move(begin), b_end = std::move(end), t = t_v, + hold_acc = std::move(acc) + ]() mutable->auto { + while (b_end >= it->key) { + const IndexRecord<T, K> &r = *it; + if (r.is_valid(t.db_transaction.trans)) { + const typename T::accessor_t acc = + r.access(t.db_transaction); + it++; + return make_option(std::move(acc)); + } it++; - return make_option(std::move(acc)); } - it++; - } - return Option<const typename T::accessor_t>(); - }); + return Option<const typename T::accessor_t>(); + }, + size); } template <class T, class K> diff --git a/src/utils/iterator/iterator_base.cpp b/src/utils/iterator/iterator_base.cpp new file mode 100644 index 000000000..63615c825 --- /dev/null +++ b/src/utils/iterator/iterator_base.cpp @@ -0,0 +1,43 @@ +#include "utils/iterator/iterator.hpp" + +template <class T> +template <class OP> +auto IteratorBase<T>::map(OP &&op) +{ + return iter::make_map<decltype(std::move(*this)), OP>(std::move(*this), + std::move(op)); +} + +template <class T> +template <class OP> +auto IteratorBase<T>::filter(OP &&op) +{ + return iter::make_filter<decltype(std::move(*this)), OP>(std::move(*this), + std::move(op)); +} + +template <class T> +auto IteratorBase<T>::to() +{ + return map([](auto er) { return er.to(); }).fill(); +} + +template <class T> +auto IteratorBase<T>::fill() +{ + return filter([](auto &ra) { return ra.fill(); }); +} + +template <class T> +template <class TYPE> +auto IteratorBase<T>::type(TYPE const &type) +{ + return filter([&](auto &ra) { return ra.edge_type() == type; }); +} + +template <class T> +template <class OP> +void IteratorBase<T>::for_all(OP &&op) +{ + iter::for_all(std::move(*this), std::move(op)); +}