@hpcc-js/wasm-duckdb 1.12.0 → 1.13.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.
- package/README.md +581 -16
- package/dist/index.js +13 -10
- package/dist/index.js.map +4 -4
- package/package.json +11 -13
- package/src/duckdb.ts +253 -46
- package/types/duckdb.d.ts +238 -0
- package/types/duckdblib.d.ts +170 -0
- package/types/build/duckdb-browser-eh.worker.d.ts +0 -2
- package/types/build/duckdb-eh.wasm.d.ts +0 -2
- package/types/src/duckdb.d.ts +0 -52
- /package/types/{src/__package__.d.ts → __package__.d.ts} +0 -0
- /package/types/{src/index.d.ts → index.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
# @hpcc-js/wasm-duckdb
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
A WebAssembly wrapper for [DuckDB](https://github.com/duckdb/duckdb), an in-process SQL OLAP database management system. This package provides a consistent loading experience with the rest of the @hpcc-js/wasm library.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ✅ In-process SQL database (no server required)
|
|
8
|
+
- ✅ OLAP-optimized for analytical queries
|
|
9
|
+
- ✅ Full SQL support with DuckDB's rich feature set
|
|
10
|
+
- ✅ Prepared statements with parameter binding
|
|
11
|
+
- ✅ Transaction management (commit/rollback)
|
|
12
|
+
- ✅ Virtual file system for CSV, JSON, and other formats
|
|
13
|
+
- ✅ JSON export of query results
|
|
14
|
+
- ✅ Type-safe value handling
|
|
5
15
|
|
|
6
16
|
## Installation
|
|
7
17
|
|
|
@@ -9,31 +19,586 @@ See [DuckDB](https://github.com/duckdb/duckdb) and [DuckDB-wasm](https://github.
|
|
|
9
19
|
npm install @hpcc-js/wasm-duckdb
|
|
10
20
|
```
|
|
11
21
|
|
|
12
|
-
##
|
|
22
|
+
## Quick Start
|
|
13
23
|
|
|
14
24
|
```typescript
|
|
15
25
|
import { DuckDB } from "@hpcc-js/wasm-duckdb";
|
|
16
26
|
|
|
17
|
-
|
|
18
|
-
const
|
|
27
|
+
// Load the WASM module
|
|
28
|
+
const duckdb = await DuckDB.load();
|
|
29
|
+
|
|
30
|
+
// Create a connection
|
|
31
|
+
const connection = duckdb.connect();
|
|
32
|
+
|
|
33
|
+
// Execute a query
|
|
34
|
+
const result = connection.query("SELECT 'Hello, DuckDB!' AS message");
|
|
35
|
+
console.log(result.getValue(0, 0)); // "Hello, DuckDB!"
|
|
36
|
+
|
|
37
|
+
// Clean up
|
|
38
|
+
result.delete();
|
|
39
|
+
connection.delete();
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## API Reference
|
|
43
|
+
|
|
44
|
+
### DuckDB Class
|
|
45
|
+
|
|
46
|
+
#### Static Methods
|
|
47
|
+
|
|
48
|
+
##### `DuckDB.load(): Promise<DuckDB>`
|
|
49
|
+
Loads and initializes the DuckDB WASM module. Returns a singleton instance.
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
const duckdb = await DuckDB.load();
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
##### `DuckDB.unload(): void`
|
|
56
|
+
Unloads the WASM instance (useful for cleanup in tests).
|
|
57
|
+
|
|
58
|
+
#### Instance Methods
|
|
59
|
+
|
|
60
|
+
##### `version(): string`
|
|
61
|
+
Returns the DuckDB version string.
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
console.log(duckdb.version()); // e.g., "v1.4.3"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
##### `numberOfThreads(): number`
|
|
68
|
+
Returns the number of threads available.
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
console.log(duckdb.numberOfThreads()); // e.g., 1
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
##### `connect(): Connection`
|
|
75
|
+
Creates a new database connection.
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
const connection = duckdb.connect();
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
##### `registerFile(path: string, content: Uint8Array): void`
|
|
82
|
+
Registers a file in the virtual file system with binary content.
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
const csvContent = "id,name\n1,Alice\n2,Bob";
|
|
86
|
+
const bytes = new TextEncoder().encode(csvContent);
|
|
87
|
+
duckdb.registerFile("data.csv", bytes);
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
##### `registerFileString(fileName: string, content: string): void`
|
|
91
|
+
Registers a file in the virtual file system with string content.
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
const data = [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }];
|
|
95
|
+
duckdb.registerFileString("data.json", JSON.stringify(data));
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Connection Class
|
|
99
|
+
|
|
100
|
+
#### Query Execution
|
|
101
|
+
|
|
102
|
+
##### `query(sql: string): MaterializedQueryResult`
|
|
103
|
+
Executes a SQL query and returns the result.
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
const result = connection.query("SELECT * FROM users WHERE age > 18");
|
|
107
|
+
console.log(result.rowCount()); // Number of rows
|
|
108
|
+
result.delete(); // Always clean up!
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
##### `prepare(sql: string): PreparedStatement`
|
|
112
|
+
Creates a prepared statement for repeated execution with different parameters.
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
const stmt = connection.prepare("SELECT * FROM users WHERE id = ?");
|
|
116
|
+
const result = stmt.execute([42]);
|
|
117
|
+
result.delete();
|
|
118
|
+
stmt.delete();
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
##### `interrupt(): void`
|
|
122
|
+
Interrupts the currently running query.
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
connection.interrupt();
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
##### `getQueryProgress(): number`
|
|
129
|
+
Gets the progress of the currently executing query (0.0 to 1.0).
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
const progress = connection.getQueryProgress();
|
|
133
|
+
console.log(`Query is ${progress * 100}% complete`);
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### Transaction Management
|
|
137
|
+
|
|
138
|
+
##### `beginTransaction(): void`
|
|
139
|
+
Starts a new transaction.
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
connection.beginTransaction();
|
|
143
|
+
connection.query("INSERT INTO users VALUES (1, 'Alice')").delete();
|
|
144
|
+
connection.commit();
|
|
145
|
+
```
|
|
19
146
|
|
|
147
|
+
##### `commit(): void`
|
|
148
|
+
Commits the current transaction.
|
|
149
|
+
|
|
150
|
+
##### `rollback(): void`
|
|
151
|
+
Rolls back the current transaction.
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
connection.beginTransaction();
|
|
155
|
+
connection.query("INSERT INTO users VALUES (1, 'Alice')").delete();
|
|
156
|
+
connection.rollback(); // Changes discarded
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
##### `setAutoCommit(enabled: boolean): void`
|
|
160
|
+
Enables or disables auto-commit mode (default: enabled).
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
connection.setAutoCommit(false);
|
|
164
|
+
// Multiple operations in a single transaction
|
|
165
|
+
connection.setAutoCommit(true);
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
##### `isAutoCommit(): boolean`
|
|
169
|
+
Checks if auto-commit is enabled.
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
console.log(connection.isAutoCommit()); // true
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
##### `hasActiveTransaction(): boolean`
|
|
176
|
+
Checks if there's an active transaction.
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
console.log(connection.hasActiveTransaction()); // false
|
|
180
|
+
connection.beginTransaction();
|
|
181
|
+
console.log(connection.hasActiveTransaction()); // true
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### PreparedStatement Class
|
|
185
|
+
|
|
186
|
+
Prepared statements allow you to execute the same query multiple times with different parameters efficiently.
|
|
187
|
+
|
|
188
|
+
##### `execute(params: any[]): QueryResult`
|
|
189
|
+
Executes the prepared statement with the provided parameters.
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
const stmt = connection.prepare("SELECT * FROM users WHERE age > ? AND city = ?");
|
|
193
|
+
const result1 = stmt.execute([18, "New York"]);
|
|
194
|
+
const result2 = stmt.execute([25, "London"]);
|
|
195
|
+
|
|
196
|
+
result1.delete();
|
|
197
|
+
result2.delete();
|
|
198
|
+
stmt.delete();
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Supported parameter types:**
|
|
202
|
+
- `string` - VARCHAR
|
|
203
|
+
- `number` - INTEGER or DOUBLE
|
|
204
|
+
- `boolean` - BOOLEAN
|
|
205
|
+
- `null` or `undefined` - NULL
|
|
206
|
+
|
|
207
|
+
##### `names(): string[]`
|
|
208
|
+
Returns the column names that will be returned by the query.
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
const stmt = connection.prepare("SELECT id, name FROM users");
|
|
212
|
+
console.log(stmt.names()); // ["id", "name"]
|
|
213
|
+
stmt.delete();
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
##### `types(): string[]`
|
|
217
|
+
Returns the column type names.
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
const stmt = connection.prepare("SELECT id, name FROM users");
|
|
221
|
+
console.log(stmt.types()); // ["INTEGER", "VARCHAR"]
|
|
222
|
+
stmt.delete();
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
##### `columnCount(): number`
|
|
226
|
+
Returns the number of columns in the result.
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
console.log(stmt.columnCount()); // 2
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
##### `statementType(): number`
|
|
233
|
+
Returns the statement type as a numeric code.
|
|
234
|
+
|
|
235
|
+
##### `hasError(): boolean`
|
|
236
|
+
Checks if the statement has an error.
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
const stmt = connection.prepare("SELECT * FROM invalid_syntax WHERE");
|
|
240
|
+
if (stmt.hasError()) {
|
|
241
|
+
console.error(stmt.getError());
|
|
242
|
+
}
|
|
243
|
+
stmt.delete();
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
##### `getError(): string`
|
|
247
|
+
Returns the error message if `hasError()` is true.
|
|
248
|
+
|
|
249
|
+
### MaterializedQueryResult Class
|
|
250
|
+
|
|
251
|
+
Represents the result of a query execution.
|
|
252
|
+
|
|
253
|
+
#### Result Metadata
|
|
254
|
+
|
|
255
|
+
##### `rowCount(): bigint`
|
|
256
|
+
Returns the number of rows in the result.
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
const result = connection.query("SELECT * FROM users");
|
|
260
|
+
console.log(Number(result.rowCount())); // e.g., 10
|
|
261
|
+
result.delete();
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
##### `columnCount(): bigint`
|
|
265
|
+
Returns the number of columns in the result.
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
console.log(Number(result.columnCount())); // e.g., 3
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
##### `columnNames(): string[]`
|
|
272
|
+
Returns an array of column names.
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
const result = connection.query("SELECT id, name, age FROM users LIMIT 1");
|
|
276
|
+
console.log(result.columnNames()); // ["id", "name", "age"]
|
|
277
|
+
result.delete();
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
##### `columnName(index: bigint): string`
|
|
281
|
+
Returns the name of a specific column by index.
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
console.log(result.columnName(0n)); // "id"
|
|
285
|
+
console.log(result.columnName(1n)); // "name"
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
##### `columnTypes(): string[]`
|
|
289
|
+
Returns an array of column type names.
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
console.log(result.columnTypes()); // ["INTEGER", "VARCHAR", "INTEGER"]
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
##### `resultType(): number`
|
|
296
|
+
Returns the result type as a numeric code.
|
|
297
|
+
|
|
298
|
+
##### `statementType(): number`
|
|
299
|
+
Returns the statement type that produced this result.
|
|
300
|
+
|
|
301
|
+
#### Data Access
|
|
302
|
+
|
|
303
|
+
##### `getValue(column: number, row: number): any`
|
|
304
|
+
Returns the value at the specified column and row.
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
const result = connection.query("SELECT id, name FROM users LIMIT 1");
|
|
308
|
+
const id = result.getValue(0, 0); // First column, first row
|
|
309
|
+
const name = result.getValue(1, 0); // Second column, first row
|
|
310
|
+
console.log(`User ${id}: ${name}`);
|
|
311
|
+
result.delete();
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**Return types:**
|
|
315
|
+
- `null` for NULL values
|
|
316
|
+
- `boolean` for BOOLEAN columns
|
|
317
|
+
- `number` for numeric columns (TINYINT, SMALLINT, INTEGER, BIGINT, FLOAT, DOUBLE)
|
|
318
|
+
- `string` for VARCHAR and other types
|
|
319
|
+
|
|
320
|
+
##### `toJSON(): string`
|
|
321
|
+
Converts the entire result to a JSON string (array of objects).
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
const result = connection.query("SELECT id, name, age FROM users");
|
|
325
|
+
const json = result.toJSON();
|
|
326
|
+
// Returns: '[{"id":1,"name":"Alice","age":30},{"id":2,"name":"Bob","age":25}]'
|
|
327
|
+
|
|
328
|
+
const data = JSON.parse(json);
|
|
329
|
+
console.log(data[0].name); // "Alice"
|
|
330
|
+
result.delete();
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
**Features:**
|
|
334
|
+
- Returns a JSON array with one object per row
|
|
335
|
+
- Column names become object keys
|
|
336
|
+
- NULL values are represented as `null`
|
|
337
|
+
- Proper JSON escaping for special characters
|
|
338
|
+
- NaN and Infinity are converted to `null`
|
|
339
|
+
|
|
340
|
+
##### `collection(): ColumnDataCollection`
|
|
341
|
+
Returns the underlying column data collection.
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
const collection = result.collection();
|
|
345
|
+
console.log(Number(collection.count())); // Row count
|
|
346
|
+
console.log(Number(collection.columnCount())); // Column count
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
#### Output
|
|
350
|
+
|
|
351
|
+
##### `stringify(): string`
|
|
352
|
+
Returns a string representation of the result.
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
const result = connection.query("SELECT * FROM users LIMIT 3");
|
|
356
|
+
console.log(result.stringify());
|
|
357
|
+
result.delete();
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
##### `print(): void`
|
|
361
|
+
Prints the result to the console.
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
result.print();
|
|
365
|
+
// Outputs formatted table to console
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
#### Error Handling
|
|
369
|
+
|
|
370
|
+
##### `hasError(): boolean`
|
|
371
|
+
Checks if the query resulted in an error.
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
const result = connection.query("SELECT * FROM nonexistent_table");
|
|
375
|
+
if (result.hasError()) {
|
|
376
|
+
console.error("Query failed:", result.getError());
|
|
377
|
+
}
|
|
378
|
+
result.delete();
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
##### `getError(): string`
|
|
382
|
+
Returns the error message if one occurred.
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
const errorMsg = result.getError();
|
|
386
|
+
console.log(errorMsg); // Error message string
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
## Usage Examples
|
|
390
|
+
|
|
391
|
+
### Basic Query
|
|
392
|
+
|
|
393
|
+
```typescript
|
|
394
|
+
import { DuckDB } from "@hpcc-js/wasm-duckdb";
|
|
395
|
+
|
|
396
|
+
const duckdb = await DuckDB.load();
|
|
397
|
+
const connection = duckdb.connect();
|
|
398
|
+
|
|
399
|
+
const result = connection.query(`
|
|
400
|
+
SELECT
|
|
401
|
+
id,
|
|
402
|
+
name,
|
|
403
|
+
age
|
|
404
|
+
FROM (VALUES
|
|
405
|
+
(1, 'Alice', 30),
|
|
406
|
+
(2, 'Bob', 25),
|
|
407
|
+
(3, 'Charlie', 35)
|
|
408
|
+
) AS users(id, name, age)
|
|
409
|
+
WHERE age > 25
|
|
410
|
+
`);
|
|
411
|
+
|
|
412
|
+
console.log(`Found ${result.rowCount()} users`);
|
|
413
|
+
for (let i = 0; i < Number(result.rowCount()); i++) {
|
|
414
|
+
const id = result.getValue(0, i);
|
|
415
|
+
const name = result.getValue(1, i);
|
|
416
|
+
const age = result.getValue(2, i);
|
|
417
|
+
console.log(`${id}: ${name} (${age} years old)`);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
result.delete();
|
|
421
|
+
connection.delete();
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### Prepared Statements
|
|
425
|
+
|
|
426
|
+
```typescript
|
|
427
|
+
const connection = duckdb.connect();
|
|
428
|
+
|
|
429
|
+
// Create a table
|
|
430
|
+
connection.query("CREATE TABLE users (id INTEGER, name VARCHAR, age INTEGER)").delete();
|
|
431
|
+
|
|
432
|
+
// Insert data using prepared statement
|
|
433
|
+
const insertStmt = connection.prepare("INSERT INTO users VALUES (?, ?, ?)");
|
|
434
|
+
insertStmt.execute([1, "Alice", 30]).delete();
|
|
435
|
+
insertStmt.execute([2, "Bob", 25]).delete();
|
|
436
|
+
insertStmt.execute([3, "Charlie", 35]).delete();
|
|
437
|
+
insertStmt.delete();
|
|
438
|
+
|
|
439
|
+
// Query with prepared statement
|
|
440
|
+
const queryStmt = connection.prepare("SELECT * FROM users WHERE age > ?");
|
|
441
|
+
const result = queryStmt.execute([26]);
|
|
442
|
+
|
|
443
|
+
console.log(result.toJSON());
|
|
444
|
+
// [{"id":1,"name":"Alice","age":30},{"id":3,"name":"Charlie","age":35}]
|
|
445
|
+
|
|
446
|
+
result.delete();
|
|
447
|
+
queryStmt.delete();
|
|
448
|
+
connection.delete();
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### Working with JSON Files
|
|
452
|
+
|
|
453
|
+
```typescript
|
|
454
|
+
const duckdb = await DuckDB.load();
|
|
455
|
+
const connection = duckdb.connect();
|
|
456
|
+
|
|
457
|
+
// Register JSON data as a file
|
|
20
458
|
const data = [
|
|
21
|
-
{ "
|
|
22
|
-
{ "
|
|
459
|
+
{ product: "Laptop", price: 999.99, quantity: 5 },
|
|
460
|
+
{ product: "Mouse", price: 29.99, quantity: 20 },
|
|
461
|
+
{ product: "Keyboard", price: 79.99, quantity: 15 }
|
|
23
462
|
];
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
463
|
+
duckdb.registerFileString("products.json", JSON.stringify(data));
|
|
464
|
+
|
|
465
|
+
// Query the JSON file
|
|
466
|
+
const result = connection.query(`
|
|
467
|
+
SELECT
|
|
468
|
+
product,
|
|
469
|
+
price,
|
|
470
|
+
quantity,
|
|
471
|
+
price * quantity AS total_value
|
|
472
|
+
FROM read_json_auto('products.json')
|
|
473
|
+
ORDER BY total_value DESC
|
|
474
|
+
`);
|
|
475
|
+
|
|
476
|
+
console.log(result.toJSON());
|
|
477
|
+
result.delete();
|
|
478
|
+
connection.delete();
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### Working with CSV Files
|
|
482
|
+
|
|
483
|
+
```typescript
|
|
484
|
+
const csvData = `id,name,department,salary
|
|
485
|
+
1,Alice,Engineering,120000
|
|
486
|
+
2,Bob,Sales,80000
|
|
487
|
+
3,Charlie,Engineering,110000
|
|
488
|
+
4,Diana,HR,75000`;
|
|
489
|
+
|
|
490
|
+
duckdb.registerFileString("employees.csv", csvData);
|
|
491
|
+
|
|
492
|
+
const result = connection.query(`
|
|
493
|
+
SELECT
|
|
494
|
+
department,
|
|
495
|
+
COUNT(*) as employee_count,
|
|
496
|
+
AVG(salary) as avg_salary
|
|
497
|
+
FROM read_csv_auto('employees.csv')
|
|
498
|
+
GROUP BY department
|
|
499
|
+
ORDER BY avg_salary DESC
|
|
500
|
+
`);
|
|
501
|
+
|
|
502
|
+
result.print(); // Prints formatted table
|
|
503
|
+
result.delete();
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### Transaction Management
|
|
507
|
+
|
|
508
|
+
```typescript
|
|
509
|
+
const connection = duckdb.connect();
|
|
510
|
+
|
|
511
|
+
connection.query("CREATE TABLE accounts (id INTEGER, balance DECIMAL)").delete();
|
|
512
|
+
connection.query("INSERT INTO accounts VALUES (1, 1000), (2, 500)").delete();
|
|
513
|
+
|
|
514
|
+
// Transfer money between accounts
|
|
515
|
+
connection.setAutoCommit(false);
|
|
516
|
+
connection.beginTransaction();
|
|
517
|
+
|
|
518
|
+
try {
|
|
519
|
+
connection.query("UPDATE accounts SET balance = balance - 200 WHERE id = 1").delete();
|
|
520
|
+
connection.query("UPDATE accounts SET balance = balance + 200 WHERE id = 2").delete();
|
|
521
|
+
connection.commit();
|
|
522
|
+
console.log("Transfer successful");
|
|
523
|
+
} catch (error) {
|
|
524
|
+
connection.rollback();
|
|
525
|
+
console.error("Transfer failed, rolled back");
|
|
32
526
|
}
|
|
33
527
|
|
|
34
|
-
|
|
528
|
+
connection.delete();
|
|
35
529
|
```
|
|
36
530
|
|
|
531
|
+
### JSON Export
|
|
532
|
+
|
|
533
|
+
```typescript
|
|
534
|
+
const result = connection.query("SELECT * FROM users ORDER BY age");
|
|
535
|
+
|
|
536
|
+
// Export entire result as JSON
|
|
537
|
+
const jsonString = result.toJSON();
|
|
538
|
+
|
|
539
|
+
// Save to file or send to API
|
|
540
|
+
console.log(jsonString);
|
|
541
|
+
// [{"id":2,"name":"Bob","age":25},{"id":1,"name":"Alice","age":30},...]
|
|
542
|
+
|
|
543
|
+
// Parse back to JavaScript
|
|
544
|
+
const users = JSON.parse(jsonString);
|
|
545
|
+
users.forEach(user => {
|
|
546
|
+
console.log(`${user.name} is ${user.age} years old`);
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
result.delete();
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
### Error Handling
|
|
553
|
+
|
|
554
|
+
```typescript
|
|
555
|
+
const connection = duckdb.connect();
|
|
556
|
+
|
|
557
|
+
// Query error handling
|
|
558
|
+
const result = connection.query("SELECT * FROM nonexistent_table");
|
|
559
|
+
if (result.hasError()) {
|
|
560
|
+
console.error("Query error:", result.getError());
|
|
561
|
+
} else {
|
|
562
|
+
console.log("Query succeeded");
|
|
563
|
+
}
|
|
564
|
+
result.delete();
|
|
565
|
+
|
|
566
|
+
// Prepared statement error handling
|
|
567
|
+
const stmt = connection.prepare("SELECT * FROM invalid_syntax WHERE");
|
|
568
|
+
if (stmt.hasError()) {
|
|
569
|
+
console.error("Statement preparation error:", stmt.getError());
|
|
570
|
+
}
|
|
571
|
+
stmt.delete();
|
|
572
|
+
|
|
573
|
+
connection.delete();
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
## Memory Management
|
|
577
|
+
|
|
578
|
+
**Important:** Always call `.delete()` on results, prepared statements, and connections when done to free memory:
|
|
579
|
+
|
|
580
|
+
```typescript
|
|
581
|
+
const result = connection.query("SELECT * FROM users");
|
|
582
|
+
// Use result...
|
|
583
|
+
result.delete(); // Clean up!
|
|
584
|
+
|
|
585
|
+
const stmt = connection.prepare("SELECT * FROM users WHERE id = ?");
|
|
586
|
+
// Use stmt...
|
|
587
|
+
stmt.delete(); // Clean up!
|
|
588
|
+
|
|
589
|
+
connection.delete(); // Clean up when done with connection
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
## TypeScript Support
|
|
593
|
+
|
|
594
|
+
This package includes full TypeScript type definitions for type-safe development.
|
|
595
|
+
|
|
37
596
|
## Reference
|
|
38
597
|
|
|
39
598
|
* [API Documentation](https://hpcc-systems.github.io/hpcc-js-wasm/duckdb/src/duckdb/classes/DuckDB.html)
|
|
599
|
+
* [DuckDB Documentation](https://duckdb.org/docs/)
|
|
600
|
+
* [DuckDB WASM](https://github.com/duckdb/duckdb-wasm)
|
|
601
|
+
|
|
602
|
+
## License
|
|
603
|
+
|
|
604
|
+
See the root package for license information.
|