File indexing completed on 2025-01-05 04:46:56

0001 /*
0002     SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "dbconfig.h"
0008 
0009 #include "akonadiserver_debug.h"
0010 #include "dbconfigmysql.h"
0011 #include "dbconfigpostgresql.h"
0012 #include "dbconfigsqlite.h"
0013 
0014 #include <config-akonadi.h>
0015 
0016 #include "private/instance_p.h"
0017 #include "private/standarddirs_p.h"
0018 
0019 #include <QProcess>
0020 #include <memory>
0021 
0022 using namespace Akonadi;
0023 using namespace Akonadi::Server;
0024 
0025 // TODO: make me Q_GLOBAL_STATIC
0026 static DbConfig *s_DbConfigInstance = nullptr;
0027 
0028 DbConfig::DbConfig()
0029     : DbConfig(StandardDirs::serverConfigFile(StandardDirs::ReadWrite))
0030 {
0031 }
0032 
0033 DbConfig::DbConfig(const QString &configFile)
0034 {
0035     QSettings settings(configFile, QSettings::IniFormat);
0036 
0037     mSizeThreshold = 4096;
0038     const QVariant value = settings.value(QStringLiteral("General/SizeThreshold"), mSizeThreshold);
0039     if (value.canConvert<qint64>()) {
0040         mSizeThreshold = value.value<qint64>();
0041         if (mSizeThreshold < 0) {
0042             mSizeThreshold = 0;
0043         }
0044     } else {
0045         mSizeThreshold = 0;
0046     }
0047 }
0048 
0049 DbConfig::~DbConfig()
0050 {
0051 }
0052 
0053 bool DbConfig::isConfigured()
0054 {
0055     return s_DbConfigInstance;
0056 }
0057 
0058 QString DbConfig::defaultAvailableDatabaseBackend(QSettings &settings)
0059 {
0060     QString driverName = QStringLiteral(AKONADI_DATABASE_BACKEND);
0061 
0062     std::unique_ptr<DbConfig> dbConfigFallbackTest;
0063     if (driverName == QLatin1StringView("QMYSQL")) {
0064         dbConfigFallbackTest = std::make_unique<DbConfigMysql>();
0065     } else if (driverName == QLatin1StringView("QPSQL")) {
0066         dbConfigFallbackTest = std::make_unique<DbConfigPostgresql>();
0067     }
0068 
0069     if (dbConfigFallbackTest && !dbConfigFallbackTest->isAvailable(settings) && DbConfigSqlite().isAvailable(settings)) {
0070         qCWarning(AKONADISERVER_LOG) << driverName << " requirements not available. Falling back to using QSQLITE.";
0071         driverName = QStringLiteral("QSQLITE");
0072     }
0073 
0074     return driverName;
0075 }
0076 
0077 DbConfig *DbConfig::configuredDatabase()
0078 {
0079     if (!s_DbConfigInstance) {
0080         const QString serverConfigFile = StandardDirs::serverConfigFile(StandardDirs::ReadWrite);
0081         QSettings settings(serverConfigFile, QSettings::IniFormat);
0082 
0083         // determine driver to use
0084         QString driverName = settings.value(QStringLiteral("General/Driver")).toString();
0085         if (driverName.isEmpty()) {
0086             driverName = defaultAvailableDatabaseBackend(settings);
0087 
0088             // when using the default, write it explicitly, in case the default changes later
0089             settings.setValue(QStringLiteral("General/Driver"), driverName);
0090             settings.sync();
0091         }
0092 
0093         if (driverName == QLatin1StringView("QMYSQL")) {
0094             s_DbConfigInstance = new DbConfigMysql;
0095         } else if (driverName == QLatin1StringView("QSQLITE") || driverName == QLatin1StringView("QSQLITE3")) {
0096             // QSQLITE3 is legacy name for the Akonadi fork of the upstream QSQLITE driver.
0097             // It is kept here for backwards compatibility with old server config files.
0098             s_DbConfigInstance = new DbConfigSqlite();
0099         } else if (driverName == QLatin1StringView("QPSQL")) {
0100             s_DbConfigInstance = new DbConfigPostgresql;
0101         } else {
0102             qCCritical(AKONADISERVER_LOG) << "Unknown database driver: " << driverName;
0103             qCCritical(AKONADISERVER_LOG) << "Available drivers are: " << QSqlDatabase::drivers();
0104             return nullptr;
0105         }
0106 
0107         if (!s_DbConfigInstance->init(settings)) {
0108             delete s_DbConfigInstance;
0109             s_DbConfigInstance = nullptr;
0110         }
0111     }
0112 
0113     return s_DbConfigInstance;
0114 }
0115 
0116 void DbConfig::destroy()
0117 {
0118     delete s_DbConfigInstance;
0119     s_DbConfigInstance = nullptr;
0120 }
0121 
0122 bool DbConfig::startInternalServer()
0123 {
0124     // do nothing
0125     return true;
0126 }
0127 
0128 void DbConfig::stopInternalServer()
0129 {
0130     // do nothing
0131 }
0132 
0133 void DbConfig::setup()
0134 {
0135     // do nothing
0136 }
0137 
0138 qint64 DbConfig::sizeThreshold() const
0139 {
0140     return mSizeThreshold;
0141 }
0142 
0143 QString DbConfig::defaultDatabaseName()
0144 {
0145     if (!Instance::hasIdentifier()) {
0146         return QStringLiteral("akonadi");
0147     }
0148     // dash is not allowed in PSQL
0149     return QLatin1StringView("akonadi_") % Instance::identifier().replace(QLatin1Char('-'), QLatin1Char('_'));
0150 }
0151 
0152 void DbConfig::initSession(const QSqlDatabase &database)
0153 {
0154     Q_UNUSED(database)
0155 }
0156 
0157 int DbConfig::execute(const QString &cmd, const QStringList &args) const
0158 {
0159     qCDebug(AKONADISERVER_LOG) << "Executing: " << cmd << args.join(QLatin1Char(' '));
0160     return QProcess::execute(cmd, args);
0161 }