package common import ( "database/sql" qgen "github.com/Azareal/Gosora/query_gen" ) var GroupPromotions *DefaultGroupPromotionStore type GroupPromotion struct { ID int From int To int TwoWay bool Level int MinTime int } type GroupPromotionStore interface { GetByGroup() ([]*GroupPromotion, error) Get(id int) (*GroupPromotion, error) PromoteIfEligible(u *User, level int) error Delete(id int) error Create(from int, to int, twoWay bool, level int) (int, error) } type DefaultGroupPromotionStore struct { getByGroup *sql.Stmt get *sql.Stmt delete *sql.Stmt create *sql.Stmt getByUser *sql.Stmt updateUser *sql.Stmt } func NewDefaultGroupPromotionStore(acc *qgen.Accumulator) (*DefaultGroupPromotionStore, error) { ugp := "users_groups_promotions" return &DefaultGroupPromotionStore{ getByGroup: acc.Select(ugp).Columns("pid, from_gid, to_gid, two_way, level, minTime").Where("from_gid=? OR to_gid=?").Prepare(), get: acc.Select(ugp).Columns("from_gid, to_gid, two_way, level, minTime").Where("pid = ?").Prepare(), delete: acc.Delete(ugp).Where("pid = ?").Prepare(), create: acc.Insert(ugp).Columns("from_gid, to_gid, two_way, level, minTime").Fields("?,?,?,?,?").Prepare(), getByUser: acc.Select(ugp).Columns("pid, to_gid, two_way, level, minTime").Where("from_gid=? AND level>=?").Orderby("level DESC").Limit("1").Prepare(), updateUser: acc.Update("users").Set("group = ?").Where("level >= ?").Prepare(), }, acc.FirstError() } func (s *DefaultGroupPromotionStore) GetByGroup(gid int) (gps []*GroupPromotion, err error) { rows, err := s.getByGroup.Query(gid, gid) if err != nil { return nil, err } defer rows.Close() for rows.Next() { g := &GroupPromotion{} err := rows.Scan(&g.ID, &g.From, &g.To, &g.TwoWay, &g.Level, &g.MinTime) if err != nil { return nil, err } gps = append(gps, g) } return gps, rows.Err() } // TODO: Cache the group promotions to avoid hitting the database as much func (s *DefaultGroupPromotionStore) Get(id int) (*GroupPromotion, error) { /*g, err := s.cache.Get(id) if err == nil { return u, nil }*/ g := &GroupPromotion{ID: id} err := s.get.QueryRow(id).Scan(&g.From, &g.To, &g.TwoWay, &g.Level, &g.MinTime) if err == nil { //s.cache.Set(u) } return g, err } func (s *DefaultGroupPromotionStore) PromoteIfEligible(u *User, level int) error { g := &GroupPromotion{From: u.Group} err := s.getByUser.QueryRow(u.Group, level).Scan(&g.ID, &g.To, &g.TwoWay, &g.Level, &g.MinTime) if err == sql.ErrNoRows { return nil } else if err != nil { return err } _, err = s.updateUser.Exec(g.To, g.Level) return err } func (s *DefaultGroupPromotionStore) Delete(id int) error { _, err := s.delete.Exec(id) return err } func (s *DefaultGroupPromotionStore) Create(from int, to int, twoWay bool, level int) (int, error) { res, err := s.create.Exec(from, to, twoWay, level, 0) if err != nil { return 0, err } lastID, err := res.LastInsertId() return int(lastID), err }