MATCH ... SET ... RETURN clause

This commit is contained in:
Marko Budiselic 2016-01-25 21:22:12 +01:00
parent 7c52817e41
commit aa49a0997e
13 changed files with 251 additions and 58 deletions

1
.gitignore vendored
View File

@ -9,3 +9,4 @@
memgraph
*~
*.pyc
*.breakpoint

View File

@ -16,3 +16,4 @@
#include "match.hpp"
#include "queries.hpp"
#include "start.hpp"
#include "set.hpp"

View File

@ -40,29 +40,34 @@ struct Relationship;
struct Node;
struct LabelList;
struct Pattern;
struct Return;
struct ReturnList;
struct Distinct;
struct Delete;
struct Match;
struct Where;
struct Start;
struct ReadQuery;
struct WriteQuery;
struct DeleteQuery;
struct Create;
struct Match;
struct Where;
struct Set;
struct Delete;
struct Start;
struct WriteQuery;
struct ReadQuery;
struct UpdateQuery;
struct DeleteQuery;
struct SetKey;
struct SetValue;
struct SetElement;
struct SetList;
struct AstVisitor : public Visitor<Accessor, Boolean, Float, Identifier, Alias,
Integer, String, Property, And, Or, Lt, Gt, Ge, Le, Eq, Ne, Plus, Minus,
Star, Slash, Rem, PropertyList, RelationshipList, Relationship, Node,
RelationshipSpecs, LabelList, ReturnList, Pattern, Match, ReadQuery,
Start, Where, WriteQuery, Create, Return, Distinct, Delete,
DeleteQuery> {};
DeleteQuery, UpdateQuery, Set, SetKey, SetValue, SetElement, SetList> {};
}

View File

@ -1,14 +1,24 @@
#pragma once
#include "ast_node.hpp"
#include "match.hpp"
#include "return.hpp"
#include "create.hpp"
#include "match.hpp"
#include "set.hpp"
#include "delete.hpp"
#include "return.hpp"
namespace ast
{
struct WriteQuery : public AstNode<WriteQuery>
{
WriteQuery(Create* create, Return* return_clause)
: create(create), return_clause(return_clause) {}
Create* create;
Return* return_clause;
};
struct ReadQuery : public AstNode<ReadQuery>
{
ReadQuery(Match* match, Return* return_clause)
@ -18,12 +28,16 @@ struct ReadQuery : public AstNode<ReadQuery>
Return* return_clause;
};
struct WriteQuery : public AstNode<WriteQuery>
struct UpdateQuery : public AstNode<UpdateQuery>
{
WriteQuery(Create* create, Return* return_clause)
: create(create), return_clause(return_clause) {}
UpdateQuery(Match* match_clause, Set* set_clause, Return* return_clause)
: match_clause(match_clause), set_clause(set_clause),
return_clause(return_clause)
{
}
Create* create;
Match* match_clause;
Set* set_clause;
Return* return_clause;
};

58
cypher/ast/set.hpp Normal file
View File

@ -0,0 +1,58 @@
#pragma once
#include "accessor.hpp"
#include "list.hpp"
#include "expr.hpp"
namespace ast
{
//
// SetList
// ^
// |
// |------------------------------------|
// SetElement
// ^
// |
// |-------------------|
// Accessor SetValue
// ^ ^
// | |
// |-------| |-------|
// SET n.name = "Paul", n.surname = "Scholes"
// ^ ^
// | |
// element entity element property
//
struct SetValue : public AstNode<SetValue>
{
SetValue(Expr* value)
: value(value) {}
Expr* value;
};
struct SetElement : public AstNode<SetElement>
{
SetElement(Accessor* accessor, SetValue* set_value)
: accessor(accessor), set_value(set_value) {}
Accessor* accessor;
SetValue* set_value;
};
struct SetList : public List<SetElement, SetList>
{
using List::List;
};
struct Set : public AstNode<Set>
{
Set(SetList* set_list)
: set_list(set_list) {}
SetList* set_list;
};
}

View File

@ -8,26 +8,17 @@ namespace ast
struct Start : public AstNode<Start>
{
Start(ReadQuery* read_query)
: read_query(read_query)
{
}
Start(WriteQuery* write_query)
: write_query(write_query)
{
}
Start(DeleteQuery* delete_query)
: delete_query(delete_query)
{
}
Start(WriteQuery* write_query) : write_query(write_query) {}
Start(ReadQuery* read_query) : read_query(read_query) {}
Start(UpdateQuery* update_query) : update_query(update_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};
WriteQuery* write_query {nullptr};
ReadQuery* read_query {nullptr};
UpdateQuery* update_query {nullptr};
DeleteQuery* delete_query {nullptr};
};
};

