@@ -15,6 +15,7 @@ import {
15
15
} from './runtime' ;
16
16
import { DuckDBModule } from './duckdb_module' ;
17
17
import * as udf from './udf_runtime' ;
18
+ import { DuckDBAccessMode } from './config' ;
18
19
19
20
const OPFS_PREFIX_LEN = 'opfs://' . length ;
20
21
const PATH_SEP_REGEX = / \/ | \\ / ;
@@ -110,8 +111,11 @@ export const BROWSER_RUNTIME: DuckDBRuntime & {
110
111
BROWSER_RUNTIME . _opfsRoot = await navigator . storage . getDirectory ( ) ;
111
112
}
112
113
} ,
113
- /** Prepare a file handle that could only be acquired aschronously */
114
- async prepareFileHandles ( filePaths : string [ ] , protocol : DuckDBDataProtocol ) : Promise < PreparedDBFileHandle [ ] > {
114
+ /** Prepare a file handle that could only be acquired asynchronously */
115
+ async prepareFileHandles ( filePaths : string [ ] , protocol : DuckDBDataProtocol , accessMode ?: DuckDBAccessMode ) : Promise < PreparedDBFileHandle [ ] > {
116
+ // DuckDBAccessMode.UNDEFINED will be treated as READ_WRITE
117
+ // See: https://github.com/duckdb/duckdb/blob/5f5512b827df6397afd31daedb4bbdee76520019/src/main/database.cpp#L442-L444
118
+ const isReadWrite = ! accessMode || accessMode === DuckDBAccessMode . READ_WRITE ;
115
119
if ( protocol === DuckDBDataProtocol . BROWSER_FSACCESS ) {
116
120
await BROWSER_RUNTIME . assignOPFSRoot ( ) ;
117
121
const prepare = async ( path : string ) : Promise < PreparedDBFileHandle > => {
@@ -135,13 +139,16 @@ export const BROWSER_RUNTIME: DuckDBRuntime & {
135
139
}
136
140
// mkdir -p
137
141
for ( const folder of folders ) {
138
- dirHandle = await dirHandle . getDirectoryHandle ( folder , { create : true } ) ;
142
+ dirHandle = await dirHandle . getDirectoryHandle ( folder , { create : isReadWrite } ) ;
139
143
}
140
144
}
141
145
const fileHandle = await dirHandle . getFileHandle ( fileName , { create : false } ) . catch ( e => {
142
146
if ( e ?. name === 'NotFoundError' ) {
143
- console . debug ( `File ${ path } does not exists yet, creating...` ) ;
144
- return dirHandle . getFileHandle ( fileName , { create : true } ) ;
147
+ if ( isReadWrite ) {
148
+ console . debug ( `File ${ path } does not exists yet, creating...` ) ;
149
+ return dirHandle . getFileHandle ( fileName , { create : true } ) ;
150
+ }
151
+ console . debug ( `File ${ path } does not exists, aborting as we are in read-only mode` ) ;
145
152
}
146
153
throw e ;
147
154
} ) ;
@@ -166,11 +173,11 @@ export const BROWSER_RUNTIME: DuckDBRuntime & {
166
173
}
167
174
throw new Error ( `Unsupported protocol ${ protocol } for paths ${ filePaths } with protocol ${ protocol } ` ) ;
168
175
} ,
169
- /** Prepare a file handle that could only be acquired aschronously */
170
- async prepareDBFileHandle ( dbPath : string , protocol : DuckDBDataProtocol ) : Promise < PreparedDBFileHandle [ ] > {
176
+ /** Prepare a file handle that could only be acquired asynchronously */
177
+ async prepareDBFileHandle ( dbPath : string , protocol : DuckDBDataProtocol , accessMode ?: DuckDBAccessMode ) : Promise < PreparedDBFileHandle [ ] > {
171
178
if ( protocol === DuckDBDataProtocol . BROWSER_FSACCESS && this . prepareFileHandles ) {
172
179
const filePaths = [ dbPath , `${ dbPath } .wal` ] ;
173
- return this . prepareFileHandles ( filePaths , protocol ) ;
180
+ return this . prepareFileHandles ( filePaths , protocol , accessMode ) ;
174
181
}
175
182
throw new Error ( `Unsupported protocol ${ protocol } for path ${ dbPath } with protocol ${ protocol } ` ) ;
176
183
} ,
0 commit comments