v / vlib / db / pg / tx.v
167 lines · 141 sloc · 4.54 KB · 2b04a6ecbf16697b4a6ae2e1e02d3a381967e8f0
Raw
1module pg
2
3import io
4
5// Tx is a database transaction. It pins a single `Conn` from the pool for
6// the lifetime of the transaction, so all queries run on the same physical
7// connection. The pinned conn is returned to the pool when `commit()` or
8// `rollback()` is called; failing to call either leaks the conn.
9@[heap]
10pub struct Tx {
11mut:
12 conn &Conn = unsafe { nil }
13 done bool
14}
15
16fn (tx &Tx) ensure_active() ! {
17 if tx.done {
18 return error('pg: transaction is already finished')
19 }
20 if isnil(tx.conn) {
21 return error('pg: transaction has no connection')
22 }
23}
24
25fn (mut tx Tx) finish() {
26 if tx.done {
27 return
28 }
29 tx.done = true
30 if !isnil(tx.conn) {
31 mut c := tx.conn
32 c.close() or {}
33 tx.conn = unsafe { nil }
34 }
35}
36
37// commit commits the transaction and returns the pinned conn to the pool.
38pub fn (mut tx Tx) commit() ! {
39 tx.ensure_active()!
40 defer {
41 tx.finish()
42 }
43 tx.conn.commit()!
44}
45
46// rollback rolls back the transaction and returns the pinned conn to the pool.
47pub fn (mut tx Tx) rollback() ! {
48 tx.ensure_active()!
49 defer {
50 tx.finish()
51 }
52 tx.conn.rollback()!
53}
54
55// savepoint creates a savepoint named `name`.
56pub fn (mut tx Tx) savepoint(name string) ! {
57 tx.ensure_active()!
58 tx.conn.savepoint(name)!
59}
60
61// rollback_to rolls the transaction back to the savepoint named `name`.
62pub fn (mut tx Tx) rollback_to(name string) ! {
63 tx.ensure_active()!
64 tx.conn.rollback_to(name)!
65}
66
67// release_savepoint releases the savepoint named `name`.
68pub fn (mut tx Tx) release_savepoint(name string) ! {
69 tx.ensure_active()!
70 tx.conn.release_savepoint(name)!
71}
72
73// raw returns the pinned conn for advanced use cases. The caller MUST NOT
74// call `close()` on it; the conn is owned by the transaction.
75pub fn (mut tx Tx) raw() !&Conn {
76 tx.ensure_active()!
77 return tx.conn
78}
79
80// ---- exec/query helpers ----
81
82// exec runs `query` on the pinned conn.
83pub fn (mut tx Tx) exec(query string) ![]Row {
84 tx.ensure_active()!
85 return tx.conn.exec(query)
86}
87
88// exec_no_null runs `query` and returns rows with no nullable fields.
89pub fn (mut tx Tx) exec_no_null(query string) ![]RowNoNull {
90 tx.ensure_active()!
91 return tx.conn.exec_no_null(query)
92}
93
94// exec_result runs `query` and returns a `Result`.
95pub fn (mut tx Tx) exec_result(query string) !Result {
96 tx.ensure_active()!
97 return tx.conn.exec_result(query)
98}
99
100// exec_one runs `query` and returns its first row.
101pub fn (mut tx Tx) exec_one(query string) !Row {
102 tx.ensure_active()!
103 return tx.conn.exec_one(query)
104}
105
106// exec_param_many runs `query` with the given parameters.
107pub fn (mut tx Tx) exec_param_many(query string, params []string) ![]Row {
108 tx.ensure_active()!
109 return tx.conn.exec_param_many(query, params)
110}
111
112// exec_param_many_result runs `query` with parameters and returns a `Result`.
113pub fn (mut tx Tx) exec_param_many_result(query string, params []string) !Result {
114 tx.ensure_active()!
115 return tx.conn.exec_param_many_result(query, params)
116}
117
118// exec_param runs `query` with one `$1` parameter.
119pub fn (mut tx Tx) exec_param(query string, param string) ![]Row {
120 return tx.exec_param_many(query, [param])
121}
122
123// exec_param2 runs `query` with two parameters.
124pub fn (mut tx Tx) exec_param2(query string, param string, param2 string) ![]Row {
125 return tx.exec_param_many(query, [param, param2])
126}
127
128// q_int runs `query` and returns the first column of the first row as int.
129pub fn (mut tx Tx) q_int(query string) !int {
130 tx.ensure_active()!
131 return tx.conn.q_int(query)
132}
133
134// q_string runs `query` and returns the first column of the first row as string.
135pub fn (mut tx Tx) q_string(query string) !string {
136 tx.ensure_active()!
137 return tx.conn.q_string(query)
138}
139
140// q_strings runs `query` and returns the full row set (alias of `exec`).
141pub fn (mut tx Tx) q_strings(query string) ![]Row {
142 return tx.exec(query)
143}
144
145// prepare registers a prepared statement on the pinned conn.
146pub fn (mut tx Tx) prepare(name string, query string, num_params int) ! {
147 tx.ensure_active()!
148 return tx.conn.prepare(name, query, num_params)
149}
150
151// exec_prepared runs a previously-prepared statement on the pinned conn.
152pub fn (mut tx Tx) exec_prepared(name string, params []string) ![]Row {
153 tx.ensure_active()!
154 return tx.conn.exec_prepared(name, params)
155}
156
157// exec_prepared_result runs a previously-prepared statement on the pinned conn.
158pub fn (mut tx Tx) exec_prepared_result(name string, params []string) !Result {
159 tx.ensure_active()!
160 return tx.conn.exec_prepared_result(name, params)
161}
162
163// copy_expert runs a COPY command on the pinned conn.
164pub fn (mut tx Tx) copy_expert(query string, mut file io.ReaderWriter) !int {
165 tx.ensure_active()!
166 return tx.conn.copy_expert(query, mut file)
167}
168