@duckdb/node-api 1.2.1-alpha.16 → 1.2.2-alpha.18

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 (62) hide show
  1. package/README.md +223 -28
  2. package/lib/DuckDBAppender.d.ts +2 -2
  3. package/lib/DuckDBAppender.js +4 -4
  4. package/lib/DuckDBConnection.d.ts +4 -4
  5. package/lib/DuckDBConnection.js +10 -6
  6. package/lib/DuckDBDataChunk.d.ts +12 -4
  7. package/lib/DuckDBDataChunk.js +64 -6
  8. package/lib/DuckDBInstance.d.ts +2 -0
  9. package/lib/DuckDBInstance.js +9 -9
  10. package/lib/DuckDBInstanceCache.d.ts +8 -0
  11. package/lib/DuckDBInstanceCache.js +28 -0
  12. package/lib/DuckDBResult.d.ts +15 -1
  13. package/lib/DuckDBResult.js +62 -9
  14. package/lib/DuckDBResultReader.d.ts +15 -1
  15. package/lib/DuckDBResultReader.js +42 -5
  16. package/lib/DuckDBType.d.ts +9 -0
  17. package/lib/DuckDBType.js +61 -0
  18. package/lib/DuckDBValueConverter.d.ts +1 -3
  19. package/lib/DuckDBValueConverters.d.ts +47 -0
  20. package/lib/DuckDBValueConverters.js +214 -0
  21. package/lib/JS.d.ts +3 -0
  22. package/lib/JS.js +2 -0
  23. package/lib/JSDuckDBValueConverter.d.ts +3 -0
  24. package/lib/JSDuckDBValueConverter.js +46 -0
  25. package/lib/Json.d.ts +3 -0
  26. package/lib/Json.js +2 -0
  27. package/lib/JsonDuckDBValueConverter.d.ts +3 -0
  28. package/lib/JsonDuckDBValueConverter.js +46 -0
  29. package/lib/conversion/stringFromBlob.d.ts +2 -0
  30. package/lib/conversion/stringFromBlob.js +28 -2
  31. package/lib/convertColumnsFromChunks.d.ts +1 -1
  32. package/lib/convertColumnsFromChunks.js +1 -1
  33. package/lib/convertColumnsObjectFromChunks.d.ts +1 -1
  34. package/lib/convertColumnsObjectFromChunks.js +1 -1
  35. package/lib/convertRowObjectsFromChunks.d.ts +1 -1
  36. package/lib/convertRowObjectsFromChunks.js +1 -1
  37. package/lib/convertRowsFromChunks.d.ts +1 -1
  38. package/lib/createConfig.d.ts +2 -0
  39. package/lib/createConfig.js +19 -0
  40. package/lib/createDuckDBValueConverter.d.ts +3 -0
  41. package/lib/createDuckDBValueConverter.js +15 -0
  42. package/lib/duckdb.d.ts +8 -3
  43. package/lib/duckdb.js +10 -5
  44. package/lib/getColumnsFromChunks.js +2 -8
  45. package/lib/getColumnsObjectFromChunks.js +2 -11
  46. package/lib/getRowObjectsFromChunks.js +1 -8
  47. package/lib/getRowsFromChunks.js +1 -1
  48. package/lib/values/DuckDBBitValue.d.ts +1 -1
  49. package/lib/values/DuckDBBitValue.js +13 -2
  50. package/lib/values/DuckDBDateValue.d.ts +1 -1
  51. package/lib/values/DuckDBDateValue.js +5 -2
  52. package/lib/values/DuckDBDecimalValue.d.ts +1 -1
  53. package/lib/values/DuckDBDecimalValue.js +3 -0
  54. package/lib/values/DuckDBTimeValue.d.ts +1 -1
  55. package/lib/values/DuckDBTimeValue.js +5 -2
  56. package/lib/values/DuckDBTimestampTZValue.d.ts +1 -1
  57. package/lib/values/DuckDBTimestampTZValue.js +5 -2
  58. package/lib/values/DuckDBTimestampValue.d.ts +1 -1
  59. package/lib/values/DuckDBTimestampValue.js +5 -2
  60. package/package.json +2 -2
  61. package/lib/DuckDBValueToJsonConverter.d.ts +0 -10
  62. package/lib/DuckDBValueToJsonConverter.js +0 -101
