diff --git a/include/storage/indexes/indexes.hpp b/include/storage/indexes/indexes.hpp index a385223fb..153d306b0 100644 --- a/include/storage/indexes/indexes.hpp +++ b/include/storage/indexes/indexes.hpp @@ -20,6 +20,61 @@ public: // Adds index defined in given definition. Returns true if successfull. bool add_index(IndexDefinition id); + // + // // Returns index from location. + // template + // Option> get_index(IndexLocation loc) + // { + // size_t code = loc.location_code(); + // + // switch (code) { + // case 0: // Illegal location + // return Option>(); + // + // case 1: + // switch (loc.side) { + // case EdgeSide: { + // return make_option( + // db.graph.edges + // .property_family_find_or_create(loc.property_name.get()) + // .index); + // } + // case VertexSide: { + // return make_option( + // db.graph.vertices + // .property_family_find_or_create(loc.property_name.get()) + // .index); + // } + // default: + // throw new NonExhaustiveSwitch("Unkown side: " + + // std::to_string(loc.side)); + // }; + // + // case 2: // Can't be removed + // return Option>(); + // + // case 3: // Not yet implemented + // throw new NotYetImplemented("Getting index over label and " + // "property isn't yet implemented"); + // case 4: // Can't be removed + // return Option>(); + // + // case 5: // Not yet implemented + // throw new NotYetImplemented("Getting index over edge_type and " + // "property isn't yet implemented"); + // case 6: // Not yet implemented + // throw new NotYetImplemented("Getting index over edge_type and " + // "label isn't yet implemented"); + // case 7: // Not yet implemented + // throw new NotYetImplemented("Getting index over label, edge_type + // " + // "and property isn't yet + // implemented"); + // default: + // throw new NonExhaustiveSwitch("Unkown index location code: " + + // std::to_string(code)); + // } + // } // Removes index from given location. Returns true if successfull or if no // index was present. False if index location is illegal. @@ -98,7 +153,7 @@ public: f); } - // Updates property indexes for given TypeGroup TG and IU index update + // Updates property indexes for given TypeGroup TG and IU index_update template bool update_property_indexes(IU &iu, const tx::Transaction &t) { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 16d377a87..5e8a88c40 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -89,6 +89,15 @@ target_link_libraries(snapshot ${yaml_static_lib}) add_test(NAME snapshot COMMAND snapshot) set_property(TARGET snapshot PROPERTY CXX_STANDARD 14) +# test index validity +add_executable(index integration/index.cpp) +target_link_libraries(index memgraph) +target_link_libraries(index Threads::Threads) +target_link_libraries(index ${fmt_static_lib}) +target_link_libraries(index ${yaml_static_lib}) +add_test(NAME index COMMAND index) +set_property(TARGET index PROPERTY CXX_STANDARD 14) + # test query engine add_executable(integration_query_engine integration/query_engine.cpp) target_link_libraries(integration_query_engine Threads::Threads) diff --git a/tests/integration/index.cpp b/tests/integration/index.cpp new file mode 100644 index 000000000..1f9790f02 --- /dev/null +++ b/tests/integration/index.cpp @@ -0,0 +1,240 @@ +#include "query_engine/hardcode/queries.hpp" + +#include + +#include "barrier/barrier.cpp" + +#include "logging/default.hpp" +#include "logging/streams/stdout.hpp" +#include "query_engine/query_stripper.hpp" +#include "storage/indexes/indexes.hpp" +#include "utils/sysinfo/memory.hpp" + +// Returns uniform random size_t generator from range [0,n> +auto rand_gen(size_t n) +{ + std::default_random_engine generator; + std::uniform_int_distribution distribution(0, n - 1); + return std::bind(distribution, generator); +} + +void run(size_t n, std::string &query, Db &db) +{ + auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL); + auto qf = load_queries(barrier::trans(db)); + auto stripped = stripper.strip(query); + std::cout << "Running query [" << stripped.hash << "] for " << n << " time." + << std::endl; + for (int i = 0; i < n; i++) { + properties_t vec = stripped.arguments; + assert(qf[stripped.hash](std::move(vec))); + } +} + +void add_edge(size_t n, Db &db) +{ + auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL); + auto qf = load_queries(barrier::trans(db)); + std::string query = "MATCH (n1), (n2) WHERE ID(n1)=0 AND " + "ID(n2)=1 CREATE (n1)<-[r:IS {age: " + "25,weight: 70}]-(n2) RETURN r"; + + auto stripped = stripper.strip(query); + std::cout << "Running query [" << stripped.hash << "] for " << n + << " time to add edge." << std::endl; + + std::vector vertices; + for (auto &v : db.graph.vertices.access()) { + vertices.push_back(v.second.id); + } + + auto rand = rand_gen(vertices.size()); + for (int i = 0; i < n; i++) { + properties_t vec = stripped.arguments; + vec[0] = Property(Int64(vertices[rand()]), Flags::Int64); + vec[1] = Property(Int64(vertices[rand()]), Flags::Int64); + assert(qf[stripped.hash](std::move(vec))); + } +} + +void add_property(Db &db, StoredProperty &prop) +{ + DbAccessor t(db); + + t.vertex_access().fill().for_all([&](auto va) { va.set(prop); }); + + assert(t.commit()); +} + +void add_vertex_property_serial_int(Db &db, PropertyFamily &f) +{ + DbAccessor t(db); + + auto key = f.get(Int64::type).family_key(); + + size_t i = 0; + t.vertex_access().fill().for_all([&](auto va) mutable { + va.set(StoredProperty(Int64(i), key)); + i++; + }); + + assert(t.commit()); +} + +void add_edge_property_serial_int(Db &db, PropertyFamily &f) +{ + DbAccessor t(db); + + auto key = f.get(Int64::type).family_key(); + + size_t i = 0; + t.edge_access().fill().for_all([&](auto va) mutable { + va.set(StoredProperty(Int64(i), key)); + i++; + }); + + assert(t.commit()); +} + +template +size_t size(Db &db, IndexHolder &h) +{ + DbAccessor t(db); + + size_t count = 0; + auto oin = h.get_read(); + if (oin.is_present()) { + oin.get()->for_range(t).for_all([&](auto va) mutable { count++; }); + } + + t.commit(); + + return count; +} + +void assert_empty(Db &db) +{ + assert(db.graph.vertices.access().size() == 0); + assert(db.graph.edges.access().size() == 0); +} + +void clean_vertex(Db &db) +{ + DbTransaction t(db); + t.clean_vertex_section(); + t.trans.commit(); +} + +void clean_edge(Db &db) +{ + DbTransaction t(db); + t.clean_edge_section(); + t.trans.commit(); +} + +void clear_database(Db &db) +{ + std::string delete_all_vertices = "MATCH (n) DELETE n"; + std::string delete_all_edges = "MATCH ()-[r]-() DELETE r"; + + run(1, delete_all_edges, db); + run(1, delete_all_vertices, db); + clean_vertex(db); + clean_edge(db); + assert_empty(db); +} + +bool equal(Db &a, Db &b) +{ + { + auto acc_a = a.graph.vertices.access(); + auto acc_b = b.graph.vertices.access(); + + if (acc_a.size() != acc_b.size()) { + return false; + } + + auto it_a = acc_a.begin(); + auto it_b = acc_b.begin(); + + for (auto i = acc_a.size(); i > 0; i--) { + // TODO: compare + } + } + + { + auto acc_a = a.graph.edges.access(); + auto acc_b = b.graph.edges.access(); + + if (acc_a.size() != acc_b.size()) { + return false; + } + + auto it_a = acc_a.begin(); + auto it_b = acc_b.begin(); + + for (auto i = acc_a.size(); i > 0; i--) { + // TODO: compare + } + } + + return true; +} + +int main(void) +{ + logging::init_async(); + logging::log->pipe(std::make_unique()); + + size_t cvl_n = 1000; + + 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"; + + IndexDefinition vertex_property_nonunique_unordered = { + IndexLocation{VertexSide, Option("prop"), + Option(), Option()}, + IndexType{false, None}}; + IndexDefinition edge_property_nonunique_unordered = { + IndexLocation{EdgeSide, Option("prop"), + Option(), Option()}, + IndexType{false, None}}; + IndexDefinition edge_property_unique_ordered = { + IndexLocation{EdgeSide, Option("prop"), + Option(), Option()}, + IndexType{true, Ascending}}; + IndexDefinition vertex_property_unique_ordered = { + IndexLocation{VertexSide, Option("prop"), + Option(), Option()}, + IndexType{true, Ascending}}; + + // ******************************* TEST 1 ********************************// + { + std::cout << "TEST1" << std::endl; + // add indexes + // add vertices LABEL + // add edges + // add vertices property + // assert index size. + Db db("index", false); + assert(db.indexes().add_index(vertex_property_nonunique_unordered)); + assert(db.indexes().add_index(edge_property_nonunique_unordered)); + run(cvl_n, create_vertex_label, db); + add_edge(cvl_n, db); + assert(cvl_n == + size(db, db.graph.vertices.property_family_find_or_create("prop") + .index)); + assert( + cvl_n == + size(db, + db.graph.edges.property_family_find_or_create("prop").index)); + } + + // TODO: more tests + + return 0; +}