From d45121a1a2c9c7736efaff0dd7dfccd9210ece50 Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Wed, 2 Nov 2016 16:05:02 +0100 Subject: [PATCH] scenario 000001 pass, dressipi scenario 1 - 3 more queries have to be implemented --- .clang-format | 10 +- CMakeLists.txt | 9 +- .../bolt/v1/serialization/record_stream.hpp | 9 ++ .../communication/bolt/v1/states/executor.hpp | 2 +- .../v1/transport/streamed_bolt_decoder.hpp | 2 +- include/logging/loggable.hpp | 14 ++ include/query/backend/backend.hpp | 10 ++ include/query/backend/code_generator.hpp | 40 +++++ include/query/backend/cpp/code_generator.hpp | 22 +++ .../backend/cpp_old}/clause_action.hpp | 0 .../backend/cpp_old}/code.hpp | 19 ++- .../backend/cpp_old}/cpp_generator.hpp | 13 +- include/query/backend/cpp_old/cypher.hpp | 65 ++++++++ .../backend/cpp_old}/cypher_state.hpp | 49 +++--- .../backend/cpp_old}/entity_search.hpp | 0 .../query/backend/cpp_old/handlers/all.hpp | 11 ++ .../backend/cpp_old}/handlers/create.hpp | 26 +--- .../backend/cpp_old}/handlers/delete.hpp | 9 +- .../backend/cpp_old}/handlers/includes.hpp | 13 +- .../backend/cpp_old}/handlers/match.hpp | 6 +- .../backend/cpp_old}/handlers/return.hpp | 52 ++++--- .../backend/cpp_old}/handlers/set.hpp | 2 +- .../cpp_old}/handlers/transaction_begin.hpp | 2 +- .../cpp_old}/handlers/transaction_commit.hpp | 2 +- .../backend/cpp_old}/namer.hpp | 0 .../backend/cpp_old}/query_action.hpp | 0 .../backend/cpp_old}/query_action_data.hpp | 11 +- .../backend/cpp_old}/structures.hpp | 0 include/query/backend/llvm/code_generator.hpp | 3 + .../dynamic_lib.hpp} | 4 +- .../query_engine.hpp => query/engine.hpp} | 12 +- .../query/exception/cpp_code_generator.hpp | 9 ++ include/query/exception/decoder_exception.hpp | 9 ++ include/query/exception/out_of_memory.hpp | 9 ++ include/query/exception/plan_compilation.hpp | 9 ++ include/query/exception/plan_execution.hpp | 9 ++ include/query/exception/query_engine.hpp | 9 ++ include/query/frontend/cypher.hpp | 33 ++++ .../frontend/cypher/traverser.hpp} | 46 +++--- include/query/frontend/opencypher.hpp | 10 ++ .../query/frontend/opencypher/traverser.hpp | 3 + .../hardcode/queries.hpp | 3 +- .../i_code_cpu.hpp => query/i_plan_cpu.hpp} | 14 +- .../query/ir/tree/create.hpp | 0 include/query/ir/tree/delete.hpp | 0 include/query/ir/tree/edge.hpp | 0 include/query/ir/tree/node.hpp | 27 ++++ include/query/ir/tree/query.hpp | 5 + include/query/ir/tree/read.hpp | 0 include/query/ir/tree/tree.hpp | 0 include/query/ir/tree/update.hpp | 0 include/query/ir/tree/vertex.hpp | 0 .../query/language}/cypher/.gitignore | 0 .../query/language}/cypher/ast/accessor.hpp | 0 .../query/language}/cypher/ast/alias.hpp | 0 .../query/language}/cypher/ast/ast.hpp | 0 .../query/language}/cypher/ast/ast_echo.hpp | 0 .../query/language}/cypher/ast/ast_node.hpp | 0 .../language}/cypher/ast/ast_visitor.hpp | 0 .../query/language}/cypher/ast/create.hpp | 0 .../query/language}/cypher/ast/delete.hpp | 7 +- .../query/language}/cypher/ast/distinct.hpp | 0 .../query/language}/cypher/ast/expr.hpp | 0 .../query/language}/cypher/ast/functions.hpp | 0 .../query/language}/cypher/ast/identifier.hpp | 0 .../query/language}/cypher/ast/list.hpp | 0 .../query/language}/cypher/ast/match.hpp | 0 .../query/language}/cypher/ast/node.hpp | 0 .../query/language}/cypher/ast/operators.hpp | 0 .../query/language}/cypher/ast/pattern.hpp | 0 .../query/language}/cypher/ast/property.hpp | 0 .../query/language}/cypher/ast/queries.hpp | 0 .../language}/cypher/ast/relationship.hpp | 0 .../query/language}/cypher/ast/return.hpp | 0 .../query/language}/cypher/ast/set.hpp | 0 .../query/language}/cypher/ast/start.hpp | 0 .../query/language}/cypher/ast/tree.hpp | 0 .../query/language}/cypher/ast/values.hpp | 0 .../query/language}/cypher/ast/where.hpp | 0 .../query/language}/cypher/ast/with.hpp | 0 .../query/language}/cypher/common.hpp | 0 .../query/language}/cypher/compiler.hpp | 0 .../query/language}/cypher/cypher.y | 22 ++- .../language}/cypher/debug/tree_print.hpp | 146 +++++++++--------- include/query/language/cypher/errors.hpp | 43 ++++++ .../query/language}/cypher/lexer.cpp | 0 .../query/language}/cypher/parser.cpp | 0 .../query/language}/cypher/parser.hpp | 0 .../query/language}/cypher/token.hpp | 0 .../cypher/tokenizer/cypher_lexer.hpp | 1 + .../language}/cypher/tokenizer/lexer.hpp | 6 +- .../language}/cypher/visitor/traverser.hpp | 4 +- .../plan/compiler.hpp} | 25 ++- include/query/plan/generator.hpp | 29 ++++ include/query/plan/program.hpp | 26 ++++ .../plan}/program_executor.hpp | 17 +- .../plan}/program_loader.hpp | 78 +++++----- include/query/preprocesor.hpp | 31 ++++ include/query/strip/stripped.hpp | 32 ++++ .../strip/stripper.hpp} | 39 +++-- include/{query_engine => query}/util.hpp | 10 +- include/query_engine/code_generator.hpp | 81 ---------- .../code_generator/handlers/all.hpp | 11 -- include/query_engine/exceptions/errors.hpp | 19 --- .../query_engine/exceptions/exceptions.hpp | 39 ----- include/query_engine/query_hasher.hpp | 23 --- include/query_engine/query_program.hpp | 21 --- include/query_engine/query_result.hpp | 44 ------ include/query_engine/query_stripped.hpp | 24 --- include/storage/indexes/indexes.hpp | 3 +- include/template_engine/engine.hpp | 6 +- .../utils/exceptions/non_exaustive_switch.hpp | 9 ++ .../utils/exceptions/not_yet_implemented.hpp | 9 ++ src/communication/bolt/v1/states/executor.cpp | 33 ++-- src/cypher/errors.hpp | 31 ---- src/memgraph_bolt.cpp | 4 +- .../template/barrier_template_code_cpu.cpp | 10 +- .../template/template_code_cpu.cpp | 12 +- src/query_engine/util.cpp | 2 +- src/template_engine/engine.cpp | 2 +- tests/integration/__init__.py | 0 tests/integration/cleaning.cpp | 4 +- tests/integration/{internal => }/crud.py | 0 tests/integration/index.cpp | 4 +- tests/integration/pilot/dressipi/crud.py | 59 ------- tests/integration/pilot/dressipi/run.py | 4 - tests/integration/queries.cpp | 18 +-- tests/integration/scenario.py | 78 ++++++++++ tests/integration/scenario/__init__.py | 0 tests/integration/scenario/no_000001.py | 34 ++++ tests/integration/snapshot.cpp | 4 +- tests/manual/cpp_generator.cpp | 2 +- tests/manual/cypher_ast.cpp | 6 +- tests/manual/queries.cpp | 8 +- tests/manual/query_engine.cpp | 23 ++- tests/manual/query_hasher.cpp | 22 +-- tests/unit/cypher_state_machine.cpp | 2 +- tests/unit/cypher_traversal.cpp | 7 +- tests/unit/parameter_index.cpp | 2 +- tests/unit/template_engine.cpp | 5 +- 140 files changed, 1032 insertions(+), 761 deletions(-) create mode 100644 include/logging/loggable.hpp create mode 100644 include/query/backend/backend.hpp create mode 100644 include/query/backend/code_generator.hpp create mode 100644 include/query/backend/cpp/code_generator.hpp rename include/{query_engine/code_generator => query/backend/cpp_old}/clause_action.hpp (100%) rename include/{query_engine/traverser => query/backend/cpp_old}/code.hpp (92%) rename include/{query_engine/code_generator => query/backend/cpp_old}/cpp_generator.hpp (90%) create mode 100644 include/query/backend/cpp_old/cypher.hpp rename include/{query_engine/code_generator => query/backend/cpp_old}/cypher_state.hpp (81%) rename include/{query_engine/code_generator => query/backend/cpp_old}/entity_search.hpp (100%) create mode 100644 include/query/backend/cpp_old/handlers/all.hpp rename include/{query_engine/code_generator => query/backend/cpp_old}/handlers/create.hpp (66%) rename include/{query_engine/code_generator => query/backend/cpp_old}/handlers/delete.hpp (58%) rename include/{query_engine/code_generator => query/backend/cpp_old}/handlers/includes.hpp (76%) rename include/{query_engine/code_generator => query/backend/cpp_old}/handlers/match.hpp (92%) rename include/{query_engine/code_generator => query/backend/cpp_old}/handlers/return.hpp (73%) rename include/{query_engine/code_generator => query/backend/cpp_old}/handlers/set.hpp (93%) rename include/{query_engine/code_generator => query/backend/cpp_old}/handlers/transaction_begin.hpp (76%) rename include/{query_engine/code_generator => query/backend/cpp_old}/handlers/transaction_commit.hpp (79%) rename include/{query_engine/code_generator => query/backend/cpp_old}/namer.hpp (100%) rename include/{query_engine/code_generator => query/backend/cpp_old}/query_action.hpp (100%) rename include/{query_engine/code_generator => query/backend/cpp_old}/query_action_data.hpp (93%) rename include/{query_engine/code_generator => query/backend/cpp_old}/structures.hpp (100%) create mode 100644 include/query/backend/llvm/code_generator.hpp rename include/{query_engine/memgraph_dynamic_lib.hpp => query/dynamic_lib.hpp} (78%) rename include/{query_engine/query_engine.hpp => query/engine.hpp} (81%) create mode 100644 include/query/exception/cpp_code_generator.hpp create mode 100644 include/query/exception/decoder_exception.hpp create mode 100644 include/query/exception/out_of_memory.hpp create mode 100644 include/query/exception/plan_compilation.hpp create mode 100644 include/query/exception/plan_execution.hpp create mode 100644 include/query/exception/query_engine.hpp create mode 100644 include/query/frontend/cypher.hpp rename include/{query_engine/traverser/cpp_traverser.hpp => query/frontend/cypher/traverser.hpp} (92%) create mode 100644 include/query/frontend/opencypher.hpp create mode 100644 include/query/frontend/opencypher/traverser.hpp rename include/{query_engine => query}/hardcode/queries.hpp (99%) rename include/{query_engine/i_code_cpu.hpp => query/i_plan_cpu.hpp} (53%) rename tests/integration/pilot/dressipi/__init__.py => include/query/ir/tree/create.hpp (100%) create mode 100644 include/query/ir/tree/delete.hpp create mode 100644 include/query/ir/tree/edge.hpp create mode 100644 include/query/ir/tree/node.hpp create mode 100644 include/query/ir/tree/query.hpp create mode 100644 include/query/ir/tree/read.hpp create mode 100644 include/query/ir/tree/tree.hpp create mode 100644 include/query/ir/tree/update.hpp create mode 100644 include/query/ir/tree/vertex.hpp rename {src => include/query/language}/cypher/.gitignore (100%) rename {src => include/query/language}/cypher/ast/accessor.hpp (100%) rename {src => include/query/language}/cypher/ast/alias.hpp (100%) rename {src => include/query/language}/cypher/ast/ast.hpp (100%) rename {src => include/query/language}/cypher/ast/ast_echo.hpp (100%) rename {src => include/query/language}/cypher/ast/ast_node.hpp (100%) rename {src => include/query/language}/cypher/ast/ast_visitor.hpp (100%) rename {src => include/query/language}/cypher/ast/create.hpp (100%) rename {src => include/query/language}/cypher/ast/delete.hpp (51%) rename {src => include/query/language}/cypher/ast/distinct.hpp (100%) rename {src => include/query/language}/cypher/ast/expr.hpp (100%) rename {src => include/query/language}/cypher/ast/functions.hpp (100%) rename {src => include/query/language}/cypher/ast/identifier.hpp (100%) rename {src => include/query/language}/cypher/ast/list.hpp (100%) rename {src => include/query/language}/cypher/ast/match.hpp (100%) rename {src => include/query/language}/cypher/ast/node.hpp (100%) rename {src => include/query/language}/cypher/ast/operators.hpp (100%) rename {src => include/query/language}/cypher/ast/pattern.hpp (100%) rename {src => include/query/language}/cypher/ast/property.hpp (100%) rename {src => include/query/language}/cypher/ast/queries.hpp (100%) rename {src => include/query/language}/cypher/ast/relationship.hpp (100%) rename {src => include/query/language}/cypher/ast/return.hpp (100%) rename {src => include/query/language}/cypher/ast/set.hpp (100%) rename {src => include/query/language}/cypher/ast/start.hpp (100%) rename {src => include/query/language}/cypher/ast/tree.hpp (100%) rename {src => include/query/language}/cypher/ast/values.hpp (100%) rename {src => include/query/language}/cypher/ast/where.hpp (100%) rename {src => include/query/language}/cypher/ast/with.hpp (100%) rename {src => include/query/language}/cypher/common.hpp (100%) rename {src => include/query/language}/cypher/compiler.hpp (100%) rename {src => include/query/language}/cypher/cypher.y (96%) rename {src => include/query/language}/cypher/debug/tree_print.hpp (66%) create mode 100644 include/query/language/cypher/errors.hpp rename {src => include/query/language}/cypher/lexer.cpp (100%) rename {src => include/query/language}/cypher/parser.cpp (100%) rename {src => include/query/language}/cypher/parser.hpp (100%) rename {src => include/query/language}/cypher/token.hpp (100%) rename {src => include/query/language}/cypher/tokenizer/cypher_lexer.hpp (98%) rename {src => include/query/language}/cypher/tokenizer/lexer.hpp (94%) rename {src => include/query/language}/cypher/visitor/traverser.hpp (98%) rename include/{query_engine/code_compiler.hpp => query/plan/compiler.hpp} (70%) create mode 100644 include/query/plan/generator.hpp create mode 100644 include/query/plan/program.hpp rename include/{query_engine => query/plan}/program_executor.hpp (60%) rename include/{query_engine => query/plan}/program_loader.hpp (50%) create mode 100644 include/query/preprocesor.hpp create mode 100644 include/query/strip/stripped.hpp rename include/{query_engine/query_stripper.hpp => query/strip/stripper.hpp} (78%) rename include/{query_engine => query}/util.hpp (91%) delete mode 100644 include/query_engine/code_generator.hpp delete mode 100644 include/query_engine/code_generator/handlers/all.hpp delete mode 100644 include/query_engine/exceptions/errors.hpp delete mode 100644 include/query_engine/exceptions/exceptions.hpp delete mode 100644 include/query_engine/query_hasher.hpp delete mode 100644 include/query_engine/query_program.hpp delete mode 100644 include/query_engine/query_result.hpp delete mode 100644 include/query_engine/query_stripped.hpp create mode 100644 include/utils/exceptions/non_exaustive_switch.hpp create mode 100644 include/utils/exceptions/not_yet_implemented.hpp delete mode 100644 src/cypher/errors.hpp create mode 100644 tests/integration/__init__.py rename tests/integration/{internal => }/crud.py (100%) delete mode 100644 tests/integration/pilot/dressipi/crud.py delete mode 100644 tests/integration/pilot/dressipi/run.py create mode 100644 tests/integration/scenario.py create mode 100644 tests/integration/scenario/__init__.py create mode 100644 tests/integration/scenario/no_000001.py diff --git a/.clang-format b/.clang-format index d34cbdb68..b5072c076 100644 --- a/.clang-format +++ b/.clang-format @@ -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 ... diff --git a/CMakeLists.txt b/CMakeLists.txt index fbb8198d8..42cbf61ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/include/communication/bolt/v1/serialization/record_stream.hpp b/include/communication/bolt/v1/serialization/record_stream.hpp index 13aad4a11..25b51acd3 100644 --- a/include/communication/bolt/v1/serialization/record_stream.hpp +++ b/include/communication/bolt/v1/serialization/record_stream.hpp @@ -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 &fields) { // TODO: that should be one level below? diff --git a/include/communication/bolt/v1/states/executor.hpp b/include/communication/bolt/v1/states/executor.hpp index e614d57d2..80d4da949 100644 --- a/include/communication/bolt/v1/states/executor.hpp +++ b/include/communication/bolt/v1/states/executor.hpp @@ -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 { diff --git a/include/communication/bolt/v1/transport/streamed_bolt_decoder.hpp b/include/communication/bolt/v1/transport/streamed_bolt_decoder.hpp index fc7a8b037..c190690ae 100644 --- a/include/communication/bolt/v1/transport/streamed_bolt_decoder.hpp +++ b/include/communication/bolt/v1/transport/streamed_bolt_decoder.hpp @@ -3,7 +3,7 @@ #include #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" diff --git a/include/logging/loggable.hpp b/include/logging/loggable.hpp new file mode 100644 index 000000000..15b7d985e --- /dev/null +++ b/include/logging/loggable.hpp @@ -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; +}; diff --git a/include/query/backend/backend.hpp b/include/query/backend/backend.hpp new file mode 100644 index 000000000..1c3c735af --- /dev/null +++ b/include/query/backend/backend.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include "query/ir/tree/node.hpp" + +class Backend +{ +public: + virtual void process(ir::Node *node) = 0; + virtual ~Backend() {} +}; diff --git a/include/query/backend/code_generator.hpp b/include/query/backend/code_generator.hpp new file mode 100644 index 000000000..b8a74f9ed --- /dev/null +++ b/include/query/backend/code_generator.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include +#include + +#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(); } +}; diff --git a/include/query/backend/cpp/code_generator.hpp b/include/query/backend/cpp/code_generator.hpp new file mode 100644 index 000000000..b88bc31ec --- /dev/null +++ b/include/query/backend/cpp/code_generator.hpp @@ -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"); + + } +}; diff --git a/include/query_engine/code_generator/clause_action.hpp b/include/query/backend/cpp_old/clause_action.hpp similarity index 100% rename from include/query_engine/code_generator/clause_action.hpp rename to include/query/backend/cpp_old/clause_action.hpp diff --git a/include/query_engine/traverser/code.hpp b/include/query/backend/cpp_old/code.hpp similarity index 92% rename from include/query_engine/traverser/code.hpp rename to include/query/backend/cpp_old/code.hpp index df09381ca..e7419147f 100644 --- a/include/query_engine/traverser/code.hpp +++ b/include/query/backend/cpp_old/code.hpp @@ -1,11 +1,14 @@ #pragma once +// !! DEPRICATED !! + #include -#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; diff --git a/include/query_engine/code_generator/cpp_generator.hpp b/include/query/backend/cpp_old/cpp_generator.hpp similarity index 90% rename from include/query_engine/code_generator/cpp_generator.hpp rename to include/query/backend/cpp_old/cpp_generator.hpp index 6433c9fd1..90e2c22c3 100644 --- a/include/query_engine/code_generator/cpp_generator.hpp +++ b/include/query/backend/cpp_old/cpp_generator.hpp @@ -2,10 +2,10 @@ #include -#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); diff --git a/include/query/backend/cpp_old/cypher.hpp b/include/query/backend/cpp_old/cypher.hpp new file mode 100644 index 000000000..7c62632f8 --- /dev/null +++ b/include/query/backend/cpp_old/cypher.hpp @@ -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 +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 + 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().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; +}; diff --git a/include/query_engine/code_generator/cypher_state.hpp b/include/query/backend/cpp_old/cypher_state.hpp similarity index 81% rename from include/query_engine/code_generator/cypher_state.hpp rename to include/query/backend/cpp_old/cypher_state.hpp index 2822429cf..e477f5f9e 100644 --- a/include/query_engine/code_generator/cypher_state.hpp +++ b/include/query/backend/cpp_old/cypher_state.hpp @@ -5,8 +5,8 @@ #include #include -#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; + using tags_type = std::vector; using properties_type = std::map; 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{}; } 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 " + variable_name + " = "; - print += "{"; + "std::map " + 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; } }; diff --git a/include/query_engine/code_generator/entity_search.hpp b/include/query/backend/cpp_old/entity_search.hpp similarity index 100% rename from include/query_engine/code_generator/entity_search.hpp rename to include/query/backend/cpp_old/entity_search.hpp diff --git a/include/query/backend/cpp_old/handlers/all.hpp b/include/query/backend/cpp_old/handlers/all.hpp new file mode 100644 index 000000000..f7d54eba2 --- /dev/null +++ b/include/query/backend/cpp_old/handlers/all.hpp @@ -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" diff --git a/include/query_engine/code_generator/handlers/create.hpp b/include/query/backend/cpp_old/handlers/create.hpp similarity index 66% rename from include/query_engine/code_generator/handlers/create.hpp rename to include/query/backend/cpp_old/handlers/create.hpp index 1d5b6b7eb..746792925 100644 --- a/include/query_engine/code_generator/handlers/create.hpp +++ b/include/query/backend/cpp_old/handlers/create.hpp @@ -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); } diff --git a/include/query_engine/code_generator/handlers/delete.hpp b/include/query/backend/cpp_old/handlers/delete.hpp similarity index 58% rename from include/query_engine/code_generator/handlers/delete.hpp rename to include/query/backend/cpp_old/handlers/delete.hpp index 4a4fabb4b..31b68ac6c 100644 --- a/include/query_engine/code_generator/handlers/delete.hpp +++ b/include/query/backend/cpp_old/handlers/delete.hpp @@ -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); diff --git a/include/query_engine/code_generator/handlers/includes.hpp b/include/query/backend/cpp_old/handlers/includes.hpp similarity index 76% rename from include/query_engine/code_generator/handlers/includes.hpp rename to include/query/backend/cpp_old/handlers/includes.hpp index c1c24d409..eea8a96d7 100644 --- a/include/query_engine/code_generator/handlers/includes.hpp +++ b/include/query/backend/cpp_old/handlers/includes.hpp @@ -6,12 +6,13 @@ #include #include -#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; diff --git a/include/query_engine/code_generator/handlers/match.hpp b/include/query/backend/cpp_old/handlers/match.hpp similarity index 92% rename from include/query_engine/code_generator/handlers/match.hpp rename to include/query/backend/cpp_old/handlers/match.hpp index eeb1ce4bc..e47318b42 100644 --- a/include/query_engine/code_generator/handlers/match.hpp +++ b/include/query/backend/cpp_old/handlers/match.hpp @@ -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); diff --git a/include/query_engine/code_generator/handlers/return.hpp b/include/query/backend/cpp_old/handlers/return.hpp similarity index 73% rename from include/query_engine/code_generator/handlers/return.hpp rename to include/query/backend/cpp_old/handlers/return.hpp index dd2d414dc..0867be83e 100644 --- a/include/query_engine/code_generator/handlers/return.hpp +++ b/include/query/backend/cpp_old/handlers/return.hpp @@ -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 diff --git a/include/query_engine/code_generator/handlers/set.hpp b/include/query/backend/cpp_old/handlers/set.hpp similarity index 93% rename from include/query_engine/code_generator/handlers/set.hpp rename to include/query/backend/cpp_old/handlers/set.hpp index 73e513738..324411a3b 100644 --- a/include/query_engine/code_generator/handlers/set.hpp +++ b/include/query/backend/cpp_old/handlers/set.hpp @@ -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 { diff --git a/include/query_engine/code_generator/handlers/transaction_begin.hpp b/include/query/backend/cpp_old/handlers/transaction_begin.hpp similarity index 76% rename from include/query_engine/code_generator/handlers/transaction_begin.hpp rename to include/query/backend/cpp_old/handlers/transaction_begin.hpp index 52bfc4ce8..1030a766c 100644 --- a/include/query_engine/code_generator/handlers/transaction_begin.hpp +++ b/include/query/backend/cpp_old/handlers/transaction_begin.hpp @@ -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 { diff --git a/include/query_engine/code_generator/handlers/transaction_commit.hpp b/include/query/backend/cpp_old/handlers/transaction_commit.hpp similarity index 79% rename from include/query_engine/code_generator/handlers/transaction_commit.hpp rename to include/query/backend/cpp_old/handlers/transaction_commit.hpp index a19749dea..71998a8de 100644 --- a/include/query_engine/code_generator/handlers/transaction_commit.hpp +++ b/include/query/backend/cpp_old/handlers/transaction_commit.hpp @@ -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 { diff --git a/include/query_engine/code_generator/namer.hpp b/include/query/backend/cpp_old/namer.hpp similarity index 100% rename from include/query_engine/code_generator/namer.hpp rename to include/query/backend/cpp_old/namer.hpp diff --git a/include/query_engine/code_generator/query_action.hpp b/include/query/backend/cpp_old/query_action.hpp similarity index 100% rename from include/query_engine/code_generator/query_action.hpp rename to include/query/backend/cpp_old/query_action.hpp diff --git a/include/query_engine/code_generator/query_action_data.hpp b/include/query/backend/cpp_old/query_action_data.hpp similarity index 93% rename from include/query_engine/code_generator/query_action_data.hpp rename to include/query/backend/cpp_old/query_action_data.hpp index 22a994c08..1ef09db1c 100644 --- a/include/query_engine/code_generator/query_action_data.hpp +++ b/include/query/backend/cpp_old/query_action_data.hpp @@ -4,9 +4,9 @@ #include #include -#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 entity_data; std::map relationship_data; std::vector 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; } diff --git a/include/query_engine/code_generator/structures.hpp b/include/query/backend/cpp_old/structures.hpp similarity index 100% rename from include/query_engine/code_generator/structures.hpp rename to include/query/backend/cpp_old/structures.hpp diff --git a/include/query/backend/llvm/code_generator.hpp b/include/query/backend/llvm/code_generator.hpp new file mode 100644 index 000000000..3302e4e29 --- /dev/null +++ b/include/query/backend/llvm/code_generator.hpp @@ -0,0 +1,3 @@ +#pragma once + +// TODO: implementation diff --git a/include/query_engine/memgraph_dynamic_lib.hpp b/include/query/dynamic_lib.hpp similarity index 78% rename from include/query_engine/memgraph_dynamic_lib.hpp rename to include/query/dynamic_lib.hpp index 5a1bcb2a3..e28757cf6 100644 --- a/include/query_engine/memgraph_dynamic_lib.hpp +++ b/include/query/dynamic_lib.hpp @@ -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; using destruct = destruct_t; - using lib_object = ICodeCPU; + using lib_object = IPlanCPU; }; template diff --git a/include/query_engine/query_engine.hpp b/include/query/engine.hpp similarity index 81% rename from include/query_engine/query_engine.hpp rename to include/query/engine.hpp index bdf3344b3..a468244dd 100644 --- a/include/query_engine/query_engine.hpp +++ b/include/query/engine.hpp @@ -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; } } diff --git a/include/query/exception/cpp_code_generator.hpp b/include/query/exception/cpp_code_generator.hpp new file mode 100644 index 000000000..7f61c8628 --- /dev/null +++ b/include/query/exception/cpp_code_generator.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "utils/exceptions/basic_exception.hpp" + +class CppCodeGeneratorException : public BasicException +{ +public: + using BasicException::BasicException; +}; diff --git a/include/query/exception/decoder_exception.hpp b/include/query/exception/decoder_exception.hpp new file mode 100644 index 000000000..86458f2ef --- /dev/null +++ b/include/query/exception/decoder_exception.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "utils/exceptions/basic_exception.hpp" + +class DecoderException : public BasicException +{ +public: + using BasicException::BasicException; +}; diff --git a/include/query/exception/out_of_memory.hpp b/include/query/exception/out_of_memory.hpp new file mode 100644 index 000000000..96635781b --- /dev/null +++ b/include/query/exception/out_of_memory.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "utils/exceptions/basic_exception.hpp" + +class OutOfMemory : public BasicException +{ +public: + using BasicException::BasicException; +}; diff --git a/include/query/exception/plan_compilation.hpp b/include/query/exception/plan_compilation.hpp new file mode 100644 index 000000000..e722a21e5 --- /dev/null +++ b/include/query/exception/plan_compilation.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "utils/exceptions/basic_exception.hpp" + +class PlanCompilationException : public BasicException +{ +public: + using BasicException::BasicException; +}; diff --git a/include/query/exception/plan_execution.hpp b/include/query/exception/plan_execution.hpp new file mode 100644 index 000000000..58b9f7531 --- /dev/null +++ b/include/query/exception/plan_execution.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "utils/exceptions/basic_exception.hpp" + +class PlanExecutionException : public BasicException +{ +public: + using BasicException::BasicException; +}; diff --git a/include/query/exception/query_engine.hpp b/include/query/exception/query_engine.hpp new file mode 100644 index 000000000..150051fc3 --- /dev/null +++ b/include/query/exception/query_engine.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "utils/exceptions/basic_exception.hpp" + +class QueryEngineException : public BasicException +{ +public: + using BasicException::BasicException; +}; diff --git a/include/query/frontend/cypher.hpp b/include/query/frontend/cypher.hpp new file mode 100644 index 000000000..379371790 --- /dev/null +++ b/include/query/frontend/cypher.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include + +#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; +}; + +} diff --git a/include/query_engine/traverser/cpp_traverser.hpp b/include/query/frontend/cypher/traverser.hpp similarity index 92% rename from include/query_engine/traverser/cpp_traverser.hpp rename to include/query/frontend/cypher/traverser.hpp index ac077d6d0..d64660e47 100644 --- a/include/query_engine/traverser/cpp_traverser.hpp +++ b/include/query/frontend/cypher/traverser.hpp @@ -2,13 +2,13 @@ #include -#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; // } } }; diff --git a/include/query/frontend/opencypher.hpp b/include/query/frontend/opencypher.hpp new file mode 100644 index 000000000..8b38c3fa9 --- /dev/null +++ b/include/query/frontend/opencypher.hpp @@ -0,0 +1,10 @@ +#pragma once + +namespace opencypher +{ + +class Fronted +{ +}; + +} diff --git a/include/query/frontend/opencypher/traverser.hpp b/include/query/frontend/opencypher/traverser.hpp new file mode 100644 index 000000000..3302e4e29 --- /dev/null +++ b/include/query/frontend/opencypher/traverser.hpp @@ -0,0 +1,3 @@ +#pragma once + +// TODO: implementation diff --git a/include/query_engine/hardcode/queries.hpp b/include/query/hardcode/queries.hpp similarity index 99% rename from include/query_engine/hardcode/queries.hpp rename to include/query/hardcode/queries.hpp index f7c773617..c2c839316 100644 --- a/include/query_engine/hardcode/queries.hpp +++ b/include/query/hardcode/queries.hpp @@ -18,6 +18,7 @@ namespace barrier #include #include #include + #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 diff --git a/include/query_engine/i_code_cpu.hpp b/include/query/i_plan_cpu.hpp similarity index 53% rename from include/query_engine/i_code_cpu.hpp rename to include/query/i_plan_cpu.hpp index b78ca803d..395bd7108 100644 --- a/include/query_engine/i_code_cpu.hpp +++ b/include/query/i_plan_cpu.hpp @@ -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 -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 -using produce_t = ICodeCPU *(*)(); +using produce_t = IPlanCPU *(*)(); template -using destruct_t = void (*)(ICodeCPU *); +using destruct_t = void (*)(IPlanCPU *); diff --git a/tests/integration/pilot/dressipi/__init__.py b/include/query/ir/tree/create.hpp similarity index 100% rename from tests/integration/pilot/dressipi/__init__.py rename to include/query/ir/tree/create.hpp diff --git a/include/query/ir/tree/delete.hpp b/include/query/ir/tree/delete.hpp new file mode 100644 index 000000000..e69de29bb diff --git a/include/query/ir/tree/edge.hpp b/include/query/ir/tree/edge.hpp new file mode 100644 index 000000000..e69de29bb diff --git a/include/query/ir/tree/node.hpp b/include/query/ir/tree/node.hpp new file mode 100644 index 000000000..6d331fd15 --- /dev/null +++ b/include/query/ir/tree/node.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +#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> childs; + Node *parent; +}; +} diff --git a/include/query/ir/tree/query.hpp b/include/query/ir/tree/query.hpp new file mode 100644 index 000000000..9be39246b --- /dev/null +++ b/include/query/ir/tree/query.hpp @@ -0,0 +1,5 @@ +#pragma once + +class Query : public Node +{ +}; diff --git a/include/query/ir/tree/read.hpp b/include/query/ir/tree/read.hpp new file mode 100644 index 000000000..e69de29bb diff --git a/include/query/ir/tree/tree.hpp b/include/query/ir/tree/tree.hpp new file mode 100644 index 000000000..e69de29bb diff --git a/include/query/ir/tree/update.hpp b/include/query/ir/tree/update.hpp new file mode 100644 index 000000000..e69de29bb diff --git a/include/query/ir/tree/vertex.hpp b/include/query/ir/tree/vertex.hpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/cypher/.gitignore b/include/query/language/cypher/.gitignore similarity index 100% rename from src/cypher/.gitignore rename to include/query/language/cypher/.gitignore diff --git a/src/cypher/ast/accessor.hpp b/include/query/language/cypher/ast/accessor.hpp similarity index 100% rename from src/cypher/ast/accessor.hpp rename to include/query/language/cypher/ast/accessor.hpp diff --git a/src/cypher/ast/alias.hpp b/include/query/language/cypher/ast/alias.hpp similarity index 100% rename from src/cypher/ast/alias.hpp rename to include/query/language/cypher/ast/alias.hpp diff --git a/src/cypher/ast/ast.hpp b/include/query/language/cypher/ast/ast.hpp similarity index 100% rename from src/cypher/ast/ast.hpp rename to include/query/language/cypher/ast/ast.hpp diff --git a/src/cypher/ast/ast_echo.hpp b/include/query/language/cypher/ast/ast_echo.hpp similarity index 100% rename from src/cypher/ast/ast_echo.hpp rename to include/query/language/cypher/ast/ast_echo.hpp diff --git a/src/cypher/ast/ast_node.hpp b/include/query/language/cypher/ast/ast_node.hpp similarity index 100% rename from src/cypher/ast/ast_node.hpp rename to include/query/language/cypher/ast/ast_node.hpp diff --git a/src/cypher/ast/ast_visitor.hpp b/include/query/language/cypher/ast/ast_visitor.hpp similarity index 100% rename from src/cypher/ast/ast_visitor.hpp rename to include/query/language/cypher/ast/ast_visitor.hpp diff --git a/src/cypher/ast/create.hpp b/include/query/language/cypher/ast/create.hpp similarity index 100% rename from src/cypher/ast/create.hpp rename to include/query/language/cypher/ast/create.hpp diff --git a/src/cypher/ast/delete.hpp b/include/query/language/cypher/ast/delete.hpp similarity index 51% rename from src/cypher/ast/delete.hpp rename to include/query/language/cypher/ast/delete.hpp index b2a8a8985..1cbdbed05 100644 --- a/src/cypher/ast/delete.hpp +++ b/include/query/language/cypher/ast/delete.hpp @@ -8,10 +8,11 @@ namespace ast struct Delete : public AstNode { - Delete(Identifier* identifier) - : identifier(identifier) {} - + Delete(Identifier* identifier, bool is_detached = false) + : identifier(identifier), is_detached(is_detached) {} + Identifier* identifier; + bool is_detached; }; } diff --git a/src/cypher/ast/distinct.hpp b/include/query/language/cypher/ast/distinct.hpp similarity index 100% rename from src/cypher/ast/distinct.hpp rename to include/query/language/cypher/ast/distinct.hpp diff --git a/src/cypher/ast/expr.hpp b/include/query/language/cypher/ast/expr.hpp similarity index 100% rename from src/cypher/ast/expr.hpp rename to include/query/language/cypher/ast/expr.hpp diff --git a/src/cypher/ast/functions.hpp b/include/query/language/cypher/ast/functions.hpp similarity index 100% rename from src/cypher/ast/functions.hpp rename to include/query/language/cypher/ast/functions.hpp diff --git a/src/cypher/ast/identifier.hpp b/include/query/language/cypher/ast/identifier.hpp similarity index 100% rename from src/cypher/ast/identifier.hpp rename to include/query/language/cypher/ast/identifier.hpp diff --git a/src/cypher/ast/list.hpp b/include/query/language/cypher/ast/list.hpp similarity index 100% rename from src/cypher/ast/list.hpp rename to include/query/language/cypher/ast/list.hpp diff --git a/src/cypher/ast/match.hpp b/include/query/language/cypher/ast/match.hpp similarity index 100% rename from src/cypher/ast/match.hpp rename to include/query/language/cypher/ast/match.hpp diff --git a/src/cypher/ast/node.hpp b/include/query/language/cypher/ast/node.hpp similarity index 100% rename from src/cypher/ast/node.hpp rename to include/query/language/cypher/ast/node.hpp diff --git a/src/cypher/ast/operators.hpp b/include/query/language/cypher/ast/operators.hpp similarity index 100% rename from src/cypher/ast/operators.hpp rename to include/query/language/cypher/ast/operators.hpp diff --git a/src/cypher/ast/pattern.hpp b/include/query/language/cypher/ast/pattern.hpp similarity index 100% rename from src/cypher/ast/pattern.hpp rename to include/query/language/cypher/ast/pattern.hpp diff --git a/src/cypher/ast/property.hpp b/include/query/language/cypher/ast/property.hpp similarity index 100% rename from src/cypher/ast/property.hpp rename to include/query/language/cypher/ast/property.hpp diff --git a/src/cypher/ast/queries.hpp b/include/query/language/cypher/ast/queries.hpp similarity index 100% rename from src/cypher/ast/queries.hpp rename to include/query/language/cypher/ast/queries.hpp diff --git a/src/cypher/ast/relationship.hpp b/include/query/language/cypher/ast/relationship.hpp similarity index 100% rename from src/cypher/ast/relationship.hpp rename to include/query/language/cypher/ast/relationship.hpp diff --git a/src/cypher/ast/return.hpp b/include/query/language/cypher/ast/return.hpp similarity index 100% rename from src/cypher/ast/return.hpp rename to include/query/language/cypher/ast/return.hpp diff --git a/src/cypher/ast/set.hpp b/include/query/language/cypher/ast/set.hpp similarity index 100% rename from src/cypher/ast/set.hpp rename to include/query/language/cypher/ast/set.hpp diff --git a/src/cypher/ast/start.hpp b/include/query/language/cypher/ast/start.hpp similarity index 100% rename from src/cypher/ast/start.hpp rename to include/query/language/cypher/ast/start.hpp diff --git a/src/cypher/ast/tree.hpp b/include/query/language/cypher/ast/tree.hpp similarity index 100% rename from src/cypher/ast/tree.hpp rename to include/query/language/cypher/ast/tree.hpp diff --git a/src/cypher/ast/values.hpp b/include/query/language/cypher/ast/values.hpp similarity index 100% rename from src/cypher/ast/values.hpp rename to include/query/language/cypher/ast/values.hpp diff --git a/src/cypher/ast/where.hpp b/include/query/language/cypher/ast/where.hpp similarity index 100% rename from src/cypher/ast/where.hpp rename to include/query/language/cypher/ast/where.hpp diff --git a/src/cypher/ast/with.hpp b/include/query/language/cypher/ast/with.hpp similarity index 100% rename from src/cypher/ast/with.hpp rename to include/query/language/cypher/ast/with.hpp diff --git a/src/cypher/common.hpp b/include/query/language/cypher/common.hpp similarity index 100% rename from src/cypher/common.hpp rename to include/query/language/cypher/common.hpp diff --git a/src/cypher/compiler.hpp b/include/query/language/cypher/compiler.hpp similarity index 100% rename from src/cypher/compiler.hpp rename to include/query/language/cypher/compiler.hpp diff --git a/src/cypher/cypher.y b/include/query/language/cypher/cypher.y similarity index 96% rename from src/cypher/cypher.y rename to include/query/language/cypher/cypher.y index 2081f4a11..fa3e81085 100644 --- a/src/cypher/cypher.y +++ b/include/query/language/cypher/cypher.y @@ -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 #include - #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(I); + D = ast->create(I, false); +} + +delete_clause(D) ::= DETACH DELETE idn(I). { + D = ast->create(I, true); } // ---- pattern list diff --git a/src/cypher/debug/tree_print.hpp b/include/query/language/cypher/debug/tree_print.hpp similarity index 66% rename from src/cypher/debug/tree_print.hpp rename to include/query/language/cypher/debug/tree_print.hpp index b7a21e2db..89f29b7e2 100644 --- a/src/cypher/debug/tree_print.hpp +++ b/include/query/language/cypher/debug/tree_print.hpp @@ -3,7 +3,7 @@ #include #include -#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 - 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 <_expr) override { auto entry = printer.advance("Less Than"); Traverser::visit(lt_expr); } - void visit(ast::Gt& gt_expr) override + void visit(ast::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); diff --git a/include/query/language/cypher/errors.hpp b/include/query/language/cypher/errors.hpp new file mode 100644 index 000000000..e43b1381f --- /dev/null +++ b/include/query/language/cypher/errors.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include + +#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) + { + } +}; diff --git a/src/cypher/lexer.cpp b/include/query/language/cypher/lexer.cpp similarity index 100% rename from src/cypher/lexer.cpp rename to include/query/language/cypher/lexer.cpp diff --git a/src/cypher/parser.cpp b/include/query/language/cypher/parser.cpp similarity index 100% rename from src/cypher/parser.cpp rename to include/query/language/cypher/parser.cpp diff --git a/src/cypher/parser.hpp b/include/query/language/cypher/parser.hpp similarity index 100% rename from src/cypher/parser.hpp rename to include/query/language/cypher/parser.hpp diff --git a/src/cypher/token.hpp b/include/query/language/cypher/token.hpp similarity index 100% rename from src/cypher/token.hpp rename to include/query/language/cypher/token.hpp diff --git a/src/cypher/tokenizer/cypher_lexer.hpp b/include/query/language/cypher/tokenizer/cypher_lexer.hpp similarity index 98% rename from src/cypher/tokenizer/cypher_lexer.hpp rename to include/query/language/cypher/tokenizer/cypher_lexer.hpp index 971fbb5f3..d4ca665f2 100644 --- a/src/cypher/tokenizer/cypher_lexer.hpp +++ b/include/query/language/cypher/tokenizer/cypher_lexer.hpp @@ -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 diff --git a/src/cypher/tokenizer/lexer.hpp b/include/query/language/cypher/tokenizer/lexer.hpp similarity index 94% rename from src/cypher/tokenizer/lexer.hpp rename to include/query/language/cypher/tokenizer/lexer.hpp index c9d27824f..1075ea40a 100644 --- a/src/cypher/tokenizer/lexer.hpp +++ b/include/query/language/cypher/tokenizer/lexer.hpp @@ -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(-1)) - throw LexicalError(token); + throw CypherLexicalError(token); return token; } diff --git a/src/cypher/visitor/traverser.hpp b/include/query/language/cypher/visitor/traverser.hpp similarity index 98% rename from src/cypher/visitor/traverser.hpp rename to include/query/language/cypher/visitor/traverser.hpp index 941fa28d6..be1d3cc92 100644 --- a/src/cypher/visitor/traverser.hpp +++ b/include/query/language/cypher/visitor/traverser.hpp @@ -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 { diff --git a/include/query_engine/code_compiler.hpp b/include/query/plan/compiler.hpp similarity index 70% rename from include/query_engine/code_compiler.hpp rename to include/query/plan/compiler.hpp index 7a98333e0..f63983504 100644 --- a/include/query_engine/code_compiler.hpp +++ b/include/query/plan/compiler.hpp @@ -2,24 +2,24 @@ #include -#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, diff --git a/include/query/plan/generator.hpp b/include/query/plan/generator.hpp new file mode 100644 index 000000000..90201821a --- /dev/null +++ b/include/query/plan/generator.hpp @@ -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 +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; +}; diff --git a/include/query/plan/program.hpp b/include/query/plan/program.hpp new file mode 100644 index 000000000..06843cb9c --- /dev/null +++ b/include/query/plan/program.hpp @@ -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 +struct QueryProgram +{ + using plan_t = IPlanCPU; + + QueryProgram(plan_t *plan, QueryStripped &&stripped) + : plan(plan), stripped(std::forward(stripped)) + { + } + + QueryProgram(QueryProgram &other) = delete; + QueryProgram(QueryProgram &&other) = default; + + plan_t *plan; + QueryStripped stripped; +}; diff --git a/include/query_engine/program_executor.hpp b/include/query/plan/program_executor.hpp similarity index 60% rename from include/query_engine/program_executor.hpp rename to include/query/plan/program_executor.hpp index 1f2bd694b..8a00828e8 100644 --- a/include/query_engine/program_executor.hpp +++ b/include/query/plan/program_executor.hpp @@ -3,9 +3,10 @@ #include #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 &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(""); } } }; diff --git a/include/query_engine/program_loader.hpp b/include/query/plan/program_loader.hpp similarity index 50% rename from include/query_engine/program_loader.hpp rename to include/query/plan/program_loader.hpp index ae7255ff2..513289d0c 100644 --- a/include/query_engine/program_loader.hpp +++ b/include/query/plan/program_loader.hpp @@ -5,16 +5,16 @@ #include #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 class ProgramLoader @@ -24,40 +24,34 @@ public: using sptr_code_lib = std::shared_ptr; using query_program_t = QueryProgram; - 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 stripper; - // TODO ifdef MEMGRAPH64 problem, how to use this kind // of ifdef functions? // uint64_t depends on fnv function std::unordered_map code_libs; - CodeGenerator 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; + PlanGenerator plan_generator; + + PlanCompiler plan_compiler; + + sptr_code_lib load_code_lib(const std::string &path) { sptr_code_lib code_lib = std::make_shared>(path); code_lib->load(); diff --git a/include/query/preprocesor.hpp b/include/query/preprocesor.hpp new file mode 100644 index 000000000..a7305b11d --- /dev/null +++ b/include/query/preprocesor.hpp @@ -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 stripper; +}; diff --git a/include/query/strip/stripped.hpp b/include/query/strip/stripped.hpp new file mode 100644 index 000000000..b8627041c --- /dev/null +++ b/include/query/strip/stripped.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include + +#include "storage/model/properties/property.hpp" + +/* + * Query Plan Arguments Type + */ +using plan_args_t = std::vector; + +/* + * 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(query)), + arguments(std::forward(arguments)), hash(hash) + { + } + QueryStripped(QueryStripped &other) = delete; + QueryStripped(QueryStripped &&other) = default; + + std::string query; + plan_args_t arguments; + uint64_t hash; +}; diff --git a/include/query_engine/query_stripper.hpp b/include/query/strip/stripper.hpp similarity index 78% rename from include/query_engine/query_stripper.hpp rename to include/query/strip/stripper.hpp index d577da0cf..decc63325 100644 --- a/include/query_engine/query_stripper.hpp +++ b/include/query/strip/stripper.hpp @@ -7,9 +7,9 @@ #include #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 -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 -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(strip_types)...)), lexer(std::make_unique()) { @@ -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::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{})) { + while (auto token = tokenizer.lookup()) + { + if (_or(token.id, strip_types, std::make_index_sequence{})) + { 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 strip_types; CypherLexer::uptr lexer; diff --git a/include/query_engine/util.hpp b/include/query/util.hpp similarity index 91% rename from include/query_engine/util.hpp rename to include/query/util.hpp index d8fe8210a..b7294dc21 100644 --- a/include/query_engine/util.hpp +++ b/include/query/util.hpp @@ -7,12 +7,12 @@ #include "fmt/format.h" #include "logging/default.hpp" -#include "query_engine/exceptions/errors.hpp" #include "storage/model/properties/properties.hpp" #include "storage/model/properties/property.hpp" #include "storage/model/properties/traversers/consolewriter.hpp" #include "storage/model/properties/traversers/jsonwriter.hpp" #include "utils/types/byte.hpp" +#include "utils/exceptions/basic_exception.hpp" using std::cout; using std::endl; @@ -38,6 +38,12 @@ void cout_property(const StoredProperty &property); namespace { +class CodeLineFormatException : public BasicException +{ +public: + using BasicException::BasicException; +}; + template std::string format(const std::string &format_str, const Args &... args) { @@ -50,7 +56,7 @@ std::string code_line(const std::string &format_str, const Args &... args) try { return "\t" + format(format_str, args...) + "\n"; } catch (std::runtime_error &e) { - throw CodeGenerationError(std::string(e.what()) + " " + format_str); + throw CodeLineFormatException(std::string(e.what()) + " " + format_str); } } diff --git a/include/query_engine/code_generator.hpp b/include/query_engine/code_generator.hpp deleted file mode 100644 index 704385ddb..000000000 --- a/include/query_engine/code_generator.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once - -#include "config/config.hpp" -#include "cypher/ast/ast.hpp" -#include "cypher/compiler.hpp" -#include "logging/default.hpp" -#include "query_engine/exceptions/errors.hpp" -#include "template_engine/engine.hpp" -#include "traverser/cpp_traverser.hpp" -#include "utils/string/file.hpp" -#include "utils/type_discovery.hpp" - -using std::string; - -template -class CodeGenerator -{ -public: - CodeGenerator() : logger(logging::log->logger("CodeGenerator")) {} - - void generate_cpp(const std::string &query, const uint64_t stripped_hash, - const std::string &path) - { - // TODO: optimize; one time initialization -> be careful that object - // has a state - // TODO: multithread test - CppTraverser cpp_traverser; - - // get paths -#ifdef BARRIER - string template_path = CONFIG(config::BARRIER_TEMPLATE_CPU_CPP_PATH); -#else - string template_path = CONFIG(config::TEMPLATE_CPU_CPP_PATH); -#endif - string template_file = utils::read_file(template_path.c_str()); - - // syntax tree generation - try { - tree = compiler.syntax_tree(query); - } catch (const std::runtime_error &e) { - logger.error("Syntax error: {}", query); - throw QueryEngineException(std::string(e.what())); - } - - cpp_traverser.reset(); - - // code generation - try { - tree.root->accept(cpp_traverser); - } catch (const SemanticError &e) { - throw e; - } catch (const std::exception &e) { - logger.error("AST traversal error: {}", std::string(e.what())); - throw QueryEngineException("Unknown code generation error"); - } - - // save the code - 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().to_string()}, -#endif - {"code", cpp_traverser.code}}); - - logger.debug("generated code: {}", generated); - - utils::write_file(generated, path); - } - -protected: - Logger logger; - -private: - template_engine::TemplateEngine template_engine; - ast::Ast tree; - cypher::Compiler compiler; -}; diff --git a/include/query_engine/code_generator/handlers/all.hpp b/include/query_engine/code_generator/handlers/all.hpp deleted file mode 100644 index 1561d953f..000000000 --- a/include/query_engine/code_generator/handlers/all.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -// TODO: refactor build state machine instead of ifs - -#include "query_engine/code_generator/handlers/create.hpp" -#include "query_engine/code_generator/handlers/delete.hpp" -#include "query_engine/code_generator/handlers/match.hpp" -#include "query_engine/code_generator/handlers/return.hpp" -#include "query_engine/code_generator/handlers/set.hpp" -#include "query_engine/code_generator/handlers/transaction_begin.hpp" -#include "query_engine/code_generator/handlers/transaction_commit.hpp" diff --git a/include/query_engine/exceptions/errors.hpp b/include/query_engine/exceptions/errors.hpp deleted file mode 100644 index 8eb87318f..000000000 --- a/include/query_engine/exceptions/errors.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "utils/exceptions/basic_exception.hpp" - -// TODO: optimaze exceptions in respect to cypher/errors.hpp - -class SemanticError : public BasicException -{ -public: - SemanticError(const std::string& what) : - BasicException("Semantic error: " + what) {} -}; - -class CodeGenerationError : public BasicException -{ -public: - CodeGenerationError(const std::string& what) : - BasicException("Code Generation error: " + what) {} -}; diff --git a/include/query_engine/exceptions/exceptions.hpp b/include/query_engine/exceptions/exceptions.hpp deleted file mode 100644 index a4b4dbb59..000000000 --- a/include/query_engine/exceptions/exceptions.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include "utils/exceptions/basic_exception.hpp" - -class QueryEngineException : public BasicException -{ -public: - using BasicException::BasicException; -}; - -class CppGeneratorException : public BasicException -{ -public: - using BasicException::BasicException; -}; - -class DecoderException : public BasicException -{ -public: - using BasicException::BasicException; -}; - -class NotYetImplemented : public BasicException -{ -public: - using BasicException::BasicException; -}; - -class NonExhaustiveSwitch : public BasicException -{ -public: - using BasicException::BasicException; -}; - -class OutOfMemory : public BasicException -{ -public: - using BasicException::BasicException; -}; diff --git a/include/query_engine/query_hasher.hpp b/include/query_engine/query_hasher.hpp deleted file mode 100644 index 975ff691e..000000000 --- a/include/query_engine/query_hasher.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "cypher/common.hpp" -#include "query_stripper.hpp" -#include "utils/hashing/fnv.hpp" - -class QueryHasher -{ -public: - QueryHasher() - : stripper(make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL)) {} - - std::string hash(std::string &query) - { - auto stripped = stripper.strip(query); - auto stripped_hash = fnv(stripped.query); - auto hash_string = std::to_string(stripped_hash); - return hash_string; - } - -private: - QueryStripper stripper; -}; diff --git a/include/query_engine/query_program.hpp b/include/query_engine/query_program.hpp deleted file mode 100644 index 56d43ea41..000000000 --- a/include/query_engine/query_program.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "query_engine/i_code_cpu.hpp" -#include "query_engine/query_stripped.hpp" - -template -struct QueryProgram -{ - using code_t = ICodeCPU; - - QueryProgram(code_t *code, QueryStripped &&stripped) - : code(code), stripped(std::forward(stripped)) - { - } - - QueryProgram(QueryProgram &other) = delete; - QueryProgram(QueryProgram &&other) = default; - - code_t *code; - QueryStripped stripped; -}; diff --git a/include/query_engine/query_result.hpp b/include/query_engine/query_result.hpp deleted file mode 100644 index 6ed096daf..000000000 --- a/include/query_engine/query_result.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -// !! DEPRICATED !! -// TODO: DELETE - -#include -#include -#include -#include - -#include "storage/model/properties/properties.hpp" - -template -struct ResultList -{ - using sptr = std::shared_ptr; - using data_t = std::vector *>; - - ResultList() = default; - ResultList(ResultList &other) = delete; - ResultList(ResultList &&other) = default; - ResultList(data_t &&data) : data(std::forward(data)) {} - - explicit operator bool() const { return data.size() > 0; } - - std::vector *> data; -}; - -template -struct QueryResult -{ - using sptr = std::shared_ptr; - using data_t = - std::unordered_map::sptr>; - - QueryResult() = default; - QueryResult(QueryResult &other) = delete; - QueryResult(QueryResult &&other) = default; - QueryResult(data_t &&data) : data(std::forward(data)) {} - - explicit operator bool() const { return data.size() > 0; } - - data_t data; -}; diff --git a/include/query_engine/query_stripped.hpp b/include/query_engine/query_stripped.hpp deleted file mode 100644 index 49fb22396..000000000 --- a/include/query_engine/query_stripped.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include - -#include "storage/model/properties/property.hpp" - -using code_args_t = std::vector; - -struct QueryStripped -{ - QueryStripped(const std::string &&query, uint64_t hash, - code_args_t &&arguments) - : query(std::forward(query)), hash(hash), - arguments(std::forward(arguments)) - { - } - - QueryStripped(QueryStripped &other) = delete; - QueryStripped(QueryStripped &&other) = default; - - std::string query; - uint64_t hash; - code_args_t arguments; -}; diff --git a/include/storage/indexes/indexes.hpp b/include/storage/indexes/indexes.hpp index 69a344f5b..677d21fea 100644 --- a/include/storage/indexes/indexes.hpp +++ b/include/storage/indexes/indexes.hpp @@ -1,13 +1,14 @@ #pragma once #include "database/db.hpp" -#include "query_engine/exceptions/exceptions.hpp" #include "storage/garbage/garbage.hpp" #include "storage/graph.hpp" #include "storage/indexes/impl/nonunique_unordered_index.hpp" #include "storage/indexes/impl/unique_ordered_index.hpp" #include "storage/indexes/index_definition.hpp" #include "transactions/engine.hpp" +#include "utils/exceptions/non_exaustive_switch.hpp" +#include "utils/exceptions/not_yet_implemented.hpp" // Operation on indexes in the This should be the only place which knows how // to get all indexes in database. diff --git a/include/template_engine/engine.hpp b/include/template_engine/engine.hpp index 1df56f802..ec5f3db04 100644 --- a/include/template_engine/engine.hpp +++ b/include/template_engine/engine.hpp @@ -9,10 +9,6 @@ namespace template_engine using std::string; using data = std::unordered_map; -class TemplateEngine -{ -public: - string render(const string& form, const data& partials); -}; +string render(const string& form, const data& partials); } diff --git a/include/utils/exceptions/non_exaustive_switch.hpp b/include/utils/exceptions/non_exaustive_switch.hpp new file mode 100644 index 000000000..96e914cde --- /dev/null +++ b/include/utils/exceptions/non_exaustive_switch.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "utils/exceptions/basic_exception.hpp" + +class NonExhaustiveSwitch : public BasicException +{ +public: + using BasicException::BasicException; +}; diff --git a/include/utils/exceptions/not_yet_implemented.hpp b/include/utils/exceptions/not_yet_implemented.hpp new file mode 100644 index 000000000..b9b4b563b --- /dev/null +++ b/include/utils/exceptions/not_yet_implemented.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include "utils/exceptions/basic_exception.hpp" + +class NotYetImplemented : public BasicException +{ +public: + using BasicException::BasicException; +}; diff --git a/src/communication/bolt/v1/states/executor.cpp b/src/communication/bolt/v1/states/executor.cpp index c38d4d323..4d3371235 100644 --- a/src/communication/bolt/v1/states/executor.cpp +++ b/src/communication/bolt/v1/states/executor.cpp @@ -1,5 +1,5 @@ -#include "communication/bolt/v1/messaging/codes.hpp" #include "communication/bolt/v1/states/executor.hpp" +#include "communication/bolt/v1/messaging/codes.hpp" #ifdef BARRIER #include "barrier/barrier.cpp" @@ -20,30 +20,42 @@ State *Executor::run(Session &session) auto message_type = session.decoder.read_byte(); - if (message_type == MessageCode::Run) { + if (message_type == MessageCode::Run) + { Query q; q.statement = session.decoder.read_string(); - try { + try + { return this->run(session, q); // TODO: RETURN success MAYBE - } catch (QueryEngineException &e) { + } + catch (QueryEngineException &e) + { session.output_stream.write_failure( {{"code", "Memgraph.QueryEngineException"}, {"message", e.what()}}); session.output_stream.send(); return session.bolt.states.error.get(); } - } else if (message_type == MessageCode::PullAll) { + } + else if (message_type == MessageCode::PullAll) + { pull_all(session); - } else if (message_type == MessageCode::DiscardAll) { + } + else if (message_type == MessageCode::DiscardAll) + { discard_all(session); - } else if (message_type == MessageCode::Reset) { + } + else if (message_type == MessageCode::Reset) + { // TODO: rollback current transaction // discard all records waiting to be sent return this; - } else { + } + else + { logger.error("Unrecognized message recieved"); logger.debug("Invalid message type 0x{:02X}", message_type); @@ -53,7 +65,7 @@ State *Executor::run(Session &session) return this; } -State* Executor::run(Session &session, Query &query) +State *Executor::run(Session &session, Query &query) { logger.trace("[Run] '{}'", query.statement); @@ -63,7 +75,8 @@ State* Executor::run(Session &session, Query &query) auto is_successfully_executed = query_engine.execute(query.statement, db, session.output_stream); - if (!is_successfully_executed) { + if (!is_successfully_executed) + { session.output_stream.write_failure( {{"code", "Memgraph.QueryExecutionFail"}, {"message", "Query execution has failed (probably there is no " diff --git a/src/cypher/errors.hpp b/src/cypher/errors.hpp deleted file mode 100644 index 1afcb3fc6..000000000 --- a/src/cypher/errors.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "token.hpp" -#include - -// TODO: optimaze exceptions in respect to -// query_engine/exceptions/error.hpp - -class SyntaxError : public std::runtime_error -{ -public: - SyntaxError(const std::string &near) - : std::runtime_error("Syntax error: near '" + near + "'.") - { - } -}; - -class LexicalError : public std::runtime_error -{ -public: - LexicalError(const Token &token) - : std::runtime_error("Lexical error: unrecognized token '" + - token.value + "'.") - { - } -}; - -class ParserError : public std::runtime_error -{ - using runtime_error::runtime_error; -}; diff --git a/src/memgraph_bolt.cpp b/src/memgraph_bolt.cpp index 23f812b98..07119974f 100644 --- a/src/memgraph_bolt.cpp +++ b/src/memgraph_bolt.cpp @@ -71,9 +71,9 @@ int main(void) bolt::Server server(std::move(socket)); serverptr = &server; + // TODO: N should be configurable auto N = std::thread::hardware_concurrency(); - - logger.info("Starting {} workers", N); + logger.info("Starting {} workers", 1); server.start(N); logger.info("Shutting down..."); diff --git a/src/query_engine/template/barrier_template_code_cpu.cpp b/src/query_engine/template/barrier_template_code_cpu.cpp index e06dcc856..d33aaa113 100644 --- a/src/query_engine/template/barrier_template_code_cpu.cpp +++ b/src/query_engine/template/barrier_template_code_cpu.cpp @@ -1,7 +1,7 @@ #include #include -#include "query_engine/i_code_cpu.hpp" +#include "query/i_plan_cpu.hpp" #include "storage/model/properties/all.hpp" using std::cout; @@ -13,11 +13,11 @@ using std::endl; namespace barrier { -class {{class_name}} : public ICodeCPU<{{stream}}> +class {{class_name}} : public IPlanCPU<{{stream}}> { public: - bool run(Db &db, code_args_t &args, + bool run(Db &db, plan_args_t &args, {{stream}} &stream) override { {{code}} @@ -29,13 +29,13 @@ public: } -extern "C" ICodeCPU* produce() +extern "C" IPlanCPU* produce() { // BARRIER! return new barrier::{{class_name}}(); } -extern "C" void destruct(ICodeCPU* p) +extern "C" void destruct(IPlanCPU* p) { delete p; } diff --git a/src/query_engine/template/template_code_cpu.cpp b/src/query_engine/template/template_code_cpu.cpp index 47c56795f..ccfdb700e 100644 --- a/src/query_engine/template/template_code_cpu.cpp +++ b/src/query_engine/template/template_code_cpu.cpp @@ -1,8 +1,8 @@ #include #include -#include "query_engine/util.hpp" -#include "query_engine/i_code_cpu.hpp" +#include "query/util.hpp" +#include "query/i_plan_cpu.hpp" #include "storage/model/properties/all.hpp" using std::cout; @@ -10,11 +10,11 @@ using std::endl; // query: {{query}} -class {{class_name}} : public ICodeCPU<{{stream}}> +class {{class_name}} : public IPlanCPU<{{stream}}> { public: - bool run(Db &db, code_args_t &args, + bool run(Db &db, plan_args_t &args, {{stream}} &stream) override { {{code}} @@ -23,12 +23,12 @@ public: ~{{class_name}}() {} }; -extern "C" ICodeCPU<{{stream}}>* produce() +extern "C" IPlanCPU<{{stream}}>* produce() { return new {{class_name}}(); } -extern "C" void destruct(ICodeCPU<{{stream}}>* p) +extern "C" void destruct(IPlanCPU<{{stream}}>* p) { delete p; } diff --git a/src/query_engine/util.cpp b/src/query_engine/util.cpp index 4385ab87f..811f2762b 100644 --- a/src/query_engine/util.cpp +++ b/src/query_engine/util.cpp @@ -1,4 +1,4 @@ -#include "query_engine/util.hpp" +#include "query/util.hpp" #include "storage/type_group_edge.hpp" #include "storage/type_group_vertex.hpp" diff --git a/src/template_engine/engine.cpp b/src/template_engine/engine.cpp index 7b0e4ca9b..0237f67e3 100644 --- a/src/template_engine/engine.cpp +++ b/src/template_engine/engine.cpp @@ -5,7 +5,7 @@ namespace template_engine { -string TemplateEngine::render(const string& form, const data& partials) +string render(const string& form, const data& partials) { // TODO more optimal implementation // another option is something like https://github.com/no1msd/mstch diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/integration/cleaning.cpp b/tests/integration/cleaning.cpp index b8db0afff..1bca27a75 100644 --- a/tests/integration/cleaning.cpp +++ b/tests/integration/cleaning.cpp @@ -1,4 +1,4 @@ -#include "query_engine/hardcode/queries.hpp" +#include "query/hardcode/queries.hpp" #ifdef BARRIER #include "barrier/barrier.cpp" @@ -6,7 +6,7 @@ #include "logging/default.hpp" #include "logging/streams/stdout.hpp" -#include "query_engine/query_stripper.hpp" +#include "query/strip/stripper.hpp" #include "utils/sysinfo/memory.hpp" template diff --git a/tests/integration/internal/crud.py b/tests/integration/crud.py similarity index 100% rename from tests/integration/internal/crud.py rename to tests/integration/crud.py diff --git a/tests/integration/index.cpp b/tests/integration/index.cpp index 9d13aea5f..56db281b0 100644 --- a/tests/integration/index.cpp +++ b/tests/integration/index.cpp @@ -1,4 +1,4 @@ -#include "query_engine/hardcode/queries.hpp" +#include "query/hardcode/queries.hpp" #include @@ -8,7 +8,7 @@ #include "logging/default.hpp" #include "logging/streams/stdout.hpp" -#include "query_engine/query_stripper.hpp" +#include "query/strip/stripper.hpp" #include "storage/indexes/indexes.hpp" #include "utils/sysinfo/memory.hpp" diff --git a/tests/integration/pilot/dressipi/crud.py b/tests/integration/pilot/dressipi/crud.py deleted file mode 100644 index 6cef5524f..000000000 --- a/tests/integration/pilot/dressipi/crud.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from neo4j.v1 import GraphDatabase, basic_auth, types - -# initialize driver and create session -# default username and password are used -driver = GraphDatabase.driver("bolt://localhost", - auth=basic_auth("neo4j", "neo4j"), - encrypted=0) -session = driver.session() - -# all test queries and expected results -# one element in queries is called test entry -# it contains test query + -# touple(number of expected results, expected properties) -# TODO: create custom data structures -queries = [ - ("CREATE (n:Garment {garment_id: 1234, garment_category_id: 1}) RETURN n", - (1, [{"garment_id": 1234, "garment_category_id": 1}])), - ("CREATE(p:Profile {profile_id: 111, partner_id: 55}) RETURN p", - (1, [{"profile_id": 111, "partner_id": 55}])), - # ("MATCH (p:Profile) RETURN p", - # (1, [{"profile_id": 111, "partner_id": 55}])), - ("MATCH (n) DELETE n", - (0, [])) -]; - -# iterate through all queries and execute them agains the database -for query, result in queries: - - # extract count and properties from test entries - count, test_properties = result - records = [record for record in session.run(query)] - - # check count - assert len(records) == count, \ - "Number of results for %s isn't good;" \ - " expected: %s, got %s" % (query, count, len(records)) - - # in case that result should contain just one result - # test properties - # TODO: test others - if count == 1: - # extract properties from record - record = records[0] - record_name, = record - received_properties = {key: value - for (key, value) in record[record_name].items()} - - # get expected properties - expected_properties = test_properties[0] - - # check properties - assert expected_properties == received_properties, \ - "Received properties for %s are not good; expected: %s, " \ - "got %s" % (query, expected_properties, received_properties) - -print("Dressipi integration test passed OK") diff --git a/tests/integration/pilot/dressipi/run.py b/tests/integration/pilot/dressipi/run.py deleted file mode 100644 index 059efc6b4..000000000 --- a/tests/integration/pilot/dressipi/run.py +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import crud diff --git a/tests/integration/queries.cpp b/tests/integration/queries.cpp index 496225e3f..5326f1208 100644 --- a/tests/integration/queries.cpp +++ b/tests/integration/queries.cpp @@ -1,4 +1,4 @@ -#include "query_engine/hardcode/queries.hpp" +#include "query/hardcode/queries.hpp" #ifdef BARRIER #include "barrier/barrier.cpp" @@ -8,7 +8,7 @@ #include "database/db.hpp" #include "logging/default.hpp" #include "logging/streams/stdout.hpp" -#include "query_engine/query_stripper.hpp" +#include "query/strip/stripper.hpp" int main(void) { @@ -36,11 +36,10 @@ int main(void) "CREATE (n:LABEL {name: \"TEST2\"}) RETURN n", "CREATE (n:LABEL {name: \"TEST3\"}) RETURN n", "CREATE (n:OTHER {name: \"TEST4\"}) RETURN n" - "CREATE (n:ACCOUNT {id: 2322, name: \"TEST\", country: \"Croatia\", created_at: 2352352}) RETURN n", - "MATCH (n {id: 0}) RETURN n", - "MATCH (n {id: 1}) RETURN n", - "MATCH (n {id: 2}) RETURN n", - "MATCH (n {id: 3}) RETURN n", + "CREATE (n:ACCOUNT {id: 2322, name: \"TEST\", country: \"Croatia\", " + "created_at: 2352352}) RETURN n", + "MATCH (n {id: 0}) RETURN n", "MATCH (n {id: 1}) RETURN n", + "MATCH (n {id: 2}) RETURN n", "MATCH (n {id: 3}) RETURN n", "MATCH (a {id:0}), (p {id: 1}) CREATE (a)-[r:IS]->(p) RETURN r", "MATCH (a {id:1}), (p {id: 2}) CREATE (a)-[r:IS]->(p) RETURN r", "MATCH ()-[r]-() WHERE ID(r)=0 RETURN r", @@ -48,8 +47,9 @@ int main(void) "MATCH (n: {id: 0}) SET n.name = \"TEST100\" RETURN n", "MATCH (n: {id: 1}) SET n.name = \"TEST101\" RETURN n", "MATCH (n: {id: 0}) SET n.name = \"TEST102\" RETURN n", - "MATCH (n:LABEL) RETURN n", - "MATCH (n1), (n2) WHERE ID(n1)=0 AND ID(n2)=1 CREATE (n1)<-[r:IS {age: 25,weight: 70}]-(n2) RETURN r", + "MATCH (n:LABEL) RETURN n", "MATCH (n1), (n2) WHERE ID(n1)=0 AND " + "ID(n2)=1 CREATE (n1)<-[r:IS {age: " + "25,weight: 70}]-(n2) RETURN r", "MATCH (n) RETURN n", "MATCH (n:LABEL) RETURN n", "MATCH (n) DELETE n ", "MATCH (n:LABEL) DELETE n", "MATCH (n) WHERE ID(n) = 0 DELETE n", "MATCH ()-[r]-() WHERE ID(r) = 0 DELETE r", "MATCH ()-[r]-() DELETE r", diff --git a/tests/integration/scenario.py b/tests/integration/scenario.py new file mode 100644 index 000000000..1c0d7a0e1 --- /dev/null +++ b/tests/integration/scenario.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import logging + +# TODO: auto import +from scenario import no_000001 +from neo4j.v1 import GraphDatabase, basic_auth, types, Node + +scenarios = [no_000001.scenario_1] + +# logging init +log = logging.getLogger(__name__) + +# initialize driver and create session +session = GraphDatabase.driver("bolt://localhost", + auth=basic_auth("neo4j", "1234"), + encrypted=0).session() + + +def check(condition, scenario_no, message): + ''' + Checks condition if condition is false the whole test will be stopped and + scenario_no + message will be printed out. + + :param condition: bool + :param scenario_no: int + :param message: assert message + :returns: None + ''' + if not condition: + log.error("Error in scenario: %s" % scenario_no) + assert condition, message + + +if __name__ == "__main__": + + logging.basicConfig(level=logging.DEBUG) + + for scenario in scenarios: + + # iterate through all queries and execute them agains the database + for query, result in scenario.queries: + + # extract count and properties from test entries + count, expected = result + records = [record for record in session.run(query)] + + log.info("%s" % records) + + # check count + check(len(records) == count, scenario.no, + "Number of results for %s isn't good;" \ + " expected: %s, got %s" % (query, count, len(records))) + + # in case that the result is single + if count == 1: + # extract properties from record + record = records[0] + record_name, = record + data = record[record_name] + + if type(data) is Node: + received = {k: v for (k, v) in data.items()} + else: + received = data + + # get expected elements + expected = expected[0] + + # check properties + check(expected == received, scenario.no, + "Received data for %s isn't OK; expected: %s, " \ + "got %s" % (query, expected, received)) + + elif count > 1: + # TODO: implement the full test + pass diff --git a/tests/integration/scenario/__init__.py b/tests/integration/scenario/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/integration/scenario/no_000001.py b/tests/integration/scenario/no_000001.py new file mode 100644 index 000000000..634cca994 --- /dev/null +++ b/tests/integration/scenario/no_000001.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "Marko Budiselic" + +class Scenario1: + ''' + Create Match Retrun Sequence + ''' + + def __init__(self): + ''' + Constructor + ''' + self.no = 1 + self.desctiption = "Create Match Retrun Sequence" + self.init_graph = [] + self.queries = [ + ("MATCH (n) DETACH DELETE n", (0, None)), + ("MATCH (n) RETURN n", (0, [])), + ("CREATE (n:Label) RETURN n", (1, [{}])), + ("MATCH (n) RETURN n", (1, [{}])), + ("CREATE (n:Label {prop: 0}) RETURN n", (1, [{"prop": 0}])), + ("MATCH (n) RETURN n", (2, [{}, {"prop": 0}])), + ("CREATE (n:Label {prop: 1}) RETURN n", (1, [{"prop": 1}])), + ("MATCH (n) RETURN n", (3, [{}, {"prop": 0}, {"prop": 1}])), + ("CREATE (n {prop: 1}) RETURN n", (1, [{"prop": 1}])), + ("MATCH (n) RETURN n", (4, [{}, {"prop": 0}, {"prop": 1}, {"prop": 0}])), + ("MATCH (n:Label) RETURN n", (3, [{}, {"prop": 0}, {"prop": 1}])), + ("MATCH (n:Label {prop: 0}) RETURN n", (1, [{"prop": 0}])), + ] + self.side_effects = None + +scenario_1 = Scenario1() diff --git a/tests/integration/snapshot.cpp b/tests/integration/snapshot.cpp index 34725d059..3a233bff9 100644 --- a/tests/integration/snapshot.cpp +++ b/tests/integration/snapshot.cpp @@ -1,4 +1,4 @@ -#include "query_engine/hardcode/queries.hpp" +#include "query/hardcode/queries.hpp" #include @@ -8,7 +8,7 @@ #include "logging/default.hpp" #include "logging/streams/stdout.hpp" -#include "query_engine/query_stripper.hpp" +#include "query/strip/stripper.hpp" #include "storage/indexes/indexes.hpp" #include "utils/sysinfo/memory.hpp" diff --git a/tests/manual/cpp_generator.cpp b/tests/manual/cpp_generator.cpp index bca29c085..113686d4a 100644 --- a/tests/manual/cpp_generator.cpp +++ b/tests/manual/cpp_generator.cpp @@ -1,6 +1,6 @@ #include -#include "query_engine/code_generator/cpp_generator.hpp" +#include "query/backend/cpp_old/cypher.hpp" using ParameterIndexKey::Type::InternalId; using ParameterIndexKey::Type::Projection; diff --git a/tests/manual/cypher_ast.cpp b/tests/manual/cypher_ast.cpp index 56d324b43..588072018 100644 --- a/tests/manual/cypher_ast.cpp +++ b/tests/manual/cypher_ast.cpp @@ -2,10 +2,10 @@ #include #include -#include "cypher/compiler.hpp" -#include "cypher/debug/tree_print.hpp" +#include "query/language/cypher/common.hpp" +#include "query/language/cypher/compiler.hpp" +#include "query/language/cypher/debug/tree_print.hpp" #include "utils/command_line/arguments.hpp" -#include "cypher/common.hpp" #include "utils/terminate_handler.hpp" using std::cout; diff --git a/tests/manual/queries.cpp b/tests/manual/queries.cpp index 698cac25b..df189f7ae 100644 --- a/tests/manual/queries.cpp +++ b/tests/manual/queries.cpp @@ -1,16 +1,16 @@ #include -#include "query_engine/hardcode/queries.hpp" +#include "query/hardcode/queries.hpp" #ifdef BARRIER #include "barrier/barrier.cpp" #endif -#include "logging/default.hpp" -#include "logging/streams/stdout.hpp" #include "communication/bolt/v1/serialization/bolt_serializer.hpp" #include "database/db.hpp" -#include "query_engine/query_stripper.hpp" +#include "logging/default.hpp" +#include "logging/streams/stdout.hpp" +#include "query/strip/stripper.hpp" #include "storage/edges.cpp" #include "storage/edges.hpp" #include "storage/vertices.cpp" diff --git a/tests/manual/query_engine.cpp b/tests/manual/query_engine.cpp index 343e0937d..e097a46c1 100644 --- a/tests/manual/query_engine.cpp +++ b/tests/manual/query_engine.cpp @@ -2,21 +2,21 @@ #define DEBUG 1 -#include "utils/command_line/arguments.hpp" -#include "cypher/common.hpp" -#include "query_engine/query_engine.hpp" -#include "utils/time/timer.hpp" -#include "utils/terminate_handler.hpp" #include "communication/communication.hpp" +#include "query/language/cypher/common.hpp" #include "logging/default.hpp" #include "logging/streams/stdout.hpp" +#include "query/engine.hpp" +#include "utils/command_line/arguments.hpp" +#include "utils/terminate_handler.hpp" +#include "utils/time/timer.hpp" using std::cout; using std::endl; using std::cin; int main(void) -{ +{ std::set_terminate(&terminate_handler); logging::init_sync(); @@ -36,18 +36,17 @@ int main(void) cout << "> "; std::string command; std::getline(cin, command); - if (command == "quit") - break; - + if (command == "quit") break; + // execute command try { engine.execute(command, db, stream); - } catch (const std::exception& e) { + } catch (const std::exception &e) { cout << e.what() << endl; - } catch (const QueryEngineException& e) { + } catch (const QueryEngineException &e) { cout << e.what() << endl; } } - + return 0; } diff --git a/tests/manual/query_hasher.cpp b/tests/manual/query_hasher.cpp index 01065229a..bc0e9cba6 100644 --- a/tests/manual/query_hasher.cpp +++ b/tests/manual/query_hasher.cpp @@ -1,8 +1,7 @@ #include -#include "cypher/common.hpp" -#include "query_engine/query_hasher.hpp" -#include "query_engine/query_stripper.hpp" +#include "query/language/cypher/common.hpp" +#include "query/preprocesor.hpp" #include "utils/command_line/arguments.hpp" #include "utils/type_discovery.hpp" @@ -18,19 +17,14 @@ int main(int argc, char **argv) // query extraction auto input_query = extract_query(arguments); + QueryPreprocessor preprocessor; + auto preprocessed = preprocessor.preprocess(input_query); + cout << "QUERY: " << input_query << endl; - - auto stripper = make_query_stripper(TK_LONG, TK_FLOAT, TK_STR, TK_BOOL); - auto stripped = stripper.strip(input_query); - - cout << "STRIPPED QUERY: " << stripped.query << endl; - - QueryHasher query_hasher; - - cout << "QUERY HASH: " << query_hasher.hash(stripped.query) << endl; - + cout << "STRIPPED QUERY: " << preprocessed.query << endl; + cout << "QUERY HASH: " << preprocessed.hash << endl; cout << "PROPERTIES:" << endl; - for (auto property : stripped.arguments) { + for (auto property : preprocessed.arguments) { cout << " " << property << endl; } diff --git a/tests/unit/cypher_state_machine.cpp b/tests/unit/cypher_state_machine.cpp index 787f45336..02f4f5581 100644 --- a/tests/unit/cypher_state_machine.cpp +++ b/tests/unit/cypher_state_machine.cpp @@ -1,6 +1,6 @@ #include -#include "query_engine/code_generator/entity_search.hpp" +#include "query/backend/cpp_old/entity_search.hpp" #include "utils/assert.hpp" #include "utils/underlying_cast.hpp" diff --git a/tests/unit/cypher_traversal.cpp b/tests/unit/cypher_traversal.cpp index 9cbc19891..1b94d129c 100644 --- a/tests/unit/cypher_traversal.cpp +++ b/tests/unit/cypher_traversal.cpp @@ -1,9 +1,5 @@ #include #include - -#include "cypher/compiler.hpp" -#include "cypher/debug/tree_print.hpp" - #include #include #include @@ -11,6 +7,9 @@ #include #include +#include "query/language/cypher/compiler.hpp" +#include "query/language/cypher/debug/tree_print.hpp" + namespace fs = std::experimental::filesystem; using std::cout; diff --git a/tests/unit/parameter_index.cpp b/tests/unit/parameter_index.cpp index 895d8ec5b..542591dd6 100644 --- a/tests/unit/parameter_index.cpp +++ b/tests/unit/parameter_index.cpp @@ -1,6 +1,6 @@ #include -#include "query_engine/code_generator/query_action_data.hpp" +#include "query/backend/cpp_old/query_action_data.hpp" #include "utils/assert.hpp" using ParameterIndexKey::Type::InternalId; diff --git a/tests/unit/template_engine.cpp b/tests/unit/template_engine.cpp index 16072ca1d..d5b511b47 100644 --- a/tests/unit/template_engine.cpp +++ b/tests/unit/template_engine.cpp @@ -5,9 +5,8 @@ TEST_CASE("Template Engine - basic placeholder replacement") { - template_engine::TemplateEngine engine; - auto rendered = - engine.render("{{one}} {{two}}", {{"one", "two"}, {"two", "one"}}); + auto rendered = template_engine::render("{{one}} {{two}}", + {{"one", "two"}, {"two", "one"}}); REQUIRE(rendered == "two one"); }