File indexing completed on 2024-06-23 05:07:03
0001 /*************************************************************************** 0002 * SPDX-FileCopyrightText: 2006 Tobias Koenig <tokoe@kde.org> * 0003 * SPDX-FileCopyrightText: 2014 Daniel Vrátil <dvratil@redhat.com> * 0004 * * 0005 * SPDX-License-Identifier: LGPL-2.0-or-later * 0006 ***************************************************************************/ 0007 0008 #include "searchhelper.h" 0009 0010 #include "entities.h" 0011 #include "storage/countquerybuilder.h" 0012 0013 #include "private/protocol_p.h" 0014 0015 using namespace Akonadi::Server; 0016 0017 static qint64 parentCollectionId(qint64 collectionId) 0018 { 0019 QueryBuilder qb(Collection::tableName(), QueryBuilder::Select); 0020 qb.addColumn(Collection::parentIdColumn()); 0021 qb.addValueCondition(Collection::idColumn(), Query::Equals, collectionId); 0022 if (!qb.exec()) { 0023 return -1; 0024 } 0025 if (!qb.query().next()) { 0026 return -1; 0027 } 0028 const auto parentId = qb.query().value(0).toLongLong(); 0029 qb.query().finish(); 0030 return parentId; 0031 } 0032 0033 QList<qint64> SearchHelper::matchSubcollectionsByMimeType(const QList<qint64> &ancestors, const QStringList &mimeTypes) 0034 { 0035 // Get all collections with given mime types 0036 QueryBuilder qb(Collection::tableName(), QueryBuilder::Select); 0037 qb.setDistinct(true); 0038 qb.addColumn(Collection::idFullColumnName()); 0039 qb.addColumn(Collection::parentIdFullColumnName()); 0040 qb.addJoin(QueryBuilder::LeftJoin, 0041 CollectionMimeTypeRelation::tableName(), 0042 CollectionMimeTypeRelation::leftFullColumnName(), 0043 Collection::idFullColumnName()); 0044 qb.addJoin(QueryBuilder::LeftJoin, MimeType::tableName(), CollectionMimeTypeRelation::rightFullColumnName(), MimeType::idFullColumnName()); 0045 Query::Condition cond(Query::Or); 0046 for (const QString &mt : mimeTypes) { 0047 cond.addValueCondition(MimeType::nameFullColumnName(), Query::Equals, mt); 0048 } 0049 if (!cond.isEmpty()) { 0050 qb.addCondition(cond); 0051 } 0052 0053 if (!qb.exec()) { 0054 qCWarning(AKONADISERVER_LOG) << "Failed to query search collections"; 0055 return QList<qint64>(); 0056 } 0057 0058 QMap<qint64 /* parentId */, QList<qint64> /* collectionIds */> candidateCollections; 0059 while (qb.query().next()) { 0060 candidateCollections[qb.query().value(1).toLongLong()].append(qb.query().value(0).toLongLong()); 0061 } 0062 qb.query().finish(); 0063 0064 // If the ancestors list contains root, then return what we got, since everything 0065 // is sub collection of root 0066 QList<qint64> results; 0067 if (ancestors.contains(0)) { 0068 for (const QList<qint64> &res : std::as_const(candidateCollections)) { 0069 results += res; 0070 } 0071 return results; 0072 } 0073 0074 // Try to resolve direct descendants 0075 for (qint64 ancestor : ancestors) { 0076 const QList<qint64> cols = candidateCollections.take(ancestor); 0077 if (!cols.isEmpty()) { 0078 results += cols; 0079 } 0080 } 0081 0082 for (auto iter = candidateCollections.begin(), iterEnd = candidateCollections.end(); iter != iterEnd; ++iter) { 0083 // Traverse the collection chain up to root 0084 qint64 parentId = iter.key(); 0085 while (!ancestors.contains(parentId) && parentId > 0) { 0086 parentId = parentCollectionId(parentId); 0087 } 0088 // Ok, we found a requested ancestor in the parent chain 0089 if (parentId > 0) { 0090 results += iter.value(); 0091 } 0092 } 0093 0094 return results; 0095 }