nolanlawson / cordova-plugin-sqlite-2

Native SQLite database API for Cordova/PhoneGap/Ionic, modeled after WebSQL (UNMAINTAINED)
https://nolanlawson.com/2016/04/10/introducing-the-cordova-sqlite-plugin-2/
Apache License 2.0
168 stars 28 forks source link

Database not migrated after app update? (Data loss after update) #80

Open knubie opened 3 years ago

knubie commented 3 years ago

I've had several users recently report that they lost all of their data after updating the app. I found this answer from stackoverflow very concerning:

There are scenarios where this gets even more complex. When an application is updated it is installed into a new location with a new application container path. Data inside the old application container is migrated. There are few guarantees regarding what may or may not be migrated as part of the update process. It may be everything, it may be only some things. In particular there are is no guidance concerning how files or directories marked with the NSURLIsExcludedFromBackupKey resource attribute will be treated. In practice it seems that these are often the least likely files to be migrated, and when they are migrated the NSURLIsExcludedFromBackupKey attribute is rarely preserved.

What is the reason for marking the db directory as NSURLIsExcludedFromBackupKey?

nolanlawson commented 3 years ago

Honestly I can't recall why I set that value. Looks like cordova-sqlite-storage made this optional.

knubie commented 3 years ago

Have you ever experienced the issue I mentioned where the db file was not migrated over with an app update? I'm not certain that that's what's happening in my case, but this is the closest match I could find to a possibility. BTW that SO answer is 6+ years old and I'm not even sure if it's really true or not.

knubie commented 3 years ago

Well, I found this thread https://github.com/storesafe/cordova-sqlite-storage/issues/430 which references this 5 year old article from Apple which advises never to store a sqlite store file in iCloud (why this is the case is not really explained in the article). But it seems that some people were getting their app rejected over this.

knubie commented 2 years ago

I reached out to Apple about this and referenced that article, and this is what the had to say:

First, it seems like you are confused about iCloud storage API and iCloud backup. The link you cited is about iCloud storage API, which developers can use to synchronize files across devices on demand, while NSURLIsExcludedFromBackupKey is about iCloud backup, which is a system feature that can back up your device to iCloud. Setting NSURLIsExcludedFromBackupKey to true tells the system to ignore the URL when backing up the device; it doesn’t have any impact on iCloud synchronization.

So it seems like the NSURLIsExcludedFromBackupKey is not really necessary here.

cmaas commented 2 years ago

A few years back the recommendation was to not store downloaded content / cached stuff in iCloud backups. In addition, many apps use remote servers to store user data and the SQLite database is just an offline-cache or something like that. As far as I can tell, cordova plugins using SQLite just tried to store temporary data in SQLite and were rejected for this. Hence, NSURLIsExcludedFromBackupKey is set to YES.

But if your app uses SQLite for user data, especially as the sole database in a local-only or offline-first app, it's totally fine and actually expected to have the SQLite database be backed up to iCloud.

I had people who restored their data from an iCloud backup after getting a new phone lose all of their data, because NSURLIsExcludedFromBackupKey was set to YES initially. I changed it to NO.

I'd appreciate an option in the plugin to make this configurable, preferrably using NO as the default value.

Furthermore, I'd suggest to actually set NO explicitly so that existing SQLite database files are included in future iCloud backups. If you never set NO and just have the code that sets YES removed, I think the existing files might still have this flag.

Pseudo-code to make this more understandable:

// don't do this:
if (options.excludeFromBackupKey) {
  NSURLIsExcludedFromBackupKey = 'YES'
}

// do this to set proper flags for existing files:
if (options.excludeFromBackupKey) {
  NSURLIsExcludedFromBackupKey = 'YES'
}
else {
  NSURLIsExcludedFromBackupKey = 'NO'
}