From b7f1be88d0fe54e7db593c8abb8b3e0668e48f97 Mon Sep 17 00:00:00 2001 From: M66B Date: Wed, 15 Jan 2020 13:16:52 +0100 Subject: [PATCH] Switched to FTS5 --- FAQ.md | 5 +++++ app/src/main/java/eu/faircode/email/DaoMessage.java | 2 +- app/src/main/java/eu/faircode/email/FtsDbHelper.java | 12 ++++++------ .../main/java/eu/faircode/email/WorkerCleanup.java | 8 ++++---- app/src/main/java/eu/faircode/email/WorkerFts.java | 4 ++++ app/src/main/res/values/strings.xml | 2 +- 6 files changed, 21 insertions(+), 12 deletions(-) diff --git a/FAQ.md b/FAQ.md index e135eb6ed7..74b49f6a5f 100644 --- a/FAQ.md +++ b/FAQ.md @@ -691,6 +691,11 @@ Searching through a large number of messages is not very fast because of two lim This means that searching for a message text requires that files containing the message texts need to be opened one by one to check if the searched text is contained in the file, which is a relative expensive process. +In the *miscellaneous settings* you can enable *Full text search* to significantly increase the speed of searching on the device, +but be aware that this will increase battery usage and significantly increase storage space usage too. +An advantage is that a number of advanced query options will become available, +see [here](https://www.sqlite.org/fts5.html#full_text_query_syntax). + Searching messages on the device is a free feature, searching messages on the server is a pro feature.
diff --git a/app/src/main/java/eu/faircode/email/DaoMessage.java b/app/src/main/java/eu/faircode/email/DaoMessage.java index ad364e36d9..171683fad2 100644 --- a/app/src/main/java/eu/faircode/email/DaoMessage.java +++ b/app/src/main/java/eu/faircode/email/DaoMessage.java @@ -238,7 +238,7 @@ public interface DaoMessage { " WHERE content" + " AND NOT fts" + " AND folder.type <> '" + EntityFolder.OUTBOX + "'" + - " ORDER BY message.received DESC") + " ORDER BY message.received") Cursor getMessageFts(); @Query("SELECT id, account, thread, (:find IS NULL" + diff --git a/app/src/main/java/eu/faircode/email/FtsDbHelper.java b/app/src/main/java/eu/faircode/email/FtsDbHelper.java index 23187ea282..9104ecf425 100644 --- a/app/src/main/java/eu/faircode/email/FtsDbHelper.java +++ b/app/src/main/java/eu/faircode/email/FtsDbHelper.java @@ -33,8 +33,8 @@ import javax.mail.Address; import io.requery.android.database.sqlite.SQLiteDatabase; import io.requery.android.database.sqlite.SQLiteOpenHelper; +// https://www.sqlite.org/fts5.html public class FtsDbHelper extends SQLiteOpenHelper { - // https://www.sqlite.org/fts3.html private static final int DATABASE_VERSION = 1; private static final String DATABASE_NAME = "fts.db"; @@ -46,7 +46,7 @@ public class FtsDbHelper extends SQLiteOpenHelper { public void onCreate(SQLiteDatabase db) { Log.i("FTS create"); db.execSQL("CREATE VIRTUAL TABLE `message`" + - " USING fts4(`folder`, `time`, `address`, `subject`, `keyword`, `text`)"); + " USING fts5 (`folder` UNINDEXED, `time` UNINDEXED, `address`, `subject`, `keyword`, `text`)"); } @Override @@ -70,7 +70,7 @@ public class FtsDbHelper extends SQLiteOpenHelper { delete(db, message.id); ContentValues cv = new ContentValues(); - cv.put("docid", message.id); + cv.put("rowid", message.id); cv.put("folder", message.folder); cv.put("time", message.received); cv.put("address", MessageHelper.formatAddresses(address.toArray(new Address[0]), true, false)); @@ -88,14 +88,14 @@ public class FtsDbHelper extends SQLiteOpenHelper { } void delete(SQLiteDatabase db, long id) { - db.delete("message", "docid = ?", new Object[]{id}); + db.delete("message", "rowid = ?", new Object[]{id}); } List match(SQLiteDatabase db, Long folder, String search) { Log.i("FTS folder=" + folder + " search=" + search); List result = new ArrayList<>(); try (Cursor cursor = db.query( - "message", new String[]{"docid"}, + "message", new String[]{"rowid"}, folder == null ? "message MATCH ?" : "folder = ? AND message MATCH ?", folder == null ? new Object[]{search} : new Object[]{folder, search}, null, null, "time DESC", null)) { @@ -108,7 +108,7 @@ public class FtsDbHelper extends SQLiteOpenHelper { Cursor getIds(SQLiteDatabase db) { return db.query( - "message", new String[]{"docid"}, + "message", new String[]{"rowid"}, null, null, null, null, "time"); } diff --git a/app/src/main/java/eu/faircode/email/WorkerCleanup.java b/app/src/main/java/eu/faircode/email/WorkerCleanup.java index 41ba9e97ff..23c0849731 100644 --- a/app/src/main/java/eu/faircode/email/WorkerCleanup.java +++ b/app/src/main/java/eu/faircode/email/WorkerCleanup.java @@ -199,11 +199,11 @@ public class WorkerCleanup extends Worker { try (SQLiteDatabase sdb = ftsDb.getWritableDatabase()) { try (Cursor cursor = ftsDb.getIds(sdb)) { while (cursor.moveToNext()) { - long docid = cursor.getLong(0); - EntityMessage message = db.message().getMessage(docid); + long rowid = cursor.getLong(0); + EntityMessage message = db.message().getMessage(rowid); if (message == null) { - Log.i("Deleting docid" + docid); - ftsDb.delete(sdb, docid); + Log.i("Deleting rowid" + rowid); + ftsDb.delete(sdb, rowid); fts++; } } diff --git a/app/src/main/java/eu/faircode/email/WorkerFts.java b/app/src/main/java/eu/faircode/email/WorkerFts.java index 3e69f9f525..19b63cf8cf 100644 --- a/app/src/main/java/eu/faircode/email/WorkerFts.java +++ b/app/src/main/java/eu/faircode/email/WorkerFts.java @@ -36,6 +36,8 @@ import java.util.concurrent.TimeUnit; import io.requery.android.database.sqlite.SQLiteDatabase; +import static android.os.Process.THREAD_PRIORITY_BACKGROUND; + public class WorkerFts extends Worker { private static final int INDEX_DELAY = 30; // seconds @@ -47,6 +49,8 @@ public class WorkerFts extends Worker { @NonNull @Override public Result doWork() { + Thread.currentThread().setPriority(THREAD_PRIORITY_BACKGROUND); + try { Log.i("FTS index"); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9116d1480d..41fb503c49 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -447,7 +447,7 @@ This Android version does not support notification grouping This Android version does not support notification channels - Enabling this improves search performance, but also increases battery and storage usage + Enabling this improves search performance, but also increases battery and storage space usage This will restart the app List of current experimental features Enable extra logging and show debug information at various places