openCypher
openCypher copied to clipboard
Node/relationship accessibility after DELETE operation
CIR-2017-263
This issue is related to the semantics of operations where operands are variables bound to deleted nodes or relationships. The topic is partially covered by scenarios from ReturnAcceptance2 feature:
- accessibility of node labels - inaccessible
- accessibility of relationship type - accessible
- accessibility of node/relationship properties values - inaccessible
The general request is to specify Cypher behaviour in some different scenarios presented below with current results of neo4j console.
1. Entity node/relationship is returned after deletion
For database:
create ()-[:mytype {n:1}]->()
following query:
match ()-[r]->()
delete r
return id(r)
gives following result:
+-------+
| id(r) |
+-------+
| 0 |
+-------+
1 row
2 ms
Relationships deleted: 1
2. Keys function returns empty list after node/relationship deletion
For database:
create ()-[:mytype {n:1}]->()
following query:
match ()-[r]->()
delete r
return keys(r)
gives following result:
+---------+
| keys(r) |
+---------+
| [] |
+---------+
1 row
8 ms
Relationships deleted: 1
3. Functions startNode, endNode return ids of corresponding nodes
For database:
create ()-[:mytype {n:1}]->()
following query:
match ()-[r]->()
delete r
return startNode(r),endNode(r)
gives following result:
+---------------------------+
| startNode(r) | endNode(r) |
+---------------------------+
| Node[4]{} | Node[5]{} |
+---------------------------+
1 row
20 ms
Relationships deleted: 1
4. Node is matched after deletion
For database:
create ({x:1}),({x:2})
following query:
match (n {x:1})
delete (n)
with n as n
match (n),(m {x:2})
return id(n), m
gives following result:
+-----------------------+
| id(n) | m |
+-----------------------+
| 9 | Node[10]{x:2} |
+-----------------------+
1 row
19 ms
Nodes deleted: 1
Are above results semantically correct?
Historically, Neo4j has supported so-called 'tombstone semantics' with respect to deleted entities; the DELETE operation only marks the entity for deletion, and materialises this only when the query ends (during commit time, in transactional terms). With such semantics, all entity details (labels, properties, etc) would still be available within the query.
This was recently changed in Neo4j as is observed by the above, where the decision was to only provide the id of the deleted entity, and to fail any operation that tried to extract other things. These changes were initiated as a reaction to a discussion on what semantics to provide for returning deleted entities:
CREATE (n:Node {prop: 1})
DELETE n
RETURN n
This has not been specified formally, however, so I would view Neo4j's behaviour as convention rather than standard.
I'll outline two possible options as I see it:
'Tombstone' semantics
DELETE marks the entity for deletion; all subsequent operations involving the entity within the query will function as normal, including returning the entity. Matching will not find the entity in the graph(s) it was previously present in.
A variation on this would be to invalidate the id of the entity at return time, somehow (since it is no longer valid after query termination).
'Strict' semantics
DELETE functionally removes the entity entirely. Any subsequent operation involving the entity would either return empty/null or fail (depending on what makes sense for the operation).