[network/ruqola] src/core/localdatabase: Fix initiaze database. Remove duplicate code

Laurent Montel <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit b2dd6a1209243f1a97838a98ad543bfc11e4a9f8 by Laurent Montel.
Committed on 16/08/2026 at 12:57.
Pushed by mlaurent into branch 'master'.

Fix initiaze database. Remove duplicate code

M  +58   -57   src/core/localdatabase/localdatabasebase.cpp
M  +2    -0    src/core/localdatabase/localdatabasebase.h

https://invent.kde.org/network/ruqola/-/commit/b2dd6a1209243f1a97838a98ad543bfc11e4a9f8

diff --git a/src/core/localdatabase/localdatabasebase.cpp b/src/core/localdatabase/localdatabasebase.cpp
index 45c072f0e6..bfeb975105 100644
--- a/src/core/localdatabase/localdatabasebase.cpp
+++ b/src/core/localdatabase/localdatabasebase.cpp
@@ -9,6 +9,7 @@
 #include "ruqola_database_debug.h"
 
 #include <QDir>
+#include <QFile>
 #include <QFileInfo>
 #include <QSqlDatabase>
 #include <QSqlError>
@@ -125,78 +126,78 @@ QString LocalDatabaseBase::generateDatabaseName(const QString &accountName, cons
     return dbName;
 }
 
