set DB schema version programmatically in a centralized way, use exceptions when things go wrong

This commit is contained in:
Martin Rotter 2022-02-02 08:43:45 +01:00
parent 392ff2415f
commit 46f3e25e92
6 changed files with 45 additions and 37 deletions

View File

@ -3,8 +3,6 @@ CREATE TABLE Information (
inf_value TEXT
);
-- !
INSERT INTO Information VALUES ('schema_version', '2');
-- !
CREATE TABLE Accounts (
id $$,
type TEXT NOT NULL CHECK (type != ''), /* ID of the account type. Each account defines its own, for example 'ttrss'. */

View File

@ -26,6 +26,4 @@ INSERT INTO Feeds (id, title, description, date_created, icon, category, source,
SELECT id, title, description, date_created, icon, category, source, update_type, update_interval, account_id, custom_id, custom_data
FROM backup_Feeds;
-- !
DROP TABLE backup_Feeds;
-- !
UPDATE Information SET inf_value = '2' WHERE inf_key = 'schema_version';
DROP TABLE backup_Feeds;

View File

@ -14,28 +14,23 @@
DatabaseDriver::DatabaseDriver(QObject* parent) : QObject(parent)
{}
bool DatabaseDriver::updateDatabaseSchema(QSqlQuery& query,
void DatabaseDriver::updateDatabaseSchema(QSqlQuery& query,
int source_db_schema_version,
const QString& database_name) {
const int current_version = QSL(APP_DB_SCHEMA_VERSION).toInt();
while (source_db_schema_version != current_version) {
try {
const QStringList statements = prepareScript(APP_SQL_PATH,
QSL(APP_DB_UPDATE_FILE_PATTERN).arg(ddlFilePrefix(),
QString::number(source_db_schema_version),
QString::number(source_db_schema_version + 1)),
database_name);
const QStringList statements = prepareScript(APP_SQL_PATH,
QSL(APP_DB_UPDATE_FILE_PATTERN).arg(ddlFilePrefix(),
QString::number(source_db_schema_version),
QString::number(source_db_schema_version + 1)),
database_name);
for (const QString& statement : statements) {
if (!query.exec(statement) && query.lastError().isValid()) {
throw ApplicationException(query.lastError().text());
}
for (const QString& statement : statements) {
if (!query.exec(statement) && query.lastError().isValid()) {
throw ApplicationException(query.lastError().text());
}
}
catch (const ApplicationException& ex) {
qFatal("Error when running SQL scripts: %s.", qPrintable(ex.message()));
}
// Increment the version.
qDebugNN << LOGSEC_DB
@ -47,7 +42,20 @@ bool DatabaseDriver::updateDatabaseSchema(QSqlQuery& query,
source_db_schema_version++;
}
return true;
setSchemaVersion(query, current_version, false);
}
void DatabaseDriver::setSchemaVersion(QSqlQuery& query, int new_schema_version, bool empty_table) {
if (!query.prepare(empty_table
? QSL("INSERT INTO Information VALUES ('schema_version', :schema_version);")
: QSL("UPDATE Information SET inf_value = :schema_version WHERE inf_key = 'schema_version';"))) {
throw ApplicationException(query.lastError().text());
}
query.bindValue(QSL(":schema_version"), QString::number(new_schema_version));
if (!query.exec()) {
throw ApplicationException(query.lastError().text());
}
}
QStringList DatabaseDriver::prepareScript(const QString& base_sql_folder,

View File

@ -46,10 +46,12 @@ class DatabaseDriver : public QObject {
DatabaseDriver::DesiredStorageType desired_type = DatabaseDriver::DesiredStorageType::FromSettings) = 0;
protected:
bool updateDatabaseSchema(QSqlQuery& query,
void updateDatabaseSchema(QSqlQuery& query,
int source_db_schema_version,
const QString& database_name = {});
void setSchemaVersion(QSqlQuery& query, int new_schema_version, bool empty_table);
QStringList prepareScript(const QString& base_sql_folder,
const QString& sql_file,
const QString& database_name = {});

View File

@ -183,6 +183,8 @@ QSqlDatabase MariaDbDriver::initializeDatabase(const QString& connection_name) {
throw ApplicationException(query_db.lastError().text());
}
}
setSchemaVersion(query_db, QSL(APP_DB_SCHEMA_VERSION).toInt(), true);
}
catch (const ApplicationException& ex) {
qFatal("Error when running SQL scripts: %s.", qPrintable(ex.message()));
@ -196,18 +198,17 @@ QSqlDatabase MariaDbDriver::initializeDatabase(const QString& connection_name) {
const int installed_db_schema = query_db.value(0).toString().toInt();
if (installed_db_schema < QSL(APP_DB_SCHEMA_VERSION).toInt()) {
if (updateDatabaseSchema(query_db, installed_db_schema, database_name)) {
try {
updateDatabaseSchema(query_db, installed_db_schema, database_name);
qDebugNN << LOGSEC_DB
<< "Database schema was updated from"
<< QUOTE_W_SPACE(installed_db_schema)
<< "to"
<< QUOTE_W_SPACE(APP_DB_SCHEMA_VERSION)
<< "successully or it is already up to date.";
<< "successully.";
}
else {
qFatal("Database schema was not updated from '%s' to '%s' successully.",
qPrintable(QString::number(installed_db_schema)),
APP_DB_SCHEMA_VERSION);
catch (const ApplicationException& ex) {
qFatal("Error when updating DB schema from %d: %s.", installed_db_schema, qPrintable(ex.message()));
}
}
}

View File

@ -254,6 +254,8 @@ QSqlDatabase SqliteDriver::initializeDatabase(const QString& connection_name, bo
throw ApplicationException(query_db.lastError().text());
}
}
setSchemaVersion(query_db, QSL(APP_DB_SCHEMA_VERSION).toInt(), true);
}
catch (const ApplicationException& ex) {
qFatal("Error when running SQL scripts: %s.", qPrintable(ex.message()));
@ -274,18 +276,17 @@ QSqlDatabase SqliteDriver::initializeDatabase(const QString& connection_name, bo
qFatal("Creation of backup SQLite DB file failed.");
}
if (updateDatabaseSchema(query_db, installed_db_schema)) {
try {
updateDatabaseSchema(query_db, installed_db_schema);
qDebugNN << LOGSEC_DB
<< "Database schema was updated from '"
<< installed_db_schema
<< "' to '"
<< APP_DB_SCHEMA_VERSION
<< "' successully or it is already up to date.";
<< "Database schema was updated from"
<< QUOTE_W_SPACE(installed_db_schema)
<< "to"
<< QUOTE_W_SPACE(APP_DB_SCHEMA_VERSION)
<< "successully.";
}
else {
qFatal("Database schema was not updated from '%s' to '%s' successully.",
qPrintable(QString::number(installed_db_schema)),
APP_DB_SCHEMA_VERSION);
catch (const ApplicationException& ex) {
qFatal("Error when updating DB schema from %d: %s.", installed_db_schema, qPrintable(ex.message()));
}
}