forked from go-reform/reform
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdb.go
More file actions
129 lines (112 loc) · 3.51 KB
/
db.go
File metadata and controls
129 lines (112 loc) · 3.51 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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package reform
import (
"context"
"database/sql"
"time"
)
// DBInterface is a subset of *sql.DB used by reform.
// Can be used together with NewDBFromInterface for easier integration with existing code or for passing test doubles.
//
// It may grow and shrink over time to include only needed *sql.DB methods,
// and is excluded from SemVer compatibility guarantees.
type DBInterface interface {
DBTXContext
BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error)
// Deprecated: do not use, it will be removed in v1.6.
DBTX
// Deprecated: do not use, it will be removed in v1.6.
Begin() (*sql.Tx, error)
}
// check interface
var _ DBInterface = (*sql.DB)(nil)
// DB represents a connection to SQL database.
type DB struct {
*Querier
db DBInterface
}
// NewDB creates new DB object for given SQL database connection.
// Logger can be nil.
func NewDB(db *sql.DB, dialect Dialect, logger Logger) *DB {
return NewDBFromInterface(db, dialect, logger)
}
// NewDBFromInterface creates new DB object for given DBInterface.
// Can be used for easier integration with existing code or for passing test doubles.
// Logger can be nil.
func NewDBFromInterface(db DBInterface, dialect Dialect, logger Logger) *DB {
return &DB{
Querier: newQuerier(context.Background(), db, "", dialect, logger, false, nil, nil),
db: db,
}
}
// DBInterface returns DBInterface associated with a given DB object.
func (db *DB) DBInterface() DBInterface {
return db.db
}
// AddSlaves adds slave *sql.DB connections.
func (db *DB) AddSlaves(slaves ...*sql.DB) {
for _, s := range slaves {
db.slaves = append(db.slaves, newQuerier(context.Background(), s, "", db.Dialect, db.Logger, false, nil, nil))
}
}
// Begin starts transaction with Querier's context and default options.
func (db *DB) Begin() (*TX, error) {
return db.BeginTx(db.Querier.ctx, nil)
}
// BeginTx starts transaction with given context and options (can be nil).
func (db *DB) BeginTx(ctx context.Context, opts *sql.TxOptions) (*TX, error) {
db.logBefore("BEGIN", nil)
start := time.Now()
tx, err := db.db.BeginTx(ctx, opts)
db.logAfter("BEGIN", nil, time.Since(start), err)
if err != nil {
return nil, err
}
return newTX(ctx, tx, db.Dialect, db.Logger), nil
}
// InTransaction wraps function execution in transaction with Querier's context and default options,
// rolling back it in case of error or panic, committing otherwise.
func (db *DB) InTransaction(f func(t *TX) error) error {
return db.InTransactionContext(db.Querier.ctx, nil, f)
}
// InTransactionContext wraps function execution in transaction with given context and options (can be nil),
// rolling back it in case of error or panic, committing otherwise.
func (db *DB) InTransactionContext(ctx context.Context, opts *sql.TxOptions, f func(t *TX) error) error {
tx, err := db.BeginTx(ctx, opts)
if err != nil {
return err
}
var committed bool
defer func() {
if !committed {
// always return f() or Commit() error, not possible Rollback() error
_ = tx.Rollback()
}
}()
tx.Querier.onCommitCalls = tx.Querier.onCommitCalls[:0]
err = f(tx)
if err == nil {
err = tx.Commit()
}
if err == nil {
committed = true
for _, call := range tx.Querier.onCommitCalls {
if e := call(); e != nil {
return e
}
}
}
return err
}
// MasterQuerier returns Querier that uses only master connection.
func (db *DB) MasterQuerier() *Querier {
q := db.clone()
q.inTransaction = false
q.slaves = nil
q.onCommitCalls = nil
return q
}
// check interfaces
var (
_ DBTX = (*DB)(nil)
_ DBTXContext = (*DB)(nil)
)