1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
package dal
import (
"fmt"
"time"
)
// List names one of the two tables of create-09.sql, each a set of strings.
type List int
const (
BlockedFeeds List = iota
AllowedRequesters
)
func (l List) table() (table, column string) {
switch l {
case BlockedFeeds:
return "blocked_feeds", "url"
case AllowedRequesters:
return "allowed_requesters", "moniker"
}
panic(fmt.Sprintf("unknown list %d", l))
}
func (repo *Repo) IsInList(list List, entry string) (bool, error) {
repo.muDb.RLock()
defer repo.muDb.RUnlock()
table, column := list.table()
var count int
err := repo.db.QueryRow(`SELECT COUNT(*) FROM `+table+` WHERE `+column+`=?`, entry).Scan(&count)
return count != 0, err
}
func (repo *Repo) IsListEmpty(list List) (bool, error) {
repo.muDb.RLock()
defer repo.muDb.RUnlock()
table, _ := list.table()
var count int
err := repo.db.QueryRow(`SELECT COUNT(*) FROM ` + table).Scan(&count)
return count == 0, err
}
// AddToList adds every entry, in one transaction; an entry already there
// keeps its added_at.
func (repo *Repo) AddToList(list List, entries []string, when time.Time) error {
repo.muDb.Lock()
defer repo.muDb.Unlock()
table, column := list.table()
tx, err := repo.db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
for _, e := range entries {
if _, err = tx.Exec(`INSERT INTO `+table+` (`+column+`, added_at) VALUES (?, ?)
ON CONFLICT DO NOTHING`, e, when); err != nil {
return err
}
}
return tx.Commit()
}
// RemoveFromList removes every entry, in one transaction, and returns those
// that were not there.
func (repo *Repo) RemoveFromList(list List, entries []string) (notFound []string, err error) {
repo.muDb.Lock()
defer repo.muDb.Unlock()
table, column := list.table()
tx, err := repo.db.Begin()
if err != nil {
return nil, err
}
defer tx.Rollback()
for _, e := range entries {
res, err := tx.Exec(`DELETE FROM `+table+` WHERE `+column+`=?`, e)
if err != nil {
return nil, err
}
if n, err := res.RowsAffected(); err != nil {
return nil, err
} else if n == 0 {
notFound = append(notFound, e)
}
}
return notFound, tx.Commit()
}
func (repo *Repo) GetList(list List) ([]string, error) {
repo.muDb.RLock()
defer repo.muDb.RUnlock()
table, column := list.table()
rows, err := repo.db.Query(`SELECT ` + column + ` FROM ` + table + ` ORDER BY ` + column)
if err != nil {
return nil, err
}
defer rows.Close()
var res []string
for rows.Next() {
var e string
if err = rows.Scan(&e); err != nil {
return nil, err
}
res = append(res, e)
}
return res, rows.Err()
}
|