|
@@ -27,76 +27,211 @@ import androidx.sqlite.db.SupportSQLiteDatabase
|
|
|
import com.nextcloud.client.database.NextcloudDatabase
|
|
|
|
|
|
class RoomMigration : Migration(NextcloudDatabase.FIRST_ROOM_DB_VERSION - 1, NextcloudDatabase.FIRST_ROOM_DB_VERSION) {
|
|
|
+
|
|
|
override fun migrate(database: SupportSQLiteDatabase) {
|
|
|
- // migrate LONG, STRING to INTEGER, TEXT
|
|
|
migrateFilesystemTable(database)
|
|
|
migrateUploadsTable(database)
|
|
|
+ migrateCapabilitiesTable(database)
|
|
|
+ migrateFilesTable(database)
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * filesystem table: STRING converted to TEXT
|
|
|
+ */
|
|
|
private fun migrateFilesystemTable(database: SupportSQLiteDatabase) {
|
|
|
- val table = "filesystem"
|
|
|
- val newTable = "${table}_new"
|
|
|
- // create table with fixed types
|
|
|
- database.execSQL(
|
|
|
- "CREATE TABLE $newTable (" +
|
|
|
- "_id INTEGER PRIMARY KEY," +
|
|
|
- "local_path TEXT," +
|
|
|
- "is_folder INTEGER," +
|
|
|
- "found_at INTEGER," +
|
|
|
- "upload_triggered INTEGER," +
|
|
|
- "syncedfolder_id TEXT," +
|
|
|
- "crc32 TEXT," +
|
|
|
- "modified_at INTEGER " +
|
|
|
- ")"
|
|
|
- )
|
|
|
- // copy data
|
|
|
- val columns =
|
|
|
- "_id, local_path, is_folder, found_at, upload_triggered, syncedfolder_id, crc32, modified_at"
|
|
|
- database.execSQL(
|
|
|
- "INSERT INTO $newTable ($columns) " +
|
|
|
- "SELECT $columns FROM $table"
|
|
|
+ val newColumns = mapOf(
|
|
|
+ "_id" to TYPE_INTEGER_PRIMARY_KEY,
|
|
|
+ "local_path" to TYPE_TEXT,
|
|
|
+ "is_folder" to TYPE_INTEGER,
|
|
|
+ "found_at" to TYPE_INTEGER,
|
|
|
+ "upload_triggered" to TYPE_INTEGER,
|
|
|
+ "syncedfolder_id" to TYPE_TEXT,
|
|
|
+ "crc32" to TYPE_TEXT,
|
|
|
+ "modified_at" to TYPE_INTEGER
|
|
|
)
|
|
|
- // replace table
|
|
|
- database.execSQL("DROP TABLE $table")
|
|
|
- database.execSQL("ALTER TABLE $newTable RENAME TO $table")
|
|
|
+
|
|
|
+ migrateTable(database, "filesystem", newColumns)
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * uploads table: LONG converted to INTEGER
|
|
|
+ */
|
|
|
private fun migrateUploadsTable(database: SupportSQLiteDatabase) {
|
|
|
- val table = "list_of_uploads"
|
|
|
- val newTable = "${table}_new"
|
|
|
- // create table with fixed types
|
|
|
- database.execSQL(
|
|
|
- "CREATE TABLE $newTable (" +
|
|
|
- "_id INTEGER PRIMARY KEY," +
|
|
|
- "local_path TEXT, " +
|
|
|
- "remote_path TEXT, " +
|
|
|
- "account_name TEXT, " +
|
|
|
- "file_size INTEGER, " +
|
|
|
- "status INTEGER, " +
|
|
|
- "local_behaviour INTEGER, " +
|
|
|
- "upload_time INTEGER, " +
|
|
|
- "name_collision_policy INTEGER, " +
|
|
|
- "is_create_remote_folder INTEGER, " +
|
|
|
- "upload_end_timestamp INTEGER, " +
|
|
|
- "last_result INTEGER, " +
|
|
|
- "is_while_charging_only INTEGER, " +
|
|
|
- "is_wifi_only INTEGER, " +
|
|
|
- "created_by INTEGER, " +
|
|
|
- "folder_unlock_token TEXT " +
|
|
|
- ")"
|
|
|
+ val newColumns = mapOf(
|
|
|
+ "_id" to TYPE_INTEGER_PRIMARY_KEY,
|
|
|
+ "local_path" to TYPE_TEXT,
|
|
|
+ "remote_path" to TYPE_TEXT,
|
|
|
+ "account_name" to TYPE_TEXT,
|
|
|
+ "file_size" to TYPE_INTEGER,
|
|
|
+ "status" to TYPE_INTEGER,
|
|
|
+ "local_behaviour" to TYPE_INTEGER,
|
|
|
+ "upload_time" to TYPE_INTEGER,
|
|
|
+ "name_collision_policy" to TYPE_INTEGER,
|
|
|
+ "is_create_remote_folder" to TYPE_INTEGER,
|
|
|
+ "upload_end_timestamp" to TYPE_INTEGER,
|
|
|
+ "last_result" to TYPE_INTEGER,
|
|
|
+ "is_while_charging_only" to TYPE_INTEGER,
|
|
|
+ "is_wifi_only" to TYPE_INTEGER,
|
|
|
+ "created_by" to TYPE_INTEGER,
|
|
|
+ "folder_unlock_token" to TYPE_TEXT
|
|
|
+ )
|
|
|
+
|
|
|
+ migrateTable(database, "list_of_uploads", newColumns)
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * capabilities table: "files_drop" column removed
|
|
|
+ */
|
|
|
+ private fun migrateCapabilitiesTable(database: SupportSQLiteDatabase) {
|
|
|
+ val newColumns = mapOf(
|
|
|
+ "_id" to TYPE_INTEGER_PRIMARY_KEY,
|
|
|
+ "account" to TYPE_TEXT,
|
|
|
+ "version_mayor" to TYPE_INTEGER,
|
|
|
+ "version_minor" to TYPE_INTEGER,
|
|
|
+ "version_micro" to TYPE_INTEGER,
|
|
|
+ "version_string" to TYPE_TEXT,
|
|
|
+ "version_edition" to TYPE_TEXT,
|
|
|
+ "extended_support" to TYPE_INTEGER,
|
|
|
+ "core_pollinterval" to TYPE_INTEGER,
|
|
|
+ "sharing_api_enabled" to TYPE_INTEGER,
|
|
|
+ "sharing_public_enabled" to TYPE_INTEGER,
|
|
|
+ "sharing_public_password_enforced" to TYPE_INTEGER,
|
|
|
+ "sharing_public_expire_date_enabled" to TYPE_INTEGER,
|
|
|
+ "sharing_public_expire_date_days" to TYPE_INTEGER,
|
|
|
+ "sharing_public_expire_date_enforced" to TYPE_INTEGER,
|
|
|
+ "sharing_public_send_mail" to TYPE_INTEGER,
|
|
|
+ "sharing_public_upload" to TYPE_INTEGER,
|
|
|
+ "sharing_user_send_mail" to TYPE_INTEGER,
|
|
|
+ "sharing_resharing" to TYPE_INTEGER,
|
|
|
+ "sharing_federation_outgoing" to TYPE_INTEGER,
|
|
|
+ "sharing_federation_incoming" to TYPE_INTEGER,
|
|
|
+ "files_bigfilechunking" to TYPE_INTEGER,
|
|
|
+ "files_undelete" to TYPE_INTEGER,
|
|
|
+ "files_versioning" to TYPE_INTEGER,
|
|
|
+ "external_links" to TYPE_INTEGER,
|
|
|
+ "server_name" to TYPE_TEXT,
|
|
|
+ "server_color" to TYPE_TEXT,
|
|
|
+ "server_text_color" to TYPE_TEXT,
|
|
|
+ "server_element_color" to TYPE_TEXT,
|
|
|
+ "server_slogan" to TYPE_TEXT,
|
|
|
+ "server_logo" to TYPE_TEXT,
|
|
|
+ "background_url" to TYPE_TEXT,
|
|
|
+ "end_to_end_encryption" to TYPE_INTEGER,
|
|
|
+ "activity" to TYPE_INTEGER,
|
|
|
+ "background_default" to TYPE_INTEGER,
|
|
|
+ "background_plain" to TYPE_INTEGER,
|
|
|
+ "richdocument" to TYPE_INTEGER,
|
|
|
+ "richdocument_mimetype_list" to TYPE_TEXT,
|
|
|
+ "richdocument_direct_editing" to TYPE_INTEGER,
|
|
|
+ "richdocument_direct_templates" to TYPE_INTEGER,
|
|
|
+ "richdocument_optional_mimetype_list" to TYPE_TEXT,
|
|
|
+ "sharing_public_ask_for_optional_password" to TYPE_INTEGER,
|
|
|
+ "richdocument_product_name" to TYPE_TEXT,
|
|
|
+ "direct_editing_etag" to TYPE_TEXT,
|
|
|
+ "user_status" to TYPE_INTEGER,
|
|
|
+ "user_status_supports_emoji" to TYPE_INTEGER,
|
|
|
+ "etag" to TYPE_TEXT,
|
|
|
+ "files_locking_version" to TYPE_TEXT
|
|
|
+ )
|
|
|
+
|
|
|
+ migrateTable(database, "capabilities", newColumns)
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * files table: "public_link" column removed
|
|
|
+ */
|
|
|
+ private fun migrateFilesTable(database: SupportSQLiteDatabase) {
|
|
|
+ val newColumns = mapOf(
|
|
|
+ "_id" to TYPE_INTEGER_PRIMARY_KEY,
|
|
|
+ "filename" to TYPE_TEXT,
|
|
|
+ "encrypted_filename" to TYPE_TEXT,
|
|
|
+ "path" to TYPE_TEXT,
|
|
|
+ "path_decrypted" to TYPE_TEXT,
|
|
|
+ "parent" to TYPE_INTEGER,
|
|
|
+ "created" to TYPE_INTEGER,
|
|
|
+ "modified" to TYPE_INTEGER,
|
|
|
+ "content_type" to TYPE_TEXT,
|
|
|
+ "content_length" to TYPE_INTEGER,
|
|
|
+ "media_path" to TYPE_TEXT,
|
|
|
+ "file_owner" to TYPE_TEXT,
|
|
|
+ "last_sync_date" to TYPE_INTEGER,
|
|
|
+ "last_sync_date_for_data" to TYPE_INTEGER,
|
|
|
+ "modified_at_last_sync_for_data" to TYPE_INTEGER,
|
|
|
+ "etag" to TYPE_TEXT,
|
|
|
+ "etag_on_server" to TYPE_TEXT,
|
|
|
+ "share_by_link" to TYPE_INTEGER,
|
|
|
+ "permissions" to TYPE_TEXT,
|
|
|
+ "remote_id" to TYPE_TEXT,
|
|
|
+ "update_thumbnail" to TYPE_INTEGER,
|
|
|
+ "is_downloading" to TYPE_INTEGER,
|
|
|
+ "favorite" to TYPE_INTEGER,
|
|
|
+ "is_encrypted" to TYPE_INTEGER,
|
|
|
+ "etag_in_conflict" to TYPE_TEXT,
|
|
|
+ "shared_via_users" to TYPE_INTEGER,
|
|
|
+ "mount_type" to TYPE_INTEGER,
|
|
|
+ "has_preview" to TYPE_INTEGER,
|
|
|
+ "unread_comments_count" to TYPE_INTEGER,
|
|
|
+ "owner_id" to TYPE_TEXT,
|
|
|
+ "owner_display_name" to TYPE_TEXT,
|
|
|
+ "note" to TYPE_TEXT,
|
|
|
+ "sharees" to TYPE_TEXT,
|
|
|
+ "rich_workspace" to TYPE_TEXT,
|
|
|
+ "metadata_size" to TYPE_TEXT,
|
|
|
+ "locked" to TYPE_INTEGER,
|
|
|
+ "lock_type" to TYPE_INTEGER,
|
|
|
+ "lock_owner" to TYPE_TEXT,
|
|
|
+ "lock_owner_display_name" to TYPE_TEXT,
|
|
|
+ "lock_owner_editor" to TYPE_TEXT,
|
|
|
+ "lock_timestamp" to TYPE_INTEGER,
|
|
|
+ "lock_timeout" to TYPE_INTEGER,
|
|
|
+ "lock_token" to TYPE_TEXT
|
|
|
)
|
|
|
+ migrateTable(database, "filelist", newColumns)
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun migrateTable(database: SupportSQLiteDatabase, tableName: String, newColumns: Map<String, String>) {
|
|
|
+ require(newColumns.isNotEmpty())
|
|
|
+ val newTableTempName = "${tableName}_new"
|
|
|
+ createNewTable(database, newTableTempName, newColumns)
|
|
|
+ copyData(database, tableName, newTableTempName, newColumns.keys)
|
|
|
+ replaceTable(database, tableName, newTableTempName)
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun createNewTable(
|
|
|
+ database: SupportSQLiteDatabase,
|
|
|
+ newTableName: String,
|
|
|
+ columns: Map<String, String>
|
|
|
+ ) {
|
|
|
+ val columnsString = columns.entries.joinToString(",") { "${it.key} ${it.value}" }
|
|
|
+ database.execSQL("CREATE TABLE $newTableName ($columnsString)")
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun copyData(
|
|
|
+ database: SupportSQLiteDatabase,
|
|
|
+ tableName: String,
|
|
|
+ newTableName: String,
|
|
|
+ columnNames: Iterable<String>
|
|
|
+ ) {
|
|
|
+ val columnsString = columnNames.joinToString(",")
|
|
|
|
|
|
- // copy data
|
|
|
- val columns =
|
|
|
- "_id, local_path, remote_path, account_name, file_size, status, local_behaviour, upload_time," +
|
|
|
- " name_collision_policy, is_create_remote_folder, upload_end_timestamp, last_result," +
|
|
|
- " is_while_charging_only, is_wifi_only, created_by, folder_unlock_token"
|
|
|
database.execSQL(
|
|
|
- "INSERT INTO $newTable ($columns) " +
|
|
|
- "SELECT $columns FROM $table"
|
|
|
+ "INSERT INTO $newTableName ($columnsString) " +
|
|
|
+ "SELECT $columnsString FROM $tableName"
|
|
|
)
|
|
|
- // replace table
|
|
|
- database.execSQL("DROP TABLE $table")
|
|
|
- database.execSQL("ALTER TABLE $newTable RENAME TO $table")
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun replaceTable(
|
|
|
+ database: SupportSQLiteDatabase,
|
|
|
+ tableName: String,
|
|
|
+ newTableTempName: String
|
|
|
+ ) {
|
|
|
+ database.execSQL("DROP TABLE $tableName")
|
|
|
+ database.execSQL("ALTER TABLE $newTableTempName RENAME TO $tableName")
|
|
|
+ }
|
|
|
+
|
|
|
+ companion object {
|
|
|
+ private const val TYPE_TEXT = "TEXT"
|
|
|
+ private const val TYPE_INTEGER = "INTEGER"
|
|
|
+ private const val TYPE_INTEGER_PRIMARY_KEY = "INTEGER PRIMARY KEY"
|
|
|
}
|
|
|
}
|