MATCH ... SET ... RETURN clause
This commit is contained in:
parent
7c52817e41
commit
aa49a0997e
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,3 +9,4 @@
|
|||||||
memgraph
|
memgraph
|
||||||
*~
|
*~
|
||||||
*.pyc
|
*.pyc
|
||||||
|
*.breakpoint
|
||||||
|
@ -16,3 +16,4 @@
|
|||||||
#include "match.hpp"
|
#include "match.hpp"
|
||||||
#include "queries.hpp"
|
#include "queries.hpp"
|
||||||
#include "start.hpp"
|
#include "start.hpp"
|
||||||
|
#include "set.hpp"
|
||||||
|
@ -40,29 +40,34 @@ struct Relationship;
|
|||||||
|
|
||||||
struct Node;
|
struct Node;
|
||||||
struct LabelList;
|
struct LabelList;
|
||||||
|
|
||||||
struct Pattern;
|
struct Pattern;
|
||||||
|
|
||||||
struct Return;
|
struct Return;
|
||||||
struct ReturnList;
|
struct ReturnList;
|
||||||
struct Distinct;
|
struct Distinct;
|
||||||
struct Delete;
|
|
||||||
|
|
||||||
struct Match;
|
|
||||||
struct Where;
|
|
||||||
|
|
||||||
struct Start;
|
|
||||||
struct ReadQuery;
|
|
||||||
struct WriteQuery;
|
|
||||||
struct DeleteQuery;
|
|
||||||
|
|
||||||
struct Create;
|
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,
|
struct AstVisitor : public Visitor<Accessor, Boolean, Float, Identifier, Alias,
|
||||||
Integer, String, Property, And, Or, Lt, Gt, Ge, Le, Eq, Ne, Plus, Minus,
|
Integer, String, Property, And, Or, Lt, Gt, Ge, Le, Eq, Ne, Plus, Minus,
|
||||||
Star, Slash, Rem, PropertyList, RelationshipList, Relationship, Node,
|
Star, Slash, Rem, PropertyList, RelationshipList, Relationship, Node,
|
||||||
RelationshipSpecs, LabelList, ReturnList, Pattern, Match, ReadQuery,
|
RelationshipSpecs, LabelList, ReturnList, Pattern, Match, ReadQuery,
|
||||||
Start, Where, WriteQuery, Create, Return, Distinct, Delete,
|
Start, Where, WriteQuery, Create, Return, Distinct, Delete,
|
||||||
DeleteQuery> {};
|
DeleteQuery, UpdateQuery, Set, SetKey, SetValue, SetElement, SetList> {};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,24 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ast_node.hpp"
|
#include "ast_node.hpp"
|
||||||
#include "match.hpp"
|
|
||||||
#include "return.hpp"
|
|
||||||
#include "create.hpp"
|
#include "create.hpp"
|
||||||
|
#include "match.hpp"
|
||||||
|
#include "set.hpp"
|
||||||
#include "delete.hpp"
|
#include "delete.hpp"
|
||||||
|
#include "return.hpp"
|
||||||
|
|
||||||
namespace ast
|
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>
|
struct ReadQuery : public AstNode<ReadQuery>
|
||||||
{
|
{
|
||||||
ReadQuery(Match* match, Return* return_clause)
|
ReadQuery(Match* match, Return* return_clause)
|
||||||
@ -18,12 +28,16 @@ struct ReadQuery : public AstNode<ReadQuery>
|
|||||||
Return* return_clause;
|
Return* return_clause;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WriteQuery : public AstNode<WriteQuery>
|
struct UpdateQuery : public AstNode<UpdateQuery>
|
||||||
{
|
{
|
||||||
WriteQuery(Create* create, Return* return_clause)
|
UpdateQuery(Match* match_clause, Set* set_clause, Return* return_clause)
|
||||||
: create(create), return_clause(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;
|
Return* return_clause;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
58
cypher/ast/set.hpp
Normal file
58
cypher/ast/set.hpp
Normal 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -8,26 +8,17 @@ namespace ast
|
|||||||
|
|
||||||
struct Start : public AstNode<Start>
|
struct Start : public AstNode<Start>
|
||||||
{
|
{
|
||||||
Start(ReadQuery* read_query)
|
Start(WriteQuery* write_query) : write_query(write_query) {}
|
||||||
: read_query(read_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) {}
|
||||||
|
|
||||||
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
|
// TODO: the start structure must have a different implementation
|
||||||
// is this class necessary?
|
// is this class necessary?
|
||||||
ReadQuery* read_query{nullptr};
|
WriteQuery* write_query {nullptr};
|
||||||
WriteQuery* write_query{nullptr};
|
ReadQuery* read_query {nullptr};
|
||||||
DeleteQuery* delete_query{nullptr};
|
UpdateQuery* update_query {nullptr};
|
||||||
|
DeleteQuery* delete_query {nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -55,24 +55,20 @@
|
|||||||
|
|
||||||
// start structure
|
// start structure
|
||||||
|
|
||||||
start ::= read_query(RQ). {
|
|
||||||
ast->root = ast->create<ast::Start>(RQ);
|
|
||||||
}
|
|
||||||
|
|
||||||
start ::= write_query(WQ). {
|
start ::= write_query(WQ). {
|
||||||
ast->root = ast->create<ast::Start>(WQ);
|
ast->root = ast->create<ast::Start>(WQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
start ::= delete_query(DQ). {
|
start ::= read_query(RQ). {
|
||||||
ast->root = ast->create<ast::Start>(DQ);
|
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*}
|
start ::= delete_query(DQ). {
|
||||||
|
ast->root = ast->create<ast::Start>(DQ);
|
||||||
read_query(RQ) ::= match_clause(M) return_clause(R). {
|
|
||||||
RQ = ast->create<ast::ReadQuery>(M, R);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// write query structure
|
// write query structure
|
||||||
@ -87,6 +83,34 @@ write_query(WQ) ::= create_clause(C). {
|
|||||||
WQ = ast->create<ast::WriteQuery>(C, nullptr);
|
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
|
// delete query structure
|
||||||
|
|
||||||
%type delete_query {ast::DeleteQuery*}
|
%type delete_query {ast::DeleteQuery*}
|
||||||
@ -250,6 +274,9 @@ distinct(R) ::= DISTINCT idn(I). {
|
|||||||
R = ast->create<ast::Distinct>(I);
|
R = ast->create<ast::Distinct>(I);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// list of properties
|
||||||
|
// e.g. { name: "wayne", surname: "rooney"}
|
||||||
|
|
||||||
%type properties {ast::PropertyList*}
|
%type properties {ast::PropertyList*}
|
||||||
|
|
||||||
// '{' <property_list> '}'
|
// '{' <property_list> '}'
|
||||||
@ -343,12 +370,6 @@ idn(I) ::= IDN(X). {
|
|||||||
I = ast->create<ast::Identifier>(X->value);
|
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). {
|
expr(E) ::= INT(V). {
|
||||||
auto value = std::stoi(V->value);
|
auto value = std::stoi(V->value);
|
||||||
E = ast->create<ast::Integer>(value);
|
E = ast->create<ast::Integer>(value);
|
||||||
@ -369,3 +390,39 @@ expr(E) ::= BOOL(V). {
|
|||||||
E = ast->create<ast::Boolean>(value);
|
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);
|
||||||
|
}
|
||||||
|
@ -44,12 +44,13 @@ public:
|
|||||||
rule("(?i:FALSE)", TK_BOOL);
|
rule("(?i:FALSE)", TK_BOOL);
|
||||||
|
|
||||||
// keywords
|
// keywords
|
||||||
|
rule("(?i:CREATE)", TK_CREATE);
|
||||||
rule("(?i:MATCH)", TK_MATCH);
|
rule("(?i:MATCH)", TK_MATCH);
|
||||||
rule("(?i:WHERE)", TK_WHERE);
|
rule("(?i:WHERE)", TK_WHERE);
|
||||||
|
rule("(?i:SET)", TK_SET);
|
||||||
rule("(?i:RETURN)", TK_RETURN);
|
rule("(?i:RETURN)", TK_RETURN);
|
||||||
rule("(?i:DELETE)", TK_DELETE);
|
|
||||||
rule("(?i:CREATE)", TK_CREATE);
|
|
||||||
rule("(?i:DISTINCT)", TK_DISTINCT);
|
rule("(?i:DISTINCT)", TK_DISTINCT);
|
||||||
|
rule("(?i:DELETE)", TK_DELETE);
|
||||||
|
|
||||||
rule("(?i:AND)", TK_AND);
|
rule("(?i:AND)", TK_AND);
|
||||||
rule("(?i:OR)", TK_OR);
|
rule("(?i:OR)", TK_OR);
|
||||||
|
@ -317,6 +317,36 @@ public:
|
|||||||
Traverser::visit(create);
|
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:
|
private:
|
||||||
Printer printer;
|
Printer printer;
|
||||||
};
|
};
|
||||||
|
1
cypher/query/read-write/match-set-return.cypher
Normal file
1
cypher/query/read-write/match-set-return.cypher
Normal file
@ -0,0 +1 @@
|
|||||||
|
MATCH (n {surname:"Neville"}) SET n.surname="Neville", n.age=30 RETURN n
|
1
cypher/query/read-write/match-set.cypher
Normal file
1
cypher/query/read-write/match-set.cypher
Normal file
@ -0,0 +1 @@
|
|||||||
|
MATCH (n {age: 30, role: "player"}) SET n.age=31
|
@ -1 +1 @@
|
|||||||
CREATE (n {name: {value}})
|
CREATE (n {name: "value"})
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "cypher/ast/ast_visitor.hpp"
|
|
||||||
#include "cypher/ast/ast.hpp"
|
#include "cypher/ast/ast.hpp"
|
||||||
|
#include "cypher/ast/ast_visitor.hpp"
|
||||||
|
|
||||||
class Traverser : public ast::AstVisitor
|
class Traverser : public ast::AstVisitor
|
||||||
{
|
{
|
||||||
@ -12,10 +12,12 @@ public:
|
|||||||
|
|
||||||
void visit(ast::Start& start) override
|
void visit(ast::Start& start) override
|
||||||
{
|
{
|
||||||
|
if (start.write_query != nullptr)
|
||||||
|
accept(start.write_query);
|
||||||
if (start.read_query != nullptr)
|
if (start.read_query != nullptr)
|
||||||
accept(start.read_query);
|
accept(start.read_query);
|
||||||
if (start.read_query != nullptr)
|
if (start.update_query != nullptr)
|
||||||
accept(start.write_query);
|
accept(start.update_query);
|
||||||
if (start.delete_query != nullptr)
|
if (start.delete_query != nullptr)
|
||||||
accept(start.delete_query);
|
accept(start.delete_query);
|
||||||
}
|
}
|
||||||
@ -25,7 +27,7 @@ public:
|
|||||||
accept(delete_query.match);
|
accept(delete_query.match);
|
||||||
accept(delete_query.delete_clause);
|
accept(delete_query.delete_clause);
|
||||||
}
|
}
|
||||||
|
|
||||||
void visit(ast::ReadQuery& read_query) override
|
void visit(ast::ReadQuery& read_query) override
|
||||||
{
|
{
|
||||||
accept(read_query.match);
|
accept(read_query.match);
|
||||||
@ -196,6 +198,37 @@ public:
|
|||||||
accept(write_query.return_clause);
|
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
|
void visit(ast::Create& create) override
|
||||||
{
|
{
|
||||||
accept(create.pattern);
|
accept(create.pattern);
|
||||||
|
Loading…
Reference in New Issue
Block a user