Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Customizable LogSQLFunc #104

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ type (
// while result and err refer to the result of the execution.
ExecLogFunc func(ctx context.Context, t time.Duration, sql string, result sql.Result, err error)

// LogSQLFunc returns the SQL statement for the given query with parameters being replaced with the actual values.
// It is called once for each call to ExecLogFunc(), QueryLogFunc(), LogFunc(), & PerfFunc()
// The result is only for logging purpose and should not be used to execute.
LogSQLFunc func(q *Query) string

// BuilderFunc creates a Builder instance using the given DB instance and Executor.
BuilderFunc func(*DB, Executor) Builder

Expand All @@ -59,6 +64,11 @@ type (
QueryLogFunc QueryLogFunc
// ExecLogFunc is called each time when a SQL statement is executed.
ExecLogFunc ExecLogFunc
// LogSQLFunc returns the SQL statement for the given query with parameters being replaced with the actual values.
// It is called once for each call to ExecLogFunc(), QueryLogFunc(), LogFunc(), & PerfFunc()
// The result is only for logging purpose and should not be used to execute.
// DefaultLogSQLFunc() is used when this is left nil.
LogSQLFunc LogSQLFunc

sqlDB *sql.DB
driverName string
Expand Down
39 changes: 37 additions & 2 deletions query.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"context"
"database/sql"
"database/sql/driver"
"encoding/hex"
"errors"
"fmt"
"strings"
Expand Down Expand Up @@ -57,6 +58,8 @@ type Query struct {
QueryLogFunc QueryLogFunc
// ExecLogFunc is called each time when a SQL statement is executed.
ExecLogFunc ExecLogFunc
// LogSQLFunc is called once for each call to ExecLogFunc(), QueryLogFunc(), LogFunc(), & PerfFunc()
LogSQLFunc LogSQLFunc
}

// NewQuery creates a new Query with the given SQL statement.
Expand All @@ -74,6 +77,7 @@ func NewQuery(db *DB, executor Executor, sql string) *Query {
PerfFunc: db.PerfFunc,
QueryLogFunc: db.QueryLogFunc,
ExecLogFunc: db.ExecLogFunc,
LogSQLFunc: db.LogSQLFunc,
}
}

Expand All @@ -95,9 +99,18 @@ func (q *Query) WithContext(ctx context.Context) *Query {
return q
}

// logSQL returns the SQL statement with parameters being replaced with the actual values.
// The result is only for logging purpose and should not be used to execute.
func (q *Query) logSQL() string {

if q.LogSQLFunc != nil {
return q.LogSQLFunc(q)
}

return DefaultLogSQLFunc(q)
}

// DefaultLogSQLFunc() returns the SQL statement for the given query with parameters being replaced with the actual values.
// It is called once for each call to ExecLogFunc, QueryLogFunc, LogFunc, & PerfFunc.
func DefaultLogSQLFunc(q *Query) string {
s := q.sql
for k, v := range q.params {
if valuer, ok := v.(driver.Valuer); ok && valuer != nil {
Expand All @@ -116,6 +129,28 @@ func (q *Query) logSQL() string {
return s
}

// Bin2HexLogSQLFunc() returns the SQL statement for the given query with parameters being replaced with the actual values.
// It differs from DefaultLogSQLFunc() only in the respect that it prints []byte values in hexadecimal.
// It is called once for each call to ExecLogFunc, QueryLogFunc, LogFunc, & PerfFunc.
func Bin2HexLogSQLFunc(q *Query) string {
s := q.sql
for k, v := range q.params {
if valuer, ok := v.(driver.Valuer); ok && valuer != nil {
v, _ = valuer.Value()
}
var sv string
if str, ok := v.(string); ok {
sv = "'" + strings.Replace(str, "'", "''", -1) + "'"
} else if bs, ok := v.([]byte); ok {
sv = "0x" + hex.EncodeToString(bs)
} else {
sv = fmt.Sprintf("%v", v)
}
s = strings.Replace(s, "{:"+k+"}", sv, -1)
}
return s
}

// Params returns the parameters to be bound to the SQL statement represented by this query.
func (q *Query) Params() Params {
return q.params
Expand Down