scenario 000001 pass, dressipi scenario 1 - 3 more queries have to be implemented

This commit is contained in:
Marko Budiselic 2016-11-02 16:05:02 +01:00
parent 7d85bc2bc0
commit d45121a1a2
140 changed files with 1032 additions and 761 deletions

View File

@ -3,7 +3,7 @@ Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: false
AlignOperands: true
@ -22,15 +22,15 @@ BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: true
AfterControlStatement: false
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: false
AfterStruct: true
AfterUnion: true
BeforeCatch: false
BeforeElse: false
BeforeCatch: true
BeforeElse: true
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
@ -84,6 +84,6 @@ SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: "C++11"
TabWidth: 8
TabWidth: 4
UseTab: Never
...

View File

@ -99,7 +99,7 @@ set(catch_source_dir "${libs_dir}/Catch")
# build memgraph's cypher grammar
# copy grammar file to the build directory
FILE(COPY ${src_dir}/cypher/cypher.y DESTINATION ${CMAKE_BINARY_DIR})
FILE(COPY ${include_dir}/query/language/cypher/cypher.y DESTINATION ${CMAKE_BINARY_DIR})
# build cypher parser (only c file - cypher.c)
EXECUTE_PROCESS(
COMMAND ${lemon_dir}/lemon ${CMAKE_BINARY_DIR}/cypher.y -s
@ -164,10 +164,9 @@ FILE(COPY ${include_dir}/storage/label/label_store.hpp DESTINATION ${build_inclu
FILE(COPY ${include_dir}/storage/model/edge_map.hpp DESTINATION ${build_include_dir}/storage/model)
FILE(COPY ${include_dir}/storage/model/properties/flags.hpp DESTINATION ${build_include_dir}/storage/model/properties)
FILE(COPY ${include_dir}/query_engine/util.hpp DESTINATION ${build_include_dir}/query_engine)
FILE(COPY ${include_dir}/query_engine/i_code_cpu.hpp DESTINATION ${build_include_dir}/query_engine)
FILE(COPY ${include_dir}/query_engine/query_result.hpp DESTINATION ${build_include_dir}/query_engine)
FILE(COPY ${include_dir}/query_engine/query_stripped.hpp DESTINATION ${build_include_dir}/query_engine)
FILE(COPY ${include_dir}/query/util.hpp DESTINATION ${build_include_dir}/query)
FILE(COPY ${include_dir}/query/i_plan_cpu.hpp DESTINATION ${build_include_dir}/query)
FILE(COPY ${include_dir}/query/strip/stripped.hpp DESTINATION ${build_include_dir}/query/strip)
FILE(COPY ${include_dir}/data_structures/concurrent/concurrent_map.hpp DESTINATION ${build_include_dir}/data_structures/concurrent)
FILE(COPY ${include_dir}/data_structures/concurrent/concurrent_set.hpp DESTINATION ${build_include_dir}/data_structures/concurrent)

View File

@ -43,6 +43,15 @@ public:
bolt_encoder.message_ignored();
}
void write_empty_fields()
{
bolt_encoder.message_success();
bolt_encoder.write_map_header(1);
bolt_encoder.write_string("fields");
write_list_header(0);
chunk();
}
void write_fields(const std::vector<std::string> &fields)
{
// TODO: that should be one level below?

View File

@ -2,7 +2,7 @@
#include "communication/bolt/v1/states/state.hpp"
#include "communication/bolt/v1/session.hpp"
#include "query_engine/query_engine.hpp"
#include "query/engine.hpp"
namespace bolt
{

View File

@ -3,7 +3,7 @@
#include <string>
#include "communication/bolt/v1/packing/codes.hpp"
#include "query_engine/exceptions/exceptions.hpp"
#include "query/exception/decoder_exception.hpp"
#include "utils/bswap.hpp"
#include "utils/types/byte.hpp"

View File

@ -0,0 +1,14 @@
#pragma once
#include "logging/default.hpp"
class Loggable
{
public:
Loggable(const std::string& name) : logger(logging::log->logger(name)) {}
virtual ~Loggable() {}
protected:
Logger logger;
};

View File

@ -0,0 +1,10 @@
#pragma once
#include "query/ir/tree/node.hpp"
class Backend
{
public:
virtual void process(ir::Node *node) = 0;
virtual ~Backend() {}
};

View File

@ -0,0 +1,40 @@
#pragma once
#include <stdexcept>
#include <string>
#include "query/backend/backend.hpp"
class CodeGenerator : public Backend
{
private:
struct Code
{
public:
void println(const std::string &line)
{
code.append(line + "\n");
line_no++;
}
void save(const std::string &)
{
throw std::runtime_error("TODO: implementation");
}
void reset() { code = ""; }
std::string code;
uint64_t line_no;
};
protected:
Code code;
public:
void emit(const std::string &line) { code.println(line); }
void save(const std::string &path) { code.save(path); }
void reset() { code.reset(); }
};

View File

@ -0,0 +1,22 @@
#pragma once
#include "query/backend/code_generator.hpp"
/*
* Traverses the intermediate representation tree and generates
* C++ code.
*/
class CppCodeGenerator : public CodeGenerator
{
public:
CppCodeGenerator()
{
throw std::runtime_error("TODO: implementation");
}
void process(ir::Node *) override
{
throw std::runtime_error("TODO: implementation");
}
};

View File

@ -1,11 +1,14 @@
#pragma once
// !! DEPRICATED !!
#include <string>
#include "query_engine/util.hpp"
#include "query/util.hpp"
struct Code
class Code
{
public:
std::string code;
void reset() { code = ""; }
@ -152,6 +155,12 @@ const std::string print_property =
}
// DELETE
const std::string detach_delete_all_nodes =
"t.vertex_access().fill().isolated().for_all("
" [&](auto a) {{ a.remove(); }});";
const std::string delete_all_detached_nodes =
"t.vertex_access().fill().isolated().for_all(\n"
" [&](auto a) {{ a.remove(); }});\n"
" stream.write_empty_fields();\n"
" stream.write_meta(\"w\");\n";
const std::string delete_whole_graph =
"t.edge_access().fill().for_all(\n"
" [&](auto e) { e.remove(); }\n"
");\n" + delete_all_detached_nodes;

View File

@ -2,10 +2,10 @@
#include <vector>
#include "query_engine/code_generator/cypher_state.hpp"
#include "query_engine/code_generator/handlers/all.hpp"
#include "query_engine/code_generator/query_action.hpp"
#include "query_engine/exceptions/exceptions.hpp"
#include "query/backend/cpp_old/cypher_state.hpp"
#include "query/backend/cpp_old/handlers/all.hpp"
#include "query/backend/cpp_old/query_action.hpp"
#include "query/exception/cpp_code_generator.hpp"
class CppGenerator
{
@ -24,11 +24,12 @@ public:
{
std::string code = "";
for (uint64_t i = processed_index; i < unprocessed_index; ++i) {
for (uint64_t i = processed_index; i < unprocessed_index; ++i)
{
auto &action = actions.at(i);
auto query_action = action.first;
if (action_functions.find(query_action) == action_functions.end())
throw CppGeneratorException(
throw CppCodeGeneratorException(
"Query Action Function is not defined");
auto &action_data = action.second;
code += action_functions[query_action](_cypher_data, action_data);

View File

@ -0,0 +1,65 @@
#pragma once
// DEPRICATED!
#include "config/config.hpp"
#include "query/frontend/cypher/traverser.hpp"
#include "query/language/cypher/errors.hpp"
#include "template_engine/engine.hpp"
#include "utils/string/file.hpp"
#include "utils/type_discovery.hpp"
template <typename Stream>
class CypherBackend
{
public:
CypherBackend() : logger(logging::log->logger("CypherBackend"))
{
// load template file
#ifdef BARRIER
std::string template_path =
CONFIG(config::BARRIER_TEMPLATE_CPU_CPP_PATH);
#else
std::string template_path = CONFIG(config::TEMPLATE_CPU_CPP_PATH);
#endif
template_file = utils::read_file(template_path.c_str());
}
template <typename Tree>
void generate_code(const Tree &tree, const std::string &query,
const uint64_t stripped_hash, const std::string &path)
{
CppTraverser cpp_traverser;
cpp_traverser.reset();
try {
tree.root->accept(cpp_traverser);
} catch (const CypherSemanticError &e) {
throw e;
} catch (const std::exception &e) {
logger.error("AST traversal error: {}", std::string(e.what()));
throw e;
}
// save the code
std::string generated = template_engine::render(
template_file, {{"class_name", "CodeCPU"},
{"stripped_hash", std::to_string(stripped_hash)},
{"query", query},
#ifdef BARRIER
{"stream", "RecordStream<::io::Socket>"},
#else
{"stream", type_name<Stream>().to_string()},
#endif
{"code", cpp_traverser.code}});
logger.trace("generated code: {}", generated);
utils::write_file(generated, path);
}
protected:
Logger logger;
private:
std::string template_file;
};

View File

@ -5,8 +5,8 @@
#include <string>
#include <vector>
#include "query_engine/code_generator/namer.hpp"
#include "query_engine/exceptions/exceptions.hpp"
#include "query/backend/cpp_old/namer.hpp"
#include "query/exception/cpp_code_generator.hpp"
#include "storage/model/properties/flags.hpp"
// main states that are used while ast is traversed
@ -50,7 +50,7 @@ enum class EntitySource : uint8_t
class CypherStateData
{
public:
using tags_type = std::vector<std::string>;
using tags_type = std::vector<std::string>;
using properties_type = std::map<std::string, int64_t>;
private:
@ -96,25 +96,25 @@ public:
void node_matched(const std::string &name)
{
entity_type[name] = EntityType::Node;
entity_type[name] = EntityType::Node;
entity_status[name] = EntityStatus::Matched;
}
void node_created(const std::string &name)
{
entity_type[name] = EntityType::Node;
entity_type[name] = EntityType::Node;
entity_status[name] = EntityStatus::Created;
}
void relationship_matched(const std::string &name)
{
entity_type[name] = EntityType::Relationship;
entity_type[name] = EntityType::Relationship;
entity_status[name] = EntityStatus::Matched;
}
void relationship_created(const std::string &name)
{
entity_type[name] = EntityType::Relationship;
entity_type[name] = EntityType::Relationship;
entity_status[name] = EntityStatus::Created;
}
@ -127,7 +127,7 @@ public:
auto tags(const std::string &name) const
{
if (entity_tags.find(name) == entity_tags.end())
throw CppGeneratorException("No tags for specified entity");
throw CppCodeGeneratorException("No tags for specified entity");
return entity_tags.at(name);
}
@ -138,17 +138,24 @@ public:
void tag(const std::string &name, const std::string &new_tag)
{
if (entity_tags.find(name) == entity_tags.end()) {
if (entity_tags.find(name) == entity_tags.end())
{
entity_tags[name] = std::vector<std::string>{};
}
entity_tags[name].emplace_back(new_tag);
}
auto has_properties(const std::string& name)
{
return entity_properties.find(name) != entity_properties.end();
}
// entity properties
auto properties(const std::string &name) const
{
if (entity_properties.find(name) == entity_properties.end())
throw CppGeneratorException("No properties for specified entity");
throw CppCodeGeneratorException(
"No properties for specified entity: " + name);
return entity_properties.at(name);
}
@ -160,7 +167,8 @@ public:
void index(const std::string &entity, const std::string &property,
int64_t index)
{
if (entity_properties.find(entity) == entity_properties.end()) {
if (entity_properties.find(entity) == entity_properties.end())
{
entity_properties[entity] = properties_type{};
}
entity_properties[entity][property] = index;
@ -169,12 +177,13 @@ public:
auto index(const std::string &entity, const std::string &property_name)
{
if (entity_properties.find(entity) == entity_properties.end())
throw CppGeneratorException("No properties for specified entity");
throw CppCodeGeneratorException(
"No properties for specified entity");
auto properties = entity_properties.at(entity);
if (properties.find(property_name) == properties.end())
throw CppGeneratorException(
throw CppCodeGeneratorException(
"No property for specified property name");
return properties[property_name];
@ -186,19 +195,21 @@ public:
{
// TODO: find out smarter way it's not hard
std::string print =
"std::map<std::string, int64_t> " + variable_name + " = ";
print += "{";
"std::map<std::string, int64_t> " + variable_name + " = {";
auto indices = entity_properties.at(name);
size_t i = 0;
iter_t it = indices.begin();
size_t i = 0;
iter_t it = indices.begin();
for (; it != indices.end(); ++it, ++i)
{
print +=
"{\"" + it->first + "\"," + std::to_string(it->second) + "}";
if (i < indices.size() - 1)
print += ",";
if (i < indices.size() - 1) print += ",";
}
print += "};";
return print;
}
};

View File

@ -0,0 +1,11 @@
#pragma once
// TODO: refactor build state machine instead of ifs
#include "query/backend/cpp_old/handlers/create.hpp"
#include "query/backend/cpp_old/handlers/delete.hpp"
#include "query/backend/cpp_old/handlers/match.hpp"
#include "query/backend/cpp_old/handlers/return.hpp"
#include "query/backend/cpp_old/handlers/set.hpp"
#include "query/backend/cpp_old/handlers/transaction_begin.hpp"
#include "query/backend/cpp_old/handlers/transaction_commit.hpp"

View File

@ -1,6 +1,6 @@
#pragma once
#include "query_engine/code_generator/handlers/includes.hpp"
#include "includes.hpp"
auto create_query_action =
[](CypherStateData &cypher_data,
@ -35,7 +35,8 @@ auto create_query_action =
// find start and end node
auto &relationships_data = action_data.relationship_data;
if (relationships_data.find(name) == relationships_data.end())
throw CodeGenerationError("Unable to find data for: " + name);
throw CppCodeGeneratorException("Unable to find data for: " +
name);
auto &relationship_data = relationships_data.at(name);
auto left_node = relationship_data.nodes.first;
auto right_node = relationship_data.nodes.second;
@ -43,12 +44,12 @@ auto create_query_action =
// TODO: If node isn't already matched or created it has to be
// created here. It is not possible for now.
if (cypher_data.status(left_node) != EntityStatus::Matched) {
throw SemanticError("Create Relationship: node " + left_node +
" can't be found");
throw CypherSemanticError("Create Relationship: node " +
left_node + " can't be found");
}
if (cypher_data.status(right_node) != EntityStatus::Matched) {
throw SemanticError("Create Relationship: node " + right_node +
" can't be found");
throw CypherSemanticError("Create Relationship: node " +
right_node + " can't be found");
}
// create relationship
@ -64,19 +65,6 @@ auto create_query_action =
code += code_line(code::set_type, name, tag);
}
// define direction
// if (relationship_data.direction == Direction::Right) {
// code += code_line(code::node_out, left_node, name);
// code += code_line(code::node_in, right_node, name);
// code += code_line(code::edge_from, name, left_node);
// code += code_line(code::edge_to, name, right_node);
// } else if (relationship_data.direction == Direction::Left) {
// code += code_line(code::node_out, right_node, name);
// code += code_line(code::node_in, left_node, name);
// code += code_line(code::edge_from, name, right_node);
// code += code_line(code::edge_to, name, left_node);
// }
// mark relationship as created
cypher_data.relationship_created(name);
}

View File

@ -1,6 +1,6 @@
#pragma once
#include "query_engine/code_generator/handlers/includes.hpp"
#include "includes.hpp"
auto delete_query_action =
[](CypherStateData &cypher_data,
@ -10,8 +10,11 @@ auto delete_query_action =
for (auto const &kv : action_data.actions) {
auto entity = kv.first;
if (kv.second == ClauseAction::DeleteNode) {
code += code_line(detach_delete_all_nodes);
if (kv.second == ClauseAction::DeleteNode && action_data.is_detach) {
code += code_line(delete_whole_graph);
}
if (kv.second == ClauseAction::DeleteNode && !action_data.is_detach) {
code += code_line(delete_all_detached_nodes);
}
if (kv.second == ClauseAction::DeleteRelationship) {
code += code_line("// DELETE Relationship({})", entity);

View File

@ -6,12 +6,13 @@
#include <utility>
#include <vector>
#include "query_engine/code_generator/cypher_state.hpp"
#include "query_engine/code_generator/namer.hpp"
#include "query_engine/code_generator/query_action_data.hpp"
#include "query_engine/exceptions/errors.hpp"
#include "query_engine/traverser/code.hpp"
#include "query_engine/util.hpp"
#include "query/backend/cpp_old/cypher_state.hpp"
#include "query/backend/cpp_old/namer.hpp"
#include "query/backend/cpp_old/query_action_data.hpp"
#include "query/backend/cpp_old/code.hpp"
#include "query/util.hpp"
#include "query/exception/cpp_code_generator.hpp"
#include "query/language/cypher/errors.hpp"
using ParameterIndexKey::Type::InternalId;
using Direction = RelationshipData::Direction;

View File

@ -1,6 +1,6 @@
#pragma once
#include "query_engine/code_generator/handlers/includes.hpp"
#include "includes.hpp"
namespace
{
@ -49,7 +49,7 @@ auto match_query_action =
}
if (place == entity_search::search_label_index) {
if (action_data.entity_data.at(name).tags.size() > 1) {
throw SemanticError("Multiple label match (currently NOT supported)");
throw CypherSemanticError("Multiple label match (currently NOT supported)");
}
cypher_data.source(name, EntitySource::LabelIndex);
cypher_data.tags(name, action_data.entity_data.at(name).tags);
@ -72,7 +72,7 @@ auto match_query_action =
}
if (place == entity_search::search_type_index) {
if (action_data.entity_data.at(name).tags.size() > 1) {
throw SemanticError("Multiple type match (currently NOT supported)");
throw CypherSemanticError("Multiple type match (currently NOT supported)");
}
cypher_data.source(name, EntitySource::TypeIndex);
cypher_data.tags(name, action_data.entity_data.at(name).tags);

View File

@ -1,6 +1,8 @@
#pragma once
#include "query_engine/code_generator/handlers/includes.hpp"
#include "includes.hpp"
// TODO: total fuck up; replace this with IR + Backend
auto return_query_action =
[](CypherStateData &cypher_data,
@ -15,8 +17,8 @@ auto return_query_action =
{
auto &entity = element.entity;
if (!cypher_data.exist(entity))
throw SemanticError(
if (!cypher_data.exist(entity))
throw CypherSemanticError(
fmt::format("{} couldn't be found (RETURN clause).", entity));
if (element.is_entity_only())
@ -36,42 +38,49 @@ auto return_query_action =
code += code_line(code::write_all_vertices, entity);
else if (cypher_data.type(entity) == EntityType::Relationship)
code += code_line(code::write_all_edges, entity);
}
// the client will receive entities from label index
if (cypher_data.source(entity) == EntitySource::LabelIndex)
if (cypher_data.status(entity) != EntityStatus::Created &&
cypher_data.source(entity) == EntitySource::LabelIndex)
{
if (cypher_data.tags(entity).size() == 0)
throw CppGeneratorException("node has no labels");
throw CppCodeGeneratorException("node has no labels");
// node and no other property
if (cypher_data.type(entity) == EntityType::Node) {
auto label = cypher_data.tags(entity).at(0);
if (cypher_data.properties(entity).size() > 0)
if (cypher_data.type(entity) == EntityType::Node)
{
auto label = cypher_data.tags(entity).at(0);
if (cypher_data.has_properties(entity))
{
code += code_line(code::find_and_write_vertices_by_label_and_properties,
cypher_data.print_indices(entity), label, entity);
code += code_line(
code::
find_and_write_vertices_by_label_and_properties,
cypher_data.print_indices(entity), label, entity);
}
else
{
code += code_line(code::find_and_write_vertices_by_label,
entity, label);
code +=
code_line(code::find_and_write_vertices_by_label,
entity, label);
}
}
}
if (cypher_data.source(entity) == EntitySource::TypeIndex)
{
if (cypher_data.type(entity) == EntityType::Relationship) {
if (cypher_data.type(entity) == EntityType::Relationship)
{
if (cypher_data.tags(entity).size() == 0)
throw CppGeneratorException("edge has no tag");
auto type = cypher_data.tags(entity).at(0);
throw CppCodeGeneratorException("edge has no tag");
auto type = cypher_data.tags(entity).at(0);
code += code_line(code::find_and_write_edges_by_type,
entity, type);
}
}
}
else if (element.is_projection())
}
else if (element.is_projection())
{
code += code_line("// TODO: implement projection");
// auto &property = element.property;
@ -94,10 +103,11 @@ auto return_query_action =
if (cypher_data.source(name) == EntitySource::LabelIndex)
{
auto tags = cypher_data.tags(name);
if (tags.size() == 1) {
if (tags.size() == 1)
{
auto label = tags.at(0);
code += code_line(code::count_vertices_for_one_label,
name, label);
code += code_line(code::count_vertices_for_one_label, name,
label);
}
// TODO: do for more, isn't easy because of
// multiple iterators, but we have iterator infrastructure

View File

@ -1,6 +1,6 @@
#pragma once
#include "query_engine/code_generator/handlers/includes.hpp"
#include "includes.hpp"
auto set_query_action = [](CypherStateData &cypher_data,
const QueryActionData &action_data) -> std::string {

View File

@ -1,6 +1,6 @@
#pragma once
#include "query_engine/code_generator/handlers/includes.hpp"
#include "includes.hpp"
auto transaction_begin_action = [](CypherStateData &,
const QueryActionData &) -> std::string {

View File

@ -1,6 +1,6 @@
#pragma once
#include "query_engine/code_generator/handlers/includes.hpp"
#include "includes.hpp"
auto transaction_commit_action = [](CypherStateData &,
const QueryActionData &) -> std::string {

View File

@ -4,9 +4,9 @@
#include <map>
#include <vector>
#include "query_engine/code_generator/clause_action.hpp"
#include "query_engine/code_generator/entity_search.hpp"
#include "query_engine/exceptions/exceptions.hpp"
#include "query/backend/cpp_old/clause_action.hpp"
#include "query/backend/cpp_old/entity_search.hpp"
#include "query/exception/cpp_code_generator.hpp"
#include "storage/model/properties/all.hpp"
#include "utils/assert.hpp"
#include "utils/underlying_cast.hpp"
@ -118,6 +118,7 @@ struct QueryActionData
std::map<std::string, EntityData> entity_data;
std::map<std::string, RelationshipData> relationship_data;
std::vector<ReturnElement> return_elements;
bool is_detach;
CypherStateMachine csm;
QueryActionData() = default;
@ -146,7 +147,7 @@ struct QueryActionData
auto get_entity_property(const std::string &entity) const
{
if (entity_data.find(entity) == entity_data.end())
throw CppGeneratorException("Entity " + entity + " doesn't exist");
throw CppCodeGeneratorException("Entity " + entity + " doesn't exist");
return entity_data.at(entity);
}
@ -154,7 +155,7 @@ struct QueryActionData
auto get_tags(const std::string& entity) const
{
if (entity_data.find(entity) == entity_data.end())
throw CppGeneratorException("Entity " + entity + "doesn't exist");
throw CppCodeGeneratorException("Entity " + entity + "doesn't exist");
return entity_data.at(entity).tags;
}

View File

@ -0,0 +1,3 @@
#pragma once
// TODO: implementation

View File

@ -1,6 +1,6 @@
#pragma once
#include "query_engine/i_code_cpu.hpp"
#include "query/i_plan_cpu.hpp"
#include "dc/dynamic_lib.hpp"
namespace
@ -12,7 +12,7 @@ class MemgraphDynamicLib
public:
using produce = produce_t<Stream>;
using destruct = destruct_t<Stream>;
using lib_object = ICodeCPU<Stream>;
using lib_object = IPlanCPU<Stream>;
};
template <typename Stream>

View File

@ -2,9 +2,10 @@
#include "database/db.hpp"
#include "logging/default.hpp"
#include "program_executor.hpp"
#include "program_loader.hpp"
#include "query_result.hpp"
#include "query/exception/query_engine.hpp"
#include "query/plan/program.hpp"
#include "query/plan/program_loader.hpp"
#include "query/plan/program_executor.hpp"
/*
* Current arhitecture:
@ -20,8 +21,7 @@ class QueryEngine
public:
QueryEngine() : logger(logging::log->logger("QueryEngine")) {}
auto execute(const std::string &query, Db &db,
Stream &stream)
auto execute(const std::string &query, Db &db, Stream &stream)
{
try {
auto program = program_loader.load(query);
@ -38,6 +38,8 @@ public:
logger.error("QueryEngineException: {}", std::string(e.what()));
// return false;
throw e;
} catch (std::exception &e) {
throw e;
}
}

View File

@ -0,0 +1,9 @@
#pragma once
#include "utils/exceptions/basic_exception.hpp"
class CppCodeGeneratorException : public BasicException
{
public:
using BasicException::BasicException;
};

View File

@ -0,0 +1,9 @@
#pragma once
#include "utils/exceptions/basic_exception.hpp"
class DecoderException : public BasicException
{
public:
using BasicException::BasicException;
};

View File

@ -0,0 +1,9 @@
#pragma once
#include "utils/exceptions/basic_exception.hpp"
class OutOfMemory : public BasicException
{
public:
using BasicException::BasicException;
};

View File

@ -0,0 +1,9 @@
#pragma once
#include "utils/exceptions/basic_exception.hpp"
class PlanCompilationException : public BasicException
{
public:
using BasicException::BasicException;
};

View File

@ -0,0 +1,9 @@
#pragma once
#include "utils/exceptions/basic_exception.hpp"
class PlanExecutionException : public BasicException
{
public:
using BasicException::BasicException;
};

View File

@ -0,0 +1,9 @@
#pragma once
#include "utils/exceptions/basic_exception.hpp"
class QueryEngineException : public BasicException
{
public:
using BasicException::BasicException;
};

View File

@ -0,0 +1,33 @@
#pragma once
#include <string>
#include "logging/loggable.hpp"
#include "query/language/cypher/compiler.hpp"
// DEPRICATED
namespace cypher
{
class Frontend
{
public:
Frontend() {}
auto generate_ir(const std::string& query)
{
try {
return compiler.syntax_tree(query);
} catch (const BasicException &e) {
// logger.error("Parsing error while processing query: {}", query);
// logger.error(std::string(e.what()));
throw e;
}
}
private:
cypher::Compiler compiler;
};
}

View File

@ -2,13 +2,13 @@
#include <string>
#include "cypher/visitor/traverser.hpp"
#include "query_engine/code_generator/cpp_generator.hpp"
#include "query_engine/code_generator/entity_search.hpp"
#include "query_engine/code_generator/structures.hpp"
#include "query_engine/exceptions/exceptions.hpp"
#include "query_engine/traverser/code.hpp"
#include "logging/default.hpp"
#include "query/backend/cpp_old/code.hpp"
#include "query/backend/cpp_old/cpp_generator.hpp"
#include "query/backend/cpp_old/entity_search.hpp"
#include "query/backend/cpp_old/structures.hpp"
#include "query/language/cypher/errors.hpp"
#include "query/language/cypher/visitor/traverser.hpp"
struct SetElementState
{
@ -107,9 +107,10 @@ public:
void semantic_check() const
{
if (!has_return)
throw SemanticError("The query doesn't have RETURN clause. Next "
"releases will support query without RETURN "
"clause");
throw CypherSemanticError(
"The query doesn't have RETURN clause. Next "
"releases will support query without RETURN "
"clause");
}
void visit(ast::WriteQuery &write_query) override
@ -258,11 +259,8 @@ public:
Traverser::visit(ast_node);
// this is here because of RETURN clause
// CREATE (n {...}) RETURN n
if (cypher_data.status(name) != EntityStatus::Matched &&
state == CypherState::Create)
{
state == CypherState::Create) {
cypher_data.node_created(name);
}
}
@ -300,8 +298,7 @@ public:
auto &cypher_data = generator.cypher_data();
auto &action_data = generator.action_data();
if (!ast_relationship.has_name())
return;
if (!ast_relationship.has_name()) return;
entity = ast_relationship.name();
using ast_direction = ast::Relationship::Direction;
@ -362,9 +359,9 @@ public:
if (ast_relationship_type_list.has_value()) {
auto type = ast_relationship_type_list.value->name;
action_data.add_entity_tag(entity, type);
action_data.csm.search_cost(
entity, entity_search::search_type_index,
entity_search::type_cost);
action_data.csm.search_cost(entity,
entity_search::search_type_index,
entity_search::type_cost);
}
Traverser::visit(ast_relationship_type_list);
@ -411,7 +408,8 @@ public:
// update action data
auto &action_data = generator.action_data();
action_data.parameter_index.emplace(ParameterIndexKey(entity, prop), index);
action_data.parameter_index.emplace(ParameterIndexKey(entity, prop),
index);
action_data.add_entitiy_property(entity, prop);
// update cypher data
@ -469,7 +467,7 @@ public:
auto entity_type = cypher_data.type(entity);
if (entity_type == EntityType::None)
throw SemanticError("Entity (" + entity + ") doesn't exist");
throw CypherSemanticError("Entity (" + entity + ") doesn't exist");
auto &action_data = generator.action_data();
@ -515,27 +513,27 @@ public:
Traverser::visit(ast_set_value);
}
void visit(ast::Delete& ast_delete) override
void visit(ast::Delete &ast_delete) override
{
code += generator.generate();
state = CypherState::Delete;
generator.add_action(QueryAction::Delete);
auto &action_data = generator.add_action(QueryAction::Delete);
Traverser::visit(ast_delete);
code += generator.generate();
}
void visit(ast::CountFunction& ast_count) override
void visit(ast::CountFunction &ast_count) override
{
auto &action_data = generator.action_data();
auto &cypher_data = generator.cypher_data();
// if (state == CypherState::Return)
// {
action_data.actions[ast_count.argument] = ClauseAction::ReturnCount;
action_data.actions[ast_count.argument] = ClauseAction::ReturnCount;
// }
}
};

View File

@ -0,0 +1,10 @@
#pragma once
namespace opencypher
{
class Fronted
{
};
}

View File

@ -0,0 +1,3 @@
#pragma once
// TODO: implementation

View File

@ -18,6 +18,7 @@ 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"
@ -37,7 +38,7 @@ namespace barrier
#include "utils/iterator/iterator.hpp"
#include "utils/option_ptr.hpp"
#include "utils/reference_wrapper.hpp"
#include "query_engine/util.hpp"
#include "query/util.hpp"
#endif

View File

@ -1,6 +1,6 @@
#pragma once
#include "query_engine/query_stripped.hpp"
#include "query/strip/stripped.hpp"
#ifdef BARRIER
#include "barrier/barrier.hpp"
@ -12,19 +12,19 @@
#endif
template <typename Stream>
class ICodeCPU
class IPlanCPU
{
public:
#ifdef BARRIER
virtual bool run(barrier::Db &db, code_args_t &args, Stream &stream) = 0;
virtual bool run(barrier::Db &db, plan_args_t &args, Stream &stream) = 0;
#else
virtual bool run(Db &db, code_args_t &args, Stream &stream) = 0;
virtual bool run(Db &db, plan_args_t &args, Stream &stream) = 0;
#endif
virtual ~ICodeCPU() {}
virtual ~IPlanCPU() {}
};
template <typename Stream>
using produce_t = ICodeCPU<Stream> *(*)();
using produce_t = IPlanCPU<Stream> *(*)();
template <typename Stream>
using destruct_t = void (*)(ICodeCPU<Stream> *);
using destruct_t = void (*)(IPlanCPU<Stream> *);

View File

View File

View File

@ -0,0 +1,27 @@
#pragma once
#include <memory>
#include <vector>
#include "query/backend/backend.hpp"
namespace ir
{
class Node
{
public:
virtual ~Node() {}
virtual void accept(Backend* visitor)
{
for (auto &child : childs)
{
visitor->process(child.get());
}
}
std::vector<std::unique_ptr<Node>> childs;
Node *parent;
};
}

View File

@ -0,0 +1,5 @@
#pragma once
class Query : public Node
{
};

View File

View File

View File

View File

View File

@ -8,10 +8,11 @@ namespace ast
struct Delete : public AstNode<Delete>
{
Delete(Identifier* identifier)
: identifier(identifier) {}
Delete(Identifier* identifier, bool is_detached = false)
: identifier(identifier), is_detached(is_detached) {}
Identifier* identifier;
bool is_detached;
};
}

View File

@ -21,13 +21,13 @@
printf("possible token: %s\n", yyTokenName[i]);
}
}
throw SyntaxError(TOKEN->value);
throw CypherSyntaxError(TOKEN->value);
#endif
}
%stack_overflow
{
throw ParserError("Parser stack overflow");
throw CypherParsingError("Parser stack overflow");
}
%name cypher_parser
@ -38,10 +38,10 @@
#include <cassert>
#include <cstdlib>
#include "cypher/token.hpp"
#include "cypher/errors.hpp"
#include "cypher/ast/ast.hpp"
#include "cypher/ast/tree.hpp"
#include "query/language/cypher/token.hpp"
#include "query/language/cypher/errors.hpp"
#include "query/language/cypher/ast/ast.hpp"
#include "query/language/cypher/ast/tree.hpp"
#define DEBUG(X) std::cout << "PARSER: " << X << std::endl
}
@ -198,9 +198,15 @@ match_clause(M) ::= MATCH pattern_list(P) where_clause(W). {
}
%type delete_clause {ast::Delete*}
// TODO: add DETACH DELETE
// TODO: expression list support
delete_clause(D) ::= DELETE idn(I). {
D = ast->create<ast::Delete>(I);
D = ast->create<ast::Delete>(I, false);
}
delete_clause(D) ::= DETACH DELETE idn(I). {
D = ast->create<ast::Delete>(I, true);
}
// ---- pattern list

View File

@ -3,7 +3,7 @@
#include <iostream>
#include <stack>
#include "cypher/visitor/traverser.hpp"
#include "query/language/cypher/visitor/traverser.hpp"
class PrintVisitor : public Traverser
{
@ -13,52 +13,48 @@ public:
public:
friend class Entry;
Printer(std::ostream& stream, const std::string& header)
Printer(std::ostream &stream, const std::string &header)
: stream(stream)
{
// stream << header;
}
~Printer()
{
stream << std::endl;
}
~Printer() { stream << std::endl; }
class Entry
{
public:
Entry(Printer& printer) : printer(printer), valid(true)
Entry(Printer &printer) : printer(printer), valid(true)
{
printer.level++;
for(size_t i = 1; i < printer.level; ++i)
for (size_t i = 1; i < printer.level; ++i)
printer.stream << "| ";
printer.stream << "+--";
}
Entry(const Entry&) = delete;
Entry(const Entry &) = delete;
Entry(Entry&& other) : printer(other.printer), valid(true)
Entry(Entry &&other) : printer(other.printer), valid(true)
{
other.valid = false;
}
~Entry()
{
if(valid)
printer.level--;
if (valid) printer.level--;
}
template <class T>
Entry& operator<<(const T& item)
Entry &operator<<(const T &item)
{
printer.stream << item;
return *this;
}
private:
Printer& printer;
Printer &printer;
bool valid;
};
@ -68,7 +64,7 @@ public:
return std::move(Entry(*this));
}
Entry advance(const std::string& text)
Entry advance(const std::string &text)
{
stream << std::endl;
auto entry = Entry(*this);
@ -77,116 +73,115 @@ public:
}
private:
std::ostream& stream;
std::ostream &stream;
size_t level = 0;
};
PrintVisitor(std::ostream& stream)
: printer(stream, "Printing AST") {}
PrintVisitor(std::ostream &stream) : printer(stream, "Printing AST") {}
void visit(ast::Start& start) override
void visit(ast::Start &start) override
{
auto entry = printer.advance("Start");
Traverser::visit(start);
}
void visit(ast::ReadQuery& read_query) override
void visit(ast::ReadQuery &read_query) override
{
auto entry = printer.advance("Read Query");
Traverser::visit(read_query);
}
void visit(ast::ReadWriteQuery& query) override
void visit(ast::ReadWriteQuery &query) override
{
auto entry = printer.advance("Read Write Query");
Traverser::visit(query);
}
void visit(ast::Match& match) override
void visit(ast::Match &match) override
{
auto entry = printer.advance("Match");
Traverser::visit(match);
}
void visit(ast::Pattern& pattern) override
void visit(ast::Pattern &pattern) override
{
auto entry = printer.advance("Pattern");
Traverser::visit(pattern);
}
void visit(ast::PatternExpr& pattern_expr) override
void visit(ast::PatternExpr &pattern_expr) override
{
auto entry = printer.advance("Pattern Expression");
Traverser::visit(pattern_expr);
}
void visit(ast::PatternList& pattern_list) override
void visit(ast::PatternList &pattern_list) override
{
auto entry = printer.advance("Pattern List");
Traverser::visit(pattern_list);
}
void visit(ast::Node& node) override
void visit(ast::Node &node) override
{
auto entry = printer.advance("Node");
Traverser::visit(node);
}
void visit(ast::Alias& alias) override
void visit(ast::Alias &alias) override
{
auto entry = printer.advance();
entry << "Alias: '" << alias.name << "' AS '" << alias.alias << "'";
}
void visit(ast::Identifier& idn) override
void visit(ast::Identifier &idn) override
{
auto entry = printer.advance();
entry << "Identifier '" << idn.name << "'";
}
void visit(ast::IdentifierList& list) override
void visit(ast::IdentifierList &list) override
{
auto entry = printer.advance("Identifier List");
Traverser::visit(list);
}
void visit(ast::Return& return_clause) override
void visit(ast::Return &return_clause) override
{
auto entry = printer.advance("Return");
Traverser::visit(return_clause);
}
void visit(ast::Distinct& distinct) override
void visit(ast::Distinct &distinct) override
{
auto entry = printer.advance("Distinct");
Traverser::visit(distinct);
}
void visit(ast::Accessor& accessor) override
void visit(ast::Accessor &accessor) override
{
auto entry = printer.advance("Accessor");
Traverser::visit(accessor);
}
void visit(ast::Boolean& boolean) override
void visit(ast::Boolean &boolean) override
{
auto entry = printer.advance();
entry << "Boolean " << boolean.value;
}
void visit(ast::Float& floating) override
void visit(ast::Float &floating) override
{
auto entry = printer.advance();
entry << "Float " << floating.value;
}
void visit(ast::Integer& integer) override
void visit(ast::Integer &integer) override
{
auto entry = printer.advance();
entry << "Integer " << integer.value;
}
void visit(ast::Long& ast_long) override
void visit(ast::Long &ast_long) override
{
auto entry = printer.advance();
entry << "Long " << ast_long.value;
@ -198,224 +193,227 @@ public:
// entry << "ULong " << ulong.value;
// }
void visit(ast::String& string) override
void visit(ast::String &string) override
{
auto entry = printer.advance();
entry << "String " << string.value;
}
void visit(ast::InternalIdExpr& internal_id) override
void visit(ast::InternalIdExpr &internal_id) override
{
auto entry = printer.advance("InternalId");
Traverser::visit(internal_id);
}
void visit(ast::Property& property) override
void visit(ast::Property &property) override
{
auto entry = printer.advance("Property");
Traverser::visit(property);
}
void visit(ast::And& and_expr) override
void visit(ast::And &and_expr) override
{
auto entry = printer.advance("And");
Traverser::visit(and_expr);
}
void visit(ast::Or& or_expr) override
void visit(ast::Or &or_expr) override
{
auto entry = printer.advance("Or");
Traverser::visit(or_expr);
}
void visit(ast::Lt& lt_expr) override
void visit(ast::Lt &lt_expr) override
{
auto entry = printer.advance("Less Than");
Traverser::visit(lt_expr);
}
void visit(ast::Gt& gt_expr) override
void visit(ast::Gt &gt_expr) override
{
auto entry = printer.advance("Greater Than");
Traverser::visit(gt_expr);
}
void visit(ast::Ge& ge_expr) override
void visit(ast::Ge &ge_expr) override
{
auto entry = printer.advance("Greater od Equal");
Traverser::visit(ge_expr);
}
void visit(ast::Le& le_expr) override
void visit(ast::Le &le_expr) override
{
auto entry = printer.advance("Less or Equal");
Traverser::visit(le_expr);
}
void visit(ast::Eq& eq_expr) override
void visit(ast::Eq &eq_expr) override
{
auto entry = printer.advance("Equal");
Traverser::visit(eq_expr);
}
void visit(ast::Ne& ne_expr) override
void visit(ast::Ne &ne_expr) override
{
auto entry = printer.advance("Not Equal");
Traverser::visit(ne_expr);
}
void visit(ast::Plus& plus) override
void visit(ast::Plus &plus) override
{
auto entry = printer.advance("Plus");
Traverser::visit(plus);
}
void visit(ast::Minus& minus) override
void visit(ast::Minus &minus) override
{
auto entry = printer.advance("Minus");
Traverser::visit(minus);
}
void visit(ast::Star& star) override
void visit(ast::Star &star) override
{
auto entry = printer.advance("Star");
Traverser::visit(star);
}
void visit(ast::Slash& slash) override
void visit(ast::Slash &slash) override
{
auto entry = printer.advance("Slash");
Traverser::visit(slash);
}
void visit(ast::Rem& rem) override
void visit(ast::Rem &rem) override
{
auto entry = printer.advance("Rem (%)");
Traverser::visit(rem);
}
void visit(ast::CountFunction& count) override
void visit(ast::CountFunction &count) override
{
auto entry = printer.advance("Count ");
entry << count.name << "(" << count.argument << ")";
}
void visit(ast::LabelsFunction& labels) override
void visit(ast::LabelsFunction &labels) override
{
auto entry = printer.advance("Labels ");
entry << labels.name << "(" << labels.argument << ")";
}
void visit(ast::PropertyList& prop_list) override
void visit(ast::PropertyList &prop_list) override
{
auto entry = printer.advance("Property List");
Traverser::visit(prop_list);
}
void visit(ast::RelationshipTypeList& rel_list) override
void visit(ast::RelationshipTypeList &rel_list) override
{
auto entry = printer.advance("Relationship Type List");
Traverser::visit(rel_list);
}
void visit(ast::Relationship& rel) override
void visit(ast::Relationship &rel) override
{
auto entry = printer.advance("Relationship");
entry << " direction: " << rel.direction;
Traverser::visit(rel);
}
void visit(ast::RelationshipSpecs& rel_specs) override
void visit(ast::RelationshipSpecs &rel_specs) override
{
auto entry = printer.advance("Relationship Specs");
Traverser::visit(rel_specs);
}
void visit(ast::LabelList& labels) override
void visit(ast::LabelList &labels) override
{
auto entry = printer.advance("Label List");
Traverser::visit(labels);
}
void visit(ast::ReturnList& return_list) override
void visit(ast::ReturnList &return_list) override
{
auto entry = printer.advance("Return List");
Traverser::visit(return_list);
}
void visit(ast::Where& where) override
void visit(ast::Where &where) override
{
auto entry = printer.advance("Where");
Traverser::visit(where);
}
void visit(ast::WriteQuery& write_query) override
void visit(ast::WriteQuery &write_query) override
{
auto entry = printer.advance("Write Query");
Traverser::visit(write_query);
}
void visit(ast::DeleteQuery& delete_query) override
void visit(ast::DeleteQuery &delete_query) override
{
auto entry = printer.advance("Delete Query");
Traverser::visit(delete_query);
}
void visit(ast::Delete& delete_clause) override
void visit(ast::Delete &delete_clause) override
{
auto entry = printer.advance("Delete");
auto is_detached = delete_clause.is_detached ? "yes" : "no";
auto text_entry =
std::string("Delete - DETACH: ") + std::string(is_detached);
auto entry = printer.advance(text_entry);
Traverser::visit(delete_clause);
}
void visit(ast::Create& create) override
void visit(ast::Create &create) override
{
auto entry = printer.advance("Create");
Traverser::visit(create);
}
void visit(ast::UpdateQuery& update_query) override
void visit(ast::UpdateQuery &update_query) override
{
auto entry = printer.advance("Update Query");
Traverser::visit(update_query);
}
void visit(ast::Set& set_clause) override
void visit(ast::Set &set_clause) override
{
auto entry = printer.advance("Set");
Traverser::visit(set_clause);
}
void visit(ast::SetValue& set_value) override
void visit(ast::SetValue &set_value) override
{
auto entry = printer.advance("Set Value");
Traverser::visit(set_value);
}
void visit(ast::SetElement& set_element) override
void visit(ast::SetElement &set_element) override
{
auto entry = printer.advance("Set Element");
Traverser::visit(set_element);
}
void visit(ast::SetList& set_list) override
void visit(ast::SetList &set_list) override
{
auto entry = printer.advance("Set List");
Traverser::visit(set_list);
}
void visit(ast::WithClause& with_clause) override
void visit(ast::WithClause &with_clause) override
{
auto entry = printer.advance("With Clause");
Traverser::visit(with_clause);
}
void visit(ast::WithList& with_list) override
void visit(ast::WithList &with_list) override
{
auto entry = printer.advance("With List");
Traverser::visit(with_list);
}
void visit(ast::WithQuery& with_query) override
void visit(ast::WithQuery &with_query) override
{
auto entry = printer.advance("With Query");
Traverser::visit(with_query);

View File

@ -0,0 +1,43 @@
#pragma once
#include <stdexcept>
#include "token.hpp"
#include "utils/exceptions/basic_exception.hpp"
class CypherParsingError : public BasicException
{
public:
CypherParsingError(const std::string &what)
: BasicException("Cypher Parsing Error: " + what)
{
}
};
class CypherLexicalError : public BasicException
{
public:
CypherLexicalError(const Token &token)
: BasicException("Cypher Lexical Error: unrecognized token '" +
token.value + "'.")
{
}
};
class CypherSyntaxError : public BasicException
{
public:
CypherSyntaxError(const std::string &near)
: BasicException("Cypher Syntax Error: near '" + near + "'.")
{
}
};
class CypherSemanticError : public BasicException
{
public:
CypherSemanticError(const std::string &what)
: BasicException("Cypher Semanic Error: " + what)
{
}
};

View File

@ -48,6 +48,7 @@ public:
rule("(?i:SET)", TK_SET);
rule("(?i:RETURN)", TK_RETURN);
rule("(?i:DISTINCT)", TK_DISTINCT);
rule("(?i:DETACH)", TK_DETACH);
rule("(?i:DELETE)", TK_DELETE);
rule("(?i:WITH)", TK_WITH);
// TODO: here should be better regex

View File

@ -12,8 +12,8 @@
#include "lexertl/lookup.hpp"
#pragma GCC diagnostic pop
#include "cypher/errors.hpp"
#include "cypher/token.hpp"
#include "query/language/cypher/errors.hpp"
#include "query/language/cypher/token.hpp"
class Lexer
{
@ -56,7 +56,7 @@ public:
auto token = Token {results.id, results.str()};
if(results.id == static_cast<decltype(results.id)>(-1))
throw LexicalError(token);
throw CypherLexicalError(token);
return token;
}

View File

@ -1,7 +1,7 @@
#pragma once
#include "cypher/ast/ast.hpp"
#include "cypher/ast/ast_visitor.hpp"
#include "query/language/cypher/ast/ast.hpp"
#include "query/language/cypher/ast/ast_visitor.hpp"
class Traverser : public ast::AstVisitor
{

View File

@ -2,24 +2,24 @@
#include <string>
#include "exceptions/exceptions.hpp"
#include "logging/default.hpp"
#include "query/exception/plan_compilation.hpp"
#include "utils/string/join.hpp"
// TODO:
// * all libraries have to be compiled in the server compile time
// * compile command has to be generated
class CodeCompiler
class PlanCompiler
{
public:
CodeCompiler() : logger(logging::log->logger("CodeCompiler")) {}
PlanCompiler() : logger(logging::log->logger("PlanCompiler")) {}
void compile(const std::string &in_file, const std::string &out_file)
{
std::string flags;
// TODO: sync this with cmake configuration
// TODO: sync this with cmake configuration
#ifdef BARRIER
flags += " -DBARRIER";
#endif
@ -46,14 +46,13 @@ public:
auto compile_command = utils::prints(
"clang++" + flags,
// "-std=c++1y -O2 -DNDEBUG", // compile flags
"-std=c++1y", // compile flags // TODO: load from config file
in_file, // input file
"-o", out_file, // ouput file
"-I./include", // include paths (TODO: parameter)
"-std=c++1y", // compile flags // TODO: load from config file
in_file, // input file
"-o", out_file, // ouput file
"-I./include", // include paths (TODO: parameter)
"-I../include",
"-I../libs/fmt", // TODO: load from config
"-I../../libs/fmt",
"-L./ -L../",
"-I../../libs/fmt", "-L./ -L../",
#ifdef BARRIER
"-lbarrier_pic",
#endif
@ -68,9 +67,9 @@ public:
// if compilation has failed throw exception
if (compile_status == -1) {
throw QueryEngineException("Code compilation error. Generated code "
"is not compilable or compilation "
"settings are wrong");
throw PlanCompilationException(
"Code compilation error. Generated code is not compilable or "
"compilation settings are wrong");
}
logger.debug("SUCCESS: Query Code Compilation: {} -> {}", in_file,

View File

@ -0,0 +1,29 @@
#pragma once
#include "config/config.hpp"
#include "query/language/cypher/ast/ast.hpp"
#include "query/language/cypher/compiler.hpp"
#include "logging/loggable.hpp"
#include "template_engine/engine.hpp"
#include "utils/string/file.hpp"
#include "utils/type_discovery.hpp"
template <typename Frontend, typename Backend>
class PlanGenerator : public Loggable
{
public:
PlanGenerator() : Loggable("PlanGenerator") {}
void generate_plan(const std::string &query, const uint64_t stripped_hash,
const std::string &path)
{
// TODO: multithread environment TEST
// multiple connections for the same query at the beginning
auto ir = frontend.generate_ir(query);
backend.generate_code(ir, query, stripped_hash, path);
}
private:
Frontend frontend;
Backend backend;
};

View File

@ -0,0 +1,26 @@
#pragma once
#include "query/i_plan_cpu.hpp"
#include "query/strip/stripped.hpp"
/*
* Query Program Contains:
* * Query Plan
* * Query Arguments (Stripped)
*/
template <typename Stream>
struct QueryProgram
{
using plan_t = IPlanCPU<Stream>;
QueryProgram(plan_t *plan, QueryStripped &&stripped)
: plan(plan), stripped(std::forward<QueryStripped>(stripped))
{
}
QueryProgram(QueryProgram &other) = delete;
QueryProgram(QueryProgram &&other) = default;
plan_t *plan;
QueryStripped stripped;
};

View File

@ -3,9 +3,10 @@
#include <string>
#include "database/db.hpp"
#include "query_engine/exceptions/exceptions.hpp"
#include "query_engine/util.hpp"
#include "query_program.hpp"
#include "query/exception/query_engine.hpp"
#include "query/exception/plan_execution.hpp"
#include "query/plan/program.hpp"
#include "query/util.hpp"
// preparations before execution
// execution
@ -28,16 +29,16 @@ public:
auto execute(QueryProgram<Stream> &program, Db &db, Stream &stream)
{
try {
// TODO: return result of query/code exection
// TODO: return result of query/code exection
#ifdef BARRIER
return program.code->run(barrier::trans(db),
return program.plan->run(barrier::trans(db),
program.stripped.arguments, stream);
#else
return program.code->run(db, program.stripped.arguments, stream);
return program.plan->run(db, program.stripped.arguments, stream);
#endif
// TODO: catch more exceptions
} catch (...) {
// TODO: return more information about the error
throw QueryEngineException("code execution error");
throw PlanExecutionException("");
}
}
};

View File

@ -5,16 +5,16 @@
#include <unordered_map>
#include "config/config.hpp"
#include "query_engine/code_compiler.hpp"
#include "query_engine/code_generator.hpp"
#include "query_engine/memgraph_dynamic_lib.hpp"
#include "query_engine/query_program.hpp"
#include "query_engine/query_stripper.hpp"
#include "utils/hashing/fnv.hpp"
#include "logging/default.hpp"
#include "query/backend/cpp_old/cypher.hpp"
#include "query/dynamic_lib.hpp"
#include "query/frontend/cypher.hpp"
#include "query/plan/compiler.hpp"
#include "query/plan/generator.hpp"
#include "query/plan/program.hpp"
#include "query/preprocesor.hpp"
#include "utils/file.hpp"
using std::string;
#include "utils/hashing/fnv.hpp"
template <typename Stream>
class ProgramLoader
@ -24,40 +24,34 @@ public:
using sptr_code_lib = std::shared_ptr<code_lib_t>;
using query_program_t = QueryProgram<Stream>;
ProgramLoader() :
logger(logging::log->logger("ProgramLoader")),
stripper(make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL))
ProgramLoader() : logger(logging::log->logger("PlanLoader")) {}
auto load(const std::string &query)
{
}
auto preprocessed = preprocessor.preprocess(query);
logger.debug("stripped_query = {}", preprocessed.query);
logger.debug("query_hash = {}", std::to_string(preprocessed.hash));
auto load(const string &query)
{
auto stripped = stripper.strip(query);
logger.debug("stripped_query = {}", stripped.query);
auto hash_string = std::to_string(stripped.hash);
logger.debug("query_hash = {}", hash_string);
auto code_lib_iter = code_libs.find(stripped.hash);
auto code_lib_iter = code_libs.find(preprocessed.hash);
// code is already compiled and loaded, just return runnable
// instance
if (code_lib_iter != code_libs.end()) {
auto code = code_lib_iter->second->instance();
return query_program_t(code, std::move(stripped));
return query_program_t(code, std::move(preprocessed));
}
auto base_path = CONFIG(config::COMPILE_CPU_PATH);
auto hash_string = std::to_string(preprocessed.hash);
auto path_cpp = base_path + hash_string + ".cpp";
auto hard_code_cpp = base_path + "hardcode/" + hash_string + ".cpp";
auto stripped_space = stripper.strip_space(query);
auto stripped_space = preprocessor.strip_space(query);
// cpp files in the hardcode folder have bigger priority then
// other cpp files
if (!utils::fexists(hard_code_cpp))
{
code_generator.generate_cpp(stripped_space.query, stripped.hash,
path_cpp);
if (!utils::fexists(hard_code_cpp)) {
plan_generator.generate_plan(stripped_space.query,
preprocessed.hash, path_cpp);
}
// compile the code
@ -65,39 +59,39 @@ public:
// hardcoded queries are compiled to the same folder as generated
// queries (all .so files are in the same folder)
if (utils::fexists(hard_code_cpp))
{
code_compiler.compile(hard_code_cpp, path_so);
}
else
{
code_compiler.compile(path_cpp, path_so);
if (utils::fexists(hard_code_cpp)) {
plan_compiler.compile(hard_code_cpp, path_so);
} else {
plan_compiler.compile(path_cpp, path_so);
}
// loads dynamic lib and store it
auto code_lib = load_code_lib(path_so);
code_libs.insert({{stripped.hash, code_lib}});
code_libs.insert({{preprocessed.hash, code_lib}});
// return an instance of runnable code (ICodeCPU)
return query_program_t(code_lib->instance(), std::move(stripped));
return query_program_t(code_lib->instance(), std::move(preprocessed));
}
protected:
Logger logger;
private:
// TODO somehow remove int.. from here
QueryStripper<int, int, int, int> stripper;
// TODO ifdef MEMGRAPH64 problem, how to use this kind
// of ifdef functions?
// uint64_t depends on fnv function
std::unordered_map<uint64_t, sptr_code_lib> code_libs;
CodeGenerator<Stream> code_generator;
CodeCompiler code_compiler;
QueryPreprocessor preprocessor;
sptr_code_lib load_code_lib(const string &path)
// TODO: compile time switch between frontends and backends
using frontend_t = cypher::Frontend;
using backend_t = CypherBackend<Stream>;
PlanGenerator<frontend_t, backend_t> plan_generator;
PlanCompiler plan_compiler;
sptr_code_lib load_code_lib(const std::string &path)
{
sptr_code_lib code_lib = std::make_shared<CodeLib<Stream>>(path);
code_lib->load();

View File

@ -0,0 +1,31 @@
#pragma once
#include "query/strip/stripper.hpp"
/*
* Query preprocessing contains:
* * query stripping
*
* The preprocessing results are:
* * stripped query |
* * stripped arguments |-> QueryStripped
* * stripped query hash |
*/
class QueryPreprocessor
{
public:
QueryPreprocessor()
: stripper(make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL))
{
}
auto strip_space(const std::string& query)
{
return stripper.strip_space(query);
}
auto preprocess(const std::string &query) { return stripper.strip(query); }
private:
QueryStripper<int, int, int, int> stripper;
};

View File

@ -0,0 +1,32 @@
#pragma once
#include <vector>
#include "storage/model/properties/property.hpp"
/*
* Query Plan Arguments Type
*/
using plan_args_t = std::vector<Property>;
/*
* QueryStripped contains:
* * stripped query
* * plan arguments stripped from query
* * hash of stripped query
*/
struct QueryStripped
{
QueryStripped(const std::string &&query, plan_args_t &&arguments,
uint64_t hash)
: query(std::forward<const std::string>(query)),
arguments(std::forward<plan_args_t>(arguments)), hash(hash)
{
}
QueryStripped(QueryStripped &other) = delete;
QueryStripped(QueryStripped &&other) = default;
std::string query;
plan_args_t arguments;
uint64_t hash;
};

View File

@ -7,9 +7,9 @@
#include <utility>
#include "cypher/cypher.h"
#include "cypher/tokenizer/cypher_lexer.hpp"
#include "logging/default.hpp"
#include "query_stripped.hpp"
#include "logging/loggable.hpp"
#include "query/language/cypher/tokenizer/cypher_lexer.hpp"
#include "query/strip/stripped.hpp"
#include "storage/model/properties/all.hpp"
#include "utils/hashing/fnv.hpp"
#include "utils/string/transform.hpp"
@ -17,17 +17,16 @@
// TODO: Maybe std::move(v) is faster, but it must be cheked for validity.
template <class T, class V>
void store_query_param(code_args_t &arguments, V &&v)
void store_query_param(plan_args_t &arguments, V &&v)
{
arguments.emplace_back(Property(T(std::move(v)), T::type));
}
template <typename... Ts>
class QueryStripper
class QueryStripper : public Loggable
{
public:
QueryStripper(Ts &&... strip_types)
: logger(logging::log->logger("QueryStripper")),
QueryStripper(Ts &&... strip_types) : Loggable("QueryStripper"),
strip_types(std::make_tuple(std::forward<Ts>(strip_types)...)),
lexer(std::make_unique<CypherLexer>())
{
@ -35,17 +34,15 @@ public:
QueryStripper(QueryStripper &other) = delete;
QueryStripper(QueryStripper &&other)
: 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)
{
auto stripped = strip(query, " ");
return QueryStripped(std::move(stripped.query), stripped.hash,
std::move(stripped.arguments));
return strip(query, " ");
}
auto strip(const std::string &query, const std::string &separator = "")
@ -60,13 +57,14 @@ public:
constexpr auto size = std::tuple_size<decltype(strip_types)>::value;
int counter = 0;
code_args_t stripped_arguments;
plan_args_t stripped_arguments;
std::string stripped_query;
stripped_query.reserve(query.size());
while (auto token = tokenizer.lookup()) {
// TODO: better implementation
if (_or(token.id, strip_types, std::make_index_sequence<size>{})) {
while (auto token = tokenizer.lookup())
{
if (_or(token.id, strip_types, std::make_index_sequence<size>{}))
{
auto index = counter++;
switch (token.id) {
case TK_LONG:
@ -90,7 +88,7 @@ public:
std::stof(token.value));
break;
default:
// TODO: other propertys
// TODO: other properties
assert(false);
}
stripped_query += std::to_string(index) + separator;
@ -100,12 +98,13 @@ public:
}
}
return QueryStripped(std::move(stripped_query), fnv(stripped_query),
std::move(stripped_arguments));
auto hash = fnv(stripped_query);
return QueryStripped(std::move(stripped_query),
std::move(stripped_arguments),
hash);
}
private:
Logger logger;
std::tuple<Ts...> strip_types;
CypherLexer::uptr lexer;

Some files were not shown because too many files have changed in this diff Show More