From d3cb4e649177443e8ecfd7f86d136fc0a319e2f3 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Fri, 12 May 2017 14:00:54 +0200 Subject: Don't add resources that don't match the query during a livequery --- common/resourcefacade.cpp | 43 +++++++++++++++++++++++++++++++------------ common/resourcefacade.h | 18 +++++++++--------- tests/querytest.cpp | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 21 deletions(-) diff --git a/common/resourcefacade.cpp b/common/resourcefacade.cpp index e6f98a9..dab6aed 100644 --- a/common/resourcefacade.cpp +++ b/common/resourcefacade.cpp @@ -96,17 +96,24 @@ template LocalStorageQueryRunner::LocalStorageQueryRunner(const Query &query, const QByteArray &identifier, const QByteArray &typeName, ConfigNotifier &configNotifier, const Sink::Log::Context &ctx) : mResultProvider(new ResultProvider), mConfigStore(identifier, typeName), mGuard(new QObject), mLogCtx(ctx.subContext("config")) { + + auto matchesTypeAndIds = [query, this] (const QByteArray &type, const QByteArray &id) { + if (query.hasFilter(ApplicationDomain::SinkResource::ResourceType::name) && query.getFilter(ApplicationDomain::SinkResource::ResourceType::name).value.toByteArray() != type) { + SinkTraceCtx(mLogCtx) << "Skipping due to type."; + return false; + } + if (!query.ids().isEmpty() && !query.ids().contains(id)) { + return false; + } + return true; + }; + QObject *guard = new QObject; - mResultProvider->setFetcher([this, query, guard, &configNotifier](const QSharedPointer &) { + mResultProvider->setFetcher([this, query, guard, &configNotifier, matchesTypeAndIds](const QSharedPointer &) { const auto entries = mConfigStore.getEntries(); for (const auto &res : entries.keys()) { const auto type = entries.value(res); - - if (query.hasFilter(ApplicationDomain::SinkResource::ResourceType::name) && query.getFilter(ApplicationDomain::SinkResource::ResourceType::name).value.toByteArray() != type) { - SinkTraceCtx(mLogCtx) << "Skipping due to type."; - continue; - } - if (!query.ids().isEmpty() && !query.ids().contains(res)) { + if (!matchesTypeAndIds(type, res)){ continue; } auto entity = readFromConfig(mConfigStore, res, type, query.requestedProperties); @@ -124,8 +131,14 @@ LocalStorageQueryRunner::LocalStorageQueryRunner(const Query &query, }); if (query.liveQuery()) { { - auto ret = QObject::connect(&configNotifier, &ConfigNotifier::added, guard, [this](const ApplicationDomain::ApplicationDomainType::Ptr &entry) { + auto ret = QObject::connect(&configNotifier, &ConfigNotifier::added, guard, [this, query, matchesTypeAndIds](const ApplicationDomain::ApplicationDomainType::Ptr &entry, const QByteArray &type) { auto entity = entry.staticCast(); + if (!matchesTypeAndIds(type, entity->identifier())){ + return; + } + if (!matchesFilter(query.getBaseFilters(), *entity)){ + return; + } SinkTraceCtx(mLogCtx) << "A new resource has been added: " << entity->identifier(); updateStatus(*entity); mResultProvider->add(entity); @@ -133,8 +146,14 @@ LocalStorageQueryRunner::LocalStorageQueryRunner(const Query &query, Q_ASSERT(ret); } { - auto ret = QObject::connect(&configNotifier, &ConfigNotifier::modified, guard, [this](const ApplicationDomain::ApplicationDomainType::Ptr &entry) { + auto ret = QObject::connect(&configNotifier, &ConfigNotifier::modified, guard, [this, query, matchesTypeAndIds](const ApplicationDomain::ApplicationDomainType::Ptr &entry, const QByteArray &type) { auto entity = entry.staticCast(); + if (!matchesTypeAndIds(type, entity->identifier())){ + return; + } + if (!matchesFilter(query.getBaseFilters(), *entity)){ + return; + } updateStatus(*entity); mResultProvider->modify(entity); }); @@ -218,7 +237,7 @@ KAsync::Job LocalStorageFacade::create(const DomainType &domai } configStore.modify(identifier, configurationValues); } - sConfigNotifier.add(::readFromConfig(configStore, identifier, type, QByteArrayList{})); + sConfigNotifier.add(::readFromConfig(configStore, identifier, type, QByteArrayList{}), type); }); } @@ -247,7 +266,7 @@ KAsync::Job LocalStorageFacade::modify(const DomainType &domai } const auto type = configStore.getEntries().value(identifier); - sConfigNotifier.modify(::readFromConfig(configStore, identifier, type, QByteArrayList{})); + sConfigNotifier.modify(::readFromConfig(configStore, identifier, type, QByteArrayList{}), type); }); } @@ -277,7 +296,7 @@ KAsync::Job LocalStorageFacade::remove(const DomainType &domai SinkTrace() << "Removing: " << identifier; auto configStore = ConfigStore(configStoreIdentifier, typeName); configStore.remove(identifier); - sConfigNotifier.remove(QSharedPointer::create(domainObject)); + sConfigNotifier.remove(QSharedPointer::create(domainObject), typeName); }); } diff --git a/common/resourcefacade.h b/common/resourcefacade.h index 1cc075c..76fadce 100644 --- a/common/resourcefacade.h +++ b/common/resourcefacade.h @@ -36,24 +36,24 @@ class ConfigNotifier : public QObject { Q_OBJECT public: - void add(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account) + void add(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account, const QByteArray &type) { - emit added(account); + emit added(account, type); } - void remove(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account) + void remove(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account, const QByteArray &type) { - emit removed(account); + emit removed(account, type); } - void modify(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account) + void modify(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account, const QByteArray &type) { - emit modified(account); + emit modified(account, type); } signals: - void added(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account); - void removed(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account); - void modified(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account); + void added(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account, const QByteArray &type); + void removed(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account, const QByteArray &type); + void modified(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &account, const QByteArray &type); }; template diff --git a/tests/querytest.cpp b/tests/querytest.cpp index 72eca86..4ff1be8 100644 --- a/tests/querytest.cpp +++ b/tests/querytest.cpp @@ -625,6 +625,41 @@ private slots: // We fetch before the data is available and rely on the live query mechanism to deliver the actual data auto folders = Sink::Store::read(Sink::Query{}.resourceContainsFilter("cap1")); QCOMPARE(folders.size(), 1); + + //TODO this should be part of the regular cleanup between tests + VERIFYEXEC(Store::remove(resource1)); + VERIFYEXEC(Store::remove(resource2)); + } + + void testFilteredLiveResourceSubQuery() + { + using namespace Sink; + using namespace Sink::ApplicationDomain; + + //Setup + auto resource1 = ApplicationDomainType::createEntity(); + resource1.setResourceType("sink.dummy"); + resource1.setCapabilities(QByteArrayList() << "cap1"); + VERIFYEXEC(Store::create(resource1)); + VERIFYEXEC(Store::create(Folder{resource1.identifier()})); + VERIFYEXEC(ResourceControl::flushMessageQueue(resource1.identifier())); + + auto model = Sink::Store::loadModel(Query{Query::LiveQuery}.resourceContainsFilter("cap1")); + QTRY_COMPARE(model->rowCount(), 1); + + auto resource2 = ApplicationDomainType::createEntity(); + resource2.setCapabilities(QByteArrayList() << "cap2"); + resource2.setResourceType("sink.dummy"); + VERIFYEXEC(Store::create(resource2)); + VERIFYEXEC(Store::create(Folder{resource2.identifier()})); + VERIFYEXEC(ResourceControl::flushMessageQueue(resource2.identifier())); + + //The new resource should be filtered and thus not make it in here + QCOMPARE(model->rowCount(), 1); + + //TODO this should be part of the regular cleanup between tests + VERIFYEXEC(Store::remove(resource1)); + VERIFYEXEC(Store::remove(resource2)); } void testLivequeryUnmatchInThread() -- cgit v1.2.3