node-firebird 2.8.1 → 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.
Files changed (53) hide show
  1. package/README.md +268 -7
  2. package/lib/index.d.ts +17 -9
  3. package/lib/index.js +42 -3
  4. package/lib/named-params.d.ts +42 -0
  5. package/lib/named-params.js +133 -0
  6. package/lib/pool.js +1 -1
  7. package/lib/srp.d.ts +3 -3
  8. package/lib/types.d.ts +185 -25
  9. package/lib/uri.d.ts +57 -0
  10. package/lib/uri.js +193 -0
  11. package/lib/wire/connection.d.ts +92 -59
  12. package/lib/wire/connection.js +286 -55
  13. package/lib/wire/const.d.ts +9 -1
  14. package/lib/wire/const.js +21 -9
  15. package/lib/wire/database.d.ts +51 -26
  16. package/lib/wire/database.js +26 -8
  17. package/lib/wire/eventConnection.js +5 -3
  18. package/lib/wire/query-stream.d.ts +18 -0
  19. package/lib/wire/query-stream.js +73 -0
  20. package/lib/wire/serialize.d.ts +18 -2
  21. package/lib/wire/serialize.js +7 -0
  22. package/lib/wire/service.d.ts +42 -0
  23. package/lib/wire/service.js +145 -0
  24. package/lib/wire/socket.d.ts +3 -1
  25. package/lib/wire/socket.js +5 -2
  26. package/lib/wire/statement.d.ts +40 -20
  27. package/lib/wire/statement.js +26 -6
  28. package/lib/wire/transaction.d.ts +32 -18
  29. package/lib/wire/transaction.js +50 -8
  30. package/lib/wire/wire-types.d.ts +116 -0
  31. package/lib/wire/wire-types.js +10 -0
  32. package/lib/wire/xsqlvar.d.ts +18 -18
  33. package/package.json +1 -1
  34. package/src/index.ts +54 -15
  35. package/src/messages.ts +1 -1
  36. package/src/named-params.ts +145 -0
  37. package/src/pool.ts +1 -1
  38. package/src/srp.ts +6 -6
  39. package/src/types.ts +183 -25
  40. package/src/unix-crypt.ts +9 -9
  41. package/src/uri.ts +204 -0
  42. package/src/wire/connection.ts +481 -234
  43. package/src/wire/const.ts +21 -9
  44. package/src/wire/database.ts +75 -43
  45. package/src/wire/eventConnection.ts +8 -5
  46. package/src/wire/query-stream.ts +80 -0
  47. package/src/wire/serialize.ts +29 -0
  48. package/src/wire/service.ts +188 -6
  49. package/src/wire/socket.ts +17 -8
  50. package/src/wire/statement.ts +68 -31
  51. package/src/wire/transaction.ts +85 -33
  52. package/src/wire/wire-types.ts +127 -0
  53. package/src/wire/xsqlvar.ts +9 -7
@@ -1,6 +1,13 @@
1
- import { doCallback, doError, fromCallback } from '../callback';
1
+ import { doCallback, doError, fromCallback, type Callback, type SimpleCallback } from '../callback';
2
+ import { parseNamedPlaceholders } from '../named-params';
2
3
  import { noop } from '../utils';
3
4
  import Const from './const';
5
+ import makeQueryStream from './query-stream';
6
+ import type Connection from './connection';
7
+ import type Database from './database';
8
+ import type Statement from './statement';
9
+ import type { BatchCb, StatementCb, InternalQueryOptions } from './wire-types';
10
+ import type { BatchOptions, BatchResult, QueryOptions, QueryParams, QueryStreamOptions, SequentialCallback } from '../types';
4
11
 
5
12
  /***************************************
6
13
  *
@@ -25,7 +32,7 @@ function abortError(signal: any): Error {
25
32
  * GDSCode.CANCELLED). Returns the wrapped callback that detaches the
26
33
  * listener once the operation settles.
27
34
  */
