@sqlrooms/duckdb 0.29.0-rc.4 → 0.29.0-rc.6

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
@@ -236,6 +236,29 @@ function QualifiedTableOps() {
236
236
  }
237
237
  ```
238
238
 
239
+ ### Loading the Schema Catalog
240
+
241
+ Use `loadSchemaCatalog()` when you need the database/schema/table hierarchy,
242
+ including empty schemas and attached databases whose `main` schema has no
243
+ tables yet. The catalog filter receives typed entries for databases, schemas,
244
+ and tables, so schema visibility does not depend on fake table names.
245
+ Related option and filter types are exported for callers that wrap these
246
+ helpers in their own APIs.
247
+
248
+ ```ts
249
+ import {
250
+ defaultLoadSchemaCatalogFilter,
251
+ loadSchemaCatalog,
252
+ } from '@sqlrooms/duckdb';
253
+
254
+ const catalog = await loadSchemaCatalog(connector, {
255
+ filterFunction: (entry) =>
256
+ entry.type === 'schema' && entry.schema === 'scratch'
257
+ ? false
258
+ : defaultLoadSchemaCatalogFilter(entry),
259
+ });
260
+ ```
261
+
239
262
  ## Loading Data from Files
240
263
 
241
264
  ### Using Load Functions Directly
@@ -2,11 +2,23 @@ import { DataTable, DbSchemaNode, DuckDbConnector, QualifiedTableName, QueryHand
2
2
  import { BaseRoomStoreState } from '@sqlrooms/room-store';
3
3
  import * as arrow from 'apache-arrow';
4
4
  import { StateCreator } from 'zustand';
5
- import { LoadTableSchemasFilter, LoadTableSchemasFilterFunction } from './loadTableSchemas';
5
+ import { LoadSchemaCatalogFilterFunction, LoadTableSchemasFilter, LoadTableSchemasFilterFunction } from './loadTableSchemas';
6
6
  /**
7
- * Default filter to exclude internal SQLRooms tables, schemas, and databases
7
+ * Default predicate: which tables/schemas/databases appear in the data source panel.
8
+ * Hides `__sqlrooms_*` names and DuckDB's `temp` database.
9
+ */
10
+ export declare const defaultLoadTableSchemasFilter: LoadTableSchemasFilterFunction;
11
+ /**
12
+ * Factory returning {@link defaultLoadTableSchemasFilter}.
13
+ * Hides `__sqlrooms_*` names and DuckDB's `temp` database.
14
+ * Apps can pass {@link CreateDuckDbSliceProps.loadTableSchemasFilter} to add more rules.
8
15
  */
9
16
  export declare function createDefaultLoadTableSchemasFilter(): LoadTableSchemasFilterFunction;
17
+ /**
18
+ * Default catalog visibility predicate for the data source panel.
19
+ * Hides SQLRooms internal objects and DuckDB's temporary database catalog.
20
+ */
21
+ export declare const defaultLoadSchemaCatalogFilter: LoadSchemaCatalogFilterFunction;
10
22
  /**
11
23
  * State and actions for the DuckDB slice
12
24
  */
@@ -183,17 +195,21 @@ export type DuckDbSliceState = {
183
195
  export type CreateDuckDbSliceProps = {
184
196
  connector?: DuckDbConnector;
185
197
  /**
186
- * Optional filter function to control which tables are included when loading schemas.
187
- * By default, filters out tables/schemas/databases starting with '__sqlrooms_'.
188
- * @param table - The qualified table name to evaluate
189
- * @returns true to include the table, false to exclude it
198
+ * Optional table visibility filter.
199
+ * Defaults to {@link createDefaultLoadTableSchemasFilter}.
190
200
  */
191
201
  loadTableSchemasFilter?: LoadTableSchemasFilterFunction | null;
202
+ /**
203
+ * Optional catalog visibility filter for the data source panel.
204
+ * Defaults to {@link defaultLoadSchemaCatalogFilter}. When omitted, custom
205
+ * table filters still apply to table entries while schemas/databases use the default.
206
+ */
207
+ loadSchemaCatalogFilter?: LoadSchemaCatalogFilterFunction | null;
192
208
  };
193
209
  /**
194
210
  * Create a DuckDB slice for managing the connector
195
211
  */
196
- export declare function createDuckDbSlice({ connector, loadTableSchemasFilter, }?: CreateDuckDbSliceProps): StateCreator<DuckDbSliceState>;
212
+ export declare function createDuckDbSlice({ connector, loadTableSchemasFilter, loadSchemaCatalogFilter, }?: CreateDuckDbSliceProps): StateCreator<DuckDbSliceState>;
197
213
  /**
198
214
  * @internal
199
215
  * Select values from the room store that includes the DuckDB slice.
@@ -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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"}
@@ -5,19 +5,51 @@ import deepEquals from 'fast-deep-equal';
5
5
  import { produce } from 'immer';
6
6
  import { z } from 'zod';
7
7
  import { createWasmDuckDbConnector } from './connectors/createDuckDbConnector';
8
- import { loadTableSchemas, } from './loadTableSchemas';
8
+ import { loadSchemaCatalog, loadTableSchemas, } from './loadTableSchemas';
9
9
  const DUCKDB_COMMAND_OWNER = '@sqlrooms/duckdb';
10
10
  const INTERNAL_SQLROOMS_PREFIX = '__sqlrooms';
11
+ /** DuckDB's temporary database catalog; never show in the default data source tree. */
12
+ const DUCKDB_TEMP_DATABASE = 'temp';
11
13
  /**
12
- * Default filter to exclude internal SQLRooms tables, schemas, and databases
14
+ * Default predicate: which tables/schemas/databases appear in the data source panel.
15
+ * Hides `__sqlrooms_*` names and DuckDB's `temp` database.
16
+ */
17
+ export const defaultLoadTableSchemasFilter = (table) => {
18
+ if (table.table?.startsWith(INTERNAL_SQLROOMS_PREFIX) ||
19
+ table.database?.startsWith(INTERNAL_SQLROOMS_PREFIX) ||
20
+ table.schema?.startsWith(INTERNAL_SQLROOMS_PREFIX)) {
21
+ return false;
22
+ }
23
+ if (table.database === DUCKDB_TEMP_DATABASE) {
24
+ return false;
25
+ }
26
+ return true;
27
+ };
28
+ /**
29
+ * Factory returning {@link defaultLoadTableSchemasFilter}.
30
+ * Hides `__sqlrooms_*` names and DuckDB's `temp` database.
31
+ * Apps can pass {@link CreateDuckDbSliceProps.loadTableSchemasFilter} to add more rules.
13
32
  */
14
33
  export function createDefaultLoadTableSchemasFilter() {
15
- return (table) => {
16
- return (!table.table?.startsWith(INTERNAL_SQLROOMS_PREFIX) &&
17
- !table.database?.startsWith(INTERNAL_SQLROOMS_PREFIX) &&
18
- !table.schema?.startsWith(INTERNAL_SQLROOMS_PREFIX));
19
- };
34
+ return defaultLoadTableSchemasFilter;
20
35
  }
36
+ /**
37
+ * Default catalog visibility predicate for the data source panel.
38
+ * Hides SQLRooms internal objects and DuckDB's temporary database catalog.
39
+ */
40
+ export const defaultLoadSchemaCatalogFilter = (entry) => {
41
+ switch (entry.type) {
42
+ case 'database':
43
+ return (!entry.database.startsWith(INTERNAL_SQLROOMS_PREFIX) &&
44
+ entry.database !== DUCKDB_TEMP_DATABASE);
45
+ case 'schema':
46
+ return (!entry.database.startsWith(INTERNAL_SQLROOMS_PREFIX) &&
47
+ entry.database !== DUCKDB_TEMP_DATABASE &&
48
+ !entry.schema.startsWith(INTERNAL_SQLROOMS_PREFIX));
49
+ case 'table':
50
+ return defaultLoadTableSchemasFilter(entry.table);
51
+ }
52
+ };
21
53
  const DropTableCommandInput = z.object({
22
54
  tableName: z.string().describe('Name of the table to drop.'),
23
55
  });
@@ -48,9 +80,20 @@ const CreateTableFromQueryCommandInput = z.object({
48
80
  /**
49
81
  * Create a DuckDB slice for managing the connector
50
82
  */
51
- export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loadTableSchemasFilter = createDefaultLoadTableSchemasFilter(), } = {}) {
83
+ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loadTableSchemasFilter = defaultLoadTableSchemasFilter, loadSchemaCatalogFilter, } = {}) {
52
84
  let refreshPromise = null;
53
85
  let pendingSchemaRefresh = false;
86
+ const effectiveSchemaCatalogFilter = loadSchemaCatalogFilter ??
87
+ (loadTableSchemasFilter === null
88
+ ? null
89
+ : ((entry) => {
90
+ if (entry.type === 'table') {
91
+ return loadTableSchemasFilter
92
+ ? loadTableSchemasFilter(entry.table)
93
+ : true;
94
+ }
95
+ return defaultLoadSchemaCatalogFilter(entry);
96
+ }));
54
97
  return createSlice((set, get, store) => {
55
98
  /**
56
99
  * Internal helper to load a table schema by exact name, bypassing the visibility filter.
@@ -307,7 +350,7 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
307
350
  }));
308
351
  refreshPromise = (async () => {
309
352
  try {
310
- let newTables;
353
+ let schemasWithTables = [];
311
354
  do {
312
355
  pendingSchemaRefresh = false;
313
356
  const connector = await get().db.getConnector();
@@ -320,12 +363,19 @@ export function createDuckDbSlice({ connector = createWasmDuckDbConnector(), loa
320
363
  .getChild('database')
321
364
  ?.get(0);
322
365
  }));
323
- newTables = await get().db.loadTableSchemas();
366
+ schemasWithTables = await loadSchemaCatalog(connector, {
367
+ filterFunction: effectiveSchemaCatalogFilter,
368
+ });
324
369
  } while (pendingSchemaRefresh);
325
- if (!deepEquals(newTables, get().db.tables)) {
370
+ const newTables = schemasWithTables.flatMap((s) => s.tables);
371
+ const currentTables = get().db.tables;
372
+ const currentSchemaTrees = get().db.schemaTrees;
373
+ const newSchemaTrees = createDbSchemaTrees(schemasWithTables);
374
+ if (!deepEquals(newTables, currentTables) ||
375
+ !deepEquals(newSchemaTrees, currentSchemaTrees)) {
326
376
  set((state) => produce(state, (draft) => {
327
377
  draft.db.tables = newTables;
328
- draft.db.schemaTrees = createDbSchemaTrees(newTables);
378
+ draft.db.schemaTrees = newSchemaTrees;
329
379
  }));
330
380
  }
331
381
  return newTables;
@@ -1 +1 @@
1
- {"version":3,"file":"DuckDbSlice.js","sourceRoot":"","sources":["../src/DuckDbSlice.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createDbSchemaTrees,\n DataTable,\n DbSchemaNode,\n DuckDbConnector,\n escapeVal,\n getColValAsNumber,\n isQualifiedTableName,\n joinStatements,\n makeQualifiedTableName,\n QualifiedTableName,\n QueryHandle,\n separateLastStatement,\n} from '@sqlrooms/duckdb-core';\nimport {\n BaseRoomStoreState,\n createSlice,\n registerCommandsForOwner,\n RoomCommand,\n unregisterCommandsForOwner,\n useBaseRoomStore,\n} from '@sqlrooms/room-store';\nimport * as arrow from 'apache-arrow';\nimport deepEquals from 'fast-deep-equal';\nimport {produce} from 'immer';\nimport {z} from 'zod';\nimport {StateCreator} from 'zustand';\nimport {createWasmDuckDbConnector} from './connectors/createDuckDbConnector';\nimport {\n loadTableSchemas,\n LoadTableSchemasFilter,\n LoadTableSchemasFilterFunction,\n} from './loadTableSchemas';\n\nconst DUCKDB_COMMAND_OWNER = '@sqlrooms/duckdb';\nconst INTERNAL_SQLROOMS_PREFIX = '__sqlrooms';\n\n/**\n * Default filter to exclude internal SQLRooms tables, schemas, and databases\n */\nexport function createDefaultLoadTableSchemasFilter(): LoadTableSchemasFilterFunction {\n return (table: QualifiedTableName): boolean => {\n return (\n !table.table?.startsWith(INTERNAL_SQLROOMS_PREFIX) &&\n !table.database?.startsWith(INTERNAL_SQLROOMS_PREFIX) &&\n !table.schema?.startsWith(INTERNAL_SQLROOMS_PREFIX)\n );\n };\n}\n\nconst DropTableCommandInput = z.object({\n tableName: z.string().describe('Name of the table to drop.'),\n});\ntype DropTableCommandInput = z.infer<typeof DropTableCommandInput>;\n\nconst CreateTableFromQueryCommandInput = z.object({\n tableName: z.string().describe('Name of the table or view to create.'),\n query: z.string().describe('SQL query used to populate the table/view.'),\n replace: z\n .boolean()\n .optional()\n .default(true)\n .describe('Whether to replace existing table/view with the same name.'),\n view: z\n .boolean()\n .optional()\n .default(false)\n .describe('Whether to create a view instead of a table.'),\n temp: z\n .boolean()\n .optional()\n .default(false)\n .describe('Whether to create a temporary object.'),\n allowMultipleStatements: z\n .boolean()\n .optional()\n .default(false)\n .describe('Allow multiple SQL statements where the final one is SELECT.'),\n});\n\ntype CreateTableFromQueryCommandInput = z.infer<\n typeof CreateTableFromQueryCommandInput\n>;\n\n/**\n * State and actions for the DuckDB slice\n */\nexport type DuckDbSliceState = {\n db: {\n /**\n * The DuckDB connector instance\n */\n connector: DuckDbConnector;\n /**\n * @deprecated We shouldn't limit the schema to a single one.\n */\n schema: string;\n\n currentSchema: string | undefined;\n currentDatabase: string | undefined;\n\n /**\n * Cache of refreshed table schemas\n */\n tables: DataTable[];\n /**\n * Cache of row counts for tables\n */\n tableRowCounts: {[tableName: string]: number};\n /**\n * Cache of schema trees for tables\n */\n schemaTrees?: DbSchemaNode[];\n /**\n * Cache of currently running query handles.\n * This is only used for running queries to deduplicate them (especially for useSql),\n * the cache is cleared when the query is completed.\n */\n queryCache: {[key: string]: QueryHandle};\n /**\n * Whether the table schemas are being refreshed\n */\n isRefreshingTableSchemas: boolean;\n\n /**\n * Set a new DuckDB connector\n */\n setConnector: (connector: DuckDbConnector) => void;\n\n /**\n * Initialize the connector (creates a WasmDuckDbConnector if none exists)\n */\n initialize: () => Promise<void>;\n\n /**\n * Close and clean up the connector\n */\n destroy: () => Promise<void>;\n\n /**\n * Add a table to the room.\n * @param tableName - The name of the table to add.\n * @param data - The data to add to the table: an arrow table or an array of records.\n * @returns A promise that resolves to the table that was added.\n */\n addTable(\n tableName: string | QualifiedTableName,\n data: arrow.Table | Record<string, unknown>[],\n ): Promise<DataTable>;\n\n /**\n * Load the schemas of the tables in the database.\n */\n loadTableSchemas(filter?: LoadTableSchemasFilter): 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: (\n query: string,\n version?: number,\n ) => 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 or view with optional schema and database.\n * @param tableName - The name of the relation to delete (qualified or plain)\n */\n dropRelation: (tableName: string | QualifiedTableName) => Promise<void>;\n\n /**\n * Delete a table with optional schema and database.\n * @param tableName - The name of the table to delete (qualified or plain)\n */\n dropTable: (tableName: string | QualifiedTableName) => Promise<void>;\n\n /**\n * Create a table or view from a query.\n * @param tableName - The name of the table/view to create.\n * @param query - The query to create the table/view from.\n * @param options - Creation options.\n * @returns The table/view name and rowCount (undefined for views).\n */\n createTableFromQuery: (\n tableName: string | QualifiedTableName,\n query: string,\n options?: {\n replace?: boolean;\n temp?: boolean;\n view?: boolean;\n allowMultipleStatements?: boolean;\n abortSignal?: AbortSignal;\n },\n ) => Promise<{\n tableName: string | QualifiedTableName;\n rowCount: number | undefined;\n }>;\n\n /**\n * Parse a SQL SELECT statement to JSON\n * @param sql - The SQL SELECT statement to parse.\n * @returns A promise that resolves to the parsed JSON.\n */\n sqlSelectToJson: (sql: string) => Promise<\n | {\n error: true;\n error_type: string;\n error_message: string;\n error_subtype: string;\n position: string;\n }\n | {\n error: false;\n statements: {\n node: {\n from_table: {\n alias: string;\n show_type: string;\n table_name: string;\n };\n select_list: Record<string, unknown>[];\n type: string;\n };\n }[];\n }\n >;\n };\n};\n\nexport type CreateDuckDbSliceProps = {\n connector?: DuckDbConnector;\n /**\n * Optional filter function to control which tables are included when loading schemas.\n * By default, filters out tables/schemas/databases starting with '__sqlrooms_'.\n * @param table - The qualified table name to evaluate\n * @returns true to include the table, false to exclude it\n */\n loadTableSchemasFilter?: LoadTableSchemasFilterFunction | null;\n};\n\n/**\n * Create a DuckDB slice for managing the connector\n */\nexport function createDuckDbSlice({\n connector = createWasmDuckDbConnector(),\n loadTableSchemasFilter = createDefaultLoadTableSchemasFilter(),\n}: CreateDuckDbSliceProps = {}): StateCreator<DuckDbSliceState> {\n let refreshPromise: Promise<DataTable[]> | null = null;\n let pendingSchemaRefresh = false;\n return createSlice<DuckDbSliceState, BaseRoomStoreState & DuckDbSliceState>(\n (set, get, store) => {\n /**\n * Internal helper to load a table schema by exact name, bypassing the visibility filter.\n * Used when performing exact lookups (e.g., checking if a specific table exists).\n */\n const loadTableSchemaByName = async (\n tableName: string | QualifiedTableName,\n ): Promise<DataTable | undefined> => {\n const qualifiedName = isQualifiedTableName(tableName)\n ? tableName\n : makeQualifiedTableName({table: tableName});\n const connector = await get().db.getConnector();\n const [table] = await loadTableSchemas(connector, qualifiedName);\n return table;\n };\n\n return {\n db: {\n connector, // Will be initialized during init\n schema: 'main', // TODO: remove schema, we should not limit the schema to a single one.\n currentSchema: undefined,\n currentDatabase: undefined,\n isRefreshingTableSchemas: false,\n tables: [],\n tableRowCounts: {},\n schemaTrees: undefined,\n queryCache: {},\n\n setConnector: (connector: DuckDbConnector) => {\n set(\n produce((state) => {\n state.config.dataSources = [];\n state.db.connector = connector;\n }),\n );\n },\n\n initialize: async () => {\n await get().db.connector.initialize();\n // No await here, we want to continue initializing the room even\n // if the table schemas are not refreshed yet\n get().db.refreshTableSchemas();\n registerCommandsForOwner(\n store,\n DUCKDB_COMMAND_OWNER,\n createDuckDbCommands(),\n );\n },\n\n getConnector: async () => {\n await get().db.connector.initialize();\n return get().db.connector;\n },\n\n destroy: async () => {\n unregisterCommandsForOwner(store, DUCKDB_COMMAND_OWNER);\n // Wait for any in-flight refreshTableSchemas() to finish before\n // destroying the connector. initialize() fires it without await,\n // so it may still be querying the native DuckDB instance; tearing\n // that down mid-flight causes a use-after-free segfault.\n if (refreshPromise) {\n try {\n await refreshPromise;\n } catch {\n // ignore – we're shutting down\n }\n }\n try {\n if (get().db.connector) {\n await get().db.connector.destroy();\n }\n } catch (err) {\n console.error('Error during DuckDB shutdown:', err);\n }\n },\n\n /**\n * Creates a table or view from a SQL query.\n * @param tableName - Name of the table/view to create\n * @param query - SQL query (must be a SELECT statement, or multiple statements ending with a SELECT when allowMultipleStatements is true)\n * @param options - Creation options\n * @param options.replace - If true, uses CREATE OR REPLACE (default: true)\n * @param options.temp - If true, creates a temporary table/view (default: false)\n * @param options.view - If true, creates a view instead of a table (default: false)\n * @param options.allowMultipleStatements - If true, allows multiple statements where preceding statements are executed first and the final SELECT is wrapped in CREATE TABLE/VIEW (default: false)\n * @returns Object with tableName and rowCount (rowCount is undefined for views)\n */\n async createTableFromQuery(\n tableName: string | QualifiedTableName,\n query: string,\n options?: {\n replace?: boolean;\n temp?: boolean;\n view?: boolean;\n allowMultipleStatements?: boolean;\n abortSignal?: AbortSignal;\n },\n ) {\n const {\n replace = true,\n temp = false,\n view = false,\n allowMultipleStatements = false,\n abortSignal,\n } = options || {};\n\n // For temp tables/views, DuckDB requires the \"temp\" database\n const baseQualifiedName = isQualifiedTableName(tableName)\n ? tableName\n : makeQualifiedTableName({table: tableName});\n\n const qualifiedName = temp\n ? makeQualifiedTableName({\n table: baseQualifiedName.table,\n schema: baseQualifiedName.schema,\n database: 'temp',\n })\n : baseQualifiedName;\n\n const connector = await get().db.getConnector();\n\n const {precedingStatements, lastStatement} =\n separateLastStatement(query);\n\n if (!allowMultipleStatements && precedingStatements.length > 0) {\n throw new Error(\n 'Query must contain exactly one statement (set allowMultipleStatements: true to execute multiple statements)',\n );\n }\n\n // The last statement must be a SELECT\n const parsedQuery = await get().db.sqlSelectToJson(lastStatement);\n if (parsedQuery.error) {\n throw new Error(\n 'Final statement must be a valid SELECT statement',\n );\n }\n\n // Build CREATE statement with options\n const createKeyword = [\n 'CREATE',\n replace ? 'OR REPLACE' : '',\n temp ? 'TEMP' : '',\n view ? 'VIEW' : 'TABLE',\n ]\n .filter(Boolean)\n .join(' ');\n\n const createStatement = `${createKeyword} ${qualifiedName} AS (\n ${lastStatement}\n )`;\n\n const fullQuery = joinStatements(\n precedingStatements,\n createStatement,\n );\n const result = await connector.query(fullQuery, {\n signal: abortSignal,\n });\n // Views don't have a row count, only tables do\n const rowCount = view ? undefined : getColValAsNumber(result);\n return {tableName, rowCount};\n },\n\n /**\n * @deprecated Use .tables or .loadTableSchemas() instead\n */\n async getTables(schema) {\n const tableSchemas = await get().db.loadTableSchemas({schema});\n return tableSchemas.map((t) => t.table.table);\n },\n\n /**\n * @deprecated Use .loadTableSchemas() instead\n */\n async getTableSchema(tableName: string, schema = 'main') {\n const newLocal = await get().db.loadTableSchemas({\n schema,\n table: tableName,\n });\n return newLocal[0];\n },\n\n /**\n * @deprecated Use .loadTableRowCount() instead\n */\n async getTableRowCount(table, schema = 'main') {\n return get().db.loadTableRowCount({table, schema});\n },\n\n async loadTableRowCount(tableName: string | QualifiedTableName) {\n const {schema, database, table} =\n typeof tableName === 'string'\n ? {table: tableName}\n : tableName || {};\n const connector = await get().db.getConnector();\n const result = await connector.query(\n `SELECT COUNT(*) FROM ${makeQualifiedTableName({\n schema,\n database,\n table,\n })}`,\n );\n return getColValAsNumber(result);\n },\n\n /**\n * @deprecated Use .loadTableSchemas() instead\n */\n async getTableSchemas(schema) {\n return await get().db.loadTableSchemas({schema});\n },\n\n async loadTableSchemas(\n filter?: LoadTableSchemasFilter,\n ): Promise<DataTable[]> {\n const connector = await get().db.getConnector();\n return loadTableSchemas(connector, {\n ...filter,\n filterFunction: loadTableSchemasFilter,\n });\n },\n\n async checkTableExists(tableName: string | QualifiedTableName) {\n const table = await loadTableSchemaByName(tableName);\n return Boolean(table);\n },\n\n async dropRelation(tableName): Promise<void> {\n const connector = await get().db.getConnector();\n const qualifiedTable = isQualifiedTableName(tableName)\n ? tableName\n : makeQualifiedTableName({table: tableName});\n const table =\n get().db.findTableByName(qualifiedTable) ??\n (await loadTableSchemaByName(qualifiedTable));\n const isView = table?.isView;\n if (isView) {\n await connector.query(`DROP VIEW IF EXISTS ${qualifiedTable};`);\n } else {\n await connector.query(`DROP TABLE IF EXISTS ${qualifiedTable};`);\n }\n get().db.refreshTableSchemas();\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 const table =\n get().db.findTableByName(qualifiedTable) ??\n (await loadTableSchemaByName(qualifiedTable));\n\n if (table?.isView) {\n throw new Error(\n `\"${qualifiedTable}\" is a view. Use dropRelation() to remove views.`,\n );\n }\n\n await connector.query(`DROP TABLE IF EXISTS ${qualifiedTable};`);\n 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 loadTableSchemaByName(qualifiedName);\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 get().db.refreshTableSchemas();\n return newTable;\n },\n\n async setTableRowCount(tableName, rowCount) {\n const qualifiedName = isQualifiedTableName(tableName)\n ? tableName\n : makeQualifiedTableName({table: tableName});\n set((state) =>\n produce(state, (draft) => {\n draft.db.tableRowCounts[qualifiedName.toString()] = rowCount;\n }),\n );\n },\n\n getTable(tableName) {\n return get().db.findTableByName(tableName);\n },\n\n findTableByName(tableName: string | QualifiedTableName) {\n const {table, schema, database} = {\n schema: get().db.currentSchema,\n database: get().db.currentDatabase,\n ...(typeof tableName === 'string'\n ? {table: tableName}\n : tableName),\n };\n return get().db.tables.find(\n (t) =>\n t.table.table === table &&\n (!schema || t.table.schema === schema) &&\n (!database || t.table.database === database),\n );\n },\n\n async refreshTableSchemas(): Promise<DataTable[]> {\n if (refreshPromise) {\n pendingSchemaRefresh = true;\n return refreshPromise;\n }\n set((state) =>\n produce(state, (draft) => {\n draft.db.isRefreshingTableSchemas = true;\n }),\n );\n refreshPromise = (async () => {\n try {\n let newTables: DataTable[];\n do {\n pendingSchemaRefresh = false;\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\n .getChild('schema')\n ?.get(0);\n draft.db.currentDatabase = result\n .getChild('database')\n ?.get(0);\n }),\n );\n newTables = await get().db.loadTableSchemas();\n } while (pendingSchemaRefresh);\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 refreshPromise = null;\n set((state) =>\n produce(state, (draft) => {\n draft.db.isRefreshingTableSchemas = false;\n }),\n );\n }\n })();\n return refreshPromise;\n },\n\n async sqlSelectToJson(sql: string) {\n const connector = await get().db.getConnector();\n const parsedQuery = (\n await connector.query(\n `SELECT json_serialize_sql(${escapeVal(sql)})`,\n )\n )\n .getChildAt(0)\n ?.get(0);\n return JSON.parse(parsedQuery);\n },\n\n async executeSql(query: string): Promise<QueryHandle | null> {\n // Create a unique key for this query\n const queryKey = `${query}`;\n const connector = await get().db.getConnector();\n\n // Check if we already have a cached query for this key\n const existingQuery = get().db.queryCache[queryKey];\n if (existingQuery) {\n return existingQuery;\n }\n\n const queryHandle = connector.query(query);\n // Cache the query handle immediately\n set((state) =>\n produce(state, (draft) => {\n draft.db.queryCache[queryKey] = queryHandle;\n }),\n );\n\n queryHandle.result.finally(() => {\n // remove from cache after completion\n set((state) =>\n produce(state, (draft) => {\n delete draft.db.queryCache[queryKey];\n }),\n );\n });\n\n return queryHandle;\n },\n },\n };\n },\n );\n}\n\ntype DuckDbCommandStoreState = BaseRoomStoreState & DuckDbSliceState;\n\nfunction createDuckDbCommands(): RoomCommand<DuckDbCommandStoreState>[] {\n return [\n {\n id: 'db.refresh-table-schemas',\n name: 'Refresh table schemas',\n description: 'Reload table and schema metadata from DuckDB',\n group: 'Database',\n keywords: ['duckdb', 'database', 'refresh', 'tables', 'schemas'],\n metadata: {\n readOnly: true,\n idempotent: true,\n riskLevel: 'low',\n },\n isEnabled: ({getState}) => !getState().db.isRefreshingTableSchemas,\n execute: async ({getState}) => {\n await getState().db.refreshTableSchemas();\n return {\n success: true,\n commandId: 'db.refresh-table-schemas',\n message: 'Table schemas refreshed.',\n };\n },\n },\n {\n id: 'db.drop-table',\n name: 'Drop relation',\n description: 'Drop a table or view from DuckDB by name',\n group: 'Database',\n keywords: [\n 'duckdb',\n 'database',\n 'drop',\n 'table',\n 'view',\n 'relation',\n 'delete',\n ],\n inputSchema: DropTableCommandInput,\n inputDescription: 'Provide a tableName to remove from DuckDB.',\n metadata: {\n readOnly: false,\n idempotent: true,\n riskLevel: 'high',\n requiresConfirmation: true,\n },\n validateInput: async (input, {getState}) => {\n const {tableName} = input as DropTableCommandInput;\n const exists = await getState().db.checkTableExists(tableName);\n if (!exists) {\n throw new Error(`Table \"${tableName}\" does not exist.`);\n }\n },\n execute: async ({getState}, input) => {\n const {tableName} = input as DropTableCommandInput;\n await getState().db.dropRelation(tableName);\n return {\n success: true,\n commandId: 'db.drop-table',\n message: `Dropped relation \"${tableName}\".`,\n };\n },\n },\n {\n id: 'db.create-table-from-query',\n name: 'Create table from query',\n description: 'Create a table or view from a SQL query',\n group: 'Database',\n keywords: ['duckdb', 'database', 'create', 'table', 'view', 'query'],\n inputSchema: CreateTableFromQueryCommandInput,\n inputDescription:\n 'Provide tableName and query, with optional replace/view/temp flags.',\n metadata: {\n readOnly: false,\n idempotent: false,\n riskLevel: 'medium',\n },\n validateInput: (input) => {\n const {query} = input as CreateTableFromQueryCommandInput;\n if (!query.trim()) {\n throw new Error('Query cannot be empty.');\n }\n },\n execute: async ({getState}, input) => {\n const {tableName, query, replace, view, temp, allowMultipleStatements} =\n input as CreateTableFromQueryCommandInput;\n const result = await getState().db.createTableFromQuery(\n tableName,\n query,\n {\n replace,\n view,\n temp,\n allowMultipleStatements,\n },\n );\n await getState().db.refreshTableSchemas();\n return {\n success: true,\n commandId: 'db.create-table-from-query',\n message: `Created ${view ? 'view' : 'table'} \"${tableName}\".`,\n data: result,\n };\n },\n },\n ];\n}\n\n/**\n * @internal\n * Select values from the room store that includes the DuckDB slice.\n *\n * This is a typed wrapper around `useBaseRoomStore` that narrows the\n * state to `RoomStateWithDuckDb` so selectors can access `db` safely.\n *\n * @typeParam T - The selected slice of state returned by the selector\n * @param selector - Function that selects a value from the store state\n * @returns The selected value of type `T`\n */\nexport function useStoreWithDuckDb<T>(\n selector: (state: BaseRoomStoreState & DuckDbSliceState) => T,\n): T {\n return useBaseRoomStore<DuckDbSliceState, T>((state) => selector(state));\n}\n"]}
1
+ {"version":3,"file":"DuckDbSlice.js","sourceRoot":"","sources":["../src/DuckDbSlice.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createDbSchemaTrees,\n DataTable,\n DbSchemaNode,\n DuckDbConnector,\n escapeVal,\n getColValAsNumber,\n isQualifiedTableName,\n joinStatements,\n makeQualifiedTableName,\n QualifiedTableName,\n QueryHandle,\n SchemaWithTables,\n separateLastStatement,\n} from '@sqlrooms/duckdb-core';\nimport {\n BaseRoomStoreState,\n createSlice,\n registerCommandsForOwner,\n RoomCommand,\n unregisterCommandsForOwner,\n useBaseRoomStore,\n} from '@sqlrooms/room-store';\nimport * as arrow from 'apache-arrow';\nimport deepEquals from 'fast-deep-equal';\nimport {produce} from 'immer';\nimport {z} from 'zod';\nimport {StateCreator} from 'zustand';\nimport {createWasmDuckDbConnector} from './connectors/createDuckDbConnector';\nimport {\n loadSchemaCatalog,\n LoadSchemaCatalogFilterFunction,\n loadTableSchemas,\n LoadTableSchemasFilter,\n LoadTableSchemasFilterFunction,\n} from './loadTableSchemas';\n\nconst DUCKDB_COMMAND_OWNER = '@sqlrooms/duckdb';\nconst INTERNAL_SQLROOMS_PREFIX = '__sqlrooms';\n\n/** DuckDB's temporary database catalog; never show in the default data source tree. */\nconst DUCKDB_TEMP_DATABASE = 'temp';\n\n/**\n * Default predicate: which tables/schemas/databases appear in the data source panel.\n * Hides `__sqlrooms_*` names and DuckDB's `temp` database.\n */\nexport const defaultLoadTableSchemasFilter: LoadTableSchemasFilterFunction = (\n table: QualifiedTableName,\n): boolean => {\n if (\n table.table?.startsWith(INTERNAL_SQLROOMS_PREFIX) ||\n table.database?.startsWith(INTERNAL_SQLROOMS_PREFIX) ||\n table.schema?.startsWith(INTERNAL_SQLROOMS_PREFIX)\n ) {\n return false;\n }\n if (table.database === DUCKDB_TEMP_DATABASE) {\n return false;\n }\n return true;\n};\n\n/**\n * Factory returning {@link defaultLoadTableSchemasFilter}.\n * Hides `__sqlrooms_*` names and DuckDB's `temp` database.\n * Apps can pass {@link CreateDuckDbSliceProps.loadTableSchemasFilter} to add more rules.\n */\nexport function createDefaultLoadTableSchemasFilter(): LoadTableSchemasFilterFunction {\n return defaultLoadTableSchemasFilter;\n}\n\n/**\n * Default catalog visibility predicate for the data source panel.\n * Hides SQLRooms internal objects and DuckDB's temporary database catalog.\n */\nexport const defaultLoadSchemaCatalogFilter: LoadSchemaCatalogFilterFunction = (\n entry,\n): boolean => {\n switch (entry.type) {\n case 'database':\n return (\n !entry.database.startsWith(INTERNAL_SQLROOMS_PREFIX) &&\n entry.database !== DUCKDB_TEMP_DATABASE\n );\n case 'schema':\n return (\n !entry.database.startsWith(INTERNAL_SQLROOMS_PREFIX) &&\n entry.database !== DUCKDB_TEMP_DATABASE &&\n !entry.schema.startsWith(INTERNAL_SQLROOMS_PREFIX)\n );\n case 'table':\n return defaultLoadTableSchemasFilter(entry.table);\n }\n};\n\nconst DropTableCommandInput = z.object({\n tableName: z.string().describe('Name of the table to drop.'),\n});\ntype DropTableCommandInput = z.infer<typeof DropTableCommandInput>;\n\nconst CreateTableFromQueryCommandInput = z.object({\n tableName: z.string().describe('Name of the table or view to create.'),\n query: z.string().describe('SQL query used to populate the table/view.'),\n replace: z\n .boolean()\n .optional()\n .default(true)\n .describe('Whether to replace existing table/view with the same name.'),\n view: z\n .boolean()\n .optional()\n .default(false)\n .describe('Whether to create a view instead of a table.'),\n temp: z\n .boolean()\n .optional()\n .default(false)\n .describe('Whether to create a temporary object.'),\n allowMultipleStatements: z\n .boolean()\n .optional()\n .default(false)\n .describe('Allow multiple SQL statements where the final one is SELECT.'),\n});\n\ntype CreateTableFromQueryCommandInput = z.infer<\n typeof CreateTableFromQueryCommandInput\n>;\n\n/**\n * State and actions for the DuckDB slice\n */\nexport type DuckDbSliceState = {\n db: {\n /**\n * The DuckDB connector instance\n */\n connector: DuckDbConnector;\n /**\n * @deprecated We shouldn't limit the schema to a single one.\n */\n schema: string;\n\n currentSchema: string | undefined;\n currentDatabase: string | undefined;\n\n /**\n * Cache of refreshed table schemas\n */\n tables: DataTable[];\n /**\n * Cache of row counts for tables\n */\n tableRowCounts: {[tableName: string]: number};\n /**\n * Cache of schema trees for tables\n */\n schemaTrees?: DbSchemaNode[];\n /**\n * Cache of currently running query handles.\n * This is only used for running queries to deduplicate them (especially for useSql),\n * the cache is cleared when the query is completed.\n */\n queryCache: {[key: string]: QueryHandle};\n /**\n * Whether the table schemas are being refreshed\n */\n isRefreshingTableSchemas: boolean;\n\n /**\n * Set a new DuckDB connector\n */\n setConnector: (connector: DuckDbConnector) => void;\n\n /**\n * Initialize the connector (creates a WasmDuckDbConnector if none exists)\n */\n initialize: () => Promise<void>;\n\n /**\n * Close and clean up the connector\n */\n destroy: () => Promise<void>;\n\n /**\n * Add a table to the room.\n * @param tableName - The name of the table to add.\n * @param data - The data to add to the table: an arrow table or an array of records.\n * @returns A promise that resolves to the table that was added.\n */\n addTable(\n tableName: string | QualifiedTableName,\n data: arrow.Table | Record<string, unknown>[],\n ): Promise<DataTable>;\n\n /**\n * Load the schemas of the tables in the database.\n */\n loadTableSchemas(filter?: LoadTableSchemasFilter): 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: (\n query: string,\n version?: number,\n ) => 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 or view with optional schema and database.\n * @param tableName - The name of the relation to delete (qualified or plain)\n */\n dropRelation: (tableName: string | QualifiedTableName) => Promise<void>;\n\n /**\n * Delete a table with optional schema and database.\n * @param tableName - The name of the table to delete (qualified or plain)\n */\n dropTable: (tableName: string | QualifiedTableName) => Promise<void>;\n\n /**\n * Create a table or view from a query.\n * @param tableName - The name of the table/view to create.\n * @param query - The query to create the table/view from.\n * @param options - Creation options.\n * @returns The table/view name and rowCount (undefined for views).\n */\n createTableFromQuery: (\n tableName: string | QualifiedTableName,\n query: string,\n options?: {\n replace?: boolean;\n temp?: boolean;\n view?: boolean;\n allowMultipleStatements?: boolean;\n abortSignal?: AbortSignal;\n },\n ) => Promise<{\n tableName: string | QualifiedTableName;\n rowCount: number | undefined;\n }>;\n\n /**\n * Parse a SQL SELECT statement to JSON\n * @param sql - The SQL SELECT statement to parse.\n * @returns A promise that resolves to the parsed JSON.\n */\n sqlSelectToJson: (sql: string) => Promise<\n | {\n error: true;\n error_type: string;\n error_message: string;\n error_subtype: string;\n position: string;\n }\n | {\n error: false;\n statements: {\n node: {\n from_table: {\n alias: string;\n show_type: string;\n table_name: string;\n };\n select_list: Record<string, unknown>[];\n type: string;\n };\n }[];\n }\n >;\n };\n};\n\nexport type CreateDuckDbSliceProps = {\n connector?: DuckDbConnector;\n /**\n * Optional table visibility filter.\n * Defaults to {@link createDefaultLoadTableSchemasFilter}.\n */\n loadTableSchemasFilter?: LoadTableSchemasFilterFunction | null;\n /**\n * Optional catalog visibility filter for the data source panel.\n * Defaults to {@link defaultLoadSchemaCatalogFilter}. When omitted, custom\n * table filters still apply to table entries while schemas/databases use the default.\n */\n loadSchemaCatalogFilter?: LoadSchemaCatalogFilterFunction | null;\n};\n\n/**\n * Create a DuckDB slice for managing the connector\n */\nexport function createDuckDbSlice({\n connector = createWasmDuckDbConnector(),\n loadTableSchemasFilter = defaultLoadTableSchemasFilter,\n loadSchemaCatalogFilter,\n}: CreateDuckDbSliceProps = {}): StateCreator<DuckDbSliceState> {\n let refreshPromise: Promise<DataTable[]> | null = null;\n let pendingSchemaRefresh = false;\n const effectiveSchemaCatalogFilter =\n loadSchemaCatalogFilter ??\n (loadTableSchemasFilter === null\n ? null\n : (((entry) => {\n if (entry.type === 'table') {\n return loadTableSchemasFilter\n ? loadTableSchemasFilter(entry.table)\n : true;\n }\n return defaultLoadSchemaCatalogFilter(entry);\n }) satisfies LoadSchemaCatalogFilterFunction));\n return createSlice<DuckDbSliceState, BaseRoomStoreState & DuckDbSliceState>(\n (set, get, store) => {\n /**\n * Internal helper to load a table schema by exact name, bypassing the visibility filter.\n * Used when performing exact lookups (e.g., checking if a specific table exists).\n */\n const loadTableSchemaByName = async (\n tableName: string | QualifiedTableName,\n ): Promise<DataTable | undefined> => {\n const qualifiedName = isQualifiedTableName(tableName)\n ? tableName\n : makeQualifiedTableName({table: tableName});\n const connector = await get().db.getConnector();\n const [table] = await loadTableSchemas(connector, qualifiedName);\n return table;\n };\n\n return {\n db: {\n connector, // Will be initialized during init\n schema: 'main', // TODO: remove schema, we should not limit the schema to a single one.\n currentSchema: undefined,\n currentDatabase: undefined,\n isRefreshingTableSchemas: false,\n tables: [],\n tableRowCounts: {},\n schemaTrees: undefined,\n queryCache: {},\n\n setConnector: (connector: DuckDbConnector) => {\n set(\n produce((state) => {\n state.config.dataSources = [];\n state.db.connector = connector;\n }),\n );\n },\n\n initialize: async () => {\n await get().db.connector.initialize();\n // No await here, we want to continue initializing the room even\n // if the table schemas are not refreshed yet\n get().db.refreshTableSchemas();\n registerCommandsForOwner(\n store,\n DUCKDB_COMMAND_OWNER,\n createDuckDbCommands(),\n );\n },\n\n getConnector: async () => {\n await get().db.connector.initialize();\n return get().db.connector;\n },\n\n destroy: async () => {\n unregisterCommandsForOwner(store, DUCKDB_COMMAND_OWNER);\n // Wait for any in-flight refreshTableSchemas() to finish before\n // destroying the connector. initialize() fires it without await,\n // so it may still be querying the native DuckDB instance; tearing\n // that down mid-flight causes a use-after-free segfault.\n if (refreshPromise) {\n try {\n await refreshPromise;\n } catch {\n // ignore – we're shutting down\n }\n }\n try {\n if (get().db.connector) {\n await get().db.connector.destroy();\n }\n } catch (err) {\n console.error('Error during DuckDB shutdown:', err);\n }\n },\n\n /**\n * Creates a table or view from a SQL query.\n * @param tableName - Name of the table/view to create\n * @param query - SQL query (must be a SELECT statement, or multiple statements ending with a SELECT when allowMultipleStatements is true)\n * @param options - Creation options\n * @param options.replace - If true, uses CREATE OR REPLACE (default: true)\n * @param options.temp - If true, creates a temporary table/view (default: false)\n * @param options.view - If true, creates a view instead of a table (default: false)\n * @param options.allowMultipleStatements - If true, allows multiple statements where preceding statements are executed first and the final SELECT is wrapped in CREATE TABLE/VIEW (default: false)\n * @returns Object with tableName and rowCount (rowCount is undefined for views)\n */\n async createTableFromQuery(\n tableName: string | QualifiedTableName,\n query: string,\n options?: {\n replace?: boolean;\n temp?: boolean;\n view?: boolean;\n allowMultipleStatements?: boolean;\n abortSignal?: AbortSignal;\n },\n ) {\n const {\n replace = true,\n temp = false,\n view = false,\n allowMultipleStatements = false,\n abortSignal,\n } = options || {};\n\n // For temp tables/views, DuckDB requires the \"temp\" database\n const baseQualifiedName = isQualifiedTableName(tableName)\n ? tableName\n : makeQualifiedTableName({table: tableName});\n\n const qualifiedName = temp\n ? makeQualifiedTableName({\n table: baseQualifiedName.table,\n schema: baseQualifiedName.schema,\n database: 'temp',\n })\n : baseQualifiedName;\n\n const connector = await get().db.getConnector();\n\n const {precedingStatements, lastStatement} =\n separateLastStatement(query);\n\n if (!allowMultipleStatements && precedingStatements.length > 0) {\n throw new Error(\n 'Query must contain exactly one statement (set allowMultipleStatements: true to execute multiple statements)',\n );\n }\n\n // The last statement must be a SELECT\n const parsedQuery = await get().db.sqlSelectToJson(lastStatement);\n if (parsedQuery.error) {\n throw new Error(\n 'Final statement must be a valid SELECT statement',\n );\n }\n\n // Build CREATE statement with options\n const createKeyword = [\n 'CREATE',\n replace ? 'OR REPLACE' : '',\n temp ? 'TEMP' : '',\n view ? 'VIEW' : 'TABLE',\n ]\n .filter(Boolean)\n .join(' ');\n\n const createStatement = `${createKeyword} ${qualifiedName} AS (\n ${lastStatement}\n )`;\n\n const fullQuery = joinStatements(\n precedingStatements,\n createStatement,\n );\n const result = await connector.query(fullQuery, {\n signal: abortSignal,\n });\n // Views don't have a row count, only tables do\n const rowCount = view ? undefined : getColValAsNumber(result);\n return {tableName, rowCount};\n },\n\n /**\n * @deprecated Use .tables or .loadTableSchemas() instead\n */\n async getTables(schema) {\n const tableSchemas = await get().db.loadTableSchemas({schema});\n return tableSchemas.map((t) => t.table.table);\n },\n\n /**\n * @deprecated Use .loadTableSchemas() instead\n */\n async getTableSchema(tableName: string, schema = 'main') {\n const newLocal = await get().db.loadTableSchemas({\n schema,\n table: tableName,\n });\n return newLocal[0];\n },\n\n /**\n * @deprecated Use .loadTableRowCount() instead\n */\n async getTableRowCount(table, schema = 'main') {\n return get().db.loadTableRowCount({table, schema});\n },\n\n async loadTableRowCount(tableName: string | QualifiedTableName) {\n const {schema, database, table} =\n typeof tableName === 'string'\n ? {table: tableName}\n : tableName || {};\n const connector = await get().db.getConnector();\n const result = await connector.query(\n `SELECT COUNT(*) FROM ${makeQualifiedTableName({\n schema,\n database,\n table,\n })}`,\n );\n return getColValAsNumber(result);\n },\n\n /**\n * @deprecated Use .loadTableSchemas() instead\n */\n async getTableSchemas(schema) {\n return await get().db.loadTableSchemas({schema});\n },\n\n async loadTableSchemas(\n filter?: LoadTableSchemasFilter,\n ): Promise<DataTable[]> {\n const connector = await get().db.getConnector();\n return loadTableSchemas(connector, {\n ...filter,\n filterFunction: loadTableSchemasFilter,\n });\n },\n\n async checkTableExists(tableName: string | QualifiedTableName) {\n const table = await loadTableSchemaByName(tableName);\n return Boolean(table);\n },\n\n async dropRelation(tableName): Promise<void> {\n const connector = await get().db.getConnector();\n const qualifiedTable = isQualifiedTableName(tableName)\n ? tableName\n : makeQualifiedTableName({table: tableName});\n const table =\n get().db.findTableByName(qualifiedTable) ??\n (await loadTableSchemaByName(qualifiedTable));\n const isView = table?.isView;\n if (isView) {\n await connector.query(`DROP VIEW IF EXISTS ${qualifiedTable};`);\n } else {\n await connector.query(`DROP TABLE IF EXISTS ${qualifiedTable};`);\n }\n get().db.refreshTableSchemas();\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 const table =\n get().db.findTableByName(qualifiedTable) ??\n (await loadTableSchemaByName(qualifiedTable));\n\n if (table?.isView) {\n throw new Error(\n `\"${qualifiedTable}\" is a view. Use dropRelation() to remove views.`,\n );\n }\n\n await connector.query(`DROP TABLE IF EXISTS ${qualifiedTable};`);\n 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 loadTableSchemaByName(qualifiedName);\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 get().db.refreshTableSchemas();\n return newTable;\n },\n\n async setTableRowCount(tableName, rowCount) {\n const qualifiedName = isQualifiedTableName(tableName)\n ? tableName\n : makeQualifiedTableName({table: tableName});\n set((state) =>\n produce(state, (draft) => {\n draft.db.tableRowCounts[qualifiedName.toString()] = rowCount;\n }),\n );\n },\n\n getTable(tableName) {\n return get().db.findTableByName(tableName);\n },\n\n findTableByName(tableName: string | QualifiedTableName) {\n const {table, schema, database} = {\n schema: get().db.currentSchema,\n database: get().db.currentDatabase,\n ...(typeof tableName === 'string'\n ? {table: tableName}\n : tableName),\n };\n return get().db.tables.find(\n (t) =>\n t.table.table === table &&\n (!schema || t.table.schema === schema) &&\n (!database || t.table.database === database),\n );\n },\n\n async refreshTableSchemas(): Promise<DataTable[]> {\n if (refreshPromise) {\n pendingSchemaRefresh = true;\n return refreshPromise;\n }\n set((state) =>\n produce(state, (draft) => {\n draft.db.isRefreshingTableSchemas = true;\n }),\n );\n refreshPromise = (async () => {\n try {\n let schemasWithTables: SchemaWithTables[] = [];\n do {\n pendingSchemaRefresh = false;\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\n .getChild('schema')\n ?.get(0);\n draft.db.currentDatabase = result\n .getChild('database')\n ?.get(0);\n }),\n );\n schemasWithTables = await loadSchemaCatalog(connector, {\n filterFunction: effectiveSchemaCatalogFilter,\n });\n } while (pendingSchemaRefresh);\n\n const newTables = schemasWithTables.flatMap((s) => s.tables);\n const currentTables = get().db.tables;\n const currentSchemaTrees = get().db.schemaTrees;\n const newSchemaTrees = createDbSchemaTrees(schemasWithTables);\n\n if (\n !deepEquals(newTables, currentTables) ||\n !deepEquals(newSchemaTrees, currentSchemaTrees)\n ) {\n set((state) =>\n produce(state, (draft) => {\n draft.db.tables = newTables;\n draft.db.schemaTrees = newSchemaTrees;\n }),\n );\n }\n return newTables;\n } catch (err) {\n get().room.captureException(err);\n return [];\n } finally {\n refreshPromise = null;\n set((state) =>\n produce(state, (draft) => {\n draft.db.isRefreshingTableSchemas = false;\n }),\n );\n }\n })();\n return refreshPromise;\n },\n\n async sqlSelectToJson(sql: string) {\n const connector = await get().db.getConnector();\n const parsedQuery = (\n await connector.query(\n `SELECT json_serialize_sql(${escapeVal(sql)})`,\n )\n )\n .getChildAt(0)\n ?.get(0);\n return JSON.parse(parsedQuery);\n },\n\n async executeSql(query: string): Promise<QueryHandle | null> {\n // Create a unique key for this query\n const queryKey = `${query}`;\n const connector = await get().db.getConnector();\n\n // Check if we already have a cached query for this key\n const existingQuery = get().db.queryCache[queryKey];\n if (existingQuery) {\n return existingQuery;\n }\n\n const queryHandle = connector.query(query);\n // Cache the query handle immediately\n set((state) =>\n produce(state, (draft) => {\n draft.db.queryCache[queryKey] = queryHandle;\n }),\n );\n\n queryHandle.result.finally(() => {\n // remove from cache after completion\n set((state) =>\n produce(state, (draft) => {\n delete draft.db.queryCache[queryKey];\n }),\n );\n });\n\n return queryHandle;\n },\n },\n };\n },\n );\n}\n\ntype DuckDbCommandStoreState = BaseRoomStoreState & DuckDbSliceState;\n\nfunction createDuckDbCommands(): RoomCommand<DuckDbCommandStoreState>[] {\n return [\n {\n id: 'db.refresh-table-schemas',\n name: 'Refresh table schemas',\n description: 'Reload table and schema metadata from DuckDB',\n group: 'Database',\n keywords: ['duckdb', 'database', 'refresh', 'tables', 'schemas'],\n metadata: {\n readOnly: true,\n idempotent: true,\n riskLevel: 'low',\n },\n isEnabled: ({getState}) => !getState().db.isRefreshingTableSchemas,\n execute: async ({getState}) => {\n await getState().db.refreshTableSchemas();\n return {\n success: true,\n commandId: 'db.refresh-table-schemas',\n message: 'Table schemas refreshed.',\n };\n },\n },\n {\n id: 'db.drop-table',\n name: 'Drop relation',\n description: 'Drop a table or view from DuckDB by name',\n group: 'Database',\n keywords: [\n 'duckdb',\n 'database',\n 'drop',\n 'table',\n 'view',\n 'relation',\n 'delete',\n ],\n inputSchema: DropTableCommandInput,\n inputDescription: 'Provide a tableName to remove from DuckDB.',\n metadata: {\n readOnly: false,\n idempotent: true,\n riskLevel: 'high',\n requiresConfirmation: true,\n },\n validateInput: async (input, {getState}) => {\n const {tableName} = input as DropTableCommandInput;\n const exists = await getState().db.checkTableExists(tableName);\n if (!exists) {\n throw new Error(`Table \"${tableName}\" does not exist.`);\n }\n },\n execute: async ({getState}, input) => {\n const {tableName} = input as DropTableCommandInput;\n await getState().db.dropRelation(tableName);\n return {\n success: true,\n commandId: 'db.drop-table',\n message: `Dropped relation \"${tableName}\".`,\n };\n },\n },\n {\n id: 'db.create-table-from-query',\n name: 'Create table from query',\n description: 'Create a table or view from a SQL query',\n group: 'Database',\n keywords: ['duckdb', 'database', 'create', 'table', 'view', 'query'],\n inputSchema: CreateTableFromQueryCommandInput,\n inputDescription:\n 'Provide tableName and query, with optional replace/view/temp flags.',\n metadata: {\n readOnly: false,\n idempotent: false,\n riskLevel: 'medium',\n },\n validateInput: (input) => {\n const {query} = input as CreateTableFromQueryCommandInput;\n if (!query.trim()) {\n throw new Error('Query cannot be empty.');\n }\n },\n execute: async ({getState}, input) => {\n const {tableName, query, replace, view, temp, allowMultipleStatements} =\n input as CreateTableFromQueryCommandInput;\n const result = await getState().db.createTableFromQuery(\n tableName,\n query,\n {\n replace,\n view,\n temp,\n allowMultipleStatements,\n },\n );\n await getState().db.refreshTableSchemas();\n return {\n success: true,\n commandId: 'db.create-table-from-query',\n message: `Created ${view ? 'view' : 'table'} \"${tableName}\".`,\n data: result,\n };\n },\n },\n ];\n}\n\n/**\n * @internal\n * Select values from the room store that includes the DuckDB slice.\n *\n * This is a typed wrapper around `useBaseRoomStore` that narrows the\n * state to `RoomStateWithDuckDb` so selectors can access `db` safely.\n *\n * @typeParam T - The selected slice of state returned by the selector\n * @param selector - Function that selects a value from the store state\n * @returns The selected value of type `T`\n */\nexport function useStoreWithDuckDb<T>(\n selector: (state: BaseRoomStoreState & DuckDbSliceState) => T,\n): T {\n return useBaseRoomStore<DuckDbSliceState, T>((state) => selector(state));\n}\n"]}
@@ -17,6 +17,6 @@ export type DuckDbConnectorOptions = ({
17
17
  };
18
18
  export declare function createDuckDbConnector(options: DuckDbConnectorOptions): DuckDbConnector;
19
19
  export { createWasmDuckDbConnector };
20
- export type { WasmDuckDbConnector };
20
+ export type { WasmDuckDbConnector, WasmDuckDbConnectorOptions };
21
21
  export declare function isWasmDuckDbConnector(connector: DuckDbConnector): connector is WasmDuckDbConnector;
22
22
  //# sourceMappingURL=createDuckDbConnector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createDuckDbConnector.d.ts","sourceRoot":"","sources":["../../src/connectors/createDuckDbConnector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,uBAAuB,CAAC;AACtD,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,0BAA0B,EAC3B,MAAM,uBAAuB,CAAC;AAG/B,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,IAAI,CAAC;AAEhD;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAC9B,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,GAAG,0BAA0B,CAAC,GAC7C;IACE,IAAI,EAAE,IAAI,CAAC;IACX,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEN,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,sBAAsB,GAC9B,eAAe,CAUjB;AAED,OAAO,EAAC,yBAAyB,EAAC,CAAC;AACnC,YAAY,EAAC,mBAAmB,EAAC,CAAC;AAElC,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,eAAe,GACzB,SAAS,IAAI,mBAAmB,CAElC"}
1
+ {"version":3,"file":"createDuckDbConnector.d.ts","sourceRoot":"","sources":["../../src/connectors/createDuckDbConnector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,uBAAuB,CAAC;AACtD,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,0BAA0B,EAC3B,MAAM,uBAAuB,CAAC;AAG/B,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,IAAI,CAAC;AAEhD;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAC9B,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,GAAG,0BAA0B,CAAC,GAC7C;IACE,IAAI,EAAE,IAAI,CAAC;IACX,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEN,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,sBAAsB,GAC9B,eAAe,CAUjB;AAED,OAAO,EAAC,yBAAyB,EAAC,CAAC;AACnC,YAAY,EAAC,mBAAmB,EAAE,0BAA0B,EAAC,CAAC;AAE9D,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,eAAe,GACzB,SAAS,IAAI,mBAAmB,CAElC"}
@@ -1 +1 @@
1
- {"version":3,"file":"createDuckDbConnector.js","sourceRoot":"","sources":["../../src/connectors/createDuckDbConnector.ts"],"names":[],"mappings":"AACA,OAAO,EACL,yBAAyB,GAG1B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAC,8BAA8B,EAAC,MAAM,4BAA4B,CAAC;AAmB1E,MAAM,UAAU,qBAAqB,CACnC,OAA+B;IAE/B,MAAM,EAAC,IAAI,EAAE,GAAG,IAAI,EAAC,GAAG,OAAO,CAAC;IAChC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,MAAM;YACT,OAAO,yBAAyB,CAAC,IAAI,CAAC,CAAC;QACzC,KAAK,IAAI;YACP,OAAO,8BAA8B,CAAC,IAAI,CAAC,CAAC;QAC9C;YACE,MAAM,IAAI,KAAK,CAAC,sCAAsC,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AAED,OAAO,EAAC,yBAAyB,EAAC,CAAC;AAGnC,MAAM,UAAU,qBAAqB,CACnC,SAA0B;IAE1B,OAAQ,SAAiB,CAAC,IAAI,KAAK,MAAM,CAAC;AAC5C,CAAC","sourcesContent":["import {DuckDbConnector} from '@sqlrooms/duckdb-core';\nimport {\n createWasmDuckDbConnector,\n WasmDuckDbConnector,\n WasmDuckDbConnectorOptions,\n} from './WasmDuckDbConnector';\nimport {createWebSocketDuckDbConnector} from './WebSocketDuckDbConnector';\n\nexport type DuckDbConnectorType = 'wasm' | 'ws';\n\n/**\n * Options for creating a DuckDB connector instance.\n * @deprecated Use `createWasmDuckDbConnector` or `createWebSocketDuckDbConnector` instead.\n * @public\n */\nexport type DuckDbConnectorOptions =\n | ({type: 'wasm'} & WasmDuckDbConnectorOptions)\n | {\n type: 'ws';\n /** WebSocket server URL */\n wsUrl?: string;\n /** SQL to run after connection */\n initializationQuery?: string;\n };\n\nexport function createDuckDbConnector(\n options: DuckDbConnectorOptions,\n): DuckDbConnector {\n const {type, ...rest} = options;\n switch (type) {\n case 'wasm':\n return createWasmDuckDbConnector(rest);\n case 'ws':\n return createWebSocketDuckDbConnector(rest);\n default:\n throw new Error(`Unsupported DuckDB connector type: ${type}`);\n }\n}\n\nexport {createWasmDuckDbConnector};\nexport type {WasmDuckDbConnector};\n\nexport function isWasmDuckDbConnector(\n connector: DuckDbConnector,\n): connector is WasmDuckDbConnector {\n return (connector as any).type === 'wasm';\n}\n"]}
1
+ {"version":3,"file":"createDuckDbConnector.js","sourceRoot":"","sources":["../../src/connectors/createDuckDbConnector.ts"],"names":[],"mappings":"AACA,OAAO,EACL,yBAAyB,GAG1B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAC,8BAA8B,EAAC,MAAM,4BAA4B,CAAC;AAmB1E,MAAM,UAAU,qBAAqB,CACnC,OAA+B;IAE/B,MAAM,EAAC,IAAI,EAAE,GAAG,IAAI,EAAC,GAAG,OAAO,CAAC;IAChC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,MAAM;YACT,OAAO,yBAAyB,CAAC,IAAI,CAAC,CAAC;QACzC,KAAK,IAAI;YACP,OAAO,8BAA8B,CAAC,IAAI,CAAC,CAAC;QAC9C;YACE,MAAM,IAAI,KAAK,CAAC,sCAAsC,IAAI,EAAE,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AAED,OAAO,EAAC,yBAAyB,EAAC,CAAC;AAGnC,MAAM,UAAU,qBAAqB,CACnC,SAA0B;IAE1B,OAAQ,SAAiB,CAAC,IAAI,KAAK,MAAM,CAAC;AAC5C,CAAC","sourcesContent":["import {DuckDbConnector} from '@sqlrooms/duckdb-core';\nimport {\n createWasmDuckDbConnector,\n WasmDuckDbConnector,\n WasmDuckDbConnectorOptions,\n} from './WasmDuckDbConnector';\nimport {createWebSocketDuckDbConnector} from './WebSocketDuckDbConnector';\n\nexport type DuckDbConnectorType = 'wasm' | 'ws';\n\n/**\n * Options for creating a DuckDB connector instance.\n * @deprecated Use `createWasmDuckDbConnector` or `createWebSocketDuckDbConnector` instead.\n * @public\n */\nexport type DuckDbConnectorOptions =\n | ({type: 'wasm'} & WasmDuckDbConnectorOptions)\n | {\n type: 'ws';\n /** WebSocket server URL */\n wsUrl?: string;\n /** SQL to run after connection */\n initializationQuery?: string;\n };\n\nexport function createDuckDbConnector(\n options: DuckDbConnectorOptions,\n): DuckDbConnector {\n const {type, ...rest} = options;\n switch (type) {\n case 'wasm':\n return createWasmDuckDbConnector(rest);\n case 'ws':\n return createWebSocketDuckDbConnector(rest);\n default:\n throw new Error(`Unsupported DuckDB connector type: ${type}`);\n }\n}\n\nexport {createWasmDuckDbConnector};\nexport type {WasmDuckDbConnector, WasmDuckDbConnectorOptions};\n\nexport function isWasmDuckDbConnector(\n connector: DuckDbConnector,\n): connector is WasmDuckDbConnector {\n return (connector as any).type === 'wasm';\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -5,13 +5,13 @@
5
5
  export { DuckDBAccessMode } from '@duckdb/duckdb-wasm';
6
6
  export type { DuckDBBundles, DuckDBConfig } from '@duckdb/duckdb-wasm';
7
7
  export { isSpatialLoadFileOptions, LoadFileOptions, SpatialLoadFileOptions, } from '@sqlrooms/room-config';
8
- export { createDuckDbConnector, createWasmDuckDbConnector, isWasmDuckDbConnector, type DuckDbConnectorOptions, type DuckDbConnectorType, type WasmDuckDbConnector, } from './connectors/createDuckDbConnector';
8
+ export { createDuckDbConnector, createWasmDuckDbConnector, isWasmDuckDbConnector, type DuckDbConnectorOptions, type DuckDbConnectorType, type WasmDuckDbConnector, type WasmDuckDbConnectorOptions, } from './connectors/createDuckDbConnector';
9
9
  export { createWebSocketDuckDbConnector, type WebSocketDuckDbConnector, type WebSocketDuckDbConnectorOptions, } from './connectors/WebSocketDuckDbConnector';
10
- export { createDuckDbSlice, useStoreWithDuckDb, createDefaultLoadTableSchemasFilter, type CreateDuckDbSliceProps, type DuckDbSliceState, } from './DuckDbSlice';
11
- export { type LoadTableSchemasFilter } from './loadTableSchemas';
10
+ export { createDuckDbSlice, useStoreWithDuckDb, createDefaultLoadTableSchemasFilter, defaultLoadSchemaCatalogFilter, defaultLoadTableSchemasFilter, type CreateDuckDbSliceProps, type DuckDbSliceState, } from './DuckDbSlice';
11
+ export { loadSchemaCatalog, type LoadSchemaCatalogFilterFunction, type LoadSchemaCatalogOptions, type LoadTableSchemasFilterFunction, type SchemaCatalogFilterEntry, type LoadTableSchemasFilter, type LoadTableSchemasOptions, } from './loadTableSchemas';
12
12
  export { useExportToCsv, type UseExportToCsvReturn } from './use-export-to-csv';
13
13
  export { useCopyAsTsv, type CopyAsTsvOptions, type CopyAsTsvResult, type UseCopyAsTsvReturn, } from './use-copy-as-tsv';
14
14
  export { useDuckDb } from './useDuckDb';
15
15
  export { useDuckDbQuery, useSql, type DuckDbQueryResult, type UseSqlQueryResult, } from './useSql';
16
- export { arrowTableToJson, createBaseDuckDbConnector, createDbSchemaTrees, createTypedRowAccessor, escapeId, escapeVal, getArrowColumnTypeCategory, getColValAsNumber, getDuckDbTypeCategory, getSqlErrorWithPointer, isNumericDuckType, isQualifiedTableName, joinStatements, literalToSQL, load, loadCSV, loadJSON, loadObjects, loadParquet, loadSpatial, makeLimitQuery, makeQualifiedTableName, sanitizeQuery, separateLastStatement, splitSqlStatements, sqlFrom, getFunctionSuggestions, getFunctionDocumentation, type BaseDuckDbConnectorImpl, type BaseDuckDbConnectorOptions, type ColumnNodeObject, type ColumnTypeCategory, type DatabaseNodeObject, type DataTable, type DbSchemaNode, type DuckDbConnector, type FunctionSuggestion, type GroupedFunctionSuggestion, type NodeObject, type QualifiedTableName, type QueryHandle, type QueryOptions, type SchemaNodeObject, type SeparatedStatements, type TableColumn, type TableNodeObject, type TypedRowAccessor, } from '@sqlrooms/duckdb-core';
16
+ export { arrowTableToJson, createBaseDuckDbConnector, createDbSchemaTrees, createTypedRowAccessor, escapeId, escapeVal, getArrowColumnTypeCategory, getColValAsNumber, getDuckDbTypeCategory, getSqlErrorWithPointer, isNumericDuckType, isQualifiedTableName, joinStatements, literalToSQL, load, loadCSV, loadJSON, loadObjects, loadParquet, loadSpatial, makeLimitQuery, makeQualifiedTableName, sanitizeQuery, separateLastStatement, splitSqlStatements, sqlFrom, getFunctionSuggestions, getFunctionDocumentation, type BaseDuckDbConnectorImpl, type BaseDuckDbConnectorOptions, type ColumnNodeObject, type ColumnTypeCategory, type DatabaseNodeObject, type DataTable, type DbSchemaNode, type DuckDbConnector, type FunctionSuggestion, type GroupedFunctionSuggestion, type NodeObject, type QualifiedTableName, type QueryHandle, type QueryOptions, type SchemaNodeObject, type SchemaWithTables, type SeparatedStatements, type TableColumn, type TableNodeObject, type TypedRowAccessor, } from '@sqlrooms/duckdb-core';
17
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,gBAAgB,EAAC,MAAM,qBAAqB,CAAC;AACrD,YAAY,EAAC,aAAa,EAAE,YAAY,EAAC,MAAM,qBAAqB,CAAC;AAErE,OAAO,EACL,wBAAwB,EACxB,eAAe,EACf,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,GACzB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EACL,8BAA8B,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,+BAA+B,GACrC,MAAM,uCAAuC,CAAC;AAE/C,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,mCAAmC,EACnC,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAC,KAAK,sBAAsB,EAAC,MAAM,oBAAoB,CAAC;AAE/D,OAAO,EAAC,cAAc,EAAE,KAAK,oBAAoB,EAAC,MAAM,qBAAqB,CAAC;AAE9E,OAAO,EACL,YAAY,EACZ,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,kBAAkB,GACxB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AAEtC,OAAO,EACL,cAAc,EACd,MAAM,EACN,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,GACvB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,gBAAgB,EAChB,yBAAyB,EACzB,mBAAmB,EACnB,sBAAsB,EACtB,QAAQ,EACR,SAAS,EACT,0BAA0B,EAC1B,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,EACd,YAAY,EACZ,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,WAAW,EACX,WAAW,EACX,WAAW,EACX,cAAc,EACd,sBAAsB,EACtB,aAAa,EACb,qBAAqB,EACrB,kBAAkB,EAClB,OAAO,EACP,sBAAsB,EACtB,wBAAwB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,0BAA0B,EAC/B,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,gBAAgB,EAAC,MAAM,qBAAqB,CAAC;AACrD,YAAY,EAAC,aAAa,EAAE,YAAY,EAAC,MAAM,qBAAqB,CAAC;AAErE,OAAO,EACL,wBAAwB,EACxB,eAAe,EACf,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,0BAA0B,GAChC,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EACL,8BAA8B,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,+BAA+B,GACrC,MAAM,uCAAuC,CAAC;AAE/C,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,mCAAmC,EACnC,8BAA8B,EAC9B,6BAA6B,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,iBAAiB,EACjB,KAAK,+BAA+B,EACpC,KAAK,wBAAwB,EAC7B,KAAK,8BAA8B,EACnC,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,GAC7B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAC,cAAc,EAAE,KAAK,oBAAoB,EAAC,MAAM,qBAAqB,CAAC;AAE9E,OAAO,EACL,YAAY,EACZ,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,kBAAkB,GACxB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AAEtC,OAAO,EACL,cAAc,EACd,MAAM,EACN,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,GACvB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,gBAAgB,EAChB,yBAAyB,EACzB,mBAAmB,EACnB,sBAAsB,EACtB,QAAQ,EACR,SAAS,EACT,0BAA0B,EAC1B,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,EACd,YAAY,EACZ,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,WAAW,EACX,WAAW,EACX,WAAW,EACX,cAAc,EACd,sBAAsB,EACtB,aAAa,EACb,qBAAqB,EACrB,kBAAkB,EAClB,OAAO,EACP,sBAAsB,EACtB,wBAAwB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,0BAA0B,EAC/B,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,uBAAuB,CAAC"}
package/dist/index.js CHANGED
@@ -6,7 +6,8 @@ export { DuckDBAccessMode } from '@duckdb/duckdb-wasm';
6
6
  export { isSpatialLoadFileOptions, LoadFileOptions, SpatialLoadFileOptions, } from '@sqlrooms/room-config';
7
7
  export { createDuckDbConnector, createWasmDuckDbConnector, isWasmDuckDbConnector, } from './connectors/createDuckDbConnector';
8
8
  export { createWebSocketDuckDbConnector, } from './connectors/WebSocketDuckDbConnector';
9
- export { createDuckDbSlice, useStoreWithDuckDb, createDefaultLoadTableSchemasFilter, } from './DuckDbSlice';
9
+ export { createDuckDbSlice, useStoreWithDuckDb, createDefaultLoadTableSchemasFilter, defaultLoadSchemaCatalogFilter, defaultLoadTableSchemasFilter, } from './DuckDbSlice';
10
+ export { loadSchemaCatalog, } from './loadTableSchemas';
10
11
  export { useExportToCsv } from './use-export-to-csv';
11
12
  export { useCopyAsTsv, } from './use-copy-as-tsv';
12
13
  export { useDuckDb } from './useDuckDb';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,gBAAgB,EAAC,MAAM,qBAAqB,CAAC;AAGrD,OAAO,EACL,wBAAwB,EACxB,eAAe,EACf,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,GAItB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EACL,8BAA8B,GAG/B,MAAM,uCAAuC,CAAC;AAE/C,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,mCAAmC,GAGpC,MAAM,eAAe,CAAC;AAIvB,OAAO,EAAC,cAAc,EAA4B,MAAM,qBAAqB,CAAC;AAE9E,OAAO,EACL,YAAY,GAIb,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AAEtC,OAAO,EACL,cAAc,EACd,MAAM,GAGP,MAAM,UAAU,CAAC;AAElB,uCAAuC;AACvC,OAAO,EACL,gBAAgB,EAChB,yBAAyB,EACzB,mBAAmB,EACnB,sBAAsB,EACtB,QAAQ,EACR,SAAS,EACT,0BAA0B,EAC1B,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,EACd,YAAY,EACZ,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,WAAW,EACX,WAAW,EACX,WAAW,EACX,cAAc,EACd,sBAAsB,EACtB,aAAa,EACb,qBAAqB,EACrB,kBAAkB,EAClB,OAAO,EACP,sBAAsB,EACtB,wBAAwB,GAoBzB,MAAM,uBAAuB,CAAC","sourcesContent":["/**\n * {@include ../README.md}\n * @packageDocumentation\n */\n\nexport {DuckDBAccessMode} from '@duckdb/duckdb-wasm';\nexport type {DuckDBBundles, DuckDBConfig} from '@duckdb/duckdb-wasm';\n\nexport {\n isSpatialLoadFileOptions,\n LoadFileOptions,\n SpatialLoadFileOptions,\n} from '@sqlrooms/room-config';\n\nexport {\n createDuckDbConnector,\n createWasmDuckDbConnector,\n isWasmDuckDbConnector,\n type DuckDbConnectorOptions,\n type DuckDbConnectorType,\n type WasmDuckDbConnector,\n} from './connectors/createDuckDbConnector';\n\nexport {\n createWebSocketDuckDbConnector,\n type WebSocketDuckDbConnector,\n type WebSocketDuckDbConnectorOptions,\n} from './connectors/WebSocketDuckDbConnector';\n\nexport {\n createDuckDbSlice,\n useStoreWithDuckDb,\n createDefaultLoadTableSchemasFilter,\n type CreateDuckDbSliceProps,\n type DuckDbSliceState,\n} from './DuckDbSlice';\n\nexport {type LoadTableSchemasFilter} from './loadTableSchemas';\n\nexport {useExportToCsv, type UseExportToCsvReturn} from './use-export-to-csv';\n\nexport {\n useCopyAsTsv,\n type CopyAsTsvOptions,\n type CopyAsTsvResult,\n type UseCopyAsTsvReturn,\n} from './use-copy-as-tsv';\n\nexport {useDuckDb} from './useDuckDb';\n\nexport {\n useDuckDbQuery,\n useSql,\n type DuckDbQueryResult,\n type UseSqlQueryResult,\n} from './useSql';\n\n// Re-export from @sqlrooms/duckdb-core\nexport {\n arrowTableToJson,\n createBaseDuckDbConnector,\n createDbSchemaTrees,\n createTypedRowAccessor,\n escapeId,\n escapeVal,\n getArrowColumnTypeCategory,\n getColValAsNumber,\n getDuckDbTypeCategory,\n getSqlErrorWithPointer,\n isNumericDuckType,\n isQualifiedTableName,\n joinStatements,\n literalToSQL,\n load,\n loadCSV,\n loadJSON,\n loadObjects,\n loadParquet,\n loadSpatial,\n makeLimitQuery,\n makeQualifiedTableName,\n sanitizeQuery,\n separateLastStatement,\n splitSqlStatements,\n sqlFrom,\n getFunctionSuggestions,\n getFunctionDocumentation,\n type BaseDuckDbConnectorImpl,\n type BaseDuckDbConnectorOptions,\n type ColumnNodeObject,\n type ColumnTypeCategory,\n type DatabaseNodeObject,\n type DataTable,\n type DbSchemaNode,\n type DuckDbConnector,\n type FunctionSuggestion,\n type GroupedFunctionSuggestion,\n type NodeObject,\n type QualifiedTableName,\n type QueryHandle,\n type QueryOptions,\n type SchemaNodeObject,\n type SeparatedStatements,\n type TableColumn,\n type TableNodeObject,\n type TypedRowAccessor,\n} from '@sqlrooms/duckdb-core';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,gBAAgB,EAAC,MAAM,qBAAqB,CAAC;AAGrD,OAAO,EACL,wBAAwB,EACxB,eAAe,EACf,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,GAKtB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EACL,8BAA8B,GAG/B,MAAM,uCAAuC,CAAC;AAE/C,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,mCAAmC,EACnC,8BAA8B,EAC9B,6BAA6B,GAG9B,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,iBAAiB,GAOlB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAC,cAAc,EAA4B,MAAM,qBAAqB,CAAC;AAE9E,OAAO,EACL,YAAY,GAIb,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AAEtC,OAAO,EACL,cAAc,EACd,MAAM,GAGP,MAAM,UAAU,CAAC;AAElB,uCAAuC;AACvC,OAAO,EACL,gBAAgB,EAChB,yBAAyB,EACzB,mBAAmB,EACnB,sBAAsB,EACtB,QAAQ,EACR,SAAS,EACT,0BAA0B,EAC1B,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,cAAc,EACd,YAAY,EACZ,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,WAAW,EACX,WAAW,EACX,WAAW,EACX,cAAc,EACd,sBAAsB,EACtB,aAAa,EACb,qBAAqB,EACrB,kBAAkB,EAClB,OAAO,EACP,sBAAsB,EACtB,wBAAwB,GAqBzB,MAAM,uBAAuB,CAAC","sourcesContent":["/**\n * {@include ../README.md}\n * @packageDocumentation\n */\n\nexport {DuckDBAccessMode} from '@duckdb/duckdb-wasm';\nexport type {DuckDBBundles, DuckDBConfig} from '@duckdb/duckdb-wasm';\n\nexport {\n isSpatialLoadFileOptions,\n LoadFileOptions,\n SpatialLoadFileOptions,\n} from '@sqlrooms/room-config';\n\nexport {\n createDuckDbConnector,\n createWasmDuckDbConnector,\n isWasmDuckDbConnector,\n type DuckDbConnectorOptions,\n type DuckDbConnectorType,\n type WasmDuckDbConnector,\n type WasmDuckDbConnectorOptions,\n} from './connectors/createDuckDbConnector';\n\nexport {\n createWebSocketDuckDbConnector,\n type WebSocketDuckDbConnector,\n type WebSocketDuckDbConnectorOptions,\n} from './connectors/WebSocketDuckDbConnector';\n\nexport {\n createDuckDbSlice,\n useStoreWithDuckDb,\n createDefaultLoadTableSchemasFilter,\n defaultLoadSchemaCatalogFilter,\n defaultLoadTableSchemasFilter,\n type CreateDuckDbSliceProps,\n type DuckDbSliceState,\n} from './DuckDbSlice';\n\nexport {\n loadSchemaCatalog,\n type LoadSchemaCatalogFilterFunction,\n type LoadSchemaCatalogOptions,\n type LoadTableSchemasFilterFunction,\n type SchemaCatalogFilterEntry,\n type LoadTableSchemasFilter,\n type LoadTableSchemasOptions,\n} from './loadTableSchemas';\n\nexport {useExportToCsv, type UseExportToCsvReturn} from './use-export-to-csv';\n\nexport {\n useCopyAsTsv,\n type CopyAsTsvOptions,\n type CopyAsTsvResult,\n type UseCopyAsTsvReturn,\n} from './use-copy-as-tsv';\n\nexport {useDuckDb} from './useDuckDb';\n\nexport {\n useDuckDbQuery,\n useSql,\n type DuckDbQueryResult,\n type UseSqlQueryResult,\n} from './useSql';\n\n// Re-export from @sqlrooms/duckdb-core\nexport {\n arrowTableToJson,\n createBaseDuckDbConnector,\n createDbSchemaTrees,\n createTypedRowAccessor,\n escapeId,\n escapeVal,\n getArrowColumnTypeCategory,\n getColValAsNumber,\n getDuckDbTypeCategory,\n getSqlErrorWithPointer,\n isNumericDuckType,\n isQualifiedTableName,\n joinStatements,\n literalToSQL,\n load,\n loadCSV,\n loadJSON,\n loadObjects,\n loadParquet,\n loadSpatial,\n makeLimitQuery,\n makeQualifiedTableName,\n sanitizeQuery,\n separateLastStatement,\n splitSqlStatements,\n sqlFrom,\n getFunctionSuggestions,\n getFunctionDocumentation,\n type BaseDuckDbConnectorImpl,\n type BaseDuckDbConnectorOptions,\n type ColumnNodeObject,\n type ColumnTypeCategory,\n type DatabaseNodeObject,\n type DataTable,\n type DbSchemaNode,\n type DuckDbConnector,\n type FunctionSuggestion,\n type GroupedFunctionSuggestion,\n type NodeObject,\n type QualifiedTableName,\n type QueryHandle,\n type QueryOptions,\n type SchemaNodeObject,\n type SchemaWithTables,\n type SeparatedStatements,\n type TableColumn,\n type TableNodeObject,\n type TypedRowAccessor,\n} from '@sqlrooms/duckdb-core';\n"]}
@@ -1,4 +1,4 @@
1
- import { DataTable, DuckDbConnector, QualifiedTableName } from '@sqlrooms/duckdb-core';
1
+ import { DataTable, DuckDbConnector, QualifiedTableName, SchemaWithTables } from '@sqlrooms/duckdb-core';
2
2
  export type LoadTableSchemasFilterFunction = (table: QualifiedTableName) => boolean;
3
3
  export type LoadTableSchemasFilter = {
4
4
  schema?: string;
@@ -8,10 +8,31 @@ export type LoadTableSchemasFilter = {
8
8
  export type LoadTableSchemasOptions = LoadTableSchemasFilter & {
9
9
  filterFunction?: LoadTableSchemasFilterFunction | null;
10
10
  };
11
+ export type SchemaCatalogFilterEntry = {
12
+ type: 'database';
13
+ database: string;
14
+ } | {
15
+ type: 'schema';
16
+ database: string;
17
+ schema: string;
18
+ } | {
19
+ type: 'table';
20
+ table: QualifiedTableName;
21
+ };
22
+ export type LoadSchemaCatalogFilterFunction = (entry: SchemaCatalogFilterEntry) => boolean;
23
+ export type LoadSchemaCatalogOptions = LoadTableSchemasFilter & {
24
+ filterFunction?: LoadSchemaCatalogFilterFunction | null;
25
+ };
11
26
  /**
12
27
  * Internal helper to load table schemas with optional filter bypass.
13
28
  * Used for exact lookups where we don't want the visibility filter to hide results.
14
29
  * Omit `filterFunction` to bypass filtering.
15
30
  */
16
31
  export declare function loadTableSchemas(connector: DuckDbConnector, options?: LoadTableSchemasOptions): Promise<DataTable[]>;
32
+ /**
33
+ * Load the visible DuckDB schema catalog in one metadata query.
34
+ * Starts from schemas, then left-joins tables, views, and columns so empty
35
+ * schemas and empty attached database `main` schemas are preserved.
36
+ */
37
+ export declare function loadSchemaCatalog(connector: DuckDbConnector, options?: LoadSchemaCatalogOptions): Promise<SchemaWithTables[]>;
17
38
  //# sourceMappingURL=loadTableSchemas.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"loadTableSchemas.d.ts","sourceRoot":"","sources":["../src/loadTableSchemas.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,eAAe,EAGf,kBAAkB,EAEnB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,MAAM,8BAA8B,GAAG,CAC3C,KAAK,EAAE,kBAAkB,KACtB,OAAO,CAAC;AAEb,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,sBAAsB,GAAG;IAC7D,cAAc,CAAC,EAAE,8BAA8B,GAAG,IAAI,CAAC;CACxD,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,eAAe,EAC1B,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,SAAS,EAAE,CAAC,CAiBtB"}
1
+ {"version":3,"file":"loadTableSchemas.d.ts","sourceRoot":"","sources":["../src/loadTableSchemas.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,eAAe,EAGf,kBAAkB,EAClB,gBAAgB,EAEjB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,MAAM,8BAA8B,GAAG,CAC3C,KAAK,EAAE,kBAAkB,KACtB,OAAO,CAAC;AAEb,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,sBAAsB,GAAG;IAC7D,cAAc,CAAC,EAAE,8BAA8B,GAAG,IAAI,CAAC;CACxD,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAChC;IAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAC,GACpC;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,GAClD;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,kBAAkB,CAAA;CAAC,CAAC;AAE/C,MAAM,MAAM,+BAA+B,GAAG,CAC5C,KAAK,EAAE,wBAAwB,KAC5B,OAAO,CAAC;AAEb,MAAM,MAAM,wBAAwB,GAAG,sBAAsB,GAAG;IAC9D,cAAc,CAAC,EAAE,+BAA+B,GAAG,IAAI,CAAC;CACzD,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,eAAe,EAC1B,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,SAAS,EAAE,CAAC,CAiBtB;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,eAAe,EAC1B,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA2C7B"}
@@ -18,6 +18,47 @@ export async function loadTableSchemas(connector, options = {}) {
18
18
  }
19
19
  return tables;
20
20
  }
21
+ /**
22
+ * Load the visible DuckDB schema catalog in one metadata query.
23
+ * Starts from schemas, then left-joins tables, views, and columns so empty
24
+ * schemas and empty attached database `main` schemas are preserved.
25
+ */
26
+ export async function loadSchemaCatalog(connector, options = {}) {
27
+ const { filterFunction, ...filter } = options;
28
+ const result = await connector.query(buildSchemaCatalogQuery(filter));
29
+ const groups = new Map();
30
+ const includedDatabases = new Set();
31
+ const keyOf = (database, schema) => `${database}\x00${schema}`;
32
+ for (let i = 0; i < result.numRows; i++) {
33
+ const database = String(result.getChild('database')?.get(i) ?? '').trim();
34
+ const schema = String(result.getChild('schema')?.get(i) ?? '').trim();
35
+ if (!database || !schema)
36
+ continue;
37
+ if (!includedDatabases.has(database)) {
38
+ if (filterFunction?.({ type: 'database', database }) === false) {
39
+ continue;
40
+ }
41
+ else {
42
+ includedDatabases.add(database);
43
+ }
44
+ }
45
+ if (filterFunction?.({ type: 'schema', database, schema }) === false) {
46
+ continue;
47
+ }
48
+ const key = keyOf(database, schema);
49
+ let group = groups.get(key);
50
+ if (!group) {
51
+ group = { database, schema, tables: [] };
52
+ groups.set(key, group);
53
+ }
54
+ const table = parseSchemaCatalogTableRow(result, i);
55
+ if (table &&
56
+ (!filterFunction || filterFunction({ type: 'table', table: table.table }))) {
57
+ group.tables.push(table);
58
+ }
59
+ }
60
+ return Array.from(groups.values());
61
+ }
21
62
  function isDuckDbPlaceholderViewColumn(columnName, columnType) {
22
63
  return columnName === '__' && columnType.toUpperCase() === 'UNKNOWN';
23
64
  }
@@ -67,6 +108,12 @@ function parseTableSchemaRow(describeResults, index) {
67
108
  : estimatedSize,
68
109
  };
69
110
  }
111
+ function parseSchemaCatalogTableRow(result, index) {
112
+ const rowTable = result.getChild('name')?.get(index);
113
+ if (rowTable == null)
114
+ return null;
115
+ return parseTableSchemaRow(result, index);
116
+ }
70
117
  function buildMetadataWhereClause(nameColumn, filter) {
71
118
  const { schema, database, table } = filter;
72
119
  return [
@@ -79,6 +126,77 @@ function buildMetadataWhereClause(nameColumn, filter) {
79
126
  .filter(Boolean)
80
127
  .join(' AND ');
81
128
  }
129
+ function buildSchemaWhereClause(filter) {
130
+ const { schema, database } = filter;
131
+ return [
132
+ database
133
+ ? `database_name = ${escapeVal(database)}`
134
+ : `database_name != 'system'`,
135
+ schema ? `schema_name = ${escapeVal(schema)}` : 'schema_name IS NOT NULL',
136
+ `(internal = false OR schema_name = 'main')`,
137
+ ]
138
+ .filter(Boolean)
139
+ .join(' AND ');
140
+ }
141
+ function buildSchemaCatalogQuery(filter) {
142
+ const schemaWhereClause = buildSchemaWhereClause(filter);
143
+ const tableWhereClause = buildMetadataWhereClause('table_name', filter);
144
+ const viewWhereClause = buildMetadataWhereClause('view_name', filter);
145
+ return `WITH schemas AS (
146
+ FROM duckdb_schemas() SELECT DISTINCT
147
+ COALESCE(
148
+ NULLIF(CAST(database_name AS VARCHAR), ''),
149
+ current_database()
150
+ ) AS database,
151
+ CAST(schema_name AS VARCHAR) AS schema
152
+ WHERE ${schemaWhereClause}
153
+ ),
154
+ tables_and_views AS (
155
+ FROM duckdb_tables() SELECT
156
+ database_name AS database,
157
+ schema_name AS schema,
158
+ table_name AS name,
159
+ sql,
160
+ comment,
161
+ estimated_size,
162
+ FALSE AS isView
163
+ WHERE ${tableWhereClause}
164
+ UNION ALL
165
+ FROM duckdb_views() SELECT
166
+ database_name AS database,
167
+ schema_name AS schema,
168
+ view_name AS name,
169
+ sql,
170
+ comment,
171
+ NULL AS estimated_size,
172
+ TRUE AS isView
173
+ WHERE ${viewWhereClause}
174
+ ),
175
+ columns AS (
176
+ FROM duckdb_columns() SELECT
177
+ database_name AS database,
178
+ schema_name AS schema,
179
+ table_name AS name,
180
+ list(column_name ORDER BY column_index) AS column_names,
181
+ list(data_type ORDER BY column_index) AS column_types
182
+ WHERE ${tableWhereClause}
183
+ GROUP BY database_name, schema_name, table_name
184
+ )
185
+ SELECT
186
+ tables_and_views.isView AS isView,
187
+ schemas.database AS database,
188
+ schemas.schema AS schema,
189
+ tables_and_views.name AS name,
190
+ columns.column_names AS column_names,
191
+ columns.column_types AS column_types,
192
+ tables_and_views.sql AS sql,
193
+ tables_and_views.comment AS comment,
194
+ tables_and_views.estimated_size AS estimated_size
195
+ FROM schemas
196
+ LEFT JOIN tables_and_views USING (database, schema)
197
+ LEFT JOIN columns USING (database, schema, name)
198
+ ORDER BY schemas.database, schemas.schema, tables_and_views.isView, tables_and_views.name`;
199
+ }
82
200
  /**
83
201
  * Builds the SQL query to load table and view schemas from DuckDB system catalogs.
84
202
  * Uses CTEs to efficiently join table/view metadata with column information.
@@ -1 +1 @@
1
- {"version":3,"file":"loadTableSchemas.js","sourceRoot":"","sources":["../src/loadTableSchemas.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n DataTable,\n DuckDbConnector,\n escapeVal,\n makeQualifiedTableName,\n QualifiedTableName,\n TableColumn,\n} from '@sqlrooms/duckdb-core';\n\nexport type LoadTableSchemasFilterFunction = (\n table: QualifiedTableName,\n) => boolean;\n\nexport type LoadTableSchemasFilter = {\n schema?: string;\n database?: string;\n table?: string;\n};\n\nexport type LoadTableSchemasOptions = LoadTableSchemasFilter & {\n filterFunction?: LoadTableSchemasFilterFunction | null;\n};\n\n/**\n * Internal helper to load table schemas with optional filter bypass.\n * Used for exact lookups where we don't want the visibility filter to hide results.\n * Omit `filterFunction` to bypass filtering.\n */\nexport async function loadTableSchemas(\n connector: DuckDbConnector,\n options: LoadTableSchemasOptions = {},\n): Promise<DataTable[]> {\n const {filterFunction, ...filter} = options;\n\n const sql = buildTableSchemasQuery(filter);\n const describeResults = await connector.query(sql);\n const tables: DataTable[] = [];\n\n for (let i = 0; i < describeResults.numRows; i++) {\n const dataTable = parseTableSchemaRow(describeResults, i);\n\n // Apply filter (if not provided or null, include all tables)\n if (!filterFunction || filterFunction(dataTable.table)) {\n tables.push(dataTable);\n }\n }\n\n return tables;\n}\n\nfunction isDuckDbPlaceholderViewColumn(\n columnName: string,\n columnType: string,\n): boolean {\n return columnName === '__' && columnType.toUpperCase() === 'UNKNOWN';\n}\n\n/**\n * Parses a single row from the table schema query results into a DataTable object.\n */\nfunction parseTableSchemaRow(describeResults: any, index: number): DataTable {\n const isView = describeResults.getChild('isView')?.get(index);\n const rowDatabase = describeResults.getChild('database')?.get(index);\n const rowSchema = describeResults.getChild('schema')?.get(index);\n const rowTable = describeResults.getChild('name')?.get(index);\n const sql = describeResults.getChild('sql')?.get(index);\n const comment = describeResults.getChild('comment')?.get(index);\n const estimatedSize = describeResults.getChild('estimated_size')?.get(index);\n const columnNames = describeResults.getChild('column_names')?.get(index);\n const columnTypes = describeResults.getChild('column_types')?.get(index);\n\n const qualifiedTable = makeQualifiedTableName({\n database: rowDatabase,\n schema: rowSchema,\n table: rowTable,\n });\n\n const columns: TableColumn[] = [];\n for (let ci = 0; ci < (columnNames?.length ?? 0); ci++) {\n const columnName = String(columnNames.get(ci));\n const columnType = String(columnTypes?.get(ci));\n if (isDuckDbPlaceholderViewColumn(columnName, columnType)) {\n continue;\n }\n columns.push({\n name: columnName,\n type: columnType,\n });\n }\n\n return {\n table: qualifiedTable,\n database: rowDatabase,\n schema: rowSchema,\n tableName: rowTable,\n columns,\n sql,\n comment,\n isView: Boolean(isView),\n rowCount:\n typeof estimatedSize === 'bigint'\n ? Number(estimatedSize)\n : estimatedSize === null\n ? undefined\n : estimatedSize,\n };\n}\n\nfunction buildMetadataWhereClause(\n nameColumn: string,\n filter: LoadTableSchemasFilter,\n): string {\n const {schema, database, table} = filter;\n return [\n database\n ? `database_name = ${escapeVal(database)}`\n : `database_name != 'system'`,\n schema ? `schema_name = ${escapeVal(schema)}` : '',\n table ? `${nameColumn} = ${escapeVal(table)}` : '',\n ]\n .filter(Boolean)\n .join(' AND ');\n}\n\n/**\n * Builds the SQL query to load table and view schemas from DuckDB system catalogs.\n * Uses CTEs to efficiently join table/view metadata with column information.\n */\nfunction buildTableSchemasQuery(filter: LoadTableSchemasFilter): string {\n const tableWhereClause = buildMetadataWhereClause('table_name', filter);\n const viewWhereClause = buildMetadataWhereClause('view_name', filter);\n\n return `WITH tables_and_views AS (\n FROM duckdb_tables() SELECT\n database_name AS database,\n schema_name AS schema,\n table_name AS name,\n sql,\n comment,\n estimated_size,\n FALSE AS isView\n WHERE ${tableWhereClause}\n UNION ALL\n FROM duckdb_views() SELECT\n database_name AS database,\n schema_name AS schema,\n view_name AS name,\n sql,\n comment,\n NULL AS estimated_size,\n TRUE AS isView\n WHERE ${viewWhereClause}\n ),\n columns AS (\n FROM duckdb_columns() SELECT\n database_name AS database,\n schema_name AS schema,\n table_name AS name,\n list(column_name ORDER BY column_index) AS column_names,\n list(data_type ORDER BY column_index) AS column_types\n WHERE ${tableWhereClause}\n GROUP BY database_name, schema_name, table_name\n )\n SELECT\n isView,\n database,\n schema,\n name,\n column_names,\n column_types,\n sql,\n comment,\n estimated_size\n FROM tables_and_views\n LEFT JOIN columns USING (database, schema, name)\n ORDER BY isView, database, schema, name`;\n}\n"]}
1
+ {"version":3,"file":"loadTableSchemas.js","sourceRoot":"","sources":["../src/loadTableSchemas.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n DataTable,\n DuckDbConnector,\n escapeVal,\n makeQualifiedTableName,\n QualifiedTableName,\n SchemaWithTables,\n TableColumn,\n} from '@sqlrooms/duckdb-core';\n\nexport type LoadTableSchemasFilterFunction = (\n table: QualifiedTableName,\n) => boolean;\n\nexport type LoadTableSchemasFilter = {\n schema?: string;\n database?: string;\n table?: string;\n};\n\nexport type LoadTableSchemasOptions = LoadTableSchemasFilter & {\n filterFunction?: LoadTableSchemasFilterFunction | null;\n};\n\nexport type SchemaCatalogFilterEntry =\n | {type: 'database'; database: string}\n | {type: 'schema'; database: string; schema: string}\n | {type: 'table'; table: QualifiedTableName};\n\nexport type LoadSchemaCatalogFilterFunction = (\n entry: SchemaCatalogFilterEntry,\n) => boolean;\n\nexport type LoadSchemaCatalogOptions = LoadTableSchemasFilter & {\n filterFunction?: LoadSchemaCatalogFilterFunction | null;\n};\n\n/**\n * Internal helper to load table schemas with optional filter bypass.\n * Used for exact lookups where we don't want the visibility filter to hide results.\n * Omit `filterFunction` to bypass filtering.\n */\nexport async function loadTableSchemas(\n connector: DuckDbConnector,\n options: LoadTableSchemasOptions = {},\n): Promise<DataTable[]> {\n const {filterFunction, ...filter} = options;\n\n const sql = buildTableSchemasQuery(filter);\n const describeResults = await connector.query(sql);\n const tables: DataTable[] = [];\n\n for (let i = 0; i < describeResults.numRows; i++) {\n const dataTable = parseTableSchemaRow(describeResults, i);\n\n // Apply filter (if not provided or null, include all tables)\n if (!filterFunction || filterFunction(dataTable.table)) {\n tables.push(dataTable);\n }\n }\n\n return tables;\n}\n\n/**\n * Load the visible DuckDB schema catalog in one metadata query.\n * Starts from schemas, then left-joins tables, views, and columns so empty\n * schemas and empty attached database `main` schemas are preserved.\n */\nexport async function loadSchemaCatalog(\n connector: DuckDbConnector,\n options: LoadSchemaCatalogOptions = {},\n): Promise<SchemaWithTables[]> {\n const {filterFunction, ...filter} = options;\n const result = await connector.query(buildSchemaCatalogQuery(filter));\n const groups = new Map<string, SchemaWithTables>();\n const includedDatabases = new Set<string>();\n const keyOf = (database: string, schema: string) =>\n `${database}\\x00${schema}`;\n\n for (let i = 0; i < result.numRows; i++) {\n const database = String(result.getChild('database')?.get(i) ?? '').trim();\n const schema = String(result.getChild('schema')?.get(i) ?? '').trim();\n if (!database || !schema) continue;\n\n if (!includedDatabases.has(database)) {\n if (filterFunction?.({type: 'database', database}) === false) {\n continue;\n } else {\n includedDatabases.add(database);\n }\n }\n\n if (filterFunction?.({type: 'schema', database, schema}) === false) {\n continue;\n }\n\n const key = keyOf(database, schema);\n let group = groups.get(key);\n\n if (!group) {\n group = {database, schema, tables: []};\n groups.set(key, group);\n }\n\n const table = parseSchemaCatalogTableRow(result, i);\n if (\n table &&\n (!filterFunction || filterFunction({type: 'table', table: table.table}))\n ) {\n group.tables.push(table);\n }\n }\n\n return Array.from(groups.values());\n}\n\nfunction isDuckDbPlaceholderViewColumn(\n columnName: string,\n columnType: string,\n): boolean {\n return columnName === '__' && columnType.toUpperCase() === 'UNKNOWN';\n}\n\n/**\n * Parses a single row from the table schema query results into a DataTable object.\n */\nfunction parseTableSchemaRow(describeResults: any, index: number): DataTable {\n const isView = describeResults.getChild('isView')?.get(index);\n const rowDatabase = describeResults.getChild('database')?.get(index);\n const rowSchema = describeResults.getChild('schema')?.get(index);\n const rowTable = describeResults.getChild('name')?.get(index);\n const sql = describeResults.getChild('sql')?.get(index);\n const comment = describeResults.getChild('comment')?.get(index);\n const estimatedSize = describeResults.getChild('estimated_size')?.get(index);\n const columnNames = describeResults.getChild('column_names')?.get(index);\n const columnTypes = describeResults.getChild('column_types')?.get(index);\n\n const qualifiedTable = makeQualifiedTableName({\n database: rowDatabase,\n schema: rowSchema,\n table: rowTable,\n });\n\n const columns: TableColumn[] = [];\n for (let ci = 0; ci < (columnNames?.length ?? 0); ci++) {\n const columnName = String(columnNames.get(ci));\n const columnType = String(columnTypes?.get(ci));\n if (isDuckDbPlaceholderViewColumn(columnName, columnType)) {\n continue;\n }\n columns.push({\n name: columnName,\n type: columnType,\n });\n }\n\n return {\n table: qualifiedTable,\n database: rowDatabase,\n schema: rowSchema,\n tableName: rowTable,\n columns,\n sql,\n comment,\n isView: Boolean(isView),\n rowCount:\n typeof estimatedSize === 'bigint'\n ? Number(estimatedSize)\n : estimatedSize === null\n ? undefined\n : estimatedSize,\n };\n}\n\nfunction parseSchemaCatalogTableRow(\n result: any,\n index: number,\n): DataTable | null {\n const rowTable = result.getChild('name')?.get(index);\n if (rowTable == null) return null;\n return parseTableSchemaRow(result, index);\n}\n\nfunction buildMetadataWhereClause(\n nameColumn: string,\n filter: LoadTableSchemasFilter,\n): string {\n const {schema, database, table} = filter;\n return [\n database\n ? `database_name = ${escapeVal(database)}`\n : `database_name != 'system'`,\n schema ? `schema_name = ${escapeVal(schema)}` : '',\n table ? `${nameColumn} = ${escapeVal(table)}` : '',\n ]\n .filter(Boolean)\n .join(' AND ');\n}\n\nfunction buildSchemaWhereClause(filter: LoadTableSchemasFilter): string {\n const {schema, database} = filter;\n return [\n database\n ? `database_name = ${escapeVal(database)}`\n : `database_name != 'system'`,\n schema ? `schema_name = ${escapeVal(schema)}` : 'schema_name IS NOT NULL',\n `(internal = false OR schema_name = 'main')`,\n ]\n .filter(Boolean)\n .join(' AND ');\n}\n\nfunction buildSchemaCatalogQuery(filter: LoadTableSchemasFilter): string {\n const schemaWhereClause = buildSchemaWhereClause(filter);\n const tableWhereClause = buildMetadataWhereClause('table_name', filter);\n const viewWhereClause = buildMetadataWhereClause('view_name', filter);\n\n return `WITH schemas AS (\n FROM duckdb_schemas() SELECT DISTINCT\n COALESCE(\n NULLIF(CAST(database_name AS VARCHAR), ''),\n current_database()\n ) AS database,\n CAST(schema_name AS VARCHAR) AS schema\n WHERE ${schemaWhereClause}\n ),\n tables_and_views AS (\n FROM duckdb_tables() SELECT\n database_name AS database,\n schema_name AS schema,\n table_name AS name,\n sql,\n comment,\n estimated_size,\n FALSE AS isView\n WHERE ${tableWhereClause}\n UNION ALL\n FROM duckdb_views() SELECT\n database_name AS database,\n schema_name AS schema,\n view_name AS name,\n sql,\n comment,\n NULL AS estimated_size,\n TRUE AS isView\n WHERE ${viewWhereClause}\n ),\n columns AS (\n FROM duckdb_columns() SELECT\n database_name AS database,\n schema_name AS schema,\n table_name AS name,\n list(column_name ORDER BY column_index) AS column_names,\n list(data_type ORDER BY column_index) AS column_types\n WHERE ${tableWhereClause}\n GROUP BY database_name, schema_name, table_name\n )\n SELECT\n tables_and_views.isView AS isView,\n schemas.database AS database,\n schemas.schema AS schema,\n tables_and_views.name AS name,\n columns.column_names AS column_names,\n columns.column_types AS column_types,\n tables_and_views.sql AS sql,\n tables_and_views.comment AS comment,\n tables_and_views.estimated_size AS estimated_size\n FROM schemas\n LEFT JOIN tables_and_views USING (database, schema)\n LEFT JOIN columns USING (database, schema, name)\n ORDER BY schemas.database, schemas.schema, tables_and_views.isView, tables_and_views.name`;\n}\n\n/**\n * Builds the SQL query to load table and view schemas from DuckDB system catalogs.\n * Uses CTEs to efficiently join table/view metadata with column information.\n */\nfunction buildTableSchemasQuery(filter: LoadTableSchemasFilter): string {\n const tableWhereClause = buildMetadataWhereClause('table_name', filter);\n const viewWhereClause = buildMetadataWhereClause('view_name', filter);\n\n return `WITH tables_and_views AS (\n FROM duckdb_tables() SELECT\n database_name AS database,\n schema_name AS schema,\n table_name AS name,\n sql,\n comment,\n estimated_size,\n FALSE AS isView\n WHERE ${tableWhereClause}\n UNION ALL\n FROM duckdb_views() SELECT\n database_name AS database,\n schema_name AS schema,\n view_name AS name,\n sql,\n comment,\n NULL AS estimated_size,\n TRUE AS isView\n WHERE ${viewWhereClause}\n ),\n columns AS (\n FROM duckdb_columns() SELECT\n database_name AS database,\n schema_name AS schema,\n table_name AS name,\n list(column_name ORDER BY column_index) AS column_names,\n list(data_type ORDER BY column_index) AS column_types\n WHERE ${tableWhereClause}\n GROUP BY database_name, schema_name, table_name\n )\n SELECT\n isView,\n database,\n schema,\n name,\n column_names,\n column_types,\n sql,\n comment,\n estimated_size\n FROM tables_and_views\n LEFT JOIN columns USING (database, schema, name)\n ORDER BY isView, database, schema, name`;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sqlrooms/duckdb",
3
- "version": "0.29.0-rc.4",
3
+ "version": "0.29.0-rc.6",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/sqlrooms/sqlrooms.git"
@@ -25,18 +25,18 @@
25
25
  "typedoc": "typedoc"
26
26
  },
27
27
  "dependencies": {
28
- "@duckdb/duckdb-wasm": "1.32.0",
29
- "@sqlrooms/duckdb-core": "0.29.0-rc.4",
30
- "@sqlrooms/room-config": "0.29.0-rc.4",
31
- "@sqlrooms/room-store": "0.29.0-rc.4",
32
- "@sqlrooms/utils": "0.29.0-rc.4",
28
+ "@duckdb/duckdb-wasm": "^1.32.0 || 1.33.1-dev55.0",
29
+ "@sqlrooms/duckdb-core": "0.29.0-rc.6",
30
+ "@sqlrooms/room-config": "0.29.0-rc.6",
31
+ "@sqlrooms/room-store": "0.29.0-rc.6",
32
+ "@sqlrooms/utils": "0.29.0-rc.6",
33
33
  "fast-deep-equal": "^3.1.3",
34
34
  "immer": "^11.0.1",
35
35
  "zod": "^4.1.8",
36
36
  "zustand": "^5.0.8"
37
37
  },
38
38
  "devDependencies": {
39
- "@sqlrooms/duckdb-node": "0.29.0-rc.4",
39
+ "@sqlrooms/duckdb-node": "0.29.0-rc.6",
40
40
  "@types/jest": "^30.0.0",
41
41
  "jest": "^30.1.3",
42
42
  "ts-jest": "^29.4.4"
@@ -47,5 +47,5 @@
47
47
  "publishConfig": {
48
48
  "access": "public"
49
49
  },
50
- "gitHead": "8694bab9d3d915a06d28675ad801b21444bcc55f"
50
+ "gitHead": "fbf5ee8897c5c06306b5433d26378cf658b5b298"
51
51
  }