better architecture for hardcoded test queries (still has to be polished)

This commit is contained in:
Marko Budiselic 2016-11-17 15:46:36 +01:00
parent 8362b64e9f
commit afc0a4a176
76 changed files with 599 additions and 262 deletions

View File

@ -593,6 +593,7 @@ if (MEMGRAPH)
target_link_libraries(${MEMGRAPH_BUILD_NAME} memgraph)
endif ()
target_link_libraries(${MEMGRAPH_BUILD_NAME} stdc++fs)
target_link_libraries(${MEMGRAPH_BUILD_NAME} Threads::Threads)
target_link_libraries(${MEMGRAPH_BUILD_NAME} cypher_lib)
if (UNIX)

View File

@ -21,10 +21,11 @@ public:
#else
std::string template_path = CONFIG(config::TEMPLATE_CPU_CPP_PATH);
#endif
template_file = utils::read_file(template_path.c_str());
template_text = utils::read_text(fs::path(template_path));
}
template <typename Tree>
// TODO: query and path shoud be distinct types
void generate_code(const Tree &tree, const std::string &query,
const uint64_t stripped_hash, const std::string &path)
{
@ -42,7 +43,7 @@ public:
// save the code
std::string generated = template_engine::render(
template_file, {{"class_name", "CodeCPU"},
template_text.str(), {{"class_name", "CodeCPU"},
{"stripped_hash", std::to_string(stripped_hash)},
{"query", query},
#ifdef BARRIER
@ -54,12 +55,12 @@ public:
logger.trace("generated code: {}", generated);
utils::write_file(generated, path);
utils::write(utils::Text(generated), fs::path(path));
}
protected:
Logger logger;
private:
std::string template_file;
utils::Text template_text;
};

View File

@ -8,15 +8,24 @@ auto delete_query_action =
std::string code = "";
for (auto const &kv : action_data.actions) {
// TODO: don't delete the whole graph
for (auto const &kv : action_data.actions)
{
auto entity = kv.first;
if (kv.second == ClauseAction::DeleteNode && action_data.is_detach) {
if (kv.second == ClauseAction::DeleteNode && action_data.is_detach)
{
code += code_line(delete_whole_graph);
}
if (kv.second == ClauseAction::DeleteNode && !action_data.is_detach) {
if (kv.second == ClauseAction::DeleteNode && !action_data.is_detach)
{
code += code_line(delete_all_detached_nodes);
}
if (kv.second == ClauseAction::DeleteRelationship) {
if (kv.second == ClauseAction::DeleteRelationship)
{
code += code_line("// DELETE Relationship({})", entity);
}
}

View File

@ -1,50 +1,13 @@
#pragma once
#include <iostream>
#include <map>
#include "includes.hpp"
using namespace std;
#ifdef BARRIER
#include "barrier/barrier.hpp"
namespace barrier
namespace hardcode
{
#else
#include <cassert>
#include <map>
#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 "query/util.hpp"
#endif
auto load_queries(Db &db)
auto load_basic_functions(Db &db)
{
std::map<uint64_t, std::function<bool(properties_t &&)>> queries;
query_functions_t functions;
// CREATE (n {prop: 0}) RETURN n
auto create_node = [&db](properties_t &&args) {
@ -54,7 +17,7 @@ auto load_queries(Db &db)
vertex_accessor.set(property_key, std::move(args[0]));
return t.commit();
};
queries[11597417457737499503u] = create_node;
functions[11597417457737499503u] = create_node;
// CREATE (n:LABEL {name: "TEST"}) RETURN n;
auto create_labeled_and_named_node = [&db](properties_t &&args) {
@ -490,45 +453,35 @@ auto load_queries(Db &db)
return false;
}
};
queries[17721584194272598838u] = match_label_property;
functions[17721584194272598838u] = match_label_property;
// Blueprint:
// auto = [&db](properties_t &&args) {
// DbAccessor t(db);
//
//
// return t.commit();
// };
queries[15284086425088081497u] = match_all_nodes;
queries[4857652843629217005u] = match_by_label;
queries[15648836733456301916u] = create_edge_v2;
queries[10597108978382323595u] = create_account;
queries[5397556489557792025u] = create_labeled_and_named_node;
functions[15284086425088081497u] = match_all_nodes;
functions[4857652843629217005u] = match_by_label;
functions[15648836733456301916u] = create_edge_v2;
functions[10597108978382323595u] = create_account;
functions[5397556489557792025u] = create_labeled_and_named_node;
// TODO: query hasher reports two hash values
queries[998725786176032607u] = create_labeled_and_named_node_v2;
queries[16090682663946456821u] = create_labeled_and_named_node_v2;
functions[998725786176032607u] = create_labeled_and_named_node_v2;
functions[16090682663946456821u] = create_labeled_and_named_node_v2;
queries[7939106225150551899u] = create_edge;
queries[6579425155585886196u] = create_edge;
queries[11198568396549106428u] = find_node_by_internal_id;
queries[8320600413058284114u] = find_edge_by_internal_id;
queries[6813335159006269041u] = update_node;
queries[10506105811763742758u] = match_all_delete;
queries[13742779491897528506u] = match_label_delete;
queries[11349462498691305864u] = match_id_delete;
queries[6963549500479100885u] = match_edge_id_delete;
queries[14897166600223619735u] = match_edge_all_delete;
queries[16888549834923624215u] = match_edge_type_delete;
queries[11675960684124428508u] = match_id_type_return;
queries[15698881472054193835u] = match_name_type_return;
queries[12595102442911913761u] = match_name_type_return_cross;
queries[8918221081398321263u] = match_label_type_return;
functions[7939106225150551899u] = create_edge;
functions[6579425155585886196u] = create_edge;
functions[11198568396549106428u] = find_node_by_internal_id;
functions[8320600413058284114u] = find_edge_by_internal_id;
functions[6813335159006269041u] = update_node;
functions[10506105811763742758u] = match_all_delete;
functions[13742779491897528506u] = match_label_delete;
functions[11349462498691305864u] = match_id_delete;
functions[6963549500479100885u] = match_edge_id_delete;
functions[14897166600223619735u] = match_edge_all_delete;
functions[16888549834923624215u] = match_edge_type_delete;
functions[11675960684124428508u] = match_id_type_return;
functions[15698881472054193835u] = match_name_type_return;
functions[12595102442911913761u] = match_name_type_return_cross;
functions[8918221081398321263u] = match_label_type_return;
return queries;
return functions;
}
#ifdef BARRIER
}
#endif

View File

@ -0,0 +1,123 @@
#pragma once
#include "includes.hpp"
namespace hardcode
{
// TODO: decouple hashes from the code because hashes could and should be
// tested separately
auto load_dressipi_functions(Db &db)
{
query_functions_t functions;
// Query: CREATE (n {garment_id: 1234, garment_category_id: 1}) RETURN n
// Hash: 12139093029838549530
functions[12139093029838549530u] = [&db](properties_t &&args) {
DbAccessor t(db);
return t.commit();
};
// Query: CREATE (p:profile {profile_id: 111, partner_id: 55}) RETURN p
// Hash: 17158428452166262783
functions[17158428452166262783u] = [&db](properties_t &&args) {
DbAccessor t(db);
return t.commit();
};
// Query: MATCH (g:garment {garment_id: 1234}) SET g:FF RETURN labels(g)
// Hash: 11123780635391515946
functions[11123780635391515946u] = [&db](properties_t &&args) {
DbAccessor t(db);
return t.commit();
};
// Query: MATCH (p:profile {profile_id: 111, partner_id: 55})-[s:score]-(g:garment{garment_id: 1234}) SET s.score = 1550 RETURN s.score
// Hash: 674581607834128909
functions[674581607834128909u] = [&db](properties_t &&args) {
DbAccessor t(db);
return t.commit();
};
// Query: MATCH (g:garment {garment_id: 3456}) SET g.reveals = 50 RETURN g
// Hash: 2839969099736071844
functions[2839969099736071844u] = [&db](properties_t &&args) {
DbAccessor t(db);
return t.commit();
};
// Query: MERGE (g1:garment {garment_id: 1234})-[r:default_outfit]-(g2:garment {garment_id: 2345}) RETURN r
// Hash: 3782642357973971504
functions[3782642357973971504u] = [&db](properties_t &&args) {
DbAccessor t(db);
return t.commit();
};
// Query: MERGE (p:profile {profile_id: 111, partner_id: 55})-[s:score]-(g.garment {garment_id: 1234}) SET s.score=1500 RETURN s
// Hash: 7871009397157280694
functions[7871009397157280694u] = [&db](properties_t &&args) {
DbAccessor t(db);
return t.commit();
};
// Query: MATCH (p:profile {profile_id: 111, partner_id: 55})-[s:score]-(g.garment {garment_id: 1234}) DELETE s
// Hash: 9459600951073026137
functions[9459600951073026137u] = [&db](properties_t &&args) {
DbAccessor t(db);
return t.commit();
};
// Query: MATCH (p:profile {profile_id: 113}) DELETE p
// Hash: 6763665709953344106
functions[6763665709953344106u] = [&db](properties_t &&args) {
DbAccessor t(db);
return t.commit();
};
// Query: MATCH (n) DETACH DELETE n
// Hash: 4798158026600988079
functions[4798158026600988079u] = [&db](properties_t &&args) {
DbAccessor t(db);
return t.commit();
};
// Query: MATCH (p:profile) RETURN p
// Hash: 15599970964909894866
functions[15599970964909894866u] = [&db](properties_t &&args) {
DbAccessor t(db);
return t.commit();
};
// Query: MATCH (g:garment) RETURN COUNT(g)
// Hash: 11458306387621940265
functions[11458306387621940265u] = [&db](properties_t &&args) {
DbAccessor t(db);
return t.commit();
};
// Query: MATCH (g:garment {garment_id: 1234}) RETURN g
// Hash: 7756609649964321221
functions[7756609649964321221u] = [&db](properties_t &&args) {
DbAccessor t(db);
return t.commit();
};
// Query: MATCH (p:profile {partner_id: 55}) RETURN p
// Hash: 17506488413143988006
functions[17506488413143988006u] = [&db](properties_t &&args) {
DbAccessor t(db);
return t.commit();
};
// Query: MATCH (n) RETURN count(n)
// Hash: 10510787599699014973
functions[10510787599699014973u] = [&db](properties_t &&args) {
DbAccessor t(db);
return t.commit();
};
return functions;
}
}

View File

@ -0,0 +1,38 @@
#pragma once
#include <cassert>
#include <iostream>
#include <map>
#include <map>
#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 "query/util.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"
using namespace std;
namespace hardcode
{
using query_functions_t =
std::map<uint64_t, std::function<bool(properties_t &&)>>;
}

View File

@ -20,3 +20,4 @@
#include "expr.hpp"
#include "with.hpp"
#include "functions.hpp"
#include "merge.hpp"

View File

@ -55,6 +55,7 @@ struct ReturnList;
struct Distinct;
struct Create;
struct Merge;
struct Match;
struct Where;
struct Set;
@ -66,6 +67,7 @@ struct ReadQuery;
struct UpdateQuery;
struct DeleteQuery;
struct ReadWriteQuery;
struct MergeQuery;
struct SetKey;
struct SetValue;
@ -89,7 +91,7 @@ struct AstVisitor
Return, Distinct, Delete, DeleteQuery, UpdateQuery, Set, SetKey,
ReadWriteQuery, IdentifierList, WithList, WithClause, WithQuery, Long,
CountFunction, LabelsFunction, InternalIdExpr, SetValue, SetElement,
LabelSetElement, SetList>
MergeQuery, Merge, LabelSetElement, SetList>
{
};
}

View File

@ -0,0 +1,18 @@
#pragma once
#include "ast_node.hpp"
#include "pattern.hpp"
#include "return.hpp"
namespace ast
{
struct Merge : public AstNode<Merge>
{
Merge(Pattern* pattern)
: pattern(pattern) {}
Pattern* pattern;
};
}

View File

@ -6,6 +6,7 @@
#include "match.hpp"
#include "return.hpp"
#include "set.hpp"
#include "merge.hpp"
namespace ast
{
@ -70,4 +71,17 @@ struct ReadWriteQuery : public AstNode<ReadWriteQuery>
Return *return_clause;
};
struct MergeQuery : public AstNode<MergeQuery>
{
MergeQuery(Merge* merge_clause, Set* set_clause, Return* return_clause) :
merge_clause(merge_clause), set_clause(set_clause),
return_clause(return_clause)
{
}
Merge *merge_clause;
Set *set_clause;
Return *return_clause;
};
}

View File

@ -1,15 +1,24 @@
#pragma once
#include <vector>
#include "utils/command_line/arguments.hpp"
#include "utils/string/file.hpp"
std::string extract_query(const std::vector<std::string>& arguments)
auto extract_queries(const std::vector<std::string>& arguments)
{
std::vector<std::string> queries;
// load single query
if (contains_argument(arguments, "-q"))
return get_argument(arguments, "-q", "CREATE (n) RETURN n");
auto default_file = "query.cypher";
{
queries.emplace_back(get_argument(arguments, "-q", "CREATE (n) RETURN n"));
return queries;
}
// load multiple queries from file
auto default_file = "queries.cypher";
auto file = get_argument(arguments, "-f", default_file);
// TODO: error handling
return utils::read_file(file.c_str());
return utils::read_lines(file.c_str());
}

View File

@ -81,6 +81,22 @@ start ::= read_write_query(Q). {
ast->root = Q;
}
start ::= merge_query(Q). {
ast->root = Q;
}
// -- merge query
%type merge_query {ast::MergeQuery*}
merge_query(MQ) ::= merge_clause(MC) set_clause(SC) return_clause(RC). {
MQ = ast->create<ast::MergeQuery>(MC, SC, RC);
}
merge_query(MQ) ::= merge_clause(MC) return_clause(RC). {
MQ = ast->create<ast::MergeQuery>(MC, nullptr, RC);
}
// -- with query
%type with_query {ast::WithQuery*}
@ -188,7 +204,13 @@ delete_query(DQ) ::= match_clause(M) delete_clause(D). {
%type create_clause {ast::Create*}
create_clause(C) ::= CREATE pattern(P). {
C = ast->create<ast::Create>(P);
C = ast->create<ast::Create>(P);
}
%type merge_clause {ast::Merge*}
merge_clause(M) ::= MERGE pattern(P). {
M = ast->create<ast::Merge>(P);
}
%type match_clause {ast::Match*}

View File

@ -350,6 +350,12 @@ public:
Traverser::visit(write_query);
}
void visit(ast::MergeQuery &merge_query) override
{
auto entry = printer.advance("Merge Query");
Traverser::visit(merge_query);
}
void visit(ast::DeleteQuery &delete_query) override
{
auto entry = printer.advance("Delete Query");
@ -371,6 +377,12 @@ public:
Traverser::visit(create);
}
void visit(ast::Merge &merge) override
{
auto entry = printer.advance("Merge");
Traverser::visit(merge);
}
void visit(ast::UpdateQuery &update_query) override
{
auto entry = printer.advance("Update Query");

View File

@ -43,6 +43,7 @@ public:
// keywords
rule("(?i:CREATE)", TK_CREATE);
rule("(?i:MERGE)", TK_MERGE);
rule("(?i:MATCH)", TK_MATCH);
rule("(?i:WHERE)", TK_WHERE);
rule("(?i:SET)", TK_SET);

View File

@ -34,6 +34,13 @@ public:
accept(query.return_clause);
}
void visit(ast::MergeQuery& query) override
{
accept(query.merge_clause);
accept(query.set_clause);
accept(query.return_clause);
}
void visit(ast::Match& match) override
{
accept(match.pattern_list);
@ -261,6 +268,11 @@ public:
accept(create.pattern);
}
void visit(ast::Merge& merge) override
{
accept(merge.pattern);
}
void visit(ast::Distinct& distinct) override
{
accept(distinct.identifier);

View File

@ -27,5 +27,10 @@ public:
auto preprocess(const std::string &query) { return stripper.strip(query); }
private:
// In C++17 the ints should be unnecessary?
// as far as I understand in C++17 class template parameters
// can be deduced just like function template parameters
// TODO: once C++ 17 will be well suported by comilers
// refactor this piece of code
QueryStripper<int, int, int, int> stripper;
};

View File

@ -26,7 +26,8 @@ template <typename... Ts>
class QueryStripper : public Loggable
{
public:
QueryStripper(Ts &&... strip_types) : Loggable("QueryStripper"),
QueryStripper(Ts &&... strip_types)
: Loggable("QueryStripper"),
strip_types(std::make_tuple(std::forward<Ts>(strip_types)...)),
lexer(std::make_unique<CypherLexer>())
{
@ -34,19 +35,21 @@ public:
QueryStripper(QueryStripper &other) = delete;
QueryStripper(QueryStripper &&other) : Loggable("QueryStripper"),
strip_types(std::move(other.strip_types)),
QueryStripper(QueryStripper &&other)
: Loggable("QueryStripper"), strip_types(std::move(other.strip_types)),
lexer(std::move(other.lexer))
{
}
auto strip_space(const std::string &query)
{
return strip(query, " ");
}
auto strip_space(const std::string &query) { return strip(query, " "); }
auto strip(const std::string &query, const std::string &separator = "")
{
// -------------------------------------------------------------------
// TODO: write speed tests and then optimize, because this
// function is called before every query execution !
// -------------------------------------------------------------------
// TODO write this more optimal (resplace string
// concatenation with something smarter)
// TODO: in place substring replacement
@ -66,7 +69,8 @@ public:
if (_or(token.id, strip_types, std::make_index_sequence<size>{}))
{
auto index = counter++;
switch (token.id) {
switch (token.id)
{
case TK_LONG:
store_query_param<Int64>(stripped_arguments,
std::stol(token.value));
@ -78,7 +82,8 @@ public:
// TODO: remove
store_query_param<String>(stripped_arguments, token.value);
break;
case TK_BOOL: {
case TK_BOOL:
{
bool value = token.value[0] == 'T' || token.value[0] == 't';
store_query_param<Bool>(stripped_arguments, value);
break;
@ -92,16 +97,33 @@ public:
assert(false);
}
stripped_query += std::to_string(index) + separator;
} else {
// TODO: lowercase only keywords like (MATCH, CREATE, ...)
}
else
{
// if token is keyword then lowercase because query hash
// should be the same
// TODO: probably we shoud do the lowercase before
// or during the tokenization (SPEED TESTS)
if (token.id == TK_OR || token.id == TK_AND ||
token.id == TK_NOT || token.id == TK_WITH ||
token.id == TK_SET || token.id == TK_CREATE ||
token.id == TK_MERGE || token.id == TK_MATCH ||
token.id == TK_DELETE || token.id == TK_DETACH ||
token.id == TK_WHERE || token.id == TK_RETURN ||
token.id == TK_DISTINCT || token.id == TK_COUNT ||
token.id == TK_LABELS)
{
std::transform(token.value.begin(), token.value.end(),
token.value.begin(), ::tolower);
}
stripped_query += token.value + separator;
}
}
// TODO: hash function should be a template parameter
auto hash = fnv(stripped_query);
return QueryStripped(std::move(stripped_query),
std::move(stripped_arguments),
hash);
std::move(stripped_arguments), hash);
}
private:
@ -111,7 +133,7 @@ private:
template <typename Value, typename Tuple, std::size_t... index>
bool _or(Value &&value, Tuple &&tuple, std::index_sequence<index...>)
{
return or_vargs(std::forward<Value>(value),
return utils::or_vargs(std::forward<Value>(value),
std::get<index>(std::forward<Tuple>(tuple))...);
}
};

View File

@ -5,7 +5,7 @@
#include <stdexcept>
#include <cstdlib>
// TODO: isolate from caller (caller should know that his dependency is
// TODO: isolate from caller (caller shouldn't know that his dependency is)
// yaml-cpp
#include "yaml-cpp/yaml.h"
@ -50,6 +50,10 @@ public:
return config;
}
void register_program_arguments()
{
}
std::string operator[](const char* key)
{
return _config[key].template as<std::string>();

View File

@ -1,19 +1,66 @@
#pragma once
#include <cerrno>
// TODO: remove experimental from here once that becomes possible
#include <experimental/filesystem>
#include <fstream>
#include <ostream>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <cerrno>
#include <stdexcept>
#include <fmt/format.h>
// TODO: remove experimental from here once it becomes possible
namespace fs = std::experimental::filesystem;
namespace utils
{
std::string read_file(const char *filename);
/*
* Type safe text object.
*/
class Text
{
public:
Text() = default;
explicit Text(const std::string &text) : text_(text) {}
void write_file(const std::string& content, const std::string& path);
// text could be huge and copy operationt would be too expensive
Text(const Text& other) = delete;
Text& operator=(const Text& other) = delete;
// the object is movable
Text (Text&& other) = default;
Text& operator=(Text&& other)
{
text_ = std::move(other.text_);
return *this;
}
const std::string &str() const { return text_; }
private:
std::string text_;
};
/*
* Reads the whole text from a file at the path.
*/
Text read_text(const fs::path &path);
/*
* Reads all the lines from a file at the path.
*/
std::vector<std::string> read_lines(const fs::path &path);
// TODO: lazy implementation of read_lines functionality (line by line)
// TODO: read word by word + lazy implementation
/*
* Write text in a file at the path.
*/
void write(const Text &text, const fs::path &path);
}

View File

@ -2,23 +2,38 @@
#include <iostream>
// variadic argument printer
namespace utils
{
/*
* Variadic argument print
*/
template<class Head>
void _print_vargs(std::ostream& s, Head&& head)
void print_vargs(std::ostream& s, Head&& head)
{
s << std::forward<Head>(head);
}
template<class Head, class ...Tail>
void _print_vargs(std::ostream& s, Head&& head, Tail&& ...tail)
void print_vargs(std::ostream& s, Head&& head, Tail&& ...tail)
{
s << std::forward<Head>(head);
_print_vargs(s, std::forward<Tail>(tail)...);
print_vargs(s, std::forward<Tail>(tail)...);
}
/*
* Compile time print line.
*
* USAGE:
* RUN: utils::printer("ONE ", "TWO");
* OUTPUT: "ONE TWO\n"
*
* TODO: reimplament with C++17 fold expressions
*/
template<class ...Args>
void print_vargs(Args&&... args)
void println(Args&&... args)
{
_print_vargs(std::cout, std::forward<Args>(args)...);
print_vargs(std::cout, std::forward<Args>(args)...);
std::cout << std::endl;
}
// value equality with any of variadic argument
@ -39,3 +54,5 @@ bool or_vargs(Value&& value, Array&&... array)
{
return _or_vargs(std::forward<Value>(value), std::forward<Array>(array)...);
}
}

View File

@ -1,25 +1,43 @@
#include "utils/string/file.hpp"
#include <iterator>
namespace utils
{
std::string read_file(const char *filename)
namespace fs = std::experimental::filesystem;
Text read_text(const fs::path &path)
{
std::ifstream in(filename, std::ios::in | std::ios::binary);
std::ifstream in(path, std::ios::in | std::ios::binary);
if (in)
return std::string(std::istreambuf_iterator<char>(in),
std::istreambuf_iterator<char>());
return Text(std::string(std::istreambuf_iterator<char>(in),
std::istreambuf_iterator<char>()));
auto error_message = fmt::format("{0}{1}", "Fail to read: ", filename);
auto error_message = fmt::format("{0}{1}", "Fail to read: ", path.c_str());
throw std::runtime_error(error_message);
}
void write_file(const std::string& content, const std::string& path)
std::vector<std::string> read_lines(const fs::path &path)
{
std::vector<std::string> lines;
std::ifstream stream(path.c_str());
std::string line;
while (std::getline(stream, line))
{
lines.emplace_back(line);
}
return lines;
}
void write(const Text &text, const fs::path &path)
{
std::ofstream stream;
stream.open(path.c_str());
stream << content;
stream << text.str();
stream.close();
}

View File

@ -64,6 +64,7 @@ endforeach()
# test hard coded queries
add_executable(integration_queries integration/queries.cpp)
target_link_libraries(integration_queries stdc++fs)
target_link_libraries(integration_queries memgraph)
target_link_libraries(integration_queries Threads::Threads)
target_link_libraries(integration_queries ${fmt_static_lib})
@ -102,6 +103,7 @@ set_property(TARGET index PROPERTY CXX_STANDARD 14)
# cypher_ast
add_executable(manual_cypher_ast manual/cypher_ast.cpp)
target_link_libraries(manual_cypher_ast stdc++fs)
target_link_libraries(manual_cypher_ast memgraph)
target_link_libraries(manual_cypher_ast Threads::Threads)
target_link_libraries(manual_cypher_ast ${fmt_static_lib})
@ -120,6 +122,7 @@ set_property(TARGET manual_queries PROPERTY CXX_STANDARD 14)
# query_engine
add_executable(manual_query_engine manual/query_engine.cpp)
target_link_libraries(manual_query_engine stdc++fs)
target_link_libraries(manual_query_engine memgraph)
target_link_libraries(manual_query_engine ${fmt_static_lib})
target_link_libraries(manual_query_engine ${yaml_static_lib})
@ -130,6 +133,7 @@ set_property(TARGET manual_query_engine PROPERTY CXX_STANDARD 14)
# query_hasher
add_executable(manual_query_hasher manual/query_hasher.cpp)
target_link_libraries(manual_query_hasher stdc++fs)
target_link_libraries(manual_query_hasher memgraph)
target_link_libraries(manual_query_hasher ${fmt_static_lib})
target_link_libraries(manual_query_hasher ${yaml_static_lib})

View File

@ -0,0 +1,27 @@
CREATE (n:LABEL {name: "TEST01"}) RETURN n
CREATE (n:LABEL {name: "TEST02"}) 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
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
MATCH ()-[r]-() WHERE ID(r)=1 RETURN r
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) 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
MATCH ()-[r:TYPE]-() DELETE r
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"
CREATE (n:LABEL1:LABEL2 {name: "TEST01", age: 20}) RETURN n
MATCH (n:LABEL1:LABEL2 {name: "TEST01", age: 20}) RETURN n

View File

@ -0,0 +1,15 @@
CREATE (n {garment_id: 1234, garment_category_id: 1}) RETURN n
CREATE (p:profile {profile_id: 111, partner_id: 55}) RETURN p
MATCH (g:garment {garment_id: 1234}) SET g:FF RETURN labels(g)
MATCH (p:profile {profile_id: 111, partner_id: 55})-[s:score]-(g:garment{garment_id: 1234}) SET s.score = 1550 RETURN s.score
MATCH (g:garment {garment_id: 3456}) SET g.reveals = 50 RETURN g
MERGE (g1:garment {garment_id: 1234})-[r:default_outfit]-(g2:garment {garment_id: 2345}) RETURN r
MERGE (p:profile {profile_id: 111, partner_id: 55})-[s:score]-(g.garment {garment_id: 1234}) SET s.score=1500 RETURN s
MATCH (p:profile {profile_id: 111, partner_id: 55})-[s:score]-(g.garment {garment_id: 1234}) DELETE s
MATCH (p:profile {profile_id: 113}) DELETE p
MATCH (n) DETACH DELETE n
MATCH (p:profile) RETURN p
MATCH (g:garment) RETURN COUNT(g)
MATCH (g:garment {garment_id: 1234}) RETURN g
MATCH (p:profile {partner_id: 55}) RETURN p
MATCH (n) RETURN count(n)

View File

View File

@ -1,11 +1,6 @@
#include "query/hardcode/queries.hpp"
#ifdef BARRIER
#include "barrier/barrier.cpp"
#endif
#include "logging/default.hpp"
#include "logging/streams/stdout.hpp"
#include "query/hardcode/basic.hpp"
#include "query/strip/stripper.hpp"
#include "utils/sysinfo/memory.hpp"
@ -15,7 +10,8 @@ void run(size_t n, std::string &query, S &stripper, Q &qf)
auto stripped = stripper.strip(query);
std::cout << "Running query [" << stripped.hash << "] for " << n << " time."
<< std::endl;
for (int i = 0; i < n; i++) {
for (int i = 0; i < n; i++)
{
properties_t vec = stripped.arguments;
assert(qf[stripped.hash](std::move(vec)));
}
@ -37,11 +33,7 @@ int main(void)
Db db("cleaning");
#ifdef BARRIER
auto query_functions = load_queries(barrier::trans(db));
#else
auto query_functions = load_queries(db);
#endif
auto query_functions = hardcode::load_basic_functions(db);
auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL);
@ -50,7 +42,7 @@ int main(void)
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";
std::string delete_all_vertices = "MATCH (n) DELETE n";
// ******************************* TEST 1 ********************************//
// add vertices a

View File

@ -1,11 +1,6 @@
#include "query/hardcode/queries.hpp"
#include <random>
#ifdef BARRIER
#include "barrier/barrier.cpp"
#endif
#include "query/hardcode/basic.hpp"
#include "logging/default.hpp"
#include "logging/streams/stdout.hpp"
#include "query/strip/stripper.hpp"
@ -24,11 +19,7 @@ void run(size_t n, std::string &query, Db &db)
{
auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL);
#ifdef BARRIER
auto qf = load_queries(barrier::trans(db));
#else
auto qf = load_queries(db);
#endif
auto qf = hardcode::load_basic_functions(db);
auto stripped = stripper.strip(query);
std::cout << "Running query [" << stripped.hash << "] for " << n << " time."
@ -43,11 +34,7 @@ void add_edge(size_t n, Db &db)
{
auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL);
#ifdef BARRIER
auto qf = load_queries(barrier::trans(db));
#else
auto qf = load_queries(db);
#endif
auto qf = hardcode::load_basic_functions(db);
std::string query = "MATCH (n1), (n2) WHERE ID(n1)=0 AND "
"ID(n2)=1 CREATE (n1)<-[r:IS {age: "

View File

@ -1,76 +1,60 @@
#include "query/hardcode/queries.hpp"
#ifdef BARRIER
#include "barrier/barrier.cpp"
#endif
#include "communication/bolt/v1/serialization/bolt_serializer.hpp"
#include "database/db.hpp"
#include "logging/default.hpp"
#include "logging/streams/stdout.hpp"
#include "query/hardcode/basic.hpp"
#include "query/hardcode/dressipi.hpp"
#include "query/strip/stripper.hpp"
#include "utils/string/file.hpp"
#include "utils/variadic/variadic.hpp"
#include "utils/command_line/arguments.hpp"
int main(void)
int main(int argc, char *argv[])
{
auto arguments = all_arguments(argc, argv);
// POSSIBILITIES: basic, dressipi
auto suite_name = get_argument(arguments, "-s", "basic");
// POSSIBILITIES: query_execution, hash_generation
auto work_mode = get_argument(arguments, "-w", "query_execution");
// init logging
logging::init_async();
logging::log->pipe(std::make_unique<Stdout>());
// init db, functions and stripper
Db db;
#ifdef BARRIER
auto query_functions = load_queries(barrier::trans(db));
#else
auto query_functions = load_queries(db);
#endif
hardcode::query_functions_t query_functions;
if (suite_name == "dressipi")
{
query_functions = std::move(hardcode::load_dressipi_functions(db));
}
else
{
query_functions = std::move(hardcode::load_basic_functions(db));
}
auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL);
// TODO: put all queries into a file
std::vector<std::string> queries = {
// load quries
std::string file_path = "data/queries/core/" + suite_name + ".txt";
auto queries = utils::read_lines(file_path.c_str());
// 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",
// execute all queries
for (auto &query : queries)
{
utils::println("Query: ", query);
"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",
"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",
"MATCH ()-[r]-() WHERE ID(r)=1 RETURN r",
"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) 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",
"MATCH ()-[r:TYPE]-() DELETE r",
"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"
// 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);
std::cout << "Query hash: " << stripped.hash << std::endl;
utils::println("Hash: ", stripped.hash);
// TODO: more robust solution (enum like)
if (work_mode == "hash_generation") continue;
auto result =
query_functions[stripped.hash](std::move(stripped.arguments));
permanent_assert(result == true,
"Result retured from query function is not true");
utils::println("------------------------ PASS");
}
return 0;

View File

@ -1,13 +1,8 @@
#include "query/hardcode/queries.hpp"
#include <random>
#ifdef BARRIER
#include "barrier/barrier.cpp"
#endif
#include "logging/default.hpp"
#include "logging/streams/stdout.hpp"
#include "query/hardcode/basic.hpp"
#include "query/strip/stripper.hpp"
#include "storage/indexes/indexes.hpp"
#include "utils/sysinfo/memory.hpp"
@ -24,16 +19,13 @@ void run(size_t n, std::string &query, Db &db)
{
auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL);
#ifdef BARRIER
auto qf = load_queries(barrier::trans(db));
#else
auto qf = load_queries(db);
#endif
auto qf = hardcode::load_basic_functions(db);
auto stripped = stripper.strip(query);
std::cout << "Running query [" << stripped.hash << "] for " << n << " time."
<< std::endl;
for (int i = 0; i < n; i++) {
for (int i = 0; i < n; i++)
{
properties_t vec = stripped.arguments;
assert(qf[stripped.hash](std::move(vec)));
}
@ -42,11 +34,7 @@ void run(size_t n, std::string &query, Db &db)
void add_edge(size_t n, Db &db)
{
auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL);
#ifdef BARRIER
auto qf = load_queries(barrier::trans(db));
#else
auto qf = load_queries(db);
#endif
auto qf = hardcode::load_basic_functions(db);
std::string query = "MATCH (n1), (n2) WHERE ID(n1)=0 AND "
"ID(n2)=1 CREATE (n1)<-[r:IS {age: "
@ -57,15 +45,17 @@ void add_edge(size_t n, Db &db)
<< " time to add edge." << std::endl;
std::vector<int64_t> vertices;
for (auto &v : db.graph.vertices.access()) {
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++) {
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);
vec[0] = Property(Int64(vertices[rand()]), Flags::Int64);
vec[1] = Property(Int64(vertices[rand()]), Flags::Int64);
assert(qf[stripped.hash](std::move(vec)));
}
}
@ -99,8 +89,9 @@ size_t size(Db &db, IndexHolder<TypeGroupVertex, std::nullptr_t> &h)
DbAccessor t(db);
size_t count = 0;
auto oin = h.get_read();
if (oin.is_present()) {
auto oin = h.get_read();
if (oin.is_present())
{
oin.get()->for_range(t).for_all([&](auto va) mutable { count++; });
}
@ -132,7 +123,7 @@ void clean_edge(Db &db)
void clear_database(Db &db)
{
std::string delete_all_vertices = "MATCH (n) DELETE n";
std::string delete_all_edges = "MATCH ()-[r]-() DELETE r";
std::string delete_all_edges = "MATCH ()-[r]-() DELETE r";
run(1, delete_all_edges, db);
run(1, delete_all_vertices, db);
@ -147,14 +138,16 @@ 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()) {
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--) {
for (auto i = acc_a.size(); i > 0; i--)
{
// TODO: compare
}
}
@ -163,14 +156,16 @@ bool equal(Db &a, Db &b)
auto acc_a = a.graph.edges.access();
auto acc_b = b.graph.edges.access();
if (acc_a.size() != acc_b.size()) {
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--) {
for (auto i = acc_a.size(); i > 0; i--)
{
// TODO: compare
}
}
@ -190,7 +185,7 @@ int main(void)
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";
std::string delete_all_vertices = "MATCH (n) DELETE n";
// ******************************* TEST 1 ********************************//
{

View File

@ -19,14 +19,18 @@ int main(int argc, char *argv[])
auto arguments = all_arguments(argc, argv);
// // query extraction
auto cypher_query = extract_query(arguments);
cout << "QUERY: " << cypher_query << endl;
auto queries = extract_queries(arguments);
auto print_visitor = new PrintVisitor(cout);
cypher::Compiler compiler;
auto tree = compiler.syntax_tree(cypher_query);
tree.root->accept(*print_visitor);
cout << endl;
for (auto &query : queries)
{
cout << "QUERY: " << query << endl;
auto print_visitor = new PrintVisitor(cout);
cypher::Compiler compiler;
auto tree = compiler.syntax_tree(query);
tree.root->accept(*print_visitor);
cout << endl;
}
return 0;
}

View File

@ -1,15 +1,11 @@
#include <iostream>
#include "query/hardcode/queries.hpp"
#ifdef BARRIER
#include "barrier/barrier.cpp"
#endif
#include "communication/bolt/v1/serialization/bolt_serializer.hpp"
#include "database/db.hpp"
#include "logging/default.hpp"
#include "logging/streams/stdout.hpp"
#include "query/hardcode/basic.hpp"
#include "query/hardcode/dressipi.hpp"
#include "query/strip/stripper.hpp"
#include "storage/edges.cpp"
#include "storage/edges.hpp"
@ -24,25 +20,23 @@ int main(int argc, char **argv)
logging::log->pipe(std::make_unique<Stdout>());
Db db;
#ifdef BARRIER
auto queries = load_queries(barrier::trans(db));
#else
auto queries = load_queries(db);
#endif
auto queries = hardcode::load_basic_functions(db);
auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL);
vector<string> history;
string command;
cout << "-- Memgraph query engine --" << endl;
do {
do
{
cout << "> ";
getline(cin, command);
history.push_back(command);
auto stripped = stripper.strip(command);
if (queries.find(stripped.hash) == queries.end()) {
if (queries.find(stripped.hash) == queries.end())
{
cout << "unsupported query" << endl;
continue;
}

View File

@ -15,18 +15,24 @@ int main(int argc, char **argv)
auto arguments = all_arguments(argc, argv);
// query extraction
auto input_query = extract_query(arguments);
auto queries = extract_queries(arguments);
QueryPreprocessor preprocessor;
auto preprocessed = preprocessor.preprocess(input_query);
cout << "QUERY: " << input_query << endl;
cout << "STRIPPED QUERY: " << preprocessed.query << endl;
cout << "QUERY HASH: " << preprocessed.hash << endl;
cout << "PROPERTIES:" << endl;
for (auto property : preprocessed.arguments) {
cout << " " << property << endl;
for (auto &query : queries)
{
auto preprocessed = preprocessor.preprocess(query);
cout << "QUERY: " << query << endl;
cout << "STRIPPED QUERY: " << preprocessed.query << endl;
cout << "QUERY HASH: " << preprocessed.hash << endl;
cout << "PROPERTIES:" << endl;
for (auto property : preprocessed.arguments) {
cout << " " << property << endl;
}
cout << "-----------------------------" << endl;
}
return 0;
}