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  }
55  PimItemTagRelation::tableName(),
56  qb.getTableWithColumn(PimItem::idColumn()),
57  PimItemTagRelation::leftFullColumnName());
58  qb.addValueCondition(PimItemTagRelation::rightFullColumnName(), Query::Equals, *tagId);
59  }
60 }
61 
62 void ItemQueryHelper::remoteIdToQuery(const QStringList &rids, const CommandContext &context, QueryBuilder &qb)
63 {
64  if (rids.size() == 1) {
65  qb.addValueCondition(qb.getTableWithColumn(PimItem::remoteIdColumn()), Query::Equals, rids.first());
66  } else {
67  qb.addValueCondition(qb.getTableWithColumn(PimItem::remoteIdColumn()), Query::In, rids);
68  }
69 
70  if (context.resource().isValid()) {
71  qb.addJoin(QueryBuilder::InnerJoin, Collection::tableName(), qb.getTableWithColumn(PimItem::collectionIdColumn()), Collection::idFullColumnName());
72  qb.addValueCondition(Collection::resourceIdFullColumnName(), Query::Equals, context.resource().id());
73  }
74  if (context.collectionId() > 0) {
75  qb.addValueCondition(qb.getTableWithColumn(PimItem::collectionIdColumn()), Query::Equals, context.collectionId());
76  }
77 
78  const auto tagId = context.tagId();
79  if (tagId.has_value()) {
81  PimItemTagRelation::tableName(),
82  qb.getTableWithColumn(PimItem::idColumn()),
83  PimItemTagRelation::leftFullColumnName());
84  qb.addValueCondition(PimItemTagRelation::rightFullColumnName(), Query::Equals, *tagId);
85  }
86 }
87 
88 void ItemQueryHelper::gidToQuery(const QStringList &gids, const CommandContext &context, QueryBuilder &qb)
89 {
90  if (gids.size() == 1) {
91  qb.addValueCondition(qb.getTableWithColumn(PimItem::gidColumn()), Query::Equals, gids.first());
92  } else {
93  qb.addValueCondition(qb.getTableWithColumn(PimItem::gidColumn()), Query::In, gids);
94  }
95 
96  const auto tagId = context.tagId();
97  if (tagId.has_value()) {
98  // When querying for items by tag, only return matches from that resource
99  if (context.resource().isValid()) {
100  qb.addJoin(QueryBuilder::InnerJoin, Collection::tableName(), qb.getTableWithColumn(PimItem::collectionIdColumn()), Collection::idFullColumnName());
101  qb.addValueCondition(Collection::resourceIdFullColumnName(), Query::Equals, context.resource().id());
102  }
104  PimItemTagRelation::tableName(),
105  qb.getTableWithColumn(PimItem::idColumn()),
106  PimItemTagRelation::leftFullColumnName());
107  qb.addValueCondition(PimItemTagRelation::rightFullColumnName(), Query::Equals, *tagId);
108  }
109 }
110 
111 void ItemQueryHelper::scopeToQuery(const Scope &scope, const CommandContext &context, QueryBuilder &qb)
112 {
113  // Handle fetch by collection/tag
114  if (scope.scope() == Scope::Invalid && !context.isEmpty()) {
115  itemSetToQuery(ImapSet(), context, qb);
116  return;
117  }
118 
119  if (scope.scope() == Scope::Uid) {
120  itemSetToQuery(scope.uidSet(), context, qb);
121  return;
122  }
123 
124  if (scope.scope() == Scope::Gid) {
125  ItemQueryHelper::gidToQuery(scope.gidSet(), context, qb);
126  return;
127  }
128 
129  if (context.collectionId() <= 0 && !context.resource().isValid()) {
130  throw HandlerException("Operations based on remote identifiers require a resource or collection context");
131  }
132 
133  if (scope.scope() == Scope::Rid) {
134  ItemQueryHelper::remoteIdToQuery(scope.ridSet(), context, qb);
135  return;
136  } else if (scope.scope() == Scope::HierarchicalRid) {
137  QVector<Scope::HRID> hridChain = scope.hridChain();
138  const Scope::HRID itemHRID = hridChain.takeFirst();
139  const Collection parentCol = CollectionQueryHelper::resolveHierarchicalRID(hridChain, context.resource().id());
140  const Collection oldSelection = context.collection();
141  CommandContext tmpContext(context);
142  tmpContext.setCollection(parentCol);
143  remoteIdToQuery(QStringList() << itemHRID.remoteId, tmpContext, qb);
144  return;
145  }
146 
147  throw HandlerException("Dude, WTF?!?");
148 }
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 Tue Dec 6 2022 03:53:33 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.