feat: disable prepare nested transaction

This commit is contained in:
a631807682 2023-02-15 14:59:28 +08:00
parent 02b7e26f6b
commit 484d162023
No known key found for this signature in database
GPG Key ID: 137D1D75522168AB
3 changed files with 11 additions and 1 deletions

View File

@ -617,7 +617,7 @@ func (db *DB) Transaction(fc func(tx *DB) error, opts ...*sql.TxOptions) (err er
if committer, ok := db.Statement.ConnPool.(TxCommitter); ok && committer != nil { if committer, ok := db.Statement.ConnPool.(TxCommitter); ok && committer != nil {
// nested transaction // nested transaction
if !db.DisableNestedTransaction { if !db.DisableNestedTransaction && (db.PrepareStmt && !db.DisablePrepareNestedTransaction) {
err = db.SavePoint(fmt.Sprintf("sp%p", fc)).Error err = db.SavePoint(fmt.Sprintf("sp%p", fc)).Error
if err != nil { if err != nil {
return return

View File

@ -41,6 +41,8 @@ type Config struct {
IgnoreRelationshipsWhenMigrating bool IgnoreRelationshipsWhenMigrating bool
// DisableNestedTransaction disable nested transaction // DisableNestedTransaction disable nested transaction
DisableNestedTransaction bool DisableNestedTransaction bool
// DisablePrepareNestedTransaction disable nested transaction in prepare statement
DisablePrepareNestedTransaction bool
// AllowGlobalUpdate allow global update // AllowGlobalUpdate allow global update
AllowGlobalUpdate bool AllowGlobalUpdate bool
// QueryFields executes the SQL query with all fields of the table // QueryFields executes the SQL query with all fields of the table

View File

@ -51,6 +51,14 @@ func TestPreparedStmt(t *testing.T) {
if err := tx.Find(&result3, user2.ID).Error; err != nil { if err := tx.Find(&result3, user2.ID).Error; err != nil {
t.Fatalf("no error should happen but got %v", err) t.Fatalf("no error should happen but got %v", err)
} }
user3 := *GetUser("prepared_stmt_transaction", Config{})
err := tx.Transaction(func(tx1 *gorm.DB) error {
return tx1.Transaction(func(tx2 *gorm.DB) error {
return tx2.Create(&user3).Error
})
})
AssertEqual(t, nil, err)
} }
func TestPreparedStmtFromTransaction(t *testing.T) { func TestPreparedStmtFromTransaction(t *testing.T) {