-
Notifications
You must be signed in to change notification settings - Fork 0
/
db.go
176 lines (147 loc) · 3.47 KB
/
db.go
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
// Copyright © 2019 Alexandre KOVAC <contact@kovacou.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
package database
import (
"database/sql/driver"
"log"
"sync"
// Loading mysql driver by default.
_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
"github.com/kovacou/go-database/builder"
)
// db is a wrapper around sqlx.DB.
type db struct {
id uint
dbx **sqlx.DB
tx *sqlx.Tx
m *sync.Mutex
logOut *log.Logger
logErr *log.Logger
err error
ctx *ctx
env Environment
profiler *profiler
}
// Copy the current connection.
func (conn *db) Copy() Connection {
return conn.copy()
}
// copy the current connection.
func (conn *db) copy() *db {
return &db{
id: conn.id,
dbx: conn.dbx,
m: conn.m,
logOut: conn.logOut,
logErr: conn.logErr,
ctx: conn.ctx,
env: conn.env,
profiler: conn.profiler,
}
}
// SetLogger set a new logger to the db.
func (conn *db) SetLogger(out *log.Logger, err *log.Logger) {
if out != nil {
conn.logOut = out
}
if err != nil {
conn.logErr = err
}
}
// hasDebug says if the connection have debug mode enable.
func (conn *db) hasDebug() bool {
return Debug || conn.env.Debug
}
// hasVerbose says if the connection have verbose mode enable.
func (conn *db) hasVerbose() bool {
return Verbose || conn.env.Verbose
}
// hasProfiling says if the connection have a profiler attached.
func (conn *db) hasProfiling() bool {
return conn.profiler != nil
}
// DB return the unwrapped sqlx.DB.
func (conn *db) DB() *sqlx.DB {
conn.Connect()
return *conn.dbx
}
// Close closes the database and prevents new queries from starting.
func (conn *db) Close() (err error) {
if conn.ctx != nil {
conn.ctx.Done()
}
if dbx := *conn.dbx; dbx != nil {
err = dbx.Close()
}
return
}
// Ping verifies a connection to the database is still alive,
// establishing a connection if necessary.
func (conn *db) Ping() error {
if err := conn.Connect(); err != nil {
return err
}
if dbx := (*conn.dbx); dbx != nil {
return dbx.Ping()
}
return driver.ErrBadConn
}
// MustPing call Ping and panic if there is an error.
func (conn *db) MustPing() {
if err := conn.Ping(); err != nil {
panic(err.Error())
}
}
// Connect to a database and verify with a ping.
func (conn *db) Connect() (err error) {
if (*conn.dbx) != nil {
return
}
conn.m.Lock()
if (*conn.dbx) != nil {
conn.m.Unlock()
return
}
*conn.dbx, err = sqlx.Connect(
conn.env.Driver,
conn.env.String(),
)
conn.m.Unlock()
if err != nil {
return
}
dbx := *conn.dbx
dbx.SetMaxIdleConns(conn.env.MaxIdle)
dbx.SetMaxOpenConns(conn.env.MaxOpen)
dbx.SetConnMaxLifetime(conn.env.MaxLifetime)
dbx.SetConnMaxIdleTime(conn.env.MaxLifetime)
if conn.env.ProfilerEnable {
conn.m.Lock()
conn.ctx = newContext(nil)
conn.profiler = newProfiler(conn.env.ProfilerOutput)
conn.m.Unlock()
if conn.hasVerbose() {
conn.logOut.Printf("profiler is running on \033[3;1m%s\033[0m", conn.profiler.DirectoryOutput)
}
}
if conn.hasVerbose() {
conn.logOut.Printf("\033[92;1mconnected ✔\033[0m")
}
return
}
// Tables fetch tables of the current schema
func (conn *db) Tables() (t []string) {
if conn.env.Driver == "mysql" {
_, _ = conn.SelectSlice(builder.NewQuery("SHOW TABLES"), func(v []any) {
t = append(t, string(v[0].([]uint8)))
})
}
return t
}
// LastError return the last error that occured.
func (conn *db) LastError() error {
return conn.err
}