initial db driver refactoring
This commit is contained in:
parent
3494925eb6
commit
be07b2d514
73 changed files with 961 additions and 1492 deletions
|
@ -4,189 +4,4 @@ CREATE DATABASE IF NOT EXISTS ## CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_c
|
|||
-- !
|
||||
USE ##;
|
||||
-- !
|
||||
DROP TABLE IF EXISTS Information;
|
||||
-- !
|
||||
CREATE TABLE IF NOT EXISTS Information (
|
||||
id INTEGER AUTO_INCREMENT PRIMARY KEY,
|
||||
inf_key TEXT NOT NULL,
|
||||
inf_value TEXT NOT NULL
|
||||
);
|
||||
-- !
|
||||
INSERT INTO Information VALUES (1, 'schema_version', '1');
|
||||
-- !
|
||||
CREATE TABLE IF NOT EXISTS Accounts (
|
||||
id INTEGER AUTO_INCREMENT PRIMARY KEY,
|
||||
type TEXT NOT NULL CHECK (type != ''),
|
||||
proxy_type INTEGER NOT NULL DEFAULT 0 CHECK (proxy_type >= 0),
|
||||
proxy_host TEXT,
|
||||
proxy_port INTEGER,
|
||||
proxy_username TEXT,
|
||||
proxy_password TEXT
|
||||
);
|
||||
-- !
|
||||
CREATE TABLE IF NOT EXISTS TtRssAccounts (
|
||||
id INTEGER,
|
||||
username TEXT NOT NULL,
|
||||
password TEXT,
|
||||
auth_protected INTEGER(1) NOT NULL DEFAULT 0 CHECK (auth_protected >= 0 AND auth_protected <= 1),
|
||||
auth_username TEXT,
|
||||
auth_password TEXT,
|
||||
url TEXT NOT NULL,
|
||||
force_update INTEGER(1) NOT NULL DEFAULT 0 CHECK (force_update >= 0 AND force_update <= 1),
|
||||
update_only_unread INTEGER(1) NOT NULL DEFAULT 0 CHECK (update_only_unread >= 0 AND update_only_unread <= 1),
|
||||
|
||||
FOREIGN KEY (id) REFERENCES Accounts (id)
|
||||
);
|
||||
-- !
|
||||
CREATE TABLE IF NOT EXISTS OwnCloudAccounts (
|
||||
id INTEGER,
|
||||
username TEXT NOT NULL,
|
||||
password TEXT,
|
||||
url TEXT NOT NULL,
|
||||
force_update INTEGER(1) NOT NULL DEFAULT 0 CHECK (force_update >= 0 AND force_update <= 1),
|
||||
msg_limit INTEGER NOT NULL DEFAULT -1 CHECK (msg_limit >= -1),
|
||||
update_only_unread INTEGER(1) NOT NULL DEFAULT 0 CHECK (update_only_unread >= 0 AND update_only_unread <= 1),
|
||||
|
||||
FOREIGN KEY (id) REFERENCES Accounts (id)
|
||||
);
|
||||
-- !
|
||||
CREATE TABLE IF NOT EXISTS InoreaderAccounts (
|
||||
id INTEGER,
|
||||
username TEXT NOT NULL,
|
||||
app_id TEXT,
|
||||
app_key TEXT,
|
||||
redirect_url TEXT,
|
||||
refresh_token TEXT,
|
||||
msg_limit INTEGER NOT NULL DEFAULT -1 CHECK (msg_limit >= -1),
|
||||
|
||||
FOREIGN KEY (id) REFERENCES Accounts (id)
|
||||
);
|
||||
-- !
|
||||
CREATE TABLE IF NOT EXISTS GmailAccounts (
|
||||
id INTEGER,
|
||||
username TEXT NOT NULL,
|
||||
app_id TEXT,
|
||||
app_key TEXT,
|
||||
redirect_url TEXT,
|
||||
refresh_token TEXT,
|
||||
msg_limit INTEGER NOT NULL DEFAULT -1 CHECK (msg_limit >= -1),
|
||||
|
||||
FOREIGN KEY (id) REFERENCES Accounts (id)
|
||||
);
|
||||
-- !
|
||||
CREATE TABLE IF NOT EXISTS GoogleReaderApiAccounts (
|
||||
id INTEGER,
|
||||
type INTEGER NOT NULL CHECK (type >= 1),
|
||||
username TEXT NOT NULL,
|
||||
password TEXT,
|
||||
url TEXT NOT NULL,
|
||||
msg_limit INTEGER NOT NULL DEFAULT -1 CHECK (msg_limit >= -1),
|
||||
|
||||
FOREIGN KEY (id) REFERENCES Accounts (id)
|
||||
);
|
||||
-- !
|
||||
CREATE TABLE IF NOT EXISTS FeedlyAccounts (
|
||||
id INTEGER,
|
||||
username TEXT NOT NULL,
|
||||
developer_access_token TEXT,
|
||||
refresh_token TEXT,
|
||||
msg_limit INTEGER NOT NULL DEFAULT -1 CHECK (msg_limit >= -1),
|
||||
update_only_unread INTEGER(1) NOT NULL DEFAULT 0 CHECK (update_only_unread >= 0 AND update_only_unread <= 1),
|
||||
|
||||
FOREIGN KEY (id) REFERENCES Accounts (id)
|
||||
);
|
||||
-- !
|
||||
DROP TABLE IF EXISTS Categories;
|
||||
-- !
|
||||
CREATE TABLE IF NOT EXISTS Categories (
|
||||
id INTEGER AUTO_INCREMENT PRIMARY KEY,
|
||||
parent_id TEXT NOT NULL,
|
||||
title VARCHAR(100) NOT NULL CHECK (title != ''),
|
||||
description TEXT,
|
||||
date_created BIGINT,
|
||||
icon BLOB,
|
||||
account_id INTEGER NOT NULL,
|
||||
custom_id TEXT,
|
||||
|
||||
FOREIGN KEY (account_id) REFERENCES Accounts (id)
|
||||
);
|
||||
-- !
|
||||
DROP TABLE IF EXISTS Feeds;
|
||||
-- !
|
||||
CREATE TABLE IF NOT EXISTS Feeds (
|
||||
id INTEGER AUTO_INCREMENT PRIMARY KEY,
|
||||
title TEXT NOT NULL CHECK (title != ''),
|
||||
description TEXT,
|
||||
date_created BIGINT,
|
||||
icon BLOB,
|
||||
category INTEGER NOT NULL CHECK (category >= -1),
|
||||
encoding TEXT,
|
||||
source_type INTEGER,
|
||||
url VARCHAR(1000),
|
||||
post_process TEXT,
|
||||
protected INTEGER(1) NOT NULL CHECK (protected >= 0 AND protected <= 1),
|
||||
username TEXT,
|
||||
password TEXT,
|
||||
update_type INTEGER(1) NOT NULL CHECK (update_type >= 0),
|
||||
update_interval INTEGER NOT NULL DEFAULT 15 CHECK (update_interval >= 1),
|
||||
type INTEGER,
|
||||
account_id INTEGER NOT NULL,
|
||||
custom_id TEXT,
|
||||
|
||||
FOREIGN KEY (account_id) REFERENCES Accounts (id)
|
||||
);
|
||||
-- !
|
||||
DROP TABLE IF EXISTS Messages;
|
||||
-- !
|
||||
CREATE TABLE IF NOT EXISTS Messages (
|
||||
id INTEGER AUTO_INCREMENT PRIMARY KEY,
|
||||
is_read INTEGER(1) NOT NULL DEFAULT 0 CHECK (is_read >= 0 AND is_read <= 1),
|
||||
is_deleted INTEGER(1) NOT NULL DEFAULT 0 CHECK (is_deleted >= 0 AND is_deleted <= 1),
|
||||
is_important INTEGER(1) NOT NULL DEFAULT 0 CHECK (is_important >= 0 AND is_important <= 1),
|
||||
feed TEXT NOT NULL,
|
||||
title TEXT NOT NULL CHECK (title != ''),
|
||||
url TEXT,
|
||||
author TEXT,
|
||||
date_created BIGINT NOT NULL CHECK (date_created != 0),
|
||||
contents TEXT,
|
||||
is_pdeleted INTEGER(1) NOT NULL DEFAULT 0 CHECK (is_pdeleted >= 0 AND is_pdeleted <= 1),
|
||||
enclosures TEXT,
|
||||
account_id INTEGER NOT NULL,
|
||||
custom_id TEXT,
|
||||
custom_hash TEXT,
|
||||
|
||||
FOREIGN KEY (account_id) REFERENCES Accounts (id)
|
||||
);
|
||||
-- !
|
||||
CREATE TABLE IF NOT EXISTS MessageFilters (
|
||||
id INTEGER AUTO_INCREMENT PRIMARY KEY,
|
||||
name TEXT NOT NULL CHECK (name != ''),
|
||||
script TEXT NOT NULL CHECK (script != '')
|
||||
);
|
||||
-- !
|
||||
CREATE TABLE IF NOT EXISTS MessageFiltersInFeeds (
|
||||
filter INTEGER NOT NULL,
|
||||
feed_custom_id TEXT NOT NULL,
|
||||
account_id INTEGER NOT NULL,
|
||||
|
||||
FOREIGN KEY (filter) REFERENCES MessageFilters (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (account_id) REFERENCES Accounts (id) ON DELETE CASCADE
|
||||
);
|
||||
-- !
|
||||
CREATE TABLE IF NOT EXISTS Labels (
|
||||
id INTEGER AUTO_INCREMENT PRIMARY KEY,
|
||||
name TEXT NOT NULL CHECK (name != ''),
|
||||
color VARCHAR(7),
|
||||
custom_id TEXT,
|
||||
account_id INTEGER NOT NULL,
|
||||
|
||||
FOREIGN KEY (account_id) REFERENCES Accounts (id)
|
||||
);
|
||||
-- !
|
||||
CREATE TABLE IF NOT EXISTS LabelsInMessages (
|
||||
label TEXT NOT NULL, /* Custom ID of label. */
|
||||
message TEXT NOT NULL, /* Custom ID of message. */
|
||||
account_id INTEGER NOT NULL,
|
||||
|
||||
FOREIGN KEY (account_id) REFERENCES Accounts (id) ON DELETE CASCADE
|
||||
);
|
||||
!! db_init_sqlite.sql
|
|
@ -137,8 +137,8 @@ void FeedDownloader::updateOneFeed(Feed* feed) {
|
|||
|
||||
bool is_main_thread = QThread::currentThread() == qApp->thread();
|
||||
QSqlDatabase database = is_main_thread ?
|
||||
qApp->database()->connection(metaObject()->className()) :
|
||||
qApp->database()->connection(QSL("feed_upd"));
|
||||
qApp->database()->driver()->connection(metaObject()->className()) :
|
||||
qApp->database()->driver()->connection(QSL("feed_upd"));
|
||||
|
||||
// Perform per-message filtering.
|
||||
QJSEngine filter_engine;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "3rd-party/boolinq/boolinq.h"
|
||||
#include "definitions/definitions.h"
|
||||
#include "gui/dialogs/formmain.h"
|
||||
#include "miscellaneous/databasefactory.h"
|
||||
#include "database/databasefactory.h"
|
||||
#include "miscellaneous/feedreader.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/textfactory.h"
|
||||
|
|
|
@ -25,7 +25,7 @@ QList<Enclosure> Enclosures::decodeEnclosuresFromString(const QString& enclosure
|
|||
#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
|
||||
Qt::SplitBehaviorFlags::SkipEmptyParts)) {
|
||||
#else
|
||||
QString::SkipEmptyParts)) {
|
||||
QString::SplitBehavior::SkipEmptyParts)) {
|
||||
#endif
|
||||
Enclosure enclosure;
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
#include "core/messagesmodelcache.h"
|
||||
#include "definitions/definitions.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasefactory.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasefactory.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/skinfactory.h"
|
||||
#include "miscellaneous/textfactory.h"
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
|
||||
#include "core/messagesmodelsqllayer.h"
|
||||
|
||||
#include "database/databasequeries.h"
|
||||
#include "definitions/definitions.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
|
||||
MessagesModelSqlLayer::MessagesModelSqlLayer()
|
||||
: m_filter(QSL(DEFAULT_SQL_MESSAGES_FILTER)), m_fieldNames({}), m_orderByNames({}),
|
||||
m_sortColumns({}), m_numericColumns({}), m_sortOrders({}) {
|
||||
m_db = qApp->database()->connection(QSL("MessagesModel"));
|
||||
m_db = qApp->database()->driver()->connection(QSL("MessagesModel"));
|
||||
|
||||
// Used in <x>: SELECT <x1>, <x2> FROM ....;
|
||||
m_fieldNames = DatabaseQueries::messageTableAttributes(false);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#include "miscellaneous/databasecleaner.h"
|
||||
#include "database/databasecleaner.h"
|
||||
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QThread>
|
||||
|
@ -18,7 +18,7 @@ void DatabaseCleaner::purgeDatabaseData(const CleanerOrders& which_data) {
|
|||
bool result = true;
|
||||
const int difference = 99 / 12;
|
||||
int progress = 0;
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
if (which_data.m_removeReadMessages) {
|
||||
progress += difference;
|
||||
|
@ -67,7 +67,7 @@ void DatabaseCleaner::purgeDatabaseData(const CleanerOrders& which_data) {
|
|||
emit purgeProgress(progress, tr("Shrinking database file..."));
|
||||
|
||||
// Call driver-specific vacuuming function.
|
||||
result &= qApp->database()->vacuumDatabase();
|
||||
result &= qApp->database()->driver()->vacuumDatabase();
|
||||
progress += difference;
|
||||
emit purgeProgress(progress, tr("Database file shrinked..."));
|
||||
}
|
|
@ -20,8 +20,6 @@ class DatabaseCleaner : public QObject {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
// Constructors.
|
||||
explicit DatabaseCleaner(QObject* parent = nullptr);
|
||||
virtual ~DatabaseCleaner() = default;
|
||||
|
49
src/librssguard/database/databasedriver.cpp
Executable file
49
src/librssguard/database/databasedriver.cpp
Executable file
|
@ -0,0 +1,49 @@
|
|||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#include "database/databasedriver.h"
|
||||
|
||||
#include "definitions/definitions.h"
|
||||
#include "exceptions/ioexception.h"
|
||||
#include "miscellaneous/iofactory.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QRegularExpression>
|
||||
|
||||
DatabaseDriver::DatabaseDriver(QObject* parent) : QObject(parent)
|
||||
{}
|
||||
|
||||
QStringList DatabaseDriver::prepareScript(const QString& base_sql_folder, const QString& sql_file, const QString& database_name) {
|
||||
QStringList statements;
|
||||
auto next_file = base_sql_folder + QDir::separator() + sql_file;
|
||||
QString sql_script = QString::fromUtf8(IOFactory::readFile(next_file));
|
||||
auto new_statements = sql_script.split(APP_DB_COMMENT_SPLIT,
|
||||
#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
|
||||
Qt::SplitBehaviorFlags::SkipEmptyParts);
|
||||
#else
|
||||
QString::SplitBehavior::SkipEmptyParts);
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < new_statements.size(); i++) {
|
||||
if (new_statements.at(i).startsWith(APP_DB_INCLUDE_PLACEHOLDER)) {
|
||||
// We include another file.
|
||||
QString included_file_name = new_statements.at(i).mid(QSL(APP_DB_INCLUDE_PLACEHOLDER).size() + 1);
|
||||
|
||||
auto included_file = base_sql_folder + QDir::separator() + included_file_name;
|
||||
QString included_sql_script = QString::fromUtf8(IOFactory::readFile(included_file));
|
||||
auto included_statements = sql_script.split(APP_DB_COMMENT_SPLIT,
|
||||
#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
|
||||
Qt::SplitBehaviorFlags::SkipEmptyParts);
|
||||
#else
|
||||
QString::SplitBehavior::SkipEmptyParts);
|
||||
#endif
|
||||
|
||||
statements << included_statements;
|
||||
}
|
||||
else {
|
||||
statements << new_statements.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
statements.replaceInStrings(APP_DB_NAME_PLACEHOLDER, database_name);
|
||||
return statements;
|
||||
}
|
50
src/librssguard/database/databasedriver.h
Executable file
50
src/librssguard/database/databasedriver.h
Executable file
|
@ -0,0 +1,50 @@
|
|||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#ifndef DATABASEDRIVER_H
|
||||
#define DATABASEDRIVER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <QSqlDatabase>
|
||||
|
||||
class DatabaseDriver : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
// Describes available types of database backend.
|
||||
enum class DriverType {
|
||||
SQLite,
|
||||
MySQL
|
||||
};
|
||||
|
||||
// Describes what type of database user wants.
|
||||
enum class DesiredStorageType {
|
||||
StrictlyFileBased,
|
||||
StrictlyInMemory,
|
||||
FromSettings
|
||||
};
|
||||
|
||||
explicit DatabaseDriver(QObject* parent = nullptr);
|
||||
|
||||
// API.
|
||||
virtual QString humanDriverType() const = 0;
|
||||
virtual QString qtDriverCode() const = 0;
|
||||
virtual DriverType driverType() const = 0;
|
||||
virtual bool vacuumDatabase() = 0;
|
||||
virtual bool saveDatabase() = 0;
|
||||
virtual void backupDatabase(const QString& backup_folder, const QString& backup_name) = 0;
|
||||
virtual bool initiateRestoration(const QString& database_package_file) = 0;
|
||||
virtual bool finishRestoration() = 0;
|
||||
virtual qint64 databaseDataSize() = 0;
|
||||
virtual QSqlDatabase connection(const QString& connection_name,
|
||||
DatabaseDriver::DesiredStorageType desired_type = DatabaseDriver::DesiredStorageType::FromSettings) = 0;
|
||||
|
||||
protected:
|
||||
QStringList prepareScript(const QString& base_sql_folder,
|
||||
const QString& sql_file,
|
||||
const QString& database_name = {});
|
||||
|
||||
};
|
||||
|
||||
#endif // DATABASEDRIVER_H
|
81
src/librssguard/database/databasefactory.cpp
Normal file
81
src/librssguard/database/databasefactory.cpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#include "database/databasefactory.h"
|
||||
|
||||
#include "3rd-party/boolinq/boolinq.h"
|
||||
#include "database/sqlitedriver.h"
|
||||
#include "gui/messagebox.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/iofactory.h"
|
||||
#include "miscellaneous/textfactory.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QSqlError>
|
||||
#include <QSqlQuery>
|
||||
#include <QVariant>
|
||||
|
||||
DatabaseFactory::DatabaseFactory(QObject* parent)
|
||||
: QObject(parent), m_dbDriver(nullptr) {
|
||||
determineDriver();
|
||||
}
|
||||
|
||||
/*else if (m_activeDatabaseDriver == DatabaseDriver::UsedDriver::MYSQL) {
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className(),
|
||||
DatabaseDriver::DesiredType::FromSettings);
|
||||
QSqlQuery query(database);
|
||||
|
||||
query.prepare("SELECT Round(Sum(data_length + index_length), 1) "
|
||||
"FROM information_schema.tables "
|
||||
"WHERE table_schema = :db "
|
||||
"GROUP BY table_schema;");
|
||||
query.bindValue(QSL(":db"), database.databaseName());
|
||||
|
||||
if (query.exec() && query.next()) {
|
||||
return query.value(0).value<qint64>();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
void DatabaseFactory::removeConnection(const QString& connection_name) {
|
||||
qDebugNN << LOGSEC_DB << "Removing database connection '" << connection_name << "'.";
|
||||
QSqlDatabase::removeDatabase(connection_name);
|
||||
}
|
||||
|
||||
void DatabaseFactory::determineDriver() {
|
||||
m_allDbDrivers = {
|
||||
new SqliteDriver(qApp->settings()->value(GROUP(Database), SETTING(Database::UseInMemory)).toBool(), this)
|
||||
};
|
||||
|
||||
if (QSqlDatabase::isDriverAvailable(APP_DB_MYSQL_DRIVER)) {
|
||||
//m_allDbDrivers.append(new MariaDbDriver(this));
|
||||
}
|
||||
|
||||
const QString db_driver = qApp->settings()->value(GROUP(Database), SETTING(Database::ActiveDriver)).toString();
|
||||
|
||||
m_dbDriver = boolinq::from(m_allDbDrivers).firstOrDefault([db_driver](DatabaseDriver* driv) {
|
||||
return QString::compare(driv->qtDriverCode(), db_driver, Qt::CaseSensitivity::CaseInsensitive) == 0;
|
||||
});
|
||||
|
||||
if (m_dbDriver == nullptr) {
|
||||
qFatal("DB driver for '%s' was not found.", qPrintable(db_driver));
|
||||
}
|
||||
}
|
||||
|
||||
DatabaseDriver* DatabaseFactory::driver() const {
|
||||
return m_dbDriver;
|
||||
}
|
||||
|
||||
DatabaseDriver* DatabaseFactory::driverForType(DatabaseDriver::DriverType d) const {
|
||||
return boolinq::from(m_allDbDrivers).firstOrDefault([d](DatabaseDriver* driv) {
|
||||
return driv->driverType() == d;
|
||||
});
|
||||
}
|
||||
|
||||
DatabaseDriver::DriverType DatabaseFactory::activeDatabaseDriver() const {
|
||||
return m_dbDriver->driverType();
|
||||
}
|
47
src/librssguard/database/databasefactory.h
Normal file
47
src/librssguard/database/databasefactory.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#ifndef DATABASEFACTORY_H
|
||||
#define DATABASEFACTORY_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "database/databasedriver.h"
|
||||
|
||||
#include <QSqlDatabase>
|
||||
|
||||
class DatabaseFactory : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
// Describes possible MySQL-specific errors.
|
||||
enum class MySQLError {
|
||||
Ok = 0,
|
||||
UnknownError = 1,
|
||||
AccessDenied = 1045,
|
||||
UnknownDatabase = 1049,
|
||||
ConnectionError = 2002,
|
||||
CantConnect = 2003,
|
||||
UnknownHost = 2005
|
||||
};
|
||||
|
||||
// Constructor.
|
||||
explicit DatabaseFactory(QObject* parent = nullptr);
|
||||
|
||||
// Removes connection.
|
||||
void removeConnection(const QString& connection_name = {});
|
||||
|
||||
// Returns identification of currently active database driver.
|
||||
DatabaseDriver::DriverType activeDatabaseDriver() const;
|
||||
|
||||
DatabaseDriver* driver() const;
|
||||
DatabaseDriver* driverForType(DatabaseDriver::DriverType d) const;
|
||||
|
||||
private:
|
||||
void determineDriver();
|
||||
|
||||
QList<DatabaseDriver*> m_allDbDrivers;
|
||||
DatabaseDriver* m_dbDriver;
|
||||
};
|
||||
|
||||
#endif // DATABASEFACTORY_H
|
|
@ -1,6 +1,6 @@
|
|||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
|
||||
#include "3rd-party/boolinq/boolinq.h"
|
||||
#include "exceptions/applicationexception.h"
|
||||
|
@ -947,10 +947,10 @@ int DatabaseQueries::updateMessages(QSqlDatabase db,
|
|||
"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;");
|
||||
|
||||
if (use_transactions && !query_begin_transaction.exec(qApp->database()->obtainBeginTransactionSql())) {
|
||||
if (use_transactions && !db.transaction()) {
|
||||
qCriticalNN << LOGSEC_DB
|
||||
<< "Transaction start for message downloader failed: '"
|
||||
<< query_begin_transaction.lastError().text() << "'.";
|
||||
<< "Transaction start for message downloader failed:"
|
||||
<< QUOTE_W_SPACE_DOT(query_begin_transaction.lastError().text());
|
||||
return updated_messages;
|
||||
}
|
||||
|
||||
|
@ -1220,9 +1220,8 @@ int DatabaseQueries::updateMessages(QSqlDatabase db,
|
|||
|
||||
if (use_transactions && !db.commit()) {
|
||||
qCriticalNN << LOGSEC_DB
|
||||
<< "Transaction commit for message downloader failed: '"
|
||||
<< db.lastError().text()
|
||||
<< "'.";
|
||||
<< "Transaction commit for message downloader failed:"
|
||||
<< QUOTE_W_SPACE_DOT(db.lastError().text());
|
||||
db.rollback();
|
||||
|
||||
if (ok != nullptr) {
|
|
@ -319,7 +319,7 @@ Assignment DatabaseQueries::getFeeds(const QSqlDatabase& db,
|
|||
|
||||
template<typename Categ, typename Fee>
|
||||
void DatabaseQueries::loadFromDatabase(ServiceRoot* root) {
|
||||
QSqlDatabase database = qApp->database()->connection(root->metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(root->metaObject()->className());
|
||||
Assignment categories = DatabaseQueries::getCategories<Categ>(database, root->accountId());
|
||||
Assignment feeds = DatabaseQueries::getFeeds<Fee>(database, qApp->feedReader()->messageFilters(), root->accountId());
|
||||
auto labels = DatabaseQueries::getLabelsForAccount(database, root->accountId());
|
492
src/librssguard/database/sqlitedriver.cpp
Executable file
492
src/librssguard/database/sqlitedriver.cpp
Executable file
|
@ -0,0 +1,492 @@
|
|||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#include "database/sqlitedriver.h"
|
||||
|
||||
#include "exceptions/applicationexception.h"
|
||||
#include "exceptions/ioexception.h"
|
||||
#include "miscellaneous/application.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QSqlError>
|
||||
#include <QSqlQuery>
|
||||
|
||||
SqliteDriver::SqliteDriver(bool in_memory, QObject* parent)
|
||||
: DatabaseDriver(parent), m_inMemoryDatabase(in_memory),
|
||||
m_databaseFilePath(qApp->userDataFolder() + QDir::separator() + QString(APP_DB_SQLITE_PATH)),
|
||||
m_fileBasedDatabaseInitialized(false),
|
||||
m_inMemoryDatabaseInitialized(false) {}
|
||||
|
||||
DatabaseDriver::DriverType SqliteDriver::driverType() const {
|
||||
return DriverType::SQLite;
|
||||
}
|
||||
|
||||
bool SqliteDriver::vacuumDatabase() {
|
||||
QSqlDatabase database;
|
||||
|
||||
saveDatabase();
|
||||
database = connection(objectName(), DatabaseDriver::DesiredStorageType::StrictlyFileBased);
|
||||
|
||||
QSqlQuery query_vacuum(database);
|
||||
|
||||
return query_vacuum.exec(QSL("VACUUM"));
|
||||
}
|
||||
|
||||
bool SqliteDriver::saveDatabase() {
|
||||
if (!m_inMemoryDatabase) {
|
||||
return true;
|
||||
}
|
||||
|
||||
qDebugNN << LOGSEC_DB << "Saving in-memory working database back to persistent file-based storage.";
|
||||
|
||||
QSqlDatabase database = connection(QSL("SaveFromMemory"), DatabaseDriver::DesiredStorageType::StrictlyInMemory);
|
||||
QSqlDatabase file_database = connection(QSL("SaveToFile"), DatabaseDriver::DesiredStorageType::StrictlyFileBased);
|
||||
QSqlQuery copy_contents(database);
|
||||
|
||||
// Attach database.
|
||||
copy_contents.exec(QString(QSL("ATTACH DATABASE '%1' AS 'storage';")).arg(file_database.databaseName()));
|
||||
|
||||
// Copy all stuff.
|
||||
QStringList tables;
|
||||
|
||||
if (copy_contents.exec(QSL("SELECT name FROM storage.sqlite_master WHERE type='table';"))) {
|
||||
while (copy_contents.next()) {
|
||||
tables.append(copy_contents.value(0).toString());
|
||||
}
|
||||
}
|
||||
else {
|
||||
qFatal("Cannot obtain list of table names from file-base SQLite database.");
|
||||
}
|
||||
|
||||
for (const QString& table : tables) {
|
||||
if (copy_contents.exec(QString(QSL("DELETE FROM storage.%1;")).arg(table))) {
|
||||
qDebugNN << LOGSEC_DB << "Cleaning old data from 'storage." << table << "'.";
|
||||
}
|
||||
else {
|
||||
qCriticalNN << LOGSEC_DB << "Failed to clean old data from 'storage."
|
||||
<< table << "', error: '"
|
||||
<< copy_contents.lastError().text() << "'.";
|
||||
}
|
||||
|
||||
if (copy_contents.exec(QString(QSL("INSERT INTO storage.%1 SELECT * FROM main.%1;")).arg(table))) {
|
||||
qDebugNN << LOGSEC_DB << "Copying new data into 'main."
|
||||
<< table << "'.";
|
||||
}
|
||||
else {
|
||||
qCriticalNN << LOGSEC_DB
|
||||
<< "Failed to copy new data to 'main."
|
||||
<< table
|
||||
<< "', error: '"
|
||||
<< copy_contents.lastError().text()
|
||||
<< "'.";
|
||||
}
|
||||
}
|
||||
|
||||
// Detach database and finish.
|
||||
if (copy_contents.exec(QSL("DETACH 'storage'"))) {
|
||||
qDebugNN << LOGSEC_DB << "Detaching persistent SQLite file.";
|
||||
}
|
||||
else {
|
||||
qCriticalNN << LOGSEC_DB
|
||||
<< "Failed to detach SQLite file, error: '"
|
||||
<< copy_contents.lastError().text()
|
||||
<< "'.";
|
||||
}
|
||||
|
||||
copy_contents.finish();
|
||||
return true;
|
||||
}
|
||||
|
||||
QSqlDatabase SqliteDriver::connection(const QString& connection_name, DesiredStorageType desired_type) {
|
||||
if (desired_type == DatabaseDriver::DesiredStorageType::StrictlyInMemory ||
|
||||
(desired_type == DatabaseDriver::DesiredStorageType::FromSettings && m_inMemoryDatabase)) {
|
||||
// We request in-memory database (either user explicitly
|
||||
// needs in-memory database or it was enabled in the settings).
|
||||
if (!m_inMemoryDatabaseInitialized) {
|
||||
// It is not initialized yet.
|
||||
return initializeInMemoryDatabase();
|
||||
}
|
||||
else {
|
||||
QSqlDatabase database;
|
||||
|
||||
if (QSqlDatabase::contains(connection_name)) {
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "SQLite connection '"
|
||||
<< connection_name
|
||||
<< "' is already active.";
|
||||
|
||||
// This database connection was added previously, no need to
|
||||
// setup its properties.
|
||||
database = QSqlDatabase::database(connection_name);
|
||||
}
|
||||
else {
|
||||
database = QSqlDatabase::addDatabase(APP_DB_SQLITE_DRIVER, connection_name);
|
||||
database.setConnectOptions(QSL("QSQLITE_OPEN_URI;QSQLITE_ENABLE_SHARED_CACHE"));
|
||||
database.setDatabaseName(QSL("file::memory:"));
|
||||
}
|
||||
|
||||
if (!database.isOpen() && !database.open()) {
|
||||
qFatal("In-memory SQLite database was NOT opened. Delivered error message: '%s'.",
|
||||
qPrintable(database.lastError().text()));
|
||||
}
|
||||
else {
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "In-memory SQLite database connection '"
|
||||
<< connection_name
|
||||
<< "' seems to be established.";
|
||||
}
|
||||
|
||||
return database;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// We request file-based database.
|
||||
if (!m_fileBasedDatabaseInitialized) {
|
||||
// File-based database is not yet initialised.
|
||||
return initializeFileBasedDatabase(connection_name);
|
||||
}
|
||||
else {
|
||||
QSqlDatabase database;
|
||||
|
||||
if (QSqlDatabase::contains(connection_name)) {
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "SQLite connection '"
|
||||
<< connection_name
|
||||
<< "' is already active.";
|
||||
|
||||
// This database connection was added previously, no need to
|
||||
// setup its properties.
|
||||
database = QSqlDatabase::database(connection_name);
|
||||
}
|
||||
else {
|
||||
// Database connection with this name does not exist
|
||||
// yet, add it and set it up.
|
||||
database = QSqlDatabase::addDatabase(APP_DB_SQLITE_DRIVER, connection_name);
|
||||
const QDir db_path(m_databaseFilePath);
|
||||
QFile db_file(db_path.absoluteFilePath(APP_DB_SQLITE_FILE));
|
||||
|
||||
// Setup database file path.
|
||||
database.setDatabaseName(db_file.fileName());
|
||||
}
|
||||
|
||||
if (!database.isOpen() && !database.open()) {
|
||||
qFatal("File-based SQLite database was NOT opened. Delivered error message: '%s'.",
|
||||
qPrintable(database.lastError().text()));
|
||||
}
|
||||
else {
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "File-based SQLite database connection '"
|
||||
<< connection_name
|
||||
<< "' to file '"
|
||||
<< QDir::toNativeSeparators(database.databaseName())
|
||||
<< "' seems to be established.";
|
||||
}
|
||||
|
||||
return database;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SqliteDriver::initiateRestoration(const QString& database_package_file) {
|
||||
return IOFactory::copyFile(database_package_file,
|
||||
m_databaseFilePath + QDir::separator() +
|
||||
BACKUP_NAME_DATABASE + BACKUP_SUFFIX_DATABASE);
|
||||
}
|
||||
|
||||
bool SqliteDriver::finishRestoration() {
|
||||
const QString backup_database_file = m_databaseFilePath + QDir::separator() + BACKUP_NAME_DATABASE + BACKUP_SUFFIX_DATABASE;
|
||||
|
||||
if (QFile::exists(backup_database_file)) {
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "Backup database file '"
|
||||
<< QDir::toNativeSeparators(backup_database_file)
|
||||
<< "' was detected. Restoring it.";
|
||||
|
||||
if (IOFactory::copyFile(backup_database_file, m_databaseFilePath + QDir::separator() + APP_DB_SQLITE_FILE)) {
|
||||
QFile::remove(backup_database_file);
|
||||
qDebugNN << LOGSEC_DB << "Database file was restored successully.";
|
||||
}
|
||||
else {
|
||||
qCriticalNN << LOGSEC_DB
|
||||
<< "Database file was NOT restored due to error when copying the file.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QSqlDatabase SqliteDriver::initializeInMemoryDatabase() {
|
||||
QSqlDatabase database = QSqlDatabase::addDatabase(APP_DB_SQLITE_DRIVER);
|
||||
|
||||
database.setConnectOptions(QSL("QSQLITE_OPEN_URI;QSQLITE_ENABLE_SHARED_CACHE"));
|
||||
database.setDatabaseName(QSL("file::memory:"));
|
||||
|
||||
if (!database.open()) {
|
||||
qFatal("In-memory SQLite database was NOT opened. Delivered error message: '%s'",
|
||||
qPrintable(database.lastError().text()));
|
||||
}
|
||||
else {
|
||||
QSqlQuery query_db(database);
|
||||
|
||||
query_db.setForwardOnly(true);
|
||||
setPragmas(query_db);
|
||||
|
||||
// Sample query which checks for existence of tables.
|
||||
query_db.exec(QSL("SELECT inf_value FROM Information WHERE inf_key = 'schema_version'"));
|
||||
|
||||
if (query_db.lastError().isValid()) {
|
||||
qWarningNN << LOGSEC_DB << "Error occurred. In-memory SQLite database is not initialized. Initializing now.";
|
||||
|
||||
try {
|
||||
const QStringList statements = prepareScript(APP_SQL_PATH, APP_DB_SQLITE_INIT);
|
||||
|
||||
for (const QString& statement : statements) {
|
||||
query_db.exec(statement);
|
||||
|
||||
if (query_db.lastError().isValid()) {
|
||||
throw ApplicationException(query_db.lastError().text());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const ApplicationException& ex) {
|
||||
qFatal("Error when running SQL scripts: %s.", qPrintable(ex.message()));
|
||||
}
|
||||
|
||||
qDebugNN << LOGSEC_DB << "In-memory SQLite database backend should be ready now.";
|
||||
}
|
||||
else {
|
||||
query_db.next();
|
||||
qDebugNN << LOGSEC_DB << "In-memory SQLite database connection seems to be established.";
|
||||
qDebugNN << LOGSEC_DB << "In-memory SQLite database has version '"
|
||||
<< query_db.value(0).toString()
|
||||
<< "'.";
|
||||
}
|
||||
|
||||
// Loading messages from file-based database.
|
||||
QSqlDatabase file_database = connection(objectName(), DatabaseDriver::DesiredStorageType::StrictlyFileBased);
|
||||
QSqlQuery copy_contents(database);
|
||||
|
||||
// Attach database.
|
||||
copy_contents.exec(QString("ATTACH DATABASE '%1' AS 'storage';").arg(file_database.databaseName()));
|
||||
|
||||
// Copy all stuff.
|
||||
QStringList tables;
|
||||
|
||||
if (copy_contents.exec(QSL("SELECT name FROM storage.sqlite_master WHERE type='table';"))) {
|
||||
while (copy_contents.next()) {
|
||||
tables.append(copy_contents.value(0).toString());
|
||||
}
|
||||
}
|
||||
else {
|
||||
qFatal("Cannot obtain list of table names from file-base SQLite database.");
|
||||
}
|
||||
|
||||
for (const QString& table : tables) {
|
||||
copy_contents.exec(QString("INSERT INTO main.%1 SELECT * FROM storage.%1;").arg(table));
|
||||
}
|
||||
|
||||
qDebugNN << LOGSEC_DB << "Copying data from file-based database into working in-memory database.";
|
||||
|
||||
// Detach database and finish.
|
||||
copy_contents.exec(QSL("DETACH 'storage'"));
|
||||
copy_contents.finish();
|
||||
query_db.finish();
|
||||
}
|
||||
|
||||
// Everything is initialized now.
|
||||
m_inMemoryDatabaseInitialized = true;
|
||||
return database;
|
||||
}
|
||||
|
||||
QSqlDatabase SqliteDriver::initializeFileBasedDatabase(const QString& connection_name) {
|
||||
finishRestoration();
|
||||
|
||||
// Prepare file paths.
|
||||
const QDir db_path(m_databaseFilePath);
|
||||
QFile db_file(db_path.absoluteFilePath(APP_DB_SQLITE_FILE));
|
||||
|
||||
// Check if database directory exists.
|
||||
if (!db_path.exists()) {
|
||||
if (!db_path.mkpath(db_path.absolutePath())) {
|
||||
// Failure when create database file path.
|
||||
qFatal("Directory '%s' for SQLite database file '%s' was NOT created."
|
||||
"This is HUGE problem.",
|
||||
qPrintable(db_path.absolutePath()),
|
||||
qPrintable(db_file.symLinkTarget()));
|
||||
}
|
||||
}
|
||||
|
||||
// Folders are created. Create new QSQLDatabase object.
|
||||
QSqlDatabase database;
|
||||
|
||||
database = QSqlDatabase::addDatabase(APP_DB_SQLITE_DRIVER, connection_name);
|
||||
database.setDatabaseName(db_file.fileName());
|
||||
|
||||
if (!database.open()) {
|
||||
qFatal("File-based SQLite database was NOT opened. Delivered error message: '%s'",
|
||||
qPrintable(database.lastError().text()));
|
||||
}
|
||||
else {
|
||||
QSqlQuery query_db(database);
|
||||
|
||||
query_db.setForwardOnly(true);
|
||||
setPragmas(query_db);
|
||||
|
||||
// Sample query which checks for existence of tables.
|
||||
if (!query_db.exec(QSL("SELECT inf_value FROM Information WHERE inf_key = 'schema_version'"))) {
|
||||
qWarningNN << LOGSEC_DB << "Error occurred. File-based SQLite database is not initialized. Initializing now.";
|
||||
|
||||
try {
|
||||
const QStringList statements = prepareScript(APP_SQL_PATH, APP_DB_SQLITE_INIT);
|
||||
|
||||
for (const QString& statement : statements) {
|
||||
query_db.exec(statement);
|
||||
|
||||
if (query_db.lastError().isValid()) {
|
||||
throw ApplicationException(query_db.lastError().text());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const ApplicationException& ex) {
|
||||
qFatal("Error when running SQL scripts: %s.", qPrintable(ex.message()));
|
||||
}
|
||||
|
||||
query_db.finish();
|
||||
qDebugNN << LOGSEC_DB << "File-based SQLite database backend should be ready now.";
|
||||
}
|
||||
else {
|
||||
query_db.next();
|
||||
const QString installed_db_schema = query_db.value(0).toString();
|
||||
|
||||
query_db.finish();
|
||||
|
||||
if (installed_db_schema.toInt() < QString(APP_DB_SCHEMA_VERSION).toInt()) {
|
||||
if (updateDatabaseSchema(database, installed_db_schema)) {
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "Database schema was updated from '"
|
||||
<< installed_db_schema
|
||||
<< "' to '"
|
||||
<< APP_DB_SCHEMA_VERSION
|
||||
<< "' successully or it is already up to date.";
|
||||
}
|
||||
else {
|
||||
qFatal("Database schema was not updated from '%s' to '%s' successully.",
|
||||
qPrintable(installed_db_schema),
|
||||
APP_DB_SCHEMA_VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "File-based SQLite database connection '"
|
||||
<< connection_name
|
||||
<< "' to file '"
|
||||
<< QDir::toNativeSeparators(database.databaseName())
|
||||
<< "' seems to be established.";
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "File-based SQLite database has version '"
|
||||
<< installed_db_schema
|
||||
<< "'.";
|
||||
}
|
||||
}
|
||||
|
||||
// Everything is initialized now.
|
||||
m_fileBasedDatabaseInitialized = true;
|
||||
return database;
|
||||
}
|
||||
|
||||
QString SqliteDriver::databaseFilePath() const {
|
||||
return m_databaseFilePath + QDir::separator() + APP_DB_SQLITE_FILE;
|
||||
}
|
||||
|
||||
bool SqliteDriver::updateDatabaseSchema(const QSqlDatabase& database, const QString& source_db_schema_version) {
|
||||
int working_version = QString(source_db_schema_version).remove('.').toInt();
|
||||
const int current_version = QString(APP_DB_SCHEMA_VERSION).remove('.').toInt();
|
||||
|
||||
// Now, it would be good to create backup of SQLite DB file.
|
||||
if (IOFactory::copyFile(databaseFilePath(), databaseFilePath() + ".bak")) {
|
||||
qDebugNN << LOGSEC_DB << "Creating backup of SQLite DB file.";
|
||||
}
|
||||
else {
|
||||
qFatal("Creation of backup SQLite DB file failed.");
|
||||
}
|
||||
|
||||
while (working_version != current_version) {
|
||||
try {
|
||||
const QStringList statements = prepareScript(APP_SQL_PATH,
|
||||
QString(APP_DB_UPDATE_FILE_PATTERN).arg(QSL("sqlite"),
|
||||
QString::number(working_version),
|
||||
QString::number(working_version + 1)));
|
||||
|
||||
for (const QString& statement : statements) {
|
||||
QSqlQuery query = database.exec(statement);
|
||||
|
||||
if (!query.exec(statement) && query.lastError().isValid()) {
|
||||
throw ApplicationException(query.lastError().text());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const ApplicationException& ex) {
|
||||
qFatal("Error when running SQL scripts: %s.", qPrintable(ex.message()));
|
||||
}
|
||||
|
||||
// Increment the version.
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "Updating database schema:"
|
||||
<< QUOTE_W_SPACE(working_version)
|
||||
<< "->"
|
||||
<< QUOTE_W_SPACE_DOT(working_version + 1);
|
||||
|
||||
working_version++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SqliteDriver::setPragmas(QSqlQuery& query) {
|
||||
query.exec(QSL("PRAGMA encoding = \"UTF-8\""));
|
||||
query.exec(QSL("PRAGMA synchronous = OFF"));
|
||||
query.exec(QSL("PRAGMA journal_mode = MEMORY"));
|
||||
query.exec(QSL("PRAGMA page_size = 4096"));
|
||||
query.exec(QSL("PRAGMA cache_size = 16384"));
|
||||
query.exec(QSL("PRAGMA count_changes = OFF"));
|
||||
query.exec(QSL("PRAGMA temp_store = MEMORY"));
|
||||
}
|
||||
|
||||
qint64 SqliteDriver::databaseDataSize() {
|
||||
QSqlDatabase database = connection(metaObject()->className(), DatabaseDriver::DesiredStorageType::FromSettings);
|
||||
qint64 result = 1;
|
||||
QSqlQuery query(database);
|
||||
|
||||
if (query.exec(QSL("PRAGMA page_count;"))) {
|
||||
query.next();
|
||||
result *= query.value(0).value<qint64>();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (query.exec(QSL("PRAGMA page_size;"))) {
|
||||
query.next();
|
||||
result *= query.value(0).value<qint64>();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QString SqliteDriver::humanDriverType() const {
|
||||
return tr("SQLite (embedded database)");
|
||||
}
|
||||
|
||||
QString SqliteDriver::qtDriverCode() const {
|
||||
return APP_DB_SQLITE_DRIVER;
|
||||
}
|
||||
|
||||
void SqliteDriver::backupDatabase(const QString& backup_folder, const QString& backup_name) {
|
||||
if (!IOFactory::copyFile(databaseFilePath(),
|
||||
backup_folder + QDir::separator() + backup_name + BACKUP_SUFFIX_DATABASE)) {
|
||||
throw ApplicationException(tr("Database file not copied to output directory successfully."));
|
||||
}
|
||||
}
|
38
src/librssguard/database/sqlitedriver.h
Executable file
38
src/librssguard/database/sqlitedriver.h
Executable file
|
@ -0,0 +1,38 @@
|
|||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#ifndef SQLITEDRIVER_H
|
||||
#define SQLITEDRIVER_H
|
||||
|
||||
#include "database/databasedriver.h"
|
||||
|
||||
class SqliteDriver : public DatabaseDriver {
|
||||
public:
|
||||
explicit SqliteDriver(bool in_memory, QObject* parent = nullptr);
|
||||
|
||||
virtual DriverType driverType() const;
|
||||
virtual bool vacuumDatabase();
|
||||
virtual bool saveDatabase();
|
||||
virtual bool initiateRestoration(const QString& database_package_file);
|
||||
virtual bool finishRestoration();
|
||||
virtual QSqlDatabase connection(const QString& connection_name,
|
||||
DatabaseDriver::DesiredStorageType desired_type = DatabaseDriver::DesiredStorageType::FromSettings);
|
||||
virtual qint64 databaseDataSize();
|
||||
virtual QString humanDriverType() const;
|
||||
virtual QString qtDriverCode() const;
|
||||
virtual void backupDatabase(const QString& backup_folder, const QString& backup_name);
|
||||
|
||||
private:
|
||||
QSqlDatabase initializeInMemoryDatabase();
|
||||
QSqlDatabase initializeFileBasedDatabase(const QString& connection_name);
|
||||
bool updateDatabaseSchema(const QSqlDatabase& database, const QString& source_db_schema_version);
|
||||
void setPragmas(QSqlQuery& query);
|
||||
QString databaseFilePath() const;
|
||||
|
||||
private:
|
||||
bool m_inMemoryDatabase;
|
||||
QString m_databaseFilePath;
|
||||
bool m_fileBasedDatabaseInitialized;
|
||||
bool m_inMemoryDatabaseInitialized;
|
||||
};
|
||||
|
||||
#endif // SQLITEDRIVER_H
|
|
@ -155,6 +155,7 @@
|
|||
#define APP_DB_SCHEMA_VERSION "1"
|
||||
#define APP_DB_UPDATE_FILE_PATTERN "db_update_%1_%2_%3.sql"
|
||||
#define APP_DB_COMMENT_SPLIT "-- !\n"
|
||||
#define APP_DB_INCLUDE_PLACEHOLDER "!!"
|
||||
#define APP_DB_NAME_PLACEHOLDER "##"
|
||||
|
||||
#define APP_CFG_PATH "config"
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#ifndef TYPEDEFS_H
|
||||
#define TYPEDEFS_H
|
||||
|
||||
|
|
|
@ -28,8 +28,7 @@ FormBackupDatabaseSettings::FormBackupDatabaseSettings(QWidget* parent) : QDialo
|
|||
QDateTime::currentDateTime().toString(QSL("yyyyMMddHHmm")));
|
||||
m_ui->m_lblResult->setStatus(WidgetWithStatus::StatusType::Warning, tr("No operation executed yet."), tr("No operation executed yet."));
|
||||
|
||||
if (qApp->database()->activeDatabaseDriver() != DatabaseFactory::UsedDriver::SQLITE &&
|
||||
qApp->database()->activeDatabaseDriver() != DatabaseFactory::UsedDriver::SQLITE_MEMORY) {
|
||||
if (qApp->database()->activeDatabaseDriver() != DatabaseDriver::DriverType::SQLite) {
|
||||
m_ui->m_checkBackupDatabase->setDisabled(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
#include "gui/dialogs/formdatabasecleanup.h"
|
||||
|
||||
#include "database/databasefactory.h"
|
||||
#include "gui/guiutilities.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasefactory.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
|
||||
#include <QCloseEvent>
|
||||
|
@ -95,12 +95,10 @@ void FormDatabaseCleanup::onPurgeFinished(bool finished) {
|
|||
}
|
||||
|
||||
void FormDatabaseCleanup::loadDatabaseInfo() {
|
||||
qint64 file_size = qApp->database()->getDatabaseFileSize();
|
||||
qint64 data_size = qApp->database()->getDatabaseDataSize();
|
||||
QString file_size_str = file_size > 0 ? QString::number(file_size / 1000000.0) + QL1S(" MB") : tr("unknown");
|
||||
qint64 data_size = qApp->database()->driver()->databaseDataSize();
|
||||
QString data_size_str = data_size > 0 ? QString::number(data_size / 1000000.0) + QL1S(" MB") : tr("unknown");
|
||||
|
||||
m_ui->m_txtFileSize->setText(tr("file: %1, data: %2").arg(file_size_str, data_size_str));
|
||||
m_ui->m_txtDatabaseType->setText(qApp->database()->humanDriverName(qApp->database()->activeDatabaseDriver()));
|
||||
m_ui->m_txtFileSize->setText(data_size_str);
|
||||
m_ui->m_txtDatabaseType->setText(qApp->database()->driver()->humanDriverType());
|
||||
m_ui->m_checkShrink->setChecked(m_ui->m_checkShrink->isEnabled());
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include "ui_formdatabasecleanup.h"
|
||||
|
||||
#include "miscellaneous/databasecleaner.h"
|
||||
#include "database/databasecleaner.h"
|
||||
|
||||
class FormDatabaseCleanup : public QDialog {
|
||||
Q_OBJECT
|
||||
|
|
|
@ -99,7 +99,7 @@
|
|||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="m_lblFileSize">
|
||||
<property name="text">
|
||||
<string>Database file size</string>
|
||||
<string>Total data size</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>m_txtFileSize</cstring>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "gui/systemtrayicon.h"
|
||||
#include "gui/tabbar.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasefactory.h"
|
||||
#include "database/databasefactory.h"
|
||||
#include "miscellaneous/feedreader.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/mutex.h"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#include "gui/guiutilities.h"
|
||||
#include "gui/messagebox.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/feedreader.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "network-web/webfactory.h"
|
||||
|
@ -216,7 +216,7 @@ void FormMessageFiltersManager::testFilter() {
|
|||
// Perform per-message filtering.
|
||||
auto* selected_fd_cat = selectedCategoryFeed();
|
||||
QJSEngine filter_engine;
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
MessageObject msg_obj(&database,
|
||||
selected_fd_cat->kind() == RootItem::Kind::Feed
|
||||
? selected_fd_cat->customId()
|
||||
|
@ -292,7 +292,7 @@ void FormMessageFiltersManager::displayMessagesOfFeed() {
|
|||
void FormMessageFiltersManager::processCheckedFeeds() {
|
||||
QList<RootItem*> checked = m_feedsModel->sourceModel()->checkedItems();
|
||||
auto* fltr = selectedFilter();
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
for (RootItem* it : checked) {
|
||||
if (it->kind() == RootItem::Kind::Feed) {
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
#include "gui/messagesview.h"
|
||||
#include "gui/statusbar.h"
|
||||
#include "gui/systemtrayicon.h"
|
||||
#include "miscellaneous/databasecleaner.h"
|
||||
#include "miscellaneous/databasefactory.h"
|
||||
#include "database/databasecleaner.h"
|
||||
#include "database/databasefactory.h"
|
||||
#include "miscellaneous/feedreader.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/mutex.h"
|
||||
|
|
|
@ -81,7 +81,7 @@ QStringList FeedsToolBar::defaultActions() const {
|
|||
#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
|
||||
Qt::SplitBehaviorFlags::SkipEmptyParts);
|
||||
#else
|
||||
QString::SkipEmptyParts);
|
||||
QString::SplitBehavior::SkipEmptyParts);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -91,6 +91,6 @@ QStringList FeedsToolBar::savedActions() const {
|
|||
#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
|
||||
Qt::SplitBehaviorFlags::SkipEmptyParts);
|
||||
#else
|
||||
QString::SkipEmptyParts);
|
||||
QString::SplitBehavior::SkipEmptyParts);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "3rd-party/boolinq/boolinq.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
|
@ -22,7 +22,7 @@ LabelsMenu::LabelsMenu(const QList<Message>& messages, const QList<Label*>& labe
|
|||
addAction(act_not_labels);
|
||||
}
|
||||
else {
|
||||
QSqlDatabase db = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase db = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
for (Label* label: boolinq::from(labels).orderBy([](const Label* label) {
|
||||
return label->title().toLower();
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
|
||||
#include "gui/messagepreviewer.h"
|
||||
|
||||
#include "database/databasequeries.h"
|
||||
#include "gui/dialogs/formmain.h"
|
||||
#include "gui/messagebox.h"
|
||||
#include "gui/plaintoolbutton.h"
|
||||
#include "gui/searchtextwidget.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "network-web/webfactory.h"
|
||||
#include "services/abstract/label.h"
|
||||
#include "services/abstract/labelsnode.h"
|
||||
|
@ -165,7 +165,8 @@ void MessagePreviewer::markMessageAsReadUnread(RootItem::ReadStatus read) {
|
|||
if (m_root->getParentServiceRoot()->onBeforeSetMessagesRead(m_root.data(),
|
||||
QList<Message>() << m_message,
|
||||
read)) {
|
||||
DatabaseQueries::markMessagesReadUnread(qApp->database()->connection(objectName(), DatabaseFactory::DesiredType::FromSettings),
|
||||
DatabaseQueries::markMessagesReadUnread(qApp->database()->driver()->connection(objectName(),
|
||||
DatabaseDriver::DesiredStorageType::FromSettings),
|
||||
QStringList() << QString::number(m_message.m_id),
|
||||
read);
|
||||
m_root->getParentServiceRoot()->onAfterSetMessagesRead(m_root.data(),
|
||||
|
@ -188,7 +189,7 @@ void MessagePreviewer::switchMessageImportance(bool checked) {
|
|||
m_isImportant
|
||||
? RootItem::Importance::NotImportant
|
||||
: RootItem::Importance::Important))) {
|
||||
DatabaseQueries::switchMessagesImportance(qApp->database()->connection(objectName(), DatabaseFactory::DesiredType::FromSettings),
|
||||
DatabaseQueries::switchMessagesImportance(qApp->database()->driver()->connection(objectName(), DatabaseDriver::DesiredStorageType::FromSettings),
|
||||
QStringList() << QString::number(m_message.m_id));
|
||||
m_root->getParentServiceRoot()->onAfterSwitchMessageImportance(m_root.data(),
|
||||
QList<ImportanceChange>()
|
||||
|
@ -229,7 +230,7 @@ void MessagePreviewer::updateLabels(bool only_clear) {
|
|||
|
||||
if (m_root.data() != nullptr && !m_root.data()->getParentServiceRoot()->labelsNode()->labels().isEmpty()) {
|
||||
m_separator = m_toolBar->addSeparator();
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
for (auto* label : m_root.data()->getParentServiceRoot()->labelsNode()->labels()) {
|
||||
LabelButton* btn_label = new LabelButton(this);
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
#include "gui/settings/settingsdatabase.h"
|
||||
|
||||
#include "database/databasefactory.h"
|
||||
#include "definitions/definitions.h"
|
||||
#include "gui/guiutilities.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasefactory.h"
|
||||
|
||||
SettingsDatabase::SettingsDatabase(Settings* settings, QWidget* parent)
|
||||
: SettingsPanel(settings, parent), m_ui(new Ui::SettingsDatabase) {
|
||||
|
@ -44,12 +44,15 @@ SettingsDatabase::~SettingsDatabase() {
|
|||
}
|
||||
|
||||
void SettingsDatabase::mysqlTestConnection() {
|
||||
const DatabaseFactory::MySQLError error_code = qApp->database()->mysqlTestConnection(m_ui->m_txtMysqlHostname->lineEdit()->text(),
|
||||
// TODO: TODO
|
||||
|
||||
/*
|
||||
const DatabaseFactory::MySQLError error_code = qApp->database()->driver()->mysqlTestConnection(m_ui->m_txtMysqlHostname->lineEdit()->text(),
|
||||
m_ui->m_spinMysqlPort->value(),
|
||||
m_ui->m_txtMysqlDatabase->lineEdit()->text(),
|
||||
m_ui->m_txtMysqlUsername->lineEdit()->text(),
|
||||
m_ui->m_txtMysqlPassword->lineEdit()->text());
|
||||
const QString interpretation = qApp->database()->mysqlInterpretErrorCode(error_code);
|
||||
const QString interpretation = qApp->database()->driver()->mysqlInterpretErrorCode(error_code);
|
||||
|
||||
switch (error_code) {
|
||||
case DatabaseFactory::MySQLError::Ok:
|
||||
|
@ -61,6 +64,7 @@ void SettingsDatabase::mysqlTestConnection() {
|
|||
m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::StatusType::Error, interpretation, interpretation);
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void SettingsDatabase::onMysqlHostnameChanged(const QString& new_hostname) {
|
||||
|
@ -127,19 +131,23 @@ void SettingsDatabase::loadSettings() {
|
|||
tr("You did not executed any connection test yet."));
|
||||
|
||||
// Load SQLite.
|
||||
m_ui->m_cmbDatabaseDriver->addItem(qApp->database()->humanDriverName(DatabaseFactory::UsedDriver::SQLITE), APP_DB_SQLITE_DRIVER);
|
||||
auto* lite_driver = qApp->database()->driverForType(DatabaseDriver::DriverType::SQLite);
|
||||
|
||||
m_ui->m_cmbDatabaseDriver->addItem(lite_driver->humanDriverType(), lite_driver->qtDriverCode());
|
||||
|
||||
// Load in-memory database status.
|
||||
m_ui->m_checkSqliteUseInMemoryDatabase->setChecked(settings()->value(GROUP(Database), SETTING(Database::UseInMemory)).toBool());
|
||||
|
||||
if (QSqlDatabase::isDriverAvailable(APP_DB_MYSQL_DRIVER)) {
|
||||
auto* mysq_driver = qApp->database()->driverForType(DatabaseDriver::DriverType::MySQL);
|
||||
|
||||
if (mysq_driver != nullptr) {
|
||||
onMysqlHostnameChanged(QString());
|
||||
onMysqlUsernameChanged(QString());
|
||||
onMysqlPasswordChanged(QString());
|
||||
onMysqlDatabaseChanged(QString());
|
||||
|
||||
// Load MySQL.
|
||||
m_ui->m_cmbDatabaseDriver->addItem(qApp->database()->humanDriverName(DatabaseFactory::UsedDriver::MYSQL), APP_DB_MYSQL_DRIVER);
|
||||
m_ui->m_cmbDatabaseDriver->addItem(mysq_driver->humanDriverType(), mysq_driver->qtDriverCode());
|
||||
|
||||
// Setup placeholders.
|
||||
m_ui->m_txtMysqlHostname->lineEdit()->setPlaceholderText(tr("Hostname of your MySQL server"));
|
||||
|
|
|
@ -84,7 +84,7 @@ QStringList StatusBar::defaultActions() const {
|
|||
#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
|
||||
Qt::SplitBehaviorFlags::SkipEmptyParts);
|
||||
#else
|
||||
QString::SkipEmptyParts);
|
||||
QString::SplitBehavior::SkipEmptyParts);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@ QStringList StatusBar::savedActions() const {
|
|||
#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
|
||||
Qt::SplitBehaviorFlags::SkipEmptyParts);
|
||||
#else
|
||||
QString::SkipEmptyParts);
|
||||
QString::SplitBehavior::SkipEmptyParts);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "gui/searchtextwidget.h"
|
||||
#include "gui/webviewer.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "network-web/networkfactory.h"
|
||||
#include "network-web/webfactory.h"
|
||||
|
|
|
@ -43,6 +43,11 @@ HEADERS += core/feeddownloader.h \
|
|||
core/messagesmodelcache.h \
|
||||
core/messagesmodelsqllayer.h \
|
||||
core/messagesproxymodel.h \
|
||||
database/databasecleaner.h \
|
||||
database/databasedriver.h \
|
||||
database/databasefactory.h \
|
||||
database/databasequeries.h \
|
||||
database/sqlitedriver.h \
|
||||
definitions/definitions.h \
|
||||
definitions/typedefs.h \
|
||||
dynamic-shortcuts/dynamicshortcuts.h \
|
||||
|
@ -107,9 +112,6 @@ HEADERS += core/feeddownloader.h \
|
|||
gui/widgetwithstatus.h \
|
||||
miscellaneous/application.h \
|
||||
miscellaneous/autosaver.h \
|
||||
miscellaneous/databasecleaner.h \
|
||||
miscellaneous/databasefactory.h \
|
||||
miscellaneous/databasequeries.h \
|
||||
miscellaneous/externaltool.h \
|
||||
miscellaneous/feedreader.h \
|
||||
miscellaneous/iconfactory.h \
|
||||
|
@ -222,6 +224,11 @@ SOURCES += core/feeddownloader.cpp \
|
|||
core/messagesmodelcache.cpp \
|
||||
core/messagesmodelsqllayer.cpp \
|
||||
core/messagesproxymodel.cpp \
|
||||
database/databasecleaner.cpp \
|
||||
database/databasedriver.cpp \
|
||||
database/databasefactory.cpp \
|
||||
database/databasequeries.cpp \
|
||||
database/sqlitedriver.cpp \
|
||||
dynamic-shortcuts/dynamicshortcuts.cpp \
|
||||
dynamic-shortcuts/dynamicshortcutswidget.cpp \
|
||||
dynamic-shortcuts/shortcutcatcher.cpp \
|
||||
|
@ -284,9 +291,6 @@ SOURCES += core/feeddownloader.cpp \
|
|||
gui/widgetwithstatus.cpp \
|
||||
miscellaneous/application.cpp \
|
||||
miscellaneous/autosaver.cpp \
|
||||
miscellaneous/databasecleaner.cpp \
|
||||
miscellaneous/databasefactory.cpp \
|
||||
miscellaneous/databasequeries.cpp \
|
||||
miscellaneous/externaltool.cpp \
|
||||
miscellaneous/feedreader.cpp \
|
||||
miscellaneous/iconfactory.cpp \
|
||||
|
|
|
@ -313,23 +313,17 @@ void Application::backupDatabaseSettings(bool backup_database, bool backup_setti
|
|||
}
|
||||
}
|
||||
|
||||
if (backup_database &&
|
||||
(database()->activeDatabaseDriver() == DatabaseFactory::UsedDriver::SQLITE ||
|
||||
database()->activeDatabaseDriver() == DatabaseFactory::UsedDriver::SQLITE_MEMORY)) {
|
||||
if (backup_database) {
|
||||
// We need to save the database first.
|
||||
database()->saveDatabase();
|
||||
|
||||
if (!IOFactory::copyFile(database()->sqliteDatabaseFilePath(),
|
||||
target_path + QDir::separator() + backup_name + BACKUP_SUFFIX_DATABASE)) {
|
||||
throw ApplicationException(tr("Database file not copied to output directory successfully."));
|
||||
}
|
||||
database()->driver()->saveDatabase();
|
||||
database()->driver()->backupDatabase(target_path, backup_name);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::restoreDatabaseSettings(bool restore_database, bool restore_settings,
|
||||
const QString& source_database_file_path, const QString& source_settings_file_path) {
|
||||
if (restore_database) {
|
||||
if (!qApp->database()->initiateRestoration(source_database_file_path)) {
|
||||
if (!qApp->database()->driver()->initiateRestoration(source_database_file_path)) {
|
||||
throw ApplicationException(tr("Database restoration was not initiated. Make sure that output directory is writable."));
|
||||
}
|
||||
}
|
||||
|
@ -501,7 +495,7 @@ void Application::onAboutToQuit() {
|
|||
}
|
||||
|
||||
qApp->feedReader()->quit();
|
||||
database()->saveDatabase();
|
||||
database()->driver()->saveDatabase();
|
||||
|
||||
if (mainForm() != nullptr) {
|
||||
mainForm()->saveSize();
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
#include "qtsingleapplication/qtsingleapplication.h"
|
||||
|
||||
#include "core/feeddownloader.h"
|
||||
#include "database/databasefactory.h"
|
||||
#include "definitions/definitions.h"
|
||||
#include "gui/systemtrayicon.h"
|
||||
#include "miscellaneous/databasefactory.h"
|
||||
#include "miscellaneous/feedreader.h"
|
||||
#include "miscellaneous/iofactory.h"
|
||||
#include "miscellaneous/localization.h"
|
||||
|
|
|
@ -1,940 +0,0 @@
|
|||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#include "miscellaneous/databasefactory.h"
|
||||
|
||||
#include "gui/messagebox.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/iofactory.h"
|
||||
#include "miscellaneous/textfactory.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QSqlError>
|
||||
#include <QSqlQuery>
|
||||
#include <QVariant>
|
||||
|
||||
DatabaseFactory::DatabaseFactory(QObject* parent)
|
||||
: QObject(parent),
|
||||
m_activeDatabaseDriver(UsedDriver::SQLITE),
|
||||
m_mysqlDatabaseInitialized(false),
|
||||
m_sqliteFileBasedDatabaseInitialized(false),
|
||||
m_sqliteInMemoryDatabaseInitialized(false) {
|
||||
setObjectName(QSL("DatabaseFactory"));
|
||||
determineDriver();
|
||||
}
|
||||
|
||||
qint64 DatabaseFactory::getDatabaseFileSize() const {
|
||||
if (m_activeDatabaseDriver == UsedDriver::SQLITE || m_activeDatabaseDriver == UsedDriver::SQLITE_MEMORY) {
|
||||
return QFileInfo(sqliteDatabaseFilePath()).size();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
qint64 DatabaseFactory::getDatabaseDataSize() const {
|
||||
if (m_activeDatabaseDriver == UsedDriver::SQLITE || m_activeDatabaseDriver == UsedDriver::SQLITE_MEMORY) {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DesiredType::FromSettings);
|
||||
qint64 result = 1;
|
||||
QSqlQuery query(database);
|
||||
|
||||
if (query.exec(QSL("PRAGMA page_count;"))) {
|
||||
query.next();
|
||||
result *= query.value(0).value<qint64>();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (query.exec(QSL("PRAGMA page_size;"))) {
|
||||
query.next();
|
||||
result *= query.value(0).value<qint64>();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
else if (m_activeDatabaseDriver == UsedDriver::MYSQL) {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className(), DesiredType::FromSettings);
|
||||
QSqlQuery query(database);
|
||||
|
||||
query.prepare("SELECT Round(Sum(data_length + index_length), 1) "
|
||||
"FROM information_schema.tables "
|
||||
"WHERE table_schema = :db "
|
||||
"GROUP BY table_schema;");
|
||||
query.bindValue(QSL(":db"), database.databaseName());
|
||||
|
||||
if (query.exec() && query.next()) {
|
||||
return query.value(0).value<qint64>();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
DatabaseFactory::MySQLError DatabaseFactory::mysqlTestConnection(const QString& hostname, int port, const QString& w_database,
|
||||
const QString& username, const QString& password) {
|
||||
QSqlDatabase database = QSqlDatabase::addDatabase(APP_DB_MYSQL_DRIVER, APP_DB_MYSQL_TEST);
|
||||
|
||||
database.setHostName(hostname);
|
||||
database.setPort(port);
|
||||
database.setUserName(username);
|
||||
database.setPassword(password);
|
||||
database.setDatabaseName(w_database);
|
||||
|
||||
if (database.open() && !database.lastError().isValid()) {
|
||||
QSqlQuery query(QSL("SELECT version();"), database);
|
||||
|
||||
if (!query.lastError().isValid() && query.next()) {
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "Checked MySQL database, version is '"
|
||||
<< query.value(0).toString()
|
||||
<< "'.";
|
||||
|
||||
// Connection succeeded, clean up the mess and return OK status.
|
||||
database.close();
|
||||
return MySQLError::Ok;
|
||||
}
|
||||
else {
|
||||
database.close();
|
||||
return MySQLError::UnknownError;
|
||||
}
|
||||
}
|
||||
else if (database.lastError().isValid()) {
|
||||
auto nat = database.lastError().nativeErrorCode();
|
||||
bool nat_converted = false;
|
||||
auto nat_int = nat.toInt(&nat_converted);
|
||||
|
||||
if (nat_converted) {
|
||||
return static_cast<MySQLError>(nat_int);
|
||||
}
|
||||
else {
|
||||
qWarningNN << LOGSEC_DB
|
||||
<< "Failed to recognize MySQL error code: '"
|
||||
<< nat
|
||||
<< "'.";
|
||||
|
||||
return MySQLError::UnknownError;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return MySQLError::UnknownError;
|
||||
}
|
||||
}
|
||||
|
||||
QString DatabaseFactory::mysqlInterpretErrorCode(MySQLError error_code) const {
|
||||
switch (error_code) {
|
||||
case MySQLError::Ok:
|
||||
return tr("MySQL server works as expected.");
|
||||
|
||||
case MySQLError::UnknownDatabase:
|
||||
return tr("Selected database does not exist (yet). It will be created. It's okay.");
|
||||
|
||||
case MySQLError::CantConnect:
|
||||
case MySQLError::ConnectionError:
|
||||
case MySQLError::UnknownHost:
|
||||
return tr("No MySQL server is running in the target destination.");
|
||||
|
||||
case MySQLError::AccessDenied:
|
||||
return tr("Access denied. Invalid username or password used.");
|
||||
|
||||
default:
|
||||
return tr("Unknown error: '%1'.").arg(int(error_code));
|
||||
}
|
||||
}
|
||||
|
||||
bool DatabaseFactory::initiateRestoration(const QString& database_backup_file_path) {
|
||||
switch (m_activeDatabaseDriver) {
|
||||
case UsedDriver::SQLITE:
|
||||
case UsedDriver::SQLITE_MEMORY:
|
||||
return IOFactory::copyFile(database_backup_file_path,
|
||||
m_sqliteDatabaseFilePath + QDir::separator() +
|
||||
BACKUP_NAME_DATABASE + BACKUP_SUFFIX_DATABASE);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseFactory::finishRestoration() {
|
||||
if (m_activeDatabaseDriver != UsedDriver::SQLITE && m_activeDatabaseDriver != UsedDriver::SQLITE_MEMORY) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QString backup_database_file = m_sqliteDatabaseFilePath + QDir::separator() + BACKUP_NAME_DATABASE + BACKUP_SUFFIX_DATABASE;
|
||||
|
||||
if (QFile::exists(backup_database_file)) {
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "Backup database file '"
|
||||
<< QDir::toNativeSeparators(backup_database_file)
|
||||
<< "' was detected. Restoring it.";
|
||||
|
||||
if (IOFactory::copyFile(backup_database_file, m_sqliteDatabaseFilePath + QDir::separator() + APP_DB_SQLITE_FILE)) {
|
||||
QFile::remove(backup_database_file);
|
||||
qDebugNN << LOGSEC_DB << "Database file was restored successully.";
|
||||
}
|
||||
else {
|
||||
qCriticalNN << LOGSEC_DB
|
||||
<< "Database file was NOT restored due to error when copying the file.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseFactory::sqliteAssemblyDatabaseFilePath() {
|
||||
m_sqliteDatabaseFilePath = qApp->userDataFolder() + QDir::separator() + QString(APP_DB_SQLITE_PATH);
|
||||
}
|
||||
|
||||
QSqlDatabase DatabaseFactory::sqliteInitializeInMemoryDatabase() {
|
||||
QSqlDatabase database = QSqlDatabase::addDatabase(APP_DB_SQLITE_DRIVER);
|
||||
|
||||
database.setConnectOptions(QSL("QSQLITE_OPEN_URI;QSQLITE_ENABLE_SHARED_CACHE"));
|
||||
database.setDatabaseName(QSL("file::memory:"));
|
||||
|
||||
if (!database.open()) {
|
||||
qFatal("In-memory SQLite database was NOT opened. Delivered error message: '%s'",
|
||||
qPrintable(database.lastError().text()));
|
||||
}
|
||||
else {
|
||||
QSqlQuery query_db(database);
|
||||
|
||||
query_db.setForwardOnly(true);
|
||||
query_db.exec(QSL("PRAGMA encoding = \"UTF-8\""));
|
||||
query_db.exec(QSL("PRAGMA synchronous = OFF"));
|
||||
query_db.exec(QSL("PRAGMA journal_mode = MEMORY"));
|
||||
query_db.exec(QSL("PRAGMA page_size = 4096"));
|
||||
query_db.exec(QSL("PRAGMA cache_size = 16384"));
|
||||
query_db.exec(QSL("PRAGMA count_changes = OFF"));
|
||||
query_db.exec(QSL("PRAGMA temp_store = MEMORY"));
|
||||
|
||||
// Sample query which checks for existence of tables.
|
||||
query_db.exec(QSL("SELECT inf_value FROM Information WHERE inf_key = 'schema_version'"));
|
||||
|
||||
if (query_db.lastError().isValid()) {
|
||||
qWarningNN << LOGSEC_DB << "Error occurred. In-memory SQLite database is not initialized. Initializing now.";
|
||||
QFile file_init(APP_SQL_PATH + QDir::separator() + APP_DB_SQLITE_INIT);
|
||||
|
||||
if (!file_init.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
// Database initialization file not opened. HUGE problem.
|
||||
qFatal("In-memory SQLite database initialization file '%s' from directory '%s' was not found. In-memory database is uninitialized.",
|
||||
APP_DB_SQLITE_INIT,
|
||||
qPrintable(APP_SQL_PATH));
|
||||
}
|
||||
|
||||
const QStringList statements = QString(file_init.readAll()).split(APP_DB_COMMENT_SPLIT,
|
||||
#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
|
||||
Qt::SplitBehaviorFlags::SkipEmptyParts);
|
||||
#else
|
||||
QString::SkipEmptyParts);
|
||||
#endif
|
||||
|
||||
database.transaction();
|
||||
|
||||
for (const QString& statement : statements) {
|
||||
query_db.exec(statement);
|
||||
|
||||
if (query_db.lastError().isValid()) {
|
||||
qFatal("In-memory SQLite database initialization failed. Initialization script '%s' is not correct.",
|
||||
APP_DB_SQLITE_INIT);
|
||||
}
|
||||
}
|
||||
|
||||
database.commit();
|
||||
qDebugNN << LOGSEC_DB << "In-memory SQLite database backend should be ready now.";
|
||||
}
|
||||
else {
|
||||
query_db.next();
|
||||
qDebugNN << LOGSEC_DB << "In-memory SQLite database connection seems to be established.";
|
||||
qDebugNN << LOGSEC_DB << "In-memory SQLite database has version '"
|
||||
<< query_db.value(0).toString()
|
||||
<< "'.";
|
||||
}
|
||||
|
||||
// Loading messages from file-based database.
|
||||
QSqlDatabase file_database = sqliteConnection(objectName(), DesiredType::StrictlyFileBased);
|
||||
QSqlQuery copy_contents(database);
|
||||
|
||||
// Attach database.
|
||||
copy_contents.exec(QString("ATTACH DATABASE '%1' AS 'storage';").arg(file_database.databaseName()));
|
||||
|
||||
// Copy all stuff.
|
||||
QStringList tables;
|
||||
|
||||
if (copy_contents.exec(QSL("SELECT name FROM storage.sqlite_master WHERE type='table';"))) {
|
||||
while (copy_contents.next()) {
|
||||
tables.append(copy_contents.value(0).toString());
|
||||
}
|
||||
}
|
||||
else {
|
||||
qFatal("Cannot obtain list of table names from file-base SQLite database.");
|
||||
}
|
||||
|
||||
for (const QString& table : tables) {
|
||||
copy_contents.exec(QString("INSERT INTO main.%1 SELECT * FROM storage.%1;").arg(table));
|
||||
}
|
||||
|
||||
qDebugNN << LOGSEC_DB << "Copying data from file-based database into working in-memory database.";
|
||||
|
||||
// Detach database and finish.
|
||||
copy_contents.exec(QSL("DETACH 'storage'"));
|
||||
copy_contents.finish();
|
||||
query_db.finish();
|
||||
}
|
||||
|
||||
// Everything is initialized now.
|
||||
m_sqliteInMemoryDatabaseInitialized = true;
|
||||
return database;
|
||||
}
|
||||
|
||||
QSqlDatabase DatabaseFactory::sqliteInitializeFileBasedDatabase(const QString& connection_name) {
|
||||
finishRestoration();
|
||||
|
||||
// Prepare file paths.
|
||||
const QDir db_path(m_sqliteDatabaseFilePath);
|
||||
QFile db_file(db_path.absoluteFilePath(APP_DB_SQLITE_FILE));
|
||||
|
||||
// Check if database directory exists.
|
||||
if (!db_path.exists()) {
|
||||
if (!db_path.mkpath(db_path.absolutePath())) {
|
||||
// Failure when create database file path.
|
||||
qFatal("Directory '%s' for SQLite database file '%s' was NOT created."
|
||||
"This is HUGE problem.",
|
||||
qPrintable(db_path.absolutePath()),
|
||||
qPrintable(db_file.symLinkTarget()));
|
||||
}
|
||||
}
|
||||
|
||||
// Folders are created. Create new QSQLDatabase object.
|
||||
QSqlDatabase database;
|
||||
|
||||
database = QSqlDatabase::addDatabase(APP_DB_SQLITE_DRIVER, connection_name);
|
||||
database.setDatabaseName(db_file.fileName());
|
||||
|
||||
if (!database.open()) {
|
||||
qFatal("File-based SQLite database was NOT opened. Delivered error message: '%s'",
|
||||
qPrintable(database.lastError().text()));
|
||||
}
|
||||
else {
|
||||
QSqlQuery query_db(database);
|
||||
|
||||
query_db.setForwardOnly(true);
|
||||
query_db.exec(QSL("PRAGMA encoding = \"UTF-8\""));
|
||||
query_db.exec(QSL("PRAGMA synchronous = OFF"));
|
||||
query_db.exec(QSL("PRAGMA journal_mode = MEMORY"));
|
||||
query_db.exec(QSL("PRAGMA page_size = 4096"));
|
||||
query_db.exec(QSL("PRAGMA cache_size = 16384"));
|
||||
query_db.exec(QSL("PRAGMA count_changes = OFF"));
|
||||
query_db.exec(QSL("PRAGMA temp_store = MEMORY"));
|
||||
|
||||
// Sample query which checks for existence of tables.
|
||||
if (!query_db.exec(QSL("SELECT inf_value FROM Information WHERE inf_key = 'schema_version'"))) {
|
||||
qWarningNN << LOGSEC_DB << "Error occurred. File-based SQLite database is not initialized. Initializing now.";
|
||||
QFile file_init(APP_SQL_PATH + QDir::separator() + APP_DB_SQLITE_INIT);
|
||||
|
||||
if (!file_init.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
// Database initialization file not opened. HUGE problem.
|
||||
qFatal("SQLite database initialization file '%s' from directory '%s' was not found. File-based database is uninitialized.",
|
||||
APP_DB_SQLITE_INIT,
|
||||
qPrintable(APP_SQL_PATH));
|
||||
}
|
||||
|
||||
const QStringList statements = QString(file_init.readAll()).split(APP_DB_COMMENT_SPLIT,
|
||||
#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
|
||||
Qt::SplitBehaviorFlags::SkipEmptyParts);
|
||||
#else
|
||||
QString::SkipEmptyParts);
|
||||
#endif
|
||||
|
||||
database.transaction();
|
||||
|
||||
for (const QString& statement : statements) {
|
||||
query_db.exec(statement);
|
||||
|
||||
if (query_db.lastError().isValid()) {
|
||||
qFatal("File-based SQLite database initialization failed. Initialization script '%s' is not correct.",
|
||||
APP_DB_SQLITE_INIT);
|
||||
}
|
||||
}
|
||||
|
||||
database.commit();
|
||||
query_db.finish();
|
||||
qDebugNN << LOGSEC_DB << "File-based SQLite database backend should be ready now.";
|
||||
}
|
||||
else {
|
||||
query_db.next();
|
||||
const QString installed_db_schema = query_db.value(0).toString();
|
||||
|
||||
query_db.finish();
|
||||
|
||||
if (installed_db_schema.toInt() < QString(APP_DB_SCHEMA_VERSION).toInt()) {
|
||||
if (sqliteUpdateDatabaseSchema(database, installed_db_schema)) {
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "Database schema was updated from '"
|
||||
<< installed_db_schema
|
||||
<< "' to '"
|
||||
<< APP_DB_SCHEMA_VERSION
|
||||
<< "' successully or it is already up to date.";
|
||||
}
|
||||
else {
|
||||
qFatal("Database schema was not updated from '%s' to '%s' successully.",
|
||||
qPrintable(installed_db_schema),
|
||||
APP_DB_SCHEMA_VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "File-based SQLite database connection '"
|
||||
<< connection_name
|
||||
<< "' to file '"
|
||||
<< QDir::toNativeSeparators(database.databaseName())
|
||||
<< "' seems to be established.";
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "File-based SQLite database has version '"
|
||||
<< installed_db_schema
|
||||
<< "'.";
|
||||
}
|
||||
}
|
||||
|
||||
// Everything is initialized now.
|
||||
m_sqliteFileBasedDatabaseInitialized = true;
|
||||
return database;
|
||||
}
|
||||
|
||||
QString DatabaseFactory::sqliteDatabaseFilePath() const {
|
||||
return m_sqliteDatabaseFilePath + QDir::separator() + APP_DB_SQLITE_FILE;
|
||||
}
|
||||
|
||||
bool DatabaseFactory::sqliteUpdateDatabaseSchema(const QSqlDatabase& database, const QString& source_db_schema_version) {
|
||||
int working_version = QString(source_db_schema_version).remove('.').toInt();
|
||||
const int current_version = QString(APP_DB_SCHEMA_VERSION).remove('.').toInt();
|
||||
|
||||
// Now, it would be good to create backup of SQLite DB file.
|
||||
if (IOFactory::copyFile(sqliteDatabaseFilePath(), sqliteDatabaseFilePath() + ".bak")) {
|
||||
qDebugNN << LOGSEC_DB << "Creating backup of SQLite DB file.";
|
||||
}
|
||||
else {
|
||||
qFatal("Creation of backup SQLite DB file failed.");
|
||||
}
|
||||
|
||||
while (working_version != current_version) {
|
||||
const QString update_file_name = QString(APP_SQL_PATH) + QDir::separator() +
|
||||
QString(APP_DB_UPDATE_FILE_PATTERN).arg(QSL("sqlite"),
|
||||
QString::number(working_version),
|
||||
QString::number(working_version + 1));
|
||||
|
||||
if (!QFile::exists(update_file_name)) {
|
||||
qFatal("Updating of database schema failed. File '%s' does not exist.", qPrintable(QDir::toNativeSeparators(update_file_name)));
|
||||
}
|
||||
|
||||
QFile update_file_handle(update_file_name);
|
||||
|
||||
if (!update_file_handle.open(QIODevice::Text | QIODevice::ReadOnly | QIODevice::Unbuffered)) {
|
||||
qFatal("Updating of database schema failed. File '%s' cannot be opened.", qPrintable(QDir::toNativeSeparators(update_file_name)));
|
||||
}
|
||||
|
||||
const QStringList statements = QString(update_file_handle.readAll()).split(APP_DB_COMMENT_SPLIT,
|
||||
#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
|
||||
Qt::SplitBehaviorFlags::SkipEmptyParts);
|
||||
#else
|
||||
QString::SkipEmptyParts);
|
||||
#endif
|
||||
|
||||
for (const QString& statement : statements) {
|
||||
QSqlQuery query = database.exec(statement);
|
||||
|
||||
if (query.lastError().isValid()) {
|
||||
qFatal("Query for updating database schema failed: '%s'.", qPrintable(query.lastError().text()));
|
||||
}
|
||||
}
|
||||
|
||||
// Increment the version.
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "Updating database schema:"
|
||||
<< QUOTE_W_SPACE(working_version)
|
||||
<< "->"
|
||||
<< QUOTE_W_SPACE_DOT(working_version + 1);
|
||||
|
||||
working_version++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DatabaseFactory::mysqlUpdateDatabaseSchema(const QSqlDatabase& database,
|
||||
const QString& source_db_schema_version,
|
||||
const QString& db_name) {
|
||||
int working_version = QString(source_db_schema_version).remove('.').toInt();
|
||||
const int current_version = QString(APP_DB_SCHEMA_VERSION).remove('.').toInt();
|
||||
|
||||
while (working_version != current_version) {
|
||||
const QString update_file_name = QString(APP_SQL_PATH) + QDir::separator() +
|
||||
QString(APP_DB_UPDATE_FILE_PATTERN).arg(QSL("mysql"),
|
||||
QString::number(working_version),
|
||||
QString::number(working_version + 1));
|
||||
|
||||
if (!QFile::exists(update_file_name)) {
|
||||
qFatal("Updating of database schema failed. File '%s' does not exist.", qPrintable(QDir::toNativeSeparators(update_file_name)));
|
||||
}
|
||||
|
||||
QFile update_file_handle(update_file_name);
|
||||
|
||||
if (!update_file_handle.open(QIODevice::Text | QIODevice::ReadOnly | QIODevice::Unbuffered)) {
|
||||
qFatal("Updating of database schema failed. File '%s' cannot be opened.", qPrintable(QDir::toNativeSeparators(update_file_name)));
|
||||
}
|
||||
|
||||
QStringList statements = QString(update_file_handle.readAll()).split(APP_DB_COMMENT_SPLIT,
|
||||
#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
|
||||
Qt::SplitBehaviorFlags::SkipEmptyParts);
|
||||
#else
|
||||
QString::SkipEmptyParts);
|
||||
#endif
|
||||
|
||||
for (QString statement : statements) {
|
||||
QSqlQuery query = database.exec(statement.replace(APP_DB_NAME_PLACEHOLDER, db_name));
|
||||
|
||||
if (query.lastError().isValid()) {
|
||||
auto xx = query.lastError().text();
|
||||
|
||||
qFatal("Query for updating database schema failed: '%s'.", qPrintable(query.lastError().text()));
|
||||
}
|
||||
}
|
||||
|
||||
// Increment the version.
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "Updating database schema: '"
|
||||
<< working_version
|
||||
<< "' -> '"
|
||||
<< working_version + 1
|
||||
<< "'.";
|
||||
|
||||
working_version++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QSqlDatabase DatabaseFactory::connection(const QString& connection_name, DesiredType desired_type) {
|
||||
switch (m_activeDatabaseDriver) {
|
||||
case UsedDriver::MYSQL:
|
||||
return mysqlConnection(connection_name);
|
||||
|
||||
case UsedDriver::SQLITE:
|
||||
case UsedDriver::SQLITE_MEMORY:
|
||||
default:
|
||||
return sqliteConnection(connection_name, desired_type);
|
||||
}
|
||||
}
|
||||
|
||||
QString DatabaseFactory::humanDriverName(DatabaseFactory::UsedDriver driver) const {
|
||||
switch (driver) {
|
||||
case UsedDriver::MYSQL:
|
||||
return tr("MySQL/MariaDB (dedicated database)");
|
||||
|
||||
case UsedDriver::SQLITE:
|
||||
case UsedDriver::SQLITE_MEMORY:
|
||||
default:
|
||||
return tr("SQLite (embedded database)");
|
||||
}
|
||||
}
|
||||
|
||||
QString DatabaseFactory::humanDriverName(const QString& driver_code) const {
|
||||
if (driver_code == APP_DB_SQLITE_DRIVER) {
|
||||
return humanDriverName(UsedDriver::SQLITE);
|
||||
}
|
||||
else if (driver_code == APP_DB_MYSQL_DRIVER) {
|
||||
return humanDriverName(UsedDriver::MYSQL);
|
||||
}
|
||||
else {
|
||||
return humanDriverName(UsedDriver::SQLITE);
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseFactory::removeConnection(const QString& connection_name) {
|
||||
qDebugNN << LOGSEC_DB << "Removing database connection '" << connection_name << "'.";
|
||||
QSqlDatabase::removeDatabase(connection_name);
|
||||
}
|
||||
|
||||
QString DatabaseFactory::obtainBeginTransactionSql() const {
|
||||
if (m_activeDatabaseDriver == UsedDriver::SQLITE || m_activeDatabaseDriver == UsedDriver::SQLITE_MEMORY) {
|
||||
return QSL("BEGIN IMMEDIATE TRANSACTION;");
|
||||
}
|
||||
else {
|
||||
return QSL("START TRANSACTION;");
|
||||
}
|
||||
}
|
||||
|
||||
void DatabaseFactory::sqliteSaveMemoryDatabase() {
|
||||
qDebugNN << LOGSEC_DB << "Saving in-memory working database back to persistent file-based storage.";
|
||||
|
||||
QSqlDatabase database = sqliteConnection(QSL("SaveFromMemory"), DesiredType::StrictlyInMemory);
|
||||
QSqlDatabase file_database = sqliteConnection(QSL("SaveToFile"), DesiredType::StrictlyFileBased);
|
||||
QSqlQuery copy_contents(database);
|
||||
|
||||
// Attach database.
|
||||
copy_contents.exec(QString(QSL("ATTACH DATABASE '%1' AS 'storage';")).arg(file_database.databaseName()));
|
||||
|
||||
// Copy all stuff.
|
||||
QStringList tables;
|
||||
|
||||
if (copy_contents.exec(QSL("SELECT name FROM storage.sqlite_master WHERE type='table';"))) {
|
||||
while (copy_contents.next()) {
|
||||
tables.append(copy_contents.value(0).toString());
|
||||
}
|
||||
}
|
||||
else {
|
||||
qFatal("Cannot obtain list of table names from file-base SQLite database.");
|
||||
}
|
||||
|
||||
for (const QString& table : tables) {
|
||||
if (copy_contents.exec(QString(QSL("DELETE FROM storage.%1;")).arg(table))) {
|
||||
qDebugNN << LOGSEC_DB << "Cleaning old data from 'storage." << table << "'.";
|
||||
}
|
||||
else {
|
||||
qCriticalNN << LOGSEC_DB << "Failed to clean old data from 'storage."
|
||||
<< table << "', error: '"
|
||||
<< copy_contents.lastError().text() << "'.";
|
||||
}
|
||||
|
||||
if (copy_contents.exec(QString(QSL("INSERT INTO storage.%1 SELECT * FROM main.%1;")).arg(table))) {
|
||||
qDebugNN << LOGSEC_DB << "Copying new data into 'main."
|
||||
<< table << "'.";
|
||||
}
|
||||
else {
|
||||
qCriticalNN << LOGSEC_DB
|
||||
<< "Failed to copy new data to 'main."
|
||||
<< table
|
||||
<< "', error: '"
|
||||
<< copy_contents.lastError().text()
|
||||
<< "'.";
|
||||
}
|
||||
}
|
||||
|
||||
// Detach database and finish.
|
||||
if (copy_contents.exec(QSL("DETACH 'storage'"))) {
|
||||
qDebugNN << LOGSEC_DB << "Detaching persistent SQLite file.";
|
||||
}
|
||||
else {
|
||||
qCriticalNN << LOGSEC_DB
|
||||
<< "Failed to detach SQLite file, error: '"
|
||||
<< copy_contents.lastError().text()
|
||||
<< "'.";
|
||||
}
|
||||
|
||||
copy_contents.finish();
|
||||
}
|
||||
|
||||
void DatabaseFactory::determineDriver() {
|
||||
const QString db_driver = qApp->settings()->value(GROUP(Database), SETTING(Database::ActiveDriver)).toString();
|
||||
|
||||
if (db_driver == APP_DB_MYSQL_DRIVER && QSqlDatabase::isDriverAvailable(APP_DB_SQLITE_DRIVER)) {
|
||||
// User wants to use MySQL and MySQL is actually available. Use it.
|
||||
m_activeDatabaseDriver = UsedDriver::MYSQL;
|
||||
qDebugNN << LOGSEC_DB << "Working database source was as MySQL database.";
|
||||
}
|
||||
else {
|
||||
// User wants to use SQLite, which is always available. Check if file-based
|
||||
// or in-memory database will be used.
|
||||
if (qApp->settings()->value(GROUP(Database), SETTING(Database::UseInMemory)).toBool()) {
|
||||
// Use in-memory SQLite database.
|
||||
m_activeDatabaseDriver = UsedDriver::SQLITE_MEMORY;
|
||||
qDebugNN << LOGSEC_DB << "Working database source was determined as SQLite in-memory database.";
|
||||
}
|
||||
else {
|
||||
// Use strictly file-base SQLite database.
|
||||
m_activeDatabaseDriver = UsedDriver::SQLITE;
|
||||
qDebugNN << LOGSEC_DB << "Working database source was determined as SQLite file-based database.";
|
||||
}
|
||||
|
||||
sqliteAssemblyDatabaseFilePath();
|
||||
}
|
||||
}
|
||||
|
||||
DatabaseFactory::UsedDriver DatabaseFactory::activeDatabaseDriver() const {
|
||||
return m_activeDatabaseDriver;
|
||||
}
|
||||
|
||||
QSqlDatabase DatabaseFactory::mysqlConnection(const QString& connection_name) {
|
||||
if (!m_mysqlDatabaseInitialized) {
|
||||
// Return initialized database.
|
||||
return mysqlInitializeDatabase(connection_name);
|
||||
}
|
||||
else {
|
||||
QSqlDatabase database;
|
||||
|
||||
if (QSqlDatabase::contains(connection_name)) {
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "MySQL connection '"
|
||||
<< connection_name
|
||||
<< "' is already active.";
|
||||
|
||||
// This database connection was added previously, no need to
|
||||
// setup its properties.
|
||||
database = QSqlDatabase::database(connection_name);
|
||||
}
|
||||
else {
|
||||
// Database connection with this name does not exist
|
||||
// yet, add it and set it up.
|
||||
database = QSqlDatabase::addDatabase(APP_DB_MYSQL_DRIVER, connection_name);
|
||||
database.setHostName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLHostname)).toString());
|
||||
database.setPort(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLPort)).toInt());
|
||||
database.setUserName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLUsername)).toString());
|
||||
database.setPassword(qApp->settings()->password(GROUP(Database), SETTING(Database::MySQLPassword)).toString());
|
||||
database.setDatabaseName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLDatabase)).toString());
|
||||
}
|
||||
|
||||
if (!database.isOpen() && !database.open()) {
|
||||
qFatal("MySQL database was NOT opened. Delivered error message: '%s'.",
|
||||
qPrintable(database.lastError().text()));
|
||||
}
|
||||
else {
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "MySQL database connection '"
|
||||
<< connection_name
|
||||
<< "' to file '"
|
||||
<< QDir::toNativeSeparators(database.databaseName())
|
||||
<< "' seems to be established.";
|
||||
}
|
||||
|
||||
return database;
|
||||
}
|
||||
}
|
||||
|
||||
QSqlDatabase DatabaseFactory::mysqlInitializeDatabase(const QString& connection_name) {
|
||||
// Folders are created. Create new QSQLDatabase object.
|
||||
QSqlDatabase database = QSqlDatabase::addDatabase(APP_DB_MYSQL_DRIVER, connection_name);
|
||||
const QString database_name = qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLDatabase)).toString();
|
||||
|
||||
database.setHostName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLHostname)).toString());
|
||||
database.setPort(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLPort)).toInt());
|
||||
database.setUserName(qApp->settings()->value(GROUP(Database), SETTING(Database::MySQLUsername)).toString());
|
||||
database.setPassword(qApp->settings()->password(GROUP(Database), SETTING(Database::MySQLPassword)).toString());
|
||||
|
||||
if (!database.open()) {
|
||||
qCriticalNN << LOGSEC_DB
|
||||
<< "MySQL database was NOT opened. Delivered error message: '"
|
||||
<< database.lastError().text()
|
||||
<< "'.";
|
||||
|
||||
// Now, we will display error warning and return SQLite connection.
|
||||
// Also, we set the SQLite driver as active one.
|
||||
qApp->settings()->setValue(GROUP(Database), Database::ActiveDriver, APP_DB_SQLITE_DRIVER);
|
||||
determineDriver();
|
||||
MessageBox::show(nullptr, QMessageBox::Critical, tr("MySQL database not available"),
|
||||
tr("%1 cannot use MySQL storage, it is not available. %1 is now switching to SQLite database. Start your MySQL server "
|
||||
"and make adjustments in application settings.").arg(APP_NAME));
|
||||
return connection(objectName(), DesiredType::FromSettings);
|
||||
}
|
||||
else {
|
||||
QSqlQuery query_db(database);
|
||||
|
||||
query_db.setForwardOnly(true);
|
||||
|
||||
if (!query_db.exec(QString("USE %1").arg(database_name))
|
||||
|| !query_db.exec(QSL("SELECT inf_value FROM Information WHERE inf_key = 'schema_version'"))) {
|
||||
// If no "rssguard" database exists or schema version is wrong, then initialize it.
|
||||
qWarningNN << LOGSEC_DB << "Error occurred. MySQL database is not initialized. Initializing now.";
|
||||
QFile file_init(APP_SQL_PATH + QDir::separator() + APP_DB_MYSQL_INIT);
|
||||
|
||||
if (!file_init.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
// Database initialization file not opened. HUGE problem.
|
||||
qFatal("MySQL database initialization file '%s' from directory '%s' was not found. File-based database is uninitialized.",
|
||||
APP_DB_MYSQL_INIT,
|
||||
qPrintable(APP_SQL_PATH));
|
||||
}
|
||||
|
||||
const QStringList statements = QString(file_init.readAll()).split(APP_DB_COMMENT_SPLIT,
|
||||
#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
|
||||
Qt::SplitBehaviorFlags::SkipEmptyParts);
|
||||
#else
|
||||
QString::SkipEmptyParts);
|
||||
#endif
|
||||
|
||||
database.transaction();
|
||||
|
||||
for (QString statement : statements) {
|
||||
// Assign real database name and run the query.
|
||||
query_db.exec(statement.replace(APP_DB_NAME_PLACEHOLDER, database_name));
|
||||
|
||||
if (query_db.lastError().isValid()) {
|
||||
qFatal("MySQL database initialization failed. Initialization script '%s' is not correct. Error : '%s'.",
|
||||
APP_DB_MYSQL_INIT, qPrintable(query_db.lastError().databaseText()));
|
||||
}
|
||||
}
|
||||
|
||||
database.commit();
|
||||
qDebugNN << LOGSEC_DB << "MySQL database backend should be ready now.";
|
||||
}
|
||||
else {
|
||||
// Database was previously initialized. Now just check the schema version.
|
||||
query_db.next();
|
||||
const QString installed_db_schema = query_db.value(0).toString();
|
||||
|
||||
if (installed_db_schema.toInt() < QString(APP_DB_SCHEMA_VERSION).toInt()) {
|
||||
if (mysqlUpdateDatabaseSchema(database, installed_db_schema, database_name)) {
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "Database schema was updated from '"
|
||||
<< installed_db_schema
|
||||
<< "' to '"
|
||||
<< APP_DB_SCHEMA_VERSION
|
||||
<< "' successully or it is already up to date.";
|
||||
}
|
||||
else {
|
||||
qFatal("Database schema was not updated from '%s' to '%s' successully.",
|
||||
qPrintable(installed_db_schema),
|
||||
APP_DB_SCHEMA_VERSION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query_db.finish();
|
||||
}
|
||||
|
||||
// Everything is initialized now.
|
||||
m_mysqlDatabaseInitialized = true;
|
||||
return database;
|
||||
}
|
||||
|
||||
bool DatabaseFactory::mysqlVacuumDatabase() {
|
||||
QSqlDatabase database = mysqlConnection(objectName());
|
||||
QSqlQuery query_vacuum(database);
|
||||
|
||||
return query_vacuum.exec(QSL("OPTIMIZE TABLE Feeds;")) && query_vacuum.exec(QSL("OPTIMIZE TABLE Messages;"));
|
||||
}
|
||||
|
||||
QSqlDatabase DatabaseFactory::sqliteConnection(const QString& connection_name, DatabaseFactory::DesiredType desired_type) {
|
||||
if (desired_type == DesiredType::StrictlyInMemory ||
|
||||
(desired_type == DesiredType::FromSettings && m_activeDatabaseDriver == UsedDriver::SQLITE_MEMORY)) {
|
||||
// We request in-memory database (either user explicitly
|
||||
// needs in-memory database or it was enabled in the settings).
|
||||
if (!m_sqliteInMemoryDatabaseInitialized) {
|
||||
// It is not initialized yet.
|
||||
return sqliteInitializeInMemoryDatabase();
|
||||
}
|
||||
else {
|
||||
QSqlDatabase database;
|
||||
|
||||
if (QSqlDatabase::contains(connection_name)) {
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "SQLite connection '"
|
||||
<< connection_name
|
||||
<< "' is already active.";
|
||||
|
||||
// This database connection was added previously, no need to
|
||||
// setup its properties.
|
||||
database = QSqlDatabase::database(connection_name);
|
||||
}
|
||||
else {
|
||||
database = QSqlDatabase::addDatabase(APP_DB_SQLITE_DRIVER, connection_name);
|
||||
database.setConnectOptions(QSL("QSQLITE_OPEN_URI;QSQLITE_ENABLE_SHARED_CACHE"));
|
||||
database.setDatabaseName(QSL("file::memory:"));
|
||||
}
|
||||
|
||||
if (!database.isOpen() && !database.open()) {
|
||||
qFatal("In-memory SQLite database was NOT opened. Delivered error message: '%s'.",
|
||||
qPrintable(database.lastError().text()));
|
||||
}
|
||||
else {
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "In-memory SQLite database connection '"
|
||||
<< connection_name
|
||||
<< "' seems to be established.";
|
||||
}
|
||||
|
||||
return database;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// We request file-based database.
|
||||
if (!m_sqliteFileBasedDatabaseInitialized) {
|
||||
// File-based database is not yet initialised.
|
||||
return sqliteInitializeFileBasedDatabase(connection_name);
|
||||
}
|
||||
else {
|
||||
QSqlDatabase database;
|
||||
|
||||
if (QSqlDatabase::contains(connection_name)) {
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "SQLite connection '"
|
||||
<< connection_name
|
||||
<< "' is already active.";
|
||||
|
||||
// This database connection was added previously, no need to
|
||||
// setup its properties.
|
||||
database = QSqlDatabase::database(connection_name);
|
||||
}
|
||||
else {
|
||||
// Database connection with this name does not exist
|
||||
// yet, add it and set it up.
|
||||
database = QSqlDatabase::addDatabase(APP_DB_SQLITE_DRIVER, connection_name);
|
||||
const QDir db_path(m_sqliteDatabaseFilePath);
|
||||
QFile db_file(db_path.absoluteFilePath(APP_DB_SQLITE_FILE));
|
||||
|
||||
// Setup database file path.
|
||||
database.setDatabaseName(db_file.fileName());
|
||||
}
|
||||
|
||||
if (!database.isOpen() && !database.open()) {
|
||||
qFatal("File-based SQLite database was NOT opened. Delivered error message: '%s'.",
|
||||
qPrintable(database.lastError().text()));
|
||||
}
|
||||
else {
|
||||
qDebugNN << LOGSEC_DB
|
||||
<< "File-based SQLite database connection '"
|
||||
<< connection_name
|
||||
<< "' to file '"
|
||||
<< QDir::toNativeSeparators(database.databaseName())
|
||||
<< "' seems to be established.";
|
||||
}
|
||||
|
||||
return database;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DatabaseFactory::sqliteVacuumDatabase() {
|
||||
QSqlDatabase database;
|
||||
|
||||
if (m_activeDatabaseDriver == UsedDriver::SQLITE) {
|
||||
database = sqliteConnection(objectName(), DesiredType::StrictlyFileBased);
|
||||
}
|
||||
else if (m_activeDatabaseDriver == UsedDriver::SQLITE_MEMORY) {
|
||||
sqliteSaveMemoryDatabase();
|
||||
database = sqliteConnection(objectName(), DesiredType::StrictlyFileBased);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
QSqlQuery query_vacuum(database);
|
||||
|
||||
return query_vacuum.exec(QSL("VACUUM"));
|
||||
}
|
||||
|
||||
void DatabaseFactory::saveDatabase() {
|
||||
switch (m_activeDatabaseDriver) {
|
||||
case UsedDriver::SQLITE_MEMORY:
|
||||
sqliteSaveMemoryDatabase();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool DatabaseFactory::vacuumDatabase() {
|
||||
switch (m_activeDatabaseDriver) {
|
||||
case UsedDriver::SQLITE_MEMORY:
|
||||
case UsedDriver::SQLITE:
|
||||
return sqliteVacuumDatabase();
|
||||
|
||||
case UsedDriver::MYSQL:
|
||||
return mysqlVacuumDatabase();
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,167 +0,0 @@
|
|||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#ifndef DATABASEFACTORY_H
|
||||
#define DATABASEFACTORY_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QSqlDatabase>
|
||||
|
||||
class DatabaseFactory : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
// Describes available typos of database backend.
|
||||
enum class UsedDriver {
|
||||
SQLITE,
|
||||
SQLITE_MEMORY,
|
||||
MYSQL
|
||||
};
|
||||
|
||||
// Describes what type of database user wants.
|
||||
enum class DesiredType {
|
||||
StrictlyFileBased,
|
||||
StrictlyInMemory,
|
||||
FromSettings
|
||||
};
|
||||
|
||||
// Describes possible MySQL-specific errors.
|
||||
enum class MySQLError {
|
||||
Ok = 0,
|
||||
UnknownError = 1,
|
||||
AccessDenied = 1045,
|
||||
UnknownDatabase = 1049,
|
||||
ConnectionError = 2002,
|
||||
CantConnect = 2003,
|
||||
UnknownHost = 2005
|
||||
};
|
||||
|
||||
//
|
||||
// GENERAL stuff.
|
||||
//
|
||||
|
||||
// Constructor.
|
||||
explicit DatabaseFactory(QObject* parent = nullptr);
|
||||
|
||||
// Destructor.
|
||||
virtual ~DatabaseFactory() = default;
|
||||
|
||||
// Returns size of DB file.
|
||||
qint64 getDatabaseFileSize() const;
|
||||
|
||||
// Returns size of data contained in the DB file.
|
||||
qint64 getDatabaseDataSize() const;
|
||||
|
||||
// If in-memory is true, then :memory: database is returned
|
||||
// In-memory database is DEFAULT database.
|
||||
// NOTE: This always returns OPENED database.
|
||||
QSqlDatabase connection(const QString& connection_name, DesiredType desired_type = DesiredType::FromSettings);
|
||||
|
||||
QString humanDriverName(UsedDriver driver) const;
|
||||
QString humanDriverName(const QString& driver_code) const;
|
||||
|
||||
// Removes connection.
|
||||
void removeConnection(const QString& connection_name = QString());
|
||||
|
||||
QString obtainBeginTransactionSql() const;
|
||||
|
||||
// Performs any needed database-related operation to be done
|
||||
// to gracefully exit the application.
|
||||
void saveDatabase();
|
||||
|
||||
// Performs cleanup of the database.
|
||||
bool vacuumDatabase();
|
||||
|
||||
// Returns identification of currently active database driver.
|
||||
UsedDriver activeDatabaseDriver() const;
|
||||
|
||||
// Copies selected backup database (file) to active database path.
|
||||
bool initiateRestoration(const QString& database_backup_file_path);
|
||||
|
||||
// Finishes restoration from backup file.
|
||||
void finishRestoration();
|
||||
|
||||
//
|
||||
// SQLITE stuff.
|
||||
//
|
||||
QString sqliteDatabaseFilePath() const;
|
||||
|
||||
//
|
||||
// MySQL stuff.
|
||||
//
|
||||
|
||||
// Tests if database connection with given data
|
||||
// can be established and returns 0 if it can.
|
||||
// Otherwise returns MySQL-specific error code.
|
||||
MySQLError mysqlTestConnection(const QString& hostname, int port, const QString& w_database,
|
||||
const QString& username, const QString& password);
|
||||
|
||||
// Interprets MySQL error code.
|
||||
QString mysqlInterpretErrorCode(MySQLError error_code) const;
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
// GENERAL stuff.
|
||||
//
|
||||
|
||||
// Decides which database backend will be used in this
|
||||
// application session.
|
||||
void determineDriver();
|
||||
|
||||
// Holds the type of currently activated database backend.
|
||||
UsedDriver m_activeDatabaseDriver;
|
||||
|
||||
//
|
||||
// MYSQL stuff.
|
||||
//
|
||||
|
||||
// Returns (always OPENED) MySQL database connection.
|
||||
QSqlDatabase mysqlConnection(const QString& connection_name);
|
||||
|
||||
// Initializes MySQL database.
|
||||
QSqlDatabase mysqlInitializeDatabase(const QString& connection_name);
|
||||
|
||||
// Updates database schema.
|
||||
bool mysqlUpdateDatabaseSchema(const QSqlDatabase& database, const QString& source_db_schema_version, const QString& db_name);
|
||||
|
||||
// Runs "VACUUM" on the database.
|
||||
bool mysqlVacuumDatabase();
|
||||
|
||||
// True if MySQL database is fully initialized for use,
|
||||
// otherwise false.
|
||||
bool m_mysqlDatabaseInitialized;
|
||||
|
||||
//
|
||||
// SQLITE stuff.
|
||||
//
|
||||
|
||||
QSqlDatabase sqliteConnection(const QString& connection_name, DesiredType desired_type);
|
||||
|
||||
// Runs "VACUUM" on the database.
|
||||
bool sqliteVacuumDatabase();
|
||||
|
||||
// Performs saving of items from in-memory database
|
||||
// to file-based database.
|
||||
void sqliteSaveMemoryDatabase();
|
||||
|
||||
// Assemblies database file path.
|
||||
void sqliteAssemblyDatabaseFilePath();
|
||||
|
||||
// Updates database schema.
|
||||
bool sqliteUpdateDatabaseSchema(const QSqlDatabase& database, const QString& source_db_schema_version);
|
||||
|
||||
// Creates new connection, initializes database and
|
||||
// returns opened connections.
|
||||
QSqlDatabase sqliteInitializeInMemoryDatabase();
|
||||
QSqlDatabase sqliteInitializeFileBasedDatabase(const QString& connection_name);
|
||||
|
||||
// Path to database file.
|
||||
QString m_sqliteDatabaseFilePath;
|
||||
|
||||
// Is database file initialized?
|
||||
bool m_sqliteFileBasedDatabaseInitialized;
|
||||
bool m_sqliteInMemoryDatabaseInitialized;
|
||||
};
|
||||
|
||||
#endif // DATABASEFACTORY_H
|
|
@ -10,7 +10,7 @@
|
|||
#include "core/messagesproxymodel.h"
|
||||
#include "gui/dialogs/formmessagefiltersmanager.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/mutex.h"
|
||||
#include "services/abstract/cacheforserviceroot.h"
|
||||
#include "services/abstract/serviceroot.h"
|
||||
|
@ -162,7 +162,7 @@ void FeedReader::loadSavedMessageFilters() {
|
|||
// Load all message filters from database.
|
||||
// All plugin services will hook active filters to
|
||||
// all feeds.
|
||||
m_messageFilters = DatabaseQueries::getMessageFilters(qApp->database()->connection(metaObject()->className()));
|
||||
m_messageFilters = DatabaseQueries::getMessageFilters(qApp->database()->driver()->connection(metaObject()->className()));
|
||||
|
||||
for (auto* filter : m_messageFilters) {
|
||||
filter->setParent(this);
|
||||
|
@ -170,7 +170,7 @@ void FeedReader::loadSavedMessageFilters() {
|
|||
}
|
||||
|
||||
MessageFilter* FeedReader::addMessageFilter(const QString& title, const QString& script) {
|
||||
auto* fltr = DatabaseQueries::addMessageFilter(qApp->database()->connection(metaObject()->className()), title, script);
|
||||
auto* fltr = DatabaseQueries::addMessageFilter(qApp->database()->driver()->connection(metaObject()->className()), title, script);
|
||||
|
||||
m_messageFilters.append(fltr);
|
||||
return fltr;
|
||||
|
@ -187,20 +187,20 @@ void FeedReader::removeMessageFilter(MessageFilter* filter) {
|
|||
}
|
||||
|
||||
// Remove from DB.
|
||||
DatabaseQueries::removeMessageFilterAssignments(qApp->database()->connection(metaObject()->className()), filter->id());
|
||||
DatabaseQueries::removeMessageFilter(qApp->database()->connection(metaObject()->className()), filter->id());
|
||||
DatabaseQueries::removeMessageFilterAssignments(qApp->database()->driver()->connection(metaObject()->className()), filter->id());
|
||||
DatabaseQueries::removeMessageFilter(qApp->database()->driver()->connection(metaObject()->className()), filter->id());
|
||||
|
||||
// Free from memory as last step.
|
||||
filter->deleteLater();
|
||||
}
|
||||
|
||||
void FeedReader::updateMessageFilter(MessageFilter* filter) {
|
||||
DatabaseQueries::updateMessageFilter(qApp->database()->connection(metaObject()->className()), filter);
|
||||
DatabaseQueries::updateMessageFilter(qApp->database()->driver()->connection(metaObject()->className()), filter);
|
||||
}
|
||||
|
||||
void FeedReader::assignMessageFilterToFeed(Feed* feed, MessageFilter* filter) {
|
||||
feed->appendMessageFilter(filter);
|
||||
DatabaseQueries::assignMessageFilterToFeed(qApp->database()->connection(metaObject()->className()),
|
||||
DatabaseQueries::assignMessageFilterToFeed(qApp->database()->driver()->connection(metaObject()->className()),
|
||||
feed->customId(),
|
||||
filter->id(),
|
||||
feed->getParentServiceRoot()->accountId());
|
||||
|
@ -208,7 +208,7 @@ void FeedReader::assignMessageFilterToFeed(Feed* feed, MessageFilter* filter) {
|
|||
|
||||
void FeedReader::removeMessageFilterToFeedAssignment(Feed* feed, MessageFilter* filter) {
|
||||
feed->removeMessageFilter(filter);
|
||||
DatabaseQueries::removeMessageFilterFromFeed(qApp->database()->connection(metaObject()->className()),
|
||||
DatabaseQueries::removeMessageFilterFromFeed(qApp->database()->driver()->connection(metaObject()->className()),
|
||||
feed->customId(),
|
||||
filter->id(),
|
||||
feed->getParentServiceRoot()->accountId());
|
||||
|
|
|
@ -376,7 +376,7 @@ void AdBlockRule::parseFilter() {
|
|||
#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
|
||||
Qt::SplitBehaviorFlags::SkipEmptyParts);
|
||||
#else
|
||||
QString::SkipEmptyParts);
|
||||
QString::SplitBehavior::SkipEmptyParts);
|
||||
#endif
|
||||
int handledOptions = 0;
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ QList<HttpResponse> Downloader::decodeMultipartAnswer(QNetworkReply* reply) {
|
|||
#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
|
||||
Qt::SplitBehaviorFlags::SkipEmptyParts);
|
||||
#else
|
||||
QString::SkipEmptyParts);
|
||||
QString::SplitBehavior::SkipEmptyParts);
|
||||
#endif
|
||||
|
||||
QList<HttpResponse> parts;
|
||||
|
@ -175,7 +175,7 @@ QList<HttpResponse> Downloader::decodeMultipartAnswer(QNetworkReply* reply) {
|
|||
#if QT_VERSION >= 0x050F00 // Qt >= 5.15.0
|
||||
Qt::SplitBehaviorFlags::SkipEmptyParts)) {
|
||||
#else
|
||||
QString::SkipEmptyParts)) {
|
||||
QString::SplitBehavior::SkipEmptyParts)) {
|
||||
#endif
|
||||
int index_colon = header_line.indexOf(QL1C(':'));
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "services/abstract/category.h"
|
||||
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/textfactory.h"
|
||||
#include "services/abstract/cacheforserviceroot.h"
|
||||
|
@ -34,7 +34,7 @@ void Category::updateCounts(bool including_total_count) {
|
|||
return;
|
||||
}
|
||||
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
bool ok;
|
||||
QMap<QString, QPair<int, int>> counts = DatabaseQueries::getMessageCountsForCategory(database,
|
||||
customId(),
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "definitions/definitions.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/feedreader.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/mutex.h"
|
||||
|
@ -45,7 +45,7 @@ Feed::Feed(const Feed& other) : RootItem(other) {
|
|||
}
|
||||
|
||||
QList<Message> Feed::undeletedMessages() const {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
return DatabaseQueries::getUndeletedMessagesForFeed(database, customId(), getParentServiceRoot()->accountId());
|
||||
}
|
||||
|
@ -161,8 +161,8 @@ void Feed::appendMessageFilter(MessageFilter* filter) {
|
|||
void Feed::updateCounts(bool including_total_count) {
|
||||
bool is_main_thread = QThread::currentThread() == qApp->thread();
|
||||
QSqlDatabase database = is_main_thread ?
|
||||
qApp->database()->connection(metaObject()->className()) :
|
||||
qApp->database()->connection(QSL("feed_upd"));
|
||||
qApp->database()->driver()->connection(metaObject()->className()) :
|
||||
qApp->database()->driver()->connection(QSL("feed_upd"));
|
||||
int account_id = getParentServiceRoot()->accountId();
|
||||
|
||||
if (including_total_count) {
|
||||
|
@ -208,8 +208,8 @@ int Feed::updateMessages(const QList<Message>& messages, bool error_during_obtai
|
|||
QString custom_id = customId();
|
||||
int account_id = getParentServiceRoot()->accountId();
|
||||
QSqlDatabase database = is_main_thread ?
|
||||
qApp->database()->connection(metaObject()->className()) :
|
||||
qApp->database()->connection(QSL("feed_upd"));
|
||||
qApp->database()->driver()->connection(metaObject()->className()) :
|
||||
qApp->database()->driver()->connection(QSL("feed_upd"));
|
||||
|
||||
updated_messages = DatabaseQueries::updateMessages(database, messages, custom_id, account_id,
|
||||
source(), force_update, &anything_updated, &ok);
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
#include "gui/networkproxydetails.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasefactory.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasefactory.h"
|
||||
#include "database/databasequeries.h"
|
||||
|
||||
class ServiceRoot;
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "gui/feedsview.h"
|
||||
#include "gui/messagebox.h"
|
||||
#include "gui/systemtrayicon.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "services/abstract/category.h"
|
||||
#include "services/abstract/rootitem.h"
|
||||
|
@ -91,7 +91,7 @@ void FormCategoryDetails::apply() {
|
|||
m_category->setDescription(m_ui->m_txtDescription->lineEdit()->text());
|
||||
m_category->setIcon(m_ui->m_btnIcon->icon());
|
||||
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
DatabaseQueries::createOverwriteCategory(database, m_category, m_serviceRoot->accountId(), parent->id());
|
||||
m_serviceRoot->requestItemReassignment(m_category, parent);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "gui/guiutilities.h"
|
||||
#include "gui/messagebox.h"
|
||||
#include "gui/systemtrayicon.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/textfactory.h"
|
||||
#include "network-web/networkfactory.h"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "services/abstract/importantnode.h"
|
||||
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "services/abstract/cacheforserviceroot.h"
|
||||
#include "services/abstract/serviceroot.h"
|
||||
|
@ -20,7 +20,7 @@ ImportantNode::ImportantNode(RootItem* parent_item) : RootItem(parent_item) {
|
|||
}
|
||||
|
||||
QList<Message> ImportantNode::undeletedMessages() const {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
return DatabaseQueries::getUndeletedImportantMessages(database, getParentServiceRoot()->accountId());
|
||||
}
|
||||
|
@ -28,8 +28,8 @@ QList<Message> ImportantNode::undeletedMessages() const {
|
|||
void ImportantNode::updateCounts(bool including_total_count) {
|
||||
bool is_main_thread = QThread::currentThread() == qApp->thread();
|
||||
QSqlDatabase database = is_main_thread ?
|
||||
qApp->database()->connection(metaObject()->className()) :
|
||||
qApp->database()->connection(QSL("feed_upd"));
|
||||
qApp->database()->driver()->connection(metaObject()->className()) :
|
||||
qApp->database()->driver()->connection(QSL("feed_upd"));
|
||||
int account_id = getParentServiceRoot()->accountId();
|
||||
|
||||
if (including_total_count) {
|
||||
|
@ -41,7 +41,7 @@ void ImportantNode::updateCounts(bool including_total_count) {
|
|||
|
||||
bool ImportantNode::cleanMessages(bool clean_read_only) {
|
||||
ServiceRoot* service = getParentServiceRoot();
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
if (DatabaseQueries::cleanImportantMessages(database, clean_read_only, service->accountId())) {
|
||||
service->updateCounts(true);
|
||||
|
@ -62,7 +62,7 @@ bool ImportantNode::markAsReadUnread(RootItem::ReadStatus status) {
|
|||
cache->addMessageStatesToCache(service->customIDSOfMessagesForItem(this), status);
|
||||
}
|
||||
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
if (DatabaseQueries::markImportantMessagesReadUnread(database, service->accountId(), status)) {
|
||||
service->updateCounts(false);
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
#include "gui/dialogs/formaddeditlabel.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasefactory.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasefactory.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "services/abstract/cacheforserviceroot.h"
|
||||
#include "services/abstract/labelsnode.h"
|
||||
#include "services/abstract/serviceroot.h"
|
||||
|
@ -49,7 +49,7 @@ bool Label::editViaGui() {
|
|||
FormAddEditLabel form(qApp->mainFormWidget());
|
||||
|
||||
if (form.execForEdit(this)) {
|
||||
QSqlDatabase db = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase db = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
return DatabaseQueries::updateLabel(db, this);
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ bool Label::canBeDeleted() const {
|
|||
}
|
||||
|
||||
bool Label::deleteViaGui() {
|
||||
QSqlDatabase db = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase db = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
if (DatabaseQueries::deleteLabel(db, this)) {
|
||||
getParentServiceRoot()->requestItemRemoval(this);
|
||||
|
@ -78,8 +78,8 @@ bool Label::deleteViaGui() {
|
|||
void Label::updateCounts(bool including_total_count) {
|
||||
bool is_main_thread = QThread::currentThread() == qApp->thread();
|
||||
QSqlDatabase database = is_main_thread ?
|
||||
qApp->database()->connection(metaObject()->className()) :
|
||||
qApp->database()->connection(QSL("feed_upd"));
|
||||
qApp->database()->driver()->connection(metaObject()->className()) :
|
||||
qApp->database()->driver()->connection(QSL("feed_upd"));
|
||||
int account_id = getParentServiceRoot()->accountId();
|
||||
|
||||
if (including_total_count) {
|
||||
|
@ -90,7 +90,7 @@ void Label::updateCounts(bool including_total_count) {
|
|||
}
|
||||
|
||||
QList<Message> Label::undeletedMessages() const {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
return DatabaseQueries::getUndeletedMessagesWithLabel(database, this);
|
||||
}
|
||||
|
@ -112,8 +112,8 @@ QIcon Label::generateIcon(const QColor& color) {
|
|||
void Label::assignToMessage(const Message& msg) {
|
||||
bool is_main_thread = QThread::currentThread() == qApp->thread();
|
||||
QSqlDatabase database = is_main_thread ?
|
||||
qApp->database()->connection(metaObject()->className()) :
|
||||
qApp->database()->connection(QSL("feed_upd"));
|
||||
qApp->database()->driver()->connection(metaObject()->className()) :
|
||||
qApp->database()->driver()->connection(QSL("feed_upd"));
|
||||
|
||||
if (getParentServiceRoot()->onBeforeLabelMessageAssignmentChanged({ this }, { msg }, true)) {
|
||||
DatabaseQueries::assignLabelToMessage(database, this, msg);
|
||||
|
@ -125,8 +125,8 @@ void Label::assignToMessage(const Message& msg) {
|
|||
void Label::deassignFromMessage(const Message& msg) {
|
||||
bool is_main_thread = QThread::currentThread() == qApp->thread();
|
||||
QSqlDatabase database = is_main_thread ?
|
||||
qApp->database()->connection(metaObject()->className()) :
|
||||
qApp->database()->connection(QSL("feed_upd"));
|
||||
qApp->database()->driver()->connection(metaObject()->className()) :
|
||||
qApp->database()->driver()->connection(QSL("feed_upd"));
|
||||
|
||||
if (getParentServiceRoot()->onBeforeLabelMessageAssignmentChanged({ this }, { msg }, false)) {
|
||||
DatabaseQueries::deassignLabelFromMessage(database, this, msg);
|
||||
|
@ -145,7 +145,7 @@ void Label::setCountOfUnreadMessages(int unreadCount) {
|
|||
|
||||
bool Label::cleanMessages(bool clear_only_read) {
|
||||
ServiceRoot* service = getParentServiceRoot();
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
if (DatabaseQueries::cleanLabelledMessages(database, clear_only_read, this)) {
|
||||
service->updateCounts(true);
|
||||
|
@ -166,7 +166,7 @@ bool Label::markAsReadUnread(RootItem::ReadStatus status) {
|
|||
cache->addMessageStatesToCache(service->customIDSOfMessagesForItem(this), status);
|
||||
}
|
||||
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
if (DatabaseQueries::markLabelledMessagesReadUnread(database, this, status)) {
|
||||
service->updateCounts(false);
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
#include "gui/dialogs/formaddeditlabel.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasefactory.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasefactory.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "services/abstract/serviceroot.h"
|
||||
|
||||
|
@ -27,7 +27,7 @@ void LabelsNode::loadLabels(const QList<Label*>& labels) {
|
|||
}
|
||||
|
||||
QList<Message> LabelsNode::undeletedMessages() const {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
return DatabaseQueries::getUndeletedLabelledMessages(database, getParentServiceRoot()->accountId());
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ void LabelsNode::createLabel() {
|
|||
Label* new_lbl = frm.execForAdd();
|
||||
|
||||
if (new_lbl != nullptr) {
|
||||
QSqlDatabase db = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase db = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
DatabaseQueries::createLabel(db, new_lbl, getParentServiceRoot()->accountId());
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "services/abstract/recyclebin.h"
|
||||
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/textfactory.h"
|
||||
#include "services/abstract/cacheforserviceroot.h"
|
||||
|
@ -36,8 +36,8 @@ int RecycleBin::countOfAllMessages() const {
|
|||
void RecycleBin::updateCounts(bool update_total_count) {
|
||||
bool is_main_thread = QThread::currentThread() == qApp->thread();
|
||||
QSqlDatabase database = is_main_thread ?
|
||||
qApp->database()->connection(metaObject()->className()) :
|
||||
qApp->database()->connection(QSL("feed_upd"));
|
||||
qApp->database()->driver()->connection(metaObject()->className()) :
|
||||
qApp->database()->driver()->connection(QSL("feed_upd"));
|
||||
|
||||
m_unreadCount = DatabaseQueries::getMessageCountsForBin(database, getParentServiceRoot()->accountId(), false);
|
||||
|
||||
|
@ -67,13 +67,13 @@ QList<QAction*> RecycleBin::contextMenuFeedsList() {
|
|||
|
||||
QList<Message> RecycleBin::undeletedMessages() const {
|
||||
const int account_id = getParentServiceRoot()->accountId();
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
return DatabaseQueries::getUndeletedMessagesForBin(database, account_id);
|
||||
}
|
||||
|
||||
bool RecycleBin::markAsReadUnread(RootItem::ReadStatus status) {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
ServiceRoot* parent_root = getParentServiceRoot();
|
||||
auto* cache = dynamic_cast<CacheForServiceRoot*>(parent_root);
|
||||
|
||||
|
@ -93,7 +93,7 @@ bool RecycleBin::markAsReadUnread(RootItem::ReadStatus status) {
|
|||
}
|
||||
|
||||
bool RecycleBin::cleanMessages(bool clear_only_read) {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
ServiceRoot* parent_root = getParentServiceRoot();
|
||||
|
||||
if (DatabaseQueries::purgeMessagesFromBin(database, clear_only_read, parent_root->accountId())) {
|
||||
|
@ -112,7 +112,7 @@ bool RecycleBin::empty() {
|
|||
}
|
||||
|
||||
bool RecycleBin::restore() {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
ServiceRoot* parent_root = getParentServiceRoot();
|
||||
|
||||
if (DatabaseQueries::restoreBin(database, parent_root->accountId())) {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "core/feedsmodel.h"
|
||||
#include "core/messagesmodel.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/textfactory.h"
|
||||
#include "services/abstract/cacheforserviceroot.h"
|
||||
|
@ -28,7 +28,7 @@ ServiceRoot::ServiceRoot(RootItem* parent)
|
|||
ServiceRoot::~ServiceRoot() = default;
|
||||
|
||||
bool ServiceRoot::deleteViaGui() {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
if (DatabaseQueries::deleteAccount(database, accountId())) {
|
||||
stop();
|
||||
|
@ -47,7 +47,7 @@ bool ServiceRoot::markAsReadUnread(RootItem::ReadStatus status) {
|
|||
cache->addMessageStatesToCache(customIDSOfMessagesForItem(this), status);
|
||||
}
|
||||
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
if (DatabaseQueries::markAccountReadUnread(database, accountId(), status)) {
|
||||
updateCounts(false);
|
||||
|
@ -135,7 +135,7 @@ void ServiceRoot::updateCounts(bool including_total_count) {
|
|||
return;
|
||||
}
|
||||
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
bool ok;
|
||||
QMap<QString, QPair<int, int>> counts = DatabaseQueries::getMessageCountsForAccount(database, accountId(), including_total_count, &ok);
|
||||
|
||||
|
@ -187,7 +187,7 @@ QIcon ServiceRoot::feedIconForMessage(const QString& feed_custom_id) const {
|
|||
}
|
||||
|
||||
void ServiceRoot::removeOldAccountFromDatabase(bool including_messages) {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
DatabaseQueries::deleteAccountData(database, accountId(), including_messages);
|
||||
}
|
||||
|
@ -225,7 +225,7 @@ void ServiceRoot::appendCommonNodes() {
|
|||
}
|
||||
|
||||
bool ServiceRoot::cleanFeeds(QList<Feed*> items, bool clean_read_only) {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
if (DatabaseQueries::cleanFeeds(database, textualFeedIds(items), clean_read_only, accountId())) {
|
||||
getParentServiceRoot()->updateCounts(true);
|
||||
|
@ -239,29 +239,29 @@ bool ServiceRoot::cleanFeeds(QList<Feed*> items, bool clean_read_only) {
|
|||
}
|
||||
|
||||
void ServiceRoot::storeNewFeedTree(RootItem* root) {
|
||||
DatabaseQueries::storeAccountTree(qApp->database()->connection(metaObject()->className()), root, accountId());
|
||||
DatabaseQueries::storeAccountTree(qApp->database()->driver()->connection(metaObject()->className()), root, accountId());
|
||||
}
|
||||
|
||||
void ServiceRoot::removeLeftOverMessages() {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
DatabaseQueries::purgeLeftoverMessages(database, accountId());
|
||||
}
|
||||
|
||||
void ServiceRoot::removeLeftOverMessageFilterAssignments() {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
DatabaseQueries::purgeLeftoverMessageFilterAssignments(database, accountId());
|
||||
}
|
||||
|
||||
void ServiceRoot::removeLeftOverMessageLabelAssignments() {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
DatabaseQueries::purgeLeftoverLabelAssignments(database, accountId());
|
||||
}
|
||||
|
||||
QList<Message> ServiceRoot::undeletedMessages() const {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
return DatabaseQueries::getUndeletedMessagesForAccount(database, accountId());
|
||||
}
|
||||
|
@ -279,7 +279,7 @@ ServiceRoot::LabelOperation ServiceRoot::supportedLabelOperations() const {
|
|||
}
|
||||
|
||||
void ServiceRoot::saveAccountDataToDatabase() {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
DatabaseQueries::createOverwriteAccount(database, this);
|
||||
}
|
||||
|
@ -461,35 +461,35 @@ QStringList ServiceRoot::customIDSOfMessagesForItem(RootItem* item) {
|
|||
}
|
||||
|
||||
case RootItem::Kind::Label: {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
list = DatabaseQueries::customIdsOfMessagesFromLabel(database, item->toLabel());
|
||||
break;
|
||||
}
|
||||
|
||||
case RootItem::Kind::ServiceRoot: {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
list = DatabaseQueries::customIdsOfMessagesFromAccount(database, accountId());
|
||||
break;
|
||||
}
|
||||
|
||||
case RootItem::Kind::Bin: {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
list = DatabaseQueries::customIdsOfMessagesFromBin(database, accountId());
|
||||
break;
|
||||
}
|
||||
|
||||
case RootItem::Kind::Feed: {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
list = DatabaseQueries::customIdsOfMessagesFromFeed(database, item->customId(), accountId());
|
||||
break;
|
||||
}
|
||||
|
||||
case RootItem::Kind::Important: {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
list = DatabaseQueries::customIdsOfImportantMessages(database, accountId());
|
||||
break;
|
||||
|
@ -505,7 +505,7 @@ QStringList ServiceRoot::customIDSOfMessagesForItem(RootItem* item) {
|
|||
}
|
||||
|
||||
bool ServiceRoot::markFeedsReadUnread(QList<Feed*> items, RootItem::ReadStatus read) {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
if (DatabaseQueries::markFeedsReadUnread(database, textualFeedIds(items), accountId(), read)) {
|
||||
getParentServiceRoot()->updateCounts(false);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "definitions/definitions.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "services/feedly/definitions.h"
|
||||
#include "services/feedly/feedlyserviceroot.h"
|
||||
|
@ -17,7 +17,7 @@ ServiceRoot* FeedlyEntryPoint::createNewRoot() const {
|
|||
}
|
||||
|
||||
QList<ServiceRoot*> FeedlyEntryPoint::initializeSubtree() const {
|
||||
QSqlDatabase database = qApp->database()->connection(QSL("FeedlyEntryPoint"));
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(QSL("FeedlyEntryPoint"));
|
||||
|
||||
return DatabaseQueries::getAccounts<FeedlyServiceRoot>(database, code());
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "3rd-party/boolinq/boolinq.h"
|
||||
#include "exceptions/networkexception.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "network-web/networkfactory.h"
|
||||
#include "network-web/webfactory.h"
|
||||
#include "services/abstract/category.h"
|
||||
|
@ -520,7 +520,7 @@ void FeedlyNetwork::onTokensRetrieved(const QString& access_token, const QString
|
|||
Q_UNUSED(access_token)
|
||||
|
||||
if (m_service != nullptr && !refresh_token.isEmpty()) {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
DatabaseQueries::storeNewOauthTokens(database, refresh_token, m_service->accountId());
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "exceptions/applicationexception.h"
|
||||
#include "exceptions/networkexception.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/mutex.h"
|
||||
#include "miscellaneous/textfactory.h"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "definitions/definitions.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "services/gmail/definitions.h"
|
||||
#include "services/gmail/gmailserviceroot.h"
|
||||
|
@ -19,7 +19,7 @@ ServiceRoot* GmailEntryPoint::createNewRoot() const {
|
|||
}
|
||||
|
||||
QList<ServiceRoot*> GmailEntryPoint::initializeSubtree() const {
|
||||
QSqlDatabase database = qApp->database()->connection(QSL("GmailEntryPoint"));
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(QSL("GmailEntryPoint"));
|
||||
|
||||
return DatabaseQueries::getAccounts<GmailServiceRoot>(database, code());
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "gui/dialogs/formmain.h"
|
||||
#include "gui/tabwidget.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/textfactory.h"
|
||||
#include "network-web/networkfactory.h"
|
||||
#include "network-web/oauth2service.h"
|
||||
|
@ -133,7 +133,7 @@ void GmailNetworkFactory::initializeOauth() {
|
|||
Q_UNUSED(access_token)
|
||||
|
||||
if (m_service != nullptr && !refresh_token.isEmpty()) {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
DatabaseQueries::storeNewOauthTokens(database, refresh_token, m_service->accountId());
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "services/gmail/gmailserviceroot.h"
|
||||
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "network-web/oauth2service.h"
|
||||
#include "services/abstract/importantnode.h"
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "gui/guiutilities.h"
|
||||
#include "gui/messagebox.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "services/gmail/gmailnetworkfactory.h"
|
||||
#include "services/gmail/gmailserviceroot.h"
|
||||
|
@ -38,7 +38,7 @@ FormAddEditEmail::FormAddEditEmail(GmailServiceRoot* root, QWidget* parent)
|
|||
this,
|
||||
&FormAddEditEmail::onOkClicked);
|
||||
|
||||
QSqlDatabase db = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase db = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
m_possibleRecipients = DatabaseQueries::getAllRecipients(db, m_root->accountId());
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "definitions/definitions.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "services/greader/definitions.h"
|
||||
#include "services/greader/greaderserviceroot.h"
|
||||
|
@ -17,7 +17,7 @@ ServiceRoot* GreaderEntryPoint::createNewRoot() const {
|
|||
}
|
||||
|
||||
QList<ServiceRoot*> GreaderEntryPoint::initializeSubtree() const {
|
||||
QSqlDatabase database = qApp->database()->connection(QSL("GreaderEntryPoint"));
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(QSL("GreaderEntryPoint"));
|
||||
|
||||
return DatabaseQueries::getAccounts<GreaderServiceRoot>(database, code());
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "definitions/definitions.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/mutex.h"
|
||||
#include "miscellaneous/textfactory.h"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "definitions/definitions.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "services/inoreader/definitions.h"
|
||||
#include "services/inoreader/gui/formeditinoreaderaccount.h"
|
||||
|
@ -20,7 +20,7 @@ ServiceRoot* InoreaderEntryPoint::createNewRoot() const {
|
|||
}
|
||||
|
||||
QList<ServiceRoot*> InoreaderEntryPoint::initializeSubtree() const {
|
||||
QSqlDatabase database = qApp->database()->connection(QSL("InoreaderEntryPoint"));
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(QSL("InoreaderEntryPoint"));
|
||||
|
||||
return DatabaseQueries::getAccounts<InoreaderServiceRoot>(database, code());
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "gui/dialogs/formmain.h"
|
||||
#include "gui/tabwidget.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "network-web/networkfactory.h"
|
||||
#include "network-web/oauth2service.h"
|
||||
#include "network-web/silentnetworkaccessmanager.h"
|
||||
|
@ -68,7 +68,7 @@ void InoreaderNetworkFactory::initializeOauth() {
|
|||
Q_UNUSED(access_token)
|
||||
|
||||
if (m_service != nullptr && m_service->accountId() > 0 && !refresh_token.isEmpty()) {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
DatabaseQueries::storeNewOauthTokens(database, refresh_token, m_service->accountId());
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "services/inoreader/inoreaderserviceroot.h"
|
||||
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "network-web/oauth2service.h"
|
||||
#include "services/abstract/importantnode.h"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "services/owncloud/owncloudfeed.h"
|
||||
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "services/owncloud/owncloudnetworkfactory.h"
|
||||
#include "services/owncloud/owncloudserviceroot.h"
|
||||
|
@ -27,7 +27,7 @@ bool OwnCloudFeed::deleteViaGui() {
|
|||
}
|
||||
|
||||
bool OwnCloudFeed::removeItself() {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
return DatabaseQueries::deleteFeed(database, customId().toInt(), serviceRoot()->accountId());
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "definitions/definitions.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "services/owncloud/definitions.h"
|
||||
#include "services/owncloud/gui/formeditowncloudaccount.h"
|
||||
|
@ -17,7 +17,7 @@ ServiceRoot* OwnCloudServiceEntryPoint::createNewRoot() const {
|
|||
}
|
||||
|
||||
QList<ServiceRoot*> OwnCloudServiceEntryPoint::initializeSubtree() const {
|
||||
QSqlDatabase database = qApp->database()->connection(QSL("OwnCloudServiceEntryPoint"));
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(QSL("OwnCloudServiceEntryPoint"));
|
||||
|
||||
return DatabaseQueries::getAccounts<OwnCloudServiceRoot>(database, code());
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "definitions/definitions.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/mutex.h"
|
||||
#include "miscellaneous/textfactory.h"
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
#include "services/standard/gui/formeditstandardaccount.h"
|
||||
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasefactory.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasefactory.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "services/standard/standardserviceroot.h"
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "services/standard/gui/formstandardfeeddetails.h"
|
||||
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "network-web/networkfactory.h"
|
||||
#include "services/abstract/category.h"
|
||||
|
@ -79,7 +79,7 @@ void FormStandardFeedDetails::apply() {
|
|||
std_feed->setUsername(m_authDetails->m_txtUsername->lineEdit()->text());
|
||||
std_feed->setPassword(m_authDetails->m_txtPassword->lineEdit()->text());
|
||||
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
DatabaseQueries::createOverwriteFeed(database, std_feed, m_serviceRoot->accountId(), parent->id());
|
||||
m_serviceRoot->requestItemReassignment(m_feed, parent);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "definitions/definitions.h"
|
||||
#include "gui/feedmessageviewer.h"
|
||||
#include "gui/feedsview.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/settings.h"
|
||||
#include "miscellaneous/textfactory.h"
|
||||
|
@ -27,7 +27,7 @@ Qt::ItemFlags StandardCategory::additionalFlags() const {
|
|||
}
|
||||
|
||||
bool StandardCategory::performDragDropChange(RootItem* target_item) {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
DatabaseQueries::createOverwriteCategory(database, this, getParentServiceRoot()->accountId(), target_item->id());
|
||||
serviceRoot()->requestItemReassignment(this, target_item);
|
||||
|
@ -77,7 +77,7 @@ bool StandardCategory::removeItself() {
|
|||
|
||||
if (children_removed) {
|
||||
// Children are removed, remove this standard category too.
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
return DatabaseQueries::deleteCategory(database, id());
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "exceptions/scriptexception.h"
|
||||
#include "gui/feedmessageviewer.h"
|
||||
#include "gui/feedsview.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/settings.h"
|
||||
#include "miscellaneous/simplecrypt/simplecrypt.h"
|
||||
|
@ -202,7 +202,7 @@ void StandardFeed::fetchMetadataForItself() {
|
|||
setIcon(metadata->icon());
|
||||
delete metadata;
|
||||
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
DatabaseQueries::createOverwriteFeed(database, this, getParentServiceRoot()->accountId(), parent()->id());
|
||||
|
||||
|
@ -500,7 +500,7 @@ Qt::ItemFlags StandardFeed::additionalFlags() const {
|
|||
}
|
||||
|
||||
bool StandardFeed::performDragDropChange(RootItem* target_item) {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
DatabaseQueries::createOverwriteFeed(database, this, getParentServiceRoot()->accountId(), target_item->id());
|
||||
serviceRoot()->requestItemReassignment(this, target_item);
|
||||
|
@ -508,7 +508,7 @@ bool StandardFeed::performDragDropChange(RootItem* target_item) {
|
|||
}
|
||||
|
||||
bool StandardFeed::removeItself() {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
return DatabaseQueries::deleteFeed(database, customId().toInt(), getParentServiceRoot()->accountId());
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "definitions/definitions.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "services/standard/gui/formeditstandardaccount.h"
|
||||
#include "services/standard/standardserviceroot.h"
|
||||
|
||||
|
@ -36,7 +36,7 @@ ServiceRoot* StandardServiceEntryPoint::createNewRoot() const {
|
|||
|
||||
QList<ServiceRoot*> StandardServiceEntryPoint::initializeSubtree() const {
|
||||
// Check DB if standard account is enabled.
|
||||
QSqlDatabase database = qApp->database()->connection(QSL("StandardServiceEntryPoint"));
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(QSL("StandardServiceEntryPoint"));
|
||||
|
||||
return DatabaseQueries::getAccounts<StandardServiceRoot>(database, code());
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "exceptions/scriptexception.h"
|
||||
#include "gui/messagebox.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/mutex.h"
|
||||
#include "miscellaneous/settings.h"
|
||||
|
@ -344,7 +344,7 @@ bool StandardServiceRoot::mergeImportExportModel(FeedsImportExportModel* model,
|
|||
// Add category to model.
|
||||
new_category->clearChildren();
|
||||
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
try {
|
||||
DatabaseQueries::createOverwriteCategory(database,
|
||||
|
@ -380,7 +380,7 @@ bool StandardServiceRoot::mergeImportExportModel(FeedsImportExportModel* model,
|
|||
else if (source_item->kind() == RootItem::Kind::Feed) {
|
||||
auto* source_feed = dynamic_cast<StandardFeed*>(source_item);
|
||||
auto* new_feed = new StandardFeed(*source_feed);
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
DatabaseQueries::createOverwriteFeed(database,
|
||||
new_feed,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "definitions/definitions.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/textfactory.h"
|
||||
#include "services/tt-rss/definitions.h"
|
||||
|
@ -40,7 +40,7 @@ bool TtRssFeed::deleteViaGui() {
|
|||
}
|
||||
|
||||
bool TtRssFeed::removeItself() {
|
||||
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className());
|
||||
|
||||
return DatabaseQueries::deleteFeed(database, customId().toInt(), serviceRoot()->accountId());
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "services/tt-rss/ttrssserviceentrypoint.h"
|
||||
|
||||
#include "definitions/definitions.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "services/tt-rss/definitions.h"
|
||||
#include "services/tt-rss/gui/formeditttrssaccount.h"
|
||||
|
@ -40,7 +40,7 @@ ServiceRoot* TtRssServiceEntryPoint::createNewRoot() const {
|
|||
|
||||
QList<ServiceRoot*> TtRssServiceEntryPoint::initializeSubtree() const {
|
||||
// Check DB if standard account is enabled.
|
||||
QSqlDatabase database = qApp->database()->connection(QSL("TtRssServiceEntryPoint"));
|
||||
QSqlDatabase database = qApp->database()->driver()->connection(QSL("TtRssServiceEntryPoint"));
|
||||
|
||||
return DatabaseQueries::getAccounts<TtRssServiceRoot>(database, code());
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "services/tt-rss/ttrssserviceroot.h"
|
||||
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/databasequeries.h"
|
||||
#include "database/databasequeries.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/mutex.h"
|
||||
#include "miscellaneous/settings.h"
|
||||
|
|
Loading…
Add table
Reference in a new issue