X-Git-Url: https://git.quassel-irc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fcore%2Fpostgresqlstorage.cpp;h=40ff80cb1659a07c7dd65e86606d17afec48aebf;hb=edc55b1f86cf613a332eeeb5d85537a54120dfa5;hp=200fd14ca5bde5087fea0357fcd5122849bdb9ac;hpb=c1cf157116de7fc3da96203aa6f03c38c7ebb650;p=quassel.git diff --git a/src/core/postgresqlstorage.cpp b/src/core/postgresqlstorage.cpp index 200fd14c..40ff80cb 100644 --- a/src/core/postgresqlstorage.cpp +++ b/src/core/postgresqlstorage.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-2018 by the Quassel Project * + * Copyright (C) 2005-2019 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -22,7 +22,6 @@ #include -#include "logmessage.h" #include "network.h" #include "quassel.h" @@ -46,7 +45,7 @@ std::unique_ptr PostgreSqlStorage::createMigrationWr bool PostgreSqlStorage::isAvailable() const { if (!QSqlDatabase::isDriverAvailable("QPSQL")) { - quWarning() << qPrintable(tr("PostgreSQL driver plugin not available for Qt. Installed drivers:")) + qWarning() << qPrintable(tr("PostgreSQL driver plugin not available for Qt. Installed drivers:")) << qPrintable(QSqlDatabase::drivers().join(", ")); return false; } @@ -92,7 +91,7 @@ bool PostgreSqlStorage::initDbSession(QSqlDatabase& db) // as this is the expected behavior. // If it is a newer version, switch to legacy mode. - quWarning() << "Switching Postgres to legacy mode. (set standard conforming strings to off)"; + qWarning() << "Switching Postgres to legacy mode. (set standard conforming strings to off)"; // If the following calls fail, it is a legacy DB anyways, so it doesn't matter // and no need to check the outcome. db.exec("set standard_conforming_strings = off"); @@ -106,14 +105,14 @@ bool PostgreSqlStorage::initDbSession(QSqlDatabase& db) if (query.lastError().isValid()) { // We cannot enable standard conforming strings... // since Quassel does no escaping by itself, this would yield a major vulnerability. - quError() << "Failed to enable standard_conforming_strings for the Postgres db!"; + qCritical() << "Failed to enable standard_conforming_strings for the Postgres db!"; return false; } } break; default: // The slash got replaced with 0 or more than 2 slashes! o_O - quError() << "Your version of Qt does something _VERY_ strange to slashes in QSqlQueries! You should consult your trusted doctor!"; + qCritical() << "Your version of Qt does something _VERY_ strange to slashes in QSqlQueries! You should consult your trusted doctor!"; return false; break; } @@ -121,7 +120,7 @@ bool PostgreSqlStorage::initDbSession(QSqlDatabase& db) // Set the PostgreSQL session timezone to UTC, since we want timestamps stored in UTC QSqlQuery tzQuery = db.exec("SET timezone = 'UTC'"); if (tzQuery.lastError().isValid()) { - quError() << "Failed to set timezone to UTC!"; + qCritical() << "Failed to set timezone to UTC!"; return false; } @@ -165,19 +164,39 @@ int PostgreSqlStorage::installedSchemaVersion() return AbstractSqlStorage::installedSchemaVersion(); } -bool PostgreSqlStorage::updateSchemaVersion(int newVersion) +bool PostgreSqlStorage::updateSchemaVersion(int newVersion, bool clearUpgradeStep) { - QSqlQuery query(logDb()); + // Atomically update the schema version and clear the upgrade step, if specified + // Note: This will need reworked if "updateSchemaVersion" is ever called within a transaction. + QSqlDatabase db = logDb(); + if (!beginTransaction(db)) { + qWarning() << "PostgreSqlStorage::updateSchemaVersion(int, bool): cannot start transaction!"; + qWarning() << " -" << qPrintable(db.lastError().text()); + return false; + } + + QSqlQuery query(db); query.prepare("UPDATE coreinfo SET value = :version WHERE key = 'schemaversion'"); query.bindValue(":version", newVersion); safeExec(query); - bool success = true; if (!watchQuery(query)) { - qCritical() << "PostgreSqlStorage::updateSchemaVersion(int): Updating schema version failed!"; - success = false; + qCritical() << "PostgreSqlStorage::updateSchemaVersion(int, bool): Updating schema version failed!"; + db.rollback(); + return false; } - return success; + + if (clearUpgradeStep) { + // Try clearing the upgrade step if requested + if (!setSchemaVersionUpgradeStep("")) { + db.rollback(); + return false; + } + } + + // Successful, commit and return true + db.commit(); + return true; } bool PostgreSqlStorage::setupSchemaVersion(int version) @@ -195,6 +214,50 @@ bool PostgreSqlStorage::setupSchemaVersion(int version) return success; } +QString PostgreSqlStorage::schemaVersionUpgradeStep() +{ + QSqlQuery query(logDb()); + query.prepare("SELECT value FROM coreinfo WHERE key = 'schemaupgradestep'"); + safeExec(query); + watchQuery(query); + if (query.first()) + return query.value(0).toString(); + + // Fall back to the default value + return AbstractSqlStorage::schemaVersionUpgradeStep(); +} + +bool PostgreSqlStorage::setSchemaVersionUpgradeStep(QString upgradeQuery) +{ + // Intentionally do not wrap in a transaction so other functions can include multiple operations + + QSqlQuery query(logDb()); + query.prepare("UPDATE coreinfo SET value = :upgradestep WHERE key = 'schemaupgradestep'"); + query.bindValue(":upgradestep", upgradeQuery); + safeExec(query); + + // Make sure that the query didn't fail (shouldn't ever happen), and that some non-zero number + // of rows were affected + bool success = watchQuery(query) && query.numRowsAffected() != 0; + + if (!success) { + // The key might not exist (Quassel 0.13.0 and older). Try inserting it... + query = QSqlQuery(logDb()); + query.prepare("INSERT INTO coreinfo (key, value) VALUES ('schemaupgradestep', :upgradestep)"); + query.bindValue(":upgradestep", upgradeQuery); + safeExec(query); + + if (!watchQuery(query)) { + qCritical() << Q_FUNC_INFO << "Setting schema upgrade step failed!"; + success = false; + } + else { + success = true; + } + } + return success; +} + UserId PostgreSqlStorage::addUser(const QString& user, const QString& password, const QString& authenticator) { QSqlQuery query(logDb());