Merge pull request #3519 from k9mail/add_folder_extra_values

Allow backend code to store additional per-account and per-folder data
This commit is contained in:
cketti 2018-07-22 18:21:51 +02:00 committed by GitHub
commit b35074315c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 194 additions and 2 deletions

View file

@ -234,6 +234,36 @@ class K9BackendFolder(
}
}
override fun getFolderExtraString(name: String): String? {
return database.getStringOrNull(
table = "folder_extra_values",
column = "value_string"
)
}
override fun setFolderExtraString(name: String, value: String) {
database.setString(
table = "folder_extra_values",
column = "value_string",
value = value
)
}
override fun getFolderExtraNumber(name: String): Long? {
return database.getLongOrNull(
table = "folder_extra_values",
column = "value_integer"
)
}
override fun setFolderExtraNumber(name: String, value: Long) {
database.setLong(
table = "folder_extra_values",
column = "value_integer",
value = value
)
}
private fun LockableDatabase.getString(
table: String = "folders",
@ -253,6 +283,24 @@ class K9BackendFolder(
}
}
private fun LockableDatabase.getStringOrNull(
table: String = "folders",
column: String,
selection: String = "id = ?",
vararg selectionArgs: String = arrayOf(databaseId)
): String? {
return execute(false) { db ->
val cursor = db.query(table, arrayOf(column), selection, selectionArgs, null, null, null)
cursor.use {
if (it.moveToFirst()) {
it.getStringOrNull(0)
} else {
null
}
}
}
}
private fun LockableDatabase.setString(
table: String = "folders",
column: String,
@ -281,6 +329,24 @@ class K9BackendFolder(
}
}
private fun LockableDatabase.getLongOrNull(
table: String = "folders",
column: String,
selection: String = "id = ?",
vararg selectionArgs: String = arrayOf(databaseId)
): Long? {
return execute(false) { db ->
val cursor = db.query(table, arrayOf(column), selection, selectionArgs, null, null, null)
cursor.use {
if (it.moveToFirst()) {
it.getLongOrNull(0)
} else {
null
}
}
}
}
private fun LockableDatabase.setLong(
table: String = "folders",
column: String,

View file

@ -1,5 +1,8 @@
package com.fsck.k9.mailstore
import android.content.ContentValues
import android.database.Cursor
import androidx.core.database.getStringOrNull
import com.fsck.k9.Account
import com.fsck.k9.Preferences
import com.fsck.k9.backend.api.BackendFolder
@ -8,9 +11,68 @@ import com.fsck.k9.backend.api.BackendStorage
class K9BackendStorage(
private val preferences: Preferences,
private val account: Account,
private val localStore: LocalStore) : BackendStorage {
private val localStore: LocalStore
) : BackendStorage {
private val database = localStore.database
override fun getFolder(folderServerId: String): BackendFolder {
return K9BackendFolder(preferences, account, localStore, folderServerId)
}
override fun getExtraString(name: String): String? {
return database.execute(false) { db ->
val cursor = db.query(
"account_extra_values",
arrayOf("value_string"),
"name = ?",
arrayOf(name),
null, null, null)
cursor.use {
if (it.moveToFirst()) {
it.getStringOrNull(0)
} else {
null
}
}
}
}
override fun setExtraString(name: String, value: String) {
database.execute(false) { db ->
val contentValues = ContentValues().apply {
put("value_string", value)
}
db.update("account_extra_values", contentValues, "name = ?", arrayOf(name))
}
}
override fun getExtraNumber(name: String): Long? {
return database.execute(false) { db ->
val cursor = db.query(
"account_extra_values",
arrayOf("value_integer"),
"name = ?",
arrayOf(name),
null, null, null)
cursor.use {
if (it.moveToFirst()) {
it.getLongOrNull(0)
} else {
null
}
}
}
}
override fun setExtraNumber(name: String, value: Long) {
database.execute(false) { db ->
val contentValues = ContentValues().apply {
put("value_integer", value)
}
db.update("account_extra_values", contentValues, "name = ?", arrayOf(name))
}
}
private fun Cursor.getLongOrNull(columnIndex: Int): Long? = if (isNull(columnIndex)) null else getLong(columnIndex)
}

View file

@ -179,7 +179,7 @@ public class LocalStore {
*/
private static final int THREAD_FLAG_UPDATE_BATCH_SIZE = 500;
public static final int DB_VERSION = 63;
public static final int DB_VERSION = 64;
private final Context context;
private final ContentResolver contentResolver;

View file

@ -73,6 +73,13 @@ class StoreSchemaDefinition implements LockableDatabase.SchemaDefinition {
}
private static void dbCreateDatabaseFromScratch(SQLiteDatabase db) {
db.execSQL("DROP TABLE IF EXISTS account_extra_values");
db.execSQL("CREATE TABLE account_extra_values (" +
"name TEXT NOT NULL PRIMARY KEY, " +
"value_text TEXT, " +
"value_integer INTEGER " +
")");
db.execSQL("DROP TABLE IF EXISTS folders");
db.execSQL("CREATE TABLE folders (" +
"id INTEGER PRIMARY KEY," +
@ -97,6 +104,15 @@ class StoreSchemaDefinition implements LockableDatabase.SchemaDefinition {
db.execSQL("DROP INDEX IF EXISTS folder_server_id");
db.execSQL("CREATE INDEX folder_server_id ON folders (server_id)");
db.execSQL("DROP TABLE IF EXISTS folder_extra_values");
db.execSQL("CREATE TABLE folder_extra_values (" +
"folder_id INTEGER NOT NULL, " +
"name TEXT NOT NULL, " +
"value_text TEXT, " +
"value_integer INTEGER, " +
"PRIMARY KEY (folder_id, name)" +
")");
db.execSQL("DROP TABLE IF EXISTS messages");
db.execSQL("CREATE TABLE messages (" +
"id INTEGER PRIMARY KEY, " +
@ -203,6 +219,13 @@ class StoreSchemaDefinition implements LockableDatabase.SchemaDefinition {
db.execSQL("DROP TRIGGER IF EXISTS delete_folder");
db.execSQL("CREATE TRIGGER delete_folder BEFORE DELETE ON folders BEGIN DELETE FROM messages WHERE old.id = folder_id; END;");
db.execSQL("DROP TRIGGER IF EXISTS delete_folder_extra_values");
db.execSQL("CREATE TRIGGER delete_folder_extra_values " +
"BEFORE DELETE ON folders " +
"BEGIN " +
"DELETE FROM folder_extra_values WHERE old.id = folder_id; " +
"END;");
db.execSQL("DROP TRIGGER IF EXISTS delete_message");
db.execSQL("CREATE TRIGGER delete_message " +
"BEFORE DELETE ON messages " +

View file

@ -0,0 +1,30 @@
package com.fsck.k9.mailstore.migrations
import android.database.sqlite.SQLiteDatabase
internal object MigrationTo64 {
@JvmStatic
fun addExtraValuesTables(db: SQLiteDatabase) {
db.execSQL("CREATE TABLE account_extra_values (" +
"name TEXT NOT NULL PRIMARY KEY, " +
"value_text TEXT, " +
"value_integer INTEGER " +
")")
db.execSQL("CREATE TABLE folder_extra_values (" +
"folder_id INTEGER NOT NULL, " +
"name TEXT NOT NULL, " +
"value_text TEXT, " +
"value_integer INTEGER, " +
"PRIMARY KEY (folder_id, name)" +
")")
db.execSQL("CREATE TRIGGER delete_folder_extra_values " +
"BEFORE DELETE ON folders " +
"BEGIN " +
"DELETE FROM folder_extra_values WHERE old.id = folder_id; " +
"END;")
}
}

View file

@ -83,6 +83,8 @@ public class Migrations {
MigrationTo61.removeErrorsFolder(db);
case 61:
MigrationTo62.addServerIdColumnToFoldersTable(db);
case 63:
MigrationTo64.addExtraValuesTables(db);
}
if (shouldBuildFtsTable) {

View file

@ -28,6 +28,10 @@ interface BackendFolder {
fun getLatestOldMessageSeenTime(): Date
fun setLatestOldMessageSeenTime(date: Date)
fun getOldestMessageDate(): Date?
fun getFolderExtraString(name: String): String?
fun setFolderExtraString(name: String, value: String)
fun getFolderExtraNumber(name: String): Long?
fun setFolderExtraNumber(name: String, value: Long)
enum class MoreMessages {
UNKNOWN,

View file

@ -2,4 +2,9 @@ package com.fsck.k9.backend.api
interface BackendStorage {
fun getFolder(folderServerId: String): BackendFolder
fun getExtraString(name: String): String?
fun setExtraString(name: String, value: String)
fun getExtraNumber(name: String): Long?
fun setExtraNumber(name: String, value: Long)
}