Mobile: Fixes #11571: Use alternative fix to set the sqlite CursorWindow size to 50mb #11726
+48
−13
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There is an issue that on certain Android devices, it is possible to get the "Row too big to fit into CursorWindow" error when synchronizing and handling notes which are large in size (at least 1-2mb depending on whether E2E encryption is enabled and the version of Android). This is due to a limitation which is put in place in the Android versions of sqlite specifically. Attempts have been made to workaround this in the past by a change to MainApplication.kt, but unfortunately some users report the issue still occurring.
On my own device (a Samsung Galaxy S9+ on Android 10) I can reproduce the "Row too big to fit into CursorWindow" error by importing a large note which is over 4mb in size and then deleting it (among other ways to produce the error). The example I have been using for this is big.jex (attached at the bottom). Upon deletion of the imported note, I am presented with an alert saying: "This note could not be deleted: On query {"sql":"SELECT * FROM
notes
WHERE id IN ('xxxxxxxxxxxxxxxxxxxxxxx')","params":[]}: Row too big to fit into CursorWindow requiredPos=0, totalRows=1".If I do the same on Android 10 on emulator, I get no error, which is evidence that the workaround in MainApplication.kt is working correctly on some devices.
From testing via hacked versions of the Joplin app which I built, I have confirmed that the logic for extending the CursorWindow size in MainApplication.kt executes without errors on my device (where the workaround does not work). The value of the sCursorWindowSize field on the android.database.CursorWindow class is indeed changed to the desired value via reflection. However, the CursorWindow size used by sqlite queries throughout the application in practice is not extended, when running on my device. This is despite the fact that when I write the sqlite version on my device to the log, it returns v3.22.0, which is the expected version for API 29, as per the documentation here https://developer.android.com/reference/android/database/sqlite/package-summary . This page also specifies that the vendor may include their own version of sqlite on the device instead, so although the version specified is the same, the binary still may be a custom build.
I believe the issue occurs on some devices, because the version of sqlite included with the device does not make use of a Cursor implementation which makes use of the CursorWindow class. To ensure that the desired cursor window size is always used, the change can be made at a lower level by patching the react-native-sqlite-storage code to use the new constructor available in api 28 and above. The patch also includes logic to not make use of this new constructor when the api level is below 28 (increasing the cursor size is not supported on versions lower than this anyway), to avoid breaking the code on older devices. There is also only a need to patch the SQLitePlugin class used for the device version of sqlite, because if you use the native sqlite mode of this library, there is no such limitation of cursor window size being enforced. However using the native sqlite mode is not the best option, as the sqlite version is not the most up to date and some users have reported issues with it not working on their device.
Testing:
I have verified that this patch to react-native-sqlite-storage does indeed fix the issue on my device, as when using this version, I am able to import big.jex, view it and delete it without issues or errors in the log. This signifies that increasing the CursorWindow size has indeed worked. Also browsing, opening, editing and tagging notes all work as normal. I have also tested the change using the app on emulator using Android O (API 27) and can confirm that browsing, opening, editing and tagging notes all work as normal, meaning the logic to only apply the workaround if API level is 28 or above is working.
big.zip