364 lines
8.2 KiB
Gherkin
364 lines
8.2 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: WithAcceptance
|
||
|
|
||
|
Scenario: Passing on pattern nodes
|
||
|
Given an empty graph
|
||
|
And having executed:
|
||
|
"""
|
||
|
CREATE (:A)-[:REL]->(:B)
|
||
|
"""
|
||
|
When executing query:
|
||
|
"""
|
||
|
MATCH (a:A)
|
||
|
WITH a
|
||
|
MATCH (a)-->(b)
|
||
|
RETURN *
|
||
|
"""
|
||
|
Then the result should be:
|
||
|
| a | b |
|
||
|
| (:A) | (:B) |
|
||
|
And no side effects
|
||
|
|
||
|
Scenario: ORDER BY and LIMIT can be used
|
||
|
Given an empty graph
|
||
|
And having executed:
|
||
|
"""
|
||
|
CREATE (a:A), (), (), (),
|
||
|
(a)-[:REL]->()
|
||
|
"""
|
||
|
When executing query:
|
||
|
"""
|
||
|
MATCH (a:A)
|
||
|
WITH a
|
||
|
ORDER BY a.name
|
||
|
LIMIT 1
|
||
|
MATCH (a)-->(b)
|
||
|
RETURN a
|
||
|
"""
|
||
|
Then the result should be:
|
||
|
| a |
|
||
|
| (:A) |
|
||
|
And no side effects
|
||
|
|
||
|
Scenario: No dependencies between the query parts
|
||
|
Given an empty graph
|
||
|
And having executed:
|
||
|
"""
|
||
|
CREATE (:A), (:B)
|
||
|
"""
|
||
|
When executing query:
|
||
|
"""
|
||
|
MATCH (a)
|
||
|
WITH a
|
||
|
MATCH (b)
|
||
|
RETURN a, b
|
||
|
"""
|
||
|
Then the result should be:
|
||
|
| a | b |
|
||
|
| (:A) | (:A) |
|
||
|
| (:A) | (:B) |
|
||
|
| (:B) | (:A) |
|
||
|
| (:B) | (:B) |
|
||
|
And no side effects
|
||
|
|
||
|
Scenario: Aliasing
|
||
|
Given an empty graph
|
||
|
And having executed:
|
||
|
"""
|
||
|
CREATE (:Begin {prop: 42}),
|
||
|
(:End {prop: 42}),
|
||
|
(:End {prop: 3})
|
||
|
"""
|
||
|
When executing query:
|
||
|
"""
|
||
|
MATCH (a:Begin)
|
||
|
WITH a.prop AS property
|
||
|
MATCH (b:End)
|
||
|
WHERE property = b.prop
|
||
|
RETURN b
|
||
|
"""
|
||
|
Then the result should be:
|
||
|
| b |
|
||
|
| (:End {prop: 42}) |
|
||
|
And no side effects
|
||
|
|
||
|
Scenario: Handle dependencies across WITH
|
||
|
Given an empty graph
|
||
|
And having executed:
|
||
|
"""
|
||
|
CREATE (a:End {prop: 42, id: 0}),
|
||
|
(:End {prop: 3}),
|
||
|
(:Begin {prop: a.id})
|
||
|
"""
|
||
|
When executing query:
|
||
|
"""
|
||
|
MATCH (a:Begin)
|
||
|
WITH a.prop AS property
|
||
|
LIMIT 1
|
||
|
MATCH (b)
|
||
|
WHERE b.id = property
|
||
|
RETURN b
|
||
|
"""
|
||
|
Then the result should be:
|
||
|
| b |
|
||
|
| (:End {prop: 42, id: 0}) |
|
||
|
And no side effects
|
||
|
|
||
|
Scenario: Handle dependencies across WITH with SKIP
|
||
|
Given an empty graph
|
||
|
And having executed:
|
||
|
"""
|
||
|
CREATE (a {prop: 'A', key: 0, id: 0}),
|
||
|
({prop: 'B', key: a.id, id: 1}),
|
||
|
({prop: 'C', key: 0, id: 2})
|
||
|
"""
|
||
|
When executing query:
|
||
|
"""
|
||
|
MATCH (a)
|
||
|
WITH a.prop AS property, a.key AS idToUse
|
||
|
ORDER BY property
|
||
|
SKIP 1
|
||
|
MATCH (b)
|
||
|
WHERE b.id = idToUse
|
||
|
RETURN DISTINCT b
|
||
|
"""
|
||
|
Then the result should be:
|
||
|
| b |
|
||
|
| ({prop: 'A', key: 0, id: 0}) |
|
||
|
And no side effects
|
||
|
|
||
|
Scenario: WHERE after WITH should filter results
|
||
|
Given an empty graph
|
||
|
And having executed:
|
||
|
"""
|
||
|
CREATE ({name: 'A'}),
|
||
|
({name: 'B'}),
|
||
|
({name: 'C'})
|
||
|
"""
|
||
|
When executing query:
|
||
|
"""
|
||
|
MATCH (a)
|
||
|
WITH a
|
||
|
WHERE a.name = 'B'
|
||
|
RETURN a
|
||
|
"""
|
||
|
Then the result should be:
|
||
|
| a |
|
||
|
| ({name: 'B'}) |
|
||
|
And no side effects
|
||
|
|
||
|
Scenario: WHERE after WITH can filter on top of an aggregation
|
||
|
Given an empty graph
|
||
|
And having executed:
|
||
|
"""
|
||
|
CREATE (a {name: 'A'}),
|
||
|
(b {name: 'B'})
|
||
|
CREATE (a)-[:REL]->(),
|
||
|
(a)-[:REL]->(),
|
||
|
(a)-[:REL]->(),
|
||
|
(b)-[:REL]->()
|
||
|
"""
|
||
|
When executing query:
|
||
|
"""
|
||
|
MATCH (a)-->()
|
||
|
WITH a, count(*) AS relCount
|
||
|
WHERE relCount > 1
|
||
|
RETURN a
|
||
|
"""
|
||
|
Then the result should be:
|
||
|
| a |
|
||
|
| ({name: 'A'}) |
|
||
|
And no side effects
|
||
|
|
||
|
Scenario: ORDER BY on an aggregating key
|
||
|
Given an empty graph
|
||
|
And having executed:
|
||
|
"""
|
||
|
CREATE ({bar: 'A'}),
|
||
|
({bar: 'A'}),
|
||
|
({bar: 'B'})
|
||
|
"""
|
||
|
When executing query:
|
||
|
"""
|
||
|
MATCH (a)
|
||
|
WITH a.bar AS bars, count(*) AS relCount
|
||
|
ORDER BY a.bar
|
||
|
RETURN *
|
||
|
"""
|
||
|
Then the result should be:
|
||
|
| bars | relCount |
|
||
|
| 'A' | 2 |
|
||
|
| 'B' | 1 |
|
||
|
And no side effects
|
||
|
|
||
|
Scenario: ORDER BY a DISTINCT column
|
||
|
Given an empty graph
|
||
|
And having executed:
|
||
|
"""
|
||
|
CREATE ({bar: 'A'}),
|
||
|
({bar: 'A'}),
|
||
|
({bar: 'B'})
|
||
|
"""
|
||
|
When executing query:
|
||
|
"""
|
||
|
MATCH (a)
|
||
|
WITH DISTINCT a.bar AS bars
|
||
|
ORDER BY a.bar
|
||
|
RETURN *
|
||
|
"""
|
||
|
Then the result should be:
|
||
|
| bars |
|
||
|
| 'A' |
|
||
|
| 'B' |
|
||
|
And no side effects
|
||
|
|
||
|
Scenario: WHERE on a DISTINCT column
|
||
|
Given an empty graph
|
||
|
And having executed:
|
||
|
"""
|
||
|
CREATE ({bar: 'A'}),
|
||
|
({bar: 'A'}),
|
||
|
({bar: 'B'})
|
||
|
"""
|
||
|
When executing query:
|
||
|
"""
|
||
|
MATCH (a)
|
||
|
WITH DISTINCT a.bar AS bars
|
||
|
WHERE a.bar = 'B'
|
||
|
RETURN *
|
||
|
"""
|
||
|
Then the result should be:
|
||
|
| bars |
|
||
|
| 'B' |
|
||
|
And no side effects
|
||
|
|
||
|
Scenario: A simple pattern with one bound endpoint
|
||
|
Given an empty graph
|
||
|
And having executed:
|
||
|
"""
|
||
|
CREATE (:A)-[:REL]->(:B)
|
||
|
"""
|
||
|
When executing query:
|
||
|
"""
|
||
|
MATCH (a:A)-[r:REL]->(b:B)
|
||
|
WITH a AS b, b AS tmp, r AS r
|
||
|
WITH b AS a, r
|
||
|
LIMIT 1
|
||
|
MATCH (a)-[r]->(b)
|
||
|
RETURN a, r, b
|
||
|
"""
|
||
|
Then the result should be:
|
||
|
| a | r | b |
|
||
|
| (:A) | [:REL] | (:B) |
|
||
|
And no side effects
|
||
|
|
||
|
Scenario: Null handling
|
||
|
Given an empty graph
|
||
|
When executing query:
|
||
|
"""
|
||
|
OPTIONAL MATCH (a:Start)
|
||
|
WITH a
|
||
|
MATCH (a)-->(b)
|
||
|
RETURN *
|
||
|
"""
|
||
|
Then the result should be:
|
||
|
| a | b | r |
|
||
|
And no side effects
|
||
|
|
||
|
Scenario: Nested maps
|
||
|
Given an empty graph
|
||
|
When executing query:
|
||
|
"""
|
||
|
WITH {foo: {bar: 'baz'}} AS nestedMap
|
||
|
RETURN nestedMap.foo.bar
|
||
|
"""
|
||
|
Then the result should be:
|
||
|
| nestedMap.foo.bar |
|
||
|
| 'baz' |
|
||
|
And no side effects
|
||
|
|
||
|
Scenario: Connected components succeeding WITH
|
||
|
Given an empty graph
|
||
|
And having executed:
|
||
|
"""
|
||
|
CREATE (:A)-[:REL]->(:X)
|
||
|
CREATE (:B)
|
||
|
"""
|
||
|
When executing query:
|
||
|
"""
|
||
|
MATCH (n:A)
|
||
|
WITH n
|
||
|
LIMIT 1
|
||
|
MATCH (m:B), (n)-->(x:X)
|
||
|
RETURN *
|
||
|
"""
|
||
|
Then the result should be:
|
||
|
| m | n | x |
|
||
|
| (:B) | (:A) | (:X) |
|
||
|
And no side effects
|
||
|
|
||
|
Scenario: Single WITH using a predicate and aggregation
|
||
|
Given an empty graph
|
||
|
And having executed:
|
||
|
"""
|
||
|
CREATE ({prop: 43}), ({prop: 42})
|
||
|
"""
|
||
|
When executing query:
|
||
|
"""
|
||
|
MATCH (n)
|
||
|
WITH n
|
||
|
WHERE n.prop = 42
|
||
|
RETURN count(*)
|
||
|
"""
|
||
|
Then the result should be:
|
||
|
| count(*) |
|
||
|
| 1 |
|
||
|
And no side effects
|
||
|
|
||
|
Scenario: Multiple WITHs using a predicate and aggregation
|
||
|
Given an empty graph
|
||
|
And having executed:
|
||
|
"""
|
||
|
CREATE (a {name: 'David'}),
|
||
|
(b {name: 'Other'}),
|
||
|
(c {name: 'NotOther'}),
|
||
|
(d {name: 'NotOther2'}),
|
||
|
(a)-[:REL]->(b),
|
||
|
(a)-[:REL]->(c),
|
||
|
(a)-[:REL]->(d),
|
||
|
(b)-[:REL]->(),
|
||
|
(b)-[:REL]->(),
|
||
|
(c)-[:REL]->(),
|
||
|
(c)-[:REL]->(),
|
||
|
(d)-[:REL]->()
|
||
|
"""
|
||
|
When executing query:
|
||
|
"""
|
||
|
MATCH (david {name: 'David'})--(otherPerson)-->()
|
||
|
WITH otherPerson, count(*) AS foaf
|
||
|
WHERE foaf > 1
|
||
|
WITH otherPerson
|
||
|
WHERE otherPerson.name <> 'NotOther'
|
||
|
RETURN count(*)
|
||
|
"""
|
||
|
Then the result should be:
|
||
|
| count(*) |
|
||
|
| 1 |
|
||
|
And no side effects
|