diff --git a/app/src/main/java/eu/faircode/email/DB.java b/app/src/main/java/eu/faircode/email/DB.java
index af9a94bc7b..850da9aabb 100644
--- a/app/src/main/java/eu/faircode/email/DB.java
+++ b/app/src/main/java/eu/faircode/email/DB.java
@@ -6,6 +6,7 @@ import android.app.ActivityManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabaseCorruptException;
import android.net.Uri;
import android.os.Build;
import android.text.TextUtils;
@@ -142,16 +143,39 @@ public abstract class DB extends RoomDatabase {
@Override
public void init(@NonNull DatabaseConfiguration configuration) {
- // https://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint
- if (BuildConfig.DEBUG) {
- File dbfile = configuration.context.getDatabasePath(DB_NAME);
- if (dbfile.exists()) {
- try (SQLiteDatabase db = SQLiteDatabase.openDatabase(dbfile.getPath(), null, SQLiteDatabase.OPEN_READWRITE)) {
- Log.i("Set PRAGMA wal_autocheckpoint=" + DB_CHECKPOINT);
- try (Cursor cursor = db.rawQuery("PRAGMA wal_autocheckpoint=" + DB_CHECKPOINT + ";", null)) {
- cursor.moveToNext(); // required
+ File dbfile = configuration.context.getDatabasePath(DB_NAME);
+
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(configuration.context);
+ boolean sqlite_integrity_check = prefs.getBoolean("sqlite_integrity_check", true);
+
+ // https://www.sqlite.org/pragma.html#pragma_integrity_check
+ if (sqlite_integrity_check && dbfile.exists()) {
+ String check = (Helper.isRedmiNote() || Helper.isOnePlus() || BuildConfig.DEBUG
+ ? "integrity_check" : "quick_check");
+ try (SQLiteDatabase db = SQLiteDatabase.openDatabase(dbfile.getPath(), null, SQLiteDatabase.OPEN_READWRITE)) {
+ Log.i("PRAGMA " + check);
+ try (Cursor cursor = db.rawQuery("PRAGMA " + check + ";", null)) {
+ while (cursor.moveToNext()) {
+ String line = cursor.getString(0);
+ if ("ok".equals(line))
+ Log.i("PRAGMA " + check + "=" + line);
+ else
+ Log.e("PRAGMA " + check + "=" + line);
}
}
+ } catch (SQLiteDatabaseCorruptException ex) {
+ Log.e(ex);
+ dbfile.delete();
+ }
+ }
+
+ // https://www.sqlite.org/pragma.html#pragma_wal_autocheckpoint
+ if (BuildConfig.DEBUG && dbfile.exists()) {
+ try (SQLiteDatabase db = SQLiteDatabase.openDatabase(dbfile.getPath(), null, SQLiteDatabase.OPEN_READWRITE)) {
+ Log.i("Set PRAGMA wal_autocheckpoint=" + DB_CHECKPOINT);
+ try (Cursor cursor = db.rawQuery("PRAGMA wal_autocheckpoint=" + DB_CHECKPOINT + ";", null)) {
+ cursor.moveToNext(); // required
+ }
}
}
diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java b/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java
index 758b82af66..673e67c09b 100644
--- a/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java
+++ b/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java
@@ -164,6 +164,7 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
private TextView tvRoomQueryThreads;
private SeekBar sbRoomQueryThreads;
private ImageButton ibRoom;
+ private SwitchCompat swIntegrity;
private SwitchCompat swWal;
private SwitchCompat swCheckpoints;
private SwitchCompat swAnalyze;
@@ -238,8 +239,8 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
"watchdog", "experiments", "main_log", "protocol", "log_level", "debug", "leak_canary",
"test1", "test2", "test3", "test4", "test5",
"work_manager", // "external_storage",
- "query_threads", "wal",
- "sqlite_checkpoints", "sqlite_analyze", "sqlite_auto_vacuum", "sqlite_sync_extra", "sqlite_cache",
+ "query_threads",
+ "sqlite_integrity_check", "wal", "sqlite_checkpoints", "sqlite_analyze", "sqlite_auto_vacuum", "sqlite_sync_extra", "sqlite_cache",
"chunk_size", "thread_range", "undo_manager",
"webview_legacy", "browser_zoom", "fake_dark",
"show_recent",
@@ -363,6 +364,7 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
tvRoomQueryThreads = view.findViewById(R.id.tvRoomQueryThreads);
sbRoomQueryThreads = view.findViewById(R.id.sbRoomQueryThreads);
ibRoom = view.findViewById(R.id.ibRoom);
+ swIntegrity = view.findViewById(R.id.swIntegrity);
swWal = view.findViewById(R.id.swWal);
swCheckpoints = view.findViewById(R.id.swCheckpoints);
swAnalyze = view.findViewById(R.id.swAnalyze);
@@ -1097,6 +1099,17 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
}
});
+ swIntegrity.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton v, boolean checked) {
+ prefs.edit()
+ .putBoolean("sqlite_integrity_check", checked)
+ .remove("debug")
+ .commit();
+ ApplicationEx.restart(v.getContext(), "sqlite_integrity_check");
+ }
+ });
+
swWal.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
@@ -1975,6 +1988,7 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc
tvRoomQueryThreads.setText(getString(R.string.title_advanced_room_query_threads, NF.format(query_threads)));
sbRoomQueryThreads.setProgress(query_threads);
+ swIntegrity.setChecked(prefs.getBoolean("sqlite_integrity_check", true));
swWal.setChecked(prefs.getBoolean("wal", true));
swCheckpoints.setChecked(prefs.getBoolean("sqlite_checkpoints", true));
swAnalyze.setChecked(prefs.getBoolean("sqlite_analyze", true));
diff --git a/app/src/main/res/layout/fragment_options_misc.xml b/app/src/main/res/layout/fragment_options_misc.xml
index 53cd692ac2..df38d74da9 100644
--- a/app/src/main/res/layout/fragment_options_misc.xml
+++ b/app/src/main/res/layout/fragment_options_misc.xml
@@ -1025,6 +1025,18 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/ibRoom" />
+
+
Initialize work manager
Use external storage
ROOM query threads: %1$s
+ sqlite integrity check
sqlite WAL
sqlite checkpoints
sqlite analyze