Skip to content

proposal: cascading deletion support #407

@a8m

Description

@a8m

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 DDLs, 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 #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:

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.

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:

    client.User.
        UpdateOne(a8m).
        RemoveCards(card).
        WithCascadeDelete(false).
        Save(ctx)
  2. Add support for sessions - need more design, but the idea goes as follows:

    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:

    client.User.Delete().
    	WithCards(predicates...).
    	Exec(ctx)

Please feel free to give feedback and comment. Nothing is set in stone yet!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions