node-firebird 2.9.0 → 2.10.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 +166 -6
- package/lib/index.d.ts +5 -0
- package/lib/index.js +32 -1
- package/lib/pool.js +1 -1
- package/lib/srp.d.ts +3 -3
- package/lib/types.d.ts +143 -5
- package/lib/uri.js +2 -2
- package/lib/wire/connection.d.ts +92 -59
- package/lib/wire/connection.js +267 -53
- package/lib/wire/const.d.ts +9 -1
- package/lib/wire/const.js +21 -9
- package/lib/wire/database.d.ts +51 -26
- package/lib/wire/database.js +26 -8
- package/lib/wire/eventConnection.js +5 -3
- package/lib/wire/query-stream.d.ts +18 -0
- package/lib/wire/query-stream.js +73 -0
- package/lib/wire/serialize.d.ts +18 -2
- package/lib/wire/serialize.js +7 -0
- package/lib/wire/service.d.ts +42 -0
- package/lib/wire/service.js +145 -0
- package/lib/wire/socket.d.ts +3 -1
- package/lib/wire/socket.js +5 -2
- package/lib/wire/statement.d.ts +31 -19
- package/lib/wire/statement.js +1 -5
- package/lib/wire/transaction.d.ts +30 -18
- package/lib/wire/transaction.js +23 -4
- package/lib/wire/wire-types.d.ts +116 -0
- package/lib/wire/wire-types.js +10 -0
- package/lib/wire/xsqlvar.d.ts +18 -18
- package/package.json +1 -1
- package/src/index.ts +36 -4
- package/src/messages.ts +1 -1
- package/src/pool.ts +1 -1
- package/src/srp.ts +6 -6
- package/src/types.ts +140 -5
- package/src/unix-crypt.ts +9 -9
- package/src/uri.ts +2 -2
- package/src/wire/connection.ts +464 -232
- package/src/wire/const.ts +21 -9
- package/src/wire/database.ts +75 -43
- package/src/wire/eventConnection.ts +8 -5
- package/src/wire/query-stream.ts +80 -0
- package/src/wire/serialize.ts +29 -0
- package/src/wire/service.ts +188 -6
- package/src/wire/socket.ts +17 -8
- package/src/wire/statement.ts +37 -29
- package/src/wire/transaction.ts +57 -32
- package/src/wire/wire-types.ts +127 -0
- package/src/wire/xsqlvar.ts +9 -7
package/src/wire/const.ts
CHANGED
|
@@ -269,7 +269,8 @@ const SUPPORTED_PROTOCOL = [
|
|
|
269
269
|
[protocol.PROTOCOL_VERSION16, connect.ARCHITECTURE_GENERIC, acceptType.ptype_lazy_send, acceptType.ptype_lazy_send, 7],
|
|
270
270
|
[protocol.PROTOCOL_VERSION17, connect.ARCHITECTURE_GENERIC, acceptType.ptype_lazy_send, acceptType.ptype_lazy_send, 8],
|
|
271
271
|
[protocol.PROTOCOL_VERSION18, connect.ARCHITECTURE_GENERIC, acceptType.ptype_lazy_send, acceptType.ptype_lazy_send, 9],
|
|
272
|
-
[protocol.PROTOCOL_VERSION19, connect.ARCHITECTURE_GENERIC, acceptType.ptype_lazy_send, acceptType.ptype_lazy_send, 10]
|
|
272
|
+
[protocol.PROTOCOL_VERSION19, connect.ARCHITECTURE_GENERIC, acceptType.ptype_lazy_send, acceptType.ptype_lazy_send, 10],
|
|
273
|
+
[protocol.PROTOCOL_VERSION20, connect.ARCHITECTURE_GENERIC, acceptType.ptype_lazy_send, acceptType.ptype_lazy_send, 11]
|
|
273
274
|
];
|
|
274
275
|
|
|
275
276
|
const authPlugin = {
|
|
@@ -472,16 +473,27 @@ const dpb = {
|
|
|
472
473
|
isc_dpb_reset_icu : 89,
|
|
473
474
|
isc_dpb_map_attach : 90,
|
|
474
475
|
isc_dpb_session_time_zone : 91,
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
476
|
+
// Firebird 4.0
|
|
477
|
+
isc_dpb_set_db_replica : 92,
|
|
478
|
+
isc_dpb_set_bind : 93,
|
|
479
|
+
isc_dpb_decfloat_round : 94,
|
|
480
|
+
isc_dpb_decfloat_traps : 95,
|
|
481
|
+
isc_dpb_clear_map : 96,
|
|
482
|
+
// Firebird 5.0
|
|
483
|
+
isc_dpb_upgrade_db : 97,
|
|
484
|
+
isc_dpb_parallel_workers : 100,
|
|
485
|
+
isc_dpb_worker_attach : 101,
|
|
486
|
+
// Firebird 6.0
|
|
487
|
+
// isc_dpb_owner sets the owner of a newly created database to a user
|
|
488
|
+
// other than the connecting one (create only; requires superuser).
|
|
489
|
+
isc_dpb_owner : 102,
|
|
490
|
+
isc_dpb_max_blob_cache_size : 103,
|
|
491
|
+
isc_dpb_max_inline_blob_size : 104, // Firebird 5.0.3+
|
|
478
492
|
// isc_dpb_search_path sets the comma-separated ordered list of schema
|
|
479
493
|
// names to search for unqualified object names (similar to PostgreSQL
|
|
480
|
-
// search_path).
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
// (CURRENT_SCHEMA) at connection time. Available on Protocol 20+.
|
|
484
|
-
isc_dpb_default_schema : 95,
|
|
494
|
+
// search_path). CURRENT_SCHEMA is the first existing schema of the list.
|
|
495
|
+
// Available on Protocol 20+ (Firebird 6.0).
|
|
496
|
+
isc_dpb_search_path : 105,
|
|
485
497
|
};
|
|
486
498
|
|
|
487
499
|
const cnct = {
|
package/src/wire/database.ts
CHANGED
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
import Events from 'events';
|
|
2
|
-
import { doError, fromCallback } from '../callback';
|
|
2
|
+
import { doError, fromCallback, type Callback, type SimpleCallback } from '../callback';
|
|
3
3
|
import { escape } from '../utils';
|
|
4
4
|
import Const from './const';
|
|
5
5
|
import EventConnection from './eventConnection';
|
|
6
6
|
import FbEventManager from './fbEventManager';
|
|
7
|
+
import makeQueryStream from './query-stream';
|
|
8
|
+
import type Connection from './connection';
|
|
9
|
+
import type Transaction from './transaction';
|
|
10
|
+
import type Statement from './statement';
|
|
11
|
+
import type { BatchCb, StatementCb, InternalQueryOptions } from './wire-types';
|
|
12
|
+
import type { BatchOptions, BatchResult, Isolation, QueryParams, QueryStreamOptions, TransactionCallback, TransactionOptions } from '../types';
|
|
13
|
+
|
|
14
|
+
/** Callback for startTransaction: the internal optional-args shape, or the
|
|
15
|
+
* public TransactionCallback (non-optional transaction) from types.ts. */
|
|
16
|
+
type TransactionCb = Callback<Transaction> | TransactionCallback;
|
|
17
|
+
|
|
18
|
+
/** startTransaction options: resolved options object, a bare isolation
|
|
19
|
+
* array, or omitted entirely (callback in the options position). */
|
|
20
|
+
type TransactionArg = TransactionOptions | Isolation | TransactionCb | undefined;
|
|
7
21
|
|
|
8
22
|
/***************************************
|
|
9
23
|
*
|
|
@@ -40,7 +54,7 @@ import FbEventManager from './fbEventManager';
|
|
|
40
54
|
*
|
|
41
55
|
***************************************/
|
|
42
56
|
|
|
43
|
-
function readblob(blob: any, callback:
|
|
57
|
+
function readblob(blob: any, callback: Callback): void {
|
|
44
58
|
if (blob === undefined || blob === null) {
|
|
45
59
|
callback(null, blob);
|
|
46
60
|
return;
|
|
@@ -80,7 +94,7 @@ function readblob(blob: any, callback: (err: any, data?: any) => void): void {
|
|
|
80
94
|
});
|
|
81
95
|
}
|
|
82
96
|
|
|
83
|
-
function fetchBlobSyncRow(row: any, meta: any[], callback:
|
|
97
|
+
function fetchBlobSyncRow(row: any, meta: any[], callback: Callback): void {
|
|
84
98
|
if (!row || !meta || !meta.length) {
|
|
85
99
|
callback(null, row);
|
|
86
100
|
return;
|
|
@@ -118,10 +132,10 @@ function fetchBlobSyncRow(row: any, meta: any[], callback: (err: any, row?: any)
|
|
|
118
132
|
}
|
|
119
133
|
|
|
120
134
|
class Database extends Events.EventEmitter {
|
|
121
|
-
connection:
|
|
135
|
+
connection: Connection;
|
|
122
136
|
eventid: number;
|
|
123
137
|
|
|
124
|
-
constructor(connection:
|
|
138
|
+
constructor(connection: Connection) {
|
|
125
139
|
super();
|
|
126
140
|
this.connection = connection;
|
|
127
141
|
connection.db = this;
|
|
@@ -132,7 +146,7 @@ class Database extends Events.EventEmitter {
|
|
|
132
146
|
return escape(value, this.connection.accept.protocolVersion);
|
|
133
147
|
}
|
|
134
148
|
|
|
135
|
-
detach(callback?:
|
|
149
|
+
detach(callback?: Callback, force?: boolean): this {
|
|
136
150
|
var self = this;
|
|
137
151
|
|
|
138
152
|
if (!force && self.connection._pending.length > 0) {
|
|
@@ -150,7 +164,7 @@ class Database extends Events.EventEmitter {
|
|
|
150
164
|
if (callback)
|
|
151
165
|
callback(err, obj);
|
|
152
166
|
|
|
153
|
-
}
|
|
167
|
+
});
|
|
154
168
|
} else {
|
|
155
169
|
self.emit('detach', false);
|
|
156
170
|
if (callback)
|
|
@@ -160,32 +174,35 @@ class Database extends Events.EventEmitter {
|
|
|
160
174
|
return self;
|
|
161
175
|
}
|
|
162
176
|
|
|
163
|
-
transaction(options:
|
|
177
|
+
transaction(options: TransactionArg, callback?: TransactionCb): this {
|
|
164
178
|
return this.startTransaction(options, callback);
|
|
165
179
|
}
|
|
166
180
|
|
|
167
|
-
startTransaction(options:
|
|
181
|
+
startTransaction(options: TransactionArg, callback?: TransactionCb): this {
|
|
168
182
|
this.connection.startTransaction(options, callback);
|
|
169
183
|
return this;
|
|
170
184
|
}
|
|
171
185
|
|
|
172
|
-
newStatement(query: string, callback:
|
|
173
|
-
|
|
186
|
+
newStatement(query: string, callback: StatementCb): this {
|
|
187
|
+
// the public strict callback shape and the internal optional-args
|
|
188
|
+
// shape only differ in optionality; treat it as the internal one
|
|
189
|
+
const cb = callback as Callback<Statement>;
|
|
190
|
+
this.startTransaction(function(err: any, transaction?: Transaction) {
|
|
174
191
|
|
|
175
|
-
if (err) {
|
|
176
|
-
|
|
192
|
+
if (err || !transaction) {
|
|
193
|
+
cb(err);
|
|
177
194
|
return;
|
|
178
195
|
}
|
|
179
196
|
|
|
180
|
-
transaction.newStatement(query, function(err: any, statement
|
|
197
|
+
transaction.newStatement(query, function(err: any, statement?: Statement) {
|
|
181
198
|
|
|
182
199
|
if (err) {
|
|
183
|
-
|
|
200
|
+
cb(err);
|
|
184
201
|
return;
|
|
185
202
|
}
|
|
186
203
|
|
|
187
204
|
transaction.commit(function(err: any) {
|
|
188
|
-
|
|
205
|
+
cb(err, statement);
|
|
189
206
|
});
|
|
190
207
|
});
|
|
191
208
|
});
|
|
@@ -193,7 +210,7 @@ class Database extends Events.EventEmitter {
|
|
|
193
210
|
return this;
|
|
194
211
|
}
|
|
195
212
|
|
|
196
|
-
execute(query: string, params?:
|
|
213
|
+
execute(query: string, params?: QueryParams | Callback, callback?: any, options?: InternalQueryOptions): this {
|
|
197
214
|
if (params instanceof Function) {
|
|
198
215
|
options = callback;
|
|
199
216
|
callback = params;
|
|
@@ -202,9 +219,9 @@ class Database extends Events.EventEmitter {
|
|
|
202
219
|
|
|
203
220
|
var self = this;
|
|
204
221
|
|
|
205
|
-
self.connection.startTransaction(function(err: any, transaction
|
|
222
|
+
self.connection.startTransaction(function(err: any, transaction?: Transaction) {
|
|
206
223
|
|
|
207
|
-
if (err) {
|
|
224
|
+
if (err || !transaction) {
|
|
208
225
|
doError(err, callback);
|
|
209
226
|
return;
|
|
210
227
|
}
|
|
@@ -238,17 +255,17 @@ class Database extends Events.EventEmitter {
|
|
|
238
255
|
* err.batchCompletion. Use transaction.executeBatch for partial-success
|
|
239
256
|
* handling.
|
|
240
257
|
*/
|
|
241
|
-
executeBatch(query: string, rows:
|
|
258
|
+
executeBatch(query: string, rows: QueryParams[], callback?: BatchCb, options?: BatchOptions): this {
|
|
242
259
|
var self = this;
|
|
243
260
|
|
|
244
|
-
self.connection.startTransaction(function(err: any, transaction
|
|
245
|
-
if (err) {
|
|
261
|
+
self.connection.startTransaction(function(err: any, transaction?: Transaction) {
|
|
262
|
+
if (err || !transaction) {
|
|
246
263
|
doError(err, callback);
|
|
247
264
|
return;
|
|
248
265
|
}
|
|
249
266
|
|
|
250
|
-
transaction.executeBatch(query, rows, function(err: any, result
|
|
251
|
-
if (err) {
|
|
267
|
+
transaction.executeBatch(query, rows, function(err: any, result?: BatchResult) {
|
|
268
|
+
if (err || !result) {
|
|
252
269
|
transaction.rollback(function() {
|
|
253
270
|
doError(err, callback);
|
|
254
271
|
});
|
|
@@ -277,7 +294,7 @@ class Database extends Events.EventEmitter {
|
|
|
277
294
|
return self;
|
|
278
295
|
}
|
|
279
296
|
|
|
280
|
-
sequentially(query: string, params?: any, on?: any, callback?: any, options:
|
|
297
|
+
sequentially(query: string, params?: any, on?: any, callback?: any, options: InternalQueryOptions | boolean = {}): this {
|
|
281
298
|
if (params instanceof Function) {
|
|
282
299
|
options = callback;
|
|
283
300
|
callback = on;
|
|
@@ -295,7 +312,7 @@ class Database extends Events.EventEmitter {
|
|
|
295
312
|
}
|
|
296
313
|
|
|
297
314
|
var self = this;
|
|
298
|
-
var _on = function(row: any, i: number, meta: any, next: (err?: any) => void) {
|
|
315
|
+
var _on = function(row: any, i: number, meta: any[], next: (err?: any) => void) {
|
|
299
316
|
var done = false;
|
|
300
317
|
var finish = function(err?: any) {
|
|
301
318
|
if (done) {
|
|
@@ -348,7 +365,20 @@ class Database extends Events.EventEmitter {
|
|
|
348
365
|
return self;
|
|
349
366
|
}
|
|
350
367
|
|
|
351
|
-
|
|
368
|
+
/**
|
|
369
|
+
* Run `query` and return an object-mode Readable emitting one row per
|
|
370
|
+
* chunk (what pg-query-stream / mysql2 .stream() return), with real
|
|
371
|
+
* backpressure: fetching pauses while the stream buffer is full. Runs
|
|
372
|
+
* in its own transaction, like db.query. Destroying the stream early
|
|
373
|
+
* (e.g. a pipeline() teardown) aborts the fetch and releases the
|
|
374
|
+
* statement. Rows go through the regular decode path, so typeCast,
|
|
375
|
+
* blobAsText and jsonAsObject all apply.
|
|
376
|
+
*/
|
|
377
|
+
queryStream(query: string, params?: QueryParams, options?: QueryStreamOptions) {
|
|
378
|
+
return makeQueryStream(this, query, params, options);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
query(query: string, params?: QueryParams | Callback, callback?: any, options: InternalQueryOptions = {}): this {
|
|
352
382
|
if (params instanceof Function) {
|
|
353
383
|
options = callback || {};
|
|
354
384
|
callback = params;
|
|
@@ -366,7 +396,7 @@ class Database extends Events.EventEmitter {
|
|
|
366
396
|
return self;
|
|
367
397
|
}
|
|
368
398
|
|
|
369
|
-
drop(callback?:
|
|
399
|
+
drop(callback?: SimpleCallback): void {
|
|
370
400
|
return this.connection.dropDatabase(callback);
|
|
371
401
|
}
|
|
372
402
|
|
|
@@ -377,7 +407,7 @@ class Database extends Events.EventEmitter {
|
|
|
377
407
|
* GDSCode.CANCELLED. `kind` defaults to fb_cancel_raise; cancellation is
|
|
378
408
|
* per-attachment, not per-statement.
|
|
379
409
|
*/
|
|
380
|
-
cancel(kind?: number |
|
|
410
|
+
cancel(kind?: number | SimpleCallback, callback?: SimpleCallback): this {
|
|
381
411
|
if (typeof kind === 'function') {
|
|
382
412
|
callback = kind;
|
|
383
413
|
kind = undefined;
|
|
@@ -386,7 +416,7 @@ class Database extends Events.EventEmitter {
|
|
|
386
416
|
return this;
|
|
387
417
|
}
|
|
388
418
|
|
|
389
|
-
attachEvent(callback:
|
|
419
|
+
attachEvent(callback: Callback<FbEventManager>): this {
|
|
390
420
|
var self = this;
|
|
391
421
|
const eventid = self.eventid++;
|
|
392
422
|
if (process.env.FIREBIRD_DEBUG) {
|
|
@@ -450,7 +480,7 @@ class Database extends Events.EventEmitter {
|
|
|
450
480
|
* @param {function} [callback] - Asynchronous completion callback.
|
|
451
481
|
* @returns {Database}
|
|
452
482
|
*/
|
|
453
|
-
createTablespace(name: string, filePath: string, callback?:
|
|
483
|
+
createTablespace(name: string, filePath: string, callback?: Callback): this {
|
|
454
484
|
const sql = `CREATE TABLESPACE ${name} FILE '${filePath}'`;
|
|
455
485
|
return this.execute(sql, [], callback);
|
|
456
486
|
}
|
|
@@ -464,7 +494,7 @@ class Database extends Events.EventEmitter {
|
|
|
464
494
|
* @param {function} [callback] - Asynchronous completion callback.
|
|
465
495
|
* @returns {Database}
|
|
466
496
|
*/
|
|
467
|
-
alterTablespace(name: string, filePath: string, callback?:
|
|
497
|
+
alterTablespace(name: string, filePath: string, callback?: Callback): this {
|
|
468
498
|
const sql = `ALTER TABLESPACE ${name} SET FILE TO '${filePath}'`;
|
|
469
499
|
return this.execute(sql, [], callback);
|
|
470
500
|
}
|
|
@@ -477,7 +507,7 @@ class Database extends Events.EventEmitter {
|
|
|
477
507
|
* @param {function} [callback] - Asynchronous completion callback.
|
|
478
508
|
* @returns {Database}
|
|
479
509
|
*/
|
|
480
|
-
dropTablespace(name: string, callback?:
|
|
510
|
+
dropTablespace(name: string, callback?: Callback): this {
|
|
481
511
|
const sql = `DROP TABLESPACE ${name}`;
|
|
482
512
|
return this.execute(sql, [], callback);
|
|
483
513
|
}
|
|
@@ -492,7 +522,7 @@ class Database extends Events.EventEmitter {
|
|
|
492
522
|
* @param {function} [callback] - Asynchronous completion callback.
|
|
493
523
|
* @returns {Database}
|
|
494
524
|
*/
|
|
495
|
-
createSchema(schemaName: string, tablespaceName?: string |
|
|
525
|
+
createSchema(schemaName: string, tablespaceName?: string | Callback, callback?: Callback): this {
|
|
496
526
|
if (typeof tablespaceName === 'function') {
|
|
497
527
|
callback = tablespaceName;
|
|
498
528
|
tablespaceName = undefined;
|
|
@@ -511,22 +541,24 @@ class Database extends Events.EventEmitter {
|
|
|
511
541
|
* callback API — the promises resolve with the rows alone.
|
|
512
542
|
*/
|
|
513
543
|
|
|
514
|
-
queryAsync(query: string, params?:
|
|
544
|
+
queryAsync(query: string, params?: QueryParams, options?: InternalQueryOptions): Promise<any[]> {
|
|
515
545
|
var self = this;
|
|
516
546
|
return fromCallback(function(cb) { self.query(query, params, cb, options); });
|
|
517
547
|
}
|
|
518
548
|
|
|
519
|
-
executeAsync(query: string, params?:
|
|
549
|
+
executeAsync(query: string, params?: QueryParams, options?: InternalQueryOptions): Promise<any[]> {
|
|
520
550
|
var self = this;
|
|
521
551
|
return fromCallback(function(cb) { self.execute(query, params, cb, options); });
|
|
522
552
|
}
|
|
523
553
|
|
|
524
|
-
executeBatchAsync(query: string, rows:
|
|
554
|
+
executeBatchAsync(query: string, rows: QueryParams[], options?: BatchOptions): Promise<BatchResult> {
|
|
525
555
|
var self = this;
|
|
526
556
|
return fromCallback(function(cb) { self.executeBatch(query, rows, cb, options); });
|
|
527
557
|
}
|
|
528
558
|
|
|
529
|
-
|
|
559
|
+
/** `on` may hold the options when the params argument is the row callback
|
|
560
|
+
* (public overload: sequentiallyAsync(query, rowCallback, options)). */
|
|
561
|
+
sequentiallyAsync(query: string, params?: any, on?: any, options?: InternalQueryOptions | boolean): Promise<void> {
|
|
530
562
|
if (params instanceof Function) {
|
|
531
563
|
options = on;
|
|
532
564
|
on = params;
|
|
@@ -536,16 +568,16 @@ class Database extends Events.EventEmitter {
|
|
|
536
568
|
return fromCallback(function(cb) { self.sequentially(query, params, on, cb, options); });
|
|
537
569
|
}
|
|
538
570
|
|
|
539
|
-
transactionAsync(options?:
|
|
571
|
+
transactionAsync(options?: TransactionOptions | Isolation): Promise<Transaction> {
|
|
540
572
|
var self = this;
|
|
541
573
|
return fromCallback(function(cb) { self.startTransaction(options, cb); });
|
|
542
574
|
}
|
|
543
575
|
|
|
544
|
-
startTransactionAsync(options?:
|
|
576
|
+
startTransactionAsync(options?: TransactionOptions | Isolation): Promise<Transaction> {
|
|
545
577
|
return this.transactionAsync(options);
|
|
546
578
|
}
|
|
547
579
|
|
|
548
|
-
newStatementAsync(query: string): Promise<
|
|
580
|
+
newStatementAsync(query: string): Promise<Statement> {
|
|
549
581
|
var self = this;
|
|
550
582
|
return fromCallback(function(cb) { self.newStatement(query, cb); });
|
|
551
583
|
}
|
|
@@ -560,7 +592,7 @@ class Database extends Events.EventEmitter {
|
|
|
560
592
|
return fromCallback(function(cb) { self.drop(cb); });
|
|
561
593
|
}
|
|
562
594
|
|
|
563
|
-
attachEventAsync(): Promise<
|
|
595
|
+
attachEventAsync(): Promise<FbEventManager> {
|
|
564
596
|
var self = this;
|
|
565
597
|
return fromCallback(function(cb) { self.attachEvent(cb); });
|
|
566
598
|
}
|
|
@@ -575,7 +607,7 @@ class Database extends Events.EventEmitter {
|
|
|
575
607
|
* resolves, rolls back when it rejects (the original error is rethrown,
|
|
576
608
|
* even if the rollback itself fails).
|
|
577
609
|
*/
|
|
578
|
-
async withTransaction<T>(work: (transaction:
|
|
610
|
+
async withTransaction<T>(work: (transaction: Transaction) => Promise<T> | T, options?: TransactionOptions | Isolation): Promise<T> {
|
|
579
611
|
const transaction = await this.transactionAsync(options);
|
|
580
612
|
try {
|
|
581
613
|
const result = await work(transaction);
|
|
@@ -22,8 +22,8 @@ class EventConnection {
|
|
|
22
22
|
this._isOpened = false;
|
|
23
23
|
this._socket = net.createConnection(port, host);
|
|
24
24
|
this._bind_events(host, port, callback);
|
|
25
|
-
this.error;
|
|
26
|
-
this.eventcallback;
|
|
25
|
+
this.error = null;
|
|
26
|
+
this.eventcallback = null;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
_bind_events(host: string, port: number, callback?: () => void): void {
|
|
@@ -60,9 +60,10 @@ class EventConnection {
|
|
|
60
60
|
xdr.buffer = buf;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
var op_pos = xdr.pos;
|
|
64
|
+
|
|
63
65
|
try {
|
|
64
66
|
|
|
65
|
-
var op_pos = xdr.pos;
|
|
66
67
|
var tmp_event: Record<string, number>;
|
|
67
68
|
while (xdr.pos < xdr.buffer.length) {
|
|
68
69
|
do {
|
|
@@ -72,10 +73,12 @@ class EventConnection {
|
|
|
72
73
|
switch (r) {
|
|
73
74
|
case Const.op_event:
|
|
74
75
|
xdr.readInt(); // db handle
|
|
75
|
-
|
|
76
|
+
// op_event always carries a payload; readArray only
|
|
77
|
+
// returns undefined for zero-length arrays
|
|
78
|
+
buf = xdr.readArray()!;
|
|
76
79
|
// first byte is always set to 1
|
|
77
80
|
tmp_event = {};
|
|
78
|
-
var lst_event = [];
|
|
81
|
+
var lst_event: { name: string; count: number }[] = [];
|
|
79
82
|
var eventname = '';
|
|
80
83
|
var eventcount = 0;
|
|
81
84
|
var pos = 1;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/***************************************
|
|
2
|
+
*
|
|
3
|
+
* queryStream — object-mode Readable over sequentially()
|
|
4
|
+
*
|
|
5
|
+
***************************************/
|
|
6
|
+
|
|
7
|
+
import { Readable } from 'stream';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Build an object-mode Readable that emits one row per chunk, implemented
|
|
11
|
+
* on top of `target.sequentially()`'s next()-based backpressure: fetching
|
|
12
|
+
* pauses whenever the stream's internal buffer is full and resumes when
|
|
13
|
+
* the consumer drains it. Shared by Database.queryStream and
|
|
14
|
+
* Transaction.queryStream.
|
|
15
|
+
*
|
|
16
|
+
* Destroying the stream early (including a pipeline() teardown) aborts the
|
|
17
|
+
* row loop, which releases the statement server-side.
|
|
18
|
+
*/
|
|
19
|
+
function makeQueryStream(target: any, query: string, params?: any, options?: any): Readable {
|
|
20
|
+
options = options || {};
|
|
21
|
+
|
|
22
|
+
const streamOptions: any = { objectMode: true };
|
|
23
|
+
if (options.highWaterMark !== undefined) {
|
|
24
|
+
streamOptions.highWaterMark = options.highWaterMark;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// forwarded to sequentially(); these keys would break its plumbing
|
|
28
|
+
const queryOptions = { ...options };
|
|
29
|
+
delete queryOptions.on;
|
|
30
|
+
delete queryOptions.asStream;
|
|
31
|
+
delete queryOptions.highWaterMark;
|
|
32
|
+
|
|
33
|
+
// sentinel used to stop the row loop on early destroy; recognized by
|
|
34
|
+
// identity in the completion callback and never surfaced to the user
|
|
35
|
+
const abortError = new Error('queryStream destroyed');
|
|
36
|
+
|
|
37
|
+
let pendingNext: ((err?: any) => void) | null = null;
|
|
38
|
+
const resume = (err?: any) => {
|
|
39
|
+
if (pendingNext) {
|
|
40
|
+
const next = pendingNext;
|
|
41
|
+
pendingNext = null;
|
|
42
|
+
next(err);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const stream = new Readable({
|
|
47
|
+
...streamOptions,
|
|
48
|
+
read() {
|
|
49
|
+
resume();
|
|
50
|
+
},
|
|
51
|
+
destroy(err: any, cb: (err?: any) => void) {
|
|
52
|
+
// if the row loop is paused waiting for us, abort it so the
|
|
53
|
+
// statement is released instead of leaking mid-fetch
|
|
54
|
+
resume(abortError);
|
|
55
|
+
cb(err);
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
target.sequentially(query, params, function (row: any, _index: number, next: (err?: any) => void) {
|
|
60
|
+
if (stream.destroyed) {
|
|
61
|
+
next(abortError);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (stream.push(row)) {
|
|
65
|
+
next();
|
|
66
|
+
} else {
|
|
67
|
+
pendingNext = next;
|
|
68
|
+
}
|
|
69
|
+
}, function (err: any) {
|
|
70
|
+
if (err && err !== abortError) {
|
|
71
|
+
stream.destroy(err);
|
|
72
|
+
} else if (!stream.destroyed) {
|
|
73
|
+
stream.push(null);
|
|
74
|
+
}
|
|
75
|
+
}, queryOptions);
|
|
76
|
+
|
|
77
|
+
return stream;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export = makeQueryStream;
|
package/src/wire/serialize.ts
CHANGED
|
@@ -421,6 +421,28 @@ export class XdrReader {
|
|
|
421
421
|
buffer: Buffer;
|
|
422
422
|
pos: number;
|
|
423
423
|
|
|
424
|
+
// Row-decode scratch state used by decodeResponse (connection.ts) while
|
|
425
|
+
// decoding op_fetch_response / op_sql_response. Only meaningful within a
|
|
426
|
+
// single decode call: incomplete packets are re-decoded from scratch on
|
|
427
|
+
// a fresh XdrReader, and decodeResponse clears these at branch entry so
|
|
428
|
+
// nothing leaks between packets sharing a data event (issue #341).
|
|
429
|
+
/** opcode carried over for a resumed decode (vestigial, see connection.ts) */
|
|
430
|
+
r?: number | null;
|
|
431
|
+
/** partial fetch-op flag (vestigial) */
|
|
432
|
+
fop?: boolean;
|
|
433
|
+
/** fetch status of the current row batch (100 = end of cursor) */
|
|
434
|
+
fstatus?: number;
|
|
435
|
+
/** rows remaining in the current packet */
|
|
436
|
+
fcount?: number;
|
|
437
|
+
/** column index the row decode stopped at */
|
|
438
|
+
fcolumn?: number;
|
|
439
|
+
/** row currently being decoded (object or array) */
|
|
440
|
+
frow?: any;
|
|
441
|
+
/** rows decoded so far in this call */
|
|
442
|
+
frows?: any[];
|
|
443
|
+
/** cached object-row keys (column aliases) */
|
|
444
|
+
fcols?: string[];
|
|
445
|
+
|
|
424
446
|
constructor(buffer: Buffer) {
|
|
425
447
|
this.buffer = buffer;
|
|
426
448
|
this.pos = 0;
|
|
@@ -506,6 +528,13 @@ export class XdrReader {
|
|
|
506
528
|
var len = this.readInt();
|
|
507
529
|
if (!len)
|
|
508
530
|
return;
|
|
531
|
+
// Firebird 2.5 sign-extends XDR opaque lengths above 32767: a
|
|
532
|
+
// 32768-byte array arrives as length 0xFFFF8000. A negative length
|
|
533
|
+
// is never valid, so recover the real length from the low 16 bits
|
|
534
|
+
// instead of corrupting the read position (issue #312 — hang when
|
|
535
|
+
// preparing a statement with very many parameters on FB 2.5).
|
|
536
|
+
if (len < 0)
|
|
537
|
+
len &= 0xFFFF;
|
|
509
538
|
var r = this.buffer.slice(this.pos, this.pos + len);
|
|
510
539
|
this.pos += align(len);
|
|
511
540
|
return r;
|