Commit 8240e111 authored by Antonio Larrosa Jimenez's avatar Antonio Larrosa Jimenez Committed by Antonio Larrosa Jimenez
Browse files

Fallback to using the QSQLITE3 driver if QMYSQL can't be used

On SUSE Linux Enterprise Desktop (SLED) with the PackageHub repository
enabled (which provides the KDE packages) the mysql package is not available,
so there's no mysqld, and the QMYSQL driver can't be used.

OTOH, SUSE Linux Enterprise Server (SLES) with the same PackageHub repository
enabled has a mariadb package available which provides the mysqld binary.

Since the akonadi-server package for SLES and SLED is the same, we can't
just set DATABASE_BACKEND to SQLITE at buildtime and we need to choose
a fallback at runtime, which is what this commit implements.

If it's the first time akonadi starts and mysql is expected to be used, this
commit checks if it's really usable, and if it's not, it checks if the QSQLITE3 driver
is available and if it is, we fall back to it instead of using mysql.

Since we need to find out if a DbConfig* object can be initialized before
it's actually initialized, I added a bool storeSettings parameter to
DbConfig::init(QSettings &) that can be used to try the initialization
(find out available paths, etc.) without storing anything.

Then I added two methods DbConfigMysql::areRequirementsAvailable and
DbConfigSqlite::areRequirementsAvailable that check if the given object
has the system requirements available. I didn't add it to
DbConfigPostgresql because Postgresql isn't used by default in any case.

