-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.go
129 lines (101 loc) · 2.33 KB
/
client.go
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
118
119
120
121
122
123
124
125
126
127
128
129
package sqlwrap
import (
"context"
"database/sql"
"fmt"
_ "github.com/mattn/go-sqlite3"
)
type Client struct {
*sql.DB
}
type (
Params map[string]any
Values []any
)
//go:generate ragel -e -G2 -Z prepare_in_list.rl
func Open(driver string, connection string) (*Client, error) {
database, err := sql.Open(driver, connection)
if err != nil {
return nil, fmt.Errorf("could not open database: %w", err)
}
return &Client{
DB: database,
}, nil
}
func In(query string, params Params) (string, error) {
if len(params) == 0 {
return query, nil
}
for _, value := range params {
if _, ok := value.(Values); ok {
query, err := prepareInList(query, params)
if err != nil {
return "", fmt.Errorf("could not prepare query for IN list: %w", err)
}
return query, nil
}
}
return query, nil
}
func (c *Client) Get(
ctx context.Context,
destination interface{},
query string,
params Params,
) error {
var err error
query, err = In(query, params)
if err != nil {
return fmt.Errorf("could not setup IN list for GET: %w", err)
}
names := make([]any, 0, len(params))
for name, value := range params {
names = append(names, sql.Named(name, value))
}
row := c.DB.QueryRowContext(ctx, query, names...)
err = row.Err()
if err != nil {
return fmt.Errorf("could not execute query for result: %w", err)
}
err = row.Scan(destination)
if err != nil {
return fmt.Errorf("could not scan result: %w", err)
}
return nil
}
func (c *Client) Select(
ctx context.Context,
destination *[]string,
query string,
params map[string]interface{},
) error {
var err error
query, err = prepareInList(query, params)
if err != nil {
return fmt.Errorf("could not prepare query for IN list: %w", err)
}
names := []any{}
for name, value := range params {
names = append(names, sql.Named(name, value))
}
rows, err := c.DB.QueryContext(ctx, query, names...)
if err != nil {
return fmt.Errorf("could not execute for results: %w", err)
}
if rows.Err() != nil {
return fmt.Errorf("could not execute for results: %w", err)
}
defer rows.Close()
var value string
for rows.Next() {
err := rows.Scan(&value)
if err != nil {
return fmt.Errorf("could not scan for result: %w", err)
}
*destination = append(*destination, value)
}
if err != nil {
return fmt.Errorf("could not scan result: %w", err)
}
return nil
}