Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specify the behaviour of deleted elements #332

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions cip/1.accepted/CIP2018-10-19-Delete-Semantics.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
= CIP2018-10-19 Semantics of Deleted Elements
:numbered:
:toc:
:toc-placement: macro
:source-highlighter: codemirror

*Author:* Tobias Lindaaker <[email protected]>

toc::[]

== Semantics of Deleted Elements

Cypher allows read statements to occur after update statements.
This includes reading statements after statements that delete elements.
Since the driving table of the preceding query is retained into the succeeding reading statements, this means that entries in the driving table that previously contained elements might now contain elements that have been deleted.

The semantics of accessing such elements is the same as accessing `NULL` values.

This can be thought of as replacing all occurrences of the deleted elements (anywhere) in the driving table (including in nested values) with `NULL`, or as treating the deleted elements as _effectively_ `NULL`.

These semantics effect the `DELETE` statement itself, even if not succeeded by further read statements, since the same element can occur in multiple rows in the driving table.


=== Accessing properties of deleted Elements
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a change from current behaviour.

This is the main change that people seem to agree that we want from this change proposal.


Accessing properties of deleted elements produces a `NULL` value, just like accessing a property from a `NULL` value would.

=== Pattern matching on deleted Elements
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a change from current behaviour.

Currently pattern matching on NULL produces 0 rows.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we deviate from the "behaves like null" in this case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The proposal in this section is to have this be the behaviour for all nulls.


Pattern matching on deleted elements produces a single row containing only `NULL` bindings, in the same way as `OPTIONAL MATCH` would.

=== Deleting deleted Elements
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same as current behaviour, but should still be documented.


Deleting a deleted element (or any `NULL` value) is a no-op.

=== Equality of deleted Elements
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a change from current behaviour, where two references to the same element are considered equal even after the element has been deleted.


The normal semantics is that two `NULL` values are never considered equal.
This extends to deleted elements, since they are equivalent to `NULL` for _all_ intents and purposes.

[source, cypher]
.This query returns `same1: *true*; same2: *false*` for all rows
----
MATCH (n), (m)
WHERE n = m AND NOT EXISTS { (n)-() }
WITH n, m, n = m AS same1
DELETE n
RETURN same1, n = m AS same2
----

=== Deleted elements in paths
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also a change from current behaviour.

The controversial part of it is that it could be argued that it might be expensive to implement such checking to see if the elements of the path have been deleted. I would argue that since all operations on a path accesses all the elements anyhow, the cost of such checking is negligible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A nice thing about this behaviour for paths is that it works really well with the (intended) behaviour of UNWIND, where for example UNWIND nodes(p) AS n would produce a single row with n bound to NULL if an element of p was deleted (since p would be considered NULL and nodes(NULL) returns NULL, and UNWIND NULL AS n produces a single row with n bound to NULL).


If an element is deleted that is part of a path value, such a path can no longer exist, therefore the path value is to be treated as _effectively_ `NULL` (in the same way that the deleted element that is part of it would).

[source, cypher]
.This query returns `a: *null*; b: *null*; c: *null*` for all rows
----
MATCH p=()-[r]->()
DELETE r
RETURN p AS a, nodes(p) AS b, relationships(p) AS c
----

=== Effects of DELETE on types

In the part of a query following a `DELETE` statement that deletes elements of type node, all elements of type node may now be nullable.
In the part of a query following a `DELETE` statement that deletes elements of type relationship, all elements of type relationship may now be nullable.
In the part of a query following a `DETACH DELETE` statement, all elements of type node and of type relationship may now be nullable.

An implementation that tracks the types of nodes and relationships more closely, such as by which labels they have, it is allowed to not treat elements as nullable in the part of the query following `DELETE` iff it can be proven that those entities are unaffected by the `DELETE`.