Add optional flag to Match clause

Reviewers: florijan, mislav.bradac

Reviewed By: florijan

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D320
This commit is contained in:
Teon Banek 2017-04-27 10:42:53 +02:00
parent f0aaca4a1a
commit 8b8aee9b38
3 changed files with 39 additions and 27 deletions

View File

@ -645,6 +645,7 @@ class Match : public Clause {
} }
std::vector<Pattern *> patterns_; std::vector<Pattern *> patterns_;
Where *where_ = nullptr; Where *where_ = nullptr;
bool optional_ = false;
protected: protected:
Match(int uid) : Clause(uid) {} Match(int uid) : Clause(uid) {}

View File

@ -129,10 +129,7 @@ antlrcpp::Any CypherMainVisitor::visitClause(CypherParser::ClauseContext *ctx) {
antlrcpp::Any CypherMainVisitor::visitCypherMatch( antlrcpp::Any CypherMainVisitor::visitCypherMatch(
CypherParser::CypherMatchContext *ctx) { CypherParser::CypherMatchContext *ctx) {
auto *match = storage_.Create<Match>(); auto *match = storage_.Create<Match>();
if (ctx->OPTIONAL()) { match->optional_ = !!ctx->OPTIONAL();
// TODO: implement other clauses.
throw utils::NotYetImplemented();
}
if (ctx->where()) { if (ctx->where()) {
match->where_ = ctx->where()->accept(this); match->where_ = ctx->where()->accept(this);
} }

View File

@ -505,16 +505,17 @@ TEST(CypherMainVisitorTest, NodePattern) {
ASSERT_EQ(query->clauses_.size(), 2U); ASSERT_EQ(query->clauses_.size(), 2U);
auto *match = dynamic_cast<Match *>(query->clauses_[0]); auto *match = dynamic_cast<Match *>(query->clauses_[0]);
ASSERT_TRUE(match); ASSERT_TRUE(match);
ASSERT_FALSE(match->where_); EXPECT_FALSE(match->optional_);
EXPECT_FALSE(match->where_);
ASSERT_EQ(match->patterns_.size(), 1U); ASSERT_EQ(match->patterns_.size(), 1U);
ASSERT_TRUE(match->patterns_[0]); ASSERT_TRUE(match->patterns_[0]);
ASSERT_EQ(match->patterns_[0]->atoms_.size(), 1U); ASSERT_EQ(match->patterns_[0]->atoms_.size(), 1U);
auto node = dynamic_cast<NodeAtom *>(match->patterns_[0]->atoms_[0]); auto node = dynamic_cast<NodeAtom *>(match->patterns_[0]->atoms_[0]);
ASSERT_TRUE(node); ASSERT_TRUE(node);
ASSERT_TRUE(node->identifier_); ASSERT_TRUE(node->identifier_);
ASSERT_EQ(node->identifier_->name_, EXPECT_EQ(node->identifier_->name_,
CypherMainVisitor::kAnonPrefix + std::to_string(1)); CypherMainVisitor::kAnonPrefix + std::to_string(1));
ASSERT_THAT(node->labels_, UnorderedElementsAre( EXPECT_THAT(node->labels_, UnorderedElementsAre(
ast_generator.db_accessor_->label("label1"), ast_generator.db_accessor_->label("label1"),
ast_generator.db_accessor_->label("label2"), ast_generator.db_accessor_->label("label2"),
ast_generator.db_accessor_->label("label3"))); ast_generator.db_accessor_->label("label3")));
@ -525,7 +526,7 @@ TEST(CypherMainVisitorTest, NodePattern) {
ASSERT_TRUE(literal->value_.type() == TypedValue::Type::Int); ASSERT_TRUE(literal->value_.type() == TypedValue::Type::Int);
properties[x.first] = literal->value_.Value<int64_t>(); properties[x.first] = literal->value_.Value<int64_t>();
} }
ASSERT_THAT(properties, EXPECT_THAT(properties,
UnorderedElementsAre( UnorderedElementsAre(
Pair(ast_generator.db_accessor_->property("a"), 5), Pair(ast_generator.db_accessor_->property("a"), 5),
Pair(ast_generator.db_accessor_->property("b"), 10))); Pair(ast_generator.db_accessor_->property("b"), 10)));
@ -535,19 +536,24 @@ TEST(CypherMainVisitorTest, NodePatternIdentifier) {
AstGenerator ast_generator("MATCH (var) RETURN 1"); AstGenerator ast_generator("MATCH (var) RETURN 1");
auto *query = ast_generator.query_; auto *query = ast_generator.query_;
auto *match = dynamic_cast<Match *>(query->clauses_[0]); auto *match = dynamic_cast<Match *>(query->clauses_[0]);
ASSERT_FALSE(match->where_); ASSERT_TRUE(match);
EXPECT_FALSE(match->optional_);
EXPECT_FALSE(match->where_);
auto node = dynamic_cast<NodeAtom *>(match->patterns_[0]->atoms_[0]); auto node = dynamic_cast<NodeAtom *>(match->patterns_[0]->atoms_[0]);
ASSERT_TRUE(node);
ASSERT_TRUE(node->identifier_); ASSERT_TRUE(node->identifier_);
ASSERT_EQ(node->identifier_->name_, "var"); EXPECT_EQ(node->identifier_->name_, "var");
ASSERT_THAT(node->labels_, UnorderedElementsAre()); EXPECT_THAT(node->labels_, UnorderedElementsAre());
ASSERT_THAT(node->properties_, UnorderedElementsAre()); EXPECT_THAT(node->properties_, UnorderedElementsAre());
} }
TEST(CypherMainVisitorTest, RelationshipPatternNoDetails) { TEST(CypherMainVisitorTest, RelationshipPatternNoDetails) {
AstGenerator ast_generator("MATCH ()--() RETURN 1"); AstGenerator ast_generator("MATCH ()--() RETURN 1");
auto *query = ast_generator.query_; auto *query = ast_generator.query_;
auto *match = dynamic_cast<Match *>(query->clauses_[0]); auto *match = dynamic_cast<Match *>(query->clauses_[0]);
ASSERT_FALSE(match->where_); ASSERT_TRUE(match);
EXPECT_FALSE(match->optional_);
EXPECT_FALSE(match->where_);
ASSERT_EQ(match->patterns_.size(), 1U); ASSERT_EQ(match->patterns_.size(), 1U);
ASSERT_TRUE(match->patterns_[0]); ASSERT_TRUE(match->patterns_[0]);
ASSERT_EQ(match->patterns_[0]->atoms_.size(), 3U); ASSERT_EQ(match->patterns_[0]->atoms_.size(), 3U);
@ -557,9 +563,9 @@ TEST(CypherMainVisitorTest, RelationshipPatternNoDetails) {
ASSERT_TRUE(edge); ASSERT_TRUE(edge);
auto *node2 = dynamic_cast<NodeAtom *>(match->patterns_[0]->atoms_[2]); auto *node2 = dynamic_cast<NodeAtom *>(match->patterns_[0]->atoms_[2]);
ASSERT_TRUE(node2); ASSERT_TRUE(node2);
ASSERT_EQ(edge->direction_, EdgeAtom::Direction::BOTH); EXPECT_EQ(edge->direction_, EdgeAtom::Direction::BOTH);
ASSERT_TRUE(edge->identifier_); ASSERT_TRUE(edge->identifier_);
ASSERT_THAT(edge->identifier_->name_, EXPECT_THAT(edge->identifier_->name_,
CypherMainVisitor::kAnonPrefix + std::to_string(2)); CypherMainVisitor::kAnonPrefix + std::to_string(2));
} }
@ -568,7 +574,8 @@ TEST(CypherMainVisitorTest, PatternPartBraces) {
AstGenerator ast_generator("MATCH ((()--())) RETURN 1"); AstGenerator ast_generator("MATCH ((()--())) RETURN 1");
auto *query = ast_generator.query_; auto *query = ast_generator.query_;
auto *match = dynamic_cast<Match *>(query->clauses_[0]); auto *match = dynamic_cast<Match *>(query->clauses_[0]);
ASSERT_FALSE(match->where_); ASSERT_TRUE(match);
EXPECT_FALSE(match->where_);
ASSERT_EQ(match->patterns_.size(), 1U); ASSERT_EQ(match->patterns_.size(), 1U);
ASSERT_TRUE(match->patterns_[0]); ASSERT_TRUE(match->patterns_[0]);
ASSERT_EQ(match->patterns_[0]->atoms_.size(), 3U); ASSERT_EQ(match->patterns_[0]->atoms_.size(), 3U);
@ -578,9 +585,9 @@ TEST(CypherMainVisitorTest, PatternPartBraces) {
ASSERT_TRUE(edge); ASSERT_TRUE(edge);
auto *node2 = dynamic_cast<NodeAtom *>(match->patterns_[0]->atoms_[2]); auto *node2 = dynamic_cast<NodeAtom *>(match->patterns_[0]->atoms_[2]);
ASSERT_TRUE(node2); ASSERT_TRUE(node2);
ASSERT_EQ(edge->direction_, EdgeAtom::Direction::BOTH); EXPECT_EQ(edge->direction_, EdgeAtom::Direction::BOTH);
ASSERT_TRUE(edge->identifier_); ASSERT_TRUE(edge->identifier_);
ASSERT_THAT(edge->identifier_->name_, EXPECT_THAT(edge->identifier_->name_,
CypherMainVisitor::kAnonPrefix + std::to_string(2)); CypherMainVisitor::kAnonPrefix + std::to_string(2));
} }
@ -589,10 +596,13 @@ TEST(CypherMainVisitorTest, RelationshipPatternDetails) {
"MATCH ()<-[:type1|type2 {a : 5, b : 10}]-() RETURN 1"); "MATCH ()<-[:type1|type2 {a : 5, b : 10}]-() RETURN 1");
auto *query = ast_generator.query_; auto *query = ast_generator.query_;
auto *match = dynamic_cast<Match *>(query->clauses_[0]); auto *match = dynamic_cast<Match *>(query->clauses_[0]);
ASSERT_FALSE(match->where_); ASSERT_TRUE(match);
EXPECT_FALSE(match->optional_);
EXPECT_FALSE(match->where_);
auto *edge = dynamic_cast<EdgeAtom *>(match->patterns_[0]->atoms_[1]); auto *edge = dynamic_cast<EdgeAtom *>(match->patterns_[0]->atoms_[1]);
ASSERT_EQ(edge->direction_, EdgeAtom::Direction::LEFT); ASSERT_TRUE(edge);
ASSERT_THAT( EXPECT_EQ(edge->direction_, EdgeAtom::Direction::LEFT);
EXPECT_THAT(
edge->edge_types_, edge->edge_types_,
UnorderedElementsAre(ast_generator.db_accessor_->edge_type("type1"), UnorderedElementsAre(ast_generator.db_accessor_->edge_type("type1"),
ast_generator.db_accessor_->edge_type("type2"))); ast_generator.db_accessor_->edge_type("type2")));
@ -603,7 +613,7 @@ TEST(CypherMainVisitorTest, RelationshipPatternDetails) {
ASSERT_TRUE(literal->value_.type() == TypedValue::Type::Int); ASSERT_TRUE(literal->value_.type() == TypedValue::Type::Int);
properties[x.first] = literal->value_.Value<int64_t>(); properties[x.first] = literal->value_.Value<int64_t>();
} }
ASSERT_THAT(properties, EXPECT_THAT(properties,
UnorderedElementsAre( UnorderedElementsAre(
Pair(ast_generator.db_accessor_->property("a"), 5), Pair(ast_generator.db_accessor_->property("a"), 5),
Pair(ast_generator.db_accessor_->property("b"), 10))); Pair(ast_generator.db_accessor_->property("b"), 10)));
@ -613,11 +623,14 @@ TEST(CypherMainVisitorTest, RelationshipPatternVariable) {
AstGenerator ast_generator("MATCH ()-[var]->() RETURN 1"); AstGenerator ast_generator("MATCH ()-[var]->() RETURN 1");
auto *query = ast_generator.query_; auto *query = ast_generator.query_;
auto *match = dynamic_cast<Match *>(query->clauses_[0]); auto *match = dynamic_cast<Match *>(query->clauses_[0]);
ASSERT_FALSE(match->where_); ASSERT_TRUE(match);
EXPECT_FALSE(match->optional_);
EXPECT_FALSE(match->where_);
auto *edge = dynamic_cast<EdgeAtom *>(match->patterns_[0]->atoms_[1]); auto *edge = dynamic_cast<EdgeAtom *>(match->patterns_[0]->atoms_[1]);
ASSERT_EQ(edge->direction_, EdgeAtom::Direction::RIGHT); ASSERT_TRUE(edge);
EXPECT_EQ(edge->direction_, EdgeAtom::Direction::RIGHT);
ASSERT_TRUE(edge->identifier_); ASSERT_TRUE(edge->identifier_);
ASSERT_THAT(edge->identifier_->name_, "var"); EXPECT_THAT(edge->identifier_->name_, "var");
} }
// // Relationship with unbounded variable range. // // Relationship with unbounded variable range.
@ -743,12 +756,13 @@ TEST(CypherMainVisitorTest, DeleteDetach) {
ASSERT_EQ(identifier1->name_, "n"); ASSERT_EQ(identifier1->name_, "n");
} }
TEST(CypherMainVisitorTest, MatchWhere) { TEST(CypherMainVisitorTest, OptionalMatchWhere) {
AstGenerator ast_generator("MATCH (n) WHERE m RETURN 1"); AstGenerator ast_generator("OPTIONAL MATCH (n) WHERE m RETURN 1");
auto *query = ast_generator.query_; auto *query = ast_generator.query_;
ASSERT_EQ(query->clauses_.size(), 2U); ASSERT_EQ(query->clauses_.size(), 2U);
auto *match = dynamic_cast<Match *>(query->clauses_[0]); auto *match = dynamic_cast<Match *>(query->clauses_[0]);
ASSERT_TRUE(match); ASSERT_TRUE(match);
EXPECT_TRUE(match->optional_);
ASSERT_TRUE(match->where_); ASSERT_TRUE(match->where_);
auto *identifier = dynamic_cast<Identifier *>(match->where_->expression_); auto *identifier = dynamic_cast<Identifier *>(match->where_->expression_);
ASSERT_TRUE(identifier); ASSERT_TRUE(identifier);