package models import ( "database/sql" "errors" ) type VoterModelInterface interface { Insert(identity string, electionID int) (int, error) CountByElection(electionID int) (int, error) Exists(voterIdentity string, electionID int) (bool, error) } type VoterModel struct { DB *sql.DB } func (v *VoterModel) Insert(identity string, electionID int) (int, error) { tx, err := v.DB.Begin() if err != nil { return 0, err } defer tx.Rollback() result, err := tx.Exec(` INSERT INTO voters (identity, election_id) VALUES (?, ?)`, identity, electionID) if err != nil { return 0, err } if err = tx.Commit(); err != nil { return 0, err } voterId, err := result.LastInsertId() return int(voterId), nil } func (v *VoterModel) CountByElection(electionID int) (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 int) (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 }