File indexing completed on 2025-01-05 04:46:59
0001 /* 0002 SPDX-FileCopyrightText: 2009 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "itemqueryhelper.h" 0008 0009 #include "collectionqueryhelper.h" 0010 #include "commandcontext.h" 0011 #include "handler.h" 0012 #include "storage/querybuilder.h" 0013 #include "storage/queryhelper.h" 0014 0015 #include "private/imapset_p.h" 0016 #include "private/scope_p.h" 0017 0018 using namespace Akonadi; 0019 using namespace Akonadi::Server; 0020 0021 void ItemQueryHelper::itemSetToQuery(const ImapSet &set, QueryBuilder &qb, const Collection &collection) 0022 { 0023 if (!set.isEmpty()) { 0024 QueryHelper::setToQuery(set, qb.getTableWithColumn(PimItem::idColumn()), qb); 0025 } 0026 if (collection.isValid()) { 0027 if (collection.isVirtual() || collection.resource().isVirtual()) { 0028 qb.addJoin(QueryBuilder::InnerJoin, 0029 CollectionPimItemRelation::tableName(), 0030 CollectionPimItemRelation::rightFullColumnName(), 0031 qb.getTableWithColumn(PimItem::idColumn())); 0032 qb.addValueCondition(CollectionPimItemRelation::leftFullColumnName(), Query::Equals, collection.id()); 0033 } else { 0034 qb.addValueCondition(qb.getTableWithColumn(PimItem::collectionIdColumn()), Query::Equals, collection.id()); 0035 } 0036 } 0037 } 0038 0039 void ItemQueryHelper::itemSetToQuery(const ImapSet &set, const CommandContext &context, QueryBuilder &qb) 0040 { 0041 if (context.collectionId() >= 0) { 0042 itemSetToQuery(set, qb, context.collection()); 0043 } else { 0044 itemSetToQuery(set, qb); 0045 } 0046 0047 const auto tagId = context.tagId(); 0048 if (tagId.has_value()) { 0049 // When querying for items by tag, only return matches from that resource 0050 if (context.resource().isValid()) { 0051 qb.addJoin(QueryBuilder::InnerJoin, Collection::tableName(), qb.getTableWithColumn(PimItem::collectionIdColumn()), Collection::idFullColumnName()); 0052 qb.addValueCondition(Collection::resourceIdFullColumnName(), Query::Equals, context.resource().id()); 0053 } 0054 qb.addJoin(QueryBuilder::InnerJoin, 0055 PimItemTagRelation::tableName(), 0056 qb.getTableWithColumn(PimItem::idColumn()), 0057 PimItemTagRelation::leftFullColumnName()); 0058 qb.addValueCondition(PimItemTagRelation::rightFullColumnName(), Query::Equals, *tagId); 0059 } 0060 } 0061 0062 void ItemQueryHelper::remoteIdToQuery(const QStringList &rids, const CommandContext &context, QueryBuilder &qb) 0063 { 0064 if (rids.size() == 1) { 0065 qb.addValueCondition(qb.getTableWithColumn(PimItem::remoteIdColumn()), Query::Equals, rids.first()); 0066 } else { 0067 qb.addValueCondition(qb.getTableWithColumn(PimItem::remoteIdColumn()), Query::In, rids); 0068 } 0069 0070 if (context.resource().isValid()) { 0071 qb.addJoin(QueryBuilder::InnerJoin, Collection::tableName(), qb.getTableWithColumn(PimItem::collectionIdColumn()), Collection::idFullColumnName()); 0072 qb.addValueCondition(Collection::resourceIdFullColumnName(), Query::Equals, context.resource().id()); 0073 } 0074 if (context.collectionId() > 0) { 0075 qb.addValueCondition(qb.getTableWithColumn(PimItem::collectionIdColumn()), Query::Equals, context.collectionId()); 0076 } 0077 0078 const auto tagId = context.tagId(); 0079 if (tagId.has_value()) { 0080 qb.addJoin(QueryBuilder::InnerJoin, 0081 PimItemTagRelation::tableName(), 0082 qb.getTableWithColumn(PimItem::idColumn()), 0083 PimItemTagRelation::leftFullColumnName()); 0084 qb.addValueCondition(PimItemTagRelation::rightFullColumnName(), Query::Equals, *tagId); 0085 } 0086 } 0087 0088 void ItemQueryHelper::gidToQuery(const QStringList &gids, const CommandContext &context, QueryBuilder &qb) 0089 { 0090 if (gids.size() == 1) { 0091 qb.addValueCondition(qb.getTableWithColumn(PimItem::gidColumn()), Query::Equals, gids.first()); 0092 } else { 0093 qb.addValueCondition(qb.getTableWithColumn(PimItem::gidColumn()), Query::In, gids); 0094 } 0095 0096 const auto tagId = context.tagId(); 0097 if (tagId.has_value()) { 0098 // When querying for items by tag, only return matches from that resource 0099 if (context.resource().isValid()) { 0100 qb.addJoin(QueryBuilder::InnerJoin, Collection::tableName(), qb.getTableWithColumn(PimItem::collectionIdColumn()), Collection::idFullColumnName()); 0101 qb.addValueCondition(Collection::resourceIdFullColumnName(), Query::Equals, context.resource().id()); 0102 } 0103 qb.addJoin(QueryBuilder::InnerJoin, 0104 PimItemTagRelation::tableName(), 0105 qb.getTableWithColumn(PimItem::idColumn()), 0106 PimItemTagRelation::leftFullColumnName()); 0107 qb.addValueCondition(PimItemTagRelation::rightFullColumnName(), Query::Equals, *tagId); 0108 } 0109 } 0110 0111 void ItemQueryHelper::scopeToQuery(const Scope &scope, const CommandContext &context, QueryBuilder &qb) 0112 { 0113 // Handle fetch by collection/tag 0114 if (scope.scope() == Scope::Invalid && !context.isEmpty()) { 0115 itemSetToQuery(ImapSet(), context, qb); 0116 return; 0117 } 0118 0119 if (scope.scope() == Scope::Uid) { 0120 itemSetToQuery(scope.uidSet(), context, qb); 0121 return; 0122 } 0123 0124 if (scope.scope() == Scope::Gid) { 0125 ItemQueryHelper::gidToQuery(scope.gidSet(), context, qb); 0126 return; 0127 } 0128 0129 if (context.collectionId() <= 0 && !context.resource().isValid()) { 0130 throw HandlerException("Operations based on remote identifiers require a resource or collection context"); 0131 } 0132 0133 if (scope.scope() == Scope::Rid) { 0134 ItemQueryHelper::remoteIdToQuery(scope.ridSet(), context, qb); 0135 return; 0136 } else if (scope.scope() == Scope::HierarchicalRid) { 0137 QList<Scope::HRID> hridChain = scope.hridChain(); 0138 const Scope::HRID itemHRID = hridChain.takeFirst(); 0139 const Collection parentCol = CollectionQueryHelper::resolveHierarchicalRID(hridChain, context.resource().id()); 0140 const Collection oldSelection = context.collection(); 0141 CommandContext tmpContext(context); 0142 tmpContext.setCollection(parentCol); 0143 remoteIdToQuery(QStringList() << itemHRID.remoteId, tmpContext, qb); 0144 return; 0145 } 0146 0147 throw HandlerException("Dude, WTF?!?"); 0148 }