UI: Fix DB encoding on migrations.

This commit is contained in:
Nodir Temirkhodjaev 2020-10-19 18:01:09 +03:00
parent dee9b73d2d
commit 7f986b08e0
7 changed files with 47 additions and 31 deletions

View File

@ -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<QString>(srcColumns.constBegin(), srcColumns.constEnd());
const auto dstColumnsSet = QSet<QString>(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());

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 =

View File

@ -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;

View File

@ -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;
}