@m2k-5f/pgtx 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/dist/connection.d.ts +28 -16
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +138 -82
- package/dist/error.d.ts +18 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +37 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -1
- package/dist/pool.d.ts +1 -1
- package/dist/pool.d.ts.map +1 -1
- package/dist/pool.js +5 -5
- package/dist/protocol/connection-response-reader.d.ts +2 -1
- package/dist/protocol/connection-response-reader.d.ts.map +1 -1
- package/dist/protocol/connection-response-reader.js +39 -3
- package/dist/query.d.ts +24 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +28 -0
- package/dist/queue.d.ts +2 -0
- package/dist/queue.d.ts.map +1 -1
- package/dist/queue.js +14 -2
- package/dist/transaction.d.ts +1 -1
- package/dist/transaction.d.ts.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/value-parser.d.ts +1 -1
- package/dist/utils/value-parser.d.ts.map +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -25,10 +25,12 @@ npm install @m2k-5f/pgtx
|
|
|
25
25
|
|
|
26
26
|
| Tool | RPS | Avg Time | Connections |
|
|
27
27
|
|------|-----|----------|-------------|
|
|
28
|
-
| **Pgtx** | **1584** | **0.631ms** | **20 (
|
|
29
|
-
| Native `pg` | 179 | 5.585ms | 20 |
|
|
28
|
+
| **Pgtx** | **1584** | **0.631ms** | **20 pool connections (pipeline multiplexing)** |
|
|
29
|
+
| Native `pg` | 179 | 5.585ms | 20 pool connections |
|
|
30
30
|
|
|
31
|
-
**9x faster**
|
|
31
|
+
**Up to 9x faster in concurrent pipeline workloads**
|
|
32
|
+
|
|
33
|
+
**Pgtx achieves higher throughput by multiplexing concurrent queries over PostgreSQL connections using pipeline execution.**
|
|
32
34
|
|
|
33
35
|
|
|
34
36
|
> Benchmark source available in the [repository](https://github.com/M2K-5F/pgtx).
|
|
@@ -43,7 +45,7 @@ npm install @m2k-5f/pgtx
|
|
|
43
45
|
- **Bulk inserts** — Auto-extract columns from objects
|
|
44
46
|
- **Dynamic updates** — Generate SET clauses from objects
|
|
45
47
|
- **Recursive fragments** — Compose SQL like Lego
|
|
46
|
-
- **Prepared statements** —
|
|
48
|
+
- **Prepared statements** — Automatic prepared statement caching
|
|
47
49
|
- **Connection pool** — Auto-management connections with support for pipeline queries via the pool itself.
|
|
48
50
|
- **Zero dependencies** — Lightweight and blazing
|
|
49
51
|
|
package/dist/connection.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { ColumnDescription } from "./types";
|
|
1
|
+
import { Branded, ColumnDescription } from "./types";
|
|
2
2
|
import { Transaction } from "./transaction";
|
|
3
|
-
import { Queue } from "./queue";
|
|
4
3
|
type LogLevel = "none" | "error" | "notice" | "query";
|
|
5
4
|
export type ConnectionParams = {
|
|
6
5
|
user: string;
|
|
@@ -10,17 +9,25 @@ export type ConnectionParams = {
|
|
|
10
9
|
database: string;
|
|
11
10
|
logLevel?: LogLevel;
|
|
12
11
|
};
|
|
13
|
-
export type
|
|
14
|
-
columns: ColumnDescription[];
|
|
12
|
+
export type ExecuteQueueUnit = {
|
|
15
13
|
rows: (string | null)[][];
|
|
16
14
|
resolve: (value: any) => void;
|
|
17
15
|
reject: (err: Error) => void;
|
|
18
|
-
|
|
19
|
-
statementName: string | null;
|
|
16
|
+
statementName: StatementName;
|
|
20
17
|
};
|
|
21
|
-
export
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
export type ParsingQueueUnit = {
|
|
19
|
+
resolve: (statementName: StatementName) => void;
|
|
20
|
+
reject: (error: Error) => void;
|
|
21
|
+
text: QueryText;
|
|
22
|
+
statementName: StatementName;
|
|
23
|
+
};
|
|
24
|
+
export type DescribeQueueUnit = {
|
|
25
|
+
resolve: (value: ColumnDescription[]) => void;
|
|
26
|
+
reject: (error: Error) => void;
|
|
27
|
+
statementName: StatementName;
|
|
28
|
+
};
|
|
29
|
+
export type StatementName = Branded<string, 'statementName'>;
|
|
30
|
+
export type QueryText = Branded<string, 'queryText'>;
|
|
24
31
|
/**
|
|
25
32
|
* Represents a single dedicated connection to the PostgreSQL database.
|
|
26
33
|
*
|
|
@@ -56,10 +63,11 @@ export declare class Connection {
|
|
|
56
63
|
private _isAlive;
|
|
57
64
|
private _socket;
|
|
58
65
|
private _writer;
|
|
59
|
-
private
|
|
60
|
-
private
|
|
61
|
-
private
|
|
62
|
-
private
|
|
66
|
+
private _pipelinesQueue;
|
|
67
|
+
private _described;
|
|
68
|
+
private _describingPending;
|
|
69
|
+
private _parsed;
|
|
70
|
+
private _parsingPending;
|
|
63
71
|
private _stmtCounter;
|
|
64
72
|
private _logLevel;
|
|
65
73
|
private _nextStatement;
|
|
@@ -69,7 +77,7 @@ export declare class Connection {
|
|
|
69
77
|
*
|
|
70
78
|
* @param params - Connection parameters
|
|
71
79
|
* @returns A new Connection instance
|
|
72
|
-
* @throws {
|
|
80
|
+
* @throws {PostgresError} If authentication fails or connection cannot be established
|
|
73
81
|
*
|
|
74
82
|
* @example
|
|
75
83
|
* ```ts
|
|
@@ -107,7 +115,9 @@ export declare class Connection {
|
|
|
107
115
|
* const users = await conn.query<User>`SELECT * FROM users`
|
|
108
116
|
* ```
|
|
109
117
|
*/
|
|
110
|
-
query<T extends Record<string,
|
|
118
|
+
query<T extends Record<string, any>>(templates: TemplateStringsArray, ...params: any[]): Promise<T[]>;
|
|
119
|
+
private _createQuery;
|
|
120
|
+
private _writeQuery;
|
|
111
121
|
/**
|
|
112
122
|
* Starts a managed transaction on this connection.
|
|
113
123
|
*
|
|
@@ -132,13 +142,15 @@ export declare class Connection {
|
|
|
132
142
|
begin<T>(txCallback: (transaction: Transaction) => Promise<T>): Promise<T>;
|
|
133
143
|
private _registerFlush;
|
|
134
144
|
private _flush;
|
|
145
|
+
private _getCurrentQuery;
|
|
146
|
+
private _rejectPipeline;
|
|
135
147
|
private _handlePacket;
|
|
136
|
-
private _handleError;
|
|
137
148
|
/**
|
|
138
149
|
* Checks if the connection is still alive and usable.
|
|
139
150
|
* Returns `false` if the socket is destroyed or connection is dead.
|
|
140
151
|
*/
|
|
141
152
|
get isAlive(): boolean;
|
|
153
|
+
private _destroyConnection;
|
|
142
154
|
/**
|
|
143
155
|
* Closes the connection immediately.
|
|
144
156
|
* All pending queries will be rejected with an error.
|
package/dist/connection.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"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"}
|
package/dist/connection.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Connection =
|
|
3
|
+
exports.Connection = void 0;
|
|
4
4
|
const process_1 = require("process");
|
|
5
5
|
const connection_request_writer_1 = require("./protocol/connection-request-writer");
|
|
6
6
|
const socket_authorization_1 = require("./protocol/socket-authorization");
|
|
@@ -10,16 +10,8 @@ const template_compiler_1 = require("./utils/template-compiler");
|
|
|
10
10
|
const transaction_1 = require("./transaction");
|
|
11
11
|
const socket_connector_1 = require("./protocol/socket-connector");
|
|
12
12
|
const queue_1 = require("./queue");
|
|
13
|
+
const query_1 = require("./query");
|
|
13
14
|
const ErrConnectionDead = new Error("Connection is Dead");
|
|
14
|
-
class ConnectionQueryQueue extends queue_1.Queue {
|
|
15
|
-
rejectAllNext(error) {
|
|
16
|
-
while (!this.isFree) {
|
|
17
|
-
this.get().reject(error);
|
|
18
|
-
this.next();
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
exports.ConnectionQueryQueue = ConnectionQueryQueue;
|
|
23
15
|
/**
|
|
24
16
|
* Represents a single dedicated connection to the PostgreSQL database.
|
|
25
17
|
*
|
|
@@ -57,13 +49,16 @@ class Connection {
|
|
|
57
49
|
constructor(socket, writer, logLevel) {
|
|
58
50
|
this._isFlushing = false;
|
|
59
51
|
this._isAlive = true;
|
|
60
|
-
this.
|
|
61
|
-
this.
|
|
62
|
-
this.
|
|
63
|
-
this.
|
|
52
|
+
this._pipelinesQueue = new queue_1.Queue();
|
|
53
|
+
this._described = new Map();
|
|
54
|
+
this._describingPending = new Set();
|
|
55
|
+
this._parsed = new Map();
|
|
56
|
+
this._parsingPending = new Map();
|
|
64
57
|
this._stmtCounter = 0;
|
|
65
58
|
this._logLevel = logLevel;
|
|
66
|
-
this._socket = new socket_connector_1.SocketConnector(socket, (type, reader) => this._handlePacket(type, reader),
|
|
59
|
+
this._socket = new socket_connector_1.SocketConnector(socket, (type, reader) => this._handlePacket(type, reader), (err) => {
|
|
60
|
+
this._destroyConnection();
|
|
61
|
+
});
|
|
67
62
|
this._writer = writer;
|
|
68
63
|
}
|
|
69
64
|
/**
|
|
@@ -71,7 +66,7 @@ class Connection {
|
|
|
71
66
|
*
|
|
72
67
|
* @param params - Connection parameters
|
|
73
68
|
* @returns A new Connection instance
|
|
74
|
-
* @throws {
|
|
69
|
+
* @throws {PostgresError} If authentication fails or connection cannot be established
|
|
75
70
|
*
|
|
76
71
|
* @example
|
|
77
72
|
* ```ts
|
|
@@ -113,47 +108,67 @@ class Connection {
|
|
|
113
108
|
* const users = await conn.query<User>`SELECT * FROM users`
|
|
114
109
|
* ```
|
|
115
110
|
*/
|
|
116
|
-
query(templates, ...
|
|
111
|
+
query(templates, ...params) {
|
|
112
|
+
this._registerFlush();
|
|
117
113
|
if (!this._isAlive)
|
|
118
114
|
throw ErrConnectionDead;
|
|
119
|
-
const
|
|
115
|
+
const { text, args } = (0, template_compiler_1.compileSqlTemplate)({ templates, args: params });
|
|
120
116
|
if (this._logLevel === 'query') {
|
|
121
|
-
console.log(`\nQUERY: ${
|
|
117
|
+
console.log(`\nQUERY: ${text}\n${args.length !== 0 ? `ARGUMENTS: [${args}]\n` : ""}`);
|
|
122
118
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
119
|
+
const query = this._createQuery(text, args);
|
|
120
|
+
this._writeQuery(query);
|
|
121
|
+
return query.promise;
|
|
122
|
+
}
|
|
123
|
+
_createQuery(text, args) {
|
|
124
|
+
if (this._parsed.has(text)) {
|
|
125
|
+
const statementName = this._parsed.get(text);
|
|
126
|
+
if (this._described.has(statementName)) {
|
|
127
|
+
const columns = this._described.get(statementName);
|
|
128
|
+
return new query_1.Query(text, args, query_1.QueryState.Executing, statementName, columns);
|
|
130
129
|
}
|
|
131
130
|
else {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
if (!this._statements.has(query.text) && !this._parsePending.has(query.text)) {
|
|
135
|
-
statementName = this._nextStatement();
|
|
136
|
-
this._parsePending.set(query.text, statementName);
|
|
137
|
-
rejectParsed = (error) => {
|
|
138
|
-
this._parsePending.delete(query.text);
|
|
139
|
-
reject(error);
|
|
140
|
-
};
|
|
141
|
-
this._writer
|
|
142
|
-
.writeParse(statementName, query.text);
|
|
143
|
-
console.log('parsed once', statementName, query.text);
|
|
131
|
+
if (this._describingPending.has(statementName)) {
|
|
132
|
+
return new query_1.Query(text, args, query_1.QueryState.Executing, statementName);
|
|
144
133
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
134
|
+
else {
|
|
135
|
+
this._describingPending.add(statementName);
|
|
136
|
+
return new query_1.Query(text, args, query_1.QueryState.Describing, statementName);
|
|
148
137
|
}
|
|
149
|
-
this._queue.push({
|
|
150
|
-
resolve, reject: rejectParsed, columns: [], rows: [], statementName: statementName, text: query.text
|
|
151
|
-
});
|
|
152
|
-
this._writer
|
|
153
|
-
.writeBind("", statementName, query.args)
|
|
154
|
-
.writeExecute("");
|
|
155
138
|
}
|
|
156
|
-
}
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
if (this._parsingPending.has(text)) {
|
|
142
|
+
const statementName = this._parsingPending.get(text);
|
|
143
|
+
return new query_1.Query(text, args, query_1.QueryState.Describing, statementName);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
const statementName = this._nextStatement();
|
|
147
|
+
this._parsingPending.set(text, statementName);
|
|
148
|
+
return new query_1.Query(text, args, query_1.QueryState.Parsing, statementName);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
_writeQuery(query) {
|
|
153
|
+
if (query.state === query_1.QueryState.Parsing) {
|
|
154
|
+
this._writer
|
|
155
|
+
.writeParse(query.statementName, query.text)
|
|
156
|
+
.writeDescribe(query.statementName)
|
|
157
|
+
.writeBind("", query.statementName, query.args)
|
|
158
|
+
.writeExecute("");
|
|
159
|
+
}
|
|
160
|
+
if (query.state === query_1.QueryState.Describing) {
|
|
161
|
+
this._writer
|
|
162
|
+
.writeDescribe(query.statementName)
|
|
163
|
+
.writeBind("", query.statementName, query.args)
|
|
164
|
+
.writeExecute("");
|
|
165
|
+
}
|
|
166
|
+
if (query.state === query_1.QueryState.Executing) {
|
|
167
|
+
this._writer
|
|
168
|
+
.writeBind("", query.statementName, query.args)
|
|
169
|
+
.writeExecute("");
|
|
170
|
+
}
|
|
171
|
+
this._pipelinesQueue.get().push(query);
|
|
157
172
|
}
|
|
158
173
|
/**
|
|
159
174
|
* Starts a managed transaction on this connection.
|
|
@@ -196,12 +211,16 @@ class Connection {
|
|
|
196
211
|
_registerFlush() {
|
|
197
212
|
if (!this._isFlushing) {
|
|
198
213
|
this._isFlushing = true;
|
|
199
|
-
|
|
214
|
+
this._pipelinesQueue.push(new queue_1.Queue());
|
|
215
|
+
(0, process_1.nextTick)(() => {
|
|
216
|
+
this._flush();
|
|
217
|
+
});
|
|
200
218
|
}
|
|
201
219
|
}
|
|
202
220
|
_flush() {
|
|
221
|
+
this._isFlushing = false;
|
|
203
222
|
if (!this._isAlive) {
|
|
204
|
-
this.
|
|
223
|
+
this._rejectPipeline(ErrConnectionDead);
|
|
205
224
|
return;
|
|
206
225
|
}
|
|
207
226
|
try {
|
|
@@ -209,19 +228,30 @@ class Connection {
|
|
|
209
228
|
this._writer.clear();
|
|
210
229
|
}
|
|
211
230
|
catch (err) {
|
|
212
|
-
this.
|
|
213
|
-
|
|
214
|
-
|
|
231
|
+
this._destroyConnection();
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
_getCurrentQuery() {
|
|
235
|
+
return this._pipelinesQueue.get().get();
|
|
236
|
+
}
|
|
237
|
+
_rejectPipeline(error) {
|
|
238
|
+
if (this._pipelinesQueue.isFree)
|
|
239
|
+
return;
|
|
240
|
+
const queue = this._pipelinesQueue.get();
|
|
241
|
+
while (queue.hasMore) {
|
|
242
|
+
queue.get().reject(error);
|
|
243
|
+
queue.next();
|
|
215
244
|
}
|
|
216
245
|
}
|
|
217
246
|
_handlePacket(type, reader) {
|
|
218
|
-
const context = this._queue.get();
|
|
219
247
|
switch (type) {
|
|
220
248
|
case constants_1.ResponseTypes.ParseComplete:
|
|
221
249
|
{
|
|
222
250
|
reader.readParseComplete();
|
|
223
|
-
this.
|
|
224
|
-
this.
|
|
251
|
+
const query = this._getCurrentQuery();
|
|
252
|
+
this._parsingPending.delete(query.text);
|
|
253
|
+
this._parsed.set(query.text, query.statementName);
|
|
254
|
+
query.state = query_1.QueryState.Describing;
|
|
225
255
|
}
|
|
226
256
|
break;
|
|
227
257
|
case constants_1.ResponseTypes.BindComplete:
|
|
@@ -242,50 +272,74 @@ class Connection {
|
|
|
242
272
|
case constants_1.ResponseTypes.NoData:
|
|
243
273
|
{
|
|
244
274
|
reader.readNoData();
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
275
|
+
const query = this._getCurrentQuery();
|
|
276
|
+
this._describingPending.delete(query.statementName);
|
|
277
|
+
this._described.set(query.statementName, []);
|
|
278
|
+
query.state = query_1.QueryState.Executing;
|
|
248
279
|
}
|
|
249
280
|
break;
|
|
250
281
|
case constants_1.ResponseTypes.RowDescription:
|
|
251
282
|
{
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
283
|
+
const columns = reader.readRowDescription();
|
|
284
|
+
const query = this._getCurrentQuery();
|
|
285
|
+
this._describingPending.delete(query.statementName);
|
|
286
|
+
this._described.set(query.statementName, columns);
|
|
287
|
+
query.state = query_1.QueryState.Executing;
|
|
288
|
+
query.columns = columns;
|
|
258
289
|
}
|
|
259
290
|
break;
|
|
260
291
|
case constants_1.ResponseTypes.DataRow:
|
|
261
292
|
{
|
|
262
|
-
|
|
293
|
+
const query = this._getCurrentQuery();
|
|
294
|
+
query.rows.push(reader.readDataRow());
|
|
263
295
|
}
|
|
264
296
|
break;
|
|
265
297
|
case constants_1.ResponseTypes.ComandComplete:
|
|
266
298
|
{
|
|
267
299
|
reader.readCommandComplete();
|
|
268
|
-
if (
|
|
269
|
-
|
|
300
|
+
if (this._pipelinesQueue.isFree) {
|
|
301
|
+
this._destroyConnection();
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
const query = this._getCurrentQuery();
|
|
305
|
+
if (!query) {
|
|
306
|
+
this._destroyConnection();
|
|
307
|
+
break;
|
|
270
308
|
}
|
|
271
|
-
|
|
272
|
-
|
|
309
|
+
if (!query.columns) {
|
|
310
|
+
query.columns = this._described.get(query.statementName);
|
|
311
|
+
}
|
|
312
|
+
query.state = query_1.QueryState.Completed;
|
|
313
|
+
this._pipelinesQueue.get().next();
|
|
314
|
+
query.resolve((0, value_parser_1.parseRowValues)(query.columns, query.rows));
|
|
273
315
|
}
|
|
274
316
|
break;
|
|
275
317
|
case constants_1.ResponseTypes.ErrorResponse:
|
|
276
318
|
{
|
|
277
|
-
const
|
|
319
|
+
const error = reader.readErrorResponse();
|
|
278
320
|
if (this._logLevel === 'error' || this._logLevel === 'notice' || this._logLevel === 'query') {
|
|
279
|
-
console.log(`\nError: ${
|
|
321
|
+
console.log(`\nError: ${error}\n`);
|
|
280
322
|
}
|
|
281
|
-
const
|
|
282
|
-
|
|
323
|
+
const query = this._getCurrentQuery();
|
|
324
|
+
switch (query.state) {
|
|
325
|
+
case query_1.QueryState.Parsing:
|
|
326
|
+
this._parsingPending.delete(query.text);
|
|
327
|
+
break;
|
|
328
|
+
case query_1.QueryState.Describing:
|
|
329
|
+
this._describingPending.delete(query.statementName);
|
|
330
|
+
break;
|
|
331
|
+
}
|
|
332
|
+
query.state = query_1.QueryState.Failed;
|
|
333
|
+
this._rejectPipeline(error);
|
|
283
334
|
}
|
|
284
335
|
break;
|
|
285
336
|
case constants_1.ResponseTypes.ReadyForQuery:
|
|
286
337
|
{
|
|
287
|
-
this._isFlushing = false;
|
|
288
338
|
reader.readReadyForQuery();
|
|
339
|
+
const pipeline = this._pipelinesQueue.get();
|
|
340
|
+
if (!pipeline.hasMore) {
|
|
341
|
+
this._pipelinesQueue.next();
|
|
342
|
+
}
|
|
289
343
|
}
|
|
290
344
|
break;
|
|
291
345
|
case constants_1.ResponseTypes.Notice:
|
|
@@ -299,11 +353,6 @@ class Connection {
|
|
|
299
353
|
default: console.warn('Undeclared response type: ', type);
|
|
300
354
|
}
|
|
301
355
|
}
|
|
302
|
-
_handleError(error) {
|
|
303
|
-
this._isAlive = false;
|
|
304
|
-
this._queue.rejectAllNext(error);
|
|
305
|
-
this._socket.destroy();
|
|
306
|
-
}
|
|
307
356
|
/**
|
|
308
357
|
* Checks if the connection is still alive and usable.
|
|
309
358
|
* Returns `false` if the socket is destroyed or connection is dead.
|
|
@@ -311,6 +360,14 @@ class Connection {
|
|
|
311
360
|
get isAlive() {
|
|
312
361
|
return this._isAlive && !this._socket.isDestroyed;
|
|
313
362
|
}
|
|
363
|
+
_destroyConnection() {
|
|
364
|
+
this._isAlive = false;
|
|
365
|
+
this._socket.destroy();
|
|
366
|
+
while (this._pipelinesQueue.hasMore) {
|
|
367
|
+
this._rejectPipeline(ErrConnectionDead);
|
|
368
|
+
this._pipelinesQueue.next();
|
|
369
|
+
}
|
|
370
|
+
}
|
|
314
371
|
/**
|
|
315
372
|
* Closes the connection immediately.
|
|
316
373
|
* All pending queries will be rejected with an error.
|
|
@@ -322,8 +379,7 @@ class Connection {
|
|
|
322
379
|
* ```
|
|
323
380
|
*/
|
|
324
381
|
close() {
|
|
325
|
-
this.
|
|
326
|
-
this._socket.destroy();
|
|
382
|
+
this._destroyConnection();
|
|
327
383
|
}
|
|
328
384
|
}
|
|
329
385
|
exports.Connection = Connection;
|
package/dist/error.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare class PostgresError extends Error {
|
|
2
|
+
message: string;
|
|
3
|
+
code: string;
|
|
4
|
+
detail: string;
|
|
5
|
+
severity: string;
|
|
6
|
+
where: string;
|
|
7
|
+
hint: string;
|
|
8
|
+
position: string;
|
|
9
|
+
dataType: string;
|
|
10
|
+
constraint: string;
|
|
11
|
+
constructor(message: string, code: string, detail: string, severity: string, where: string, hint: string, position: string, dataType: string, constraint: string);
|
|
12
|
+
get isParseError(): boolean;
|
|
13
|
+
get isDeadlock(): boolean;
|
|
14
|
+
get isConstraintViolation(): boolean;
|
|
15
|
+
get isTimeout(): boolean;
|
|
16
|
+
get isConnectionFailure(): boolean;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,qBAAa,aAAc,SAAQ,KAAK;IAEhB,OAAO,EAAE,MAAM;IACxB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,MAAM;IACd,QAAQ,EAAE,MAAM;IAChB,KAAK,EAAE,MAAM;IACb,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,MAAM;IAChB,QAAQ,EAAE,MAAM;IAChB,UAAU,EAAE,MAAM;gBART,OAAO,EAAE,MAAM,EACxB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM;IAQ7B,IAAI,YAAY,IAAI,OAAO,CAE1B;IAID,IAAI,UAAU,IAAI,OAAO,CAExB;IAID,IAAI,qBAAqB,IAAI,OAAO,CAEnC;IAGD,IAAI,SAAS,IAAI,OAAO,CAEvB;IAGD,IAAI,mBAAmB,IAAI,OAAO,CAEjC;CACJ"}
|
package/dist/error.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PostgresError = void 0;
|
|
4
|
+
class PostgresError extends Error {
|
|
5
|
+
constructor(message, code, detail, severity, where, hint, position, dataType, constraint) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.message = message;
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.detail = detail;
|
|
10
|
+
this.severity = severity;
|
|
11
|
+
this.where = where;
|
|
12
|
+
this.hint = hint;
|
|
13
|
+
this.position = position;
|
|
14
|
+
this.dataType = dataType;
|
|
15
|
+
this.constraint = constraint;
|
|
16
|
+
this.name = "PostgresError";
|
|
17
|
+
}
|
|
18
|
+
// Parse error
|
|
19
|
+
get isParseError() {
|
|
20
|
+
return this.code.startsWith('42');
|
|
21
|
+
}
|
|
22
|
+
// Execute error
|
|
23
|
+
get isDeadlock() {
|
|
24
|
+
return this.code === '40P01';
|
|
25
|
+
}
|
|
26
|
+
// Execute error
|
|
27
|
+
get isConstraintViolation() {
|
|
28
|
+
return this.code.startsWith('23');
|
|
29
|
+
}
|
|
30
|
+
get isTimeout() {
|
|
31
|
+
return this.code === '57014';
|
|
32
|
+
}
|
|
33
|
+
get isConnectionFailure() {
|
|
34
|
+
return this.code.startsWith('08') || this.code.startsWith('57') && this.code !== '57014';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.PostgresError = PostgresError;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { Pool as PgtxPool } from "./pool";
|
|
|
2
2
|
import { IdentifierClause, InsertClause, ArrayClause, UpdateClause, ExcludeUpdateClause, WhereClause, LiteralClause, FragmentClause } from './clauses';
|
|
3
3
|
import { Connection } from "./connection";
|
|
4
4
|
import { Transaction } from "./transaction";
|
|
5
|
+
import { setTypeParser } from "./utils/value-parser";
|
|
5
6
|
/**
|
|
6
7
|
* Core SQL tagging utility for Pgtx.
|
|
7
8
|
* Provides type-safe helpers for building dynamic queries with recursive support.
|
|
@@ -119,4 +120,6 @@ export declare const sql: {
|
|
|
119
120
|
export { Connection as Connection };
|
|
120
121
|
export { Transaction as Transaction };
|
|
121
122
|
export { PgtxPool as Pool };
|
|
123
|
+
export { setTypeParser as setTypeParser };
|
|
124
|
+
export * from "./clauses";
|
|
122
125
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EACH,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,mBAAmB,EAEnB,WAAW,EACX,aAAa,EACb,cAAc,EACjB,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EACH,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,mBAAmB,EAEnB,WAAW,EACX,aAAa,EACb,cAAc,EACjB,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD;;;GAGG;AACH,eAAO,MAAM,GAAG;IACZ;;;;;;;;;;;OAWG;;IAGH;;;;;;OAMG;;IAGH;;;;;;OAMG;;IAGH;;;;;;;;OAQG;;IAGH;;;;;;;;;;;KAWC;;IAGD;;;;;;;;;;OAUG;;IAGH;;;;;;;OAOG;;IAGH;;;;;;;;OAQG;;IAGH;;;;;;;;;;;;;;;;;;;OAmBG;;CAEN,CAAA;AAGD;;;GAGG;AAEH,OAAO,EAAE,UAAU,IAAI,UAAU,EAAE,CAAA;AAEnC,OAAO,EAAE,WAAW,IAAI,WAAW,EAAE,CAAA;AAErC,OAAO,EAAE,QAAQ,IAAI,IAAI,EAAE,CAAA;AAE3B,OAAO,EAAE,aAAa,IAAI,aAAa,EAAE,CAAA;AAEzC,cAAc,WAAW,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
2
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Pool = exports.Transaction = exports.Connection = exports.sql = void 0;
|
|
17
|
+
exports.setTypeParser = exports.Pool = exports.Transaction = exports.Connection = exports.sql = void 0;
|
|
4
18
|
const pool_1 = require("./pool");
|
|
5
19
|
Object.defineProperty(exports, "Pool", { enumerable: true, get: function () { return pool_1.Pool; } });
|
|
6
20
|
const clauses_1 = require("./clauses");
|
|
@@ -8,6 +22,8 @@ const connection_1 = require("./connection");
|
|
|
8
22
|
Object.defineProperty(exports, "Connection", { enumerable: true, get: function () { return connection_1.Connection; } });
|
|
9
23
|
const transaction_1 = require("./transaction");
|
|
10
24
|
Object.defineProperty(exports, "Transaction", { enumerable: true, get: function () { return transaction_1.Transaction; } });
|
|
25
|
+
const value_parser_1 = require("./utils/value-parser");
|
|
26
|
+
Object.defineProperty(exports, "setTypeParser", { enumerable: true, get: function () { return value_parser_1.setTypeParser; } });
|
|
11
27
|
/**
|
|
12
28
|
* Core SQL tagging utility for Pgtx.
|
|
13
29
|
* Provides type-safe helpers for building dynamic queries with recursive support.
|
|
@@ -118,3 +134,4 @@ exports.sql = {
|
|
|
118
134
|
*/
|
|
119
135
|
array: clauses_1.ArrayClause.create,
|
|
120
136
|
};
|
|
137
|
+
__exportStar(require("./clauses"), exports);
|
package/dist/pool.d.ts
CHANGED
|
@@ -127,7 +127,7 @@ export declare class Pool {
|
|
|
127
127
|
* const users = await pool.query<User>`SELECT * FROM users`
|
|
128
128
|
* ```
|
|
129
129
|
*/
|
|
130
|
-
query<T extends Record<string,
|
|
130
|
+
query<T extends Record<string, any>>(templates: TemplateStringsArray, ...args: any[]): Promise<T[]>;
|
|
131
131
|
/**
|
|
132
132
|
* Number of available (idle) connections in the pool.
|
|
133
133
|
*/
|
package/dist/pool.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAK3C,KAAK,UAAU,GAAG,gBAAgB,GAAG;IACjC,GAAG,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,qBAAa,IAAI;IACb,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,IAAI,CAAQ;IACpB,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,QAAQ,CAAsB;IACtC,OAAO,CAAC,SAAS,CAAQ;IAEzB,OAAO,CAAC,YAAY;gBAIR,MAAM,EAAE,UAAU;IAM9B;;;;;;;;;;;;;;;;;OAiBG;IACG,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC;IA6BpC;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,IAAI,EAAE,UAAU;IAoBxB;;;;;;;;;;;;;;;;;OAiBG;IACG,KAAK,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAYhF;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,EAAE,oBAAoB,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAmCnG;;OAEG;IACH,IAAI,IAAI,WAEP;IAGD;;;OAGG;IACH,IAAI,KAAK,WAER;IAGD;;;;;;;;;;OAUG;IACG,KAAK;CAed"}
|
package/dist/pool.js
CHANGED
|
@@ -71,7 +71,7 @@ class Pool {
|
|
|
71
71
|
*/
|
|
72
72
|
async acquire() {
|
|
73
73
|
this._checkClosed();
|
|
74
|
-
while (
|
|
74
|
+
while (this._available.hasMore) {
|
|
75
75
|
const conn = this._available.get();
|
|
76
76
|
this._available.next();
|
|
77
77
|
if (conn.isAlive) {
|
|
@@ -117,7 +117,7 @@ class Pool {
|
|
|
117
117
|
this._total--;
|
|
118
118
|
return;
|
|
119
119
|
}
|
|
120
|
-
if (
|
|
120
|
+
if (this._waiting.hasMore) {
|
|
121
121
|
const waiter = this._waiting.get();
|
|
122
122
|
this._waiting.next();
|
|
123
123
|
waiter.resolve(conn);
|
|
@@ -178,7 +178,7 @@ class Pool {
|
|
|
178
178
|
*/
|
|
179
179
|
query(templates, ...args) {
|
|
180
180
|
this._checkClosed();
|
|
181
|
-
while (
|
|
181
|
+
while (this._available.hasMore) {
|
|
182
182
|
const conn = this._available.get();
|
|
183
183
|
if (conn.isAlive) {
|
|
184
184
|
return conn.query(templates, ...args);
|
|
@@ -229,12 +229,12 @@ class Pool {
|
|
|
229
229
|
* ```
|
|
230
230
|
*/
|
|
231
231
|
async close() {
|
|
232
|
-
while (
|
|
232
|
+
while (this._available.hasMore) {
|
|
233
233
|
const conn = this._available.get();
|
|
234
234
|
this._available.next();
|
|
235
235
|
conn.close();
|
|
236
236
|
}
|
|
237
|
-
while (
|
|
237
|
+
while (this._waiting.hasMore) {
|
|
238
238
|
const waiter = this._waiting.get();
|
|
239
239
|
this._waiting.next();
|
|
240
240
|
waiter.reject(new Error('Pool closed'));
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AuthenticationCode, ResponseType, TransactionStatus } from "./constants";
|
|
2
2
|
import { ColumnDescription } from "../types";
|
|
3
|
+
import { PostgresError } from "../error";
|
|
3
4
|
export declare class ConnectionResponseBuffer {
|
|
4
5
|
private buffer;
|
|
5
6
|
private caret;
|
|
@@ -31,7 +32,7 @@ export declare class ConnectionResponseReader {
|
|
|
31
32
|
PID: number;
|
|
32
33
|
secret: number;
|
|
33
34
|
};
|
|
34
|
-
readErrorResponse():
|
|
35
|
+
readErrorResponse(): PostgresError;
|
|
35
36
|
readReadyForQuery(): TransactionStatus;
|
|
36
37
|
readSaslMechanisms(): string[];
|
|
37
38
|
readSaslMessage(): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection-response-reader.d.ts","sourceRoot":"","sources":["../../src/protocol/connection-response-reader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"connection-response-reader.d.ts","sourceRoot":"","sources":["../../src/protocol/connection-response-reader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAGxC,qBAAa,wBAAwB;IAI7B,OAAO,CAAC,MAAM;IAHlB,OAAO,CAAC,KAAK,CAAI;IAEjB,OAAO;IAKP,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM;IAK1B,QAAQ,IAAI,MAAM;IAOlB,SAAS,IAAI,MAAM;IAOnB,SAAS,IAAI,MAAM;IAOnB,WAAW,IAAI,MAAM;IAQrB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAOrC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAOjC,OAAO,IAAI,OAAO;IAKlB,aAAa,IAAI,OAAO;IAaxB,iBAAiB;CAGpB;AAGD,qBAAa,wBAAwB;IAI7B,OAAO,CAAC,MAAM;IAHlB,OAAO,CAAC,mBAAmB,CAAK;IAEhC,OAAO;IAKP,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM;IAK1B,QAAQ,IAC6B,YAAY;IAIjD,kBAAkB,IAGoB,kBAAkB;IAIxD,WAAW;IAKX,mBAAmB;;;;IAUnB,kBAAkB;;;;IAUlB,iBAAiB,IAAI,aAAa;IA8ClC,iBAAiB,IAEoB,iBAAiB;IAItD,kBAAkB,IAAI,MAAM,EAAE;IAa9B,eAAe,IAAI,MAAM;IAOzB,kBAAkB;IAuBlB,WAAW;IAmBX,mBAAmB,IAAI,MAAM;IAM7B,OAAO;IAKP,aAAa;IAKb,iBAAiB;IAKjB,iBAAiB;IAKjB,gBAAgB;IAKhB,wBAAwB;IAQxB,UAAU;CAGb"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ConnectionResponseReader = exports.ConnectionResponseBuffer = void 0;
|
|
4
|
+
const error_1 = require("../error");
|
|
4
5
|
class ConnectionResponseBuffer {
|
|
5
6
|
constructor(buffer) {
|
|
6
7
|
this.buffer = buffer;
|
|
@@ -91,16 +92,51 @@ class ConnectionResponseReader {
|
|
|
91
92
|
}
|
|
92
93
|
readErrorResponse() {
|
|
93
94
|
this.buffer.readInt32();
|
|
95
|
+
let severity = '';
|
|
96
|
+
let code = '';
|
|
94
97
|
let message = '';
|
|
98
|
+
let detail = '';
|
|
99
|
+
let where = '';
|
|
100
|
+
let hint = '';
|
|
101
|
+
let position = '';
|
|
102
|
+
let dataType = '';
|
|
103
|
+
let constraint = '';
|
|
95
104
|
while (true) {
|
|
96
105
|
const marker = this.buffer.readChar();
|
|
97
106
|
if (marker === '\0')
|
|
98
107
|
break;
|
|
99
108
|
const text = this.buffer.readCString();
|
|
100
|
-
|
|
101
|
-
|
|
109
|
+
switch (marker) {
|
|
110
|
+
case 'S':
|
|
111
|
+
severity = text;
|
|
112
|
+
break;
|
|
113
|
+
case 'C':
|
|
114
|
+
code = text;
|
|
115
|
+
break;
|
|
116
|
+
case 'M':
|
|
117
|
+
message = text;
|
|
118
|
+
break;
|
|
119
|
+
case 'D':
|
|
120
|
+
detail = text;
|
|
121
|
+
break;
|
|
122
|
+
case 'W':
|
|
123
|
+
where = text;
|
|
124
|
+
break;
|
|
125
|
+
case 'H':
|
|
126
|
+
hint = text;
|
|
127
|
+
break;
|
|
128
|
+
case 'P':
|
|
129
|
+
position = text;
|
|
130
|
+
break;
|
|
131
|
+
case 'd':
|
|
132
|
+
dataType = text;
|
|
133
|
+
break;
|
|
134
|
+
case 'n':
|
|
135
|
+
constraint = text;
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
102
138
|
}
|
|
103
|
-
return message;
|
|
139
|
+
return new error_1.PostgresError(message, code, detail, severity, where, hint, position, dataType, constraint);
|
|
104
140
|
}
|
|
105
141
|
readReadyForQuery() {
|
|
106
142
|
this.buffer.readInt32();
|
package/dist/query.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { QueryText, StatementName } from "./connection";
|
|
2
|
+
import { ColumnDescription, ValueOF } from "./types";
|
|
3
|
+
export declare const QueryState: {
|
|
4
|
+
readonly Parsing: 0;
|
|
5
|
+
readonly Describing: 1;
|
|
6
|
+
readonly Executing: 2;
|
|
7
|
+
readonly Completed: 3;
|
|
8
|
+
readonly Failed: 4;
|
|
9
|
+
};
|
|
10
|
+
export type State = ValueOF<typeof QueryState>;
|
|
11
|
+
export declare class Query<T> {
|
|
12
|
+
text: QueryText;
|
|
13
|
+
args: (string | null)[];
|
|
14
|
+
state: State;
|
|
15
|
+
statementName: StatementName;
|
|
16
|
+
columns?: ColumnDescription[] | undefined;
|
|
17
|
+
promise: Promise<T[]>;
|
|
18
|
+
resolve: (value: T[]) => void;
|
|
19
|
+
reject: (error: Error) => void;
|
|
20
|
+
rows: (string | null)[][];
|
|
21
|
+
constructor(text: QueryText, args: (string | null)[], state: State, statementName: StatementName, columns?: ColumnDescription[] | undefined);
|
|
22
|
+
setState(state: State): void;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGrD,eAAO,MAAM,UAAU;;;;;;CAMb,CAAA;AAGV,MAAM,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,UAAU,CAAC,CAAA;AAG9C,qBAAa,KAAK,CAAC,CAAC;IAOL,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE;IACvB,KAAK,EAAE,KAAK;IACZ,aAAa,EAAE,aAAa;IAC5B,OAAO,CAAC,EAAE,iBAAiB,EAAE;IAVxC,OAAO,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAA;IACrB,OAAO,EAAG,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,IAAI,CAAA;IAC9B,MAAM,EAAG,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAC/B,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,CAAK;gBAGnB,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,EACvB,KAAK,EAAE,KAAK,EACZ,aAAa,EAAE,aAAa,EAC5B,OAAO,CAAC,EAAE,iBAAiB,EAAE,YAAA;IAQxC,QAAQ,CAAC,KAAK,EAAE,KAAK;CAGxB"}
|
package/dist/query.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Query = exports.QueryState = void 0;
|
|
4
|
+
exports.QueryState = {
|
|
5
|
+
Parsing: 0,
|
|
6
|
+
Describing: 1,
|
|
7
|
+
Executing: 2,
|
|
8
|
+
Completed: 3,
|
|
9
|
+
Failed: 4
|
|
10
|
+
};
|
|
11
|
+
class Query {
|
|
12
|
+
constructor(text, args, state, statementName, columns) {
|
|
13
|
+
this.text = text;
|
|
14
|
+
this.args = args;
|
|
15
|
+
this.state = state;
|
|
16
|
+
this.statementName = statementName;
|
|
17
|
+
this.columns = columns;
|
|
18
|
+
this.rows = [];
|
|
19
|
+
this.promise = new Promise((a, b) => {
|
|
20
|
+
this.resolve = a;
|
|
21
|
+
this.reject = b;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
setState(state) {
|
|
25
|
+
this.state = state;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.Query = Query;
|
package/dist/queue.d.ts
CHANGED
package/dist/queue.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAAA,qBAAa,KAAK,CAAC,CAAC;IAChB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,QAAQ,CAAI;IAEpB,IAAI;
|
|
1
|
+
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAAA,qBAAa,KAAK,CAAC,CAAC;IAChB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,QAAQ,CAAI;IAEpB,IAAI;IASJ,GAAG;IAKH,KAAK;IAYL,IAAI,CAAC,IAAI,EAAE,CAAC;IAIZ,IAAI,IAAI,WAEP;IAGD,IAAI,OAAO,YAEV;IAGD,IAAI,MAAM,YAA+C;CAC5D"}
|
package/dist/queue.js
CHANGED
|
@@ -8,7 +8,7 @@ class Queue {
|
|
|
8
8
|
}
|
|
9
9
|
next() {
|
|
10
10
|
this._pointer++;
|
|
11
|
-
if (this._pointer
|
|
11
|
+
if (this._pointer >= this._queue.length) {
|
|
12
12
|
this._queue = [];
|
|
13
13
|
this._pointer = 0;
|
|
14
14
|
}
|
|
@@ -16,12 +16,24 @@ class Queue {
|
|
|
16
16
|
get() {
|
|
17
17
|
return this._queue[this._pointer];
|
|
18
18
|
}
|
|
19
|
+
shift() {
|
|
20
|
+
const item = this._queue[this._pointer];
|
|
21
|
+
this._pointer++;
|
|
22
|
+
if (this._pointer >= this._queue.length) {
|
|
23
|
+
this._queue = [];
|
|
24
|
+
this._pointer = 0;
|
|
25
|
+
}
|
|
26
|
+
return item;
|
|
27
|
+
}
|
|
19
28
|
push(item) {
|
|
20
29
|
this._queue.push(item);
|
|
21
30
|
}
|
|
22
31
|
get size() {
|
|
23
32
|
return this._queue.length - this._pointer;
|
|
24
33
|
}
|
|
25
|
-
get
|
|
34
|
+
get hasMore() {
|
|
35
|
+
return this._pointer < this._queue.length;
|
|
36
|
+
}
|
|
37
|
+
get isFree() { return this._pointer >= this._queue.length; }
|
|
26
38
|
}
|
|
27
39
|
exports.Queue = Queue;
|
package/dist/transaction.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ export declare class Transaction {
|
|
|
23
23
|
/**
|
|
24
24
|
* Executes a query within the current transaction.
|
|
25
25
|
*/
|
|
26
|
-
query<T extends Record<string,
|
|
26
|
+
query<T extends Record<string, any>>(strings: TemplateStringsArray, ...values: any[]): Promise<T[]>;
|
|
27
27
|
/**
|
|
28
28
|
* Creates a sub-transaction using PostgreSQL SAVEPOINT.
|
|
29
29
|
* If the callback throws, only the actions within this savepoint are rolled back.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEzC;;;GAGG;AACH,qBAAa,WAAW;IAIhB,QAAQ,CAAC,IAAI,EAAE,UAAU;IAH7B,OAAO,CAAC,UAAU,CAAiB;gBAGtB,IAAI,EAAE,UAAU;IAG7B;;OAEG;IACH,IAAW,QAAQ,IAAI,OAAO,CAE7B;IAED,OAAO,CAAC,WAAW;IAMnB;;OAEG;IACU,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAOpC;;OAEG;IACU,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAOtC;;OAEG;IACU,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEzC;;;GAGG;AACH,qBAAa,WAAW;IAIhB,QAAQ,CAAC,IAAI,EAAE,UAAU;IAH7B,OAAO,CAAC,UAAU,CAAiB;gBAGtB,IAAI,EAAE,UAAU;IAG7B;;OAEG;IACH,IAAW,QAAQ,IAAI,OAAO,CAE7B;IAED,OAAO,CAAC,WAAW;IAMnB;;OAEG;IACU,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAOpC;;OAEG;IACU,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAOtC;;OAEG;IACU,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAKhH;;;;;;;;;OASG;IACU,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;CAe5G"}
|
package/dist/types.d.ts
CHANGED
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,CAAC,OAAO,SAAS,GAAG,EAAE,OAAO,SAAS,GAAG,EAAE,IAAI;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;CACpD,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;CAC3B,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IAC/B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,GAAG,EAAE,CAAC;CACf,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC3B,SAAS,EAAE,oBAAoB,CAAC;IAChC,IAAI,EAAE,GAAG,EAAE,CAAC;CACf,CAAA;AAGD,MAAM,MAAM,iBAAiB,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAClB,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,CAAC,OAAO,SAAS,GAAG,EAAE,OAAO,SAAS,GAAG,EAAE,IAAI;IACxE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;CACpD,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;CAC3B,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IAC/B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,GAAG,EAAE,CAAC;CACf,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC3B,SAAS,EAAE,oBAAoB,CAAC;IAChC,IAAI,EAAE,GAAG,EAAE,CAAC;CACf,CAAA;AAGD,MAAM,MAAM,iBAAiB,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,OAAO,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,GAAG;IAAC,OAAO,EAAE,KAAK,CAAA;CAAC,CAAA;AAEpD,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ColumnDescription } from "../types";
|
|
2
2
|
declare const Parsers: Record<number, (value: string) => unknown>;
|
|
3
|
-
export declare function parseRowValues(columns: ColumnDescription[], rows: (string | null)[][]): Record<string, any
|
|
3
|
+
export declare function parseRowValues(columns: ColumnDescription[], rows: (string | null)[][]): Record<string, any>[];
|
|
4
4
|
export declare const setTypeParser: (typeOID: keyof typeof Parsers, parser: (value: string) => unknown) => void;
|
|
5
5
|
export {};
|
|
6
6
|
//# sourceMappingURL=value-parser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"value-parser.d.ts","sourceRoot":"","sources":["../../src/utils/value-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AA+B5C,QAAA,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAkD9C,CAAA;AAMV,wBAAgB,cAAc,CAAC,OAAO,EAAE,iBAAiB,EAAE,EAAE,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"value-parser.d.ts","sourceRoot":"","sources":["../../src/utils/value-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AA+B5C,QAAA,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAkD9C,CAAA;AAMV,wBAAgB,cAAc,CAAC,OAAO,EAAE,iBAAiB,EAAE,EAAE,IAAI,EAAE,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CA8B7G;AAGD,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,OAAO,OAAO,EAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,SAE9F,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@m2k-5f/pgtx",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Blazing-fast PostgreSQL driver with pipeline support.",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -40,8 +40,9 @@
|
|
|
40
40
|
}
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
+
"@types/node": "^26.1.1",
|
|
44
|
+
"pg": "^8.22.0",
|
|
43
45
|
"tsx": "^4.21.0",
|
|
44
|
-
"typescript": "^5.0.0"
|
|
45
|
-
"@types/node": "^26.1.1"
|
|
46
|
+
"typescript": "^5.0.0"
|
|
46
47
|
}
|
|
47
48
|
}
|