Sqlite: Add exception if statement is called outside of a lock

Sometimes it is really hard to trace if sqlite statement is called
outside of a database connection lock. So we know throw an exception
in the unit test. So we get failing tests.

Change-Id: I71485b9473075751a2fb771ce7e2954e28d8413e
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Marco Bubke
2021-04-29 18:02:31 +02:00
parent 943c31a5b4
commit 5fda083436
14 changed files with 179 additions and 172 deletions

View File

@@ -195,23 +195,6 @@ public:
resetter.reset();
}
template<typename ResultType>
std::vector<ResultType> values(std::size_t reserveSize)
{
Resetter resetter{this};
std::vector<ResultType> resultValues;
resultValues.reserve(std::max(reserveSize, m_maximumResultCount));
while (BaseStatement::next())
emplaceBackValues(resultValues);
setMaximumResultCount(resultValues.size());
resetter.reset();
return resultValues;
}
template<typename ResultType, typename... QueryTypes>
auto values(std::size_t reserveSize, const QueryTypes &...queryValues)
{
@@ -438,7 +421,10 @@ private:
{
Resetter(StatementImplementation *statement)
: statement(statement)
{}
{
if (statement && !statement->database().isLocked())
throw DatabaseIsNotLocked{"Database connection is not locked!"};
}
Resetter(Resetter &) = delete;
Resetter &operator=(Resetter &) = delete;

View File

@@ -70,6 +70,8 @@ Database::Database(Utils::PathString &&databaseFilePath,
: m_databaseBackend(*this)
, m_busyTimeout(busyTimeout)
{
std::lock_guard lock{*this};
setJournalMode(journalMode);
open(std::move(databaseFilePath));
@@ -94,7 +96,6 @@ void Database::open()
else
m_databaseBackend.registerBusyHandler();
registerTransactionStatements();
initializeTables();
m_isOpen = true;
}
@@ -127,18 +128,6 @@ bool Database::isOpen() const
return m_isOpen;
}
Table &Database::addTable()
{
m_sqliteTables.emplace_back();
return m_sqliteTables.back();
}
const std::vector<Table> &Database::tables() const
{
return m_sqliteTables;
}
void Database::setDatabaseFilePath(Utils::PathString &&databaseFilePath)
{
m_databaseFilePath = std::move(databaseFilePath);
@@ -189,20 +178,6 @@ void Database::execute(Utils::SmallStringView sqlStatement)
m_databaseBackend.execute(sqlStatement);
}
void Database::initializeTables()
{
try {
ExclusiveTransaction transaction(*this);
for (Table &table : m_sqliteTables)
table.initialize(*this);
transaction.commit();
} catch (const StatementIsBusy &) {
initializeTables();
}
}
void Database::registerTransactionStatements()
{
m_statements = std::make_unique<Statements>(*this);
@@ -257,9 +232,16 @@ void Database::sessionRollback()
void Database::lock()
{
m_databaseMutex.lock();
#ifdef UNIT_TESTS
m_isLocked = true;
#endif
}
void Database::unlock()
{
#ifdef UNIT_TESTS
m_isLocked = false;
#endif
m_databaseMutex.unlock();
}

View File

@@ -87,9 +87,6 @@ public:
bool isOpen() const;
Table &addTable();
const std::vector<Table> &tables() const;
void setDatabaseFilePath(Utils::PathString &&databaseFilePath);
const Utils::PathString &databaseFilePath() const;
@@ -148,14 +145,23 @@ public:
SessionChangeSets changeSets() const;
bool isLocked() const
{
#ifdef UNIT_TESTS
return m_isLocked;
#else
return true;
#endif
}
void lock() override;
void unlock() override;
private:
void deferredBegin() override;
void immediateBegin() override;
void exclusiveBegin() override;
void commit() override;
void rollback() override;
void lock() override;
void unlock() override;
void immediateSessionBegin() override;
void sessionCommit() override;
void sessionRollback() override;
@@ -170,7 +176,6 @@ private:
private:
Utils::PathString m_databaseFilePath;
DatabaseBackend m_databaseBackend;
std::vector<Table> m_sqliteTables;
std::mutex m_databaseMutex;
std::unique_ptr<Statements> m_statements;
std::chrono::milliseconds m_busyTimeout;
@@ -178,6 +183,7 @@ private:
OpenMode m_openMode = OpenMode::ReadWrite;
bool m_isOpen = false;
bool m_isInitialized = false;
bool m_isLocked = false;
};
} // namespace Sqlite

View File

@@ -26,6 +26,7 @@
#include "sqlitedatabasebackend.h"
#include "sqlitebasestatement.h"
#include "sqlitedatabase.h"
#include "sqliteexception.h"
#include "sqlitereadstatement.h"
#include "sqlitereadwritestatement.h"

View File

@@ -410,4 +410,12 @@ public:
{}
};
class DatabaseIsNotLocked : public Exception
{
public:
DatabaseIsNotLocked(const char *whatErrorHasHappen)
: Exception(whatErrorHasHappen)
{}
};
} // namespace Sqlite