diff --git a/src/query/frontend/ast/ast.hpp b/src/query/frontend/ast/ast.hpp index dc177a9ac..58f4f8a90 100644 --- a/src/query/frontend/ast/ast.hpp +++ b/src/query/frontend/ast/ast.hpp @@ -47,8 +47,8 @@ class PropertyLookup : public Expression { visitor.PostVisit(*this); } - Expression *expression_; - GraphDb::Property property_; + Expression *expression_ = nullptr; + GraphDb::Property property_ = nullptr; // TODO potential problem: property lookups are allowed on both map literals // and records, but map literals have strings as keys and records have // GraphDb::Property @@ -72,7 +72,7 @@ class NamedExpression : public Tree { } std::string name_; - Expression* expression_; + Expression* expression_ = nullptr; protected: NamedExpression(int uid) : Tree(uid) {} @@ -95,7 +95,7 @@ class NodeAtom : public PatternAtom { visitor.PostVisit(*this); } - Identifier* identifier_; + Identifier* identifier_ = nullptr; std::vector labels_; std::map properties_; @@ -103,7 +103,6 @@ class NodeAtom : public PatternAtom { NodeAtom(int uid) : PatternAtom(uid) {} NodeAtom(int uid, Identifier *identifier) : PatternAtom(uid), identifier_(identifier) {} - }; class EdgeAtom : public PatternAtom { @@ -117,8 +116,9 @@ class EdgeAtom : public PatternAtom { visitor.PostVisit(*this); } - Direction direction = Direction::BOTH; - Identifier* identifier_; + Direction direction_ = Direction::BOTH; + Identifier* identifier_ = nullptr; + std::vector types_; protected: EdgeAtom(int uid) : PatternAtom(uid) {} @@ -140,7 +140,7 @@ class Pattern : public Tree { } visitor.PostVisit(*this); } - Identifier* identifier_; + Identifier* identifier_ = nullptr; std::vector atoms_; protected: diff --git a/src/query/frontend/ast/cypher_main_visitor.cpp b/src/query/frontend/ast/cypher_main_visitor.cpp index b006c48fd..1df03b15f 100644 --- a/src/query/frontend/ast/cypher_main_visitor.cpp +++ b/src/query/frontend/ast/cypher_main_visitor.cpp @@ -39,18 +39,36 @@ namespace { //} } +const std::string CypherMainVisitor::kAnonPrefix = "anon"; + antlrcpp::Any CypherMainVisitor::visitSingleQuery(CypherParser::SingleQueryContext *ctx) { query_ = storage_.query(); for (auto *child : ctx->clause()) { query_->clauses_.push_back(child->accept(this)); } + // Construct unique names for anonymous identifiers; + int id = 1; + for (auto **identifier : anonymous_identifiers) { + while (true) { + std::string id_name = kAnonPrefix + std::to_string(id++); + if (users_identifiers.find(id_name) == users_identifiers.end()) { + *identifier = storage_.Create(id_name); + break; + } + } + } return query_; } + antlrcpp::Any CypherMainVisitor::visitClause(CypherParser::ClauseContext *ctx) { - if (!ctx->cypherReturn() && !ctx->cypherMatch()) { - throw std::exception(); + if (ctx->cypherReturn()) { + return (Clause *)ctx->cypherReturn()->accept(this).as(); } + if (ctx->cypherMatch()) { + return (Clause *)ctx->cypherMatch()->accept(this).as(); + } + throw std::exception(); return visitChildren(ctx); } @@ -110,21 +128,15 @@ antlrcpp::Any CypherMainVisitor::visitNodePattern(CypherParser::NodePatternContext *ctx) { auto *node = storage_.Create(); if (ctx->variable()) { - // TODO: user's identifiers should be unchanged, but we must be sure that - // ours identifier is not in a clash with user's. std::string variable = ctx->variable()->accept(this); - node->identifier_ = - storage_.Create(kUserIdentPrefix + variable); + node->identifier_ = storage_.Create(variable); + users_identifiers.insert(variable); } else { - node->identifier_ = storage_.Create( - kAnonIdentPrefix + std::to_string(next_ident_id_++)); + anonymous_identifiers.push_back(&node->identifier_); } if (ctx->nodeLabels()) { - std::vector labels = ctx->nodeLabels()->accept(this); - for (const auto &label : labels) { - // TODO: Labels should be garbage collected. - node->labels_.push_back(ctx_.db_accessor_.label(label)); - } + node->labels_ = + ctx->nodeLabels()->accept(this).as>(); } if (ctx->properties()) { throw std::exception(); @@ -138,9 +150,9 @@ CypherMainVisitor::visitNodePattern(CypherParser::NodePatternContext *ctx) { antlrcpp::Any CypherMainVisitor::visitNodeLabels(CypherParser::NodeLabelsContext *ctx) { - std::vector labels; + std::vector labels; for (auto *node_label : ctx->nodeLabel()) { - labels.push_back(node_label->accept(this)); + labels.push_back(ctx_.db_accessor_.label(node_label->accept(this))); } return labels; } @@ -193,13 +205,11 @@ antlrcpp::Any CypherMainVisitor::visitPatternPart(CypherParser::PatternPartContext *ctx) { Pattern *pattern = ctx->anonymousPatternPart()->accept(this); if (ctx->variable()) { - // TODO: don't change user's identifier name. std::string variable = ctx->variable()->accept(this); - pattern->identifier_ = - storage_.Create(kUserIdentPrefix + variable); + pattern->identifier_ = storage_.Create(variable); + users_identifiers.insert(variable); } else { - pattern->identifier_ = storage_.Create( - kAnonIdentPrefix + std::to_string(next_ident_id_++)); + anonymous_identifiers.push_back(&pattern->identifier_); } return pattern; } @@ -210,7 +220,7 @@ antlrcpp::Any CypherMainVisitor::visitPatternElement( return ctx->patternElement()->accept(this); } auto pattern = storage_.Create(); - pattern->atoms_.push_back(ctx->nodePattern()->accept(this)); + pattern->atoms_.push_back(ctx->nodePattern()->accept(this).as()); for (auto *pattern_element_chain : ctx->patternElementChain()) { std::pair element = pattern_element_chain->accept(this); @@ -223,8 +233,8 @@ antlrcpp::Any CypherMainVisitor::visitPatternElement( antlrcpp::Any CypherMainVisitor::visitPatternElementChain( CypherParser::PatternElementChainContext *ctx) { return std::pair( - ctx->relationshipPattern()->accept(this), - ctx->nodePattern()->accept(this)); + ctx->relationshipPattern()->accept(this).as(), + ctx->nodePattern()->accept(this).as()); } antlrcpp::Any CypherMainVisitor::visitRelationshipPattern( @@ -234,12 +244,14 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipPattern( if (ctx->relationshipDetail()->variable()) { std::string variable = ctx->relationshipDetail()->variable()->accept(this); - // TODO: Don't change user's identifier name. - edge->identifier_ = - storage_.Create(kUserIdentPrefix + variable); + edge->identifier_ = storage_.Create(variable); + users_identifiers.insert(variable); } if (ctx->relationshipDetail()->relationshipTypes()) { - throw std::exception(); + edge->types_ = ctx->relationshipDetail() + ->relationshipTypes() + ->accept(this) + .as>(); } if (ctx->relationshipDetail()->properties()) { throw std::exception(); @@ -256,18 +268,17 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipPattern( // relationship.lower_bound = range.first; // relationship.upper_bound = range.second; if (!edge->identifier_) { - edge->identifier_ = storage_.Create( - kAnonIdentPrefix + std::to_string(next_ident_id_++)); + anonymous_identifiers.push_back(&edge->identifier_); } if (ctx->leftArrowHead() && !ctx->rightArrowHead()) { - edge->direction = EdgeAtom::Direction::LEFT; + edge->direction_ = EdgeAtom::Direction::LEFT; } else if (!ctx->leftArrowHead() && ctx->rightArrowHead()) { - edge->direction = EdgeAtom::Direction::RIGHT; + edge->direction_ = EdgeAtom::Direction::RIGHT; } else { // <-[]-> and -[]- is the same thing as far as we understand openCypher // grammar. - edge->direction = EdgeAtom::Direction::BOTH; + edge->direction_ = EdgeAtom::Direction::BOTH; } return edge; } @@ -280,14 +291,11 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipDetail( antlrcpp::Any CypherMainVisitor::visitRelationshipTypes( CypherParser::RelationshipTypesContext *ctx) { - throw std::exception(); - (void)ctx; - return 0; - // std::vector types; - // for (auto *label : ctx->relTypeName()) { - // types.push_back(label->accept(this)); - // } - // return types; + std::vector types; + for (auto *edge_type : ctx->relTypeName()) { + types.push_back(ctx_.db_accessor_.edge_type(edge_type->accept(this))); + } + return types; } antlrcpp::Any @@ -546,7 +554,8 @@ antlrcpp::Any CypherMainVisitor::visitAtom(CypherParser::AtomContext *ctx) { return ctx->parenthesizedExpression()->accept(this); } else if (ctx->variable()) { std::string variable = ctx->variable()->accept(this); - return storage_.Create(kUserIdentPrefix + variable); + users_identifiers.insert(variable); + return storage_.Create(variable); } // TODO: Implement this. We don't support comprehensions, functions, // filtering... at the moment. diff --git a/src/query/frontend/ast/cypher_main_visitor.hpp b/src/query/frontend/ast/cypher_main_visitor.hpp index 3e95f8bc1..29515a990 100644 --- a/src/query/frontend/ast/cypher_main_visitor.hpp +++ b/src/query/frontend/ast/cypher_main_visitor.hpp @@ -290,14 +290,16 @@ private: public: Query *query() { return query_; } + const static std::string kAnonPrefix; private: Context &ctx_; - int next_ident_id_; - const std::string kUserIdentPrefix = "u_"; - const std::string kAnonIdentPrefix = "a_"; + // Set of identifiers from queries. + std::unordered_set users_identifiers; + // Identifiers that user didn't name. + std::vector anonymous_identifiers; AstTreeStorage storage_; - Query *query_; + Query *query_ = nullptr; }; } } diff --git a/src/query/frontend/logical/operator.hpp b/src/query/frontend/logical/operator.hpp index d2679609d..04f2ec877 100644 --- a/src/query/frontend/logical/operator.hpp +++ b/src/query/frontend/logical/operator.hpp @@ -66,7 +66,7 @@ public: } private: - NodeAtom* node_atom_; + NodeAtom* node_atom_ = nullptr; }; class ScanAll : public LogicalOperator { @@ -99,7 +99,7 @@ class ScanAll : public LogicalOperator { } private: - NodeAtom *node_atom_; + NodeAtom *node_atom_ = nullptr; }; class NodeFilter : public LogicalOperator { diff --git a/tests/unit/cypher_main_visitor.cpp b/tests/unit/cypher_main_visitor.cpp index 955ad7bc4..65ae3463e 100644 --- a/tests/unit/cypher_main_visitor.cpp +++ b/tests/unit/cypher_main_visitor.cpp @@ -5,182 +5,116 @@ #include #include "antlr4-runtime.h" +#include "dbms/dbms.hpp" #include "gmock/gmock.h" #include "query/context.hpp" #include "query/frontend/ast/cypher_main_visitor.hpp" #include "query/frontend/opencypher/parser.hpp" #include "gtest/gtest.h" -using namespace ::testing; +namespace { + +using namespace query; +using namespace query::frontend; +using testing::UnorderedElementsAre; + +class AstGenerator { +public: + AstGenerator(const std::string &query) + : dbms_(), db_accessor_(dbms_.active()), + context_(Config{}, *db_accessor_), query_string_(query), parser_(query), + visitor_(context_), query_([&]() { + visitor_.visit(parser_.tree()); + return visitor_.query(); + }()) {} + + Dbms dbms_; + std::unique_ptr db_accessor_; + Context context_; + std::string query_string_; + ::frontend::opencypher::Parser parser_; + CypherMainVisitor visitor_; + Query *query_; +}; + +TEST(CompilerStructuresTest, SyntaxException) { + ASSERT_THROW(AstGenerator("CREATE ()-[*1...2]-()"), std::exception); +} + +TEST(CompilerStructuresTest, NodePattern) { + AstGenerator ast_generator("MATCH (:label1:label2:label3)"); + auto *query = ast_generator.query_; + ASSERT_EQ(query->clauses_.size(), 1U); + auto *match = dynamic_cast(query->clauses_[0]); + ASSERT_TRUE(match); + ASSERT_EQ(match->patterns_.size(), 1U); + ASSERT_TRUE(match->patterns_[0]); + ASSERT_EQ(match->patterns_[0]->atoms_.size(), 1U); + auto node = dynamic_cast(match->patterns_[0]->atoms_[0]); + ASSERT_TRUE(node); + ASSERT_TRUE(node->identifier_); + ASSERT_EQ(node->identifier_->name_, + CypherMainVisitor::kAnonPrefix + std::to_string(1)); + ASSERT_THAT(node->labels_, UnorderedElementsAre( + ast_generator.db_accessor_->label("label1"), + ast_generator.db_accessor_->label("label2"), + ast_generator.db_accessor_->label("label3"))); + // TODO: add test for properties. +} + +TEST(CompilerStructuresTest, NodePatternIdentifier) { + AstGenerator ast_generator("MATCH (var)"); + auto *query = ast_generator.query_; + auto *match = dynamic_cast(query->clauses_[0]); + auto node = dynamic_cast(match->patterns_[0]->atoms_[0]); + ASSERT_TRUE(node->identifier_); + ASSERT_EQ(node->identifier_->name_, "var"); + ASSERT_THAT(node->labels_, UnorderedElementsAre()); + // TODO: add test for properties. +} + +TEST(CompilerStructuresTest, RelationshipPatternNoDetails) { + AstGenerator ast_generator("MATCH ()--()"); + auto *query = ast_generator.query_; + auto *match = dynamic_cast(query->clauses_[0]); + ASSERT_EQ(match->patterns_.size(), 1U); + ASSERT_TRUE(match->patterns_[0]); + ASSERT_EQ(match->patterns_[0]->atoms_.size(), 3U); + auto *node1 = dynamic_cast(match->patterns_[0]->atoms_[0]); + ASSERT_TRUE(node1); + auto *edge = dynamic_cast(match->patterns_[0]->atoms_[1]); + ASSERT_TRUE(edge); + auto *node2 = dynamic_cast(match->patterns_[0]->atoms_[2]); + ASSERT_TRUE(node2); + ASSERT_EQ(edge->direction_, EdgeAtom::Direction::BOTH); + ASSERT_TRUE(edge->identifier_); + ASSERT_THAT(edge->identifier_->name_, + CypherMainVisitor::kAnonPrefix + std::to_string(2)); +} + +TEST(CompilerStructuresTest, RelationshipPatternDetails) { + AstGenerator ast_generator("MATCH ()<-[:type1|type2]-()"); + auto *query = ast_generator.query_; + auto *match = dynamic_cast(query->clauses_[0]); + auto *edge = dynamic_cast(match->patterns_[0]->atoms_[1]); + ASSERT_EQ(edge->direction_, EdgeAtom::Direction::LEFT); + ASSERT_THAT( + edge->types_, + UnorderedElementsAre(ast_generator.db_accessor_->edge_type("type1"), + ast_generator.db_accessor_->edge_type("type2"))); + // TODO: test properties +} + +TEST(CompilerStructuresTest, RelationshipPatternVariable) { + AstGenerator ast_generator("MATCH ()-[var]->()"); + auto *query = ast_generator.query_; + auto *match = dynamic_cast(query->clauses_[0]); + auto *edge = dynamic_cast(match->patterns_[0]->atoms_[1]); + ASSERT_EQ(edge->direction_, EdgeAtom::Direction::RIGHT); + ASSERT_TRUE(edge->identifier_); + ASSERT_THAT(edge->identifier_->name_, "var"); +} -// namespace { -// -// using query::Context; -// using namespace query::frontend; -// -// class ParserTables { -// template -// auto FilterAnies(std::unordered_map map) { -// std::unordered_map filtered; -// for (auto x : map) { -// if (x.second.is()) { -// filtered[x.first] = x.second.as(); -// } -// } -// return filtered; -// } -// -// public: -// ParserTables(const std::string &query) { -// frontend::opencypher::Parser parser(query); -// auto *tree = parser.tree(); -// CypherMainVisitor visitor; -// visitor.visit(tree); -// identifiers_map_ = visitor.ids_map().back(); -// symbol_table_ = visitor.symbol_table(); -// pattern_parts_ = FilterAnies(symbol_table_); -// nodes_ = FilterAnies(symbol_table_); -// relationships_ = FilterAnies(symbol_table_); -// } -// -// std::unordered_map identifiers_map_; -// std::unordered_map symbol_table_; -// std::unordered_map pattern_parts_; -// std::unordered_map nodes_; -// std::unordered_map relationships_; -// }; -// -// // TODO: Once expression evaluation is implemented, we should also test if -// // property values are equal. -// void CompareNodes(std::pair node_entry, -// std::vector labels, -// std::vector property_keys) { -// auto node = node_entry.second; -// ASSERT_EQ(node_entry.first, node.output_id); -// ASSERT_THAT(node.labels, -// UnorderedElementsAreArray(labels.begin(), labels.end())); -// std::vector node_property_keys; -// for (auto x : node.properties) { -// node_property_keys.push_back(x.first); -// } -// ASSERT_THAT( -// node_property_keys, -// UnorderedElementsAreArray(property_keys.begin(), property_keys.end())); -// } -// -// // If has_range is false, lower and upper bound values are ignored. -// // TODO: Once expression evaluation is implemented, we should also test if -// // property values are equal. -// void CompareRelationships( -// std::pair relationship_entry, -// Relationship::Direction direction, std::vector types, -// std::vector property_keys, bool has_range, -// int64_t lower_bound = 1LL, int64_t upper_bound = LLONG_MAX) { -// auto relationship = relationship_entry.second; -// ASSERT_EQ(relationship_entry.first, relationship.output_id); -// ASSERT_EQ(relationship.direction, direction); -// ASSERT_THAT(relationship.types, -// UnorderedElementsAreArray(types.begin(), types.end())); -// std::vector relationship_property_keys; -// for (auto x : relationship.properties) { -// relationship_property_keys.push_back(x.first); -// } -// ASSERT_THAT( -// relationship_property_keys, -// UnorderedElementsAreArray(property_keys.begin(), property_keys.end())); -// ASSERT_EQ(relationship.has_range, has_range); -// if (!has_range) -// return; -// ASSERT_EQ(relationship.lower_bound, lower_bound); -// ASSERT_EQ(relationship.upper_bound, upper_bound); -// } -// -// // SyntaxException on incorrect syntax. -// TEST(CompilerStructuresTest, SyntaxException) { -// ASSERT_THROW(ParserTables("CREATE ()-[*1...2]-()"), -// frontend::opencypher::SyntaxException); -// } -// -// // Empty node. -// TEST(CompilerStructuresTest, NodePatternEmpty) { -// ParserTables parser("CREATE ()"); -// ASSERT_EQ(parser.identifiers_map_.size(), 0U); -// ASSERT_EQ(parser.nodes_.size(), 1U); -// CompareNodes(*parser.nodes_.begin(), {}, {}); -// } -// -// // Node with variable. -// TEST(CompilerStructuresTest, NodePatternVariable) { -// ParserTables parser("CREATE (var)"); -// ASSERT_EQ(parser.identifiers_map_.size(), 1U); -// ASSERT_NE(parser.identifiers_map_.find("var"), parser.identifiers_map_.end()); -// ASSERT_EQ(parser.nodes_.size(), 1U); -// auto output_identifier = parser.identifiers_map_["var"]; -// ASSERT_NE(parser.nodes_.find(output_identifier), parser.nodes_.end()); -// CompareNodes(*parser.nodes_.begin(), {}, {}); -// } -// -// // Node with labels. -// TEST(CompilerStructuresTest, NodePatternLabels) { -// ParserTables parser("CREATE (:label1:label2:label3)"); -// ASSERT_EQ(parser.identifiers_map_.size(), 0U); -// ASSERT_EQ(parser.nodes_.size(), 1U); -// CompareNodes(*parser.nodes_.begin(), {"label1", "label2", "label3"}, {}); -// } -// -// // Node with properties. -// TEST(CompilerStructuresTest, NodePatternProperties) { -// ParserTables parser("CREATE ({age: 5, name: \"John\", surname: \"Smith\"})"); -// ASSERT_EQ(parser.identifiers_map_.size(), 0U); -// ASSERT_EQ(parser.nodes_.size(), 1U); -// CompareNodes(*parser.nodes_.begin(), {}, {"age", "name", "surname"}); -// } -// -// // Relationship without relationship details. -// TEST(CompilerStructuresTest, RelationshipPatternNoDetails) { -// ParserTables parser("CREATE ()--()"); -// ASSERT_EQ(parser.identifiers_map_.size(), 0U); -// ASSERT_EQ(parser.relationships_.size(), 1U); -// CompareRelationships(*parser.relationships_.begin(), -// Relationship::Direction::BOTH, {}, {}, false); -// } -// -// // Relationship with empty relationship details. -// TEST(CompilerStructuresTest, RelationshipPatternEmptyDetails) { -// ParserTables parser("CREATE ()-[]-()"); -// ASSERT_EQ(parser.identifiers_map_.size(), 0U); -// ASSERT_EQ(parser.relationships_.size(), 1U); -// CompareRelationships(*parser.relationships_.begin(), -// Relationship::Direction::BOTH, {}, {}, false); -// } -// -// // Relationship with left direction. -// TEST(CompilerStructuresTest, RelationshipPatternLeftDirection) { -// ParserTables parser("CREATE ()<--()"); -// ASSERT_EQ(parser.identifiers_map_.size(), 0U); -// ASSERT_EQ(parser.relationships_.size(), 1U); -// CompareRelationships(*parser.relationships_.begin(), -// Relationship::Direction::LEFT, {}, {}, false); -// } -// -// // Relationship with right direction. -// TEST(CompilerStructuresTest, RelationshipPatternRightDirection) { -// ParserTables parser("CREATE ()-[]->()"); -// ASSERT_EQ(parser.identifiers_map_.size(), 0U); -// ASSERT_EQ(parser.relationships_.size(), 1U); -// CompareRelationships(*parser.relationships_.begin(), -// Relationship::Direction::RIGHT, {}, {}, false); -// } -// -// // Relationship with both directions. -// TEST(CompilerStructuresTest, RelationshipPatternBothDirection) { -// ParserTables parser("CREATE ()<-[]->()"); -// ASSERT_EQ(parser.identifiers_map_.size(), 0U); -// ASSERT_EQ(parser.relationships_.size(), 1U); -// CompareRelationships(*parser.relationships_.begin(), -// Relationship::Direction::BOTH, {}, {}, false); -// } -// // // Relationship with unbounded variable range. // TEST(CompilerStructuresTest, RelationshipPatternUnbounded) { // ParserTables parser("CREATE ()-[*]-()"); @@ -190,7 +124,7 @@ using namespace ::testing; // Relationship::Direction::BOTH, {}, {}, true, 1, // LLONG_MAX); // } -// +// // // Relationship with lower bounded variable range. // TEST(CompilerStructuresTest, RelationshipPatternLowerBounded) { // ParserTables parser("CREATE ()-[*5..]-()"); @@ -200,7 +134,7 @@ using namespace ::testing; // Relationship::Direction::BOTH, {}, {}, true, 5, // LLONG_MAX); // } -// +// // // Relationship with upper bounded variable range. // TEST(CompilerStructuresTest, RelationshipPatternUpperBounded) { // ParserTables parser("CREATE ()-[*..10]-()"); @@ -209,7 +143,7 @@ using namespace ::testing; // CompareRelationships(*parser.relationships_.begin(), // Relationship::Direction::BOTH, {}, {}, true, 1, 10); // } -// +// // // Relationship with lower and upper bounded variable range. // TEST(CompilerStructuresTest, RelationshipPatternLowerUpperBounded) { // ParserTables parser("CREATE ()-[*5..10]-()"); @@ -218,7 +152,7 @@ using namespace ::testing; // CompareRelationships(*parser.relationships_.begin(), // Relationship::Direction::BOTH, {}, {}, true, 5, 10); // } -// +// // // Relationship with fixed number of edges. // TEST(CompilerStructuresTest, RelationshipPatternFixedRange) { // ParserTables parser("CREATE ()-[*10]-()"); @@ -227,48 +161,15 @@ using namespace ::testing; // CompareRelationships(*parser.relationships_.begin(), // Relationship::Direction::BOTH, {}, {}, true, 10, 10); // } -// +// // // Relationship with invalid bound (larger than long long). // TEST(CompilerStructuresTest, RelationshipPatternInvalidBound) { // ASSERT_THROW( // ParserTables parser("CREATE ()-[*100000000000000000000000000]-()"), // SemanticException); // } -// -// // Relationship with variable -// TEST(CompilerStructuresTest, RelationshipPatternVariable) { -// ParserTables parser("CREATE ()-[var]-()"); -// ASSERT_EQ(parser.identifiers_map_.size(), 1U); -// ASSERT_NE(parser.identifiers_map_.find("var"), parser.identifiers_map_.end()); -// ASSERT_EQ(parser.relationships_.size(), 1U); -// auto output_identifier = parser.identifiers_map_["var"]; -// ASSERT_NE(parser.relationships_.find(output_identifier), -// parser.relationships_.end()); -// CompareRelationships(*parser.relationships_.begin(), -// Relationship::Direction::BOTH, {}, {}, false); -// } -// -// // Relationship with labels. -// TEST(CompilerStructuresTest, RelationshipPatternLabels) { -// ParserTables parser("CREATE ()-[:label1|label2|:label3]-()"); -// ASSERT_EQ(parser.identifiers_map_.size(), 0U); -// ASSERT_EQ(parser.relationships_.size(), 1U); -// CompareRelationships(*parser.relationships_.begin(), -// Relationship::Direction::BOTH, -// {"label1", "label2", "label3"}, {}, false); -// } -// -// // Relationship with properties. -// TEST(CompilerStructuresTest, RelationshipPatternProperties) { -// ParserTables parser( -// "CREATE ()-[{age: 5, name: \"John\", surname: \"Smith\"}]-()"); -// ASSERT_EQ(parser.identifiers_map_.size(), 0U); -// ASSERT_EQ(parser.relationships_.size(), 1U); -// CompareRelationships(*parser.relationships_.begin(), -// Relationship::Direction::BOTH, {}, -// {"age", "name", "surname"}, false); -// } -// +// +// // // PatternPart. // TEST(CompilerStructuresTest, PatternPart) { // ParserTables parser("CREATE ()--()"); @@ -279,7 +180,7 @@ using namespace ::testing; // ASSERT_EQ(parser.pattern_parts_.begin()->second.nodes.size(), 2U); // ASSERT_EQ(parser.pattern_parts_.begin()->second.relationships.size(), 1U); // } -// +// // // PatternPart in braces. // TEST(CompilerStructuresTest, PatternPartBraces) { // ParserTables parser("CREATE ((()--()))"); @@ -290,7 +191,7 @@ using namespace ::testing; // ASSERT_EQ(parser.pattern_parts_.begin()->second.nodes.size(), 2U); // ASSERT_EQ(parser.pattern_parts_.begin()->second.relationships.size(), 1U); // } -// +// // // PatternPart with variable. // TEST(CompilerStructuresTest, PatternPartVariable) { // ParserTables parser("CREATE var=()--()"); @@ -300,63 +201,16 @@ using namespace ::testing; // ASSERT_EQ(parser.nodes_.size(), 2U); // ASSERT_EQ(parser.pattern_parts_.begin()->second.nodes.size(), 2U); // ASSERT_EQ(parser.pattern_parts_.begin()->second.relationships.size(), 1U); -// ASSERT_NE(parser.identifiers_map_.find("var"), parser.identifiers_map_.end()); +// ASSERT_NE(parser.identifiers_map_.find("var"), +// parser.identifiers_map_.end()); // auto output_identifier = parser.identifiers_map_["var"]; // ASSERT_NE(parser.pattern_parts_.find(output_identifier), // parser.pattern_parts_.end()); // } -// +// // // Multiple nodes with same variable and properties. // TEST(CompilerStructuresTest, MultipleNodesWithVariableAndProperties) { // ASSERT_THROW(ParserTables parser("CREATE (a {b: 5})-[]-(a {c: 5})"), // SemanticException); // } -// -// // Multiple nodes with same variable name. -// TEST(CompilerStructuresTest, MultipleNodesWithVariable) { -// ParserTables parser("CREATE (a {b: 5, c: 5})-[]-(a)"); -// ASSERT_EQ(parser.identifiers_map_.size(), 1U); -// ASSERT_EQ(parser.pattern_parts_.size(), 1U); -// ASSERT_EQ(parser.relationships_.size(), 1U); -// ASSERT_EQ(parser.nodes_.size(), 1U); -// auto pattern_part = parser.pattern_parts_.begin()->second; -// ASSERT_EQ(pattern_part.nodes.size(), 2U); -// ASSERT_EQ(pattern_part.relationships.size(), 1U); -// ASSERT_EQ(pattern_part.nodes[0], pattern_part.nodes[1]); -// } -// -// // Multiple relationships with same variable name and properties. -// TEST(CompilerStructuresTest, MultipleRelationshipsWithVariableAndProperties) { -// ASSERT_THROW(ParserTables parser("CREATE ()-[e {a: 5}]-()-[e {c: 5}]-()"), -// SemanticException); -// } -// -// // Multiple relationships with same variable name. -// TEST(CompilerStructuresTest, MultipleRelationshipsWithVariable) { -// ParserTables parser("CREATE ()-[a {a: 5}]-()-[a]-()"); -// ASSERT_EQ(parser.identifiers_map_.size(), 1U); -// ASSERT_EQ(parser.pattern_parts_.size(), 1U); -// ASSERT_EQ(parser.relationships_.size(), 1U); -// ASSERT_EQ(parser.nodes_.size(), 3U); -// auto pattern_part = parser.pattern_parts_.begin()->second; -// ASSERT_EQ(pattern_part.nodes.size(), 3U); -// ASSERT_EQ(pattern_part.relationships.size(), 2U); -// ASSERT_NE(pattern_part.nodes[0], pattern_part.nodes[1]); -// ASSERT_NE(pattern_part.nodes[1], pattern_part.nodes[2]); -// ASSERT_NE(pattern_part.nodes[0], pattern_part.nodes[2]); -// ASSERT_EQ(pattern_part.relationships[0], pattern_part.relationships[1]); -// } -// -// // Different structures (nodes, realtionships, patterns) with same variable -// // name. -// TEST(CompilerStructuresTest, DifferentTypesWithVariable) { -// ASSERT_THROW(ParserTables parser("CREATE a=(a)"), SemanticException); -// ASSERT_THROW(ParserTables parser("CREATE (a)-[a]-()"), SemanticException); -// ASSERT_THROW(ParserTables parser("CREATE a=()-[a]-()"), SemanticException); -// } -// } - -int main(int argc, char **argv) { - InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); }