@sqlrooms/duckdb 0.16.4 → 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 CHANGED
@@ -2,12 +2,25 @@ A powerful wrapper around DuckDB-WASM that provides React hooks and utilities fo
2
2
 
3
3
  ## Features
4
4
 
5
- - 🔄 **React Integration**: Hooks for seamless integration with React applications
6
- - 📊 **Type-Safe Queries**: Execute SQL queries with TypeScript type safety
7
- - 🔍 **Data Validation**: Optional runtime validation using Zod schemas
8
- - 📁 **File Operations**: Import data from various file formats (CSV, JSON, Parquet)
9
- - 📤 **Data Export**: Export query results to CSV files
10
- - 🏹 **Arrow Integration**: Work with Apache Arrow tables for efficient data processing
5
+ ### React Integration & Type Safety
6
+
7
+ - **React Hooks**: Seamless integration with React applications via `useSql`
8
+ - **Runtime Validation**: Optional Zod schema validation for query results with type transformations
9
+ - **Typed Row Accessors**: Type-safe row access with validation and multiple iteration methods
10
+
11
+ ### Data Management
12
+
13
+ - **File Operations**: Import data from various file formats (CSV, JSON, Parquet) with auto-detection
14
+ - **Arrow Integration**: Work directly with Apache Arrow tables for efficient columnar data processing
15
+ - **Schema Management**: Comprehensive database, schema, and table discovery and management
16
+ - **Qualified Table Names**: Full support for `database.schema.table` naming convention
17
+
18
+ ### Performance & Operations
19
+
20
+ - **Query Deduplication**: Automatic deduplication of identical running queries to prevent duplicate execution
21
+ - **Query Cancellation**: Cancel running queries with full composability support via `QueryHandle` interface ([learn more](https://sqlrooms.org/query-cancellation))
22
+ - **Data Export**: Export query results to CSV files with pagination for large datasets
23
+ - **Batch Processing**: Handle large datasets efficiently with built-in pagination support
11
24
 
12
25
  ## Installation
13
26
 
@@ -84,53 +97,173 @@ function ValidatedUserList() {
84
97
  }
85
98
  ```
86
99
 
87
- ### Creating Tables from Different Sources
100
+ ## Working with Tables
101
+
102
+ ### Using the Store for Direct Database Operations
88
103
 
89
104
  ```tsx
90
- import {
91
- createTableFromQuery,
92
- createTableFromObjects,
93
- createViewFromFile,
94
- } from '@sqlrooms/duckdb';
95
-
96
- // Create a table from a SQL query
97
- await createTableFromQuery(
98
- 'filtered_users',
99
- 'SELECT * FROM users WHERE active = true',
100
- );
101
-
102
- // Create a table from JavaScript objects
103
- const users = [
104
- {id: 1, name: 'Alice', email: 'alice@example.com'},
105
- {id: 2, name: 'Bob', email: 'bob@example.com'},
106
- ];
107
- await createTableFromObjects('new_users', users);
108
-
109
- // Create a view from a file upload
110
- function FileUploader() {
111
- const handleFileUpload = async (event) => {
112
- const file = event.target.files[0];
113
- if (file) {
114
- await createViewFromFile(file.name, 'main', 'uploaded_data', file);
115
- }
105
+ function DatabaseManager() {
106
+ const createTableFromQuery = useRoomStore(
107
+ (state) => state.db.createTableFromQuery,
108
+ );
109
+ const addTable = useRoomStore((state) => state.db.addTable);
110
+ const dropTable = useRoomStore((state) => state.db.dropTable);
111
+ const tables = useRoomStore((state) => state.db.tables);
112
+ const refreshTableSchemas = useRoomStore(
113
+ (state) => state.db.refreshTableSchemas,
114
+ );
115
+
116
+ // Create a table from a query
117
+ const handleCreateTable = async () => {
118
+ const result = await createTableFromQuery(
119
+ 'filtered_users',
120
+ 'SELECT * FROM users WHERE active = true',
121
+ );
122
+ console.log(`Created table with ${result.rowCount} rows`);
123
+ };
124
+
125
+ // Add a table from JavaScript objects
126
+ const handleAddTable = async () => {
127
+ const users = [
128
+ {id: 1, name: 'Alice', email: 'alice@example.com'},
129
+ {id: 2, name: 'Bob', email: 'bob@example.com'},
130
+ ];
131
+ await addTable('new_users', users);
132
+ };
133
+
134
+ // Drop a table
135
+ const handleDropTable = async () => {
136
+ await dropTable('old_table');
137
+ };
138
+
139
+ return (
140
+ <div>
141
+ <button onClick={handleCreateTable}>Create Filtered Users Table</button>
142
+ <button onClick={handleAddTable}>Add New Users Table</button>
143
+ <button onClick={handleDropTable}>Drop Old Table</button>
144
+ <button onClick={refreshTableSchemas}>Refresh Schemas</button>
145
+
146
+ <h3>Available Tables:</h3>
147
+ <ul>
148
+ {tables.map((table) => (
149
+ <li key={table.table.toString()}>
150
+ {table.table.toString()} ({table.columns.length} columns)
151
+ </li>
152
+ ))}
153
+ </ul>
154
+ </div>
155
+ );
156
+ }
157
+ ```
158
+
159
+ ### Working with Qualified Table Names
160
+
161
+ ```tsx
162
+ import {makeQualifiedTableName} from '@sqlrooms/duckdb';
163
+
164
+ // Support for database.schema.table naming
165
+ const qualifiedTable = makeQualifiedTableName({
166
+ database: 'mydb',
167
+ schema: 'public',
168
+ table: 'users',
169
+ });
170
+
171
+ // Use with table operations
172
+ await createTableFromQuery(qualifiedTable, 'SELECT * FROM source_table');
173
+ await dropTable(qualifiedTable);
174
+ const tableExists = await checkTableExists(qualifiedTable);
175
+ ```
176
+
177
+ ## Loading Data from Files
178
+
179
+ ### Using Load Functions Directly
180
+
181
+ ```tsx
182
+ import {loadCSV, loadJSON, loadParquet, loadObjects} from '@sqlrooms/duckdb';
183
+
184
+ function DataLoader() {
185
+ const getConnector = useRoomStore((state) => state.db.getConnector);
186
+
187
+ const handleLoadCSV = async (file: File) => {
188
+ const connector = await getConnector();
189
+
190
+ // Generate SQL to load CSV file
191
+ const sql = loadCSV('my_table', file.name, {
192
+ auto_detect: true,
193
+ replace: true,
194
+ });
195
+
196
+ // Execute the load operation
197
+ await connector.query(sql).result;
198
+ };
199
+
200
+ const handleLoadObjects = async () => {
201
+ const connector = await getConnector();
202
+ const data = [
203
+ {id: 1, name: 'Alice'},
204
+ {id: 2, name: 'Bob'},
205
+ ];
206
+
207
+ // Generate SQL to load objects
208
+ const sql = loadObjects('users', data, {replace: true});
209
+ await connector.query(sql).result;
210
+ };
211
+
212
+ return (
213
+ <div>
214
+ <input
215
+ type="file"
216
+ accept=".csv"
217
+ onChange={(e) => {
218
+ if (e.target.files?.[0]) handleLoadCSV(e.target.files[0]);
219
+ }}
220
+ />
221
+ <button onClick={handleLoadObjects}>Load Sample Data</button>
222
+ </div>
223
+ );
224
+ }
225
+ ```
226
+
227
+ ### Using the Connector Directly
228
+
229
+ ```tsx
230
+ function AdvancedDataLoader() {
231
+ const connector = useRoomStore((state) => state.db.connector);
232
+
233
+ const handleFileUpload = async (file: File) => {
234
+ // Load file directly using the connector
235
+ await connector.loadFile(file, 'uploaded_data', {
236
+ method: 'auto', // Auto-detect file type
237
+ replace: true,
238
+ temp: false,
239
+ });
240
+ };
241
+
242
+ const handleLoadArrowTable = async (arrowTable: arrow.Table) => {
243
+ // Load Arrow table directly
244
+ await connector.loadArrow(arrowTable, 'arrow_data');
116
245
  };
117
246
 
118
247
  return (
119
248
  <input
120
249
  type="file"
121
250
  accept=".csv,.json,.parquet"
122
- onChange={handleFileUpload}
251
+ onChange={(e) => {
252
+ if (e.target.files?.[0]) handleFileUpload(e.target.files[0]);
253
+ }}
123
254
  />
124
255
  );
125
256
  }
126
257
  ```
127
258
 
128
- ### Exporting Data to CSV
259
+ ## Exporting Data to CSV
129
260
 
130
261
  ```tsx
131
- import {exportToCsv} from '@sqlrooms/duckdb';
262
+ import {useExportToCsv} from '@sqlrooms/duckdb';
132
263
 
133
264
  function ExportButton() {
265
+ const {exportToCsv} = useExportToCsv();
266
+
134
267
  const handleExport = async () => {
135
268
  await exportToCsv('SELECT * FROM users ORDER BY name', 'users_export.csv');
136
269
  };
@@ -139,31 +272,72 @@ function ExportButton() {
139
272
  }
140
273
  ```
141
274
 
142
- ### Low-Level DuckDB Access
275
+ ## Low-Level DuckDB Access
143
276
 
144
- ```tsx
145
- import {getDuckDb} from '@sqlrooms/duckdb';
277
+ ### Basic direct usage
146
278
 
279
+ ```tsx
147
280
  async function executeCustomQuery() {
148
- const {conn} = await getDuckDb();
281
+ // Grab the connector directly (no React hook necessary inside plain TS)
282
+ const connector = useRoomStore((state) => state.db.connector);
149
283
 
150
- // Execute a query directly
151
- const result = await conn.query('SELECT COUNT(*) as count FROM users');
284
+ // QueryHandle is promise-like – await it directly
285
+ const result = await connector.query('SELECT COUNT(*) AS count FROM users');
152
286
 
153
- // Access the Arrow table directly
287
+ // Inspect Arrow table
154
288
  const count = result.getChildAt(0)?.get(0);
155
289
  console.log(`Total users: ${count}`);
290
+ }
291
+ ```
156
292
 
157
- return result;
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]);
158
310
  }
159
311
  ```
160
312
 
161
- ## Advanced Features
313
+ ### Advanced operations with the Zustand store
162
314
 
163
- - **Batch Processing**: Handle large datasets with pagination
164
- - **Arrow Integration**: Work directly with Apache Arrow tables for efficient data processing
165
- - **Schema Management**: Create, inspect, and manage database schemas
166
- - **File Management**: Register and manage files in the DuckDB instance
315
+ ```tsx
316
+ function AdvancedOperations() {
317
+ const executeSql = useRoomStore((s) => s.db.executeSql);
318
+ const sqlSelectToJson = useRoomStore((s) => s.db.sqlSelectToJson);
319
+ const checkTableExists = useRoomStore((s) => s.db.checkTableExists);
320
+
321
+ const handleAdvancedQuery = async () => {
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);
327
+ }
328
+
329
+ // Parse SQL to JSON (analysis tool)
330
+ const parsed = await sqlSelectToJson('SELECT id, name FROM users');
331
+ console.log('Parsed query:', parsed);
332
+
333
+ // Safety check before destructive operations
334
+ const exists = await checkTableExists('users');
335
+ console.log('Table exists:', exists);
336
+ };
337
+
338
+ return <button onClick={handleAdvancedQuery}>Run Advanced Operations</button>;
339
+ }
340
+ ```
167
341
 
168
342
  For more information, visit the SQLRooms documentation.
169
343
 
@@ -1,4 +1,4 @@
1
- import { ProjectState } from '@sqlrooms/project';
1
+ import { RoomState } from '@sqlrooms/core';
2
2
  import * as arrow from 'apache-arrow';
3
3
  import { z } from 'zod';
4
4
  import { StateCreator } from 'zustand';
@@ -64,7 +64,7 @@ export type DuckDbSliceState = {
64
64
  */
65
65
  destroy: () => Promise<void>;
66
66
  /**
67
- * Add a table to the project.
67
+ * Add a table to the room.
68
68
  * @param tableName - The name of the table to add.
69
69
  * @param data - The data to add to the table: an arrow table or an array of records.
70
70
  * @returns A promise that resolves to the table that was added.
@@ -179,7 +179,7 @@ export type DuckDbSliceState = {
179
179
  export declare function createDuckDbSlice({ connector, }: {
180
180
  connector?: DuckDbConnector;
181
181
  }): StateCreator<DuckDbSliceState>;
182
- type ProjectStateWithDuckDb = ProjectState<DuckDbSliceConfig> & DuckDbSliceState;
183
- export declare function useStoreWithDuckDb<T>(selector: (state: ProjectStateWithDuckDb) => T): T;
182
+ type RoomStateWithDuckDb = RoomState<DuckDbSliceConfig> & DuckDbSliceState;
183
+ export declare function useStoreWithDuckDb<T>(selector: (state: RoomStateWithDuckDb) => T): T;
184
184
  export {};
185
185
  //# sourceMappingURL=DuckDbSlice.d.ts.map
@@ -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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"}
@@ -1,4 +1,4 @@
1
- import { createBaseSlice, useBaseProjectStore, } from '@sqlrooms/project';
1
+ import { createBaseSlice, useBaseRoomStore } from '@sqlrooms/core';
2
2
  import * as arrow from 'apache-arrow';
3
3
  import deepEquals from 'fast-deep-equal';
4
4
  import { produce } from 'immer';
@@ -41,6 +41,7 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), })
41
41
  await get().db.refreshTableSchemas();
42
42
  },
43
43
  getConnector: async () => {
44
+ await get().db.connector.initialize();
44
45
  return get().db.connector;
45
46
  },
46
47
  destroy: async () => {
@@ -69,7 +70,7 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), })
69
70
  }
70
71
  const rowCount = getColValAsNumber(await connector.query(`CREATE OR REPLACE TABLE ${qualifiedName} AS (
71
72
  ${statements[0]}
72
- )`).result);
73
+ )`));
73
74
  return { tableName, rowCount };
