81289d0663
Reviewers: buda Reviewed By: buda Subscribers: matej.gradicek Differential Revision: https://phabricator.memgraph.io/D122
599 lines
14 KiB
Gherkin
599 lines
14 KiB
Gherkin
#
|
|
# 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 |
|