MATCH ... SET ... RETURN clause
This commit is contained in:
parent
7c52817e41
commit
aa49a0997e
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,3 +9,4 @@
|
||||
memgraph
|
||||
*~
|
||||
*.pyc
|
||||
*.breakpoint
|
||||
|
@ -16,3 +16,4 @@
|
||||
#include "match.hpp"
|
||||
#include "queries.hpp"
|
||||
#include "start.hpp"
|
||||
#include "set.hpp"
|
||||
|
@ -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> {};
|
||||
|
||||
}
|
||||
|
@ -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
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,25 +8,16 @@ 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};
|
||||
ReadQuery* read_query {nullptr};
|
||||
UpdateQuery* update_query {nullptr};
|
||||
DeleteQuery* delete_query {nullptr};
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
};
|
||||
|
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
|
||||
|
||||
#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);
|
||||
|
Loading…
Reference in New Issue
Block a user