firebird-wasm 0.9.0 → 0.10.1

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 (75) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/dist/.tsbuildinfo.build +1 -1
  3. package/dist/browser/engine-transport.d.ts +19 -0
  4. package/dist/browser/engine-transport.d.ts.map +1 -1
  5. package/dist/browser/engine-transport.js +67 -0
  6. package/dist/browser/engine-transport.js.map +1 -1
  7. package/dist/browser/firebird-browser.d.ts +44 -1
  8. package/dist/browser/firebird-browser.d.ts.map +1 -1
  9. package/dist/browser/firebird-browser.js +123 -0
  10. package/dist/browser/firebird-browser.js.map +1 -1
  11. package/dist/browser/index.d.ts +1 -1
  12. package/dist/browser/index.d.ts.map +1 -1
  13. package/dist/browser/opfs-fs.d.ts.map +1 -1
  14. package/dist/browser/opfs-fs.js +18 -7
  15. package/dist/browser/opfs-fs.js.map +1 -1
  16. package/dist/browser/shared-transport.d.ts +3 -0
  17. package/dist/browser/shared-transport.d.ts.map +1 -1
  18. package/dist/browser/shared-transport.js +9 -0
  19. package/dist/browser/shared-transport.js.map +1 -1
  20. package/dist/browser/worker-protocol.d.ts +1 -1
  21. package/dist/browser/worker-protocol.d.ts.map +1 -1
  22. package/dist/browser/worker-transport.d.ts +3 -0
  23. package/dist/browser/worker-transport.d.ts.map +1 -1
  24. package/dist/browser/worker-transport.js +9 -0
  25. package/dist/browser/worker-transport.js.map +1 -1
  26. package/dist/drizzle/index.d.ts +170 -0
  27. package/dist/drizzle/index.d.ts.map +1 -0
  28. package/dist/drizzle/index.js +627 -0
  29. package/dist/drizzle/index.js.map +1 -0
  30. package/dist/electric/apply.d.ts +1 -0
  31. package/dist/electric/apply.d.ts.map +1 -1
  32. package/dist/electric/apply.js +28 -8
  33. package/dist/electric/apply.js.map +1 -1
  34. package/dist/electric/index.js +6 -1
  35. package/dist/electric/index.js.map +1 -1
  36. package/dist/electric/values.d.ts.map +1 -1
  37. package/dist/electric/values.js +5 -2
  38. package/dist/electric/values.js.map +1 -1
  39. package/dist/electric-server/catalog.d.ts.map +1 -1
  40. package/dist/electric-server/catalog.js +3 -2
  41. package/dist/electric-server/catalog.js.map +1 -1
  42. package/dist/electric-server/index.d.ts +19 -0
  43. package/dist/electric-server/index.d.ts.map +1 -1
  44. package/dist/electric-server/index.js +147 -14
  45. package/dist/electric-server/index.js.map +1 -1
  46. package/dist/firebird.d.ts +48 -9
  47. package/dist/firebird.d.ts.map +1 -1
  48. package/dist/firebird.js +927 -60
  49. package/dist/firebird.js.map +1 -1
  50. package/dist/index.d.ts +4 -1
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +7 -1
  53. package/dist/index.js.map +1 -1
  54. package/dist/kysely/index.d.ts +197 -0
  55. package/dist/kysely/index.d.ts.map +1 -0
  56. package/dist/kysely/index.js +777 -0
  57. package/dist/kysely/index.js.map +1 -0
  58. package/dist/sql-tag.d.ts +5 -16
  59. package/dist/sql-tag.d.ts.map +1 -1
  60. package/dist/sql-tag.js +15 -0
  61. package/dist/sql-tag.js.map +1 -1
  62. package/dist/types.d.ts +24 -3
  63. package/dist/types.d.ts.map +1 -1
  64. package/dist/version.d.ts +1 -1
  65. package/dist/version.d.ts.map +1 -1
  66. package/dist/version.js +1 -1
  67. package/dist/version.js.map +1 -1
  68. package/dist/wasm/firebird-embedded-st.js +1 -1
  69. package/dist/wasm/firebird-embedded-st.wasm +0 -0
  70. package/dist/wasm/firebird-embedded.js +1 -1
  71. package/dist/wasm/firebird-embedded.wasm +0 -0
  72. package/dist/wasm-loader.d.ts +16 -0
  73. package/dist/wasm-loader.d.ts.map +1 -1
  74. package/dist/wasm-loader.js.map +1 -1
  75. package/package.json +21 -3
