Skip to content

Commit 3fd50dc

Browse files
committed
Merge remote-tracking branch 'duckdb/main' into v1.2-histrionicus
2 parents 0e4f827 + 7f4ae76 commit 3fd50dc

File tree

9 files changed

+93
-2
lines changed

9 files changed

+93
-2
lines changed

lib/include/duckdb/web/webdb.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ class WebDB {
3333
public:
3434
/// A connection
3535
class Connection {
36+
friend WebDB;
37+
3638
protected:
3739
/// The webdb
3840
WebDB& webdb_;

lib/src/webdb.cc

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
#include "duckdb/web/webdb.h"
44

5+
#include <emscripten/val.h>
6+
57
#include <chrono>
68
#include <cstddef>
79
#include <cstdio>
@@ -783,11 +785,53 @@ std::string WebDB::Tokenize(std::string_view text) {
783785
/// Get the version
784786
std::string_view WebDB::GetVersion() { return database_->LibraryVersion(); }
785787

788+
class ProgressBarCustom : public ProgressBarDisplay {
789+
double value{0.0};
790+
double times{0.0};
791+
double to_send{1.0};
792+
793+
public:
794+
ProgressBarCustom() {
795+
value = 0.0;
796+
times = 0.0;
797+
to_send = 1.0;
798+
}
799+
~ProgressBarCustom() {}
800+
static void SendMessage(double end, double percentage, double times) {
801+
emscripten::val::global("DUCKDB_RUNTIME").call<void>("progressUpdate", end ? 1.0 : 0.0, percentage, times);
802+
}
803+
804+
public:
805+
void Update(double percentage) {
806+
if (percentage >= value + 1.0) {
807+
value = percentage;
808+
times = 1.0;
809+
SendMessage(false, percentage, times);
810+
to_send = 10.0;
811+
} else {
812+
times += 1.0;
813+
if (times >= to_send) {
814+
SendMessage(false, percentage, times);
815+
to_send *= 10.0;
816+
}
817+
}
818+
}
819+
void Finish() {
820+
SendMessage(true, value, times);
821+
value = 0.0;
822+
times = 0.0;
823+
to_send = 1.0;
824+
}
825+
static unique_ptr<ProgressBarDisplay> GetProgressBar() { return make_uniq<ProgressBarCustom>(); }
826+
};
827+
786828
/// Create a session
787829
WebDB::Connection* WebDB::Connect() {
788830
auto conn = duckdb::make_uniq<WebDB::Connection>(*this);
789831
auto conn_ptr = conn.get();
790832
connections_.insert({conn_ptr, std::move(conn)});
833+
ClientConfig::GetConfig(*conn_ptr->connection_.context).wait_time = 1;
834+
ClientConfig::GetConfig(*conn_ptr->connection_.context).display_create_func = ProgressBarCustom::GetProgressBar;
791835
return conn_ptr;
792836
}
793837

packages/duckdb-wasm/src/bindings/connection.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,14 @@ export class DuckDBConnection {
4646
resolve(this._bindings.pollPendingQuery(this._conn));
4747
} catch (e: any) {
4848
console.log(e);
49-
reject(e);
49+
// If the worker is not set, the worker has been terminated
50+
if (e.message.includes('worker is not set!')) {
51+
reject(new Error('Worker has been terminated'));
52+
} else {
53+
//Otherwise, reject with the error
54+
reject(e);
55+
}
56+
5057
}
5158
});
5259
}

