@sqlrooms/duckdb 0.17.0 → 0.18.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 +44 -29
- package/dist/DuckDbSlice.d.ts.map +1 -1
- package/dist/DuckDbSlice.js +6 -7
- package/dist/DuckDbSlice.js.map +1 -1
- package/dist/connectors/BaseDuckDbConnector.d.ts.map +1 -1
- package/dist/connectors/BaseDuckDbConnector.js +8 -5
- package/dist/connectors/BaseDuckDbConnector.js.map +1 -1
- package/dist/connectors/DuckDbConnector.d.ts +40 -15
- package/dist/connectors/DuckDbConnector.d.ts.map +1 -1
- package/dist/connectors/DuckDbConnector.js.map +1 -1
- package/dist/exportToCsv.js +1 -1
- package/dist/exportToCsv.js.map +1 -1
- package/dist/useDuckDb.d.ts +4 -1
- package/dist/useDuckDb.d.ts.map +1 -1
- package/dist/useDuckDb.js.map +1 -1
- package/dist/useSql.js +1 -1
- package/dist/useSql.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ A powerful wrapper around DuckDB-WASM that provides React hooks and utilities fo
|
|
|
4
4
|
|
|
5
5
|
### React Integration & Type Safety
|
|
6
6
|
|
|
7
|
-
- **React Hooks**: Seamless integration with React applications via `useSql`
|
|
7
|
+
- **React Hooks**: Seamless integration with React applications via `useSql`
|
|
8
8
|
- **Runtime Validation**: Optional Zod schema validation for query results with type transformations
|
|
9
9
|
- **Typed Row Accessors**: Type-safe row access with validation and multiple iteration methods
|
|
10
10
|
|
|
@@ -102,8 +102,6 @@ function ValidatedUserList() {
|
|
|
102
102
|
### Using the Store for Direct Database Operations
|
|
103
103
|
|
|
104
104
|
```tsx
|
|
105
|
-
import {useRoomStore} from '@sqlrooms/duckdb';
|
|
106
|
-
|
|
107
105
|
function DatabaseManager() {
|
|
108
106
|
const createTableFromQuery = useRoomStore(
|
|
109
107
|
(state) => state.db.createTableFromQuery,
|
|
@@ -182,7 +180,6 @@ const tableExists = await checkTableExists(qualifiedTable);
|
|
|
182
180
|
|
|
183
181
|
```tsx
|
|
184
182
|
import {loadCSV, loadJSON, loadParquet, loadObjects} from '@sqlrooms/duckdb';
|
|
185
|
-
import {useRoomStore} from '@sqlrooms/duckdb';
|
|
186
183
|
|
|
187
184
|
function DataLoader() {
|
|
188
185
|
const getConnector = useRoomStore((state) => state.db.getConnector);
|
|
@@ -230,10 +227,8 @@ function DataLoader() {
|
|
|
230
227
|
### Using the Connector Directly
|
|
231
228
|
|
|
232
229
|
```tsx
|
|
233
|
-
import {useDuckDb} from '@sqlrooms/duckdb';
|
|
234
|
-
|
|
235
230
|
function AdvancedDataLoader() {
|
|
236
|
-
const connector =
|
|
231
|
+
const connector = useRoomStore((state) => state.db.connector);
|
|
237
232
|
|
|
238
233
|
const handleFileUpload = async (file: File) => {
|
|
239
234
|
// Load file directly using the connector
|
|
@@ -279,43 +274,63 @@ function ExportButton() {
|
|
|
279
274
|
|
|
280
275
|
## Low-Level DuckDB Access
|
|
281
276
|
|
|
282
|
-
|
|
283
|
-
import {useDuckDb, useRoomStore} from '@sqlrooms/duckdb';
|
|
277
|
+
### Basic direct usage
|
|
284
278
|
|
|
279
|
+
```tsx
|
|
285
280
|
async function executeCustomQuery() {
|
|
286
|
-
//
|
|
287
|
-
const connector =
|
|
281
|
+
// Grab the connector directly (no React hook necessary inside plain TS)
|
|
282
|
+
const connector = useRoomStore((state) => state.db.connector);
|
|
288
283
|
|
|
289
|
-
//
|
|
290
|
-
const
|
|
291
|
-
const result = await queryHandle.result;
|
|
284
|
+
// QueryHandle is promise-like – await it directly
|
|
285
|
+
const result = await connector.query('SELECT COUNT(*) AS count FROM users');
|
|
292
286
|
|
|
293
|
-
//
|
|
287
|
+
// Inspect Arrow table
|
|
294
288
|
const count = result.getChildAt(0)?.get(0);
|
|
295
289
|
console.log(`Total users: ${count}`);
|
|
290
|
+
}
|
|
291
|
+
```
|
|
296
292
|
|
|
297
|
-
|
|
293
|
+
### Cancellation examples
|
|
294
|
+
|
|
295
|
+
```tsx
|
|
296
|
+
async function cancelExample() {
|
|
297
|
+
const connector = useRoomStore((state) => state.db.connector);
|
|
298
|
+
|
|
299
|
+
// 1. Manual cancel via the handle
|
|
300
|
+
const query = connector.query('SELECT * FROM large_table');
|
|
301
|
+
setTimeout(() => h.cancel(), 2000); // cancel after 2 s
|
|
302
|
+
await query; // throws if cancelled
|
|
303
|
+
|
|
304
|
+
// 2. Composable cancellation – many queries, one controller
|
|
305
|
+
const controller = new AbortController();
|
|
306
|
+
const q1 = connector.query('SELECT 1', {signal: controller.signal});
|
|
307
|
+
const q2 = connector.query('SELECT 2', {signal: controller.signal});
|
|
308
|
+
controller.abort(); // cancels q1 & q2
|
|
309
|
+
await Promise.allSettled([q1, q2]);
|
|
298
310
|
}
|
|
311
|
+
```
|
|
299
312
|
|
|
300
|
-
|
|
313
|
+
### Advanced operations with the Zustand store
|
|
314
|
+
|
|
315
|
+
```tsx
|
|
301
316
|
function AdvancedOperations() {
|
|
302
|
-
const executeSql = useRoomStore((
|
|
303
|
-
const sqlSelectToJson = useRoomStore((
|
|
304
|
-
const checkTableExists = useRoomStore((
|
|
317
|
+
const executeSql = useRoomStore((s) => s.db.executeSql);
|
|
318
|
+
const sqlSelectToJson = useRoomStore((s) => s.db.sqlSelectToJson);
|
|
319
|
+
const checkTableExists = useRoomStore((s) => s.db.checkTableExists);
|
|
305
320
|
|
|
306
321
|
const handleAdvancedQuery = async () => {
|
|
307
|
-
//
|
|
308
|
-
const
|
|
309
|
-
if (
|
|
310
|
-
const
|
|
311
|
-
console.log('Query result:',
|
|
322
|
+
// Cached execution with deduplication
|
|
323
|
+
const query = await executeSql('SELECT * FROM users LIMIT 10');
|
|
324
|
+
if (query) {
|
|
325
|
+
const rows = await query; // await handle directly
|
|
326
|
+
console.log('Query result:', rows);
|
|
312
327
|
}
|
|
313
328
|
|
|
314
|
-
// Parse SQL
|
|
315
|
-
const
|
|
316
|
-
console.log('Parsed query:',
|
|
329
|
+
// Parse SQL to JSON (analysis tool)
|
|
330
|
+
const parsed = await sqlSelectToJson('SELECT id, name FROM users');
|
|
331
|
+
console.log('Parsed query:', parsed);
|
|
317
332
|
|
|
318
|
-
//
|
|
333
|
+
// Safety check before destructive operations
|
|
319
334
|
const exists = await checkTableExists('users');
|
|
320
335
|
console.log('Table exists:', exists);
|
|
321
336
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DuckDbSlice.d.ts","sourceRoot":"","sources":["../src/DuckDbSlice.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"DuckDbSlice.d.ts","sourceRoot":"","sources":["../src/DuckDbSlice.ts"],"names":[],"mappings":"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"}
|
package/dist/DuckDbSlice.js
CHANGED
|
@@ -70,7 +70,7 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), })
|
|
|
70
70
|
}
|
|
71
71
|
const rowCount = getColValAsNumber(await connector.query(`CREATE OR REPLACE TABLE ${qualifiedName} AS (
|
|
72
72
|
${statements[0]}
|
|
73
|
-
)`)
|
|
73
|
+
)`));
|
|
74
74
|
return { tableName, rowCount };
|
|
75
75
|
},
|
|
76
76
|
/**
|
|
@@ -105,7 +105,7 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), })
|
|
|
105
105
|
schema,
|
|
106
106
|
database,
|
|
107
107
|
table,
|
|
108
|
-
})}`)
|
|
108
|
+
})}`);
|
|
109
109
|
return getColValAsNumber(result);
|
|
110
110
|
},
|
|
111
111
|
/**
|
|
@@ -128,7 +128,7 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), })
|
|
|
128
128
|
]
|
|
129
129
|
.filter(Boolean)
|
|
130
130
|
.join(' AND ')}`
|
|
131
|
-
: ''}`)
|
|
131
|
+
: ''}`);
|
|
132
132
|
const newTables = [];
|
|
133
133
|
for (let i = 0; i < describeResults.numRows; i++) {
|
|
134
134
|
const database = describeResults.getChild('database')?.get(i);
|
|
@@ -172,8 +172,7 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), })
|
|
|
172
172
|
const qualifiedTable = isQualifiedTableName(tableName)
|
|
173
173
|
? tableName
|
|
174
174
|
: makeQualifiedTableName({ table: tableName });
|
|
175
|
-
await connector.query(`DROP TABLE IF EXISTS ${qualifiedTable};`)
|
|
176
|
-
.result;
|
|
175
|
+
await connector.query(`DROP TABLE IF EXISTS ${qualifiedTable};`);
|
|
177
176
|
await get().db.refreshTableSchemas();
|
|
178
177
|
},
|
|
179
178
|
async addTable(tableName, data) {
|
|
@@ -227,7 +226,7 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), })
|
|
|
227
226
|
}));
|
|
228
227
|
try {
|
|
229
228
|
const connector = await get().db.getConnector();
|
|
230
|
-
const result = await connector.query(`SELECT current_schema() AS schema, current_database() AS database`)
|
|
229
|
+
const result = await connector.query(`SELECT current_schema() AS schema, current_database() AS database`);
|
|
231
230
|
set((state) => produce(state, (draft) => {
|
|
232
231
|
draft.db.currentSchema = result.getChild('schema')?.get(0);
|
|
233
232
|
draft.db.currentDatabase = result.getChild('database')?.get(0);
|
|
@@ -254,7 +253,7 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), })
|
|
|
254
253
|
},
|
|
255
254
|
async sqlSelectToJson(sql) {
|
|
256
255
|
const connector = await get().db.getConnector();
|
|
257
|
-
const parsedQuery = (await connector.query(`SELECT json_serialize_sql(${escapeVal(sql)})`)
|
|
256
|
+
const parsedQuery = (await connector.query(`SELECT json_serialize_sql(${escapeVal(sql)})`))
|
|
258
257
|
.getChildAt(0)
|
|
259
258
|
?.get(0);
|
|
260
259
|
return JSON.parse(parsedQuery);
|
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 {createBaseSlice, RoomState, useBaseRoomStore} from '@sqlrooms/core';\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 {DuckDbConnector, QueryHandle} from './connectors/DuckDbConnector';\nimport {createWasmDuckDbConnector} from './connectors/createDuckDbConnector';\nimport {\n escapeId,\n escapeVal,\n getColValAsNumber,\n isQualifiedTableName,\n makeQualifiedTableName,\n QualifiedTableName,\n splitSqlStatements,\n} from './duckdb-utils';\nimport {createDbSchemaTrees as createDbSchemaTrees} from './schemaTree';\nimport {DataTable, TableColumn, DbSchemaNode} from './types';\n\nexport const DuckDbSliceConfig = z.object({\n // nothing yet\n});\nexport type DuckDbSliceConfig = z.infer<typeof DuckDbSliceConfig>;\n\nexport type SchemaAndDatabase = {\n schema?: string;\n database?: string;\n};\n\nexport function createDefaultDuckDbConfig(): DuckDbSliceConfig {\n return {\n // nothing yet\n };\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 */\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\n * @param options - Optional parameters including schema and database\n */\n dropTable: (tableName: string | QualifiedTableName) => Promise<void>;\n\n /**\n * Create a table from a query.\n * @param tableName - The name of the table to create.\n * @param query - The query to create the table from.\n * @returns The table that was created.\n */\n createTableFromQuery: (\n tableName: string | QualifiedTableName,\n query: string,\n ) => Promise<{tableName: string | QualifiedTableName; rowCount: number}>;\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 };\n }[];\n }\n >;\n };\n};\n\n/**\n * Create a DuckDB slice for managing the connector\n */\nexport function createDuckDbSlice({\n connector = createWasmDuckDbConnector(),\n}: {\n connector?: DuckDbConnector;\n}): StateCreator<DuckDbSliceState> {\n return createBaseSlice<DuckDbSliceConfig, DuckDbSliceState>((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 schemaTree: 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 async createTableFromQuery(\n tableName: string | QualifiedTableName,\n query: string,\n ) {\n const qualifiedName = isQualifiedTableName(tableName)\n ? tableName\n : makeQualifiedTableName({table: tableName});\n\n const connector = await get().db.getConnector();\n\n const statements = splitSqlStatements(query);\n if (statements.length !== 1) {\n throw new Error('Query must contain exactly one statement');\n }\n const statement = statements[0] as string;\n const parsedQuery = await get().db.sqlSelectToJson(statement);\n if (parsedQuery.error) {\n throw new Error('Query is not a valid SELECT statement');\n }\n\n const rowCount = getColValAsNumber(\n await connector.query(\n `CREATE OR REPLACE TABLE ${qualifiedName} AS (\n ${statements[0]}\n )`,\n ).result,\n );\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 ).result;\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 describeResults = await connector.query(\n `FROM (DESCRIBE)\n SELECT \n database, schema,\n name, column_names, column_types\n ${\n schema || database || table\n ? `WHERE ${[\n schema ? `schema = '${escapeId(schema)}'` : '',\n database ? `database = '${escapeId(database)}'` : '',\n table ? `name = '${escapeId(table)}'` : '',\n ]\n .filter(Boolean)\n .join(' AND ')}`\n : ''\n }`,\n ).result;\n\n const newTables: DataTable[] = [];\n for (let i = 0; i < describeResults.numRows; 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 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; di++) {\n columns.push({\n name: columnNames.get(di),\n type: columnTypes.get(di),\n });\n }\n newTables.push({\n table: makeQualifiedTableName({database, schema, table}),\n database,\n schema,\n tableName: table,\n columns,\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 .result;\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' ? {table: tableName} : 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 ).result;\n set((state) =>\n produce(state, (draft) => {\n draft.db.currentSchema = result.getChild('schema')?.get(0);\n draft.db.currentDatabase = result.getChild('database')?.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 ).result\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\ntype RoomStateWithDuckDb = RoomState<DuckDbSliceConfig> & DuckDbSliceState;\n\nexport function useStoreWithDuckDb<T>(\n selector: (state: RoomStateWithDuckDb) => T,\n): T {\n return useBaseRoomStore<DuckDbSliceConfig, RoomState<DuckDbSliceConfig>, T>(\n (state) => selector(state as unknown as RoomStateWithDuckDb),\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"DuckDbSlice.js","sourceRoot":"","sources":["../src/DuckDbSlice.ts"],"names":[],"mappings":"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","sourcesContent":["import {createBaseSlice, RoomState, useBaseRoomStore} from '@sqlrooms/core';\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 {DuckDbConnector, QueryHandle} from './connectors/DuckDbConnector';\nimport {createWasmDuckDbConnector} from './connectors/createDuckDbConnector';\nimport {\n escapeId,\n escapeVal,\n getColValAsNumber,\n isQualifiedTableName,\n makeQualifiedTableName,\n QualifiedTableName,\n splitSqlStatements,\n} from './duckdb-utils';\nimport {createDbSchemaTrees as createDbSchemaTrees} from './schemaTree';\nimport {DataTable, TableColumn, DbSchemaNode} from './types';\n\nexport const DuckDbSliceConfig = z.object({\n // nothing yet\n});\nexport type DuckDbSliceConfig = z.infer<typeof DuckDbSliceConfig>;\n\nexport type SchemaAndDatabase = {\n schema?: string;\n database?: string;\n};\n\nexport function createDefaultDuckDbConfig(): DuckDbSliceConfig {\n return {\n // nothing yet\n };\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 */\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\n * @param options - Optional parameters including schema and database\n */\n dropTable: (tableName: string | QualifiedTableName) => Promise<void>;\n\n /**\n * Create a table from a query.\n * @param tableName - The name of the table to create.\n * @param query - The query to create the table from.\n * @returns The table that was created.\n */\n createTableFromQuery: (\n tableName: string | QualifiedTableName,\n query: string,\n ) => Promise<{tableName: string | QualifiedTableName; rowCount: number}>;\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 };\n }[];\n }\n >;\n };\n};\n\n/**\n * Create a DuckDB slice for managing the connector\n */\nexport function createDuckDbSlice({\n connector = createWasmDuckDbConnector(),\n}: {\n connector?: DuckDbConnector;\n}): StateCreator<DuckDbSliceState> {\n return createBaseSlice<DuckDbSliceConfig, DuckDbSliceState>((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 schemaTree: 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 async createTableFromQuery(\n tableName: string | QualifiedTableName,\n query: string,\n ) {\n const qualifiedName = isQualifiedTableName(tableName)\n ? tableName\n : makeQualifiedTableName({table: tableName});\n\n const connector = await get().db.getConnector();\n\n const statements = splitSqlStatements(query);\n if (statements.length !== 1) {\n throw new Error('Query must contain exactly one statement');\n }\n const statement = statements[0] as string;\n const parsedQuery = await get().db.sqlSelectToJson(statement);\n if (parsedQuery.error) {\n throw new Error('Query is not a valid SELECT statement');\n }\n\n const rowCount = getColValAsNumber(\n await connector.query(\n `CREATE OR REPLACE TABLE ${qualifiedName} AS (\n ${statements[0]}\n )`,\n ),\n );\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 describeResults = await connector.query(\n `FROM (DESCRIBE)\n SELECT \n database, schema,\n name, column_names, column_types\n ${\n schema || database || table\n ? `WHERE ${[\n schema ? `schema = '${escapeId(schema)}'` : '',\n database ? `database = '${escapeId(database)}'` : '',\n table ? `name = '${escapeId(table)}'` : '',\n ]\n .filter(Boolean)\n .join(' AND ')}`\n : ''\n }`,\n );\n\n const newTables: DataTable[] = [];\n for (let i = 0; i < describeResults.numRows; 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 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; di++) {\n columns.push({\n name: columnNames.get(di),\n type: columnTypes.get(di),\n });\n }\n newTables.push({\n table: makeQualifiedTableName({database, schema, table}),\n database,\n schema,\n tableName: table,\n columns,\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' ? {table: tableName} : 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.getChild('database')?.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\ntype RoomStateWithDuckDb = RoomState<DuckDbSliceConfig> & DuckDbSliceState;\n\nexport function useStoreWithDuckDb<T>(\n selector: (state: RoomStateWithDuckDb) => T,\n): T {\n return useBaseRoomStore<DuckDbSliceConfig, RoomState<DuckDbSliceConfig>, T>(\n (state) => selector(state as unknown as RoomStateWithDuckDb),\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseDuckDbConnector.d.ts","sourceRoot":"","sources":["../../src/connectors/BaseDuckDbConnector.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,eAAe,EACf,mBAAmB,EACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AACrC,OAAO,EAAC,eAAe,EAA4B,MAAM,mBAAmB,CAAC;AAI7E,MAAM,WAAW,0BAA0B;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,uBAAuB;IACtC,kBAAkB,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,eAAe,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,oBAAoB,CAAC,CAAC,SAAS,OAAO,GAAG,GAAG,EAC1C,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,EACnB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3B,mBAAmB,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,iBAAiB,CAAC,CAChB,IAAI,EAAE,KAAK,CAAC,KAAK,GAAG,UAAU,EAC9B,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAC,GACvB,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,mBAAmB,CAAC,CAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC/B,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,mBAAmB,GACzB,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,gBAAgB,CAAC,CACf,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,eAAe,GACrB,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB;AAED,wBAAgB,yBAAyB,CACvC,EACE,MAAmB,EACnB,mBAAwB,GACzB,EAAE,0BAA0B,YAAK,EAClC,IAAI,EAAE,uBAAuB,GAC5B,eAAe,
|
|
1
|
+
{"version":3,"file":"BaseDuckDbConnector.d.ts","sourceRoot":"","sources":["../../src/connectors/BaseDuckDbConnector.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,eAAe,EACf,mBAAmB,EACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AACrC,OAAO,EAAC,eAAe,EAA4B,MAAM,mBAAmB,CAAC;AAI7E,MAAM,WAAW,0BAA0B;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,uBAAuB;IACtC,kBAAkB,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,eAAe,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,oBAAoB,CAAC,CAAC,SAAS,OAAO,GAAG,GAAG,EAC1C,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,EACnB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3B,mBAAmB,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,iBAAiB,CAAC,CAChB,IAAI,EAAE,KAAK,CAAC,KAAK,GAAG,UAAU,EAC9B,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAC,GACvB,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,mBAAmB,CAAC,CAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC/B,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,mBAAmB,GACzB,OAAO,CAAC,IAAI,CAAC,CAAC;IACjB,gBAAgB,CAAC,CACf,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,eAAe,GACrB,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB;AAED,wBAAgB,yBAAyB,CACvC,EACE,MAAmB,EACnB,mBAAwB,GACzB,EAAE,0BAA0B,YAAK,EAClC,IAAI,EAAE,uBAAuB,GAC5B,eAAe,CA8JjB"}
|
|
@@ -60,11 +60,15 @@ export function createBaseDuckDbConnector({ dbPath = ':memory:', initializationQ
|
|
|
60
60
|
const resultPromise = queryPromiseFactory(abortController.signal, queryId).finally(() => {
|
|
61
61
|
state.activeQueries.delete(queryId);
|
|
62
62
|
});
|
|
63
|
-
|
|
63
|
+
const handle = {
|
|
64
64
|
result: resultPromise,
|
|
65
65
|
signal: abortController.signal,
|
|
66
66
|
cancel: async () => cancelQuery(queryId),
|
|
67
|
+
then: resultPromise.then.bind(resultPromise),
|
|
68
|
+
catch: resultPromise.catch.bind(resultPromise),
|
|
69
|
+
finally: resultPromise.finally?.bind(resultPromise),
|
|
67
70
|
};
|
|
71
|
+
return handle;
|
|
68
72
|
};
|
|
69
73
|
const execute = (sql, options) => createQueryHandle((signal, id) => impl.executeQueryInternal(sql, signal, id), options);
|
|
70
74
|
const query = (queryStr, options) => createQueryHandle((signal, id) => impl.executeQueryInternal(queryStr, signal, id), options);
|
|
@@ -82,11 +86,10 @@ export function createBaseDuckDbConnector({ dbPath = ':memory:', initializationQ
|
|
|
82
86
|
const fileName = file;
|
|
83
87
|
await ensureInitialized();
|
|
84
88
|
if (opts && isSpatialLoadFileOptions(opts)) {
|
|
85
|
-
await query(loadSpatial(tableName, fileName, opts))
|
|
89
|
+
await query(loadSpatial(tableName, fileName, opts));
|
|
86
90
|
}
|
|
87
91
|
else {
|
|
88
|
-
await query(load(opts?.method ?? 'auto', tableName, fileName, opts))
|
|
89
|
-
.result;
|
|
92
|
+
await query(load(opts?.method ?? 'auto', tableName, fileName, opts));
|
|
90
93
|
}
|
|
91
94
|
};
|
|
92
95
|
const loadArrow = async (file, tableName, opts) => {
|
|
@@ -100,7 +103,7 @@ export function createBaseDuckDbConnector({ dbPath = ':memory:', initializationQ
|
|
|
100
103
|
return impl.loadObjectsInternal(file, tableName, opts);
|
|
101
104
|
}
|
|
102
105
|
await ensureInitialized();
|
|
103
|
-
await query(loadObjectsSql(tableName, file, opts))
|
|
106
|
+
await query(loadObjectsSql(tableName, file, opts));
|
|
104
107
|
};
|
|
105
108
|
return {
|
|
106
109
|
initialize,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseDuckDbConnector.js","sourceRoot":"","sources":["../../src/connectors/BaseDuckDbConnector.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,GAGzB,MAAM,uBAAuB,CAAC;AAI/B,OAAO,EAAC,IAAI,EAAE,WAAW,IAAI,cAAc,EAAE,WAAW,EAAC,MAAM,aAAa,CAAC;AAC7E,OAAO,EAAC,sBAAsB,EAAC,MAAM,qBAAqB,CAAC;AAiC3D,MAAM,UAAU,yBAAyB,CACvC,EACE,MAAM,GAAG,UAAU,EACnB,mBAAmB,GAAG,EAAE,MACM,EAAE,EAClC,IAA6B;IAE7B,MAAM,KAAK,GAAG;QACZ,MAAM;QACN,mBAAmB;QACnB,WAAW,EAAE,KAAK;QAClB,YAAY,EAAE,IAA4B;QAC1C,aAAa,EAAE,IAAI,GAAG,EAA2B;KAClD,CAAC;IAEF,MAAM,iBAAiB,GAAG,KAAK,IAAI,EAAE;QACnC,IAAI,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;YAC7C,MAAM,KAAK,CAAC,YAAY,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,KAAK,IAAI,EAAE;QAC5B,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QACD,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;YACvB,OAAO,KAAK,CAAC,YAAY,CAAC;QAC5B,CAAC;QACD,KAAK,CAAC,YAAY,GAAG,CAAC,KAAK,IAAI,EAAE;YAC/B,MAAM,IAAI,CAAC,kBAAkB,EAAE,EAAE,CAAC;YAClC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC;YACzB,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;QAC5B,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACjB,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC;YAC1B,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;YAC1B,MAAM,GAAG,CAAC;QACZ,CAAC,CAAC,CAAC;QACH,OAAO,KAAK,CAAC,YAAY,CAAC;IAC5B,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE;QACzB,MAAM,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;QAC/B,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC;QAC1B,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC;IAC5B,CAAC,CAAC;IAEF,MAAM,eAAe,GAAG,GAAG,EAAE,CAC3B,KAAK,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IAE/D,MAAM,WAAW,GAAG,KAAK,EAAE,OAAe,EAAE,EAAE;QAC5C,MAAM,eAAe,GAAG,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACzD,IAAI,eAAe,EAAE,CAAC;YACpB,eAAe,CAAC,KAAK,EAAE,CAAC;YACxB,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACtC,CAAC;QACD,MAAM,IAAI,CAAC,mBAAmB,EAAE,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC,CAAC;IAEF,MAAM,iBAAiB,GAAG,CACxB,mBAAyE,EACzE,OAAsB,EACN,EAAE;QAClB,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;QAC9C,MAAM,OAAO,GAAG,eAAe,EAAE,CAAC;QAClC,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;YACpB,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;YAClC,IAAI,UAAU,CAAC,OAAO;gBAAE,eAAe,CAAC,KAAK,EAAE,CAAC;;gBAC3C,UAAU,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC,CAAC;QAC3E,CAAC;QACD,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QAClD,MAAM,aAAa,GAAG,mBAAmB,CACvC,eAAe,CAAC,MAAM,EACtB,OAAO,CACR,CAAC,OAAO,CAAC,GAAG,EAAE;YACb,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QACH,OAAO;YACL,MAAM,EAAE,aAAa;YACrB,MAAM,EAAE,eAAe,CAAC,MAAM;YAC9B,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC;SACzC,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,CAAC,GAAW,EAAE,OAAsB,EAAe,EAAE,CACnE,iBAAiB,CACf,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,EAC1D,OAAO,CACR,CAAC;IAEJ,MAAM,KAAK,GAAG,CACZ,QAAgB,EAChB,OAAsB,EACO,EAAE,CAC/B,iBAAiB,CACf,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAI,QAAQ,EAAE,MAAM,EAAE,EAAE,CAAC,EAClE,OAAO,CACR,CAAC;IAEJ,MAAM,SAAS,GAAG,CAChB,QAAgB,EAChB,OAAsB,EACI,EAAE,CAC5B,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QACpE,OAAO,sBAAsB,CAAC,EAAC,UAAU,EAAE,KAAK,EAAC,CAAC,CAAC;IACrD,CAAC,EAAE,OAAO,CAAC,CAAC;IAEd,MAAM,QAAQ,GAAG,KAAK,EACpB,IAAmB,EACnB,SAAiB,EACjB,IAAsB,EACtB,EAAE;QACF,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,IAAI,YAAY,IAAI,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,iBAAiB,EAAE,EAAC,KAAK,EAAE,EAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAC,EAAC,CAAC,CAAC;QACvE,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC;QACtB,MAAM,iBAAiB,EAAE,CAAC;QAC1B,IAAI,IAAI,IAAI,wBAAwB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3C,MAAM,KAAK,CAAC,WAAW,CAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;QAC7D,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,IAAI,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;iBACjE,MAAM,CAAC;QACZ,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,KAAK,EACrB,IAA8B,EAC9B,SAAiB,EACjB,IAAwB,EACT,EAAE;QACjB,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;QACvD,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACrC,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,KAAK,EACvB,IAA+B,EAC/B,SAAiB,EACjB,IAA0B,EAC1B,EAAE;QACF,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;QACzD,CAAC;QACD,MAAM,iBAAiB,EAAE,CAAC;QAC1B,MAAM,KAAK,CAAC,cAAc,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;IAC5D,CAAC,CAAC;IAEF,OAAO;QACL,UAAU;QACV,OAAO;QACP,OAAO;QACP,KAAK;QACL,SAAS;QACT,QAAQ;QACR,SAAS;QACT,WAAW;KACZ,CAAC;AACJ,CAAC","sourcesContent":["import {\n isSpatialLoadFileOptions,\n LoadFileOptions,\n StandardLoadOptions,\n} from '@sqlrooms/room-config';\nimport * as arrow from 'apache-arrow';\nimport {TypeMap} from 'apache-arrow';\nimport {DuckDbConnector, QueryHandle, QueryOptions} from './DuckDbConnector';\nimport {load, loadObjects as loadObjectsSql, loadSpatial} from './load/load';\nimport {createTypedRowAccessor} from '../typedRowAccessor';\n\nexport interface BaseDuckDbConnectorOptions {\n dbPath?: string;\n initializationQuery?: string;\n}\n\nexport interface BaseDuckDbConnectorImpl {\n initializeInternal?(): Promise<void>;\n destroyInternal?(): Promise<void>;\n executeQueryInternal<T extends TypeMap = any>(\n query: string,\n signal: AbortSignal,\n queryId?: string,\n ): Promise<arrow.Table<T>>;\n cancelQueryInternal?(queryId: string): Promise<void>;\n loadArrowInternal?(\n file: arrow.Table | Uint8Array,\n tableName: string,\n opts?: {schema?: string},\n ): Promise<void>;\n loadObjectsInternal?(\n file: Record<string, unknown>[],\n tableName: string,\n opts?: StandardLoadOptions,\n ): Promise<void>;\n loadFileInternal?(\n file: string | File,\n tableName: string,\n opts?: LoadFileOptions,\n ): Promise<void>;\n}\n\nexport function createBaseDuckDbConnector(\n {\n dbPath = ':memory:',\n initializationQuery = '',\n }: BaseDuckDbConnectorOptions = {},\n impl: BaseDuckDbConnectorImpl,\n): DuckDbConnector {\n const state = {\n dbPath,\n initializationQuery,\n initialized: false,\n initializing: null as Promise<void> | null,\n activeQueries: new Map<string, AbortController>(),\n };\n\n const ensureInitialized = async () => {\n if (!state.initialized && state.initializing) {\n await state.initializing;\n }\n };\n\n const initialize = async () => {\n if (state.initialized) {\n return;\n }\n if (state.initializing) {\n return state.initializing;\n }\n state.initializing = (async () => {\n await impl.initializeInternal?.();\n state.initialized = true;\n state.initializing = null;\n })().catch((err) => {\n state.initialized = false;\n state.initializing = null;\n throw err;\n });\n return state.initializing;\n };\n\n const destroy = async () => {\n await impl.destroyInternal?.();\n state.initialized = false;\n state.initializing = null;\n };\n\n const generateQueryId = () =>\n `q_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n\n const cancelQuery = async (queryId: string) => {\n const abortController = state.activeQueries.get(queryId);\n if (abortController) {\n abortController.abort();\n state.activeQueries.delete(queryId);\n }\n await impl.cancelQueryInternal?.(queryId);\n };\n\n const createQueryHandle = <T>(\n queryPromiseFactory: (signal: AbortSignal, queryId: string) => Promise<T>,\n options?: QueryOptions,\n ): QueryHandle<T> => {\n const abortController = new AbortController();\n const queryId = generateQueryId();\n if (options?.signal) {\n const userSignal = options.signal;\n if (userSignal.aborted) abortController.abort();\n else userSignal.addEventListener('abort', () => abortController.abort());\n }\n state.activeQueries.set(queryId, abortController);\n const resultPromise = queryPromiseFactory(\n abortController.signal,\n queryId,\n ).finally(() => {\n state.activeQueries.delete(queryId);\n });\n return {\n result: resultPromise,\n signal: abortController.signal,\n cancel: async () => cancelQuery(queryId),\n };\n };\n\n const execute = (sql: string, options?: QueryOptions): QueryHandle =>\n createQueryHandle(\n (signal, id) => impl.executeQueryInternal(sql, signal, id),\n options,\n );\n\n const query = <T extends TypeMap = any>(\n queryStr: string,\n options?: QueryOptions,\n ): QueryHandle<arrow.Table<T>> =>\n createQueryHandle(\n (signal, id) => impl.executeQueryInternal<T>(queryStr, signal, id),\n options,\n );\n\n const queryJson = <T = Record<string, any>>(\n queryStr: string,\n options?: QueryOptions,\n ): QueryHandle<Iterable<T>> =>\n createQueryHandle(async (signal, id) => {\n const table = await impl.executeQueryInternal(queryStr, signal, id);\n return createTypedRowAccessor({arrowTable: table});\n }, options);\n\n const loadFile = async (\n file: string | File,\n tableName: string,\n opts?: LoadFileOptions,\n ) => {\n if (impl.loadFileInternal) {\n return impl.loadFileInternal(file, tableName, opts);\n }\n if (file instanceof File) {\n throw new Error('Not implemented', {cause: {file, tableName, opts}});\n }\n const fileName = file;\n await ensureInitialized();\n if (opts && isSpatialLoadFileOptions(opts)) {\n await query(loadSpatial(tableName, fileName, opts)).result;\n } else {\n await query(load(opts?.method ?? 'auto', tableName, fileName, opts))\n .result;\n }\n };\n\n const loadArrow = async (\n file: arrow.Table | Uint8Array,\n tableName: string,\n opts?: {schema?: string},\n ): Promise<void> => {\n if (impl.loadArrowInternal) {\n return impl.loadArrowInternal(file, tableName, opts);\n }\n throw new Error('Not implemented');\n };\n\n const loadObjects = async (\n file: Record<string, unknown>[],\n tableName: string,\n opts?: StandardLoadOptions,\n ) => {\n if (impl.loadObjectsInternal) {\n return impl.loadObjectsInternal(file, tableName, opts);\n }\n await ensureInitialized();\n await query(loadObjectsSql(tableName, file, opts)).result;\n };\n\n return {\n initialize,\n destroy,\n execute,\n query,\n queryJson,\n loadFile,\n loadArrow,\n loadObjects,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"BaseDuckDbConnector.js","sourceRoot":"","sources":["../../src/connectors/BaseDuckDbConnector.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n isSpatialLoadFileOptions,\n LoadFileOptions,\n StandardLoadOptions,\n} from '@sqlrooms/room-config';\nimport * as arrow from 'apache-arrow';\nimport {TypeMap} from 'apache-arrow';\nimport {DuckDbConnector, QueryHandle, QueryOptions} from './DuckDbConnector';\nimport {load, loadObjects as loadObjectsSql, loadSpatial} from './load/load';\nimport {createTypedRowAccessor} from '../typedRowAccessor';\n\nexport interface BaseDuckDbConnectorOptions {\n dbPath?: string;\n initializationQuery?: string;\n}\n\nexport interface BaseDuckDbConnectorImpl {\n initializeInternal?(): Promise<void>;\n destroyInternal?(): Promise<void>;\n executeQueryInternal<T extends TypeMap = any>(\n query: string,\n signal: AbortSignal,\n queryId?: string,\n ): Promise<arrow.Table<T>>;\n cancelQueryInternal?(queryId: string): Promise<void>;\n loadArrowInternal?(\n file: arrow.Table | Uint8Array,\n tableName: string,\n opts?: {schema?: string},\n ): Promise<void>;\n loadObjectsInternal?(\n file: Record<string, unknown>[],\n tableName: string,\n opts?: StandardLoadOptions,\n ): Promise<void>;\n loadFileInternal?(\n file: string | File,\n tableName: string,\n opts?: LoadFileOptions,\n ): Promise<void>;\n}\n\nexport function createBaseDuckDbConnector(\n {\n dbPath = ':memory:',\n initializationQuery = '',\n }: BaseDuckDbConnectorOptions = {},\n impl: BaseDuckDbConnectorImpl,\n): DuckDbConnector {\n const state = {\n dbPath,\n initializationQuery,\n initialized: false,\n initializing: null as Promise<void> | null,\n activeQueries: new Map<string, AbortController>(),\n };\n\n const ensureInitialized = async () => {\n if (!state.initialized && state.initializing) {\n await state.initializing;\n }\n };\n\n const initialize = async () => {\n if (state.initialized) {\n return;\n }\n if (state.initializing) {\n return state.initializing;\n }\n state.initializing = (async () => {\n await impl.initializeInternal?.();\n state.initialized = true;\n state.initializing = null;\n })().catch((err) => {\n state.initialized = false;\n state.initializing = null;\n throw err;\n });\n return state.initializing;\n };\n\n const destroy = async () => {\n await impl.destroyInternal?.();\n state.initialized = false;\n state.initializing = null;\n };\n\n const generateQueryId = () =>\n `q_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n\n const cancelQuery = async (queryId: string) => {\n const abortController = state.activeQueries.get(queryId);\n if (abortController) {\n abortController.abort();\n state.activeQueries.delete(queryId);\n }\n await impl.cancelQueryInternal?.(queryId);\n };\n\n const createQueryHandle = <T>(\n queryPromiseFactory: (signal: AbortSignal, queryId: string) => Promise<T>,\n options?: QueryOptions,\n ): QueryHandle<T> => {\n const abortController = new AbortController();\n const queryId = generateQueryId();\n if (options?.signal) {\n const userSignal = options.signal;\n if (userSignal.aborted) abortController.abort();\n else userSignal.addEventListener('abort', () => abortController.abort());\n }\n state.activeQueries.set(queryId, abortController);\n const resultPromise = queryPromiseFactory(\n abortController.signal,\n queryId,\n ).finally(() => {\n state.activeQueries.delete(queryId);\n });\n const handle: QueryHandle<T> = {\n result: resultPromise,\n signal: abortController.signal,\n cancel: async () => cancelQuery(queryId),\n then: resultPromise.then.bind(resultPromise),\n catch: resultPromise.catch.bind(resultPromise),\n finally: resultPromise.finally?.bind(resultPromise),\n } as unknown as QueryHandle<T>;\n return handle;\n };\n\n const execute = (sql: string, options?: QueryOptions): QueryHandle =>\n createQueryHandle(\n (signal, id) => impl.executeQueryInternal(sql, signal, id),\n options,\n );\n\n const query = <T extends TypeMap = any>(\n queryStr: string,\n options?: QueryOptions,\n ): QueryHandle<arrow.Table<T>> =>\n createQueryHandle(\n (signal, id) => impl.executeQueryInternal<T>(queryStr, signal, id),\n options,\n );\n\n const queryJson = <T = Record<string, any>>(\n queryStr: string,\n options?: QueryOptions,\n ): QueryHandle<Iterable<T>> =>\n createQueryHandle(async (signal, id) => {\n const table = await impl.executeQueryInternal(queryStr, signal, id);\n return createTypedRowAccessor({arrowTable: table});\n }, options);\n\n const loadFile = async (\n file: string | File,\n tableName: string,\n opts?: LoadFileOptions,\n ) => {\n if (impl.loadFileInternal) {\n return impl.loadFileInternal(file, tableName, opts);\n }\n if (file instanceof File) {\n throw new Error('Not implemented', {cause: {file, tableName, opts}});\n }\n const fileName = file;\n await ensureInitialized();\n if (opts && isSpatialLoadFileOptions(opts)) {\n await query(loadSpatial(tableName, fileName, opts));\n } else {\n await query(load(opts?.method ?? 'auto', tableName, fileName, opts));\n }\n };\n\n const loadArrow = async (\n file: arrow.Table | Uint8Array,\n tableName: string,\n opts?: {schema?: string},\n ): Promise<void> => {\n if (impl.loadArrowInternal) {\n return impl.loadArrowInternal(file, tableName, opts);\n }\n throw new Error('Not implemented');\n };\n\n const loadObjects = async (\n file: Record<string, unknown>[],\n tableName: string,\n opts?: StandardLoadOptions,\n ) => {\n if (impl.loadObjectsInternal) {\n return impl.loadObjectsInternal(file, tableName, opts);\n }\n await ensureInitialized();\n await query(loadObjectsSql(tableName, file, opts));\n };\n\n return {\n initialize,\n destroy,\n execute,\n query,\n queryJson,\n loadFile,\n loadArrow,\n loadObjects,\n };\n}\n"]}
|
|
@@ -14,26 +14,49 @@ export interface QueryOptions {
|
|
|
14
14
|
signal?: AbortSignal;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
* Handle for managing query execution and cancellation
|
|
17
|
+
* Handle for managing query execution and cancellation.
|
|
18
|
+
*
|
|
19
|
+
* It is **Promise-like**, so you can either:
|
|
20
|
+
*
|
|
21
|
+
* • `await handle` – the most ergonomic form, or
|
|
22
|
+
* • `await handle.result` – kept for backwards-compatibility.
|
|
23
|
+
*
|
|
24
|
+
* Additional capabilities:
|
|
25
|
+
* • Standard Promise API: `.then()`, `.catch()`, `.finally()`
|
|
26
|
+
* • `handle.cancel()` – cancel the running query.
|
|
27
|
+
* • `handle.signal` – `AbortSignal` that fires when the query is cancelled.
|
|
18
28
|
*
|
|
19
29
|
* @example
|
|
20
30
|
* ```typescript
|
|
21
31
|
* // Simple usage
|
|
22
32
|
* const handle = connector.query('SELECT * FROM table');
|
|
23
|
-
* await handle.result
|
|
33
|
+
* const table = await handle; // no .result needed
|
|
24
34
|
*
|
|
25
35
|
* // With cancellation
|
|
26
|
-
* const
|
|
27
|
-
*
|
|
36
|
+
* const controller = new AbortController();
|
|
37
|
+
* const handle = connector.query('SELECT * FROM large_table', { signal: controller.signal });
|
|
38
|
+
* setTimeout(() => controller.abort(), 5000);
|
|
28
39
|
*
|
|
29
|
-
* //
|
|
40
|
+
* // Manual cancel via the handle
|
|
41
|
+
* const h = connector.query('SELECT * FROM table');
|
|
42
|
+
* await someCondition;
|
|
43
|
+
* await h.cancel();
|
|
44
|
+
*
|
|
45
|
+
* // Composable cancellation (multiple queries, one controller)
|
|
30
46
|
* const controller = new AbortController();
|
|
31
|
-
* const
|
|
32
|
-
* const
|
|
33
|
-
*
|
|
47
|
+
* const h1 = connector.query('SELECT * FROM table1', { signal: controller.signal });
|
|
48
|
+
* const h2 = connector.query('SELECT * FROM table2', { signal: controller.signal });
|
|
49
|
+
* // Later...
|
|
50
|
+
* controller.abort(); // Cancels h1 and h2 together
|
|
51
|
+
*
|
|
52
|
+
* // Using Promise utilities
|
|
53
|
+
* const [t1, t2] = await Promise.all([
|
|
54
|
+
* connector.query('select 1'),
|
|
55
|
+
* connector.query('select 2')
|
|
56
|
+
* ]);
|
|
34
57
|
* ```
|
|
35
58
|
*/
|
|
36
|
-
export
|
|
59
|
+
export type QueryHandle<T = any> = PromiseLike<T> & {
|
|
37
60
|
/** Promise that resolves with query results */
|
|
38
61
|
result: Promise<T>;
|
|
39
62
|
/**
|
|
@@ -67,7 +90,11 @@ export interface QueryHandle<T = any> {
|
|
|
67
90
|
* ```
|
|
68
91
|
*/
|
|
69
92
|
signal: AbortSignal;
|
|
70
|
-
|
|
93
|
+
/** Attach a callback for only the rejection of the Promise */
|
|
94
|
+
catch: Promise<T>['catch'];
|
|
95
|
+
/** Attach a callback that's invoked when the Promise is settled (fulfilled or rejected) */
|
|
96
|
+
finally: Promise<T>['finally'];
|
|
97
|
+
};
|
|
71
98
|
/**
|
|
72
99
|
* DuckDB connector interface with advanced query cancellation support
|
|
73
100
|
*
|
|
@@ -201,8 +228,7 @@ export interface DuckDbConnector {
|
|
|
201
228
|
* @example
|
|
202
229
|
* ```typescript
|
|
203
230
|
* // Basic query
|
|
204
|
-
* const handle = connector.query('SELECT * FROM users WHERE active = true');
|
|
205
|
-
* const table = await handle.result;
|
|
231
|
+
* const handle = await connector.query('SELECT * FROM users WHERE active = true');
|
|
206
232
|
* console.log(`Found ${table.numRows} active users`);
|
|
207
233
|
*
|
|
208
234
|
* // Query with timeout
|
|
@@ -214,7 +240,7 @@ export interface DuckDbConnector {
|
|
|
214
240
|
* });
|
|
215
241
|
*
|
|
216
242
|
* try {
|
|
217
|
-
* const result = await handle
|
|
243
|
+
* const result = await handle;
|
|
218
244
|
* console.log('Query completed within timeout');
|
|
219
245
|
* } catch (error) {
|
|
220
246
|
* if (error.name === 'AbortError') {
|
|
@@ -237,8 +263,7 @@ export interface DuckDbConnector {
|
|
|
237
263
|
* @example
|
|
238
264
|
* ```typescript
|
|
239
265
|
* // Simple JSON query
|
|
240
|
-
* const
|
|
241
|
-
* const users = await handle.result;
|
|
266
|
+
* const users = await connector.queryJson('SELECT name, email FROM users LIMIT 10');
|
|
242
267
|
* for (const user of users) {
|
|
243
268
|
* console.log(`${user.name}: ${user.email}`);
|
|
244
269
|
* }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DuckDbConnector.d.ts","sourceRoot":"","sources":["../../src/connectors/DuckDbConnector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAE,mBAAmB,EAAC,MAAM,uBAAuB,CAAC;AAC3E,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AAErC;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED
|
|
1
|
+
{"version":3,"file":"DuckDbConnector.d.ts","sourceRoot":"","sources":["../../src/connectors/DuckDbConnector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAE,mBAAmB,EAAC,MAAM,uBAAuB,CAAC;AAC3E,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AAErC;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,GAAG,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,GAAG;IAClD,+CAA+C;IAC/C,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAEnB;;;OAGG;IACH,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,MAAM,EAAE,WAAW,CAAC;IAEpB,8DAA8D;IAC9D,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAE3B,2FAA2F;IAC3F,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;CAChC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B;;OAEG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,WAAW,CAAC;IAE1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACH,KAAK,CAAC,CAAC,SAAS,OAAO,GAAG,GAAG,EAC3B,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,YAAY,GACrB,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAE/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkCG;IACH,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC/B,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,YAAY,GACrB,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAE5B;;;;;OAKG;IACH,QAAQ,CACN,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,eAAe,GACrB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;;;OAIG;IACH,SAAS,CACP,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,UAAU,EAC/B,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAC,GACvB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;;;;OAKG;IACH,WAAW,CACT,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC/B,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,mBAAmB,GACzB,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DuckDbConnector.js","sourceRoot":"","sources":["../../src/connectors/DuckDbConnector.ts"],"names":[],"mappings":"","sourcesContent":["import {LoadFileOptions, StandardLoadOptions} from '@sqlrooms/room-config';\nimport * as arrow from 'apache-arrow';\nimport {TypeMap} from 'apache-arrow';\n\n/**\n * Options for query execution\n */\nexport interface QueryOptions {\n /**\n * Optional external abort signal for coordinated cancellation.\n * When provided, the query will be cancelled if this signal is aborted.\n * This enables powerful composition patterns like cancelling multiple\n * queries together or integrating with other cancellable operations.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Handle for managing query execution and cancellation\n *\n * @example\n * ```typescript\n * // Simple usage\n * const handle = connector.query('SELECT * FROM table');\n * await handle.result;\n *\n * // With cancellation\n * const handle = connector.query('SELECT * FROM large_table');\n * setTimeout(() => handle.cancel(), 5000);\n *\n * // Composable cancellation\n * const controller = new AbortController();\n * const handle1 = connector.query('SELECT * FROM table1', { signal: controller.signal });\n * const handle2 = connector.query('SELECT * FROM table2', { signal: controller.signal });\n * controller.abort(); // Cancels both queries\n * ```\n */\nexport interface QueryHandle<T = any> {\n /** Promise that resolves with query results */\n result: Promise<T>;\n\n /**\n * Method to cancel the query with optional cleanup.\n * This provides a clean abstraction over the underlying cancellation mechanism.\n */\n cancel: () => Promise<void>;\n\n /**\n * Read-only access to the abort signal for composability.\n *\n * Key benefits:\n * - **Event-driven**: Listen for abort events to update UI or perform cleanup\n * - **Integration**: Use with other Web APIs like fetch() that accept AbortSignal\n * - **Status checking**: Check if query is already cancelled with signal.aborted\n *\n * @example\n * ```typescript\n * // Listen for cancellation events\n * handle.signal.addEventListener('abort', () => {\n * console.log('Query cancelled');\n * updateUI('Operation cancelled');\n * });\n *\n * // Check cancellation status\n * if (handle.signal.aborted) {\n * console.log('Query was already cancelled');\n * }\n *\n * // Use with other APIs\n * const response = await fetch('/api/data', { signal: handle.signal });\n * ```\n */\n signal: AbortSignal;\n}\n\n/**\n * DuckDB connector interface with advanced query cancellation support\n *\n * This interface provides a hybrid approach that combines the simplicity of method-based\n * cancellation with the composability of Web Standards (AbortController/AbortSignal).\n *\n * ## Key Benefits of This Design\n *\n * ### 🔗 Composability\n * Cancel multiple queries with a single controller:\n * ```typescript\n * const controller = new AbortController();\n * const query1 = connector.query('SELECT * FROM table1', { signal: controller.signal });\n * const query2 = connector.query('SELECT * FROM table2', { signal: controller.signal });\n * controller.abort(); // Cancels both queries\n * ```\n *\n * ### 🌐 Integration with Web APIs\n * Use the same signal for queries and HTTP requests:\n * ```typescript\n * const controller = new AbortController();\n * const queryHandle = connector.query('SELECT * FROM table', { signal: controller.signal });\n * const response = await fetch('/api/data', { signal: controller.signal });\n * // controller.abort() cancels both the query and the HTTP request\n * ```\n *\n * ### 🎛️ Flexibility\n * Simple usage when you don't need external control, advanced when you do:\n * ```typescript\n * // Simple - internal cancellation management\n * const handle = connector.query('SELECT * FROM table');\n * handle.cancel();\n *\n * // Advanced - external cancellation control\n * const controller = new AbortController();\n * const handle = connector.query('SELECT * FROM table', { signal: controller.signal });\n * controller.abort();\n * ```\n *\n * ### 📡 Event-Driven\n * React to cancellation events for better UX:\n * ```typescript\n * handle.signal.addEventListener('abort', () => {\n * showNotification('Query cancelled');\n * hideLoadingSpinner();\n * });\n * ```\n *\n * ### ⏱️ Timeout Support\n * Built-in timeout capability with manual override:\n * ```typescript\n * const timeoutController = new AbortController();\n * setTimeout(() => timeoutController.abort(), 30000); // 30s timeout\n *\n * const handle = connector.query('SELECT * FROM large_table', {\n * signal: timeoutController.signal\n * });\n *\n * // User can still cancel manually\n * cancelButton.onclick = () => timeoutController.abort();\n * ```\n *\n * ### 🏗️ Signal Composition\n * Combine multiple cancellation sources:\n * ```typescript\n * function combineSignals(...signals: AbortSignal[]): AbortSignal {\n * const controller = new AbortController();\n * signals.forEach(signal => {\n * if (signal.aborted) controller.abort();\n * else signal.addEventListener('abort', () => controller.abort());\n * });\n * return controller.signal;\n * }\n *\n * const userSignal = userController.signal;\n * const timeoutSignal = createTimeoutSignal(30000);\n * const combinedSignal = combineSignals(userSignal, timeoutSignal);\n *\n * const handle = connector.query('SELECT * FROM table', { signal: combinedSignal });\n * ```\n */\nexport interface DuckDbConnector {\n /**\n * Initialize the connector.\n * The function returns a promise that resolves when the connector is initialized.\n * Calling the initialize() function multiple times should not restart the initialization.\n * See BaseDuckDbConnector for an implementation example.\n */\n initialize(): Promise<void>;\n\n /**\n * Destroy the connector and clean up resources\n */\n destroy(): Promise<void>;\n\n /**\n * Execute a SQL query without returning a result\n *\n * @param sql SQL query to execute\n * @param options Optional query options including abort signal for coordinated cancellation\n * @returns QueryHandle containing:\n * - result: Promise that resolves when execution completes\n * - cancel: Method to cancel the query with cleanup\n * - signal: AbortSignal for composability with other cancellable operations\n *\n * @example\n * ```typescript\n * // Simple execution\n * const handle = connector.execute('CREATE TABLE test AS SELECT * FROM source');\n * await handle.result;\n *\n * // With external cancellation control\n * const controller = new AbortController();\n * const handle = connector.execute('DROP TABLE large_table', {\n * signal: controller.signal\n * });\n *\n * // Cancel if it takes too long\n * setTimeout(() => controller.abort(), 5000);\n * ```\n */\n execute(sql: string, options?: QueryOptions): QueryHandle;\n\n /**\n * Execute a SQL query and return the result as an Arrow table\n *\n * @param query SQL query to execute\n * @param options Optional query options including abort signal for coordinated cancellation\n * @returns QueryHandle containing:\n * - result: Promise that resolves with Arrow table\n * - cancel: Method to cancel the query with cleanup\n * - signal: AbortSignal for composability with other cancellable operations\n *\n * @example\n * ```typescript\n * // Basic query\n * const handle = connector.query('SELECT * FROM users WHERE active = true');\n * const table = await handle.result;\n * console.log(`Found ${table.numRows} active users`);\n *\n * // Query with timeout\n * const controller = new AbortController();\n * setTimeout(() => controller.abort(), 30000); // 30s timeout\n *\n * const handle = connector.query('SELECT * FROM very_large_table', {\n * signal: controller.signal\n * });\n *\n * try {\n * const result = await handle.result;\n * console.log('Query completed within timeout');\n * } catch (error) {\n * if (error.name === 'AbortError') {\n * console.log('Query timed out');\n * }\n * }\n * ```\n */\n query<T extends TypeMap = any>(\n query: string,\n options?: QueryOptions,\n ): QueryHandle<arrow.Table<T>>;\n\n /**\n * Execute a SQL query and return the result as a JSON object\n *\n * @param query SQL query to execute\n * @param options Optional query options including abort signal for coordinated cancellation\n * @returns QueryHandle containing:\n * - result: Promise that resolves with iterable of JSON objects\n * - cancel: Method to cancel the query with cleanup\n * - signal: AbortSignal for composability with other cancellable operations\n *\n * @example\n * ```typescript\n * // Simple JSON query\n * const handle = connector.queryJson('SELECT name, email FROM users LIMIT 10');\n * const users = await handle.result;\n * for (const user of users) {\n * console.log(`${user.name}: ${user.email}`);\n * }\n *\n * // Coordinated cancellation with multiple operations\n * const operationController = new AbortController();\n *\n * const usersHandle = connector.queryJson('SELECT * FROM users', {\n * signal: operationController.signal\n * });\n *\n * const ordersHandle = connector.queryJson('SELECT * FROM orders', {\n * signal: operationController.signal\n * });\n *\n * // Cancel both queries if user navigates away\n * window.addEventListener('beforeunload', () => {\n * operationController.abort();\n * });\n * ```\n */\n queryJson<T = Record<string, any>>(\n query: string,\n options?: QueryOptions,\n ): QueryHandle<Iterable<T>>;\n\n /**\n * Load a file into DuckDB and create a table\n * @param fileName - Path to the file to load\n * @param tableName - Name of the table to create\n * @param opts - Load options\n */\n loadFile(\n fileName: string | File,\n tableName: string,\n opts?: LoadFileOptions,\n ): Promise<void>;\n\n /**\n * Load an arrow table or an arrow IPC stream into DuckDB\n * @param table - Arrow table or arrow IPC stream to load\n * @param tableName - Name of the table to create\n */\n loadArrow(\n table: arrow.Table | Uint8Array,\n tableName: string,\n opts?: {schema?: string},\n ): Promise<void>;\n\n /**\n * Load JavaScript objects into DuckDB\n * @param data - Array of objects to load\n * @param tableName - Name of the table to create\n * @param opts - Load options\n */\n loadObjects(\n data: Record<string, unknown>[],\n tableName: string,\n opts?: StandardLoadOptions,\n ): Promise<void>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"DuckDbConnector.js","sourceRoot":"","sources":["../../src/connectors/DuckDbConnector.ts"],"names":[],"mappings":"","sourcesContent":["import {LoadFileOptions, StandardLoadOptions} from '@sqlrooms/room-config';\nimport * as arrow from 'apache-arrow';\nimport {TypeMap} from 'apache-arrow';\n\n/**\n * Options for query execution\n */\nexport interface QueryOptions {\n /**\n * Optional external abort signal for coordinated cancellation.\n * When provided, the query will be cancelled if this signal is aborted.\n * This enables powerful composition patterns like cancelling multiple\n * queries together or integrating with other cancellable operations.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Handle for managing query execution and cancellation.\n *\n * It is **Promise-like**, so you can either:\n *\n * • `await handle` – the most ergonomic form, or\n * • `await handle.result` – kept for backwards-compatibility.\n *\n * Additional capabilities:\n * • Standard Promise API: `.then()`, `.catch()`, `.finally()`\n * • `handle.cancel()` – cancel the running query.\n * • `handle.signal` – `AbortSignal` that fires when the query is cancelled.\n *\n * @example\n * ```typescript\n * // Simple usage\n * const handle = connector.query('SELECT * FROM table');\n * const table = await handle; // no .result needed\n *\n * // With cancellation\n * const controller = new AbortController();\n * const handle = connector.query('SELECT * FROM large_table', { signal: controller.signal });\n * setTimeout(() => controller.abort(), 5000);\n *\n * // Manual cancel via the handle\n * const h = connector.query('SELECT * FROM table');\n * await someCondition;\n * await h.cancel();\n *\n * // Composable cancellation (multiple queries, one controller)\n * const controller = new AbortController();\n * const h1 = connector.query('SELECT * FROM table1', { signal: controller.signal });\n * const h2 = connector.query('SELECT * FROM table2', { signal: controller.signal });\n * // Later...\n * controller.abort(); // Cancels h1 and h2 together\n *\n * // Using Promise utilities\n * const [t1, t2] = await Promise.all([\n * connector.query('select 1'),\n * connector.query('select 2')\n * ]);\n * ```\n */\nexport type QueryHandle<T = any> = PromiseLike<T> & {\n /** Promise that resolves with query results */\n result: Promise<T>;\n\n /**\n * Method to cancel the query with optional cleanup.\n * This provides a clean abstraction over the underlying cancellation mechanism.\n */\n cancel: () => Promise<void>;\n\n /**\n * Read-only access to the abort signal for composability.\n *\n * Key benefits:\n * - **Event-driven**: Listen for abort events to update UI or perform cleanup\n * - **Integration**: Use with other Web APIs like fetch() that accept AbortSignal\n * - **Status checking**: Check if query is already cancelled with signal.aborted\n *\n * @example\n * ```typescript\n * // Listen for cancellation events\n * handle.signal.addEventListener('abort', () => {\n * console.log('Query cancelled');\n * updateUI('Operation cancelled');\n * });\n *\n * // Check cancellation status\n * if (handle.signal.aborted) {\n * console.log('Query was already cancelled');\n * }\n *\n * // Use with other APIs\n * const response = await fetch('/api/data', { signal: handle.signal });\n * ```\n */\n signal: AbortSignal;\n\n /** Attach a callback for only the rejection of the Promise */\n catch: Promise<T>['catch'];\n\n /** Attach a callback that's invoked when the Promise is settled (fulfilled or rejected) */\n finally: Promise<T>['finally'];\n};\n\n/**\n * DuckDB connector interface with advanced query cancellation support\n *\n * This interface provides a hybrid approach that combines the simplicity of method-based\n * cancellation with the composability of Web Standards (AbortController/AbortSignal).\n *\n * ## Key Benefits of This Design\n *\n * ### 🔗 Composability\n * Cancel multiple queries with a single controller:\n * ```typescript\n * const controller = new AbortController();\n * const query1 = connector.query('SELECT * FROM table1', { signal: controller.signal });\n * const query2 = connector.query('SELECT * FROM table2', { signal: controller.signal });\n * controller.abort(); // Cancels both queries\n * ```\n *\n * ### 🌐 Integration with Web APIs\n * Use the same signal for queries and HTTP requests:\n * ```typescript\n * const controller = new AbortController();\n * const queryHandle = connector.query('SELECT * FROM table', { signal: controller.signal });\n * const response = await fetch('/api/data', { signal: controller.signal });\n * // controller.abort() cancels both the query and the HTTP request\n * ```\n *\n * ### 🎛️ Flexibility\n * Simple usage when you don't need external control, advanced when you do:\n * ```typescript\n * // Simple - internal cancellation management\n * const handle = connector.query('SELECT * FROM table');\n * handle.cancel();\n *\n * // Advanced - external cancellation control\n * const controller = new AbortController();\n * const handle = connector.query('SELECT * FROM table', { signal: controller.signal });\n * controller.abort();\n * ```\n *\n * ### 📡 Event-Driven\n * React to cancellation events for better UX:\n * ```typescript\n * handle.signal.addEventListener('abort', () => {\n * showNotification('Query cancelled');\n * hideLoadingSpinner();\n * });\n * ```\n *\n * ### ⏱️ Timeout Support\n * Built-in timeout capability with manual override:\n * ```typescript\n * const timeoutController = new AbortController();\n * setTimeout(() => timeoutController.abort(), 30000); // 30s timeout\n *\n * const handle = connector.query('SELECT * FROM large_table', {\n * signal: timeoutController.signal\n * });\n *\n * // User can still cancel manually\n * cancelButton.onclick = () => timeoutController.abort();\n * ```\n *\n * ### 🏗️ Signal Composition\n * Combine multiple cancellation sources:\n * ```typescript\n * function combineSignals(...signals: AbortSignal[]): AbortSignal {\n * const controller = new AbortController();\n * signals.forEach(signal => {\n * if (signal.aborted) controller.abort();\n * else signal.addEventListener('abort', () => controller.abort());\n * });\n * return controller.signal;\n * }\n *\n * const userSignal = userController.signal;\n * const timeoutSignal = createTimeoutSignal(30000);\n * const combinedSignal = combineSignals(userSignal, timeoutSignal);\n *\n * const handle = connector.query('SELECT * FROM table', { signal: combinedSignal });\n * ```\n */\nexport interface DuckDbConnector {\n /**\n * Initialize the connector.\n * The function returns a promise that resolves when the connector is initialized.\n * Calling the initialize() function multiple times should not restart the initialization.\n * See BaseDuckDbConnector for an implementation example.\n */\n initialize(): Promise<void>;\n\n /**\n * Destroy the connector and clean up resources\n */\n destroy(): Promise<void>;\n\n /**\n * Execute a SQL query without returning a result\n *\n * @param sql SQL query to execute\n * @param options Optional query options including abort signal for coordinated cancellation\n * @returns QueryHandle containing:\n * - result: Promise that resolves when execution completes\n * - cancel: Method to cancel the query with cleanup\n * - signal: AbortSignal for composability with other cancellable operations\n *\n * @example\n * ```typescript\n * // Simple execution\n * const handle = connector.execute('CREATE TABLE test AS SELECT * FROM source');\n * await handle.result;\n *\n * // With external cancellation control\n * const controller = new AbortController();\n * const handle = connector.execute('DROP TABLE large_table', {\n * signal: controller.signal\n * });\n *\n * // Cancel if it takes too long\n * setTimeout(() => controller.abort(), 5000);\n * ```\n */\n execute(sql: string, options?: QueryOptions): QueryHandle;\n\n /**\n * Execute a SQL query and return the result as an Arrow table\n *\n * @param query SQL query to execute\n * @param options Optional query options including abort signal for coordinated cancellation\n * @returns QueryHandle containing:\n * - result: Promise that resolves with Arrow table\n * - cancel: Method to cancel the query with cleanup\n * - signal: AbortSignal for composability with other cancellable operations\n *\n * @example\n * ```typescript\n * // Basic query\n * const handle = await connector.query('SELECT * FROM users WHERE active = true');\n * console.log(`Found ${table.numRows} active users`);\n *\n * // Query with timeout\n * const controller = new AbortController();\n * setTimeout(() => controller.abort(), 30000); // 30s timeout\n *\n * const handle = connector.query('SELECT * FROM very_large_table', {\n * signal: controller.signal\n * });\n *\n * try {\n * const result = await handle;\n * console.log('Query completed within timeout');\n * } catch (error) {\n * if (error.name === 'AbortError') {\n * console.log('Query timed out');\n * }\n * }\n * ```\n */\n query<T extends TypeMap = any>(\n query: string,\n options?: QueryOptions,\n ): QueryHandle<arrow.Table<T>>;\n\n /**\n * Execute a SQL query and return the result as a JSON object\n *\n * @param query SQL query to execute\n * @param options Optional query options including abort signal for coordinated cancellation\n * @returns QueryHandle containing:\n * - result: Promise that resolves with iterable of JSON objects\n * - cancel: Method to cancel the query with cleanup\n * - signal: AbortSignal for composability with other cancellable operations\n *\n * @example\n * ```typescript\n * // Simple JSON query\n * const users = await connector.queryJson('SELECT name, email FROM users LIMIT 10');\n * for (const user of users) {\n * console.log(`${user.name}: ${user.email}`);\n * }\n *\n * // Coordinated cancellation with multiple operations\n * const operationController = new AbortController();\n *\n * const usersHandle = connector.queryJson('SELECT * FROM users', {\n * signal: operationController.signal\n * });\n *\n * const ordersHandle = connector.queryJson('SELECT * FROM orders', {\n * signal: operationController.signal\n * });\n *\n * // Cancel both queries if user navigates away\n * window.addEventListener('beforeunload', () => {\n * operationController.abort();\n * });\n * ```\n */\n queryJson<T = Record<string, any>>(\n query: string,\n options?: QueryOptions,\n ): QueryHandle<Iterable<T>>;\n\n /**\n * Load a file into DuckDB and create a table\n * @param fileName - Path to the file to load\n * @param tableName - Name of the table to create\n * @param opts - Load options\n */\n loadFile(\n fileName: string | File,\n tableName: string,\n opts?: LoadFileOptions,\n ): Promise<void>;\n\n /**\n * Load an arrow table or an arrow IPC stream into DuckDB\n * @param table - Arrow table or arrow IPC stream to load\n * @param tableName - Name of the table to create\n */\n loadArrow(\n table: arrow.Table | Uint8Array,\n tableName: string,\n opts?: {schema?: string},\n ): Promise<void>;\n\n /**\n * Load JavaScript objects into DuckDB\n * @param data - Array of objects to load\n * @param tableName - Name of the table to create\n * @param opts - Load options\n */\n loadObjects(\n data: Record<string, unknown>[],\n tableName: string,\n opts?: StandardLoadOptions,\n ): Promise<void>;\n}\n"]}
|
package/dist/exportToCsv.js
CHANGED
|
@@ -11,7 +11,7 @@ export function useExportToCsv() {
|
|
|
11
11
|
const currentQuery = `(
|
|
12
12
|
${query}
|
|
13
13
|
) LIMIT ${pageSize} OFFSET ${offset}`;
|
|
14
|
-
const results = await dbConnector.query(currentQuery)
|
|
14
|
+
const results = await dbConnector.query(currentQuery);
|
|
15
15
|
// Check if we received any results; if not, we are done.
|
|
16
16
|
if (results.numRows === 0) {
|
|
17
17
|
break;
|
package/dist/exportToCsv.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exportToCsv.js","sourceRoot":"","sources":["../src/exportToCsv.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAEjD,MAAM,UAAU,cAAc;IAC5B,MAAM,YAAY,GAAG,kBAAkB,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC;IAC1E,OAAO;QACL,WAAW,EAAE,KAAK,EAAE,KAAa,EAAE,QAAgB,EAAE,QAAQ,GAAG,MAAM,EAAE,EAAE;YACxE,MAAM,WAAW,GAAG,MAAM,YAAY,EAAE,CAAC;YAEzC,IAAI,MAAM,GAAG,CAAC,CAAC;YACf,MAAM,KAAK,GAAW,EAAE,CAAC;YACzB,IAAI,YAAY,GAAG,KAAK,CAAC;YAEzB,OAAO,IAAI,EAAE,CAAC;gBACZ,MAAM,YAAY,GAAG;YACjB,KAAK;kBACC,QAAQ,WAAW,MAAM,EAAE,CAAC;gBACtC,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC
|
|
1
|
+
{"version":3,"file":"exportToCsv.js","sourceRoot":"","sources":["../src/exportToCsv.ts"],"names":[],"mappings":"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","sourcesContent":["import * as arrow from 'apache-arrow';\nimport {useStoreWithDuckDb} from './DuckDbSlice';\n\nexport function useExportToCsv() {\n const getConnector = useStoreWithDuckDb((state) => state.db.getConnector);\n return {\n exportToCsv: async (query: string, fileName: string, pageSize = 100000) => {\n const dbConnector = await getConnector();\n\n let offset = 0;\n const blobs: Blob[] = [];\n let headersAdded = false;\n\n while (true) {\n const currentQuery = `(\n ${query}\n ) LIMIT ${pageSize} OFFSET ${offset}`;\n const results = await dbConnector.query(currentQuery);\n\n // Check if we received any results; if not, we are done.\n if (results.numRows === 0) {\n break;\n }\n\n const csvChunk = convertToCsv(results, !headersAdded);\n blobs.push(new Blob([csvChunk], {type: 'text/csv'}));\n\n // Ensure that headers are not added in subsequent iterations\n headersAdded = true;\n\n // Increment offset to fetch the next chunk\n offset += pageSize;\n }\n\n const fullCsvBlob = new Blob(blobs, {type: 'text/csv'});\n downloadBlob(fullCsvBlob, fileName);\n },\n };\n}\n\nfunction convertToCsv(\n arrowTable: arrow.Table,\n includeHeaders: boolean,\n): string {\n // return includeHeaders\n // ? csvFormat(arrowTable.toArray())\n // : csvFormatBody(arrowTable.toArray());\n\n const columnNames = arrowTable.schema.fields.map((field) => field.name);\n const columnsByName = columnNames.reduce(\n (acc, columnName) => {\n const col = arrowTable.getChild(columnName);\n if (col) acc[columnName] = col;\n return acc;\n },\n {} as Record<string, arrow.Vector>,\n );\n\n // Add header\n let csvContent = includeHeaders ? columnNames.join(',') + '\\r\\n' : '';\n\n // Add data rows\n for (let i = 0; i < arrowTable.numRows; i++) {\n const csvRow = columnNames\n .map((columnName) => {\n const cellValue = columnsByName[columnName]?.get(i);\n\n // If the cell value is null or undefined, set it to an empty string.\n if (cellValue == null) return '';\n\n // Convert cell value to string\n let cellValueStr = String(cellValue);\n\n // Escape double quotes and wrap cell value in double quotes if necessary\n if (\n cellValueStr.includes('\"') ||\n cellValueStr.includes(',') ||\n cellValueStr.includes('\\n')\n ) {\n cellValueStr = '\"' + cellValueStr.replace(/\"/g, '\"\"') + '\"';\n }\n\n return cellValueStr;\n })\n .join(',');\n\n csvContent += csvRow + '\\r\\n';\n }\n\n return csvContent;\n}\n\nfunction downloadBlob(blob: Blob, filename: string) {\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = filename;\n document.body.appendChild(a);\n a.click();\n URL.revokeObjectURL(url);\n document.body.removeChild(a);\n}\n"]}
|
package/dist/useDuckDb.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import * as duckdb from '@duckdb/duckdb-wasm';
|
|
2
2
|
import { DuckDbConnector } from './connectors/DuckDbConnector';
|
|
3
3
|
/**
|
|
4
|
-
* @deprecated
|
|
4
|
+
* @deprecated
|
|
5
5
|
*/
|
|
6
6
|
export type DuckConn = DuckDb;
|
|
7
|
+
/**
|
|
8
|
+
* @deprecated
|
|
9
|
+
*/
|
|
7
10
|
export type DuckDb = {
|
|
8
11
|
db: duckdb.AsyncDuckDB;
|
|
9
12
|
conn: duckdb.AsyncDuckDBConnection;
|
package/dist/useDuckDb.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDuckDb.d.ts","sourceRoot":"","sources":["../src/useDuckDb.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,qBAAqB,CAAC;AAE9C,OAAO,EAAC,eAAe,EAAC,MAAM,8BAA8B,CAAC;AAE7D;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE9B,MAAM,MAAM,MAAM,GAAG;IACnB,EAAE,EAAE,MAAM,CAAC,WAAW,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC,qBAAqB,CAAC;IACnC,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAgB,SAAS,IAAI,eAAe,CAG3C"}
|
|
1
|
+
{"version":3,"file":"useDuckDb.d.ts","sourceRoot":"","sources":["../src/useDuckDb.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,qBAAqB,CAAC;AAE9C,OAAO,EAAC,eAAe,EAAC,MAAM,8BAA8B,CAAC;AAE7D;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE9B;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG;IACnB,EAAE,EAAE,MAAM,CAAC,WAAW,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC,qBAAqB,CAAC;IACnC,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAgB,SAAS,IAAI,eAAe,CAG3C"}
|
package/dist/useDuckDb.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDuckDb.js","sourceRoot":"","sources":["../src/useDuckDb.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"useDuckDb.js","sourceRoot":"","sources":["../src/useDuckDb.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAiBjD,MAAM,UAAU,SAAS;IACvB,MAAM,SAAS,GAAG,kBAAkB,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC;IACpE,OAAO,SAAS,CAAC;AACnB,CAAC","sourcesContent":["import * as duckdb from '@duckdb/duckdb-wasm';\nimport {useStoreWithDuckDb} from './DuckDbSlice';\nimport {DuckDbConnector} from './connectors/DuckDbConnector';\n\n/**\n * @deprecated\n */\nexport type DuckConn = DuckDb;\n\n/**\n * @deprecated\n */\nexport type DuckDb = {\n db: duckdb.AsyncDuckDB;\n conn: duckdb.AsyncDuckDBConnection;\n worker: Worker;\n};\n\nexport function useDuckDb(): DuckDbConnector {\n const connector = useStoreWithDuckDb((state) => state.db.connector);\n return connector;\n}\n"]}
|
package/dist/useSql.js
CHANGED
package/dist/useSql.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSql.js","sourceRoot":"","sources":["../src/useSql.ts"],"names":[],"mappings":"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","sourcesContent":["import * as arrow from 'apache-arrow';\nimport {useEffect, useState} from 'react';\nimport {z} from 'zod';\nimport {useStoreWithDuckDb} from './DuckDbSlice';\nimport {createTypedRowAccessor, TypedRowAccessor} from './typedRowAccessor';\nimport {QueryHandle} from './connectors/DuckDbConnector';\n\n/**\n * A wrapper interface that exposes the underlying Arrow table,\n * a typed row accessor, and the number of rows.\n */\nexport interface UseSqlQueryResult<T> extends TypedRowAccessor<T> {\n /** The underlying Arrow table */\n arrowTable: arrow.Table;\n}\n\n/**\n * @deprecated Use UseSqlQueryResult instead\n */\nexport type DuckDbQueryResult<T> = UseSqlQueryResult<T>;\n\n/**\n * A React hook for executing SQL queries with automatic state management.\n * Provides two ways to ensure type safety:\n * 1. Using TypeScript types (compile-time safety only)\n * 2. Using Zod schemas (both compile-time and runtime validation)\n *\n * @example\n * ```typescript\n * // Option 1: Using TypeScript types (faster, no runtime validation)\n * interface User {\n * id: number;\n * name: string;\n * email: string;\n * }\n *\n * const {data, isLoading, error} = useSql<User>({\n * query: 'SELECT id, name, email FROM users'\n * });\n *\n * // Option 2: Using Zod schema (slower but with runtime validation)\n * const userSchema = z.object({\n * id: z.number(),\n * name: z.string(),\n * email: z.string().email(),\n * createdAt: z.string().transform(str => new Date(str)) // Transform string to Date\n * });\n *\n * const {data: validatedData, isLoading, error} = useSql(\n * userSchema,\n * {query: 'SELECT id, name, email, created_at as createdAt FROM users'}\n * );\n * ```\n *\n * ## Error Handling\n * ```typescript\n * if (isLoading) return <div>Loading...</div>;\n * if (error) {\n * // With Zod, you can catch validation errors specifically\n * if (error instanceof z.ZodError) {\n * return <div>Validation Error: {error.errors[0].message}</div>;\n * }\n * return <div>Error: {error.message}</div>;\n * }\n * if (!data) return null;\n * ```\n *\n * ## Data Access Methods\n *\n * There are several ways to access data with different performance characteristics:\n *\n * ### 1. Typed Row Access (getRow, rows(), toArray())\n * - Provides type safety and validation\n * - Converts data to JavaScript objects\n * - Slower for large datasets due to object creation and validation\n *\n * ```typescript\n * // Iterate through rows using the rows() iterator (recommended)\n * for (const user of data.rows()) {\n * console.log(user.name, user.email);\n * }\n *\n * // Traditional for loop with index access\n * for (let i = 0; i < data.length; i++) {\n * const user = data.getRow(i);\n * console.log(`User ${i}: ${user.name} (${user.email})`);\n * }\n *\n * // Get all rows as an array\n * const allUsers = data.toArray();\n *\n * // With Zod schema, transformed fields are available\n * for (const user of validatedData.rows()) {\n * console.log(`Created: ${user.createdAt.toISOString()}`); // createdAt is a Date object\n * }\n * ```\n *\n * ### 2. Direct Arrow Table Access\n * - Much faster for large datasets\n * - Columnar access is more efficient for analytics\n * - No type safety or validation\n *\n * ```typescript\n * // For performance-critical operations with large datasets:\n * const nameColumn = data.arrowTable.getChild('name');\n * const emailColumn = data.arrowTable.getChild('email');\n *\n * // Fast columnar iteration (no object creation)\n * for (let i = 0; i < data.length; i++) {\n * console.log(nameColumn.get(i), emailColumn.get(i));\n * }\n *\n * // Note: For filtering data, it's most efficient to use SQL in your query\n * const { data } = useSql<User>({\n * query: \"SELECT * FROM users WHERE age > 30\"\n * });\n * ```\n *\n * ### 3. Using Flechette for Advanced Operations\n *\n * For more advanced Arrow operations, consider using [Flechette](https://idl.uw.edu/flechette/),\n * a faster and lighter alternative to the standard Arrow JS implementation.\n *\n * ```typescript\n * // Example using Flechette with SQL query results\n * import { tableFromIPC } from '@uwdata/flechette';\n *\n * // Convert Arrow table to Flechette table\n * const serializedData = data.arrowTable.serialize();\n * const flechetteTable = tableFromIPC(serializedData);\n *\n * // Extract all columns into a { name: array, ... } object\n * const columns = flechetteTable.toColumns();\n *\n * // Create a new table with a selected subset of columns\n * const subtable = flechetteTable.select(['name', 'email']);\n *\n * // Convert to array of objects with customization options\n * const objects = flechetteTable.toArray({\n * useDate: true, // Convert timestamps to Date objects\n * useMap: true // Create Map objects for key-value pairs\n * });\n *\n * // For large datasets, consider memory management\n * serializedData = null; // Allow garbage collection of the serialized data\n * ```\n *\n * Flechette provides several advantages:\n * - Better performance (1.3-1.6x faster value iteration, 7-11x faster row object extraction)\n * - Smaller footprint (~43k minified vs 163k for Arrow JS)\n * - Support for additional data types (including decimal-to-number conversion)\n * - More flexible data value conversion options\n *\n * @template Row The TypeScript type for each row in the result\n * @param options Configuration object containing the query and execution control\n * @returns Object containing the query result, loading state, and any error\n *\n * @template Schema The Zod schema type that defines the shape and validation of each row\n * @param zodSchema A Zod schema that defines the expected shape and validation rules for each row\n * @param options Configuration object containing the query and execution control\n * @returns Object containing the validated query result, loading state, and any error\n */\nexport function useSql<Row>(options: {query: string; enabled?: boolean}): {\n data: UseSqlQueryResult<Row> | undefined;\n error: Error | null;\n isLoading: boolean;\n};\n\nexport function useSql<Schema extends z.ZodType>(\n zodSchema: Schema,\n options: {\n query: string;\n enabled?: boolean;\n },\n): {\n data: UseSqlQueryResult<z.infer<Schema>> | undefined;\n error: Error | null;\n isLoading: boolean;\n};\n\n/**\n * Implementation of useSql that handles both overloads\n */\nexport function useSql<\n Row extends arrow.TypeMap,\n Schema extends z.ZodType = z.ZodType,\n>(\n zodSchemaOrOptions: Schema | {query: string; enabled?: boolean},\n maybeOptions?: {query: string; enabled?: boolean},\n) {\n // Determine if we're using the schema overload\n const hasZodSchema = maybeOptions !== undefined;\n const options = hasZodSchema\n ? maybeOptions\n : (zodSchemaOrOptions as {query: string; enabled?: boolean});\n const schema = hasZodSchema ? (zodSchemaOrOptions as Schema) : undefined;\n\n const [data, setData] = useState<UseSqlQueryResult<Row> | undefined>(\n undefined,\n );\n const [error, setError] = useState<Error | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n const executeSql = useStoreWithDuckDb((state) => state.db.executeSql);\n\n useEffect(() => {\n let isMounted = true;\n\n const fetchData = async () => {\n if (!options.enabled && options.enabled !== undefined) {\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const queryHandle = await executeSql(options.query);\n if (!queryHandle || !isMounted) {\n return;\n }\n\n const result = await queryHandle.result;\n if (!isMounted) {\n return;\n }\n\n // Create a row accessor that optionally validates with the schema\n const rowAccessor = createTypedRowAccessor<Row>({\n arrowTable: result,\n validate: schema ? (row: unknown) => schema.parse(row) : undefined,\n });\n\n setData({...rowAccessor, arrowTable: result});\n } catch (err) {\n if (isMounted) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n } finally {\n if (isMounted) {\n setIsLoading(false);\n }\n }\n };\n\n fetchData();\n\n return () => {\n isMounted = false;\n };\n }, [options.query, options.enabled, executeSql]);\n\n return {\n data,\n error,\n isLoading,\n };\n}\n\n/**\n * @deprecated Use useSql instead\n */\nexport const useDuckDbQuery = useSql;\n"]}
|
|
1
|
+
{"version":3,"file":"useSql.js","sourceRoot":"","sources":["../src/useSql.ts"],"names":[],"mappings":"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","sourcesContent":["import * as arrow from 'apache-arrow';\nimport {useEffect, useState} from 'react';\nimport {z} from 'zod';\nimport {useStoreWithDuckDb} from './DuckDbSlice';\nimport {createTypedRowAccessor, TypedRowAccessor} from './typedRowAccessor';\nimport {QueryHandle} from './connectors/DuckDbConnector';\n\n/**\n * A wrapper interface that exposes the underlying Arrow table,\n * a typed row accessor, and the number of rows.\n */\nexport interface UseSqlQueryResult<T> extends TypedRowAccessor<T> {\n /** The underlying Arrow table */\n arrowTable: arrow.Table;\n}\n\n/**\n * @deprecated Use UseSqlQueryResult instead\n */\nexport type DuckDbQueryResult<T> = UseSqlQueryResult<T>;\n\n/**\n * A React hook for executing SQL queries with automatic state management.\n * Provides two ways to ensure type safety:\n * 1. Using TypeScript types (compile-time safety only)\n * 2. Using Zod schemas (both compile-time and runtime validation)\n *\n * @example\n * ```typescript\n * // Option 1: Using TypeScript types (faster, no runtime validation)\n * interface User {\n * id: number;\n * name: string;\n * email: string;\n * }\n *\n * const {data, isLoading, error} = useSql<User>({\n * query: 'SELECT id, name, email FROM users'\n * });\n *\n * // Option 2: Using Zod schema (slower but with runtime validation)\n * const userSchema = z.object({\n * id: z.number(),\n * name: z.string(),\n * email: z.string().email(),\n * createdAt: z.string().transform(str => new Date(str)) // Transform string to Date\n * });\n *\n * const {data: validatedData, isLoading, error} = useSql(\n * userSchema,\n * {query: 'SELECT id, name, email, created_at as createdAt FROM users'}\n * );\n * ```\n *\n * ## Error Handling\n * ```typescript\n * if (isLoading) return <div>Loading...</div>;\n * if (error) {\n * // With Zod, you can catch validation errors specifically\n * if (error instanceof z.ZodError) {\n * return <div>Validation Error: {error.errors[0].message}</div>;\n * }\n * return <div>Error: {error.message}</div>;\n * }\n * if (!data) return null;\n * ```\n *\n * ## Data Access Methods\n *\n * There are several ways to access data with different performance characteristics:\n *\n * ### 1. Typed Row Access (getRow, rows(), toArray())\n * - Provides type safety and validation\n * - Converts data to JavaScript objects\n * - Slower for large datasets due to object creation and validation\n *\n * ```typescript\n * // Iterate through rows using the rows() iterator (recommended)\n * for (const user of data.rows()) {\n * console.log(user.name, user.email);\n * }\n *\n * // Traditional for loop with index access\n * for (let i = 0; i < data.length; i++) {\n * const user = data.getRow(i);\n * console.log(`User ${i}: ${user.name} (${user.email})`);\n * }\n *\n * // Get all rows as an array\n * const allUsers = data.toArray();\n *\n * // With Zod schema, transformed fields are available\n * for (const user of validatedData.rows()) {\n * console.log(`Created: ${user.createdAt.toISOString()}`); // createdAt is a Date object\n * }\n * ```\n *\n * ### 2. Direct Arrow Table Access\n * - Much faster for large datasets\n * - Columnar access is more efficient for analytics\n * - No type safety or validation\n *\n * ```typescript\n * // For performance-critical operations with large datasets:\n * const nameColumn = data.arrowTable.getChild('name');\n * const emailColumn = data.arrowTable.getChild('email');\n *\n * // Fast columnar iteration (no object creation)\n * for (let i = 0; i < data.length; i++) {\n * console.log(nameColumn.get(i), emailColumn.get(i));\n * }\n *\n * // Note: For filtering data, it's most efficient to use SQL in your query\n * const { data } = useSql<User>({\n * query: \"SELECT * FROM users WHERE age > 30\"\n * });\n * ```\n *\n * ### 3. Using Flechette for Advanced Operations\n *\n * For more advanced Arrow operations, consider using [Flechette](https://idl.uw.edu/flechette/),\n * a faster and lighter alternative to the standard Arrow JS implementation.\n *\n * ```typescript\n * // Example using Flechette with SQL query results\n * import { tableFromIPC } from '@uwdata/flechette';\n *\n * // Convert Arrow table to Flechette table\n * const serializedData = data.arrowTable.serialize();\n * const flechetteTable = tableFromIPC(serializedData);\n *\n * // Extract all columns into a { name: array, ... } object\n * const columns = flechetteTable.toColumns();\n *\n * // Create a new table with a selected subset of columns\n * const subtable = flechetteTable.select(['name', 'email']);\n *\n * // Convert to array of objects with customization options\n * const objects = flechetteTable.toArray({\n * useDate: true, // Convert timestamps to Date objects\n * useMap: true // Create Map objects for key-value pairs\n * });\n *\n * // For large datasets, consider memory management\n * serializedData = null; // Allow garbage collection of the serialized data\n * ```\n *\n * Flechette provides several advantages:\n * - Better performance (1.3-1.6x faster value iteration, 7-11x faster row object extraction)\n * - Smaller footprint (~43k minified vs 163k for Arrow JS)\n * - Support for additional data types (including decimal-to-number conversion)\n * - More flexible data value conversion options\n *\n * @template Row The TypeScript type for each row in the result\n * @param options Configuration object containing the query and execution control\n * @returns Object containing the query result, loading state, and any error\n *\n * @template Schema The Zod schema type that defines the shape and validation of each row\n * @param zodSchema A Zod schema that defines the expected shape and validation rules for each row\n * @param options Configuration object containing the query and execution control\n * @returns Object containing the validated query result, loading state, and any error\n */\nexport function useSql<Row>(options: {query: string; enabled?: boolean}): {\n data: UseSqlQueryResult<Row> | undefined;\n error: Error | null;\n isLoading: boolean;\n};\n\nexport function useSql<Schema extends z.ZodType>(\n zodSchema: Schema,\n options: {\n query: string;\n enabled?: boolean;\n },\n): {\n data: UseSqlQueryResult<z.infer<Schema>> | undefined;\n error: Error | null;\n isLoading: boolean;\n};\n\n/**\n * Implementation of useSql that handles both overloads\n */\nexport function useSql<\n Row extends arrow.TypeMap,\n Schema extends z.ZodType = z.ZodType,\n>(\n zodSchemaOrOptions: Schema | {query: string; enabled?: boolean},\n maybeOptions?: {query: string; enabled?: boolean},\n) {\n // Determine if we're using the schema overload\n const hasZodSchema = maybeOptions !== undefined;\n const options = hasZodSchema\n ? maybeOptions\n : (zodSchemaOrOptions as {query: string; enabled?: boolean});\n const schema = hasZodSchema ? (zodSchemaOrOptions as Schema) : undefined;\n\n const [data, setData] = useState<UseSqlQueryResult<Row> | undefined>(\n undefined,\n );\n const [error, setError] = useState<Error | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n const executeSql = useStoreWithDuckDb((state) => state.db.executeSql);\n\n useEffect(() => {\n let isMounted = true;\n\n const fetchData = async () => {\n if (!options.enabled && options.enabled !== undefined) {\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const queryHandle = await executeSql(options.query);\n if (!queryHandle || !isMounted) {\n return;\n }\n\n const result = await queryHandle;\n if (!isMounted) {\n return;\n }\n\n // Create a row accessor that optionally validates with the schema\n const rowAccessor = createTypedRowAccessor<Row>({\n arrowTable: result,\n validate: schema ? (row: unknown) => schema.parse(row) : undefined,\n });\n\n setData({...rowAccessor, arrowTable: result});\n } catch (err) {\n if (isMounted) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n } finally {\n if (isMounted) {\n setIsLoading(false);\n }\n }\n };\n\n fetchData();\n\n return () => {\n isMounted = false;\n };\n }, [options.query, options.enabled, executeSql]);\n\n return {\n data,\n error,\n isLoading,\n };\n}\n\n/**\n * @deprecated Use useSql instead\n */\nexport const useDuckDbQuery = useSql;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sqlrooms/duckdb",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@duckdb/duckdb-wasm": "1.29.1-dev204.0",
|
|
22
|
-
"@sqlrooms/core": "0.
|
|
23
|
-
"@sqlrooms/utils": "0.
|
|
22
|
+
"@sqlrooms/core": "0.18.0",
|
|
23
|
+
"@sqlrooms/utils": "0.18.0",
|
|
24
24
|
"fast-deep-equal": "^3.1.3",
|
|
25
25
|
"immer": "^10.1.1",
|
|
26
26
|
"zod": "^3.25.57",
|
|
@@ -43,5 +43,5 @@
|
|
|
43
43
|
"test": "jest",
|
|
44
44
|
"test:watch": "jest --watch"
|
|
45
45
|
},
|
|
46
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "c1c06c9549ca74b9d4f515f6667b77d3196652df"
|
|
47
47
|
}
|