mirror of
https://github.com/thunderbird/thunderbird-android.git
synced 2024-09-20 04:02:14 +02:00
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:
commit
b35074315c
@ -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(
|
private fun LockableDatabase.getString(
|
||||||
table: String = "folders",
|
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(
|
private fun LockableDatabase.setString(
|
||||||
table: String = "folders",
|
table: String = "folders",
|
||||||
column: String,
|
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(
|
private fun LockableDatabase.setLong(
|
||||||
table: String = "folders",
|
table: String = "folders",
|
||||||
column: String,
|
column: String,
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package com.fsck.k9.mailstore
|
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.Account
|
||||||
import com.fsck.k9.Preferences
|
import com.fsck.k9.Preferences
|
||||||
import com.fsck.k9.backend.api.BackendFolder
|
import com.fsck.k9.backend.api.BackendFolder
|
||||||
@ -8,9 +11,68 @@ import com.fsck.k9.backend.api.BackendStorage
|
|||||||
class K9BackendStorage(
|
class K9BackendStorage(
|
||||||
private val preferences: Preferences,
|
private val preferences: Preferences,
|
||||||
private val account: Account,
|
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 {
|
override fun getFolder(folderServerId: String): BackendFolder {
|
||||||
return K9BackendFolder(preferences, account, localStore, folderServerId)
|
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)
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,7 @@ public class LocalStore {
|
|||||||
*/
|
*/
|
||||||
private static final int THREAD_FLAG_UPDATE_BATCH_SIZE = 500;
|
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 Context context;
|
||||||
private final ContentResolver contentResolver;
|
private final ContentResolver contentResolver;
|
||||||
|
@ -73,6 +73,13 @@ class StoreSchemaDefinition implements LockableDatabase.SchemaDefinition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void dbCreateDatabaseFromScratch(SQLiteDatabase db) {
|
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("DROP TABLE IF EXISTS folders");
|
||||||
db.execSQL("CREATE TABLE folders (" +
|
db.execSQL("CREATE TABLE folders (" +
|
||||||
"id INTEGER PRIMARY KEY," +
|
"id INTEGER PRIMARY KEY," +
|
||||||
@ -97,6 +104,15 @@ class StoreSchemaDefinition implements LockableDatabase.SchemaDefinition {
|
|||||||
db.execSQL("DROP INDEX IF EXISTS folder_server_id");
|
db.execSQL("DROP INDEX IF EXISTS folder_server_id");
|
||||||
db.execSQL("CREATE INDEX folder_server_id ON folders (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("DROP TABLE IF EXISTS messages");
|
||||||
db.execSQL("CREATE TABLE messages (" +
|
db.execSQL("CREATE TABLE messages (" +
|
||||||
"id INTEGER PRIMARY KEY, " +
|
"id INTEGER PRIMARY KEY, " +
|
||||||
@ -203,6 +219,13 @@ class StoreSchemaDefinition implements LockableDatabase.SchemaDefinition {
|
|||||||
db.execSQL("DROP TRIGGER IF EXISTS delete_folder");
|
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("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("DROP TRIGGER IF EXISTS delete_message");
|
||||||
db.execSQL("CREATE TRIGGER delete_message " +
|
db.execSQL("CREATE TRIGGER delete_message " +
|
||||||
"BEFORE DELETE ON messages " +
|
"BEFORE DELETE ON messages " +
|
||||||
|
@ -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;")
|
||||||
|
}
|
||||||
|
}
|
@ -83,6 +83,8 @@ public class Migrations {
|
|||||||
MigrationTo61.removeErrorsFolder(db);
|
MigrationTo61.removeErrorsFolder(db);
|
||||||
case 61:
|
case 61:
|
||||||
MigrationTo62.addServerIdColumnToFoldersTable(db);
|
MigrationTo62.addServerIdColumnToFoldersTable(db);
|
||||||
|
case 63:
|
||||||
|
MigrationTo64.addExtraValuesTables(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldBuildFtsTable) {
|
if (shouldBuildFtsTable) {
|
||||||
|
@ -28,6 +28,10 @@ interface BackendFolder {
|
|||||||
fun getLatestOldMessageSeenTime(): Date
|
fun getLatestOldMessageSeenTime(): Date
|
||||||
fun setLatestOldMessageSeenTime(date: Date)
|
fun setLatestOldMessageSeenTime(date: Date)
|
||||||
fun getOldestMessageDate(): 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 {
|
enum class MoreMessages {
|
||||||
UNKNOWN,
|
UNKNOWN,
|
||||||
|
@ -2,4 +2,9 @@ package com.fsck.k9.backend.api
|
|||||||
|
|
||||||
interface BackendStorage {
|
interface BackendStorage {
|
||||||
fun getFolder(folderServerId: String): BackendFolder
|
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)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user