fix wrong stuff when doing backup of DB - was not working because of WAL journalling mode
This commit is contained in:
parent
96920ab723
commit
2deb6446eb
@ -5,12 +5,6 @@
|
||||
#include "exceptions/applicationexception.h"
|
||||
#include "miscellaneous/application.h"
|
||||
|
||||
#if defined(SYSTEM_SQLITE3)
|
||||
#include <sqlite3.h>
|
||||
#else
|
||||
#include "3rd-party/sqlite/sqlite3.h"
|
||||
#endif
|
||||
|
||||
#include <QDir>
|
||||
#include <QSqlDriver>
|
||||
#include <QSqlError>
|
||||
@ -44,25 +38,25 @@ QString SqliteDriver::ddlFilePrefix() const {
|
||||
return QSL("sqlite");
|
||||
}
|
||||
|
||||
int loadOrSaveDb(sqlite3* pInMemory, const char* zFilename, int isSave) {
|
||||
int rc; /* Function return code */
|
||||
sqlite3* pFile; /* Database connection opened on zFilename */
|
||||
sqlite3_backup* pBackup; /* Backup object used to copy data */
|
||||
sqlite3* pTo; /* Database to copy to (pFile or pInMemory) */
|
||||
sqlite3* pFrom; /* Database to copy from (pFile or pInMemory) */
|
||||
int SqliteDriver::loadOrSaveDbInMemoryDb(sqlite3* in_memory_db, const char* db_filename, bool save) {
|
||||
int rc; /* Function return code */
|
||||
sqlite3* p_file; /* Database connection opened on zFilename */
|
||||
sqlite3_backup* p_backup; /* Backup object used to copy data */
|
||||
sqlite3* p_to; /* Database to copy to (pFile or pInMemory) */
|
||||
sqlite3* p_from; /* Database to copy from (pFile or pInMemory) */
|
||||
|
||||
/* Open the database file identified by zFilename. Exit early if this fails
|
||||
** for any reason. */
|
||||
rc = sqlite3_open(zFilename, &pFile);
|
||||
if (rc == SQLITE_OK) {
|
||||
rc = sqlite3_open(db_filename, &p_file);
|
||||
|
||||
if (rc == SQLITE_OK) {
|
||||
/* If this is a 'load' operation (isSave==0), then data is copied
|
||||
** from the database file just opened to database pInMemory.
|
||||
** Otherwise, if this is a 'save' operation (isSave==1), then data
|
||||
** is copied from pInMemory to pFile. Set the variables pFrom and
|
||||
** pTo accordingly. */
|
||||
pFrom = (isSave ? pInMemory : pFile);
|
||||
pTo = (isSave ? pFile : pInMemory);
|
||||
p_from = (save ? in_memory_db : p_file);
|
||||
p_to = (save ? p_file : in_memory_db);
|
||||
|
||||
/* Set up the backup procedure to copy from the "main" database of
|
||||
** connection pFile to the main database of connection pInMemory.
|
||||
@ -76,19 +70,19 @@ int loadOrSaveDb(sqlite3* pInMemory, const char* zFilename, int isSave) {
|
||||
** connection pTo. If no error occurred, then the error code belonging
|
||||
** to pTo is set to SQLITE_OK.
|
||||
*/
|
||||
pBackup = sqlite3_backup_init(pTo, "main", pFrom, "main");
|
||||
if (pBackup) {
|
||||
(void)sqlite3_backup_step(pBackup, -1);
|
||||
(void)sqlite3_backup_finish(pBackup);
|
||||
p_backup = sqlite3_backup_init(p_to, "main", p_from, "main");
|
||||
if (p_backup) {
|
||||
(void)sqlite3_backup_step(p_backup, -1);
|
||||
(void)sqlite3_backup_finish(p_backup);
|
||||
}
|
||||
rc = sqlite3_errcode(pTo);
|
||||
rc = sqlite3_errcode(p_to);
|
||||
}
|
||||
|
||||
sqlite3_db_cacheflush(pFile);
|
||||
sqlite3_db_cacheflush(p_file);
|
||||
|
||||
/* Close the database connection opened on database file zFilename
|
||||
** and return the result of this function. */
|
||||
(void)sqlite3_close(pFile);
|
||||
(void)sqlite3_close(p_file);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -96,69 +90,28 @@ bool SqliteDriver::saveDatabase() {
|
||||
if (!m_inMemoryDatabase) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
qDebugNN << LOGSEC_DB << "Saving in-memory working database back to persistent file-based storage.";
|
||||
|
||||
qDebugNN << LOGSEC_DB << "Saving in-memory working database back to persistent file-based storage.";
|
||||
QSqlDatabase database = connection(QSL("SaveFromMemory"), DatabaseDriver::DesiredStorageType::StrictlyInMemory);
|
||||
const QDir db_path(m_databaseFilePath);
|
||||
QFile db_file(db_path.absoluteFilePath(QSL(APP_DB_SQLITE_FILE)));
|
||||
QVariant v = database.driver()->handle();
|
||||
|
||||
QSqlDatabase database = connection(QSL("SaveFromMemory"), DatabaseDriver::DesiredStorageType::StrictlyInMemory);
|
||||
const QDir db_path(m_databaseFilePath);
|
||||
QFile db_file(db_path.absoluteFilePath(QSL(APP_DB_SQLITE_FILE)));
|
||||
QVariant v = database.driver()->handle();
|
||||
if (v.isValid() && (qstrcmp(v.typeName(), "sqlite3*") == 0)) {
|
||||
// v.data() returns a pointer to the handle
|
||||
sqlite3* handle = *static_cast<sqlite3**>(v.data());
|
||||
|
||||
if (v.isValid() && (qstrcmp(v.typeName(), "sqlite3*") == 0)) {
|
||||
// v.data() returns a pointer to the handle
|
||||
sqlite3* handle = *static_cast<sqlite3**>(v.data());
|
||||
if (handle) {
|
||||
loadOrSaveDb(handle, QDir::toNativeSeparators(db_file.fileName()).toStdString().c_str(), 1);
|
||||
if (handle != nullptr) {
|
||||
loadOrSaveDbInMemoryDb(handle, QDir::toNativeSeparators(db_file.fileName()).toStdString().c_str(), 1);
|
||||
}
|
||||
else {
|
||||
throw ApplicationException(tr("cannot get native 'sqlite3' DB handle"));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
/*
|
||||
QSqlQuery copy_contents(database);
|
||||
|
||||
// Attach database.
|
||||
copy_contents.exec(QString(QSL("ATTACH DATABASE '%1' AS 'storage';")).arg(file_database.databaseName()));
|
||||
|
||||
// Copy all stuff.
|
||||
QStringList tables;
|
||||
|
||||
if (copy_contents.exec(QSL("SELECT name FROM storage.sqlite_master WHERE type='table';"))) {
|
||||
while (copy_contents.next()) {
|
||||
tables.append(copy_contents.value(0).toString());
|
||||
}
|
||||
}
|
||||
else {
|
||||
qFatal("Cannot obtain list of table names from file-base SQLite database.");
|
||||
}
|
||||
|
||||
for (const QString& table : tables) {
|
||||
if (copy_contents.exec(QString(QSL("DELETE FROM storage.%1;")).arg(table))) {
|
||||
qDebugNN << LOGSEC_DB << "Cleaning old data from 'storage." << table << "'.";
|
||||
}
|
||||
else {
|
||||
qCriticalNN << LOGSEC_DB << "Failed to clean old data from 'storage." << table << "', error: '"
|
||||
<< copy_contents.lastError().text() << "'.";
|
||||
}
|
||||
|
||||
if (copy_contents.exec(QString(QSL("INSERT INTO storage.%1 SELECT * FROM main.%1;")).arg(table))) {
|
||||
qDebugNN << LOGSEC_DB << "Copying new data from 'main." << table << "'.";
|
||||
}
|
||||
else {
|
||||
qCriticalNN << LOGSEC_DB << "Failed to copy new data from 'main." << table << "', error: '"
|
||||
<< copy_contents.lastError().text() << "'.";
|
||||
}
|
||||
}
|
||||
|
||||
// Detach database and finish.
|
||||
if (copy_contents.exec(QSL("DETACH 'storage'"))) {
|
||||
qDebugNN << LOGSEC_DB << "Detaching persistent SQLite file.";
|
||||
}
|
||||
else {
|
||||
qCriticalNN << LOGSEC_DB << "Failed to detach SQLite file, error: '" << copy_contents.lastError().text() << "'.";
|
||||
}
|
||||
|
||||
copy_contents.finish();
|
||||
return true;*/
|
||||
}
|
||||
|
||||
QSqlDatabase SqliteDriver::connection(const QString& connection_name, DesiredStorageType desired_type) {
|
||||
@ -394,13 +347,13 @@ QString SqliteDriver::databaseFilePath() const {
|
||||
|
||||
void SqliteDriver::setPragmas(QSqlQuery& query) {
|
||||
query.exec(QSL("PRAGMA encoding = \"UTF-8\""));
|
||||
query.exec(QSL("PRAGMA synchronous = OFF"));
|
||||
// query.exec(QSL("PRAGMA journal_mode = MEMORY"));
|
||||
query.exec(QSL("PRAGMA page_size = 4096"));
|
||||
query.exec(QSL("PRAGMA cache_size = 16384"));
|
||||
query.exec(QSL("PRAGMA page_size = 32768"));
|
||||
query.exec(QSL("PRAGMA cache_size = 32768"));
|
||||
query.exec(QSL("PRAGMA mmap_size = 100000000"));
|
||||
query.exec(QSL("PRAGMA count_changes = OFF"));
|
||||
query.exec(QSL("PRAGMA temp_store = MEMORY"));
|
||||
query.exec(QSL("PRAGMA journal_mode = WAL"));
|
||||
query.exec(QSL("PRAGMA synchronous = OFF"));
|
||||
query.exec(QSL("PRAGMA journal_mode = MEMORY"));
|
||||
}
|
||||
|
||||
qint64 SqliteDriver::databaseDataSize() {
|
||||
@ -436,6 +389,8 @@ QString SqliteDriver::qtDriverCode() const {
|
||||
}
|
||||
|
||||
void SqliteDriver::backupDatabase(const QString& backup_folder, const QString& backup_name) {
|
||||
qDebugNN << LOGSEC_DB << "Creating SQLite DB backup.";
|
||||
|
||||
saveDatabase();
|
||||
|
||||
if (!IOFactory::copyFile(databaseFilePath(),
|
||||
|
@ -5,8 +5,14 @@
|
||||
|
||||
#include "database/databasedriver.h"
|
||||
|
||||
#if defined(SYSTEM_SQLITE3)
|
||||
#include <sqlite3.h>
|
||||
#else
|
||||
#include "3rd-party/sqlite/sqlite3.h"
|
||||
#endif
|
||||
|
||||
class SqliteDriver : public DatabaseDriver {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SqliteDriver(bool in_memory, QObject* parent = nullptr);
|
||||
@ -19,7 +25,8 @@ class SqliteDriver : public DatabaseDriver {
|
||||
virtual bool initiateRestoration(const QString& database_package_file);
|
||||
virtual bool finishRestoration();
|
||||
virtual QSqlDatabase connection(const QString& connection_name,
|
||||
DatabaseDriver::DesiredStorageType desired_type = DatabaseDriver::DesiredStorageType::FromSettings);
|
||||
DatabaseDriver::DesiredStorageType desired_type =
|
||||
DatabaseDriver::DesiredStorageType::FromSettings);
|
||||
virtual qint64 databaseDataSize();
|
||||
virtual QString humanDriverType() const;
|
||||
virtual QString qtDriverCode() const;
|
||||
@ -32,6 +39,9 @@ class SqliteDriver : public DatabaseDriver {
|
||||
void setPragmas(QSqlQuery& query);
|
||||
QString databaseFilePath() const;
|
||||
|
||||
// Uses native "sqlite3" handle to save or load in-memory DB from/to file.
|
||||
int loadOrSaveDbInMemoryDb(sqlite3* in_memory_db, const char* db_filename, bool save);
|
||||
|
||||
private:
|
||||
bool m_inMemoryDatabase;
|
||||
QString m_databaseFilePath;
|
||||
|
@ -790,7 +790,13 @@ void Application::onAboutToQuit() {
|
||||
}
|
||||
|
||||
qApp->feedReader()->quit();
|
||||
database()->driver()->saveDatabase();
|
||||
|
||||
try {
|
||||
database()->driver()->saveDatabase();
|
||||
}
|
||||
catch (const ApplicationException& ex) {
|
||||
qCriticalNN << LOGSEC_DB << "Error when saving DB:" << QUOTE_W_SPACE_DOT(ex.message());
|
||||
}
|
||||
|
||||
if (mainForm() != nullptr) {
|
||||
mainForm()->saveSize();
|
||||
|
Loading…
x
Reference in New Issue
Block a user