package database import ( "errors" "fmt" "log" "strings" "tomatentum.net/outfit-voting-abi26/internal/util" ) const VALUESTEMPLATE string = "(%s, %s, %s, %d)" const INITVOTEDB string = "CREATE TABLE IF NOT EXISTS vote(id varchar(16) PRIMARY KEY, category TEXT NOT NULL, name TEXT NOT NULL, votes int NOT NULL)" const INSERTVOTEENTRY string = "INSERT INTO vote(id, category, name, votes) VALUES($1, $2, $3, $4)" const BULKINSERTVOTEENTRY string = "INSERT INTO vote(id, category, name, votes) VALUES" const SETVOTE string = "UPDATE vote SET votes = $1 WHERE id = $2" const INCVOTE string = "UPDATE vote SET votes = votes + 1 WHERE id = $1" const DELVOTEENTRY string = "DELETE FROM vote WHERE id = $1" const BULKDELVOTEENTRY string = "DELETE FROM vote WHERE id IN (%s)" const GETVOTES string = "SELECT * FROM vote ORDER BY votes DESC" const GETVOTEOPTIONS string = "SELECT id, category, name FROM vote" const GETVOTE string = "SELECT * FROM vote WHERE id = $1" type VoteEntry struct { VoteOption Votes int } type VoteOption struct { ID string Category string Name string } func initVoteDB() error { _, err := db.Exec(INITVOTEDB) return err } func InsertVoteEntry(name string, category string) (VoteEntry, error) { id, err := util.RandString(8) if err != nil { return VoteEntry{}, err } _, err = db.Exec(INSERTVOTEENTRY, id, category, name, 0) if err != nil { return VoteEntry{}, err } return VoteEntry{VoteOption{id, category, name}, 0}, nil } func BulkInsertVoteEntry(names []string, category string) (*[]VoteEntry, error) { stmnt := BULKINSERTVOTEENTRY var entries []VoteEntry = make([]VoteEntry, len(names)) for i, v := range names { id, err := util.RandString(8) if err != nil { return nil, err } stmnt = stmnt + fmt.Sprintf(VALUESTEMPLATE, id, category, v, 0) entries = append(entries, VoteEntry{VoteOption{id, category, v}, 0}) if i < len(names)-1 { stmnt = stmnt + "," } } stmnt = stmnt + ";" _, err := db.Exec(stmnt) if err != nil { return nil, err } return &entries, nil } func SetVote(id string, votes int) error { _, err := db.Exec(SETVOTE, votes, id) if err != nil { return err } return nil } func IncVote(id string) error { res, err := db.Exec(INCVOTE, id) if err != nil { return err } n, _ := res.RowsAffected() if n < 1 { return errors.New("id does not exist") } return nil } func DelVoteEntry(id string) error { res, err := db.Exec(DELVOTEENTRY, id) if err != nil { return err } n, _ := res.RowsAffected() if n < 1 { return errors.New("id does not exist") } return nil } func BulkDelVoteEntry(ids []string) error { placeholders := make([]string, len(ids)) args := make([]any, len(ids)) for i := 0; i < len(ids); i++ { placeholders[i] = fmt.Sprintf("$%d", i+1) args[i] = ids[i] } stmnt := fmt.Sprintf(BULKDELVOTEENTRY, strings.Join(placeholders, ", ")) log.Println(stmnt) res, err := db.Exec(stmnt, args...) if err != nil { return err } n, _ := res.RowsAffected() if n < 1 { return errors.New("id does not exist") } return nil } func GetVotes() ([]VoteEntry, error) { res, err := db.Query(GETVOTES) if err != nil { return nil, err } defer res.Close() var current VoteEntry var entries []VoteEntry = []VoteEntry{} for res.Next() { if err := res.Err(); err != nil { return nil, err } if err := res.Scan(¤t.ID, ¤t.Category, ¤t.Name, ¤t.Votes); err != nil { return nil, err } entries = append(entries, current) } return entries, nil } func GetVoteOptions() ([]VoteOption, error) { res, err := db.Query(GETVOTEOPTIONS) if err != nil { return nil, err } defer res.Close() var current VoteOption var entries []VoteOption = []VoteOption{} for res.Next() { if err := res.Err(); err != nil { return nil, err } if err := res.Scan(¤t.ID, ¤t.Category, ¤t.Name); err != nil { return nil, err } entries = append(entries, current) } return entries, nil } func GetVote(id string) (VoteEntry, error) { res := db.QueryRow(GETVOTE, id) var current VoteEntry if err := res.Scan(¤t.ID, ¤t.Category, ¤t.Name, ¤t.Votes); err != nil { return VoteEntry{}, err } return current, nil }