# # Copyright 2017 "Neo Technology", # Network Engine for Objects in Lund AB (http://neotechnology.com) # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Feature: MergeRelationshipAcceptance Scenario: Creating a relationship Given an empty graph And having executed: """ CREATE (:A), (:B) """ When executing query: """ MATCH (a:A), (b:B) MERGE (a)-[r:TYPE]->(b) RETURN count(*) """ Then the result should be: | count(*) | | 1 | And the side effects should be: | +relationships | 1 | Scenario: Matching a relationship Given an empty graph And having executed: """ CREATE (a:A), (b:B) CREATE (a)-[:TYPE]->(b) """ When executing query: """ MATCH (a:A), (b:B) MERGE (a)-[r:TYPE]->(b) RETURN count(r) """ Then the result should be: | count(r) | | 1 | And no side effects Scenario: Matching two relationships Given an empty graph And having executed: """ CREATE (a:A), (b:B) CREATE (a)-[:TYPE]->(b) CREATE (a)-[:TYPE]->(b) """ When executing query: """ MATCH (a:A), (b:B) MERGE (a)-[r:TYPE]->(b) RETURN count(r) """ Then the result should be: | count(r) | | 2 | And no side effects Scenario: Filtering relationships Given an empty graph And having executed: """ CREATE (a:A), (b:B) CREATE (a)-[:TYPE {name: 'r1'}]->(b) CREATE (a)-[:TYPE {name: 'r2'}]->(b) """ When executing query: """ MATCH (a:A), (b:B) MERGE (a)-[r:TYPE {name: 'r2'}]->(b) RETURN count(r) """ Then the result should be: | count(r) | | 1 | And no side effects Scenario: Creating relationship when all matches filtered out Given an empty graph And having executed: """ CREATE (a:A), (b:B) CREATE (a)-[:TYPE {name: 'r1'}]->(b) """ When executing query: """ MATCH (a:A), (b:B) MERGE (a)-[r:TYPE {name: 'r2'}]->(b) RETURN count(r) """ Then the result should be: | count(r) | | 1 | And the side effects should be: | +relationships | 1 | | +properties | 1 | Scenario: Matching incoming relationship Given an empty graph And having executed: """ CREATE (a:A), (b:B) CREATE (b)-[:TYPE]->(a) CREATE (a)-[:TYPE]->(b) """ When executing query: """ MATCH (a:A), (b:B) MERGE (a)<-[r:TYPE]-(b) RETURN count(r) """ Then the result should be: | count(r) | | 1 | And no side effects Scenario: Creating relationship with property Given an empty graph And having executed: """ CREATE (a:A), (b:B) """ When executing query: """ MATCH (a:A), (b:B) MERGE (a)-[r:TYPE {name: 'Lola'}]->(b) RETURN count(r) """ Then the result should be: | count(r) | | 1 | And the side effects should be: | +relationships | 1 | | +properties | 1 | Scenario: Using ON CREATE on a node Given an empty graph And having executed: """ CREATE (:A), (:B) """ When executing query: """ MATCH (a:A), (b:B) MERGE (a)-[:KNOWS]->(b) ON CREATE SET b.created = 1 """ Then the result should be empty And the side effects should be: | +relationships | 1 | | +properties | 1 | Scenario: Using ON CREATE on a relationship Given an empty graph And having executed: """ CREATE (:A), (:B) """ When executing query: """ MATCH (a:A), (b:B) MERGE (a)-[r:TYPE]->(b) ON CREATE SET r.name = 'Lola' RETURN count(r) """ Then the result should be: | count(r) | | 1 | And the side effects should be: | +relationships | 1 | | +properties | 1 | Scenario: Using ON MATCH on created node Given an empty graph And having executed: """ CREATE (:A), (:B) """ When executing query: """ MATCH (a:A), (b:B) MERGE (a)-[:KNOWS]->(b) ON MATCH SET b.created = 1 """ Then the result should be empty And the side effects should be: | +relationships | 1 | Scenario: Using ON MATCH on created relationship Given an empty graph And having executed: """ CREATE (:A), (:B) """ When executing query: """ MATCH (a:A), (b:B) MERGE (a)-[r:KNOWS]->(b) ON MATCH SET r.created = 1 """ Then the result should be empty And the side effects should be: | +relationships | 1 | Scenario: Using ON MATCH on a relationship Given an empty graph And having executed: """ CREATE (a:A), (b:B) CREATE (a)-[:TYPE]->(b) """ When executing query: """ MATCH (a:A), (b:B) MERGE (a)-[r:TYPE]->(b) ON MATCH SET r.name = 'Lola' RETURN count(r) """ Then the result should be: | count(r) | | 1 | And the side effects should be: | +properties | 1 | Scenario: Using ON CREATE and ON MATCH Given an empty graph And having executed: """ CREATE (a:A {id: 1}), (b:B {id: 2}) CREATE (a)-[:TYPE]->(b) CREATE (:A {id: 3}), (:B {id: 4}) """ When executing query: """ MATCH (a:A), (b:B) MERGE (a)-[r:TYPE]->(b) ON CREATE SET r.name = 'Lola' ON MATCH SET r.name = 'RUN' RETURN count(r) """ Then the result should be: | count(r) | | 4 | And the side effects should be: | +relationships | 3 | | +properties | 4 | Scenario: Creating relationship using merged nodes Given an empty graph And having executed: """ CREATE (a:A), (b:B) """ When executing query: """ MERGE (a:A) MERGE (b:B) MERGE (a)-[:FOO]->(b) """ Then the result should be empty And the side effects should be: | +relationships | 1 | Scenario: Mixing MERGE with CREATE Given an empty graph When executing query: """ CREATE (a:A), (b:B) MERGE (a)-[:KNOWS]->(b) CREATE (b)-[:KNOWS]->(c:C) RETURN count(*) """ Then the result should be: | count(*) | | 1 | And the side effects should be: | +nodes | 3 | | +relationships | 2 | | +labels | 3 | Scenario: Introduce named paths 1 Given an empty graph When executing query: """ MERGE (a {x: 1}) MERGE (b {x: 2}) MERGE p = (a)-[:R]->(b) RETURN p """ Then the result should be: | p | | <({x: 1})-[:R]->({x: 2})> | And the side effects should be: | +nodes | 2 | | +relationships | 1 | | +properties | 2 | Scenario: Introduce named paths 2 Given an empty graph When executing query: """ MERGE p = (a {x: 1}) RETURN p """ Then the result should be: | p | | <({x: 1})> | And the side effects should be: | +nodes | 1 | | +properties | 1 | Scenario: Use outgoing direction when unspecified Given an empty graph When executing query: """ CREATE (a {id: 2}), (b {id: 1}) MERGE (a)-[r:KNOWS]-(b) RETURN startNode(r).id AS s, endNode(r).id AS e """ Then the result should be: | s | e | | 2 | 1 | And the side effects should be: | +nodes | 2 | | +relationships | 1 | | +properties | 2 | Scenario: Match outgoing relationship when direction unspecified Given an empty graph And having executed: """ CREATE (a {id: 1}), (b {id: 2}) CREATE (a)-[:KNOWS]->(b) """ When executing query: """ MATCH (a {id: 2}), (b {id: 1}) MERGE (a)-[r:KNOWS]-(b) RETURN r """ Then the result should be: | r | | [:KNOWS] | And no side effects Scenario: Match both incoming and outgoing relationships when direction unspecified Given an empty graph And having executed: """ CREATE (a {id: 2}), (b {id: 1}), (c {id: 1}), (d {id: 2}) CREATE (a)-[:KNOWS {name: 'ab'}]->(b) CREATE (c)-[:KNOWS {name: 'cd'}]->(d) """ When executing query: """ MATCH (a {id: 2})--(b {id: 1}) MERGE (a)-[r:KNOWS]-(b) RETURN r """ Then the result should be: | r | | [:KNOWS {name: 'ab'}] | | [:KNOWS {name: 'cd'}] | And no side effects Scenario: Fail when imposing new predicates on a variable that is already bound Given any graph When executing query: """ CREATE (a:Foo) MERGE (a)-[r:KNOWS]->(a:Bar) """ Then a SyntaxError should be raised at compile time: VariableAlreadyBound Scenario: Using list properties via variable Given an empty graph When executing query: """ CREATE (a:Foo), (b:Bar) WITH a, b UNWIND ['a,b', 'a,b'] AS str WITH a, b, split(str, ',') AS roles MERGE (a)-[r:FB {foobar: roles}]->(b) RETURN count(*) """ Then the result should be: | count(*) | | 2 | And the side effects should be: | +nodes | 2 | | +relationships | 1 | | +labels | 2 | | +properties | 1 | Scenario: Matching using list property Given an empty graph And having executed: """ CREATE (a:A), (b:B) CREATE (a)-[:T {prop: [42, 43]}]->(b) """ When executing query: """ MATCH (a:A), (b:B) MERGE (a)-[r:T {prop: [42, 43]}]->(b) RETURN count(*) """ Then the result should be: | count(*) | | 1 | And no side effects Scenario: Using bound variables from other updating clause Given an empty graph When executing query: """ CREATE (a), (b) MERGE (a)-[:X]->(b) RETURN count(a) """ Then the result should be: | count(a) | | 1 | And the side effects should be: | +nodes | 2 | | +relationships | 1 | Scenario: UNWIND with multiple merges Given an empty graph When executing query: """ UNWIND ['Keanu Reeves', 'Hugo Weaving', 'Carrie-Anne Moss', 'Laurence Fishburne'] AS actor MERGE (m:Movie {name: 'The Matrix'}) MERGE (p:Person {name: actor}) MERGE (p)-[:ACTED_IN]->(m) """ Then the result should be empty And the side effects should be: | +nodes | 5 | | +relationships | 4 | | +labels | 5 | | +properties | 5 | Scenario: Do not match on deleted entities Given an empty graph And having executed: """ CREATE (a:A) CREATE (b1:B {value: 0}), (b2:B {value: 1}) CREATE (c1:C), (c2:C) CREATE (a)-[:REL]->(b1), (a)-[:REL]->(b2), (b1)-[:REL]->(c1), (b2)-[:REL]->(c2) """ When executing query: """ MATCH (a:A)-[ab]->(b:B)-[bc]->(c:C) DELETE ab, bc, b, c MERGE (newB:B {value: 1}) MERGE (a)-[:REL]->(newB) MERGE (newC:C) MERGE (newB)-[:REL]->(newC) """ Then the result should be empty And the side effects should be: | +nodes | 2 | | -nodes | 4 | | +relationships | 2 | | -relationships | 4 | | +labels | 2 | | +properties | 1 | Scenario: Do not match on deleted relationships Given an empty graph And having executed: """ CREATE (a:A), (b:B) CREATE (a)-[:T {name: 'rel1'}]->(b), (a)-[:T {name: 'rel2'}]->(b) """ When executing query: """ MATCH (a)-[t:T]->(b) DELETE t MERGE (a)-[t2:T {name: 'rel3'}]->(b) RETURN t2.name """ Then the result should be: | t2.name | | 'rel3' | | 'rel3' | And the side effects should be: | +relationships | 1 | | -relationships | 2 | | +properties | 1 | Scenario: Aliasing of existing nodes 1 Given an empty graph And having executed: """ CREATE ({id: 0}) """ When executing query: """ MATCH (n) MATCH (m) WITH n AS a, m AS b MERGE (a)-[r:T]->(b) RETURN a.id AS a, b.id AS b """ Then the result should be: | a | b | | 0 | 0 | And the side effects should be: | +relationships | 1 | Scenario: Aliasing of existing nodes 2 Given an empty graph And having executed: """ CREATE ({id: 0}) """ When executing query: """ MATCH (n) WITH n AS a, n AS b MERGE (a)-[r:T]->(b) RETURN a.id AS a """ Then the result should be: | a | | 0 | And the side effects should be: | +relationships | 1 | Scenario: Double aliasing of existing nodes 1 Given an empty graph And having executed: """ CREATE ({id: 0}) """ When executing query: """ MATCH (n) MATCH (m) WITH n AS a, m AS b MERGE (a)-[:T]->(b) WITH a AS x, b AS y MERGE (a) MERGE (b) MERGE (a)-[:T]->(b) RETURN x.id AS x, y.id AS y """ Then the result should be: | x | y | | 0 | 0 | And the side effects should be: | +relationships | 1 | Scenario: Double aliasing of existing nodes 2 Given an empty graph And having executed: """ CREATE ({id: 0}) """ When executing query: """ MATCH (n) WITH n AS a MERGE (c) MERGE (a)-[:T]->(c) WITH a AS x MERGE (c) MERGE (x)-[:T]->(c) RETURN x.id AS x """ Then the result should be: | x | | 0 | And the side effects should be: | +relationships | 1 |