@sqlrooms/duckdb 0.15.0 → 0.16.1

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.
Files changed (40) hide show
  1. package/dist/DuckDbSlice.d.ts +102 -23
  2. package/dist/DuckDbSlice.d.ts.map +1 -1
  3. package/dist/DuckDbSlice.js +201 -63
  4. package/dist/DuckDbSlice.js.map +1 -1
  5. package/dist/connectors/BaseDuckDbConnector.d.ts +22 -5
  6. package/dist/connectors/BaseDuckDbConnector.d.ts.map +1 -1
  7. package/dist/connectors/BaseDuckDbConnector.js +66 -15
  8. package/dist/connectors/BaseDuckDbConnector.js.map +1 -1
  9. package/dist/connectors/DuckDbConnector.d.ts +237 -4
  10. package/dist/connectors/DuckDbConnector.d.ts.map +1 -1
  11. package/dist/connectors/DuckDbConnector.js.map +1 -1
  12. package/dist/connectors/WasmDuckDbConnector.d.ts +2 -1
  13. package/dist/connectors/WasmDuckDbConnector.d.ts.map +1 -1
  14. package/dist/connectors/WasmDuckDbConnector.js +90 -17
  15. package/dist/connectors/WasmDuckDbConnector.js.map +1 -1
  16. package/dist/duckdb-utils.d.ts +67 -0
  17. package/dist/duckdb-utils.d.ts.map +1 -1
  18. package/dist/duckdb-utils.js +195 -0
  19. package/dist/duckdb-utils.js.map +1 -1
  20. package/dist/exportToCsv.js +1 -1
  21. package/dist/exportToCsv.js.map +1 -1
  22. package/dist/index.d.ts +3 -2
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +3 -2
  25. package/dist/index.js.map +1 -1
  26. package/dist/schemaTree.d.ts +8 -0
  27. package/dist/schemaTree.d.ts.map +1 -0
  28. package/dist/schemaTree.js +76 -0
  29. package/dist/schemaTree.js.map +1 -0
  30. package/dist/typeCategories.d.ts +16 -0
  31. package/dist/typeCategories.d.ts.map +1 -0
  32. package/dist/typeCategories.js +72 -0
  33. package/dist/typeCategories.js.map +1 -0
  34. package/dist/types.d.ts +35 -0
  35. package/dist/types.d.ts.map +1 -1
  36. package/dist/types.js.map +1 -1
  37. package/dist/useSql.d.ts.map +1 -1
  38. package/dist/useSql.js +11 -7
  39. package/dist/useSql.js.map +1 -1
  40. package/package.json +13 -12
@@ -49,18 +49,7 @@ export class WasmDuckDbConnector extends BaseDuckDbConnector {
49
49
  path: this.dbPath,
50
50
  query: this.queryConfig,
51
51
  });
52
- const conn = await db.connect();
53
- // Add error handling to conn.query
54
- const originalQuery = conn.query;
55
- conn.query = (async (q) => {
56
- const stack = new Error().stack;
57
- try {
58
- return await originalQuery.call(conn, q);
59
- }
60
- catch (err) {
61
- throw new DuckQueryError(err, q, stack);
62
- }
63
- });
52
+ const conn = augmentConnectionQueryError(await db.connect());
64
53
  if (this.initializationQuery) {
65
54
  await conn.query(this.initializationQuery);
66
55
  }
@@ -97,16 +86,82 @@ export class WasmDuckDbConnector extends BaseDuckDbConnector {
97
86
  throw err;
98
87
  }
99
88
  }
