andpor/react-native-sqlite-storage

deleteDatabase() does not delete journal files on iOS

Opened this issue · 0 comments

I know this module isn't really being maintained anymore, but thought people should know...

If you're trying to delete your database in order to replace it with a new one, iOS may give you a database corrupt error when you try to open the new one.

Specifically: On iOS calling this module's deleteDatabase("yourDbName") method will delete the database file, but will not delete its accomapying journal file(s) and other temporary files.

Expected Behavior

deleteDatabase("yourDbName") should also delete any database journal files. The possible files depend on the database's PRAGMA journal_mode...

  • If the journal_mode is set to "journal" then there may be file yourDbName-journal
  • If the journal mode is "wal" then there may be files yourDbName-wal and yourDbName-shm

According to the SQLite docs there may be other temporary database files.

Current Behavior

In the module's Andriod native code all database files seem to be deleted using the system API, but on iOS the module's native code is just deleting the main database file. Journal files are left in place.

Possible Solutions

  1. In RN JavaScript we could delete any database files before opening our replacement database with SQLite.openDatabase(). It may not be easy to find them all, since the docs say there are nine kinds of temporary files, and it doesn't give precise filenames for some of them. But journal, wal and shm files are easily located though. Deleting these may be enough for most use-cases.

  2. A more reliable solution: Maybe iOS has a SQLite API method similar to Android's android.database.sqlite.SQLiteDatabase.deleteDatabase()?
    I can't find any docs whatsoever on iOS sqlite3 API for obj-c, but it it appears to follow the SQLite C interface. It looks like resetting the database is a way of removing temporary files.

  3. Perhaps it can be done in JavaScript with: open db → vacuum db → close db → delete database file

Steps to Reproduce

  • Open your react-native app on iOS
  • Open database with const db = await SQLiteStorage.openDatabase(dbName)
  • Close database with await db.close(). The journal file(s) should now be there beside the main db file.
  • Delete database with const deleteResult = await SQLiteStorage.deleteDatabase(dbName)
  • Get a folder listing of the database folder. On iOS the journal files will still be there. On Android they'll be gone.

Context

After an app update our app often needs to replace a database during the app's startup. When we do this on iOS we sometimes get a database corrupt error in the XCode console. The problem is resolved when we manually delete the old journal files before opening the new database (although this might not be 100% reliable).

Your Environment

  • SQLite PRAGMA journal_mode: "wal"
  • React Native SQLite Storage Version used: 6.0.1
  • React Native version used: 66.5
  • Operating System and version (simulator or device): iPhone 8 (iOS 16.7.10), iPhone 13 Pro (iOS 18.1.1)
  • IDE used: XCode