Convert antlr merge to AST
Summary: Convert antlr merge to AST and add Merge node to AST Reviewers: florijan, mislav.bradac Reviewed By: florijan Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D315
This commit is contained in:
parent
cc00101cbd
commit
788d4a37d0
@ -851,6 +851,31 @@ class RemoveLabels : public Clause {
|
|||||||
: Clause(uid), identifier_(identifier), labels_(labels) {}
|
: Clause(uid), identifier_(identifier), labels_(labels) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Merge : public Clause {
|
||||||
|
friend class AstTreeStorage;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Accept(TreeVisitorBase &visitor) override {
|
||||||
|
if (visitor.PreVisit(*this)) {
|
||||||
|
visitor.Visit(*this);
|
||||||
|
pattern_->Accept(visitor);
|
||||||
|
for (auto &set : on_match_) {
|
||||||
|
set->Accept(visitor);
|
||||||
|
}
|
||||||
|
for (auto &set : on_create_) {
|
||||||
|
set->Accept(visitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Pattern *pattern_ = nullptr;
|
||||||
|
std::vector<Clause *> on_match_;
|
||||||
|
std::vector<Clause *> on_create_;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Merge(int uid) : Clause(uid) {}
|
||||||
|
};
|
||||||
|
|
||||||
// It would be better to call this AstTree, but we already have a class Tree,
|
// It would be better to call this AstTree, but we already have a class Tree,
|
||||||
// which could be renamed to Node or AstTreeNode, but we also have a class
|
// which could be renamed to Node or AstTreeNode, but we also have a class
|
||||||
// called NodeAtom...
|
// called NodeAtom...
|
||||||
|
@ -44,6 +44,7 @@ class SetProperties;
|
|||||||
class SetLabels;
|
class SetLabels;
|
||||||
class RemoveProperty;
|
class RemoveProperty;
|
||||||
class RemoveLabels;
|
class RemoveLabels;
|
||||||
|
class Merge;
|
||||||
|
|
||||||
using TreeVisitorBase = ::utils::Visitor<
|
using TreeVisitorBase = ::utils::Visitor<
|
||||||
Query, NamedExpression, OrOperator, XorOperator, AndOperator, NotOperator,
|
Query, NamedExpression, OrOperator, XorOperator, AndOperator, NotOperator,
|
||||||
@ -53,5 +54,5 @@ using TreeVisitorBase = ::utils::Visitor<
|
|||||||
UnaryPlusOperator, UnaryMinusOperator, IsNullOperator, Identifier, Literal,
|
UnaryPlusOperator, UnaryMinusOperator, IsNullOperator, Identifier, Literal,
|
||||||
PropertyLookup, Aggregation, Function, Create, Match, Return, With, Pattern,
|
PropertyLookup, Aggregation, Function, Create, Match, Return, With, Pattern,
|
||||||
NodeAtom, EdgeAtom, Delete, Where, SetProperty, SetProperties, SetLabels,
|
NodeAtom, EdgeAtom, Delete, Where, SetProperty, SetProperties, SetLabels,
|
||||||
RemoveProperty, RemoveLabels>;
|
RemoveProperty, RemoveLabels, Merge>;
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,8 @@ antlrcpp::Any CypherMainVisitor::visitSingleQuery(
|
|||||||
dynamic_cast<SetProperties *>(clause) ||
|
dynamic_cast<SetProperties *>(clause) ||
|
||||||
dynamic_cast<SetLabels *>(clause) ||
|
dynamic_cast<SetLabels *>(clause) ||
|
||||||
dynamic_cast<RemoveProperty *>(clause) ||
|
dynamic_cast<RemoveProperty *>(clause) ||
|
||||||
dynamic_cast<RemoveLabels *>(clause)) {
|
dynamic_cast<RemoveLabels *>(clause) ||
|
||||||
|
dynamic_cast<Merge *>(clause)) {
|
||||||
if (has_return) {
|
if (has_return) {
|
||||||
throw SemanticException("Update clauses can't be after return");
|
throw SemanticException("Update clauses can't be after return");
|
||||||
}
|
}
|
||||||
@ -116,6 +117,9 @@ antlrcpp::Any CypherMainVisitor::visitClause(CypherParser::ClauseContext *ctx) {
|
|||||||
if (ctx->with()) {
|
if (ctx->with()) {
|
||||||
return static_cast<Clause *>(ctx->with()->accept(this).as<With *>());
|
return static_cast<Clause *>(ctx->with()->accept(this).as<With *>());
|
||||||
}
|
}
|
||||||
|
if (ctx->merge()) {
|
||||||
|
return static_cast<Clause *>(ctx->merge()->accept(this).as<Merge *>());
|
||||||
|
}
|
||||||
// TODO: implement other clauses.
|
// TODO: implement other clauses.
|
||||||
throw utils::NotYetImplemented();
|
throw utils::NotYetImplemented();
|
||||||
return 0;
|
return 0;
|
||||||
@ -943,4 +947,20 @@ antlrcpp::Any CypherMainVisitor::visitWith(CypherParser::WithContext *ctx) {
|
|||||||
}
|
}
|
||||||
return with;
|
return with;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
antlrcpp::Any CypherMainVisitor::visitMerge(CypherParser::MergeContext *ctx) {
|
||||||
|
auto *merge = storage_.Create<Merge>();
|
||||||
|
merge->pattern_ = ctx->patternPart()->accept(this);
|
||||||
|
for (auto &merge_action : ctx->mergeAction()) {
|
||||||
|
auto set = merge_action->set()->accept(this).as<std::vector<Clause *>>();
|
||||||
|
if (merge_action->MATCH()) {
|
||||||
|
merge->on_match_.insert(merge->on_match_.end(), set.begin(), set.end());
|
||||||
|
} else {
|
||||||
|
debug_assert(merge_action->CREATE(), "Expected ON MATCH or ON CREATE");
|
||||||
|
merge->on_create_.insert(merge->on_create_.end(), set.begin(), set.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return merge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace query::frontend
|
||||||
|
@ -470,6 +470,11 @@ class CypherMainVisitor : public antlropencypher::CypherBaseVisitor {
|
|||||||
*/
|
*/
|
||||||
antlrcpp::Any visitWith(CypherParser::WithContext *ctx) override;
|
antlrcpp::Any visitWith(CypherParser::WithContext *ctx) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Merge*
|
||||||
|
*/
|
||||||
|
antlrcpp::Any visitMerge(CypherParser::MergeContext *ctx) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Query *query() { return query_; }
|
Query *query() { return query_; }
|
||||||
const static std::string kAnonPrefix;
|
const static std::string kAnonPrefix;
|
||||||
|
@ -924,6 +924,7 @@ TEST(CypherMainVisitorTest, ClausesOrdering) {
|
|||||||
ASSERT_THROW(AstGenerator("RETURN 1 RETURN 1"), SemanticException);
|
ASSERT_THROW(AstGenerator("RETURN 1 RETURN 1"), SemanticException);
|
||||||
ASSERT_THROW(AstGenerator("RETURN 1 MATCH (n) RETURN n"), SemanticException);
|
ASSERT_THROW(AstGenerator("RETURN 1 MATCH (n) RETURN n"), SemanticException);
|
||||||
ASSERT_THROW(AstGenerator("RETURN 1 DELETE n"), SemanticException);
|
ASSERT_THROW(AstGenerator("RETURN 1 DELETE n"), SemanticException);
|
||||||
|
ASSERT_THROW(AstGenerator("RETURN 1 MERGE (n)"), SemanticException);
|
||||||
ASSERT_THROW(AstGenerator("RETURN 1 WITH n AS m RETURN 1"),
|
ASSERT_THROW(AstGenerator("RETURN 1 WITH n AS m RETURN 1"),
|
||||||
SemanticException);
|
SemanticException);
|
||||||
|
|
||||||
@ -945,4 +946,21 @@ TEST(CypherMainVisitorTest, ClausesOrdering) {
|
|||||||
AstGenerator("WITH 1 AS n SET n += m");
|
AstGenerator("WITH 1 AS n SET n += m");
|
||||||
AstGenerator("WITH 1 AS n MATCH (n) RETURN n");
|
AstGenerator("WITH 1 AS n MATCH (n) RETURN n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(CypherMainVisitorTest, Merge) {
|
||||||
|
AstGenerator ast_generator(
|
||||||
|
"MERGE (a) -[:r]- (b) ON MATCH SET a.x = b.x "
|
||||||
|
"ON CREATE SET b :label ON MATCH SET b = a");
|
||||||
|
auto *query = ast_generator.query_;
|
||||||
|
ASSERT_EQ(query->clauses_.size(), 1U);
|
||||||
|
auto *merge = dynamic_cast<Merge *>(query->clauses_[0]);
|
||||||
|
ASSERT_TRUE(merge);
|
||||||
|
EXPECT_TRUE(dynamic_cast<Pattern *>(merge->pattern_));
|
||||||
|
ASSERT_EQ(merge->on_match_.size(), 2U);
|
||||||
|
EXPECT_TRUE(dynamic_cast<SetProperty *>(merge->on_match_[0]));
|
||||||
|
EXPECT_TRUE(dynamic_cast<SetProperties *>(merge->on_match_[1]));
|
||||||
|
ASSERT_EQ(merge->on_create_.size(), 1U);
|
||||||
|
EXPECT_TRUE(dynamic_cast<SetLabels *>(merge->on_create_[0]));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user