@sqlrooms/duckdb 0.16.3 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +206 -47
- package/dist/DuckDbSlice.d.ts +4 -4
- package/dist/DuckDbSlice.d.ts.map +1 -1
- package/dist/DuckDbSlice.js +6 -5
- package/dist/DuckDbSlice.js.map +1 -1
- package/dist/connectors/BaseDuckDbConnector.d.ts +15 -38
- package/dist/connectors/BaseDuckDbConnector.d.ts.map +1 -1
- package/dist/connectors/BaseDuckDbConnector.js +87 -88
- package/dist/connectors/BaseDuckDbConnector.js.map +1 -1
- package/dist/connectors/DuckDbConnector.d.ts +5 -2
- package/dist/connectors/DuckDbConnector.d.ts.map +1 -1
- package/dist/connectors/DuckDbConnector.js.map +1 -1
- package/dist/connectors/WasmDuckDbConnector.d.ts +10 -25
- package/dist/connectors/WasmDuckDbConnector.d.ts.map +1 -1
- package/dist/connectors/WasmDuckDbConnector.js +160 -199
- package/dist/connectors/WasmDuckDbConnector.js.map +1 -1
- package/dist/connectors/createDuckDbConnector.d.ts +11 -0
- package/dist/connectors/createDuckDbConnector.d.ts.map +1 -0
- package/dist/connectors/createDuckDbConnector.js +15 -0
- package/dist/connectors/createDuckDbConnector.js.map +1 -0
- package/dist/connectors/load/load.d.ts +1 -1
- package/dist/connectors/load/load.d.ts.map +1 -1
- package/dist/connectors/load/load.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/typedRowAccessor.d.ts +1 -1
- package/dist/typedRowAccessor.d.ts.map +1 -1
- package/dist/typedRowAccessor.js.map +1 -1
- package/package.json +4 -5
|
@@ -1,117 +1,116 @@
|
|
|
1
|
-
import { isSpatialLoadFileOptions, } from '@sqlrooms/
|
|
2
|
-
import { load, loadObjects, loadSpatial } from './load/load';
|
|
1
|
+
import { isSpatialLoadFileOptions, } from '@sqlrooms/room-config';
|
|
2
|
+
import { load, loadObjects as loadObjectsSql, loadSpatial } from './load/load';
|
|
3
3
|
import { createTypedRowAccessor } from '../typedRowAccessor';
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (this.initialized) {
|
|
16
|
-
return;
|
|
4
|
+
export function createBaseDuckDbConnector({ dbPath = ':memory:', initializationQuery = '', } = {}, impl) {
|
|
5
|
+
const state = {
|
|
6
|
+
dbPath,
|
|
7
|
+
initializationQuery,
|
|
8
|
+
initialized: false,
|
|
9
|
+
initializing: null,
|
|
10
|
+
activeQueries: new Map(),
|
|
11
|
+
};
|
|
12
|
+
const ensureInitialized = async () => {
|
|
13
|
+
if (!state.initialized && state.initializing) {
|
|
14
|
+
await state.initializing;
|
|
17
15
|
}
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
};
|
|
17
|
+
const initialize = async () => {
|
|
18
|
+
if (state.initialized) {
|
|
19
|
+
return;
|
|
20
20
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
async initializeInternal() {
|
|
25
|
-
// To be implemented by subclasses
|
|
26
|
-
}
|
|
27
|
-
async destroy() {
|
|
28
|
-
// To be implemented by subclasses
|
|
29
|
-
}
|
|
30
|
-
async ensureInitialized() {
|
|
31
|
-
if (!this.initialized && this.initializing) {
|
|
32
|
-
await this.initializing;
|
|
21
|
+
if (state.initializing) {
|
|
22
|
+
return state.initializing;
|
|
33
23
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
24
|
+
state.initializing = (async () => {
|
|
25
|
+
await impl.initializeInternal?.();
|
|
26
|
+
state.initialized = true;
|
|
27
|
+
state.initializing = null;
|
|
28
|
+
})().catch((err) => {
|
|
29
|
+
state.initialized = false;
|
|
30
|
+
state.initializing = null;
|
|
31
|
+
throw err;
|
|
32
|
+
});
|
|
33
|
+
return state.initializing;
|
|
34
|
+
};
|
|
35
|
+
const destroy = async () => {
|
|
36
|
+
await impl.destroyInternal?.();
|
|
37
|
+
state.initialized = false;
|
|
38
|
+
state.initializing = null;
|
|
39
|
+
};
|
|
40
|
+
const generateQueryId = () => `q_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
41
|
+
const cancelQuery = async (queryId) => {
|
|
42
|
+
const abortController = state.activeQueries.get(queryId);
|
|
41
43
|
if (abortController) {
|
|
42
44
|
abortController.abort();
|
|
43
|
-
|
|
45
|
+
state.activeQueries.delete(queryId);
|
|
44
46
|
}
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
* Creates a QueryHandle with common signal handling logic.
|
|
49
|
-
* This method handles the AbortController setup, signal chaining, and cleanup.
|
|
50
|
-
*/
|
|
51
|
-
createQueryHandleInternal(queryPromiseFactory, options) {
|
|
47
|
+
await impl.cancelQueryInternal?.(queryId);
|
|
48
|
+
};
|
|
49
|
+
const createQueryHandle = (queryPromiseFactory, options) => {
|
|
52
50
|
const abortController = new AbortController();
|
|
53
|
-
const queryId =
|
|
54
|
-
// If user provided a signal, listen for its abort event
|
|
51
|
+
const queryId = generateQueryId();
|
|
55
52
|
if (options?.signal) {
|
|
56
53
|
const userSignal = options.signal;
|
|
57
|
-
if (userSignal.aborted)
|
|
54
|
+
if (userSignal.aborted)
|
|
58
55
|
abortController.abort();
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
userSignal.addEventListener('abort', () => {
|
|
62
|
-
abortController.abort();
|
|
63
|
-
});
|
|
64
|
-
}
|
|
56
|
+
else
|
|
57
|
+
userSignal.addEventListener('abort', () => abortController.abort());
|
|
65
58
|
}
|
|
66
|
-
|
|
67
|
-
// Execute the query with abort signal support
|
|
59
|
+
state.activeQueries.set(queryId, abortController);
|
|
68
60
|
const resultPromise = queryPromiseFactory(abortController.signal, queryId).finally(() => {
|
|
69
|
-
|
|
61
|
+
state.activeQueries.delete(queryId);
|
|
70
62
|
});
|
|
71
63
|
return {
|
|
72
64
|
result: resultPromise,
|
|
73
65
|
signal: abortController.signal,
|
|
74
|
-
cancel: async () =>
|
|
75
|
-
await this.cancelQueryInternal(queryId);
|
|
76
|
-
},
|
|
66
|
+
cancel: async () => cancelQuery(queryId),
|
|
77
67
|
};
|
|
78
|
-
}
|
|
79
|
-
execute(sql, options)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
return
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}, options);
|
|
90
|
-
}
|
|
91
|
-
async loadFile(file, tableName, opts) {
|
|
68
|
+
};
|
|
69
|
+
const execute = (sql, options) => createQueryHandle((signal, id) => impl.executeQueryInternal(sql, signal, id), options);
|
|
70
|
+
const query = (queryStr, options) => createQueryHandle((signal, id) => impl.executeQueryInternal(queryStr, signal, id), options);
|
|
71
|
+
const queryJson = (queryStr, options) => createQueryHandle(async (signal, id) => {
|
|
72
|
+
const table = await impl.executeQueryInternal(queryStr, signal, id);
|
|
73
|
+
return createTypedRowAccessor({ arrowTable: table });
|
|
74
|
+
}, options);
|
|
75
|
+
const loadFile = async (file, tableName, opts) => {
|
|
76
|
+
if (impl.loadFileInternal) {
|
|
77
|
+
return impl.loadFileInternal(file, tableName, opts);
|
|
78
|
+
}
|
|
92
79
|
if (file instanceof File) {
|
|
93
80
|
throw new Error('Not implemented', { cause: { file, tableName, opts } });
|
|
94
81
|
}
|
|
95
82
|
const fileName = file;
|
|
83
|
+
await ensureInitialized();
|
|
96
84
|
if (opts && isSpatialLoadFileOptions(opts)) {
|
|
97
|
-
|
|
98
|
-
await queryHandle.result;
|
|
85
|
+
await query(loadSpatial(tableName, fileName, opts)).result;
|
|
99
86
|
}
|
|
100
87
|
else {
|
|
101
|
-
|
|
102
|
-
|
|
88
|
+
await query(load(opts?.method ?? 'auto', tableName, fileName, opts))
|
|
89
|
+
.result;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const loadArrow = async (file, tableName, opts) => {
|
|
93
|
+
if (impl.loadArrowInternal) {
|
|
94
|
+
return impl.loadArrowInternal(file, tableName, opts);
|
|
103
95
|
}
|
|
104
|
-
}
|
|
105
|
-
async loadArrow(file, tableName, opts) {
|
|
106
96
|
throw new Error('Not implemented');
|
|
107
|
-
}
|
|
108
|
-
async
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
97
|
+
};
|
|
98
|
+
const loadObjects = async (file, tableName, opts) => {
|
|
99
|
+
if (impl.loadObjectsInternal) {
|
|
100
|
+
return impl.loadObjectsInternal(file, tableName, opts);
|
|
101
|
+
}
|
|
102
|
+
await ensureInitialized();
|
|
103
|
+
await query(loadObjectsSql(tableName, file, opts)).result;
|
|
104
|
+
};
|
|
105
|
+
return {
|
|
106
|
+
initialize,
|
|
107
|
+
destroy,
|
|
108
|
+
execute,
|
|
109
|
+
query,
|
|
110
|
+
queryJson,
|
|
111
|
+
loadFile,
|
|
112
|
+
loadArrow,
|
|
113
|
+
loadObjects,
|
|
114
|
+
};
|
|
116
115
|
}
|
|
117
116
|
//# sourceMappingURL=BaseDuckDbConnector.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseDuckDbConnector.js","sourceRoot":"","sources":["../../src/connectors/BaseDuckDbConnector.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n isSpatialLoadFileOptions,\n LoadFileOptions,\n StandardLoadOptions,\n} from '@sqlrooms/project-config';\nimport * as arrow from 'apache-arrow';\nimport {TypeMap} from 'apache-arrow';\nimport {DuckDbConnector, QueryHandle, QueryOptions} from './DuckDbConnector';\nimport {load, loadObjects, loadSpatial} from './load/load';\nimport {createTypedRowAccessor} from '../typedRowAccessor';\n\nexport abstract class BaseDuckDbConnector implements DuckDbConnector {\n protected dbPath: string;\n protected initializationQuery: string;\n protected initialized = false;\n protected initializing: Promise<void> | null = null;\n protected activeQueries = new Map<string, AbortController>();\n\n constructor({\n initializationQuery = '',\n dbPath = ':memory:',\n }: {\n dbPath?: string;\n initializationQuery?: string;\n } = {}) {\n this.dbPath = dbPath;\n this.initializationQuery = initializationQuery;\n }\n\n async initialize(): Promise<void> {\n if (this.initialized) {\n return;\n }\n if (this.initializing) {\n return this.initializing;\n }\n this.initializing = this.initializeInternal();\n return this.initializing;\n }\n\n protected async initializeInternal(): Promise<void> {\n // To be implemented by subclasses\n }\n\n async destroy(): Promise<void> {\n // To be implemented by subclasses\n }\n\n protected async ensureInitialized(): Promise<void> {\n if (!this.initialized && this.initializing) {\n await this.initializing;\n }\n }\n\n /**\n * Cancel a query by its internal ID\n * @param queryId Internal query ID to cancel\n */\n protected async cancelQueryInternal(queryId: string): Promise<void> {\n const abortController = this.activeQueries.get(queryId);\n if (abortController) {\n abortController.abort();\n this.activeQueries.delete(queryId);\n }\n // Subclasses can override this for additional cleanup\n }\n\n /**\n * Abstract method for executing a query with abort signal support.\n * Subclasses must implement this to handle the actual query execution.\n */\n protected abstract executeQueryInternal<T extends TypeMap = any>(\n query: string,\n signal: AbortSignal,\n queryId?: string,\n ): Promise<arrow.Table<T>>;\n\n /**\n * Creates a QueryHandle with common signal handling logic.\n * This method handles the AbortController setup, signal chaining, and cleanup.\n */\n protected createQueryHandleInternal<T>(\n queryPromiseFactory: (signal: AbortSignal, queryId: string) => Promise<T>,\n options?: QueryOptions,\n ): QueryHandle<T> {\n const abortController = new AbortController();\n const queryId = this.generateQueryId();\n\n // If user provided a signal, listen for its abort event\n if (options?.signal) {\n const userSignal = options.signal;\n if (userSignal.aborted) {\n abortController.abort();\n } else {\n userSignal.addEventListener('abort', () => {\n abortController.abort();\n });\n }\n }\n\n this.activeQueries.set(queryId, abortController);\n\n // Execute the query with abort signal support\n const resultPromise = queryPromiseFactory(abortController.signal, queryId).finally(\n () => {\n this.activeQueries.delete(queryId);\n },\n );\n\n return {\n result: resultPromise,\n signal: abortController.signal,\n cancel: async () => {\n await this.cancelQueryInternal(queryId);\n },\n };\n }\n\n execute(sql: string, options?: QueryOptions): QueryHandle {\n return this.createQueryHandleInternal(\n (signal, queryId) => this.executeQueryInternal(sql, signal, queryId),\n options,\n );\n }\n\n query<T extends TypeMap = any>(\n query: string,\n options?: QueryOptions,\n ): QueryHandle<arrow.Table<T>> {\n return this.createQueryHandleInternal(\n (signal, queryId) => this.executeQueryInternal<T>(query, signal, queryId),\n options,\n );\n }\n\n queryJson<T = Record<string, any>>(\n query: string,\n options?: QueryOptions,\n ): QueryHandle<Iterable<T>> {\n return this.createQueryHandleInternal(async (signal, queryId) => {\n const table = await this.executeQueryInternal(query, signal, queryId);\n return createTypedRowAccessor({arrowTable: table});\n }, options);\n }\n\n async loadFile(\n file: string | File,\n tableName: string,\n opts?: LoadFileOptions,\n ) {\n if (file instanceof File) {\n throw new Error('Not implemented', {cause: {file, tableName, opts}});\n }\n const fileName = file;\n if (opts && isSpatialLoadFileOptions(opts)) {\n const queryHandle = this.query(loadSpatial(tableName, fileName, opts));\n await queryHandle.result;\n } else {\n const queryHandle = this.query(\n load(opts?.method ?? 'auto', tableName, fileName, opts),\n );\n await queryHandle.result;\n }\n }\n\n async loadArrow(\n file: arrow.Table | Uint8Array,\n tableName: string,\n opts?: {schema?: string}\n ): Promise<void> {\n throw new Error('Not implemented');\n }\n\n async loadObjects(\n file: Record<string, unknown>[],\n tableName: string,\n opts?: StandardLoadOptions,\n ) {\n await this.ensureInitialized();\n const queryHandle = this.query(loadObjects(tableName, file, opts));\n await queryHandle.result;\n }\n\n protected generateQueryId(): string {\n return `q_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"BaseDuckDbConnector.js","sourceRoot":"","sources":["../../src/connectors/BaseDuckDbConnector.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n isSpatialLoadFileOptions,\n LoadFileOptions,\n StandardLoadOptions,\n} from '@sqlrooms/room-config';\nimport * as arrow from 'apache-arrow';\nimport {TypeMap} from 'apache-arrow';\nimport {DuckDbConnector, QueryHandle, QueryOptions} from './DuckDbConnector';\nimport {load, loadObjects as loadObjectsSql, loadSpatial} from './load/load';\nimport {createTypedRowAccessor} from '../typedRowAccessor';\n\nexport interface BaseDuckDbConnectorOptions {\n dbPath?: string;\n initializationQuery?: string;\n}\n\nexport interface BaseDuckDbConnectorImpl {\n initializeInternal?(): Promise<void>;\n destroyInternal?(): Promise<void>;\n executeQueryInternal<T extends TypeMap = any>(\n query: string,\n signal: AbortSignal,\n queryId?: string,\n ): Promise<arrow.Table<T>>;\n cancelQueryInternal?(queryId: string): Promise<void>;\n loadArrowInternal?(\n file: arrow.Table | Uint8Array,\n tableName: string,\n opts?: {schema?: string},\n ): Promise<void>;\n loadObjectsInternal?(\n file: Record<string, unknown>[],\n tableName: string,\n opts?: StandardLoadOptions,\n ): Promise<void>;\n loadFileInternal?(\n file: string | File,\n tableName: string,\n opts?: LoadFileOptions,\n ): Promise<void>;\n}\n\nexport function createBaseDuckDbConnector(\n {\n dbPath = ':memory:',\n initializationQuery = '',\n }: BaseDuckDbConnectorOptions = {},\n impl: BaseDuckDbConnectorImpl,\n): DuckDbConnector {\n const state = {\n dbPath,\n initializationQuery,\n initialized: false,\n initializing: null as Promise<void> | null,\n activeQueries: new Map<string, AbortController>(),\n };\n\n const ensureInitialized = async () => {\n if (!state.initialized && state.initializing) {\n await state.initializing;\n }\n };\n\n const initialize = async () => {\n if (state.initialized) {\n return;\n }\n if (state.initializing) {\n return state.initializing;\n }\n state.initializing = (async () => {\n await impl.initializeInternal?.();\n state.initialized = true;\n state.initializing = null;\n })().catch((err) => {\n state.initialized = false;\n state.initializing = null;\n throw err;\n });\n return state.initializing;\n };\n\n const destroy = async () => {\n await impl.destroyInternal?.();\n state.initialized = false;\n state.initializing = null;\n };\n\n const generateQueryId = () =>\n `q_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n\n const cancelQuery = async (queryId: string) => {\n const abortController = state.activeQueries.get(queryId);\n if (abortController) {\n abortController.abort();\n state.activeQueries.delete(queryId);\n }\n await impl.cancelQueryInternal?.(queryId);\n };\n\n const createQueryHandle = <T>(\n queryPromiseFactory: (signal: AbortSignal, queryId: string) => Promise<T>,\n options?: QueryOptions,\n ): QueryHandle<T> => {\n const abortController = new AbortController();\n const queryId = generateQueryId();\n if (options?.signal) {\n const userSignal = options.signal;\n if (userSignal.aborted) abortController.abort();\n else userSignal.addEventListener('abort', () => abortController.abort());\n }\n state.activeQueries.set(queryId, abortController);\n const resultPromise = queryPromiseFactory(\n abortController.signal,\n queryId,\n ).finally(() => {\n state.activeQueries.delete(queryId);\n });\n return {\n result: resultPromise,\n signal: abortController.signal,\n cancel: async () => cancelQuery(queryId),\n };\n };\n\n const execute = (sql: string, options?: QueryOptions): QueryHandle =>\n createQueryHandle(\n (signal, id) => impl.executeQueryInternal(sql, signal, id),\n options,\n );\n\n const query = <T extends TypeMap = any>(\n queryStr: string,\n options?: QueryOptions,\n ): QueryHandle<arrow.Table<T>> =>\n createQueryHandle(\n (signal, id) => impl.executeQueryInternal<T>(queryStr, signal, id),\n options,\n );\n\n const queryJson = <T = Record<string, any>>(\n queryStr: string,\n options?: QueryOptions,\n ): QueryHandle<Iterable<T>> =>\n createQueryHandle(async (signal, id) => {\n const table = await impl.executeQueryInternal(queryStr, signal, id);\n return createTypedRowAccessor({arrowTable: table});\n }, options);\n\n const loadFile = async (\n file: string | File,\n tableName: string,\n opts?: LoadFileOptions,\n ) => {\n if (impl.loadFileInternal) {\n return impl.loadFileInternal(file, tableName, opts);\n }\n if (file instanceof File) {\n throw new Error('Not implemented', {cause: {file, tableName, opts}});\n }\n const fileName = file;\n await ensureInitialized();\n if (opts && isSpatialLoadFileOptions(opts)) {\n await query(loadSpatial(tableName, fileName, opts)).result;\n } else {\n await query(load(opts?.method ?? 'auto', tableName, fileName, opts))\n .result;\n }\n };\n\n const loadArrow = async (\n file: arrow.Table | Uint8Array,\n tableName: string,\n opts?: {schema?: string},\n ): Promise<void> => {\n if (impl.loadArrowInternal) {\n return impl.loadArrowInternal(file, tableName, opts);\n }\n throw new Error('Not implemented');\n };\n\n const loadObjects = async (\n file: Record<string, unknown>[],\n tableName: string,\n opts?: StandardLoadOptions,\n ) => {\n if (impl.loadObjectsInternal) {\n return impl.loadObjectsInternal(file, tableName, opts);\n }\n await ensureInitialized();\n await query(loadObjectsSql(tableName, file, opts)).result;\n };\n\n return {\n initialize,\n destroy,\n execute,\n query,\n queryJson,\n loadFile,\n loadArrow,\n loadObjects,\n };\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LoadFileOptions, StandardLoadOptions } from '@sqlrooms/
|
|
1
|
+
import { LoadFileOptions, StandardLoadOptions } from '@sqlrooms/room-config';
|
|
2
2
|
import * as arrow from 'apache-arrow';
|
|
3
3
|
import { TypeMap } from 'apache-arrow';
|
|
4
4
|
/**
|
|
@@ -151,7 +151,10 @@ export interface QueryHandle<T = any> {
|
|
|
151
151
|
*/
|
|
152
152
|
export interface DuckDbConnector {
|
|
153
153
|
/**
|
|
154
|
-
* Initialize the connector
|
|
154
|
+
* Initialize the connector.
|
|
155
|
+
* The function returns a promise that resolves when the connector is initialized.
|
|
156
|
+
* Calling the initialize() function multiple times should not restart the initialization.
|
|
157
|
+
* See BaseDuckDbConnector for an implementation example.
|
|
155
158
|
*/
|
|
156
159
|
initialize(): Promise<void>;
|
|
157
160
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DuckDbConnector.d.ts","sourceRoot":"","sources":["../../src/connectors/DuckDbConnector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAE,mBAAmB,EAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"DuckDbConnector.d.ts","sourceRoot":"","sources":["../../src/connectors/DuckDbConnector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAE,mBAAmB,EAAC,MAAM,uBAAuB,CAAC;AAC3E,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AAErC;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,GAAG;IAClC,+CAA+C;IAC/C,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAEnB;;;OAGG;IACH,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,MAAM,EAAE,WAAW,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B;;OAEG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzB;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,WAAW,CAAC;IAE1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkCG;IACH,KAAK,CAAC,CAAC,SAAS,OAAO,GAAG,GAAG,EAC3B,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,YAAY,GACrB,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAE/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACH,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC/B,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,YAAY,GACrB,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAE5B;;;;;OAKG;IACH,QAAQ,CACN,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,eAAe,GACrB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;;;OAIG;IACH,SAAS,CACP,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,UAAU,EAC/B,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAC,GACvB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;;;;OAKG;IACH,WAAW,CACT,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC/B,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,mBAAmB,GACzB,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DuckDbConnector.js","sourceRoot":"","sources":["../../src/connectors/DuckDbConnector.ts"],"names":[],"mappings":"","sourcesContent":["import {LoadFileOptions, StandardLoadOptions} from '@sqlrooms/project-config';\nimport * as arrow from 'apache-arrow';\nimport {TypeMap} from 'apache-arrow';\n\n/**\n * Options for query execution\n */\nexport interface QueryOptions {\n /**\n * Optional external abort signal for coordinated cancellation.\n * When provided, the query will be cancelled if this signal is aborted.\n * This enables powerful composition patterns like cancelling multiple\n * queries together or integrating with other cancellable operations.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Handle for managing query execution and cancellation\n *\n * @example\n * ```typescript\n * // Simple usage\n * const handle = connector.query('SELECT * FROM table');\n * await handle.result;\n *\n * // With cancellation\n * const handle = connector.query('SELECT * FROM large_table');\n * setTimeout(() => handle.cancel(), 5000);\n *\n * // Composable cancellation\n * const controller = new AbortController();\n * const handle1 = connector.query('SELECT * FROM table1', { signal: controller.signal });\n * const handle2 = connector.query('SELECT * FROM table2', { signal: controller.signal });\n * controller.abort(); // Cancels both queries\n * ```\n */\nexport interface QueryHandle<T = any> {\n /** Promise that resolves with query results */\n result: Promise<T>;\n\n /**\n * Method to cancel the query with optional cleanup.\n * This provides a clean abstraction over the underlying cancellation mechanism.\n */\n cancel: () => Promise<void>;\n\n /**\n * Read-only access to the abort signal for composability.\n *\n * Key benefits:\n * - **Event-driven**: Listen for abort events to update UI or perform cleanup\n * - **Integration**: Use with other Web APIs like fetch() that accept AbortSignal\n * - **Status checking**: Check if query is already cancelled with signal.aborted\n *\n * @example\n * ```typescript\n * // Listen for cancellation events\n * handle.signal.addEventListener('abort', () => {\n * console.log('Query cancelled');\n * updateUI('Operation cancelled');\n * });\n *\n * // Check cancellation status\n * if (handle.signal.aborted) {\n * console.log('Query was already cancelled');\n * }\n *\n * // Use with other APIs\n * const response = await fetch('/api/data', { signal: handle.signal });\n * ```\n */\n signal: AbortSignal;\n}\n\n/**\n * DuckDB connector interface with advanced query cancellation support\n *\n * This interface provides a hybrid approach that combines the simplicity of method-based\n * cancellation with the composability of Web Standards (AbortController/AbortSignal).\n *\n * ## Key Benefits of This Design\n *\n * ### 🔗 Composability\n * Cancel multiple queries with a single controller:\n * ```typescript\n * const controller = new AbortController();\n * const query1 = connector.query('SELECT * FROM table1', { signal: controller.signal });\n * const query2 = connector.query('SELECT * FROM table2', { signal: controller.signal });\n * controller.abort(); // Cancels both queries\n * ```\n *\n * ### 🌐 Integration with Web APIs\n * Use the same signal for queries and HTTP requests:\n * ```typescript\n * const controller = new AbortController();\n * const queryHandle = connector.query('SELECT * FROM table', { signal: controller.signal });\n * const response = await fetch('/api/data', { signal: controller.signal });\n * // controller.abort() cancels both the query and the HTTP request\n * ```\n *\n * ### 🎛️ Flexibility\n * Simple usage when you don't need external control, advanced when you do:\n * ```typescript\n * // Simple - internal cancellation management\n * const handle = connector.query('SELECT * FROM table');\n * handle.cancel();\n *\n * // Advanced - external cancellation control\n * const controller = new AbortController();\n * const handle = connector.query('SELECT * FROM table', { signal: controller.signal });\n * controller.abort();\n * ```\n *\n * ### 📡 Event-Driven\n * React to cancellation events for better UX:\n * ```typescript\n * handle.signal.addEventListener('abort', () => {\n * showNotification('Query cancelled');\n * hideLoadingSpinner();\n * });\n * ```\n *\n * ### ⏱️ Timeout Support\n * Built-in timeout capability with manual override:\n * ```typescript\n * const timeoutController = new AbortController();\n * setTimeout(() => timeoutController.abort(), 30000); // 30s timeout\n *\n * const handle = connector.query('SELECT * FROM large_table', {\n * signal: timeoutController.signal\n * });\n *\n * // User can still cancel manually\n * cancelButton.onclick = () => timeoutController.abort();\n * ```\n *\n * ### 🏗️ Signal Composition\n * Combine multiple cancellation sources:\n * ```typescript\n * function combineSignals(...signals: AbortSignal[]): AbortSignal {\n * const controller = new AbortController();\n * signals.forEach(signal => {\n * if (signal.aborted) controller.abort();\n * else signal.addEventListener('abort', () => controller.abort());\n * });\n * return controller.signal;\n * }\n *\n * const userSignal = userController.signal;\n * const timeoutSignal = createTimeoutSignal(30000);\n * const combinedSignal = combineSignals(userSignal, timeoutSignal);\n *\n * const handle = connector.query('SELECT * FROM table', { signal: combinedSignal });\n * ```\n */\nexport interface DuckDbConnector {\n /**\n * Initialize the connector\n */\n initialize(): Promise<void>;\n\n /**\n * Destroy the connector and clean up resources\n */\n destroy(): Promise<void>;\n\n /**\n * Execute a SQL query without returning a result\n *\n * @param sql SQL query to execute\n * @param options Optional query options including abort signal for coordinated cancellation\n * @returns QueryHandle containing:\n * - result: Promise that resolves when execution completes\n * - cancel: Method to cancel the query with cleanup\n * - signal: AbortSignal for composability with other cancellable operations\n *\n * @example\n * ```typescript\n * // Simple execution\n * const handle = connector.execute('CREATE TABLE test AS SELECT * FROM source');\n * await handle.result;\n *\n * // With external cancellation control\n * const controller = new AbortController();\n * const handle = connector.execute('DROP TABLE large_table', {\n * signal: controller.signal\n * });\n *\n * // Cancel if it takes too long\n * setTimeout(() => controller.abort(), 5000);\n * ```\n */\n execute(sql: string, options?: QueryOptions): QueryHandle;\n\n /**\n * Execute a SQL query and return the result as an Arrow table\n *\n * @param query SQL query to execute\n * @param options Optional query options including abort signal for coordinated cancellation\n * @returns QueryHandle containing:\n * - result: Promise that resolves with Arrow table\n * - cancel: Method to cancel the query with cleanup\n * - signal: AbortSignal for composability with other cancellable operations\n *\n * @example\n * ```typescript\n * // Basic query\n * const handle = connector.query('SELECT * FROM users WHERE active = true');\n * const table = await handle.result;\n * console.log(`Found ${table.numRows} active users`);\n *\n * // Query with timeout\n * const controller = new AbortController();\n * setTimeout(() => controller.abort(), 30000); // 30s timeout\n *\n * const handle = connector.query('SELECT * FROM very_large_table', {\n * signal: controller.signal\n * });\n *\n * try {\n * const result = await handle.result;\n * console.log('Query completed within timeout');\n * } catch (error) {\n * if (error.name === 'AbortError') {\n * console.log('Query timed out');\n * }\n * }\n * ```\n */\n query<T extends TypeMap = any>(\n query: string,\n options?: QueryOptions,\n ): QueryHandle<arrow.Table<T>>;\n\n /**\n * Execute a SQL query and return the result as a JSON object\n *\n * @param query SQL query to execute\n * @param options Optional query options including abort signal for coordinated cancellation\n * @returns QueryHandle containing:\n * - result: Promise that resolves with iterable of JSON objects\n * - cancel: Method to cancel the query with cleanup\n * - signal: AbortSignal for composability with other cancellable operations\n *\n * @example\n * ```typescript\n * // Simple JSON query\n * const handle = connector.queryJson('SELECT name, email FROM users LIMIT 10');\n * const users = await handle.result;\n * for (const user of users) {\n * console.log(`${user.name}: ${user.email}`);\n * }\n *\n * // Coordinated cancellation with multiple operations\n * const operationController = new AbortController();\n *\n * const usersHandle = connector.queryJson('SELECT * FROM users', {\n * signal: operationController.signal\n * });\n *\n * const ordersHandle = connector.queryJson('SELECT * FROM orders', {\n * signal: operationController.signal\n * });\n *\n * // Cancel both queries if user navigates away\n * window.addEventListener('beforeunload', () => {\n * operationController.abort();\n * });\n * ```\n */\n queryJson<T = Record<string, any>>(\n query: string,\n options?: QueryOptions,\n ): QueryHandle<Iterable<T>>;\n\n /**\n * Load a file into DuckDB and create a table\n * @param fileName - Path to the file to load\n * @param tableName - Name of the table to create\n * @param opts - Load options\n */\n loadFile(\n fileName: string | File,\n tableName: string,\n opts?: LoadFileOptions,\n ): Promise<void>;\n\n /**\n * Load an arrow table or an arrow IPC stream into DuckDB\n * @param table - Arrow table or arrow IPC stream to load\n * @param tableName - Name of the table to create\n */\n loadArrow(\n table: arrow.Table | Uint8Array,\n tableName: string,\n opts?: {schema?: string},\n ): Promise<void>;\n\n /**\n * Load JavaScript objects into DuckDB\n * @param data - Array of objects to load\n * @param tableName - Name of the table to create\n * @param opts - Load options\n */\n loadObjects(\n data: Record<string, unknown>[],\n tableName: string,\n opts?: StandardLoadOptions,\n ): Promise<void>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"DuckDbConnector.js","sourceRoot":"","sources":["../../src/connectors/DuckDbConnector.ts"],"names":[],"mappings":"","sourcesContent":["import {LoadFileOptions, StandardLoadOptions} from '@sqlrooms/room-config';\nimport * as arrow from 'apache-arrow';\nimport {TypeMap} from 'apache-arrow';\n\n/**\n * Options for query execution\n */\nexport interface QueryOptions {\n /**\n * Optional external abort signal for coordinated cancellation.\n * When provided, the query will be cancelled if this signal is aborted.\n * This enables powerful composition patterns like cancelling multiple\n * queries together or integrating with other cancellable operations.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Handle for managing query execution and cancellation\n *\n * @example\n * ```typescript\n * // Simple usage\n * const handle = connector.query('SELECT * FROM table');\n * await handle.result;\n *\n * // With cancellation\n * const handle = connector.query('SELECT * FROM large_table');\n * setTimeout(() => handle.cancel(), 5000);\n *\n * // Composable cancellation\n * const controller = new AbortController();\n * const handle1 = connector.query('SELECT * FROM table1', { signal: controller.signal });\n * const handle2 = connector.query('SELECT * FROM table2', { signal: controller.signal });\n * controller.abort(); // Cancels both queries\n * ```\n */\nexport interface QueryHandle<T = any> {\n /** Promise that resolves with query results */\n result: Promise<T>;\n\n /**\n * Method to cancel the query with optional cleanup.\n * This provides a clean abstraction over the underlying cancellation mechanism.\n */\n cancel: () => Promise<void>;\n\n /**\n * Read-only access to the abort signal for composability.\n *\n * Key benefits:\n * - **Event-driven**: Listen for abort events to update UI or perform cleanup\n * - **Integration**: Use with other Web APIs like fetch() that accept AbortSignal\n * - **Status checking**: Check if query is already cancelled with signal.aborted\n *\n * @example\n * ```typescript\n * // Listen for cancellation events\n * handle.signal.addEventListener('abort', () => {\n * console.log('Query cancelled');\n * updateUI('Operation cancelled');\n * });\n *\n * // Check cancellation status\n * if (handle.signal.aborted) {\n * console.log('Query was already cancelled');\n * }\n *\n * // Use with other APIs\n * const response = await fetch('/api/data', { signal: handle.signal });\n * ```\n */\n signal: AbortSignal;\n}\n\n/**\n * DuckDB connector interface with advanced query cancellation support\n *\n * This interface provides a hybrid approach that combines the simplicity of method-based\n * cancellation with the composability of Web Standards (AbortController/AbortSignal).\n *\n * ## Key Benefits of This Design\n *\n * ### 🔗 Composability\n * Cancel multiple queries with a single controller:\n * ```typescript\n * const controller = new AbortController();\n * const query1 = connector.query('SELECT * FROM table1', { signal: controller.signal });\n * const query2 = connector.query('SELECT * FROM table2', { signal: controller.signal });\n * controller.abort(); // Cancels both queries\n * ```\n *\n * ### 🌐 Integration with Web APIs\n * Use the same signal for queries and HTTP requests:\n * ```typescript\n * const controller = new AbortController();\n * const queryHandle = connector.query('SELECT * FROM table', { signal: controller.signal });\n * const response = await fetch('/api/data', { signal: controller.signal });\n * // controller.abort() cancels both the query and the HTTP request\n * ```\n *\n * ### 🎛️ Flexibility\n * Simple usage when you don't need external control, advanced when you do:\n * ```typescript\n * // Simple - internal cancellation management\n * const handle = connector.query('SELECT * FROM table');\n * handle.cancel();\n *\n * // Advanced - external cancellation control\n * const controller = new AbortController();\n * const handle = connector.query('SELECT * FROM table', { signal: controller.signal });\n * controller.abort();\n * ```\n *\n * ### 📡 Event-Driven\n * React to cancellation events for better UX:\n * ```typescript\n * handle.signal.addEventListener('abort', () => {\n * showNotification('Query cancelled');\n * hideLoadingSpinner();\n * });\n * ```\n *\n * ### ⏱️ Timeout Support\n * Built-in timeout capability with manual override:\n * ```typescript\n * const timeoutController = new AbortController();\n * setTimeout(() => timeoutController.abort(), 30000); // 30s timeout\n *\n * const handle = connector.query('SELECT * FROM large_table', {\n * signal: timeoutController.signal\n * });\n *\n * // User can still cancel manually\n * cancelButton.onclick = () => timeoutController.abort();\n * ```\n *\n * ### 🏗️ Signal Composition\n * Combine multiple cancellation sources:\n * ```typescript\n * function combineSignals(...signals: AbortSignal[]): AbortSignal {\n * const controller = new AbortController();\n * signals.forEach(signal => {\n * if (signal.aborted) controller.abort();\n * else signal.addEventListener('abort', () => controller.abort());\n * });\n * return controller.signal;\n * }\n *\n * const userSignal = userController.signal;\n * const timeoutSignal = createTimeoutSignal(30000);\n * const combinedSignal = combineSignals(userSignal, timeoutSignal);\n *\n * const handle = connector.query('SELECT * FROM table', { signal: combinedSignal });\n * ```\n */\nexport interface DuckDbConnector {\n /**\n * Initialize the connector.\n * The function returns a promise that resolves when the connector is initialized.\n * Calling the initialize() function multiple times should not restart the initialization.\n * See BaseDuckDbConnector for an implementation example.\n */\n initialize(): Promise<void>;\n\n /**\n * Destroy the connector and clean up resources\n */\n destroy(): Promise<void>;\n\n /**\n * Execute a SQL query without returning a result\n *\n * @param sql SQL query to execute\n * @param options Optional query options including abort signal for coordinated cancellation\n * @returns QueryHandle containing:\n * - result: Promise that resolves when execution completes\n * - cancel: Method to cancel the query with cleanup\n * - signal: AbortSignal for composability with other cancellable operations\n *\n * @example\n * ```typescript\n * // Simple execution\n * const handle = connector.execute('CREATE TABLE test AS SELECT * FROM source');\n * await handle.result;\n *\n * // With external cancellation control\n * const controller = new AbortController();\n * const handle = connector.execute('DROP TABLE large_table', {\n * signal: controller.signal\n * });\n *\n * // Cancel if it takes too long\n * setTimeout(() => controller.abort(), 5000);\n * ```\n */\n execute(sql: string, options?: QueryOptions): QueryHandle;\n\n /**\n * Execute a SQL query and return the result as an Arrow table\n *\n * @param query SQL query to execute\n * @param options Optional query options including abort signal for coordinated cancellation\n * @returns QueryHandle containing:\n * - result: Promise that resolves with Arrow table\n * - cancel: Method to cancel the query with cleanup\n * - signal: AbortSignal for composability with other cancellable operations\n *\n * @example\n * ```typescript\n * // Basic query\n * const handle = connector.query('SELECT * FROM users WHERE active = true');\n * const table = await handle.result;\n * console.log(`Found ${table.numRows} active users`);\n *\n * // Query with timeout\n * const controller = new AbortController();\n * setTimeout(() => controller.abort(), 30000); // 30s timeout\n *\n * const handle = connector.query('SELECT * FROM very_large_table', {\n * signal: controller.signal\n * });\n *\n * try {\n * const result = await handle.result;\n * console.log('Query completed within timeout');\n * } catch (error) {\n * if (error.name === 'AbortError') {\n * console.log('Query timed out');\n * }\n * }\n * ```\n */\n query<T extends TypeMap = any>(\n query: string,\n options?: QueryOptions,\n ): QueryHandle<arrow.Table<T>>;\n\n /**\n * Execute a SQL query and return the result as a JSON object\n *\n * @param query SQL query to execute\n * @param options Optional query options including abort signal for coordinated cancellation\n * @returns QueryHandle containing:\n * - result: Promise that resolves with iterable of JSON objects\n * - cancel: Method to cancel the query with cleanup\n * - signal: AbortSignal for composability with other cancellable operations\n *\n * @example\n * ```typescript\n * // Simple JSON query\n * const handle = connector.queryJson('SELECT name, email FROM users LIMIT 10');\n * const users = await handle.result;\n * for (const user of users) {\n * console.log(`${user.name}: ${user.email}`);\n * }\n *\n * // Coordinated cancellation with multiple operations\n * const operationController = new AbortController();\n *\n * const usersHandle = connector.queryJson('SELECT * FROM users', {\n * signal: operationController.signal\n * });\n *\n * const ordersHandle = connector.queryJson('SELECT * FROM orders', {\n * signal: operationController.signal\n * });\n *\n * // Cancel both queries if user navigates away\n * window.addEventListener('beforeunload', () => {\n * operationController.abort();\n * });\n * ```\n */\n queryJson<T = Record<string, any>>(\n query: string,\n options?: QueryOptions,\n ): QueryHandle<Iterable<T>>;\n\n /**\n * Load a file into DuckDB and create a table\n * @param fileName - Path to the file to load\n * @param tableName - Name of the table to create\n * @param opts - Load options\n */\n loadFile(\n fileName: string | File,\n tableName: string,\n opts?: LoadFileOptions,\n ): Promise<void>;\n\n /**\n * Load an arrow table or an arrow IPC stream into DuckDB\n * @param table - Arrow table or arrow IPC stream to load\n * @param tableName - Name of the table to create\n */\n loadArrow(\n table: arrow.Table | Uint8Array,\n tableName: string,\n opts?: {schema?: string},\n ): Promise<void>;\n\n /**\n * Load JavaScript objects into DuckDB\n * @param data - Array of objects to load\n * @param tableName - Name of the table to create\n * @param opts - Load options\n */\n loadObjects(\n data: Record<string, unknown>[],\n tableName: string,\n opts?: StandardLoadOptions,\n ): Promise<void>;\n}\n"]}
|
|
@@ -1,33 +1,18 @@
|
|
|
1
1
|
import * as duckdb from '@duckdb/duckdb-wasm';
|
|
2
2
|
import { DuckDBQueryConfig } from '@duckdb/duckdb-wasm';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
private queryConfig?;
|
|
12
|
-
constructor({ logging, initializationQuery, dbPath, queryConfig, }?: {
|
|
13
|
-
dbPath?: string;
|
|
14
|
-
queryConfig?: DuckDBQueryConfig;
|
|
15
|
-
initializationQuery?: string;
|
|
16
|
-
logging?: boolean;
|
|
17
|
-
});
|
|
18
|
-
protected initializeInternal(): Promise<void>;
|
|
19
|
-
destroy(): Promise<void>;
|
|
20
|
-
protected executeQueryInternal<T extends arrow.TypeMap = any>(query: string, signal: AbortSignal): Promise<arrow.Table<T>>;
|
|
21
|
-
protected cancelQueryInternal(queryId: string): Promise<void>;
|
|
22
|
-
loadFile(file: string | File, tableName: string, opts?: LoadFileOptions): Promise<void>;
|
|
23
|
-
loadArrow(file: arrow.Table | Uint8Array, tableName: string, opts?: {
|
|
24
|
-
schema?: string;
|
|
25
|
-
}): Promise<void>;
|
|
26
|
-
loadObjects(file: Record<string, unknown>[], tableName: string, opts?: StandardLoadOptions): Promise<void>;
|
|
27
|
-
private withTempRegisteredFile;
|
|
3
|
+
import { DuckDbConnector } from './DuckDbConnector';
|
|
4
|
+
export interface WasmDuckDbConnectorOptions {
|
|
5
|
+
dbPath?: string;
|
|
6
|
+
queryConfig?: DuckDBQueryConfig;
|
|
7
|
+
initializationQuery?: string;
|
|
8
|
+
logging?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface WasmDuckDbConnector extends DuckDbConnector {
|
|
28
11
|
getDb(): duckdb.AsyncDuckDB;
|
|
29
12
|
getConnection(): duckdb.AsyncDuckDBConnection;
|
|
13
|
+
readonly type: 'wasm';
|
|
30
14
|
}
|
|
15
|
+
export declare function createWasmDuckDbConnector(options?: WasmDuckDbConnectorOptions): WasmDuckDbConnector;
|
|
31
16
|
export declare class DuckQueryError extends Error {
|
|
32
17
|
readonly cause: unknown;
|
|
33
18
|
readonly query: string | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WasmDuckDbConnector.d.ts","sourceRoot":"","sources":["../../src/connectors/WasmDuckDbConnector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAqB,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"WasmDuckDbConnector.d.ts","sourceRoot":"","sources":["../../src/connectors/WasmDuckDbConnector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAqB,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AAa1E,OAAO,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAC;AAElD,MAAM,WAAW,0BAA0B;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,mBAAoB,SAAQ,eAAe;IAC1D,KAAK,IAAI,MAAM,CAAC,WAAW,CAAC;IAC5B,aAAa,IAAI,MAAM,CAAC,qBAAqB,CAAC;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,0BAA+B,GACvC,mBAAmB,CAyOrB;AAeD,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;gBAChC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS;IAOlE,kBAAkB;IAOlB,iBAAiB;CAGlB"}
|