6
6
"github.com/XDoubleU/essentia/pkg/database"
7
7
"github.com/jackc/pgx/v5"
8
8
"github.com/jackc/pgx/v5/pgconn"
9
- "github.com/jackc/pgx/v5/pgtype"
10
9
)
11
10
12
11
// PgxSyncTx uses [database.SyncTx] to make sure
@@ -17,19 +16,14 @@ type PgxSyncTx struct {
17
16
18
17
// PgxSyncRow is a concurrent wrapper for [pgx.Row].
19
18
type PgxSyncRow struct {
20
- rows pgx.Rows
21
- err error
19
+ syncTx * database. SyncTx [ pgx.Tx ]
20
+ row pgx. Row
22
21
}
23
22
24
23
// PgxSyncRows is a concurrent wrapper for [pgx.Rows].
25
24
type PgxSyncRows struct {
26
- values [][]any
27
- rawValues [][][]byte
28
- err error
29
- fieldDescriptions []pgconn.FieldDescription
30
- commandTag pgconn.CommandTag
31
- conn * pgx.Conn
32
- i int
25
+ syncTx * database.SyncTx [pgx.Tx ]
26
+ rows pgx.Rows
33
27
}
34
28
35
29
// CreatePgxSyncTx returns a [pgx.Tx] which works concurrently.
@@ -62,48 +56,17 @@ func (tx *PgxSyncTx) Query(
62
56
sql string ,
63
57
args ... any ,
64
58
) (pgx.Rows , error ) {
65
- return database .WrapInSyncTx (
66
- ctx ,
67
- tx .syncTx ,
68
- func (ctx context.Context ) (* PgxSyncRows , error ) {
69
- rows , err := tx .syncTx .Tx .Query (ctx , sql , args ... )
70
- if err != nil {
71
- return nil , err
72
- }
73
- defer rows .Close ()
74
-
75
- var results [][]any
76
- var rawResults [][][]byte
77
- for rows .Next () {
78
- var values []any
79
- values , err = rows .Values ()
80
- if err != nil {
81
- break
82
- }
83
-
84
- temp := rows .RawValues ()
85
- rawValues := make ([][]byte , len (temp ))
86
- copy (rawValues , temp )
87
-
88
- results = append (results , values )
89
- rawResults = append (rawResults , rawValues )
90
- }
91
-
92
- if err == nil {
93
- err = rows .Err ()
94
- }
95
-
96
- return & PgxSyncRows {
97
- values : results ,
98
- rawValues : rawResults ,
99
- err : err ,
100
- fieldDescriptions : rows .FieldDescriptions (),
101
- commandTag : rows .CommandTag (),
102
- conn : rows .Conn (),
103
- i : - 1 ,
104
- }, nil
105
- },
106
- )
59
+ tx .syncTx .Mutex .Lock ()
60
+
61
+ rows , err := tx .syncTx .Tx .Query (ctx , sql , args ... )
62
+ if err != nil {
63
+ return nil , err
64
+ }
65
+
66
+ return & PgxSyncRows {
67
+ syncTx : tx .syncTx ,
68
+ rows : rows ,
69
+ }, nil
107
70
}
108
71
109
72
// SendBatch is used to wrap [pgx.Tx.QueryRow] in a [database.SyncTx].
@@ -117,84 +80,68 @@ func (tx *PgxSyncTx) SendBatch(ctx context.Context, b *pgx.Batch) pgx.BatchResul
117
80
)
118
81
}
119
82
120
- // Close doesn't do anything for [PgxSyncRows] as these are closed in [Query ].
83
+ // Close closes the opened [pgx.Rows ].
121
84
func (rows * PgxSyncRows ) Close () {
85
+ rows .syncTx .Unlock ()
86
+ rows .rows .Close ()
122
87
}
123
88
124
89
// CommandTag fetches the [pgconn.CommandTag].
125
90
func (rows * PgxSyncRows ) CommandTag () pgconn.CommandTag {
126
- return rows .commandTag
91
+ return rows .rows . CommandTag ()
127
92
}
128
93
129
94
// Conn fetches the [pgx.Conn].
130
95
func (rows * PgxSyncRows ) Conn () * pgx.Conn {
131
- return rows .conn
96
+ return rows .rows . Conn ()
132
97
}
133
98
134
99
// Err fetches any errors.
135
100
func (rows * PgxSyncRows ) Err () error {
136
- return rows .err
101
+ return rows .rows . Err ()
137
102
}
138
103
139
104
// FieldDescriptions fetches [pgconn.FieldDescription]s.
140
105
func (rows * PgxSyncRows ) FieldDescriptions () []pgconn.FieldDescription {
141
- return rows .fieldDescriptions
106
+ return rows .rows . FieldDescriptions ()
142
107
}
143
108
144
109
// Next continues to the next row of [PgxSyncRows] if there is one.
145
110
func (rows * PgxSyncRows ) Next () bool {
146
- rows .i ++
147
- return rows .i < len (rows .values )
111
+ return rows .rows .Next ()
148
112
}
149
113
150
114
// RawValues fetches the raw values of the current row.
151
115
func (rows * PgxSyncRows ) RawValues () [][]byte {
152
- return rows .rawValues [ rows .i ]
116
+ return rows .rows .RawValues ()
153
117
}
154
118
155
119
// Scan scans the data of the current row into dest.
156
120
func (rows * PgxSyncRows ) Scan (dest ... any ) error {
157
- if err := rows .Err (); err != nil {
158
- return err
159
- }
160
-
161
- return pgx .ScanRow (
162
- pgtype .NewMap (),
163
- rows .FieldDescriptions (),
164
- rows .RawValues (),
165
- dest ... )
121
+ return rows .rows .Scan (dest ... )
166
122
}
167
123
168
124
// Values fetches the values of the current row.
169
125
func (rows * PgxSyncRows ) Values () ([]any , error ) {
170
- return rows .values [ rows .i ], nil
126
+ return rows .rows .Values ()
171
127
}
172
128
173
129
// QueryRow is used to wrap [pgx.Tx.QueryRow] in a [database.SyncTx].
174
130
func (tx * PgxSyncTx ) QueryRow (ctx context.Context , sql string , args ... any ) pgx.Row {
175
- rows , err := tx .Query (ctx , sql , args ... )
131
+ tx .syncTx .Mutex .Lock ()
132
+
133
+ row := tx .syncTx .Tx .QueryRow (ctx , sql , args ... )
176
134
177
135
return & PgxSyncRow {
178
- rows : rows ,
179
- err : err ,
136
+ syncTx : tx . syncTx ,
137
+ row : row ,
180
138
}
181
139
}
182
140
183
141
// Scan scans the data of [PgxSyncRow] into dest.
184
142
func (row * PgxSyncRow ) Scan (dest ... any ) error {
185
- if row .err != nil {
186
- return row .err
187
- }
188
-
189
- if err := row .rows .Err (); err != nil {
190
- return err
191
- }
192
-
193
- if ! row .rows .Next () {
194
- return pgx .ErrNoRows
195
- }
196
-
197
- return row .rows .Scan (dest ... )
143
+ defer row .syncTx .Unlock ()
144
+ return row .row .Scan (dest ... )
198
145
}
199
146
200
147
// Ping is used to wrap [pgx.Tx.Conn.Ping] in a [database.SyncTx].
0 commit comments