File indexing completed on 2025-01-19 03:53:44
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2017-07-01 0007 * Description : Similarity DB schema update 0008 * 0009 * SPDX-FileCopyrightText: 2007-2009 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0010 * SPDX-FileCopyrightText: 2010-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0011 * SPDX-FileCopyrightText: 2017 by Swati Lodha <swatilodha27 at gmail dot com> 0012 * SPDX-FileCopyrightText: 2018 by Mario Frank <mario dot frank at uni minus potsdam dot de> 0013 * 0014 * SPDX-License-Identifier: GPL-2.0-or-later 0015 * 0016 * ============================================================ */ 0017 0018 #include "similaritydbschemaupdater.h" 0019 0020 // Qt includes 0021 0022 #include <QFileInfo> 0023 #include <QFile> 0024 #include <QDir> 0025 0026 // KDE includes 0027 0028 #include <klocalizedstring.h> 0029 0030 // Local includes 0031 0032 #include "digikam_debug.h" 0033 #include "collectionscannerobserver.h" 0034 #include "dbenginebackend.h" 0035 #include "similaritydbaccess.h" 0036 #include "similaritydb.h" 0037 0038 namespace Digikam 0039 { 0040 0041 int SimilarityDbSchemaUpdater::schemaVersion() 0042 { 0043 return 1; 0044 } 0045 0046 // ------------------------------------------------------------------------------------- 0047 0048 class Q_DECL_HIDDEN SimilarityDbSchemaUpdater::Private 0049 { 0050 0051 public: 0052 0053 explicit Private() 0054 : setError(false), 0055 currentVersion(0), 0056 currentRequiredVersion(0), 0057 dbAccess(nullptr), 0058 observer(nullptr) 0059 { 0060 } 0061 0062 public: 0063 0064 bool setError; 0065 0066 int currentVersion; 0067 int currentRequiredVersion; 0068 0069 SimilarityDbAccess* dbAccess; 0070 0071 InitializationObserver* observer; 0072 }; 0073 0074 SimilarityDbSchemaUpdater::SimilarityDbSchemaUpdater(SimilarityDbAccess* const dbAccess) 0075 : d(new Private) 0076 { 0077 d->dbAccess = dbAccess; 0078 } 0079 0080 SimilarityDbSchemaUpdater::~SimilarityDbSchemaUpdater() 0081 { 0082 delete d; 0083 } 0084 0085 bool SimilarityDbSchemaUpdater::update() 0086 { 0087 bool success = startUpdates(); 0088 0089 // even on failure, try to set current version - it may have incremented 0090 if (d->currentVersion) 0091 { 0092 d->dbAccess->db()->setSetting(QLatin1String("DBSimilarityVersion"), 0093 QString::number(d->currentVersion)); 0094 } 0095 0096 if (d->currentRequiredVersion) 0097 { 0098 d->dbAccess->db()->setSetting(QLatin1String("DBSimilarityVersionRequired"), 0099 QString::number(d->currentRequiredVersion)); 0100 } 0101 0102 return success; 0103 } 0104 0105 void SimilarityDbSchemaUpdater::setObserver(InitializationObserver* const observer) 0106 { 0107 d->observer = observer; 0108 } 0109 0110 bool SimilarityDbSchemaUpdater::startUpdates() 0111 { 0112 // First step: do we have an empty database? 0113 QStringList tables = d->dbAccess->backend()->tables(); 0114 0115 if (tables.contains(QLatin1String("SimilaritySettings"), Qt::CaseInsensitive)) 0116 { 0117 // Find out schema version of db file 0118 QString version = d->dbAccess->db()->getSetting(QLatin1String("DBSimilarityVersion")); 0119 QString versionRequired = d->dbAccess->db()->getSetting(QLatin1String("DBSimilarityVersionRequired")); 0120 0121 qCDebug(DIGIKAM_SIMILARITYDB_LOG) << "Similarity database: have a structure version " 0122 << version; 0123 0124 // mini schema update 0125 if (version.isEmpty() && d->dbAccess->parameters().isSQLite()) 0126 { 0127 version = d->dbAccess->db()->getSetting(QLatin1String("DBVersion")); 0128 } 0129 0130 if (version.isEmpty() && d->dbAccess->parameters().isMySQL()) 0131 { 0132 version = d->dbAccess->db()->getLegacySetting(QLatin1String("DBSimilarityVersion")); 0133 versionRequired = d->dbAccess->db()->getLegacySetting(QLatin1String("DBSimilarityVersionRequired")); 0134 } 0135 0136 // We absolutely require the DBSimilarityVersion setting 0137 if (version.isEmpty()) 0138 { 0139 // Something is damaged. Give up. 0140 0141 qCCritical(DIGIKAM_SIMILARITYDB_LOG) << "Similarity database: database version not available! Giving up schema upgrading."; 0142 0143 QString errorMsg = i18n("The database is not valid: " 0144 "the \"DBSimilarityVersion\" setting does not exist. " 0145 "The current database schema version cannot be verified. " 0146 "Try to start with an empty database. "); 0147 0148 d->dbAccess->setLastError(errorMsg); 0149 0150 if (d->observer) 0151 { 0152 d->observer->error(errorMsg); 0153 d->observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort); 0154 } 0155 0156 return false; 0157 } 0158 0159 // current version describes the current state of the schema in the db, 0160 // schemaVersion is the version required by the program. 0161 d->currentVersion = version.toInt(); 0162 0163 if (d->currentVersion > schemaVersion()) 0164 { 0165 // trying to open a database with a more advanced than this SimilarityDbSchemaUpdater supports 0166 if (!versionRequired.isEmpty() && versionRequired.toInt() <= schemaVersion()) 0167 { 0168 // version required may be less than current version 0169 return true; 0170 } 0171 else 0172 { 0173 QString errorMsg = i18n("The database has been used with a more recent version of digiKam " 0174 "and has been updated to a database schema which cannot be used with this version. " 0175 "(This means this digiKam version is too old, or the database format is to recent) " 0176 "Please use the more recent version of digikam that you used before. "); 0177 d->dbAccess->setLastError(errorMsg); 0178 0179 if (d->observer) 0180 { 0181 d->observer->error(errorMsg); 0182 d->observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort); 0183 } 0184 0185 return false; 0186 } 0187 } 0188 else 0189 { 0190 return makeUpdates(); 0191 } 0192 } 0193 else 0194 { 0195 qCDebug(DIGIKAM_SIMILARITYDB_LOG) << "Similarity database: no database file available"; 0196 0197 DbEngineParameters parameters = d->dbAccess->parameters(); 0198 0199 // No legacy handling: start with a fresh db 0200 if (!createDatabase()) 0201 { 0202 QString errorMsg = i18n("Failed to create tables in database.\n ") + 0203 d->dbAccess->backend()->lastError(); 0204 d->dbAccess->setLastError(errorMsg); 0205 0206 if (d->observer) 0207 { 0208 d->observer->error(errorMsg); 0209 d->observer->finishedSchemaUpdate(InitializationObserver::UpdateErrorMustAbort); 0210 } 0211 0212 return false; 0213 } 0214 0215 return true; 0216 } 0217 } 0218 0219 0220 bool SimilarityDbSchemaUpdater::createDatabase() 0221 { 0222 if (createTables() && 0223 createIndices() && 0224 createTriggers()) 0225 { 0226 d->currentVersion = schemaVersion(); 0227 d->currentRequiredVersion = 1; 0228 return true; 0229 } 0230 else 0231 { 0232 return false; 0233 } 0234 } 0235 0236 bool SimilarityDbSchemaUpdater::createTables() 0237 { 0238 return d->dbAccess->backend()->execDBAction(d->dbAccess->backend()->getDBAction(QLatin1String("CreateSimilarityDB"))); 0239 } 0240 0241 bool SimilarityDbSchemaUpdater::createIndices() 0242 { 0243 return d->dbAccess->backend()->execDBAction(d->dbAccess->backend()->getDBAction(QLatin1String("CreateSimilarityDBIndices"))); 0244 } 0245 0246 bool SimilarityDbSchemaUpdater::createTriggers() 0247 { 0248 return d->dbAccess->backend()->execDBAction(d->dbAccess->backend()->getDBAction(QLatin1String("CreateSimilarityDBTriggers"))); 0249 } 0250 0251 bool SimilarityDbSchemaUpdater::makeUpdates() 0252 { 0253 if (d->currentVersion < schemaVersion()) 0254 { 0255 if (d->currentVersion == 1) 0256 { 0257 updateV1ToV2(); 0258 } 0259 } 0260 0261 return true; 0262 } 0263 0264 bool SimilarityDbSchemaUpdater::updateV1ToV2() 0265 { 0266 // Do nothing for now. 0267 return true; 0268 } 0269 0270 } // namespace Digikam