diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2018-02-22 17:22:26 +0100 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2018-02-22 17:22:45 +0100 |
commit | 7287dae6c279583e5c5f0fafd8207341cc5a15af (patch) | |
tree | 22457f7d5a7a8a0e050f72072ee146db1b4d3ff8 /common/datastorequery.cpp | |
parent | 7748c2a5c1cc29a8c69ea051174e31b02af4a208 (diff) | |
download | sink-7287dae6c279583e5c5f0fafd8207341cc5a15af.tar.gz sink-7287dae6c279583e5c5f0fafd8207341cc5a15af.zip |
Properly deal with filtered entities in reduced queries.
Filtered entities would still end up in the entities list before.
Diffstat (limited to 'common/datastorequery.cpp')
-rw-r--r-- | common/datastorequery.cpp | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/common/datastorequery.cpp b/common/datastorequery.cpp index 9e61a3d..b77dfc9 100644 --- a/common/datastorequery.cpp +++ b/common/datastorequery.cpp | |||
@@ -267,14 +267,14 @@ public: | |||
267 | for (auto &aggregator : mAggregators) { | 267 | for (auto &aggregator : mAggregators) { |
268 | aggregator.reset(); | 268 | aggregator.reset(); |
269 | } | 269 | } |
270 | 270 | QVector<QByteArray> reducedAndFilteredResults; | |
271 | for (const auto &r : results) { | 271 | for (const auto &r : results) { |
272 | readEntity(r, [&, this](const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation operation) { | 272 | readEntity(r, [&, this](const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation operation) { |
273 | //We need to apply all property filters that we have until the reduction, because the index lookup was unfiltered. | 273 | //We need to apply all property filters that we have until the reduction, because the index lookup was unfiltered. |
274 | if (!matchesFilter(entity)) { | 274 | if (!matchesFilter(entity)) { |
275 | return; | 275 | return; |
276 | } | 276 | } |
277 | 277 | reducedAndFilteredResults << r; | |
278 | Q_ASSERT(operation != Sink::Operation_Removal); | 278 | Q_ASSERT(operation != Sink::Operation_Removal); |
279 | for (auto &aggregator : mAggregators) { | 279 | for (auto &aggregator : mAggregators) { |
280 | if (!aggregator.property.isEmpty()) { | 280 | if (!aggregator.property.isEmpty()) { |
@@ -294,14 +294,18 @@ public: | |||
294 | for (auto &aggregator : mAggregators) { | 294 | for (auto &aggregator : mAggregators) { |
295 | aggregateValues.insert(aggregator.resultProperty, aggregator.result()); | 295 | aggregateValues.insert(aggregator.resultProperty, aggregator.result()); |
296 | } | 296 | } |
297 | return {selectionResult, results, aggregateValues}; | 297 | return {selectionResult, reducedAndFilteredResults, aggregateValues}; |
298 | } | 298 | } |
299 | 299 | ||
300 | bool next(const std::function<void(const ResultSet::Result &)> &callback) Q_DECL_OVERRIDE { | 300 | bool next(const std::function<void(const ResultSet::Result &)> &callback) Q_DECL_OVERRIDE { |
301 | bool foundValue = false; | 301 | bool foundValue = false; |
302 | while(!foundValue && mSource->next([this, callback, &foundValue](const ResultSet::Result &result) { | 302 | while(!foundValue && mSource->next([this, callback, &foundValue](const ResultSet::Result &result) { |
303 | const auto reductionValue = [&] { | 303 | const auto reductionValue = [&] { |
304 | if (result.operation == Sink::Operation_Removal) { | 304 | const auto v = result.entity.getProperty(mReductionProperty); |
305 | //Because we also get Operation_Removal for filtered entities. We use the fact that actually removed entites | ||
306 | //won't have the property to reduce on. | ||
307 | //TODO: Perhaps find a cleaner solutoin than abusing Operation::Removed for filtered properties. | ||
308 | if (v.isNull() && result.operation == Sink::Operation_Removal) { | ||
305 | //For removals we have to read the last revision to get a value, and thus be able to find the correct thread. | 309 | //For removals we have to read the last revision to get a value, and thus be able to find the correct thread. |
306 | QVariant reductionValue; | 310 | QVariant reductionValue; |
307 | readPrevious(result.entity.identifier(), [&] (const ApplicationDomain::ApplicationDomainType &prev) { | 311 | readPrevious(result.entity.identifier(), [&] (const ApplicationDomain::ApplicationDomainType &prev) { |
@@ -309,10 +313,15 @@ public: | |||
309 | }); | 313 | }); |
310 | return reductionValue; | 314 | return reductionValue; |
311 | } else { | 315 | } else { |
312 | return result.entity.getProperty(mReductionProperty); | 316 | return v; |
313 | } | 317 | } |
314 | }(); | 318 | }(); |
315 | const auto &reductionValueBa = getByteArray(reductionValue); | 319 | if (reductionValue.isNull()) { |
320 | //We failed to find a value to reduce on, so ignore this entity. | ||
321 | //Can happen if the entity was already removed and we have no previous revision. | ||
322 | return; | ||
323 | } | ||
324 | const auto reductionValueBa = getByteArray(reductionValue); | ||
316 | if (!mReducedValues.contains(reductionValueBa)) { | 325 | if (!mReducedValues.contains(reductionValueBa)) { |
317 | //Only reduce every value once. | 326 | //Only reduce every value once. |
318 | mReducedValues.insert(reductionValueBa); | 327 | mReducedValues.insert(reductionValueBa); |
@@ -356,7 +365,6 @@ public: | |||
356 | } | 365 | } |
357 | } | 366 | } |
358 | } | 367 | } |
359 | return false; | ||
360 | })) | 368 | })) |
361 | {} | 369 | {} |
362 | return foundValue; | 370 | return foundValue; |