summaryrefslogtreecommitdiff
path: root/src/libs/sqlite/sqlitedatabasebackend.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/sqlite/sqlitedatabasebackend.cpp')
-rw-r--r--src/libs/sqlite/sqlitedatabasebackend.cpp180
1 files changed, 97 insertions, 83 deletions
diff --git a/src/libs/sqlite/sqlitedatabasebackend.cpp b/src/libs/sqlite/sqlitedatabasebackend.cpp
index 07c2da46fe..0fd18dfaa1 100644
--- a/src/libs/sqlite/sqlitedatabasebackend.cpp
+++ b/src/libs/sqlite/sqlitedatabasebackend.cpp
@@ -84,19 +84,22 @@ void DatabaseBackend::checkpointFullWalLog()
checkIfLogCouldBeCheckpointed(resultCode);
}
-void DatabaseBackend::open(Utils::SmallStringView databaseFilePath, OpenMode mode)
+void DatabaseBackend::open(Utils::SmallStringView databaseFilePath,
+ OpenMode openMode,
+ JournalMode journalMode)
{
checkCanOpenDatabase(databaseFilePath);
+ sqlite3 *handle = m_databaseHandle.get();
int resultCode = sqlite3_open_v2(std::string(databaseFilePath).c_str(),
- &m_databaseHandle,
- openMode(mode),
+ &handle,
+ createOpenFlags(openMode, journalMode),
nullptr);
+ m_databaseHandle.reset(handle);
checkDatabaseCouldBeOpened(resultCode);
- sqlite3_extended_result_codes(m_databaseHandle, true);
- resultCode = sqlite3_carray_init(m_databaseHandle, nullptr, nullptr);
+ resultCode = sqlite3_carray_init(m_databaseHandle.get(), nullptr, nullptr);
checkCarrayCannotBeIntialized(resultCode);
}
@@ -104,7 +107,7 @@ void DatabaseBackend::open(Utils::SmallStringView databaseFilePath, OpenMode mod
sqlite3 *DatabaseBackend::sqliteDatabaseHandle() const
{
checkDatabaseHandleIsNotNull();
- return m_databaseHandle;
+ return m_databaseHandle.get();
}
void DatabaseBackend::setPragmaValue(Utils::SmallStringView pragmaKey, Utils::SmallStringView newPragmaValue)
@@ -168,6 +171,19 @@ LockingMode DatabaseBackend::lockingMode() const
return pragmaToLockingMode(pragmaValue("main.locking_mode"));
}
+int DatabaseBackend::version() const
+{
+ return toValue<int>("PRAGMA main.user_version");
+}
+
+void DatabaseBackend::setVersion(int version)
+{
+ ReadWriteStatement<>{Utils::SmallString{"PRAGMA main.user_version = "}
+ + Utils::SmallString::number(version),
+ m_database}
+ .execute();
+}
+
int DatabaseBackend::changesCount() const
{
return sqlite3_changes(sqliteDatabaseHandle());
@@ -202,12 +218,11 @@ void DatabaseBackend::close()
{
checkForOpenDatabaseWhichCanBeClosed();
- int resultCode = sqlite3_close(m_databaseHandle);
+ int resultCode = sqlite3_close(m_databaseHandle.get());
checkDatabaseClosing(resultCode);
- m_databaseHandle = nullptr;
-
+ m_databaseHandle.release();
}
bool DatabaseBackend::databaseIsOpen() const
@@ -217,12 +232,7 @@ bool DatabaseBackend::databaseIsOpen() const
void DatabaseBackend::closeWithoutException()
{
- if (m_databaseHandle) {
- int resultCode = sqlite3_close_v2(m_databaseHandle);
- m_databaseHandle = nullptr;
- if (resultCode != SQLITE_OK)
- qWarning() << "SqliteDatabaseBackend::closeWithoutException: Unexpected error at closing the database!";
- }
+ m_databaseHandle.reset();
}
namespace {
@@ -246,15 +256,17 @@ void DatabaseBackend::registerBusyHandler()
void DatabaseBackend::checkForOpenDatabaseWhichCanBeClosed()
{
if (m_databaseHandle == nullptr)
- throw DatabaseIsAlreadyClosed("SqliteDatabaseBackend::close: database is not open so it cannot be closed.");
+ throw DatabaseIsAlreadyClosed();
}
void DatabaseBackend::checkDatabaseClosing(int resultCode)
{
switch (resultCode) {
case SQLITE_OK: return;
- case SQLITE_BUSY: throw DatabaseIsBusy("SqliteDatabaseBackend::close: database is busy because of e.g. unfinalized statements and will stay open!");
- default: throwUnknowError("SqliteDatabaseBackend::close: unknown error happens at closing!");
+ case SQLITE_BUSY:
+ throw DatabaseIsBusy();
+ default:
+ throw UnknowError("SqliteDatabaseBackend::close: unknown error happens at closing!");
}
}
@@ -264,8 +276,7 @@ void DatabaseBackend::checkCanOpenDatabase(Utils::SmallStringView databaseFilePa
throw DatabaseFilePathIsEmpty("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened because the file path is empty!");
if (!QFileInfo::exists(QFileInfo(QString(databaseFilePath)).path()))
- throw WrongFilePath("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened because of wrong file path!",
- Utils::SmallString(databaseFilePath));
+ throw WrongFilePath(Utils::SmallString(databaseFilePath));
if (databaseIsOpen())
throw DatabaseIsAlreadyOpen("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened because it is already open!");
@@ -273,81 +284,75 @@ void DatabaseBackend::checkCanOpenDatabase(Utils::SmallStringView databaseFilePa
void DatabaseBackend::checkDatabaseCouldBeOpened(int resultCode)
{
- switch (resultCode) {
- case SQLITE_OK:
- return;
- default:
+ if (resultCode != SQLITE_OK) {
+ try {
+ Sqlite::throwError(resultCode, sqliteDatabaseHandle());
+ } catch (...) {
closeWithoutException();
- throw UnknowError(
- "SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened:",
- sqlite3_errmsg(sqliteDatabaseHandle()));
+ throw;
}
+ }
}
void DatabaseBackend::checkCarrayCannotBeIntialized(int resultCode)
{
if (resultCode != SQLITE_OK)
- throwDatabaseIsNotOpen(
- "SqliteDatabaseBackend: database cannot be opened because carray failed!");
+ throw DatabaseIsNotOpen();
}
void DatabaseBackend::checkPragmaValue(Utils::SmallStringView databaseValue,
Utils::SmallStringView expectedValue)
{
if (databaseValue != expectedValue)
- throw PragmaValueNotSet("SqliteDatabaseBackend::setPragmaValue: pragma value is not set!");
+ throw PragmaValueNotSet();
}
void DatabaseBackend::checkDatabaseHandleIsNotNull() const
{
if (m_databaseHandle == nullptr)
- throwDatabaseIsNotOpen("SqliteDatabaseBackend: database is not open!");
+ throw DatabaseIsNotOpen();
}
void DatabaseBackend::checkIfMultithreadingIsActivated(int resultCode)
{
if (resultCode != SQLITE_OK)
- throwExceptionStatic(
- "SqliteDatabaseBackend::activateMultiThreading: multithreading can't be activated!");
+ throw MultiTheadingCannotBeActivated{};
}
void DatabaseBackend::checkIfLoogingIsActivated(int resultCode)
{
if (resultCode != SQLITE_OK)
- throwExceptionStatic("SqliteDatabaseBackend::activateLogging: logging can't be activated!");
+ throw LoggingCannotBeActivated{};
}
void DatabaseBackend::checkMmapSizeIsSet(int resultCode)
{
if (resultCode != SQLITE_OK)
- throwExceptionStatic(
- "SqliteDatabaseBackend::checkMmapSizeIsSet: mmap size can't be changed!");
+ throw MemoryMappingCannotBeChanged{};
}
void DatabaseBackend::checkInitializeSqliteLibraryWasSuccesful(int resultCode)
{
if (resultCode != SQLITE_OK)
- throwExceptionStatic(
- "SqliteDatabaseBackend::initializeSqliteLibrary: SqliteLibrary cannot initialized!");
+ throw LibraryCannotBeInitialized{};
}
void DatabaseBackend::checkShutdownSqliteLibraryWasSuccesful(int resultCode)
{
if (resultCode != SQLITE_OK)
- throwExceptionStatic(
- "SqliteDatabaseBackend::shutdownSqliteLibrary: SqliteLibrary cannot be shutdowned!");
+ throw LibraryCannotBeShutdown{};
}
void DatabaseBackend::checkIfLogCouldBeCheckpointed(int resultCode)
{
if (resultCode != SQLITE_OK)
- throwException("SqliteDatabaseBackend::checkpointFullWalLog: WAL log could not be checkpointed!");
+ throw LogCannotBeCheckpointed{};
}
void DatabaseBackend::checkIfBusyTimeoutWasSet(int resultCode)
{
if (resultCode != SQLITE_OK)
- throwException("SqliteDatabaseBackend::setBusyTimeout: Busy timeout cannot be set!");
+ throw BusyTimerCannotBeSet{};
}
namespace {
@@ -379,65 +384,57 @@ JournalMode DatabaseBackend::pragmaToJournalMode(Utils::SmallStringView pragma)
int index = indexOfPragma(pragma, journalModeStrings);
if (index < 0)
- throwExceptionStatic("SqliteDatabaseBackend::pragmaToJournalMode: pragma can't be transformed in a journal mode enumeration!");
+ throw PragmaValueCannotBeTransformed{};
return static_cast<JournalMode>(index);
}
-int DatabaseBackend::openMode(OpenMode mode)
+int DatabaseBackend::createOpenFlags(OpenMode openMode, JournalMode journalMode)
{
- int sqliteMode = SQLITE_OPEN_CREATE;
+ int sqliteOpenFlags = SQLITE_OPEN_CREATE | SQLITE_OPEN_EXRESCODE;
+
+ if (journalMode == JournalMode::Memory)
+ sqliteOpenFlags |= SQLITE_OPEN_MEMORY;
- switch (mode) {
- case OpenMode::ReadOnly: sqliteMode |= SQLITE_OPEN_READONLY; break;
- case OpenMode::ReadWrite: sqliteMode |= SQLITE_OPEN_READWRITE; break;
+ switch (openMode) {
+ case OpenMode::ReadOnly:
+ sqliteOpenFlags |= SQLITE_OPEN_READONLY;
+ break;
+ case OpenMode::ReadWrite:
+ sqliteOpenFlags |= SQLITE_OPEN_READWRITE;
+ break;
}
- return sqliteMode;
+ return sqliteOpenFlags;
}
void DatabaseBackend::setBusyTimeout(std::chrono::milliseconds timeout)
{
- sqlite3_busy_timeout(m_databaseHandle, int(timeout.count()));
+ sqlite3_busy_timeout(m_databaseHandle.get(), int(timeout.count()));
}
void DatabaseBackend::walCheckpointFull()
{
- int resultCode = sqlite3_wal_checkpoint_v2(m_databaseHandle,
+ int resultCode = sqlite3_wal_checkpoint_v2(m_databaseHandle.get(),
nullptr,
SQLITE_CHECKPOINT_TRUNCATE,
nullptr,
nullptr);
- switch (resultCode) {
- case SQLITE_OK:
- break;
- case SQLITE_BUSY_RECOVERY:
- case SQLITE_BUSY_SNAPSHOT:
- case SQLITE_BUSY_TIMEOUT:
- case SQLITE_BUSY:
- throw DatabaseIsBusy("DatabaseBackend::walCheckpointFull: Operation could not concluded "
- "because database is busy!");
- case SQLITE_ERROR_MISSING_COLLSEQ:
- case SQLITE_ERROR_RETRY:
- case SQLITE_ERROR_SNAPSHOT:
- case SQLITE_ERROR:
- throwException("DatabaseBackend::walCheckpointFull: Error occurred!");
- case SQLITE_MISUSE:
- throwExceptionStatic("DatabaseBackend::walCheckpointFull: Misuse of database!");
- }
+ if (resultCode != SQLITE_OK)
+ Sqlite::throwError(resultCode, sqliteDatabaseHandle());
}
void DatabaseBackend::setUpdateHook(
void *object,
void (*callback)(void *object, int, char const *database, char const *, long long rowId))
{
- sqlite3_update_hook(m_databaseHandle, callback, object);
+ sqlite3_update_hook(m_databaseHandle.get(), callback, object);
}
void DatabaseBackend::resetUpdateHook()
{
- sqlite3_update_hook(m_databaseHandle, nullptr, nullptr);
+ sqlite3_update_hook(m_databaseHandle.get(), nullptr, nullptr);
}
void DatabaseBackend::setBusyHandler(DatabaseBackend::BusyHandler &&busyHandler)
@@ -446,27 +443,34 @@ void DatabaseBackend::setBusyHandler(DatabaseBackend::BusyHandler &&busyHandler)
registerBusyHandler();
}
-void DatabaseBackend::throwExceptionStatic(const char *whatHasHappens)
-{
- throw Exception(whatHasHappens);
-}
+namespace {
-void DatabaseBackend::throwException(const char *whatHasHappens) const
+int progressHandlerCallback(void *userData)
{
- if (m_databaseHandle)
- throw ExceptionWithMessage(whatHasHappens, sqlite3_errmsg(m_databaseHandle));
- else
- throw Exception(whatHasHappens);
+ auto &&progressHandler = *static_cast<DatabaseBackend::ProgressHandler *>(userData);
+
+ return progressHandler() == Progress::Interrupt;
}
-void DatabaseBackend::throwUnknowError(const char *whatHasHappens) const
+} // namespace
+
+void DatabaseBackend::setProgressHandler(int operationCount, ProgressHandler &&progressHandler)
{
- throw UnknowError(whatHasHappens);
+ m_progressHandler = std::move(progressHandler);
+
+ if (m_progressHandler)
+ sqlite3_progress_handler(sqliteDatabaseHandle(),
+ operationCount,
+ &progressHandlerCallback,
+ &m_progressHandler);
+ else {
+ sqlite3_progress_handler(sqliteDatabaseHandle(), 0, nullptr, nullptr);
+ }
}
-void DatabaseBackend::throwDatabaseIsNotOpen(const char *whatHasHappens) const
+void DatabaseBackend::resetProgressHandler()
{
- throw DatabaseIsNotOpen(whatHasHappens);
+ sqlite3_progress_handler(sqliteDatabaseHandle(), 0, nullptr, nullptr);
}
template<typename Type>
@@ -483,4 +487,14 @@ Type DatabaseBackend::toValue(Utils::SmallStringView sqlStatement) const
}
}
+void DatabaseBackend::Deleter::operator()(sqlite3 *database)
+{
+ if (database) {
+ int resultCode = sqlite3_close_v2(database);
+ if (resultCode != SQLITE_OK)
+ qWarning() << "SqliteDatabaseBackend::closeWithoutException: Unexpected error at "
+ "closing the database!";
+ }
+}
+
} // namespace Sqlite