QmlDesigner: Use Sqlite source location wrapper

Task-number: QDS-14575
Change-Id: I217d22da3bcf8a611dfa9b521495b5f6b646ef15
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Marco Bubke
2025-01-21 19:27:38 +01:00
parent 6275402528
commit d91bd4cf1c
33 changed files with 1358 additions and 920 deletions

View File

@@ -28,10 +28,12 @@ namespace Sqlite {
using NanotraceHR::keyValue; using NanotraceHR::keyValue;
BaseStatement::BaseStatement(Utils::SmallStringView sqlStatement, Database &database) BaseStatement::BaseStatement(Utils::SmallStringView sqlStatement,
Database &database,
const source_location &sourceLocation)
: m_database(database) : m_database(database)
{ {
prepare(sqlStatement); prepare(sqlStatement, sourceLocation);
} }
class UnlockNotification class UnlockNotification
@@ -67,15 +69,15 @@ private:
std::mutex m_mutex; std::mutex m_mutex;
}; };
void BaseStatement::waitForUnlockNotify() const void BaseStatement::waitForUnlockNotify(const source_location &sourceLocation) const
{ {
UnlockNotification unlockNotification; UnlockNotification unlockNotification;
int resultCode = sqlite3_unlock_notify(sqliteDatabaseHandle(), int resultCode = sqlite3_unlock_notify(sqliteDatabaseHandle(sourceLocation),
UnlockNotification::unlockNotifyCallBack, UnlockNotification::unlockNotifyCallBack,
&unlockNotification); &unlockNotification);
if (resultCode == SQLITE_LOCKED) if (resultCode == SQLITE_LOCKED)
throw DeadLock(); throw DeadLock(sourceLocation);
unlockNotification.wait(); unlockNotification.wait();
} }
@@ -89,7 +91,7 @@ void BaseStatement::reset() const noexcept
sqlite3_reset(m_compiledStatement.get()); sqlite3_reset(m_compiledStatement.get());
} }
bool BaseStatement::next() const bool BaseStatement::next(const source_location &sourceLocation) const
{ {
NanotraceHR::Tracer tracer{"next", NanotraceHR::Tracer tracer{"next",
sqliteLowLevelCategory(), sqliteLowLevelCategory(),
@@ -99,7 +101,7 @@ bool BaseStatement::next() const
do { do {
resultCode = sqlite3_step(m_compiledStatement.get()); resultCode = sqlite3_step(m_compiledStatement.get());
if (resultCode == SQLITE_LOCKED) { if (resultCode == SQLITE_LOCKED) {
waitForUnlockNotify(); waitForUnlockNotify(sourceLocation);
sqlite3_reset(m_compiledStatement.get()); sqlite3_reset(m_compiledStatement.get());
} }
@@ -110,15 +112,15 @@ bool BaseStatement::next() const
else if (resultCode == SQLITE_DONE) else if (resultCode == SQLITE_DONE)
return false; return false;
Sqlite::throwError(resultCode, sqliteDatabaseHandle()); Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
} }
void BaseStatement::step() const void BaseStatement::step(const source_location &sourceLocation) const
{ {
next(); next(sourceLocation);
} }
void BaseStatement::bindNull(int index) void BaseStatement::bindNull(int index, const source_location &sourceLocation)
{ {
NanotraceHR::Tracer tracer{"bind null", NanotraceHR::Tracer tracer{"bind null",
sqliteLowLevelCategory(), sqliteLowLevelCategory(),
@@ -127,15 +129,15 @@ void BaseStatement::bindNull(int index)
int resultCode = sqlite3_bind_null(m_compiledStatement.get(), index); int resultCode = sqlite3_bind_null(m_compiledStatement.get(), index);
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
Sqlite::throwError(resultCode, sqliteDatabaseHandle()); Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
} }
void BaseStatement::bind(int index, NullValue) void BaseStatement::bind(int index, NullValue, const source_location &sourceLocation)
{ {
bindNull(index); bindNull(index, sourceLocation);
} }
void BaseStatement::bind(int index, int value) void BaseStatement::bind(int index, int value, const source_location &sourceLocation)
{ {
NanotraceHR::Tracer tracer{"bind int", NanotraceHR::Tracer tracer{"bind int",
sqliteLowLevelCategory(), sqliteLowLevelCategory(),
@@ -145,10 +147,10 @@ void BaseStatement::bind(int index, int value)
int resultCode = sqlite3_bind_int(m_compiledStatement.get(), index, value); int resultCode = sqlite3_bind_int(m_compiledStatement.get(), index, value);
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
Sqlite::throwError(resultCode, sqliteDatabaseHandle()); Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
} }
void BaseStatement::bind(int index, long long value) void BaseStatement::bind(int index, long long value, const source_location &sourceLocation)
{ {
NanotraceHR::Tracer tracer{"bind long long", NanotraceHR::Tracer tracer{"bind long long",
sqliteLowLevelCategory(), sqliteLowLevelCategory(),
@@ -158,10 +160,10 @@ void BaseStatement::bind(int index, long long value)
int resultCode = sqlite3_bind_int64(m_compiledStatement.get(), index, value); int resultCode = sqlite3_bind_int64(m_compiledStatement.get(), index, value);
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
Sqlite::throwError(resultCode, sqliteDatabaseHandle()); Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
} }
void BaseStatement::bind(int index, double value) void BaseStatement::bind(int index, double value, const source_location &sourceLocation)
{ {
NanotraceHR::Tracer tracer{"bind double", NanotraceHR::Tracer tracer{"bind double",
sqliteLowLevelCategory(), sqliteLowLevelCategory(),
@@ -171,10 +173,10 @@ void BaseStatement::bind(int index, double value)
int resultCode = sqlite3_bind_double(m_compiledStatement.get(), index, value); int resultCode = sqlite3_bind_double(m_compiledStatement.get(), index, value);
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
Sqlite::throwError(resultCode, sqliteDatabaseHandle()); Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
} }
void BaseStatement::bind(int index, void *pointer) void BaseStatement::bind(int index, void *pointer, const source_location &sourceLocation)
{ {
NanotraceHR::Tracer tracer{"bind pointer", NanotraceHR::Tracer tracer{"bind pointer",
sqliteLowLevelCategory(), sqliteLowLevelCategory(),
@@ -184,10 +186,10 @@ void BaseStatement::bind(int index, void *pointer)
int resultCode = sqlite3_bind_pointer(m_compiledStatement.get(), index, pointer, "carray", nullptr); int resultCode = sqlite3_bind_pointer(m_compiledStatement.get(), index, pointer, "carray", nullptr);
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
Sqlite::throwError(resultCode, sqliteDatabaseHandle()); Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
} }
void BaseStatement::bind(int index, Utils::span<const int> values) void BaseStatement::bind(int index, Utils::span<const int> values, const source_location &sourceLocation)
{ {
NanotraceHR::Tracer tracer{"bind int span", NanotraceHR::Tracer tracer{"bind int span",
sqliteLowLevelCategory(), sqliteLowLevelCategory(),
@@ -203,10 +205,12 @@ void BaseStatement::bind(int index, Utils::span<const int> values)
CARRAY_INT32, CARRAY_INT32,
SQLITE_STATIC); SQLITE_STATIC);
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
Sqlite::throwError(resultCode, sqliteDatabaseHandle()); Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
} }
void BaseStatement::bind(int index, Utils::span<const long long> values) void BaseStatement::bind(int index,
Utils::span<const long long> values,
const source_location &sourceLocation)
{ {
NanotraceHR::Tracer tracer{"bind long long span", NanotraceHR::Tracer tracer{"bind long long span",
sqliteLowLevelCategory(), sqliteLowLevelCategory(),
@@ -222,10 +226,12 @@ void BaseStatement::bind(int index, Utils::span<const long long> values)
CARRAY_INT64, CARRAY_INT64,
SQLITE_STATIC); SQLITE_STATIC);
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
Sqlite::throwError(resultCode, sqliteDatabaseHandle()); Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
} }
void BaseStatement::bind(int index, Utils::span<const double> values) void BaseStatement::bind(int index,
Utils::span<const double> values,
const source_location &sourceLocation)
{ {
NanotraceHR::Tracer tracer{"bind double span", NanotraceHR::Tracer tracer{"bind double span",
sqliteLowLevelCategory(), sqliteLowLevelCategory(),
@@ -241,10 +247,12 @@ void BaseStatement::bind(int index, Utils::span<const double> values)
CARRAY_DOUBLE, CARRAY_DOUBLE,
SQLITE_STATIC); SQLITE_STATIC);
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
Sqlite::throwError(resultCode, sqliteDatabaseHandle()); Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
} }
void BaseStatement::bind(int index, Utils::span<const char *> values) void BaseStatement::bind(int index,
Utils::span<const char *> values,
const source_location &sourceLocation)
{ {
NanotraceHR::Tracer tracer{"bind const char* span", NanotraceHR::Tracer tracer{"bind const char* span",
sqliteLowLevelCategory(), sqliteLowLevelCategory(),
@@ -260,10 +268,10 @@ void BaseStatement::bind(int index, Utils::span<const char *> values)
CARRAY_TEXT, CARRAY_TEXT,
SQLITE_STATIC); SQLITE_STATIC);
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
Sqlite::throwError(resultCode, sqliteDatabaseHandle()); Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
} }
void BaseStatement::bind(int index, Utils::SmallStringView text) void BaseStatement::bind(int index, Utils::SmallStringView text, const source_location &sourceLocation)
{ {
NanotraceHR::Tracer tracer{"bind string", NanotraceHR::Tracer tracer{"bind string",
sqliteLowLevelCategory(), sqliteLowLevelCategory(),
@@ -277,10 +285,10 @@ void BaseStatement::bind(int index, Utils::SmallStringView text)
int(text.size()), int(text.size()),
SQLITE_STATIC); SQLITE_STATIC);
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
Sqlite::throwError(resultCode, sqliteDatabaseHandle()); Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
} }
void BaseStatement::bind(int index, BlobView blobView) void BaseStatement::bind(int index, BlobView blobView, const source_location &sourceLocation)
{ {
NanotraceHR::Tracer tracer{"bind blob", NanotraceHR::Tracer tracer{"bind blob",
sqliteLowLevelCategory(), sqliteLowLevelCategory(),
@@ -302,10 +310,10 @@ void BaseStatement::bind(int index, BlobView blobView)
} }
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
Sqlite::throwError(resultCode, sqliteDatabaseHandle()); Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
} }
void BaseStatement::bind(int index, const Value &value) void BaseStatement::bind(int index, const Value &value, const source_location &sourceLocation)
{ {
NanotraceHR::Tracer tracer{ NanotraceHR::Tracer tracer{
"bind value", "bind value",
@@ -315,24 +323,24 @@ void BaseStatement::bind(int index, const Value &value)
switch (value.type()) { switch (value.type()) {
case ValueType::Integer: case ValueType::Integer:
bind(index, value.toInteger()); bind(index, value.toInteger(), sourceLocation);
break; break;
case ValueType::Float: case ValueType::Float:
bind(index, value.toFloat()); bind(index, value.toFloat(), sourceLocation);
break; break;
case ValueType::String: case ValueType::String:
bind(index, value.toStringView()); bind(index, value.toStringView(), sourceLocation);
break; break;
case ValueType::Blob: case ValueType::Blob:
bind(index, value.toBlobView()); bind(index, value.toBlobView(), sourceLocation);
break; break;
case ValueType::Null: case ValueType::Null:
bind(index, NullValue{}); bind(index, NullValue{}, sourceLocation);
break; break;
} }
} }
void BaseStatement::bind(int index, ValueView value) void BaseStatement::bind(int index, ValueView value, const source_location &sourceLocation)
{ {
NanotraceHR::Tracer tracer{ NanotraceHR::Tracer tracer{
"bind value", "bind value",
@@ -342,37 +350,37 @@ void BaseStatement::bind(int index, ValueView value)
switch (value.type()) { switch (value.type()) {
case ValueType::Integer: case ValueType::Integer:
bind(index, value.toInteger()); bind(index, value.toInteger(), sourceLocation);
break; break;
case ValueType::Float: case ValueType::Float:
bind(index, value.toFloat()); bind(index, value.toFloat(), sourceLocation);
break; break;
case ValueType::String: case ValueType::String:
bind(index, value.toStringView()); bind(index, value.toStringView(), sourceLocation);
break; break;
case ValueType::Blob: case ValueType::Blob:
bind(index, value.toBlobView()); bind(index, value.toBlobView(), sourceLocation);
break; break;
case ValueType::Null: case ValueType::Null:
bind(index, NullValue{}); bind(index, NullValue{}, sourceLocation);
break; break;
} }
} }
void BaseStatement::prepare(Utils::SmallStringView sqlStatement) void BaseStatement::prepare(Utils::SmallStringView sqlStatement, const source_location &sourceLocation)
{ {
NanotraceHR::Tracer tracer{"prepare", NanotraceHR::Tracer tracer{"prepare",
sqliteLowLevelCategory(), sqliteLowLevelCategory(),
keyValue("sql statement", sqlStatement)}; keyValue("sql statement", sqlStatement)};
if (!m_database.isLocked()) if (!m_database.isLocked())
throw DatabaseIsNotLocked{}; throw DatabaseIsNotLocked{sourceLocation};
int resultCode; int resultCode;
do { do {
sqlite3_stmt *sqliteStatement = nullptr; sqlite3_stmt *sqliteStatement = nullptr;
resultCode = sqlite3_prepare_v2(sqliteDatabaseHandle(), resultCode = sqlite3_prepare_v2(sqliteDatabaseHandle(sourceLocation),
sqlStatement.data(), sqlStatement.data(),
int(sqlStatement.size()), int(sqlStatement.size()),
&sqliteStatement, &sqliteStatement,
@@ -381,33 +389,34 @@ void BaseStatement::prepare(Utils::SmallStringView sqlStatement)
if (resultCode == SQLITE_LOCKED) { if (resultCode == SQLITE_LOCKED) {
tracer.tick("wait for unlock"); tracer.tick("wait for unlock");
waitForUnlockNotify(); waitForUnlockNotify(sourceLocation);
} }
} while (resultCode == SQLITE_LOCKED); } while (resultCode == SQLITE_LOCKED);
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
Sqlite::throwError(resultCode, sqliteDatabaseHandle()); Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
tracer.end(keyValue("sqlite statement", handle())); tracer.end(keyValue("sqlite statement", handle()));
} }
sqlite3 *BaseStatement::sqliteDatabaseHandle() const sqlite3 *BaseStatement::sqliteDatabaseHandle(const source_location &sourceLocation) const
{ {
return m_database.backend().sqliteDatabaseHandle(); return m_database.backend().sqliteDatabaseHandle(sourceLocation);
} }
void BaseStatement::checkBindingParameterCount(int bindingParameterCount) const void BaseStatement::checkBindingParameterCount(int bindingParameterCount,
const source_location &sourceLocation) const
{ {
if (bindingParameterCount != sqlite3_bind_parameter_count(m_compiledStatement.get())) if (bindingParameterCount != sqlite3_bind_parameter_count(m_compiledStatement.get()))
throw WrongBindingParameterCount{}; throw WrongBindingParameterCount{sourceLocation};
} }
void BaseStatement::checkColumnCount(int columnCount) const void BaseStatement::checkColumnCount(int columnCount, const source_location &sourceLocation) const
{ {
if (columnCount != sqlite3_column_count(m_compiledStatement.get())) if (columnCount != sqlite3_column_count(m_compiledStatement.get()))
throw WrongColumnCount{}; throw WrongColumnCount{sourceLocation};
} }
bool BaseStatement::isReadOnlyStatement() const bool BaseStatement::isReadOnlyStatement() const

View File

@@ -6,6 +6,7 @@
#include "sqlite3_fwd.h" #include "sqlite3_fwd.h"
#include "sqliteglobal.h" #include "sqliteglobal.h"
#include "sourcelocation.h"
#include "sqliteblob.h" #include "sqliteblob.h"
#include "sqliteexception.h" #include "sqliteexception.h"
#include "sqliteids.h" #include "sqliteids.h"
@@ -41,14 +42,16 @@ class SQLITE_EXPORT BaseStatement
public: public:
using Database = ::Sqlite::Database; using Database = ::Sqlite::Database;
explicit BaseStatement(Utils::SmallStringView sqlStatement, Database &database); explicit BaseStatement(Utils::SmallStringView sqlStatement,
Database &database,
const source_location &sourceLocation);
BaseStatement(const BaseStatement &) = delete; BaseStatement(const BaseStatement &) = delete;
BaseStatement &operator=(const BaseStatement &) = delete; BaseStatement &operator=(const BaseStatement &) = delete;
BaseStatement(BaseStatement &&) = default; BaseStatement(BaseStatement &&) = default;
bool next() const; bool next(const source_location &sourceLocation) const;
void step() const; void step(const source_location &sourceLocation) const;
void reset() const noexcept; void reset() const noexcept;
Type fetchType(int column) const; Type fetchType(int column) const;
@@ -62,52 +65,56 @@ public:
template<typename Type> template<typename Type>
Type fetchValue(int column) const; Type fetchValue(int column) const;
void bindNull(int index); void bindNull(int index, const source_location &sourceLocation);
void bind(int index, NullValue); void bind(int index, NullValue, const source_location &sourceLocation);
void bind(int index, int value); void bind(int index, int value, const source_location &sourceLocation);
void bind(int index, long long value); void bind(int index, long long value, const source_location &sourceLocation);
void bind(int index, double value); void bind(int index, double value, const source_location &sourceLocation);
void bind(int index, void *pointer); void bind(int index, void *pointer, const source_location &sourceLocation);
void bind(int index, Utils::span<const int> values); void bind(int index, Utils::span<const int> values, const source_location &sourceLocation);
void bind(int index, Utils::span<const long long> values); void bind(int index, Utils::span<const long long> values, const source_location &sourceLocation);
void bind(int index, Utils::span<const double> values); void bind(int index, Utils::span<const double> values, const source_location &sourceLocation);
void bind(int index, Utils::span<const char *> values); void bind(int index, Utils::span<const char *> values, const source_location &sourceLocation);
void bind(int index, Utils::SmallStringView value); void bind(int index, Utils::SmallStringView value, const source_location &sourceLocation);
void bind(int index, const Value &value); void bind(int index, const Value &value, const source_location &sourceLocation);
void bind(int index, ValueView value); void bind(int index, ValueView value, const source_location &sourceLocation);
void bind(int index, BlobView blobView); void bind(int index, BlobView blobView, const source_location &sourceLocation);
template<typename Type, typename std::enable_if_t<Type::IsBasicId::value, bool> = true> template<typename Type, typename std::enable_if_t<Type::IsBasicId::value, bool> = true>
void bind(int index, Type id) void bind(int index, Type id, const source_location &sourceLocation)
{ {
if (!id.isNull()) if (!id.isNull())
bind(index, id.internalId()); bind(index, id.internalId(), sourceLocation);
else else
bindNull(index); bindNull(index, sourceLocation);
} }
template<typename Enumeration, std::enable_if_t<std::is_enum_v<Enumeration>, bool> = true> template<typename Enumeration, std::enable_if_t<std::is_enum_v<Enumeration>, bool> = true>
void bind(int index, Enumeration enumeration) void bind(int index, Enumeration enumeration, const source_location &sourceLocation)
{ {
bind(index, Utils::to_underlying(enumeration)); bind(index, Utils::to_underlying(enumeration), sourceLocation);
} }
void bind(int index, uint value) { bind(index, static_cast<long long>(value)); } void bind(int index, uint value, const source_location &sourceLocation)
void bind(int index, long value)
{ {
bind(index, static_cast<long long>(value)); bind(index, static_cast<long long>(value), sourceLocation);
} }
void prepare(Utils::SmallStringView sqlStatement); void bind(int index, long value, const source_location &sourceLocation)
void waitForUnlockNotify() const; {
bind(index, static_cast<long long>(value), sourceLocation);
}
sqlite3 *sqliteDatabaseHandle() const; void prepare(Utils::SmallStringView sqlStatement, const source_location &sourceLocation);
void waitForUnlockNotify(const source_location &sourceLocation) const;
sqlite3 *sqliteDatabaseHandle(const source_location &sourceLocation) const;
void setIfIsReadyToFetchValues(int resultCode) const; void setIfIsReadyToFetchValues(int resultCode) const;
void checkBindingName(int index) const; void checkBindingName(int index) const;
void checkBindingParameterCount(int bindingParameterCount) const; void checkBindingParameterCount(int bindingParameterCount,
void checkColumnCount(int columnCount) const; const source_location &sourceLocation) const;
void checkColumnCount(int columnCount, const source_location &sourceLocation) const;
bool isReadOnlyStatement() const; bool isReadOnlyStatement() const;
QString columnName(int column) const; QString columnName(int column) const;
@@ -150,7 +157,7 @@ public:
using BaseStatement::BaseStatement; using BaseStatement::BaseStatement;
StatementImplementation(StatementImplementation &&) = default; StatementImplementation(StatementImplementation &&) = default;
void execute() void execute(const source_location &sourceLocation = source_location::current())
{ {
using NanotraceHR::keyValue; using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{ NanotraceHR::Tracer tracer{
@@ -160,11 +167,11 @@ public:
}; };
Resetter resetter{this}; Resetter resetter{this};
BaseStatement::next(); BaseStatement::next(sourceLocation);
} }
template<typename... ValueType> template<typename... ValueType>
void bindValues(const ValueType &...values) void bindValues(const source_location &sourceLocation, const ValueType &...values)
{ {
using NanotraceHR::keyValue; using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"bind", NanotraceHR::Tracer tracer{"bind",
@@ -174,11 +181,11 @@ public:
static_assert(BindParameterCount == sizeof...(values), "Wrong binding parameter count!"); static_assert(BindParameterCount == sizeof...(values), "Wrong binding parameter count!");
int index = 0; int index = 0;
(BaseStatement::bind(++index, values), ...); (BaseStatement::bind(++index, values, sourceLocation), ...);
} }
template<typename... ValueType> template<typename... ValueType>
void write(const ValueType&... values) void write(const source_location &sourceLocation, const ValueType &...values)
{ {
using NanotraceHR::keyValue; using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"write", NanotraceHR::Tracer tracer{"write",
@@ -186,8 +193,15 @@ public:
keyValue("sqlite statement", BaseStatement::handle())}; keyValue("sqlite statement", BaseStatement::handle())};
Resetter resetter{this}; Resetter resetter{this};
bindValues(values...); bindValues(sourceLocation, values...);
BaseStatement::next(); BaseStatement::next(sourceLocation);
}
template<typename... ValueType>
void write(const ValueType &...values)
{
static constexpr auto sourceLocation = source_location::current();
write(sourceLocation, values...);
} }
template<typename T> template<typename T>
@@ -213,9 +227,9 @@ public:
template<typename Container, template<typename Container,
std::size_t capacity = 32, std::size_t capacity = 32,
typename = std::enable_if_t<is_container<Container>::value>, typename std::enable_if_t<is_container<Container>::value, bool> = true,
typename... QueryTypes> typename... QueryTypes>
auto values(const QueryTypes &...queryValues) auto values(const source_location &sourceLocation, const QueryTypes &...queryValues)
{ {
using NanotraceHR::keyValue; using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"values", NanotraceHR::Tracer tracer{"values",
@@ -228,9 +242,9 @@ public:
if constexpr (!is_small_container<Container>::value) if constexpr (!is_small_container<Container>::value)
resultValues.reserve(static_cast<size_tupe>(std::max(capacity, m_maximumResultCount))); resultValues.reserve(static_cast<size_tupe>(std::max(capacity, m_maximumResultCount)));
bindValues(queryValues...); bindValues(sourceLocation, queryValues...);
while (BaseStatement::next()) while (BaseStatement::next(sourceLocation))
emplaceBackValues(resultValues); emplaceBackValues(resultValues);
setMaximumResultCount(static_cast<std::size_t>(resultValues.size())); setMaximumResultCount(static_cast<std::size_t>(resultValues.size()));
@@ -238,18 +252,39 @@ public:
return resultValues; return resultValues;
} }
template<typename ResultType, template<typename Container,
std::size_t capacity = 32, std::size_t capacity = 32,
template<typename...> typename Container = std::vector, typename std::enable_if_t<is_container<Container>::value, bool> = true,
typename = std::enable_if_t<!is_container<ResultType>::value>,
typename... QueryTypes> typename... QueryTypes>
auto values(const QueryTypes &...queryValues) auto values(const QueryTypes &...queryValues)
{ {
return values<Container<ResultType>, capacity>(queryValues...); static constexpr auto sourceLocation = source_location::current();
return value<Container, capacity>(sourceLocation, queryValues...);
}
template<typename ResultType,
std::size_t capacity = 32,
template<typename...> typename Container = std::vector,
typename std::enable_if_t<!is_container<ResultType>::value, bool> = true,
typename... QueryTypes>
auto values(const source_location &sourceLocation, const QueryTypes &...queryValues)
{
return values<Container<ResultType>, capacity>(sourceLocation, queryValues...);
}
template<typename ResultType,
std::size_t capacity = 32,
template<typename...> typename Container = std::vector,
typename std::enable_if_t<!is_container<ResultType>::value, bool> = true,
typename... QueryTypes>
auto values(const QueryTypes &...queryValues)
{
static constexpr auto sourceLocation = source_location::current();
return values<ResultType, capacity, Container>(sourceLocation, queryValues...);
} }
template<typename ResultType, typename... QueryTypes> template<typename ResultType, typename... QueryTypes>
auto value(const QueryTypes &...queryValues) auto value(const source_location &sourceLocation, const QueryTypes &...queryValues)
{ {
using NanotraceHR::keyValue; using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"value", NanotraceHR::Tracer tracer{"value",
@@ -259,16 +294,23 @@ public:
Resetter resetter{this}; Resetter resetter{this};
ResultType resultValue{}; ResultType resultValue{};
bindValues(queryValues...); bindValues(sourceLocation, queryValues...);
if (BaseStatement::next()) if (BaseStatement::next(sourceLocation))
resultValue = createValue<ResultType>(); resultValue = createValue<ResultType>();
return resultValue; return resultValue;
} }
template<typename ResultType, typename... QueryTypes> template<typename ResultType, typename... QueryTypes>
auto optionalValue(const QueryTypes &...queryValues) auto value(const QueryTypes &...queryValues)
{
static constexpr auto sourceLocation = source_location::current();
return value<ResultType>(sourceLocation, queryValues...);
}
template<typename ResultType, typename... QueryTypes>
auto optionalValue(const source_location &sourceLocation, const QueryTypes &...queryValues)
{ {
using NanotraceHR::keyValue; using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"optionalValue", NanotraceHR::Tracer tracer{"optionalValue",
@@ -278,31 +320,42 @@ public:
Resetter resetter{this}; Resetter resetter{this};
std::optional<ResultType> resultValue; std::optional<ResultType> resultValue;
bindValues(queryValues...); bindValues(sourceLocation, queryValues...);
if (BaseStatement::next()) if (BaseStatement::next(sourceLocation))
resultValue = createOptionalValue<std::optional<ResultType>>(); resultValue = createOptionalValue<std::optional<ResultType>>();
return resultValue; return resultValue;
} }
template<typename ResultType, typename... QueryTypes>
auto optionalValue(const QueryTypes &...queryValues)
{
static constexpr auto sourceLocation = source_location::current();
return optionalValue<ResultType>(sourceLocation, queryValues...);
}
template<typename Type> template<typename Type>
static auto toValue(Utils::SmallStringView sqlStatement, Database &database) static auto toValue(Utils::SmallStringView sqlStatement,
Database &database,
const source_location &sourceLocation = source_location::current())
{ {
using NanotraceHR::keyValue; using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"toValue", sqliteHighLevelCategory()}; NanotraceHR::Tracer tracer{"toValue", sqliteHighLevelCategory()};
StatementImplementation statement(sqlStatement, database); StatementImplementation statement(sqlStatement, database, sourceLocation);
statement.checkColumnCount(1); statement.checkColumnCount(1, sourceLocation);
statement.next(); statement.next(sourceLocation);
return statement.template fetchValue<Type>(0); return statement.template fetchValue<Type>(0);
} }
template<typename Callable, typename... QueryTypes> template<typename Callable, typename... QueryTypes>
void readCallback(Callable &&callable, const QueryTypes &...queryValues) void readCallback(Callable &&callable,
const source_location &sourceLocation,
const QueryTypes &...queryValues)
{ {
using NanotraceHR::keyValue; using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"readCallback", NanotraceHR::Tracer tracer{"readCallback",
@@ -311,9 +364,9 @@ public:
Resetter resetter{this}; Resetter resetter{this};
bindValues(queryValues...); bindValues(sourceLocation, queryValues...);
while (BaseStatement::next()) { while (BaseStatement::next(sourceLocation)) {
auto control = callCallable(callable); auto control = callCallable(callable);
if (control == CallbackControl::Abort) if (control == CallbackControl::Abort)
@@ -321,8 +374,17 @@ public:
} }
} }
template<typename Callable, typename... QueryTypes>
void readCallback(Callable &&callable, const QueryTypes &...queryValues)
{
static constexpr auto sourceLocation = source_location::current();
readCallback(callable, sourceLocation, queryValues...);
}
template<typename Container, typename... QueryTypes> template<typename Container, typename... QueryTypes>
void readTo(Container &container, const QueryTypes &...queryValues) void readTo(Container &container,
const source_location &sourceLocation,
const QueryTypes &...queryValues)
{ {
using NanotraceHR::keyValue; using NanotraceHR::keyValue;
NanotraceHR::Tracer tracer{"readTo", NanotraceHR::Tracer tracer{"readTo",
@@ -331,22 +393,43 @@ public:
Resetter resetter{this}; Resetter resetter{this};
bindValues(queryValues...); bindValues(sourceLocation, queryValues...);
while (BaseStatement::next()) while (BaseStatement::next(sourceLocation))
emplaceBackValues(container); emplaceBackValues(container);
} }
template<typename Container, typename... QueryTypes>
void readTo(Container &container, const QueryTypes &...queryValues)
{
static constexpr auto sourceLocation = source_location::current();
readTo(container, sourceLocation, queryValues...);
}
template<typename ResultType, typename... QueryTypes>
auto range(const source_location &sourceLocation, const QueryTypes &...queryValues)
{
return SqliteResultRange<ResultType>{*this, sourceLocation, queryValues...};
}
template<typename ResultType, typename... QueryTypes> template<typename ResultType, typename... QueryTypes>
auto range(const QueryTypes &...queryValues) auto range(const QueryTypes &...queryValues)
{ {
return SqliteResultRange<ResultType>{*this, queryValues...}; static constexpr auto sourceLocation = source_location::current();
return SqliteResultRange<ResultType>{*this, sourceLocation, queryValues...};
}
template<typename ResultType, typename... QueryTypes>
auto rangeWithTransaction(const source_location &sourceLocation, const QueryTypes &...queryValues)
{
return SqliteResultRangeWithTransaction<ResultType>{*this, sourceLocation, queryValues...};
} }
template<typename ResultType, typename... QueryTypes> template<typename ResultType, typename... QueryTypes>
auto rangeWithTransaction(const QueryTypes &...queryValues) auto rangeWithTransaction(const QueryTypes &...queryValues)
{ {
return SqliteResultRangeWithTransaction<ResultType>{*this, queryValues...}; static constexpr auto sourceLocation = source_location::current();
return SqliteResultRangeWithTransaction<ResultType>{*this, sourceLocation, queryValues...};
} }
template<typename ResultType> template<typename ResultType>
@@ -362,23 +445,28 @@ public:
using pointer = ResultType *; using pointer = ResultType *;
using reference = ResultType &; using reference = ResultType &;
SqliteResultIteratator(StatementImplementation &statement) SqliteResultIteratator(StatementImplementation &statement,
const source_location &sourceLocation)
: m_statement{statement} : m_statement{statement}
, m_hasNext{m_statement.next()} , m_sourceLocation{sourceLocation}
, m_hasNext{m_statement.next(sourceLocation)}
{} {}
SqliteResultIteratator(StatementImplementation &statement, bool hasNext) SqliteResultIteratator(StatementImplementation &statement,
const source_location &sourceLocation,
bool hasNext)
: m_statement{statement} : m_statement{statement}
, m_sourceLocation{sourceLocation}
, m_hasNext{hasNext} , m_hasNext{hasNext}
{} {}
SqliteResultIteratator &operator++() SqliteResultIteratator &operator++()
{ {
m_hasNext = m_statement.next(); m_hasNext = m_statement.next(m_sourceLocation);
return *this; return *this;
} }
void operator++(int) { m_hasNext = m_statement.next(); } void operator++(int) { m_hasNext = m_statement.next(m_sourceLocation); }
friend bool operator==(const SqliteResultIteratator &first, friend bool operator==(const SqliteResultIteratator &first,
const SqliteResultIteratator &second) const SqliteResultIteratator &second)
@@ -396,6 +484,7 @@ public:
private: private:
StatementImplementation &m_statement; StatementImplementation &m_statement;
const source_location &m_sourceLocation;
bool m_hasNext = false; bool m_hasNext = false;
}; };
@@ -404,8 +493,9 @@ public:
using const_iterator = iterator; using const_iterator = iterator;
template<typename... QueryTypes> template<typename... QueryTypes>
BaseSqliteResultRange(StatementImplementation &statement) BaseSqliteResultRange(StatementImplementation &statement, const source_location &sourceLocation)
: m_statement{statement} : m_statement{statement}
, m_sourceLocation{sourceLocation}
{ {
} }
@@ -413,8 +503,9 @@ public:
BaseSqliteResultRange &operator=(BaseSqliteResultRange &) = delete; BaseSqliteResultRange &operator=(BaseSqliteResultRange &) = delete;
BaseSqliteResultRange &operator=(BaseSqliteResultRange &&) = delete; BaseSqliteResultRange &operator=(BaseSqliteResultRange &&) = delete;
iterator begin() & { return iterator{m_statement}; } iterator begin() & { return iterator{m_statement, m_sourceLocation}; }
iterator end() & { return iterator{m_statement, false}; }
iterator end() & { return iterator{m_statement, m_sourceLocation, false}; }
const_iterator begin() const & { return iterator{m_statement}; } const_iterator begin() const & { return iterator{m_statement}; }
const_iterator end() const & { return iterator{m_statement, false}; } const_iterator end() const & { return iterator{m_statement, false}; }
@@ -422,6 +513,7 @@ public:
private: private:
using TracerCategory = std::decay_t<decltype(sqliteHighLevelCategory())>; using TracerCategory = std::decay_t<decltype(sqliteHighLevelCategory())>;
StatementImplementation &m_statement; StatementImplementation &m_statement;
const source_location &m_sourceLocation;
NanotraceHR::Tracer<TracerCategory, typename TracerCategory::IsActive> tracer{ NanotraceHR::Tracer<TracerCategory, typename TracerCategory::IsActive> tracer{
"range", "range",
sqliteHighLevelCategory(), sqliteHighLevelCategory(),
@@ -433,11 +525,13 @@ public:
{ {
public: public:
template<typename... QueryTypes> template<typename... QueryTypes>
SqliteResultRange(StatementImplementation &statement, const QueryTypes &...queryValues) SqliteResultRange(StatementImplementation &statement,
: BaseSqliteResultRange<ResultType>{statement} const source_location &sourceLocation,
const QueryTypes &...queryValues)
: BaseSqliteResultRange<ResultType>{statement, sourceLocation}
, resetter{&statement} , resetter{&statement}
{ {
statement.bindValues(queryValues...); statement.bindValues(sourceLocation, queryValues...);
} }
private: private:
@@ -450,12 +544,14 @@ public:
public: public:
template<typename... QueryTypes> template<typename... QueryTypes>
SqliteResultRangeWithTransaction(StatementImplementation &statement, SqliteResultRangeWithTransaction(StatementImplementation &statement,
const source_location &sourceLocation,
const QueryTypes &...queryValues) const QueryTypes &...queryValues)
: BaseSqliteResultRange<ResultType>{statement} : BaseSqliteResultRange<ResultType>{statement, sourceLocation}
, m_transaction{statement.database()} , m_transaction{statement.database(), sourceLocation}
, resetter{&statement} , resetter{&statement}
, sourceLocation{sourceLocation}
{ {
statement.bindValues(queryValues...); statement.bindValues(sourceLocation, queryValues...);
} }
~SqliteResultRangeWithTransaction() ~SqliteResultRangeWithTransaction()
@@ -463,13 +559,14 @@ public:
resetter.reset(); resetter.reset();
if (!std::uncaught_exceptions()) { if (!std::uncaught_exceptions()) {
m_transaction.commit(); m_transaction.commit(sourceLocation);
} }
} }
private: private:
DeferredTransaction<typename BaseStatement::Database> m_transaction; DeferredTransaction<typename BaseStatement::Database> m_transaction;
Resetter resetter; Resetter resetter;
source_location sourceLocation;
}; };
protected: protected:

View File

@@ -19,34 +19,40 @@ namespace Sqlite {
class Database::Statements class Database::Statements
{ {
public: public:
Statements(Database &database) Statements(Database &database, const source_location &sourceLocation)
: database(database) : database(database)
, sourceLocation(sourceLocation)
{} {}
public: public:
Database &database; Database &database;
ReadWriteStatement<> deferredBegin{"BEGIN", database}; source_location sourceLocation;
ReadWriteStatement<> immediateBegin{"BEGIN IMMEDIATE", database}; ReadWriteStatement<> deferredBegin{"BEGIN", database, sourceLocation};
ReadWriteStatement<> exclusiveBegin{"BEGIN EXCLUSIVE", database}; ReadWriteStatement<> immediateBegin{"BEGIN IMMEDIATE", database, sourceLocation};
ReadWriteStatement<> commitBegin{"COMMIT", database}; ReadWriteStatement<> exclusiveBegin{"BEGIN EXCLUSIVE", database, sourceLocation};
ReadWriteStatement<> rollbackBegin{"ROLLBACK", database}; ReadWriteStatement<> commitBegin{"COMMIT", database, sourceLocation};
ReadWriteStatement<> rollbackBegin{"ROLLBACK", database, sourceLocation};
Sessions sessions{database, "main", "databaseSessions"}; Sessions sessions{database, "main", "databaseSessions"};
}; };
Database::Database() Database::Database(const source_location &sourceLocation)
: m_databaseBackend(*this) : m_databaseBackend(*this, sourceLocation)
{ {
} }
Database::Database(Utils::PathString databaseFilePath, JournalMode journalMode, LockingMode lockingMode) Database::Database(Utils::PathString databaseFilePath,
: Database{std::move(databaseFilePath), 0ms, journalMode, lockingMode} JournalMode journalMode,
LockingMode lockingMode,
const source_location &sourceLocation)
: Database{std::move(databaseFilePath), 0ms, journalMode, lockingMode, sourceLocation}
{} {}
Database::Database(Utils::PathString databaseFilePath, Database::Database(Utils::PathString databaseFilePath,
std::chrono::milliseconds busyTimeout, std::chrono::milliseconds busyTimeout,
JournalMode journalMode, JournalMode journalMode,
LockingMode lockingMode) LockingMode lockingMode,
: m_databaseBackend(*this) const source_location &sourceLocation)
: m_databaseBackend(*this, sourceLocation)
, m_busyTimeout(busyTimeout) , m_busyTimeout(busyTimeout)
{ {
std::lock_guard lock{*this}; std::lock_guard lock{*this};
@@ -62,36 +68,38 @@ Database::Database(Utils::PathString databaseFilePath,
Database::~Database() = default; Database::~Database() = default;
void Database::activateLogging() void Database::activateLogging(const source_location &sourceLocation)
{ {
DatabaseBackend::activateLogging(); DatabaseBackend::activateLogging(sourceLocation);
} }
void Database::open(LockingMode lockingMode) void Database::open(LockingMode lockingMode, const source_location &sourceLocation)
{ {
m_databaseBackend.open(m_databaseFilePath, m_openMode, m_journalMode); m_databaseBackend.open(m_databaseFilePath, m_openMode, m_journalMode, sourceLocation);
if (m_busyTimeout > 0ms) if (m_busyTimeout > 0ms)
m_databaseBackend.setBusyTimeout(m_busyTimeout); m_databaseBackend.setBusyTimeout(m_busyTimeout);
else else
m_databaseBackend.registerBusyHandler(); m_databaseBackend.registerBusyHandler(sourceLocation);
m_databaseBackend.setLockingMode(lockingMode); m_databaseBackend.setLockingMode(lockingMode, sourceLocation);
m_databaseBackend.setJournalMode(m_journalMode); m_databaseBackend.setJournalMode(m_journalMode, sourceLocation);
registerTransactionStatements(); registerTransactionStatements(sourceLocation);
m_isOpen = true; m_isOpen = true;
} }
void Database::open(Utils::PathString &&databaseFilePath, LockingMode lockingMode) void Database::open(Utils::PathString &&databaseFilePath,
LockingMode lockingMode,
const source_location &sourceLocation)
{ {
m_isInitialized = QFileInfo::exists(QString(databaseFilePath)); m_isInitialized = QFileInfo::exists(QString(databaseFilePath));
setDatabaseFilePath(std::move(databaseFilePath)); setDatabaseFilePath(std::move(databaseFilePath));
open(lockingMode); open(lockingMode, sourceLocation);
} }
void Database::close() void Database::close(const source_location &sourceLocation)
{ {
m_isOpen = false; m_isOpen = false;
deleteTransactionStatements(); deleteTransactionStatements();
m_databaseBackend.close(); m_databaseBackend.close(sourceLocation);
} }
bool Database::isInitialized() const bool Database::isInitialized() const
@@ -124,9 +132,9 @@ void Database::applyAndUpdateSessions()
m_statements->sessions.applyAndUpdateSessions(); m_statements->sessions.applyAndUpdateSessions();
} }
SessionChangeSets Database::changeSets() const SessionChangeSets Database::changeSets(const source_location &sourceLocation) const
{ {
return m_statements->sessions.changeSets(); return m_statements->sessions.changeSets(sourceLocation);
} }
const Utils::PathString &Database::databaseFilePath() const const Utils::PathString &Database::databaseFilePath() const
@@ -144,9 +152,9 @@ JournalMode Database::journalMode() const
return m_journalMode; return m_journalMode;
} }
LockingMode Database::lockingMode() const LockingMode Database::lockingMode(const source_location &sourceLocation) const
{ {
return m_databaseBackend.lockingMode(); return m_databaseBackend.lockingMode(sourceLocation);
} }
void Database::setOpenMode(OpenMode openMode) void Database::setOpenMode(OpenMode openMode)
@@ -159,14 +167,14 @@ OpenMode Database::openMode() const
return m_openMode; return m_openMode;
} }
void Database::execute(Utils::SmallStringView sqlStatement) void Database::execute(Utils::SmallStringView sqlStatement, const source_location &sourceLocation)
{ {
m_databaseBackend.execute(sqlStatement); m_databaseBackend.execute(sqlStatement, sourceLocation);
} }
void Database::registerTransactionStatements() void Database::registerTransactionStatements(const source_location &sourceLocation)
{ {
m_statements = std::make_unique<Statements>(*this); m_statements = std::make_unique<Statements>(*this, sourceLocation);
} }
void Database::deleteTransactionStatements() void Database::deleteTransactionStatements()
@@ -174,68 +182,70 @@ void Database::deleteTransactionStatements()
m_statements.reset(); m_statements.reset();
} }
void Database::deferredBegin() void Database::deferredBegin(const source_location &sourceLocation)
{ {
m_statements->deferredBegin.execute(); m_statements->deferredBegin.execute(sourceLocation);
} }
void Database::immediateBegin() void Database::immediateBegin(const source_location &sourceLocation)
{ {
m_statements->immediateBegin.execute(); m_statements->immediateBegin.execute(sourceLocation);
} }
void Database::exclusiveBegin() void Database::exclusiveBegin(const source_location &sourceLocation)
{ {
m_statements->exclusiveBegin.execute(); m_statements->exclusiveBegin.execute(sourceLocation);
} }
void Database::commit() void Database::commit(const source_location &sourceLocation)
{ {
m_statements->commitBegin.execute(); m_statements->commitBegin.execute(sourceLocation);
} }
void Database::rollback() void Database::rollback(const source_location &sourceLocation)
{ {
m_statements->rollbackBegin.execute(); m_statements->rollbackBegin.execute(sourceLocation);
} }
void Database::immediateSessionBegin() void Database::immediateSessionBegin(const source_location &sourceLocation)
{ {
m_statements->immediateBegin.execute(); m_statements->immediateBegin.execute(sourceLocation);
m_statements->sessions.create(); m_statements->sessions.create(sourceLocation);
} }
void Database::sessionCommit()
void Database::sessionCommit(const source_location &sourceLocation)
{ {
m_statements->sessions.commit(); m_statements->sessions.commit(sourceLocation);
m_statements->commitBegin.execute(); m_statements->commitBegin.execute(sourceLocation);
} }
void Database::sessionRollback()
void Database::sessionRollback(const source_location &sourceLocation)
{ {
m_statements->sessions.rollback(); m_statements->sessions.rollback();
m_statements->rollbackBegin.execute(); m_statements->rollbackBegin.execute(sourceLocation);
} }
void Database::resetDatabaseForTestsOnly() void Database::resetDatabaseForTestsOnly(const source_location &sourceLocation)
{ {
m_databaseBackend.resetDatabaseForTestsOnly(); m_databaseBackend.resetDatabaseForTestsOnly(sourceLocation);
setIsInitialized(false); setIsInitialized(false);
} }
void Database::clearAllTablesForTestsOnly() void Database::clearAllTablesForTestsOnly(const source_location &sourceLocation)
{ {
m_databaseBackend.disableForeignKeys(); m_databaseBackend.disableForeignKeys(sourceLocation);
{ {
Sqlite::ImmediateTransaction transaction{*this}; Sqlite::ImmediateTransaction transaction{*this, sourceLocation};
ReadStatement<1> tablesStatement{"SELECT name FROM sqlite_schema WHERE type='table'", *this}; ReadStatement<1> tablesStatement{"SELECT name FROM sqlite_schema WHERE type='table'", *this};
auto tables = tablesStatement.template values<Utils::SmallString>(); auto tables = tablesStatement.template values<Utils::SmallString>(sourceLocation);
for (const auto &table : tables) for (const auto &table : tables)
execute("DELETE FROM " + table); execute("DELETE FROM " + table, sourceLocation);
transaction.commit(); transaction.commit(sourceLocation);
} }
m_databaseBackend.enableForeignKeys(); m_databaseBackend.enableForeignKeys(sourceLocation);
} }
DatabaseBackend &Database::backend() DatabaseBackend &Database::backend()

View File

@@ -3,6 +3,7 @@
#pragma once #pragma once
#include "sourcelocation.h"
#include "sqlitedatabasebackend.h" #include "sqlitedatabasebackend.h"
#include "sqlitedatabaseinterface.h" #include "sqlitedatabaseinterface.h"
#include "sqliteglobal.h" #include "sqliteglobal.h"
@@ -46,24 +47,29 @@ public:
using ReadWriteStatement = Sqlite::ReadWriteStatement<ResultCount, BindParameterCount>; using ReadWriteStatement = Sqlite::ReadWriteStatement<ResultCount, BindParameterCount>;
using BusyHandler = DatabaseBackend::BusyHandler; using BusyHandler = DatabaseBackend::BusyHandler;
Database(); Database(const source_location &sourceLocation = source_location::current());
Database(Utils::PathString databaseFilePath, Database(Utils::PathString databaseFilePath,
JournalMode journalMode = JournalMode::Wal, JournalMode journalMode = JournalMode::Wal,
LockingMode lockingMode = LockingMode::Default); LockingMode lockingMode = LockingMode::Default,
const source_location &sourceLocation = source_location::current());
Database(Utils::PathString databaseFilePath, Database(Utils::PathString databaseFilePath,
std::chrono::milliseconds busyTimeout, std::chrono::milliseconds busyTimeout,
JournalMode journalMode = JournalMode::Wal, JournalMode journalMode = JournalMode::Wal,
LockingMode lockingMode = LockingMode::Default); LockingMode lockingMode = LockingMode::Default,
const source_location &sourceLocation = source_location::current());
~Database(); ~Database();
Database(const Database &) = delete; Database(const Database &) = delete;
Database &operator=(const Database &) = delete; Database &operator=(const Database &) = delete;
static void activateLogging(); static void activateLogging(const source_location &sourceLocation = source_location::current());
void open(LockingMode lockingMode = LockingMode::Default); void open(LockingMode lockingMode = LockingMode::Default,
void open(Utils::PathString &&databaseFilePath, LockingMode lockingMode = LockingMode::Default); const source_location &sourceLocation = source_location::current());
void close(); void open(Utils::PathString &&databaseFilePath,
LockingMode lockingMode = LockingMode::Default,
const source_location &sourceLocation = source_location::current());
void close(const source_location &sourceLocation = source_location::current());
bool isInitialized() const; bool isInitialized() const;
void setIsInitialized(bool isInitialized); void setIsInitialized(bool isInitialized);
@@ -76,34 +82,52 @@ public:
void setJournalMode(JournalMode journalMode); void setJournalMode(JournalMode journalMode);
JournalMode journalMode() const; JournalMode journalMode() const;
LockingMode lockingMode() const; LockingMode lockingMode(const source_location &sourceLocation = source_location::current()) const;
void setOpenMode(OpenMode openMode); void setOpenMode(OpenMode openMode);
OpenMode openMode() const; OpenMode openMode() const;
void execute(Utils::SmallStringView sqlStatement) override; void execute(Utils::SmallStringView sqlStatement,
const source_location &sourceLocation = source_location::current()) override;
DatabaseBackend &backend(); DatabaseBackend &backend();
int64_t lastInsertedRowId() const int64_t lastInsertedRowId(const source_location &sourceLocation = source_location::current()) const
{ {
return m_databaseBackend.lastInsertedRowId(); return m_databaseBackend.lastInsertedRowId(sourceLocation);
} }
void setLastInsertedRowId(int64_t rowId) { m_databaseBackend.setLastInsertedRowId(rowId); } void setLastInsertedRowId(int64_t rowId,
const source_location &sourceLocation = source_location::current())
{
m_databaseBackend.setLastInsertedRowId(rowId, sourceLocation);
}
int version() const { return m_databaseBackend.version(); } int version(const source_location &sourceLocation = source_location::current()) const
void setVersion(int version) { m_databaseBackend.setVersion(version); } {
return m_databaseBackend.version(sourceLocation);
}
int changesCount() { return m_databaseBackend.changesCount(); } void setVersion(int version, const source_location &sourceLocation = source_location::current())
{
m_databaseBackend.setVersion(version, sourceLocation);
}
int totalChangesCount() { return m_databaseBackend.totalChangesCount(); } int changesCount(const source_location &sourceLocation = source_location::current())
{
return m_databaseBackend.changesCount(sourceLocation);
}
void walCheckpointFull() override int totalChangesCount(const source_location &sourceLocation = source_location::current())
{
return m_databaseBackend.totalChangesCount(sourceLocation);
}
void walCheckpointFull(const source_location &sourceLocation = source_location::current()) override
{ {
std::lock_guard<std::mutex> lock{m_databaseMutex}; std::lock_guard<std::mutex> lock{m_databaseMutex};
try { try {
m_databaseBackend.walCheckpointFull(); m_databaseBackend.walCheckpointFull(sourceLocation);
} catch (const StatementIsBusy &) { } catch (const StatementIsBusy &) {
} }
} }
@@ -123,12 +147,13 @@ public:
void setAttachedTables(const Utils::SmallStringVector &tables) override; void setAttachedTables(const Utils::SmallStringVector &tables) override;
void applyAndUpdateSessions() override; void applyAndUpdateSessions() override;
void setBusyHandler(BusyHandler busyHandler) void setBusyHandler(BusyHandler busyHandler,
const source_location &sourceLocation = source_location::current())
{ {
m_databaseBackend.setBusyHandler(std::move(busyHandler)); m_databaseBackend.setBusyHandler(std::move(busyHandler), sourceLocation);
} }
SessionChangeSets changeSets() const; SessionChangeSets changeSets(const source_location &sourceLocation = source_location::current()) const;
bool isLocked() const bool isLocked() const
{ {
@@ -155,21 +180,21 @@ public:
m_databaseMutex.unlock(); m_databaseMutex.unlock();
} }
void deferredBegin() override; void deferredBegin(const source_location &sourceLocation) override;
void immediateBegin() override; void immediateBegin(const source_location &sourceLocation) override;
void exclusiveBegin() override; void exclusiveBegin(const source_location &sourceLocation) override;
void commit() override; void commit(const source_location &sourceLocation) override;
void rollback() override; void rollback(const source_location &sourceLocation) override;
void immediateSessionBegin() override; void immediateSessionBegin(const source_location &sourceLocation) override;
void sessionCommit() override; void sessionCommit(const source_location &sourceLocation) override;
void sessionRollback() override; void sessionRollback(const source_location &sourceLocation) override;
void resetDatabaseForTestsOnly(); void resetDatabaseForTestsOnly(const source_location &sourceLocation = source_location::current());
void clearAllTablesForTestsOnly(); void clearAllTablesForTestsOnly(const source_location &sourceLocation = source_location::current());
private: private:
void initializeTables(); void initializeTables();
void registerTransactionStatements(); void registerTransactionStatements(const source_location &sourceLocation);
void deleteTransactionStatements(); void deleteTransactionStatements();
std::mutex &databaseMutex() { return m_databaseMutex; } std::mutex &databaseMutex() { return m_databaseMutex; }

View File

@@ -26,13 +26,14 @@ namespace Sqlite {
using namespace std::literals; using namespace std::literals;
DatabaseBackend::DatabaseBackend(Database &database) DatabaseBackend::DatabaseBackend(Database &database, const source_location &sourceLocation)
: m_database(database) : m_database(database)
, m_databaseHandle(nullptr) , m_databaseHandle(nullptr)
, m_busyHandler([](int) { , m_busyHandler([](int) {
std::this_thread::sleep_for(10ms); std::this_thread::sleep_for(10ms);
return true; return true;
}) })
, m_sourceLocation{sourceLocation}
{ {
} }
@@ -41,16 +42,18 @@ DatabaseBackend::~DatabaseBackend()
closeWithoutException(); closeWithoutException();
} }
void DatabaseBackend::setRanslatorentriesapSize(qint64 defaultSize, qint64 maximumSize) void DatabaseBackend::setRanslatorentriesapSize(qint64 defaultSize,
qint64 maximumSize,
const source_location &sourceLocation)
{ {
int resultCode = sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, defaultSize, maximumSize); int resultCode = sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, defaultSize, maximumSize);
checkMmapSizeIsSet(resultCode); checkMmapSizeIsSet(resultCode, sourceLocation);
} }
void DatabaseBackend::activateMultiThreading() void DatabaseBackend::activateMultiThreading(const source_location &sourceLocation)
{ {
int resultCode = sqlite3_config(SQLITE_CONFIG_MULTITHREAD); int resultCode = sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
checkIfMultithreadingIsActivated(resultCode); checkIfMultithreadingIsActivated(resultCode, sourceLocation);
} }
static void sqliteLog(void*,int errorCode,const char *errorMessage) static void sqliteLog(void*,int errorCode,const char *errorMessage)
@@ -58,37 +61,42 @@ static void sqliteLog(void*,int errorCode,const char *errorMessage)
std::cout << "Sqlite " << sqlite3_errstr(errorCode) << ": " << errorMessage << std::endl; std::cout << "Sqlite " << sqlite3_errstr(errorCode) << ": " << errorMessage << std::endl;
} }
void DatabaseBackend::activateLogging() void DatabaseBackend::activateLogging(const source_location &sourceLocation)
{ {
if (qEnvironmentVariableIsSet("QTC_SQLITE_LOGGING")) { if (qEnvironmentVariableIsSet("QTC_SQLITE_LOGGING")) {
int resultCode = sqlite3_config(SQLITE_CONFIG_LOG, sqliteLog, nullptr); int resultCode = sqlite3_config(SQLITE_CONFIG_LOG, sqliteLog, nullptr);
checkIfLoogingIsActivated(resultCode); checkIfLoogingIsActivated(resultCode, sourceLocation);
} }
} }
void DatabaseBackend::initializeSqliteLibrary() void DatabaseBackend::initializeSqliteLibrary(const source_location &sourceLocation)
{ {
int resultCode = sqlite3_initialize(); int resultCode = sqlite3_initialize();
checkInitializeSqliteLibraryWasSuccesful(resultCode); checkInitializeSqliteLibraryWasSuccesful(resultCode, sourceLocation);
} }
void DatabaseBackend::shutdownSqliteLibrary() void DatabaseBackend::shutdownSqliteLibrary(const source_location &sourceLocation)
{ {
int resultCode = sqlite3_shutdown(); int resultCode = sqlite3_shutdown();
checkShutdownSqliteLibraryWasSuccesful(resultCode); checkShutdownSqliteLibraryWasSuccesful(resultCode, sourceLocation);
} }
void DatabaseBackend::checkpointFullWalLog() void DatabaseBackend::checkpointFullWalLog(const source_location &sourceLocation)
{ {
int resultCode = sqlite3_wal_checkpoint_v2(sqliteDatabaseHandle(), nullptr, SQLITE_CHECKPOINT_FULL, nullptr, nullptr); int resultCode = sqlite3_wal_checkpoint_v2(sqliteDatabaseHandle(sourceLocation),
checkIfLogCouldBeCheckpointed(resultCode); nullptr,
SQLITE_CHECKPOINT_FULL,
nullptr,
nullptr);
checkIfLogCouldBeCheckpointed(resultCode, sourceLocation);
} }
void DatabaseBackend::open(Utils::SmallStringView databaseFilePath, void DatabaseBackend::open(Utils::SmallStringView databaseFilePath,
OpenMode openMode, OpenMode openMode,
JournalMode journalMode) JournalMode journalMode,
const source_location &sourceLocation)
{ {
checkCanOpenDatabase(databaseFilePath); checkCanOpenDatabase(databaseFilePath, sourceLocation);
sqlite3 *handle = m_databaseHandle.get(); sqlite3 *handle = m_databaseHandle.get();
int resultCode = sqlite3_open_v2(std::string(databaseFilePath).c_str(), int resultCode = sqlite3_open_v2(std::string(databaseFilePath).c_str(),
@@ -97,42 +105,46 @@ void DatabaseBackend::open(Utils::SmallStringView databaseFilePath,
nullptr); nullptr);
m_databaseHandle.reset(handle); m_databaseHandle.reset(handle);
checkDatabaseCouldBeOpened(resultCode); checkDatabaseCouldBeOpened(resultCode, sourceLocation);
resultCode = sqlite3_carray_init(m_databaseHandle.get(), nullptr, nullptr); resultCode = sqlite3_carray_init(m_databaseHandle.get(), nullptr, nullptr);
checkCarrayCannotBeIntialized(resultCode); checkCarrayCannotBeIntialized(resultCode, sourceLocation);
} }
sqlite3 *DatabaseBackend::sqliteDatabaseHandle() const sqlite3 *DatabaseBackend::sqliteDatabaseHandle(const source_location &sourceLocation) const
{ {
checkDatabaseHandleIsNotNull(); checkDatabaseHandleIsNotNull(sourceLocation);
return m_databaseHandle.get(); return m_databaseHandle.get();
} }
void DatabaseBackend::setPragmaValue(Utils::SmallStringView pragmaKey, Utils::SmallStringView newPragmaValue) void DatabaseBackend::setPragmaValue(Utils::SmallStringView pragmaKey,
Utils::SmallStringView newPragmaValue,
const source_location &sourceLocation)
{ {
ReadWriteStatement<1>{Utils::SmallString::join({"PRAGMA ", pragmaKey, "='", newPragmaValue, "'"}), ReadWriteStatement<1>{Utils::SmallString::join({"PRAGMA ", pragmaKey, "='", newPragmaValue, "'"}),
m_database} m_database}
.execute(); .execute();
Utils::SmallString pragmeValueInDatabase = toValue<Utils::SmallString>("PRAGMA " + pragmaKey); Utils::SmallString pragmeValueInDatabase = toValue<Utils::SmallString>("PRAGMA " + pragmaKey,
sourceLocation);
checkPragmaValue(pragmeValueInDatabase, newPragmaValue); checkPragmaValue(pragmeValueInDatabase, newPragmaValue, sourceLocation);
} }
Utils::SmallString DatabaseBackend::pragmaValue(Utils::SmallStringView pragma) const Utils::SmallString DatabaseBackend::pragmaValue(Utils::SmallStringView pragma,
const source_location &sourceLocation) const
{ {
return toValue<Utils::SmallString>("PRAGMA " + pragma); return toValue<Utils::SmallString>("PRAGMA " + pragma, sourceLocation);
} }
void DatabaseBackend::setJournalMode(JournalMode journalMode) void DatabaseBackend::setJournalMode(JournalMode journalMode, const source_location &sourceLocation)
{ {
setPragmaValue("journal_mode", journalModeToPragma(journalMode)); setPragmaValue("journal_mode", journalModeToPragma(journalMode), sourceLocation);
} }
JournalMode DatabaseBackend::journalMode() JournalMode DatabaseBackend::journalMode(const source_location &sourceLocation)
{ {
return pragmaToJournalMode(pragmaValue("journal_mode")); return pragmaToJournalMode(pragmaValue("journal_mode", sourceLocation), sourceLocation);
} }
namespace { namespace {
@@ -160,67 +172,69 @@ LockingMode pragmaToLockingMode(Utils::SmallStringView pragma)
} }
} // namespace } // namespace
void DatabaseBackend::setLockingMode(LockingMode lockingMode) void DatabaseBackend::setLockingMode(LockingMode lockingMode, const source_location &sourceLocation)
{ {
if (lockingMode != LockingMode::Default) if (lockingMode != LockingMode::Default)
setPragmaValue("main.locking_mode", lockingModeToPragma(lockingMode)); setPragmaValue("main.locking_mode", lockingModeToPragma(lockingMode), sourceLocation);
} }
LockingMode DatabaseBackend::lockingMode() const LockingMode DatabaseBackend::lockingMode(const source_location &sourceLocation) const
{ {
return pragmaToLockingMode(pragmaValue("main.locking_mode")); return pragmaToLockingMode(pragmaValue("main.locking_mode", sourceLocation));
} }
int DatabaseBackend::version() const int DatabaseBackend::version(const source_location &sourceLocation) const
{ {
return toValue<int>("PRAGMA main.user_version"); return toValue<int>("PRAGMA main.user_version", sourceLocation);
} }
void DatabaseBackend::setVersion(int version) void DatabaseBackend::setVersion(int version, const source_location &sourceLocation)
{ {
ReadWriteStatement<>{Utils::SmallString{"PRAGMA main.user_version = "} ReadWriteStatement<>{Utils::SmallString{"PRAGMA main.user_version = "}
+ Utils::SmallString::number(version), + Utils::SmallString::number(version),
m_database} m_database,
.execute(); sourceLocation}
.execute(sourceLocation);
} }
int DatabaseBackend::changesCount() const int DatabaseBackend::changesCount(const source_location &sourceLocation) const
{ {
return sqlite3_changes(sqliteDatabaseHandle()); return sqlite3_changes(sqliteDatabaseHandle(sourceLocation));
} }
int DatabaseBackend::totalChangesCount() const int DatabaseBackend::totalChangesCount(const source_location &sourceLocation) const
{ {
return sqlite3_total_changes(sqliteDatabaseHandle()); return sqlite3_total_changes(sqliteDatabaseHandle(sourceLocation));
} }
int64_t DatabaseBackend::lastInsertedRowId() const int64_t DatabaseBackend::lastInsertedRowId(const source_location &sourceLocation) const
{ {
return sqlite3_last_insert_rowid(sqliteDatabaseHandle()); return sqlite3_last_insert_rowid(sqliteDatabaseHandle(sourceLocation));
} }
void DatabaseBackend::setLastInsertedRowId(int64_t rowId) void DatabaseBackend::setLastInsertedRowId(int64_t rowId, const source_location &sourceLocation)
{ {
sqlite3_set_last_insert_rowid(sqliteDatabaseHandle(), rowId); sqlite3_set_last_insert_rowid(sqliteDatabaseHandle(sourceLocation), rowId);
} }
void DatabaseBackend::execute(Utils::SmallStringView sqlStatement) void DatabaseBackend::execute(Utils::SmallStringView sqlStatement,
const source_location &sourceLocation)
{ {
try { try {
ReadWriteStatement<0> statement(sqlStatement, m_database); ReadWriteStatement<0> statement(sqlStatement, m_database, sourceLocation);
statement.execute(); statement.execute(sourceLocation);
} catch (StatementIsBusy &) { } catch (StatementIsBusy &) {
execute(sqlStatement); execute(sqlStatement, sourceLocation);
} }
} }
void DatabaseBackend::close() void DatabaseBackend::close(const source_location &sourceLocation)
{ {
checkForOpenDatabaseWhichCanBeClosed(); checkForOpenDatabaseWhichCanBeClosed(sourceLocation);
int resultCode = sqlite3_close(m_databaseHandle.get()); int resultCode = sqlite3_close(m_databaseHandle.get());
checkDatabaseClosing(resultCode); checkDatabaseClosing(resultCode, sourceLocation);
m_databaseHandle.release(); m_databaseHandle.release();
} }
@@ -246,66 +260,72 @@ int busyHandlerCallback(void *userData, int counter)
} // namespace } // namespace
void DatabaseBackend::registerBusyHandler() void DatabaseBackend::registerBusyHandler(const source_location &sourceLocation)
{ {
int resultCode = sqlite3_busy_handler(sqliteDatabaseHandle(), int resultCode = sqlite3_busy_handler(sqliteDatabaseHandle(sourceLocation),
&busyHandlerCallback, &busyHandlerCallback,
&m_busyHandler); &m_busyHandler);
checkIfBusyTimeoutWasSet(resultCode); checkIfBusyTimeoutWasSet(resultCode, sourceLocation);
} }
void DatabaseBackend::resetDatabaseForTestsOnly() void DatabaseBackend::resetDatabaseForTestsOnly(const source_location &sourceLocation)
{ {
sqlite3_db_config(sqliteDatabaseHandle(), SQLITE_DBCONFIG_RESET_DATABASE, 1, 0); sqlite3_db_config(sqliteDatabaseHandle(sourceLocation), SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
sqlite3_exec(sqliteDatabaseHandle(), "VACUUM", nullptr, nullptr, nullptr); sqlite3_exec(sqliteDatabaseHandle(sourceLocation), "VACUUM", nullptr, nullptr, nullptr);
sqlite3_db_config(sqliteDatabaseHandle(), SQLITE_DBCONFIG_RESET_DATABASE, 0, 0); sqlite3_db_config(sqliteDatabaseHandle(sourceLocation), SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
} }
void DatabaseBackend::enableForeignKeys() void DatabaseBackend::enableForeignKeys(const source_location &sourceLocation)
{ {
sqlite3_exec(sqliteDatabaseHandle(), "PRAGMA foreign_keys=ON", nullptr, nullptr, nullptr); sqlite3_exec(sqliteDatabaseHandle(sourceLocation), "PRAGMA foreign_keys=ON", nullptr, nullptr, nullptr);
} }
void DatabaseBackend::disableForeignKeys() void DatabaseBackend::disableForeignKeys(const source_location &sourceLocation)
{ {
sqlite3_exec(sqliteDatabaseHandle(), "PRAGMA foreign_keys=OFF", nullptr, nullptr, nullptr); sqlite3_exec(sqliteDatabaseHandle(sourceLocation), "PRAGMA foreign_keys=OFF", nullptr, nullptr, nullptr);
} }
void DatabaseBackend::checkForOpenDatabaseWhichCanBeClosed() void DatabaseBackend::checkForOpenDatabaseWhichCanBeClosed(const source_location &sourceLocation)
{ {
if (m_databaseHandle == nullptr) if (m_databaseHandle == nullptr)
throw DatabaseIsAlreadyClosed(); throw DatabaseIsAlreadyClosed(sourceLocation);
} }
void DatabaseBackend::checkDatabaseClosing(int resultCode) void DatabaseBackend::checkDatabaseClosing(int resultCode, const source_location &sourceLocation)
{ {
switch (resultCode) { switch (resultCode) {
case SQLITE_OK: return; case SQLITE_OK: return;
case SQLITE_BUSY: case SQLITE_BUSY:
throw DatabaseIsBusy(); throw DatabaseIsBusy(sourceLocation);
default: default:
throw UnknowError("SqliteDatabaseBackend::close: unknown error happens at closing!"); throw UnknowError("SqliteDatabaseBackend::close: unknown error happens at closing!",
sourceLocation);
} }
} }
void DatabaseBackend::checkCanOpenDatabase(Utils::SmallStringView databaseFilePath) void DatabaseBackend::checkCanOpenDatabase(Utils::SmallStringView databaseFilePath,
const source_location &sourceLocation)
{ {
if (databaseFilePath.isEmpty()) if (databaseFilePath.isEmpty())
throw DatabaseFilePathIsEmpty("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened because the file path is empty!"); throw DatabaseFilePathIsEmpty("SqliteDatabaseBackend::SqliteDatabaseBackend: database "
"cannot be opened because the file path is empty!",
sourceLocation);
if (!QFileInfo::exists(QFileInfo(QString{databaseFilePath}).path())) if (!QFileInfo::exists(QFileInfo(QString{databaseFilePath}).path()))
throw WrongFilePath(Utils::SmallString(databaseFilePath)); throw WrongFilePath(Utils::SmallString(databaseFilePath), sourceLocation);
if (databaseIsOpen()) if (databaseIsOpen())
throw DatabaseIsAlreadyOpen("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened because it is already open!"); throw DatabaseIsAlreadyOpen("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot "
"be opened because it is already open!",
sourceLocation);
} }
void DatabaseBackend::checkDatabaseCouldBeOpened(int resultCode) void DatabaseBackend::checkDatabaseCouldBeOpened(int resultCode, const source_location &sourceLocation)
{ {
if (resultCode != SQLITE_OK) { if (resultCode != SQLITE_OK) {
try { try {
Sqlite::throwError(resultCode, sqliteDatabaseHandle()); Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
} catch (...) { } catch (...) {
closeWithoutException(); closeWithoutException();
throw; throw;
@@ -313,65 +333,71 @@ void DatabaseBackend::checkDatabaseCouldBeOpened(int resultCode)
} }
} }
void DatabaseBackend::checkCarrayCannotBeIntialized(int resultCode) void DatabaseBackend::checkCarrayCannotBeIntialized(int resultCode,
const source_location &sourceLocation)
{ {
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
throw DatabaseIsNotOpen(); throw DatabaseIsNotOpen(sourceLocation);
} }
void DatabaseBackend::checkPragmaValue(Utils::SmallStringView databaseValue, void DatabaseBackend::checkPragmaValue(Utils::SmallStringView databaseValue,
Utils::SmallStringView expectedValue) Utils::SmallStringView expectedValue,
const source_location &sourceLocation)
{ {
if (databaseValue != expectedValue) if (databaseValue != expectedValue)
throw PragmaValueNotSet(); throw PragmaValueNotSet(sourceLocation);
} }
void DatabaseBackend::checkDatabaseHandleIsNotNull() const void DatabaseBackend::checkDatabaseHandleIsNotNull(const source_location &sourceLocation) const
{ {
if (m_databaseHandle == nullptr) if (m_databaseHandle == nullptr)
throw DatabaseIsNotOpen(); throw DatabaseIsNotOpen(sourceLocation);
} }
void DatabaseBackend::checkIfMultithreadingIsActivated(int resultCode) void DatabaseBackend::checkIfMultithreadingIsActivated(int resultCode,
const source_location &sourceLocation)
{ {
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
throw MultiTheadingCannotBeActivated{}; throw MultiTheadingCannotBeActivated{sourceLocation};
} }
void DatabaseBackend::checkIfLoogingIsActivated(int resultCode) void DatabaseBackend::checkIfLoogingIsActivated(int resultCode, const source_location &sourceLocation)
{ {
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
throw LoggingCannotBeActivated{}; throw LoggingCannotBeActivated{sourceLocation};
} }
void DatabaseBackend::checkMmapSizeIsSet(int resultCode) void DatabaseBackend::checkMmapSizeIsSet(int resultCode, const source_location &sourceLocation)
{ {
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
throw MemoryMappingCannotBeChanged{}; throw MemoryMappingCannotBeChanged{sourceLocation};
} }
void DatabaseBackend::checkInitializeSqliteLibraryWasSuccesful(int resultCode) void DatabaseBackend::checkInitializeSqliteLibraryWasSuccesful(int resultCode,
const source_location &sourceLocation)
{ {
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
throw LibraryCannotBeInitialized{}; throw LibraryCannotBeInitialized{sourceLocation};
} }
void DatabaseBackend::checkShutdownSqliteLibraryWasSuccesful(int resultCode) void DatabaseBackend::checkShutdownSqliteLibraryWasSuccesful(int resultCode,
const source_location &sourceLocation)
{ {
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
throw LibraryCannotBeShutdown{}; throw LibraryCannotBeShutdown{sourceLocation};
} }
void DatabaseBackend::checkIfLogCouldBeCheckpointed(int resultCode) void DatabaseBackend::checkIfLogCouldBeCheckpointed(int resultCode,
const source_location &sourceLocation)
{ {
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
throw LogCannotBeCheckpointed{}; throw LogCannotBeCheckpointed{sourceLocation};
} }
void DatabaseBackend::checkIfBusyTimeoutWasSet(int resultCode) void DatabaseBackend::checkIfBusyTimeoutWasSet(int resultCode, const source_location &sourceLocation)
{ {
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
throw BusyTimerCannotBeSet{}; throw BusyTimerCannotBeSet{sourceLocation};
} }
namespace { namespace {
@@ -398,12 +424,13 @@ Utils::SmallStringView DatabaseBackend::journalModeToPragma(JournalMode journalM
return journalModeStrings[int(journalMode)]; return journalModeStrings[int(journalMode)];
} }
JournalMode DatabaseBackend::pragmaToJournalMode(Utils::SmallStringView pragma) JournalMode DatabaseBackend::pragmaToJournalMode(Utils::SmallStringView pragma,
const source_location &sourceLocation)
{ {
int index = indexOfPragma(pragma, journalModeStrings); int index = indexOfPragma(pragma, journalModeStrings);
if (index < 0) if (index < 0)
throw PragmaValueCannotBeTransformed{}; throw PragmaValueCannotBeTransformed{sourceLocation};
return static_cast<JournalMode>(index); return static_cast<JournalMode>(index);
} }
@@ -432,7 +459,7 @@ void DatabaseBackend::setBusyTimeout(std::chrono::milliseconds timeout)
sqlite3_busy_timeout(m_databaseHandle.get(), int(timeout.count())); sqlite3_busy_timeout(m_databaseHandle.get(), int(timeout.count()));
} }
void DatabaseBackend::walCheckpointFull() void DatabaseBackend::walCheckpointFull(const source_location &sourceLocation)
{ {
int resultCode = sqlite3_wal_checkpoint_v2(m_databaseHandle.get(), int resultCode = sqlite3_wal_checkpoint_v2(m_databaseHandle.get(),
nullptr, nullptr,
@@ -441,7 +468,7 @@ void DatabaseBackend::walCheckpointFull()
nullptr); nullptr);
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
Sqlite::throwError(resultCode, sqliteDatabaseHandle()); Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
} }
void DatabaseBackend::setUpdateHook( void DatabaseBackend::setUpdateHook(
@@ -456,10 +483,11 @@ void DatabaseBackend::resetUpdateHook()
sqlite3_update_hook(m_databaseHandle.get(), nullptr, nullptr); sqlite3_update_hook(m_databaseHandle.get(), nullptr, nullptr);
} }
void DatabaseBackend::setBusyHandler(DatabaseBackend::BusyHandler &&busyHandler) void DatabaseBackend::setBusyHandler(DatabaseBackend::BusyHandler &&busyHandler,
const source_location &sourceLocation)
{ {
m_busyHandler = std::move(busyHandler); m_busyHandler = std::move(busyHandler);
registerBusyHandler(); registerBusyHandler(sourceLocation);
} }
namespace { namespace {
@@ -473,36 +501,39 @@ int progressHandlerCallback(void *userData)
} // namespace } // namespace
void DatabaseBackend::setProgressHandler(int operationCount, ProgressHandler &&progressHandler) void DatabaseBackend::setProgressHandler(int operationCount,
ProgressHandler &&progressHandler,
const source_location &sourceLocation)
{ {
m_progressHandler = std::move(progressHandler); m_progressHandler = std::move(progressHandler);
if (m_progressHandler) if (m_progressHandler)
sqlite3_progress_handler(sqliteDatabaseHandle(), sqlite3_progress_handler(sqliteDatabaseHandle(sourceLocation),
operationCount, operationCount,
&progressHandlerCallback, &progressHandlerCallback,
&m_progressHandler); &m_progressHandler);
else { else {
sqlite3_progress_handler(sqliteDatabaseHandle(), 0, nullptr, nullptr); sqlite3_progress_handler(sqliteDatabaseHandle(sourceLocation), 0, nullptr, nullptr);
} }
} }
void DatabaseBackend::resetProgressHandler() void DatabaseBackend::resetProgressHandler(const source_location &sourceLocation)
{ {
sqlite3_progress_handler(sqliteDatabaseHandle(), 0, nullptr, nullptr); sqlite3_progress_handler(sqliteDatabaseHandle(sourceLocation), 0, nullptr, nullptr);
} }
template<typename Type> template<typename Type>
Type DatabaseBackend::toValue(Utils::SmallStringView sqlStatement) const Type DatabaseBackend::toValue(Utils::SmallStringView sqlStatement,
const source_location &sourceLocation) const
{ {
try { try {
ReadWriteStatement<1> statement(sqlStatement, m_database); ReadWriteStatement<1> statement(sqlStatement, m_database, sourceLocation);
statement.next(); statement.next(sourceLocation);
return statement.fetchValue<Type>(0); return statement.fetchValue<Type>(0);
} catch (StatementIsBusy &) { } catch (StatementIsBusy &) {
return toValue<Type>(sqlStatement); return toValue<Type>(sqlStatement, sourceLocation);
} }
} }

View File

@@ -3,6 +3,7 @@
#pragma once #pragma once
#include "sourcelocation.h"
#include "sqlite3_fwd.h" #include "sqlite3_fwd.h"
#include "sqliteglobal.h" #include "sqliteglobal.h"
@@ -23,7 +24,7 @@ public:
using BusyHandler = std::function<bool(int count)>; using BusyHandler = std::function<bool(int count)>;
using ProgressHandler = std::function<Progress()>; using ProgressHandler = std::function<Progress()>;
DatabaseBackend(Database &database); DatabaseBackend(Database &database, const source_location &sourceLocation);
~DatabaseBackend(); ~DatabaseBackend();
DatabaseBackend(const DatabaseBackend &) = delete; DatabaseBackend(const DatabaseBackend &) = delete;
@@ -32,85 +33,102 @@ public:
DatabaseBackend(DatabaseBackend &&) = delete; DatabaseBackend(DatabaseBackend &&) = delete;
DatabaseBackend &operator=(DatabaseBackend &&) = delete; DatabaseBackend &operator=(DatabaseBackend &&) = delete;
static void setRanslatorentriesapSize(qint64 defaultSize, qint64 maximumSize); static void setRanslatorentriesapSize(qint64 defaultSize,
static void activateMultiThreading(); qint64 maximumSize,
static void activateLogging(); const source_location &sourceLocation);
static void initializeSqliteLibrary(); static void activateMultiThreading(const source_location &sourceLocation);
static void shutdownSqliteLibrary(); static void activateLogging(const source_location &sourceLocation);
void checkpointFullWalLog(); static void initializeSqliteLibrary(const source_location &sourceLocation);
static void shutdownSqliteLibrary(const source_location &sourceLocation);
void checkpointFullWalLog(const source_location &sourceLocation);
void open(Utils::SmallStringView databaseFilePath, OpenMode openMode, JournalMode journalMode); void open(Utils::SmallStringView databaseFilePath,
void close(); OpenMode openMode,
JournalMode journalMode,
const source_location &sourceLocation);
void close(const source_location &sourceLocation);
void closeWithoutException(); void closeWithoutException();
sqlite3 *sqliteDatabaseHandle() const; sqlite3 *sqliteDatabaseHandle(const source_location &sourceLocation) const;
void setJournalMode(JournalMode journalMode); void setJournalMode(JournalMode journalMode, const source_location &sourceLocation);
JournalMode journalMode(); JournalMode journalMode(const source_location &sourceLocation);
void setLockingMode(LockingMode lockingMode); void setLockingMode(LockingMode lockingMode, const source_location &sourceLocation);
LockingMode lockingMode() const; LockingMode lockingMode(const source_location &sourceLocation) const;
Utils::SmallStringVector columnNames(Utils::SmallStringView tableName); Utils::SmallStringVector columnNames(Utils::SmallStringView tableName);
int version() const; int version(const source_location &sourceLocation) const;
void setVersion(int version); void setVersion(int version, const source_location &sourceLocation);
int changesCount() const; int changesCount(const source_location &sourceLocation) const;
int totalChangesCount() const; int totalChangesCount(const source_location &sourceLocation) const;
int64_t lastInsertedRowId() const; int64_t lastInsertedRowId(const source_location &sourceLocation) const;
void setLastInsertedRowId(int64_t rowId); void setLastInsertedRowId(int64_t rowId, const source_location &sourceLocation);
void execute(Utils::SmallStringView sqlStatement); void execute(Utils::SmallStringView sqlStatement, const source_location &sourceLocation);
template<typename Type> template<typename Type>
Type toValue(Utils::SmallStringView sqlStatement) const; Type toValue(Utils::SmallStringView sqlStatement, const source_location &sourceLocation) const;
static int createOpenFlags(OpenMode openMode, JournalMode journalMode); static int createOpenFlags(OpenMode openMode, JournalMode journalMode);
void setBusyTimeout(std::chrono::milliseconds timeout); void setBusyTimeout(std::chrono::milliseconds timeout);
void walCheckpointFull(); void walCheckpointFull(const source_location &sourceLocation);
void setUpdateHook( void setUpdateHook(
void *object, void *object,
void (*callback)(void *object, int, char const *database, char const *, long long rowId)); void (*callback)(void *object, int, char const *database, char const *, long long rowId));
void resetUpdateHook(); void resetUpdateHook();
void setBusyHandler(BusyHandler &&busyHandler); void setBusyHandler(BusyHandler &&busyHandler, const source_location &sourceLocation);
void setProgressHandler(int operationCount, ProgressHandler &&progressHandler); void setProgressHandler(int operationCount,
void resetProgressHandler(); ProgressHandler &&progressHandler,
const source_location &sourceLocation);
void resetProgressHandler(const source_location &sourceLocation);
void registerBusyHandler(); void registerBusyHandler(const source_location &sourceLocation);
void resetDatabaseForTestsOnly(); void resetDatabaseForTestsOnly(const source_location &sourceLocation);
void enableForeignKeys(); void enableForeignKeys(const source_location &sourceLocation);
void disableForeignKeys(); void disableForeignKeys(const source_location &sourceLocation);
protected: protected:
bool databaseIsOpen() const; bool databaseIsOpen() const;
void setPragmaValue(Utils::SmallStringView pragma, Utils::SmallStringView value); void setPragmaValue(Utils::SmallStringView pragma,
Utils::SmallString pragmaValue(Utils::SmallStringView pragma) const; Utils::SmallStringView value,
const source_location &sourceLocation);
Utils::SmallString pragmaValue(Utils::SmallStringView pragma,
const source_location &sourceLocation) const;
void checkForOpenDatabaseWhichCanBeClosed(); void checkForOpenDatabaseWhichCanBeClosed(const source_location &sourceLocation);
void checkDatabaseClosing(int resultCode); void checkDatabaseClosing(int resultCode, const source_location &sourceLocation);
void checkCanOpenDatabase(Utils::SmallStringView databaseFilePath); void checkCanOpenDatabase(Utils::SmallStringView databaseFilePath,
void checkDatabaseCouldBeOpened(int resultCode); const source_location &sourceLocation);
void checkCarrayCannotBeIntialized(int resultCode); void checkDatabaseCouldBeOpened(int resultCode, const source_location &sourceLocation);
void checkPragmaValue(Utils::SmallStringView databaseValue, Utils::SmallStringView expectedValue); void checkCarrayCannotBeIntialized(int resultCode, const source_location &sourceLocation);
void checkDatabaseHandleIsNotNull() const; void checkPragmaValue(Utils::SmallStringView databaseValue,
static void checkIfMultithreadingIsActivated(int resultCode); Utils::SmallStringView expectedValue,
static void checkIfLoogingIsActivated(int resultCode); const source_location &sourceLocation);
static void checkMmapSizeIsSet(int resultCode); void checkDatabaseHandleIsNotNull(const source_location &sourceLocation) const;
static void checkInitializeSqliteLibraryWasSuccesful(int resultCode); static void checkIfMultithreadingIsActivated(int resultCode,
static void checkShutdownSqliteLibraryWasSuccesful(int resultCode); const source_location &sourceLocation);
void checkIfLogCouldBeCheckpointed(int resultCode); static void checkIfLoogingIsActivated(int resultCode, const source_location &sourceLocation);
void checkIfBusyTimeoutWasSet(int resultCode); static void checkMmapSizeIsSet(int resultCode, const source_location &sourceLocation);
static void checkInitializeSqliteLibraryWasSuccesful(int resultCode,
const source_location &sourceLocation);
static void checkShutdownSqliteLibraryWasSuccesful(int resultCode,
const source_location &sourceLocation);
void checkIfLogCouldBeCheckpointed(int resultCode, const source_location &sourceLocation);
void checkIfBusyTimeoutWasSet(int resultCode, const source_location &sourceLocation);
static Utils::SmallStringView journalModeToPragma(JournalMode journalMode); static Utils::SmallStringView journalModeToPragma(JournalMode journalMode);
static JournalMode pragmaToJournalMode(Utils::SmallStringView pragma); static JournalMode pragmaToJournalMode(Utils::SmallStringView pragma,
const source_location &sourceLocation);
private: private:
struct Deleter struct Deleter
@@ -123,6 +141,7 @@ private:
std::unique_ptr<sqlite3, Deleter> m_databaseHandle; std::unique_ptr<sqlite3, Deleter> m_databaseHandle;
BusyHandler m_busyHandler; BusyHandler m_busyHandler;
ProgressHandler m_progressHandler; ProgressHandler m_progressHandler;
source_location m_sourceLocation;
}; };
} // namespace Sqlite } // namespace Sqlite

View File

@@ -5,14 +5,17 @@
#include <utils/smallstringvector.h> #include <utils/smallstringvector.h>
#include "sourcelocation.h"
#include "sqliteglobal.h" #include "sqliteglobal.h"
namespace Sqlite { namespace Sqlite {
class DatabaseInterface class DatabaseInterface
{ {
public: public:
virtual void walCheckpointFull() = 0; virtual void walCheckpointFull(const source_location &sourceLocation = source_location::current()) = 0;
virtual void execute(Utils::SmallStringView sqlStatement) = 0; virtual void execute(Utils::SmallStringView sqlStatement,
const source_location &sourceLocation = source_location::current())
= 0;
virtual void setUpdateHook( virtual void setUpdateHook(
void *object, void *object,
void (*)(void *object, int, char const *database, char const *, long long rowId)) void (*)(void *object, int, char const *database, char const *, long long rowId))

View File

@@ -684,185 +684,185 @@ const char *CannotOpenSynbolicLink::what() const noexcept
return "Sqlite::CannotOpenSynbolicLink"; return "Sqlite::CannotOpenSynbolicLink";
} }
void throwError(int resultCode, sqlite3 *sqliteHandle) void throwError(int resultCode, sqlite3 *sqliteHandle, const source_location &sourceLocation)
{ {
switch (resultCode) { switch (resultCode) {
case SQLITE_BUSY_RECOVERY: case SQLITE_BUSY_RECOVERY:
throw StatementIsBusyRecovering(sqlite3_errmsg(sqliteHandle)); throw StatementIsBusyRecovering(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_BUSY_SNAPSHOT: case SQLITE_BUSY_SNAPSHOT:
throw StatementIsBusySnapshot(sqlite3_errmsg(sqliteHandle)); throw StatementIsBusySnapshot(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_BUSY_TIMEOUT: case SQLITE_BUSY_TIMEOUT:
throw StatementIsBusyTimeout(sqlite3_errmsg(sqliteHandle)); throw StatementIsBusyTimeout(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_BUSY: case SQLITE_BUSY:
throw StatementIsBusy(sqlite3_errmsg(sqliteHandle)); throw StatementIsBusy(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_ERROR_MISSING_COLLSEQ: case SQLITE_ERROR_MISSING_COLLSEQ:
throw StatementHasErrorMissingCollatingSequence(sqlite3_errmsg(sqliteHandle)); throw StatementHasErrorMissingCollatingSequence(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_ERROR_RETRY: case SQLITE_ERROR_RETRY:
throw StatementHasErrorRetry(sqlite3_errmsg(sqliteHandle)); throw StatementHasErrorRetry(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_ERROR_SNAPSHOT: case SQLITE_ERROR_SNAPSHOT:
throw StatementHasErrorSnapshot(sqlite3_errmsg(sqliteHandle)); throw StatementHasErrorSnapshot(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_ERROR: case SQLITE_ERROR:
throw StatementHasError(sqlite3_errmsg(sqliteHandle)); throw StatementHasError(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_MISUSE: case SQLITE_MISUSE:
throw StatementIsMisused(sqlite3_errmsg(sqliteHandle)); throw StatementIsMisused(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_CONSTRAINT_CHECK: case SQLITE_CONSTRAINT_CHECK:
throw CheckConstraintPreventsModification(sqlite3_errmsg(sqliteHandle)); throw CheckConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_CONSTRAINT_COMMITHOOK: case SQLITE_CONSTRAINT_COMMITHOOK:
throw CommitHookConstraintPreventsModification(sqlite3_errmsg(sqliteHandle)); throw CommitHookConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_CONSTRAINT_DATATYPE: case SQLITE_CONSTRAINT_DATATYPE:
throw DataTypeConstraintPreventsModification(sqlite3_errmsg(sqliteHandle)); throw DataTypeConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_CONSTRAINT_FOREIGNKEY: case SQLITE_CONSTRAINT_FOREIGNKEY:
throw ForeignKeyConstraintPreventsModification(sqlite3_errmsg(sqliteHandle)); throw ForeignKeyConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_CONSTRAINT_FUNCTION: case SQLITE_CONSTRAINT_FUNCTION:
throw FunctionConstraintPreventsModification(sqlite3_errmsg(sqliteHandle)); throw FunctionConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_CONSTRAINT_NOTNULL: case SQLITE_CONSTRAINT_NOTNULL:
throw NotNullConstraintPreventsModification(sqlite3_errmsg(sqliteHandle)); throw NotNullConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_CONSTRAINT_PINNED: case SQLITE_CONSTRAINT_PINNED:
throw PinnedConstraintPreventsModification(sqlite3_errmsg(sqliteHandle)); throw PinnedConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_CONSTRAINT_PRIMARYKEY: case SQLITE_CONSTRAINT_PRIMARYKEY:
throw PrimaryKeyConstraintPreventsModification(sqlite3_errmsg(sqliteHandle)); throw PrimaryKeyConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_CONSTRAINT_ROWID: case SQLITE_CONSTRAINT_ROWID:
throw RowIdConstraintPreventsModification(sqlite3_errmsg(sqliteHandle)); throw RowIdConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_CONSTRAINT_TRIGGER: case SQLITE_CONSTRAINT_TRIGGER:
throw TriggerConstraintPreventsModification(sqlite3_errmsg(sqliteHandle)); throw TriggerConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_CONSTRAINT_UNIQUE: case SQLITE_CONSTRAINT_UNIQUE:
throw UniqueConstraintPreventsModification(sqlite3_errmsg(sqliteHandle)); throw UniqueConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_CONSTRAINT_VTAB: case SQLITE_CONSTRAINT_VTAB:
throw VirtualTableConstraintPreventsModification(sqlite3_errmsg(sqliteHandle)); throw VirtualTableConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_CONSTRAINT: case SQLITE_CONSTRAINT:
throw ConstraintPreventsModification(sqlite3_errmsg(sqliteHandle)); throw ConstraintPreventsModification(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_TOOBIG: case SQLITE_TOOBIG:
throw TooBig(sqlite3_errmsg(sqliteHandle)); throw TooBig(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_SCHEMA: case SQLITE_SCHEMA:
throw SchemeChangeError(sqlite3_errmsg(sqliteHandle)); throw SchemeChangeError(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_READONLY_CANTINIT: case SQLITE_READONLY_CANTINIT:
throw CannotInitializeReadOnlyConnection(sqlite3_errmsg(sqliteHandle)); throw CannotInitializeReadOnlyConnection(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_READONLY_CANTLOCK: case SQLITE_READONLY_CANTLOCK:
throw CannotLockReadOnlyConnection(sqlite3_errmsg(sqliteHandle)); throw CannotLockReadOnlyConnection(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_READONLY_DBMOVED: case SQLITE_READONLY_DBMOVED:
throw CannotWriteToMovedDatabase(sqlite3_errmsg(sqliteHandle)); throw CannotWriteToMovedDatabase(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_READONLY_DIRECTORY: case SQLITE_READONLY_DIRECTORY:
throw CannotCreateLogInReadonlyDirectory(sqlite3_errmsg(sqliteHandle)); throw CannotCreateLogInReadonlyDirectory(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_READONLY_RECOVERY: case SQLITE_READONLY_RECOVERY:
throw DatabaseNeedsToBeRecovered(sqlite3_errmsg(sqliteHandle)); throw DatabaseNeedsToBeRecovered(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_READONLY_ROLLBACK: case SQLITE_READONLY_ROLLBACK:
throw CannotRollbackToReadOnlyConnection(sqlite3_errmsg(sqliteHandle)); throw CannotRollbackToReadOnlyConnection(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_READONLY: case SQLITE_READONLY:
throw CannotWriteToReadOnlyConnection(sqlite3_errmsg(sqliteHandle)); throw CannotWriteToReadOnlyConnection(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_PROTOCOL: case SQLITE_PROTOCOL:
throw ProtocolError(sqlite3_errmsg(sqliteHandle)); throw ProtocolError(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_NOMEM: case SQLITE_NOMEM:
throw std::bad_alloc(); throw std::bad_alloc();
case SQLITE_NOLFS: case SQLITE_NOLFS:
throw DatabaseExceedsMaximumFileSize(sqlite3_errmsg(sqliteHandle)); throw DatabaseExceedsMaximumFileSize(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_MISMATCH: case SQLITE_MISMATCH:
throw DataTypeMismatch(sqlite3_errmsg(sqliteHandle)); throw DataTypeMismatch(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_LOCKED_SHAREDCACHE: case SQLITE_LOCKED_SHAREDCACHE:
throw ConnectionsSharedCacheIsLocked(sqlite3_errmsg(sqliteHandle)); throw ConnectionsSharedCacheIsLocked(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_LOCKED_VTAB: case SQLITE_LOCKED_VTAB:
throw ConnectionsVirtualTableIsLocked(sqlite3_errmsg(sqliteHandle)); throw ConnectionsVirtualTableIsLocked(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_LOCKED: case SQLITE_LOCKED:
throw ConnectionIsLocked(sqlite3_errmsg(sqliteHandle)); throw ConnectionIsLocked(sqlite3_errmsg(sqliteHandle), sourceLocation);
case SQLITE_IOERR_READ: case SQLITE_IOERR_READ:
throw InputOutputCannotRead(); throw InputOutputCannotRead(sourceLocation);
case SQLITE_IOERR_SHORT_READ: case SQLITE_IOERR_SHORT_READ:
throw InputOutputCannotShortRead(); throw InputOutputCannotShortRead(sourceLocation);
case SQLITE_IOERR_WRITE: case SQLITE_IOERR_WRITE:
throw InputOutputCannotWrite(); throw InputOutputCannotWrite(sourceLocation);
case SQLITE_IOERR_FSYNC: case SQLITE_IOERR_FSYNC:
throw InputOutputCannotSynchronizeFile(); throw InputOutputCannotSynchronizeFile(sourceLocation);
case SQLITE_IOERR_DIR_FSYNC: case SQLITE_IOERR_DIR_FSYNC:
throw InputOutputCannotSynchronizeDirectory(); throw InputOutputCannotSynchronizeDirectory(sourceLocation);
case SQLITE_IOERR_TRUNCATE: case SQLITE_IOERR_TRUNCATE:
throw InputOutputCannotTruncate(); throw InputOutputCannotTruncate(sourceLocation);
case SQLITE_IOERR_FSTAT: case SQLITE_IOERR_FSTAT:
throw InputOutputCannotFsStat(); throw InputOutputCannotFsStat(sourceLocation);
case SQLITE_IOERR_UNLOCK: case SQLITE_IOERR_UNLOCK:
throw InputOutputCannotUnlock(); throw InputOutputCannotUnlock(sourceLocation);
case SQLITE_IOERR_RDLOCK: case SQLITE_IOERR_RDLOCK:
throw InputOutputCannotReadLock(); throw InputOutputCannotReadLock(sourceLocation);
case SQLITE_IOERR_DELETE: case SQLITE_IOERR_DELETE:
throw InputOutputCannotDelete(); throw InputOutputCannotDelete(sourceLocation);
case SQLITE_IOERR_BLOCKED: case SQLITE_IOERR_BLOCKED:
throw InputOutputBlocked(); throw InputOutputBlocked(sourceLocation);
case SQLITE_IOERR_NOMEM: case SQLITE_IOERR_NOMEM:
throw InputOutputNoMemory(); throw InputOutputNoMemory(sourceLocation);
case SQLITE_IOERR_ACCESS: case SQLITE_IOERR_ACCESS:
throw InputOutputCannotAccess(); throw InputOutputCannotAccess(sourceLocation);
case SQLITE_IOERR_CHECKRESERVEDLOCK: case SQLITE_IOERR_CHECKRESERVEDLOCK:
throw InputOutputCannotCheckReservedLock(); throw InputOutputCannotCheckReservedLock(sourceLocation);
case SQLITE_IOERR_LOCK: case SQLITE_IOERR_LOCK:
throw InputOutputCannotLock(); throw InputOutputCannotLock(sourceLocation);
case SQLITE_IOERR_CLOSE: case SQLITE_IOERR_CLOSE:
throw InputOutputCannotClose(); throw InputOutputCannotClose(sourceLocation);
case SQLITE_IOERR_DIR_CLOSE: case SQLITE_IOERR_DIR_CLOSE:
throw InputOutputCannotCloseDirectory(); throw InputOutputCannotCloseDirectory(sourceLocation);
case SQLITE_IOERR_SHMOPEN: case SQLITE_IOERR_SHMOPEN:
throw InputOutputCannotOpenSharedMemory(); throw InputOutputCannotOpenSharedMemory(sourceLocation);
case SQLITE_IOERR_SHMSIZE: case SQLITE_IOERR_SHMSIZE:
throw InputOutputCannotEnlargeSharedMemory(); throw InputOutputCannotEnlargeSharedMemory(sourceLocation);
case SQLITE_IOERR_SHMLOCK: case SQLITE_IOERR_SHMLOCK:
throw InputOutputCannotLockSharedMemory(); throw InputOutputCannotLockSharedMemory(sourceLocation);
case SQLITE_IOERR_SHMMAP: case SQLITE_IOERR_SHMMAP:
throw InputOutputCannotMapSharedMemory(); throw InputOutputCannotMapSharedMemory(sourceLocation);
case SQLITE_IOERR_SEEK: case SQLITE_IOERR_SEEK:
throw InputOutputCannotSeek(); throw InputOutputCannotSeek(sourceLocation);
case SQLITE_IOERR_DELETE_NOENT: case SQLITE_IOERR_DELETE_NOENT:
throw InputOutputCannotDeleteNonExistingFile(); throw InputOutputCannotDeleteNonExistingFile(sourceLocation);
case SQLITE_IOERR_MMAP: case SQLITE_IOERR_MMAP:
throw InputOutputCannotMemoryMap(); throw InputOutputCannotMemoryMap(sourceLocation);
case SQLITE_IOERR_GETTEMPPATH: case SQLITE_IOERR_GETTEMPPATH:
throw InputOutputCannotGetTemporaryPath(); throw InputOutputCannotGetTemporaryPath(sourceLocation);
case SQLITE_IOERR_CONVPATH: case SQLITE_IOERR_CONVPATH:
throw InputOutputConvPathFailed(); throw InputOutputConvPathFailed(sourceLocation);
case SQLITE_IOERR_VNODE: case SQLITE_IOERR_VNODE:
throw InputOutputVNodeError(); throw InputOutputVNodeError(sourceLocation);
case SQLITE_IOERR_AUTH: case SQLITE_IOERR_AUTH:
throw InputOutputCannotAuthenticate(); throw InputOutputCannotAuthenticate(sourceLocation);
case SQLITE_IOERR_BEGIN_ATOMIC: case SQLITE_IOERR_BEGIN_ATOMIC:
throw InputOutputCannotBeginAtomic(); throw InputOutputCannotBeginAtomic(sourceLocation);
case SQLITE_IOERR_COMMIT_ATOMIC: case SQLITE_IOERR_COMMIT_ATOMIC:
throw InputOutputCannotCommitAtomic(); throw InputOutputCannotCommitAtomic(sourceLocation);
case SQLITE_IOERR_ROLLBACK_ATOMIC: case SQLITE_IOERR_ROLLBACK_ATOMIC:
throw InputOutputCannotRollbackAtomic(); throw InputOutputCannotRollbackAtomic(sourceLocation);
case SQLITE_IOERR_DATA: case SQLITE_IOERR_DATA:
throw InputOutputDataError(); throw InputOutputDataError(sourceLocation);
case SQLITE_IOERR_CORRUPTFS: case SQLITE_IOERR_CORRUPTFS:
throw InputOutputFileSystemIsCorrupt(); throw InputOutputFileSystemIsCorrupt(sourceLocation);
case SQLITE_IOERR: case SQLITE_IOERR:
throw InputOutputError(); throw InputOutputError(sourceLocation);
case SQLITE_INTERRUPT: case SQLITE_INTERRUPT:
throw ExecutionInterrupted(); throw ExecutionInterrupted(sourceLocation);
case SQLITE_CORRUPT_INDEX: case SQLITE_CORRUPT_INDEX:
throw DatabaseHasCorruptIndex(); throw DatabaseHasCorruptIndex(sourceLocation);
case SQLITE_CORRUPT_SEQUENCE: case SQLITE_CORRUPT_SEQUENCE:
throw DatabaseHasCorruptSequence(); throw DatabaseHasCorruptSequence(sourceLocation);
case SQLITE_CORRUPT_VTAB: case SQLITE_CORRUPT_VTAB:
throw DatabaseHasCorruptVirtualTable(); throw DatabaseHasCorruptVirtualTable(sourceLocation);
case SQLITE_CORRUPT: case SQLITE_CORRUPT:
throw DatabaseIsCorrupt(); throw DatabaseIsCorrupt(sourceLocation);
case SQLITE_CANTOPEN_CONVPATH: case SQLITE_CANTOPEN_CONVPATH:
throw CannotOpenConvPath(); throw CannotOpenConvPath(sourceLocation);
case SQLITE_CANTOPEN_DIRTYWAL: case SQLITE_CANTOPEN_DIRTYWAL:
throw CannotOpenDirtyWal(); throw CannotOpenDirtyWal(sourceLocation);
case SQLITE_CANTOPEN_FULLPATH: case SQLITE_CANTOPEN_FULLPATH:
throw CannotCovertToFullPath(); throw CannotCovertToFullPath(sourceLocation);
case SQLITE_CANTOPEN_ISDIR: case SQLITE_CANTOPEN_ISDIR:
throw CannotOpenDirectoryPath(); throw CannotOpenDirectoryPath(sourceLocation);
case SQLITE_CANTOPEN_NOTEMPDIR: case SQLITE_CANTOPEN_NOTEMPDIR:
throw CannotOpenNoTempDir(); throw CannotOpenNoTempDir(sourceLocation);
case SQLITE_CANTOPEN_SYMLINK: case SQLITE_CANTOPEN_SYMLINK:
throw CannotOpenSynbolicLink(); throw CannotOpenSynbolicLink(sourceLocation);
case SQLITE_CANTOPEN: case SQLITE_CANTOPEN:
throw CannotOpen(); throw CannotOpen(sourceLocation);
case SQLITE_RANGE: case SQLITE_RANGE:
throw BindingIndexIsOutOfRange(sqlite3_errmsg(sqliteHandle)); throw BindingIndexIsOutOfRange(sqlite3_errmsg(sqliteHandle), sourceLocation);
} }
if (sqliteHandle) if (sqliteHandle)
throw UnknowError(sqlite3_errmsg(sqliteHandle)); throw UnknowError(sqlite3_errmsg(sqliteHandle), sourceLocation);
else else
throw UnknowError(); throw UnknowError({}, sourceLocation);
} }
} // namespace Sqlite } // namespace Sqlite

View File

@@ -147,198 +147,231 @@ public:
class SQLITE_EXPORT InputOutputCannotAuthenticate : public InputOutputError class SQLITE_EXPORT InputOutputCannotAuthenticate : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotBeginAtomic : public InputOutputError class SQLITE_EXPORT InputOutputCannotBeginAtomic : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotCommitAtomic : public InputOutputError class SQLITE_EXPORT InputOutputCannotCommitAtomic : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotRollbackAtomic : public InputOutputError class SQLITE_EXPORT InputOutputCannotRollbackAtomic : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputDataError : public InputOutputError class SQLITE_EXPORT InputOutputDataError : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputBlocked : public InputOutputError class SQLITE_EXPORT InputOutputBlocked : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputFileSystemIsCorrupt : public InputOutputError class SQLITE_EXPORT InputOutputFileSystemIsCorrupt : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputVNodeError : public InputOutputError class SQLITE_EXPORT InputOutputVNodeError : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputConvPathFailed : public InputOutputError class SQLITE_EXPORT InputOutputConvPathFailed : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotGetTemporaryPath : public InputOutputError class SQLITE_EXPORT InputOutputCannotGetTemporaryPath : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotMemoryMap : public InputOutputError class SQLITE_EXPORT InputOutputCannotMemoryMap : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotDeleteNonExistingFile : public InputOutputError class SQLITE_EXPORT InputOutputCannotDeleteNonExistingFile : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotSeek : public InputOutputError class SQLITE_EXPORT InputOutputCannotSeek : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotMapSharedMemory : public InputOutputError class SQLITE_EXPORT InputOutputCannotMapSharedMemory : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotLockSharedMemory : public InputOutputError class SQLITE_EXPORT InputOutputCannotLockSharedMemory : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotEnlargeSharedMemory : public InputOutputError class SQLITE_EXPORT InputOutputCannotEnlargeSharedMemory : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotOpenSharedMemory : public InputOutputError class SQLITE_EXPORT InputOutputCannotOpenSharedMemory : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotCloseDirectory : public InputOutputError class SQLITE_EXPORT InputOutputCannotCloseDirectory : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotClose : public InputOutputError class SQLITE_EXPORT InputOutputCannotClose : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotLock : public InputOutputError class SQLITE_EXPORT InputOutputCannotLock : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotCheckReservedLock : public InputOutputError class SQLITE_EXPORT InputOutputCannotCheckReservedLock : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotAccess : public InputOutputError class SQLITE_EXPORT InputOutputCannotAccess : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputNoMemory : public InputOutputError class SQLITE_EXPORT InputOutputNoMemory : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotDelete : public InputOutputError class SQLITE_EXPORT InputOutputCannotDelete : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotReadLock : public InputOutputError class SQLITE_EXPORT InputOutputCannotReadLock : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotUnlock : public InputOutputError class SQLITE_EXPORT InputOutputCannotUnlock : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotFsStat : public InputOutputError class SQLITE_EXPORT InputOutputCannotFsStat : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotTruncate : public InputOutputError class SQLITE_EXPORT InputOutputCannotTruncate : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotSynchronizeDirectory : public InputOutputError class SQLITE_EXPORT InputOutputCannotSynchronizeDirectory : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotSynchronizeFile : public InputOutputError class SQLITE_EXPORT InputOutputCannotSynchronizeFile : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotWrite : public InputOutputError class SQLITE_EXPORT InputOutputCannotWrite : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotShortRead : public InputOutputError class SQLITE_EXPORT InputOutputCannotShortRead : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class SQLITE_EXPORT InputOutputCannotRead : public InputOutputError class SQLITE_EXPORT InputOutputCannotRead : public InputOutputError
{ {
public: public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
@@ -896,6 +929,8 @@ public:
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
[[noreturn]] SQLITE_EXPORT void throwError(int resultCode, sqlite3 *sqliteHandle); [[noreturn]] SQLITE_EXPORT void throwError(int resultCode,
sqlite3 *sqliteHandle,
const source_location &sourceLocation);
} // namespace Sqlite } // namespace Sqlite

View File

@@ -35,9 +35,9 @@ void pathExists(sqlite3_context *context, int, sqlite3_value **arguments)
namespace Sqlite::FunctionRegistry { namespace Sqlite::FunctionRegistry {
void registerPathExists(Sqlite::Database &database) void registerPathExists(Sqlite::Database &database, const source_location &sourceLocation)
{ {
sqlite3_create_function(database.backend().sqliteDatabaseHandle(), sqlite3_create_function(database.backend().sqliteDatabaseHandle(sourceLocation),
"pathExists", "pathExists",
1, 1,
SQLITE_UTF8 | SQLITE_INNOCUOUS, SQLITE_UTF8 | SQLITE_INNOCUOUS,

View File

@@ -7,6 +7,7 @@
namespace Sqlite::FunctionRegistry { namespace Sqlite::FunctionRegistry {
SQLITE_EXPORT void registerPathExists(Sqlite::Database &database); SQLITE_EXPORT void registerPathExists(
Sqlite::Database &database, const source_location &sourceLocation = source_location::current());
} // namespace Sqlite::FunctionRegistry } // namespace Sqlite::FunctionRegistry

View File

@@ -14,12 +14,12 @@ void LibraryInitializer::initialize()
LibraryInitializer::LibraryInitializer() LibraryInitializer::LibraryInitializer()
{ {
DatabaseBackend::initializeSqliteLibrary(); DatabaseBackend::initializeSqliteLibrary(source_location::current());
} }
LibraryInitializer::~LibraryInitializer() noexcept(false) LibraryInitializer::~LibraryInitializer() noexcept(false)
{ {
DatabaseBackend::shutdownSqliteLibrary(); DatabaseBackend::shutdownSqliteLibrary(source_location::current());
} }
} // namespace Sqlite } // namespace Sqlite

View File

@@ -11,21 +11,28 @@ class ProgressHandler
{ {
public: public:
template<typename Callable> template<typename Callable>
ProgressHandler(Callable &&callable, int operationCount, Database &database) ProgressHandler(Callable &&callable,
int operationCount,
Database &database,
const source_location &sourceLocation = source_location::current())
: m_database{database} : m_database{database}
, m_sourceLocation{sourceLocation}
{ {
std::unique_lock<TransactionInterface> locker{m_database}; std::unique_lock<TransactionInterface> locker{m_database};
m_database.backend().setProgressHandler(operationCount, std::forward<Callable>(callable)); m_database.backend().setProgressHandler(operationCount,
std::forward<Callable>(callable),
sourceLocation);
} }
~ProgressHandler() ~ProgressHandler()
{ {
std::unique_lock<TransactionInterface> locker{m_database}; std::unique_lock<TransactionInterface> locker{m_database};
m_database.backend().resetProgressHandler(); m_database.backend().resetProgressHandler(m_sourceLocation);
} }
private: private:
Database &m_database; Database &m_database;
source_location m_sourceLocation;
}; };
} // namespace Sqlite } // namespace Sqlite

View File

@@ -14,12 +14,14 @@ class ReadStatement final
using Base = StatementImplementation<BaseStatement, ResultCount, BindParameterCount>; using Base = StatementImplementation<BaseStatement, ResultCount, BindParameterCount>;
public: public:
ReadStatement(Utils::SmallStringView sqlStatement, Database &database) ReadStatement(Utils::SmallStringView sqlStatement,
: Base{sqlStatement, database} Database &database,
const source_location &sourceLocation = source_location::current())
: Base{sqlStatement, database, sourceLocation}
{ {
checkIsReadOnlyStatement(); checkIsReadOnlyStatement(sourceLocation);
Base::checkBindingParameterCount(BindParameterCount); Base::checkBindingParameterCount(BindParameterCount, sourceLocation);
Base::checkColumnCount(ResultCount); Base::checkColumnCount(ResultCount, sourceLocation);
} }
using Base::optionalValue; using Base::optionalValue;
@@ -32,48 +34,89 @@ public:
using Base::values; using Base::values;
template<typename ResultType, typename... QueryTypes> template<typename ResultType, typename... QueryTypes>
auto valueWithTransaction(const QueryTypes &...queryValues) auto valueWithTransaction(const source_location &sourceLocation, const QueryTypes &...queryValues)
{ {
return withImplicitTransaction(Base::database(), [&] { return withImplicitTransaction(Base::database(), [&] {
return Base::template value<ResultType>(queryValues...); return Base::template value<ResultType>(sourceLocation, queryValues...);
});
}
template<typename ResultType, typename... QueryTypes>
auto valueWithTransaction(const QueryTypes &...queryValues)
{
static constexpr auto sourceLocation = source_location::current();
return valueWithTransaction<ResultType>(sourceLocation, queryValues...);
}
template<typename ResultType, typename... QueryTypes>
auto optionalValueWithTransaction(const source_location &sourceLocation,
const QueryTypes &...queryValues)
{
return withImplicitTransaction(Base::database(), [&] {
return Base::template optionalValue<ResultType>(sourceLocation, queryValues...);
}); });
} }
template<typename ResultType, typename... QueryTypes> template<typename ResultType, typename... QueryTypes>
auto optionalValueWithTransaction(const QueryTypes &...queryValues) auto optionalValueWithTransaction(const QueryTypes &...queryValues)
{
static constexpr auto sourceLocation = source_location::current();
return optionalValueWithTransaction<ResultType>(sourceLocation, queryValues...);
}
template<typename ResultType, std::size_t capacity = 32, typename... QueryTypes>
auto valuesWithTransaction(const source_location &sourceLocation, const QueryTypes &...queryValues)
{ {
return withImplicitTransaction(Base::database(), [&] { return withImplicitTransaction(Base::database(), [&] {
return Base::template optionalValue<ResultType>(queryValues...); return Base::template values<ResultType, capacity>(sourceLocation, queryValues...);
}); });
} }
template<typename ResultType, std::size_t capacity = 32, typename... QueryTypes> template<typename ResultType, std::size_t capacity = 32, typename... QueryTypes>
auto valuesWithTransaction(const QueryTypes &...queryValues) auto valuesWithTransaction(const QueryTypes &...queryValues)
{ {
return withImplicitTransaction(Base::database(), [&] { static constexpr auto sourceLocation = source_location::current();
return Base::template values<ResultType, capacity>(queryValues...); return valuesWithTransaction<ResultType, capacity>(sourceLocation, queryValues...);
}
template<typename Callable, typename... QueryTypes>
void readCallbackWithTransaction(Callable &&callable,
const source_location &sourceLocation,
const QueryTypes &...queryValues)
{
withImplicitTransaction(Base::database(), [&] {
Base::readCallback(std::forward<Callable>(callable), sourceLocation, queryValues...);
}); });
} }
template<typename Callable, typename... QueryTypes> template<typename Callable, typename... QueryTypes>
void readCallbackWithTransaction(Callable &&callable, const QueryTypes &...queryValues) void readCallbackWithTransaction(Callable &&callable, const QueryTypes &...queryValues)
{ {
withImplicitTransaction(Base::database(), [&] { static constexpr auto sourceLocation = source_location::current();
Base::readCallback(std::forward<Callable>(callable), queryValues...); readCallbackWithTransaction(callable, sourceLocation, queryValues...);
}); }
template<typename Container, typename... QueryTypes>
void readToWithTransaction(Container &container,
const source_location &sourceLocation,
const QueryTypes &...queryValues)
{
withImplicitTransaction(Base::database(),
[&] { Base::readTo(container, sourceLocation, queryValues...); });
} }
template<typename Container, typename... QueryTypes> template<typename Container, typename... QueryTypes>
void readToWithTransaction(Container &container, const QueryTypes &...queryValues) void readToWithTransaction(Container &container, const QueryTypes &...queryValues)
{ {
withImplicitTransaction(Base::database(), [&] { Base::readTo(container, queryValues...); }); static constexpr auto sourceLocation = source_location::current();
readToWithTransaction(container, sourceLocation, queryValues...);
} }
protected: protected:
void checkIsReadOnlyStatement() void checkIsReadOnlyStatement(const source_location &sourceLocation)
{ {
if (!Base::isReadOnlyStatement()) if (!Base::isReadOnlyStatement())
throw NotReadOnlySqlStatement(); throw NotReadOnlySqlStatement(sourceLocation);
} }
}; };

View File

@@ -15,11 +15,13 @@ class ReadWriteStatement final
using Base = StatementImplementation<BaseStatement, ResultCount, BindParameterCount>; using Base = StatementImplementation<BaseStatement, ResultCount, BindParameterCount>;
public: public:
ReadWriteStatement(Utils::SmallStringView sqlStatement, Database &database) ReadWriteStatement(Utils::SmallStringView sqlStatement,
: Base{sqlStatement, database} Database &database,
const source_location &sourceLocation = source_location::current())
: Base{sqlStatement, database, sourceLocation}
{ {
Base::checkBindingParameterCount(BindParameterCount); Base::checkBindingParameterCount(BindParameterCount, sourceLocation);
Base::checkColumnCount(ResultCount); Base::checkColumnCount(ResultCount, sourceLocation);
} }
using Base::execute; using Base::execute;
@@ -31,53 +33,98 @@ public:
using Base::values; using Base::values;
using Base::write; using Base::write;
template<typename ResultType, typename... QueryTypes>
auto valueWithTransaction(const source_location &sourceLocation, const QueryTypes &...queryValues)
{
return withImmediateTransaction(
Base::database(),
[&] { return Base::template value<ResultType>(sourceLocation, queryValues...); },
sourceLocation);
}
template<typename ResultType, typename... QueryTypes> template<typename ResultType, typename... QueryTypes>
auto valueWithTransaction(const QueryTypes &...queryValues) auto valueWithTransaction(const QueryTypes &...queryValues)
{ {
return withImmediateTransaction(Base::database(), [&] { static constexpr auto sourceLocation = source_location::current();
return Base::template value<ResultType>(queryValues...); return valueWithTransaction<ResultType>(sourceLocation, queryValues...);
}); }
template<typename ResultType, typename... QueryTypes>
auto optionalValueWithTransaction(const source_location &sourceLocation,
const QueryTypes &...queryValues)
{
return withImmediateTransaction(
Base::database(),
[&] { return Base::template optionalValue<ResultType>(sourceLocation, queryValues...); },
sourceLocation);
} }
template<typename ResultType, typename... QueryTypes> template<typename ResultType, typename... QueryTypes>
auto optionalValueWithTransaction(const QueryTypes &...queryValues) auto optionalValueWithTransaction(const QueryTypes &...queryValues)
{ {
return withImmediateTransaction(Base::database(), [&] { static constexpr auto sourceLocation = source_location::current();
return Base::template optionalValue<ResultType>(queryValues...); return optionalValueWithTransaction<ResultType>(sourceLocation, queryValues...);
});
} }
template<typename ResultType, template<typename ResultType, std::size_t capacity = 32, typename... QueryTypes>
std::size_t capacity = 32, auto valuesWithTransaction(const source_location &sourceLocation, const QueryTypes &...queryValues)
typename... QueryTypes> {
return withImmediateTransaction(
Base::database(),
[&] {
return Base::template values<ResultType, capacity>(sourceLocation, queryValues...);
},
sourceLocation);
}
template<typename ResultType, std::size_t capacity = 32, typename... QueryTypes>
auto valuesWithTransaction(const QueryTypes &...queryValues) auto valuesWithTransaction(const QueryTypes &...queryValues)
{ {
return withImmediateTransaction(Base::database(), [&] { static constexpr auto sourceLocation = source_location::current();
return Base::template values<ResultType, capacity>(queryValues...); return valuesWithTransaction<ResultType, capacity>(sourceLocation, queryValues...);
}); }
template<typename Callable, typename... QueryTypes>
void readCallbackWithTransaction(Callable &&callable,
const source_location &sourceLocation,
const QueryTypes &...queryValues)
{
withImmediateTransaction(
Base::database(),
[&] {
Base::readCallback(std::forward<Callable>(callable), sourceLocation, queryValues...);
},
sourceLocation);
} }
template<typename Callable, typename... QueryTypes> template<typename Callable, typename... QueryTypes>
void readCallbackWithTransaction(Callable &&callable, const QueryTypes &...queryValues) void readCallbackWithTransaction(Callable &&callable, const QueryTypes &...queryValues)
{ {
withImmediateTransaction(Base::database(), [&] { static constexpr auto sourceLocation = source_location::current();
Base::readCallback(std::forward<Callable>(callable), queryValues...); readCallbackWithTransaction(callable, sourceLocation, queryValues...);
}); }
template<typename Container, typename... QueryTypes>
void readToWithTransaction(Container &container,
const source_location &sourceLocation,
const QueryTypes &...queryValues)
{
withImmediateTransaction(
Base::database(),
[&] { Base::readTo(container, sourceLocation, queryValues...); },
sourceLocation);
} }
template<typename Container, typename... QueryTypes> template<typename Container, typename... QueryTypes>
void readToWithTransaction(Container &container, const QueryTypes &...queryValues) void readToWithTransaction(Container &container, const QueryTypes &...queryValues)
{ {
withImmediateTransaction(Base::database(), [&] { static constexpr auto sourceLocation = source_location::current();
Base::readTo(container, queryValues...); readToWithTransaction(container, sourceLocation, queryValues...);
});
} }
void executeWithTransaction() void executeWithTransaction(const source_location &sourceLocation = source_location::current())
{ {
withImmediateTransaction(Base::database(), [&] { withImmediateTransaction(Base::database(), [&] { Base::execute(sourceLocation); }, sourceLocation);
Base::execute();
});
} }
}; };

View File

@@ -14,19 +14,19 @@ namespace Sqlite {
namespace { namespace {
void checkResultCode(int resultCode) void checkResultCode(int resultCode, const source_location &sourceLocation)
{ {
switch (resultCode) { switch (resultCode) {
case SQLITE_NOMEM: case SQLITE_NOMEM:
throw std::bad_alloc(); throw std::bad_alloc();
case SQLITE_SCHEMA: case SQLITE_SCHEMA:
throw CannotApplyChangeSet(); throw CannotApplyChangeSet(sourceLocation);
case SQLITE_MISUSE: case SQLITE_MISUSE:
throw ChangeSetIsMisused(); throw ChangeSetIsMisused(sourceLocation);
} }
if (resultCode != SQLITE_OK) if (resultCode != SQLITE_OK)
throw UnknowError(); throw UnknowError({}, sourceLocation);
} }
int xConflict(void *, int conflict, sqlite3_changeset_iter *) int xConflict(void *, int conflict, sqlite3_changeset_iter *)
@@ -48,11 +48,12 @@ int xConflict(void *, int conflict, sqlite3_changeset_iter *)
} }
} // namespace } // namespace
void Sessions::attachTables(const Utils::SmallStringVector &tableNames) void Sessions::attachTables(const Utils::SmallStringVector &tableNames,
const source_location &sourceLocation)
{ {
for (Utils::SmallStringView tableName : tableNames) { for (Utils::SmallStringView tableName : tableNames) {
int resultCode = sqlite3session_attach(session.get(), std::string(tableName).c_str()); int resultCode = sqlite3session_attach(session.get(), std::string(tableName).c_str());
checkResultCode(resultCode); checkResultCode(resultCode, sourceLocation);
} }
} }
@@ -63,25 +64,25 @@ void Sessions::setAttachedTables(Utils::SmallStringVector tables)
tableNames = std::move(tables); tableNames = std::move(tables);
} }
void Sessions::create() void Sessions::create(const source_location &sourceLocation)
{ {
sqlite3_session *newSession = nullptr; sqlite3_session *newSession = nullptr;
int resultCode = sqlite3session_create(database.backend().sqliteDatabaseHandle(), int resultCode = sqlite3session_create(database.backend().sqliteDatabaseHandle(sourceLocation),
std::string(databaseName).c_str(), std::string(databaseName).c_str(),
&newSession); &newSession);
session.reset(newSession); session.reset(newSession);
checkResultCode(resultCode); checkResultCode(resultCode, sourceLocation);
attachTables(tableNames); attachTables(tableNames, sourceLocation);
} }
void Sessions::commit() void Sessions::commit(const source_location &sourceLocation)
{ {
if (session && !sqlite3session_isempty(session.get())) { if (session && !sqlite3session_isempty(session.get())) {
SessionChangeSet changeSet{*this}; SessionChangeSet changeSet{*this};
insertSession.write(changeSet.asBlobView()); insertSession.write(sourceLocation, changeSet.asBlobView());
} }
session.reset(); session.reset();
@@ -92,7 +93,8 @@ void Sessions::rollback()
session.reset(); session.reset();
} }
void Internal::SessionsBase::createSessionTable(Database &database) void Internal::SessionsBase::createSessionTable(Database &database,
const source_location &sourceLocation)
{ {
Sqlite::Table table; Sqlite::Table table;
table.setUseIfNotExists(true); table.setUseIfNotExists(true);
@@ -100,20 +102,22 @@ void Internal::SessionsBase::createSessionTable(Database &database)
table.addColumn("id", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{AutoIncrement::Yes}}); table.addColumn("id", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{AutoIncrement::Yes}});
table.addColumn("changeset", Sqlite::ColumnType::Blob); table.addColumn("changeset", Sqlite::ColumnType::Blob);
table.initialize(database); table.initialize(database, sourceLocation);
} }
void Sessions::revert() void Sessions::revert(const source_location &sourceLocation)
{ {
ReadStatement<1> selectChangeSets{Utils::PathString::join({"SELECT changeset FROM ", ReadStatement<1> selectChangeSets{Utils::PathString::join({"SELECT changeset FROM ",
sessionsTableName, sessionsTableName,
" ORDER BY id DESC"}), " ORDER BY id DESC"}),
database}; database,
sourceLocation};
auto changeSets = selectChangeSets.values<SessionChangeSet, 1024>(); auto changeSets = selectChangeSets.values<SessionChangeSet, 1024>(sourceLocation);
for (auto &changeSet : changeSets) { for (auto &changeSet : changeSets) {
int resultCode = sqlite3changeset_apply_v2(database.backend().sqliteDatabaseHandle(), int resultCode = sqlite3changeset_apply_v2(database.backend().sqliteDatabaseHandle(
sourceLocation),
changeSet.size(), changeSet.size(),
changeSet.data(), changeSet.data(),
nullptr, nullptr,
@@ -123,21 +127,23 @@ void Sessions::revert()
nullptr, nullptr,
SQLITE_CHANGESETAPPLY_INVERT SQLITE_CHANGESETAPPLY_INVERT
| SQLITE_CHANGESETAPPLY_NOSAVEPOINT); | SQLITE_CHANGESETAPPLY_NOSAVEPOINT);
checkResultCode(resultCode); checkResultCode(resultCode, sourceLocation);
} }
} }
void Sessions::apply() void Sessions::apply(const source_location &sourceLocation)
{ {
ReadStatement<1> selectChangeSets{Utils::PathString::join({"SELECT changeset FROM ", ReadStatement<1> selectChangeSets{Utils::PathString::join({"SELECT changeset FROM ",
sessionsTableName, sessionsTableName,
" ORDER BY id"}), " ORDER BY id"}),
database}; database,
sourceLocation};
auto changeSets = selectChangeSets.values<SessionChangeSet, 1024>(); auto changeSets = selectChangeSets.values<SessionChangeSet, 1024>(sourceLocation);
for (auto &changeSet : changeSets) { for (auto &changeSet : changeSets) {
int resultCode = sqlite3changeset_apply_v2(database.backend().sqliteDatabaseHandle(), int resultCode = sqlite3changeset_apply_v2(database.backend().sqliteDatabaseHandle(
sourceLocation),
changeSet.size(), changeSet.size(),
changeSet.data(), changeSet.data(),
nullptr, nullptr,
@@ -146,31 +152,35 @@ void Sessions::apply()
nullptr, nullptr,
nullptr, nullptr,
SQLITE_CHANGESETAPPLY_NOSAVEPOINT); SQLITE_CHANGESETAPPLY_NOSAVEPOINT);
checkResultCode(resultCode); checkResultCode(resultCode, sourceLocation);
} }
} }
void Sessions::applyAndUpdateSessions() void Sessions::applyAndUpdateSessions(const source_location &sourceLocation)
{ {
create(); create(sourceLocation);
apply(); apply(sourceLocation);
deleteAll(); deleteAll(sourceLocation);
commit(); commit(sourceLocation);
} }
void Sessions::deleteAll() void Sessions::deleteAll(const source_location &sourceLocation)
{ {
WriteStatement<0>{Utils::SmallString::join({"DELETE FROM ", sessionsTableName}), database}.execute(); WriteStatement<0>{Utils::SmallString::join({"DELETE FROM ", sessionsTableName}),
database,
sourceLocation}
.execute(sourceLocation);
} }
SessionChangeSets Sessions::changeSets() const SessionChangeSets Sessions::changeSets(const source_location &sourceLocation) const
{ {
ReadStatement<1> selectChangeSets{Utils::PathString::join({"SELECT changeset FROM ", ReadStatement<1> selectChangeSets{Utils::PathString::join({"SELECT changeset FROM ",
sessionsTableName, sessionsTableName,
" ORDER BY id DESC"}), " ORDER BY id DESC"}),
database}; database,
sourceLocation};
return selectChangeSets.values<SessionChangeSet, 1024>(); return selectChangeSets.values<SessionChangeSet, 1024>(sourceLocation);
} }
void Sessions::Deleter::operator()(sqlite3_session *session) void Sessions::Deleter::operator()(sqlite3_session *session)

View File

@@ -15,13 +15,15 @@ namespace Internal {
class SQLITE_EXPORT SessionsBase class SQLITE_EXPORT SessionsBase
{ {
public: public:
SessionsBase(Database &database, Utils::SmallStringView sessionsTableName) SessionsBase(Database &database,
Utils::SmallStringView sessionsTableName,
const source_location &sourceLocation)
: sessionsTableName(sessionsTableName) : sessionsTableName(sessionsTableName)
{ {
createSessionTable(database); createSessionTable(database, sourceLocation);
} }
void createSessionTable(Database &database); void createSessionTable(Database &database, const source_location &sourceLocation);
public: public:
Utils::SmallString sessionsTableName; Utils::SmallString sessionsTableName;
@@ -33,31 +35,33 @@ class SQLITE_EXPORT Sessions : public Internal::SessionsBase
public: public:
Sessions(Database &database, Sessions(Database &database,
Utils::SmallStringView databaseName, Utils::SmallStringView databaseName,
Utils::SmallStringView sessionsTableName) Utils::SmallStringView sessionsTableName,
: SessionsBase(database, sessionsTableName) const source_location &sourceLocation = source_location::current())
: SessionsBase(database, sessionsTableName, sourceLocation)
, database(database) , database(database)
, insertSession{Utils::PathString::join( , insertSession{Utils::PathString::join(
{"INSERT INTO ", sessionsTableName, "(changeset) VALUES(?)"}), {"INSERT INTO ", sessionsTableName, "(changeset) VALUES(?)"}),
database} database,
sourceLocation}
, databaseName(databaseName) , databaseName(databaseName)
{} {}
~Sessions(); ~Sessions();
void setAttachedTables(Utils::SmallStringVector tables); void setAttachedTables(Utils::SmallStringVector tables);
void create(); void create(const source_location &sourceLocation = source_location::current());
void commit(); void commit(const source_location &sourceLocation = source_location::current());
void rollback(); void rollback();
void revert(); void revert(const source_location &sourceLocation = source_location::current());
void apply(); void apply(const source_location &sourceLocation = source_location::current());
void applyAndUpdateSessions(); void applyAndUpdateSessions(const source_location &sourceLocation = source_location::current());
void deleteAll(); void deleteAll(const source_location &sourceLocation = source_location::current());
SessionChangeSets changeSets() const; SessionChangeSets changeSets(const source_location &sourceLocation = source_location::current()) const;
private: private:
void attachTables(const Utils::SmallStringVector &tables); void attachTables(const Utils::SmallStringVector &tables, const source_location &sourceLocation);
struct Deleter struct Deleter
{ {

View File

@@ -136,8 +136,9 @@ public:
return m_isReady; return m_isReady;
} }
template <typename Database> template<typename Database>
void initialize(Database &database) void initialize(Database &database,
const source_location &sourceLocation = source_location::current())
{ {
CreateTableSqlStatementBuilder<ColumnType> builder; CreateTableSqlStatementBuilder<ColumnType> builder;
@@ -148,17 +149,18 @@ public:
builder.setColumns(m_sqliteColumns); builder.setColumns(m_sqliteColumns);
builder.setConstraints(m_tableConstraints); builder.setConstraints(m_tableConstraints);
database.execute(builder.sqlStatement()); database.execute(builder.sqlStatement(), sourceLocation);
initializeIndices(database); initializeIndices(database, sourceLocation);
m_isReady = true; m_isReady = true;
} }
template <typename Database>
void initializeIndices(Database &database) template<typename Database>
void initializeIndices(Database &database, const source_location &sourceLocation)
{ {
for (const Index &index : m_sqliteIndices) for (const Index &index : m_sqliteIndices)
database.execute(index.sqlStatement()); database.execute(index.sqlStatement(), sourceLocation);
} }
friend bool operator==(const BasicTable &first, const BasicTable &second) friend bool operator==(const BasicTable &first, const BasicTable &second)

View File

@@ -3,6 +3,7 @@
#pragma once #pragma once
#include "sourcelocation.h"
#include "sqliteglobal.h" #include "sqliteglobal.h"
#include <utils/smallstringview.h> #include <utils/smallstringview.h>
@@ -22,16 +23,16 @@ public:
TransactionInterface(const TransactionInterface &) = delete; TransactionInterface(const TransactionInterface &) = delete;
TransactionInterface &operator=(const TransactionInterface &) = delete; TransactionInterface &operator=(const TransactionInterface &) = delete;
virtual void deferredBegin() = 0; virtual void deferredBegin(const source_location &sourceLocation) = 0;
virtual void immediateBegin() = 0; virtual void immediateBegin(const source_location &sourceLocation) = 0;
virtual void exclusiveBegin() = 0; virtual void exclusiveBegin(const source_location &sourceLocation) = 0;
virtual void commit() = 0; virtual void commit(const source_location &sourceLocation) = 0;
virtual void rollback() = 0; virtual void rollback(const source_location &sourceLocation) = 0;
virtual void lock() = 0; virtual void lock() = 0;
virtual void unlock() = 0; virtual void unlock() = 0;
virtual void immediateSessionBegin() = 0; virtual void immediateSessionBegin(const source_location &sourceLocation) = 0;
virtual void sessionCommit() = 0; virtual void sessionCommit(const source_location &sourceLocation) = 0;
virtual void sessionRollback() = 0; virtual void sessionRollback(const source_location &sourceLocation) = 0;
protected: protected:
~TransactionInterface() = default; ~TransactionInterface() = default;
@@ -46,15 +47,16 @@ public:
AbstractTransaction(const AbstractTransaction &) = delete; AbstractTransaction(const AbstractTransaction &) = delete;
AbstractTransaction &operator=(const AbstractTransaction &) = delete; AbstractTransaction &operator=(const AbstractTransaction &) = delete;
void commit() void commit(const source_location &sourceLocation = source_location::current())
{ {
m_interface.commit(); m_interface.commit(sourceLocation);
m_isAlreadyCommited = true; m_isAlreadyCommited = true;
m_locker.unlock(); m_locker.unlock();
} }
protected: protected:
~AbstractTransaction() = default; ~AbstractTransaction() = default;
AbstractTransaction(TransactionInterface &transactionInterface) AbstractTransaction(TransactionInterface &transactionInterface)
: m_interface(transactionInterface) : m_interface(transactionInterface)
{ {
@@ -94,9 +96,9 @@ public:
AbstractThrowingSessionTransaction(const AbstractThrowingSessionTransaction &) = delete; AbstractThrowingSessionTransaction(const AbstractThrowingSessionTransaction &) = delete;
AbstractThrowingSessionTransaction &operator=(const AbstractThrowingSessionTransaction &) = delete; AbstractThrowingSessionTransaction &operator=(const AbstractThrowingSessionTransaction &) = delete;
void commit() void commit(const source_location &sourceLocation = source_location::current())
{ {
m_interface.sessionCommit(); m_interface.sessionCommit(sourceLocation);
m_isAlreadyCommited = true; m_isAlreadyCommited = true;
m_locker.unlock(); m_locker.unlock();
} }
@@ -105,7 +107,7 @@ public:
{ {
try { try {
if (m_rollback) if (m_rollback)
m_interface.sessionRollback(); m_interface.sessionRollback(m_sourceLocation);
} catch (...) { } catch (...) {
if (!std::uncaught_exceptions()) if (!std::uncaught_exceptions())
throw; throw;
@@ -113,11 +115,14 @@ public:
} }
protected: protected:
AbstractThrowingSessionTransaction(TransactionInterface &transactionInterface) AbstractThrowingSessionTransaction(TransactionInterface &transactionInterface,
: m_interface(transactionInterface) const source_location &sourceLocation)
: m_sourceLocation(sourceLocation)
, m_interface(transactionInterface)
{} {}
protected: protected:
source_location m_sourceLocation;
TransactionInterface &m_interface; TransactionInterface &m_interface;
std::unique_lock<TransactionInterface> m_locker{m_interface}; std::unique_lock<TransactionInterface> m_locker{m_interface};
bool m_isAlreadyCommited = false; bool m_isAlreadyCommited = false;
@@ -136,7 +141,7 @@ public:
{ {
try { try {
if (Base::m_rollback) if (Base::m_rollback)
Base::m_interface.rollback(); Base::m_interface.rollback(m_sourceLocation);
} catch (...) { } catch (...) {
if (!std::uncaught_exceptions()) if (!std::uncaught_exceptions())
throw; throw;
@@ -144,10 +149,15 @@ public:
} }
protected: protected:
AbstractThrowingTransaction(TransactionInterface &transactionInterface) AbstractThrowingTransaction(TransactionInterface &transactionInterface,
const source_location &sourceLocation)
: AbstractTransaction<TransactionInterface>(transactionInterface) : AbstractTransaction<TransactionInterface>(transactionInterface)
, m_sourceLocation(sourceLocation)
{ {
} }
private:
source_location m_sourceLocation;
}; };
template<typename TransactionInterface> template<typename TransactionInterface>
@@ -162,26 +172,33 @@ public:
{ {
try { try {
if (Base::m_rollback) if (Base::m_rollback)
Base::m_interface.rollback(); Base::m_interface.rollback(m_sourceLocation);
} catch (...) { } catch (...) {
} }
} }
protected: protected:
AbstractNonThrowingDestructorTransaction(TransactionInterface &transactionInterface) AbstractNonThrowingDestructorTransaction(TransactionInterface &transactionInterface,
const source_location &sourceLocation)
: AbstractTransaction<TransactionInterface>(transactionInterface) : AbstractTransaction<TransactionInterface>(transactionInterface)
, m_sourceLocation(sourceLocation)
{ {
} }
private:
source_location m_sourceLocation;
}; };
template<typename BaseTransaction> template<typename BaseTransaction>
class BasicDeferredTransaction : public BaseTransaction class BasicDeferredTransaction : public BaseTransaction
{ {
public: public:
BasicDeferredTransaction(typename BaseTransaction::Transaction &transactionInterface) BasicDeferredTransaction(typename BaseTransaction::Transaction &transactionInterface,
: BaseTransaction(transactionInterface) const source_location &sourceLocation = source_location::current())
: BaseTransaction(transactionInterface, sourceLocation)
{ {
transactionInterface.deferredBegin(); transactionInterface.deferredBegin(sourceLocation);
} }
~BasicDeferredTransaction() ~BasicDeferredTransaction()
@@ -201,19 +218,20 @@ public:
}; };
template<typename Transaction, typename TransactionInterface, typename Callable> template<typename Transaction, typename TransactionInterface, typename Callable>
auto withTransaction(TransactionInterface &transactionInterface, Callable &&callable) auto withTransaction(TransactionInterface &transactionInterface,
-> std::invoke_result_t<Callable> Callable &&callable,
const source_location &sourceLocation) -> std::invoke_result_t<Callable>
{ {
Transaction transaction{transactionInterface}; Transaction transaction{transactionInterface, sourceLocation};
if constexpr (std::is_void_v<std::invoke_result_t<Callable>>) { if constexpr (std::is_void_v<std::invoke_result_t<Callable>>) {
callable(); callable();
transaction.commit(); transaction.commit(sourceLocation);
} else { } else {
auto results = callable(); auto results = callable();
transaction.commit(); transaction.commit(sourceLocation);
return results; return results;
} }
@@ -232,18 +250,25 @@ auto withImplicitTransaction(TransactionInterface &transactionInterface, Callabl
} }
template<typename TransactionInterface, typename Callable> template<typename TransactionInterface, typename Callable>
auto withDeferredTransaction(TransactionInterface &transactionInterface, Callable &&callable) auto withDeferredTransaction(TransactionInterface &transactionInterface,
Callable &&callable,
const source_location &sourceLocation = source_location::current())
{ {
if constexpr (std::is_void_v<std::invoke_result_t<Callable>>) { if constexpr (std::is_void_v<std::invoke_result_t<Callable>>) {
withTransaction<DeferredTransaction<TransactionInterface>>(transactionInterface, withTransaction<DeferredTransaction<TransactionInterface>>(transactionInterface,
std::forward<Callable>(callable)); std::forward<Callable>(callable),
sourceLocation);
} else { } else {
return withTransaction<DeferredTransaction<TransactionInterface>>(transactionInterface, return withTransaction<DeferredTransaction<TransactionInterface>>(transactionInterface,
std::forward<Callable>( std::forward<Callable>(
callable)); callable),
sourceLocation);
} }
} }
template<typename TransactionInterface>
DeferredTransaction(TransactionInterface &, const source_location &)
-> DeferredTransaction<TransactionInterface>;
template<typename TransactionInterface> template<typename TransactionInterface>
DeferredTransaction(TransactionInterface &) -> DeferredTransaction<TransactionInterface>; DeferredTransaction(TransactionInterface &) -> DeferredTransaction<TransactionInterface>;
@@ -257,6 +282,9 @@ public:
using Base::Base; using Base::Base;
}; };
template<typename TransactionInterface>
DeferredNonThrowingDestructorTransaction(TransactionInterface &, const source_location &)
-> DeferredNonThrowingDestructorTransaction<TransactionInterface>;
template<typename TransactionInterface> template<typename TransactionInterface>
DeferredNonThrowingDestructorTransaction(TransactionInterface &) DeferredNonThrowingDestructorTransaction(TransactionInterface &)
-> DeferredNonThrowingDestructorTransaction<TransactionInterface>; -> DeferredNonThrowingDestructorTransaction<TransactionInterface>;
@@ -265,10 +293,11 @@ template<typename BaseTransaction>
class BasicImmediateTransaction : public BaseTransaction class BasicImmediateTransaction : public BaseTransaction
{ {
public: public:
BasicImmediateTransaction(typename BaseTransaction::Transaction &transactionInterface) BasicImmediateTransaction(typename BaseTransaction::Transaction &transactionInterface,
: BaseTransaction(transactionInterface) const source_location &sourceLocation = source_location::current())
: BaseTransaction(transactionInterface, sourceLocation)
{ {
transactionInterface.immediateBegin(); transactionInterface.immediateBegin(sourceLocation);
} }
~BasicImmediateTransaction() ~BasicImmediateTransaction()
@@ -288,19 +317,25 @@ public:
}; };
template<typename TransactionInterface, typename Callable> template<typename TransactionInterface, typename Callable>
auto withImmediateTransaction(TransactionInterface &transactionInterface, Callable &&callable) auto withImmediateTransaction(TransactionInterface &transactionInterface,
Callable &&callable,
const source_location &sourceLocation = source_location::current())
{ {
if constexpr (std::is_void_v<std::invoke_result_t<Callable>>) { if constexpr (std::is_void_v<std::invoke_result_t<Callable>>) {
withTransaction<ImmediateTransaction<TransactionInterface>>(transactionInterface, withTransaction<ImmediateTransaction<TransactionInterface>>(transactionInterface,
std::forward<Callable>( std::forward<Callable>(callable),
callable)); sourceLocation);
} else { } else {
return withTransaction<ImmediateTransaction<TransactionInterface>>(transactionInterface, return withTransaction<ImmediateTransaction<TransactionInterface>>(transactionInterface,
std::forward<Callable>( std::forward<Callable>(
callable)); callable),
sourceLocation);
} }
} }
template<typename TransactionInterface>
ImmediateTransaction(TransactionInterface &, const source_location &)
-> ImmediateTransaction<TransactionInterface>;
template<typename TransactionInterface> template<typename TransactionInterface>
ImmediateTransaction(TransactionInterface &) -> ImmediateTransaction<TransactionInterface>; ImmediateTransaction(TransactionInterface &) -> ImmediateTransaction<TransactionInterface>;
@@ -314,6 +349,9 @@ public:
using Base::Base; using Base::Base;
}; };
template<typename TransactionInterface>
ImmediateNonThrowingDestructorTransaction(TransactionInterface &, const source_location &)
-> ImmediateNonThrowingDestructorTransaction<TransactionInterface>;
template<typename TransactionInterface> template<typename TransactionInterface>
ImmediateNonThrowingDestructorTransaction(TransactionInterface &) ImmediateNonThrowingDestructorTransaction(TransactionInterface &)
-> ImmediateNonThrowingDestructorTransaction<TransactionInterface>; -> ImmediateNonThrowingDestructorTransaction<TransactionInterface>;
@@ -322,10 +360,11 @@ template<typename BaseTransaction>
class BasicExclusiveTransaction : public BaseTransaction class BasicExclusiveTransaction : public BaseTransaction
{ {
public: public:
BasicExclusiveTransaction(typename BaseTransaction::Transaction &transactionInterface) BasicExclusiveTransaction(typename BaseTransaction::Transaction &transactionInterface,
: BaseTransaction(transactionInterface) const source_location &sourceLocation = source_location::current())
: BaseTransaction(transactionInterface, sourceLocation)
{ {
transactionInterface.exclusiveBegin(); transactionInterface.exclusiveBegin(sourceLocation);
} }
~BasicExclusiveTransaction() ~BasicExclusiveTransaction()
@@ -344,6 +383,9 @@ public:
using Base::Base; using Base::Base;
}; };
template<typename TransactionInterface>
ExclusiveTransaction(TransactionInterface &, const source_location &)
-> ExclusiveTransaction<TransactionInterface>;
template<typename TransactionInterface> template<typename TransactionInterface>
ExclusiveTransaction(TransactionInterface &) -> ExclusiveTransaction<TransactionInterface>; ExclusiveTransaction(TransactionInterface &) -> ExclusiveTransaction<TransactionInterface>;
@@ -357,6 +399,9 @@ public:
using Base::Base; using Base::Base;
}; };
template<typename TransactionInterface>
ExclusiveNonThrowingDestructorTransaction(TransactionInterface &, const source_location &)
-> ExclusiveNonThrowingDestructorTransaction<TransactionInterface>;
template<typename TransactionInterface> template<typename TransactionInterface>
ExclusiveNonThrowingDestructorTransaction(TransactionInterface &) ExclusiveNonThrowingDestructorTransaction(TransactionInterface &)
-> ExclusiveNonThrowingDestructorTransaction<TransactionInterface>; -> ExclusiveNonThrowingDestructorTransaction<TransactionInterface>;
@@ -368,17 +413,20 @@ class ImmediateSessionTransaction final
using Base = AbstractThrowingSessionTransaction<TransactionInterface>; using Base = AbstractThrowingSessionTransaction<TransactionInterface>;
public: public:
ImmediateSessionTransaction(typename Base::Transaction &transactionInterface) ImmediateSessionTransaction(typename Base::Transaction &transactionInterface,
: AbstractThrowingSessionTransaction<TransactionInterface>(transactionInterface) const source_location &sourceLocation = source_location::current())
: AbstractThrowingSessionTransaction<TransactionInterface>(transactionInterface, sourceLocation)
{ {
transactionInterface.immediateSessionBegin(); transactionInterface.immediateSessionBegin(sourceLocation);
} }
~ImmediateSessionTransaction() { Base::m_rollback = !Base::m_isAlreadyCommited; } ~ImmediateSessionTransaction() { Base::m_rollback = !Base::m_isAlreadyCommited; }
}; };
template<typename TransactionInterface>
ImmediateSessionTransaction(TransactionInterface &, const source_location &)
-> ImmediateSessionTransaction<TransactionInterface>;
template<typename TransactionInterface> template<typename TransactionInterface>
ImmediateSessionTransaction(TransactionInterface &) ImmediateSessionTransaction(TransactionInterface &)
-> ImmediateSessionTransaction<TransactionInterface>; -> ImmediateSessionTransaction<TransactionInterface>;
} // namespace Sqlite } // namespace Sqlite

View File

@@ -12,12 +12,14 @@ class WriteStatement : protected StatementImplementation<BaseStatement, -1, Bind
using Base = StatementImplementation<BaseStatement, -1, BindParameterCount>; using Base = StatementImplementation<BaseStatement, -1, BindParameterCount>;
public: public:
WriteStatement(Utils::SmallStringView sqlStatement, Database &database) WriteStatement(Utils::SmallStringView sqlStatement,
: Base(sqlStatement, database) Database &database,
const source_location &sourceLocation = source_location::current())
: Base(sqlStatement, database, sourceLocation)
{ {
checkIsWritableStatement(); checkIsWritableStatement(sourceLocation);
Base::checkBindingParameterCount(BindParameterCount); Base::checkBindingParameterCount(BindParameterCount, sourceLocation);
Base::checkColumnCount(0); Base::checkColumnCount(0, sourceLocation);
} }
using Base::database; using Base::database;
@@ -25,10 +27,10 @@ public:
using Base::write; using Base::write;
protected: protected:
void checkIsWritableStatement() void checkIsWritableStatement(const source_location &sourceLocation)
{ {
if (Base::isReadOnlyStatement()) if (Base::isReadOnlyStatement())
throw NotWriteSqlStatement(); throw NotWriteSqlStatement(sourceLocation);
} }
}; };

View File

@@ -11,6 +11,9 @@
namespace QmlDesigner { namespace QmlDesigner {
namespace { namespace {
constexpr auto sourceLocation = Sqlite::source_location::current();
struct Initializer struct Initializer
{ {
Initializer(Sqlite::Database &database, bool isInitialized) Initializer(Sqlite::Database &database, bool isInitialized)
@@ -34,7 +37,7 @@ struct Initializer
table.addPrimaryKeyContraint({filePathColumn, idColumn, keyColumn}); table.addPrimaryKeyContraint({filePathColumn, idColumn, keyColumn});
table.initialize(database); table.initialize(database, sourceLocation);
} }
}; };

View File

@@ -2267,7 +2267,7 @@ SmallSourceIds<32> ProjectStorage::fetchSubdirectorySourceIds(SourceId directory
void ProjectStorage::setPropertyEditorPathId(TypeId typeId, SourceId pathId) void ProjectStorage::setPropertyEditorPathId(TypeId typeId, SourceId pathId)
{ {
Sqlite::ImmediateSessionTransaction transaction{database}; Sqlite::ImmediateTransaction transaction{database};
s->upsertPropertyEditorPathIdStatement.write(typeId, pathId); s->upsertPropertyEditorPathIdStatement.write(typeId, pathId);

View File

@@ -19,8 +19,8 @@ public:
: m_databaseMock{&databaseMock} : m_databaseMock{&databaseMock}
{} {}
MOCK_METHOD0(next, bool()); MOCK_METHOD(bool, next, (const Sqlite::source_location &sourceLocation));
MOCK_METHOD0(step, void ()); MOCK_METHOD(void, step, (const Sqlite::source_location &sourceLocation));
MOCK_METHOD0(reset, void ()); MOCK_METHOD0(reset, void ());
MOCK_CONST_METHOD1(fetchIntValue, int (int)); MOCK_CONST_METHOD1(fetchIntValue, int (int));
@@ -35,16 +35,20 @@ public:
template<typename Type> template<typename Type>
Type fetchValue(int column) const; Type fetchValue(int column) const;
MOCK_METHOD2(bind, void (int, int)); MOCK_METHOD(void, bind, (int, int, const Sqlite::source_location &sourceLocation));
MOCK_METHOD2(bind, void (int, long long)); MOCK_METHOD(void, bind, (int, long long, const Sqlite::source_location &sourceLocation));
MOCK_METHOD2(bind, void (int, double)); MOCK_METHOD(void, bind, (int, double, const Sqlite::source_location &sourceLocation));
MOCK_METHOD2(bind, void (int, Utils::SmallStringView)); MOCK_METHOD(void,
MOCK_METHOD2(bind, void (int, long)); bind,
(int, Utils::SmallStringView, const Sqlite::source_location &sourceLocation));
MOCK_METHOD(void, bind, (int, long, const Sqlite::source_location &sourceLocation));
MOCK_METHOD1(prepare, void(Utils::SmallStringView sqlStatement)); MOCK_METHOD(void,
prepare,
(Utils::SmallStringView sqlStatement, const Sqlite::source_location &sourceLocation));
MOCK_METHOD1(checkColumnCount, void(int)); MOCK_METHOD(void, checkColumnCount, (int, const Sqlite::source_location &sourceLocation));
MOCK_METHOD1(checkBindingParameterCount, void(int)); MOCK_METHOD(void, checkBindingParameterCount, (int, const Sqlite::source_location &sourceLocation));
MOCK_CONST_METHOD0(isReadOnlyStatement, bool()); MOCK_CONST_METHOD0(isReadOnlyStatement, bool());

View File

@@ -11,14 +11,14 @@
class MockSqliteTransactionBackend : public Sqlite::TransactionInterface class MockSqliteTransactionBackend : public Sqlite::TransactionInterface
{ {
public: public:
MOCK_METHOD0(deferredBegin, void ()); MOCK_METHOD(void, deferredBegin, (const Sqlite::source_location &sourceLocation));
MOCK_METHOD0(immediateBegin, void ()); MOCK_METHOD(void, immediateBegin, (const Sqlite::source_location &sourceLocation));
MOCK_METHOD0(exclusiveBegin, void ()); MOCK_METHOD(void, exclusiveBegin, (const Sqlite::source_location &sourceLocation));
MOCK_METHOD0(commit, void ()); MOCK_METHOD(void, commit, (const Sqlite::source_location &sourceLocation));
MOCK_METHOD0(rollback, void ()); MOCK_METHOD(void, rollback, (const Sqlite::source_location &sourceLocation));
MOCK_METHOD0(lock, void ()); MOCK_METHOD(void, lock, ());
MOCK_METHOD0(unlock, void ()); MOCK_METHOD(void, unlock, ());
MOCK_METHOD0(immediateSessionBegin, void()); MOCK_METHOD(void, immediateSessionBegin, (const Sqlite::source_location &sourceLocation));
MOCK_METHOD0(sessionCommit, void()); MOCK_METHOD(void, sessionCommit, (const Sqlite::source_location &sourceLocation));
MOCK_METHOD0(sessionRollback, void()); MOCK_METHOD(void, sessionRollback, (const Sqlite::source_location &sourceLocation));
}; };

View File

@@ -28,7 +28,15 @@ public:
MOCK_METHOD(void, prepare, (Utils::SmallStringView sqlStatement), ()); MOCK_METHOD(void, prepare, (Utils::SmallStringView sqlStatement), ());
MOCK_METHOD(void, execute, (Utils::SmallStringView sqlStatement), (override)); MOCK_METHOD(void,
execute,
(Utils::SmallStringView sqlStatement, const Sqlite::source_location &sourceLocation),
(override));
void execute(Utils::SmallStringView sqlStatement)
{
execute(sqlStatement, Sqlite::source_location::current());
}
MOCK_METHOD(int64_t, lastInsertedRowId, (), (const)); MOCK_METHOD(int64_t, lastInsertedRowId, (), (const));
@@ -41,7 +49,9 @@ public:
MOCK_METHOD(void, setIsInitialized, (bool), ()); MOCK_METHOD(void, setIsInitialized, (bool), ());
MOCK_METHOD(void, walCheckpointFull, (), (override)); MOCK_METHOD(void, walCheckpointFull, (const Sqlite::source_location &sourceLocation), (override));
void walCheckpointFull() { walCheckpointFull(Sqlite::source_location::current()); }
MOCK_METHOD(void, MOCK_METHOD(void,
setUpdateHook, setUpdateHook,

View File

@@ -11,14 +11,14 @@
class SqliteTransactionBackendMock : public Sqlite::TransactionInterface class SqliteTransactionBackendMock : public Sqlite::TransactionInterface
{ {
public: public:
MOCK_METHOD(void, deferredBegin, (), (override)); MOCK_METHOD(void, deferredBegin, (const Sqlite::source_location &sourceLocation), (override));
MOCK_METHOD(void, immediateBegin, (), (override)); MOCK_METHOD(void, immediateBegin, (const Sqlite::source_location &sourceLocation), (override));
MOCK_METHOD(void, exclusiveBegin, (), (override)); MOCK_METHOD(void, exclusiveBegin, (const Sqlite::source_location &sourceLocation), (override));
MOCK_METHOD(void, commit, (), (override)); MOCK_METHOD(void, commit, (const Sqlite::source_location &sourceLocation), (override));
MOCK_METHOD(void, rollback, (), (override)); MOCK_METHOD(void, rollback, (const Sqlite::source_location &sourceLocation), (override));
MOCK_METHOD(void, lock, (), (override)); MOCK_METHOD(void, lock, (), (override));
MOCK_METHOD(void, unlock, (), (override)); MOCK_METHOD(void, unlock, (), (override));
MOCK_METHOD(void, immediateSessionBegin, (), (override)); MOCK_METHOD(void, immediateSessionBegin, (const Sqlite::source_location &sourceLocation), (override));
MOCK_METHOD(void, sessionCommit, (), (override)); MOCK_METHOD(void, sessionCommit, (const Sqlite::source_location &sourceLocation), (override));
MOCK_METHOD(void, sessionRollback, (), (override)); MOCK_METHOD(void, sessionRollback, (const Sqlite::source_location &sourceLocation), (override));
}; };

View File

@@ -29,9 +29,9 @@ TEST(ImageCacheStorageUpdateTest, add_column_mid_size_if_version_is_zero)
{ {
NiceMock<SqliteDatabaseMock> databaseMock; NiceMock<SqliteDatabaseMock> databaseMock;
ON_CALL(databaseMock, isInitialized()).WillByDefault(Return(true)); ON_CALL(databaseMock, isInitialized()).WillByDefault(Return(true));
EXPECT_CALL(databaseMock, execute(_)).Times(AnyNumber()); EXPECT_CALL(databaseMock, execute(_, _)).Times(AnyNumber());
EXPECT_CALL(databaseMock, execute(Eq("ALTER TABLE images ADD COLUMN midSizeImage"))); EXPECT_CALL(databaseMock, execute(Eq("ALTER TABLE images ADD COLUMN midSizeImage"), _));
QmlDesigner::ImageCacheStorage<SqliteDatabaseMock> storage{databaseMock}; QmlDesigner::ImageCacheStorage<SqliteDatabaseMock> storage{databaseMock};
} }
@@ -42,8 +42,8 @@ TEST(ImageCacheStorageUpdateTest, delete_all_rows_before_adding_mid_size_column)
ON_CALL(databaseMock, isInitialized()).WillByDefault(Return(true)); ON_CALL(databaseMock, isInitialized()).WillByDefault(Return(true));
InSequence s; InSequence s;
EXPECT_CALL(databaseMock, execute(Eq("DELETE FROM images"))); EXPECT_CALL(databaseMock, execute(Eq("DELETE FROM images"), _));
EXPECT_CALL(databaseMock, execute(Eq("ALTER TABLE images ADD COLUMN midSizeImage"))); EXPECT_CALL(databaseMock, execute(Eq("ALTER TABLE images ADD COLUMN midSizeImage"), _));
QmlDesigner::ImageCacheStorage<SqliteDatabaseMock> storage{databaseMock}; QmlDesigner::ImageCacheStorage<SqliteDatabaseMock> storage{databaseMock};
} }
@@ -52,9 +52,9 @@ TEST(ImageCacheStorageUpdateTest, dont_call_add_column_mid_size_if_database_was_
{ {
NiceMock<SqliteDatabaseMock> databaseMock; NiceMock<SqliteDatabaseMock> databaseMock;
ON_CALL(databaseMock, isInitialized()).WillByDefault(Return(false)); ON_CALL(databaseMock, isInitialized()).WillByDefault(Return(false));
EXPECT_CALL(databaseMock, execute(_)).Times(2); EXPECT_CALL(databaseMock, execute(_, _)).Times(2);
EXPECT_CALL(databaseMock, execute(Eq("ALTER TABLE images ADD COLUMN midSizeImage"))).Times(0); EXPECT_CALL(databaseMock, execute(Eq("ALTER TABLE images ADD COLUMN midSizeImage"), _)).Times(0);
QmlDesigner::ImageCacheStorage<SqliteDatabaseMock> storage{databaseMock}; QmlDesigner::ImageCacheStorage<SqliteDatabaseMock> storage{databaseMock};
} }
@@ -118,11 +118,11 @@ TEST_F(ImageCacheStorageTest, fetch_image_calls)
{ {
InSequence s; InSequence s;
EXPECT_CALL(databaseMock, deferredBegin()); EXPECT_CALL(databaseMock, deferredBegin(_));
EXPECT_CALL(selectImageStatement, EXPECT_CALL(selectImageStatement,
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"), valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
TypedEq<long long>(123))); TypedEq<long long>(123)));
EXPECT_CALL(databaseMock, commit()); EXPECT_CALL(databaseMock, commit(_));
storage.fetchImage("/path/to/component", {123}); storage.fetchImage("/path/to/component", {123});
} }
@@ -131,17 +131,17 @@ TEST_F(ImageCacheStorageTest, fetch_image_calls_is_busy)
{ {
InSequence s; InSequence s;
EXPECT_CALL(databaseMock, deferredBegin()); EXPECT_CALL(databaseMock, deferredBegin(_));
EXPECT_CALL(selectImageStatement, EXPECT_CALL(selectImageStatement,
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"), valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
TypedEq<long long>(123))) TypedEq<long long>(123)))
.WillOnce(Throw(Sqlite::StatementIsBusy("busy"))); .WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
EXPECT_CALL(databaseMock, rollback()); EXPECT_CALL(databaseMock, rollback(_));
EXPECT_CALL(databaseMock, deferredBegin()); EXPECT_CALL(databaseMock, deferredBegin(_));
EXPECT_CALL(selectImageStatement, EXPECT_CALL(selectImageStatement,
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"), valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
TypedEq<long long>(123))); TypedEq<long long>(123)));
EXPECT_CALL(databaseMock, commit()); EXPECT_CALL(databaseMock, commit(_));
storage.fetchImage("/path/to/component", {123}); storage.fetchImage("/path/to/component", {123});
} }
@@ -150,11 +150,11 @@ TEST_F(ImageCacheStorageTest, fetch_mid_size_image_calls)
{ {
InSequence s; InSequence s;
EXPECT_CALL(databaseMock, deferredBegin()); EXPECT_CALL(databaseMock, deferredBegin(_));
EXPECT_CALL(selectMidSizeImageStatement, EXPECT_CALL(selectMidSizeImageStatement,
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"), valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
TypedEq<long long>(123))); TypedEq<long long>(123)));
EXPECT_CALL(databaseMock, commit()); EXPECT_CALL(databaseMock, commit(_));
storage.fetchMidSizeImage("/path/to/component", {123}); storage.fetchMidSizeImage("/path/to/component", {123});
} }
@@ -163,17 +163,17 @@ TEST_F(ImageCacheStorageTest, fetch_mid_size_image_calls_is_busy)
{ {
InSequence s; InSequence s;
EXPECT_CALL(databaseMock, deferredBegin()); EXPECT_CALL(databaseMock, deferredBegin(_));
EXPECT_CALL(selectMidSizeImageStatement, EXPECT_CALL(selectMidSizeImageStatement,
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"), valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
TypedEq<long long>(123))) TypedEq<long long>(123)))
.WillOnce(Throw(Sqlite::StatementIsBusy("busy"))); .WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
EXPECT_CALL(databaseMock, rollback()); EXPECT_CALL(databaseMock, rollback(_));
EXPECT_CALL(databaseMock, deferredBegin()); EXPECT_CALL(databaseMock, deferredBegin(_));
EXPECT_CALL(selectMidSizeImageStatement, EXPECT_CALL(selectMidSizeImageStatement,
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"), valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
TypedEq<long long>(123))); TypedEq<long long>(123)));
EXPECT_CALL(databaseMock, commit()); EXPECT_CALL(databaseMock, commit(_));
storage.fetchMidSizeImage("/path/to/component", {123}); storage.fetchMidSizeImage("/path/to/component", {123});
} }
@@ -182,11 +182,11 @@ TEST_F(ImageCacheStorageTest, fetch_small_image_calls)
{ {
InSequence s; InSequence s;
EXPECT_CALL(databaseMock, deferredBegin()); EXPECT_CALL(databaseMock, deferredBegin(_));
EXPECT_CALL(selectSmallImageStatement, EXPECT_CALL(selectSmallImageStatement,
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"), valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
TypedEq<long long>(123))); TypedEq<long long>(123)));
EXPECT_CALL(databaseMock, commit()); EXPECT_CALL(databaseMock, commit(_));
storage.fetchSmallImage("/path/to/component", {123}); storage.fetchSmallImage("/path/to/component", {123});
} }
@@ -195,17 +195,17 @@ TEST_F(ImageCacheStorageTest, fetch_small_image_calls_is_busy)
{ {
InSequence s; InSequence s;
EXPECT_CALL(databaseMock, deferredBegin()); EXPECT_CALL(databaseMock, deferredBegin(_));
EXPECT_CALL(selectSmallImageStatement, EXPECT_CALL(selectSmallImageStatement,
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"), valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
TypedEq<long long>(123))) TypedEq<long long>(123)))
.WillOnce(Throw(Sqlite::StatementIsBusy("busy"))); .WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
EXPECT_CALL(databaseMock, rollback()); EXPECT_CALL(databaseMock, rollback(_));
EXPECT_CALL(databaseMock, deferredBegin()); EXPECT_CALL(databaseMock, deferredBegin(_));
EXPECT_CALL(selectSmallImageStatement, EXPECT_CALL(selectSmallImageStatement,
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"), valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
TypedEq<long long>(123))); TypedEq<long long>(123)));
EXPECT_CALL(databaseMock, commit()); EXPECT_CALL(databaseMock, commit(_));
storage.fetchSmallImage("/path/to/component", {123}); storage.fetchSmallImage("/path/to/component", {123});
} }
@@ -214,11 +214,11 @@ TEST_F(ImageCacheStorageTest, fetch_icon_calls)
{ {
InSequence s; InSequence s;
EXPECT_CALL(databaseMock, deferredBegin()); EXPECT_CALL(databaseMock, deferredBegin(_));
EXPECT_CALL(selectIconStatement, EXPECT_CALL(selectIconStatement,
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"), valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
TypedEq<long long>(123))); TypedEq<long long>(123)));
EXPECT_CALL(databaseMock, commit()); EXPECT_CALL(databaseMock, commit(_));
storage.fetchIcon("/path/to/component", {123}); storage.fetchIcon("/path/to/component", {123});
} }
@@ -227,17 +227,17 @@ TEST_F(ImageCacheStorageTest, fetch_icon_calls_is_busy)
{ {
InSequence s; InSequence s;
EXPECT_CALL(databaseMock, deferredBegin()); EXPECT_CALL(databaseMock, deferredBegin(_));
EXPECT_CALL(selectIconStatement, EXPECT_CALL(selectIconStatement,
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"), valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
TypedEq<long long>(123))) TypedEq<long long>(123)))
.WillOnce(Throw(Sqlite::StatementIsBusy("busy"))); .WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
EXPECT_CALL(databaseMock, rollback()); EXPECT_CALL(databaseMock, rollback(_));
EXPECT_CALL(databaseMock, deferredBegin()); EXPECT_CALL(databaseMock, deferredBegin(_));
EXPECT_CALL(selectIconStatement, EXPECT_CALL(selectIconStatement,
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"), valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
TypedEq<long long>(123))); TypedEq<long long>(123)));
EXPECT_CALL(databaseMock, commit()); EXPECT_CALL(databaseMock, commit(_));
storage.fetchIcon("/path/to/component", {123}); storage.fetchIcon("/path/to/component", {123});
} }
@@ -246,14 +246,14 @@ TEST_F(ImageCacheStorageTest, store_image_calls)
{ {
InSequence s; InSequence s;
EXPECT_CALL(databaseMock, immediateBegin()); EXPECT_CALL(databaseMock, immediateBegin(_));
EXPECT_CALL(upsertImageStatement, EXPECT_CALL(upsertImageStatement,
write(TypedEq<Utils::SmallStringView>("/path/to/component"), write(TypedEq<Utils::SmallStringView>("/path/to/component"),
TypedEq<long long>(123), TypedEq<long long>(123),
Not(IsEmpty()), Not(IsEmpty()),
Not(IsEmpty()), Not(IsEmpty()),
Not(IsEmpty()))); Not(IsEmpty())));
EXPECT_CALL(databaseMock, commit()); EXPECT_CALL(databaseMock, commit(_));
storage.storeImage("/path/to/component", {123}, image1, midSizeImage1, smallImage1); storage.storeImage("/path/to/component", {123}, image1, midSizeImage1, smallImage1);
} }
@@ -262,14 +262,14 @@ TEST_F(ImageCacheStorageTest, store_empty_image_calls)
{ {
InSequence s; InSequence s;
EXPECT_CALL(databaseMock, immediateBegin()); EXPECT_CALL(databaseMock, immediateBegin(_));
EXPECT_CALL(upsertImageStatement, EXPECT_CALL(upsertImageStatement,
write(TypedEq<Utils::SmallStringView>("/path/to/component"), write(TypedEq<Utils::SmallStringView>("/path/to/component"),
TypedEq<long long>(123), TypedEq<long long>(123),
IsEmpty(), IsEmpty(),
IsEmpty(), IsEmpty(),
IsEmpty())); IsEmpty()));
EXPECT_CALL(databaseMock, commit()); EXPECT_CALL(databaseMock, commit(_));
storage.storeImage("/path/to/component", {123}, QImage{}, QImage{}, QImage{}); storage.storeImage("/path/to/component", {123}, QImage{}, QImage{}, QImage{});
} }
@@ -278,15 +278,15 @@ TEST_F(ImageCacheStorageTest, store_image_calls_is_busy)
{ {
InSequence s; InSequence s;
EXPECT_CALL(databaseMock, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy"))); EXPECT_CALL(databaseMock, immediateBegin(_)).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
EXPECT_CALL(databaseMock, immediateBegin()); EXPECT_CALL(databaseMock, immediateBegin(_));
EXPECT_CALL(upsertImageStatement, EXPECT_CALL(upsertImageStatement,
write(TypedEq<Utils::SmallStringView>("/path/to/component"), write(TypedEq<Utils::SmallStringView>("/path/to/component"),
TypedEq<long long>(123), TypedEq<long long>(123),
IsEmpty(), IsEmpty(),
IsEmpty(), IsEmpty(),
IsEmpty())); IsEmpty()));
EXPECT_CALL(databaseMock, commit()); EXPECT_CALL(databaseMock, commit(_));
storage.storeImage("/path/to/component", {123}, QImage{}, QImage{}, QImage{}); storage.storeImage("/path/to/component", {123}, QImage{}, QImage{}, QImage{});
} }
@@ -295,12 +295,12 @@ TEST_F(ImageCacheStorageTest, store_icon_calls)
{ {
InSequence s; InSequence s;
EXPECT_CALL(databaseMock, immediateBegin()); EXPECT_CALL(databaseMock, immediateBegin(_));
EXPECT_CALL(upsertIconStatement, EXPECT_CALL(upsertIconStatement,
write(TypedEq<Utils::SmallStringView>("/path/to/component"), write(TypedEq<Utils::SmallStringView>("/path/to/component"),
TypedEq<long long>(123), TypedEq<long long>(123),
A<Sqlite::BlobView>())); A<Sqlite::BlobView>()));
EXPECT_CALL(databaseMock, commit()); EXPECT_CALL(databaseMock, commit(_));
storage.storeIcon("/path/to/component", {123}, icon1); storage.storeIcon("/path/to/component", {123}, icon1);
} }
@@ -309,12 +309,12 @@ TEST_F(ImageCacheStorageTest, store_empty_icon_calls)
{ {
InSequence s; InSequence s;
EXPECT_CALL(databaseMock, immediateBegin()); EXPECT_CALL(databaseMock, immediateBegin(_));
EXPECT_CALL(upsertIconStatement, EXPECT_CALL(upsertIconStatement,
write(TypedEq<Utils::SmallStringView>("/path/to/component"), write(TypedEq<Utils::SmallStringView>("/path/to/component"),
TypedEq<long long>(123), TypedEq<long long>(123),
IsEmpty())); IsEmpty()));
EXPECT_CALL(databaseMock, commit()); EXPECT_CALL(databaseMock, commit(_));
storage.storeIcon("/path/to/component", {123}, QIcon{}); storage.storeIcon("/path/to/component", {123}, QIcon{});
} }
@@ -323,20 +323,20 @@ TEST_F(ImageCacheStorageTest, store_icon_calls_is_busy)
{ {
InSequence s; InSequence s;
EXPECT_CALL(databaseMock, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy"))); EXPECT_CALL(databaseMock, immediateBegin(_)).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
EXPECT_CALL(databaseMock, immediateBegin()); EXPECT_CALL(databaseMock, immediateBegin(_));
EXPECT_CALL(upsertIconStatement, EXPECT_CALL(upsertIconStatement,
write(TypedEq<Utils::SmallStringView>("/path/to/component"), write(TypedEq<Utils::SmallStringView>("/path/to/component"),
TypedEq<long long>(123), TypedEq<long long>(123),
IsEmpty())); IsEmpty()));
EXPECT_CALL(databaseMock, commit()); EXPECT_CALL(databaseMock, commit(_));
storage.storeIcon("/path/to/component", {123}, QIcon{}); storage.storeIcon("/path/to/component", {123}, QIcon{});
} }
TEST_F(ImageCacheStorageTest, call_wal_checkoint_full) TEST_F(ImageCacheStorageTest, call_wal_checkoint_full)
{ {
EXPECT_CALL(databaseMock, walCheckpointFull()); EXPECT_CALL(databaseMock, walCheckpointFull(_));
storage.walCheckpointFull(); storage.walCheckpointFull();
} }
@@ -345,8 +345,8 @@ TEST_F(ImageCacheStorageTest, call_wal_checkoint_full_is_busy)
{ {
InSequence s; InSequence s;
EXPECT_CALL(databaseMock, walCheckpointFull()).WillOnce(Throw(Sqlite::StatementIsBusy("busy"))); EXPECT_CALL(databaseMock, walCheckpointFull(_)).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
EXPECT_CALL(databaseMock, walCheckpointFull()); EXPECT_CALL(databaseMock, walCheckpointFull(_));
storage.walCheckpointFull(); storage.walCheckpointFull();
} }

View File

@@ -26,6 +26,8 @@ using Sqlite::JournalMode;
using Sqlite::OpenMode; using Sqlite::OpenMode;
using Sqlite::Table; using Sqlite::Table;
constexpr auto sourceLocation = Sqlite::source_location::current();
class SqliteDatabase : public ::testing::Test class SqliteDatabase : public ::testing::Test
{ {
protected: protected:
@@ -199,37 +201,37 @@ TEST_F(SqliteDatabase, last_row_id)
TEST_F(SqliteDatabase, deferred_begin) TEST_F(SqliteDatabase, deferred_begin)
{ {
ASSERT_NO_THROW(transactionInterface.deferredBegin()); ASSERT_NO_THROW(transactionInterface.deferredBegin(sourceLocation));
transactionInterface.commit(); transactionInterface.commit(sourceLocation);
} }
TEST_F(SqliteDatabase, immediate_begin) TEST_F(SqliteDatabase, immediate_begin)
{ {
ASSERT_NO_THROW(transactionInterface.immediateBegin()); ASSERT_NO_THROW(transactionInterface.immediateBegin(sourceLocation));
transactionInterface.commit(); transactionInterface.commit(sourceLocation);
} }
TEST_F(SqliteDatabase, exclusive_begin) TEST_F(SqliteDatabase, exclusive_begin)
{ {
ASSERT_NO_THROW(transactionInterface.exclusiveBegin()); ASSERT_NO_THROW(transactionInterface.exclusiveBegin(sourceLocation));
transactionInterface.commit(); transactionInterface.commit(sourceLocation);
} }
TEST_F(SqliteDatabase, commit) TEST_F(SqliteDatabase, commit)
{ {
transactionInterface.deferredBegin(); transactionInterface.deferredBegin(sourceLocation);
ASSERT_NO_THROW(transactionInterface.commit()); ASSERT_NO_THROW(transactionInterface.commit(sourceLocation));
} }
TEST_F(SqliteDatabase, rollback) TEST_F(SqliteDatabase, rollback)
{ {
transactionInterface.deferredBegin(); transactionInterface.deferredBegin(sourceLocation);
ASSERT_NO_THROW(transactionInterface.rollback()); ASSERT_NO_THROW(transactionInterface.rollback(sourceLocation));
} }
TEST_F(SqliteDatabase, set_update_hook_set) TEST_F(SqliteDatabase, set_update_hook_set)

View File

@@ -24,6 +24,8 @@ using Sqlite::OpenMode;
using Sqlite::Exception; using Sqlite::Exception;
using Sqlite::WriteStatement; using Sqlite::WriteStatement;
constexpr auto sourceLocation = Sqlite::source_location::current();
class SqliteDatabaseBackend : public ::testing::Test class SqliteDatabaseBackend : public ::testing::Test
{ {
protected: protected:
@@ -31,7 +33,10 @@ protected:
{ {
database.lock(); database.lock();
QDir::temp().remove(QStringLiteral("SqliteDatabaseBackendTest.db")); QDir::temp().remove(QStringLiteral("SqliteDatabaseBackendTest.db"));
databaseBackend.open(databaseFilePath, OpenMode::ReadWrite, Sqlite::JournalMode::Wal); databaseBackend.open(databaseFilePath,
OpenMode::ReadWrite,
Sqlite::JournalMode::Wal,
sourceLocation);
} }
~SqliteDatabaseBackend() noexcept(true) ~SqliteDatabaseBackend() noexcept(true)
@@ -49,56 +54,60 @@ using SqliteDatabaseBackendSlowTest = SqliteDatabaseBackend;
TEST_F(SqliteDatabaseBackend, open_already_open_database) TEST_F(SqliteDatabaseBackend, open_already_open_database)
{ {
ASSERT_THROW(databaseBackend.open(databaseFilePath, OpenMode::ReadWrite, Sqlite::JournalMode::Wal), ASSERT_THROW(databaseBackend.open(databaseFilePath,
OpenMode::ReadWrite,
Sqlite::JournalMode::Wal,
sourceLocation),
Sqlite::DatabaseIsAlreadyOpen); Sqlite::DatabaseIsAlreadyOpen);
} }
TEST_F(SqliteDatabaseBackend, close_already_closed_database) TEST_F(SqliteDatabaseBackend, close_already_closed_database)
{ {
databaseBackend.close(); databaseBackend.close(sourceLocation);
ASSERT_THROW(databaseBackend.close(), Sqlite::DatabaseIsAlreadyClosed); ASSERT_THROW(databaseBackend.close(sourceLocation), Sqlite::DatabaseIsAlreadyClosed);
} }
TEST_F(SqliteDatabaseBackend, open_with_wrong_path) TEST_F(SqliteDatabaseBackend, open_with_wrong_path)
{ {
ASSERT_THROW(databaseBackend.open("/xxx/SqliteDatabaseBackendTest.db", ASSERT_THROW(databaseBackend.open("/xxx/SqliteDatabaseBackendTest.db",
OpenMode::ReadWrite, OpenMode::ReadWrite,
Sqlite::JournalMode::Wal), Sqlite::JournalMode::Wal,
sourceLocation),
Sqlite::WrongFilePath); Sqlite::WrongFilePath);
} }
TEST_F(SqliteDatabaseBackend, default_journal_mode) TEST_F(SqliteDatabaseBackend, default_journal_mode)
{ {
ASSERT_THAT(databaseBackend.journalMode(), JournalMode::Delete); ASSERT_THAT(databaseBackend.journalMode(sourceLocation), JournalMode::Delete);
} }
TEST_F(SqliteDatabaseBackendSlowTest, wal_journal_mode) TEST_F(SqliteDatabaseBackendSlowTest, wal_journal_mode)
{ {
databaseBackend.setJournalMode(JournalMode::Wal); databaseBackend.setJournalMode(JournalMode::Wal, sourceLocation);
ASSERT_THAT(databaseBackend.journalMode(), JournalMode::Wal); ASSERT_THAT(databaseBackend.journalMode(sourceLocation), JournalMode::Wal);
} }
TEST_F(SqliteDatabaseBackend, truncate_journal_mode) TEST_F(SqliteDatabaseBackend, truncate_journal_mode)
{ {
databaseBackend.setJournalMode(JournalMode::Truncate); databaseBackend.setJournalMode(JournalMode::Truncate, sourceLocation);
ASSERT_THAT(databaseBackend.journalMode(), JournalMode::Truncate); ASSERT_THAT(databaseBackend.journalMode(sourceLocation), JournalMode::Truncate);
} }
TEST_F(SqliteDatabaseBackend, memory_journal_mode) TEST_F(SqliteDatabaseBackend, memory_journal_mode)
{ {
databaseBackend.setJournalMode(JournalMode::Memory); databaseBackend.setJournalMode(JournalMode::Memory, sourceLocation);
ASSERT_THAT(databaseBackend.journalMode(), JournalMode::Memory); ASSERT_THAT(databaseBackend.journalMode(sourceLocation), JournalMode::Memory);
} }
TEST_F(SqliteDatabaseBackend, persist_journal_mode) TEST_F(SqliteDatabaseBackend, persist_journal_mode)
{ {
databaseBackend.setJournalMode(JournalMode::Persist); databaseBackend.setJournalMode(JournalMode::Persist, sourceLocation);
ASSERT_THAT(databaseBackend.journalMode(), JournalMode::Persist); ASSERT_THAT(databaseBackend.journalMode(sourceLocation), JournalMode::Persist);
} }
TEST_F(SqliteDatabaseBackend, open_mode_read_only) TEST_F(SqliteDatabaseBackend, open_mode_read_only)

View File

@@ -56,6 +56,8 @@ bool compareValue(SqliteTestStatement<2, 1> &statement, Type value, int column)
return false; return false;
} }
constexpr auto sourceLocation = Sqlite::source_location::current();
MATCHER_P3(HasValues, MATCHER_P3(HasValues,
value1, value1,
value2, value2,
@@ -66,9 +68,9 @@ MATCHER_P3(HasValues,
Database &database = arg.database(); Database &database = arg.database();
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE rowid=?", database); SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE rowid=?", database);
statement.bind(1, rowid); statement.bind(1, rowid, sourceLocation);
statement.next(); statement.next(sourceLocation);
return compareValue(statement, value1, 0) && compareValue(statement, value2, 1); return compareValue(statement, value1, 0) && compareValue(statement, value2, 1);
} }
@@ -78,9 +80,9 @@ MATCHER_P(HasNullValues, rowid, std::string(negation ? "isn't null" : "is null")
Database &database = arg.database(); Database &database = arg.database();
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE rowid=?", database); SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE rowid=?", database);
statement.bind(1, rowid); statement.bind(1, rowid, sourceLocation);
statement.next(); statement.next(sourceLocation);
return statement.fetchValueView(0).isNull() && statement.fetchValueView(1).isNull(); return statement.fetchValueView(0).isNull() && statement.fetchValueView(1).isNull();
} }
@@ -163,7 +165,7 @@ TEST_F(SqliteStatement, count_rows)
{ {
SqliteTestStatement<3> statement("SELECT * FROM test", database); SqliteTestStatement<3> statement("SELECT * FROM test", database);
int nextCount = 0; int nextCount = 0;
while (statement.next()) while (statement.next(sourceLocation))
++nextCount; ++nextCount;
int sqlCount = ReadStatement<1>::toValue<int>("SELECT count(*) FROM test", database); int sqlCount = ReadStatement<1>::toValue<int>("SELECT count(*) FROM test", database);
@@ -174,9 +176,9 @@ TEST_F(SqliteStatement, count_rows)
TEST_F(SqliteStatement, value) TEST_F(SqliteStatement, value)
{ {
SqliteTestStatement<3> statement("SELECT name, number, value FROM test ORDER BY name", database); SqliteTestStatement<3> statement("SELECT name, number, value FROM test ORDER BY name", database);
statement.next(); statement.next(sourceLocation);
statement.next(); statement.next(sourceLocation);
ASSERT_THAT(statement.fetchValue<int>(0), 0); ASSERT_THAT(statement.fetchValue<int>(0), 0);
ASSERT_THAT(statement.fetchValue<int64_t>(0), 0); ASSERT_THAT(statement.fetchValue<int64_t>(0), 0);
@@ -226,8 +228,8 @@ TEST_F(SqliteStatement, bind_null)
database.execute("INSERT INTO test VALUES (NULL, 323, 344)"); database.execute("INSERT INTO test VALUES (NULL, 323, 344)");
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE name IS ?", database); SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE name IS ?", database);
statement.bindNull(1); statement.bindNull(1, sourceLocation);
statement.next(); statement.next(sourceLocation);
ASSERT_TRUE(statement.fetchValueView(0).isNull()); ASSERT_TRUE(statement.fetchValueView(0).isNull());
ASSERT_THAT(statement.fetchValue<int>(1), 323); ASSERT_THAT(statement.fetchValue<int>(1), 323);
@@ -238,8 +240,8 @@ TEST_F(SqliteStatement, bind_null_value)
database.execute("INSERT INTO test VALUES (NULL, 323, 344)"); database.execute("INSERT INTO test VALUES (NULL, 323, 344)");
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE name IS ?", database); SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE name IS ?", database);
statement.bind(1, Sqlite::NullValue{}); statement.bind(1, Sqlite::NullValue{}, sourceLocation);
statement.next(); statement.next(sourceLocation);
ASSERT_TRUE(statement.fetchValueView(0).isNull()); ASSERT_TRUE(statement.fetchValueView(0).isNull());
ASSERT_THAT(statement.fetchValue<int>(1), 323); ASSERT_THAT(statement.fetchValue<int>(1), 323);
@@ -250,11 +252,11 @@ TEST_F(SqliteStatement, bind_invalid_int_id_to_null)
TestIntId id; TestIntId id;
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database); SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
statement.bind(1, id); statement.bind(1, id, sourceLocation);
statement.next(); statement.next(sourceLocation);
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database); SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
readStatement.next(); readStatement.next(sourceLocation);
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Null); ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Null);
} }
@@ -263,11 +265,11 @@ TEST_F(SqliteStatement, bind_invalid_compound_id_to_null)
CompoundId id; CompoundId id;
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database); SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
statement.bind(1, id); statement.bind(1, id, sourceLocation);
statement.next(); statement.next(sourceLocation);
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database); SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
readStatement.next(); readStatement.next(sourceLocation);
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Null); ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Null);
} }
@@ -276,11 +278,11 @@ TEST_F(SqliteStatement, bind_int_id)
TestIntId id{TestIntId::create(42)}; TestIntId id{TestIntId::create(42)};
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database); SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
statement.bind(1, id); statement.bind(1, id, sourceLocation);
statement.next(); statement.next(sourceLocation);
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database); SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
readStatement.next(); readStatement.next(sourceLocation);
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Integer); ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Integer);
ASSERT_THAT(readStatement.fetchIntValue(0), 42); ASSERT_THAT(readStatement.fetchIntValue(0), 42);
} }
@@ -290,11 +292,11 @@ TEST_F(SqliteStatement, bind_compound_id)
CompoundId id = CompoundId::create(42); CompoundId id = CompoundId::create(42);
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database); SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
statement.bind(1, id); statement.bind(1, id, sourceLocation);
statement.next(); statement.next(sourceLocation);
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database); SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
readStatement.next(); readStatement.next(sourceLocation);
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Integer); ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Integer);
ASSERT_THAT(readStatement.fetchIntValue(0), 42); ASSERT_THAT(readStatement.fetchIntValue(0), 42);
} }
@@ -305,11 +307,11 @@ TEST_F(SqliteStatement, bind_special_state_id)
constexpr TestIntId unresolvedTypeId = TestIntId::createSpecialState(SpecialIdState::Unresolved); constexpr TestIntId unresolvedTypeId = TestIntId::createSpecialState(SpecialIdState::Unresolved);
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database); SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
statement.bind(1, unresolvedTypeId); statement.bind(1, unresolvedTypeId, sourceLocation);
statement.next(); statement.next(sourceLocation);
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database); SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
readStatement.next(); readStatement.next(sourceLocation);
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Integer); ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Integer);
ASSERT_THAT(readStatement.fetchIntValue(0), -1); ASSERT_THAT(readStatement.fetchIntValue(0), -1);
} }
@@ -319,11 +321,11 @@ TEST_F(SqliteStatement, bind_invalid_long_long_id_to_null)
TestLongLongId id; TestLongLongId id;
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database); SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
statement.bind(1, id); statement.bind(1, id, sourceLocation);
statement.next(); statement.next(sourceLocation);
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database); SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
readStatement.next(); readStatement.next(sourceLocation);
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Null); ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Null);
} }
@@ -332,11 +334,11 @@ TEST_F(SqliteStatement, bind_long_long_id)
TestLongLongId id{TestLongLongId::create(42)}; TestLongLongId id{TestLongLongId::create(42)};
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database); SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
statement.bind(1, id); statement.bind(1, id, sourceLocation);
statement.next(); statement.next(sourceLocation);
SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database); SqliteTestStatement<1, 1> readStatement("SELECT value FROM test WHERE name='id'", database);
readStatement.next(); readStatement.next(sourceLocation);
ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Integer); ASSERT_THAT(readStatement.fetchType(0), Sqlite::Type::Integer);
ASSERT_THAT(readStatement.fetchIntValue(0), 42); ASSERT_THAT(readStatement.fetchIntValue(0), 42);
} }
@@ -345,8 +347,8 @@ TEST_F(SqliteStatement, bind_string)
{ {
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE name=?", database); SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE name=?", database);
statement.bind(1, Utils::SmallStringView("foo")); statement.bind(1, Utils::SmallStringView("foo"), sourceLocation);
statement.next(); statement.next(sourceLocation);
ASSERT_THAT(statement.fetchSmallStringViewValue(0), "foo"); ASSERT_THAT(statement.fetchSmallStringViewValue(0), "foo");
ASSERT_THAT(statement.fetchValue<double>(1), 23.3); ASSERT_THAT(statement.fetchValue<double>(1), 23.3);
@@ -356,8 +358,8 @@ TEST_F(SqliteStatement, bind_integer)
{ {
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=?", database); SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=?", database);
statement.bind(1, 40); statement.bind(1, 40, sourceLocation);
statement.next(); statement.next(sourceLocation);
ASSERT_THAT(statement.fetchSmallStringViewValue(0), "poo"); ASSERT_THAT(statement.fetchSmallStringViewValue(0), "poo");
} }
@@ -366,8 +368,8 @@ TEST_F(SqliteStatement, bind_long_integer)
{ {
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=?", database); SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=?", database);
statement.bind(1, int64_t(40)); statement.bind(1, int64_t(40), sourceLocation);
statement.next(); statement.next(sourceLocation);
ASSERT_THAT(statement.fetchSmallStringViewValue(0), "poo"); ASSERT_THAT(statement.fetchSmallStringViewValue(0), "poo");
} }
@@ -376,8 +378,8 @@ TEST_F(SqliteStatement, bind_double)
{ {
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=?", database); SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=?", database);
statement.bind(1, 23.3); statement.bind(1, 23.3, sourceLocation);
statement.next(); statement.next(sourceLocation);
ASSERT_THAT(statement.fetchSmallStringViewValue(0), "foo"); ASSERT_THAT(statement.fetchSmallStringViewValue(0), "foo");
} }
@@ -387,8 +389,8 @@ TEST_F(SqliteStatement, bind_pointer)
SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?, 5, 'int64')", database); SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?, 5, 'int64')", database);
std::vector<long long> values{1, 1, 2, 3, 5}; std::vector<long long> values{1, 1, 2, 3, 5};
statement.bind(1, values.data()); statement.bind(1, values.data(), sourceLocation);
statement.next(); statement.next(sourceLocation);
ASSERT_THAT(statement.fetchIntValue(0), 1); ASSERT_THAT(statement.fetchIntValue(0), 1);
} }
@@ -398,11 +400,11 @@ TEST_F(SqliteStatement, bind_int_carray)
SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database); SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database);
std::vector<int> values{3, 10, 20, 33, 55}; std::vector<int> values{3, 10, 20, 33, 55};
statement.bind(1, values); statement.bind(1, values, sourceLocation);
statement.next(); statement.next(sourceLocation);
statement.next(); statement.next(sourceLocation);
statement.next(); statement.next(sourceLocation);
statement.next(); statement.next(sourceLocation);
ASSERT_THAT(statement.fetchIntValue(0), 33); ASSERT_THAT(statement.fetchIntValue(0), 33);
} }
@@ -412,11 +414,11 @@ TEST_F(SqliteStatement, bind_long_long_carray)
SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database); SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database);
std::vector<long long> values{3, 10, 20, 33, 55}; std::vector<long long> values{3, 10, 20, 33, 55};
statement.bind(1, values); statement.bind(1, values, sourceLocation);
statement.next(); statement.next(sourceLocation);
statement.next(); statement.next(sourceLocation);
statement.next(); statement.next(sourceLocation);
statement.next(); statement.next(sourceLocation);
ASSERT_THAT(statement.fetchLongLongValue(0), 33); ASSERT_THAT(statement.fetchLongLongValue(0), 33);
} }
@@ -426,11 +428,11 @@ TEST_F(SqliteStatement, bind_double_carray)
SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database); SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database);
std::vector<double> values{3.3, 10.2, 20.54, 33.21, 55}; std::vector<double> values{3.3, 10.2, 20.54, 33.21, 55};
statement.bind(1, values); statement.bind(1, values, sourceLocation);
statement.next(); statement.next(sourceLocation);
statement.next(); statement.next(sourceLocation);
statement.next(); statement.next(sourceLocation);
statement.next(); statement.next(sourceLocation);
ASSERT_THAT(statement.fetchDoubleValue(0), 33.21); ASSERT_THAT(statement.fetchDoubleValue(0), 33.21);
} }
@@ -440,11 +442,11 @@ TEST_F(SqliteStatement, bind_text_carray)
SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database); SqliteTestStatement<1, 1> statement("SELECT value FROM carray(?)", database);
std::vector<const char *> values{"yi", "er", "san", "se", "wu"}; std::vector<const char *> values{"yi", "er", "san", "se", "wu"};
statement.bind(1, values); statement.bind(1, values, sourceLocation);
statement.next(); statement.next(sourceLocation);
statement.next(); statement.next(sourceLocation);
statement.next(); statement.next(sourceLocation);
statement.next(); statement.next(sourceLocation);
ASSERT_THAT(statement.fetchSmallStringViewValue(0), Eq("se")); ASSERT_THAT(statement.fetchSmallStringViewValue(0), Eq("se"));
} }
@@ -456,8 +458,8 @@ TEST_F(SqliteStatement, bind_blob)
auto bytePointer = reinterpret_cast<const std::byte *>(chars); auto bytePointer = reinterpret_cast<const std::byte *>(chars);
Sqlite::BlobView bytes{bytePointer, sizeof(chars) - 1}; Sqlite::BlobView bytes{bytePointer, sizeof(chars) - 1};
statement.bind(1, bytes); statement.bind(1, bytes, sourceLocation);
statement.next(); statement.next(sourceLocation);
ASSERT_THAT(statement.fetchBlobValue(0), Eq(bytes)); ASSERT_THAT(statement.fetchBlobValue(0), Eq(bytes));
} }
@@ -467,8 +469,8 @@ TEST_F(SqliteStatement, bind_empty_blob)
SqliteTestStatement<1, 1> statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database); SqliteTestStatement<1, 1> statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database);
Sqlite::BlobView bytes; Sqlite::BlobView bytes;
statement.bind(1, bytes); statement.bind(1, bytes, sourceLocation);
statement.next(); statement.next(sourceLocation);
ASSERT_THAT(statement.fetchBlobValue(0), IsEmpty()); ASSERT_THAT(statement.fetchBlobValue(0), IsEmpty());
} }
@@ -477,49 +479,51 @@ TEST_F(SqliteStatement, bind_index_is_zero_is_throwing_binding_index_is_out_of_b
{ {
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database); SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
ASSERT_THROW(statement.bind(0, 40), Sqlite::BindingIndexIsOutOfRange); ASSERT_THROW(statement.bind(0, 40, sourceLocation), Sqlite::BindingIndexIsOutOfRange);
} }
TEST_F(SqliteStatement, bind_index_is_zero_is_throwing_binding_index_is_out_of_bound_null) TEST_F(SqliteStatement, bind_index_is_zero_is_throwing_binding_index_is_out_of_bound_null)
{ {
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database); SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
ASSERT_THROW(statement.bind(0, Sqlite::NullValue{}), Sqlite::BindingIndexIsOutOfRange); ASSERT_THROW(statement.bind(0, Sqlite::NullValue{}, sourceLocation),
Sqlite::BindingIndexIsOutOfRange);
} }
TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_long_long) TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_long_long)
{ {
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database); SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
ASSERT_THROW(statement.bind(2, 40LL), Sqlite::BindingIndexIsOutOfRange); ASSERT_THROW(statement.bind(2, 40LL, sourceLocation), Sqlite::BindingIndexIsOutOfRange);
} }
TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_string_view) TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_string_view)
{ {
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database); SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
ASSERT_THROW(statement.bind(2, "foo"), Sqlite::BindingIndexIsOutOfRange); ASSERT_THROW(statement.bind(2, "foo", sourceLocation), Sqlite::BindingIndexIsOutOfRange);
} }
TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_string_float) TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_string_float)
{ {
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database); SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
ASSERT_THROW(statement.bind(2, 2.), Sqlite::BindingIndexIsOutOfRange); ASSERT_THROW(statement.bind(2, 2., sourceLocation), Sqlite::BindingIndexIsOutOfRange);
} }
TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_pointer) TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_pointer)
{ {
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database); SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
ASSERT_THROW(statement.bind(2, nullptr), Sqlite::BindingIndexIsOutOfRange); ASSERT_THROW(statement.bind(2, nullptr, sourceLocation), Sqlite::BindingIndexIsOutOfRange);
} }
TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_value) TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_value)
{ {
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database); SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE number=$1", database);
ASSERT_THROW(statement.bind(2, Sqlite::Value{1}), Sqlite::BindingIndexIsOutOfRange); ASSERT_THROW(statement.bind(2, Sqlite::Value{1}, sourceLocation),
Sqlite::BindingIndexIsOutOfRange);
} }
TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_blob) TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_of_bound_blob)
@@ -527,14 +531,14 @@ TEST_F(SqliteStatement, bind_index_is_to_large_is_throwing_binding_index_is_out_
SqliteTestStatement<1, 1> statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database); SqliteTestStatement<1, 1> statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database);
Sqlite::BlobView bytes{QByteArray{"XXX"}}; Sqlite::BlobView bytes{QByteArray{"XXX"}};
ASSERT_THROW(statement.bind(2, bytes), Sqlite::BindingIndexIsOutOfRange); ASSERT_THROW(statement.bind(2, bytes, sourceLocation), Sqlite::BindingIndexIsOutOfRange);
} }
TEST_F(SqliteStatement, bind_values) TEST_F(SqliteStatement, bind_values)
{ {
SqliteTestStatement<0, 3> statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); SqliteTestStatement<0, 3> statement("UPDATE test SET name=?, number=? WHERE rowid=?", database);
statement.bindValues("see", 7.23, 1); statement.bindValues(sourceLocation, "see", 7.23, 1);
statement.execute(); statement.execute();
ASSERT_THAT(statement, HasValues("see", "7.23", 1)); ASSERT_THAT(statement, HasValues("see", "7.23", 1));
@@ -544,7 +548,7 @@ TEST_F(SqliteStatement, bind_null_values)
{ {
SqliteTestStatement<0, 3> statement("UPDATE test SET name=?, number=? WHERE rowid=?", database); SqliteTestStatement<0, 3> statement("UPDATE test SET name=?, number=? WHERE rowid=?", database);
statement.bindValues(Sqlite::NullValue{}, Sqlite::Value{}, 1); statement.bindValues(sourceLocation, Sqlite::NullValue{}, Sqlite::Value{}, 1);
statement.execute(); statement.execute();
ASSERT_THAT(statement, HasNullValues(1)); ASSERT_THAT(statement, HasNullValues(1));
@@ -1219,7 +1223,7 @@ TEST_F(SqliteStatement, get_optional_value_calls_reset)
TEST_F(SqliteStatement, get_optional_value_calls_reset_if_exception_is_thrown) TEST_F(SqliteStatement, get_optional_value_calls_reset_if_exception_is_thrown)
{ {
MockSqliteStatement<1, 1> mockStatement{databaseMock}; MockSqliteStatement<1, 1> mockStatement{databaseMock};
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
EXPECT_CALL(mockStatement, reset()); EXPECT_CALL(mockStatement, reset());
@@ -1355,7 +1359,7 @@ TEST_F(SqliteStatement, get_value_calls_reset_if_exception_is_thrown)
int x = 0; int x = 0;
}; };
MockSqliteStatement<1, 1> mockStatement{databaseMock}; MockSqliteStatement<1, 1> mockStatement{databaseMock};
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
EXPECT_CALL(mockStatement, reset()); EXPECT_CALL(mockStatement, reset());
@@ -1386,9 +1390,9 @@ TEST_F(SqliteStatement, get_range_with_transaction_without_arguments_calls)
MockSqliteStatement<1, 0> mockStatement{databaseMock}; MockSqliteStatement<1, 0> mockStatement{databaseMock};
EXPECT_CALL(databaseMock, lock()); EXPECT_CALL(databaseMock, lock());
EXPECT_CALL(databaseMock, deferredBegin()); EXPECT_CALL(databaseMock, deferredBegin(_));
EXPECT_CALL(mockStatement, reset()); EXPECT_CALL(mockStatement, reset());
EXPECT_CALL(databaseMock, commit()); EXPECT_CALL(databaseMock, commit(_));
EXPECT_CALL(databaseMock, unlock()); EXPECT_CALL(databaseMock, unlock());
mockStatement.rangeWithTransaction<int>(); mockStatement.rangeWithTransaction<int>();
@@ -1397,7 +1401,7 @@ TEST_F(SqliteStatement, get_range_with_transaction_without_arguments_calls)
TEST_F(SqliteStatement, get_values_without_arguments_calls_reset_if_exception_is_thrown) TEST_F(SqliteStatement, get_values_without_arguments_calls_reset_if_exception_is_thrown)
{ {
MockSqliteStatement<1, 0> mockStatement{databaseMock}; MockSqliteStatement<1, 0> mockStatement{databaseMock};
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
EXPECT_CALL(mockStatement, reset()); EXPECT_CALL(mockStatement, reset());
@@ -1407,7 +1411,7 @@ TEST_F(SqliteStatement, get_values_without_arguments_calls_reset_if_exception_is
TEST_F(SqliteStatement, get_range_without_arguments_calls_reset_if_exception_is_thrown) TEST_F(SqliteStatement, get_range_without_arguments_calls_reset_if_exception_is_thrown)
{ {
MockSqliteStatement<1, 0> mockStatement{databaseMock}; MockSqliteStatement<1, 0> mockStatement{databaseMock};
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
auto range = mockStatement.range<int>(); auto range = mockStatement.range<int>();
EXPECT_CALL(mockStatement, reset()); EXPECT_CALL(mockStatement, reset());
@@ -1419,12 +1423,12 @@ TEST_F(SqliteStatement, get_range_with_transaction_without_arguments_calls_reset
{ {
InSequence s; InSequence s;
MockSqliteStatement<1, 0> mockStatement{databaseMock}; MockSqliteStatement<1, 0> mockStatement{databaseMock};
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
EXPECT_CALL(databaseMock, lock()); EXPECT_CALL(databaseMock, lock());
EXPECT_CALL(databaseMock, deferredBegin()); EXPECT_CALL(databaseMock, deferredBegin(_));
EXPECT_CALL(mockStatement, reset()); EXPECT_CALL(mockStatement, reset());
EXPECT_CALL(databaseMock, rollback()); EXPECT_CALL(databaseMock, rollback(_));
EXPECT_CALL(databaseMock, unlock()); EXPECT_CALL(databaseMock, unlock());
EXPECT_THROW( EXPECT_THROW(
@@ -1447,7 +1451,7 @@ TEST_F(SqliteStatement, get_values_with_simple_arguments_calls_reset)
TEST_F(SqliteStatement, get_values_with_simple_arguments_calls_reset_if_exception_is_thrown) TEST_F(SqliteStatement, get_values_with_simple_arguments_calls_reset_if_exception_is_thrown)
{ {
MockSqliteStatement<1, 2> mockStatement{databaseMock}; MockSqliteStatement<1, 2> mockStatement{databaseMock};
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
EXPECT_CALL(mockStatement, reset()); EXPECT_CALL(mockStatement, reset());
@@ -1458,7 +1462,7 @@ TEST_F(SqliteStatement, reset_if_write_is_throwing_exception)
{ {
MockSqliteStatement<1, 1> mockStatement{databaseMock}; MockSqliteStatement<1, 1> mockStatement{databaseMock};
EXPECT_CALL(mockStatement, bind(1, TypedEq<Utils::SmallStringView>("bar"))) EXPECT_CALL(mockStatement, bind(1, TypedEq<Utils::SmallStringView>("bar"), _))
.WillOnce(Throw(Sqlite::StatementIsBusy(""))); .WillOnce(Throw(Sqlite::StatementIsBusy("")));
EXPECT_CALL(mockStatement, reset()); EXPECT_CALL(mockStatement, reset());
@@ -1469,7 +1473,7 @@ TEST_F(SqliteStatement, reset_if_execute_throws_exception)
{ {
MockSqliteStatement<1, 0> mockStatement{databaseMock}; MockSqliteStatement<1, 0> mockStatement{databaseMock};
EXPECT_CALL(mockStatement, next()).WillOnce(Throw(Sqlite::StatementIsBusy(""))); EXPECT_CALL(mockStatement, next(_)).WillOnce(Throw(Sqlite::StatementIsBusy("")));
EXPECT_CALL(mockStatement, reset()); EXPECT_CALL(mockStatement, reset());
ASSERT_ANY_THROW(mockStatement.execute()); ASSERT_ANY_THROW(mockStatement.execute());
@@ -1576,7 +1580,7 @@ TEST_F(SqliteStatement, read_callback_throws_for_error)
{ {
MockFunction<Sqlite::CallbackControl(Utils::SmallStringView, long long)> callbackMock; MockFunction<Sqlite::CallbackControl(Utils::SmallStringView, long long)> callbackMock;
MockSqliteStatement<2> mockStatement{databaseMock}; MockSqliteStatement<2> mockStatement{databaseMock};
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
ASSERT_THROW(mockStatement.readCallback(callbackMock.AsStdFunction()), Sqlite::StatementHasError); ASSERT_THROW(mockStatement.readCallback(callbackMock.AsStdFunction()), Sqlite::StatementHasError);
} }
@@ -1585,7 +1589,7 @@ TEST_F(SqliteStatement, read_callback_calls_reset_if_exception_is_thrown)
{ {
MockFunction<Sqlite::CallbackControl(Utils::SmallStringView, long long)> callbackMock; MockFunction<Sqlite::CallbackControl(Utils::SmallStringView, long long)> callbackMock;
MockSqliteStatement<2> mockStatement{databaseMock}; MockSqliteStatement<2> mockStatement{databaseMock};
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
EXPECT_CALL(mockStatement, reset()); EXPECT_CALL(mockStatement, reset());
@@ -1626,7 +1630,7 @@ TEST_F(SqliteStatement, read_to_throws_for_error)
{ {
std::deque<FooValue> values; std::deque<FooValue> values;
MockSqliteStatement mockStatement{databaseMock}; MockSqliteStatement mockStatement{databaseMock};
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
ASSERT_THROW(mockStatement.readTo(values), Sqlite::StatementHasError); ASSERT_THROW(mockStatement.readTo(values), Sqlite::StatementHasError);
} }
@@ -1635,7 +1639,7 @@ TEST_F(SqliteStatement, read_to_calls_reset_if_exception_is_thrown)
{ {
std::deque<FooValue> values; std::deque<FooValue> values;
MockSqliteStatement mockStatement{databaseMock}; MockSqliteStatement mockStatement{databaseMock};
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError(""))); ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
EXPECT_CALL(mockStatement, reset()); EXPECT_CALL(mockStatement, reset());

View File

@@ -74,9 +74,9 @@ TEST_F(SqliteTable, initialize_table)
table.addColumn("name"); table.addColumn("name");
table.addColumn("value"); table.addColumn("value");
EXPECT_CALL(databaseMock, EXPECT_CALL(
execute(Eq( databaseMock,
"CREATE TEMPORARY TABLE IF NOT EXISTS testTable(name, value) WITHOUT ROWID"))); execute(Eq("CREATE TEMPORARY TABLE IF NOT EXISTS testTable(name, value) WITHOUT ROWID"), _));
table.initialize(databaseMock); table.initialize(databaseMock);
} }
@@ -90,13 +90,14 @@ TEST_F(SqliteTable, initialize_table_with_index)
table.addIndex({column}); table.addIndex({column});
table.addIndex({column2}, "value IS NOT NULL"); table.addIndex({column2}, "value IS NOT NULL");
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name, value)"))); EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name, value)"), _));
EXPECT_CALL(databaseMock, EXPECT_CALL(
execute(Eq( databaseMock,
"CREATE INDEX IF NOT EXISTS index_normal_testTable_name ON testTable(name)"))); execute(Eq("CREATE INDEX IF NOT EXISTS index_normal_testTable_name ON testTable(name)"), _));
EXPECT_CALL(databaseMock, EXPECT_CALL(databaseMock,
execute(Eq("CREATE INDEX IF NOT EXISTS index_partial_testTable_value ON " execute(Eq("CREATE INDEX IF NOT EXISTS index_partial_testTable_value ON "
"testTable(value) WHERE value IS NOT NULL"))); "testTable(value) WHERE value IS NOT NULL"),
_));
table.initialize(databaseMock); table.initialize(databaseMock);
} }
@@ -110,14 +111,15 @@ TEST_F(SqliteTable, initialize_table_with_unique_index)
table.addUniqueIndex({column}); table.addUniqueIndex({column});
table.addUniqueIndex({column2}, "value IS NOT NULL"); table.addUniqueIndex({column2}, "value IS NOT NULL");
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name, value)"))); EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name, value)"), _));
EXPECT_CALL( EXPECT_CALL(
databaseMock, databaseMock,
execute(Eq( execute(
"CREATE UNIQUE INDEX IF NOT EXISTS index_unique_testTable_name ON testTable(name)"))); Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_unique_testTable_name ON testTable(name)"), _));
EXPECT_CALL(databaseMock, EXPECT_CALL(databaseMock,
execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_unique_partial_testTable_value " execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_unique_partial_testTable_value "
"ON testTable(value) WHERE value IS NOT NULL"))); "ON testTable(value) WHERE value IS NOT NULL"),
_));
table.initialize(databaseMock); table.initialize(databaseMock);
} }
@@ -135,7 +137,8 @@ TEST_F(SqliteTable, add_foreign_key_column_with_table_calls)
EXPECT_CALL(databaseMock, EXPECT_CALL(databaseMock,
execute(Eq("CREATE TABLE testTable(name INTEGER REFERENCES foreignTable ON UPDATE " execute(Eq("CREATE TABLE testTable(name INTEGER REFERENCES foreignTable ON UPDATE "
"SET NULL ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)"))); "SET NULL ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)"),
_));
table.initialize(databaseMock); table.initialize(databaseMock);
} }
@@ -156,7 +159,8 @@ TEST_F(SqliteTable, add_foreign_key_column_with_column_calls)
databaseMock, databaseMock,
execute( execute(
Eq("CREATE TABLE testTable(name TEXT REFERENCES foreignTable(foreignColumn) ON UPDATE " Eq("CREATE TABLE testTable(name TEXT REFERENCES foreignTable(foreignColumn) ON UPDATE "
"SET DEFAULT ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED)"))); "SET DEFAULT ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED)"),
_));
table.initialize(databaseMock); table.initialize(databaseMock);
} }
@@ -307,7 +311,8 @@ TEST_F(SqliteTable, add_primary_table_contraint)
const auto &nameColumn = table.addColumn("name"); const auto &nameColumn = table.addColumn("name");
table.addPrimaryKeyContraint({idColumn, nameColumn}); table.addPrimaryKeyContraint({idColumn, nameColumn});
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(id, name, PRIMARY KEY(id, name))"))); EXPECT_CALL(databaseMock,
execute(Eq("CREATE TABLE testTable(id, name, PRIMARY KEY(id, name))"), _));
table.initialize(databaseMock); table.initialize(databaseMock);
} }
@@ -367,7 +372,8 @@ TEST_F(StrictSqliteTable, initialize_table)
EXPECT_CALL(databaseMock, EXPECT_CALL(databaseMock,
execute(Eq("CREATE TEMPORARY TABLE IF NOT EXISTS testTable(name ANY, value ANY) " execute(Eq("CREATE TEMPORARY TABLE IF NOT EXISTS testTable(name ANY, value ANY) "
"WITHOUT ROWID, STRICT"))); "WITHOUT ROWID, STRICT"),
_));
table.initialize(databaseMock); table.initialize(databaseMock);
} }
@@ -381,13 +387,14 @@ TEST_F(StrictSqliteTable, initialize_table_with_index)
table.addIndex({column}); table.addIndex({column});
table.addIndex({column2}, "value IS NOT NULL"); table.addIndex({column2}, "value IS NOT NULL");
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name ANY, value ANY) STRICT"))); EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name ANY, value ANY) STRICT"), _));
EXPECT_CALL(databaseMock, EXPECT_CALL(
execute(Eq( databaseMock,
"CREATE INDEX IF NOT EXISTS index_normal_testTable_name ON testTable(name)"))); execute(Eq("CREATE INDEX IF NOT EXISTS index_normal_testTable_name ON testTable(name)"), _));
EXPECT_CALL(databaseMock, EXPECT_CALL(databaseMock,
execute(Eq("CREATE INDEX IF NOT EXISTS index_partial_testTable_value ON " execute(Eq("CREATE INDEX IF NOT EXISTS index_partial_testTable_value ON "
"testTable(value) WHERE value IS NOT NULL"))); "testTable(value) WHERE value IS NOT NULL"),
_));
table.initialize(databaseMock); table.initialize(databaseMock);
} }
@@ -401,14 +408,15 @@ TEST_F(StrictSqliteTable, initialize_table_with_unique_index)
table.addUniqueIndex({column}); table.addUniqueIndex({column});
table.addUniqueIndex({column2}, "value IS NOT NULL"); table.addUniqueIndex({column2}, "value IS NOT NULL");
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name ANY, value ANY) STRICT"))); EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name ANY, value ANY) STRICT"), _));
EXPECT_CALL( EXPECT_CALL(
databaseMock, databaseMock,
execute(Eq( execute(
"CREATE UNIQUE INDEX IF NOT EXISTS index_unique_testTable_name ON testTable(name)"))); Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_unique_testTable_name ON testTable(name)"), _));
EXPECT_CALL(databaseMock, EXPECT_CALL(databaseMock,
execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_unique_partial_testTable_value " execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_unique_partial_testTable_value "
"ON testTable(value) WHERE value IS NOT NULL"))); "ON testTable(value) WHERE value IS NOT NULL"),
_));
table.initialize(databaseMock); table.initialize(databaseMock);
} }
@@ -426,7 +434,8 @@ TEST_F(StrictSqliteTable, add_foreign_key_column_with_table_calls)
EXPECT_CALL(databaseMock, EXPECT_CALL(databaseMock,
execute(Eq("CREATE TABLE testTable(name INTEGER REFERENCES foreignTable ON UPDATE " execute(Eq("CREATE TABLE testTable(name INTEGER REFERENCES foreignTable ON UPDATE "
"SET NULL ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED) STRICT"))); "SET NULL ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED) STRICT"),
_));
table.initialize(databaseMock); table.initialize(databaseMock);
} }
@@ -449,7 +458,8 @@ TEST_F(StrictSqliteTable, add_foreign_key_column_with_column_calls)
databaseMock, databaseMock,
execute( execute(
Eq("CREATE TABLE testTable(name TEXT REFERENCES foreignTable(foreignColumn) ON UPDATE " Eq("CREATE TABLE testTable(name TEXT REFERENCES foreignTable(foreignColumn) ON UPDATE "
"SET DEFAULT ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED) STRICT"))); "SET DEFAULT ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED) STRICT"),
_));
table.initialize(databaseMock); table.initialize(databaseMock);
} }
@@ -604,9 +614,9 @@ TEST_F(StrictSqliteTable, add_primary_table_contraint)
const auto &nameColumn = table.addColumn("name"); const auto &nameColumn = table.addColumn("name");
table.addPrimaryKeyContraint({idColumn, nameColumn}); table.addPrimaryKeyContraint({idColumn, nameColumn});
EXPECT_CALL(databaseMock, EXPECT_CALL(
execute( databaseMock,
Eq("CREATE TABLE testTable(id ANY, name ANY, PRIMARY KEY(id, name)) STRICT"))); execute(Eq("CREATE TABLE testTable(id ANY, name ANY, PRIMARY KEY(id, name)) STRICT"), _));
table.initialize(databaseMock); table.initialize(databaseMock);
} }