Also, note that this check is only done the first time akonadi starts
when it's not configured. Once it starts with mysql or sqlite3 this
configuration is stored and used the next times without any further
check.
parent 0f25bf4c
......@@ -59,6 +59,16 @@ DbConfig *DbConfig::configuredDatabase()
QString driverName = settings.value(QStringLiteral("General/Driver")).toString();
if (driverName.isEmpty()) {
driverName = QStringLiteral(AKONADI_DATABASE_BACKEND);
// If we fallback to use QMYSQL by default, let's check that it's really available.
if (driverName == QLatin1String("QMYSQL")) {
DbConfigMysql dbConfigMysql;
if (!dbConfigMysql.areRequirementsAvailable(settings)
&& DbConfigSqlite(DbConfigSqlite::Custom).areRequirementsAvailable(settings)) {
qCWarning(AKONADISERVER_LOG) << "QMYSQL requirements not available. Falling back to using QSQLITE3.";
driverName = QStringLiteral("QSQLITE3");
}
}
// when using the default, write it explicitly, in case the default changes later
settings.setValue(QStringLiteral("General/Driver"), driverName);
settings.sync();
......
......@@ -51,9 +51,9 @@ public:
* and before the initial database connection is set up.
*
* At this point the default settings should be determined, merged
* with the given @p settings and written back.
* with the given @p settings and written back if @p storeSettings is true.
*/
virtual bool init(QSettings &settings) = 0;
virtual bool init(QSettings &settings, bool storeSettings=true) = 0;
/**
* This method applies the configured settings to the QtSql @p database
......
......@@ -65,7 +65,7 @@ static QString findExecutable(const QString &bin)
return path;
}
bool DbConfigMysql::init(QSettings &settings)
bool DbConfigMysql::init(QSettings &settings, bool storeSettings)
{
// determine default settings depending on the driver
QString defaultHostName;
......@@ -134,17 +134,19 @@ bool DbConfigMysql::init(QSettings &settings)
qCDebug(AKONADISERVER_LOG) << "Using mysqld:" << mMysqldPath;
// store back the default values
settings.beginGroup(driverName());
settings.setValue(QStringLiteral("Name"), mDatabaseName);
settings.setValue(QStringLiteral("Host"), mHostName);
settings.setValue(QStringLiteral("Options"), mConnectionOptions);
if (!mMysqldPath.isEmpty()) {
settings.setValue(QStringLiteral("ServerPath"), mMysqldPath);
if (storeSettings) {
// store back the default values
settings.beginGroup(driverName());
settings.setValue(QStringLiteral("Name"), mDatabaseName);
settings.setValue(QStringLiteral("Host"), mHostName);
settings.setValue(QStringLiteral("Options"), mConnectionOptions);
if (!mMysqldPath.isEmpty()) {
settings.setValue(QStringLiteral("ServerPath"), mMysqldPath);
}
settings.setValue(QStringLiteral("StartServer"), mInternalServer);
settings.endGroup();
settings.sync();
}
settings.setValue(QStringLiteral("StartServer"), mInternalServer);
settings.endGroup();
settings.sync();
// apply temporary changes to the settings
if (mInternalServer) {
......@@ -156,6 +158,20 @@ bool DbConfigMysql::init(QSettings &settings)
return true;
}
bool DbConfigMysql::areRequirementsAvailable(QSettings &settings)
{
if (!QSqlDatabase::drivers().contains(driverName()))
return false;
if (!init(settings, false))
return false;
if (mInternalServer && (mMysqldPath.isEmpty() || !QFile::exists(mMysqldPath)))
return false;
return true;
}
void DbConfigMysql::apply(QSqlDatabase &database)
{
if (!mDatabaseName.isEmpty()) {
......
......@@ -38,9 +38,15 @@ public:
* and before the initial database connection is set up.
*
* At this point the default settings should be determined, merged
* with the given @p settings and written back.
* with the given @p settings and written back if @p storeSettings is true.
*/
bool init(QSettings &settings) override;
bool init(QSettings &settings, bool storeSettings=true) override;
/**
* This method checks if the requirements for this database connection are met
* in the system (QMYSQL driver is available, mysqld binary is found, etc.).
*/
bool areRequirementsAvailable(QSettings &settings);
/**
* This method applies the configured settings to the QtSql @p database
......
......@@ -123,7 +123,7 @@ QStringList DbConfigPostgresql::postgresSearchPaths(const QString &versionedPath
return paths;
}
bool DbConfigPostgresql::init(QSettings &settings)
bool DbConfigPostgresql::init(QSettings &settings, bool storeSettings)
{
// determine default settings depending on the driver
QString defaultHostName;
......@@ -186,19 +186,21 @@ bool DbConfigPostgresql::init(QSettings &settings)
}
settings.endGroup();
// store back the default values
settings.beginGroup(driverName());
settings.setValue(QStringLiteral("Name"), mDatabaseName);
settings.setValue(QStringLiteral("Host"), mHostName);
if (mHostPort) {
settings.setValue(QStringLiteral("Port"), mHostPort);
}
settings.setValue(QStringLiteral("Options"), mConnectionOptions);
settings.setValue(QStringLiteral("ServerPath"), mServerPath);
settings.setValue(QStringLiteral("InitDbPath"), mInitDbPath);
settings.setValue(QStringLiteral("StartServer"), mInternalServer);
settings.endGroup();
settings.sync();
if (storeSettings) {
// store back the default values
settings.beginGroup(driverName());
settings.setValue(QStringLiteral("Name"), mDatabaseName);
settings.setValue(QStringLiteral("Host"), mHostName);
if (mHostPort) {
settings.setValue(QStringLiteral("Port"), mHostPort);
}
settings.setValue(QStringLiteral("Options"), mConnectionOptions);
settings.setValue(QStringLiteral("ServerPath"), mServerPath);
settings.setValue(QStringLiteral("InitDbPath"), mInitDbPath);
settings.setValue(QStringLiteral("StartServer"), mInternalServer);
settings.endGroup();
settings.sync();
}
return true;
}
......
......@@ -36,9 +36,9 @@ public:
* and before the initial database connection is set up.
*
* At this point the default settings should be determined, merged
* with the given @p settings and written back.
* with the given @p settings and written back if @p storeSettings is true.
*/
bool init(QSettings &settings) override;
bool init(QSettings &settings, bool storeSettings=true) override;
/**
* This method applies the configured settings to the QtSql @p database
......
......@@ -72,7 +72,7 @@ QString DbConfigSqlite::databaseName() const
return mDatabaseName;
}
bool DbConfigSqlite::init(QSettings &settings)
bool DbConfigSqlite::init(QSettings &settings, bool storeSettings)
{
// determine default settings depending on the driver
const QString defaultDbName = sqliteDataFile();
......@@ -89,11 +89,24 @@ bool DbConfigSqlite::init(QSettings &settings)
mConnectionOptions = settings.value(QStringLiteral("Options")).toString();
settings.endGroup();
// store back the default values
settings.beginGroup(driverName());
settings.setValue(QStringLiteral("Name"), mDatabaseName);
settings.endGroup();
settings.sync();
if (storeSettings) {
// store back the default values
settings.beginGroup(driverName());
settings.setValue(QStringLiteral("Name"), mDatabaseName);
settings.endGroup();
settings.sync();
}
return true;
}
bool DbConfigSqlite::areRequirementsAvailable(QSettings &settings)
{
if (!QSqlDatabase::drivers().contains(driverName()))
return false;
if (!init(settings, false))
return false;
return true;
}
......
......@@ -40,9 +40,15 @@ public:
* and before the initial database connection is set up.
*
* At this point the default settings should be determined, merged
* with the given @p settings and written back.
* with the given @p settings and written back if @p storeSettings is true.
*/
bool init(QSettings &settings) override;
bool init(QSettings &settings, bool storeSettings) override;
/**
* This method checks if the requirements for this database connection are met
* in the system (QSQLITE/QSQLITE3 driver is available, object can be initialized, etc.).
*/
bool areRequirementsAvailable(QSettings &settings);
/**
* This method applies the configured settings to the QtSql @p database
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment