Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/stefan-niedermann/nextcloud-deck.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Niedermann <info@niedermann.it>2021-03-15 17:54:34 +0300
committerNiedermann IT-Dienstleistungen <stefan-niedermann@users.noreply.github.com>2021-03-15 23:37:11 +0300
commitfe65e77a63427706f6761c03bf82b0d788028b6b (patch)
treea5c3b45d0b8071cbe9a1da0940719db6f5a453eb
parentca95166373ccfaefc1b26e177d6b20e7e7478424 (diff)
Move database migrations to own classes
Signed-off-by: Stefan Niedermann <info@niedermann.it>
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DeckDatabase.java512
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_10_11.java56
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_11_12.java17
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_12_13.java17
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_13_14.java17
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_14_15.java33
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_15_16.java20
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_16_17.java31
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_17_18.java17
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_18_19.java19
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_19_20.java32
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_20_21.java121
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_21_22.java32
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_22_23.java28
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_23_24.java37
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_24_25.java22
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_25_26.java39
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_26_27.java61
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_27_28.java16
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_28_29.java22
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_8_9.java24
-rw-r--r--app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_9_10.java19
22 files changed, 722 insertions, 470 deletions
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DeckDatabase.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DeckDatabase.java
index 6871c8fa6..dca8676c9 100644
--- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DeckDatabase.java
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DeckDatabase.java
@@ -1,25 +1,15 @@
package it.niedermann.nextcloud.deck.persistence.sync.adapters.db;
-import android.content.ContentValues;
import android.content.Context;
-import android.content.SharedPreferences;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.graphics.Color;
-import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
-import androidx.preference.PreferenceManager;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.room.TypeConverters;
-import androidx.room.migration.Migration;
import androidx.sqlite.db.SupportSQLiteDatabase;
-import it.niedermann.android.util.ColorUtil;
import it.niedermann.nextcloud.deck.DeckLog;
-import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.api.LastSyncUtil;
import it.niedermann.nextcloud.deck.model.AccessControl;
import it.niedermann.nextcloud.deck.model.Account;
@@ -35,7 +25,6 @@ import it.niedermann.nextcloud.deck.model.Label;
import it.niedermann.nextcloud.deck.model.Permission;
import it.niedermann.nextcloud.deck.model.Stack;
import it.niedermann.nextcloud.deck.model.User;
-import it.niedermann.nextcloud.deck.model.enums.DBStatus;
import it.niedermann.nextcloud.deck.model.ocs.Activity;
import it.niedermann.nextcloud.deck.model.ocs.comment.DeckComment;
import it.niedermann.nextcloud.deck.model.ocs.comment.Mention;
@@ -44,7 +33,6 @@ import it.niedermann.nextcloud.deck.model.ocs.projects.OcsProject;
import it.niedermann.nextcloud.deck.model.ocs.projects.OcsProjectResource;
import it.niedermann.nextcloud.deck.model.relations.UserInBoard;
import it.niedermann.nextcloud.deck.model.relations.UserInGroup;
-import it.niedermann.nextcloud.deck.model.widget.filter.EWidgetType;
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidget;
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidgetAccount;
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidgetBoard;
@@ -54,7 +42,6 @@ import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidgetSort;
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidgetStack;
import it.niedermann.nextcloud.deck.model.widget.filter.FilterWidgetUser;
import it.niedermann.nextcloud.deck.model.widget.singlecard.SingleCardWidgetModel;
-import it.niedermann.nextcloud.deck.persistence.sync.SyncWorker;
import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.converter.DateTypeConverter;
import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.converter.EnumConverter;
import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.dao.AccessControlDao;
@@ -88,6 +75,27 @@ import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.dao.widgets.fil
import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.dao.widgets.filter.FilterWidgetSortDao;
import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.dao.widgets.filter.FilterWidgetStackDao;
import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.dao.widgets.filter.FilterWidgetUserDao;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_10_11;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_11_12;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_12_13;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_13_14;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_14_15;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_15_16;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_16_17;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_17_18;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_18_19;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_19_20;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_20_21;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_21_22;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_22_23;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_23_24;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_24_25;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_25_26;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_26_27;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_27_28;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_28_29;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_8_9;
+import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration.Migration_9_10;
@Database(
entities = {
@@ -134,403 +142,6 @@ public abstract class DeckDatabase extends RoomDatabase {
private static final String DECK_DB_NAME = "NC_DECK_DB.db";
private static volatile DeckDatabase instance;
- private static final Migration MIGRATION_8_9 = new Migration(8, 9) {
- @Override
- public void migrate(SupportSQLiteDatabase database) {
- database.execSQL("CREATE TABLE `DeckComment` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `status` INTEGER NOT NULL, `lastModified` INTEGER, `lastModifiedLocal` INTEGER, `objectId` INTEGER, `actorType` TEXT, `creationDateTime` INTEGER, `actorId` TEXT, `actorDisplayName` TEXT, `message` TEXT, FOREIGN KEY(`objectId`) REFERENCES `Card`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE )");
- database.execSQL("CREATE TABLE `Mention` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `commentId` INTEGER, `mentionId` TEXT, `mentionType` TEXT, `mentionDisplayName` TEXT, FOREIGN KEY(`commentId`) REFERENCES `DeckComment`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE )");
- database.execSQL("CREATE INDEX `index_DeckComment_accountId` ON `DeckComment` (`accountId`)");
- database.execSQL("CREATE INDEX `comment_accID` ON `DeckComment` (`accountId`)");
- database.execSQL("CREATE UNIQUE INDEX `index_DeckComment_accountId_id` ON `DeckComment` (`accountId`, `id`)");
- database.execSQL("CREATE INDEX `index_DeckComment_id` ON `DeckComment` (`id`)");
- database.execSQL("CREATE INDEX `index_DeckComment_lastModifiedLocal` ON `DeckComment` (`lastModifiedLocal`)");
- database.execSQL("CREATE INDEX `index_DeckComment_objectId` ON `DeckComment` (`objectId`)");
- database.execSQL("CREATE INDEX `index_Mention_commentId` ON `Mention` (`commentId`)");
- }
- };
-
- private static final Migration MIGRATION_9_10 = new Migration(9, 10) {
- @Override
- public void migrate(SupportSQLiteDatabase database) {
- database.execSQL("ALTER TABLE `Account` ADD `color` TEXT NOT NULL DEFAULT '#0082c9'");
- database.execSQL("ALTER TABLE `Account` ADD `textColor` TEXT NOT NULL DEFAULT '#ffffff'");
- database.execSQL("ALTER TABLE `Account` ADD `serverDeckVersion` TEXT NOT NULL DEFAULT '0.6.4'");
- database.execSQL("ALTER TABLE `Account` ADD `maintenanceEnabled` INTEGER NOT NULL DEFAULT 0");
- }
- };
-
- private static final Migration MIGRATION_10_11 = new Migration(10, 11) {
- @Override
- public void migrate(SupportSQLiteDatabase database) {
- // replace duplicates with the server-known ones
- Cursor duplucatesCursor = database.query("SELECT boardId, title, count(*) FROM Label group by boardid, title having count(*) > 1");
- if (duplucatesCursor != null && duplucatesCursor.moveToFirst()) {
- do {
- long boardId = duplucatesCursor.getLong(0);
- String title = duplucatesCursor.getString(1);
- Cursor singleDuplicateCursor = database.query("select localId from Label where boardId = ? and title = ? order by id desc", new Object[]{boardId, title});
- if (singleDuplicateCursor != null && singleDuplicateCursor.moveToFirst()) {
- long idToUse = -1;
- do {
- if (idToUse < 0) {
- // desc order -> first one is the one with remote ID or a random one. keep this one.
- idToUse = singleDuplicateCursor.getLong(0);
- continue;
- }
- long idToReplace = singleDuplicateCursor.getLong(0);
- Cursor cardsAssignedToDuplicateCursor = database.query("select cardId, exists(select 1 from JoinCardWithLabel ij where ij.labelId = ? and ij.cardId = cardId) " +
- "from JoinCardWithLabel where labelId = ?", new Object[]{idToUse, idToReplace});
- if (cardsAssignedToDuplicateCursor != null && cardsAssignedToDuplicateCursor.moveToFirst()) {
- do {
- long cardId = cardsAssignedToDuplicateCursor.getLong(0);
- boolean hasDestinationLabelAssigned = cardsAssignedToDuplicateCursor.getInt(1) > 0;
- database.execSQL("DELETE FROM JoinCardWithLabel where labelId = ? and cardId = ?", new Object[]{idToReplace, cardId});
-
- if (!hasDestinationLabelAssigned) {
- database.execSQL("INSERT INTO JoinCardWithLabel (status,labelId,cardId) VALUES (?, ?, ?)", new Object[]{DBStatus.LOCAL_EDITED.getId(), idToUse, cardId});
- }
- } while (cardsAssignedToDuplicateCursor.moveToNext());
- }
- database.execSQL("DELETE FROM Label where localId = ?", new Object[]{idToReplace});
- } while (singleDuplicateCursor.moveToNext());
- }
- } while (duplucatesCursor.moveToNext());
- }
-// database.execSQL("DELETE FROM Label WHERE id IS NULL AND EXISTS(SELECT 1 FROM Label il WHERE il.boardId = boardId AND il.title = title AND id IS NOT NULL)");
- database.execSQL("CREATE UNIQUE INDEX idx_label_title_unique ON Label(boardId, title)");
- }
- };
-
- private static final Migration MIGRATION_11_12 = new Migration(11, 12) {
- @Override
- public void migrate(SupportSQLiteDatabase database) {
- database.execSQL("CREATE TABLE `SingleCardWidgetModel` (`widgetId` INTEGER PRIMARY KEY, `accountId` INTEGER, `boardId` INTEGER, `cardId` INTEGER, FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE, FOREIGN KEY(`boardId`) REFERENCES `Board`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE, FOREIGN KEY(`cardId`) REFERENCES `Card`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE )");
- database.execSQL("CREATE INDEX `index_SingleCardWidgetModel_cardId` ON `SingleCardWidgetModel` (`cardId`)");
- }
- };
-
- private static final Migration MIGRATION_12_13 = new Migration(12, 13) {
- @Override
- public void migrate(SupportSQLiteDatabase database) {
- database.execSQL("CREATE INDEX `idx_cardWidgetModel_accountId` ON `SingleCardWidgetModel` (`accountId`)");
- database.execSQL("CREATE INDEX `idx_cardWidgetModel_boardId` ON `SingleCardWidgetModel` (`boardId`)");
- }
- };
-
- private static final Migration MIGRATION_13_14 = new Migration(13, 14) {
- @Override
- public void migrate(SupportSQLiteDatabase database) {
- database.execSQL("ALTER TABLE `DeckComment` ADD `parentId` INTEGER REFERENCES DeckComment(localId) ON DELETE CASCADE");
- database.execSQL("CREATE INDEX `idx_comment_parentID` ON DeckComment(parentId)");
- }
- };
-
- private static final Migration MIGRATION_15_16 = new Migration(15, 16) {
- @Override
- public void migrate(SupportSQLiteDatabase database) {
- database.execSQL("CREATE TABLE `StackWidgetModel` (`appWidgetId` INTEGER PRIMARY KEY, `accountId` INTEGER, `stackId` INTEGER, `darkTheme` INTEGER CHECK (`darkTheme` IN (0,1)) NOT NULL, " +
- "FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE, " +
- "FOREIGN KEY(`stackId`) REFERENCES `Stack`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE )");
- database.execSQL("CREATE INDEX `index_StackWidgetModel_stackId` ON `StackWidgetModel` (`stackId`)");
- database.execSQL("CREATE INDEX `index_StackWidgetModel_accountId` ON `StackWidgetModel` (`accountId`)");
- }
- };
-
- private static final Migration MIGRATION_16_17 = new Migration(16, 17) {
- @Override
- public void migrate(SupportSQLiteDatabase database) {
- database.execSQL("CREATE TABLE `OcsProject` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `name` TEXT NOT NULL, `status` INTEGER NOT NULL, `lastModified` INTEGER, `lastModifiedLocal` INTEGER)");
- database.execSQL("CREATE UNIQUE INDEX `index_OcsProject_accountId_id` ON `OcsProject` (`accountId`, `id`)");
- database.execSQL("CREATE INDEX `index_project_accID` ON `OcsProject` (`accountId`)");
- database.execSQL("CREATE INDEX `index_OcsProject_id` ON `OcsProject` (`id`)");
- database.execSQL("CREATE INDEX `index_OcsProject_lastModifiedLocal` ON `OcsProject` (`lastModifiedLocal`)");
-
- database.execSQL("CREATE TABLE `OcsProjectResource` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `name` TEXT, `status` INTEGER NOT NULL, `lastModified` INTEGER, `lastModifiedLocal` INTEGER, `projectId` INTEGER NOT NULL, `type` TEXT , `link` TEXT , `path` TEXT, `iconUrl` TEXT , `previewAvailable` INTEGER, `mimetype` TEXT, FOREIGN KEY(`projectId`) REFERENCES `OcsProject`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE)");
- database.execSQL("CREATE INDEX `index_projectResource_accID` ON `OcsProjectResource` (`accountId`)");
- database.execSQL("CREATE INDEX `index_projectResource_projectId` ON `OcsProjectResource` (`projectId`)");
- database.execSQL("CREATE UNIQUE INDEX `index_OcsProjectResource_accountId_id` ON `OcsProjectResource` (`accountId`, `id`, `projectId`)");
- database.execSQL("CREATE INDEX `index_OcsProjectResource_id` ON `OcsProjectResource` (`id`)");
- database.execSQL("CREATE INDEX `index_OcsProjectResource_lastModifiedLocal` ON `OcsProjectResource` (`lastModifiedLocal`)");
-
- database.execSQL("CREATE TABLE `JoinCardWithProject` (`status` INTEGER NOT NULL, `projectId` INTEGER NOT NULL, `cardId` INTEGER NOT NULL, PRIMARY KEY (`projectId`, `cardId`), FOREIGN KEY(`cardId`) REFERENCES `Card`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE, FOREIGN KEY(`projectId`) REFERENCES `OcsProject`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE)");
- database.execSQL("CREATE INDEX `index_JoinCardWithProject_projectId` ON `JoinCardWithProject` (`projectId`)");
- database.execSQL("CREATE INDEX `index_JoinCardWithProject_cardId` ON `JoinCardWithProject` (`cardId`)");
- }
- };
-
- private static final Migration MIGRATION_17_18 = new Migration(17, 18) {
- @Override
- public void migrate(SupportSQLiteDatabase database) {
- // https://github.com/stefan-niedermann/nextcloud-deck/issues/435
- database.execSQL("ALTER TABLE `Account` ADD `etag` TEXT");
- }
- };
- private static final Migration MIGRATION_18_19 = new Migration(18, 19) {
- @Override
- public void migrate(SupportSQLiteDatabase database) {
- // https://github.com/stefan-niedermann/nextcloud-deck/issues/619
- database.execSQL("DROP INDEX `index_OcsProjectResource_accountId_id`");
- database.execSQL("ALTER TABLE `OcsProjectResource` ADD `idString` TEXT");
- database.execSQL("CREATE UNIQUE INDEX `index_OcsProjectResource_accountId_id` ON `OcsProjectResource` (`accountId`, `id`, `idString`, `projectId`)");
- }
- };
- private static final Migration MIGRATION_19_20 = new Migration(19, 20) {
- @Override
- public void migrate(SupportSQLiteDatabase database) {
- // https://github.com/stefan-niedermann/nextcloud-deck/issues/492
- // https://github.com/stefan-niedermann/nextcloud-deck/issues/631
- database.execSQL("CREATE TABLE `UserInGroup` (`groupId` INTEGER NOT NULL, `memberId` INTEGER NOT NULL, " +
- "primary KEY(`groupId`, `memberId`), " +
- "FOREIGN KEY(`groupId`) REFERENCES `User`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE, " +
- "FOREIGN KEY(`memberId`) REFERENCES `User`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE)");
- database.execSQL("CREATE UNIQUE INDEX `unique_idx_group_member` ON `UserInGroup` (`groupId`, `memberId`)");
- database.execSQL("CREATE INDEX `index_UserInGroup_groupId` ON `UserInGroup` (`groupId`)");
- database.execSQL("CREATE INDEX `index_UserInGroup_memberId` ON `UserInGroup` (`memberId`)");
-
- database.execSQL("CREATE TABLE `UserInBoard` (`userId` INTEGER NOT NULL, `boardId` INTEGER NOT NULL, " +
- "primary KEY(`userId`, `boardId`), " +
- "FOREIGN KEY(`userId`) REFERENCES `User`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE, " +
- "FOREIGN KEY(`boardId`) REFERENCES `Board`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE)");
- database.execSQL("CREATE UNIQUE INDEX `unique_idx_user_board` ON `UserInBoard` (`userId`, `boardId`)");
- database.execSQL("CREATE INDEX `index_UserInBoard_userId` ON `UserInBoard` (`userId`)");
- database.execSQL("CREATE INDEX `index_UserInBoard_boardId` ON `UserInBoard` (`boardId`)");
- }
- };
-
- private static final Migration MIGRATION_20_21 = new Migration(20, 21) {
- @Override
- public void migrate(SupportSQLiteDatabase database) {
- // https://github.com/stefan-niedermann/nextcloud-deck/issues/556
- String suffix = "_new";
- {
- String tableName = "Account";
- database.execSQL("CREATE TABLE `" + tableName + suffix + "` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` TEXT NOT NULL, `userName` TEXT NOT NULL, `url` TEXT NOT NULL, " +
- "`color` INTEGER NOT NULL DEFAULT 0, `textColor` INTEGER NOT NULL DEFAULT 0, `serverDeckVersion` TEXT NOT NULL DEFAULT '0.6.4', `maintenanceEnabled` INTEGER NOT NULL DEFAULT 0, `etag` TEXT)");
- Cursor cursor = database.query("select * from `" + tableName + "`");
- while (cursor.moveToNext()) {
- String colorAsString1 = cursor.getString(4); // color
- String colorAsString2 = cursor.getString(5); // textColor
-
- @ColorInt int color1;
- @ColorInt int color2;
- try {
- color1 = Color.parseColor(ColorUtil.INSTANCE.formatColorToParsableHexString(colorAsString1));
- color2 = Color.parseColor(ColorUtil.INSTANCE.formatColorToParsableHexString(colorAsString2));
- } catch (Exception e) {
- color1 = Color.GRAY;
- color2 = Color.GRAY;
- }
- database.execSQL("Insert into `" + tableName + suffix + "` VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", new Object[]{
- cursor.getLong(0), cursor.getString(1), cursor.getString(2), cursor.getString(3),
- color1, color2, cursor.getString(6), cursor.getInt(7), cursor.getString(8)});
-
- }
-
-
- database.execSQL("DROP TABLE `" + tableName + "`");
- database.execSQL("ALTER TABLE `" + tableName + suffix + "` RENAME TO `" + tableName + "`");
- database.execSQL("CREATE UNIQUE INDEX `index_Account_name` ON `" + tableName + "` (`name`)");
- database.execSQL("UPDATE SQLITE_SEQUENCE SET seq = (select max(id) from " + tableName + ") WHERE name = ?", new Object[]{tableName});
- }
- {
- String tableName = "Board";
- database.execSQL("CREATE TABLE `" + tableName + suffix + "` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `status` INTEGER NOT NULL, " +
- "`lastModified` INTEGER, `lastModifiedLocal` INTEGER, `title` TEXT, `ownerId` INTEGER NOT NULL, `color` INTEGER, " +
- "`archived` INTEGER NOT NULL, `shared` INTEGER NOT NULL, `deletedAt` INTEGER, `permissionRead` INTEGER NOT NULL, " +
- "`permissionEdit` INTEGER NOT NULL, `permissionManage` INTEGER NOT NULL, `permissionShare` INTEGER NOT NULL, " +
- "FOREIGN KEY(`ownerId`) REFERENCES `User`(`localId`) ON UPDATE NO ACTION ON DELETE SET NULL )");
- Cursor cursor = database.query("select * from `" + tableName + "`");
- while (cursor.moveToNext()) {
- String colorAsString1 = cursor.getString(8); // color
-
- @ColorInt int color1;
- try {
- color1 = Color.parseColor(ColorUtil.INSTANCE.formatColorToParsableHexString(colorAsString1));
- } catch (Exception e) {
- color1 = Color.GRAY;
- }
- database.execSQL("Insert into `" + tableName + suffix + "` VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", new Object[]{
- cursor.getLong(0), cursor.getLong(1), cursor.getLong(2), cursor.getInt(3),
- cursor.getLong(4), cursor.getLong(5), cursor.getString(6), cursor.getLong(7), color1,
- cursor.getInt(9), cursor.getInt(10), cursor.getInt(11), cursor.getInt(12),
- cursor.getInt(13), cursor.getInt(14), cursor.getInt(15)
- });
-
- }
-
-
- database.execSQL("DROP TABLE `" + tableName + "`");
- database.execSQL("ALTER TABLE `" + tableName + suffix + "` RENAME TO `" + tableName + "`");
- database.execSQL("CREATE INDEX `index_Board_accountId` ON `" + tableName + "` (`accountId`)");
- database.execSQL("CREATE UNIQUE INDEX `index_Board_accountId_id` ON `" + tableName + "` (`accountId`, `id`)");
- database.execSQL("CREATE INDEX `index_Board_id` ON `" + tableName + "` (`id`)");
- database.execSQL("CREATE INDEX `index_Board_ownerId` ON `" + tableName + "` (`ownerId`)");
- database.execSQL("CREATE INDEX `index_Board_lastModifiedLocal` ON `" + tableName + "` (`lastModifiedLocal`)");
- database.execSQL("UPDATE SQLITE_SEQUENCE SET seq = (select max(id) from " + tableName + ") WHERE name = ?", new Object[]{tableName});
- }
- {
- String tableName = "Label";
- database.execSQL("CREATE TABLE `" + tableName + suffix + "` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `status` INTEGER NOT NULL, " +
- "`lastModified` INTEGER, `lastModifiedLocal` INTEGER, `title` TEXT, `color` INTEGER NOT NULL DEFAULT 0, `boardId` INTEGER NOT NULL, " +
- "FOREIGN KEY(`boardId`) REFERENCES `Board`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE )");
- Cursor cursor = database.query("select * from `" + tableName + "`");
- while (cursor.moveToNext()) {
- String colorAsString1 = cursor.getString(7); // color
-
- @ColorInt int color1;
- try {
- color1 = Color.parseColor(ColorUtil.INSTANCE.formatColorToParsableHexString(colorAsString1));
- } catch (Exception e) {
- color1 = Color.GRAY;
- }
- database.execSQL("Insert into `" + tableName + suffix + "` VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", new Object[]{
- cursor.getLong(0), cursor.getLong(1), cursor.getLong(2), cursor.getInt(3),
- cursor.getLong(4), cursor.getLong(5), cursor.getString(6), color1, cursor.getLong(8)});
-
- }
-
-
- database.execSQL("DROP TABLE `" + tableName + "`");
- database.execSQL("ALTER TABLE `" + tableName + suffix + "` RENAME TO `" + tableName + "`");
- database.execSQL("CREATE UNIQUE INDEX `index_Label_accountId_id` ON `" + tableName + "` (`accountId`, `id`)");
- database.execSQL("CREATE INDEX `index_Label_boardId` ON `" + tableName + "` (`boardId`)");
- database.execSQL("CREATE INDEX `index_Label_accountId` ON `" + tableName + "` (`accountId`)");
- database.execSQL("CREATE UNIQUE INDEX `idx_label_title_unique` ON `" + tableName + "` (`boardId`, `title`)");
- database.execSQL("CREATE INDEX `index_Label_id` ON `" + tableName + "` (`id`)");
- database.execSQL("CREATE INDEX `index_Label_lastModifiedLocal` ON `" + tableName + "` (`lastModifiedLocal`)");
- database.execSQL("UPDATE SQLITE_SEQUENCE SET seq = (select max(id) from " + tableName + ") WHERE name = ?", new Object[]{tableName});
- }
- }
- };
-
- private static final Migration MIGRATION_22_23 = new Migration(22, 23) {
- @Override
- public void migrate(SupportSQLiteDatabase database) {
- // https://github.com/stefan-niedermann/nextcloud-deck/issues/359
- database.execSQL("ALTER TABLE `Account` ADD `boardsEtag` TEXT");
- database.execSQL("ALTER TABLE `Board` ADD `etag` TEXT");
- database.execSQL("ALTER TABLE `Stack` ADD `etag` TEXT");
- database.execSQL("ALTER TABLE `Card` ADD `etag` TEXT");
- database.execSQL("ALTER TABLE `Label` ADD `etag` TEXT");
- database.execSQL("ALTER TABLE `AccessControl` ADD `etag` TEXT");
- database.execSQL("ALTER TABLE `Attachment` ADD `etag` TEXT");
- database.execSQL("ALTER TABLE `User` ADD `etag` TEXT");
- database.execSQL("ALTER TABLE `DeckComment` ADD `etag` TEXT");
- database.execSQL("ALTER TABLE `Activity` ADD `etag` TEXT");
- database.execSQL("ALTER TABLE `OcsProject` ADD `etag` TEXT");
- database.execSQL("ALTER TABLE `OcsProjectResource` ADD `etag` TEXT");
- }
- };
-
- /**
- * Reset ETags (comments weren't loading due to bug)
- */
- private static final Migration MIGRATION_24_25 = new Migration(24, 25) {
- @Override
- public void migrate(SupportSQLiteDatabase database) {
- database.execSQL("UPDATE `Account` SET `boardsEtag` = NULL");
- database.execSQL("UPDATE `Board` SET `etag` = NULL");
- database.execSQL("UPDATE `Stack` SET `etag` = NULL");
- database.execSQL("UPDATE `Card` SET `etag` = NULL");
- }
- };
-
- private static final Migration MIGRATION_25_26 = new Migration(25, 26) {
- @Override
- public void migrate(SupportSQLiteDatabase database) {
- database.execSQL("CREATE TABLE `FilterWidget` (`id` INTEGER PRIMARY KEY NOT NULL, `title` TEXT, `dueType` INTEGER, `widgetType` INTEGER NOT NULL)");
- database.execSQL("CREATE TABLE `FilterWidgetAccount` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterWidgetId` INTEGER, `accountId` INTEGER, `includeNoUser` INTEGER NOT NULL, `includeNoProject` INTEGER NOT NULL, FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`filterWidgetId`) REFERENCES `FilterWidget`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
- database.execSQL("CREATE TABLE `FilterWidgetBoard` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterAccountId` INTEGER, `boardId` INTEGER, `includeNoLabel` INTEGER NOT NULL, FOREIGN KEY(`boardId`) REFERENCES `Board`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`filterAccountId`) REFERENCES `FilterWidgetAccount`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
- database.execSQL("CREATE TABLE `FilterWidgetLabel` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterBoardId` INTEGER, `labelId` INTEGER, FOREIGN KEY(`labelId`) REFERENCES `Label`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`filterBoardId`) REFERENCES `FilterWidgetBoard`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
- database.execSQL("CREATE TABLE `FilterWidgetSort` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterWidgetId` INTEGER, `direction` INTEGER NOT NULL, `criteria` INTEGER NOT NULL, `ruleOrder` INTEGER NOT NULL, FOREIGN KEY(`filterWidgetId`) REFERENCES `FilterWidget`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
- database.execSQL("CREATE TABLE `FilterWidgetStack` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterBoardId` INTEGER, `stackId` INTEGER, FOREIGN KEY(`stackId`) REFERENCES `Stack`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`filterBoardId`) REFERENCES `FilterWidgetBoard`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
- database.execSQL("CREATE TABLE `FilterWidgetUser` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterAccountId` INTEGER, `userId` INTEGER, FOREIGN KEY(`userId`) REFERENCES `User`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`filterAccountId`) REFERENCES `FilterWidgetAccount`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
- database.execSQL("CREATE TABLE `FilterWidgetProject` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterAccountId` INTEGER, `projectId` INTEGER, FOREIGN KEY(`projectId`) REFERENCES `OcsProject`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`filterAccountId`) REFERENCES `FilterWidgetAccount`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
- database.execSQL("CREATE INDEX `index_FilterWidgetAccount_filterWidgetId` ON `FilterWidgetAccount` (`filterWidgetId`)");
- database.execSQL("CREATE INDEX `idx_FilterWidgetAccount_accountId` ON `FilterWidgetAccount` (`accountId`)");
- database.execSQL("CREATE INDEX `idx_FilterWidgetBoard_boardId` ON `FilterWidgetBoard` (`boardId`)");
- database.execSQL("CREATE INDEX `idx_FilterWidgetBoard_filterAccountId` ON `FilterWidgetBoard` (`filterAccountId`)");
- database.execSQL("CREATE INDEX `idx_FilterWidgetLabel_filterBoardId` ON `FilterWidgetLabel` (`filterBoardId`)");
- database.execSQL("CREATE INDEX `idx_FilterWidgetLabel_labelId` ON `FilterWidgetLabel` (`labelId`)");
- database.execSQL("CREATE INDEX `idx_FilterWidgetSort_filterWidgetId` ON `FilterWidgetSort` (`filterWidgetId`)");
- database.execSQL("CREATE INDEX `idx_FilterWidgetStack_filterBoardId` ON `FilterWidgetStack` (`filterBoardId`)");
- database.execSQL("CREATE INDEX `idx_FilterWidgetStack_stackId` ON `FilterWidgetStack` (`stackId`)");
- database.execSQL("CREATE INDEX `idx_FilterWidgetUser_filterAccountId` ON `FilterWidgetUser` (`filterAccountId`)");
- database.execSQL("CREATE INDEX `idx_FilterWidgetUser_userId` ON `FilterWidgetUser` (`userId`)");
- database.execSQL("CREATE INDEX `idx_FilterWidgetProject_filterAccountId` ON `FilterWidgetProject` (`filterAccountId`)");
- database.execSQL("CREATE INDEX `idx_FilterWidgetProject_projectId` ON `FilterWidgetProject` (`projectId`)");
- database.execSQL("CREATE INDEX `unique_idx_FilterWidgetSort_filterWidgetId_criteria` ON `FilterWidgetSort` (`filterWidgetId`, `criteria`)");
- database.execSQL("CREATE INDEX `unique_idx_FilterWidgetSort_filterWidgetId_ruleOrder` ON `FilterWidgetSort` (`filterWidgetId`, `ruleOrder`)");
-
- }
- };
- private static final Migration MIGRATION_26_27 = new Migration(26, 27) {
- @Override
- public void migrate(SupportSQLiteDatabase database) {
-
- Cursor cursor = database.query("select s.localId, s.boardId, s.accountId, w.appWidgetId from `StackWidgetModel` w inner join `Stack` s on s.localId = w.stackId");
- while (cursor.moveToNext()) {
- Long localStackId = cursor.getLong(0);
- Long localBoardId = cursor.getLong(1);
- Long accountId = cursor.getLong(2);
- Long filterWidgetId = cursor.getLong(3);
-
- // widget:
- ContentValues values = new ContentValues();
- values.put("widgetType", EWidgetType.STACK_WIDGET.getId());
- values.put("id", filterWidgetId);
- database.insert("FilterWidget", SQLiteDatabase.CONFLICT_NONE, values);
-
- // account
- values = new ContentValues();
- values.put("filterWidgetId", filterWidgetId);
- values.put("accountId", accountId);
- values.put("includeNoUser", false);
- values.put("includeNoProject", false);
- long filterWidgetAccountId = database.insert("FilterWidgetAccount", SQLiteDatabase.CONFLICT_NONE, values);
-
- // board
- values = new ContentValues();
- values.put("filterAccountId", filterWidgetAccountId);
- values.put("boardId", localBoardId);
- values.put("includeNoLabel", false);
- long filterWidgetBoardId = database.insert("FilterWidgetBoard", SQLiteDatabase.CONFLICT_NONE, values);
-
- // stack
- values = new ContentValues();
- values.put("filterBoardId", filterWidgetBoardId);
- values.put("stackId", localStackId);
- database.insert("FilterWidgetStack", SQLiteDatabase.CONFLICT_NONE, values);
-
-
- }
-
- // cleanup
- database.execSQL("DROP TABLE `StackWidgetModel`");
- }
- };
-
- private static final Migration MIGRATION_27_28 = new Migration(27, 28) {
- @Override
- public void migrate(SupportSQLiteDatabase database) {
- database.execSQL("ALTER TABLE `Attachment` ADD COLUMN `fileId` INTEGER");
- }
- };
-
- /**
- * Reset ETags for cards because <a href="https://github.com/nextcloud/deck/issues/2874">the attachments for this card might not be complete</a>.
- */
- private static final Migration MIGRATION_28_29 = new Migration(28, 29) {
- @Override
- public void migrate(SupportSQLiteDatabase database) {
- database.execSQL("UPDATE `Account` SET `boardsEtag` = NULL");
- database.execSQL("UPDATE `Board` SET `etag` = NULL");
- database.execSQL("UPDATE `Stack` SET `etag` = NULL");
- database.execSQL("UPDATE `Card` SET `etag` = NULL");
- }
- };
-
-
public static final RoomDatabase.Callback ON_CREATE_CALLBACK = new RoomDatabase.Callback() {
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
@@ -552,66 +163,27 @@ public abstract class DeckDatabase extends RoomDatabase {
context,
DeckDatabase.class,
DECK_DB_NAME)
- .addMigrations(MIGRATION_8_9)
- .addMigrations(MIGRATION_9_10)
- .addMigrations(MIGRATION_10_11)
- .addMigrations(MIGRATION_11_12)
- .addMigrations(MIGRATION_12_13)
- .addMigrations(MIGRATION_13_14)
- .addMigrations(new Migration(14, 15) {
- @Override
- public void migrate(@NonNull SupportSQLiteDatabase database) {
- // https://github.com/stefan-niedermann/nextcloud-deck/issues/570
- SyncWorker.update(context);
- // https://github.com/stefan-niedermann/nextcloud-deck/issues/525
- PreferenceManager
- .getDefaultSharedPreferences(context)
- .edit()
- .remove("it.niedermann.nextcloud.deck.theme_text")
- .apply();
- }
- })
- .addMigrations(MIGRATION_15_16)
- .addMigrations(MIGRATION_16_17)
- .addMigrations(MIGRATION_17_18)
- .addMigrations(MIGRATION_18_19)
- .addMigrations(MIGRATION_19_20)
- .addMigrations(MIGRATION_20_21)
- .addMigrations(new Migration(21, 22) {
- @Override
- public void migrate(@NonNull SupportSQLiteDatabase database) {
- // https://github.com/stefan-niedermann/nextcloud-deck/issues/715
- final SharedPreferences.Editor lastSyncPref = context.getApplicationContext().getSharedPreferences("it.niedermann.nextcloud.deck.last_sync", Context.MODE_PRIVATE).edit();
- Cursor cursor = database.query("select id from `Account`");
- while (cursor.moveToNext()) {
- lastSyncPref.remove("lS_" + cursor.getLong(0));
- }
- cursor.close();
- lastSyncPref.apply();
- }
- })
- .addMigrations(MIGRATION_22_23)
- .addMigrations(new Migration(23, 24) {
- @Override
- public void migrate(@NonNull SupportSQLiteDatabase database) {
- // https://github.com/stefan-niedermann/nextcloud-deck/issues/392
- SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
- final String themePref = context.getString(R.string.pref_key_dark_theme);
-
- if (sharedPreferences.contains(themePref)) {
- SharedPreferences.Editor editor = sharedPreferences.edit();
- final boolean darkTheme = sharedPreferences.getBoolean(themePref, false);
- editor.remove(themePref);
- editor.putString(themePref, darkTheme ? context.getString(R.string.pref_value_theme_dark) : context.getString(R.string.pref_value_theme_light));
- editor.apply();
- }
- }
- })
- .addMigrations(MIGRATION_24_25)
- .addMigrations(MIGRATION_25_26)
- .addMigrations(MIGRATION_26_27)
- .addMigrations(MIGRATION_27_28)
- .addMigrations(MIGRATION_28_29)
+ .addMigrations(new Migration_8_9())
+ .addMigrations(new Migration_9_10())
+ .addMigrations(new Migration_10_11())
+ .addMigrations(new Migration_11_12())
+ .addMigrations(new Migration_12_13())
+ .addMigrations(new Migration_13_14())
+ .addMigrations(new Migration_14_15(context))
+ .addMigrations(new Migration_15_16())
+ .addMigrations(new Migration_16_17())
+ .addMigrations(new Migration_17_18())
+ .addMigrations(new Migration_18_19())
+ .addMigrations(new Migration_19_20())
+ .addMigrations(new Migration_20_21())
+ .addMigrations(new Migration_21_22(context))
+ .addMigrations(new Migration_22_23())
+ .addMigrations(new Migration_23_24(context))
+ .addMigrations(new Migration_24_25())
+ .addMigrations(new Migration_25_26())
+ .addMigrations(new Migration_26_27())
+ .addMigrations(new Migration_27_28())
+ .addMigrations(new Migration_28_29())
.fallbackToDestructiveMigration()
.addCallback(ON_CREATE_CALLBACK)
.build();
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_10_11.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_10_11.java
new file mode 100644
index 000000000..5da5e0451
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_10_11.java
@@ -0,0 +1,56 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import android.database.Cursor;
+
+import androidx.annotation.NonNull;
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+import it.niedermann.nextcloud.deck.model.enums.DBStatus;
+
+public class Migration_10_11 extends Migration {
+
+ public Migration_10_11() {
+ super(10, 11);
+ }
+
+ @Override
+ public void migrate(@NonNull SupportSQLiteDatabase database) {
+ // replace duplicates with the server-known ones
+ Cursor duplucatesCursor = database.query("SELECT boardId, title, count(*) FROM Label group by boardid, title having count(*) > 1");
+ if (duplucatesCursor != null && duplucatesCursor.moveToFirst()) {
+ do {
+ long boardId = duplucatesCursor.getLong(0);
+ String title = duplucatesCursor.getString(1);
+ Cursor singleDuplicateCursor = database.query("select localId from Label where boardId = ? and title = ? order by id desc", new Object[]{boardId, title});
+ if (singleDuplicateCursor != null && singleDuplicateCursor.moveToFirst()) {
+ long idToUse = -1;
+ do {
+ if (idToUse < 0) {
+ // desc order -> first one is the one with remote ID or a random one. keep this one.
+ idToUse = singleDuplicateCursor.getLong(0);
+ continue;
+ }
+ long idToReplace = singleDuplicateCursor.getLong(0);
+ Cursor cardsAssignedToDuplicateCursor = database.query("select cardId, exists(select 1 from JoinCardWithLabel ij where ij.labelId = ? and ij.cardId = cardId) " +
+ "from JoinCardWithLabel where labelId = ?", new Object[]{idToUse, idToReplace});
+ if (cardsAssignedToDuplicateCursor != null && cardsAssignedToDuplicateCursor.moveToFirst()) {
+ do {
+ long cardId = cardsAssignedToDuplicateCursor.getLong(0);
+ boolean hasDestinationLabelAssigned = cardsAssignedToDuplicateCursor.getInt(1) > 0;
+ database.execSQL("DELETE FROM JoinCardWithLabel where labelId = ? and cardId = ?", new Object[]{idToReplace, cardId});
+
+ if (!hasDestinationLabelAssigned) {
+ database.execSQL("INSERT INTO JoinCardWithLabel (status,labelId,cardId) VALUES (?, ?, ?)", new Object[]{DBStatus.LOCAL_EDITED.getId(), idToUse, cardId});
+ }
+ } while (cardsAssignedToDuplicateCursor.moveToNext());
+ }
+ database.execSQL("DELETE FROM Label where localId = ?", new Object[]{idToReplace});
+ } while (singleDuplicateCursor.moveToNext());
+ }
+ } while (duplucatesCursor.moveToNext());
+ }
+ // database.execSQL("DELETE FROM Label WHERE id IS NULL AND EXISTS(SELECT 1 FROM Label il WHERE il.boardId = boardId AND il.title = title AND id IS NOT NULL)");
+ database.execSQL("CREATE UNIQUE INDEX idx_label_title_unique ON Label(boardId, title)");
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_11_12.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_11_12.java
new file mode 100644
index 000000000..e20fca274
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_11_12.java
@@ -0,0 +1,17 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+public class Migration_11_12 extends Migration {
+
+ public Migration_11_12() {
+ super(11, 12);
+ }
+
+ @Override
+ public void migrate(SupportSQLiteDatabase database) {
+ database.execSQL("CREATE TABLE `SingleCardWidgetModel` (`widgetId` INTEGER PRIMARY KEY, `accountId` INTEGER, `boardId` INTEGER, `cardId` INTEGER, FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE, FOREIGN KEY(`boardId`) REFERENCES `Board`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE, FOREIGN KEY(`cardId`) REFERENCES `Card`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE )");
+ database.execSQL("CREATE INDEX `index_SingleCardWidgetModel_cardId` ON `SingleCardWidgetModel` (`cardId`)");
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_12_13.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_12_13.java
new file mode 100644
index 000000000..8a85f1651
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_12_13.java
@@ -0,0 +1,17 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+public class Migration_12_13 extends Migration {
+
+ public Migration_12_13() {
+ super(12, 13);
+ }
+
+ @Override
+ public void migrate(SupportSQLiteDatabase database) {
+ database.execSQL("CREATE INDEX `idx_cardWidgetModel_accountId` ON `SingleCardWidgetModel` (`accountId`)");
+ database.execSQL("CREATE INDEX `idx_cardWidgetModel_boardId` ON `SingleCardWidgetModel` (`boardId`)");
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_13_14.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_13_14.java
new file mode 100644
index 000000000..28737c367
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_13_14.java
@@ -0,0 +1,17 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+public class Migration_13_14 extends Migration {
+
+ public Migration_13_14() {
+ super(13, 14);
+ }
+
+ @Override
+ public void migrate(SupportSQLiteDatabase database) {
+ database.execSQL("ALTER TABLE `DeckComment` ADD `parentId` INTEGER REFERENCES DeckComment(localId) ON DELETE CASCADE");
+ database.execSQL("CREATE INDEX `idx_comment_parentID` ON DeckComment(parentId)");
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_14_15.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_14_15.java
new file mode 100644
index 000000000..b238e1d99
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_14_15.java
@@ -0,0 +1,33 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.preference.PreferenceManager;
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+import it.niedermann.nextcloud.deck.persistence.sync.SyncWorker;
+
+public class Migration_14_15 extends Migration {
+
+ @NonNull
+ private final Context context;
+
+ public Migration_14_15(@NonNull Context context) {
+ super(14, 15);
+ this.context = context;
+ }
+
+ @Override
+ public void migrate(@NonNull SupportSQLiteDatabase database) {
+ // https://github.com/stefan-niedermann/nextcloud-deck/issues/570
+ SyncWorker.update(context);
+ // https://github.com/stefan-niedermann/nextcloud-deck/issues/525
+ PreferenceManager
+ .getDefaultSharedPreferences(context)
+ .edit()
+ .remove("it.niedermann.nextcloud.deck.theme_text")
+ .apply();
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_15_16.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_15_16.java
new file mode 100644
index 000000000..e04b7a98f
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_15_16.java
@@ -0,0 +1,20 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+public class Migration_15_16 extends Migration {
+
+ public Migration_15_16() {
+ super(15, 16);
+ }
+
+ @Override
+ public void migrate(SupportSQLiteDatabase database) {
+ database.execSQL("CREATE TABLE `StackWidgetModel` (`appWidgetId` INTEGER PRIMARY KEY, `accountId` INTEGER, `stackId` INTEGER, `darkTheme` INTEGER CHECK (`darkTheme` IN (0,1)) NOT NULL, " +
+ "FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE, " +
+ "FOREIGN KEY(`stackId`) REFERENCES `Stack`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE )");
+ database.execSQL("CREATE INDEX `index_StackWidgetModel_stackId` ON `StackWidgetModel` (`stackId`)");
+ database.execSQL("CREATE INDEX `index_StackWidgetModel_accountId` ON `StackWidgetModel` (`accountId`)");
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_16_17.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_16_17.java
new file mode 100644
index 000000000..2aad359b4
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_16_17.java
@@ -0,0 +1,31 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+public class Migration_16_17 extends Migration {
+
+ public Migration_16_17() {
+ super(16, 17);
+ }
+
+ @Override
+ public void migrate(SupportSQLiteDatabase database) {
+ database.execSQL("CREATE TABLE `OcsProject` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `name` TEXT NOT NULL, `status` INTEGER NOT NULL, `lastModified` INTEGER, `lastModifiedLocal` INTEGER)");
+ database.execSQL("CREATE UNIQUE INDEX `index_OcsProject_accountId_id` ON `OcsProject` (`accountId`, `id`)");
+ database.execSQL("CREATE INDEX `index_project_accID` ON `OcsProject` (`accountId`)");
+ database.execSQL("CREATE INDEX `index_OcsProject_id` ON `OcsProject` (`id`)");
+ database.execSQL("CREATE INDEX `index_OcsProject_lastModifiedLocal` ON `OcsProject` (`lastModifiedLocal`)");
+
+ database.execSQL("CREATE TABLE `OcsProjectResource` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `name` TEXT, `status` INTEGER NOT NULL, `lastModified` INTEGER, `lastModifiedLocal` INTEGER, `projectId` INTEGER NOT NULL, `type` TEXT , `link` TEXT , `path` TEXT, `iconUrl` TEXT , `previewAvailable` INTEGER, `mimetype` TEXT, FOREIGN KEY(`projectId`) REFERENCES `OcsProject`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE)");
+ database.execSQL("CREATE INDEX `index_projectResource_accID` ON `OcsProjectResource` (`accountId`)");
+ database.execSQL("CREATE INDEX `index_projectResource_projectId` ON `OcsProjectResource` (`projectId`)");
+ database.execSQL("CREATE UNIQUE INDEX `index_OcsProjectResource_accountId_id` ON `OcsProjectResource` (`accountId`, `id`, `projectId`)");
+ database.execSQL("CREATE INDEX `index_OcsProjectResource_id` ON `OcsProjectResource` (`id`)");
+ database.execSQL("CREATE INDEX `index_OcsProjectResource_lastModifiedLocal` ON `OcsProjectResource` (`lastModifiedLocal`)");
+
+ database.execSQL("CREATE TABLE `JoinCardWithProject` (`status` INTEGER NOT NULL, `projectId` INTEGER NOT NULL, `cardId` INTEGER NOT NULL, PRIMARY KEY (`projectId`, `cardId`), FOREIGN KEY(`cardId`) REFERENCES `Card`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE, FOREIGN KEY(`projectId`) REFERENCES `OcsProject`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE)");
+ database.execSQL("CREATE INDEX `index_JoinCardWithProject_projectId` ON `JoinCardWithProject` (`projectId`)");
+ database.execSQL("CREATE INDEX `index_JoinCardWithProject_cardId` ON `JoinCardWithProject` (`cardId`)");
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_17_18.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_17_18.java
new file mode 100644
index 000000000..42151e3c6
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_17_18.java
@@ -0,0 +1,17 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+public class Migration_17_18 extends Migration {
+
+ public Migration_17_18() {
+ super(17, 18);
+ }
+
+ @Override
+ public void migrate(SupportSQLiteDatabase database) {
+ // https://github.com/stefan-niedermann/nextcloud-deck/issues/435
+ database.execSQL("ALTER TABLE `Account` ADD `etag` TEXT");
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_18_19.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_18_19.java
new file mode 100644
index 000000000..d45f99c31
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_18_19.java
@@ -0,0 +1,19 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+public class Migration_18_19 extends Migration {
+
+ public Migration_18_19() {
+ super(18, 19);
+ }
+
+ @Override
+ public void migrate(SupportSQLiteDatabase database) {
+ // https://github.com/stefan-niedermann/nextcloud-deck/issues/619
+ database.execSQL("DROP INDEX `index_OcsProjectResource_accountId_id`");
+ database.execSQL("ALTER TABLE `OcsProjectResource` ADD `idString` TEXT");
+ database.execSQL("CREATE UNIQUE INDEX `index_OcsProjectResource_accountId_id` ON `OcsProjectResource` (`accountId`, `id`, `idString`, `projectId`)");
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_19_20.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_19_20.java
new file mode 100644
index 000000000..b5abb8945
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_19_20.java
@@ -0,0 +1,32 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+public class Migration_19_20 extends Migration {
+
+ public Migration_19_20() {
+ super(19, 20);
+ }
+
+ @Override
+ public void migrate(SupportSQLiteDatabase database) {
+ // https://github.com/stefan-niedermann/nextcloud-deck/issues/492
+ // https://github.com/stefan-niedermann/nextcloud-deck/issues/631
+ database.execSQL("CREATE TABLE `UserInGroup` (`groupId` INTEGER NOT NULL, `memberId` INTEGER NOT NULL, " +
+ "primary KEY(`groupId`, `memberId`), " +
+ "FOREIGN KEY(`groupId`) REFERENCES `User`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE, " +
+ "FOREIGN KEY(`memberId`) REFERENCES `User`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE)");
+ database.execSQL("CREATE UNIQUE INDEX `unique_idx_group_member` ON `UserInGroup` (`groupId`, `memberId`)");
+ database.execSQL("CREATE INDEX `index_UserInGroup_groupId` ON `UserInGroup` (`groupId`)");
+ database.execSQL("CREATE INDEX `index_UserInGroup_memberId` ON `UserInGroup` (`memberId`)");
+
+ database.execSQL("CREATE TABLE `UserInBoard` (`userId` INTEGER NOT NULL, `boardId` INTEGER NOT NULL, " +
+ "primary KEY(`userId`, `boardId`), " +
+ "FOREIGN KEY(`userId`) REFERENCES `User`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE, " +
+ "FOREIGN KEY(`boardId`) REFERENCES `Board`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE)");
+ database.execSQL("CREATE UNIQUE INDEX `unique_idx_user_board` ON `UserInBoard` (`userId`, `boardId`)");
+ database.execSQL("CREATE INDEX `index_UserInBoard_userId` ON `UserInBoard` (`userId`)");
+ database.execSQL("CREATE INDEX `index_UserInBoard_boardId` ON `UserInBoard` (`boardId`)");
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_20_21.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_20_21.java
new file mode 100644
index 000000000..4b182b2ad
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_20_21.java
@@ -0,0 +1,121 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import android.database.Cursor;
+import android.graphics.Color;
+
+import androidx.annotation.ColorInt;
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+import it.niedermann.android.util.ColorUtil;
+
+public class Migration_20_21 extends Migration {
+
+ public Migration_20_21() {
+ super(20, 21);
+ }
+
+ @Override
+ public void migrate(SupportSQLiteDatabase database) {
+ // https://github.com/stefan-niedermann/nextcloud-deck/issues/556
+ String suffix = "_new";
+ {
+ String tableName = "Account";
+ database.execSQL("CREATE TABLE `" + tableName + suffix + "` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `name` TEXT NOT NULL, `userName` TEXT NOT NULL, `url` TEXT NOT NULL, " +
+ "`color` INTEGER NOT NULL DEFAULT 0, `textColor` INTEGER NOT NULL DEFAULT 0, `serverDeckVersion` TEXT NOT NULL DEFAULT '0.6.4', `maintenanceEnabled` INTEGER NOT NULL DEFAULT 0, `etag` TEXT)");
+ Cursor cursor = database.query("select * from `" + tableName + "`");
+ while (cursor.moveToNext()) {
+ String colorAsString1 = cursor.getString(4); // color
+ String colorAsString2 = cursor.getString(5); // textColor
+
+ @ColorInt int color1;
+ @ColorInt int color2;
+ try {
+ color1 = Color.parseColor(ColorUtil.INSTANCE.formatColorToParsableHexString(colorAsString1));
+ color2 = Color.parseColor(ColorUtil.INSTANCE.formatColorToParsableHexString(colorAsString2));
+ } catch (Exception e) {
+ color1 = Color.GRAY;
+ color2 = Color.GRAY;
+ }
+ database.execSQL("Insert into `" + tableName + suffix + "` VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", new Object[]{
+ cursor.getLong(0), cursor.getString(1), cursor.getString(2), cursor.getString(3),
+ color1, color2, cursor.getString(6), cursor.getInt(7), cursor.getString(8)});
+
+ }
+
+
+ database.execSQL("DROP TABLE `" + tableName + "`");
+ database.execSQL("ALTER TABLE `" + tableName + suffix + "` RENAME TO `" + tableName + "`");
+ database.execSQL("CREATE UNIQUE INDEX `index_Account_name` ON `" + tableName + "` (`name`)");
+ database.execSQL("UPDATE SQLITE_SEQUENCE SET seq = (select max(id) from " + tableName + ") WHERE name = ?", new Object[]{tableName});
+ }
+ {
+ String tableName = "Board";
+ database.execSQL("CREATE TABLE `" + tableName + suffix + "` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `status` INTEGER NOT NULL, " +
+ "`lastModified` INTEGER, `lastModifiedLocal` INTEGER, `title` TEXT, `ownerId` INTEGER NOT NULL, `color` INTEGER, " +
+ "`archived` INTEGER NOT NULL, `shared` INTEGER NOT NULL, `deletedAt` INTEGER, `permissionRead` INTEGER NOT NULL, " +
+ "`permissionEdit` INTEGER NOT NULL, `permissionManage` INTEGER NOT NULL, `permissionShare` INTEGER NOT NULL, " +
+ "FOREIGN KEY(`ownerId`) REFERENCES `User`(`localId`) ON UPDATE NO ACTION ON DELETE SET NULL )");
+ Cursor cursor = database.query("select * from `" + tableName + "`");
+ while (cursor.moveToNext()) {
+ String colorAsString1 = cursor.getString(8); // color
+
+ @ColorInt int color1;
+ try {
+ color1 = Color.parseColor(ColorUtil.INSTANCE.formatColorToParsableHexString(colorAsString1));
+ } catch (Exception e) {
+ color1 = Color.GRAY;
+ }
+ database.execSQL("Insert into `" + tableName + suffix + "` VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", new Object[]{
+ cursor.getLong(0), cursor.getLong(1), cursor.getLong(2), cursor.getInt(3),
+ cursor.getLong(4), cursor.getLong(5), cursor.getString(6), cursor.getLong(7), color1,
+ cursor.getInt(9), cursor.getInt(10), cursor.getInt(11), cursor.getInt(12),
+ cursor.getInt(13), cursor.getInt(14), cursor.getInt(15)
+ });
+
+ }
+
+
+ database.execSQL("DROP TABLE `" + tableName + "`");
+ database.execSQL("ALTER TABLE `" + tableName + suffix + "` RENAME TO `" + tableName + "`");
+ database.execSQL("CREATE INDEX `index_Board_accountId` ON `" + tableName + "` (`accountId`)");
+ database.execSQL("CREATE UNIQUE INDEX `index_Board_accountId_id` ON `" + tableName + "` (`accountId`, `id`)");
+ database.execSQL("CREATE INDEX `index_Board_id` ON `" + tableName + "` (`id`)");
+ database.execSQL("CREATE INDEX `index_Board_ownerId` ON `" + tableName + "` (`ownerId`)");
+ database.execSQL("CREATE INDEX `index_Board_lastModifiedLocal` ON `" + tableName + "` (`lastModifiedLocal`)");
+ database.execSQL("UPDATE SQLITE_SEQUENCE SET seq = (select max(id) from " + tableName + ") WHERE name = ?", new Object[]{tableName});
+ }
+ {
+ String tableName = "Label";
+ database.execSQL("CREATE TABLE `" + tableName + suffix + "` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `status` INTEGER NOT NULL, " +
+ "`lastModified` INTEGER, `lastModifiedLocal` INTEGER, `title` TEXT, `color` INTEGER NOT NULL DEFAULT 0, `boardId` INTEGER NOT NULL, " +
+ "FOREIGN KEY(`boardId`) REFERENCES `Board`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE )");
+ Cursor cursor = database.query("select * from `" + tableName + "`");
+ while (cursor.moveToNext()) {
+ String colorAsString1 = cursor.getString(7); // color
+
+ @ColorInt int color1;
+ try {
+ color1 = Color.parseColor(ColorUtil.INSTANCE.formatColorToParsableHexString(colorAsString1));
+ } catch (Exception e) {
+ color1 = Color.GRAY;
+ }
+ database.execSQL("Insert into `" + tableName + suffix + "` VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", new Object[]{
+ cursor.getLong(0), cursor.getLong(1), cursor.getLong(2), cursor.getInt(3),
+ cursor.getLong(4), cursor.getLong(5), cursor.getString(6), color1, cursor.getLong(8)});
+
+ }
+
+
+ database.execSQL("DROP TABLE `" + tableName + "`");
+ database.execSQL("ALTER TABLE `" + tableName + suffix + "` RENAME TO `" + tableName + "`");
+ database.execSQL("CREATE UNIQUE INDEX `index_Label_accountId_id` ON `" + tableName + "` (`accountId`, `id`)");
+ database.execSQL("CREATE INDEX `index_Label_boardId` ON `" + tableName + "` (`boardId`)");
+ database.execSQL("CREATE INDEX `index_Label_accountId` ON `" + tableName + "` (`accountId`)");
+ database.execSQL("CREATE UNIQUE INDEX `idx_label_title_unique` ON `" + tableName + "` (`boardId`, `title`)");
+ database.execSQL("CREATE INDEX `index_Label_id` ON `" + tableName + "` (`id`)");
+ database.execSQL("CREATE INDEX `index_Label_lastModifiedLocal` ON `" + tableName + "` (`lastModifiedLocal`)");
+ database.execSQL("UPDATE SQLITE_SEQUENCE SET seq = (select max(id) from " + tableName + ") WHERE name = ?", new Object[]{tableName});
+ }
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_21_22.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_21_22.java
new file mode 100644
index 000000000..73560795a
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_21_22.java
@@ -0,0 +1,32 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+
+import androidx.annotation.NonNull;
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+public class Migration_21_22 extends Migration {
+
+ @NonNull
+ private final Context context;
+
+ public Migration_21_22(@NonNull Context context) {
+ super(21, 22);
+ this.context = context;
+ }
+
+ @Override
+ public void migrate(@NonNull SupportSQLiteDatabase database) {
+ // https://github.com/stefan-niedermann/nextcloud-deck/issues/715
+ final SharedPreferences.Editor lastSyncPref = context.getApplicationContext().getSharedPreferences("it.niedermann.nextcloud.deck.last_sync", Context.MODE_PRIVATE).edit();
+ final Cursor cursor = database.query("select id from `Account`");
+ while (cursor.moveToNext()) {
+ lastSyncPref.remove("lS_" + cursor.getLong(0));
+ }
+ cursor.close();
+ lastSyncPref.apply();
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_22_23.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_22_23.java
new file mode 100644
index 000000000..79106db19
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_22_23.java
@@ -0,0 +1,28 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+public class Migration_22_23 extends Migration {
+
+ public Migration_22_23() {
+ super(22, 23);
+ }
+
+ @Override
+ public void migrate(SupportSQLiteDatabase database) {
+ // https://github.com/stefan-niedermann/nextcloud-deck/issues/359
+ database.execSQL("ALTER TABLE `Account` ADD `boardsEtag` TEXT");
+ database.execSQL("ALTER TABLE `Board` ADD `etag` TEXT");
+ database.execSQL("ALTER TABLE `Stack` ADD `etag` TEXT");
+ database.execSQL("ALTER TABLE `Card` ADD `etag` TEXT");
+ database.execSQL("ALTER TABLE `Label` ADD `etag` TEXT");
+ database.execSQL("ALTER TABLE `AccessControl` ADD `etag` TEXT");
+ database.execSQL("ALTER TABLE `Attachment` ADD `etag` TEXT");
+ database.execSQL("ALTER TABLE `User` ADD `etag` TEXT");
+ database.execSQL("ALTER TABLE `DeckComment` ADD `etag` TEXT");
+ database.execSQL("ALTER TABLE `Activity` ADD `etag` TEXT");
+ database.execSQL("ALTER TABLE `OcsProject` ADD `etag` TEXT");
+ database.execSQL("ALTER TABLE `OcsProjectResource` ADD `etag` TEXT");
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_23_24.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_23_24.java
new file mode 100644
index 000000000..363691115
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_23_24.java
@@ -0,0 +1,37 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+import androidx.annotation.NonNull;
+import androidx.preference.PreferenceManager;
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+import it.niedermann.nextcloud.deck.R;
+
+public class Migration_23_24 extends Migration {
+
+ @NonNull
+ private final Context context;
+
+ public Migration_23_24(@NonNull Context context) {
+ super(23, 24);
+ this.context = context;
+ }
+
+ @Override
+ public void migrate(@NonNull SupportSQLiteDatabase database) {
+ // https://github.com/stefan-niedermann/nextcloud-deck/issues/392
+ final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
+ final String themePref = context.getString(R.string.pref_key_dark_theme);
+
+ if (sharedPreferences.contains(themePref)) {
+ SharedPreferences.Editor editor = sharedPreferences.edit();
+ final boolean darkTheme = sharedPreferences.getBoolean(themePref, false);
+ editor.remove(themePref);
+ editor.putString(themePref, darkTheme ? context.getString(R.string.pref_value_theme_dark) : context.getString(R.string.pref_value_theme_light));
+ editor.apply();
+ }
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_24_25.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_24_25.java
new file mode 100644
index 000000000..6d2bff544
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_24_25.java
@@ -0,0 +1,22 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+/**
+ * Reset ETags (comments weren't loading due to bug)
+ */
+public class Migration_24_25 extends Migration {
+
+ public Migration_24_25() {
+ super(24, 25);
+ }
+
+ @Override
+ public void migrate(SupportSQLiteDatabase database) {
+ database.execSQL("UPDATE `Account` SET `boardsEtag` = NULL");
+ database.execSQL("UPDATE `Board` SET `etag` = NULL");
+ database.execSQL("UPDATE `Stack` SET `etag` = NULL");
+ database.execSQL("UPDATE `Card` SET `etag` = NULL");
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_25_26.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_25_26.java
new file mode 100644
index 000000000..18f03e14b
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_25_26.java
@@ -0,0 +1,39 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+public class Migration_25_26 extends Migration {
+
+ public Migration_25_26() {
+ super(25, 26);
+ }
+
+ @Override
+ public void migrate(SupportSQLiteDatabase database) {
+ database.execSQL("CREATE TABLE `FilterWidget` (`id` INTEGER PRIMARY KEY NOT NULL, `title` TEXT, `dueType` INTEGER, `widgetType` INTEGER NOT NULL)");
+ database.execSQL("CREATE TABLE `FilterWidgetAccount` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterWidgetId` INTEGER, `accountId` INTEGER, `includeNoUser` INTEGER NOT NULL, `includeNoProject` INTEGER NOT NULL, FOREIGN KEY(`accountId`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`filterWidgetId`) REFERENCES `FilterWidget`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
+ database.execSQL("CREATE TABLE `FilterWidgetBoard` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterAccountId` INTEGER, `boardId` INTEGER, `includeNoLabel` INTEGER NOT NULL, FOREIGN KEY(`boardId`) REFERENCES `Board`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`filterAccountId`) REFERENCES `FilterWidgetAccount`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
+ database.execSQL("CREATE TABLE `FilterWidgetLabel` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterBoardId` INTEGER, `labelId` INTEGER, FOREIGN KEY(`labelId`) REFERENCES `Label`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`filterBoardId`) REFERENCES `FilterWidgetBoard`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
+ database.execSQL("CREATE TABLE `FilterWidgetSort` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterWidgetId` INTEGER, `direction` INTEGER NOT NULL, `criteria` INTEGER NOT NULL, `ruleOrder` INTEGER NOT NULL, FOREIGN KEY(`filterWidgetId`) REFERENCES `FilterWidget`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
+ database.execSQL("CREATE TABLE `FilterWidgetStack` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterBoardId` INTEGER, `stackId` INTEGER, FOREIGN KEY(`stackId`) REFERENCES `Stack`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`filterBoardId`) REFERENCES `FilterWidgetBoard`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
+ database.execSQL("CREATE TABLE `FilterWidgetUser` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterAccountId` INTEGER, `userId` INTEGER, FOREIGN KEY(`userId`) REFERENCES `User`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`filterAccountId`) REFERENCES `FilterWidgetAccount`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
+ database.execSQL("CREATE TABLE `FilterWidgetProject` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `filterAccountId` INTEGER, `projectId` INTEGER, FOREIGN KEY(`projectId`) REFERENCES `OcsProject`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`filterAccountId`) REFERENCES `FilterWidgetAccount`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )");
+ database.execSQL("CREATE INDEX `index_FilterWidgetAccount_filterWidgetId` ON `FilterWidgetAccount` (`filterWidgetId`)");
+ database.execSQL("CREATE INDEX `idx_FilterWidgetAccount_accountId` ON `FilterWidgetAccount` (`accountId`)");
+ database.execSQL("CREATE INDEX `idx_FilterWidgetBoard_boardId` ON `FilterWidgetBoard` (`boardId`)");
+ database.execSQL("CREATE INDEX `idx_FilterWidgetBoard_filterAccountId` ON `FilterWidgetBoard` (`filterAccountId`)");
+ database.execSQL("CREATE INDEX `idx_FilterWidgetLabel_filterBoardId` ON `FilterWidgetLabel` (`filterBoardId`)");
+ database.execSQL("CREATE INDEX `idx_FilterWidgetLabel_labelId` ON `FilterWidgetLabel` (`labelId`)");
+ database.execSQL("CREATE INDEX `idx_FilterWidgetSort_filterWidgetId` ON `FilterWidgetSort` (`filterWidgetId`)");
+ database.execSQL("CREATE INDEX `idx_FilterWidgetStack_filterBoardId` ON `FilterWidgetStack` (`filterBoardId`)");
+ database.execSQL("CREATE INDEX `idx_FilterWidgetStack_stackId` ON `FilterWidgetStack` (`stackId`)");
+ database.execSQL("CREATE INDEX `idx_FilterWidgetUser_filterAccountId` ON `FilterWidgetUser` (`filterAccountId`)");
+ database.execSQL("CREATE INDEX `idx_FilterWidgetUser_userId` ON `FilterWidgetUser` (`userId`)");
+ database.execSQL("CREATE INDEX `idx_FilterWidgetProject_filterAccountId` ON `FilterWidgetProject` (`filterAccountId`)");
+ database.execSQL("CREATE INDEX `idx_FilterWidgetProject_projectId` ON `FilterWidgetProject` (`projectId`)");
+ database.execSQL("CREATE INDEX `unique_idx_FilterWidgetSort_filterWidgetId_criteria` ON `FilterWidgetSort` (`filterWidgetId`, `criteria`)");
+ database.execSQL("CREATE INDEX `unique_idx_FilterWidgetSort_filterWidgetId_ruleOrder` ON `FilterWidgetSort` (`filterWidgetId`, `ruleOrder`)");
+
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_26_27.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_26_27.java
new file mode 100644
index 000000000..93d1d7b84
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_26_27.java
@@ -0,0 +1,61 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+import it.niedermann.nextcloud.deck.model.widget.filter.EWidgetType;
+
+public class Migration_26_27 extends Migration {
+
+ public Migration_26_27() {
+ super(26, 27);
+ }
+
+ @Override
+ public void migrate(SupportSQLiteDatabase database) {
+
+ Cursor cursor = database.query("select s.localId, s.boardId, s.accountId, w.appWidgetId from `StackWidgetModel` w inner join `Stack` s on s.localId = w.stackId");
+ while (cursor.moveToNext()) {
+ Long localStackId = cursor.getLong(0);
+ Long localBoardId = cursor.getLong(1);
+ Long accountId = cursor.getLong(2);
+ Long filterWidgetId = cursor.getLong(3);
+
+ // widget:
+ ContentValues values = new ContentValues();
+ values.put("widgetType", EWidgetType.STACK_WIDGET.getId());
+ values.put("id", filterWidgetId);
+ database.insert("FilterWidget", SQLiteDatabase.CONFLICT_NONE, values);
+
+ // account
+ values = new ContentValues();
+ values.put("filterWidgetId", filterWidgetId);
+ values.put("accountId", accountId);
+ values.put("includeNoUser", false);
+ values.put("includeNoProject", false);
+ long filterWidgetAccountId = database.insert("FilterWidgetAccount", SQLiteDatabase.CONFLICT_NONE, values);
+
+ // board
+ values = new ContentValues();
+ values.put("filterAccountId", filterWidgetAccountId);
+ values.put("boardId", localBoardId);
+ values.put("includeNoLabel", false);
+ long filterWidgetBoardId = database.insert("FilterWidgetBoard", SQLiteDatabase.CONFLICT_NONE, values);
+
+ // stack
+ values = new ContentValues();
+ values.put("filterBoardId", filterWidgetBoardId);
+ values.put("stackId", localStackId);
+ database.insert("FilterWidgetStack", SQLiteDatabase.CONFLICT_NONE, values);
+
+
+ }
+
+ // cleanup
+ database.execSQL("DROP TABLE `StackWidgetModel`");
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_27_28.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_27_28.java
new file mode 100644
index 000000000..cc5780bf0
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_27_28.java
@@ -0,0 +1,16 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+public class Migration_27_28 extends Migration {
+
+ public Migration_27_28() {
+ super(27, 28);
+ }
+
+ @Override
+ public void migrate(SupportSQLiteDatabase database) {
+ database.execSQL("ALTER TABLE `Attachment` ADD COLUMN `fileId` INTEGER");
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_28_29.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_28_29.java
new file mode 100644
index 000000000..69c163639
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_28_29.java
@@ -0,0 +1,22 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+/**
+ * Reset ETags for cards because <a href="https://github.com/nextcloud/deck/issues/2874">the attachments for this card might not be complete</a>.
+ */
+public class Migration_28_29 extends Migration {
+
+ public Migration_28_29() {
+ super(28, 29);
+ }
+
+ @Override
+ public void migrate(SupportSQLiteDatabase database) {
+ database.execSQL("UPDATE `Account` SET `boardsEtag` = NULL");
+ database.execSQL("UPDATE `Board` SET `etag` = NULL");
+ database.execSQL("UPDATE `Stack` SET `etag` = NULL");
+ database.execSQL("UPDATE `Card` SET `etag` = NULL");
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_8_9.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_8_9.java
new file mode 100644
index 000000000..9660f8b83
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_8_9.java
@@ -0,0 +1,24 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+public class Migration_8_9 extends Migration {
+
+ public Migration_8_9() {
+ super(8, 9);
+ }
+
+ @Override
+ public void migrate(SupportSQLiteDatabase database) {
+ database.execSQL("CREATE TABLE `DeckComment` (`localId` INTEGER PRIMARY KEY AUTOINCREMENT, `accountId` INTEGER NOT NULL, `id` INTEGER, `status` INTEGER NOT NULL, `lastModified` INTEGER, `lastModifiedLocal` INTEGER, `objectId` INTEGER, `actorType` TEXT, `creationDateTime` INTEGER, `actorId` TEXT, `actorDisplayName` TEXT, `message` TEXT, FOREIGN KEY(`objectId`) REFERENCES `Card`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE )");
+ database.execSQL("CREATE TABLE `Mention` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `commentId` INTEGER, `mentionId` TEXT, `mentionType` TEXT, `mentionDisplayName` TEXT, FOREIGN KEY(`commentId`) REFERENCES `DeckComment`(`localId`) ON UPDATE NO ACTION ON DELETE CASCADE )");
+ database.execSQL("CREATE INDEX `index_DeckComment_accountId` ON `DeckComment` (`accountId`)");
+ database.execSQL("CREATE INDEX `comment_accID` ON `DeckComment` (`accountId`)");
+ database.execSQL("CREATE UNIQUE INDEX `index_DeckComment_accountId_id` ON `DeckComment` (`accountId`, `id`)");
+ database.execSQL("CREATE INDEX `index_DeckComment_id` ON `DeckComment` (`id`)");
+ database.execSQL("CREATE INDEX `index_DeckComment_lastModifiedLocal` ON `DeckComment` (`lastModifiedLocal`)");
+ database.execSQL("CREATE INDEX `index_DeckComment_objectId` ON `DeckComment` (`objectId`)");
+ database.execSQL("CREATE INDEX `index_Mention_commentId` ON `Mention` (`commentId`)");
+ }
+}
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_9_10.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_9_10.java
new file mode 100644
index 000000000..5e020844a
--- /dev/null
+++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/migration/Migration_9_10.java
@@ -0,0 +1,19 @@
+package it.niedermann.nextcloud.deck.persistence.sync.adapters.db.migration;
+
+import androidx.room.migration.Migration;
+import androidx.sqlite.db.SupportSQLiteDatabase;
+
+public class Migration_9_10 extends Migration {
+
+ public Migration_9_10() {
+ super(9, 10);
+ }
+
+ @Override
+ public void migrate(SupportSQLiteDatabase database) {
+ database.execSQL("ALTER TABLE `Account` ADD `color` TEXT NOT NULL DEFAULT '#0082c9'");
+ database.execSQL("ALTER TABLE `Account` ADD `textColor` TEXT NOT NULL DEFAULT '#ffffff'");
+ database.execSQL("ALTER TABLE `Account` ADD `serverDeckVersion` TEXT NOT NULL DEFAULT '0.6.4'");
+ database.execSQL("ALTER TABLE `Account` ADD `maintenanceEnabled` INTEGER NOT NULL DEFAULT 0");
+ }
+}