Udara S.S Liyanage
Udara S.S Liyanage

Reputation: 6453

Gorm Association Delete does not remove rows, instead update rows

A client has many Roles. I want to delete all Roles once a client is deleted.

 type Client struct {
        Id                          string `gorm:"primaryKey"`
        CreatedAt                   time.Time
        UpdatedAt                   time.Time
        Roles [] Role
    }
    
    type Role struct {
        Id        uint `gorm:"primarykey"`
        CreatedAt time.Time
        UpdatedAt time.Time
    
        ClientID string
    }
    
    return db.Transaction(func(tx *gorm.DB) error {
            err = db.Model(&clientToRemove).Association("Roles").Delete(&clientToRemove.Roles)
            if err != nil {
                return err
            }
    
            err = db.Delete(&clientToRemove).Error
            if err != nil {
                return err
            }
    
            return nil
        })

I expect related rows in role to be removed, instead of delete query, it executes an update query to remove client_id.

[210.834ms] [rows:1] UPDATE "role" SET "client_id"=NULL WHERE "role"."client_id" = 'xxxxxxxxxxx' AND "role"."id" = 9

How to completely remove rows in associated role table?

Database is Postgres

Upvotes: 0

Views: 1021

Answers (2)

Use Unscoped(). As described in documentation.

Modifying Deletion Behavior with Unscoped

For scenarios requiring actual deletion of associated records, the Unscoped method alters this behavior.

  • Soft Delete: Marks associated records as deleted (sets deleted_at field) without removing them from the database.
db.Model(&user).Association("Languages").Unscoped().Clear()
  • Permanent Delete: Physically deletes the association records from the database.
// db.Unscoped().Model(&user)
db.Unscoped().Model(&user).Association("Languages").Unscoped().Clear()

Upvotes: 0

Emin Laletovic
Emin Laletovic

Reputation: 4324

As stated in the documentation, the delete with association operation will just remove the references between Client and TenantRole. In your case, it just updated the TenantRole records to set the client_id to NULL.

If you want to delete the objects as well, you can try using Select with the delete operation. Please note that this only works if the primary key is not zero, so your query might look something like this:

err = db.Select("TenantRoles").Delete(&Client{Id: clientId}).Error

or just use clientToRemove if it already has the Id field populated

err = db.Select("TenantRoles").Delete(&clientToRemove).Error

Upvotes: 1

Related Questions