2019-04-22 02:59:20 +00:00

701 lines
24 KiB
Go

package dao
import (
"bytes"
"context"
"fmt"
"go-common/app/service/main/favorite/model"
"go-common/library/database/sql"
"go-common/library/log"
"go-common/library/xstr"
)
const (
_folderSharding int64 = 100 // folder by mid
_relationSharding int64 = 500 // objects in folder by mid
_usersSharding int64 = 500 // objects faved by oid
_countSharding int64 = 50 // objects count by oid
// folder table
_cntFolderSQL = "SELECT COUNT(id) FROM fav_folder_%s WHERE type=? AND mid=? AND state=0"
_folderSQL = "SELECT id,type,mid,name,cover,description,count,attr,state,ctime,mtime FROM fav_folder_%s WHERE id=? AND type=? AND mid=?"
_userFoldersSQL = "SELECT id,type,mid,name,cover,description,count,attr,state,ctime,mtime FROM fav_folder_%s WHERE type=? AND mid=? AND state=0"
_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"
_folderByIdsSQL = "SELECT id,type,mid,name,cover,description,count,attr,state,ctime,mtime FROM fav_folder_%s WHERE id in (%s)"
_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"
_addFolderSQL = `INSERT INTO fav_folder_%s (type,mid,name,cover,description,count,attr,state,ctime,mtime) VALUES (?,?,?,?,?,?,?,?,?,?)
ON DUPLICATE KEY UPDATE name=?,cover=?,description=?,count=?,attr=?,state=?,ctime=?,mtime=?`
_delFolderSQL = "UPDATE fav_folder_%s SET state=1 WHERE type=? AND id=?"
_updateFolderSQL = "UPDATE fav_folder_%s SET name=?,description=?,cover=?,attr=?,state=?,mtime=? WHERE type=? AND id=?"
_upFolderNameSQL = "UPDATE IGNORE fav_folder_%s SET name=? WHERE id=?"
_upFolderAttrSQL = "UPDATE fav_folder_%s SET attr=? WHERE id=?"
// relation table
_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"
_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 ?,?"
_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 ?,?"
_relationFidsSQL = "SELECT fid FROM fav_relation_%s WHERE type=? AND mid=? AND oid=? AND state=0"
_FidsByOidsSQL = "SELECT oid,fid FROM fav_relation_%s WHERE type=? AND mid=? AND oid in (%s) AND state=0"
_cntRelationSQL = "SELECT COUNT(id) FROM fav_relation_%s FORCE INDEX(ix_fid_state_type_mtime) WHERE fid=? AND state=0 AND type=?"
_cntAllRelationSQL = "SELECT COUNT(id) FROM fav_relation_%s FORCE INDEX(ix_fid_state_sequence) WHERE fid=? AND state=0"
_addRelationSQL = "INSERT INTO fav_relation_%s (type,oid,mid,fid,state,ctime,mtime) VALUES(?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE state=?,mtime=?"
_maddRelationsSQL = "INSERT INTO fav_relation_%s (type,oid,mid,fid,state) VALUES %s ON DUPLICATE KEY UPDATE state=0"
_delRelationSQL = "UPDATE fav_relation_%s SET state=1 WHERE type=? AND fid=? AND oid=?"
_delRelationsSQL = "UPDATE fav_relation_%s SET state=1 WHERE type=? AND fid=? AND oid in (%s)"
_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"
_copyRelationsSQL = `INSERT IGNORE INTO fav_relation_%s (type,oid,mid,fid)
SELECT %d,oid,%d,%d FROM fav_relation_%s WHERE type=? AND mid=? AND fid=? AND oid in (%s) AND state=0
ON DUPLICATE KEY UPDATE state=0`
_batchOidsSQL = `SELECT oid FROM fav_relation_%s WHERE type=? AND mid=? AND state=0 LIMIT ?`
// users table
_cntUsersSQL = "SELECT COUNT(id) FROM fav_users_%s WHERE type=? AND oid=? AND state=0"
_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 ?,?"
// folderSort table
_folderSortSQL = "SELECT id,type,mid,sort,ctime,mtime FROM fav_folder_sort WHERE type=? AND mid=?"
_setFolderSortSQL = "INSERT INTO fav_folder_sort (type,mid,sort,ctime,mtime) VALUES (?,?,?,?,?) ON DUPLICATE KEY UPDATE sort=?,mtime=?"
// count table
_countSQL = "SELECT count FROM fav_count_%s WHERE type=? AND oid=?"
_countsSQL = "SELECT oid,count FROM fav_count_%s WHERE type=? AND oid in (%s)"
_folderStatSQL = "SELECT fid,play,fav,share from fav_folder_stat_%s WHERE fid in (%s)"
)
// folderHit hit table by the mod of mid and _folderSharding.
func folderHit(mid int64) string {
return fmt.Sprintf("%02d", mid%_folderSharding)
}
// relationHit hit table by the mod of mid and _relationSharding.
func relationHit(mid int64) string {
return fmt.Sprintf("%03d", mid%_relationSharding)
}
// usersHit hit table by the mod of oid and _userSharding.
func usersHit(oid int64) string {
return fmt.Sprintf("%03d", oid%_usersSharding)
}
// countHit hit table by the mod of oid and _countSharding.
func countHit(oid int64) string {
return fmt.Sprintf("%02d", oid%_countSharding)
}
// pingMySQL check mysql connection.
func (d *Dao) pingMySQL(c context.Context) error {
if err := d.dbRead.Ping(c); err != nil {
return err
}
if err := d.dbPush.Ping(c); err != nil {
return err
}
return d.db.Ping(c)
}
// Folder get a Folder by fid from mysql.
func (d *Dao) Folder(c context.Context, tp int8, mid, fid int64) (f *model.Folder, err error) {
f = new(model.Folder)
row := d.db.QueryRow(c, fmt.Sprintf(_folderSQL, folderHit(mid)), fid, tp, mid)
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 {
if err == sql.ErrNoRows {
f = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// FolderByName get a Folder by name from mysql.
func (d *Dao) FolderByName(c context.Context, tp int8, mid int64, name string) (f *model.Folder, err error) {
f = &model.Folder{}
row := d.db.QueryRow(c, fmt.Sprintf(_folderByNameSQL, folderHit(mid)), name, tp, mid)
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 {
if err == sql.ErrNoRows {
f = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// DefaultFolder get default folder from mysql.
func (d *Dao) DefaultFolder(c context.Context, tp int8, mid int64) (f *model.Folder, err error) {
f = new(model.Folder)
row := d.db.QueryRow(c, fmt.Sprintf(_defFolderSQL, folderHit(mid)), tp, mid)
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 {
if err == sql.ErrNoRows {
f = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// AddFolder add a new favorite folder to mysql.
func (d *Dao) AddFolder(c context.Context, f *model.Folder) (fid int64, err error) {
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,
f.Name, f.Cover, f.Description, f.Count, f.Attr, f.State, f.CTime, f.MTime)
if err != nil {
log.Error("db.Exec error(%v)", err)
return
}
return res.LastInsertId()
}
// UpdateFolder add a new favorite folder to mysql.
func (d *Dao) UpdateFolder(c context.Context, f *model.Folder) (fid int64, err error) {
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)
if err != nil {
log.Error("db.Exec error(%v)", err)
return
}
return res.RowsAffected()
}
// UpFolderName rename user's folder name to mysql.
func (d *Dao) UpFolderName(c context.Context, typ int8, mid, fid int64, name string) (rows int64, err error) {
res, err := d.db.Exec(c, fmt.Sprintf(_upFolderNameSQL, folderHit(mid)), name, fid)
if err != nil {
log.Error("db.Exec error(%v)", err)
return
}
return res.RowsAffected()
}
// UpFolderAttr update user's folder attr to mysql.
func (d *Dao) UpFolderAttr(c context.Context, typ int8, mid, fid int64, attr int32) (rows int64, err error) {
res, err := d.db.Exec(c, fmt.Sprintf(_upFolderAttrSQL, folderHit(mid)), attr, fid)
if err != nil {
log.Error("db.Exec error(%v)", err)
return
}
return res.RowsAffected()
}
// FolderRelations get favorite relations from mysql.
func (d *Dao) FolderRelations(c context.Context, typ int8, mid, fid int64, start, end int) (fr []*model.Favorite, err error) {
rows, err := d.db.Query(c, fmt.Sprintf(_relationsSQL, relationHit(mid)), fid, typ, start, end)
if err != nil {
log.Error("d.db.Query(%s,%d,%d,%d,%d,%d) error(%v)", fmt.Sprintf(_relationsSQL, relationHit(mid)), typ, mid, fid, start, end, err)
return
}
defer rows.Close()
fr = make([]*model.Favorite, 0)
for rows.Next() {
var r = &model.Favorite{}
if err = rows.Scan(&r.ID, &r.Type, &r.Oid, &r.Mid, &r.Fid, &r.State, &r.CTime, &r.MTime, &r.Sequence); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
if r.Type != typ || r.Mid != mid {
log.Error("dirty data relations(%d,%d,%d)", typ, mid, fid)
continue
}
fr = append(fr, r)
}
err = rows.Err()
return
}
// FolderAllRelations get favorite relations from mysql.
func (d *Dao) FolderAllRelations(c context.Context, mid, fid int64, start, end int) (fr []*model.Favorite, err error) {
rows, err := d.db.Query(c, fmt.Sprintf(_allRelationsSQL, relationHit(mid)), fid, start, end)
if err != nil {
log.Error("d.db.Query(%s,%d,%d,%d,%d,%d) error(%v)", fmt.Sprintf(_allRelationsSQL, relationHit(mid)), mid, fid, start, end, err)
return
}
defer rows.Close()
fr = make([]*model.Favorite, 0)
for rows.Next() {
var r = &model.Favorite{}
if err = rows.Scan(&r.ID, &r.Type, &r.Oid, &r.Mid, &r.Fid, &r.State, &r.CTime, &r.MTime, &r.Sequence); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
if r.Mid != mid {
log.Error("dirty data relations(%d,%d,%d)", mid, fid)
continue
}
fr = append(fr, r)
}
err = rows.Err()
return
}
// Folders get folders from mysql.
func (d *Dao) Folders(c context.Context, fvmids []*model.ArgFVmid) (fs map[string]*model.Folder, err error) {
tblMap := make(map[string][]int64, len(fvmids))
for _, fvmid := range fvmids {
folderHits := folderHit(fvmid.Vmid)
tblMap[folderHits] = append(tblMap[folderHits], fvmid.Fid)
}
fs = make(map[string]*model.Folder, len(fvmids))
for folderHit, fids := range tblMap {
fidsStr := xstr.JoinInts(fids)
var rows *sql.Rows
if rows, err = d.db.Query(c, fmt.Sprintf(_folderByIdsSQL, folderHit, fidsStr)); err != nil {
log.Error("d.db.Query(%s,%s,%s) error(%v)", _folderByIdsSQL, folderHit, fidsStr, err)
return
}
defer rows.Close()
for rows.Next() {
f := new(model.Folder)
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 {
log.Error("rows.Scan error(%v)", err)
return
}
fmid := xstr.JoinInts([]int64{f.ID, f.Mid})
fs[fmid] = f
}
err = rows.Err()
if err != nil {
return
}
}
return
}
// RelationFidsByOid get favortied folders in relations by oid from mysql.
func (d *Dao) RelationFidsByOid(c context.Context, tp int8, mid, oid int64) (fids []int64, err error) {
var fid int64
rows, err := d.db.Query(c, fmt.Sprintf(_relationFidsSQL, relationHit(mid)), tp, mid, oid)
if err != nil {
log.Error("d.db.Query(%d,%d,%d) error(%v)", tp, mid, oid, err)
return
}
defer rows.Close()
for rows.Next() {
if err = rows.Scan(&fid); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
fids = append(fids, fid)
}
err = rows.Err()
return
}
// RelationFidsByOids get favortied folders in relations by oid from mysql.
func (d *Dao) RelationFidsByOids(c context.Context, tp int8, mid int64, oids []int64) (fidsMap map[int64][]int64, err error) {
oidsStr := xstr.JoinInts(oids)
rows, err := d.dbRead.Query(c, fmt.Sprintf(_FidsByOidsSQL, relationHit(mid), oidsStr), tp, mid)
if err != nil {
log.Error("d.db.Query(%d,%d,%d) error(%v)", mid, mid, oidsStr, err)
return
}
defer rows.Close()
var oid, fid int64
fidsMap = make(map[int64][]int64, len(oids))
for rows.Next() {
if err = rows.Scan(&oid, &fid); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
fidsMap[oid] = append(fidsMap[oid], fid)
}
err = rows.Err()
return
}
// CntRelations get favoried folders count in relation from mysql.
func (d *Dao) CntRelations(c context.Context, mid, fid int64, typ int8) (count int, err error) {
row := d.db.QueryRow(c, fmt.Sprintf(_cntRelationSQL, relationHit(mid)), fid, typ)
if err = row.Scan(&count); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// CntRelations get favoried folders count in relation from mysql.
func (d *Dao) CntAllRelations(c context.Context, mid, fid int64) (count int, err error) {
row := d.db.QueryRow(c, fmt.Sprintf(_cntAllRelationSQL, relationHit(mid)), fid)
if err = row.Scan(&count); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// FolderCnt get user's folder count.
func (d *Dao) FolderCnt(c context.Context, tp int8, mid int64) (count int, err error) {
row := d.db.QueryRow(c, fmt.Sprintf(_cntFolderSQL, folderHit(mid)), tp, mid)
if err = row.Scan(&count); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// AddFav add a favorite relation to mysql.
func (d *Dao) AddFav(c context.Context, fr *model.Favorite) (rows int64, err error) {
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)
if err != nil {
log.Error("db.Exec error(%v)", err)
return
}
return res.RowsAffected()
}
// DelFav delete a favorite relation to mysql.
func (d *Dao) DelFav(c context.Context, tp int8, mid, fid, oid int64) (rows int64, err error) {
res, err := d.db.Exec(c, fmt.Sprintf(_delRelationSQL, relationHit(mid)), tp, fid, oid)
if err != nil {
log.Error("d.db.Exec(%d,%d,%d,%d) error(%v)", mid, tp, fid, oid, err)
return
}
return res.RowsAffected()
}
// AddRelation add a favorite relation to mysql.
func (d *Dao) AddRelation(c context.Context, fr *model.Favorite) (rows int64, err error) {
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)
if err != nil {
log.Error("db.Exec error(%v)", err)
return
}
return res.LastInsertId()
}
// Relation get a relation from mysql.
func (d *Dao) Relation(c context.Context, tp int8, mid, fid, oid int64) (m *model.Favorite, err error) {
m = &model.Favorite{}
row := d.db.QueryRow(c, fmt.Sprintf(_relationSQL, relationHit(mid)), tp, mid, fid, oid)
if err = row.Scan(&m.ID, &m.Type, &m.Oid, &m.Mid, &m.Fid, &m.State, &m.CTime, &m.MTime, &m.Sequence); err != nil {
if err == sql.ErrNoRows {
err = nil
m = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// DelRelation delete a favorite relation to mysql.
func (d *Dao) DelRelation(c context.Context, tp int8, mid, fid, oid int64) (rows int64, err error) {
res, err := d.db.Exec(c, fmt.Sprintf(_delRelationSQL, relationHit(mid)), tp, fid, oid)
if err != nil {
log.Error("d.db.Exec(%d,%d,%d,%d) error(%v)", mid, tp, fid, oid, err)
return
}
return res.RowsAffected()
}
// MultiDelRelations delete relations to mysql.
func (d *Dao) MultiDelRelations(c context.Context, tp int8, mid, fid int64, oids []int64) (rows int64, err error) {
if len(oids) <= 0 {
return
}
oidsStr := xstr.JoinInts(oids)
res, err := d.db.Exec(c, fmt.Sprintf(_delRelationsSQL, relationHit(mid), oidsStr), tp, fid)
if err != nil {
log.Error("d.db.Exec(%d,%d,%d,%s) error(%v)", mid, tp, fid, oidsStr, err)
return
}
return res.RowsAffected()
}
// TxMultiDelRelations delete relations to mysql.
func (d *Dao) TxMultiDelRelations(tx *sql.Tx, tp int8, mid, fid int64, oids []int64) (rows int64, err error) {
if len(oids) <= 0 {
return
}
oidsStr := xstr.JoinInts(oids)
res, err := tx.Exec(fmt.Sprintf(_delRelationsSQL, relationHit(mid), oidsStr), tp, fid)
if err != nil {
log.Error("d.db.Exec(%d,%d,%d,%s) error(%v)", mid, tp, fid, oidsStr, err)
return
}
return res.RowsAffected()
}
// MultiAddRelations insert relations to mysql.
func (d *Dao) MultiAddRelations(c context.Context, tp int8, mid, fid int64, oids []int64) (rows int64, err error) {
var buffer bytes.Buffer
valuesTpl := "(%d,%d,%d,%d,%d),"
for _, oid := range oids {
buffer.WriteString(fmt.Sprintf(valuesTpl, tp, oid, mid, fid, 0))
}
buffer.Truncate(buffer.Len() - 1)
res, err := d.db.Exec(c, fmt.Sprintf(_maddRelationsSQL, relationHit(mid), buffer.String()))
if err != nil {
log.Error("d.db.Exec(%d,%d,%d,%s) error(%v)", mid, tp, fid, oids, err)
return
}
return res.RowsAffected()
}
// DelFolder delete a folder to mysql.
func (d *Dao) DelFolder(c context.Context, tp int8, mid, fid int64) (rows int64, err error) {
res, err := d.db.Exec(c, fmt.Sprintf(_delFolderSQL, folderHit(mid)), tp, fid)
if err != nil {
log.Error("d.db.Exec(mid:%d,tp:%d,fid:%d) error(%v)", mid, tp, fid, err)
return
}
return res.RowsAffected()
}
// FolderStats get folders from mysql.
func (d *Dao) FolderStats(c context.Context, fvmids []*model.ArgFVmid) (fs map[int64]*model.Folder, err error) {
tblMap := make(map[int64][]int64, len(fvmids))
for _, fvmid := range fvmids {
tblMap[fvmid.Vmid] = append(tblMap[fvmid.Vmid], fvmid.Fid)
}
fs = make(map[int64]*model.Folder, len(fvmids))
for vmid, fids := range tblMap {
fidsStr := xstr.JoinInts(fids)
var rows *sql.Rows
if rows, err = d.db.Query(c, fmt.Sprintf(_folderStatSQL, folderHit(vmid), fidsStr)); err != nil {
log.Error("d.db.Query(%s,%s,%s) error(%v)", _folderStatSQL, folderHit(vmid), fidsStr, err)
return
}
defer rows.Close()
for rows.Next() {
stat := new(model.Folder)
if err = rows.Scan(&stat.ID, &stat.PlayCount, &stat.FavedCount, &stat.ShareCount); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
fs[stat.ID*100+vmid%100] = stat
}
err = rows.Err()
if err != nil {
return
}
}
return
}
// UserFolders get user's folders.
func (d *Dao) UserFolders(c context.Context, typ int8, mid int64) (fs map[int64]*model.Folder, err error) {
rows, err := d.db.Query(c, fmt.Sprintf(_userFoldersSQL, folderHit(mid)), typ, mid)
if err != nil {
log.Error("d.db.Query(mid:%d,typ:%d) error(%v)", mid, typ, err)
return
}
defer rows.Close()
fs = make(map[int64]*model.Folder)
for rows.Next() {
f := new(model.Folder)
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 {
log.Error("rows.Scan error(%v)", err)
return
}
fs[f.ID] = f
}
err = rows.Err()
return
}
// FolderSort return user's folders sort by type & mid.
func (d *Dao) FolderSort(c context.Context, typ int8, mid int64) (fst *model.FolderSort, err error) {
var b []byte
fst = new(model.FolderSort)
row := d.db.QueryRow(c, _folderSortSQL, typ, mid)
if err = row.Scan(&fst.ID, &fst.Type, &fst.Mid, &b, &fst.CTime, &fst.MTime); err != nil {
if err == sql.ErrNoRows {
fst = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
return
}
fst.SetIndex(b)
return
}
// UpFolderSort update user's folder sort.
func (d *Dao) UpFolderSort(c context.Context, fst *model.FolderSort) (rows int64, err error) {
sort := fst.Index()
res, err := d.db.Exec(c, _setFolderSortSQL, fst.Type, fst.Mid, sort, fst.CTime, fst.MTime, sort, fst.MTime)
if err != nil {
log.Error("d.db.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// RecentOids return user's three newest fav from a folder.
func (d *Dao) RecentOids(c context.Context, mid, fid int64, typ int8) (oids []int64, err error) {
rows, err := d.dbRead.Query(c, fmt.Sprintf(_recentOidsSQL, relationHit(mid)), fid)
if err != nil {
log.Error("d.db.Query(%d,%d) error(%v)", mid, fid, err)
return
}
defer rows.Close()
for rows.Next() {
var oid int64
var otyp int8
if err = rows.Scan(&oid, &otyp); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
if otyp == typ {
oids = append(oids, oid)
}
}
err = rows.Err()
return
}
// RecentOids return user's three newest fav from a folder.
func (d *Dao) RecentRes(c context.Context, mid, fid int64) (res []*model.Resource, err error) {
rows, err := d.dbRead.Query(c, fmt.Sprintf(_recentOidsSQL, relationHit(mid)), fid)
if err != nil {
log.Error("d.db.Query(%d,%d) error(%v)", mid, fid, err)
return
}
defer rows.Close()
for rows.Next() {
var oid int64
var typ int32
if err = rows.Scan(&oid, &typ); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
res = append(res, &model.Resource{Oid: oid, Typ: typ})
}
err = rows.Err()
return
}
// TxCopyRelations copy resources from oldfid to newfid by oids.
func (d *Dao) TxCopyRelations(tx *sql.Tx, typ int8, oldmid, mid, oldfid, newfid int64, oids []int64) (rows int64, err error) {
res, err := tx.Exec(fmt.Sprintf(_copyRelationsSQL, relationHit(mid), typ, mid, newfid, relationHit(oldmid), xstr.JoinInts(oids)), typ, oldmid, oldfid)
if err != nil {
log.Error("db.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// CopyRelations copy resources from oldfid to newfid by oids.
func (d *Dao) CopyRelations(c context.Context, typ int8, oldmid, mid, oldfid, newfid int64, oids []int64) (rows int64, err error) {
res, err := d.db.Exec(c, fmt.Sprintf(_copyRelationsSQL, relationHit(mid), typ, mid, newfid, relationHit(oldmid), xstr.JoinInts(oids)), typ, oldmid, oldfid)
if err != nil {
log.Error("db.Exec() error(%v)", err)
return
}
return res.RowsAffected()
}
// CntUsers get favoried users count from mysql.
func (d *Dao) CntUsers(c context.Context, typ int8, oid int64) (count int, err error) {
row := d.dbPush.QueryRow(c, fmt.Sprintf(_cntUsersSQL, usersHit(oid)), typ, oid)
if err = row.Scan(&count); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// Users get favorite users from mysql.
func (d *Dao) Users(c context.Context, typ int8, oid int64, start, end int) (us []*model.User, err error) {
rows, err := d.dbPush.Query(c, fmt.Sprintf(_usersSQL, usersHit(oid)), typ, oid, start, end)
if err != nil {
log.Error("d.db.Query(%d,%d,%d,%d) error(%v)", typ, oid, start, end, err)
return
}
defer rows.Close()
us = make([]*model.User, 0)
for rows.Next() {
var u = new(model.User)
if err = rows.Scan(&u.ID, &u.Type, &u.Oid, &u.Mid, &u.State, &u.CTime, &u.MTime); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
us = append(us, u)
}
err = rows.Err()
return
}
// OidCount get oid's fav count from mysql.
func (d *Dao) OidCount(c context.Context, typ int8, oid int64) (count int64, err error) {
row := d.dbPush.QueryRow(c, fmt.Sprintf(_countSQL, countHit(oid)), typ, oid)
if err = row.Scan(&count); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// OidsCount get oids's count from mysql.
func (d *Dao) OidsCount(c context.Context, typ int8, oids []int64) (counts map[int64]int64, err error) {
tblMap := make(map[string][]int64, len(oids))
for _, oid := range oids {
countHit := countHit(oid)
tblMap[countHit] = append(tblMap[countHit], oid)
}
counts = make(map[int64]int64, len(oids))
for countHit, oids := range tblMap {
oidsStr := xstr.JoinInts(oids)
var rows *sql.Rows
if rows, err = d.db.Query(c, fmt.Sprintf(_countsSQL, countHit, oidsStr), typ); err != nil {
log.Error("d.db.Query(%s,%d) error(%v)", fmt.Sprintf(_countsSQL, countHit, oidsStr), typ, err)
return
}
defer rows.Close()
for rows.Next() {
var oid, count int64
if err = rows.Scan(&oid, &count); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
counts[oid] = count
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
return
}
}
return
}
// BatchOids get batch oids from mysql.
func (d *Dao) BatchOids(c context.Context, typ int8, mid int64, limit int) (oids []int64, err error) {
rows, err := d.dbRead.Query(c, fmt.Sprintf(_batchOidsSQL, relationHit(mid)), typ, mid, limit)
if err != nil {
log.Error("d.db.Query(%d,%d,%d) error(%v)", typ, mid, limit, err)
return
}
defer rows.Close()
for rows.Next() {
var oid int64
if err = rows.Scan(&oid); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
oids = append(oids, oid)
}
if err = rows.Err(); err != nil {
log.Error("rows.Err() error(%v)", err)
}
return
}