View File

@@ -4,15 +4,18 @@
#pragma once #pragma once
#include <sqlitebasestatement.h> #include <sqlitebasestatement.h>
template<int ResultCount, int BindParameterCount = 0> template<int ResultCount, int BindParameterCount = 0>
class SqliteTestStatement class SqliteTestStatement
: public Sqlite::StatementImplementation<Sqlite::BaseStatement, ResultCount, BindParameterCount> : public Sqlite::StatementImplementation<Sqlite::BaseStatement, ResultCount, BindParameterCount>
{ {
using Base = Sqlite::StatementImplementation<Sqlite::BaseStatement, ResultCount, BindParameterCount>; using Base = Sqlite::StatementImplementation<Sqlite::BaseStatement, ResultCount, BindParameterCount>;
static constexpr auto sourceLocation = Sqlite::source_location::current();
public: public:
explicit SqliteTestStatement(Utils::SmallStringView sqlStatement, Sqlite::Database &database) explicit SqliteTestStatement(Utils::SmallStringView sqlStatement, Sqlite::Database &database)
: Base(sqlStatement, database) : Base(sqlStatement, database, sourceLocation)
{} {}
}; };

View File

@@ -35,8 +35,8 @@ TEST_F(SqliteTransaction, deferred_transaction_commit)
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin()); EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
EXPECT_CALL(mockTransactionBackend, commit()); EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
DeferredTransaction transaction{mockTransactionBackend}; DeferredTransaction transaction{mockTransactionBackend};
@@ -48,8 +48,8 @@ TEST_F(SqliteTransaction, deferred_transaction_roll_back)
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin()); EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
EXPECT_CALL(mockTransactionBackend, rollback()); EXPECT_CALL(mockTransactionBackend, rollback(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
DeferredTransaction transaction{mockTransactionBackend}; DeferredTransaction transaction{mockTransactionBackend};
@@ -60,8 +60,8 @@ TEST_F(SqliteTransaction, immediate_transaction_commit)
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateBegin()); EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
EXPECT_CALL(mockTransactionBackend, commit()); EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
ImmediateTransaction transaction{mockTransactionBackend}; ImmediateTransaction transaction{mockTransactionBackend};
@@ -73,8 +73,8 @@ TEST_F(SqliteTransaction, immediate_transaction_roll_back)
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateBegin()); EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
EXPECT_CALL(mockTransactionBackend, rollback()); EXPECT_CALL(mockTransactionBackend, rollback(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
ImmediateTransaction transaction{mockTransactionBackend}; ImmediateTransaction transaction{mockTransactionBackend};
@@ -85,8 +85,8 @@ TEST_F(SqliteTransaction, exclusive_transaction_commit)
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, exclusiveBegin()); EXPECT_CALL(mockTransactionBackend, exclusiveBegin(_));
EXPECT_CALL(mockTransactionBackend, commit()); EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
ExclusiveTransaction transaction{mockTransactionBackend}; ExclusiveTransaction transaction{mockTransactionBackend};
@@ -98,8 +98,8 @@ TEST_F(SqliteTransaction, exclusive_transaction_roll_back)
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, exclusiveBegin()); EXPECT_CALL(mockTransactionBackend, exclusiveBegin(_));
EXPECT_CALL(mockTransactionBackend, rollback()); EXPECT_CALL(mockTransactionBackend, rollback(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
ExclusiveTransaction transaction{mockTransactionBackend}; ExclusiveTransaction transaction{mockTransactionBackend};
@@ -110,8 +110,8 @@ TEST_F(SqliteTransaction, deferred_non_throwing_destructor_transaction_commit)
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin()); EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
EXPECT_CALL(mockTransactionBackend, commit()); EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
DeferredNonThrowingDestructorTransaction transaction{mockTransactionBackend}; DeferredNonThrowingDestructorTransaction transaction{mockTransactionBackend};
@@ -123,8 +123,8 @@ TEST_F(SqliteTransaction, deferred_non_throwing_destructor_transaction_commit_ca
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin()); EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
EXPECT_CALL(mockTransactionBackend, commit()); EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
DeferredNonThrowingDestructorTransaction transaction{mockTransactionBackend}; DeferredNonThrowingDestructorTransaction transaction{mockTransactionBackend};
@@ -136,8 +136,8 @@ TEST_F(SqliteTransaction, deferred_non_throwing_destructor_transaction_roll_back
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin()); EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
EXPECT_CALL(mockTransactionBackend, rollback()); EXPECT_CALL(mockTransactionBackend, rollback(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
DeferredNonThrowingDestructorTransaction transaction{mockTransactionBackend}; DeferredNonThrowingDestructorTransaction transaction{mockTransactionBackend};
@@ -148,8 +148,8 @@ TEST_F(SqliteTransaction, immediate_non_throwing_destructor_transaction_commit)
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateBegin()); EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
EXPECT_CALL(mockTransactionBackend, commit()); EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
ImmediateNonThrowingDestructorTransaction transaction{mockTransactionBackend}; ImmediateNonThrowingDestructorTransaction transaction{mockTransactionBackend};
@@ -161,8 +161,8 @@ TEST_F(SqliteTransaction, immediate_non_throwing_destructor_transaction_roll_bac
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateBegin()); EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
EXPECT_CALL(mockTransactionBackend, rollback()); EXPECT_CALL(mockTransactionBackend, rollback(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
ImmediateNonThrowingDestructorTransaction transaction{mockTransactionBackend}; ImmediateNonThrowingDestructorTransaction transaction{mockTransactionBackend};
@@ -173,8 +173,8 @@ TEST_F(SqliteTransaction, exclusive_non_throwing_destructor_transaction_commit)
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, exclusiveBegin()); EXPECT_CALL(mockTransactionBackend, exclusiveBegin(_));
EXPECT_CALL(mockTransactionBackend, commit()); EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
ExclusiveNonThrowingDestructorTransaction transaction{mockTransactionBackend}; ExclusiveNonThrowingDestructorTransaction transaction{mockTransactionBackend};
@@ -186,8 +186,8 @@ TEST_F(SqliteTransaction, exclusive_t_non_throwing_destructorransaction_roll_bac
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, exclusiveBegin()); EXPECT_CALL(mockTransactionBackend, exclusiveBegin(_));
EXPECT_CALL(mockTransactionBackend, rollback()); EXPECT_CALL(mockTransactionBackend, rollback(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
ExclusiveNonThrowingDestructorTransaction transaction{mockTransactionBackend}; ExclusiveNonThrowingDestructorTransaction transaction{mockTransactionBackend};
@@ -195,21 +195,21 @@ TEST_F(SqliteTransaction, exclusive_t_non_throwing_destructorransaction_roll_bac
TEST_F(SqliteTransaction, deferred_transaction_begin_throws) TEST_F(SqliteTransaction, deferred_transaction_begin_throws)
{ {
ON_CALL(mockTransactionBackend, deferredBegin()).WillByDefault(Throw(Sqlite::Exception())); ON_CALL(mockTransactionBackend, deferredBegin(_)).WillByDefault(Throw(Sqlite::Exception()));
ASSERT_THROW(DeferredTransaction{mockTransactionBackend}, Sqlite::Exception); ASSERT_THROW(DeferredTransaction{mockTransactionBackend}, Sqlite::Exception);
} }
TEST_F(SqliteTransaction, immediate_transaction_begin_throws) TEST_F(SqliteTransaction, immediate_transaction_begin_throws)
{ {
ON_CALL(mockTransactionBackend, immediateBegin()).WillByDefault(Throw(Sqlite::Exception())); ON_CALL(mockTransactionBackend, immediateBegin(_)).WillByDefault(Throw(Sqlite::Exception()));
ASSERT_THROW(ImmediateTransaction{mockTransactionBackend}, Sqlite::Exception); ASSERT_THROW(ImmediateTransaction{mockTransactionBackend}, Sqlite::Exception);
} }
TEST_F(SqliteTransaction, exclusive_transaction_begin_throws) TEST_F(SqliteTransaction, exclusive_transaction_begin_throws)
{ {
ON_CALL(mockTransactionBackend, exclusiveBegin()).WillByDefault(Throw(Sqlite::Exception())); ON_CALL(mockTransactionBackend, exclusiveBegin(_)).WillByDefault(Throw(Sqlite::Exception()));
ASSERT_THROW(ExclusiveTransaction{mockTransactionBackend}, Sqlite::Exception); ASSERT_THROW(ExclusiveTransaction{mockTransactionBackend}, Sqlite::Exception);
} }
@@ -219,8 +219,8 @@ TEST_F(SqliteTransaction, deferred_transaction_begin_throws_and_not_rollback)
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin()).WillOnce(Throw(Sqlite::Exception())); EXPECT_CALL(mockTransactionBackend, deferredBegin(_)).WillOnce(Throw(Sqlite::Exception()));
EXPECT_CALL(mockTransactionBackend, rollback()).Times(0); EXPECT_CALL(mockTransactionBackend, rollback(_)).Times(0);
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
ASSERT_ANY_THROW(DeferredTransaction{mockTransactionBackend}); ASSERT_ANY_THROW(DeferredTransaction{mockTransactionBackend});
@@ -231,8 +231,8 @@ TEST_F(SqliteTransaction, immediate_transaction_begin_throws_and_not_rollback)
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateBegin()).WillOnce(Throw(Sqlite::Exception())); EXPECT_CALL(mockTransactionBackend, immediateBegin(_)).WillOnce(Throw(Sqlite::Exception()));
EXPECT_CALL(mockTransactionBackend, rollback()).Times(0); EXPECT_CALL(mockTransactionBackend, rollback(_)).Times(0);
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
ASSERT_ANY_THROW(ImmediateTransaction{mockTransactionBackend}); ASSERT_ANY_THROW(ImmediateTransaction{mockTransactionBackend});
@@ -243,8 +243,8 @@ TEST_F(SqliteTransaction, exclusive_transaction_begin_throws_and_not_rollback)
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, exclusiveBegin()).WillOnce(Throw(Sqlite::Exception())); EXPECT_CALL(mockTransactionBackend, exclusiveBegin(_)).WillOnce(Throw(Sqlite::Exception()));
EXPECT_CALL(mockTransactionBackend, rollback()).Times(0); EXPECT_CALL(mockTransactionBackend, rollback(_)).Times(0);
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
ASSERT_ANY_THROW(ExclusiveTransaction{mockTransactionBackend}); ASSERT_ANY_THROW(ExclusiveTransaction{mockTransactionBackend});
@@ -252,7 +252,7 @@ TEST_F(SqliteTransaction, exclusive_transaction_begin_throws_and_not_rollback)
TEST_F(SqliteTransaction, transaction_commit_throws) TEST_F(SqliteTransaction, transaction_commit_throws)
{ {
ON_CALL(mockTransactionBackend, commit()).WillByDefault(Throw(Sqlite::Exception())); ON_CALL(mockTransactionBackend, commit(_)).WillByDefault(Throw(Sqlite::Exception()));
ImmediateTransaction transaction{mockTransactionBackend}; ImmediateTransaction transaction{mockTransactionBackend};
ASSERT_THROW(transaction.commit(), Sqlite::Exception); ASSERT_THROW(transaction.commit(), Sqlite::Exception);
@@ -260,14 +260,14 @@ TEST_F(SqliteTransaction, transaction_commit_throws)
TEST_F(SqliteTransaction, transaction_rollback_in_destructor_throws) TEST_F(SqliteTransaction, transaction_rollback_in_destructor_throws)
{ {
ON_CALL(mockTransactionBackend, rollback()).WillByDefault(Throw(Sqlite::Exception())); ON_CALL(mockTransactionBackend, rollback(_)).WillByDefault(Throw(Sqlite::Exception()));
ASSERT_THROW(ExclusiveTransaction{mockTransactionBackend}, Sqlite::Exception); ASSERT_THROW(ExclusiveTransaction{mockTransactionBackend}, Sqlite::Exception);
} }
TEST_F(SqliteTransaction, transaction_rollback_in_destructor_dont_throws) TEST_F(SqliteTransaction, transaction_rollback_in_destructor_dont_throws)
{ {
ON_CALL(mockTransactionBackend, rollback()).WillByDefault(Throw(Sqlite::Exception())); ON_CALL(mockTransactionBackend, rollback(_)).WillByDefault(Throw(Sqlite::Exception()));
ASSERT_NO_THROW(ExclusiveNonThrowingDestructorTransaction{mockTransactionBackend}); ASSERT_NO_THROW(ExclusiveNonThrowingDestructorTransaction{mockTransactionBackend});
} }
@@ -277,8 +277,8 @@ TEST_F(SqliteTransaction, immediate_session_transaction_commit)
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateSessionBegin()); EXPECT_CALL(mockTransactionBackend, immediateSessionBegin(_));
EXPECT_CALL(mockTransactionBackend, sessionCommit()); EXPECT_CALL(mockTransactionBackend, sessionCommit(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
ImmediateSessionTransaction transaction{mockTransactionBackend}; ImmediateSessionTransaction transaction{mockTransactionBackend};
@@ -290,8 +290,8 @@ TEST_F(SqliteTransaction, immediate_session_transaction_roll_back)
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateSessionBegin()); EXPECT_CALL(mockTransactionBackend, immediateSessionBegin(_));
EXPECT_CALL(mockTransactionBackend, sessionRollback()); EXPECT_CALL(mockTransactionBackend, sessionRollback(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
ImmediateSessionTransaction transaction{mockTransactionBackend}; ImmediateSessionTransaction transaction{mockTransactionBackend};
@@ -299,14 +299,14 @@ TEST_F(SqliteTransaction, immediate_session_transaction_roll_back)
TEST_F(SqliteTransaction, session_transaction_rollback_in_destructor_throws) TEST_F(SqliteTransaction, session_transaction_rollback_in_destructor_throws)
{ {
ON_CALL(mockTransactionBackend, sessionRollback()).WillByDefault(Throw(Sqlite::Exception())); ON_CALL(mockTransactionBackend, sessionRollback(_)).WillByDefault(Throw(Sqlite::Exception()));
ASSERT_THROW(ImmediateSessionTransaction{mockTransactionBackend}, Sqlite::Exception); ASSERT_THROW(ImmediateSessionTransaction{mockTransactionBackend}, Sqlite::Exception);
} }
TEST_F(SqliteTransaction, immidiate_session_transaction_begin_throws) TEST_F(SqliteTransaction, immidiate_session_transaction_begin_throws)
{ {
ON_CALL(mockTransactionBackend, immediateSessionBegin()).WillByDefault(Throw(Sqlite::Exception())); ON_CALL(mockTransactionBackend, immediateSessionBegin(_)).WillByDefault(Throw(Sqlite::Exception()));
ASSERT_THROW(ImmediateSessionTransaction{mockTransactionBackend}, Sqlite::Exception); ASSERT_THROW(ImmediateSessionTransaction{mockTransactionBackend}, Sqlite::Exception);
} }
@@ -316,8 +316,8 @@ TEST_F(SqliteTransaction, immediate_session_transaction_begin_throws_and_not_rol
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateSessionBegin()).WillOnce(Throw(Sqlite::Exception())); EXPECT_CALL(mockTransactionBackend, immediateSessionBegin(_)).WillOnce(Throw(Sqlite::Exception()));
EXPECT_CALL(mockTransactionBackend, sessionRollback()).Times(0); EXPECT_CALL(mockTransactionBackend, sessionRollback(_)).Times(0);
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
ASSERT_ANY_THROW(ImmediateSessionTransaction{mockTransactionBackend}); ASSERT_ANY_THROW(ImmediateSessionTransaction{mockTransactionBackend});
@@ -328,9 +328,9 @@ TEST_F(SqliteTransaction, with_implicit_transaction_no_return_does_not_commit)
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin()).Times(0); EXPECT_CALL(mockTransactionBackend, deferredBegin(_)).Times(0);
EXPECT_CALL(callableMock, Call()); EXPECT_CALL(callableMock, Call());
EXPECT_CALL(mockTransactionBackend, commit()).Times(0); EXPECT_CALL(mockTransactionBackend, commit(_)).Times(0);
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
Sqlite::withImplicitTransaction(mockTransactionBackend, callableMock.AsStdFunction()); Sqlite::withImplicitTransaction(mockTransactionBackend, callableMock.AsStdFunction());
@@ -341,9 +341,9 @@ TEST_F(SqliteTransaction, with_implicit_transaction_with_return_does_not_commit)
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin()).Times(0); EXPECT_CALL(mockTransactionBackend, deferredBegin(_)).Times(0);
EXPECT_CALL(callableWithReturnMock, Call()); EXPECT_CALL(callableWithReturnMock, Call());
EXPECT_CALL(mockTransactionBackend, commit()).Times(0); EXPECT_CALL(mockTransactionBackend, commit(_)).Times(0);
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
Sqlite::withImplicitTransaction(mockTransactionBackend, callableWithReturnMock.AsStdFunction()); Sqlite::withImplicitTransaction(mockTransactionBackend, callableWithReturnMock.AsStdFunction());
@@ -365,9 +365,9 @@ TEST_F(SqliteTransaction, with_implicit_transaction_do_calls_rollsback_for_excep
ON_CALL(callableMock, Call()).WillByDefault(Throw(std::exception{})); ON_CALL(callableMock, Call()).WillByDefault(Throw(std::exception{}));
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin()).Times(0); EXPECT_CALL(mockTransactionBackend, deferredBegin(_)).Times(0);
EXPECT_CALL(callableMock, Call()); EXPECT_CALL(callableMock, Call());
EXPECT_CALL(mockTransactionBackend, rollback()).Times(0); EXPECT_CALL(mockTransactionBackend, rollback(_)).Times(0);
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
try { try {
@@ -381,9 +381,9 @@ TEST_F(SqliteTransaction, with_deferred_transaction_no_return_commit)
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin()); EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
EXPECT_CALL(callableMock, Call()); EXPECT_CALL(callableMock, Call());
EXPECT_CALL(mockTransactionBackend, commit()); EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
Sqlite::withDeferredTransaction(mockTransactionBackend, callableMock.AsStdFunction()); Sqlite::withDeferredTransaction(mockTransactionBackend, callableMock.AsStdFunction());
@@ -394,9 +394,9 @@ TEST_F(SqliteTransaction, with_deferred_transaction_with_return_commit)
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin()); EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
EXPECT_CALL(callableWithReturnMock, Call()); EXPECT_CALL(callableWithReturnMock, Call());
EXPECT_CALL(mockTransactionBackend, commit()); EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
Sqlite::withDeferredTransaction(mockTransactionBackend, callableWithReturnMock.AsStdFunction()); Sqlite::withDeferredTransaction(mockTransactionBackend, callableWithReturnMock.AsStdFunction());
@@ -418,9 +418,9 @@ TEST_F(SqliteTransaction, with_deferred_transaction_rollsback_for_exception)
ON_CALL(callableMock, Call()).WillByDefault(Throw(std::exception{})); ON_CALL(callableMock, Call()).WillByDefault(Throw(std::exception{}));
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin()); EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
EXPECT_CALL(callableMock, Call()); EXPECT_CALL(callableMock, Call());
EXPECT_CALL(mockTransactionBackend, rollback()); EXPECT_CALL(mockTransactionBackend, rollback(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
try { try {
@@ -434,9 +434,9 @@ TEST_F(SqliteTransaction, with_immediate_transaction_no_return_commit)
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateBegin()); EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
EXPECT_CALL(callableMock, Call()); EXPECT_CALL(callableMock, Call());
EXPECT_CALL(mockTransactionBackend, commit()); EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
Sqlite::withImmediateTransaction(mockTransactionBackend, callableMock.AsStdFunction()); Sqlite::withImmediateTransaction(mockTransactionBackend, callableMock.AsStdFunction());
@@ -447,9 +447,9 @@ TEST_F(SqliteTransaction, with_immediate_transaction_with_return_commit)
InSequence s; InSequence s;
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateBegin()); EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
EXPECT_CALL(callableWithReturnMock, Call()); EXPECT_CALL(callableWithReturnMock, Call());
EXPECT_CALL(mockTransactionBackend, commit()); EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
Sqlite::withImmediateTransaction(mockTransactionBackend, callableWithReturnMock.AsStdFunction()); Sqlite::withImmediateTransaction(mockTransactionBackend, callableWithReturnMock.AsStdFunction());
@@ -471,9 +471,9 @@ TEST_F(SqliteTransaction, with_immediate_transaction_rollsback_for_exception)
ON_CALL(callableMock, Call()).WillByDefault(Throw(std::exception{})); ON_CALL(callableMock, Call()).WillByDefault(Throw(std::exception{}));
EXPECT_CALL(mockTransactionBackend, lock()); EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateBegin()); EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
EXPECT_CALL(callableMock, Call()); EXPECT_CALL(callableMock, Call());
EXPECT_CALL(mockTransactionBackend, rollback()); EXPECT_CALL(mockTransactionBackend, rollback(_));
EXPECT_CALL(mockTransactionBackend, unlock()); EXPECT_CALL(mockTransactionBackend, unlock());
try { try {