-bool LocalDatabaseBase::initializeDataBase(const QString &accountName, const QByteArray &roomId, QSqlDatabase &db)
+void LocalDatabaseBase::forgetDataBase(const QString &dbName, QSqlDatabase &db)
 {
-    const QString dbName = generateDatabaseName(accountName, roomId);
-    db = QSqlDatabase::database(dbName);
-    if (!db.isValid()) {
-        db = QSqlDatabase::addDatabase(u"QSQLITE"_s, dbName);
-        const QString dirPath = mBasePath + accountName;
-        if (!QDir().mkpath(dirPath)) {
-            qCWarning(RUQOLA_DATABASE_LOG) << "Couldn't create" << dirPath;
-            return false;
-        }
-        const QString fileName = dbFileName(accountName, roomId);
-        const bool dbExists = QFileInfo::exists(fileName);
-        db.setDatabaseName(fileName);
-        if (!db.open()) {
-            qCWarning(RUQOLA_DATABASE_LOG) << "Couldn't create" << db.databaseName();
-            return false;
-        }
-        QSqlQuery query(db);
-        if (!dbExists) {
-            query.exec(schemaDataBase());
-            if (query.lastError().isValid()) {
-                qCWarning(RUQOLA_DATABASE_LOG) << "Couldn't create table LOGS in" << db.databaseName() << ":" << db.lastError();
-                return false;
-            }
-        }
-        // Using the write-ahead log and sync = NORMAL for faster writes
-        // (idea taken from kactivities-stat)
-        query.exec(u"PRAGMA synchronous = 1"_s);
-        // use the write-ahead log (requires sqlite > 3.7.0)
-        query.exec(u"PRAGMA journal_mode = WAL"_s);
+    // removeDatabase() warns and keeps the connection alive as long as a QSqlDatabase copy exists,
+    // so drop ours first.
+    db = QSqlDatabase();
+    if (QSqlDatabase::contains(dbName)) {
+        QSqlDatabase::removeDatabase(dbName);
     }
-
-    Q_ASSERT(db.isValid());
-    Q_ASSERT(db.isOpen());
-    return true;
 }
 
-bool LocalDatabaseBase::initializeDataBase(const QString &accountName, QSqlDatabase &db)
+bool LocalDatabaseBase::openOrCreateDataBase(const QString &dbName, const QString &dirPath, const QString &fileName, QSqlDatabase &db)
 {
-    const QString dbName = databaseName(accountName);
     db = QSqlDatabase::database(dbName);
-    if (!db.isValid()) {
-        db = QSqlDatabase::addDatabase(u"QSQLITE"_s, dbName);
-        const QString dirPath = mBasePath + accountName;
-        if (!QDir().mkpath(dirPath)) {
-            qCWarning(RUQOLA_DATABASE_LOG) << "Couldn't create" << dirPath;
-            return false;
-        }
-        const QString fileName = dbFileName(accountName);
-        const bool dbExists = QFileInfo::exists(fileName);
-        db.setDatabaseName(fileName);
-        if (!db.open()) {
-            qCWarning(RUQOLA_DATABASE_LOG) << "Couldn't create" << db.databaseName();
-            return false;
-        }
+    if (db.isValid() && db.isOpen()) {
+        return true;
+    }
+    // Either there is no such connection yet, or a previous attempt failed halfway through (the
+    // connection is registered but was never opened). Drop it: isValid() only tells us the driver
+    // is there, so keeping it would make us skip the schema creation below forever.
+    forgetDataBase(dbName, db);
+
+    if (!QDir().mkpath(dirPath)) {
+        qCWarning(RUQOLA_DATABASE_LOG) << "Couldn't create" << dirPath;
+        return false;
+    }
+    const bool dbExists = QFileInfo::exists(fileName);
+    db = QSqlDatabase::addDatabase(u"QSQLITE"_s, dbName);
+    db.setDatabaseName(fileName);
+    if (!db.open()) {
+        qCWarning(RUQOLA_DATABASE_LOG) << "Couldn't create" << db.databaseName();
+        forgetDataBase(dbName, db);
+        return false;
+    }
+    bool schemaFailed = false;
+    {
         QSqlQuery query(db);
         if (!dbExists) {
             query.exec(schemaDataBase());
             if (query.lastError().isValid()) {
-                qCWarning(RUQOLA_DATABASE_LOG) << "Couldn't create table LOGS in" << db.databaseName() << ":" << db.lastError();
-                return false;
+                qCWarning(RUQOLA_DATABASE_LOG) << "Couldn't create table in" << db.databaseName() << ":" << db.lastError();
+                schemaFailed = true;
             }
         }
-        // Using the write-ahead log and sync = NORMAL for faster writes
-        // (idea taken from kactivities-stat)
-        query.exec(u"PRAGMA synchronous = 1"_s);
-        // use the write-ahead log (requires sqlite > 3.7.0)
-        query.exec(u"PRAGMA journal_mode = WAL"_s);
+        if (!schemaFailed) {
+            // Using the write-ahead log and sync = NORMAL for faster writes
+            // (idea taken from kactivities-stat)
+            query.exec(u"PRAGMA synchronous = 1"_s);
+            // use the write-ahead log (requires sqlite > 3.7.0)
+            query.exec(u"PRAGMA journal_mode = WAL"_s);
+        }
+    }
+    if (schemaFailed) {
+        // open() has just created an empty file. Remove it along with the connection, otherwise the
+        // next run would see an existing file, skip the schema creation and query missing tables.
+        forgetDataBase(dbName, db);
+        if (!QFile::remove(fileName)) {
+            qCWarning(RUQOLA_DATABASE_LOG) << "Couldn't remove incomplete database" << fileName;
+        }
+        return false;
     }
 
     Q_ASSERT(db.isValid());
     Q_ASSERT(db.isOpen());
     return true;
 }
+
+bool LocalDatabaseBase::initializeDataBase(const QString &accountName, const QByteArray &roomId, QSqlDatabase &db)
+{
+    return openOrCreateDataBase(generateDatabaseName(accountName, roomId), mBasePath + accountName, dbFileName(accountName, roomId), db);
+}
+
+bool LocalDatabaseBase::initializeDataBase(const QString &accountName, QSqlDatabase &db)
+{
+    return openOrCreateDataBase(databaseName(accountName), mBasePath + accountName, dbFileName(accountName), db);
+}
diff --git a/src/core/localdatabase/localdatabasebase.h b/src/core/localdatabase/localdatabasebase.h
index 8ac6743539..f9c3e7567b 100644
--- a/src/core/localdatabase/localdatabasebase.h
+++ b/src/core/localdatabase/localdatabasebase.h
@@ -49,4 +49,6 @@ protected:
 
 private:
     [[nodiscard]] LIBRUQOLACORE_NO_EXPORT QString generateDatabaseName(const QString &accountName, const QByteArray &roomId) const;
+    [[nodiscard]] LIBRUQOLACORE_NO_EXPORT bool openOrCreateDataBase(const QString &dbName, const QString &dirPath, const QString &fileName, QSqlDatabase &db);
+    LIBRUQOLACORE_NO_EXPORT static void forgetDataBase(const QString &dbName, QSqlDatabase &db);
 };
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.