Where and delete from antlr to highlevel ast

Reviewers: teon.banek

Reviewed By: teon.banek

Differential Revision: https://phabricator.memgraph.io/D181
This commit is contained in:
Mislav Bradac 2017-03-27 10:04:37 +02:00
parent 9c7acf780c
commit 6a547839e1
5 changed files with 122 additions and 3 deletions

View File

@ -496,7 +496,6 @@ class Match : public Clause {
friend class AstTreeStorage;
public:
std::vector<Pattern *> patterns_;
void Accept(TreeVisitorBase &visitor) override {
visitor.Visit(*this);
for (auto &pattern : patterns_) {
@ -504,6 +503,8 @@ class Match : public Clause {
}
visitor.PostVisit(*this);
}
std::vector<Pattern *> patterns_;
Where *where_ = nullptr;
protected:
Match(int uid) : Clause(uid) {}
@ -526,6 +527,39 @@ class Return : public Clause {
Return(int uid) : Clause(uid) {}
};
class Delete : public Clause {
friend class AstTreeStorage;
public:
void Accept(TreeVisitorBase &visitor) override {
visitor.Visit(*this);
for (auto &expr : expressions_) {
expr->Accept(visitor);
}
visitor.PostVisit(*this);
}
std::vector<Expression *> expressions_;
bool detach_ = false;
protected:
Delete(int uid) : Clause(uid) {}
};
class Where : public Tree {
friend class AstTreeStorage;
public:
void Accept(TreeVisitorBase &visitor) override {
visitor.Visit(*this);
expression_->Accept(visitor);
visitor.PostVisit(*this);
}
Expression *expression_ = nullptr;
protected:
Where(int uid) : Tree(uid) {}
};
// 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
// called NodeAtom...

View File

@ -33,6 +33,8 @@ class LessOperator;
class GreaterOperator;
class LessEqualOperator;
class GreaterEqualOperator;
class Delete;
class Where;
using TreeVisitorBase = ::utils::Visitor<
Query, NamedExpression, OrOperator, XorOperator, AndOperator, NotOperator,
@ -40,5 +42,5 @@ using TreeVisitorBase = ::utils::Visitor<
DivisionOperator, ModOperator, NotEqualOperator, EqualOperator,
LessOperator, GreaterOperator, LessEqualOperator, GreaterEqualOperator,
UnaryPlusOperator, UnaryMinusOperator, Identifier, Literal, PropertyLookup,
Create, Match, Return, Pattern, NodeAtom, EdgeAtom>;
Create, Match, Return, Pattern, NodeAtom, EdgeAtom, Delete, Where>;
}

View File

@ -50,6 +50,10 @@ antlrcpp::Any CypherMainVisitor::visitClause(CypherParser::ClauseContext *ctx) {
if (ctx->create()) {
return static_cast<Clause *>(ctx->create()->accept(this).as<Create *>());
}
if (ctx->cypherDelete()) {
return static_cast<Clause *>(
ctx->cypherDelete()->accept(this).as<Delete *>());
}
// TODO: implement other clauses.
throw NotYetImplemented();
return 0;
@ -58,10 +62,13 @@ antlrcpp::Any CypherMainVisitor::visitClause(CypherParser::ClauseContext *ctx) {
antlrcpp::Any CypherMainVisitor::visitCypherMatch(
CypherParser::CypherMatchContext *ctx) {
auto *match = storage_.Create<Match>();
if (ctx->OPTIONAL() || ctx->where()) {
if (ctx->OPTIONAL()) {
// TODO: implement other clauses.
throw NotYetImplemented();
}
if (ctx->where()) {
match->where_ = ctx->where()->accept(this);
}
match->patterns_ = ctx->pattern()->accept(this).as<std::vector<Pattern *>>();
return match;
}
@ -665,5 +672,23 @@ antlrcpp::Any CypherMainVisitor::visitBooleanLiteral(
throw std::exception();
}
}
antlrcpp::Any CypherMainVisitor::visitCypherDelete(
CypherParser::CypherDeleteContext *ctx) {
auto *del = storage_.Create<Delete>();
if (ctx->DETACH()) {
del->detach_ = true;
}
for (auto *expression : ctx->expression()) {
del->expressions_.push_back(expression->accept(this));
}
return del;
}
antlrcpp::Any CypherMainVisitor::visitWhere(CypherParser::WhereContext *ctx) {
auto *where = storage_.Create<Where>();
where->expression_ = ctx->expression()->accept(this);
return where;
}
}
}

View File

@ -400,6 +400,17 @@ class CypherMainVisitor : public antlropencypher::CypherBaseVisitor {
antlrcpp::Any visitDoubleLiteral(
CypherParser::DoubleLiteralContext *ctx) override;
/**
* @return Delete*
*/
antlrcpp::Any visitCypherDelete(
CypherParser::CypherDeleteContext *ctx) override;
/**
* @return Where*
*/
antlrcpp::Any visitWhere(CypherParser::WhereContext *ctx) override;
public:
Query *query() { return query_; }
const static std::string kAnonPrefix;

View File

@ -367,6 +367,7 @@ TEST(CypherMainVisitorTest, NodePattern) {
ASSERT_EQ(query->clauses_.size(), 1U);
auto *match = dynamic_cast<Match *>(query->clauses_[0]);
ASSERT_TRUE(match);
ASSERT_FALSE(match->where_);
ASSERT_EQ(match->patterns_.size(), 1U);
ASSERT_TRUE(match->patterns_[0]);
ASSERT_EQ(match->patterns_[0]->atoms_.size(), 1U);
@ -396,6 +397,7 @@ TEST(CypherMainVisitorTest, NodePatternIdentifier) {
AstGenerator ast_generator("MATCH (var)");
auto *query = ast_generator.query_;
auto *match = dynamic_cast<Match *>(query->clauses_[0]);
ASSERT_FALSE(match->where_);
auto node = dynamic_cast<NodeAtom *>(match->patterns_[0]->atoms_[0]);
ASSERT_TRUE(node->identifier_);
ASSERT_EQ(node->identifier_->name_, "var");
@ -407,6 +409,7 @@ TEST(CypherMainVisitorTest, RelationshipPatternNoDetails) {
AstGenerator ast_generator("MATCH ()--()");
auto *query = ast_generator.query_;
auto *match = dynamic_cast<Match *>(query->clauses_[0]);
ASSERT_FALSE(match->where_);
ASSERT_EQ(match->patterns_.size(), 1U);
ASSERT_TRUE(match->patterns_[0]);
ASSERT_EQ(match->patterns_[0]->atoms_.size(), 3U);
@ -427,6 +430,7 @@ TEST(CypherMainVisitorTest, PatternPartBraces) {
AstGenerator ast_generator("MATCH ((()--()))");
auto *query = ast_generator.query_;
auto *match = dynamic_cast<Match *>(query->clauses_[0]);
ASSERT_FALSE(match->where_);
ASSERT_EQ(match->patterns_.size(), 1U);
ASSERT_TRUE(match->patterns_[0]);
ASSERT_EQ(match->patterns_[0]->atoms_.size(), 3U);
@ -446,6 +450,7 @@ TEST(CypherMainVisitorTest, RelationshipPatternDetails) {
AstGenerator ast_generator("MATCH ()<-[:type1|type2 {a : 5, b : 10}]-()");
auto *query = ast_generator.query_;
auto *match = dynamic_cast<Match *>(query->clauses_[0]);
ASSERT_FALSE(match->where_);
auto *edge = dynamic_cast<EdgeAtom *>(match->patterns_[0]->atoms_[1]);
ASSERT_EQ(edge->direction_, EdgeAtom::Direction::LEFT);
ASSERT_THAT(
@ -469,6 +474,7 @@ TEST(CypherMainVisitorTest, RelationshipPatternVariable) {
AstGenerator ast_generator("MATCH ()-[var]->()");
auto *query = ast_generator.query_;
auto *match = dynamic_cast<Match *>(query->clauses_[0]);
ASSERT_FALSE(match->where_);
auto *edge = dynamic_cast<EdgeAtom *>(match->patterns_[0]->atoms_[1]);
ASSERT_EQ(edge->direction_, EdgeAtom::Direction::RIGHT);
ASSERT_TRUE(edge->identifier_);
@ -568,4 +574,45 @@ TEST(CypherMainVisitorTest, Create) {
ASSERT_TRUE(node->identifier_);
ASSERT_EQ(node->identifier_->name_, "n");
}
TEST(CypherMainVisitorTest, Delete) {
AstGenerator ast_generator("DELETE n, m");
auto *query = ast_generator.query_;
ASSERT_EQ(query->clauses_.size(), 1U);
auto *del = dynamic_cast<Delete *>(query->clauses_[0]);
ASSERT_TRUE(del);
ASSERT_FALSE(del->detach_);
ASSERT_EQ(del->expressions_.size(), 2U);
auto *identifier1 = dynamic_cast<Identifier *>(del->expressions_[0]);
ASSERT_TRUE(identifier1);
ASSERT_EQ(identifier1->name_, "n");
auto *identifier2 = dynamic_cast<Identifier *>(del->expressions_[1]);
ASSERT_TRUE(identifier2);
ASSERT_EQ(identifier2->name_, "m");
}
TEST(CypherMainVisitorTest, DeleteDetach) {
AstGenerator ast_generator("DETACH DELETE n");
auto *query = ast_generator.query_;
ASSERT_EQ(query->clauses_.size(), 1U);
auto *del = dynamic_cast<Delete *>(query->clauses_[0]);
ASSERT_TRUE(del);
ASSERT_TRUE(del->detach_);
ASSERT_EQ(del->expressions_.size(), 1U);
auto *identifier1 = dynamic_cast<Identifier *>(del->expressions_[0]);
ASSERT_TRUE(identifier1);
ASSERT_EQ(identifier1->name_, "n");
}
TEST(Visitor, MatchWhere) {
AstGenerator ast_generator("MATCH (n) WHERE n");
auto *query = ast_generator.query_;
ASSERT_EQ(query->clauses_.size(), 1U);
auto *match = dynamic_cast<Match *>(query->clauses_[0]);
ASSERT_TRUE(match);
ASSERT_TRUE(match->where_);
auto *identifier = dynamic_cast<Identifier *>(match->where_->expression_);
ASSERT_TRUE(identifier);
ASSERT_EQ(identifier->name_, "n");
}
}