From a11ebef9c5425868a0f7fbbcdab07c53c05bdd28 Mon Sep 17 00:00:00 2001 From: florijan Date: Thu, 16 Feb 2017 17:43:39 +0100 Subject: [PATCH] Properties system and core storage major refactor. STABLE STATE, unit tests added. --- include/storage/record_accessor.hpp | 11 +- include/storage/vertex.hpp | 3 +- include/storage/vertex_accessor.hpp | 2 +- src/storage/vertex_accessor.cpp | 26 ++++- tests/unit/record_edge_vertex_accessor.cpp | 126 ++++++++++++++++++++- 5 files changed, 154 insertions(+), 14 deletions(-) diff --git a/include/storage/record_accessor.hpp b/include/storage/record_accessor.hpp index e269c309c..42afc8f6f 100644 --- a/include/storage/record_accessor.hpp +++ b/include/storage/record_accessor.hpp @@ -76,20 +76,23 @@ public: */ size_t PropsErase(GraphDb::Property key); + /** + * Returns the properties of this record. + * @return + */ const TypedValueStore &Properties() const; void PropertiesAccept(std::function handler, std::function finish = {}) const; - // Assumes same transaction friend bool operator==(const RecordAccessor &a, const RecordAccessor &b) { - // TODO consider the legitimacy of this comparison + assert(&a.db_accessor_ == &b.db_accessor_); // assume the same db_accessor / transaction return &a.vlist_ == &b.vlist_; } friend bool operator!=(const RecordAccessor &a, const RecordAccessor &b) { - // TODO consider the legitimacy of this comparison - return a != b; + assert(&a.db_accessor_ == &b.db_accessor_); // assume the same db_accessor / transaction + return !(a == b); } /** diff --git a/include/storage/vertex.hpp b/include/storage/vertex.hpp index 353260f3c..504ba0205 100644 --- a/include/storage/vertex.hpp +++ b/include/storage/vertex.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include "database/graph_db.hpp" @@ -16,6 +15,6 @@ class Vertex : public mvcc::Record { public: std::vector*> out_; std::vector*> in_; - std::set labels_; + std::vector labels_; TypedValueStore properties_; }; diff --git a/include/storage/vertex_accessor.hpp b/include/storage/vertex_accessor.hpp index 0335b113b..c9c9b707a 100644 --- a/include/storage/vertex_accessor.hpp +++ b/include/storage/vertex_accessor.hpp @@ -61,7 +61,7 @@ public: * Returns all the Labels of the Vertex. * @return */ - const std::set& labels() const; + const std::vector& labels() const; /** * Returns EdgeAccessors for all incoming edges. diff --git a/src/storage/vertex_accessor.cpp b/src/storage/vertex_accessor.cpp index c6480fa52..8d129d386 100644 --- a/src/storage/vertex_accessor.cpp +++ b/src/storage/vertex_accessor.cpp @@ -1,3 +1,5 @@ +#include + #include "storage/edge_accessor.hpp" #include "storage/vertex_accessor.hpp" #include "storage/util.hpp" @@ -11,19 +13,33 @@ size_t VertexAccessor::in_degree() const { } bool VertexAccessor::add_label(GraphDb::Label label) { - return update().labels_.emplace(label).second; + auto &labels_view = view().labels_; + auto found = std::find(labels_view.begin(), labels_view.end(), label); + if (found!= labels_view.end()) + return false; + + // not a duplicate label, add it + update().labels_.emplace_back(label); + return true; } size_t VertexAccessor::remove_label(GraphDb::Label label) { - return update().labels_.erase(label); + auto &labels = update().labels_; + auto found = std::find(labels.begin(), labels.end(), label); + if (found == labels.end()) + return 0; + + std::swap(*found, labels.back()); + labels.pop_back(); + return 1; } bool VertexAccessor::has_label(GraphDb::Label label) const { - auto &label_set = this->view().labels_; - return label_set.find(label) != label_set.end(); + auto &labels = this->view().labels_; + return std::find(labels.begin(), labels.end(), label) != labels.end(); } -const std::set& VertexAccessor::labels() const { +const std::vector& VertexAccessor::labels() const { return this->view().labels_; } diff --git a/tests/unit/record_edge_vertex_accessor.cpp b/tests/unit/record_edge_vertex_accessor.cpp index cce389344..e660ee38f 100644 --- a/tests/unit/record_edge_vertex_accessor.cpp +++ b/tests/unit/record_edge_vertex_accessor.cpp @@ -1,3 +1,4 @@ +#include #include "gtest/gtest.h" @@ -10,15 +11,136 @@ #include "storage/edge_accessor.hpp" -TEST(RecordAccessor, PropertySet) { +TEST(RecordAccessor, Properties) { Dbms dbms; GraphDbAccessor dba = dbms.active(); auto vertex = dba.insert_vertex(); + auto &properties = vertex.Properties(); + auto property = dba.property("PropName"); + auto property_other = dba.property("Other"); + EXPECT_EQ(vertex.PropsAt(property).type_, TypedValue::Type::Null); vertex.PropsSet(property, 42); EXPECT_EQ(vertex.PropsAt(property).Value(), 42); - EXPECT_TRUE((vertex.PropsAt(dba.property("Other")) == TypedValue::Null).Value()); + EXPECT_EQ(properties.at(property).Value(), 42); + EXPECT_EQ(vertex.PropsAt(property_other).type_, TypedValue::Type::Null); + EXPECT_EQ(properties.at(property_other).type_, TypedValue::Type::Null); + + vertex.PropsErase(property); + EXPECT_EQ(vertex.PropsAt(property).type_, TypedValue::Type::Null); + EXPECT_EQ(properties.at(property).type_, TypedValue::Type::Null); +} + +TEST(RecordAccessor, DbAccessor) { + Dbms dbms; + GraphDbAccessor dba = dbms.active(); + + auto vertex = dba.insert_vertex(); + const auto& const_vertex_dba = vertex.db_accessor(); + EXPECT_EQ(&dba, &const_vertex_dba); + auto& vertex_dba = vertex.db_accessor(); + EXPECT_EQ(&dba, &vertex_dba); +} + +TEST(RecordAccessor, RecordEquality) { + + Dbms dbms; + GraphDbAccessor dba = dbms.active(); + + auto v1 = dba.insert_vertex(); + auto v2 = dba.insert_vertex(); + EXPECT_EQ(v1, v1); + EXPECT_NE(v1, v2); + + auto e1 = dba.insert_edge(v1, v2, dba.edge_type("type")); + auto e2 = dba.insert_edge(v1, v2, dba.edge_type("type")); + EXPECT_EQ(e1, e1); + EXPECT_NE(e1, e2); +} + +TEST(RecordAccessor, VertexLabels) { + + Dbms dbms; + GraphDbAccessor dba = dbms.active(); + auto v1 = dba.insert_vertex(); + auto &labels = v1.labels(); + + EXPECT_EQ(v1.labels().size(), 0); + + GraphDb::Label l1 = dba.label("label1"); + GraphDb::Label l2 = dba.label("label2"); + + // adding labels + EXPECT_FALSE(v1.has_label(l1)); + EXPECT_TRUE(v1.add_label(l1)); + EXPECT_TRUE(v1.has_label(l1)); + + EXPECT_EQ(v1.labels().size(), 1); + EXPECT_EQ(labels.size(), 1); + EXPECT_FALSE(v1.add_label(l1)); + EXPECT_EQ(v1.labels().size(), 1); + EXPECT_EQ(labels.size(), 1); + + EXPECT_FALSE(v1.has_label(l2)); + EXPECT_TRUE(v1.add_label(l2)); + EXPECT_TRUE(v1.has_label(l2)); + EXPECT_EQ(v1.labels().size(), 2); + EXPECT_EQ(labels.size(), 2); + + // removing labels + GraphDb::Label l3 = dba.label("label3"); + EXPECT_EQ(v1.remove_label(l3), 0); + EXPECT_EQ(labels.size(), 2); + + EXPECT_EQ(v1.remove_label(l1), 1); + EXPECT_FALSE(v1.has_label(l1)); + EXPECT_EQ(v1.labels().size(), 1); + + EXPECT_EQ(v1.remove_label(l1), 0); + EXPECT_TRUE(v1.has_label(l2)); +} + +TEST(RecordAccessor, EdgeType) { + Dbms dbms; + GraphDbAccessor dba = dbms.active(); + auto v1 = dba.insert_vertex(); + auto v2 = dba.insert_vertex(); + + GraphDb::EdgeType likes = dba.edge_type("likes"); + GraphDb::EdgeType hates = dba.edge_type("hates"); + + auto edge = dba.insert_edge(v1, v2, likes); + EXPECT_EQ(edge.edge_type(), likes); + EXPECT_NE(edge.edge_type(), hates); + + edge.set_edge_type(hates); + EXPECT_EQ(edge.edge_type(), hates); + EXPECT_NE(edge.edge_type(), likes); +} + +TEST(RecordAccessor, VertexEdgeConnections) { + Dbms dbms; + GraphDbAccessor dba = dbms.active(); + auto v1 = dba.insert_vertex(); + auto v2 = dba.insert_vertex(); + auto edge = dba.insert_edge(v1, v2, dba.edge_type("likes")); + + EXPECT_EQ(edge.from(), v1); + EXPECT_NE(edge.from(), v2); + EXPECT_EQ(edge.to(), v2); + EXPECT_NE(edge.to(), v1); + + EXPECT_EQ(v1.in().size(), 0); + EXPECT_EQ(v1.out().size(), 1); + EXPECT_EQ(v2.in().size(), 1); + EXPECT_EQ(v2.out().size(), 0); + + for (auto e : v1.out()) + EXPECT_EQ(edge, e); + + for (auto e : v2.in()) + EXPECT_EQ(edge, e); }