summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGareth Pethig <gareth.pethig@nokia.com>2009-05-07 20:01:44 +1000
committerGareth Pethig <gareth.pethig@nokia.com>2009-05-07 20:01:44 +1000
commit27af764b9063d79c28664390702cf8242f07a5a1 (patch)
tree720eea1da13f210e332f7b9afc1164f013ddd0e9
parent5639741f45327422daca4247568963be89499080 (diff)
Update maemo patch to 2009W17 changes.2009W19-0maemo1
Update Changelog.
-rw-r--r--debian/changelog6
-rw-r--r--debian/patches/0001-maemo_changes.diff5988
2 files changed, 1387 insertions, 4607 deletions
diff --git a/debian/changelog b/debian/changelog
index 01c68b1b..bf4fe388 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+qt4-messagingframework (2009W19-0maemo1) hardy; urgency=low
+
+ * Pull from upstream.
+
+ -- Gareth Pethig <gareth.pethig@nokia.com> Thu, 07 May 2009 19:56:45 +1000
+
qt4-messagingframework (2009W17-0maemo2) hardy; urgency=low
* Add SPARQL library to package.
diff --git a/debian/patches/0001-maemo_changes.diff b/debian/patches/0001-maemo_changes.diff
index 50905629..7dcce571 100644
--- a/debian/patches/0001-maemo_changes.diff
+++ b/debian/patches/0001-maemo_changes.diff
@@ -578,7 +578,7 @@ index 0000000..cfbd6ca
@@ -0,0 +1 @@
+#include "qmailserviceaction.h"
diff --git a/src/libraries/qtopiamail/qmailstore.cpp b/src/libraries/qtopiamail/qmailstore.cpp
-index 814a2dd..504303b 100644
+index bc5fecc..992cafc 100644
--- a/src/libraries/qtopiamail/qmailstore.cpp
+++ b/src/libraries/qtopiamail/qmailstore.cpp
@@ -11,7 +11,12 @@
@@ -596,10 +596,10 @@ index 814a2dd..504303b 100644
\class QMailStore
diff --git a/src/libraries/qtopiamail/qmailstore_sparql.cpp b/src/libraries/qtopiamail/qmailstore_sparql.cpp
new file mode 100644
-index 0000000..029ca4e
+index 0000000..f596c19
--- /dev/null
+++ b/src/libraries/qtopiamail/qmailstore_sparql.cpp
-@@ -0,0 +1,6610 @@
+@@ -0,0 +1,3314 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
@@ -617,9 +617,6 @@ index 0000000..029ca4e
+#include "semaphore_p.h"
+#include "qmailnamespace.h"
+#include "qmaillog.h"
-+#include <QSqlQuery>
-+#include <QSqlError>
-+#include <QSqlRecord>
+#include <QTextCodec>
+#include <sys/types.h>
+#include <sys/ipc.h>
@@ -647,63 +644,6 @@ index 0000000..029ca4e
+using nonstd::tr1::cref;
+
+
-+class QMailStorePrivate::Key
-+{
-+ enum Type {
-+ Account = 0,
-+ AccountSort,
-+ Folder,
-+ FolderSort,
-+ Message,
-+ MessageSort,
-+ Text
-+ };
-+
-+ Type m_type;
-+ const void* m_key;
-+ const QString* m_alias;
-+
-+ template<typename NonKeyType>
-+ bool isType(NonKeyType) const { return false; }
-+
-+ bool isType(QMailAccountKey*) const { return (m_type == Account); }
-+ bool isType(QMailAccountSortKey*) const { return (m_type == AccountSort); }
-+ bool isType(QMailFolderKey*) const { return (m_type == Folder); }
-+ bool isType(QMailFolderSortKey*) const { return (m_type == FolderSort); }
-+ bool isType(QMailMessageKey*) const { return (m_type == Message); }
-+ bool isType(QMailMessageSortKey*) const { return (m_type == MessageSort); }
-+ bool isType(QString*) const { return (m_type == Text); }
-+
-+ const QMailAccountKey &key(QMailAccountKey*) const { return *reinterpret_cast<const QMailAccountKey*>(m_key); }
-+ const QMailAccountSortKey &key(QMailAccountSortKey*) const { return *reinterpret_cast<const QMailAccountSortKey*>(m_key); }
-+ const QMailFolderKey &key(QMailFolderKey*) const { return *reinterpret_cast<const QMailFolderKey*>(m_key); }
-+ const QMailFolderSortKey &key(QMailFolderSortKey*) const { return *reinterpret_cast<const QMailFolderSortKey*>(m_key); }
-+ const QMailMessageKey &key(QMailMessageKey*) const { return *reinterpret_cast<const QMailMessageKey*>(m_key); }
-+ const QMailMessageSortKey &key(QMailMessageSortKey*) const { return *reinterpret_cast<const QMailMessageSortKey*>(m_key); }
-+ const QString &key(QString*) const { return *m_alias; }
-+
-+public:
-+ explicit Key(const QMailAccountKey &key, const QString &alias = QString()) : m_type(Account), m_key(&key), m_alias(&alias) {}
-+ explicit Key(const QMailAccountSortKey &key, const QString &alias = QString()) : m_type(AccountSort), m_key(&key), m_alias(&alias) {}
-+
-+ explicit Key(const QMailFolderKey &key, const QString &alias = QString()) : m_type(Folder), m_key(&key), m_alias(&alias) {}
-+ explicit Key(const QMailFolderSortKey &key, const QString &alias = QString()) : m_type(FolderSort), m_key(&key), m_alias(&alias) {}
-+
-+ explicit Key(const QMailMessageKey &key, const QString &alias = QString()) : m_type(Message), m_key(&key), m_alias(&alias) {}
-+ explicit Key(const QMailMessageSortKey &key, const QString &alias = QString()) : m_type(MessageSort), m_key(&key), m_alias(&alias) {}
-+
-+ explicit Key(const QString &text) : m_type(Text), m_key(0), m_alias(&text) {}
-+
-+ template<typename KeyType>
-+ bool isType() const { return isType(reinterpret_cast<KeyType*>(0)); }
-+
-+ template<typename KeyType>
-+ const KeyType &key() const { return key(reinterpret_cast<KeyType*>(0)); }
-+
-+ const QString &alias() const { return *m_alias; }
-+};
-+
-+
+namespace { // none of this code is externally visible:
+
+//using namespace QMailDataComparator;
@@ -768,7 +708,6 @@ index 0000000..029ca4e
+
+typedef Guard<ProcessMutex> MutexGuard;
+
-+
+template <typename IdType>
+QVariantList idValueList(const QList<IdType>& ids)
+{
@@ -816,1488 +755,877 @@ index 0000000..029ca4e
+ return qMakePair(unescape(uri.mid(0, index), ':'), unescape(uri.mid(index + 1), ':'));
+}
+
++const char *WellKnownUris[] = {
++ "qmf://groove.harmattan.com/email#",
++ "qmf://groove.nokia.com/folder#",
++ "qmf://groove.nokia.com/accounts#" };
+
-+template<typename ValueContainer>
-+class MessageValueExtractor;
-+
-+// Class to extract QMailMessageMetaData properties to QVariant form
-+template<>
-+class MessageValueExtractor<QMailMessageMetaData>
++template <class T, int INDEX>
++class WellKnownUri : public SparqlUri
+{
-+ const QMailMessageMetaData &_data;
-+
+public:
-+ MessageValueExtractor(const QMailMessageMetaData &d) : _data(d) {}
-+
-+ QVariant id() const { return _data.id().toULongLong(); }
-+
-+ QVariant messageType() const { return static_cast<int>(_data.messageType()); }
-+
-+ QVariant parentFolderId() const { return _data.parentFolderId().toULongLong(); }
-+
-+ QVariant from() const { return _data.from().toString(); }
-+
-+ QVariant to() const { return QMailAddress::toStringList(_data.to()).join(","); }
-+
-+ QVariant subject() const { return _data.subject(); }
-+
-+ QVariant date() const { return _data.date().toLocalTime(); }
-+
-+ QVariant receivedDate() const { return _data.receivedDate().toLocalTime(); }
-+
-+ // Don't record the value of the UnloadedData flag:
-+ QVariant status() const { return (_data.status() & ~QMailMessage::UnloadedData); }
-+
-+ QVariant parentAccountId() const { return _data.parentAccountId().toULongLong(); }
-+
-+ QVariant serverUid() const { return _data.serverUid(); }
-+
-+ QVariant size() const { return _data.size(); }
-+
-+ QVariant content() const { return static_cast<int>(_data.content()); }
-+
-+ QVariant previousParentFolderId() const { return _data.previousParentFolderId().toULongLong(); }
-+
-+ QVariant contentScheme() const { return _data.contentScheme(); }
-+
-+ QVariant contentIdentifier() const { return _data.contentIdentifier(); }
-+
-+ QVariant inResponseTo() const { return _data.inResponseTo().toULongLong(); }
-+
-+ QVariant responseType() const { return static_cast<int>(_data.responseType()); }
++ WellKnownUri() : SparqlUri(WellKnownUris[INDEX]) {}
++ WellKnownUri(const T& id) : SparqlUri(WellKnownUris[INDEX], id.toULongLong()) {}
++ T id() const { return T(id()); }
++ operator T () { return id(); }
+};
+
-+// Class to extract QMailMessageMetaData properties from QVariant object
-+template<>
-+class MessageValueExtractor<QVariant>
-+{
-+ const QVariant &_value;
-+
-+public:
-+ MessageValueExtractor(const QVariant &v) : _value(v) {}
++typedef WellKnownUri<QMailMessageId, 0> MailMessageUri;
++typedef WellKnownUri<QMailFolderId, 1> MailFolderUri;
++typedef WellKnownUri<QMailAccountId, 2> MailAccountUri;
+
-+ QMailMessageId id() const { return QMailMessageId(QMailStorePrivate::extractValue<quint64>(_value)); }
-+
-+ QMailMessage::MessageType messageType() const { return QMailMessage::MessageType(QMailStorePrivate::extractValue<int>(_value)); }
-+
-+ QMailFolderId parentFolderId() const { return QMailFolderId(QMailStorePrivate::extractValue<quint64>(_value)); }
-+
-+ QMailAddress from() const { return QMailAddress(QMailStorePrivate::extractValue<QString>(_value)); }
-+
-+ QList<QMailAddress> to() const { return QMailAddress::fromStringList(QMailStorePrivate::extractValue<QString>(_value)); }
-+
-+ QString subject() const { return QMailStorePrivate::extractValue<QString>(_value); }
-+
-+ QMailTimeStamp date() const { return QMailTimeStamp(QMailStorePrivate::extractValue<QDateTime>(_value)); }
-+
-+ QMailTimeStamp receivedDate() const { return QMailTimeStamp(QMailStorePrivate::extractValue<QDateTime>(_value)); }
-+
-+ quint64 status() const { return QMailStorePrivate::extractValue<quint64>(_value); }
-+
-+ QMailAccountId parentAccountId() const { return QMailAccountId(QMailStorePrivate::extractValue<quint64>(_value)); }
-+
-+ QString serverUid() const { return QMailStorePrivate::extractValue<QString>(_value); }
-+
-+ int size() const { return QMailStorePrivate::extractValue<int>(_value); }
-+
-+ QMailMessage::ContentType content() const { return QMailMessage::ContentType(QMailStorePrivate::extractValue<int>(_value)); }
-+
-+ QMailFolderId previousParentFolderId() const { return QMailFolderId(QMailStorePrivate::extractValue<quint64>(_value)); }
-+
-+ QString contentUri() const { return QMailStorePrivate::extractValue<QString>(_value); }
-+
-+ QMailMessageId inResponseTo() const { return QMailMessageId(QMailStorePrivate::extractValue<quint64>(_value)); }
-+
-+ QMailMessage::ResponseType responseType() const { return QMailMessage::ResponseType(QMailStorePrivate::extractValue<int>(_value)); }
-+};
-+
-+
-+// Properties of the mailmessages table
-+static QMailStorePrivate::MessagePropertyMap messagePropertyMap()
++QString combineOperatorString(QMailKey::Combiner op)
+{
-+ QMailStorePrivate::MessagePropertyMap map;
-+
-+ map.insert(QMailMessageKey::Id,"id");
-+ map.insert(QMailMessageKey::Type,"type");
-+ map.insert(QMailMessageKey::ParentFolderId,"parentfolderid");
-+ map.insert(QMailMessageKey::Sender,"sender");
-+ map.insert(QMailMessageKey::Recipients,"recipients");
-+ map.insert(QMailMessageKey::Subject,"subject");
-+ map.insert(QMailMessageKey::TimeStamp,"stamp");
-+ map.insert(QMailMessageKey::ReceptionTimeStamp,"receivedstamp");
-+ map.insert(QMailMessageKey::Status,"status");
-+ map.insert(QMailMessageKey::ParentAccountId,"parentaccountid");
-+ map.insert(QMailMessageKey::ServerUid,"serveruid");
-+ map.insert(QMailMessageKey::Size,"size");
-+ map.insert(QMailMessageKey::ContentType,"contenttype");
-+ map.insert(QMailMessageKey::PreviousParentFolderId,"previousparentfolderid");
-+ map.insert(QMailMessageKey::ContentScheme,"mailfile");
-+ map.insert(QMailMessageKey::ContentIdentifier,"mailfile");
-+ map.insert(QMailMessageKey::InResponseTo,"responseid");
-+ map.insert(QMailMessageKey::ResponseType,"responsetype");
-+
-+ return map;
-+}
++ switch (op)
++ {
++ case And:
++ return " && ";
++ break;
+
-+static QString messagePropertyName(QMailMessageKey::Property property)
-+{
-+ static const QMailStorePrivate::MessagePropertyMap map(messagePropertyMap());
++ case Or:
++ return " || ";
++ break;
+
-+ QMailStorePrivate::MessagePropertyMap::const_iterator it = map.find(property);
-+ if (it != map.end())
-+ return it.value();
++ case None:
++ break;
++ }
+
-+ if ((property != QMailMessageKey::AncestorFolderIds) &&
-+ (property != QMailMessageKey::Conversation) &&
-+ (property != QMailMessageKey::Custom))
-+ qWarning() << "Unknown message property:" << property;
-+
+ return QString();
+}
+
-+typedef QMap<QMailAccountKey::Property, QString> AccountPropertyMap;
++template <class Comparator>
++QString operatorString(Comparator op, int argsNumber = 1);
+
-+// Properties of the mailaccounts table
-+static AccountPropertyMap accountPropertyMap()
++QString operatorStringPattern(int argNumber, const QString& op, const QString& comp)
+{
-+ AccountPropertyMap map;
-+
-+ map.insert(QMailAccountKey::Id,"id");
-+ map.insert(QMailAccountKey::Name,"name");
-+ map.insert(QMailAccountKey::MessageType,"type");
-+ map.insert(QMailAccountKey::FromAddress,"emailaddress");
-+ map.insert(QMailAccountKey::Status,"status");
++ QStringList pattern;
++ for (int i = 0; i<argNumber; i++)
++ pattern << "(%1 " + op + " %" + QString::number(i+2) + ")";
+
-+ return map;
++ if (argNumber > 1)
++ return "(" + pattern.join(comp) + ")";
++ else
++ return pattern.join(comp);
+}
+
-+static QString accountPropertyName(QMailAccountKey::Property property)
++template <>
++QString operatorString<QMailKey::Comparator>(QMailKey::Comparator op, int argsNumber)
+{
-+ static const AccountPropertyMap map(accountPropertyMap());
-+
-+ AccountPropertyMap::const_iterator it = map.find(property);
-+ if (it != map.end())
-+ return it.value();
-+
-+ if (property != QMailAccountKey::Custom)
-+ qWarning() << "Unknown account property:" << property;
-+
-+ return QString();
-+}
++ switch (op)
++ {
++ case Equal:
++ // "(%1 = \"%2\")" : "(%1 = \"%2\") || (%1 = \"%3\")"
++ return (argsNumber == 1 ? operatorStringPattern(argsNumber, "=", "") : operatorStringPattern(argsNumber, "=", " || "));
++ break;
+
-+typedef QMap<QMailFolderKey::Property, QString> FolderPropertyMap;
++ case NotEqual:
++ // "(%1 != \"%2\")" : "(%1 != \"%2\") && (%1 != \"%3\")"
++ return (argsNumber == 1 ? operatorStringPattern(argsNumber, "!=", "") : operatorStringPattern(argsNumber, "!=", " && "));
++ break;
+
-+// Properties of the mailfolders table
-+static FolderPropertyMap folderPropertyMap()
-+{
-+ FolderPropertyMap map;
++ case LessThan:
++ return "(%1 < %2)";
++ break;
+
-+ map.insert(QMailFolderKey::Id,"id");
-+ map.insert(QMailFolderKey::Path,"name");
-+ map.insert(QMailFolderKey::ParentFolderId,"parentid");
-+ map.insert(QMailFolderKey::ParentAccountId,"parentaccountid");
-+ map.insert(QMailFolderKey::DisplayName,"displayname");
-+ map.insert(QMailFolderKey::Status,"status");
-+ map.insert(QMailFolderKey::ServerCount,"servercount");
-+ map.insert(QMailFolderKey::ServerUnreadCount,"serverunreadcount");
++ case LessThanEqual:
++ return "(%1 <= %2)";
++ break;
+
-+ return map;
-+}
++ case GreaterThan:
++ return "(%1 > %2)";
++ break;
+
-+static QString folderPropertyName(QMailFolderKey::Property property)
-+{
-+ static const FolderPropertyMap map(folderPropertyMap());
++ case GreaterThanEqual:
++ return "(%1 >= %2)";
++ break;
+
-+ FolderPropertyMap::const_iterator it = map.find(property);
-+ if (it != map.end())
-+ return it.value();
++ case Includes:
++ case Present:
++ // "(%1 & \"%2\")" : "(%1 = \"%2\") || (%1 = \"%3\")"
++ return (argsNumber == 1 ? operatorStringPattern(argsNumber, "&", "") : operatorStringPattern(argsNumber, "=", " || "));
++ break;
+
-+ if ((property != QMailFolderKey::AncestorFolderIds) &&
-+ (property != QMailFolderKey::Custom))
-+ qWarning() << "Unknown folder property:" << property;
++ case Excludes:
++ case Absent:
++ // "!(%1 & \"%2\")" : "(%1 != \"%2\") && (%1 != \"%3\")"
++ return (argsNumber == 1 ? "(!" + operatorStringPattern(argsNumber, "&", "") + ")": operatorStringPattern(argsNumber, "!=", " && "));
++ break;
++ }
+
+ return QString();
+}
+
-+// Build lists of column names from property values
-+
-+static QString qualifiedName(const QString &name, const QString &alias)
-+{
-+ if (alias.isEmpty())
-+ return name;
-+
-+ return (alias + '.' + name);
-+}
-+
-+template<typename PropertyType>
-+QString fieldName(PropertyType property, const QString &alias);
-+
-+template<>
-+QString fieldName<QMailMessageKey::Property>(QMailMessageKey::Property property, const QString& alias)
-+{
-+ return qualifiedName(messagePropertyName(property), alias);
-+}
-+
-+template<>
-+QString fieldName<QMailFolderKey::Property>(QMailFolderKey::Property property, const QString& alias)
-+{
-+ return qualifiedName(folderPropertyName(property), alias);
-+}
-+
-+template<>
-+QString fieldName<QMailAccountKey::Property>(QMailAccountKey::Property property, const QString& alias)
-+{
-+ return qualifiedName(accountPropertyName(property), alias);
-+}
-+
-+template<typename SourceType, typename TargetType>
-+TargetType matchingProperty(SourceType source);
++template <class Property>
++QString propertyNameString(Property property);
+
-+static QMap<QMailMessageSortKey::Property, QMailMessageKey::Property> messageSortMapInit()
++template <>
++QString propertyNameString<QMailMessageKey::Property>(QMailMessageKey::Property property)
+{
-+ QMap<QMailMessageSortKey::Property, QMailMessageKey::Property> map;
++ switch (property)
++ {
++ case QMailMessageKey::Id:
++ return "?id";
+
-+ // Provide a mapping of sort key properties to the corresponding filter key
-+ map.insert(QMailMessageSortKey::Id, QMailMessageKey::Id);
-+ map.insert(QMailMessageSortKey::Type, QMailMessageKey::Type);
-+ map.insert(QMailMessageSortKey::ParentFolderId, QMailMessageKey::ParentFolderId);
-+ map.insert(QMailMessageSortKey::Sender, QMailMessageKey::Sender);
-+ map.insert(QMailMessageSortKey::Recipients, QMailMessageKey::Recipients);
-+ map.insert(QMailMessageSortKey::Subject, QMailMessageKey::Subject);
-+ map.insert(QMailMessageSortKey::TimeStamp, QMailMessageKey::TimeStamp);
-+ map.insert(QMailMessageSortKey::ReceptionTimeStamp, QMailMessageKey::ReceptionTimeStamp);
-+ map.insert(QMailMessageSortKey::Status, QMailMessageKey::Status);
-+ map.insert(QMailMessageSortKey::ParentAccountId, QMailMessageKey::ParentAccountId);
-+ map.insert(QMailMessageSortKey::ServerUid, QMailMessageKey::ServerUid);
-+ map.insert(QMailMessageSortKey::Size, QMailMessageKey::Size);
-+ map.insert(QMailMessageSortKey::ContentType, QMailMessageKey::ContentType);
-+ map.insert(QMailMessageSortKey::PreviousParentFolderId, QMailMessageKey::PreviousParentFolderId);
++ case QMailMessageKey::Type:
++ return "?type";
+
-+ return map;
-+}
++ case QMailMessageKey::ParentFolderId:
++ return "?parentFolderId";
+
-+template<>
-+QMailMessageKey::Property matchingProperty<QMailMessageSortKey::Property, QMailMessageKey::Property>(QMailMessageSortKey::Property source)
-+{
-+ static QMap<QMailMessageSortKey::Property, QMailMessageKey::Property> map(messageSortMapInit());
-+ return map.value(source);
-+}
++ case QMailMessageKey::Sender:
++ return "?sender";
+
-+static QMap<QMailFolderSortKey::Property, QMailFolderKey::Property> folderSortMapInit()
-+{
-+ QMap<QMailFolderSortKey::Property, QMailFolderKey::Property> map;
++ case QMailMessageKey::Recipients:
++ return "?recipients";
+
-+ // Provide a mapping of sort key properties to the corresponding filter key
-+ map.insert(QMailFolderSortKey::Id, QMailFolderKey::Id);
-+ map.insert(QMailFolderSortKey::Path, QMailFolderKey::Path);
-+ map.insert(QMailFolderSortKey::ParentFolderId, QMailFolderKey::ParentFolderId);
-+ map.insert(QMailFolderSortKey::ParentAccountId, QMailFolderKey::ParentAccountId);
-+ map.insert(QMailFolderSortKey::DisplayName, QMailFolderKey::DisplayName);
-+ map.insert(QMailFolderSortKey::Status, QMailFolderKey::Status);
-+ map.insert(QMailFolderSortKey::ServerCount, QMailFolderKey::ServerCount);
-+ map.insert(QMailFolderSortKey::ServerUnreadCount, QMailFolderKey::ServerUnreadCount);
++ case QMailMessageKey::Subject:
++ return "?subject";
+
-+ return map;
-+}
++ case QMailMessageKey::TimeStamp:
++ return "?timestamp";
+
-+template<>
-+QMailFolderKey::Property matchingProperty<QMailFolderSortKey::Property, QMailFolderKey::Property>(QMailFolderSortKey::Property source)
-+{
-+ static QMap<QMailFolderSortKey::Property, QMailFolderKey::Property> map(folderSortMapInit());
-+ return map.value(source);
-+}
++ case QMailMessageKey::Status:
++ return "?status";
+
-+static QMap<QMailAccountSortKey::Property, QMailAccountKey::Property> accountSortMapInit()
-+{
-+ QMap<QMailAccountSortKey::Property, QMailAccountKey::Property> map;
++ case QMailMessageKey::Conversation:
++ return "?conversation";
+
-+ // Provide a mapping of sort key properties to the corresponding filter key
-+ map.insert(QMailAccountSortKey::Id, QMailAccountKey::Id);
-+ map.insert(QMailAccountSortKey::Name, QMailAccountKey::Name);
-+ map.insert(QMailAccountSortKey::MessageType, QMailAccountKey::MessageType);
-+ map.insert(QMailAccountSortKey::Status, QMailAccountKey::Status);
++ case QMailMessageKey::ReceptionTimeStamp:
++ return "?receptionTimeStamp";
+
-+ return map;
-+}
++ case QMailMessageKey::ServerUid:
++ return "?serverUid";
+
-+template<>
-+QMailAccountKey::Property matchingProperty<QMailAccountSortKey::Property, QMailAccountKey::Property>(QMailAccountSortKey::Property source)
-+{
-+ static QMap<QMailAccountSortKey::Property, QMailAccountKey::Property> map(accountSortMapInit());
-+ return map.value(source);
-+}
++ case QMailMessageKey::Size:
++ return "?size";
+
-+template<>
-+QString fieldName<QMailMessageSortKey::Property>(QMailMessageSortKey::Property property, const QString &alias)
-+{
-+ return qualifiedName(messagePropertyName(matchingProperty<QMailMessageSortKey::Property, QMailMessageKey::Property>(property)), alias);
-+}
++ case QMailMessageKey::ParentAccountId:
++ return "?parentAccountId";
+
-+template<>
-+QString fieldName<QMailFolderSortKey::Property>(QMailFolderSortKey::Property property, const QString &alias)
-+{
-+ return qualifiedName(folderPropertyName(matchingProperty<QMailFolderSortKey::Property, QMailFolderKey::Property>(property)), alias);
-+}
++ case QMailMessageKey::AncestorFolderIds:
++ return "?ancestorFolderIds";
+
-+template<>
-+QString fieldName<QMailAccountSortKey::Property>(QMailAccountSortKey::Property property, const QString &alias)
-+{
-+ return qualifiedName(accountPropertyName(matchingProperty<QMailAccountSortKey::Property, QMailAccountKey::Property>(property)), alias);
-+}
++ case QMailMessageKey::ContentType:
++ return "?contentType";
+
-+template<typename PropertyType>
-+QString fieldNames(const QList<PropertyType> &properties, const QString &separator, const QString &alias)
-+{
-+ QStringList fields;
-+ foreach (const PropertyType &property, properties)
-+ fields.append(fieldName(property, alias));
++ case QMailMessageKey::PreviousParentFolderId:
++ return "?previousParentFolderId";
+
-+ return fields.join(separator);
-+}
++ case QMailMessageKey::ContentScheme:
++ return "?contentScheme";
+
-+template<typename ArgumentType>
-+void appendWhereValues(const ArgumentType &a, QVariantList &values);
++ case QMailMessageKey::ContentIdentifier:
++ return "?contentIdentifier";
+
-+template<typename KeyType>
-+QVariantList whereClauseValues(const KeyType& key)
-+{
-+ QVariantList values;
++ case QMailMessageKey::InResponseTo:
++ return "?inResponseTo";
+
-+ foreach (const typename KeyType::ArgumentType& a, key.arguments())
-+ ::appendWhereValues(a, values);
++ case QMailMessageKey::ResponseType:
++ return "?responseType";
+
-+ foreach (const KeyType& subkey, key.subKeys())
-+ values += ::whereClauseValues<KeyType>(subkey);
++ case QMailMessageKey::Custom:
++ return "?custom";
+
-+ return values;
++ default:
++ Q_ASSERT(false);
++ }
++ return QString();
+}
+
-+template <typename Key, typename Argument = typename Key::ArgumentType>
-+class ArgumentExtractorBase
++template <>
++QString propertyNameString<QMailFolderKey::Property>(QMailFolderKey::Property property)
+{
-+protected:
-+ const Argument &arg;
-+
-+ ArgumentExtractorBase(const Argument &a) : arg(a) {}
-+
-+ QString minimalString(const QString &s) const
-+ {
-+ // If the argument is a phone number, ensure it is in minimal form
-+ QMailAddress address(s);
-+ if (address.isPhoneNumber()) {
-+ QString minimal(address.minimalPhoneNumber());
-+
-+ // Rather than compare exact numbers, we will only use the trailing
-+ // digits to compare phone numbers - otherwise, slightly different
-+ // forms of the same number will not be matched
-+ static const int significantDigits = 8;
-+
-+ int extraneous = minimal.length() - significantDigits;
-+ if (extraneous > 0)
-+ minimal.remove(0, extraneous);
-+
-+ return minimal;
-+ }
-+
-+ return s;
-+ }
-+
-+ QString submatchString(const QString &s, bool valueMinimalised) const
-+ {
-+ if (!s.isEmpty()) {
-+ // Delimit data for sql "LIKE" operator
-+ if (((arg.op == Includes) || (arg.op == Excludes)) || (((arg.op == Equal) || (arg.op == NotEqual)) && valueMinimalised))
-+ return QString("\%" + s + "\%");
-+ } else if ((arg.op == Includes) || (arg.op == Excludes)) {
-+ return QString("\%");
-+ }
-+
-+ return s;
-+ }
-+
-+ QString addressStringValue() const
++ switch (property)
+ {
-+ return submatchString(minimalString(QMailStorePrivate::extractValue<QString>(arg.valueList.first())), true);
-+ }
++ case QMailFolderKey::Id:
++ return "?id";
+
-+ QString stringValue() const
-+ {
-+ return submatchString(QMailStorePrivate::extractValue<QString>(arg.valueList.first()), false);
-+ }
++ case QMailFolderKey::Path:
++ return "?path";
+
-+ QVariantList stringValues() const
-+ {
-+ QVariantList values;
++ case QMailFolderKey::ParentFolderId:
++ return "?parentFolderId";
+
-+ if (arg.valueList.count() == 1) {
-+ values.append(stringValue());
-+ } else {
-+ // Includes/Excludes is not a pattern match with multiple values
-+ foreach (const QVariant &item, arg.valueList)
-+ values.append(QMailStorePrivate::extractValue<QString>(item));
-+ }
++ case QMailFolderKey::ParentAccountId:
++ return "?parentAccountId";
+
-+ return values;
-+ }
++ case QMailFolderKey::DisplayName:
++ return "?displayName";
+
-+ template<typename ID>
-+ quint64 idValue() const
-+ {
-+ return QMailStorePrivate::extractValue<ID>(arg.valueList.first()).toULongLong();
-+ }
++ case QMailFolderKey::Status:
++ return "?status";
+
-+ template<typename ClauseKey>
-+ QVariantList idValues() const
-+ {
-+ const QVariant& var = arg.valueList.first();
++ case QMailFolderKey::AncestorFolderIds:
++ return "?ancestorFolderIds";
+
-+ if (qVariantCanConvert<ClauseKey>(var)) {
-+ return ::whereClauseValues(qVariantValue<ClauseKey>(var));
-+ } else {
-+ QVariantList values;
++ case QMailFolderKey::ServerCount:
++ return "?serverCount";
+
-+ foreach (const QVariant &item, arg.valueList)
-+ values.append(QMailStorePrivate::extractValue<typename ClauseKey::IdType>(item).toULongLong());
++ case QMailFolderKey::ServerUnreadCount:
++ return "?serverUnreadCount";
+
-+ return values;
-+ }
-+ }
++ case QMailFolderKey::Custom:
++ return "?custom";
+
-+ int intValue() const
-+ {
-+ return QMailStorePrivate::extractValue<int>(arg.valueList.first());
++ default:
++ Q_ASSERT(false);
+ }
++ return QString();
++}
+
-+ QVariantList intValues() const
++template <>
++QString propertyNameString<QMailAccountKey::Property>(QMailAccountKey::Property property)
++{
++ switch (property)
+ {
-+ QVariantList values;
-+
-+ foreach (const QVariant &item, arg.valueList)
-+ values.append(QMailStorePrivate::extractValue<int>(item));
++ case QMailAccountKey::Id:
++ return "?id";
+
-+ return values;
-+ }
++ case QMailAccountKey::Name:
++ return "?name";
+
-+ int quint64Value() const
-+ {
-+ return QMailStorePrivate::extractValue<quint64>(arg.valueList.first());
-+ }
++ case QMailAccountKey::MessageType:
++ return "?messageType";
+
-+ QVariantList customValues() const
-+ {
-+ QVariantList values;
++ case QMailAccountKey::FromAddress:
++ return "?fromAddress";
+
-+ QStringList constraints = QMailStorePrivate::extractValue<QStringList>(arg.valueList.first());
-+ // Field name required for existence or value test
-+ values.append(constraints.takeFirst());
++ case QMailAccountKey::Status:
++ return "?status";
+
-+ if (!constraints.isEmpty()) {
-+ // For a value test, we need the comparison value also
-+ values.append(submatchString(constraints.takeFirst(), false));
-+ }
++ case QMailAccountKey::Custom:
++ return "?custom";
+
-+ return values;
++ default:
++ Q_ASSERT(false);
+ }
-+};
-+
++ return QString();
++}
+
-+template<typename PropertyType, typename BitmapType = int>
-+class RecordExtractorBase
++template <>
++QString propertyNameString<QMailMessageSortKey::Property>(QMailMessageSortKey::Property property)
+{
-+protected:
-+ const QSqlRecord &record;
-+ const BitmapType bitmap;
-+
-+ RecordExtractorBase(const QSqlRecord &r, BitmapType b = 0) : record(r), bitmap(b) {}
-+ virtual ~RecordExtractorBase() {}
-+
-+ template<typename ValueType>
-+ ValueType value(const QString &field, const ValueType &defaultValue = ValueType()) const
-+ {
-+ int index(fieldIndex(field, bitmap));
-+
-+ if (record.isNull(index))
-+ return defaultValue;
-+ else
-+ return QMailStorePrivate::extractValue<ValueType>(record.value(index), defaultValue);
-+ }
-+
-+ template<typename ValueType>
-+ ValueType value(PropertyType p, const ValueType &defaultValue = ValueType()) const
-+ {
-+ return value(fieldName(p, QString()), defaultValue);
-+ }
-+
-+ virtual int fieldIndex(const QString &field, BitmapType b) const = 0;
-+
-+ int mappedFieldIndex(const QString &field, BitmapType bitmap, QMap<BitmapType, QMap<QString, int> > &fieldIndex) const
++ switch (property)
+ {
-+ typename QMap<BitmapType, QMap<QString, int> >::iterator it = fieldIndex.find(bitmap);
-+ if (it == fieldIndex.end()) {
-+ it = fieldIndex.insert(bitmap, QMap<QString, int>());
-+ }
-+
-+ QMap<QString, int> &fields(it.value());
-+
-+ QMap<QString, int>::iterator fit = fields.find(field);
-+ if (fit != fields.end())
-+ return fit.value();
-+
-+ int index = record.indexOf(field);
-+ fields.insert(field, index);
-+ return index;
-+ }
-+};
-+
-+
-+// Class to extract data from records of the mailmessages table
-+class MessageRecord : public RecordExtractorBase<QMailMessageKey::Property, QMailMessageKey::Properties>
-+{
-+public:
-+ MessageRecord(const QSqlRecord &r, QMailMessageKey::Properties props)
-+ : RecordExtractorBase<QMailMessageKey::Property, QMailMessageKey::Properties>(r, props) {}
-+
-+ QMailMessageId id() const { return QMailMessageId(value<quint64>(QMailMessageKey::Id)); }
-+
-+ QMailMessage::MessageType messageType() const { return QMailMessage::MessageType(value<int>(QMailMessageKey::Type, QMailMessage::None)); }
-+
-+ QMailFolderId parentFolderId() const { return QMailFolderId(value<quint64>(QMailMessageKey::ParentFolderId)); }
-+
-+ QMailAddress from() const { return QMailAddress(value<QString>(QMailMessageKey::Sender)); }
-+
-+ QList<QMailAddress> to() const { return QMailAddress::fromStringList(value<QString>(QMailMessageKey::Recipients)); }
-+
-+ QString subject() const { return value<QString>(QMailMessageKey::Subject); }
-+
-+ QMailTimeStamp date() const { return QMailTimeStamp(value<QDateTime>(QMailMessageKey::TimeStamp)); }
++ case QMailMessageSortKey::Id:
++ return "?id";
+
-+ QMailTimeStamp receivedDate() const { return QMailTimeStamp(value<QDateTime>(QMailMessageKey::TimeStamp)); }
++ case QMailMessageSortKey::Type:
++ return "?type";
+
-+ quint64 status() const { return value<quint64>(QMailMessageKey::Status, 0); }
++ case QMailMessageSortKey::ParentFolderId:
++ return "?parentFolderId";
+
-+ QMailAccountId parentAccountId() const { return QMailAccountId(value<quint64>(QMailMessageKey::ParentAccountId)); }
++ case QMailMessageSortKey::Sender:
++ return "?sender";
+
-+ QString serverUid() const { return value<QString>(QMailMessageKey::ServerUid); }
++ case QMailMessageSortKey::Recipients:
++ return "?recipients";
+
-+ int size() const { return value<int>(QMailMessageKey::Size); }
++ case QMailMessageSortKey::Subject:
++ return "?subject";
+
-+ QMailMessage::ContentType content() const { return QMailMessage::ContentType(value<int>(QMailMessageKey::ContentType, QMailMessage::UnknownContent)); }
++ case QMailMessageSortKey::TimeStamp:
++ return "?timestamp";
+
-+ QMailFolderId previousParentFolderId() const { return QMailFolderId(value<quint64>(QMailMessageKey::PreviousParentFolderId)); }
++ case QMailMessageSortKey::Status:
++ return "?status";
+
-+ QString contentScheme() const
-+ {
-+ if (_uriElements.first.isNull())
-+ _uriElements = ::uriElements(value<QString>(QMailMessageKey::ContentScheme));
++ case QMailMessageSortKey::ReceptionTimeStamp:
++ return "?receptionTimeStamp";
+
-+ return _uriElements.first;
-+ }
++ case QMailMessageSortKey::ServerUid:
++ return "?serverUid";
+
-+ QString contentIdentifier() const
-+ {
-+ if (_uriElements.first.isNull())
-+ _uriElements = ::uriElements(value<QString>(QMailMessageKey::ContentIdentifier));
++ case QMailMessageSortKey::Size:
++ return "?size";
+
-+ return _uriElements.second;
-+ }
++ case QMailMessageSortKey::ParentAccountId:
++ return "?parentAccountId";
+
-+ QMailMessageId inResponseTo() const { return QMailMessageId(value<quint64>(QMailMessageKey::InResponseTo)); }
++ case QMailMessageSortKey::ContentType:
++ return "?contentType";
+
-+ QMailMessage::ResponseType responseType() const { return QMailMessage::ResponseType(value<int>(QMailMessageKey::ResponseType, QMailMessage::NoResponse)); }
++ case QMailMessageSortKey::PreviousParentFolderId:
++ return "?previousParentFolderId";
+
-+private:
-+ int fieldIndex(const QString &field, QMailMessageKey::Properties props) const
-+ {
-+ return mappedFieldIndex(field, props, _fieldIndex);
++ default:
++ Q_ASSERT(false);
+ }
++ return QString();
++}
+
-+ mutable QPair<QString, QString> _uriElements;
-+
-+ static QMap<QMailMessageKey::Properties, QMap<QString, int> > _fieldIndex;
-+};
-+
-+QMap<QMailMessageKey::Properties, QMap<QString, int> > MessageRecord::_fieldIndex;
-+
-+
-+// Class to convert QMailMessageKey argument values to SQL bind values
-+class MessageKeyArgumentExtractor : public ArgumentExtractorBase<QMailMessageKey>
++template <>
++QString propertyNameString<QMailFolderSortKey::Property>(QMailFolderSortKey::Property property)
+{
-+public:
-+ MessageKeyArgumentExtractor(const QMailMessageKey::ArgumentType &a)
-+ : ArgumentExtractorBase<QMailMessageKey>(a) {}
-+
-+ QVariantList id() const { return idValues<QMailMessageKey>(); }
-+
-+ QVariant messageType() const { return intValue(); }
-+
-+ QVariantList parentFolderId() const { return idValues<QMailFolderKey>(); }
-+
-+ QVariantList ancestorFolderIds() const { return idValues<QMailFolderKey>(); }
-+
-+ QVariantList sender() const { return stringValues(); }
-+
-+ QVariant recipients() const { return addressStringValue(); }
-+
-+ QVariantList subject() const { return stringValues(); }
-+
-+ QVariant date() const { return QMailStorePrivate::extractValue<QDateTime>(arg.valueList.first()); }
-+
-+ QVariant receivedDate() const { return QMailStorePrivate::extractValue<QDateTime>(arg.valueList.first()); }
-+
-+ QVariant status() const
++ switch (property)
+ {
-+ // The UnloadedData flag has no meaningful persistent value
-+ return (QMailStorePrivate::extractValue<quint64>(arg.valueList.first()) & ~QMailMessage::UnloadedData);
-+ }
++ case QMailFolderSortKey::Id:
++ return "?id";
+
-+ QVariantList parentAccountId() const { return idValues<QMailAccountKey>(); }
++ case QMailFolderSortKey::Path:
++ return "?path";
+
-+ QVariantList serverUid() const { return stringValues(); }
++ case QMailFolderSortKey::ParentFolderId:
++ return "?parentFolderId";
+
-+ QVariant size() const { return intValue(); }
++ case QMailFolderSortKey::ParentAccountId:
++ return "?parentAccountId";
+
-+ QVariantList content() const { return intValues(); }
++ case QMailFolderSortKey::DisplayName:
++ return "?displayName";
+
-+ QVariantList previousParentFolderId() const { return idValues<QMailFolderKey>(); }
++ case QMailFolderSortKey::Status:
++ return "?status";
+
-+ QVariant contentScheme() const
-+ {
-+ // Any colons in the field will be stored in escaped format
-+ QString value(::escape(QMailStorePrivate::extractValue<QString>(arg.valueList.first()), ':'));
++ case QMailFolderSortKey::ServerCount:
++ return "?serverCount";
+
-+ if ((arg.op == Includes) || (arg.op == Excludes)) {
-+ value.prepend('%').append('%');
-+ } else if ((arg.op == Equal) || (arg.op == NotEqual)) {
-+ value.append(":%");
-+ }
-+ return value;
++ case QMailFolderSortKey::ServerUnreadCount:
++ return "?serverUnreadCount";
++
++ default:
++ Q_ASSERT(false);
+ }
++ return QString();
++}
+
-+ QVariant contentIdentifier() const
-+ {
-+ // Any colons in the field will be stored in escaped format
-+ QString value(::escape(QMailStorePrivate::extractValue<QString>(arg.valueList.first()), ':'));
++template <>
++QString propertyNameString<QMailAccountSortKey::Property>(QMailAccountSortKey::Property property)
++{
++ switch (property)
++ {
++ case QMailAccountSortKey::Id:
++ return "?id";
+
-+ if ((arg.op == Includes) || (arg.op == Excludes)) {
-+ value.prepend('%').append('%');
-+ } else if ((arg.op == Equal) || (arg.op == NotEqual)) {
-+ value.prepend("%:");
-+ }
-+ return value;
-+ }
++ case QMailAccountSortKey::Name:
++ return "?name";
+
-+ QVariantList inResponseTo() const { return idValues<QMailMessageKey>(); }
++ case QMailAccountSortKey::MessageType:
++ return "?messageType";
+
-+ QVariantList responseType() const { return intValues(); }
++ case QMailAccountSortKey::Status:
++ return "?status";
+
-+ QVariant conversation() const
-+ {
-+ // TODO: Not yet implemented
-+ return QVariant();
++ default:
++ Q_ASSERT(false);
+ }
++ return QString();
++}
+
-+ QVariantList custom() const { return customValues(); }
-+};
++template <class Property>
++QString sparqlPropertyStatmentString(const QString& uri, Property property);
+
-+template<>
-+void appendWhereValues<QMailMessageKey::ArgumentType>(const QMailMessageKey::ArgumentType &a, QVariantList &values)
++template <>
++QString sparqlPropertyStatmentString<QMailMessageKey::Property>(const QString& uri, QMailMessageKey::Property property)
+{
-+ const MessageKeyArgumentExtractor extractor(a);
++ /*
++ * TBD: Complete this function with all properties description.
++ */
++ switch (property)
++ {
++ case QMailMessageKey::Id:
++ return QString();
+
-+ switch (a.property)
-+ {
-+ case QMailMessageKey::Id:
-+ if (a.valueList.count() < IdLookupThreshold) {
-+ values += extractor.id();
-+ } else {
-+ // This value match has been replaced by a table lookup
-+ }
-+ break;
++ case QMailMessageKey::Type:
++ return QString();
+
-+ case QMailMessageKey::Type:
-+ values += extractor.messageType();
-+ break;
++ case QMailMessageKey::ParentFolderId:
++ return QString("%1 nie:isLogicalPartOf %2 .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailMessageKey::ParentFolderId:
-+ values += extractor.parentFolderId();
-+ break;
++ case QMailMessageKey::Sender:
++ return QString("%1 nmo:sender [ rdf:type nco:Contact ; nco:hasEmailAddress %2 ] .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailMessageKey::AncestorFolderIds:
-+ values += extractor.ancestorFolderIds();
-+ break;
++ case QMailMessageKey::Recipients:
++ return QString("%1 nmo:recipient [ rdf:type nco:Contact ; nco:hasEmailAddress %2 ] .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailMessageKey::Sender:
-+ values += extractor.sender();
-+ break;
++ case QMailMessageKey::Subject:
++ return QString("%1 nmo:messageSubject %2 .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailMessageKey::Recipients:
-+ values += extractor.recipients();
-+ break;
++ case QMailMessageKey::TimeStamp:
++ return QString("%1 nmo:sentDate %2 .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailMessageKey::Subject:
-+ values += extractor.subject();
-+ break;
++ case QMailMessageKey::Status:
++ return QString("%1 nmo:status %2 .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailMessageKey::TimeStamp:
-+ values += extractor.date();
-+ break;
++ case QMailMessageKey::Conversation:
++ return QString();
+
-+ case QMailMessageKey::ReceptionTimeStamp:
-+ values += extractor.receivedDate();
-+ break;
++ case QMailMessageKey::ReceptionTimeStamp:
++ return QString();
+
-+ case QMailMessageKey::Status:
-+ values += extractor.status();
-+ break;
++ case QMailMessageKey::ServerUid:
++ return QString("%1 nmo:messageId %2 .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailMessageKey::ParentAccountId:
-+ values += extractor.parentAccountId();
-+ break;
++ case QMailMessageKey::Size:
++ return QString("%1 nie:contentSize %2 .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailMessageKey::ServerUid:
-+ values += extractor.serverUid();
-+ break;
++ case QMailMessageKey::ParentAccountId:
++ return QString("%1 nie:relatedTo %2 .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailMessageKey::Size:
-+ values += extractor.size();
-+ break;
++ case QMailMessageKey::AncestorFolderIds:
++ return QString();
+
-+ case QMailMessageKey::ContentType:
-+ values += extractor.content();
-+ break;
++ case QMailMessageKey::ContentType:
++ return QString();
+
-+ case QMailMessageKey::PreviousParentFolderId:
-+ values += extractor.previousParentFolderId();
-+ break;
++ case QMailMessageKey::PreviousParentFolderId:
++ return QString();
+
-+ case QMailMessageKey::ContentScheme:
-+ values += extractor.contentScheme();
-+ break;
++ case QMailMessageKey::ContentScheme:
++ return QString();
+
-+ case QMailMessageKey::ContentIdentifier:
-+ values += extractor.contentIdentifier();
-+ break;
++ case QMailMessageKey::ContentIdentifier:
++ return QString("%1 nie:isStoredAs [ rdf:type nie:DataObject ; nie:dataSource %2 ] .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailMessageKey::InResponseTo:
-+ values += extractor.inResponseTo();
-+ break;
++ case QMailMessageKey::InResponseTo:
++ return QString("%1 nmo:inReplyTo %2 .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailMessageKey::ResponseType:
-+ values += extractor.responseType();
-+ break;
++ case QMailMessageKey::ResponseType:
++ return QString();
+
-+ case QMailMessageKey::Conversation:
-+ values += extractor.conversation();
-+ break;
++ case QMailMessageKey::Custom:
++ return QString();
+
-+ case QMailMessageKey::Custom:
-+ values += extractor.custom();
-+ break;
++ default:
++ Q_ASSERT(false);
+ }
++ return QString();
+}
+
-+
-+// Class to extract data from records of the mailaccounts table
-+class AccountRecord : public RecordExtractorBase<QMailAccountKey::Property>
++template <>
++QString sparqlPropertyStatmentString<QMailFolderKey::Property>(const QString& uri, QMailFolderKey::Property property)
+{
-+public:
-+ AccountRecord(const QSqlRecord &r)
-+ : RecordExtractorBase<QMailAccountKey::Property>(r) {}
-+
-+ QMailAccountId id() const { return QMailAccountId(value<quint64>(QMailAccountKey::Id)); }
-+
-+ QString name() const { return value<QString>(QMailAccountKey::Name); }
-+
-+ QMailMessage::MessageType messageType() const { return QMailMessage::MessageType(value<int>(QMailAccountKey::MessageType, -1)); }
-+
-+ QString fromAddress() const { return value<QString>(QMailAccountKey::FromAddress); }
-+
-+ quint64 status() const { return value<quint64>(QMailAccountKey::Status); }
-+
-+ QString signature() const { return value<QString>("signature"); }
-+
-+private:
-+ int fieldIndex(const QString &field, int props) const
++ /*
++ * TBD: Complete this function with all properties description.
++ */
++ switch (property)
+ {
-+ return mappedFieldIndex(field, props, _fieldIndex);
-+ }
++ case QMailFolderKey::Id:
++ return "id";
+
-+ static QMap<int, QMap<QString, int> > _fieldIndex;
-+};
++ case QMailFolderKey::Path:
++ return QString("%1 nmo:folderName %2 .").arg(uri).arg(propertyNameString(property));
+
-+QMap<int, QMap<QString, int> > AccountRecord::_fieldIndex;
++ case QMailFolderKey::ParentFolderId:
++ return QString("%1 nie:isLogicalPartOf %2 .").arg(uri).arg(propertyNameString(property));
+
++ case QMailFolderKey::ParentAccountId:
++ return QString("%1 nie:relatedTo %2 .").arg(uri).arg(propertyNameString(property));
+
-+// Class to convert QMailAccountKey argument values to SQL bind values
-+class AccountKeyArgumentExtractor : public ArgumentExtractorBase<QMailAccountKey>
-+{
-+public:
-+ AccountKeyArgumentExtractor(const QMailAccountKey::ArgumentType &a)
-+ : ArgumentExtractorBase<QMailAccountKey>(a) {}
++ case QMailFolderKey::DisplayName:
++ return QString("%1 nmo:folderDisplayName %2 .").arg(uri).arg(propertyNameString(property));
+
-+ QVariantList id() const { return idValues<QMailAccountKey>(); }
++ case QMailFolderKey::Status:
++ return QString("%1 nmo:status %2 .").arg(uri).arg(propertyNameString(property));
+
-+ QVariantList name() const { return stringValues(); }
++ case QMailFolderKey::AncestorFolderIds:
++ return QString();
+
-+ QVariant messageType() const { return intValue(); }
++ case QMailFolderKey::ServerCount:
++ return QString("%1 nmo:serverCount %2 .").arg(uri).arg(propertyNameString(property));
+
-+ QVariant fromAddress() const
-+ {
-+ QString value(QMailStorePrivate::extractValue<QString>(arg.valueList.first()));
++ case QMailFolderKey::ServerUnreadCount:
++ return QString("%1 nmo:serverUnreadCount %2 .").arg(uri).arg(propertyNameString(property));
+
-+ // This test will be converted to a LIKE test, for all comparators
-+ if (arg.op == Equal || arg.op == NotEqual) {
-+ // Ensure exact match by testing for address delimiters
-+ value.prepend('<').append('>');
-+ }
++ case QMailFolderKey::Custom:
++ return QString();
+
-+ return value.prepend('%').append('%');
++ default:
++ Q_ASSERT(false);
+ }
++ return QString();
++}
+
-+ QVariant status() const { return quint64Value(); }
-+
-+ QVariantList custom() const { return customValues(); }
-+};
-+
-+template<>
-+void appendWhereValues<QMailAccountKey::ArgumentType>(const QMailAccountKey::ArgumentType &a, QVariantList &values)
++template <>
++QString sparqlPropertyStatmentString<QMailAccountKey::Property>(const QString& uri, QMailAccountKey::Property property)
+{
-+ const AccountKeyArgumentExtractor extractor(a);
-+
-+ switch (a.property)
++ /*
++ * TBD: Complete this function with all properties description.
++ */
++ switch (property)
+ {
-+ case QMailAccountKey::Id:
-+ values += extractor.id();
-+ break;
++ case QMailAccountKey::Id:
++ return QString();
+
-+ case QMailAccountKey::Name:
-+ values += extractor.name();
-+ break;
++ case QMailAccountKey::Name:
++ return QString("%1 nmo:accountName %2 .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailAccountKey::MessageType:
-+ values += extractor.messageType();
-+ break;
++ case QMailAccountKey::MessageType:
++ return QString();
+
-+ case QMailAccountKey::FromAddress:
-+ values += extractor.fromAddress();
-+ break;
++ case QMailAccountKey::FromAddress:
++ return QString("%1 nmo:fromAddress [ rdf:type nco:EmailAddress ; nco:emailAddress %2 ] .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailAccountKey::Status:
-+ values += extractor.status();
-+ break;
++ case QMailAccountKey::Status:
++ return QString("%1 nmo:status %2 .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailAccountKey::Custom:
-+ values += extractor.custom();
-+ break;
++ case QMailAccountKey::Custom:
++ return QString();
++
++ default:
++ Q_ASSERT(false);
+ }
++ return QString();
+}
+
-+
-+// Class to extract data from records of the mailfolders table
-+class FolderRecord : public RecordExtractorBase<QMailFolderKey::Property>
++template <>
++QString sparqlPropertyStatmentString<QMailMessageSortKey::Property>(const QString& uri, QMailMessageSortKey::Property property)
+{
-+public:
-+ FolderRecord(const QSqlRecord &r)
-+ : RecordExtractorBase<QMailFolderKey::Property>(r) {}
-+
-+ QMailFolderId id() const { return QMailFolderId(value<quint64>(QMailFolderKey::Id)); }
-+
-+ QString path() const { return value<QString>(QMailFolderKey::Path); }
-+
-+ QMailFolderId parentFolderId() const { return QMailFolderId(value<quint64>(QMailFolderKey::ParentFolderId)); }
-+
-+ QMailAccountId parentAccountId() const { return QMailAccountId(value<quint64>(QMailFolderKey::ParentAccountId)); }
-+
-+ QString displayName() const { return value<QString>(QMailFolderKey::DisplayName); }
-+
-+ quint64 status() const { return value<quint64>(QMailFolderKey::Status); }
-+
-+ uint serverCount() const { return value<uint>(QMailFolderKey::ServerCount); }
-+
-+ uint serverUnreadCount() const { return value<uint>(QMailFolderKey::ServerUnreadCount); }
-+
-+private:
-+ int fieldIndex(const QString &field, int props) const
++ /*
++ * TBD: Complete this function with all properties description.
++ */
++ switch (property)
+ {
-+ return mappedFieldIndex(field, props, _fieldIndex);
-+ }
++ case QMailMessageSortKey::Id:
++ return QString();
+
-+ static QMap<int, QMap<QString, int> > _fieldIndex;
-+};
++ case QMailMessageSortKey::Type:
++ return QString();
+
-+QMap<int, QMap<QString, int> > FolderRecord::_fieldIndex;
++ case QMailMessageSortKey::ParentFolderId:
++ return QString("%1 nie:isLogicalPartOf %2 .").arg(uri).arg(propertyNameString(property));
+
++ case QMailMessageSortKey::Sender:
++ return QString("%1 nmo:sender [ rdf:type nco:Contact ; nco:hasEmailAddress %2 ] .").arg(uri).arg(propertyNameString(property));
+
-+// Class to convert QMailFolderKey argument values to SQL bind values
-+class FolderKeyArgumentExtractor : public ArgumentExtractorBase<QMailFolderKey>
-+{
-+public:
-+ FolderKeyArgumentExtractor(const QMailFolderKey::ArgumentType &a)
-+ : ArgumentExtractorBase<QMailFolderKey>(a) {}
++ case QMailMessageSortKey::Recipients:
++ return QString("%1 nmo:recipient [ rdf:type nco:Contact ; nco:hasEmailAddress %2 ] .").arg(uri).arg(propertyNameString(property));
+
-+ QVariantList id() const { return idValues<QMailFolderKey>(); }
++ case QMailMessageSortKey::Subject:
++ return QString("%1 nmo:messageSubject %2 .").arg(uri).arg(propertyNameString(property));
+
-+ QVariantList path() const { return stringValues(); }
++ case QMailMessageSortKey::TimeStamp:
++ return QString("%1 nmo:sentDate %2 .").arg(uri).arg(propertyNameString(property));
+
-+ QVariantList parentFolderId() const { return idValues<QMailFolderKey>(); }
++ case QMailMessageSortKey::Status:
++ return QString("%1 nmo:status %2 .").arg(uri).arg(propertyNameString(property));
+
-+ QVariantList ancestorFolderIds() const { return idValues<QMailFolderKey>(); }
++ case QMailMessageSortKey::ReceptionTimeStamp:
++ return QString();
+
-+ QVariantList parentAccountId() const { return idValues<QMailAccountKey>(); }
++ case QMailMessageSortKey::ServerUid:
++ return QString("%1 nmo:messageId %2 .").arg(uri).arg(propertyNameString(property));
+
-+ QVariantList displayName() const { return stringValues(); }
++ case QMailMessageSortKey::Size:
++ return QString("%1 nie:contentSize %2 .").arg(uri).arg(propertyNameString(property));
+
-+ QVariant status() const { return quint64Value(); }
++ case QMailMessageSortKey::ParentAccountId:
++ return QString("%1 nie:relatedTo %2 .").arg(uri).arg(propertyNameString(property));
+
-+ QVariant serverCount() const { return intValue(); }
++ case QMailMessageSortKey::ContentType:
++ return QString();
+
-+ QVariant serverUnreadCount() const { return intValue(); }
++ case QMailMessageSortKey::PreviousParentFolderId:
++ return QString();
+
-+ QVariantList custom() const { return customValues(); }
-+};
++ default:
++ Q_ASSERT(false);
++ }
++ return QString();
++}
+
-+template<>
-+void appendWhereValues<QMailFolderKey::ArgumentType>(const QMailFolderKey::ArgumentType &a, QVariantList &values)
++template <>
++QString sparqlPropertyStatmentString<QMailFolderSortKey::Property>(const QString& uri, QMailFolderSortKey::Property property)
+{
-+ const FolderKeyArgumentExtractor extractor(a);
-+
-+ switch (a.property)
++ /*
++ * TBD: Complete this function with all properties description.
++ */
++ switch (property)
+ {
-+ case QMailFolderKey::Id:
-+ values += extractor.id();
-+ break;
-+
-+ case QMailFolderKey::Path:
-+ values += extractor.path();
-+ break;
++ case QMailFolderSortKey::Id:
++ return "id";
+
-+ case QMailFolderKey::ParentFolderId:
-+ values += extractor.parentFolderId();
-+ break;
++ case QMailFolderSortKey::Path:
++ return QString("%1 nmo:folderName %2 .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailFolderKey::AncestorFolderIds:
-+ values += extractor.ancestorFolderIds();
-+ break;
++ case QMailFolderSortKey::ParentFolderId:
++ return QString("%1 nie:isLogicalPartOf %2 .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailFolderKey::ParentAccountId:
-+ values += extractor.parentAccountId();
-+ break;
++ case QMailFolderSortKey::ParentAccountId:
++ return QString("%1 nie:relatedTo %2 .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailFolderKey::DisplayName:
-+ values += extractor.displayName();
-+ break;
++ case QMailFolderSortKey::DisplayName:
++ return QString("%1 nmo:folderDisplayName %2 .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailFolderKey::Status:
-+ values += extractor.status();
-+ break;
++ case QMailFolderSortKey::Status:
++ return QString("%1 nmo:status %2 .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailFolderKey::ServerCount:
-+ values += extractor.serverCount();
-+ break;
++ case QMailFolderSortKey::ServerCount:
++ return QString("%1 nmo:serverCount %2 .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailFolderKey::ServerUnreadCount:
-+ values += extractor.serverUnreadCount();
-+ break;
++ case QMailFolderSortKey::ServerUnreadCount:
++ return QString("%1 nmo:serverUnreadCount %2 .").arg(uri).arg(propertyNameString(property));
+
-+ case QMailFolderKey::Custom:
-+ values += extractor.custom();
-+ break;
++ default:
++ Q_ASSERT(false);
+ }
++ return QString();
+}
+
-+
-+// Class to extract data from records of the deletedmessages table
-+class MessageRemovalRecord : public RecordExtractorBase<int>
++template <>
++QString sparqlPropertyStatmentString<QMailAccountSortKey::Property>(const QString& uri, QMailAccountSortKey::Property property)
+{
-+public:
-+ MessageRemovalRecord(const QSqlRecord &r)
-+ : RecordExtractorBase<int>(r) {}
-+
-+ quint64 id() const { return value<quint64>("id"); }
-+
-+ QMailAccountId parentAccountId() const { return QMailAccountId(value<quint64>("parentaccountid")); }
-+
-+ QString serverUid() const { return value<QString>("serveruid"); }
-+
-+ QMailFolderId parentFolderId() const { return QMailFolderId(value<quint64>("parentfolderid")); }
-+
-+private:
-+ int fieldIndex(const QString &field, int props) const
++ /*
++ * TBD: Complete this function with all properties description.
++ */
++ switch (property)
+ {
-+ return mappedFieldIndex(field, props, _fieldIndex);
-+ }
++ case QMailAccountSortKey::Id:
++ return QString();
+
-+ static QMap<int, QMap<QString, int> > _fieldIndex;
-+};
++ case QMailAccountSortKey::Name:
++ return QString("%1 nmo:accountName %2 .").arg(uri).arg(propertyNameString(property));
+
-+QMap<int, QMap<QString, int> > MessageRemovalRecord::_fieldIndex;
++ case QMailAccountSortKey::MessageType:
++ return QString();
+
++ case QMailAccountSortKey::Status:
++ return QString("%1 nmo:status %2 .").arg(uri).arg(propertyNameString(property));
+
-+static QString incrementAlias(const QString &alias)
-+{
-+ QRegExp aliasPattern("([a-z]+)([0-9]+)");
-+ if (aliasPattern.exactMatch(alias)) {
-+ return aliasPattern.cap(1) + QString::number(aliasPattern.cap(2).toInt() + 1);
++ default:
++ Q_ASSERT(false);
+ }
-+
+ return QString();
+}
+
-+template<typename ArgumentListType>
-+QString buildOrderClause(const ArgumentListType &list, const QString &alias)
++template <class Key, class SortKey>
++QString keyStatment(const QString& uri, const Key& key, const SortKey& sort = SortKey())
+{
-+ if (list.isEmpty())
-+ return QString();
-+
-+ QStringList sortColumns;
-+ foreach (typename ArgumentListType::const_reference arg, list)
-+ sortColumns.append(fieldName(arg.first, alias) + ' ' + (arg.second == Qt::AscendingOrder ? "ASC" : "DESC"));
-+
-+ return QString(" ORDER BY ") + sortColumns.join(",");
-+}
-+
++ typedef typename Key::ArgumentType ArgumentType;
++ typedef typename SortKey::ArgumentType SortArgumentType;
+
-+QString operatorString(QMailKey::Comparator op, bool multipleArgs = false, bool patternMatch = false, bool bitwiseMultiples = false)
-+{
-+ switch (op)
++ QStringList arguments;
++ foreach (SortArgumentType argument, sort.arguments())
+ {
-+ case Equal:
-+ return (multipleArgs ? " IN " : (patternMatch ? " LIKE " : " = "));
-+ break;
-+
-+ case NotEqual:
-+ return (multipleArgs ? " NOT IN " : (patternMatch ? " NOT LIKE " : " <> "));
-+ break;
-+
-+ case LessThan:
-+ return " < ";
-+ break;
-+
-+ case LessThanEqual:
-+ return " <= ";
-+ break;
-+
-+ case GreaterThan:
-+ return " > ";
-+ break;
-+
-+ case GreaterThanEqual:
-+ return " >= ";
-+ break;
-+
-+ case Includes:
-+ case Present:
-+ return (multipleArgs ? " IN " : (bitwiseMultiples ? " & " : " LIKE "));
-+ break;
++ QString statement = sparqlPropertyStatmentString(uri, argument.first);
++ if (!arguments.contains(statement))
++ arguments << statement;
++ }
+
-+ case Excludes:
-+ case Absent:
-+ // Note: the result is not correct in the bitwiseMultiples case!
-+ return (multipleArgs ? " NOT IN " : (bitwiseMultiples ? " & " : " NOT LIKE "));
-+ break;
++ foreach (ArgumentType argument, key.arguments())
++ {
++ QString statement = sparqlPropertyStatmentString(uri, argument.property);
++ if (!arguments.contains(statement))
++ arguments << statement;
+ }
+
-+ return QString();
++ foreach (const Key& subkey, key.subKeys())
++ arguments << keyStatment(uri, subkey, SortKey());
++
++ return arguments.join("\n");
+}
+
-+QString combineOperatorString(QMailKey::Combiner op)
++QString argumentValue(const QVariant& value)
+{
-+ switch (op)
-+ {
-+ case And:
-+ return " AND ";
-+ break;
-+
-+ case Or:
-+ return " OR ";
-+ break;
-+
-+ case None:
-+ break;
++ if (qVariantCanConvert<QMailAccountId>(value))
++ return MailAccountUri(qVariantValue<QMailAccountId>(value));
++ else if (qVariantCanConvert<QMailFolderId>(value))
++ return MailFolderUri(qVariantValue<QMailFolderId>(value));
++ else if (qVariantCanConvert<QMailMessageId>(value))
++ return MailMessageUri(qVariantValue<QMailMessageId>(value));
++ else if (qVariantCanConvert<QString>(value))
++ return qVariantValue<QString>(value);
++ else if (qVariantCanConvert<int>(value))
++ return QString::number(qVariantValue<int>(value));
++ else {
++ Q_ASSERT(false);
+ }
-+
+ return QString();
+}
+
-+QString columnExpression(const QString &column, QMailKey::Comparator op, const QString &value, bool multipleArgs = false, bool patternMatch = false, bool bitwiseMultiples = false)
++template <class ArgumentType>
++QString keyArgument(const ArgumentType& argument)
+{
-+ QString operation(operatorString(op, multipleArgs, patternMatch, bitwiseMultiples));
++ typedef typename ArgumentType::Property Property;
++ typedef typename ArgumentType::Comparator Comparator;
+
-+ QString expression(column + operation);
++ QString pattern = operatorString(argument.op, argument.valueList.count());
++ pattern = pattern.arg(propertyNameString(argument.property));
+
-+ // Special case handling:
-+ if (bitwiseMultiples && (op == QMailKey::Excludes)) {
-+ if (!value.isEmpty()) {
-+ return "0 = (" + expression + value + ")";
-+ } else {
-+ return "0 = " + expression;
-+ }
-+ }
++ foreach (QVariant value, argument.valueList)
++ pattern = pattern.arg(argumentValue(value));
+
-+ return expression + value;
++ return pattern;
+}
+
-+QString columnExpression(const QString &column, QMailKey::Comparator op, const QVariantList &valueList, bool patternMatch = false, bool bitwiseMultiples = false)
++template <class Key>
++QString keyFilter(const Key& key)
+{
-+ QString value(QMailStorePrivate::expandValueList(valueList));
-+
-+ return columnExpression(column, op, value, (valueList.count() > 1), patternMatch, bitwiseMultiples);
-+}
++ typedef typename Key::ArgumentType ArgumentType;
+
-+QString baseExpression(const QString &column, QMailKey::Comparator op, bool multipleArgs = false, bool patternMatch = false, bool bitwiseMultiples = false)
-+{
-+ return columnExpression(column, op, QString(), multipleArgs, patternMatch, bitwiseMultiples);
-+}
++ QStringList arguments;
++ foreach (ArgumentType argument, key.arguments())
++ arguments << keyArgument<ArgumentType>(argument);
+
++ foreach (const Key& subkey, key.subKeys())
++ arguments << keyFilter<Key>(subkey);
+
-+template<typename Key>
-+QString whereClauseItem(const Key &key, const typename Key::ArgumentType &arg, const QString &alias, const QMailStorePrivate &store);
++ QString filter = arguments.size() > 1 ? QString(key.isNegated() ? "!(%1)" : "(%1)") :
++ QString(key.isNegated() ? "!(%1)" : "%1");
++ return filter.arg(arguments.join(combineOperatorString(key.combiner())));
++}
+
-+template<>
-+QString whereClauseItem<QMailAccountKey>(const QMailAccountKey &, const QMailAccountKey::ArgumentType &a, const QString &alias, const QMailStorePrivate &store)
++template <class SortKey>
++QString sortKey(const SortKey& sortKey)
+{
-+ QString item;
-+ {
-+ QTextStream q(&item);
-+
-+ QString columnName = fieldName(a.property, alias);
-+
-+ bool bitwise((a.property == QMailAccountKey::Status) || (a.property == QMailAccountKey::MessageType));
-+ bool patternMatching(a.property == QMailAccountKey::FromAddress);
-+
-+ QString expression = columnExpression(columnName, a.op, a.valueList, patternMatching, bitwise);
-+
-+ switch(a.property)
-+ {
-+ case QMailAccountKey::Id:
-+ if (a.valueList.first().canConvert<QMailAccountKey>()) {
-+ QMailAccountKey subKey = a.valueList.first().value<QMailAccountKey>();
-+ QString nestedAlias(incrementAlias(alias));
-+
-+ // Expand comparison to sub-query result
-+ q << baseExpression(columnName, a.op, true) << "( SELECT " << qualifiedName("id", nestedAlias) << " FROM mailaccounts " << nestedAlias;
-+ q << store.buildWhereClause(QMailStorePrivate::Key(subKey, nestedAlias)) << ")";
-+ } else {
-+ q << expression;
-+ }
-+ break;
-+
-+ case QMailAccountKey::Custom:
-+ // Match on custom field
-+ {
-+ QString nestedAlias(incrementAlias(alias));
++ typedef typename SortKey::ArgumentType ArgumentType;
+
-+ // Is this an existence test or a value test?
-+ if ((a.op == QMailKey::Present) || (a.op == QMailKey::Absent)) {
-+ q << qualifiedName("id", alias) << operatorString(a.op, true) << "( SELECT " << qualifiedName("id", nestedAlias);
-+ q << " FROM mailaccountcustom " << nestedAlias << " WHERE name=? )";
-+ } else {
-+ q << qualifiedName("id", alias) << " IN ( SELECT " << qualifiedName("id", nestedAlias); q << " FROM mailaccountcustom " << nestedAlias;
-+ q << " WHERE " << qualifiedName("name", nestedAlias) << "=? AND " << qualifiedName("value", nestedAlias) << operatorString(a.op, false) << "? )";
-+ }
-+ }
-+ break;
++ QString orderCondition;
++ foreach (ArgumentType argument, sortKey.arguments())
++ if (argument.second == Qt::AscendingOrder)
++ orderCondition += QString(" ASC(%1)").arg(propertyNameString(argument.first));
++ else
++ orderCondition += QString(" DESC(%1)").arg(propertyNameString(argument.first));
+
-+ case QMailAccountKey::Status:
-+ case QMailAccountKey::MessageType:
-+ case QMailAccountKey::Name:
-+ case QMailAccountKey::FromAddress:
++ if (!orderCondition.isEmpty())
++ return QString("ORDER BY %1").arg(orderCondition);
+
-+ q << expression;
-+ break;
-+ }
-+ }
-+ return item;
++ return QString();
+}
+
-+template<>
-+QString whereClauseItem<QMailMessageKey>(const QMailMessageKey &key, const QMailMessageKey::ArgumentType &a, const QString &alias, const QMailStorePrivate &store)
++QString keyQuery(const QMailMessageKey& key, const QMailMessageSortKey& sort = QMailMessageSortKey())
+{
-+ QString item;
-+ {
-+ QTextStream q(&item);
-+
-+ QString columnName = fieldName(a.property, alias);
-+
-+ bool bitwise((a.property == QMailMessageKey::Type) || (a.property == QMailMessageKey::Status));
-+ bool patternMatching((a.property == QMailMessageKey::Sender) || (a.property == QMailMessageKey::Recipients) ||
-+ (a.property == QMailMessageKey::ContentScheme) || (a.property == QMailMessageKey::ContentIdentifier));
-+
-+ QString expression = columnExpression(columnName, a.op, a.valueList, patternMatching, bitwise);
-+
-+ switch(a.property)
-+ {
-+ case QMailMessageKey::Id:
-+ if (a.valueList.count() >= IdLookupThreshold) {
-+ q << baseExpression(columnName, a.op, true) << "( SELECT id FROM " << QMailStorePrivate::temporaryTableName(key) << ")";
-+ } else {
-+ if (a.valueList.first().canConvert<QMailMessageKey>()) {
-+ QMailMessageKey subKey = a.valueList.first().value<QMailMessageKey>();
-+ QString nestedAlias(incrementAlias(alias));
-+
-+ // Expand comparison to sub-query result
-+ q << baseExpression(columnName, a.op, true) << "( SELECT " << qualifiedName("id", nestedAlias) << " FROM mailmessages " << nestedAlias;
-+ q << store.buildWhereClause(QMailStorePrivate::Key(subKey, nestedAlias)) << ")";
-+ } else {
-+ q << expression;
-+ }
-+ }
-+ break;
-+
-+ case QMailMessageKey::ParentFolderId:
-+ case QMailMessageKey::PreviousParentFolderId:
-+ if(a.valueList.first().canConvert<QMailFolderKey>()) {
-+ QMailFolderKey parentFolderKey = a.valueList.first().value<QMailFolderKey>();
-+ QString nestedAlias(incrementAlias(alias));
-+
-+ q << baseExpression(columnName, a.op, true) << "( SELECT " << qualifiedName("id", nestedAlias) << " FROM mailfolders " << nestedAlias;
-+ q << store.buildWhereClause(QMailStorePrivate::Key(parentFolderKey, nestedAlias)) << ")";
-+ } else {
-+ q << expression;
-+ }
-+ break;
-+
-+ case QMailMessageKey::AncestorFolderIds:
-+ if (a.valueList.first().canConvert<QMailFolderKey>()) {
-+ QMailFolderKey folderSubKey = a.valueList.first().value<QMailFolderKey>();
-+ QString nestedAlias(incrementAlias(alias));
-+
-+ q << baseExpression(fieldName(QMailMessageKey::ParentFolderId, alias), a.op, true);
-+ q << "( SELECT DISTINCT descendantid FROM mailfolderlinks WHERE id IN ( SELECT " << qualifiedName("id", nestedAlias) << " FROM mailfolders" << nestedAlias;
-+ q << store.buildWhereClause(QMailStorePrivate::Key(folderSubKey, nestedAlias)) << ") )";
-+ } else {
-+ q << baseExpression(fieldName(QMailMessageKey::ParentFolderId, alias), a.op, true) << "( SELECT DISTINCT descendantid FROM mailfolderlinks WHERE id";
-+ if (a.valueList.count() > 1) {
-+ q << " IN " << QMailStorePrivate::expandValueList(a.valueList) << ")";
-+ } else {
-+ q << "=? )";
-+ }
-+ }
-+ break;
-+
-+ case QMailMessageKey::ParentAccountId:
-+ if(a.valueList.first().canConvert<QMailAccountKey>()) {
-+ QMailAccountKey parentAccountKey = a.valueList.first().value<QMailAccountKey>();
-+ QString nestedAlias(incrementAlias(alias));
++ QString query("SELECT ?mail \n"
++ "WHERE { \n"
++ "?mail rdf:type nmo:Email . \n"
++ "%1"
++ "%2"
++ "} %3\n");
+
-+ q << baseExpression(columnName, a.op, true) << "( SELECT " << qualifiedName("id", nestedAlias) << " FROM mailaccounts " << nestedAlias;
-+ q << store.buildWhereClause(QMailStorePrivate::Key(parentAccountKey, nestedAlias)) << ")";
-+ } else {
-+ q << expression;
-+ }
-+ break;
++ QString statement = keyStatment("?mail", key, sort);
++ if (!statement.isEmpty())
++ statement = QString("%1 \n").arg(statement);
+
-+ case QMailMessageKey::Custom:
-+ // Match on custom field
-+ {
-+ QString nestedAlias(incrementAlias(alias));
++ QString filter;
++ if (!key.isEmpty())
++ filter = QString("FILTER %1 \n").arg(keyFilter(key));
+
-+ // Is this an existence test or a value test?
-+ if ((a.op == QMailKey::Present) || (a.op == QMailKey::Absent)) {
-+ q << qualifiedName("id", alias) << operatorString(a.op, true) << "( SELECT " << qualifiedName("id", nestedAlias);
-+ q << " FROM mailmessagecustom " << nestedAlias << " WHERE name=? )";
-+ } else {
-+ q << qualifiedName("id", alias) << " IN ( SELECT " << qualifiedName("id", nestedAlias); q << " FROM mailmessagecustom " << nestedAlias;
-+ q << " WHERE " << qualifiedName("name", nestedAlias) << "=? AND " << qualifiedName("value", nestedAlias) << operatorString(a.op, false) << "? )";
-+ }
-+ }
-+ break;
++ return query.arg(statement).arg(filter).arg(sortKey(sort));
++}
+
-+ case QMailMessageKey::InResponseTo:
-+ if (a.valueList.first().canConvert<QMailMessageKey>()) {
-+ QMailMessageKey messageKey = a.valueList.first().value<QMailMessageKey>();
-+ QString nestedAlias(incrementAlias(alias));
++QString keyQuery(const QMailFolderKey& key, const QMailFolderSortKey& sort = QMailFolderSortKey())
++{
++ QString query("SELECT ?folder \n"
++ "WHERE { \n"
++ "?folder rdf:type nmo:MailFolder . \n"
++ "%1"
++ "%2"
++ "} %3\n");
+
-+ q << baseExpression(columnName, a.op, true) << "( SELECT " << qualifiedName("id", nestedAlias) << " FROM mailmessages " << nestedAlias;
-+ q << store.buildWhereClause(QMailStorePrivate::Key(messageKey, nestedAlias)) << ")";
-+ } else {
-+ q << expression;
-+ }
-+ break;
++ QString statement = keyStatment("?folder", key, sort);
++ if (!statement.isEmpty())
++ statement = QString("%1 \n").arg(statement);
+
-+ case QMailMessageKey::Type:
-+ case QMailMessageKey::Status:
-+ case QMailMessageKey::Sender:
-+ case QMailMessageKey::Recipients:
-+ case QMailMessageKey::Subject:
-+ case QMailMessageKey::TimeStamp:
-+ case QMailMessageKey::ReceptionTimeStamp:
-+ case QMailMessageKey::ServerUid:
-+ case QMailMessageKey::Size:
-+ case QMailMessageKey::ContentType:
-+ case QMailMessageKey::ContentScheme:
-+ case QMailMessageKey::ContentIdentifier:
-+ case QMailMessageKey::ResponseType:
-+ q << expression;
-+ break;
++ QString filter;
++ if (!key.isEmpty())
++ filter = QString("FILTER %1 \n").arg(keyFilter(key));
+
-+ case QMailMessageKey::Conversation:
-+ // TODO: Not yet implemented
-+ break;
-+ }
-+ }
-+ return item;
++ return query.arg(statement).arg(filter).arg(sortKey(sort));
+}
+
-+template<>
-+QString whereClauseItem<QMailFolderKey>(const QMailFolderKey &, const QMailFolderKey::ArgumentType &a, const QString &alias, const QMailStorePrivate &store)
++QString keyQuery(const QMailAccountKey& key, const QMailAccountSortKey& sort = QMailAccountSortKey())
+{
-+ QString item;
-+ {
-+ QTextStream q(&item);
-+
-+ QString columnName(fieldName(a.property, alias));
-+
-+ bool bitwise(a.property == QMailFolderKey::Status);
-+ QString expression = columnExpression(columnName, a.op, a.valueList, false, bitwise);
-+
-+ switch (a.property)
-+ {
-+ case QMailFolderKey::Id:
-+ if (a.valueList.first().canConvert<QMailFolderKey>()) {
-+ QMailFolderKey subKey = a.valueList.first().value<QMailFolderKey>();
-+ QString nestedAlias(incrementAlias(alias));
++ QString query("SELECT ?account \n"
++ "WHERE { \n"
++ "?account rdf:type nmo:Mailbox . \n"
++ "%1"
++ "%2"
++ "} %3\n");
+
-+ // Expand comparison to sub-query result
-+ q << baseExpression(columnName, a.op, true) << "( SELECT " << qualifiedName("id", nestedAlias) << " FROM mailfolders " << nestedAlias;
-+ q << store.buildWhereClause(QMailStorePrivate::Key(subKey, nestedAlias)) << ")";
-+ } else {
-+ q << expression;
-+ }
-+ break;
++ QString statement = keyStatment("?account", key, sort);
++ if (!statement.isEmpty())
++ statement = QString("%1 \n").arg(statement);
+
-+ case QMailFolderKey::ParentFolderId:
-+ if(a.valueList.first().canConvert<QMailFolderKey>()) {
-+ QMailFolderKey folderSubKey = a.valueList.first().value<QMailFolderKey>();
-+ QString nestedAlias(incrementAlias(alias));
++ QString filter;
++ if (!key.isEmpty())
++ filter = QString("FILTER %1 \n").arg(keyFilter(key));
+
-+ q << baseExpression(columnName, a.op, true) << "( SELECT " << qualifiedName("id", nestedAlias) << " FROM mailfolders " << nestedAlias;
-+ q << store.buildWhereClause(QMailStorePrivate::Key(folderSubKey, nestedAlias)) << ")";
-+ } else {
-+ q << expression;
-+ }
-+ break;
++ return query.arg(statement).arg(filter).arg(sortKey(sort));
++}
+
-+ case QMailFolderKey::AncestorFolderIds:
-+ if (a.valueList.first().canConvert<QMailFolderKey>()) {
-+ QMailFolderKey folderSubKey = a.valueList.first().value<QMailFolderKey>();
-+ QString nestedAlias(incrementAlias(alias));
++QString keyCount(const QMailMessageKey& key)
++{
++ QString query("SELECT COUNT(?mail) AS count \n"
++ "WHERE { \n"
++ "?mail rdf:type nmo:Email . \n"
++ "%1"
++ "%2"
++ "}\n");
+
-+ q << baseExpression(fieldName(QMailFolderKey::Id, alias), a.op, true);
-+ q << "( SELECT DISTINCT descendantid FROM mailfolderlinks WHERE id IN ( SELECT " << qualifiedName("id", nestedAlias) << " FROM mailfolders" << nestedAlias;
-+ q << store.buildWhereClause(QMailStorePrivate::Key(folderSubKey, nestedAlias)) << ") )";
-+ } else {
-+ q << baseExpression(fieldName(QMailFolderKey::Id, alias), a.op, true) << "( SELECT DISTINCT descendantid FROM mailfolderlinks WHERE id";
-+ if (a.valueList.count() > 1) {
-+ q << " IN " << QMailStorePrivate::expandValueList(a.valueList) << ")";
-+ } else {
-+ q << "=? )";
-+ }
-+ }
-+ break;
++ QString statement = keyStatment("?mail", key, QMailAccountSortKey());
++ if (!statement.isEmpty())
++ statement = QString("%1 \n").arg(statement);
+
-+ case QMailFolderKey::ParentAccountId:
-+ if(a.valueList.first().canConvert<QMailAccountKey>()) {
-+ QMailAccountKey accountSubKey = a.valueList.first().value<QMailAccountKey>();
-+ QString nestedAlias(incrementAlias(alias));
++ QString filter;
++ if (!key.isEmpty())
++ filter = QString("FILTER %1 \n").arg(keyFilter(key));
+
-+ q << baseExpression(columnName, a.op, true) << "( SELECT " << qualifiedName("id", nestedAlias) << " FROM mailaccounts " << nestedAlias;
-+ q << store.buildWhereClause(QMailStorePrivate::Key(accountSubKey, nestedAlias)) << ")";
-+ } else {
-+ q << expression;
-+ }
-+ break;
++ return query.arg(statement).arg(filter);
++}
+
-+ case QMailFolderKey::Custom:
-+ // Match on custom field
-+ {
-+ QString nestedAlias(incrementAlias(alias));
++QString keyCount(const QMailFolderKey& key)
++{
++ QString query("SELECT COUNT(?folder) AS count \n"
++ "WHERE { \n"
++ "?folder rdf:type nmo:MailFolder . \n"
++ "%1"
++ "%2"
++ "}\n");
+
-+ // Is this an existence test or a value test?
-+ if ((a.op == QMailKey::Present) || (a.op == QMailKey::Absent)) {
-+ q << qualifiedName("id", alias) << operatorString(a.op, true) << "( SELECT " << qualifiedName("id", nestedAlias);
-+ q << " FROM mailfoldercustom " << nestedAlias << " WHERE name=? )";
-+ } else {
-+ q << qualifiedName("id", alias) << " IN ( SELECT " << qualifiedName("id", nestedAlias); q << " FROM mailfoldercustom " << nestedAlias;
-+ q << " WHERE " << qualifiedName("name", nestedAlias) << "=? AND " << qualifiedName("value", nestedAlias) << operatorString(a.op, false) << "? )";
-+ }
-+ }
-+ break;
++ QString statement = keyStatment("?folder", key, QMailAccountSortKey());
++ if (!statement.isEmpty())
++ statement = QString("%1 \n").arg(statement);
+
-+ case QMailFolderKey::Status:
-+ case QMailFolderKey::Path:
-+ case QMailFolderKey::DisplayName:
-+ case QMailFolderKey::ServerCount:
-+ case QMailFolderKey::ServerUnreadCount:
++ QString filter;
++ if (!key.isEmpty())
++ filter = QString("FILTER %1 \n").arg(keyFilter(key));
+
-+ q << expression;
-+ break;
-+ }
-+ }
-+ return item;
++ return query.arg(statement).arg(filter);
+}
+
-+template<typename KeyType, typename ArgumentListType, typename KeyListType, typename CombineType>
-+QString buildWhereClause(const KeyType &key,
-+ const ArgumentListType &args,
-+ const KeyListType &subKeys,
-+ CombineType combine,
-+ bool negated,
-+ bool nested,
-+ bool firstClause,
-+ const QString &alias,
-+ const QMailStorePrivate& store)
++QString keyCount(const QMailAccountKey& key)
+{
-+ QString whereClause;
-+ QString logicalOpString(combineOperatorString(combine));
++ QString query("SELECT COUNT(?account) AS count \n"
++ "WHERE { \n"
++ "?account rdf:type nmo:Mailbox . \n"
++ "%1"
++ "%2"
++ "}\n");
+
-+ if (!key.isEmpty()) {
-+ QTextStream s(&whereClause);
++ QString statement = keyStatment("?account", key, QMailAccountSortKey());
++ if (!statement.isEmpty())
++ statement = QString("%1 \n").arg(statement);
+
-+ QString op = " ";
-+ foreach (typename ArgumentListType::const_reference a, args) {
-+ s << op << whereClauseItem(key, a, alias, store);
-+ op = logicalOpString;
-+ }
++ QString filter;
++ if (!key.isEmpty())
++ filter = QString("FILTER %1 \n").arg(keyFilter(key));
+
-+ // subkeys
-+ s.flush();
-+ if (whereClause.isEmpty())
-+ op = " ";
++ return query.arg(statement).arg(filter);
++}
+
-+ foreach (typename KeyListType::const_reference subkey, subKeys) {
-+ QString nestedWhere(store.buildWhereClause(QMailStorePrivate::Key(subkey, alias), true));
-+ if (!nestedWhere.isEmpty())
-+ s << op << " (" << nestedWhere << ") ";
++template <class Key>
++void debugKey(const Key& key)
++{
++ typedef typename Key::ArgumentType ArgumentType;
+
-+ op = logicalOpString;
-+ }
-+ }
++ qDebug() << "Key Combiner:" << key.combiner();
++ qDebug() << "Key Is empty:" << key.isEmpty();
++ qDebug() << "Key Non Matching:" << key.isNonMatching();
++ qDebug() << "Key Is Negated:" << key.isNegated();
+
-+ // Finalise the where clause
-+ if (!whereClause.isEmpty()) {
-+ if (negated) {
-+ whereClause = " NOT (" + whereClause + ")";
-+ }
-+ if (!nested) {
-+ whereClause.prepend(firstClause ? " WHERE " : " AND ");
-+ }
++ foreach (ArgumentType argument, key.arguments())
++ {
++ qDebug() << "Argument Property:" << argument.property;
++ qDebug() << "Argument Comparator:" << argument.op;
++ foreach (QVariant value, argument.valueList)
++ qDebug() << "Argument Value List:" << value;
+ }
+
-+ return whereClause;
-+}
-+
-+QPair<QString, qint64> tableInfo(const QString &name, qint64 version)
-+{
-+ return qMakePair(name, version);
-+}
-+
-+QPair<quint64, QString> folderInfo(QMailFolder::StandardFolder id, const QString &name)
-+{
-+ return qMakePair(static_cast<quint64>(id), name);
++ foreach (const Key& subkey, key.subKeys())
++ debugKey(subkey);
+}
+
-+/* SPARQL CODE */
+QString nmoRecipients(const QList<QMailAddress>& recipients)
+{
+ QString result;
@@ -2331,181 +1659,8 @@ index 0000000..029ca4e
+ return T();
+}
+
-+QString comparator(QMailKey::Comparator comparator)
-+{
-+ static QMap<QMailKey::Comparator, QString> comparatorMap;
-+ comparatorMap.insert(QMailKey::LessThan, "<");
-+ comparatorMap.insert(QMailKey::LessThanEqual, "<-");
-+ comparatorMap.insert(QMailKey::GreaterThan, ">");
-+ comparatorMap.insert(QMailKey::GreaterThanEqual, ">=");
-+ comparatorMap.insert(QMailKey::Equal, "=");
-+ comparatorMap.insert(QMailKey::NotEqual, "!=");
-+ comparatorMap.insert(QMailKey::Includes, "IN");
-+ comparatorMap.insert(QMailKey::Excludes, "NOT IN");
-+ comparatorMap.insert(QMailKey::Present, "EXISTS");
-+ comparatorMap.insert(QMailKey::Absent, "NOT EXISTS");
-+
-+ return comparatorMap.value(comparator);
-+}
-+
-+QString messageConstraint(const QString& variable, const QMailMessageKey& key)
-+{
-+ QString constraint;
-+ foreach (QMailMessageKey::ArgumentType argument, key.arguments())
-+ {
-+ switch (argument.property)
-+ {
-+ case QMailMessageKey::Id:
-+ // Nothing to select
-+ break;
-+ case QMailMessageKey::Type:
-+ Q_ASSERT(false);
-+ break;
-+ case QMailMessageKey::ParentFolderId:
-+ constraint += QString(variable + " nie:isLogicalPartOf <qmf://groove.nokia.com/folder#%1> . \n").arg(argument.valueList.first().value<QMailFolderId>().toULongLong());
-+ break;
-+ case QMailMessageKey::Sender:
-+ Q_ASSERT(false);
-+ break;
-+ case QMailMessageKey::Recipients:
-+ Q_ASSERT(false);
-+ break;
-+ case QMailMessageKey::Subject:
-+ Q_ASSERT(false);
-+ break;
-+ case QMailMessageKey::TimeStamp:
-+ Q_ASSERT(false);
-+ break;
-+ case QMailMessageKey::Status:
-+ constraint += QString(variable + " nmo:status \"%1\" . \n").arg(argument.valueList.first().toULongLong());
-+ break;
-+ case QMailMessageKey::Conversation:
-+ Q_ASSERT(false);
-+ break;
-+ case QMailMessageKey::ReceptionTimeStamp:
-+ Q_ASSERT(false);
-+ break;
-+ case QMailMessageKey::ServerUid:
-+ Q_ASSERT(false);
-+ break;
-+ case QMailMessageKey::Size:
-+ Q_ASSERT(false);
-+ break;
-+ case QMailMessageKey::ParentAccountId:
-+ constraint += QString(variable + " nie:relatedTo <qmf://groove.nokia.com/accounts#%1> . \n").arg(argument.valueList.first().value<QMailAccountId>().toULongLong());
-+ break;
-+ case QMailMessageKey::AncestorFolderIds:
-+ Q_ASSERT(false);
-+ break;
-+ case QMailMessageKey::ContentType:
-+ Q_ASSERT(false);
-+ break;
-+ case QMailMessageKey::PreviousParentFolderId:
-+ Q_ASSERT(false);
-+ break;
-+ case QMailMessageKey::ContentScheme:
-+ Q_ASSERT(false);
-+ break;
-+ case QMailMessageKey::ContentIdentifier:
-+ Q_ASSERT(false);
-+ break;
-+ case QMailMessageKey::InResponseTo:
-+ Q_ASSERT(false);
-+ break;
-+ case QMailMessageKey::ResponseType:
-+ Q_ASSERT(false);
-+ break;
-+ case QMailMessageKey::Custom:
-+ Q_ASSERT(false);
-+ break;
-+
-+ default:
-+ Q_ASSERT(false);
-+ }
-+ }
-+ return " " + constraint;
-+}
-+
-+QString folderConstraint(const QString& variable, const QMailFolderKey& key)
-+{
-+ QString constraint;
-+ foreach (QMailFolderKey::ArgumentType argument, key.arguments())
-+ {
-+ switch (argument.property)
-+ {
-+ case QMailFolderKey::Id:
-+ // Nothing to select
-+ break;
-+ case QMailFolderKey::Path:
-+ constraint += QString(variable + " nmo:folderName \"%1\" . \n").arg(argument.valueList.first().toString());
-+ break;
-+ case QMailFolderKey::ParentFolderId:
-+ constraint += QString(variable + " nie:isLogicalPartOf <qmf://groove.nokia.com/folder#%1> . \n").arg(argument.valueList.first().value<QMailFolderId>().toULongLong());
-+ break;
-+ case QMailFolderKey::ParentAccountId:
-+ constraint += QString(variable + " nie:relatedTo <qmf://groove.nokia.com/accounts#%1> . \n").arg(argument.valueList.first().value<QMailAccountId>().toULongLong());
-+ break;
-+ case QMailFolderKey::DisplayName:
-+ constraint += QString(variable + " nmo:folderDisplayName \"%1\" . \n").arg(argument.valueList.first().toULongLong());
-+ break;
-+ case QMailFolderKey::Status:
-+ constraint += QString(variable + " nmo:status : \"%1\" . \n").arg(argument.valueList.first().toULongLong());
-+ break;
-+ case QMailFolderKey::AncestorFolderIds:
-+ Q_ASSERT(false);
-+ break;
-+ case QMailFolderKey::ServerCount:
-+ constraint += QString(variable + " nmo:serverCount \"%1\" . \n").arg(argument.valueList.first().toULongLong());
-+ break;
-+ case QMailFolderKey::ServerUnreadCount:
-+ constraint += QString(variable + " nmo:serverUnreadCount \"%1\" . \n").arg(argument.valueList.first().toULongLong());
-+ break;
-+ case QMailFolderKey::Custom:
-+ Q_ASSERT(false);
-+ break;
-+ default:
-+ Q_ASSERT(false);
-+ }
-+ }
-+ return " " + constraint;
-+}
-+
-+QString accountConstraint(const QString& variable, const QMailAccountKey& key)
-+{
-+ QString constraint;
-+ foreach (QMailAccountKey::ArgumentType argument, key.arguments())
-+ {
-+ switch (argument.property)
-+ {
-+ case QMailAccountKey::Id:
-+ // Nothing to select
-+ break;
-+ case QMailAccountKey::Name:
-+ constraint += QString(variable + " nmo:accountName \"%1\" . \n").arg(argument.valueList.first().toString());
-+ break;
-+ case QMailAccountKey::MessageType:
-+ constraint += QString(variable + " nmo:fromAddress [ nco:emailAddress \"%1\" ] . \n").arg(argument.valueList.first().toString());
-+ break;
-+ case QMailAccountKey::FromAddress:
-+ Q_ASSERT(false);
-+ break;
-+ case QMailAccountKey::Status:
-+ constraint += QString(variable + " nmo:status \"%1\"^^xsd:integer . \n").arg(argument.valueList.first().toULongLong());
-+ break;
-+ case QMailAccountKey::Custom:
-+ Q_ASSERT(false);
-+ break;
-+ default:
-+ Q_ASSERT(false);
-+ }
-+ }
-+ return " " + constraint;
-+}
-+
-+
+} // namespace
+
-+
+// We need to support recursive locking, per-process
+static volatile int mutexLockCount = 0;
+static volatile int readLockCount = 0;
@@ -2526,7 +1681,7 @@ index 0000000..029ca4e
+};
+
+QMailStorePrivate::Transaction::Transaction(QMailStorePrivate* d)
-+ : m_d(d),
++ : m_d(d),
+ m_initted(false),
+ m_committed(false)
+{
@@ -2539,10 +1694,8 @@ index 0000000..029ca4e
+ if (m_d->databaseMutex().lock(10000)) {
+ // Wait for any readers to complete
+ if (m_d->databaseReadLock().wait(10000)) {
-+ if (m_d->transaction()) {
+ ++mutexLockCount;
+ m_initted = true;
-+ }
+ } else {
+ qWarning() << "Unable to wait for database read lock to reach zero!";
+ }
@@ -2559,7 +1712,6 @@ index 0000000..029ca4e
+QMailStorePrivate::Transaction::~Transaction()
+{
+ if (m_initted && !m_committed) {
-+ m_d->rollback();
+
+ --mutexLockCount;
+ if (mutexLockCount == 0)
@@ -2570,11 +1722,12 @@ index 0000000..029ca4e
+bool QMailStorePrivate::Transaction::commit()
+{
+ if (m_initted && !m_committed) {
-+ if ((m_committed = m_d->commit())) {
-+ --mutexLockCount;
-+ if (mutexLockCount == 0)
-+ m_d->databaseMutex().unlock();
-+ }
++ // TBD: Pretend that we've
++ // commited that already.
++ m_committed = true;
++ --mutexLockCount;
++ if (mutexLockCount == 0)
++ m_d->databaseMutex().unlock();
+ }
+
+ return m_committed;
@@ -2585,7 +1738,6 @@ index 0000000..029ca4e
+ return m_committed;
+}
+
-+
+class QMailStorePrivate::ReadLock
+{
+ QMailStorePrivate *m_d;
@@ -2629,7 +1781,6 @@ index 0000000..029ca4e
+ }
+}
+
-+
+template<typename FunctionType>
+QMailStorePrivate::AttemptResult evaluate(QMailStorePrivate::WriteAccess, FunctionType func, const QString& description, QMailStorePrivate* d)
+{
@@ -2653,7 +1804,6 @@ index 0000000..029ca4e
+ return func(l);
+}
+
-+
+QMailStore::ErrorCode errorType(QMailStorePrivate::ReadAccess)
+{
+ return QMailStore::InvalidId;
@@ -2664,6 +1814,32 @@ index 0000000..029ca4e
+ return QMailStore::ConstraintFailure;
+}
+
++// Properties of the mailmessages table
++static QMailStorePrivate::MessagePropertyMap messagePropertyMap()
++{
++ QMailStorePrivate::MessagePropertyMap map;
++
++ map.insert(QMailMessageKey::Id,"id");
++ map.insert(QMailMessageKey::Type,"type");
++ map.insert(QMailMessageKey::ParentFolderId,"parentfolderid");
++ map.insert(QMailMessageKey::Sender,"sender");
++ map.insert(QMailMessageKey::Recipients,"recipients");
++ map.insert(QMailMessageKey::Subject,"subject");
++ map.insert(QMailMessageKey::TimeStamp,"stamp");
++ map.insert(QMailMessageKey::ReceptionTimeStamp,"receivedstamp");
++ map.insert(QMailMessageKey::Status,"status");
++ map.insert(QMailMessageKey::ParentAccountId,"parentaccountid");
++ map.insert(QMailMessageKey::ServerUid,"serveruid");
++ map.insert(QMailMessageKey::Size,"size");
++ map.insert(QMailMessageKey::ContentType,"contenttype");
++ map.insert(QMailMessageKey::PreviousParentFolderId,"previousparentfolderid");
++ map.insert(QMailMessageKey::ContentScheme,"mailfile");
++ map.insert(QMailMessageKey::ContentIdentifier,"mailfile");
++ map.insert(QMailMessageKey::InResponseTo,"responseid");
++ map.insert(QMailMessageKey::ResponseType,"responsetype");
++
++ return map;
++}
+
+const QMailMessageKey::Properties &QMailStorePrivate::updatableMessageProperties()
+{
@@ -2693,13 +1869,13 @@ index 0000000..029ca4e
+ return p;
+}
+
-+const QMailStorePrivate::MessagePropertyMap& QMailStorePrivate::messagePropertyMap()
++const QMailStorePrivate::MessagePropertyMap& QMailStorePrivate::messagePropertyMap()
+{
+ static const MessagePropertyMap map(::messagePropertyMap());
+ return map;
+}
+
-+const QMailStorePrivate::MessagePropertyList& QMailStorePrivate::messagePropertyList()
++const QMailStorePrivate::MessagePropertyList& QMailStorePrivate::messagePropertyList()
+{
+ static const MessagePropertyList list(messagePropertyMap().keys());
+ return list;
@@ -2718,7 +1894,9 @@ index 0000000..029ca4e
+
+int QMailStorePrivate::databaseIdentifier(int n) const
+{
-+ int result = static_cast<int>(::ftok(database.databaseName().toAscii(), n));
++ // TBD: Find good file name for the SPARQL database
++ QString databasePath = QDir::homePath() + "/.cache/tracker/contents.db";
++ int result = static_cast<int>(::ftok(databasePath.toAscii(), n));
+ if (result == -1)
+ qFatal("Could not create database semaphore. Database could not be found.");
+ return result;
@@ -2739,10 +1917,6 @@ index 0000000..029ca4e
+ qDebug() << "QMailStorePrivate::QMailStorePrivate";
+ ProcessMutex creationMutex(pathIdentifier(QDir::rootPath()));
+ MutexGuard guard(creationMutex);
-+ if (guard.lock(1000)) {
-+ //open the database
-+ database = QMail::createDatabase();
-+ }
+ mutex = new ProcessMutex(databaseIdentifier(1));
+ readLock = new ProcessReadLock(databaseIdentifier(2));
+ if (contentMutex == 0) {
@@ -2779,50 +1953,22 @@ index 0000000..029ca4e
+ return init;
+ }
+
-+ if (database.isOpenError()) {
++ if (sparqlDatabase.isOpenError()) {
+ qMailLog(Messaging) << "Unable to open database in initStore!";
+ return false;
+ }
+
-+ {
-+ Transaction t(this);
-+
-+ if (!ensureVersionInfo() ||
-+ !setupTables(QList<TableInfo>() << tableInfo("mailaccounts", 106)
-+ << tableInfo("mailaccountcustom", 100)
-+ << tableInfo("mailaccountconfig", 100)
-+ << tableInfo("mailaccountfolders", 100)
-+ << tableInfo("mailfolders", 102)
-+ << tableInfo("mailfoldercustom", 100)
-+ << tableInfo("mailfolderlinks", 100)
-+ << tableInfo("mailmessages", 105)
-+ << tableInfo("mailmessagecustom", 100)
-+ << tableInfo("mailstatusflags", 101)
-+ << tableInfo("deletedmessages", 101)) ||
-+ !setupFolders(QList<FolderInfo>() << folderInfo(QMailFolder::InboxFolder, tr("Inbox"))
-+ << folderInfo(QMailFolder::OutboxFolder, tr("Outbox"))
-+ << folderInfo(QMailFolder::DraftsFolder, tr("Drafts"))
-+ << folderInfo(QMailFolder::SentFolder, tr("Sent"))
-+ << folderInfo(QMailFolder::TrashFolder, tr("Trash")))) {
-+ return false;
-+ }
-+
-+ if (!t.commit()) {
-+ qMailLog(Messaging) << "Could not commit setup operation to database";
++ if (!setupStandardFolder(QMailFolder::InboxFolder, tr("Inbox")) ||
++ !setupStandardFolder(QMailFolder::OutboxFolder, tr("Outbox")) ||
++ !setupStandardFolder(QMailFolder::DraftsFolder, tr("Drafts")) ||
++ !setupStandardFolder(QMailFolder::SentFolder, tr("Sent")) ||
++ !setupStandardFolder(QMailFolder::TrashFolder, tr("Trash"))) {
+ return false;
+ }
+
+ QMailAccount::initStore();
+ QMailFolder::initStore();
+ QMailMessage::initStore();
-+ }
-+
-+#if defined(Q_USE_SQLITE)
-+ // default sqlite cache_size of 2000*1.5KB is too large, as we only want
-+ // to cache 100 metadata records
-+ QSqlQuery query( database );
-+ query.exec(QLatin1String("PRAGMA cache_size=50"));
-+#endif
+
+ if (!QMailContentManagerFactory::init()) {
+ qMailLog(Messaging) << "Could not initialize content manager factory";
@@ -2841,1037 +1987,127 @@ index 0000000..029ca4e
+ folderCache.clear();
+ headerCache.clear();
+
-+ // Drop all data
-+ foreach (const QString &table, database.tables()) {
-+ if (table != "versioninfo") {
-+ QString sql("DELETE FROM %1");
-+ QSqlQuery query(database);
-+ if (!query.exec(sql.arg(table))) {
-+ qMailLog(Messaging) << "Failed to delete from table - query:" << sql << "- error:" << query.lastError().text();
-+ }
-+ }
-+ }
++ // TBD: Drop all data
+
+ // Remove all content
+ QMailContentManagerFactory::clearContent();
+}
+
-+bool QMailStorePrivate::transaction(void)
-+{
-+ if (inTransaction) {
-+ qMailLog(Messaging) << "(" << ::getpid() << ")" << "Transaction already exists at begin!";
-+ qWarning() << "Transaction already exists at begin!";
-+ }
-+
-+ clearQueryError();
-+
-+ // Ensure any outstanding temp tables are removed before we begin this transaction
-+ destroyTemporaryTables();
-+
-+ if (!database.transaction()) {
-+ setQueryError(database.lastError(), "Failed to initiate transaction");
-+ return false;
-+ }
-+
-+ inTransaction = true;
-+ return true;
-+}
-+
-+static QString queryText(const QString &query, const QList<QVariant> &values)
-+{
-+ static const QChar marker('?');
-+ static const QChar quote('\'');
-+
-+ QString result(query);
-+
-+ QList<QVariant>::const_iterator it = values.begin(), end = values.end();
-+ int index = result.indexOf(marker);
-+ while ((index != -1) && (it != end)) {
-+ QString substitute((*it).toString());
-+ if ((*it).type() == QVariant::String)
-+ substitute.prepend(quote).append(quote);
-+
-+ result.replace(index, 1, substitute);
-+
-+ ++it;
-+ index = result.indexOf(marker, index + substitute.length());
-+ }
-+
-+ return result;
-+}
-+
-+static QString queryText(const QSqlQuery &query)
-+{
-+ // Note: we currently only handle positional parameters
-+ return queryText(query.lastQuery().simplified(), query.boundValues().values());
-+}
-+
-+QSqlQuery QMailStorePrivate::prepare(const QString& sql)
-+{
-+ if (!inTransaction) {
-+ // Ensure any outstanding temp tables are removed before we begin this query
-+ destroyTemporaryTables();
-+ }
-+
-+ clearQueryError();
-+
-+ QSqlQuery query(database);
-+
-+ // Create any temporary tables needed for this query
-+ while (!requiredTableKeys.isEmpty()) {
-+ const QMailMessageKey *key = requiredTableKeys.takeFirst();
-+ if (!temporaryTableKeys.contains(key)) {
-+ QString tableName = temporaryTableName(*key);
-+
-+ bool ok = true;
-+ QSqlQuery tableQuery(database);
-+ if (!tableQuery.exec(QString("CREATE TEMP TABLE %1 ( id INTEGER PRIMARY KEY )").arg(tableName))) {
-+ ok = false;
-+ } else {
-+ temporaryTableKeys.append(key);
-+
-+ // Add the ID values to the temp table
-+ foreach (const QVariant &var, key->arguments().first().valueList) {
-+ quint64 id = 0;
-+
-+ if (qVariantCanConvert<QMailMessageId>(var)) {
-+ id = var.value<QMailMessageId>().toULongLong();
-+ } else if (qVariantCanConvert<QMailFolderId>(var)) {
-+ id = var.value<QMailFolderId>().toULongLong();
-+ } else if (qVariantCanConvert<QMailAccountId>(var)) {
-+ id = var.value<QMailAccountId>().toULongLong();
-+ }
-+
-+ if (id != 0) {
-+ tableQuery = QSqlQuery(database);
-+ if (!tableQuery.exec(QString("INSERT INTO %1 VALUES (%2)").arg(tableName).arg(id))) {
-+ ok = false;
-+ break;
-+ }
-+ } else {
-+ qMailLog(Messaging) << "Unable to extract ID value from valuelist!";
-+ ok = false;
-+ break;
-+ }
-+ }
-+ }
-+
-+ if (!ok) {
-+ setQueryError(tableQuery.lastError(), "Failed to create temporary table", queryText(tableQuery));
-+ qMailLog(Messaging) << "Unable to prepare query:" << sql;
-+ return query;
-+ }
-+ }
-+ }
-+
-+ if (!query.prepare(sql)) {
-+ setQueryError(query.lastError(), "Failed to prepare query", queryText(query));
-+ }
-+
-+ // TODO: setForwardOnly?
-+ return query;
-+}
-+
-+bool QMailStorePrivate::execute(QSqlQuery& query, bool batch)
-+{
-+ bool success = (batch ? query.execBatch() : query.exec());
-+ if (!success) {
-+ setQueryError(query.lastError(), "Failed to execute query", queryText(query));
-+ return false;
-+ }
-+
-+#ifdef QMAILSTORE_LOG_SQL
-+ qMailLog(Messaging) << "(" << ::getpid() << ")" << qPrintable(queryText(query));
-+#endif
-+
-+ if (!inTransaction) {
-+ // We should be finished with these temporary tables
-+ expiredTableKeys = temporaryTableKeys;
-+ temporaryTableKeys.clear();
-+ }
-+
-+ return true;
-+}
-+
-+bool QMailStorePrivate::commit(void)
-+{
-+ if (!inTransaction) {
-+ qMailLog(Messaging) << "(" << ::getpid() << ")" << "Transaction does not exist at commit!";
-+ qWarning() << "Transaction does not exist at commit!";
-+ }
-+
-+ if (!database.commit()) {
-+ setQueryError(database.lastError(), "Failed to commit transaction");
-+ return false;
-+ } else {
-+ inTransaction = false;
-+
-+ // Expire any temporary tables we were using
-+ expiredTableKeys = temporaryTableKeys;
-+ temporaryTableKeys.clear();
-+ }
-+
-+ return true;
-+}
-+
-+void QMailStorePrivate::rollback(void)
-+{
-+ if (!inTransaction) {
-+ qMailLog(Messaging) << "(" << ::getpid() << ")" << "Transaction does not exist at rollback!";
-+ qWarning() << "Transaction does not exist at rollback!";
-+ }
-+
-+ inTransaction = false;
-+
-+ if (!database.rollback()) {
-+ setQueryError(database.lastError(), "Failed to rollback transaction");
-+ }
-+}
-+
-+int QMailStorePrivate::queryError() const
-+{
-+ return lastQueryError;
-+}
-+
-+void QMailStorePrivate::setQueryError(const QSqlError &error, const QString &description, const QString &statement)
++void QMailStorePrivate::setQueryError(const SparqlQuery& query, const QString &description)
+{
+ QString s;
+ QTextStream ts(&s);
+
-+ lastQueryError = error.number();
-+
-+ ts << qPrintable(description) << "; error:\"" << error.text() << '"';
-+ if (!statement.isEmpty())
-+ ts << "; statement:\"" << statement.simplified() << '"';
++ lastQueryError = query.error();
+
++ ts << qPrintable(description) << "; error:\"" << query.query() << '"';
+ qMailLog(Messaging) << "(" << ::getpid() << ")" << qPrintable(s);
+ qWarning() << qPrintable(s);
+}
+
-+void QMailStorePrivate::clearQueryError(void)
-+{
-+ lastQueryError = 0;
-+}
-+
-+template<bool PtrSizeExceedsLongSize>
-+QString numericPtrValue(const void *ptr)
-+{
-+ return QString::number(reinterpret_cast<unsigned long long>(ptr), 16).rightJustified(16, '0');
-+}
-+
-+template<>
-+QString numericPtrValue<false>(const void *ptr)
-+{
-+ return QString::number(reinterpret_cast<unsigned long>(ptr), 16).rightJustified(8, '0');;
-+}
-+
-+QString QMailStorePrivate::temporaryTableName(const QMailMessageKey& key)
-+{
-+ const QMailMessageKey *ptr = &key;
-+ return QString("qtopiamail_idmatch_%1").arg(numericPtrValue<(sizeof(void*) > sizeof(unsigned long))>(ptr));
-+}
-+
-+void QMailStorePrivate::createTemporaryTable(const QMailMessageKey& key) const
-+{
-+ requiredTableKeys.append(&key);
-+}
-+
-+void QMailStorePrivate::destroyTemporaryTables()
-+{
-+ while (!expiredTableKeys.isEmpty()) {
-+ const QMailMessageKey *key = expiredTableKeys.takeFirst();
-+ QString tableName = temporaryTableName(*key);
-+
-+ QSqlQuery query(database);
-+ if (!query.exec(QString("DROP TABLE %1").arg(tableName))) {
-+ QString sql = queryText(query);
-+ QString err = query.lastError().text();
-+
-+ qMailLog(Messaging) << "(" << ::getpid() << ")" << "Failed to drop temporary table - query:" << qPrintable(sql) << "; error:" << qPrintable(err);
-+ qWarning() << "Failed to drop temporary table - query:" << qPrintable(sql) << "; error:" << qPrintable(err);
-+ }
-+ }
-+}
-+
-+bool QMailStorePrivate::idValueExists(quint64 id, const QString& table)
-+{
-+ QSqlQuery query(database);
-+ QString sql = "SELECT id FROM " + table + " WHERE id=?";
-+ if(!query.prepare(sql)) {
-+ setQueryError(query.lastError(), "Failed to prepare idExists query", queryText(query));
-+ return false;
-+ }
-+
-+ query.addBindValue(id);
-+
-+ if(!query.exec()) {
-+ setQueryError(query.lastError(), "Failed to execute idExists query", queryText(query));
-+ return false;
-+ }
-+
-+ return (query.first());
-+}
-+
-+bool QMailStorePrivate::idExists(const QMailAccountId& id, const QString& table)
-+{
-+ return idValueExists(id.toULongLong(), (table.isEmpty() ? "mailaccounts" : table));
-+}
-+
-+bool QMailStorePrivate::idExists(const QMailFolderId& id, const QString& table)
-+{
-+ return idValueExists(id.toULongLong(), (table.isEmpty() ? "mailfolders" : table));
-+}
-+
-+bool QMailStorePrivate::idExists(const QMailMessageId& id, const QString& table)
-+{
-+ return idValueExists(id.toULongLong(), (table.isEmpty() ? "mailmessages" : table));
-+}
-+
-+QMailAccount QMailStorePrivate::extractAccount(const QSqlRecord& r)
-+{
-+ const AccountRecord record(r);
-+
-+ QMailAccount result;
-+ result.setId(record.id());
-+ result.setName(record.name());
-+ result.setMessageType(record.messageType());
-+ result.setStatus(record.status());
-+ result.setSignature(record.signature());
-+ result.setFromAddress(QMailAddress(record.fromAddress()));
-+
-+ return result;
-+}
-+
-+QMailFolder QMailStorePrivate::extractFolder(const QSqlRecord& r)
-+{
-+ const FolderRecord record(r);
-+
-+ QMailFolder result(record.path(), record.parentFolderId(), record.parentAccountId());
-+ result.setId(record.id());
-+ result.setDisplayName(record.displayName());
-+ result.setStatus(record.status());
-+ result.setServerCount(record.serverCount());
-+ result.setServerUnreadCount(record.serverUnreadCount());
-+ return result;
-+}
-+
-+void QMailStorePrivate::extractMessageMetaData(const QSqlRecord& r,
-+ QMailMessageKey::Properties recordProperties,
-+ const QMailMessageKey::Properties& properties,
-+ QMailMessageMetaData* metaData)
-+{
-+ // Record whether we have loaded all data for this message
-+ bool unloadedProperties = (properties != allMessageProperties());
-+ if (!unloadedProperties) {
-+ // If there is message content, mark the object as not completely loaded
-+ if (!r.value("mailfile").toString().isEmpty())
-+ unloadedProperties = true;
-+ }
-+
-+ // Use wrapper to extract data items
-+ const MessageRecord messageRecord(r, recordProperties);
-+
-+ foreach (QMailMessageKey::Property p, messagePropertyList()) {
-+ switch (properties & p)
-+ {
-+ case QMailMessageKey::Id:
-+ metaData->setId(messageRecord.id());
-+ break;
-+
-+ case QMailMessageKey::Type:
-+ metaData->setMessageType(messageRecord.messageType());
-+ break;
-+
-+ case QMailMessageKey::ParentFolderId:
-+ metaData->setParentFolderId(messageRecord.parentFolderId());
-+ break;
-+
-+ case QMailMessageKey::Sender:
-+ metaData->setFrom(messageRecord.from());
-+ break;
-+
-+ case QMailMessageKey::Recipients:
-+ metaData->setTo(messageRecord.to());
-+ break;
-+
-+ case QMailMessageKey::Subject:
-+ metaData->setSubject(messageRecord.subject());
-+ break;
-+
-+ case QMailMessageKey::TimeStamp:
-+ metaData->setDate(messageRecord.date());
-+ break;
-+
-+ case QMailMessageKey::ReceptionTimeStamp:
-+ metaData->setReceivedDate(messageRecord.receivedDate());
-+ break;
-+
-+ case QMailMessageKey::Status:
-+ metaData->setStatus(messageRecord.status());
-+ break;
-+
-+ case QMailMessageKey::ParentAccountId:
-+ metaData->setParentAccountId(messageRecord.parentAccountId());
-+ break;
-+
-+ case QMailMessageKey::ServerUid:
-+ metaData->setServerUid(messageRecord.serverUid());
-+ break;
-+
-+ case QMailMessageKey::Size:
-+ metaData->setSize(messageRecord.size());
-+ break;
-+
-+ case QMailMessageKey::ContentType:
-+ metaData->setContent(messageRecord.content());
-+ break;
-+
-+ case QMailMessageKey::PreviousParentFolderId:
-+ metaData->setPreviousParentFolderId(messageRecord.previousParentFolderId());
-+ break;
-+
-+ case QMailMessageKey::ContentScheme:
-+ metaData->setContentScheme(messageRecord.contentScheme());
-+ break;
-+
-+ case QMailMessageKey::ContentIdentifier:
-+ metaData->setContentIdentifier(messageRecord.contentIdentifier());
-+ break;
-+
-+ case QMailMessageKey::InResponseTo:
-+ metaData->setInResponseTo(messageRecord.inResponseTo());
-+ break;
-+
-+ case QMailMessageKey::ResponseType:
-+ metaData->setResponseType(messageRecord.responseType());
-+ break;
-+ }
-+ }
-+
-+ if (unloadedProperties) {
-+ // This message is not completely loaded
-+ metaData->setStatus(QMailMessage::UnloadedData, true);
-+ }
-+
-+ metaData->setUnmodified();
-+}
-+
-+QMailMessageMetaData QMailStorePrivate::extractMessageMetaData(const QSqlRecord& r, QMailMessageKey::Properties recordProperties, const QMailMessageKey::Properties& properties)
-+{
-+ QMailMessageMetaData metaData;
-+
-+ extractMessageMetaData(r, recordProperties, properties, &metaData);
-+ return metaData;
-+}
-+
-+QMailMessage QMailStorePrivate::extractMessage(const QSqlRecord& r, const QMap<QString, QString> &customFields, const QMailMessageKey::Properties& properties)
-+{
-+ QMailMessage newMessage;
-+
-+ // Load the meta data items (note 'SELECT *' does not give the same result as 'SELECT expand(allMessageProperties())')
-+ extractMessageMetaData(r, QMailMessageKey::Properties(0), properties, &newMessage);
-+ newMessage.setUnmodified();
-+
-+ newMessage.setCustomFields(customFields);
-+ newMessage.setCustomFieldsModified(false);
-+
-+ QString contentUri(r.value("mailfile").toString());
-+ if (!contentUri.isEmpty()) {
-+ QPair<QString, QString> elements(::uriElements(contentUri));
-+
-+ MutexGuard lock(contentManagerMutex());
-+ if (!lock.lock(1000)) {
-+ qMailLog(Messaging) << "Unable to acquire message body mutex in extractMessage!";
-+ return QMailMessage();
-+ }
-+
-+ QMailContentManager *contentManager = QMailContentManagerFactory::create(elements.first);
-+ if (contentManager) {
-+ // Load the message content (manager should be able to access the metadata also)
-+ QMailStore::ErrorCode code = contentManager->load(elements.second, &newMessage);
-+ if (code != QMailStore::NoError) {
-+ setLastError(code);
-+ qMailLog(Messaging) << "Unable to load message content:" << contentUri;
-+ return QMailMessage();
-+ }
-+ } else {
-+ qMailLog(Messaging) << "Unable to create content manager for scheme:" << elements.first;
-+ return QMailMessage();
-+ }
-+
-+ // Re-load the meta data items so that they take precedence over the loaded content
-+ extractMessageMetaData(r, QMailMessageKey::Properties(0), properties, &newMessage);
-+ newMessage.setUnmodified();
-+
-+ newMessage.setCustomFields(customFields);
-+ newMessage.setCustomFieldsModified(false);
-+ }
-+
-+ return newMessage;
-+}
-+
-+QMailMessageRemovalRecord QMailStorePrivate::extractMessageRemovalRecord(const QSqlRecord& r)
-+{
-+ const MessageRemovalRecord record(r);
-+
-+ QMailMessageRemovalRecord result(record.parentAccountId(), record.serverUid(), record.parentFolderId());
-+ return result;
-+}
-+
-+QString QMailStorePrivate::buildOrderClause(const Key& key) const
-+{
-+ if (key.isType<QMailMessageSortKey>()) {
-+ const QMailMessageSortKey &sortKey(key.key<QMailMessageSortKey>());
-+ return ::buildOrderClause(sortKey.arguments(), key.alias());
-+ } else if (key.isType<QMailFolderSortKey>()) {
-+ const QMailFolderSortKey &sortKey(key.key<QMailFolderSortKey>());
-+ return ::buildOrderClause(sortKey.arguments(), key.alias());
-+ } else if (key.isType<QMailAccountSortKey>()) {
-+ const QMailAccountSortKey &sortKey(key.key<QMailAccountSortKey>());
-+ return ::buildOrderClause(sortKey.arguments(), key.alias());
-+ }
-+
-+ return QString();
-+}
-+
-+QString QMailStorePrivate::buildWhereClause(const Key& key, bool nested, bool firstClause) const
++QString QMailStorePrivate::queryError() const
+{
-+ if (key.isType<QMailMessageKey>()) {
-+ const QMailMessageKey &messageKey(key.key<QMailMessageKey>());
-+
-+ // See if we need to create any temporary tables to use in this query
-+ foreach (const QMailMessageKey::ArgumentType &a, messageKey.arguments()) {
-+ if (a.property == QMailMessageKey::Id && a.valueList.count() >= IdLookupThreshold) {
-+ createTemporaryTable(messageKey);
-+ }
-+ }
-+
-+ return ::buildWhereClause(messageKey, messageKey.arguments(), messageKey.subKeys(), messageKey.combiner(), messageKey.isNegated(), nested, firstClause, key.alias(), *this);
-+ } else if (key.isType<QMailFolderKey>()) {
-+ const QMailFolderKey &folderKey(key.key<QMailFolderKey>());
-+ return ::buildWhereClause(folderKey, folderKey.arguments(), folderKey.subKeys(), folderKey.combiner(), folderKey.isNegated(), nested, firstClause, key.alias(), *this);
-+ } else if (key.isType<QMailAccountKey>()) {
-+ const QMailAccountKey &accountKey(key.key<QMailAccountKey>());
-+ return ::buildWhereClause(accountKey, accountKey.arguments(), accountKey.subKeys(), accountKey.combiner(), accountKey.isNegated(), nested, firstClause, key.alias(), *this);
-+ }
-+
-+ return QString();
++ return lastQueryError;
+}
+
-+QVariantList QMailStorePrivate::whereClauseValues(const Key& key) const
++void QMailStorePrivate::clearQueryError(void)
+{
-+ if (key.isType<QMailMessageKey>()) {
-+ const QMailMessageKey &messageKey(key.key<QMailMessageKey>());
-+ return ::whereClauseValues(messageKey);
-+ } else if (key.isType<QMailFolderKey>()) {
-+ const QMailFolderKey &folderKey(key.key<QMailFolderKey>());
-+ return ::whereClauseValues(folderKey);
-+ } else if (key.isType<QMailAccountKey>()) {
-+ const QMailAccountKey &accountKey(key.key<QMailAccountKey>());
-+ return ::whereClauseValues(accountKey);
-+ }
-+
-+ return QVariantList();
++ lastQueryError.clear();
+}
+
-+bool QMailStorePrivate::containsProperty(const QMailMessageKey::Property& p,
-+ const QMailMessageKey& key) const
++bool QMailStorePrivate::uriExists(const QString& uri)
+{
-+ foreach(const QMailMessageKey::ArgumentType &a, key.arguments())
-+ if(a.property == p)
-+ return true;
-+
-+ foreach(const QMailMessageKey &k, key.subKeys())
-+ if(containsProperty(p,k))
-+ return true;
-+
++ // TBD: Check whether value exists already
++ Q_UNUSED(uri);
+ return false;
+}
+
-+bool QMailStorePrivate::containsProperty(const QMailMessageSortKey::Property& p,
-+ const QMailMessageSortKey& key) const
-+{
-+ foreach(const QMailMessageSortKey::ArgumentType &a, key.arguments())
-+ if(a.first == p)
-+ return true;
-+
-+ return false;
-+}
-+
-+QVariantList QMailStorePrivate::messageValues(const QMailMessageKey::Properties& prop, const QMailMessageMetaData& data)
-+{
-+ QVariantList values;
-+
-+ const MessageValueExtractor<QMailMessageMetaData> extractor(data);
-+
-+ // The ContentScheme and ContentIdentifier properties map to the same field
-+ QMailMessageKey::Properties properties(prop);
-+ if ((properties & QMailMessageKey::ContentScheme) && (properties & QMailMessageKey::ContentIdentifier))
-+ properties &= ~QMailMessageKey::ContentIdentifier;
-+
-+ foreach (QMailMessageKey::Property p, messagePropertyList()) {
-+ switch (properties & p)
-+ {
-+ case QMailMessageKey::Id:
-+ values.append(extractor.id());
-+ break;
-+
-+ case QMailMessageKey::Type:
-+ values.append(extractor.messageType());
-+ break;
-+
-+ case QMailMessageKey::ParentFolderId:
-+ values.append(extractor.parentFolderId());
-+ break;
-+
-+ case QMailMessageKey::Sender:
-+ values.append(extractor.from());
-+ break;
-+
-+ case QMailMessageKey::Recipients:
-+ values.append(extractor.to());
-+ break;
-+
-+ case QMailMessageKey::Subject:
-+ values.append(extractor.subject());
-+ break;
-+
-+ case QMailMessageKey::TimeStamp:
-+ values.append(extractor.date());
-+ break;
-+
-+ case QMailMessageKey::ReceptionTimeStamp:
-+ values.append(extractor.receivedDate());
-+ break;
-+
-+ case QMailMessageKey::Status:
-+ values.append(extractor.status());
-+ break;
-+
-+ case QMailMessageKey::ParentAccountId:
-+ values.append(extractor.parentAccountId());
-+ break;
-+
-+ case QMailMessageKey::ServerUid:
-+ values.append(extractor.serverUid());
-+ break;
-+
-+ case QMailMessageKey::Size:
-+ values.append(extractor.size());
-+ break;
-+
-+ case QMailMessageKey::ContentType:
-+ values.append(extractor.content());
-+ break;
-+
-+ case QMailMessageKey::PreviousParentFolderId:
-+ values.append(extractor.previousParentFolderId());
-+ break;
-+
-+ case QMailMessageKey::ContentScheme:
-+ case QMailMessageKey::ContentIdentifier:
-+ // For either of these (there can be only one) we want to produce the entire URI
-+ values.append(::contentUri(extractor.contentScheme().toString(), extractor.contentIdentifier().toString()));
-+ break;
-+
-+ case QMailMessageKey::InResponseTo:
-+ values.append(extractor.inResponseTo());
-+ break;
-+
-+ case QMailMessageKey::ResponseType:
-+ values.append(extractor.responseType());
-+ break;
-+ }
-+ }
-+
-+ return values;
-+}
-+
-+void QMailStorePrivate::updateMessageValues(const QMailMessageKey::Properties& properties, const QVariantList& values, const QMap<QString, QString>& customFields, QMailMessageMetaData& metaData)
-+{
-+ QPair<QString, QString> uriElements;
-+ QVariantList::const_iterator it = values.constBegin();
-+
-+ foreach (QMailMessageKey::Property p, messagePropertyList()) {
-+ const MessageValueExtractor<QVariant> extractor(*it);
-+ bool valueConsumed(true);
-+
-+ switch (properties & p)
-+ {
-+ case QMailMessageKey::Id:
-+ metaData.setId(extractor.id());
-+ break;
-+
-+ case QMailMessageKey::Type:
-+ metaData.setMessageType(extractor.messageType());
-+ break;
-+
-+ case QMailMessageKey::ParentFolderId:
-+ metaData.setParentFolderId(extractor.parentFolderId());
-+ break;
-+
-+ case QMailMessageKey::Sender:
-+ metaData.setFrom(extractor.from());
-+ break;
-+
-+ case QMailMessageKey::Recipients:
-+ metaData.setTo(extractor.to());
-+ break;
-+
-+ case QMailMessageKey::Subject:
-+ metaData.setSubject(extractor.subject());
-+ break;
-+
-+ case QMailMessageKey::TimeStamp:
-+ metaData.setDate(extractor.date());
-+ break;
-+
-+ case QMailMessageKey::ReceptionTimeStamp:
-+ metaData.setReceivedDate(extractor.receivedDate());
-+ break;
-+
-+ case QMailMessageKey::Status:
-+ metaData.setStatus(extractor.status());
-+ break;
-+
-+ case QMailMessageKey::ParentAccountId:
-+ metaData.setParentAccountId(extractor.parentAccountId());
-+ break;
-+
-+ case QMailMessageKey::ServerUid:
-+ metaData.setServerUid(extractor.serverUid());
-+ break;
-+
-+ case QMailMessageKey::Size:
-+ metaData.setSize(extractor.size());
-+ break;
-+
-+ case QMailMessageKey::ContentType:
-+ metaData.setContent(extractor.content());
-+ break;
-+
-+ case QMailMessageKey::PreviousParentFolderId:
-+ metaData.setPreviousParentFolderId(extractor.previousParentFolderId());
-+ break;
-+
-+ case QMailMessageKey::ContentScheme:
-+ if (uriElements.first.isEmpty()) {
-+ uriElements = ::uriElements(extractor.contentUri());
-+ } else {
-+ valueConsumed = false;
-+ }
-+ metaData.setContentScheme(uriElements.first);
-+ break;
-+
-+ case QMailMessageKey::ContentIdentifier:
-+ if (uriElements.first.isEmpty()) {
-+ uriElements = ::uriElements(extractor.contentUri());
-+ } else {
-+ valueConsumed = false;
-+ }
-+ metaData.setContentIdentifier(uriElements.second);
-+ break;
-+
-+ case QMailMessageKey::InResponseTo:
-+ metaData.setInResponseTo(extractor.inResponseTo());
-+ break;
-+
-+ case QMailMessageKey::ResponseType:
-+ metaData.setResponseType(extractor.responseType());
-+ break;
-+
-+ case QMailMessageKey::Custom:
-+ metaData.setCustomFields(customFields);
-+ break;
-+
-+ default:
-+ valueConsumed = false;
-+ break;
-+ }
-+
-+ if (valueConsumed)
-+ ++it;
-+ }
-+
-+ if (it != values.constEnd())
-+ qWarning() << QString("updateMessageValues: %1 values not consumed!").arg(values.constEnd() - it);
-+
-+ // The target message is not completely loaded
-+ metaData.setStatus(QMailMessage::UnloadedData, true);
-+}
-+
-+bool QMailStorePrivate::executeFile(QFile &file)
-+{
-+ bool result(true);
-+
-+ // read assuming utf8 encoding.
-+ QTextStream ts(&file);
-+ ts.setCodec(QTextCodec::codecForName("utf8"));
-+ ts.setAutoDetectUnicode(true);
-+
-+ QString sql = parseSql(ts);
-+ while (result && !sql.isEmpty()) {
-+ QSqlQuery query(database);
-+ if (!query.exec(sql)) {
-+ qMailLog(Messaging) << "Failed to exec table creation SQL query:" << sql << "- error:" << query.lastError().text();
-+ result = false;
-+ }
-+ sql = parseSql(ts);
-+ }
-+
-+ return result;
-+}
-+
-+bool QMailStorePrivate::ensureVersionInfo()
-+{
-+ if (!database.tables().contains("versioninfo", Qt::CaseInsensitive)) {
-+ // Use the same version scheme as dbmigrate, in case we need to cooperate later
-+ QString sql("CREATE TABLE versioninfo ("
-+ " tableName NVARCHAR (255) NOT NULL,"
-+ " versionNum INTEGER NOT NULL,"
-+ " lastUpdated NVARCHAR(20) NOT NULL,"
-+ " PRIMARY KEY(tableName, versionNum))");
-+
-+ QSqlQuery query(database);
-+ if (!query.exec(sql)) {
-+ qMailLog(Messaging) << "Failed to create versioninfo table - query:" << sql << "- error:" << query.lastError().text();
-+ return false;
-+ }
-+ }
-+
-+ return true;
-+}
-+
-+qint64 QMailStorePrivate::tableVersion(const QString &name) const
++bool QMailStorePrivate::setupStandardFolder(enum QMailFolder::StandardFolder folder, const QString& name)
+{
-+ QString sql("SELECT COALESCE(MAX(versionNum), 0) FROM versioninfo WHERE tableName=?");
-+
-+ QSqlQuery query(database);
-+ query.prepare(sql);
-+ query.addBindValue(name);
-+ if (query.exec() && query.first())
-+ return query.value(0).value<qint64>();
-+
-+ qMailLog(Messaging) << "Failed to query versioninfo - query:" << sql << "- error:" << query.lastError().text();
-+ return 0;
-+}
++ MailFolderUri folderUri(QMailFolderId((int)folder));
++ MailFolderUri parentFolderUri(QMailFolderId(0));
++ MailAccountUri parentAccountUri(QMailAccountId(0));
+
-+bool QMailStorePrivate::setTableVersion(const QString &name, qint64 version)
-+{
-+ QString sql("DELETE FROM versioninfo WHERE tableName=? AND versionNum=?");
++ SparqlQuery query(SparqlQuery::UpdateQuery);
++ query.prepare(QString(
++ "INSERT { \n"
++ "%1 rdf:type nmo:MailFolder ; \n"
++ " nmo:folderName \"%2\" ; \n"
++ " nie:isLogicalPartOf %3 ; \n"
++ " nie:relatedTo %4 ; \n"
++ " nmo:folderDisplayName \"%5\" ; \n"
++ " nmo:status \"%6\"^^xsd:integer ; \n"
++ " nmo:serverCount \"%7\"^^xsd:integer ; \n"
++ " nmo:serverUnreadCount \"%8\"^^xsd:integet . \n"
++ "}").arg(folderUri.uri())
++ .arg(name)
++ .arg(parentFolderUri.uri())
++ .arg(parentAccountUri.uri())
++ .arg(0)
++ .arg(0)
++ .arg(0)
++ .arg(0));
+
-+ // Delete any existing entry for this table
-+ QSqlQuery query(database);
-+ query.prepare(sql);
-+ query.addBindValue(name);
-+ query.addBindValue(version);
++ // TBD: Add custom fields later
+
-+ if (!query.exec()) {
-+ qMailLog(Messaging) << "Failed to delete versioninfo - query:" << sql << "- error:" << query.lastError().text();
++ if (!query.exec())
++ {
++ qDebug() << "Query failed:" << query.error();
+ return false;
-+ } else {
-+ sql = "INSERT INTO versioninfo (tablename,versionNum,lastUpdated) VALUES (?,?,?)";
-+
-+ // Insert the updated info
-+ query = QSqlQuery(database);
-+ query.prepare(sql);
-+ query.addBindValue(name);
-+ query.addBindValue(version);
-+ query.addBindValue(QDateTime::currentDateTime().toString());
-+
-+ if (!query.exec()) {
-+ qMailLog(Messaging) << "Failed to insert versioninfo - query:" << sql << "- error:" << query.lastError().text();
-+ return false;
-+ }
+ }
+
-+ return true;
-+}
-+
-+qint64 QMailStorePrivate::incrementTableVersion(const QString &name, qint64 current)
-+{
-+ qint64 next = current + 1;
-+
-+ QString versionInfo("-" + QString::number(current) + "-" + QString::number(next));
-+ QString scriptName(":/QtopiaSql/" + database.driverName() + "/" + name + versionInfo);
-+
-+ QFile data(scriptName);
-+ if (!data.open(QIODevice::ReadOnly)) {
-+ qMailLog(Messaging) << "Failed to load table upgrade resource:" << name;
-+ } else {
-+ if (executeFile(data)) {
-+ // Update the table version number
-+ if (setTableVersion(name, next))
-+ current = next;
-+ }
-+ }
-+
-+ return current;
-+}
-+
-+bool QMailStorePrivate::upgradeTableVersion(const QString &name, qint64 current, qint64 final)
-+{
-+ while (current < final) {
-+ int newVersion = incrementTableVersion(name, current);
-+ if (newVersion == current) {
-+ qMailLog(Messaging) << "Failed to increment table version from:" << current << "(" << name << ")";
-+ break;
-+ } else {
-+ current = newVersion;
-+ }
-+ }
-+
-+ return (current == final);
-+}
-+
-+bool QMailStorePrivate::createTable(const QString &name)
-+{
-+ bool result = true;
-+
-+ // load schema.
-+ QFile data(":/QtopiaSql/" + database.driverName() + "/" + name);
-+ if (!data.open(QIODevice::ReadOnly)) {
-+ qMailLog(Messaging) << "Failed to load table schema resource:" << name;
-+ result = false;
-+ } else {
-+ result = executeFile(data);
-+ }
-+
-+ return result;
-+}
-+
-+bool QMailStorePrivate::setupTables(const QList<TableInfo> &tableList)
-+{
-+ bool result = true;
-+
-+ QStringList tables = database.tables();
-+
-+ foreach (const TableInfo &table, tableList) {
-+ const QString &tableName(table.first);
-+ qint64 version(table.second);
++ qDebug() << "Query succeeded";
+
-+ if (!tables.contains(tableName, Qt::CaseInsensitive)) {
-+ // Create the table
-+ result &= (createTable(tableName) && setTableVersion(tableName, version));
-+ } else {
-+ // Ensure the table does not have an incompatible version
-+ qint64 dbVersion = tableVersion(tableName);
-+ if (dbVersion == 0) {
-+ qWarning() << "No version for existing table:" << tableName;
-+ result = false;
-+ } else if (dbVersion != version) {
-+ if (version > dbVersion) {
-+ // Try upgrading the table
-+ result = upgradeTableVersion(tableName, dbVersion, version);
-+ qMailLog(Messaging) << (result ? "Upgraded" : "Unable to upgrade") << "version for table:" << tableName << " from" << dbVersion << "to" << version;
-+ } else {
-+ qWarning() << "Incompatible version for table:" << tableName << "- existing" << dbVersion << "!=" << version;
-+ result = false;
-+ }
-+ }
-+ }
-+ }
-+
-+ return result;
++ // TBD: Update folder links also
++ return true;
+}
+
-+bool QMailStorePrivate::setupFolders(const QList<FolderInfo> &folderList)
++QMailAccount QMailStorePrivate::extractAccount(const QMailAccountId& id, const QStringList& list)
+{
-+ QSet<quint64> folderIds;
-+
-+ {
-+ QSqlQuery query(simpleQuery("SELECT id FROM mailfolders",
-+ "folder ids query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return false;
-+
-+ while (query.next())
-+ folderIds.insert(query.value(0).toULongLong());
-+ }
-+
-+ foreach (const FolderInfo &folder, folderList) {
-+ if (folderIds.contains(folder.first))
-+ continue;
-+ QSqlQuery query(simpleQuery("INSERT INTO mailfolders (id,name,parentid,parentaccountid,displayname,status,servercount,serverunreadcount) VALUES (?,?,?,?,?,?,?,?)",
-+ QVariantList() << folder.first
-+ << folder.second
-+ << quint64(0)
-+ << quint64(0)
-+ << QString()
-+ << quint64(0)
-+ << int(0)
-+ << int(0),
-+ "setupFolders insert query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return false;
-+ }
++ QMailAccount account;
+
-+ return true;
-+}
++ // Load account data
++ account.setId(id);
++ account.setName(list.at(0));
++ /* account.setStatus(list.at(1).toULongLong()); */
++ account.setSignature(list.at(1));
++ account.setFromAddress(QMailAddress(list.at(2)));
+
-+QString QMailStorePrivate::parseSql(QTextStream& ts)
-+{
-+ QString qry = "";
-+ while(!ts.atEnd())
-+ {
-+ QString line = ts.readLine();
-+ // comment, remove.
-+ if (line.contains(QLatin1String("--")))
-+ line.truncate (line.indexOf (QLatin1String("--")));
-+ if (line.trimmed ().length () == 0)
-+ continue;
-+ qry += line;
-+
-+ if ( line.contains( ';' ) == false)
-+ qry += QLatin1String(" ");
-+ else
-+ return qry;
-+ }
-+ return qry;
++ return account;
+}
+
-+QString QMailStorePrivate::expandValueList(const QVariantList& valueList)
++QMailFolder QMailStorePrivate::extractFolder(const QMailFolderId& id, const QStringList& list)
+{
-+ Q_ASSERT(!valueList.isEmpty());
-+ return expandValueList(valueList.count());
-+}
++ // Load folder data
++ QMailFolder folder(list.at(0), IdFromUri<QMailFolderId>(list.at(1)), IdFromUri<QMailAccountId>(list.at(2)));
+
-+QString QMailStorePrivate::expandValueList(int valueCount)
-+{
-+ Q_ASSERT(valueCount > 0);
++ folder.setId(id);
++ folder.setDisplayName(list.at(3));
++// folder.setStatus(list.at(4).toULongLong());
++// folder.setServerCount(list.at(5).toUInt());
++// folder.setServerUnreadCount(list.at(6).toUInt());
+
-+ if (valueCount == 1) {
-+ return "(?)";
-+ } else {
-+ QString inList = " (?";
-+ for (int i = 1; i < valueCount; ++i)
-+ inList += ",?";
-+ inList += ")";
-+ return inList;
-+ }
++ return folder;
+}
+
-+QString QMailStorePrivate::expandProperties(const QMailMessageKey::Properties& prop, bool update) const
++void QMailStorePrivate::extractMessageMetaData(const QStringList& list, QMailMessageMetaData* metaData)
+{
-+ QString out;
++ // Load message properties
+
-+ // The ContentScheme and ContentIdentifier properties map to the same field
-+ QMailMessageKey::Properties properties(prop);
-+ if ((properties & QMailMessageKey::ContentScheme) && (properties & QMailMessageKey::ContentIdentifier))
-+ properties &= ~QMailMessageKey::ContentIdentifier;
++ metaData->setParentFolderId(IdFromUri<QMailFolderId>(list.at(0)));
++ metaData->setFrom(QMailAddress(list.at(1), list.at(2)));
++ metaData->setSubject(list.at(3));
++ metaData->setDate(QMailTimeStamp(list.at(4)));
++ metaData->setStatus(list.at(5).toULongLong());
++ metaData->setParentAccountId(IdFromUri<QMailAccountId>(list.at(6)));
++ metaData->setServerUid(list.at(10));
++ metaData->setSize(list.at(9).toUInt());
++ metaData->setContent((QMailMessageMetaDataFwd::ContentType)list.at(10).toInt());
++ metaData->setInResponseTo(QMailMessageId(IdFromUri<QMailMessageId>(list.at(11))));
++ metaData->setResponseType((QMailMessageMetaDataFwd::ResponseType)list.at(12).toInt());
++ metaData->setReceivedDate(QMailTimeStamp(list.at(13)));
+
-+ const QMailStorePrivate::MessagePropertyMap &map(messagePropertyMap());
-+ foreach (QMailMessageKey::Property p, messagePropertyList()) {
-+ if (properties & p) {
-+ if (!out.isEmpty())
-+ out += ",";
-+ out += map.value(p);
-+ if (update)
-+ out += "=?";
-+ }
-+ }
-+
-+ return out;
++ metaData->setUnmodified();
+}
+
+bool QMailStorePrivate::addAccount(QMailAccount *account, QMailAccountConfiguration *config,
@@ -4196,7 +2432,7 @@ index 0000000..029ca4e
+{
+ QMailMessageMetaDataList metaData;
+ repeatedly<ReadAccess>(bind(&QMailStorePrivate::attemptMessagesMetaData, const_cast<QMailStorePrivate*>(this),
-+ cref(key), cref(properties), option, &metaData),
++ cref(key), cref(properties), option, &metaData),
+ "messagesMetaData");
+ return metaData;
+}
@@ -4375,7 +2611,7 @@ index 0000000..029ca4e
+ return false;
+ } else {
+ // result == DatabaseFailure
-+ if (queryError() == Sqlite3BusyErrorNumber) {
++ if (queryError() == "Sqlite3BusyErrorNumber") {
+ if (attemptCount < MaxAttempts) {
+ qMailLog(Messaging) << ::getpid() << "Failed to" << qPrintable(description) << "- busy, pausing to retry";
+
@@ -4389,7 +2625,7 @@ index 0000000..029ca4e
+ qMailLog(Messaging) << ::getpid() << "Retry count exceeded - failed to" << qPrintable(description);
+ break;
+ }
-+ } else if (queryError() == Sqlite3ConstraintErrorNumber) {
++ } else if (queryError() == "Sqlite3ConstraintErrorNumber") {
+ qMailLog(Messaging) << ::getpid() << "Unable to" << qPrintable(description) << "- constraint failure";
+ setLastError(QMailStore::ConstraintFailure);
+ break;
@@ -4407,7 +2643,7 @@ index 0000000..029ca4e
+ return false;
+}
+
-+QMailStorePrivate::AttemptResult QMailStorePrivate::addCustomFields(quint64 id, const QMap<QString, QString> &fields, const QString &tableName)
++QMailStorePrivate::AttemptResult QMailStorePrivate::addCustomFields(quint64 id, const QMap<QString, QString> &fields)
+{
+ if (!fields.isEmpty()) {
+ QVariantList customFields;
@@ -4419,35 +2655,21 @@ index 0000000..029ca4e
+ customFields.append(QVariant(it.key()));
+ customValues.append(QVariant(it.value()));
+ }
-+
-+ // Batch insert the custom fields
-+ QString sql("INSERT INTO %1 (id,name,value) VALUES (%2,?,?)");
-+ QSqlQuery query(batchQuery(sql.arg(tableName).arg(QString::number(id)),
-+ QVariantList() << QVariant(customFields)
-+ << QVariant(customValues),
-+ QString("%1 custom field insert query").arg(tableName)));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
++ // TBD: Add custom fields
++ Q_UNUSED(id);
+ }
+
+ return Success;
+}
+
-+QMailStorePrivate::AttemptResult QMailStorePrivate::updateCustomFields(quint64 id, const QMap<QString, QString> &fields, const QString &tableName)
++QMailStorePrivate::AttemptResult QMailStorePrivate::updateCustomFields(quint64 id, const QMap<QString, QString> &fields)
+{
+ QMap<QString, QString> existing;
+
+ {
+ // Find the existing fields
-+ QString sql("SELECT name,value FROM %1 WHERE id=?");
-+ QSqlQuery query(simpleQuery(sql.arg(tableName),
-+ QVariantList() << id,
-+ QString("%1 update custom select query").arg(tableName)));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ while (query.next())
-+ existing.insert(query.value(0).toString(), query.value(1).toString());
++ // TBD: Put actual code here
++ Q_UNUSED(id);
+ }
+
+ QVariantList obsoleteFields;
@@ -4476,338 +2698,30 @@ index 0000000..029ca4e
+ }
+ }
+
-+ if (!obsoleteFields.isEmpty()) {
-+ // Remove the obsolete fields
-+ QString sql("DELETE FROM %1 WHERE id=? AND name IN %2");
-+ QSqlQuery query(simpleQuery(sql.arg(tableName).arg(expandValueList(obsoleteFields)),
-+ QVariantList() << id << obsoleteFields,
-+ QString("%1 update custom delete query").arg(tableName)));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+
-+ if (!modifiedFields.isEmpty()) {
-+ // Batch update the modified fields
-+ QString sql("UPDATE %1 SET value=? WHERE id=%2 AND name=?");
-+ QSqlQuery query(batchQuery(sql.arg(tableName).arg(QString::number(id)),
-+ QVariantList() << QVariant(modifiedValues)
-+ << QVariant(modifiedFields),
-+ QString("%1 update custom update query").arg(tableName)));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+
-+ if (!addedFields.isEmpty()) {
-+ // Batch insert the added fields
-+ QString sql("INSERT INTO %1 (id,name,value) VALUES (%2,?,?)");
-+ QSqlQuery query(batchQuery(sql.arg(tableName).arg(QString::number(id)),
-+ QVariantList() << QVariant(addedFields)
-+ << QVariant(addedValues),
-+ QString("%1 update custom insert query").arg(tableName)));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+
-+ return Success;
-+}
-+
-+QMailStorePrivate::AttemptResult QMailStorePrivate::customFields(quint64 id, QMap<QString, QString> *fields, const QString &tableName)
-+{
-+ QString sql("SELECT name,value FROM %1 WHERE id=?");
-+ QSqlQuery query(simpleQuery(sql.arg(tableName),
-+ QVariantList() << id,
-+ QString("%1 custom field query").arg(tableName)));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ while (query.next())
-+ fields->insert(query.value(0).toString(), query.value(1).toString());
-+
++ // TBD: Update custom fields
+ return Success;
+}
+
-+/* Replaced with SPARQL
-+QMailStorePrivate::AttemptResult QMailStorePrivate::attemptAddAccount(QMailAccount *account, QMailAccountConfiguration* config,
-+ QMailAccountIdList *addedAccountIds,
-+ Transaction &t)
++QMailStorePrivate::AttemptResult QMailStorePrivate::customFields(quint64 id, QMap<QString, QString> *fields)
+{
-+ if (account->id().isValid() && idExists(account->id())) {
-+ qMailLog(Messaging) << "Account already exists in database, use update instead";
-+ return Failure;
-+ }
-+
-+ QMailAccountId insertId;
-+
-+ {
-+ QString properties("type,name,status,signature,emailaddress");
-+ QString values("?,?,?,?,?");
-+ QVariantList propertyValues;
-+ propertyValues << static_cast<int>(account->messageType())
-+ << account->name()
-+ << account->status()
-+ << account->signature()
-+ << account->fromAddress().toString(true);
-+
-+ {
-+ QSqlQuery query(simpleQuery(QString("INSERT INTO mailaccounts (%1) VALUES (%2)").arg(properties).arg(values),
-+ propertyValues,
-+ "addAccount mailaccounts query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ //Extract the insert id
-+ insertId = QMailAccountId(extractValue<quint64>(query.lastInsertId()));
-+ }
++ // TBD: Load information about custom fields
++ Q_UNUSED(id);
++ Q_UNUSED(fields);
+
-+ // Insert any standard folders configured for this account
-+ const QMap<QMailFolder::StandardFolder, QMailFolderId> &folders(account->standardFolders());
-+ if (!folders.isEmpty()) {
-+ QVariantList types;
-+ QVariantList folderIds;
-+
-+ QMap<QMailFolder::StandardFolder, QMailFolderId>::const_iterator it = folders.begin(), end = folders.end();
-+ for ( ; it != end; ++it) {
-+ types.append(QVariant(static_cast<int>(it.key())));
-+ folderIds.append(QVariant(it.value().toULongLong()));
-+ }
-+
-+ // Batch insert the folders
-+ QString sql("INSERT into mailaccountfolders (id,foldertype,folderid) VALUES (%1,?,?)");
-+ QSqlQuery query(batchQuery(sql.arg(QString::number(insertId.toULongLong())),
-+ QVariantList() << QVariant(types)
-+ << QVariant(folderIds),
-+ "addAccount mailaccountfolders query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+
-+ // Insert any custom fields belonging to this account
-+ AttemptResult result = addCustomFields(insertId.toULongLong(), account->customFields(), "mailaccountcustom");
-+ if (result != Success)
-+ return result;
-+ }
-+
-+ if (config) {
-+ foreach (const QString &service, config->services()) {
-+ QMailAccountConfiguration::ServiceConfiguration &serviceConfig(config->serviceConfiguration(service));
-+ const QMap<QString, QString> &fields = serviceConfig.values();
-+
-+ QVariantList configFields;
-+ QVariantList configValues;
-+
-+ // Insert any configuration fields belonging to this account
-+ QMap<QString, QString>::const_iterator it = fields.begin(), end = fields.end();
-+ for ( ; it != end; ++it) {
-+ configFields.append(QVariant(it.key()));
-+ configValues.append(QVariant(it.value()));
-+ }
-+
-+ // Batch insert the custom fields
-+ QString sql("INSERT INTO mailaccountconfig (id,service,name,value) VALUES (%1,'%2',?,?)");
-+ QSqlQuery query(batchQuery(sql.arg(QString::number(insertId.toULongLong())).arg(service),
-+ QVariantList() << QVariant(configFields)
-+ << QVariant(configValues),
-+ "addAccount mailaccountconfig query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+
-+ config->setId(insertId);
-+ }
-+
-+ account->setId(insertId);
-+
-+ if (!t.commit()) {
-+ qMailLog(Messaging) << "Could not commit account changes to database";
-+
-+ account->setId(QMailAccountId()); //revert the id
-+ return DatabaseFailure;
-+ }
-+
-+ addedAccountIds->append(insertId);
+ return Success;
+}
-+*/
-+/* Replaced with SQPARQL
-+QMailStorePrivate::AttemptResult QMailStorePrivate::attemptAddFolder(QMailFolder *folder,
-+ QMailFolderIdList *addedFolderIds, QMailAccountIdList *modifiedAccountIds,
-+ Transaction &t)
-+{
-+ //check that the parent folder actually exists
-+ if (!checkPreconditions(*folder))
-+ return Failure;
-+
-+ QMailFolderId insertId;
+
-+ {
-+ {
-+ QSqlQuery query(simpleQuery("INSERT INTO mailfolders (name,parentid,parentaccountid,displayname,status,servercount,serverunreadcount) VALUES (?,?,?,?,?,?,?)",
-+ QVariantList() << folder->path()
-+ << folder->parentFolderId().toULongLong()
-+ << folder->parentAccountId().toULongLong()
-+ << folder->displayName()
-+ << folder->status()
-+ << folder->serverCount()
-+ << folder->serverUnreadCount(),
-+ "addFolder mailfolders query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ // Extract the inserted id
-+ insertId = QMailFolderId(extractValue<quint64>(query.lastInsertId()));
-+ }
-+
-+ // Insert any custom fields belonging to this folder
-+ AttemptResult result = addCustomFields(insertId.toULongLong(), folder->customFields(), "mailfoldercustom");
-+ if (result != Success)
-+ return result;
-+ }
-+
-+ folder->setId(insertId);
-+
-+ //create links to ancestor folders
-+ if (folder->parentFolderId().isValid()) {
-+ {
-+ //add records for each ancestor folder
-+ QSqlQuery query(simpleQuery("INSERT INTO mailfolderlinks "
-+ "SELECT DISTINCT id,? FROM mailfolderlinks WHERE descendantid=?",
-+ QVariantList() << folder->id().toULongLong()
-+ << folder->parentFolderId().toULongLong(),
-+ "mailfolderlinks insert ancestors"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+
-+ {
-+ // Our direct parent is also an ancestor
-+ QSqlQuery query(simpleQuery("INSERT INTO mailfolderlinks VALUES (?,?)",
-+ QVariantList() << folder->parentFolderId().toULongLong()
-+ << folder->id().toULongLong(),
-+ "mailfolderlinks insert parent"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+ }
-+
-+ if (!t.commit()) {
-+ qMailLog(Messaging) << "Could not commit folder changes to database";
-+
-+ folder->setId(QMailFolderId()); //revert the id
-+ return DatabaseFailure;
-+ }
-+
-+ addedFolderIds->append(insertId);
-+ if (folder->parentAccountId().isValid())
-+ modifiedAccountIds->append(folder->parentAccountId());
-+ return Success;
-+}
-+*/
-+
-+/* Replaced with SQPARQL
-+QMailStorePrivate::AttemptResult QMailStorePrivate::attemptAddMessage(QMailMessageMetaData *metaData,
-+ QMailMessageIdList *addedMessageIds, QMailFolderIdList *modifiedFolderIds, QMailAccountIdList *modifiedAccountIds,
-+ Transaction &t)
-+{
-+ if (!metaData->parentFolderId().isValid()) {
-+ qMailLog(Messaging) << "Unable to add message. Invalid parent folder id";
-+ return Failure;
-+ }
-+
-+ if (metaData->id().isValid() && idExists(metaData->id())) {
-+ qMailLog(Messaging) << "Message ID" << metaData->id() << "already exists in database, use update instead";
-+ return Failure;
-+ }
-+
-+ // Ensure that any phone numbers are added in minimal form
-+ QMailAddress from(metaData->from());
-+ QString fromText(from.isPhoneNumber() ? from.minimalPhoneNumber() : from.toString());
-+
-+ QStringList recipients;
-+ foreach (const QMailAddress& address, metaData->to())
-+ recipients.append(address.isPhoneNumber() ? address.minimalPhoneNumber() : address.toString());
-+
-+ QMailMessageId insertId;
-+
-+ {
-+ // Add the record to the mailmessages table
-+ QSqlQuery query(simpleQuery("INSERT INTO mailmessages (type,"
-+ "parentfolderid,"
-+ "sender,"
-+ "recipients,"
-+ "subject,"
-+ "stamp,"
-+ "status,"
-+ "parentaccountid,"
-+ "mailfile,"
-+ "serveruid,"
-+ "size,"
-+ "contenttype,"
-+ "responseid,"
-+ "responsetype,"
-+ "receivedstamp"
-+ ") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
-+ QVariantList() << static_cast<int>(metaData->messageType())
-+ << metaData->parentFolderId().toULongLong()
-+ << fromText
-+ << recipients.join(",")
-+ << metaData->subject()
-+ << QMailTimeStamp(metaData->date()).toLocalTime()
-+ << static_cast<int>(metaData->status())
-+ << metaData->parentAccountId().toULongLong()
-+ << ::contentUri(*metaData)
-+ << metaData->serverUid()
-+ << metaData->size()
-+ << static_cast<int>(metaData->content())
-+ << metaData->inResponseTo().toULongLong()
-+ << metaData->responseType()
-+ << QMailTimeStamp(metaData->receivedDate()).toLocalTime(),
-+ "addMessage mailmessages query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ //retrieve the insert id
-+ insertId = QMailMessageId(extractValue<quint64>(query.lastInsertId()));
-+ }
-+
-+ // Insert any custom fields belonging to this message
-+ AttemptResult result = addCustomFields(insertId.toULongLong(), metaData->customFields(), "mailmessagecustom");
-+ if (result != Success)
-+ return result;
-+
-+ // Find the complete set of modified folders, including ancestor folders
-+ QMailFolderIdList folderIds;
-+ folderIds.append(metaData->parentFolderId());
-+ folderIds += folderAncestorIds(folderIds, true, &result);
-+ if (result != Success)
-+ return result;
-+
-+ if (!t.commit()) {
-+ qMailLog(Messaging) << "Could not commit message changes to database";
-+ return DatabaseFailure;
-+ }
-+
-+ metaData->setId(insertId);
-+ addedMessageIds->append(insertId);
-+ *modifiedFolderIds = folderIds;
-+ if (metaData->parentAccountId().isValid())
-+ modifiedAccountIds->append(metaData->parentAccountId());
-+ return Success;
-+}
-+*/
+
+QMailStorePrivate::AttemptResult QMailStorePrivate::attemptRemoveAccounts(const QMailAccountKey &key,
+ QMailAccountIdList *deletedAccounts, QMailFolderIdList *deletedFolders, QMailMessageIdList *deletedMessages,
+ Transaction &t)
+{
-+ QStringList expiredContent;
-+
-+ if (deleteAccounts(key, *deletedAccounts, *deletedFolders, *deletedMessages, expiredContent)) {
-+ if (t.commit()) {
-+ //remove deleted objects from caches
-+ removeExpiredData(*deletedMessages, expiredContent, *deletedFolders, *deletedAccounts);
-+ return Success;
-+ }
-+ }
++ // TBD: Delete accounts
++ Q_UNUSED(key);
++ Q_UNUSED(deletedAccounts);
++ Q_UNUSED(deletedFolders);
++ Q_UNUSED(deletedMessages);
++ Q_UNUSED(t);
+
+ return DatabaseFailure;
+}
@@ -4816,15 +2730,13 @@ index 0000000..029ca4e
+ QMailFolderIdList *deletedFolders, QMailMessageIdList *deletedMessages, QMailAccountIdList *modifiedAccounts,
+ Transaction &t)
+{
-+ QStringList expiredContent;
-+
-+ if (deleteFolders(key, option, *deletedFolders, *deletedMessages, expiredContent, *modifiedAccounts)) {
-+ if (t.commit()) {
-+ //remove deleted objects from caches
-+ removeExpiredData(*deletedMessages, expiredContent, *deletedFolders);
-+ return Success;
-+ }
-+ }
++ // TBD: Remove folders
++ Q_UNUSED(key);
++ Q_UNUSED(option);
++ Q_UNUSED(deletedFolders);
++ Q_UNUSED(deletedMessages);
++ Q_UNUSED(modifiedAccounts);
++ Q_UNUSED(t);
+
+ return DatabaseFailure;
+}
@@ -4833,15 +2745,13 @@ index 0000000..029ca4e
+ QMailMessageIdList *deletedMessages, QMailAccountIdList *modifiedAccounts, QMailFolderIdList *modifiedFolders,
+ Transaction &t)
+{
-+ QStringList expiredContent;
-+
-+ if (deleteMessages(key, option, *deletedMessages, expiredContent, *modifiedAccounts, *modifiedFolders)) {
-+ if (t.commit()) {
-+ //remove deleted objects from caches
-+ removeExpiredData(*deletedMessages, expiredContent);
-+ return Success;
-+ }
-+ }
++ // TBD: Remove messages
++ Q_UNUSED(key);
++ Q_UNUSED(option);
++ Q_UNUSED(deletedMessages);
++ Q_UNUSED(modifiedAccounts);
++ Q_UNUSED(modifiedFolders);
++ Q_UNUSED(t);
+
+ return DatabaseFailure;
+}
@@ -4850,221 +2760,13 @@ index 0000000..029ca4e
+ QMailAccountIdList *updatedAccountIds,
+ Transaction &t)
+{
++ Q_UNUSED(t);
++
+ QMailAccountId id(account ? account->id() : config ? config->id() : QMailAccountId());
+ if (!id.isValid())
+ return Failure;
+
+ if (account) {
-+ QString properties("type=?, name=?, status=?, signature=?, emailaddress=?");
-+ QVariantList propertyValues;
-+ propertyValues << static_cast<int>(account->messageType())
-+ << account->name()
-+ << account->status()
-+ << account->signature()
-+ << account->fromAddress().toString(true);
-+
-+ {
-+ QSqlQuery query(simpleQuery(QString("UPDATE mailaccounts SET %1 WHERE id=?").arg(properties),
-+ propertyValues << id.toULongLong(),
-+ "updateAccount mailaccounts query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+
-+ // Update any standard folders configured
-+ const QMap<QMailFolder::StandardFolder, QMailFolderId> &folders(account->standardFolders());
-+ QMap<QMailFolder::StandardFolder, QMailFolderId> existingFolders;
-+
-+ {
-+ // Find the existing folders
-+ QSqlQuery query(simpleQuery("SELECT foldertype,folderid FROM mailaccountfolders WHERE id=?",
-+ QVariantList() << id.toULongLong(),
-+ "updateAccount mailaccountfolders select query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ while (query.next())
-+ existingFolders.insert(QMailFolder::StandardFolder(query.value(0).toInt()), QMailFolderId(query.value(1).toULongLong()));
-+ }
-+
-+ QVariantList obsoleteTypes;
-+ QVariantList modifiedTypes;
-+ QVariantList modifiedFolders;
-+ QVariantList addedTypes;
-+ QVariantList addedFolders;
-+
-+ // Compare the sets
-+ QMap<QMailFolder::StandardFolder, QMailFolderId>::const_iterator fend = folders.end(), eend = existingFolders.end();
-+ QMap<QMailFolder::StandardFolder, QMailFolderId>::const_iterator it = existingFolders.begin();
-+ for ( ; it != eend; ++it) {
-+ QMap<QMailFolder::StandardFolder, QMailFolderId>::const_iterator current = folders.find(it.key());
-+ if (current == fend) {
-+ obsoleteTypes.append(QVariant(static_cast<int>(it.key())));
-+ } else if (*current != *it) {
-+ modifiedTypes.append(QVariant(static_cast<int>(current.key())));
-+ modifiedFolders.append(QVariant(current.value().toULongLong()));
-+ }
-+ }
-+
-+ for (it = folders.begin(); it != fend; ++it) {
-+ if (existingFolders.find(it.key()) == eend) {
-+ addedTypes.append(QVariant(static_cast<int>(it.key())));
-+ addedFolders.append(QVariant(it.value().toULongLong()));
-+ }
-+ }
-+
-+ if (!obsoleteTypes.isEmpty()) {
-+ // Remove the obsolete folders
-+ QString sql("DELETE FROM mailaccountfolders WHERE id=? AND foldertype IN %2");
-+ QSqlQuery query(simpleQuery(sql.arg(expandValueList(obsoleteTypes)),
-+ QVariantList() << id.toULongLong() << obsoleteTypes,
-+ "updateAccount mailaccountfolders delete query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+
-+ if (!modifiedTypes.isEmpty()) {
-+ // Batch update the modified folders
-+ QString sql("UPDATE mailaccountfolders SET folderid=? WHERE id=%2 AND foldertype=?");
-+ QSqlQuery query(batchQuery(sql.arg(QString::number(id.toULongLong())),
-+ QVariantList() << QVariant(modifiedFolders)
-+ << QVariant(modifiedTypes),
-+ "updateAccount mailaccountfolders update query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+
-+ if (!addedTypes.isEmpty()) {
-+ // Batch insert the added fields
-+ QString sql("INSERT INTO mailaccountfolders (id,foldertype,folderid) VALUES (%2,?,?)");
-+ QSqlQuery query(batchQuery(sql.arg(QString::number(id.toULongLong())),
-+ QVariantList() << QVariant(addedTypes)
-+ << QVariant(addedFolders),
-+ "updateAccount mailaccountfolders insert query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+
-+ if (account->customFieldsModified()) {
-+ AttemptResult result = updateCustomFields(id.toULongLong(), account->customFields(), "mailaccountcustom");
-+ if (result != Success)
-+ return result;
-+ }
-+ }
-+
-+ if (config) {
-+ // Find the complete set of configuration fields
-+ QMap<QPair<QString, QString>, QString> fields;
-+
-+ foreach (const QString &service, config->services()) {
-+ QMailAccountConfiguration::ServiceConfiguration &serviceConfig(config->serviceConfiguration(service));
-+ const QMap<QString, QString> &values = serviceConfig.values();
-+
-+ // Insert any configuration fields belonging to this account
-+ QMap<QString, QString>::const_iterator it = values.begin(), end = values.end();
-+ for ( ; it != end; ++it)
-+ fields.insert(qMakePair(service, it.key()), it.value());
-+ }
-+
-+ // Find the existing fields in the database
-+ QMap<QPair<QString, QString>, QString> existing;
-+
-+ {
-+ QSqlQuery query(simpleQuery("SELECT service,name,value FROM mailaccountconfig WHERE id=?",
-+ QVariantList() << id.toULongLong(),
-+ "updateAccount mailaccountconfig select query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ while (query.next())
-+ existing.insert(qMakePair(query.value(0).toString(), query.value(1).toString()), query.value(2).toString());
-+ }
-+
-+ QMap<QString, QVariantList> obsoleteFields;
-+ QMap<QString, QVariantList> modifiedFields;
-+ QMap<QString, QVariantList> modifiedValues;
-+ QMap<QString, QVariantList> addedFields;
-+ QMap<QString, QVariantList> addedValues;
-+
-+ // Compare the sets
-+ QMap<QPair<QString, QString>, QString>::const_iterator fend = fields.end(), eend = existing.end();
-+ QMap<QPair<QString, QString>, QString>::const_iterator it = existing.begin();
-+ for ( ; it != eend; ++it) {
-+ const QPair<QString, QString> &name = it.key();
-+ QMap<QPair<QString, QString>, QString>::const_iterator current = fields.find(name);
-+ if (current == fend) {
-+ obsoleteFields[name.first].append(QVariant(name.second));
-+ } else if (*current != *it) {
-+ modifiedFields[name.first].append(QVariant(name.second));
-+ modifiedValues[name.first].append(QVariant(current.value()));
-+ }
-+ }
-+
-+ for (it = fields.begin(); it != fend; ++it) {
-+ const QPair<QString, QString> &name = it.key();
-+ if (existing.find(name) == eend) {
-+ addedFields[name.first].append(QVariant(name.second));
-+ addedValues[name.first].append(QVariant(it.value()));
-+ }
-+ }
-+
-+ if (!obsoleteFields.isEmpty()) {
-+ // Remove the obsolete fields
-+ QMap<QString, QVariantList>::const_iterator it = obsoleteFields.begin(), end = obsoleteFields.end();
-+ for ( ; it != end; ++it) {
-+ const QString &service = it.key();
-+ const QVariantList &fields = it.value();
-+
-+ QString sql("DELETE FROM mailaccountconfig WHERE id=? AND service='%1' AND name IN %2");
-+ QSqlQuery query(simpleQuery(sql.arg(service).arg(expandValueList(fields)),
-+ QVariantList() << id.toULongLong() << fields,
-+ "updateAccount mailaccountconfig delete query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+ }
-+
-+ if (!modifiedFields.isEmpty()) {
-+ // Batch update the modified fields
-+ QMap<QString, QVariantList>::const_iterator it = modifiedFields.begin(), end = modifiedFields.end();
-+ for (QMap<QString, QVariantList>::const_iterator vit = modifiedValues.begin(); it != end; ++it, ++vit) {
-+ const QString &service = it.key();
-+ const QVariantList &fields = it.value();
-+ const QVariantList &values = vit.value();
-+
-+ QString sql("UPDATE mailaccountconfig SET value=? WHERE id=%1 AND service='%2' AND name=?");
-+ QSqlQuery query(batchQuery(sql.arg(QString::number(id.toULongLong())).arg(service),
-+ QVariantList() << QVariant(values) << QVariant(fields),
-+ "updateAccount mailaccountconfig update query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+ }
-+
-+ if (!addedFields.isEmpty()) {
-+ // Batch insert the added fields
-+ QMap<QString, QVariantList>::const_iterator it = addedFields.begin(), end = addedFields.end();
-+ for (QMap<QString, QVariantList>::const_iterator vit = addedValues.begin(); it != end; ++it, ++vit) {
-+ const QString &service = it.key();
-+ const QVariantList &fields = it.value();
-+ const QVariantList &values = vit.value();
-+
-+ QString sql("INSERT INTO mailaccountconfig (id,service,name,value) VALUES (%1,'%2',?,?)");
-+ QSqlQuery query(batchQuery(sql.arg(QString::number(id.toULongLong())).arg(service),
-+ QVariantList() << QVariant(fields) << QVariant(values),
-+ "updateAccount mailaccountconfig insert query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+ }
-+ }
-+
-+ if (!t.commit()) {
-+ qMailLog(Messaging) << "Could not commit account update to database";
-+ return DatabaseFailure;
-+ }
-+
-+ if (account) {
+ // Update the account cache
+ if (accountCache.contains(id))
+ accountCache.insert(*account);
@@ -5085,82 +2787,9 @@ index 0000000..029ca4e
+ QMailFolderId parentFolderId;
+ QMailAccountId parentAccountId;
+
-+ {
-+ //find the current parent folder
-+ QSqlQuery query(simpleQuery("SELECT parentid, parentaccountid FROM mailfolders WHERE id=?",
-+ QVariantList() << folder->id().toULongLong(),
-+ "mailfolder parent query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ if (query.first()) {
-+ parentFolderId = QMailFolderId(extractValue<quint64>(query.value(0)));
-+ parentAccountId = QMailAccountId(extractValue<quint64>(query.value(1)));
-+ }
-+ }
-+
-+ {
-+ QSqlQuery query(simpleQuery("UPDATE mailfolders SET name=?,parentid=?,parentaccountid=?,displayname=?,status=?,servercount=?,serverunreadcount=? WHERE id=?",
-+ QVariantList() << folder->path()
-+ << folder->parentFolderId().toULongLong()
-+ << folder->parentAccountId().toULongLong()
-+ << folder->displayName()
-+ << folder->status()
-+ << folder->serverCount()
-+ << folder->serverUnreadCount()
-+ << folder->id().toULongLong(),
-+ "updateFolder mailfolders query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+
-+ if (folder->customFieldsModified()) {
-+ AttemptResult result = updateCustomFields(folder->id().toULongLong(), folder->customFields(), "mailfoldercustom");
-+ if (result != Success)
-+ return result;
-+ }
-+
-+ if (parentFolderId != folder->parentFolderId()) {
-+ // QMailAccount contains a copy of the folder data; we need to tell it to reload
-+ if (parentFolderId.isValid())
-+ modifiedAccountIds->append(parentAccountId);
-+ if (folder->parentFolderId().isValid() && !modifiedAccountIds->contains(folder->parentAccountId()))
-+ modifiedAccountIds->append(folder->parentAccountId());
-+
-+ {
-+ //remove existing links to this folder
-+ QSqlQuery query(simpleQuery("DELETE FROM mailfolderlinks WHERE descendantid = ?",
-+ QVariantList() << folder->id().toULongLong(),
-+ "mailfolderlinks delete in update"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+
-+ {
-+ //add links to the new parent
-+ QSqlQuery query(simpleQuery("INSERT INTO mailfolderlinks "
-+ "SELECT DISTINCT id,? FROM mailfolderlinks WHERE descendantid=?",
-+ QVariantList() << folder->id().toULongLong()
-+ << folder->parentFolderId().toULongLong(),
-+ "mailfolderlinks insert ancestors"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+
-+ {
-+ QSqlQuery query(simpleQuery("INSERT INTO mailfolderlinks VALUES (?,?)",
-+ QVariantList() << folder->parentFolderId().toULongLong()
-+ << folder->id().toULongLong(),
-+ "mailfolderlinks insert parent"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+ }
-+
-+ if (!t.commit()) {
-+ qMailLog(Messaging) << "Could not commit folder update to database";
-+ return DatabaseFailure;
-+ }
++ // TBD: Update folder
++ Q_UNUSED(modifiedAccountIds);
++ Q_UNUSED(t);
+
+ //update the folder cache
+ if (folderCache.contains(folder->id()))
@@ -5190,34 +2819,8 @@ index 0000000..029ca4e
+ if (metaData->dataModified() || updateContent) {
+ // Find the existing properties
+ {
-+ QSqlQuery query(simpleQuery("SELECT parentaccountId,parentfolderId,mailfile FROM mailmessages WHERE id=?",
-+ QVariantList() << metaData->id().toULongLong(),
-+ "updateMessage existing properties query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ if (query.first()) {
-+ parentAccountId = QMailAccountId(extractValue<quint64>(query.value(0)));
-+ parentFolderId = QMailFolderId(extractValue<quint64>(query.value(1)));
-+ contentUri = extractValue<QString>(query.value(2));
-+
-+ // Find any folders affected by this update
-+ folderIds.append(metaData->parentFolderId());
-+ if (parentFolderId != metaData->parentFolderId()) {
-+ // The previous location folder has also changed
-+ folderIds.append(parentFolderId);
-+ metaData->setPreviousParentFolderId(parentFolderId);
-+ }
-+
-+ // Ancestor folders are also considered to be affected
-+ AttemptResult result;
-+ folderIds += folderAncestorIds(folderIds, true, &result);
-+ if (result != Success)
-+ return result;
-+ } else {
-+ qMailLog(Messaging) << "Could not query parent account, folder and content URI";
-+ return Failure;
-+ }
++ // TBD: Query database
++ Q_UNUSED(t);
+ }
+
+ if (updateContent) {
@@ -5271,16 +2874,11 @@ index 0000000..029ca4e
+ extractedValues = messageValues(updateProperties, *metaData);
+
+ {
-+ QString sql("UPDATE mailmessages SET %1 WHERE id=?");
-+ QSqlQuery query(simpleQuery(sql.arg(expandProperties(updateProperties, true)),
-+ extractedValues + (QVariantList() << metaData->id().toULongLong()),
-+ "updateMessage mailmessages update"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
++ // TBD: update exctracted values
+ }
+
+ if (metaData->customFieldsModified()) {
-+ AttemptResult result = updateCustomFields(metaData->id().toULongLong(), metaData->customFields(), "mailmessagecustom");
++ AttemptResult result = updateCustomFields(metaData->id().toULongLong(), metaData->customFields());
+ if (result != Success)
+ return result;
+
@@ -5288,11 +2886,6 @@ index 0000000..029ca4e
+ }
+ }
+
-+ if (!t.commit()) {
-+ qMailLog(Messaging) << "Could not commit folder update to database";
-+ return DatabaseFailure;
-+ }
-+
+ if (parentAccountId.isValid()) {
+ // The message is now up-to-date with data store
+ metaData->setUnmodified();
@@ -5376,92 +2969,20 @@ index 0000000..029ca4e
+ QMailMessageKey::Properties properties(props);
+
+ if (properties & QMailMessageKey::ParentFolderId) {
-+ if (!idExists(data.parentFolderId())) {
++ MailFolderUri folderUri(data.parentFolderId());
++ if (!uriExists(folderUri)) {
+ qMailLog(Messaging) << "Update of messages failed. Parent folder does not exist";
+ return Failure;
+ }
+ }
+
-+ QVariantList extractedValues;
-+
-+ //get the valid ids
-+ *updatedMessageIds = queryMessages(key, QMailMessageSortKey());
-+ if (!updatedMessageIds->isEmpty()) {
-+ // Find the set of folders and accounts whose contents are modified by this update
-+ QMailMessageKey modifiedMessageKey(QMailMessageKey::id(*updatedMessageIds));
-+ AttemptResult result = affectedByMessageIds(*updatedMessageIds, modifiedFolderIds, modifiedAccountIds);
-+ if (result != Success)
-+ return result;
-+
-+ // If we're setting parentFolderId, that folder is modified also
-+ if (properties & QMailMessageKey::ParentFolderId) {
-+ if (!modifiedFolderIds->contains(data.parentFolderId()))
-+ modifiedFolderIds->append(data.parentFolderId());
-+
-+ // All these messages need to have previousparentfolderid updated, where it will change
-+ QSqlQuery query(simpleQuery("UPDATE mailmessages SET previousparentfolderid=parentfolderid",
-+ QVariantList(),
-+ QList<Key>() << Key(modifiedMessageKey),
-+ "updateMessagesMetaData mailmessages previousparentfolderid update query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+
-+ if (properties & QMailMessageKey::Custom) {
-+ // Here, we can't compare the input to each target individually. Instead, remove
-+ // all custom fields from the affected messages, and add (or re-add) the new ones
-+ QVariantList addedFields;
-+ QVariantList addedValues;
-+
-+ const QMap<QString, QString> &fields = data.customFields();
-+ QMap<QString, QString>::const_iterator it = fields.begin(), end = fields.end();
-+ for ( ; it != end; ++it) {
-+ addedFields.append(QVariant(it.key()));
-+ addedValues.append(QVariant(it.value()));
-+ }
-+
-+ {
-+ // Remove the obsolete fields
-+ QSqlQuery query(simpleQuery("DELETE FROM mailmessagecustom",
-+ Key(modifiedMessageKey),
-+ "updateMessagesMetaData mailmessagecustom delete query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+
-+ if (!addedFields.isEmpty()) {
-+ foreach (const QMailMessageId &id, *updatedMessageIds) {
-+ // Batch insert the added fields
-+ QString sql("INSERT INTO mailmessagecustom (id,name,value) VALUES (%1,?,?)");
-+ QSqlQuery query(batchQuery(sql.arg(QString::number(id.toULongLong())),
-+ QVariantList() << QVariant(addedFields)
-+ << QVariant(addedValues),
-+ "updateMessagesMetaData mailmessagecustom insert query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+ }
-+
-+ properties &= ~QMailMessageKey::Custom;
-+ }
-+
-+ if (properties != 0) {
-+ extractedValues = messageValues(properties, data);
-+
-+ QString sql("UPDATE mailmessages SET %1");
-+ QSqlQuery query(simpleQuery(sql.arg(expandProperties(properties, true)),
-+ extractedValues,
-+ Key(modifiedMessageKey),
-+ "updateMessagesMetaData mailmessages query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+ }
++ // TBD: Update message metadata
++ Q_UNUSED(key);
++ Q_UNUSED(modifiedFolderIds);
++ Q_UNUSED(modifiedAccountIds);
++ Q_UNUSED(t);
+
-+ if (!t.commit()) {
-+ qMailLog(Messaging) << "Could not commit metadata update to database";
-+ return DatabaseFailure;
-+ }
++ QVariantList extractedValues;
+
+ // Update the header cache
+ foreach (const QMailMessageId& id, *updatedMessageIds) {
@@ -5482,27 +3003,11 @@ index 0000000..029ca4e
+{
+ //get the valid ids
+ *updatedMessageIds = queryMessages(key, QMailMessageSortKey());
-+ if (!updatedMessageIds->isEmpty()) {
-+ // Find the set of folders and accounts whose contents are modified by this update
-+ AttemptResult result = affectedByMessageIds(*updatedMessageIds, modifiedFolderIds, modifiedAccountIds);
-+ if (result != Success)
-+ return result;
+
-+ {
-+ QString sql("UPDATE mailmessages SET status=(status %1 ?)");
-+ QSqlQuery query(simpleQuery(sql.arg(set ? "|" : "&"),
-+ QVariantList() << (set ? status : ~status),
-+ Key(QMailMessageKey::id(*updatedMessageIds)),
-+ "updateMessagesMetaData status query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+ }
-+
-+ if (!t.commit()) {
-+ qMailLog(Messaging) << "Could not commit metadata status update to database";
-+ return DatabaseFailure;
-+ }
++ // TBD: Update status
++ Q_UNUSED(modifiedFolderIds);
++ Q_UNUSED(modifiedAccountIds);
++ Q_UNUSED(t);
+
+ // Update the header cache
+ foreach (const QMailMessageId& id, *updatedMessageIds) {
@@ -5523,43 +3028,11 @@ index 0000000..029ca4e
+ QMailMessageIdList *updatedMessageIds, QMailFolderIdList *modifiedFolderIds, QMailAccountIdList *modifiedAccountIds,
+ Transaction &t)
+{
-+ // Find the message and folders that are affected by this update
-+ QSqlQuery query(simpleQuery("SELECT t0.id, t0.parentfolderid, t0.previousparentfolderid FROM mailmessages t0",
-+ Key(key, "t0"),
-+ "restoreToPreviousFolder info query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ QSet<quint64> folderIdSet;
-+ while (query.next()) {
-+ updatedMessageIds->append(QMailMessageId(extractValue<quint64>(query.value(0))));
-+
-+ folderIdSet.insert(extractValue<quint64>(query.value(1)));
-+ folderIdSet.insert(extractValue<quint64>(query.value(2)));
-+ }
-+
-+ if (!folderIdSet.isEmpty()) {
-+ QMailFolderIdList folderIds;
-+ foreach (quint64 id, folderIdSet)
-+ folderIds.append(QMailFolderId(id));
-+
-+ // Find the set of folders and accounts whose contents are modified by this update
-+ AttemptResult result = affectedByFolderIds(folderIds, modifiedFolderIds, modifiedAccountIds);
-+ if (result != Success)
-+ return result;
-+
-+ // Update the message records
-+ QSqlQuery query(simpleQuery("UPDATE mailmessages SET parentfolderid=previousparentfolderid, previousparentfolderid=NULL",
-+ Key(QMailMessageKey::id(*updatedMessageIds)),
-+ "restoreToPreviousFolder update query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+
-+ if (!t.commit()) {
-+ qMailLog(Messaging) << "Could not commit message folder restoration to database";
-+ return DatabaseFailure;
-+ }
++ // TBD: Restore messages to previous folder
++ Q_UNUSED(key);
++ Q_UNUSED(modifiedFolderIds);
++ Q_UNUSED(modifiedAccountIds);
++ Q_UNUSED(t);
+
+ // Update the header cache
+ foreach (const QMailMessageId &id, *updatedMessageIds) {
@@ -5580,290 +3053,34 @@ index 0000000..029ca4e
+{
+ QMailMessageIdList removalIds;
+
-+ {
-+ QString sql("SELECT id FROM deletedmessages WHERE parentaccountid=?");
-+
-+ QVariantList bindValues;
-+ bindValues << accountId.toULongLong();
-+
-+ if (!serverUids.isEmpty()) {
-+ QVariantList uidValues;
-+ foreach (const QString& uid, serverUids)
-+ uidValues.append(uid);
-+
-+ sql.append(" AND serveruid IN %1");
-+ sql = sql.arg(expandValueList(uidValues));
-+
-+ bindValues << uidValues;
-+ }
-+
-+ QSqlQuery query(simpleQuery(sql,
-+ bindValues,
-+ "purgeMessageRemovalRecord info query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ while (query.next())
-+ removalIds.append(QMailMessageId(extractValue<quint64>(query.value(0))));
-+ }
-+
-+ // anything to remove?
-+ if (!removalIds.isEmpty()) {
-+ QSqlQuery query(simpleQuery("DELETE FROM deletedmessages",
-+ Key(QMailMessageKey::id(removalIds)),
-+ "purgeMessageRemovalRecord delete query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+ }
-+
-+ if (!t.commit()) {
-+ qMailLog(Messaging) << "Could not commit message removal record deletion to database";
-+ return DatabaseFailure;
-+ }
-+
-+ return Success;
-+}
-+
-+/* Replaced with SPARQL
-+QMailStorePrivate::AttemptResult QMailStorePrivate::attemptCountAccounts(const QMailAccountKey &key, int *result,
-+ ReadLock &)
-+{
-+ QSqlQuery query(simpleQuery("SELECT COUNT(*) FROM mailaccounts",
-+ Key(key),
-+ "countAccounts mailaccounts query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ if (query.first())
-+ *result = extractValue<int>(query.value(0));
-+
-+ return Success;
-+}
-+*/
-+
-+/* Replaced with SPARQL
-+QMailStorePrivate::AttemptResult QMailStorePrivate::attemptCountFolders(const QMailFolderKey &key, int *result,
-+ ReadLock &)
-+{
-+ QSqlQuery query(simpleQuery("SELECT COUNT(*) FROM mailfolders",
-+ Key(key),
-+ "countFolders mailfolders query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ if (query.first())
-+ *result = extractValue<int>(query.value(0));
++ // TBD: Purge remove records
++ Q_UNUSED(accountId);
++ Q_UNUSED(serverUids);
++ Q_UNUSED(t);
+
+ return Success;
+}
-+*/
+
-+/* Replaced with SPARQL
-+QMailStorePrivate::AttemptResult QMailStorePrivate::attemptCountMessages(const QMailMessageKey &key,
-+ int *result,
-+ ReadLock &)
-+{
-+ QSqlQuery query(simpleQuery("SELECT COUNT(*) FROM mailmessages",
-+ Key(key),
-+ "countMessages mailmessages query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ if (query.first())
-+ *result = extractValue<int>(query.value(0));
-+
-+ return Success;
-+}
-+*/
+
+QMailStorePrivate::AttemptResult QMailStorePrivate::attemptSizeOfMessages(const QMailMessageKey &key,
+ int *result,
+ ReadLock &)
+{
-+ QSqlQuery query(simpleQuery("SELECT SUM(size FROM mailmessages",
-+ Key(key),
-+ "sizeOfMessages mailmessages query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ if (query.first())
-+ *result = extractValue<int>(query.value(0));
++ // TBD: Count overal size of the messages
++ Q_UNUSED(key);
++ Q_UNUSED(result);
+
+ return Success;
+}
+
-+/* Replaced with SPARQL
-+QMailStorePrivate::AttemptResult QMailStorePrivate::attemptQueryAccounts(const QMailAccountKey &key, const QMailAccountSortKey &sortKey,
-+ QMailAccountIdList *ids,
-+ ReadLock &)
-+{
-+ QSqlQuery query(simpleQuery("SELECT id FROM mailaccounts",
-+ QVariantList(),
-+ QList<Key>() << Key(key) << Key(sortKey),
-+ "queryAccounts mailaccounts query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ while (query.next())
-+ ids->append(QMailAccountId(extractValue<quint64>(query.value(0))));
-+
-+ return Success;
-+}
-+*/
-+
-+/* Replaced with SPARQL
-+QMailStorePrivate::AttemptResult QMailStorePrivate::attemptQueryFolders(const QMailFolderKey &key, const QMailFolderSortKey &sortKey,
-+ QMailFolderIdList *ids,
-+ ReadLock &)
-+{
-+ QSqlQuery query(simpleQuery("SELECT id FROM mailfolders",
-+ QVariantList(),
-+ QList<Key>() << Key(key) << Key(sortKey),
-+ "queryFolders mailfolders query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ while (query.next())
-+ ids->append(QMailFolderId(extractValue<quint64>(query.value(0))));
-+
-+ return Success;
-+}
-+*/
-+
-+/* Replaced with SPARQL
-+QMailStorePrivate::AttemptResult QMailStorePrivate::attemptQueryMessages(const QMailMessageKey &key, const QMailMessageSortKey &sortKey,
-+ QMailMessageIdList *ids,
-+ ReadLock &)
-+{
-+ QSqlQuery query(simpleQuery("SELECT id FROM mailmessages",
-+ QVariantList(),
-+ QList<Key>() << Key(key) << Key(sortKey),
-+ "queryMessages mailmessages query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ while (query.next())
-+ ids->append(QMailMessageId(extractValue<quint64>(query.value(0))));
-+
-+ //store the results of this call for cache preloading
-+ lastQueryMessageResult = *ids;
-+
-+ return Success;
-+}
-+*/
-+
-+/* Replaced with SPARQL
-+QMailStorePrivate::AttemptResult QMailStorePrivate::attemptAccount(const QMailAccountId &id,
-+ QMailAccount *result,
-+ ReadLock &)
-+{
-+ {
-+ QSqlQuery query(simpleQuery("SELECT * FROM mailaccounts WHERE id=?",
-+ QVariantList() << id.toULongLong(),
-+ "account mailaccounts query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ if (query.first()) {
-+ *result = extractAccount(query.record());
-+ }
-+ }
-+
-+ if (result->id().isValid()) {
-+ {
-+ // Find any standard folders configured for this account
-+ QSqlQuery query(simpleQuery("SELECT foldertype,folderid FROM mailaccountfolders WHERE id=?",
-+ QVariantList() << id.toULongLong(),
-+ "account mailaccountfolders query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ while (query.next())
-+ result->setStandardFolder(QMailFolder::StandardFolder(query.value(0).toInt()), QMailFolderId(query.value(1).toULongLong()));
-+ }
-+
-+ // Find any custom fields for this account
-+ QMap<QString, QString> fields;
-+ AttemptResult attemptResult = customFields(id.toULongLong(), &fields, "mailaccountcustom");
-+ if (attemptResult != Success)
-+ return attemptResult;
-+
-+ result->setCustomFields(fields);
-+ result->setCustomFieldsModified(false);
-+
-+ {
-+ // Find the type of the account
-+ QSqlQuery query(simpleQuery("SELECT service,value FROM mailaccountconfig WHERE id=? AND name='servicetype'",
-+ QVariantList() << id.toULongLong(),
-+ "account mailaccountconfig query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ while (query.next()) {
-+ QString service(query.value(0).toString());
-+ QString type(query.value(1).toString());
-+
-+ if (type.contains("source")) {
-+ result->addMessageSource(service);
-+ }
-+ if (type.contains("sink")) {
-+ result->addMessageSink(service);
-+ }
-+ }
-+ }
-+
-+ //update cache
-+ accountCache.insert(*result);
-+ return Success;
-+ }
-+
-+ return Failure;
-+}
-+*/
-+
+QMailStorePrivate::AttemptResult QMailStorePrivate::attemptAccountConfiguration(const QMailAccountId &id,
+ QMailAccountConfiguration *result,
+ ReadLock &)
+{
-+ // Find any configuration fields for this account
-+ QSqlQuery query(simpleQuery("SELECT service,name,value FROM mailaccountconfig WHERE id=? ORDER BY service",
-+ QVariantList() << id.toULongLong(),
-+ "accountConfiguration mailaccountconfig query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ QString service;
-+ QMailAccountConfiguration::ServiceConfiguration *serviceConfig = 0;
-+
-+ while (query.next()) {
-+ QString svc(query.value(0).toString());
-+ if (svc != service) {
-+ service = svc;
-+
-+ if (!result->services().contains(service)) {
-+ // Add this service to the configuration
-+ result->addServiceConfiguration(service);
-+ }
-+
-+ serviceConfig = &result->serviceConfiguration(service);
-+ }
-+
-+ serviceConfig->setValue(query.value(1).toString(), query.value(2).toString());
-+ }
++ // TBD: Find any configuration fields for this account
+
-+ if (service.isEmpty()) {
-+ // No services - is this an error?
-+ QSqlQuery query(simpleQuery("SELECT COUNT(*) FROM mailaccounts WHERE id=?",
-+ QVariantList() << id.toULongLong(),
-+ "accountConfiguration mailaccounts query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
++ // TBD: Fill account configuration with information
+
-+ if (query.first()) {
-+ if (extractValue<int>(query.value(0)) == 0)
-+ return Failure;
-+ }
-+ }
+
+ result->setId(id);
+ result->setModified(false);
@@ -5871,69 +3088,6 @@ index 0000000..029ca4e
+ return Success;
+}
+
-+/* Replaced with SPARQL
-+QMailStorePrivate::AttemptResult QMailStorePrivate::attemptFolder(const QMailFolderId &id,
-+ QMailFolder *result,
-+ ReadLock &)
-+{
-+ {
-+ QSqlQuery query(simpleQuery("SELECT * FROM mailfolders WHERE id=?",
-+ QVariantList() << id.toULongLong(),
-+ "folder mailfolders query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ if (query.first()) {
-+ *result = extractFolder(query.record());
-+ }
-+ }
-+
-+ if (result->id().isValid()) {
-+ // Find any custom fields for this folder
-+ QMap<QString, QString> fields;
-+ AttemptResult attemptResult = customFields(id.toULongLong(), &fields, "mailfoldercustom");
-+ if (attemptResult != Success)
-+ return attemptResult;
-+
-+ result->setCustomFields(fields);
-+ result->setCustomFieldsModified(false);
-+
-+ //update cache
-+ folderCache.insert(*result);
-+ return Success;
-+ }
-+
-+ return Failure;
-+}
-+*/
-+
-+/* Replaced with SPARQL
-+QMailStorePrivate::AttemptResult QMailStorePrivate::attemptMessage(const QMailMessageId &id,
-+ QMailMessage *result,
-+ ReadLock &)
-+{
-+ // Find any custom fields for this message
-+ QMap<QString, QString> fields;
-+ AttemptResult attemptResult = customFields(id.toULongLong(), &fields, "mailmessagecustom");
-+ if (attemptResult != Success)
-+ return attemptResult;
-+
-+ QSqlQuery query(simpleQuery("SELECT * FROM mailmessages WHERE id=?",
-+ QVariantList() << id.toULongLong(),
-+ "message mailmessages id query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ if (query.first()) {
-+ *result = extractMessage(query.record(), fields);
-+ if (result->id().isValid())
-+ return Success;
-+ }
-+
-+ return Failure;
-+}
-+*/
-+
+QMailStorePrivate::AttemptResult QMailStorePrivate::attemptMessage(const QString &uid, const QMailAccountId &accountId,
+ QMailMessage *result,
+ ReadLock &lock)
@@ -5941,15 +3095,9 @@ index 0000000..029ca4e
+ quint64 id(0);
+
+ {
-+ QSqlQuery query(simpleQuery("SELECT id FROM mailmessages WHERE serveruid=? AND parentaccountid=?",
-+ QVariantList() << uid << accountId.toULongLong(),
-+ "message mailmessages uid/parentaccountid query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ if (query.first()) {
-+ id = extractValue<quint64>(query.value(0));
-+ }
++ // TBD: Search for the message with particular server UID
++ Q_UNUSED(uid);
++ Q_UNUSED(accountId);
+ }
+
+ if (id == 0) {
@@ -5959,31 +3107,17 @@ index 0000000..029ca4e
+ return attemptMessage(QMailMessageId(id), result, lock);
+}
+
-+QMailStorePrivate::AttemptResult QMailStorePrivate::attemptMessagesMetaData(const QMailMessageKey& key, const QMailMessageKey::Properties &properties, QMailStore::ReturnOption option,
-+ QMailMessageMetaDataList *result,
++QMailStorePrivate::AttemptResult QMailStorePrivate::attemptMessagesMetaData(const QMailMessageKey& key, const QMailMessageKey::Properties &properties, QMailStore::ReturnOption option,
++ QMailMessageMetaDataList *result,
+ ReadLock &)
+{
+ if (properties == QMailMessageKey::Custom) {
+ // We're only selecting custom fields
-+ QString sql("SELECT %1 name, value FROM mailmessagecustom WHERE id IN ( SELECT t0.id FROM mailmessages t0");
-+ sql += buildWhereClause(Key(key, "t0")) + " )";
-+
-+ QVariantList whereValues(::whereClauseValues(key));
-+ QSqlQuery query(simpleQuery(sql.arg(option == QMailStore::ReturnDistinct ? "DISTINCT " : ""),
-+ whereValues,
-+ "messagesMetaData combined query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
+
-+ // Find all the values for each parameter name in the set
++ // TBD: Search by custom fields
+ QMap<QString, QStringList> fields;
-+ while (query.next())
-+ fields[query.value(0).toString()].append(query.value(1).toString());
-+
-+ // Create records for each of these parameters
+ int maxLen = 0;
-+ foreach (const QStringList &list, fields.values())
-+ maxLen = qMax<uint>(maxLen, list.count());
++ Q_UNUSED(key);
+
+ for (int i = 0; i < maxLen; ++i)
+ result->append(QMailMessageMetaData());
@@ -6006,9 +3140,6 @@ index 0000000..029ca4e
+ qWarning() << "Warning: Distinct-ness is not supported with custom fields!";
+ }
+
-+ QString sql("SELECT %1 %2 FROM mailmessages t0");
-+ sql = sql.arg(option == QMailStore::ReturnDistinct ? "DISTINCT " : "");
-+
+ QMailMessageKey::Properties props(properties);
+
+ bool removeId(false);
@@ -6019,14 +3150,7 @@ index 0000000..029ca4e
+ }
+
+ {
-+ QSqlQuery query(simpleQuery(sql.arg(expandProperties(props, false)),
-+ Key(key, "t0"),
-+ "messagesMetaData mailmessages query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ while (query.next())
-+ result->append(extractMessageMetaData(query.record(), props, props));
++ // TBD: Search messages by fields
+ }
+
+ if (includeCustom) {
@@ -6034,7 +3158,7 @@ index 0000000..029ca4e
+ for ( ; it != end; ++it) {
+ // Add the custom fields to the record
+ QMap<QString, QString> fields;
-+ AttemptResult attemptResult = customFields((*it).id().toULongLong(), &fields, "mailmessagecustom");
++ AttemptResult attemptResult = customFields((*it).id().toULongLong(), &fields);
+ if (attemptResult != Success)
+ return attemptResult;
+
@@ -6055,23 +3179,10 @@ index 0000000..029ca4e
+ QMailMessageRemovalRecordList *result,
+ ReadLock &)
+{
-+ QVariantList values;
-+ values << accountId.toULongLong();
-+
-+ QString sql("SELECT * FROM deletedmessages WHERE parentaccountid=?");
-+ if (folderId.isValid()) {
-+ sql += " AND parentfolderid=?";
-+ values << folderId.toULongLong();
-+ }
-+
-+ QSqlQuery query(simpleQuery(sql,
-+ values,
-+ "messageRemovalRecords deletedmessages query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ while (query.next())
-+ result->append(extractMessageRemovalRecord(query.record()));
++ // TBD: Search for deleted messages
++ Q_UNUSED(accountId);
++ Q_UNUSED(folderId);
++ Q_UNUSED(result);
+
+ return Success;
+}
@@ -6080,14 +3191,9 @@ index 0000000..029ca4e
+ QMailFolderIdList *result,
+ ReadLock &)
+{
-+ QSqlQuery query(simpleQuery("SELECT DISTINCT t0.parentfolderid FROM mailmessages t0",
-+ Key(key, "t0"),
-+ "messageFolderIds folder select query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ while (query.next())
-+ result->append(QMailFolderId(extractValue<quint64>(query.value(0))));
++ // TBD: Look for message ID
++ Q_UNUSED(key);
++ Q_UNUSED(result);
+
+ return Success;
+}
@@ -6096,14 +3202,9 @@ index 0000000..029ca4e
+ QMailAccountIdList *result,
+ ReadLock &)
+{
-+ QSqlQuery query(simpleQuery("SELECT DISTINCT parentaccountid FROM mailfolders t0",
-+ Key(key, "t0"),
-+ "folderAccountIds account select query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ while (query.next())
-+ result->append(QMailAccountId(extractValue<quint64>(query.value(0))));
++ // TBD: Look for message folder ID
++ Q_UNUSED(key);
++ Q_UNUSED(result);
+
+ return Success;
+}
@@ -6112,19 +3213,9 @@ index 0000000..029ca4e
+ QMailFolderIdList *result,
+ ReadLock &)
+{
-+ QVariantList idValues;
-+ foreach (const QMailFolderId& id, ids)
-+ idValues.append(id.toULongLong());
-+
-+ QString sql("SELECT DISTINCT id FROM mailfolderlinks WHERE descendantid IN %1");
-+ QSqlQuery query(simpleQuery(sql.arg(expandValueList(idValues)),
-+ idValues,
-+ "folderAncestorIds id select query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ while (query.next())
-+ result->append(QMailFolderId(extractValue<quint64>(query.value(0))));
++ // TBD: Look for ancestor message folder ID
++ Q_UNUSED(ids);
++ Q_UNUSED(result);
+
+ return Success;
+}
@@ -6200,15 +3291,10 @@ index 0000000..029ca4e
+ int *result,
+ ReadLock &)
+{
-+ QSqlQuery query(simpleQuery("SELECT COALESCE(statusbit,0) FROM mailstatusflags WHERE name=? AND context=?",
-+ QVariantList() << name << context,
-+ "mailstatusflags select"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ *result = 0;
-+ if (query.next())
-+ *result = extractValue<int>(query.value(0));
++ // TBD: Find out wheither this status bit is present
++ Q_UNUSED(name);
++ Q_UNUSED(context);
++ Q_UNUSED(result);
+
+ return Success;
+}
@@ -6218,32 +3304,18 @@ index 0000000..029ca4e
+{
+ int highest = 0;
+
-+ {
-+ // Find the highest
-+ QSqlQuery query(simpleQuery("SELECT MAX(statusbit) FROM mailstatusflags WHERE context=?",
-+ QVariantList() << context,
-+ "mailstatusflags register select"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
-+
-+ if (query.next())
-+ highest = extractValue<int>(query.value(0));
-+ }
++ // TBD: Find out the highest bit
++ Q_UNUSED(name);
++ Q_UNUSED(context);
++ Q_UNUSED(t);
+
+ if (highest == maximum) {
+ return Failure;
+ } else {
-+ QSqlQuery query(simpleQuery("INSERT INTO mailstatusflags (name,context,statusbit) VALUES (?,?,?)",
-+ QVariantList() << name << context << (highest + 1),
-+ "mailstatusflags register insert"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return DatabaseFailure;
++ // TBD: Add new status bit
+ }
+
-+ if (!t.commit()) {
-+ qMailLog(Messaging) << "Could not commit statusflag changes to database";
-+ return DatabaseFailure;
-+ }
++ t.commit();
+
+ return Success;
+}
@@ -6278,7 +3350,8 @@ index 0000000..029ca4e
+
+ if(folder.parentFolderId().isValid())
+ {
-+ if(!idExists(folder.parentFolderId(),"mailfolders"))
++ MailFolderUri folderUri(folder.parentFolderId());
++ if(!uriExists(folderUri))
+ {
+ qMailLog(Messaging) << "Parent folder does not exist!";
+ return false;
@@ -6287,7 +3360,8 @@ index 0000000..029ca4e
+
+ if(folder.parentAccountId().isValid())
+ {
-+ if(!idExists(folder.parentAccountId(),"mailaccounts"))
++ MailAccountUri accountUri(folder.parentAccountId());
++ if(!uriExists(accountUri))
+ {
+ qMailLog(Messaging) << "Parent account does not exist!";
+ return false;
@@ -6304,103 +3378,13 @@ index 0000000..029ca4e
+ QMailAccountIdList& modifiedAccounts,
+ QMailFolderIdList& modifiedFolders)
+{
-+ QString elements("id,mailfile,parentaccountid,parentfolderId");
-+ if (option == QMailStore::CreateRemovalRecord)
-+ elements += ",serveruid,previousparentfolderid";
-+
-+ QVariantList removalAccountIds;
-+ QVariantList removalServerUids;
-+ QVariantList removalFolderIds;
-+
-+ {
-+ // Get the information we need to delete these messages
-+ QSqlQuery query(simpleQuery(QString("SELECT %1 FROM mailmessages").arg(elements),
-+ Key(key),
-+ "deleteMessages info query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return false;
-+
-+ while (query.next()) {
-+ QMailMessageId messageId(extractValue<quint64>(query.value(0)));
-+ deletedMessages.append(messageId);
-+
-+ QString contentUri(extractValue<QString>(query.value(1)));
-+ if (!contentUri.isEmpty())
-+ expiredContent.append(contentUri);
-+
-+ QMailAccountId parentAccountId(extractValue<quint64>(query.value(2)));
-+ if (!modifiedAccounts.contains(parentAccountId))
-+ modifiedAccounts.append(parentAccountId);
-+
-+ QMailFolderId folderId(extractValue<quint64>(query.value(3)));
-+ if (!modifiedFolders.contains(folderId))
-+ modifiedFolders.append(folderId);
-+
-+ if (option == QMailStore::CreateRemovalRecord) {
-+ // Extract the info needed to create removal records
-+ removalAccountIds.append(parentAccountId.toULongLong());
-+ removalServerUids.append(extractValue<QString>(query.value(4)));
-+ if (folderId == QMailFolderId(QMailFolder::TrashFolder)) {
-+ removalFolderIds.append(extractValue<quint64>(query.value(5)));
-+ } else {
-+ removalFolderIds.append(folderId.toULongLong());
-+ }
-+ }
-+ }
-+ }
-+
-+ // No messages? Then we're already done
-+ if (deletedMessages.isEmpty())
-+ return true;
-+
-+ // Any ancestor folders of the directly modified folders are indirectly modified
-+ QVariantList folderIdValues(idValueList(modifiedFolders));
-+
-+ if (!folderIdValues.isEmpty()) {
-+ QString sql("SELECT DISTINCT id FROM mailfolderlinks WHERE descendantid IN %1");
-+ QSqlQuery query(simpleQuery(sql.arg(expandValueList(folderIdValues)),
-+ folderIdValues,
-+ "deleteMessages mailfolderlinks ancestor query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return false;
-+
-+ while (query.next())
-+ modifiedFolders.append(QMailFolderId(extractValue<quint64>(query.value(0))));
-+ }
-+
-+ // Insert the removal records
-+ if (!removalAccountIds.isEmpty()) {
-+ // WARNING - QList::operator<<(QList) actually appends the list items to the object,
-+ // rather than insert the actual list!
-+ QSqlQuery query(batchQuery("INSERT INTO deletedmessages (parentaccountid,serveruid,parentfolderid) VALUES (?,?,?)",
-+ QVariantList() << QVariant(removalAccountIds)
-+ << QVariant(removalServerUids)
-+ << QVariant(removalFolderIds),
-+ "deleteMessages insert removal records query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return false;
-+ }
-+
-+ // Use the derived ID list rather than the key, in case the deletion statements affect the key result
-+ QVariantList idValues(idValueList(deletedMessages));
-+
-+ {
-+ // Delete any custom fields associated with these messages
-+ QString sql("DELETE FROM mailmessagecustom");
-+ QSqlQuery query(simpleQuery(sql, Key(QMailMessageKey::id(deletedMessages)),
-+ "deleteMessages delete mailmessagecustom query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return false;
-+ }
-+
-+ {
-+ // Perform the message deletion
-+ QString sql("DELETE FROM mailmessages");
-+ QSqlQuery query(simpleQuery(sql, Key(QMailMessageKey::id(deletedMessages)),
-+ "deleteMessages delete mailmessages query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return false;
-+ }
++ // TBD: Delete messages
++ Q_UNUSED(key);
++ Q_UNUSED(option);
++ Q_UNUSED(deletedMessages);
++ Q_UNUSED(expiredContent);
++ Q_UNUSED(modifiedAccounts);
++ Q_UNUSED(modifiedFolders);
+
+ return true;
+}
@@ -6412,76 +3396,13 @@ index 0000000..029ca4e
+ QStringList& expiredContent,
+ QMailAccountIdList& modifiedAccounts)
+{
-+ {
-+ // Get the identifiers for all the folders we're deleting
-+ QSqlQuery query(simpleQuery("SELECT t0.id FROM mailfolders t0",
-+ Key(key, "t0"),
-+ "deleteFolders info query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return false;
-+
-+ while (query.next())
-+ deletedFolders.append(QMailFolderId(extractValue<quint64>(query.value(0))));
-+ }
-+
-+ // No folders? Then we're already done
-+ if (deletedFolders.isEmpty())
-+ return true;
-+
-+ // Create a key to select messages in the folders to be deleted
-+ QMailMessageKey messagesKey(QMailMessageKey::parentFolderId(key));
-+
-+ // We won't report the modified folders, since they're about to be deleted
-+ QMailFolderIdList modifiedFolders;
-+
-+ // Delete all the messages contained by the folders we're deleting
-+ if (!deleteMessages(messagesKey, option, deletedMessages, expiredContent, modifiedAccounts, modifiedFolders))
-+ return false;
-+
-+ // Delete any references to these folders in the mailfolderlinks table
-+ QString statement("DELETE FROM mailfolderlinks WHERE %1 IN ( SELECT t0.id FROM mailfolders t0");
-+ statement += buildWhereClause(Key(key, "t0")) + " )";
-+
-+ QVariantList whereValues(::whereClauseValues(key));
-+
-+ {
-+ // Delete where target folders are ancestors
-+ QSqlQuery query(simpleQuery(statement.arg("id"),
-+ whereValues,
-+ "deleteFolders mailfolderlinks ancestor query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return false;
-+ }
-+
-+ {
-+ // Delete where target folders are descendants
-+ QSqlQuery query(simpleQuery(statement.arg("descendantid"),
-+ whereValues,
-+ "deleteFolders mailfolderlinks descendant query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return false;
-+ }
-+
-+ // Use the derived ID list rather than the key, in case the deletion statements affect the key result
-+ QVariantList idValues(idValueList(deletedFolders));
-+
-+ {
-+ // Delete any custom fields associated with these folders
-+ QString sql("DELETE FROM mailfoldercustom");
-+ QSqlQuery query(simpleQuery(sql, Key(QMailFolderKey::id(deletedFolders)),
-+ "deleteFolders delete mailfoldercustom query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return false;
-+ }
-+
-+ {
-+ // Perform the folder deletion
-+ QString sql("DELETE FROM mailfolders");
-+ QSqlQuery query(simpleQuery(sql, Key(QMailFolderKey::id(deletedFolders)),
-+ "deleteFolders delete mailfolders query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return false;
-+ }
++ // TBD: Delete folders, subfolders and all messages
++ Q_UNUSED(key);
++ Q_UNUSED(option);
++ Q_UNUSED(deletedFolders);
++ Q_UNUSED(deletedMessages);
++ Q_UNUSED(expiredContent);
++ Q_UNUSED(modifiedAccounts);
+
+ return true;
+}
@@ -6492,176 +3413,16 @@ index 0000000..029ca4e
+ QMailMessageIdList& deletedMessages,
+ QStringList& expiredContent)
+{
-+ {
-+ // Get the identifiers for all the accounts we're deleting
-+ QSqlQuery query(simpleQuery("SELECT t0.id FROM mailaccounts t0",
-+ Key(key, "t0"),
-+ "deleteAccounts info query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return false;
-+
-+ while (query.next())
-+ deletedAccounts.append(QMailAccountId(extractValue<quint64>(query.value(0))));
-+ }
-+
-+ // No accounts? Then we're already done
-+ if (deletedAccounts.isEmpty())
-+ return true;
-+
-+ // Create a key to select folders from the accounts to be deleted
-+ QMailFolderKey foldersKey(QMailFolderKey::parentAccountId(key));
-+
-+ // We won't create new message removal records, since there will be no account to link them to
-+ QMailStore::MessageRemovalOption option(QMailStore::NoRemovalRecord);
-+ QMailAccountIdList modifiedAccounts;
-+
-+ // Delete all the folders contained by the accounts we're deleting
-+ if (!deleteFolders(foldersKey, option, deletedFolders, deletedMessages, expiredContent, modifiedAccounts))
-+ return false;
-+
-+ // Also delete any messages belonging to these accounts, that aren't in folders owned by the accounts
-+
-+ // Create a key to select messages for the accounts to be deleted
-+ QMailMessageKey messagesKey(QMailMessageKey::parentAccountId(key));
-+
-+ // We won't report the modified folders, since they're about to be deleted
-+ QMailFolderIdList modifiedFolders;
-+
-+ // Delete all the messages contained by the folders we're deleting
-+ if (!deleteMessages(messagesKey, option, deletedMessages, expiredContent, modifiedAccounts, modifiedFolders))
-+ return false;
-+
-+ QVariantList idValues(idValueList(deletedAccounts));
-+
-+ {
-+ // Delete the removal records related to these accounts
-+ QString sql("DELETE FROM deletedmessages WHERE parentaccountid IN %1");
-+ QSqlQuery query(simpleQuery(sql.arg(expandValueList(idValues)),
-+ idValues,
-+ "deleteAccounts removal record delete query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return false;
-+ }
-+
-+ {
-+ // Remove any standard folders associated with these accounts
-+ QString sql("DELETE FROM mailaccountfolders WHERE id IN %1");
-+ QSqlQuery query(simpleQuery(sql.arg(expandValueList(idValues)),
-+ idValues,
-+ "deleteAccounts delete mailaccountfolders query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return false;
-+ }
-+
-+ {
-+ // Remove any custom fields associated with these accounts
-+ QString sql("DELETE FROM mailaccountcustom WHERE id IN %1");
-+ QSqlQuery query(simpleQuery(sql.arg(expandValueList(idValues)),
-+ idValues,
-+ "deleteAccounts delete mailaccountcustom query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return false;
-+ }
-+
-+ {
-+ // Remove any configuration fields associated with these accounts
-+ QString sql("DELETE FROM mailaccountconfig WHERE id IN %1");
-+ QSqlQuery query(simpleQuery(sql.arg(expandValueList(idValues)),
-+ idValues,
-+ "deleteAccounts delete mailaccountconfig query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return false;
-+ }
-+
-+ {
-+ // Perform the account deletion
-+ QString sql("DELETE FROM mailaccounts WHERE id IN %1");
-+ QSqlQuery query(simpleQuery(sql.arg(expandValueList(idValues)),
-+ idValues,
-+ "deleteAccounts delete mailaccounts query"));
-+ if (query.lastError().type() != QSqlError::NoError)
-+ return false;
-+ }
++ // TBD: Delete accounts, folders, subfolders and all messages
++ Q_UNUSED(key);
++ Q_UNUSED(deletedAccounts);
++ Q_UNUSED(deletedFolders);
++ Q_UNUSED(deletedMessages);
++ Q_UNUSED(expiredContent);
+
+ return true;
+}
+
-+QSqlQuery QMailStorePrivate::simpleQuery(const QString& statement, const QString& descriptor)
-+{
-+ return performQuery(statement, false, QVariantList(), QList<Key>(), descriptor);
-+}
-+
-+QSqlQuery QMailStorePrivate::simpleQuery(const QString& statement, const QVariantList& bindValues, const QString& descriptor)
-+{
-+ return performQuery(statement, false, bindValues, QList<Key>(), descriptor);
-+}
-+
-+QSqlQuery QMailStorePrivate::simpleQuery(const QString& statement, const Key& key, const QString& descriptor)
-+{
-+ return performQuery(statement, false, QVariantList(), QList<Key>() << key, descriptor);
-+}
-+
-+QSqlQuery QMailStorePrivate::simpleQuery(const QString& statement, const QVariantList& bindValues, const Key& key, const QString& descriptor)
-+{
-+ return performQuery(statement, false, bindValues, QList<Key>() << key, descriptor);
-+}
-+
-+QSqlQuery QMailStorePrivate::simpleQuery(const QString& statement, const QVariantList& bindValues, const QList<Key>& keys, const QString& descriptor)
-+{
-+ return performQuery(statement, false, bindValues, keys, descriptor);
-+}
-+
-+QSqlQuery QMailStorePrivate::batchQuery(const QString& statement, const QVariantList& bindValues, const QString& descriptor)
-+{
-+ return performQuery(statement, true, bindValues, QList<Key>(), descriptor);
-+}
-+
-+QSqlQuery QMailStorePrivate::batchQuery(const QString& statement, const QVariantList& bindValues, const Key& key, const QString& descriptor)
-+{
-+ return performQuery(statement, true, bindValues, QList<Key>() << key, descriptor);
-+}
-+
-+QSqlQuery QMailStorePrivate::batchQuery(const QString& statement, const QVariantList& bindValues, const QList<Key>& keys, const QString& descriptor)
-+{
-+ return performQuery(statement, true, bindValues, keys, descriptor);
-+}
-+
-+QSqlQuery QMailStorePrivate::performQuery(const QString& statement, bool batch, const QVariantList& bindValues, const QList<Key>& keys, const QString& descriptor)
-+{
-+ QString keyStatements;
-+ QVariantList keyValues;
-+
-+ bool firstClause(true);
-+ foreach (const Key &key, keys) {
-+ if (key.isType<QMailMessageKey>() || key.isType<QMailFolderKey>() || key.isType<QMailAccountKey>()) {
-+ keyStatements.append(buildWhereClause(key, false, firstClause));
-+ keyValues << whereClauseValues(key);
-+ } else if (key.isType<QMailMessageSortKey>() || key.isType<QMailFolderSortKey>() || key.isType<QMailAccountSortKey>()) {
-+ keyStatements.append(buildOrderClause(key));
-+ } else if (key.isType<QString>()) {
-+ keyStatements.append(key.key<QString>());
-+ }
-+
-+ firstClause = false;
-+ }
-+
-+ QSqlQuery query(prepare(statement + keyStatements));
-+ if (query.lastError().type() != QSqlError::NoError) {
-+ qMailLog(Messaging) << "Could not prepare query" << descriptor;
-+ } else {
-+ foreach (const QVariant& value, bindValues)
-+ query.addBindValue(value);
-+ foreach (const QVariant& value, keyValues)
-+ query.addBindValue(value);
-+
-+ if (!execute(query, batch)){
-+ qMailLog(Messaging) << "Could not execute query" << descriptor;
-+ }
-+ }
-+
-+ return query;
-+}
-+
+void QMailStorePrivate::emitIpcNotification(QMailStoreImplementation::AccountUpdateSignal signal, const QMailAccountIdList &ids)
+{
+ if ((signal == &QMailStore::accountsUpdated) || (signal == &QMailStore::accountsRemoved)) {
@@ -6692,7 +3453,6 @@ index 0000000..029ca4e
+ QMailStoreImplementation::emitIpcNotification(signal, ids);
+}
+
-+/* SPARQL Code */
+QMailStorePrivate::AttemptResult QMailStorePrivate::attemptAddMessage(QMailMessageMetaData *metaData,
+ QMailMessageIdList *addedMessageIds, QMailFolderIdList *modifiedFolderIds, QMailAccountIdList *modifiedAccountIds,
+ Transaction &t)
@@ -6704,43 +3464,44 @@ index 0000000..029ca4e
+ return Failure;
+ }
+
-+ SparqlUri uri("qmf://groove.harmattan.com/email#");
++ MailMessageUri messageUri;
++ MailFolderUri parentFolderUri(metaData->parentFolderId());
++ MailAccountUri parentAccountUri(metaData->parentAccountId());
++
+ SparqlQuery query(SparqlQuery::UpdateQuery);
+ query.prepare(QString(
+ "INSERT {\n"
-+ " <%1> rdf:type nmo:Email ;\n"
-+ " nie:isLogicalPartOf <qmf://groove.nokia.com/folder#%2> ;\n"
-+ " nmo:sender [\n"
-+ " rdf:type nco:Contact ;\n"
-+ " nco:fullname \"%3\" ; \n"
-+ " nco:hasEmailAddress <mailto:%4> ] ;\n"
-+
++ "%1 rdf:type nmo:Email ;\n"
++ " nie:isLogicalPartOf %2 ;\n"
++ " nmo:sender [\n"
++ " rdf:type nco:Contact ;\n"
++ " nco:fullname \"%3\" ; \n"
++ " nco:hasEmailAddress <mailto:%4> ] ;\n"
+ + nmoRecipients(metaData->to()) +
-+
-+ " nmo:messageSubject \"%5\" ;\n"
-+ " nmo:sentDate \"%6\"^^xsd:dateTime ;\n"
-+ " nmo:status \"%7\"^^xsd:integer ;\n"
-+ " nie:relatedTo <qmf://groove.nokia.com/accounts#%8> ;\n"
-+ " nie:isStoredAs [\n"
-+ " rdf:type nie:DataObject ;\n"
-+ " nie:dataSource <%9> ] ;\n"
-+ " nmo:messageId <%10> ;\n"
-+ " nie:contentSize \"%11\"^^xsd:integer ;\n"
-+ " nie:mimeType \"%12\" ;\n"
-+ " nmo:inReplyTo <%13> ;\n"
-+ " nmo:messageHeader [\n"
-+ " rdf:type nmo:MessageHeader ;\n"
-+ " nmo:headerName \"responseType\" ;\n"
-+ " nmo:headerValue \"%14\" ] ;\n"
-+ " nmo:receivedDate \"%15\"^^xsd:dateTime .\n"
-+ "}").arg(uri.uri())
-+ .arg(metaData->parentFolderId().toULongLong())
++ " nmo:messageSubject \"%5\" ;\n"
++ " nmo:sentDate \"%6\"^^xsd:dateTime ;\n"
++ " nmo:status \"%7\"^^xsd:integer ;\n"
++ " nie:relatedTo %8 ;\n"
++ " nie:isStoredAs [\n"
++ " rdf:type nie:DataObject ;\n"
++ " nie:dataSource <%9> ] ;\n"
++ " nmo:messageId \"%10\" ;\n"
++ " nie:contentSize \"%11\"^^xsd:integer ;\n"
++ " nie:mimeType \"%12\" ;\n"
++ " nmo:inReplyTo \"%13\" ;\n"
++ " nmo:messageHeader [\n"
++ " rdf:type nmo:MessageHeader ;\n"
++ " nmo:headerName \"responseType\" ;\n"
++ " nmo:headerValue \"%14\" ] ;\n"
++ " nmo:receivedDate \"%15\"^^xsd:dateTime .\n"
++ "}").arg(messageUri.uri())
++ .arg(parentFolderUri.uri())
+ .arg(metaData->from().name())
+ .arg(metaData->from().address())
+ .arg(metaData->subject())
+ .arg(QMailTimeStamp(metaData->date()).toLocalTime().toString())
+ .arg(static_cast<int>(metaData->status()))
-+ .arg(metaData->parentAccountId().toULongLong())
++ .arg(parentAccountUri.uri())
+ .arg(::contentUri(*metaData))
+ .arg(metaData->serverUid())
+ .arg(metaData->size())
@@ -6758,12 +3519,13 @@ index 0000000..029ca4e
+ }
+
+ qDebug() << "Query succeeded";
-+ metaData->setId(QMailMessageId(uri.id()));
++ metaData->setId(QMailMessageId(messageUri.id()));
+
+ addedMessageIds->append(metaData->id());
+ *modifiedFolderIds = QMailFolderIdList() << metaData->parentFolderId();
+ if (metaData->parentAccountId().isValid())
+ modifiedAccountIds->append(metaData->parentAccountId());
++
+ return Success;
+}
+
@@ -6777,22 +3539,25 @@ index 0000000..029ca4e
+ if (!checkPreconditions(*folder))
+ return Failure;
+
-+ SparqlUri uri("qmf://groove.nokia.com/folder#");
++ MailFolderUri folderUri;
++ MailFolderUri parentFolderUri(folder->parentFolderId());
++ MailAccountUri parentAccountUri(folder->parentAccountId());
++
+ SparqlQuery query(SparqlQuery::UpdateQuery);
+ query.prepare(QString(
+ "INSERT { \n"
-+ "<%1> rdf:type nmo:MailFolder ; \n"
++ "%1 rdf:type nmo:MailFolder ; \n"
+ " nmo:folderName \"%2\" ; \n"
-+ " nie:isLogicalPartOf <qmf://groove.nokia.com/folder#%3> ; \n"
-+ " nie:relatedTo <qmf://groove.nokia.com/accounts#%4> ; \n"
++ " nie:isLogicalPartOf %3 ; \n"
++ " nie:relatedTo %4 ; \n"
+ " nmo:folderDisplayName \"%5\" ; \n"
+ " nmo:status \"%6\"^^xsd:integer ; \n"
+ " nmo:serverCount \"%7\"^^xsd:integer ; \n"
+ " nmo:serverUnreadCount \"%8\"^^xsd:integet . \n"
-+ "}").arg(uri.uri())
++ "}").arg(folderUri.uri())
+ .arg(folder->path())
-+ .arg(folder->parentFolderId().toULongLong())
-+ .arg(folder->parentAccountId().toULongLong())
++ .arg(parentFolderUri.uri())
++ .arg(parentAccountUri.uri())
+ .arg(folder->displayName())
+ .arg(folder->status())
+ .arg(folder->serverCount())
@@ -6807,13 +3572,14 @@ index 0000000..029ca4e
+ }
+
+ qDebug() << "Query succeeded";
-+ folder->setId(QMailFolderId(uri.id()));
++ folder->setId(QMailFolderId(folderUri.id()));
+
+ // TBD: Update folder links also
+
+ addedFolderIds->append(folder->id());
+ if (folder->parentAccountId().isValid())
+ modifiedAccountIds->append(folder->parentAccountId());
++
+ return Success;
+}
+
@@ -6821,27 +3587,27 @@ index 0000000..029ca4e
+ QMailAccountIdList *addedAccountIds,
+ Transaction &t)
+{
++ Q_UNUSED(config);
+ Q_UNUSED(t);
+
-+ SparqlUri uri("qmf://groove.nokia.com/accounts#");
++ MailAccountUri accountUri;
+ SparqlQuery query(SparqlQuery::UpdateQuery);
+ query.prepare(QString(
+ "INSERT { \n"
-+ "<%1> rdf:type nmo:Mailbox ; \n"
++ "%1 rdf:type nmo:Mailbox ; \n"
+ " nmo:accountName \"%2\" ; \n"
+ " nmo:status \"%3\"^^xsd:integer ; \n"
+ " nmo:signature \"%4\" ; \n"
+ " nmo:fromAddress [ \n"
+ " rdf:type nco:EmailAddress ; \n"
+ " nco:emailAddress \"%5\" ] . \n"
-+ "}").arg(uri.uri())
++ "}").arg(accountUri.uri())
+ .arg(account->name())
+ .arg(account->status())
+ .arg(account->signature())
+ .arg(account->fromAddress().toString(true)));
+
+ // TBD: Add custom fields later
-+ // TBD: Add account configuration
+
+ if (!query.exec())
+ {
@@ -6850,7 +3616,7 @@ index 0000000..029ca4e
+ }
+
+ qDebug() << "Query succeeded";
-+ account->setId(QMailAccountId(uri.id()));
++ account->setId(QMailAccountId(accountUri.id()));
+
+ addedAccountIds->append(account->id());
+ return Success;
@@ -6860,20 +3626,19 @@ index 0000000..029ca4e
+ QMailAccount *result,
+ ReadLock &)
+{
-+ QMailAccount account;
-+
++ MailAccountUri messageUri(id);
+ SparqlQuery query(SparqlQuery::SearchQuery);
+ query.prepare(QString(
+ "SELECT ?name ?signature ?fromAddress \n"
+ "WHERE { \n"
-+ "<qmf://groove.nokia.com/accounts#%1> rdf:type nmo:Mailbox ; \n"
++ "%1 rdf:type nmo:Mailbox ; \n"
+ " nmo:accountName ?name ; \n"
+// " nmo:status ?status ; \n"
+ " nmo:signature ?signature ; \n"
+ " nmo:fromAddress [ \n"
+ " rdf:type nco:EmailAddress ; \n"
+ " nco:emailAddress ?fromAddress ] . \n"
-+ "}").arg(id.toULongLong()));
++ "}").arg(messageUri.uri()));
+
+ if (!query.exec())
+ {
@@ -6882,18 +3647,9 @@ index 0000000..029ca4e
+ }
+
+ SparqlResult res = query.result();
-+
+ Q_ASSERT(!res.end());
+
-+ QStringList list = res.fetchRow();
-+
-+ account.setId(id);
-+ account.setName(list.at(0));
-+// account.setStatus(list.at(1).toULongLong());
-+ account.setSignature(list.at(1));
-+ account.setFromAddress(QMailAddress(list.at(2)));
-+
-+ *result = account;
++ *result = extractAccount(id, res.fetchRow());
+
+ // Update cache
+ accountCache.insert(*result);
@@ -6905,11 +3661,12 @@ index 0000000..029ca4e
+ QMailFolder *result,
+ ReadLock &)
+{
++ MailFolderUri folderUri(id);
+ SparqlQuery query(SparqlQuery::SearchQuery);
+ query.prepare(QString(
+ "SELECT ?name ?parentFolder ?parentAccount ?displayName \n"
+ "WHERE { \n"
-+ "<qmf://groove.nokia.com/folder#%1> rdf:type nmo:MailFolder ; \n"
++ "%1 rdf:type nmo:MailFolder ; \n"
+ " nmo:folderName ?name ; \n"
+ " nie:isLogicalPartOf ?parentFolder ; \n"
+ " nie:relatedTo ?parentAccount ; \n"
@@ -6917,7 +3674,7 @@ index 0000000..029ca4e
+// " nmo:status ?status ; \n"
+// " nmo:serverCount ?serverCount ; \n"
+// " nmo:serverUnreadCount ?serverUnreadCount . \n"
-+ "}").arg(id.toULongLong()));
++ "}").arg(folderUri.uri()));
+
+ if (!query.exec())
+ {
@@ -6926,22 +3683,13 @@ index 0000000..029ca4e
+ }
+
+ SparqlResult res = query.result();
-+
+ Q_ASSERT(!res.end());
+
-+ QStringList list = res.fetchRow();
++ *result = extractFolder(id, res.fetchRow());
+
-+ QMailFolder folder(list.at(0), IdFromUri<QMailFolderId>(list.at(1)), IdFromUri<QMailAccountId>(list.at(2)));
-+ folder.setId(id);
-+ folder.setDisplayName(list.at(3));
-+// folder.setStatus(list.at(4).toULongLong());
-+// folder.setServerCount(list.at(5).toUInt());
-+// folder.setServerUnreadCount(list.at(6).toUInt());
-+
-+ *result = folder;
-+
-+ //update cache
++ // Update cache
+ folderCache.insert(*result);
++
+ return Success;
+}
+
@@ -6952,16 +3700,17 @@ index 0000000..029ca4e
+ if (!id.isValid())
+ return Failure;
+
++ MailMessageUri messageUri(id);
+ SparqlQuery query(SparqlQuery::SearchQuery);
+ query.prepare(QString(
+ "SELECT ?fullName ?mailAddress \n"
+ "WHERE { \n"
-+ "<qmf://groove.harmattan.com/email#%1> rdf:type nmo:Email ;\n"
-+ "nmo:recipient [\n"
-+ " rdf:type nco:Contact ;\n"
-+ " nco:fullname ?fullName ; \n"
-+ " nco:hasEmailAddress ?mailAddress ] \n"
-+ "}").arg(id.toULongLong()));
++ "%1 rdf:type nmo:Email ; \n"
++ " nmo:recipient [ \n"
++ " rdf:type nco:Contact ; \n"
++ " nco:fullname ?fullName ; \n"
++ " nco:hasEmailAddress ?mailAddress ] \n"
++ "}").arg(messageUri.uri()));
+
+ if (!query.exec())
+ {
@@ -6981,29 +3730,29 @@ index 0000000..029ca4e
+ query.prepare(QString(
+ "SELECT ?folderId ?senderFullName ?senderEmailAddress ?messageSubject ?sentDate ?status ?accountId ?dataSource ?uid ?contentSize ?mimeType ?inReplyTo ?headerValue ?receivedDate \n"
+ "WHERE { \n"
-+ " <qmf://groove.harmattan.com/email#%1> rdf:type nmo:Email ;\n"
-+ " nie:isLogicalPartOf ?folderId ;\n"
-+ " nmo:sender [\n"
-+ " rdf:type nco:Contact ;\n"
-+ " nco:fullname ?senderFullName ; \n"
-+ " nco:hasEmailAddress ?senderEmailAddress ] ;\n"
-+ " nmo:messageSubject ?messageSubject ;\n"
-+ " nmo:sentDate ?sentDate ;\n"
-+ " nmo:status ?status ;\n"
-+ " nie:relatedTo ?accountId ;\n"
-+ " nie:isStoredAs [\n"
-+ " rdf:type nie:DataObject ;\n"
-+ " nie:dataSource ?dataSource ] ;\n"
-+ " nmo:messageId ?uid ;\n"
-+ " nie:contentSize ?contentSize ;\n"
-+ " nie:mimeType ?mimeType ;\n"
-+ " nmo:inReplyTo ?inReplyTo ;\n"
-+ " nmo:messageHeader [\n"
-+ " rdf:type nmo:MessageHeader ;\n"
-+ " nmo:headerName \"responseType\" ;\n"
-+ " nmo:headerValue ?headerValue ] ;\n"
-+ " nmo:receivedDate ?receivedDate .\n"
-+ "}").arg(id.toULongLong()));
++ "%1 rdf:type nmo:Email ;\n"
++ " nie:isLogicalPartOf ?folderId ;\n"
++ " nmo:sender [\n"
++ " rdf:type nco:Contact ;\n"
++ " nco:fullname ?senderFullName ; \n"
++ " nco:hasEmailAddress ?senderEmailAddress ] ;\n"
++ " nmo:messageSubject ?messageSubject ;\n"
++ " nmo:sentDate ?sentDate ;\n"
++ " nmo:status ?status ;\n"
++ " nie:relatedTo ?accountId ;\n"
++ " nie:isStoredAs [\n"
++ " rdf:type nie:DataObject ;\n"
++ " nie:dataSource ?dataSource ] ;\n"
++ " nmo:messageId ?uid ;\n"
++ " nie:contentSize ?contentSize ;\n"
++ " nie:mimeType ?mimeType ;\n"
++ " nmo:inReplyTo ?inReplyTo ;\n"
++ " nmo:messageHeader [\n"
++ " rdf:type nmo:MessageHeader ;\n"
++ " nmo:headerName \"responseType\" ;\n"
++ " nmo:headerValue ?headerValue ] ;\n"
++ " nmo:receivedDate ?receivedDate .\n"
++ "}").arg(messageUri.uri()));
+
+ if (!query.exec())
+ {
@@ -7012,26 +3761,11 @@ index 0000000..029ca4e
+ }
+
+ res = query.result();
-+
+ Q_ASSERT(!res.end());
+
-+ QStringList list = res.fetchRow();
-+
+ QMailMessage message;
+ message.setId(id);
-+ message.setParentFolderId(IdFromUri<QMailFolderId>(list.at(0)));
-+ message.setFrom(QMailAddress(list.at(1), list.at(2)));
-+ message.setSubject(list.at(3));
-+ message.setDate(QMailTimeStamp(list.at(4)));
-+ message.setStatus(list.at(5).toULongLong());
-+ message.setParentAccountId(IdFromUri<QMailAccountId>(list.at(6)));
-+ message.setServerUid(list.at(10));
-+ message.setSize(list.at(9).toUInt());
-+ message.setContent((QMailMessageMetaDataFwd::ContentType)list.at(10).toInt());
-+ message.setInResponseTo(QMailMessageId(IdFromUri<QMailMessageId>(list.at(11))));
-+ message.setResponseType((QMailMessageMetaDataFwd::ResponseType)list.at(12).toInt());
-+ message.setReceivedDate(QMailTimeStamp(list.at(13)));
-+
++ extractMessageMetaData(res.fetchRow(), &message);
+ message.setTo(recipients);
+
+ *result = message;
@@ -7044,12 +3778,7 @@ index 0000000..029ca4e
+ ReadLock &)
+{
+ SparqlQuery query(SparqlQuery::SearchQuery);
-+ query.prepare(QString(
-+ "SELECT ?account \n"
-+ "WHERE { \n"
-+ " ?account rdf:type nmo:Mailbox . \n"
-+ + accountConstraint("?account", key) +
-+ "} \n"));
++ query.prepare(keyQuery(key, sortKey));
+
+ if (!query.exec())
+ {
@@ -7075,12 +3804,7 @@ index 0000000..029ca4e
+ ReadLock &)
+{
+ SparqlQuery query(SparqlQuery::SearchQuery);
-+ query.prepare(QString(
-+ "SELECT ?folder \n"
-+ "WHERE { \n"
-+ " ?folder rdf:type nmo:MailFolder . \n"
-+ + folderConstraint("?folder", key) +
-+ "} \n"));
++ query.prepare(keyQuery(key, sortKey));
+
+ if (!query.exec())
+ {
@@ -7106,12 +3830,7 @@ index 0000000..029ca4e
+ ReadLock &)
+{
+ SparqlQuery query(SparqlQuery::SearchQuery);
-+ query.prepare(QString(
-+ "SELECT ?message \n"
-+ "WHERE { \n"
-+ " ?message rdf:type nmo:Email . \n"
-+ + messageConstraint("?message", key) +
-+ "} \n"));
++ query.prepare(keyQuery(key, sortKey));
+
+ if (!query.exec())
+ {
@@ -7136,12 +3855,7 @@ index 0000000..029ca4e
+ ReadLock &)
+{
+ SparqlQuery query(SparqlQuery::SearchQuery);
-+ query.prepare(QString(
-+ "SELECT COUNT(?accountId) AS count \n"
-+ "WHERE { \n"
-+ " ?accountId rdf:type nmo:Mailbox . \n"
-+ + accountConstraint("?accountId", key) +
-+ "} \n"));
++ query.prepare(keyCount(key));
+
+ if (!query.exec())
+ {
@@ -7162,12 +3876,7 @@ index 0000000..029ca4e
+ ReadLock &)
+{
+ SparqlQuery query(SparqlQuery::SearchQuery);
-+ query.prepare(QString(
-+ "SELECT COUNT(?folderId) AS count \n"
-+ "WHERE { \n"
-+ " ?folderId rdf:type nmo:MailFolder . \n"
-+ + folderConstraint("?folderId", key) +
-+ "} \n"));
++ query.prepare(keyCount(key));
+
+ if (!query.exec())
+ {
@@ -7189,12 +3898,7 @@ index 0000000..029ca4e
+ ReadLock &)
+{
+ SparqlQuery query(SparqlQuery::SearchQuery);
-+ query.prepare(QString(
-+ "SELECT COUNT(?emailId) AS count \n"
-+ "WHERE { \n"
-+ " ?emailId rdf:type nmo:Email . \n"
-+ + messageConstraint("?emailId", key) +
-+ "} \n"));
++ query.prepare(keyCount(key));
+
+ if (!query.exec())
+ {
@@ -7212,10 +3916,10 @@ index 0000000..029ca4e
+}
diff --git a/src/libraries/qtopiamail/qmailstore_sparql.h b/src/libraries/qtopiamail/qmailstore_sparql.h
new file mode 100644
-index 0000000..e7ec13a
+index 0000000..4d185cd
--- /dev/null
+++ b/src/libraries/qtopiamail/qmailstore_sparql.h
-@@ -0,0 +1,530 @@
+@@ -0,0 +1,470 @@
+/****************************************************************************
+**
+** This file is part of the $PACKAGE_NAME$.
@@ -7243,7 +3947,6 @@ index 0000000..e7ec13a
+#include "qmailstoreimplementation_p.h"
+#include "sparqldatabase.h"
+
-+#include <QSqlDatabase>
+#include <QCache>
+
+//#define QMAILSTORE_LOG_SQL //define to enable SQL query logging
@@ -7255,7 +3958,8 @@ index 0000000..e7ec13a
+
+class ProcessMutex;
+class ProcessReadLock;
-+
++class SparqlResult;
++class SparqlQuery;
+
+class QMailStorePrivate : public QMailStoreImplementation
+{
@@ -7343,7 +4047,6 @@ index 0000000..e7ec13a
+ QMailMessageMetaData messageMetaData(const QMailMessageId &id) const;
+ QMailMessageMetaData messageMetaData(const QString &uid, const QMailAccountId &accountId) const;
+ QMailMessageMetaDataList messagesMetaData(const QMailMessageKey &key, const QMailMessageKey::Properties &properties, QMailStore::ReturnOption option) const;
-+
+ QMailMessageRemovalRecordList messageRemovalRecords(const QMailAccountId &parentAccountId, const QMailFolderId &parentFolderId) const;
+
+ bool registerAccountStatusFlag(const QString &name);
@@ -7355,21 +4058,13 @@ index 0000000..e7ec13a
+ bool registerMessageStatusFlag(const QString &name);
+ quint64 messageStatusMask(const QString &name) const;
+
-+ QString buildOrderClause(const Key& key) const;
-+
-+ QString buildWhereClause(const Key& key, bool nested = false, bool firstClause = true) const;
-+ QVariantList whereClauseValues(const Key& key) const;
-+
+ static QString expandValueList(const QVariantList& valueList);
+ static QString expandValueList(int valueCount);
+
-+ static QString temporaryTableName(const QMailMessageKey &key);
-+
+ template<typename ValueType>
+ static ValueType extractValue(const QVariant& var, const ValueType &defaultValue = ValueType());
+
+private:
-+ friend class Transaction;
+ friend class ReadLock;
+
+ enum AttemptResult { Success = 0, Failure, DatabaseFailure };
@@ -7388,59 +4083,15 @@ index 0000000..e7ec13a
+ bool containsProperty(const QMailMessageKey::Property& p, const QMailMessageKey& key) const;
+ bool containsProperty(const QMailMessageSortKey::Property& p, const QMailMessageSortKey& sortkey) const;
+
-+ QString expandProperties(const QMailMessageKey::Properties& p, bool update = false) const;
-+
+ int databaseIdentifier(int n) const;
+
-+ bool ensureVersionInfo();
-+ qint64 tableVersion(const QString &name) const;
-+ bool setTableVersion(const QString &name, qint64 version);
-+
-+ qint64 incrementTableVersion(const QString &name, qint64 current);
-+ bool upgradeTableVersion(const QString &name, qint64 current, qint64 final);
-+
-+ bool createTable(const QString &name);
-+
-+ typedef QPair<QString, qint64> TableInfo;
-+ bool setupTables(const QList<TableInfo> &tableList);
-+
-+ typedef QPair<quint64, QString> FolderInfo;
-+ bool setupFolders(const QList<FolderInfo> &folderList);
-+
-+ void createTemporaryTable(const QMailMessageKey &key) const;
-+ void destroyTemporaryTables(void);
++ bool setupStandardFolder(QMailFolder::StandardFolder folder, const QString& name);
+
-+ bool transaction(void);
-+ bool commit(void);
-+ void rollback(void);
-+
-+ void setQueryError(const QSqlError&, const QString& description = QString(), const QString& statement = QString());
++ void setQueryError(const SparqlQuery& query, const QString& description = QString());
++ QString queryError() const;
+ void clearQueryError(void);
+
-+ QSqlQuery prepare(const QString& sql);
-+ bool execute(QSqlQuery& q, bool batch = false);
-+ int queryError(void) const;
-+
-+ QSqlQuery performQuery(const QString& statement, bool batch, const QVariantList& bindValues, const QList<Key>& keys, const QString& descriptor);
-+
-+ bool executeFile(QFile &file);
-+
-+ QSqlQuery simpleQuery(const QString& statement, const QString& descriptor);
-+ QSqlQuery simpleQuery(const QString& statement, const QVariantList& bindValues, const QString& descriptor);
-+
-+ QSqlQuery simpleQuery(const QString& statement, const Key& key, const QString& descriptor);
-+ QSqlQuery simpleQuery(const QString& statement, const QVariantList& bindValues, const Key& key, const QString& descriptor);
-+ QSqlQuery simpleQuery(const QString& statement, const QVariantList& bindValues, const QList<Key>& keys, const QString& descriptor);
-+
-+ QSqlQuery batchQuery(const QString& statement, const QVariantList& bindValues, const QString& descriptor);
-+ QSqlQuery batchQuery(const QString& statement, const QVariantList& bindValues, const Key& key, const QString& descriptor);
-+ QSqlQuery batchQuery(const QString& statement, const QVariantList& bindValues, const QList<Key>& keys, const QString& descriptor);
-+
-+ bool idValueExists(quint64 id, const QString& table);
-+
-+ bool idExists(const QMailAccountId& id, const QString& table = QString());
-+ bool idExists(const QMailFolderId& id, const QString& table = QString());
-+ bool idExists(const QMailMessageId& id, const QString& table = QString());
++ bool uriExists(const QString& uri);
+
+ bool checkPreconditions(const QMailFolder& folder, bool update = false);
+
@@ -7478,9 +4129,9 @@ index 0000000..e7ec13a
+ template<typename AccessType, typename FunctionType>
+ bool repeatedly(FunctionType func, const QString &description) const;
+
-+ AttemptResult addCustomFields(quint64 id, const QMap<QString, QString> &fields, const QString &tableName);
-+ AttemptResult updateCustomFields(quint64 id, const QMap<QString, QString> &fields, const QString &tableName);
-+ AttemptResult customFields(quint64 id, QMap<QString, QString> *fields, const QString &tableName);
++ AttemptResult addCustomFields(quint64 id, const QMap<QString, QString> &fields);
++ AttemptResult updateCustomFields(quint64 id, const QMap<QString, QString> &fields);
++ AttemptResult customFields(quint64 id, QMap<QString, QString> *fields);
+
+ AttemptResult attemptAddAccount(QMailAccount *account, QMailAccountConfiguration* config,
+ QMailAccountIdList *addedAccountIds,
@@ -7587,7 +4238,7 @@ index 0000000..e7ec13a
+ QMailMessage *result,
+ ReadLock &);
+
-+ AttemptResult attemptMessagesMetaData(const QMailMessageKey& key, const QMailMessageKey::Properties &properties, QMailStore::ReturnOption option,
++ AttemptResult attemptMessagesMetaData(const QMailMessageKey& key, const QMailMessageKey::Properties &properties, QMailStore::ReturnOption option,
+ QMailMessageMetaDataList *result,
+ ReadLock &);
+
@@ -7614,11 +4265,10 @@ index 0000000..e7ec13a
+ AttemptResult attemptRegisterStatusBit(const QString &name, const QString &context, int maximum,
+ Transaction &t);
+
-+ QMailAccount extractAccount(const QSqlRecord& r);
-+ QMailFolder extractFolder(const QSqlRecord& r);
-+ QMailMessageMetaData extractMessageMetaData(const QSqlRecord& r, QMailMessageKey::Properties recordProperties, const QMailMessageKey::Properties& properties = allMessageProperties());
-+ QMailMessage extractMessage(const QSqlRecord& r, const QMap<QString, QString> &customFields, const QMailMessageKey::Properties& properties = allMessageProperties());
-+ QMailMessageRemovalRecord extractMessageRemovalRecord(const QSqlRecord& r);
++ QMailAccount extractAccount(const QMailAccountId& id, const QStringList& list);
++ QMailFolder extractFolder(const QMailFolderId& id, const QStringList& list);
++ void extractMessageMetaData(const QStringList& list, QMailMessageMetaData* metaData);
++ QMailMessageRemovalRecord extractMessageRemovalRecord(const QStringList& r);
+
+ virtual void emitIpcNotification(QMailStoreImplementation::AccountUpdateSignal signal, const QMailAccountIdList &ids);
+ virtual void emitIpcNotification(QMailStoreImplementation::FolderUpdateSignal signal, const QMailFolderIdList &ids);
@@ -7629,8 +4279,6 @@ index 0000000..e7ec13a
+ static const int accountCacheSize = 10;
+ static const int lookAhead = 5;
+
-+ static QString parseSql(QTextStream& ts);
-+
+ static QVariantList messageValues(const QMailMessageKey::Properties& properties, const QMailMessageMetaData& data);
+ static void updateMessageValues(const QMailMessageKey::Properties& properties, const QVariantList& values, const QMap<QString, QString>& customFields, QMailMessageMetaData& metaData);
+
@@ -7639,8 +4287,6 @@ index 0000000..e7ec13a
+ static QString messageFilePath(const QString &fileName);
+ static int pathIdentifier(const QString &filePath);
+
-+ static void extractMessageMetaData(const QSqlRecord& r, QMailMessageKey::Properties recordProperties, const QMailMessageKey::Properties& properties, QMailMessageMetaData* metaData);
-+
+private:
+ template <typename T, typename ID>
+ class Cache
@@ -7659,8 +4305,6 @@ index 0000000..e7ec13a
+ QCache<quint64,T> mCache;
+ };
+
-+ mutable QSqlDatabase database;
-+
+ mutable QMailMessageIdList lastQueryMessageResult;
+
+ mutable Cache<QMailMessageMetaData, QMailMessageId> headerCache;
@@ -7672,7 +4316,7 @@ index 0000000..e7ec13a
+ QList<const QMailMessageKey*> expiredTableKeys;
+
+ bool inTransaction;
-+ mutable int lastQueryError;
++ mutable QString lastQueryError;
+
+ ProcessMutex *mutex;
+ ProcessReadLock *readLock;
@@ -7882,12 +4526,40 @@ index d63acdf..ce4b0a7 100644
}
QString QMail::sslCertsPath()
+diff --git a/src/libraries/sparql/include/SparqlDatabase b/src/libraries/sparql/include/SparqlDatabase
+new file mode 100644
+index 0000000..ac92cb7
+--- /dev/null
++++ b/src/libraries/sparql/include/SparqlDatabase
+@@ -0,0 +1 @@
++#include "sparqldatabase.h"
+diff --git a/src/libraries/sparql/include/SparqlQuery b/src/libraries/sparql/include/SparqlQuery
+new file mode 100644
+index 0000000..bf9b61e
+--- /dev/null
++++ b/src/libraries/sparql/include/SparqlQuery
+@@ -0,0 +1 @@
++#include "sparqlquery.h"
+diff --git a/src/libraries/sparql/include/SparqlResult b/src/libraries/sparql/include/SparqlResult
+new file mode 100644
+index 0000000..8e66d59
+--- /dev/null
++++ b/src/libraries/sparql/include/SparqlResult
+@@ -0,0 +1 @@
++#include "sparqlresult.h"
+diff --git a/src/libraries/sparql/include/SparqlUri b/src/libraries/sparql/include/SparqlUri
+new file mode 100644
+index 0000000..52d7ed8
+--- /dev/null
++++ b/src/libraries/sparql/include/SparqlUri
+@@ -0,0 +1 @@
++#include "sparqluri.h"
diff --git a/src/libraries/sparql/sparql.pro b/src/libraries/sparql/sparql.pro
new file mode 100644
-index 0000000..7a56540
+index 0000000..b323449
--- /dev/null
+++ b/src/libraries/sparql/sparql.pro
-@@ -0,0 +1,31 @@
+@@ -0,0 +1,39 @@
+TEMPLATE = lib
+
+TARGET = sparql
@@ -7897,13 +4569,18 @@ index 0000000..7a56540
+QT *= dbus
+
+# Input
-+HEADERS += sparqldatabase.h \
-+ sparqlquery.h \
-+ sparqlresult.h \
-+ tracker/registertypes.h \
-+ tracker/resourcesproxy.h \
-+ sparqluri.h
-+SOURCES += sparqldatabase.cpp \
++DBUS_HEADERS += tracker/registertypes.h \
++ tracker/resourcesproxy.h
++
++SPARQL_HEADERS += sparqldatabase.h \
++ sparqlquery.h \
++ sparqlresult.h \
++ sparqluri.h
++
++HEADERS += $$DBUS_HEADERS $$SPARQL_HEADERS
++
++SOURCES += \
++ sparqldatabase.cpp \
+ sparqlquery.cpp \
+ sparqlresult.cpp \
+ tracker/registertypes.cpp \
@@ -7911,20 +4588,23 @@ index 0000000..7a56540
+ sparqluri.cpp
+
+# Install headers
-+headers.files = $$HEADERS include/*
-+headers.path = $$QMF_INSTALL_ROOT/include/qmf
++sparql_headers.files = $$SPARQL_HEADERS include/*
++sparql_headers.path = $$QMF_INSTALL_ROOT/include/qmf
+
-+INSTALLS += headers
++dbus_headers.files = $$DBUS_HEADERS
++dbus_headers.path = $$QMF_INSTALL_ROOT/include/qmf/tracker
++
++INSTALLS += sparql_headers dbus_headers
+
+target.path += $$QMF_INSTALL_ROOT/lib
+
+INSTALLS += target
diff --git a/src/libraries/sparql/sparqldatabase.cpp b/src/libraries/sparql/sparqldatabase.cpp
new file mode 100644
-index 0000000..dce2971
+index 0000000..7568a09
--- /dev/null
+++ b/src/libraries/sparql/sparqldatabase.cpp
-@@ -0,0 +1,31 @@
+@@ -0,0 +1,44 @@
+#include "sparqldatabase.h"
+
+#include <QDBusConnection>
@@ -7934,7 +4614,8 @@ index 0000000..dce2971
+
+
+SparqlDatabase::SparqlDatabase(const QString& databaseName) :
-+ _proxy(databaseName, "/org/freedesktop/Tracker/Resources", QDBusConnection::sessionBus())
++ _proxy(databaseName, "/org/freedesktop/Tracker/Resources", QDBusConnection::sessionBus()),
++ _databaseName(databaseName)
+{
+ qDebug() << "SparqlDatabase::SparqlDatabase";
+ if (!_defaultDatabase)
@@ -7956,26 +4637,38 @@ index 0000000..dce2971
+{
+ return _defaultDatabase;
+}
++
++QString SparqlDatabase::databaseName() const
++{
++ return _databaseName;
++}
++
++bool SparqlDatabase::isOpenError() const
++{
++ // Check wheither we are connected
++ bool isConnected = _proxy.connection().isConnected();
++ return !isConnected;
++}
diff --git a/src/libraries/sparql/sparqldatabase.h b/src/libraries/sparql/sparqldatabase.h
new file mode 100644
-index 0000000..5b8c246
+index 0000000..ab1d6b5
--- /dev/null
+++ b/src/libraries/sparql/sparqldatabase.h
-@@ -0,0 +1,44 @@
+@@ -0,0 +1,59 @@
+#ifndef SPARQLDATABASE_H
+#define SPARQLDATABASE_H
+
+#include "tracker/resourcesproxy.h"
+
+/**
-+ * @brief SparqlDatabase represents connection to the SPARQL data base.
++ * \brief SparqlDatabase represents connection to the SPARQL data base.
+ *
+ * SparqlDatabase represents connection to the SPARQL data base. It relies on the
+ * proxy implementation. It is possible to keep several databases opened at the same
+ * time, but only one of them will be default. All queries without exact database
+ * specification will be performed with default database.
+ *
-+ * @see SparqlQuery
++ * \see SparqlQuery
+ */
+class SparqlDatabase
+{
@@ -7983,35 +4676,50 @@ index 0000000..5b8c246
+
+public:
+ /**
-+ * @brief Creates new database
++ * \brief Creates new database
+ *
-+ * @param databaseName Name of the data base.
++ * \param databaseName Name of the data base.
+ */
+ SparqlDatabase(const QString& databaseName = "org.freedesktop.Tracker");
-+ /// Default destructor
-+ ~SparqlDatabase();
+
++ /**
++ * \brief Default destructor
++ */
++ ~SparqlDatabase();
+
+ /**
-+ * @brief Returns default database
++ * \brief Returns default database
+ *
+ * First created database will become default one.
++ *
++ * \return Pointer to the default database.
+ */
+ static SparqlDatabase* defaultDatabase();
+
++ /**
++ * \brief Returns name of the database
++ */
++ QString databaseName() const;
++
++ /**
++ * \brief Returns true wheither there was an error during opening database.
++ */
++ bool isOpenError() const;
++
+private:
+ static SparqlDatabase* _defaultDatabase;
+
+ ResourcesProxy _proxy;
++ QString _databaseName;
+};
+
+#endif // SPARQLDATABASE_H
diff --git a/src/libraries/sparql/sparqlquery.cpp b/src/libraries/sparql/sparqlquery.cpp
new file mode 100644
-index 0000000..3241e07
+index 0000000..951c115
--- /dev/null
+++ b/src/libraries/sparql/sparqlquery.cpp
-@@ -0,0 +1,81 @@
+@@ -0,0 +1,86 @@
+#include "sparqlquery.h"
+#include "sparqldatabase.h"
+#include "sparqlresult.h"
@@ -8093,12 +4801,17 @@ index 0000000..3241e07
+{
+ return _error;
+}
++
++QString SparqlQuery::query() const
++{
++ return _query;
++}
diff --git a/src/libraries/sparql/sparqlquery.h b/src/libraries/sparql/sparqlquery.h
new file mode 100644
-index 0000000..bca2387
+index 0000000..a030cfb
--- /dev/null
+++ b/src/libraries/sparql/sparqlquery.h
-@@ -0,0 +1,84 @@
+@@ -0,0 +1,102 @@
+#ifndef SPARQLQUERY_H
+#define SPARQLQUERY_H
+
@@ -8110,7 +4823,7 @@ index 0000000..bca2387
+class SparqlResult;
+
+/**
-+ * @brief SparqlQuery represents SPARQL query.
++ * \brief SparqlQuery represents SPARQL query.
+ *
+ * There are two different types of queries: search and update queries. Search query uses standard SPARQL syntax
+ * and can only read information from the database. Update queries exploit Advanced SPARQL syntax and allow to
@@ -8119,14 +4832,16 @@ index 0000000..bca2387
+ * Database can be defeined explicitely or default database can be used. In anycase at least one SparqlDatabase
+ * object must be created.
+ *
-+ * @see SparqlDatabase
++ * \see SparqlDatabase
+ */
+class SparqlQuery
+{
+ friend class SparqlResult;
+
+public:
-+ /// Type of the query
++ /**
++ * \brief Type of the query
++ */
+ enum QueryType
+ {
+ SearchQuery, ///< Query can use SELECT, CONSTRUCT, DESCRIBE or ASK SPARQL statments
@@ -8134,22 +4849,29 @@ index 0000000..bca2387
+ };
+
+ /**
-+ * @brief Constructs SPARQL query
++ * \brief Constructs SPARQL query
+ *
-+ * @param type Type of the quey.
-+ * @param query Query string, It can be defined later with prepare() method.
-+ * @param database Pointer to the database. Default database will be used in case of NULL.
++ * \param type Type of the quey.
++ * \param query Query string, It can be defined later with prepare() method.
++ * \param database Pointer to the database. Default database will be used in case of NULL.
+ */
+ SparqlQuery(QueryType type, const QString& query = QString(), SparqlDatabase* database = NULL);
+
-+ /// Default destructor
++ /**
++ * \brief Default destructor
++ */
+ ~SparqlQuery();
+
-+ /// Prepare query for execution
++ /**
++ * \brief Prepare query for execution
++ *
++ * \param SPARQL query to prepare.
++ * \return Status of the application.
++ */
+ bool prepare(const QString query);
+
+ /**
-+ * @brief Execute prepared query
++ * \brief Execute prepared query
+ *
+ * Before executing a query it has to be prepared using prepare() method.
+ * In case of any errors exec() will return false. More detailes information
@@ -8158,20 +4880,29 @@ index 0000000..bca2387
+ * Result of query execution can be retrieved using result() method.
+ * Retult is available only for Search queries.
+ *
-+ * @return true in case of success and false in case of failure.
++ * \return true in case of success and false in case of failure.
+ */
+ bool exec();
+
+ /**
-+ * @brief Returns result of the operation
++ * \brief Returns result of the operation
+ *
-+ * @return result can be NULL in case of error or Update query was executed.
++ * \return result can be NULL in case of error or Update query was executed.
+ */
+ SparqlResult result() const;
+
-+ /// Returns textual representation of the error.
++ /**
++ * \brief Returns textual representation of the error.
++ *
++ * \return Literal error description.
++ */
+ QString error() const;
+
++ /**
++ * \brief Returns prepared SPARQL query to execute.
++ */
++ QString query() const;
++
+private:
+ QueryType _type;
+ QString _query;
@@ -8222,10 +4953,10 @@ index 0000000..de7f2a0
+}
diff --git a/src/libraries/sparql/sparqlresult.h b/src/libraries/sparql/sparqlresult.h
new file mode 100644
-index 0000000..a6ce68e
+index 0000000..2c9be91
--- /dev/null
+++ b/src/libraries/sparql/sparqlresult.h
-@@ -0,0 +1,46 @@
+@@ -0,0 +1,56 @@
+#ifndef SPARQLRESULT_H
+#define SPARQLRESULT_H
+
@@ -8235,7 +4966,7 @@ index 0000000..a6ce68e
+class SparqlQuery;
+
+/**
-+ * @brief SparqlResult provides convenient way to fetch data from the executed query.
++ * \brief SparqlResult provides convenient way to fetch data from the executed query.
+ *
+ * To fetch data from already executed query you have to get instance of that class
+ * with SparqlQuery::result() method and call fetchRow() method till you reach the end().
@@ -8245,23 +4976,33 @@ index 0000000..a6ce68e
+ * to the query and you should not access any methods of this class in case of SparqlQuery
+ * was destroyed.
+ *
-+ * @see SparqlQuery
++ * \see SparqlQuery
+ */
+class SparqlResult
+{
+ friend class SparqlQuery;
+
+public:
-+ /// Fetch the row with results of the query
++ /**
++ * \brief Fetch the row with results of the query
++ *
++ * \return List of values of the row.
++ */
+ const QStringList& fetchRow();
+
-+ /// Does the result point to the beginig of data set
++ /**
++ * \brief Does the result point to the beginig of data set
++ */
+ bool begin() const;
+
-+ /// Does the result point to the end of the data set
++ /**
++ * \brief Does the result point to the end of the data set
++ */
+ bool end() const;
+
-+ /// Reset result and make it points to the begining again
++ /**
++ * \brief Reset result and make it points to the begining again
++ */
+ void reset();
+
+private:
@@ -8274,37 +5015,13 @@ index 0000000..a6ce68e
+#endif // SPARQLRESULT_H
diff --git a/src/libraries/sparql/sparqluri.cpp b/src/libraries/sparql/sparqluri.cpp
new file mode 100644
-index 0000000..2caa6d4
+index 0000000..6963010
--- /dev/null
+++ b/src/libraries/sparql/sparqluri.cpp
-@@ -0,0 +1,154 @@
-+/**
-+ * \brief SparqlUri provides automatic URI generation.
-+ *
-+ * URI is unique identifier in the SPARQL language, it is required
-+ * to be able to generate unique identifiers fast and easy. SparqlUri class
-+ * provides convenient way to generate such URI.
-+ *
-+ * Every URI has base part and autogenerated part. Base part can be defined by user.
-+ * Autogenerated part will be changed with every increment operation.
-+ *
-+ * Autogenerate URI will look like http://base.part/is/fixed#nnnnnn, where nnnnnn is 64bit
-+ * integer, No any prediction is made about order or number of digits in the nnnnnn.
-+ *
-+ * \see SparqlQuery
-+ */
-+
+@@ -0,0 +1,88 @@
+#include "sparqluri.h"
-+
+#include <QUuid>
+
-+/**
-+ * \brief Constructor of the URI
-+ *
-+ * Unique id will be autogenerated.
-+ *
-+ * \param base Fixed part of the URI.
-+ */
+SparqlUri::SparqlUri(const QString& base) :
+ _id(generate())
+{
@@ -8312,14 +5029,6 @@ index 0000000..2caa6d4
+ Q_ASSERT(ret);
+}
+
-+/**
-+ * \brief Constructor of the URI generator
-+ *
-+ * Value of id is passed as a parameter
-+ *
-+ * \param base Fixed part of the URI.
-+ * \param id Pre-defined id is used in this case.
-+ */
+SparqlUri::SparqlUri(const QString& base, quint64 id) :
+ _id(id)
+{
@@ -8327,54 +5036,32 @@ index 0000000..2caa6d4
+ Q_ASSERT(ret);
+}
+
-+/**
-+ * \brief Set new fixed base of the URI
-+ */
+bool SparqlUri::setBase(const QString& base)
+{
+ _base = base;
+ return true;
+}
+
-+/**
-+ * \brief Get fixed base part of the URI
-+ */
+QString SparqlUri::base() const
+{
+ return _base;
+}
+
-+/**
-+ * \brief Get current URI as a string
-+ */
+QString SparqlUri::uri() const
+{
-+ return base() + QString::number(_id);
++ return QString("<%1>").arg(base() + QString::number(_id));
+}
+
-+/**
-+ * \brief Set current nnnnnn part as 64-bit integer
-+ */
+void SparqlUri::setId(quint64 id)
+{
+ _id = id;
+}
+
-+/**
-+ * \brief Get current nnnnnn part as 64-bit integer
-+ */
+quint64 SparqlUri::id() const
+{
+ return _id;
+}
+
-+/**
-+ * \brief Generates new nnnnnn.
-+ *
-+ * Current URI is not updated. To update current URI as well operator++ should be used.
-+ *
-+ * \return new nnnnnn part of the URI as 64-bit unsigned integer.
-+ */
+quint64 SparqlUri::generate()
+{
+ /*
@@ -8398,34 +5085,22 @@ index 0000000..2caa6d4
+ return id;
+}
+
-+/**
-+ * \brief Convenience operator returns URI
-+ */
+SparqlUri::operator QString () const
+{
+ return uri();
+}
+
-+/**
-+ * \brief Convenience operator returns nnnnnn part of the URI
-+ */
+SparqlUri::operator quint64 () const
+{
+ return id();
+}
+
-+/**
-+ * \brief Generates new URI and returns new value
-+ */
+QString SparqlUri::operator++ ()
+{
+ _id = generate();
+ return uri();
+}
+
-+/**
-+ * \brief Generates new URI and returns old value
-+ */
+QString SparqlUri::operator++ (int)
+{
+ QString result(uri());
@@ -8434,35 +5109,104 @@ index 0000000..2caa6d4
+}
diff --git a/src/libraries/sparql/sparqluri.h b/src/libraries/sparql/sparqluri.h
new file mode 100644
-index 0000000..21e0556
+index 0000000..44aeab1
--- /dev/null
+++ b/src/libraries/sparql/sparqluri.h
-@@ -0,0 +1,33 @@
+@@ -0,0 +1,102 @@
+#ifndef SPARQLURI_H
+#define SPARQLURI_H
+
+#include "sparqldatabase.h"
+
++/**
++ * \brief SparqlUri provides automatic URI generation.
++ *
++ * URI is unique identifier in the SPARQL language, it is required
++ * to be able to generate unique identifiers fast and easy. SparqlUri class
++ * provides convenient way to generate such URI.
++ *
++ * Every URI has base part and autogenerated part. Base part can be defined by user.
++ * Autogenerated part will be changed with every increment operation.
++ *
++ * Autogenerate URI will look like http://base.part/is/fixed#nnnnnn, where nnnnnn is 64bit
++ * integer, No any prediction is made about order or number of digits in the nnnnnn.
++ *
++ * \see SparqlQuery
++ */
+class SparqlUri
+{
+public:
++ /**
++ * \brief Constructor of the URI
++ *
++ * Unique id will be autogenerated.
++ *
++ * \param base Fixed part of the URI.
++ */
+ SparqlUri(const QString& base);
++
++ /**
++ * \brief Constructor of the URI generator
++ *
++ * Value of id is passed as a parameter
++ *
++ * \param base Fixed part of the URI.
++ * \param id Pre-defined id is used in this case.
++ */
+ SparqlUri(const QString& base, quint64 id);
+
++ /**
++ * \brief Set new fixed base of the URI
++ */
+ bool setBase(const QString& base);
++
++ /**
++ * \brief Get fixed base part of the URI
++ */
+ QString base() const;
+
++ /**
++ * \brief Get current URI as a string
++ */
+ void setId(quint64 id);
++
++ /**
++ * \brief Set current nnnnnn part as 64-bit integer
++ */
+ quint64 id() const;
+
++ /**
++ * \brief Get current nnnnnn part as 64-bit integer
++ */
+ QString uri() const;
+
++ /**
++ * \brief Generates new nnnnnn.
++ *
++ * Current URI is not updated. To update current URI as well operator++ should be used.
++ *
++ * \return new nnnnnn part of the URI as 64-bit unsigned integer.
++ */
+ quint64 generate();
+
++ /**
++ * \brief Convenience operator returns URI
++ */
+ operator QString () const;
++
++ /**
++ * \brief Convenience operator returns nnnnnn part of the URI
++ */
+ operator quint64 () const;
+
++ /**
++ * \brief Generates new URI and returns new value
++ */
+ QString operator++ ();
++
++ /**
++ * \brief Generates new URI and returns old value
++ */
+ QString operator++ (int);
+
+private:
@@ -8713,7 +5457,7 @@ index 0000000..9d8f79d
+</node>
diff --git a/tools/sparql-import/main.cpp b/tools/sparql-import/main.cpp
new file mode 100644
-index 0000000..86153dd
+index 0000000..c8a8b28
--- /dev/null
+++ b/tools/sparql-import/main.cpp
@@ -0,0 +1,141 @@
@@ -8737,12 +5481,10 @@ index 0000000..86153dd
+
+ QMailStore* sqlStore = QMailStore::instance();
+
-+/*
+ qDebug() << sqlStore->countAccounts();
+ qDebug() << sqlStore->countFolders();
+ qDebug() << sqlStore->countMessages();
+
-+
+ qDebug() << "Number of accounts:" << sparqlStore.countAccounts();
+
+ QMailAccountIdList accountIdList = sparqlStore.queryAccounts();
@@ -8777,14 +5519,30 @@ index 0000000..86153dd
+ }
+ }
+
-+ */
++ QMailFolderKey folderKey = QMailFolderKey::parentAccountId(QMailAccountId());
++ QMailFolderIdList folderIdList = sparqlStore.queryFolders(folderKey);
++
++ foreach (QMailFolderId folderId, folderIdList)
++ {
++ QMailFolder folder = sparqlStore.folder(folderId);
++
++ QMailMessageKey messageKey = QMailMessageKey::parentFolderId(folderId);
++
++ qDebug() << "Number of Messages (" << folder.displayName() << ")" << sparqlStore.countMessages(messageKey);
++
++ QMailMessageIdList messageIdList = sparqlStore.queryMessages(messageKey);
+
-+ // Add standard folders
-+ sparqlStore.setupStandardFolder(QMailFolder::InboxFolder, "Inbox");
-+ sparqlStore.setupStandardFolder(QMailFolder::OutboxFolder, "Outbox");
-+ sparqlStore.setupStandardFolder(QMailFolder::DraftsFolder, "Drafts");
-+ sparqlStore.setupStandardFolder(QMailFolder::SentFolder, "Sent");
-+ sparqlStore.setupStandardFolder(QMailFolder::TrashFolder, "Trash");
++ foreach (QMailMessageId messageId, messageIdList)
++ {
++ QMailMessage message = sparqlStore.message(messageId);
++
++ qDebug() << message.subject();
++ }
++
++ }
++
++
++ /*
+
+ QMailAccountIdList accountIdList = sqlStore->queryAccounts();
+
@@ -8802,12 +5560,7 @@ index 0000000..86153dd
+ {
+ QMailFolder folder(folderId);
+
-+ if (!(QMailFolder::InboxFolder <= folder.id().toULongLong()) ||
-+ !(folder.id().toULongLong() <= QMailFolder::TrashFolder))
-+ {
-+ sparqlStore.addFolder(&folder);
-+ }
-+ folder.setParentAccountId(account.id());
++ sparqlStore.addFolder(&folder);
+
+ QMailMessageKey messageKey = QMailMessageKey::parentFolderId(folderId);
+
@@ -8817,9 +5570,6 @@ index 0000000..86153dd
+ {
+ QMailMessage message(messageId);
+
-+ message.setParentAccountId(account.id());
-+ message.setParentFolderId(folder.id());
-+
+ sparqlStore.addMessage(&message);
+ }
+ }
@@ -8833,11 +5583,7 @@ index 0000000..86153dd
+ {
+ QMailFolder folder(folderId);
+
-+ if (!(QMailFolder::InboxFolder <= folder.id().toULongLong()) ||
-+ !(folder.id().toULongLong() <= QMailFolder::TrashFolder))
-+ {
-+ sparqlStore.addFolder(&folder);
-+ }
++ sparqlStore.addFolder(&folder);
+
+ QMailMessageKey messageKey = QMailMessageKey::parentFolderId(folderId);
+
@@ -8847,13 +5593,11 @@ index 0000000..86153dd
+ {
+ QMailMessage message(messageId);
+
-+ message.setParentFolderId(folder.id());
-+
+ sparqlStore.addMessage(&message);
+ }
+ }
+
-+ //*/
++ */
+ return 0;
+}
+
@@ -8889,10 +5633,10 @@ index 0000000..3429430
+INSTALLS += target
diff --git a/tools/sparql-import/sparqlmailstore.cpp b/tools/sparql-import/sparqlmailstore.cpp
new file mode 100644
-index 0000000..d1ad530
+index 0000000..b524f72
--- /dev/null
+++ b/tools/sparql-import/sparqlmailstore.cpp
-@@ -0,0 +1,1371 @@
+@@ -0,0 +1,1404 @@
+#include "sparqlmailstore.h"
+
+#include "sparqluri.h"
@@ -8939,10 +5683,25 @@ index 0000000..d1ad530
+ return qMakePair(unescape(uri.mid(0, index), ':'), unescape(uri.mid(index + 1), ':'));
+}
+
-+namespace {
-+
+using namespace QMailKey;
+
++const char *WellKnownUris[] = {
++ "qmf://groove.harmattan.com/email#",
++ "qmf://groove.nokia.com/folder#",
++ "qmf://groove.nokia.com/accounts#" };
++
++template <int INDEX>
++class WellKnownUri : public SparqlUri
++{
++public:
++ WellKnownUri() : SparqlUri(WellKnownUris[INDEX]) {}
++ WellKnownUri(quint64 id) : SparqlUri(WellKnownUris[INDEX], id) {}
++};
++
++typedef WellKnownUri<1> MailMessageUri;
++typedef WellKnownUri<2> MailFolderUri;
++typedef WellKnownUri<3> MailAccountUri;
++
+QString combineOperatorString(QMailKey::Combiner op)
+{
+ switch (op)
@@ -8969,7 +5728,7 @@ index 0000000..d1ad530
+{
+ QStringList pattern;
+ for (int i = 0; i<argNumber; i++)
-+ pattern << "(%1 " + op + " \"%" + QString::number(i+2) + "\")";
++ pattern << "(%1 " + op + " %" + QString::number(i+2) + ")";
+
+ if (argNumber > 1)
+ return "(" + pattern.join(comp) + ")";
@@ -9588,11 +6347,11 @@ index 0000000..d1ad530
+QString argumentValue(const QVariant& value)
+{
+ if (qVariantCanConvert<QMailAccountId>(value))
-+ return QString::number(qVariantValue<QMailAccountId>(value).toULongLong());
++ return MailAccountUri(qVariantValue<QMailAccountId>(value).toULongLong());
+ else if (qVariantCanConvert<QMailFolderId>(value))
-+ return QString::number(qVariantValue<QMailFolderId>(value).toULongLong());
++ return MailFolderUri(qVariantValue<QMailFolderId>(value).toULongLong());
+ else if (qVariantCanConvert<QMailMessageId>(value))
-+ return QString::number(qVariantValue<QMailMessageId>(value).toULongLong());
++ return MailMessageUri(qVariantValue<QMailMessageId>(value).toULongLong());
+ else if (qVariantCanConvert<QString>(value))
+ return qVariantValue<QString>(value);
+ else if (qVariantCanConvert<int>(value))
@@ -9658,11 +6417,19 @@ index 0000000..d1ad530
+ QString query("SELECT ?mail \n"
+ "WHERE { \n"
+ "?mail rdf:type nmo:Email . \n"
-+ "%1 \n"
-+ "FILTER %2 \n"
++ "%1"
++ "%2"
+ "} %3\n");
+
-+ return query.arg(keyStatment("?mail", key, sort), keyFilter(key), sortKey(sort));
++ QString statement = keyStatment("?mail", key, sort);
++ if (!statement.isEmpty())
++ statement = QString("%1 \n").arg(statement);
++
++ QString filter;
++ if (!key.isEmpty())
++ filter = QString("FILTER %1 \n").arg(keyFilter(key));
++
++ return query.arg(statement).arg(filter).arg(sortKey(sort));
+}
+
+QString keyQuery(const QMailFolderKey& key, const QMailFolderSortKey& sort = QMailFolderSortKey())
@@ -9670,11 +6437,19 @@ index 0000000..d1ad530
+ QString query("SELECT ?folder \n"
+ "WHERE { \n"
+ "?folder rdf:type nmo:MailFolder . \n"
-+ "%1 \n"
-+ "FILTER %2 \n"
++ "%1"
++ "%2"
+ "} %3\n");
+
-+ return query.arg(keyStatment("?folder", key, sort), keyFilter(key), sortKey(sort));
++ QString statement = keyStatment("?folder", key, sort);
++ if (!statement.isEmpty())
++ statement = QString("%1 \n").arg(statement);
++
++ QString filter;
++ if (!key.isEmpty())
++ filter = QString("FILTER %1 \n").arg(keyFilter(key));
++
++ return query.arg(statement).arg(filter).arg(sortKey(sort));
+}
+
+QString keyQuery(const QMailAccountKey& key, const QMailAccountSortKey& sort = QMailAccountSortKey())
@@ -9682,11 +6457,19 @@ index 0000000..d1ad530
+ QString query("SELECT ?account \n"
+ "WHERE { \n"
+ "?account rdf:type nmo:Mailbox . \n"
-+ "%1 \n"
-+ "FILTER %2 \n"
++ "%1"
++ "%2"
+ "} %3\n");
+
-+ return query.arg(keyStatment("?account", key, sort), keyFilter(key), sortKey(sort));
++ QString statement = keyStatment("?account", key, sort);
++ if (!statement.isEmpty())
++ statement = QString("%1 \n").arg(statement);
++
++ QString filter;
++ if (!key.isEmpty())
++ filter = QString("FILTER %1 \n").arg(keyFilter(key));
++
++ return query.arg(statement).arg(filter).arg(sortKey(sort));
+}
+
+QString keyCount(const QMailMessageKey& key)
@@ -9694,11 +6477,19 @@ index 0000000..d1ad530
+ QString query("SELECT COUNT(?mail) AS count \n"
+ "WHERE { \n"
+ "?mail rdf:type nmo:Email . \n"
-+ "%1 \n"
-+ "FILTER %2 \n"
++ "%1"
++ "%2"
+ "}\n");
+
-+ return query.arg(keyStatment("?mail", key, QMailMessageSortKey()), keyFilter(key));
++ QString statement = keyStatment("?mail", key, QMailAccountSortKey());
++ if (!statement.isEmpty())
++ statement = QString("%1 \n").arg(statement);
++
++ QString filter;
++ if (!key.isEmpty())
++ filter = QString("FILTER %1 \n").arg(keyFilter(key));
++
++ return query.arg(statement).arg(filter);
+}
+
+QString keyCount(const QMailFolderKey& key)
@@ -9706,11 +6497,19 @@ index 0000000..d1ad530
+ QString query("SELECT COUNT(?folder) AS count \n"
+ "WHERE { \n"
+ "?folder rdf:type nmo:MailFolder . \n"
-+ "%1 \n"
-+ "FILTER %2 \n"
++ "%1"
++ "%2"
+ "}\n");
+
-+ return query.arg(keyStatment("?folder", key, QMailFolderSortKey()), keyFilter(key));
++ QString statement = keyStatment("?folder", key, QMailAccountSortKey());
++ if (!statement.isEmpty())
++ statement = QString("%1 \n").arg(statement);
++
++ QString filter;
++ if (!key.isEmpty())
++ filter = QString("FILTER %1 \n").arg(keyFilter(key));
++
++ return query.arg(statement).arg(filter);
+}
+
+QString keyCount(const QMailAccountKey& key)
@@ -9718,11 +6517,19 @@ index 0000000..d1ad530
+ QString query("SELECT COUNT(?account) AS count \n"
+ "WHERE { \n"
+ "?account rdf:type nmo:Mailbox . \n"
-+ "%1 \n"
-+ "FILTER %2 \n"
++ "%1"
++ "%2"
+ "}\n");
+
-+ return query.arg(keyStatment("?account", key, QMailAccountSortKey()), keyFilter(key));
++ QString statement = keyStatment("?account", key, QMailAccountSortKey());
++ if (!statement.isEmpty())
++ statement = QString("%1 \n").arg(statement);
++
++ QString filter;
++ if (!key.isEmpty())
++ filter = QString("FILTER %1 \n").arg(keyFilter(key));
++
++ return query.arg(statement).arg(filter);
+}
+
+template <class Key>
@@ -9747,9 +6554,6 @@ index 0000000..d1ad530
+ debugKey(subkey);
+}
+
-+} // End namespace
-+
-+
+QString nmoRecipients(const QList<QMailAddress>& recipients)
+{
+ QString result;
@@ -9787,43 +6591,44 @@ index 0000000..d1ad530
+
+void SparqlMailStore::addMessage(QMailMessageMetaData* metaData)
+{
-+ SparqlUri uri("qmf://groove.harmattan.com/email#");
++ MailMessageUri messageUri(metaData->id().toULongLong());
++ MailFolderUri parentFolderUri(metaData->parentFolderId().toULongLong());
++ MailAccountUri parentAccountUri(metaData->parentAccountId().toULongLong());
++
+ SparqlQuery query(SparqlQuery::UpdateQuery);
+ query.prepare(QString(
+ "INSERT {\n"
-+ " <%1> rdf:type nmo:Email ;\n"
-+ " nie:isLogicalPartOf <qmf://groove.nokia.com/folder#%2> ;\n"
-+ " nmo:sender [\n"
-+ " rdf:type nco:Contact ;\n"
-+ " nco:fullname \"%3\" ; \n"
-+ " nco:hasEmailAddress <mailto:%4> ] ;\n"
-+
++ "%1 rdf:type nmo:Email ;\n"
++ " nie:isLogicalPartOf %2 ;\n"
++ " nmo:sender [\n"
++ " rdf:type nco:Contact ;\n"
++ " nco:fullname \"%3\" ; \n"
++ " nco:hasEmailAddress <mailto:%4> ] ;\n"
+ + nmoRecipients(metaData->to()) +
-+
-+ " nmo:messageSubject \"%5\" ;\n"
-+ " nmo:sentDate \"%6\"^^xsd:dateTime ;\n"
-+ " nmo:status \"%7\"^^xsd:integer ;\n"
-+ " nie:relatedTo <qmf://groove.nokia.com/accounts#%8> ;\n"
-+ " nie:isStoredAs [\n"
-+ " rdf:type nie:DataObject ;\n"
-+ " nie:dataSource <%9> ] ;\n"
-+ " nmo:messageId <%10> ;\n"
-+ " nie:contentSize \"%11\"^^xsd:integer ;\n"
-+ " nie:mimeType \"%12\" ;\n"
-+ " nmo:inReplyTo <%13> ;\n"
-+ " nmo:messageHeader [\n"
-+ " rdf:type nmo:MessageHeader ;\n"
-+ " nmo:headerName \"responseType\" ;\n"
-+ " nmo:headerValue \"%14\" ] ;\n"
-+ " nmo:receivedDate \"%15\"^^xsd:dateTime .\n"
-+ "}").arg(uri.uri())
-+ .arg(metaData->parentFolderId().toULongLong())
++ " nmo:messageSubject \"%5\" ;\n"
++ " nmo:sentDate \"%6\"^^xsd:dateTime ;\n"
++ " nmo:status \"%7\"^^xsd:integer ;\n"
++ " nie:relatedTo %8 ;\n"
++ " nie:isStoredAs [\n"
++ " rdf:type nie:DataObject ;\n"
++ " nie:dataSource <%9> ] ;\n"
++ " nmo:messageId \"%10\" ;\n"
++ " nie:contentSize \"%11\"^^xsd:integer ;\n"
++ " nie:mimeType \"%12\" ;\n"
++ " nmo:inReplyTo \"%13\" ;\n"
++ " nmo:messageHeader [\n"
++ " rdf:type nmo:MessageHeader ;\n"
++ " nmo:headerName \"responseType\" ;\n"
++ " nmo:headerValue \"%14\" ] ;\n"
++ " nmo:receivedDate \"%15\"^^xsd:dateTime .\n"
++ "}").arg(messageUri.uri())
++ .arg(parentFolderUri.uri())
+ .arg(metaData->from().name())
+ .arg(metaData->from().address())
+ .arg(metaData->subject())
+ .arg(QMailTimeStamp(metaData->date()).toLocalTime().toString())
+ .arg(static_cast<int>(metaData->status()))
-+ .arg(metaData->parentAccountId().toULongLong())
++ .arg(parentAccountUri.uri())
+ .arg(::contentUri(*metaData))
+ .arg(metaData->serverUid())
+ .arg(metaData->size())
@@ -9841,27 +6646,30 @@ index 0000000..d1ad530
+ }
+
+ qDebug() << "Query succeeded";
-+ metaData->setId(QMailMessageId(uri.id()));
++ metaData->setId(QMailMessageId(messageUri.id()));
+}
+
+void SparqlMailStore::addFolder(QMailFolder* folder)
+{
-+ SparqlUri uri("qmf://groove.nokia.com/folder#");
++ MailFolderUri folderUri(folder->id().toULongLong());
++ MailFolderUri parentFolderUri(folder->parentFolderId().toULongLong());
++ MailAccountUri parentAccountUri(folder->parentAccountId().toULongLong());
++
+ SparqlQuery query(SparqlQuery::UpdateQuery);
+ query.prepare(QString(
+ "INSERT { \n"
-+ "<%1> rdf:type nmo:MailFolder ; \n"
++ "%1 rdf:type nmo:MailFolder ; \n"
+ " nmo:folderName \"%2\" ; \n"
-+ " nie:isLogicalPartOf <qmf://groove.nokia.com/folder#%3> ; \n"
-+ " nie:relatedTo <qmf://groove.nokia.com/accounts#%4> ; \n"
++ " nie:isLogicalPartOf %3 ; \n"
++ " nie:relatedTo %4 ; \n"
+ " nmo:folderDisplayName \"%5\" ; \n"
+ " nmo:status \"%6\"^^xsd:integer ; \n"
+ " nmo:serverCount \"%7\"^^xsd:integer ; \n"
+ " nmo:serverUnreadCount \"%8\"^^xsd:integet . \n"
-+ "}").arg(uri.uri())
++ "}").arg(folderUri.uri())
+ .arg(folder->path())
-+ .arg(folder->parentFolderId().toULongLong())
-+ .arg(folder->parentAccountId().toULongLong())
++ .arg(parentFolderUri.uri())
++ .arg(parentAccountUri.uri())
+ .arg(folder->displayName())
+ .arg(folder->status())
+ .arg(folder->serverCount())
@@ -9876,25 +6684,25 @@ index 0000000..d1ad530
+ }
+
+ qDebug() << "Query succeeded";
-+ folder->setId(QMailFolderId(uri.id()));
++ folder->setId(QMailFolderId(folderUri.id()));
+
+ // TBD: Update folder links also
+}
+
+void SparqlMailStore::addAccount(QMailAccount* account)
+{
-+ SparqlUri uri("qmf://groove.nokia.com/accounts#");
++ MailAccountUri accountUri(account->id().toULongLong());
+ SparqlQuery query(SparqlQuery::UpdateQuery);
+ query.prepare(QString(
+ "INSERT { \n"
-+ "<%1> rdf:type nmo:Mailbox ; \n"
++ "%1 rdf:type nmo:Mailbox ; \n"
+ " nmo:accountName \"%2\" ; \n"
+ " nmo:status \"%3\"^^xsd:integer ; \n"
+ " nmo:signature \"%4\" ; \n"
+ " nmo:fromAddress [ \n"
+ " rdf:type nco:EmailAddress ; \n"
+ " nco:emailAddress \"%5\" ] . \n"
-+ "}").arg(uri.uri())
++ "}").arg(accountUri.uri())
+ .arg(account->name())
+ .arg(account->status())
+ .arg(account->signature())
@@ -9909,25 +6717,26 @@ index 0000000..d1ad530
+ }
+
+ qDebug() << "Query succeeded";
-+ account->setId(QMailAccountId(uri.id()));
++ account->setId(QMailAccountId(accountUri.id()));
+}
+
+QMailAccount SparqlMailStore::account(const QMailAccountId& id) const
+{
+ QMailAccount account;
+
++ MailMessageUri messageUri(id.toULongLong());
+ SparqlQuery query(SparqlQuery::SearchQuery);
+ query.prepare(QString(
+ "SELECT ?name ?signature ?fromAddress \n"
+ "WHERE { \n"
-+ "<qmf://groove.nokia.com/accounts#%1> rdf:type nmo:Mailbox ; \n"
++ "%1 rdf:type nmo:Mailbox ; \n"
+ " nmo:accountName ?name ; \n"
+// " nmo:status ?status ; \n"
+ " nmo:signature ?signature ; \n"
+ " nmo:fromAddress [ \n"
+ " rdf:type nco:EmailAddress ; \n"
+ " nco:emailAddress ?fromAddress ] . \n"
-+ "}").arg(id.toULongLong()));
++ "}").arg(messageUri.uri()));
+
+ if (!query.exec())
+ {
@@ -9952,11 +6761,12 @@ index 0000000..d1ad530
+
+QMailFolder SparqlMailStore::folder(const QMailFolderId& id) const
+{
++ MailFolderUri folderUri(id.toULongLong());
+ SparqlQuery query(SparqlQuery::SearchQuery);
+ query.prepare(QString(
+ "SELECT ?name ?parentFolder ?parentAccount ?displayName \n"
+ "WHERE { \n"
-+ "<qmf://groove.nokia.com/folder#%1> rdf:type nmo:MailFolder ; \n"
++ "%1 rdf:type nmo:MailFolder ; \n"
+ " nmo:folderName ?name ; \n"
+ " nie:isLogicalPartOf ?parentFolder ; \n"
+ " nie:relatedTo ?parentAccount ; \n"
@@ -9964,7 +6774,7 @@ index 0000000..d1ad530
+// " nmo:status ?status ; \n"
+// " nmo:serverCount ?serverCount ; \n"
+// " nmo:serverUnreadCount ?serverUnreadCount . \n"
-+ "}").arg(id.toULongLong()));
++ "}").arg(folderUri.uri()));
+
+ if (!query.exec())
+ {
@@ -9990,16 +6800,17 @@ index 0000000..d1ad530
+
+QMailMessage SparqlMailStore::message(const QMailMessageId& id) const
+{
++ MailMessageUri messageUri(id.toULongLong());
+ SparqlQuery query(SparqlQuery::SearchQuery);
+ query.prepare(QString(
+ "SELECT ?fullName ?mailAddress \n"
+ "WHERE { \n"
-+ "<qmf://groove.harmattan.com/email#%1> rdf:type nmo:Email ;\n"
-+ "nmo:recipient [\n"
-+ " rdf:type nco:Contact ;\n"
-+ " nco:fullname ?fullName ; \n"
-+ " nco:hasEmailAddress ?mailAddress ] \n"
-+ "}").arg(id.toULongLong()));
++ "%1 rdf:type nmo:Email ; \n"
++ " nmo:recipient [ \n"
++ " rdf:type nco:Contact ; \n"
++ " nco:fullname ?fullName ; \n"
++ " nco:hasEmailAddress ?mailAddress ] \n"
++ "}").arg(messageUri.uri()));
+
+ if (!query.exec())
+ {
@@ -10019,29 +6830,29 @@ index 0000000..d1ad530
+ query.prepare(QString(
+ "SELECT ?folderId ?senderFullName ?senderEmailAddress ?messageSubject ?sentDate ?status ?accountId ?dataSource ?uid ?contentSize ?mimeType ?inReplyTo ?headerValue ?receivedDate \n"
+ "WHERE { \n"
-+ " <qmf://groove.harmattan.com/email#%1> rdf:type nmo:Email ;\n"
-+ " nie:isLogicalPartOf ?folderId ;\n"
-+ " nmo:sender [\n"
-+ " rdf:type nco:Contact ;\n"
-+ " nco:fullname ?senderFullName ; \n"
-+ " nco:hasEmailAddress ?senderEmailAddress ] ;\n"
-+ " nmo:messageSubject ?messageSubject ;\n"
-+ " nmo:sentDate ?sentDate ;\n"
-+ " nmo:status ?status ;\n"
-+ " nie:relatedTo ?accountId ;\n"
-+ " nie:isStoredAs [\n"
-+ " rdf:type nie:DataObject ;\n"
-+ " nie:dataSource ?dataSource ] ;\n"
-+ " nmo:messageId ?uid ;\n"
-+ " nie:contentSize ?contentSize ;\n"
-+ " nie:mimeType ?mimeType ;\n"
-+ " nmo:inReplyTo ?inReplyTo ;\n"
-+ " nmo:messageHeader [\n"
-+ " rdf:type nmo:MessageHeader ;\n"
-+ " nmo:headerName \"responseType\" ;\n"
-+ " nmo:headerValue ?headerValue ] ;\n"
-+ " nmo:receivedDate ?receivedDate .\n"
-+ "}").arg(id.toULongLong()));
++ "%1 rdf:type nmo:Email ;\n"
++ " nie:isLogicalPartOf ?folderId ;\n"
++ " nmo:sender [\n"
++ " rdf:type nco:Contact ;\n"
++ " nco:fullname ?senderFullName ; \n"
++ " nco:hasEmailAddress ?senderEmailAddress ] ;\n"
++ " nmo:messageSubject ?messageSubject ;\n"
++ " nmo:sentDate ?sentDate ;\n"
++ " nmo:status ?status ;\n"
++ " nie:relatedTo ?accountId ;\n"
++ " nie:isStoredAs [\n"
++ " rdf:type nie:DataObject ;\n"
++ " nie:dataSource ?dataSource ] ;\n"
++ " nmo:messageId ?uid ;\n"
++ " nie:contentSize ?contentSize ;\n"
++ " nie:mimeType ?mimeType ;\n"
++ " nmo:inReplyTo ?inReplyTo ;\n"
++ " nmo:messageHeader [\n"
++ " rdf:type nmo:MessageHeader ;\n"
++ " nmo:headerName \"responseType\" ;\n"
++ " nmo:headerValue ?headerValue ] ;\n"
++ " nmo:receivedDate ?receivedDate .\n"
++ "}").arg(messageUri.uri()));
+
+ if (!query.exec())
+ {
@@ -10129,7 +6940,6 @@ index 0000000..d1ad530
+ return result.fetchRow().first().toInt();
+}
+
-+
+QMailAccountIdList SparqlMailStore::queryAccounts(const QMailAccountKey &key, const QMailAccountSortKey &sortKey) const
+{
+ QMailAccountIdList accountIdList;
@@ -10231,45 +7041,12 @@ index 0000000..d1ad530
+{
+ Q_UNUSED(account);
+}
-+
-+void SparqlMailStore::setupStandardFolder(QMailFolder::StandardFolder folder, const QString& name)
-+{
-+ SparqlQuery query(SparqlQuery::UpdateQuery);
-+ query.prepare(QString(
-+ "INSERT { \n"
-+ "<%1> rdf:type nmo:MailFolder ; \n"
-+ " nmo:folderName \"%2\" ; \n"
-+ " nie:isLogicalPartOf <qmf://groove.nokia.com/folder#%3> ; \n"
-+ " nie:relatedTo <qmf://groove.nokia.com/accounts#%4> ; \n"
-+ " nmo:folderDisplayName \"%5\" ; \n"
-+ " nmo:status \"%6\"^^xsd:integer ; \n"
-+ " nmo:serverCount \"%7\"^^xsd:integer ; \n"
-+ " nmo:serverUnreadCount \"%8\"^^xsd:integet . \n"
-+ "}").arg("qmf://groove.nokia.com/folder#" + QString::number(folder))
-+ .arg(name)
-+ .arg(0)
-+ .arg(0)
-+ .arg(name)
-+ .arg(0)
-+ .arg(0)
-+ .arg(0));
-+
-+ // TBD: Add custom fields later
-+
-+ if (!query.exec())
-+ {
-+ qDebug() << "Query failed:" << query.error();
-+ return;
-+ }
-+
-+ qDebug() << "Query succeeded";
-+}
diff --git a/tools/sparql-import/sparqlmailstore.h b/tools/sparql-import/sparqlmailstore.h
new file mode 100644
-index 0000000..60f8b20
+index 0000000..9bcd838
--- /dev/null
+++ b/tools/sparql-import/sparqlmailstore.h
-@@ -0,0 +1,45 @@
+@@ -0,0 +1,42 @@
+#ifndef MAILSTORE_H
+#define MAILSTORE_H
+
@@ -10309,9 +7086,6 @@ index 0000000..60f8b20
+ void removeMessage(const QMailMessageMetaData& metaData);
+ void removeFolder(const QMailFolder& folder);
+ void removeAccount(const QMailAccount& account);
-+
-+ void setupStandardFolder(QMailFolder::StandardFolder folder, const QString& name);
-+
+};
+
+#endif // MAILSTORE_H