Skip to content

Commit

Permalink
Implement merging / importing database file (Closes #3259)
Browse files Browse the repository at this point in the history
  • Loading branch information
tuomas2 committed May 25, 2024
1 parent 4e27b3d commit 10deea3
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,10 @@ import net.bible.service.db.DatabaseContainer.Companion.maxDatabaseVersion
import net.bible.service.db.OLD_MONOLITHIC_DATABASE_NAME
import net.bible.service.download.isPseudoBook
import net.bible.service.cloudsync.CloudSync
import net.bible.service.cloudsync.SyncableDatabaseDefinition
import net.bible.service.common.CommonUtils.determineFileType
import net.bible.service.common.CommonUtils.grantUriReadPermissions
import net.bible.service.db.importDatabaseFile
import net.bible.service.sword.dbFile
import net.bible.service.sword.epub.epubDir
import net.bible.service.sword.epub.isManuallyInstalledEpub
Expand Down Expand Up @@ -662,17 +664,28 @@ object BackupControl {
}
hourglass.show()
beforeRestore()
DatabaseContainer.reset()
for (fileName in selection) {
val category = SyncableDatabaseDefinition.filenameToCategory[fileName]
val restore =
if (category != null)
askIfRestoreOrImport(category, activity)
else true

val f = File(unzipFolder, "db/${fileName}")
Log.i(TAG, "Restoring $fileName")
val targetFilePath = activity.getDatabasePath(fileName).path
val targetFile = File(targetFilePath)
f.copyTo(targetFile, overwrite = true)
File("$targetFilePath-journal").delete()
File("$targetFilePath-shm").delete()
File("$targetFilePath-wal").delete()
if (restore) {
Log.i(TAG, "Restoring $fileName")
DatabaseContainer.instance.dbByFilename[fileName]?.close()
val targetFilePath = activity.getDatabasePath(fileName).path
val targetFile = File(targetFilePath)
f.copyTo(targetFile, overwrite = true)
File("$targetFilePath-journal").delete()
File("$targetFilePath-shm").delete()
File("$targetFilePath-wal").delete()
} else {
importDatabaseFile(category!!, f)
}
}
DatabaseContainer.reset()
selection
}
if (DatabaseContainer.ready) {
Expand All @@ -686,6 +699,20 @@ object BackupControl {
true
}

private suspend fun askIfRestoreOrImport(category: SyncableDatabaseDefinition, context: ActivityBase): Boolean = withContext(Dispatchers.Main) {
suspendCoroutine {
val message =
context.getString(R.string.ask_restore_or_import, context.getString(category.contentDescription))
AlertDialog.Builder(context)
.setTitle(R.string.backup_restore2)
.setMessage(message)
.setPositiveButton(R.string.restore) { _, _ -> it.resume(true) }
.setNegativeButton(R.string.import2) { _, _ -> it.resume(false) }
.setOnCancelListener { _ -> it.resume(false) }
.show()
}
}

private suspend fun restoreOldMonolithicDatabaseFromFileInputStreamWithUI(
activity: ActivityBase,
inputStream: InputStream
Expand Down
11 changes: 10 additions & 1 deletion app/src/main/java/net/bible/service/cloudsync/SyncUtilities.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ package net.bible.service.cloudsync
import android.util.Log
import androidx.sqlite.db.SupportSQLiteDatabase
import net.bible.android.activity.R
import net.bible.android.database.BookmarkDatabase
import net.bible.android.database.LogEntry
import net.bible.android.database.ReadingPlanDatabase
import net.bible.android.database.SyncableRoomDatabase
import net.bible.android.database.WorkspaceDatabase
import net.bible.android.database.migrations.getColumnNames
import net.bible.android.database.migrations.getColumnNamesJoined
import net.bible.service.common.CommonUtils
Expand All @@ -45,6 +48,11 @@ enum class SyncableDatabaseDefinition {
WORKSPACES -> R.string.workspaces_contents
}

val filename get() = when(this) {
BOOKMARKS -> BookmarkDatabase.dbFileName
READINGPLANS ->ReadingPlanDatabase.dbFileName
WORKSPACES -> WorkspaceDatabase.dbFileName
}
val tables get() = when(this) {
BOOKMARKS -> listOf(
Table(
Expand Down Expand Up @@ -97,12 +105,13 @@ enum class SyncableDatabaseDefinition {
get() = CommonUtils.settings.getBoolean("gdrive_"+ name.lowercase(), false)
set(value) = CommonUtils.settings.setBoolean("gdrive_"+name.lowercase(), value)

private val accessor get() = DatabaseContainer.databaseAccessorsByCategory[this]!!
val accessor get() = DatabaseContainer.databaseAccessorsByCategory[this]!!
val lastSynchronized get() = if(!syncEnabled) null else accessor.dao.getLong(LAST_SYNCHRONIZED_KEY)

companion object {
val ALL = arrayOf(BOOKMARKS, WORKSPACES, READINGPLANS)
val nameToCategory = ALL.associateBy { it.name }
val filenameToCategory = ALL.associateBy { it.filename }
}
}

Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/net/bible/service/db/DatabaseContainer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@ class DatabaseContainer {
private val backedUpDatabases = arrayOf(bookmarkDb, readingPlanDb, workspaceDb, repoDb, settingsDb)
private val allDatabases = arrayOf(*backedUpDatabases, downloadDocumentsDb, chooseDocumentsDb)

val dbByFilename = allDatabases.associateBy { it.openHelper.databaseName }

internal fun sync() = allDatabases.forEach {
it.openHelper.writableDatabase
// we are not using WAL mode any more, but it does not hurt either. Just in case we switch back to WAL.
Expand Down
57 changes: 57 additions & 0 deletions app/src/main/java/net/bible/service/db/ImportDb.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2024 Martin Denham, Tuomas Airaksinen and the AndBible contributors.
*
* This file is part of AndBible: Bible Study (http://github.com/AndBible/and-bible).
*
* AndBible is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* AndBible is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with AndBible.
* If not, see http://www.gnu.org/licenses/.
*/

package net.bible.service.db

import android.util.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import net.bible.android.database.migrations.getColumnNamesJoined
import net.bible.service.cloudsync.SyncableDatabaseDefinition
import java.io.File
import java.lang.Exception

private const val TAG = "ImportDb"

suspend fun importDatabaseFile(category: SyncableDatabaseDefinition, dbFile: File) = withContext(Dispatchers.IO) {
val dbDef = category.accessor
val importDbFile = dbDef.dbFactory(dbFile.absolutePath)
importDbFile.openHelper.writableDatabase.use {}
dbDef.writableDb.run {
execSQL("ATTACH DATABASE '${dbFile.absolutePath}' AS import")
execSQL("PRAGMA foreign_keys=OFF;")
beginTransaction()
try {
for (tableDef in dbDef.tableDefinitions) {
val table = tableDef.tableName
val cols = getColumnNamesJoined(this, table)
execSQL("""
INSERT OR IGNORE INTO $table ($cols)
SELECT $cols FROM import.$table
""".trimIndent())
}
setTransactionSuccessful()
} catch (e: Exception) {
Log.e(TAG, "Error occurred in importDatabaseFile", e)
throw e
} finally {
endTransaction()
execSQL("PRAGMA foreign_keys=ON;")
execSQL("DETACH DATABASE import")
}
}
}
4 changes: 2 additions & 2 deletions app/src/main/res/layout/backup_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/backup_restore"
android:text="@string/backup_restore2"
android:layout_marginTop="20dp"
android:textSize="20sp"
android:textStyle="bold" />
Expand Down Expand Up @@ -131,7 +131,7 @@
android:layout_marginTop="10dp"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:text="@string/backup_restore_from" />
android:text="@string/backup_restore_from2" />


<TextView
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,9 @@
<string name="backup_document_info">Bibles, commentaries, dictionaries, maps etc.</string>
<string name="backup_to">Backup to…</string>
<string name="backup_restore_from">Restore from…</string>
<string name="backup_restore_from2">Restore or Import from…</string>
<string name="backup_restore">Restore</string>
<string name="backup_restore2">Restore or Import</string>

<!-- What items (study pads, bookmarks etc) user wants to restore from app db backup file? -->
<string name="restore_what">What do you want to restore?</string>
Expand Down Expand Up @@ -1217,4 +1219,7 @@
<string name="dont_show">
Don\'t show this message again
</string>
<string name="ask_restore_or_import">Do you want to restore (remove existing and read selected database) or import (import selected database into existing database) %s?</string>
<string name="restore">Restore</string>
<string name="import2">Import</string>
</resources>

0 comments on commit 10deea3

Please sign in to comment.