Akonadi

itemqueryhelper.cpp
1 /*
2  SPDX-FileCopyrightText: 2009 Volker Krause <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "itemqueryhelper.h"
8 
9 #include "collectionqueryhelper.h"
10 #include "commandcontext.h"
11 #include "handler.h"
12 #include "storage/querybuilder.h"
13 #include "storage/queryhelper.h"
14 
15 #include <private/imapset_p.h>
16 #include <private/scope_p.h>
17 
18 using namespace Akonadi;
19 using namespace Akonadi::Server;
20 
21 void ItemQueryHelper::itemSetToQuery(const ImapSet &set, QueryBuilder &qb, const Collection &collection)
22 {
23  if (!set.isEmpty()) {
24  QueryHelper::setToQuery(set, qb.getTableWithColumn(PimItem::idColumn()), qb);
25  }
26  if (collection.isValid()) {
27  if (collection.isVirtual() || collection.resource().isVirtual()) {
29  CollectionPimItemRelation::tableName(),
30  CollectionPimItemRelation::rightFullColumnName(),
31  qb.getTableWithColumn(PimItem::idColumn()));
32  qb.addValueCondition(CollectionPimItemRelation::leftFullColumnName(), Query::Equals, collection.id());
33  } else {
34  qb.addValueCondition(qb.getTableWithColumn(PimItem::collectionIdColumn()), Query::Equals, collection.id());
35  }
36  }
37 }
38 
39 void ItemQueryHelper::itemSetToQuery(const ImapSet &set, const CommandContext &context, QueryBuilder &qb)
40 {
41  if (context.collectionId() >= 0) {
42  itemSetToQuery(set, qb, context.collection());
43  } else {
44  itemSetToQuery(set, qb);
45  }
46 
47  const auto tagId = context.tagId();
48  if (tagId.has_value()) {
49  // When querying for items by tag, only return matches from that resource
50  if (context.resource().isValid()) {
51  qb.addJoin(QueryBuilder::InnerJoin, Collection::tableName(), qb.getTableWithColumn(PimItem::collectionIdColumn()), Collection::idFullColumnName());
52  qb.addValueCondition(Collection::resourceIdFullColumnName(), Query::Equals, context.resource().id());
53  }
54  qb.addJoin(QueryBuilder::InnerJoin, PimItemTagRelation::tableName(), qb.getTableWithColumn(PimItem::idColumn()), PimItemTagRelation::leftFullColumnName());
55  qb.addValueCondition(PimItemTagRelation::rightFullColumnName(), Query::Equals, *tagId);
56  }
57 }
58 
59 void ItemQueryHelper::remoteIdToQuery(const QStringList &rids, const CommandContext &context, QueryBuilder &qb)
60 {
61  if (rids.size() == 1) {
62  qb.addValueCondition(qb.getTableWithColumn(PimItem::remoteIdColumn()), Query::Equals, rids.first());
63  } else {
64  qb.addValueCondition(qb.getTableWithColumn(PimItem::remoteIdColumn()), Query::In, rids);
65  }
66 
67  if (context.resource().isValid()) {
68  qb.addJoin(QueryBuilder::InnerJoin, Collection::tableName(), qb.getTableWithColumn(PimItem::collectionIdColumn()), Collection::idFullColumnName());
69  qb.addValueCondition(Collection::resourceIdFullColumnName(), Query::Equals, context.resource().id());
70  }
71  if (context.collectionId() > 0) {
72  qb.addValueCondition(qb.getTableWithColumn(PimItem::collectionIdColumn()), Query::Equals, context.collectionId());
73  }
74 
75  const auto tagId = context.tagId();
76  if (tagId.has_value()) {
77  qb.addJoin(QueryBuilder::InnerJoin, PimItemTagRelation::tableName(), qb.getTableWithColumn(PimItem::idColumn()), PimItemTagRelation::leftFullColumnName());
78  qb.addValueCondition(PimItemTagRelation::rightFullColumnName(), Query::Equals, *tagId);
79  }
80 }
81 
82 void ItemQueryHelper::gidToQuery(const QStringList &gids, const CommandContext &context, QueryBuilder &qb)
83 {
84  if (gids.size() == 1) {
85  qb.addValueCondition(qb.getTableWithColumn(PimItem::gidColumn()), Query::Equals, gids.first());
86  } else {
87  qb.addValueCondition(qb.getTableWithColumn(PimItem::gidColumn()), Query::In, gids);
88  }
89 
90  const auto tagId = context.tagId();
91  if (tagId.has_value()) {
92  // When querying for items by tag, only return matches from that resource
93  if (context.resource().isValid()) {
94  qb.addJoin(QueryBuilder::InnerJoin, Collection::tableName(), qb.getTableWithColumn(PimItem::collectionIdColumn()), Collection::idFullColumnName());
95  qb.addValueCondition(Collection::resourceIdFullColumnName(), Query::Equals, context.resource().id());
96  }
97  qb.addJoin(QueryBuilder::InnerJoin, PimItemTagRelation::tableName(), qb.getTableWithColumn(PimItem::idColumn()), PimItemTagRelation::leftFullColumnName());
98  qb.addValueCondition(PimItemTagRelation::rightFullColumnName(), Query::Equals, *tagId);
99  }
100 }
101 
102 void ItemQueryHelper::scopeToQuery(const Scope &scope, const CommandContext &context, QueryBuilder &qb)
103 {
104  // Handle fetch by collection/tag
105  if (scope.scope() == Scope::Invalid && !context.isEmpty()) {
106  itemSetToQuery(ImapSet(), context, qb);
107  return;
108  }
109 
110  if (scope.scope() == Scope::Uid) {
111  itemSetToQuery(scope.uidSet(), context, qb);
112  return;
113  }
114 
115  if (scope.scope() == Scope::Gid) {
116  ItemQueryHelper::gidToQuery(scope.gidSet(), context, qb);
117  return;
118  }
119 
120  if (context.collectionId() <= 0 && !context.resource().isValid()) {
121  throw HandlerException("Operations based on remote identifiers require a resource or collection context");
122  }
123 
124  if (scope.scope() == Scope::Rid) {
125  ItemQueryHelper::remoteIdToQuery(scope.ridSet(), context, qb);
126  return;
127  } else if (scope.scope() == Scope::HierarchicalRid) {
128  QVector<Scope::HRID> hridChain = scope.hridChain();
129  const Scope::HRID itemHRID = hridChain.takeFirst();
130  const Collection parentCol = CollectionQueryHelper::resolveHierarchicalRID(hridChain, context.resource().id());
131  const Collection oldSelection = context.collection();
132  CommandContext tmpContext(context);
133  tmpContext.setCollection(parentCol);
134  remoteIdToQuery(QStringList() << itemHRID.remoteId, tmpContext, qb);
135  return;
136  }
137 
138  throw HandlerException("Dude, WTF?!?");
139 }
T & first()
void scopeToQuery(const Scope &scope, const CommandContext &context, QueryBuilder &qb)
Add conditions to qb for the given item operation scope scope.
QString getTableWithColumn(const QString &column) const
Returns concatenated table name with column name.
@ InnerJoin
NOTE: only supported for UPDATE and SELECT queries.
Definition: querybuilder.h:48
Represents a collection of PIM items.
Definition: collection.h:61
void setToQuery(const ImapSet &set, const QString &column, QueryBuilder &qb)
Add conditions to qb for the given uid set set applied to column.
Definition: queryhelper.cpp:16
Collection resolveHierarchicalRID(const QVector< Scope::HRID > &hridChain, Resource::Id resId)
Retrieve the collection referred to by the given hierarchical RID chain.
void itemSetToQuery(const ImapSet &set, QueryBuilder &qb, const Collection &collection=Collection())
Add conditions to qb for the given item set set.
void addJoin(JoinType joinType, const QString &table, const Query::Condition &condition)
Join a table to the query.
int size() const const
void addValueCondition(const QString &column, Query::CompareOperator op, const QVariant &value, ConditionType type=WhereCondition)
Add a WHERE or HAVING condition which compares a column with a given value.
void remoteIdToQuery(const QStringList &rids, const CommandContext &context, QueryBuilder &qb)
Add conditions to qb for the given remote identifier rid.
T takeFirst()
Helper class to construct arbitrary SQL queries.
Definition: querybuilder.h:31
Helper integration between Akonadi and Qt.
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Thu Jun 30 2022 03:51:46 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.