+ // Upgrade from schema version 1, first used in Privacy Browser 1.8, to schema version 2, first used in Privacy Browser 3.15.
+ if (oldVersion < 2) {
+ // Add the folder ID column.
+ bookmarksDatabase.execSQL("ALTER TABLE $BOOKMARKS_TABLE ADD COLUMN $FOLDER_ID INTEGER")
+
+ // Get a cursor with all the folders.
+ val foldersCursor = bookmarksDatabase.rawQuery("SELECT $ID FROM $BOOKMARKS_TABLE WHERE $IS_FOLDER = 1", null)
+
+ // Get the folders cursor ID column index.
+ val foldersCursorIdColumnIndex = foldersCursor.getColumnIndexOrThrow(ID)
+
+ // Add a folder ID to each folder.
+ while(foldersCursor.moveToNext()) {
+ // Get the current folder database ID.
+ val databaseId = foldersCursor.getInt(foldersCursorIdColumnIndex)
+
+ // Generate a folder ID.
+ val folderId = Date().time
+
+ // Create a folder content values.
+ val folderContentValues = ContentValues()
+
+ // Store the new folder ID in the content values.
+ folderContentValues.put(FOLDER_ID, folderId)
+
+ // Update the folder with the new folder ID.
+ bookmarksDatabase.update(BOOKMARKS_TABLE, folderContentValues, "$ID = $databaseId", null)
+
+ // Wait 2 milliseconds to ensure that the next folder ID is unique.
+ Thread.sleep(2)
+ }
+
+ // Close the folders cursor.
+ foldersCursor.close()
+
+
+ // Add the parent folder ID column.
+ bookmarksDatabase.execSQL("ALTER TABLE $BOOKMARKS_TABLE ADD COLUMN $PARENT_FOLDER_ID INTEGER")
+
+ // Get a cursor with all the bookmarks.
+ val bookmarksCursor = bookmarksDatabase.rawQuery("SELECT $ID, parentfolder FROM $BOOKMARKS_TABLE", null)
+
+ // Get the bookmarks cursor ID column index.
+ val bookmarksCursorIdColumnIndex = bookmarksCursor.getColumnIndexOrThrow(ID)
+ val bookmarksCursorParentFolderColumnIndex = bookmarksCursor.getColumnIndexOrThrow("parentfolder")
+
+ // Populate the parent folder ID for each bookmark.
+ while(bookmarksCursor.moveToNext()) {
+ // Get the information from the cursor.
+ val databaseId = bookmarksCursor.getInt(bookmarksCursorIdColumnIndex)
+ val oldParentFolderString = bookmarksCursor.getString(bookmarksCursorParentFolderColumnIndex)
+
+ // Initialize the new parent folder ID.
+ var newParentFolderId = HOME_FOLDER_ID
+
+ // Get the parent folder ID if the bookmark is not in the home folder.
+ if (oldParentFolderString.isNotEmpty()) {
+ // SQL escape the old parent folder string.
+ val sqlEscapedFolderName = DatabaseUtils.sqlEscapeString(oldParentFolderString)
+
+ // Get the parent folder cursor.
+ val parentFolderCursor = bookmarksDatabase.rawQuery("SELECT $FOLDER_ID FROM $BOOKMARKS_TABLE WHERE $BOOKMARK_NAME = $sqlEscapedFolderName AND $IS_FOLDER = 1", null)
+
+ // Get the new parent folder ID if it exists.
+ if (parentFolderCursor.count > 0) {
+ // Move to the first entry.
+ parentFolderCursor.moveToFirst()
+
+ // Get the new parent folder ID.
+ newParentFolderId = parentFolderCursor.getLong(parentFolderCursor.getColumnIndexOrThrow(FOLDER_ID))
+ }
+
+ // Close the parent folder cursor.
+ parentFolderCursor.close()
+ }
+
+ // Create a bookmark content values.
+ val bookmarkContentValues = ContentValues()
+
+ // Store the new parent folder ID in the content values.
+ bookmarkContentValues.put(PARENT_FOLDER_ID, newParentFolderId)
+
+ // Update the folder with the new folder ID.
+ bookmarksDatabase.update(BOOKMARKS_TABLE, bookmarkContentValues, "$ID = $databaseId", null)
+ }
+
+ // Close the bookmarks cursor.
+ bookmarksCursor.close()
+
+ // This upgrade removed the old `parentfolder` string column.
+ // SQLite amazingly only added a command to drop a column in version 3.35.0. <https://www.sqlite.org/changes.html>
+ // It will be a while before that is supported in Android. <https://developer.android.com/reference/android/database/sqlite/package-summary>
+ // Although a new table could be created and all the data copied to it, I think I will just leave the old parent folder column. It will be wiped out the next time an import is run.
+ }