From 7c52817e412acfa4a57288aa786eb5d4b16231c9 Mon Sep 17 00:00:00 2001 From: Marko Budiselic Date: Sun, 24 Jan 2016 16:21:46 +0100 Subject: [PATCH] First implementation of delete query --- cypher/Makefile | 4 +- cypher/ast/alias.hpp | 20 ++++++ cypher/ast/ast.hpp | 2 + cypher/ast/ast_visitor.hpp | 8 ++- cypher/ast/delete.hpp | 17 +++++ cypher/ast/identifier.hpp | 5 +- cypher/ast/queries.hpp | 10 +++ cypher/ast/start.hpp | 24 +++++-- cypher/cypher.y | 67 +++++++++++++------ cypher/cypher_lexer.hpp | 1 + cypher/debug/tree_print.hpp | 19 +++++- cypher/query/read-write/match-delete.cypher | 1 + .../read-write/match-where-delete.cypher | 1 + cypher/visitor/traverser.hpp | 19 +++++- 14 files changed, 161 insertions(+), 37 deletions(-) create mode 100644 cypher/ast/alias.hpp create mode 100644 cypher/ast/delete.hpp create mode 100644 cypher/query/read-write/match-delete.cypher create mode 100644 cypher/query/read-write/match-where-delete.cypher diff --git a/cypher/Makefile b/cypher/Makefile index a4017d6c9..00958eab8 100644 --- a/cypher/Makefile +++ b/cypher/Makefile @@ -1,6 +1,6 @@ CXX = clang++ -CXXFLAGS = -std=c++1y -# CXXFLAGS = -std=c++1y -g # DEBUG CXXFLAGS +# CXXFLAGS = -std=c++1y +CXXFLAGS = -std=c++1y -g # DEBUG CXXFLAGS INC = -I../ parser: parser.o cypher.o diff --git a/cypher/ast/alias.hpp b/cypher/ast/alias.hpp new file mode 100644 index 000000000..f51d3eaef --- /dev/null +++ b/cypher/ast/alias.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include "ast_node.hpp" + +namespace ast +{ + +// TODO: set identifier as base class +struct Alias : public AstNode +{ + Alias(std::string name, std::string alias) + : name(name), alias(alias) {} + + std::string name; + std::string alias; +}; + +} diff --git a/cypher/ast/ast.hpp b/cypher/ast/ast.hpp index 4d334ad07..6e51a8388 100644 --- a/cypher/ast/ast.hpp +++ b/cypher/ast/ast.hpp @@ -3,6 +3,7 @@ #include "accessor.hpp" #include "values.hpp" #include "identifier.hpp" +#include "alias.hpp" #include "operators.hpp" #include "property.hpp" #include "relationship.hpp" @@ -11,6 +12,7 @@ #include "return.hpp" #include "pattern.hpp" #include "return.hpp" +#include "delete.hpp" #include "match.hpp" #include "queries.hpp" #include "start.hpp" diff --git a/cypher/ast/ast_visitor.hpp b/cypher/ast/ast_visitor.hpp index 00a06ee27..8dc0aece3 100644 --- a/cypher/ast/ast_visitor.hpp +++ b/cypher/ast/ast_visitor.hpp @@ -6,6 +6,7 @@ namespace ast { struct Identifier; +struct Alias; // properties struct Property; @@ -45,6 +46,7 @@ struct Pattern; struct Return; struct ReturnList; struct Distinct; +struct Delete; struct Match; struct Where; @@ -52,13 +54,15 @@ struct Where; struct Start; struct ReadQuery; struct WriteQuery; +struct DeleteQuery; struct Create; -struct AstVisitor : public Visitor {}; + Start, Where, WriteQuery, Create, Return, Distinct, Delete, + DeleteQuery> {}; } diff --git a/cypher/ast/delete.hpp b/cypher/ast/delete.hpp new file mode 100644 index 000000000..b2a8a8985 --- /dev/null +++ b/cypher/ast/delete.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "ast_node.hpp" +#include "identifier.hpp" + +namespace ast +{ + +struct Delete : public AstNode +{ + Delete(Identifier* identifier) + : identifier(identifier) {} + + Identifier* identifier; +}; + +} diff --git a/cypher/ast/identifier.hpp b/cypher/ast/identifier.hpp index 69ba41b09..2221aacac 100644 --- a/cypher/ast/identifier.hpp +++ b/cypher/ast/identifier.hpp @@ -9,11 +9,10 @@ namespace ast struct Identifier : public AstNode { - Identifier(std::string name, std::string alias) - : name(name), alias(alias) {} + Identifier(std::string name) + : name(name) {} std::string name; - std::string alias; }; } diff --git a/cypher/ast/queries.hpp b/cypher/ast/queries.hpp index 5de0f6ebd..3de9863d6 100644 --- a/cypher/ast/queries.hpp +++ b/cypher/ast/queries.hpp @@ -4,6 +4,7 @@ #include "match.hpp" #include "return.hpp" #include "create.hpp" +#include "delete.hpp" namespace ast { @@ -26,4 +27,13 @@ struct WriteQuery : public AstNode Return* return_clause; }; +struct DeleteQuery : public AstNode +{ + DeleteQuery(Match* match, Delete* delete_clause) + : match(match), delete_clause(delete_clause) {} + + Match* match; + Delete* delete_clause; +}; + } diff --git a/cypher/ast/start.hpp b/cypher/ast/start.hpp index e52c58c29..784fd200a 100644 --- a/cypher/ast/start.hpp +++ b/cypher/ast/start.hpp @@ -8,12 +8,26 @@ namespace ast struct Start : public AstNode { - Start(ReadQuery* read_query, WriteQuery* write_query) - : read_query(read_query), write_query(write_query) {} + Start(ReadQuery* read_query) + : read_query(read_query) + { + } - ReadQuery* read_query; - WriteQuery* write_query; - // ReadWriteQuery* read_write_query; + Start(WriteQuery* write_query) + : write_query(write_query) + { + } + + Start(DeleteQuery* delete_query) + : delete_query(delete_query) + { + } + + // TODO: the start structure must have a different implementation + // is this class necessary? + ReadQuery* read_query{nullptr}; + WriteQuery* write_query{nullptr}; + DeleteQuery* delete_query{nullptr}; }; }; diff --git a/cypher/cypher.y b/cypher/cypher.y index bbcf034ea..cc6f756ca 100644 --- a/cypher/cypher.y +++ b/cypher/cypher.y @@ -15,12 +15,12 @@ { int n = sizeof(yyTokenName) / sizeof(yyTokenName[0]); for (int i = 0; i < n; ++i) { - int a = yy_find_shift_action(yypParser, (YYCODETYPE)i); - if (a < YYNSTATE + YYNRULE) { - printf("possible token: %s\n", yyTokenName[i]); - } + int a = yy_find_shift_action(yypParser, (YYCODETYPE)i); + if (a < YYNSTATE + YYNRULE) { + printf("possible token: %s\n", yyTokenName[i]); + } } - // throw SyntaxError(TOKEN->value); + throw SyntaxError(TOKEN->value); } %stack_overflow @@ -53,15 +53,30 @@ %left PLUS MINUS. %left STAR SLASH REM. +// start structure + start ::= read_query(RQ). { - ast->root = ast->create(RQ, nullptr); + ast->root = ast->create(RQ); } start ::= write_query(WQ). { - ast->root = ast->create(nullptr, WQ); + ast->root = ast->create(WQ); +} + +start ::= delete_query(DQ). { + ast->root = ast->create(DQ); +} + +// read query structure + +%type read_query {ast::ReadQuery*} + +read_query(RQ) ::= match_clause(M) return_clause(R). { + RQ = ast->create(M, R); } // write query structure + %type write_query {ast::WriteQuery*} write_query(WQ) ::= create_clause(C) return_clause(R). { @@ -72,28 +87,34 @@ write_query(WQ) ::= create_clause(C). { WQ = ast->create(C, nullptr); } +// delete query structure + +%type delete_query {ast::DeleteQuery*} + +delete_query(DQ) ::= match_clause(M) delete_clause(D). { + DQ = ast->create(M, D); +} + %type create_clause {ast::Create*} create_clause(C) ::= CREATE pattern(P). { C = ast->create(P); } -// read query structure -%type read_query {ast::ReadQuery*} - -read_query(RQ) ::= match_clause(M) return_clause(R). { - RQ = ast->create(M, R); -} - %type match_clause {ast::Match*} match_clause(M) ::= MATCH pattern(P) where_clause(W). { M = ast->create(P, W); } +%type delete_clause {ast::Delete*} +// TODO: add DETACH DELETE +delete_clause(D) ::= DELETE idn(I). { + D = ast->create(I); +} + %type pattern {ast::Pattern*} -// pattern specification pattern(P) ::= node(N) rel(R) pattern(NEXT). { P = ast->create(N, R, NEXT); } @@ -102,6 +123,9 @@ pattern(P) ::= node(N). { P = ast->create(N, nullptr, nullptr); } +// update query +// MATCH ... WITH ... SET ... RETURN + %type rel {ast::Relationship*} rel(R) ::= MINUS rel_spec(S) MINUS. { // bidirectional @@ -316,15 +340,14 @@ expr(E) ::= idn(I) DOT idn(P). { %type idn {ast::Identifier*} idn(I) ::= IDN(X). { - I = ast->create(X->value, ""); + I = ast->create(X->value); } -/* -not the best idea TODO: how to put AS into the grammar -*/ -idn(I) ::= IDN(X) AS IDN(A). { - I = ast->create(X->value, A->value); -} +//%type alias {ast::Alias*} +// +//alias(A) ::= IDN(X) AS IDN(Y). { +// A = ast->create(X->value, Y->value); +//} expr(E) ::= INT(V). { auto value = std::stoi(V->value); diff --git a/cypher/cypher_lexer.hpp b/cypher/cypher_lexer.hpp index 2f47729b1..65b191278 100644 --- a/cypher/cypher_lexer.hpp +++ b/cypher/cypher_lexer.hpp @@ -47,6 +47,7 @@ public: rule("(?i:MATCH)", TK_MATCH); rule("(?i:WHERE)", TK_WHERE); rule("(?i:RETURN)", TK_RETURN); + rule("(?i:DELETE)", TK_DELETE); rule("(?i:CREATE)", TK_CREATE); rule("(?i:DISTINCT)", TK_DISTINCT); diff --git a/cypher/debug/tree_print.hpp b/cypher/debug/tree_print.hpp index ca27e4eef..769b66c8e 100644 --- a/cypher/debug/tree_print.hpp +++ b/cypher/debug/tree_print.hpp @@ -112,11 +112,16 @@ public: Traverser::visit(node); } + void visit(ast::Alias& alias) override + { + auto entry = printer.advance(); + entry << "Alias: '" << alias.name << "' AS '" << alias.alias << "'"; + } + void visit(ast::Identifier& idn) override { auto entry = printer.advance(); entry << "Identifier '" << idn.name << "'"; - entry << " Alias '" << idn.alias << "'"; } void visit(ast::Return& return_clause) override @@ -294,6 +299,18 @@ public: Traverser::visit(write_query); } + void visit(ast::DeleteQuery& delete_query) override + { + auto entry = printer.advance("Delete Query"); + Traverser::visit(delete_query); + } + + void visit(ast::Delete& delete_clause) override + { + auto entry = printer.advance("Delete"); + Traverser::visit(delete_clause); + } + void visit(ast::Create& create) override { auto entry = printer.advance("Create"); diff --git a/cypher/query/read-write/match-delete.cypher b/cypher/query/read-write/match-delete.cypher new file mode 100644 index 000000000..2452dd48f --- /dev/null +++ b/cypher/query/read-write/match-delete.cypher @@ -0,0 +1 @@ +MATCH (n) DELETE n diff --git a/cypher/query/read-write/match-where-delete.cypher b/cypher/query/read-write/match-where-delete.cypher new file mode 100644 index 000000000..1da6e5f77 --- /dev/null +++ b/cypher/query/read-write/match-where-delete.cypher @@ -0,0 +1 @@ +MATCH (n:Person) WHERE n.name="Alice" DELETE n diff --git a/cypher/visitor/traverser.hpp b/cypher/visitor/traverser.hpp index 678001532..4730ae0a1 100644 --- a/cypher/visitor/traverser.hpp +++ b/cypher/visitor/traverser.hpp @@ -12,8 +12,18 @@ public: void visit(ast::Start& start) override { - accept(start.read_query); - accept(start.write_query); + if (start.read_query != nullptr) + accept(start.read_query); + if (start.read_query != nullptr) + accept(start.write_query); + if (start.delete_query != nullptr) + accept(start.delete_query); + } + + void visit(ast::DeleteQuery& delete_query) override + { + accept(delete_query.match); + accept(delete_query.delete_clause); } void visit(ast::ReadQuery& read_query) override @@ -196,6 +206,11 @@ public: accept(distinct.identifier); } + void visit(ast::Delete& delete_clause) override + { + accept(delete_clause.identifier); + } + protected: template void accept(T* node)