summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRémi Nicole <nicole@kolabsystems.com>2018-07-27 13:37:32 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2018-07-27 13:47:54 +0200
commit0a9b39a1f58c1f5b1a424acbe369db520a12df42 (patch)
tree4c64e5680150f50088bf114cbab39f79f781d242
parent620c4f551d3de830a516475ad02965695cb25945 (diff)
downloadsink-0a9b39a1f58c1f5b1a424acbe369db520a12df42.tar.gz
sink-0a9b39a1f58c1f5b1a424acbe369db520a12df42.zip
Use Key API in DataStoreQuery
Reviewers: cmollekopf Reviewed By: cmollekopf Tags: #sink Differential Revision: https://phabricator.kde.org/D14099
-rw-r--r--common/datastorequery.cpp66
-rw-r--r--common/datastorequery.h20
-rw-r--r--common/storage/entitystore.cpp62
-rw-r--r--common/storage/entitystore.h13
-rw-r--r--common/storage/key.cpp47
-rw-r--r--common/storage/key.h17
-rw-r--r--common/typeindex.cpp10
-rw-r--r--common/typeindex.h2
8 files changed, 158 insertions, 79 deletions
diff --git a/common/datastorequery.cpp b/common/datastorequery.cpp
index aca4bb1..aa315c6 100644
--- a/common/datastorequery.cpp
+++ b/common/datastorequery.cpp
@@ -41,17 +41,20 @@ class Source : public FilterBase {
41 public: 41 public:
42 typedef QSharedPointer<Source> Ptr; 42 typedef QSharedPointer<Source> Ptr;
43 43
44 QVector<QByteArray> mIds; 44 QVector<Identifier> mIds;
45 QVector<QByteArray>::ConstIterator mIt; 45 QVector<Identifier>::ConstIterator mIt;
46 QVector<QByteArray> mIncrementalIds; 46 QVector<Identifier> mIncrementalIds;
47 QVector<QByteArray>::ConstIterator mIncrementalIt; 47 QVector<Identifier>::ConstIterator mIncrementalIt;
48 48
49 Source (const QVector<QByteArray> &ids, DataStoreQuery *store) 49 Source (const QVector<QByteArray> &ids, DataStoreQuery *store)
50 : FilterBase(store), 50 : FilterBase(store),
51 mIds(ids), 51 mIds()
52 mIt(mIds.constBegin())
53 { 52 {
54 53 mIds.reserve(ids.size());
54 for (const auto &id : ids) {
55 mIds.append(Identifier::fromDisplayByteArray(id));
56 }
57 mIt = mIds.constBegin();
55 } 58 }
56 59
57 virtual ~Source(){} 60 virtual ~Source(){}
@@ -63,9 +66,13 @@ class Source : public FilterBase {
63 } 66 }
64 }; 67 };
65 68
66 void add(const QVector<QByteArray> &ids) 69 void add(const QVector<Key> &keys)
67 { 70 {
68 mIncrementalIds = ids; 71 mIncrementalIds.clear();
72 mIncrementalIds.reserve(keys.size());
73 for (const auto &key : keys) {
74 mIncrementalIds.append(key.identifier());
75 }
69 mIncrementalIt = mIncrementalIds.constBegin(); 76 mIncrementalIt = mIncrementalIds.constBegin();
70 } 77 }
71 78
@@ -222,7 +229,7 @@ public:
222 229
223 QSet<QByteArray> mReducedValues; 230 QSet<QByteArray> mReducedValues;
224 QSet<QByteArray> mIncrementallyReducedValues; 231 QSet<QByteArray> mIncrementallyReducedValues;
225 QHash<QByteArray, QByteArray> mSelectedValues; 232 QHash<QByteArray, Identifier> mSelectedValues;
226 QByteArray mReductionProperty; 233 QByteArray mReductionProperty;
227 QByteArray mSelectionProperty; 234 QByteArray mSelectionProperty;
228 QueryBase::Reduce::Selector::Comparator mSelectionComparator; 235 QueryBase::Reduce::Selector::Comparator mSelectionComparator;
@@ -263,7 +270,7 @@ public:
263 } 270 }
264 271
265 struct ReductionResult { 272 struct ReductionResult {
266 QByteArray selection; 273 Identifier selection;
267 QVector<QByteArray> aggregateIds; 274 QVector<QByteArray> aggregateIds;
268 QMap<QByteArray, QVariant> aggregateValues; 275 QMap<QByteArray, QVariant> aggregateValues;
269 }; 276 };
@@ -272,7 +279,7 @@ public:
272 { 279 {
273 QMap<QByteArray, QVariant> aggregateValues; 280 QMap<QByteArray, QVariant> aggregateValues;
274 QVariant selectionResultValue; 281 QVariant selectionResultValue;
275 QByteArray selectionResult; 282 Identifier selectionResult;
276 const auto results = indexLookup(mReductionProperty, reductionValue); 283 const auto results = indexLookup(mReductionProperty, reductionValue);
277 for (auto &aggregator : mAggregators) { 284 for (auto &aggregator : mAggregators) {
278 aggregator.reset(); 285 aggregator.reset();
@@ -284,7 +291,7 @@ public:
284 if (!matchesFilter(entity)) { 291 if (!matchesFilter(entity)) {
285 return; 292 return;
286 } 293 }
287 reducedAndFilteredResults << r; 294 reducedAndFilteredResults << r.toDisplayByteArray();
288 Q_ASSERT(operation != Sink::Operation_Removal); 295 Q_ASSERT(operation != Sink::Operation_Removal);
289 for (auto &aggregator : mAggregators) { 296 for (auto &aggregator : mAggregators) {
290 if (!aggregator.property.isEmpty()) { 297 if (!aggregator.property.isEmpty()) {
@@ -296,7 +303,7 @@ public:
296 auto selectionValue = entity.getProperty(mSelectionProperty); 303 auto selectionValue = entity.getProperty(mSelectionProperty);
297 if (!selectionResultValue.isValid() || compare(selectionValue, selectionResultValue, mSelectionComparator)) { 304 if (!selectionResultValue.isValid() || compare(selectionValue, selectionResultValue, mSelectionComparator)) {
298 selectionResultValue = selectionValue; 305 selectionResultValue = selectionValue;
299 selectionResult = entity.identifier(); 306 selectionResult = Identifier::fromDisplayByteArray(entity.identifier());
300 } 307 }
301 }); 308 });
302 } 309 }
@@ -318,7 +325,8 @@ public:
318 if (v.isNull() && result.operation == Sink::Operation_Removal) { 325 if (v.isNull() && result.operation == Sink::Operation_Removal) {
319 //For removals we have to read the last revision to get a value, and thus be able to find the correct thread. 326 //For removals we have to read the last revision to get a value, and thus be able to find the correct thread.
320 QVariant reductionValue; 327 QVariant reductionValue;
321 readPrevious(result.entity.identifier(), [&] (const ApplicationDomain::ApplicationDomainType &prev) { 328 const auto id = Identifier::fromDisplayByteArray(result.entity.identifier());
329 readPrevious(id, [&] (const ApplicationDomain::ApplicationDomainType &prev) {
322 Q_ASSERT(result.entity.identifier() == prev.identifier()); 330 Q_ASSERT(result.entity.identifier() == prev.identifier());
323 reductionValue = prev.getProperty(mReductionProperty); 331 reductionValue = prev.getProperty(mReductionProperty);
324 }); 332 });
@@ -341,7 +349,7 @@ public:
341 auto reductionResult = reduceOnValue(reductionValue); 349 auto reductionResult = reduceOnValue(reductionValue);
342 350
343 //This can happen if we get a removal message from a filtered entity and all entites of the reduction are filtered. 351 //This can happen if we get a removal message from a filtered entity and all entites of the reduction are filtered.
344 if (reductionResult.selection.isEmpty()) { 352 if (reductionResult.selection.isNull()) {
345 return; 353 return;
346 } 354 }
347 mSelectedValues.insert(reductionValueBa, reductionResult.selection); 355 mSelectedValues.insert(reductionValueBa, reductionResult.selection);
@@ -362,27 +370,27 @@ public:
362 //If mSelectedValues did not contain the value, oldSelectionResult will be empty.(Happens if entites have been filtered) 370 //If mSelectedValues did not contain the value, oldSelectionResult will be empty.(Happens if entites have been filtered)
363 auto oldSelectionResult = mSelectedValues.take(reductionValueBa); 371 auto oldSelectionResult = mSelectedValues.take(reductionValueBa);
364 SinkTraceCtx(mDatastore->mLogCtx) << "Old selection result: " << oldSelectionResult << " New selection result: " << selectionResult.selection; 372 SinkTraceCtx(mDatastore->mLogCtx) << "Old selection result: " << oldSelectionResult << " New selection result: " << selectionResult.selection;
365 if (selectionResult.selection.isEmpty() && oldSelectionResult.isEmpty()) { 373 if (selectionResult.selection.isNull() && oldSelectionResult.isNull()) {
366 //Nothing to do, the item was filtered before, and still is. 374 //Nothing to do, the item was filtered before, and still is.
367 } else if (oldSelectionResult == selectionResult.selection) { 375 } else if (oldSelectionResult == selectionResult.selection) {
368 mSelectedValues.insert(reductionValueBa, selectionResult.selection); 376 mSelectedValues.insert(reductionValueBa, selectionResult.selection);
369 Q_ASSERT(!selectionResult.selection.isEmpty()); 377 Q_ASSERT(!selectionResult.selection.isNull());
370 readEntity(selectionResult.selection, [&](const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation) { 378 readEntity(selectionResult.selection, [&](const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation) {
371 callback({entity, Sink::Operation_Modification, selectionResult.aggregateValues, selectionResult.aggregateIds}); 379 callback({entity, Sink::Operation_Modification, selectionResult.aggregateValues, selectionResult.aggregateIds});
372 }); 380 });
373 } else { 381 } else {
374 //remove old result 382 //remove old result
375 if (!oldSelectionResult.isEmpty()) { 383 if (!oldSelectionResult.isNull()) {
376 readEntity(oldSelectionResult, [&](const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation) { 384 readEntity(oldSelectionResult, [&](const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation) {
377 callback({entity, Sink::Operation_Removal}); 385 callback({entity, Sink::Operation_Removal});
378 }); 386 });
379 } 387 }
380 388
381 //If the last item has been removed, then there's nothing to add 389 //If the last item has been removed, then there's nothing to add
382 if (!selectionResult.selection.isEmpty()) { 390 if (!selectionResult.selection.isNull()) {
383 //add new result 391 //add new result
384 mSelectedValues.insert(reductionValueBa, selectionResult.selection); 392 mSelectedValues.insert(reductionValueBa, selectionResult.selection);
385 Q_ASSERT(!selectionResult.selection.isEmpty()); 393 Q_ASSERT(!selectionResult.selection.isNull());
386 readEntity(selectionResult.selection, [&](const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation) { 394 readEntity(selectionResult.selection, [&](const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation) {
387 callback({entity, Sink::Operation_Creation, selectionResult.aggregateValues, selectionResult.aggregateIds}); 395 callback({entity, Sink::Operation_Creation, selectionResult.aggregateValues, selectionResult.aggregateIds});
388 }); 396 });
@@ -477,17 +485,17 @@ DataStoreQuery::State::Ptr DataStoreQuery::getState()
477 return state; 485 return state;
478} 486}
479 487
480void DataStoreQuery::readEntity(const QByteArray &key, const BufferCallback &resultCallback) 488void DataStoreQuery::readEntity(const Identifier &id, const BufferCallback &resultCallback)
481{ 489{
482 mStore.readLatest(mType, key, resultCallback); 490 mStore.readLatest(mType, id, resultCallback);
483} 491}
484 492
485void DataStoreQuery::readPrevious(const QByteArray &key, const std::function<void (const ApplicationDomain::ApplicationDomainType &)> &callback) 493void DataStoreQuery::readPrevious(const Identifier &id, const std::function<void (const ApplicationDomain::ApplicationDomainType &)> &callback)
486{ 494{
487 mStore.readPrevious(mType, key, mStore.maxRevision(), callback); 495 mStore.readPrevious(mType, id, mStore.maxRevision(), callback);
488} 496}
489 497
490QVector<QByteArray> DataStoreQuery::indexLookup(const QByteArray &property, const QVariant &value) 498QVector<Identifier> DataStoreQuery::indexLookup(const QByteArray &property, const QVariant &value)
491{ 499{
492 return mStore.indexLookup(mType, property, value); 500 return mStore.indexLookup(mType, property, value);
493} 501}
@@ -654,10 +662,10 @@ void DataStoreQuery::setupQuery(const Sink::QueryBase &query_)
654 mCollector = Collector::Ptr::create(baseSet, this); 662 mCollector = Collector::Ptr::create(baseSet, this);
655} 663}
656 664
657QVector<QByteArray> DataStoreQuery::loadIncrementalResultSet(qint64 baseRevision) 665QVector<Key> DataStoreQuery::loadIncrementalResultSet(qint64 baseRevision)
658{ 666{
659 QVector<QByteArray> changedKeys; 667 QVector<Key> changedKeys;
660 mStore.readRevisions(baseRevision, mType, [&](const QByteArray &key) { 668 mStore.readRevisions(baseRevision, mType, [&](const Key &key) {
661 changedKeys << key; 669 changedKeys << key;
662 }); 670 });
663 return changedKeys; 671 return changedKeys;
diff --git a/common/datastorequery.h b/common/datastorequery.h
index 2311585..a224e64 100644
--- a/common/datastorequery.h
+++ b/common/datastorequery.h
@@ -22,7 +22,7 @@
22#include "resultset.h" 22#include "resultset.h"
23#include "log.h" 23#include "log.h"
24#include "storage/entitystore.h" 24#include "storage/entitystore.h"
25 25#include "storage/key.h"
26 26
27class Source; 27class Source;
28class Bloom; 28class Bloom;
@@ -59,13 +59,13 @@ private:
59 typedef std::function<bool(const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation)> FilterFunction; 59 typedef std::function<bool(const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation)> FilterFunction;
60 typedef std::function<void(const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation)> BufferCallback; 60 typedef std::function<void(const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation)> BufferCallback;
61 61
62 QVector<QByteArray> indexLookup(const QByteArray &property, const QVariant &value); 62 QVector<Sink::Storage::Identifier> indexLookup(const QByteArray &property, const QVariant &value);
63 63
64 void readEntity(const QByteArray &key, const BufferCallback &resultCallback); 64 void readEntity(const Sink::Storage::Identifier &id, const BufferCallback &resultCallback);
65 void readPrevious(const QByteArray &key, const std::function<void (const Sink::ApplicationDomain::ApplicationDomainType &)> &callback); 65 void readPrevious(const Sink::Storage::Identifier &id, const std::function<void (const Sink::ApplicationDomain::ApplicationDomainType &)> &callback);
66 66
67 ResultSet createFilteredSet(ResultSet &resultSet, const FilterFunction &); 67 ResultSet createFilteredSet(ResultSet &resultSet, const FilterFunction &);
68 QVector<QByteArray> loadIncrementalResultSet(qint64 baseRevision); 68 QVector<Sink::Storage::Key> loadIncrementalResultSet(qint64 baseRevision);
69 69
70 void setupQuery(const Sink::QueryBase &query_); 70 void setupQuery(const Sink::QueryBase &query_);
71 QByteArrayList executeSubquery(const Sink::QueryBase &subquery); 71 QByteArrayList executeSubquery(const Sink::QueryBase &subquery);
@@ -96,22 +96,22 @@ public:
96 96
97 virtual ~FilterBase(){} 97 virtual ~FilterBase(){}
98 98
99 void readEntity(const QByteArray &key, const std::function<void(const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation)> &callback) 99 void readEntity(const Sink::Storage::Identifier &id, const std::function<void(const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Operation)> &callback)
100 { 100 {
101 Q_ASSERT(mDatastore); 101 Q_ASSERT(mDatastore);
102 mDatastore->readEntity(key, callback); 102 mDatastore->readEntity(id, callback);
103 } 103 }
104 104
105 QVector<QByteArray> indexLookup(const QByteArray &property, const QVariant &value) 105 QVector<Sink::Storage::Identifier> indexLookup(const QByteArray &property, const QVariant &value)
106 { 106 {
107 Q_ASSERT(mDatastore); 107 Q_ASSERT(mDatastore);
108 return mDatastore->indexLookup(property, value); 108 return mDatastore->indexLookup(property, value);
109 } 109 }
110 110
111 void readPrevious(const QByteArray &key, const std::function<void (const Sink::ApplicationDomain::ApplicationDomainType &)> &callback) 111 void readPrevious(const Sink::Storage::Identifier &id, const std::function<void (const Sink::ApplicationDomain::ApplicationDomainType &)> &callback)
112 { 112 {
113 Q_ASSERT(mDatastore); 113 Q_ASSERT(mDatastore);
114 mDatastore->readPrevious(key, callback); 114 mDatastore->readPrevious(id, callback);
115 } 115 }
116 116
117 virtual void skip() { mSource->skip(); } 117 virtual void skip() { mSource->skip(); }
diff --git a/common/storage/entitystore.cpp b/common/storage/entitystore.cpp
index a1f6108..71690fe 100644
--- a/common/storage/entitystore.cpp
+++ b/common/storage/entitystore.cpp
@@ -461,11 +461,11 @@ QVector<QByteArray> EntityStore::indexLookup(const QByteArray &type, const Query
461 return d->typeIndex(type).query(query, appliedFilters, appliedSorting, d->getTransaction(), d->resourceContext.instanceId()); 461 return d->typeIndex(type).query(query, appliedFilters, appliedSorting, d->getTransaction(), d->resourceContext.instanceId());
462} 462}
463 463
464QVector<QByteArray> EntityStore::indexLookup(const QByteArray &type, const QByteArray &property, const QVariant &value) 464QVector<Identifier> EntityStore::indexLookup(const QByteArray &type, const QByteArray &property, const QVariant &value)
465{ 465{
466 if (!d->exists()) { 466 if (!d->exists()) {
467 SinkTraceCtx(d->logCtx) << "Database is not existing: " << type; 467 SinkTraceCtx(d->logCtx) << "Database is not existing: " << type;
468 return QVector<QByteArray>(); 468 return {};
469 } 469 }
470 return d->typeIndex(type).lookup(property, value, d->getTransaction()); 470 return d->typeIndex(type).lookup(property, value, d->getTransaction());
471} 471}
@@ -476,9 +476,9 @@ void EntityStore::indexLookup(const QByteArray &type, const QByteArray &property
476 SinkTraceCtx(d->logCtx) << "Database is not existing: " << type; 476 SinkTraceCtx(d->logCtx) << "Database is not existing: " << type;
477 return; 477 return;
478 } 478 }
479 auto list = d->typeIndex(type).lookup(property, value, d->getTransaction()); 479 auto list = indexLookup(type, property, value);
480 for (const auto &uid : list) { 480 for (const auto &id : list) {
481 callback(uid); 481 callback(id.toDisplayByteArray());
482 } 482 }
483 /* Index index(type + ".index." + property, d->transaction); */ 483 /* Index index(type + ".index." + property, d->transaction); */
484 /* index.lookup(value, [&](const QByteArray &sinkId) { */ 484 /* index.lookup(value, [&](const QByteArray &sinkId) { */
@@ -489,29 +489,25 @@ void EntityStore::indexLookup(const QByteArray &type, const QByteArray &property
489 /* }); */ 489 /* }); */
490} 490}
491 491
492void EntityStore::readLatest(const QByteArray &type, const QByteArray &key, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback) 492void EntityStore::readLatest(const QByteArray &type, const Identifier &id, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback)
493{ 493{
494 Q_ASSERT(d); 494 Q_ASSERT(d);
495 Q_ASSERT(!key.isEmpty()); 495 const auto internalKey = id.toInternalByteArray();
496 // TODO: we shouldn't pass whole keys to this function
497 // check the testSingle test from querytest
498 const auto internalKey = [&key]() {
499 if(key.size() == Identifier::DISPLAY_REPR_SIZE) {
500 return Identifier::fromDisplayByteArray(key).toInternalByteArray();
501 } else {
502 return Key::fromDisplayByteArray(key).toInternalByteArray();
503 }
504 }();
505 auto db = DataStore::mainDatabase(d->getTransaction(), type); 496 auto db = DataStore::mainDatabase(d->getTransaction(), type);
506 db.findLatest(internalKey, 497 db.findLatest(internalKey,
507 [=](const QByteArray &key, const QByteArray &value) { 498 [=](const QByteArray &key, const QByteArray &value) {
508 const auto uid = Sink::Storage::Key::fromInternalByteArray(key).identifier().toDisplayByteArray(); 499 const auto uid = Sink::Storage::Key::fromInternalByteArray(key).identifier().toDisplayByteArray();
509 callback(uid, Sink::EntityBuffer(value.data(), value.size())); 500 callback(uid, Sink::EntityBuffer(value.data(), value.size()));
510 }, 501 },
511 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Error during readLatest query: " << error.message << key; }); 502 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Error during readLatest query: " << error.message << id; });
512} 503}
513 504
514void EntityStore::readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const ApplicationDomainType &)> callback) 505void EntityStore::readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback)
506{
507 readLatest(type, Identifier::fromDisplayByteArray(uid), callback);
508}
509
510void EntityStore::readLatest(const QByteArray &type, const Identifier &uid, const std::function<void(const ApplicationDomainType &)> callback)
515{ 511{
516 readLatest(type, uid, [&](const QByteArray &uid, const EntityBuffer &buffer) { 512 readLatest(type, uid, [&](const QByteArray &uid, const EntityBuffer &buffer) {
517 //TODO cache max revision for the duration of the transaction. 513 //TODO cache max revision for the duration of the transaction.
@@ -519,7 +515,12 @@ void EntityStore::readLatest(const QByteArray &type, const QByteArray &uid, cons
519 }); 515 });
520} 516}
521 517
522void EntityStore::readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const ApplicationDomainType &, Sink::Operation)> callback) 518void EntityStore::readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const ApplicationDomainType &)> callback)
519{
520 readLatest(type, Identifier::fromDisplayByteArray(uid), callback);
521}
522
523void EntityStore::readLatest(const QByteArray &type, const Identifier &uid, const std::function<void(const ApplicationDomainType &, Sink::Operation)> callback)
523{ 524{
524 readLatest(type, uid, [&](const QByteArray &uid, const EntityBuffer &buffer) { 525 readLatest(type, uid, [&](const QByteArray &uid, const EntityBuffer &buffer) {
525 //TODO cache max revision for the duration of the transaction. 526 //TODO cache max revision for the duration of the transaction.
@@ -527,6 +528,11 @@ void EntityStore::readLatest(const QByteArray &type, const QByteArray &uid, cons
527 }); 528 });
528} 529}
529 530
531void EntityStore::readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const ApplicationDomainType &, Sink::Operation)> callback)
532{
533 readLatest(type, Identifier::fromDisplayByteArray(uid), callback);
534}
535
530ApplicationDomain::ApplicationDomainType EntityStore::readLatest(const QByteArray &type, const QByteArray &uid) 536ApplicationDomain::ApplicationDomainType EntityStore::readLatest(const QByteArray &type, const QByteArray &uid)
531{ 537{
532 ApplicationDomainType dt; 538 ApplicationDomainType dt;
@@ -573,7 +579,7 @@ void EntityStore::readAll(const QByteArray &type, const std::function<void(const
573 }); 579 });
574} 580}
575 581
576void EntityStore::readRevisions(qint64 baseRevision, const QByteArray &expectedType, const std::function<void(const QByteArray &key)> &callback) 582void EntityStore::readRevisions(qint64 baseRevision, const QByteArray &expectedType, const std::function<void(const Key &key)> &callback)
577{ 583{
578 qint64 revisionCounter = baseRevision; 584 qint64 revisionCounter = baseRevision;
579 const qint64 topRevision = DataStore::maxRevision(d->getTransaction()); 585 const qint64 topRevision = DataStore::maxRevision(d->getTransaction());
@@ -592,15 +598,15 @@ void EntityStore::readRevisions(qint64 baseRevision, const QByteArray &expectedT
592 const auto key = Key(Identifier::fromDisplayByteArray(uid), revisionCounter); 598 const auto key = Key(Identifier::fromDisplayByteArray(uid), revisionCounter);
593 599
594 revisionCounter++; 600 revisionCounter++;
595 callback(key.toDisplayByteArray()); 601 callback(key);
596 } 602 }
597} 603}
598 604
599void EntityStore::readPrevious(const QByteArray &type, const QByteArray &uid, qint64 revision, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback) 605void EntityStore::readPrevious(const QByteArray &type, const Identifier &id, qint64 revision, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback)
600{ 606{
601 auto db = DataStore::mainDatabase(d->getTransaction(), type); 607 auto db = DataStore::mainDatabase(d->getTransaction(), type);
602 qint64 latestRevision = 0; 608 qint64 latestRevision = 0;
603 const auto internalUid = Identifier::fromDisplayByteArray(uid).toInternalByteArray(); 609 const auto internalUid = id.toInternalByteArray();
604 db.scan(internalUid, 610 db.scan(internalUid,
605 [&latestRevision, revision](const QByteArray &key, const QByteArray &) -> bool { 611 [&latestRevision, revision](const QByteArray &key, const QByteArray &) -> bool {
606 const auto foundRevision = Key::fromInternalByteArray(key).revision().toQint64(); 612 const auto foundRevision = Key::fromInternalByteArray(key).revision().toQint64();
@@ -610,21 +616,21 @@ void EntityStore::readPrevious(const QByteArray &type, const QByteArray &uid, qi
610 return true; 616 return true;
611 }, 617 },
612 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Failed to read current value from storage: " << error.message; }, true); 618 [&](const DataStore::Error &error) { SinkWarningCtx(d->logCtx) << "Failed to read current value from storage: " << error.message; }, true);
613 const auto key = Key(Identifier::fromDisplayByteArray(uid), latestRevision); 619 const auto key = Key(id, latestRevision);
614 readEntity(type, key.toDisplayByteArray(), callback); 620 readEntity(type, key.toDisplayByteArray(), callback);
615} 621}
616 622
617void EntityStore::readPrevious(const QByteArray &type, const QByteArray &uid, qint64 revision, const std::function<void(const ApplicationDomainType &)> callback) 623void EntityStore::readPrevious(const QByteArray &type, const Identifier &id, qint64 revision, const std::function<void(const ApplicationDomainType &)> callback)
618{ 624{
619 readPrevious(type, uid, revision, [&](const QByteArray &uid, const EntityBuffer &buffer) { 625 readPrevious(type, id, revision, [&](const QByteArray &uid, const EntityBuffer &buffer) {
620 callback(d->createApplicationDomainType(type, uid, DataStore::maxRevision(d->getTransaction()), buffer)); 626 callback(d->createApplicationDomainType(type, uid, DataStore::maxRevision(d->getTransaction()), buffer));
621 }); 627 });
622} 628}
623 629
624ApplicationDomain::ApplicationDomainType EntityStore::readPrevious(const QByteArray &type, const QByteArray &uid, qint64 revision) 630ApplicationDomain::ApplicationDomainType EntityStore::readPrevious(const QByteArray &type, const Identifier &id, qint64 revision)
625{ 631{
626 ApplicationDomainType dt; 632 ApplicationDomainType dt;
627 readPrevious(type, uid, revision, [&](const ApplicationDomainType &entity) { 633 readPrevious(type, id, revision, [&](const ApplicationDomainType &entity) {
628 dt = *ApplicationDomainType::getInMemoryRepresentation<ApplicationDomainType>(entity, entity.availableProperties()); 634 dt = *ApplicationDomainType::getInMemoryRepresentation<ApplicationDomainType>(entity, entity.availableProperties());
629 }); 635 });
630 return dt; 636 return dt;
diff --git a/common/storage/entitystore.h b/common/storage/entitystore.h
index 1dcd285..619b884 100644
--- a/common/storage/entitystore.h
+++ b/common/storage/entitystore.h
@@ -59,7 +59,7 @@ public:
59 59
60 QVector<QByteArray> fullScan(const QByteArray &type); 60 QVector<QByteArray> fullScan(const QByteArray &type);
61 QVector<QByteArray> indexLookup(const QByteArray &type, const QueryBase &query, QSet<QByteArrayList> &appliedFilters, QByteArray &appliedSorting); 61 QVector<QByteArray> indexLookup(const QByteArray &type, const QueryBase &query, QSet<QByteArrayList> &appliedFilters, QByteArray &appliedSorting);
62 QVector<QByteArray> indexLookup(const QByteArray &type, const QByteArray &property, const QVariant &value); 62 QVector<Sink::Storage::Identifier> indexLookup(const QByteArray &type, const QByteArray &property, const QVariant &value);
63 void indexLookup(const QByteArray &type, const QByteArray &property, const QVariant &value, const std::function<void(const QByteArray &uid)> &callback); 63 void indexLookup(const QByteArray &type, const QByteArray &property, const QVariant &value, const std::function<void(const QByteArray &uid)> &callback);
64 template<typename EntityType, typename PropertyType> 64 template<typename EntityType, typename PropertyType>
65 void indexLookup(const QVariant &value, const std::function<void(const QByteArray &uid)> &callback) { 65 void indexLookup(const QVariant &value, const std::function<void(const QByteArray &uid)> &callback) {
@@ -67,10 +67,13 @@ public:
67 } 67 }
68 68
69 ///Returns the uid and buffer. Note that the memory only remains valid until the next operation or transaction end. 69 ///Returns the uid and buffer. Note that the memory only remains valid until the next operation or transaction end.
70 void readLatest(const QByteArray &type, const Identifier &uid, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback);
70 void readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback); 71 void readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback);
71 ///Returns an entity. Note that the memory only remains valid until the next operation or transaction end. 72 ///Returns an entity. Note that the memory only remains valid until the next operation or transaction end.
73 void readLatest(const QByteArray &type, const Identifier &uid, const std::function<void(const ApplicationDomainType &entity)> callback);
72 void readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const ApplicationDomainType &entity)> callback); 74 void readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const ApplicationDomainType &entity)> callback);
73 ///Returns an entity and operation. Note that the memory only remains valid until the next operation or transaction end. 75 ///Returns an entity and operation. Note that the memory only remains valid until the next operation or transaction end.
76 void readLatest(const QByteArray &type, const Identifier &uid, const std::function<void(const ApplicationDomainType &entity, Sink::Operation)> callback);
74 void readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const ApplicationDomainType &entity, Sink::Operation)> callback); 77 void readLatest(const QByteArray &type, const QByteArray &uid, const std::function<void(const ApplicationDomainType &entity, Sink::Operation)> callback);
75 78
76 ///Returns a copy 79 ///Returns a copy
@@ -94,10 +97,10 @@ public:
94 } 97 }
95 98
96 99
97 void readPrevious(const QByteArray &type, const QByteArray &uid, qint64 revision, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback); 100 void readPrevious(const QByteArray &type, const Sink::Storage::Identifier &id, qint64 revision, const std::function<void(const QByteArray &uid, const EntityBuffer &entity)> callback);
98 void readPrevious(const QByteArray &type, const QByteArray &uid, qint64 revision, const std::function<void(const ApplicationDomainType &entity)> callback); 101 void readPrevious(const QByteArray &type, const Sink::Storage::Identifier &id, qint64 revision, const std::function<void(const ApplicationDomainType &entity)> callback);
99 ///Returns a copy 102 ///Returns a copy
100 ApplicationDomainType readPrevious(const QByteArray &type, const QByteArray &uid, qint64 revision); 103 ApplicationDomainType readPrevious(const QByteArray &type, const Sink::Storage::Identifier &id, qint64 revision);
101 104
102 template<typename T> 105 template<typename T>
103 T readPrevious(const QByteArray &uid, qint64 revision) { 106 T readPrevious(const QByteArray &uid, qint64 revision) {
@@ -115,7 +118,7 @@ public:
115 }); 118 });
116 } 119 }
117 120
118 void readRevisions(qint64 baseRevision, const QByteArray &type, const std::function<void(const QByteArray &key)> &callback); 121 void readRevisions(qint64 baseRevision, const QByteArray &type, const std::function<void(const Key &key)> &callback);
119 122
120 ///Db contains entity (but may already be marked as removed 123 ///Db contains entity (but may already be marked as removed
121 bool contains(const QByteArray &type, const QByteArray &uid); 124 bool contains(const QByteArray &type, const QByteArray &uid);
diff --git a/common/storage/key.cpp b/common/storage/key.cpp
index 01a3e3a..cfeb016 100644
--- a/common/storage/key.cpp
+++ b/common/storage/key.cpp
@@ -46,8 +46,14 @@ QDebug &operator<<(QDebug &dbg, const Key &key)
46 46
47// Identifier 47// Identifier
48 48
49Identifier Identifier::createIdentifier()
50{
51 return Identifier(QUuid::createUuid());
52}
53
49QByteArray Identifier::toInternalByteArray() const 54QByteArray Identifier::toInternalByteArray() const
50{ 55{
56 Q_ASSERT(!uid.isNull());
51 return uid.toRfc4122(); 57 return uid.toRfc4122();
52} 58}
53 59
@@ -73,6 +79,21 @@ Identifier Identifier::fromDisplayByteArray(const QByteArray &bytes)
73 return Identifier(QUuid(bytes)); 79 return Identifier(QUuid(bytes));
74} 80}
75 81
82bool Identifier::isNull() const
83{
84 return uid.isNull();
85}
86
87bool Identifier::operator==(const Identifier &other) const
88{
89 return uid == other.uid;
90}
91
92bool Identifier::operator!=(const Identifier &other) const
93{
94 return !(*this == other);
95}
96
76// Revision 97// Revision
77 98
78QByteArray Revision::toInternalByteArray() const 99QByteArray Revision::toInternalByteArray() const
@@ -107,6 +128,16 @@ qint64 Revision::toQint64() const
107 return rev; 128 return rev;
108} 129}
109 130
131bool Revision::operator==(const Revision &other) const
132{
133 return rev == other.rev;
134}
135
136bool Revision::operator!=(const Revision &other) const
137{
138 return !(*this == other);
139}
140
110// Key 141// Key
111 142
112QByteArray Key::toInternalByteArray() const 143QByteArray Key::toInternalByteArray() const
@@ -154,3 +185,19 @@ void Key::setRevision(const Revision &newRev)
154{ 185{
155 rev = newRev; 186 rev = newRev;
156} 187}
188
189bool Key::isNull() const
190{
191 return id.isNull();
192}
193
194bool Key::operator==(const Key &other) const
195{
196 return (id == other.id) && (rev == other.rev);
197}
198
199bool Key::operator!=(const Key &other) const
200{
201 return !(*this == other);
202}
203
diff --git a/common/storage/key.h b/common/storage/key.h
index 76dbd13..a5b92bb 100644
--- a/common/storage/key.h
+++ b/common/storage/key.h
@@ -37,7 +37,8 @@ public:
37 static const constexpr size_t INTERNAL_REPR_SIZE = 16; 37 static const constexpr size_t INTERNAL_REPR_SIZE = 16;
38 static const constexpr size_t DISPLAY_REPR_SIZE = 38; 38 static const constexpr size_t DISPLAY_REPR_SIZE = 38;
39 39
40 Identifier() : uid(QUuid::createUuid()){}; 40 Identifier() = default;
41 static Identifier createIdentifier();
41 42
42 QByteArray toInternalByteArray() const; 43 QByteArray toInternalByteArray() const;
43 static Identifier fromInternalByteArray(const QByteArray &bytes); 44 static Identifier fromInternalByteArray(const QByteArray &bytes);
@@ -45,6 +46,11 @@ public:
45 QByteArray toDisplayByteArray() const; 46 QByteArray toDisplayByteArray() const;
46 static Identifier fromDisplayByteArray(const QByteArray &bytes); 47 static Identifier fromDisplayByteArray(const QByteArray &bytes);
47 48
49 bool isNull() const;
50
51 bool operator==(const Identifier &other) const;
52 bool operator!=(const Identifier &other) const;
53
48private: 54private:
49 explicit Identifier(const QUuid &uid) : uid(uid) {} 55 explicit Identifier(const QUuid &uid) : uid(uid) {}
50 QUuid uid; 56 QUuid uid;
@@ -66,6 +72,9 @@ public:
66 static Revision fromDisplayByteArray(const QByteArray &bytes); 72 static Revision fromDisplayByteArray(const QByteArray &bytes);
67 qint64 toQint64() const; 73 qint64 toQint64() const;
68 74
75 bool operator==(const Revision &other) const;
76 bool operator!=(const Revision &other) const;
77
69private: 78private:
70 qint64 rev; 79 qint64 rev;
71}; 80};
@@ -76,6 +85,7 @@ public:
76 static const constexpr size_t INTERNAL_REPR_SIZE = Identifier::INTERNAL_REPR_SIZE + Revision::INTERNAL_REPR_SIZE; 85 static const constexpr size_t INTERNAL_REPR_SIZE = Identifier::INTERNAL_REPR_SIZE + Revision::INTERNAL_REPR_SIZE;
77 static const constexpr size_t DISPLAY_REPR_SIZE = Identifier::DISPLAY_REPR_SIZE + Revision::DISPLAY_REPR_SIZE; 86 static const constexpr size_t DISPLAY_REPR_SIZE = Identifier::DISPLAY_REPR_SIZE + Revision::DISPLAY_REPR_SIZE;
78 87
88 Key() : id(), rev(0) {}
79 Key(const Identifier &id, const Revision &rev) : id(id), rev(rev) {} 89 Key(const Identifier &id, const Revision &rev) : id(id), rev(rev) {}
80 90
81 QByteArray toInternalByteArray() const; 91 QByteArray toInternalByteArray() const;
@@ -87,6 +97,11 @@ public:
87 const Revision &revision() const; 97 const Revision &revision() const;
88 void setRevision(const Revision &newRev); 98 void setRevision(const Revision &newRev);
89 99
100 bool isNull() const;
101
102 bool operator==(const Key &other) const;
103 bool operator!=(const Key &other) const;
104
90private: 105private:
91 Identifier id; 106 Identifier id;
92 Revision rev; 107 Revision rev;
diff --git a/common/typeindex.cpp b/common/typeindex.cpp
index 887a146..1dd54e8 100644
--- a/common/typeindex.cpp
+++ b/common/typeindex.cpp
@@ -427,17 +427,17 @@ QVector<QByteArray> TypeIndex::query(const Sink::QueryBase &query, QSet<QByteArr
427 return {}; 427 return {};
428} 428}
429 429
430QVector<QByteArray> TypeIndex::lookup(const QByteArray &property, const QVariant &value, 430QVector<Identifier> TypeIndex::lookup(const QByteArray &property, const QVariant &value,
431 Sink::Storage::DataStore::Transaction &transaction) 431 Sink::Storage::DataStore::Transaction &transaction)
432{ 432{
433 SinkTraceCtx(mLogCtx) << "Index lookup on property: " << property << mSecondaryProperties.keys() << mProperties; 433 SinkTraceCtx(mLogCtx) << "Index lookup on property: " << property << mSecondaryProperties.keys() << mProperties;
434 if (mProperties.contains(property)) { 434 if (mProperties.contains(property)) {
435 QVector<QByteArray> keys; 435 QVector<Identifier> keys;
436 Index index(indexName(property), transaction); 436 Index index(indexName(property), transaction);
437 const auto lookupKey = getByteArray(value); 437 const auto lookupKey = getByteArray(value);
438 index.lookup(lookupKey, 438 index.lookup(lookupKey,
439 [&](const QByteArray &value) { 439 [&](const QByteArray &value) {
440 keys << Identifier::fromInternalByteArray(value).toDisplayByteArray(); 440 keys << Identifier::fromInternalByteArray(value);
441 }, 441 },
442 [property](const Index::Error &error) { 442 [property](const Index::Error &error) {
443 SinkWarning() << "Error in index: " << error.message << property; 443 SinkWarning() << "Error in index: " << error.message << property;
@@ -447,7 +447,7 @@ QVector<QByteArray> TypeIndex::lookup(const QByteArray &property, const QVariant
447 } else if (mSecondaryProperties.contains(property)) { 447 } else if (mSecondaryProperties.contains(property)) {
448 // Lookups on secondary indexes first lookup the key, and then lookup the results again to 448 // Lookups on secondary indexes first lookup the key, and then lookup the results again to
449 // resolve to entity id's 449 // resolve to entity id's
450 QVector<QByteArray> keys; 450 QVector<Identifier> keys;
451 auto resultProperty = mSecondaryProperties.value(property); 451 auto resultProperty = mSecondaryProperties.value(property);
452 452
453 QVector<QByteArray> secondaryKeys; 453 QVector<QByteArray> secondaryKeys;
@@ -466,7 +466,7 @@ QVector<QByteArray> TypeIndex::lookup(const QByteArray &property, const QVariant
466 } else { 466 } else {
467 SinkWarning() << "Tried to lookup " << property << " but couldn't find value"; 467 SinkWarning() << "Tried to lookup " << property << " but couldn't find value";
468 } 468 }
469 return QVector<QByteArray>(); 469 return {};
470} 470}
471 471
472template <> 472template <>
diff --git a/common/typeindex.h b/common/typeindex.h
index a701e9c..f2cabaf 100644
--- a/common/typeindex.h
+++ b/common/typeindex.h
@@ -95,7 +95,7 @@ public:
95 void remove(const Sink::Storage::Identifier &identifier, const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Storage::DataStore::Transaction &transaction, const QByteArray &resourceInstanceId); 95 void remove(const Sink::Storage::Identifier &identifier, const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Storage::DataStore::Transaction &transaction, const QByteArray &resourceInstanceId);
96 96
97 QVector<QByteArray> query(const Sink::QueryBase &query, QSet<QByteArrayList> &appliedFilters, QByteArray &appliedSorting, Sink::Storage::DataStore::Transaction &transaction, const QByteArray &resourceInstanceId); 97 QVector<QByteArray> query(const Sink::QueryBase &query, QSet<QByteArrayList> &appliedFilters, QByteArray &appliedSorting, Sink::Storage::DataStore::Transaction &transaction, const QByteArray &resourceInstanceId);
98 QVector<QByteArray> lookup(const QByteArray &property, const QVariant &value, Sink::Storage::DataStore::Transaction &transaction); 98 QVector<Sink::Storage::Identifier> lookup(const QByteArray &property, const QVariant &value, Sink::Storage::DataStore::Transaction &transaction);
99 99
100 template <typename Left, typename Right> 100 template <typename Left, typename Right>
101 QVector<QByteArray> secondaryLookup(const QVariant &value) 101 QVector<QByteArray> secondaryLookup(const QVariant &value)