proposal: cascading deletion support
- Dominant language
- Go
- Stars
- 17.2k
- Forks
- 1k
- PR merge metrics
- No merged PRs in 30d
Description
We want to add support for cascading deletion in ent. We are in early discussions and your comments and feedback can help us.
----
#### GENERAL IDEA
The cascading deletion will be implemented in the framework and won't be configured
in the database (e.g. `ON DELETE CASCADE` in MySQL), in order to support privacy checks,
logging, tracing, etc.
What about adding support for database-level deletion? See below. I was thinking about adding support for schema [DDL](https://en.wikipedia.org/wiki/Data_definition_language)s, and this way, users will be able to configure `ON DELETE CASCADE` actions on their tables. But this is part of a different discussion.
**Update**: database-level cascading deletion was added in https://github.com/ent/ent/pull/1339
--
The first option is `cascade-delete`, which indicates that if a user is deleted, the cards
that are associated with it will be deleted as well. The schema declaration is as follows:
```go
func (User) Edges() []ent.Edge {
return []ent.Edge{
edge.To("cards", Card.Type).
Cascade(edge.Delete()),
}
}
```
The second option is `delete-orphan`, which provides the same functionality as `cascade-delete`,
but in addition to that, it indicates that nodes without a reference should be deleted.
For example, if a user removes an edge from the card, the card should be deleted - because it's an orphan.
```go
func (User) Edges() []ent.Edge {
return []ent.Edge{
edge.To("cards", Card.Type).
Cascade(edge.Delete(), edge.DeleteOrphan()),
}
}
```
However, sometimes we want to move a reference to a "child node" from one parent to the other.
For example, move the card ownership from Ariel to Alex - in this case, we don't want the card
to be deleted (between the ownership transition). Therefore, I'm thinking about 2 options:
1. Add an option to disable cascade-deletion on delete operation. For example:
```go
client.User.
UpdateOne(a8m).
RemoveCards(card).
WithCascadeDelete(false).
Save(ctx)
```
2. Add support for sessions - need more design, but the idea goes as follows:
```go
s := client.Session()
s.User.UpdateOne(a8m).RemoveCards(card).Save(ctx)
s.User.UpdateOne(alex).AddCards(card).Save(ctx)
s.Commit() // Maybe, s.Flush() to not confuse with ent.Tx.
```
Since adding support for a session is a broader change, maybe we can start with option 1, and add support for sessions after V1.
2 additional notes:
1. A node can only cascade deletion to edges of type:
- For O2M edge: an edge from a user to its pets - A pet can't delete its owner.
- For O2O edge: only the owner of the edge can delete it - An address can't delete its resident.
- For bidirectional O2O: cascade-deletion is not allowed - A user can't delete its spouse.
2. I was thinking about adding this functionality outside of the schema as well. For example, add this to the Delete/Update builders:
```go
client.User.Delete().
WithCards(predicates...).
Exec(ctx)
```
Please feel free to give feedback and comment. Nothing is set in stone yet!
Contributor guide
Assessment
This issue has not been assessed yet.