This commit is contained in:
Martin Rotter 2022-09-16 09:15:48 +02:00
parent aef6b14bf2
commit a10cc039f1
2 changed files with 271 additions and 261 deletions

View File

@ -225,40 +225,24 @@ void MessagesModel::setupHeaderData() {
m_headerData << m_headerData <<
/*: Tooltip for ID of message.*/ tr("Id") << /*: Tooltip for ID of message.*/ tr("Id") <<
/*: Tooltip for "read" column in msg list.*/ tr("Read") << /*: Tooltip for "read" column in msg list.*/ tr("Read") <<
/*: Tooltip for "important" column in msg list.*/ tr("Important") << /*: Tooltip for "important" column in msg list.*/ tr("Important") <<
/*: Tooltip for "deleted" column in msg list.*/ tr("Deleted") << /*: Tooltip for "deleted" column in msg list.*/ tr("Deleted") <<
/*: Tooltip for "pdeleted" column in msg list.*/ tr("Permanently deleted") << /*: Tooltip for "pdeleted" column in msg list.*/ tr("Permanently deleted") <<
/*: Tooltip for custom ID of feed of message.*/ tr("Feed ID") << /*: Tooltip for custom ID of feed of message.*/ tr("Feed ID") <<
/*: Tooltip for title of message.*/ tr("Title") << /*: Tooltip for title of message.*/ tr("Title") <<
/*: Tooltip for url of message.*/ tr("Url") << /*: Tooltip for url of message.*/ tr("Url") <<
/*: Tooltip for author of message.*/ tr("Author") << /*: Tooltip for author of message.*/ tr("Author") <<
/*: Tooltip for creation date of message.*/ tr("Date") << /*: Tooltip for creation date of message.*/ tr("Date") <<
/*: Tooltip for contents of message.*/ tr("Contents") << /*: Tooltip for contents of message.*/ tr("Contents") <<
/*: Tooltip for attachments of message.*/ tr("Attachments") << /*: Tooltip for attachments of message.*/ tr("Attachments") <<
/*: Tooltip for score of message.*/ tr("Score") << /*: Tooltip for score of message.*/ tr("Score") <<
/*: Tooltip for account ID of message.*/ tr("Account ID") << /*: Tooltip for account ID of message.*/ tr("Account ID") <<
/*: Tooltip for custom ID of message.*/ tr("Custom ID") << /*: Tooltip for custom ID of message.*/ tr("Custom ID") <<
/*: Tooltip for custom hash string of message.*/ tr("Custom hash") << /*: Tooltip for custom hash string of message.*/ tr("Custom hash") <<
/*: Tooltip for name of feed for message.*/ tr("Feed") << /*: Tooltip for name of feed for message.*/ tr("Feed") <<
/*: Tooltip for indication of presence of enclosures.*/ tr("Has enclosures") <<
/*: Tooltip for indication of presence of enclosures.*/ tr("Has enclosures"); /*: Tooltip for indication of labels of message.*/ tr("Assigned labels");
m_tooltipData << tr("ID of the article.") << tr("Is article read?") << tr("Is article important?") m_tooltipData << tr("ID of the article.") << tr("Is article read?") << tr("Is article important?")
<< tr("Is article deleted?") << tr("Is article permanently deleted from recycle bin?") << tr("Is article deleted?") << tr("Is article permanently deleted from recycle bin?")
@ -267,7 +251,7 @@ void MessagesModel::setupHeaderData() {
<< tr("Contents of the article.") << tr("List of attachments.") << tr("Score of the article.") << tr("Contents of the article.") << tr("List of attachments.") << tr("Score of the article.")
<< tr("Account ID of the article.") << tr("Custom ID of the article.") << tr("Account ID of the article.") << tr("Custom ID of the article.")
<< tr("Custom hash of the article.") << tr("Name of feed of the article.") << tr("Custom hash of the article.") << tr("Name of feed of the article.")
<< tr("Indication of enclosures presence within the article."); << tr("Indication of enclosures presence within the article.") << tr("Labels assigned to the article.");
} }
Qt::ItemFlags MessagesModel::flags(const QModelIndex& index) const { Qt::ItemFlags MessagesModel::flags(const QModelIndex& index) const {

View File

@ -37,6 +37,9 @@ QMap<int, QString> DatabaseQueries::messageTableAttributes(bool only_msg_table)
"THEN 'true' " "THEN 'true' "
"ELSE 'false' " "ELSE 'false' "
"END AS has_enclosures"); "END AS has_enclosures");
field_names[18] = QSL("(SELECT GROUP_CONCAT(Labels.name) FROM Labels WHERE Labels.id IN (SELECT "
"LabelsInMessages.label FROM LabelsInMessages WHERE LabelsInMessages.account_id = "
"Messages.account_id AND LabelsInMessages.message = Messages.custom_id))");
return field_names; return field_names;
} }
@ -270,7 +273,9 @@ bool DatabaseQueries::markLabelledMessagesReadUnread(const QSqlDatabase& db, Lab
" is_deleted = 0 AND " " is_deleted = 0 AND "
" is_pdeleted = 0 AND " " is_pdeleted = 0 AND "
" account_id = :account_id AND " " account_id = :account_id AND "
" EXISTS (SELECT * FROM LabelsInMessages WHERE LabelsInMessages.label = :label AND Messages.account_id = LabelsInMessages.account_id AND Messages.custom_id = LabelsInMessages.message);")); " EXISTS (SELECT * FROM LabelsInMessages WHERE LabelsInMessages.label = :label AND "
"Messages.account_id = LabelsInMessages.account_id AND Messages.custom_id = "
"LabelsInMessages.message);"));
q.bindValue(QSL(":read"), read == RootItem::ReadStatus::Read ? 1 : 0); q.bindValue(QSL(":read"), read == RootItem::ReadStatus::Read ? 1 : 0);
q.bindValue(QSL(":account_id"), label->getParentServiceRoot()->accountId()); q.bindValue(QSL(":account_id"), label->getParentServiceRoot()->accountId());
q.bindValue(QSL(":label"), label->customId()); q.bindValue(QSL(":label"), label->customId());
@ -278,7 +283,9 @@ bool DatabaseQueries::markLabelledMessagesReadUnread(const QSqlDatabase& db, Lab
return q.exec(); return q.exec();
} }
bool DatabaseQueries::markImportantMessagesReadUnread(const QSqlDatabase& db, int account_id, RootItem::ReadStatus read) { bool DatabaseQueries::markImportantMessagesReadUnread(const QSqlDatabase& db,
int account_id,
RootItem::ReadStatus read) {
QSqlQuery q(db); QSqlQuery q(db);
q.setForwardOnly(true); q.setForwardOnly(true);
@ -300,7 +307,9 @@ bool DatabaseQueries::markUnreadMessagesRead(const QSqlDatabase& db, int account
return q.exec(); return q.exec();
} }
bool DatabaseQueries::markMessagesReadUnread(const QSqlDatabase& db, const QStringList& ids, RootItem::ReadStatus read) { bool DatabaseQueries::markMessagesReadUnread(const QSqlDatabase& db,
const QStringList& ids,
RootItem::ReadStatus read) {
QSqlQuery q(db); QSqlQuery q(db);
q.setForwardOnly(true); q.setForwardOnly(true);
@ -314,8 +323,7 @@ bool DatabaseQueries::markMessageImportant(const QSqlDatabase& db, int id, RootI
q.setForwardOnly(true); q.setForwardOnly(true);
if (!q.prepare(QSL("UPDATE Messages SET is_important = :important WHERE id = :id;"))) { if (!q.prepare(QSL("UPDATE Messages SET is_important = :important WHERE id = :id;"))) {
qWarningNN << LOGSEC_DB qWarningNN << LOGSEC_DB << "Query preparation failed for message importance switch.";
<< "Query preparation failed for message importance switch.";
return false; return false;
} }
@ -326,12 +334,16 @@ bool DatabaseQueries::markMessageImportant(const QSqlDatabase& db, int id, RootI
return q.exec(); return q.exec();
} }
bool DatabaseQueries::markFeedsReadUnread(const QSqlDatabase& db, const QStringList& ids, int account_id, RootItem::ReadStatus read) { bool DatabaseQueries::markFeedsReadUnread(const QSqlDatabase& db,
const QStringList& ids,
int account_id,
RootItem::ReadStatus read) {
QSqlQuery q(db); QSqlQuery q(db);
q.setForwardOnly(true); q.setForwardOnly(true);
q.prepare(QSL("UPDATE Messages SET is_read = :read " q.prepare(QSL("UPDATE Messages SET is_read = :read "
"WHERE feed IN (%1) AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;").arg(ids.join(QSL(", ")))); "WHERE feed IN (%1) AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;")
.arg(ids.join(QSL(", "))));
q.bindValue(QSL(":read"), read == RootItem::ReadStatus::Read ? 1 : 0); q.bindValue(QSL(":read"), read == RootItem::ReadStatus::Read ? 1 : 0);
q.bindValue(QSL(":account_id"), account_id); q.bindValue(QSL(":account_id"), account_id);
return q.exec(); return q.exec();
@ -376,9 +388,8 @@ bool DatabaseQueries::deleteOrRestoreMessagesToFromBin(const QSqlDatabase& db, c
QSqlQuery q(db); QSqlQuery q(db);
q.setForwardOnly(true); q.setForwardOnly(true);
return q.exec(QSL("UPDATE Messages SET is_deleted = %2, is_pdeleted = %3 WHERE id IN (%1);").arg(ids.join(QSL(", ")), return q.exec(QSL("UPDATE Messages SET is_deleted = %2, is_pdeleted = %3 WHERE id IN (%1);")
QString::number(deleted ? 1 : 0), .arg(ids.join(QSL(", ")), QString::number(deleted ? 1 : 0), QString::number(0)));
QString::number(0)));
} }
bool DatabaseQueries::restoreBin(const QSqlDatabase& db, int account_id) { bool DatabaseQueries::restoreBin(const QSqlDatabase& db, int account_id) {
@ -469,12 +480,14 @@ QMap<QString, QPair<int, int>> DatabaseQueries::getMessageCountsForCategory(cons
if (only_total_counts) { if (only_total_counts) {
q.prepare(QSL("SELECT feed, sum((is_read + 1) % 2), count(*) FROM Messages " q.prepare(QSL("SELECT feed, sum((is_read + 1) % 2), count(*) FROM Messages "
"WHERE feed IN (SELECT custom_id FROM Feeds WHERE category = :category AND account_id = :account_id) AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id " "WHERE feed IN (SELECT custom_id FROM Feeds WHERE category = :category AND account_id = :account_id) "
"AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id "
"GROUP BY feed;")); "GROUP BY feed;"));
} }
else { else {
q.prepare(QSL("SELECT feed, sum((is_read + 1) % 2) FROM Messages " q.prepare(QSL("SELECT feed, sum((is_read + 1) % 2) FROM Messages "
"WHERE feed IN (SELECT custom_id FROM Feeds WHERE category = :category AND account_id = :account_id) AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id " "WHERE feed IN (SELECT custom_id FROM Feeds WHERE category = :category AND account_id = :account_id) "
"AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id "
"GROUP BY feed;")); "GROUP BY feed;"));
} }
@ -509,8 +522,10 @@ QMap<QString, QPair<int, int>> DatabaseQueries::getMessageCountsForCategory(cons
return counts; return counts;
} }
QMap<QString, QPair<int, int>> DatabaseQueries::getMessageCountsForAccount(const QSqlDatabase& db, int account_id, QMap<QString, QPair<int, int>> DatabaseQueries::getMessageCountsForAccount(const QSqlDatabase& db,
bool only_total_counts, bool* ok) { int account_id,
bool only_total_counts,
bool* ok) {
QMap<QString, QPair<int, int>> counts; QMap<QString, QPair<int, int>> counts;
QSqlQuery q(db); QSqlQuery q(db);
@ -557,8 +572,11 @@ QMap<QString, QPair<int, int>> DatabaseQueries::getMessageCountsForAccount(const
return counts; return counts;
} }
int DatabaseQueries::getMessageCountsForFeed(const QSqlDatabase& db, const QString& feed_custom_id, int DatabaseQueries::getMessageCountsForFeed(const QSqlDatabase& db,
int account_id, bool only_total_counts, bool* ok) { const QString& feed_custom_id,
int account_id,
bool only_total_counts,
bool* ok) {
QSqlQuery q(db); QSqlQuery q(db);
q.setForwardOnly(true); q.setForwardOnly(true);
@ -569,7 +587,8 @@ int DatabaseQueries::getMessageCountsForFeed(const QSqlDatabase& db, const QStri
} }
else { else {
q.prepare(QSL("SELECT count(*) FROM Messages " q.prepare(QSL("SELECT count(*) FROM Messages "
"WHERE feed = :feed AND is_deleted = 0 AND is_pdeleted = 0 AND is_read = 0 AND account_id = :account_id;")); "WHERE feed = :feed AND is_deleted = 0 AND is_pdeleted = 0 AND is_read = 0 AND account_id = "
":account_id;"));
} }
q.bindValue(QSL(":feed"), feed_custom_id); q.bindValue(QSL(":feed"), feed_custom_id);
@ -591,7 +610,11 @@ int DatabaseQueries::getMessageCountsForFeed(const QSqlDatabase& db, const QStri
} }
} }
int DatabaseQueries::getMessageCountsForLabel(const QSqlDatabase& db, Label* label, int account_id, bool only_total_counts, bool* ok) { int DatabaseQueries::getMessageCountsForLabel(const QSqlDatabase& db,
Label* label,
int account_id,
bool only_total_counts,
bool* ok) {
QSqlQuery q(db); QSqlQuery q(db);
q.setForwardOnly(true); q.setForwardOnly(true);
@ -601,7 +624,8 @@ int DatabaseQueries::getMessageCountsForLabel(const QSqlDatabase& db, Label* lab
"INNER JOIN LabelsInMessages " "INNER JOIN LabelsInMessages "
"ON " "ON "
" Messages.is_pdeleted = 0 AND Messages.is_deleted = 0 AND " " Messages.is_pdeleted = 0 AND Messages.is_deleted = 0 AND "
" LabelsInMessages.account_id = :account_id AND LabelsInMessages.account_id = Messages.account_id AND " " LabelsInMessages.account_id = :account_id AND LabelsInMessages.account_id = Messages.account_id "
"AND "
" LabelsInMessages.label = :label AND LabelsInMessages.message = Messages.custom_id;")); " LabelsInMessages.label = :label AND LabelsInMessages.message = Messages.custom_id;"));
} }
else { else {
@ -609,7 +633,8 @@ int DatabaseQueries::getMessageCountsForLabel(const QSqlDatabase& db, Label* lab
"INNER JOIN LabelsInMessages " "INNER JOIN LabelsInMessages "
"ON " "ON "
" Messages.is_pdeleted = 0 AND Messages.is_deleted = 0 AND Messages.is_read = 0 AND " " Messages.is_pdeleted = 0 AND Messages.is_deleted = 0 AND Messages.is_read = 0 AND "
" LabelsInMessages.account_id = :account_id AND LabelsInMessages.account_id = Messages.account_id AND " " LabelsInMessages.account_id = :account_id AND LabelsInMessages.account_id = Messages.account_id "
"AND "
" LabelsInMessages.label = :label AND LabelsInMessages.message = Messages.custom_id;")); " LabelsInMessages.label = :label AND LabelsInMessages.message = Messages.custom_id;"));
} }
@ -632,7 +657,10 @@ int DatabaseQueries::getMessageCountsForLabel(const QSqlDatabase& db, Label* lab
} }
} }
int DatabaseQueries::getImportantMessageCounts(const QSqlDatabase& db, int account_id, bool only_total_counts, bool* ok) { int DatabaseQueries::getImportantMessageCounts(const QSqlDatabase& db,
int account_id,
bool only_total_counts,
bool* ok) {
QSqlQuery q(db); QSqlQuery q(db);
q.setForwardOnly(true); q.setForwardOnly(true);
@ -643,7 +671,8 @@ int DatabaseQueries::getImportantMessageCounts(const QSqlDatabase& db, int accou
} }
else { else {
q.prepare(QSL("SELECT count(*) FROM Messages " q.prepare(QSL("SELECT count(*) FROM Messages "
"WHERE is_read = 0 AND is_important = 1 AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;")); "WHERE is_read = 0 AND is_important = 1 AND is_deleted = 0 AND is_pdeleted = 0 AND account_id = "
":account_id;"));
} }
q.bindValue(QSL(":account_id"), account_id); q.bindValue(QSL(":account_id"), account_id);
@ -689,7 +718,10 @@ int DatabaseQueries::getUnreadMessageCounts(const QSqlDatabase& db, int account_
} }
} }
int DatabaseQueries::getMessageCountsForBin(const QSqlDatabase& db, int account_id, bool including_total_counts, bool* ok) { int DatabaseQueries::getMessageCountsForBin(const QSqlDatabase& db,
int account_id,
bool including_total_counts,
bool* ok) {
QSqlQuery q(db); QSqlQuery q(db);
q.setForwardOnly(true); q.setForwardOnly(true);
@ -728,13 +760,15 @@ QList<Message> DatabaseQueries::getUndeletedMessagesWithLabel(const QSqlDatabase
q.prepare(QSL("SELECT %1 " q.prepare(QSL("SELECT %1 "
"FROM Messages " "FROM Messages "
"INNER JOIN Feeds " "INNER JOIN Feeds "
"ON Messages.feed = Feeds.custom_id AND Messages.account_id = :account_id AND Messages.account_id = Feeds.account_id " "ON Messages.feed = Feeds.custom_id AND Messages.account_id = :account_id AND Messages.account_id = "
"Feeds.account_id "
"INNER JOIN LabelsInMessages " "INNER JOIN LabelsInMessages "
"ON " "ON "
" Messages.is_pdeleted = 0 AND Messages.is_deleted = 0 AND " " Messages.is_pdeleted = 0 AND Messages.is_deleted = 0 AND "
" LabelsInMessages.account_id = :account_id AND LabelsInMessages.account_id = Messages.account_id AND " " LabelsInMessages.account_id = :account_id AND LabelsInMessages.account_id = Messages.account_id AND "
" LabelsInMessages.label = :label AND " " LabelsInMessages.label = :label AND "
" LabelsInMessages.message = Messages.custom_id;").arg(messageTableAttributes(true).values().join(QSL(", ")))); " LabelsInMessages.message = Messages.custom_id;")
.arg(messageTableAttributes(true).values().join(QSL(", "))));
q.bindValue(QSL(":account_id"), label->getParentServiceRoot()->accountId()); q.bindValue(QSL(":account_id"), label->getParentServiceRoot()->accountId());
q.bindValue(QSL(":label"), label->customId()); q.bindValue(QSL(":label"), label->customId());
@ -772,7 +806,8 @@ QList<Message> DatabaseQueries::getUndeletedLabelledMessages(const QSqlDatabase&
"WHERE Messages.is_deleted = 0 AND Messages.is_pdeleted = 0 AND Messages.account_id = :account_id AND " "WHERE Messages.is_deleted = 0 AND Messages.is_pdeleted = 0 AND Messages.account_id = :account_id AND "
" (SELECT COUNT(*) FROM LabelsInMessages " " (SELECT COUNT(*) FROM LabelsInMessages "
" WHERE account_id = :account_id AND " " WHERE account_id = :account_id AND "
" message = Messages.custom_id) > 0;").arg(messageTableAttributes(true).values().join(QSL(", ")))); " message = Messages.custom_id) > 0;")
.arg(messageTableAttributes(true).values().join(QSL(", "))));
q.bindValue(QSL(":account_id"), account_id); q.bindValue(QSL(":account_id"), account_id);
if (q.exec()) { if (q.exec()) {
@ -806,7 +841,8 @@ QList<Message> DatabaseQueries::getUndeletedImportantMessages(const QSqlDatabase
q.prepare(QSL("SELECT %1 " q.prepare(QSL("SELECT %1 "
"FROM Messages " "FROM Messages "
"WHERE is_important = 1 AND is_deleted = 0 AND " "WHERE is_important = 1 AND is_deleted = 0 AND "
" is_pdeleted = 0 AND account_id = :account_id;").arg(messageTableAttributes(true).values().join(QSL(", ")))); " is_pdeleted = 0 AND account_id = :account_id;")
.arg(messageTableAttributes(true).values().join(QSL(", "))));
q.bindValue(QSL(":account_id"), account_id); q.bindValue(QSL(":account_id"), account_id);
if (q.exec()) { if (q.exec()) {
@ -840,7 +876,8 @@ QList<Message> DatabaseQueries::getUndeletedUnreadMessages(const QSqlDatabase& d
q.prepare(QSL("SELECT %1 " q.prepare(QSL("SELECT %1 "
"FROM Messages " "FROM Messages "
"WHERE is_read = 0 AND is_deleted = 0 AND " "WHERE is_read = 0 AND is_deleted = 0 AND "
" is_pdeleted = 0 AND account_id = :account_id;").arg(messageTableAttributes(true).values().join(QSL(", ")))); " is_pdeleted = 0 AND account_id = :account_id;")
.arg(messageTableAttributes(true).values().join(QSL(", "))));
q.bindValue(QSL(":account_id"), account_id); q.bindValue(QSL(":account_id"), account_id);
if (q.exec()) { if (q.exec()) {
@ -866,8 +903,10 @@ QList<Message> DatabaseQueries::getUndeletedUnreadMessages(const QSqlDatabase& d
return messages; return messages;
} }
QList<Message> DatabaseQueries::getUndeletedMessagesForFeed(const QSqlDatabase& db, const QString& feed_custom_id, QList<Message> DatabaseQueries::getUndeletedMessagesForFeed(const QSqlDatabase& db,
int account_id, bool* ok) { const QString& feed_custom_id,
int account_id,
bool* ok) {
QList<Message> messages; QList<Message> messages;
QSqlQuery q(db); QSqlQuery q(db);
@ -875,7 +914,8 @@ QList<Message> DatabaseQueries::getUndeletedMessagesForFeed(const QSqlDatabase&
q.prepare(QSL("SELECT %1 " q.prepare(QSL("SELECT %1 "
"FROM Messages " "FROM Messages "
"WHERE is_deleted = 0 AND is_pdeleted = 0 AND " "WHERE is_deleted = 0 AND is_pdeleted = 0 AND "
" feed = :feed AND account_id = :account_id;").arg(messageTableAttributes(true).values().join(QSL(", ")))); " feed = :feed AND account_id = :account_id;")
.arg(messageTableAttributes(true).values().join(QSL(", "))));
q.bindValue(QSL(":feed"), feed_custom_id); q.bindValue(QSL(":feed"), feed_custom_id);
q.bindValue(QSL(":account_id"), account_id); q.bindValue(QSL(":account_id"), account_id);
@ -909,7 +949,8 @@ QList<Message> DatabaseQueries::getUndeletedMessagesForBin(const QSqlDatabase& d
q.setForwardOnly(true); q.setForwardOnly(true);
q.prepare(QSL("SELECT %1 " q.prepare(QSL("SELECT %1 "
"FROM Messages " "FROM Messages "
"WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;").arg(messageTableAttributes(true).values().join(QSL(", ")))); "WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;")
.arg(messageTableAttributes(true).values().join(QSL(", "))));
q.bindValue(QSL(":account_id"), account_id); q.bindValue(QSL(":account_id"), account_id);
if (q.exec()) { if (q.exec()) {
@ -942,7 +983,8 @@ QList<Message> DatabaseQueries::getUndeletedMessagesForAccount(const QSqlDatabas
q.setForwardOnly(true); q.setForwardOnly(true);
q.prepare(QSL("SELECT %1 " q.prepare(QSL("SELECT %1 "
"FROM Messages " "FROM Messages "
"WHERE is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;").arg(messageTableAttributes(true).values().join(QSL(", ")))); "WHERE is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;")
.arg(messageTableAttributes(true).values().join(QSL(", "))));
q.bindValue(QSL(":account_id"), account_id); q.bindValue(QSL(":account_id"), account_id);
if (q.exec()) { if (q.exec()) {
@ -992,7 +1034,8 @@ QStringList DatabaseQueries::bagOfMessages(const QSqlDatabase& db, ServiceRoot::
q.prepare(QSL("SELECT custom_id " q.prepare(QSL("SELECT custom_id "
"FROM Messages " "FROM Messages "
"WHERE %1 AND feed = :feed AND account_id = :account_id;").arg(query)); "WHERE %1 AND feed = :feed AND account_id = :account_id;")
.arg(query));
q.bindValue(QSL(":account_id"), feed->getParentServiceRoot()->accountId()); q.bindValue(QSL(":account_id"), feed->getParentServiceRoot()->accountId());
q.bindValue(QSL(":feed"), feed->customId()); q.bindValue(QSL(":feed"), feed->customId());
@ -1065,40 +1108,47 @@ QPair<int, int> DatabaseQueries::updateMessages(QSqlDatabase db,
// NOTE: This only applies to messages from standard RSS/ATOM/JSON feeds without ID/GUID. // NOTE: This only applies to messages from standard RSS/ATOM/JSON feeds without ID/GUID.
query_select_with_url.setForwardOnly(true); query_select_with_url.setForwardOnly(true);
query_select_with_url.prepare(QSL("SELECT id, date_created, is_read, is_important, contents, feed FROM Messages " query_select_with_url.prepare(QSL("SELECT id, date_created, is_read, is_important, contents, feed FROM Messages "
"WHERE feed = :feed AND title = :title AND url = :url AND author = :author AND account_id = :account_id;")); "WHERE feed = :feed AND title = :title AND url = :url AND author = :author AND "
"account_id = :account_id;"));
// When we have custom ID of the message which is service-specific (synchronized services). // When we have custom ID of the message which is service-specific (synchronized services).
query_select_with_custom_id.setForwardOnly(true); query_select_with_custom_id.setForwardOnly(true);
query_select_with_custom_id.prepare(QSL("SELECT id, date_created, is_read, is_important, contents, feed, title, author FROM Messages " query_select_with_custom_id
.prepare(QSL("SELECT id, date_created, is_read, is_important, contents, feed, title, author FROM Messages "
"WHERE custom_id = :custom_id AND account_id = :account_id;")); "WHERE custom_id = :custom_id AND account_id = :account_id;"));
// We have custom ID of message, but it is feed-specific not service-specific (standard RSS/ATOM/JSON). // We have custom ID of message, but it is feed-specific not service-specific (standard RSS/ATOM/JSON).
query_select_with_custom_id_for_feed.setForwardOnly(true); query_select_with_custom_id_for_feed.setForwardOnly(true);
query_select_with_custom_id_for_feed.prepare(QSL("SELECT id, date_created, is_read, is_important, contents, title, author FROM Messages " query_select_with_custom_id_for_feed
.prepare(QSL("SELECT id, date_created, is_read, is_important, contents, title, author FROM Messages "
"WHERE feed = :feed AND custom_id = :custom_id AND account_id = :account_id;")); "WHERE feed = :feed AND custom_id = :custom_id AND account_id = :account_id;"));
// In some case, messages are already stored in the DB and they all have primary DB ID. // In some case, messages are already stored in the DB and they all have primary DB ID.
// This is particularly the case when user runs some message filter manually on existing messages // This is particularly the case when user runs some message filter manually on existing messages
// of some feed. // of some feed.
query_select_with_id.setForwardOnly(true); query_select_with_id.setForwardOnly(true);
query_select_with_id.prepare(QSL("SELECT date_created, is_read, is_important, contents, feed, title, author FROM Messages " query_select_with_id
.prepare(QSL("SELECT date_created, is_read, is_important, contents, feed, title, author FROM Messages "
"WHERE id = :id AND account_id = :account_id;")); "WHERE id = :id AND account_id = :account_id;"));
// Used to insert new messages. // Used to insert new messages.
query_insert.setForwardOnly(true); query_insert.setForwardOnly(true);
query_insert.prepare(QSL("INSERT INTO Messages " query_insert.prepare(QSL("INSERT INTO Messages "
"(feed, title, is_read, is_important, is_deleted, url, author, score, date_created, contents, enclosures, custom_id, custom_hash, account_id) " "(feed, title, is_read, is_important, is_deleted, url, author, score, date_created, "
"VALUES (:feed, :title, :is_read, :is_important, :is_deleted, :url, :author, :score, :date_created, :contents, :enclosures, :custom_id, :custom_hash, :account_id);")); "contents, enclosures, custom_id, custom_hash, account_id) "
"VALUES (:feed, :title, :is_read, :is_important, :is_deleted, :url, :author, :score, "
":date_created, :contents, :enclosures, :custom_id, :custom_hash, :account_id);"));
// Used to update existing messages. // Used to update existing messages.
query_update.setForwardOnly(true); query_update.setForwardOnly(true);
query_update.prepare(QSL("UPDATE Messages " query_update.prepare(QSL("UPDATE Messages "
"SET title = :title, is_read = :is_read, is_important = :is_important, is_deleted = :is_deleted, url = :url, author = :author, score = :score, date_created = :date_created, contents = :contents, enclosures = :enclosures, feed = :feed " "SET title = :title, is_read = :is_read, is_important = :is_important, is_deleted = "
":is_deleted, url = :url, author = :author, score = :score, date_created = :date_created, "
"contents = :contents, enclosures = :enclosures, feed = :feed "
"WHERE id = :id;")); "WHERE id = :id;"));
if (use_transactions && !db.transaction()) { if (use_transactions && !db.transaction()) {
qCriticalNN << LOGSEC_DB qCriticalNN << LOGSEC_DB << "Transaction start for message downloader failed:"
<< "Transaction start for message downloader failed:"
<< QUOTE_W_SPACE_DOT(query_begin_transaction.lastError().text()); << QUOTE_W_SPACE_DOT(query_begin_transaction.lastError().text());
return updated_messages; return updated_messages;
} }
@ -1121,9 +1171,7 @@ QPair<int, int> DatabaseQueries::updateMessages(QSqlDatabase db,
query_select_with_id.bindValue(QSL(":id"), message.m_id); query_select_with_id.bindValue(QSL(":id"), message.m_id);
query_select_with_id.bindValue(QSL(":account_id"), account_id); query_select_with_id.bindValue(QSL(":account_id"), account_id);
qDebugNN << LOGSEC_DB qDebugNN << LOGSEC_DB << "Checking if message with primary ID" << QUOTE_W_SPACE(message.m_id)
<< "Checking if message with primary ID"
<< QUOTE_W_SPACE(message.m_id)
<< "is present in DB."; << "is present in DB.";
if (query_select_with_id.exec() && query_select_with_id.next()) { if (query_select_with_id.exec() && query_select_with_id.next()) {
@ -1136,13 +1184,11 @@ QPair<int, int> DatabaseQueries::updateMessages(QSqlDatabase db,
title_existing_message = query_select_with_id.value(5).toString(); title_existing_message = query_select_with_id.value(5).toString();
author_existing_message = query_select_with_id.value(6).toString(); author_existing_message = query_select_with_id.value(6).toString();
qDebugNN << LOGSEC_DB qDebugNN << LOGSEC_DB << "Message with direct DB ID is already present in DB and has DB ID"
<< "Message with direct DB ID is already present in DB and has DB ID"
<< QUOTE_W_SPACE_DOT(id_existing_message); << QUOTE_W_SPACE_DOT(id_existing_message);
} }
else if (query_select_with_id.lastError().isValid()) { else if (query_select_with_id.lastError().isValid()) {
qWarningNN << LOGSEC_DB qWarningNN << LOGSEC_DB << "Failed to check for existing message in DB via primary ID:"
<< "Failed to check for existing message in DB via primary ID:"
<< QUOTE_W_SPACE_DOT(query_select_with_id.lastError().text()); << QUOTE_W_SPACE_DOT(query_select_with_id.lastError().text());
} }
@ -1158,13 +1204,8 @@ QPair<int, int> DatabaseQueries::updateMessages(QSqlDatabase db,
query_select_with_url.bindValue(QSL(":author"), unnulifyString(message.m_author)); query_select_with_url.bindValue(QSL(":author"), unnulifyString(message.m_author));
query_select_with_url.bindValue(QSL(":account_id"), account_id); query_select_with_url.bindValue(QSL(":account_id"), account_id);
qDebugNN << LOGSEC_DB qDebugNN << LOGSEC_DB << "Checking if message with title " << QUOTE_NO_SPACE(message.m_title) << ", url "
<< "Checking if message with title " << QUOTE_NO_SPACE(message.m_url) << "' and author " << QUOTE_NO_SPACE(message.m_author)
<< QUOTE_NO_SPACE(message.m_title)
<< ", url "
<< QUOTE_NO_SPACE(message.m_url)
<< "' and author "
<< QUOTE_NO_SPACE(message.m_author)
<< " is present in DB."; << " is present in DB.";
if (query_select_with_url.exec() && query_select_with_url.next()) { if (query_select_with_url.exec() && query_select_with_url.next()) {
@ -1177,13 +1218,11 @@ QPair<int, int> DatabaseQueries::updateMessages(QSqlDatabase db,
title_existing_message = unnulifyString(message.m_title); title_existing_message = unnulifyString(message.m_title);
author_existing_message = unnulifyString(message.m_author); author_existing_message = unnulifyString(message.m_author);
qDebugNN << LOGSEC_DB qDebugNN << LOGSEC_DB << "Message with these attributes is already present in DB and has DB ID"
<< "Message with these attributes is already present in DB and has DB ID"
<< QUOTE_W_SPACE_DOT(id_existing_message); << QUOTE_W_SPACE_DOT(id_existing_message);
} }
else if (query_select_with_url.lastError().isValid()) { else if (query_select_with_url.lastError().isValid()) {
qWarningNN << LOGSEC_DB qWarningNN << LOGSEC_DB << "Failed to check for existing message in DB via URL/TITLE/AUTHOR:"
<< "Failed to check for existing message in DB via URL/TITLE/AUTHOR:"
<< QUOTE_W_SPACE_DOT(query_select_with_url.lastError().text()); << QUOTE_W_SPACE_DOT(query_select_with_url.lastError().text());
} }
@ -1197,10 +1236,8 @@ QPair<int, int> DatabaseQueries::updateMessages(QSqlDatabase db,
query_select_with_custom_id.bindValue(QSL(":account_id"), account_id); query_select_with_custom_id.bindValue(QSL(":account_id"), account_id);
query_select_with_custom_id.bindValue(QSL(":custom_id"), unnulifyString(message.m_customId)); query_select_with_custom_id.bindValue(QSL(":custom_id"), unnulifyString(message.m_customId));
qDebugNN << LOGSEC_DB qDebugNN << LOGSEC_DB << "Checking if message with service-specific custom ID"
<< "Checking if message with service-specific custom ID" << QUOTE_W_SPACE(message.m_customId) << "is present in DB.";
<< QUOTE_W_SPACE(message.m_customId)
<< "is present in DB.";
if (query_select_with_custom_id.exec() && query_select_with_custom_id.next()) { if (query_select_with_custom_id.exec() && query_select_with_custom_id.next()) {
id_existing_message = query_select_with_custom_id.value(0).toInt(); id_existing_message = query_select_with_custom_id.value(0).toInt();
@ -1212,16 +1249,11 @@ QPair<int, int> DatabaseQueries::updateMessages(QSqlDatabase db,
title_existing_message = query_select_with_custom_id.value(6).toString(); title_existing_message = query_select_with_custom_id.value(6).toString();
author_existing_message = query_select_with_custom_id.value(7).toString(); author_existing_message = query_select_with_custom_id.value(7).toString();
qDebugNN << LOGSEC_DB qDebugNN << LOGSEC_DB << "Message with custom ID" << QUOTE_W_SPACE(message.m_customId)
<< "Message with custom ID" << "is already present in DB and has DB ID '" << id_existing_message << "'.";
<< QUOTE_W_SPACE(message.m_customId)
<< "is already present in DB and has DB ID '"
<< id_existing_message
<< "'.";
} }
else if (query_select_with_custom_id.lastError().isValid()) { else if (query_select_with_custom_id.lastError().isValid()) {
qWarningNN << LOGSEC_DB qWarningNN << LOGSEC_DB << "Failed to check for existing message in DB via ID:"
<< "Failed to check for existing message in DB via ID:"
<< QUOTE_W_SPACE_DOT(query_select_with_custom_id.lastError().text()); << QUOTE_W_SPACE_DOT(query_select_with_custom_id.lastError().text());
} }
@ -1234,9 +1266,7 @@ QPair<int, int> DatabaseQueries::updateMessages(QSqlDatabase db,
query_select_with_custom_id_for_feed.bindValue(QSL(":feed"), feed_custom_id); query_select_with_custom_id_for_feed.bindValue(QSL(":feed"), feed_custom_id);
query_select_with_custom_id_for_feed.bindValue(QSL(":custom_id"), unnulifyString(message.m_customId)); query_select_with_custom_id_for_feed.bindValue(QSL(":custom_id"), unnulifyString(message.m_customId));
qDebugNN << LOGSEC_DB qDebugNN << LOGSEC_DB << "Checking if message with feed-specific custom ID" << QUOTE_W_SPACE(message.m_customId)
<< "Checking if message with feed-specific custom ID"
<< QUOTE_W_SPACE(message.m_customId)
<< "is present in DB."; << "is present in DB.";
if (query_select_with_custom_id_for_feed.exec() && query_select_with_custom_id_for_feed.next()) { if (query_select_with_custom_id_for_feed.exec() && query_select_with_custom_id_for_feed.next()) {
@ -1249,15 +1279,11 @@ QPair<int, int> DatabaseQueries::updateMessages(QSqlDatabase db,
title_existing_message = query_select_with_custom_id_for_feed.value(5).toString(); title_existing_message = query_select_with_custom_id_for_feed.value(5).toString();
author_existing_message = query_select_with_custom_id_for_feed.value(6).toString(); author_existing_message = query_select_with_custom_id_for_feed.value(6).toString();
qDebugNN << LOGSEC_DB qDebugNN << LOGSEC_DB << "Message with custom ID" << QUOTE_W_SPACE(message.m_customId)
<< "Message with custom ID" << "is already present in DB and has DB ID" << QUOTE_W_SPACE_DOT(id_existing_message);
<< QUOTE_W_SPACE(message.m_customId)
<< "is already present in DB and has DB ID"
<< QUOTE_W_SPACE_DOT(id_existing_message);
} }
else if (query_select_with_custom_id_for_feed.lastError().isValid()) { else if (query_select_with_custom_id_for_feed.lastError().isValid()) {
qWarningNN << LOGSEC_DB qWarningNN << LOGSEC_DB << "Failed to check for existing message in DB via ID:"
<< "Failed to check for existing message in DB via ID:"
<< QUOTE_W_SPACE_DOT(query_select_with_custom_id_for_feed.lastError().text()); << QUOTE_W_SPACE_DOT(query_select_with_custom_id_for_feed.lastError().text());
} }
@ -1286,17 +1312,17 @@ QPair<int, int> DatabaseQueries::updateMessages(QSqlDatabase db,
// 4) FOR ALL SERVICES: // 4) FOR ALL SERVICES:
// Message update is forced, we want to overwrite message as some arbitrary atribute was changed, // Message update is forced, we want to overwrite message as some arbitrary atribute was changed,
// this particularly happens when manual message filter execution happens. // this particularly happens when manual message filter execution happens.
bool ignore_contents_changes = qApp->settings()->value(GROUP(Messages), SETTING(Messages::IgnoreContentsChanges)).toBool(); bool ignore_contents_changes =
bool cond_1 = !message.m_customId.isEmpty() && feed->getParentServiceRoot()->isSyncable() && qApp->settings()->value(GROUP(Messages), SETTING(Messages::IgnoreContentsChanges)).toBool();
bool cond_1 =
!message.m_customId.isEmpty() && feed->getParentServiceRoot()->isSyncable() &&
(message.m_created.toMSecsSinceEpoch() != date_existing_message || (message.m_created.toMSecsSinceEpoch() != date_existing_message ||
message.m_isRead != is_read_existing_message || message.m_isRead != is_read_existing_message || message.m_isImportant != is_important_existing_message ||
message.m_isImportant != is_important_existing_message ||
(message.m_feedId != feed_id_existing_message && message.m_feedId == feed_custom_id) || (message.m_feedId != feed_id_existing_message && message.m_feedId == feed_custom_id) ||
message.m_title != title_existing_message || message.m_title != title_existing_message ||
(!ignore_contents_changes && message.m_contents != contents_existing_message)); (!ignore_contents_changes && message.m_contents != contents_existing_message));
bool cond_2 = !message.m_customId.isEmpty() && !feed->getParentServiceRoot()->isSyncable() && bool cond_2 = !message.m_customId.isEmpty() && !feed->getParentServiceRoot()->isSyncable() &&
(message.m_title != title_existing_message || (message.m_title != title_existing_message || message.m_author != author_existing_message ||
message.m_author != author_existing_message ||
(!ignore_contents_changes && message.m_contents != contents_existing_message)); (!ignore_contents_changes && message.m_contents != contents_existing_message));
bool cond_3 = (message.m_createdFromFeed && message.m_created.toMSecsSinceEpoch() != date_existing_message) || bool cond_3 = (message.m_createdFromFeed && message.m_created.toMSecsSinceEpoch() != date_existing_message) ||
(!ignore_contents_changes && message.m_contents != contents_existing_message); (!ignore_contents_changes && message.m_contents != contents_existing_message);
@ -1305,7 +1331,8 @@ QPair<int, int> DatabaseQueries::updateMessages(QSqlDatabase db,
// Message exists and is changed, update it. // Message exists and is changed, update it.
query_update.bindValue(QSL(":title"), unnulifyString(message.m_title)); query_update.bindValue(QSL(":title"), unnulifyString(message.m_title));
query_update.bindValue(QSL(":is_read"), int(message.m_isRead)); query_update.bindValue(QSL(":is_read"), int(message.m_isRead));
query_update.bindValue(QSL(":is_important"), (feed->getParentServiceRoot()->isSyncable() || message.m_isImportant) query_update.bindValue(QSL(":is_important"),
(feed->getParentServiceRoot()->isSyncable() || message.m_isImportant)
? int(message.m_isImportant) ? int(message.m_isImportant)
: is_important_existing_message); : is_important_existing_message);
query_update.bindValue(QSL(":is_deleted"), int(message.m_isDeleted)); query_update.bindValue(QSL(":is_deleted"), int(message.m_isDeleted));
@ -1319,12 +1346,8 @@ QPair<int, int> DatabaseQueries::updateMessages(QSqlDatabase db,
query_update.bindValue(QSL(":id"), id_existing_message); query_update.bindValue(QSL(":id"), id_existing_message);
if (query_update.exec()) { if (query_update.exec()) {
qDebugNN << LOGSEC_DB qDebugNN << LOGSEC_DB << "Overwriting message with title" << QUOTE_W_SPACE(message.m_title) << "URL"
<< "Overwriting message with title" << QUOTE_W_SPACE(message.m_url) << "in DB.";
<< QUOTE_W_SPACE(message.m_title)
<< "URL"
<< QUOTE_W_SPACE(message.m_url)
<< "in DB.";
if (!message.m_isRead) { if (!message.m_isRead) {
updated_messages.first++; updated_messages.first++;
@ -1334,8 +1357,7 @@ QPair<int, int> DatabaseQueries::updateMessages(QSqlDatabase db,
} }
else if (query_update.lastError().isValid()) { else if (query_update.lastError().isValid()) {
qWarningNN << LOGSEC_DB qWarningNN << LOGSEC_DB
<< "Failed to update message in DB:" << "Failed to update message in DB:" << QUOTE_W_SPACE_DOT(query_update.lastError().text());
<< QUOTE_W_SPACE_DOT(query_update.lastError().text());
} }
query_update.finish(); query_update.finish();
@ -1354,7 +1376,8 @@ QPair<int, int> DatabaseQueries::updateMessages(QSqlDatabase db,
if (!msgs_to_insert.isEmpty()) { if (!msgs_to_insert.isEmpty()) {
QString bulk_insert = QSL("INSERT INTO Messages " QString bulk_insert = QSL("INSERT INTO Messages "
"(feed, title, is_read, is_important, is_deleted, url, author, score, date_created, contents, enclosures, custom_id, custom_hash, account_id) " "(feed, title, is_read, is_important, is_deleted, url, author, score, date_created, "
"contents, enclosures, custom_id, custom_hash, account_id) "
"VALUES %1;"); "VALUES %1;");
for (int i = 0; i < msgs_to_insert.size(); i += 1000) { for (int i = 0; i < msgs_to_insert.size(); i += 1000) {
@ -1365,9 +1388,7 @@ QPair<int, int> DatabaseQueries::updateMessages(QSqlDatabase db,
Message* msg = msgs_to_insert[l]; Message* msg = msgs_to_insert[l];
if (msg->m_title.isEmpty()) { if (msg->m_title.isEmpty()) {
qCriticalNN << LOGSEC_DB qCriticalNN << LOGSEC_DB << "Message" << QUOTE_W_SPACE(msg->m_customId)
<< "Message"
<< QUOTE_W_SPACE(msg->m_customId)
<< "will not be inserted to DB because it does not meet DB constraints."; << "will not be inserted to DB because it does not meet DB constraints.";
// Message is not inserted to DB at last, // Message is not inserted to DB at last,
@ -1407,9 +1428,7 @@ QPair<int, int> DatabaseQueries::updateMessages(QSqlDatabase db,
if (bulk_error.isValid()) { if (bulk_error.isValid()) {
QString txt = bulk_error.text() + bulk_error.databaseText() + bulk_error.driverText(); QString txt = bulk_error.text() + bulk_error.databaseText() + bulk_error.driverText();
qCriticalNN << LOGSEC_DB qCriticalNN << LOGSEC_DB << "Failed bulk insert of articles:" << QUOTE_W_SPACE_DOT(txt);
<< "Failed bulk insert of articles:"
<< QUOTE_W_SPACE_DOT(txt);
} }
else { else {
// OK, we bulk-inserted many messages but the thing is that they do not // OK, we bulk-inserted many messages but the thing is that they do not
@ -1437,9 +1456,7 @@ QPair<int, int> DatabaseQueries::updateMessages(QSqlDatabase db,
setLabelsForMessage(db, message.m_assignedLabels, message); setLabelsForMessage(db, message.m_assignedLabels, message);
} }
else { else {
qWarningNN << LOGSEC_DB qWarningNN << LOGSEC_DB << "Cannot set labels for message" << QUOTE_W_SPACE(message.m_title)
<< "Cannot set labels for message"
<< QUOTE_W_SPACE(message.m_title)
<< "because we don't have ID or custom ID."; << "because we don't have ID or custom ID.";
} }
} }
@ -1449,16 +1466,15 @@ QPair<int, int> DatabaseQueries::updateMessages(QSqlDatabase db,
// just to keep the data consistent. // just to keep the data consistent.
if (db.exec("UPDATE Messages " if (db.exec("UPDATE Messages "
"SET custom_id = id " "SET custom_id = id "
"WHERE custom_id IS NULL OR custom_id = '';").lastError().isValid()) { "WHERE custom_id IS NULL OR custom_id = '';")
qWarningNN << LOGSEC_DB .lastError()
<< "Failed to set custom ID for all messages:" .isValid()) {
<< QUOTE_W_SPACE_DOT(db.lastError().text()); qWarningNN << LOGSEC_DB << "Failed to set custom ID for all messages:" << QUOTE_W_SPACE_DOT(db.lastError().text());
} }
if (use_transactions && !db.commit()) { if (use_transactions && !db.commit()) {
qCriticalNN << LOGSEC_DB qCriticalNN << LOGSEC_DB
<< "Transaction commit for message downloader failed:" << "Transaction commit for message downloader failed:" << QUOTE_W_SPACE_DOT(db.lastError().text());
<< QUOTE_W_SPACE_DOT(db.lastError().text());
db.rollback(); db.rollback();
if (ok != nullptr) { if (ok != nullptr) {
@ -1481,7 +1497,8 @@ bool DatabaseQueries::purgeMessagesFromBin(const QSqlDatabase& db, bool clear_on
q.setForwardOnly(true); q.setForwardOnly(true);
if (clear_only_read) { if (clear_only_read) {
q.prepare(QSL("UPDATE Messages SET is_pdeleted = 1 WHERE is_read = 1 AND is_deleted = 1 AND account_id = :account_id;")); q.prepare(QSL("UPDATE Messages SET is_pdeleted = 1 WHERE is_read = 1 AND is_deleted = 1 AND account_id = "
":account_id;"));
} }
else { else {
q.prepare(QSL("UPDATE Messages SET is_pdeleted = 1 WHERE is_deleted = 1 AND account_id = :account_id;")); q.prepare(QSL("UPDATE Messages SET is_pdeleted = 1 WHERE is_deleted = 1 AND account_id = :account_id;"));
@ -1512,9 +1529,7 @@ bool DatabaseQueries::deleteAccount(const QSqlDatabase& db, ServiceRoot* account
query.bindValue(QSL(":account_id"), account->accountId()); query.bindValue(QSL(":account_id"), account->accountId());
if (!query.exec()) { if (!query.exec()) {
qCriticalNN << LOGSEC_DB qCriticalNN << LOGSEC_DB << "Removing of account from DB failed, this is critical: '" << query.lastError().text()
<< "Removing of account from DB failed, this is critical: '"
<< query.lastError().text()
<< "'."; << "'.";
return false; return false;
} }
@ -1576,7 +1591,9 @@ bool DatabaseQueries::cleanLabelledMessages(const QSqlDatabase& db, bool clean_r
" is_pdeleted = 0 AND " " is_pdeleted = 0 AND "
" is_read = 1 AND " " is_read = 1 AND "
" account_id = :account_id AND " " account_id = :account_id AND "
" EXISTS (SELECT * FROM LabelsInMessages WHERE LabelsInMessages.label = :label AND Messages.account_id = LabelsInMessages.account_id AND Messages.custom_id = LabelsInMessages.message);")); " EXISTS (SELECT * FROM LabelsInMessages WHERE LabelsInMessages.label = :label AND "
"Messages.account_id = LabelsInMessages.account_id AND Messages.custom_id = "
"LabelsInMessages.message);"));
} }
else { else {
q.prepare(QSL("UPDATE Messages SET is_deleted = :deleted " q.prepare(QSL("UPDATE Messages SET is_deleted = :deleted "
@ -1584,7 +1601,9 @@ bool DatabaseQueries::cleanLabelledMessages(const QSqlDatabase& db, bool clean_r
" is_deleted = 0 AND " " is_deleted = 0 AND "
" is_pdeleted = 0 AND " " is_pdeleted = 0 AND "
" account_id = :account_id AND " " account_id = :account_id AND "
" EXISTS (SELECT * FROM LabelsInMessages WHERE LabelsInMessages.label = :label AND Messages.account_id = LabelsInMessages.account_id AND Messages.custom_id = LabelsInMessages.message);")); " EXISTS (SELECT * FROM LabelsInMessages WHERE LabelsInMessages.label = :label AND "
"Messages.account_id = LabelsInMessages.account_id AND Messages.custom_id = "
"LabelsInMessages.message);"));
} }
q.bindValue(QSL(":deleted"), 1); q.bindValue(QSL(":deleted"), 1);
@ -1592,10 +1611,7 @@ bool DatabaseQueries::cleanLabelledMessages(const QSqlDatabase& db, bool clean_r
q.bindValue(QSL(":label"), label->customId()); q.bindValue(QSL(":label"), label->customId());
if (!q.exec()) { if (!q.exec()) {
qWarningNN << LOGSEC_DB qWarningNN << LOGSEC_DB << "Cleaning of labelled messages failed: '" << q.lastError().text() << "'.";
<< "Cleaning of labelled messages failed: '"
<< q.lastError().text()
<< "'.";
return false; return false;
} }
else { else {
@ -1610,7 +1626,8 @@ bool DatabaseQueries::cleanImportantMessages(const QSqlDatabase& db, bool clean_
if (clean_read_only) { if (clean_read_only) {
q.prepare(QSL("UPDATE Messages SET is_deleted = :deleted " q.prepare(QSL("UPDATE Messages SET is_deleted = :deleted "
"WHERE is_important = 1 AND is_deleted = 0 AND is_pdeleted = 0 AND is_read = 1 AND account_id = :account_id;")); "WHERE is_important = 1 AND is_deleted = 0 AND is_pdeleted = 0 AND is_read = 1 AND account_id = "
":account_id;"));
} }
else { else {
q.prepare(QSL("UPDATE Messages SET is_deleted = :deleted " q.prepare(QSL("UPDATE Messages SET is_deleted = :deleted "
@ -1621,10 +1638,7 @@ bool DatabaseQueries::cleanImportantMessages(const QSqlDatabase& db, bool clean_
q.bindValue(QSL(":account_id"), account_id); q.bindValue(QSL(":account_id"), account_id);
if (!q.exec()) { if (!q.exec()) {
qWarningNN << LOGSEC_DB qWarningNN << LOGSEC_DB << "Cleaning of important messages failed: '" << q.lastError().text() << "'.";
<< "Cleaning of important messages failed: '"
<< q.lastError().text()
<< "'.";
return false; return false;
} }
else { else {
@ -1643,10 +1657,7 @@ bool DatabaseQueries::cleanUnreadMessages(const QSqlDatabase& db, int account_id
q.bindValue(QSL(":account_id"), account_id); q.bindValue(QSL(":account_id"), account_id);
if (!q.exec()) { if (!q.exec()) {
qWarningNN << LOGSEC_DB qWarningNN << LOGSEC_DB << "Cleaning of unread messages failed: '" << q.lastError().text() << "'.";
<< "Cleaning of unread messages failed: '"
<< q.lastError().text()
<< "'.";
return false; return false;
} }
else { else {
@ -1661,7 +1672,8 @@ bool DatabaseQueries::cleanFeeds(const QSqlDatabase& db, const QStringList& ids,
if (clean_read_only) { if (clean_read_only) {
q.prepare(QString("UPDATE Messages SET is_deleted = :deleted " q.prepare(QString("UPDATE Messages SET is_deleted = :deleted "
"WHERE feed IN (%1) AND is_deleted = 0 AND is_pdeleted = 0 AND is_read = 1 AND account_id = :account_id;") "WHERE feed IN (%1) AND is_deleted = 0 AND is_pdeleted = 0 AND is_read = 1 AND account_id = "
":account_id;")
.arg(ids.join(QSL(", ")))); .arg(ids.join(QSL(", "))));
} }
else { else {
@ -1674,10 +1686,7 @@ bool DatabaseQueries::cleanFeeds(const QSqlDatabase& db, const QStringList& ids,
q.bindValue(QSL(":account_id"), account_id); q.bindValue(QSL(":account_id"), account_id);
if (!q.exec()) { if (!q.exec()) {
qWarningNN << LOGSEC_DB qWarningNN << LOGSEC_DB << "Cleaning of feeds failed: '" << q.lastError().text() << "'.";
<< "Cleaning of feeds failed: '"
<< q.lastError().text()
<< "'.";
return false; return false;
} }
else { else {
@ -1689,16 +1698,13 @@ bool DatabaseQueries::purgeLeftoverMessageFilterAssignments(const QSqlDatabase&
QSqlQuery q(db); QSqlQuery q(db);
q.setForwardOnly(true); q.setForwardOnly(true);
q.prepare( q.prepare(QSL("DELETE FROM MessageFiltersInFeeds "
QSL("DELETE FROM MessageFiltersInFeeds "
"WHERE account_id = :account_id AND " "WHERE account_id = :account_id AND "
"feed_custom_id NOT IN (SELECT custom_id FROM Feeds WHERE account_id = :account_id);")); "feed_custom_id NOT IN (SELECT custom_id FROM Feeds WHERE account_id = :account_id);"));
q.bindValue(QSL(":account_id"), account_id); q.bindValue(QSL(":account_id"), account_id);
if (!q.exec()) { if (!q.exec()) {
qWarningNN << LOGSEC_DB qWarningNN << LOGSEC_DB << "Removing of leftover message filter assignments failed: '" << q.lastError().text()
<< "Removing of leftover message filter assignments failed: '"
<< q.lastError().text()
<< "'."; << "'.";
return false; return false;
} }
@ -1712,14 +1718,12 @@ bool DatabaseQueries::purgeLeftoverMessages(const QSqlDatabase& db, int account_
q.setForwardOnly(true); q.setForwardOnly(true);
q.prepare(QSL("DELETE FROM Messages " q.prepare(QSL("DELETE FROM Messages "
"WHERE account_id = :account_id AND feed NOT IN (SELECT custom_id FROM Feeds WHERE account_id = :account_id);")); "WHERE account_id = :account_id AND feed NOT IN (SELECT custom_id FROM Feeds WHERE account_id = "
":account_id);"));
q.bindValue(QSL(":account_id"), account_id); q.bindValue(QSL(":account_id"), account_id);
if (!q.exec()) { if (!q.exec()) {
qWarningNN << LOGSEC_DB qWarningNN << LOGSEC_DB << "Removing of leftover messages failed: '" << q.lastError().text() << "'.";
<< "Removing of leftover messages failed: '"
<< q.lastError().text()
<< "'.";
return false; return false;
} }
else { else {
@ -1733,10 +1737,11 @@ bool DatabaseQueries::purgeLeftoverLabelAssignments(const QSqlDatabase& db, int
if (account_id <= 0) { if (account_id <= 0) {
succ = q.exec(QSL("DELETE FROM LabelsInMessages " succ = q.exec(QSL("DELETE FROM LabelsInMessages "
"WHERE NOT EXISTS (SELECT * FROM Messages WHERE Messages.account_id = LabelsInMessages.account_id AND Messages.custom_id = LabelsInMessages.message);")) "WHERE NOT EXISTS (SELECT * FROM Messages WHERE Messages.account_id = "
&& "LabelsInMessages.account_id AND Messages.custom_id = LabelsInMessages.message);")) &&
q.exec(QSL("DELETE FROM LabelsInMessages " q.exec(QSL("DELETE FROM LabelsInMessages "
"WHERE NOT EXISTS (SELECT * FROM Labels WHERE Labels.account_id = LabelsInMessages.account_id AND Labels.custom_id = LabelsInMessages.label);")); "WHERE NOT EXISTS (SELECT * FROM Labels WHERE Labels.account_id = LabelsInMessages.account_id "
"AND Labels.custom_id = LabelsInMessages.label);"));
} }
else { else {
q.prepare(QSL("DELETE FROM LabelsInMessages " q.prepare(QSL("DELETE FROM LabelsInMessages "
@ -1748,10 +1753,7 @@ bool DatabaseQueries::purgeLeftoverLabelAssignments(const QSqlDatabase& db, int
} }
if (!succ) { if (!succ) {
qWarningNN << LOGSEC_DB qWarningNN << LOGSEC_DB << "Removing of leftover label assignments failed: '" << q.lastError().text() << "'.";
<< "Removing of leftover label assignments failed: '"
<< q.lastError().text()
<< "'.";
} }
return succ; return succ;
@ -1827,7 +1829,9 @@ QStringList DatabaseQueries::customIdsOfMessagesFromLabel(const QSqlDatabase& db
" is_deleted = 0 AND " " is_deleted = 0 AND "
" is_pdeleted = 0 AND " " is_pdeleted = 0 AND "
" account_id = :account_id AND " " account_id = :account_id AND "
" EXISTS (SELECT * FROM LabelsInMessages WHERE LabelsInMessages.label = :label AND Messages.account_id = LabelsInMessages.account_id AND Messages.custom_id = LabelsInMessages.message);")); " EXISTS (SELECT * FROM LabelsInMessages WHERE LabelsInMessages.label = :label AND "
"Messages.account_id = LabelsInMessages.account_id AND Messages.custom_id = "
"LabelsInMessages.message);"));
q.bindValue(QSL(":account_id"), label->getParentServiceRoot()->accountId()); q.bindValue(QSL(":account_id"), label->getParentServiceRoot()->accountId());
q.bindValue(QSL(":label"), label->customId()); q.bindValue(QSL(":label"), label->customId());
@ -1896,7 +1900,8 @@ QStringList DatabaseQueries::customIdsOfMessagesFromBin(const QSqlDatabase& db,
QStringList ids; QStringList ids;
q.setForwardOnly(true); q.setForwardOnly(true);
q.prepare(QSL("SELECT custom_id FROM Messages WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;")); q.prepare(QSL("SELECT custom_id FROM Messages WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = "
":account_id;"));
q.bindValue(QSL(":account_id"), account_id); q.bindValue(QSL(":account_id"), account_id);
if (ok != nullptr) { if (ok != nullptr) {
@ -1913,12 +1918,16 @@ QStringList DatabaseQueries::customIdsOfMessagesFromBin(const QSqlDatabase& db,
return ids; return ids;
} }
QStringList DatabaseQueries::customIdsOfMessagesFromFeed(const QSqlDatabase& db, const QString& feed_custom_id, int account_id, bool* ok) { QStringList DatabaseQueries::customIdsOfMessagesFromFeed(const QSqlDatabase& db,
const QString& feed_custom_id,
int account_id,
bool* ok) {
QSqlQuery q(db); QSqlQuery q(db);
QStringList ids; QStringList ids;
q.setForwardOnly(true); q.setForwardOnly(true);
q.prepare(QSL("SELECT custom_id FROM Messages WHERE is_deleted = 0 AND is_pdeleted = 0 AND feed = :feed AND account_id = :account_id;")); q.prepare(QSL("SELECT custom_id FROM Messages WHERE is_deleted = 0 AND is_pdeleted = 0 AND feed = :feed AND "
"account_id = :account_id;"));
q.bindValue(QSL(":account_id"), account_id); q.bindValue(QSL(":account_id"), account_id);
q.bindValue(QSL(":feed"), feed_custom_id); q.bindValue(QSL(":feed"), feed_custom_id);
@ -1936,12 +1945,14 @@ QStringList DatabaseQueries::customIdsOfMessagesFromFeed(const QSqlDatabase& db,
return ids; return ids;
} }
void DatabaseQueries::createOverwriteCategory(const QSqlDatabase& db, Category* category, int account_id, int new_parent_id) { void DatabaseQueries::createOverwriteCategory(const QSqlDatabase& db,
Category* category,
int account_id,
int new_parent_id) {
QSqlQuery q(db); QSqlQuery q(db);
int next_sort_order; int next_sort_order;
if (category->id() <= 0 || if (category->id() <= 0 || (category->parent() != nullptr && category->parent()->id() != new_parent_id)) {
(category->parent() != nullptr && category->parent()->id() != new_parent_id)) {
q.prepare(QSL("SELECT MAX(ordr) FROM Categories WHERE account_id = :account_id AND parent_id = :parent_id;")); q.prepare(QSL("SELECT MAX(ordr) FROM Categories WHERE account_id = :account_id AND parent_id = :parent_id;"));
q.bindValue(QSL(":account_id"), account_id); q.bindValue(QSL(":account_id"), account_id);
q.bindValue(QSL(":parent_id"), new_parent_id); q.bindValue(QSL(":parent_id"), new_parent_id);
@ -1961,7 +1972,8 @@ void DatabaseQueries::createOverwriteCategory(const QSqlDatabase& db, Category*
// We need to insert category first. // We need to insert category first.
q.prepare(QSL("INSERT INTO " q.prepare(QSL("INSERT INTO "
"Categories (parent_id, ordr, title, date_created, account_id) " "Categories (parent_id, ordr, title, date_created, account_id) "
"VALUES (0, 0, 'new', 0, %1);").arg(QString::number(account_id))); "VALUES (0, 0, 'new', 0, %1);")
.arg(QString::number(account_id)));
if (!q.exec()) { if (!q.exec()) {
throw ApplicationException(q.lastError().text()); throw ApplicationException(q.lastError().text());
@ -1984,7 +1996,8 @@ void DatabaseQueries::createOverwriteCategory(const QSqlDatabase& db, Category*
category->setSortOrder(next_sort_order); category->setSortOrder(next_sort_order);
q.prepare("UPDATE Categories " q.prepare("UPDATE Categories "
"SET parent_id = :parent_id, ordr = :ordr, title = :title, description = :description, date_created = :date_created, " "SET parent_id = :parent_id, ordr = :ordr, title = :title, description = :description, date_created = "
":date_created, "
" icon = :icon, account_id = :account_id, custom_id = :custom_id " " icon = :icon, account_id = :account_id, custom_id = :custom_id "
"WHERE id = :id;"); "WHERE id = :id;");
q.bindValue(QSL(":parent_id"), new_parent_id); q.bindValue(QSL(":parent_id"), new_parent_id);
@ -2006,8 +2019,7 @@ void DatabaseQueries::createOverwriteFeed(const QSqlDatabase& db, Feed* feed, in
QSqlQuery q(db); QSqlQuery q(db);
int next_sort_order; int next_sort_order;
if (feed->id() <= 0 || if (feed->id() <= 0 || (feed->parent() != nullptr && feed->parent()->id() != new_parent_id)) {
(feed->parent() != nullptr && feed->parent()->id() != new_parent_id)) {
// We either insert completely new feed or we move feed // We either insert completely new feed or we move feed
// to new parent. Get new viable sort order. // to new parent. Get new viable sort order.
q.prepare(QSL("SELECT MAX(ordr) FROM Feeds WHERE account_id = :account_id AND category = :category;")); q.prepare(QSL("SELECT MAX(ordr) FROM Feeds WHERE account_id = :account_id AND category = :category;"));
@ -2029,7 +2041,8 @@ void DatabaseQueries::createOverwriteFeed(const QSqlDatabase& db, Feed* feed, in
// We need to insert feed first. // We need to insert feed first.
q.prepare(QSL("INSERT INTO " q.prepare(QSL("INSERT INTO "
"Feeds (title, ordr, date_created, category, update_type, update_interval, account_id, custom_id) " "Feeds (title, ordr, date_created, category, update_type, update_interval, account_id, custom_id) "
"VALUES ('new', 0, 0, 0, 0, 1, %1, 'new');").arg(QString::number(account_id))); "VALUES ('new', 0, 0, 0, 0, 1, %1, 'new');")
.arg(QString::number(account_id)));
if (!q.exec()) { if (!q.exec()) {
throw ApplicationException(q.lastError().text()); throw ApplicationException(q.lastError().text());
@ -2160,8 +2173,7 @@ bool DatabaseQueries::deleteFeed(const QSqlDatabase& db, Feed* feed, int account
q.bindValue(QSL(":feed"), feed->customId()); q.bindValue(QSL(":feed"), feed->customId());
q.bindValue(QSL(":account_id"), account_id); q.bindValue(QSL(":account_id"), account_id);
return q.exec() && return q.exec() && purgeLeftoverMessageFilterAssignments(db, account_id) &&
purgeLeftoverMessageFilterAssignments(db, account_id) &&
purgeLeftoverLabelAssignments(db, account_id); purgeLeftoverLabelAssignments(db, account_id);
} }
@ -2177,20 +2189,26 @@ bool DatabaseQueries::deleteCategory(const QSqlDatabase& db, Category* category)
return q.exec(); return q.exec();
} }
void DatabaseQueries::moveItem(RootItem* item, bool move_top, bool move_bottom, int move_index, const QSqlDatabase& db) { void DatabaseQueries::moveItem(RootItem* item,
if (item->kind() != RootItem::Kind::Feed && bool move_top,
item->kind() != RootItem::Kind::Category && bool move_bottom,
int move_index,
const QSqlDatabase& db) {
if (item->kind() != RootItem::Kind::Feed && item->kind() != RootItem::Kind::Category &&
item->kind() != RootItem::Kind::ServiceRoot) { item->kind() != RootItem::Kind::ServiceRoot) {
return; return;
} }
auto neighbors = item->parent()->childItems(); auto neighbors = item->parent()->childItems();
int max_sort_order = boolinq::from(neighbors).select([=](RootItem* it) { int max_sort_order = boolinq::from(neighbors)
.select([=](RootItem* it) {
return it->kind() == item->kind() ? it->sortOrder() : 0; return it->kind() == item->kind() ? it->sortOrder() : 0;
}).max(); })
.max();
if ((!move_top && !move_bottom && item->sortOrder() == move_index) || /* Item is already sorted OK. */ if ((!move_top && !move_bottom && item->sortOrder() == move_index) || /* Item is already sorted OK. */
(!move_top && !move_bottom && move_index < 0 ) || /* Order cannot be smaller than 0 if we do not move to begin/end. */ (!move_top && !move_bottom &&
move_index < 0) || /* Order cannot be smaller than 0 if we do not move to begin/end. */
(!move_top && !move_bottom && move_index > max_sort_order) || /* Cannot move past biggest sort order. */ (!move_top && !move_bottom && move_index > max_sort_order) || /* Cannot move past biggest sort order. */
(move_top && item->sortOrder() == 0) || /* Item is already on top. */ (move_top && item->sortOrder() == 0) || /* Item is already on top. */
(move_bottom && item->sortOrder() == max_sort_order) || /* Item is already on bottom. */ (move_bottom && item->sortOrder() == max_sort_order) || /* Item is already on bottom. */
@ -2261,7 +2279,8 @@ void DatabaseQueries::moveItem(RootItem* item, bool move_top, bool move_bottom,
} }
q.prepare(QSL("UPDATE %1 SET ordr = :ordr WHERE id = :id;").arg(table_name)); q.prepare(QSL("UPDATE %1 SET ordr = :ordr WHERE id = :id;").arg(table_name));
q.bindValue(QSL(":id"), item->kind() == RootItem::Kind::ServiceRoot ? item->toServiceRoot()->accountId() : item->id()); q.bindValue(QSL(":id"),
item->kind() == RootItem::Kind::ServiceRoot ? item->toServiceRoot()->accountId() : item->id());
q.bindValue(QSL(":ordr"), move_index); q.bindValue(QSL(":ordr"), move_index);
if (!q.exec()) { if (!q.exec()) {
@ -2270,16 +2289,20 @@ void DatabaseQueries::moveItem(RootItem* item, bool move_top, bool move_bottom,
// Fix live sort orders. // Fix live sort orders.
if (item->sortOrder() > move_index) { if (item->sortOrder() > move_index) {
boolinq::from(neighbors).where([=](RootItem* it) { boolinq::from(neighbors)
.where([=](RootItem* it) {
return it->kind() == item->kind() && it->sortOrder() < move_high && it->sortOrder() >= move_low; return it->kind() == item->kind() && it->sortOrder() < move_high && it->sortOrder() >= move_low;
}).for_each([](RootItem* it) { })
.for_each([](RootItem* it) {
it->setSortOrder(it->sortOrder() + 1); it->setSortOrder(it->sortOrder() + 1);
}); });
} }
else { else {
boolinq::from(neighbors).where([=](RootItem* it) { boolinq::from(neighbors)
.where([=](RootItem* it) {
return it->kind() == item->kind() && it->sortOrder() > move_low && it->sortOrder() <= move_high; return it->kind() == item->kind() && it->sortOrder() > move_low && it->sortOrder() <= move_high;
}).for_each([](RootItem* it) { })
.for_each([](RootItem* it) {
it->setSortOrder(it->sortOrder() - 1); it->setSortOrder(it->sortOrder() - 1);
}); });
} }
@ -2287,10 +2310,10 @@ void DatabaseQueries::moveItem(RootItem* item, bool move_top, bool move_bottom,
item->setSortOrder(move_index); item->setSortOrder(move_index);
} }
MessageFilter* DatabaseQueries::addMessageFilter(const QSqlDatabase& db, const QString& title, MessageFilter* DatabaseQueries::addMessageFilter(const QSqlDatabase& db, const QString& title, const QString& script) {
const QString& script) {
if (!db.driver()->hasFeature(QSqlDriver::DriverFeature::LastInsertId)) { if (!db.driver()->hasFeature(QSqlDriver::DriverFeature::LastInsertId)) {
throw ApplicationException(QObject::tr("Cannot insert article filter, because current database cannot return last inserted row ID.")); throw ApplicationException(QObject::tr("Cannot insert article filter, because current database cannot return last "
"inserted row ID."));
} }
QSqlQuery q(db); QSqlQuery q(db);
@ -2414,8 +2437,11 @@ QMultiMap<QString, int> DatabaseQueries::messageFiltersInFeeds(const QSqlDatabas
return filters_in_feeds; return filters_in_feeds;
} }
void DatabaseQueries::assignMessageFilterToFeed(const QSqlDatabase& db, const QString& feed_custom_id, void DatabaseQueries::assignMessageFilterToFeed(const QSqlDatabase& db,
int filter_id, int account_id, bool* ok) { const QString& feed_custom_id,
int filter_id,
int account_id,
bool* ok) {
QSqlQuery q(db); QSqlQuery q(db);
q.prepare(QSL("INSERT INTO MessageFiltersInFeeds (filter, feed_custom_id, account_id) " q.prepare(QSL("INSERT INTO MessageFiltersInFeeds (filter, feed_custom_id, account_id) "
@ -2460,8 +2486,11 @@ void DatabaseQueries::updateMessageFilter(const QSqlDatabase& db, MessageFilter*
} }
} }
void DatabaseQueries::removeMessageFilterFromFeed(const QSqlDatabase& db, const QString& feed_custom_id, void DatabaseQueries::removeMessageFilterFromFeed(const QSqlDatabase& db,
int filter_id, int account_id, bool* ok) { const QString& feed_custom_id,
int filter_id,
int account_id,
bool* ok) {
QSqlQuery q(db); QSqlQuery q(db);
q.prepare(QSL("DELETE FROM MessageFiltersInFeeds " q.prepare(QSL("DELETE FROM MessageFiltersInFeeds "
@ -2506,16 +2535,14 @@ QStringList DatabaseQueries::getAllGmailRecipients(const QSqlDatabase& db, int a
return rec; return rec;
} }
bool DatabaseQueries::storeNewOauthTokens(const QSqlDatabase& db, bool DatabaseQueries::storeNewOauthTokens(const QSqlDatabase& db, const QString& refresh_token, int account_id) {
const QString& refresh_token, int account_id) {
QSqlQuery query(db); QSqlQuery query(db);
query.prepare(QSL("SELECT custom_data FROM Accounts WHERE id = :id;")); query.prepare(QSL("SELECT custom_data FROM Accounts WHERE id = :id;"));
query.bindValue(QSL(":id"), account_id); query.bindValue(QSL(":id"), account_id);
if (!query.exec() || !query.next()) { if (!query.exec() || !query.next()) {
qWarningNN << LOGSEC_OAUTH qWarningNN << LOGSEC_OAUTH << "Cannot fetch custom data column for storing of OAuth tokens, because of error:"
<< "Cannot fetch custom data column for storing of OAuth tokens, because of error:"
<< QUOTE_W_SPACE_DOT(query.lastError().text()); << QUOTE_W_SPACE_DOT(query.lastError().text());
return false; return false;
} }
@ -2531,8 +2558,7 @@ bool DatabaseQueries::storeNewOauthTokens(const QSqlDatabase& db,
if (!query.exec()) { if (!query.exec()) {
qWarningNN << LOGSEC_OAUTH qWarningNN << LOGSEC_OAUTH
<< "Cannot store OAuth tokens, because of error:" << "Cannot store OAuth tokens, because of error:" << QUOTE_W_SPACE_DOT(query.lastError().text());
<< QUOTE_W_SPACE_DOT(query.lastError().text());
return false; return false;
} }
else { else {