mirror of
https://github.com/tnodir/fort
synced 2024-11-15 05:46:03 +00:00
UI: ConfManager: Import DB without app restarting
This commit is contained in:
parent
1e251de80b
commit
83114e1569
59
src/ui/3rdparty/sqlite/sqlitedb.cpp
vendored
59
src/ui/3rdparty/sqlite/sqlitedb.cpp
vendored
@ -88,6 +88,8 @@ bool SqliteDb::open()
|
|||||||
const bool ok = sqlite3_open_v2(filePathUtf8.data(), &m_db, m_openFlags, nullptr) == SQLITE_OK;
|
const bool ok = sqlite3_open_v2(filePathUtf8.data(), &m_db, m_openFlags, nullptr) == SQLITE_OK;
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
|
setBusyTimeoutMs(DATABASE_BUSY_TIMEOUT);
|
||||||
|
|
||||||
SqliteDbExt::registerExtensions(this);
|
SqliteDbExt::registerExtensions(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,10 +302,22 @@ QStringList SqliteDb::columnNames(const QString &tableName, const QString &schem
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SqliteDb::import(SqliteDb::MigrateOptions &opt)
|
||||||
|
{
|
||||||
|
// Get the importing DB version
|
||||||
|
{
|
||||||
|
SqliteDb db(opt.backupFilePath, SqliteDb::OpenDefaultReadOnly);
|
||||||
|
if (!db.open())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
opt.userVersion = db.userVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
return importDb(opt);
|
||||||
|
}
|
||||||
|
|
||||||
bool SqliteDb::migrate(MigrateOptions &opt)
|
bool SqliteDb::migrate(MigrateOptions &opt)
|
||||||
{
|
{
|
||||||
setBusyTimeoutMs(DATABASE_BUSY_TIMEOUT);
|
|
||||||
|
|
||||||
if (!opt.sqlPragmas) {
|
if (!opt.sqlPragmas) {
|
||||||
opt.sqlPragmas = defaultSqlPragmas;
|
opt.sqlPragmas = defaultSqlPragmas;
|
||||||
}
|
}
|
||||||
@ -316,16 +330,14 @@ bool SqliteDb::migrate(MigrateOptions &opt)
|
|||||||
|
|
||||||
opt.userVersion = userVersion;
|
opt.userVersion = userVersion;
|
||||||
|
|
||||||
// Check migration options
|
|
||||||
if (!canMigrate(opt))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Migrate the DB
|
// Migrate the DB
|
||||||
const bool isNewDb = (userVersion == 0);
|
const bool isNewDb = (userVersion == 0);
|
||||||
if (isNewDb) {
|
if (isNewDb) {
|
||||||
opt.recreate = false;
|
opt.recreate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opt.backupFilePath = backupFilePath();
|
||||||
|
|
||||||
return migrateDb(opt, userVersion, isNewDb);
|
return migrateDb(opt, userVersion, isNewDb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,6 +359,10 @@ bool SqliteDb::canMigrate(const MigrateOptions &opt) const
|
|||||||
|
|
||||||
bool SqliteDb::migrateDb(const MigrateOptions &opt, int userVersion, bool isNewDb)
|
bool SqliteDb::migrateDb(const MigrateOptions &opt, int userVersion, bool isNewDb)
|
||||||
{
|
{
|
||||||
|
// Check migration options
|
||||||
|
if (!canMigrate(opt))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!migrateDbBegin(opt, userVersion, isNewDb))
|
if (!migrateDbBegin(opt, userVersion, isNewDb))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -422,7 +438,7 @@ bool SqliteDb::migrateDbBegin(const MigrateOptions &opt, int &userVersion, bool
|
|||||||
userVersion = 0;
|
userVersion = 0;
|
||||||
isNewDb = true;
|
isNewDb = true;
|
||||||
|
|
||||||
return clearWithBackup(opt.sqlPragmas);
|
return clearWithBackup(opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SqliteDb::migrateDbEnd(const MigrateOptions &opt)
|
bool SqliteDb::migrateDbEnd(const MigrateOptions &opt)
|
||||||
@ -506,21 +522,19 @@ bool SqliteDb::createFtsTable(const FtsTable &ftsTable)
|
|||||||
return executeStr(sql);
|
return executeStr(sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SqliteDb::clearWithBackup(const char *sqlPragmas)
|
bool SqliteDb::clearWithBackup(const MigrateOptions &opt)
|
||||||
{
|
{
|
||||||
const QString oldEncoding = this->encoding();
|
const QString oldEncoding = this->encoding();
|
||||||
|
|
||||||
close();
|
close();
|
||||||
|
|
||||||
const QString tempFilePath = backupFilePath();
|
if (!(renameDbFile(m_filePath, opt.backupFilePath) && open())) {
|
||||||
|
|
||||||
if (!(renameDbFile(m_filePath, tempFilePath) && open())) {
|
|
||||||
qCWarning(LC) << "Cannot re-create the DB" << m_filePath;
|
qCWarning(LC) << "Cannot re-create the DB" << m_filePath;
|
||||||
renameDbFile(tempFilePath, m_filePath);
|
renameDbFile(opt.backupFilePath, m_filePath);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
execute(sqlPragmas);
|
execute(opt.sqlPragmas);
|
||||||
setEncoding(oldEncoding);
|
setEncoding(oldEncoding);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -530,16 +544,14 @@ bool SqliteDb::importBackup(const MigrateOptions &opt)
|
|||||||
{
|
{
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
|
||||||
const QString tempFilePath = backupFilePath();
|
|
||||||
|
|
||||||
// Re-import the DB
|
// Re-import the DB
|
||||||
if (opt.importOldData) {
|
if (opt.importOldData) {
|
||||||
success = importDb(opt, tempFilePath);
|
success = importDb(opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the old DB
|
// Remove the old DB
|
||||||
if (success) {
|
if (success) {
|
||||||
removeDbFile(tempFilePath);
|
removeDbFile(opt.backupFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
@ -550,11 +562,13 @@ QString SqliteDb::backupFilePath() const
|
|||||||
return m_filePath + ".temp";
|
return m_filePath + ".temp";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SqliteDb::importDb(const MigrateOptions &opt, const QString &sourceFilePath)
|
bool SqliteDb::importDb(const MigrateOptions &opt)
|
||||||
{
|
{
|
||||||
const QString srcSchema = migrationOldSchemaName();
|
const QString srcSchema = migrationOldSchemaName();
|
||||||
const QString dstSchema = migrationNewSchemaName();
|
const QString dstSchema = migrationNewSchemaName();
|
||||||
|
|
||||||
|
const QString &sourceFilePath = opt.backupFilePath;
|
||||||
|
|
||||||
if (!attach(srcSchema, sourceFilePath)) {
|
if (!attach(srcSchema, sourceFilePath)) {
|
||||||
qCWarning(LC) << "Cannot attach the DB" << sourceFilePath << "Error:" << errorMessage();
|
qCWarning(LC) << "Cannot attach the DB" << sourceFilePath << "Error:" << errorMessage();
|
||||||
return false;
|
return false;
|
||||||
@ -587,6 +601,8 @@ bool SqliteDb::copyTables(const QString &srcSchema, const QString &dstSchema)
|
|||||||
const QStringList srcTableNames = tableNames(srcSchema);
|
const QStringList srcTableNames = tableNames(srcSchema);
|
||||||
|
|
||||||
for (const QString &tableName : srcTableNames) {
|
for (const QString &tableName : srcTableNames) {
|
||||||
|
clearTable(dstSchema, tableName);
|
||||||
|
|
||||||
if (!copyTable(srcSchema, dstSchema, tableName))
|
if (!copyTable(srcSchema, dstSchema, tableName))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -623,6 +639,13 @@ bool SqliteDb::copyTable(
|
|||||||
return executeStr(sql);
|
return executeStr(sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SqliteDb::clearTable(const QString &dstSchema, const QString &tableName)
|
||||||
|
{
|
||||||
|
const auto sql = QString("DELETE FROM %1;").arg(entityName(dstSchema, tableName));
|
||||||
|
|
||||||
|
return executeStr(sql);
|
||||||
|
}
|
||||||
|
|
||||||
SqliteStmt *SqliteDb::stmt(const char *sql)
|
SqliteStmt *SqliteDb::stmt(const char *sql)
|
||||||
{
|
{
|
||||||
SqliteStmt *stmt = m_stmts.value(sql);
|
SqliteStmt *stmt = m_stmts.value(sql);
|
||||||
|
15
src/ui/3rdparty/sqlite/sqlitedb.h
vendored
15
src/ui/3rdparty/sqlite/sqlitedb.h
vendored
@ -45,15 +45,21 @@ public:
|
|||||||
|
|
||||||
struct MigrateOptions
|
struct MigrateOptions
|
||||||
{
|
{
|
||||||
const QString sqlDir;
|
const char *sqlDir;
|
||||||
const char *sqlPragmas = nullptr;
|
const char *sqlPragmas = nullptr;
|
||||||
|
|
||||||
int version = 0;
|
int version = 0;
|
||||||
int userVersion = 0;
|
int userVersion = 0;
|
||||||
|
|
||||||
bool recreate = true;
|
bool recreate = true;
|
||||||
bool importOldData = true;
|
bool importOldData = true;
|
||||||
bool autoCopyTables = true;
|
bool autoCopyTables = true;
|
||||||
|
|
||||||
|
QString backupFilePath;
|
||||||
|
|
||||||
SQLITEDB_MIGRATE_FUNC migrateFunc = nullptr;
|
SQLITEDB_MIGRATE_FUNC migrateFunc = nullptr;
|
||||||
void *migrateContext = nullptr;
|
void *migrateContext = nullptr;
|
||||||
|
|
||||||
QVector<FtsTable> ftsTables;
|
QVector<FtsTable> ftsTables;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -115,6 +121,8 @@ public:
|
|||||||
QStringList tableNames(const QString &schemaName = {});
|
QStringList tableNames(const QString &schemaName = {});
|
||||||
QStringList columnNames(const QString &tableName, const QString &schemaName = {});
|
QStringList columnNames(const QString &tableName, const QString &schemaName = {});
|
||||||
|
|
||||||
|
bool import(SqliteDb::MigrateOptions &opt);
|
||||||
|
|
||||||
bool migrate(SqliteDb::MigrateOptions &opt);
|
bool migrate(SqliteDb::MigrateOptions &opt);
|
||||||
|
|
||||||
SqliteStmt *stmt(const char *sql);
|
SqliteStmt *stmt(const char *sql);
|
||||||
@ -136,14 +144,15 @@ private:
|
|||||||
bool createFtsTables(const MigrateOptions &opt);
|
bool createFtsTables(const MigrateOptions &opt);
|
||||||
bool createFtsTable(const FtsTable &ftsTable);
|
bool createFtsTable(const FtsTable &ftsTable);
|
||||||
|
|
||||||
bool clearWithBackup(const char *sqlPragmas);
|
bool clearWithBackup(const MigrateOptions &opt);
|
||||||
bool importBackup(const MigrateOptions &opt);
|
bool importBackup(const MigrateOptions &opt);
|
||||||
|
|
||||||
QString backupFilePath() const;
|
QString backupFilePath() const;
|
||||||
|
|
||||||
bool importDb(const MigrateOptions &opt, const QString &sourceFilePath);
|
bool importDb(const MigrateOptions &opt);
|
||||||
bool copyTables(const QString &srcSchema, const QString &dstSchema);
|
bool copyTables(const QString &srcSchema, const QString &dstSchema);
|
||||||
bool copyTable(const QString &srcSchema, const QString &dstSchema, const QString &tableName);
|
bool copyTable(const QString &srcSchema, const QString &dstSchema, const QString &tableName);
|
||||||
|
bool clearTable(const QString &dstSchema, const QString &tableName);
|
||||||
|
|
||||||
void clearStmts();
|
void clearStmts();
|
||||||
|
|
||||||
|
@ -219,6 +219,30 @@ bool migrateFunc(SqliteDb *db, int version, bool isNewDb, void *ctx)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SqliteDb::MigrateOptions migrateOptions()
|
||||||
|
{
|
||||||
|
SqliteDb::MigrateOptions opt = {
|
||||||
|
.sqlDir = ":/conf/migrations",
|
||||||
|
.version = DATABASE_USER_VERSION,
|
||||||
|
.recreate = true,
|
||||||
|
.migrateFunc = &migrateFunc,
|
||||||
|
.ftsTables = {
|
||||||
|
{
|
||||||
|
.contentTable = "app",
|
||||||
|
.contentRowid = "app_id",
|
||||||
|
.columns = { "path", "name", "notes" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.contentTable = "rule",
|
||||||
|
.contentRowid = "rule_id",
|
||||||
|
.columns = { "name", "notes" }
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return opt;
|
||||||
|
}
|
||||||
|
|
||||||
bool loadAddressGroups(SqliteDb *db, const QList<AddressGroup *> &addressGroups, int &index)
|
bool loadAddressGroups(SqliteDb *db, const QList<AddressGroup *> &addressGroups, int &index)
|
||||||
{
|
{
|
||||||
SqliteStmt stmt;
|
SqliteStmt stmt;
|
||||||
@ -512,24 +536,7 @@ bool ConfManager::setupDb()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SqliteDb::MigrateOptions opt = {
|
SqliteDb::MigrateOptions opt = migrateOptions();
|
||||||
.sqlDir = ":/conf/migrations",
|
|
||||||
.version = DATABASE_USER_VERSION,
|
|
||||||
.recreate = true,
|
|
||||||
.migrateFunc = &migrateFunc,
|
|
||||||
.ftsTables = {
|
|
||||||
{
|
|
||||||
.contentTable = "app",
|
|
||||||
.contentRowid = "app_id",
|
|
||||||
.columns = { "path", "name", "notes" }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.contentTable = "rule",
|
|
||||||
.contentRowid = "rule_id",
|
|
||||||
.columns = { "name", "notes" }
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!sqliteDb()->migrate(opt)) {
|
if (!sqliteDb()->migrate(opt)) {
|
||||||
qCCritical(LC) << "Migration error" << sqliteDb()->filePath();
|
qCCritical(LC) << "Migration error" << sqliteDb()->filePath();
|
||||||
@ -773,13 +780,11 @@ bool ConfManager::importBackup(const QString &path)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
settings->clearCache();
|
settings->clearCache();
|
||||||
|
|
||||||
|
emit iniUserChanged(iniUser(), /*onlyFlags=*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Import DB: Close DB from UI side
|
// Import DB
|
||||||
{
|
|
||||||
sqliteDb()->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
return importMasterBackup(inPath);
|
return importMasterBackup(inPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -798,17 +803,20 @@ bool ConfManager::importMasterBackup(const QString &path)
|
|||||||
|
|
||||||
// Import Db
|
// Import Db
|
||||||
if (ok) {
|
if (ok) {
|
||||||
sqliteDb()->close();
|
SqliteDb::MigrateOptions opt = migrateOptions();
|
||||||
|
|
||||||
ok = importFile(sqliteDb()->filePath(), path);
|
opt.backupFilePath = path + FileUtil::fileName(sqliteDb()->filePath());
|
||||||
|
|
||||||
|
ok = sqliteDb()->import(opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ok) {
|
if (ok) {
|
||||||
|
emit iniChanged(conf()->ini());
|
||||||
|
emit confChanged(/*onlyFlags=*/false);
|
||||||
|
} else {
|
||||||
qCWarning(LC) << "Import error:" << path;
|
qCWarning(LC) << "Import error:" << path;
|
||||||
}
|
}
|
||||||
|
|
||||||
IoC<FortManager>()->processRestartRequired("Backup Imported");
|
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user