From 7f986b08e0e1d9803e16c376cdd5f13ab171c850 Mon Sep 17 00:00:00 2001 From: Nodir Temirkhodjaev Date: Mon, 19 Oct 2020 18:01:09 +0300 Subject: [PATCH] UI: Fix DB encoding on migrations. --- src/ui/3rdparty/sqlite/sqlitedb.cpp | 46 ++++++++++++++++++++++++----- src/ui/3rdparty/sqlite/sqlitedb.h | 6 +++- src/ui/conf/confmanager.cpp | 8 +---- src/ui/stat/statmanager.cpp | 4 +-- src/ui/stat/statsql.cpp | 4 --- src/ui/stat/statsql.h | 2 -- src/ui/util/app/appinfomanager.cpp | 8 +---- 7 files changed, 47 insertions(+), 31 deletions(-) diff --git a/src/ui/3rdparty/sqlite/sqlitedb.cpp b/src/ui/3rdparty/sqlite/sqlitedb.cpp index 988ab681..6c2bb05f 100644 --- a/src/ui/3rdparty/sqlite/sqlitedb.cpp +++ b/src/ui/3rdparty/sqlite/sqlitedb.cpp @@ -17,6 +17,11 @@ Q_LOGGING_CATEGORY(CLOG_SQLITEDB, "fort.sqlitedb") namespace { +const char *const defaultSqlPragmas = "PRAGMA journal_mode = WAL;" + "PRAGMA locking_mode = EXCLUSIVE;" + "PRAGMA synchronous = NORMAL;" + "PRAGMA encoding = 'UTF-8';"; + bool removeDbFile(const QString &filePath) { if (!filePath.startsWith(QLatin1Char(':')) && QFile::exists(filePath) @@ -177,6 +182,11 @@ bool SqliteDb::rollbackSavepoint(const char *name) : executeStr(QString("ROLLBACK TO %1;").arg(name)); } +int SqliteDb::errorCode() const +{ + return sqlite3_errcode(m_db); +} + QString SqliteDb::errorMessage() const { const char *text = sqlite3_errmsg(m_db); @@ -195,6 +205,17 @@ bool SqliteDb::setUserVersion(int v) return executeStr(sql); } +QString SqliteDb::encoding() +{ + return executeEx("PRAGMA encoding;").toString(); +} + +bool SqliteDb::setEncoding(const QString &v) +{ + const auto sql = QString("PRAGMA encoding = '%1';").arg(v); + return executeStr(sql); +} + QString SqliteDb::entityName(const QString &schemaName, const QString &objectName) { return schemaName.isEmpty() ? objectName : schemaName + '.' + objectName; @@ -237,9 +258,14 @@ QStringList SqliteDb::columnNames(const QString &tableName, const QString &schem return list; } -bool SqliteDb::migrate(const QString &sqlDir, int version, bool recreate, bool importOldData, - SQLITEDB_MIGRATE_FUNC migrateFunc, void *migrateContext) +bool SqliteDb::migrate(const QString &sqlDir, const char *sqlPragmas, int version, bool recreate, + bool importOldData, SQLITEDB_MIGRATE_FUNC migrateFunc, void *migrateContext) { + if (!sqlPragmas) { + sqlPragmas = defaultSqlPragmas; + } + execute(sqlPragmas); + // Check version int userVersion = this->userVersion(); if (userVersion == version) @@ -253,8 +279,10 @@ bool SqliteDb::migrate(const QString &sqlDir, int version, bool recreate, bool i bool isNewDb = (userVersion == 0); // Re-create the DB + QString oldEncoding; QString tempFilePath; if (recreate && !isNewDb) { + oldEncoding = this->encoding(); close(); tempFilePath = m_filePath + ".temp"; @@ -265,6 +293,8 @@ bool SqliteDb::migrate(const QString &sqlDir, int version, bool recreate, bool i return false; } + execute(sqlPragmas); + userVersion = 0; isNewDb = true; } @@ -275,6 +305,10 @@ bool SqliteDb::migrate(const QString &sqlDir, int version, bool recreate, bool i beginTransaction(); + if (!oldEncoding.isEmpty()) { + setEncoding(oldEncoding); + } + while (userVersion < version) { ++userVersion; @@ -327,8 +361,6 @@ bool SqliteDb::migrate(const QString &sqlDir, int version, bool recreate, bool i // Remove the old DB if (success) { removeDbFile(tempFilePath); - } else { - renameDbFile(tempFilePath, m_filePath); } } @@ -342,7 +374,7 @@ bool SqliteDb::importDb( const QLatin1String dstSchema("main"); if (!attach(srcSchema, sourceFilePath)) { - dbWarning() << "Cannot attach the DB" << sourceFilePath; + dbWarning() << "Cannot attach the DB" << sourceFilePath << "Error:" << errorMessage(); return false; } @@ -365,7 +397,7 @@ bool SqliteDb::importDb( } // Intersect column names -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) auto columnsSet = QSet(srcColumns.constBegin(), srcColumns.constEnd()); const auto dstColumnsSet = QSet(dstColumns.constBegin(), dstColumns.constEnd()); #else @@ -374,7 +406,7 @@ bool SqliteDb::importDb( #endif columnsSet.intersect(dstColumnsSet); -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) const QStringList columns(columnsSet.constBegin(), columnsSet.constEnd()); #else const QStringList columns(columnsSet.toList()); diff --git a/src/ui/3rdparty/sqlite/sqlitedb.h b/src/ui/3rdparty/sqlite/sqlitedb.h index 075f38d8..55260541 100644 --- a/src/ui/3rdparty/sqlite/sqlitedb.h +++ b/src/ui/3rdparty/sqlite/sqlitedb.h @@ -50,16 +50,20 @@ public: bool releaseSavepoint(const char *name = nullptr); bool rollbackSavepoint(const char *name = nullptr); + int errorCode() const; QString errorMessage() const; int userVersion(); bool setUserVersion(int v); + QString encoding(); + bool setEncoding(const QString &v); + static QString entityName(const QString &schemaName, const QString &objectName); QStringList tableNames(const QString &schemaName = QString()); QStringList columnNames(const QString &tableName, const QString &schemaName = QString()); - bool migrate(const QString &sqlDir, int version, bool recreate = false, + bool migrate(const QString &sqlDir, const char *sqlPragmas, int version, bool recreate = false, bool importOldData = false, SQLITEDB_MIGRATE_FUNC migrateFunc = nullptr, void *migrateContext = nullptr); diff --git a/src/ui/conf/confmanager.cpp b/src/ui/conf/confmanager.cpp index 94305b47..7b082ae8 100644 --- a/src/ui/conf/confmanager.cpp +++ b/src/ui/conf/confmanager.cpp @@ -28,10 +28,6 @@ Q_LOGGING_CATEGORY(CLOG_CONF_MANAGER, "fort.confManager") namespace { -const char *const sqlPragmas = "PRAGMA journal_mode = WAL;" - "PRAGMA locking_mode = EXCLUSIVE;" - "PRAGMA synchronous = NORMAL;"; - const char *const sqlSelectAddressGroups = "SELECT addr_group_id, include_all, exclude_all," " include_zones, exclude_zones," " include_text, exclude_text" @@ -361,10 +357,8 @@ bool ConfManager::initialize() return false; } - m_sqliteDb->execute(sqlPragmas); - if (!m_sqliteDb->migrate( - ":/conf/migrations", DATABASE_USER_VERSION, true, true, &migrateFunc)) { + ":/conf/migrations", nullptr, DATABASE_USER_VERSION, true, true, &migrateFunc)) { logCritical() << "Migration error" << m_sqliteDb->filePath(); return false; } diff --git a/src/ui/stat/statmanager.cpp b/src/ui/stat/statmanager.cpp index 0be453b8..9480a310 100644 --- a/src/ui/stat/statmanager.cpp +++ b/src/ui/stat/statmanager.cpp @@ -94,10 +94,8 @@ bool StatManager::initialize() return false; } - m_sqliteDb->execute(StatSql::sqlPragmas); - if (!m_sqliteDb->migrate( - ":/stat/migrations", DATABASE_USER_VERSION, true, true, &migrateFunc)) { + ":/stat/migrations", nullptr, DATABASE_USER_VERSION, true, true, &migrateFunc)) { logCritical() << "Migration error" << m_sqliteDb->filePath(); return false; } diff --git a/src/ui/stat/statsql.cpp b/src/ui/stat/statsql.cpp index f27bda1e..30d785c0 100644 --- a/src/ui/stat/statsql.cpp +++ b/src/ui/stat/statsql.cpp @@ -1,9 +1,5 @@ #include "statsql.h" -const char *const StatSql::sqlPragmas = "PRAGMA journal_mode = WAL;" - "PRAGMA locking_mode = EXCLUSIVE;" - "PRAGMA synchronous = NORMAL;"; - const char *const StatSql::sqlSelectAppId = "SELECT app_id FROM app WHERE path = ?1;"; const char *const StatSql::sqlInsertAppId = diff --git a/src/ui/stat/statsql.h b/src/ui/stat/statsql.h index f1315e3a..e5f02cb0 100644 --- a/src/ui/stat/statsql.h +++ b/src/ui/stat/statsql.h @@ -4,8 +4,6 @@ class StatSql { public: - static const char *const sqlPragmas; - static const char *const sqlSelectAppId; static const char *const sqlInsertAppId; static const char *const sqlDeleteAppId; diff --git a/src/ui/util/app/appinfomanager.cpp b/src/ui/util/app/appinfomanager.cpp index 8f6ffcdf..f21f3298 100644 --- a/src/ui/util/app/appinfomanager.cpp +++ b/src/ui/util/app/appinfomanager.cpp @@ -22,10 +22,6 @@ Q_LOGGING_CATEGORY(CLOG_APPINFOCACHE, "fort.appInfoWorker") namespace { -const char *const sqlPragmas = "PRAGMA journal_mode = WAL;" - "PRAGMA locking_mode = EXCLUSIVE;" - "PRAGMA synchronous = NORMAL;"; - const char *const sqlSelectAppInfo = "SELECT file_descr, company_name," " product_name, product_ver, file_mod_time, icon_id" " FROM app WHERE path = ?1;"; @@ -81,9 +77,7 @@ void AppInfoManager::setupDb(const QString &filePath) return; } - m_sqliteDb->execute(sqlPragmas); - - if (!m_sqliteDb->migrate(":/appinfocache/migrations", DATABASE_USER_VERSION, true)) { + if (!m_sqliteDb->migrate(":/appinfocache/migrations", nullptr, DATABASE_USER_VERSION, true)) { logCritical() << "Migration error" << filePath; return; }