28
- function hookAbortSignal(connection: any, signal: any, callback: any): any {
35
+ function hookAbortSignal(connection: Connection, signal: AbortSignal, callback: any): any {
29
36
  var settled = false;
30
37
  var onAbort = function() {
31
38
  if (!settled)
@@ -41,29 +48,58 @@ function hookAbortSignal(connection: any, signal: any, callback: any): any {
41
48
  }
42
49
 
43
50
  class Transaction {
44
- connection: any;
45
- db: any;
46
- handle: number;
47
- [key: string]: any;
51
+ connection: Connection;
52
+ db: Database;
53
+ // populated externally from the op_transaction response
54
+ handle!: number;
48
55
 
49
- constructor(connection: any) {
56
+ constructor(connection: Connection) {
50
57
  this.connection = connection;
51
58
  this.db = connection.db;
52
59
  }
53
60
 
54
- newStatement(query: string, callback: (err: any, statement?: any) => void): void {
61
+ /** Per-call options.namedPlaceholders overrides the connection option. */
62
+ private namedPlaceholdersEnabled(options?: InternalQueryOptions): boolean {
63
+ if (options && options.namedPlaceholders !== undefined)
64
+ return !!options.namedPlaceholders;
65
+ return !!(this.connection.options && this.connection.options.namedPlaceholders);
66
+ }
67
+
68
+ newStatement(query: string, callback: StatementCb, options?: InternalQueryOptions): void {
55
69
  var cnx = this.connection;
56
70
  var self = this;
57
- var query_cache = cnx.getCachedQuery(query);
71
+ // the public strict callback shape and the internal optional-args
72
+ // shape only differ in optionality; treat it as the internal one
73
+ var cb = callback as Callback<Statement>;
74
+
75
+ // With namedPlaceholders on, prepare the positional rewrite and
76
+ // remember the name order on the statement so statement.execute can
77
+ // accept a values-by-name object. The rewritten SQL is the cache key.
78
+ var names: string[] | null = null;
79
+ if (this.namedPlaceholdersEnabled(options)) {
80
+ var parsed = parseNamedPlaceholders(query);
81
+ if (parsed.names) {
82
+ query = parsed.sql;
83
+ names = parsed.names;
84
+ }
85
+ }
86
+
87
+ var deliver = function(err: any, statement?: Statement) {
88
+ if (statement)
89
+ statement.namedParams = names;
90
+ cb(err, statement);
91
+ };
92
+
93
+ var query_cache = cnx.takeCachedStatement(query);
58
94
 
59
95
  if (query_cache) {
60
- callback(null, query_cache);
96
+ deliver(null, query_cache);
61
97
  } else {
62
- cnx.prepare(self, query, false, callback);
98
+ cnx.prepare(self, query, false, deliver);
63
99
  }
64
100
  }
65
101
 
66
- execute(query: string, params?: any, callback?: any, options?: any): void {
102
+ execute(query: string, params?: QueryParams | Callback, callback?: any, options?: InternalQueryOptions): void {
67
103
  if (params instanceof Function) {
68
104
  options = callback;
69
105
  callback = params;
@@ -80,15 +116,19 @@ class Transaction {
80
116
  }
81
117
 
82
118
  var self = this;
83
- this.newStatement(query, function(err: any, statement: any) {
119
+ this.newStatement(query, function(err: any, statement?: Statement) {
84
120
 
85
- if (err) {
121
+ if (err || !statement) {
86
122
  doError(err, callback);
87
123
  return;
88
124
  }
89
125
 
90
126
  function dropError(err: any) {
91
- statement.release();
127
+ // do not put a statement that just failed back into the cache
128
+ // (statement is guaranteed by the guard above; hoisting keeps
129
+ // the narrowing from reaching this function declaration)
130
+ statement!._failed = true;
131
+ statement!.release();
92
132
  doCallback(err, callback);
93
133
  }
94
134
 
@@ -148,10 +188,10 @@ class Transaction {
148
188
  }
149
189
 
150
190
  }, options);
151
- });
191
+ }, options);
152
192
  }
153
193
 
154
- sequentially(query: string, params?: any, on?: any, callback?: any, options: any = {}): this {
194
+ sequentially(query: string, params?: any, on?: any, callback?: any, options: InternalQueryOptions | boolean = {}): this {
155
195
  if (params instanceof Function) {
156
196
  options = callback;
157
197
  callback = on;
@@ -169,7 +209,7 @@ class Transaction {
169
209
  }
170
210
 
171
211
  var self = this;
172
- var _on = function(row: any, i: number, meta: any, next: (err?: any) => void) {
212
+ var _on = function(row: any, i: number, meta: any[], next: (err?: any) => void) {
173
213
  var done = false;
174
214
  var finish = function(err?: any) {
175
215
  if (done) {
@@ -215,7 +255,17 @@ class Transaction {
215
255
  return self;
216
256
  }
217
257
 
218
- query(query: string, params?: any, callback?: any, options: any = {}): void {
258
+ /**
259
+ * Run `query` inside this transaction and return an object-mode
260
+ * Readable emitting one row per chunk, with real backpressure (see
261
+ * Database.queryStream). The transaction is NOT committed when the
262
+ * stream ends — commit or roll back yourself.
263
+ */
264
+ queryStream(query: string, params?: QueryParams, options?: QueryStreamOptions) {
265
+ return makeQueryStream(this, query, params, options);
266
+ }
267
+
268
+ query(query: string, params?: QueryParams | Callback, callback?: any, options: InternalQueryOptions = {}): void {
219
269
  if (params instanceof Function) {
220
270
  callback = params;
221
271
  params = undefined;
@@ -242,56 +292,58 @@ class Transaction {
242
292
  * commit or roll back yourself (or use db.executeBatch for
243
293
  * all-or-nothing semantics).
244
294
  */
245
- executeBatch(query: string, rows: any[][], callback?: any, options?: any): void {
295
+ executeBatch(query: string, rows: QueryParams[], callback?: BatchCb, options?: BatchOptions & QueryOptions): void {
246
296
  var self = this;
247
- this.newStatement(query, function(err: any, statement: any) {
248
- if (err) {
297
+ this.newStatement(query, function(err: any, statement?: Statement) {
298
+ if (err || !statement) {
249
299
  doError(err, callback);
250
300
  return;
251
301
  }
252
302
 
253
- statement.executeBatch(self, rows, function(err: any, result: any) {
303
+ statement.executeBatch(self, rows, function(err: any, result: BatchResult) {
304
+ if (err)
305
+ statement._failed = true;
254
306
  statement.release();
255
307
  if (callback)
256
308
  callback(err, result);
257
309
  }, options);
258
- });
310
+ }, options);
259
311
  }
260
312
 
261
- executeBatchAsync(query: string, rows: any[][], options?: any): Promise<any> {
313
+ executeBatchAsync(query: string, rows: QueryParams[], options?: BatchOptions & QueryOptions): Promise<BatchResult> {
262
314
  var self = this;
263
315
  return fromCallback(function(cb) { self.executeBatch(query, rows, cb, options); });
264
316
  }
265
317
 
266
- commit(callback?: (err?: any) => void): void {
318
+ commit(callback?: SimpleCallback): void {
267
319
  this.connection.commit(this, callback);
268
320
  }
269
321
 
270
- rollback(callback?: (err?: any) => void): void {
322
+ rollback(callback?: SimpleCallback): void {
271
323
  this.connection.rollback(this, callback);
272
324
  }
273
325
 
274
- commitRetaining(callback?: (err?: any) => void): void {
326
+ commitRetaining(callback?: SimpleCallback): void {
275
327
  this.connection.commitRetaining(this, callback);
276
328
  }
277
329
 
278
- rollbackRetaining(callback?: (err?: any) => void): void {
330
+ rollbackRetaining(callback?: SimpleCallback): void {
279
331
  this.connection.rollbackRetaining(this, callback);
280
332
  }
281
333
 
282
334
  /* Promise / async-await API — wrappers over the callback methods above. */
283
335
 
284
- queryAsync(query: string, params?: any, options?: any): Promise<any[]> {
336
+ queryAsync(query: string, params?: QueryParams, options?: InternalQueryOptions): Promise<any[]> {
285
337
  var self = this;
286
338
  return fromCallback(function(cb) { self.query(query, params, cb, options); });
287
339
  }
288
340
 
289
- executeAsync(query: string, params?: any, options?: any): Promise<any[]> {
341
+ executeAsync(query: string, params?: QueryParams, options?: InternalQueryOptions): Promise<any[]> {
290
342
  var self = this;
291
343
  return fromCallback(function(cb) { self.execute(query, params, cb, options); });
292
344
  }
293
345
 
294
- sequentiallyAsync(query: string, params?: any, on?: any, options?: any): Promise<void> {
346
+ sequentiallyAsync(query: string, params?: any, on?: SequentialCallback, options?: InternalQueryOptions | boolean): Promise<void> {
295
347
  if (params instanceof Function) {
296
348
  options = on;
297
349
  on = params;
@@ -301,7 +353,7 @@ class Transaction {
301
353
  return fromCallback(function(cb) { self.sequentially(query, params, on, cb, options); });
302
354
  }
303
355
 
304
- newStatementAsync(query: string): Promise<any> {
356
+ newStatementAsync(query: string): Promise<Statement> {
305
357
  var self = this;
306
358
  return fromCallback(function(cb) { self.newStatement(query, cb); });
307
359
  }
@@ -0,0 +1,127 @@
1
+ /***************************************
2
+ *
3
+ * Internal wire-protocol types (type-only module)
4
+ *
5
+ * Shared vocabulary for the wire core (connection/statement/transaction/
6
+ * database). Nothing here exists at runtime.
7
+ *
8
+ ***************************************/
9
+
10
+ import type { Callback, FbStatusItem } from '../callback';
11
+ import type Statement from './statement';
12
+ import type { BatchResult, Options, QueryOptions, Statement as PublicStatement } from '../types';
13
+
14
+ /**
15
+ * One entry of the connection's response queue (`connection._queue`).
16
+ * The function itself is the user/driver callback; the extra properties
17
+ * steer decodeResponse:
18
+ *
19
+ * - `response` — pre-allocated object the op_response decode fills in
20
+ * (a Statement, Transaction, or plain response object).
21
+ * - `statement` — statement whose `output` describes the rows of an
22
+ * op_fetch_response / op_sql_response.
23
+ * - `lazy_count`— number of chained lazy op_responses this entry consumes
24
+ * (ptype_lazy_send batches e.g. allocate+prepare).
25
+ *
26
+ * Deferred ops (op_free_statement, op_close_blob, ...) push `undefined`
27
+ * placeholders so every server response still pairs with one entry.
28
+ */
29
+ export interface QueueCallback {
30
+ (err?: any, obj?: any): void;
31
+ response?: any;
32
+ statement?: Statement;
33
+ lazy_count?: number;
34
+ }
35
+
36
+ /** A queue entry: a callback, or a placeholder for a deferred op. */
37
+ export type QueueEntry = QueueCallback | undefined;
38
+
39
+ /** XDR quad — 64-bit value as two 32-bit halves (blob ids, object ids). */
40
+ export interface Quad {
41
+ high: number;
42
+ low: number;
43
+ }
44
+
45
+ /**
46
+ * Decoded op_response packet (see parseOpResponse): object handle, object
47
+ * id, optional info buffer and, on failure, the status vector. Statement /
48
+ * Transaction responses are these fields merged onto the pre-allocated
49
+ * object from QueueCallback.response.
50
+ */
51
+ export interface WireResponse {
52
+ handle?: number;
53
+ oid?: Quad;
54
+ buffer?: Buffer;
55
+ status?: FbStatusItem[];
56
+ /** isc_arg_warning entries — attached to a SUCCESSFUL response */
57
+ warnings?: FbStatusItem[];
58
+ sqlcode?: number;
59
+ message?: string;
60
+ }
61
+
62
+ /** Result of decoding op_fetch_response / op_sql_response row data. */
63
+ export interface FetchResult {
64
+ data: any[];
65
+ /** true when the cursor is exhausted (fetch status 100 / singleton). */
66
+ fetched: boolean;
67
+ /** pending blobAsText fetches to resolve before delivering rows. */
68
+ arrBlob?: any[];
69
+ }
70
+
71
+ /**
72
+ * Protocol negotiation result decoded from op_accept / op_cond_accept /
73
+ * op_accept_data, plus the auth/crypt state accumulated during the
74
+ * handshake (op_cont_auth rounds, wire-crypt keys).
75
+ */
76
+ export interface AcceptPacket {
77
+ protocolVersion: number;
78
+ protocolArchitecture: number;
79
+ protocolMinimumType: number;
80
+ compress: boolean;
81
+ pluginName: string;
82
+ authData: any;
83
+ sessionKey?: any;
84
+ [key: string]: any;
85
+ }
86
+
87
+ /**
88
+ * Query options as the wire core sees them: the public QueryOptions plus
89
+ * the internal row-delivery flags set by the Database/Transaction helpers
90
+ * (query / sequentially / queryStream).
91
+ */
92
+ export type InternalQueryOptions = QueryOptions & {
93
+ /** deliver rows as objects keyed by column alias */
94
+ asObject?: boolean;
95
+ /** deliver rows one by one (row events / `on` delegate) instead of accumulating */
96
+ asStream?: boolean;
97
+ /** per-row delegate installed by sequentially() */
98
+ on?: (row: any, index: number, meta: any[], next: (err?: any) => void) => void;
99
+ [key: string]: any;
100
+ };
101
+
102
+ /**
103
+ * newStatement callback: the internal optional-args shape, or the public
104
+ * strict shape (non-optional statement) declared in types.ts.
105
+ */
106
+ export type StatementCb = Callback<Statement> | ((err: Error | null, statement: PublicStatement) => void);
107
+
108
+ /**
109
+ * executeBatch callback: the internal optional-args shape, or the public
110
+ * strict shape (non-optional result) declared in types.ts.
111
+ */
112
+ export type BatchCb = Callback<BatchResult> | ((err: any, result: BatchResult) => void);
113
+
114
+ /**
115
+ * Connection options as the wire core sees them: the public Options plus
116
+ * internal flags set by the driver itself.
117
+ */
118
+ export type InternalOptions = Options & {
119
+ /** set by the pool so detach() returns the connection instead */
120
+ isPool?: boolean;
121
+ /** override path of the firebird.msg error-message file */
122
+ messageFile?: string;
123
+ /** legacy statement-cache flags (mapped onto statementCacheSize) */
124
+ cacheQuery?: boolean;
125
+ maxCachedQuery?: number;
126
+ [key: string]: any;
127
+ };
@@ -26,7 +26,7 @@ const
26
26
  * Commonly used Firebird charsets not listed here fall back to the
27
27
  * connection-level DEFAULT_ENCODING (typically 'utf8').
28
28
  */
29
- const FirebirdToNodeEncoding = Object.freeze({
29
+ const FirebirdToNodeEncoding: Readonly<Record<string, string>> = Object.freeze({
30
30
  UTF8: 'utf8',
31
31
  UNICODE_FSS: 'utf8',
32
32
  WIN1252: 'latin1',
@@ -36,7 +36,7 @@ const FirebirdToNodeEncoding = Object.freeze({
36
36
  NONE: 'latin1', // unspecified charset – treat as binary-safe latin1
37
37
  });
38
38
 
39
- const FirebirdCharsetWidths = {
39
+ const FirebirdCharsetWidths: Record<string, number> = {
40
40
  'UTF8': 4,
41
41
  'UNICODE_FSS': 3,
42
42
  'SJIS': 2,
@@ -71,11 +71,13 @@ function resolveTextEncoding(options?: any): BufferEncoding {
71
71
  * describe response before decode()/calcBlr() are called.
72
72
  */
73
73
  export abstract class SQLVarBase {
74
- type: number;
75
- subType: number;
76
- scale: number;
77
- length: number;
78
- nullable: boolean;
74
+ // populated externally (see the doc comment above), hence the definite
75
+ // assignment assertions
76
+ type!: number;
77
+ subType!: number;
78
+ scale!: number;
79
+ length!: number;
80
+ nullable!: boolean;
79
81
  field?: string;
80
82
  relation?: string;
81
83
  relationSchema?: string;