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

View File

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

View File

@@ -19,34 +19,40 @@ namespace Sqlite {
class Database::Statements
{
public:
Statements(Database &database)
Statements(Database &database, const source_location &sourceLocation)
: database(database)
, sourceLocation(sourceLocation)
{}
public:
Database &database;
ReadWriteStatement<> deferredBegin{"BEGIN", database};
ReadWriteStatement<> immediateBegin{"BEGIN IMMEDIATE", database};
ReadWriteStatement<> exclusiveBegin{"BEGIN EXCLUSIVE", database};
ReadWriteStatement<> commitBegin{"COMMIT", database};
ReadWriteStatement<> rollbackBegin{"ROLLBACK", database};
source_location sourceLocation;
ReadWriteStatement<> deferredBegin{"BEGIN", database, sourceLocation};
ReadWriteStatement<> immediateBegin{"BEGIN IMMEDIATE", database, sourceLocation};
ReadWriteStatement<> exclusiveBegin{"BEGIN EXCLUSIVE", database, sourceLocation};
ReadWriteStatement<> commitBegin{"COMMIT", database, sourceLocation};
ReadWriteStatement<> rollbackBegin{"ROLLBACK", database, sourceLocation};
Sessions sessions{database, "main", "databaseSessions"};
};
Database::Database()
: m_databaseBackend(*this)
Database::Database(const source_location &sourceLocation)
: m_databaseBackend(*this, sourceLocation)
{
}
Database::Database(Utils::PathString databaseFilePath, JournalMode journalMode, LockingMode lockingMode)
: Database{std::move(databaseFilePath), 0ms, journalMode, lockingMode}
Database::Database(Utils::PathString databaseFilePath,
JournalMode journalMode,
LockingMode lockingMode,
const source_location &sourceLocation)
: Database{std::move(databaseFilePath), 0ms, journalMode, lockingMode, sourceLocation}
{}
Database::Database(Utils::PathString databaseFilePath,
std::chrono::milliseconds busyTimeout,
JournalMode journalMode,
LockingMode lockingMode)
: m_databaseBackend(*this)
LockingMode lockingMode,
const source_location &sourceLocation)
: m_databaseBackend(*this, sourceLocation)
, m_busyTimeout(busyTimeout)
{
std::lock_guard lock{*this};
@@ -62,36 +68,38 @@ Database::Database(Utils::PathString databaseFilePath,
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)
m_databaseBackend.setBusyTimeout(m_busyTimeout);
else
m_databaseBackend.registerBusyHandler();
m_databaseBackend.setLockingMode(lockingMode);
m_databaseBackend.setJournalMode(m_journalMode);
registerTransactionStatements();
m_databaseBackend.registerBusyHandler(sourceLocation);
m_databaseBackend.setLockingMode(lockingMode, sourceLocation);
m_databaseBackend.setJournalMode(m_journalMode, sourceLocation);
registerTransactionStatements(sourceLocation);
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));
setDatabaseFilePath(std::move(databaseFilePath));
open(lockingMode);
open(lockingMode, sourceLocation);
}
void Database::close()
void Database::close(const source_location &sourceLocation)
{
m_isOpen = false;
deleteTransactionStatements();
m_databaseBackend.close();
m_databaseBackend.close(sourceLocation);
}
bool Database::isInitialized() const
@@ -124,9 +132,9 @@ void Database::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
@@ -144,9 +152,9 @@ JournalMode Database::journalMode() const
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)
@@ -159,14 +167,14 @@ OpenMode Database::openMode() const
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()
@@ -174,68 +182,70 @@ void Database::deleteTransactionStatements()
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->sessions.create();
m_statements->immediateBegin.execute(sourceLocation);
m_statements->sessions.create(sourceLocation);
}
void Database::sessionCommit()
void Database::sessionCommit(const source_location &sourceLocation)
{
m_statements->sessions.commit();
m_statements->commitBegin.execute();
m_statements->sessions.commit(sourceLocation);
m_statements->commitBegin.execute(sourceLocation);
}
void Database::sessionRollback()
void Database::sessionRollback(const source_location &sourceLocation)
{
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);
}
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};
auto tables = tablesStatement.template values<Utils::SmallString>();
auto tables = tablesStatement.template values<Utils::SmallString>(sourceLocation);
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()

View File

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

View File

