Skip to content

Commit da13cf0

Browse files
committed
Add support for opening regular files with idbvfs
1 parent 30abb7b commit da13cf0

3 files changed

Lines changed: 94 additions & 22 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
## [Unreleased](https://github.com/gilzoide/unity-sqlite-net/compare/1.3.2...HEAD)
33
### Fixed
44
- SQLiteException that were storing "not an error" messages now has the correct error messages
5+
- Support for opening single file databases in WebGL with idbvfs
56

67

78
## [1.3.2](https://github.com/gilzoide/unity-sqlite-net/tree/1.3.2)

Plugins/idbvfs/idbvfs.cpp

Lines changed: 91 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,19 @@ static void TRACE_LOG(const char *fmt, ...) {
7272

7373
using namespace sqlitevfs;
7474

75+
76+
/// Checks whether zName is a path to a regular file
77+
static bool isRegularFile(const char *zName) {
78+
struct stat st;
79+
if (stat(zName, &st) == 0) {
80+
if (S_ISREG(st.st_mode)) {
81+
return true;
82+
}
83+
}
84+
return false;
85+
}
86+
87+
7588
class IdbPage {
7689
public:
7790
IdbPage() {}
@@ -90,8 +103,7 @@ class IdbPage {
90103
}
91104

92105
bool exists() const {
93-
if (FILE *f = fopen(filename.c_str(), "r")) {
94-
fclose(f);
106+
if (isRegularFile(filename.c_str())) {
95107
return true;
96108
}
97109
else {
@@ -164,11 +176,7 @@ class IdbPage {
164176

165177
struct IdbFileSize : public IdbPage {
166178
IdbFileSize() : IdbPage() {}
167-
IdbFileSize(sqlite3_filename file_name, bool autoload = true) : IdbPage(file_name, IDBVFS_SIZE_KEY) {
168-
if (autoload) {
169-
load();
170-
}
171-
}
179+
IdbFileSize(sqlite3_filename file_name) : IdbPage(file_name, IDBVFS_SIZE_KEY) {}
172180

173181
void load() {
174182
scan_into("%lu", &file_size);
@@ -210,28 +218,49 @@ struct IdbFile : public SQLiteFileImpl {
210218
sqlite3_filename file_name;
211219
IdbFileSize file_size;
212220
std::vector<uint8_t> journal_data;
221+
FILE *regular_file;
213222
bool is_db;
214223

215224
IdbFile() {}
216-
IdbFile(sqlite3_filename file_name, bool is_db) : file_name(file_name), file_size(file_name), is_db(is_db) {}
225+
IdbFile(sqlite3_filename file_name, bool is_db)
226+
: file_name(file_name)
227+
, file_size(file_name)
228+
, is_db(is_db)
229+
{
230+
if (isRegularFile(file_name)) {
231+
regular_file = fopen(file_name, "r+");
232+
}
233+
else {
234+
regular_file = nullptr;
235+
file_size.load();
236+
}
237+
}
217238

218239
int iVersion() const override {
219240
return 1;
220241
}
221242

222243
int xClose() override {
244+
if (regular_file) {
245+
fclose(regular_file);
246+
}
223247
return SQLITE_OK;
224248
}
225249

226250
int xRead(void *p, int iAmt, sqlite3_int64 iOfst) override {
227251
TRACE_LOG("READ %s %d @ %ld", file_name, iAmt, iOfst);
228-
if (iAmt + iOfst > file_size.get()) {
229-
TRACE_LOG(" > %d", false);
230-
return SQLITE_IOERR_SHORT_READ;
231-
}
232-
233252
int result;
234-
if (is_db) {
253+
if (regular_file) {
254+
fseek(regular_file, iOfst, SEEK_SET);
255+
size_t bytes_read = fread(p, 1, iAmt, regular_file);
256+
if (bytes_read < iAmt) {
257+
result = SQLITE_IOERR_SHORT_READ;
258+
}
259+
else {
260+
result = SQLITE_OK;
261+
}
262+
}
263+
else if (is_db) {
235264
result = readDb(p, iAmt, iOfst);
236265
}
237266
else {
@@ -244,7 +273,17 @@ struct IdbFile : public SQLiteFileImpl {
244273
int xWrite(const void *p, int iAmt, sqlite3_int64 iOfst) override {
245274
TRACE_LOG("WRITE %s %d @ %ld", file_name, iAmt, iOfst);
246275
int result;
247-
if (is_db) {
276+
if (regular_file) {
277+
fseek(regular_file, iOfst, SEEK_SET);
278+
size_t stored_bytes = fwrite(p, 1, iAmt, regular_file);
279+
if (stored_bytes < iAmt) {
280+
result = SQLITE_IOERR_WRITE;
281+
}
282+
else {
283+
result = SQLITE_OK;
284+
}
285+
}
286+
else if (is_db) {
248287
result = writeDb(p, iAmt, iOfst);
249288
}
250289
else {
@@ -256,8 +295,14 @@ struct IdbFile : public SQLiteFileImpl {
256295

257296
int xTruncate(sqlite3_int64 size) override {
258297
TRACE_LOG("TRUNCATE %s to %ld", file_name, size);
259-
file_size.set(size);
260-
TRACE_LOG(" > %d", true);
298+
if (regular_file) {
299+
int fd = fileno(regular_file);
300+
ftruncate(fd, size);
301+
}
302+
else {
303+
file_size.set(size);
304+
}
305+
TRACE_LOG(" > %d", SQLITE_OK);
261306
return SQLITE_OK;
262307
}
263308

@@ -269,7 +314,13 @@ struct IdbFile : public SQLiteFileImpl {
269314
file.store(journal_data);
270315
file_size.set(journal_data.size());
271316
}
272-
bool success = file_size.sync();
317+
bool success;
318+
if (regular_file) {
319+
success = fflush(regular_file) == 0 && fsync(fileno(regular_file)) == 0;
320+
}
321+
else {
322+
success = file_size.sync();
323+
}
273324
INLINE_JS({
274325
Module.idbvfsSyncfs();
275326
});
@@ -279,7 +330,11 @@ struct IdbFile : public SQLiteFileImpl {
279330

280331
int xFileSize(sqlite3_int64 *pSize) override {
281332
TRACE_LOG("FILE SIZE %s", file_name);
282-
if (!journal_data.empty()) {
333+
if (regular_file) {
334+
fseek(regular_file, 0, SEEK_END);
335+
*pSize = ftell(regular_file);
336+
}
337+
else if (!journal_data.empty()) {
283338
*pSize = journal_data.size();
284339
}
285340
else {
@@ -391,7 +446,16 @@ struct IdbVfs : public SQLiteVfsImpl<IdbFile> {
391446

392447
int xDelete(const char *zName, int syncDir) override {
393448
TRACE_LOG("DELETE %s", zName);
394-
IdbFileSize file_size(zName, false);
449+
if (isRegularFile(zName)) {
450+
if (unlink(zName) == 0) {
451+
return SQLITE_OK;
452+
}
453+
else {
454+
return SQLITE_IOERR_DELETE;
455+
}
456+
}
457+
458+
IdbFileSize file_size(zName);
395459
if (!file_size.remove()) {
396460
return SQLITE_IOERR_DELETE;
397461
}
@@ -412,8 +476,13 @@ struct IdbVfs : public SQLiteVfsImpl<IdbFile> {
412476
case SQLITE_ACCESS_EXISTS:
413477
case SQLITE_ACCESS_READWRITE:
414478
case SQLITE_ACCESS_READ:
415-
IdbFileSize file_size(zName, false);
416-
*pResOut = file_size.exists();
479+
if (isRegularFile(zName)) {
480+
*pResOut = 1;
481+
}
482+
else {
483+
IdbFileSize file_size(zName);
484+
*pResOut = file_size.exists();
485+
}
417486
TRACE_LOG(" > %d", *pResOut);
418487
return SQLITE_OK;
419488
}

Plugins/idbvfs/idbvfs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
*
2929
* For more information, please refer to <http://unlicense.org/>
3030
*/
31+
#pragma once
32+
3133
#ifdef __cplusplus
3234
extern "C" {
3335
#endif

0 commit comments

Comments
 (0)