Files
qv/internal/models/voters.go

105 lines
1.9 KiB
Go

package models
import (
"database/sql"
"errors"
)
type VoterModelInterface interface {
InsertMultiple(identities []string, electionID string) ([]int, error)
CountByElection(electionID string) (int, error)
Exists(voterIdentity string, electionID string) (bool, error)
}
type VoterModel struct {
DB *sql.DB
}
func (v *VoterModel) InsertMultiple(identities []string, electionID string) ([]int, error) {
tx, err := v.DB.Begin()
if err != nil {
return nil, err
}
defer tx.Rollback()
stmt, err := tx.Prepare(`
INSERT INTO voters (identity, election_id)
VALUES (?, ?)`)
if err != nil {
return nil, err
}
defer stmt.Close()
voterIDs := make([]int, 0, len(identities))
for _, identity := range identities {
result, err := stmt.Exec(identity, electionID)
if err != nil {
return nil, err
}
voterID, err := result.LastInsertId()
if err != nil {
return nil, err
}
voterIDs = append(voterIDs, int(voterID))
}
if err = tx.Commit(); err != nil {
return nil, err
}
return voterIDs, nil
}
func (v *VoterModel) CountByElection(electionID string) (int, error) {
// use a transaction to prevent race conditions
tx, err := v.DB.Begin()
if err != nil {
return 0, err
}
defer tx.Rollback()
query := `
SELECT COUNT(identity)
FROM voters
WHERE election_id = ?
GROUP BY election_id;
`
row := tx.QueryRow(query, electionID)
var voterCount int
err = row.Scan(&voterCount)
if err != nil {
return 0, err
}
tx.Commit()
return voterCount, nil
}
func (v *VoterModel) Exists(voterIdentity string, electionID string) (bool, error) {
query := `
SELECT EXISTS (
SELECT 1
FROM voters
WHERE identity = ? AND election_id = ?
)
`
var exists bool
err := v.DB.QueryRow(query, voterIdentity, electionID).Scan(&exists)
if err != nil {
if errors.Is(sql.ErrNoRows, err) {
return false, nil
}
return false, err
}
return exists, nil
}