@sqlrooms/duckdb 0.28.0-rc.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +70 -31
- package/dist/DuckDbSlice.d.ts.map +1 -1
- package/dist/DuckDbSlice.js +125 -2
- package/dist/DuckDbSlice.js.map +1 -1
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -147,6 +147,9 @@ function ArrowTableSchemaExample() {
|
|
|
147
147
|
### Using the Store for Direct Database Operations
|
|
148
148
|
|
|
149
149
|
```tsx
|
|
150
|
+
import {useRoomStore} from './store';
|
|
151
|
+
import {Button} from '@sqlrooms/ui';
|
|
152
|
+
|
|
150
153
|
function DatabaseManager() {
|
|
151
154
|
const createTableFromQuery = useRoomStore(
|
|
152
155
|
(state) => state.db.createTableFromQuery,
|
|
@@ -183,10 +186,10 @@ function DatabaseManager() {
|
|
|
183
186
|
|
|
184
187
|
return (
|
|
185
188
|
<div>
|
|
186
|
-
<
|
|
187
|
-
<
|
|
188
|
-
<
|
|
189
|
-
<
|
|
189
|
+
<Button onClick={handleCreateTable}>Create Filtered Users Table</Button>
|
|
190
|
+
<Button onClick={handleAddTable}>Add New Users Table</Button>
|
|
191
|
+
<Button onClick={handleDropTable}>Drop Old Table</Button>
|
|
192
|
+
<Button onClick={refreshTableSchemas}>Refresh Schemas</Button>
|
|
190
193
|
|
|
191
194
|
<h3>Available Tables:</h3>
|
|
192
195
|
<ul>
|
|
@@ -205,18 +208,32 @@ function DatabaseManager() {
|
|
|
205
208
|
|
|
206
209
|
```tsx
|
|
207
210
|
import {makeQualifiedTableName} from '@sqlrooms/duckdb';
|
|
211
|
+
import {useRoomStore} from './store';
|
|
212
|
+
import {Button} from '@sqlrooms/ui';
|
|
208
213
|
|
|
209
|
-
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
214
|
+
function QualifiedTableOps() {
|
|
215
|
+
const createTableFromQuery = useRoomStore(
|
|
216
|
+
(state) => state.db.createTableFromQuery,
|
|
217
|
+
);
|
|
218
|
+
const dropTable = useRoomStore((state) => state.db.dropTable);
|
|
219
|
+
const checkTableExists = useRoomStore((state) => state.db.checkTableExists);
|
|
220
|
+
|
|
221
|
+
const run = async () => {
|
|
222
|
+
// Support for database.schema.table naming
|
|
223
|
+
const qualifiedTable = makeQualifiedTableName({
|
|
224
|
+
database: 'mydb',
|
|
225
|
+
schema: 'public',
|
|
226
|
+
table: 'users',
|
|
227
|
+
});
|
|
215
228
|
|
|
216
|
-
|
|
217
|
-
await
|
|
218
|
-
|
|
219
|
-
|
|
229
|
+
await createTableFromQuery(qualifiedTable, 'SELECT * FROM source_table');
|
|
230
|
+
const tableExists = await checkTableExists(qualifiedTable);
|
|
231
|
+
console.log('Table exists after create:', tableExists);
|
|
232
|
+
await dropTable(qualifiedTable);
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
return <Button onClick={() => void run()}>Run qualified table ops</Button>;
|
|
236
|
+
}
|
|
220
237
|
```
|
|
221
238
|
|
|
222
239
|
## Loading Data from Files
|
|
@@ -225,6 +242,8 @@ const tableExists = await checkTableExists(qualifiedTable);
|
|
|
225
242
|
|
|
226
243
|
```tsx
|
|
227
244
|
import {loadCSV, loadJSON, loadParquet, loadObjects} from '@sqlrooms/duckdb';
|
|
245
|
+
import {useRoomStore} from './store';
|
|
246
|
+
import {Button} from '@sqlrooms/ui';
|
|
228
247
|
|
|
229
248
|
function DataLoader() {
|
|
230
249
|
const getConnector = useRoomStore((state) => state.db.getConnector);
|
|
@@ -263,7 +282,7 @@ function DataLoader() {
|
|
|
263
282
|
if (e.target.files?.[0]) handleLoadCSV(e.target.files[0]);
|
|
264
283
|
}}
|
|
265
284
|
/>
|
|
266
|
-
<
|
|
285
|
+
<Button onClick={handleLoadObjects}>Load Sample Data</Button>
|
|
267
286
|
</div>
|
|
268
287
|
);
|
|
269
288
|
}
|
|
@@ -272,21 +291,32 @@ function DataLoader() {
|
|
|
272
291
|
### Using the Connector Directly
|
|
273
292
|
|
|
274
293
|
```tsx
|
|
294
|
+
import * as arrow from 'apache-arrow';
|
|
295
|
+
import {useRoomStore} from './store';
|
|
296
|
+
|
|
275
297
|
function AdvancedDataLoader() {
|
|
276
|
-
const
|
|
298
|
+
const getConnector = useRoomStore((state) => state.db.getConnector);
|
|
277
299
|
|
|
278
300
|
const handleFileUpload = async (file: File) => {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
301
|
+
try {
|
|
302
|
+
const connector = await getConnector();
|
|
303
|
+
await connector.loadFile(file, 'uploaded_data', {
|
|
304
|
+
method: 'auto', // Auto-detect file type
|
|
305
|
+
replace: true,
|
|
306
|
+
temp: false,
|
|
307
|
+
});
|
|
308
|
+
} catch (error) {
|
|
309
|
+
console.error('Failed to load uploaded file:', error);
|
|
310
|
+
}
|
|
285
311
|
};
|
|
286
312
|
|
|
287
313
|
const handleLoadArrowTable = async (arrowTable: arrow.Table) => {
|
|
288
|
-
|
|
289
|
-
|
|
314
|
+
try {
|
|
315
|
+
const connector = await getConnector();
|
|
316
|
+
await connector.loadArrow(arrowTable, 'arrow_data');
|
|
317
|
+
} catch (error) {
|
|
318
|
+
console.error('Failed to load Arrow table:', error);
|
|
319
|
+
}
|
|
290
320
|
};
|
|
291
321
|
|
|
292
322
|
return (
|
|
@@ -294,7 +324,9 @@ function AdvancedDataLoader() {
|
|
|
294
324
|
type="file"
|
|
295
325
|
accept=".csv,.json,.parquet"
|
|
296
326
|
onChange={(e) => {
|
|
297
|
-
if (e.target.files?.[0])
|
|
327
|
+
if (e.target.files?.[0]) {
|
|
328
|
+
void handleFileUpload(e.target.files[0]);
|
|
329
|
+
}
|
|
298
330
|
}}
|
|
299
331
|
/>
|
|
300
332
|
);
|
|
@@ -305,6 +337,7 @@ function AdvancedDataLoader() {
|
|
|
305
337
|
|
|
306
338
|
```tsx
|
|
307
339
|
import {useExportToCsv} from '@sqlrooms/duckdb';
|
|
340
|
+
import {Button} from '@sqlrooms/ui';
|
|
308
341
|
|
|
309
342
|
function ExportButton() {
|
|
310
343
|
const {exportToCsv} = useExportToCsv();
|
|
@@ -313,7 +346,7 @@ function ExportButton() {
|
|
|
313
346
|
await exportToCsv('SELECT * FROM users ORDER BY name', 'users_export.csv');
|
|
314
347
|
};
|
|
315
348
|
|
|
316
|
-
return <
|
|
349
|
+
return <Button onClick={handleExport}>Export to CSV</Button>;
|
|
317
350
|
}
|
|
318
351
|
```
|
|
319
352
|
|
|
@@ -322,9 +355,11 @@ function ExportButton() {
|
|
|
322
355
|
### Basic direct usage
|
|
323
356
|
|
|
324
357
|
```tsx
|
|
358
|
+
import {roomStore} from './store';
|
|
359
|
+
|
|
325
360
|
async function executeCustomQuery() {
|
|
326
|
-
//
|
|
327
|
-
const connector =
|
|
361
|
+
// Plain TS/JS usage: read connector from the store API directly.
|
|
362
|
+
const connector = roomStore.getState().db.connector;
|
|
328
363
|
|
|
329
364
|
// QueryHandle is promise-like – await it directly
|
|
330
365
|
const result = await connector.query('SELECT COUNT(*) AS count FROM users');
|
|
@@ -338,12 +373,14 @@ async function executeCustomQuery() {
|
|
|
338
373
|
### Cancellation examples
|
|
339
374
|
|
|
340
375
|
```tsx
|
|
376
|
+
import {roomStore} from './store';
|
|
377
|
+
|
|
341
378
|
async function cancelExample() {
|
|
342
|
-
const connector =
|
|
379
|
+
const connector = roomStore.getState().db.connector;
|
|
343
380
|
|
|
344
381
|
// 1. Manual cancel via the handle
|
|
345
382
|
const query = connector.query('SELECT * FROM large_table');
|
|
346
|
-
setTimeout(() =>
|
|
383
|
+
setTimeout(() => query.cancel(), 2000); // cancel after 2 s
|
|
347
384
|
await query; // throws if cancelled
|
|
348
385
|
|
|
349
386
|
// 2. Composable cancellation – many queries, one controller
|
|
@@ -358,6 +395,8 @@ async function cancelExample() {
|
|
|
358
395
|
### Advanced operations with the Zustand store
|
|
359
396
|
|
|
360
397
|
```tsx
|
|
398
|
+
import {Button} from '@sqlrooms/ui';
|
|
399
|
+
|
|
361
400
|
function AdvancedOperations() {
|
|
362
401
|
const executeSql = useRoomStore((s) => s.db.executeSql);
|
|
363
402
|
const sqlSelectToJson = useRoomStore((s) => s.db.sqlSelectToJson);
|
|
@@ -380,7 +419,7 @@ function AdvancedOperations() {
|
|
|
380
419
|
console.log('Table exists:', exists);
|
|
381
420
|
};
|
|
382
421
|
|
|
383
|
-
return <
|
|
422
|
+
return <Button onClick={handleAdvancedQuery}>Run Advanced Operations</Button>;
|
|
384
423
|
}
|
|
385
424
|
```
|
|
386
425
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DuckDbSlice.d.ts","sourceRoot":"","sources":["../src/DuckDbSlice.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,SAAS,EACT,YAAY,EACZ,eAAe,EAMf,kBAAkB,EAClB,WAAW,EAGZ,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,kBAAkB,
|
|
1
|
+
{"version":3,"file":"DuckDbSlice.d.ts","sourceRoot":"","sources":["../src/DuckDbSlice.ts"],"names":[],"mappings":"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"}
|
package/dist/DuckDbSlice.js
CHANGED
|
@@ -1,9 +1,38 @@
|
|
|
1
1
|
import { createDbSchemaTrees, escapeVal, getColValAsNumber, isQualifiedTableName, joinStatements, makeQualifiedTableName, separateLastStatement, } from '@sqlrooms/duckdb-core';
|
|
2
|
-
import { createSlice, useBaseRoomStore, } from '@sqlrooms/room-store';
|
|
2
|
+
import { createSlice, registerCommandsForOwner, unregisterCommandsForOwner, useBaseRoomStore, } from '@sqlrooms/room-store';
|
|
3
3
|
import * as arrow from 'apache-arrow';
|
|
4
4
|
import deepEquals from 'fast-deep-equal';
|
|
5
5
|
import { produce } from 'immer';
|
|
6
|
+
import { z } from 'zod';
|
|
6
7
|
import { createWasmDuckDbConnector } from './connectors/createDuckDbConnector';
|
|
8
|
+
const DUCKDB_COMMAND_OWNER = '@sqlrooms/duckdb';
|
|
9
|
+
const DropTableCommandInput = z.object({
|
|
10
|
+
tableName: z.string().describe('Name of the table to drop.'),
|
|
11
|
+
});
|
|
12
|
+
const CreateTableFromQueryCommandInput = z.object({
|
|
13
|
+
tableName: z.string().describe('Name of the table or view to create.'),
|
|
14
|
+
query: z.string().describe('SQL query used to populate the table/view.'),
|
|
15
|
+
replace: z
|
|
16
|
+
.boolean()
|
|
17
|
+
.optional()
|
|
18
|
+
.default(true)
|
|
19
|
+
.describe('Whether to replace existing table/view with the same name.'),
|
|
20
|
+
view: z
|
|
21
|
+
.boolean()
|
|
22
|
+
.optional()
|
|
23
|
+
.default(false)
|
|
24
|
+
.describe('Whether to create a view instead of a table.'),
|
|
25
|
+
temp: z
|
|
26
|
+
.boolean()
|
|
27
|
+
.optional()
|
|
28
|
+
.default(false)
|
|
29
|
+
.describe('Whether to create a temporary object.'),
|
|
30
|
+
allowMultipleStatements: z
|
|
31
|
+
.boolean()
|
|
32
|
+
.optional()
|
|
33
|
+
.default(false)
|
|
34
|
+
.describe('Allow multiple SQL statements where the final one is SELECT.'),
|
|
35
|
+
});
|
|
7
36
|
function isDuckDbPlaceholderViewColumn(columnName, columnType) {
|
|
8
37
|
return columnName === '__' && columnType.toUpperCase() === 'UNKNOWN';
|
|
9
38
|
}
|
|
@@ -11,7 +40,7 @@ function isDuckDbPlaceholderViewColumn(columnName, columnType) {
|
|
|
11
40
|
* Create a DuckDB slice for managing the connector
|
|
12
41
|
*/
|
|
13
42
|
export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), } = {}) {
|
|
14
|
-
return createSlice((set, get) => {
|
|
43
|
+
return createSlice((set, get, store) => {
|
|
15
44
|
return {
|
|
16
45
|
db: {
|
|
17
46
|
connector, // Will be initialized during init
|
|
@@ -32,12 +61,14 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), } =
|
|
|
32
61
|
initialize: async () => {
|
|
33
62
|
await get().db.connector.initialize();
|
|
34
63
|
await get().db.refreshTableSchemas();
|
|
64
|
+
registerCommandsForOwner(store, DUCKDB_COMMAND_OWNER, createDuckDbCommands());
|
|
35
65
|
},
|
|
36
66
|
getConnector: async () => {
|
|
37
67
|
await get().db.connector.initialize();
|
|
38
68
|
return get().db.connector;
|
|
39
69
|
},
|
|
40
70
|
destroy: async () => {
|
|
71
|
+
unregisterCommandsForOwner(store, DUCKDB_COMMAND_OWNER);
|
|
41
72
|
try {
|
|
42
73
|
if (get().db.connector) {
|
|
43
74
|
await get().db.connector.destroy();
|
|
@@ -359,6 +390,98 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), } =
|
|
|
359
390
|
};
|
|
360
391
|
});
|
|
361
392
|
}
|
|
393
|
+
function createDuckDbCommands() {
|
|
394
|
+
return [
|
|
395
|
+
{
|
|
396
|
+
id: 'db.refresh-table-schemas',
|
|
397
|
+
name: 'Refresh table schemas',
|
|
398
|
+
description: 'Reload table and schema metadata from DuckDB',
|
|
399
|
+
group: 'Database',
|
|
400
|
+
keywords: ['duckdb', 'database', 'refresh', 'tables', 'schemas'],
|
|
401
|
+
metadata: {
|
|
402
|
+
readOnly: true,
|
|
403
|
+
idempotent: true,
|
|
404
|
+
riskLevel: 'low',
|
|
405
|
+
},
|
|
406
|
+
isEnabled: ({ getState }) => !getState().db.isRefreshingTableSchemas,
|
|
407
|
+
execute: async ({ getState }) => {
|
|
408
|
+
await getState().db.refreshTableSchemas();
|
|
409
|
+
return {
|
|
410
|
+
success: true,
|
|
411
|
+
commandId: 'db.refresh-table-schemas',
|
|
412
|
+
message: 'Table schemas refreshed.',
|
|
413
|
+
};
|
|
414
|
+
},
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
id: 'db.drop-table',
|
|
418
|
+
name: 'Drop table',
|
|
419
|
+
description: 'Drop a table from DuckDB by name',
|
|
420
|
+
group: 'Database',
|
|
421
|
+
keywords: ['duckdb', 'database', 'drop', 'table', 'delete'],
|
|
422
|
+
inputSchema: DropTableCommandInput,
|
|
423
|
+
inputDescription: 'Provide a tableName to remove from DuckDB.',
|
|
424
|
+
metadata: {
|
|
425
|
+
readOnly: false,
|
|
426
|
+
idempotent: true,
|
|
427
|
+
riskLevel: 'high',
|
|
428
|
+
requiresConfirmation: true,
|
|
429
|
+
},
|
|
430
|
+
validateInput: async (input, { getState }) => {
|
|
431
|
+
const { tableName } = input;
|
|
432
|
+
const exists = await getState().db.checkTableExists(tableName);
|
|
433
|
+
if (!exists) {
|
|
434
|
+
throw new Error(`Table "${tableName}" does not exist.`);
|
|
435
|
+
}
|
|
436
|
+
},
|
|
437
|
+
execute: async ({ getState }, input) => {
|
|
438
|
+
const { tableName } = input;
|
|
439
|
+
await getState().db.dropTable(tableName);
|
|
440
|
+
return {
|
|
441
|
+
success: true,
|
|
442
|
+
commandId: 'db.drop-table',
|
|
443
|
+
message: `Dropped table "${tableName}".`,
|
|
444
|
+
};
|
|
445
|
+
},
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
id: 'db.create-table-from-query',
|
|
449
|
+
name: 'Create table from query',
|
|
450
|
+
description: 'Create a table or view from a SQL query',
|
|
451
|
+
group: 'Database',
|
|
452
|
+
keywords: ['duckdb', 'database', 'create', 'table', 'view', 'query'],
|
|
453
|
+
inputSchema: CreateTableFromQueryCommandInput,
|
|
454
|
+
inputDescription: 'Provide tableName and query, with optional replace/view/temp flags.',
|
|
455
|
+
metadata: {
|
|
456
|
+
readOnly: false,
|
|
457
|
+
idempotent: false,
|
|
458
|
+
riskLevel: 'medium',
|
|
459
|
+
},
|
|
460
|
+
validateInput: (input) => {
|
|
461
|
+
const { query } = input;
|
|
462
|
+
if (!query.trim()) {
|
|
463
|
+
throw new Error('Query cannot be empty.');
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
execute: async ({ getState }, input) => {
|
|
467
|
+
const { tableName, query, replace, view, temp, allowMultipleStatements } = input;
|
|
468
|
+
const result = await getState().db.createTableFromQuery(tableName, query, {
|
|
469
|
+
replace,
|
|
470
|
+
view,
|
|
471
|
+
temp,
|
|
472
|
+
allowMultipleStatements,
|
|
473
|
+
});
|
|
474
|
+
await getState().db.refreshTableSchemas();
|
|
475
|
+
return {
|
|
476
|
+
success: true,
|
|
477
|
+
commandId: 'db.create-table-from-query',
|
|
478
|
+
message: `Created ${view ? 'view' : 'table'} "${tableName}".`,
|
|
479
|
+
data: result,
|
|
480
|
+
};
|
|
481
|
+
},
|
|
482
|
+
},
|
|
483
|
+
];
|
|
484
|
+
}
|
|
362
485
|
/**
|
|
363
486
|
* @internal
|
|
364
487
|
* Select values from the room store that includes the DuckDB slice.
|
package/dist/DuckDbSlice.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DuckDbSlice.js","sourceRoot":"","sources":["../src/DuckDbSlice.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createDbSchemaTrees,\n DataTable,\n DbSchemaNode,\n DuckDbConnector,\n escapeVal,\n getColValAsNumber,\n isQualifiedTableName,\n joinStatements,\n makeQualifiedTableName,\n QualifiedTableName,\n QueryHandle,\n separateLastStatement,\n TableColumn,\n} from '@sqlrooms/duckdb-core';\nimport {\n BaseRoomStoreState,\n createSlice,\n useBaseRoomStore,\n} from '@sqlrooms/room-store';\nimport * as arrow from 'apache-arrow';\nimport deepEquals from 'fast-deep-equal';\nimport {produce} from 'immer';\nimport {StateCreator} from 'zustand';\nimport {createWasmDuckDbConnector} from './connectors/createDuckDbConnector';\n\nfunction isDuckDbPlaceholderViewColumn(\n columnName: string,\n columnType: string,\n): boolean {\n return columnName === '__' && columnType.toUpperCase() === 'UNKNOWN';\n}\n\nexport type SchemaAndDatabase = {\n schema?: string;\n database?: string;\n};\n\n/**\n * State and actions for the DuckDB slice\n */\nexport type DuckDbSliceState = {\n db: {\n /**\n * The DuckDB connector instance\n */\n connector: DuckDbConnector;\n /**\n * @deprecated We shouldn't limit the schema to a single one.\n */\n schema: string;\n\n currentSchema: string | undefined;\n currentDatabase: string | undefined;\n\n /**\n * Cache of refreshed table schemas\n */\n tables: DataTable[];\n /**\n * Cache of row counts for tables\n */\n tableRowCounts: {[tableName: string]: number};\n /**\n * Cache of schema trees for tables\n */\n schemaTrees?: DbSchemaNode[];\n /**\n * Cache of currently running query handles.\n * This is only used for running queries to deduplicate them (especially for useSql),\n * the cache is cleared when the query is completed.\n */\n queryCache: {[key: string]: QueryHandle};\n /**\n * Whether the table schemas are being refreshed\n */\n isRefreshingTableSchemas: boolean;\n\n /**\n * Set a new DuckDB connector\n */\n setConnector: (connector: DuckDbConnector) => void;\n\n /**\n * Initialize the connector (creates a WasmDuckDbConnector if none exists)\n */\n initialize: () => Promise<void>;\n\n /**\n * Close and clean up the connector\n */\n destroy: () => Promise<void>;\n\n /**\n * Add a table to the room.\n * @param tableName - The name of the table to add.\n * @param data - The data to add to the table: an arrow table or an array of records.\n * @returns A promise that resolves to the table that was added.\n */\n addTable(\n tableName: string | QualifiedTableName,\n data: arrow.Table | Record<string, unknown>[],\n ): Promise<DataTable>;\n\n /**\n * Load the schemas of the tables in the database.\n */\n loadTableSchemas(\n filter?: SchemaAndDatabase & {table?: string},\n ): Promise<DataTable[]>;\n\n /**\n * @deprecated Use findTableByName instead\n */\n getTable(tableName: string): DataTable | undefined;\n\n /**\n * @internal Avoid using this directly, it's for internal use.\n */\n setTableRowCount(\n tableName: string | QualifiedTableName,\n rowCount: number,\n ): void;\n\n /**\n * Find a table by name in the last refreshed table schemas.\n * If no schema or database is provided, the table will be found in the current schema\n * and database (from last table schemas refresh).\n * @param tableName - The name of the table to find or a qualified table name.\n * @returns The table or undefined if not found.\n */\n findTableByName(\n tableName: string | QualifiedTableName,\n ): DataTable | undefined;\n\n /**\n * Refresh table schemas from the database.\n * @returns A promise that resolves to the updated tables.\n */\n refreshTableSchemas(): Promise<DataTable[]>;\n /**\n * Get the connector. If it's not initialized, it will be initialized.\n */\n getConnector: () => Promise<DuckDbConnector>;\n\n /**\n * @deprecated Use .loadTableRowCount() instead\n */\n getTableRowCount: (table: string, schema?: string) => Promise<number>;\n\n /**\n * Load the row count of a table\n */\n loadTableRowCount: (\n tableName: string | QualifiedTableName,\n ) => Promise<number>;\n\n /**\n * Execute a query with query handle (not result) caching and deduplication\n * @param query - The SQL query to execute\n * @returns The QueryHandle for the query or null if disabled\n */\n executeSql: (query: string) => Promise<QueryHandle | null>;\n\n /**\n * @deprecated Use .tables or .loadTableSchemas() instead\n */\n getTables: (schema?: string) => Promise<string[]>;\n\n /**\n * @deprecated Use .loadTableSchemas() instead\n */\n getTableSchema: (\n tableName: string,\n schema?: string,\n ) => Promise<DataTable | undefined>;\n\n /**\n * @deprecated Use .tables or .loadTableSchemas() instead\n */\n getTableSchemas: (schema?: string) => Promise<DataTable[]>;\n\n /**\n * Check if a table exists\n */\n checkTableExists: (\n tableName: string | QualifiedTableName,\n ) => Promise<boolean>;\n\n /**\n * Delete a table with optional schema and database\n * @param tableName - The name of the table to delete (qualified or plain)\n */\n dropTable: (tableName: string | QualifiedTableName) => Promise<void>;\n\n /**\n * Create a table or view from a query.\n * @param tableName - The name of the table/view to create.\n * @param query - The query to create the table/view from.\n * @param options - Creation options.\n * @returns The table/view name and rowCount (undefined for views).\n */\n createTableFromQuery: (\n tableName: string | QualifiedTableName,\n query: string,\n options?: {\n replace?: boolean;\n temp?: boolean;\n view?: boolean;\n allowMultipleStatements?: boolean;\n abortSignal?: AbortSignal;\n },\n ) => Promise<{\n tableName: string | QualifiedTableName;\n rowCount: number | undefined;\n }>;\n\n /**\n * Parse a SQL SELECT statement to JSON\n * @param sql - The SQL SELECT statement to parse.\n * @returns A promise that resolves to the parsed JSON.\n */\n sqlSelectToJson: (sql: string) => Promise<\n | {\n error: true;\n error_type: string;\n error_message: string;\n error_subtype: string;\n position: string;\n }\n | {\n error: false;\n statements: {\n node: {\n from_table: {\n alias: string;\n show_type: string;\n table_name: string;\n };\n select_list: Record<string, unknown>[];\n type: string;\n };\n }[];\n }\n >;\n };\n};\n\ntype CreateDuckDbSliceProps = {\n connector?: DuckDbConnector;\n};\n\n/**\n * Create a DuckDB slice for managing the connector\n */\nexport function createDuckDbSlice({\n connector = createWasmDuckDbConnector(),\n}: CreateDuckDbSliceProps = {}): StateCreator<DuckDbSliceState> {\n return createSlice<DuckDbSliceState, BaseRoomStoreState & DuckDbSliceState>(\n (set, get) => {\n return {\n db: {\n connector, // Will be initialized during init\n schema: 'main', // TODO: remove schema, we should not limit the schema to a single one.\n currentSchema: undefined,\n currentDatabase: undefined,\n isRefreshingTableSchemas: false,\n tables: [],\n tableRowCounts: {},\n schemaTrees: undefined,\n queryCache: {},\n\n setConnector: (connector: DuckDbConnector) => {\n set(\n produce((state) => {\n state.config.dataSources = [];\n state.db.connector = connector;\n }),\n );\n },\n\n initialize: async () => {\n await get().db.connector.initialize();\n await get().db.refreshTableSchemas();\n },\n\n getConnector: async () => {\n await get().db.connector.initialize();\n return get().db.connector;\n },\n\n destroy: async () => {\n try {\n if (get().db.connector) {\n await get().db.connector.destroy();\n }\n } catch (err) {\n console.error('Error during DuckDB shutdown:', err);\n }\n },\n\n /**\n * Creates a table or view from a SQL query.\n * @param tableName - Name of the table/view to create\n * @param query - SQL query (must be a SELECT statement, or multiple statements ending with a SELECT when allowMultipleStatements is true)\n * @param options - Creation options\n * @param options.replace - If true, uses CREATE OR REPLACE (default: true)\n * @param options.temp - If true, creates a temporary table/view (default: false)\n * @param options.view - If true, creates a view instead of a table (default: false)\n * @param options.allowMultipleStatements - If true, allows multiple statements where preceding statements are executed first and the final SELECT is wrapped in CREATE TABLE/VIEW (default: false)\n * @returns Object with tableName and rowCount (rowCount is undefined for views)\n */\n async createTableFromQuery(\n tableName: string | QualifiedTableName,\n query: string,\n options?: {\n replace?: boolean;\n temp?: boolean;\n view?: boolean;\n allowMultipleStatements?: boolean;\n abortSignal?: AbortSignal;\n },\n ) {\n const {\n replace = true,\n temp = false,\n view = false,\n allowMultipleStatements = false,\n abortSignal,\n } = options || {};\n\n // For temp tables/views, DuckDB requires the \"temp\" database\n const baseQualifiedName = isQualifiedTableName(tableName)\n ? tableName\n : makeQualifiedTableName({table: tableName});\n\n const qualifiedName = temp\n ? makeQualifiedTableName({\n table: baseQualifiedName.table,\n schema: baseQualifiedName.schema,\n database: 'temp',\n })\n : baseQualifiedName;\n\n const connector = await get().db.getConnector();\n\n const {precedingStatements, lastStatement} =\n separateLastStatement(query);\n\n if (!allowMultipleStatements && precedingStatements.length > 0) {\n throw new Error(\n 'Query must contain exactly one statement (set allowMultipleStatements: true to execute multiple statements)',\n );\n }\n\n // The last statement must be a SELECT\n const parsedQuery = await get().db.sqlSelectToJson(lastStatement);\n if (parsedQuery.error) {\n throw new Error(\n 'Final statement must be a valid SELECT statement',\n );\n }\n\n // Build CREATE statement with options\n const createKeyword = [\n 'CREATE',\n replace ? 'OR REPLACE' : '',\n temp ? 'TEMP' : '',\n view ? 'VIEW' : 'TABLE',\n ]\n .filter(Boolean)\n .join(' ');\n\n const createStatement = `${createKeyword} ${qualifiedName} AS (\n ${lastStatement}\n )`;\n\n const fullQuery = joinStatements(\n precedingStatements,\n createStatement,\n );\n const result = await connector.query(fullQuery, {\n signal: abortSignal,\n });\n // Views don't have a row count, only tables do\n const rowCount = view ? undefined : getColValAsNumber(result);\n return {tableName, rowCount};\n },\n\n /**\n * @deprecated Use .tables or .loadTableSchemas() instead\n */\n async getTables(schema) {\n const tableSchemas = await get().db.loadTableSchemas({schema});\n return tableSchemas.map((t) => t.table.table);\n },\n\n /**\n * @deprecated Use .loadTableSchemas() instead\n */\n async getTableSchema(tableName: string, schema = 'main') {\n const newLocal = await get().db.loadTableSchemas({\n schema,\n table: tableName,\n });\n return newLocal[0];\n },\n\n /**\n * @deprecated Use .loadTableRowCount() instead\n */\n async getTableRowCount(table, schema = 'main') {\n return get().db.loadTableRowCount({table, schema});\n },\n\n async loadTableRowCount(tableName: string | QualifiedTableName) {\n const {schema, database, table} =\n typeof tableName === 'string'\n ? {table: tableName}\n : tableName || {};\n const connector = await get().db.getConnector();\n const result = await connector.query(\n `SELECT COUNT(*) FROM ${makeQualifiedTableName({\n schema,\n database,\n table,\n })}`,\n );\n return getColValAsNumber(result);\n },\n\n /**\n * @deprecated Use .loadTableSchemas() instead\n */\n async getTableSchemas(schema) {\n return await get().db.loadTableSchemas({schema});\n },\n\n async loadTableSchemas(\n filter?: SchemaAndDatabase & {table?: string},\n ): Promise<DataTable[]> {\n const {schema, database, table} = filter || {};\n const sql = `WITH tables_and_views AS (\n FROM duckdb_tables() SELECT\n database_name AS database,\n schema_name AS schema,\n table_name AS name,\n sql,\n comment,\n estimated_size,\n FALSE AS isView\n UNION\n FROM duckdb_views() SELECT\n database_name AS database,\n schema_name AS schema,\n view_name AS name,\n sql,\n comment,\n NULL estimated_size,\n TRUE AS isView\n )\n SELECT\n isView,\n database, schema,\n name, column_names, column_types,\n sql, comment,\n estimated_size\n FROM (DESCRIBE)\n LEFT OUTER JOIN tables_and_views USING (database, schema, name)\n ${\n schema || database || table\n ? `WHERE ${[\n schema ? `schema = ${escapeVal(schema)}` : '',\n database ? `database = ${escapeVal(database)}` : '',\n table ? `name = ${escapeVal(table)}` : '',\n ]\n .filter(Boolean)\n .join(' AND ')}`\n : ''\n }`;\n const describeResults = await connector.query(sql);\n\n const newTables: DataTable[] = [];\n for (let i = 0; i < describeResults.numRows; i++) {\n const isView = describeResults.getChild('isView')?.get(i);\n const database = describeResults.getChild('database')?.get(i);\n const schema = describeResults.getChild('schema')?.get(i);\n const table = describeResults.getChild('name')?.get(i);\n const sql = describeResults.getChild('sql')?.get(i);\n const comment = describeResults.getChild('comment')?.get(i);\n const estimatedSize = describeResults\n .getChild('estimated_size')\n ?.get(i);\n const columnNames = describeResults\n .getChild('column_names')\n ?.get(i);\n const columnTypes = describeResults\n .getChild('column_types')\n ?.get(i);\n const columns: TableColumn[] = [];\n for (let di = 0; di < (columnNames?.length ?? 0); di++) {\n const columnName = String(columnNames.get(di));\n const columnType = String(columnTypes?.get(di));\n if (isDuckDbPlaceholderViewColumn(columnName, columnType)) {\n continue;\n }\n columns.push({\n name: columnName,\n type: columnType,\n });\n }\n newTables.push({\n table: makeQualifiedTableName({database, schema, table}),\n database,\n schema,\n tableName: table,\n columns,\n sql,\n comment,\n isView: Boolean(isView),\n rowCount:\n typeof estimatedSize === 'bigint'\n ? Number(estimatedSize)\n : estimatedSize === null\n ? undefined\n : estimatedSize,\n });\n }\n return newTables;\n },\n\n async checkTableExists(tableName: string | QualifiedTableName) {\n const qualifiedName = isQualifiedTableName(tableName)\n ? tableName\n : makeQualifiedTableName({table: tableName});\n const table = (await get().db.loadTableSchemas(qualifiedName))[0];\n if (!table) {\n return false;\n }\n return true;\n },\n\n async dropTable(tableName): Promise<void> {\n const connector = await get().db.getConnector();\n const qualifiedTable = isQualifiedTableName(tableName)\n ? tableName\n : makeQualifiedTableName({table: tableName});\n await connector.query(`DROP TABLE IF EXISTS ${qualifiedTable};`);\n await get().db.refreshTableSchemas();\n },\n\n async addTable(tableName, data) {\n const qualifiedName = isQualifiedTableName(tableName)\n ? tableName\n : makeQualifiedTableName({table: tableName});\n\n const {db} = get();\n if (data instanceof arrow.Table) {\n // TODO: make sure the table is replaced\n await db.connector.loadArrow(data, qualifiedName.toString());\n } else {\n await db.connector.loadObjects(data, qualifiedName.toString(), {\n replace: true,\n });\n }\n const newTable = (await db.loadTableSchemas(qualifiedName))[0];\n if (!newTable) {\n throw new Error('Failed to add table');\n }\n set((state) =>\n produce(state, (draft) => {\n draft.db.tables.push(newTable);\n }),\n );\n await get().db.refreshTableSchemas();\n return newTable;\n },\n\n async setTableRowCount(tableName, rowCount) {\n const qualifiedName = isQualifiedTableName(tableName)\n ? tableName\n : makeQualifiedTableName({table: tableName});\n set((state) =>\n produce(state, (draft) => {\n draft.db.tableRowCounts[qualifiedName.toString()] = rowCount;\n }),\n );\n },\n\n getTable(tableName) {\n return get().db.findTableByName(tableName);\n },\n\n findTableByName(tableName: string | QualifiedTableName) {\n const {table, schema, database} = {\n schema: get().db.currentSchema,\n database: get().db.currentDatabase,\n ...(typeof tableName === 'string'\n ? {table: tableName}\n : tableName),\n };\n return get().db.tables.find(\n (t) =>\n t.table.table === table &&\n (!schema || t.table.schema === schema) &&\n (!database || t.table.database === database),\n );\n },\n\n async refreshTableSchemas(): Promise<DataTable[]> {\n set((state) =>\n produce(state, (draft) => {\n draft.db.isRefreshingTableSchemas = true;\n }),\n );\n try {\n const connector = await get().db.getConnector();\n const result = await connector.query(\n `SELECT current_schema() AS schema, current_database() AS database`,\n );\n set((state) =>\n produce(state, (draft) => {\n draft.db.currentSchema = result.getChild('schema')?.get(0);\n draft.db.currentDatabase = result\n .getChild('database')\n ?.get(0);\n }),\n );\n const newTables = await get().db.loadTableSchemas();\n // Only update if there's an actual change in the schemas\n if (!deepEquals(newTables, get().db.tables)) {\n set((state) =>\n produce(state, (draft) => {\n draft.db.tables = newTables;\n draft.db.schemaTrees = createDbSchemaTrees(newTables);\n }),\n );\n }\n return newTables;\n } catch (err) {\n get().room.captureException(err);\n return [];\n } finally {\n set((state) =>\n produce(state, (draft) => {\n draft.db.isRefreshingTableSchemas = false;\n }),\n );\n }\n },\n\n async sqlSelectToJson(sql: string) {\n const connector = await get().db.getConnector();\n const parsedQuery = (\n await connector.query(\n `SELECT json_serialize_sql(${escapeVal(sql)})`,\n )\n )\n .getChildAt(0)\n ?.get(0);\n return JSON.parse(parsedQuery);\n },\n\n async executeSql(query: string): Promise<QueryHandle | null> {\n // Create a unique key for this query\n const queryKey = `${query}`;\n const connector = await get().db.getConnector();\n\n // Check if we already have a cached query for this key\n const existingQuery = get().db.queryCache[queryKey];\n if (existingQuery) {\n return existingQuery;\n }\n\n const queryHandle = connector.query(query);\n // Cache the query handle immediately\n set((state) =>\n produce(state, (draft) => {\n draft.db.queryCache[queryKey] = queryHandle;\n }),\n );\n\n queryHandle.result.finally(() => {\n // remove from cache after completion\n set((state) =>\n produce(state, (draft) => {\n delete draft.db.queryCache[queryKey];\n }),\n );\n });\n\n return queryHandle;\n },\n },\n };\n },\n );\n}\n\n/**\n * @internal\n * Select values from the room store that includes the DuckDB slice.\n *\n * This is a typed wrapper around `useBaseRoomStore` that narrows the\n * state to `RoomStateWithDuckDb` so selectors can access `db` safely.\n *\n * @typeParam T - The selected slice of state returned by the selector\n * @param selector - Function that selects a value from the store state\n * @returns The selected value of type `T`\n */\nexport function useStoreWithDuckDb<T>(\n selector: (state: BaseRoomStoreState & DuckDbSliceState) => T,\n): T {\n return useBaseRoomStore<DuckDbSliceState, T>((state) => selector(state));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"DuckDbSlice.js","sourceRoot":"","sources":["../src/DuckDbSlice.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createDbSchemaTrees,\n DataTable,\n DbSchemaNode,\n DuckDbConnector,\n escapeVal,\n getColValAsNumber,\n isQualifiedTableName,\n joinStatements,\n makeQualifiedTableName,\n QualifiedTableName,\n QueryHandle,\n separateLastStatement,\n TableColumn,\n} from '@sqlrooms/duckdb-core';\nimport {\n BaseRoomStoreState,\n createSlice,\n registerCommandsForOwner,\n RoomCommand,\n unregisterCommandsForOwner,\n useBaseRoomStore,\n} from '@sqlrooms/room-store';\nimport * as arrow from 'apache-arrow';\nimport deepEquals from 'fast-deep-equal';\nimport {produce} from 'immer';\nimport {z} from 'zod';\nimport {StateCreator} from 'zustand';\nimport {createWasmDuckDbConnector} from './connectors/createDuckDbConnector';\n\nconst DUCKDB_COMMAND_OWNER = '@sqlrooms/duckdb';\nconst DropTableCommandInput = z.object({\n tableName: z.string().describe('Name of the table to drop.'),\n});\ntype DropTableCommandInput = z.infer<typeof DropTableCommandInput>;\n\nconst CreateTableFromQueryCommandInput = z.object({\n tableName: z.string().describe('Name of the table or view to create.'),\n query: z.string().describe('SQL query used to populate the table/view.'),\n replace: z\n .boolean()\n .optional()\n .default(true)\n .describe('Whether to replace existing table/view with the same name.'),\n view: z\n .boolean()\n .optional()\n .default(false)\n .describe('Whether to create a view instead of a table.'),\n temp: z\n .boolean()\n .optional()\n .default(false)\n .describe('Whether to create a temporary object.'),\n allowMultipleStatements: z\n .boolean()\n .optional()\n .default(false)\n .describe('Allow multiple SQL statements where the final one is SELECT.'),\n});\ntype CreateTableFromQueryCommandInput = z.infer<\n typeof CreateTableFromQueryCommandInput\n>;\n\nfunction isDuckDbPlaceholderViewColumn(\n columnName: string,\n columnType: string,\n): boolean {\n return columnName === '__' && columnType.toUpperCase() === 'UNKNOWN';\n}\n\nexport type SchemaAndDatabase = {\n schema?: string;\n database?: string;\n};\n\n/**\n * State and actions for the DuckDB slice\n */\nexport type DuckDbSliceState = {\n db: {\n /**\n * The DuckDB connector instance\n */\n connector: DuckDbConnector;\n /**\n * @deprecated We shouldn't limit the schema to a single one.\n */\n schema: string;\n\n currentSchema: string | undefined;\n currentDatabase: string | undefined;\n\n /**\n * Cache of refreshed table schemas\n */\n tables: DataTable[];\n /**\n * Cache of row counts for tables\n */\n tableRowCounts: {[tableName: string]: number};\n /**\n * Cache of schema trees for tables\n */\n schemaTrees?: DbSchemaNode[];\n /**\n * Cache of currently running query handles.\n * This is only used for running queries to deduplicate them (especially for useSql),\n * the cache is cleared when the query is completed.\n */\n queryCache: {[key: string]: QueryHandle};\n /**\n * Whether the table schemas are being refreshed\n */\n isRefreshingTableSchemas: boolean;\n\n /**\n * Set a new DuckDB connector\n */\n setConnector: (connector: DuckDbConnector) => void;\n\n /**\n * Initialize the connector (creates a WasmDuckDbConnector if none exists)\n */\n initialize: () => Promise<void>;\n\n /**\n * Close and clean up the connector\n */\n destroy: () => Promise<void>;\n\n /**\n * Add a table to the room.\n * @param tableName - The name of the table to add.\n * @param data - The data to add to the table: an arrow table or an array of records.\n * @returns A promise that resolves to the table that was added.\n */\n addTable(\n tableName: string | QualifiedTableName,\n data: arrow.Table | Record<string, unknown>[],\n ): Promise<DataTable>;\n\n /**\n * Load the schemas of the tables in the database.\n */\n loadTableSchemas(\n filter?: SchemaAndDatabase & {table?: string},\n ): Promise<DataTable[]>;\n\n /**\n * @deprecated Use findTableByName instead\n */\n getTable(tableName: string): DataTable | undefined;\n\n /**\n * @internal Avoid using this directly, it's for internal use.\n */\n setTableRowCount(\n tableName: string | QualifiedTableName,\n rowCount: number,\n ): void;\n\n /**\n * Find a table by name in the last refreshed table schemas.\n * If no schema or database is provided, the table will be found in the current schema\n * and database (from last table schemas refresh).\n * @param tableName - The name of the table to find or a qualified table name.\n * @returns The table or undefined if not found.\n */\n findTableByName(\n tableName: string | QualifiedTableName,\n ): DataTable | undefined;\n\n /**\n * Refresh table schemas from the database.\n * @returns A promise that resolves to the updated tables.\n */\n refreshTableSchemas(): Promise<DataTable[]>;\n /**\n * Get the connector. If it's not initialized, it will be initialized.\n */\n getConnector: () => Promise<DuckDbConnector>;\n\n /**\n * @deprecated Use .loadTableRowCount() instead\n */\n getTableRowCount: (table: string, schema?: string) => Promise<number>;\n\n /**\n * Load the row count of a table\n */\n loadTableRowCount: (\n tableName: string | QualifiedTableName,\n ) => Promise<number>;\n\n /**\n * Execute a query with query handle (not result) caching and deduplication\n * @param query - The SQL query to execute\n * @returns The QueryHandle for the query or null if disabled\n */\n executeSql: (query: string) => Promise<QueryHandle | null>;\n\n /**\n * @deprecated Use .tables or .loadTableSchemas() instead\n */\n getTables: (schema?: string) => Promise<string[]>;\n\n /**\n * @deprecated Use .loadTableSchemas() instead\n */\n getTableSchema: (\n tableName: string,\n schema?: string,\n ) => Promise<DataTable | undefined>;\n\n /**\n * @deprecated Use .tables or .loadTableSchemas() instead\n */\n getTableSchemas: (schema?: string) => Promise<DataTable[]>;\n\n /**\n * Check if a table exists\n */\n checkTableExists: (\n tableName: string | QualifiedTableName,\n ) => Promise<boolean>;\n\n /**\n * Delete a table with optional schema and database\n * @param tableName - The name of the table to delete (qualified or plain)\n */\n dropTable: (tableName: string | QualifiedTableName) => Promise<void>;\n\n /**\n * Create a table or view from a query.\n * @param tableName - The name of the table/view to create.\n * @param query - The query to create the table/view from.\n * @param options - Creation options.\n * @returns The table/view name and rowCount (undefined for views).\n */\n createTableFromQuery: (\n tableName: string | QualifiedTableName,\n query: string,\n options?: {\n replace?: boolean;\n temp?: boolean;\n view?: boolean;\n allowMultipleStatements?: boolean;\n abortSignal?: AbortSignal;\n },\n ) => Promise<{\n tableName: string | QualifiedTableName;\n rowCount: number | undefined;\n }>;\n\n /**\n * Parse a SQL SELECT statement to JSON\n * @param sql - The SQL SELECT statement to parse.\n * @returns A promise that resolves to the parsed JSON.\n */\n sqlSelectToJson: (sql: string) => Promise<\n | {\n error: true;\n error_type: string;\n error_message: string;\n error_subtype: string;\n position: string;\n }\n | {\n error: false;\n statements: {\n node: {\n from_table: {\n alias: string;\n show_type: string;\n table_name: string;\n };\n select_list: Record<string, unknown>[];\n type: string;\n };\n }[];\n }\n >;\n };\n};\n\ntype CreateDuckDbSliceProps = {\n connector?: DuckDbConnector;\n};\n\n/**\n * Create a DuckDB slice for managing the connector\n */\nexport function createDuckDbSlice({\n connector = createWasmDuckDbConnector(),\n}: CreateDuckDbSliceProps = {}): StateCreator<DuckDbSliceState> {\n return createSlice<DuckDbSliceState, BaseRoomStoreState & DuckDbSliceState>(\n (set, get, store) => {\n return {\n db: {\n connector, // Will be initialized during init\n schema: 'main', // TODO: remove schema, we should not limit the schema to a single one.\n currentSchema: undefined,\n currentDatabase: undefined,\n isRefreshingTableSchemas: false,\n tables: [],\n tableRowCounts: {},\n schemaTrees: undefined,\n queryCache: {},\n\n setConnector: (connector: DuckDbConnector) => {\n set(\n produce((state) => {\n state.config.dataSources = [];\n state.db.connector = connector;\n }),\n );\n },\n\n initialize: async () => {\n await get().db.connector.initialize();\n await get().db.refreshTableSchemas();\n registerCommandsForOwner(\n store,\n DUCKDB_COMMAND_OWNER,\n createDuckDbCommands(),\n );\n },\n\n getConnector: async () => {\n await get().db.connector.initialize();\n return get().db.connector;\n },\n\n destroy: async () => {\n unregisterCommandsForOwner(store, DUCKDB_COMMAND_OWNER);\n try {\n if (get().db.connector) {\n await get().db.connector.destroy();\n }\n } catch (err) {\n console.error('Error during DuckDB shutdown:', err);\n }\n },\n\n /**\n * Creates a table or view from a SQL query.\n * @param tableName - Name of the table/view to create\n * @param query - SQL query (must be a SELECT statement, or multiple statements ending with a SELECT when allowMultipleStatements is true)\n * @param options - Creation options\n * @param options.replace - If true, uses CREATE OR REPLACE (default: true)\n * @param options.temp - If true, creates a temporary table/view (default: false)\n * @param options.view - If true, creates a view instead of a table (default: false)\n * @param options.allowMultipleStatements - If true, allows multiple statements where preceding statements are executed first and the final SELECT is wrapped in CREATE TABLE/VIEW (default: false)\n * @returns Object with tableName and rowCount (rowCount is undefined for views)\n */\n async createTableFromQuery(\n tableName: string | QualifiedTableName,\n query: string,\n options?: {\n replace?: boolean;\n temp?: boolean;\n view?: boolean;\n allowMultipleStatements?: boolean;\n abortSignal?: AbortSignal;\n },\n ) {\n const {\n replace = true,\n temp = false,\n view = false,\n allowMultipleStatements = false,\n abortSignal,\n } = options || {};\n\n // For temp tables/views, DuckDB requires the \"temp\" database\n const baseQualifiedName = isQualifiedTableName(tableName)\n ? tableName\n : makeQualifiedTableName({table: tableName});\n\n const qualifiedName = temp\n ? makeQualifiedTableName({\n table: baseQualifiedName.table,\n schema: baseQualifiedName.schema,\n database: 'temp',\n })\n : baseQualifiedName;\n\n const connector = await get().db.getConnector();\n\n const {precedingStatements, lastStatement} =\n separateLastStatement(query);\n\n if (!allowMultipleStatements && precedingStatements.length > 0) {\n throw new Error(\n 'Query must contain exactly one statement (set allowMultipleStatements: true to execute multiple statements)',\n );\n }\n\n // The last statement must be a SELECT\n const parsedQuery = await get().db.sqlSelectToJson(lastStatement);\n if (parsedQuery.error) {\n throw new Error(\n 'Final statement must be a valid SELECT statement',\n );\n }\n\n // Build CREATE statement with options\n const createKeyword = [\n 'CREATE',\n replace ? 'OR REPLACE' : '',\n temp ? 'TEMP' : '',\n view ? 'VIEW' : 'TABLE',\n ]\n .filter(Boolean)\n .join(' ');\n\n const createStatement = `${createKeyword} ${qualifiedName} AS (\n ${lastStatement}\n )`;\n\n const fullQuery = joinStatements(\n precedingStatements,\n createStatement,\n );\n const result = await connector.query(fullQuery, {\n signal: abortSignal,\n });\n // Views don't have a row count, only tables do\n const rowCount = view ? undefined : getColValAsNumber(result);\n return {tableName, rowCount};\n },\n\n /**\n * @deprecated Use .tables or .loadTableSchemas() instead\n */\n async getTables(schema) {\n const tableSchemas = await get().db.loadTableSchemas({schema});\n return tableSchemas.map((t) => t.table.table);\n },\n\n /**\n * @deprecated Use .loadTableSchemas() instead\n */\n async getTableSchema(tableName: string, schema = 'main') {\n const newLocal = await get().db.loadTableSchemas({\n schema,\n table: tableName,\n });\n return newLocal[0];\n },\n\n /**\n * @deprecated Use .loadTableRowCount() instead\n */\n async getTableRowCount(table, schema = 'main') {\n return get().db.loadTableRowCount({table, schema});\n },\n\n async loadTableRowCount(tableName: string | QualifiedTableName) {\n const {schema, database, table} =\n typeof tableName === 'string'\n ? {table: tableName}\n : tableName || {};\n const connector = await get().db.getConnector();\n const result = await connector.query(\n `SELECT COUNT(*) FROM ${makeQualifiedTableName({\n schema,\n database,\n table,\n })}`,\n );\n return getColValAsNumber(result);\n },\n\n /**\n * @deprecated Use .loadTableSchemas() instead\n */\n async getTableSchemas(schema) {\n return await get().db.loadTableSchemas({schema});\n },\n\n async loadTableSchemas(\n filter?: SchemaAndDatabase & {table?: string},\n ): Promise<DataTable[]> {\n const {schema, database, table} = filter || {};\n const sql = `WITH tables_and_views AS (\n FROM duckdb_tables() SELECT\n database_name AS database,\n schema_name AS schema,\n table_name AS name,\n sql,\n comment,\n estimated_size,\n FALSE AS isView\n UNION\n FROM duckdb_views() SELECT\n database_name AS database,\n schema_name AS schema,\n view_name AS name,\n sql,\n comment,\n NULL estimated_size,\n TRUE AS isView\n )\n SELECT\n isView,\n database, schema,\n name, column_names, column_types,\n sql, comment,\n estimated_size\n FROM (DESCRIBE)\n LEFT OUTER JOIN tables_and_views USING (database, schema, name)\n ${\n schema || database || table\n ? `WHERE ${[\n schema ? `schema = ${escapeVal(schema)}` : '',\n database ? `database = ${escapeVal(database)}` : '',\n table ? `name = ${escapeVal(table)}` : '',\n ]\n .filter(Boolean)\n .join(' AND ')}`\n : ''\n }`;\n const describeResults = await connector.query(sql);\n\n const newTables: DataTable[] = [];\n for (let i = 0; i < describeResults.numRows; i++) {\n const isView = describeResults.getChild('isView')?.get(i);\n const database = describeResults.getChild('database')?.get(i);\n const schema = describeResults.getChild('schema')?.get(i);\n const table = describeResults.getChild('name')?.get(i);\n const sql = describeResults.getChild('sql')?.get(i);\n const comment = describeResults.getChild('comment')?.get(i);\n const estimatedSize = describeResults\n .getChild('estimated_size')\n ?.get(i);\n const columnNames = describeResults\n .getChild('column_names')\n ?.get(i);\n const columnTypes = describeResults\n .getChild('column_types')\n ?.get(i);\n const columns: TableColumn[] = [];\n for (let di = 0; di < (columnNames?.length ?? 0); di++) {\n const columnName = String(columnNames.get(di));\n const columnType = String(columnTypes?.get(di));\n if (isDuckDbPlaceholderViewColumn(columnName, columnType)) {\n continue;\n }\n columns.push({\n name: columnName,\n type: columnType,\n });\n }\n newTables.push({\n table: makeQualifiedTableName({database, schema, table}),\n database,\n schema,\n tableName: table,\n columns,\n sql,\n comment,\n isView: Boolean(isView),\n rowCount:\n typeof estimatedSize === 'bigint'\n ? Number(estimatedSize)\n : estimatedSize === null\n ? undefined\n : estimatedSize,\n });\n }\n return newTables;\n },\n\n async checkTableExists(tableName: string | QualifiedTableName) {\n const qualifiedName = isQualifiedTableName(tableName)\n ? tableName\n : makeQualifiedTableName({table: tableName});\n const table = (await get().db.loadTableSchemas(qualifiedName))[0];\n if (!table) {\n return false;\n }\n return true;\n },\n\n async dropTable(tableName): Promise<void> {\n const connector = await get().db.getConnector();\n const qualifiedTable = isQualifiedTableName(tableName)\n ? tableName\n : makeQualifiedTableName({table: tableName});\n await connector.query(`DROP TABLE IF EXISTS ${qualifiedTable};`);\n await get().db.refreshTableSchemas();\n },\n\n async addTable(tableName, data) {\n const qualifiedName = isQualifiedTableName(tableName)\n ? tableName\n : makeQualifiedTableName({table: tableName});\n\n const {db} = get();\n if (data instanceof arrow.Table) {\n // TODO: make sure the table is replaced\n await db.connector.loadArrow(data, qualifiedName.toString());\n } else {\n await db.connector.loadObjects(data, qualifiedName.toString(), {\n replace: true,\n });\n }\n const newTable = (await db.loadTableSchemas(qualifiedName))[0];\n if (!newTable) {\n throw new Error('Failed to add table');\n }\n set((state) =>\n produce(state, (draft) => {\n draft.db.tables.push(newTable);\n }),\n );\n await get().db.refreshTableSchemas();\n return newTable;\n },\n\n async setTableRowCount(tableName, rowCount) {\n const qualifiedName = isQualifiedTableName(tableName)\n ? tableName\n : makeQualifiedTableName({table: tableName});\n set((state) =>\n produce(state, (draft) => {\n draft.db.tableRowCounts[qualifiedName.toString()] = rowCount;\n }),\n );\n },\n\n getTable(tableName) {\n return get().db.findTableByName(tableName);\n },\n\n findTableByName(tableName: string | QualifiedTableName) {\n const {table, schema, database} = {\n schema: get().db.currentSchema,\n database: get().db.currentDatabase,\n ...(typeof tableName === 'string'\n ? {table: tableName}\n : tableName),\n };\n return get().db.tables.find(\n (t) =>\n t.table.table === table &&\n (!schema || t.table.schema === schema) &&\n (!database || t.table.database === database),\n );\n },\n\n async refreshTableSchemas(): Promise<DataTable[]> {\n set((state) =>\n produce(state, (draft) => {\n draft.db.isRefreshingTableSchemas = true;\n }),\n );\n try {\n const connector = await get().db.getConnector();\n const result = await connector.query(\n `SELECT current_schema() AS schema, current_database() AS database`,\n );\n set((state) =>\n produce(state, (draft) => {\n draft.db.currentSchema = result.getChild('schema')?.get(0);\n draft.db.currentDatabase = result\n .getChild('database')\n ?.get(0);\n }),\n );\n const newTables = await get().db.loadTableSchemas();\n // Only update if there's an actual change in the schemas\n if (!deepEquals(newTables, get().db.tables)) {\n set((state) =>\n produce(state, (draft) => {\n draft.db.tables = newTables;\n draft.db.schemaTrees = createDbSchemaTrees(newTables);\n }),\n );\n }\n return newTables;\n } catch (err) {\n get().room.captureException(err);\n return [];\n } finally {\n set((state) =>\n produce(state, (draft) => {\n draft.db.isRefreshingTableSchemas = false;\n }),\n );\n }\n },\n\n async sqlSelectToJson(sql: string) {\n const connector = await get().db.getConnector();\n const parsedQuery = (\n await connector.query(\n `SELECT json_serialize_sql(${escapeVal(sql)})`,\n )\n )\n .getChildAt(0)\n ?.get(0);\n return JSON.parse(parsedQuery);\n },\n\n async executeSql(query: string): Promise<QueryHandle | null> {\n // Create a unique key for this query\n const queryKey = `${query}`;\n const connector = await get().db.getConnector();\n\n // Check if we already have a cached query for this key\n const existingQuery = get().db.queryCache[queryKey];\n if (existingQuery) {\n return existingQuery;\n }\n\n const queryHandle = connector.query(query);\n // Cache the query handle immediately\n set((state) =>\n produce(state, (draft) => {\n draft.db.queryCache[queryKey] = queryHandle;\n }),\n );\n\n queryHandle.result.finally(() => {\n // remove from cache after completion\n set((state) =>\n produce(state, (draft) => {\n delete draft.db.queryCache[queryKey];\n }),\n );\n });\n\n return queryHandle;\n },\n },\n };\n },\n );\n}\n\ntype DuckDbCommandStoreState = BaseRoomStoreState & DuckDbSliceState;\n\nfunction createDuckDbCommands(): RoomCommand<DuckDbCommandStoreState>[] {\n return [\n {\n id: 'db.refresh-table-schemas',\n name: 'Refresh table schemas',\n description: 'Reload table and schema metadata from DuckDB',\n group: 'Database',\n keywords: ['duckdb', 'database', 'refresh', 'tables', 'schemas'],\n metadata: {\n readOnly: true,\n idempotent: true,\n riskLevel: 'low',\n },\n isEnabled: ({getState}) => !getState().db.isRefreshingTableSchemas,\n execute: async ({getState}) => {\n await getState().db.refreshTableSchemas();\n return {\n success: true,\n commandId: 'db.refresh-table-schemas',\n message: 'Table schemas refreshed.',\n };\n },\n },\n {\n id: 'db.drop-table',\n name: 'Drop table',\n description: 'Drop a table from DuckDB by name',\n group: 'Database',\n keywords: ['duckdb', 'database', 'drop', 'table', 'delete'],\n inputSchema: DropTableCommandInput,\n inputDescription: 'Provide a tableName to remove from DuckDB.',\n metadata: {\n readOnly: false,\n idempotent: true,\n riskLevel: 'high',\n requiresConfirmation: true,\n },\n validateInput: async (input, {getState}) => {\n const {tableName} = input as DropTableCommandInput;\n const exists = await getState().db.checkTableExists(tableName);\n if (!exists) {\n throw new Error(`Table \"${tableName}\" does not exist.`);\n }\n },\n execute: async ({getState}, input) => {\n const {tableName} = input as DropTableCommandInput;\n await getState().db.dropTable(tableName);\n return {\n success: true,\n commandId: 'db.drop-table',\n message: `Dropped table \"${tableName}\".`,\n };\n },\n },\n {\n id: 'db.create-table-from-query',\n name: 'Create table from query',\n description: 'Create a table or view from a SQL query',\n group: 'Database',\n keywords: ['duckdb', 'database', 'create', 'table', 'view', 'query'],\n inputSchema: CreateTableFromQueryCommandInput,\n inputDescription:\n 'Provide tableName and query, with optional replace/view/temp flags.',\n metadata: {\n readOnly: false,\n idempotent: false,\n riskLevel: 'medium',\n },\n validateInput: (input) => {\n const {query} = input as CreateTableFromQueryCommandInput;\n if (!query.trim()) {\n throw new Error('Query cannot be empty.');\n }\n },\n execute: async ({getState}, input) => {\n const {tableName, query, replace, view, temp, allowMultipleStatements} =\n input as CreateTableFromQueryCommandInput;\n const result = await getState().db.createTableFromQuery(\n tableName,\n query,\n {\n replace,\n view,\n temp,\n allowMultipleStatements,\n },\n );\n await getState().db.refreshTableSchemas();\n return {\n success: true,\n commandId: 'db.create-table-from-query',\n message: `Created ${view ? 'view' : 'table'} \"${tableName}\".`,\n data: result,\n };\n },\n },\n ];\n}\n\n/**\n * @internal\n * Select values from the room store that includes the DuckDB slice.\n *\n * This is a typed wrapper around `useBaseRoomStore` that narrows the\n * state to `RoomStateWithDuckDb` so selectors can access `db` safely.\n *\n * @typeParam T - The selected slice of state returned by the selector\n * @param selector - Function that selects a value from the store state\n * @returns The selected value of type `T`\n */\nexport function useStoreWithDuckDb<T>(\n selector: (state: BaseRoomStoreState & DuckDbSliceState) => T,\n): T {\n return useBaseRoomStore<DuckDbSliceState, T>((state) => selector(state));\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sqlrooms/duckdb",
|
|
3
|
-
"version": "0.28.0
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -20,17 +20,17 @@
|
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@duckdb/duckdb-wasm": "1.32.0",
|
|
23
|
-
"@sqlrooms/duckdb-core": "0.28.0
|
|
24
|
-
"@sqlrooms/room-config": "0.28.0
|
|
25
|
-
"@sqlrooms/room-store": "0.28.0
|
|
26
|
-
"@sqlrooms/utils": "0.28.0
|
|
23
|
+
"@sqlrooms/duckdb-core": "0.28.0",
|
|
24
|
+
"@sqlrooms/room-config": "0.28.0",
|
|
25
|
+
"@sqlrooms/room-store": "0.28.0",
|
|
26
|
+
"@sqlrooms/utils": "0.28.0",
|
|
27
27
|
"fast-deep-equal": "^3.1.3",
|
|
28
28
|
"immer": "^11.0.1",
|
|
29
29
|
"zod": "^4.1.8",
|
|
30
30
|
"zustand": "^5.0.8"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@sqlrooms/duckdb-node": "0.28.0
|
|
33
|
+
"@sqlrooms/duckdb-node": "0.28.0",
|
|
34
34
|
"@types/jest": "^30.0.0",
|
|
35
35
|
"jest": "^30.1.3",
|
|
36
36
|
"ts-jest": "^29.4.4"
|
|
@@ -47,5 +47,5 @@
|
|
|
47
47
|
"test": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' jest",
|
|
48
48
|
"test:watch": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' jest --watch"
|
|
49
49
|
},
|
|
50
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "dcac54f8adf77240e293c93d224a0ce9fd8142a9"
|
|
51
51
|
}
|