From d1d6a91e1ba80d0b6276bbf9f1b1bc28ab7f1114 Mon Sep 17 00:00:00 2001 From: Oirio Joshi Date: Tue, 28 Jan 2020 19:37:43 +0100 Subject: [PATCH] Fix NULL _id record on db upgrade Fixes #122 --- components/databasemanager.cpp | 69 +++++++++++++++++++++++++++++++++- utils/definitionholder.cpp | 2 +- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/components/databasemanager.cpp b/components/databasemanager.cpp index 60f84e9..13c2f7d 100755 --- a/components/databasemanager.cpp +++ b/components/databasemanager.cpp @@ -377,7 +377,8 @@ bool DatabaseManager::upgradeDatabase(const int oldVersion) { //handle database version upgrades int currentUpgradeVersion = oldVersion; - QSqlQuery query(getDatabase()); + QSqlDatabase db = getDatabase(); + QSqlQuery query(db); //upgrade v1 -> v2 if (currentUpgradeVersion == 1) { @@ -429,6 +430,72 @@ bool DatabaseManager::upgradeDatabase(const int oldVersion) } currentUpgradeVersion = 3; } + //upgrade v3 -> v4 + if (currentUpgradeVersion == 3) { + bool error = false; + QString errorMessage; + + //fix inconsistent data sets, see https://github.com/giowck/symphytum/issues/122 + //first, check if there are any + //get all collections, including the metadata copy + QStringList collectionsToCheck; + error |= !query.exec("SELECT table_name FROM collections"); + while (query.next()) { + QString c = query.value(0).toString(); + collectionsToCheck.append(c); + collectionsToCheck.append(c + "_metadata"); + } + + //check for any _id NULL values + QStringList collectionsToFix; + foreach (QString tableName, collectionsToCheck) { + error |= !query.exec(QString("SELECT _id FROM %1 WHERE _id IS NULL").arg(tableName)); + if (query.next()) { + collectionsToFix.append(tableName); + } + } + + //correct NULL _id records if any + if (collectionsToFix.size() > 0) { + //start transaction to speed up writes + db.transaction(); + + foreach (QString tableName, collectionsToFix) { + //get original CREATE TABLE statement + error |= !query.exec(QString("SELECT sql FROM sqlite_master " + "WHERE tbl_name=\"%1\"").arg(tableName)); + if (query.next()) { + QString create_sql = query.value(0).toString(); + //add PRIMARY KEY constraint + create_sql.replace("_id INT", "_id INTEGER PRIMARY KEY"); + //rename table + QString tableNameFixed = tableName + "_fixed"; + create_sql.replace(tableName, tableNameFixed); + //create new fixed table + error |= !query.exec(create_sql); + //copy data over to new table + error |= !query.exec(QString("INSERT INTO %1 SELECT * FROM %2") + .arg(tableNameFixed).arg(tableName)); + //delete old table + error |= !query.exec(QString("DROP TABLE %1").arg(tableName)); + //rename fixed table to original name + error |= !query.exec(QString("ALTER TABLE %1 RENAME TO %2") + .arg(tableNameFixed).arg(tableName)); + } + } + + //commit transaction + db.commit(); + } + + if (error) { + QMessageBox::critical(nullptr, QObject::tr("Database Version Upgrade Failed"), + QObject::tr("Error: failed in v3 -> v4")); + return false; + } + + currentUpgradeVersion = 4; + } //add new blocks on new versions here //upgrade done diff --git a/utils/definitionholder.cpp b/utils/definitionholder.cpp index 4528be6..9201f2c 100755 --- a/utils/definitionholder.cpp +++ b/utils/definitionholder.cpp @@ -27,7 +27,7 @@ QString DefinitionHolder::DOWNLOAD_URL = "https://github.com/giowck/symphytum" QString DefinitionHolder::HELP_URL = "https://github.com/giowck/symphytum/wiki"; QString DefinitionHolder::DONATE_URL = "https://github.com/giowck/symphytum/blob/master/doc/donate.md"; int DefinitionHolder::SOFTWARE_BUILD = 10; -int DefinitionHolder::DATABASE_VERSION = 3; +int DefinitionHolder::DATABASE_VERSION = 4; bool DefinitionHolder::APP_STORE = false; bool DefinitionHolder::APPIMAGE_LINUX = false; bool DefinitionHolder::WIN_PORTABLE = false;