Browse Source

Add migrations for capabilities and files tables as well

They both have unused columns that were not removed in previous migrations, and this makes Room unhappy

Signed-off-by: Álvaro Brey <alvaro.brey@nextcloud.com>
Álvaro Brey 2 years ago
parent
commit
ec07d26334

+ 192 - 57
app/src/main/java/com/nextcloud/client/database/migrations/RoomMigration.kt

@@ -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"
     }
 }