From d6a01b3f82d626856001356c0875aa738a0346ac Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Tue, 4 Oct 2016 08:25:18 +0200 Subject: Support for subqueries. This allows us to match properties from a subquery. Unfortunately this also means that DataStoreQuery needs access to all type implementations to issue the subquery (for potentially another type). --- common/datastorequery.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) (limited to 'common/datastorequery.cpp') diff --git a/common/datastorequery.cpp b/common/datastorequery.cpp index 3c4ae00..c4fbe13 100644 --- a/common/datastorequery.cpp +++ b/common/datastorequery.cpp @@ -21,6 +21,11 @@ #include "log.h" #include "entitybuffer.h" #include "entity_generated.h" +#include "applicationdomaintype.h" + +#include "folder.h" +#include "mail.h" +#include "event.h" using namespace Sink; @@ -373,8 +378,44 @@ QVector DataStoreQuery::indexLookup(const QByteArray &property, cons /* } */ /* } */ +template +QSharedPointer prepareQuery(const QByteArray &type, Args && ... args) +{ + if (type == ApplicationDomain::getTypeName()) { + return ApplicationDomain::TypeImplementation::prepareQuery(std::forward(args)...); + } else if (type == ApplicationDomain::getTypeName()) { + return ApplicationDomain::TypeImplementation::prepareQuery(std::forward(args)...); + } else if (type == ApplicationDomain::getTypeName()) { + return ApplicationDomain::TypeImplementation::prepareQuery(std::forward(args)...); + } + Q_ASSERT(false); + return QSharedPointer(); +} + +QByteArrayList DataStoreQuery::executeSubquery(const Query &subquery) +{ + Q_ASSERT(!subquery.type.isEmpty()); + auto sub = prepareQuery(subquery.type, subquery, mTransaction); + auto result = sub->execute(); + QByteArrayList ids; + while (result.next([&ids](const QByteArray &uid, const Sink::EntityBuffer &, Sink::Operation) { + ids << uid; + })) + {} + return ids; +} + void DataStoreQuery::setupQuery() { + for (const auto &k : mQuery.propertyFilter.keys()) { + const auto comparator = mQuery.propertyFilter.value(k); + if (comparator.value.canConvert()) { + SinkTrace() << "Executing subquery for property: " << k; + const auto result = executeSubquery(comparator.value.value()); + mQuery.propertyFilter.insert(k, Query::Comparator(QVariant::fromValue(result), Query::Comparator::In)); + } + } + FilterBase::Ptr baseSet; QSet remainingFilters = mQuery.getBaseFilters().keys().toSet(); QByteArray appliedSorting; @@ -459,7 +500,7 @@ ResultSet DataStoreQuery::update(qint64 baseRevision) SinkTrace() << "Changed: " << incrementalResultSet; mSource->add(incrementalResultSet); ResultSet::ValueGenerator generator = [this](const ResultSet::Callback &callback) -> bool { - if (mCollector->next([callback](Sink::Operation operation, const QByteArray &uid, const Sink::EntityBuffer &buffer) { + if (mCollector->next([this, callback](Sink::Operation operation, const QByteArray &uid, const Sink::EntityBuffer &buffer) { SinkTrace() << "Got incremental result: " << uid << operation; callback(uid, buffer, operation); })) @@ -477,7 +518,7 @@ ResultSet DataStoreQuery::execute() SinkTrace() << "Executing query"; ResultSet::ValueGenerator generator = [this](const ResultSet::Callback &callback) -> bool { - if (mCollector->next([callback](Sink::Operation operation, const QByteArray &uid, const Sink::EntityBuffer &buffer) { + if (mCollector->next([this, callback](Sink::Operation operation, const QByteArray &uid, const Sink::EntityBuffer &buffer) { if (operation != Sink::Operation_Removal) { SinkTrace() << "Got initial result: " << uid << operation; callback(uid, buffer, Sink::Operation_Creation); -- cgit v1.2.3