Documentation ¶
Overview ¶
Package logsql provides wrapper for database/sql with Logger interface. To create new logged *sql.DB use either NewConnectorFromDriver or NewConnectorFromConnector to retrieve driver.Connector and pass it to sql.OpenDB.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrNilLogHandler = errors.New("log handler is nil") ErrUnsupportedByDriver = errors.New("unsupported by underlying driver") )
Functions ¶
func NewConnectorFromConnector ¶
NewConnectorFromConnector returns new driver.Connector based on existing connector. Panics if Config.Validate returns non nil error
func NewConnectorFromDriver ¶
NewConnectorFromDriver returns new driver.Connector based on an existing driver and DSN. Panics if Config.Validate returns non-nil error
func NoOpQueryErrReplacer ¶
NoOpQueryErrReplacer will not replace anything
Types ¶
type Config ¶
type Config struct { Qer QueryErrReplacer LogHandler Logger }
Config must contain Logger for logging sql.DB events. If Qer is nil, NoOpQueryErrReplacer will be used
type Logger ¶
type Logger interface { Connect(ctx context.Context, err error, dt time.Duration) ConnClose(ctx context.Context, err error, dt time.Duration) TxBegin(ctx context.Context, err error, dt time.Duration) TxCommit(ctx context.Context, err error, dt time.Duration) TxRollback(ctx context.Context, err error, dt time.Duration) Exec(ctx context.Context, query string, args []driver.NamedValue, replacedErr error, err error, dt time.Duration) Query(ctx context.Context, query string, args []driver.NamedValue, replacedErr error, err error, dt time.Duration) Ping(ctx context.Context, err error, dt time.Duration) RowsClose(ctx context.Context, err error, dt time.Duration) // RowsNext can receive [io.EOF] as err in the end of scanning RowsNext(ctx context.Context, dest []driver.Value, err error, dt time.Duration) PrepareStatement(ctx context.Context, query string, err error, dt time.Duration) ClosePreparedStatement(ctx context.Context, query string, err error, dt time.Duration) ExecPreparedStatement(ctx context.Context, query string, args []driver.NamedValue, replacedErr error, err error, dt time.Duration) QueryPreparedStatement(ctx context.Context, query string, args []driver.NamedValue, replacedErr error, err error, dt time.Duration) }
Logger is used to log specific cases internally in [sql.DB]
type QueryErrReplacer ¶
QueryErrReplacer can be used for replacing actual errors from a driver ("Query", "QueryContext", "Exec", "ExecContext"). QueryErrReplacer must return non-nil error if new error should substitute the original one, nil otherwise. Such substitution is useful in case of checking raw SQL errors.
Example of handling SQL specific 42P07 error:
- SQL driver query error which underlying driver usually returns type SqlError struct { Code string } func (e SqlError) Error() string { return e.Code }
- Your own specific error var errDuplicateTable = errors.New("duplicate table")
3. QueryErrReplacer function. If err is not a SqlError, don't substitute anything. If it is expected error 42P07 return your own errDuplicateTable
func myErrReplacer(err error) error { var pgErr SqlError if !errors.As(err, &pgErr) { return nil } switch pgErr.Code { case "42P07": return errDuplicateTable default: return nil } }
4. Handling. Thus, your own error can be handled in a specific way. Moreover, if Logger is properly configured, no ERROR entry will appear in logs because this error was expected
err := db.ExecContext(ctx, query) if err != nil { if errors.Is(err, errDuplicateTable) { // ... } return err }