SQL refactoring.

This commit is contained in:
Martin Rotter 2016-04-12 13:30:31 +02:00
parent 216d736573
commit 73241e4bb7
5 changed files with 247 additions and 157 deletions

View File

@ -18,11 +18,13 @@
#include "miscellaneous/databasequeries.h"
#include "services/abstract/category.h"
#include "services/abstract/feed.h"
#include "services/owncloud/owncloudserviceroot.h"
#include "services/owncloud/owncloudcategory.h"
#include "services/owncloud/owncloudfeed.h"
#include "services/owncloud/network/owncloudnetworkfactory.h"
#include "services/standard/standardserviceroot.h"
#include "services/standard/standardcategory.h"
#include "services/standard/standardfeed.h"
#include "miscellaneous/textfactory.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
@ -1067,5 +1069,208 @@ bool DatabaseQueries::editCategory(QSqlDatabase db, int parent_id, int category_
return q.exec();
}
int DatabaseQueries::addFeed(QSqlDatabase db, int parent_id, int account_id, const QString &title,
const QString &description, QDateTime creation_date, const QIcon &icon,
const QString &encoding, const QString &url, bool is_protected,
const QString &username, const QString &password,
Feed::AutoUpdateType auto_update_type,
int auto_update_interval, StandardFeed::Type feed_format, bool *ok) {
QSqlQuery q(db);
q.setForwardOnly(true);
q.prepare("INSERT INTO Feeds "
"(title, description, date_created, icon, category, encoding, url, protected, username, password, update_type, update_interval, type, account_id) "
"VALUES (:title, :description, :date_created, :icon, :category, :encoding, :url, :protected, :username, :password, :update_type, :update_interval, :type, :account_id);");
q.bindValue(QSL(":title"), title);
q.bindValue(QSL(":description"), description);
q.bindValue(QSL(":date_created"), creation_date.toMSecsSinceEpoch());
q.bindValue(QSL(":icon"), qApp->icons()->toByteArray(icon));
q.bindValue(QSL(":category"), parent_id);
q.bindValue(QSL(":encoding"), encoding);
q.bindValue(QSL(":url"), url);
q.bindValue(QSL(":protected"), is_protected ? 1 : 0);
q.bindValue(QSL(":username"), username);
q.bindValue(QSL(":account_id"), account_id);
if (password.isEmpty()) {
q.bindValue(QSL(":password"), password);
}
else {
q.bindValue(QSL(":password"), TextFactory::encrypt(password));
}
q.bindValue(QSL(":update_type"), (int) auto_update_type);
q.bindValue(QSL(":update_interval"), auto_update_interval);
q.bindValue(QSL(":type"), (int) feed_format);
if (q.exec()) {
int new_id = q.lastInsertId().toInt();
// Now set custom ID in the DB.
q.prepare(QSL("UPDATE Feeds SET custom_id = :custom_id WHERE id = :id;"));
q.bindValue(QSL(":custom_id"), QString::number(new_id));
q.bindValue(QSL(":id"), new_id);
q.exec();
if (ok != NULL) {
*ok = true;
}
return new_id;
}
else {
if (ok != NULL) {
*ok = false;
}
qDebug("Failed to add feed to database: '%s'.", qPrintable(q.lastError().text()));
return 0;
}
}
bool DatabaseQueries::editFeed(QSqlDatabase db, int parent_id, int feed_id, const QString &title,
const QString &description, const QIcon &icon,
const QString &encoding, const QString &url, bool is_protected,
const QString &username, const QString &password,
Feed::AutoUpdateType auto_update_type,
int auto_update_interval, StandardFeed::Type feed_format) {
QSqlQuery q(db);
q.setForwardOnly(true);
q.prepare("UPDATE Feeds "
"SET title = :title, description = :description, icon = :icon, category = :category, encoding = :encoding, url = :url, protected = :protected, username = :username, password = :password, update_type = :update_type, update_interval = :update_interval, type = :type "
"WHERE id = :id;");
q.bindValue(QSL(":title"), title);
q.bindValue(QSL(":description"), description);
q.bindValue(QSL(":icon"), qApp->icons()->toByteArray(icon));
q.bindValue(QSL(":category"), parent_id);
q.bindValue(QSL(":encoding"), encoding);
q.bindValue(QSL(":url"), url);
q.bindValue(QSL(":protected"), is_protected ? 1 : 0);
q.bindValue(QSL(":username"), username);
if (password.isEmpty()) {
q.bindValue(QSL(":password"), password);
}
else {
q.bindValue(QSL(":password"), TextFactory::encrypt(password));
}
q.bindValue(QSL(":update_type"), (int) auto_update_type);
q.bindValue(QSL(":update_interval"), auto_update_interval);
q.bindValue(QSL(":type"), feed_format);
q.bindValue(QSL(":id"), feed_id);
return q.exec();
}
QList<ServiceRoot*> DatabaseQueries::getAccounts(QSqlDatabase db, bool *ok) {
QSqlQuery q(db);
QList<ServiceRoot*> roots;
q.setForwardOnly(true);
q.prepare(QSL("SELECT id FROM Accounts WHERE type = :type;"));
q.bindValue(QSL(":type"), SERVICE_CODE_STD_RSS);
if (q.exec()) {
while (q.next()) {
StandardServiceRoot *root = new StandardServiceRoot();
root->setAccountId(q.value(0).toInt());
roots.append(root);
}
if (ok != NULL) {
*ok = true;
}
}
else {
if (ok != NULL) {
*ok = false;
}
}
return roots;
}
Assignment DatabaseQueries::getCategories(QSqlDatabase db, int account_id, bool *ok) {
Assignment categories;
// Obtain data for categories from the database.
QSqlQuery q(db);
q.setForwardOnly(true);
q.prepare(QSL("SELECT * FROM Categories WHERE account_id = :account_id;"));
q.bindValue(QSL(":account_id"), account_id);
if (!q.exec()) {
qFatal("Query for obtaining categories failed. Error message: '%s'.",
qPrintable(q.lastError().text()));
if (ok != NULL) {
*ok = false;
}
}
if (ok != NULL) {
*ok = true;
}
while (q.next()) {
AssignmentItem pair;
pair.first = q.value(CAT_DB_PARENT_ID_INDEX).toInt();
pair.second = new StandardCategory(q.record());
categories << pair;
}
return categories;
}
Assignment DatabaseQueries::getFeeds(QSqlDatabase db, int account_id, bool *ok) {
Assignment feeds;
QSqlQuery q(db);
q.setForwardOnly(true);
q.prepare(QSL("SELECT * FROM Feeds WHERE account_id = :account_id;"));
q.bindValue(QSL(":account_id"), account_id);
if (!q.exec()) {
qFatal("Query for obtaining feeds failed. Error message: '%s'.",
qPrintable(q.lastError().text()));
if (ok != NULL) {
*ok = false;
}
}
if (ok != NULL) {
*ok = true;
}
while (q.next()) {
// Process this feed.
StandardFeed::Type type = static_cast<StandardFeed::Type>(q.value(FDS_DB_TYPE_INDEX).toInt());
switch (type) {
case StandardFeed::Atom10:
case StandardFeed::Rdf:
case StandardFeed::Rss0X:
case StandardFeed::Rss2X: {
AssignmentItem pair;
pair.first = q.value(FDS_DB_CATEGORY_INDEX).toInt();
pair.second = new StandardFeed(q.record());
qobject_cast<StandardFeed*>(pair.second)->setType(type);
feeds << pair;
break;
}
default:
break;
}
}
return feeds;
}
DatabaseQueries::DatabaseQueries() {
}