100
- async query(query) {
89
+ async executeQueryInternal(query, signal) {
90
+ // Make sure the WASM runtime is ready.
101
91
  await this.ensureInitialized();
102
- if (!this.conn) {
103
- throw new Error('DuckDB connection not initialized');
92
+ if (!this.db) {
93
+ throw new Error('DuckDB not initialized');
94
+ }
95
+ // Short‑circuit if the caller already aborted.
96
+ if (signal.aborted) {
97
+ throw new Error('Query aborted before execution');
98
+ }
99
+ // 👉 Open a *fresh* connection dedicated to this request.
100
+ const conn = augmentConnectionQueryError(await this.db.connect());
101
+ // 1️⃣ Kick‑off the statement using the *cancellable* streaming API
102
+ const streamPromise = conn.send(query, /* allowStreamResult */ true);
103
+ // Handle to the Arrow reader so we can cancel it later.
104
+ let reader = null;
105
+ // 2️⃣ Helper to materialise all batches into one Arrow Table.
106
+ const buildTable = async () => {
107
+ reader = await streamPromise;
108
+ const batches = [];
109
+ let rowCount = 0;
110
+ for await (const batch of reader) {
111
+ // DuckDB‑wasm may emit an empty placeholder batch when connections
112
+ // race. Ignore any batch whose `numRows` is zero.
113
+ if (batch.numRows === 0)
114
+ continue;
115
+ batches.push(batch);
116
+ rowCount += batch.numRows;
117
+ }
118
+ if (rowCount === 0) {
119
+ return arrow.tableFromArrays({});
120
+ }
121
+ return new arrow.Table(batches);
122
+ };
123
+ // 3️⃣ Wire the AbortSignal → DuckDB interrupt.
124
+ let abortHandler;
125
+ const abortPromise = new Promise((_, reject) => {
126
+ abortHandler = () => {
127
+ // Interrupt DuckDB *and* stop the Arrow stream
128
+ conn.cancelSent().catch(() => {
129
+ /* ignore if nothing to cancel */
130
+ });
131
+ reader?.cancel?.();
132
+ reject(new Error('Query cancelled'));
133
+ };
134
+ signal.addEventListener('abort', abortHandler);
135
+ });
136
+ try {
137
+ // Whichever finishes first (query or cancel) wins.
138
+ return await Promise.race([buildTable(), abortPromise]);
139
+ }
140
+ finally {
141
+ if (abortHandler) {
142
+ signal.removeEventListener('abort', abortHandler);
143
+ }
144
+ // Always close the per‑query connection.
145
+ await conn.close();
146
+ }
147
+ }
148
+ async cancelQueryInternal(queryId) {
149
+ // First, invoke the base‑class logic (removes AbortController listeners, etc.)
150
+ await super.cancelQueryInternal(queryId);
151
+ // Then, interrupt the running statement on the DuckDB side.
152
+ if (this.conn) {
153
+ try {
154
+ await this.conn.cancelSent();
155
+ }
156
+ catch (err) {
157
+ // If no statement is active or interrupt fails, just log and move on.
158
+ console.warn('DuckDB cancelSent failed:', err);
159
+ }
104
160
  }
105
- return await this.conn.query(query);
106
161
  }
107
162
  async loadFile(file, tableName, opts) {
108
163
  await this.withTempRegisteredFile(file, async (fileName) => {
109
- super.loadFile(fileName, tableName, opts);
164
+ await super.loadFile(fileName, tableName, opts);
110
165
  });
111
166
  }
112
167
  async loadArrow(file, tableName, opts) {
@@ -172,6 +227,24 @@ export class WasmDuckDbConnector extends BaseDuckDbConnector {
172
227
  return this.conn;
173
228
  }
174
229
  }
230
+ /**
231
+ * Augment the connection query method to include the full query and stack trace in the error.
232
+ * @param conn - The connection to augment.
233
+ * @returns The augmented connection.
234
+ */
235
+ function augmentConnectionQueryError(conn) {
236
+ const originalQuery = conn.query;
237
+ conn.query = (async (q) => {
238
+ const stack = new Error().stack;
239
+ try {
240
+ return await originalQuery.call(conn, q);
241
+ }
242
+ catch (err) {
243
+ throw new DuckQueryError(err, q, stack);
244
+ }
245
+ });
246
+ return conn;
247
+ }
175
248
  export class DuckQueryError extends Error {
176
249
  cause;
177
250
  query;
@@ -1 +1 @@
1
- {"version":3,"file":"WasmDuckDbConnector.js","sourceRoot":"","sources":["../../src/connectors/WasmDuckDbConnector.ts"],"names":[],"mappings":"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","sourcesContent":["import * as duckdb from '@duckdb/duckdb-wasm';\nimport {DuckDBDataProtocol, DuckDBQueryConfig} from '@duckdb/duckdb-wasm';\nimport {LoadFileOptions, StandardLoadOptions} from '@sqlrooms/project-config';\nimport {splitFilePath} from '@sqlrooms/utils';\nimport * as arrow from 'apache-arrow';\nimport {BaseDuckDbConnector} from './BaseDuckDbConnector';\nimport {loadObjects} from './load/load';\n\nexport class WasmDuckDbConnector extends BaseDuckDbConnector {\n private logging: boolean;\n private db: duckdb.AsyncDuckDB | null = null;\n private conn: duckdb.AsyncDuckDBConnection | null = null;\n private worker: Worker | null = null;\n private queryConfig?: DuckDBQueryConfig;\n\n constructor({\n logging = false,\n initializationQuery = '',\n dbPath = ':memory:',\n queryConfig,\n }: {\n dbPath?: string;\n queryConfig?: DuckDBQueryConfig;\n initializationQuery?: string;\n logging?: boolean;\n } = {}) {\n super({dbPath, initializationQuery});\n this.queryConfig = queryConfig;\n this.logging = logging;\n }\n\n protected async initializeInternal(): Promise<void> {\n if (!globalThis.Worker) {\n throw new Error('No Worker support in this environment');\n }\n\n try {\n const allBundles = duckdb.getJsDelivrBundles();\n const bestBundle = await duckdb.selectBundle(allBundles);\n if (!bestBundle.mainWorker) {\n throw new Error('No best bundle found for DuckDB worker');\n }\n const workerUrl = URL.createObjectURL(\n new Blob([`importScripts(\"${bestBundle.mainWorker}\");`], {\n type: 'text/javascript',\n }),\n );\n\n const worker = new window.Worker(workerUrl);\n const logger = this.logging\n ? new duckdb.ConsoleLogger()\n : {\n // Silently log\n log: () => {\n /* do nothing */\n },\n };\n\n const db = new (class extends duckdb.AsyncDuckDB {\n onError(event: ErrorEvent) {\n super.onError(event);\n console.error('DuckDB worker error:', event);\n }\n })(logger, worker);\n\n await db.instantiate(bestBundle.mainModule, bestBundle.pthreadWorker);\n URL.revokeObjectURL(workerUrl);\n\n await db.open({\n path: this.dbPath,\n query: this.queryConfig,\n });\n\n const conn = await db.connect();\n\n // Add error handling to conn.query\n const originalQuery = conn.query;\n conn.query = (async (q: string) => {\n const stack = new Error().stack;\n try {\n return await originalQuery.call(conn, q);\n } catch (err) {\n throw new DuckQueryError(err, q, stack);\n }\n }) as typeof conn.query;\n\n if (this.initializationQuery) {\n await conn.query(this.initializationQuery);\n }\n\n this.db = db;\n this.conn = conn;\n this.worker = worker;\n this.initialized = true;\n } catch (err) {\n this.initialized = false;\n this.initializing = null;\n throw err;\n }\n }\n\n async destroy(): Promise<void> {\n try {\n if (this.conn) {\n await this.conn.close();\n this.conn = null;\n }\n\n if (this.db) {\n await this.db.terminate();\n this.db = null;\n }\n\n if (this.worker) {\n this.worker.terminate();\n this.worker = null;\n }\n\n this.initialized = false;\n this.initializing = null;\n } catch (err) {\n console.error('Error during DuckDB shutdown:', err);\n throw err;\n }\n }\n\n async query<T extends arrow.TypeMap = any>(\n query: string,\n ): Promise<arrow.Table<T>> {\n await this.ensureInitialized();\n if (!this.conn) {\n throw new Error('DuckDB connection not initialized');\n }\n return await this.conn.query(query);\n }\n\n async loadFile(\n file: string | File,\n tableName: string,\n opts?: LoadFileOptions,\n ) {\n await this.withTempRegisteredFile(file, async (fileName) => {\n super.loadFile(fileName, tableName, opts);\n });\n }\n\n async loadArrow(\n file: arrow.Table | Uint8Array,\n tableName: string,\n opts?: {schema?: string},\n ) {\n await this.ensureInitialized();\n if (!this.conn) {\n throw new Error('DuckDB connection not initialized');\n }\n const options = {name: tableName, schema: opts?.schema};\n if (file instanceof arrow.Table) {\n await this.conn.insertArrowTable(file, options);\n } else {\n await this.conn.insertArrowFromIPCStream(file, options);\n }\n }\n\n async loadObjects(\n file: Record<string, unknown>[],\n tableName: string,\n opts?: StandardLoadOptions,\n ) {\n await this.ensureInitialized();\n if (!this.conn) {\n throw new Error('DuckDB connection not initialized');\n }\n await this.conn.query(loadObjects(tableName, file, opts));\n }\n\n private async withTempRegisteredFile(\n file: string | File,\n action: (fileName: string) => Promise<void>,\n ) {\n await this.ensureInitialized();\n if (!this.conn || !this.db) {\n throw new Error('DuckDB connection not initialized');\n }\n let fileName: string;\n let tempFileName: string | undefined = undefined;\n if (file instanceof File) {\n // Extension might help DuckDB determine the file type\n const {ext} = splitFilePath(file.name);\n tempFileName = `${Math.random().toString(36).substring(2, 15)}${ext ? `.${ext}` : ''}`;\n fileName = tempFileName;\n await this.db.registerFileHandle(\n fileName,\n file,\n DuckDBDataProtocol.BROWSER_FILEREADER,\n true,\n );\n } else {\n fileName = file;\n }\n try {\n await action(fileName);\n } catch (err) {\n console.error(`Error during file loading \"${fileName}\":`, err);\n throw err;\n } finally {\n if (tempFileName) {\n await this.db.dropFile(tempFileName);\n }\n }\n }\n\n getDb(): duckdb.AsyncDuckDB {\n if (!this.db) {\n throw new Error('DuckDB not initialized');\n }\n return this.db;\n }\n\n getConnection(): duckdb.AsyncDuckDBConnection {\n if (!this.conn) {\n throw new Error('DuckDB connection not initialized');\n }\n return this.conn;\n }\n}\n\nexport class DuckQueryError extends Error {\n readonly cause: unknown;\n readonly query: string | undefined;\n readonly queryCallStack: string | undefined;\n constructor(err: unknown, query: string, stack: string | undefined) {\n super(err instanceof Error ? err.message : `${err}`);\n this.cause = err;\n this.query = query;\n this.queryCallStack = stack;\n Object.setPrototypeOf(this, DuckQueryError.prototype);\n }\n getDetailedMessage() {\n const {message, query, queryCallStack: stack} = this;\n return (\n `DB query failed: ${message}` +\n `\\n\\nFull query:\\n\\n${query}\\n\\nQuery call stack:\\n\\n${stack}\\n\\n`\n );\n }\n getMessageForUser() {\n const {message} = this;\n return message;\n }\n}\n"]}
1
+ {"version":3,"file":"WasmDuckDbConnector.js","sourceRoot":"","sources":["../../src/connectors/WasmDuckDbConnector.ts"],"names":[],"mappings":"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","sourcesContent":["import * as duckdb from '@duckdb/duckdb-wasm';\nimport {DuckDBDataProtocol, DuckDBQueryConfig} from '@duckdb/duckdb-wasm';\nimport {LoadFileOptions, StandardLoadOptions} from '@sqlrooms/project-config';\nimport {splitFilePath} from '@sqlrooms/utils';\nimport * as arrow from 'apache-arrow';\nimport {BaseDuckDbConnector} from './BaseDuckDbConnector';\nimport {loadObjects} from './load/load';\n\nexport class WasmDuckDbConnector extends BaseDuckDbConnector {\n private logging: boolean;\n private db: duckdb.AsyncDuckDB | null = null;\n private conn: duckdb.AsyncDuckDBConnection | null = null;\n private worker: Worker | null = null;\n private queryConfig?: DuckDBQueryConfig;\n\n constructor({\n logging = false,\n initializationQuery = '',\n dbPath = ':memory:',\n queryConfig,\n }: {\n dbPath?: string;\n queryConfig?: DuckDBQueryConfig;\n initializationQuery?: string;\n logging?: boolean;\n } = {}) {\n super({dbPath, initializationQuery});\n this.queryConfig = queryConfig;\n this.logging = logging;\n }\n\n protected async initializeInternal(): Promise<void> {\n if (!globalThis.Worker) {\n throw new Error('No Worker support in this environment');\n }\n\n try {\n const allBundles = duckdb.getJsDelivrBundles();\n const bestBundle = await duckdb.selectBundle(allBundles);\n if (!bestBundle.mainWorker) {\n throw new Error('No best bundle found for DuckDB worker');\n }\n const workerUrl = URL.createObjectURL(\n new Blob([`importScripts(\"${bestBundle.mainWorker}\");`], {\n type: 'text/javascript',\n }),\n );\n\n const worker = new window.Worker(workerUrl);\n const logger = this.logging\n ? new duckdb.ConsoleLogger()\n : {\n // Silently log\n log: () => {\n /* do nothing */\n },\n };\n\n const db = new (class extends duckdb.AsyncDuckDB {\n onError(event: ErrorEvent) {\n super.onError(event);\n console.error('DuckDB worker error:', event);\n }\n })(logger, worker);\n\n await db.instantiate(bestBundle.mainModule, bestBundle.pthreadWorker);\n URL.revokeObjectURL(workerUrl);\n\n await db.open({\n path: this.dbPath,\n query: this.queryConfig,\n });\n\n const conn = augmentConnectionQueryError(await db.connect());\n if (this.initializationQuery) {\n await conn.query(this.initializationQuery);\n }\n\n this.db = db;\n this.conn = conn;\n this.worker = worker;\n this.initialized = true;\n } catch (err) {\n this.initialized = false;\n this.initializing = null;\n throw err;\n }\n }\n\n async destroy(): Promise<void> {\n try {\n if (this.conn) {\n await this.conn.close();\n this.conn = null;\n }\n\n if (this.db) {\n await this.db.terminate();\n this.db = null;\n }\n\n if (this.worker) {\n this.worker.terminate();\n this.worker = null;\n }\n\n this.initialized = false;\n this.initializing = null;\n } catch (err) {\n console.error('Error during DuckDB shutdown:', err);\n throw err;\n }\n }\n\n protected async executeQueryInternal<T extends arrow.TypeMap = any>(\n query: string,\n signal: AbortSignal,\n ): Promise<arrow.Table<T>> {\n // Make sure the WASM runtime is ready.\n await this.ensureInitialized();\n if (!this.db) {\n throw new Error('DuckDB not initialized');\n }\n\n // Short‑circuit if the caller already aborted.\n if (signal.aborted) {\n throw new Error('Query aborted before execution');\n }\n\n // 👉 Open a *fresh* connection dedicated to this request.\n const conn = augmentConnectionQueryError(await this.db.connect());\n\n // 1️⃣ Kick‑off the statement using the *cancellable* streaming API\n const streamPromise = conn.send<T>(query, /* allowStreamResult */ true);\n\n // Handle to the Arrow reader so we can cancel it later.\n let reader: arrow.RecordBatchReader<T> | null = null;\n\n // 2️⃣ Helper to materialise all batches into one Arrow Table.\n const buildTable = async () => {\n reader = await streamPromise;\n\n const batches: arrow.RecordBatch<T>[] = [];\n let rowCount = 0;\n\n for await (const batch of reader) {\n // DuckDB‑wasm may emit an empty placeholder batch when connections\n // race. Ignore any batch whose `numRows` is zero.\n if (batch.numRows === 0) continue;\n\n batches.push(batch);\n rowCount += batch.numRows;\n }\n\n if (rowCount === 0) {\n return arrow.tableFromArrays({}) as unknown as arrow.Table<T>;\n }\n return new arrow.Table(batches);\n };\n\n // 3️⃣ Wire the AbortSignal → DuckDB interrupt.\n let abortHandler: (() => void) | undefined;\n const abortPromise = new Promise<never>((_, reject) => {\n abortHandler = () => {\n // Interrupt DuckDB *and* stop the Arrow stream\n conn.cancelSent().catch(() => {\n /* ignore if nothing to cancel */\n });\n reader?.cancel?.();\n reject(new Error('Query cancelled'));\n };\n signal.addEventListener('abort', abortHandler);\n });\n\n try {\n // Whichever finishes first (query or cancel) wins.\n return await Promise.race([buildTable(), abortPromise]);\n } finally {\n if (abortHandler) {\n signal.removeEventListener('abort', abortHandler);\n }\n // Always close the per‑query connection.\n await conn.close();\n }\n }\n\n protected async cancelQueryInternal(queryId: string): Promise<void> {\n // First, invoke the base‑class logic (removes AbortController listeners, etc.)\n await super.cancelQueryInternal(queryId);\n\n // Then, interrupt the running statement on the DuckDB side.\n if (this.conn) {\n try {\n await this.conn.cancelSent();\n } catch (err) {\n // If no statement is active or interrupt fails, just log and move on.\n console.warn('DuckDB cancelSent failed:', err);\n }\n }\n }\n\n async loadFile(\n file: string | File,\n tableName: string,\n opts?: LoadFileOptions,\n ) {\n await this.withTempRegisteredFile(file, async (fileName) => {\n await super.loadFile(fileName, tableName, opts);\n });\n }\n\n async loadArrow(\n file: arrow.Table | Uint8Array,\n tableName: string,\n opts?: {schema?: string},\n ) {\n await this.ensureInitialized();\n if (!this.conn) {\n throw new Error('DuckDB connection not initialized');\n }\n const options = {name: tableName, schema: opts?.schema};\n if (file instanceof arrow.Table) {\n await this.conn.insertArrowTable(file, options);\n } else {\n await this.conn.insertArrowFromIPCStream(file, options);\n }\n }\n\n async loadObjects(\n file: Record<string, unknown>[],\n tableName: string,\n opts?: StandardLoadOptions,\n ) {\n await this.ensureInitialized();\n if (!this.conn) {\n throw new Error('DuckDB connection not initialized');\n }\n await this.conn.query(loadObjects(tableName, file, opts));\n }\n\n private async withTempRegisteredFile(\n file: string | File,\n action: (fileName: string) => Promise<void>,\n ) {\n await this.ensureInitialized();\n if (!this.conn || !this.db) {\n throw new Error('DuckDB connection not initialized');\n }\n let fileName: string;\n let tempFileName: string | undefined = undefined;\n if (file instanceof File) {\n // Extension might help DuckDB determine the file type\n const {ext} = splitFilePath(file.name);\n tempFileName = `${Math.random().toString(36).substring(2, 15)}${ext ? `.${ext}` : ''}`;\n fileName = tempFileName;\n await this.db.registerFileHandle(\n fileName,\n file,\n DuckDBDataProtocol.BROWSER_FILEREADER,\n true,\n );\n } else {\n fileName = file;\n }\n try {\n await action(fileName);\n } catch (err) {\n console.error(`Error during file loading \"${fileName}\":`, err);\n throw err;\n } finally {\n if (tempFileName) {\n await this.db.dropFile(tempFileName);\n }\n }\n }\n\n getDb(): duckdb.AsyncDuckDB {\n if (!this.db) {\n throw new Error('DuckDB not initialized');\n }\n return this.db;\n }\n\n getConnection(): duckdb.AsyncDuckDBConnection {\n if (!this.conn) {\n throw new Error('DuckDB connection not initialized');\n }\n return this.conn;\n }\n}\n\n/**\n * Augment the connection query method to include the full query and stack trace in the error.\n * @param conn - The connection to augment.\n * @returns The augmented connection.\n */\nfunction augmentConnectionQueryError(conn: duckdb.AsyncDuckDBConnection) {\n const originalQuery = conn.query;\n conn.query = (async (q: string) => {\n const stack = new Error().stack;\n try {\n return await originalQuery.call(conn, q);\n } catch (err) {\n throw new DuckQueryError(err, q, stack);\n }\n }) as typeof conn.query;\n return conn;\n}\n\nexport class DuckQueryError extends Error {\n readonly cause: unknown;\n readonly query: string | undefined;\n readonly queryCallStack: string | undefined;\n constructor(err: unknown, query: string, stack: string | undefined) {\n super(err instanceof Error ? err.message : `${err}`);\n this.cause = err;\n this.query = query;\n this.queryCallStack = stack;\n Object.setPrototypeOf(this, DuckQueryError.prototype);\n }\n getDetailedMessage() {\n const {message, query, queryCallStack: stack} = this;\n return (\n `DB query failed: ${message}` +\n `\\n\\nFull query:\\n\\n${query}\\n\\nQuery call stack:\\n\\n${stack}\\n\\n`\n );\n }\n getMessageForUser() {\n const {message} = this;\n return message;\n }\n}\n"]}
@@ -1,4 +1,24 @@
1
1
  import * as arrow from 'apache-arrow';
2
+ export type QualifiedTableName = {
3
+ database?: string;
4
+ schema?: string;
5
+ table: string;
6
+ toString: () => string;
7
+ };
8
+ export declare function isQualifiedTableName(tableName: string | QualifiedTableName): tableName is QualifiedTableName;
9
+ /**
10
+ * Get a qualified table name from a table name, schema, and database.
11
+ * @param table - The name of the table.
12
+ * @param schema - The schema of the table.
13
+ * @param database - The database of the table.
14
+ * @returns The qualified table name.
15
+ */
16
+ export declare function makeQualifiedTableName({ database, schema, table, }: QualifiedTableName): {
17
+ database: string | undefined;
18
+ schema: string | undefined;
19
+ table: string;
20
+ toString: () => string;
21
+ };
2
22
  /**
3
23
  * Escapes a value for use in DuckDB SQL queries by wrapping it in single quotes
4
24
  * and escaping any existing single quotes by doubling them.
@@ -44,4 +64,51 @@ export declare const isNumericDuckType: (type: string) => boolean;
44
64
  * const value = getColValAsNumber(table, "amount", 0)
45
65
  */
46
66
  export declare function getColValAsNumber(res: arrow.Table, column?: string | number, index?: number): number;
67
+ /**
68
+ * Function given a query and position finds the line and column of the console.error();
69
+ *
70
+ * @param query - The query to parse
71
+ * @param position - The position of the error
72
+ * @returns The line and column of the error
73
+ */
74
+ export declare const getSqlErrorWithPointer: (query: string, position: number) => {
75
+ line: number;
76
+ column: number;
77
+ lineText: string;
78
+ pointerLine: string;
79
+ formatted: string;
80
+ };
81
+ /**
82
+ * Split a string with potentially multiple SQL queries (separated as usual by ';')
83
+ * into an array of queries.
84
+ * This implementation:
85
+ * - Handles single and double quoted strings with proper escaping
86
+ * - Removes all comments: line comments (--) and block comments (/* ... *\/)
87
+ * - Ignores semicolons in quoted strings and comments
88
+ * - Trims whitespace from queries
89
+ * - Handles SQL-style escaped quotes ('' inside strings)
90
+ * - Returns only non-empty queries
91
+ *
92
+ * @param input - The SQL string containing one or more statements
93
+ * @returns An array of SQL statements with all comments removed
94
+ */
95
+ export declare function splitSqlStatements(input: string): string[];
96
+ /**
97
+ * Sanitizes a SQL query by removing trailing semicolons, comments, and normalizing whitespace
98
+ */
99
+ export declare function sanitizeQuery(query: string): string;
100
+ /**
101
+ * Make a limit query from a query and a limit.
102
+ * @param query - The SELECT query to make limited.
103
+ * @param options - The options for the limit query.
104
+ * @param options.limit - The number of rows to limit the query to.
105
+ * @param options.offset - The number of rows to offset the query by.
106
+ * @param options.sanitize - Whether to sanitize the query.
107
+ * @returns The limited query.
108
+ */
109
+ export declare function makeLimitQuery(query: string, { limit, offset, sanitize, }?: {
110
+ limit?: number;
111
+ offset?: number;
112
+ sanitize?: boolean;
113
+ }): string;
47
114
  //# sourceMappingURL=duckdb-utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"duckdb-utils.d.ts","sourceRoot":"","sources":["../src/duckdb-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC;;;;;;;;GAQG;AACH,eAAO,MAAM,SAAS,GAAI,KAAK,OAAO,WAErC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,QAAQ,GAAI,IAAI,MAAM,WAMlC,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,YAKjB,CAAC;AAE9B;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,KAAK,CAAC,KAAK,EAChB,MAAM,GAAE,MAAM,GAAG,MAAU,EAC3B,KAAK,SAAI,GACR,MAAM,CASR"}
1
+ {"version":3,"file":"duckdb-utils.d.ts","sourceRoot":"","sources":["../src/duckdb-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,MAAM,CAAC;CACxB,CAAC;AAEF,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,GAAG,kBAAkB,GACrC,SAAS,IAAI,kBAAkB,CAEjC;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,MAAM,EACN,KAAK,GACN,EAAE,kBAAkB;;;;;EAWpB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,SAAS,GAAI,KAAK,OAAO,WAErC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,QAAQ,GAAI,IAAI,MAAM,WAMlC,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,YAKjB,CAAC;AAE9B;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,KAAK,CAAC,KAAK,EAChB,MAAM,GAAE,MAAM,GAAG,MAAU,EAC3B,KAAK,SAAI,GACR,MAAM,CASR;AAED;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,GAAI,OAAO,MAAM,EAAE,UAAU,MAAM;;;;;;CAsBrE,CAAC;AAoBF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAqG1D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOnD;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,EACE,KAAW,EACX,MAAU,EACV,QAAe,GAChB,GAAE;IACD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACf,UAKP"}
@@ -1,3 +1,25 @@
1
+ export function isQualifiedTableName(tableName) {
2
+ return typeof tableName === 'object' && 'toString' in tableName;
3
+ }
4
+ /**
5
+ * Get a qualified table name from a table name, schema, and database.
6
+ * @param table - The name of the table.
7
+ * @param schema - The schema of the table.
8
+ * @param database - The database of the table.
9
+ * @returns The qualified table name.
10
+ */
11
+ export function makeQualifiedTableName({ database, schema, table, }) {
12
+ const qualifiedTableName = [database, schema, table]
13
+ .filter((id) => id !== undefined && id !== null)
14
+ .map((id) => escapeId(id))
15
+ .join('.');
16
+ return {
17
+ database,
18
+ schema,
19
+ table,
20
+ toString: () => qualifiedTableName,
21
+ };
22
+ }
1
23
  /**
2
24
  * Escapes a value for use in DuckDB SQL queries by wrapping it in single quotes
3
25
  * and escaping any existing single quotes by doubling them.
@@ -62,4 +84,177 @@ export function getColValAsNumber(res, column = 0, index = 0) {
62
84
  // if it's an array (can be returned by duckdb as bigint)
63
85
  return Number(v[0] ?? v);
64
86
  }
87
+ /**
88
+ * Function given a query and position finds the line and column of the console.error();
89
+ *
90
+ * @param query - The query to parse
91
+ * @param position - The position of the error
92
+ * @returns The line and column of the error
93
+ */
94
+ export const getSqlErrorWithPointer = (query, position) => {
95
+ // Clamp position to be within the string bounds
96
+ const safePos = Math.max(0, Math.min(position, query.length));
97
+ // Get the substring up to the error position
98
+ const upToPos = query.slice(0, safePos);
99
+ // Split by newlines
100
+ const lines = upToPos.split('\n');
101
+ const line = lines.length; // 1-based
102
+ // Defensive: lines[lines.length - 1] is always defined, but add fallback for linter
103
+ const lastLine = lines[lines.length - 1] ?? '';
104
+ const column = lastLine.length + 1; // 1-based
105
+ // Get the full line text from the original query
106
+ const queryLines = query.split('\n');
107
+ const lineText = queryLines[line - 1] ?? '';
108
+ // Pointer line: spaces up to column-1, then ^
109
+ const pointerLine = ' '.repeat(Math.max(0, column - 1)) + '^';
110
+ // Formatted output as requested
111
+ const formatted = `LINE ${line}: ${lineText}\n${' '.repeat(`LINE ${line}: `.length)}${pointerLine}`;
112
+ return { line, column, lineText, pointerLine, formatted };
113
+ };
114
+ //
115
+ // const queries = splitSqlStatements(`
116
+ // SELECT * FROM users WHERE name = 'John;Doe';
117
+ // SELECT * FROM orders -- This comment; won't break;
118
+ // /*
119
+ // Multi-line comment;
120
+ // With semicolons;
121
+ // */
122
+ // SELECT "Quoted;identifier" FROM table;
123
+ //`);
124
+ // Returns:
125
+ // [
126
+ // "SELECT * FROM users WHERE name = 'John;Doe'",
127
+ // "SELECT * FROM orders -- This comment; won't break",
128
+ // "SELECT \"Quoted;identifier\" FROM table"
129
+ // ]
130
+ /**
131
+ * Split a string with potentially multiple SQL queries (separated as usual by ';')
132
+ * into an array of queries.
133
+ * This implementation:
134
+ * - Handles single and double quoted strings with proper escaping
135
+ * - Removes all comments: line comments (--) and block comments (/* ... *\/)
136
+ * - Ignores semicolons in quoted strings and comments
137
+ * - Trims whitespace from queries
138
+ * - Handles SQL-style escaped quotes ('' inside strings)
139
+ * - Returns only non-empty queries
140
+ *
141
+ * @param input - The SQL string containing one or more statements
142
+ * @returns An array of SQL statements with all comments removed
143
+ */
144
+ export function splitSqlStatements(input) {
145
+ const queries = [];
146
+ let currentQuery = '';
147
+ let inSingleQuote = false;
148
+ let inDoubleQuote = false;
149
+ let inLineComment = false;
150
+ let inBlockComment = false;
151
+ for (let i = 0; i < input.length; i++) {
152
+ const char = input[i];
153
+ if (inLineComment) {
154
+ if (char === '\n') {
155
+ inLineComment = false;
156
+ currentQuery += char; // preserve newlines for line numbers
157
+ }
158
+ // else: skip comment chars
159
+ continue;
160
+ }
161
+ if (inBlockComment) {
162
+ if (char === '*' && input[i + 1] === '/') {
163
+ inBlockComment = false;
164
+ i++; // skip '/'
165
+ }
166
+ // else: skip comment chars
167
+ continue;
168
+ }
169
+ if (inSingleQuote) {
170
+ currentQuery += char;
171
+ if (char === "'") {
172
+ // Handle escaped single quotes in SQL
173
+ if (i + 1 < input.length && input[i + 1] === "'") {
174
+ currentQuery += input[++i];
175
+ }
176
+ else {
177
+ inSingleQuote = false;
178
+ }
179
+ }
180
+ continue;
181
+ }
182
+ if (inDoubleQuote) {
183
+ currentQuery += char;
184
+ if (char === '"') {
185
+ // Handle escaped double quotes
186
+ if (i + 1 < input.length && input[i + 1] === '"') {
187
+ currentQuery += input[++i];
188
+ }
189
+ else {
190
+ inDoubleQuote = false;
191
+ }
192
+ }
193
+ continue;
194
+ }
195
+ // Check for comment starts
196
+ if (char === '-' && input[i + 1] === '-') {
197
+ inLineComment = true;
198
+ i++; // skip next '-'
199
+ continue;
200
+ }
201
+ if (char === '/' && input[i + 1] === '*') {
202
+ inBlockComment = true;
203
+ i++; // skip next '*'
204
+ continue;
205
+ }
206
+ // Check for quote starts
207
+ if (char === "'") {
208
+ inSingleQuote = true;
209
+ currentQuery += char;
210
+ continue;
211
+ }
212
+ if (char === '"') {
213
+ inDoubleQuote = true;
214
+ currentQuery += char;
215
+ continue;
216
+ }
217
+ // Handle query separator
218
+ if (char === ';') {
219
+ const trimmed = currentQuery.trim();
220
+ if (trimmed.length > 0) {
221
+ queries.push(trimmed);
222
+ }
223
+ currentQuery = '';
224
+ continue;
225
+ }
226
+ currentQuery += char;
227
+ }
228
+ // Add the final query
229
+ const trimmed = currentQuery.trim();
230
+ if (trimmed.length > 0) {
231
+ queries.push(trimmed);
232
+ }
233
+ return queries;
234
+ }
235
+ /**
236
+ * Sanitizes a SQL query by removing trailing semicolons, comments, and normalizing whitespace
237
+ */
238
+ export function sanitizeQuery(query) {
239
+ return query
240
+ .trim() // Remove leading/trailing whitespace
241
+ .replace(/;+$/, '') // Remove all trailing semicolons
242
+ .replace(/--.*$/gm, '') // Remove single-line comments
243
+ .replace(/\/\*[\s\S]*?\*\//g, '') // Remove multi-line comments
244
+ .replace(/\s+/g, ' '); // Normalize whitespace to single spaces
245
+ }
246
+ /**
247
+ * Make a limit query from a query and a limit.
248
+ * @param query - The SELECT query to make limited.
249
+ * @param options - The options for the limit query.
250
+ * @param options.limit - The number of rows to limit the query to.
251
+ * @param options.offset - The number of rows to offset the query by.
252
+ * @param options.sanitize - Whether to sanitize the query.
253
+ * @returns The limited query.
254
+ */
255
+ export function makeLimitQuery(query, { limit = 100, offset = 0, sanitize = true, } = {}) {
256
+ return `SELECT * FROM (
257
+ ${sanitize ? sanitizeQuery(query) : query}
258
+ ) LIMIT ${limit} OFFSET ${offset}`;
259
+ }
65
260
  //# sourceMappingURL=duckdb-utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"duckdb-utils.js","sourceRoot":"","sources":["../src/duckdb-utils.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAY,EAAE,EAAE;IACxC,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;AAChD,CAAC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,EAAU,EAAE,EAAE;IACrC,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;IACvB,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7C,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;AACxC,CAAC,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,IAAY,EAAE,EAAE,CAChD,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC;IACxB,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC;IAC5B,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;IAC1B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;IACzB,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAE9B;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iBAAiB,CAC/B,GAAgB,EAChB,SAA0B,CAAC,EAC3B,KAAK,GAAG,CAAC;IAET,MAAM,CAAC,GAAG,CACR,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAC3E,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;IACd,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QAClC,OAAO,GAAG,CAAC;IACb,CAAC;IACD,yDAAyD;IACzD,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3B,CAAC","sourcesContent":["import * as arrow from 'apache-arrow';\n\n/**\n * Escapes a value for use in DuckDB SQL queries by wrapping it in single quotes\n * and escaping any existing single quotes by doubling them.\n *\n * @param val - The value to escape. Will be converted to string if not already a string.\n * @returns The escaped string value wrapped in single quotes.\n * @example\n * escapeVal(\"John's data\") // Returns \"'John''s data'\"\n */\nexport const escapeVal = (val: unknown) => {\n return `'${String(val).replace(/'/g, \"''\")}'`;\n};\n\n/**\n * Escapes an identifier (like table or column names) for use in DuckDB SQL queries\n * by wrapping it in double quotes and escaping any existing double quotes by doubling them.\n * If the identifier is already properly quoted, returns it as is.\n *\n * @param id - The identifier string to escape\n * @returns The escaped identifier wrapped in double quotes\n * @example\n * escapeId(\"my_table\") // Returns '\"my_table\"'\n * escapeId(\"my\"\"table\") // Returns '\"my\"\"\"\"table\"'\n */\nexport const escapeId = (id: string) => {\n const str = String(id);\n if (str.startsWith('\"') && str.endsWith('\"')) {\n return str;\n }\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n};\n\n/**\n * Checks if a DuckDB type string represents a numeric type.\n * Includes INTEGER, DECIMAL, FLOAT, REAL, and DOUBLE types.\n *\n * @param type - The DuckDB type string to check\n * @returns True if the type is numeric, false otherwise\n * @example\n * isNumericDuckType('INTEGER') // Returns true\n * isNumericDuckType('VARCHAR') // Returns false\n */\nexport const isNumericDuckType = (type: string) =>\n type.indexOf('INT') >= 0 ||\n type.indexOf('DECIMAL') >= 0 ||\n type.indexOf('FLOAT') >= 0 ||\n type.indexOf('REAL') >= 0 ||\n type.indexOf('DOUBLE') >= 0;\n\n/**\n * Extracts a numeric value from an Arrow Table at the specified column and row index.\n * Handles both column name and index-based access. Converts BigInt values to numbers.\n *\n * @param res - The Arrow Table containing the data\n * @param column - The column name or index (0-based) to read from. Defaults to first column (0)\n * @param index - The row index (0-based) to read from. Defaults to first row (0)\n * @returns The numeric value at the specified position, or NaN if the value is null/undefined\n * @example\n * const value = getColValAsNumber(table, \"amount\", 0)\n */\nexport function getColValAsNumber(\n res: arrow.Table,\n column: string | number = 0,\n index = 0,\n): number {\n const v = (\n typeof column === 'number' ? res.getChildAt(column) : res.getChild(column)\n )?.get(index);\n if (v === undefined || v === null) {\n return NaN;\n }\n // if it's an array (can be returned by duckdb as bigint)\n return Number(v[0] ?? v);\n}\n"]}
1
+ {"version":3,"file":"duckdb-utils.js","sourceRoot":"","sources":["../src/duckdb-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import * as arrow from 'apache-arrow';\n\nexport type QualifiedTableName = {\n database?: string;\n schema?: string;\n table: string;\n toString: () => string;\n};\n\nexport function isQualifiedTableName(\n tableName: string | QualifiedTableName,\n): tableName is QualifiedTableName {\n return typeof tableName === 'object' && 'toString' in tableName;\n}\n\n/**\n * Get a qualified table name from a table name, schema, and database.\n * @param table - The name of the table.\n * @param schema - The schema of the table.\n * @param database - The database of the table.\n * @returns The qualified table name.\n */\nexport function makeQualifiedTableName({\n database,\n schema,\n table,\n}: QualifiedTableName) {\n const qualifiedTableName = [database, schema, table]\n .filter((id) => id !== undefined && id !== null)\n .map((id) => escapeId(id))\n .join('.');\n return {\n database,\n schema,\n table,\n toString: () => qualifiedTableName,\n };\n}\n\n/**\n * Escapes a value for use in DuckDB SQL queries by wrapping it in single quotes\n * and escaping any existing single quotes by doubling them.\n *\n * @param val - The value to escape. Will be converted to string if not already a string.\n * @returns The escaped string value wrapped in single quotes.\n * @example\n * escapeVal(\"John's data\") // Returns \"'John''s data'\"\n */\nexport const escapeVal = (val: unknown) => {\n return `'${String(val).replace(/'/g, \"''\")}'`;\n};\n\n/**\n * Escapes an identifier (like table or column names) for use in DuckDB SQL queries\n * by wrapping it in double quotes and escaping any existing double quotes by doubling them.\n * If the identifier is already properly quoted, returns it as is.\n *\n * @param id - The identifier string to escape\n * @returns The escaped identifier wrapped in double quotes\n * @example\n * escapeId(\"my_table\") // Returns '\"my_table\"'\n * escapeId(\"my\"\"table\") // Returns '\"my\"\"\"\"table\"'\n */\nexport const escapeId = (id: string) => {\n const str = String(id);\n if (str.startsWith('\"') && str.endsWith('\"')) {\n return str;\n }\n return `\"${str.replace(/\"/g, '\"\"')}\"`;\n};\n\n/**\n * Checks if a DuckDB type string represents a numeric type.\n * Includes INTEGER, DECIMAL, FLOAT, REAL, and DOUBLE types.\n *\n * @param type - The DuckDB type string to check\n * @returns True if the type is numeric, false otherwise\n * @example\n * isNumericDuckType('INTEGER') // Returns true\n * isNumericDuckType('VARCHAR') // Returns false\n */\nexport const isNumericDuckType = (type: string) =>\n type.indexOf('INT') >= 0 ||\n type.indexOf('DECIMAL') >= 0 ||\n type.indexOf('FLOAT') >= 0 ||\n type.indexOf('REAL') >= 0 ||\n type.indexOf('DOUBLE') >= 0;\n\n/**\n * Extracts a numeric value from an Arrow Table at the specified column and row index.\n * Handles both column name and index-based access. Converts BigInt values to numbers.\n *\n * @param res - The Arrow Table containing the data\n * @param column - The column name or index (0-based) to read from. Defaults to first column (0)\n * @param index - The row index (0-based) to read from. Defaults to first row (0)\n * @returns The numeric value at the specified position, or NaN if the value is null/undefined\n * @example\n * const value = getColValAsNumber(table, \"amount\", 0)\n */\nexport function getColValAsNumber(\n res: arrow.Table,\n column: string | number = 0,\n index = 0,\n): number {\n const v = (\n typeof column === 'number' ? res.getChildAt(column) : res.getChild(column)\n )?.get(index);\n if (v === undefined || v === null) {\n return NaN;\n }\n // if it's an array (can be returned by duckdb as bigint)\n return Number(v[0] ?? v);\n}\n\n/**\n * Function given a query and position finds the line and column of the console.error();\n *\n * @param query - The query to parse\n * @param position - The position of the error\n * @returns The line and column of the error\n */\nexport const getSqlErrorWithPointer = (query: string, position: number) => {\n // Clamp position to be within the string bounds\n const safePos = Math.max(0, Math.min(position, query.length));\n // Get the substring up to the error position\n const upToPos = query.slice(0, safePos);\n // Split by newlines\n const lines = upToPos.split('\\n');\n const line = lines.length; // 1-based\n // Defensive: lines[lines.length - 1] is always defined, but add fallback for linter\n const lastLine = lines[lines.length - 1] ?? '';\n const column = lastLine.length + 1; // 1-based\n\n // Get the full line text from the original query\n const queryLines = query.split('\\n');\n const lineText = queryLines[line - 1] ?? '';\n // Pointer line: spaces up to column-1, then ^\n const pointerLine = ' '.repeat(Math.max(0, column - 1)) + '^';\n\n // Formatted output as requested\n const formatted = `LINE ${line}: ${lineText}\\n${' '.repeat(`LINE ${line}: `.length)}${pointerLine}`;\n\n return {line, column, lineText, pointerLine, formatted};\n};\n\n//\n// const queries = splitSqlStatements(`\n// SELECT * FROM users WHERE name = 'John;Doe';\n// SELECT * FROM orders -- This comment; won't break;\n// /*\n// Multi-line comment;\n// With semicolons;\n// */\n// SELECT \"Quoted;identifier\" FROM table;\n//`);\n\n// Returns:\n// [\n// \"SELECT * FROM users WHERE name = 'John;Doe'\",\n// \"SELECT * FROM orders -- This comment; won't break\",\n// \"SELECT \\\"Quoted;identifier\\\" FROM table\"\n// ]\n\n/**\n * Split a string with potentially multiple SQL queries (separated as usual by ';')\n * into an array of queries.\n * This implementation:\n * - Handles single and double quoted strings with proper escaping\n * - Removes all comments: line comments (--) and block comments (/* ... *\\/)\n * - Ignores semicolons in quoted strings and comments\n * - Trims whitespace from queries\n * - Handles SQL-style escaped quotes ('' inside strings)\n * - Returns only non-empty queries\n *\n * @param input - The SQL string containing one or more statements\n * @returns An array of SQL statements with all comments removed\n */\nexport function splitSqlStatements(input: string): string[] {\n const queries: string[] = [];\n let currentQuery = '';\n let inSingleQuote = false;\n let inDoubleQuote = false;\n let inLineComment = false;\n let inBlockComment = false;\n\n for (let i = 0; i < input.length; i++) {\n const char = input[i];\n\n if (inLineComment) {\n if (char === '\\n') {\n inLineComment = false;\n currentQuery += char; // preserve newlines for line numbers\n }\n // else: skip comment chars\n continue;\n }\n\n if (inBlockComment) {\n if (char === '*' && input[i + 1] === '/') {\n inBlockComment = false;\n i++; // skip '/'\n }\n // else: skip comment chars\n continue;\n }\n\n if (inSingleQuote) {\n currentQuery += char;\n if (char === \"'\") {\n // Handle escaped single quotes in SQL\n if (i + 1 < input.length && input[i + 1] === \"'\") {\n currentQuery += input[++i];\n } else {\n inSingleQuote = false;\n }\n }\n continue;\n }\n\n if (inDoubleQuote) {\n currentQuery += char;\n if (char === '\"') {\n // Handle escaped double quotes\n if (i + 1 < input.length && input[i + 1] === '\"') {\n currentQuery += input[++i];\n } else {\n inDoubleQuote = false;\n }\n }\n continue;\n }\n\n // Check for comment starts\n if (char === '-' && input[i + 1] === '-') {\n inLineComment = true;\n i++; // skip next '-'\n continue;\n }\n\n if (char === '/' && input[i + 1] === '*') {\n inBlockComment = true;\n i++; // skip next '*'\n continue;\n }\n\n // Check for quote starts\n if (char === \"'\") {\n inSingleQuote = true;\n currentQuery += char;\n continue;\n }\n\n if (char === '\"') {\n inDoubleQuote = true;\n currentQuery += char;\n continue;\n }\n\n // Handle query separator\n if (char === ';') {\n const trimmed = currentQuery.trim();\n if (trimmed.length > 0) {\n queries.push(trimmed);\n }\n currentQuery = '';\n continue;\n }\n\n currentQuery += char;\n }\n\n // Add the final query\n const trimmed = currentQuery.trim();\n if (trimmed.length > 0) {\n queries.push(trimmed);\n }\n\n return queries;\n}\n\n/**\n * Sanitizes a SQL query by removing trailing semicolons, comments, and normalizing whitespace\n */\nexport function sanitizeQuery(query: string): string {\n return query\n .trim() // Remove leading/trailing whitespace\n .replace(/;+$/, '') // Remove all trailing semicolons\n .replace(/--.*$/gm, '') // Remove single-line comments\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '') // Remove multi-line comments\n .replace(/\\s+/g, ' '); // Normalize whitespace to single spaces\n}\n\n/**\n * Make a limit query from a query and a limit.\n * @param query - The SELECT query to make limited.\n * @param options - The options for the limit query.\n * @param options.limit - The number of rows to limit the query to.\n * @param options.offset - The number of rows to offset the query by.\n * @param options.sanitize - Whether to sanitize the query.\n * @returns The limited query.\n */\nexport function makeLimitQuery(\n query: string,\n {\n limit = 100,\n offset = 0,\n sanitize = true,\n }: {\n limit?: number;\n offset?: number;\n sanitize?: boolean;\n } = {},\n) {\n return `SELECT * FROM (\n ${sanitize ? sanitizeQuery(query) : query}\n ) LIMIT ${limit} OFFSET ${offset}`;\n}\n"]}
@@ -11,7 +11,7 @@ export function useExportToCsv() {
11
11
  const currentQuery = `(
12
12
  ${query}
13
13
  ) LIMIT ${pageSize} OFFSET ${offset}`;
14
- const results = await dbConnector.query(currentQuery);
14
+ const results = await dbConnector.query(currentQuery).result;
15
15
  // Check if we received any results; if not, we are done.
16
16
  if (results.numRows === 0) {
17
17
  break;
@@ -1 +1 @@
1
- {"version":3,"file":"exportToCsv.js","sourceRoot":"","sources":["../src/exportToCsv.ts"],"names":[],"mappings":"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","sourcesContent":["import * as arrow from 'apache-arrow';\nimport {useStoreWithDuckDb} from './DuckDbSlice';\n\nexport function useExportToCsv() {\n const getConnector = useStoreWithDuckDb((state) => state.db.getConnector);\n return {\n exportToCsv: async (query: string, fileName: string, pageSize = 100000) => {\n const dbConnector = await getConnector();\n\n let offset = 0;\n const blobs: Blob[] = [];\n let headersAdded = false;\n\n while (true) {\n const currentQuery = `(\n ${query}\n ) LIMIT ${pageSize} OFFSET ${offset}`;\n const results = await dbConnector.query(currentQuery);\n\n // Check if we received any results; if not, we are done.\n if (results.numRows === 0) {\n break;\n }\n\n const csvChunk = convertToCsv(results, !headersAdded);\n blobs.push(new Blob([csvChunk], {type: 'text/csv'}));\n\n // Ensure that headers are not added in subsequent iterations\n headersAdded = true;\n\n // Increment offset to fetch the next chunk\n offset += pageSize;\n }\n\n const fullCsvBlob = new Blob(blobs, {type: 'text/csv'});\n downloadBlob(fullCsvBlob, fileName);\n },\n };\n}\n\nfunction convertToCsv(\n arrowTable: arrow.Table,\n includeHeaders: boolean,\n): string {\n // return includeHeaders\n // ? csvFormat(arrowTable.toArray())\n // : csvFormatBody(arrowTable.toArray());\n\n const columnNames = arrowTable.schema.fields.map((field) => field.name);\n const columnsByName = columnNames.reduce(\n (acc, columnName) => {\n const col = arrowTable.getChild(columnName);\n if (col) acc[columnName] = col;\n return acc;\n },\n {} as Record<string, arrow.Vector>,\n );\n\n // Add header\n let csvContent = includeHeaders ? columnNames.join(',') + '\\r\\n' : '';\n\n // Add data rows\n for (let i = 0; i < arrowTable.numRows; i++) {\n const csvRow = columnNames\n .map((columnName) => {\n const cellValue = columnsByName[columnName]?.get(i);\n\n // If the cell value is null or undefined, set it to an empty string.\n if (cellValue == null) return '';\n\n // Convert cell value to string\n let cellValueStr = String(cellValue);\n\n // Escape double quotes and wrap cell value in double quotes if necessary\n if (\n cellValueStr.includes('\"') ||\n cellValueStr.includes(',') ||\n cellValueStr.includes('\\n')\n ) {\n cellValueStr = '\"' + cellValueStr.replace(/\"/g, '\"\"') + '\"';\n }\n\n return cellValueStr;\n })\n .join(',');\n\n csvContent += csvRow + '\\r\\n';\n }\n\n return csvContent;\n}\n\nfunction downloadBlob(blob: Blob, filename: string) {\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = filename;\n document.body.appendChild(a);\n a.click();\n URL.revokeObjectURL(url);\n document.body.removeChild(a);\n}\n"]}
1
+ {"version":3,"file":"exportToCsv.js","sourceRoot":"","sources":["../src/exportToCsv.ts"],"names":[],"mappings":"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","sourcesContent":["import * as arrow from 'apache-arrow';\nimport {useStoreWithDuckDb} from './DuckDbSlice';\n\nexport function useExportToCsv() {\n const getConnector = useStoreWithDuckDb((state) => state.db.getConnector);\n return {\n exportToCsv: async (query: string, fileName: string, pageSize = 100000) => {\n const dbConnector = await getConnector();\n\n let offset = 0;\n const blobs: Blob[] = [];\n let headersAdded = false;\n\n while (true) {\n const currentQuery = `(\n ${query}\n ) LIMIT ${pageSize} OFFSET ${offset}`;\n const results = await dbConnector.query(currentQuery).result;\n\n // Check if we received any results; if not, we are done.\n if (results.numRows === 0) {\n break;\n }\n\n const csvChunk = convertToCsv(results, !headersAdded);\n blobs.push(new Blob([csvChunk], {type: 'text/csv'}));\n\n // Ensure that headers are not added in subsequent iterations\n headersAdded = true;\n\n // Increment offset to fetch the next chunk\n offset += pageSize;\n }\n\n const fullCsvBlob = new Blob(blobs, {type: 'text/csv'});\n downloadBlob(fullCsvBlob, fileName);\n },\n };\n}\n\nfunction convertToCsv(\n arrowTable: arrow.Table,\n includeHeaders: boolean,\n): string {\n // return includeHeaders\n // ? csvFormat(arrowTable.toArray())\n // : csvFormatBody(arrowTable.toArray());\n\n const columnNames = arrowTable.schema.fields.map((field) => field.name);\n const columnsByName = columnNames.reduce(\n (acc, columnName) => {\n const col = arrowTable.getChild(columnName);\n if (col) acc[columnName] = col;\n return acc;\n },\n {} as Record<string, arrow.Vector>,\n );\n\n // Add header\n let csvContent = includeHeaders ? columnNames.join(',') + '\\r\\n' : '';\n\n // Add data rows\n for (let i = 0; i < arrowTable.numRows; i++) {\n const csvRow = columnNames\n .map((columnName) => {\n const cellValue = columnsByName[columnName]?.get(i);\n\n // If the cell value is null or undefined, set it to an empty string.\n if (cellValue == null) return '';\n\n // Convert cell value to string\n let cellValueStr = String(cellValue);\n\n // Escape double quotes and wrap cell value in double quotes if necessary\n if (\n cellValueStr.includes('\"') ||\n cellValueStr.includes(',') ||\n cellValueStr.includes('\\n')\n ) {\n cellValueStr = '\"' + cellValueStr.replace(/\"/g, '\"\"') + '\"';\n }\n\n return cellValueStr;\n })\n .join(',');\n\n csvContent += csvRow + '\\r\\n';\n }\n\n return csvContent;\n}\n\nfunction downloadBlob(blob: Blob, filename: string) {\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = filename;\n document.body.appendChild(a);\n a.click();\n URL.revokeObjectURL(url);\n document.body.removeChild(a);\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -5,9 +5,10 @@
5
5
  export * from './types';
6
6
  export * from './useDuckDb';
7
7
  export * from './exportToCsv';
8
- export * from './arrow-utils';
8
+ export { arrowTableToJson } from './arrow-utils';
9
+ export { getDuckDbTypeCategory, getArrowColumnTypeCategory, } from './typeCategories';
9
10
  export * from './useSql';
10
- export { createDuckDbSlice, createDefaultDuckDbConfig, DuckDbSliceConfig, type DuckDbSliceState, } from './DuckDbSlice';
11
+ export { createDuckDbSlice, createDefaultDuckDbConfig, DuckDbSliceConfig, type DuckDbSliceState, useStoreWithDuckDb, } from './DuckDbSlice';
11
12
  export * from './connectors/DuckDbConnector';
12
13
  export * from './connectors/BaseDuckDbConnector';
13
14
  export * from './connectors/WasmDuckDbConnector';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,iBAAiB,EACjB,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAC;AACvB,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AACjD,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,KAAK,gBAAgB,EACrB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAC,gBAAgB,EAAC,MAAM,eAAe,CAAC;AAC/C,OAAO,EACL,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,kBAAkB,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AACjD,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,KAAK,gBAAgB,EACrB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -5,9 +5,10 @@
5
5
  export * from './types';
6
6
  export * from './useDuckDb';
7
7
  export * from './exportToCsv';
8
- export * from './arrow-utils';
8
+ export { arrowTableToJson } from './arrow-utils';
9
+ export { getDuckDbTypeCategory, getArrowColumnTypeCategory, } from './typeCategories';
9
10
  export * from './useSql';
10
- export { createDuckDbSlice, createDefaultDuckDbConfig, DuckDbSliceConfig, } from './DuckDbSlice';
11
+ export { createDuckDbSlice, createDefaultDuckDbConfig, DuckDbSliceConfig, useStoreWithDuckDb, } from './DuckDbSlice';
11
12
  export * from './connectors/DuckDbConnector';
12
13
  export * from './connectors/BaseDuckDbConnector';
13
14
  export * from './connectors/WasmDuckDbConnector';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC;AACzB,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,iBAAiB,GAElB,MAAM,eAAe,CAAC;AACvB,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AACjD,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAEL,sBAAsB,GACvB,MAAM,oBAAoB,CAAC","sourcesContent":["/**\n * {@include ../README.md}\n * @packageDocumentation\n */\n\nexport * from './types';\nexport * from './useDuckDb';\nexport * from './exportToCsv';\nexport * from './arrow-utils';\nexport * from './useSql';\nexport {\n createDuckDbSlice,\n createDefaultDuckDbConfig,\n DuckDbSliceConfig,\n type DuckDbSliceState,\n} from './DuckDbSlice';\nexport * from './connectors/DuckDbConnector';\nexport * from './connectors/BaseDuckDbConnector';\nexport * from './connectors/WasmDuckDbConnector';\nexport * from './connectors/load/load';\nexport * from './duckdb-utils';\nexport {\n LoadFileOptions,\n SpatialLoadFileOptions,\n isSpatialLoadFileOptions,\n} from '@sqlrooms/project-config';\nexport {\n type TypedRowAccessor,\n createTypedRowAccessor,\n} from './typedRowAccessor';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAC,gBAAgB,EAAC,MAAM,eAAe,CAAC;AAC/C,OAAO,EACL,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,kBAAkB,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,iBAAiB,EAEjB,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AACjD,cAAc,wBAAwB,CAAC;AACvC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAEL,sBAAsB,GACvB,MAAM,oBAAoB,CAAC","sourcesContent":["/**\n * {@include ../README.md}\n * @packageDocumentation\n */\n\nexport * from './types';\nexport * from './useDuckDb';\nexport * from './exportToCsv';\nexport {arrowTableToJson} from './arrow-utils';\nexport {\n getDuckDbTypeCategory,\n getArrowColumnTypeCategory,\n} from './typeCategories';\nexport * from './useSql';\nexport {\n createDuckDbSlice,\n createDefaultDuckDbConfig,\n DuckDbSliceConfig,\n type DuckDbSliceState,\n useStoreWithDuckDb,\n} from './DuckDbSlice';\nexport * from './connectors/DuckDbConnector';\nexport * from './connectors/BaseDuckDbConnector';\nexport * from './connectors/WasmDuckDbConnector';\nexport * from './connectors/load/load';\nexport * from './duckdb-utils';\nexport {\n LoadFileOptions,\n SpatialLoadFileOptions,\n isSpatialLoadFileOptions,\n} from '@sqlrooms/project-config';\nexport {\n type TypedRowAccessor,\n createTypedRowAccessor,\n} from './typedRowAccessor';\n"]}