@@ -26,13 +26,14 @@ namespace Sqlite {
using namespace std::literals;
DatabaseBackend::DatabaseBackend(Database &database)
DatabaseBackend::DatabaseBackend(Database &database, const source_location &sourceLocation)
: m_database(database)
, m_databaseHandle(nullptr)
, m_busyHandler([](int) {
std::this_thread::sleep_for(10ms);
return true;
})
, m_sourceLocation{sourceLocation}
{
}
@@ -41,16 +42,18 @@ DatabaseBackend::~DatabaseBackend()
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);
checkMmapSizeIsSet(resultCode);
checkMmapSizeIsSet(resultCode, sourceLocation);
}
void DatabaseBackend::activateMultiThreading()
void DatabaseBackend::activateMultiThreading(const source_location &sourceLocation)
{
int resultCode = sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
checkIfMultithreadingIsActivated(resultCode);
checkIfMultithreadingIsActivated(resultCode, sourceLocation);
}
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;
}
void DatabaseBackend::activateLogging()
void DatabaseBackend::activateLogging(const source_location &sourceLocation)
{
if (qEnvironmentVariableIsSet("QTC_SQLITE_LOGGING")) {
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();
checkInitializeSqliteLibraryWasSuccesful(resultCode);
checkInitializeSqliteLibraryWasSuccesful(resultCode, sourceLocation);
}
void DatabaseBackend::shutdownSqliteLibrary()
void DatabaseBackend::shutdownSqliteLibrary(const source_location &sourceLocation)
{
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);
checkIfLogCouldBeCheckpointed(resultCode);
int resultCode = sqlite3_wal_checkpoint_v2(sqliteDatabaseHandle(sourceLocation),
nullptr,
SQLITE_CHECKPOINT_FULL,
nullptr,
nullptr);
checkIfLogCouldBeCheckpointed(resultCode, sourceLocation);
}
void DatabaseBackend::open(Utils::SmallStringView databaseFilePath,
OpenMode openMode,
JournalMode journalMode)
JournalMode journalMode,
const source_location &sourceLocation)
{
checkCanOpenDatabase(databaseFilePath);
checkCanOpenDatabase(databaseFilePath, sourceLocation);
sqlite3 *handle = m_databaseHandle.get();
int resultCode = sqlite3_open_v2(std::string(databaseFilePath).c_str(),
@@ -97,42 +105,46 @@ void DatabaseBackend::open(Utils::SmallStringView databaseFilePath,
nullptr);
m_databaseHandle.reset(handle);
checkDatabaseCouldBeOpened(resultCode);
checkDatabaseCouldBeOpened(resultCode, sourceLocation);
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();
}
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, "'"}),
m_database}
.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 {
@@ -160,67 +172,69 @@ LockingMode pragmaToLockingMode(Utils::SmallStringView pragma)
}
} // namespace
void DatabaseBackend::setLockingMode(LockingMode lockingMode)
void DatabaseBackend::setLockingMode(LockingMode lockingMode, const source_location &sourceLocation)
{
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 = "}
+ Utils::SmallString::number(version),
m_database}
.execute();
m_database,
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 {
ReadWriteStatement<0> statement(sqlStatement, m_database);
statement.execute();
ReadWriteStatement<0> statement(sqlStatement, m_database, sourceLocation);
statement.execute(sourceLocation);
} 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());
checkDatabaseClosing(resultCode);
checkDatabaseClosing(resultCode, sourceLocation);
m_databaseHandle.release();
}
@@ -246,66 +260,72 @@ int busyHandlerCallback(void *userData, int counter)
} // 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,
&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_exec(sqliteDatabaseHandle(), "VACUUM", nullptr, nullptr, nullptr);
sqlite3_db_config(sqliteDatabaseHandle(), SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
sqlite3_db_config(sqliteDatabaseHandle(sourceLocation), SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
sqlite3_exec(sqliteDatabaseHandle(sourceLocation), "VACUUM", nullptr, nullptr, nullptr);
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)
throw DatabaseIsAlreadyClosed();
throw DatabaseIsAlreadyClosed(sourceLocation);
}
void DatabaseBackend::checkDatabaseClosing(int resultCode)
void DatabaseBackend::checkDatabaseClosing(int resultCode, const source_location &sourceLocation)
{
switch (resultCode) {
case SQLITE_OK: return;
case SQLITE_BUSY:
throw DatabaseIsBusy();
throw DatabaseIsBusy(sourceLocation);
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())
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()))
throw WrongFilePath(Utils::SmallString(databaseFilePath));
throw WrongFilePath(Utils::SmallString(databaseFilePath), sourceLocation);
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) {
try {
Sqlite::throwError(resultCode, sqliteDatabaseHandle());
Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
} catch (...) {
closeWithoutException();
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)
throw DatabaseIsNotOpen();
throw DatabaseIsNotOpen(sourceLocation);
}
void DatabaseBackend::checkPragmaValue(Utils::SmallStringView databaseValue,
Utils::SmallStringView expectedValue)
Utils::SmallStringView expectedValue,
const source_location &sourceLocation)
{
if (databaseValue != expectedValue)
throw PragmaValueNotSet();
throw PragmaValueNotSet(sourceLocation);
}
void DatabaseBackend::checkDatabaseHandleIsNotNull() const
void DatabaseBackend::checkDatabaseHandleIsNotNull(const source_location &sourceLocation) const
{
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)
throw MultiTheadingCannotBeActivated{};
throw MultiTheadingCannotBeActivated{sourceLocation};
}
void DatabaseBackend::checkIfLoogingIsActivated(int resultCode)
void DatabaseBackend::checkIfLoogingIsActivated(int resultCode, const source_location &sourceLocation)
{
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)
throw MemoryMappingCannotBeChanged{};
throw MemoryMappingCannotBeChanged{sourceLocation};
}
void DatabaseBackend::checkInitializeSqliteLibraryWasSuccesful(int resultCode)
void DatabaseBackend::checkInitializeSqliteLibraryWasSuccesful(int resultCode,
const source_location &sourceLocation)
{
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)
throw LibraryCannotBeShutdown{};
throw LibraryCannotBeShutdown{sourceLocation};
}
void DatabaseBackend::checkIfLogCouldBeCheckpointed(int resultCode)
void DatabaseBackend::checkIfLogCouldBeCheckpointed(int resultCode,
const source_location &sourceLocation)
{
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)
throw BusyTimerCannotBeSet{};
throw BusyTimerCannotBeSet{sourceLocation};
}
namespace {
@@ -398,12 +424,13 @@ Utils::SmallStringView DatabaseBackend::journalModeToPragma(JournalMode journalM
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);
if (index < 0)
throw PragmaValueCannotBeTransformed{};
throw PragmaValueCannotBeTransformed{sourceLocation};
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()));
}
void DatabaseBackend::walCheckpointFull()
void DatabaseBackend::walCheckpointFull(const source_location &sourceLocation)
{
int resultCode = sqlite3_wal_checkpoint_v2(m_databaseHandle.get(),
nullptr,
@@ -441,7 +468,7 @@ void DatabaseBackend::walCheckpointFull()
nullptr);
if (resultCode != SQLITE_OK)
Sqlite::throwError(resultCode, sqliteDatabaseHandle());
Sqlite::throwError(resultCode, sqliteDatabaseHandle(sourceLocation), sourceLocation);
}
void DatabaseBackend::setUpdateHook(
@@ -456,10 +483,11 @@ void DatabaseBackend::resetUpdateHook()
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);
registerBusyHandler();
registerBusyHandler(sourceLocation);
}
namespace {
@@ -473,36 +501,39 @@ int progressHandlerCallback(void *userData)
} // namespace
void DatabaseBackend::setProgressHandler(int operationCount, ProgressHandler &&progressHandler)
void DatabaseBackend::setProgressHandler(int operationCount,
ProgressHandler &&progressHandler,
const source_location &sourceLocation)
{
m_progressHandler = std::move(progressHandler);
if (m_progressHandler)
sqlite3_progress_handler(sqliteDatabaseHandle(),
sqlite3_progress_handler(sqliteDatabaseHandle(sourceLocation),
operationCount,
&progressHandlerCallback,
&m_progressHandler);
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>
Type DatabaseBackend::toValue(Utils::SmallStringView sqlStatement) const
Type DatabaseBackend::toValue(Utils::SmallStringView sqlStatement,
const source_location &sourceLocation) const
{
try {
ReadWriteStatement<1> statement(sqlStatement, m_database);
ReadWriteStatement<1> statement(sqlStatement, m_database, sourceLocation);
statement.next();
statement.next(sourceLocation);
return statement.fetchValue<Type>(0);
} catch (StatementIsBusy &) {
return toValue<Type>(sqlStatement);
return toValue<Type>(sqlStatement, sourceLocation);
}
}

View File

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

View File

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

View File

@@ -147,198 +147,231 @@ public:
class SQLITE_EXPORT InputOutputCannotAuthenticate : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotBeginAtomic : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotCommitAtomic : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotRollbackAtomic : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputDataError : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputBlocked : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputFileSystemIsCorrupt : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputVNodeError : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputConvPathFailed : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotGetTemporaryPath : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotMemoryMap : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotDeleteNonExistingFile : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotSeek : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotMapSharedMemory : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotLockSharedMemory : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotEnlargeSharedMemory : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotOpenSharedMemory : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotCloseDirectory : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotClose : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotLock : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotCheckReservedLock : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotAccess : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputNoMemory : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotDelete : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotReadLock : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotUnlock : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotFsStat : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotTruncate : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotSynchronizeDirectory : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotSynchronizeFile : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotWrite : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotShortRead : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
class SQLITE_EXPORT InputOutputCannotRead : public InputOutputError
{
public:
using InputOutputError::InputOutputError;
const char *what() const noexcept override;
};
@@ -896,6 +929,8 @@ public:
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

View File

@@ -35,9 +35,9 @@ void pathExists(sqlite3_context *context, int, sqlite3_value **arguments)
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",
1,
SQLITE_UTF8 | SQLITE_INNOCUOUS,

View File

@@ -7,6 +7,7 @@
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

View File

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

View File

@@ -11,21 +11,28 @@ class ProgressHandler
{
public:
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_sourceLocation{sourceLocation}
{
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()
{
std::unique_lock<TransactionInterface> locker{m_database};
m_database.backend().resetProgressHandler();
m_database.backend().resetProgressHandler(m_sourceLocation);
}
private:
Database &m_database;
source_location m_sourceLocation;
};
} // namespace Sqlite

View File

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

View File

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

View File

@@ -14,19 +14,19 @@ namespace Sqlite {
namespace {
void checkResultCode(int resultCode)
void checkResultCode(int resultCode, const source_location &sourceLocation)
{
switch (resultCode) {
case SQLITE_NOMEM:
throw std::bad_alloc();
case SQLITE_SCHEMA:
throw CannotApplyChangeSet();
throw CannotApplyChangeSet(sourceLocation);
case SQLITE_MISUSE:
throw ChangeSetIsMisused();
throw ChangeSetIsMisused(sourceLocation);
}
if (resultCode != SQLITE_OK)
throw UnknowError();
throw UnknowError({}, sourceLocation);
}
int xConflict(void *, int conflict, sqlite3_changeset_iter *)
@@ -48,11 +48,12 @@ int xConflict(void *, int conflict, sqlite3_changeset_iter *)
}
} // namespace
void Sessions::attachTables(const Utils::SmallStringVector &tableNames)
void Sessions::attachTables(const Utils::SmallStringVector &tableNames,
const source_location &sourceLocation)
{
for (Utils::SmallStringView tableName : tableNames) {
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);
}
void Sessions::create()
void Sessions::create(const source_location &sourceLocation)
{
sqlite3_session *newSession = nullptr;
int resultCode = sqlite3session_create(database.backend().sqliteDatabaseHandle(),
int resultCode = sqlite3session_create(database.backend().sqliteDatabaseHandle(sourceLocation),
std::string(databaseName).c_str(),
&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())) {
SessionChangeSet changeSet{*this};
insertSession.write(changeSet.asBlobView());
insertSession.write(sourceLocation, changeSet.asBlobView());
}
session.reset();
@@ -92,7 +93,8 @@ void Sessions::rollback()
session.reset();
}
void Internal::SessionsBase::createSessionTable(Database &database)
void Internal::SessionsBase::createSessionTable(Database &database,
const source_location &sourceLocation)
{
Sqlite::Table table;
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("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 ",
sessionsTableName,
" ORDER BY id DESC"}),
database};
database,
sourceLocation};
auto changeSets = selectChangeSets.values<SessionChangeSet, 1024>();
auto changeSets = selectChangeSets.values<SessionChangeSet, 1024>(sourceLocation);
for (auto &changeSet : changeSets) {
int resultCode = sqlite3changeset_apply_v2(database.backend().sqliteDatabaseHandle(),
int resultCode = sqlite3changeset_apply_v2(database.backend().sqliteDatabaseHandle(
sourceLocation),
changeSet.size(),
changeSet.data(),
nullptr,
@@ -123,21 +127,23 @@ void Sessions::revert()
nullptr,
SQLITE_CHANGESETAPPLY_INVERT
| 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 ",
sessionsTableName,
" ORDER BY id"}),
database};
database,
sourceLocation};
auto changeSets = selectChangeSets.values<SessionChangeSet, 1024>();
auto changeSets = selectChangeSets.values<SessionChangeSet, 1024>(sourceLocation);
for (auto &changeSet : changeSets) {
int resultCode = sqlite3changeset_apply_v2(database.backend().sqliteDatabaseHandle(),
int resultCode = sqlite3changeset_apply_v2(database.backend().sqliteDatabaseHandle(
sourceLocation),
changeSet.size(),
changeSet.data(),
nullptr,
@@ -146,31 +152,35 @@ void Sessions::apply()
nullptr,
nullptr,
SQLITE_CHANGESETAPPLY_NOSAVEPOINT);
checkResultCode(resultCode);
checkResultCode(resultCode, sourceLocation);
}
}
void Sessions::applyAndUpdateSessions()
void Sessions::applyAndUpdateSessions(const source_location &sourceLocation)
{
create();
apply();
deleteAll();
commit();
create(sourceLocation);
apply(sourceLocation);
deleteAll(sourceLocation);
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 ",
sessionsTableName,
" 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)

View File

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

View File

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

View File

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

View File

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

View File

@@ -11,6 +11,9 @@
namespace QmlDesigner {
namespace {
constexpr auto sourceLocation = Sqlite::source_location::current();
struct Initializer
{
Initializer(Sqlite::Database &database, bool isInitialized)
@@ -34,7 +37,7 @@ struct Initializer
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)
{
Sqlite::ImmediateSessionTransaction transaction{database};
Sqlite::ImmediateTransaction transaction{database};
s->upsertPropertyEditorPathIdStatement.write(typeId, pathId);

View File

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

View File

@@ -11,14 +11,14 @@
class MockSqliteTransactionBackend : public Sqlite::TransactionInterface
{
public:
MOCK_METHOD0(deferredBegin, void ());
MOCK_METHOD0(immediateBegin, void ());
MOCK_METHOD0(exclusiveBegin, void ());
MOCK_METHOD0(commit, void ());
MOCK_METHOD0(rollback, void ());
MOCK_METHOD0(lock, void ());
MOCK_METHOD0(unlock, void ());
MOCK_METHOD0(immediateSessionBegin, void());
MOCK_METHOD0(sessionCommit, void());
MOCK_METHOD0(sessionRollback, void());
MOCK_METHOD(void, deferredBegin, (const Sqlite::source_location &sourceLocation));
MOCK_METHOD(void, immediateBegin, (const Sqlite::source_location &sourceLocation));
MOCK_METHOD(void, exclusiveBegin, (const Sqlite::source_location &sourceLocation));
MOCK_METHOD(void, commit, (const Sqlite::source_location &sourceLocation));
MOCK_METHOD(void, rollback, (const Sqlite::source_location &sourceLocation));
MOCK_METHOD(void, lock, ());
MOCK_METHOD(void, unlock, ());
MOCK_METHOD(void, immediateSessionBegin, (const Sqlite::source_location &sourceLocation));
MOCK_METHOD(void, sessionCommit, (const Sqlite::source_location &sourceLocation));
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, 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));
@@ -41,7 +49,9 @@ public:
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,
setUpdateHook,

View File

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

View File

@@ -26,6 +26,8 @@ using Sqlite::JournalMode;
using Sqlite::OpenMode;
using Sqlite::Table;
constexpr auto sourceLocation = Sqlite::source_location::current();
class SqliteDatabase : public ::testing::Test
{
protected:
@@ -199,37 +201,37 @@ TEST_F(SqliteDatabase, last_row_id)
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)
{
ASSERT_NO_THROW(transactionInterface.immediateBegin());
ASSERT_NO_THROW(transactionInterface.immediateBegin(sourceLocation));
transactionInterface.commit();
transactionInterface.commit(sourceLocation);
}
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)
{
transactionInterface.deferredBegin();
transactionInterface.deferredBegin(sourceLocation);
ASSERT_NO_THROW(transactionInterface.commit());
ASSERT_NO_THROW(transactionInterface.commit(sourceLocation));
}
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)

View File

@@ -24,6 +24,8 @@ using Sqlite::OpenMode;
using Sqlite::Exception;
using Sqlite::WriteStatement;
constexpr auto sourceLocation = Sqlite::source_location::current();
class SqliteDatabaseBackend : public ::testing::Test
{
protected:
@@ -31,7 +33,10 @@ protected:
{
database.lock();
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)
@@ -49,56 +54,60 @@ using SqliteDatabaseBackendSlowTest = SqliteDatabaseBackend;
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);
}
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)
{
ASSERT_THROW(databaseBackend.open("/xxx/SqliteDatabaseBackendTest.db",
OpenMode::ReadWrite,
Sqlite::JournalMode::Wal),
Sqlite::JournalMode::Wal,
sourceLocation),
Sqlite::WrongFilePath);
}
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)
{
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)
{
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)
{
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)
{
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)

