ent / ent/ent

proposal: cascading deletion support

Open
#407 10 comments 39 reactions 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.