db.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. package util
  2. import (
  3. "database/sql"
  4. "errors"
  5. "fmt"
  6. "sync"
  7. "time"
  8. // mysql
  9. _ "github.com/go-sql-driver/mysql"
  10. "github.com/jmoiron/sqlx"
  11. )
  12. const (
  13. // DBErrCodeOK ok
  14. DBErrCodeOK = 0
  15. // DBErrCodeException exception
  16. DBErrCodeException = 1
  17. // DBErrCodeExists exists
  18. DBErrCodeExists = 2
  19. // DBErrCodeNotFound not found
  20. DBErrCodeNotFound = 3
  21. // DBErrCodeAuthorized authorized
  22. DBErrCodeAuthorized = 4
  23. // DBErrCodeNotConnect connect error
  24. DBErrCodeNotConnect = 5
  25. )
  26. // DbConfig config
  27. type DbConfig struct {
  28. Driver string
  29. DNS string
  30. MaxOpenConns int
  31. MaxIdle int
  32. MaxLifetime time.Duration
  33. }
  34. // DbReply db exec return insert/update/delete
  35. type DbReply struct {
  36. OK bool
  37. Err error
  38. LastErr error
  39. ErrCode int
  40. LastID int64
  41. RowsAffected int64
  42. }
  43. // DbReplyToReply db reply to respinse
  44. func DbReplyToReply(reply DbReply) *ReplyData {
  45. status := ErrOk
  46. if !reply.OK {
  47. switch reply.ErrCode {
  48. case DBErrCodeException:
  49. status = ErrException
  50. case DBErrCodeExists:
  51. status = ErrDataExists
  52. case DBErrCodeNotFound:
  53. status = ErrDataNotFound
  54. case DBErrCodeAuthorized:
  55. status = ErrUnAuthorized
  56. case DBErrCodeNotConnect:
  57. status = ErrNotFound
  58. }
  59. return ErrReplyData(status, reply.LastErr.Error())
  60. }
  61. return OkReplyData()
  62. }
  63. var (
  64. config DbConfig
  65. db *sqlx.DB
  66. err error
  67. once sync.Once
  68. )
  69. // DB define
  70. type DB struct {
  71. conn *sqlx.DB
  72. tx *sqlx.Tx
  73. }
  74. // SetDbConfig set
  75. func SetDbConfig(cfg DbConfig) {
  76. config.Driver = cfg.Driver
  77. config.DNS = cfg.DNS
  78. config.MaxOpenConns = cfg.MaxOpenConns
  79. config.MaxIdle = cfg.MaxIdle
  80. config.MaxLifetime = cfg.MaxLifetime * time.Second
  81. }
  82. // ErrSQLNoRows check norows error
  83. func ErrSQLNoRows(err error) bool {
  84. if err == sql.ErrNoRows {
  85. return true
  86. }
  87. return false
  88. }
  89. // DbReplyOk exec ok
  90. func DbReplyOk(rowsAffected, lastID int64) DbReply {
  91. var reply DbReply
  92. reply.OK = true
  93. reply.ErrCode = 0
  94. reply.LastID = lastID
  95. reply.RowsAffected = rowsAffected
  96. return reply
  97. }
  98. // DbReplyFaild exec faild
  99. func DbReplyFaild(errCode int, err, errText error) DbReply {
  100. var reply DbReply
  101. reply.OK = false
  102. reply.ErrCode = errCode
  103. reply.LastID = -1
  104. reply.RowsAffected = -1
  105. reply.Err = err
  106. reply.LastErr = errText
  107. return reply
  108. }
  109. // NewDB new DB object
  110. func NewDB() *DB {
  111. return &DB{}
  112. }
  113. // ReleaseDB free db connect
  114. func ReleaseDB() {
  115. if db != nil {
  116. db.Close()
  117. }
  118. }
  119. // NewConfigDB new DB dynamic object
  120. func NewConfigDB(config DbConfig) (dbx *DB, err error) {
  121. dbx = &DB{}
  122. dbx.conn, err = sqlx.Connect(config.Driver, config.DNS)
  123. if err == nil {
  124. dbx.conn.SetMaxOpenConns(config.MaxOpenConns)
  125. dbx.conn.SetMaxIdleConns(config.MaxIdle)
  126. dbx.conn.SetConnMaxLifetime(config.MaxLifetime)
  127. dbx.conn.Ping()
  128. }
  129. return
  130. }
  131. // ReleaseConfigDB free db connect
  132. func ReleaseConfigDB(dbx *DB) {
  133. if dbx.conn != nil {
  134. dbx.conn.Close()
  135. }
  136. }
  137. func connect() (dbx *sqlx.DB, err error) {
  138. once.Do(func() {
  139. db, err = sqlx.Connect(config.Driver, config.DNS)
  140. if err == nil {
  141. db.DB.SetMaxOpenConns(config.MaxOpenConns)
  142. db.DB.SetMaxIdleConns(config.MaxIdle)
  143. db.DB.SetConnMaxLifetime(config.MaxLifetime)
  144. db.Ping()
  145. }
  146. })
  147. dbx = db
  148. return
  149. }
  150. // Connect connect to database
  151. func (d *DB) Connect() (err error) {
  152. if d.conn != nil {
  153. return
  154. }
  155. d.conn, err = connect()
  156. return
  157. }
  158. // Close close database connect
  159. func (d *DB) Close() {
  160. //d.conn.Close()
  161. }
  162. // BeginTrans begin trans
  163. func (d *DB) BeginTrans() (err error) {
  164. d.conn, err = connect()
  165. if err != nil {
  166. return
  167. }
  168. d.tx = d.conn.MustBegin()
  169. return
  170. }
  171. // Commit commit
  172. func (d *DB) Commit() error {
  173. return d.tx.Commit()
  174. }
  175. // Rollback rollback
  176. func (d *DB) Rollback() error {
  177. return d.tx.Rollback()
  178. }
  179. // TransExec trans execute
  180. func (d *DB) TransExec(query string, args interface{}) (LastInsertId, RowsAffected int64, err error) {
  181. if rs, err := d.tx.NamedExec(query, args); err == nil {
  182. RowsAffected, _ = rs.RowsAffected()
  183. LastInsertId, _ = rs.LastInsertId()
  184. }
  185. return
  186. }
  187. // TransUpdate trans update
  188. func (d *DB) TransUpdate(query string, args interface{}) (reply DbReply) {
  189. var (
  190. err error
  191. rs sql.Result
  192. )
  193. if rs, err = d.tx.NamedExec(query, args); err == nil {
  194. a, _ := rs.RowsAffected()
  195. reply = DbReplyOk(a, 0)
  196. } else {
  197. reply = DbReplyFaild(DBErrCodeException, err, errors.New(`数据执行错误`))
  198. }
  199. return
  200. }
  201. // Rows get rows
  202. func (d *DB) Rows(dest interface{}, query string, args interface{}) error {
  203. err := d.Connect()
  204. if err != nil {
  205. return err
  206. }
  207. defer d.Close()
  208. nstmt, err := d.conn.PrepareNamed(query)
  209. if err != nil {
  210. return err
  211. }
  212. defer nstmt.Close()
  213. err = nstmt.Select(dest, args)
  214. return err
  215. }
  216. // Row get row
  217. func (d *DB) Row(dest interface{}, query string, args interface{}) error {
  218. err := d.Connect()
  219. if err != nil {
  220. return err
  221. }
  222. defer d.Close()
  223. nstmt, err := d.conn.PrepareNamed(query)
  224. if err != nil {
  225. return err
  226. }
  227. defer nstmt.Close()
  228. err = nstmt.Get(dest, args)
  229. return err
  230. }
  231. // InsertReply insert and return DbReply
  232. func (d *DB) InsertReply(query string, args interface{}) (reply DbReply) {
  233. var (
  234. err error
  235. rs sql.Result
  236. )
  237. err = d.Connect()
  238. if err != nil {
  239. reply = DbReplyFaild(DBErrCodeNotConnect, err, errors.New(`数据库连接错误`))
  240. return
  241. }
  242. defer d.Close()
  243. if rs, err = d.conn.NamedExec(query, args); err == nil {
  244. a, _ := rs.RowsAffected()
  245. n, _ := rs.LastInsertId()
  246. reply = DbReplyOk(a, n)
  247. } else {
  248. reply = DbReplyFaild(DBErrCodeException, err, errors.New(`数据执行错误`))
  249. }
  250. return
  251. }
  252. // UpdateReply update/delete and return DbReply
  253. func (d *DB) UpdateReply(query string, args interface{}) (reply DbReply) {
  254. var (
  255. err error
  256. rs sql.Result
  257. )
  258. err = d.Connect()
  259. if err != nil {
  260. reply = DbReplyFaild(DBErrCodeNotConnect, err, errors.New(`数据库连接错误`))
  261. return
  262. }
  263. defer d.Close()
  264. if rs, err = d.conn.NamedExec(query, args); err == nil {
  265. a, _ := rs.RowsAffected()
  266. reply = DbReplyOk(a, 0)
  267. } else {
  268. reply = DbReplyFaild(DBErrCodeException, err, errors.New(`数据执行错误`))
  269. }
  270. return
  271. }
  272. // Insert insert into
  273. func (d *DB) Insert(query string, args interface{}) (LastInsertId, RowsAffected int64, err error) {
  274. err = d.Connect()
  275. if err != nil {
  276. return
  277. }
  278. defer d.Close()
  279. if rs, err := d.conn.NamedExec(query, args); err == nil {
  280. LastInsertId, _ = rs.LastInsertId()
  281. RowsAffected, _ = rs.RowsAffected()
  282. }
  283. return
  284. }
  285. // Update update/delete
  286. func (d *DB) Update(query string, args interface{}) (RowsAffected int64, err error) {
  287. err = d.Connect()
  288. if err != nil {
  289. return
  290. }
  291. defer d.Close()
  292. if rs, err := d.conn.NamedExec(query, args); err == nil {
  293. RowsAffected, _ = rs.RowsAffected()
  294. }
  295. return
  296. }
  297. // Limit MySQL limit
  298. func (d *DB) Limit(page, pagesize int) string {
  299. return fmt.Sprintf(" limit %d, %d", (page-1)*pagesize, pagesize)
  300. }