@sqlrooms/duckdb 0.29.0-rc.8 → 0.29.0-rc.9

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
@@ -57,6 +57,33 @@ function UserList() {
57
57
 
58
58
  For more information and examples on using the `useSql` hook, see the [useSql API documentation](/api/duckdb/functions/useSql).
59
59
 
60
+ ### Monitoring WebSocket DuckDB Connections
61
+
62
+ `createWebSocketDuckDbConnector()` exposes the persistent WebSocket lifecycle
63
+ through `connectionStatus`, `subscribeConnectionStatus()`, and the optional
64
+ `onConnectionStatusChange` callback. Use this for live UI affordances such as
65
+ lost-connection dialogs. Call `reconnect()` to reopen the socket and rerun the
66
+ connector initialization SQL without destroying the connector instance.
67
+
68
+ ```tsx
69
+ import {createWebSocketDuckDbConnector} from '@sqlrooms/duckdb';
70
+
71
+ const connector = createWebSocketDuckDbConnector({
72
+ wsUrl: 'ws://localhost:4000',
73
+ onConnectionStatusChange: (status) => {
74
+ console.log('DuckDB WebSocket status:', status);
75
+ },
76
+ });
77
+
78
+ const unsubscribe = connector.subscribeConnectionStatus((status) => {
79
+ if (status === 'disconnected') {
80
+ console.warn('DuckDB WebSocket disconnected');
81
+ }
82
+ });
83
+
84
+ await connector.reconnect();
85
+ ```
86
+
60
87
  ### Looking up Table Metadata
61
88
 
62
89
  Use `useDataTable()` in React components or `db.findTable()` from the room
@@ -229,15 +256,12 @@ function DatabaseManager() {
229
256
  ### Working with Qualified Table Names
230
257
 
231
258
  ```tsx
232
- import {
233
- makeQualifiedTableName,
234
- quoteTableReference,
235
- resolveTableReference,
236
- } from '@sqlrooms/duckdb';
259
+ import {quoteTableReference, resolveTableReference} from '@sqlrooms/duckdb';
237
260
  import {useRoomStore} from './store';
238
261
  import {Button} from '@sqlrooms/ui';
239
262
 
240
263
  function QualifiedTableOps() {
264
+ const qualifyTableName = useRoomStore((state) => state.db.qualifyTableName);
241
265
  const createTableFromQuery = useRoomStore(
242
266
  (state) => state.db.createTableFromQuery,
243
267
  );
@@ -245,17 +269,20 @@ function QualifiedTableOps() {
245
269
  const checkTableExists = useRoomStore((state) => state.db.checkTableExists);
246
270
 
247
271
  const run = async () => {
248
- // Support for database.schema.table naming
249
- const qualifiedTable = makeQualifiedTableName({
272
+ // Store-aware qualification knows which database is the default.
273
+ const qualifiedTable = qualifyTableName({
250
274
  database: 'mydb',
251
275
  schema: 'public',
252
276
  table: 'users',
253
277
  });
278
+ // toString() is the canonical portable table ID; toFullString() includes
279
+ // the database when explicit catalog qualification is needed.
254
280
  const tableSql = quoteTableReference(qualifiedTable.toString());
255
281
  const resolved = resolveTableReference([{table: qualifiedTable}], 'users');
256
282
 
257
283
  await createTableFromQuery(qualifiedTable, 'SELECT * FROM source_table');
258
284
  console.log('Quoted table reference:', tableSql);
285
+ console.log('Fully qualified reference:', qualifiedTable.toFullString());
259
286
  console.log('Resolved table:', resolved.table?.table.toString());
260
287
  const tableExists = await checkTableExists(qualifiedTable);
261
288
  console.log('Table exists after create:', tableExists);
@@ -34,6 +34,13 @@ export type DuckDbSliceState = {
34
34
  schema: string;
35
35
  currentSchema: string | undefined;
36
36
  currentDatabase: string | undefined;
37
+ /**
38
+ * Create a context-aware qualified table name.
39
+ *
40
+ * String inputs are treated as table identifier names, not SQL references;
41
+ * use findTable() when resolving an existing table reference.
42
+ */
43
+ qualifyTableName(tableName: string | QualifiedTableNameInput): QualifiedTableName;
37
44
  /**
38
45
  * Cache of refreshed table schemas
39
46
  */
@@ -198,6 +205,7 @@ export type DuckDbSliceState = {
198
205
  }>;
199
206
  };
200
207
  };
208
+ type QualifiedTableNameInput = Pick<QualifiedTableName, 'database' | 'schema' | 'table' | 'defaultDatabase'>;
201
209
  export type CreateDuckDbSliceProps = {
202
210
  connector?: DuckDbConnector;
203
211
  /**
@@ -228,4 +236,5 @@ export declare function createDuckDbSlice({ connector, loadTableSchemasFilter, l
228
236
  * @returns The selected value of type `T`
229
237
  */
230
238
  export declare function useStoreWithDuckDb<T>(selector: (state: BaseRoomStoreState & DuckDbSliceState) => T): T;
239
+ export {};
231
240
  //# 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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"}
@@ -15,7 +15,7 @@ const DUCKDB_TEMP_DATABASE = 'temp';
15
15
  * Hides `__sqlrooms_*` names and DuckDB's `temp` database.
16
16
  */
17
17
  export const defaultLoadTableSchemasFilter = (table) => {
18
- if (table.table?.startsWith(INTERNAL_SQLROOMS_PREFIX) ||
18
+ if (table.table.startsWith(INTERNAL_SQLROOMS_PREFIX) ||
19
19
  table.database?.startsWith(INTERNAL_SQLROOMS_PREFIX) ||
20
20
  table.schema?.startsWith(INTERNAL_SQLROOMS_PREFIX)) {
21
21
  return false;
@@ -95,17 +95,55 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
95
95
  return defaultLoadSchemaCatalogFilter(entry);
96
96
  }));
97
97
  return createSlice((set, get, store) => {
98
+ const parseTableReferenceParts = (tableName) => {
99
+ const parsed = parseQualifiedSqlIdentifier(tableName);
100
+ return parsed?.table
101
+ ? {
102
+ database: parsed.database,
103
+ schema: parsed.schema,
104
+ table: parsed.table,
105
+ }
106
+ : { table: tableName };
107
+ };
98
108
  /**
99
109
  * Internal helper to load a table schema by exact name, bypassing the visibility filter.
100
110
  * Used when performing exact lookups (e.g., checking if a specific table exists).
101
111
  */
102
112
  const loadTableSchemaByName = async (tableName) => {
103
- const qualifiedName = isQualifiedTableName(tableName)
104
- ? tableName
105
- : makeQualifiedTableName({ table: tableName });
113
+ const tableNameParts = typeof tableName === 'string'
114
+ ? parseTableReferenceParts(tableName)
115
+ : tableName;
116
+ const qualifiedName = get().db.qualifyTableName(tableNameParts);
106
117
  const connector = await get().db.getConnector();
107
- const [table] = await loadTableSchemas(connector, qualifiedName);
108
- return table;
118
+ const [table] = await loadTableSchemas(connector, {
119
+ database: qualifiedName.database,
120
+ schema: qualifiedName.schema,
121
+ table: qualifiedName.table,
122
+ defaultDatabase: get().db.currentDatabase,
123
+ });
124
+ return table &&
125
+ table.table.table === qualifiedName.table &&
126
+ (!qualifiedName.schema ||
127
+ table.table.schema === qualifiedName.schema) &&
128
+ (!qualifiedName.database ||
129
+ table.table.database === qualifiedName.database)
130
+ ? table
131
+ : undefined;
132
+ };
133
+ const throwIfUnresolvedExplicitDatabaseReference = (tableName, table) => {
134
+ if (table) {
135
+ return;
136
+ }
137
+ const database = typeof tableName === 'string'
138
+ ? parseTableReferenceParts(tableName).database
139
+ : tableName.database;
140
+ if (!database) {
141
+ return;
142
+ }
143
+ const qualifiedName = isQualifiedTableName(tableName)
144
+ ? get().db.qualifyTableName(tableName)
145
+ : get().db.qualifyTableName(parseTableReferenceParts(tableName));
146
+ throw new Error(`Relation "${qualifiedName}" not found.`);
109
147
  };
110
148
  return {
111
149
  db: {
@@ -118,6 +156,16 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
118
156
  tableRowCounts: {},
119
157
  schemaTrees: undefined,
120
158
  queryCache: {},
159
+ qualifyTableName(tableName) {
160
+ const { currentDatabase, currentSchema } = get().db;
161
+ const parts = typeof tableName === 'string' ? { table: tableName } : tableName;
162
+ return makeQualifiedTableName({
163
+ database: parts.database ?? currentDatabase,
164
+ schema: parts.schema ?? currentSchema,
165
+ table: parts.table,
166
+ defaultDatabase: parts.defaultDatabase ?? currentDatabase,
167
+ });
168
+ },
121
169
  setConnector: (connector) => {
122
170
  set(produce((state) => {
123
171
  state.config.dataSources = [];
@@ -172,14 +220,13 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
172
220
  async createTableFromQuery(tableName, query, options) {
173
221
  const { replace = true, temp = false, view = false, allowMultipleStatements = false, abortSignal, } = options || {};
174
222
  // For temp tables/views, DuckDB requires the "temp" database
175
- const baseQualifiedName = isQualifiedTableName(tableName)
176
- ? tableName
177
- : makeQualifiedTableName({ table: tableName });
223
+ const baseQualifiedName = get().db.qualifyTableName(tableName);
178
224
  const qualifiedName = temp
179
225
  ? makeQualifiedTableName({
180
226
  table: baseQualifiedName.table,
181
227
  schema: baseQualifiedName.schema,
182
228
  database: 'temp',
229
+ defaultDatabase: get().db.currentDatabase,
183
230
  })
184
231
  : baseQualifiedName;
185
232
  const connector = await get().db.getConnector();
@@ -233,14 +280,14 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
233
280
  * @deprecated Use .loadTableRowCount() instead
234
281
  */
235
282
  async getTableRowCount(table, schema = 'main') {
236
- return get().db.loadTableRowCount({ table, schema });
283
+ return get().db.loadTableRowCount(get().db.qualifyTableName({ table, schema }));
237
284
  },
238
285
  async loadTableRowCount(tableName) {
239
286
  const { schema, database, table } = typeof tableName === 'string'
240
- ? { table: tableName }
241
- : tableName || {};
287
+ ? get().db.qualifyTableName(parseTableReferenceParts(tableName))
288
+ : get().db.qualifyTableName(tableName);
242
289
  const connector = await get().db.getConnector();
243
- const result = await connector.query(`SELECT COUNT(*) FROM ${makeQualifiedTableName({
290
+ const result = await connector.query(`SELECT COUNT(*) FROM ${get().db.qualifyTableName({
244
291
  schema,
245
292
  database,
246
293
  table,
@@ -258,19 +305,23 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
258
305
  return loadTableSchemas(connector, {
259
306
  ...filter,
260
307
  filterFunction: loadTableSchemasFilter,
308
+ defaultDatabase: get().db.currentDatabase,
261
309
  });
262
310
  },
263
311
  async checkTableExists(tableName) {
264
- const table = await loadTableSchemaByName(tableName);
312
+ const table = get().db.findTable(tableName) ??
313
+ (await loadTableSchemaByName(tableName));
265
314
  return Boolean(table);
266
315
  },
267
316
  async dropRelation(tableName) {
268
317
  const connector = await get().db.getConnector();
269
- const qualifiedTable = isQualifiedTableName(tableName)
270
- ? tableName
271
- : makeQualifiedTableName({ table: tableName });
272
- const table = get().db.findTable(qualifiedTable) ??
273
- (await loadTableSchemaByName(qualifiedTable));
318
+ const table = get().db.findTable(tableName) ??
319
+ (await loadTableSchemaByName(tableName));
320
+ throwIfUnresolvedExplicitDatabaseReference(tableName, table);
321
+ const qualifiedTable = table?.table ??
322
+ (isQualifiedTableName(tableName)
323
+ ? get().db.qualifyTableName(tableName)
324
+ : get().db.qualifyTableName(parseTableReferenceParts(tableName)));
274
325
  const isView = table?.isView;
275
326
  if (isView) {
276
327
  await connector.query(`DROP VIEW IF EXISTS ${qualifiedTable};`);
@@ -282,11 +333,13 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
282
333
  },
283
334
  async dropTable(tableName) {
284
335
  const connector = await get().db.getConnector();
285
- const qualifiedTable = isQualifiedTableName(tableName)
286
- ? tableName
287
- : makeQualifiedTableName({ table: tableName });
288
- const table = get().db.findTable(qualifiedTable) ??
289
- (await loadTableSchemaByName(qualifiedTable));
336
+ const table = get().db.findTable(tableName) ??
337
+ (await loadTableSchemaByName(tableName));
338
+ throwIfUnresolvedExplicitDatabaseReference(tableName, table);
339
+ const qualifiedTable = table?.table ??
340
+ (isQualifiedTableName(tableName)
341
+ ? get().db.qualifyTableName(tableName)
342
+ : get().db.qualifyTableName(parseTableReferenceParts(tableName)));
290
343
  if (table?.isView) {
291
344
  throw new Error(`"${qualifiedTable}" is a view. Use dropRelation() to remove views.`);
292
345
  }
@@ -294,9 +347,7 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
294
347
  get().db.refreshTableSchemas();
295
348
  },
296
349
  async addTable(tableName, data) {
297
- const qualifiedName = isQualifiedTableName(tableName)
298
- ? tableName
299
- : makeQualifiedTableName({ table: tableName });
350
+ const qualifiedName = get().db.qualifyTableName(tableName);
300
351
  const { db } = get();
301
352
  if (data instanceof arrow.Table) {
302
353
  // TODO: make sure the table is replaced
@@ -318,9 +369,7 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
318
369
  return newTable;
319
370
  },
320
371
  async setTableRowCount(tableName, rowCount) {
321
- const qualifiedName = isQualifiedTableName(tableName)
322
- ? tableName
323
- : makeQualifiedTableName({ table: tableName });
372
+ const qualifiedName = get().db.qualifyTableName(tableName);
324
373
  set((state) => produce(state, (draft) => {
325
374
  draft.db.tableRowCounts[qualifiedName.toString()] = rowCount;
326
375
  }));
@@ -335,14 +384,33 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
335
384
  (!schema || t.table.schema === schema) &&
336
385
  (!database || t.table.database === database))
337
386
  : undefined;
338
- const { table, schema, database } = {
387
+ const findUniqueMatchingTable = ({ table, schema, }) => {
388
+ if (!table)
389
+ return undefined;
390
+ const matches = tables.filter((t) => t.table.table === table &&
391
+ (!schema || t.table.schema === schema));
392
+ return matches.length === 1 ? matches[0] : undefined;
393
+ };
394
+ const resolvedTableName = typeof tableName === 'string'
395
+ ? (parseQualifiedSqlIdentifier(tableName) ?? {})
396
+ : tableName;
397
+ const { table, schema, database, defaultDatabase } = {
339
398
  schema: currentSchema,
340
399
  database: currentDatabase,
341
- ...(typeof tableName === 'string'
342
- ? (parseQualifiedSqlIdentifier(tableName) ?? {})
343
- : tableName),
400
+ ...resolvedTableName,
344
401
  };
345
- return findMatchingTable({ table, schema, database });
402
+ const exactMatch = findMatchingTable({ table, schema, database });
403
+ if (exactMatch)
404
+ return exactMatch;
405
+ const isStaleDefaultDatabaseReference = typeof tableName !== 'string' &&
406
+ database &&
407
+ defaultDatabase &&
408
+ database === defaultDatabase &&
409
+ database !== currentDatabase;
410
+ if (isStaleDefaultDatabaseReference) {
411
+ return findUniqueMatchingTable({ table, schema });
412
+ }
413
+ return undefined;
346
414
  },
347
415
  findTableByName(tableName) {
348
416
  return get().db.findTable(tableName);
@@ -362,16 +430,23 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
362
430
  pendingSchemaRefresh = false;
363
431
  const connector = await get().db.getConnector();
364
432
  const result = await connector.query(`SELECT current_schema() AS schema, current_database() AS database`);
433
+ const currentSchemaValue = result.getChild('schema')?.get(0);
434
+ const currentDatabaseValue = result
435
+ .getChild('database')
436
+ ?.get(0);
437
+ const currentSchema = currentSchemaValue == null
438
+ ? undefined
439
+ : String(currentSchemaValue);
440
+ const currentDatabase = currentDatabaseValue == null
441
+ ? undefined
442
+ : String(currentDatabaseValue);
365
443
  set((state) => produce(state, (draft) => {
366
- draft.db.currentSchema = result
367
- .getChild('schema')
368
- ?.get(0);
369
- draft.db.currentDatabase = result
370
- .getChild('database')
371
- ?.get(0);
444
+ draft.db.currentSchema = currentSchema;
445
+ draft.db.currentDatabase = currentDatabase;
372
446
  }));
373
447
  schemasWithTables = await loadSchemaCatalog(connector, {
374
448
  filterFunction: effectiveSchemaCatalogFilter,
449
+ defaultDatabase: currentDatabase,
375
450
  });
376
451
  } while (pendingSchemaRefresh);
377
452
  const newTables = schemasWithTables.flatMap((s) => s.tables);
@@ -421,7 +496,12 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
421
496
  set((state) => produce(state, (draft) => {
422
497
  draft.db.queryCache[queryKey] = queryHandle;
423
498
  }));
424
- queryHandle.result.finally(() => {
499
+ queryHandle.result
500
+ .catch(() => {
501
+ // Prevent unhandled promise rejection warnings.
502
+ // Callers handle errors via await/try-catch.
503
+ })
504
+ .finally(() => {
425
505
  // remove from cache after completion
426
506
  set((state) => produce(state, (draft) => {
427
507
  delete draft.db.queryCache[queryKey];