diff --git a/src/cypher/ast/ast_visitor.hpp b/src/cypher/ast/ast_visitor.hpp index 1edb58fad..7eb25aa16 100644 --- a/src/cypher/ast/ast_visitor.hpp +++ b/src/cypher/ast/ast_visitor.hpp @@ -71,6 +71,8 @@ struct WithList; struct WithClause; struct WithQuery; +struct InternalIdExpr; + struct AstVisitor : public Visitor<Accessor, Boolean, Float, Identifier, Alias, Integer, String, Property, And, Or, Lt, Gt, Ge, Le, Eq, Ne, Plus, @@ -81,6 +83,7 @@ struct AstVisitor Distinct, Delete, DeleteQuery, UpdateQuery, Set, SetKey, ReadWriteQuery, IdentifierList, WithList, WithClause, WithQuery, + InternalIdExpr, SetValue, SetElement, SetList> { }; diff --git a/src/cypher/ast/expr.hpp b/src/cypher/ast/expr.hpp index 701129759..0e80100a0 100644 --- a/src/cypher/ast/expr.hpp +++ b/src/cypher/ast/expr.hpp @@ -14,10 +14,7 @@ struct ValueExpr : public Crtp<Derived>, public Expr { using uptr = std::unique_ptr<Derived>; - virtual void accept(AstVisitor& visitor) - { - visitor.visit(this->derived()); - } + virtual void accept(AstVisitor &visitor) { visitor.visit(this->derived()); } }; template <class T, class Derived> @@ -30,24 +27,20 @@ struct LeafExpr : public ValueExpr<Derived> template <class Derived> struct BinaryExpr : public ValueExpr<Derived> { - BinaryExpr(Expr* left, Expr* right) : left(left), right(right) {} + BinaryExpr(Expr *left, Expr *right) : left(left), right(right) {} - Expr* left; - Expr* right; + Expr *left; + Expr *right; }; struct PatternExpr : public Expr { using uptr = std::unique_ptr<PatternExpr>; - PatternExpr(Pattern* pattern) : pattern(pattern) {} + PatternExpr(Pattern *pattern) : pattern(pattern) {} - virtual void accept(AstVisitor& visitor) - { - visitor.visit(*this); - } + virtual void accept(AstVisitor &visitor) { visitor.visit(*this); } - Pattern* pattern; + Pattern *pattern; }; - } diff --git a/src/cypher/ast/values.hpp b/src/cypher/ast/values.hpp index b2ccf5dc2..8b581c2ae 100644 --- a/src/cypher/ast/values.hpp +++ b/src/cypher/ast/values.hpp @@ -17,6 +17,16 @@ struct Integer : public LeafExpr<int, Integer> using LeafExpr::LeafExpr; }; +struct Long : public LeafExpr<int64_t, Long> +{ + using LeafExpr::LeafExpr; +}; + +struct ULong : public LeafExpr<uint64_t, ULong> +{ + using LeafExpr::LeafExpr; +}; + struct Boolean : public LeafExpr<bool, Boolean> { using LeafExpr::LeafExpr; @@ -27,4 +37,17 @@ struct String : public LeafExpr<std::string, String> using LeafExpr::LeafExpr; }; +struct InternalIdExpr : public Expr +{ + InternalIdExpr(Identifier *identifier, Integer *value) + : identifier(identifier), value(value) + { + } + + Identifier *identifier; + Integer *value; + + virtual void accept(AstVisitor &visitor) { visitor.visit(*this); } +}; + } diff --git a/src/cypher/cypher.y b/src/cypher/cypher.y index 226eb88ca..5696c7429 100644 --- a/src/cypher/cypher.y +++ b/src/cypher/cypher.y @@ -444,6 +444,11 @@ value_expr(E) ::= idn(I) DOT idn(P). { E = ast->create<ast::Accessor>(I, P); } +value_expr(E) ::= ID LP idn(I) RP EQ INT(V). { + auto value = std::stoi(V->value); + E = ast->create<ast::InternalIdExpr>(I, ast->create<ast::Integer>(value)); +} + %type idn {ast::Identifier*} idn(I) ::= IDN(X). { diff --git a/src/cypher/debug/tree_print.hpp b/src/cypher/debug/tree_print.hpp index 46d03673f..52a5aa67d 100644 --- a/src/cypher/debug/tree_print.hpp +++ b/src/cypher/debug/tree_print.hpp @@ -184,12 +184,24 @@ public: entry << "Integer " << integer.value; } + // void visit(ast::ULong& ulong) override + // { + // auto entry = printer.advance(); + // entry << "ULong " << ulong.value; + // } + void visit(ast::String& string) override { auto entry = printer.advance(); entry << "String " << string.value; } + void visit(ast::InternalIdExpr& internal_id) override + { + auto entry = printer.advance("InternalId"); + Traverser::visit(internal_id); + } + void visit(ast::Property& property) override { auto entry = printer.advance("Property"); diff --git a/src/cypher/tokenizer/cypher_lexer.hpp b/src/cypher/tokenizer/cypher_lexer.hpp index 2ca0e3146..14e685080 100644 --- a/src/cypher/tokenizer/cypher_lexer.hpp +++ b/src/cypher/tokenizer/cypher_lexer.hpp @@ -50,6 +50,10 @@ public: rule("(?i:DISTINCT)", TK_DISTINCT); rule("(?i:DELETE)", TK_DELETE); rule("(?i:WITH)", TK_WITH); + // TODO: here should be better regex + // problem is that id in property list isn't ID from where + // part + rule("(?-i:ID)", TK_ID); rule("(?i:AND)", TK_AND); rule("(?i:OR)", TK_OR); diff --git a/src/cypher/visitor/traverser.hpp b/src/cypher/visitor/traverser.hpp index ddfbd4a69..d60d84bd8 100644 --- a/src/cypher/visitor/traverser.hpp +++ b/src/cypher/visitor/traverser.hpp @@ -30,11 +30,8 @@ public: void visit(ast::ReadWriteQuery& query) override { accept(query.match_clause); - accept(query.create_clause); - - if (query.return_clause != nullptr) - accept(query.return_clause); + accept(query.return_clause); } void visit(ast::Match& match) override @@ -279,6 +276,12 @@ public: accept(with_query.return_clause); } + void visit(ast::InternalIdExpr& internal_id) override + { + accept(internal_id.identifier); + accept(internal_id.value); + } + protected: template<class T> void accept(T* node) diff --git a/src/query_engine/traverser/read_traverser.hpp b/src/query_engine/traverser/read_traverser.hpp index 0f5aed6ec..8afb123f2 100644 --- a/src/query_engine/traverser/read_traverser.hpp +++ b/src/query_engine/traverser/read_traverser.hpp @@ -27,6 +27,10 @@ public: ++index; } + void visit(ast::InternalIdExpr& internal_id) override + { + } + void visit(ast::Return& ret) override { #ifdef DEBUG diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f111c0baf..1a86cc587 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -45,6 +45,7 @@ foreach(test ${concurrency_test_names}) set(test_name concurrent_${test}) add_executable(${test_name} concurrent/${test}.cpp) target_link_libraries(${test_name} Threads::Threads) + target_link_libraries(${test_name} ${fmt_static_lib}) add_test(NAME ${test_name} COMMAND ${test_name}) set_property(TARGET ${test_name} PROPERTY CXX_STANDARD 14) endforeach() @@ -60,8 +61,16 @@ set_property(TARGET integration_queries PROPERTY CXX_STANDARD 14) ## MANUAL TESTS +# query engine add_executable(manual_query_engine manual/query_engine.cpp ${memgraph_src_files}) target_link_libraries(manual_query_engine ${fmt_static_lib}) target_link_libraries(manual_query_engine dl) target_link_libraries(manual_query_engine cypher_lib) set_property(TARGET manual_query_engine PROPERTY CXX_STANDARD 14) + +# ast traversal +add_executable(cypher_ast_traverser manual/cypher_ast.cpp ${mamgraph_src_files}) +target_link_libraries(cypher_ast_traverser ${fmt_static_lib}) +target_link_libraries(cypher_ast_traverser cypher_lib) +set_property(TARGET cypher_ast_traverser PROPERTY CXX_STANDARD 14) + diff --git a/tests/data/cypher_queries/complex/powerlinx_opportunities.cypher b/tests/data/cypher_queries/complex/powerlinx_opportunities.cypher index 42ca35b3b..0e92c6d94 100644 --- a/tests/data/cypher_queries/complex/powerlinx_opportunities.cypher +++ b/tests/data/cypher_queries/complex/powerlinx_opportunities.cypher @@ -1 +1 @@ -MATCH (p:Personnel)-[:CREATED]->(o:Opportunity)-[:HAS_MATCH]->(c:Company {id: "321"}) RETURN (a:Account {id: "123"})-[:IS]->(p) +MATCH (p:Personnel)-[:CREATED]->(o:Opportunity)-[:HAS_MATCH]->(c:Company {identifier: "321"}) RETURN (a:Account {prop: "123"})-[:IS]->(p) diff --git a/tests/data/cypher_queries/sprint_0/query_0.cypher b/tests/data/cypher_queries/sprint_0/query_00.cypher similarity index 100% rename from tests/data/cypher_queries/sprint_0/query_0.cypher rename to tests/data/cypher_queries/sprint_0/query_00.cypher diff --git a/tests/data/cypher_queries/sprint_0/query_1.cypher b/tests/data/cypher_queries/sprint_0/query_01.cypher similarity index 100% rename from tests/data/cypher_queries/sprint_0/query_1.cypher rename to tests/data/cypher_queries/sprint_0/query_01.cypher diff --git a/tests/data/cypher_queries/sprint_0/query_2.cypher b/tests/data/cypher_queries/sprint_0/query_02.cypher similarity index 100% rename from tests/data/cypher_queries/sprint_0/query_2.cypher rename to tests/data/cypher_queries/sprint_0/query_02.cypher diff --git a/tests/data/cypher_queries/sprint_0/query_3.cypher b/tests/data/cypher_queries/sprint_0/query_03.cypher similarity index 100% rename from tests/data/cypher_queries/sprint_0/query_3.cypher rename to tests/data/cypher_queries/sprint_0/query_03.cypher diff --git a/tests/data/cypher_queries/sprint_0/query_04.cypher b/tests/data/cypher_queries/sprint_0/query_04.cypher new file mode 100644 index 000000000..d254561d9 --- /dev/null +++ b/tests/data/cypher_queries/sprint_0/query_04.cypher @@ -0,0 +1 @@ +MATCH (n {id:0}) SET n.name = "TEST100" RETURN n diff --git a/tests/data/cypher_queries/sprint_0/query_5.cypher b/tests/data/cypher_queries/sprint_0/query_05.cypher similarity index 100% rename from tests/data/cypher_queries/sprint_0/query_5.cypher rename to tests/data/cypher_queries/sprint_0/query_05.cypher diff --git a/tests/data/cypher_queries/sprint_0/query_6.cypher b/tests/data/cypher_queries/sprint_0/query_06.cypher similarity index 100% rename from tests/data/cypher_queries/sprint_0/query_6.cypher rename to tests/data/cypher_queries/sprint_0/query_06.cypher diff --git a/tests/data/cypher_queries/sprint_0/query_07.cypher b/tests/data/cypher_queries/sprint_0/query_07.cypher new file mode 100644 index 000000000..70529220f --- /dev/null +++ b/tests/data/cypher_queries/sprint_0/query_07.cypher @@ -0,0 +1 @@ +MATCH ()-[r]-() WHERE ID(r)=0 RETURN r diff --git a/tests/data/cypher_queries/sprint_0/query_08.cypher b/tests/data/cypher_queries/sprint_0/query_08.cypher new file mode 100644 index 000000000..cbf64ae66 --- /dev/null +++ b/tests/data/cypher_queries/sprint_0/query_08.cypher @@ -0,0 +1 @@ +MATCH (a),(b) WHERE ID(a)=0 AND ID(b)=1 RETURN a,b diff --git a/tests/data/cypher_queries/sprint_0/query_09.cypher b/tests/data/cypher_queries/sprint_0/query_09.cypher new file mode 100644 index 000000000..8bc4fa3fb --- /dev/null +++ b/tests/data/cypher_queries/sprint_0/query_09.cypher @@ -0,0 +1 @@ +MATCH (n) WHERE ID(n)=0 SET n.name = "bla" RETURN n diff --git a/tests/data/cypher_queries/sprint_0/query_10.cypher b/tests/data/cypher_queries/sprint_0/query_10.cypher new file mode 100644 index 000000000..425c0ddb5 --- /dev/null +++ b/tests/data/cypher_queries/sprint_0/query_10.cypher @@ -0,0 +1 @@ +MATCH ()-[r]-() WHERE ID(r)=0 SET r.test = "bla" RETURN r diff --git a/tests/data/cypher_queries/sprint_0/query_4.cypher b/tests/data/cypher_queries/sprint_0/query_4.cypher deleted file mode 100644 index f76d46faa..000000000 --- a/tests/data/cypher_queries/sprint_0/query_4.cypher +++ /dev/null @@ -1 +0,0 @@ -MATCH (n {id: 0}) SET n.name = "TEST100" RETURN n diff --git a/tests/manual/cypher_ast.cpp b/tests/manual/cypher_ast.cpp new file mode 100644 index 000000000..00d55cd75 --- /dev/null +++ b/tests/manual/cypher_ast.cpp @@ -0,0 +1,44 @@ +#include <cstdlib> +#include <vector> +#include <vector> + +#include "cypher/compiler.hpp" +#include "cypher/debug/tree_print.hpp" +#include "utils/command_line/arguments.hpp" +#include "cypher/common.hpp" +#include "utils/terminate_handler.hpp" + +using std::cout; +using std::endl; + +// * INPUT ARGUMENTS * +// -q -> query +// -v -> visitor +// -f -> file +// +int main(int argc, char *argv[]) +{ + std::set_terminate(&terminate_handler); + + // arguments parsing + auto arguments = all_arguments(argc, argv); + + // query extraction + auto cypher_query = extract_query(arguments); + cout << "QUERY: " << cypher_query << endl; + + // traversers + auto traverser = get_argument(arguments, "-t", "code"); + auto print_traverser = Traverser::sptr(new PrintVisitor(cout)); + std::map<std::string, Traverser::sptr> traversers = { + {"print", print_traverser} + }; + + cypher::Compiler compiler; + auto tree = compiler.syntax_tree(cypher_query); + + auto t = traversers[traverser]; + tree.root->accept(*t); + + return 0; +}