74
75
  },
75
76
  /**
@@ -104,7 +105,7 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), })
104
105
  schema,
105
106
  database,
106
107
  table,
107
- })}`).result;
108
+ })}`);
108
109
  return getColValAsNumber(result);
109
110
  },
110
111
  /**
@@ -127,7 +128,7 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), })
127
128
  ]
128
129
  .filter(Boolean)
129
130
  .join(' AND ')}`
130
- : ''}`).result;
131
+ : ''}`);
131
132
  const newTables = [];
132
133
  for (let i = 0; i < describeResults.numRows; i++) {
133
134
  const database = describeResults.getChild('database')?.get(i);
@@ -171,8 +172,7 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), })
171
172
  const qualifiedTable = isQualifiedTableName(tableName)
172
173
  ? tableName
173
174
  : makeQualifiedTableName({ table: tableName });
174
- await connector.query(`DROP TABLE IF EXISTS ${qualifiedTable};`)
175
- .result;
175
+ await connector.query(`DROP TABLE IF EXISTS ${qualifiedTable};`);
176
176
  await get().db.refreshTableSchemas();
177
177
  },
178
178
  async addTable(tableName, data) {
@@ -226,7 +226,7 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), })
226
226
  }));
227
227
  try {
228
228
  const connector = await get().db.getConnector();
229
- const result = await connector.query(`SELECT current_schema() AS schema, current_database() AS database`).result;
229
+ const result = await connector.query(`SELECT current_schema() AS schema, current_database() AS database`);
230
230
  set((state) => produce(state, (draft) => {
231
231
  draft.db.currentSchema = result.getChild('schema')?.get(0);
232
232
  draft.db.currentDatabase = result.getChild('database')?.get(0);
@@ -242,7 +242,7 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), })
242
242
  return newTables;
243
243
  }
244
244
  catch (err) {
245
- get().project.captureException(err);
245
+ get().room.captureException(err);
246
246
  return [];
247
247
  }
248
248
  finally {
@@ -253,7 +253,7 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), })
253
253
  },
254
254
  async sqlSelectToJson(sql) {
255
255
  const connector = await get().db.getConnector();
256
- const parsedQuery = (await connector.query(`SELECT json_serialize_sql(${escapeVal(sql)})`).result)
256
+ const parsedQuery = (await connector.query(`SELECT json_serialize_sql(${escapeVal(sql)})`))
257
257
  .getChildAt(0)
258
258
  ?.get(0);
259
259
  return JSON.parse(parsedQuery);
@@ -285,6 +285,6 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), })
285
285
  });
286
286
  }
287
287
  export function useStoreWithDuckDb(selector) {
288
- return useBaseProjectStore((state) => selector(state));
288
+ return useBaseRoomStore((state) => selector(state));
289
289
  }
290
290
  //# sourceMappingURL=DuckDbSlice.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DuckDbSlice.js","sourceRoot":"","sources":["../src/DuckDbSlice.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createBaseSlice,\n ProjectState,\n useBaseProjectStore,\n} from '@sqlrooms/project';\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 project.\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 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().project.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 ProjectStateWithDuckDb = ProjectState<DuckDbSliceConfig> &\n DuckDbSliceState;\n\nexport function useStoreWithDuckDb<T>(\n selector: (state: ProjectStateWithDuckDb) => T,\n): T {\n return useBaseProjectStore<\n DuckDbSliceConfig,\n ProjectState<DuckDbSliceConfig>,\n T\n >((state) => selector(state as unknown as ProjectStateWithDuckDb));\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,4 +1,4 @@
1
- import { LoadFileOptions, StandardLoadOptions } from '@sqlrooms/project-config';
1
+ import { LoadFileOptions, StandardLoadOptions } from '@sqlrooms/room-config';
2
2
  import * as arrow from 'apache-arrow';
3
3
  import { TypeMap } from 'apache-arrow';
4
4
  import { DuckDbConnector } from './DuckDbConnector';
@@ -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,0BAA0B,CAAC;AAClC,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,CA2JjB"}
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"}