View File

@@ -56,6 +56,8 @@ bool compareValue(SqliteTestStatement<2, 1> &statement, Type value, int column)
return false;
}
constexpr auto sourceLocation = Sqlite::source_location::current();
MATCHER_P3(HasValues,
value1,
value2,
@@ -66,9 +68,9 @@ MATCHER_P3(HasValues,
Database &database = arg.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);
}
@@ -78,9 +80,9 @@ MATCHER_P(HasNullValues, rowid, std::string(negation ? "isn't null" : "is null")
Database &database = arg.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();
}
@@ -163,7 +165,7 @@ TEST_F(SqliteStatement, count_rows)
{
SqliteTestStatement<3> statement("SELECT * FROM test", database);
int nextCount = 0;
while (statement.next())
while (statement.next(sourceLocation))
++nextCount;
int sqlCount = ReadStatement<1>::toValue<int>("SELECT count(*) FROM test", database);
@@ -174,9 +176,9 @@ TEST_F(SqliteStatement, count_rows)
TEST_F(SqliteStatement, value)
{
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<int64_t>(0), 0);
@@ -226,8 +228,8 @@ TEST_F(SqliteStatement, bind_null)
database.execute("INSERT INTO test VALUES (NULL, 323, 344)");
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE name IS ?", database);
statement.bindNull(1);
statement.next();
statement.bindNull(1, sourceLocation);
statement.next(sourceLocation);
ASSERT_TRUE(statement.fetchValueView(0).isNull());
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)");
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE name IS ?", database);
statement.bind(1, Sqlite::NullValue{});
statement.next();
statement.bind(1, Sqlite::NullValue{}, sourceLocation);
statement.next(sourceLocation);
ASSERT_TRUE(statement.fetchValueView(0).isNull());
ASSERT_THAT(statement.fetchValue<int>(1), 323);
@@ -250,11 +252,11 @@ TEST_F(SqliteStatement, bind_invalid_int_id_to_null)
TestIntId id;
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
statement.bind(1, id);
statement.next();
statement.bind(1, id, sourceLocation);
statement.next(sourceLocation);
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);
}
@@ -263,11 +265,11 @@ TEST_F(SqliteStatement, bind_invalid_compound_id_to_null)
CompoundId id;
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
statement.bind(1, id);
statement.next();
statement.bind(1, id, sourceLocation);
statement.next(sourceLocation);
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);
}
@@ -276,11 +278,11 @@ TEST_F(SqliteStatement, bind_int_id)
TestIntId id{TestIntId::create(42)};
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
statement.bind(1, id);
statement.next();
statement.bind(1, id, sourceLocation);
statement.next(sourceLocation);
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.fetchIntValue(0), 42);
}
@@ -290,11 +292,11 @@ TEST_F(SqliteStatement, bind_compound_id)
CompoundId id = CompoundId::create(42);
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
statement.bind(1, id);
statement.next();
statement.bind(1, id, sourceLocation);
statement.next(sourceLocation);
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.fetchIntValue(0), 42);
}
@@ -305,11 +307,11 @@ TEST_F(SqliteStatement, bind_special_state_id)
constexpr TestIntId unresolvedTypeId = TestIntId::createSpecialState(SpecialIdState::Unresolved);
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
statement.bind(1, unresolvedTypeId);
statement.next();
statement.bind(1, unresolvedTypeId, sourceLocation);
statement.next(sourceLocation);
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.fetchIntValue(0), -1);
}
@@ -319,11 +321,11 @@ TEST_F(SqliteStatement, bind_invalid_long_long_id_to_null)
TestLongLongId id;
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
statement.bind(1, id);
statement.next();
statement.bind(1, id, sourceLocation);
statement.next(sourceLocation);
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);
}
@@ -332,11 +334,11 @@ TEST_F(SqliteStatement, bind_long_long_id)
TestLongLongId id{TestLongLongId::create(42)};
SqliteTestStatement<0, 1> statement("INSERT INTO test VALUES ('id', 323, ?)", database);
statement.bind(1, id);
statement.next();
statement.bind(1, id, sourceLocation);
statement.next(sourceLocation);
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.fetchIntValue(0), 42);
}
@@ -345,8 +347,8 @@ TEST_F(SqliteStatement, bind_string)
{
SqliteTestStatement<2, 1> statement("SELECT name, number FROM test WHERE name=?", database);
statement.bind(1, Utils::SmallStringView("foo"));
statement.next();
statement.bind(1, Utils::SmallStringView("foo"), sourceLocation);
statement.next(sourceLocation);
ASSERT_THAT(statement.fetchSmallStringViewValue(0), "foo");
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);
statement.bind(1, 40);
statement.next();
statement.bind(1, 40, sourceLocation);
statement.next(sourceLocation);
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);
statement.bind(1, int64_t(40));
statement.next();
statement.bind(1, int64_t(40), sourceLocation);
statement.next(sourceLocation);
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);
statement.bind(1, 23.3);
statement.next();
statement.bind(1, 23.3, sourceLocation);
statement.next(sourceLocation);
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);
std::vector<long long> values{1, 1, 2, 3, 5};
statement.bind(1, values.data());
statement.next();
statement.bind(1, values.data(), sourceLocation);
statement.next(sourceLocation);
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);
std::vector<int> values{3, 10, 20, 33, 55};
statement.bind(1, values);
statement.next();
statement.next();
statement.next();
statement.next();
statement.bind(1, values, sourceLocation);
statement.next(sourceLocation);
statement.next(sourceLocation);
statement.next(sourceLocation);
statement.next(sourceLocation);
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);
std::vector<long long> values{3, 10, 20, 33, 55};
statement.bind(1, values);
statement.next();
statement.next();
statement.next();
statement.next();
statement.bind(1, values, sourceLocation);
statement.next(sourceLocation);
statement.next(sourceLocation);
statement.next(sourceLocation);
statement.next(sourceLocation);
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);
std::vector<double> values{3.3, 10.2, 20.54, 33.21, 55};
statement.bind(1, values);
statement.next();
statement.next();
statement.next();
statement.next();
statement.bind(1, values, sourceLocation);
statement.next(sourceLocation);
statement.next(sourceLocation);
statement.next(sourceLocation);
statement.next(sourceLocation);
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);
std::vector<const char *> values{"yi", "er", "san", "se", "wu"};
statement.bind(1, values);
statement.next();
statement.next();
statement.next();
statement.next();
statement.bind(1, values, sourceLocation);
statement.next(sourceLocation);
statement.next(sourceLocation);
statement.next(sourceLocation);
statement.next(sourceLocation);
ASSERT_THAT(statement.fetchSmallStringViewValue(0), Eq("se"));
}
@@ -456,8 +458,8 @@ TEST_F(SqliteStatement, bind_blob)
auto bytePointer = reinterpret_cast<const std::byte *>(chars);
Sqlite::BlobView bytes{bytePointer, sizeof(chars) - 1};
statement.bind(1, bytes);
statement.next();
statement.bind(1, bytes, sourceLocation);
statement.next(sourceLocation);
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);
Sqlite::BlobView bytes;
statement.bind(1, bytes);
statement.next();
statement.bind(1, bytes, sourceLocation);
statement.next(sourceLocation);
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);
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
@@ -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);
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)
{
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();
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);
statement.bindValues(Sqlite::NullValue{}, Sqlite::Value{}, 1);
statement.bindValues(sourceLocation, Sqlite::NullValue{}, Sqlite::Value{}, 1);
statement.execute();
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)
{
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());
@@ -1355,7 +1359,7 @@ TEST_F(SqliteStatement, get_value_calls_reset_if_exception_is_thrown)
int x = 0;
};
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());
@@ -1386,9 +1390,9 @@ TEST_F(SqliteStatement, get_range_with_transaction_without_arguments_calls)
MockSqliteStatement<1, 0> mockStatement{databaseMock};
EXPECT_CALL(databaseMock, lock());
EXPECT_CALL(databaseMock, deferredBegin());
EXPECT_CALL(databaseMock, deferredBegin(_));
EXPECT_CALL(mockStatement, reset());
EXPECT_CALL(databaseMock, commit());
EXPECT_CALL(databaseMock, commit(_));
EXPECT_CALL(databaseMock, unlock());
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)
{
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());
@@ -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)
{
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>();
EXPECT_CALL(mockStatement, reset());
@@ -1419,12 +1423,12 @@ TEST_F(SqliteStatement, get_range_with_transaction_without_arguments_calls_reset
{
InSequence s;
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, deferredBegin());
EXPECT_CALL(databaseMock, deferredBegin(_));
EXPECT_CALL(mockStatement, reset());
EXPECT_CALL(databaseMock, rollback());
EXPECT_CALL(databaseMock, rollback(_));
EXPECT_CALL(databaseMock, unlock());
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)
{
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());
@@ -1458,7 +1462,7 @@ TEST_F(SqliteStatement, reset_if_write_is_throwing_exception)
{
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("")));
EXPECT_CALL(mockStatement, reset());
@@ -1469,7 +1473,7 @@ TEST_F(SqliteStatement, reset_if_execute_throws_exception)
{
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());
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;
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);
}
@@ -1585,7 +1589,7 @@ TEST_F(SqliteStatement, read_callback_calls_reset_if_exception_is_thrown)
{
MockFunction<Sqlite::CallbackControl(Utils::SmallStringView, long long)> callbackMock;
MockSqliteStatement<2> mockStatement{databaseMock};
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
EXPECT_CALL(mockStatement, reset());
@@ -1626,7 +1630,7 @@ TEST_F(SqliteStatement, read_to_throws_for_error)
{
std::deque<FooValue> values;
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);
}
@@ -1635,7 +1639,7 @@ TEST_F(SqliteStatement, read_to_calls_reset_if_exception_is_thrown)
{
std::deque<FooValue> values;
MockSqliteStatement mockStatement{databaseMock};
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
ON_CALL(mockStatement, next(_)).WillByDefault(Throw(Sqlite::StatementHasError("")));
EXPECT_CALL(mockStatement, reset());

View File

@@ -74,9 +74,9 @@ TEST_F(SqliteTable, initialize_table)
table.addColumn("name");
table.addColumn("value");
EXPECT_CALL(databaseMock,
execute(Eq(
"CREATE TEMPORARY TABLE IF NOT EXISTS testTable(name, value) WITHOUT ROWID")));
EXPECT_CALL(
databaseMock,
execute(Eq("CREATE TEMPORARY TABLE IF NOT EXISTS testTable(name, value) WITHOUT ROWID"), _));
table.initialize(databaseMock);
}
@@ -90,13 +90,14 @@ TEST_F(SqliteTable, initialize_table_with_index)
table.addIndex({column});
table.addIndex({column2}, "value IS NOT NULL");
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name, value)")));
EXPECT_CALL(databaseMock,
execute(Eq(
"CREATE INDEX IF NOT EXISTS index_normal_testTable_name ON testTable(name)")));
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name, value)"), _));
EXPECT_CALL(
databaseMock,
execute(Eq("CREATE INDEX IF NOT EXISTS index_normal_testTable_name ON testTable(name)"), _));
EXPECT_CALL(databaseMock,
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);
}
@@ -110,14 +111,15 @@ TEST_F(SqliteTable, initialize_table_with_unique_index)
table.addUniqueIndex({column});
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(
databaseMock,
execute(Eq(
"CREATE UNIQUE INDEX IF NOT EXISTS index_unique_testTable_name ON testTable(name)")));
execute(
Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_unique_testTable_name ON testTable(name)"), _));
EXPECT_CALL(databaseMock,
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);
}
@@ -135,7 +137,8 @@ TEST_F(SqliteTable, add_foreign_key_column_with_table_calls)
EXPECT_CALL(databaseMock,
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);
}
@@ -156,7 +159,8 @@ TEST_F(SqliteTable, add_foreign_key_column_with_column_calls)
databaseMock,
execute(
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);
}
@@ -307,7 +311,8 @@ TEST_F(SqliteTable, add_primary_table_contraint)
const auto &nameColumn = table.addColumn("name");
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);
}
@@ -367,7 +372,8 @@ TEST_F(StrictSqliteTable, initialize_table)
EXPECT_CALL(databaseMock,
execute(Eq("CREATE TEMPORARY TABLE IF NOT EXISTS testTable(name ANY, value ANY) "
"WITHOUT ROWID, STRICT")));
"WITHOUT ROWID, STRICT"),
_));
table.initialize(databaseMock);
}
@@ -381,13 +387,14 @@ TEST_F(StrictSqliteTable, initialize_table_with_index)
table.addIndex({column});
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 INDEX IF NOT EXISTS index_normal_testTable_name ON testTable(name)")));
EXPECT_CALL(databaseMock, execute(Eq("CREATE TABLE testTable(name ANY, value ANY) STRICT"), _));
EXPECT_CALL(
databaseMock,
execute(Eq("CREATE INDEX IF NOT EXISTS index_normal_testTable_name ON testTable(name)"), _));
EXPECT_CALL(databaseMock,
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);
}
@@ -401,14 +408,15 @@ TEST_F(StrictSqliteTable, initialize_table_with_unique_index)
table.addUniqueIndex({column});
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(
databaseMock,
execute(Eq(
"CREATE UNIQUE INDEX IF NOT EXISTS index_unique_testTable_name ON testTable(name)")));
execute(
Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_unique_testTable_name ON testTable(name)"), _));
EXPECT_CALL(databaseMock,
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);
}
@@ -426,7 +434,8 @@ TEST_F(StrictSqliteTable, add_foreign_key_column_with_table_calls)
EXPECT_CALL(databaseMock,
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);
}
@@ -449,7 +458,8 @@ TEST_F(StrictSqliteTable, add_foreign_key_column_with_column_calls)
databaseMock,
execute(
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);
}
@@ -604,9 +614,9 @@ TEST_F(StrictSqliteTable, add_primary_table_contraint)
const auto &nameColumn = table.addColumn("name");
table.addPrimaryKeyContraint({idColumn, nameColumn});
EXPECT_CALL(databaseMock,
execute(
Eq("CREATE TABLE testTable(id ANY, name ANY, PRIMARY KEY(id, name)) STRICT")));
EXPECT_CALL(
databaseMock,
execute(Eq("CREATE TABLE testTable(id ANY, name ANY, PRIMARY KEY(id, name)) STRICT"), _));
table.initialize(databaseMock);
}

