@@ -18,6 +18,7 @@ import { InstantiationProgress } from '../bindings/progress';
1818import { arrowToSQLField } from '../json_typedef' ;
1919import { WebFile } from '../bindings/web_file' ;
2020import { DuckDBDataProtocol } from '../bindings' ;
21+ import { searchOPFSFiles , isOPFSProtocol } from "../utils/opfs_util" ;
2122import { ProgressEntry } from '../log' ;
2223
2324const TEXT_ENCODER = new TextEncoder ( ) ;
@@ -49,6 +50,8 @@ export class AsyncDuckDB implements AsyncDuckDBBindings {
4950 protected _nextMessageId = 0 ;
5051 /** The pending requests */
5152 protected _pendingRequests : Map < number , WorkerTaskVariant > = new Map ( ) ;
53+ /** The DuckDBConfig */
54+ protected _config : DuckDBConfig = { } ;
5255
5356 constructor ( logger : Logger , worker : Worker | null = null ) {
5457 this . _logger = logger ;
@@ -63,6 +66,11 @@ export class AsyncDuckDB implements AsyncDuckDBBindings {
6366 return this . _logger ;
6467 }
6568
69+ /** Get the logger */
70+ public get config ( ) : DuckDBConfig {
71+ return this . _config ;
72+ }
73+
6674 /** Attach to worker */
6775 protected attach ( worker : Worker ) : void {
6876 this . _worker = worker ;
@@ -104,7 +112,7 @@ export class AsyncDuckDB implements AsyncDuckDBBindings {
104112 transfer : ArrayBuffer [ ] = [ ] ,
105113 ) : Promise < WorkerTaskReturnType < W > > {
106114 if ( ! this . _worker ) {
107- console . error ( 'cannot send a message since the worker is not set!' ) ;
115+ console . error ( 'cannot send a message since the worker is not set!:' + task . type + "," + task . data ) ;
108116 return undefined as any ;
109117 }
110118 const mid = this . _nextMessageId ++ ;
@@ -327,8 +335,8 @@ export class AsyncDuckDB implements AsyncDuckDBBindings {
327335 return await this . postTask ( task ) ;
328336 }
329337 /** Try to drop files */
330- public async dropFiles ( ) : Promise < null > {
331- const task = new WorkerTask < WorkerRequestType . DROP_FILES , null , null > ( WorkerRequestType . DROP_FILES , null ) ;
338+ public async dropFiles ( names ?: string [ ] ) : Promise < null > {
339+ const task = new WorkerTask < WorkerRequestType . DROP_FILES , string [ ] | undefined , null > ( WorkerRequestType . DROP_FILES , names ) ;
332340 return await this . postTask ( task ) ;
333341 }
334342 /** Flush all files */
@@ -370,6 +378,7 @@ export class AsyncDuckDB implements AsyncDuckDBBindings {
370378
371379 /** Open a new database */
372380 public async open ( config : DuckDBConfig ) : Promise < void > {
381+ this . _config = config ;
373382 const task = new WorkerTask < WorkerRequestType . OPEN , DuckDBConfig , null > ( WorkerRequestType . OPEN , config ) ;
374383 await this . postTask ( task ) ;
375384 }
@@ -404,6 +413,21 @@ export class AsyncDuckDB implements AsyncDuckDBBindings {
404413
405414 /** Run a query */
406415 public async runQuery ( conn : ConnectionID , text : string ) : Promise < Uint8Array > {
416+ if ( this . shouldOPFSFileHandling ( ) ) {
417+ const files = await this . registerOPFSFileFromSQL ( text ) ;
418+ try {
419+ return await this . _runQueryAsync ( conn , text ) ;
420+ } finally {
421+ if ( files . length > 0 ) {
422+ await this . dropFiles ( files ) ;
423+ }
424+ }
425+ } else {
426+ return await this . _runQueryAsync ( conn , text ) ;
427+ }
428+ }
429+
430+ private async _runQueryAsync ( conn : ConnectionID , text : string ) : Promise < Uint8Array > {
407431 const task = new WorkerTask < WorkerRequestType . RUN_QUERY , [ ConnectionID , string ] , Uint8Array > (
408432 WorkerRequestType . RUN_QUERY ,
409433 [ conn , text ] ,
@@ -416,6 +440,25 @@ export class AsyncDuckDB implements AsyncDuckDBBindings {
416440 conn : ConnectionID ,
417441 text : string ,
418442 allowStreamResult : boolean = false ,
443+ ) : Promise < Uint8Array | null > {
444+ if ( this . shouldOPFSFileHandling ( ) ) {
445+ const files = await this . registerOPFSFileFromSQL ( text ) ;
446+ try {
447+ return await this . _startPendingQueryAsync ( conn , text , allowStreamResult ) ;
448+ } finally {
449+ if ( files . length > 0 ) {
450+ await this . dropFiles ( files ) ;
451+ }
452+ }
453+ } else {
454+ return await this . _startPendingQueryAsync ( conn , text , allowStreamResult ) ;
455+ }
456+ }
457+
458+ private async _startPendingQueryAsync (
459+ conn : ConnectionID ,
460+ text : string ,
461+ allowStreamResult : boolean = false ,
419462 ) : Promise < Uint8Array | null > {
420463 const task = new WorkerTask <
421464 WorkerRequestType . START_PENDING_QUERY ,
@@ -424,6 +467,7 @@ export class AsyncDuckDB implements AsyncDuckDBBindings {
424467 > ( WorkerRequestType . START_PENDING_QUERY , [ conn , text , allowStreamResult ] ) ;
425468 return await this . postTask ( task ) ;
426469 }
470+
427471 /** Poll a pending query */
428472 public async pollPendingQuery ( conn : ConnectionID ) : Promise < Uint8Array | null > {
429473 const task = new WorkerTask < WorkerRequestType . POLL_PENDING_QUERY , ConnectionID , Uint8Array | null > (
@@ -657,4 +701,26 @@ export class AsyncDuckDB implements AsyncDuckDBBindings {
657701 ) ;
658702 await this . postTask ( task ) ;
659703 }
704+
705+ private shouldOPFSFileHandling ( ) :boolean {
706+ if ( isOPFSProtocol ( this . config . path ?? "" ) ) {
707+ return this . config . opfs ?. fileHandling == "auto" ;
708+ }
709+ return false ;
710+ }
711+
712+ private async registerOPFSFileFromSQL ( text : string ) {
713+ const files = searchOPFSFiles ( text ) ;
714+ const result : string [ ] = [ ] ;
715+ for ( const file of files ) {
716+ try {
717+ await this . registerOPFSFileName ( file ) ;
718+ result . push ( file ) ;
719+ } catch ( e ) {
720+ console . error ( e ) ;
721+ throw new Error ( "File Not found:" + file ) ;
722+ }
723+ }
724+ return result ;
725+ }
660726}
0 commit comments