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
|
package postgres
import (
"database/sql"
"github.com/NyaaPantsu/nyaa/util/log"
_ "github.com/lib/pq"
)
func New(param string) (db *Database, err error) {
db = new(Database)
db.conn, err = sql.Open("postgres", param)
if err != nil {
db = nil
}
return
}
type Database struct {
conn *sql.DB
prepared map[string]*sql.Stmt
}
func (db *Database) getPrepared(name string) *sql.Stmt {
return db.prepared[name]
}
func (db *Database) Query(q string, param ...interface{}) (*sql.Rows, error) {
return db.conn.Query(q, param...)
}
func (db *Database) Init() (err error) {
// ensure tables
for idx := range tables {
log.Debugf("ensure table %s", tables[idx].name)
err = tables[idx].Exec(db.conn)
if err != nil {
log.Errorf("Failed to ensure table %s: %s", tables[idx].name, err.Error())
return
}
}
// generate prepared statements
for k := range statements {
var stmt *sql.Stmt
stmt, err = db.conn.Prepare(statements[k])
if err != nil {
log.Errorf("failed to build prepared statement %s: %s", k, err.Error())
return
}
db.prepared[k] = stmt
}
return
}
// execute prepared statement with arguments, visit result and autoclose rows after done visiting
func (db *Database) queryWithPrepared(name string, visit func(*sql.Rows) error, params ...interface{}) (err error) {
var rows *sql.Rows
rows, err = db.getPrepared(name).Query(params...)
if err == sql.ErrNoRows {
err = nil
} else if err == nil {
err = visit(rows)
rows.Close()
}
return
}
// execute prepared statement with arguments, visit single row
func (db *Database) queryRowWithPrepared(name string, visit func(*sql.Row) error, params ...interface{}) (err error) {
err = visit(db.getPrepared(name).QueryRow(params...))
return
}
// execute a query by name and return how many rows were affected
func (db *Database) execQuery(name string, p ...interface{}) (affected uint32, err error) {
var result sql.Result
result, err = db.getPrepared(name).Exec(p...)
if err == nil {
var d int64
d, err = result.RowsAffected()
if err == nil {
affected = uint32(d)
}
}
return
}
|