Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions packages/duckdb-wasm/karma/s3rver/s3rver.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
const S3rver = require('s3rver');

const CORS_CONFIG = "<CORSConfiguration>\n" +
" <CORSRule>\n" +
" <AllowedOrigin>*</AllowedOrigin>\n" +
" <AllowedMethod>PUT</AllowedMethod>\n" +
" <AllowedMethod>GET</AllowedMethod>\n" +
" <AllowedMethod>HEAD</AllowedMethod>\n" +
" <AllowedHeader>*</AllowedHeader>\n" +
" <ExposeHeaders>Content-Range</ExposeHeaders>\n" +
" </CORSRule>\n" +
"</CORSConfiguration>";
const CORS_CONFIG =
'<CORSConfiguration>\n' +
' <CORSRule>\n' +
' <AllowedOrigin>*</AllowedOrigin>\n' +
' <AllowedMethod>PUT</AllowedMethod>\n' +
' <AllowedMethod>GET</AllowedMethod>\n' +
' <AllowedMethod>HEAD</AllowedMethod>\n' +
' <AllowedHeader>*</AllowedHeader>\n' +
' <ExposeHeaders>Content-Range</ExposeHeaders>\n' +
' </CORSRule>\n' +
'</CORSConfiguration>';

var createS3rver = function (args, config, logger) {
const log = logger.create('S3-test-server');
Expand All @@ -19,10 +20,10 @@ var createS3rver = function (args, config, logger) {
address: 'localhost',
silent: config.s3rver.silent,
directory: './../../.tmp/s3rver',
configureBuckets: [{name: 'test-bucket', configs:[CORS_CONFIG]}]
configureBuckets: [{ name: 'test-bucket', configs: [CORS_CONFIG] }],
}).run();
};

