Correctly check variables inside property maps

Reviewers: florijan, mislav.bradac

Reviewed By: mislav.bradac

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D271
This commit is contained in:
Teon Banek 2017-04-12 16:08:01 +02:00
parent 55ef48c78e
commit 596b015e99
2 changed files with 25 additions and 9 deletions

View File

@ -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;

View File

@ -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);
}
}