summaryrefslogtreecommitdiffstats
path: root/common/queryrunner.cpp
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2016-02-16 17:43:22 +0100
committerChristian Mollekopf <chrigi_1@fastmail.fm>2016-02-16 17:43:22 +0100
commit529dd17eec62a9702b8837f8f1976dfbf28fdd82 (patch)
tree3fe5581a76b83cd9c4360b67e7dd99ceb8c0eaab /common/queryrunner.cpp
parent8acaae496f9e816c4c1b1126fc6409b6fafe6500 (diff)
downloadsink-529dd17eec62a9702b8837f8f1976dfbf28fdd82.tar.gz
sink-529dd17eec62a9702b8837f8f1976dfbf28fdd82.zip
Prepared sort indexes
Diffstat (limited to 'common/queryrunner.cpp')
-rw-r--r--common/queryrunner.cpp32
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
64private: 64private:
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
213template<class DomainType> 214template<class DomainType>
@@ -234,14 +235,18 @@ void QueryWorker<DomainType>::readEntity(const Sink::Storage::NamedDatabase &db,
234} 235}
235 236
236template<class DomainType> 237template<class DomainType>
237ResultSet QueryWorker<DomainType>::loadInitialResultSet(const Sink::Query &query, Sink::Storage::Transaction &transaction, QSet<QByteArray> &remainingFilters) 238ResultSet 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
379template<class DomainType> 386template<class DomainType>
380qint64 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) 387qint64 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);