#
# 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: CreateAcceptance

  Scenario: Create a single node with multiple labels
    Given any graph
    When executing query:
      """
      CREATE (:A:B:C:D)
      """
    Then the result should be empty
    And the side effects should be:
      | +nodes  | 1 |
      | +labels | 4 |

  Scenario: Combine MATCH and CREATE
    Given an empty graph
    And having executed:
      """
      CREATE (), ()
      """
    When executing query:
      """
      MATCH ()
      CREATE ()
      """
    Then the result should be empty
    And the side effects should be:
      | +nodes  | 2 |

  Scenario: Combine MATCH, WITH and CREATE
    Given an empty graph
    And having executed:
      """
      CREATE (), ()
      """
    When executing query:
      """
      MATCH ()
      CREATE ()
      WITH *
      MATCH ()
      CREATE ()
      """
    Then the result should be empty
    And the side effects should be:
      | +nodes  | 10 |

  Scenario: Newly-created nodes not visible to preceding MATCH
    Given an empty graph
    And having executed:
      """
      CREATE ()
      """
    When executing query:
      """
      MATCH ()
      CREATE ()
      """
    Then the result should be empty
    And the side effects should be:
      | +nodes  | 1 |

  Scenario: Create a single node with properties
    Given any graph
    When executing query:
      """
      CREATE (n {prop: 'foo'})
      RETURN n.prop AS p
      """
    Then the result should be:
      | p     |
      | 'foo' |
    And the side effects should be:
      | +nodes      | 1 |
      | +properties | 1 |

  Scenario: Creating a node with null properties should not return those properties
    Given any graph
    When executing query:
      """
      CREATE (n {id: 12, property: null})
      RETURN n.id AS id
      """
    Then the result should be:
      | id |
      | 12 |
    And the side effects should be:
      | +nodes      | 1 |
      | +properties | 1 |

  Scenario: Creating a relationship with null properties should not return those properties
    Given any graph
    When executing query:
      """
      CREATE ()-[r:X {id: 12, property: null}]->()
      RETURN r.id
      """
    Then the result should be:
      | r.id |
      | 12   |
    And the side effects should be:
      | +nodes         | 2 |
      | +relationships | 1 |
      | +properties    | 1 |

  Scenario: Create a simple pattern
    Given any graph
    When executing query:
      """
      CREATE ()-[:R]->()
      """
    Then the result should be empty
    And the side effects should be:
      | +nodes         | 2 |
      | +relationships | 1 |

  Scenario: Create a self loop
    Given any graph
    When executing query:
      """
      CREATE (root:R)-[:LINK]->(root)
      """
    Then the result should be empty
    And the side effects should be:
      | +nodes         | 1 |
      | +relationships | 1 |
      | +labels        | 1 |

  Scenario: Create a self loop using MATCH
    Given an empty graph
    And having executed:
      """
      CREATE (:R)
      """
    When executing query:
      """
      MATCH (root:R)
      CREATE (root)-[:LINK]->(root)
      """
    Then the result should be empty
    And the side effects should be:
      | +relationships | 1 |

  Scenario: Create nodes and relationships
    Given any graph
    When executing query:
      """
      CREATE (a), (b),
             (a)-[:R]->(b)
      """
    Then the result should be empty
    And the side effects should be:
      | +nodes         | 2 |
      | +relationships | 1 |

  Scenario: Create a relationship with a property
    Given any graph
    When executing query:
      """
      CREATE ()-[:R {prop: 42}]->()
      """
    Then the result should be empty
    And the side effects should be:
      | +nodes         | 2 |
      | +relationships | 1 |
      | +properties    | 1 |

  Scenario: Create a relationship with the correct direction
    Given an empty graph
    And having executed:
      """
      CREATE (:X)
      CREATE (:Y)
      """
    When executing query:
      """
      MATCH (x:X), (y:Y)
      CREATE (x)<-[:TYPE]-(y)
      """
    Then the result should be empty
    And the side effects should be:
      | +relationships | 1 |
    When executing control query:
      """
      MATCH (x:X)<-[:TYPE]-(y:Y)
      RETURN x, y
      """
    Then the result should be:
      | x    |  y   |
      | (:X) | (:Y) |

  Scenario: Create a relationship and an end node from a matched starting node
    Given an empty graph
    And having executed:
      """
      CREATE (:Begin)
      """
    When executing query:
      """
      MATCH (x:Begin)
      CREATE (x)-[:TYPE]->(:End)
      """
    Then the result should be empty
    And the side effects should be:
      | +nodes         | 1 |
      | +relationships | 1 |
      | +labels        | 1 |
    When executing control query:
      """
      MATCH (x:Begin)-[:TYPE]->()
      RETURN x
      """
    Then the result should be:
      | x        |
      | (:Begin) |

  Scenario: Create a single node after a WITH
    Given an empty graph
    And having executed:
      """
      CREATE (), ()
      """
    When executing query:
      """
      MATCH ()
      CREATE ()
      WITH *
      CREATE ()
      """
    Then the result should be empty
    And the side effects should be:
      | +nodes | 4 |

  Scenario: Create a relationship with a reversed direction
    Given an empty graph
    When executing query:
      """
      CREATE (:A)<-[:R]-(:B)
      """
    Then the result should be empty
    And the side effects should be:
      | +nodes         | 2 |
      | +relationships | 1 |
      | +labels        | 2 |
    When executing control query:
      """
      MATCH (a:A)<-[:R]-(b:B)
      RETURN a, b
      """
    Then the result should be:
      | a    | b    |
      | (:A) | (:B) |

  Scenario: Create a pattern with multiple hops
    Given an empty graph
    When executing query:
      """
      CREATE (:A)-[:R]->(:B)-[:R]->(:C)
      """
    Then the result should be empty
    And the side effects should be:
      | +nodes         | 3 |
      | +relationships | 2 |
      | +labels        | 3 |
    When executing control query:
      """
      MATCH (a:A)-[:R]->(b:B)-[:R]->(c:C)
      RETURN a, b, c
      """
    Then the result should be:
      | a    | b    | c    |
      | (:A) | (:B) | (:C) |

  Scenario: Create a pattern with multiple hops in the reverse direction
    Given any graph
    When executing query:
      """
      CREATE (:A)<-[:R]-(:B)<-[:R]-(:C)
      """
    Then the result should be empty
    And the side effects should be:
      | +nodes         | 3 |
      | +relationships | 2 |
      | +labels        | 3 |
    When executing control query:
      """
      MATCH (a)<-[:R]-(b)<-[:R]-(c)
      RETURN a, b, c
      """
    Then the result should be:
      | a    | b    | c    |
      | (:A) | (:B) | (:C) |

  Scenario: Create a pattern with multiple hops in varying directions
    Given any graph
    When executing query:
      """
      CREATE (:A)-[:R]->(:B)<-[:R]-(:C)
      """
    Then the result should be empty
    And the side effects should be:
      | +nodes         | 3 |
      | +relationships | 2 |
      | +labels        | 3 |
    When executing control query:
      """
      MATCH (a:A)-[r1:R]->(b:B)<-[r2:R]-(c:C)
      RETURN a, b, c
      """
    Then the result should be:
      | a    | b    | c    |
      | (:A) | (:B) | (:C) |

  Scenario: Create a pattern with multiple hops with multiple types and varying directions
    Given any graph
    When executing query:
      """
      CREATE ()-[:R1]->()<-[:R2]-()-[:R3]->()
      """
    Then the result should be empty
    And the side effects should be:
      | +nodes         | 4 |
      | +relationships | 3 |
    When executing query:
      """
      MATCH ()-[r1:R1]->()<-[r2:R2]-()-[r3:R3]->()
      RETURN r1, r2, r3
      """
    Then the result should be:
      | r1    | r2    | r3    |
      | [:R1] | [:R2] | [:R3] |

  Scenario: Nodes are not created when aliases are applied to variable names
    Given an empty graph
    And having executed:
      """
      CREATE ({foo: 1})
      """
    When executing query:
      """
      MATCH (n)
      MATCH (m)
      WITH n AS a, m AS b
      CREATE (a)-[:T]->(b)
      RETURN a, b
      """
    Then the result should be:
      | a          | b          |
      | ({foo: 1}) | ({foo: 1}) |
    And the side effects should be:
      | +relationships | 1 |

  Scenario: Only a single node is created when an alias is applied to a variable name
    Given an empty graph
    And having executed:
      """
      CREATE (:X)
      """
    When executing query:
      """
      MATCH (n)
      WITH n AS a
      CREATE (a)-[:T]->()
      RETURN a
      """
    Then the result should be:
      | a    |
      | (:X) |
    And the side effects should be:
      | +nodes         | 1 |
      | +relationships | 1 |

  Scenario: Nodes are not created when aliases are applied to variable names multiple times
    Given an empty graph
    And having executed:
      """
      CREATE ({foo: 'A'})
      """
    When executing query:
      """
      MATCH (n)
      MATCH (m)
      WITH n AS a, m AS b
      CREATE (a)-[:T]->(b)
      WITH a AS x, b AS y
      CREATE (x)-[:T]->(y)
      RETURN x, y
      """
    Then the result should be:
      | x            | y            |
      | ({foo: 'A'}) | ({foo: 'A'}) |
    And the side effects should be:
      | +relationships | 2 |

  Scenario: Only a single node is created when an alias is applied to a variable name multiple times
    Given an empty graph
    And having executed:
      """
      CREATE ({foo: 5})
      """
    When executing query:
      """
      MATCH (n)
      WITH n AS a
      CREATE (a)-[:T]->()
      WITH a AS x
      CREATE (x)-[:T]->()
      RETURN x
      """
    Then the result should be:
      | x          |
      | ({foo: 5}) |
    And the side effects should be:
      | +nodes         | 2 |
      | +relationships | 2 |

  Scenario: A bound node should be recognized after projection with WITH + WITH
    Given any graph
    When executing query:
      """
      CREATE (a)
      WITH a
      WITH *
      CREATE (b)
      CREATE (a)<-[:T]-(b)
      """
    Then the result should be empty
    And the side effects should be:
      | +nodes         | 2 |
      | +relationships | 1 |

  Scenario: A bound node should be recognized after projection with WITH + UNWIND
    Given any graph
    When executing query:
      """
      CREATE (a)
      WITH a
      UNWIND [0] AS i
      CREATE (b)
      CREATE (a)<-[:T]-(b)
      """
    Then the result should be empty
    And the side effects should be:
      | +nodes         | 2 |
      | +relationships | 1 |

  Scenario: A bound node should be recognized after projection with WITH + MERGE node
    Given an empty graph
    When executing query:
      """
      CREATE (a)
      WITH a
      MERGE ()
      CREATE (b)
      CREATE (a)<-[:T]-(b)
      """
    Then the result should be empty
    And the side effects should be:
      | +nodes         | 2 |
      | +relationships | 1 |

  Scenario: A bound node should be recognized after projection with WITH + MERGE pattern
    Given an empty graph
    When executing query:
      """
      CREATE (a)
      WITH a
      MERGE (x)
      MERGE (y)
      MERGE (x)-[:T]->(y)
      CREATE (b)
      CREATE (a)<-[:T]-(b)
      """
    Then the result should be empty
    And the side effects should be:
      | +nodes         | 2 |
      | +relationships | 2 |

  Scenario: Fail when trying to create using an undirected relationship pattern
    Given any graph
    When executing query:
      """
      CREATE ({id: 2})-[r:KNOWS]-({id: 1})
      RETURN r
      """
    Then a SyntaxError should be raised at compile time: RequiresDirectedRelationship

  Scenario: Creating a pattern with multiple hops and changing directions
    Given an empty graph
    When executing query:
      """
      CREATE (:A)<-[:R1]-(:B)-[:R2]->(:C)
      """
    Then the result should be empty
    And the side effects should be:
      | +nodes         | 3 |
      | +relationships | 2 |
      | +labels        | 3 |
    When executing control query:
      """
      MATCH (a:A)<-[r1:R1]-(b:B)-[r2:R2]->(c:C) RETURN *
      """
    Then the result should be:
      | a    | r1    | b    | r2    | c    |
      | (:A) | [:R1] | (:B) | [:R2] | (:C) |
