forked from AirspaceTechnologies/go-psql
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.go
156 lines (121 loc) · 3.4 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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package psql
import (
"context"
"database/sql"
"errors"
"fmt"
"os"
)
// Client is a helper type to easily connect to PostgreSQL database instances.
//
// It satisfies the `health.Metric` interface.
type Client struct {
*sql.DB
connStr string
}
func NewClient(cfg *Config) *Client {
connStr := os.Getenv("DATABASE_URL")
if connStr == "" && cfg != nil {
connStr = cfg.connString()
}
return &Client{connStr: connStr}
}
func (c *Client) Start(driverName string) error {
if driverName == "" {
driverName = "postgres"
}
db, err := sql.Open(driverName, c.connStr)
if err != nil {
return fmt.Errorf("unable to open connection to postgres db: %w", err)
}
c.DB = db
return nil
}
func (c *Client) Stop() error {
return c.Close()
}
func (c *Client) Started() bool {
return c.DB != nil
}
func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) {
if c.DB == nil {
return nil, errors.New("db is nil")
}
tx, err := c.DB.BeginTx(ctx, opts)
if err != nil {
return nil, err
}
return &Tx{Tx: tx}, nil
}
func (c *Client) RunInTransaction(ctx context.Context, f func(context.Context, *Tx) error, opts *sql.TxOptions) error {
tx, err := c.BeginTx(ctx, opts)
if err != nil {
return err
}
var ranFunc bool
defer func() {
if !ranFunc {
// panicked in f still need to rollback transaction
tx.Rollback()
}
}()
err = f(ctx, tx)
ranFunc = true
if err != nil {
return tx.Rollback()
}
return tx.Commit()
}
func (c *Client) Select(tableName string, cols ...string) *Query {
return Select(c, tableName, cols...)
}
func (c *Client) Insert(ctx context.Context, v Model, cols ...string) error {
return Insert(ctx, c, v, cols...)
}
func (c *Client) Update(ctx context.Context, v Model, cols ...string) error {
return Update(ctx, c, v, cols...)
}
func (c *Client) Delete(ctx context.Context, v Model) (int64, error) {
return Delete(ctx, c, v)
}
func (c *Client) Save(ctx context.Context, v Model, cols ...string) error {
return Save(ctx, c, v, cols...)
}
func (c *Client) UpdateAll(table string, attrs Attrs) *Query {
return UpdateAll(c, table, attrs)
}
func (c *Client) DeleteAll(table string) *Query {
return DeleteAll(c, table)
}
func (c *Client) RawSelect(ctx context.Context, outSlicePtr interface{}, q string, args ...interface{}) error {
return RawSelect(ctx, c, outSlicePtr, q, args...)
}
func (c *Client) RawQuery(ctx context.Context, q string, args ...interface{}) (*QueryResult, error) {
return RawQuery(ctx, c, q, args...)
}
// Returning Queries
// The following scan all values back into the struct from the row
func (c *Client) InsertReturning(ctx context.Context, v Model, cols ...string) error {
return InsertReturning(ctx, c, v, cols...)
}
func (c *Client) UpdateReturning(ctx context.Context, v Model, cols ...string) error {
return UpdateReturning(ctx, c, v, cols...)
}
func (c *Client) DeleteReturning(ctx context.Context, v Model) error {
return DeleteReturning(ctx, c, v)
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// health.Metric
// Name returns `"psql"`.
//
// To better identify the `Client` may be wrapped in a prefixed metric:
//
// health.PrefixedMetric{Prefix: "MyDatabaseName", BaseMetric: c}
//
func (c *Client) Name() string {
return "psql"
}
// Status calls the client's `Ping` method to determine connectivity.
func (c *Client) Status(ctx context.Context) error {
return c.PingContext(ctx)
}