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 }