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