Fix affected rows for Scan, change affected rows count for row/rows to '-', close #3532

This commit is contained in:
Jinzhu 2020-09-27 12:25:38 +08:00
parent ba253982bf
commit 9eec6ae066
5 changed files with 51 additions and 10 deletions

View File

@ -74,7 +74,6 @@ func (cs *callbacks) Raw() *processor {
func (p *processor) Execute(db *DB) { func (p *processor) Execute(db *DB) {
curTime := time.Now() curTime := time.Now()
stmt := db.Statement stmt := db.Statement
db.RowsAffected = 0
if stmt.Model == nil { if stmt.Model == nil {
stmt.Model = stmt.Dest stmt.Model = stmt.Dest

View File

@ -16,6 +16,8 @@ func RowQuery(db *gorm.DB) {
} else { } else {
db.Statement.Dest = db.Statement.ConnPool.QueryRowContext(db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...) db.Statement.Dest = db.Statement.ConnPool.QueryRowContext(db.Statement.Context, db.Statement.SQL.String(), db.Statement.Vars...)
} }
db.RowsAffected = -1
} }
} }
} }

View File

@ -8,6 +8,7 @@ import (
"strings" "strings"
"gorm.io/gorm/clause" "gorm.io/gorm/clause"
"gorm.io/gorm/logger"
"gorm.io/gorm/schema" "gorm.io/gorm/schema"
"gorm.io/gorm/utils" "gorm.io/gorm/utils"
) )
@ -353,7 +354,9 @@ func (db *DB) Rows() (*sql.Rows, error) {
// Scan scan value to a struct // Scan scan value to a struct
func (db *DB) Scan(dest interface{}) (tx *DB) { func (db *DB) Scan(dest interface{}) (tx *DB) {
currentLogger, newLogger := db.Logger, logger.Recorder.New()
tx = db.getInstance() tx = db.getInstance()
tx.Logger = newLogger
if rows, err := tx.Rows(); err != nil { if rows, err := tx.Rows(); err != nil {
tx.AddError(err) tx.AddError(err)
} else { } else {
@ -362,6 +365,11 @@ func (db *DB) Scan(dest interface{}) (tx *DB) {
tx.ScanRows(rows, dest) tx.ScanRows(rows, dest)
} }
} }
currentLogger.Trace(tx.Statement.Context, newLogger.BeginAt, func() (string, int64) {
return newLogger.SQL, tx.RowsAffected
}, tx.Error)
tx.Logger = currentLogger
return return
} }

View File

@ -63,6 +63,7 @@ var (
LogLevel: Warn, LogLevel: Warn,
Colorful: true, Colorful: true,
}) })
Recorder = traceRecorder{Interface: Default}
) )
func New(writer Writer, config Config) Interface { func New(writer Writer, config Config) Interface {
@ -70,18 +71,18 @@ func New(writer Writer, config Config) Interface {
infoStr = "%s\n[info] " infoStr = "%s\n[info] "
warnStr = "%s\n[warn] " warnStr = "%s\n[warn] "
errStr = "%s\n[error] " errStr = "%s\n[error] "
traceStr = "%s\n[%.3fms] [rows:%d] %s" traceStr = "%s\n[%.3fms] [rows:%v] %s"
traceWarnStr = "%s\n[%.3fms] [rows:%d] %s" traceWarnStr = "%s\n[%.3fms] [rows:%v] %s"
traceErrStr = "%s %s\n[%.3fms] [rows:%d] %s" traceErrStr = "%s %s\n[%.3fms] [rows:%v] %s"
) )
if config.Colorful { if config.Colorful {
infoStr = Green + "%s\n" + Reset + Green + "[info] " + Reset infoStr = Green + "%s\n" + Reset + Green + "[info] " + Reset
warnStr = BlueBold + "%s\n" + Reset + Magenta + "[warn] " + Reset warnStr = BlueBold + "%s\n" + Reset + Magenta + "[warn] " + Reset
errStr = Magenta + "%s\n" + Reset + Red + "[error] " + Reset errStr = Magenta + "%s\n" + Reset + Red + "[error] " + Reset
traceStr = Green + "%s\n" + Reset + Yellow + "[%.3fms] " + BlueBold + "[rows:%d]" + Reset + " %s" traceStr = Green + "%s\n" + Reset + Yellow + "[%.3fms] " + BlueBold + "[rows:%v]" + Reset + " %s"
traceWarnStr = Green + "%s\n" + Reset + RedBold + "[%.3fms] " + Yellow + "[rows:%d]" + Magenta + " %s" + Reset traceWarnStr = Green + "%s\n" + Reset + RedBold + "[%.3fms] " + Yellow + "[rows:%v]" + Magenta + " %s" + Reset
traceErrStr = RedBold + "%s " + MagentaBold + "%s\n" + Reset + Yellow + "[%.3fms] " + BlueBold + "[rows:%d]" + Reset + " %s" traceErrStr = RedBold + "%s " + MagentaBold + "%s\n" + Reset + Yellow + "[%.3fms] " + BlueBold + "[rows:%v]" + Reset + " %s"
} }
return &logger{ return &logger{
@ -138,13 +139,43 @@ func (l logger) Trace(ctx context.Context, begin time.Time, fc func() (string, i
switch { switch {
case err != nil && l.LogLevel >= Error: case err != nil && l.LogLevel >= Error:
sql, rows := fc() sql, rows := fc()
if rows == -1 {
l.Printf(l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, "-", sql)
} else {
l.Printf(l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, rows, sql) l.Printf(l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, rows, sql)
}
case elapsed > l.SlowThreshold && l.SlowThreshold != 0 && l.LogLevel >= Warn: case elapsed > l.SlowThreshold && l.SlowThreshold != 0 && l.LogLevel >= Warn:
sql, rows := fc() sql, rows := fc()
if rows == -1 {
l.Printf(l.traceWarnStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, "-", sql)
} else {
l.Printf(l.traceWarnStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, rows, sql) l.Printf(l.traceWarnStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, rows, sql)
}
case l.LogLevel >= Info: case l.LogLevel >= Info:
sql, rows := fc() sql, rows := fc()
if rows == -1 {
l.Printf(l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, "-", sql)
} else {
l.Printf(l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, rows, sql) l.Printf(l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, rows, sql)
} }
} }
}
}
type traceRecorder struct {
Interface
BeginAt time.Time
SQL string
RowsAffected int64
Err error
}
func (l traceRecorder) New() *traceRecorder {
return &traceRecorder{Interface: l.Interface}
}
func (l *traceRecorder) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
l.BeginAt = begin
l.SQL, l.RowsAffected = fc()
l.Err = err
} }

View File

@ -52,6 +52,7 @@ func scanIntoMap(mapValue map[string]interface{}, values []interface{}, columns
func Scan(rows *sql.Rows, db *DB, initialized bool) { func Scan(rows *sql.Rows, db *DB, initialized bool) {
columns, _ := rows.Columns() columns, _ := rows.Columns()
values := make([]interface{}, len(columns)) values := make([]interface{}, len(columns))
db.RowsAffected = 0
switch dest := db.Statement.Dest.(type) { switch dest := db.Statement.Dest.(type) {
case map[string]interface{}, *map[string]interface{}: case map[string]interface{}, *map[string]interface{}: