# # 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: MatchAcceptance Scenario: Path query should return results in written order Given an empty graph And having executed: """ CREATE (:Label1)<-[:TYPE]-(:Label2) """ When executing query: """ MATCH p = (a:Label1)<--(:Label2) RETURN p """ Then the result should be: | p | | <(:Label1)<-[:TYPE]-(:Label2)> | And no side effects Scenario: Longer path query should return results in written order Given an empty graph And having executed: """ CREATE (:Label1)<-[:T1]-(:Label2)-[:T2]->(:Label3) """ When executing query: """ MATCH p = (a:Label1)<--(:Label2)--() RETURN p """ Then the result should be: | p | | <(:Label1)<-[:T1]-(:Label2)-[:T2]->(:Label3)> | And no side effects Scenario: Use multiple MATCH clauses to do a Cartesian product Given an empty graph And having executed: """ CREATE ({value: 1}), ({value: 2}), ({value: 3}) """ When executing query: """ MATCH (n), (m) RETURN n.value AS n, m.value AS m """ Then the result should be: | n | m | | 1 | 1 | | 1 | 2 | | 1 | 3 | | 2 | 1 | | 2 | 2 | | 2 | 3 | | 3 | 3 | | 3 | 1 | | 3 | 2 | And no side effects Scenario: Use params in pattern matching predicates Given an empty graph And having executed: """ CREATE (:A)-[:T {foo: 'bar'}]->(:B {name: 'me'}) """ And parameters are: | param | 'bar' | When executing query: """ MATCH (a)-[r]->(b) WHERE r.foo = $param RETURN b """ Then the result should be: | b | | (:B {name: 'me'}) | And no side effects Scenario: Filter out based on node prop name Given an empty graph And having executed: """ CREATE ({name: 'Someone'})<-[:X]-()-[:X]->({name: 'Andres'}) """ When executing query: """ MATCH ()-[rel:X]-(a) WHERE a.name = 'Andres' RETURN a """ Then the result should be: | a | | ({name: 'Andres'}) | And no side effects Scenario: Honour the column name for RETURN items Given an empty graph And having executed: """ CREATE ({name: 'Someone'}) """ When executing query: """ MATCH (a) WITH a.name AS a RETURN a """ Then the result should be: | a | | 'Someone' | And no side effects Scenario: Filter based on rel prop name Given an empty graph And having executed: """ CREATE (:A)<-[:KNOWS {name: 'monkey'}]-()-[:KNOWS {name: 'woot'}]->(:B) """ When executing query: """ MATCH (node)-[r:KNOWS]->(a) WHERE r.name = 'monkey' RETURN a """ Then the result should be: | a | | (:A) | And no side effects Scenario: Cope with shadowed variables Given an empty graph And having executed: """ CREATE ({value: 1, name: 'King Kong'}), ({value: 2, name: 'Ann Darrow'}) """ When executing query: """ MATCH (n) WITH n.name AS n RETURN n """ Then the result should be: | n | | 'Ann Darrow' | | 'King Kong' | And no side effects Scenario: Get neighbours Given an empty graph And having executed: """ CREATE (a:A {value: 1})-[:KNOWS]->(b:B {value: 2}) """ When executing query: """ MATCH (n1)-[rel:KNOWS]->(n2) RETURN n1, n2 """ Then the result should be: | n1 | n2 | | (:A {value: 1}) | (:B {value: 2}) | And no side effects Scenario: Get two related nodes Given an empty graph And having executed: """ CREATE (a:A {value: 1}), (a)-[:KNOWS]->(b:B {value: 2}), (a)-[:KNOWS]->(c:C {value: 3}) """ When executing query: """ MATCH ()-[rel:KNOWS]->(x) RETURN x """ Then the result should be: | x | | (:B {value: 2}) | | (:C {value: 3}) | And no side effects Scenario: Get related to related to Given an empty graph And having executed: """ CREATE (a:A {value: 1})-[:KNOWS]->(b:B {value: 2})-[:FRIEND]->(c:C {value: 3}) """ When executing query: """ MATCH (n)-->(a)-->(b) RETURN b """ Then the result should be: | b | | (:C {value: 3}) | And no side effects Scenario: Handle comparison between node properties Given an empty graph And having executed: """ CREATE (a:A {animal: 'monkey'}), (b:B {animal: 'cow'}), (c:C {animal: 'monkey'}), (d:D {animal: 'cow'}), (a)-[:KNOWS]->(b), (a)-[:KNOWS]->(c), (d)-[:KNOWS]->(b), (d)-[:KNOWS]->(c) """ When executing query: """ MATCH (n)-[rel]->(x) WHERE n.animal = x.animal RETURN n, x """ Then the result should be: | n | x | | (:A {animal: 'monkey'}) | (:C {animal: 'monkey'}) | | (:D {animal: 'cow'}) | (:B {animal: 'cow'}) | And no side effects Scenario: Return two subgraphs with bound undirected relationship Given an empty graph And having executed: """ CREATE (a:A {value: 1})-[:REL {name: 'r'}]->(b:B {value: 2}) """ When executing query: """ MATCH (a)-[r {name: 'r'}]-(b) RETURN a, b """ Then the result should be: | a | b | | (:B {value: 2}) | (:A {value: 1}) | | (:A {value: 1}) | (:B {value: 2}) | And no side effects Scenario: Return two subgraphs with bound undirected relationship and optional relationship Given an empty graph And having executed: """ CREATE (a:A {value: 1})-[:REL {name: 'r1'}]->(b:B {value: 2})-[:REL {name: 'r2'}]->(c:C {value: 3}) """ When executing query: """ MATCH (a)-[r {name: 'r1'}]-(b) OPTIONAL MATCH (b)-[r2]-(c) WHERE r <> r2 RETURN a, b, c """ Then the result should be: | a | b | c | | (:A {value: 1}) | (:B {value: 2}) | (:C {value: 3}) | | (:B {value: 2}) | (:A {value: 1}) | null | And no side effects Scenario: Rel type function works as expected Given an empty graph And having executed: """ CREATE (a:A {name: 'A'}), (b:B {name: 'B'}), (c:C {name: 'C'}), (a)-[:KNOWS]->(b), (a)-[:HATES]->(c) """ When executing query: """ MATCH (n {name: 'A'})-[r]->(x) WHERE type(r) = 'KNOWS' RETURN x """ Then the result should be: | x | | (:B {name: 'B'}) | And no side effects Scenario: Walk alternative relationships Given an empty graph And having executed: """ CREATE (a {name: 'A'}), (b {name: 'B'}), (c {name: 'C'}), (a)-[:KNOWS]->(b), (a)-[:HATES]->(c), (a)-[:WONDERS]->(c) """ When executing query: """ MATCH (n)-[r]->(x) WHERE type(r) = 'KNOWS' OR type(r) = 'HATES' RETURN r """ Then the result should be: | r | | [:KNOWS] | | [:HATES] | And no side effects Scenario: Handle OR in the WHERE clause Given an empty graph And having executed: """ CREATE (a:A {p1: 12}), (b:B {p2: 13}), (c:C) """ When executing query: """ MATCH (n) WHERE n.p1 = 12 OR n.p2 = 13 RETURN n """ Then the result should be: | n | | (:A {p1: 12}) | | (:B {p2: 13}) | And no side effects Scenario: Return a simple path Given an empty graph And having executed: """ CREATE (a:A {name: 'A'})-[:KNOWS]->(b:B {name: 'B'}) """ When executing query: """ MATCH p = (a {name: 'A'})-->(b) RETURN p """ Then the result should be: | p | | <(:A {name: 'A'})-[:KNOWS]->(:B {name: 'B'})> | And no side effects Scenario: Return a three node path Given an empty graph And having executed: """ CREATE (a:A {name: 'A'})-[:KNOWS]->(b:B {name: 'B'})-[:KNOWS]->(c:C {name: 'C'}) """ When executing query: """ MATCH p = (a {name: 'A'})-[rel1]->(b)-[rel2]->(c) RETURN p """ Then the result should be: | p | | <(:A {name: 'A'})-[:KNOWS]->(:B {name: 'B'})-[:KNOWS]->(:C {name: 'C'})> | And no side effects Scenario: Do not return anything because path length does not match Given an empty graph And having executed: """ CREATE (a:A {name: 'A'})-[:KNOWS]->(b:B {name: 'B'}) """ When executing query: """ MATCH p = (n)-->(x) WHERE length(p) = 10 RETURN x """ Then the result should be empty And no side effects Scenario: Pass the path length test Given an empty graph And having executed: """ CREATE (a:A {name: 'A'})-[:KNOWS]->(b:B {name: 'B'}) """ When executing query: """ MATCH p = (n)-->(x) WHERE length(p) = 1 RETURN x """ Then the result should be: | x | | (:B {name: 'B'}) | And no side effects Scenario: Return relationships by fetching them from the path - starting from the end Given an empty graph And having executed: """ CREATE (a:A)-[:REL {value: 1}]->(b:B)-[:REL {value: 2}]->(e:End) """ When executing query: """ MATCH p = (a)-[:REL*2..2]->(b:End) RETURN relationships(p) """ Then the result should be: | relationships(p) | | [[:REL {value: 1}], [:REL {value: 2}]] | And no side effects Scenario: Return relationships by fetching them from the path Given an empty graph And having executed: """ CREATE (s:Start)-[:REL {value: 1}]->(b:B)-[:REL {value: 2}]->(c:C) """ When executing query: """ MATCH p = (a:Start)-[:REL*2..2]->(b) RETURN relationships(p) """ Then the result should be: | relationships(p) | | [[:REL {value: 1}], [:REL {value: 2}]] | And no side effects Scenario: Return relationships by collecting them as a list - wrong way Given an empty graph And having executed: """ CREATE (a:A)-[:REL {value: 1}]->(b:B)-[:REL {value: 2}]->(e:End) """ When executing query: """ MATCH (a)-[r:REL*2..2]->(b:End) RETURN r """ Then the result should be: | r | | [[:REL {value: 1}], [:REL {value: 2}]] | And no side effects Scenario: Return relationships by collecting them as a list - undirected Given an empty graph And having executed: """ CREATE (a:End {value: 1})-[:REL {value: 1}]->(b:B)-[:REL {value: 2}]->(c:End {value: 2}) """ When executing query: """ MATCH (a)-[r:REL*2..2]-(b:End) RETURN r """ Then the result should be: | r | | [[:REL {value:1}], [:REL {value:2}]] | | [[:REL {value:2}], [:REL {value:1}]] | And no side effects Scenario: Return relationships by collecting them as a list Given an empty graph And having executed: """ CREATE (s:Start)-[:REL {value: 1}]->(b:B)-[:REL {value: 2}]->(c:C) """ When executing query: """ MATCH (a:Start)-[r:REL*2..2]-(b) RETURN r """ Then the result should be: | r | | [[:REL {value: 1}], [:REL {value: 2}]] | And no side effects Scenario: Return a var length path Given an empty graph And having executed: """ CREATE (a:A {name: 'A'})-[:KNOWS {value: 1}]->(b:B {name: 'B'})-[:KNOWS {value: 2}]->(c:C {name: 'C'}) """ When executing query: """ MATCH p = (n {name: 'A'})-[:KNOWS*1..2]->(x) RETURN p """ Then the result should be: | p | | <(:A {name: 'A'})-[:KNOWS {value: 1}]->(:B {name: 'B'})> | | <(:A {name: 'A'})-[:KNOWS {value: 1}]->(:B {name: 'B'})-[:KNOWS {value: 2}]->(:C {name: 'C'})> | And no side effects Scenario: Return a var length path of length zero Given an empty graph And having executed: """ CREATE (a:A)-[:REL]->(b:B) """ When executing query: """ MATCH p = (a)-[*0..1]->(b) RETURN a, b, length(p) AS l """ Then the result should be: | a | b | l | | (:A) | (:A) | 0 | | (:B) | (:B) | 0 | | (:A) | (:B) | 1 | And no side effects Scenario: Return a named var length path of length zero Given an empty graph And having executed: """ CREATE (a:A {name: 'A'})-[:KNOWS]->(b:B {name: 'B'})-[:FRIEND]->(c:C {name: 'C'}) """ When executing query: """ MATCH p = (a {name: 'A'})-[:KNOWS*0..1]->(b)-[:FRIEND*0..1]->(c) RETURN p """ Then the result should be: | p | | <(:A {name: 'A'})> | | <(:A {name: 'A'})-[:KNOWS]->(:B {name: 'B'})> | | <(:A {name: 'A'})-[:KNOWS]->(:B {name: 'B'})-[:FRIEND]->(:C {name: 'C'})> | And no side effects Scenario: Accept skip zero Given any graph When executing query: """ MATCH (n) WHERE 1 = 0 RETURN n SKIP 0 """ Then the result should be empty And no side effects