Your Question
I want to delete the existing record in a transaction after error creation. In the document, it is said that the transaction will be rolled back if an error is returned. But in the example below, the transaction is aborted due to an error in the creation, not after returns an error
func (l likeGorm) CreateOrDelete(ctx context.Context, like *entity.Like) error {
return l.db.Transaction(func(tx *gorm.DB) error {
likeDB := l.marshal(like)
// Create - ERROR: duplicate key value violates unique constraint "like_db_pkey" (SQLSTATE 23505)
if err := tx.WithContext(ctx).Model(l.model).Create(likeDB).Error; err != nil {
if isDuplicate(err) {
// Delete - ERROR: current transaction is aborted, commands ignored until end of transaction block (SQLSTATE 25P02)
if err := tx.WithContext(ctx).Model(l.model).
Where("post_uuid = ? AND creator_uuid = ?", like.PostID, like.Creator).
Delete(l.model).Error; err != nil {
return err
}
return nil
}
return err
}
return nil
})
}
The document you expected this should be explained
https://gorm.io/docs/transactions.html#Transaction
Expected answer
How can I handle a query error by another query in a transaction?
Comment From: ghost
@thanhpp Shouldn't be like this.
func BeginTransaction(db *gorm.DB) {
if !db.Config.SkipDefaultTransaction && db.Error == nil {
if tx := db.Begin(); tx.Error == nil {
db.Statement.ConnPool = tx.Statement.ConnPool
db.InstanceSet("gorm:started_transaction", true)
} else if tx.Error == gorm.ErrInvalidTransaction {
tx.Error = nil
} else {
db.Error = tx.Error
}
}
}
Begin() will return gorm.ErrInvalidTransaction so create's transaction don't begin.
Comment From: thanhpp
BeginTransaction @longlihale
Can you suggest a way to workaround?
Comment From: ghost
I try it and find the transaction is not aborted due to an error in the creation, after returns an error....
Comment From: ghost
BeginTransaction @longlihale
Can you suggest a way to workaround?
It should be ok to use db.Transaction
Comment From: thanhpp
BeginTransaction @longlihale
Can you suggest a way to workaround?
It should be ok to use
db.Transaction
This is a picture of my code's execution. It shows that the second query (delete) returns an error due to the transaction being aborted
Comment From: ghost
@thanhpp hello, can you provide a demo in https://github.com/go-gorm/playground ? :kissing_heart:
Comment From: thanhpp
@longlihale https://github.com/go-gorm/playground/pull/402 I still met the same problem using the playground
Comment From: jinzhu
seems like this is a feature of postgres, refer: https://www.endpointdev.com/blog/2015/02/postgres-onerrorrollback-explained/****
Comment From: OrkhanAlikhanov
How did you guys resolve it? I tried to wrap the code another transaction to create a savepoint but didn't seem to help.
Comment From: OrkhanAlikhanov
Wait, it actually helped. I just had to make sure that the code was rolling back to the previous savepoint by returning non-nil error.