workin on it...

This commit is contained in:
Martin Rotter 2023-06-01 09:27:32 +02:00
parent ee68d07db2
commit 58cf78b7f0
14 changed files with 140 additions and 185 deletions

View File

@ -69,6 +69,7 @@ CREATE TABLE Messages (
account_id INTEGER NOT NULL,
custom_id TEXT,
custom_hash TEXT,
Labels TEXT NOT NULL DEFAULT "." /* Holds list of assigned labels. */
FOREIGN KEY (account_id) REFERENCES Accounts (id) ON DELETE CASCADE
);

View File

@ -0,0 +1,8 @@
USE ##;
-- !
SET FOREIGN_KEY_CHECKS = 0;
-- !
!! db_update_sqlite_4_5.sql
-- !
SET FOREIGN_KEY_CHECKS = 1;
-- !

View File

@ -0,0 +1,4 @@
/* Copy label IDs to Messages table. */
/* Remove LabelsInMessages table. */

View File

@ -117,7 +117,7 @@ void Message::sanitize(const Feed* feed, bool fix_future_datetimes) {
}
Message Message::fromSqlRecord(const QSqlRecord& record, bool* result) {
if (record.count() != MSG_DB_LABELS + 1) {
if (record.count() != MSG_DB_LABELS_IDS + 1) {
if (result != nullptr) {
*result = false;
}

View File

@ -247,7 +247,8 @@ void MessagesModel::setupHeaderData() {
/*: Tooltip for custom hash string of message.*/ tr("Custom hash") <<
/*: Tooltip for name of feed for message.*/ tr("Feed") <<
/*: Tooltip for indication of presence of enclosures.*/ tr("Has enclosures") <<
/*: Tooltip for indication of labels of message.*/ tr("Assigned labels");
/*: Tooltip for indication of labels of message.*/ tr("Assigned labels") <<
/*: Tooltip for indication of label IDs of message.*/ tr("Assigned label IDs");
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?")
@ -256,7 +257,8 @@ void MessagesModel::setupHeaderData() {
<< 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("Custom hash of the article.") << tr("Name of feed of the article.")
<< tr("Indication of enclosures presence within the article.") << tr("Labels assigned to the article.");
<< tr("Indication of enclosures presence within the article.") << tr("Labels assigned to the article.")
<< tr("Label IDs assigned to the article.");
}
Qt::ItemFlags MessagesModel::flags(const QModelIndex& index) const {

View File

@ -34,6 +34,7 @@ MessagesModelSqlLayer::MessagesModelSqlLayer()
m_orderByNames[MSG_DB_FEED_TITLE_INDEX] = QSL("Feeds.title");
m_orderByNames[MSG_DB_HAS_ENCLOSURES] = QSL("has_enclosures");
m_orderByNames[MSG_DB_LABELS] = QSL("msg_labels");
m_orderByNames[MSG_DB_LABELS_IDS] = QSL("Messages.labels");
m_numericColumns << MSG_DB_ID_INDEX << MSG_DB_READ_INDEX << MSG_DB_DELETED_INDEX << MSG_DB_PDELETED_INDEX
<< MSG_DB_IMPORTANT_INDEX << MSG_DB_ACCOUNT_ID_INDEX << MSG_DB_DCREATED_INDEX << MSG_DB_SCORE_INDEX;

View File

@ -60,8 +60,6 @@ void DatabaseCleaner::purgeDatabaseData(CleanerOrders which_data) {
emit purgeProgress(progress, tr("Starred articles purged..."));
}
result &= DatabaseQueries::purgeLeftoverLabelAssignments(database);
if (which_data.m_shrinkDatabase) {
progress += difference;
emit purgeProgress(progress, tr("Shrinking database file..."));

View File

@ -37,10 +37,17 @@ QMap<int, QString> DatabaseQueries::messageTableAttributes(bool only_msg_table)
"THEN 'true' "
"ELSE 'false' "
"END AS has_enclosures");
field_names[MSG_DB_LABELS] = QSL("1 as msg_labels");
field_names[MSG_DB_LABELS_IDS] = QSL("Messages.labels");
// TODO: zpomaluje zobrazení seznamu zpráv
/*
field_names[MSG_DB_LABELS] =
QSL("(SELECT GROUP_CONCAT(Labels.name) FROM Labels WHERE Labels.custom_id IN (SELECT "
"LabelsInMessages.label FROM LabelsInMessages WHERE LabelsInMessages.account_id = "
"Messages.account_id AND LabelsInMessages.message = Messages.custom_id)) as msg_labels");
*/
return field_names;
}
@ -68,10 +75,14 @@ QVariantHash DatabaseQueries::deserializeCustomData(const QString& data) {
bool DatabaseQueries::isLabelAssignedToMessage(const QSqlDatabase& db, Label* label, const Message& msg) {
QSqlQuery q(db);
// TODO: ověřit
q.setForwardOnly(true);
q.prepare(QSL("SELECT COUNT(*) FROM LabelsInMessages "
"WHERE label = :label AND message = :message AND account_id = :account_id;"));
q.bindValue(QSL(":label"), label->customId());
q.prepare(QSL("SELECT COUNT(*) FROM Messages "
"WHERE "
"Messages.labels LIKE :label AND "
"Messages.custom_id = :message AND "
"account_id = :account_id;"));
q.bindValue(QSL(":label"), QSL("%.%1.%").arg(label->customId()));
q.bindValue(QSL(":message"), msg.m_customId);
q.bindValue(QSL(":account_id"), label->getParentServiceRoot()->accountId());
@ -83,10 +94,12 @@ bool DatabaseQueries::isLabelAssignedToMessage(const QSqlDatabase& db, Label* la
bool DatabaseQueries::deassignLabelFromMessage(const QSqlDatabase& db, Label* label, const Message& msg) {
QSqlQuery q(db);
// TODO: ověřit.
q.setForwardOnly(true);
q.prepare(QSL("DELETE FROM LabelsInMessages "
"WHERE label = :label AND message = :message AND account_id = :account_id;"));
q.bindValue(QSL(":label"), label->customId());
q.prepare(QSL("UPDATE Messages "
"SET Messages.labels = REPLACE(Messages.labels, :label, \".\") "
"WHERE Messages.custom_id = :message AND account_id = :account_id;"));
q.bindValue(QSL(":label"), QSL(".%1.").arg(label->customId()));
q.bindValue(QSL(":message"), msg.m_customId.isEmpty() ? QString::number(msg.m_id) : msg.m_customId);
q.bindValue(QSL(":account_id"), label->getParentServiceRoot()->accountId());
@ -94,57 +107,44 @@ bool DatabaseQueries::deassignLabelFromMessage(const QSqlDatabase& db, Label* la
}
bool DatabaseQueries::assignLabelToMessage(const QSqlDatabase& db, Label* label, const Message& msg) {
deassignLabelFromMessage(db, label, msg);
QSqlQuery q(db);
// TODO: ověřit.
q.setForwardOnly(true);
q.prepare(QSL("DELETE FROM LabelsInMessages "
"WHERE label = :label AND message = :message AND account_id = :account_id;"));
q.bindValue(QSL(":label"), label->customId());
q.prepare(QSL("UPDATE Messages "
"SET Messages.labels = Messages.labels || :label "
"WHERE Messages.custom_id = :message AND account_id = :account_id;"));
q.bindValue(QSL(":label"), QSL("%1.").arg(label->customId()));
q.bindValue(QSL(":message"), msg.m_customId.isEmpty() ? QString::number(msg.m_id) : msg.m_customId);
q.bindValue(QSL(":account_id"), label->getParentServiceRoot()->accountId());
auto succ = q.exec();
if (succ) {
q.prepare(QSL("INSERT INTO LabelsInMessages (label, message, account_id) "
"VALUES (:label, :message, :account_id);"));
q.bindValue(QSL(":label"), label->customId());
q.bindValue(QSL(":message"), msg.m_customId.isEmpty() ? QString::number(msg.m_id) : msg.m_customId);
q.bindValue(QSL(":account_id"), label->getParentServiceRoot()->accountId());
succ = q.exec();
}
return succ;
return q.exec();
}
bool DatabaseQueries::setLabelsForMessage(const QSqlDatabase& db, const QList<Label*>& labels, const Message& msg) {
QSqlQuery q(db);
auto std_lbls = boolinq::from(labels)
.select([](Label* lbl) {
return lbl->customId();
})
.toStdList();
QStringList lbls = FROM_STD_LIST(QStringList, std_lbls);
QString lblss = QSL(".") + lbls.join('.') + QSL(".");
// TODO: ověřit.
q.setForwardOnly(true);
q.prepare(QSL("DELETE FROM LabelsInMessages WHERE message = :message AND account_id = :account_id"));
q.bindValue(QSL(":account_id"), msg.m_accountId);
q.prepare(QSL("UPDATE Messages "
"SET Messages.labels = :labels "
"WHERE Messages.custom_id = :message AND account_id = :account_id;"));
q.bindValue(QSL(":labels"), lblss);
q.bindValue(QSL(":message"), msg.m_customId.isEmpty() ? QString::number(msg.m_id) : msg.m_customId);
q.bindValue(QSL(":account_id"), msg.m_accountId);
auto succ = q.exec();
if (!succ) {
return false;
}
q.prepare(QSL("INSERT INTO LabelsInMessages (message, label, account_id) VALUES (:message, :label, :account_id);"));
for (const Label* label : labels) {
q.bindValue(QSL(":account_id"), msg.m_accountId);
q.bindValue(QSL(":message"), msg.m_customId.isEmpty() ? QString::number(msg.m_id) : msg.m_customId);
q.bindValue(QSL(":label"), label->customId());
if (!q.exec()) {
return false;
}
}
return true;
return q.exec();
}
QList<Label*> DatabaseQueries::getLabelsForAccount(const QSqlDatabase& db, int account_id) {
@ -171,21 +171,28 @@ QList<Label*> DatabaseQueries::getLabelsForAccount(const QSqlDatabase& db, int a
QList<Label*> DatabaseQueries::getLabelsForMessage(const QSqlDatabase& db,
const Message& msg,
const QList<Label*> installed_labels) {
const QList<Label*>& installed_labels) {
QList<Label*> labels;
QSqlQuery q(db);
// TODO: ověřit
q.setForwardOnly(true);
q.prepare(QSL("SELECT DISTINCT label FROM LabelsInMessages WHERE message = :message AND account_id = :account_id;"));
q.prepare(QSL("SELECT labels FROM Messages WHERE custom_id = :message AND account_id = :account_id;"));
q.bindValue(QSL(":account_id"), msg.m_accountId);
q.bindValue(QSL(":message"), msg.m_customId.isEmpty() ? QString::number(msg.m_id) : msg.m_customId);
if (q.exec()) {
if (q.exec() && q.next()) {
auto label_ids = q.value(0).toString().split('.',
#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
Qt::SplitBehaviorFlags::SkipEmptyParts);
#else
QString::SplitBehavior::SkipEmptyParts);
#endif
auto iter = boolinq::from(installed_labels);
while (q.next()) {
auto lbl_id = q.value(0).toString();
for (const QString& lbl_id : label_ids) {
Label* candidate_label = iter.firstOrDefault([&](const Label* lbl) {
return lbl->customId() == lbl_id;
});
@ -223,9 +230,12 @@ bool DatabaseQueries::deleteLabel(const QSqlDatabase& db, Label* label) {
q.bindValue(QSL(":id"), label->id());
q.bindValue(QSL(":account_id"), label->getParentServiceRoot()->accountId());
// TODO: ověřit
if (q.exec()) {
q.prepare(QSL("DELETE FROM LabelsInMessages WHERE label = :custom_id AND account_id = :account_id;"));
q.bindValue(QSL(":custom_id"), label->customId());
q.prepare(QSL("UPDATE Messages "
"SET Messages.labels = REPLACE(Messages.labels, :label, \".\") "
"WHERE account_id = :account_id;"));
q.bindValue(QSL(":label"), QSL(".%1.").arg(label->customId()));
q.bindValue(QSL(":account_id"), label->getParentServiceRoot()->accountId());
return q.exec();
@ -267,18 +277,17 @@ bool DatabaseQueries::createLabel(const QSqlDatabase& db, Label* label, int acco
bool DatabaseQueries::markLabelledMessagesReadUnread(const QSqlDatabase& db, Label* label, RootItem::ReadStatus read) {
QSqlQuery q(db);
// TODO: ověřit
q.setForwardOnly(true);
q.prepare(QSL("UPDATE Messages SET is_read = :read "
"WHERE "
" is_deleted = 0 AND "
" is_pdeleted = 0 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);"));
" labels LIKE :label;"));
q.bindValue(QSL(":read"), read == RootItem::ReadStatus::Read ? 1 : 0);
q.bindValue(QSL(":account_id"), label->getParentServiceRoot()->accountId());
q.bindValue(QSL(":label"), label->customId());
q.bindValue(QSL(":label"), QSL("%.%1.%").arg(label->customId()));
return q.exec();
}
@ -619,27 +628,27 @@ int DatabaseQueries::getMessageCountsForLabel(const QSqlDatabase& db,
q.setForwardOnly(true);
// TODO: ověřit
if (only_total_counts) {
q.prepare(QSL("SELECT COUNT(*) FROM Messages "
"INNER JOIN LabelsInMessages "
"ON "
" Messages.is_pdeleted = 0 AND Messages.is_deleted = 0 AND "
" LabelsInMessages.account_id = :account_id AND LabelsInMessages.account_id = Messages.account_id "
"AND "
" LabelsInMessages.label = :label AND LabelsInMessages.message = Messages.custom_id;"));
"WHERE "
" is_deleted = 0 AND "
" is_pdeleted = 0 AND "
" account_id = :account_id AND "
" labels LIKE :label;"));
}
else {
q.prepare(QSL("SELECT COUNT(*) FROM Messages "
"INNER JOIN LabelsInMessages "
"ON "
" 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.label = :label AND LabelsInMessages.message = Messages.custom_id;"));
"WHERE "
" is_deleted = 0 AND "
" is_pdeleted = 0 AND "
" is_read = 0 AND "
" account_id = :account_id AND "
" labels LIKE :label;"));
}
q.bindValue(QSL(":account_id"), account_id);
q.bindValue(QSL(":label"), label->customId());
q.bindValue(QSL(":label"), QSL("%.%1.%").arg(label->customId()));
if (q.exec() && q.next()) {
if (ok != nullptr) {
@ -757,20 +766,20 @@ QList<Message> DatabaseQueries::getUndeletedMessagesWithLabel(const QSqlDatabase
QList<Message> messages;
QSqlQuery q(db);
// TODO: ověřit
q.prepare(QSL("SELECT %1 "
"FROM Messages "
"INNER JOIN Feeds "
"ON Messages.feed = Feeds.custom_id AND Messages.account_id = :account_id AND Messages.account_id = "
"Feeds.account_id "
"INNER JOIN LabelsInMessages "
"ON "
" Messages.is_pdeleted = 0 AND Messages.is_deleted = 0 AND "
" LabelsInMessages.account_id = :account_id AND LabelsInMessages.account_id = Messages.account_id AND "
" LabelsInMessages.label = :label AND "
" LabelsInMessages.message = Messages.custom_id;")
"WHERE "
" is_deleted = 0 AND "
" is_pdeleted = 0 AND "
" account_id = :account_id AND "
" labels LIKE :label;")
.arg(messageTableAttributes(true).values().join(QSL(", "))));
q.bindValue(QSL(":account_id"), label->getParentServiceRoot()->accountId());
q.bindValue(QSL(":label"), label->customId());
q.bindValue(QSL(":label"), QSL("%.%1.%").arg(label->customId()));
if (q.exec()) {
while (q.next()) {
@ -799,14 +808,16 @@ QList<Message> DatabaseQueries::getUndeletedLabelledMessages(const QSqlDatabase&
QList<Message> messages;
QSqlQuery q(db);
// TODO: ověřit
q.prepare(QSL("SELECT %1 "
"FROM Messages "
"LEFT JOIN Feeds "
"ON Messages.feed = Feeds.custom_id AND Messages.account_id = Feeds.account_id "
"WHERE Messages.is_deleted = 0 AND Messages.is_pdeleted = 0 AND Messages.account_id = :account_id AND "
" (SELECT COUNT(*) FROM LabelsInMessages "
" WHERE account_id = :account_id AND "
" message = Messages.custom_id) > 0;")
"WHERE "
" is_deleted = 0 AND "
" is_pdeleted = 0 AND "
" account_id = :account_id AND "
" LENGTH(labels) > 2;")
.arg(messageTableAttributes(true).values().join(QSL(", "))));
q.bindValue(QSL(":account_id"), account_id);
@ -1054,12 +1065,14 @@ QHash<QString, QStringList> DatabaseQueries::bagsOfMessages(const QSqlDatabase&
q.setForwardOnly(true);
q.prepare(QSL("SELECT message "
"FROM LabelsInMessages "
"WHERE label = :label AND account_id = :account_id;"));
// TODO: ověřit
q.prepare(QSL("SELECT custom_id FROM Messages "
"WHERE "
" account_id = :account_id AND "
" labels LIKE :label;"));
for (const Label* lbl : labels) {
q.bindValue(QSL(":label"), lbl->customId());
q.bindValue(QSL(":label"), QSL("%.%1.%").arg(lbl->customId()));
q.bindValue(QSL(":account_id"), lbl->getParentServiceRoot()->accountId());
q.exec();
@ -1521,7 +1534,6 @@ bool DatabaseQueries::deleteAccount(const QSqlDatabase& db, ServiceRoot* account
QStringList queries;
queries << QSL("DELETE FROM MessageFiltersInFeeds WHERE account_id = :account_id;")
<< QSL("DELETE FROM LabelsInMessages WHERE account_id = :account_id;")
<< QSL("DELETE FROM Messages WHERE account_id = :account_id;")
<< QSL("DELETE FROM Feeds WHERE account_id = :account_id;")
<< QSL("DELETE FROM Categories WHERE account_id = :account_id;")
@ -1568,12 +1580,6 @@ bool DatabaseQueries::deleteAccountData(const QSqlDatabase& db,
q.bindValue(QSL(":account_id"), account_id);
result &= q.exec();
if (delete_messages_too) {
q.prepare(QSL("DELETE FROM LabelsInMessages WHERE account_id = :account_id;"));
q.bindValue(QSL(":account_id"), account_id);
result &= q.exec();
}
if (delete_labels_too) {
q.prepare(QSL("DELETE FROM Labels WHERE account_id = :account_id;"));
q.bindValue(QSL(":account_id"), account_id);
@ -1591,31 +1597,27 @@ bool DatabaseQueries::cleanLabelledMessages(const QSqlDatabase& db, bool clean_r
if (clean_read_only) {
q.prepare(QSL("UPDATE Messages SET is_deleted = :deleted "
"WHERE "
" is_deleted = 0 AND "
" is_pdeleted = 0 AND "
" is_read = 1 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);"));
" is_deleted = 0 AND "
" is_pdeleted = 0 AND "
" is_read = 1 AND "
" account_id = :account_id AND "
" labels LIKE :label;"));
}
else {
q.prepare(QSL("UPDATE Messages SET is_deleted = :deleted "
"WHERE "
" is_deleted = 0 AND "
" is_pdeleted = 0 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);"));
" is_deleted = 0 AND "
" is_pdeleted = 0 AND "
" account_id = :account_id AND "
" labels LIKE :label;"));
}
q.bindValue(QSL(":deleted"), 1);
q.bindValue(QSL(":account_id"), label->getParentServiceRoot()->accountId());
q.bindValue(QSL(":label"), label->customId());
q.bindValue(QSL(":label"), QSL("%.%1.%").arg(label->customId()));
if (!q.exec()) {
qWarningNN << LOGSEC_DB << "Cleaning of labelled messages failed: '" << q.lastError().text() << "'.";
qWarningNN << LOGSEC_DB << "Cleaning of labelled messages failed:" << QUOTE_W_SPACE_DOT(q.lastError().text());
return false;
}
else {
@ -1735,48 +1737,6 @@ bool DatabaseQueries::purgeLeftoverMessages(const QSqlDatabase& db, int account_
}
}
bool DatabaseQueries::purgeLeftoverLabelAssignments(const QSqlDatabase& db, int account_id) {
QSqlQuery q(db);
bool succ = false;
if (account_id <= 0) {
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);")) &&
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);"));
}
else {
q.prepare(QSL("DELETE FROM LabelsInMessages "
"WHERE account_id = :account_id AND "
" (message NOT IN (SELECT custom_id FROM Messages WHERE account_id = :account_id) OR "
" label NOT IN (SELECT custom_id FROM Labels WHERE account_id = :account_id));"));
q.bindValue(QSL(":account_id"), account_id);
succ = q.exec();
}
if (!succ) {
qWarningNN << LOGSEC_DB << "Removing of leftover label assignments failed: '" << q.lastError().text() << "'.";
}
return succ;
}
bool DatabaseQueries::purgeLabelsAndLabelAssignments(const QSqlDatabase& db, int account_id) {
QSqlQuery q(db);
q.prepare(QSL("DELETE FROM LabelsInMessages WHERE account_id = :account_id;"));
q.bindValue(QSL(":account_id"), account_id);
auto succ = q.exec();
q.prepare(QSL("DELETE FROM Labels WHERE account_id = :account_id;"));
q.bindValue(QSL(":account_id"), account_id);
succ &= q.exec();
return succ;
}
void DatabaseQueries::storeAccountTree(const QSqlDatabase& db, RootItem* tree_root, int account_id) {
// Iterate all children.
auto str = tree_root->getSubTree();
@ -1835,6 +1795,7 @@ QStringList DatabaseQueries::customIdsOfMessagesFromLabel(const QSqlDatabase& db
QSqlQuery q(db);
QStringList ids;
// TODO: ověřit
q.setForwardOnly(true);
q.prepare(QSL("SELECT custom_id FROM Messages "
"WHERE "
@ -1842,11 +1803,9 @@ QStringList DatabaseQueries::customIdsOfMessagesFromLabel(const QSqlDatabase& db
" is_deleted = 0 AND "
" is_pdeleted = 0 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);"));
" labels LIKE :label;"));
q.bindValue(QSL(":account_id"), label->getParentServiceRoot()->accountId());
q.bindValue(QSL(":label"), label->customId());
q.bindValue(QSL(":label"), QSL("%.%1.%").arg(label->customId()));
q.bindValue(QSL(":read"), target_read == RootItem::ReadStatus::Read ? 0 : 1);
if (ok != nullptr) {
@ -2202,8 +2161,7 @@ bool DatabaseQueries::deleteFeed(const QSqlDatabase& db, Feed* feed, int account
q.bindValue(QSL(":feed"), feed->customId());
q.bindValue(QSL(":account_id"), account_id);
return q.exec() && purgeLeftoverMessageFilterAssignments(db, account_id) &&
purgeLeftoverLabelAssignments(db, account_id);
return q.exec() && purgeLeftoverMessageFilterAssignments(db, account_id);
}
bool DatabaseQueries::deleteCategory(const QSqlDatabase& db, Category* category) {

View File

@ -36,7 +36,7 @@ class DatabaseQueries {
static QList<Label*> getLabelsForAccount(const QSqlDatabase& db, int account_id);
static QList<Label*> getLabelsForMessage(const QSqlDatabase& db,
const Message& msg,
const QList<Label*> installed_labels);
const QList<Label*>& installed_labels);
static bool updateLabel(const QSqlDatabase& db, Label* label);
static bool deleteLabel(const QSqlDatabase& db, Label* label);
static bool createLabel(const QSqlDatabase& db, Label* label, int account_id);
@ -67,11 +67,6 @@ class DatabaseQueries {
static bool purgeMessagesFromBin(const QSqlDatabase& db, bool clear_only_read, int account_id);
static bool purgeLeftoverMessages(const QSqlDatabase& db, int account_id);
// Purges message/label assignments where source message or label does not exist.
// If account ID smaller than 1 is passed, then do this for all accounts.
static bool purgeLeftoverLabelAssignments(const QSqlDatabase& db, int account_id = 0);
static bool purgeLabelsAndLabelAssignments(const QSqlDatabase& db, int account_id);
// Counts of unread/all messages.
static QMap<QString, QPair<int, int>> getMessageCountsForCategory(const QSqlDatabase& db,
const QString& custom_id,
@ -125,9 +120,7 @@ class DatabaseQueries {
RootItem::ReadStatus target_read,
int account_id,
bool* ok = nullptr);
static QStringList customIdsOfUnreadMessages(const QSqlDatabase& db,
int account_id,
bool* ok = nullptr);
static QStringList customIdsOfUnreadMessages(const QSqlDatabase& db, int account_id, bool* ok = nullptr);
static QStringList customIdsOfMessagesFromAccount(const QSqlDatabase& db,
RootItem::ReadStatus target_read,
int account_id,

View File

@ -268,6 +268,7 @@
#define MSG_DB_FEED_TITLE_INDEX 16
#define MSG_DB_HAS_ENCLOSURES 17
#define MSG_DB_LABELS 18
#define MSG_DB_LABELS_IDS 19
// Indexes of columns as they are DEFINED IN THE TABLE for CATEGORIES.
#define CAT_DB_ID_INDEX 0

View File

@ -392,7 +392,6 @@ void FormMessageFiltersManager::processCheckedFeeds() {
// Purge the message completely and remove leftovers.
DatabaseQueries::purgeMessage(database, msg->m_id);
DatabaseQueries::purgeLeftoverLabelAssignments(database, msg->m_accountId);
}
else if (result == MessageObject::FilteringAction::Ignore) {
remove_from_list = true;

View File

@ -851,6 +851,10 @@ void MessagesView::adjustColumns() {
hideColumn(MSG_DB_FEED_TITLE_INDEX);
hideColumn(MSG_DB_HAS_ENCLOSURES);
hideColumn(MSG_DB_LABELS);
#if !defined(NDEBUG)
hideColumn(MSG_DB_LABELS_IDS);
#endif
}
}

View File

@ -270,12 +270,6 @@ void ServiceRoot::removeLeftOverMessageFilterAssignments() {
DatabaseQueries::purgeLeftoverMessageFilterAssignments(database, accountId());
}
void ServiceRoot::removeLeftOverMessageLabelAssignments() {
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
DatabaseQueries::purgeLeftoverLabelAssignments(database, accountId());
}
QList<Message> ServiceRoot::undeletedMessages() const {
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
@ -506,7 +500,6 @@ void ServiceRoot::syncIn() {
// so remove left over messages and filter assignments.
removeLeftOverMessages();
removeLeftOverMessageFilterAssignments();
removeLeftOverMessageLabelAssignments();
auto chi = new_tree->childItems();
@ -724,16 +717,14 @@ bool ServiceRoot::loadMessagesForItem(RootItem* item, MessagesModel* model) {
}
else if (item->kind() == RootItem::Kind::Label) {
// Show messages with particular label.
model->setFilter(QSL("Messages.is_deleted = 0 AND Messages.is_pdeleted = 0 AND Messages.account_id = %1 AND "
"(SELECT COUNT(*) FROM LabelsInMessages WHERE account_id = %1 AND message = "
"Messages.custom_id AND label = '%2') > 0")
model->setFilter(QSL("Messages.is_deleted = 0 AND Messages.is_pdeleted = 0 AND "
"Messages.labels LIKE \"%.%2.%\" AND Messages.account_id = %1")
.arg(QString::number(accountId()), item->customId()));
}
else if (item->kind() == RootItem::Kind::Labels) {
// Show messages with any label.
model->setFilter(QSL("Messages.is_deleted = 0 AND Messages.is_pdeleted = 0 AND Messages.account_id = %1 AND "
"(SELECT COUNT(*) FROM LabelsInMessages WHERE account_id = %1 AND message = "
"Messages.custom_id) > 0")
model->setFilter(QSL("Messages.is_deleted = 0 AND Messages.is_pdeleted = 0 AND "
"LENGTH(Messages.labels) > 2 AND Messages.account_id = %1")
.arg(QString::number(accountId())));
}
else if (item->kind() == RootItem::Kind::ServiceRoot) {

View File

@ -264,11 +264,6 @@ class ServiceRoot : public RootItem {
// from another machine and then performs sync-in on this machine.
void removeLeftOverMessageFilterAssignments();
// Removes all labels/message assignments which are
// assigned to non-existing messages or which are
// assigned from non-existing labels.
void removeLeftOverMessageLabelAssignments();
// Takes lists of feeds/categories and assembles them into the tree structure.
void assembleCategories(const Assignment& categories);
void assembleFeeds(const Assignment& feeds);