mysql.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. package dao
  2. import (
  3. "context"
  4. xsql "database/sql"
  5. "fmt"
  6. "time"
  7. "go-common/app/service/main/relation/model"
  8. "go-common/app/service/main/relation/model/i64b"
  9. "go-common/library/database/sql"
  10. "go-common/library/log"
  11. "go-common/library/xstr"
  12. )
  13. const (
  14. _shard = 500
  15. _statShard = 50
  16. _tagShard = 100
  17. _tagUserShard = 500
  18. _defaultTag = "默认分组"
  19. _specialTag = "特别关注"
  20. // relation
  21. _getFollowingSQL = "SELECT fid,attribute,mtime FROM user_relation_mid_%03d WHERE mid=? AND status=0"
  22. _getFollowingInSQL = "SELECT fid,attribute,mtime FROM user_relation_mid_%03d WHERE mid=? AND status=0 AND fid IN (%s)"
  23. _addFollowingSQL = "INSERT INTO user_relation_mid_%03d (mid,fid,attribute,source,status, ctime,mtime) VALUES (?,?,?,?,0,?,?) ON DUPLICATE KEY UPDATE attribute=attribute|?,source=?,status=0,mtime=?"
  24. _setFollowingSQL = "UPDATE user_relation_mid_%03d SET attribute=?,source=?,status=?,mtime=? WHERE mid=? AND fid=?"
  25. _getFollowersSQL = "SELECT mid,attribute,mtime FROM user_relation_fid_%03d WHERE fid=? AND status=0 AND attribute IN (2,6) ORDER BY mtime DESC LIMIT 1000"
  26. _addFollowersSQL = "INSERT INTO user_relation_fid_%03d (mid,fid,attribute,source,status,ctime,mtime) VALUES (?,?,?,?,0,?,?) ON DUPLICATE KEY UPDATE attribute=attribute|?,source=?,status=0,mtime=?"
  27. _setFollowersSQL = "UPDATE user_relation_fid_%03d SET attribute=?,source=?,status=?,mtime=? WHERE fid=? AND mid=?"
  28. _getRelationSQL = "SELECT attribute FROM user_relation_mid_%03d WHERE mid=? AND fid=? AND status=0 LIMIT 1"
  29. _addStatIgnoreSQL = "INSERT IGNORE INTO user_relation_stat_%02d (mid,following,whisper,black,follower,ctime,mtime) VALUES (?,?,?,?,?,?,?)"
  30. _addStatSQL = "UPDATE user_relation_stat_%02d SET following=following+?,whisper=whisper+?,black=black+?,follower=follower+?,mtime=? WHERE mid=?"
  31. _setStatSQL = "UPDATE user_relation_stat_%02d SET following=?,whisper=?,black=?,follower=?,mtime=? WHERE mid=?"
  32. _getStatSQL = "SELECT mid,following,whisper,black,follower, ctime,mtime from user_relation_stat_%02d where mid=?"
  33. _getTxStatSQL = "SELECT mid,following,whisper,black,follower,ctime,mtime from user_relation_stat_%02d where mid=? FOR UPDATE"
  34. // relation tag table
  35. _getTagsSQL = "SELECT id,name,status,mtime FROM user_relation_tag_%02d WHERE mid=? AND status=0"
  36. _addTagSQL = "INSERT INTO user_relation_tag_%02d (mid,name,status,ctime,mtime) VALUES (?,?,0,?,?)"
  37. _delTagSQL = "DELETE FROM user_relation_tag_%02d WHERE id=? AND mid=?"
  38. _setTagNameSQL = "UPDATE user_relation_tag_%02d SET name=?,mtime=? WHERE id=?"
  39. // relation tag user table
  40. _getTagUserSQL = "SELECT fid,tag FROM user_relation_tag_user_%03d WHERE mid=?"
  41. _getUsersTagSQL = "SELECT fid,tag FROM user_relation_tag_user_%03d WHERE mid=? AND fid IN(%s)"
  42. _getTagsByMidFidSQL = "SELECT fid,tag,mtime FROM user_relation_tag_user_%03d WHERE mid=? and fid=?"
  43. _addTagUserSQL = "INSERT INTO user_relation_tag_user_%03d (mid,fid,tag,ctime,mtime) VALUES (?,?,?,?,?) ON DUPLICATE KEY UPDATE tag=?"
  44. _setTagUserSQL = "UPDATE user_relation_tag_user_%03d SET tag=?,mtime=? WHERE mid=? AND fid=?"
  45. _delTagUserSQL = "DELETE FROM user_relation_tag_user_%03d WHERE mid=? AND fid=?"
  46. // relation monitor
  47. _loadMonitorSQL = "SELECT mid FROM user_relation_monitor"
  48. _addMonitorSQL = "INSERT IGNORE INTO user_relation_monitor (mid,ctime,mtime) VALUES (?,?,?)"
  49. _delMonitorSQL = "DELETE FROM user_relation_monitor WHERE mid = ?"
  50. // relation achieve
  51. _hasReachAchieve = "SELECT count(1) FROM user_addit WHERE mid=? AND achieve_flags>=?"
  52. // follower notify
  53. _getFollowerNotifySettingSQL = "SELECT disable_follower_notify FROM user_addit where mid=?"
  54. _enableFollowerNotifySQL = "INSERT INTO user_addit (mid, disable_follower_notify) VALUES(?, 0) ON DUPLICATE KEY UPDATE disable_follower_notify=0"
  55. _disableFollowerNotifySQL = "INSERT INTO user_addit (mid, disable_follower_notify) VALUES(?, 1) ON DUPLICATE KEY UPDATE disable_follower_notify=1"
  56. )
  57. func hit(id int64) int64 {
  58. return id % _shard
  59. }
  60. func statHit(id int64) int64 {
  61. return id % _statShard
  62. }
  63. func tagHit(id int64) int64 {
  64. return id % _tagShard
  65. }
  66. func tagUserHit(id int64) int64 {
  67. return id % _tagUserShard
  68. }
  69. // BeginTran begin transaction.
  70. func (d *Dao) BeginTran(c context.Context) (*sql.Tx, error) {
  71. return d.db.Begin(c)
  72. }
  73. // Followings get user's following list.
  74. func (d *Dao) Followings(c context.Context, mid int64) (res []*model.Following, err error) {
  75. var rows *sql.Rows
  76. if rows, err = d.db.Query(c, fmt.Sprintf(_getFollowingSQL, hit(mid)), mid); err != nil {
  77. log.Error("d.query[%s].hit(%d).mid(%d) error(%v)", _getFollowingSQL, hit(mid), mid, err)
  78. return
  79. }
  80. defer rows.Close()
  81. for rows.Next() {
  82. r := new(model.Following)
  83. if err = rows.Scan(&r.Mid, &r.Attribute, &r.MTime); err != nil {
  84. log.Error("row.Scan() error(%v)", err)
  85. res = nil
  86. return
  87. }
  88. res = append(res, r)
  89. }
  90. err = rows.Err()
  91. return
  92. }
  93. // FollowingsIn get user's following list by in fids
  94. func (d *Dao) FollowingsIn(c context.Context, mid int64, fids []int64) (res []*model.Following, err error) {
  95. var rows *sql.Rows
  96. if rows, err = d.db.Query(c, fmt.Sprintf(_getFollowingInSQL, hit(mid), xstr.JoinInts(fids)), mid); err != nil {
  97. log.Error("d.query[%d].Query(%d) error(%v)", hit(mid), mid, err)
  98. return
  99. }
  100. defer rows.Close()
  101. for rows.Next() {
  102. r := new(model.Following)
  103. if err = rows.Scan(&r.Mid, &r.Attribute, &r.MTime); err != nil {
  104. log.Error("row.Scan() error(%v)", err)
  105. res = nil
  106. return
  107. }
  108. res = append(res, r)
  109. }
  110. err = rows.Err()
  111. return
  112. }
  113. // TxAddFollowing add following by transaction.
  114. func (d *Dao) TxAddFollowing(c context.Context, tx *sql.Tx, mid, fid int64, mask uint32, source uint8, now time.Time) (affected int64, err error) {
  115. var res xsql.Result
  116. if res, err = tx.Exec(fmt.Sprintf(_addFollowingSQL, hit(mid)), mid, fid, mask, source, now, now, mask, source, now); err != nil {
  117. log.Error("add following: tx.Exec(%v, %d, %d, %d) error(%v)", mid, fid, mask, source, err)
  118. return
  119. }
  120. return res.RowsAffected()
  121. }
  122. // TxSetFollowing set following by transaction.
  123. func (d *Dao) TxSetFollowing(c context.Context, tx *sql.Tx, mid, fid int64, attribute uint32, source uint8, status int, now time.Time) (affected int64, err error) {
  124. var res xsql.Result
  125. if res, err = tx.Exec(fmt.Sprintf(_setFollowingSQL, hit(mid)), attribute, source, status, now, mid, fid); err != nil {
  126. log.Error("tx.Exec(%d, %d, %d, %d, %d) error(%v)", mid, fid, attribute, source, status, err)
  127. return
  128. }
  129. return res.RowsAffected()
  130. }
  131. // Followers get user's latest 1000 followers(attribute = AttrFollowing), order by mtime desc.
  132. func (d *Dao) Followers(c context.Context, mid int64) (res []*model.Following, err error) {
  133. var rows *sql.Rows
  134. if rows, err = d.db.Query(c, fmt.Sprintf(_getFollowersSQL, hit(mid)), mid); err != nil {
  135. log.Error("d.query(%s).hit(%d).mid(%d) error(%v)", _getFollowersSQL, hit(mid), mid, err)
  136. return
  137. }
  138. defer rows.Close()
  139. for rows.Next() {
  140. r := new(model.Following)
  141. if err = rows.Scan(&r.Mid, &r.Attribute, &r.MTime); err != nil {
  142. log.Error("row.Scan() error(%v)", err)
  143. res = nil
  144. return
  145. }
  146. res = append(res, r)
  147. }
  148. err = rows.Err()
  149. return
  150. }
  151. // TxAddFollower add follower by transaction.
  152. func (d *Dao) TxAddFollower(c context.Context, tx *sql.Tx, mid, fid int64, mask uint32, source uint8, now time.Time) (affected int64, err error) {
  153. var res xsql.Result
  154. if res, err = tx.Exec(fmt.Sprintf(_addFollowersSQL, hit(fid)), mid, fid, mask, source, now, now, mask, source, now); err != nil {
  155. log.Error("add follower: tx.Exec(%v, %d, %d, %d), error(%v)", mid, fid, mask, source, err)
  156. return
  157. }
  158. return res.RowsAffected()
  159. }
  160. // TxSetFollower set follower by transaction.
  161. func (d *Dao) TxSetFollower(c context.Context, tx *sql.Tx, mid, fid int64, attribute uint32, source uint8, status int, now time.Time) (affected int64, err error) {
  162. var res xsql.Result
  163. if res, err = tx.Exec(fmt.Sprintf(_setFollowersSQL, hit(fid)), attribute, source, status, now, fid, mid); err != nil {
  164. log.Error("tx.Exec(%d, %d, %d, %d, %d) error(%v)", mid, fid, attribute, source, status, err)
  165. return
  166. }
  167. return res.RowsAffected()
  168. }
  169. // Stat get stat.
  170. func (d *Dao) Stat(c context.Context, mid int64) (stat *model.Stat, err error) {
  171. var row = d.db.QueryRow(c, fmt.Sprintf(_getStatSQL, statHit(mid)), mid)
  172. stat = new(model.Stat)
  173. if err = row.Scan(&stat.Mid, &stat.Following, &stat.Whisper, &stat.Black, &stat.Follower, &stat.CTime, &stat.MTime); err != nil {
  174. if err == sql.ErrNoRows {
  175. stat = nil
  176. err = nil
  177. } else {
  178. log.Error("row.Scan() error(%v)", err)
  179. }
  180. }
  181. return
  182. }
  183. // TxStat get stat for update by transaction.
  184. func (d *Dao) TxStat(c context.Context, tx *sql.Tx, mid int64) (stat *model.Stat, err error) {
  185. row := tx.QueryRow(fmt.Sprintf(_getTxStatSQL, statHit(mid)), mid)
  186. stat = new(model.Stat)
  187. if err = row.Scan(&stat.Mid, &stat.Following, &stat.Whisper, &stat.Black, &stat.Follower, &stat.CTime, &stat.MTime); err != nil {
  188. if err == sql.ErrNoRows {
  189. stat = nil
  190. err = nil
  191. } else {
  192. log.Error("row.Scan() error(%v)", err)
  193. }
  194. }
  195. return
  196. }
  197. // AddStat try add stat.
  198. func (d *Dao) AddStat(c context.Context, mid int64, stat *model.Stat, now time.Time) (affected int64, err error) {
  199. var res xsql.Result
  200. if res, err = d.db.Exec(c, fmt.Sprintf(_addStatIgnoreSQL, statHit(mid)), mid, stat.Following, stat.Whisper, stat.Black, stat.Follower, now, now); err != nil {
  201. log.Error("d.db.Exec(%s, %d, %v, %v) error(%v)", _addStatIgnoreSQL, mid, stat, now, err)
  202. return
  203. }
  204. return res.RowsAffected()
  205. }
  206. // TxAddStat add params stat to stat by transaction.
  207. func (d *Dao) TxAddStat(c context.Context, tx *sql.Tx, mid int64, stat *model.Stat, now time.Time) (affected int64, err error) {
  208. var res xsql.Result
  209. if res, err = tx.Exec(fmt.Sprintf(_addStatSQL, statHit(mid)), stat.Following, stat.Whisper, stat.Black, stat.Follower, now, mid); err != nil {
  210. log.Error("tx.Exec(%s, %d, %v, %v) error(%v)", _addStatSQL, mid, stat, now, err)
  211. return
  212. }
  213. return res.RowsAffected()
  214. }
  215. // TxSetStat set stat to params stat by transaction.
  216. func (d *Dao) TxSetStat(c context.Context, tx *sql.Tx, mid int64, stat *model.Stat, now time.Time) (affected int64, err error) {
  217. var res xsql.Result
  218. if res, err = tx.Exec(fmt.Sprintf(_setStatSQL, statHit(mid)), stat.Following, stat.Whisper, stat.Black, stat.Follower, now, mid); err != nil {
  219. log.Error("tx.Exec(%s, %d, %v, %v) error(%v)", _setStatSQL, mid, stat, now, err)
  220. return
  221. }
  222. return res.RowsAffected()
  223. }
  224. // Relation get relation between mid and fid.
  225. func (d *Dao) Relation(c context.Context, mid, fid int64) (attr uint32, err error) {
  226. row := d.db.QueryRow(c, fmt.Sprintf(_getRelationSQL, hit(mid)), mid, fid)
  227. if err = row.Scan(&attr); err != nil {
  228. if err == sql.ErrNoRows {
  229. attr = model.AttrNoRelation
  230. err = nil
  231. } else {
  232. log.Error("row.Scan() error(%v)", err)
  233. }
  234. }
  235. return
  236. }
  237. // LoadMonitor load all mids into redis set.
  238. func (d *Dao) LoadMonitor(c context.Context) (mids []int64, err error) {
  239. var rows *sql.Rows
  240. if rows, err = d.db.Query(c, _loadMonitorSQL); err != nil {
  241. log.Error("d.Query.Exec(%s) error(%v)", _loadMonitorSQL, err)
  242. return
  243. }
  244. defer rows.Close()
  245. for rows.Next() {
  246. var mid int64
  247. if err = rows.Scan(&mid); err != nil {
  248. log.Error("row.Scan() error(%v)", err)
  249. mids = nil
  250. return
  251. }
  252. mids = append(mids, mid)
  253. }
  254. err = rows.Err()
  255. return
  256. }
  257. // AddMonitor add mid to monitor table
  258. func (d *Dao) AddMonitor(c context.Context, mid int64, now time.Time) (affected int64, err error) {
  259. var res xsql.Result
  260. if res, err = d.db.Exec(c, _addMonitorSQL, mid, now, now); err != nil {
  261. log.Error("d.AddMonitor.Exec(%s, %d) error(%v)", _addMonitorSQL, mid, err)
  262. return
  263. }
  264. return res.RowsAffected()
  265. }
  266. // DelMonitor del mid from monitor table
  267. func (d *Dao) DelMonitor(c context.Context, mid int64) (affected int64, err error) {
  268. var res xsql.Result
  269. if res, err = d.db.Exec(c, _delMonitorSQL, mid); err != nil {
  270. log.Error("d.DelMonitor.Exec(%s, %d)", _delMonitorSQL, mid)
  271. return
  272. }
  273. return res.RowsAffected()
  274. }
  275. // TxDelTagUser delete tag user record.
  276. func (d *Dao) TxDelTagUser(c context.Context, tx *sql.Tx, mid, fid int64) (affected int64, err error) {
  277. var res xsql.Result
  278. if res, err = tx.Exec(fmt.Sprintf(_delTagUserSQL, tagUserHit(mid)), mid, fid); err != nil {
  279. log.Error("tx.Exec(%d, %d) error(%v)", mid, fid, err)
  280. return
  281. }
  282. return res.RowsAffected()
  283. }
  284. // Tags get tags list.
  285. func (d *Dao) Tags(c context.Context, mid int64) (res map[int64]*model.Tag, err error) {
  286. var rows *sql.Rows
  287. if rows, err = d.db.Query(c, fmt.Sprintf(_getTagsSQL, tagHit(mid)), mid); err != nil {
  288. log.Error("d.getTagsStmt[%d].Query(%d) error(%sv)", tagHit(mid), mid, err)
  289. return
  290. }
  291. defer rows.Close()
  292. res = make(map[int64]*model.Tag)
  293. for rows.Next() {
  294. r := new(model.Tag)
  295. if err = rows.Scan(&r.Id, &r.Name, &r.Status, &r.MTime); err != nil {
  296. log.Error("d.getTagsStmt[%d].Query(%d) row.Scan() error(%v)", tagHit(mid), mid, err)
  297. res = nil
  298. return
  299. }
  300. res[r.Id] = r
  301. }
  302. res[0] = &model.Tag{Id: 0, Name: _defaultTag}
  303. res[-10] = &model.Tag{Id: -10, Name: _specialTag}
  304. err = rows.Err()
  305. return
  306. }
  307. // AddTag add tag.
  308. func (d *Dao) AddTag(c context.Context, mid, fid int64, tag string, now time.Time) (lastID int64, err error) {
  309. var res xsql.Result
  310. if res, err = d.db.Exec(c, fmt.Sprintf(_addTagSQL, tagHit(mid)), mid, tag, now, now); err != nil {
  311. log.Error("d.db.Exec(%s, %d, %d, %s) error(%v)", _addTagSQL, mid, fid, tag, err)
  312. return
  313. }
  314. return res.LastInsertId()
  315. }
  316. // DelTag del tag.
  317. func (d *Dao) DelTag(c context.Context, mid, id int64) (affected int64, err error) {
  318. var res xsql.Result
  319. if res, err = d.db.Exec(c, fmt.Sprintf(_delTagSQL, tagHit(mid)), id, mid); err != nil {
  320. log.Error("d.db.Exec(%s, %d, %d) error(%v)", _delTagSQL, mid, id, err)
  321. return
  322. }
  323. return res.RowsAffected()
  324. }
  325. // SetTagName update tag name info.
  326. func (d *Dao) SetTagName(c context.Context, id, mid int64, name string, now time.Time) (affected int64, err error) {
  327. var res xsql.Result
  328. if res, err = d.db.Exec(c, fmt.Sprintf(_setTagNameSQL, tagHit(mid)), name, now, id); err != nil {
  329. log.Error("d.db.Exec(%s, %s, %d, %d)", _setTagNameSQL, name, mid, id)
  330. return
  331. }
  332. return res.RowsAffected()
  333. }
  334. // TagUserByMidFid get tagIds by mid and fid.
  335. func (d *Dao) TagUserByMidFid(c context.Context, mid, fid int64) (tag *model.TagUser, err error) {
  336. row := d.db.QueryRow(c, fmt.Sprintf(_getTagsByMidFidSQL, tagUserHit(mid)), mid, fid)
  337. var tids i64b.Int64Bytes
  338. tag = new(model.TagUser)
  339. if err = row.Scan(&tag.Fid, &tids, &tag.MTime); err != nil {
  340. if err == sql.ErrNoRows {
  341. tag = nil
  342. err = nil
  343. } else {
  344. log.Error("d.getTagStmt[%d].Query(%d) row.Scan() error(%v)", tagUserHit(mid), mid, err)
  345. }
  346. return
  347. }
  348. tag.Tag = tids
  349. return
  350. }
  351. // UsersTags users tag by fids.
  352. func (d *Dao) UsersTags(c context.Context, mid int64, fid []int64) (tags map[int64]*model.TagUser, err error) {
  353. row, err := d.db.Query(c, fmt.Sprintf(_getUsersTagSQL, tagUserHit(mid), xstr.JoinInts(fid)), mid)
  354. if err != nil {
  355. return
  356. }
  357. defer row.Close()
  358. tags = make(map[int64]*model.TagUser)
  359. for row.Next() {
  360. tag := new(model.TagUser)
  361. var tids i64b.Int64Bytes
  362. if err = row.Scan(&tag.Fid, &tids); err != nil {
  363. return
  364. }
  365. tag.Tag = tids
  366. tags[tag.Fid] = tag
  367. }
  368. return
  369. }
  370. // UserTag user tag
  371. func (d *Dao) UserTag(c context.Context, mid int64) (tags map[int64][]int64, err error) {
  372. var rows *sql.Rows
  373. if rows, err = d.db.Query(c, fmt.Sprintf(_getTagUserSQL, tagUserHit(mid)), mid); err != nil {
  374. log.Error("d.Query[%d].Query(%d) error(%sv)", tagUserHit(mid), mid, err)
  375. return
  376. }
  377. defer rows.Close()
  378. tags = make(map[int64][]int64)
  379. for rows.Next() {
  380. var (
  381. tids i64b.Int64Bytes
  382. fid int64
  383. )
  384. if err = rows.Scan(&fid, &tids); err != nil {
  385. log.Error("d.Scan[%d].Query(%d) row.Scan() error(%v)", tagUserHit(mid), mid, err)
  386. tags = nil
  387. return
  388. }
  389. tags[fid] = tids
  390. }
  391. err = rows.Err()
  392. return
  393. }
  394. // SetTagUser setTagUser info.
  395. func (d *Dao) SetTagUser(c context.Context, mid, fid int64, tag i64b.Int64Bytes, now time.Time) (affected int64, err error) {
  396. var res xsql.Result
  397. if res, err = d.db.Exec(c, fmt.Sprintf(_setTagUserSQL, tagUserHit(mid)), tag.Bytes(), now, mid, fid); err != nil {
  398. log.Error("d.db.Exec(%s, %d, %d, %v) error (%v)", _setTagUserSQL, mid, fid, tag.Bytes(), err)
  399. return
  400. }
  401. return res.RowsAffected()
  402. }
  403. // AddTagUser update tag name info.
  404. func (d *Dao) AddTagUser(c context.Context, mid, fid int64, tag []int64, now time.Time) (affected int64, err error) {
  405. var res xsql.Result
  406. if res, err = d.db.Exec(c, fmt.Sprintf(_addTagUserSQL, tagUserHit(mid)), mid, fid, i64b.Int64Bytes(tag), now, now, i64b.Int64Bytes(tag)); err != nil {
  407. log.Error("d.db.Exec(%s, %d, %d, %v) error (%v)", _addTagUserSQL, mid, fid, tag, err)
  408. return
  409. }
  410. return res.RowsAffected()
  411. }
  412. // HasReachAchieve is
  413. func (d *Dao) HasReachAchieve(c context.Context, mid int64, achieve model.AchieveFlag) bool {
  414. row := d.db.QueryRow(c, _hasReachAchieve, mid, uint64(achieve))
  415. count := 0
  416. if err := row.Scan(&count); err != nil {
  417. if err == xsql.ErrNoRows {
  418. return false
  419. }
  420. log.Warn("Failed to check has reach achieve: mid: %d, achieve: %d, error: %+v", mid, achieve, err)
  421. return false
  422. }
  423. if count > 0 {
  424. return true
  425. }
  426. return false
  427. }
  428. // FollowerNotifySetting get follower-notify setting
  429. // 这里返回用户通知开关的状态(和数据库存储的状态值相反)
  430. func (d *Dao) FollowerNotifySetting(c context.Context, mid int64) (bool, error) {
  431. row := d.db.QueryRow(c, _getFollowerNotifySettingSQL, mid)
  432. var disableFollowerNotify bool
  433. if err := row.Scan(&disableFollowerNotify); err != nil {
  434. if err != sql.ErrNoRows {
  435. log.Error("row.Scan() error(%v)", err)
  436. }
  437. return true, nil
  438. }
  439. if disableFollowerNotify {
  440. return false, nil
  441. }
  442. return true, nil
  443. }
  444. // EnableFollowerNotify enable follower-notify setting
  445. func (d *Dao) EnableFollowerNotify(c context.Context, mid int64) (affected int64, err error) {
  446. var res xsql.Result
  447. if res, err = d.db.Exec(c, _enableFollowerNotifySQL, mid); err != nil {
  448. log.Error("enable follower-notify: tx.Exec(%d) error(%v)", mid, err)
  449. return
  450. }
  451. return res.RowsAffected()
  452. }
  453. // DisableFollowerNotify disable follower-notify setting
  454. func (d *Dao) DisableFollowerNotify(c context.Context, mid int64) (affected int64, err error) {
  455. var res xsql.Result
  456. if res, err = d.db.Exec(c, _disableFollowerNotifySQL, mid); err != nil {
  457. log.Error("diabel follower-notify: tx.Exec(%d) error(%v)", mid, err)
  458. return
  459. }
  460. return res.RowsAffected()
  461. }