forked from mirror/gorm
Add BeginTx for parity with sql.DB.BeginTx (#2227)
This commit is contained in:
parent
ac78f05986
commit
af01854d3e
|
@ -1,6 +1,9 @@
|
||||||
package gorm
|
package gorm
|
||||||
|
|
||||||
import "database/sql"
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
)
|
||||||
|
|
||||||
// SQLCommon is the minimal database connection functionality gorm requires. Implemented by *sql.DB.
|
// SQLCommon is the minimal database connection functionality gorm requires. Implemented by *sql.DB.
|
||||||
type SQLCommon interface {
|
type SQLCommon interface {
|
||||||
|
@ -12,6 +15,7 @@ type SQLCommon interface {
|
||||||
|
|
||||||
type sqlDb interface {
|
type sqlDb interface {
|
||||||
Begin() (*sql.Tx, error)
|
Begin() (*sql.Tx, error)
|
||||||
|
BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type sqlTx interface {
|
type sqlTx interface {
|
||||||
|
|
10
main.go
10
main.go
|
@ -1,6 +1,7 @@
|
||||||
package gorm
|
package gorm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -503,11 +504,16 @@ func (s *DB) Debug() *DB {
|
||||||
return s.clone().LogMode(true)
|
return s.clone().LogMode(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin begin a transaction
|
// Begin begins a transaction
|
||||||
func (s *DB) Begin() *DB {
|
func (s *DB) Begin() *DB {
|
||||||
|
return s.BeginTx(context.Background(), &sql.TxOptions{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// BeginTX begins a transaction with options
|
||||||
|
func (s *DB) BeginTx(ctx context.Context, opts *sql.TxOptions) *DB {
|
||||||
c := s.clone()
|
c := s.clone()
|
||||||
if db, ok := c.db.(sqlDb); ok && db != nil {
|
if db, ok := c.db.(sqlDb); ok && db != nil {
|
||||||
tx, err := db.Begin()
|
tx, err := db.BeginTx(ctx, opts)
|
||||||
c.db = interface{}(tx).(SQLCommon)
|
c.db = interface{}(tx).(SQLCommon)
|
||||||
|
|
||||||
c.dialect.SetDB(c.db)
|
c.dialect.SetDB(c.db)
|
||||||
|
|
35
main_test.go
35
main_test.go
|
@ -1,6 +1,7 @@
|
||||||
package gorm_test
|
package gorm_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"database/sql/driver"
|
"database/sql/driver"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -471,6 +472,40 @@ func TestTransaction_NoErrorOnRollbackAfterCommit(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTransactionReadonly(t *testing.T) {
|
||||||
|
dialect := os.Getenv("GORM_DIALECT")
|
||||||
|
if dialect == "" {
|
||||||
|
dialect = "sqlite"
|
||||||
|
}
|
||||||
|
switch dialect {
|
||||||
|
case "mssql", "sqlite":
|
||||||
|
t.Skipf("%s does not support readonly transactions\n", dialect)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx := DB.Begin()
|
||||||
|
u := User{Name: "transcation"}
|
||||||
|
if err := tx.Save(&u).Error; err != nil {
|
||||||
|
t.Errorf("No error should raise")
|
||||||
|
}
|
||||||
|
tx.Commit()
|
||||||
|
|
||||||
|
tx = DB.BeginTx(context.Background(), &sql.TxOptions{ReadOnly: true})
|
||||||
|
if err := tx.First(&User{}, "name = ?", "transcation").Error; err != nil {
|
||||||
|
t.Errorf("Should find saved record")
|
||||||
|
}
|
||||||
|
|
||||||
|
if sqlTx, ok := tx.CommonDB().(*sql.Tx); !ok || sqlTx == nil {
|
||||||
|
t.Errorf("Should return the underlying sql.Tx")
|
||||||
|
}
|
||||||
|
|
||||||
|
u = User{Name: "transcation-2"}
|
||||||
|
if err := tx.Save(&u).Error; err == nil {
|
||||||
|
t.Errorf("Error should have been raised in a readonly transaction")
|
||||||
|
}
|
||||||
|
|
||||||
|
tx.Rollback()
|
||||||
|
}
|
||||||
|
|
||||||
func TestRow(t *testing.T) {
|
func TestRow(t *testing.T) {
|
||||||
user1 := User{Name: "RowUser1", Age: 1, Birthday: parseTime("2000-1-1")}
|
user1 := User{Name: "RowUser1", Age: 1, Birthday: parseTime("2000-1-1")}
|
||||||
user2 := User{Name: "RowUser2", Age: 10, Birthday: parseTime("2010-1-1")}
|
user2 := User{Name: "RowUser2", Age: 10, Birthday: parseTime("2010-1-1")}
|
||||||
|
|
Loading…
Reference in New Issue