View File

@ -55,24 +55,20 @@
// start structure
start ::= read_query(RQ). {
ast->root = ast->create<ast::Start>(RQ);
}
start ::= write_query(WQ). {
ast->root = ast->create<ast::Start>(WQ);
}
start ::= delete_query(DQ). {
ast->root = ast->create<ast::Start>(DQ);
start ::= read_query(RQ). {
ast->root = ast->create<ast::Start>(RQ);
}
// read query structure
start ::= update_query(UQ). {
ast->root = ast->create<ast::Start>(UQ);
}
%type read_query {ast::ReadQuery*}
read_query(RQ) ::= match_clause(M) return_clause(R). {
RQ = ast->create<ast::ReadQuery>(M, R);
start ::= delete_query(DQ). {
ast->root = ast->create<ast::Start>(DQ);
}
// write query structure
@ -87,6 +83,34 @@ write_query(WQ) ::= create_clause(C). {
WQ = ast->create<ast::WriteQuery>(C, nullptr);
}
// read query structure
%type read_query {ast::ReadQuery*}
read_query(RQ) ::= match_clause(M) return_clause(R). {
RQ = ast->create<ast::ReadQuery>(M, R);
}
// update query structure
%type update_query {ast::UpdateQuery*}
update_query(UQ) ::= match_clause(M) set_clause(S) return_clause(R). {
UQ = ast->create<ast::UpdateQuery>(M, S, R);
}
update_query(UQ) ::= match_clause(M) set_clause(S). {
UQ = ast->create<ast::UpdateQuery>(M, S, nullptr);
}
// set clause
%type set_clause {ast::Set*}
set_clause(S) ::= SET set_list(L). {
S = ast->create<ast::Set>(L);
}
// delete query structure
%type delete_query {ast::DeleteQuery*}
@ -250,6 +274,9 @@ distinct(R) ::= DISTINCT idn(I). {
R = ast->create<ast::Distinct>(I);
}
// list of properties
// e.g. { name: "wayne", surname: "rooney"}
%type properties {ast::PropertyList*}
// '{' <property_list> '}'
@ -343,12 +370,6 @@ idn(I) ::= IDN(X). {
I = ast->create<ast::Identifier>(X->value);
}
//%type alias {ast::Alias*}
//
//alias(A) ::= IDN(X) AS IDN(Y). {
// A = ast->create<ast::Alias>(X->value, Y->value);
//}
expr(E) ::= INT(V). {
auto value = std::stoi(V->value);
E = ast->create<ast::Integer>(value);
@ -369,3 +390,39 @@ expr(E) ::= BOOL(V). {
E = ast->create<ast::Boolean>(value);
}
//%type alias {ast::Alias*}
//
//alias(A) ::= IDN(X) AS IDN(Y). {
// A = ast->create<ast::Alias>(X->value, Y->value);
//}
// set list
// e.g. MATCH (n) SET n.name = "Ryan", n.surname = "Giggs" RETURN n
%type set_list {ast::SetList*}
set_list(L) ::= set_element(E) COMMA set_list(N). {
L = ast->create<ast::SetList>(E, N);
}
set_list(L) ::= set_element(E). {
L = ast->create<ast::SetList>(E, nullptr);
}
%type set_element {ast::SetElement*}
set_element(E) ::= accessor(A) EQ set_value(V). {
E = ast->create<ast::SetElement>(A, V);
}
%type accessor {ast::Accessor*}
accessor(A) ::= idn(E) DOT idn(P). {
A = ast->create<ast::Accessor>(E, P);
}
%type set_value {ast::SetValue*}
set_value(V) ::= expr(E). {
V = ast->create<ast::SetValue>(E);
}

View File

@ -44,12 +44,13 @@ public:
rule("(?i:FALSE)", TK_BOOL);
// keywords
rule("(?i:CREATE)", TK_CREATE);
rule("(?i:MATCH)", TK_MATCH);
rule("(?i:WHERE)", TK_WHERE);
rule("(?i:SET)", TK_SET);
rule("(?i:RETURN)", TK_RETURN);
rule("(?i:DELETE)", TK_DELETE);
rule("(?i:CREATE)", TK_CREATE);
rule("(?i:DISTINCT)", TK_DISTINCT);
rule("(?i:DELETE)", TK_DELETE);
rule("(?i:AND)", TK_AND);
rule("(?i:OR)", TK_OR);

View File

@ -317,6 +317,36 @@ public:
Traverser::visit(create);
}
void visit(ast::UpdateQuery& update_query) override
{
auto entry = printer.advance("Update Query");
Traverser::visit(update_query);
}
void visit(ast::Set& set_clause) override
{
auto entry = printer.advance("Set");
Traverser::visit(set_clause);
}
void visit(ast::SetValue& set_value) override
{
auto entry = printer.advance("Set Value");
Traverser::visit(set_value);
}
void visit(ast::SetElement& set_element) override
{
auto entry = printer.advance("Set Element");
Traverser::visit(set_element);
}
void visit(ast::SetList& set_list) override
{
auto entry = printer.advance("Set List");
Traverser::visit(set_list);
}
private:
Printer printer;
};

View File

@ -0,0 +1 @@
MATCH (n {surname:"Neville"}) SET n.surname="Neville", n.age=30 RETURN n

View File

@ -0,0 +1 @@
MATCH (n {age: 30, role: "player"}) SET n.age=31

View File

@ -1 +1 @@
CREATE (n {name: {value}})
CREATE (n {name: "value"})

View File

@ -1,7 +1,7 @@
#pragma once
#include "cypher/ast/ast_visitor.hpp"
#include "cypher/ast/ast.hpp"
#include "cypher/ast/ast_visitor.hpp"
class Traverser : public ast::AstVisitor
{
@ -12,10 +12,12 @@ public:
void visit(ast::Start& start) override
{
if (start.write_query != nullptr)
accept(start.write_query);
if (start.read_query != nullptr)
accept(start.read_query);
if (start.read_query != nullptr)
accept(start.write_query);
if (start.update_query != nullptr)
accept(start.update_query);
if (start.delete_query != nullptr)
accept(start.delete_query);
}
@ -196,6 +198,37 @@ public:
accept(write_query.return_clause);
}
void visit(ast::UpdateQuery& update_query) override
{
accept(update_query.match_clause);
accept(update_query.set_clause);
if (update_query.return_clause != nullptr)
accept(update_query.return_clause);
}
void visit(ast::Set& set_clause) override
{
accept(set_clause.set_list);
}
void visit(ast::SetValue& set_value) override
{
accept(set_value.value);
}
void visit(ast::SetElement& set_element) override
{
accept(set_element.accessor);
accept(set_element.set_value);
}
void visit(ast::SetList& set_list) override
{
accept(set_list.value);
if (set_list.next != nullptr)
accept(set_list.next);
}
void visit(ast::Create& create) override
{
accept(create.pattern);