@@ -0,0 +1,777 @@
1
+ "use strict";
2
+ /**
3
+ * firebird-wasm/kysely – a Kysely dialect for `FirebirdBrowser` and `FirebirdLite`.
4
+ *
5
+ * ```ts
6
+ * import { Kysely } from 'kysely';
7
+ * import type { Generated } from 'kysely';
8
+ * import { FirebirdDialect, createKysely } from 'firebird-wasm/kysely';
9
+ *
10
+ * interface Database {
11
+ * items: {
12
+ * id: Generated<number>;
13
+ * title: string;
14
+ * done: boolean;
15
+ * };
16
+ * }
17
+ *
18
+ * const db = createKysely<Database>(fb);
19
+ * // or: new Kysely<Database>({ dialect: new FirebirdDialect({ database: fb }) });
20
+ *
21
+ * const rows = await db
22
+ * .selectFrom('items')
23
+ * .select(['id', 'title', 'done'])
24
+ * .where('done', '=', false)
25
+ * .orderBy('id')
26
+ * .offset(10)
27
+ * .limit(5)
28
+ * .execute();
29
+ * ```
30
+ *
31
+ * Compiles to Firebird 3+ SQL:
32
+ * - `?` positional parameter placeholders;
33
+ * - `OFFSET ? ROWS FETCH NEXT ? ROWS ONLY` pagination (and `ROWS ?` on `UPDATE`/`DELETE`);
34
+ * - `INSERT / UPDATE / DELETE … RETURNING`;
35
+ * - `UPDATE OR INSERT INTO … MATCHING (…)` on `.onConflict(oc => oc.column(…).doUpdateSet(…))`;
36
+ * - multi-row `INSERT INTO … SELECT … FROM RDB$DATABASE UNION ALL …`;
37
+ * - `GENERATED BY DEFAULT AS IDENTITY` for `autoIncrement` / `serial` / `bigserial`;
38
+ * - bijective identifier folding (`items` ↔ `"ITEMS"`, while `"camelCase"` stays `"camelCase"`),
39
+ * so lowercase Kysely table/column types work out of the box against unquoted Firebird DDL.
40
+ */
41
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
42
+ if (kind === "m") throw new TypeError("Private method is not writable");
43
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
44
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
45
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
46
+ };
47
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
48
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
49
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
50
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
51
+ };
52
+ var _FirebirdDialect_config, _FirebirdQueryCompiler_identifierCase, _FirebirdQueryCompiler_pendingSelectLimits, _FirebirdDriver_config, _FirebirdDriver_db, _FirebirdDriver_connection, _FirebirdDriver_queue, _FirebirdDriver_releaseCurrent, _FirebirdConnection_db, _FirebirdConnection_identifierCase, _FirebirdConnection_tx, _FirebirdConnection_finishTx, _FirebirdConnection_txDone, _FirebirdIntrospector_db, _FirebirdIntrospector_identifierCase;
53
+ Object.defineProperty(exports, "__esModule", { value: true });
54
+ exports.FirebirdIntrospector = exports.FirebirdDriver = exports.FirebirdQueryCompiler = exports.FirebirdAdapter = exports.FirebirdDialect = void 0;
55
+ exports.createKysely = createKysely;
56
+ exports.parseMultiRowInsert = parseMultiRowInsert;
57
+ const kysely_1 = require("kysely");
58
+ /**
59
+ * Convenience helper to construct a `Kysely<DB>` instance over a `FirebirdBrowser`
60
+ * or `FirebirdLite` database.
61
+ */
62
+ function createKysely(database, options = {}) {
63
+ return new kysely_1.Kysely({
64
+ dialect: new FirebirdDialect({ database, ...options }),
65
+ });
66
+ }
67
+ /**
68
+ * Kysely dialect for Firebird (`FirebirdBrowser` and `FirebirdLite`).
69
+ */
70
+ class FirebirdDialect {
71
+ constructor(config) {
72
+ _FirebirdDialect_config.set(this, void 0);
73
+ __classPrivateFieldSet(this, _FirebirdDialect_config, { ...config }, "f");
74
+ }
75
+ createDriver() {
76
+ return new FirebirdDriver(__classPrivateFieldGet(this, _FirebirdDialect_config, "f"));
77
+ }
78
+ createQueryCompiler() {
79
+ return new FirebirdQueryCompiler(__classPrivateFieldGet(this, _FirebirdDialect_config, "f").identifierCase ?? 'lower');
80
+ }
81
+ createAdapter() {
82
+ return new FirebirdAdapter();
83
+ }
84
+ createIntrospector(db) {
85
+ return new FirebirdIntrospector(db, __classPrivateFieldGet(this, _FirebirdDialect_config, "f").identifierCase ?? 'lower');
86
+ }
87
+ }
88
+ exports.FirebirdDialect = FirebirdDialect;
89
+ _FirebirdDialect_config = new WeakMap();
90
+ /**
91
+ * Kysely dialect adapter for Firebird.
92
+ *
93
+ * Firebird supports `INSERT / UPDATE / DELETE … RETURNING`, and requires DDL
94
+ * to commit before DML in the same table can use the new metadata.
95
+ */
96
+ class FirebirdAdapter extends kysely_1.DialectAdapterBase {
97
+ get supportsTransactionalDdl() {
98
+ return false;
99
+ }
100
+ get supportsReturning() {
101
+ return true;
102
+ }
103
+ async acquireMigrationLock() {
104
+ // Firebird databases are either single-user in the browser or serialize
105
+ // DDL through metadata locks on the server.
106
+ }
107
+ async releaseMigrationLock() {
108
+ // No-op.
109
+ }
110
+ }
111
+ exports.FirebirdAdapter = FirebirdAdapter;
112
+ const DATA_TYPE_MAP = {
113
+ serial: 'integer generated by default as identity',
114
+ bigserial: 'bigint generated by default as identity',
115
+ text: 'blob sub_type text',
116
+ bytea: 'blob sub_type binary',
117
+ timestamptz: 'timestamp with time zone',
118
+ timetz: 'time with time zone',
119
+ float4: 'float',
120
+ float8: 'double precision',
121
+ int2: 'smallint',
122
+ int4: 'integer',
123
+ int8: 'bigint',
124
+ uuid: 'varchar(36)',
125
+ json: 'blob sub_type text',
126
+ jsonb: 'blob sub_type text',
127
+ };
128
+ /**
129
+ * Kysely query compiler targeting Firebird 3+ SQL syntax.
130
+ */
131
+ class FirebirdQueryCompiler extends kysely_1.DefaultQueryCompiler {
132
+ constructor(identifierCase = 'lower') {
133
+ super();
134
+ _FirebirdQueryCompiler_identifierCase.set(this, void 0);
135
+ _FirebirdQueryCompiler_pendingSelectLimits.set(this, []);
136
+ __classPrivateFieldSet(this, _FirebirdQueryCompiler_identifierCase, identifierCase, "f");
137
+ }
138
+ getCurrentParameterPlaceholder() {
139
+ return '?';
140
+ }
141
+ getLeftIdentifierWrapper() {
142
+ return '"';
143
+ }
144
+ getRightIdentifierWrapper() {
145
+ return '"';
146
+ }
147
+ getAutoIncrement() {
148
+ return 'generated by default as identity';
149
+ }
150
+ compileUnwrappedIdentifier(node) {
151
+ const mapped = __classPrivateFieldGet(this, _FirebirdQueryCompiler_identifierCase, "f") === 'lower' && /^[a-z_][a-z0-9_$]*$/.test(node.name)
152
+ ? node.name.toUpperCase()
153
+ : node.name;
154
+ super.compileUnwrappedIdentifier({ ...node, name: mapped });
155
+ }
156
+ visitSelectQuery(node) {
157
+ if (node.offset && node.limit) {
158
+ // Firebird SQL requires OFFSET <n> ROWS before FETCH NEXT <m> ROWS ONLY.
159
+ __classPrivateFieldGet(this, _FirebirdQueryCompiler_pendingSelectLimits, "f").push(node.limit);
160
+ try {
161
+ super.visitSelectQuery({ ...node, limit: undefined });
162
+ }
163
+ finally {
164
+ __classPrivateFieldGet(this, _FirebirdQueryCompiler_pendingSelectLimits, "f").pop();
165
+ }
166
+ return;
167
+ }
168
+ __classPrivateFieldGet(this, _FirebirdQueryCompiler_pendingSelectLimits, "f").push(undefined);
169
+ try {
170
+ super.visitSelectQuery(node);
171
+ }
172
+ finally {
173
+ __classPrivateFieldGet(this, _FirebirdQueryCompiler_pendingSelectLimits, "f").pop();
174
+ }
175
+ }
176
+ visitOffset(node) {
177
+ this.append('offset ');
178
+ this.visitNode(node.offset);
179
+ this.append(' rows');
180
+ const pendingLimit = __classPrivateFieldGet(this, _FirebirdQueryCompiler_pendingSelectLimits, "f")[__classPrivateFieldGet(this, _FirebirdQueryCompiler_pendingSelectLimits, "f").length - 1];
181
+ if (pendingLimit) {
182
+ __classPrivateFieldGet(this, _FirebirdQueryCompiler_pendingSelectLimits, "f")[__classPrivateFieldGet(this, _FirebirdQueryCompiler_pendingSelectLimits, "f").length - 1] = undefined;
183
+ this.append(' ');
184
+ this.visitNode(pendingLimit);
185
+ }
186
+ }
187
+ visitLimit(node) {
188
+ const parent = this.parentNode;
189
+ if (parent &&
190
+ (parent.kind === 'UpdateQueryNode' || parent.kind === 'DeleteQueryNode')) {
191
+ this.append('rows ');
192
+ this.visitNode(node.limit);
193
+ return;
194
+ }
195
+ this.append('fetch next ');
196
+ this.visitNode(node.limit);
197
+ this.append(' rows only');
198
+ }
199
+ visitValues(node) {
200
+ if (node.values.length <= 1) {
201
+ super.visitValues(node);
202
+ return;
203
+ }
204
+ // Firebird multi-row INSERT: SELECT ?, ? FROM RDB$DATABASE UNION ALL ...
205
+ for (let i = 0; i < node.values.length; i++) {
206
+ if (i > 0)
207
+ this.append(' union all ');
208
+ this.append('select ');
209
+ const item = node.values[i];
210
+ if (item.kind === 'PrimitiveValueListNode') {
211
+ const vals = item.values;
212
+ for (let j = 0; j < vals.length; j++) {
213
+ if (j > 0)
214
+ this.append(', ');
215
+ this.appendValue(vals[j]);
216
+ }
217
+ }
218
+ else if (item.kind === 'ValueListNode') {
219
+ this.compileList(item.values);
220
+ }
221
+ else {
222
+ this.visitNode(item);
223
+ }
224
+ this.append(' from rdb$database');
225
+ }
226
+ }
227
+ visitInsertQuery(node) {
228
+ if (node.onConflict &&
229
+ node.onConflict.columns &&
230
+ node.onConflict.columns.length > 0 &&
231
+ !node.onConflict.doNothing) {
232
+ // Compile Kysely's onConflict(oc => oc.column(...).doUpdateSet(...))
233
+ // to Firebird's native UPDATE OR INSERT INTO ... VALUES (...) MATCHING (...).
234
+ if (node.with) {
235
+ this.visitNode(node.with);
236
+ this.append(' ');
237
+ }
238
+ this.append('update or insert');
239
+ if (node.into) {
240
+ this.append(' into ');
241
+ this.visitNode(node.into);
242
+ }
243
+ if (node.columns) {
244
+ this.append(' (');
245
+ this.compileList(node.columns);
246
+ this.append(')');
247
+ }
248
+ if (node.values) {
249
+ this.append(' ');
250
+ this.visitNode(node.values);
251
+ }
252
+ this.append(' matching (');
253
+ this.compileList(node.onConflict.columns);
254
+ this.append(')');
255
+ if (node.returning) {
256
+ this.append(' ');
257
+ this.visitNode(node.returning);
258
+ }
259
+ return;
260
+ }
261
+ super.visitInsertQuery(node);
262
+ }
263
+ visitCreateTable(node) {
264
+ if (node.temporary) {
265
+ // Firebird syntax: CREATE GLOBAL TEMPORARY TABLE ...
266
+ this.append('create global temporary table ');
267
+ if (node.ifNotExists) {
268
+ this.append('if not exists ');
269
+ }
270
+ this.visitNode(node.table);
271
+ if (!node.selectQuery) {
272
+ this.append(' (');
273
+ this.compileList([
274
+ ...node.columns,
275
+ ...(node.constraints ?? []),
276
+ ]);
277
+ this.append(')');
278
+ }
279
+ if (node.onCommit) {
280
+ this.append(' on commit ');
281
+ this.append(node.onCommit);
282
+ }
283
+ if (node.selectQuery) {
284
+ this.append(' as ');
285
+ this.visitNode(node.selectQuery);
286
+ }
287
+ return;
288
+ }
289
+ super.visitCreateTable(node);
290
+ }
291
+ visitColumnDefinition(node) {
292
+ if (node.autoIncrement) {
293
+ super.visitColumnDefinition({
294
+ ...node,
295
+ autoIncrement: false,
296
+ frontModifiers: [
297
+ ...(node.frontModifiers ?? []),
298
+ {
299
+ kind: 'RawNode',
300
+ sqlFragments: [this.getAutoIncrement()],
301
+ parameters: [],
302
+ },
303
+ ],
304
+ });
305
+ return;
306
+ }
307
+ super.visitColumnDefinition(node);
308
+ }
309
+ visitDataType(node) {
310
+ const mapped = DATA_TYPE_MAP[String(node.dataType).toLowerCase()];
311
+ if (mapped) {
312
+ this.append(mapped);
313
+ return;
314
+ }
315
+ super.visitDataType(node);
316
+ }
317
+ visitAddColumn(node) {
318
+ this.append('add ');
319
+ this.visitNode(node.column);
320
+ }
321
+ visitDropColumn(node) {
322
+ this.append('drop ');
323
+ this.visitNode(node.column);
324
+ }
325
+ visitRenameColumn(node) {
326
+ this.append('alter column ');
327
+ this.visitNode(node.column);
328
+ this.append(' to ');
329
+ this.visitNode(node.renameTo);
330
+ }
331
+ }
332
+ exports.FirebirdQueryCompiler = FirebirdQueryCompiler;
333
+ _FirebirdQueryCompiler_identifierCase = new WeakMap(), _FirebirdQueryCompiler_pendingSelectLimits = new WeakMap();
334
+ const BEGIN_TX = Symbol('BEGIN_TX');
335
+ const COMMIT_TX = Symbol('COMMIT_TX');
336
+ const ROLLBACK_TX = Symbol('ROLLBACK_TX');
337
+ /**
338
+ * Kysely driver backed by a `FirebirdBrowser` or `FirebirdLite` instance.
339
+ */
340
+ class FirebirdDriver {
341
+ constructor(config) {
342
+ _FirebirdDriver_config.set(this, void 0);
343
+ _FirebirdDriver_db.set(this, void 0);
344
+ _FirebirdDriver_connection.set(this, void 0);
345
+ _FirebirdDriver_queue.set(this, Promise.resolve());
346
+ _FirebirdDriver_releaseCurrent.set(this, void 0);
347
+ __classPrivateFieldSet(this, _FirebirdDriver_config, config, "f");
348
+ }
349
+ async init() {
350
+ __classPrivateFieldSet(this, _FirebirdDriver_db, __classPrivateFieldGet(this, _FirebirdDriver_db, "f") ?? (typeof __classPrivateFieldGet(this, _FirebirdDriver_config, "f").database === 'function'
351
+ ? await __classPrivateFieldGet(this, _FirebirdDriver_config, "f").database()
352
+ : __classPrivateFieldGet(this, _FirebirdDriver_config, "f").database), "f");
353
+ __classPrivateFieldSet(this, _FirebirdDriver_connection, new FirebirdConnection(__classPrivateFieldGet(this, _FirebirdDriver_db, "f"), __classPrivateFieldGet(this, _FirebirdDriver_config, "f").identifierCase ?? 'lower'), "f");
354
+ if (__classPrivateFieldGet(this, _FirebirdDriver_config, "f").onCreateConnection) {
355
+ await __classPrivateFieldGet(this, _FirebirdDriver_config, "f").onCreateConnection(__classPrivateFieldGet(this, _FirebirdDriver_connection, "f"));
356
+ }
357
+ }
358
+ async acquireConnection() {
359
+ const prev = __classPrivateFieldGet(this, _FirebirdDriver_queue, "f");
360
+ let release;
361
+ __classPrivateFieldSet(this, _FirebirdDriver_queue, new Promise((r) => {
362
+ release = r;
363
+ }), "f");
364
+ await prev;
365
+ __classPrivateFieldSet(this, _FirebirdDriver_releaseCurrent, release, "f");
366
+ return __classPrivateFieldGet(this, _FirebirdDriver_connection, "f");
367
+ }
368
+ async beginTransaction(connection, settings) {
369
+ await connection[BEGIN_TX](settings);
370
+ }
371
+ async commitTransaction(connection) {
372
+ await connection[COMMIT_TX]();
373
+ }
374
+ async rollbackTransaction(connection) {
375
+ await connection[ROLLBACK_TX]();
376
+ }
377
+ async savepoint(connection, savepointName) {
378
+ await connection.executeQuery(kysely_1.CompiledQuery.raw(`savepoint ${quoteSavepoint(savepointName)}`));
379
+ }
380
+ async rollbackToSavepoint(connection, savepointName) {
381
+ await connection.executeQuery(kysely_1.CompiledQuery.raw(`rollback to savepoint ${quoteSavepoint(savepointName)}`));
382
+ }
383
+ async releaseSavepoint(connection, savepointName) {
384
+ await connection.executeQuery(kysely_1.CompiledQuery.raw(`release savepoint ${quoteSavepoint(savepointName)}`));
385
+ }
386
+ async releaseConnection() {
387
+ const release = __classPrivateFieldGet(this, _FirebirdDriver_releaseCurrent, "f");
388
+ __classPrivateFieldSet(this, _FirebirdDriver_releaseCurrent, undefined, "f");
389
+ release?.();
390
+ }
391
+ async destroy() {
392
+ if (__classPrivateFieldGet(this, _FirebirdDriver_config, "f").closeOnDestroy && __classPrivateFieldGet(this, _FirebirdDriver_db, "f")?.close) {
393
+ await __classPrivateFieldGet(this, _FirebirdDriver_db, "f").close();
394
+ }
395
+ }
396
+ }
397
+ exports.FirebirdDriver = FirebirdDriver;
398
+ _FirebirdDriver_config = new WeakMap(), _FirebirdDriver_db = new WeakMap(), _FirebirdDriver_connection = new WeakMap(), _FirebirdDriver_queue = new WeakMap(), _FirebirdDriver_releaseCurrent = new WeakMap();
399
+ class FirebirdConnection {
400
+ constructor(db, identifierCase) {
401
+ _FirebirdConnection_db.set(this, void 0);
402
+ _FirebirdConnection_identifierCase.set(this, void 0);
403
+ _FirebirdConnection_tx.set(this, void 0);
404
+ _FirebirdConnection_finishTx.set(this, void 0);
405
+ _FirebirdConnection_txDone.set(this, void 0);
406
+ __classPrivateFieldSet(this, _FirebirdConnection_db, db, "f");
407
+ __classPrivateFieldSet(this, _FirebirdConnection_identifierCase, identifierCase, "f");
408
+ }
409
+ async executeQuery(compiledQuery) {
410
+ const target = __classPrivateFieldGet(this, _FirebirdConnection_tx, "f") ?? __classPrivateFieldGet(this, _FirebirdConnection_db, "f");
411
+ const params = [...compiledQuery.parameters];
412
+ const multiInsert = parseMultiRowInsert(compiledQuery.sql, params);
413
+ if (shouldUseExec(compiledQuery.query, compiledQuery.sql)) {
414
+ if (multiInsert && typeof target.execBatch === 'function') {
415
+ if (multiInsert.uniformSql) {
416
+ const res = await target.execBatch(multiInsert.uniformSql, multiInsert.rows.map((r) => r.params));
417
+ const affected = extractAffectedRows(res) ?? multiInsert.rows.length;
418
+ return {
419
+ numAffectedRows: BigInt(affected),
420
+ rows: [],
421
+ };
422
+ }
423
+ for (const row of multiInsert.rows) {
424
+ await target.exec(row.sql, row.params);
425
+ }
426
+ return {
427
+ numAffectedRows: BigInt(multiInsert.rows.length),
428
+ rows: [],
429
+ };
430
+ }
431
+ const res = await target.exec(compiledQuery.sql, params);
432
+ const affected = extractAffectedRows(res);
433
+ return {
434
+ ...(affected !== undefined ? { numAffectedRows: BigInt(affected) } : {}),
435
+ rows: [],
436
+ };
437
+ }
438
+ if (multiInsert && multiInsert.hasReturning && typeof target.execBatch === 'function') {
439
+ const rawRows = [];
440
+ for (const row of multiInsert.rows) {
441
+ const res = await target.query(row.sql, row.params, {
442
+ rowMode: 'object',
443
+ });
444
+ rawRows.push(...res.rows);
445
+ }
446
+ const rows = mapRows(rawRows, __classPrivateFieldGet(this, _FirebirdConnection_identifierCase, "f"));
447
+ return {
448
+ numAffectedRows: BigInt(rows.length),
449
+ rows,
450
+ };
451
+ }
452
+ const result = await target.query(compiledQuery.sql, params, {
453
+ rowMode: 'object',
454
+ });
455
+ const rows = mapRows(result.rows, __classPrivateFieldGet(this, _FirebirdConnection_identifierCase, "f"));
456
+ const kind = compiledQuery.query?.kind;
457
+ const isMutatingReturning = kind === 'InsertQueryNode' ||
458
+ kind === 'UpdateQueryNode' ||
459
+ kind === 'DeleteQueryNode';
460
+ return {
461
+ ...(isMutatingReturning ? { numAffectedRows: BigInt(rows.length) } : {}),
462
+ rows,
463
+ };
464
+ }
465
+ async *streamQuery(compiledQuery, chunkSize = 500) {
466
+ const target = __classPrivateFieldGet(this, _FirebirdConnection_tx, "f") ?? __classPrivateFieldGet(this, _FirebirdConnection_db, "f");
467
+ if (typeof target.queryStream === 'function') {
468
+ const stream = target.queryStream(compiledQuery.sql, [...compiledQuery.parameters], { batchSize: chunkSize && chunkSize > 0 ? chunkSize : 500, rowMode: 'object' });
469
+ for await (const batch of stream) {
470
+ yield {
471
+ rows: mapRows(batch.rows, __classPrivateFieldGet(this, _FirebirdConnection_identifierCase, "f")),
472
+ };
473
+ }
474
+ return;
475
+ }
476
+ const result = await this.executeQuery(compiledQuery);
477
+ if (result.rows.length > 0) {
478
+ yield { rows: result.rows };
479
+ }
480
+ }
481
+ async [(_FirebirdConnection_db = new WeakMap(), _FirebirdConnection_identifierCase = new WeakMap(), _FirebirdConnection_tx = new WeakMap(), _FirebirdConnection_finishTx = new WeakMap(), _FirebirdConnection_txDone = new WeakMap(), BEGIN_TX)](settings) {
482
+ let signalReady;
483
+ let signalStartError;
484
+ const ready = new Promise((resolve, reject) => {
485
+ signalReady = resolve;
486
+ signalStartError = reject;
487
+ });
488
+ const waitForAction = new Promise((resolve) => {
489
+ __classPrivateFieldSet(this, _FirebirdConnection_finishTx, resolve, "f");
490
+ });
491
+ __classPrivateFieldSet(this, _FirebirdConnection_txDone, __classPrivateFieldGet(this, _FirebirdConnection_db, "f")
492
+ .transaction(async (tx) => {
493
+ __classPrivateFieldSet(this, _FirebirdConnection_tx, tx, "f");
494
+ signalReady();
495
+ const action = await waitForAction;
496
+ if (action === 'rollback') {
497
+ await tx.rollback();
498
+ }
499
+ }, mapTransactionSettings(settings))
500
+ .then(() => undefined, (err) => {
501
+ signalStartError(err);
502
+ throw err;
503
+ }), "f");
504
+ await ready;
505
+ }
506
+ async [COMMIT_TX]() {
507
+ const finish = __classPrivateFieldGet(this, _FirebirdConnection_finishTx, "f");
508
+ const done = __classPrivateFieldGet(this, _FirebirdConnection_txDone, "f");
509
+ __classPrivateFieldSet(this, _FirebirdConnection_finishTx, undefined, "f");
510
+ __classPrivateFieldSet(this, _FirebirdConnection_txDone, undefined, "f");
511
+ __classPrivateFieldSet(this, _FirebirdConnection_tx, undefined, "f");
512
+ finish?.('commit');
513
+ await done;
514
+ }
515
+ async [ROLLBACK_TX]() {
516
+ const finish = __classPrivateFieldGet(this, _FirebirdConnection_finishTx, "f");
517
+ const done = __classPrivateFieldGet(this, _FirebirdConnection_txDone, "f");
518
+ __classPrivateFieldSet(this, _FirebirdConnection_finishTx, undefined, "f");
519
+ __classPrivateFieldSet(this, _FirebirdConnection_txDone, undefined, "f");
520
+ __classPrivateFieldSet(this, _FirebirdConnection_tx, undefined, "f");
521
+ finish?.('rollback');
522
+ await done?.catch(() => undefined);
523
+ }
524
+ }
525
+ /**
526
+ * Kysely database introspector reading Firebird's `RDB$RELATIONS` and `RDB$RELATION_FIELDS`.
527
+ */
528
+ class FirebirdIntrospector {
529
+ constructor(db, identifierCase = 'lower') {
530
+ _FirebirdIntrospector_db.set(this, void 0);
531
+ _FirebirdIntrospector_identifierCase.set(this, void 0);
532
+ __classPrivateFieldSet(this, _FirebirdIntrospector_db, db, "f");
533
+ __classPrivateFieldSet(this, _FirebirdIntrospector_identifierCase, identifierCase, "f");
534
+ }
535
+ async getSchemas() {
536
+ return [];
537
+ }
538
+ async getTables(options = { withInternalKyselyTables: false }) {
539
+ const relResult = await (0, kysely_1.sql) `SELECT TRIM(RDB$RELATION_NAME) AS "name", CASE WHEN RDB$VIEW_BLR IS NULL THEN 0 ELSE 1 END AS "is_view" FROM RDB$RELATIONS WHERE COALESCE(RDB$SYSTEM_FLAG, 0) = 0 ORDER BY RDB$RELATION_NAME`.execute(__classPrivateFieldGet(this, _FirebirdIntrospector_db, "f"));
540
+ const colResult = await (0, kysely_1.sql) `SELECT TRIM(rf.RDB$RELATION_NAME) AS "relation_name", TRIM(rf.RDB$FIELD_NAME) AS "field_name", f.RDB$FIELD_TYPE AS "field_type", COALESCE(f.RDB$FIELD_SUB_TYPE, 0) AS "field_sub_type", COALESCE(f.RDB$FIELD_SCALE, 0) AS "field_scale", COALESCE(rf.RDB$NULL_FLAG, f.RDB$NULL_FLAG, 0) AS "null_flag", CASE WHEN rf.RDB$DEFAULT_SOURCE IS NOT NULL OR f.RDB$DEFAULT_SOURCE IS NOT NULL THEN 1 ELSE 0 END AS "has_default", CASE WHEN rf.RDB$IDENTITY_TYPE IS NOT NULL THEN 1 ELSE 0 END AS "is_identity" FROM RDB$RELATION_FIELDS rf JOIN RDB$FIELDS f ON f.RDB$FIELD_NAME = rf.RDB$FIELD_SOURCE JOIN RDB$RELATIONS r ON r.RDB$RELATION_NAME = rf.RDB$RELATION_NAME WHERE COALESCE(r.RDB$SYSTEM_FLAG, 0) = 0 ORDER BY rf.RDB$RELATION_NAME, rf.RDB$FIELD_POSITION`.execute(__classPrivateFieldGet(this, _FirebirdIntrospector_db, "f"));
541
+ const colsByRelation = new Map();
542
+ for (const c of colResult.rows) {
543
+ const rel = String(c.relation_name).trim();
544
+ const rawName = String(c.field_name).trim();
545
+ const colName = formatOutputIdentifier(rawName, __classPrivateFieldGet(this, _FirebirdIntrospector_identifierCase, "f"));
546
+ const list = colsByRelation.get(rel) ?? [];
547
+ list.push({
548
+ name: colName,
549
+ dataType: firebirdFieldTypeName(Number(c.field_type), Number(c.field_sub_type), Number(c.field_scale)),
550
+ isNullable: Number(c.null_flag) === 0,
551
+ isAutoIncrementing: Number(c.is_identity) === 1,
552
+ hasDefaultValue: Number(c.has_default) === 1 || Number(c.is_identity) === 1,
553
+ });
554
+ colsByRelation.set(rel, list);
555
+ }
556
+ const tables = [];
557
+ for (const r of relResult.rows) {
558
+ const rawRel = String(r.name).trim();
559
+ const lowerRel = rawRel.toLowerCase();
560
+ if (!options.withInternalKyselyTables &&
561
+ (lowerRel === 'kysely_migration' || lowerRel === 'kysely_migration_lock')) {
562
+ continue;
563
+ }
564
+ tables.push({
565
+ name: formatOutputIdentifier(rawRel, __classPrivateFieldGet(this, _FirebirdIntrospector_identifierCase, "f")),
566
+ isView: Number(r.is_view) === 1,
567
+ columns: colsByRelation.get(rawRel) ?? [],
568
+ });
569
+ }
570
+ return tables;
571
+ }
572
+ async getMetadata(options) {
573
+ return {
574
+ tables: await this.getTables(options),
575
+ };
576
+ }
577
+ }
578
+ exports.FirebirdIntrospector = FirebirdIntrospector;
579
+ _FirebirdIntrospector_db = new WeakMap(), _FirebirdIntrospector_identifierCase = new WeakMap();
580
+ function shouldUseExec(node, sql) {
581
+ if (!node)
582
+ return !/^\s*(select|with|execute\s+procedure)\b/i.test(sql) && !/\breturning\b/i.test(sql);
583
+ switch (node.kind) {
584
+ case 'SelectQueryNode':
585
+ return false;
586
+ case 'InsertQueryNode':
587
+ case 'UpdateQueryNode':
588
+ case 'DeleteQueryNode':
589
+ return !node.returning;
590
+ case 'CreateTableNode':
591
+ case 'DropTableNode':
592
+ case 'AlterTableNode':
593
+ case 'CreateIndexNode':
594
+ case 'DropIndexNode':
595
+ case 'CreateViewNode':
596
+ case 'DropViewNode':
597
+ case 'CreateSchemaNode':
598
+ case 'DropSchemaNode':
599
+ return true;
600
+ default:
601
+ return (!/^\s*(select|with|execute\s+procedure)\b/i.test(sql) &&
602
+ !/\b(returning|returns)\b/i.test(sql));
603
+ }
604
+ }
605
+ function formatOutputIdentifier(name, mode) {
606
+ if (mode === 'lower' && /^[A-Z_][A-Z0-9_$]*$/.test(name)) {
607
+ return name.toLowerCase();
608
+ }
609
+ return name;
610
+ }
611
+ function mapRows(rows, mode) {
612
+ if (mode === 'preserve' || rows.length === 0) {
613
+ return rows;
614
+ }
615
+ const first = rows[0];
616
+ const keys = Object.keys(first);
617
+ const mappedKeys = keys.map((k) => formatOutputIdentifier(k, mode));
618
+ if (keys.every((k, i) => k === mappedKeys[i])) {
619
+ return rows;
620
+ }
621
+ return rows.map((row) => {
622
+ const out = {};
623
+ for (let i = 0; i < keys.length; i++) {
624
+ out[mappedKeys[i]] = row[keys[i]];
625
+ }
626
+ return out;
627
+ });
628
+ }
629
+ function mapTransactionSettings(settings) {
630
+ const options = {};
631
+ if (settings.accessMode === 'read only') {
632
+ options.readOnly = true;
633
+ }
634
+ switch (settings.isolationLevel) {
635
+ case 'read uncommitted':
636
+ case 'read committed':
637
+ options.isolationLevel = 'READ_COMMITTED';
638
+ break;
639
+ case 'repeatable read':
640
+ case 'snapshot':
641
+ options.isolationLevel = 'SNAPSHOT';
642
+ break;
643
+ case 'serializable':
644
+ options.isolationLevel = 'SNAPSHOT_TABLE_STABILITY';
645
+ break;
646
+ }
647
+ return options;
648
+ }
649
+ function quoteSavepoint(name) {
650
+ if (!/^[A-Za-z_][A-Za-z0-9_$]*$/.test(name)) {
651
+ throw new Error(`Invalid savepoint name: ${name}`);
652
+ }
653
+ return name;
654
+ }
655
+ function firebirdFieldTypeName(type, subType, scale) {
656
+ if ((type === 7 || type === 8 || type === 16 || type === 26) && (scale < 0 || subType === 1 || subType === 2)) {
657
+ return subType === 2 ? 'decimal' : 'numeric';
658
+ }
659
+ switch (type) {
660
+ case 7:
661
+ return 'smallint';
662
+ case 8:
663
+ return 'integer';
664
+ case 10:
665
+ return 'float';
666
+ case 12:
667
+ return 'date';
668
+ case 13:
669
+ return 'time';
670
+ case 14:
671
+ return 'char';
672
+ case 16:
673
+ return 'bigint';
674
+ case 23:
675
+ return 'boolean';
676
+ case 24:
677
+ case 25:
678
+ return 'decfloat';
679
+ case 26:
680
+ return 'int128';
681
+ case 27:
682
+ return 'double precision';
683
+ case 28:
684
+ return 'time with time zone';
685
+ case 29:
686
+ return 'timestamp with time zone';
687
+ case 35:
688
+ return 'timestamp';
689
+ case 37:
690
+ return 'varchar';
691
+ case 261:
692
+ return subType === 1 ? 'text' : 'blob';
693
+ default:
694
+ return `type_${type}`;
695
+ }
696
+ }
697
+ function extractAffectedRows(res) {
698
+ if (typeof res === 'object' && res !== null && 'affectedRows' in res) {
699
+ const n = res.affectedRows;
700
+ return typeof n === 'number' ? n : undefined;
701
+ }
702
+ if (Array.isArray(res)) {
703
+ let total = 0;
704
+ for (const item of res) {
705
+ if (typeof item === 'object' && item !== null && 'affectedRows' in item) {
706
+ total += Number(item.affectedRows ?? 0);
707
+ }
708
+ }
709
+ return total;
710
+ }
711
+ return undefined;
712
+ }
713
+ const MULTI_ROW_INSERT_RE = /^((?:with\b[\s\S]+?\s+)?insert\s+into\s+[\s\S]+?\)\s+(?:overriding\s+system\s+value\s+)?)(select\s+[\s\S]+?\s+from\s+rdb\$database(?:\s+union\s+all\s+select\s+[\s\S]+?\s+from\s+rdb\$database)+)(\s+returning\s+[\s\S]+)?$/i;
714
+ function countPlaceholders(sqlFragment) {
715
+ let count = 0;
716
+ let inSingle = false;
717
+ let inDouble = false;
718
+ for (let i = 0; i < sqlFragment.length; i++) {
719
+ const ch = sqlFragment[i];
720
+ if (ch === "'" && !inDouble) {
721
+ inSingle = !inSingle;
722
+ }
723
+ else if (ch === '"' && !inSingle) {
724
+ inDouble = !inDouble;
725
+ }
726
+ else if (ch === '?' && !inSingle && !inDouble) {
727
+ count++;
728
+ }
729
+ }
730
+ return count;
731
+ }
732
+ /**
733
+ * Splits a multi-row `INSERT INTO ... SELECT ... FROM RDB$DATABASE UNION ALL ...`
734
+ * statement into per-row `INSERT INTO ... VALUES (...)` statements so execution
735
+ * against `FirebirdLite` / `FirebirdBrowser` can use `execBatch` (or per-row
736
+ * `INSERT ... VALUES (...) RETURNING ...`), avoiding Firebird's `-804 Data type unknown`
737
+ * error on untyped `?` parameters inside `SELECT ? FROM RDB$DATABASE`.
738
+ * @internal
739
+ */
740
+ function parseMultiRowInsert(sql, params) {
741
+ const m = MULTI_ROW_INSERT_RE.exec(sql.trim());
742
+ if (!m)
743
+ return undefined;
744
+ const prefix = m[1];
745
+ const selectsBody = m[2];
746
+ const returningSuffix = m[3] ?? '';
747
+ const branches = selectsBody.split(/\s+union\s+all\s+/i);
748
+ if (branches.length < 2)
749
+ return undefined;
750
+ const rows = [];
751
+ let paramOffset = 0;
752
+ for (const branch of branches) {
753
+ const bm = /^select\s+([\s\S]+?)\s+from\s+rdb\$database$/i.exec(branch.trim());
754
+ if (!bm)
755
+ return undefined;
756
+ const exprs = bm[1];
757
+ const pCount = countPlaceholders(exprs);
758
+ if (paramOffset + pCount > params.length)
759
+ return undefined;
760
+ const rowParams = params.slice(paramOffset, paramOffset + pCount);
761
+ paramOffset += pCount;
762
+ rows.push({
763
+ sql: `${prefix}values (${exprs})${returningSuffix}`,
764
+ params: rowParams,
765
+ });
766
+ }
767
+ if (paramOffset !== params.length)
768
+ return undefined;
769
+ const firstSql = rows[0].sql;
770
+ const uniformSql = rows.every((r) => r.sql === firstSql) ? firstSql : undefined;
771
+ return {
772
+ rows,
773
+ uniformSql,
774
+ hasReturning: returningSuffix.length > 0,
775
+ };
776
+ }
777
+ //# sourceMappingURL=index.js.map