From 596b015e990cc86883d25956c84a4ba4171cd1da Mon Sep 17 00:00:00 2001 From: Teon Banek Date: Wed, 12 Apr 2017 16:08:01 +0200 Subject: [PATCH] Correctly check variables inside property maps Reviewers: florijan, mislav.bradac Reviewed By: mislav.bradac Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D271 --- .../frontend/semantic/symbol_generator.cpp | 13 ++++-------- tests/unit/query_semantic.cpp | 21 +++++++++++++++++++ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/query/frontend/semantic/symbol_generator.cpp b/src/query/frontend/semantic/symbol_generator.cpp index 1ad6bc9e1..a9898dcfc 100644 --- a/src/query/frontend/semantic/symbol_generator.cpp +++ b/src/query/frontend/semantic/symbol_generator.cpp @@ -73,12 +73,10 @@ void SymbolGenerator::PostVisit(With &with) { void SymbolGenerator::Visit(Identifier &ident) { Symbol symbol; - if (scope_.in_pattern) { + if (scope_.in_pattern && !scope_.in_property_map) { // Patterns can bind new symbols or reference already bound. But there // are the following special cases: - // 1) Expressions in property maps `{prop_name: expr}` can only reference - // bound variables. - // 2) Patterns used to create nodes and edges cannot redeclare already + // 1) Patterns used to create nodes and edges cannot redeclare already // established bindings. Declaration only happens in single node // patterns and in edge patterns. OpenCypher example, // `MATCH (n) CREATE (n)` should throw an error that `n` is already @@ -87,12 +85,9 @@ void SymbolGenerator::Visit(Identifier &ident) { // Additionally, we will support edge referencing in pattern: // `MATCH (n) - [r] -> (n) - [r] -> (n) RETURN r`, which would // usually raise redeclaration of `r`. - if (scope_.in_property_map && !HasSymbol(ident.name_)) { - // Case 1) - throw UnboundVariableError(ident.name_); - } else if ((scope_.in_create_node || scope_.in_create_edge) && + if ((scope_.in_create_node || scope_.in_create_edge) && HasSymbol(ident.name_)) { - // Case 2) + // Case 1) throw RedeclareVariableError(ident.name_); } auto type = Symbol::Type::Vertex; diff --git a/tests/unit/query_semantic.cpp b/tests/unit/query_semantic.cpp index d26f728c7..287f5bfd0 100644 --- a/tests/unit/query_semantic.cpp +++ b/tests/unit/query_semantic.cpp @@ -447,4 +447,25 @@ TEST(TestSymbolGenerator, NestedAggregation) { EXPECT_THROW(query->Accept(symbol_generator), SemanticException); } +TEST(TestSymbolGenerator, MatchPropCreateNodeProp) { + // Test MATCH (n) CREATE (m {prop: n.prop}) + Dbms dbms; + auto dba = dbms.active(); + auto prop = dba->property("prop"); + AstTreeStorage storage; + auto node_n = NODE("n"); + auto node_m = NODE("m"); + auto n_prop = PROPERTY_LOOKUP("n", prop); + node_m->properties_[prop] = n_prop; + auto query = QUERY(MATCH(PATTERN(node_n)), CREATE(PATTERN(node_m))); + SymbolTable symbol_table; + SymbolGenerator symbol_generator(symbol_table); + query->Accept(symbol_generator); + EXPECT_EQ(symbol_table.max_position(), 2); + auto n = symbol_table.at(*node_n->identifier_); + EXPECT_EQ(n, symbol_table.at(*n_prop->expression_)); + auto m = symbol_table.at(*node_m->identifier_); + EXPECT_NE(n, m); +} + }