DB refactoring.

This commit is contained in:
Martin Rotter 2015-12-20 19:02:29 +01:00
parent 1a411c7685
commit dd1d7be8b0
11 changed files with 81 additions and 146 deletions

View File

@ -33,7 +33,6 @@
MessagesModel::MessagesModel(QObject *parent)
: QSqlTableModel(parent, qApp->database()->connection(QSL("MessagesModel"), DatabaseFactory::FromSettings)),
m_messageHighlighter(NoHighlighting), m_customDateFormat(QString()) {
setObjectName(QSL("MessagesModel"));
setupFonts();
setupIcons();
setupHeaderData();

View File

@ -273,7 +273,7 @@ void FeedsView::openSelectedItemsInNewspaperMode() {
if (!messages.isEmpty()) {
emit openMessagesInNewspaperView(messages);
QTimer::singleShot(0, this, SLOT(markSelectedItemRead()));
QTimer::singleShot(150, this, SLOT(markSelectedItemRead()));
}
}

View File

@ -27,7 +27,6 @@
DatabaseCleaner::DatabaseCleaner(QObject *parent) : QObject(parent) {
setObjectName("DatabaseCleaner");
}
DatabaseCleaner::~DatabaseCleaner() {
@ -42,7 +41,7 @@ void DatabaseCleaner::purgeDatabaseData(const CleanerOrders &which_data) {
bool result = true;
int difference = 99 / 8;
int progress = 0;
QSqlDatabase database = qApp->database()->connection(objectName(), DatabaseFactory::FromSettings);
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
if (which_data.m_removeReadMessages) {
progress += difference;

View File

@ -41,8 +41,7 @@ DatabaseFactory::~DatabaseFactory() {
qint64 DatabaseFactory::getDatabaseSize() {
if (m_activeDatabaseDriver == SQLITE || m_activeDatabaseDriver == SQLITE_MEMORY) {
qint64 size = QFileInfo(sqliteDatabaseFilePath()).size();
return size;
return QFileInfo(sqliteDatabaseFilePath()).size();
}
else {
return 0;

View File

@ -60,6 +60,7 @@ class DatabaseFactory : public QObject {
// Destructor.
virtual ~DatabaseFactory();
// Returns size of DB file.
qint64 getDatabaseSize();
// If in-memory is true, then :memory: database is returned

View File

@ -118,35 +118,17 @@ QList<Message> RecycleBin::undeletedMessages() const {
bool RecycleBin::markAsReadUnread(RootItem::ReadStatus status) {
QSqlDatabase db_handle = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
if (!db_handle.transaction()) {
qWarning("Starting transaction for recycle bin read change.");
return false;
}
QSqlQuery query_read_msg(db_handle);
ServiceRoot *parent_root = getParentServiceRoot();
query_read_msg.setForwardOnly(true);
if (!query_read_msg.prepare("UPDATE Messages SET is_read = :read "
"WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;")) {
qWarning("Query preparation failed for recycle bin read change.");
db_handle.rollback();
return false;
}
query_read_msg.prepare("UPDATE Messages SET is_read = :read "
"WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;");
query_read_msg.bindValue(QSL(":read"), status == RootItem::Read ? 1 : 0);
query_read_msg.bindValue(QSL(":account_id"), parent_root->accountId());
if (!query_read_msg.exec()) {
qDebug("Query execution for recycle bin read change failed.");
db_handle.rollback();
}
// Commit changes.
if (db_handle.commit()) {
if (query_read_msg.exec()) {
updateCounts(false);
parent_root->itemChanged(QList<RootItem*>() << this);
@ -154,18 +136,12 @@ bool RecycleBin::markAsReadUnread(RootItem::ReadStatus status) {
return true;
}
else {
return db_handle.rollback();
return false;
}
}
bool RecycleBin::cleanMessages(bool clear_only_read) {
QSqlDatabase db_handle = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
if (!db_handle.transaction()) {
qWarning("Starting transaction for recycle bin emptying.");
return false;
}
ServiceRoot *parent_root = getParentServiceRoot();
QSqlQuery query_empty_bin(db_handle);
@ -181,22 +157,14 @@ bool RecycleBin::cleanMessages(bool clear_only_read) {
query_empty_bin.bindValue(QSL(":account_id"), parent_root->accountId());
if (!query_empty_bin.exec()) {
qWarning("Query execution failed for recycle bin emptying.");
db_handle.rollback();
return false;
}
// Commit changes.
if (db_handle.commit()) {
if (query_empty_bin.exec()) {
updateCounts(true);
parent_root->itemChanged(QList<RootItem*>() << this);
parent_root->requestReloadMessageList(true);
return true;
return true;;
}
else {
return db_handle.rollback();
return false;
}
}
@ -206,12 +174,6 @@ bool RecycleBin::empty() {
bool RecycleBin::restore() {
QSqlDatabase db_handle = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
if (!db_handle.transaction()) {
qWarning("Starting transaction for recycle bin restoring.");
return false;
}
ServiceRoot *parent_root = getParentServiceRoot();
QSqlQuery query_empty_bin(db_handle);
@ -220,15 +182,7 @@ bool RecycleBin::restore() {
"WHERE is_deleted = 1 AND is_pdeleted = 0 AND account_id = :account_id;");
query_empty_bin.bindValue(QSL(":account_id"), parent_root->accountId());
if (!query_empty_bin.exec()) {
qWarning("Query execution failed for recycle bin restoring.");
db_handle.rollback();
return false;
}
// Commit changes.
if (db_handle.commit()) {
if (query_empty_bin.exec()) {
parent_root->updateCounts(true);
parent_root->itemChanged(parent_root->getSubTree());
parent_root->requestReloadMessageList(true);
@ -236,6 +190,6 @@ bool RecycleBin::restore() {
return true;
}
else {
return db_handle.rollback();
return false;
}
}

View File

@ -23,6 +23,7 @@
#include "services/abstract/category.h"
#include <QSqlQuery>
#include <QSqlError>
ServiceRoot::ServiceRoot(RootItem *parent) : RootItem(parent), m_accountId(NO_PARENT_CATEGORY) {
@ -34,61 +35,50 @@ ServiceRoot::~ServiceRoot() {
bool ServiceRoot::deleteViaGui() {
QSqlDatabase connection = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
QSqlQuery query(connection);
int account_id = accountId();
query.setForwardOnly(true);
// Remove all messages.
if (!QSqlQuery(connection).exec(QString("DELETE FROM Messages WHERE account_id = %1;").arg(accountId()))) {
return false;
QStringList queries;
queries << 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;") <<
QSL("DELETE FROM Accounts WHERE id = :account_id;");
foreach (const QString &q, queries) {
query.prepare(q);
query.bindValue(QSL(":account_id"), account_id);
if (!query.exec()) {
qCritical("Removing of account from DB failed, this is critical: '%s'.", qPrintable(query.lastError().text()));
return false;
}
else {
query.finish();
}
}
// Remove all feeds.
if (!QSqlQuery(connection).exec(QString("DELETE FROM Feeds WHERE account_id = %1;").arg(accountId()))) {
return false;
}
// Remove all categories.
if (!QSqlQuery(connection).exec(QString("DELETE FROM Categories WHERE account_id = %1;").arg(accountId()))) {
return false;
}
// Switch "existence" flag.
bool data_removed = QSqlQuery(connection).exec(QString("DELETE FROM Accounts WHERE id = %1;").arg(accountId()));
if (data_removed) {
requestItemRemoval(this);
}
return data_removed;
requestItemRemoval(this);
return true;
}
bool ServiceRoot::markAsReadUnread(RootItem::ReadStatus status) {
QSqlDatabase db_handle = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
QSqlQuery query(db_handle);
query.setForwardOnly(true);
query.prepare(QSL("UPDATE Messages SET is_read = :read WHERE is_pdeleted = 0 AND account_id = :account_id;"));
if (!db_handle.transaction()) {
qWarning("Starting transaction for feeds read change.");
return false;
}
query.bindValue(QSL(":account_id"), accountId());
query.bindValue(QSL(":read"), status == RootItem::Read ? 1 : 0);
QSqlQuery query_read_msg(db_handle);
query_read_msg.setForwardOnly(true);
query_read_msg.prepare(QSL("UPDATE Messages SET is_read = :read WHERE is_pdeleted = 0 AND account_id = :account_id;"));
query_read_msg.bindValue(QSL(":account_id"), accountId());
query_read_msg.bindValue(QSL(":read"), status == RootItem::Read ? 1 : 0);
if (!query_read_msg.exec()) {
qDebug("Query execution for feeds read change failed.");
db_handle.rollback();
}
// Commit changes.
if (db_handle.commit()) {
if (query.exec()) {
updateCounts(false);
itemChanged(getSubTree());
requestReloadMessageList(status == RootItem::Read);
return true;
}
else {
return db_handle.rollback();
return false;
}
}
@ -96,20 +86,18 @@ QList<Message> ServiceRoot::undeletedMessages() const {
QList<Message> messages;
int account_id = accountId();
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
QSqlQuery query_read_msg(database);
QSqlQuery query(database);
query_read_msg.setForwardOnly(true);
query_read_msg.prepare("SELECT * "
"FROM Messages "
"WHERE is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;");
query_read_msg.bindValue(QSL(":account_id"), account_id);
query.setForwardOnly(true);
query.prepare("SELECT * "
"FROM Messages "
"WHERE is_deleted = 0 AND is_pdeleted = 0 AND account_id = :account_id;");
query.bindValue(QSL(":account_id"), account_id);
// FIXME: Fix those const functions, this is fucking ugly.
if (query_read_msg.exec()) {
while (query_read_msg.next()) {
if (query.exec()) {
while (query.next()) {
bool decoded;
Message message = Message::fromSqlRecord(query_read_msg.record(), &decoded);
Message message = Message::fromSqlRecord(query.record(), &decoded);
if (decoded) {
messages.append(message);

View File

@ -173,14 +173,13 @@ bool StandardCategory::addItself(RootItem *parent) {
query_add.bindValue(QSL(":account_id"), parent->getParentServiceRoot()->accountId());
if (!query_add.exec()) {
qDebug("Failed to add category to database: %s.", qPrintable(query_add.lastError().text()));
qDebug("Failed to add category to database: '%s'.", qPrintable(query_add.lastError().text()));
// Query failed.
return false;
}
setId(query_add.lastInsertId().toInt());
return true;
}

View File

@ -227,21 +227,26 @@ QString StandardFeed::typeToString(StandardFeed::Type type) {
void StandardFeed::updateCounts(bool including_total_count) {
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
QSqlQuery query_all(database);
query_all.setForwardOnly(true);
QSqlQuery query(database);
query.setForwardOnly(true);
if (including_total_count) {
if (query_all.exec(QString("SELECT count(*) FROM Messages WHERE feed = '%1' AND is_deleted = 0 AND account_id = %2;").arg(QString::number(id()),
QString::number(const_cast<StandardFeed*>(this)->serviceRoot()->accountId()))) && query_all.next()) {
m_totalCount = query_all.value(0).toInt();
query.prepare(QSL("SELECT count(*) FROM Messages WHERE feed = :feed AND is_pdeleted = 0 AND is_deleted = 0 AND account_id = :account_id;"));
query.bindValue(QSL(":feed"), id());
query.bindValue(QSL(":account_id"), serviceRoot()->accountId());
if (query.exec() && query.next()) {
m_totalCount = query.value(0).toInt();
}
}
// Obtain count of unread messages.
if (query_all.exec(QString("SELECT count(*) FROM Messages WHERE feed = '%1' AND is_deleted = 0 AND is_read = 0 AND account_id = %2;").arg(QString::number(id()),
QString::number(const_cast<StandardFeed*>(this)->serviceRoot()->accountId()))) && query_all.next()) {
int new_unread_count = query_all.value(0).toInt();
query.prepare(QSL("SELECT count(*) FROM Messages WHERE feed = :feed AND is_pdeleted = 0 AND is_deleted = 0 AND is_read = 0 AND account_id = :account_id;"));
query.bindValue(QSL(":feed"), id());
query.bindValue(QSL(":account_id"), serviceRoot()->accountId());
if (query.exec() && query.next()) {
int new_unread_count = query.value(0).toInt();
if (status() == NewMessages && new_unread_count < m_unreadCount) {
setStatus(Normal);
@ -544,7 +549,7 @@ bool StandardFeed::addItself(RootItem *parent) {
query_add_feed.bindValue(QSL(":type"), (int) type());
if (!query_add_feed.exec()) {
qDebug("Failed to add feed to database: %s.", qPrintable(query_add_feed.lastError().text()));
qDebug("Failed to add feed to database: '%s'.", qPrintable(query_add_feed.lastError().text()));
// Query failed.
return false;
@ -641,7 +646,7 @@ int StandardFeed::updateMessages(const QList<Message> &messages) {
if (!database.transaction()) {
database.rollback();
qDebug("Transaction start for message downloader failed.");
qDebug("Transaction start for message downloader failed: '%s'.", qPrintable(database.lastError().text()));
return updated_messages;
}
@ -692,7 +697,6 @@ int StandardFeed::updateMessages(const QList<Message> &messages) {
}
query_insert.finish();
qDebug("Adding new message '%s' to DB.", qPrintable(message.m_title));
}
else if (message.m_createdFromFeed && !datetime_stamps.contains(message.m_created.toMSecsSinceEpoch())) {
@ -704,7 +708,6 @@ int StandardFeed::updateMessages(const QList<Message> &messages) {
query_update.bindValue(QSL(":enclosures"), Enclosures::encodeEnclosuresToString(message.m_enclosures));
query_update.exec();
query_update.finish();
qDebug("Updating contents of duplicate message '%s'.", qPrintable(message.m_title));
}
else {
@ -723,7 +726,6 @@ int StandardFeed::updateMessages(const QList<Message> &messages) {
}
query_insert.finish();
qDebug("Adding new duplicate (with potentially updated contents) message '%s' to DB.", qPrintable(message.m_title));
}
}
@ -735,7 +737,6 @@ int StandardFeed::updateMessages(const QList<Message> &messages) {
if (!database.commit()) {
database.rollback();
qDebug("Transaction commit for message downloader failed.");
}
else {
@ -768,7 +769,6 @@ StandardFeed::StandardFeed(const QSqlRecord &record) : Feed(NULL) {
setPassword(TextFactory::decrypt(record.value(FDS_DB_PASSWORD_INDEX).toString()));
}
setAutoUpdateType(static_cast<Feed::AutoUpdateType>(record.value(FDS_DB_UPDATE_TYPE_INDEX).toInt()));
setAutoUpdateInitialInterval(record.value(FDS_DB_UPDATE_INTERVAL_INDEX).toInt());
}

View File

@ -71,8 +71,11 @@ ServiceRoot *StandardServiceEntryPoint::createNewRoot() {
int id_to_assign = query.value(0).toInt() + 1;
if (query.exec(QString("INSERT INTO Accounts (id, type) VALUES (%1, '%2');").arg(QString::number(id_to_assign),
SERVICE_CODE_STD_RSS))) {
query.prepare(QSL("INSERT INTO Accounts (id, type) VALUES (:id, :type);"));
query.bindValue(QSL(":id"), id_to_assign);
query.bindValue(QSL(":type"), SERVICE_CODE_STD_RSS);
if (query.exec()) {
StandardServiceRoot *root = new StandardServiceRoot();
root->setAccountId(id_to_assign);
return root;
@ -88,7 +91,11 @@ QList<ServiceRoot*> StandardServiceEntryPoint::initializeSubtree() {
QSqlQuery query(database);
QList<ServiceRoot*> roots;
if (query.exec(QString("SELECT id FROM Accounts WHERE type = '%1';").arg(SERVICE_CODE_STD_RSS))) {
query.setForwardOnly(true);
query.prepare(QSL("SELECT id FROM Accounts WHERE type = :type;"));
query.bindValue(QSL(":type"), SERVICE_CODE_STD_RSS);
if (query.exec()) {
while (query.next()) {
StandardServiceRoot *root = new StandardServiceRoot();
root->setAccountId(query.value(0).toInt());

View File

@ -149,22 +149,11 @@ RecycleBin *StandardServiceRoot::recycleBin() {
bool StandardServiceRoot::markFeedsReadUnread(QList<Feed*> items, ReadStatus read) {
QSqlDatabase db_handle = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
if (!db_handle.transaction()) {
qWarning("Starting transaction for feeds read change.");
return false;
}
QSqlQuery query_read_msg(db_handle);
query_read_msg.setForwardOnly(true);
if (!query_read_msg.prepare(QString("UPDATE Messages SET is_read = :read "
"WHERE feed IN (%1) AND is_deleted = 0 AND is_pdeleted = 0;").arg(textualFeedIds(items).join(QSL(", "))))) {
qWarning("Query preparation failed for feeds read change.");
db_handle.rollback();
return false;
}
query_read_msg.prepare(QString("UPDATE Messages SET is_read = :read "
"WHERE feed IN (%1) AND is_deleted = 0 AND is_pdeleted = 0;").arg(textualFeedIds(items).join(QSL(", "))));
query_read_msg.bindValue(QSL(":read"), read == RootItem::Read ? 1 : 0);