summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2016-09-27 16:15:44 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2016-09-27 16:15:44 +0200
commit5830d7e0d1d35494823f5fa61a4871b8d9df1c9d (patch)
tree1383d9b6ad926a97ee8376175c6bee01182dc096 /common
parent529db49c496f4f668cec3f7c59d2d0ec78c50c9a (diff)
downloadsink-5830d7e0d1d35494823f5fa61a4871b8d9df1c9d.tar.gz
sink-5830d7e0d1d35494823f5fa61a4871b8d9df1c9d.zip
Use the Query::filter api.
Diffstat (limited to 'common')
-rw-r--r--common/datastorequery.cpp31
-rw-r--r--common/query.h108
-rw-r--r--common/test.cpp2
3 files changed, 64 insertions, 77 deletions
diff --git a/common/datastorequery.cpp b/common/datastorequery.cpp
index 0fc9234..3c4ae00 100644
--- a/common/datastorequery.cpp
+++ b/common/datastorequery.cpp
@@ -146,6 +146,7 @@ public:
146 typedef QSharedPointer<Reduce> Ptr; 146 typedef QSharedPointer<Reduce> Ptr;
147 147
148 QHash<QByteArray, QVariant> mAggregateValues; 148 QHash<QByteArray, QVariant> mAggregateValues;
149 QSet<QByteArray> mReducedValues;
149 QByteArray mReductionProperty; 150 QByteArray mReductionProperty;
150 QByteArray mSelectionProperty; 151 QByteArray mSelectionProperty;
151 Query::Reduce::Selector::Comparator mSelectionComparator; 152 Query::Reduce::Selector::Comparator mSelectionComparator;
@@ -184,7 +185,9 @@ public:
184 bool foundValue = false; 185 bool foundValue = false;
185 while(!foundValue && mSource->next([this, callback, &foundValue](Sink::Operation operation, const QByteArray &uid, const Sink::EntityBuffer &entityBuffer) { 186 while(!foundValue && mSource->next([this, callback, &foundValue](Sink::Operation operation, const QByteArray &uid, const Sink::EntityBuffer &entityBuffer) {
186 auto reductionValue = getProperty(entityBuffer.entity(), mReductionProperty); 187 auto reductionValue = getProperty(entityBuffer.entity(), mReductionProperty);
187 if (!mAggregateValues.contains(getByteArray(reductionValue))) { 188 if (!mReducedValues.contains(getByteArray(reductionValue))) {
189 //Only reduce every value once.
190 mReducedValues.insert(getByteArray(reductionValue));
188 QVariant selectionResultValue; 191 QVariant selectionResultValue;
189 QByteArray selectionResult; 192 QByteArray selectionResult;
190 auto results = indexLookup(mReductionProperty, reductionValue); 193 auto results = indexLookup(mReductionProperty, reductionValue);
@@ -373,17 +376,16 @@ QVector<QByteArray> DataStoreQuery::indexLookup(const QByteArray &property, cons
373void DataStoreQuery::setupQuery() 376void DataStoreQuery::setupQuery()
374{ 377{
375 FilterBase::Ptr baseSet; 378 FilterBase::Ptr baseSet;
376 QSet<QByteArray> remainingFilters; 379 QSet<QByteArray> remainingFilters = mQuery.getBaseFilters().keys().toSet();
377 QByteArray appliedSorting; 380 QByteArray appliedSorting;
378 if (!mQuery.ids.isEmpty()) { 381 if (!mQuery.ids.isEmpty()) {
379 mSource = Source::Ptr::create(mQuery.ids.toVector(), this); 382 mSource = Source::Ptr::create(mQuery.ids.toVector(), this);
380 baseSet = mSource; 383 baseSet = mSource;
381 remainingFilters = mQuery.propertyFilter.keys().toSet();
382 } else { 384 } else {
383 QSet<QByteArray> appliedFilters; 385 QSet<QByteArray> appliedFilters;
384 386
385 auto resultSet = mTypeIndex.query(mQuery, appliedFilters, appliedSorting, mTransaction); 387 auto resultSet = mTypeIndex.query(mQuery, appliedFilters, appliedSorting, mTransaction);
386 remainingFilters = mQuery.propertyFilter.keys().toSet() - appliedFilters; 388 remainingFilters = remainingFilters - appliedFilters;
387 389
388 // We do a full scan if there were no indexes available to create the initial set. 390 // We do a full scan if there were no indexes available to create the initial set.
389 if (appliedFilters.isEmpty()) { 391 if (appliedFilters.isEmpty()) {
@@ -394,12 +396,12 @@ void DataStoreQuery::setupQuery()
394 } 396 }
395 baseSet = mSource; 397 baseSet = mSource;
396 } 398 }
397 if (!mQuery.propertyFilter.isEmpty()) { 399 if (!mQuery.getBaseFilters().isEmpty()) {
398 auto filter = Filter::Ptr::create(baseSet, this); 400 auto filter = Filter::Ptr::create(baseSet, this);
399 filter->propertyFilter = mQuery.propertyFilter; 401 //For incremental queries the remaining filters are not sufficient
400 /* for (const auto &f : remainingFilters) { */ 402 for (const auto &f : mQuery.getBaseFilters().keys()) {
401 /* filter->propertyFilter.insert(f, mQuery.propertyFilter.value(f)); */ 403 filter->propertyFilter.insert(f, mQuery.getFilter(f));
402 /* } */ 404 }
403 baseSet = filter; 405 baseSet = filter;
404 } 406 }
405 /* if (appliedSorting.isEmpty() && !mQuery.sortProperty.isEmpty()) { */ 407 /* if (appliedSorting.isEmpty() && !mQuery.sortProperty.isEmpty()) { */
@@ -407,15 +409,16 @@ void DataStoreQuery::setupQuery()
407 /* baseSet = Sort::Ptr::create(baseSet, mQuery.sortProperty); */ 409 /* baseSet = Sort::Ptr::create(baseSet, mQuery.sortProperty); */
408 /* } */ 410 /* } */
409 411
412 //Setup the rest of the filter stages on top of the base set
410 for (const auto &stage : mQuery.filterStages) { 413 for (const auto &stage : mQuery.filterStages) {
411 if (auto filter = stage.dynamicCast<Query::Filter>()) { 414 if (auto filter = stage.dynamicCast<Query::Filter>()) {
412 415 auto f = Filter::Ptr::create(baseSet, this);
416 f->propertyFilter = filter->propertyFilter;
417 baseSet = f;
413 } else if (auto filter = stage.dynamicCast<Query::Reduce>()) { 418 } else if (auto filter = stage.dynamicCast<Query::Reduce>()) {
414 auto reduce = Reduce::Ptr::create(filter->property, filter->selector.property, filter->selector.comparator, baseSet, this); 419 baseSet = Reduce::Ptr::create(filter->property, filter->selector.property, filter->selector.comparator, baseSet, this);
415 baseSet = reduce;
416 } else if (auto filter = stage.dynamicCast<Query::Bloom>()) { 420 } else if (auto filter = stage.dynamicCast<Query::Bloom>()) {
417 auto reduce = Bloom::Ptr::create(filter->property, baseSet, this); 421 baseSet = Bloom::Ptr::create(filter->property, baseSet, this);
418 baseSet = reduce;
419 } 422 }
420 } 423 }
421 424
diff --git a/common/query.h b/common/query.h
index 0c6260b..3362ac7 100644
--- a/common/query.h
+++ b/common/query.h
@@ -58,26 +58,6 @@ public:
58 Comparators comparator; 58 Comparators comparator;
59 }; 59 };
60 60
61
62 static Query PropertyFilter(const QByteArray &key, const QVariant &value)
63 {
64 Query query;
65 query.propertyFilter.insert(key, Comparator(value));
66 return query;
67 }
68
69 static Query PropertyContainsFilter(const QByteArray &key, const QVariant &value)
70 {
71 Query query;
72 query.propertyFilter.insert(key, Comparator(value, Comparator::Contains));
73 return query;
74 }
75
76 static Query PropertyFilter(const QByteArray &key, const ApplicationDomain::Entity &entity)
77 {
78 return PropertyFilter(key, QVariant::fromValue(entity.identifier()));
79 }
80
81 static Query ResourceFilter(const QByteArray &identifier) 61 static Query ResourceFilter(const QByteArray &identifier)
82 { 62 {
83 Query query; 63 Query query;
@@ -97,33 +77,6 @@ public:
97 return ResourceFilter(entity.identifier()); 77 return ResourceFilter(entity.identifier());
98 } 78 }
99 79
100 static Query AccountFilter(const QByteArray &identifier)
101 {
102 Query query;
103 query.accounts.append(identifier);
104 return query;
105 }
106
107 static Query CapabilityFilter(const QByteArray &capability)
108 {
109 Query query;
110 query.propertyFilter.insert("capabilities", Comparator(capability, Comparator::Contains));
111 return query;
112 }
113
114 static Query AccountFilter(const QByteArrayList &identifier)
115 {
116 Q_ASSERT(!identifier.isEmpty());
117 Query query;
118 query.accounts = identifier;
119 return query;
120 }
121
122 static Query AccountFilter(const ApplicationDomain::SinkAccount &entity)
123 {
124 return AccountFilter(entity.identifier());
125 }
126
127 static Query IdentityFilter(const QByteArray &identifier) 80 static Query IdentityFilter(const QByteArray &identifier)
128 { 81 {
129 Q_ASSERT(!identifier.isEmpty()); 82 Q_ASSERT(!identifier.isEmpty());
@@ -146,24 +99,17 @@ public:
146 return query; 99 return query;
147 } 100 }
148 101
149 static Query RequestedProperties(const QByteArrayList &properties) 102 template <typename T>
150 { 103 Query &request()
151 Query query;
152 query.requestedProperties = properties;
153 return query;
154 }
155
156 static Query RequestTree(const QByteArray &parentProperty)
157 { 104 {
158 Query query; 105 requestedProperties << T::name;
159 query.parentProperty = parentProperty; 106 return *this;
160 return query;
161 } 107 }
162 108
163 template <typename T> 109 template <typename T>
164 Query &request() 110 Query &requestTree()
165 { 111 {
166 requestedProperties << T::name; 112 parentProperty = T::name;
167 return *this; 113 return *this;
168 } 114 }
169 115
@@ -227,9 +173,8 @@ public:
227 * Filters 173 * Filters
228 */ 174 */
229 class Filter : public FilterStage { 175 class Filter : public FilterStage {
230 QByteArrayList ids; 176 public:
231 QHash<QByteArray, Comparator> propertyFilter; 177 QHash<QByteArray, Comparator> propertyFilter;
232 QByteArray sortProperty;
233 }; 178 };
234 179
235 template <typename T> 180 template <typename T>
@@ -239,6 +184,12 @@ public:
239 } 184 }
240 185
241 template <typename T> 186 template <typename T>
187 Query &containsFilter(const QVariant &value)
188 {
189 return filter(T::name, Comparator(value, Comparator::Contains));
190 }
191
192 template <typename T>
242 Query &filter(const Comparator &comparator) 193 Query &filter(const Comparator &comparator)
243 { 194 {
244 return filter(T::name, comparator); 195 return filter(T::name, comparator);
@@ -362,6 +313,39 @@ public:
362 filterStages << bloom; 313 filterStages << bloom;
363 } 314 }
364 315
316 //Query fixtures
317
318 /**
319 * Returns the complete thread, containing all mails from all folders.
320 */
321 static Query completeThread(const ApplicationDomain::Mail &mail)
322 {
323 Sink::Query query;
324 if (!mail.resourceInstanceIdentifier().isEmpty()) {
325 query.filter(ApplicationDomain::SinkResource(mail.resourceInstanceIdentifier()));
326 }
327 query.ids << mail.identifier();
328 query.sort<ApplicationDomain::Mail::Date>();
329 query.bloom<ApplicationDomain::Mail::ThreadId>();
330 return query;
331 }
332
333 /**
334 * Returns thread leaders only, sorted by date.
335 */
336 static Query threadLeaders(const ApplicationDomain::Folder &folder)
337 {
338 Sink::Query query;
339 if (!folder.resourceInstanceIdentifier().isEmpty()) {
340 query.filter(ApplicationDomain::SinkResource(folder.resourceInstanceIdentifier()));
341 }
342 query.filter<ApplicationDomain::Mail::Folder>(folder);
343 query.sort<ApplicationDomain::Mail::Date>();
344 query.reduce<ApplicationDomain::Mail::ThreadId>(Query::Reduce::Selector::max<ApplicationDomain::Mail::Date>());
345 return query;
346 }
347
348
365}; 349};
366 350
367} 351}
diff --git a/common/test.cpp b/common/test.cpp
index 1a8e11d..97c42ef 100644
--- a/common/test.cpp
+++ b/common/test.cpp
@@ -147,7 +147,7 @@ public:
147 } 147 }
148 SinkTrace() << "-------------------------."; 148 SinkTrace() << "-------------------------.";
149 for (const auto &res : mTestAccount->entities<T>()) { 149 for (const auto &res : mTestAccount->entities<T>()) {
150 qDebug() << "Parent filter " << query.propertyFilter.value("parent").value.toByteArray() << res->identifier() << res->getProperty("parent").toByteArray(); 150 qDebug() << "Parent filter " << query.getFilter("parent").value.toByteArray() << res->identifier() << res->getProperty("parent").toByteArray();
151 auto parentProperty = res->getProperty("parent").toByteArray(); 151 auto parentProperty = res->getProperty("parent").toByteArray();
152 if ((!parent && parentProperty.isEmpty()) || (parent && parentProperty == parent->identifier()) || query.parentProperty.isEmpty()) { 152 if ((!parent && parentProperty.isEmpty()) || (parent && parentProperty == parent->identifier()) || query.parentProperty.isEmpty()) {
153 qDebug() << "Found a match" << res->identifier(); 153 qDebug() << "Found a match" << res->identifier();