db.go 7.1 KB

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