Add BulkGetByName method to UserStore.
Add RawBulkGetByNameForConvo method to UserStore. Add ErrSomeUsersNotFound error. User Manager Search Experiment. De-duplicate common user store scan logic. Use inqbuild in BulkGetMap in UserStore.
This commit is contained in:
parent
8decc0c1a8
commit
9437561c76
@ -14,12 +14,15 @@ import (
|
|||||||
var Users UserStore
|
var Users UserStore
|
||||||
var ErrAccountExists = errors.New("this username is already in use")
|
var ErrAccountExists = errors.New("this username is already in use")
|
||||||
var ErrLongUsername = errors.New("this username is too long")
|
var ErrLongUsername = errors.New("this username is too long")
|
||||||
|
var ErrSomeUsersNotFound = errors.New("Unable to find some users")
|
||||||
|
|
||||||
type UserStore interface {
|
type UserStore interface {
|
||||||
DirtyGet(id int) *User
|
DirtyGet(id int) *User
|
||||||
Get(id int) (*User, error)
|
Get(id int) (*User, error)
|
||||||
Getn(id int) *User
|
Getn(id int) *User
|
||||||
GetByName(name string) (*User, error)
|
GetByName(name string) (*User, error)
|
||||||
|
BulkGetByName(names []string) (list []*User, err error)
|
||||||
|
RawBulkGetByNameForConvo(f func(int, string, int, bool, int, int) error, names []string) error
|
||||||
Exists(id int) bool
|
Exists(id int) bool
|
||||||
SearchOffset(name, email string, gid, offset, perPage int) (users []*User, err error)
|
SearchOffset(name, email string, gid, offset, perPage int) (users []*User, err error)
|
||||||
GetOffset(offset, perPage int) ([]*User, error)
|
GetOffset(offset, perPage int) ([]*User, error)
|
||||||
@ -66,7 +69,7 @@ func NewDefaultUserStore(cache UserCache) (*DefaultUserStore, error) {
|
|||||||
|
|
||||||
get: acc.Select(u).Columns("name,group,active,is_super_admin,session,email,avatar,message,level,score,posts,liked,last_ip,temp_group,createdAt,enable_embeds,profile_comments,who_can_convo").Where("uid=?").Prepare(),
|
get: acc.Select(u).Columns("name,group,active,is_super_admin,session,email,avatar,message,level,score,posts,liked,last_ip,temp_group,createdAt,enable_embeds,profile_comments,who_can_convo").Where("uid=?").Prepare(),
|
||||||
getByName: acc.Select(u).Columns(allCols).Where("name=?").Prepare(),
|
getByName: acc.Select(u).Columns(allCols).Where("name=?").Prepare(),
|
||||||
searchOffset: acc.Select(u).Columns(allCols).Where("(name=? OR ?='') AND (email=? OR ?='') AND (group=? OR ?='')").Orderby("uid ASC").Limit("?,?").Prepare(),
|
searchOffset: acc.Select(u).Columns(allCols).Where("(name=? OR ?='') AND (email=? OR ?='') AND (group=? OR ?=0)").Orderby("uid ASC").Limit("?,?").Prepare(),
|
||||||
getOffset: acc.Select(u).Columns(allCols).Orderby("uid ASC").Limit("?,?").Prepare(),
|
getOffset: acc.Select(u).Columns(allCols).Orderby("uid ASC").Limit("?,?").Prepare(),
|
||||||
getAll: acc.Select(u).Columns(allCols).Prepare(),
|
getAll: acc.Select(u).Columns(allCols).Prepare(),
|
||||||
|
|
||||||
@ -75,7 +78,7 @@ func NewDefaultUserStore(cache UserCache) (*DefaultUserStore, error) {
|
|||||||
nameExists: acc.Exists(u, "name").Prepare(),
|
nameExists: acc.Exists(u, "name").Prepare(),
|
||||||
|
|
||||||
count: acc.Count(u).Prepare(),
|
count: acc.Count(u).Prepare(),
|
||||||
countSearch: acc.Count(u).Where("(name=? OR ?='') AND (email=? OR ?='') AND (group=? OR ?='')").Prepare(),
|
countSearch: acc.Count(u).Where("(name LIKE ('%'+?+'%') OR ?='') AND (email=? OR ?='') AND (group=? OR ?=0)").Prepare(),
|
||||||
}, acc.FirstError()
|
}, acc.FirstError()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,6 +93,11 @@ func (s *DefaultUserStore) DirtyGet(id int) *User {
|
|||||||
return BlankUser()
|
return BlankUser()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *DefaultUserStore) scanUser(r *sql.Row, u *User) (embeds int, err error) {
|
||||||
|
e := r.Scan(&u.Name, &u.Group, &u.Active, &u.IsSuperAdmin, &u.Session, &u.Email, &u.RawAvatar, &u.Message, &u.Level, &u.Score, &u.Posts, &u.Liked, &u.LastIP, &u.TempGroup, &u.CreatedAt, &embeds, &u.Privacy.ShowComments, &u.Privacy.AllowMessage)
|
||||||
|
return embeds, e
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Log weird cache errors? Not just here but in every *Cache?
|
// TODO: Log weird cache errors? Not just here but in every *Cache?
|
||||||
func (s *DefaultUserStore) Get(id int) (*User, error) {
|
func (s *DefaultUserStore) Get(id int) (*User, error) {
|
||||||
u, err := s.cache.Get(id)
|
u, err := s.cache.Get(id)
|
||||||
@ -102,8 +110,7 @@ func (s *DefaultUserStore) Get(id int) (*User, error) {
|
|||||||
//log.Print("uncached user")
|
//log.Print("uncached user")
|
||||||
|
|
||||||
u = &User{ID: id, Loggedin: true}
|
u = &User{ID: id, Loggedin: true}
|
||||||
var embeds int
|
embeds, err := s.scanUser(s.get.QueryRow(id), u)
|
||||||
err = s.get.QueryRow(id).Scan(&u.Name, &u.Group, &u.Active, &u.IsSuperAdmin, &u.Session, &u.Email, &u.RawAvatar, &u.Message, &u.Level, &u.Score, &u.Posts, &u.Liked, &u.LastIP, &u.TempGroup, &u.CreatedAt, &embeds, &u.Privacy.ShowComments, &u.Privacy.AllowMessage)
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if embeds != -1 {
|
if embeds != -1 {
|
||||||
u.ParseSettings = DefaultParseSettings.CopyPtr()
|
u.ParseSettings = DefaultParseSettings.CopyPtr()
|
||||||
@ -122,8 +129,7 @@ func (s *DefaultUserStore) Getn(id int) *User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u = &User{ID: id, Loggedin: true}
|
u = &User{ID: id, Loggedin: true}
|
||||||
var embeds int
|
embeds, err := s.scanUser(s.get.QueryRow(id), u)
|
||||||
err := s.get.QueryRow(id).Scan(&u.Name, &u.Group, &u.Active, &u.IsSuperAdmin, &u.Session, &u.Email, &u.RawAvatar, &u.Message, &u.Level, &u.Score, &u.Posts, &u.Liked, &u.LastIP, &u.TempGroup, &u.CreatedAt, &embeds, &u.Privacy.ShowComments, &u.Privacy.AllowMessage)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -154,6 +160,74 @@ func (s *DefaultUserStore) GetByName(name string) (*User, error) {
|
|||||||
return u, nil
|
return u, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Optimise the query to avoid preparing it on the spot? Maybe, use knowledge of the most common IN() parameter counts?
|
||||||
|
// ! This bypasses the cache, use frugally
|
||||||
|
func (s *DefaultUserStore) BulkGetByName(names []string) (list []*User, err error) {
|
||||||
|
if len(names) == 0 {
|
||||||
|
return list, nil
|
||||||
|
} else if len(names) == 1 {
|
||||||
|
user, err := s.GetByName(names[0])
|
||||||
|
if err != nil {
|
||||||
|
return list, err
|
||||||
|
}
|
||||||
|
return []*User{user}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
idList, q := inqbuildstr(names)
|
||||||
|
rows, err := qgen.NewAcc().Select("users").Columns("uid,name,group,active,is_super_admin,session,email,avatar,message,level,score,posts,liked,last_ip,temp_group,createdAt,enable_embeds,profile_comments,who_can_convo").Where("name IN(" + q + ")").Query(idList...)
|
||||||
|
if err != nil {
|
||||||
|
return list, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var embeds int
|
||||||
|
for rows.Next() {
|
||||||
|
u := &User{Loggedin: true}
|
||||||
|
err := rows.Scan(&u.ID, &u.Name, &u.Group, &u.Active, &u.IsSuperAdmin, &u.Session, &u.Email, &u.RawAvatar, &u.Message, &u.Level, &u.Score, &u.Posts, &u.Liked, &u.LastIP, &u.TempGroup, &u.CreatedAt, &embeds, &u.Privacy.ShowComments, &u.Privacy.AllowMessage)
|
||||||
|
if err != nil {
|
||||||
|
return list, err
|
||||||
|
}
|
||||||
|
if embeds != -1 {
|
||||||
|
u.ParseSettings = DefaultParseSettings.CopyPtr()
|
||||||
|
u.ParseSettings.NoEmbed = embeds == 0
|
||||||
|
}
|
||||||
|
u.Init()
|
||||||
|
s.cache.Set(u)
|
||||||
|
list[u.ID] = u
|
||||||
|
}
|
||||||
|
if err = rows.Err(); err != nil {
|
||||||
|
return list, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Did we miss any users?
|
||||||
|
if len(names) > len(list) {
|
||||||
|
return list, ErrSomeUsersNotFound
|
||||||
|
}
|
||||||
|
return list, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special case function for efficiency
|
||||||
|
func (s *DefaultUserStore) RawBulkGetByNameForConvo(f func(int, string, int, bool, int, int) error, names []string) error {
|
||||||
|
idList, q := inqbuildstr(names)
|
||||||
|
rows, e := qgen.NewAcc().Select("users").Columns("uid,name,group,is_super_admin,temp_group,who_can_convo").Where("name IN(" + q + ")").Query(idList...)
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
for rows.Next() {
|
||||||
|
var name string
|
||||||
|
var id, group, temp_group, who_can_convo int
|
||||||
|
var super_admin bool
|
||||||
|
if e = rows.Scan(&id, &name, &group, &super_admin, &temp_group, &who_can_convo); e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
if e = f(id, name, group, super_admin, temp_group, who_can_convo); e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rows.Err()
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Optimise this, so we don't wind up hitting the database every-time for small gaps
|
// TODO: Optimise this, so we don't wind up hitting the database every-time for small gaps
|
||||||
// TODO: Make this a little more consistent with DefaultGroupStore's GetRange method
|
// TODO: Make this a little more consistent with DefaultGroupStore's GetRange method
|
||||||
func (s *DefaultUserStore) GetOffset(offset, perPage int) (users []*User, err error) {
|
func (s *DefaultUserStore) GetOffset(offset, perPage int) (users []*User, err error) {
|
||||||
@ -262,15 +336,7 @@ func (s *DefaultUserStore) BulkGetMap(ids []int) (list map[int]*User, err error)
|
|||||||
return list, nil
|
return list, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add a function for the q stuff
|
idList, q := inqbuild(ids)
|
||||||
var q string
|
|
||||||
idList := make([]interface{}, len(ids))
|
|
||||||
for i, id := range ids {
|
|
||||||
idList[i] = strconv.Itoa(id)
|
|
||||||
q += "?,"
|
|
||||||
}
|
|
||||||
q = q[0 : len(q)-1]
|
|
||||||
|
|
||||||
rows, err := qgen.NewAcc().Select("users").Columns("uid,name,group,active,is_super_admin,session,email,avatar,message,level,score,posts,liked,last_ip,temp_group,createdAt,enable_embeds,profile_comments,who_can_convo").Where("uid IN(" + q + ")").Query(idList...)
|
rows, err := qgen.NewAcc().Select("users").Columns("uid,name,group,active,is_super_admin,session,email,avatar,message,level,score,posts,liked,last_ip,temp_group,createdAt,enable_embeds,profile_comments,who_can_convo").Where("uid IN(" + q + ")").Query(idList...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return list, err
|
return list, err
|
||||||
@ -316,8 +382,7 @@ func (s *DefaultUserStore) BulkGetMap(ids []int) (list map[int]*User, err error)
|
|||||||
|
|
||||||
func (s *DefaultUserStore) BypassGet(id int) (*User, error) {
|
func (s *DefaultUserStore) BypassGet(id int) (*User, error) {
|
||||||
u := &User{ID: id, Loggedin: true}
|
u := &User{ID: id, Loggedin: true}
|
||||||
var embeds int
|
embeds, err := s.scanUser(s.get.QueryRow(id), u)
|
||||||
err := s.get.QueryRow(id).Scan(&u.Name, &u.Group, &u.Active, &u.IsSuperAdmin, &u.Session, &u.Email, &u.RawAvatar, &u.Message, &u.Level, &u.Score, &u.Posts, &u.Liked, &u.LastIP, &u.TempGroup, &u.CreatedAt, &embeds, &u.Privacy.ShowComments, &u.Privacy.AllowMessage)
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if embeds != -1 {
|
if embeds != -1 {
|
||||||
u.ParseSettings = DefaultParseSettings.CopyPtr()
|
u.ParseSettings = DefaultParseSettings.CopyPtr()
|
||||||
|
Loading…
Reference in New Issue
Block a user