package/README.md CHANGED
@@ -4,30 +4,33 @@ An API for using [DuckDB](https://duckdb.org/) in [Node](https://nodejs.org/).
4
4
 
5
5
  This is a high-level API meant for applications.
6
6
  It depends on low-level bindings that adhere closely to [DuckDB's C API](https://duckdb.org/docs/api/c/overview),
7
- available separately as [@duckdb/duckdb-bindings](https://www.npmjs.com/package/@duckdb/node-bindings).
7
+ available separately as [@duckdb/node-bindings](https://www.npmjs.com/package/@duckdb/node-bindings).
8
8
 
9
9
  ## Features
10
10
 
11
- ### Main differences from [duckdb-node](https://www.npmjs.com/package/duckdb)
12
- - Native support for Promises; no need for separate [duckdb-async](https://www.npmjs.com/package/duckdb-async) wrapper.
13
- - DuckDB-specific API; not based on the [SQLite Node API](https://www.npmjs.com/package/sqlite3).
14
- - Lossless & efficent support for values of all [DuckDB data types](https://duckdb.org/docs/sql/data_types/overview).
15
- - Wraps [released DuckDB binaries](https://github.com/duckdb/duckdb/releases) instead of rebuilding DuckDB.
16
- - Built on [DuckDB's C API](https://duckdb.org/docs/api/c/overview); exposes more functionality.
11
+ ### Main Differences from [duckdb-node](https://www.npmjs.com/package/duckdb)
12
+ * Native support for Promises; no need for separate [duckdb-async](https://www.npmjs.com/package/duckdb-async) wrapper.
13
+ * DuckDB-specific API; not based on the [SQLite Node API](https://www.npmjs.com/package/sqlite3).
14
+ * Lossless & efficent support for values of all [DuckDB data types](https://duckdb.org/docs/sql/data_types/overview).
15
+ * Wraps [released DuckDB binaries](https://github.com/duckdb/duckdb/releases) instead of rebuilding DuckDB.
16
+ * Built on [DuckDB's C API](https://duckdb.org/docs/api/c/overview); exposes more functionality.
17
17
 
18
18
  ### Roadmap
19
19
 
20
20
  Some features are not yet complete:
21
- - Binding and appending the MAP and UNION data types
22
- - Appending default values row-by-row
23
- - User-defined types & functions
24
- - Profiling info
25
- - Table description
26
- - APIs for Arrow
21
+ * Binding and appending the MAP and UNION data types
22
+ * Appending default values row-by-row
23
+ * User-defined types & functions
24
+ * Profiling info
25
+ * Table description
26
+ * APIs for Arrow
27
+
28
+ See the [issues list on GitHub](https://github.com/duckdb/duckdb-node-neo/issues)
29
+ for the most up-to-date roadmap.
27
30
 
28
31
  ### Supported Platforms
29
32
 
30
- - Linux arm64 (experimental)
33
+ - Linux arm64
31
34
  - Linux x64
32
35
  - Mac OS X (Darwin) arm64 (Apple Silicon)
33
36
  - Mac OS X (Darwin) x64 (Intel)
@@ -45,6 +48,17 @@ console.log(duckdb.version());
45
48
  console.log(duckdb.configurationOptionDescriptions());
46
49
  ```
47
50
 
51
+ ### Connect
52
+
53
+ ```ts
54
+ import { DuckDBConnection } from '@duckdb/node-api';
55
+
56
+ const connection = await DuckDBConnection.create();
57
+ ```
58
+
59
+ This uses the default instance.
60
+ For advanced usage, you can create instances explicitly.
61
+
48
62
  ### Create Instance
49
63
 
50
64
  ```ts
@@ -66,14 +80,33 @@ Read from and write to a database file, which is created if needed:
66
80
  const instance = await DuckDBInstance.create('my_duckdb.db');
67
81
  ```
68
82
 
69
- Set configuration options:
83
+ Set [configuration options](https://duckdb.org/docs/stable/configuration/overview.html#configuration-reference):
70
84
  ```ts
71
85
  const instance = await DuckDBInstance.create('my_duckdb.db', {
72
86
  threads: '4'
73
87
  });
74
88
  ```
75
89
 
76
- ### Connect
90
+ ### Instance Cache
91
+
92
+ Multiple instances in the same process should not
93
+ attach the same database.
94
+
95
+ To prevent this, an instance cache can be used:
96
+ ```ts
97
+ const instance = await DuckDBInstance.fromCache('my_duckdb.db');
98
+ ```
99
+
100
+ This uses the default instance cache. For advanced usage, you can create
101
+ instance caches explicitly:
102
+ ```ts
103
+ import { DuckDBInstanceCache } from '@duckdb/node-api';
104
+
105
+ const cache = new DuckDBInstanceCache();
106
+ const instance = await cache.getOrCreateInstance('my_duckdb.db');
107
+ ```
108
+
109
+ ### Connect to Instance
77
110
 
78
111
  ```ts
79
112
  const connection = await instance.connect();
@@ -85,13 +118,13 @@ Connections will be disconnected automatically soon after their reference
85
118
  is dropped, but you can also disconnect explicitly if and when you want:
86
119
 
87
120
  ```ts
88
- connection.disconnect();
121
+ connection.disconnectSync();
89
122
  ```
90
123
 
91
124
  or, equivalently:
92
125
 
93
126
  ```ts
94
- connection.close();
127
+ connection.closeSync();
95
128
  ```
96
129
 
97
130
  ### Run SQL
@@ -150,6 +183,36 @@ const result = await connection.run('select $a, $b, $c', {
150
183
  });
151
184
  ```
152
185
 
186
+ ### Specifying Values
187
+
188
+ Values of many data types are represented using one of the JS primitives
189
+ `boolean`, `number`, `bigint`, or `string`.
190
+ Also, any type can have `null` values.
191
+
192
+ Values of some data types need to be constructed using special functions.
193
+ These are:
194
+
195
+ | Type | Function |
196
+ | ---- | -------- |
197
+ | `ARRAY` | `arrayValue` |
198
+ | `BIT` | `bitValue` |
199
+ | `BLOB` | `blobValue` |
200
+ | `DATE` | `dateValue` |
201
+ | `DECIMAL` | `decimalValue` |
202
+ | `INTERVAL` | `intervalValue` |
203
+ | `LIST` | `listValue` |
204
+ | `MAP` | `mapValue` |
205
+ | `STRUCT` | `structValue` |
206
+ | `TIME` | `timeValue` |
207
+ | `TIMETZ` | `timeTZValue` |
208
+ | `TIMESTAMP` | `timestampValue` |
209
+ | `TIMESTAMPTZ` | `timestampTZValue` |
210
+ | `TIMESTAMP_S` | `timestampSecondsValue` |
211
+ | `TIMESTAMP_MS` | `timestampMillisValue` |
212
+ | `TIMESTAMP_NS` | `timestampNanosValue` |
213
+ | `UNION` | `unionValue` |
214
+ | `UUID` | `uuidValue` |
215
+
153
216
  ### Stream Results
154
217
 
155
218
  Streaming results evaluate lazily when rows are read.
@@ -221,13 +284,21 @@ const columnsObject = reader.getColumnsObject();
221
284
  // { i: [0, 1, 2], n: [10, 11, 12] }
222
285
  ```
223
286
 
224
- ### Convert Result Data to JSON
287
+ ### Convert Result Data
288
+
289
+ By default, data values that cannot be represented as JS built-ins
290
+ are returned as specialized JS objects; see `Inspect Data Values` below.
225
291
 
226
- By default, data values that cannot be represented as JS primitives
227
- are returned as rich JS objects; see `Inspect Data Values` below.
292
+ To retrieve data in a different form, such as JS built-ins or values that
293
+ can be losslessly serialized to JSON, use the `JS` or `Json` forms of the
294
+ above result data methods.
228
295
 
229
- To retrieve data in a form that can be losslessly serialized to JSON,
230
- use the `Json` forms of the above result data methods:
296
+ Custom converters can be supplied as well. See the implementations of
297
+ [JSDuckDBValueConverter](https://github.com/duckdb/duckdb-node-neo/blob/main/api/src/JSDuckDBValueConverter.ts)
298
+ and [JsonDuckDBValueConverters](https://github.com/duckdb/duckdb-node-neo/blob/main/api/src/JsonDuckDBValueConverter.ts)
299
+ for how to do this.
300
+
301
+ Examples (using the `Json` forms):
231
302
 
232
303
  ```ts
233
304
  const reader = await connection.runAndReadAll(
@@ -375,6 +446,127 @@ const columnsObject = reader.getColumnsObjectJson();
375
446
  // }
376
447
  ```
377
448
 
449
+ Column names and types can also be serialized to JSON:
450
+ ```ts
451
+ const columnNamesAndTypes = reader.columnNamesAndTypesJson();
452
+ // {
453
+ // "columnNames": [
454
+ // "int_array",
455
+ // "struct",
456
+ // "map",
457
+ // "union"
458
+ // ],
459
+ // "columnTypes": [
460
+ // {
461
+ // "typeId": 24,
462
+ // "valueType": {
463
+ // "typeId": 4
464
+ // }
465
+ // },
466
+ // {
467
+ // "typeId": 25,
468
+ // "entryNames": [
469
+ // "a",
470
+ // "b"
471
+ // ],
472
+ // "entryTypes": [
473
+ // {
474
+ // "typeId": 4
475
+ // },
476
+ // {
477
+ // "typeId": 17
478
+ // }
479
+ // ]
480
+ // },
481
+ // {
482
+ // "typeId": 26,
483
+ // "keyType": {
484
+ // "typeId": 17
485
+ // },
486
+ // "valueType": {
487
+ // "typeId": 17
488
+ // }
489
+ // },
490
+ // {
491
+ // "typeId": 28,
492
+ // "memberTags": [
493
+ // "name",
494
+ // "age"
495
+ // ],
496
+ // "memberTypes": [
497
+ // {
498
+ // "typeId": 17
499
+ // },
500
+ // {
501
+ // "typeId": 3
502
+ // }
503
+ // ]
504
+ // }
505
+ // ]
506
+ // }
507
+
508
+ const columnNameAndTypeObjects = reader.columnNameAndTypeObjectsJson();
509
+ // [
510
+ // {
511
+ // "columnName": "int_array",
512
+ // "columnType": {
513
+ // "typeId": 24,
514
+ // "valueType": {
515
+ // "typeId": 4
516
+ // }
517
+ // }
518
+ // },
519
+ // {
520
+ // "columnName": "struct",
521
+ // "columnType": {
522
+ // "typeId": 25,
523
+ // "entryNames": [
524
+ // "a",
525
+ // "b"
526
+ // ],
527
+ // "entryTypes": [
528
+ // {
529
+ // "typeId": 4
530
+ // },
531
+ // {
532
+ // "typeId": 17
533
+ // }
534
+ // ]
535
+ // }
536
+ // },
537
+ // {
538
+ // "columnName": "map",
539
+ // "columnType": {
540
+ // "typeId": 26,
541
+ // "keyType": {
542
+ // "typeId": 17
543
+ // },
544
+ // "valueType": {
545
+ // "typeId": 17
546
+ // }
547
+ // }
548
+ // },
549
+ // {
550
+ // "columnName": "union",
551
+ // "columnType": {
552
+ // "typeId": 28,
553
+ // "memberTags": [
554
+ // "name",
555
+ // "age"
556
+ // ],
557
+ // "memberTypes": [
558
+ // {
559
+ // "typeId": 17
560
+ // },
561
+ // {
562
+ // "typeId": 3
563
+ // }
564
+ // ]
565
+ // }
566
+ // }
567
+ // ]
568
+ ```
569
+
378
570
  ### Fetch Chunks
379
571
 
380
572
  Fetch all chunks:
@@ -409,11 +601,12 @@ Get chunk data:
409
601
  ```ts
410
602
  const rows = chunk.getRows();
411
603
 
412
- const rowObjects = chunk.getRowObjects();
604
+ const rowObjects = chunk.getRowObjects(result.deduplicatedColumnNames());
413
605
 
414
606
  const columns = chunk.getColumns();
415
607
 
416
- const columnsObject = chunk.getColumnsObject();
608
+ const columnsObject =
609
+ chunk.getColumnsObject(result.deduplicatedColumnNames());
417
610
  ```
418
611
 
419
612
  Get chunk data (one value at a time)
@@ -654,13 +847,13 @@ appender.appendInteger(123);
654
847
  appender.appendVarchar('mallard');
655
848
  appender.endRow();
656
849
 
657
- appender.flush();
850
+ appender.flushSync();
658
851
 
659
852
  appender.appendInteger(17);
660
853
  appender.appendVarchar('goose');
661
854
  appender.endRow();
662
855
 
663
- appender.close(); // also flushes
856
+ appender.closeSync(); // also flushes
664
857
  ```
665
858
 
666
859
  ### Append Data Chunk
@@ -685,9 +878,11 @@ chunk.setColumns([
685
878
  // ]);
686
879
 
687
880
  appender.appendDataChunk(chunk);
688
- appender.flush();
881
+ appender.flushSync();
689
882
  ```
690
883
 
884
+ See "Specifying Values" above for how to supply values to the appender.
885
+
691
886
  ### Extract Statements
692
887
 
693
888
  ```ts
@@ -5,8 +5,8 @@ import { DuckDBArrayValue, DuckDBBitValue, DuckDBDateValue, DuckDBDecimalValue,
5
5
  export declare class DuckDBAppender {
6
6
  private readonly appender;
7
7
  constructor(appender: duckdb.Appender);
8
- close(): void;
9
- flush(): void;
8
+ closeSync(): void;
9
+ flushSync(): void;
10
10
  get columnCount(): number;
11
11
  columnType(columnIndex: number): DuckDBType;
12
12
  endRow(): void;
@@ -13,11 +13,11 @@ class DuckDBAppender {
13
13
  constructor(appender) {
14
14
  this.appender = appender;
15
15
  }
16
- close() {
17
- node_bindings_1.default.appender_close(this.appender);
16
+ closeSync() {
17
+ node_bindings_1.default.appender_close_sync(this.appender);
18
18
  }
19
- flush() {
20
- node_bindings_1.default.appender_flush(this.appender);
19
+ flushSync() {
20
+ node_bindings_1.default.appender_flush_sync(this.appender);
21
21
  }
22
22
  get columnCount() {
23
23
  return node_bindings_1.default.appender_column_count(this.appender);
@@ -12,10 +12,10 @@ import { DuckDBValue } from './values';
12
12
  export declare class DuckDBConnection {
13
13
  private readonly connection;
14
14
  constructor(connection: duckdb.Connection);
15
- static create(instance: DuckDBInstance): Promise<DuckDBConnection>;
16
- /** Same as disconnect. */
17
- close(): void;
18
- disconnect(): void;
15
+ static create(instance?: DuckDBInstance): Promise<DuckDBConnection>;
16
+ /** Same as disconnectSync. */
17
+ closeSync(): void;
18
+ disconnectSync(): void;
19
19
  interrupt(): void;
20
20
  get progress(): duckdb.QueryProgress;
21
21
  run(sql: string, values?: DuckDBValue[] | Record<string, DuckDBValue>, types?: DuckDBType[] | Record<string, DuckDBType | undefined>): Promise<DuckDBMaterializedResult>;
@@ -7,6 +7,7 @@ exports.DuckDBConnection = void 0;
7
7
  const node_bindings_1 = __importDefault(require("@duckdb/node-bindings"));
8
8
  const DuckDBAppender_1 = require("./DuckDBAppender");
9
9
  const DuckDBExtractedStatements_1 = require("./DuckDBExtractedStatements");
10
+ const DuckDBInstance_1 = require("./DuckDBInstance");
10
11
  const DuckDBMaterializedResult_1 = require("./DuckDBMaterializedResult");
11
12
  const DuckDBPreparedStatement_1 = require("./DuckDBPreparedStatement");
12
13
  const DuckDBResultReader_1 = require("./DuckDBResultReader");
@@ -16,14 +17,17 @@ class DuckDBConnection {
16
17
  this.connection = connection;
17
18
  }
18
19
  static async create(instance) {
19
- return instance.connect();
20
+ if (instance) {
21
+ return instance.connect();
22
+ }
23
+ return (await DuckDBInstance_1.DuckDBInstance.fromCache()).connect();
20
24
  }
21
- /** Same as disconnect. */
22
- close() {
23
- return this.disconnect();
25
+ /** Same as disconnectSync. */
26
+ closeSync() {
27
+ return this.disconnectSync();
24
28
  }
25
- disconnect() {
26
- return node_bindings_1.default.disconnect(this.connection);
29
+ disconnectSync() {
30
+ return node_bindings_1.default.disconnect_sync(this.connection);
27
31
  }
28
32
  interrupt() {
29
33
  node_bindings_1.default.interrupt(this.connection);
@@ -14,20 +14,28 @@ export declare class DuckDBDataChunk {
14
14
  set rowCount(count: number);
15
15
  getColumnVector(columnIndex: number): DuckDBVector;
16
16
  visitColumnValues(columnIndex: number, visitValue: (value: DuckDBValue, rowIndex: number, columnIndex: number, type: DuckDBType) => void): void;
17
+ appendColumnValues(columnIndex: number, values: DuckDBValue[]): void;
17
18
  getColumnValues(columnIndex: number): DuckDBValue[];
18
- convertColumnValues<T>(columnIndex: number, converter: DuckDBValueConverter<T>): T[];
19
+ convertColumnValues<T>(columnIndex: number, converter: DuckDBValueConverter<T>): (T | null)[];
19
20
  setColumnValues(columnIndex: number, values: readonly DuckDBValue[]): void;
20
21
  visitColumns(visitColumn: (column: DuckDBValue[], columnIndex: number, type: DuckDBType) => void): void;
22
+ appendToColumns(columns: (DuckDBValue[] | undefined)[]): void;
21
23
  getColumns(): DuckDBValue[][];
22
- convertColumns<T>(converter: DuckDBValueConverter<T>): T[][];
24
+ convertColumns<T>(converter: DuckDBValueConverter<T>): (T | null)[][];
23
25
  setColumns(columns: readonly (readonly DuckDBValue[])[]): void;
26
+ appendToColumnsObject(columnNames: readonly string[], columnsObject: Record<string, DuckDBValue[] | undefined>): void;
27
+ getColumnsObject(columnNames: readonly string[]): Record<string, DuckDBValue[]>;
24
28
  visitColumnMajor(visitValue: (value: DuckDBValue, rowIndex: number, columnIndex: number, type: DuckDBType) => void): void;
25
29
  visitRowValues(rowIndex: number, visitValue: (value: DuckDBValue, rowIndex: number, columnIndex: number, type: DuckDBType) => void): void;
30
+ appendRowValues(rowIndex: number, values: DuckDBValue[]): void;
26
31
  getRowValues(rowIndex: number): DuckDBValue[];
27
- convertRowValues<T>(rowIndex: number, converter: DuckDBValueConverter<T>): T[];
32
+ convertRowValues<T>(rowIndex: number, converter: DuckDBValueConverter<T>): (T | null)[];
28
33
  visitRows(visitRow: (row: DuckDBValue[], rowIndex: number) => void): void;
34
+ appendToRows(rows: DuckDBValue[][]): void;
29
35
  getRows(): DuckDBValue[][];
30
- convertRows<T>(converter: DuckDBValueConverter<T>): T[][];
36
+ convertRows<T>(converter: DuckDBValueConverter<T>): (T | null)[][];
31
37
  setRows(rows: readonly (readonly DuckDBValue[])[]): void;
38
+ appendToRowObjects(columnNames: readonly string[], rowObjects: Record<string, DuckDBValue>[]): void;
39
+ getRowObjects(columnNames: readonly string[]): Record<string, DuckDBValue>[];
32
40
  visitRowMajor(visitValue: (value: DuckDBValue, rowIndex: number, columnIndex: number, type: DuckDBType) => void): void;
33
41
  }
@@ -46,15 +46,17 @@ class DuckDBDataChunk {
46
46
  visitValue(vector.getItem(rowIndex), rowIndex, columnIndex, type);
47
47
  }
48
48
  }
49
+ appendColumnValues(columnIndex, values) {
50
+ this.visitColumnValues(columnIndex, (value) => values.push(value));
51
+ }
49
52
  getColumnValues(columnIndex) {
50
53
  const values = [];
51
- this.visitColumnValues(columnIndex, (value) => values.push(value));
54
+ this.appendColumnValues(columnIndex, values);
52
55
  return values;
53
56
  }
54
57
  convertColumnValues(columnIndex, converter) {
55
58
  const convertedValues = [];
56
- const type = this.getColumnVector(columnIndex).type;
57
- this.visitColumnValues(columnIndex, (value) => convertedValues.push(converter.convertValue(value, type)));
59
+ this.visitColumnValues(columnIndex, (value, _r, _c, type) => convertedValues.push(converter(value, type, converter)));
58
60
  return convertedValues;
59
61
  }
60
62
  setColumnValues(columnIndex, values) {
@@ -73,6 +75,17 @@ class DuckDBDataChunk {
73
75
  visitColumn(this.getColumnValues(columnIndex), columnIndex, this.getColumnVector(columnIndex).type);
74
76
  }
75
77
  }
78
+ appendToColumns(columns) {
79
+ const columnCount = this.columnCount;
80
+ for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
81
+ let column = columns[columnIndex];
82
+ if (!column) {
83
+ column = [];
84
+ columns[columnIndex] = column;
85
+ }
86
+ this.appendColumnValues(columnIndex, column);
87
+ }
88
+ }
76
89
  getColumns() {
77
90
  const columns = [];
78
91
  this.visitColumns((column) => columns.push(column));
@@ -94,6 +107,26 @@ class DuckDBDataChunk {
94
107
  this.setColumnValues(columnIndex, columns[columnIndex]);
95
108
  }
96
109
  }
110
+ appendToColumnsObject(columnNames, columnsObject) {
111
+ const columnCount = this.columnCount;
112
+ if (columnNames.length !== columnCount) {
113
+ throw new Error(`Provided number of column names (${columnNames.length}) does not match column count (${this.columnCount})`);
114
+ }
115
+ for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
116
+ const columnName = columnNames[columnIndex];
117
+ let columnValues = columnsObject[columnName];
118
+ if (!columnValues) {
119
+ columnValues = [];
120
+ columnsObject[columnName] = columnValues;
121
+ }
122
+ this.appendColumnValues(columnIndex, columnValues);
123
+ }
124
+ }
125
+ getColumnsObject(columnNames) {
126
+ const columnsObject = {};
127
+ this.appendToColumnsObject(columnNames, columnsObject);
128
+ return columnsObject;
129
+ }
97
130
  visitColumnMajor(visitValue) {
98
131
  const columnCount = this.columnCount;
99
132
  for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
@@ -107,14 +140,17 @@ class DuckDBDataChunk {
107
140
  visitValue(vector.getItem(rowIndex), rowIndex, columnIndex, vector.type);
108
141
  }
109
142
  }
143
+ appendRowValues(rowIndex, values) {
144
+ this.visitRowValues(rowIndex, (value) => values.push(value));
145
+ }
110
146
  getRowValues(rowIndex) {
111
147
  const values = [];
112
- this.visitRowValues(rowIndex, (value) => values.push(value));
148
+ this.appendRowValues(rowIndex, values);
113
149
  return values;
114
150
  }
115
151
  convertRowValues(rowIndex, converter) {
116
152
  const convertedValues = [];
117
- this.visitRowValues(rowIndex, (value, _, columnIndex) => convertedValues.push(converter.convertValue(value, this.getColumnVector(columnIndex).type)));
153
+ this.visitRowValues(rowIndex, (value, _, columnIndex) => convertedValues.push(converter(value, this.getColumnVector(columnIndex).type, converter)));
118
154
  return convertedValues;
119
155
  }
120
156
  visitRows(visitRow) {
@@ -123,9 +159,12 @@ class DuckDBDataChunk {
123
159
  visitRow(this.getRowValues(rowIndex), rowIndex);
124
160
  }
125
161
  }
162
+ appendToRows(rows) {
163
+ this.visitRows((row) => rows.push(row));
164
+ }
126
165
  getRows() {
127
166
  const rows = [];
128
- this.visitRows((row) => rows.push(row));
167
+ this.appendToRows(rows);
129
168
  return rows;
130
169
  }
131
170
  convertRows(converter) {
@@ -147,6 +186,25 @@ class DuckDBDataChunk {
147
186
  vector.flush();
148
187
  }
149
188
  }
189
+ appendToRowObjects(columnNames, rowObjects) {
190
+ const columnCount = this.columnCount;
191
+ if (columnNames.length !== columnCount) {
192
+ throw new Error(`Provided number of column names (${columnNames.length}) does not match column count (${this.columnCount})`);
193
+ }
194
+ const rowCount = this.rowCount;
195
+ for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
196
+ let rowObject = {};
197
+ this.visitRowValues(rowIndex, (value, _, columnIndex) => {
198
+ rowObject[columnNames[columnIndex]] = value;
199
+ });
200
+ rowObjects.push(rowObject);
201
+ }
202
+ }
203
+ getRowObjects(columnNames) {
204
+ const rowObjects = [];
205
+ this.appendToRowObjects(columnNames, rowObjects);
206
+ return rowObjects;
207
+ }
150
208
  visitRowMajor(visitValue) {
151
209
  const rowCount = this.rowCount;
152
210
  const columnCount = this.columnCount;
@@ -4,5 +4,7 @@ export declare class DuckDBInstance {
4
4
  private readonly db;
5
5
  constructor(db: duckdb.Database);
6
6
  static create(path?: string, options?: Record<string, string>): Promise<DuckDBInstance>;
7
+ static fromCache(path?: string, options?: Record<string, string>): Promise<DuckDBInstance>;
7
8
  connect(): Promise<DuckDBConnection>;
9
+ closeSync(): void;
8
10
  }
@@ -5,26 +5,26 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.DuckDBInstance = void 0;
7
7
  const node_bindings_1 = __importDefault(require("@duckdb/node-bindings"));
8
+ const createConfig_1 = require("./createConfig");
8
9
  const DuckDBConnection_1 = require("./DuckDBConnection");
10
+ const DuckDBInstanceCache_1 = require("./DuckDBInstanceCache");
9
11
  class DuckDBInstance {
10
12
  db;
11
13
  constructor(db) {
12
14
  this.db = db;
13
15
  }
14
16
  static async create(path, options) {
15
- const config = node_bindings_1.default.create_config();
16
- // Set the default duckdb_api value for the api. Can be overridden.
17
- node_bindings_1.default.set_config(config, 'duckdb_api', 'node-neo-api');
18
- if (options) {
19
- for (const optionName in options) {
20
- const optionValue = String(options[optionName]);
21
- node_bindings_1.default.set_config(config, optionName, optionValue);
22
- }
23
- }
17
+ const config = (0, createConfig_1.createConfig)(options);
24
18
  return new DuckDBInstance(await node_bindings_1.default.open(path, config));
25
19
  }
20
+ static async fromCache(path, options) {
21
+ return DuckDBInstanceCache_1.DuckDBInstanceCache.singleton.getOrCreateInstance(path, options);
22
+ }
26
23
  async connect() {
27
24
  return new DuckDBConnection_1.DuckDBConnection(await node_bindings_1.default.connect(this.db));
28
25
  }
26
+ closeSync() {
27
+ node_bindings_1.default.close_sync(this.db);
28
+ }
29
29
  }
30
30
  exports.DuckDBInstance = DuckDBInstance;
@@ -0,0 +1,8 @@
1
+ import { DuckDBInstance } from './DuckDBInstance';
2
+ export declare class DuckDBInstanceCache {
3
+ private readonly cache;
4
+ constructor();
5
+ getOrCreateInstance(path?: string, options?: Record<string, string>): Promise<DuckDBInstance>;
6
+ private static singletonInstance;
7
+ static get singleton(): DuckDBInstanceCache;
8
+ }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DuckDBInstanceCache = void 0;
7
+ const node_bindings_1 = __importDefault(require("@duckdb/node-bindings"));
8
+ const DuckDBInstance_1 = require("./DuckDBInstance");
9
+ const createConfig_1 = require("./createConfig");
10
+ class DuckDBInstanceCache {
11
+ cache;
12
+ constructor() {
13
+ this.cache = node_bindings_1.default.create_instance_cache();
14
+ }
15
+ async getOrCreateInstance(path, options) {
16
+ const config = (0, createConfig_1.createConfig)(options);
17
+ const db = await node_bindings_1.default.get_or_create_from_cache(this.cache, path, config);
18
+ return new DuckDBInstance_1.DuckDBInstance(db);
19
+ }
20
+ static singletonInstance;
21
+ static get singleton() {
22
+ if (!DuckDBInstanceCache.singletonInstance) {
23
+ DuckDBInstanceCache.singletonInstance = new DuckDBInstanceCache();
24
+ }
25
+ return DuckDBInstanceCache.singletonInstance;
26
+ }
27
+ }
28
+ exports.DuckDBInstanceCache = DuckDBInstanceCache;