summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/datastorequery.cpp121
-rw-r--r--common/datastorequery.h7
-rw-r--r--common/domain/applicationdomaintype.h8
-rw-r--r--common/domain/mail.cpp80
-rw-r--r--common/modelresult.cpp6
-rw-r--r--common/typeindex.cpp68
-rw-r--r--common/typeindex.h39
7 files changed, 251 insertions, 78 deletions
diff --git a/common/datastorequery.cpp b/common/datastorequery.cpp
index 95df1a0..7c0fdea 100644
--- a/common/datastorequery.cpp
+++ b/common/datastorequery.cpp
@@ -141,51 +141,78 @@ public:
141 } 141 }
142}; 142};
143 143
144/* class Reduction : public FilterBase { */ 144class Reduce : public FilterBase {
145/* public: */ 145public:
146/* typedef QSharedPointer<Reduction> Ptr; */ 146 typedef QSharedPointer<Reduce> Ptr;
147
148 QHash<QByteArray, QVariant> mAggregateValues;
149 QByteArray mReductionProperty;
150 QByteArray mSelectionProperty;
151 enum SelectionComparator {
152 Max
153 /* Min, */
154 /* First */
155 };
156 SelectionComparator mSelectionComparator;
147 157
148/* QHash<QByteArray, QDateTime> aggregateValues; */ 158 Reduce(const QByteArray &reductionProperty, const QByteArray &selectionProperty, SelectionComparator comparator, FilterBase::Ptr source, DataStoreQuery *store)
159 : FilterBase(source, store),
160 mReductionProperty(reductionProperty),
161 mSelectionProperty(selectionProperty),
162 mSelectionComparator(comparator)
163 {
149 164
150/* Reduction(FilterBase::Ptr source, DataStoreQuery *store) */ 165 }
151/* : FilterBase(source, store) */
152/* { */
153 166
154/* } */ 167 virtual ~Reduce(){}
155 168
156/* virtual ~Reduction(){} */ 169 static QByteArray getByteArray(const QVariant &value)
157 170 {
158/* bool next(const std::function<void(const QByteArray &uid, const Sink::EntityBuffer &entityBuffer)> &callback) Q_DECL_OVERRIDE { */ 171 if (value.type() == QVariant::DateTime) {
159/* bool foundValue = false; */ 172 return value.toDateTime().toString().toLatin1();
160/* while(!foundValue && mSource->next([this, callback, &foundValue](const QByteArray &uid, const Sink::EntityBuffer &entityBuffer) { */ 173 }
161/* const auto operation = entityBuffer.operation(); */ 174 if (value.isValid() && !value.toByteArray().isEmpty()) {
162/* SinkTrace() << "Filter: " << uid << operation; */ 175 return value.toByteArray();
163/* //Always accept removals. They can't match the filter since the data is gone. */ 176 }
164/* if (operation == Sink::Operation_Removal) { */ 177 return QByteArray();
165/* callback(uid, entityBuffer); */ 178 }
166/* foundValue = true; */
167/* } else if (matchesFilter(uid, entityBuffer)) { */
168/* callback(uid, entityBuffer); */
169/* foundValue = true; */
170/* } */
171/* return false; */
172/* })) */
173/* {} */
174/* return foundValue; */
175/* } */
176 179
177/* bool matchesFilter(const QByteArray &uid, const Sink::EntityBuffer &entityBuffer) { */ 180 static bool compare(const QVariant &left, const QVariant &right, SelectionComparator comparator)
178/* for (const auto &filterProperty : propertyFilter.keys()) { */ 181 {
179/* const auto property = getProperty(entityBuffer.entity(), filterProperty); */ 182 if (comparator == Max) {
180/* const auto comparator = propertyFilter.value(filterProperty); */ 183 return left > right;
181/* if (!comparator.matches(property)) { */ 184 }
182/* SinkTrace() << "Filtering entity due to property mismatch on filter: " << filterProperty << property << ":" << comparator.value; */ 185 return false;
183/* return false; */ 186 }
184/* } */ 187
185/* } */ 188 bool next(const std::function<void(Sink::Operation operation, const QByteArray &uid, const Sink::EntityBuffer &entityBuffer)> &callback) Q_DECL_OVERRIDE {
186/* return true; */ 189 bool foundValue = false;
187/* } */ 190 while(!foundValue && mSource->next([this, callback, &foundValue](Sink::Operation operation, const QByteArray &uid, const Sink::EntityBuffer &entityBuffer) {
188/* }; */ 191 auto reductionValue = getProperty(entityBuffer.entity(), mReductionProperty);
192 if (!mAggregateValues.contains(getByteArray(reductionValue))) {
193 QVariant selectionResultValue;
194 QByteArray selectionResult;
195 auto results = indexLookup(mReductionProperty, reductionValue);
196 for (const auto r : results) {
197 readEntity(r, [&, this](const QByteArray &uid, const Sink::EntityBuffer &entityBuffer) {
198 auto selectionValue = getProperty(entityBuffer.entity(), mSelectionProperty);
199 if (!selectionResultValue.isValid() || compare(selectionValue, selectionResultValue, mSelectionComparator)) {
200 selectionResultValue = selectionValue;
201 selectionResult = uid;
202 }
203 });
204 }
205 readEntity(selectionResult, [&, this](const QByteArray &uid, const Sink::EntityBuffer &entityBuffer) {
206 callback(Sink::Operation_Creation, uid, entityBuffer);
207 foundValue = true;
208 });
209 }
210 return false;
211 }))
212 {}
213 return foundValue;
214 }
215};
189 216
190DataStoreQuery::DataStoreQuery(const Sink::Query &query, const QByteArray &type, Sink::Storage::Transaction &transaction, TypeIndex &typeIndex, std::function<QVariant(const Sink::Entity &entity, const QByteArray &property)> getProperty) 217DataStoreQuery::DataStoreQuery(const Sink::Query &query, const QByteArray &type, Sink::Storage::Transaction &transaction, TypeIndex &typeIndex, std::function<QVariant(const Sink::Entity &entity, const QByteArray &property)> getProperty)
191 : mQuery(query), mTransaction(transaction), mType(type), mTypeIndex(typeIndex), mDb(Storage::mainDatabase(mTransaction, mType)), mGetProperty(getProperty) 218 : mQuery(query), mTransaction(transaction), mType(type), mTypeIndex(typeIndex), mDb(Storage::mainDatabase(mTransaction, mType)), mGetProperty(getProperty)
@@ -230,6 +257,11 @@ QVariant DataStoreQuery::getProperty(const Sink::Entity &entity, const QByteArra
230 return mGetProperty(entity, property); 257 return mGetProperty(entity, property);
231} 258}
232 259
260QVector<QByteArray> DataStoreQuery::indexLookup(const QByteArray &property, const QVariant &value)
261{
262 return mTypeIndex.lookup(property, value, mTransaction);
263}
264
233/* ResultSet DataStoreQuery::filterAndSortSet(ResultSet &resultSet, const FilterFunction &filter, const QByteArray &sortProperty) */ 265/* ResultSet DataStoreQuery::filterAndSortSet(ResultSet &resultSet, const FilterFunction &filter, const QByteArray &sortProperty) */
234/* { */ 266/* { */
235/* const bool sortingRequired = !sortProperty.isEmpty(); */ 267/* const bool sortingRequired = !sortProperty.isEmpty(); */
@@ -347,11 +379,10 @@ void DataStoreQuery::setupQuery()
347 /* baseSet = Sort::Ptr::create(baseSet, mQuery.sortProperty); */ 379 /* baseSet = Sort::Ptr::create(baseSet, mQuery.sortProperty); */
348 /* } */ 380 /* } */
349 381
350 /* if (mQuery.threadLeaderOnly) { */ 382 if (mQuery.threadLeaderOnly) {
351 /* auto reduce = Reduce::Ptr::create(baseSet, this); */ 383 auto reduce = Reduce::Ptr::create("threadId", "date", Reduce::Max, baseSet, this);
352 384 baseSet = reduce;
353 /* baseSet = reduce; */ 385 }
354 /* } */
355 386
356 mCollector = Collector::Ptr::create(baseSet, this); 387 mCollector = Collector::Ptr::create(baseSet, this);
357} 388}
diff --git a/common/datastorequery.h b/common/datastorequery.h
index c9f6a3a..ea61780 100644
--- a/common/datastorequery.h
+++ b/common/datastorequery.h
@@ -44,6 +44,7 @@ protected:
44 typedef std::function<void(const QByteArray &uid, const Sink::EntityBuffer &entityBuffer)> BufferCallback; 44 typedef std::function<void(const QByteArray &uid, const Sink::EntityBuffer &entityBuffer)> BufferCallback;
45 45
46 virtual QVariant getProperty(const Sink::Entity &entity, const QByteArray &property); 46 virtual QVariant getProperty(const Sink::Entity &entity, const QByteArray &property);
47 QVector<QByteArray> indexLookup(const QByteArray &property, const QVariant &value);
47 48
48 virtual void readEntity(const QByteArray &key, const BufferCallback &resultCallback); 49 virtual void readEntity(const QByteArray &key, const BufferCallback &resultCallback);
49 50
@@ -100,6 +101,12 @@ public:
100 return mDatastore->getProperty(entity, property); 101 return mDatastore->getProperty(entity, property);
101 } 102 }
102 103
104 QVector<QByteArray> indexLookup(const QByteArray &property, const QVariant &value)
105 {
106 Q_ASSERT(mDatastore);
107 return mDatastore->indexLookup(property, value);
108 }
109
103 virtual void skip() { mSource->skip(); }; 110 virtual void skip() { mSource->skip(); };
104 111
105 //Returns true for as long as a result is available 112 //Returns true for as long as a result is available
diff --git a/common/domain/applicationdomaintype.h b/common/domain/applicationdomaintype.h
index c853397..c824251 100644
--- a/common/domain/applicationdomaintype.h
+++ b/common/domain/applicationdomaintype.h
@@ -79,6 +79,12 @@
79 void set##NAME(const QByteArray &value) { setProperty(NAME::name, QVariant::fromValue(value)); } \ 79 void set##NAME(const QByteArray &value) { setProperty(NAME::name, QVariant::fromValue(value)); } \
80 QByteArray get##NAME() const { return getProperty(NAME::name).value<QByteArray>(); } \ 80 QByteArray get##NAME() const { return getProperty(NAME::name).value<QByteArray>(); } \
81 81
82#define SINK_INDEX_PROPERTY(TYPE, NAME, LOWERCASENAME) \
83 struct NAME { \
84 static constexpr const char *name = #LOWERCASENAME; \
85 typedef TYPE Type; \
86 }; \
87
82 88
83namespace Sink { 89namespace Sink {
84namespace ApplicationDomain { 90namespace ApplicationDomain {
@@ -240,6 +246,7 @@ struct SINK_EXPORT Mail : public Entity {
240 SINK_PROPERTY(bool, Sent, sent); 246 SINK_PROPERTY(bool, Sent, sent);
241 SINK_EXTRACTED_PROPERTY(QByteArray, MessageId, messageId); 247 SINK_EXTRACTED_PROPERTY(QByteArray, MessageId, messageId);
242 SINK_EXTRACTED_PROPERTY(QByteArray, ParentMessageId, parentMessageId); 248 SINK_EXTRACTED_PROPERTY(QByteArray, ParentMessageId, parentMessageId);
249 SINK_INDEX_PROPERTY(QByteArray, ThreadId, threadId);
243}; 250};
244 251
245/** 252/**
@@ -378,6 +385,7 @@ class SINK_EXPORT TypeImplementation;
378#undef SINK_EXTRACTED_PROPERTY 385#undef SINK_EXTRACTED_PROPERTY
379#undef SINK_BLOB_PROPERTY 386#undef SINK_BLOB_PROPERTY
380#undef SINK_REFERENCE_PROPERTY 387#undef SINK_REFERENCE_PROPERTY
388#undef SINK_INDEX_PROPERTY
381 389
382Q_DECLARE_METATYPE(Sink::ApplicationDomain::ApplicationDomainType) 390Q_DECLARE_METATYPE(Sink::ApplicationDomain::ApplicationDomainType)
383Q_DECLARE_METATYPE(Sink::ApplicationDomain::ApplicationDomainType::Ptr) 391Q_DECLARE_METATYPE(Sink::ApplicationDomain::ApplicationDomainType::Ptr)
diff --git a/common/domain/mail.cpp b/common/domain/mail.cpp
index 483a2f2..2b6eb84 100644
--- a/common/domain/mail.cpp
+++ b/common/domain/mail.cpp
@@ -60,6 +60,10 @@ static TypeIndex &getIndex()
60 index->addPropertyWithSorting<QByteArray, QDateTime>(Mail::Folder::name, Mail::Date::name); 60 index->addPropertyWithSorting<QByteArray, QDateTime>(Mail::Folder::name, Mail::Date::name);
61 index->addProperty<QByteArray>(Mail::MessageId::name); 61 index->addProperty<QByteArray>(Mail::MessageId::name);
62 index->addProperty<QByteArray>(Mail::ParentMessageId::name); 62 index->addProperty<QByteArray>(Mail::ParentMessageId::name);
63
64 index->addProperty<Mail::MessageId>();
65 index->addSecondaryProperty<Mail::MessageId, Mail::ThreadId>();
66 index->addSecondaryProperty<Mail::ThreadId, Mail::MessageId>();
63 } 67 }
64 return *index; 68 return *index;
65} 69}
@@ -120,42 +124,44 @@ static QString stripOffPrefixes(const QString &subject)
120 124
121static void updateThreadingIndex(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction) 125static void updateThreadingIndex(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction)
122{ 126{
123 auto messageId = bufferAdaptor.getProperty(Mail::MessageId::name).toByteArray(); 127 auto messageId = bufferAdaptor.getProperty(Mail::MessageId::name);
124 auto parentMessageId = bufferAdaptor.getProperty(Mail::ParentMessageId::name).toByteArray(); 128 auto parentMessageId = bufferAdaptor.getProperty(Mail::ParentMessageId::name);
125 auto subject = bufferAdaptor.getProperty(Mail::Subject::name).toString(); 129 auto subject = bufferAdaptor.getProperty(Mail::Subject::name);
126 130
127 Index msgIdIndex("msgId", transaction); 131 auto normalizedSubject = stripOffPrefixes(subject.toString()).toUtf8();
128 Index msgIdThreadIdIndex("msgIdThreadId", transaction);
129 Index subjectThreadIdIndex("subjectThreadId", transaction);
130 132
131 //Add the message to the index 133 QVector<QByteArray> thread;
132 Q_ASSERT(msgIdIndex.lookup(messageId).isEmpty());
133 msgIdIndex.add(messageId, identifier);
134 134
135 auto normalizedSubject = stripOffPrefixes(subject).toUtf8(); 135 //a child already registered our thread.
136 thread = getIndex().secondaryLookup<Mail::MessageId, Mail::ThreadId>(messageId, transaction);
136 137
137 QByteArray thread;
138 //If parent is already available, add to thread of parent 138 //If parent is already available, add to thread of parent
139 if (!parentMessageId.isEmpty() && !msgIdIndex.lookup(parentMessageId).isEmpty()) { 139 if (thread.isEmpty() && parentMessageId.isValid()) {
140 thread = msgIdThreadIdIndex.lookup(parentMessageId); 140 thread = getIndex().secondaryLookup<Mail::MessageId, Mail::ThreadId>(parentMessageId, transaction);
141 msgIdThreadIdIndex.add(messageId, thread); 141 SinkTrace() << "Found parent";
142 subjectThreadIdIndex.add(normalizedSubject, thread); 142 }
143 } else { 143 if (thread.isEmpty()) {
144 //Try to lookup the thread by subject: 144 //Try to lookup the thread by subject:
145 thread = subjectThreadIdIndex.lookup(normalizedSubject); 145 thread = getIndex().secondaryLookup<Mail::Subject, Mail::ThreadId>(normalizedSubject, transaction);
146 if (!thread.isEmpty()) { 146 if (thread.isEmpty()) {
147 msgIdThreadIdIndex.add(messageId, thread); 147 SinkTrace() << "Created a new thread ";
148 thread << QUuid::createUuid().toByteArray();
148 } else { 149 } else {
149 thread = QUuid::createUuid().toByteArray();
150 subjectThreadIdIndex.add(normalizedSubject, thread);
151 if (!parentMessageId.isEmpty()) {
152 //Register parent with thread for when it becomes available
153 msgIdThreadIdIndex.add(parentMessageId, thread);
154 }
155 } 150 }
156 } 151 }
157 Q_ASSERT(!thread.isEmpty()); 152
158 msgIdThreadIdIndex.add(messageId, thread); 153 //We should have found the thread by now
154 if (!thread.isEmpty()) {
155 if (parentMessageId.isValid()) {
156 //Register parent with thread for when it becomes available
157 getIndex().index<Mail::MessageId, Mail::ThreadId>(parentMessageId, thread.first(), transaction);
158 }
159 getIndex().index<Mail::MessageId, Mail::ThreadId>(messageId, thread.first(), transaction);
160 getIndex().index<Mail::ThreadId, Mail::MessageId>(thread.first(), messageId, transaction);
161 getIndex().index<Mail::Subject, Mail::ThreadId>(normalizedSubject, thread.first(), transaction);
162 } else {
163 SinkWarning() << "Couldn't find a thread for: " << messageId;
164 }
159} 165}
160 166
161void TypeImplementation<Mail>::index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction) 167void TypeImplementation<Mail>::index(const QByteArray &identifier, const BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction)
@@ -214,13 +220,21 @@ QSharedPointer<WritePropertyMapper<TypeImplementation<Mail>::BufferBuilder> > Ty
214 220
215DataStoreQuery::Ptr TypeImplementation<Mail>::prepareQuery(const Sink::Query &query, Sink::Storage::Transaction &transaction) 221DataStoreQuery::Ptr TypeImplementation<Mail>::prepareQuery(const Sink::Query &query, Sink::Storage::Transaction &transaction)
216{ 222{
217 223 auto mapper = initializeReadPropertyMapper();
218 224 return DataStoreQuery::Ptr::create(query, ApplicationDomain::getTypeName<Mail>(), transaction, getIndex(), [mapper, &transaction](const Sink::Entity &entity, const QByteArray &property) -> QVariant {
219 auto mapper = initializeReadPropertyMapper(); 225 if (property == Mail::ThreadId::name) {
220 return DataStoreQuery::Ptr::create(query, ApplicationDomain::getTypeName<Mail>(), transaction, getIndex(), [mapper](const Sink::Entity &entity, const QByteArray &property) {
221
222 const auto localBuffer = Sink::EntityBuffer::readBuffer<Buffer>(entity.local()); 226 const auto localBuffer = Sink::EntityBuffer::readBuffer<Buffer>(entity.local());
227 Q_ASSERT(localBuffer);
228 auto messageId = mapper->getProperty(Mail::MessageId::name, localBuffer);
229 //This is an index property that we have too lookup
230 auto thread = getIndex().secondaryLookup<Mail::MessageId, Mail::ThreadId>(messageId, transaction);
231 Q_ASSERT(!thread.isEmpty());
232 return thread.first();
233 } else {
234 const auto localBuffer = Sink::EntityBuffer::readBuffer<Buffer>(entity.local());
235 Q_ASSERT(localBuffer);
223 return mapper->getProperty(property, localBuffer); 236 return mapper->getProperty(property, localBuffer);
224 }); 237 }
238 });
225} 239}
226 240
diff --git a/common/modelresult.cpp b/common/modelresult.cpp
index d13bba9..add84aa 100644
--- a/common/modelresult.cpp
+++ b/common/modelresult.cpp
@@ -289,6 +289,12 @@ template <class T, class Ptr>
289void ModelResult<T, Ptr>::modify(const Ptr &value) 289void ModelResult<T, Ptr>::modify(const Ptr &value)
290{ 290{
291 auto childId = qHash(*value); 291 auto childId = qHash(*value);
292 if (!mEntities.contains(childId)) {
293 //Happens because the DatabaseQuery emits modifiations also if the item used to be filtered.
294 SinkTrace() << "Tried to modify a value that is not yet part of the model";
295 add(value);
296 return;
297 }
292 auto id = parentId(value); 298 auto id = parentId(value);
293 // Ignore updates we get before the initial fetch is done 299 // Ignore updates we get before the initial fetch is done
294 if (!mEntityChildrenFetched.contains(id)) { 300 if (!mEntityChildrenFetched.contains(id)) {
diff --git a/common/typeindex.cpp b/common/typeindex.cpp
index 1b04966..f537493 100644
--- a/common/typeindex.cpp
+++ b/common/typeindex.cpp
@@ -168,3 +168,71 @@ QVector<QByteArray> TypeIndex::query(const Sink::Query &query, QSet<QByteArray>
168 SinkTrace() << "No matching index"; 168 SinkTrace() << "No matching index";
169 return keys; 169 return keys;
170} 170}
171
172QVector<QByteArray> TypeIndex::lookup(const QByteArray &property, const QVariant &value, Sink::Storage::Transaction &transaction)
173{
174 SinkTrace() << "Index lookup on property: " << property << mSecondaryProperties.keys() << mProperties;
175 if (mProperties.contains(property)) {
176 QVector<QByteArray> keys;
177 Index index(indexName(property), transaction);
178 const auto lookupKey = getByteArray(value);
179 index.lookup(
180 lookupKey, [&](const QByteArray &value) { keys << value; }, [property](const Index::Error &error) { SinkWarning() << "Error in index: " << error.message << property; });
181 SinkTrace() << "Index lookup on " << property << " found " << keys.size() << " keys.";
182 return keys;
183 } else if (mSecondaryProperties.contains(property)) {
184 //Lookups on secondary indexes first lookup the key, and then lookup the results again to resolve to entity id's
185 QVector<QByteArray> keys;
186 auto resultProperty = mSecondaryProperties.value(property);
187
188 QVector<QByteArray> secondaryKeys;
189 Index index(indexName(property + resultProperty), transaction);
190 const auto lookupKey = getByteArray(value);
191 index.lookup(
192 lookupKey, [&](const QByteArray &value) { secondaryKeys << value; }, [property](const Index::Error &error) { SinkWarning() << "Error in index: " << error.message << property; });
193 SinkTrace() << "Looked up secondary keys: " << secondaryKeys;
194 for (const auto &secondary : secondaryKeys) {
195 keys += lookup(resultProperty, secondary, transaction);
196 }
197 return keys;
198 } else {
199 SinkWarning() << "Tried to lookup " << property << " but couldn't find value";
200 }
201 return QVector<QByteArray>();
202}
203
204template <>
205void TypeIndex::index<QByteArray, QByteArray>(const QByteArray &leftName, const QByteArray &rightName, const QVariant &leftValue, const QVariant &rightValue, Sink::Storage::Transaction &transaction)
206{
207 Index(indexName(leftName + rightName), transaction).add(getByteArray(leftValue), getByteArray(rightValue));
208}
209
210template <>
211void TypeIndex::index<QString, QByteArray>(const QByteArray &leftName, const QByteArray &rightName, const QVariant &leftValue, const QVariant &rightValue, Sink::Storage::Transaction &transaction)
212{
213 Index(indexName(leftName + rightName), transaction).add(getByteArray(leftValue), getByteArray(rightValue));
214}
215
216template <>
217QVector<QByteArray> TypeIndex::secondaryLookup<QByteArray>(const QByteArray &leftName, const QByteArray &rightName, const QVariant &value, Sink::Storage::Transaction &transaction)
218{
219 QVector<QByteArray> keys;
220 Index index(indexName(leftName + rightName), transaction);
221 const auto lookupKey = getByteArray(value);
222 index.lookup(
223 lookupKey, [&](const QByteArray &value) { keys << value; }, [=](const Index::Error &error) { SinkWarning() << "Error in index: " << error.message << value; });
224
225 return keys;
226}
227
228template <>
229QVector<QByteArray> TypeIndex::secondaryLookup<QString>(const QByteArray &leftName, const QByteArray &rightName, const QVariant &value, Sink::Storage::Transaction &transaction)
230{
231 QVector<QByteArray> keys;
232 Index index(indexName(leftName + rightName), transaction);
233 const auto lookupKey = getByteArray(value);
234 index.lookup(
235 lookupKey, [&](const QByteArray &value) { keys << value; }, [=](const Index::Error &error) { SinkWarning() << "Error in index: " << error.message << value; });
236
237 return keys;
238}
diff --git a/common/typeindex.h b/common/typeindex.h
index f5a32b9..7266f02 100644
--- a/common/typeindex.h
+++ b/common/typeindex.h
@@ -34,16 +34,55 @@ public:
34 template <typename T, typename S> 34 template <typename T, typename S>
35 void addPropertyWithSorting(const QByteArray &property, const QByteArray &sortProperty); 35 void addPropertyWithSorting(const QByteArray &property, const QByteArray &sortProperty);
36 36
37 template <typename T>
38 void addProperty()
39 {
40 addProperty<typename T::Type>(T::name);
41 }
42
43 template <typename T>
44 void addPropertyWithSorting()
45 {
46 addPropertyWithSorting<typename T::Type>(T::name);
47 }
48
49 template <typename Left, typename Right>
50 void addSecondaryProperty()
51 {
52 mSecondaryProperties.insert(Left::name, Right::name);
53 }
37 void add(const QByteArray &identifier, const Sink::ApplicationDomain::BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction); 54 void add(const QByteArray &identifier, const Sink::ApplicationDomain::BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction);
38 void remove(const QByteArray &identifier, const Sink::ApplicationDomain::BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction); 55 void remove(const QByteArray &identifier, const Sink::ApplicationDomain::BufferAdaptor &bufferAdaptor, Sink::Storage::Transaction &transaction);
39 56
40 QVector<QByteArray> query(const Sink::Query &query, QSet<QByteArray> &appliedFilters, QByteArray &appliedSorting, Sink::Storage::Transaction &transaction); 57 QVector<QByteArray> query(const Sink::Query &query, QSet<QByteArray> &appliedFilters, QByteArray &appliedSorting, Sink::Storage::Transaction &transaction);
58 QVector<QByteArray> lookup(const QByteArray &property, const QVariant &value, Sink::Storage::Transaction &transaction);
59
60 template <typename Left, typename Right>
61 QVector<QByteArray> secondaryLookup(const QVariant &value, Sink::Storage::Transaction &transaction)
62 {
63 return secondaryLookup<typename Left::Type>(Left::name, Right::name, value, transaction);
64 }
65
66 template <typename Type>
67 QVector<QByteArray> secondaryLookup(const QByteArray &leftName, const QByteArray &rightName, const QVariant &value, Sink::Storage::Transaction &transaction);
68
69 template <typename Left, typename Right>
70 void index(const QVariant &leftValue, const QVariant &rightValue, Sink::Storage::Transaction &transaction)
71 {
72 index<typename Left::Type, typename Right::Type>(Left::name, Right::name, leftValue, rightValue, transaction);
73 }
74
75 template <typename LeftType, typename RightType>
76 void index(const QByteArray &leftName, const QByteArray &rightName, const QVariant &leftValue, const QVariant &rightValue, Sink::Storage::Transaction &transaction);
77
41 78
42private: 79private:
43 QByteArray indexName(const QByteArray &property, const QByteArray &sortProperty = QByteArray()) const; 80 QByteArray indexName(const QByteArray &property, const QByteArray &sortProperty = QByteArray()) const;
44 QByteArray mType; 81 QByteArray mType;
45 QByteArrayList mProperties; 82 QByteArrayList mProperties;
46 QMap<QByteArray, QByteArray> mSortedProperties; 83 QMap<QByteArray, QByteArray> mSortedProperties;
84 //<Property, ResultProperty>
85 QMap<QByteArray, QByteArray> mSecondaryProperties;
47 QHash<QByteArray, std::function<void(const QByteArray &identifier, const QVariant &value, Sink::Storage::Transaction &transaction)>> mIndexer; 86 QHash<QByteArray, std::function<void(const QByteArray &identifier, const QVariant &value, Sink::Storage::Transaction &transaction)>> mIndexer;
48 QHash<QByteArray, std::function<void(const QByteArray &identifier, const QVariant &value, const QVariant &sortValue, Sink::Storage::Transaction &transaction)>> mSortIndexer; 87 QHash<QByteArray, std::function<void(const QByteArray &identifier, const QVariant &value, const QVariant &sortValue, Sink::Storage::Transaction &transaction)>> mSortIndexer;
49}; 88};