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

KDE's Doxygen guidelines are available online.