-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfactory.go
More file actions
97 lines (81 loc) · 2.3 KB
/
factory.go
File metadata and controls
97 lines (81 loc) · 2.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package sqlslog
import (
"context"
"database/sql"
"database/sql/driver"
"log/slog"
)
type Factory struct {
options *options
driverName string
dsn string
handler slog.Handler
logger *slog.Logger
}
func New(driverName, dsn string, opts ...Option) *Factory {
options := newOptions(driverName, opts...)
return &Factory{
driverName: driverName,
dsn: dsn,
options: options,
handler: options.SlogOptions.handler,
}
}
func (f *Factory) newHandler() slog.Handler {
o := f.options.SlogOptions
return o.handlerFunc(o.logWriter, &o.HandlerOptions)
}
func (f *Factory) Handler() slog.Handler {
if f.handler == nil {
f.handler = f.newHandler()
}
return f.handler
}
func (f *Factory) Logger() *slog.Logger {
if f.logger == nil {
f.logger = slog.New(f.Handler())
}
return f.logger
}
func (f *Factory) Open(ctx context.Context) (*sql.DB, error) {
stepLogger := newStepLogger(f.Logger(), f.options.stepLoggerOptions)
return open(ctx, f.driverName, f.dsn, stepLogger, f.options)
}
func open(ctx context.Context, driverName, dsn string, logger *stepLogger, options *options) (*sql.DB, error) {
lg := logger.With(
slog.String("driver", driverName),
slog.String("dsn", dsn),
)
var db *sql.DB
err := ignoreAttr(lg.Step(ctx, &options.Open, func() (*slog.Attr, error) {
var err error
db, err = openWithDriver(driverName, dsn, logger, options.DriverOptions)
return nil, err
}))
if err != nil {
return nil, err
}
return db, nil
}
func openWithDriver(driverName, dsn string, logger *stepLogger, driverOptions *driverOptions) (*sql.DB, error) {
db, err := sql.Open(driverName, dsn)
if err != nil {
return nil, err
}
// This db is not used directly, but it is used to get the driver.
drv := wrapDriver(db.Driver(), logger, driverOptions)
return openWithWrappedDriver(drv, dsn, logger, driverOptions)
}
func openWithWrappedDriver(drv driver.Driver, dsn string, logger *stepLogger, driverOptions *driverOptions) (*sql.DB, error) {
var origConnector driver.Connector
if dc, ok := drv.(driver.DriverContext); ok {
connector, err := dc.OpenConnector(dsn)
if err != nil {
return nil, err
}
origConnector = connector
} else {
origConnector = &dsnConnector{dsn: dsn, driver: drv}
}
return sql.OpenDB(wrapConnector(origConnector, logger, driverOptions.ConnectorOptions)), nil
}