diff --git a/resources/sql/db_init_mysql.sql b/resources/sql/db_init_mysql.sql index 18d7b050f..dae41c461 100644 --- a/resources/sql/db_init_mysql.sql +++ b/resources/sql/db_init_mysql.sql @@ -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 -); \ No newline at end of file +!! db_init_sqlite.sql \ No newline at end of file diff --git a/src/librssguard/core/feeddownloader.cpp b/src/librssguard/core/feeddownloader.cpp index 805b450ad..2426340d4 100644 --- a/src/librssguard/core/feeddownloader.cpp +++ b/src/librssguard/core/feeddownloader.cpp @@ -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; diff --git a/src/librssguard/core/feedsmodel.cpp b/src/librssguard/core/feedsmodel.cpp index 76bd0d19e..789eac837 100644 --- a/src/librssguard/core/feedsmodel.cpp +++ b/src/librssguard/core/feedsmodel.cpp @@ -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" diff --git a/src/librssguard/core/message.cpp b/src/librssguard/core/message.cpp index e7fb4fdce..880517be7 100644 --- a/src/librssguard/core/message.cpp +++ b/src/librssguard/core/message.cpp @@ -25,7 +25,7 @@ QList 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; diff --git a/src/librssguard/core/messagesmodel.cpp b/src/librssguard/core/messagesmodel.cpp index 6bb0abfc1..4facede41 100644 --- a/src/librssguard/core/messagesmodel.cpp +++ b/src/librssguard/core/messagesmodel.cpp @@ -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" diff --git a/src/librssguard/core/messagesmodelsqllayer.cpp b/src/librssguard/core/messagesmodelsqllayer.cpp index d47e3133d..dcb4c4b13 100644 --- a/src/librssguard/core/messagesmodelsqllayer.cpp +++ b/src/librssguard/core/messagesmodelsqllayer.cpp @@ -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 : SELECT , FROM ....; m_fieldNames = DatabaseQueries::messageTableAttributes(false); diff --git a/src/librssguard/miscellaneous/databasecleaner.cpp b/src/librssguard/database/databasecleaner.cpp similarity index 92% rename from src/librssguard/miscellaneous/databasecleaner.cpp rename to src/librssguard/database/databasecleaner.cpp index 868aa3333..6ca3372ee 100644 --- a/src/librssguard/miscellaneous/databasecleaner.cpp +++ b/src/librssguard/database/databasecleaner.cpp @@ -1,9 +1,9 @@ // For license of this file, see /LICENSE.md. -#include "miscellaneous/databasecleaner.h" +#include "database/databasecleaner.h" +#include "database/databasequeries.h" #include "miscellaneous/application.h" -#include "miscellaneous/databasequeries.h" #include #include @@ -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...")); } diff --git a/src/librssguard/miscellaneous/databasecleaner.h b/src/librssguard/database/databasecleaner.h similarity index 97% rename from src/librssguard/miscellaneous/databasecleaner.h rename to src/librssguard/database/databasecleaner.h index 64774232f..cefcce221 100644 --- a/src/librssguard/miscellaneous/databasecleaner.h +++ b/src/librssguard/database/databasecleaner.h @@ -20,8 +20,6 @@ class DatabaseCleaner : public QObject { Q_OBJECT public: - - // Constructors. explicit DatabaseCleaner(QObject* parent = nullptr); virtual ~DatabaseCleaner() = default; diff --git a/src/librssguard/database/databasedriver.cpp b/src/librssguard/database/databasedriver.cpp new file mode 100755 index 000000000..10a2d7404 --- /dev/null +++ b/src/librssguard/database/databasedriver.cpp @@ -0,0 +1,49 @@ +// For license of this file, see /LICENSE.md. + +#include "database/databasedriver.h" + +#include "definitions/definitions.h" +#include "exceptions/ioexception.h" +#include "miscellaneous/iofactory.h" + +#include +#include + +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; +} diff --git a/src/librssguard/database/databasedriver.h b/src/librssguard/database/databasedriver.h new file mode 100755 index 000000000..6ad08fbfd --- /dev/null +++ b/src/librssguard/database/databasedriver.h @@ -0,0 +1,50 @@ +// For license of this file, see /LICENSE.md. + +#ifndef DATABASEDRIVER_H +#define DATABASEDRIVER_H + +#include + +#include + +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 diff --git a/src/librssguard/database/databasefactory.cpp b/src/librssguard/database/databasefactory.cpp new file mode 100644 index 000000000..53e80825a --- /dev/null +++ b/src/librssguard/database/databasefactory.cpp @@ -0,0 +1,81 @@ +// For license of this file, see /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 +#include +#include +#include + +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(); + } + 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(); +} diff --git a/src/librssguard/database/databasefactory.h b/src/librssguard/database/databasefactory.h new file mode 100644 index 000000000..3de83aab0 --- /dev/null +++ b/src/librssguard/database/databasefactory.h @@ -0,0 +1,47 @@ +// For license of this file, see /LICENSE.md. + +#ifndef DATABASEFACTORY_H +#define DATABASEFACTORY_H + +#include + +#include "database/databasedriver.h" + +#include + +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 m_allDbDrivers; + DatabaseDriver* m_dbDriver; +}; + +#endif // DATABASEFACTORY_H diff --git a/src/librssguard/miscellaneous/databasequeries.cpp b/src/librssguard/database/databasequeries.cpp similarity index 99% rename from src/librssguard/miscellaneous/databasequeries.cpp rename to src/librssguard/database/databasequeries.cpp index a7aef6be3..513117a4b 100755 --- a/src/librssguard/miscellaneous/databasequeries.cpp +++ b/src/librssguard/database/databasequeries.cpp @@ -1,6 +1,6 @@ // For license of this file, see /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) { diff --git a/src/librssguard/miscellaneous/databasequeries.h b/src/librssguard/database/databasequeries.h similarity index 99% rename from src/librssguard/miscellaneous/databasequeries.h rename to src/librssguard/database/databasequeries.h index 4902d73de..d6318f7ee 100644 --- a/src/librssguard/miscellaneous/databasequeries.h +++ b/src/librssguard/database/databasequeries.h @@ -319,7 +319,7 @@ Assignment DatabaseQueries::getFeeds(const QSqlDatabase& db, template 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(database, root->accountId()); Assignment feeds = DatabaseQueries::getFeeds(database, qApp->feedReader()->messageFilters(), root->accountId()); auto labels = DatabaseQueries::getLabelsForAccount(database, root->accountId()); diff --git a/src/librssguard/database/sqlitedriver.cpp b/src/librssguard/database/sqlitedriver.cpp new file mode 100755 index 000000000..7cfe7d3a5 --- /dev/null +++ b/src/librssguard/database/sqlitedriver.cpp @@ -0,0 +1,492 @@ +// For license of this file, see /LICENSE.md. + +#include "database/sqlitedriver.h" + +#include "exceptions/applicationexception.h" +#include "exceptions/ioexception.h" +#include "miscellaneous/application.h" + +#include +#include +#include + +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(); + } + else { + return 0; + } + + if (query.exec(QSL("PRAGMA page_size;"))) { + query.next(); + result *= query.value(0).value(); + } + 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.")); + } +} diff --git a/src/librssguard/database/sqlitedriver.h b/src/librssguard/database/sqlitedriver.h new file mode 100755 index 000000000..cbe622e72 --- /dev/null +++ b/src/librssguard/database/sqlitedriver.h @@ -0,0 +1,38 @@ +// For license of this file, see /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 diff --git a/src/librssguard/definitions/definitions.h b/src/librssguard/definitions/definitions.h index c43b706a8..216110dd3 100755 --- a/src/librssguard/definitions/definitions.h +++ b/src/librssguard/definitions/definitions.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" diff --git a/src/librssguard/definitions/typedefs.h b/src/librssguard/definitions/typedefs.h index 46e9e535c..19e7bb02e 100755 --- a/src/librssguard/definitions/typedefs.h +++ b/src/librssguard/definitions/typedefs.h @@ -1,3 +1,5 @@ +// For license of this file, see /LICENSE.md. + #ifndef TYPEDEFS_H #define TYPEDEFS_H diff --git a/src/librssguard/gui/dialogs/formbackupdatabasesettings.cpp b/src/librssguard/gui/dialogs/formbackupdatabasesettings.cpp index 1cf72dc14..95d83781a 100644 --- a/src/librssguard/gui/dialogs/formbackupdatabasesettings.cpp +++ b/src/librssguard/gui/dialogs/formbackupdatabasesettings.cpp @@ -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); } } @@ -77,7 +76,7 @@ void FormBackupDatabaseSettings::checkBackupNames(const QString& name) { void FormBackupDatabaseSettings::checkOkButton() { m_ui->m_buttonBox->button(QDialogButtonBox::StandardButton::Ok)->setDisabled(m_ui->m_txtBackupName->lineEdit()->text().simplified().isEmpty() || - m_ui->m_lblSelectFolder->label()->text().simplified().isEmpty() || - (!m_ui->m_checkBackupDatabase->isChecked() && - !m_ui->m_checkBackupSettings->isChecked())); + m_ui->m_lblSelectFolder->label()->text().simplified().isEmpty() || + (!m_ui->m_checkBackupDatabase->isChecked() && + !m_ui->m_checkBackupSettings->isChecked())); } diff --git a/src/librssguard/gui/dialogs/formdatabasecleanup.cpp b/src/librssguard/gui/dialogs/formdatabasecleanup.cpp index 607074dbc..81db2d459 100644 --- a/src/librssguard/gui/dialogs/formdatabasecleanup.cpp +++ b/src/librssguard/gui/dialogs/formdatabasecleanup.cpp @@ -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 @@ -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()); } diff --git a/src/librssguard/gui/dialogs/formdatabasecleanup.h b/src/librssguard/gui/dialogs/formdatabasecleanup.h index b6c967507..afc8139a7 100644 --- a/src/librssguard/gui/dialogs/formdatabasecleanup.h +++ b/src/librssguard/gui/dialogs/formdatabasecleanup.h @@ -7,7 +7,7 @@ #include "ui_formdatabasecleanup.h" -#include "miscellaneous/databasecleaner.h" +#include "database/databasecleaner.h" class FormDatabaseCleanup : public QDialog { Q_OBJECT diff --git a/src/librssguard/gui/dialogs/formdatabasecleanup.ui b/src/librssguard/gui/dialogs/formdatabasecleanup.ui index 309e00f96..bce6be039 100644 --- a/src/librssguard/gui/dialogs/formdatabasecleanup.ui +++ b/src/librssguard/gui/dialogs/formdatabasecleanup.ui @@ -99,7 +99,7 @@ - Database file size + Total data size m_txtFileSize diff --git a/src/librssguard/gui/dialogs/formmain.cpp b/src/librssguard/gui/dialogs/formmain.cpp index 90ad68f3c..6ee51a0df 100755 --- a/src/librssguard/gui/dialogs/formmain.cpp +++ b/src/librssguard/gui/dialogs/formmain.cpp @@ -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" diff --git a/src/librssguard/gui/dialogs/formmessagefiltersmanager.cpp b/src/librssguard/gui/dialogs/formmessagefiltersmanager.cpp index a1b675a22..f6a4add5e 100644 --- a/src/librssguard/gui/dialogs/formmessagefiltersmanager.cpp +++ b/src/librssguard/gui/dialogs/formmessagefiltersmanager.cpp @@ -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 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) { diff --git a/src/librssguard/gui/feedmessageviewer.cpp b/src/librssguard/gui/feedmessageviewer.cpp index 34c0b8048..9361caa8f 100644 --- a/src/librssguard/gui/feedmessageviewer.cpp +++ b/src/librssguard/gui/feedmessageviewer.cpp @@ -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" diff --git a/src/librssguard/gui/feedstoolbar.cpp b/src/librssguard/gui/feedstoolbar.cpp index 484b40277..350f7b217 100644 --- a/src/librssguard/gui/feedstoolbar.cpp +++ b/src/librssguard/gui/feedstoolbar.cpp @@ -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 } diff --git a/src/librssguard/gui/labelsmenu.cpp b/src/librssguard/gui/labelsmenu.cpp index d5646c637..8c955798a 100644 --- a/src/librssguard/gui/labelsmenu.cpp +++ b/src/librssguard/gui/labelsmenu.cpp @@ -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 @@ -22,7 +22,7 @@ LabelsMenu::LabelsMenu(const QList& messages, const QList& 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(); diff --git a/src/librssguard/gui/messagepreviewer.cpp b/src/librssguard/gui/messagepreviewer.cpp index 27ebe6d17..9b1030db0 100755 --- a/src/librssguard/gui/messagepreviewer.cpp +++ b/src/librssguard/gui/messagepreviewer.cpp @@ -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() << 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() @@ -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); diff --git a/src/librssguard/gui/settings/settingsdatabase.cpp b/src/librssguard/gui/settings/settingsdatabase.cpp index 0e770b326..59141fe61 100644 --- a/src/librssguard/gui/settings/settingsdatabase.cpp +++ b/src/librssguard/gui/settings/settingsdatabase.cpp @@ -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,23 +44,27 @@ 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: - case DatabaseFactory::MySQLError::UnknownDatabase: + switch (error_code) { + case DatabaseFactory::MySQLError::Ok: + case DatabaseFactory::MySQLError::UnknownDatabase: m_ui->m_lblMysqlTestResult->setStatus(WidgetWithStatus::StatusType::Ok, interpretation, interpretation); break; - default: + default: 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")); diff --git a/src/librssguard/gui/statusbar.cpp b/src/librssguard/gui/statusbar.cpp index 14602faac..65a77b5f1 100644 --- a/src/librssguard/gui/statusbar.cpp +++ b/src/librssguard/gui/statusbar.cpp @@ -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 } diff --git a/src/librssguard/gui/webbrowser.cpp b/src/librssguard/gui/webbrowser.cpp index 6388a80f1..529bc0cc1 100644 --- a/src/librssguard/gui/webbrowser.cpp +++ b/src/librssguard/gui/webbrowser.cpp @@ -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" diff --git a/src/librssguard/librssguard.pro b/src/librssguard/librssguard.pro index c6218f52b..7419ebd47 100644 --- a/src/librssguard/librssguard.pro +++ b/src/librssguard/librssguard.pro @@ -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 \ diff --git a/src/librssguard/miscellaneous/application.cpp b/src/librssguard/miscellaneous/application.cpp index 3aaaea187..6f945dd04 100755 --- a/src/librssguard/miscellaneous/application.cpp +++ b/src/librssguard/miscellaneous/application.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(); diff --git a/src/librssguard/miscellaneous/application.h b/src/librssguard/miscellaneous/application.h index 161c6502a..c1f0bc5a0 100755 --- a/src/librssguard/miscellaneous/application.h +++ b/src/librssguard/miscellaneous/application.h @@ -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" diff --git a/src/librssguard/miscellaneous/databasefactory.cpp b/src/librssguard/miscellaneous/databasefactory.cpp deleted file mode 100644 index 079d4154b..000000000 --- a/src/librssguard/miscellaneous/databasefactory.cpp +++ /dev/null @@ -1,940 +0,0 @@ -// For license of this file, see /LICENSE.md. - -#include "miscellaneous/databasefactory.h" - -#include "gui/messagebox.h" -#include "miscellaneous/application.h" -#include "miscellaneous/iofactory.h" -#include "miscellaneous/textfactory.h" - -#include -#include -#include -#include - -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(); - } - else { - return 0; - } - - if (query.exec(QSL("PRAGMA page_size;"))) { - query.next(); - result *= query.value(0).value(); - } - 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(); - } - 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(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; - } -} diff --git a/src/librssguard/miscellaneous/databasefactory.h b/src/librssguard/miscellaneous/databasefactory.h deleted file mode 100644 index dae258833..000000000 --- a/src/librssguard/miscellaneous/databasefactory.h +++ /dev/null @@ -1,167 +0,0 @@ -// For license of this file, see /LICENSE.md. - -#ifndef DATABASEFACTORY_H -#define DATABASEFACTORY_H - -#include -#include - -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 diff --git a/src/librssguard/miscellaneous/feedreader.cpp b/src/librssguard/miscellaneous/feedreader.cpp index 6e969b6d5..6c3644374 100644 --- a/src/librssguard/miscellaneous/feedreader.cpp +++ b/src/librssguard/miscellaneous/feedreader.cpp @@ -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()); diff --git a/src/librssguard/network-web/adblock/adblockrule.cpp b/src/librssguard/network-web/adblock/adblockrule.cpp index 6d139313d..9a8ca6fe4 100644 --- a/src/librssguard/network-web/adblock/adblockrule.cpp +++ b/src/librssguard/network-web/adblock/adblockrule.cpp @@ -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; diff --git a/src/librssguard/network-web/downloader.cpp b/src/librssguard/network-web/downloader.cpp index ea62d18df..8b7b17684 100644 --- a/src/librssguard/network-web/downloader.cpp +++ b/src/librssguard/network-web/downloader.cpp @@ -153,7 +153,7 @@ QList Downloader::decodeMultipartAnswer(QNetworkReply* reply) { #if QT_VERSION >= 0x050F00 // Qt >= 5.15.0 Qt::SplitBehaviorFlags::SkipEmptyParts); #else - QString::SkipEmptyParts); + QString::SplitBehavior::SkipEmptyParts); #endif QList parts; @@ -175,7 +175,7 @@ QList 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(':')); diff --git a/src/librssguard/services/abstract/category.cpp b/src/librssguard/services/abstract/category.cpp index af8fea14e..841903e41 100644 --- a/src/librssguard/services/abstract/category.cpp +++ b/src/librssguard/services/abstract/category.cpp @@ -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> counts = DatabaseQueries::getMessageCountsForCategory(database, customId(), diff --git a/src/librssguard/services/abstract/feed.cpp b/src/librssguard/services/abstract/feed.cpp index a825adc88..16281f55c 100755 --- a/src/librssguard/services/abstract/feed.cpp +++ b/src/librssguard/services/abstract/feed.cpp @@ -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 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& 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); diff --git a/src/librssguard/services/abstract/gui/formaccountdetails.h b/src/librssguard/services/abstract/gui/formaccountdetails.h index d9c543bff..9e0d1e7de 100644 --- a/src/librssguard/services/abstract/gui/formaccountdetails.h +++ b/src/librssguard/services/abstract/gui/formaccountdetails.h @@ -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; diff --git a/src/librssguard/services/abstract/gui/formcategorydetails.cpp b/src/librssguard/services/abstract/gui/formcategorydetails.cpp index 76df97e11..6d4860246 100644 --- a/src/librssguard/services/abstract/gui/formcategorydetails.cpp +++ b/src/librssguard/services/abstract/gui/formcategorydetails.cpp @@ -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); diff --git a/src/librssguard/services/abstract/gui/formfeeddetails.cpp b/src/librssguard/services/abstract/gui/formfeeddetails.cpp index dfcd2e033..d926dca80 100644 --- a/src/librssguard/services/abstract/gui/formfeeddetails.cpp +++ b/src/librssguard/services/abstract/gui/formfeeddetails.cpp @@ -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" diff --git a/src/librssguard/services/abstract/importantnode.cpp b/src/librssguard/services/abstract/importantnode.cpp index 2bee28783..51404bc2c 100755 --- a/src/librssguard/services/abstract/importantnode.cpp +++ b/src/librssguard/services/abstract/importantnode.cpp @@ -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 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 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); diff --git a/src/librssguard/services/abstract/label.cpp b/src/librssguard/services/abstract/label.cpp index 576f4478c..38d249409 100755 --- a/src/librssguard/services/abstract/label.cpp +++ b/src/librssguard/services/abstract/label.cpp @@ -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 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); diff --git a/src/librssguard/services/abstract/labelsnode.cpp b/src/librssguard/services/abstract/labelsnode.cpp index ae35ca0d6..47247e858 100755 --- a/src/librssguard/services/abstract/labelsnode.cpp +++ b/src/librssguard/services/abstract/labelsnode.cpp @@ -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& labels) { } QList 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()); diff --git a/src/librssguard/services/abstract/recyclebin.cpp b/src/librssguard/services/abstract/recyclebin.cpp index 25403e1fc..75d09381b 100644 --- a/src/librssguard/services/abstract/recyclebin.cpp +++ b/src/librssguard/services/abstract/recyclebin.cpp @@ -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 RecycleBin::contextMenuFeedsList() { QList 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(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())) { diff --git a/src/librssguard/services/abstract/serviceroot.cpp b/src/librssguard/services/abstract/serviceroot.cpp index 2b01e8880..c259d0378 100644 --- a/src/librssguard/services/abstract/serviceroot.cpp +++ b/src/librssguard/services/abstract/serviceroot.cpp @@ -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> 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 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 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 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 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); diff --git a/src/librssguard/services/feedly/feedlyentrypoint.cpp b/src/librssguard/services/feedly/feedlyentrypoint.cpp index 75448295d..543c09791 100755 --- a/src/librssguard/services/feedly/feedlyentrypoint.cpp +++ b/src/librssguard/services/feedly/feedlyentrypoint.cpp @@ -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 FeedlyEntryPoint::initializeSubtree() const { - QSqlDatabase database = qApp->database()->connection(QSL("FeedlyEntryPoint")); + QSqlDatabase database = qApp->database()->driver()->connection(QSL("FeedlyEntryPoint")); return DatabaseQueries::getAccounts(database, code()); } diff --git a/src/librssguard/services/feedly/feedlynetwork.cpp b/src/librssguard/services/feedly/feedlynetwork.cpp index d8e1cbbbf..35cedcde0 100755 --- a/src/librssguard/services/feedly/feedlynetwork.cpp +++ b/src/librssguard/services/feedly/feedlynetwork.cpp @@ -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()); } diff --git a/src/librssguard/services/feedly/feedlyserviceroot.cpp b/src/librssguard/services/feedly/feedlyserviceroot.cpp index 9bcf94e5d..2971cdefb 100755 --- a/src/librssguard/services/feedly/feedlyserviceroot.cpp +++ b/src/librssguard/services/feedly/feedlyserviceroot.cpp @@ -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" diff --git a/src/librssguard/services/gmail/gmailentrypoint.cpp b/src/librssguard/services/gmail/gmailentrypoint.cpp index 8222ea6b6..5e0292c0a 100644 --- a/src/librssguard/services/gmail/gmailentrypoint.cpp +++ b/src/librssguard/services/gmail/gmailentrypoint.cpp @@ -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 GmailEntryPoint::initializeSubtree() const { - QSqlDatabase database = qApp->database()->connection(QSL("GmailEntryPoint")); + QSqlDatabase database = qApp->database()->driver()->connection(QSL("GmailEntryPoint")); return DatabaseQueries::getAccounts(database, code()); } diff --git a/src/librssguard/services/gmail/gmailnetworkfactory.cpp b/src/librssguard/services/gmail/gmailnetworkfactory.cpp index 7260589fe..962aba7dc 100755 --- a/src/librssguard/services/gmail/gmailnetworkfactory.cpp +++ b/src/librssguard/services/gmail/gmailnetworkfactory.cpp @@ -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()); } diff --git a/src/librssguard/services/gmail/gmailserviceroot.cpp b/src/librssguard/services/gmail/gmailserviceroot.cpp index ff3750f65..e34ab7a8d 100644 --- a/src/librssguard/services/gmail/gmailserviceroot.cpp +++ b/src/librssguard/services/gmail/gmailserviceroot.cpp @@ -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" diff --git a/src/librssguard/services/gmail/gui/formaddeditemail.cpp b/src/librssguard/services/gmail/gui/formaddeditemail.cpp index c7e8a8f32..f56a8ae58 100644 --- a/src/librssguard/services/gmail/gui/formaddeditemail.cpp +++ b/src/librssguard/services/gmail/gui/formaddeditemail.cpp @@ -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()); diff --git a/src/librssguard/services/greader/greaderentrypoint.cpp b/src/librssguard/services/greader/greaderentrypoint.cpp index c4a6c1233..498fa4c8e 100755 --- a/src/librssguard/services/greader/greaderentrypoint.cpp +++ b/src/librssguard/services/greader/greaderentrypoint.cpp @@ -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 GreaderEntryPoint::initializeSubtree() const { - QSqlDatabase database = qApp->database()->connection(QSL("GreaderEntryPoint")); + QSqlDatabase database = qApp->database()->driver()->connection(QSL("GreaderEntryPoint")); return DatabaseQueries::getAccounts(database, code()); } diff --git a/src/librssguard/services/greader/greaderserviceroot.cpp b/src/librssguard/services/greader/greaderserviceroot.cpp index c78b4e69d..837049e55 100755 --- a/src/librssguard/services/greader/greaderserviceroot.cpp +++ b/src/librssguard/services/greader/greaderserviceroot.cpp @@ -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" diff --git a/src/librssguard/services/inoreader/inoreaderentrypoint.cpp b/src/librssguard/services/inoreader/inoreaderentrypoint.cpp index 3b996672e..81207058c 100644 --- a/src/librssguard/services/inoreader/inoreaderentrypoint.cpp +++ b/src/librssguard/services/inoreader/inoreaderentrypoint.cpp @@ -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 InoreaderEntryPoint::initializeSubtree() const { - QSqlDatabase database = qApp->database()->connection(QSL("InoreaderEntryPoint")); + QSqlDatabase database = qApp->database()->driver()->connection(QSL("InoreaderEntryPoint")); return DatabaseQueries::getAccounts(database, code()); } diff --git a/src/librssguard/services/inoreader/inoreadernetworkfactory.cpp b/src/librssguard/services/inoreader/inoreadernetworkfactory.cpp index a8dff0503..b2ef61e44 100755 --- a/src/librssguard/services/inoreader/inoreadernetworkfactory.cpp +++ b/src/librssguard/services/inoreader/inoreadernetworkfactory.cpp @@ -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()); } diff --git a/src/librssguard/services/inoreader/inoreaderserviceroot.cpp b/src/librssguard/services/inoreader/inoreaderserviceroot.cpp index b2c6fc479..275bfb2cf 100644 --- a/src/librssguard/services/inoreader/inoreaderserviceroot.cpp +++ b/src/librssguard/services/inoreader/inoreaderserviceroot.cpp @@ -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" diff --git a/src/librssguard/services/owncloud/owncloudfeed.cpp b/src/librssguard/services/owncloud/owncloudfeed.cpp index 9374deeee..28664e9f3 100644 --- a/src/librssguard/services/owncloud/owncloudfeed.cpp +++ b/src/librssguard/services/owncloud/owncloudfeed.cpp @@ -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()); } diff --git a/src/librssguard/services/owncloud/owncloudserviceentrypoint.cpp b/src/librssguard/services/owncloud/owncloudserviceentrypoint.cpp index 6ef0a9527..ddcdffc0c 100644 --- a/src/librssguard/services/owncloud/owncloudserviceentrypoint.cpp +++ b/src/librssguard/services/owncloud/owncloudserviceentrypoint.cpp @@ -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 OwnCloudServiceEntryPoint::initializeSubtree() const { - QSqlDatabase database = qApp->database()->connection(QSL("OwnCloudServiceEntryPoint")); + QSqlDatabase database = qApp->database()->driver()->connection(QSL("OwnCloudServiceEntryPoint")); return DatabaseQueries::getAccounts(database, code()); } diff --git a/src/librssguard/services/owncloud/owncloudserviceroot.cpp b/src/librssguard/services/owncloud/owncloudserviceroot.cpp index 113e2f998..424285470 100644 --- a/src/librssguard/services/owncloud/owncloudserviceroot.cpp +++ b/src/librssguard/services/owncloud/owncloudserviceroot.cpp @@ -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" diff --git a/src/librssguard/services/standard/gui/formeditstandardaccount.cpp b/src/librssguard/services/standard/gui/formeditstandardaccount.cpp index 2e2fc3ffc..eda119baa 100755 --- a/src/librssguard/services/standard/gui/formeditstandardaccount.cpp +++ b/src/librssguard/services/standard/gui/formeditstandardaccount.cpp @@ -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" diff --git a/src/librssguard/services/standard/gui/formstandardfeeddetails.cpp b/src/librssguard/services/standard/gui/formstandardfeeddetails.cpp index 735cec10e..34530b928 100644 --- a/src/librssguard/services/standard/gui/formstandardfeeddetails.cpp +++ b/src/librssguard/services/standard/gui/formstandardfeeddetails.cpp @@ -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); diff --git a/src/librssguard/services/standard/standardcategory.cpp b/src/librssguard/services/standard/standardcategory.cpp index daa3c8d72..7488748f0 100644 --- a/src/librssguard/services/standard/standardcategory.cpp +++ b/src/librssguard/services/standard/standardcategory.cpp @@ -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()); } diff --git a/src/librssguard/services/standard/standardfeed.cpp b/src/librssguard/services/standard/standardfeed.cpp index f40b4a3a8..4d9619faa 100644 --- a/src/librssguard/services/standard/standardfeed.cpp +++ b/src/librssguard/services/standard/standardfeed.cpp @@ -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()); } diff --git a/src/librssguard/services/standard/standardserviceentrypoint.cpp b/src/librssguard/services/standard/standardserviceentrypoint.cpp index 8119d5bca..896c13519 100644 --- a/src/librssguard/services/standard/standardserviceentrypoint.cpp +++ b/src/librssguard/services/standard/standardserviceentrypoint.cpp @@ -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 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(database, code()); } diff --git a/src/librssguard/services/standard/standardserviceroot.cpp b/src/librssguard/services/standard/standardserviceroot.cpp index 63b913a7a..87f062a33 100644 --- a/src/librssguard/services/standard/standardserviceroot.cpp +++ b/src/librssguard/services/standard/standardserviceroot.cpp @@ -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(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, diff --git a/src/librssguard/services/tt-rss/ttrssfeed.cpp b/src/librssguard/services/tt-rss/ttrssfeed.cpp index 9076cd762..827232c96 100644 --- a/src/librssguard/services/tt-rss/ttrssfeed.cpp +++ b/src/librssguard/services/tt-rss/ttrssfeed.cpp @@ -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()); } diff --git a/src/librssguard/services/tt-rss/ttrssserviceentrypoint.cpp b/src/librssguard/services/tt-rss/ttrssserviceentrypoint.cpp index 737591d48..f73891f0c 100644 --- a/src/librssguard/services/tt-rss/ttrssserviceentrypoint.cpp +++ b/src/librssguard/services/tt-rss/ttrssserviceentrypoint.cpp @@ -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 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(database, code()); } diff --git a/src/librssguard/services/tt-rss/ttrssserviceroot.cpp b/src/librssguard/services/tt-rss/ttrssserviceroot.cpp index 28db0ebbb..b93dca382 100644 --- a/src/librssguard/services/tt-rss/ttrssserviceroot.cpp +++ b/src/librssguard/services/tt-rss/ttrssserviceroot.cpp @@ -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"