iterators, properties, search by properties in index hardcoded query; TODO: implement in compiler

This commit is contained in:
Marko Budiselic 2016-10-19 02:41:06 +02:00
parent 8ff79c3ace
commit c312c2e369
21 changed files with 174 additions and 107 deletions

View File

@ -41,9 +41,12 @@ auto return_query_action =
// the client will receive entities from label index
if (cypher_data.source(entity) == EntitySource::LabelIndex)
{
if (cypher_data.tags(entity).size() == 0)
throw CppGeneratorException("node has no labels");
// node and no other property
if (cypher_data.type(entity) == EntityType::Node) {
if (cypher_data.tags(entity).size() == 0)
throw CppGeneratorException("node has no labels");
// TODO: solve the case with more labels
auto label = cypher_data.tags(entity).at(0);
code += code_line(code::find_and_write_vertices_by_label,
entity, label);

View File

@ -18,25 +18,25 @@ namespace barrier
#include <type_traits>
#include <utility>
#include <vector>
#include "communication/bolt/v1/serialization/bolt_serializer.hpp"
#include "communication/bolt/v1/serialization/record_stream.hpp"
#include "database/db.hpp"
#include "database/db.hpp"
#include "database/db_accessor.hpp"
#include "database/db_accessor.hpp"
#include "io/network/socket.hpp"
#include "mvcc/id.hpp"
#include "storage/edge_type/edge_type.hpp"
#include "storage/edge_x_vertex.hpp"
#include "storage/indexes/index_definition.hpp"
#include "storage/label/label.hpp"
#include "storage/model/properties/all.hpp"
#include "storage/model/properties/property.hpp"
#include "utils/border.hpp"
#include "utils/iterator/iterator.hpp"
#include "utils/iterator/iterator.hpp"
#include "utils/option_ptr.hpp"
#include "utils/reference_wrapper.hpp"
#include "database/db.hpp"
#include "database/db_accessor.hpp"
#include "utils/iterator/iterator.hpp"
#include "communication/bolt/v1/serialization/bolt_serializer.hpp"
#include "communication/bolt/v1/serialization/record_stream.hpp"
#include "database/db.hpp"
#include "database/db_accessor.hpp"
#include "io/network/socket.hpp"
#include "storage/edge_type/edge_type.hpp"
#include "storage/edge_x_vertex.hpp"
#include "storage/label/label.hpp"
#endif
@ -44,38 +44,35 @@ auto load_queries(Db &db)
{
std::map<uint64_t, std::function<bool(properties_t &&)>> queries;
// CREATE (n {prop: 0}) RETURN n)
// CREATE (n {prop: 0}) RETURN n
auto create_node = [&db](properties_t &&args) {
DbAccessor t(db);
auto property_key = t.vertex_property_key("prop", args[0].key.flags());
auto vertex_accessor = t.vertex_insert();
vertex_accessor.set(property_key, std::move(args[0]));
return t.commit();
};
queries[11597417457737499503u] = create_node;
// CREATE (n:LABEL {name: "TEST"}) RETURN n;
auto create_labeled_and_named_node = [&db](properties_t &&args) {
DbAccessor t(db);
auto property_key = t.vertex_property_key("name", args[0].key.flags());
auto &label = t.label_find_or_create("LABEL");
auto vertex_accessor = t.vertex_insert();
vertex_accessor.set(property_key, std::move(args[0]));
vertex_accessor.add_label(label);
// cout_properties(vertex_accessor.properties());
return t.commit();
};
// CREATE (n:OTHER {name: "TEST"}) RETURN n;
auto create_labeled_and_named_node_v2 = [&db](properties_t &&args) {
DbAccessor t(db);
auto property_key = t.vertex_property_key("name", args[0].key.flags());
auto &label = t.label_find_or_create("OTHER");
auto vertex_accessor = t.vertex_insert();
vertex_accessor.set(property_key, std::move(args[0]));
vertex_accessor.add_label(label);
// cout_properties(vertex_accessor.properties());
return t.commit();
};
@ -88,14 +85,12 @@ auto load_queries(Db &db)
auto prop_created =
t.vertex_property_key("created_at", args[3].key.flags());
auto &label = t.label_find_or_create("ACCOUNT");
auto vertex_accessor = t.vertex_insert();
vertex_accessor.set(prop_id, std::move(args[0]));
vertex_accessor.set(prop_name, std::move(args[1]));
vertex_accessor.set(prop_country, std::move(args[2]));
vertex_accessor.set(prop_created, std::move(args[3]));
vertex_accessor.add_label(label);
// cout_properties(vertex_accessor.properties());
return t.commit();
};
@ -226,6 +221,11 @@ auto load_queries(Db &db)
auto match_all_delete = [&db](properties_t &&args) {
DbAccessor t(db);
// DETACH DELETE
// t.edge_access().fill().for_all(
// [&](auto e) { e.remove(); }
// );
t.vertex_access().fill().isolated().for_all(
[&](auto a) { a.remove(); });
@ -470,6 +470,45 @@ auto load_queries(Db &db)
};
// MATCH (n:LABEL {name: "TEST01"}) RETURN n;
auto match_label_property = [&db](properties_t &&args) {
std::map<std::string, int64_t> properties{{"name", 0}};
DbAccessor t(db);
try {
auto &label = t.label_find_or_create("LABEL");
label.index().for_range(t).for_all(
[&](auto vertex_accessor) -> void {
// TODO: record_accessor.match_execute(properties, op);
bool match = true;
for (auto &property_index : properties) {
auto property_key = t.vertex_property_key(
property_index.first,
args[property_index.second].key.flags());
if (!vertex_accessor.contains(property_key)) {
match = false;
break;
}
auto vertex_property_value =
vertex_accessor.at(property_key);
auto query_property_value = args[property_index.second];
if (!(vertex_property_value == query_property_value)) {
match = false;
break;
}
}
if (match) {
std::cout << "MATCH" << std::endl;
}
}
);
return t.commit();
} catch (...) {
t.abort();
return false;
}
};
queries[17721584194272598838u] = match_label_property;
// Blueprint:
// auto = [&db](properties_t &&args) {
// DbAccessor t(db);

View File

@ -15,7 +15,7 @@ template <class TG, class T>
using type_key_t =
typename PropertyFamily<TG>::PropertyType::template PropertyTypeKey<T>;
// Collcetion of stored properties.
// Collection of stored properties.
// NOTE: Currently underlying strucutre is a vector which is fine for smaller
// number of properties.
template <class TG>
@ -37,6 +37,8 @@ public:
size_t size() const { return props.size(); }
const bool contains(property_key &key) const;
const StoredProperty<TG> &at(PropertyFamily<TG> &key) const;
const StoredProperty<TG> &at(property_key &key) const;

View File

@ -70,7 +70,7 @@
// Generates signatures define_generator(type_name, union_name );
// for every pair type,property
#define GENERATE_FOR_ALL_PROPERTYS(define_generator) \
#define GENERATE_FOR_ALL_PROPERTIES(define_generator) \
define_generator(Null, null_v); \
define_generator(Bool, bool_v); \
define_generator(Int32, int32_v); \
@ -97,12 +97,12 @@ class PropertyHolder
public:
PropertyHolder() = delete;
GENERATE_FOR_ALL_PROPERTYS(GENERATE_CONSTRUCTOR_FOR_DATA);
GENERATE_FOR_ALL_PROPERTIES(GENERATE_CONSTRUCTOR_FOR_DATA);
PropertyHolder(PropertyHolder const &other) : key(other.key)
{
switch (other.key.get_type().flags()) {
GENERATE_FOR_ALL_PROPERTYS(
GENERATE_FOR_ALL_PROPERTIES(
GENERATE_CASE_CLAUSE_FOR_CONSTRUCTOR_COPY);
default:
assert(false);
@ -113,7 +113,7 @@ public:
PropertyHolder(PropertyHolder &&other) : key(other.key)
{
switch (other.key.get_type().flags()) {
GENERATE_FOR_ALL_PROPERTYS(
GENERATE_FOR_ALL_PROPERTIES(
GENERATE_CASE_CLAUSE_FOR_CONSTRUCTOR_MOVE);
default:
assert(false);
@ -125,7 +125,7 @@ public:
{
assert(other.key.get_type() == key.get_type());
switch (key.get_type().flags()) {
GENERATE_FOR_ALL_PROPERTYS(
GENERATE_FOR_ALL_PROPERTIES(
GENERATE_CASE_CLAUSE_FOR_CONSTRUCTOR_MOVE);
default:
assert(false);
@ -136,7 +136,7 @@ public:
~PropertyHolder()
{
switch (key.get_type().flags()) {
GENERATE_FOR_ALL_PROPERTYS(GENERATE_CASE_CLAUSE_FOR_DESTRUCTOR);
GENERATE_FOR_ALL_PROPERTIES(GENERATE_CASE_CLAUSE_FOR_DESTRUCTOR);
default:
assert(false);
}
@ -164,7 +164,7 @@ public:
void accept(Handler &h) const
{
switch (key.get_type().flags()) {
GENERATE_FOR_ALL_PROPERTYS(GENERATE_CASE_CLAUSE_FOR_HANDLER);
GENERATE_FOR_ALL_PROPERTIES(GENERATE_CASE_CLAUSE_FOR_HANDLER);
default:
assert(false);
}
@ -175,7 +175,7 @@ public:
void accept_primitive(Handler &h) const
{
switch (key.get_type().flags()) {
GENERATE_FOR_ALL_PROPERTYS(
GENERATE_FOR_ALL_PROPERTIES(
GENERATE_CASE_CLAUSE_FOR_HANDLER_PRIMITIVE);
default:
assert(false);
@ -185,7 +185,7 @@ public:
std::ostream &print(std::ostream &stream) const
{
switch (key.get_type().flags()) {
GENERATE_FOR_ALL_PROPERTYS(GENERATE_CASE_CLAUSE_FOR_PRINT);
GENERATE_FOR_ALL_PROPERTIES(GENERATE_CASE_CLAUSE_FOR_PRINT);
default:
assert(false);
}
@ -201,9 +201,10 @@ public:
{
if (key == other.key) {
switch (key.get_type().flags()) {
GENERATE_FOR_ALL_PROPERTYS(GENERATE_CASE_CLAUSE_FOR_COMPARISON);
GENERATE_FOR_ALL_PROPERTIES(GENERATE_CASE_CLAUSE_FOR_COMPARISON);
default:
assert(false);
return false;
}
} else {
return false;
@ -215,9 +216,10 @@ public:
{
if (key.get_type() == other.key.get_type()) {
switch (key.get_type().flags()) {
GENERATE_FOR_ALL_PROPERTYS(GENERATE_CASE_CLAUSE_FOR_COMPARISON);
GENERATE_FOR_ALL_PROPERTIES(GENERATE_CASE_CLAUSE_FOR_COMPARISON);
default:
assert(false);
return false;
}
} else {
return false;
@ -273,7 +275,7 @@ private:
// Stored data.
union
{
GENERATE_FOR_ALL_PROPERTYS(GENERATE_UNION_FIELD);
GENERATE_FOR_ALL_PROPERTIES(GENERATE_UNION_FIELD);
};
};
@ -285,4 +287,4 @@ private:
#undef GENERATE_CASE_CLAUSE_FOR_PRINT
#undef GENERATE_CASE_CLAUSE_FOR_COMPARISON
#undef GENERATE_UNION_FIELD
#undef GENERATE_FOR_ALL_PROPERTYS
#undef GENERATE_FOR_ALL_PROPERTIES

View File

@ -18,8 +18,7 @@ class StoredProperty : public PropertyHolder<property_key<TG>>
public:
// NOTE: Needed for properties to return reference on stored property when
// they
// don't cointain searched property.
// they don't cointain searched property.
const static class StoredProperty<TG> null;
using PropertyHolder<property_key<TG>>::PropertyHolder;

View File

@ -88,6 +88,11 @@ public:
}
}
bool contains(property_key<TG> &key) const
{
return properties().contains(key);
}
const StoredProperty<TG> &at(PropertyFamily<TG> &key) const
{
return properties().at(key);

View File

@ -14,35 +14,41 @@ class VertexAccessor : public RecordAccessor<TypeGroupVertex, VertexAccessor>
public:
using RecordAccessor::RecordAccessor;
typedef Vertex record_t;
typedef VertexRecord record_list_t;
using record_t = Vertex;
using record_list_t = VertexRecord;
// Removes self and all edges connected to it.
void remove() const;
// Returns number of out edges.
size_t out_degree() const;
// Returns number of in edges.
size_t in_degree() const;
// Returns number of all edges.
size_t degree() const;
// True if vertex isn't connected to any other vertex.
bool isolated() const;
// False if it already has labe.
// False if it already has the label.
bool add_label(const Label &label);
// False if it doesn't have label.
// False if it doesn't have the label.
bool remove_label(const Label &label);
// Checks if it has the label.
bool has_label(const Label &label) const;
// Returns container with all labels.
const std::vector<label_ref_t> &labels() const;
auto out() const;
auto in() const;
// True if there exists edge other->this
// True if there exists edge between other vertex and this vertex.
bool in_contains(VertexAccessor const &other) const;
};

View File

@ -148,7 +148,7 @@ public:
// Filters out vertices which are connected.
auto isolated()
{
return filter([&](auto &ra) { return ra.isolated(); });
return filter([&](auto &element) { return element.isolated(); });
}
// For all items calls OP.

View File

@ -52,4 +52,5 @@ auto make_iterator(F &&f, size_t count)
// is T.
return LambdaIterator<decltype(f().take()), F>(std::move(f), count);
}
}

View File

@ -54,4 +54,5 @@ auto make_limited_map(I &&iter, OP &&op)
return LimitedMap<decltype(op(iter.next().take()).take()), I, OP>(
std::move(iter), std::move(op));
}
}

View File

@ -51,4 +51,5 @@ auto make_map(I &&iter, OP &&op)
return Map<decltype(op(iter.next().take())), I, OP>(std::move(iter),
std::move(op));
}
}

View File

@ -5,7 +5,7 @@
namespace iter
{
// Class which wraps iterator with next() into c++ iterator.
// Class which wraps iterator with next() into C++ iterator.
// T - type of return value
// I - iterator type
template <class T, class I>
@ -65,10 +65,10 @@ private:
template <class I>
auto make_range_iterator(I &&iter)
{
// Because function isn't receving or in any way using type T from
// RangeIterator compiler can't deduce it thats way there is decltype in
// construction of RangeIterator. Resoulting type of iter.next().take() is
// T.
// Because this function isn't receving or in any way using type T from
// RangeIterator, compiler can't deduce it. That is the reason why
// there is decltype in construction of RangeIterator.
// declytype(iter.next().take()) is T.
return RangeIterator<decltype(iter.next().take()), I>(std::move(iter));
}
}

View File

@ -42,7 +42,7 @@ private:
template <class I>
auto make_virtual(I &&iter)
{
// Compiler cant deduce type T. decltype is here to help with it.
// Compiler can't deduce type T. decltype is here to help with it.
return Virtual<decltype(iter.next().take())>(std::move(iter));
}
}

View File

@ -7,6 +7,20 @@
#include "storage/type_group_edge.hpp"
#include "storage/type_group_vertex.hpp"
template <class TG>
const bool Properties<TG>::contains(property_key &key) const
{
for (auto &prop : props)
{
if (prop.key == key)
{
return true;
}
}
return false;
}
template <class TG>
const StoredProperty<TG> &Properties<TG>::at(PropertyFamily<TG> &fam) const
{

View File

@ -98,18 +98,6 @@ 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)
add_test(NAME integration_query_engine COMMAND integration_query_engine)
set_property(TARGET integration_query_engine PROPERTY CXX_STANDARD 14)
# test memgraph with bolt protocol
add_executable(integration_memgraph_bolt integration/memgraph_bolt.cpp)
target_link_libraries(integration_memgraph_bolt Threads::Threads)
add_test(NAME integration_memgraph_bolt COMMAND integration_memgraph_bolt)
set_property(TARGET integration_memgraph_bolt PROPERTY CXX_STANDARD 14)
## MANUAL TESTS
# cypher_ast

View File

@ -33,7 +33,7 @@ int main(void)
logging::init_async();
logging::log->pipe(std::make_unique<Stdout>());
size_t cvl_n = 1000;
size_t entities_number = 1000;
Db db("cleaning");
@ -57,14 +57,14 @@ int main(void)
// clean vertices
// delete vertices a
// clean vertices
run(cvl_n, create_vertex_label, stripper, query_functions);
assert(db.graph.vertices.access().size() == cvl_n);
run(entities_number, create_vertex_label, stripper, query_functions);
assert(db.graph.vertices.access().size() == entities_number);
clean_vertex(db);
assert(db.graph.vertices.access().size() == cvl_n);
assert(db.graph.vertices.access().size() == entities_number);
run(1, delete_label_vertices, stripper, query_functions);
assert(db.graph.vertices.access().size() == cvl_n);
assert(db.graph.vertices.access().size() == entities_number);
clean_vertex(db);
assert(db.graph.vertices.access().size() == 0);
@ -76,23 +76,23 @@ int main(void)
// 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(entities_number, create_vertex_label, stripper, query_functions);
assert(db.graph.vertices.access().size() == entities_number);
run(cvl_n, create_vertex_other, stripper, query_functions);
assert(db.graph.vertices.access().size() == cvl_n * 2);
run(entities_number, create_vertex_other, stripper, query_functions);
assert(db.graph.vertices.access().size() == entities_number * 2);
clean_vertex(db);
assert(db.graph.vertices.access().size() == cvl_n * 2);
assert(db.graph.vertices.access().size() == entities_number * 2);
run(1, delete_label_vertices, stripper, query_functions);
assert(db.graph.vertices.access().size() == cvl_n * 2);
assert(db.graph.vertices.access().size() == entities_number * 2);
clean_vertex(db);
assert(db.graph.vertices.access().size() == cvl_n);
assert(db.graph.vertices.access().size() == entities_number);
run(1, delete_all_vertices, stripper, query_functions);
assert(db.graph.vertices.access().size() == cvl_n);
assert(db.graph.vertices.access().size() == entities_number);
clean_vertex(db);
assert(db.graph.vertices.access().size() == 0);

View File

@ -1,7 +0,0 @@
#include "utils/assert.hpp"
auto main() -> int
{
permanent_assert(false, "TODO: implement memgraph bolt integration test");
return 0;
}

View File

@ -32,14 +32,20 @@ int main(void)
// TODO: put all queries into a file
std::vector<std::string> queries = {
"CREATE (n:LABEL {name: \"TEST1\"}) RETURN n",
// CREATE and MATCH by label and property
"CREATE (n:LABEL {name: \"TEST01\"}) RETURN n",
"CREATE (n:LABEL {name: \"TEST02\"}) RETURN n",
"MATCH (n:LABEL {name: \"TEST01\"}) 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",
"MATCH (n {id: 2}) RETURN n", "MATCH (n {id: 3}) 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",
"MATCH (n {id: 2}) RETURN n",
"MATCH (n {id: 3}) RETURN n",
"MATCH (a {id:0}), (p {id: 1}) CREATE (a)-[r:IS]->(p) RETURN r",
"MATCH (a {id:1}), (p {id: 2}) CREATE (a)-[r:IS]->(p) RETURN r",
"MATCH ()-[r]-() WHERE ID(r)=0 RETURN r",
@ -47,9 +53,8 @@ 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 (n1), (n2) WHERE ID(n1)=0 AND "
"ID(n2)=1 CREATE (n1)<-[r:IS {age: "
"25,weight: 70}]-(n2) RETURN r",
"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",
@ -57,7 +62,12 @@ int main(void)
"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"};
"MATCH (n:LABEL)-[:TYPE]->(m) RETURN n",
// CREATE and MATCH multiple labels and properties
"CREATE (n:LABEL1:LABEL2 {name: \"TEST01\", age: 20}) RETURN n",
"MATCH (n:LABEL1:LABEL2 {name: \"TEST01\", age: 20}) RETURN n"
};
for (auto &query : queries) {
auto stripped = stripper.strip(query);

View File

@ -1,7 +0,0 @@
#include "utils/assert.hpp"
auto main() -> int
{
permanent_assert(false, "TODO: implement query engine integration test");
return 0;
}

View File

@ -6,6 +6,8 @@
#include "barrier/barrier.cpp"
#endif
#include "logging/default.hpp"
#include "logging/streams/stdout.hpp"
#include "communication/bolt/v1/serialization/bolt_serializer.hpp"
#include "database/db.hpp"
#include "query_engine/query_stripper.hpp"
@ -18,6 +20,9 @@ using namespace std;
int main(int argc, char **argv)
{
logging::init_async();
logging::log->pipe(std::make_unique<Stdout>());
Db db;
#ifdef BARRIER
auto queries = load_queries(barrier::trans(db));
@ -25,17 +30,7 @@ int main(int argc, char **argv)
auto queries = load_queries(db);
#endif
// auto arguments = all_arguments(argc, argv);
// auto input_query = extract_query(arguments);
auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL);
// auto stripped = stripper.strip(input_query);
//
// auto time = timer<ms>([&stripped, &queries]() {
// for (int i = 0; i < 1000000; ++i) {
// queries[stripped.hash](stripped.arguments);
// }
// });
// std::cout << time << std::endl;
vector<string> history;
string command;

View File

@ -0,0 +1,15 @@
#include <iostream>
#include <vector>
#include "utils/iterator/map.hpp"
int main(void)
{
std::vector<int> test{1,2,3};
for (auto item : test) {
std::cout << item << std::endl;
}
return 0;
}