Transaction start a transaction as a block, return error will rollback, otherwise to commit. Transaction executes an arbitrary number of commands in fc within a transaction. On success the changes are committed; if an error occurs they are rolled back.
(fc func(tx *DB) error, opts ...*sql.TxOptions)
| 635 | // arbitrary number of commands in fc within a transaction. On success the changes are committed; if an error occurs |
| 636 | // they are rolled back. |
| 637 | func (db *DB) Transaction(fc func(tx *DB) error, opts ...*sql.TxOptions) (err error) { |
| 638 | panicked := true |
| 639 | |
| 640 | if committer, ok := db.Statement.ConnPool.(TxCommitter); ok && committer != nil { |
| 641 | // nested transaction |
| 642 | if !db.DisableNestedTransaction { |
| 643 | spID := new(maphash.Hash).Sum64() |
| 644 | err = db.SavePoint(fmt.Sprintf("sp%d", spID)).Error |
| 645 | if err != nil { |
| 646 | return |
| 647 | } |
| 648 | defer func() { |
| 649 | // Make sure to rollback when panic, Block error or Commit error |
| 650 | if panicked || err != nil { |
| 651 | db.RollbackTo(fmt.Sprintf("sp%d", spID)) |
| 652 | } |
| 653 | }() |
| 654 | } |
| 655 | err = fc(db.Session(&Session{NewDB: db.clone == 1})) |
| 656 | } else { |
| 657 | tx := db.Begin(opts...) |
| 658 | if tx.Error != nil { |
| 659 | return tx.Error |
| 660 | } |
| 661 | |
| 662 | defer func() { |
| 663 | // Make sure to rollback when panic, Block error or Commit error |
| 664 | if panicked || err != nil { |
| 665 | tx.Rollback() |
| 666 | } |
| 667 | }() |
| 668 | |
| 669 | if err = fc(tx); err == nil { |
| 670 | panicked = false |
| 671 | return tx.Commit().Error |
| 672 | } |
| 673 | } |
| 674 | |
| 675 | panicked = false |
| 676 | return |
| 677 | } |
| 678 | |
| 679 | // Begin begins a transaction with any transaction options opts |
| 680 | func (db *DB) Begin(opts ...*sql.TxOptions) *DB { |