sqlx.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. package db
  2. import (
  3. "context"
  4. "database/sql"
  5. "fmt"
  6. "sync"
  7. // PostgreSQL
  8. _ "github.com/lib/pq"
  9. // MySQL
  10. _ "github.com/go-sql-driver/mysql"
  11. "github.com/jmoiron/sqlx"
  12. )
  13. // DB db
  14. type DB struct {
  15. Driver string
  16. c *sqlx.DB
  17. tx *sqlx.Tx
  18. }
  19. type Tx struct {
  20. tx *sqlx.Tx
  21. }
  22. var (
  23. defaultConfig Option
  24. defaultDb *DB
  25. db *sqlx.DB
  26. once sync.Once
  27. )
  28. // SetDefaultOption default connect option
  29. func SetDefaultOption(opt Option) (err error) {
  30. defaultConfig = opt
  31. defaultDb = &DB{Driver: opt.Driver}
  32. defaultDb.c, err = connect()
  33. return
  34. }
  35. // ReleaseDefault release default connect
  36. func ReleaseDefault() error {
  37. if defaultDb != nil {
  38. if defaultDb.c != nil {
  39. defaultDb.c.Close()
  40. }
  41. }
  42. return nil
  43. }
  44. // New new DB dynamic object
  45. func New(opt Option) (dbx *DB, err error) {
  46. //dbx = &DB{}
  47. dbx.Driver = opt.Driver
  48. dbx.c, err = sqlx.Connect(opt.Driver, opt.DNS)
  49. if err != nil {
  50. return
  51. }
  52. dbx.c.SetMaxOpenConns(opt.MaxOpenConns)
  53. dbx.c.SetMaxIdleConns(opt.MaxIdle)
  54. dbx.c.SetConnMaxLifetime(opt.MaxLifetime)
  55. err = dbx.c.Ping()
  56. return
  57. }
  58. // Release release connect
  59. func Release(dbx *DB) (err error) {
  60. if dbx.c != nil {
  61. err = dbx.c.Close()
  62. }
  63. return
  64. }
  65. func connect() (dbx *sqlx.DB, err error) {
  66. once.Do(func() {
  67. db, err = sqlx.Connect(defaultConfig.Driver, defaultConfig.DNS)
  68. if err == nil {
  69. db.DB.SetMaxOpenConns(defaultConfig.MaxOpenConns)
  70. db.DB.SetMaxIdleConns(defaultConfig.MaxIdle)
  71. db.DB.SetConnMaxLifetime(defaultConfig.MaxLifetime)
  72. err = db.Ping()
  73. }
  74. })
  75. dbx = db
  76. return
  77. }
  78. // Connect connect to database
  79. func (d *DB) Connect() (err error) {
  80. if d.c != nil {
  81. return
  82. }
  83. d.c, err = connect()
  84. return
  85. }
  86. /*
  87. // Close close database connect
  88. func (d *DB) Close() error {
  89. // not use pool
  90. if d.c != nil {
  91. return d.c.Close()
  92. }
  93. return nil
  94. }
  95. // */
  96. // Ping verifies a connection to the database is still alive, establishing a connection if necessary.
  97. func (d *DB) Ping() error {
  98. return d.c.Ping()
  99. }
  100. // PingContext verifies a connection to the database is still alive, establishing a connection if necessary.
  101. func (d *DB) PingContext(ctx context.Context) error {
  102. return d.c.PingContext(ctx)
  103. }
  104. // Stats returns database statistics.
  105. func (d *DB) Stats() sql.DBStats {
  106. return d.c.Stats()
  107. }
  108. // BeginTrans begin trans
  109. func (d *DB) BeginTrans() (err error) {
  110. d.c, err = connect()
  111. if err != nil {
  112. return
  113. }
  114. d.tx = d.c.MustBegin()
  115. return
  116. }
  117. // Trans begin trans
  118. func (d *DB) Trans() (tx *Tx, err error) {
  119. d.c, err = connect()
  120. if err != nil {
  121. return
  122. }
  123. tx.tx = d.c.MustBegin()
  124. return
  125. }
  126. // Commit commit
  127. func (d *DB) Commit() error {
  128. return d.tx.Commit()
  129. }
  130. // Rollback rollback
  131. func (d *DB) Rollback() error {
  132. return d.tx.Rollback()
  133. }
  134. // TransNamedExec trans execute
  135. func (d *DB) TransExec(query string, args ...interface{}) (LastInsertId, RowsAffected int64, err error) {
  136. rs, err := d.tx.Exec(query, args...)
  137. if err != nil {
  138. return
  139. }
  140. RowsAffected, _ = rs.RowsAffected()
  141. LastInsertId, _ = rs.LastInsertId()
  142. return
  143. }
  144. // TransNamedExec trans execute, named bindvars
  145. func (d *DB) TransNamedExec(query string, args interface{}) (LastInsertId, RowsAffected int64, err error) {
  146. rs, err := d.tx.NamedExec(query, args)
  147. if err != nil {
  148. return
  149. }
  150. RowsAffected, _ = rs.RowsAffected()
  151. LastInsertId, _ = rs.LastInsertId()
  152. return
  153. }
  154. // TransGet trans get row
  155. func (d *DB) TransGet(dest interface{}, query string, args ...interface{}) (err error) {
  156. err = d.tx.Get(dest, query, args...)
  157. return
  158. }
  159. // TransNamedGet trans get row, named bindvars
  160. func (d *DB) TransNamedGet(dest interface{}, query string, args interface{}) (err error) {
  161. var nstmt *sqlx.NamedStmt
  162. nstmt, err = d.tx.PrepareNamed(query)
  163. if err != nil {
  164. return
  165. }
  166. defer nstmt.Close()
  167. err = nstmt.Get(dest, args)
  168. return
  169. }
  170. // TransSelect trans get rows
  171. func (d *DB) TransSelect(dest interface{}, query string, args ...interface{}) (err error) {
  172. err = d.tx.Select(dest, query, args...)
  173. return
  174. }
  175. // Get get one
  176. func (d *DB) Get(dest interface{}, query string, args ...interface{}) (err error) {
  177. err = d.Connect()
  178. if err != nil {
  179. return
  180. }
  181. //defer d.Close()
  182. err = d.c.Get(dest, query, args...)
  183. return
  184. }
  185. // Get get one, named bindvars
  186. func (d *DB) NamedGet(dest interface{}, query string, args interface{}) (err error) {
  187. err = d.Connect()
  188. if err != nil {
  189. return
  190. }
  191. //defer d.Close()
  192. nstmt, err := d.c.PrepareNamed(query)
  193. if err != nil {
  194. return
  195. }
  196. defer nstmt.Close()
  197. err = nstmt.Get(dest, args)
  198. return
  199. }
  200. // Select select rows
  201. func (d *DB) Select(dest interface{}, query string, args ...interface{}) error {
  202. err := d.Connect()
  203. if err != nil {
  204. return err
  205. }
  206. //defer d.Close()
  207. err = d.c.Select(dest, query, args...)
  208. return err
  209. }
  210. // NamedSelect select rows, named bindvars
  211. func (d *DB) NamedSelect(dest interface{}, query string, args interface{}) (err error) {
  212. err = d.Connect()
  213. if err != nil {
  214. return err
  215. }
  216. //defer d.Close()
  217. nstmt, err := d.c.PrepareNamed(query)
  218. if err != nil {
  219. return err
  220. }
  221. defer nstmt.Close()
  222. err = nstmt.Select(dest, args)
  223. return err
  224. }
  225. // Exec exec
  226. func (d *DB) Exec(query string, args ...interface{}) (LastInsertId, RowsAffected int64, err error) {
  227. err = d.Connect()
  228. if err != nil {
  229. return
  230. }
  231. //defer d.Close()
  232. var rs sql.Result
  233. rs, err = d.c.Exec(query, args...)
  234. if err != nil {
  235. return
  236. }
  237. LastInsertId, _ = rs.LastInsertId()
  238. RowsAffected, _ = rs.RowsAffected()
  239. return
  240. }
  241. // NamedExec exec, named bindvars
  242. func (d *DB) NamedExec(query string, args interface{}) (LastInsertId, RowsAffected int64, err error) {
  243. err = d.Connect()
  244. if err != nil {
  245. return
  246. }
  247. //defer d.Close()
  248. var rs sql.Result
  249. rs, err = d.c.NamedExec(query, args)
  250. if err != nil {
  251. return
  252. }
  253. LastInsertId, _ = rs.LastInsertId()
  254. RowsAffected, _ = rs.RowsAffected()
  255. return
  256. }
  257. // Limit MySQL/PostgreSQL limit
  258. func (d *DB) Limit(page, pagesize int) string {
  259. // MySQL limit n, size
  260. if d.Driver == DriverMySQL {
  261. return fmt.Sprintf(" LIMIT %d, %d", (page-1)*pagesize, pagesize)
  262. }
  263. // // PostgreSQL limit size offset n
  264. return fmt.Sprintf(" LIMIT %d OFFSET %d", pagesize, (page-1)*pagesize)
  265. }
  266. // Commit commit
  267. func (t *Tx) Commit() error {
  268. return t.tx.Commit()
  269. }
  270. // Rollback rollback
  271. func (t *Tx) Rollback() error {
  272. return t.tx.Rollback()
  273. }
  274. // TransNamedExec trans execute
  275. func (t *Tx) TransExec(query string, args ...interface{}) (LastInsertId, RowsAffected int64, err error) {
  276. rs, err := t.tx.Exec(query, args...)
  277. if err != nil {
  278. return
  279. }
  280. RowsAffected, _ = rs.RowsAffected()
  281. LastInsertId, _ = rs.LastInsertId()
  282. return
  283. }
  284. // TransNamedExec trans execute, named bindvars
  285. func (t *Tx) TransNamedExec(query string, args interface{}) (LastInsertId, RowsAffected int64, err error) {
  286. rs, err := t.tx.NamedExec(query, args)
  287. if err != nil {
  288. return
  289. }
  290. RowsAffected, _ = rs.RowsAffected()
  291. LastInsertId, _ = rs.LastInsertId()
  292. return
  293. }
  294. // TransGet trans get row
  295. func (t *Tx) TransGet(dest interface{}, query string, args ...interface{}) (err error) {
  296. err = t.tx.Get(dest, query, args...)
  297. return
  298. }
  299. // TransNamedGet trans get row, named bindvars
  300. func (t *Tx) TransNamedGet(dest interface{}, query string, args interface{}) (err error) {
  301. var nstmt *sqlx.NamedStmt
  302. nstmt, err = t.tx.PrepareNamed(query)
  303. if err != nil {
  304. return
  305. }
  306. defer nstmt.Close()
  307. err = nstmt.Get(dest, args)
  308. return
  309. }
  310. // TransSelect trans get rows
  311. func (t *Tx) TransSelect(dest interface{}, query string, args ...interface{}) (err error) {
  312. err = t.tx.Select(dest, query, args...)
  313. return
  314. }
  315. // Ping verifies a connection to the database is still alive, establishing a connection if necessary.
  316. func Ping() error {
  317. return defaultDb.Ping()
  318. }
  319. // PingContext verifies a connection to the database is still alive, establishing a connection if necessary.
  320. func PingContext(ctx context.Context) error {
  321. return defaultDb.PingContext(ctx)
  322. }
  323. /*
  324. // Close close database connect
  325. func Close() error {
  326. return defaultDb.Close()
  327. }
  328. // */
  329. // Stats returns database statistics.
  330. func Stats() sql.DBStats {
  331. return defaultDb.Stats()
  332. }
  333. // BeginTrans begin trans
  334. func BeginTrans() (tx *Tx, err error) {
  335. return defaultDb.Trans()
  336. }
  337. // Get get one
  338. func Get(dest interface{}, query string, args ...interface{}) error {
  339. return defaultDb.Get(dest, query, args...)
  340. }
  341. // Get get one, named bindvars
  342. func NamedGet(dest interface{}, query string, args interface{}) (err error) {
  343. return defaultDb.NamedGet(dest, query, args)
  344. }
  345. // Select select rows
  346. func Select(dest interface{}, query string, args ...interface{}) error {
  347. return defaultDb.Select(dest, query, args...)
  348. }
  349. // NamedSelect select rows, named bindvars
  350. func NamedSelect(dest interface{}, query string, args interface{}) (err error) {
  351. return defaultDb.NamedSelect(dest, query, args)
  352. }
  353. // Exec execute
  354. func Exec(query string, args ...interface{}) (LastInsertId, RowsAffected int64, err error) {
  355. return defaultDb.Exec(query, args...)
  356. }
  357. // NamedExec exec, named bindvars
  358. func NamedExec(query string, args interface{}) (LastInsertId, RowsAffected int64, err error) {
  359. return defaultDb.NamedExec(query, args)
  360. }
  361. // Limit MySQL/PostgreSQL limit
  362. func Limit(page, pagesize int) string {
  363. return defaultDb.Limit(page, pagesize)
  364. }