9#include "collectionstatistics.h"
10#include "akonadiserver_debug.h"
11#include "countquerybuilder.h"
14#include "querybuilder.h"
16#include "private/protocol_p.h"
18using namespace Akonadi::Server;
20CollectionStatistics::CollectionStatistics(
bool prefetch)
25 std::vector<QueryBuilder> builders;
28 auto qb = prepareGenericQuery();
29 qb.addColumn(PimItem::collectionIdFullColumnName());
30 qb.addGroupColumn(PimItem::collectionIdFullColumnName());
31 builders.emplace_back(std::move(qb));
35 qb = prepareGenericQuery();
36 qb.addColumn(CollectionPimItemRelation::leftFullColumnName());
38 CollectionPimItemRelation::tableName(),
39 CollectionPimItemRelation::rightFullColumnName(),
40 PimItem::idFullColumnName());
41 qb.addGroupColumn(CollectionPimItemRelation::leftFullColumnName());
42 builders.emplace_back(std::move(qb));
44 for (
auto &qb : builders) {
49 auto &
query = qb.query();
50 while (
query.next()) {
51 mCache.
insert(
query.
value(3).toLongLong(), {query.value(0).toLongLong(), query.value(1).toLongLong(), query.value(2).toLongLong()});
58 qb.addColumn(Collection::idColumn());
59 qb.addValueCondition(Collection::enabledColumn(), Query::Equals,
true);
60 qb.addValueCondition(Collection::isVirtualColumn(), Query::Equals,
false);
65 auto &
query = qb.query();
66 while (
query.next()) {
67 const auto colId =
query.
value(0).toLongLong();
69 mCache.
insert(colId, {0, 0, 0});
75void CollectionStatistics::itemAdded(
const Collection &col, qint64 size,
bool seen)
82 auto stats = mCache.
find(col.id());
83 if (stats != mCache.
end()) {
86 stats->read += (seen ? 1 : 0);
88 mCache.
insert(col.id(), calculateCollectionStatistics(col));
92void CollectionStatistics::itemsSeenChanged(
const Collection &col, qint64 seenCount)
99 auto stats = mCache.
find(col.id());
100 if (stats != mCache.
end()) {
101 stats->read += seenCount;
103 mCache.
insert(col.id(), calculateCollectionStatistics(col));
107void CollectionStatistics::invalidateCollection(
const Collection &col)
109 if (!col.isValid()) {
117void CollectionStatistics::expireCache()
123CollectionStatistics::Statistics CollectionStatistics::statistics(
const Collection &col)
126 auto it = mCache.
find(col.id());
127 if (it == mCache.
end()) {
128 it = mCache.
insert(col.id(), calculateCollectionStatistics(col));
135 static const QString SeenFlagsTableName = QStringLiteral(
"SeenFlags");
136 static const QString IgnoredFlagsTableName = QStringLiteral(
"IgnoredFlags");
138#define FLAGS_COLUMN(table, column) QStringLiteral("%1.%2").arg(table##TableName, PimItemFlagRelation::column())
141 CountQueryBuilder qb(PimItem::tableName(), PimItem::idFullColumnName(), CountQueryBuilder::Distinct);
143 qb.addAggregation(PimItem::sizeFullColumnName(), QStringLiteral(
"sum"));
153 cond.addValueCondition(FLAGS_COLUMN(SeenFlags, rightColumn), Query::IsNot,
QVariant());
154 cond.addValueCondition(FLAGS_COLUMN(IgnoredFlags, rightColumn), Query::IsNot,
QVariant());
156 Query::Case caseStmt(cond, QStringLiteral(
"1"), QStringLiteral(
"0"));
157 qb.addAggregation(caseStmt, QStringLiteral(
"sum"));
164 seenCondition.addColumnCondition(PimItem::idFullColumnName(), Query::Equals, FLAGS_COLUMN(SeenFlags, leftColumn));
165 seenCondition.addValueCondition(FLAGS_COLUMN(SeenFlags, rightColumn),
167 Flag::retrieveByNameOrCreate(QStringLiteral(AKONADI_FLAG_SEEN)).
id());
168 qb.addJoin(
QueryBuilder::LeftJoin, QStringLiteral(
"%1 AS %2").arg(PimItemFlagRelation::tableName(), SeenFlagsTableName), seenCondition);
172 ignoredCondition.addColumnCondition(PimItem::idFullColumnName(), Query::Equals, FLAGS_COLUMN(IgnoredFlags, leftColumn));
173 ignoredCondition.addValueCondition(FLAGS_COLUMN(IgnoredFlags, rightColumn),
175 Flag::retrieveByNameOrCreate(QStringLiteral(AKONADI_FLAG_IGNORED)).
id());
176 qb.addJoin(
QueryBuilder::LeftJoin, QStringLiteral(
"%1 AS %2").arg(PimItemFlagRelation::tableName(), IgnoredFlagsTableName), ignoredCondition);
184CollectionStatistics::Statistics CollectionStatistics::calculateCollectionStatistics(
const Collection &col)
186 auto qb = prepareGenericQuery();
188 if (col.isVirtual()) {
190 CollectionPimItemRelation::tableName(),
191 CollectionPimItemRelation::rightFullColumnName(),
192 PimItem::idFullColumnName());
193 qb.addValueCondition(CollectionPimItemRelation::leftFullColumnName(), Query::Equals, col.id());
195 qb.addValueCondition(PimItem::collectionIdColumn(), Query::Equals, col.id());
201 if (!qb.query().next()) {
202 qCCritical(AKONADISERVER_LOG) <<
"Error during retrieving result of statistics query:" << qb.query().lastError().text();
206 auto result = Statistics{qb.query().value(0).toLongLong(), qb.query().value(1).toLongLong(), qb.query().value(2).toLongLong()};
Represents a collection of PIM items.
Helper class for creating queries to count elements in a database.
Helper class to construct arbitrary SQL queries.
@ InnerJoin
NOTE: only supported for UPDATE and SELECT queries.
@ LeftJoin
NOTE: only supported for SELECT queries.
Represents a WHERE condition tree.
KSERVICE_EXPORT KService::List query(FilterFunc filterFunc)
bool contains(const Key &key) const const
iterator find(const Key &key)
iterator insert(const Key &key, const T &value)
bool remove(const Key &key)
T value(qsizetype i) const const