mysql.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. package dao
  2. import (
  3. "bytes"
  4. "context"
  5. "fmt"
  6. "go-common/app/service/main/favorite/model"
  7. "go-common/library/database/sql"
  8. "go-common/library/log"
  9. "go-common/library/xstr"
  10. )
  11. const (
  12. _folderSharding int64 = 100 // folder by mid
  13. _relationSharding int64 = 500 // objects in folder by mid
  14. _usersSharding int64 = 500 // objects faved by oid
  15. _countSharding int64 = 50 // objects count by oid
  16. // folder table
  17. _cntFolderSQL = "SELECT COUNT(id) FROM fav_folder_%s WHERE type=? AND mid=? AND state=0"
  18. _folderSQL = "SELECT id,type,mid,name,cover,description,count,attr,state,ctime,mtime FROM fav_folder_%s WHERE id=? AND type=? AND mid=?"
  19. _userFoldersSQL = "SELECT id,type,mid,name,cover,description,count,attr,state,ctime,mtime FROM fav_folder_%s WHERE type=? AND mid=? AND state=0"
  20. _folderByNameSQL = "SELECT id,type,mid,name,cover,description,count,attr,state,ctime,mtime FROM fav_folder_%s WHERE name=? AND type=? AND mid=? AND state=0"
  21. _folderByIdsSQL = "SELECT id,type,mid,name,cover,description,count,attr,state,ctime,mtime FROM fav_folder_%s WHERE id in (%s)"
  22. _defFolderSQL = "SELECT id,type,mid,name,cover,description,count,attr,state,ctime,mtime FROM fav_folder_%s WHERE type=? AND mid=? AND attr&2=0"
  23. _addFolderSQL = `INSERT INTO fav_folder_%s (type,mid,name,cover,description,count,attr,state,ctime,mtime) VALUES (?,?,?,?,?,?,?,?,?,?)
  24. ON DUPLICATE KEY UPDATE name=?,cover=?,description=?,count=?,attr=?,state=?,ctime=?,mtime=?`
  25. _delFolderSQL = "UPDATE fav_folder_%s SET state=1 WHERE type=? AND id=?"
  26. _updateFolderSQL = "UPDATE fav_folder_%s SET name=?,description=?,cover=?,attr=?,state=?,mtime=? WHERE type=? AND id=?"
  27. _upFolderNameSQL = "UPDATE IGNORE fav_folder_%s SET name=? WHERE id=?"
  28. _upFolderAttrSQL = "UPDATE fav_folder_%s SET attr=? WHERE id=?"
  29. // relation table
  30. _relationSQL = "SELECT id,type,oid,mid,fid,state,ctime,mtime,sequence FROM fav_relation_%s WHERE type=? AND mid=? AND fid=? AND oid=? AND state=0"
  31. _relationsSQL = "SELECT id,type,oid,mid,fid,state,ctime,mtime,sequence FROM fav_relation_%s FORCE INDEX(ix_fid_state_type_mtime) WHERE fid=? AND state=0 AND type=? ORDER BY mtime DESC LIMIT ?,?"
  32. _allRelationsSQL = "SELECT id,type,oid,mid,fid,state,ctime,mtime,sequence FROM fav_relation_%s FORCE INDEX(ix_fid_state_sequence) WHERE fid=? AND state=0 ORDER BY sequence DESC LIMIT ?,?"
  33. _relationFidsSQL = "SELECT fid FROM fav_relation_%s WHERE type=? AND mid=? AND oid=? AND state=0"
  34. _FidsByOidsSQL = "SELECT oid,fid FROM fav_relation_%s WHERE type=? AND mid=? AND oid in (%s) AND state=0"
  35. _cntRelationSQL = "SELECT COUNT(id) FROM fav_relation_%s FORCE INDEX(ix_fid_state_type_mtime) WHERE fid=? AND state=0 AND type=?"
  36. _cntAllRelationSQL = "SELECT COUNT(id) FROM fav_relation_%s FORCE INDEX(ix_fid_state_sequence) WHERE fid=? AND state=0"
  37. _addRelationSQL = "INSERT INTO fav_relation_%s (type,oid,mid,fid,state,ctime,mtime) VALUES(?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE state=?,mtime=?"
  38. _maddRelationsSQL = "INSERT INTO fav_relation_%s (type,oid,mid,fid,state) VALUES %s ON DUPLICATE KEY UPDATE state=0"
  39. _delRelationSQL = "UPDATE fav_relation_%s SET state=1 WHERE type=? AND fid=? AND oid=?"
  40. _delRelationsSQL = "UPDATE fav_relation_%s SET state=1 WHERE type=? AND fid=? AND oid in (%s)"
  41. _recentOidsSQL = "SELECT oid,type FROM fav_relation_%s FORCE INDEX(ix_fid_state_mtime) WHERE fid=? AND state=0 ORDER BY mtime DESC LIMIT 3"
  42. _copyRelationsSQL = `INSERT IGNORE INTO fav_relation_%s (type,oid,mid,fid)
  43. SELECT %d,oid,%d,%d FROM fav_relation_%s WHERE type=? AND mid=? AND fid=? AND oid in (%s) AND state=0
  44. ON DUPLICATE KEY UPDATE state=0`
  45. _batchOidsSQL = `SELECT oid FROM fav_relation_%s WHERE type=? AND mid=? AND state=0 LIMIT ?`
  46. // users table
  47. _cntUsersSQL = "SELECT COUNT(id) FROM fav_users_%s WHERE type=? AND oid=? AND state=0"
  48. _usersSQL = "SELECT id,type,oid,mid,state,ctime,mtime FROM fav_users_%s WHERE type=? AND oid=? AND state=0 ORDER BY mtime DESC LIMIT ?,?"
  49. // folderSort table
  50. _folderSortSQL = "SELECT id,type,mid,sort,ctime,mtime FROM fav_folder_sort WHERE type=? AND mid=?"
  51. _setFolderSortSQL = "INSERT INTO fav_folder_sort (type,mid,sort,ctime,mtime) VALUES (?,?,?,?,?) ON DUPLICATE KEY UPDATE sort=?,mtime=?"
  52. // count table
  53. _countSQL = "SELECT count FROM fav_count_%s WHERE type=? AND oid=?"
  54. _countsSQL = "SELECT oid,count FROM fav_count_%s WHERE type=? AND oid in (%s)"
  55. _folderStatSQL = "SELECT fid,play,fav,share from fav_folder_stat_%s WHERE fid in (%s)"
  56. )
  57. // folderHit hit table by the mod of mid and _folderSharding.
  58. func folderHit(mid int64) string {
  59. return fmt.Sprintf("%02d", mid%_folderSharding)
  60. }
  61. // relationHit hit table by the mod of mid and _relationSharding.
  62. func relationHit(mid int64) string {
  63. return fmt.Sprintf("%03d", mid%_relationSharding)
  64. }
  65. // usersHit hit table by the mod of oid and _userSharding.
  66. func usersHit(oid int64) string {
  67. return fmt.Sprintf("%03d", oid%_usersSharding)
  68. }
  69. // countHit hit table by the mod of oid and _countSharding.
  70. func countHit(oid int64) string {
  71. return fmt.Sprintf("%02d", oid%_countSharding)
  72. }
  73. // pingMySQL check mysql connection.
  74. func (d *Dao) pingMySQL(c context.Context) error {
  75. if err := d.dbRead.Ping(c); err != nil {
  76. return err
  77. }
  78. if err := d.dbPush.Ping(c); err != nil {
  79. return err
  80. }
  81. return d.db.Ping(c)
  82. }
  83. // Folder get a Folder by fid from mysql.
  84. func (d *Dao) Folder(c context.Context, tp int8, mid, fid int64) (f *model.Folder, err error) {
  85. f = new(model.Folder)
  86. row := d.db.QueryRow(c, fmt.Sprintf(_folderSQL, folderHit(mid)), fid, tp, mid)
  87. if err = row.Scan(&f.ID, &f.Type, &f.Mid, &f.Name, &f.Cover, &f.Description, &f.Count, &f.Attr, &f.State, &f.CTime, &f.MTime); err != nil {
  88. if err == sql.ErrNoRows {
  89. f = nil
  90. err = nil
  91. } else {
  92. log.Error("row.Scan error(%v)", err)
  93. }
  94. }
  95. return
  96. }
  97. // FolderByName get a Folder by name from mysql.
  98. func (d *Dao) FolderByName(c context.Context, tp int8, mid int64, name string) (f *model.Folder, err error) {
  99. f = &model.Folder{}
  100. row := d.db.QueryRow(c, fmt.Sprintf(_folderByNameSQL, folderHit(mid)), name, tp, mid)
  101. if err = row.Scan(&f.ID, &f.Type, &f.Mid, &f.Name, &f.Cover, &f.Description, &f.Count, &f.Attr, &f.State, &f.CTime, &f.MTime); err != nil {
  102. if err == sql.ErrNoRows {
  103. f = nil
  104. err = nil
  105. } else {
  106. log.Error("row.Scan error(%v)", err)
  107. }
  108. }
  109. return
  110. }
  111. // DefaultFolder get default folder from mysql.
  112. func (d *Dao) DefaultFolder(c context.Context, tp int8, mid int64) (f *model.Folder, err error) {
  113. f = new(model.Folder)
  114. row := d.db.QueryRow(c, fmt.Sprintf(_defFolderSQL, folderHit(mid)), tp, mid)
  115. if err = row.Scan(&f.ID, &f.Type, &f.Mid, &f.Name, &f.Cover, &f.Description, &f.Count, &f.Attr, &f.State, &f.CTime, &f.MTime); err != nil {
  116. if err == sql.ErrNoRows {
  117. f = nil
  118. err = nil
  119. } else {
  120. log.Error("row.Scan error(%v)", err)
  121. }
  122. }
  123. return
  124. }
  125. // AddFolder add a new favorite folder to mysql.
  126. func (d *Dao) AddFolder(c context.Context, f *model.Folder) (fid int64, err error) {
  127. res, err := d.db.Exec(c, fmt.Sprintf(_addFolderSQL, folderHit(f.Mid)), f.Type, f.Mid, f.Name, f.Cover, f.Description, f.Count, f.Attr, f.State, f.CTime, f.MTime,
  128. f.Name, f.Cover, f.Description, f.Count, f.Attr, f.State, f.CTime, f.MTime)
  129. if err != nil {
  130. log.Error("db.Exec error(%v)", err)
  131. return
  132. }
  133. return res.LastInsertId()
  134. }
  135. // UpdateFolder add a new favorite folder to mysql.
  136. func (d *Dao) UpdateFolder(c context.Context, f *model.Folder) (fid int64, err error) {
  137. res, err := d.db.Exec(c, fmt.Sprintf(_updateFolderSQL, folderHit(f.Mid)), f.Name, f.Description, f.Cover, f.Attr, f.State, f.MTime, f.Type, f.ID)
  138. if err != nil {
  139. log.Error("db.Exec error(%v)", err)
  140. return
  141. }
  142. return res.RowsAffected()
  143. }
  144. // UpFolderName rename user's folder name to mysql.
  145. func (d *Dao) UpFolderName(c context.Context, typ int8, mid, fid int64, name string) (rows int64, err error) {
  146. res, err := d.db.Exec(c, fmt.Sprintf(_upFolderNameSQL, folderHit(mid)), name, fid)
  147. if err != nil {
  148. log.Error("db.Exec error(%v)", err)
  149. return
  150. }
  151. return res.RowsAffected()
  152. }
  153. // UpFolderAttr update user's folder attr to mysql.
  154. func (d *Dao) UpFolderAttr(c context.Context, typ int8, mid, fid int64, attr int32) (rows int64, err error) {
  155. res, err := d.db.Exec(c, fmt.Sprintf(_upFolderAttrSQL, folderHit(mid)), attr, fid)
  156. if err != nil {
  157. log.Error("db.Exec error(%v)", err)
  158. return
  159. }
  160. return res.RowsAffected()
  161. }
  162. // FolderRelations get favorite relations from mysql.
  163. func (d *Dao) FolderRelations(c context.Context, typ int8, mid, fid int64, start, end int) (fr []*model.Favorite, err error) {
  164. rows, err := d.db.Query(c, fmt.Sprintf(_relationsSQL, relationHit(mid)), fid, typ, start, end)
  165. if err != nil {
  166. log.Error("d.db.Query(%s,%d,%d,%d,%d,%d) error(%v)", fmt.Sprintf(_relationsSQL, relationHit(mid)), typ, mid, fid, start, end, err)
  167. return
  168. }
  169. defer rows.Close()
  170. fr = make([]*model.Favorite, 0)
  171. for rows.Next() {
  172. var r = &model.Favorite{}
  173. if err = rows.Scan(&r.ID, &r.Type, &r.Oid, &r.Mid, &r.Fid, &r.State, &r.CTime, &r.MTime, &r.Sequence); err != nil {
  174. log.Error("rows.Scan error(%v)", err)
  175. return
  176. }
  177. if r.Type != typ || r.Mid != mid {
  178. log.Error("dirty data relations(%d,%d,%d)", typ, mid, fid)
  179. continue
  180. }
  181. fr = append(fr, r)
  182. }
  183. err = rows.Err()
  184. return
  185. }
  186. // FolderAllRelations get favorite relations from mysql.
  187. func (d *Dao) FolderAllRelations(c context.Context, mid, fid int64, start, end int) (fr []*model.Favorite, err error) {
  188. rows, err := d.db.Query(c, fmt.Sprintf(_allRelationsSQL, relationHit(mid)), fid, start, end)
  189. if err != nil {
  190. log.Error("d.db.Query(%s,%d,%d,%d,%d,%d) error(%v)", fmt.Sprintf(_allRelationsSQL, relationHit(mid)), mid, fid, start, end, err)
  191. return
  192. }
  193. defer rows.Close()
  194. fr = make([]*model.Favorite, 0)
  195. for rows.Next() {
  196. var r = &model.Favorite{}
  197. if err = rows.Scan(&r.ID, &r.Type, &r.Oid, &r.Mid, &r.Fid, &r.State, &r.CTime, &r.MTime, &r.Sequence); err != nil {
  198. log.Error("rows.Scan error(%v)", err)
  199. return
  200. }
  201. if r.Mid != mid {
  202. log.Error("dirty data relations(%d,%d,%d)", mid, fid)
  203. continue
  204. }
  205. fr = append(fr, r)
  206. }
  207. err = rows.Err()
  208. return
  209. }
  210. // Folders get folders from mysql.
  211. func (d *Dao) Folders(c context.Context, fvmids []*model.ArgFVmid) (fs map[string]*model.Folder, err error) {
  212. tblMap := make(map[string][]int64, len(fvmids))
  213. for _, fvmid := range fvmids {
  214. folderHits := folderHit(fvmid.Vmid)
  215. tblMap[folderHits] = append(tblMap[folderHits], fvmid.Fid)
  216. }
  217. fs = make(map[string]*model.Folder, len(fvmids))
  218. for folderHit, fids := range tblMap {
  219. fidsStr := xstr.JoinInts(fids)
  220. var rows *sql.Rows
  221. if rows, err = d.db.Query(c, fmt.Sprintf(_folderByIdsSQL, folderHit, fidsStr)); err != nil {
  222. log.Error("d.db.Query(%s,%s,%s) error(%v)", _folderByIdsSQL, folderHit, fidsStr, err)
  223. return
  224. }
  225. defer rows.Close()
  226. for rows.Next() {
  227. f := new(model.Folder)
  228. if err = rows.Scan(&f.ID, &f.Type, &f.Mid, &f.Name, &f.Cover, &f.Description, &f.Count, &f.Attr, &f.State, &f.CTime, &f.MTime); err != nil {
  229. log.Error("rows.Scan error(%v)", err)
  230. return
  231. }
  232. fmid := xstr.JoinInts([]int64{f.ID, f.Mid})
  233. fs[fmid] = f
  234. }
  235. err = rows.Err()
  236. if err != nil {
  237. return
  238. }
  239. }
  240. return
  241. }
  242. // RelationFidsByOid get favortied folders in relations by oid from mysql.
  243. func (d *Dao) RelationFidsByOid(c context.Context, tp int8, mid, oid int64) (fids []int64, err error) {
  244. var fid int64
  245. rows, err := d.db.Query(c, fmt.Sprintf(_relationFidsSQL, relationHit(mid)), tp, mid, oid)
  246. if err != nil {
  247. log.Error("d.db.Query(%d,%d,%d) error(%v)", tp, mid, oid, err)
  248. return
  249. }
  250. defer rows.Close()
  251. for rows.Next() {
  252. if err = rows.Scan(&fid); err != nil {
  253. log.Error("rows.Scan error(%v)", err)
  254. return
  255. }
  256. fids = append(fids, fid)
  257. }
  258. err = rows.Err()
  259. return
  260. }
  261. // RelationFidsByOids get favortied folders in relations by oid from mysql.
  262. func (d *Dao) RelationFidsByOids(c context.Context, tp int8, mid int64, oids []int64) (fidsMap map[int64][]int64, err error) {
  263. oidsStr := xstr.JoinInts(oids)
  264. rows, err := d.dbRead.Query(c, fmt.Sprintf(_FidsByOidsSQL, relationHit(mid), oidsStr), tp, mid)
  265. if err != nil {
  266. log.Error("d.db.Query(%d,%d,%d) error(%v)", mid, mid, oidsStr, err)
  267. return
  268. }
  269. defer rows.Close()
  270. var oid, fid int64
  271. fidsMap = make(map[int64][]int64, len(oids))
  272. for rows.Next() {
  273. if err = rows.Scan(&oid, &fid); err != nil {
  274. log.Error("rows.Scan error(%v)", err)
  275. return
  276. }
  277. fidsMap[oid] = append(fidsMap[oid], fid)
  278. }
  279. err = rows.Err()
  280. return
  281. }
  282. // CntRelations get favoried folders count in relation from mysql.
  283. func (d *Dao) CntRelations(c context.Context, mid, fid int64, typ int8) (count int, err error) {
  284. row := d.db.QueryRow(c, fmt.Sprintf(_cntRelationSQL, relationHit(mid)), fid, typ)
  285. if err = row.Scan(&count); err != nil {
  286. if err == sql.ErrNoRows {
  287. err = nil
  288. } else {
  289. log.Error("row.Scan error(%v)", err)
  290. }
  291. }
  292. return
  293. }
  294. // CntRelations get favoried folders count in relation from mysql.
  295. func (d *Dao) CntAllRelations(c context.Context, mid, fid int64) (count int, err error) {
  296. row := d.db.QueryRow(c, fmt.Sprintf(_cntAllRelationSQL, relationHit(mid)), fid)
  297. if err = row.Scan(&count); err != nil {
  298. if err == sql.ErrNoRows {
  299. err = nil
  300. } else {
  301. log.Error("row.Scan error(%v)", err)
  302. }
  303. }
  304. return
  305. }
  306. // FolderCnt get user's folder count.
  307. func (d *Dao) FolderCnt(c context.Context, tp int8, mid int64) (count int, err error) {
  308. row := d.db.QueryRow(c, fmt.Sprintf(_cntFolderSQL, folderHit(mid)), tp, mid)
  309. if err = row.Scan(&count); err != nil {
  310. if err == sql.ErrNoRows {
  311. err = nil
  312. } else {
  313. log.Error("row.Scan error(%v)", err)
  314. }
  315. }
  316. return
  317. }
  318. // AddFav add a favorite relation to mysql.
  319. func (d *Dao) AddFav(c context.Context, fr *model.Favorite) (rows int64, err error) {
  320. res, err := d.db.Exec(c, fmt.Sprintf(_addRelationSQL, relationHit(fr.Mid)), fr.Type, fr.Oid, fr.Mid, fr.Fid, fr.State, fr.CTime, fr.MTime, fr.State, fr.MTime)
  321. if err != nil {
  322. log.Error("db.Exec error(%v)", err)
  323. return
  324. }
  325. return res.RowsAffected()
  326. }
  327. // DelFav delete a favorite relation to mysql.
  328. func (d *Dao) DelFav(c context.Context, tp int8, mid, fid, oid int64) (rows int64, err error) {
  329. res, err := d.db.Exec(c, fmt.Sprintf(_delRelationSQL, relationHit(mid)), tp, fid, oid)
  330. if err != nil {
  331. log.Error("d.db.Exec(%d,%d,%d,%d) error(%v)", mid, tp, fid, oid, err)
  332. return
  333. }
  334. return res.RowsAffected()
  335. }
  336. // AddRelation add a favorite relation to mysql.
  337. func (d *Dao) AddRelation(c context.Context, fr *model.Favorite) (rows int64, err error) {
  338. res, err := d.db.Exec(c, fmt.Sprintf(_addRelationSQL, relationHit(fr.Mid)), fr.Type, fr.Oid, fr.Mid, fr.Fid, fr.State, fr.CTime, fr.MTime, fr.State, fr.MTime)
  339. if err != nil {
  340. log.Error("db.Exec error(%v)", err)
  341. return
  342. }
  343. return res.LastInsertId()
  344. }
  345. // Relation get a relation from mysql.
  346. func (d *Dao) Relation(c context.Context, tp int8, mid, fid, oid int64) (m *model.Favorite, err error) {
  347. m = &model.Favorite{}
  348. row := d.db.QueryRow(c, fmt.Sprintf(_relationSQL, relationHit(mid)), tp, mid, fid, oid)
  349. if err = row.Scan(&m.ID, &m.Type, &m.Oid, &m.Mid, &m.Fid, &m.State, &m.CTime, &m.MTime, &m.Sequence); err != nil {
  350. if err == sql.ErrNoRows {
  351. err = nil
  352. m = nil
  353. } else {
  354. log.Error("row.Scan error(%v)", err)
  355. }
  356. }
  357. return
  358. }
  359. // DelRelation delete a favorite relation to mysql.
  360. func (d *Dao) DelRelation(c context.Context, tp int8, mid, fid, oid int64) (rows int64, err error) {
  361. res, err := d.db.Exec(c, fmt.Sprintf(_delRelationSQL, relationHit(mid)), tp, fid, oid)
  362. if err != nil {
  363. log.Error("d.db.Exec(%d,%d,%d,%d) error(%v)", mid, tp, fid, oid, err)
  364. return
  365. }
  366. return res.RowsAffected()
  367. }
  368. // MultiDelRelations delete relations to mysql.
  369. func (d *Dao) MultiDelRelations(c context.Context, tp int8, mid, fid int64, oids []int64) (rows int64, err error) {
  370. if len(oids) <= 0 {
  371. return
  372. }
  373. oidsStr := xstr.JoinInts(oids)
  374. res, err := d.db.Exec(c, fmt.Sprintf(_delRelationsSQL, relationHit(mid), oidsStr), tp, fid)
  375. if err != nil {
  376. log.Error("d.db.Exec(%d,%d,%d,%s) error(%v)", mid, tp, fid, oidsStr, err)
  377. return
  378. }
  379. return res.RowsAffected()
  380. }
  381. // TxMultiDelRelations delete relations to mysql.
  382. func (d *Dao) TxMultiDelRelations(tx *sql.Tx, tp int8, mid, fid int64, oids []int64) (rows int64, err error) {
  383. if len(oids) <= 0 {
  384. return
  385. }
  386. oidsStr := xstr.JoinInts(oids)
  387. res, err := tx.Exec(fmt.Sprintf(_delRelationsSQL, relationHit(mid), oidsStr), tp, fid)
  388. if err != nil {
  389. log.Error("d.db.Exec(%d,%d,%d,%s) error(%v)", mid, tp, fid, oidsStr, err)
  390. return
  391. }
  392. return res.RowsAffected()
  393. }
  394. // MultiAddRelations insert relations to mysql.
  395. func (d *Dao) MultiAddRelations(c context.Context, tp int8, mid, fid int64, oids []int64) (rows int64, err error) {
  396. var buffer bytes.Buffer
  397. valuesTpl := "(%d,%d,%d,%d,%d),"
  398. for _, oid := range oids {
  399. buffer.WriteString(fmt.Sprintf(valuesTpl, tp, oid, mid, fid, 0))
  400. }
  401. buffer.Truncate(buffer.Len() - 1)
  402. res, err := d.db.Exec(c, fmt.Sprintf(_maddRelationsSQL, relationHit(mid), buffer.String()))
  403. if err != nil {
  404. log.Error("d.db.Exec(%d,%d,%d,%s) error(%v)", mid, tp, fid, oids, err)
  405. return
  406. }
  407. return res.RowsAffected()
  408. }
  409. // DelFolder delete a folder to mysql.
  410. func (d *Dao) DelFolder(c context.Context, tp int8, mid, fid int64) (rows int64, err error) {
  411. res, err := d.db.Exec(c, fmt.Sprintf(_delFolderSQL, folderHit(mid)), tp, fid)
  412. if err != nil {
  413. log.Error("d.db.Exec(mid:%d,tp:%d,fid:%d) error(%v)", mid, tp, fid, err)
  414. return
  415. }
  416. return res.RowsAffected()
  417. }
  418. // FolderStats get folders from mysql.
  419. func (d *Dao) FolderStats(c context.Context, fvmids []*model.ArgFVmid) (fs map[int64]*model.Folder, err error) {
  420. tblMap := make(map[int64][]int64, len(fvmids))
  421. for _, fvmid := range fvmids {
  422. tblMap[fvmid.Vmid] = append(tblMap[fvmid.Vmid], fvmid.Fid)
  423. }
  424. fs = make(map[int64]*model.Folder, len(fvmids))
  425. for vmid, fids := range tblMap {
  426. fidsStr := xstr.JoinInts(fids)
  427. var rows *sql.Rows
  428. if rows, err = d.db.Query(c, fmt.Sprintf(_folderStatSQL, folderHit(vmid), fidsStr)); err != nil {
  429. log.Error("d.db.Query(%s,%s,%s) error(%v)", _folderStatSQL, folderHit(vmid), fidsStr, err)
  430. return
  431. }
  432. defer rows.Close()
  433. for rows.Next() {
  434. stat := new(model.Folder)
  435. if err = rows.Scan(&stat.ID, &stat.PlayCount, &stat.FavedCount, &stat.ShareCount); err != nil {
  436. log.Error("rows.Scan error(%v)", err)
  437. return
  438. }
  439. fs[stat.ID*100+vmid%100] = stat
  440. }
  441. err = rows.Err()
  442. if err != nil {
  443. return
  444. }
  445. }
  446. return
  447. }
  448. // UserFolders get user's folders.
  449. func (d *Dao) UserFolders(c context.Context, typ int8, mid int64) (fs map[int64]*model.Folder, err error) {
  450. rows, err := d.db.Query(c, fmt.Sprintf(_userFoldersSQL, folderHit(mid)), typ, mid)
  451. if err != nil {
  452. log.Error("d.db.Query(mid:%d,typ:%d) error(%v)", mid, typ, err)
  453. return
  454. }
  455. defer rows.Close()
  456. fs = make(map[int64]*model.Folder)
  457. for rows.Next() {
  458. f := new(model.Folder)
  459. if err = rows.Scan(&f.ID, &f.Type, &f.Mid, &f.Name, &f.Cover, &f.Description, &f.Count, &f.Attr, &f.State, &f.CTime, &f.MTime); err != nil {
  460. log.Error("rows.Scan error(%v)", err)
  461. return
  462. }
  463. fs[f.ID] = f
  464. }
  465. err = rows.Err()
  466. return
  467. }
  468. // FolderSort return user's folders sort by type & mid.
  469. func (d *Dao) FolderSort(c context.Context, typ int8, mid int64) (fst *model.FolderSort, err error) {
  470. var b []byte
  471. fst = new(model.FolderSort)
  472. row := d.db.QueryRow(c, _folderSortSQL, typ, mid)
  473. if err = row.Scan(&fst.ID, &fst.Type, &fst.Mid, &b, &fst.CTime, &fst.MTime); err != nil {
  474. if err == sql.ErrNoRows {
  475. fst = nil
  476. err = nil
  477. } else {
  478. log.Error("row.Scan error(%v)", err)
  479. }
  480. return
  481. }
  482. fst.SetIndex(b)
  483. return
  484. }
  485. // UpFolderSort update user's folder sort.
  486. func (d *Dao) UpFolderSort(c context.Context, fst *model.FolderSort) (rows int64, err error) {
  487. sort := fst.Index()
  488. res, err := d.db.Exec(c, _setFolderSortSQL, fst.Type, fst.Mid, sort, fst.CTime, fst.MTime, sort, fst.MTime)
  489. if err != nil {
  490. log.Error("d.db.Exec() error(%v)", err)
  491. return
  492. }
  493. return res.RowsAffected()
  494. }
  495. // RecentOids return user's three newest fav from a folder.
  496. func (d *Dao) RecentOids(c context.Context, mid, fid int64, typ int8) (oids []int64, err error) {
  497. rows, err := d.dbRead.Query(c, fmt.Sprintf(_recentOidsSQL, relationHit(mid)), fid)
  498. if err != nil {
  499. log.Error("d.db.Query(%d,%d) error(%v)", mid, fid, err)
  500. return
  501. }
  502. defer rows.Close()
  503. for rows.Next() {
  504. var oid int64
  505. var otyp int8
  506. if err = rows.Scan(&oid, &otyp); err != nil {
  507. log.Error("rows.Scan error(%v)", err)
  508. return
  509. }
  510. if otyp == typ {
  511. oids = append(oids, oid)
  512. }
  513. }
  514. err = rows.Err()
  515. return
  516. }
  517. // RecentOids return user's three newest fav from a folder.
  518. func (d *Dao) RecentRes(c context.Context, mid, fid int64) (res []*model.Resource, err error) {
  519. rows, err := d.dbRead.Query(c, fmt.Sprintf(_recentOidsSQL, relationHit(mid)), fid)
  520. if err != nil {
  521. log.Error("d.db.Query(%d,%d) error(%v)", mid, fid, err)
  522. return
  523. }
  524. defer rows.Close()
  525. for rows.Next() {
  526. var oid int64
  527. var typ int32
  528. if err = rows.Scan(&oid, &typ); err != nil {
  529. log.Error("rows.Scan error(%v)", err)
  530. return
  531. }
  532. res = append(res, &model.Resource{Oid: oid, Typ: typ})
  533. }
  534. err = rows.Err()
  535. return
  536. }
  537. // TxCopyRelations copy resources from oldfid to newfid by oids.
  538. func (d *Dao) TxCopyRelations(tx *sql.Tx, typ int8, oldmid, mid, oldfid, newfid int64, oids []int64) (rows int64, err error) {
  539. res, err := tx.Exec(fmt.Sprintf(_copyRelationsSQL, relationHit(mid), typ, mid, newfid, relationHit(oldmid), xstr.JoinInts(oids)), typ, oldmid, oldfid)
  540. if err != nil {
  541. log.Error("db.Exec() error(%v)", err)
  542. return
  543. }
  544. return res.RowsAffected()
  545. }
  546. // CopyRelations copy resources from oldfid to newfid by oids.
  547. func (d *Dao) CopyRelations(c context.Context, typ int8, oldmid, mid, oldfid, newfid int64, oids []int64) (rows int64, err error) {
  548. res, err := d.db.Exec(c, fmt.Sprintf(_copyRelationsSQL, relationHit(mid), typ, mid, newfid, relationHit(oldmid), xstr.JoinInts(oids)), typ, oldmid, oldfid)
  549. if err != nil {
  550. log.Error("db.Exec() error(%v)", err)
  551. return
  552. }
  553. return res.RowsAffected()
  554. }
  555. // CntUsers get favoried users count from mysql.
  556. func (d *Dao) CntUsers(c context.Context, typ int8, oid int64) (count int, err error) {
  557. row := d.dbPush.QueryRow(c, fmt.Sprintf(_cntUsersSQL, usersHit(oid)), typ, oid)
  558. if err = row.Scan(&count); err != nil {
  559. if err == sql.ErrNoRows {
  560. err = nil
  561. } else {
  562. log.Error("row.Scan error(%v)", err)
  563. }
  564. }
  565. return
  566. }
  567. // Users get favorite users from mysql.
  568. func (d *Dao) Users(c context.Context, typ int8, oid int64, start, end int) (us []*model.User, err error) {
  569. rows, err := d.dbPush.Query(c, fmt.Sprintf(_usersSQL, usersHit(oid)), typ, oid, start, end)
  570. if err != nil {
  571. log.Error("d.db.Query(%d,%d,%d,%d) error(%v)", typ, oid, start, end, err)
  572. return
  573. }
  574. defer rows.Close()
  575. us = make([]*model.User, 0)
  576. for rows.Next() {
  577. var u = new(model.User)
  578. if err = rows.Scan(&u.ID, &u.Type, &u.Oid, &u.Mid, &u.State, &u.CTime, &u.MTime); err != nil {
  579. log.Error("rows.Scan error(%v)", err)
  580. return
  581. }
  582. us = append(us, u)
  583. }
  584. err = rows.Err()
  585. return
  586. }
  587. // OidCount get oid's fav count from mysql.
  588. func (d *Dao) OidCount(c context.Context, typ int8, oid int64) (count int64, err error) {
  589. row := d.dbPush.QueryRow(c, fmt.Sprintf(_countSQL, countHit(oid)), typ, oid)
  590. if err = row.Scan(&count); err != nil {
  591. if err == sql.ErrNoRows {
  592. err = nil
  593. } else {
  594. log.Error("row.Scan error(%v)", err)
  595. }
  596. }
  597. return
  598. }
  599. // OidsCount get oids's count from mysql.
  600. func (d *Dao) OidsCount(c context.Context, typ int8, oids []int64) (counts map[int64]int64, err error) {
  601. tblMap := make(map[string][]int64, len(oids))
  602. for _, oid := range oids {
  603. countHit := countHit(oid)
  604. tblMap[countHit] = append(tblMap[countHit], oid)
  605. }
  606. counts = make(map[int64]int64, len(oids))
  607. for countHit, oids := range tblMap {
  608. oidsStr := xstr.JoinInts(oids)
  609. var rows *sql.Rows
  610. if rows, err = d.db.Query(c, fmt.Sprintf(_countsSQL, countHit, oidsStr), typ); err != nil {
  611. log.Error("d.db.Query(%s,%d) error(%v)", fmt.Sprintf(_countsSQL, countHit, oidsStr), typ, err)
  612. return
  613. }
  614. defer rows.Close()
  615. for rows.Next() {
  616. var oid, count int64
  617. if err = rows.Scan(&oid, &count); err != nil {
  618. log.Error("rows.Scan error(%v)", err)
  619. return
  620. }
  621. counts[oid] = count
  622. }
  623. if err = rows.Err(); err != nil {
  624. log.Error("rows.Err() error(%v)", err)
  625. return
  626. }
  627. }
  628. return
  629. }
  630. // BatchOids get batch oids from mysql.
  631. func (d *Dao) BatchOids(c context.Context, typ int8, mid int64, limit int) (oids []int64, err error) {
  632. rows, err := d.dbRead.Query(c, fmt.Sprintf(_batchOidsSQL, relationHit(mid)), typ, mid, limit)
  633. if err != nil {
  634. log.Error("d.db.Query(%d,%d,%d) error(%v)", typ, mid, limit, err)
  635. return
  636. }
  637. defer rows.Close()
  638. for rows.Next() {
  639. var oid int64
  640. if err = rows.Scan(&oid); err != nil {
  641. log.Error("rows.Scan error(%v)", err)
  642. return
  643. }
  644. oids = append(oids, oid)
  645. }
  646. if err = rows.Err(); err != nil {
  647. log.Error("rows.Err() error(%v)", err)
  648. }
  649. return
  650. }