Add Resultsf() to *Poll.
Optimise PollResults() with a byte buffer.
This commit is contained in:
parent
ca0117f42e
commit
d91897efe4
|
@ -28,30 +28,49 @@ func (p *Poll) CastVote(optionIndex, uid int, ip string) error {
|
||||||
if Config.DisablePollIP || !p.AntiCheat {
|
if Config.DisablePollIP || !p.AntiCheat {
|
||||||
ip = ""
|
ip = ""
|
||||||
}
|
}
|
||||||
_, err := pollStmts.addVote.Exec(p.ID, uid, optionIndex, ip)
|
_, e := pollStmts.addVote.Exec(p.ID, uid, optionIndex, ip)
|
||||||
if err != nil {
|
if e != nil {
|
||||||
return err
|
return e
|
||||||
}
|
}
|
||||||
_, err = pollStmts.incVoteCount.Exec(p.ID)
|
_, e = pollStmts.incVoteCount.Exec(p.ID)
|
||||||
if err != nil {
|
if e != nil {
|
||||||
return err
|
return e
|
||||||
}
|
}
|
||||||
_, err = pollStmts.incVoteCountForOption.Exec(optionIndex, p.ID)
|
_, e = pollStmts.incVoteCountForOption.Exec(optionIndex, p.ID)
|
||||||
return err
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Poll) Delete() error {
|
func (p *Poll) Delete() error {
|
||||||
_, err := pollStmts.deletePollVotes.Exec(p.ID)
|
_, e := pollStmts.deletePollVotes.Exec(p.ID)
|
||||||
if err != nil {
|
if e != nil {
|
||||||
return err
|
return e
|
||||||
}
|
}
|
||||||
_, err = pollStmts.deletePollOptions.Exec(p.ID)
|
_, e = pollStmts.deletePollOptions.Exec(p.ID)
|
||||||
if err != nil {
|
if e != nil {
|
||||||
return err
|
return e
|
||||||
}
|
}
|
||||||
_, err = pollStmts.deletePoll.Exec(p.ID)
|
_, e = pollStmts.deletePoll.Exec(p.ID)
|
||||||
_ = Polls.GetCache().Remove(p.ID)
|
_ = Polls.GetCache().Remove(p.ID)
|
||||||
return err
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Poll) Resultsf(f func(votes int) error) error {
|
||||||
|
rows, e := pollStmts.getResults.Query(p.ID)
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var votes int
|
||||||
|
for rows.Next() {
|
||||||
|
if e := rows.Scan(&votes); e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
if e := f(votes); e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rows.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Poll) Copy() Poll {
|
func (p *Poll) Copy() Poll {
|
||||||
|
@ -59,9 +78,12 @@ func (p *Poll) Copy() Poll {
|
||||||
}
|
}
|
||||||
|
|
||||||
type PollStmts struct {
|
type PollStmts struct {
|
||||||
|
getResults *sql.Stmt
|
||||||
|
|
||||||
addVote *sql.Stmt
|
addVote *sql.Stmt
|
||||||
incVoteCount *sql.Stmt
|
incVoteCount *sql.Stmt
|
||||||
incVoteCountForOption *sql.Stmt
|
incVoteCountForOption *sql.Stmt
|
||||||
|
|
||||||
deletePoll *sql.Stmt
|
deletePoll *sql.Stmt
|
||||||
deletePollOptions *sql.Stmt
|
deletePollOptions *sql.Stmt
|
||||||
deletePollVotes *sql.Stmt
|
deletePollVotes *sql.Stmt
|
||||||
|
@ -70,13 +92,17 @@ type PollStmts struct {
|
||||||
func init() {
|
func init() {
|
||||||
DbInits.Add(func(acc *qgen.Accumulator) error {
|
DbInits.Add(func(acc *qgen.Accumulator) error {
|
||||||
p := "polls"
|
p := "polls"
|
||||||
|
wh := "pollID=?"
|
||||||
pollStmts = PollStmts{
|
pollStmts = PollStmts{
|
||||||
|
getResults: acc.Select("polls_options").Columns("votes").Where("pollID=?").Orderby("option ASC").Prepare(),
|
||||||
|
|
||||||
addVote: acc.Insert("polls_votes").Columns("pollID,uid,option,castAt,ip").Fields("?,?,?,UTC_TIMESTAMP(),?").Prepare(),
|
addVote: acc.Insert("polls_votes").Columns("pollID,uid,option,castAt,ip").Fields("?,?,?,UTC_TIMESTAMP(),?").Prepare(),
|
||||||
incVoteCount: acc.Update(p).Set("votes = votes + 1").Where("pollID=?").Prepare(),
|
incVoteCount: acc.Update(p).Set("votes=votes+1").Where(wh).Prepare(),
|
||||||
incVoteCountForOption: acc.Update("polls_options").Set("votes=votes+1").Where("option=? AND pollID=?").Prepare(),
|
incVoteCountForOption: acc.Update("polls_options").Set("votes=votes+1").Where("option=? AND pollID=?").Prepare(),
|
||||||
deletePoll: acc.Delete(p).Where("pollID=?").Prepare(),
|
|
||||||
deletePollOptions: acc.Delete("polls_options").Where("pollID=?").Prepare(),
|
deletePoll: acc.Delete(p).Where(wh).Prepare(),
|
||||||
deletePollVotes: acc.Delete("polls_votes").Where("pollID=?").Prepare(),
|
deletePollOptions: acc.Delete("polls_options").Where(wh).Prepare(),
|
||||||
|
deletePollVotes: acc.Delete("polls_votes").Where(wh).Prepare(),
|
||||||
}
|
}
|
||||||
return acc.FirstError()
|
return acc.FirstError()
|
||||||
})
|
})
|
||||||
|
|
26
misc_test.go
26
misc_test.go
|
@ -1546,6 +1546,32 @@ func TestPolls(t *testing.T) {
|
||||||
expectNilErr(t, e)
|
expectNilErr(t, e)
|
||||||
testPoll(p, 1, tid, "topics", 0, false, 1)
|
testPoll(p, 1, tid, "topics", 0, false, 1)
|
||||||
|
|
||||||
|
var vslice []int
|
||||||
|
expectNilErr(t, p.Resultsf(func(votes int) error {
|
||||||
|
vslice = append(vslice, votes)
|
||||||
|
return nil
|
||||||
|
}))
|
||||||
|
//fmt.Printf("vslice: %+v\n", vslice)
|
||||||
|
exf(vslice[0] == 1, "vslice[0] should be %d not %d", 0, vslice[0])
|
||||||
|
exf(vslice[1] == 0, "vslice[1] should be %d not %d", 1, vslice[1])
|
||||||
|
exf(vslice[2] == 0, "vslice[2] should be %d not %d", 0, vslice[2])
|
||||||
|
|
||||||
|
expectNilErr(t, p.CastVote(2, 1, ""))
|
||||||
|
expectNilErr(t, c.Polls.Reload(p.ID))
|
||||||
|
p, e = c.Polls.Get(1)
|
||||||
|
expectNilErr(t, e)
|
||||||
|
testPoll(p, 1, tid, "topics", 0, false, 2)
|
||||||
|
|
||||||
|
vslice = nil
|
||||||
|
expectNilErr(t, p.Resultsf(func(votes int) error {
|
||||||
|
vslice = append(vslice, votes)
|
||||||
|
return nil
|
||||||
|
}))
|
||||||
|
//fmt.Printf("vslice: %+v\n", vslice)
|
||||||
|
exf(vslice[0] == 1, "vslice[0] should be %d not %d", 1, vslice[0])
|
||||||
|
exf(vslice[1] == 0, "vslice[1] should be %d not %d", 0, vslice[1])
|
||||||
|
exf(vslice[2] == 1, "vslice[2] should be %d not %d", 1, vslice[2])
|
||||||
|
|
||||||
expectNilErr(t, c.Polls.ClearIPs())
|
expectNilErr(t, c.Polls.ClearIPs())
|
||||||
// TODO: Test to see if it worked
|
// TODO: Test to see if it worked
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package routes
|
package routes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
c "github.com/Azareal/Gosora/common"
|
c "github.com/Azareal/Gosora/common"
|
||||||
qgen "github.com/Azareal/Gosora/query_gen"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func PollVote(w http.ResponseWriter, r *http.Request, u *c.User, sPollID string) c.RouteError {
|
func PollVote(w http.ResponseWriter, r *http.Request, u *c.User, sPollID string) c.RouteError {
|
||||||
|
@ -78,29 +78,23 @@ func PollResults(w http.ResponseWriter, r *http.Request, u *c.User, sPollID stri
|
||||||
return c.InternalError(err, w, r)
|
return c.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Abstract this
|
// TODO: Implement a version of this which doesn't rely so much on sequential order
|
||||||
rows, err := qgen.NewAcc().Select("polls_options").Columns("votes").Where("pollID=?").Orderby("option ASC").Query(poll.ID)
|
var ob bytes.Buffer
|
||||||
if err != nil {
|
ob.WriteRune('[')
|
||||||
return c.InternalError(err, w, r)
|
var i int
|
||||||
|
e := poll.Resultsf(func(votes int) error {
|
||||||
|
if i != 0 {
|
||||||
|
ob.WriteRune(',')
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
ob.WriteString(strconv.Itoa(votes))
|
||||||
|
i++
|
||||||
optList := ""
|
return nil
|
||||||
var votes int
|
})
|
||||||
for rows.Next() {
|
if e != nil && e != sql.ErrNoRows {
|
||||||
if e := rows.Scan(&votes); e != nil {
|
|
||||||
return c.InternalError(e, w, r)
|
return c.InternalError(e, w, r)
|
||||||
}
|
}
|
||||||
optList += strconv.Itoa(votes) + ","
|
ob.WriteRune(']')
|
||||||
}
|
w.Write(ob.Bytes())
|
||||||
if err = rows.Err(); err != nil {
|
|
||||||
return c.InternalError(err, w, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Implement a version of this which doesn't rely so much on sequential order
|
|
||||||
if len(optList) > 0 {
|
|
||||||
optList = optList[:len(optList)-1]
|
|
||||||
}
|
|
||||||
w.Write([]byte("[" + optList + "]"))
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue