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

View File

@ -99,7 +99,7 @@ set(catch_source_dir "${libs_dir}/Catch")
# build memgraph's cypher grammar # build memgraph's cypher grammar
# copy grammar file to the build directory # 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) # build cypher parser (only c file - cypher.c)
EXECUTE_PROCESS( EXECUTE_PROCESS(
COMMAND ${lemon_dir}/lemon ${CMAKE_BINARY_DIR}/cypher.y -s 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/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}/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/util.hpp DESTINATION ${build_include_dir}/query)
FILE(COPY ${include_dir}/query_engine/i_code_cpu.hpp DESTINATION ${build_include_dir}/query_engine) FILE(COPY ${include_dir}/query/i_plan_cpu.hpp DESTINATION ${build_include_dir}/query)
FILE(COPY ${include_dir}/query_engine/query_result.hpp DESTINATION ${build_include_dir}/query_engine) FILE(COPY ${include_dir}/query/strip/stripped.hpp DESTINATION ${build_include_dir}/query/strip)
FILE(COPY ${include_dir}/query_engine/query_stripped.hpp DESTINATION ${build_include_dir}/query_engine)
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_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) 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(); 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) void write_fields(const std::vector<std::string> &fields)
{ {
// TODO: that should be one level below? // TODO: that should be one level below?

View File

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

View File

@ -3,7 +3,7 @@
#include <string> #include <string>
#include "communication/bolt/v1/packing/codes.hpp" #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/bswap.hpp"
#include "utils/types/byte.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 #pragma once
// !! DEPRICATED !!
#include <string> #include <string>
#include "query_engine/util.hpp" #include "query/util.hpp"
struct Code class Code
{ {
public:
std::string code; std::string code;
void reset() { code = ""; } void reset() { code = ""; }
@ -152,6 +155,12 @@ const std::string print_property =
} }
// DELETE // DELETE
const std::string detach_delete_all_nodes = const std::string delete_all_detached_nodes =
"t.vertex_access().fill().isolated().for_all(" "t.vertex_access().fill().isolated().for_all(\n"
" [&](auto a) {{ a.remove(); }});"; " [&](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 <vector>
#include "query_engine/code_generator/cypher_state.hpp" #include "query/backend/cpp_old/cypher_state.hpp"
#include "query_engine/code_generator/handlers/all.hpp" #include "query/backend/cpp_old/handlers/all.hpp"
#include "query_engine/code_generator/query_action.hpp" #include "query/backend/cpp_old/query_action.hpp"
#include "query_engine/exceptions/exceptions.hpp" #include "query/exception/cpp_code_generator.hpp"
class CppGenerator class CppGenerator
{ {
@ -24,11 +24,12 @@ public:
{ {
std::string code = ""; 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 &action = actions.at(i);
auto query_action = action.first; auto query_action = action.first;
if (action_functions.find(query_action) == action_functions.end()) if (action_functions.find(query_action) == action_functions.end())
throw CppGeneratorException( throw CppCodeGeneratorException(
"Query Action Function is not defined"); "Query Action Function is not defined");
auto &action_data = action.second; auto &action_data = action.second;
code += action_functions[query_action](_cypher_data, action_data); 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 <string>
#include <vector> #include <vector>
#include "query_engine/code_generator/namer.hpp" #include "query/backend/cpp_old/namer.hpp"
#include "query_engine/exceptions/exceptions.hpp" #include "query/exception/cpp_code_generator.hpp"
#include "storage/model/properties/flags.hpp" #include "storage/model/properties/flags.hpp"
// main states that are used while ast is traversed // main states that are used while ast is traversed
@ -50,7 +50,7 @@ enum class EntitySource : uint8_t
class CypherStateData class CypherStateData
{ {
public: public:
using tags_type = std::vector<std::string>; using tags_type = std::vector<std::string>;
using properties_type = std::map<std::string, int64_t>; using properties_type = std::map<std::string, int64_t>;
private: private:
@ -96,25 +96,25 @@ public:
void node_matched(const std::string &name) void node_matched(const std::string &name)
{ {
entity_type[name] = EntityType::Node; entity_type[name] = EntityType::Node;
entity_status[name] = EntityStatus::Matched; entity_status[name] = EntityStatus::Matched;
} }
void node_created(const std::string &name) void node_created(const std::string &name)
{ {
entity_type[name] = EntityType::Node; entity_type[name] = EntityType::Node;
entity_status[name] = EntityStatus::Created; entity_status[name] = EntityStatus::Created;
} }
void relationship_matched(const std::string &name) void relationship_matched(const std::string &name)
{ {
entity_type[name] = EntityType::Relationship; entity_type[name] = EntityType::Relationship;
entity_status[name] = EntityStatus::Matched; entity_status[name] = EntityStatus::Matched;
} }
void relationship_created(const std::string &name) void relationship_created(const std::string &name)
{ {
entity_type[name] = EntityType::Relationship; entity_type[name] = EntityType::Relationship;
entity_status[name] = EntityStatus::Created; entity_status[name] = EntityStatus::Created;
} }
@ -127,7 +127,7 @@ public:
auto tags(const std::string &name) const auto tags(const std::string &name) const
{ {
if (entity_tags.find(name) == entity_tags.end()) 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); return entity_tags.at(name);
} }
@ -138,17 +138,24 @@ public:
void tag(const std::string &name, const std::string &new_tag) 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] = std::vector<std::string>{};
} }
entity_tags[name].emplace_back(new_tag); entity_tags[name].emplace_back(new_tag);
} }
auto has_properties(const std::string& name)
{
return entity_properties.find(name) != entity_properties.end();
}
// entity properties // entity properties
auto properties(const std::string &name) const auto properties(const std::string &name) const
{ {
if (entity_properties.find(name) == entity_properties.end()) 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); return entity_properties.at(name);
} }
@ -160,7 +167,8 @@ public:
void index(const std::string &entity, const std::string &property, void index(const std::string &entity, const std::string &property,
int64_t index) 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] = properties_type{};
} }
entity_properties[entity][property] = index; entity_properties[entity][property] = index;
@ -169,12 +177,13 @@ public:
auto index(const std::string &entity, const std::string &property_name) auto index(const std::string &entity, const std::string &property_name)
{ {
if (entity_properties.find(entity) == entity_properties.end()) 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); auto properties = entity_properties.at(entity);
if (properties.find(property_name) == properties.end()) if (properties.find(property_name) == properties.end())
throw CppGeneratorException( throw CppCodeGeneratorException(
"No property for specified property name"); "No property for specified property name");
return properties[property_name]; return properties[property_name];
@ -186,19 +195,21 @@ public:
{ {
// TODO: find out smarter way it's not hard // TODO: find out smarter way it's not hard
std::string print = std::string print =
"std::map<std::string, int64_t> " + variable_name + " = "; "std::map<std::string, int64_t> " + variable_name + " = {";
print += "{";
auto indices = entity_properties.at(name); auto indices = entity_properties.at(name);
size_t i = 0; size_t i = 0;
iter_t it = indices.begin(); iter_t it = indices.begin();
for (; it != indices.end(); ++it, ++i) for (; it != indices.end(); ++it, ++i)
{ {
print += print +=
"{\"" + it->first + "\"," + std::to_string(it->second) + "}"; "{\"" + it->first + "\"," + std::to_string(it->second) + "}";
if (i < indices.size() - 1) if (i < indices.size() - 1) print += ",";
print += ",";
} }
print += "};"; print += "};";
return 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 #pragma once
#include "query_engine/code_generator/handlers/includes.hpp" #include "includes.hpp"
auto create_query_action = auto create_query_action =
[](CypherStateData &cypher_data, [](CypherStateData &cypher_data,
@ -35,7 +35,8 @@ auto create_query_action =
// find start and end node // find start and end node
auto &relationships_data = action_data.relationship_data; auto &relationships_data = action_data.relationship_data;
if (relationships_data.find(name) == relationships_data.end()) 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 &relationship_data = relationships_data.at(name);
auto left_node = relationship_data.nodes.first; auto left_node = relationship_data.nodes.first;
auto right_node = relationship_data.nodes.second; 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 // TODO: If node isn't already matched or created it has to be
// created here. It is not possible for now. // created here. It is not possible for now.
if (cypher_data.status(left_node) != EntityStatus::Matched) { if (cypher_data.status(left_node) != EntityStatus::Matched) {
throw SemanticError("Create Relationship: node " + left_node + throw CypherSemanticError("Create Relationship: node " +
" can't be found"); left_node + " can't be found");
} }
if (cypher_data.status(right_node) != EntityStatus::Matched) { if (cypher_data.status(right_node) != EntityStatus::Matched) {
throw SemanticError("Create Relationship: node " + right_node + throw CypherSemanticError("Create Relationship: node " +
" can't be found"); right_node + " can't be found");
} }
// create relationship // create relationship
@ -64,19 +65,6 @@ auto create_query_action =
code += code_line(code::set_type, name, tag); 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 // mark relationship as created
cypher_data.relationship_created(name); cypher_data.relationship_created(name);
} }

View File

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

View File

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

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "query_engine/code_generator/handlers/includes.hpp" #include "includes.hpp"
namespace namespace
{ {
@ -49,7 +49,7 @@ auto match_query_action =
} }
if (place == entity_search::search_label_index) { if (place == entity_search::search_label_index) {
if (action_data.entity_data.at(name).tags.size() > 1) { 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.source(name, EntitySource::LabelIndex);
cypher_data.tags(name, action_data.entity_data.at(name).tags); 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 (place == entity_search::search_type_index) {
if (action_data.entity_data.at(name).tags.size() > 1) { 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.source(name, EntitySource::TypeIndex);
cypher_data.tags(name, action_data.entity_data.at(name).tags); cypher_data.tags(name, action_data.entity_data.at(name).tags);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,9 +2,10 @@
#include "database/db.hpp" #include "database/db.hpp"
#include "logging/default.hpp" #include "logging/default.hpp"
#include "program_executor.hpp" #include "query/exception/query_engine.hpp"
#include "program_loader.hpp" #include "query/plan/program.hpp"
#include "query_result.hpp" #include "query/plan/program_loader.hpp"
#include "query/plan/program_executor.hpp"
/* /*
* Current arhitecture: * Current arhitecture:
@ -20,8 +21,7 @@ class QueryEngine
public: public:
QueryEngine() : logger(logging::log->logger("QueryEngine")) {} QueryEngine() : logger(logging::log->logger("QueryEngine")) {}
auto execute(const std::string &query, Db &db, auto execute(const std::string &query, Db &db, Stream &stream)
Stream &stream)
{ {
try { try {
auto program = program_loader.load(query); auto program = program_loader.load(query);
@ -38,6 +38,8 @@ public:
logger.error("QueryEngineException: {}", std::string(e.what())); logger.error("QueryEngineException: {}", std::string(e.what()));
// return false; // return false;
throw e; 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 <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 "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 struct SetElementState
{ {
@ -107,9 +107,10 @@ public:
void semantic_check() const void semantic_check() const
{ {
if (!has_return) if (!has_return)
throw SemanticError("The query doesn't have RETURN clause. Next " throw CypherSemanticError(
"releases will support query without RETURN " "The query doesn't have RETURN clause. Next "
"clause"); "releases will support query without RETURN "
"clause");
} }
void visit(ast::WriteQuery &write_query) override void visit(ast::WriteQuery &write_query) override
@ -258,11 +259,8 @@ public:
Traverser::visit(ast_node); Traverser::visit(ast_node);
// this is here because of RETURN clause
// CREATE (n {...}) RETURN n
if (cypher_data.status(name) != EntityStatus::Matched && if (cypher_data.status(name) != EntityStatus::Matched &&
state == CypherState::Create) state == CypherState::Create) {
{
cypher_data.node_created(name); cypher_data.node_created(name);
} }
} }
@ -300,8 +298,7 @@ public:
auto &cypher_data = generator.cypher_data(); auto &cypher_data = generator.cypher_data();
auto &action_data = generator.action_data(); auto &action_data = generator.action_data();
if (!ast_relationship.has_name()) if (!ast_relationship.has_name()) return;
return;
entity = ast_relationship.name(); entity = ast_relationship.name();
using ast_direction = ast::Relationship::Direction; using ast_direction = ast::Relationship::Direction;
@ -362,9 +359,9 @@ public:
if (ast_relationship_type_list.has_value()) { if (ast_relationship_type_list.has_value()) {
auto type = ast_relationship_type_list.value->name; auto type = ast_relationship_type_list.value->name;
action_data.add_entity_tag(entity, type); action_data.add_entity_tag(entity, type);
action_data.csm.search_cost( action_data.csm.search_cost(entity,
entity, entity_search::search_type_index, entity_search::search_type_index,
entity_search::type_cost); entity_search::type_cost);
} }
Traverser::visit(ast_relationship_type_list); Traverser::visit(ast_relationship_type_list);
@ -411,7 +408,8 @@ public:
// update action data // update action data
auto &action_data = generator.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); action_data.add_entitiy_property(entity, prop);
// update cypher data // update cypher data
@ -469,7 +467,7 @@ public:
auto entity_type = cypher_data.type(entity); auto entity_type = cypher_data.type(entity);
if (entity_type == EntityType::None) 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(); auto &action_data = generator.action_data();
@ -515,27 +513,27 @@ public:
Traverser::visit(ast_set_value); Traverser::visit(ast_set_value);
} }
void visit(ast::Delete& ast_delete) override void visit(ast::Delete &ast_delete) override
{ {
code += generator.generate(); code += generator.generate();
state = CypherState::Delete; state = CypherState::Delete;
generator.add_action(QueryAction::Delete); auto &action_data = generator.add_action(QueryAction::Delete);
Traverser::visit(ast_delete); Traverser::visit(ast_delete);
code += generator.generate(); code += generator.generate();
} }
void visit(ast::CountFunction& ast_count) override void visit(ast::CountFunction &ast_count) override
{ {
auto &action_data = generator.action_data(); auto &action_data = generator.action_data();
auto &cypher_data = generator.cypher_data(); auto &cypher_data = generator.cypher_data();
// if (state == CypherState::Return) // 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 <type_traits>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "communication/bolt/v1/serialization/bolt_serializer.hpp" #include "communication/bolt/v1/serialization/bolt_serializer.hpp"
#include "communication/bolt/v1/serialization/record_stream.hpp" #include "communication/bolt/v1/serialization/record_stream.hpp"
#include "database/db.hpp" #include "database/db.hpp"
@ -37,7 +38,7 @@ namespace barrier
#include "utils/iterator/iterator.hpp" #include "utils/iterator/iterator.hpp"
#include "utils/option_ptr.hpp" #include "utils/option_ptr.hpp"
#include "utils/reference_wrapper.hpp" #include "utils/reference_wrapper.hpp"
#include "query_engine/util.hpp" #include "query/util.hpp"
#endif #endif

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "query_engine/query_stripped.hpp" #include "query/strip/stripped.hpp"
#ifdef BARRIER #ifdef BARRIER
#include "barrier/barrier.hpp" #include "barrier/barrier.hpp"
@ -12,19 +12,19 @@
#endif #endif
template <typename Stream> template <typename Stream>
class ICodeCPU class IPlanCPU
{ {
public: public:
#ifdef BARRIER #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 #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 #endif
virtual ~ICodeCPU() {} virtual ~IPlanCPU() {}
}; };
template <typename Stream> template <typename Stream>
using produce_t = ICodeCPU<Stream> *(*)(); using produce_t = IPlanCPU<Stream> *(*)();
template <typename 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> struct Delete : public AstNode<Delete>
{ {
Delete(Identifier* identifier) Delete(Identifier* identifier, bool is_detached = false)
: identifier(identifier) {} : identifier(identifier), is_detached(is_detached) {}
Identifier* identifier; Identifier* identifier;
bool is_detached;
}; };
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -2,24 +2,24 @@
#include <string> #include <string>
#include "exceptions/exceptions.hpp"
#include "logging/default.hpp" #include "logging/default.hpp"
#include "query/exception/plan_compilation.hpp"
#include "utils/string/join.hpp" #include "utils/string/join.hpp"
// TODO: // TODO:
// * all libraries have to be compiled in the server compile time // * all libraries have to be compiled in the server compile time
// * compile command has to be generated // * compile command has to be generated
class CodeCompiler class PlanCompiler
{ {
public: 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) void compile(const std::string &in_file, const std::string &out_file)
{ {
std::string flags; std::string flags;
// TODO: sync this with cmake configuration // TODO: sync this with cmake configuration
#ifdef BARRIER #ifdef BARRIER
flags += " -DBARRIER"; flags += " -DBARRIER";
#endif #endif
@ -46,14 +46,13 @@ public:
auto compile_command = utils::prints( auto compile_command = utils::prints(
"clang++" + flags, "clang++" + flags,
// "-std=c++1y -O2 -DNDEBUG", // compile flags // "-std=c++1y -O2 -DNDEBUG", // compile flags
"-std=c++1y", // compile flags // TODO: load from config file "-std=c++1y", // compile flags // TODO: load from config file
in_file, // input file in_file, // input file
"-o", out_file, // ouput file "-o", out_file, // ouput file
"-I./include", // include paths (TODO: parameter) "-I./include", // include paths (TODO: parameter)
"-I../include", "-I../include",
"-I../libs/fmt", // TODO: load from config "-I../libs/fmt", // TODO: load from config
"-I../../libs/fmt", "-I../../libs/fmt", "-L./ -L../",
"-L./ -L../",
#ifdef BARRIER #ifdef BARRIER
"-lbarrier_pic", "-lbarrier_pic",
#endif #endif
@ -68,9 +67,9 @@ public:
// if compilation has failed throw exception // if compilation has failed throw exception
if (compile_status == -1) { if (compile_status == -1) {
throw QueryEngineException("Code compilation error. Generated code " throw PlanCompilationException(
"is not compilable or compilation " "Code compilation error. Generated code is not compilable or "
"settings are wrong"); "compilation settings are wrong");
} }
logger.debug("SUCCESS: Query Code Compilation: {} -> {}", in_file, 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 <string>
#include "database/db.hpp" #include "database/db.hpp"
#include "query_engine/exceptions/exceptions.hpp" #include "query/exception/query_engine.hpp"
#include "query_engine/util.hpp" #include "query/exception/plan_execution.hpp"
#include "query_program.hpp" #include "query/plan/program.hpp"
#include "query/util.hpp"
// preparations before execution // preparations before execution
// execution // execution
@ -28,16 +29,16 @@ public:
auto execute(QueryProgram<Stream> &program, Db &db, Stream &stream) auto execute(QueryProgram<Stream> &program, Db &db, Stream &stream)
{ {
try { try {
// TODO: return result of query/code exection // TODO: return result of query/code exection
#ifdef BARRIER #ifdef BARRIER
return program.code->run(barrier::trans(db), return program.plan->run(barrier::trans(db),
program.stripped.arguments, stream); program.stripped.arguments, stream);
#else #else
return program.code->run(db, program.stripped.arguments, stream); return program.plan->run(db, program.stripped.arguments, stream);
#endif #endif
// TODO: catch more exceptions
} catch (...) { } catch (...) {
// TODO: return more information about the error throw PlanExecutionException("");
throw QueryEngineException("code execution error");
} }
} }
}; };

View File

@ -5,16 +5,16 @@
#include <unordered_map> #include <unordered_map>
#include "config/config.hpp" #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 "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" #include "utils/file.hpp"
#include "utils/hashing/fnv.hpp"
using std::string;
template <typename Stream> template <typename Stream>
class ProgramLoader class ProgramLoader
@ -24,40 +24,34 @@ public:
using sptr_code_lib = std::shared_ptr<code_lib_t>; using sptr_code_lib = std::shared_ptr<code_lib_t>;
using query_program_t = QueryProgram<Stream>; using query_program_t = QueryProgram<Stream>;
ProgramLoader() : ProgramLoader() : logger(logging::log->logger("PlanLoader")) {}
logger(logging::log->logger("ProgramLoader")),
stripper(make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL)) 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 code_lib_iter = code_libs.find(preprocessed.hash);
{
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);
// code is already compiled and loaded, just return runnable // code is already compiled and loaded, just return runnable
// instance // instance
if (code_lib_iter != code_libs.end()) { if (code_lib_iter != code_libs.end()) {
auto code = code_lib_iter->second->instance(); 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 base_path = CONFIG(config::COMPILE_CPU_PATH);
auto hash_string = std::to_string(preprocessed.hash);
auto path_cpp = base_path + hash_string + ".cpp"; auto path_cpp = base_path + hash_string + ".cpp";
auto hard_code_cpp = base_path + "hardcode/" + 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 // cpp files in the hardcode folder have bigger priority then
// other cpp files // other cpp files
if (!utils::fexists(hard_code_cpp)) if (!utils::fexists(hard_code_cpp)) {
{ plan_generator.generate_plan(stripped_space.query,
code_generator.generate_cpp(stripped_space.query, stripped.hash, preprocessed.hash, path_cpp);
path_cpp);
} }
// compile the code // compile the code
@ -65,39 +59,39 @@ public:
// hardcoded queries are compiled to the same folder as generated // hardcoded queries are compiled to the same folder as generated
// queries (all .so files are in the same folder) // queries (all .so files are in the same folder)
if (utils::fexists(hard_code_cpp)) if (utils::fexists(hard_code_cpp)) {
{ plan_compiler.compile(hard_code_cpp, path_so);
code_compiler.compile(hard_code_cpp, path_so); } else {
} plan_compiler.compile(path_cpp, path_so);
else
{
code_compiler.compile(path_cpp, path_so);
} }
// loads dynamic lib and store it // loads dynamic lib and store it
auto code_lib = load_code_lib(path_so); 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 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: protected:
Logger logger; Logger logger;
private: private:
// TODO somehow remove int.. from here
QueryStripper<int, int, int, int> stripper;
// TODO ifdef MEMGRAPH64 problem, how to use this kind // TODO ifdef MEMGRAPH64 problem, how to use this kind
// of ifdef functions? // of ifdef functions?
// uint64_t depends on fnv function // uint64_t depends on fnv function
std::unordered_map<uint64_t, sptr_code_lib> code_libs; std::unordered_map<uint64_t, sptr_code_lib> code_libs;
CodeGenerator<Stream> code_generator; QueryPreprocessor preprocessor;
CodeCompiler code_compiler;
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); sptr_code_lib code_lib = std::make_shared<CodeLib<Stream>>(path);
code_lib->load(); 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 <utility>
#include "cypher/cypher.h" #include "cypher/cypher.h"
#include "cypher/tokenizer/cypher_lexer.hpp" #include "logging/loggable.hpp"
#include "logging/default.hpp" #include "query/language/cypher/tokenizer/cypher_lexer.hpp"
#include "query_stripped.hpp" #include "query/strip/stripped.hpp"
#include "storage/model/properties/all.hpp" #include "storage/model/properties/all.hpp"
#include "utils/hashing/fnv.hpp" #include "utils/hashing/fnv.hpp"
#include "utils/string/transform.hpp" #include "utils/string/transform.hpp"
@ -17,17 +17,16 @@
// TODO: Maybe std::move(v) is faster, but it must be cheked for validity. // TODO: Maybe std::move(v) is faster, but it must be cheked for validity.
template <class T, class V> 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)); arguments.emplace_back(Property(T(std::move(v)), T::type));
} }
template <typename... Ts> template <typename... Ts>
class QueryStripper class QueryStripper : public Loggable
{ {
public: public:
QueryStripper(Ts &&... strip_types) QueryStripper(Ts &&... strip_types) : Loggable("QueryStripper"),
: logger(logging::log->logger("QueryStripper")),
strip_types(std::make_tuple(std::forward<Ts>(strip_types)...)), strip_types(std::make_tuple(std::forward<Ts>(strip_types)...)),
lexer(std::make_unique<CypherLexer>()) lexer(std::make_unique<CypherLexer>())
{ {
@ -35,17 +34,15 @@ public:
QueryStripper(QueryStripper &other) = delete; QueryStripper(QueryStripper &other) = delete;
QueryStripper(QueryStripper &&other) QueryStripper(QueryStripper &&other) : Loggable("QueryStripper"),
: strip_types(std::move(other.strip_types)), strip_types(std::move(other.strip_types)),
lexer(std::move(other.lexer)) lexer(std::move(other.lexer))
{ {
} }
auto strip_space(const std::string &query) auto strip_space(const std::string &query)
{ {
auto stripped = strip(query, " "); return strip(query, " ");
return QueryStripped(std::move(stripped.query), stripped.hash,
std::move(stripped.arguments));
} }
auto strip(const std::string &query, const std::string &separator = "") 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; constexpr auto size = std::tuple_size<decltype(strip_types)>::value;
int counter = 0; int counter = 0;
code_args_t stripped_arguments; plan_args_t stripped_arguments;
std::string stripped_query; std::string stripped_query;
stripped_query.reserve(query.size()); stripped_query.reserve(query.size());
while (auto token = tokenizer.lookup()) { while (auto token = tokenizer.lookup())
// TODO: better implementation {
if (_or(token.id, strip_types, std::make_index_sequence<size>{})) { if (_or(token.id, strip_types, std::make_index_sequence<size>{}))
{
auto index = counter++; auto index = counter++;
switch (token.id) { switch (token.id) {
case TK_LONG: case TK_LONG:
@ -90,7 +88,7 @@ public:
std::stof(token.value)); std::stof(token.value));
break; break;
default: default:
// TODO: other propertys // TODO: other properties
assert(false); assert(false);
} }
stripped_query += std::to_string(index) + separator; stripped_query += std::to_string(index) + separator;
@ -100,12 +98,13 @@ public:
} }
} }
return QueryStripped(std::move(stripped_query), fnv(stripped_query), auto hash = fnv(stripped_query);
std::move(stripped_arguments)); return QueryStripped(std::move(stripped_query),
std::move(stripped_arguments),
hash);
} }
private: private:
Logger logger;
std::tuple<Ts...> strip_types; std::tuple<Ts...> strip_types;
CypherLexer::uptr lexer; CypherLexer::uptr lexer;

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