packages/duckdb-wasm/src/bindings/runtime.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ export interface DuckDBRuntime {
161161
prepareFileHandles?: (path: string[], protocol: DuckDBDataProtocol) => Promise<PreparedDBFileHandle[]>;
162162
prepareDBFileHandle?: (path: string, protocol: DuckDBDataProtocol) => Promise<PreparedDBFileHandle[]>;
163163

164+
// Internal API - experimental
165+
progressUpdate(final: number, percentage: number, iteration:number): void;
166+
164167
// Call a scalar UDF function
165168
callScalarUDF(
166169
mod: DuckDBModule,
@@ -185,6 +188,9 @@ export const DEFAULT_RUNTIME: DuckDBRuntime = {
185188
getLastFileModificationTime: (_mod: DuckDBModule, _fileId: number): number => {
186189
return 0;
187190
},
191+
progressUpdate: (_final: number, _percentage: number, _iteration: number): void => {
192+
return;
193+
},
188194
truncateFile: (_mod: DuckDBModule, _fileId: number, _newSize: number): void => {},
189195
readFile: (_mod: DuckDBModule, _fileId: number, _buffer: number, _bytes: number, _location: number): number => {
190196
return 0;

packages/duckdb-wasm/src/bindings/runtime_browser.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import {StatusCode} from '../status';
2+
import {
3+
WorkerResponseType,
4+
} from '../parallel/worker_request';
25
import {addS3Headers, getHTTPUrl} from '../utils';
36

47
import {
@@ -687,6 +690,11 @@ export const BROWSER_RUNTIME: DuckDBRuntime & {
687690
}
688691
return 0;
689692
},
693+
progressUpdate: (done: number, percentage: number, repeat: number): void => {
694+
if (postMessage) {
695+
postMessage({requestId: 0, type: WorkerResponseType.PROGRESS_UPDATE, data: {status: done?"completed":"in-progress", percentage: percentage, repetitions: repeat}});
696+
}
697+
},
690698
checkDirectory: (mod: DuckDBModule, pathPtr: number, pathLen: number) => {
691699
const path = readString(mod, pathPtr, pathLen);
692700
console.log(`checkDirectory: ${path}`);

packages/duckdb-wasm/src/bindings/runtime_node.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,9 @@ export const NODE_RUNTIME: DuckDBRuntime & {
197197
}
198198
return 0;
199199
},
200+
progressUpdate: (_final: number, _percentage: number, _iteration: number): void => {
201+
return;
202+
},
200203
getLastFileModificationTime: (mod: DuckDBModule, fileId: number) => {
201204
try {
202205
const file = NODE_RUNTIME.resolveFileInfo(mod, fileId);

packages/duckdb-wasm/src/log.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ export type LogEntry<O, T, E, V> = {
4141
readonly value: V;
4242
};
4343

44+
export type ProgressEntry = {
45+
readonly status: string;
46+
readonly percentage: string;
47+
readonly repetitions: string;
48+
}
49+
50+
/** An execution progress handler */
51+
export type ExecutionProgressHandler = (p: ProgressEntry) => void;
52+
4453
export type LogEntryVariant =
4554
| LogEntry<LogOrigin.BINDINGS, LogTopic.INSTANTIATE, LogEvent.ERROR, string>
4655
| LogEntry<LogOrigin.BINDINGS, LogTopic.QUERY, LogEvent.START, void>

packages/duckdb-wasm/src/parallel/async_bindings.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { InstantiationProgress } from '../bindings/progress';
1818
import { arrowToSQLField } from '../json_typedef';
1919
import { WebFile } from '../bindings/web_file';
2020
import { DuckDBDataProtocol } from '../bindings';
21+
import { ProgressEntry } from '../log';
2122

2223
const TEXT_ENCODER = new TextEncoder();
2324

@@ -32,6 +33,9 @@ export class AsyncDuckDB implements AsyncDuckDBBindings {
3233
/** Instantiate the module */
3334
protected _onInstantiationProgress: ((p: InstantiationProgress) => void)[] = [];
3435

36+
/** Progress callbacks */
37+
protected _onExecutionProgress: ((p: ProgressEntry) => void)[] = [];
38+
3539
/** The logger */
3640
protected readonly _logger: Logger;
3741
/** The worker */
@@ -122,6 +126,12 @@ export class AsyncDuckDB implements AsyncDuckDBBindings {
122126
const response = event.data as WorkerResponseVariant;
123127
switch (response.type) {
124128
// Request failed?
129+
case WorkerResponseType.PROGRESS_UPDATE: {
130+
for (const p of this._onExecutionProgress) {
131+
p(response.data);
132+
}
133+
return;
134+
}
125135
case WorkerResponseType.LOG: {
126136
this._logger.log(response.data);
127137
return;

packages/duckdb-wasm/src/parallel/worker_request.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { CSVInsertOptions, JSONInsertOptions, ArrowInsertOptions } from '../bindings/insert_options';
2-
import { LogEntryVariant } from '../log';
2+
import { LogEntryVariant, ProgressEntry } from '../log';
33
import { ScriptTokens } from '../bindings/tokens';
44
import { FileStatistics } from '../bindings/file_stats';
55
import { DuckDBConfig } from '../bindings/config';
@@ -57,6 +57,7 @@ export enum WorkerResponseType {
5757
FILE_STATISTICS = 'FILE_STATISTICS',
5858
INSTANTIATE_PROGRESS = 'INSTANTIATE_PROGRESS',
5959
LOG = 'LOG',
60+
PROGRESS_UPDATE = 'PROGRESS_UPDATE',
6061
OK = 'OK',
6162
PREPARED_STATEMENT_ID = 'PREPARED_STATEMENT_ID',
6263
QUERY_PLAN = 'QUERY_PLAN',
@@ -154,6 +155,7 @@ export type WorkerResponseVariant =
154155
| WorkerResponse<WorkerResponseType.FILE_STATISTICS, FileStatistics>
155156
| WorkerResponse<WorkerResponseType.INSTANTIATE_PROGRESS, InstantiationProgress>
156157
| WorkerResponse<WorkerResponseType.LOG, LogEntryVariant>
158+
| WorkerResponse<WorkerResponseType.PROGRESS_UPDATE, ProgressEntry>
157159
| WorkerResponse<WorkerResponseType.OK, null>
158160
| WorkerResponse<WorkerResponseType.PREPARED_STATEMENT_ID, number>
159161
| WorkerResponse<WorkerResponseType.QUERY_PLAN, Uint8Array>

0 commit comments

Comments
 (0)