View File

@@ -4,15 +4,18 @@
#pragma once
#include <sqlitebasestatement.h>
template<int ResultCount, int BindParameterCount = 0>
class SqliteTestStatement
: public Sqlite::StatementImplementation<Sqlite::BaseStatement, ResultCount, BindParameterCount>
{
using Base = Sqlite::StatementImplementation<Sqlite::BaseStatement, ResultCount, BindParameterCount>;
static constexpr auto sourceLocation = Sqlite::source_location::current();
public:
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;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin());
EXPECT_CALL(mockTransactionBackend, commit());
EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock());
DeferredTransaction transaction{mockTransactionBackend};
@@ -48,8 +48,8 @@ TEST_F(SqliteTransaction, deferred_transaction_roll_back)
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin());
EXPECT_CALL(mockTransactionBackend, rollback());
EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
EXPECT_CALL(mockTransactionBackend, rollback(_));
EXPECT_CALL(mockTransactionBackend, unlock());
DeferredTransaction transaction{mockTransactionBackend};
@@ -60,8 +60,8 @@ TEST_F(SqliteTransaction, immediate_transaction_commit)
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateBegin());
EXPECT_CALL(mockTransactionBackend, commit());
EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock());
ImmediateTransaction transaction{mockTransactionBackend};
@@ -73,8 +73,8 @@ TEST_F(SqliteTransaction, immediate_transaction_roll_back)
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateBegin());
EXPECT_CALL(mockTransactionBackend, rollback());
EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
EXPECT_CALL(mockTransactionBackend, rollback(_));
EXPECT_CALL(mockTransactionBackend, unlock());
ImmediateTransaction transaction{mockTransactionBackend};
@@ -85,8 +85,8 @@ TEST_F(SqliteTransaction, exclusive_transaction_commit)
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, exclusiveBegin());
EXPECT_CALL(mockTransactionBackend, commit());
EXPECT_CALL(mockTransactionBackend, exclusiveBegin(_));
EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock());
ExclusiveTransaction transaction{mockTransactionBackend};
@@ -98,8 +98,8 @@ TEST_F(SqliteTransaction, exclusive_transaction_roll_back)
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, exclusiveBegin());
EXPECT_CALL(mockTransactionBackend, rollback());
EXPECT_CALL(mockTransactionBackend, exclusiveBegin(_));
EXPECT_CALL(mockTransactionBackend, rollback(_));
EXPECT_CALL(mockTransactionBackend, unlock());
ExclusiveTransaction transaction{mockTransactionBackend};
@@ -110,8 +110,8 @@ TEST_F(SqliteTransaction, deferred_non_throwing_destructor_transaction_commit)
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin());
EXPECT_CALL(mockTransactionBackend, commit());
EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock());
DeferredNonThrowingDestructorTransaction transaction{mockTransactionBackend};
@@ -123,8 +123,8 @@ TEST_F(SqliteTransaction, deferred_non_throwing_destructor_transaction_commit_ca
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin());
EXPECT_CALL(mockTransactionBackend, commit());
EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock());
DeferredNonThrowingDestructorTransaction transaction{mockTransactionBackend};
@@ -136,8 +136,8 @@ TEST_F(SqliteTransaction, deferred_non_throwing_destructor_transaction_roll_back
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin());
EXPECT_CALL(mockTransactionBackend, rollback());
EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
EXPECT_CALL(mockTransactionBackend, rollback(_));
EXPECT_CALL(mockTransactionBackend, unlock());
DeferredNonThrowingDestructorTransaction transaction{mockTransactionBackend};
@@ -148,8 +148,8 @@ TEST_F(SqliteTransaction, immediate_non_throwing_destructor_transaction_commit)
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateBegin());
EXPECT_CALL(mockTransactionBackend, commit());
EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock());
ImmediateNonThrowingDestructorTransaction transaction{mockTransactionBackend};
@@ -161,8 +161,8 @@ TEST_F(SqliteTransaction, immediate_non_throwing_destructor_transaction_roll_bac
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateBegin());
EXPECT_CALL(mockTransactionBackend, rollback());
EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
EXPECT_CALL(mockTransactionBackend, rollback(_));
EXPECT_CALL(mockTransactionBackend, unlock());
ImmediateNonThrowingDestructorTransaction transaction{mockTransactionBackend};
@@ -173,8 +173,8 @@ TEST_F(SqliteTransaction, exclusive_non_throwing_destructor_transaction_commit)
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, exclusiveBegin());
EXPECT_CALL(mockTransactionBackend, commit());
EXPECT_CALL(mockTransactionBackend, exclusiveBegin(_));
EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock());
ExclusiveNonThrowingDestructorTransaction transaction{mockTransactionBackend};
@@ -186,8 +186,8 @@ TEST_F(SqliteTransaction, exclusive_t_non_throwing_destructorransaction_roll_bac
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, exclusiveBegin());
EXPECT_CALL(mockTransactionBackend, rollback());
EXPECT_CALL(mockTransactionBackend, exclusiveBegin(_));
EXPECT_CALL(mockTransactionBackend, rollback(_));
EXPECT_CALL(mockTransactionBackend, unlock());
ExclusiveNonThrowingDestructorTransaction transaction{mockTransactionBackend};
@@ -195,21 +195,21 @@ TEST_F(SqliteTransaction, exclusive_t_non_throwing_destructorransaction_roll_bac
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);
}
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);
}
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);
}
@@ -219,8 +219,8 @@ TEST_F(SqliteTransaction, deferred_transaction_begin_throws_and_not_rollback)
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin()).WillOnce(Throw(Sqlite::Exception()));
EXPECT_CALL(mockTransactionBackend, rollback()).Times(0);
EXPECT_CALL(mockTransactionBackend, deferredBegin(_)).WillOnce(Throw(Sqlite::Exception()));
EXPECT_CALL(mockTransactionBackend, rollback(_)).Times(0);
EXPECT_CALL(mockTransactionBackend, unlock());
ASSERT_ANY_THROW(DeferredTransaction{mockTransactionBackend});
@@ -231,8 +231,8 @@ TEST_F(SqliteTransaction, immediate_transaction_begin_throws_and_not_rollback)
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateBegin()).WillOnce(Throw(Sqlite::Exception()));
EXPECT_CALL(mockTransactionBackend, rollback()).Times(0);
EXPECT_CALL(mockTransactionBackend, immediateBegin(_)).WillOnce(Throw(Sqlite::Exception()));
EXPECT_CALL(mockTransactionBackend, rollback(_)).Times(0);
EXPECT_CALL(mockTransactionBackend, unlock());
ASSERT_ANY_THROW(ImmediateTransaction{mockTransactionBackend});
@@ -243,8 +243,8 @@ TEST_F(SqliteTransaction, exclusive_transaction_begin_throws_and_not_rollback)
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, exclusiveBegin()).WillOnce(Throw(Sqlite::Exception()));
EXPECT_CALL(mockTransactionBackend, rollback()).Times(0);
EXPECT_CALL(mockTransactionBackend, exclusiveBegin(_)).WillOnce(Throw(Sqlite::Exception()));
EXPECT_CALL(mockTransactionBackend, rollback(_)).Times(0);
EXPECT_CALL(mockTransactionBackend, unlock());
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)
{
ON_CALL(mockTransactionBackend, commit()).WillByDefault(Throw(Sqlite::Exception()));
ON_CALL(mockTransactionBackend, commit(_)).WillByDefault(Throw(Sqlite::Exception()));
ImmediateTransaction transaction{mockTransactionBackend};
ASSERT_THROW(transaction.commit(), Sqlite::Exception);
@@ -260,14 +260,14 @@ TEST_F(SqliteTransaction, transaction_commit_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);
}
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});
}
@@ -277,8 +277,8 @@ TEST_F(SqliteTransaction, immediate_session_transaction_commit)
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateSessionBegin());
EXPECT_CALL(mockTransactionBackend, sessionCommit());
EXPECT_CALL(mockTransactionBackend, immediateSessionBegin(_));
EXPECT_CALL(mockTransactionBackend, sessionCommit(_));
EXPECT_CALL(mockTransactionBackend, unlock());
ImmediateSessionTransaction transaction{mockTransactionBackend};
@@ -290,8 +290,8 @@ TEST_F(SqliteTransaction, immediate_session_transaction_roll_back)
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateSessionBegin());
EXPECT_CALL(mockTransactionBackend, sessionRollback());
EXPECT_CALL(mockTransactionBackend, immediateSessionBegin(_));
EXPECT_CALL(mockTransactionBackend, sessionRollback(_));
EXPECT_CALL(mockTransactionBackend, unlock());
ImmediateSessionTransaction transaction{mockTransactionBackend};
@@ -299,14 +299,14 @@ TEST_F(SqliteTransaction, immediate_session_transaction_roll_back)
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);
}
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);
}
@@ -316,8 +316,8 @@ TEST_F(SqliteTransaction, immediate_session_transaction_begin_throws_and_not_rol
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateSessionBegin()).WillOnce(Throw(Sqlite::Exception()));
EXPECT_CALL(mockTransactionBackend, sessionRollback()).Times(0);
EXPECT_CALL(mockTransactionBackend, immediateSessionBegin(_)).WillOnce(Throw(Sqlite::Exception()));
EXPECT_CALL(mockTransactionBackend, sessionRollback(_)).Times(0);
EXPECT_CALL(mockTransactionBackend, unlock());
ASSERT_ANY_THROW(ImmediateSessionTransaction{mockTransactionBackend});
@@ -328,9 +328,9 @@ TEST_F(SqliteTransaction, with_implicit_transaction_no_return_does_not_commit)
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin()).Times(0);
EXPECT_CALL(mockTransactionBackend, deferredBegin(_)).Times(0);
EXPECT_CALL(callableMock, Call());
EXPECT_CALL(mockTransactionBackend, commit()).Times(0);
EXPECT_CALL(mockTransactionBackend, commit(_)).Times(0);
EXPECT_CALL(mockTransactionBackend, unlock());
Sqlite::withImplicitTransaction(mockTransactionBackend, callableMock.AsStdFunction());
@@ -341,9 +341,9 @@ TEST_F(SqliteTransaction, with_implicit_transaction_with_return_does_not_commit)
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin()).Times(0);
EXPECT_CALL(mockTransactionBackend, deferredBegin(_)).Times(0);
EXPECT_CALL(callableWithReturnMock, Call());
EXPECT_CALL(mockTransactionBackend, commit()).Times(0);
EXPECT_CALL(mockTransactionBackend, commit(_)).Times(0);
EXPECT_CALL(mockTransactionBackend, unlock());
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{}));
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin()).Times(0);
EXPECT_CALL(mockTransactionBackend, deferredBegin(_)).Times(0);
EXPECT_CALL(callableMock, Call());
EXPECT_CALL(mockTransactionBackend, rollback()).Times(0);
EXPECT_CALL(mockTransactionBackend, rollback(_)).Times(0);
EXPECT_CALL(mockTransactionBackend, unlock());
try {
@@ -381,9 +381,9 @@ TEST_F(SqliteTransaction, with_deferred_transaction_no_return_commit)
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin());
EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
EXPECT_CALL(callableMock, Call());
EXPECT_CALL(mockTransactionBackend, commit());
EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock());
Sqlite::withDeferredTransaction(mockTransactionBackend, callableMock.AsStdFunction());
@@ -394,9 +394,9 @@ TEST_F(SqliteTransaction, with_deferred_transaction_with_return_commit)
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin());
EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
EXPECT_CALL(callableWithReturnMock, Call());
EXPECT_CALL(mockTransactionBackend, commit());
EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock());
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{}));
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, deferredBegin());
EXPECT_CALL(mockTransactionBackend, deferredBegin(_));
EXPECT_CALL(callableMock, Call());
EXPECT_CALL(mockTransactionBackend, rollback());
EXPECT_CALL(mockTransactionBackend, rollback(_));
EXPECT_CALL(mockTransactionBackend, unlock());
try {
@@ -434,9 +434,9 @@ TEST_F(SqliteTransaction, with_immediate_transaction_no_return_commit)
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateBegin());
EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
EXPECT_CALL(callableMock, Call());
EXPECT_CALL(mockTransactionBackend, commit());
EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock());
Sqlite::withImmediateTransaction(mockTransactionBackend, callableMock.AsStdFunction());
@@ -447,9 +447,9 @@ TEST_F(SqliteTransaction, with_immediate_transaction_with_return_commit)
InSequence s;
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateBegin());
EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
EXPECT_CALL(callableWithReturnMock, Call());
EXPECT_CALL(mockTransactionBackend, commit());
EXPECT_CALL(mockTransactionBackend, commit(_));
EXPECT_CALL(mockTransactionBackend, unlock());
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{}));
EXPECT_CALL(mockTransactionBackend, lock());
EXPECT_CALL(mockTransactionBackend, immediateBegin());
EXPECT_CALL(mockTransactionBackend, immediateBegin(_));
EXPECT_CALL(callableMock, Call());
EXPECT_CALL(mockTransactionBackend, rollback());
EXPECT_CALL(mockTransactionBackend, rollback(_));
EXPECT_CALL(mockTransactionBackend, unlock());
try {