You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
go-zero/core/stores/sqlx/tx.go

114 lines
2.3 KiB
Go

4 years ago
package sqlx
import (
"database/sql"
"fmt"
)
type (
beginnable func(*sql.DB) (trans, error)
trans interface {
Session
Commit() error
Rollback() error
}
txSession struct {
*sql.Tx
}
)
// NewSessionFromTx returns a Session with the given sql.Tx.
// Use it with caution, it's provided for other ORM to interact with.
func NewSessionFromTx(tx *sql.Tx) Session {
return txSession{Tx: tx}
}
4 years ago
func (t txSession) Exec(q string, args ...interface{}) (sql.Result, error) {
return exec(t.Tx, q, args...)
}
func (t txSession) Prepare(q string) (StmtSession, error) {
stmt, err := t.Tx.Prepare(q)
if err != nil {
4 years ago
return nil, err
}
return statement{
query: q,
stmt: stmt,
}, nil
4 years ago
}
func (t txSession) QueryRow(v interface{}, q string, args ...interface{}) error {
return query(t.Tx, func(rows *sql.Rows) error {
return unmarshalRow(v, rows, true)
}, q, args...)
}
func (t txSession) QueryRowPartial(v interface{}, q string, args ...interface{}) error {
return query(t.Tx, func(rows *sql.Rows) error {
return unmarshalRow(v, rows, false)
}, q, args...)
}
func (t txSession) QueryRows(v interface{}, q string, args ...interface{}) error {
return query(t.Tx, func(rows *sql.Rows) error {
return unmarshalRows(v, rows, true)
}, q, args...)
}
func (t txSession) QueryRowsPartial(v interface{}, q string, args ...interface{}) error {
return query(t.Tx, func(rows *sql.Rows) error {
return unmarshalRows(v, rows, false)
}, q, args...)
}
func begin(db *sql.DB) (trans, error) {
tx, err := db.Begin()
if err != nil {
4 years ago
return nil, err
}
return txSession{
Tx: tx,
}, nil
4 years ago
}
func transact(db *commonSqlConn, b beginnable, fn func(Session) error) (err error) {
conn, err := db.connProv()
4 years ago
if err != nil {
db.onError(err)
4 years ago
return err
}
return transactOnConn(conn, b, fn)
}
func transactOnConn(conn *sql.DB, b beginnable, fn func(Session) error) (err error) {
var tx trans
tx, err = b(conn)
if err != nil {
return
}
4 years ago
defer func() {
if p := recover(); p != nil {
if e := tx.Rollback(); e != nil {
err = fmt.Errorf("recover from %#v, rollback failed: %s", p, e)
} else {
err = fmt.Errorf("recoveer from %#v", p)
}
} else if err != nil {
if e := tx.Rollback(); e != nil {
err = fmt.Errorf("transaction failed: %s, rollback failed: %s", err, e)
}
} else {
err = tx.Commit()
}
}()
return fn(tx)
}