View File

@ -21,6 +21,7 @@
#include "services/abstract/rootitem.h"
#include "services/abstract/serviceroot.h"
#include "services/standard/standardfeed.h"
#include <QSqlQuery>
@ -74,6 +75,20 @@ class DatabaseQueries {
const QString &description, QDateTime creation_date, const QIcon &icon, bool *ok = NULL);
static bool editCategory(QSqlDatabase db, int parent_id, int category_id,
const QString &title, const QString &description, const QIcon &icon);
static int addFeed(QSqlDatabase db, int parent_id, int account_id, const QString &title,
const QString &description, QDateTime creation_date, const QIcon &icon,
const QString &encoding, const QString &url, bool is_protected,
const QString &username, const QString &password,
Feed::AutoUpdateType auto_update_type,
int auto_update_interval, StandardFeed::Type feed_format, bool *ok = NULL);
static bool editFeed(QSqlDatabase db, int parent_id, int feed_id, const QString &title,
const QString &description, const QIcon &icon,
const QString &encoding, const QString &url, bool is_protected,
const QString &username, const QString &password, Feed::AutoUpdateType auto_update_type,
int auto_update_interval, StandardFeed::Type feed_format);
static QList<ServiceRoot*> getAccounts(QSqlDatabase db, bool *ok = NULL);
static Assignment getCategories(QSqlDatabase db, int account_id, bool *ok = NULL);
static Assignment getFeeds(QSqlDatabase db, int account_id, bool *ok = NULL);
private:
explicit DatabaseQueries();

View File

