2017-04-03 17:26:32 +08:00
|
|
|
#include "gmock/gmock.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
|
|
|
|
#include "data_structures/ptr_int.hpp"
|
2017-04-21 21:39:41 +08:00
|
|
|
#include "database/graph_db_accessor.hpp"
|
LabelProperty index.
Summary:
Add return values.
After merge.
Inital working version. Still missing comments.
Update documentation.
Add checking for previous vlist and value equality.
After merge.
Remove functor, add boolean ffunction.
Build index.
More functionality. Start implementing tests.
Add tests.
Reviewers: matej.gradicek, mislav.bradac, mferencevic, buda, florijan
Reviewed By: mislav.bradac, buda, florijan
Subscribers: lion, florijan, teon.banek, buda, pullbot
Differential Revision: https://phabricator.memgraph.io/D355
2017-05-16 20:47:03 +08:00
|
|
|
#include "database/graph_db_datatypes.hpp"
|
2017-04-03 17:26:32 +08:00
|
|
|
#include "dbms/dbms.hpp"
|
2017-04-14 23:32:59 +08:00
|
|
|
#include "storage/vertex.hpp"
|
2017-04-03 17:26:32 +08:00
|
|
|
|
|
|
|
using testing::UnorderedElementsAreArray;
|
|
|
|
|
2017-04-14 23:32:59 +08:00
|
|
|
// Test index does it insert everything uniquely
|
|
|
|
TEST(LabelsIndex, UniqueInsert) {
|
|
|
|
KeyIndex<GraphDbTypes::Label, Vertex> index;
|
|
|
|
Dbms dbms;
|
2017-04-21 21:39:41 +08:00
|
|
|
auto dba = dbms.active();
|
2017-04-14 23:32:59 +08:00
|
|
|
tx::Engine engine;
|
|
|
|
auto t1 = engine.begin();
|
|
|
|
mvcc::VersionList<Vertex> vlist(*t1);
|
|
|
|
t1->commit();
|
|
|
|
auto t2 = engine.begin();
|
|
|
|
|
2017-04-21 21:39:41 +08:00
|
|
|
vlist.find(*t2)->labels_.push_back(dba->label("1"));
|
|
|
|
index.Update(dba->label("1"), &vlist, vlist.find(*t2));
|
2017-04-14 23:32:59 +08:00
|
|
|
// Try multiple inserts
|
2017-04-21 21:39:41 +08:00
|
|
|
index.Update(dba->label("1"), &vlist, vlist.find(*t2));
|
2017-04-14 23:32:59 +08:00
|
|
|
|
2017-04-21 21:39:41 +08:00
|
|
|
vlist.find(*t2)->labels_.push_back(dba->label("2"));
|
|
|
|
index.Update(dba->label("2"), &vlist, vlist.find(*t2));
|
2017-04-14 23:32:59 +08:00
|
|
|
|
2017-04-21 21:39:41 +08:00
|
|
|
vlist.find(*t2)->labels_.push_back(dba->label("3"));
|
|
|
|
index.Update(dba->label("3"), &vlist, vlist.find(*t2));
|
2017-04-14 23:32:59 +08:00
|
|
|
t2->commit();
|
|
|
|
|
2017-04-21 21:39:41 +08:00
|
|
|
EXPECT_EQ(index.Count(dba->label("1")), 1);
|
|
|
|
EXPECT_EQ(index.Count(dba->label("2")), 1);
|
|
|
|
EXPECT_EQ(index.Count(dba->label("3")), 1);
|
2017-04-14 23:32:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check if index filters duplicates.
|
|
|
|
TEST(LabelsIndex, UniqueFilter) {
|
|
|
|
Dbms dbms;
|
2017-06-07 15:49:51 +08:00
|
|
|
KeyIndex<GraphDbTypes::Label, Vertex> index;
|
2017-04-21 21:39:41 +08:00
|
|
|
auto dba = dbms.active();
|
2017-04-14 23:32:59 +08:00
|
|
|
tx::Engine engine;
|
|
|
|
|
|
|
|
auto t1 = engine.begin();
|
|
|
|
mvcc::VersionList<Vertex> vlist1(*t1);
|
|
|
|
mvcc::VersionList<Vertex> vlist2(*t1);
|
|
|
|
t1->engine.advance(
|
|
|
|
t1->id); // advance command so we can see our inserted version
|
|
|
|
auto r1v1 = vlist1.find(*t1);
|
2017-04-21 21:39:41 +08:00
|
|
|
auto r1v2 = vlist2.find(*t1);
|
2017-04-14 23:32:59 +08:00
|
|
|
EXPECT_NE(vlist1.find(*t1), nullptr);
|
|
|
|
|
2017-04-21 21:39:41 +08:00
|
|
|
auto label1 = dba->label("1");
|
2017-04-14 23:32:59 +08:00
|
|
|
vlist1.find(*t1)->labels_.push_back(label1);
|
|
|
|
vlist2.find(*t1)->labels_.push_back(label1);
|
|
|
|
index.Update(label1, &vlist1, r1v1);
|
|
|
|
index.Update(label1, &vlist2, r1v2);
|
|
|
|
t1->commit();
|
|
|
|
|
|
|
|
auto t2 = engine.begin();
|
|
|
|
auto r2v1 = vlist1.update(*t2);
|
|
|
|
auto r2v2 = vlist2.update(*t2);
|
|
|
|
index.Update(label1, &vlist1, r2v1);
|
|
|
|
index.Update(label1, &vlist2, r2v2);
|
|
|
|
t2->commit();
|
|
|
|
|
|
|
|
auto t3 = engine.begin();
|
|
|
|
std::vector<mvcc::VersionList<Vertex> *> expected = {&vlist1, &vlist2};
|
|
|
|
sort(expected.begin(),
|
|
|
|
expected.end()); // Entries will be sorted by vlist pointers.
|
|
|
|
int cnt = 0;
|
2017-06-07 15:49:51 +08:00
|
|
|
for (auto vlist : index.GetVlists(label1, *t3, false)) {
|
2017-04-14 23:32:59 +08:00
|
|
|
EXPECT_LT(cnt, expected.size());
|
|
|
|
EXPECT_EQ(vlist, expected[cnt++]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete not anymore relevant recods from index.
|
|
|
|
TEST(LabelsIndex, Refresh) {
|
|
|
|
KeyIndex<GraphDbTypes::Label, Vertex> index;
|
|
|
|
Dbms dbms;
|
|
|
|
auto access = dbms.active();
|
|
|
|
tx::Engine engine;
|
|
|
|
|
|
|
|
auto t1 = engine.begin();
|
|
|
|
mvcc::VersionList<Vertex> vlist1(*t1);
|
|
|
|
mvcc::VersionList<Vertex> vlist2(*t1);
|
|
|
|
t1->engine.advance(
|
|
|
|
t1->id); // advance command so we can see our inserted version
|
|
|
|
auto r1v1 = vlist1.find(*t1);
|
|
|
|
auto r1v2 = vlist2.find(*t1);
|
|
|
|
EXPECT_NE(vlist1.find(*t1), nullptr);
|
|
|
|
|
|
|
|
auto label1 = access->label("1");
|
|
|
|
vlist1.find(*t1)->labels_.push_back(label1);
|
|
|
|
vlist2.find(*t1)->labels_.push_back(label1);
|
|
|
|
index.Update(label1, &vlist1, r1v1);
|
|
|
|
index.Update(label1, &vlist2, r1v2);
|
|
|
|
t1->commit();
|
|
|
|
|
|
|
|
auto t2 = engine.begin();
|
|
|
|
auto r2v1 = vlist1.update(*t2);
|
|
|
|
auto r2v2 = vlist2.update(*t2);
|
|
|
|
index.Update(label1, &vlist1, r2v1);
|
|
|
|
index.Update(label1, &vlist2, r2v2);
|
|
|
|
int last_id = t2->id;
|
|
|
|
t2->commit();
|
|
|
|
EXPECT_EQ(index.Count(label1), 4);
|
|
|
|
|
|
|
|
index.Refresh(last_id, engine);
|
|
|
|
EXPECT_EQ(index.Count(label1), 4);
|
|
|
|
|
|
|
|
index.Refresh(last_id + 1, engine);
|
|
|
|
EXPECT_EQ(index.Count(label1), 2);
|
|
|
|
}
|
|
|
|
|
2017-04-03 17:26:32 +08:00
|
|
|
// Transaction hasn't ended and so the vertex is not visible.
|
2017-04-14 23:32:59 +08:00
|
|
|
TEST(LabelsIndexDb, AddGetZeroLabels) {
|
2017-04-03 17:26:32 +08:00
|
|
|
Dbms dbms;
|
2017-04-21 21:39:41 +08:00
|
|
|
auto dba = dbms.active();
|
|
|
|
auto vertex = dba->insert_vertex();
|
|
|
|
vertex.add_label(dba->label("test"));
|
2017-06-07 15:49:51 +08:00
|
|
|
auto collection = dba->vertices(dba->label("test"), false);
|
2017-04-05 23:23:00 +08:00
|
|
|
std::vector<VertexAccessor> collection_vector(collection.begin(),
|
|
|
|
collection.end());
|
2017-04-03 17:26:32 +08:00
|
|
|
EXPECT_EQ(collection_vector.size(), (size_t)0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test label index by adding and removing one vertex, and removing label from
|
|
|
|
// another, while the third one with an irrelevant label exists.
|
2017-04-14 23:32:59 +08:00
|
|
|
TEST(LabelsIndexDb, AddGetRemoveLabel) {
|
2017-04-03 17:26:32 +08:00
|
|
|
Dbms dbms;
|
|
|
|
{
|
2017-04-21 21:39:41 +08:00
|
|
|
auto dba = dbms.active();
|
2017-04-03 17:26:32 +08:00
|
|
|
|
2017-04-21 21:39:41 +08:00
|
|
|
auto vertex1 = dba->insert_vertex();
|
|
|
|
vertex1.add_label(dba->label("test"));
|
2017-04-03 17:26:32 +08:00
|
|
|
|
2017-04-21 21:39:41 +08:00
|
|
|
auto vertex2 = dba->insert_vertex();
|
|
|
|
vertex2.add_label(dba->label("test2"));
|
2017-04-03 17:26:32 +08:00
|
|
|
|
2017-04-21 21:39:41 +08:00
|
|
|
auto vertex3 = dba->insert_vertex();
|
|
|
|
vertex3.add_label(dba->label("test"));
|
2017-04-03 17:26:32 +08:00
|
|
|
|
2017-04-21 21:39:41 +08:00
|
|
|
dba->commit();
|
2017-04-03 17:26:32 +08:00
|
|
|
} // Finish transaction.
|
|
|
|
{
|
2017-04-21 21:39:41 +08:00
|
|
|
auto dba = dbms.active();
|
2017-04-03 17:26:32 +08:00
|
|
|
|
2017-06-07 15:49:51 +08:00
|
|
|
auto filtered = dba->vertices(dba->label("test"), false);
|
2017-04-03 17:26:32 +08:00
|
|
|
std::vector<VertexAccessor> collection(filtered.begin(), filtered.end());
|
2017-06-07 15:49:51 +08:00
|
|
|
auto vertices = dba->vertices(false);
|
2017-04-03 17:26:32 +08:00
|
|
|
|
|
|
|
std::vector<VertexAccessor> expected_collection;
|
|
|
|
for (auto vertex : vertices) {
|
2017-04-21 21:39:41 +08:00
|
|
|
if (vertex.has_label(dba->label("test"))) {
|
2017-04-03 17:26:32 +08:00
|
|
|
expected_collection.push_back(vertex);
|
|
|
|
} else {
|
2017-04-21 21:39:41 +08:00
|
|
|
EXPECT_TRUE(vertex.has_label(dba->label("test2")));
|
2017-04-03 17:26:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EXPECT_EQ(expected_collection.size(), collection.size());
|
2017-04-21 21:39:41 +08:00
|
|
|
EXPECT_TRUE(collection[0].has_label(dba->label("test")));
|
|
|
|
EXPECT_TRUE(collection[1].has_label(dba->label("test")));
|
|
|
|
EXPECT_FALSE(collection[0].has_label(dba->label("test2")));
|
|
|
|
EXPECT_FALSE(collection[1].has_label(dba->label("test2")));
|
|
|
|
dba->remove_vertex(collection[0]); // Remove from database and test if
|
|
|
|
// index won't return it.
|
2017-04-03 17:26:32 +08:00
|
|
|
|
|
|
|
// Remove label from the vertex and add new label.
|
2017-04-21 21:39:41 +08:00
|
|
|
collection[1].remove_label(dba->label("test"));
|
|
|
|
collection[1].add_label(dba->label("test2"));
|
|
|
|
dba->commit();
|
2017-04-03 17:26:32 +08:00
|
|
|
}
|
|
|
|
{
|
2017-04-21 21:39:41 +08:00
|
|
|
auto dba = dbms.active();
|
2017-04-03 17:26:32 +08:00
|
|
|
|
2017-06-07 15:49:51 +08:00
|
|
|
auto filtered = dba->vertices(dba->label("test"), false);
|
2017-04-03 17:26:32 +08:00
|
|
|
std::vector<VertexAccessor> collection(filtered.begin(), filtered.end());
|
2017-06-07 15:49:51 +08:00
|
|
|
auto vertices = dba->vertices(false);
|
2017-04-03 17:26:32 +08:00
|
|
|
|
|
|
|
std::vector<VertexAccessor> expected_collection;
|
|
|
|
for (auto vertex : vertices) {
|
2017-04-21 21:39:41 +08:00
|
|
|
if (vertex.has_label(dba->label("test"))) {
|
2017-04-03 17:26:32 +08:00
|
|
|
expected_collection.push_back(vertex);
|
|
|
|
} else {
|
2017-04-21 21:39:41 +08:00
|
|
|
EXPECT_TRUE(vertex.has_label(dba->label("test2")));
|
2017-04-03 17:26:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// It should be empty since everything with an old label is either deleted
|
|
|
|
// or doesn't have that label anymore.
|
|
|
|
EXPECT_EQ(expected_collection.size(), 0);
|
|
|
|
EXPECT_EQ(collection.size(), 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-21 21:39:41 +08:00
|
|
|
// TODO gleich - discuss with Flor the API changes and the tests
|
|
|
|
|
2017-04-03 17:26:32 +08:00
|
|
|
int main(int argc, char **argv) {
|
|
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
|
|
return RUN_ALL_TESTS();
|
|
|
|
}
|