module.exports = {
'framework:s3rver': ['factory', createS3rver]
};
'framework:s3rver': ['factory', createS3rver],
};
1 change: 1 addition & 0 deletions packages/duckdb-wasm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"build:debug": "node bundle.mjs debug && tsc --emitDeclarationOnly",
"build:release": "node bundle.mjs release && tsc --emitDeclarationOnly",
"docs": "typedoc",
"format": "prettier --write \"**/*.+(js|ts)\"",
"report": "node ./coverage.mjs",
"test:node": "node --enable-source-maps ../../node_modules/jasmine/bin/jasmine ./dist/tests-node.cjs",
"test:node:debug": "node --inspect-brk --enable-source-maps ../../node_modules/jasmine/bin/jasmine ./dist/tests-node.cjs",
Expand Down
70 changes: 50 additions & 20 deletions packages/duckdb-wasm/src/bindings/bindings_base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,15 @@ export abstract class DuckDBBindingsBase implements DuckDBBindings {
/** Tokenize a script */
public tokenize(text: string): ScriptTokens {
const BUF = TEXT_ENCODER.encode(text);
const bufferPtr = this.mod._malloc(BUF.length );
const bufferOfs = this.mod.HEAPU8.subarray(bufferPtr, bufferPtr + BUF.length );
const bufferPtr = this.mod._malloc(BUF.length);
const bufferOfs = this.mod.HEAPU8.subarray(bufferPtr, bufferPtr + BUF.length);
bufferOfs.set(BUF);
const [s, d, n] = callSRet(this.mod, 'duckdb_web_tokenize_buffer', ['number', 'number'], [bufferPtr, BUF.length]);
const [s, d, n] = callSRet(
this.mod,
'duckdb_web_tokenize_buffer',
['number', 'number'],
[bufferPtr, BUF.length],
);
this.mod._free(bufferPtr);
if (s !== StatusCode.SUCCESS) {
throw new Error(readString(this.mod, d, n));
Expand Down Expand Up @@ -172,7 +177,12 @@ export abstract class DuckDBBindingsBase implements DuckDBBindings {
const bufferPtr = this.mod._malloc(BUF.length);
const bufferOfs = this.mod.HEAPU8.subarray(bufferPtr, bufferPtr + BUF.length);
bufferOfs.set(BUF);
const [s, d, n] = callSRet(this.mod, 'duckdb_web_query_run_buffer', ['number', 'number', 'number'], [conn, bufferPtr, BUF.length]);
const [s, d, n] = callSRet(
this.mod,
'duckdb_web_query_run_buffer',
['number', 'number', 'number'],
[conn, bufferPtr, BUF.length],
);
this.mod._free(bufferPtr);
if (s !== StatusCode.SUCCESS) {
throw new Error(readString(this.mod, d, n));
Expand All @@ -189,10 +199,15 @@ export abstract class DuckDBBindingsBase implements DuckDBBindings {
*/
public startPendingQuery(conn: number, text: string, allowStreamResult: boolean = false): Uint8Array | null {
const BUF = TEXT_ENCODER.encode(text);
const bufferPtr = this.mod._malloc(BUF.length );
const bufferOfs = this.mod.HEAPU8.subarray(bufferPtr, bufferPtr + BUF.length );
const bufferPtr = this.mod._malloc(BUF.length);
const bufferOfs = this.mod.HEAPU8.subarray(bufferPtr, bufferPtr + BUF.length);
bufferOfs.set(BUF);
const [s, d, n] = callSRet(this.mod, 'duckdb_web_pending_query_start_buffer', ['number', 'number', 'number', 'boolean'], [conn, bufferPtr, BUF.length, allowStreamResult]);
const [s, d, n] = callSRet(
this.mod,
'duckdb_web_pending_query_start_buffer',
['number', 'number', 'number', 'boolean'],
[conn, bufferPtr, BUF.length, allowStreamResult],
);
this.mod._free(bufferPtr);
if (s !== StatusCode.SUCCESS) {
throw new Error(readString(this.mod, d, n));
Expand Down Expand Up @@ -230,7 +245,12 @@ export abstract class DuckDBBindingsBase implements DuckDBBindings {
}

if (!IsArrowBuffer(s)) {
throw new Error("Unexpected StatusCode from duckdb_web_query_fetch_results (" + s + ") and with self reported error as" + readString(this.mod, d, n));
throw new Error(
'Unexpected StatusCode from duckdb_web_query_fetch_results (' +
s +
') and with self reported error as' +
readString(this.mod, d, n),
);
}
if (s !== StatusCode.SUCCESS) {
throw new Error(readString(this.mod, d, n));
Expand All @@ -246,7 +266,12 @@ export abstract class DuckDBBindingsBase implements DuckDBBindings {
const bufferPtr = this.mod._malloc(BUF.length);
const bufferOfs = this.mod.HEAPU8.subarray(bufferPtr, bufferPtr + BUF.length);
bufferOfs.set(BUF);
const [s, d, n] = callSRet(this.mod, 'duckdb_web_get_tablenames_buffer', ['number', 'number', 'number'], [conn, bufferPtr, BUF.length]);
const [s, d, n] = callSRet(
this.mod,
'duckdb_web_get_tablenames_buffer',
['number', 'number', 'number'],
[conn, bufferPtr, BUF.length],
);
this.mod._free(bufferPtr);
if (s !== StatusCode.SUCCESS) {
throw new Error(readString(this.mod, d, n));
Expand Down Expand Up @@ -306,7 +331,12 @@ export abstract class DuckDBBindingsBase implements DuckDBBindings {
const bufferPtr = this.mod._malloc(BUF.length);
const bufferOfs = this.mod.HEAPU8.subarray(bufferPtr, bufferPtr + BUF.length);
bufferOfs.set(BUF);
const [s, d, n] = callSRet(this.mod, 'duckdb_web_prepared_create_buffer', ['number', 'number', 'number'], [conn, bufferPtr, BUF.length]);
const [s, d, n] = callSRet(
this.mod,
'duckdb_web_prepared_create_buffer',
['number', 'number', 'number'],
[conn, bufferPtr, BUF.length],
);
this.mod._free(bufferPtr);
if (s !== StatusCode.SUCCESS) {
throw new Error(readString(this.mod, d, n));
Expand Down Expand Up @@ -513,28 +543,28 @@ export abstract class DuckDBBindingsBase implements DuckDBBindings {
directIO: boolean,
): Promise<HandleType> {
if (protocol === DuckDBDataProtocol.BROWSER_FSACCESS) {
if( handle instanceof FileSystemSyncAccessHandle ){
if (handle instanceof FileSystemSyncAccessHandle) {
// already a handle is sync handle.
} else if( handle instanceof FileSystemFileHandle ){
} else if (handle instanceof FileSystemFileHandle) {
// handle is an async handle, should convert to sync handle
const fileHandle: FileSystemFileHandle = handle as any;
try {
handle = (await fileHandle.createSyncAccessHandle()) as any;
} catch (e: any) {
throw new Error( e.message + ":" + name );
throw new Error(e.message + ':' + name);
}
} else if( name != null ){
} else if (name != null) {
// should get sync handle from the file name.
try {
const opfsRoot = await navigator.storage.getDirectory();
const fileHandle = await opfsRoot.getFileHandle(name);
handle = (await fileHandle.createSyncAccessHandle()) as any;
} catch (e: any) {
throw new Error( e.message + ":" + name );
throw new Error(e.message + ':' + name);
}
}
}
return handle;
return handle;
}
/** Register a file object URL async */
public async registerFileHandleAsync<HandleType>(
Expand Down Expand Up @@ -625,10 +655,10 @@ export abstract class DuckDBBindingsBase implements DuckDBBindings {
}
/** Enable tracking of file statistics */
public registerOPFSFileName(file: string): Promise<void> {
if (file.startsWith("opfs://")) {
return this.prepareFileHandle(file, DuckDBDataProtocol.BROWSER_FSACCESS);
} else {
throw new Error("Not an OPFS file name: " + file);
if (file.startsWith('opfs://')) {
return this.prepareFileHandle(file, DuckDBDataProtocol.BROWSER_FSACCESS);
} else {
throw new Error('Not an OPFS file name: ' + file);
}
}
public collectFileStatistics(file: string, enable: boolean): void {
Expand Down
6 changes: 5 additions & 1 deletion packages/duckdb-wasm/src/bindings/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,11 @@ export class ResultStreamIterator implements Iterable<Uint8Array> {
/** Reached end of stream? */
_depleted: boolean;

constructor(protected bindings: DuckDBBindings, protected conn: number, protected header: Uint8Array) {
constructor(
protected bindings: DuckDBBindings,
protected conn: number,
protected header: Uint8Array,
) {
this._first = true;
this._depleted = false;
}
Expand Down
6 changes: 3 additions & 3 deletions packages/duckdb-wasm/src/bindings/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ export interface DuckDBRuntime {
openFile(mod: DuckDBModule, fileId: number, flags: FileFlags): void;
syncFile(mod: DuckDBModule, fileId: number): void;
closeFile(mod: DuckDBModule, fileId: number): void;
dropFile(mod: DuckDBModule, fileNamePtr: number, fileNameLen:number): void;
dropFile(mod: DuckDBModule, fileNamePtr: number, fileNameLen: number): void;
getLastFileModificationTime(mod: DuckDBModule, fileId: number): number;
truncateFile(mod: DuckDBModule, fileId: number, newSize: number): void;
readFile(mod: DuckDBModule, fileId: number, buffer: number, bytes: number, location: number): number;
Expand All @@ -162,7 +162,7 @@ export interface DuckDBRuntime {
prepareDBFileHandle?: (path: string, protocol: DuckDBDataProtocol) => Promise<PreparedDBFileHandle[]>;

// Internal API - experimental
progressUpdate(final: number, percentage: number, iteration:number): void;
progressUpdate(final: number, percentage: number, iteration: number): void;

// Call a scalar UDF function
callScalarUDF(
Expand All @@ -184,7 +184,7 @@ export const DEFAULT_RUNTIME: DuckDBRuntime = {
openFile: (_mod: DuckDBModule, _fileId: number, flags: FileFlags): void => {},
syncFile: (_mod: DuckDBModule, _fileId: number): void => {},
closeFile: (_mod: DuckDBModule, _fileId: number): void => {},
dropFile: (_mod: DuckDBModule, _fileNamePtr: number, _fileNameLen:number): void => {},
dropFile: (_mod: DuckDBModule, _fileNamePtr: number, _fileNameLen: number): void => {},
getLastFileModificationTime: (_mod: DuckDBModule, _fileId: number): number => {
return 0;
},
Expand Down
72 changes: 41 additions & 31 deletions packages/duckdb-wasm/src/bindings/runtime_browser.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import {StatusCode} from '../status';
import {
WorkerResponseType,
} from '../parallel/worker_request';
import {addS3Headers, getHTTPUrl} from '../utils';
import { StatusCode } from '../status';
import { WorkerResponseType } from '../parallel/worker_request';
import { addS3Headers, getHTTPUrl } from '../utils';

import {
callSRet,
Expand All @@ -22,7 +20,6 @@ import * as udf from './udf_runtime';
const OPFS_PREFIX_LEN = 'opfs://'.length;
const PATH_SEP_REGEX = /\/|\\/;


export const BROWSER_RUNTIME: DuckDBRuntime & {
_files: Map<string, any>;
_fileInfoCache: Map<number, DuckDBFileInfo>;
Expand Down Expand Up @@ -100,7 +97,7 @@ export const BROWSER_RUNTIME: DuckDBRuntime & {
if (info == null) {
return null;
}
BROWSER_RUNTIME._globalFileInfo = { ...info, blob: null} as DuckDBGlobalFileInfo;
BROWSER_RUNTIME._globalFileInfo = { ...info, blob: null } as DuckDBGlobalFileInfo;

return BROWSER_RUNTIME._globalFileInfo;
} catch (e: any) {
Expand All @@ -111,7 +108,7 @@ export const BROWSER_RUNTIME: DuckDBRuntime & {
async assignOPFSRoot(): Promise<void> {
if (!BROWSER_RUNTIME._opfsRoot) {
BROWSER_RUNTIME._opfsRoot = await navigator.storage.getDirectory();
}
}
},
/** Prepare a file handle that could only be acquired aschronously */
async prepareFileHandles(filePaths: string[], protocol: DuckDBDataProtocol): Promise<PreparedDBFileHandle[]> {
Expand Down Expand Up @@ -157,7 +154,7 @@ export const BROWSER_RUNTIME: DuckDBRuntime & {
fromCached: false,
};
} catch (e: any) {
throw new Error(e.message + ":" + name);
throw new Error(e.message + ':' + name);
}
};
const result: PreparedDBFileHandle[] = [];
Expand Down Expand Up @@ -268,7 +265,6 @@ export const BROWSER_RUNTIME: DuckDBRuntime & {
mod.HEAPF64[(result >> 3) + 1] = 0;
return result;
}

} catch (e: any) {
error = e;
console.warn(`HEAD request with range header failed: ${e}`);
Expand Down Expand Up @@ -318,13 +314,23 @@ export const BROWSER_RUNTIME: DuckDBRuntime & {
}
}

if (xhr.status == 206 && contentLength2 !== null && +contentLength2 == 1 && presumedLength !== null) {
if (
xhr.status == 206 &&
contentLength2 !== null &&
+contentLength2 == 1 &&
presumedLength !== null
) {
const result = mod._malloc(2 * 8);
mod.HEAPF64[(result >> 3) + 0] = +presumedLength;
mod.HEAPF64[(result >> 3) + 1] = 0;
return result;
}
if (xhr.status == 200 && contentLength2 !== null && contentLength !== null && +contentLength2 == +contentLength) {
if (
xhr.status == 200 &&
contentLength2 !== null &&
contentLength !== null &&
+contentLength2 == +contentLength
) {
console.warn(`fall back to full HTTP read for: ${file.dataUrl}`);
const data = mod._malloc(xhr.response.byteLength);
const src = new Uint8Array(xhr.response, 0, xhr.response.byteLength);
Expand Down Expand Up @@ -494,24 +500,24 @@ export const BROWSER_RUNTIME: DuckDBRuntime & {
closeFile: (mod: DuckDBModule, fileId: number) => {
const file = BROWSER_RUNTIME.getFileInfo(mod, fileId);
BROWSER_RUNTIME._fileInfoCache.delete(fileId);
try {
switch (file?.dataProtocol) {
case DuckDBDataProtocol.BUFFER:
case DuckDBDataProtocol.HTTP:
case DuckDBDataProtocol.S3:
break;
case DuckDBDataProtocol.NODE_FS:
case DuckDBDataProtocol.BROWSER_FILEREADER:
// XXX Remove from registry
return;
case DuckDBDataProtocol.BROWSER_FSACCESS: {
const handle: FileSystemSyncAccessHandle = BROWSER_RUNTIME._files?.get(file.fileName);
if (!handle) {
throw new Error(`No OPFS access handle registered with name: ${file.fileName}`);
try {
switch (file?.dataProtocol) {
case DuckDBDataProtocol.BUFFER:
case DuckDBDataProtocol.HTTP:
case DuckDBDataProtocol.S3:
break;
case DuckDBDataProtocol.NODE_FS:
case DuckDBDataProtocol.BROWSER_FILEREADER:
// XXX Remove from registry
return;
case DuckDBDataProtocol.BROWSER_FSACCESS: {
const handle: FileSystemSyncAccessHandle = BROWSER_RUNTIME._files?.get(file.fileName);
if (!handle) {
throw new Error(`No OPFS access handle registered with name: ${file.fileName}`);
}
return handle.flush();
}
return handle.flush();
}
}
} catch (e: any) {
console.log(e);
failWith(mod, e.toString());
Expand Down Expand Up @@ -691,9 +697,13 @@ export const BROWSER_RUNTIME: DuckDBRuntime & {
return 0;
},
progressUpdate: (done: number, percentage: number, repeat: number): void => {
if (postMessage) {
postMessage({requestId: 0, type: WorkerResponseType.PROGRESS_UPDATE, data: {status: done?"completed":"in-progress", percentage: percentage, repetitions: repeat}});
}
if (postMessage) {
postMessage({
requestId: 0,
type: WorkerResponseType.PROGRESS_UPDATE,
data: { status: done ? 'completed' : 'in-progress', percentage: percentage, repetitions: repeat },
});
}
},
checkDirectory: (mod: DuckDBModule, pathPtr: number, pathLen: number) => {
const path = readString(mod, pathPtr, pathLen);
Expand Down
2 changes: 1 addition & 1 deletion packages/duckdb-wasm/src/bindings/runtime_node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export const NODE_RUNTIME: DuckDBRuntime & {
}
return 0;
},
dropFile: (mod: DuckDBModule, _fileNamePtr: number, _fileNameLen:number) => {},
dropFile: (mod: DuckDBModule, _fileNamePtr: number, _fileNameLen: number) => {},
truncateFile: (mod: DuckDBModule, fileId: number, newSize: number) => {
try {
const file = NODE_RUNTIME.resolveFileInfo(mod, fileId);
Expand Down
2 changes: 1 addition & 1 deletion packages/duckdb-wasm/src/log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export type ProgressEntry = {
readonly status: string;
readonly percentage: string;
readonly repetitions: string;
}
};

/** An execution progress handler */
export type ExecutionProgressHandler = (p: ProgressEntry) => void;
Expand Down
Loading