diff --git a/core/libs/database/thumbsdb/thumbsdb.cpp b/core/libs/database/thumbsdb/thumbsdb.cpp index 9b59173f5a..13ae0fdd46 100644 --- a/core/libs/database/thumbsdb/thumbsdb.cpp +++ b/core/libs/database/thumbsdb/thumbsdb.cpp @@ -1,408 +1,407 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2009-05-29 * Description : Thumbnails database interface. * * Copyright (C) 2009 by Marcel Wiesweg * Copyright (C) 2009-2018 by Gilles Caulier * * This program 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 2, or (at your option) * any later version. * * This program 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. * * ============================================================ */ #include "thumbsdb.h" // Qt includes #include #include #include // Local includes #include "digikam_debug.h" #include "collectionmanager.h" #include "collectionlocation.h" namespace Digikam { class ThumbsDb::Private { public: explicit Private() : db(0) { } ThumbsDbBackend* db; }; ThumbsDb::ThumbsDb(ThumbsDbBackend* const backend) : d(new Private) { d->db = backend; } ThumbsDb::~ThumbsDb() { delete d; } bool ThumbsDb::setSetting(const QString& keyword, const QString& value ) { QMap parameters; parameters.insert(QLatin1String(":keyword"), keyword); parameters.insert(QLatin1String(":value"), value); BdEngineBackend::QueryState queryStateResult = d->db->execDBAction(d->db->getDBAction(QLatin1String("ReplaceThumbnailSetting")), parameters); return (queryStateResult == BdEngineBackend::NoErrors); } QString ThumbsDb::getSetting(const QString& keyword) { QMap parameters; parameters.insert(QLatin1String(":keyword"), keyword); QList values; // TODO Should really check return status here BdEngineBackend::QueryState queryStateResult = d->db->execDBAction(d->db->getDBAction(QLatin1String("SelectThumbnailSetting")), parameters, &values); qCDebug(DIGIKAM_THUMBSDB_LOG) << "ThumbDB SelectThumbnailSetting val ret = " << (BdEngineBackend::QueryStateEnum)queryStateResult; if (values.isEmpty()) { return QString(); } else { return values.first().toString(); } } QString ThumbsDb::getLegacySetting(const QString& keyword) { QMap parameters; parameters.insert(QLatin1String(":keyword"), keyword); QList values; // TODO Should really check return status here BdEngineBackend::QueryState queryStateResult = d->db->execDBAction(d->db->getDBAction(QLatin1String("SelectThumbnailLegacySetting")), parameters, &values); qCDebug(DIGIKAM_THUMBSDB_LOG) << "ThumbDB SelectThumbnailLegacySetting val ret = " << (BdEngineBackend::QueryStateEnum)queryStateResult; if (values.isEmpty()) { return QString(); } else { return values.first().toString(); } } static void fillThumbnailInfo(const QList &values, ThumbsDbInfo& info) { if (values.isEmpty()) { return; } info.id = values.at(0).toInt(); info.type = (DatabaseThumbnail::Type)values.at(1).toInt(); info.modificationDate = values.at(2).toDateTime(); info.orientationHint = values.at(3).toInt(); info.data = values.at(4).toByteArray(); } ThumbsDbInfo ThumbsDb::findByHash(const QString& uniqueHash, qlonglong fileSize) { QList values; d->db->execSql(QLatin1String("SELECT id, type, modificationDate, orientationHint, data " "FROM UniqueHashes " " INNER JOIN Thumbnails ON thumbId = id " "WHERE uniqueHash=? AND fileSize=?;"), uniqueHash, fileSize, &values); ThumbsDbInfo info; fillThumbnailInfo(values, info); return info; } ThumbsDbInfo ThumbsDb::findByFilePath(const QString& path) { QList values; d->db->execSql(QLatin1String("SELECT id, type, modificationDate, orientationHint, data " "FROM FilePaths " " INNER JOIN Thumbnails ON thumbId = id " "WHERE path=?;"), path, &values); ThumbsDbInfo info; fillThumbnailInfo(values, info); return info; } ThumbsDbInfo ThumbsDb::findByFilePath(const QString& path, const QString& uniqueHash) { ThumbsDbInfo info = findByFilePath(path); if (uniqueHash.isNull()) { return info; } if (info.data.isNull()) { return info; } // double check that thumbnail is not referenced by a different hash QList values; d->db->execSql(QLatin1String("SELECT uniqueHash FROM UniqueHashes WHERE thumbId=?;"), info.id, &values); if (values.isEmpty()) { return info; } else { foreach(const QVariant& hash, values) { if (hash == uniqueHash) { return info; } } return ThumbsDbInfo(); } } ThumbsDbInfo ThumbsDb::findByCustomIdentifier(const QString& id) { QList values; d->db->execSql(QLatin1String("SELECT id, type, modificationDate, orientationHint, data " "FROM CustomIdentifiers " " INNER JOIN Thumbnails ON thumbId = id " "WHERE identifier=?;"), id, &values); ThumbsDbInfo info; fillThumbnailInfo(values, info); return info; } QList ThumbsDb::findAll() { QList values; d->db->execSql(QLatin1String("SELECT id FROM Thumbnails;"), &values); QList thumbIds; foreach(const QVariant& object, values) { thumbIds << object.toInt(); } return thumbIds; } QHash ThumbsDb::getFilePathsWithThumbnail() { DbEngineSqlQuery query = d->db->prepareQuery(QString::fromLatin1("SELECT path, id " "FROM FilePaths " " INNER JOIN Thumbnails ON FilePaths.thumbId=Thumbnails.id " "WHERE type BETWEEN %1 AND %2;") .arg(DatabaseThumbnail::PGF) .arg(DatabaseThumbnail::PNG)); if (!d->db->exec(query)) { return QHash(); } QHash filePaths; while (query.next()) { filePaths[query.value(0).toString()] = query.value(1).toInt(); } return filePaths; } BdEngineBackend::QueryState ThumbsDb::insertUniqueHash(const QString& uniqueHash, qlonglong fileSize, int thumbId) { return d->db->execSql(QLatin1String("REPLACE INTO UniqueHashes (uniqueHash, fileSize, thumbId) VALUES (?,?,?);"), uniqueHash, fileSize, thumbId); } BdEngineBackend::QueryState ThumbsDb::insertFilePath(const QString& path, int thumbId) { return d->db->execSql(QLatin1String("REPLACE INTO FilePaths (path, thumbId) VALUES (?,?);"), path, thumbId); } BdEngineBackend::QueryState ThumbsDb::insertCustomIdentifier(const QString& path, int thumbId) { return d->db->execSql(QLatin1String("REPLACE INTO CustomIdentifiers (identifier, thumbId) VALUES (?,?);"), path, thumbId); } BdEngineBackend::QueryState ThumbsDb::remove(int thumbId) { return d->db->execSql(QLatin1String("DELETE FROM Thumbnails WHERE id=?;"), thumbId); } BdEngineBackend::QueryState ThumbsDb::removeByUniqueHash(const QString& uniqueHash, qlonglong fileSize) { // UniqueHashes + FilePaths entries are removed by trigger QMap parameters; parameters.insert(QLatin1String(":uniqueHash"), uniqueHash); parameters.insert(QLatin1String(":filesize"), fileSize); return d->db->execDBAction(d->db->getDBAction(QLatin1String("Delete_Thumbnail_ByUniqueHashId")), parameters); } BdEngineBackend::QueryState ThumbsDb::removeByFilePath(const QString& path) { // UniqueHashes + FilePaths entries are removed by trigger QMap parameters; parameters.insert(QLatin1String(":path"), path); return d->db->execDBAction(d->db->getDBAction(QLatin1String("Delete_Thumbnail_ByPath")), parameters); } BdEngineBackend::QueryState ThumbsDb::removeByCustomIdentifier(const QString& id) { // UniqueHashes + FilePaths entries are removed by trigger QMap parameters; parameters.insert(QLatin1String(":identifier"), id); return d->db->execDBAction(d->db->getDBAction(QLatin1String("Delete_Thumbnail_ByCustomIdentifier")), parameters); } BdEngineBackend::QueryState ThumbsDb::insertThumbnail(const ThumbsDbInfo& info, QVariant* const lastInsertId) { QVariant id; BdEngineBackend::QueryState lastQueryState; lastQueryState = d->db->execSql(QLatin1String("INSERT INTO Thumbnails (type, modificationDate, orientationHint, data) VALUES (?, ?, ?, ?);"), info.type, info.modificationDate, info.orientationHint, info.data, 0, &id); if (BdEngineBackend::NoErrors == lastQueryState) { *lastInsertId = id.toInt(); } else { *lastInsertId = -1; } return lastQueryState; } BdEngineBackend::QueryState ThumbsDb::renameByFilePath(const QString& oldPath, const QString& newPath) { - return d->db->execSql(QLatin1String("UPDATE FilePaths SET path=? " - "WHERE path=?;"), + return d->db->execSql(QLatin1String("UPDATE FilePaths SET path=? WHERE path=?;"), newPath, oldPath); } BdEngineBackend::QueryState ThumbsDb::replaceThumbnail(const ThumbsDbInfo& info) { return d->db->execSql(QLatin1String("REPLACE INTO Thumbnails (id, type, modificationDate, orientationHint, data) VALUES(?, ?, ?, ?, ?);"), QList() << info.id << info.type << info.modificationDate << info.orientationHint << info.data); } BdEngineBackend::QueryState ThumbsDb::updateModificationDate(int thumbId, const QDateTime& modificationDate) { return d->db->execSql(QLatin1String("UPDATE Thumbnails SET modificationDate=? WHERE id=?;"), modificationDate, thumbId); } void ThumbsDb::replaceUniqueHash(const QString& oldUniqueHash, int oldFileSize, const QString& newUniqueHash, int newFileSize) { d->db->execSql(QLatin1String("UPDATE UniqueHashes SET uniqueHash=?, fileSize=? WHERE uniqueHash=? AND fileSize=?;"), newUniqueHash, newFileSize, oldUniqueHash, oldFileSize); } bool ThumbsDb::integrityCheck() { QList values; d->db->execDBAction(d->db->getDBAction(QString::fromUtf8("checkThumbnailsDbIntegrity")), &values); switch (d->db->databaseType()) { case BdEngineBackend::DbType::SQLite: // For SQLite the integrity check returns a single row with one string column "ok" on success and multiple rows on error. return values.size() == 1 && values.first().toString().toLower().compare(QLatin1String("ok")) == 0; case BdEngineBackend::DbType::MySQL: // For MySQL, for every checked table, the table name, operation (check), message type (status) and the message text (ok on success) // are returned. So we check if there are four elements and if yes, whether the fourth element is "ok". //qCDebug(DIGIKAM_DATABASE_LOG) << "MySQL check returned " << values.size() << " rows"; if ((values.size() % 4) != 0) { return false; } for (QList::iterator it = values.begin() ; it != values.end() ;) { QString tableName = (*it).toString(); ++it; QString operation = (*it).toString(); ++it; QString messageType = (*it).toString(); ++it; QString messageText = (*it).toString(); ++it; if (messageText.toLower().compare(QLatin1String("ok")) != 0) { qCDebug(DIGIKAM_DATABASE_LOG) << "Failed integrity check for table " << tableName << ". Reason:" << messageText; return false; } else { //qCDebug(DIGIKAM_DATABASE_LOG) << "Passed integrity check for table " << tableName; } } // No error conditions. Db passed the integrity check. return true; default: return false; } } void ThumbsDb::vacuum() { d->db->execDBAction(d->db->getDBAction(QString::fromUtf8("vacuumThumbnailsDB"))); } } // namespace Digikam