@ -381,86 +381,35 @@ bool StandardFeed::removeItself() {
bool StandardFeed::addItself(RootItem *parent) {
// Now, add feed to persistent storage.
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
QSqlQuery query_add_feed(database);
query_add_feed.setForwardOnly(true);
query_add_feed.prepare("INSERT INTO Feeds "
"(title, description, date_created, icon, category, encoding, url, protected, username, password, update_type, update_interval, type, account_id) "
"VALUES (:title, :description, :date_created, :icon, :category, :encoding, :url, :protected, :username, :password, :update_type, :update_interval, :type, :account_id);");
query_add_feed.bindValue(QSL(":title"), title());
query_add_feed.bindValue(QSL(":description"), description());
query_add_feed.bindValue(QSL(":date_created"), creationDate().toMSecsSinceEpoch());
query_add_feed.bindValue(QSL(":icon"), qApp->icons()->toByteArray(icon()));
query_add_feed.bindValue(QSL(":category"), parent->id());
query_add_feed.bindValue(QSL(":encoding"), encoding());
query_add_feed.bindValue(QSL(":url"), url());
query_add_feed.bindValue(QSL(":protected"), (int) passwordProtected());
query_add_feed.bindValue(QSL(":username"), username());
query_add_feed.bindValue(QSL(":account_id"), parent->getParentServiceRoot()->accountId());
if (password().isEmpty()) {
query_add_feed.bindValue(QSL(":password"), password());
}
else {
query_add_feed.bindValue(QSL(":password"), TextFactory::encrypt(password()));
}
query_add_feed.bindValue(QSL(":update_type"), (int) autoUpdateType());
query_add_feed.bindValue(QSL(":update_interval"), autoUpdateInitialInterval());
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()));
bool ok;
int new_id = DatabaseQueries::addFeed(database, parent->id(), parent->getParentServiceRoot()->accountId(), title(),
description(), creationDate(), icon(), encoding(), url(), passwordProtected(),
username(), password(), autoUpdateType(), autoUpdateInitialInterval(), type(), &ok);
if (!ok) {
// Query failed.
return false;
}
else {
// New feed was added, fetch is primary id from the database.
setId(new_id);
setCustomId(new_id);
// New feed was added, fetch is primary id from the database.
setId(query_add_feed.lastInsertId().toInt());
setCustomId(id());
// Now set custom ID in the DB.
query_add_feed.prepare(QSL("UPDATE Feeds SET custom_id = :custom_id WHERE id = :id;"));
query_add_feed.bindValue(QSL(":custom_id"), QString::number(customId()));
query_add_feed.bindValue(QSL(":id"), id());
query_add_feed.exec();
return true;
return true;
}
}
bool StandardFeed::editItself(StandardFeed *new_feed_data) {
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
QSqlQuery query_update_feed(database);
StandardFeed *original_feed = this;
RootItem *new_parent = new_feed_data->parent();
query_update_feed.setForwardOnly(true);
query_update_feed.prepare("UPDATE Feeds "
"SET title = :title, description = :description, icon = :icon, category = :category, encoding = :encoding, url = :url, protected = :protected, username = :username, password = :password, update_type = :update_type, update_interval = :update_interval, type = :type "
"WHERE id = :id;");
query_update_feed.bindValue(QSL(":title"), new_feed_data->title());
query_update_feed.bindValue(QSL(":description"), new_feed_data->description());
query_update_feed.bindValue(QSL(":icon"), qApp->icons()->toByteArray(new_feed_data->icon()));
query_update_feed.bindValue(QSL(":category"), new_parent->id());
query_update_feed.bindValue(QSL(":encoding"), new_feed_data->encoding());
query_update_feed.bindValue(QSL(":url"), new_feed_data->url());
query_update_feed.bindValue(QSL(":protected"), (int) new_feed_data->passwordProtected());
query_update_feed.bindValue(QSL(":username"), new_feed_data->username());
if (password().isEmpty()) {
query_update_feed.bindValue(QSL(":password"), new_feed_data->password());
}
else {
query_update_feed.bindValue(QSL(":password"), TextFactory::encrypt(new_feed_data->password()));
}
query_update_feed.bindValue(QSL(":update_type"), (int) new_feed_data->autoUpdateType());
query_update_feed.bindValue(QSL(":update_interval"), new_feed_data->autoUpdateInitialInterval());
query_update_feed.bindValue(QSL(":type"), new_feed_data->type());
query_update_feed.bindValue(QSL(":id"), original_feed->id());
if (!query_update_feed.exec()) {
if (!DatabaseQueries::editFeed(database, new_parent->id(), original_feed->id(), new_feed_data->title(),
new_feed_data->description(), new_feed_data->icon(),
new_feed_data->encoding(), new_feed_data->url(), new_feed_data->passwordProtected(),
new_feed_data->username(), new_feed_data->password(),
new_feed_data->autoUpdateType(), new_feed_data->autoUpdateInitialInterval(),
new_feed_data->type())) {
// Persistent storage update failed, no way to continue now.
return false;
}

View File

@ -20,10 +20,9 @@
#include "definitions/definitions.h"
#include "miscellaneous/application.h"
#include "miscellaneous/databasequeries.h"
#include "services/standard/standardserviceroot.h"
#include <QSqlQuery>
StandardServiceEntryPoint::StandardServiceEntryPoint() {
}
@ -62,22 +61,12 @@ QString StandardServiceEntryPoint::code() const {
ServiceRoot *StandardServiceEntryPoint::createNewRoot() const {
// Switch DB.
QSqlDatabase database = qApp->database()->connection(QSL("StandardServiceEntryPoint"), DatabaseFactory::FromSettings);
QSqlQuery query(database);
bool ok;
int new_id = DatabaseQueries::createAccount(database, code(), &ok);
// First obtain the ID, which can be assigned to this new account.
if (!query.exec("SELECT max(id) FROM Accounts;") || !query.next()) {
return NULL;
}
int id_to_assign = query.value(0).toInt() + 1;
query.prepare(QSL("INSERT INTO Accounts (id, type) VALUES (:id, :type);"));
query.bindValue(QSL(":id"), id_to_assign);
query.bindValue(QSL(":type"), code());
if (query.exec()) {
if (ok) {
StandardServiceRoot *root = new StandardServiceRoot();
root->setAccountId(id_to_assign);
root->setAccountId(new_id);
return root;
}
else {
@ -88,20 +77,6 @@ ServiceRoot *StandardServiceEntryPoint::createNewRoot() const {
QList<ServiceRoot*> StandardServiceEntryPoint::initializeSubtree() const {
// Check DB if standard account is enabled.
QSqlDatabase database = qApp->database()->connection(QSL("StandardServiceEntryPoint"), DatabaseFactory::FromSettings);
QSqlQuery query(database);
QList<ServiceRoot*> roots;
query.setForwardOnly(true);
query.prepare(QSL("SELECT id FROM Accounts WHERE type = :type;"));
query.bindValue(QSL(":type"), code());
if (query.exec()) {
while (query.next()) {
StandardServiceRoot *root = new StandardServiceRoot();
root->setAccountId(query.value(0).toInt());
roots.append(root);
}
}
return roots;
return DatabaseQueries::getAccounts(database);
}

View File

@ -21,6 +21,7 @@
#include "miscellaneous/application.h"
#include "miscellaneous/settings.h"
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/databasequeries.h"
#include "miscellaneous/mutex.h"
#include "core/feedsmodel.h"
#include "gui/messagebox.h"
@ -35,8 +36,6 @@
#include "services/standard/gui/formstandardfeeddetails.h"
#include "services/standard/gui/formstandardimportexport.h"
#include <QSqlQuery>
#include <QSqlError>
#include <QStack>
#include <QAction>
#include <QSqlTableModel>
@ -173,61 +172,8 @@ RecycleBin *StandardServiceRoot::recycleBin() const {
void StandardServiceRoot::loadFromDatabase(){
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DatabaseFactory::FromSettings);
Assignment categories;
Assignment feeds;
// Obtain data for categories from the database.
QSqlQuery query_categories(database);
query_categories.setForwardOnly(true);
query_categories.prepare(QSL("SELECT * FROM Categories WHERE account_id = :account_id;"));
query_categories.bindValue(QSL(":account_id"), accountId());
if (!query_categories.exec()) {
qFatal("Query for obtaining categories failed. Error message: '%s'.",
qPrintable(query_categories.lastError().text()));
}
while (query_categories.next()) {
AssignmentItem pair;
pair.first = query_categories.value(CAT_DB_PARENT_ID_INDEX).toInt();
pair.second = new StandardCategory(query_categories.record());
categories << pair;
}
// All categories are now loaded.
QSqlQuery query_feeds(database);
query_feeds.setForwardOnly(true);
query_feeds.prepare(QSL("SELECT * FROM Feeds WHERE account_id = :account_id;"));
query_feeds.bindValue(QSL(":account_id"), accountId());
if (!query_feeds.exec()) {
qFatal("Query for obtaining feeds failed. Error message: '%s'.",
qPrintable(query_feeds.lastError().text()));
}
while (query_feeds.next()) {
// Process this feed.
StandardFeed::Type type = static_cast<StandardFeed::Type>(query_feeds.value(FDS_DB_TYPE_INDEX).toInt());
switch (type) {
case StandardFeed::Atom10:
case StandardFeed::Rdf:
case StandardFeed::Rss0X:
case StandardFeed::Rss2X: {
AssignmentItem pair;
pair.first = query_feeds.value(FDS_DB_CATEGORY_INDEX).toInt();
pair.second = new StandardFeed(query_feeds.record());
qobject_cast<StandardFeed*>(pair.second)->setType(type);
feeds << pair;
break;
}
default:
break;
}
}
Assignment categories = DatabaseQueries::getCategories(database, accountId());
Assignment feeds = DatabaseQueries::getFeeds(database, accountId());
// All data are now obtained, lets create the hierarchy.
assembleCategories(categories);