diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2016-02-16 17:43:22 +0100 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2016-02-16 17:43:22 +0100 |
commit | 529dd17eec62a9702b8837f8f1976dfbf28fdd82 (patch) | |
tree | 3fe5581a76b83cd9c4360b67e7dd99ceb8c0eaab /common/queryrunner.cpp | |
parent | 8acaae496f9e816c4c1b1126fc6409b6fafe6500 (diff) | |
download | sink-529dd17eec62a9702b8837f8f1976dfbf28fdd82.tar.gz sink-529dd17eec62a9702b8837f8f1976dfbf28fdd82.zip |
Prepared sort indexes
Diffstat (limited to 'common/queryrunner.cpp')
-rw-r--r-- | common/queryrunner.cpp | 32 |
1 files changed, 20 insertions, 12 deletions
diff --git a/common/queryrunner.cpp b/common/queryrunner.cpp index 2d188ae..299b987 100644 --- a/common/queryrunner.cpp +++ b/common/queryrunner.cpp | |||
@@ -54,12 +54,12 @@ private: | |||
54 | 54 | ||
55 | void readEntity(const Sink::Storage::NamedDatabase &db, const QByteArray &key, const std::function<void(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &, Sink::Operation)> &resultCallback); | 55 | void readEntity(const Sink::Storage::NamedDatabase &db, const QByteArray &key, const std::function<void(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &, Sink::Operation)> &resultCallback); |
56 | 56 | ||
57 | ResultSet loadInitialResultSet(const Sink::Query &query, Sink::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters); | 57 | ResultSet loadInitialResultSet(const Sink::Query &query, Sink::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters, QByteArray &remainingSorting); |
58 | ResultSet loadIncrementalResultSet(qint64 baseRevision, const Sink::Query &query, Sink::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters); | 58 | ResultSet loadIncrementalResultSet(qint64 baseRevision, const Sink::Query &query, Sink::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters); |
59 | 59 | ||
60 | ResultSet filterAndSortSet(ResultSet &resultSet, const std::function<bool(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject)> &filter, const Sink::Storage::NamedDatabase &db, bool initialQuery, const QByteArray &sortProperty); | 60 | ResultSet filterAndSortSet(ResultSet &resultSet, const std::function<bool(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject)> &filter, const Sink::Storage::NamedDatabase &db, bool initialQuery, const QByteArray &sortProperty); |
61 | std::function<bool(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject)> getFilter(const QSet<QByteArray> remainingFilters, const Sink::Query &query); | 61 | std::function<bool(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &domainObject)> getFilter(const QSet<QByteArray> remainingFilters, const Sink::Query &query); |
62 | qint64 load(const Sink::Query &query, const std::function<ResultSet(Sink::Storage::Transaction &, QSet<QByteArray> &)> &baseSetRetriever, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, bool initialQuery, int offset, int batchSize); | 62 | qint64 load(const Sink::Query &query, const std::function<ResultSet(Sink::Storage::Transaction &, QSet<QByteArray> &, QByteArray &)> &baseSetRetriever, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, bool initialQuery, int offset, int batchSize); |
63 | 63 | ||
64 | private: | 64 | private: |
65 | QueryRunnerBase::ResultTransformation mResultTransformation; | 65 | QueryRunnerBase::ResultTransformation mResultTransformation; |
@@ -154,6 +154,7 @@ static inline ResultSet fullScan(const Sink::Storage::Transaction &transaction, | |||
154 | Warning() << "Error during query: " << error.message; | 154 | Warning() << "Error during query: " << error.message; |
155 | }); | 155 | }); |
156 | 156 | ||
157 | Trace() << "Full scan retrieved " << keys.size() << " results."; | ||
157 | return ResultSet(keys); | 158 | return ResultSet(keys); |
158 | } | 159 | } |
159 | 160 | ||
@@ -207,7 +208,7 @@ void QueryWorker<DomainType>::replaySet(ResultSet &resultSet, Sink::ResultProvid | |||
207 | } | 208 | } |
208 | return true; | 209 | return true; |
209 | })){}; | 210 | })){}; |
210 | Trace() << "Replayed " << counter << " results"; | 211 | Trace() << "Replayed " << counter << " results." << "Limit " << batchSize; |
211 | } | 212 | } |
212 | 213 | ||
213 | template<class DomainType> | 214 | template<class DomainType> |
@@ -234,14 +235,18 @@ void QueryWorker<DomainType>::readEntity(const Sink::Storage::NamedDatabase &db, | |||
234 | } | 235 | } |
235 | 236 | ||
236 | template<class DomainType> | 237 | template<class DomainType> |
237 | ResultSet QueryWorker<DomainType>::loadInitialResultSet(const Sink::Query &query, Sink::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters) | 238 | ResultSet QueryWorker<DomainType>::loadInitialResultSet(const Sink::Query &query, Sink::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters, QByteArray &remainingSorting) |
238 | { | 239 | { |
239 | if (!query.ids.isEmpty()) { | 240 | if (!query.ids.isEmpty()) { |
240 | return ResultSet(query.ids.toVector()); | 241 | return ResultSet(query.ids.toVector()); |
241 | } | 242 | } |
242 | QSet<QByteArray> appliedFilters; | 243 | QSet<QByteArray> appliedFilters; |
243 | auto resultSet = Sink::ApplicationDomain::TypeImplementation<DomainType>::queryIndexes(query, mResourceInstanceIdentifier, appliedFilters, transaction); | 244 | QByteArray appliedSorting; |
245 | auto resultSet = Sink::ApplicationDomain::TypeImplementation<DomainType>::queryIndexes(query, mResourceInstanceIdentifier, appliedFilters, appliedSorting, transaction); | ||
244 | remainingFilters = query.propertyFilter.keys().toSet() - appliedFilters; | 246 | remainingFilters = query.propertyFilter.keys().toSet() - appliedFilters; |
247 | if (appliedSorting.isEmpty()) { | ||
248 | remainingSorting = query.sortProperty; | ||
249 | } | ||
245 | 250 | ||
246 | //We do a full scan if there were no indexes available to create the initial set. | 251 | //We do a full scan if there were no indexes available to create the initial set. |
247 | if (appliedFilters.isEmpty()) { | 252 | if (appliedFilters.isEmpty()) { |
@@ -284,6 +289,7 @@ ResultSet QueryWorker<DomainType>::filterAndSortSet(ResultSet &resultSet, const | |||
284 | { | 289 | { |
285 | const bool sortingRequired = !sortProperty.isEmpty(); | 290 | const bool sortingRequired = !sortProperty.isEmpty(); |
286 | if (initialQuery && sortingRequired) { | 291 | if (initialQuery && sortingRequired) { |
292 | Trace() << "Sorting the resultset in memory according to property: " << sortProperty; | ||
287 | //Sort the complete set by reading the sort property and filling into a sorted map | 293 | //Sort the complete set by reading the sort property and filling into a sorted map |
288 | auto sortedMap = QSharedPointer<QMap<QByteArray, QByteArray>>::create(); | 294 | auto sortedMap = QSharedPointer<QMap<QByteArray, QByteArray>>::create(); |
289 | while (resultSet.next()) { | 295 | while (resultSet.next()) { |
@@ -293,7 +299,7 @@ ResultSet QueryWorker<DomainType>::filterAndSortSet(ResultSet &resultSet, const | |||
293 | if ((operation != Sink::Operation_Removal) && filter(domainObject)) { | 299 | if ((operation != Sink::Operation_Removal) && filter(domainObject)) { |
294 | if (!sortProperty.isEmpty()) { | 300 | if (!sortProperty.isEmpty()) { |
295 | const auto sortValue = domainObject->getProperty(sortProperty); | 301 | const auto sortValue = domainObject->getProperty(sortProperty); |
296 | if (sortValue.canConvert<QDateTime>()) { | 302 | if (sortValue.type() == QVariant::DateTime) { |
297 | sortedMap->insert(QByteArray::number(std::numeric_limits<unsigned int>::max() - sortValue.toDateTime().toTime_t()), domainObject->identifier()); | 303 | sortedMap->insert(QByteArray::number(std::numeric_limits<unsigned int>::max() - sortValue.toDateTime().toTime_t()), domainObject->identifier()); |
298 | } else { | 304 | } else { |
299 | sortedMap->insert(sortValue.toString().toLatin1(), domainObject->identifier()); | 305 | sortedMap->insert(sortValue.toString().toLatin1(), domainObject->identifier()); |
@@ -305,6 +311,7 @@ ResultSet QueryWorker<DomainType>::filterAndSortSet(ResultSet &resultSet, const | |||
305 | }); | 311 | }); |
306 | } | 312 | } |
307 | 313 | ||
314 | Trace() << "Sorted " << sortedMap->size() << " values."; | ||
308 | auto iterator = QSharedPointer<QMapIterator<QByteArray, QByteArray> >::create(*sortedMap); | 315 | auto iterator = QSharedPointer<QMapIterator<QByteArray, QByteArray> >::create(*sortedMap); |
309 | ResultSet::ValueGenerator generator = [this, iterator, sortedMap, &db, filter, initialQuery](std::function<void(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &, Sink::Operation)> callback) -> bool { | 316 | ResultSet::ValueGenerator generator = [this, iterator, sortedMap, &db, filter, initialQuery](std::function<void(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &, Sink::Operation)> callback) -> bool { |
310 | if (iterator->hasNext()) { | 317 | if (iterator->hasNext()) { |
@@ -377,7 +384,7 @@ std::function<bool(const Sink::ApplicationDomain::ApplicationDomainType::Ptr &do | |||
377 | } | 384 | } |
378 | 385 | ||
379 | template<class DomainType> | 386 | template<class DomainType> |
380 | qint64 QueryWorker<DomainType>::load(const Sink::Query &query, const std::function<ResultSet(Sink::Storage::Transaction &, QSet<QByteArray> &)> &baseSetRetriever, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, bool initialQuery, int offset, int batchSize) | 387 | qint64 QueryWorker<DomainType>::load(const Sink::Query &query, const std::function<ResultSet(Sink::Storage::Transaction &, QSet<QByteArray> &, QByteArray &)> &baseSetRetriever, Sink::ResultProviderInterface<typename DomainType::Ptr> &resultProvider, bool initialQuery, int offset, int batchSize) |
381 | { | 388 | { |
382 | QTime time; | 389 | QTime time; |
383 | time.start(); | 390 | time.start(); |
@@ -390,9 +397,10 @@ qint64 QueryWorker<DomainType>::load(const Sink::Query &query, const std::functi | |||
390 | auto db = Storage::mainDatabase(transaction, mBufferType); | 397 | auto db = Storage::mainDatabase(transaction, mBufferType); |
391 | 398 | ||
392 | QSet<QByteArray> remainingFilters; | 399 | QSet<QByteArray> remainingFilters; |
393 | auto resultSet = baseSetRetriever(transaction, remainingFilters); | 400 | QByteArray remainingSorting; |
401 | auto resultSet = baseSetRetriever(transaction, remainingFilters, remainingSorting); | ||
394 | Trace() << "Base set retrieved. " << time.elapsed(); | 402 | Trace() << "Base set retrieved. " << time.elapsed(); |
395 | auto filteredSet = filterAndSortSet(resultSet, getFilter(remainingFilters, query), db, initialQuery, query.sortProperty); | 403 | auto filteredSet = filterAndSortSet(resultSet, getFilter(remainingFilters, query), db, initialQuery, remainingSorting); |
396 | Trace() << "Filtered set retrieved. " << time.elapsed(); | 404 | Trace() << "Filtered set retrieved. " << time.elapsed(); |
397 | replaySet(filteredSet, resultProvider, query.requestedProperties, offset, batchSize); | 405 | replaySet(filteredSet, resultProvider, query.requestedProperties, offset, batchSize); |
398 | Trace() << "Filtered set replayed. " << time.elapsed(); | 406 | Trace() << "Filtered set replayed. " << time.elapsed(); |
@@ -408,7 +416,7 @@ qint64 QueryWorker<DomainType>::executeIncrementalQuery(const Sink::Query &query | |||
408 | 416 | ||
409 | const qint64 baseRevision = resultProvider.revision() + 1; | 417 | const qint64 baseRevision = resultProvider.revision() + 1; |
410 | Trace() << "Running incremental query " << baseRevision; | 418 | Trace() << "Running incremental query " << baseRevision; |
411 | auto revision = load(query, [&](Sink::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters) -> ResultSet { | 419 | auto revision = load(query, [&](Sink::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters, QByteArray &remainingSorting) -> ResultSet { |
412 | return loadIncrementalResultSet(baseRevision, query, transaction, remainingFilters); | 420 | return loadIncrementalResultSet(baseRevision, query, transaction, remainingFilters); |
413 | }, resultProvider, false, 0, 0); | 421 | }, resultProvider, false, 0, 0); |
414 | Trace() << "Incremental query took: " << time.elapsed() << " ms"; | 422 | Trace() << "Incremental query took: " << time.elapsed() << " ms"; |
@@ -431,8 +439,8 @@ qint64 QueryWorker<DomainType>::executeInitialQuery(const Sink::Query &query, co | |||
431 | modifiedQuery.propertyFilter.insert(query.parentProperty, QVariant()); | 439 | modifiedQuery.propertyFilter.insert(query.parentProperty, QVariant()); |
432 | } | 440 | } |
433 | } | 441 | } |
434 | auto revision = load(modifiedQuery, [&](Sink::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters) -> ResultSet { | 442 | auto revision = load(modifiedQuery, [&](Sink::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters, QByteArray &remainingSorting) -> ResultSet { |
435 | return loadInitialResultSet(modifiedQuery, transaction, remainingFilters); | 443 | return loadInitialResultSet(modifiedQuery, transaction, remainingFilters, remainingSorting); |
436 | }, resultProvider, true, offset, batchsize); | 444 | }, resultProvider, true, offset, batchsize); |
437 | Trace() << "Initial query took: " << time.elapsed() << " ms"; | 445 | Trace() << "Initial query took: " << time.elapsed() << " ms"; |
438 | resultProvider.initialResultSetComplete(parent); | 446 | resultProvider.initialResultSetComplete(parent); |