summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2017-01-27 16:56:17 +0100
committerChristian Mollekopf <chrigi_1@fastmail.fm>2017-01-31 19:38:57 +0100
commit871a048580d5a464fb697713a5e0e2c52dee5208 (patch)
tree3cdc2bff1e9267b75448b9ca52b84fe46841e23e
parent8ddf4c9d2967ba4acc4121f8e845c07e421d9b23 (diff)
downloadsink-871a048580d5a464fb697713a5e0e2c52dee5208.tar.gz
sink-871a048580d5a464fb697713a5e0e2c52dee5208.zip
Ensure blooming queries filter as they should
After the initial bloom, it should turn into a regular filter.
-rw-r--r--common/datastorequery.cpp46
-rw-r--r--common/domain/applicationdomaintype.cpp1
-rw-r--r--tests/querytest.cpp92
3 files changed, 122 insertions, 17 deletions
diff --git a/common/datastorequery.cpp b/common/datastorequery.cpp
index d90d546..087f405 100644
--- a/common/datastorequery.cpp
+++ b/common/datastorequery.cpp
@@ -101,7 +101,7 @@ public:
101 101
102 virtual ~Filter(){} 102 virtual ~Filter(){}
103 103
104 bool next(const std::function<void(const ResultSet::Result &result)> &callback) Q_DECL_OVERRIDE { 104 virtual bool next(const std::function<void(const ResultSet::Result &result)> &callback) Q_DECL_OVERRIDE {
105 bool foundValue = false; 105 bool foundValue = false;
106 while(!foundValue && mSource->next([this, callback, &foundValue](const ResultSet::Result &result) { 106 while(!foundValue && mSource->next([this, callback, &foundValue](const ResultSet::Result &result) {
107 SinkTrace() << "Filter: " << result.entity.identifier() << result.operation; 107 SinkTrace() << "Filter: " << result.entity.identifier() << result.operation;
@@ -273,14 +273,14 @@ public:
273 } 273 }
274}; 274};
275 275
276class Bloom : public FilterBase { 276class Bloom : public Filter {
277public: 277public:
278 typedef QSharedPointer<Bloom> Ptr; 278 typedef QSharedPointer<Bloom> Ptr;
279 279
280 QByteArray mBloomProperty; 280 QByteArray mBloomProperty;
281 281
282 Bloom(const QByteArray &bloomProperty, FilterBase::Ptr source, DataStoreQuery *store) 282 Bloom(const QByteArray &bloomProperty, FilterBase::Ptr source, DataStoreQuery *store)
283 : FilterBase(source, store), 283 : Filter(source, store),
284 mBloomProperty(bloomProperty) 284 mBloomProperty(bloomProperty)
285 { 285 {
286 286
@@ -289,21 +289,33 @@ public:
289 virtual ~Bloom(){} 289 virtual ~Bloom(){}
290 290
291 bool next(const std::function<void(const ResultSet::Result &result)> &callback) Q_DECL_OVERRIDE { 291 bool next(const std::function<void(const ResultSet::Result &result)> &callback) Q_DECL_OVERRIDE {
292 bool foundValue = false; 292 if (!mBloomed) {
293 while(!foundValue && mSource->next([this, callback, &foundValue](const ResultSet::Result &result) { 293 //Initially we bloom on the first value that matches.
294 auto bloomValue = result.entity.getProperty(mBloomProperty); 294 //From there on we just filter.
295 auto results = indexLookup(mBloomProperty, bloomValue); 295 bool foundValue = false;
296 for (const auto &r : results) { 296 while(!foundValue && mSource->next([this, callback, &foundValue](const ResultSet::Result &result) {
297 readEntity(r, [&, this](const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation operation) { 297 mBloomValue = result.entity.getProperty(mBloomProperty);
298 callback({entity, Sink::Operation_Creation}); 298 auto results = indexLookup(mBloomProperty, mBloomValue);
299 foundValue = true; 299 SinkWarning() << "Bloomed on value " << mBloomValue << " and found " << results.size();
300 }); 300 for (const auto &r : results) {
301 } 301 readEntity(r, [&, this](const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation operation) {
302 return false; 302 callback({entity, Sink::Operation_Creation});
303 })) 303 foundValue = true;
304 {} 304 });
305 return foundValue; 305 }
306 return false;
307 }))
308 {}
309 mBloomed = true;
310 propertyFilter.insert(mBloomProperty, mBloomValue);
311 return foundValue;
312 } else {
313 //Filter on bloom value
314 return Filter::next(callback);
315 }
306 } 316 }
317 QVariant mBloomValue;
318 bool mBloomed = false;
307}; 319};
308 320
309DataStoreQuery::DataStoreQuery(const Sink::QueryBase &query, const QByteArray &type, EntityStore &store) 321DataStoreQuery::DataStoreQuery(const Sink::QueryBase &query, const QByteArray &type, EntityStore &store)
diff --git a/common/domain/applicationdomaintype.cpp b/common/domain/applicationdomaintype.cpp
index 6d16a3c..57d0f2d 100644
--- a/common/domain/applicationdomaintype.cpp
+++ b/common/domain/applicationdomaintype.cpp
@@ -30,6 +30,7 @@ namespace Sink {
30namespace ApplicationDomain { 30namespace ApplicationDomain {
31 31
32constexpr const char *Mail::ThreadId::name; 32constexpr const char *Mail::ThreadId::name;
33constexpr const char *Mail::Folder::name;
33 34
34static const int foo = [] { 35static const int foo = [] {
35 QMetaType::registerEqualsComparator<Reference>(); 36 QMetaType::registerEqualsComparator<Reference>();
diff --git a/tests/querytest.cpp b/tests/querytest.cpp
index 92fc1f7..10f5567 100644
--- a/tests/querytest.cpp
+++ b/tests/querytest.cpp
@@ -11,6 +11,7 @@
11#include "modelresult.h" 11#include "modelresult.h"
12#include "test.h" 12#include "test.h"
13#include "testutils.h" 13#include "testutils.h"
14#include "applicationdomaintype.h"
14 15
15using namespace Sink; 16using namespace Sink;
16using namespace Sink::ApplicationDomain; 17using namespace Sink::ApplicationDomain;
@@ -632,6 +633,7 @@ private slots:
632 auto folders = Sink::Store::read<Folder>(query); 633 auto folders = Sink::Store::read<Folder>(query);
633 QCOMPARE(folders.size(), 1); 634 QCOMPARE(folders.size(), 1);
634 } 635 }
636
635 void testLivequeryUnmatchInThread() 637 void testLivequeryUnmatchInThread()
636 { 638 {
637 // Setup 639 // Setup
@@ -707,6 +709,96 @@ private slots:
707 auto mail = model->data(model->index(0, 0, QModelIndex{}), Sink::Store::DomainObjectRole).value<Mail::Ptr>(); 709 auto mail = model->data(model->index(0, 0, QModelIndex{}), Sink::Store::DomainObjectRole).value<Mail::Ptr>();
708 QCOMPARE(mail->getUnread(), true); 710 QCOMPARE(mail->getUnread(), true);
709 } 711 }
712
713 void testBloom()
714 {
715 // Setup
716 auto folder1 = Folder::createEntity<Folder>("sink.dummy.instance1");
717 VERIFYEXEC(Sink::Store::create<Folder>(folder1));
718
719 auto folder2 = Folder::createEntity<Folder>("sink.dummy.instance1");
720 VERIFYEXEC(Sink::Store::create<Folder>(folder2));
721
722 auto mail1 = Mail::createEntity<Mail>("sink.dummy.instance1");
723 mail1.setUid("mail1");
724 mail1.setFolder(folder1);
725 VERIFYEXEC(Sink::Store::create(mail1));
726
727 // Ensure all local data is processed
728 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue("sink.dummy.instance1"));
729
730 {
731 auto mail = Mail::createEntity<Mail>("sink.dummy.instance1");
732 mail.setUid("mail2");
733 mail.setFolder(folder1);
734 VERIFYEXEC(Sink::Store::create(mail));
735 }
736 {
737 auto mail = Mail::createEntity<Mail>("sink.dummy.instance1");
738 mail.setUid("mail3");
739 mail.setFolder(folder2);
740 VERIFYEXEC(Sink::Store::create(mail));
741 }
742 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue("sink.dummy.instance1"));
743
744 Query query;
745 query.setId("testFilterCreationInThread");
746 query.filter(mail1.identifier());
747 query.bloom<Mail::Folder>();
748 query.request<Mail::Folder>();
749
750 auto model = Sink::Store::loadModel<Mail>(query);
751 QTRY_VERIFY(model->data(QModelIndex(), Sink::Store::ChildrenFetchedRole).toBool());
752 QCOMPARE(model->rowCount(), 2);
753 }
754
755 void testLivequeryFilterCreationInThread()
756 {
757 // Setup
758 auto folder1 = Folder::createEntity<Folder>("sink.dummy.instance1");
759 VERIFYEXEC(Sink::Store::create<Folder>(folder1));
760
761 auto folder2 = Folder::createEntity<Folder>("sink.dummy.instance1");
762 VERIFYEXEC(Sink::Store::create<Folder>(folder2));
763
764 auto mail1 = Mail::createEntity<Mail>("sink.dummy.instance1");
765 mail1.setUid("mail1");
766 mail1.setFolder(folder1);
767 VERIFYEXEC(Sink::Store::create(mail1));
768
769 // Ensure all local data is processed
770 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue("sink.dummy.instance1"));
771
772 Query query;
773 query.setId("testFilterCreationInThread");
774 query.filter(mail1.identifier());
775 query.bloom<Mail::Folder>();
776 query.sort<Mail::Date>();
777 query.setFlags(Query::LiveQuery);
778 query.request<Mail::Unread>();
779 query.request<Mail::Folder>();
780
781 auto model = Sink::Store::loadModel<Mail>(query);
782 QTRY_COMPARE(model->rowCount(), 1);
783
784 {
785 auto mail = Mail::createEntity<Mail>("sink.dummy.instance1");
786 mail.setUid("mail2");
787 mail.setFolder(folder1);
788 VERIFYEXEC(Sink::Store::create(mail));
789 }
790 {
791 auto mail = Mail::createEntity<Mail>("sink.dummy.instance1");
792 mail.setUid("mail3");
793 mail.setFolder(folder2);
794 VERIFYEXEC(Sink::Store::create(mail));
795 }
796 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue("sink.dummy.instance1"));
797
798 QTRY_COMPARE(model->rowCount(), 2);
799 QTest::qWait(100);
800 QCOMPARE(model->rowCount(), 2);
801 }
710}; 802};
711 803
712QTEST_MAIN(QueryTest) 804QTEST_MAIN(QueryTest)