From 3d8b086f533d252608f31806df1bae39bffa2d2f Mon Sep 17 00:00:00 2001 From: Albert S Date: Sun, 27 Feb 2022 23:37:22 +0100 Subject: [PATCH] shared: Begin db migration logic Issue: #26 --- shared/create.qrc | 5 -- shared/dbmigrator.cpp | 85 +++++++++++++++++++++++++ shared/dbmigrator.h | 24 +++++++ shared/{create.sql => migrations/1.sql} | 0 shared/migrations/migrations.qrc | 5 ++ shared/shared.pro | 8 ++- 6 files changed, 121 insertions(+), 6 deletions(-) delete mode 100644 shared/create.qrc create mode 100644 shared/dbmigrator.cpp create mode 100644 shared/dbmigrator.h rename shared/{create.sql => migrations/1.sql} (100%) create mode 100644 shared/migrations/migrations.qrc diff --git a/shared/create.qrc b/shared/create.qrc deleted file mode 100644 index 74a3900..0000000 --- a/shared/create.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - create.sql - - diff --git a/shared/dbmigrator.cpp b/shared/dbmigrator.cpp new file mode 100644 index 0000000..45ab556 --- /dev/null +++ b/shared/dbmigrator.cpp @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include +#include "dbmigrator.h" +#include "looqsgeneralexception.h" + +DBMigrator::DBMigrator(QSqlDatabase &db) +{ + Q_INIT_RESOURCE(migrations); + this->db = &db; +} + +DBMigrator::~DBMigrator() +{ + Q_CLEANUP_RESOURCE(migrations); +} + +QStringList DBMigrator::getMigrationFilenames() +{ + QStringList result; + QDirIterator it(":/looqs-migrations/"); + while(it.hasNext()) + { + result.append(it.next()); + } + return result; +} + +uint32_t DBMigrator::currentRevision() +{ + QSqlQuery dbquery(*db); + dbquery.exec("PRAGMA user_version;"); + if(!dbquery.next()) + { + throw new LooqsGeneralException("Failed to query current db revision"); + } + uint32_t result = dbquery.value(0).toUInt(); + return result; +} + +bool DBMigrator::migrationNeeded() +{ + QStringList migrations = getMigrationFilenames(); + uint32_t currentRev = currentRevision(); + + return currentRev < static_cast(migrations.size()); +} + +void DBMigrator::performMigrations() +{ + QStringList migrations = getMigrationFilenames(); + uint32_t currentRev = currentRevision(); + uint32_t targetRev = (migrations.size()); + + for(uint32_t i = currentRev + 1; i <= targetRev; i++) + { + QString fileName = QString(":/looqs-migrations/%1.sql").arg(i); + QFile file{fileName}; + if(!file.open(QIODevice::ReadOnly)) + { + throw LooqsGeneralException("Migration: Failed to find required revision file"); + } + QTextStream stream(&file); + db->transaction(); + while(!stream.atEnd()) + { + QString sql = stream.readLine(); + QSqlQuery sqlQuery{*db}; + if(!sqlQuery.exec(sql)) + { + + db->rollback(); + throw LooqsGeneralException("Failed to execute sql statement while initializing database: " + + sqlQuery.lastError().text()); + } + } + QSqlQuery updateVersion{*db}; + updateVersion.exec(QString("PRAGMA user_version=%1;").arg(i)); + db->commit(); + emit migrationDone(i); + } + emit done(); +} diff --git a/shared/dbmigrator.h b/shared/dbmigrator.h new file mode 100644 index 0000000..d9ffee3 --- /dev/null +++ b/shared/dbmigrator.h @@ -0,0 +1,24 @@ +#ifndef DBMIGRATOR_H +#define DBMIGRATOR_H +#include +#include +#include +class DBMigrator : public QObject +{ + Q_OBJECT + private: + QSqlDatabase *db; + + public: + DBMigrator(QSqlDatabase &db); + ~DBMigrator(); + uint32_t currentRevision(); + void performMigrations(); + QStringList getMigrationFilenames(); + bool migrationNeeded(); + signals: + void migrationDone(uint32_t); + void done(); +}; + +#endif // DBMIGRATOR_H diff --git a/shared/create.sql b/shared/migrations/1.sql similarity index 100% rename from shared/create.sql rename to shared/migrations/1.sql diff --git a/shared/migrations/migrations.qrc b/shared/migrations/migrations.qrc new file mode 100644 index 0000000..15bc5ce --- /dev/null +++ b/shared/migrations/migrations.qrc @@ -0,0 +1,5 @@ + + + 1.sql + + diff --git a/shared/shared.pro b/shared/shared.pro index fbbdd8b..5c9341f 100644 --- a/shared/shared.pro +++ b/shared/shared.pro @@ -27,12 +27,18 @@ DEFINES += QT_DEPRECATED_WARNINGS #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += sqlitesearch.cpp \ + databasefactory.cpp \ + dbmigrator.cpp \ + logger.cpp \ looqsgeneralexception.cpp \ common.cpp \ looqsquery.cpp HEADERS += sqlitesearch.h \ + databasefactory.h \ + dbmigrator.h \ filedata.h \ + logger.h \ looqsgeneralexception.h \ looqsquery.h \ searchresult.h \ @@ -42,4 +48,4 @@ unix { target.path = /usr/lib INSTALLS += target } -RESOURCES = create.qrc +RESOURCES = migrations/migrations.qrc