Add log track on prepare & tx

This commit is contained in:
Lunny Xiao 2020-02-29 14:51:42 +08:00
parent c8b4ea56bc
commit 046c6bc7e5
No known key found for this signature in database
GPG Key ID: C3B7C91B632F738A
4 changed files with 164 additions and 55 deletions

View File

@ -9,6 +9,9 @@ import (
"database/sql" "database/sql"
"errors" "errors"
"reflect" "reflect"
"time"
"xorm.io/xorm/log"
) )
// Stmt reprents a stmt objects // Stmt reprents a stmt objects
@ -16,6 +19,7 @@ type Stmt struct {
*sql.Stmt *sql.Stmt
db *DB db *DB
names map[string]int names map[string]int
query string
} }
func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error) { func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
@ -27,11 +31,27 @@ func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
return "?" return "?"
}) })
start := time.Now()
if db.Logger != nil {
db.Logger.BeforeSQL(log.LogContext{
Ctx: ctx,
SQL: "PREPARE",
})
}
stmt, err := db.DB.PrepareContext(ctx, query) stmt, err := db.DB.PrepareContext(ctx, query)
if db.Logger != nil {
db.Logger.AfterSQL(log.LogContext{
Ctx: ctx,
SQL: "PREPARE",
ExecuteTime: time.Now().Sub(start),
Err: err,
})
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &Stmt{stmt, db, names}, nil
return &Stmt{stmt, db, names, query}, nil
} }
func (db *DB) Prepare(query string) (*Stmt, error) { func (db *DB) Prepare(query string) (*Stmt, error) {
@ -73,11 +93,46 @@ func (s *Stmt) ExecStruct(st interface{}) (sql.Result, error) {
} }
func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (sql.Result, error) { func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (sql.Result, error) {
return s.Stmt.ExecContext(ctx, args) start := time.Now()
if s.db.Logger != nil {
s.db.Logger.BeforeSQL(log.LogContext{
Ctx: ctx,
SQL: s.query,
Args: args,
})
}
res, err := s.Stmt.ExecContext(ctx, args)
if s.db.Logger != nil {
s.db.Logger.AfterSQL(log.LogContext{
Ctx: ctx,
SQL: s.query,
Args: args,
ExecuteTime: time.Now().Sub(start),
Err: err,
})
}
return res, err
} }
func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, error) { func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, error) {
start := time.Now()
if s.db.Logger != nil {
s.db.Logger.BeforeSQL(log.LogContext{
Ctx: ctx,
SQL: s.query,
Args: args,
})
}
rows, err := s.Stmt.QueryContext(ctx, args...) rows, err := s.Stmt.QueryContext(ctx, args...)
if s.db.Logger != nil {
s.db.Logger.AfterSQL(log.LogContext{
Ctx: ctx,
SQL: s.query,
Args: args,
ExecuteTime: time.Now().Sub(start),
Err: err,
})
}
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -18,7 +18,22 @@ type Tx struct {
} }
func (db *DB) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) { func (db *DB) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) {
start := time.Now()
if db.Logger != nil {
db.Logger.BeforeSQL(log.LogContext{
Ctx: ctx,
SQL: "BEGIN TRANSACTION",
})
}
tx, err := db.DB.BeginTx(ctx, opts) tx, err := db.DB.BeginTx(ctx, opts)
if db.Logger != nil {
db.Logger.AfterSQL(log.LogContext{
Ctx: ctx,
SQL: "BEGIN TRANSACTION",
ExecuteTime: time.Now().Sub(start),
Err: err,
})
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -26,11 +41,7 @@ func (db *DB) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) {
} }
func (db *DB) Begin() (*Tx, error) { func (db *DB) Begin() (*Tx, error) {
tx, err := db.DB.Begin() return db.BeginTx(context.Background(), nil)
if err != nil {
return nil, err
}
return &Tx{tx, db}, nil
} }
func (tx *Tx) PrepareContext(ctx context.Context, query string) (*Stmt, error) { func (tx *Tx) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
@ -42,11 +53,26 @@ func (tx *Tx) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
return "?" return "?"
}) })
start := time.Now()
if tx.db.Logger != nil {
tx.db.Logger.BeforeSQL(log.LogContext{
Ctx: ctx,
SQL: "PREPARE",
})
}
stmt, err := tx.Tx.PrepareContext(ctx, query) stmt, err := tx.Tx.PrepareContext(ctx, query)
if tx.db.Logger != nil {
tx.db.Logger.AfterSQL(log.LogContext{
Ctx: ctx,
SQL: "PREPARE",
ExecuteTime: time.Now().Sub(start),
Err: err,
})
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &Stmt{stmt, tx.db, names}, nil return &Stmt{stmt, tx.db, names, query}, nil
} }
func (tx *Tx) Prepare(query string) (*Stmt, error) { func (tx *Tx) Prepare(query string) (*Stmt, error) {

View File

@ -45,7 +45,6 @@ type Dialect interface {
IsReserved(string) bool IsReserved(string) bool
Quoter() schemas.Quoter Quoter() schemas.Quoter
RollBackStr() string
AutoIncrStr() string AutoIncrStr() string
SupportInsertMany() bool SupportInsertMany() bool
@ -178,10 +177,6 @@ func (b *Base) DataSourceName() string {
return b.dataSourceName return b.dataSourceName
} }
func (db *Base) RollBackStr() string {
return "ROLL BACK"
}
func (db *Base) SupportDropIfExists() bool { func (db *Base) SupportDropIfExists() bool {
return true return true
} }

View File

@ -4,6 +4,12 @@
package xorm package xorm
import (
"time"
"xorm.io/xorm/log"
)
// Begin a transaction // Begin a transaction
func (session *Session) Begin() error { func (session *Session) Begin() error {
if session.isAutoCommit { if session.isAutoCommit {
@ -14,6 +20,7 @@ func (session *Session) Begin() error {
session.isAutoCommit = false session.isAutoCommit = false
session.isCommitedOrRollbacked = false session.isCommitedOrRollbacked = false
session.tx = tx session.tx = tx
session.saveLastSQL("BEGIN TRANSACTION") session.saveLastSQL("BEGIN TRANSACTION")
} }
return nil return nil
@ -22,10 +29,23 @@ func (session *Session) Begin() error {
// Rollback When using transaction, you can rollback if any error // Rollback When using transaction, you can rollback if any error
func (session *Session) Rollback() error { func (session *Session) Rollback() error {
if !session.isAutoCommit && !session.isCommitedOrRollbacked { if !session.isAutoCommit && !session.isCommitedOrRollbacked {
session.saveLastSQL(session.engine.dialect.RollBackStr()) session.saveLastSQL("ROLL BACK")
session.isCommitedOrRollbacked = true session.isCommitedOrRollbacked = true
session.isAutoCommit = true session.isAutoCommit = true
return session.tx.Rollback()
start := time.Now()
session.engine.logger.BeforeSQL(log.LogContext{
Ctx: session.ctx,
SQL: "ROLL BACK",
})
err := session.tx.Rollback()
session.engine.logger.AfterSQL(log.LogContext{
Ctx: session.ctx,
SQL: "ROLL BACK",
ExecuteTime: time.Now().Sub(start),
Err: err,
})
return err
} }
return nil return nil
} }
@ -36,8 +56,23 @@ func (session *Session) Commit() error {
session.saveLastSQL("COMMIT") session.saveLastSQL("COMMIT")
session.isCommitedOrRollbacked = true session.isCommitedOrRollbacked = true
session.isAutoCommit = true session.isAutoCommit = true
var err error
if err = session.tx.Commit(); err == nil { start := time.Now()
session.engine.logger.BeforeSQL(log.LogContext{
Ctx: session.ctx,
SQL: "COMMIT",
})
err := session.tx.Commit()
if err != nil {
return err
}
session.engine.logger.AfterSQL(log.LogContext{
Ctx: session.ctx,
SQL: "COMMIT",
ExecuteTime: time.Now().Sub(start),
Err: err,
})
// handle processors after tx committed // handle processors after tx committed
closureCallFunc := func(closuresPtr *[]func(interface{}), bean interface{}) { closureCallFunc := func(closuresPtr *[]func(interface{}), bean interface{}) {
if closuresPtr != nil { if closuresPtr != nil {
@ -77,7 +112,5 @@ func (session *Session) Commit() error {
cleanUpFunc(&session.afterUpdateBeans) cleanUpFunc(&session.afterUpdateBeans)
cleanUpFunc(&session.afterDeleteBeans) cleanUpFunc(&session.afterDeleteBeans)
} }
return err
}
return nil return nil
} }