github.com/Azareal/Gosora@v0.0.0-20210729070923-553e66b59003/common/reply_store.go (about)

     1  package common
     2  
     3  //import "log"
     4  import (
     5  	"database/sql"
     6  
     7  	qgen "github.com/Azareal/Gosora/query_gen"
     8  )
     9  
    10  var Rstore ReplyStore
    11  
    12  type ReplyStore interface {
    13  	Get(id int) (*Reply, error)
    14  	Each(f func(*Reply) error) error
    15  	Exists(id int) bool
    16  	ClearIPs() error
    17  	Create(t *Topic, content, ip string, uid int) (id int, err error)
    18  	Count() (count int)
    19  	CountUser(uid int) (count int)
    20  	CountMegaUser(uid int) (count int)
    21  	CountBigUser(uid int) (count int)
    22  
    23  	SetCache(cache ReplyCache)
    24  	GetCache() ReplyCache
    25  }
    26  
    27  type SQLReplyStore struct {
    28  	cache ReplyCache
    29  
    30  	get           *sql.Stmt
    31  	getAll        *sql.Stmt
    32  	exists        *sql.Stmt
    33  	create        *sql.Stmt
    34  	count         *sql.Stmt
    35  	countUser     *sql.Stmt
    36  	countWordUser *sql.Stmt
    37  
    38  	clearIPs *sql.Stmt
    39  }
    40  
    41  func NewSQLReplyStore(acc *qgen.Accumulator, cache ReplyCache) (*SQLReplyStore, error) {
    42  	if cache == nil {
    43  		cache = NewNullReplyCache()
    44  	}
    45  	re := "replies"
    46  	return &SQLReplyStore{
    47  		cache:         cache,
    48  		get:           acc.Select(re).Columns("tid,content,createdBy,createdAt,lastEdit,lastEditBy,ip,likeCount,attachCount,actionType").Where("rid=?").Prepare(),
    49  		getAll:        acc.Select(re).Columns("rid,tid,content,createdBy,createdAt,lastEdit,lastEditBy,ip,likeCount,attachCount,actionType").Prepare(),
    50  		exists:        acc.Exists(re, "rid").Prepare(),
    51  		create:        acc.Insert(re).Columns("tid,content,parsed_content,createdAt,lastUpdated,ip,words,createdBy").Fields("?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?").Prepare(),
    52  		count:         acc.Count(re).Prepare(),
    53  		countUser:     acc.Count(re).Where("createdBy=?").Prepare(),
    54  		countWordUser: acc.Count(re).Where("createdBy=? AND words>=?").Prepare(),
    55  
    56  		clearIPs: acc.Update(re).Set("ip=''").Where("ip!=''").Stmt(),
    57  	}, acc.FirstError()
    58  }
    59  
    60  func (s *SQLReplyStore) Get(id int) (*Reply, error) {
    61  	r, err := s.cache.Get(id)
    62  	if err == nil {
    63  		return r, nil
    64  	}
    65  
    66  	r = &Reply{ID: id}
    67  	err = s.get.QueryRow(id).Scan(&r.ParentID, &r.Content, &r.CreatedBy, &r.CreatedAt, &r.LastEdit, &r.LastEditBy, &r.IP, &r.LikeCount, &r.AttachCount, &r.ActionType)
    68  	if err == nil {
    69  		_ = s.cache.Set(r)
    70  	}
    71  	return r, err
    72  }
    73  
    74  /*func (s *SQLReplyStore) eachr(f func(*sql.Rows) error) error {
    75  	return eachall(s.getAll, f)
    76  }*/
    77  
    78  func (s *SQLReplyStore) Each(f func(*Reply) error) error {
    79  	rows, err := s.getAll.Query()
    80  	if err != nil {
    81  		return err
    82  	}
    83  	defer rows.Close()
    84  	for rows.Next() {
    85  		r := new(Reply)
    86  		if err := rows.Scan(&r.ID, &r.ParentID, &r.Content, &r.CreatedBy, &r.CreatedAt, &r.LastEdit, &r.LastEditBy, &r.IP, &r.LikeCount, &r.AttachCount, &r.ActionType); err != nil {
    87  			return err
    88  		}
    89  		if err := f(r); err != nil {
    90  			return err
    91  		}
    92  	}
    93  	return rows.Err()
    94  }
    95  
    96  func (s *SQLReplyStore) Exists(id int) bool {
    97  	err := s.exists.QueryRow(id).Scan(&id)
    98  	if err != nil && err != ErrNoRows {
    99  		LogError(err)
   100  	}
   101  	return err != ErrNoRows
   102  }
   103  
   104  func (s *SQLReplyStore) ClearIPs() error {
   105  	_, e := s.clearIPs.Exec()
   106  	return e
   107  }
   108  
   109  // TODO: Write a test for this
   110  func (s *SQLReplyStore) Create(t *Topic, content, ip string, uid int) (id int, err error) {
   111  	if Config.DisablePostIP {
   112  		ip = ""
   113  	}
   114  	res, err := s.create.Exec(t.ID, content, ParseMessage(content, t.ParentID, "forums", nil, nil), ip, WordCount(content), uid)
   115  	if err != nil {
   116  		return 0, err
   117  	}
   118  	lastID, err := res.LastInsertId()
   119  	if err != nil {
   120  		return 0, err
   121  	}
   122  	id = int(lastID)
   123  	return id, t.AddReply(id, uid)
   124  }
   125  
   126  // TODO: Write a test for this
   127  // Count returns the total number of topic replies on these forums
   128  func (s *SQLReplyStore) Count() (count int) {
   129  	return Countf(s.count)
   130  }
   131  func (s *SQLReplyStore) CountUser(uid int) (count int) {
   132  	return Countf(s.countUser, uid)
   133  }
   134  func (s *SQLReplyStore) CountMegaUser(uid int) (count int) {
   135  	return Countf(s.countWordUser, uid, SettingBox.Load().(SettingMap)["megapost_min_words"].(int))
   136  }
   137  func (s *SQLReplyStore) CountBigUser(uid int) (count int) {
   138  	return Countf(s.countWordUser, uid, SettingBox.Load().(SettingMap)["bigpost_min_words"].(int))
   139  }
   140  
   141  func (s *SQLReplyStore) SetCache(cache ReplyCache) {
   142  	s.cache = cache
   143  }
   144  
   145  func (s *SQLReplyStore) GetCache() ReplyCache {
   146  	return s.cache
   147  }