@ -106,7 +106,7 @@ WHERE decisions.status=0 AND :now > due`,
SELECT due FROM decisions WHERE status = 0 ORDER BY due LIMIT 1 ` ,
sqlGetVotersForProxy : `
SELECT id , name , reminder
FROM voters WHERE enabled = 1 AND id != $ 1 AND id NOT IN ( SELECT voter FROM votes WHERE decision = $ 2 ) ` ,
FROM voters WHERE enabled = 1 AND id != $ 1 ` ,
sqlGetReminderVoters : `
SELECT id , name , reminder FROM voters WHERE enabled = 1 AND reminder != ' ' AND reminder IS NOT NULL ` ,
sqlFindUnvotedDecisionsForVoter : `
@ -123,47 +123,6 @@ FROM votes
WHERE decision = $ 1 AND voter = $ 2 ` ,
}
var db * sqlx . DB
func init ( ) {
failed_statements := make ( [ ] string , 0 )
for _ , sqlStatement := range sqlStatements {
var stmt * sqlx . Stmt
stmt , err := db . Preparex ( sqlStatement )
if err != nil {
logger . Criticalf ( "ERROR parsing statement %s: %s" , sqlStatement , err )
failed_statements = append ( failed_statements , sqlStatement )
}
stmt . Close ( )
}
if len ( failed_statements ) > 0 {
panic ( fmt . Sprintf ( "%d statements failed" , len ( failed_statements ) ) )
}
migrateConf := & goose . DBConf {
MigrationsDir : config . MigrationsPath ,
Env : "production" ,
Driver : goose . DBDriver {
Name : "sqlite3" ,
OpenStr : config . DatabaseFile ,
Import : "github.com/mattn/go-sqlite3" ,
Dialect : & goose . Sqlite3Dialect { } ,
} ,
}
latest , err := goose . GetMostRecentDBVersion ( migrateConf . MigrationsDir )
if err != nil {
logger . Criticalf ( "getting the most recent database repository version failed: %s" , err )
panic ( err )
}
err = goose . RunMigrationsOnDb ( migrateConf , migrateConf . MigrationsDir , latest , db . DB )
if err != nil {
logger . Criticalf ( "running database migration failed: %s" , err )
panic ( err )
}
}
type VoteType uint8
type VoteStatus int8
@ -282,30 +241,86 @@ type Vote struct {
Notes string
}
func ( v * Vote ) Save ( ) ( err error ) {
insertVoteStmt , err := db . PrepareNamed ( sqlStatements [ sqlCreateVote ] )
type dbHandler struct {
db * sqlx . DB
}
var db * dbHandler
func NewDB ( database * sqlx . DB ) * dbHandler {
handler := & dbHandler { db : database }
failed_statements := make ( [ ] string , 0 )
for _ , sqlStatement := range sqlStatements {
var stmt * sqlx . Stmt
stmt , err := database . Preparex ( sqlStatement )
if err != nil {
log . Criticalf ( "ERROR parsing statement %s: %s" , sqlStatement , err )
failed_statements = append ( failed_statements , sqlStatement )
}
stmt . Close ( )
}
if len ( failed_statements ) > 0 {
log . Panicf ( "%d statements failed to prepare" , len ( failed_statements ) )
}
migrateConf := & goose . DBConf {
MigrationsDir : config . MigrationsPath ,
Env : "production" ,
Driver : goose . DBDriver {
Name : "sqlite3" ,
OpenStr : config . DatabaseFile ,
Import : "github.com/mattn/go-sqlite3" ,
Dialect : & goose . Sqlite3Dialect { } ,
} ,
}
latest , err := goose . GetMostRecentDBVersion ( migrateConf . MigrationsDir )
if err != nil {
logger . Errorf ( "preparing statement failed: %s" , err )
return
log . Panicf ( "getting the most recent database repository version failed: %v" , err )
}
defer insertVoteStmt . Close ( )
_ , err = insertVoteStmt . Exec ( v )
err = goose . RunMigrationsOnDb ( migrateConf , migrateConf . MigrationsDir , latest , database . DB )
if err != nil {
logger . Errorf ( "saving vote failed: %s" , err )
return
log . Panicf ( "running database migration failed: %v" , err )
}
return handler
}
func ( d * dbHandler ) Close ( ) error {
return d . db . Close ( )
}
func ( d * dbHandler ) getPreparedNamedStatement ( statementKey sqlKey ) * sqlx . NamedStmt {
statement , err := d . db . PrepareNamed ( sqlStatements [ statementKey ] )
if err != nil {
log . Panicf ( "Preparing statement failed: %v" , err )
}
return statement
}
getVoteStmt , err := db . Preparex ( sqlStatements [ sqlLoadVote ] )
func ( d * dbHandler ) getPreparedStatement ( statementKey sqlKey ) * sqlx . Stmt {
statement , err := d . db . Preparex ( sqlStatements [ statementKey ] )
if err != nil {
logger . Errorf ( "preparing statement failed: %s" , err )
log . Panicf ( "Preparing statement failed: %v" , err )
}
return statement
}
func ( v * Vote ) Save ( ) ( err error ) {
insertVoteStmt := db . getPreparedNamedStatement ( sqlCreateVote )
defer insertVoteStmt . Close ( )
if _ , err = insertVoteStmt . Exec ( v ) ; err != nil {
log . Errorf ( "saving vote failed: %v" , err )
return
}
getVoteStmt := db . getPreparedStatement ( sqlLoadVote )
defer getVoteStmt . Close ( )
err = getVoteStmt . Get ( v , v . DecisionId , v . VoterId )
if err != nil {
logger . Errorf ( "getting inserted vote failed: %s" , err )
if err = getVoteStmt . Get ( v , v . DecisionId , v . VoterId ) ; err != nil {
log . Errorf ( "getting inserted vote failed: %v" , err )
return
}
return
@ -333,6 +348,17 @@ func (v *VoteSums) Percent() int {
return v . Ayes * 100 / totalVotes
}
func ( v * VoteSums ) CalculateResult ( quorum int , majority int ) ( status VoteStatus , reasoning string ) {
if v . VoteCount ( ) < quorum {
status , reasoning = voteStatusDeclined , fmt . Sprintf ( "Needed quorum of %d has not been reached." , quorum )
} else if ( v . Ayes / v . TotalVotes ( ) ) < ( majority / 100 ) {
status , reasoning = voteStatusDeclined , fmt . Sprintf ( "Needed majority of %d%% has not been reached." , majority )
} else {
status , reasoning = voteStatusApproved , "Quorum and majority have been reached"
}
return
}
type VoteForDisplay struct {
Vote
Name string
@ -346,11 +372,7 @@ type DecisionForDisplay struct {
}
func FindDecisionForDisplayByTag ( tag string ) ( decision * DecisionForDisplay , err error ) {
decisionStmt , err := db . Preparex ( sqlStatements [ sqlLoadDecisionByTag ] )
if err != nil {
logger . Errorf ( "preparing statement failed: %s" , err )
return
}
decisionStmt := db . getPreparedStatement ( sqlLoadDecisionByTag )
defer decisionStmt . Close ( )
decision = & DecisionForDisplay { }
@ -359,7 +381,8 @@ func FindDecisionForDisplayByTag(tag string) (decision *DecisionForDisplay, err
decision = nil
err = nil
} else {
logger . Errorf ( "getting motion %s failed: %v" , tag , err )
log . Errorf ( "getting motion %s failed: %v" , tag , err )
return
}
}
decision . VoteSums , err = decision . Decision . VoteSums ( )
@ -374,13 +397,9 @@ func FindDecisionForDisplayByTag(tag string) (decision *DecisionForDisplay, err
func FindDecisionsForDisplayOnPage ( page int64 , unvoted bool , voter * Voter ) ( decisions [ ] * DecisionForDisplay , err error ) {
var decisionsStmt * sqlx . Stmt
if unvoted && voter != nil {
decisionsStmt , err = db . Preparex ( sqlStatements [ sqlLoadUnvotedDecisions ] )
decisionsStmt = db . getPreparedStatement ( sqlLoadUnvotedDecisions )
} else {
decisionsStmt , err = db . Preparex ( sqlStatements [ sqlLoadDecisions ] )
}
if err != nil {
logger . Errorf ( "preparing statement failed: %s" , err )
return
decisionsStmt = db . getPreparedStatement ( sqlLoadDecisions )
}
defer decisionsStmt . Close ( )
@ -391,7 +410,7 @@ func FindDecisionsForDisplayOnPage(page int64, unvoted bool, voter *Voter) (deci
rows , err = decisionsStmt . Queryx ( page - 1 )
}
if err != nil {
log ger . Errorf ( "loading motions for page %d failed: %v" , page , err )
log . Errorf ( "loading motions for page %d failed: %v" , page , err )
return
}
defer rows . Close ( )
@ -399,7 +418,7 @@ func FindDecisionsForDisplayOnPage(page int64, unvoted bool, voter *Voter) (deci
for rows . Next ( ) {
var d DecisionForDisplay
if err = rows . StructScan ( & d ) ; err != nil {
log ger . Errorf ( "loading motions for page %d failed: %v" , page , err )
log . Errorf ( "loading motions for page %d failed: %v" , page , err )
return
}
d . VoteSums , err = d . Decision . VoteSums ( )
@ -412,16 +431,12 @@ func FindDecisionsForDisplayOnPage(page int64, unvoted bool, voter *Voter) (deci
}
func ( d * Decision ) VoteSums ( ) ( sums * VoteSums , err error ) {
votesStmt , err := db . Preparex ( sqlStatements [ sqlLoadVoteCountsForDecision ] )
if err != nil {
logger . Errorf ( "preparing statement failed: %s" , err )
return
}
votesStmt := db . getPreparedStatement ( sqlLoadVoteCountsForDecision )
defer votesStmt . Close ( )
voteRows , err := votesStmt . Queryx ( d . Id )
if err != nil {
log ger . Errorf ( "fetching vote sums for motion %s failed: %v" , d . Tag , err )
log . Errorf ( "fetching vote sums for motion %s failed: %v" , d . Tag , err )
return
}
defer voteRows . Close ( )
@ -431,7 +446,7 @@ func (d *Decision) VoteSums() (sums *VoteSums, err error) {
var vote VoteChoice
var count int
if err = voteRows . Scan ( & vote , & count ) ; err != nil {
log ger . Errorf ( "fetching vote sums for motion %s failed: %v" , d . Tag , err )
log . Errorf ( "fetching vote sums for motion %s failed: %v" , d . Tag , err )
return
}
switch vote {
@ -447,39 +462,33 @@ func (d *Decision) VoteSums() (sums *VoteSums, err error) {
}
func ( d * DecisionForDisplay ) LoadVotes ( ) ( err error ) {
votesStmt , err := db . Preparex ( sqlStatements [ sqlLoadVotesForDecision ] )
if err != nil {
logger . Errorf ( "preparing statement failed: %s" , err )
return
}
votesStmt := db . getPreparedStatement ( sqlLoadVotesForDecision )
defer votesStmt . Close ( )
err = votesStmt . Select ( & d . Votes , d . Id )
if err != nil {
logger . Errorf ( "selecting votes for motion %s failed: %v" , d . Tag , err )
log . Errorf ( "selecting votes for motion %s failed: %v" , d . Tag , err )
return
}
return
}
func ( d * Decision ) OlderExists ( unvoted bool , voter * Voter ) ( result bool , err error ) {
var olderStmt * sqlx . Stmt
if unvoted && voter != nil {
olderStmt , err = db . Preparex ( sqlStatements [ sqlCountOlderThanUnvotedDecision ] )
} else {
olderStmt , err = db . Preparex ( sqlStatements [ sqlCountOlderThanDecision ] )
}
if err != nil {
logger . Errorf ( "preparing statement failed: %s" , err )
return
}
defer olderStmt . Close ( )
olderStmt := db . getPreparedStatement ( sqlCountOlderThanUnvotedDecision )
defer olderStmt . Close ( )
if unvoted && voter != nil {
if err = olderStmt . Get ( & result , d . Proposed , voter . Id ) ; err != nil {
logger . Errorf ( "finding older motions than %s failed: %v" , d . Tag , err )
log . Errorf ( "finding older motions than %s failed: %v" , d . Tag , err )
return
}
} else {
olderStmt := db . getPreparedStatement ( sqlCountOlderThanDecision )
defer olderStmt . Close ( )
if err = olderStmt . Get ( & result , d . Proposed ) ; err != nil {
logger . Errorf ( "finding older motions than %s failed: %v" , d . Tag , err )
log . Errorf ( "finding older motions than %s failed: %v" , d . Tag , err )
return
}
}
@ -487,76 +496,62 @@ func (d *Decision) OlderExists(unvoted bool, voter *Voter) (result bool, err err
}
func ( d * Decision ) Create ( ) ( err error ) {
insertDecisionStmt , err := db . PrepareNamed ( sqlStatements [ sqlCreateDecision ] )
if err != nil {
logger . Errorf ( "preparing statement failed: %s" , err )
return
}
insertDecisionStmt := db . getPreparedNamedStatement ( sqlCreateDecision )
defer insertDecisionStmt . Close ( )
result , err := insertDecisionStmt . Exec ( d )
if err != nil {
log ger . Errorf ( "creating motion failed: % s ", err )
log . Errorf ( "creating motion failed: % v ", err )
return
}
lastInsertId , err := result . LastInsertId ( )
if err != nil {
log ger . Errorf ( "getting id of inserted motion failed: % s ", err )
log . Errorf ( "getting id of inserted motion failed: % v ", err )
return
}
rescheduleChannel <- JobIdCloseDecisions
getDecisionStmt , err := db . Preparex ( sqlStatements [ sqlLoadDecisionById ] )
if err != nil {
logger . Errorf ( "preparing statement failed: %s" , err )
return
}
getDecisionStmt := db . getPreparedStatement ( sqlLoadDecisionById )
defer getDecisionStmt . Close ( )
err = getDecisionStmt . Get ( d , lastInsertId )
if err != nil {
logger . Errorf ( "getting inserted motion failed: %s" , err )
log . Errorf ( "getting inserted motion failed: %v" , err )
return
}
return
}
func ( d * Decision ) LoadWithId ( ) ( err error ) {
getDecisionStmt , err := db . Preparex ( sqlStatements [ sqlLoadDecisionById ] )
if err != nil {
logger . Errorf ( "preparing statement failed: %s" , err )
return
}
getDecisionStmt := db . getPreparedStatement ( sqlLoadDecisionById )
defer getDecisionStmt . Close ( )
err = getDecisionStmt . Get ( d , d . Id )
if err != nil {
logger . Errorf ( "loading updated motion failed: %s" , err )
log . Errorf ( "loading updated motion failed: %v" , err )
return
}
return
}
func ( d * Decision ) Update ( ) ( err error ) {
updateDecisionStmt , err := db . PrepareNamed ( sqlStatements [ sqlUpdateDecision ] )
if err != nil {
logger . Errorf ( "preparing statement failed: %s" , err )
return
}
updateDecisionStmt := db . getPreparedNamedStatement ( sqlUpdateDecision )
defer updateDecisionStmt . Close ( )
result , err := updateDecisionStmt . Exec ( d )
if err != nil {
log ger . Errorf ( "updating motion failed: % s ", err )
log . Errorf ( "updating motion failed: % v ", err )
return
}
affectedRows , err := result . RowsAffected ( )
if err != nil {
log ger . Error f ( "Problem determining the affected rows" )
log . Error ( "Problem determining the affected rows" )
return
} else if affectedRows != 1 {
log ger . Warningf ( "wrong number of affected rows: %d (1 expected)" , affectedRows )
log . Warningf ( "wrong number of affected rows: %d (1 expected)" , affectedRows )
}
rescheduleChannel <- JobIdCloseDecisions
@ -565,24 +560,20 @@ func (d *Decision) Update() (err error) {
}
func ( d * Decision ) UpdateStatus ( ) ( err error ) {
updateStatusStmt , err := db . PrepareNamed ( sqlStatements [ sqlUpdateDecisionStatus ] )
if err != nil {
logger . Errorf ( "preparing statement failed: %s" , err )
return
}
updateStatusStmt := db . getPreparedNamedStatement ( sqlUpdateDecisionStatus )
defer updateStatusStmt . Close ( )
result , err := updateStatusStmt . Exec ( d )
if err != nil {
log ger . Errorf ( "setting motion status failed: % s ", err )
log . Errorf ( "setting motion status failed: % v ", err )
return
}
affectedRows , err := result . RowsAffected ( )
if err != nil {
log ger . Errorf ( "determining the affected rows failed: % s ", err )
log . Errorf ( "determining the affected rows failed: % v ", err )
return
} else if affectedRows != 1 {
log ger . Warningf ( "wrong number of affected rows: %d (1 expected)" , affectedRows )
log . Warningf ( "wrong number of affected rows: %d (1 expected)" , affectedRows )
}
rescheduleChannel <- JobIdCloseDecisions
@ -595,17 +586,13 @@ func (d *Decision) String() string {
}
func FindVoterByAddress ( emailAddress string ) ( voter * Voter , err error ) {
findVoterStmt , err := db . Preparex ( sqlStatements [ sqlLoadEnabledVoterByEmail ] )
if err != nil {
logger . Errorf ( "preparing statement failed: %s" , err )
return
}
findVoterStmt := db . getPreparedStatement ( sqlLoadEnabledVoterByEmail )
defer findVoterStmt . Close ( )
voter = & Voter { }
if err = findVoterStmt . Get ( voter , emailAddress ) ; err != nil {
if err != sql . ErrNoRows {
log ger . Errorf ( "getting voter for address %s failed: %v" , emailAddress , err )
log . Errorf ( "getting voter for address %s failed: %v" , emailAddress , err )
} else {
err = nil
voter = nil
@ -614,72 +601,56 @@ func FindVoterByAddress(emailAddress string) (voter *Voter, err error) {
return
}
func ( d * Decision ) Close ( ) ( err error ) {
func ( d * Decision ) Close ( ) error {
quorum , majority := d . VoteType . QuorumAndMajority ( )
voteSums , err := d . VoteSums ( )
if err != nil {
logger . Errorf ( "getting vote sums failed: %s" , err )
return
}
votes := voteSums . VoteCount ( )
var voteSums * VoteSums
var err error
if votes < quorum {
d . Status = voteStatusDeclined
} else {
votes = voteSums . TotalVotes ( )
if ( voteSums . Ayes / votes ) > ( majority / 100 ) {
d . Status = voteStatusApproved
} else {
d . Status = voteStatusDeclined
}
if voteSums , err = d . VoteSums ( ) ; err != nil {
log . Errorf ( "getting vote sums failed: %v" , err )
return err
}
var reasoning string
d . Status , reasoning = voteSums . CalculateResult ( quorum , majority )
closeDecisionStmt , err := db . PrepareNamed ( sqlStatements [ sqlUpdateDecisionStatus ] )
if err != nil {
logger . Errorf ( "preparing statement failed: %s" , err )
return
}
closeDecisionStmt := db . getPreparedNamedStatement ( sqlUpdateDecisionStatus )
defer closeDecisionStmt . Close ( )
result , err := closeDecisionStmt . Exec ( d )
if err != nil {
logger . Errorf ( "closing vote failed: %s" , err )
return
}
affectedRows , err := result . RowsAffected ( )
if err != nil {
logger . Errorf ( "getting affected rows failed: %s" , err )
log . Errorf ( "closing vote failed: %v" , err )
return err
}
if affectedRows != 1 {
logger . Warningf ( "wrong number of affected rows: %d (1 expected)" , affectedRows )
if affectedRows , err := result . RowsAffected ( ) ; err != nil {
log . Errorf ( "getting affected rows failed: %v" , err )
return err
} else if affectedRows != 1 {
log . Warningf ( "wrong number of affected rows: %d (1 expected)" , affectedRows )
}
NotifyMailChannel <- NewNotificationClosedDecision ( d , voteSums )
NotifyMailChannel <- NewNotificationClosedDecision ( d , voteSums , reasoning )
return
log . Infof ( "decision %s closed with result %s: reasoning %s" , d . Tag , d . Status , reasoning )
return nil
}
func CloseDecisions ( ) ( err error ) {
getClosableDecisionsStmt , err := db . PrepareNamed ( sqlStatements [ sqlSelectClosableDecisions ] )
if err != nil {
logger . Errorf ( "preparing statement failed: %s" , err )
return
}
getClosableDecisionsStmt := db . getPreparedNamedStatement ( sqlSelectClosableDecisions )
defer getClosableDecisionsStmt . Close ( )
decisions := make ( [ ] * Decision , 0 )
rows , err := getClosableDecisionsStmt . Queryx ( struct { Now time . Time } { time . Now ( ) . UTC ( ) } )
if err != nil {
log ger . Errorf ( "fetching closable decisions failed: % s ", err )
log . Errorf ( "fetching closable decisions failed: % v ", err )
return
}
defer rows . Close ( )
for rows . Next ( ) {
decision := & Decision { }
if err = rows . StructScan ( decision ) ; err != nil {
log ger . Errorf ( "scanning row failed: % s ", err )
log . Errorf ( "scanning row failed: % v ", err )
return
}
decisions = append ( decisions , decision )
@ -687,9 +658,9 @@ func CloseDecisions() (err error) {
rows . Close ( )
for _ , decision := range decisions {
log ger . Debugf ( "found closable decision %s" , decision . Tag )
log . Debugf ( "found closable decision %s" , decision . Tag )
if err = decision . Close ( ) ; err != nil {
log ger . Errorf ( "closing decision %s failed: %s" , decision . Tag , err )
log . Errorf ( "closing decision %s failed: %s" , decision . Tag , err )
return
}
}
@ -698,41 +669,32 @@ func CloseDecisions() (err error) {
}
func GetNextPendingDecisionDue ( ) ( due * time . Time , err error ) {
getNextPendingDecisionDueStmt , err := db . Preparex ( sqlStatements [ sqlGetNextPendingDecisionDue ] )
if err != nil {
logger . Errorf ( "preparing statement failed: %s" , err )
return
}
getNextPendingDecisionDueStmt := db . getPreparedStatement ( sqlGetNextPendingDecisionDue )
defer getNextPendingDecisionDueStmt . Close ( )
row := getNextPendingDecisionDueStmt . QueryRow ( )
var dueTimestamp time . Time
if err = row . Scan ( & due Timestamp ) ; err != nil {
due = & time . Time { }
if err = row . Scan ( due ) ; err != nil {
if err == sql . ErrNoRows {
log ger . Debug f ( "No pending decisions" )
log . Debug ( "No pending decisions" )
return nil , nil
}
log ger . Errorf ( "parsing result failed: % s ", err )
return
log . Errorf ( "parsing result failed: % v ", err )
return nil , err
}
due = & dueTimestamp
return
}
func GetReminderVoters ( ) ( voters * [ ] Voter , err error ) {
getReminderVotersStmt , err := db . Preparex ( sqlStatements [ sqlGetReminderVoters ] )
if err != nil {
logger . Errorf ( "preparing statement failed: %s" , err )
return
}
getReminderVotersStmt := db . getPreparedStatement ( sqlGetReminderVoters )
defer getReminderVotersStmt . Close ( )
voterSlice := make ( [ ] Voter , 0 )
if err = getReminderVotersStmt . Select ( & voterSlice ) ; err != nil {
log ger . Errorf ( "getting voters failed: % s ", err )
log . Errorf ( "getting voters failed: % v ", err )
return
}
voters = & voterSlice
@ -741,17 +703,13 @@ func GetReminderVoters() (voters *[]Voter, err error) {
}
func FindUnvotedDecisionsForVoter ( voter * Voter ) ( decisions * [ ] Decision , err error ) {
findUnvotedDecisionsForVoterStmt , err := db . Preparex ( sqlStatements [ sqlFindUnvotedDecisionsForVoter ] )
if err != nil {
logger . Errorf ( "preparing statement failed: %s" , err )
return
}
findUnvotedDecisionsForVoterStmt := db . getPreparedStatement ( sqlFindUnvotedDecisionsForVoter )
defer findUnvotedDecisionsForVoterStmt . Close ( )
decisionsSlice := make ( [ ] Decision , 0 )
if err = findUnvotedDecisionsForVoterStmt . Select ( & decisionsSlice , voter . Id ) ; err != nil {
log ger . Errorf ( "getting unvoted decisions failed: % s ", err )
log . Errorf ( "getting unvoted decisions failed: % v ", err )
return
}
decisions = & decisionsSlice
@ -760,34 +718,26 @@ func FindUnvotedDecisionsForVoter(voter *Voter) (decisions *[]Decision, err erro
}
func GetVoterById ( id int64 ) ( voter * Voter , err error ) {
getVoterByIdStmt , err := db . Preparex ( sqlStatements [ sqlGetEnabledVoterById ] )
if err != nil {
logger . Errorf ( "preparing statement failed: %s" , err )
return
}
getVoterByIdStmt := db . getPreparedStatement ( sqlGetEnabledVoterById )
defer getVoterByIdStmt . Close ( )
voter = & Voter { }
if err = getVoterByIdStmt . Get ( voter , id ) ; err != nil {
log ger . Errorf ( "getting voter failed: % s ", err )
log . Errorf ( "getting voter failed: % v ", err )
return
}
return
}
func GetVotersForProxy ( proxy * Voter , decision * Decision ) ( voters * [ ] Voter , err error ) {
getVotersForProxyStmt , err := db . Preparex ( sqlStatements [ sqlGetVotersForProxy ] )
if err != nil {
logger . Errorf ( "preparing statement failed: %s" , err )
return
}
func GetVotersForProxy ( proxy * Voter ) ( voters * [ ] Voter , err error ) {
getVotersForProxyStmt := db . getPreparedStatement ( sqlGetVotersForProxy )
defer getVotersForProxyStmt . Close ( )
votersSlice := make ( [ ] Voter , 0 )
if err = getVotersForProxyStmt . Select ( & votersSlice , proxy . Id , decision . Id ); err != nil {
log ger . Errorf ( "Error getting voters for proxy failed: % s ", err )
if err = getVotersForProxyStmt . Select ( & votersSlice , proxy . Id ); err != nil {
log . Errorf ( "Error getting voters for proxy failed: % v ", err )
return
}
voters = & votersSlice